VirtualBox

source: vbox/trunk/src/recompiler/tcg/x86_64/tcg-target.c@ 37675

最後變更 在這個檔案從37675是 37675,由 vboxsync 提交於 14 年 前

rem: Synced with v0.12.5.

  • 屬性 svn:eol-style 設為 native
檔案大小: 42.2 KB
 
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
26static 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
46static 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,
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,
62};
63
64static 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
73static const int tcg_target_call_oarg_regs[2] = {
74 TCG_REG_RAX,
75 TCG_REG_RDX
76};
77
78static uint8_t *tb_ret_addr;
79
80static 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 */
107static inline int tcg_target_get_call_iarg_regs_count(int flags)
108{
109 return 6;
110}
111
112/* parse target specific constraints */
113static 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 */
172static 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
196#define SHIFT_ROL 0
197#define SHIFT_ROR 1
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
224static 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
237static 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);
247 tcg_out8(s, opc & 0xff);
248}
249
250static 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) */
257static 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 */
306static 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
343static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
344{
345 tcg_out_modrm(s, 0x8b | P_REXW, ret, arg);
346}
347
348static 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
366static void tcg_out_goto(TCGContext *s, int call, uint8_t *target)
367{
368 int32_t disp;
369
370 disp = target - s->code_ptr - 5;
371 if (disp == (target - s->code_ptr - 5)) {
372 tcg_out8(s, call ? 0xe8 : 0xe9);
373 tcg_out32(s, disp);
374 } else {
375 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R10, (tcg_target_long) target);
376 tcg_out_modrm(s, 0xff, call ? 2 : 4, TCG_REG_R10);
377 }
378}
379
380static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
381 int arg1, tcg_target_long arg2)
382{
383 if (type == TCG_TYPE_I32)
384 tcg_out_modrm_offset(s, 0x8b, ret, arg1, arg2); /* movl */
385 else
386 tcg_out_modrm_offset(s, 0x8b | P_REXW, ret, arg1, arg2); /* movq */
387}
388
389static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
390 int arg1, tcg_target_long arg2)
391{
392 if (type == TCG_TYPE_I32)
393 tcg_out_modrm_offset(s, 0x89, arg, arg1, arg2); /* movl */
394 else
395 tcg_out_modrm_offset(s, 0x89 | P_REXW, arg, arg1, arg2); /* movq */
396}
397
398static inline void tgen_arithi32(TCGContext *s, int c, int r0, int32_t val)
399{
400 if ((c == ARITH_ADD && val == 1) || (c == ARITH_SUB && val == -1)) {
401 /* inc */
402 tcg_out_modrm(s, 0xff, 0, r0);
403 } else if ((c == ARITH_ADD && val == -1) || (c == ARITH_SUB && val == 1)) {
404 /* dec */
405 tcg_out_modrm(s, 0xff, 1, r0);
406 } else if (val == (int8_t)val) {
407 tcg_out_modrm(s, 0x83, c, r0);
408 tcg_out8(s, val);
409 } else if (c == ARITH_AND && val == 0xffu) {
410 /* movzbl */
411 tcg_out_modrm(s, 0xb6 | P_EXT | P_REXB, r0, r0);
412 } else if (c == ARITH_AND && val == 0xffffu) {
413 /* movzwl */
414 tcg_out_modrm(s, 0xb7 | P_EXT, r0, r0);
415 } else {
416 tcg_out_modrm(s, 0x81, c, r0);
417 tcg_out32(s, val);
418 }
419}
420
421static inline void tgen_arithi64(TCGContext *s, int c, int r0, int64_t val)
422{
423 if ((c == ARITH_ADD && val == 1) || (c == ARITH_SUB && val == -1)) {
424 /* inc */
425 tcg_out_modrm(s, 0xff | P_REXW, 0, r0);
426 } else if ((c == ARITH_ADD && val == -1) || (c == ARITH_SUB && val == 1)) {
427 /* dec */
428 tcg_out_modrm(s, 0xff | P_REXW, 1, r0);
429 } else if (val == (int8_t)val) {
430 tcg_out_modrm(s, 0x83 | P_REXW, c, r0);
431 tcg_out8(s, val);
432 } else if (c == ARITH_AND && val == 0xffu) {
433 /* movzbl */
434 tcg_out_modrm(s, 0xb6 | P_EXT | P_REXW, r0, r0);
435 } else if (c == ARITH_AND && val == 0xffffu) {
436 /* movzwl */
437 tcg_out_modrm(s, 0xb7 | P_EXT | P_REXW, r0, r0);
438 } else if (c == ARITH_AND && val == 0xffffffffu) {
439 /* 32-bit mov zero extends */
440 tcg_out_modrm(s, 0x8b, r0, r0);
441 } else if (val == (int32_t)val) {
442 tcg_out_modrm(s, 0x81 | P_REXW, c, r0);
443 tcg_out32(s, val);
444 } else if (c == ARITH_AND && val == (uint32_t)val) {
445 tcg_out_modrm(s, 0x81, c, r0);
446 tcg_out32(s, val);
447 } else {
448 tcg_abort();
449 }
450}
451
452static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
453{
454 if (val != 0)
455 tgen_arithi64(s, ARITH_ADD, reg, val);
456}
457
458static void tcg_out_jxx(TCGContext *s, int opc, int label_index)
459{
460 int32_t val, val1;
461 TCGLabel *l = &s->labels[label_index];
462
463 if (l->has_value) {
464 val = l->u.value - (tcg_target_long)s->code_ptr;
465 val1 = val - 2;
466 if ((int8_t)val1 == val1) {
467 if (opc == -1)
468 tcg_out8(s, 0xeb);
469 else
470 tcg_out8(s, 0x70 + opc);
471 tcg_out8(s, val1);
472 } else {
473 if (opc == -1) {
474 tcg_out8(s, 0xe9);
475 tcg_out32(s, val - 5);
476 } else {
477 tcg_out8(s, 0x0f);
478 tcg_out8(s, 0x80 + opc);
479 tcg_out32(s, val - 6);
480 }
481 }
482 } else {
483 if (opc == -1) {
484 tcg_out8(s, 0xe9);
485 } else {
486 tcg_out8(s, 0x0f);
487 tcg_out8(s, 0x80 + opc);
488 }
489 tcg_out_reloc(s, s->code_ptr, R_386_PC32, label_index, -4);
490 s->code_ptr += 4;
491 }
492}
493
494static void tcg_out_brcond(TCGContext *s, int cond,
495 TCGArg arg1, TCGArg arg2, int const_arg2,
496 int label_index, int rexw)
497{
498 if (const_arg2) {
499 if (arg2 == 0) {
500 /* test r, r */
501 tcg_out_modrm(s, 0x85 | rexw, arg1, arg1);
502 } else {
503 if (rexw)
504 tgen_arithi64(s, ARITH_CMP, arg1, arg2);
505 else
506 tgen_arithi32(s, ARITH_CMP, arg1, arg2);
507 }
508 } else {
509 tcg_out_modrm(s, 0x01 | (ARITH_CMP << 3) | rexw, arg2, arg1);
510 }
511 tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index);
512}
513
514#if defined(CONFIG_SOFTMMU)
515
516#include "../../softmmu_defs.h"
517
518static void *qemu_ld_helpers[4] = {
519 __ldb_mmu,
520 __ldw_mmu,
521 __ldl_mmu,
522 __ldq_mmu,
523};
524
525static void *qemu_st_helpers[4] = {
526 __stb_mmu,
527 __stw_mmu,
528 __stl_mmu,
529 __stq_mmu,
530};
531#endif
532
533#if defined(VBOX) && defined(REM_PHYS_ADDR_IN_TLB)
534static void * const vbox_ld_helpers[] = {
535 __ldub_vbox_phys,
536 __lduw_vbox_phys,
537 __ldul_vbox_phys,
538 __ldq_vbox_phys,
539 __ldb_vbox_phys,
540 __ldw_vbox_phys,
541 __ldl_vbox_phys,
542 __ldq_vbox_phys,
543};
544
545static void * const vbox_st_helpers[] = {
546 __stb_vbox_phys,
547 __stw_vbox_phys,
548 __stl_vbox_phys,
549 __stq_vbox_phys
550};
551
552static void tcg_out_vbox_phys_read(TCGContext *s, int index, int addr_reg, int data_reg) {
553 if (addr_reg != TCG_REG_RDI)
554 /* mov addr_reg, %rdi */
555 tcg_out_modrm(s, 0x8b | P_REXW, TCG_REG_RDI, addr_reg);
556
557 tcg_out_goto(s, 1, vbox_ld_helpers[index]);
558 /* mov %rax, data_reg*/
559 tcg_out_modrm(s, 0x8b | P_REXW, data_reg, TCG_REG_RAX);
560}
561
562static void tcg_out_vbox_phys_write(TCGContext *s, int index, int addr_reg, int val_reg) {
563 if (addr_reg != TCG_REG_RDI)
564 /* mov addr_reg, %rdi */
565 tcg_out_modrm(s, 0x8b | P_REXW, TCG_REG_RDI, addr_reg);
566 if (val_reg != TCG_REG_RSI)
567 /* mov addr_reg, %rsi */
568 tcg_out_modrm(s, 0x8b | P_REXW, TCG_REG_RSI, val_reg);
569 tcg_out_goto(s, 1, vbox_st_helpers[index]);
570}
571
572#endif /* VBOX && REM_PHYS_ADDR_IN_TLB */
573
574static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
575 int opc)
576{
577 int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, rexw;
578 int32_t offset;
579#if defined(CONFIG_SOFTMMU)
580 uint8_t *label1_ptr, *label2_ptr;
581#endif
582
583 data_reg = *args++;
584 addr_reg = *args++;
585 mem_index = *args;
586 s_bits = opc & 3;
587
588 r0 = TCG_REG_RDI;
589 r1 = TCG_REG_RSI;
590
591#if TARGET_LONG_BITS == 32
592 rexw = 0;
593#else
594 rexw = P_REXW;
595#endif
596#if defined(CONFIG_SOFTMMU)
597 /* mov */
598 tcg_out_modrm(s, 0x8b | rexw, r1, addr_reg);
599
600 /* mov */
601 tcg_out_modrm(s, 0x8b | rexw, r0, addr_reg);
602
603 tcg_out_modrm(s, 0xc1 | rexw, 5, r1); /* shr $x, r1 */
604 tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
605
606 tcg_out_modrm(s, 0x81 | rexw, 4, r0); /* andl $x, r0 */
607 tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
608
609 tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */
610 tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
611
612 /* lea offset(r1, env), r1 */
613 tcg_out_modrm_offset2(s, 0x8d | P_REXW, r1, r1, TCG_AREG0, 0,
614 offsetof(CPUState, tlb_table[mem_index][0].addr_read));
615
616 /* cmp 0(r1), r0 */
617 tcg_out_modrm_offset(s, 0x3b | rexw, r0, r1, 0);
618
619 /* mov */
620 tcg_out_modrm(s, 0x8b | rexw, r0, addr_reg);
621
622 /* je label1 */
623 tcg_out8(s, 0x70 + JCC_JE);
624 label1_ptr = s->code_ptr;
625 s->code_ptr++;
626
627 /* XXX: move that code at the end of the TB */
628 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RSI, mem_index);
629 tcg_out_goto(s, 1, qemu_ld_helpers[s_bits]);
630
631 switch(opc) {
632 case 0 | 4:
633 /* movsbq */
634 tcg_out_modrm(s, 0xbe | P_EXT | P_REXW, data_reg, TCG_REG_RAX);
635 break;
636 case 1 | 4:
637 /* movswq */
638 tcg_out_modrm(s, 0xbf | P_EXT | P_REXW, data_reg, TCG_REG_RAX);
639 break;
640 case 2 | 4:
641 /* movslq */
642 tcg_out_modrm(s, 0x63 | P_REXW, data_reg, TCG_REG_RAX);
643 break;
644 case 0:
645 /* movzbq */
646 tcg_out_modrm(s, 0xb6 | P_EXT | P_REXW, data_reg, TCG_REG_RAX);
647 break;
648 case 1:
649 /* movzwq */
650 tcg_out_modrm(s, 0xb7 | P_EXT | P_REXW, data_reg, TCG_REG_RAX);
651 break;
652 case 2:
653 default:
654 /* movl */
655 tcg_out_modrm(s, 0x8b, data_reg, TCG_REG_RAX);
656 break;
657 case 3:
658 tcg_out_mov(s, data_reg, TCG_REG_RAX);
659 break;
660 }
661
662 /* jmp label2 */
663 tcg_out8(s, 0xeb);
664 label2_ptr = s->code_ptr;
665 s->code_ptr++;
666
667 /* label1: */
668 *label1_ptr = s->code_ptr - label1_ptr - 1;
669
670 /* add x(r1), r0 */
671 tcg_out_modrm_offset(s, 0x03 | P_REXW, r0, r1, offsetof(CPUTLBEntry, addend) -
672 offsetof(CPUTLBEntry, addr_read));
673 offset = 0;
674#else
675 if (GUEST_BASE == (int32_t)GUEST_BASE) {
676 r0 = addr_reg;
677 offset = GUEST_BASE;
678 } else {
679 offset = 0;
680 /* movq $GUEST_BASE, r0 */
681 tcg_out_opc(s, (0xb8 + (r0 & 7)) | P_REXW, 0, r0, 0);
682 tcg_out32(s, GUEST_BASE);
683 tcg_out32(s, GUEST_BASE >> 32);
684 /* addq addr_reg, r0 */
685 tcg_out_modrm(s, 0x01 | P_REXW, addr_reg, r0);
686 }
687#endif
688
689#if !defined(VBOX) || !defined(REM_PHYS_ADDR_IN_TLB)
690
691#ifdef TARGET_WORDS_BIGENDIAN
692 bswap = 1;
693#else
694 bswap = 0;
695#endif
696 switch(opc) {
697 case 0:
698 /* movzbl */
699 tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, offset);
700 break;
701 case 0 | 4:
702 /* movsbX */
703 tcg_out_modrm_offset(s, 0xbe | P_EXT | rexw, data_reg, r0, offset);
704 break;
705 case 1:
706 /* movzwl */
707 tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, offset);
708 if (bswap) {
709 /* rolw $8, data_reg */
710 tcg_out8(s, 0x66);
711 tcg_out_modrm(s, 0xc1, 0, data_reg);
712 tcg_out8(s, 8);
713 }
714 break;
715 case 1 | 4:
716 if (bswap) {
717 /* movzwl */
718 tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, offset);
719 /* rolw $8, data_reg */
720 tcg_out8(s, 0x66);
721 tcg_out_modrm(s, 0xc1, 0, data_reg);
722 tcg_out8(s, 8);
723
724 /* movswX data_reg, data_reg */
725 tcg_out_modrm(s, 0xbf | P_EXT | rexw, data_reg, data_reg);
726 } else {
727 /* movswX */
728 tcg_out_modrm_offset(s, 0xbf | P_EXT | rexw, data_reg, r0, offset);
729 }
730 break;
731 case 2:
732 /* movl (r0), data_reg */
733 tcg_out_modrm_offset(s, 0x8b, data_reg, r0, offset);
734 if (bswap) {
735 /* bswap */
736 tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0);
737 }
738 break;
739 case 2 | 4:
740 if (bswap) {
741 /* movl (r0), data_reg */
742 tcg_out_modrm_offset(s, 0x8b, data_reg, r0, offset);
743 /* bswap */
744 tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0);
745 /* movslq */
746 tcg_out_modrm(s, 0x63 | P_REXW, data_reg, data_reg);
747 } else {
748 /* movslq */
749 tcg_out_modrm_offset(s, 0x63 | P_REXW, data_reg, r0, offset);
750 }
751 break;
752 case 3:
753 /* movq (r0), data_reg */
754 tcg_out_modrm_offset(s, 0x8b | P_REXW, data_reg, r0, offset);
755 if (bswap) {
756 /* bswap */
757 tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT | P_REXW, 0, data_reg, 0);
758 }
759 break;
760 default:
761 tcg_abort();
762 }
763#else /* VBOX && REM_PHYS_ADDR_IN_TLB */
764 tcg_out_vbox_phys_read(s, opc, r0, data_reg);
765#endif /* VBOX && REM_PHYS_ADDR_IN_TLB */
766
767#if defined(CONFIG_SOFTMMU)
768 /* label2: */
769 *label2_ptr = s->code_ptr - label2_ptr - 1;
770#endif
771}
772
773static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
774 int opc)
775{
776 int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, rexw;
777 int32_t offset;
778#if defined(CONFIG_SOFTMMU)
779 uint8_t *label1_ptr, *label2_ptr;
780#endif
781
782 data_reg = *args++;
783 addr_reg = *args++;
784 mem_index = *args;
785
786 s_bits = opc;
787
788 r0 = TCG_REG_RDI;
789 r1 = TCG_REG_RSI;
790
791#if TARGET_LONG_BITS == 32
792 rexw = 0;
793#else
794 rexw = P_REXW;
795#endif
796#if defined(CONFIG_SOFTMMU)
797 /* mov */
798 tcg_out_modrm(s, 0x8b | rexw, r1, addr_reg);
799
800 /* mov */
801 tcg_out_modrm(s, 0x8b | rexw, r0, addr_reg);
802
803 tcg_out_modrm(s, 0xc1 | rexw, 5, r1); /* shr $x, r1 */
804 tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
805
806 tcg_out_modrm(s, 0x81 | rexw, 4, r0); /* andl $x, r0 */
807 tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
808
809 tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */
810 tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
811
812 /* lea offset(r1, env), r1 */
813 tcg_out_modrm_offset2(s, 0x8d | P_REXW, r1, r1, TCG_AREG0, 0,
814 offsetof(CPUState, tlb_table[mem_index][0].addr_write));
815
816 /* cmp 0(r1), r0 */
817 tcg_out_modrm_offset(s, 0x3b | rexw, r0, r1, 0);
818
819 /* mov */
820 tcg_out_modrm(s, 0x8b | rexw, r0, addr_reg);
821
822 /* je label1 */
823 tcg_out8(s, 0x70 + JCC_JE);
824 label1_ptr = s->code_ptr;
825 s->code_ptr++;
826
827 /* XXX: move that code at the end of the TB */
828 switch(opc) {
829 case 0:
830 /* movzbl */
831 tcg_out_modrm(s, 0xb6 | P_EXT | P_REXB, TCG_REG_RSI, data_reg);
832 break;
833 case 1:
834 /* movzwl */
835 tcg_out_modrm(s, 0xb7 | P_EXT, TCG_REG_RSI, data_reg);
836 break;
837 case 2:
838 /* movl */
839 tcg_out_modrm(s, 0x8b, TCG_REG_RSI, data_reg);
840 break;
841 default:
842 case 3:
843 tcg_out_mov(s, TCG_REG_RSI, data_reg);
844 break;
845 }
846 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, mem_index);
847 tcg_out_goto(s, 1, qemu_st_helpers[s_bits]);
848
849 /* jmp label2 */
850 tcg_out8(s, 0xeb);
851 label2_ptr = s->code_ptr;
852 s->code_ptr++;
853
854 /* label1: */
855 *label1_ptr = s->code_ptr - label1_ptr - 1;
856
857 /* add x(r1), r0 */
858 tcg_out_modrm_offset(s, 0x03 | P_REXW, r0, r1, offsetof(CPUTLBEntry, addend) -
859 offsetof(CPUTLBEntry, addr_write));
860 offset = 0;
861#else
862 if (GUEST_BASE == (int32_t)GUEST_BASE) {
863 r0 = addr_reg;
864 offset = GUEST_BASE;
865 } else {
866 offset = 0;
867 /* movq $GUEST_BASE, r0 */
868 tcg_out_opc(s, (0xb8 + (r0 & 7)) | P_REXW, 0, r0, 0);
869 tcg_out32(s, GUEST_BASE);
870 tcg_out32(s, GUEST_BASE >> 32);
871 /* addq addr_reg, r0 */
872 tcg_out_modrm(s, 0x01 | P_REXW, addr_reg, r0);
873 }
874#endif
875
876#if !defined(VBOX) || !defined(REM_PHYS_ADDR_IN_TLB)
877#ifdef TARGET_WORDS_BIGENDIAN
878 bswap = 1;
879#else
880 bswap = 0;
881#endif
882 switch(opc) {
883 case 0:
884 /* movb */
885 tcg_out_modrm_offset(s, 0x88 | P_REXB, data_reg, r0, offset);
886 break;
887 case 1:
888 if (bswap) {
889 tcg_out_modrm(s, 0x8b, r1, data_reg); /* movl */
890 tcg_out8(s, 0x66); /* rolw $8, %ecx */
891 tcg_out_modrm(s, 0xc1, 0, r1);
892 tcg_out8(s, 8);
893 data_reg = r1;
894 }
895 /* movw */
896 tcg_out8(s, 0x66);
897 tcg_out_modrm_offset(s, 0x89, data_reg, r0, offset);
898 break;
899 case 2:
900 if (bswap) {
901 tcg_out_modrm(s, 0x8b, r1, data_reg); /* movl */
902 /* bswap data_reg */
903 tcg_out_opc(s, (0xc8 + r1) | P_EXT, 0, r1, 0);
904 data_reg = r1;
905 }
906 /* movl */
907 tcg_out_modrm_offset(s, 0x89, data_reg, r0, offset);
908 break;
909 case 3:
910 if (bswap) {
911 tcg_out_mov(s, r1, data_reg);
912 /* bswap data_reg */
913 tcg_out_opc(s, (0xc8 + r1) | P_EXT | P_REXW, 0, r1, 0);
914 data_reg = r1;
915 }
916 /* movq */
917 tcg_out_modrm_offset(s, 0x89 | P_REXW, data_reg, r0, offset);
918 break;
919 default:
920 tcg_abort();
921 }
922#else /* VBOX && REM_PHYS_ADDR_IN_TLB */
923 tcg_out_vbox_phys_write(s, opc, r0, data_reg);
924#endif /* VBOX && REM_PHYS_ADDR_IN_TLB */
925
926#if defined(CONFIG_SOFTMMU)
927 /* label2: */
928 *label2_ptr = s->code_ptr - label2_ptr - 1;
929#endif
930}
931
932static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
933 const int *const_args)
934{
935 int c;
936
937 switch(opc) {
938 case INDEX_op_exit_tb:
939 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RAX, args[0]);
940 tcg_out_goto(s, 0, tb_ret_addr);
941 break;
942 case INDEX_op_goto_tb:
943 if (s->tb_jmp_offset) {
944 /* direct jump method */
945 tcg_out8(s, 0xe9); /* jmp im */
946 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
947 tcg_out32(s, 0);
948 } else {
949 /* indirect jump method */
950 /* jmp Ev */
951#ifndef VBOX
952 tcg_out_modrm_offset(s, 0xff, 4, -1,
953 (tcg_target_long)(s->tb_next +
954 args[0]));
955#else
956 /** @todo: can we clobber RAX here? */ /** @todo r=bird: I bet we cannot now... XXXX */
957 tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_RAX,
958 (tcg_target_long)&(s->tb_next[args[0]]));
959 tcg_out8(s, 0xff); tcg_out8(s, 0x20 | TCG_REG_RAX); /* jmp *(%rax) */
960#endif
961 }
962 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
963 break;
964 case INDEX_op_call:
965 if (const_args[0]) {
966 tcg_out_goto(s, 1, (void *) args[0]);
967 } else {
968 tcg_out_modrm(s, 0xff, 2, args[0]);
969 }
970 break;
971 case INDEX_op_jmp:
972 if (const_args[0]) {
973 tcg_out_goto(s, 0, (void *) args[0]);
974 } else {
975 tcg_out_modrm(s, 0xff, 4, args[0]);
976 }
977 break;
978 case INDEX_op_br:
979 tcg_out_jxx(s, JCC_JMP, args[0]);
980 break;
981 case INDEX_op_movi_i32:
982 tcg_out_movi(s, TCG_TYPE_I32, args[0], (uint32_t)args[1]);
983 break;
984 case INDEX_op_movi_i64:
985 tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
986 break;
987 case INDEX_op_ld8u_i32:
988 case INDEX_op_ld8u_i64:
989 /* movzbl */
990 tcg_out_modrm_offset(s, 0xb6 | P_EXT, args[0], args[1], args[2]);
991 break;
992 case INDEX_op_ld8s_i32:
993 /* movsbl */
994 tcg_out_modrm_offset(s, 0xbe | P_EXT, args[0], args[1], args[2]);
995 break;
996 case INDEX_op_ld8s_i64:
997 /* movsbq */
998 tcg_out_modrm_offset(s, 0xbe | P_EXT | P_REXW, args[0], args[1], args[2]);
999 break;
1000 case INDEX_op_ld16u_i32:
1001 case INDEX_op_ld16u_i64:
1002 /* movzwl */
1003 tcg_out_modrm_offset(s, 0xb7 | P_EXT, args[0], args[1], args[2]);
1004 break;
1005 case INDEX_op_ld16s_i32:
1006 /* movswl */
1007 tcg_out_modrm_offset(s, 0xbf | P_EXT, args[0], args[1], args[2]);
1008 break;
1009 case INDEX_op_ld16s_i64:
1010 /* movswq */
1011 tcg_out_modrm_offset(s, 0xbf | P_EXT | P_REXW, args[0], args[1], args[2]);
1012 break;
1013 case INDEX_op_ld_i32:
1014 case INDEX_op_ld32u_i64:
1015 /* movl */
1016 tcg_out_modrm_offset(s, 0x8b, args[0], args[1], args[2]);
1017 break;
1018 case INDEX_op_ld32s_i64:
1019 /* movslq */
1020 tcg_out_modrm_offset(s, 0x63 | P_REXW, args[0], args[1], args[2]);
1021 break;
1022 case INDEX_op_ld_i64:
1023 /* movq */
1024 tcg_out_modrm_offset(s, 0x8b | P_REXW, args[0], args[1], args[2]);
1025 break;
1026
1027 case INDEX_op_st8_i32:
1028 case INDEX_op_st8_i64:
1029 /* movb */
1030 tcg_out_modrm_offset(s, 0x88 | P_REXB, args[0], args[1], args[2]);
1031 break;
1032 case INDEX_op_st16_i32:
1033 case INDEX_op_st16_i64:
1034 /* movw */
1035 tcg_out8(s, 0x66);
1036 tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]);
1037 break;
1038 case INDEX_op_st_i32:
1039 case INDEX_op_st32_i64:
1040 /* movl */
1041 tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]);
1042 break;
1043 case INDEX_op_st_i64:
1044 /* movq */
1045 tcg_out_modrm_offset(s, 0x89 | P_REXW, args[0], args[1], args[2]);
1046 break;
1047
1048 case INDEX_op_sub_i32:
1049 c = ARITH_SUB;
1050 goto gen_arith32;
1051 case INDEX_op_and_i32:
1052 c = ARITH_AND;
1053 goto gen_arith32;
1054 case INDEX_op_or_i32:
1055 c = ARITH_OR;
1056 goto gen_arith32;
1057 case INDEX_op_xor_i32:
1058 c = ARITH_XOR;
1059 goto gen_arith32;
1060 case INDEX_op_add_i32:
1061 c = ARITH_ADD;
1062 gen_arith32:
1063 if (const_args[2]) {
1064 tgen_arithi32(s, c, args[0], args[2]);
1065 } else {
1066 tcg_out_modrm(s, 0x01 | (c << 3), args[2], args[0]);
1067 }
1068 break;
1069
1070 case INDEX_op_sub_i64:
1071 c = ARITH_SUB;
1072 goto gen_arith64;
1073 case INDEX_op_and_i64:
1074 c = ARITH_AND;
1075 goto gen_arith64;
1076 case INDEX_op_or_i64:
1077 c = ARITH_OR;
1078 goto gen_arith64;
1079 case INDEX_op_xor_i64:
1080 c = ARITH_XOR;
1081 goto gen_arith64;
1082 case INDEX_op_add_i64:
1083 c = ARITH_ADD;
1084 gen_arith64:
1085 if (const_args[2]) {
1086 tgen_arithi64(s, c, args[0], args[2]);
1087 } else {
1088 tcg_out_modrm(s, 0x01 | (c << 3) | P_REXW, args[2], args[0]);
1089 }
1090 break;
1091
1092 case INDEX_op_mul_i32:
1093 if (const_args[2]) {
1094 int32_t val;
1095 val = args[2];
1096 if (val == (int8_t)val) {
1097 tcg_out_modrm(s, 0x6b, args[0], args[0]);
1098 tcg_out8(s, val);
1099 } else {
1100 tcg_out_modrm(s, 0x69, args[0], args[0]);
1101 tcg_out32(s, val);
1102 }
1103 } else {
1104 tcg_out_modrm(s, 0xaf | P_EXT, args[0], args[2]);
1105 }
1106 break;
1107 case INDEX_op_mul_i64:
1108 if (const_args[2]) {
1109 int32_t val;
1110 val = args[2];
1111 if (val == (int8_t)val) {
1112 tcg_out_modrm(s, 0x6b | P_REXW, args[0], args[0]);
1113 tcg_out8(s, val);
1114 } else {
1115 tcg_out_modrm(s, 0x69 | P_REXW, args[0], args[0]);
1116 tcg_out32(s, val);
1117 }
1118 } else {
1119 tcg_out_modrm(s, 0xaf | P_EXT | P_REXW, args[0], args[2]);
1120 }
1121 break;
1122 case INDEX_op_div2_i32:
1123 tcg_out_modrm(s, 0xf7, 7, args[4]);
1124 break;
1125 case INDEX_op_divu2_i32:
1126 tcg_out_modrm(s, 0xf7, 6, args[4]);
1127 break;
1128 case INDEX_op_div2_i64:
1129 tcg_out_modrm(s, 0xf7 | P_REXW, 7, args[4]);
1130 break;
1131 case INDEX_op_divu2_i64:
1132 tcg_out_modrm(s, 0xf7 | P_REXW, 6, args[4]);
1133 break;
1134
1135 case INDEX_op_shl_i32:
1136 c = SHIFT_SHL;
1137 gen_shift32:
1138 if (const_args[2]) {
1139 if (args[2] == 1) {
1140 tcg_out_modrm(s, 0xd1, c, args[0]);
1141 } else {
1142 tcg_out_modrm(s, 0xc1, c, args[0]);
1143 tcg_out8(s, args[2]);
1144 }
1145 } else {
1146 tcg_out_modrm(s, 0xd3, c, args[0]);
1147 }
1148 break;
1149 case INDEX_op_shr_i32:
1150 c = SHIFT_SHR;
1151 goto gen_shift32;
1152 case INDEX_op_sar_i32:
1153 c = SHIFT_SAR;
1154 goto gen_shift32;
1155 case INDEX_op_rotl_i32:
1156 c = SHIFT_ROL;
1157 goto gen_shift32;
1158 case INDEX_op_rotr_i32:
1159 c = SHIFT_ROR;
1160 goto gen_shift32;
1161
1162 case INDEX_op_shl_i64:
1163 c = SHIFT_SHL;
1164 gen_shift64:
1165 if (const_args[2]) {
1166 if (args[2] == 1) {
1167 tcg_out_modrm(s, 0xd1 | P_REXW, c, args[0]);
1168 } else {
1169 tcg_out_modrm(s, 0xc1 | P_REXW, c, args[0]);
1170 tcg_out8(s, args[2]);
1171 }
1172 } else {
1173 tcg_out_modrm(s, 0xd3 | P_REXW, c, args[0]);
1174 }
1175 break;
1176 case INDEX_op_shr_i64:
1177 c = SHIFT_SHR;
1178 goto gen_shift64;
1179 case INDEX_op_sar_i64:
1180 c = SHIFT_SAR;
1181 goto gen_shift64;
1182 case INDEX_op_rotl_i64:
1183 c = SHIFT_ROL;
1184 goto gen_shift64;
1185 case INDEX_op_rotr_i64:
1186 c = SHIFT_ROR;
1187 goto gen_shift64;
1188
1189 case INDEX_op_brcond_i32:
1190 tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
1191 args[3], 0);
1192 break;
1193 case INDEX_op_brcond_i64:
1194 tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
1195 args[3], P_REXW);
1196 break;
1197
1198 case INDEX_op_bswap16_i32:
1199 case INDEX_op_bswap16_i64:
1200 tcg_out8(s, 0x66);
1201 tcg_out_modrm(s, 0xc1, SHIFT_ROL, args[0]);
1202 tcg_out8(s, 8);
1203 break;
1204 case INDEX_op_bswap32_i32:
1205 case INDEX_op_bswap32_i64:
1206 tcg_out_opc(s, (0xc8 + (args[0] & 7)) | P_EXT, 0, args[0], 0);
1207 break;
1208 case INDEX_op_bswap64_i64:
1209 tcg_out_opc(s, (0xc8 + (args[0] & 7)) | P_EXT | P_REXW, 0, args[0], 0);
1210 break;
1211
1212 case INDEX_op_neg_i32:
1213 tcg_out_modrm(s, 0xf7, 3, args[0]);
1214 break;
1215 case INDEX_op_neg_i64:
1216 tcg_out_modrm(s, 0xf7 | P_REXW, 3, args[0]);
1217 break;
1218
1219 case INDEX_op_not_i32:
1220 tcg_out_modrm(s, 0xf7, 2, args[0]);
1221 break;
1222 case INDEX_op_not_i64:
1223 tcg_out_modrm(s, 0xf7 | P_REXW, 2, args[0]);
1224 break;
1225
1226 case INDEX_op_ext8s_i32:
1227 tcg_out_modrm(s, 0xbe | P_EXT | P_REXB, args[0], args[1]);
1228 break;
1229 case INDEX_op_ext16s_i32:
1230 tcg_out_modrm(s, 0xbf | P_EXT, args[0], args[1]);
1231 break;
1232 case INDEX_op_ext8s_i64:
1233 tcg_out_modrm(s, 0xbe | P_EXT | P_REXW, args[0], args[1]);
1234 break;
1235 case INDEX_op_ext16s_i64:
1236 tcg_out_modrm(s, 0xbf | P_EXT | P_REXW, args[0], args[1]);
1237 break;
1238 case INDEX_op_ext32s_i64:
1239 tcg_out_modrm(s, 0x63 | P_REXW, args[0], args[1]);
1240 break;
1241 case INDEX_op_ext8u_i32:
1242 tcg_out_modrm(s, 0xb6 | P_EXT | P_REXB, args[0], args[1]);
1243 break;
1244 case INDEX_op_ext16u_i32:
1245 tcg_out_modrm(s, 0xb7 | P_EXT, args[0], args[1]);
1246 break;
1247 case INDEX_op_ext8u_i64:
1248 tcg_out_modrm(s, 0xb6 | P_EXT | P_REXW, args[0], args[1]);
1249 break;
1250 case INDEX_op_ext16u_i64:
1251 tcg_out_modrm(s, 0xb7 | P_EXT | P_REXW, args[0], args[1]);
1252 break;
1253 case INDEX_op_ext32u_i64:
1254 tcg_out_modrm(s, 0x8b, args[0], args[1]);
1255 break;
1256
1257 case INDEX_op_qemu_ld8u:
1258 tcg_out_qemu_ld(s, args, 0);
1259 break;
1260 case INDEX_op_qemu_ld8s:
1261 tcg_out_qemu_ld(s, args, 0 | 4);
1262 break;
1263 case INDEX_op_qemu_ld16u:
1264 tcg_out_qemu_ld(s, args, 1);
1265 break;
1266 case INDEX_op_qemu_ld16s:
1267 tcg_out_qemu_ld(s, args, 1 | 4);
1268 break;
1269 case INDEX_op_qemu_ld32u:
1270 tcg_out_qemu_ld(s, args, 2);
1271 break;
1272 case INDEX_op_qemu_ld32s:
1273 tcg_out_qemu_ld(s, args, 2 | 4);
1274 break;
1275 case INDEX_op_qemu_ld64:
1276 tcg_out_qemu_ld(s, args, 3);
1277 break;
1278
1279 case INDEX_op_qemu_st8:
1280 tcg_out_qemu_st(s, args, 0);
1281 break;
1282 case INDEX_op_qemu_st16:
1283 tcg_out_qemu_st(s, args, 1);
1284 break;
1285 case INDEX_op_qemu_st32:
1286 tcg_out_qemu_st(s, args, 2);
1287 break;
1288 case INDEX_op_qemu_st64:
1289 tcg_out_qemu_st(s, args, 3);
1290 break;
1291
1292 default:
1293 tcg_abort();
1294 }
1295}
1296
1297static int tcg_target_callee_save_regs[] = {
1298 TCG_REG_RBP,
1299 TCG_REG_RBX,
1300 TCG_REG_R12,
1301 TCG_REG_R13,
1302 /* TCG_REG_R14, */ /* currently used for the global env, so no
1303 need to save */
1304 TCG_REG_R15,
1305};
1306
1307static inline void tcg_out_push(TCGContext *s, int reg)
1308{
1309 tcg_out_opc(s, (0x50 + (reg & 7)), 0, reg, 0);
1310}
1311
1312static inline void tcg_out_pop(TCGContext *s, int reg)
1313{
1314 tcg_out_opc(s, (0x58 + (reg & 7)), 0, reg, 0);
1315}
1316
1317/* Generate global QEMU prologue and epilogue code */
1318void tcg_target_qemu_prologue(TCGContext *s)
1319{
1320 int i, frame_size, push_size, stack_addend;
1321
1322 /* TB prologue */
1323 /* save all callee saved registers */
1324 for(i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
1325 tcg_out_push(s, tcg_target_callee_save_regs[i]);
1326
1327 }
1328 /* reserve some stack space */
1329 push_size = 8 + ARRAY_SIZE(tcg_target_callee_save_regs) * 8;
1330 frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE;
1331 frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1332 ~(TCG_TARGET_STACK_ALIGN - 1);
1333 stack_addend = frame_size - push_size;
1334 tcg_out_addi(s, TCG_REG_RSP, -stack_addend);
1335
1336 tcg_out_modrm(s, 0xff, 4, TCG_REG_RDI); /* jmp *%rdi */
1337
1338 /* TB epilogue */
1339 tb_ret_addr = s->code_ptr;
1340 tcg_out_addi(s, TCG_REG_RSP, stack_addend);
1341 for(i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
1342 tcg_out_pop(s, tcg_target_callee_save_regs[i]);
1343 }
1344 tcg_out8(s, 0xc3); /* ret */
1345}
1346
1347static const TCGTargetOpDef x86_64_op_defs[] = {
1348 { INDEX_op_exit_tb, { } },
1349 { INDEX_op_goto_tb, { } },
1350 { INDEX_op_call, { "ri" } }, /* XXX: might need a specific constant constraint */
1351 { INDEX_op_jmp, { "ri" } }, /* XXX: might need a specific constant constraint */
1352 { INDEX_op_br, { } },
1353
1354 { INDEX_op_mov_i32, { "r", "r" } },
1355 { INDEX_op_movi_i32, { "r" } },
1356 { INDEX_op_ld8u_i32, { "r", "r" } },
1357 { INDEX_op_ld8s_i32, { "r", "r" } },
1358 { INDEX_op_ld16u_i32, { "r", "r" } },
1359 { INDEX_op_ld16s_i32, { "r", "r" } },
1360 { INDEX_op_ld_i32, { "r", "r" } },
1361 { INDEX_op_st8_i32, { "r", "r" } },
1362 { INDEX_op_st16_i32, { "r", "r" } },
1363 { INDEX_op_st_i32, { "r", "r" } },
1364
1365 { INDEX_op_add_i32, { "r", "0", "ri" } },
1366 { INDEX_op_mul_i32, { "r", "0", "ri" } },
1367 { INDEX_op_div2_i32, { "a", "d", "0", "1", "r" } },
1368 { INDEX_op_divu2_i32, { "a", "d", "0", "1", "r" } },
1369 { INDEX_op_sub_i32, { "r", "0", "ri" } },
1370 { INDEX_op_and_i32, { "r", "0", "ri" } },
1371 { INDEX_op_or_i32, { "r", "0", "ri" } },
1372 { INDEX_op_xor_i32, { "r", "0", "ri" } },
1373
1374 { INDEX_op_shl_i32, { "r", "0", "ci" } },
1375 { INDEX_op_shr_i32, { "r", "0", "ci" } },
1376 { INDEX_op_sar_i32, { "r", "0", "ci" } },
1377 { INDEX_op_rotl_i32, { "r", "0", "ci" } },
1378 { INDEX_op_rotr_i32, { "r", "0", "ci" } },
1379
1380 { INDEX_op_brcond_i32, { "r", "ri" } },
1381
1382 { INDEX_op_mov_i64, { "r", "r" } },
1383 { INDEX_op_movi_i64, { "r" } },
1384 { INDEX_op_ld8u_i64, { "r", "r" } },
1385 { INDEX_op_ld8s_i64, { "r", "r" } },
1386 { INDEX_op_ld16u_i64, { "r", "r" } },
1387 { INDEX_op_ld16s_i64, { "r", "r" } },
1388 { INDEX_op_ld32u_i64, { "r", "r" } },
1389 { INDEX_op_ld32s_i64, { "r", "r" } },
1390 { INDEX_op_ld_i64, { "r", "r" } },
1391 { INDEX_op_st8_i64, { "r", "r" } },
1392 { INDEX_op_st16_i64, { "r", "r" } },
1393 { INDEX_op_st32_i64, { "r", "r" } },
1394 { INDEX_op_st_i64, { "r", "r" } },
1395
1396 { INDEX_op_add_i64, { "r", "0", "re" } },
1397 { INDEX_op_mul_i64, { "r", "0", "re" } },
1398 { INDEX_op_div2_i64, { "a", "d", "0", "1", "r" } },
1399 { INDEX_op_divu2_i64, { "a", "d", "0", "1", "r" } },
1400 { INDEX_op_sub_i64, { "r", "0", "re" } },
1401 { INDEX_op_and_i64, { "r", "0", "reZ" } },
1402 { INDEX_op_or_i64, { "r", "0", "re" } },
1403 { INDEX_op_xor_i64, { "r", "0", "re" } },
1404
1405 { INDEX_op_shl_i64, { "r", "0", "ci" } },
1406 { INDEX_op_shr_i64, { "r", "0", "ci" } },
1407 { INDEX_op_sar_i64, { "r", "0", "ci" } },
1408 { INDEX_op_rotl_i64, { "r", "0", "ci" } },
1409 { INDEX_op_rotr_i64, { "r", "0", "ci" } },
1410
1411 { INDEX_op_brcond_i64, { "r", "re" } },
1412
1413 { INDEX_op_bswap16_i32, { "r", "0" } },
1414 { INDEX_op_bswap16_i64, { "r", "0" } },
1415 { INDEX_op_bswap32_i32, { "r", "0" } },
1416 { INDEX_op_bswap32_i64, { "r", "0" } },
1417 { INDEX_op_bswap64_i64, { "r", "0" } },
1418
1419 { INDEX_op_neg_i32, { "r", "0" } },
1420 { INDEX_op_neg_i64, { "r", "0" } },
1421
1422 { INDEX_op_not_i32, { "r", "0" } },
1423 { INDEX_op_not_i64, { "r", "0" } },
1424
1425 { INDEX_op_ext8s_i32, { "r", "r"} },
1426 { INDEX_op_ext16s_i32, { "r", "r"} },
1427 { INDEX_op_ext8s_i64, { "r", "r"} },
1428 { INDEX_op_ext16s_i64, { "r", "r"} },
1429 { INDEX_op_ext32s_i64, { "r", "r"} },
1430 { INDEX_op_ext8u_i32, { "r", "r"} },
1431 { INDEX_op_ext16u_i32, { "r", "r"} },
1432 { INDEX_op_ext8u_i64, { "r", "r"} },
1433 { INDEX_op_ext16u_i64, { "r", "r"} },
1434 { INDEX_op_ext32u_i64, { "r", "r"} },
1435
1436 { INDEX_op_qemu_ld8u, { "r", "L" } },
1437 { INDEX_op_qemu_ld8s, { "r", "L" } },
1438 { INDEX_op_qemu_ld16u, { "r", "L" } },
1439 { INDEX_op_qemu_ld16s, { "r", "L" } },
1440 { INDEX_op_qemu_ld32u, { "r", "L" } },
1441 { INDEX_op_qemu_ld32s, { "r", "L" } },
1442 { INDEX_op_qemu_ld64, { "r", "L" } },
1443
1444 { INDEX_op_qemu_st8, { "L", "L" } },
1445 { INDEX_op_qemu_st16, { "L", "L" } },
1446 { INDEX_op_qemu_st32, { "L", "L" } },
1447 { INDEX_op_qemu_st64, { "L", "L" } },
1448
1449 { -1 },
1450};
1451
1452void tcg_target_init(TCGContext *s)
1453{
1454 /* fail safe */
1455 if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
1456 tcg_abort();
1457
1458 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
1459 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffff);
1460 tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1461 (1 << TCG_REG_RDI) |
1462 (1 << TCG_REG_RSI) |
1463 (1 << TCG_REG_RDX) |
1464 (1 << TCG_REG_RCX) |
1465 (1 << TCG_REG_R8) |
1466 (1 << TCG_REG_R9) |
1467 (1 << TCG_REG_RAX) |
1468 (1 << TCG_REG_R10) |
1469 (1 << TCG_REG_R11));
1470
1471 tcg_regset_clear(s->reserved_regs);
1472 tcg_regset_set_reg(s->reserved_regs, TCG_REG_RSP);
1473
1474 tcg_add_target_add_op_defs(x86_64_op_defs);
1475}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette