|
|
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] = {
27: "%eax",
28: "%ecx",
29: "%edx",
30: "%ebx",
31: "%esp",
32: "%ebp",
33: "%esi",
34: "%edi",
35: };
36: #endif
37:
38: static const int tcg_target_reg_alloc_order[] = {
39: TCG_REG_EAX,
40: TCG_REG_EDX,
41: TCG_REG_ECX,
42: TCG_REG_EBX,
43: TCG_REG_ESI,
44: TCG_REG_EDI,
45: TCG_REG_EBP,
46: };
47:
48: static const int tcg_target_call_iarg_regs[3] = { TCG_REG_EAX, TCG_REG_EDX, TCG_REG_ECX };
49: static const int tcg_target_call_oarg_regs[2] = { TCG_REG_EAX, TCG_REG_EDX };
50:
51: static uint8_t *tb_ret_addr;
52:
53: static void patch_reloc(uint8_t *code_ptr, int type,
54: tcg_target_long value, tcg_target_long addend)
55: {
56: value += addend;
57: switch(type) {
58: case R_386_32:
59: *(uint32_t *)code_ptr = value;
60: break;
61: case R_386_PC32:
62: *(uint32_t *)code_ptr = value - (long)code_ptr;
63: break;
64: default:
65: tcg_abort();
66: }
67: }
68:
69: /* maximum number of register used for input function arguments */
70: static inline int tcg_target_get_call_iarg_regs_count(int flags)
71: {
72: flags &= TCG_CALL_TYPE_MASK;
73: switch(flags) {
74: case TCG_CALL_TYPE_STD:
75: return 0;
76: case TCG_CALL_TYPE_REGPARM_1:
77: case TCG_CALL_TYPE_REGPARM_2:
78: case TCG_CALL_TYPE_REGPARM:
79: return flags - TCG_CALL_TYPE_REGPARM_1 + 1;
80: default:
81: tcg_abort();
82: }
83: }
84:
85: /* parse target specific constraints */
86: static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
87: {
88: const char *ct_str;
89:
90: ct_str = *pct_str;
91: switch(ct_str[0]) {
92: case 'a':
93: ct->ct |= TCG_CT_REG;
94: tcg_regset_set_reg(ct->u.regs, TCG_REG_EAX);
95: break;
96: case 'b':
97: ct->ct |= TCG_CT_REG;
98: tcg_regset_set_reg(ct->u.regs, TCG_REG_EBX);
99: break;
100: case 'c':
101: ct->ct |= TCG_CT_REG;
102: tcg_regset_set_reg(ct->u.regs, TCG_REG_ECX);
103: break;
104: case 'd':
105: ct->ct |= TCG_CT_REG;
106: tcg_regset_set_reg(ct->u.regs, TCG_REG_EDX);
107: break;
108: case 'S':
109: ct->ct |= TCG_CT_REG;
110: tcg_regset_set_reg(ct->u.regs, TCG_REG_ESI);
111: break;
112: case 'D':
113: ct->ct |= TCG_CT_REG;
114: tcg_regset_set_reg(ct->u.regs, TCG_REG_EDI);
115: break;
116: case 'q':
117: ct->ct |= TCG_CT_REG;
118: tcg_regset_set32(ct->u.regs, 0, 0xf);
119: break;
120: case 'r':
121: ct->ct |= TCG_CT_REG;
122: tcg_regset_set32(ct->u.regs, 0, 0xff);
123: break;
124:
125: /* qemu_ld/st address constraint */
126: case 'L':
127: ct->ct |= TCG_CT_REG;
128: tcg_regset_set32(ct->u.regs, 0, 0xff);
129: tcg_regset_reset_reg(ct->u.regs, TCG_REG_EAX);
130: tcg_regset_reset_reg(ct->u.regs, TCG_REG_EDX);
131: break;
132: default:
133: return -1;
134: }
135: ct_str++;
136: *pct_str = ct_str;
137: return 0;
138: }
139:
140: /* test if a constant matches the constraint */
141: static inline int tcg_target_const_match(tcg_target_long val,
142: const TCGArgConstraint *arg_ct)
143: {
144: int ct;
145: ct = arg_ct->ct;
146: if (ct & TCG_CT_CONST)
147: return 1;
148: else
149: return 0;
150: }
151:
152: #define ARITH_ADD 0
153: #define ARITH_OR 1
154: #define ARITH_ADC 2
155: #define ARITH_SBB 3
156: #define ARITH_AND 4
157: #define ARITH_SUB 5
158: #define ARITH_XOR 6
159: #define ARITH_CMP 7
160:
1.1.1.2 root 161: #define SHIFT_ROL 0
162: #define SHIFT_ROR 1
1.1 root 163: #define SHIFT_SHL 4
164: #define SHIFT_SHR 5
165: #define SHIFT_SAR 7
166:
167: #define JCC_JMP (-1)
168: #define JCC_JO 0x0
169: #define JCC_JNO 0x1
170: #define JCC_JB 0x2
171: #define JCC_JAE 0x3
172: #define JCC_JE 0x4
173: #define JCC_JNE 0x5
174: #define JCC_JBE 0x6
175: #define JCC_JA 0x7
176: #define JCC_JS 0x8
177: #define JCC_JNS 0x9
178: #define JCC_JP 0xa
179: #define JCC_JNP 0xb
180: #define JCC_JL 0xc
181: #define JCC_JGE 0xd
182: #define JCC_JLE 0xe
183: #define JCC_JG 0xf
184:
185: #define P_EXT 0x100 /* 0x0f opcode prefix */
186:
187: static const uint8_t tcg_cond_to_jcc[10] = {
188: [TCG_COND_EQ] = JCC_JE,
189: [TCG_COND_NE] = JCC_JNE,
190: [TCG_COND_LT] = JCC_JL,
191: [TCG_COND_GE] = JCC_JGE,
192: [TCG_COND_LE] = JCC_JLE,
193: [TCG_COND_GT] = JCC_JG,
194: [TCG_COND_LTU] = JCC_JB,
195: [TCG_COND_GEU] = JCC_JAE,
196: [TCG_COND_LEU] = JCC_JBE,
197: [TCG_COND_GTU] = JCC_JA,
198: };
199:
200: static inline void tcg_out_opc(TCGContext *s, int opc)
201: {
202: if (opc & P_EXT)
203: tcg_out8(s, 0x0f);
204: tcg_out8(s, opc);
205: }
206:
207: static inline void tcg_out_modrm(TCGContext *s, int opc, int r, int rm)
208: {
209: tcg_out_opc(s, opc);
210: tcg_out8(s, 0xc0 | (r << 3) | rm);
211: }
212:
213: /* rm == -1 means no register index */
214: static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r, int rm,
215: int32_t offset)
216: {
217: tcg_out_opc(s, opc);
218: if (rm == -1) {
219: tcg_out8(s, 0x05 | (r << 3));
220: tcg_out32(s, offset);
221: } else if (offset == 0 && rm != TCG_REG_EBP) {
222: if (rm == TCG_REG_ESP) {
223: tcg_out8(s, 0x04 | (r << 3));
224: tcg_out8(s, 0x24);
225: } else {
226: tcg_out8(s, 0x00 | (r << 3) | rm);
227: }
228: } else if ((int8_t)offset == offset) {
229: if (rm == TCG_REG_ESP) {
230: tcg_out8(s, 0x44 | (r << 3));
231: tcg_out8(s, 0x24);
232: } else {
233: tcg_out8(s, 0x40 | (r << 3) | rm);
234: }
235: tcg_out8(s, offset);
236: } else {
237: if (rm == TCG_REG_ESP) {
238: tcg_out8(s, 0x84 | (r << 3));
239: tcg_out8(s, 0x24);
240: } else {
241: tcg_out8(s, 0x80 | (r << 3) | rm);
242: }
243: tcg_out32(s, offset);
244: }
245: }
246:
247: static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
248: {
249: if (arg != ret)
250: tcg_out_modrm(s, 0x8b, ret, arg);
251: }
252:
253: static inline void tcg_out_movi(TCGContext *s, TCGType type,
254: int ret, int32_t arg)
255: {
256: if (arg == 0) {
257: /* xor r0,r0 */
258: tcg_out_modrm(s, 0x01 | (ARITH_XOR << 3), ret, ret);
259: } else {
260: tcg_out8(s, 0xb8 + ret);
261: tcg_out32(s, arg);
262: }
263: }
264:
265: static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
266: int arg1, tcg_target_long arg2)
267: {
268: /* movl */
269: tcg_out_modrm_offset(s, 0x8b, ret, arg1, arg2);
270: }
271:
272: static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
273: int arg1, tcg_target_long arg2)
274: {
275: /* movl */
276: tcg_out_modrm_offset(s, 0x89, arg, arg1, arg2);
277: }
278:
1.1.1.3 ! root 279: static inline void tgen_arithi(TCGContext *s, int c, int r0, int32_t val, int cf)
1.1 root 280: {
1.1.1.3 ! root 281: if (!cf && ((c == ARITH_ADD && val == 1) || (c == ARITH_SUB && val == -1))) {
! 282: /* inc */
! 283: tcg_out_opc(s, 0x40 + r0);
! 284: } else if (!cf && ((c == ARITH_ADD && val == -1) || (c == ARITH_SUB && val == 1))) {
! 285: /* dec */
! 286: tcg_out_opc(s, 0x48 + r0);
! 287: } else if (val == (int8_t)val) {
1.1 root 288: tcg_out_modrm(s, 0x83, c, r0);
289: tcg_out8(s, val);
1.1.1.3 ! root 290: } else if (c == ARITH_AND && val == 0xffu && r0 < 4) {
! 291: /* movzbl */
! 292: tcg_out_modrm(s, 0xb6 | P_EXT, r0, r0);
! 293: } else if (c == ARITH_AND && val == 0xffffu) {
! 294: /* movzwl */
! 295: tcg_out_modrm(s, 0xb7 | P_EXT, r0, r0);
1.1 root 296: } else {
297: tcg_out_modrm(s, 0x81, c, r0);
298: tcg_out32(s, val);
299: }
300: }
301:
302: static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
303: {
304: if (val != 0)
1.1.1.3 ! root 305: tgen_arithi(s, ARITH_ADD, reg, val, 0);
1.1 root 306: }
307:
308: static void tcg_out_jxx(TCGContext *s, int opc, int label_index)
309: {
310: int32_t val, val1;
311: TCGLabel *l = &s->labels[label_index];
312:
313: if (l->has_value) {
314: val = l->u.value - (tcg_target_long)s->code_ptr;
315: val1 = val - 2;
316: if ((int8_t)val1 == val1) {
317: if (opc == -1)
318: tcg_out8(s, 0xeb);
319: else
320: tcg_out8(s, 0x70 + opc);
321: tcg_out8(s, val1);
322: } else {
323: if (opc == -1) {
324: tcg_out8(s, 0xe9);
325: tcg_out32(s, val - 5);
326: } else {
327: tcg_out8(s, 0x0f);
328: tcg_out8(s, 0x80 + opc);
329: tcg_out32(s, val - 6);
330: }
331: }
332: } else {
333: if (opc == -1) {
334: tcg_out8(s, 0xe9);
335: } else {
336: tcg_out8(s, 0x0f);
337: tcg_out8(s, 0x80 + opc);
338: }
339: tcg_out_reloc(s, s->code_ptr, R_386_PC32, label_index, -4);
340: s->code_ptr += 4;
341: }
342: }
343:
344: static void tcg_out_brcond(TCGContext *s, int cond,
345: TCGArg arg1, TCGArg arg2, int const_arg2,
346: int label_index)
347: {
348: if (const_arg2) {
349: if (arg2 == 0) {
350: /* test r, r */
351: tcg_out_modrm(s, 0x85, arg1, arg1);
352: } else {
1.1.1.3 ! root 353: tgen_arithi(s, ARITH_CMP, arg1, arg2, 0);
1.1 root 354: }
355: } else {
356: tcg_out_modrm(s, 0x01 | (ARITH_CMP << 3), arg2, arg1);
357: }
358: tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index);
359: }
360:
361: /* XXX: we implement it at the target level to avoid having to
362: handle cross basic blocks temporaries */
363: static void tcg_out_brcond2(TCGContext *s,
364: const TCGArg *args, const int *const_args)
365: {
366: int label_next;
367: label_next = gen_new_label();
368: switch(args[4]) {
369: case TCG_COND_EQ:
370: tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2], label_next);
371: tcg_out_brcond(s, TCG_COND_EQ, args[1], args[3], const_args[3], args[5]);
372: break;
373: case TCG_COND_NE:
374: tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2], args[5]);
375: tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], args[5]);
376: break;
377: case TCG_COND_LT:
378: tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3], args[5]);
379: tcg_out_jxx(s, JCC_JNE, label_next);
380: tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2], args[5]);
381: break;
382: case TCG_COND_LE:
383: tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3], args[5]);
384: tcg_out_jxx(s, JCC_JNE, label_next);
385: tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2], args[5]);
386: break;
387: case TCG_COND_GT:
388: tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3], args[5]);
389: tcg_out_jxx(s, JCC_JNE, label_next);
390: tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2], args[5]);
391: break;
392: case TCG_COND_GE:
393: tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3], args[5]);
394: tcg_out_jxx(s, JCC_JNE, label_next);
395: tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2], args[5]);
396: break;
397: case TCG_COND_LTU:
398: tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3], args[5]);
399: tcg_out_jxx(s, JCC_JNE, label_next);
400: tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2], args[5]);
401: break;
402: case TCG_COND_LEU:
403: tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3], args[5]);
404: tcg_out_jxx(s, JCC_JNE, label_next);
405: tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2], args[5]);
406: break;
407: case TCG_COND_GTU:
408: tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3], args[5]);
409: tcg_out_jxx(s, JCC_JNE, label_next);
410: tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2], args[5]);
411: break;
412: case TCG_COND_GEU:
413: tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3], args[5]);
414: tcg_out_jxx(s, JCC_JNE, label_next);
415: tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2], args[5]);
416: break;
417: default:
418: tcg_abort();
419: }
420: tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);
421: }
422:
423: #if defined(CONFIG_SOFTMMU)
424:
425: #include "../../softmmu_defs.h"
426:
427: static void *qemu_ld_helpers[4] = {
428: __ldb_mmu,
429: __ldw_mmu,
430: __ldl_mmu,
431: __ldq_mmu,
432: };
433:
434: static void *qemu_st_helpers[4] = {
435: __stb_mmu,
436: __stw_mmu,
437: __stl_mmu,
438: __stq_mmu,
439: };
440: #endif
441:
1.1.1.3 ! root 442: #ifndef CONFIG_USER_ONLY
! 443: #define GUEST_BASE 0
! 444: #endif
! 445:
1.1 root 446: /* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and
447: EAX. It will be useful once fixed registers globals are less
448: common. */
449: static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
450: int opc)
451: {
452: int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
453: #if defined(CONFIG_SOFTMMU)
454: uint8_t *label1_ptr, *label2_ptr;
455: #endif
456: #if TARGET_LONG_BITS == 64
457: #if defined(CONFIG_SOFTMMU)
458: uint8_t *label3_ptr;
459: #endif
460: int addr_reg2;
461: #endif
462:
463: data_reg = *args++;
464: if (opc == 3)
465: data_reg2 = *args++;
466: else
467: data_reg2 = 0;
468: addr_reg = *args++;
469: #if TARGET_LONG_BITS == 64
470: addr_reg2 = *args++;
471: #endif
472: mem_index = *args;
473: s_bits = opc & 3;
474:
475: r0 = TCG_REG_EAX;
476: r1 = TCG_REG_EDX;
477:
478: #if defined(CONFIG_SOFTMMU)
479: tcg_out_mov(s, r1, addr_reg);
480:
481: tcg_out_mov(s, r0, addr_reg);
482:
483: tcg_out_modrm(s, 0xc1, 5, r1); /* shr $x, r1 */
484: tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
485:
486: tcg_out_modrm(s, 0x81, 4, r0); /* andl $x, r0 */
487: tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
488:
489: tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */
490: tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
491:
492: tcg_out_opc(s, 0x8d); /* lea offset(r1, %ebp), r1 */
493: tcg_out8(s, 0x80 | (r1 << 3) | 0x04);
494: tcg_out8(s, (5 << 3) | r1);
495: tcg_out32(s, offsetof(CPUState, tlb_table[mem_index][0].addr_read));
496:
497: /* cmp 0(r1), r0 */
498: tcg_out_modrm_offset(s, 0x3b, r0, r1, 0);
499:
500: tcg_out_mov(s, r0, addr_reg);
501:
502: #if TARGET_LONG_BITS == 32
503: /* je label1 */
504: tcg_out8(s, 0x70 + JCC_JE);
505: label1_ptr = s->code_ptr;
506: s->code_ptr++;
507: #else
508: /* jne label3 */
509: tcg_out8(s, 0x70 + JCC_JNE);
510: label3_ptr = s->code_ptr;
511: s->code_ptr++;
512:
513: /* cmp 4(r1), addr_reg2 */
514: tcg_out_modrm_offset(s, 0x3b, addr_reg2, r1, 4);
515:
516: /* je label1 */
517: tcg_out8(s, 0x70 + JCC_JE);
518: label1_ptr = s->code_ptr;
519: s->code_ptr++;
520:
521: /* label3: */
522: *label3_ptr = s->code_ptr - label3_ptr - 1;
523: #endif
524:
525: /* XXX: move that code at the end of the TB */
526: #if TARGET_LONG_BITS == 32
527: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EDX, mem_index);
528: #else
529: tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
530: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
531: #endif
532: tcg_out8(s, 0xe8);
533: tcg_out32(s, (tcg_target_long)qemu_ld_helpers[s_bits] -
534: (tcg_target_long)s->code_ptr - 4);
535:
536: switch(opc) {
537: case 0 | 4:
538: /* movsbl */
539: tcg_out_modrm(s, 0xbe | P_EXT, data_reg, TCG_REG_EAX);
540: break;
541: case 1 | 4:
542: /* movswl */
543: tcg_out_modrm(s, 0xbf | P_EXT, data_reg, TCG_REG_EAX);
544: break;
545: case 0:
546: /* movzbl */
547: tcg_out_modrm(s, 0xb6 | P_EXT, data_reg, TCG_REG_EAX);
548: break;
549: case 1:
550: /* movzwl */
551: tcg_out_modrm(s, 0xb7 | P_EXT, data_reg, TCG_REG_EAX);
552: break;
553: case 2:
554: default:
555: tcg_out_mov(s, data_reg, TCG_REG_EAX);
556: break;
557: case 3:
558: if (data_reg == TCG_REG_EDX) {
559: tcg_out_opc(s, 0x90 + TCG_REG_EDX); /* xchg %edx, %eax */
560: tcg_out_mov(s, data_reg2, TCG_REG_EAX);
561: } else {
562: tcg_out_mov(s, data_reg, TCG_REG_EAX);
563: tcg_out_mov(s, data_reg2, TCG_REG_EDX);
564: }
565: break;
566: }
567:
568: /* jmp label2 */
569: tcg_out8(s, 0xeb);
570: label2_ptr = s->code_ptr;
571: s->code_ptr++;
572:
573: /* label1: */
574: *label1_ptr = s->code_ptr - label1_ptr - 1;
575:
576: /* add x(r1), r0 */
577: tcg_out_modrm_offset(s, 0x03, r0, r1, offsetof(CPUTLBEntry, addend) -
578: offsetof(CPUTLBEntry, addr_read));
579: #else
580: r0 = addr_reg;
581: #endif
582:
583: #ifdef TARGET_WORDS_BIGENDIAN
584: bswap = 1;
585: #else
586: bswap = 0;
587: #endif
588: switch(opc) {
589: case 0:
590: /* movzbl */
1.1.1.3 ! root 591: tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, GUEST_BASE);
1.1 root 592: break;
593: case 0 | 4:
594: /* movsbl */
1.1.1.3 ! root 595: tcg_out_modrm_offset(s, 0xbe | P_EXT, data_reg, r0, GUEST_BASE);
1.1 root 596: break;
597: case 1:
598: /* movzwl */
1.1.1.3 ! root 599: tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, GUEST_BASE);
1.1 root 600: if (bswap) {
601: /* rolw $8, data_reg */
602: tcg_out8(s, 0x66);
603: tcg_out_modrm(s, 0xc1, 0, data_reg);
604: tcg_out8(s, 8);
605: }
606: break;
607: case 1 | 4:
608: /* movswl */
1.1.1.3 ! root 609: tcg_out_modrm_offset(s, 0xbf | P_EXT, data_reg, r0, GUEST_BASE);
1.1 root 610: if (bswap) {
611: /* rolw $8, data_reg */
612: tcg_out8(s, 0x66);
613: tcg_out_modrm(s, 0xc1, 0, data_reg);
614: tcg_out8(s, 8);
615:
616: /* movswl data_reg, data_reg */
617: tcg_out_modrm(s, 0xbf | P_EXT, data_reg, data_reg);
618: }
619: break;
620: case 2:
621: /* movl (r0), data_reg */
1.1.1.3 ! root 622: tcg_out_modrm_offset(s, 0x8b, data_reg, r0, GUEST_BASE);
1.1 root 623: if (bswap) {
624: /* bswap */
625: tcg_out_opc(s, (0xc8 + data_reg) | P_EXT);
626: }
627: break;
628: case 3:
629: /* XXX: could be nicer */
630: if (r0 == data_reg) {
631: r1 = TCG_REG_EDX;
632: if (r1 == data_reg)
633: r1 = TCG_REG_EAX;
634: tcg_out_mov(s, r1, r0);
635: r0 = r1;
636: }
637: if (!bswap) {
1.1.1.3 ! root 638: tcg_out_modrm_offset(s, 0x8b, data_reg, r0, GUEST_BASE);
! 639: tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, GUEST_BASE + 4);
1.1 root 640: } else {
1.1.1.3 ! root 641: tcg_out_modrm_offset(s, 0x8b, data_reg, r0, GUEST_BASE + 4);
1.1 root 642: tcg_out_opc(s, (0xc8 + data_reg) | P_EXT);
643:
1.1.1.3 ! root 644: tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, GUEST_BASE);
1.1 root 645: /* bswap */
646: tcg_out_opc(s, (0xc8 + data_reg2) | P_EXT);
647: }
648: break;
649: default:
650: tcg_abort();
651: }
652:
653: #if defined(CONFIG_SOFTMMU)
654: /* label2: */
655: *label2_ptr = s->code_ptr - label2_ptr - 1;
656: #endif
657: }
658:
659:
660: static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
661: int opc)
662: {
663: int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
664: #if defined(CONFIG_SOFTMMU)
665: uint8_t *label1_ptr, *label2_ptr;
666: #endif
667: #if TARGET_LONG_BITS == 64
668: #if defined(CONFIG_SOFTMMU)
669: uint8_t *label3_ptr;
670: #endif
671: int addr_reg2;
672: #endif
673:
674: data_reg = *args++;
675: if (opc == 3)
676: data_reg2 = *args++;
677: else
678: data_reg2 = 0;
679: addr_reg = *args++;
680: #if TARGET_LONG_BITS == 64
681: addr_reg2 = *args++;
682: #endif
683: mem_index = *args;
684:
685: s_bits = opc;
686:
687: r0 = TCG_REG_EAX;
688: r1 = TCG_REG_EDX;
689:
690: #if defined(CONFIG_SOFTMMU)
691: tcg_out_mov(s, r1, addr_reg);
692:
693: tcg_out_mov(s, r0, addr_reg);
694:
695: tcg_out_modrm(s, 0xc1, 5, r1); /* shr $x, r1 */
696: tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
697:
698: tcg_out_modrm(s, 0x81, 4, r0); /* andl $x, r0 */
699: tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
700:
701: tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */
702: tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
703:
704: tcg_out_opc(s, 0x8d); /* lea offset(r1, %ebp), r1 */
705: tcg_out8(s, 0x80 | (r1 << 3) | 0x04);
706: tcg_out8(s, (5 << 3) | r1);
707: tcg_out32(s, offsetof(CPUState, tlb_table[mem_index][0].addr_write));
708:
709: /* cmp 0(r1), r0 */
710: tcg_out_modrm_offset(s, 0x3b, r0, r1, 0);
711:
712: tcg_out_mov(s, r0, addr_reg);
713:
714: #if TARGET_LONG_BITS == 32
715: /* je label1 */
716: tcg_out8(s, 0x70 + JCC_JE);
717: label1_ptr = s->code_ptr;
718: s->code_ptr++;
719: #else
720: /* jne label3 */
721: tcg_out8(s, 0x70 + JCC_JNE);
722: label3_ptr = s->code_ptr;
723: s->code_ptr++;
724:
725: /* cmp 4(r1), addr_reg2 */
726: tcg_out_modrm_offset(s, 0x3b, addr_reg2, r1, 4);
727:
728: /* je label1 */
729: tcg_out8(s, 0x70 + JCC_JE);
730: label1_ptr = s->code_ptr;
731: s->code_ptr++;
732:
733: /* label3: */
734: *label3_ptr = s->code_ptr - label3_ptr - 1;
735: #endif
736:
737: /* XXX: move that code at the end of the TB */
738: #if TARGET_LONG_BITS == 32
739: if (opc == 3) {
740: tcg_out_mov(s, TCG_REG_EDX, data_reg);
741: tcg_out_mov(s, TCG_REG_ECX, data_reg2);
742: tcg_out8(s, 0x6a); /* push Ib */
743: tcg_out8(s, mem_index);
744: tcg_out8(s, 0xe8);
745: tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] -
746: (tcg_target_long)s->code_ptr - 4);
747: tcg_out_addi(s, TCG_REG_ESP, 4);
748: } else {
749: switch(opc) {
750: case 0:
751: /* movzbl */
752: tcg_out_modrm(s, 0xb6 | P_EXT, TCG_REG_EDX, data_reg);
753: break;
754: case 1:
755: /* movzwl */
756: tcg_out_modrm(s, 0xb7 | P_EXT, TCG_REG_EDX, data_reg);
757: break;
758: case 2:
759: tcg_out_mov(s, TCG_REG_EDX, data_reg);
760: break;
761: }
762: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
763: tcg_out8(s, 0xe8);
764: tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] -
765: (tcg_target_long)s->code_ptr - 4);
766: }
767: #else
768: if (opc == 3) {
769: tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
770: tcg_out8(s, 0x6a); /* push Ib */
771: tcg_out8(s, mem_index);
772: tcg_out_opc(s, 0x50 + data_reg2); /* push */
773: tcg_out_opc(s, 0x50 + data_reg); /* push */
774: tcg_out8(s, 0xe8);
775: tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] -
776: (tcg_target_long)s->code_ptr - 4);
777: tcg_out_addi(s, TCG_REG_ESP, 12);
778: } else {
779: tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
780: switch(opc) {
781: case 0:
782: /* movzbl */
783: tcg_out_modrm(s, 0xb6 | P_EXT, TCG_REG_ECX, data_reg);
784: break;
785: case 1:
786: /* movzwl */
787: tcg_out_modrm(s, 0xb7 | P_EXT, TCG_REG_ECX, data_reg);
788: break;
789: case 2:
790: tcg_out_mov(s, TCG_REG_ECX, data_reg);
791: break;
792: }
793: tcg_out8(s, 0x6a); /* push Ib */
794: tcg_out8(s, mem_index);
795: tcg_out8(s, 0xe8);
796: tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] -
797: (tcg_target_long)s->code_ptr - 4);
798: tcg_out_addi(s, TCG_REG_ESP, 4);
799: }
800: #endif
801:
802: /* jmp label2 */
803: tcg_out8(s, 0xeb);
804: label2_ptr = s->code_ptr;
805: s->code_ptr++;
806:
807: /* label1: */
808: *label1_ptr = s->code_ptr - label1_ptr - 1;
809:
810: /* add x(r1), r0 */
811: tcg_out_modrm_offset(s, 0x03, r0, r1, offsetof(CPUTLBEntry, addend) -
812: offsetof(CPUTLBEntry, addr_write));
813: #else
814: r0 = addr_reg;
815: #endif
816:
817: #ifdef TARGET_WORDS_BIGENDIAN
818: bswap = 1;
819: #else
820: bswap = 0;
821: #endif
822: switch(opc) {
823: case 0:
824: /* movb */
1.1.1.3 ! root 825: tcg_out_modrm_offset(s, 0x88, data_reg, r0, GUEST_BASE);
1.1 root 826: break;
827: case 1:
828: if (bswap) {
829: tcg_out_mov(s, r1, data_reg);
830: tcg_out8(s, 0x66); /* rolw $8, %ecx */
831: tcg_out_modrm(s, 0xc1, 0, r1);
832: tcg_out8(s, 8);
833: data_reg = r1;
834: }
835: /* movw */
836: tcg_out8(s, 0x66);
1.1.1.3 ! root 837: tcg_out_modrm_offset(s, 0x89, data_reg, r0, GUEST_BASE);
1.1 root 838: break;
839: case 2:
840: if (bswap) {
841: tcg_out_mov(s, r1, data_reg);
842: /* bswap data_reg */
843: tcg_out_opc(s, (0xc8 + r1) | P_EXT);
844: data_reg = r1;
845: }
846: /* movl */
1.1.1.3 ! root 847: tcg_out_modrm_offset(s, 0x89, data_reg, r0, GUEST_BASE);
1.1 root 848: break;
849: case 3:
850: if (bswap) {
851: tcg_out_mov(s, r1, data_reg2);
852: /* bswap data_reg */
853: tcg_out_opc(s, (0xc8 + r1) | P_EXT);
1.1.1.3 ! root 854: tcg_out_modrm_offset(s, 0x89, r1, r0, GUEST_BASE);
1.1 root 855: tcg_out_mov(s, r1, data_reg);
856: /* bswap data_reg */
857: tcg_out_opc(s, (0xc8 + r1) | P_EXT);
1.1.1.3 ! root 858: tcg_out_modrm_offset(s, 0x89, r1, r0, GUEST_BASE + 4);
1.1 root 859: } else {
1.1.1.3 ! root 860: tcg_out_modrm_offset(s, 0x89, data_reg, r0, GUEST_BASE);
! 861: tcg_out_modrm_offset(s, 0x89, data_reg2, r0, GUEST_BASE + 4);
1.1 root 862: }
863: break;
864: default:
865: tcg_abort();
866: }
867:
868: #if defined(CONFIG_SOFTMMU)
869: /* label2: */
870: *label2_ptr = s->code_ptr - label2_ptr - 1;
871: #endif
872: }
873:
874: static inline void tcg_out_op(TCGContext *s, int opc,
875: const TCGArg *args, const int *const_args)
876: {
877: int c;
878:
879: switch(opc) {
880: case INDEX_op_exit_tb:
881: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EAX, args[0]);
882: tcg_out8(s, 0xe9); /* jmp tb_ret_addr */
883: tcg_out32(s, tb_ret_addr - s->code_ptr - 4);
884: break;
885: case INDEX_op_goto_tb:
886: if (s->tb_jmp_offset) {
887: /* direct jump method */
888: tcg_out8(s, 0xe9); /* jmp im */
889: s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
890: tcg_out32(s, 0);
891: } else {
892: /* indirect jump method */
893: /* jmp Ev */
894: tcg_out_modrm_offset(s, 0xff, 4, -1,
895: (tcg_target_long)(s->tb_next + args[0]));
896: }
897: s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
898: break;
899: case INDEX_op_call:
900: if (const_args[0]) {
901: tcg_out8(s, 0xe8);
902: tcg_out32(s, args[0] - (tcg_target_long)s->code_ptr - 4);
903: } else {
904: tcg_out_modrm(s, 0xff, 2, args[0]);
905: }
906: break;
907: case INDEX_op_jmp:
908: if (const_args[0]) {
909: tcg_out8(s, 0xe9);
910: tcg_out32(s, args[0] - (tcg_target_long)s->code_ptr - 4);
911: } else {
912: tcg_out_modrm(s, 0xff, 4, args[0]);
913: }
914: break;
915: case INDEX_op_br:
916: tcg_out_jxx(s, JCC_JMP, args[0]);
917: break;
918: case INDEX_op_movi_i32:
919: tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
920: break;
921: case INDEX_op_ld8u_i32:
922: /* movzbl */
923: tcg_out_modrm_offset(s, 0xb6 | P_EXT, args[0], args[1], args[2]);
924: break;
925: case INDEX_op_ld8s_i32:
926: /* movsbl */
927: tcg_out_modrm_offset(s, 0xbe | P_EXT, args[0], args[1], args[2]);
928: break;
929: case INDEX_op_ld16u_i32:
930: /* movzwl */
931: tcg_out_modrm_offset(s, 0xb7 | P_EXT, args[0], args[1], args[2]);
932: break;
933: case INDEX_op_ld16s_i32:
934: /* movswl */
935: tcg_out_modrm_offset(s, 0xbf | P_EXT, args[0], args[1], args[2]);
936: break;
937: case INDEX_op_ld_i32:
938: /* movl */
939: tcg_out_modrm_offset(s, 0x8b, args[0], args[1], args[2]);
940: break;
941: case INDEX_op_st8_i32:
942: /* movb */
943: tcg_out_modrm_offset(s, 0x88, args[0], args[1], args[2]);
944: break;
945: case INDEX_op_st16_i32:
946: /* movw */
947: tcg_out8(s, 0x66);
948: tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]);
949: break;
950: case INDEX_op_st_i32:
951: /* movl */
952: tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]);
953: break;
954: case INDEX_op_sub_i32:
955: c = ARITH_SUB;
956: goto gen_arith;
957: case INDEX_op_and_i32:
958: c = ARITH_AND;
959: goto gen_arith;
960: case INDEX_op_or_i32:
961: c = ARITH_OR;
962: goto gen_arith;
963: case INDEX_op_xor_i32:
964: c = ARITH_XOR;
965: goto gen_arith;
966: case INDEX_op_add_i32:
967: c = ARITH_ADD;
968: gen_arith:
969: if (const_args[2]) {
1.1.1.3 ! root 970: tgen_arithi(s, c, args[0], args[2], 0);
1.1 root 971: } else {
972: tcg_out_modrm(s, 0x01 | (c << 3), args[2], args[0]);
973: }
974: break;
975: case INDEX_op_mul_i32:
976: if (const_args[2]) {
977: int32_t val;
978: val = args[2];
979: if (val == (int8_t)val) {
980: tcg_out_modrm(s, 0x6b, args[0], args[0]);
981: tcg_out8(s, val);
982: } else {
983: tcg_out_modrm(s, 0x69, args[0], args[0]);
984: tcg_out32(s, val);
985: }
986: } else {
987: tcg_out_modrm(s, 0xaf | P_EXT, args[0], args[2]);
988: }
989: break;
990: case INDEX_op_mulu2_i32:
991: tcg_out_modrm(s, 0xf7, 4, args[3]);
992: break;
993: case INDEX_op_div2_i32:
994: tcg_out_modrm(s, 0xf7, 7, args[4]);
995: break;
996: case INDEX_op_divu2_i32:
997: tcg_out_modrm(s, 0xf7, 6, args[4]);
998: break;
999: case INDEX_op_shl_i32:
1000: c = SHIFT_SHL;
1001: gen_shift32:
1002: if (const_args[2]) {
1003: if (args[2] == 1) {
1004: tcg_out_modrm(s, 0xd1, c, args[0]);
1005: } else {
1006: tcg_out_modrm(s, 0xc1, c, args[0]);
1007: tcg_out8(s, args[2]);
1008: }
1009: } else {
1010: tcg_out_modrm(s, 0xd3, c, args[0]);
1011: }
1012: break;
1013: case INDEX_op_shr_i32:
1014: c = SHIFT_SHR;
1015: goto gen_shift32;
1016: case INDEX_op_sar_i32:
1017: c = SHIFT_SAR;
1018: goto gen_shift32;
1.1.1.2 root 1019: case INDEX_op_rotl_i32:
1020: c = SHIFT_ROL;
1021: goto gen_shift32;
1022: case INDEX_op_rotr_i32:
1023: c = SHIFT_ROR;
1024: goto gen_shift32;
1025:
1.1 root 1026: case INDEX_op_add2_i32:
1027: if (const_args[4])
1.1.1.3 ! root 1028: tgen_arithi(s, ARITH_ADD, args[0], args[4], 1);
1.1 root 1029: else
1030: tcg_out_modrm(s, 0x01 | (ARITH_ADD << 3), args[4], args[0]);
1031: if (const_args[5])
1.1.1.3 ! root 1032: tgen_arithi(s, ARITH_ADC, args[1], args[5], 1);
1.1 root 1033: else
1034: tcg_out_modrm(s, 0x01 | (ARITH_ADC << 3), args[5], args[1]);
1035: break;
1036: case INDEX_op_sub2_i32:
1037: if (const_args[4])
1.1.1.3 ! root 1038: tgen_arithi(s, ARITH_SUB, args[0], args[4], 1);
1.1 root 1039: else
1040: tcg_out_modrm(s, 0x01 | (ARITH_SUB << 3), args[4], args[0]);
1041: if (const_args[5])
1.1.1.3 ! root 1042: tgen_arithi(s, ARITH_SBB, args[1], args[5], 1);
1.1 root 1043: else
1044: tcg_out_modrm(s, 0x01 | (ARITH_SBB << 3), args[5], args[1]);
1045: break;
1046: case INDEX_op_brcond_i32:
1047: tcg_out_brcond(s, args[2], args[0], args[1], const_args[1], args[3]);
1048: break;
1049: case INDEX_op_brcond2_i32:
1050: tcg_out_brcond2(s, args, const_args);
1051: break;
1052:
1.1.1.2 root 1053: case INDEX_op_bswap16_i32:
1054: tcg_out8(s, 0x66);
1055: tcg_out_modrm(s, 0xc1, SHIFT_ROL, args[0]);
1056: tcg_out8(s, 8);
1057: break;
1058: case INDEX_op_bswap32_i32:
1059: tcg_out_opc(s, (0xc8 + args[0]) | P_EXT);
1060: break;
1061:
1062: case INDEX_op_neg_i32:
1063: tcg_out_modrm(s, 0xf7, 3, args[0]);
1064: break;
1065:
1066: case INDEX_op_not_i32:
1067: tcg_out_modrm(s, 0xf7, 2, args[0]);
1068: break;
1069:
1070: case INDEX_op_ext8s_i32:
1071: tcg_out_modrm(s, 0xbe | P_EXT, args[0], args[1]);
1072: break;
1073: case INDEX_op_ext16s_i32:
1074: tcg_out_modrm(s, 0xbf | P_EXT, args[0], args[1]);
1075: break;
1.1.1.3 ! root 1076: case INDEX_op_ext8u_i32:
! 1077: tcg_out_modrm(s, 0xb6 | P_EXT, args[0], args[1]);
! 1078: break;
! 1079: case INDEX_op_ext16u_i32:
! 1080: tcg_out_modrm(s, 0xb7 | P_EXT, args[0], args[1]);
! 1081: break;
1.1.1.2 root 1082:
1.1 root 1083: case INDEX_op_qemu_ld8u:
1084: tcg_out_qemu_ld(s, args, 0);
1085: break;
1086: case INDEX_op_qemu_ld8s:
1087: tcg_out_qemu_ld(s, args, 0 | 4);
1088: break;
1089: case INDEX_op_qemu_ld16u:
1090: tcg_out_qemu_ld(s, args, 1);
1091: break;
1092: case INDEX_op_qemu_ld16s:
1093: tcg_out_qemu_ld(s, args, 1 | 4);
1094: break;
1095: case INDEX_op_qemu_ld32u:
1096: tcg_out_qemu_ld(s, args, 2);
1097: break;
1098: case INDEX_op_qemu_ld64:
1099: tcg_out_qemu_ld(s, args, 3);
1100: break;
1101:
1102: case INDEX_op_qemu_st8:
1103: tcg_out_qemu_st(s, args, 0);
1104: break;
1105: case INDEX_op_qemu_st16:
1106: tcg_out_qemu_st(s, args, 1);
1107: break;
1108: case INDEX_op_qemu_st32:
1109: tcg_out_qemu_st(s, args, 2);
1110: break;
1111: case INDEX_op_qemu_st64:
1112: tcg_out_qemu_st(s, args, 3);
1113: break;
1114:
1115: default:
1116: tcg_abort();
1117: }
1118: }
1119:
1120: static const TCGTargetOpDef x86_op_defs[] = {
1121: { INDEX_op_exit_tb, { } },
1122: { INDEX_op_goto_tb, { } },
1123: { INDEX_op_call, { "ri" } },
1124: { INDEX_op_jmp, { "ri" } },
1125: { INDEX_op_br, { } },
1126: { INDEX_op_mov_i32, { "r", "r" } },
1127: { INDEX_op_movi_i32, { "r" } },
1128: { INDEX_op_ld8u_i32, { "r", "r" } },
1129: { INDEX_op_ld8s_i32, { "r", "r" } },
1130: { INDEX_op_ld16u_i32, { "r", "r" } },
1131: { INDEX_op_ld16s_i32, { "r", "r" } },
1132: { INDEX_op_ld_i32, { "r", "r" } },
1133: { INDEX_op_st8_i32, { "q", "r" } },
1134: { INDEX_op_st16_i32, { "r", "r" } },
1135: { INDEX_op_st_i32, { "r", "r" } },
1136:
1137: { INDEX_op_add_i32, { "r", "0", "ri" } },
1138: { INDEX_op_sub_i32, { "r", "0", "ri" } },
1139: { INDEX_op_mul_i32, { "r", "0", "ri" } },
1140: { INDEX_op_mulu2_i32, { "a", "d", "a", "r" } },
1141: { INDEX_op_div2_i32, { "a", "d", "0", "1", "r" } },
1142: { INDEX_op_divu2_i32, { "a", "d", "0", "1", "r" } },
1143: { INDEX_op_and_i32, { "r", "0", "ri" } },
1144: { INDEX_op_or_i32, { "r", "0", "ri" } },
1145: { INDEX_op_xor_i32, { "r", "0", "ri" } },
1146:
1147: { INDEX_op_shl_i32, { "r", "0", "ci" } },
1148: { INDEX_op_shr_i32, { "r", "0", "ci" } },
1149: { INDEX_op_sar_i32, { "r", "0", "ci" } },
1.1.1.2 root 1150: { INDEX_op_rotl_i32, { "r", "0", "ci" } },
1151: { INDEX_op_rotr_i32, { "r", "0", "ci" } },
1.1 root 1152:
1153: { INDEX_op_brcond_i32, { "r", "ri" } },
1154:
1155: { INDEX_op_add2_i32, { "r", "r", "0", "1", "ri", "ri" } },
1156: { INDEX_op_sub2_i32, { "r", "r", "0", "1", "ri", "ri" } },
1157: { INDEX_op_brcond2_i32, { "r", "r", "ri", "ri" } },
1158:
1.1.1.2 root 1159: { INDEX_op_bswap16_i32, { "r", "0" } },
1160: { INDEX_op_bswap32_i32, { "r", "0" } },
1161:
1162: { INDEX_op_neg_i32, { "r", "0" } },
1163:
1164: { INDEX_op_not_i32, { "r", "0" } },
1165:
1166: { INDEX_op_ext8s_i32, { "r", "q" } },
1167: { INDEX_op_ext16s_i32, { "r", "r" } },
1.1.1.3 ! root 1168: { INDEX_op_ext8u_i32, { "r", "q"} },
! 1169: { INDEX_op_ext16u_i32, { "r", "r"} },
1.1.1.2 root 1170:
1.1 root 1171: #if TARGET_LONG_BITS == 32
1172: { INDEX_op_qemu_ld8u, { "r", "L" } },
1173: { INDEX_op_qemu_ld8s, { "r", "L" } },
1174: { INDEX_op_qemu_ld16u, { "r", "L" } },
1175: { INDEX_op_qemu_ld16s, { "r", "L" } },
1176: { INDEX_op_qemu_ld32u, { "r", "L" } },
1177: { INDEX_op_qemu_ld64, { "r", "r", "L" } },
1178:
1179: { INDEX_op_qemu_st8, { "cb", "L" } },
1180: { INDEX_op_qemu_st16, { "L", "L" } },
1181: { INDEX_op_qemu_st32, { "L", "L" } },
1182: { INDEX_op_qemu_st64, { "L", "L", "L" } },
1183: #else
1184: { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
1185: { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
1186: { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
1187: { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
1188: { INDEX_op_qemu_ld32u, { "r", "L", "L" } },
1189: { INDEX_op_qemu_ld64, { "r", "r", "L", "L" } },
1190:
1191: { INDEX_op_qemu_st8, { "cb", "L", "L" } },
1192: { INDEX_op_qemu_st16, { "L", "L", "L" } },
1193: { INDEX_op_qemu_st32, { "L", "L", "L" } },
1194: { INDEX_op_qemu_st64, { "L", "L", "L", "L" } },
1195: #endif
1196: { -1 },
1197: };
1198:
1199: static int tcg_target_callee_save_regs[] = {
1200: /* TCG_REG_EBP, */ /* currently used for the global env, so no
1201: need to save */
1202: TCG_REG_EBX,
1203: TCG_REG_ESI,
1204: TCG_REG_EDI,
1205: };
1206:
1207: static inline void tcg_out_push(TCGContext *s, int reg)
1208: {
1209: tcg_out_opc(s, 0x50 + reg);
1210: }
1211:
1212: static inline void tcg_out_pop(TCGContext *s, int reg)
1213: {
1214: tcg_out_opc(s, 0x58 + reg);
1215: }
1216:
1217: /* Generate global QEMU prologue and epilogue code */
1218: void tcg_target_qemu_prologue(TCGContext *s)
1219: {
1220: int i, frame_size, push_size, stack_addend;
1221:
1222: /* TB prologue */
1223: /* save all callee saved registers */
1224: for(i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
1225: tcg_out_push(s, tcg_target_callee_save_regs[i]);
1226: }
1227: /* reserve some stack space */
1228: push_size = 4 + ARRAY_SIZE(tcg_target_callee_save_regs) * 4;
1229: frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE;
1230: frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1231: ~(TCG_TARGET_STACK_ALIGN - 1);
1232: stack_addend = frame_size - push_size;
1233: tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
1234:
1235: tcg_out_modrm(s, 0xff, 4, TCG_REG_EAX); /* jmp *%eax */
1236:
1237: /* TB epilogue */
1238: tb_ret_addr = s->code_ptr;
1239: tcg_out_addi(s, TCG_REG_ESP, stack_addend);
1240: for(i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
1241: tcg_out_pop(s, tcg_target_callee_save_regs[i]);
1242: }
1243: tcg_out8(s, 0xc3); /* ret */
1244: }
1245:
1246: void tcg_target_init(TCGContext *s)
1247: {
1248: /* fail safe */
1249: if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
1250: tcg_abort();
1251:
1252: tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xff);
1253: tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1254: (1 << TCG_REG_EAX) |
1255: (1 << TCG_REG_EDX) |
1256: (1 << TCG_REG_ECX));
1257:
1258: tcg_regset_clear(s->reserved_regs);
1259: tcg_regset_set_reg(s->reserved_regs, TCG_REG_ESP);
1260:
1261: tcg_add_target_add_op_defs(x86_op_defs);
1262: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.