Revision b03cce8e tcg/i386/tcg-target.c
b/tcg/i386/tcg-target.c | ||
---|---|---|
46 | 46 |
const int tcg_target_call_iarg_regs[3] = { TCG_REG_EAX, TCG_REG_EDX, TCG_REG_ECX }; |
47 | 47 |
const int tcg_target_call_oarg_regs[2] = { TCG_REG_EAX, TCG_REG_EDX }; |
48 | 48 |
|
49 |
static uint8_t *tb_ret_addr; |
|
50 |
|
|
49 | 51 |
static void patch_reloc(uint8_t *code_ptr, int type, |
50 | 52 |
tcg_target_long value, tcg_target_long addend) |
51 | 53 |
{ |
... | ... | |
879 | 881 |
switch(opc) { |
880 | 882 |
case INDEX_op_exit_tb: |
881 | 883 |
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EAX, args[0]); |
882 |
tcg_out8(s, 0xc3); /* ret */ |
|
884 |
tcg_out8(s, 0xe9); /* jmp tb_ret_addr */ |
|
885 |
tcg_out32(s, tb_ret_addr - s->code_ptr - 4); |
|
883 | 886 |
break; |
884 | 887 |
case INDEX_op_goto_tb: |
885 | 888 |
if (s->tb_jmp_offset) { |
... | ... | |
1145 | 1148 |
{ -1 }, |
1146 | 1149 |
}; |
1147 | 1150 |
|
1151 |
static int tcg_target_callee_save_regs[] = { |
|
1152 |
/* TCG_REG_EBP, */ /* currently used for the global env, so no |
|
1153 |
need to save */ |
|
1154 |
TCG_REG_EBX, |
|
1155 |
TCG_REG_ESI, |
|
1156 |
TCG_REG_EDI, |
|
1157 |
}; |
|
1158 |
|
|
1159 |
static inline void tcg_out_push(TCGContext *s, int reg) |
|
1160 |
{ |
|
1161 |
tcg_out_opc(s, 0x50 + reg); |
|
1162 |
} |
|
1163 |
|
|
1164 |
static inline void tcg_out_pop(TCGContext *s, int reg) |
|
1165 |
{ |
|
1166 |
tcg_out_opc(s, 0x58 + reg); |
|
1167 |
} |
|
1168 |
|
|
1169 |
/* Generate global QEMU prologue and epilogue code */ |
|
1170 |
void tcg_target_qemu_prologue(TCGContext *s) |
|
1171 |
{ |
|
1172 |
int i, frame_size, push_size, stack_addend; |
|
1173 |
|
|
1174 |
/* TB prologue */ |
|
1175 |
/* save all callee saved registers */ |
|
1176 |
for(i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { |
|
1177 |
tcg_out_push(s, tcg_target_callee_save_regs[i]); |
|
1178 |
} |
|
1179 |
/* reserve some stack space */ |
|
1180 |
push_size = 4 + ARRAY_SIZE(tcg_target_callee_save_regs) * 4; |
|
1181 |
frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE; |
|
1182 |
frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) & |
|
1183 |
~(TCG_TARGET_STACK_ALIGN - 1); |
|
1184 |
stack_addend = frame_size - push_size; |
|
1185 |
tcg_out_addi(s, TCG_REG_ESP, -stack_addend); |
|
1186 |
|
|
1187 |
tcg_out_modrm(s, 0xff, 4, TCG_REG_EAX); /* jmp *%eax */ |
|
1188 |
|
|
1189 |
/* TB epilogue */ |
|
1190 |
tb_ret_addr = s->code_ptr; |
|
1191 |
tcg_out_addi(s, TCG_REG_ESP, stack_addend); |
|
1192 |
for(i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) { |
|
1193 |
tcg_out_pop(s, tcg_target_callee_save_regs[i]); |
|
1194 |
} |
|
1195 |
tcg_out8(s, 0xc3); /* ret */ |
|
1196 |
} |
|
1197 |
|
|
1148 | 1198 |
void tcg_target_init(TCGContext *s) |
1149 | 1199 |
{ |
1150 | 1200 |
/* fail safe */ |
Also available in: Unified diff