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