2 * Tiny Code Generator for QEMU
4 * Copyright (c) 2008 Fabrice Bellard
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
38 static const int tcg_target_reg_alloc_order[] = {
48 static const int tcg_target_call_iarg_regs[3] = { TCG_REG_EAX, TCG_REG_EDX, TCG_REG_ECX };
49 static const int tcg_target_call_oarg_regs[2] = { TCG_REG_EAX, TCG_REG_EDX };
51 static uint8_t *tb_ret_addr;
53 static void patch_reloc(uint8_t *code_ptr, int type,
54 tcg_target_long value, tcg_target_long addend)
59 *(uint32_t *)code_ptr = value;
62 *(uint32_t *)code_ptr = value - (long)code_ptr;
65 value -= (long)code_ptr;
66 if (value != (int8_t)value) {
69 *(uint8_t *)code_ptr = value;
76 /* maximum number of register used for input function arguments */
77 static inline int tcg_target_get_call_iarg_regs_count(int flags)
79 flags &= TCG_CALL_TYPE_MASK;
81 case TCG_CALL_TYPE_STD:
83 case TCG_CALL_TYPE_REGPARM_1:
84 case TCG_CALL_TYPE_REGPARM_2:
85 case TCG_CALL_TYPE_REGPARM:
86 return flags - TCG_CALL_TYPE_REGPARM_1 + 1;
92 /* parse target specific constraints */
93 static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
100 ct->ct |= TCG_CT_REG;
101 tcg_regset_set_reg(ct->u.regs, TCG_REG_EAX);
104 ct->ct |= TCG_CT_REG;
105 tcg_regset_set_reg(ct->u.regs, TCG_REG_EBX);
108 ct->ct |= TCG_CT_REG;
109 tcg_regset_set_reg(ct->u.regs, TCG_REG_ECX);
112 ct->ct |= TCG_CT_REG;
113 tcg_regset_set_reg(ct->u.regs, TCG_REG_EDX);
116 ct->ct |= TCG_CT_REG;
117 tcg_regset_set_reg(ct->u.regs, TCG_REG_ESI);
120 ct->ct |= TCG_CT_REG;
121 tcg_regset_set_reg(ct->u.regs, TCG_REG_EDI);
124 ct->ct |= TCG_CT_REG;
125 tcg_regset_set32(ct->u.regs, 0, 0xf);
128 ct->ct |= TCG_CT_REG;
129 tcg_regset_set32(ct->u.regs, 0, 0xff);
132 /* qemu_ld/st address constraint */
134 ct->ct |= TCG_CT_REG;
135 tcg_regset_set32(ct->u.regs, 0, 0xff);
136 tcg_regset_reset_reg(ct->u.regs, TCG_REG_EAX);
137 tcg_regset_reset_reg(ct->u.regs, TCG_REG_EDX);
147 /* test if a constant matches the constraint */
148 static inline int tcg_target_const_match(tcg_target_long val,
149 const TCGArgConstraint *arg_ct)
153 if (ct & TCG_CT_CONST)
159 #define P_EXT 0x100 /* 0x0f opcode prefix */
161 #define OPC_ARITH_EvIz (0x81)
162 #define OPC_ARITH_EvIb (0x83)
163 #define OPC_ARITH_GvEv (0x03) /* ... plus (ARITH_FOO << 3) */
164 #define OPC_ADD_GvEv (OPC_ARITH_GvEv | (ARITH_ADD << 3))
165 #define OPC_BSWAP (0xc8 | P_EXT)
166 #define OPC_CMP_GvEv (OPC_ARITH_GvEv | (ARITH_CMP << 3))
167 #define OPC_DEC_r32 (0x48)
168 #define OPC_INC_r32 (0x40)
169 #define OPC_JCC_long (0x80 | P_EXT) /* ... plus condition code */
170 #define OPC_JCC_short (0x70) /* ... plus condition code */
171 #define OPC_JMP_long (0xe9)
172 #define OPC_JMP_short (0xeb)
173 #define OPC_MOVB_EvGv (0x88) /* stores, more or less */
174 #define OPC_MOVL_EvGv (0x89) /* stores, more or less */
175 #define OPC_MOVL_GvEv (0x8b) /* loads, more or less */
176 #define OPC_MOVL_Iv (0xb8)
177 #define OPC_MOVSBL (0xbe | P_EXT)
178 #define OPC_MOVSWL (0xbf | P_EXT)
179 #define OPC_MOVZBL (0xb6 | P_EXT)
180 #define OPC_MOVZWL (0xb7 | P_EXT)
181 #define OPC_POP_r32 (0x58)
182 #define OPC_PUSH_r32 (0x50)
183 #define OPC_PUSH_Iv (0x68)
184 #define OPC_PUSH_Ib (0x6a)
185 #define OPC_SHIFT_1 (0xd1)
186 #define OPC_SHIFT_Ib (0xc1)
187 #define OPC_SHIFT_cl (0xd3)
188 #define OPC_TESTL (0x85)
190 /* Group 1 opcode extensions for 0x80-0x83. */
200 /* Group 2 opcode extensions for 0xc0, 0xc1, 0xd0-0xd3. */
207 /* Group 5 opcode extensions for 0xff. */
208 #define EXT_JMPN_Ev 4
210 /* Condition codes to be added to OPC_JCC_{long,short}. */
229 static const uint8_t tcg_cond_to_jcc[10] = {
230 [TCG_COND_EQ] = JCC_JE,
231 [TCG_COND_NE] = JCC_JNE,
232 [TCG_COND_LT] = JCC_JL,
233 [TCG_COND_GE] = JCC_JGE,
234 [TCG_COND_LE] = JCC_JLE,
235 [TCG_COND_GT] = JCC_JG,
236 [TCG_COND_LTU] = JCC_JB,
237 [TCG_COND_GEU] = JCC_JAE,
238 [TCG_COND_LEU] = JCC_JBE,
239 [TCG_COND_GTU] = JCC_JA,
242 static inline void tcg_out_opc(TCGContext *s, int opc)
249 static inline void tcg_out_modrm(TCGContext *s, int opc, int r, int rm)
252 tcg_out8(s, 0xc0 | (r << 3) | rm);
255 /* rm == -1 means no register index */
256 static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r, int rm,
261 tcg_out8(s, 0x05 | (r << 3));
262 tcg_out32(s, offset);
263 } else if (offset == 0 && rm != TCG_REG_EBP) {
264 if (rm == TCG_REG_ESP) {
265 tcg_out8(s, 0x04 | (r << 3));
268 tcg_out8(s, 0x00 | (r << 3) | rm);
270 } else if ((int8_t)offset == offset) {
271 if (rm == TCG_REG_ESP) {
272 tcg_out8(s, 0x44 | (r << 3));
275 tcg_out8(s, 0x40 | (r << 3) | rm);
279 if (rm == TCG_REG_ESP) {
280 tcg_out8(s, 0x84 | (r << 3));
283 tcg_out8(s, 0x80 | (r << 3) | rm);
285 tcg_out32(s, offset);
289 /* Generate dest op= src. Uses the same ARITH_* codes as tgen_arithi. */
290 static inline void tgen_arithr(TCGContext *s, int subop, int dest, int src)
292 tcg_out_modrm(s, OPC_ARITH_GvEv + (subop << 3), dest, src);
295 static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
298 tcg_out_modrm(s, OPC_MOVL_GvEv, ret, arg);
302 static inline void tcg_out_movi(TCGContext *s, TCGType type,
303 int ret, int32_t arg)
306 tgen_arithr(s, ARITH_XOR, ret, ret);
308 tcg_out8(s, OPC_MOVL_Iv + ret);
313 static inline void tcg_out_pushi(TCGContext *s, tcg_target_long val)
315 if (val == (int8_t)val) {
316 tcg_out_opc(s, OPC_PUSH_Ib);
319 tcg_out_opc(s, OPC_PUSH_Iv);
324 static inline void tcg_out_push(TCGContext *s, int reg)
326 tcg_out_opc(s, OPC_PUSH_r32 + reg);
329 static inline void tcg_out_pop(TCGContext *s, int reg)
331 tcg_out_opc(s, OPC_POP_r32 + reg);
334 static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
335 int arg1, tcg_target_long arg2)
337 tcg_out_modrm_offset(s, OPC_MOVL_GvEv, ret, arg1, arg2);
340 static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
341 int arg1, tcg_target_long arg2)
343 tcg_out_modrm_offset(s, OPC_MOVL_EvGv, arg, arg1, arg2);
346 static void tcg_out_shifti(TCGContext *s, int subopc, int reg, int count)
349 tcg_out_modrm(s, OPC_SHIFT_1, subopc, reg);
351 tcg_out_modrm(s, OPC_SHIFT_Ib, subopc, reg);
356 static inline void tcg_out_bswap32(TCGContext *s, int reg)
358 tcg_out_opc(s, OPC_BSWAP + reg);
361 static inline void tcg_out_rolw_8(TCGContext *s, int reg)
364 tcg_out_shifti(s, SHIFT_ROL, reg, 8);
367 static inline void tcg_out_ext8u(TCGContext *s, int dest, int src)
371 tcg_out_modrm(s, OPC_MOVZBL, dest, src);
374 static void tcg_out_ext8s(TCGContext *s, int dest, int src)
378 tcg_out_modrm(s, OPC_MOVSBL, dest, src);
381 static inline void tcg_out_ext16u(TCGContext *s, int dest, int src)
384 tcg_out_modrm(s, OPC_MOVZWL, dest, src);
387 static inline void tcg_out_ext16s(TCGContext *s, int dest, int src)
390 tcg_out_modrm(s, OPC_MOVSWL, dest, src);
393 static inline void tgen_arithi(TCGContext *s, int c, int r0,
396 /* ??? While INC is 2 bytes shorter than ADDL $1, they also induce
397 partial flags update stalls on Pentium4 and are not recommended
398 by current Intel optimization manuals. */
399 if (!cf && (c == ARITH_ADD || c == ARITH_SUB) && (val == 1 || val == -1)) {
400 int opc = ((c == ARITH_ADD) ^ (val < 0) ? OPC_INC_r32 : OPC_DEC_r32);
401 tcg_out_opc(s, opc + r0);
402 } else if (val == (int8_t)val) {
403 tcg_out_modrm(s, OPC_ARITH_EvIb, c, r0);
405 } else if (c == ARITH_AND && val == 0xffu && r0 < 4) {
406 tcg_out_ext8u(s, r0, r0);
407 } else if (c == ARITH_AND && val == 0xffffu) {
408 tcg_out_ext16u(s, r0, r0);
410 tcg_out_modrm(s, OPC_ARITH_EvIz, c, r0);
415 static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
418 tgen_arithi(s, ARITH_ADD, reg, val, 0);
421 /* Use SMALL != 0 to force a short forward branch. */
422 static void tcg_out_jxx(TCGContext *s, int opc, int label_index, int small)
425 TCGLabel *l = &s->labels[label_index];
428 val = l->u.value - (tcg_target_long)s->code_ptr;
430 if ((int8_t)val1 == val1) {
432 tcg_out8(s, OPC_JMP_short);
434 tcg_out8(s, OPC_JCC_short + opc);
442 tcg_out8(s, OPC_JMP_long);
443 tcg_out32(s, val - 5);
445 tcg_out_opc(s, OPC_JCC_long + opc);
446 tcg_out32(s, val - 6);
451 tcg_out8(s, OPC_JMP_short);
453 tcg_out8(s, OPC_JCC_short + opc);
455 tcg_out_reloc(s, s->code_ptr, R_386_PC8, label_index, -1);
459 tcg_out8(s, OPC_JMP_long);
461 tcg_out_opc(s, OPC_JCC_long + opc);
463 tcg_out_reloc(s, s->code_ptr, R_386_PC32, label_index, -4);
468 static void tcg_out_cmp(TCGContext *s, TCGArg arg1, TCGArg arg2,
474 tcg_out_modrm(s, OPC_TESTL, arg1, arg1);
476 tgen_arithi(s, ARITH_CMP, arg1, arg2, 0);
479 tgen_arithr(s, ARITH_CMP, arg1, arg2);
483 static void tcg_out_brcond(TCGContext *s, TCGCond cond,
484 TCGArg arg1, TCGArg arg2, int const_arg2,
485 int label_index, int small)
487 tcg_out_cmp(s, arg1, arg2, const_arg2);
488 tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index, small);
491 /* XXX: we implement it at the target level to avoid having to
492 handle cross basic blocks temporaries */
493 static void tcg_out_brcond2(TCGContext *s, const TCGArg *args,
494 const int *const_args, int small)
497 label_next = gen_new_label();
500 tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2],
502 tcg_out_brcond(s, TCG_COND_EQ, args[1], args[3], const_args[3],
506 tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2],
508 tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3],
512 tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3],
514 tcg_out_jxx(s, JCC_JNE, label_next, 1);
515 tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2],
519 tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3],
521 tcg_out_jxx(s, JCC_JNE, label_next, 1);
522 tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2],
526 tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3],
528 tcg_out_jxx(s, JCC_JNE, label_next, 1);
529 tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2],
533 tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3],
535 tcg_out_jxx(s, JCC_JNE, label_next, 1);
536 tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2],
540 tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3],
542 tcg_out_jxx(s, JCC_JNE, label_next, 1);
543 tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2],
547 tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3],
549 tcg_out_jxx(s, JCC_JNE, label_next, 1);
550 tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2],
554 tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3],
556 tcg_out_jxx(s, JCC_JNE, label_next, 1);
557 tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2],
561 tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3],
563 tcg_out_jxx(s, JCC_JNE, label_next, 1);
564 tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2],
570 tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);
573 static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGArg dest,
574 TCGArg arg1, TCGArg arg2, int const_arg2)
576 tcg_out_cmp(s, arg1, arg2, const_arg2);
578 tcg_out_modrm(s, 0x90 | tcg_cond_to_jcc[cond] | P_EXT, 0, dest);
579 tcg_out_ext8u(s, dest, dest);
582 static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
583 const int *const_args)
586 int label_true, label_over;
588 memcpy(new_args, args+1, 5*sizeof(TCGArg));
590 if (args[0] == args[1] || args[0] == args[2]
591 || (!const_args[3] && args[0] == args[3])
592 || (!const_args[4] && args[0] == args[4])) {
593 /* When the destination overlaps with one of the argument
594 registers, don't do anything tricky. */
595 label_true = gen_new_label();
596 label_over = gen_new_label();
598 new_args[5] = label_true;
599 tcg_out_brcond2(s, new_args, const_args+1, 1);
601 tcg_out_movi(s, TCG_TYPE_I32, args[0], 0);
602 tcg_out_jxx(s, JCC_JMP, label_over, 1);
603 tcg_out_label(s, label_true, (tcg_target_long)s->code_ptr);
605 tcg_out_movi(s, TCG_TYPE_I32, args[0], 1);
606 tcg_out_label(s, label_over, (tcg_target_long)s->code_ptr);
608 /* When the destination does not overlap one of the arguments,
609 clear the destination first, jump if cond false, and emit an
610 increment in the true case. This results in smaller code. */
612 tcg_out_movi(s, TCG_TYPE_I32, args[0], 0);
614 label_over = gen_new_label();
615 new_args[4] = tcg_invert_cond(new_args[4]);
616 new_args[5] = label_over;
617 tcg_out_brcond2(s, new_args, const_args+1, 1);
619 tgen_arithi(s, ARITH_ADD, args[0], 1, 0);
620 tcg_out_label(s, label_over, (tcg_target_long)s->code_ptr);
624 #if defined(CONFIG_SOFTMMU)
626 #include "../../softmmu_defs.h"
628 static void *qemu_ld_helpers[4] = {
635 static void *qemu_st_helpers[4] = {
643 #ifndef CONFIG_USER_ONLY
647 /* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and
648 EAX. It will be useful once fixed registers globals are less
650 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
653 int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
654 #if defined(CONFIG_SOFTMMU)
655 uint8_t *label1_ptr, *label2_ptr;
657 #if TARGET_LONG_BITS == 64
658 #if defined(CONFIG_SOFTMMU)
670 #if TARGET_LONG_BITS == 64
679 #if defined(CONFIG_SOFTMMU)
680 tcg_out_mov(s, r1, addr_reg);
681 tcg_out_mov(s, r0, addr_reg);
683 tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
685 tgen_arithi(s, ARITH_AND, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
686 tgen_arithi(s, ARITH_AND, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
688 tcg_out_opc(s, 0x8d); /* lea offset(r1, %ebp), r1 */
689 tcg_out8(s, 0x80 | (r1 << 3) | 0x04);
690 tcg_out8(s, (5 << 3) | r1);
691 tcg_out32(s, offsetof(CPUState, tlb_table[mem_index][0].addr_read));
694 tcg_out_modrm_offset(s, OPC_CMP_GvEv, r0, r1, 0);
696 tcg_out_mov(s, r0, addr_reg);
698 #if TARGET_LONG_BITS == 32
700 tcg_out8(s, OPC_JCC_short + JCC_JE);
701 label1_ptr = s->code_ptr;
705 tcg_out8(s, OPC_JCC_short + JCC_JNE);
706 label3_ptr = s->code_ptr;
709 /* cmp 4(r1), addr_reg2 */
710 tcg_out_modrm_offset(s, OPC_CMP_GvEv, addr_reg2, r1, 4);
713 tcg_out8(s, OPC_JCC_short + JCC_JE);
714 label1_ptr = s->code_ptr;
718 *label3_ptr = s->code_ptr - label3_ptr - 1;
721 /* XXX: move that code at the end of the TB */
722 #if TARGET_LONG_BITS == 32
723 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EDX, mem_index);
725 tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
726 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
729 tcg_out32(s, (tcg_target_long)qemu_ld_helpers[s_bits] -
730 (tcg_target_long)s->code_ptr - 4);
734 tcg_out_ext8s(s, data_reg, TCG_REG_EAX);
737 tcg_out_ext16s(s, data_reg, TCG_REG_EAX);
740 tcg_out_ext8u(s, data_reg, TCG_REG_EAX);
743 tcg_out_ext16u(s, data_reg, TCG_REG_EAX);
747 tcg_out_mov(s, data_reg, TCG_REG_EAX);
750 if (data_reg == TCG_REG_EDX) {
751 tcg_out_opc(s, 0x90 + TCG_REG_EDX); /* xchg %edx, %eax */
752 tcg_out_mov(s, data_reg2, TCG_REG_EAX);
754 tcg_out_mov(s, data_reg, TCG_REG_EAX);
755 tcg_out_mov(s, data_reg2, TCG_REG_EDX);
761 tcg_out8(s, OPC_JMP_short);
762 label2_ptr = s->code_ptr;
766 *label1_ptr = s->code_ptr - label1_ptr - 1;
769 tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
770 offsetof(CPUTLBEntry, addend) -
771 offsetof(CPUTLBEntry, addr_read));
776 #ifdef TARGET_WORDS_BIGENDIAN
784 tcg_out_modrm_offset(s, OPC_MOVZBL, data_reg, r0, GUEST_BASE);
788 tcg_out_modrm_offset(s, OPC_MOVSBL, data_reg, r0, GUEST_BASE);
792 tcg_out_modrm_offset(s, OPC_MOVZWL, data_reg, r0, GUEST_BASE);
794 tcg_out_rolw_8(s, data_reg);
799 tcg_out_modrm_offset(s, OPC_MOVSWL, data_reg, r0, GUEST_BASE);
801 tcg_out_rolw_8(s, data_reg);
803 /* movswl data_reg, data_reg */
804 tcg_out_modrm(s, OPC_MOVSWL, data_reg, data_reg);
808 tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
810 tcg_out_bswap32(s, data_reg);
816 data_reg = data_reg2;
819 if (r0 != data_reg) {
820 tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
821 tcg_out_ld(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE + 4);
823 tcg_out_ld(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE + 4);
824 tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
827 tcg_out_bswap32(s, data_reg);
828 tcg_out_bswap32(s, data_reg2);
835 #if defined(CONFIG_SOFTMMU)
837 *label2_ptr = s->code_ptr - label2_ptr - 1;
842 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
845 int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
846 #if defined(CONFIG_SOFTMMU)
847 uint8_t *label1_ptr, *label2_ptr;
849 #if TARGET_LONG_BITS == 64
850 #if defined(CONFIG_SOFTMMU)
862 #if TARGET_LONG_BITS == 64
872 #if defined(CONFIG_SOFTMMU)
873 tcg_out_mov(s, r1, addr_reg);
874 tcg_out_mov(s, r0, addr_reg);
876 tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
878 tgen_arithi(s, ARITH_AND, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
879 tgen_arithi(s, ARITH_AND, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
881 tcg_out_opc(s, 0x8d); /* lea offset(r1, %ebp), r1 */
882 tcg_out8(s, 0x80 | (r1 << 3) | 0x04);
883 tcg_out8(s, (5 << 3) | r1);
884 tcg_out32(s, offsetof(CPUState, tlb_table[mem_index][0].addr_write));
887 tcg_out_modrm_offset(s, OPC_CMP_GvEv, r0, r1, 0);
889 tcg_out_mov(s, r0, addr_reg);
891 #if TARGET_LONG_BITS == 32
893 tcg_out8(s, OPC_JCC_short + JCC_JE);
894 label1_ptr = s->code_ptr;
898 tcg_out8(s, OPC_JCC_short + JCC_JNE);
899 label3_ptr = s->code_ptr;
902 /* cmp 4(r1), addr_reg2 */
903 tcg_out_modrm_offset(s, OPC_CMP_GvEv, addr_reg2, r1, 4);
906 tcg_out8(s, OPC_JCC_short + JCC_JE);
907 label1_ptr = s->code_ptr;
911 *label3_ptr = s->code_ptr - label3_ptr - 1;
914 /* XXX: move that code at the end of the TB */
915 #if TARGET_LONG_BITS == 32
917 tcg_out_mov(s, TCG_REG_EDX, data_reg);
918 tcg_out_mov(s, TCG_REG_ECX, data_reg2);
919 tcg_out_pushi(s, mem_index);
921 tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] -
922 (tcg_target_long)s->code_ptr - 4);
923 tcg_out_addi(s, TCG_REG_ESP, 4);
927 tcg_out_ext8u(s, TCG_REG_EDX, data_reg);
930 tcg_out_ext16u(s, TCG_REG_EDX, data_reg);
933 tcg_out_mov(s, TCG_REG_EDX, data_reg);
936 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
938 tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] -
939 (tcg_target_long)s->code_ptr - 4);
943 tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
944 tcg_out_pushi(s, mem_index);
945 tcg_out_push(s, data_reg2);
946 tcg_out_push(s, data_reg);
948 tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] -
949 (tcg_target_long)s->code_ptr - 4);
950 tcg_out_addi(s, TCG_REG_ESP, 12);
952 tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
955 tcg_out_ext8u(s, TCG_REG_ECX, data_reg);
958 tcg_out_ext16u(s, TCG_REG_ECX, data_reg);
961 tcg_out_mov(s, TCG_REG_ECX, data_reg);
964 tcg_out_pushi(s, mem_index);
966 tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] -
967 (tcg_target_long)s->code_ptr - 4);
968 tcg_out_addi(s, TCG_REG_ESP, 4);
973 tcg_out8(s, OPC_JMP_short);
974 label2_ptr = s->code_ptr;
978 *label1_ptr = s->code_ptr - label1_ptr - 1;
981 tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
982 offsetof(CPUTLBEntry, addend) -
983 offsetof(CPUTLBEntry, addr_write));
988 #ifdef TARGET_WORDS_BIGENDIAN
995 tcg_out_modrm_offset(s, OPC_MOVB_EvGv, data_reg, r0, GUEST_BASE);
999 tcg_out_mov(s, r1, data_reg);
1000 tcg_out_rolw_8(s, r1);
1005 tcg_out_modrm_offset(s, OPC_MOVL_EvGv, data_reg, r0, GUEST_BASE);
1009 tcg_out_mov(s, r1, data_reg);
1010 tcg_out_bswap32(s, r1);
1013 tcg_out_st(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
1017 tcg_out_mov(s, r1, data_reg2);
1018 tcg_out_bswap32(s, r1);
1019 tcg_out_st(s, TCG_TYPE_I32, r1, r0, GUEST_BASE);
1020 tcg_out_mov(s, r1, data_reg);
1021 tcg_out_bswap32(s, r1);
1022 tcg_out_st(s, TCG_TYPE_I32, r1, r0, GUEST_BASE + 4);
1024 tcg_out_st(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
1025 tcg_out_st(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE + 4);
1032 #if defined(CONFIG_SOFTMMU)
1034 *label2_ptr = s->code_ptr - label2_ptr - 1;
1038 static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1039 const TCGArg *args, const int *const_args)
1044 case INDEX_op_exit_tb:
1045 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EAX, args[0]);
1046 tcg_out8(s, OPC_JMP_long); /* jmp tb_ret_addr */
1047 tcg_out32(s, tb_ret_addr - s->code_ptr - 4);
1049 case INDEX_op_goto_tb:
1050 if (s->tb_jmp_offset) {
1051 /* direct jump method */
1052 tcg_out8(s, OPC_JMP_long); /* jmp im */
1053 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1056 /* indirect jump method */
1057 tcg_out_modrm_offset(s, 0xff, EXT_JMPN_Ev, -1,
1058 (tcg_target_long)(s->tb_next + args[0]));
1060 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1063 if (const_args[0]) {
1065 tcg_out32(s, args[0] - (tcg_target_long)s->code_ptr - 4);
1067 tcg_out_modrm(s, 0xff, 2, args[0]);
1071 if (const_args[0]) {
1072 tcg_out8(s, OPC_JMP_long);
1073 tcg_out32(s, args[0] - (tcg_target_long)s->code_ptr - 4);
1076 tcg_out_modrm(s, 0xff, EXT_JMPN_Ev, args[0]);
1080 tcg_out_jxx(s, JCC_JMP, args[0], 0);
1082 case INDEX_op_movi_i32:
1083 tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1085 case INDEX_op_ld8u_i32:
1087 tcg_out_modrm_offset(s, OPC_MOVZBL, args[0], args[1], args[2]);
1089 case INDEX_op_ld8s_i32:
1091 tcg_out_modrm_offset(s, OPC_MOVSBL, args[0], args[1], args[2]);
1093 case INDEX_op_ld16u_i32:
1095 tcg_out_modrm_offset(s, OPC_MOVZWL, args[0], args[1], args[2]);
1097 case INDEX_op_ld16s_i32:
1099 tcg_out_modrm_offset(s, OPC_MOVSWL, args[0], args[1], args[2]);
1101 case INDEX_op_ld_i32:
1102 tcg_out_ld(s, TCG_TYPE_I32, args[0], args[1], args[2]);
1104 case INDEX_op_st8_i32:
1106 tcg_out_modrm_offset(s, OPC_MOVB_EvGv, args[0], args[1], args[2]);
1108 case INDEX_op_st16_i32:
1111 tcg_out_modrm_offset(s, OPC_MOVL_EvGv, args[0], args[1], args[2]);
1113 case INDEX_op_st_i32:
1114 tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]);
1116 case INDEX_op_sub_i32:
1119 case INDEX_op_and_i32:
1122 case INDEX_op_or_i32:
1125 case INDEX_op_xor_i32:
1128 case INDEX_op_add_i32:
1131 if (const_args[2]) {
1132 tgen_arithi(s, c, args[0], args[2], 0);
1134 tgen_arithr(s, c, args[0], args[2]);
1137 case INDEX_op_mul_i32:
1138 if (const_args[2]) {
1141 if (val == (int8_t)val) {
1142 tcg_out_modrm(s, 0x6b, args[0], args[0]);
1145 tcg_out_modrm(s, 0x69, args[0], args[0]);
1149 tcg_out_modrm(s, 0xaf | P_EXT, args[0], args[2]);
1152 case INDEX_op_mulu2_i32:
1153 tcg_out_modrm(s, 0xf7, 4, args[3]);
1155 case INDEX_op_div2_i32:
1156 tcg_out_modrm(s, 0xf7, 7, args[4]);
1158 case INDEX_op_divu2_i32:
1159 tcg_out_modrm(s, 0xf7, 6, args[4]);
1161 case INDEX_op_shl_i32:
1164 if (const_args[2]) {
1165 tcg_out_shifti(s, c, args[0], args[2]);
1167 tcg_out_modrm(s, OPC_SHIFT_cl, c, args[0]);
1170 case INDEX_op_shr_i32:
1173 case INDEX_op_sar_i32:
1176 case INDEX_op_rotl_i32:
1179 case INDEX_op_rotr_i32:
1183 case INDEX_op_add2_i32:
1184 if (const_args[4]) {
1185 tgen_arithi(s, ARITH_ADD, args[0], args[4], 1);
1187 tgen_arithr(s, ARITH_ADD, args[0], args[4]);
1189 if (const_args[5]) {
1190 tgen_arithi(s, ARITH_ADC, args[1], args[5], 1);
1192 tgen_arithr(s, ARITH_ADC, args[1], args[5]);
1195 case INDEX_op_sub2_i32:
1196 if (const_args[4]) {
1197 tgen_arithi(s, ARITH_SUB, args[0], args[4], 1);
1199 tgen_arithr(s, ARITH_SUB, args[0], args[4]);
1201 if (const_args[5]) {
1202 tgen_arithi(s, ARITH_SBB, args[1], args[5], 1);
1204 tgen_arithr(s, ARITH_SBB, args[1], args[5]);
1207 case INDEX_op_brcond_i32:
1208 tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
1211 case INDEX_op_brcond2_i32:
1212 tcg_out_brcond2(s, args, const_args, 0);
1215 case INDEX_op_bswap16_i32:
1216 tcg_out_rolw_8(s, args[0]);
1218 case INDEX_op_bswap32_i32:
1219 tcg_out_bswap32(s, args[0]);
1222 case INDEX_op_neg_i32:
1223 tcg_out_modrm(s, 0xf7, 3, args[0]);
1226 case INDEX_op_not_i32:
1227 tcg_out_modrm(s, 0xf7, 2, args[0]);
1230 case INDEX_op_ext8s_i32:
1231 tcg_out_ext8s(s, args[0], args[1]);
1233 case INDEX_op_ext16s_i32:
1234 tcg_out_ext16s(s, args[0], args[1]);
1236 case INDEX_op_ext8u_i32:
1237 tcg_out_ext8u(s, args[0], args[1]);
1239 case INDEX_op_ext16u_i32:
1240 tcg_out_ext16u(s, args[0], args[1]);
1243 case INDEX_op_setcond_i32:
1244 tcg_out_setcond(s, args[3], args[0], args[1], args[2], const_args[2]);
1246 case INDEX_op_setcond2_i32:
1247 tcg_out_setcond2(s, args, const_args);
1250 case INDEX_op_qemu_ld8u:
1251 tcg_out_qemu_ld(s, args, 0);
1253 case INDEX_op_qemu_ld8s:
1254 tcg_out_qemu_ld(s, args, 0 | 4);
1256 case INDEX_op_qemu_ld16u:
1257 tcg_out_qemu_ld(s, args, 1);
1259 case INDEX_op_qemu_ld16s:
1260 tcg_out_qemu_ld(s, args, 1 | 4);
1262 case INDEX_op_qemu_ld32:
1263 tcg_out_qemu_ld(s, args, 2);
1265 case INDEX_op_qemu_ld64:
1266 tcg_out_qemu_ld(s, args, 3);
1269 case INDEX_op_qemu_st8:
1270 tcg_out_qemu_st(s, args, 0);
1272 case INDEX_op_qemu_st16:
1273 tcg_out_qemu_st(s, args, 1);
1275 case INDEX_op_qemu_st32:
1276 tcg_out_qemu_st(s, args, 2);
1278 case INDEX_op_qemu_st64:
1279 tcg_out_qemu_st(s, args, 3);
1287 static const TCGTargetOpDef x86_op_defs[] = {
1288 { INDEX_op_exit_tb, { } },
1289 { INDEX_op_goto_tb, { } },
1290 { INDEX_op_call, { "ri" } },
1291 { INDEX_op_jmp, { "ri" } },
1292 { INDEX_op_br, { } },
1293 { INDEX_op_mov_i32, { "r", "r" } },
1294 { INDEX_op_movi_i32, { "r" } },
1295 { INDEX_op_ld8u_i32, { "r", "r" } },
1296 { INDEX_op_ld8s_i32, { "r", "r" } },
1297 { INDEX_op_ld16u_i32, { "r", "r" } },
1298 { INDEX_op_ld16s_i32, { "r", "r" } },
1299 { INDEX_op_ld_i32, { "r", "r" } },
1300 { INDEX_op_st8_i32, { "q", "r" } },
1301 { INDEX_op_st16_i32, { "r", "r" } },
1302 { INDEX_op_st_i32, { "r", "r" } },
1304 { INDEX_op_add_i32, { "r", "0", "ri" } },
1305 { INDEX_op_sub_i32, { "r", "0", "ri" } },
1306 { INDEX_op_mul_i32, { "r", "0", "ri" } },
1307 { INDEX_op_mulu2_i32, { "a", "d", "a", "r" } },
1308 { INDEX_op_div2_i32, { "a", "d", "0", "1", "r" } },
1309 { INDEX_op_divu2_i32, { "a", "d", "0", "1", "r" } },
1310 { INDEX_op_and_i32, { "r", "0", "ri" } },
1311 { INDEX_op_or_i32, { "r", "0", "ri" } },
1312 { INDEX_op_xor_i32, { "r", "0", "ri" } },
1314 { INDEX_op_shl_i32, { "r", "0", "ci" } },
1315 { INDEX_op_shr_i32, { "r", "0", "ci" } },
1316 { INDEX_op_sar_i32, { "r", "0", "ci" } },
1317 { INDEX_op_rotl_i32, { "r", "0", "ci" } },
1318 { INDEX_op_rotr_i32, { "r", "0", "ci" } },
1320 { INDEX_op_brcond_i32, { "r", "ri" } },
1322 { INDEX_op_add2_i32, { "r", "r", "0", "1", "ri", "ri" } },
1323 { INDEX_op_sub2_i32, { "r", "r", "0", "1", "ri", "ri" } },
1324 { INDEX_op_brcond2_i32, { "r", "r", "ri", "ri" } },
1326 { INDEX_op_bswap16_i32, { "r", "0" } },
1327 { INDEX_op_bswap32_i32, { "r", "0" } },
1329 { INDEX_op_neg_i32, { "r", "0" } },
1331 { INDEX_op_not_i32, { "r", "0" } },
1333 { INDEX_op_ext8s_i32, { "r", "q" } },
1334 { INDEX_op_ext16s_i32, { "r", "r" } },
1335 { INDEX_op_ext8u_i32, { "r", "q" } },
1336 { INDEX_op_ext16u_i32, { "r", "r" } },
1338 { INDEX_op_setcond_i32, { "q", "r", "ri" } },
1339 { INDEX_op_setcond2_i32, { "r", "r", "r", "ri", "ri" } },
1341 #if TARGET_LONG_BITS == 32
1342 { INDEX_op_qemu_ld8u, { "r", "L" } },
1343 { INDEX_op_qemu_ld8s, { "r", "L" } },
1344 { INDEX_op_qemu_ld16u, { "r", "L" } },
1345 { INDEX_op_qemu_ld16s, { "r", "L" } },
1346 { INDEX_op_qemu_ld32, { "r", "L" } },
1347 { INDEX_op_qemu_ld64, { "r", "r", "L" } },
1349 { INDEX_op_qemu_st8, { "cb", "L" } },
1350 { INDEX_op_qemu_st16, { "L", "L" } },
1351 { INDEX_op_qemu_st32, { "L", "L" } },
1352 { INDEX_op_qemu_st64, { "L", "L", "L" } },
1354 { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
1355 { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
1356 { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
1357 { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
1358 { INDEX_op_qemu_ld32, { "r", "L", "L" } },
1359 { INDEX_op_qemu_ld64, { "r", "r", "L", "L" } },
1361 { INDEX_op_qemu_st8, { "cb", "L", "L" } },
1362 { INDEX_op_qemu_st16, { "L", "L", "L" } },
1363 { INDEX_op_qemu_st32, { "L", "L", "L" } },
1364 { INDEX_op_qemu_st64, { "L", "L", "L", "L" } },
1369 static int tcg_target_callee_save_regs[] = {
1370 /* TCG_REG_EBP, */ /* currently used for the global env, so no
1377 /* Generate global QEMU prologue and epilogue code */
1378 void tcg_target_qemu_prologue(TCGContext *s)
1380 int i, frame_size, push_size, stack_addend;
1383 /* save all callee saved registers */
1384 for(i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
1385 tcg_out_push(s, tcg_target_callee_save_regs[i]);
1387 /* reserve some stack space */
1388 push_size = 4 + ARRAY_SIZE(tcg_target_callee_save_regs) * 4;
1389 frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE;
1390 frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1391 ~(TCG_TARGET_STACK_ALIGN - 1);
1392 stack_addend = frame_size - push_size;
1393 tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
1395 tcg_out_modrm(s, 0xff, EXT_JMPN_Ev, TCG_REG_EAX); /* jmp *%eax */
1398 tb_ret_addr = s->code_ptr;
1399 tcg_out_addi(s, TCG_REG_ESP, stack_addend);
1400 for(i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
1401 tcg_out_pop(s, tcg_target_callee_save_regs[i]);
1403 tcg_out8(s, 0xc3); /* ret */
1406 void tcg_target_init(TCGContext *s)
1408 #if !defined(CONFIG_USER_ONLY)
1410 if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
1414 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xff);
1416 tcg_regset_clear(tcg_target_call_clobber_regs);
1417 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EAX);
1418 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EDX);
1419 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_ECX);
1421 tcg_regset_clear(s->reserved_regs);
1422 tcg_regset_set_reg(s->reserved_regs, TCG_REG_ESP);
1424 tcg_add_target_add_op_defs(x86_op_defs);