|
|
1.1 root 1: /*
2: * Tiny Code Generator for QEMU
3: *
4: * Copyright (c) 2008 Fabrice Bellard
5: *
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:
12: *
13: * The above copyright notice and this permission notice shall be included in
14: * all copies or substantial portions of the Software.
15: *
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
22: * THE SOFTWARE.
23: */
24:
25: #ifndef NDEBUG
26: static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
1.1.1.4 root 27: #if TCG_TARGET_REG_BITS == 64
28: "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
29: "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
30: #else
31: "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
32: #endif
1.1 root 33: };
34: #endif
35:
36: static const int tcg_target_reg_alloc_order[] = {
1.1.1.4 root 37: #if TCG_TARGET_REG_BITS == 64
38: TCG_REG_RBP,
39: TCG_REG_RBX,
40: TCG_REG_R12,
41: TCG_REG_R13,
42: TCG_REG_R14,
43: TCG_REG_R15,
44: TCG_REG_R10,
45: TCG_REG_R11,
46: TCG_REG_R9,
47: TCG_REG_R8,
48: TCG_REG_RCX,
49: TCG_REG_RDX,
50: TCG_REG_RSI,
51: TCG_REG_RDI,
52: TCG_REG_RAX,
53: #else
1.1 root 54: TCG_REG_EBX,
55: TCG_REG_ESI,
56: TCG_REG_EDI,
57: TCG_REG_EBP,
1.1.1.4 root 58: TCG_REG_ECX,
59: TCG_REG_EDX,
60: TCG_REG_EAX,
61: #endif
1.1 root 62: };
63:
1.1.1.4 root 64: static const int tcg_target_call_iarg_regs[] = {
65: #if TCG_TARGET_REG_BITS == 64
66: TCG_REG_RDI,
67: TCG_REG_RSI,
68: TCG_REG_RDX,
69: TCG_REG_RCX,
70: TCG_REG_R8,
71: TCG_REG_R9,
72: #else
73: TCG_REG_EAX,
74: TCG_REG_EDX,
75: TCG_REG_ECX
76: #endif
77: };
78:
1.1.1.6 ! root 79: static const int tcg_target_call_oarg_regs[] = {
1.1.1.4 root 80: TCG_REG_EAX,
1.1.1.6 ! root 81: #if TCG_TARGET_REG_BITS == 32
1.1.1.4 root 82: TCG_REG_EDX
1.1.1.6 ! root 83: #endif
1.1.1.4 root 84: };
1.1 root 85:
86: static uint8_t *tb_ret_addr;
87:
1.1.1.4 root 88: static void patch_reloc(uint8_t *code_ptr, int type,
1.1 root 89: tcg_target_long value, tcg_target_long addend)
90: {
91: value += addend;
92: switch(type) {
1.1.1.4 root 93: case R_386_PC32:
94: value -= (uintptr_t)code_ptr;
95: if (value != (int32_t)value) {
96: tcg_abort();
97: }
1.1 root 98: *(uint32_t *)code_ptr = value;
99: break;
1.1.1.4 root 100: case R_386_PC8:
101: value -= (uintptr_t)code_ptr;
102: if (value != (int8_t)value) {
103: tcg_abort();
104: }
105: *(uint8_t *)code_ptr = value;
1.1 root 106: break;
107: default:
108: tcg_abort();
109: }
110: }
111:
112: /* maximum number of register used for input function arguments */
113: static inline int tcg_target_get_call_iarg_regs_count(int flags)
114: {
1.1.1.4 root 115: if (TCG_TARGET_REG_BITS == 64) {
116: return 6;
117: }
118:
1.1 root 119: flags &= TCG_CALL_TYPE_MASK;
120: switch(flags) {
121: case TCG_CALL_TYPE_STD:
122: return 0;
123: case TCG_CALL_TYPE_REGPARM_1:
124: case TCG_CALL_TYPE_REGPARM_2:
125: case TCG_CALL_TYPE_REGPARM:
126: return flags - TCG_CALL_TYPE_REGPARM_1 + 1;
127: default:
128: tcg_abort();
129: }
130: }
131:
132: /* parse target specific constraints */
133: static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
134: {
135: const char *ct_str;
136:
137: ct_str = *pct_str;
138: switch(ct_str[0]) {
139: case 'a':
140: ct->ct |= TCG_CT_REG;
141: tcg_regset_set_reg(ct->u.regs, TCG_REG_EAX);
142: break;
143: case 'b':
144: ct->ct |= TCG_CT_REG;
145: tcg_regset_set_reg(ct->u.regs, TCG_REG_EBX);
146: break;
147: case 'c':
148: ct->ct |= TCG_CT_REG;
149: tcg_regset_set_reg(ct->u.regs, TCG_REG_ECX);
150: break;
151: case 'd':
152: ct->ct |= TCG_CT_REG;
153: tcg_regset_set_reg(ct->u.regs, TCG_REG_EDX);
154: break;
155: case 'S':
156: ct->ct |= TCG_CT_REG;
157: tcg_regset_set_reg(ct->u.regs, TCG_REG_ESI);
158: break;
159: case 'D':
160: ct->ct |= TCG_CT_REG;
161: tcg_regset_set_reg(ct->u.regs, TCG_REG_EDI);
162: break;
163: case 'q':
164: ct->ct |= TCG_CT_REG;
1.1.1.4 root 165: if (TCG_TARGET_REG_BITS == 64) {
166: tcg_regset_set32(ct->u.regs, 0, 0xffff);
167: } else {
168: tcg_regset_set32(ct->u.regs, 0, 0xf);
169: }
1.1 root 170: break;
1.1.1.6 ! root 171: case 'Q':
! 172: ct->ct |= TCG_CT_REG;
! 173: tcg_regset_set32(ct->u.regs, 0, 0xf);
! 174: break;
1.1 root 175: case 'r':
176: ct->ct |= TCG_CT_REG;
1.1.1.4 root 177: if (TCG_TARGET_REG_BITS == 64) {
178: tcg_regset_set32(ct->u.regs, 0, 0xffff);
179: } else {
180: tcg_regset_set32(ct->u.regs, 0, 0xff);
181: }
1.1 root 182: break;
183:
184: /* qemu_ld/st address constraint */
185: case 'L':
186: ct->ct |= TCG_CT_REG;
1.1.1.4 root 187: if (TCG_TARGET_REG_BITS == 64) {
188: tcg_regset_set32(ct->u.regs, 0, 0xffff);
189: tcg_regset_reset_reg(ct->u.regs, TCG_REG_RSI);
190: tcg_regset_reset_reg(ct->u.regs, TCG_REG_RDI);
191: } else {
192: tcg_regset_set32(ct->u.regs, 0, 0xff);
193: tcg_regset_reset_reg(ct->u.regs, TCG_REG_EAX);
194: tcg_regset_reset_reg(ct->u.regs, TCG_REG_EDX);
195: }
196: break;
197:
198: case 'e':
199: ct->ct |= TCG_CT_CONST_S32;
200: break;
201: case 'Z':
202: ct->ct |= TCG_CT_CONST_U32;
1.1 root 203: break;
1.1.1.4 root 204:
1.1 root 205: default:
206: return -1;
207: }
208: ct_str++;
209: *pct_str = ct_str;
210: return 0;
211: }
212:
213: /* test if a constant matches the constraint */
214: static inline int tcg_target_const_match(tcg_target_long val,
215: const TCGArgConstraint *arg_ct)
216: {
1.1.1.4 root 217: int ct = arg_ct->ct;
218: if (ct & TCG_CT_CONST) {
1.1 root 219: return 1;
1.1.1.4 root 220: }
221: if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val) {
222: return 1;
223: }
224: if ((ct & TCG_CT_CONST_U32) && val == (uint32_t)val) {
225: return 1;
226: }
227: return 0;
1.1 root 228: }
229:
1.1.1.4 root 230: #if TCG_TARGET_REG_BITS == 64
231: # define LOWREGMASK(x) ((x) & 7)
232: #else
233: # define LOWREGMASK(x) (x)
234: #endif
235:
236: #define P_EXT 0x100 /* 0x0f opcode prefix */
237: #define P_DATA16 0x200 /* 0x66 opcode prefix */
238: #if TCG_TARGET_REG_BITS == 64
239: # define P_ADDR32 0x400 /* 0x67 opcode prefix */
240: # define P_REXW 0x800 /* Set REX.W = 1 */
241: # define P_REXB_R 0x1000 /* REG field as byte register */
242: # define P_REXB_RM 0x2000 /* R/M field as byte register */
243: #else
244: # define P_ADDR32 0
245: # define P_REXW 0
246: # define P_REXB_R 0
247: # define P_REXB_RM 0
248: #endif
249:
250: #define OPC_ARITH_EvIz (0x81)
251: #define OPC_ARITH_EvIb (0x83)
252: #define OPC_ARITH_GvEv (0x03) /* ... plus (ARITH_FOO << 3) */
253: #define OPC_ADD_GvEv (OPC_ARITH_GvEv | (ARITH_ADD << 3))
254: #define OPC_BSWAP (0xc8 | P_EXT)
255: #define OPC_CALL_Jz (0xe8)
256: #define OPC_CMP_GvEv (OPC_ARITH_GvEv | (ARITH_CMP << 3))
257: #define OPC_DEC_r32 (0x48)
258: #define OPC_IMUL_GvEv (0xaf | P_EXT)
259: #define OPC_IMUL_GvEvIb (0x6b)
260: #define OPC_IMUL_GvEvIz (0x69)
261: #define OPC_INC_r32 (0x40)
262: #define OPC_JCC_long (0x80 | P_EXT) /* ... plus condition code */
263: #define OPC_JCC_short (0x70) /* ... plus condition code */
264: #define OPC_JMP_long (0xe9)
265: #define OPC_JMP_short (0xeb)
266: #define OPC_LEA (0x8d)
267: #define OPC_MOVB_EvGv (0x88) /* stores, more or less */
268: #define OPC_MOVL_EvGv (0x89) /* stores, more or less */
269: #define OPC_MOVL_GvEv (0x8b) /* loads, more or less */
270: #define OPC_MOVL_EvIz (0xc7)
271: #define OPC_MOVL_Iv (0xb8)
272: #define OPC_MOVSBL (0xbe | P_EXT)
273: #define OPC_MOVSWL (0xbf | P_EXT)
274: #define OPC_MOVSLQ (0x63 | P_REXW)
275: #define OPC_MOVZBL (0xb6 | P_EXT)
276: #define OPC_MOVZWL (0xb7 | P_EXT)
277: #define OPC_POP_r32 (0x58)
278: #define OPC_PUSH_r32 (0x50)
279: #define OPC_PUSH_Iv (0x68)
280: #define OPC_PUSH_Ib (0x6a)
281: #define OPC_RET (0xc3)
282: #define OPC_SETCC (0x90 | P_EXT | P_REXB_RM) /* ... plus cc */
283: #define OPC_SHIFT_1 (0xd1)
284: #define OPC_SHIFT_Ib (0xc1)
285: #define OPC_SHIFT_cl (0xd3)
286: #define OPC_TESTL (0x85)
287: #define OPC_XCHG_ax_r32 (0x90)
288:
289: #define OPC_GRP3_Ev (0xf7)
290: #define OPC_GRP5 (0xff)
291:
292: /* Group 1 opcode extensions for 0x80-0x83.
293: These are also used as modifiers for OPC_ARITH. */
1.1 root 294: #define ARITH_ADD 0
295: #define ARITH_OR 1
296: #define ARITH_ADC 2
297: #define ARITH_SBB 3
298: #define ARITH_AND 4
299: #define ARITH_SUB 5
300: #define ARITH_XOR 6
301: #define ARITH_CMP 7
302:
1.1.1.4 root 303: /* Group 2 opcode extensions for 0xc0, 0xc1, 0xd0-0xd3. */
1.1.1.2 root 304: #define SHIFT_ROL 0
305: #define SHIFT_ROR 1
1.1 root 306: #define SHIFT_SHL 4
307: #define SHIFT_SHR 5
308: #define SHIFT_SAR 7
309:
1.1.1.4 root 310: /* Group 3 opcode extensions for 0xf6, 0xf7. To be used with OPC_GRP3. */
311: #define EXT3_NOT 2
312: #define EXT3_NEG 3
313: #define EXT3_MUL 4
314: #define EXT3_IMUL 5
315: #define EXT3_DIV 6
316: #define EXT3_IDIV 7
317:
318: /* Group 5 opcode extensions for 0xff. To be used with OPC_GRP5. */
319: #define EXT5_INC_Ev 0
320: #define EXT5_DEC_Ev 1
321: #define EXT5_CALLN_Ev 2
322: #define EXT5_JMPN_Ev 4
323:
324: /* Condition codes to be added to OPC_JCC_{long,short}. */
1.1 root 325: #define JCC_JMP (-1)
326: #define JCC_JO 0x0
327: #define JCC_JNO 0x1
328: #define JCC_JB 0x2
329: #define JCC_JAE 0x3
330: #define JCC_JE 0x4
331: #define JCC_JNE 0x5
332: #define JCC_JBE 0x6
333: #define JCC_JA 0x7
334: #define JCC_JS 0x8
335: #define JCC_JNS 0x9
336: #define JCC_JP 0xa
337: #define JCC_JNP 0xb
338: #define JCC_JL 0xc
339: #define JCC_JGE 0xd
340: #define JCC_JLE 0xe
341: #define JCC_JG 0xf
342:
343: static const uint8_t tcg_cond_to_jcc[10] = {
344: [TCG_COND_EQ] = JCC_JE,
345: [TCG_COND_NE] = JCC_JNE,
346: [TCG_COND_LT] = JCC_JL,
347: [TCG_COND_GE] = JCC_JGE,
348: [TCG_COND_LE] = JCC_JLE,
349: [TCG_COND_GT] = JCC_JG,
350: [TCG_COND_LTU] = JCC_JB,
351: [TCG_COND_GEU] = JCC_JAE,
352: [TCG_COND_LEU] = JCC_JBE,
353: [TCG_COND_GTU] = JCC_JA,
354: };
355:
1.1.1.4 root 356: #if TCG_TARGET_REG_BITS == 64
357: static void tcg_out_opc(TCGContext *s, int opc, int r, int rm, int x)
1.1 root 358: {
1.1.1.4 root 359: int rex;
360:
361: if (opc & P_DATA16) {
362: /* We should never be asking for both 16 and 64-bit operation. */
363: assert((opc & P_REXW) == 0);
364: tcg_out8(s, 0x66);
365: }
366: if (opc & P_ADDR32) {
367: tcg_out8(s, 0x67);
368: }
369:
370: rex = 0;
371: rex |= (opc & P_REXW) >> 8; /* REX.W */
372: rex |= (r & 8) >> 1; /* REX.R */
373: rex |= (x & 8) >> 2; /* REX.X */
374: rex |= (rm & 8) >> 3; /* REX.B */
375:
376: /* P_REXB_{R,RM} indicates that the given register is the low byte.
377: For %[abcd]l we need no REX prefix, but for %{si,di,bp,sp}l we do,
378: as otherwise the encoding indicates %[abcd]h. Note that the values
379: that are ORed in merely indicate that the REX byte must be present;
380: those bits get discarded in output. */
381: rex |= opc & (r >= 4 ? P_REXB_R : 0);
382: rex |= opc & (rm >= 4 ? P_REXB_RM : 0);
383:
384: if (rex) {
385: tcg_out8(s, (uint8_t)(rex | 0x40));
386: }
387:
388: if (opc & P_EXT) {
1.1 root 389: tcg_out8(s, 0x0f);
1.1.1.4 root 390: }
1.1 root 391: tcg_out8(s, opc);
392: }
1.1.1.4 root 393: #else
394: static void tcg_out_opc(TCGContext *s, int opc)
1.1 root 395: {
1.1.1.4 root 396: if (opc & P_DATA16) {
397: tcg_out8(s, 0x66);
398: }
399: if (opc & P_EXT) {
400: tcg_out8(s, 0x0f);
401: }
402: tcg_out8(s, opc);
1.1 root 403: }
1.1.1.4 root 404: /* Discard the register arguments to tcg_out_opc early, so as not to penalize
405: the 32-bit compilation paths. This method works with all versions of gcc,
406: whereas relying on optimization may not be able to exclude them. */
407: #define tcg_out_opc(s, opc, r, rm, x) (tcg_out_opc)(s, opc)
408: #endif
409:
410: static void tcg_out_modrm(TCGContext *s, int opc, int r, int rm)
411: {
412: tcg_out_opc(s, opc, r, rm, 0);
413: tcg_out8(s, 0xc0 | (LOWREGMASK(r) << 3) | LOWREGMASK(rm));
414: }
415:
416: /* Output an opcode with a full "rm + (index<<shift) + offset" address mode.
417: We handle either RM and INDEX missing with a negative value. In 64-bit
418: mode for absolute addresses, ~RM is the size of the immediate operand
419: that will follow the instruction. */
420:
421: static void tcg_out_modrm_sib_offset(TCGContext *s, int opc, int r, int rm,
422: int index, int shift,
423: tcg_target_long offset)
424: {
425: int mod, len;
426:
427: if (index < 0 && rm < 0) {
428: if (TCG_TARGET_REG_BITS == 64) {
429: /* Try for a rip-relative addressing mode. This has replaced
430: the 32-bit-mode absolute addressing encoding. */
431: tcg_target_long pc = (tcg_target_long)s->code_ptr + 5 + ~rm;
432: tcg_target_long disp = offset - pc;
433: if (disp == (int32_t)disp) {
434: tcg_out_opc(s, opc, r, 0, 0);
435: tcg_out8(s, (LOWREGMASK(r) << 3) | 5);
436: tcg_out32(s, disp);
437: return;
438: }
1.1 root 439:
1.1.1.4 root 440: /* Try for an absolute address encoding. This requires the
441: use of the MODRM+SIB encoding and is therefore larger than
442: rip-relative addressing. */
443: if (offset == (int32_t)offset) {
444: tcg_out_opc(s, opc, r, 0, 0);
445: tcg_out8(s, (LOWREGMASK(r) << 3) | 4);
446: tcg_out8(s, (4 << 3) | 5);
447: tcg_out32(s, offset);
448: return;
449: }
450:
451: /* ??? The memory isn't directly addressable. */
452: tcg_abort();
1.1 root 453: } else {
1.1.1.4 root 454: /* Absolute address. */
455: tcg_out_opc(s, opc, r, 0, 0);
456: tcg_out8(s, (r << 3) | 5);
457: tcg_out32(s, offset);
458: return;
1.1 root 459: }
1.1.1.4 root 460: }
461:
462: /* Find the length of the immediate addend. Note that the encoding
463: that would be used for (%ebp) indicates absolute addressing. */
464: if (rm < 0) {
465: mod = 0, len = 4, rm = 5;
466: } else if (offset == 0 && LOWREGMASK(rm) != TCG_REG_EBP) {
467: mod = 0, len = 0;
468: } else if (offset == (int8_t)offset) {
469: mod = 0x40, len = 1;
470: } else {
471: mod = 0x80, len = 4;
472: }
473:
474: /* Use a single byte MODRM format if possible. Note that the encoding
475: that would be used for %esp is the escape to the two byte form. */
476: if (index < 0 && LOWREGMASK(rm) != TCG_REG_ESP) {
477: /* Single byte MODRM format. */
478: tcg_out_opc(s, opc, r, rm, 0);
479: tcg_out8(s, mod | (LOWREGMASK(r) << 3) | LOWREGMASK(rm));
1.1 root 480: } else {
1.1.1.4 root 481: /* Two byte MODRM+SIB format. */
482:
483: /* Note that the encoding that would place %esp into the index
484: field indicates no index register. In 64-bit mode, the REX.X
485: bit counts, so %r12 can be used as the index. */
486: if (index < 0) {
487: index = 4;
1.1 root 488: } else {
1.1.1.4 root 489: assert(index != TCG_REG_ESP);
1.1 root 490: }
1.1.1.4 root 491:
492: tcg_out_opc(s, opc, r, rm, index);
493: tcg_out8(s, mod | (LOWREGMASK(r) << 3) | 4);
494: tcg_out8(s, (shift << 6) | (LOWREGMASK(index) << 3) | LOWREGMASK(rm));
495: }
496:
497: if (len == 1) {
498: tcg_out8(s, offset);
499: } else if (len == 4) {
1.1 root 500: tcg_out32(s, offset);
501: }
502: }
503:
1.1.1.4 root 504: /* A simplification of the above with no index or shift. */
505: static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r,
506: int rm, tcg_target_long offset)
507: {
508: tcg_out_modrm_sib_offset(s, opc, r, rm, -1, 0, offset);
509: }
510:
511: /* Generate dest op= src. Uses the same ARITH_* codes as tgen_arithi. */
512: static inline void tgen_arithr(TCGContext *s, int subop, int dest, int src)
1.1 root 513: {
1.1.1.4 root 514: /* Propagate an opcode prefix, such as P_REXW. */
515: int ext = subop & ~0x7;
516: subop &= 0x7;
517:
518: tcg_out_modrm(s, OPC_ARITH_GvEv + (subop << 3) + ext, dest, src);
1.1 root 519: }
520:
1.1.1.6 ! root 521: static inline void tcg_out_mov(TCGContext *s, TCGType type,
! 522: TCGReg ret, TCGReg arg)
1.1.1.4 root 523: {
524: if (arg != ret) {
525: int opc = OPC_MOVL_GvEv + (type == TCG_TYPE_I64 ? P_REXW : 0);
526: tcg_out_modrm(s, opc, ret, arg);
527: }
528: }
529:
530: static void tcg_out_movi(TCGContext *s, TCGType type,
1.1.1.6 ! root 531: TCGReg ret, tcg_target_long arg)
1.1 root 532: {
533: if (arg == 0) {
1.1.1.4 root 534: tgen_arithr(s, ARITH_XOR, ret, ret);
535: return;
536: } else if (arg == (uint32_t)arg || type == TCG_TYPE_I32) {
537: tcg_out_opc(s, OPC_MOVL_Iv + LOWREGMASK(ret), 0, ret, 0);
538: tcg_out32(s, arg);
539: } else if (arg == (int32_t)arg) {
540: tcg_out_modrm(s, OPC_MOVL_EvIz + P_REXW, 0, ret);
541: tcg_out32(s, arg);
1.1 root 542: } else {
1.1.1.4 root 543: tcg_out_opc(s, OPC_MOVL_Iv + P_REXW + LOWREGMASK(ret), 0, ret, 0);
1.1 root 544: tcg_out32(s, arg);
1.1.1.4 root 545: tcg_out32(s, arg >> 31 >> 1);
546: }
547: }
548:
549: static inline void tcg_out_pushi(TCGContext *s, tcg_target_long val)
550: {
551: if (val == (int8_t)val) {
552: tcg_out_opc(s, OPC_PUSH_Ib, 0, 0, 0);
553: tcg_out8(s, val);
554: } else if (val == (int32_t)val) {
555: tcg_out_opc(s, OPC_PUSH_Iv, 0, 0, 0);
556: tcg_out32(s, val);
557: } else {
558: tcg_abort();
1.1 root 559: }
560: }
561:
1.1.1.4 root 562: static inline void tcg_out_push(TCGContext *s, int reg)
563: {
564: tcg_out_opc(s, OPC_PUSH_r32 + LOWREGMASK(reg), 0, reg, 0);
565: }
566:
567: static inline void tcg_out_pop(TCGContext *s, int reg)
568: {
569: tcg_out_opc(s, OPC_POP_r32 + LOWREGMASK(reg), 0, reg, 0);
570: }
571:
1.1.1.6 ! root 572: static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
! 573: TCGReg arg1, tcg_target_long arg2)
1.1 root 574: {
1.1.1.4 root 575: int opc = OPC_MOVL_GvEv + (type == TCG_TYPE_I64 ? P_REXW : 0);
576: tcg_out_modrm_offset(s, opc, ret, arg1, arg2);
1.1 root 577: }
578:
1.1.1.6 ! root 579: static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
! 580: TCGReg arg1, tcg_target_long arg2)
1.1 root 581: {
1.1.1.4 root 582: int opc = OPC_MOVL_EvGv + (type == TCG_TYPE_I64 ? P_REXW : 0);
583: tcg_out_modrm_offset(s, opc, arg, arg1, arg2);
1.1 root 584: }
585:
1.1.1.4 root 586: static void tcg_out_shifti(TCGContext *s, int subopc, int reg, int count)
1.1 root 587: {
1.1.1.4 root 588: /* Propagate an opcode prefix, such as P_DATA16. */
589: int ext = subopc & ~0x7;
590: subopc &= 0x7;
591:
592: if (count == 1) {
593: tcg_out_modrm(s, OPC_SHIFT_1 + ext, subopc, reg);
1.1 root 594: } else {
1.1.1.4 root 595: tcg_out_modrm(s, OPC_SHIFT_Ib + ext, subopc, reg);
596: tcg_out8(s, count);
597: }
598: }
599:
600: static inline void tcg_out_bswap32(TCGContext *s, int reg)
601: {
602: tcg_out_opc(s, OPC_BSWAP + LOWREGMASK(reg), 0, reg, 0);
603: }
604:
605: static inline void tcg_out_rolw_8(TCGContext *s, int reg)
606: {
607: tcg_out_shifti(s, SHIFT_ROL + P_DATA16, reg, 8);
608: }
609:
610: static inline void tcg_out_ext8u(TCGContext *s, int dest, int src)
611: {
612: /* movzbl */
613: assert(src < 4 || TCG_TARGET_REG_BITS == 64);
614: tcg_out_modrm(s, OPC_MOVZBL + P_REXB_RM, dest, src);
615: }
616:
617: static void tcg_out_ext8s(TCGContext *s, int dest, int src, int rexw)
618: {
619: /* movsbl */
620: assert(src < 4 || TCG_TARGET_REG_BITS == 64);
621: tcg_out_modrm(s, OPC_MOVSBL + P_REXB_RM + rexw, dest, src);
622: }
623:
624: static inline void tcg_out_ext16u(TCGContext *s, int dest, int src)
625: {
626: /* movzwl */
627: tcg_out_modrm(s, OPC_MOVZWL, dest, src);
628: }
629:
630: static inline void tcg_out_ext16s(TCGContext *s, int dest, int src, int rexw)
631: {
632: /* movsw[lq] */
633: tcg_out_modrm(s, OPC_MOVSWL + rexw, dest, src);
634: }
635:
636: static inline void tcg_out_ext32u(TCGContext *s, int dest, int src)
637: {
638: /* 32-bit mov zero extends. */
639: tcg_out_modrm(s, OPC_MOVL_GvEv, dest, src);
640: }
641:
642: static inline void tcg_out_ext32s(TCGContext *s, int dest, int src)
643: {
644: tcg_out_modrm(s, OPC_MOVSLQ, dest, src);
645: }
646:
647: static inline void tcg_out_bswap64(TCGContext *s, int reg)
648: {
649: tcg_out_opc(s, OPC_BSWAP + P_REXW + LOWREGMASK(reg), 0, reg, 0);
650: }
651:
652: static void tgen_arithi(TCGContext *s, int c, int r0,
653: tcg_target_long val, int cf)
654: {
655: int rexw = 0;
656:
657: if (TCG_TARGET_REG_BITS == 64) {
658: rexw = c & -8;
659: c &= 7;
660: }
661:
662: /* ??? While INC is 2 bytes shorter than ADDL $1, they also induce
663: partial flags update stalls on Pentium4 and are not recommended
664: by current Intel optimization manuals. */
665: if (!cf && (c == ARITH_ADD || c == ARITH_SUB) && (val == 1 || val == -1)) {
666: int is_inc = (c == ARITH_ADD) ^ (val < 0);
667: if (TCG_TARGET_REG_BITS == 64) {
668: /* The single-byte increment encodings are re-tasked as the
669: REX prefixes. Use the MODRM encoding. */
670: tcg_out_modrm(s, OPC_GRP5 + rexw,
671: (is_inc ? EXT5_INC_Ev : EXT5_DEC_Ev), r0);
672: } else {
673: tcg_out8(s, (is_inc ? OPC_INC_r32 : OPC_DEC_r32) + r0);
674: }
675: return;
676: }
677:
678: if (c == ARITH_AND) {
679: if (TCG_TARGET_REG_BITS == 64) {
680: if (val == 0xffffffffu) {
681: tcg_out_ext32u(s, r0, r0);
682: return;
683: }
684: if (val == (uint32_t)val) {
685: /* AND with no high bits set can use a 32-bit operation. */
686: rexw = 0;
687: }
688: }
689: if (val == 0xffu && (r0 < 4 || TCG_TARGET_REG_BITS == 64)) {
690: tcg_out_ext8u(s, r0, r0);
691: return;
692: }
693: if (val == 0xffffu) {
694: tcg_out_ext16u(s, r0, r0);
695: return;
696: }
697: }
698:
699: if (val == (int8_t)val) {
700: tcg_out_modrm(s, OPC_ARITH_EvIb + rexw, c, r0);
701: tcg_out8(s, val);
702: return;
703: }
704: if (rexw == 0 || val == (int32_t)val) {
705: tcg_out_modrm(s, OPC_ARITH_EvIz + rexw, c, r0);
1.1 root 706: tcg_out32(s, val);
1.1.1.4 root 707: return;
1.1 root 708: }
1.1.1.4 root 709:
710: tcg_abort();
1.1 root 711: }
712:
713: static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
714: {
1.1.1.4 root 715: if (val != 0) {
716: tgen_arithi(s, ARITH_ADD + P_REXW, reg, val, 0);
717: }
1.1 root 718: }
719:
1.1.1.4 root 720: /* Use SMALL != 0 to force a short forward branch. */
721: static void tcg_out_jxx(TCGContext *s, int opc, int label_index, int small)
1.1 root 722: {
723: int32_t val, val1;
724: TCGLabel *l = &s->labels[label_index];
1.1.1.4 root 725:
1.1 root 726: if (l->has_value) {
727: val = l->u.value - (tcg_target_long)s->code_ptr;
728: val1 = val - 2;
729: if ((int8_t)val1 == val1) {
1.1.1.4 root 730: if (opc == -1) {
731: tcg_out8(s, OPC_JMP_short);
732: } else {
733: tcg_out8(s, OPC_JCC_short + opc);
734: }
1.1 root 735: tcg_out8(s, val1);
736: } else {
1.1.1.4 root 737: if (small) {
738: tcg_abort();
739: }
1.1 root 740: if (opc == -1) {
1.1.1.4 root 741: tcg_out8(s, OPC_JMP_long);
1.1 root 742: tcg_out32(s, val - 5);
743: } else {
1.1.1.4 root 744: tcg_out_opc(s, OPC_JCC_long + opc, 0, 0, 0);
1.1 root 745: tcg_out32(s, val - 6);
746: }
747: }
1.1.1.4 root 748: } else if (small) {
749: if (opc == -1) {
750: tcg_out8(s, OPC_JMP_short);
751: } else {
752: tcg_out8(s, OPC_JCC_short + opc);
753: }
754: tcg_out_reloc(s, s->code_ptr, R_386_PC8, label_index, -1);
755: s->code_ptr += 1;
1.1 root 756: } else {
757: if (opc == -1) {
1.1.1.4 root 758: tcg_out8(s, OPC_JMP_long);
1.1 root 759: } else {
1.1.1.4 root 760: tcg_out_opc(s, OPC_JCC_long + opc, 0, 0, 0);
1.1 root 761: }
762: tcg_out_reloc(s, s->code_ptr, R_386_PC32, label_index, -4);
763: s->code_ptr += 4;
764: }
765: }
766:
1.1.1.4 root 767: static void tcg_out_cmp(TCGContext *s, TCGArg arg1, TCGArg arg2,
768: int const_arg2, int rexw)
1.1 root 769: {
770: if (const_arg2) {
771: if (arg2 == 0) {
772: /* test r, r */
1.1.1.4 root 773: tcg_out_modrm(s, OPC_TESTL + rexw, arg1, arg1);
1.1 root 774: } else {
1.1.1.4 root 775: tgen_arithi(s, ARITH_CMP + rexw, arg1, arg2, 0);
1.1 root 776: }
777: } else {
1.1.1.4 root 778: tgen_arithr(s, ARITH_CMP + rexw, arg1, arg2);
1.1 root 779: }
780: }
781:
1.1.1.4 root 782: static void tcg_out_brcond32(TCGContext *s, TCGCond cond,
783: TCGArg arg1, TCGArg arg2, int const_arg2,
784: int label_index, int small)
785: {
786: tcg_out_cmp(s, arg1, arg2, const_arg2, 0);
787: tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index, small);
788: }
789:
790: #if TCG_TARGET_REG_BITS == 64
791: static void tcg_out_brcond64(TCGContext *s, TCGCond cond,
792: TCGArg arg1, TCGArg arg2, int const_arg2,
793: int label_index, int small)
794: {
795: tcg_out_cmp(s, arg1, arg2, const_arg2, P_REXW);
796: tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index, small);
797: }
798: #else
1.1 root 799: /* XXX: we implement it at the target level to avoid having to
800: handle cross basic blocks temporaries */
1.1.1.4 root 801: static void tcg_out_brcond2(TCGContext *s, const TCGArg *args,
802: const int *const_args, int small)
1.1 root 803: {
804: int label_next;
805: label_next = gen_new_label();
806: switch(args[4]) {
807: case TCG_COND_EQ:
1.1.1.4 root 808: tcg_out_brcond32(s, TCG_COND_NE, args[0], args[2], const_args[2],
809: label_next, 1);
810: tcg_out_brcond32(s, TCG_COND_EQ, args[1], args[3], const_args[3],
811: args[5], small);
1.1 root 812: break;
813: case TCG_COND_NE:
1.1.1.4 root 814: tcg_out_brcond32(s, TCG_COND_NE, args[0], args[2], const_args[2],
815: args[5], small);
816: tcg_out_brcond32(s, TCG_COND_NE, args[1], args[3], const_args[3],
817: args[5], small);
1.1 root 818: break;
819: case TCG_COND_LT:
1.1.1.4 root 820: tcg_out_brcond32(s, TCG_COND_LT, args[1], args[3], const_args[3],
821: args[5], small);
822: tcg_out_jxx(s, JCC_JNE, label_next, 1);
823: tcg_out_brcond32(s, TCG_COND_LTU, args[0], args[2], const_args[2],
824: args[5], small);
1.1 root 825: break;
826: case TCG_COND_LE:
1.1.1.4 root 827: tcg_out_brcond32(s, TCG_COND_LT, args[1], args[3], const_args[3],
828: args[5], small);
829: tcg_out_jxx(s, JCC_JNE, label_next, 1);
830: tcg_out_brcond32(s, TCG_COND_LEU, args[0], args[2], const_args[2],
831: args[5], small);
1.1 root 832: break;
833: case TCG_COND_GT:
1.1.1.4 root 834: tcg_out_brcond32(s, TCG_COND_GT, args[1], args[3], const_args[3],
835: args[5], small);
836: tcg_out_jxx(s, JCC_JNE, label_next, 1);
837: tcg_out_brcond32(s, TCG_COND_GTU, args[0], args[2], const_args[2],
838: args[5], small);
1.1 root 839: break;
840: case TCG_COND_GE:
1.1.1.4 root 841: tcg_out_brcond32(s, TCG_COND_GT, args[1], args[3], const_args[3],
842: args[5], small);
843: tcg_out_jxx(s, JCC_JNE, label_next, 1);
844: tcg_out_brcond32(s, TCG_COND_GEU, args[0], args[2], const_args[2],
845: args[5], small);
1.1 root 846: break;
847: case TCG_COND_LTU:
1.1.1.4 root 848: tcg_out_brcond32(s, TCG_COND_LTU, args[1], args[3], const_args[3],
849: args[5], small);
850: tcg_out_jxx(s, JCC_JNE, label_next, 1);
851: tcg_out_brcond32(s, TCG_COND_LTU, args[0], args[2], const_args[2],
852: args[5], small);
1.1 root 853: break;
854: case TCG_COND_LEU:
1.1.1.4 root 855: tcg_out_brcond32(s, TCG_COND_LTU, args[1], args[3], const_args[3],
856: args[5], small);
857: tcg_out_jxx(s, JCC_JNE, label_next, 1);
858: tcg_out_brcond32(s, TCG_COND_LEU, args[0], args[2], const_args[2],
859: args[5], small);
1.1 root 860: break;
861: case TCG_COND_GTU:
1.1.1.4 root 862: tcg_out_brcond32(s, TCG_COND_GTU, args[1], args[3], const_args[3],
863: args[5], small);
864: tcg_out_jxx(s, JCC_JNE, label_next, 1);
865: tcg_out_brcond32(s, TCG_COND_GTU, args[0], args[2], const_args[2],
866: args[5], small);
1.1 root 867: break;
868: case TCG_COND_GEU:
1.1.1.4 root 869: tcg_out_brcond32(s, TCG_COND_GTU, args[1], args[3], const_args[3],
870: args[5], small);
871: tcg_out_jxx(s, JCC_JNE, label_next, 1);
872: tcg_out_brcond32(s, TCG_COND_GEU, args[0], args[2], const_args[2],
873: args[5], small);
1.1 root 874: break;
875: default:
876: tcg_abort();
877: }
878: tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);
879: }
1.1.1.4 root 880: #endif
881:
882: static void tcg_out_setcond32(TCGContext *s, TCGCond cond, TCGArg dest,
883: TCGArg arg1, TCGArg arg2, int const_arg2)
884: {
885: tcg_out_cmp(s, arg1, arg2, const_arg2, 0);
886: tcg_out_modrm(s, OPC_SETCC | tcg_cond_to_jcc[cond], 0, dest);
887: tcg_out_ext8u(s, dest, dest);
888: }
889:
890: #if TCG_TARGET_REG_BITS == 64
891: static void tcg_out_setcond64(TCGContext *s, TCGCond cond, TCGArg dest,
892: TCGArg arg1, TCGArg arg2, int const_arg2)
893: {
894: tcg_out_cmp(s, arg1, arg2, const_arg2, P_REXW);
895: tcg_out_modrm(s, OPC_SETCC | tcg_cond_to_jcc[cond], 0, dest);
896: tcg_out_ext8u(s, dest, dest);
897: }
898: #else
899: static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
900: const int *const_args)
901: {
902: TCGArg new_args[6];
903: int label_true, label_over;
904:
905: memcpy(new_args, args+1, 5*sizeof(TCGArg));
906:
907: if (args[0] == args[1] || args[0] == args[2]
908: || (!const_args[3] && args[0] == args[3])
909: || (!const_args[4] && args[0] == args[4])) {
910: /* When the destination overlaps with one of the argument
911: registers, don't do anything tricky. */
912: label_true = gen_new_label();
913: label_over = gen_new_label();
914:
915: new_args[5] = label_true;
916: tcg_out_brcond2(s, new_args, const_args+1, 1);
917:
918: tcg_out_movi(s, TCG_TYPE_I32, args[0], 0);
919: tcg_out_jxx(s, JCC_JMP, label_over, 1);
920: tcg_out_label(s, label_true, (tcg_target_long)s->code_ptr);
921:
922: tcg_out_movi(s, TCG_TYPE_I32, args[0], 1);
923: tcg_out_label(s, label_over, (tcg_target_long)s->code_ptr);
924: } else {
925: /* When the destination does not overlap one of the arguments,
926: clear the destination first, jump if cond false, and emit an
927: increment in the true case. This results in smaller code. */
928:
929: tcg_out_movi(s, TCG_TYPE_I32, args[0], 0);
930:
931: label_over = gen_new_label();
932: new_args[4] = tcg_invert_cond(new_args[4]);
933: new_args[5] = label_over;
934: tcg_out_brcond2(s, new_args, const_args+1, 1);
935:
936: tgen_arithi(s, ARITH_ADD, args[0], 1, 0);
937: tcg_out_label(s, label_over, (tcg_target_long)s->code_ptr);
938: }
939: }
940: #endif
941:
942: static void tcg_out_branch(TCGContext *s, int call, tcg_target_long dest)
943: {
944: tcg_target_long disp = dest - (tcg_target_long)s->code_ptr - 5;
945:
946: if (disp == (int32_t)disp) {
947: tcg_out_opc(s, call ? OPC_CALL_Jz : OPC_JMP_long, 0, 0, 0);
948: tcg_out32(s, disp);
949: } else {
950: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R10, dest);
951: tcg_out_modrm(s, OPC_GRP5,
952: call ? EXT5_CALLN_Ev : EXT5_JMPN_Ev, TCG_REG_R10);
953: }
954: }
955:
956: static inline void tcg_out_calli(TCGContext *s, tcg_target_long dest)
957: {
958: tcg_out_branch(s, 1, dest);
959: }
960:
961: static void tcg_out_jmp(TCGContext *s, tcg_target_long dest)
962: {
963: tcg_out_branch(s, 0, dest);
964: }
1.1 root 965:
966: #if defined(CONFIG_SOFTMMU)
967:
968: #include "../../softmmu_defs.h"
969:
970: static void *qemu_ld_helpers[4] = {
971: __ldb_mmu,
972: __ldw_mmu,
973: __ldl_mmu,
974: __ldq_mmu,
975: };
976:
977: static void *qemu_st_helpers[4] = {
978: __stb_mmu,
979: __stw_mmu,
980: __stl_mmu,
981: __stq_mmu,
982: };
1.1.1.4 root 983:
984: /* Perform the TLB load and compare.
985:
986: Inputs:
987: ADDRLO_IDX contains the index into ARGS of the low part of the
988: address; the high part of the address is at ADDR_LOW_IDX+1.
989:
990: MEM_INDEX and S_BITS are the memory context and log2 size of the load.
991:
992: WHICH is the offset into the CPUTLBEntry structure of the slot to read.
993: This should be offsetof addr_read or addr_write.
994:
995: Outputs:
996: LABEL_PTRS is filled with 1 (32-bit addresses) or 2 (64-bit addresses)
997: positions of the displacements of forward jumps to the TLB miss case.
998:
999: First argument register is loaded with the low part of the address.
1000: In the TLB hit case, it has been adjusted as indicated by the TLB
1001: and so is a host address. In the TLB miss case, it continues to
1002: hold a guest address.
1003:
1004: Second argument register is clobbered. */
1005:
1006: static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx,
1007: int mem_index, int s_bits,
1008: const TCGArg *args,
1009: uint8_t **label_ptr, int which)
1010: {
1011: const int addrlo = args[addrlo_idx];
1012: const int r0 = tcg_target_call_iarg_regs[0];
1013: const int r1 = tcg_target_call_iarg_regs[1];
1014: TCGType type = TCG_TYPE_I32;
1015: int rexw = 0;
1016:
1017: if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 64) {
1018: type = TCG_TYPE_I64;
1019: rexw = P_REXW;
1020: }
1021:
1022: tcg_out_mov(s, type, r1, addrlo);
1023: tcg_out_mov(s, type, r0, addrlo);
1024:
1025: tcg_out_shifti(s, SHIFT_SHR + rexw, r1,
1026: TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
1027:
1028: tgen_arithi(s, ARITH_AND + rexw, r0,
1029: TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
1030: tgen_arithi(s, ARITH_AND + rexw, r1,
1031: (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
1032:
1033: tcg_out_modrm_sib_offset(s, OPC_LEA + P_REXW, r1, TCG_AREG0, r1, 0,
1034: offsetof(CPUState, tlb_table[mem_index][0])
1035: + which);
1036:
1037: /* cmp 0(r1), r0 */
1038: tcg_out_modrm_offset(s, OPC_CMP_GvEv + rexw, r0, r1, 0);
1039:
1040: tcg_out_mov(s, type, r0, addrlo);
1041:
1042: /* jne label1 */
1043: tcg_out8(s, OPC_JCC_short + JCC_JNE);
1044: label_ptr[0] = s->code_ptr;
1045: s->code_ptr++;
1046:
1047: if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
1048: /* cmp 4(r1), addrhi */
1049: tcg_out_modrm_offset(s, OPC_CMP_GvEv, args[addrlo_idx+1], r1, 4);
1050:
1051: /* jne label1 */
1052: tcg_out8(s, OPC_JCC_short + JCC_JNE);
1053: label_ptr[1] = s->code_ptr;
1054: s->code_ptr++;
1055: }
1056:
1057: /* TLB Hit. */
1058:
1059: /* add addend(r1), r0 */
1060: tcg_out_modrm_offset(s, OPC_ADD_GvEv + P_REXW, r0, r1,
1061: offsetof(CPUTLBEntry, addend) - which);
1062: }
1.1 root 1063: #endif
1064:
1.1.1.4 root 1065: static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi,
1066: int base, tcg_target_long ofs, int sizeop)
1067: {
1068: #ifdef TARGET_WORDS_BIGENDIAN
1069: const int bswap = 1;
1070: #else
1071: const int bswap = 0;
1.1.1.3 root 1072: #endif
1.1.1.4 root 1073: switch (sizeop) {
1074: case 0:
1075: tcg_out_modrm_offset(s, OPC_MOVZBL, datalo, base, ofs);
1076: break;
1077: case 0 | 4:
1078: tcg_out_modrm_offset(s, OPC_MOVSBL + P_REXW, datalo, base, ofs);
1079: break;
1080: case 1:
1081: tcg_out_modrm_offset(s, OPC_MOVZWL, datalo, base, ofs);
1082: if (bswap) {
1083: tcg_out_rolw_8(s, datalo);
1084: }
1085: break;
1086: case 1 | 4:
1087: if (bswap) {
1088: tcg_out_modrm_offset(s, OPC_MOVZWL, datalo, base, ofs);
1089: tcg_out_rolw_8(s, datalo);
1090: tcg_out_modrm(s, OPC_MOVSWL + P_REXW, datalo, datalo);
1091: } else {
1092: tcg_out_modrm_offset(s, OPC_MOVSWL + P_REXW, datalo, base, ofs);
1093: }
1094: break;
1095: case 2:
1096: tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
1097: if (bswap) {
1098: tcg_out_bswap32(s, datalo);
1099: }
1100: break;
1101: #if TCG_TARGET_REG_BITS == 64
1102: case 2 | 4:
1103: if (bswap) {
1104: tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
1105: tcg_out_bswap32(s, datalo);
1106: tcg_out_ext32s(s, datalo, datalo);
1107: } else {
1108: tcg_out_modrm_offset(s, OPC_MOVSLQ, datalo, base, ofs);
1109: }
1110: break;
1111: #endif
1112: case 3:
1113: if (TCG_TARGET_REG_BITS == 64) {
1114: tcg_out_ld(s, TCG_TYPE_I64, datalo, base, ofs);
1115: if (bswap) {
1116: tcg_out_bswap64(s, datalo);
1117: }
1118: } else {
1119: if (bswap) {
1120: int t = datalo;
1121: datalo = datahi;
1122: datahi = t;
1123: }
1124: if (base != datalo) {
1125: tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
1126: tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4);
1127: } else {
1128: tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4);
1129: tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
1130: }
1131: if (bswap) {
1132: tcg_out_bswap32(s, datalo);
1133: tcg_out_bswap32(s, datahi);
1134: }
1135: }
1136: break;
1137: default:
1138: tcg_abort();
1139: }
1140: }
1.1.1.3 root 1141:
1.1 root 1142: /* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and
1143: EAX. It will be useful once fixed registers globals are less
1144: common. */
1145: static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
1146: int opc)
1147: {
1.1.1.4 root 1148: int data_reg, data_reg2 = 0;
1149: int addrlo_idx;
1.1 root 1150: #if defined(CONFIG_SOFTMMU)
1.1.1.4 root 1151: int mem_index, s_bits, arg_idx;
1152: uint8_t *label_ptr[3];
1.1 root 1153: #endif
1154:
1.1.1.4 root 1155: data_reg = args[0];
1156: addrlo_idx = 1;
1157: if (TCG_TARGET_REG_BITS == 32 && opc == 3) {
1158: data_reg2 = args[1];
1159: addrlo_idx = 2;
1160: }
1.1 root 1161:
1162: #if defined(CONFIG_SOFTMMU)
1.1.1.4 root 1163: mem_index = args[addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS)];
1164: s_bits = opc & 3;
1.1 root 1165:
1.1.1.4 root 1166: tcg_out_tlb_load(s, addrlo_idx, mem_index, s_bits, args,
1167: label_ptr, offsetof(CPUTLBEntry, addr_read));
1.1 root 1168:
1.1.1.4 root 1169: /* TLB Hit. */
1170: tcg_out_qemu_ld_direct(s, data_reg, data_reg2,
1171: tcg_target_call_iarg_regs[0], 0, opc);
1172:
1173: /* jmp label2 */
1174: tcg_out8(s, OPC_JMP_short);
1175: label_ptr[2] = s->code_ptr;
1.1 root 1176: s->code_ptr++;
1.1.1.4 root 1177:
1178: /* TLB Miss. */
1179:
1180: /* label1: */
1181: *label_ptr[0] = s->code_ptr - label_ptr[0] - 1;
1182: if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
1183: *label_ptr[1] = s->code_ptr - label_ptr[1] - 1;
1184: }
1.1 root 1185:
1186: /* XXX: move that code at the end of the TB */
1.1.1.4 root 1187: /* The first argument is already loaded with addrlo. */
1188: arg_idx = 1;
1189: if (TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 64) {
1190: tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx++],
1191: args[addrlo_idx + 1]);
1192: }
1193: tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx],
1194: mem_index);
1195: tcg_out_calli(s, (tcg_target_long)qemu_ld_helpers[s_bits]);
1.1 root 1196:
1197: switch(opc) {
1198: case 0 | 4:
1.1.1.4 root 1199: tcg_out_ext8s(s, data_reg, TCG_REG_EAX, P_REXW);
1.1 root 1200: break;
1201: case 1 | 4:
1.1.1.4 root 1202: tcg_out_ext16s(s, data_reg, TCG_REG_EAX, P_REXW);
1.1 root 1203: break;
1204: case 0:
1.1.1.4 root 1205: tcg_out_ext8u(s, data_reg, TCG_REG_EAX);
1.1 root 1206: break;
1207: case 1:
1.1.1.4 root 1208: tcg_out_ext16u(s, data_reg, TCG_REG_EAX);
1.1 root 1209: break;
1210: case 2:
1.1.1.4 root 1211: tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
1212: break;
1213: #if TCG_TARGET_REG_BITS == 64
1214: case 2 | 4:
1215: tcg_out_ext32s(s, data_reg, TCG_REG_EAX);
1.1 root 1216: break;
1.1.1.4 root 1217: #endif
1.1 root 1218: case 3:
1.1.1.4 root 1219: if (TCG_TARGET_REG_BITS == 64) {
1220: tcg_out_mov(s, TCG_TYPE_I64, data_reg, TCG_REG_RAX);
1221: } else if (data_reg == TCG_REG_EDX) {
1222: /* xchg %edx, %eax */
1223: tcg_out_opc(s, OPC_XCHG_ax_r32 + TCG_REG_EDX, 0, 0, 0);
1224: tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_EAX);
1.1 root 1225: } else {
1.1.1.4 root 1226: tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
1227: tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_EDX);
1.1 root 1228: }
1229: break;
1.1.1.4 root 1230: default:
1231: tcg_abort();
1.1 root 1232: }
1233:
1.1.1.4 root 1234: /* label2: */
1235: *label_ptr[2] = s->code_ptr - label_ptr[2] - 1;
1.1 root 1236: #else
1.1.1.4 root 1237: {
1238: int32_t offset = GUEST_BASE;
1239: int base = args[addrlo_idx];
1240:
1241: if (TCG_TARGET_REG_BITS == 64) {
1242: /* ??? We assume all operations have left us with register
1243: contents that are zero extended. So far this appears to
1244: be true. If we want to enforce this, we can either do
1245: an explicit zero-extension here, or (if GUEST_BASE == 0)
1246: use the ADDR32 prefix. For now, do nothing. */
1247:
1248: if (offset != GUEST_BASE) {
1249: tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_RDI, GUEST_BASE);
1250: tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_RDI, base);
1251: base = TCG_REG_RDI, offset = 0;
1252: }
1253: }
1254:
1255: tcg_out_qemu_ld_direct(s, data_reg, data_reg2, base, offset, opc);
1256: }
1.1 root 1257: #endif
1.1.1.4 root 1258: }
1.1 root 1259:
1.1.1.4 root 1260: static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
1261: int base, tcg_target_long ofs, int sizeop)
1262: {
1.1 root 1263: #ifdef TARGET_WORDS_BIGENDIAN
1.1.1.4 root 1264: const int bswap = 1;
1.1 root 1265: #else
1.1.1.4 root 1266: const int bswap = 0;
1.1 root 1267: #endif
1.1.1.4 root 1268: /* ??? Ideally we wouldn't need a scratch register. For user-only,
1269: we could perform the bswap twice to restore the original value
1270: instead of moving to the scratch. But as it is, the L constraint
1271: means that the second argument reg is definitely free here. */
1272: int scratch = tcg_target_call_iarg_regs[1];
1273:
1274: switch (sizeop) {
1.1 root 1275: case 0:
1.1.1.4 root 1276: tcg_out_modrm_offset(s, OPC_MOVB_EvGv + P_REXB_R, datalo, base, ofs);
1.1 root 1277: break;
1278: case 1:
1279: if (bswap) {
1.1.1.4 root 1280: tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
1281: tcg_out_rolw_8(s, scratch);
1282: datalo = scratch;
1.1 root 1283: }
1.1.1.4 root 1284: tcg_out_modrm_offset(s, OPC_MOVL_EvGv + P_DATA16, datalo, base, ofs);
1.1 root 1285: break;
1286: case 2:
1287: if (bswap) {
1.1.1.4 root 1288: tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
1289: tcg_out_bswap32(s, scratch);
1290: datalo = scratch;
1.1 root 1291: }
1.1.1.4 root 1292: tcg_out_st(s, TCG_TYPE_I32, datalo, base, ofs);
1.1 root 1293: break;
1294: case 3:
1.1.1.4 root 1295: if (TCG_TARGET_REG_BITS == 64) {
1296: if (bswap) {
1297: tcg_out_mov(s, TCG_TYPE_I64, scratch, datalo);
1298: tcg_out_bswap64(s, scratch);
1299: datalo = scratch;
1300: }
1301: tcg_out_st(s, TCG_TYPE_I64, datalo, base, ofs);
1302: } else if (bswap) {
1303: tcg_out_mov(s, TCG_TYPE_I32, scratch, datahi);
1304: tcg_out_bswap32(s, scratch);
1305: tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs);
1306: tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
1307: tcg_out_bswap32(s, scratch);
1308: tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs + 4);
1309: } else {
1310: tcg_out_st(s, TCG_TYPE_I32, datalo, base, ofs);
1311: tcg_out_st(s, TCG_TYPE_I32, datahi, base, ofs + 4);
1.1 root 1312: }
1313: break;
1314: default:
1315: tcg_abort();
1316: }
1317: }
1318:
1319: static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
1320: int opc)
1321: {
1.1.1.4 root 1322: int data_reg, data_reg2 = 0;
1323: int addrlo_idx;
1.1 root 1324: #if defined(CONFIG_SOFTMMU)
1.1.1.4 root 1325: int mem_index, s_bits;
1326: int stack_adjust;
1327: uint8_t *label_ptr[3];
1.1 root 1328: #endif
1329:
1.1.1.4 root 1330: data_reg = args[0];
1331: addrlo_idx = 1;
1332: if (TCG_TARGET_REG_BITS == 32 && opc == 3) {
1333: data_reg2 = args[1];
1334: addrlo_idx = 2;
1335: }
1.1 root 1336:
1.1.1.4 root 1337: #if defined(CONFIG_SOFTMMU)
1338: mem_index = args[addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS)];
1.1 root 1339: s_bits = opc;
1340:
1.1.1.4 root 1341: tcg_out_tlb_load(s, addrlo_idx, mem_index, s_bits, args,
1342: label_ptr, offsetof(CPUTLBEntry, addr_write));
1.1 root 1343:
1.1.1.4 root 1344: /* TLB Hit. */
1345: tcg_out_qemu_st_direct(s, data_reg, data_reg2,
1346: tcg_target_call_iarg_regs[0], 0, opc);
1.1 root 1347:
1.1.1.4 root 1348: /* jmp label2 */
1349: tcg_out8(s, OPC_JMP_short);
1350: label_ptr[2] = s->code_ptr;
1.1 root 1351: s->code_ptr++;
1.1.1.4 root 1352:
1353: /* TLB Miss. */
1354:
1355: /* label1: */
1356: *label_ptr[0] = s->code_ptr - label_ptr[0] - 1;
1357: if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
1358: *label_ptr[1] = s->code_ptr - label_ptr[1] - 1;
1359: }
1.1 root 1360:
1361: /* XXX: move that code at the end of the TB */
1.1.1.4 root 1362: if (TCG_TARGET_REG_BITS == 64) {
1363: tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32),
1364: TCG_REG_RSI, data_reg);
1365: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, mem_index);
1366: stack_adjust = 0;
1367: } else if (TARGET_LONG_BITS == 32) {
1368: tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, data_reg);
1369: if (opc == 3) {
1370: tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_ECX, data_reg2);
1371: tcg_out_pushi(s, mem_index);
1372: stack_adjust = 4;
1373: } else {
1374: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
1375: stack_adjust = 0;
1.1 root 1376: }
1377: } else {
1.1.1.4 root 1378: if (opc == 3) {
1379: tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, args[addrlo_idx + 1]);
1380: tcg_out_pushi(s, mem_index);
1381: tcg_out_push(s, data_reg2);
1382: tcg_out_push(s, data_reg);
1383: stack_adjust = 12;
1384: } else {
1385: tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, args[addrlo_idx + 1]);
1386: switch(opc) {
1387: case 0:
1388: tcg_out_ext8u(s, TCG_REG_ECX, data_reg);
1389: break;
1390: case 1:
1391: tcg_out_ext16u(s, TCG_REG_ECX, data_reg);
1392: break;
1393: case 2:
1394: tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_ECX, data_reg);
1395: break;
1396: }
1397: tcg_out_pushi(s, mem_index);
1398: stack_adjust = 4;
1.1 root 1399: }
1400: }
1401:
1.1.1.4 root 1402: tcg_out_calli(s, (tcg_target_long)qemu_st_helpers[s_bits]);
1.1 root 1403:
1.1.1.4 root 1404: if (stack_adjust == (TCG_TARGET_REG_BITS / 8)) {
1405: /* Pop and discard. This is 2 bytes smaller than the add. */
1406: tcg_out_pop(s, TCG_REG_ECX);
1407: } else if (stack_adjust != 0) {
1.1.1.5 root 1408: tcg_out_addi(s, TCG_REG_CALL_STACK, stack_adjust);
1.1 root 1409: }
1410:
1411: /* label2: */
1.1.1.4 root 1412: *label_ptr[2] = s->code_ptr - label_ptr[2] - 1;
1413: #else
1414: {
1415: int32_t offset = GUEST_BASE;
1416: int base = args[addrlo_idx];
1417:
1418: if (TCG_TARGET_REG_BITS == 64) {
1419: /* ??? We assume all operations have left us with register
1420: contents that are zero extended. So far this appears to
1421: be true. If we want to enforce this, we can either do
1422: an explicit zero-extension here, or (if GUEST_BASE == 0)
1423: use the ADDR32 prefix. For now, do nothing. */
1424:
1425: if (offset != GUEST_BASE) {
1426: tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_RDI, GUEST_BASE);
1427: tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_RDI, base);
1428: base = TCG_REG_RDI, offset = 0;
1429: }
1430: }
1431:
1432: tcg_out_qemu_st_direct(s, data_reg, data_reg2, base, offset, opc);
1433: }
1.1 root 1434: #endif
1435: }
1436:
1.1.1.4 root 1437: static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1.1 root 1438: const TCGArg *args, const int *const_args)
1439: {
1.1.1.4 root 1440: int c, rexw = 0;
1441:
1442: #if TCG_TARGET_REG_BITS == 64
1443: # define OP_32_64(x) \
1444: case glue(glue(INDEX_op_, x), _i64): \
1445: rexw = P_REXW; /* FALLTHRU */ \
1446: case glue(glue(INDEX_op_, x), _i32)
1447: #else
1448: # define OP_32_64(x) \
1449: case glue(glue(INDEX_op_, x), _i32)
1450: #endif
1451:
1.1 root 1452: switch(opc) {
1453: case INDEX_op_exit_tb:
1.1.1.4 root 1454: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_EAX, args[0]);
1455: tcg_out_jmp(s, (tcg_target_long) tb_ret_addr);
1.1 root 1456: break;
1457: case INDEX_op_goto_tb:
1458: if (s->tb_jmp_offset) {
1459: /* direct jump method */
1.1.1.4 root 1460: tcg_out8(s, OPC_JMP_long); /* jmp im */
1.1 root 1461: s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1462: tcg_out32(s, 0);
1463: } else {
1464: /* indirect jump method */
1.1.1.4 root 1465: tcg_out_modrm_offset(s, OPC_GRP5, EXT5_JMPN_Ev, -1,
1.1 root 1466: (tcg_target_long)(s->tb_next + args[0]));
1467: }
1468: s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1469: break;
1470: case INDEX_op_call:
1471: if (const_args[0]) {
1.1.1.4 root 1472: tcg_out_calli(s, args[0]);
1.1 root 1473: } else {
1.1.1.4 root 1474: /* call *reg */
1475: tcg_out_modrm(s, OPC_GRP5, EXT5_CALLN_Ev, args[0]);
1.1 root 1476: }
1477: break;
1478: case INDEX_op_jmp:
1479: if (const_args[0]) {
1.1.1.4 root 1480: tcg_out_jmp(s, args[0]);
1.1 root 1481: } else {
1.1.1.4 root 1482: /* jmp *reg */
1483: tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, args[0]);
1.1 root 1484: }
1485: break;
1486: case INDEX_op_br:
1.1.1.4 root 1487: tcg_out_jxx(s, JCC_JMP, args[0], 0);
1.1 root 1488: break;
1489: case INDEX_op_movi_i32:
1490: tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1491: break;
1.1.1.4 root 1492: OP_32_64(ld8u):
1493: /* Note that we can ignore REXW for the zero-extend to 64-bit. */
1494: tcg_out_modrm_offset(s, OPC_MOVZBL, args[0], args[1], args[2]);
1495: break;
1496: OP_32_64(ld8s):
1497: tcg_out_modrm_offset(s, OPC_MOVSBL + rexw, args[0], args[1], args[2]);
1498: break;
1499: OP_32_64(ld16u):
1500: /* Note that we can ignore REXW for the zero-extend to 64-bit. */
1501: tcg_out_modrm_offset(s, OPC_MOVZWL, args[0], args[1], args[2]);
1.1 root 1502: break;
1.1.1.4 root 1503: OP_32_64(ld16s):
1504: tcg_out_modrm_offset(s, OPC_MOVSWL + rexw, args[0], args[1], args[2]);
1505: break;
1506: #if TCG_TARGET_REG_BITS == 64
1507: case INDEX_op_ld32u_i64:
1508: #endif
1.1 root 1509: case INDEX_op_ld_i32:
1.1.1.4 root 1510: tcg_out_ld(s, TCG_TYPE_I32, args[0], args[1], args[2]);
1.1 root 1511: break;
1.1.1.4 root 1512:
1513: OP_32_64(st8):
1514: tcg_out_modrm_offset(s, OPC_MOVB_EvGv | P_REXB_R,
1515: args[0], args[1], args[2]);
1.1 root 1516: break;
1.1.1.4 root 1517: OP_32_64(st16):
1518: tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16,
1519: args[0], args[1], args[2]);
1.1 root 1520: break;
1.1.1.4 root 1521: #if TCG_TARGET_REG_BITS == 64
1522: case INDEX_op_st32_i64:
1523: #endif
1.1 root 1524: case INDEX_op_st_i32:
1.1.1.4 root 1525: tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]);
1.1 root 1526: break;
1.1.1.4 root 1527:
1528: OP_32_64(add):
1529: /* For 3-operand addition, use LEA. */
1530: if (args[0] != args[1]) {
1531: TCGArg a0 = args[0], a1 = args[1], a2 = args[2], c3 = 0;
1532:
1533: if (const_args[2]) {
1534: c3 = a2, a2 = -1;
1535: } else if (a0 == a2) {
1536: /* Watch out for dest = src + dest, since we've removed
1537: the matching constraint on the add. */
1538: tgen_arithr(s, ARITH_ADD + rexw, a0, a1);
1539: break;
1540: }
1541:
1542: tcg_out_modrm_sib_offset(s, OPC_LEA + rexw, a0, a1, a2, 0, c3);
1543: break;
1544: }
1545: c = ARITH_ADD;
1546: goto gen_arith;
1547: OP_32_64(sub):
1.1 root 1548: c = ARITH_SUB;
1549: goto gen_arith;
1.1.1.4 root 1550: OP_32_64(and):
1.1 root 1551: c = ARITH_AND;
1552: goto gen_arith;
1.1.1.4 root 1553: OP_32_64(or):
1.1 root 1554: c = ARITH_OR;
1555: goto gen_arith;
1.1.1.4 root 1556: OP_32_64(xor):
1.1 root 1557: c = ARITH_XOR;
1558: goto gen_arith;
1559: gen_arith:
1560: if (const_args[2]) {
1.1.1.4 root 1561: tgen_arithi(s, c + rexw, args[0], args[2], 0);
1.1 root 1562: } else {
1.1.1.4 root 1563: tgen_arithr(s, c + rexw, args[0], args[2]);
1.1 root 1564: }
1565: break;
1.1.1.4 root 1566:
1567: OP_32_64(mul):
1.1 root 1568: if (const_args[2]) {
1569: int32_t val;
1570: val = args[2];
1571: if (val == (int8_t)val) {
1.1.1.4 root 1572: tcg_out_modrm(s, OPC_IMUL_GvEvIb + rexw, args[0], args[0]);
1.1 root 1573: tcg_out8(s, val);
1574: } else {
1.1.1.4 root 1575: tcg_out_modrm(s, OPC_IMUL_GvEvIz + rexw, args[0], args[0]);
1.1 root 1576: tcg_out32(s, val);
1577: }
1578: } else {
1.1.1.4 root 1579: tcg_out_modrm(s, OPC_IMUL_GvEv + rexw, args[0], args[2]);
1.1 root 1580: }
1581: break;
1.1.1.4 root 1582:
1583: OP_32_64(div2):
1584: tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_IDIV, args[4]);
1.1 root 1585: break;
1.1.1.4 root 1586: OP_32_64(divu2):
1587: tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_DIV, args[4]);
1.1 root 1588: break;
1.1.1.4 root 1589:
1590: OP_32_64(shl):
1.1 root 1591: c = SHIFT_SHL;
1.1.1.4 root 1592: goto gen_shift;
1593: OP_32_64(shr):
1.1 root 1594: c = SHIFT_SHR;
1.1.1.4 root 1595: goto gen_shift;
1596: OP_32_64(sar):
1.1 root 1597: c = SHIFT_SAR;
1.1.1.4 root 1598: goto gen_shift;
1599: OP_32_64(rotl):
1.1.1.2 root 1600: c = SHIFT_ROL;
1.1.1.4 root 1601: goto gen_shift;
1602: OP_32_64(rotr):
1.1.1.2 root 1603: c = SHIFT_ROR;
1.1.1.4 root 1604: goto gen_shift;
1605: gen_shift:
1606: if (const_args[2]) {
1607: tcg_out_shifti(s, c + rexw, args[0], args[2]);
1608: } else {
1609: tcg_out_modrm(s, OPC_SHIFT_cl + rexw, c, args[0]);
1610: }
1.1 root 1611: break;
1.1.1.4 root 1612:
1.1 root 1613: case INDEX_op_brcond_i32:
1.1.1.4 root 1614: tcg_out_brcond32(s, args[2], args[0], args[1], const_args[1],
1615: args[3], 0);
1.1 root 1616: break;
1.1.1.4 root 1617: case INDEX_op_setcond_i32:
1618: tcg_out_setcond32(s, args[3], args[0], args[1],
1619: args[2], const_args[2]);
1.1 root 1620: break;
1621:
1.1.1.4 root 1622: OP_32_64(bswap16):
1623: tcg_out_rolw_8(s, args[0]);
1.1.1.2 root 1624: break;
1.1.1.4 root 1625: OP_32_64(bswap32):
1626: tcg_out_bswap32(s, args[0]);
1.1.1.2 root 1627: break;
1628:
1.1.1.4 root 1629: OP_32_64(neg):
1630: tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_NEG, args[0]);
1.1.1.2 root 1631: break;
1.1.1.4 root 1632: OP_32_64(not):
1633: tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_NOT, args[0]);
1.1.1.2 root 1634: break;
1635:
1.1.1.4 root 1636: OP_32_64(ext8s):
1637: tcg_out_ext8s(s, args[0], args[1], rexw);
1.1.1.2 root 1638: break;
1.1.1.4 root 1639: OP_32_64(ext16s):
1640: tcg_out_ext16s(s, args[0], args[1], rexw);
1.1.1.2 root 1641: break;
1.1.1.4 root 1642: OP_32_64(ext8u):
1643: tcg_out_ext8u(s, args[0], args[1]);
1.1.1.3 root 1644: break;
1.1.1.4 root 1645: OP_32_64(ext16u):
1646: tcg_out_ext16u(s, args[0], args[1]);
1.1.1.3 root 1647: break;
1.1.1.2 root 1648:
1.1 root 1649: case INDEX_op_qemu_ld8u:
1650: tcg_out_qemu_ld(s, args, 0);
1651: break;
1652: case INDEX_op_qemu_ld8s:
1653: tcg_out_qemu_ld(s, args, 0 | 4);
1654: break;
1655: case INDEX_op_qemu_ld16u:
1656: tcg_out_qemu_ld(s, args, 1);
1657: break;
1658: case INDEX_op_qemu_ld16s:
1659: tcg_out_qemu_ld(s, args, 1 | 4);
1660: break;
1.1.1.4 root 1661: #if TCG_TARGET_REG_BITS == 64
1.1 root 1662: case INDEX_op_qemu_ld32u:
1.1.1.4 root 1663: #endif
1664: case INDEX_op_qemu_ld32:
1.1 root 1665: tcg_out_qemu_ld(s, args, 2);
1666: break;
1667: case INDEX_op_qemu_ld64:
1668: tcg_out_qemu_ld(s, args, 3);
1669: break;
1.1.1.4 root 1670:
1.1 root 1671: case INDEX_op_qemu_st8:
1672: tcg_out_qemu_st(s, args, 0);
1673: break;
1674: case INDEX_op_qemu_st16:
1675: tcg_out_qemu_st(s, args, 1);
1676: break;
1677: case INDEX_op_qemu_st32:
1678: tcg_out_qemu_st(s, args, 2);
1679: break;
1680: case INDEX_op_qemu_st64:
1681: tcg_out_qemu_st(s, args, 3);
1682: break;
1683:
1.1.1.4 root 1684: #if TCG_TARGET_REG_BITS == 32
1685: case INDEX_op_brcond2_i32:
1686: tcg_out_brcond2(s, args, const_args, 0);
1687: break;
1688: case INDEX_op_setcond2_i32:
1689: tcg_out_setcond2(s, args, const_args);
1690: break;
1691: case INDEX_op_mulu2_i32:
1692: tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_MUL, args[3]);
1693: break;
1694: case INDEX_op_add2_i32:
1695: if (const_args[4]) {
1696: tgen_arithi(s, ARITH_ADD, args[0], args[4], 1);
1697: } else {
1698: tgen_arithr(s, ARITH_ADD, args[0], args[4]);
1699: }
1700: if (const_args[5]) {
1701: tgen_arithi(s, ARITH_ADC, args[1], args[5], 1);
1702: } else {
1703: tgen_arithr(s, ARITH_ADC, args[1], args[5]);
1704: }
1705: break;
1706: case INDEX_op_sub2_i32:
1707: if (const_args[4]) {
1708: tgen_arithi(s, ARITH_SUB, args[0], args[4], 1);
1709: } else {
1710: tgen_arithr(s, ARITH_SUB, args[0], args[4]);
1711: }
1712: if (const_args[5]) {
1713: tgen_arithi(s, ARITH_SBB, args[1], args[5], 1);
1714: } else {
1715: tgen_arithr(s, ARITH_SBB, args[1], args[5]);
1716: }
1717: break;
1718: #else /* TCG_TARGET_REG_BITS == 64 */
1719: case INDEX_op_movi_i64:
1720: tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
1721: break;
1722: case INDEX_op_ld32s_i64:
1723: tcg_out_modrm_offset(s, OPC_MOVSLQ, args[0], args[1], args[2]);
1724: break;
1725: case INDEX_op_ld_i64:
1726: tcg_out_ld(s, TCG_TYPE_I64, args[0], args[1], args[2]);
1727: break;
1728: case INDEX_op_st_i64:
1729: tcg_out_st(s, TCG_TYPE_I64, args[0], args[1], args[2]);
1730: break;
1731: case INDEX_op_qemu_ld32s:
1732: tcg_out_qemu_ld(s, args, 2 | 4);
1733: break;
1734:
1735: case INDEX_op_brcond_i64:
1736: tcg_out_brcond64(s, args[2], args[0], args[1], const_args[1],
1737: args[3], 0);
1738: break;
1739: case INDEX_op_setcond_i64:
1740: tcg_out_setcond64(s, args[3], args[0], args[1],
1741: args[2], const_args[2]);
1742: break;
1743:
1744: case INDEX_op_bswap64_i64:
1745: tcg_out_bswap64(s, args[0]);
1746: break;
1747: case INDEX_op_ext32u_i64:
1748: tcg_out_ext32u(s, args[0], args[1]);
1749: break;
1750: case INDEX_op_ext32s_i64:
1751: tcg_out_ext32s(s, args[0], args[1]);
1752: break;
1753: #endif
1754:
1.1.1.6 ! root 1755: OP_32_64(deposit):
! 1756: if (args[3] == 0 && args[4] == 8) {
! 1757: /* load bits 0..7 */
! 1758: tcg_out_modrm(s, OPC_MOVB_EvGv | P_REXB_R | P_REXB_RM,
! 1759: args[2], args[0]);
! 1760: } else if (args[3] == 8 && args[4] == 8) {
! 1761: /* load bits 8..15 */
! 1762: tcg_out_modrm(s, OPC_MOVB_EvGv, args[2], args[0] + 4);
! 1763: } else if (args[3] == 0 && args[4] == 16) {
! 1764: /* load bits 0..15 */
! 1765: tcg_out_modrm(s, OPC_MOVL_EvGv | P_DATA16, args[2], args[0]);
! 1766: } else {
! 1767: tcg_abort();
! 1768: }
! 1769: break;
! 1770:
1.1 root 1771: default:
1772: tcg_abort();
1773: }
1.1.1.4 root 1774:
1775: #undef OP_32_64
1.1 root 1776: }
1777:
1778: static const TCGTargetOpDef x86_op_defs[] = {
1779: { INDEX_op_exit_tb, { } },
1780: { INDEX_op_goto_tb, { } },
1781: { INDEX_op_call, { "ri" } },
1782: { INDEX_op_jmp, { "ri" } },
1783: { INDEX_op_br, { } },
1784: { INDEX_op_mov_i32, { "r", "r" } },
1785: { INDEX_op_movi_i32, { "r" } },
1786: { INDEX_op_ld8u_i32, { "r", "r" } },
1787: { INDEX_op_ld8s_i32, { "r", "r" } },
1788: { INDEX_op_ld16u_i32, { "r", "r" } },
1789: { INDEX_op_ld16s_i32, { "r", "r" } },
1790: { INDEX_op_ld_i32, { "r", "r" } },
1791: { INDEX_op_st8_i32, { "q", "r" } },
1792: { INDEX_op_st16_i32, { "r", "r" } },
1793: { INDEX_op_st_i32, { "r", "r" } },
1794:
1.1.1.4 root 1795: { INDEX_op_add_i32, { "r", "r", "ri" } },
1.1 root 1796: { INDEX_op_sub_i32, { "r", "0", "ri" } },
1797: { INDEX_op_mul_i32, { "r", "0", "ri" } },
1798: { INDEX_op_div2_i32, { "a", "d", "0", "1", "r" } },
1799: { INDEX_op_divu2_i32, { "a", "d", "0", "1", "r" } },
1800: { INDEX_op_and_i32, { "r", "0", "ri" } },
1801: { INDEX_op_or_i32, { "r", "0", "ri" } },
1802: { INDEX_op_xor_i32, { "r", "0", "ri" } },
1803:
1804: { INDEX_op_shl_i32, { "r", "0", "ci" } },
1805: { INDEX_op_shr_i32, { "r", "0", "ci" } },
1806: { INDEX_op_sar_i32, { "r", "0", "ci" } },
1.1.1.2 root 1807: { INDEX_op_rotl_i32, { "r", "0", "ci" } },
1808: { INDEX_op_rotr_i32, { "r", "0", "ci" } },
1.1 root 1809:
1810: { INDEX_op_brcond_i32, { "r", "ri" } },
1811:
1.1.1.2 root 1812: { INDEX_op_bswap16_i32, { "r", "0" } },
1813: { INDEX_op_bswap32_i32, { "r", "0" } },
1814:
1815: { INDEX_op_neg_i32, { "r", "0" } },
1816:
1817: { INDEX_op_not_i32, { "r", "0" } },
1818:
1819: { INDEX_op_ext8s_i32, { "r", "q" } },
1820: { INDEX_op_ext16s_i32, { "r", "r" } },
1.1.1.4 root 1821: { INDEX_op_ext8u_i32, { "r", "q" } },
1822: { INDEX_op_ext16u_i32, { "r", "r" } },
1823:
1824: { INDEX_op_setcond_i32, { "q", "r", "ri" } },
1825:
1.1.1.6 ! root 1826: { INDEX_op_deposit_i32, { "Q", "0", "Q" } },
! 1827:
1.1.1.4 root 1828: #if TCG_TARGET_REG_BITS == 32
1829: { INDEX_op_mulu2_i32, { "a", "d", "a", "r" } },
1830: { INDEX_op_add2_i32, { "r", "r", "0", "1", "ri", "ri" } },
1831: { INDEX_op_sub2_i32, { "r", "r", "0", "1", "ri", "ri" } },
1832: { INDEX_op_brcond2_i32, { "r", "r", "ri", "ri" } },
1833: { INDEX_op_setcond2_i32, { "r", "r", "r", "ri", "ri" } },
1834: #else
1835: { INDEX_op_mov_i64, { "r", "r" } },
1836: { INDEX_op_movi_i64, { "r" } },
1837: { INDEX_op_ld8u_i64, { "r", "r" } },
1838: { INDEX_op_ld8s_i64, { "r", "r" } },
1839: { INDEX_op_ld16u_i64, { "r", "r" } },
1840: { INDEX_op_ld16s_i64, { "r", "r" } },
1841: { INDEX_op_ld32u_i64, { "r", "r" } },
1842: { INDEX_op_ld32s_i64, { "r", "r" } },
1843: { INDEX_op_ld_i64, { "r", "r" } },
1844: { INDEX_op_st8_i64, { "r", "r" } },
1845: { INDEX_op_st16_i64, { "r", "r" } },
1846: { INDEX_op_st32_i64, { "r", "r" } },
1847: { INDEX_op_st_i64, { "r", "r" } },
1848:
1849: { INDEX_op_add_i64, { "r", "0", "re" } },
1850: { INDEX_op_mul_i64, { "r", "0", "re" } },
1851: { INDEX_op_div2_i64, { "a", "d", "0", "1", "r" } },
1852: { INDEX_op_divu2_i64, { "a", "d", "0", "1", "r" } },
1853: { INDEX_op_sub_i64, { "r", "0", "re" } },
1854: { INDEX_op_and_i64, { "r", "0", "reZ" } },
1855: { INDEX_op_or_i64, { "r", "0", "re" } },
1856: { INDEX_op_xor_i64, { "r", "0", "re" } },
1857:
1858: { INDEX_op_shl_i64, { "r", "0", "ci" } },
1859: { INDEX_op_shr_i64, { "r", "0", "ci" } },
1860: { INDEX_op_sar_i64, { "r", "0", "ci" } },
1861: { INDEX_op_rotl_i64, { "r", "0", "ci" } },
1862: { INDEX_op_rotr_i64, { "r", "0", "ci" } },
1863:
1864: { INDEX_op_brcond_i64, { "r", "re" } },
1865: { INDEX_op_setcond_i64, { "r", "r", "re" } },
1866:
1867: { INDEX_op_bswap16_i64, { "r", "0" } },
1868: { INDEX_op_bswap32_i64, { "r", "0" } },
1869: { INDEX_op_bswap64_i64, { "r", "0" } },
1870: { INDEX_op_neg_i64, { "r", "0" } },
1871: { INDEX_op_not_i64, { "r", "0" } },
1872:
1873: { INDEX_op_ext8s_i64, { "r", "r" } },
1874: { INDEX_op_ext16s_i64, { "r", "r" } },
1875: { INDEX_op_ext32s_i64, { "r", "r" } },
1876: { INDEX_op_ext8u_i64, { "r", "r" } },
1877: { INDEX_op_ext16u_i64, { "r", "r" } },
1878: { INDEX_op_ext32u_i64, { "r", "r" } },
1.1.1.6 ! root 1879:
! 1880: { INDEX_op_deposit_i64, { "Q", "0", "Q" } },
1.1.1.4 root 1881: #endif
1.1.1.2 root 1882:
1.1.1.4 root 1883: #if TCG_TARGET_REG_BITS == 64
1.1 root 1884: { INDEX_op_qemu_ld8u, { "r", "L" } },
1885: { INDEX_op_qemu_ld8s, { "r", "L" } },
1886: { INDEX_op_qemu_ld16u, { "r", "L" } },
1887: { INDEX_op_qemu_ld16s, { "r", "L" } },
1.1.1.4 root 1888: { INDEX_op_qemu_ld32, { "r", "L" } },
1.1 root 1889: { INDEX_op_qemu_ld32u, { "r", "L" } },
1.1.1.4 root 1890: { INDEX_op_qemu_ld32s, { "r", "L" } },
1891: { INDEX_op_qemu_ld64, { "r", "L" } },
1892:
1893: { INDEX_op_qemu_st8, { "L", "L" } },
1894: { INDEX_op_qemu_st16, { "L", "L" } },
1895: { INDEX_op_qemu_st32, { "L", "L" } },
1896: { INDEX_op_qemu_st64, { "L", "L" } },
1897: #elif TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
1898: { INDEX_op_qemu_ld8u, { "r", "L" } },
1899: { INDEX_op_qemu_ld8s, { "r", "L" } },
1900: { INDEX_op_qemu_ld16u, { "r", "L" } },
1901: { INDEX_op_qemu_ld16s, { "r", "L" } },
1902: { INDEX_op_qemu_ld32, { "r", "L" } },
1.1 root 1903: { INDEX_op_qemu_ld64, { "r", "r", "L" } },
1904:
1905: { INDEX_op_qemu_st8, { "cb", "L" } },
1906: { INDEX_op_qemu_st16, { "L", "L" } },
1907: { INDEX_op_qemu_st32, { "L", "L" } },
1908: { INDEX_op_qemu_st64, { "L", "L", "L" } },
1909: #else
1910: { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
1911: { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
1912: { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
1913: { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
1.1.1.4 root 1914: { INDEX_op_qemu_ld32, { "r", "L", "L" } },
1.1 root 1915: { INDEX_op_qemu_ld64, { "r", "r", "L", "L" } },
1916:
1917: { INDEX_op_qemu_st8, { "cb", "L", "L" } },
1918: { INDEX_op_qemu_st16, { "L", "L", "L" } },
1919: { INDEX_op_qemu_st32, { "L", "L", "L" } },
1920: { INDEX_op_qemu_st64, { "L", "L", "L", "L" } },
1921: #endif
1922: { -1 },
1923: };
1924:
1925: static int tcg_target_callee_save_regs[] = {
1.1.1.4 root 1926: #if TCG_TARGET_REG_BITS == 64
1927: TCG_REG_RBP,
1928: TCG_REG_RBX,
1929: TCG_REG_R12,
1930: TCG_REG_R13,
1.1.1.5 root 1931: TCG_REG_R14, /* Currently used for the global env. */
1.1.1.4 root 1932: TCG_REG_R15,
1933: #else
1.1.1.5 root 1934: TCG_REG_EBP, /* Currently used for the global env. */
1.1 root 1935: TCG_REG_EBX,
1936: TCG_REG_ESI,
1937: TCG_REG_EDI,
1.1.1.4 root 1938: #endif
1.1 root 1939: };
1940:
1941: /* Generate global QEMU prologue and epilogue code */
1.1.1.4 root 1942: static void tcg_target_qemu_prologue(TCGContext *s)
1.1 root 1943: {
1944: int i, frame_size, push_size, stack_addend;
1.1.1.4 root 1945:
1.1 root 1946: /* TB prologue */
1.1.1.4 root 1947:
1.1.1.5 root 1948: /* Reserve some stack space, also for TCG temps. */
1.1.1.4 root 1949: push_size = 1 + ARRAY_SIZE(tcg_target_callee_save_regs);
1950: push_size *= TCG_TARGET_REG_BITS / 8;
1951:
1.1.1.5 root 1952: frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE +
1953: CPU_TEMP_BUF_NLONGS * sizeof(long);
1.1.1.4 root 1954: frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1.1 root 1955: ~(TCG_TARGET_STACK_ALIGN - 1);
1956: stack_addend = frame_size - push_size;
1.1.1.5 root 1957: tcg_set_frame(s, TCG_REG_CALL_STACK, TCG_STATIC_CALL_ARGS_SIZE,
1958: CPU_TEMP_BUF_NLONGS * sizeof(long));
1959:
1960: /* Save all callee saved registers. */
1961: for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
1962: tcg_out_push(s, tcg_target_callee_save_regs[i]);
1963: }
1964:
1.1 root 1965: tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
1966:
1.1.1.5 root 1967: tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
1968:
1.1.1.4 root 1969: /* jmp *tb. */
1.1.1.5 root 1970: tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, tcg_target_call_iarg_regs[1]);
1.1.1.4 root 1971:
1.1 root 1972: /* TB epilogue */
1973: tb_ret_addr = s->code_ptr;
1.1.1.4 root 1974:
1.1.1.5 root 1975: tcg_out_addi(s, TCG_REG_CALL_STACK, stack_addend);
1.1.1.4 root 1976:
1977: for (i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
1.1 root 1978: tcg_out_pop(s, tcg_target_callee_save_regs[i]);
1979: }
1.1.1.4 root 1980: tcg_out_opc(s, OPC_RET, 0, 0, 0);
1.1 root 1981: }
1982:
1.1.1.4 root 1983: static void tcg_target_init(TCGContext *s)
1.1 root 1984: {
1.1.1.4 root 1985: #if !defined(CONFIG_USER_ONLY)
1.1 root 1986: /* fail safe */
1987: if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
1988: tcg_abort();
1.1.1.4 root 1989: #endif
1990:
1991: if (TCG_TARGET_REG_BITS == 64) {
1992: tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
1993: tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffff);
1994: } else {
1995: tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xff);
1996: }
1997:
1998: tcg_regset_clear(tcg_target_call_clobber_regs);
1999: tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EAX);
2000: tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EDX);
2001: tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_ECX);
2002: if (TCG_TARGET_REG_BITS == 64) {
2003: tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RDI);
2004: tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RSI);
2005: tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R8);
2006: tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R9);
2007: tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R10);
2008: tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R11);
2009: }
1.1 root 2010:
2011: tcg_regset_clear(s->reserved_regs);
1.1.1.5 root 2012: tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
1.1 root 2013:
2014: tcg_add_target_add_op_defs(x86_op_defs);
2015: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.