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