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