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