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