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