|
|
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:
279: static inline void tgen_arithi(TCGContext *s, int c, int r0, int32_t val)
280: {
281: if (val == (int8_t)val) {
282: tcg_out_modrm(s, 0x83, c, r0);
283: tcg_out8(s, val);
284: } else {
285: tcg_out_modrm(s, 0x81, c, r0);
286: tcg_out32(s, val);
287: }
288: }
289:
290: static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
291: {
292: if (val != 0)
293: tgen_arithi(s, ARITH_ADD, reg, val);
294: }
295:
296: static void tcg_out_jxx(TCGContext *s, int opc, int label_index)
297: {
298: int32_t val, val1;
299: TCGLabel *l = &s->labels[label_index];
300:
301: if (l->has_value) {
302: val = l->u.value - (tcg_target_long)s->code_ptr;
303: val1 = val - 2;
304: if ((int8_t)val1 == val1) {
305: if (opc == -1)
306: tcg_out8(s, 0xeb);
307: else
308: tcg_out8(s, 0x70 + opc);
309: tcg_out8(s, val1);
310: } else {
311: if (opc == -1) {
312: tcg_out8(s, 0xe9);
313: tcg_out32(s, val - 5);
314: } else {
315: tcg_out8(s, 0x0f);
316: tcg_out8(s, 0x80 + opc);
317: tcg_out32(s, val - 6);
318: }
319: }
320: } else {
321: if (opc == -1) {
322: tcg_out8(s, 0xe9);
323: } else {
324: tcg_out8(s, 0x0f);
325: tcg_out8(s, 0x80 + opc);
326: }
327: tcg_out_reloc(s, s->code_ptr, R_386_PC32, label_index, -4);
328: s->code_ptr += 4;
329: }
330: }
331:
332: static void tcg_out_brcond(TCGContext *s, int cond,
333: TCGArg arg1, TCGArg arg2, int const_arg2,
334: int label_index)
335: {
336: if (const_arg2) {
337: if (arg2 == 0) {
338: /* test r, r */
339: tcg_out_modrm(s, 0x85, arg1, arg1);
340: } else {
341: tgen_arithi(s, ARITH_CMP, arg1, arg2);
342: }
343: } else {
344: tcg_out_modrm(s, 0x01 | (ARITH_CMP << 3), arg2, arg1);
345: }
346: tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index);
347: }
348:
349: /* XXX: we implement it at the target level to avoid having to
350: handle cross basic blocks temporaries */
351: static void tcg_out_brcond2(TCGContext *s,
352: const TCGArg *args, const int *const_args)
353: {
354: int label_next;
355: label_next = gen_new_label();
356: switch(args[4]) {
357: case TCG_COND_EQ:
358: tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2], label_next);
359: tcg_out_brcond(s, TCG_COND_EQ, args[1], args[3], const_args[3], args[5]);
360: break;
361: case TCG_COND_NE:
362: tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2], args[5]);
363: tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], args[5]);
364: break;
365: case TCG_COND_LT:
366: tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3], args[5]);
367: tcg_out_jxx(s, JCC_JNE, label_next);
368: tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2], args[5]);
369: break;
370: case TCG_COND_LE:
371: tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3], args[5]);
372: tcg_out_jxx(s, JCC_JNE, label_next);
373: tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2], args[5]);
374: break;
375: case TCG_COND_GT:
376: tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3], args[5]);
377: tcg_out_jxx(s, JCC_JNE, label_next);
378: tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2], args[5]);
379: break;
380: case TCG_COND_GE:
381: tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3], args[5]);
382: tcg_out_jxx(s, JCC_JNE, label_next);
383: tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2], args[5]);
384: break;
385: case TCG_COND_LTU:
386: tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3], args[5]);
387: tcg_out_jxx(s, JCC_JNE, label_next);
388: tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2], args[5]);
389: break;
390: case TCG_COND_LEU:
391: tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3], args[5]);
392: tcg_out_jxx(s, JCC_JNE, label_next);
393: tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2], args[5]);
394: break;
395: case TCG_COND_GTU:
396: tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3], args[5]);
397: tcg_out_jxx(s, JCC_JNE, label_next);
398: tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2], args[5]);
399: break;
400: case TCG_COND_GEU:
401: tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3], args[5]);
402: tcg_out_jxx(s, JCC_JNE, label_next);
403: tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2], args[5]);
404: break;
405: default:
406: tcg_abort();
407: }
408: tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);
409: }
410:
411: #if defined(CONFIG_SOFTMMU)
412:
413: #include "../../softmmu_defs.h"
414:
415: static void *qemu_ld_helpers[4] = {
416: __ldb_mmu,
417: __ldw_mmu,
418: __ldl_mmu,
419: __ldq_mmu,
420: };
421:
422: static void *qemu_st_helpers[4] = {
423: __stb_mmu,
424: __stw_mmu,
425: __stl_mmu,
426: __stq_mmu,
427: };
428: #endif
429:
430: /* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and
431: EAX. It will be useful once fixed registers globals are less
432: common. */
433: static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
434: int opc)
435: {
436: int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
437: #if defined(CONFIG_SOFTMMU)
438: uint8_t *label1_ptr, *label2_ptr;
439: #endif
440: #if TARGET_LONG_BITS == 64
441: #if defined(CONFIG_SOFTMMU)
442: uint8_t *label3_ptr;
443: #endif
444: int addr_reg2;
445: #endif
446:
447: data_reg = *args++;
448: if (opc == 3)
449: data_reg2 = *args++;
450: else
451: data_reg2 = 0;
452: addr_reg = *args++;
453: #if TARGET_LONG_BITS == 64
454: addr_reg2 = *args++;
455: #endif
456: mem_index = *args;
457: s_bits = opc & 3;
458:
459: r0 = TCG_REG_EAX;
460: r1 = TCG_REG_EDX;
461:
462: #if defined(CONFIG_SOFTMMU)
463: tcg_out_mov(s, r1, addr_reg);
464:
465: tcg_out_mov(s, r0, addr_reg);
466:
467: tcg_out_modrm(s, 0xc1, 5, r1); /* shr $x, r1 */
468: tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
469:
470: tcg_out_modrm(s, 0x81, 4, r0); /* andl $x, r0 */
471: tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
472:
473: tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */
474: tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
475:
476: tcg_out_opc(s, 0x8d); /* lea offset(r1, %ebp), r1 */
477: tcg_out8(s, 0x80 | (r1 << 3) | 0x04);
478: tcg_out8(s, (5 << 3) | r1);
479: tcg_out32(s, offsetof(CPUState, tlb_table[mem_index][0].addr_read));
480:
481: /* cmp 0(r1), r0 */
482: tcg_out_modrm_offset(s, 0x3b, r0, r1, 0);
483:
484: tcg_out_mov(s, r0, addr_reg);
485:
486: #if TARGET_LONG_BITS == 32
487: /* je label1 */
488: tcg_out8(s, 0x70 + JCC_JE);
489: label1_ptr = s->code_ptr;
490: s->code_ptr++;
491: #else
492: /* jne label3 */
493: tcg_out8(s, 0x70 + JCC_JNE);
494: label3_ptr = s->code_ptr;
495: s->code_ptr++;
496:
497: /* cmp 4(r1), addr_reg2 */
498: tcg_out_modrm_offset(s, 0x3b, addr_reg2, r1, 4);
499:
500: /* je label1 */
501: tcg_out8(s, 0x70 + JCC_JE);
502: label1_ptr = s->code_ptr;
503: s->code_ptr++;
504:
505: /* label3: */
506: *label3_ptr = s->code_ptr - label3_ptr - 1;
507: #endif
508:
509: /* XXX: move that code at the end of the TB */
510: #if TARGET_LONG_BITS == 32
511: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EDX, mem_index);
512: #else
513: tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
514: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
515: #endif
516: tcg_out8(s, 0xe8);
517: tcg_out32(s, (tcg_target_long)qemu_ld_helpers[s_bits] -
518: (tcg_target_long)s->code_ptr - 4);
519:
520: switch(opc) {
521: case 0 | 4:
522: /* movsbl */
523: tcg_out_modrm(s, 0xbe | P_EXT, data_reg, TCG_REG_EAX);
524: break;
525: case 1 | 4:
526: /* movswl */
527: tcg_out_modrm(s, 0xbf | P_EXT, data_reg, TCG_REG_EAX);
528: break;
529: case 0:
530: /* movzbl */
531: tcg_out_modrm(s, 0xb6 | P_EXT, data_reg, TCG_REG_EAX);
532: break;
533: case 1:
534: /* movzwl */
535: tcg_out_modrm(s, 0xb7 | P_EXT, data_reg, TCG_REG_EAX);
536: break;
537: case 2:
538: default:
539: tcg_out_mov(s, data_reg, TCG_REG_EAX);
540: break;
541: case 3:
542: if (data_reg == TCG_REG_EDX) {
543: tcg_out_opc(s, 0x90 + TCG_REG_EDX); /* xchg %edx, %eax */
544: tcg_out_mov(s, data_reg2, TCG_REG_EAX);
545: } else {
546: tcg_out_mov(s, data_reg, TCG_REG_EAX);
547: tcg_out_mov(s, data_reg2, TCG_REG_EDX);
548: }
549: break;
550: }
551:
552: /* jmp label2 */
553: tcg_out8(s, 0xeb);
554: label2_ptr = s->code_ptr;
555: s->code_ptr++;
556:
557: /* label1: */
558: *label1_ptr = s->code_ptr - label1_ptr - 1;
559:
560: /* add x(r1), r0 */
561: tcg_out_modrm_offset(s, 0x03, r0, r1, offsetof(CPUTLBEntry, addend) -
562: offsetof(CPUTLBEntry, addr_read));
563: #else
564: r0 = addr_reg;
565: #endif
566:
567: #ifdef TARGET_WORDS_BIGENDIAN
568: bswap = 1;
569: #else
570: bswap = 0;
571: #endif
572: switch(opc) {
573: case 0:
574: /* movzbl */
575: tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, 0);
576: break;
577: case 0 | 4:
578: /* movsbl */
579: tcg_out_modrm_offset(s, 0xbe | P_EXT, data_reg, r0, 0);
580: break;
581: case 1:
582: /* movzwl */
583: tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, 0);
584: if (bswap) {
585: /* rolw $8, data_reg */
586: tcg_out8(s, 0x66);
587: tcg_out_modrm(s, 0xc1, 0, data_reg);
588: tcg_out8(s, 8);
589: }
590: break;
591: case 1 | 4:
592: /* movswl */
593: tcg_out_modrm_offset(s, 0xbf | P_EXT, data_reg, r0, 0);
594: if (bswap) {
595: /* rolw $8, data_reg */
596: tcg_out8(s, 0x66);
597: tcg_out_modrm(s, 0xc1, 0, data_reg);
598: tcg_out8(s, 8);
599:
600: /* movswl data_reg, data_reg */
601: tcg_out_modrm(s, 0xbf | P_EXT, data_reg, data_reg);
602: }
603: break;
604: case 2:
605: /* movl (r0), data_reg */
606: tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 0);
607: if (bswap) {
608: /* bswap */
609: tcg_out_opc(s, (0xc8 + data_reg) | P_EXT);
610: }
611: break;
612: case 3:
613: /* XXX: could be nicer */
614: if (r0 == data_reg) {
615: r1 = TCG_REG_EDX;
616: if (r1 == data_reg)
617: r1 = TCG_REG_EAX;
618: tcg_out_mov(s, r1, r0);
619: r0 = r1;
620: }
621: if (!bswap) {
622: tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 0);
623: tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, 4);
624: } else {
625: tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 4);
626: tcg_out_opc(s, (0xc8 + data_reg) | P_EXT);
627:
628: tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, 0);
629: /* bswap */
630: tcg_out_opc(s, (0xc8 + data_reg2) | P_EXT);
631: }
632: break;
633: default:
634: tcg_abort();
635: }
636:
637: #if defined(CONFIG_SOFTMMU)
638: /* label2: */
639: *label2_ptr = s->code_ptr - label2_ptr - 1;
640: #endif
641: }
642:
643:
644: static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
645: int opc)
646: {
647: int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
648: #if defined(CONFIG_SOFTMMU)
649: uint8_t *label1_ptr, *label2_ptr;
650: #endif
651: #if TARGET_LONG_BITS == 64
652: #if defined(CONFIG_SOFTMMU)
653: uint8_t *label3_ptr;
654: #endif
655: int addr_reg2;
656: #endif
657:
658: data_reg = *args++;
659: if (opc == 3)
660: data_reg2 = *args++;
661: else
662: data_reg2 = 0;
663: addr_reg = *args++;
664: #if TARGET_LONG_BITS == 64
665: addr_reg2 = *args++;
666: #endif
667: mem_index = *args;
668:
669: s_bits = opc;
670:
671: r0 = TCG_REG_EAX;
672: r1 = TCG_REG_EDX;
673:
674: #if defined(CONFIG_SOFTMMU)
675: tcg_out_mov(s, r1, addr_reg);
676:
677: tcg_out_mov(s, r0, addr_reg);
678:
679: tcg_out_modrm(s, 0xc1, 5, r1); /* shr $x, r1 */
680: tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
681:
682: tcg_out_modrm(s, 0x81, 4, r0); /* andl $x, r0 */
683: tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
684:
685: tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */
686: tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
687:
688: tcg_out_opc(s, 0x8d); /* lea offset(r1, %ebp), r1 */
689: tcg_out8(s, 0x80 | (r1 << 3) | 0x04);
690: tcg_out8(s, (5 << 3) | r1);
691: tcg_out32(s, offsetof(CPUState, tlb_table[mem_index][0].addr_write));
692:
693: /* cmp 0(r1), r0 */
694: tcg_out_modrm_offset(s, 0x3b, r0, r1, 0);
695:
696: tcg_out_mov(s, r0, addr_reg);
697:
698: #if TARGET_LONG_BITS == 32
699: /* je label1 */
700: tcg_out8(s, 0x70 + JCC_JE);
701: label1_ptr = s->code_ptr;
702: s->code_ptr++;
703: #else
704: /* jne label3 */
705: tcg_out8(s, 0x70 + JCC_JNE);
706: label3_ptr = s->code_ptr;
707: s->code_ptr++;
708:
709: /* cmp 4(r1), addr_reg2 */
710: tcg_out_modrm_offset(s, 0x3b, addr_reg2, r1, 4);
711:
712: /* je label1 */
713: tcg_out8(s, 0x70 + JCC_JE);
714: label1_ptr = s->code_ptr;
715: s->code_ptr++;
716:
717: /* label3: */
718: *label3_ptr = s->code_ptr - label3_ptr - 1;
719: #endif
720:
721: /* XXX: move that code at the end of the TB */
722: #if TARGET_LONG_BITS == 32
723: if (opc == 3) {
724: tcg_out_mov(s, TCG_REG_EDX, data_reg);
725: tcg_out_mov(s, TCG_REG_ECX, data_reg2);
726: tcg_out8(s, 0x6a); /* push Ib */
727: tcg_out8(s, mem_index);
728: tcg_out8(s, 0xe8);
729: tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] -
730: (tcg_target_long)s->code_ptr - 4);
731: tcg_out_addi(s, TCG_REG_ESP, 4);
732: } else {
733: switch(opc) {
734: case 0:
735: /* movzbl */
736: tcg_out_modrm(s, 0xb6 | P_EXT, TCG_REG_EDX, data_reg);
737: break;
738: case 1:
739: /* movzwl */
740: tcg_out_modrm(s, 0xb7 | P_EXT, TCG_REG_EDX, data_reg);
741: break;
742: case 2:
743: tcg_out_mov(s, TCG_REG_EDX, data_reg);
744: break;
745: }
746: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
747: tcg_out8(s, 0xe8);
748: tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] -
749: (tcg_target_long)s->code_ptr - 4);
750: }
751: #else
752: if (opc == 3) {
753: tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
754: tcg_out8(s, 0x6a); /* push Ib */
755: tcg_out8(s, mem_index);
756: tcg_out_opc(s, 0x50 + data_reg2); /* push */
757: tcg_out_opc(s, 0x50 + data_reg); /* push */
758: tcg_out8(s, 0xe8);
759: tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] -
760: (tcg_target_long)s->code_ptr - 4);
761: tcg_out_addi(s, TCG_REG_ESP, 12);
762: } else {
763: tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
764: switch(opc) {
765: case 0:
766: /* movzbl */
767: tcg_out_modrm(s, 0xb6 | P_EXT, TCG_REG_ECX, data_reg);
768: break;
769: case 1:
770: /* movzwl */
771: tcg_out_modrm(s, 0xb7 | P_EXT, TCG_REG_ECX, data_reg);
772: break;
773: case 2:
774: tcg_out_mov(s, TCG_REG_ECX, data_reg);
775: break;
776: }
777: tcg_out8(s, 0x6a); /* push Ib */
778: tcg_out8(s, mem_index);
779: tcg_out8(s, 0xe8);
780: tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] -
781: (tcg_target_long)s->code_ptr - 4);
782: tcg_out_addi(s, TCG_REG_ESP, 4);
783: }
784: #endif
785:
786: /* jmp label2 */
787: tcg_out8(s, 0xeb);
788: label2_ptr = s->code_ptr;
789: s->code_ptr++;
790:
791: /* label1: */
792: *label1_ptr = s->code_ptr - label1_ptr - 1;
793:
794: /* add x(r1), r0 */
795: tcg_out_modrm_offset(s, 0x03, r0, r1, offsetof(CPUTLBEntry, addend) -
796: offsetof(CPUTLBEntry, addr_write));
797: #else
798: r0 = addr_reg;
799: #endif
800:
801: #ifdef TARGET_WORDS_BIGENDIAN
802: bswap = 1;
803: #else
804: bswap = 0;
805: #endif
806: switch(opc) {
807: case 0:
808: /* movb */
809: tcg_out_modrm_offset(s, 0x88, data_reg, r0, 0);
810: break;
811: case 1:
812: if (bswap) {
813: tcg_out_mov(s, r1, data_reg);
814: tcg_out8(s, 0x66); /* rolw $8, %ecx */
815: tcg_out_modrm(s, 0xc1, 0, r1);
816: tcg_out8(s, 8);
817: data_reg = r1;
818: }
819: /* movw */
820: tcg_out8(s, 0x66);
821: tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0);
822: break;
823: case 2:
824: if (bswap) {
825: tcg_out_mov(s, r1, data_reg);
826: /* bswap data_reg */
827: tcg_out_opc(s, (0xc8 + r1) | P_EXT);
828: data_reg = r1;
829: }
830: /* movl */
831: tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0);
832: break;
833: case 3:
834: if (bswap) {
835: tcg_out_mov(s, r1, data_reg2);
836: /* bswap data_reg */
837: tcg_out_opc(s, (0xc8 + r1) | P_EXT);
838: tcg_out_modrm_offset(s, 0x89, r1, r0, 0);
839: tcg_out_mov(s, r1, data_reg);
840: /* bswap data_reg */
841: tcg_out_opc(s, (0xc8 + r1) | P_EXT);
842: tcg_out_modrm_offset(s, 0x89, r1, r0, 4);
843: } else {
844: tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0);
845: tcg_out_modrm_offset(s, 0x89, data_reg2, r0, 4);
846: }
847: break;
848: default:
849: tcg_abort();
850: }
851:
852: #if defined(CONFIG_SOFTMMU)
853: /* label2: */
854: *label2_ptr = s->code_ptr - label2_ptr - 1;
855: #endif
856: }
857:
858: static inline void tcg_out_op(TCGContext *s, int opc,
859: const TCGArg *args, const int *const_args)
860: {
861: int c;
862:
863: switch(opc) {
864: case INDEX_op_exit_tb:
865: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EAX, args[0]);
866: tcg_out8(s, 0xe9); /* jmp tb_ret_addr */
867: tcg_out32(s, tb_ret_addr - s->code_ptr - 4);
868: break;
869: case INDEX_op_goto_tb:
870: if (s->tb_jmp_offset) {
871: /* direct jump method */
872: tcg_out8(s, 0xe9); /* jmp im */
873: s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
874: tcg_out32(s, 0);
875: } else {
876: /* indirect jump method */
877: /* jmp Ev */
878: tcg_out_modrm_offset(s, 0xff, 4, -1,
879: (tcg_target_long)(s->tb_next + args[0]));
880: }
881: s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
882: break;
883: case INDEX_op_call:
884: if (const_args[0]) {
885: tcg_out8(s, 0xe8);
886: tcg_out32(s, args[0] - (tcg_target_long)s->code_ptr - 4);
887: } else {
888: tcg_out_modrm(s, 0xff, 2, args[0]);
889: }
890: break;
891: case INDEX_op_jmp:
892: if (const_args[0]) {
893: tcg_out8(s, 0xe9);
894: tcg_out32(s, args[0] - (tcg_target_long)s->code_ptr - 4);
895: } else {
896: tcg_out_modrm(s, 0xff, 4, args[0]);
897: }
898: break;
899: case INDEX_op_br:
900: tcg_out_jxx(s, JCC_JMP, args[0]);
901: break;
902: case INDEX_op_movi_i32:
903: tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
904: break;
905: case INDEX_op_ld8u_i32:
906: /* movzbl */
907: tcg_out_modrm_offset(s, 0xb6 | P_EXT, args[0], args[1], args[2]);
908: break;
909: case INDEX_op_ld8s_i32:
910: /* movsbl */
911: tcg_out_modrm_offset(s, 0xbe | P_EXT, args[0], args[1], args[2]);
912: break;
913: case INDEX_op_ld16u_i32:
914: /* movzwl */
915: tcg_out_modrm_offset(s, 0xb7 | P_EXT, args[0], args[1], args[2]);
916: break;
917: case INDEX_op_ld16s_i32:
918: /* movswl */
919: tcg_out_modrm_offset(s, 0xbf | P_EXT, args[0], args[1], args[2]);
920: break;
921: case INDEX_op_ld_i32:
922: /* movl */
923: tcg_out_modrm_offset(s, 0x8b, args[0], args[1], args[2]);
924: break;
925: case INDEX_op_st8_i32:
926: /* movb */
927: tcg_out_modrm_offset(s, 0x88, args[0], args[1], args[2]);
928: break;
929: case INDEX_op_st16_i32:
930: /* movw */
931: tcg_out8(s, 0x66);
932: tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]);
933: break;
934: case INDEX_op_st_i32:
935: /* movl */
936: tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]);
937: break;
938: case INDEX_op_sub_i32:
939: c = ARITH_SUB;
940: goto gen_arith;
941: case INDEX_op_and_i32:
942: c = ARITH_AND;
943: goto gen_arith;
944: case INDEX_op_or_i32:
945: c = ARITH_OR;
946: goto gen_arith;
947: case INDEX_op_xor_i32:
948: c = ARITH_XOR;
949: goto gen_arith;
950: case INDEX_op_add_i32:
951: c = ARITH_ADD;
952: gen_arith:
953: if (const_args[2]) {
954: tgen_arithi(s, c, args[0], args[2]);
955: } else {
956: tcg_out_modrm(s, 0x01 | (c << 3), args[2], args[0]);
957: }
958: break;
959: case INDEX_op_mul_i32:
960: if (const_args[2]) {
961: int32_t val;
962: val = args[2];
963: if (val == (int8_t)val) {
964: tcg_out_modrm(s, 0x6b, args[0], args[0]);
965: tcg_out8(s, val);
966: } else {
967: tcg_out_modrm(s, 0x69, args[0], args[0]);
968: tcg_out32(s, val);
969: }
970: } else {
971: tcg_out_modrm(s, 0xaf | P_EXT, args[0], args[2]);
972: }
973: break;
974: case INDEX_op_mulu2_i32:
975: tcg_out_modrm(s, 0xf7, 4, args[3]);
976: break;
977: case INDEX_op_div2_i32:
978: tcg_out_modrm(s, 0xf7, 7, args[4]);
979: break;
980: case INDEX_op_divu2_i32:
981: tcg_out_modrm(s, 0xf7, 6, args[4]);
982: break;
983: case INDEX_op_shl_i32:
984: c = SHIFT_SHL;
985: gen_shift32:
986: if (const_args[2]) {
987: if (args[2] == 1) {
988: tcg_out_modrm(s, 0xd1, c, args[0]);
989: } else {
990: tcg_out_modrm(s, 0xc1, c, args[0]);
991: tcg_out8(s, args[2]);
992: }
993: } else {
994: tcg_out_modrm(s, 0xd3, c, args[0]);
995: }
996: break;
997: case INDEX_op_shr_i32:
998: c = SHIFT_SHR;
999: goto gen_shift32;
1000: case INDEX_op_sar_i32:
1001: c = SHIFT_SAR;
1002: goto gen_shift32;
1.1.1.2 ! root 1003: case INDEX_op_rotl_i32:
! 1004: c = SHIFT_ROL;
! 1005: goto gen_shift32;
! 1006: case INDEX_op_rotr_i32:
! 1007: c = SHIFT_ROR;
! 1008: goto gen_shift32;
! 1009:
1.1 root 1010: case INDEX_op_add2_i32:
1011: if (const_args[4])
1012: tgen_arithi(s, ARITH_ADD, args[0], args[4]);
1013: else
1014: tcg_out_modrm(s, 0x01 | (ARITH_ADD << 3), args[4], args[0]);
1015: if (const_args[5])
1016: tgen_arithi(s, ARITH_ADC, args[1], args[5]);
1017: else
1018: tcg_out_modrm(s, 0x01 | (ARITH_ADC << 3), args[5], args[1]);
1019: break;
1020: case INDEX_op_sub2_i32:
1021: if (const_args[4])
1022: tgen_arithi(s, ARITH_SUB, args[0], args[4]);
1023: else
1024: tcg_out_modrm(s, 0x01 | (ARITH_SUB << 3), args[4], args[0]);
1025: if (const_args[5])
1026: tgen_arithi(s, ARITH_SBB, args[1], args[5]);
1027: else
1028: tcg_out_modrm(s, 0x01 | (ARITH_SBB << 3), args[5], args[1]);
1029: break;
1030: case INDEX_op_brcond_i32:
1031: tcg_out_brcond(s, args[2], args[0], args[1], const_args[1], args[3]);
1032: break;
1033: case INDEX_op_brcond2_i32:
1034: tcg_out_brcond2(s, args, const_args);
1035: break;
1036:
1.1.1.2 ! root 1037: case INDEX_op_bswap16_i32:
! 1038: tcg_out8(s, 0x66);
! 1039: tcg_out_modrm(s, 0xc1, SHIFT_ROL, args[0]);
! 1040: tcg_out8(s, 8);
! 1041: break;
! 1042: case INDEX_op_bswap32_i32:
! 1043: tcg_out_opc(s, (0xc8 + args[0]) | P_EXT);
! 1044: break;
! 1045:
! 1046: case INDEX_op_neg_i32:
! 1047: tcg_out_modrm(s, 0xf7, 3, args[0]);
! 1048: break;
! 1049:
! 1050: case INDEX_op_not_i32:
! 1051: tcg_out_modrm(s, 0xf7, 2, args[0]);
! 1052: break;
! 1053:
! 1054: case INDEX_op_ext8s_i32:
! 1055: tcg_out_modrm(s, 0xbe | P_EXT, args[0], args[1]);
! 1056: break;
! 1057: case INDEX_op_ext16s_i32:
! 1058: tcg_out_modrm(s, 0xbf | P_EXT, args[0], args[1]);
! 1059: break;
! 1060:
1.1 root 1061: case INDEX_op_qemu_ld8u:
1062: tcg_out_qemu_ld(s, args, 0);
1063: break;
1064: case INDEX_op_qemu_ld8s:
1065: tcg_out_qemu_ld(s, args, 0 | 4);
1066: break;
1067: case INDEX_op_qemu_ld16u:
1068: tcg_out_qemu_ld(s, args, 1);
1069: break;
1070: case INDEX_op_qemu_ld16s:
1071: tcg_out_qemu_ld(s, args, 1 | 4);
1072: break;
1073: case INDEX_op_qemu_ld32u:
1074: tcg_out_qemu_ld(s, args, 2);
1075: break;
1076: case INDEX_op_qemu_ld64:
1077: tcg_out_qemu_ld(s, args, 3);
1078: break;
1079:
1080: case INDEX_op_qemu_st8:
1081: tcg_out_qemu_st(s, args, 0);
1082: break;
1083: case INDEX_op_qemu_st16:
1084: tcg_out_qemu_st(s, args, 1);
1085: break;
1086: case INDEX_op_qemu_st32:
1087: tcg_out_qemu_st(s, args, 2);
1088: break;
1089: case INDEX_op_qemu_st64:
1090: tcg_out_qemu_st(s, args, 3);
1091: break;
1092:
1093: default:
1094: tcg_abort();
1095: }
1096: }
1097:
1098: static const TCGTargetOpDef x86_op_defs[] = {
1099: { INDEX_op_exit_tb, { } },
1100: { INDEX_op_goto_tb, { } },
1101: { INDEX_op_call, { "ri" } },
1102: { INDEX_op_jmp, { "ri" } },
1103: { INDEX_op_br, { } },
1104: { INDEX_op_mov_i32, { "r", "r" } },
1105: { INDEX_op_movi_i32, { "r" } },
1106: { INDEX_op_ld8u_i32, { "r", "r" } },
1107: { INDEX_op_ld8s_i32, { "r", "r" } },
1108: { INDEX_op_ld16u_i32, { "r", "r" } },
1109: { INDEX_op_ld16s_i32, { "r", "r" } },
1110: { INDEX_op_ld_i32, { "r", "r" } },
1111: { INDEX_op_st8_i32, { "q", "r" } },
1112: { INDEX_op_st16_i32, { "r", "r" } },
1113: { INDEX_op_st_i32, { "r", "r" } },
1114:
1115: { INDEX_op_add_i32, { "r", "0", "ri" } },
1116: { INDEX_op_sub_i32, { "r", "0", "ri" } },
1117: { INDEX_op_mul_i32, { "r", "0", "ri" } },
1118: { INDEX_op_mulu2_i32, { "a", "d", "a", "r" } },
1119: { INDEX_op_div2_i32, { "a", "d", "0", "1", "r" } },
1120: { INDEX_op_divu2_i32, { "a", "d", "0", "1", "r" } },
1121: { INDEX_op_and_i32, { "r", "0", "ri" } },
1122: { INDEX_op_or_i32, { "r", "0", "ri" } },
1123: { INDEX_op_xor_i32, { "r", "0", "ri" } },
1124:
1125: { INDEX_op_shl_i32, { "r", "0", "ci" } },
1126: { INDEX_op_shr_i32, { "r", "0", "ci" } },
1127: { INDEX_op_sar_i32, { "r", "0", "ci" } },
1.1.1.2 ! root 1128: { INDEX_op_sar_i32, { "r", "0", "ci" } },
! 1129: { INDEX_op_rotl_i32, { "r", "0", "ci" } },
! 1130: { INDEX_op_rotr_i32, { "r", "0", "ci" } },
1.1 root 1131:
1132: { INDEX_op_brcond_i32, { "r", "ri" } },
1133:
1134: { INDEX_op_add2_i32, { "r", "r", "0", "1", "ri", "ri" } },
1135: { INDEX_op_sub2_i32, { "r", "r", "0", "1", "ri", "ri" } },
1136: { INDEX_op_brcond2_i32, { "r", "r", "ri", "ri" } },
1137:
1.1.1.2 ! root 1138: { INDEX_op_bswap16_i32, { "r", "0" } },
! 1139: { INDEX_op_bswap32_i32, { "r", "0" } },
! 1140:
! 1141: { INDEX_op_neg_i32, { "r", "0" } },
! 1142:
! 1143: { INDEX_op_not_i32, { "r", "0" } },
! 1144:
! 1145: { INDEX_op_ext8s_i32, { "r", "q" } },
! 1146: { INDEX_op_ext16s_i32, { "r", "r" } },
! 1147:
1.1 root 1148: #if TARGET_LONG_BITS == 32
1149: { INDEX_op_qemu_ld8u, { "r", "L" } },
1150: { INDEX_op_qemu_ld8s, { "r", "L" } },
1151: { INDEX_op_qemu_ld16u, { "r", "L" } },
1152: { INDEX_op_qemu_ld16s, { "r", "L" } },
1153: { INDEX_op_qemu_ld32u, { "r", "L" } },
1154: { INDEX_op_qemu_ld64, { "r", "r", "L" } },
1155:
1156: { INDEX_op_qemu_st8, { "cb", "L" } },
1157: { INDEX_op_qemu_st16, { "L", "L" } },
1158: { INDEX_op_qemu_st32, { "L", "L" } },
1159: { INDEX_op_qemu_st64, { "L", "L", "L" } },
1160: #else
1161: { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
1162: { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
1163: { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
1164: { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
1165: { INDEX_op_qemu_ld32u, { "r", "L", "L" } },
1166: { INDEX_op_qemu_ld64, { "r", "r", "L", "L" } },
1167:
1168: { INDEX_op_qemu_st8, { "cb", "L", "L" } },
1169: { INDEX_op_qemu_st16, { "L", "L", "L" } },
1170: { INDEX_op_qemu_st32, { "L", "L", "L" } },
1171: { INDEX_op_qemu_st64, { "L", "L", "L", "L" } },
1172: #endif
1173: { -1 },
1174: };
1175:
1176: static int tcg_target_callee_save_regs[] = {
1177: /* TCG_REG_EBP, */ /* currently used for the global env, so no
1178: need to save */
1179: TCG_REG_EBX,
1180: TCG_REG_ESI,
1181: TCG_REG_EDI,
1182: };
1183:
1184: static inline void tcg_out_push(TCGContext *s, int reg)
1185: {
1186: tcg_out_opc(s, 0x50 + reg);
1187: }
1188:
1189: static inline void tcg_out_pop(TCGContext *s, int reg)
1190: {
1191: tcg_out_opc(s, 0x58 + reg);
1192: }
1193:
1194: /* Generate global QEMU prologue and epilogue code */
1195: void tcg_target_qemu_prologue(TCGContext *s)
1196: {
1197: int i, frame_size, push_size, stack_addend;
1198:
1199: /* TB prologue */
1200: /* save all callee saved registers */
1201: for(i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
1202: tcg_out_push(s, tcg_target_callee_save_regs[i]);
1203: }
1204: /* reserve some stack space */
1205: push_size = 4 + ARRAY_SIZE(tcg_target_callee_save_regs) * 4;
1206: frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE;
1207: frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1208: ~(TCG_TARGET_STACK_ALIGN - 1);
1209: stack_addend = frame_size - push_size;
1210: tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
1211:
1212: tcg_out_modrm(s, 0xff, 4, TCG_REG_EAX); /* jmp *%eax */
1213:
1214: /* TB epilogue */
1215: tb_ret_addr = s->code_ptr;
1216: tcg_out_addi(s, TCG_REG_ESP, stack_addend);
1217: for(i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
1218: tcg_out_pop(s, tcg_target_callee_save_regs[i]);
1219: }
1220: tcg_out8(s, 0xc3); /* ret */
1221: }
1222:
1223: void tcg_target_init(TCGContext *s)
1224: {
1225: /* fail safe */
1226: if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
1227: tcg_abort();
1228:
1229: tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xff);
1230: tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1231: (1 << TCG_REG_EAX) |
1232: (1 << TCG_REG_EDX) |
1233: (1 << TCG_REG_ECX));
1234:
1235: tcg_regset_clear(s->reserved_regs);
1236: tcg_regset_set_reg(s->reserved_regs, TCG_REG_ESP);
1237:
1238: tcg_add_target_add_op_defs(x86_op_defs);
1239: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.