void emit_op_base_offset(generic_op op, short base_reg, int offset, short use_reg) { switch (op) { case CLEAR: code_buf[code_idx++] = I386_INS_MOV_Ev_Iv; emit_base_offset(0, base_reg, offset); *((int4 *)&code_buf[code_idx]) = 0; code_idx += SIZEOF(int4); break; case COMPARE: code_buf[code_idx++] = I386_INS_CMP_Gv_Ev; emit_base_offset(use_reg, base_reg, offset); break; case INCREMENT: code_buf[code_idx++] = I386_INS_Grp5_Prefix; emit_base_offset(I386_INS_INC_Ev, base_reg, offset); break; case LOAD: code_buf[code_idx++] = I386_INS_MOV_Gv_Ev; emit_base_offset(use_reg, base_reg, offset); break; case LOAD_ADDRESS: code_buf[code_idx++] = I386_INS_LEA_Gv_M; emit_base_offset(use_reg, base_reg, offset); break; case PUSH: code_buf[code_idx++] = I386_INS_Grp5_Prefix; emit_base_offset(I386_INS_PUSH_Ev, base_reg, offset); break; case PUSH_ADDRESS: code_buf[code_idx++] = I386_INS_LEA_Gv_M; emit_base_offset(use_reg, base_reg, offset); code_buf[code_idx++] = I386_INS_PUSH_eAX + use_reg; break; case STORE: code_buf[code_idx++] = I386_INS_MOV_Ev_Gv; emit_base_offset(use_reg, base_reg, offset); break; case TEST: code_buf[code_idx++] = I386_INS_Grp1_Ev_Ib_Prefix; emit_base_offset(I386_INS_CMP__, base_reg, offset); code_buf[code_idx++] = 0; break; default: rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP); break; } }
zb_code *find_line_call(void *addr) { unsigned char temp_char, *call_addr; modrm_byte_type modrm_byte, temp_modrm_byte; call_addr = (unsigned char *)addr; modrm_byte.byte = *(call_addr + 1); if (I386_INS_Grp5_Prefix == *call_addr && I386_INS_CALL_Ev == modrm_byte.modrm.reg_opcode) { call_addr++; assert (I386_REG_EBX == modrm_byte.modrm.r_m); call_addr++; if (I386_MOD32_BASE_DISP_32 == modrm_byte.modrm.mod) { if (*((int4 *)call_addr) == xf_linestart * SIZEOF(INTPTR_T) || *((int4 *)call_addr) == xf_zbstart * SIZEOF(INTPTR_T)) return (zb_code *)call_addr; if (*((int4 *)call_addr) != xf_isformal * SIZEOF(INTPTR_T)) return (zb_code *)addr; call_addr += SIZEOF(int4); } else if (I386_MOD32_BASE_DISP_8 == modrm_byte.modrm.mod) { if (*((char *)call_addr) == xf_linestart * SIZEOF(INTPTR_T) || *((char *)call_addr) == xf_zbstart * SIZEOF(INTPTR_T)) return (zb_code *)call_addr; /* XF_ISFORMAL cannot be encoded in a one-byte offset, no point checking for it */ call_addr += 1; } } emit_base_offset(I386_REG_SP,0x12); emit_base_info.modrm_byte.modrm.reg_opcode = I386_REG_RAX ; inst_size = 0 ; if (MOV_INTO_ARGREG(call_addr+1,I386_INS_MOV_eAX) || MOV_INTO_STACK(call_addr+1,I386_INS_MOV_Ev_Gv) ) { modrm_byte.byte = *(call_addr + 2); while (MOV_INTO_ARGREG(call_addr+1,I386_INS_MOV_eAX) || MOV_INTO_STACK(call_addr+1,I386_INS_MOV_Ev_Gv)) { assert((8 == inst_size) || (5 == inst_size) || (6 == inst_size)) ; call_addr += inst_size ; inst_size = 0 ; } modrm_byte.byte = *(call_addr + 1); if (*call_addr++ != I386_INS_Grp5_Prefix || modrm_byte.modrm.reg_opcode != I386_INS_CALL_Ev) return (zb_code *)addr; assert (I386_MOD32_BASE_DISP_8 == modrm_byte.modrm.mod || I386_MOD32_BASE_DISP_32 == modrm_byte.modrm.mod); assert (I386_REG_RBX == modrm_byte.modrm.r_m); call_addr++; if (I386_MOD32_BASE_DISP_32 == modrm_byte.modrm.mod) { if (*(int4 *)call_addr != xf_linefetch * SIZEOF(INTPTR_T) && *(int4 *)call_addr != xf_zbfetch * SIZEOF(INTPTR_T)) return (zb_code *)addr; } else if (I386_MOD32_BASE_DISP_8 == modrm_byte.modrm.mod) { if (*(char *)call_addr != xf_linefetch * SIZEOF(INTPTR_T) && *(char *)call_addr != xf_zbfetch * SIZEOF(INTPTR_T)) return (zb_code *)addr; } } else if (*call_addr == I386_INS_Grp5_Prefix && modrm_byte.modrm.reg_opcode == I386_INS_CALL_Ev) { modrm_byte.byte = *(call_addr + 1); call_addr++; assert (I386_MOD32_BASE_DISP_8 == modrm_byte.modrm.mod || I386_MOD32_BASE_DISP_32 == modrm_byte.modrm.mod); assert (I386_REG_EBX == modrm_byte.modrm.r_m); call_addr++; if (I386_MOD32_BASE_DISP_32 == modrm_byte.modrm.mod) { if (*(int4 *)call_addr != xf_linestart * SIZEOF(INTPTR_T) && *(int4 *)call_addr != xf_zbstart * SIZEOF(INTPTR_T)) return (zb_code *)addr; } else if (I386_MOD32_BASE_DISP_8 == modrm_byte.modrm.mod) { if (*(char *)call_addr != xf_linestart * SIZEOF(INTPTR_T) && *(char *)call_addr != xf_zbstart * SIZEOF(INTPTR_T)) return (zb_code *)addr; } } return (zb_code *)call_addr; }
void emit_trip(generic_op op, oprtype *opr, bool val_output, unsigned char use_reg) { unsigned char base_reg, temp_reg; int4 offset, literal; triple *ct; if (opr->oprclass == TRIP_REF) { ct = opr->oprval.tref; if (ct->destination.oprclass) { opr = &ct->destination; } /* else lit or error */ } switch (cg_phase) { case CGP_ADDR_OPT: case CGP_APPROX_ADDR: switch (opr->oprclass) { case TRIP_REF: assert(ct->destination.oprclass == 0); assert(val_output); switch (ct->opcode) { case OC_LIT: if (run_time) { int4 pc_value_idx; switch (op) { case LOAD_ADDRESS: temp_reg = use_reg; break; case PUSH: case PUSH_ADDRESS: temp_reg = I386_REG_ECX; break; default: rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP); break; } pc_value_idx = code_idx + 5; code_idx += 1 + SIZEOF(int4) + 1; emit_addr(0, (int4)ct->operand[0].oprval.mlit->rt_addr, &offset); offset -= pc_value_idx; force_32 = 1; emit_op_base_offset(op, temp_reg, offset, temp_reg); force_32 = 0; } else { emit_op_alit(op, use_reg); code_idx += SIZEOF(int4); } if (cg_phase == CGP_APPROX_ADDR) txtrel_cnt++; break; case OC_CDLIT: if (cg_phase == CGP_APPROX_ADDR) define_symbol(GTM_LITERALS, ct->operand[0].oprval.cdlt, 0); emit_op_alit(op, use_reg); code_idx += SIZEOF(int4); break; case OC_ILIT: literal = ct->operand[0].oprval.ilit; switch(op) { case COMPARE: /* 1byte(opcode) + 1byte(ModR/M) + 4byte(literal) */ code_idx += 2 + SIZEOF(int4); break; case LOAD: code_idx += 1 + SIZEOF(int4); break; case PUSH: if (literal >= -128 && literal <= 127) code_idx += 2; else code_idx += 1 + SIZEOF(int4); break; default: rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP); break; } break; default: assertpro(FALSE && ct->opcode); break; } break; case TINT_REF: case TVAL_REF: assert(val_output); offset = sa_temps_offset[opr->oprclass]; offset -= (sa_temps[opr->oprclass] - opr->oprval.temp) * sa_class_sizes[opr->oprclass]; assertpro((0 <= offset) && (65535 >= offset)); emit_op_base_offset(op, I386_REG_EDI, offset, use_reg); break; case TCAD_REF: case TVAD_REF: case TVAR_REF: offset = sa_temps_offset[opr->oprclass]; offset -= (sa_temps[opr->oprclass] - opr->oprval.temp) * sa_class_sizes[opr->oprclass]; assertpro((0 <= offset) && (65535 >= offset)); if (opr->oprclass == TVAR_REF) base_reg = I386_REG_ESI; else base_reg = I386_REG_EDI; switch (op) { case JUMP: if (val_output) { code_idx++; emit_base_offset(I386_REG_EAX, base_reg, offset); } code_idx++; if (val_output) emit_base_offset(I386_INS_JMP_Ev, I386_REG_EAX, 0); else emit_base_offset(I386_INS_JMP_Ev, base_reg, offset); break; case LOAD_ADDRESS: code_idx++; emit_base_offset(use_reg, base_reg, offset); if (opr->oprclass == TVAR_REF) { code_idx++; emit_base_offset(use_reg, use_reg, offsetof(ht_ent_mname, value)); } break; case PUSH: if (!val_output) { code_idx++; emit_base_offset(I386_INS_PUSH_Ev, base_reg, offset); } else { code_idx++; emit_base_offset(I386_REG_ECX, base_reg, offset); code_idx++; emit_base_offset(I386_INS_PUSH_Ev, I386_REG_ECX, 0); } break; case PUSH_ADDRESS: if (val_output) { if (opr->oprclass == TVAR_REF) { code_idx++; emit_base_offset(use_reg, base_reg, offset); code_idx++; emit_base_offset(I386_INS_PUSH_Ev, use_reg, offsetof(ht_ent_mname, value)); } else { code_idx++; emit_base_offset(I386_INS_PUSH_Ev, base_reg, offset); } } else { code_idx++; emit_base_offset(I386_REG_ECX, base_reg, offset); code_idx++; } break; case STORE: if (val_output) { if (use_reg == I386_REG_EAX) temp_reg = I386_REG_EDX; else temp_reg = I386_REG_EAX; code_idx++; emit_base_offset(temp_reg, base_reg, offset); } code_idx++; if (val_output) emit_base_offset(use_reg, temp_reg, 0); else emit_base_offset(use_reg, base_reg, offset); break; default: rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP); break; } break; } break; case CGP_MACHINE: switch (opr->oprclass) { case TRIP_REF: assert(ct->destination.oprclass == 0); assert(val_output); switch (ct->opcode) { case OC_LIT: assert(ct->operand[0].oprclass == MLIT_REF); if (run_time) { int4 pc_value_idx; switch(op) { case LOAD_ADDRESS: temp_reg = use_reg; break; case PUSH: case PUSH_ADDRESS: temp_reg = I386_REG_ECX; break; default: rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP); break; } code_buf[code_idx++] = I386_INS_CALL_Jv; *((int4 *)&code_buf[code_idx]) = 0; code_idx += SIZEOF(int4); pc_value_idx = code_idx; code_buf[code_idx++] = I386_INS_POP_eAX + temp_reg; emit_addr(0, (int4)ct->operand[0].oprval.mlit->rt_addr, &offset); offset -= pc_value_idx; force_32 = 1; emit_op_base_offset(op, temp_reg, offset, temp_reg); force_32 = 0; } else { emit_op_alit(op, use_reg); emit_addr(code_reference + (code_idx * SIZEOF(unsigned char)), (int4)ct->operand[0].oprval.mlit->rt_addr, (int4 *)&code_buf[code_idx]); code_idx += SIZEOF(int4); } break; case OC_CDLIT: emit_op_alit(op, use_reg); emit_reference(code_reference + (code_idx * SIZEOF(unsigned char)), ct->operand[0].oprval.cdlt, (uint4 *)&code_buf[code_idx]); code_idx += SIZEOF(int4); break; case OC_ILIT: literal = ct->operand[0].oprval.ilit; switch (op) { case COMPARE: /* cmpl $literal,use_reg - 1byte(opcode) + 1byte(ModR/M) + 4byte(literal) */ code_buf[code_idx++] = I386_INS_Grp1_Ev_Iv_Prefix; modrm_byte.modrm.reg_opcode = I386_INS_CMP__; modrm_byte.modrm.mod = I386_MOD32_REGISTER; modrm_byte.modrm.r_m = use_reg; code_buf[code_idx++] = modrm_byte.byte; *((int4 *)&code_buf[code_idx]) = literal; code_idx += SIZEOF(int4); break; case LOAD: code_buf[code_idx++] = I386_INS_MOV_eAX + use_reg; *((int4 *)&code_buf[code_idx]) = literal; code_idx += SIZEOF(int4); break; case PUSH: if (literal >= -128 && literal <= 127) { code_buf[code_idx++] = I386_INS_PUSH_Ib; code_buf[code_idx++] = literal & 0xff; } else { code_buf[code_idx++] = I386_INS_PUSH_Iv; *((int4 *)&code_buf[code_idx]) = literal; code_idx += SIZEOF(int4); } break; default: rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP); break; } break; default: assertpro(FALSE && ct->opcode); break; } break; case TINT_REF: case TVAL_REF: assert(val_output); offset = sa_temps_offset[opr->oprclass]; offset -= (sa_temps[opr->oprclass] - opr->oprval.temp) * sa_class_sizes[opr->oprclass]; assertpro((0 <= offset) && (65535 >= offset)); emit_op_base_offset(op, I386_REG_EDI, offset, use_reg); break; case TCAD_REF: case TVAD_REF: case TVAR_REF: offset = sa_temps_offset[opr->oprclass]; offset -= (sa_temps[opr->oprclass] - opr->oprval.temp) * sa_class_sizes[opr->oprclass]; assertpro((0 <= offset) && (65535 >= offset)); if (opr->oprclass == TVAR_REF) base_reg = I386_REG_ESI; else base_reg = I386_REG_EDI; switch (op) { case JUMP: assert(use_reg == 0); if (val_output) { code_buf[code_idx++] = I386_INS_MOV_Gv_Ev; emit_base_offset(I386_REG_EAX, base_reg, offset); } code_buf[code_idx++] = I386_INS_Grp5_Prefix; if (val_output) emit_base_offset(I386_INS_JMP_Ev, I386_REG_EAX, 0); else emit_base_offset(I386_INS_JMP_Ev, base_reg, offset); break; case LOAD_ADDRESS: if (val_output) code_buf[code_idx++] = I386_INS_MOV_Gv_Ev; else code_buf[code_idx++] = I386_INS_LEA_Gv_M; emit_base_offset(use_reg, base_reg, offset); if (opr->oprclass == TVAR_REF) { code_buf[code_idx++] = I386_INS_MOV_Gv_Ev; emit_base_offset(use_reg, use_reg, offsetof(ht_ent_mname, value)); } break; case PUSH: if (val_output) { code_buf[code_idx++] = I386_INS_MOV_Gv_Ev; emit_base_offset(I386_REG_ECX, base_reg, offset); code_buf[code_idx++] = I386_INS_Grp5_Prefix; emit_base_offset(I386_INS_PUSH_Ev, I386_REG_ECX, 0); } else { code_buf[code_idx++] = I386_INS_Grp5_Prefix; emit_base_offset(I386_INS_PUSH_Ev, base_reg, offset); } break; case PUSH_ADDRESS: if (val_output) { if (opr->oprclass == TVAR_REF) { code_buf[code_idx++] = I386_INS_MOV_Gv_Ev; emit_base_offset(use_reg, base_reg, offset); code_buf[code_idx++] = I386_INS_Grp5_Prefix; emit_base_offset(I386_INS_PUSH_Ev, use_reg, offsetof(ht_ent_mname, value)); } else { code_buf[code_idx++] = I386_INS_Grp5_Prefix; emit_base_offset(I386_INS_PUSH_Ev, base_reg, offset); } } else { code_buf[code_idx++] = I386_INS_LEA_Gv_M; emit_base_offset(I386_REG_ECX, base_reg, offset); code_buf[code_idx++] = I386_INS_PUSH_eCX; } break; case STORE: if (val_output) { if (use_reg == I386_REG_EAX) temp_reg = I386_REG_EDX; else temp_reg = I386_REG_EAX; assert(temp_reg != use_reg); code_buf[code_idx++] = I386_INS_MOV_Gv_Ev; emit_base_offset(temp_reg, base_reg, offset); } code_buf[code_idx++] = I386_INS_MOV_Ev_Gv; if (val_output) emit_base_offset(use_reg, temp_reg, 0); else emit_base_offset(use_reg, base_reg, offset); break; default: rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP); break; } break; default: assertpro(FALSE && opr->oprclass); break; } break; default: assertpro(FALSE && cg_phase); break; } }
short *emit_vax_inst(short *inst, oprtype **fst_opr, oprtype **lst_opr) /* fst_opr and lst_opr are triple operands */ { short sav_in; bool oc_int; int4 cnt; oprtype *opr; triple *ct; code_idx = 0; force_32 = 0; switch (cg_phase) { case CGP_ADDR_OPT: case CGP_APPROX_ADDR: case CGP_MACHINE: switch ((sav_in = *inst++)) { case VXI_BEQL: case VXI_BGEQ: case VXI_BGTR: case VXI_BLEQ: case VXI_BLSS: case VXI_BNEQ: case VXI_BRB: case VXI_BRW: emit_jmp(sav_in, &inst); break; case VXI_BLBC: case VXI_BLBS: assert(VXT_REG == *inst); inst++; inst++; emit_xfer(4*xf_dt_get); code_buf[code_idx++] = I386_INS_CMP_eAX_Iv; *((int4 *)&code_buf[code_idx]) = 0; code_idx += SIZEOF(int4); if (sav_in == VXI_BLBC) emit_jmp(VXI_BEQL, &inst); else { assert(sav_in == VXI_BLBS); emit_jmp(VXI_BNEQ, &inst); } break; case VXI_BICB2: case VXI_BISB2: assert(VXT_LIT == *inst); inst++; assert(1 == *inst); inst++; assert(VXT_REG == *inst); inst++; inst++; if (sav_in == VXI_BICB2) emit_xfer(4*xf_dt_false); else { assert(sav_in == VXI_BISB2); emit_xfer(4*xf_dt_true); } break; case VXI_CALLS: oc_int = TRUE; if (VXT_LIT == *inst) { inst++; cnt = (int4) *inst++; } else { assert(VXT_VAL == *inst); inst++; opr = *(fst_opr + *inst); assert(opr->oprclass == TRIP_REF); ct = opr->oprval.tref; if (ct->destination.oprclass) { opr = &ct->destination; } if (opr->oprclass == TRIP_REF) { assert(ct->opcode == OC_ILIT); cnt = ct->operand[0].oprval.ilit; if (cnt >= -128 && cnt <= 127) { code_buf[code_idx++] = I386_INS_PUSH_Ib; code_buf[code_idx++] = cnt & 0xff; } else { code_buf[code_idx++] = I386_INS_PUSH_Iv; *((int4 *)&code_buf[code_idx]) = cnt; code_idx += SIZEOF(int4); } cnt++; inst++; } else { assert(opr->oprclass == TINT_REF); oc_int = FALSE; opr = *(fst_opr + *inst++); emit_trip(PUSH, opr, TRUE, 0); } } assert(VXT_XFER == *inst); inst++; emit_xfer(*inst++); if (oc_int) { if (cnt) { code_buf[code_idx++] = I386_INS_LEA_Gv_M; emit_base_offset(I386_REG_ESP, I386_REG_ESP, 4*cnt); } } else { emit_trip(LOAD, opr, TRUE, I386_REG_EDX); code_buf[code_idx++] = I386_INS_LEA_Gv_M; emit_base_offset(I386_REG_ESP, I386_REG_ESP, 4); } break; case VXI_CLRL: assert(VXT_VAL == *inst); inst++; emit_trip(CLEAR, *(fst_opr + *inst++), TRUE, 0); break; case VXI_CMPL: assert(VXT_VAL == *inst); inst++; emit_trip(LOAD, *(fst_opr + *inst++), TRUE, I386_REG_EDX); assert(VXT_VAL == *inst); inst++; emit_trip(COMPARE, *(fst_opr + *inst++), TRUE, I386_REG_EDX); break; case VXI_INCL: assert(VXT_VAL == *inst); inst++; emit_trip(INCREMENT, *(fst_opr + *inst++), TRUE, 0); break; case VXI_JMP: if (VXT_VAL == *inst) { inst++; emit_trip(JUMP, *(fst_opr + *inst++), FALSE, 0); } else { emit_jmp(sav_in, &inst); } break; case VXI_JSB: assert(VXT_XFER == *inst); inst++; emit_xfer(*inst++); break; case VXI_MOVAB: if (VXT_JMP == *inst) { inst += 2; emit_pcrel(LOAD_ADDRESS, I386_REG_EAX); assert(VXT_ADDR == *inst); inst++; emit_trip(STORE, *(fst_opr + *inst++), FALSE, I386_REG_EAX); } else if ((VXT_ADDR == *inst) || (VXT_VAL == *inst)) { bool addr; unsigned char reg; short save_inst; addr = (VXT_VAL == *inst); inst++; save_inst = *inst++; assert(VXT_REG == *inst); inst++; reg = ((*inst++ & 0x01) ? I386_REG_EDX : I386_REG_EAX); /* r0 and r1 are only ones used */ emit_trip(LOAD_ADDRESS, *(fst_opr + save_inst), addr, reg); } else assertpro(FALSE && *inst); break; case VXI_MOVC3: assert(VXT_LIT == *inst); inst += 2; assert(VXT_VAL == *inst); inst++; code_buf[code_idx++] = I386_INS_PUSH_eSI; code_buf[code_idx++] = I386_INS_PUSH_eDI; emit_trip(LOAD_ADDRESS, *(fst_opr + *inst++), TRUE, I386_REG_ECX); assert(VXT_VAL == *inst); inst++; emit_trip(LOAD_ADDRESS, *(fst_opr + *inst++), TRUE, I386_REG_EDI); code_buf[code_idx++] = I386_INS_MOV_Gv_Ev; modrm_byte.modrm.reg_opcode = I386_REG_ESI; modrm_byte.modrm.mod = I386_MOD32_REGISTER; modrm_byte.modrm.r_m = I386_REG_ECX; code_buf[code_idx++] = modrm_byte.byte; code_buf[code_idx++] = I386_INS_MOV_eCX; *((int4 *)&code_buf[code_idx]) = (int4)SIZEOF(mval); code_idx += SIZEOF(int4); code_buf[code_idx++] = I386_INS_REP_E_Prefix; code_buf[code_idx++] = I386_INS_MOVSB_Xb_Yb; code_buf[code_idx++] = I386_INS_POP_eDI; code_buf[code_idx++] = I386_INS_POP_eSI; break; case VXI_MOVL: if (VXT_REG == *inst) { inst++; if (*inst > 0x5f) /* OC_CURRHD */ /* any mode >= 6 (deferred), any register */ { inst++; assert(VXT_ADDR == *inst); inst++; emit_xfer(4*xf_get_msf); emit_op_base_offset(LOAD, I386_REG_EAX, 0, I386_REG_EAX); emit_trip(STORE, *(fst_opr + *inst++), FALSE, I386_REG_EAX); } else { bool addr; assert(0x50 == *inst); /* register mode: R0 */ inst++; if ((VXT_VAL == *inst) || (VXT_ADDR == *inst)) { addr = (VXT_VAL == *inst); inst++; emit_trip(STORE, *(fst_opr + *inst++), addr, I386_REG_EAX); } else if (VXT_REG == *inst) { unsigned char reg; inst++; if ((*inst & 0x0f) == 10) /* VAX $TEST */ { code_buf[code_idx++] = I386_INS_PUSH_eAX; emit_xfer(4*xf_dt_store); code_buf[code_idx++] = I386_INS_POP_eAX; } else { code_buf[code_idx++] = I386_INS_MOV_Ev_Gv; modrm_byte.modrm.reg_opcode = I386_REG_EAX; modrm_byte.modrm.mod = I386_MOD32_REGISTER; modrm_byte.modrm.r_m = i386_reg(*inst); code_buf[code_idx++] = modrm_byte.byte; } inst++; } else assertpro(FALSE && *inst); } } else if (VXT_VAL == *inst) { inst++; emit_trip(LOAD, *(fst_opr + *inst++), TRUE, I386_REG_EDX); assert(VXT_REG == *inst); inst++; assert(0x51 == *inst); /* register mode: R1 */ inst++; } else assertpro(FALSE && *inst); break; case VXT_IREPAB: assert(VXT_VAL == *inst); inst += 2; emit_trip(PUSH_ADDRESS, *lst_opr, TRUE, 0); break; case VXI_PUSHAB: if (VXT_JMP == *inst) { inst += 2; emit_pcrel(PUSH_ADDRESS, 0); } else if (VXT_VAL == *inst) { inst++; emit_trip(PUSH_ADDRESS, *(fst_opr + *inst++), TRUE, 0); } else assertpro(FALSE && *inst); break; case VXT_IREPL: assert(VXT_VAL == *inst); inst += 2; emit_trip(PUSH, *lst_opr, TRUE, 0); break; case VXI_PUSHL: if (VXT_LIT == *inst) { int4 lit; inst++; lit = *inst++; if (lit >= -128 && lit <= 127) { code_buf[code_idx++] = I386_INS_PUSH_Ib; code_buf[code_idx++] = lit & 0xff; } else { code_buf[code_idx++] = I386_INS_PUSH_Iv; *((int4 *)&code_buf[code_idx]) = lit; code_idx += SIZEOF(int4); } } else if (VXT_ADDR == *inst) { inst++; emit_trip(PUSH, *(fst_opr + *inst++), FALSE, 0); } else if (VXT_VAL == *inst) { inst++; emit_trip(PUSH, *(fst_opr + *inst++), TRUE, 0); } else assertpro(FALSE && *inst); break; case VXI_TSTL: if (VXT_VAL == *inst) { inst++; emit_trip(TEST, *(fst_opr + *inst++), TRUE, 0); } else if (VXT_REG == *inst) { inst++; code_buf[code_idx++] = I386_INS_CMP_eAX_Iv; assert(I386_REG_EAX == i386_reg(*inst)); /* VAX R0 */ inst++; *((int4 *)&code_buf[code_idx]) = 0; /* 32 bit immediate 0 */ code_idx += SIZEOF(int4); } else assertpro(FALSE && *inst); break; default: assertpro(FALSE && sav_in); } break; default: assertpro(FALSE && cg_phase); break; } assert(code_idx < BUFFERED_CODE_SIZE); if (cg_phase == CGP_MACHINE) { generated_code_size += code_idx; emit_immed ((char *)&code_buf[0], SIZEOF(unsigned char) * code_idx); } else if (cg_phase != CGP_ASSEMBLY) { if (cg_phase == CGP_APPROX_ADDR) { calculated_code_size += code_idx; } curr_addr += SIZEOF(unsigned char) * code_idx; } code_reference += SIZEOF(unsigned char) * code_idx; jmp_offset -= SIZEOF(unsigned char) * code_idx; return inst; }
/* Changes here, emit_base_offset, or emit_jmp may require changes in trip_gen case for OC_CALL[SP] and FORLCLDO */ void emit_xfer(short xfer) { code_buf[code_idx++] = I386_INS_Grp5_Prefix; emit_base_offset(I386_INS_CALL_Ev, I386_REG_EBX, (int4)xfer); }