Commit b03cce8e08237bb84735aa86aea5d7d7c4633e2d
1 parent
4d7a0880
fixed global variable handling with qemu load/stores - initial global prologue/e…
…pilogue implementation git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4406 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
219 additions
and
62 deletions
tcg/i386/tcg-target.c
... | ... | @@ -46,6 +46,8 @@ int tcg_target_reg_alloc_order[] = { |
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,7 +881,8 @@ static inline void tcg_out_op(TCGContext *s, int opc, |
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,6 +1148,53 @@ static const TCGTargetOpDef x86_op_defs[] = { |
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 */ | ... | ... |
tcg/tcg.c
... | ... | @@ -242,6 +242,13 @@ void tcg_context_init(TCGContext *s) |
242 | 242 | } |
243 | 243 | |
244 | 244 | tcg_target_init(s); |
245 | + | |
246 | + /* init global prologue and epilogue */ | |
247 | + s->code_buf = code_gen_prologue; | |
248 | + s->code_ptr = s->code_buf; | |
249 | + tcg_target_qemu_prologue(s); | |
250 | + flush_icache_range((unsigned long)s->code_buf, | |
251 | + (unsigned long)s->code_ptr); | |
245 | 252 | } |
246 | 253 | |
247 | 254 | void tcg_set_frame(TCGContext *s, int reg, |
... | ... | @@ -680,36 +687,57 @@ void tcg_dump_ops(TCGContext *s, FILE *outfile) |
680 | 687 | nb_oargs = arg >> 16; |
681 | 688 | nb_iargs = arg & 0xffff; |
682 | 689 | nb_cargs = def->nb_cargs; |
683 | - } else if (c == INDEX_op_nopn) { | |
684 | - /* variable number of arguments */ | |
685 | - nb_cargs = *args; | |
686 | - nb_oargs = 0; | |
687 | - nb_iargs = 0; | |
688 | - } else { | |
689 | - nb_oargs = def->nb_oargs; | |
690 | - nb_iargs = def->nb_iargs; | |
691 | - nb_cargs = def->nb_cargs; | |
692 | - } | |
693 | 690 | |
694 | - k = 0; | |
695 | - for(i = 0; i < nb_oargs; i++) { | |
696 | - if (k != 0) | |
697 | - fprintf(outfile, ","); | |
698 | - fprintf(outfile, "%s", | |
699 | - tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++])); | |
700 | - } | |
701 | - for(i = 0; i < nb_iargs; i++) { | |
702 | - if (k != 0) | |
703 | - fprintf(outfile, ","); | |
691 | + /* function name */ | |
704 | 692 | /* XXX: dump helper name for call */ |
705 | 693 | fprintf(outfile, "%s", |
706 | - tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++])); | |
707 | - } | |
708 | - for(i = 0; i < nb_cargs; i++) { | |
709 | - if (k != 0) | |
694 | + tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1])); | |
695 | + /* flags */ | |
696 | + fprintf(outfile, ",$0x%" TCG_PRIlx, | |
697 | + args[nb_oargs + nb_iargs]); | |
698 | + /* nb out args */ | |
699 | + fprintf(outfile, ",$%d", nb_oargs); | |
700 | + for(i = 0; i < nb_oargs; i++) { | |
701 | + fprintf(outfile, ","); | |
702 | + fprintf(outfile, "%s", | |
703 | + tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i])); | |
704 | + } | |
705 | + for(i = 0; i < (nb_iargs - 1); i++) { | |
710 | 706 | fprintf(outfile, ","); |
711 | - arg = args[k++]; | |
712 | - fprintf(outfile, "$0x%" TCG_PRIlx, arg); | |
707 | + fprintf(outfile, "%s", | |
708 | + tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i])); | |
709 | + } | |
710 | + } else { | |
711 | + if (c == INDEX_op_nopn) { | |
712 | + /* variable number of arguments */ | |
713 | + nb_cargs = *args; | |
714 | + nb_oargs = 0; | |
715 | + nb_iargs = 0; | |
716 | + } else { | |
717 | + nb_oargs = def->nb_oargs; | |
718 | + nb_iargs = def->nb_iargs; | |
719 | + nb_cargs = def->nb_cargs; | |
720 | + } | |
721 | + | |
722 | + k = 0; | |
723 | + for(i = 0; i < nb_oargs; i++) { | |
724 | + if (k != 0) | |
725 | + fprintf(outfile, ","); | |
726 | + fprintf(outfile, "%s", | |
727 | + tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++])); | |
728 | + } | |
729 | + for(i = 0; i < nb_iargs; i++) { | |
730 | + if (k != 0) | |
731 | + fprintf(outfile, ","); | |
732 | + fprintf(outfile, "%s", | |
733 | + tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++])); | |
734 | + } | |
735 | + for(i = 0; i < nb_cargs; i++) { | |
736 | + if (k != 0) | |
737 | + fprintf(outfile, ","); | |
738 | + arg = args[k++]; | |
739 | + fprintf(outfile, "$0x%" TCG_PRIlx, arg); | |
740 | + } | |
713 | 741 | } |
714 | 742 | fprintf(outfile, "\n"); |
715 | 743 | args += nb_iargs + nb_oargs + nb_cargs; |
... | ... | @@ -1027,6 +1055,9 @@ void tcg_liveness_analysis(TCGContext *s) |
1027 | 1055 | /* if end of basic block, update */ |
1028 | 1056 | if (def->flags & TCG_OPF_BB_END) { |
1029 | 1057 | tcg_la_bb_end(s, dead_temps); |
1058 | + } else if (def->flags & TCG_OPF_CALL_CLOBBER) { | |
1059 | + /* globals are live */ | |
1060 | + memset(dead_temps, 0, s->nb_globals); | |
1030 | 1061 | } |
1031 | 1062 | |
1032 | 1063 | /* input args are live */ |
... | ... | @@ -1119,9 +1150,7 @@ static void check_regs(TCGContext *s) |
1119 | 1150 | ts->reg != reg) { |
1120 | 1151 | printf("Inconsistency for register %s:\n", |
1121 | 1152 | tcg_target_reg_names[reg]); |
1122 | - printf("reg state:\n"); | |
1123 | - dump_regs(s); | |
1124 | - tcg_abort(); | |
1153 | + goto fail; | |
1125 | 1154 | } |
1126 | 1155 | } |
1127 | 1156 | } |
... | ... | @@ -1132,10 +1161,16 @@ static void check_regs(TCGContext *s) |
1132 | 1161 | s->reg_to_temp[ts->reg] != k) { |
1133 | 1162 | printf("Inconsistency for temp %s:\n", |
1134 | 1163 | tcg_get_arg_str_idx(s, buf, sizeof(buf), k)); |
1164 | + fail: | |
1135 | 1165 | printf("reg state:\n"); |
1136 | 1166 | dump_regs(s); |
1137 | 1167 | tcg_abort(); |
1138 | 1168 | } |
1169 | + if (ts->val_type == TEMP_VAL_CONST && k < s->nb_globals) { | |
1170 | + printf("constant forbidden in global %s\n", | |
1171 | + tcg_get_arg_str_idx(s, buf, sizeof(buf), k)); | |
1172 | + goto fail; | |
1173 | + } | |
1139 | 1174 | } |
1140 | 1175 | } |
1141 | 1176 | #endif |
... | ... | @@ -1376,13 +1411,26 @@ static void tcg_reg_alloc_op(TCGContext *s, |
1376 | 1411 | } |
1377 | 1412 | } |
1378 | 1413 | |
1379 | - /* XXX: permit generic clobber register list ? */ | |
1380 | 1414 | if (def->flags & TCG_OPF_CALL_CLOBBER) { |
1415 | + /* XXX: permit generic clobber register list ? */ | |
1381 | 1416 | for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) { |
1382 | 1417 | if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) { |
1383 | 1418 | tcg_reg_free(s, reg); |
1384 | 1419 | } |
1385 | 1420 | } |
1421 | + /* XXX: for load/store we could do that only for the slow path | |
1422 | + (i.e. when a memory callback is called) */ | |
1423 | + | |
1424 | + /* store globals and free associated registers (we assume the insn | |
1425 | + can modify any global. */ | |
1426 | + for(i = 0; i < s->nb_globals; i++) { | |
1427 | + ts = &s->temps[i]; | |
1428 | + if (!ts->fixed_reg) { | |
1429 | + if (ts->val_type == TEMP_VAL_REG) { | |
1430 | + tcg_reg_free(s, ts->reg); | |
1431 | + } | |
1432 | + } | |
1433 | + } | |
1386 | 1434 | } |
1387 | 1435 | |
1388 | 1436 | /* satisfy the output constraints */ |
... | ... | @@ -1435,6 +1483,12 @@ static void tcg_reg_alloc_op(TCGContext *s, |
1435 | 1483 | } |
1436 | 1484 | } |
1437 | 1485 | |
1486 | +#ifdef TCG_TARGET_STACK_GROWSUP | |
1487 | +#define STACK_DIR(x) (-(x)) | |
1488 | +#else | |
1489 | +#define STACK_DIR(x) (x) | |
1490 | +#endif | |
1491 | + | |
1438 | 1492 | static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, |
1439 | 1493 | int opc, const TCGArg *args, |
1440 | 1494 | unsigned int dead_iargs) |
... | ... | @@ -1443,7 +1497,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, |
1443 | 1497 | TCGArg arg, func_arg; |
1444 | 1498 | TCGTemp *ts; |
1445 | 1499 | tcg_target_long stack_offset, call_stack_size, func_addr; |
1446 | - int const_func_arg; | |
1500 | + int const_func_arg, allocate_args; | |
1447 | 1501 | TCGRegSet allocated_regs; |
1448 | 1502 | const TCGArgConstraint *arg_ct; |
1449 | 1503 | |
... | ... | @@ -1464,12 +1518,11 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, |
1464 | 1518 | call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long); |
1465 | 1519 | call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & |
1466 | 1520 | ~(TCG_TARGET_STACK_ALIGN - 1); |
1467 | -#ifdef TCG_TARGET_STACK_GROWSUP | |
1468 | - tcg_out_addi(s, TCG_REG_CALL_STACK, call_stack_size); | |
1469 | -#else | |
1470 | - tcg_out_addi(s, TCG_REG_CALL_STACK, -call_stack_size); | |
1471 | -#endif | |
1472 | - | |
1521 | + allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE); | |
1522 | + if (allocate_args) { | |
1523 | + tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size)); | |
1524 | + } | |
1525 | + /* XXX: on some architectures it does not start at zero */ | |
1473 | 1526 | stack_offset = 0; |
1474 | 1527 | for(i = nb_regs; i < nb_params; i++) { |
1475 | 1528 | arg = args[nb_oargs + i]; |
... | ... | @@ -1491,11 +1544,8 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, |
1491 | 1544 | } else { |
1492 | 1545 | tcg_abort(); |
1493 | 1546 | } |
1494 | -#ifdef TCG_TARGET_STACK_GROWSUP | |
1495 | - stack_offset -= sizeof(tcg_target_long); | |
1496 | -#else | |
1497 | - stack_offset += sizeof(tcg_target_long); | |
1498 | -#endif | |
1547 | + /* XXX: not necessarily in the same order */ | |
1548 | + stack_offset += STACK_DIR(sizeof(tcg_target_long)); | |
1499 | 1549 | } |
1500 | 1550 | |
1501 | 1551 | /* assign input registers */ |
... | ... | @@ -1525,9 +1575,6 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, |
1525 | 1575 | arg_ct = &def->args_ct[0]; |
1526 | 1576 | ts = &s->temps[func_arg]; |
1527 | 1577 | func_addr = ts->val; |
1528 | -#ifdef HOST_HPPA | |
1529 | - func_addr = (tcg_target_long)__canonicalize_funcptr_for_compare((void *)func_addr); | |
1530 | -#endif | |
1531 | 1578 | const_func_arg = 0; |
1532 | 1579 | if (ts->val_type == TEMP_VAL_MEM) { |
1533 | 1580 | reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs); |
... | ... | @@ -1586,11 +1633,9 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, |
1586 | 1633 | |
1587 | 1634 | tcg_out_op(s, opc, &func_arg, &const_func_arg); |
1588 | 1635 | |
1589 | -#ifdef TCG_TARGET_STACK_GROWSUP | |
1590 | - tcg_out_addi(s, TCG_REG_CALL_STACK, -call_stack_size); | |
1591 | -#else | |
1592 | - tcg_out_addi(s, TCG_REG_CALL_STACK, call_stack_size); | |
1593 | -#endif | |
1636 | + if (allocate_args) { | |
1637 | + tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size)); | |
1638 | + } | |
1594 | 1639 | |
1595 | 1640 | /* assign output registers and emit moves if needed */ |
1596 | 1641 | for(i = 0; i < nb_oargs; i++) { |
... | ... | @@ -1672,10 +1717,6 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, |
1672 | 1717 | args = gen_opparam_buf; |
1673 | 1718 | op_index = 0; |
1674 | 1719 | |
1675 | -#ifdef TCG_TARGET_NEEDS_PROLOGUE | |
1676 | - tcg_target_prologue(s); | |
1677 | -#endif | |
1678 | - | |
1679 | 1720 | for(;;) { |
1680 | 1721 | opc = gen_opc_buf[op_index]; |
1681 | 1722 | #ifdef CONFIG_PROFILER | ... | ... |
tcg/tcg.h
... | ... | @@ -90,6 +90,10 @@ typedef struct TCGPool { |
90 | 90 | |
91 | 91 | #define TCG_MAX_TEMPS 512 |
92 | 92 | |
93 | +/* when the size of the arguments of a called function is smaller than | |
94 | + this value, they are statically allocated in the TB stack frame */ | |
95 | +#define TCG_STATIC_CALL_ARGS_SIZE 128 | |
96 | + | |
93 | 97 | typedef int TCGType; |
94 | 98 | |
95 | 99 | #define TCG_TYPE_I32 0 |
... | ... | @@ -285,8 +289,11 @@ typedef struct TCGArgConstraint { |
285 | 289 | |
286 | 290 | #define TCG_OPF_BB_END 0x01 /* instruction defines the end of a basic |
287 | 291 | block */ |
288 | -#define TCG_OPF_CALL_CLOBBER 0x02 /* instruction clobbers call registers */ | |
289 | -#define TCG_OPF_SIDE_EFFECTS 0x04 /* instruction has side effects */ | |
292 | +#define TCG_OPF_CALL_CLOBBER 0x02 /* instruction clobbers call registers | |
293 | + and potentially update globals. */ | |
294 | +#define TCG_OPF_SIDE_EFFECTS 0x04 /* instruction has side effects : it | |
295 | + cannot be removed if its output | |
296 | + are not used */ | |
290 | 297 | |
291 | 298 | typedef struct TCGOpDef { |
292 | 299 | const char *name; |
... | ... | @@ -305,6 +312,7 @@ typedef struct TCGTargetOpDef { |
305 | 312 | extern TCGOpDef tcg_op_defs[]; |
306 | 313 | |
307 | 314 | void tcg_target_init(TCGContext *s); |
315 | +void tcg_target_qemu_prologue(TCGContext *s); | |
308 | 316 | |
309 | 317 | #define tcg_abort() \ |
310 | 318 | do {\ |
... | ... | @@ -358,3 +366,6 @@ int64_t tcg_helper_div_i64(int64_t arg1, int64_t arg2); |
358 | 366 | int64_t tcg_helper_rem_i64(int64_t arg1, int64_t arg2); |
359 | 367 | uint64_t tcg_helper_divu_i64(uint64_t arg1, uint64_t arg2); |
360 | 368 | uint64_t tcg_helper_remu_i64(uint64_t arg1, uint64_t arg2); |
369 | + | |
370 | +extern uint8_t code_gen_prologue[]; | |
371 | +#define tcg_qemu_tb_exec(tb_ptr) ((long REGPARM (*)(void *))code_gen_prologue)(tb_ptr) | ... | ... |
tcg/x86_64/tcg-target.c
... | ... | @@ -73,6 +73,8 @@ const int tcg_target_call_oarg_regs[2] = { |
73 | 73 | TCG_REG_RDX |
74 | 74 | }; |
75 | 75 | |
76 | +static uint8_t *tb_ret_addr; | |
77 | + | |
76 | 78 | static void patch_reloc(uint8_t *code_ptr, int type, |
77 | 79 | tcg_target_long value, tcg_target_long addend) |
78 | 80 | { |
... | ... | @@ -841,7 +843,8 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, |
841 | 843 | switch(opc) { |
842 | 844 | case INDEX_op_exit_tb: |
843 | 845 | tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RAX, args[0]); |
844 | - tcg_out8(s, 0xc3); /* ret */ | |
846 | + tcg_out8(s, 0xe9); /* jmp tb_ret_addr */ | |
847 | + tcg_out32(s, tb_ret_addr - s->code_ptr - 4); | |
845 | 848 | break; |
846 | 849 | case INDEX_op_goto_tb: |
847 | 850 | if (s->tb_jmp_offset) { |
... | ... | @@ -1129,6 +1132,58 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, |
1129 | 1132 | } |
1130 | 1133 | } |
1131 | 1134 | |
1135 | +static int tcg_target_callee_save_regs[] = { | |
1136 | + TCG_REG_R10, | |
1137 | + TCG_REG_R11, | |
1138 | + TCG_REG_RBP, | |
1139 | + TCG_REG_RBX, | |
1140 | + TCG_REG_R12, | |
1141 | + TCG_REG_R13, | |
1142 | + /* TCG_REG_R14, */ /* currently used for the global env, so no | |
1143 | + need to save */ | |
1144 | + TCG_REG_R15, | |
1145 | +}; | |
1146 | + | |
1147 | +static inline void tcg_out_push(TCGContext *s, int reg) | |
1148 | +{ | |
1149 | + tcg_out_opc(s, (0x50 + (reg & 7)), 0, reg, 0); | |
1150 | +} | |
1151 | + | |
1152 | +static inline void tcg_out_pop(TCGContext *s, int reg) | |
1153 | +{ | |
1154 | + tcg_out_opc(s, (0x58 + (reg & 7)), 0, reg, 0); | |
1155 | +} | |
1156 | + | |
1157 | +/* Generate global QEMU prologue and epilogue code */ | |
1158 | +void tcg_target_qemu_prologue(TCGContext *s) | |
1159 | +{ | |
1160 | + int i, frame_size, push_size, stack_addend; | |
1161 | + | |
1162 | + /* TB prologue */ | |
1163 | + /* save all callee saved registers */ | |
1164 | + for(i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { | |
1165 | + tcg_out_push(s, tcg_target_callee_save_regs[i]); | |
1166 | + | |
1167 | + } | |
1168 | + /* reserve some stack space */ | |
1169 | + push_size = 8 + ARRAY_SIZE(tcg_target_callee_save_regs) * 8; | |
1170 | + frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE; | |
1171 | + frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) & | |
1172 | + ~(TCG_TARGET_STACK_ALIGN - 1); | |
1173 | + stack_addend = frame_size - push_size; | |
1174 | + tcg_out_addi(s, TCG_REG_RSP, -stack_addend); | |
1175 | + | |
1176 | + tcg_out_modrm(s, 0xff, 4, TCG_REG_RDI); /* jmp *%rdi */ | |
1177 | + | |
1178 | + /* TB epilogue */ | |
1179 | + tb_ret_addr = s->code_ptr; | |
1180 | + tcg_out_addi(s, TCG_REG_RSP, stack_addend); | |
1181 | + for(i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) { | |
1182 | + tcg_out_pop(s, tcg_target_callee_save_regs[i]); | |
1183 | + } | |
1184 | + tcg_out8(s, 0xc3); /* ret */ | |
1185 | +} | |
1186 | + | |
1132 | 1187 | static const TCGTargetOpDef x86_64_op_defs[] = { |
1133 | 1188 | { INDEX_op_exit_tb, { } }, |
1134 | 1189 | { INDEX_op_goto_tb, { } }, |
... | ... | @@ -1212,6 +1267,10 @@ static const TCGTargetOpDef x86_64_op_defs[] = { |
1212 | 1267 | |
1213 | 1268 | void tcg_target_init(TCGContext *s) |
1214 | 1269 | { |
1270 | + /* fail safe */ | |
1271 | + if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry)) | |
1272 | + tcg_abort(); | |
1273 | + | |
1215 | 1274 | tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff); |
1216 | 1275 | tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffff); |
1217 | 1276 | tcg_regset_set32(tcg_target_call_clobber_regs, 0, |
... | ... | @@ -1227,10 +1286,6 @@ void tcg_target_init(TCGContext *s) |
1227 | 1286 | |
1228 | 1287 | tcg_regset_clear(s->reserved_regs); |
1229 | 1288 | tcg_regset_set_reg(s->reserved_regs, TCG_REG_RSP); |
1230 | - /* XXX: will be suppresed when proper global TB entry code will be | |
1231 | - generated */ | |
1232 | - tcg_regset_set_reg(s->reserved_regs, TCG_REG_RBX); | |
1233 | - tcg_regset_set_reg(s->reserved_regs, TCG_REG_RBP); | |
1234 | 1289 | |
1235 | 1290 | tcg_add_target_add_op_defs(x86_64_op_defs); |
1236 | 1291 | } | ... | ... |