/* Negate just a single ExprItem by building a -1*ei subexpression */ static void expr_xform_neg_item(yasm_expr *e, yasm_expr__item *ei) { yasm_expr *sube = yasm_xmalloc(sizeof(yasm_expr)); /* Build -1*ei subexpression */ sube->op = YASM_EXPR_MUL; sube->line = e->line; sube->numterms = 2; sube->terms[0].type = YASM_EXPR_INT; sube->terms[0].data.intn = yasm_intnum_create_int(-1); sube->terms[1] = *ei; /* structure copy */ /* Replace original ExprItem with subexp */ ei->type = YASM_EXPR_EXPR; ei->data.expn = sube; }
static int lc3b_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d, yasm_output_value_func output_value, /*@unused@*/ yasm_output_reloc_func output_reloc) { lc3b_insn *insn = (lc3b_insn *)bc->contents; /*@only@*/ yasm_intnum *delta; unsigned long buf_off = (unsigned long)(*bufp - bufstart); /* Output opcode */ YASM_SAVE_16_L(*bufp, insn->opcode); /* Insert immediate into opcode. */ switch (insn->imm_type) { case LC3B_IMM_NONE: break; case LC3B_IMM_4: insn->imm.size = 4; if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d)) return 1; break; case LC3B_IMM_5: insn->imm.size = 5; insn->imm.sign = 1; if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d)) return 1; break; case LC3B_IMM_6_WORD: insn->imm.size = 6; if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d)) return 1; break; case LC3B_IMM_6_BYTE: insn->imm.size = 6; insn->imm.sign = 1; if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d)) return 1; break; case LC3B_IMM_8: insn->imm.size = 8; if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d)) return 1; break; case LC3B_IMM_9_PC: /* Adjust relative displacement to end of bytecode */ delta = yasm_intnum_create_int(-1); if (!insn->imm.abs) insn->imm.abs = yasm_expr_create_ident(yasm_expr_int(delta), bc->line); else insn->imm.abs = yasm_expr_create(YASM_EXPR_ADD, yasm_expr_expr(insn->imm.abs), yasm_expr_int(delta), bc->line); insn->imm.size = 9; insn->imm.sign = 1; if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d)) return 1; break; case LC3B_IMM_9: insn->imm.size = 9; if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d)) return 1; break; default: yasm_internal_error(N_("Unrecognized immediate type")); } *bufp += 2; /* all instructions are 2 bytes in size */ return 0; }
/* Negates e by multiplying by -1, with distribution over lower-precedence * operators (eg ADD) and special handling to simplify result w/ADD, NEG, and * others. * * Returns a possibly reallocated e. */ static /*@only@*/ yasm_expr * expr_xform_neg_helper(/*@returned@*/ /*@only@*/ yasm_expr *e) { yasm_expr *ne; int i; switch (e->op) { case YASM_EXPR_ADD: /* distribute (recursively if expr) over terms */ for (i=0; i<e->numterms; i++) { if (e->terms[i].type == YASM_EXPR_EXPR) e->terms[i].data.expn = expr_xform_neg_helper(e->terms[i].data.expn); else expr_xform_neg_item(e, &e->terms[i]); } break; case YASM_EXPR_SUB: /* change op to ADD, and recursively negate left side (if expr) */ e->op = YASM_EXPR_ADD; if (e->terms[0].type == YASM_EXPR_EXPR) e->terms[0].data.expn = expr_xform_neg_helper(e->terms[0].data.expn); else expr_xform_neg_item(e, &e->terms[0]); break; case YASM_EXPR_NEG: /* Negating a negated value? Make it an IDENT. */ e->op = YASM_EXPR_IDENT; break; case YASM_EXPR_IDENT: /* Negating an ident? Change it into a MUL w/ -1 if there's no * floatnums present below; if there ARE floatnums, recurse. */ if (e->terms[0].type == YASM_EXPR_FLOAT) yasm_floatnum_calc(e->terms[0].data.flt, YASM_EXPR_NEG, NULL); else if (e->terms[0].type == YASM_EXPR_INT) yasm_intnum_calc(e->terms[0].data.intn, YASM_EXPR_NEG, NULL); else if (e->terms[0].type == YASM_EXPR_EXPR && yasm_expr__contains(e->terms[0].data.expn, YASM_EXPR_FLOAT)) expr_xform_neg_helper(e->terms[0].data.expn); else { e->op = YASM_EXPR_MUL; e->numterms = 2; e->terms[1].type = YASM_EXPR_INT; e->terms[1].data.intn = yasm_intnum_create_int(-1); } break; default: /* Everything else. MUL will be combined when it's leveled. * Make a new expr (to replace e) with -1*e. */ ne = yasm_xmalloc(sizeof(yasm_expr)); ne->op = YASM_EXPR_MUL; ne->line = e->line; ne->numterms = 2; ne->terms[0].type = YASM_EXPR_INT; ne->terms[0].data.intn = yasm_intnum_create_int(-1); ne->terms[1].type = YASM_EXPR_EXPR; ne->terms[1].data.expn = e; return ne; } return e; }