]> git.proxmox.com Git - mirror_qemu.git/blame - tcg/i386/tcg-target.c
tcg-i386: Tidy unary arithmetic.
[mirror_qemu.git] / tcg / i386 / tcg-target.c
CommitLineData
c896fe29
FB
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 */
d4a9eb1f
BS
24
25#ifndef NDEBUG
26static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
c896fe29
FB
27 "%eax",
28 "%ecx",
29 "%edx",
30 "%ebx",
31 "%esp",
32 "%ebp",
33 "%esi",
34 "%edi",
35};
d4a9eb1f 36#endif
c896fe29 37
d4a9eb1f 38static const int tcg_target_reg_alloc_order[] = {
c896fe29
FB
39 TCG_REG_EBX,
40 TCG_REG_ESI,
41 TCG_REG_EDI,
42 TCG_REG_EBP,
6648e296
RH
43 TCG_REG_ECX,
44 TCG_REG_EDX,
45 TCG_REG_EAX,
c896fe29
FB
46};
47
d4a9eb1f
BS
48static const int tcg_target_call_iarg_regs[3] = { TCG_REG_EAX, TCG_REG_EDX, TCG_REG_ECX };
49static const int tcg_target_call_oarg_regs[2] = { TCG_REG_EAX, TCG_REG_EDX };
c896fe29 50
b03cce8e
FB
51static uint8_t *tb_ret_addr;
52
c896fe29 53static void patch_reloc(uint8_t *code_ptr, int type,
f54b3f92 54 tcg_target_long value, tcg_target_long addend)
c896fe29 55{
f54b3f92 56 value += addend;
c896fe29
FB
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;
f75b56c1
RH
64 case R_386_PC8:
65 value -= (long)code_ptr;
66 if (value != (int8_t)value) {
67 tcg_abort();
68 }
69 *(uint8_t *)code_ptr = value;
70 break;
c896fe29
FB
71 default:
72 tcg_abort();
73 }
74}
75
76/* maximum number of register used for input function arguments */
77static inline int tcg_target_get_call_iarg_regs_count(int flags)
78{
79 flags &= TCG_CALL_TYPE_MASK;
80 switch(flags) {
81 case TCG_CALL_TYPE_STD:
82 return 0;
83 case TCG_CALL_TYPE_REGPARM_1:
84 case TCG_CALL_TYPE_REGPARM_2:
85 case TCG_CALL_TYPE_REGPARM:
86 return flags - TCG_CALL_TYPE_REGPARM_1 + 1;
87 default:
88 tcg_abort();
89 }
90}
91
92/* parse target specific constraints */
d4a9eb1f 93static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
c896fe29
FB
94{
95 const char *ct_str;
96
97 ct_str = *pct_str;
98 switch(ct_str[0]) {
99 case 'a':
100 ct->ct |= TCG_CT_REG;
101 tcg_regset_set_reg(ct->u.regs, TCG_REG_EAX);
102 break;
103 case 'b':
104 ct->ct |= TCG_CT_REG;
105 tcg_regset_set_reg(ct->u.regs, TCG_REG_EBX);
106 break;
107 case 'c':
108 ct->ct |= TCG_CT_REG;
109 tcg_regset_set_reg(ct->u.regs, TCG_REG_ECX);
110 break;
111 case 'd':
112 ct->ct |= TCG_CT_REG;
113 tcg_regset_set_reg(ct->u.regs, TCG_REG_EDX);
114 break;
115 case 'S':
116 ct->ct |= TCG_CT_REG;
117 tcg_regset_set_reg(ct->u.regs, TCG_REG_ESI);
118 break;
119 case 'D':
120 ct->ct |= TCG_CT_REG;
121 tcg_regset_set_reg(ct->u.regs, TCG_REG_EDI);
122 break;
123 case 'q':
124 ct->ct |= TCG_CT_REG;
125 tcg_regset_set32(ct->u.regs, 0, 0xf);
126 break;
127 case 'r':
128 ct->ct |= TCG_CT_REG;
129 tcg_regset_set32(ct->u.regs, 0, 0xff);
130 break;
131
132 /* qemu_ld/st address constraint */
133 case 'L':
134 ct->ct |= TCG_CT_REG;
135 tcg_regset_set32(ct->u.regs, 0, 0xff);
136 tcg_regset_reset_reg(ct->u.regs, TCG_REG_EAX);
137 tcg_regset_reset_reg(ct->u.regs, TCG_REG_EDX);
138 break;
139 default:
140 return -1;
141 }
142 ct_str++;
143 *pct_str = ct_str;
144 return 0;
145}
146
147/* test if a constant matches the constraint */
148static inline int tcg_target_const_match(tcg_target_long val,
149 const TCGArgConstraint *arg_ct)
150{
151 int ct;
152 ct = arg_ct->ct;
153 if (ct & TCG_CT_CONST)
154 return 1;
155 else
156 return 0;
157}
158
fcb5dac1
RH
159#define P_EXT 0x100 /* 0x0f opcode prefix */
160
a369a702
RH
161#define OPC_ARITH_EvIz (0x81)
162#define OPC_ARITH_EvIb (0x83)
81570a70
RH
163#define OPC_ARITH_GvEv (0x03) /* ... plus (ARITH_FOO << 3) */
164#define OPC_ADD_GvEv (OPC_ARITH_GvEv | (ARITH_ADD << 3))
fcb5dac1 165#define OPC_BSWAP (0xc8 | P_EXT)
aadb21a4 166#define OPC_CALL_Jz (0xe8)
81570a70
RH
167#define OPC_CMP_GvEv (OPC_ARITH_GvEv | (ARITH_CMP << 3))
168#define OPC_DEC_r32 (0x48)
169#define OPC_INC_r32 (0x40)
da441cff
RH
170#define OPC_JCC_long (0x80 | P_EXT) /* ... plus condition code */
171#define OPC_JCC_short (0x70) /* ... plus condition code */
172#define OPC_JMP_long (0xe9)
173#define OPC_JMP_short (0xeb)
af266089
RH
174#define OPC_MOVB_EvGv (0x88) /* stores, more or less */
175#define OPC_MOVL_EvGv (0x89) /* stores, more or less */
176#define OPC_MOVL_GvEv (0x8b) /* loads, more or less */
ef10b106 177#define OPC_MOVL_Iv (0xb8)
6817c355
RH
178#define OPC_MOVSBL (0xbe | P_EXT)
179#define OPC_MOVSWL (0xbf | P_EXT)
55e082a7
RH
180#define OPC_MOVZBL (0xb6 | P_EXT)
181#define OPC_MOVZWL (0xb7 | P_EXT)
6858614e
RH
182#define OPC_POP_r32 (0x58)
183#define OPC_PUSH_r32 (0x50)
184#define OPC_PUSH_Iv (0x68)
185#define OPC_PUSH_Ib (0x6a)
3c3accc6 186#define OPC_RET (0xc3)
32a8ffb9 187#define OPC_SETCC (0x90 | P_EXT) /* ... plus condition code */
f53dba01
RH
188#define OPC_SHIFT_1 (0xd1)
189#define OPC_SHIFT_Ib (0xc1)
190#define OPC_SHIFT_cl (0xd3)
81570a70 191#define OPC_TESTL (0x85)
fcb5dac1 192
9363dedb
RH
193#define OPC_GRP3_Ev (0xf7)
194#define OPC_GRP5 (0xff)
195
196/* Group 1 opcode extensions for 0x80-0x83.
197 These are also used as modifiers for OPC_ARITH. */
c896fe29
FB
198#define ARITH_ADD 0
199#define ARITH_OR 1
200#define ARITH_ADC 2
201#define ARITH_SBB 3
202#define ARITH_AND 4
203#define ARITH_SUB 5
204#define ARITH_XOR 6
205#define ARITH_CMP 7
206
da441cff 207/* Group 2 opcode extensions for 0xc0, 0xc1, 0xd0-0xd3. */
9619376c
AJ
208#define SHIFT_ROL 0
209#define SHIFT_ROR 1
c896fe29
FB
210#define SHIFT_SHL 4
211#define SHIFT_SHR 5
212#define SHIFT_SAR 7
213
9363dedb
RH
214/* Group 3 opcode extensions for 0xf6, 0xf7. To be used with OPC_GRP3. */
215#define EXT3_NOT 2
216#define EXT3_NEG 3
217#define EXT3_MUL 4
218#define EXT3_IMUL 5
219#define EXT3_DIV 6
220#define EXT3_IDIV 7
221
222/* Group 5 opcode extensions for 0xff. To be used with OPC_GRP5. */
223#define EXT5_CALLN_Ev 2
224#define EXT5_JMPN_Ev 4
da441cff
RH
225
226/* Condition codes to be added to OPC_JCC_{long,short}. */
c896fe29
FB
227#define JCC_JMP (-1)
228#define JCC_JO 0x0
229#define JCC_JNO 0x1
230#define JCC_JB 0x2
231#define JCC_JAE 0x3
232#define JCC_JE 0x4
233#define JCC_JNE 0x5
234#define JCC_JBE 0x6
235#define JCC_JA 0x7
236#define JCC_JS 0x8
237#define JCC_JNS 0x9
238#define JCC_JP 0xa
239#define JCC_JNP 0xb
240#define JCC_JL 0xc
241#define JCC_JGE 0xd
242#define JCC_JLE 0xe
243#define JCC_JG 0xf
244
c896fe29
FB
245static const uint8_t tcg_cond_to_jcc[10] = {
246 [TCG_COND_EQ] = JCC_JE,
247 [TCG_COND_NE] = JCC_JNE,
248 [TCG_COND_LT] = JCC_JL,
249 [TCG_COND_GE] = JCC_JGE,
250 [TCG_COND_LE] = JCC_JLE,
251 [TCG_COND_GT] = JCC_JG,
252 [TCG_COND_LTU] = JCC_JB,
253 [TCG_COND_GEU] = JCC_JAE,
254 [TCG_COND_LEU] = JCC_JBE,
255 [TCG_COND_GTU] = JCC_JA,
256};
257
258static inline void tcg_out_opc(TCGContext *s, int opc)
259{
260 if (opc & P_EXT)
261 tcg_out8(s, 0x0f);
262 tcg_out8(s, opc);
263}
264
265static inline void tcg_out_modrm(TCGContext *s, int opc, int r, int rm)
266{
267 tcg_out_opc(s, opc);
268 tcg_out8(s, 0xc0 | (r << 3) | rm);
269}
270
271/* rm == -1 means no register index */
272static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r, int rm,
273 int32_t offset)
274{
275 tcg_out_opc(s, opc);
276 if (rm == -1) {
277 tcg_out8(s, 0x05 | (r << 3));
278 tcg_out32(s, offset);
279 } else if (offset == 0 && rm != TCG_REG_EBP) {
280 if (rm == TCG_REG_ESP) {
281 tcg_out8(s, 0x04 | (r << 3));
282 tcg_out8(s, 0x24);
283 } else {
284 tcg_out8(s, 0x00 | (r << 3) | rm);
285 }
286 } else if ((int8_t)offset == offset) {
287 if (rm == TCG_REG_ESP) {
288 tcg_out8(s, 0x44 | (r << 3));
289 tcg_out8(s, 0x24);
290 } else {
291 tcg_out8(s, 0x40 | (r << 3) | rm);
292 }
293 tcg_out8(s, offset);
294 } else {
295 if (rm == TCG_REG_ESP) {
296 tcg_out8(s, 0x84 | (r << 3));
297 tcg_out8(s, 0x24);
298 } else {
299 tcg_out8(s, 0x80 | (r << 3) | rm);
300 }
301 tcg_out32(s, offset);
302 }
303}
304
81570a70
RH
305/* Generate dest op= src. Uses the same ARITH_* codes as tgen_arithi. */
306static inline void tgen_arithr(TCGContext *s, int subop, int dest, int src)
307{
308 tcg_out_modrm(s, OPC_ARITH_GvEv + (subop << 3), dest, src);
309}
310
c896fe29
FB
311static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
312{
af266089
RH
313 if (arg != ret) {
314 tcg_out_modrm(s, OPC_MOVL_GvEv, ret, arg);
315 }
c896fe29
FB
316}
317
318static inline void tcg_out_movi(TCGContext *s, TCGType type,
319 int ret, int32_t arg)
320{
321 if (arg == 0) {
81570a70 322 tgen_arithr(s, ARITH_XOR, ret, ret);
c896fe29 323 } else {
ef10b106 324 tcg_out8(s, OPC_MOVL_Iv + ret);
c896fe29
FB
325 tcg_out32(s, arg);
326 }
327}
328
6858614e
RH
329static inline void tcg_out_pushi(TCGContext *s, tcg_target_long val)
330{
331 if (val == (int8_t)val) {
332 tcg_out_opc(s, OPC_PUSH_Ib);
333 tcg_out8(s, val);
334 } else {
335 tcg_out_opc(s, OPC_PUSH_Iv);
336 tcg_out32(s, val);
337 }
338}
339
340static inline void tcg_out_push(TCGContext *s, int reg)
341{
342 tcg_out_opc(s, OPC_PUSH_r32 + reg);
343}
344
345static inline void tcg_out_pop(TCGContext *s, int reg)
346{
347 tcg_out_opc(s, OPC_POP_r32 + reg);
348}
349
e4d5434c
BS
350static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
351 int arg1, tcg_target_long arg2)
c896fe29 352{
af266089 353 tcg_out_modrm_offset(s, OPC_MOVL_GvEv, ret, arg1, arg2);
c896fe29
FB
354}
355
e4d5434c
BS
356static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
357 int arg1, tcg_target_long arg2)
c896fe29 358{
af266089 359 tcg_out_modrm_offset(s, OPC_MOVL_EvGv, arg, arg1, arg2);
c896fe29
FB
360}
361
f53dba01
RH
362static void tcg_out_shifti(TCGContext *s, int subopc, int reg, int count)
363{
364 if (count == 1) {
365 tcg_out_modrm(s, OPC_SHIFT_1, subopc, reg);
366 } else {
367 tcg_out_modrm(s, OPC_SHIFT_Ib, subopc, reg);
368 tcg_out8(s, count);
369 }
370}
371
fcb5dac1
RH
372static inline void tcg_out_bswap32(TCGContext *s, int reg)
373{
374 tcg_out_opc(s, OPC_BSWAP + reg);
375}
376
377static inline void tcg_out_rolw_8(TCGContext *s, int reg)
378{
379 tcg_out8(s, 0x66);
f53dba01 380 tcg_out_shifti(s, SHIFT_ROL, reg, 8);
fcb5dac1
RH
381}
382
55e082a7
RH
383static inline void tcg_out_ext8u(TCGContext *s, int dest, int src)
384{
385 /* movzbl */
386 assert(src < 4);
387 tcg_out_modrm(s, OPC_MOVZBL, dest, src);
388}
389
6817c355
RH
390static void tcg_out_ext8s(TCGContext *s, int dest, int src)
391{
392 /* movsbl */
393 assert(src < 4);
394 tcg_out_modrm(s, OPC_MOVSBL, dest, src);
395}
396
55e082a7
RH
397static inline void tcg_out_ext16u(TCGContext *s, int dest, int src)
398{
399 /* movzwl */
400 tcg_out_modrm(s, OPC_MOVZWL, dest, src);
401}
402
6817c355
RH
403static inline void tcg_out_ext16s(TCGContext *s, int dest, int src)
404{
405 /* movswl */
406 tcg_out_modrm(s, OPC_MOVSWL, dest, src);
407}
408
81570a70
RH
409static inline void tgen_arithi(TCGContext *s, int c, int r0,
410 int32_t val, int cf)
c896fe29 411{
81570a70
RH
412 /* ??? While INC is 2 bytes shorter than ADDL $1, they also induce
413 partial flags update stalls on Pentium4 and are not recommended
414 by current Intel optimization manuals. */
415 if (!cf && (c == ARITH_ADD || c == ARITH_SUB) && (val == 1 || val == -1)) {
416 int opc = ((c == ARITH_ADD) ^ (val < 0) ? OPC_INC_r32 : OPC_DEC_r32);
417 tcg_out_opc(s, opc + r0);
17cf428f 418 } else if (val == (int8_t)val) {
a369a702 419 tcg_out_modrm(s, OPC_ARITH_EvIb, c, r0);
c896fe29 420 tcg_out8(s, val);
b70650cb 421 } else if (c == ARITH_AND && val == 0xffu && r0 < 4) {
55e082a7 422 tcg_out_ext8u(s, r0, r0);
b70650cb 423 } else if (c == ARITH_AND && val == 0xffffu) {
55e082a7 424 tcg_out_ext16u(s, r0, r0);
c896fe29 425 } else {
a369a702 426 tcg_out_modrm(s, OPC_ARITH_EvIz, c, r0);
c896fe29
FB
427 tcg_out32(s, val);
428 }
429}
430
3e9a474e 431static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
c896fe29
FB
432{
433 if (val != 0)
17cf428f 434 tgen_arithi(s, ARITH_ADD, reg, val, 0);
c896fe29
FB
435}
436
f75b56c1
RH
437/* Use SMALL != 0 to force a short forward branch. */
438static void tcg_out_jxx(TCGContext *s, int opc, int label_index, int small)
c896fe29
FB
439{
440 int32_t val, val1;
441 TCGLabel *l = &s->labels[label_index];
442
443 if (l->has_value) {
444 val = l->u.value - (tcg_target_long)s->code_ptr;
445 val1 = val - 2;
446 if ((int8_t)val1 == val1) {
f75b56c1 447 if (opc == -1) {
da441cff 448 tcg_out8(s, OPC_JMP_short);
f75b56c1 449 } else {
da441cff 450 tcg_out8(s, OPC_JCC_short + opc);
f75b56c1 451 }
c896fe29
FB
452 tcg_out8(s, val1);
453 } else {
f75b56c1
RH
454 if (small) {
455 tcg_abort();
456 }
c896fe29 457 if (opc == -1) {
da441cff 458 tcg_out8(s, OPC_JMP_long);
c896fe29
FB
459 tcg_out32(s, val - 5);
460 } else {
da441cff 461 tcg_out_opc(s, OPC_JCC_long + opc);
c896fe29
FB
462 tcg_out32(s, val - 6);
463 }
464 }
f75b56c1
RH
465 } else if (small) {
466 if (opc == -1) {
da441cff 467 tcg_out8(s, OPC_JMP_short);
f75b56c1 468 } else {
da441cff 469 tcg_out8(s, OPC_JCC_short + opc);
f75b56c1
RH
470 }
471 tcg_out_reloc(s, s->code_ptr, R_386_PC8, label_index, -1);
472 s->code_ptr += 1;
c896fe29
FB
473 } else {
474 if (opc == -1) {
da441cff 475 tcg_out8(s, OPC_JMP_long);
c896fe29 476 } else {
da441cff 477 tcg_out_opc(s, OPC_JCC_long + opc);
c896fe29
FB
478 }
479 tcg_out_reloc(s, s->code_ptr, R_386_PC32, label_index, -4);
623e265c 480 s->code_ptr += 4;
c896fe29
FB
481 }
482}
483
1d2699ae
RH
484static void tcg_out_cmp(TCGContext *s, TCGArg arg1, TCGArg arg2,
485 int const_arg2)
c896fe29 486{
c896fe29
FB
487 if (const_arg2) {
488 if (arg2 == 0) {
c896fe29 489 /* test r, r */
81570a70 490 tcg_out_modrm(s, OPC_TESTL, arg1, arg1);
c896fe29 491 } else {
17cf428f 492 tgen_arithi(s, ARITH_CMP, arg1, arg2, 0);
c896fe29
FB
493 }
494 } else {
81570a70 495 tgen_arithr(s, ARITH_CMP, arg1, arg2);
c896fe29 496 }
1d2699ae
RH
497}
498
8a56e840 499static void tcg_out_brcond(TCGContext *s, TCGCond cond,
1d2699ae
RH
500 TCGArg arg1, TCGArg arg2, int const_arg2,
501 int label_index, int small)
502{
503 tcg_out_cmp(s, arg1, arg2, const_arg2);
f75b56c1 504 tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index, small);
c896fe29
FB
505}
506
507/* XXX: we implement it at the target level to avoid having to
508 handle cross basic blocks temporaries */
f75b56c1
RH
509static void tcg_out_brcond2(TCGContext *s, const TCGArg *args,
510 const int *const_args, int small)
c896fe29
FB
511{
512 int label_next;
513 label_next = gen_new_label();
514 switch(args[4]) {
515 case TCG_COND_EQ:
f75b56c1
RH
516 tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2],
517 label_next, 1);
518 tcg_out_brcond(s, TCG_COND_EQ, args[1], args[3], const_args[3],
519 args[5], small);
c896fe29
FB
520 break;
521 case TCG_COND_NE:
f75b56c1
RH
522 tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2],
523 args[5], small);
524 tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3],
525 args[5], small);
c896fe29
FB
526 break;
527 case TCG_COND_LT:
f75b56c1
RH
528 tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3],
529 args[5], small);
530 tcg_out_jxx(s, JCC_JNE, label_next, 1);
531 tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2],
532 args[5], small);
c896fe29
FB
533 break;
534 case TCG_COND_LE:
f75b56c1
RH
535 tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3],
536 args[5], small);
537 tcg_out_jxx(s, JCC_JNE, label_next, 1);
538 tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2],
539 args[5], small);
c896fe29
FB
540 break;
541 case TCG_COND_GT:
f75b56c1
RH
542 tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3],
543 args[5], small);
544 tcg_out_jxx(s, JCC_JNE, label_next, 1);
545 tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2],
546 args[5], small);
c896fe29
FB
547 break;
548 case TCG_COND_GE:
f75b56c1
RH
549 tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3],
550 args[5], small);
551 tcg_out_jxx(s, JCC_JNE, label_next, 1);
552 tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2],
553 args[5], small);
c896fe29
FB
554 break;
555 case TCG_COND_LTU:
f75b56c1
RH
556 tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3],
557 args[5], small);
558 tcg_out_jxx(s, JCC_JNE, label_next, 1);
559 tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2],
560 args[5], small);
c896fe29
FB
561 break;
562 case TCG_COND_LEU:
f75b56c1
RH
563 tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3],
564 args[5], small);
565 tcg_out_jxx(s, JCC_JNE, label_next, 1);
566 tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2],
567 args[5], small);
c896fe29
FB
568 break;
569 case TCG_COND_GTU:
f75b56c1
RH
570 tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3],
571 args[5], small);
572 tcg_out_jxx(s, JCC_JNE, label_next, 1);
573 tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2],
574 args[5], small);
c896fe29
FB
575 break;
576 case TCG_COND_GEU:
f75b56c1
RH
577 tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3],
578 args[5], small);
579 tcg_out_jxx(s, JCC_JNE, label_next, 1);
580 tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2],
581 args[5], small);
c896fe29
FB
582 break;
583 default:
584 tcg_abort();
585 }
586 tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);
587}
588
8a56e840 589static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGArg dest,
1d2699ae
RH
590 TCGArg arg1, TCGArg arg2, int const_arg2)
591{
592 tcg_out_cmp(s, arg1, arg2, const_arg2);
32a8ffb9 593 tcg_out_modrm(s, OPC_SETCC | tcg_cond_to_jcc[cond], 0, dest);
a369a702 594 tcg_out_ext8u(s, dest, dest);
1d2699ae
RH
595}
596
597static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
598 const int *const_args)
599{
600 TCGArg new_args[6];
601 int label_true, label_over;
602
603 memcpy(new_args, args+1, 5*sizeof(TCGArg));
604
605 if (args[0] == args[1] || args[0] == args[2]
606 || (!const_args[3] && args[0] == args[3])
607 || (!const_args[4] && args[0] == args[4])) {
608 /* When the destination overlaps with one of the argument
609 registers, don't do anything tricky. */
610 label_true = gen_new_label();
611 label_over = gen_new_label();
612
613 new_args[5] = label_true;
614 tcg_out_brcond2(s, new_args, const_args+1, 1);
615
616 tcg_out_movi(s, TCG_TYPE_I32, args[0], 0);
617 tcg_out_jxx(s, JCC_JMP, label_over, 1);
618 tcg_out_label(s, label_true, (tcg_target_long)s->code_ptr);
619
620 tcg_out_movi(s, TCG_TYPE_I32, args[0], 1);
621 tcg_out_label(s, label_over, (tcg_target_long)s->code_ptr);
622 } else {
623 /* When the destination does not overlap one of the arguments,
624 clear the destination first, jump if cond false, and emit an
625 increment in the true case. This results in smaller code. */
626
627 tcg_out_movi(s, TCG_TYPE_I32, args[0], 0);
628
629 label_over = gen_new_label();
630 new_args[4] = tcg_invert_cond(new_args[4]);
631 new_args[5] = label_over;
632 tcg_out_brcond2(s, new_args, const_args+1, 1);
633
634 tgen_arithi(s, ARITH_ADD, args[0], 1, 0);
635 tcg_out_label(s, label_over, (tcg_target_long)s->code_ptr);
636 }
637}
638
aadb21a4
RH
639static void tcg_out_calli(TCGContext *s, tcg_target_long dest)
640{
641 tcg_out_opc(s, OPC_CALL_Jz);
642 tcg_out32(s, dest - (tcg_target_long)s->code_ptr - 4);
643}
644
c896fe29 645#if defined(CONFIG_SOFTMMU)
79383c9c
BS
646
647#include "../../softmmu_defs.h"
c896fe29
FB
648
649static void *qemu_ld_helpers[4] = {
650 __ldb_mmu,
651 __ldw_mmu,
652 __ldl_mmu,
653 __ldq_mmu,
654};
655
656static void *qemu_st_helpers[4] = {
657 __stb_mmu,
658 __stw_mmu,
659 __stl_mmu,
660 __stq_mmu,
661};
662#endif
663
379f6698
PB
664#ifndef CONFIG_USER_ONLY
665#define GUEST_BASE 0
666#endif
667
c896fe29
FB
668/* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and
669 EAX. It will be useful once fixed registers globals are less
670 common. */
671static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
672 int opc)
673{
674 int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
675#if defined(CONFIG_SOFTMMU)
676 uint8_t *label1_ptr, *label2_ptr;
677#endif
678#if TARGET_LONG_BITS == 64
679#if defined(CONFIG_SOFTMMU)
680 uint8_t *label3_ptr;
681#endif
682 int addr_reg2;
683#endif
684
685 data_reg = *args++;
686 if (opc == 3)
687 data_reg2 = *args++;
688 else
689 data_reg2 = 0;
690 addr_reg = *args++;
691#if TARGET_LONG_BITS == 64
692 addr_reg2 = *args++;
693#endif
694 mem_index = *args;
695 s_bits = opc & 3;
696
697 r0 = TCG_REG_EAX;
698 r1 = TCG_REG_EDX;
699
700#if defined(CONFIG_SOFTMMU)
701 tcg_out_mov(s, r1, addr_reg);
c896fe29 702 tcg_out_mov(s, r0, addr_reg);
a369a702 703
f53dba01
RH
704 tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
705
a369a702
RH
706 tgen_arithi(s, ARITH_AND, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
707 tgen_arithi(s, ARITH_AND, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
c896fe29
FB
708
709 tcg_out_opc(s, 0x8d); /* lea offset(r1, %ebp), r1 */
710 tcg_out8(s, 0x80 | (r1 << 3) | 0x04);
711 tcg_out8(s, (5 << 3) | r1);
712 tcg_out32(s, offsetof(CPUState, tlb_table[mem_index][0].addr_read));
713
714 /* cmp 0(r1), r0 */
81570a70 715 tcg_out_modrm_offset(s, OPC_CMP_GvEv, r0, r1, 0);
c896fe29
FB
716
717 tcg_out_mov(s, r0, addr_reg);
718
719#if TARGET_LONG_BITS == 32
720 /* je label1 */
da441cff 721 tcg_out8(s, OPC_JCC_short + JCC_JE);
c896fe29
FB
722 label1_ptr = s->code_ptr;
723 s->code_ptr++;
724#else
725 /* jne label3 */
da441cff 726 tcg_out8(s, OPC_JCC_short + JCC_JNE);
c896fe29
FB
727 label3_ptr = s->code_ptr;
728 s->code_ptr++;
729
730 /* cmp 4(r1), addr_reg2 */
81570a70 731 tcg_out_modrm_offset(s, OPC_CMP_GvEv, addr_reg2, r1, 4);
c896fe29
FB
732
733 /* je label1 */
da441cff 734 tcg_out8(s, OPC_JCC_short + JCC_JE);
c896fe29
FB
735 label1_ptr = s->code_ptr;
736 s->code_ptr++;
737
738 /* label3: */
739 *label3_ptr = s->code_ptr - label3_ptr - 1;
740#endif
741
742 /* XXX: move that code at the end of the TB */
743#if TARGET_LONG_BITS == 32
744 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EDX, mem_index);
745#else
746 tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
747 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
748#endif
aadb21a4 749 tcg_out_calli(s, (tcg_target_long)qemu_ld_helpers[s_bits]);
c896fe29
FB
750
751 switch(opc) {
752 case 0 | 4:
6817c355 753 tcg_out_ext8s(s, data_reg, TCG_REG_EAX);
c896fe29
FB
754 break;
755 case 1 | 4:
6817c355 756 tcg_out_ext16s(s, data_reg, TCG_REG_EAX);
c896fe29
FB
757 break;
758 case 0:
55e082a7 759 tcg_out_ext8u(s, data_reg, TCG_REG_EAX);
9db3ba4d 760 break;
c896fe29 761 case 1:
55e082a7 762 tcg_out_ext16u(s, data_reg, TCG_REG_EAX);
9db3ba4d 763 break;
c896fe29
FB
764 case 2:
765 default:
766 tcg_out_mov(s, data_reg, TCG_REG_EAX);
767 break;
768 case 3:
769 if (data_reg == TCG_REG_EDX) {
770 tcg_out_opc(s, 0x90 + TCG_REG_EDX); /* xchg %edx, %eax */
771 tcg_out_mov(s, data_reg2, TCG_REG_EAX);
772 } else {
773 tcg_out_mov(s, data_reg, TCG_REG_EAX);
774 tcg_out_mov(s, data_reg2, TCG_REG_EDX);
775 }
776 break;
777 }
778
779 /* jmp label2 */
da441cff 780 tcg_out8(s, OPC_JMP_short);
c896fe29
FB
781 label2_ptr = s->code_ptr;
782 s->code_ptr++;
783
784 /* label1: */
785 *label1_ptr = s->code_ptr - label1_ptr - 1;
786
787 /* add x(r1), r0 */
81570a70
RH
788 tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
789 offsetof(CPUTLBEntry, addend) -
c896fe29
FB
790 offsetof(CPUTLBEntry, addr_read));
791#else
792 r0 = addr_reg;
793#endif
794
795#ifdef TARGET_WORDS_BIGENDIAN
796 bswap = 1;
797#else
798 bswap = 0;
799#endif
800 switch(opc) {
801 case 0:
802 /* movzbl */
55e082a7 803 tcg_out_modrm_offset(s, OPC_MOVZBL, data_reg, r0, GUEST_BASE);
c896fe29
FB
804 break;
805 case 0 | 4:
806 /* movsbl */
6817c355 807 tcg_out_modrm_offset(s, OPC_MOVSBL, data_reg, r0, GUEST_BASE);
c896fe29
FB
808 break;
809 case 1:
810 /* movzwl */
55e082a7 811 tcg_out_modrm_offset(s, OPC_MOVZWL, data_reg, r0, GUEST_BASE);
c896fe29 812 if (bswap) {
fcb5dac1 813 tcg_out_rolw_8(s, data_reg);
c896fe29
FB
814 }
815 break;
816 case 1 | 4:
817 /* movswl */
6817c355 818 tcg_out_modrm_offset(s, OPC_MOVSWL, data_reg, r0, GUEST_BASE);
c896fe29 819 if (bswap) {
fcb5dac1 820 tcg_out_rolw_8(s, data_reg);
c896fe29
FB
821
822 /* movswl data_reg, data_reg */
6817c355 823 tcg_out_modrm(s, OPC_MOVSWL, data_reg, data_reg);
c896fe29
FB
824 }
825 break;
826 case 2:
af266089 827 tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
c896fe29 828 if (bswap) {
fcb5dac1 829 tcg_out_bswap32(s, data_reg);
c896fe29
FB
830 }
831 break;
832 case 3:
a042ef94
RH
833 if (bswap) {
834 int t = data_reg;
835 data_reg = data_reg2;
836 data_reg2 = t;
c896fe29 837 }
a042ef94 838 if (r0 != data_reg) {
af266089
RH
839 tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
840 tcg_out_ld(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE + 4);
c896fe29 841 } else {
a042ef94
RH
842 tcg_out_ld(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE + 4);
843 tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
844 }
845 if (bswap) {
fcb5dac1 846 tcg_out_bswap32(s, data_reg);
fcb5dac1 847 tcg_out_bswap32(s, data_reg2);
c896fe29
FB
848 }
849 break;
850 default:
851 tcg_abort();
852 }
853
854#if defined(CONFIG_SOFTMMU)
855 /* label2: */
856 *label2_ptr = s->code_ptr - label2_ptr - 1;
857#endif
858}
859
860
861static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
862 int opc)
863{
864 int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
865#if defined(CONFIG_SOFTMMU)
aadb21a4 866 int stack_adjust;
c896fe29
FB
867 uint8_t *label1_ptr, *label2_ptr;
868#endif
869#if TARGET_LONG_BITS == 64
870#if defined(CONFIG_SOFTMMU)
871 uint8_t *label3_ptr;
872#endif
873 int addr_reg2;
874#endif
875
876 data_reg = *args++;
877 if (opc == 3)
878 data_reg2 = *args++;
879 else
880 data_reg2 = 0;
881 addr_reg = *args++;
882#if TARGET_LONG_BITS == 64
883 addr_reg2 = *args++;
884#endif
885 mem_index = *args;
886
887 s_bits = opc;
888
889 r0 = TCG_REG_EAX;
890 r1 = TCG_REG_EDX;
891
892#if defined(CONFIG_SOFTMMU)
893 tcg_out_mov(s, r1, addr_reg);
c896fe29
FB
894 tcg_out_mov(s, r0, addr_reg);
895
f53dba01
RH
896 tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
897
a369a702
RH
898 tgen_arithi(s, ARITH_AND, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
899 tgen_arithi(s, ARITH_AND, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
c896fe29
FB
900
901 tcg_out_opc(s, 0x8d); /* lea offset(r1, %ebp), r1 */
902 tcg_out8(s, 0x80 | (r1 << 3) | 0x04);
903 tcg_out8(s, (5 << 3) | r1);
904 tcg_out32(s, offsetof(CPUState, tlb_table[mem_index][0].addr_write));
905
906 /* cmp 0(r1), r0 */
81570a70 907 tcg_out_modrm_offset(s, OPC_CMP_GvEv, r0, r1, 0);
c896fe29
FB
908
909 tcg_out_mov(s, r0, addr_reg);
910
911#if TARGET_LONG_BITS == 32
912 /* je label1 */
da441cff 913 tcg_out8(s, OPC_JCC_short + JCC_JE);
c896fe29
FB
914 label1_ptr = s->code_ptr;
915 s->code_ptr++;
916#else
917 /* jne label3 */
da441cff 918 tcg_out8(s, OPC_JCC_short + JCC_JNE);
c896fe29
FB
919 label3_ptr = s->code_ptr;
920 s->code_ptr++;
921
922 /* cmp 4(r1), addr_reg2 */
81570a70 923 tcg_out_modrm_offset(s, OPC_CMP_GvEv, addr_reg2, r1, 4);
c896fe29
FB
924
925 /* je label1 */
da441cff 926 tcg_out8(s, OPC_JCC_short + JCC_JE);
c896fe29
FB
927 label1_ptr = s->code_ptr;
928 s->code_ptr++;
929
930 /* label3: */
931 *label3_ptr = s->code_ptr - label3_ptr - 1;
932#endif
933
934 /* XXX: move that code at the end of the TB */
935#if TARGET_LONG_BITS == 32
936 if (opc == 3) {
937 tcg_out_mov(s, TCG_REG_EDX, data_reg);
938 tcg_out_mov(s, TCG_REG_ECX, data_reg2);
6858614e 939 tcg_out_pushi(s, mem_index);
aadb21a4 940 stack_adjust = 4;
c896fe29
FB
941 } else {
942 switch(opc) {
943 case 0:
55e082a7 944 tcg_out_ext8u(s, TCG_REG_EDX, data_reg);
c896fe29
FB
945 break;
946 case 1:
55e082a7 947 tcg_out_ext16u(s, TCG_REG_EDX, data_reg);
c896fe29
FB
948 break;
949 case 2:
950 tcg_out_mov(s, TCG_REG_EDX, data_reg);
951 break;
952 }
953 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
aadb21a4 954 stack_adjust = 0;
c896fe29
FB
955 }
956#else
957 if (opc == 3) {
958 tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
6858614e
RH
959 tcg_out_pushi(s, mem_index);
960 tcg_out_push(s, data_reg2);
961 tcg_out_push(s, data_reg);
aadb21a4 962 stack_adjust = 12;
c896fe29
FB
963 } else {
964 tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
965 switch(opc) {
966 case 0:
55e082a7 967 tcg_out_ext8u(s, TCG_REG_ECX, data_reg);
c896fe29
FB
968 break;
969 case 1:
55e082a7 970 tcg_out_ext16u(s, TCG_REG_ECX, data_reg);
c896fe29
FB
971 break;
972 case 2:
973 tcg_out_mov(s, TCG_REG_ECX, data_reg);
974 break;
975 }
6858614e 976 tcg_out_pushi(s, mem_index);
aadb21a4 977 stack_adjust = 4;
c896fe29
FB
978 }
979#endif
aadb21a4
RH
980
981 tcg_out_calli(s, (tcg_target_long)qemu_st_helpers[s_bits]);
982
983 if (stack_adjust == 4) {
984 /* Pop and discard. This is 2 bytes smaller than the add. */
985 tcg_out_pop(s, TCG_REG_ECX);
986 } else if (stack_adjust != 0) {
987 tcg_out_addi(s, TCG_REG_ESP, stack_adjust);
988 }
989
c896fe29 990 /* jmp label2 */
da441cff 991 tcg_out8(s, OPC_JMP_short);
c896fe29
FB
992 label2_ptr = s->code_ptr;
993 s->code_ptr++;
994
995 /* label1: */
996 *label1_ptr = s->code_ptr - label1_ptr - 1;
997
998 /* add x(r1), r0 */
81570a70
RH
999 tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
1000 offsetof(CPUTLBEntry, addend) -
c896fe29
FB
1001 offsetof(CPUTLBEntry, addr_write));
1002#else
1003 r0 = addr_reg;
1004#endif
1005
1006#ifdef TARGET_WORDS_BIGENDIAN
1007 bswap = 1;
1008#else
1009 bswap = 0;
1010#endif
1011 switch(opc) {
1012 case 0:
af266089 1013 tcg_out_modrm_offset(s, OPC_MOVB_EvGv, data_reg, r0, GUEST_BASE);
c896fe29
FB
1014 break;
1015 case 1:
1016 if (bswap) {
1017 tcg_out_mov(s, r1, data_reg);
fcb5dac1 1018 tcg_out_rolw_8(s, r1);
c896fe29
FB
1019 data_reg = r1;
1020 }
1021 /* movw */
1022 tcg_out8(s, 0x66);
af266089 1023 tcg_out_modrm_offset(s, OPC_MOVL_EvGv, data_reg, r0, GUEST_BASE);
c896fe29
FB
1024 break;
1025 case 2:
1026 if (bswap) {
1027 tcg_out_mov(s, r1, data_reg);
fcb5dac1 1028 tcg_out_bswap32(s, r1);
c896fe29
FB
1029 data_reg = r1;
1030 }
af266089 1031 tcg_out_st(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
c896fe29
FB
1032 break;
1033 case 3:
1034 if (bswap) {
1035 tcg_out_mov(s, r1, data_reg2);
fcb5dac1 1036 tcg_out_bswap32(s, r1);
af266089 1037 tcg_out_st(s, TCG_TYPE_I32, r1, r0, GUEST_BASE);
c896fe29 1038 tcg_out_mov(s, r1, data_reg);
fcb5dac1 1039 tcg_out_bswap32(s, r1);
af266089 1040 tcg_out_st(s, TCG_TYPE_I32, r1, r0, GUEST_BASE + 4);
c896fe29 1041 } else {
af266089
RH
1042 tcg_out_st(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
1043 tcg_out_st(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE + 4);
c896fe29
FB
1044 }
1045 break;
1046 default:
1047 tcg_abort();
1048 }
1049
1050#if defined(CONFIG_SOFTMMU)
1051 /* label2: */
1052 *label2_ptr = s->code_ptr - label2_ptr - 1;
1053#endif
1054}
1055
a9751609 1056static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
c896fe29
FB
1057 const TCGArg *args, const int *const_args)
1058{
1059 int c;
1060
1061 switch(opc) {
1062 case INDEX_op_exit_tb:
1063 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EAX, args[0]);
da441cff 1064 tcg_out8(s, OPC_JMP_long); /* jmp tb_ret_addr */
b03cce8e 1065 tcg_out32(s, tb_ret_addr - s->code_ptr - 4);
c896fe29
FB
1066 break;
1067 case INDEX_op_goto_tb:
1068 if (s->tb_jmp_offset) {
1069 /* direct jump method */
da441cff 1070 tcg_out8(s, OPC_JMP_long); /* jmp im */
c896fe29
FB
1071 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1072 tcg_out32(s, 0);
1073 } else {
1074 /* indirect jump method */
9363dedb 1075 tcg_out_modrm_offset(s, OPC_GRP5, EXT5_JMPN_Ev, -1,
c896fe29
FB
1076 (tcg_target_long)(s->tb_next + args[0]));
1077 }
1078 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1079 break;
1080 case INDEX_op_call:
1081 if (const_args[0]) {
aadb21a4 1082 tcg_out_calli(s, args[0]);
c896fe29 1083 } else {
aadb21a4 1084 /* call *reg */
9363dedb 1085 tcg_out_modrm(s, OPC_GRP5, EXT5_CALLN_Ev, args[0]);
c896fe29
FB
1086 }
1087 break;
1088 case INDEX_op_jmp:
1089 if (const_args[0]) {
da441cff 1090 tcg_out8(s, OPC_JMP_long);
c896fe29
FB
1091 tcg_out32(s, args[0] - (tcg_target_long)s->code_ptr - 4);
1092 } else {
da441cff 1093 /* jmp *reg */
9363dedb 1094 tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, args[0]);
c896fe29
FB
1095 }
1096 break;
1097 case INDEX_op_br:
f75b56c1 1098 tcg_out_jxx(s, JCC_JMP, args[0], 0);
c896fe29
FB
1099 break;
1100 case INDEX_op_movi_i32:
1101 tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1102 break;
1103 case INDEX_op_ld8u_i32:
1104 /* movzbl */
55e082a7 1105 tcg_out_modrm_offset(s, OPC_MOVZBL, args[0], args[1], args[2]);
c896fe29
FB
1106 break;
1107 case INDEX_op_ld8s_i32:
1108 /* movsbl */
6817c355 1109 tcg_out_modrm_offset(s, OPC_MOVSBL, args[0], args[1], args[2]);
c896fe29
FB
1110 break;
1111 case INDEX_op_ld16u_i32:
1112 /* movzwl */
55e082a7 1113 tcg_out_modrm_offset(s, OPC_MOVZWL, args[0], args[1], args[2]);
c896fe29
FB
1114 break;
1115 case INDEX_op_ld16s_i32:
1116 /* movswl */
6817c355 1117 tcg_out_modrm_offset(s, OPC_MOVSWL, args[0], args[1], args[2]);
c896fe29
FB
1118 break;
1119 case INDEX_op_ld_i32:
af266089 1120 tcg_out_ld(s, TCG_TYPE_I32, args[0], args[1], args[2]);
c896fe29
FB
1121 break;
1122 case INDEX_op_st8_i32:
1123 /* movb */
af266089 1124 tcg_out_modrm_offset(s, OPC_MOVB_EvGv, args[0], args[1], args[2]);
c896fe29
FB
1125 break;
1126 case INDEX_op_st16_i32:
1127 /* movw */
1128 tcg_out8(s, 0x66);
af266089 1129 tcg_out_modrm_offset(s, OPC_MOVL_EvGv, args[0], args[1], args[2]);
c896fe29
FB
1130 break;
1131 case INDEX_op_st_i32:
af266089 1132 tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]);
c896fe29
FB
1133 break;
1134 case INDEX_op_sub_i32:
1135 c = ARITH_SUB;
1136 goto gen_arith;
1137 case INDEX_op_and_i32:
1138 c = ARITH_AND;
1139 goto gen_arith;
1140 case INDEX_op_or_i32:
1141 c = ARITH_OR;
1142 goto gen_arith;
1143 case INDEX_op_xor_i32:
1144 c = ARITH_XOR;
1145 goto gen_arith;
1146 case INDEX_op_add_i32:
1147 c = ARITH_ADD;
1148 gen_arith:
1149 if (const_args[2]) {
17cf428f 1150 tgen_arithi(s, c, args[0], args[2], 0);
c896fe29 1151 } else {
81570a70 1152 tgen_arithr(s, c, args[0], args[2]);
c896fe29
FB
1153 }
1154 break;
1155 case INDEX_op_mul_i32:
1156 if (const_args[2]) {
1157 int32_t val;
1158 val = args[2];
1159 if (val == (int8_t)val) {
1160 tcg_out_modrm(s, 0x6b, args[0], args[0]);
1161 tcg_out8(s, val);
1162 } else {
1163 tcg_out_modrm(s, 0x69, args[0], args[0]);
1164 tcg_out32(s, val);
1165 }
1166 } else {
1167 tcg_out_modrm(s, 0xaf | P_EXT, args[0], args[2]);
1168 }
1169 break;
1170 case INDEX_op_mulu2_i32:
9363dedb 1171 tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_MUL, args[3]);
c896fe29
FB
1172 break;
1173 case INDEX_op_div2_i32:
9363dedb 1174 tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_IDIV, args[4]);
c896fe29
FB
1175 break;
1176 case INDEX_op_divu2_i32:
9363dedb 1177 tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_DIV, args[4]);
c896fe29
FB
1178 break;
1179 case INDEX_op_shl_i32:
1180 c = SHIFT_SHL;
1181 gen_shift32:
1182 if (const_args[2]) {
f53dba01 1183 tcg_out_shifti(s, c, args[0], args[2]);
c896fe29 1184 } else {
f53dba01 1185 tcg_out_modrm(s, OPC_SHIFT_cl, c, args[0]);
c896fe29
FB
1186 }
1187 break;
1188 case INDEX_op_shr_i32:
1189 c = SHIFT_SHR;
1190 goto gen_shift32;
1191 case INDEX_op_sar_i32:
1192 c = SHIFT_SAR;
1193 goto gen_shift32;
9619376c
AJ
1194 case INDEX_op_rotl_i32:
1195 c = SHIFT_ROL;
1196 goto gen_shift32;
1197 case INDEX_op_rotr_i32:
1198 c = SHIFT_ROR;
1199 goto gen_shift32;
1200
c896fe29 1201 case INDEX_op_add2_i32:
81570a70 1202 if (const_args[4]) {
17cf428f 1203 tgen_arithi(s, ARITH_ADD, args[0], args[4], 1);
81570a70
RH
1204 } else {
1205 tgen_arithr(s, ARITH_ADD, args[0], args[4]);
1206 }
1207 if (const_args[5]) {
17cf428f 1208 tgen_arithi(s, ARITH_ADC, args[1], args[5], 1);
81570a70
RH
1209 } else {
1210 tgen_arithr(s, ARITH_ADC, args[1], args[5]);
1211 }
c896fe29
FB
1212 break;
1213 case INDEX_op_sub2_i32:
81570a70 1214 if (const_args[4]) {
17cf428f 1215 tgen_arithi(s, ARITH_SUB, args[0], args[4], 1);
81570a70
RH
1216 } else {
1217 tgen_arithr(s, ARITH_SUB, args[0], args[4]);
1218 }
1219 if (const_args[5]) {
17cf428f 1220 tgen_arithi(s, ARITH_SBB, args[1], args[5], 1);
81570a70
RH
1221 } else {
1222 tgen_arithr(s, ARITH_SBB, args[1], args[5]);
1223 }
c896fe29
FB
1224 break;
1225 case INDEX_op_brcond_i32:
f75b56c1
RH
1226 tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
1227 args[3], 0);
c896fe29
FB
1228 break;
1229 case INDEX_op_brcond2_i32:
f75b56c1 1230 tcg_out_brcond2(s, args, const_args, 0);
c896fe29
FB
1231 break;
1232
5d40cd63 1233 case INDEX_op_bswap16_i32:
fcb5dac1 1234 tcg_out_rolw_8(s, args[0]);
5d40cd63 1235 break;
66896cb8 1236 case INDEX_op_bswap32_i32:
fcb5dac1 1237 tcg_out_bswap32(s, args[0]);
9619376c
AJ
1238 break;
1239
1240 case INDEX_op_neg_i32:
9363dedb 1241 tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_NEG, args[0]);
9619376c
AJ
1242 break;
1243
1244 case INDEX_op_not_i32:
9363dedb 1245 tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_NOT, args[0]);
9619376c
AJ
1246 break;
1247
1248 case INDEX_op_ext8s_i32:
6817c355 1249 tcg_out_ext8s(s, args[0], args[1]);
9619376c
AJ
1250 break;
1251 case INDEX_op_ext16s_i32:
6817c355 1252 tcg_out_ext16s(s, args[0], args[1]);
9619376c 1253 break;
5f0ce17f 1254 case INDEX_op_ext8u_i32:
55e082a7 1255 tcg_out_ext8u(s, args[0], args[1]);
5f0ce17f
AJ
1256 break;
1257 case INDEX_op_ext16u_i32:
55e082a7 1258 tcg_out_ext16u(s, args[0], args[1]);
5f0ce17f 1259 break;
9619376c 1260
1d2699ae
RH
1261 case INDEX_op_setcond_i32:
1262 tcg_out_setcond(s, args[3], args[0], args[1], args[2], const_args[2]);
1263 break;
1264 case INDEX_op_setcond2_i32:
1265 tcg_out_setcond2(s, args, const_args);
1266 break;
1267
c896fe29
FB
1268 case INDEX_op_qemu_ld8u:
1269 tcg_out_qemu_ld(s, args, 0);
1270 break;
1271 case INDEX_op_qemu_ld8s:
1272 tcg_out_qemu_ld(s, args, 0 | 4);
1273 break;
1274 case INDEX_op_qemu_ld16u:
1275 tcg_out_qemu_ld(s, args, 1);
1276 break;
1277 case INDEX_op_qemu_ld16s:
1278 tcg_out_qemu_ld(s, args, 1 | 4);
1279 break;
86feb1c8 1280 case INDEX_op_qemu_ld32:
c896fe29
FB
1281 tcg_out_qemu_ld(s, args, 2);
1282 break;
1283 case INDEX_op_qemu_ld64:
1284 tcg_out_qemu_ld(s, args, 3);
1285 break;
1286
1287 case INDEX_op_qemu_st8:
1288 tcg_out_qemu_st(s, args, 0);
1289 break;
1290 case INDEX_op_qemu_st16:
1291 tcg_out_qemu_st(s, args, 1);
1292 break;
1293 case INDEX_op_qemu_st32:
1294 tcg_out_qemu_st(s, args, 2);
1295 break;
1296 case INDEX_op_qemu_st64:
1297 tcg_out_qemu_st(s, args, 3);
1298 break;
1299
1300 default:
1301 tcg_abort();
1302 }
1303}
1304
1305static const TCGTargetOpDef x86_op_defs[] = {
1306 { INDEX_op_exit_tb, { } },
1307 { INDEX_op_goto_tb, { } },
1308 { INDEX_op_call, { "ri" } },
1309 { INDEX_op_jmp, { "ri" } },
1310 { INDEX_op_br, { } },
1311 { INDEX_op_mov_i32, { "r", "r" } },
1312 { INDEX_op_movi_i32, { "r" } },
1313 { INDEX_op_ld8u_i32, { "r", "r" } },
1314 { INDEX_op_ld8s_i32, { "r", "r" } },
1315 { INDEX_op_ld16u_i32, { "r", "r" } },
1316 { INDEX_op_ld16s_i32, { "r", "r" } },
1317 { INDEX_op_ld_i32, { "r", "r" } },
1318 { INDEX_op_st8_i32, { "q", "r" } },
1319 { INDEX_op_st16_i32, { "r", "r" } },
1320 { INDEX_op_st_i32, { "r", "r" } },
1321
1322 { INDEX_op_add_i32, { "r", "0", "ri" } },
1323 { INDEX_op_sub_i32, { "r", "0", "ri" } },
1324 { INDEX_op_mul_i32, { "r", "0", "ri" } },
1325 { INDEX_op_mulu2_i32, { "a", "d", "a", "r" } },
1326 { INDEX_op_div2_i32, { "a", "d", "0", "1", "r" } },
1327 { INDEX_op_divu2_i32, { "a", "d", "0", "1", "r" } },
1328 { INDEX_op_and_i32, { "r", "0", "ri" } },
1329 { INDEX_op_or_i32, { "r", "0", "ri" } },
1330 { INDEX_op_xor_i32, { "r", "0", "ri" } },
1331
1332 { INDEX_op_shl_i32, { "r", "0", "ci" } },
1333 { INDEX_op_shr_i32, { "r", "0", "ci" } },
1334 { INDEX_op_sar_i32, { "r", "0", "ci" } },
9619376c
AJ
1335 { INDEX_op_rotl_i32, { "r", "0", "ci" } },
1336 { INDEX_op_rotr_i32, { "r", "0", "ci" } },
c896fe29
FB
1337
1338 { INDEX_op_brcond_i32, { "r", "ri" } },
1339
1340 { INDEX_op_add2_i32, { "r", "r", "0", "1", "ri", "ri" } },
1341 { INDEX_op_sub2_i32, { "r", "r", "0", "1", "ri", "ri" } },
1342 { INDEX_op_brcond2_i32, { "r", "r", "ri", "ri" } },
1343
5d40cd63 1344 { INDEX_op_bswap16_i32, { "r", "0" } },
66896cb8 1345 { INDEX_op_bswap32_i32, { "r", "0" } },
9619376c
AJ
1346
1347 { INDEX_op_neg_i32, { "r", "0" } },
1348
1349 { INDEX_op_not_i32, { "r", "0" } },
1350
1351 { INDEX_op_ext8s_i32, { "r", "q" } },
1352 { INDEX_op_ext16s_i32, { "r", "r" } },
55e082a7
RH
1353 { INDEX_op_ext8u_i32, { "r", "q" } },
1354 { INDEX_op_ext16u_i32, { "r", "r" } },
9619376c 1355
1d2699ae
RH
1356 { INDEX_op_setcond_i32, { "q", "r", "ri" } },
1357 { INDEX_op_setcond2_i32, { "r", "r", "r", "ri", "ri" } },
1358
c896fe29
FB
1359#if TARGET_LONG_BITS == 32
1360 { INDEX_op_qemu_ld8u, { "r", "L" } },
1361 { INDEX_op_qemu_ld8s, { "r", "L" } },
1362 { INDEX_op_qemu_ld16u, { "r", "L" } },
1363 { INDEX_op_qemu_ld16s, { "r", "L" } },
86feb1c8 1364 { INDEX_op_qemu_ld32, { "r", "L" } },
c896fe29
FB
1365 { INDEX_op_qemu_ld64, { "r", "r", "L" } },
1366
1367 { INDEX_op_qemu_st8, { "cb", "L" } },
1368 { INDEX_op_qemu_st16, { "L", "L" } },
1369 { INDEX_op_qemu_st32, { "L", "L" } },
1370 { INDEX_op_qemu_st64, { "L", "L", "L" } },
1371#else
1372 { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
1373 { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
1374 { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
1375 { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
86feb1c8 1376 { INDEX_op_qemu_ld32, { "r", "L", "L" } },
c896fe29
FB
1377 { INDEX_op_qemu_ld64, { "r", "r", "L", "L" } },
1378
1379 { INDEX_op_qemu_st8, { "cb", "L", "L" } },
1380 { INDEX_op_qemu_st16, { "L", "L", "L" } },
1381 { INDEX_op_qemu_st32, { "L", "L", "L" } },
1382 { INDEX_op_qemu_st64, { "L", "L", "L", "L" } },
1383#endif
1384 { -1 },
1385};
1386
b03cce8e
FB
1387static int tcg_target_callee_save_regs[] = {
1388 /* TCG_REG_EBP, */ /* currently used for the global env, so no
1389 need to save */
1390 TCG_REG_EBX,
1391 TCG_REG_ESI,
1392 TCG_REG_EDI,
1393};
1394
b03cce8e
FB
1395/* Generate global QEMU prologue and epilogue code */
1396void tcg_target_qemu_prologue(TCGContext *s)
1397{
1398 int i, frame_size, push_size, stack_addend;
1399
1400 /* TB prologue */
1401 /* save all callee saved registers */
1402 for(i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
1403 tcg_out_push(s, tcg_target_callee_save_regs[i]);
1404 }
1405 /* reserve some stack space */
1406 push_size = 4 + ARRAY_SIZE(tcg_target_callee_save_regs) * 4;
1407 frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE;
1408 frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1409 ~(TCG_TARGET_STACK_ALIGN - 1);
1410 stack_addend = frame_size - push_size;
1411 tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
1412
9363dedb 1413 tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, TCG_REG_EAX); /* jmp *%eax */
b03cce8e
FB
1414
1415 /* TB epilogue */
1416 tb_ret_addr = s->code_ptr;
1417 tcg_out_addi(s, TCG_REG_ESP, stack_addend);
1418 for(i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
1419 tcg_out_pop(s, tcg_target_callee_save_regs[i]);
1420 }
3c3accc6 1421 tcg_out_opc(s, OPC_RET);
b03cce8e
FB
1422}
1423
c896fe29
FB
1424void tcg_target_init(TCGContext *s)
1425{
20cb400d 1426#if !defined(CONFIG_USER_ONLY)
c896fe29
FB
1427 /* fail safe */
1428 if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
1429 tcg_abort();
20cb400d 1430#endif
c896fe29
FB
1431
1432 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xff);
4ab50ccf
RH
1433
1434 tcg_regset_clear(tcg_target_call_clobber_regs);
1435 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EAX);
1436 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EDX);
1437 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_ECX);
1438
c896fe29
FB
1439 tcg_regset_clear(s->reserved_regs);
1440 tcg_regset_set_reg(s->reserved_regs, TCG_REG_ESP);
1441
1442 tcg_add_target_add_op_defs(x86_op_defs);
1443}