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