block: default to 0 minimal / optiomal I/O size
[qemu.git] / tcg / mips / tcg-target.c
blob2af7a2e818ad5265fc524805dd1546b31567a21f
1 /*
2 * Tiny Code Generator for QEMU
4 * Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org>
5 * Copyright (c) 2009 Aurelien Jarno <aurelien@aurel32.net>
6 * Based on i386/tcg-target.c - Copyright (c) 2008 Fabrice Bellard
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
27 #if defined(TCG_TARGET_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
28 # define TCG_NEED_BSWAP 0
29 #else
30 # define TCG_NEED_BSWAP 1
31 #endif
33 #ifndef NDEBUG
34 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
35 "zero",
36 "at",
37 "v0",
38 "v1",
39 "a0",
40 "a1",
41 "a2",
42 "a3",
43 "t0",
44 "t1",
45 "t2",
46 "t3",
47 "t4",
48 "t5",
49 "t6",
50 "t7",
51 "s0",
52 "s1",
53 "s2",
54 "s3",
55 "s4",
56 "s5",
57 "s6",
58 "s7",
59 "t8",
60 "t9",
61 "k0",
62 "k1",
63 "gp",
64 "sp",
65 "fp",
66 "ra",
68 #endif
70 /* check if we really need so many registers :P */
71 static const int tcg_target_reg_alloc_order[] = {
72 TCG_REG_S0,
73 TCG_REG_S1,
74 TCG_REG_S2,
75 TCG_REG_S3,
76 TCG_REG_S4,
77 TCG_REG_S5,
78 TCG_REG_S6,
79 TCG_REG_S7,
80 TCG_REG_T1,
81 TCG_REG_T2,
82 TCG_REG_T3,
83 TCG_REG_T4,
84 TCG_REG_T5,
85 TCG_REG_T6,
86 TCG_REG_T7,
87 TCG_REG_T8,
88 TCG_REG_T9,
89 TCG_REG_A0,
90 TCG_REG_A1,
91 TCG_REG_A2,
92 TCG_REG_A3,
93 TCG_REG_V0,
94 TCG_REG_V1
97 static const int tcg_target_call_iarg_regs[4] = {
98 TCG_REG_A0,
99 TCG_REG_A1,
100 TCG_REG_A2,
101 TCG_REG_A3
104 static const int tcg_target_call_oarg_regs[2] = {
105 TCG_REG_V0,
106 TCG_REG_V1
109 static uint8_t *tb_ret_addr;
111 static inline uint32_t reloc_lo16_val (void *pc, tcg_target_long target)
113 return target & 0xffff;
116 static inline void reloc_lo16 (void *pc, tcg_target_long target)
118 *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
119 | reloc_lo16_val(pc, target);
122 static inline uint32_t reloc_hi16_val (void *pc, tcg_target_long target)
124 return (target >> 16) & 0xffff;
127 static inline void reloc_hi16 (void *pc, tcg_target_long target)
129 *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
130 | reloc_hi16_val(pc, target);
133 static inline uint32_t reloc_pc16_val (void *pc, tcg_target_long target)
135 int32_t disp;
137 disp = target - (tcg_target_long) pc - 4;
138 if (disp != (disp << 14) >> 14) {
139 tcg_abort ();
142 return (disp >> 2) & 0xffff;
145 static inline void reloc_pc16 (void *pc, tcg_target_long target)
147 *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
148 | reloc_pc16_val(pc, target);
151 static inline uint32_t reloc_26_val (void *pc, tcg_target_long target)
153 if ((((tcg_target_long)pc + 4) & 0xf0000000) != (target & 0xf0000000)) {
154 tcg_abort ();
157 return (target >> 2) & 0x3ffffff;
160 static inline void reloc_pc26 (void *pc, tcg_target_long target)
162 *(uint32_t *) pc = (*(uint32_t *) pc & ~0x3ffffff)
163 | reloc_26_val(pc, target);
166 static void patch_reloc(uint8_t *code_ptr, int type,
167 tcg_target_long value, tcg_target_long addend)
169 value += addend;
170 switch(type) {
171 case R_MIPS_LO16:
172 reloc_lo16(code_ptr, value);
173 break;
174 case R_MIPS_HI16:
175 reloc_hi16(code_ptr, value);
176 break;
177 case R_MIPS_PC16:
178 reloc_pc16(code_ptr, value);
179 break;
180 case R_MIPS_26:
181 reloc_pc26(code_ptr, value);
182 break;
183 default:
184 tcg_abort();
188 /* maximum number of register used for input function arguments */
189 static inline int tcg_target_get_call_iarg_regs_count(int flags)
191 return 4;
194 /* parse target specific constraints */
195 static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
197 const char *ct_str;
199 ct_str = *pct_str;
200 switch(ct_str[0]) {
201 case 'r':
202 ct->ct |= TCG_CT_REG;
203 tcg_regset_set(ct->u.regs, 0xffffffff);
204 break;
205 case 'C':
206 ct->ct |= TCG_CT_REG;
207 tcg_regset_clear(ct->u.regs);
208 tcg_regset_set_reg(ct->u.regs, TCG_REG_T9);
209 break;
210 case 'L': /* qemu_ld output arg constraint */
211 ct->ct |= TCG_CT_REG;
212 tcg_regset_set(ct->u.regs, 0xffffffff);
213 tcg_regset_reset_reg(ct->u.regs, TCG_REG_V0);
214 break;
215 case 'l': /* qemu_ld input arg constraint */
216 ct->ct |= TCG_CT_REG;
217 tcg_regset_set(ct->u.regs, 0xffffffff);
218 #if defined(CONFIG_SOFTMMU)
219 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
220 #endif
221 break;
222 case 'S': /* qemu_st constraint */
223 ct->ct |= TCG_CT_REG;
224 tcg_regset_set(ct->u.regs, 0xffffffff);
225 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
226 #if defined(CONFIG_SOFTMMU)
227 # if TARGET_LONG_BITS == 64
228 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1);
229 # endif
230 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
231 #endif
232 break;
233 case 'I':
234 ct->ct |= TCG_CT_CONST_U16;
235 break;
236 case 'J':
237 ct->ct |= TCG_CT_CONST_S16;
238 break;
239 case 'Z':
240 /* We are cheating a bit here, using the fact that the register
241 ZERO is also the register number 0. Hence there is no need
242 to check for const_args in each instruction. */
243 ct->ct |= TCG_CT_CONST_ZERO;
244 break;
245 default:
246 return -1;
248 ct_str++;
249 *pct_str = ct_str;
250 return 0;
253 /* test if a constant matches the constraint */
254 static inline int tcg_target_const_match(tcg_target_long val,
255 const TCGArgConstraint *arg_ct)
257 int ct;
258 ct = arg_ct->ct;
259 if (ct & TCG_CT_CONST)
260 return 1;
261 else if ((ct & TCG_CT_CONST_ZERO) && val == 0)
262 return 1;
263 else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val)
264 return 1;
265 else if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val)
266 return 1;
267 else
268 return 0;
271 /* instruction opcodes */
272 enum {
273 OPC_BEQ = 0x04 << 26,
274 OPC_BNE = 0x05 << 26,
275 OPC_ADDIU = 0x09 << 26,
276 OPC_SLTI = 0x0A << 26,
277 OPC_SLTIU = 0x0B << 26,
278 OPC_ANDI = 0x0C << 26,
279 OPC_ORI = 0x0D << 26,
280 OPC_XORI = 0x0E << 26,
281 OPC_LUI = 0x0F << 26,
282 OPC_LB = 0x20 << 26,
283 OPC_LH = 0x21 << 26,
284 OPC_LW = 0x23 << 26,
285 OPC_LBU = 0x24 << 26,
286 OPC_LHU = 0x25 << 26,
287 OPC_LWU = 0x27 << 26,
288 OPC_SB = 0x28 << 26,
289 OPC_SH = 0x29 << 26,
290 OPC_SW = 0x2B << 26,
292 OPC_SPECIAL = 0x00 << 26,
293 OPC_SLL = OPC_SPECIAL | 0x00,
294 OPC_SRL = OPC_SPECIAL | 0x02,
295 OPC_SRA = OPC_SPECIAL | 0x03,
296 OPC_SLLV = OPC_SPECIAL | 0x04,
297 OPC_SRLV = OPC_SPECIAL | 0x06,
298 OPC_SRAV = OPC_SPECIAL | 0x07,
299 OPC_JR = OPC_SPECIAL | 0x08,
300 OPC_JALR = OPC_SPECIAL | 0x09,
301 OPC_MFHI = OPC_SPECIAL | 0x10,
302 OPC_MFLO = OPC_SPECIAL | 0x12,
303 OPC_MULT = OPC_SPECIAL | 0x18,
304 OPC_MULTU = OPC_SPECIAL | 0x19,
305 OPC_DIV = OPC_SPECIAL | 0x1A,
306 OPC_DIVU = OPC_SPECIAL | 0x1B,
307 OPC_ADDU = OPC_SPECIAL | 0x21,
308 OPC_SUBU = OPC_SPECIAL | 0x23,
309 OPC_AND = OPC_SPECIAL | 0x24,
310 OPC_OR = OPC_SPECIAL | 0x25,
311 OPC_XOR = OPC_SPECIAL | 0x26,
312 OPC_NOR = OPC_SPECIAL | 0x27,
313 OPC_SLT = OPC_SPECIAL | 0x2A,
314 OPC_SLTU = OPC_SPECIAL | 0x2B,
316 OPC_SPECIAL3 = 0x1f << 26,
317 OPC_SEB = OPC_SPECIAL3 | 0x420,
318 OPC_SEH = OPC_SPECIAL3 | 0x620,
322 * Type reg
324 static inline void tcg_out_opc_reg(TCGContext *s, int opc, int rd, int rs, int rt)
326 int32_t inst;
328 inst = opc;
329 inst |= (rs & 0x1F) << 21;
330 inst |= (rt & 0x1F) << 16;
331 inst |= (rd & 0x1F) << 11;
332 tcg_out32(s, inst);
336 * Type immediate
338 static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int imm)
340 int32_t inst;
342 inst = opc;
343 inst |= (rs & 0x1F) << 21;
344 inst |= (rt & 0x1F) << 16;
345 inst |= (imm & 0xffff);
346 tcg_out32(s, inst);
350 * Type branch
352 static inline void tcg_out_opc_br(TCGContext *s, int opc, int rt, int rs)
354 /* We need to keep the offset unchanged for retranslation */
355 uint16_t offset = (uint16_t)(*(uint32_t *) &s->code_ptr);
357 tcg_out_opc_imm(s, opc, rt, rs, offset);
361 * Type sa
363 static inline void tcg_out_opc_sa(TCGContext *s, int opc, int rd, int rt, int sa)
365 int32_t inst;
367 inst = opc;
368 inst |= (rt & 0x1F) << 16;
369 inst |= (rd & 0x1F) << 11;
370 inst |= (sa & 0x1F) << 6;
371 tcg_out32(s, inst);
375 static inline void tcg_out_nop(TCGContext *s)
377 tcg_out32(s, 0);
380 static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
382 tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
385 static inline void tcg_out_movi(TCGContext *s, TCGType type,
386 int reg, int32_t arg)
388 if (arg == (int16_t)arg) {
389 tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
390 } else if (arg == (uint16_t)arg) {
391 tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
392 } else {
393 tcg_out_opc_imm(s, OPC_LUI, reg, 0, arg >> 16);
394 tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0xffff);
398 static inline void tcg_out_bswap16(TCGContext *s, int ret, int arg)
400 /* ret and arg can't be register at */
401 if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
402 tcg_abort();
405 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
406 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0x00ff);
408 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
409 tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
410 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
413 static inline void tcg_out_bswap16s(TCGContext *s, int ret, int arg)
415 /* ret and arg can't be register at */
416 if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
417 tcg_abort();
420 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
421 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff);
423 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
424 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
425 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
428 static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg)
430 /* ret and arg must be different and can't be register at */
431 if (ret == arg || ret == TCG_REG_AT || arg == TCG_REG_AT) {
432 tcg_abort();
435 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
437 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 24);
438 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
440 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, arg, 0xff00);
441 tcg_out_opc_sa(s, OPC_SLL, TCG_REG_AT, TCG_REG_AT, 8);
442 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
444 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
445 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff00);
446 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
449 static inline void tcg_out_ext8s(TCGContext *s, int ret, int arg)
451 #ifdef _MIPS_ARCH_MIPS32R2
452 tcg_out_opc_reg(s, OPC_SEB, ret, 0, arg);
453 #else
454 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
455 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 24);
456 #endif
459 static inline void tcg_out_ext16s(TCGContext *s, int ret, int arg)
461 #ifdef _MIPS_ARCH_MIPS32R2
462 tcg_out_opc_reg(s, OPC_SEH, ret, 0, arg);
463 #else
464 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 16);
465 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
466 #endif
469 static inline void tcg_out_ldst(TCGContext *s, int opc, int arg,
470 int arg1, tcg_target_long arg2)
472 if (arg2 == (int16_t) arg2) {
473 tcg_out_opc_imm(s, opc, arg, arg1, arg2);
474 } else {
475 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, arg2);
476 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, TCG_REG_AT, arg1);
477 tcg_out_opc_imm(s, opc, arg, TCG_REG_AT, 0);
481 static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg,
482 int arg1, tcg_target_long arg2)
484 tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
487 static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
488 int arg1, tcg_target_long arg2)
490 tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
493 static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
495 if (val == (int16_t)val) {
496 tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
497 } else {
498 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, val);
499 tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_REG_AT);
503 static void tcg_out_brcond(TCGContext *s, TCGCond cond, int arg1,
504 int arg2, int label_index)
506 TCGLabel *l = &s->labels[label_index];
508 switch (cond) {
509 case TCG_COND_EQ:
510 tcg_out_opc_br(s, OPC_BEQ, arg1, arg2);
511 break;
512 case TCG_COND_NE:
513 tcg_out_opc_br(s, OPC_BNE, arg1, arg2);
514 break;
515 case TCG_COND_LT:
516 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
517 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
518 break;
519 case TCG_COND_LTU:
520 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
521 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
522 break;
523 case TCG_COND_GE:
524 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
525 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
526 break;
527 case TCG_COND_GEU:
528 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
529 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
530 break;
531 case TCG_COND_LE:
532 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
533 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
534 break;
535 case TCG_COND_LEU:
536 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
537 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
538 break;
539 case TCG_COND_GT:
540 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
541 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
542 break;
543 case TCG_COND_GTU:
544 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
545 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
546 break;
547 default:
548 tcg_abort();
549 break;
551 if (l->has_value) {
552 reloc_pc16(s->code_ptr - 4, l->u.value);
553 } else {
554 tcg_out_reloc(s, s->code_ptr - 4, R_MIPS_PC16, label_index, 0);
556 tcg_out_nop(s);
559 /* XXX: we implement it at the target level to avoid having to
560 handle cross basic blocks temporaries */
561 static void tcg_out_brcond2(TCGContext *s, TCGCond cond, int arg1,
562 int arg2, int arg3, int arg4, int label_index)
564 void *label_ptr;
566 switch(cond) {
567 case TCG_COND_NE:
568 tcg_out_brcond(s, TCG_COND_NE, arg2, arg4, label_index);
569 tcg_out_brcond(s, TCG_COND_NE, arg1, arg3, label_index);
570 return;
571 case TCG_COND_EQ:
572 break;
573 case TCG_COND_LT:
574 case TCG_COND_LE:
575 tcg_out_brcond(s, TCG_COND_LT, arg2, arg4, label_index);
576 break;
577 case TCG_COND_GT:
578 case TCG_COND_GE:
579 tcg_out_brcond(s, TCG_COND_GT, arg2, arg4, label_index);
580 break;
581 case TCG_COND_LTU:
582 case TCG_COND_LEU:
583 tcg_out_brcond(s, TCG_COND_LTU, arg2, arg4, label_index);
584 break;
585 case TCG_COND_GTU:
586 case TCG_COND_GEU:
587 tcg_out_brcond(s, TCG_COND_GTU, arg2, arg4, label_index);
588 break;
589 default:
590 tcg_abort();
593 label_ptr = s->code_ptr;
594 tcg_out_opc_br(s, OPC_BNE, arg2, arg4);
595 tcg_out_nop(s);
597 switch(cond) {
598 case TCG_COND_EQ:
599 tcg_out_brcond(s, TCG_COND_EQ, arg1, arg3, label_index);
600 break;
601 case TCG_COND_LT:
602 case TCG_COND_LTU:
603 tcg_out_brcond(s, TCG_COND_LTU, arg1, arg3, label_index);
604 break;
605 case TCG_COND_LE:
606 case TCG_COND_LEU:
607 tcg_out_brcond(s, TCG_COND_LEU, arg1, arg3, label_index);
608 break;
609 case TCG_COND_GT:
610 case TCG_COND_GTU:
611 tcg_out_brcond(s, TCG_COND_GTU, arg1, arg3, label_index);
612 break;
613 case TCG_COND_GE:
614 case TCG_COND_GEU:
615 tcg_out_brcond(s, TCG_COND_GEU, arg1, arg3, label_index);
616 break;
617 default:
618 tcg_abort();
621 reloc_pc16(label_ptr, (tcg_target_long) s->code_ptr);
624 static void tcg_out_setcond(TCGContext *s, TCGCond cond, int ret,
625 int arg1, int arg2)
627 switch (cond) {
628 case TCG_COND_EQ:
629 if (arg1 == 0) {
630 tcg_out_opc_imm(s, OPC_SLTIU, ret, arg2, 1);
631 } else if (arg2 == 0) {
632 tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, 1);
633 } else {
634 tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
635 tcg_out_opc_imm(s, OPC_SLTIU, ret, ret, 1);
637 break;
638 case TCG_COND_NE:
639 if (arg1 == 0) {
640 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg2);
641 } else if (arg2 == 0) {
642 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg1);
643 } else {
644 tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
645 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, ret);
647 break;
648 case TCG_COND_LT:
649 tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
650 break;
651 case TCG_COND_LTU:
652 tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
653 break;
654 case TCG_COND_GE:
655 tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
656 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
657 break;
658 case TCG_COND_GEU:
659 tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
660 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
661 break;
662 case TCG_COND_LE:
663 tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
664 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
665 break;
666 case TCG_COND_LEU:
667 tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
668 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
669 break;
670 case TCG_COND_GT:
671 tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
672 break;
673 case TCG_COND_GTU:
674 tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
675 break;
676 default:
677 tcg_abort();
678 break;
682 /* XXX: we implement it at the target level to avoid having to
683 handle cross basic blocks temporaries */
684 static void tcg_out_setcond2(TCGContext *s, TCGCond cond, int ret,
685 int arg1, int arg2, int arg3, int arg4)
687 switch (cond) {
688 case TCG_COND_EQ:
689 tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_AT, arg2, arg4);
690 tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg1, arg3);
691 tcg_out_opc_reg(s, OPC_AND, ret, TCG_REG_AT, TCG_REG_T0);
692 return;
693 case TCG_COND_NE:
694 tcg_out_setcond(s, TCG_COND_NE, TCG_REG_AT, arg2, arg4);
695 tcg_out_setcond(s, TCG_COND_NE, TCG_REG_T0, arg1, arg3);
696 tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_AT, TCG_REG_T0);
697 return;
698 case TCG_COND_LT:
699 case TCG_COND_LE:
700 tcg_out_setcond(s, TCG_COND_LT, TCG_REG_AT, arg2, arg4);
701 break;
702 case TCG_COND_GT:
703 case TCG_COND_GE:
704 tcg_out_setcond(s, TCG_COND_GT, TCG_REG_AT, arg2, arg4);
705 break;
706 case TCG_COND_LTU:
707 case TCG_COND_LEU:
708 tcg_out_setcond(s, TCG_COND_LTU, TCG_REG_AT, arg2, arg4);
709 break;
710 case TCG_COND_GTU:
711 case TCG_COND_GEU:
712 tcg_out_setcond(s, TCG_COND_GTU, TCG_REG_AT, arg2, arg4);
713 break;
714 default:
715 tcg_abort();
716 break;
719 tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg2, arg4);
721 switch(cond) {
722 case TCG_COND_LT:
723 case TCG_COND_LTU:
724 tcg_out_setcond(s, TCG_COND_LTU, ret, arg1, arg3);
725 break;
726 case TCG_COND_LE:
727 case TCG_COND_LEU:
728 tcg_out_setcond(s, TCG_COND_LEU, ret, arg1, arg3);
729 break;
730 case TCG_COND_GT:
731 case TCG_COND_GTU:
732 tcg_out_setcond(s, TCG_COND_GTU, ret, arg1, arg3);
733 break;
734 case TCG_COND_GE:
735 case TCG_COND_GEU:
736 tcg_out_setcond(s, TCG_COND_GEU, ret, arg1, arg3);
737 break;
738 default:
739 tcg_abort();
742 tcg_out_opc_reg(s, OPC_AND, ret, ret, TCG_REG_T0);
743 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
746 #if defined(CONFIG_SOFTMMU)
748 #include "../../softmmu_defs.h"
750 static void *qemu_ld_helpers[4] = {
751 __ldb_mmu,
752 __ldw_mmu,
753 __ldl_mmu,
754 __ldq_mmu,
757 static void *qemu_st_helpers[4] = {
758 __stb_mmu,
759 __stw_mmu,
760 __stl_mmu,
761 __stq_mmu,
763 #endif
765 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
766 int opc)
768 int addr_regl, addr_reg1, addr_meml;
769 int data_regl, data_regh, data_reg1, data_reg2;
770 int mem_index, s_bits;
771 #if defined(CONFIG_SOFTMMU)
772 void *label1_ptr, *label2_ptr;
773 int sp_args;
774 #endif
775 #if TARGET_LONG_BITS == 64
776 # if defined(CONFIG_SOFTMMU)
777 uint8_t *label3_ptr;
778 # endif
779 int addr_regh, addr_reg2, addr_memh;
780 #endif
781 data_regl = *args++;
782 if (opc == 3)
783 data_regh = *args++;
784 else
785 data_regh = 0;
786 addr_regl = *args++;
787 #if TARGET_LONG_BITS == 64
788 addr_regh = *args++;
789 #endif
790 mem_index = *args;
791 s_bits = opc & 3;
793 if (opc == 3) {
794 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
795 data_reg1 = data_regh;
796 data_reg2 = data_regl;
797 #else
798 data_reg1 = data_regl;
799 data_reg2 = data_regh;
800 #endif
801 } else {
802 data_reg1 = data_regl;
803 data_reg2 = 0;
805 #if TARGET_LONG_BITS == 64
806 # if defined(TCG_TARGET_WORDS_BIGENDIAN)
807 addr_reg1 = addr_regh;
808 addr_reg2 = addr_regl;
809 addr_memh = 0;
810 addr_meml = 4;
811 # else
812 addr_reg1 = addr_regl;
813 addr_reg2 = addr_regh;
814 addr_memh = 4;
815 addr_meml = 0;
816 # endif
817 #else
818 addr_reg1 = addr_regl;
819 addr_meml = 0;
820 #endif
822 #if defined(CONFIG_SOFTMMU)
823 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
824 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
825 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
826 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
827 offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_meml);
828 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
829 tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
831 # if TARGET_LONG_BITS == 64
832 label3_ptr = s->code_ptr;
833 tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
834 tcg_out_nop(s);
836 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
837 offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_memh);
839 label1_ptr = s->code_ptr;
840 tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
841 tcg_out_nop(s);
843 reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
844 # else
845 label1_ptr = s->code_ptr;
846 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
847 tcg_out_nop(s);
848 # endif
850 /* slow path */
851 sp_args = TCG_REG_A0;
852 tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg1);
853 # if TARGET_LONG_BITS == 64
854 tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg2);
855 # endif
856 tcg_out_movi(s, TCG_TYPE_I32, sp_args++, mem_index);
857 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]);
858 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
859 tcg_out_nop(s);
861 switch(opc) {
862 case 0:
863 tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xff);
864 break;
865 case 0 | 4:
866 tcg_out_ext8s(s, data_reg1, TCG_REG_V0);
867 break;
868 case 1:
869 tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xffff);
870 break;
871 case 1 | 4:
872 tcg_out_ext16s(s, data_reg1, TCG_REG_V0);
873 break;
874 case 2:
875 tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
876 break;
877 case 3:
878 tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_V1);
879 tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
880 break;
881 default:
882 tcg_abort();
885 label2_ptr = s->code_ptr;
886 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
887 tcg_out_nop(s);
889 /* label1: fast path */
890 reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
892 tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
893 offsetof(CPUState, tlb_table[mem_index][0].addend));
894 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_A0, addr_regl);
895 #else
896 if (GUEST_BASE == (int16_t)GUEST_BASE) {
897 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_V0, addr_regl, GUEST_BASE);
898 } else {
899 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, GUEST_BASE);
900 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_V0, addr_regl);
902 #endif
904 switch(opc) {
905 case 0:
906 tcg_out_opc_imm(s, OPC_LBU, data_reg1, TCG_REG_V0, 0);
907 break;
908 case 0 | 4:
909 tcg_out_opc_imm(s, OPC_LB, data_reg1, TCG_REG_V0, 0);
910 break;
911 case 1:
912 if (TCG_NEED_BSWAP) {
913 tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
914 tcg_out_bswap16(s, data_reg1, TCG_REG_T0);
915 } else {
916 tcg_out_opc_imm(s, OPC_LHU, data_reg1, TCG_REG_V0, 0);
918 break;
919 case 1 | 4:
920 if (TCG_NEED_BSWAP) {
921 tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
922 tcg_out_bswap16s(s, data_reg1, TCG_REG_T0);
923 } else {
924 tcg_out_opc_imm(s, OPC_LH, data_reg1, TCG_REG_V0, 0);
926 break;
927 case 2:
928 if (TCG_NEED_BSWAP) {
929 tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
930 tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
931 } else {
932 tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
934 break;
935 case 3:
936 if (TCG_NEED_BSWAP) {
937 tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 4);
938 tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
939 tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
940 tcg_out_bswap32(s, data_reg2, TCG_REG_T0);
941 } else {
942 tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
943 tcg_out_opc_imm(s, OPC_LW, data_reg2, TCG_REG_V0, 4);
945 break;
946 default:
947 tcg_abort();
950 #if defined(CONFIG_SOFTMMU)
951 reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
952 #endif
955 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
956 int opc)
958 int addr_regl, addr_reg1, addr_meml;
959 int data_regl, data_regh, data_reg1, data_reg2;
960 int mem_index, s_bits;
961 #if defined(CONFIG_SOFTMMU)
962 uint8_t *label1_ptr, *label2_ptr;
963 int sp_args;
964 #endif
965 #if TARGET_LONG_BITS == 64
966 # if defined(CONFIG_SOFTMMU)
967 uint8_t *label3_ptr;
968 # endif
969 int addr_regh, addr_reg2, addr_memh;
970 #endif
972 data_regl = *args++;
973 if (opc == 3) {
974 data_regh = *args++;
975 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
976 data_reg1 = data_regh;
977 data_reg2 = data_regl;
978 #else
979 data_reg1 = data_regl;
980 data_reg2 = data_regh;
981 #endif
982 } else {
983 data_reg1 = data_regl;
984 data_reg2 = 0;
985 data_regh = 0;
987 addr_regl = *args++;
988 #if TARGET_LONG_BITS == 64
989 addr_regh = *args++;
990 # if defined(TCG_TARGET_WORDS_BIGENDIAN)
991 addr_reg1 = addr_regh;
992 addr_reg2 = addr_regl;
993 addr_memh = 0;
994 addr_meml = 4;
995 # else
996 addr_reg1 = addr_regl;
997 addr_reg2 = addr_regh;
998 addr_memh = 4;
999 addr_meml = 0;
1000 # endif
1001 #else
1002 addr_reg1 = addr_regl;
1003 addr_meml = 0;
1004 #endif
1005 mem_index = *args;
1006 s_bits = opc;
1008 #if defined(CONFIG_SOFTMMU)
1009 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
1010 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
1011 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
1012 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
1013 offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_meml);
1014 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
1015 tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
1017 # if TARGET_LONG_BITS == 64
1018 label3_ptr = s->code_ptr;
1019 tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
1020 tcg_out_nop(s);
1022 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
1023 offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_memh);
1025 label1_ptr = s->code_ptr;
1026 tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
1027 tcg_out_nop(s);
1029 reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
1030 # else
1031 label1_ptr = s->code_ptr;
1032 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
1033 tcg_out_nop(s);
1034 # endif
1036 /* slow path */
1037 sp_args = TCG_REG_A0;
1038 tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg1);
1039 # if TARGET_LONG_BITS == 64
1040 tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg2);
1041 # endif
1042 switch(opc) {
1043 case 0:
1044 tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xff);
1045 break;
1046 case 1:
1047 tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xffff);
1048 break;
1049 case 2:
1050 tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg1);
1051 break;
1052 case 3:
1053 sp_args = (sp_args + 1) & ~1;
1054 tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg1);
1055 tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg2);
1056 break;
1057 default:
1058 tcg_abort();
1060 if (sp_args > TCG_REG_A3) {
1061 /* Push mem_index on the stack */
1062 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, mem_index);
1063 tcg_out_st(s, TCG_TYPE_I32, TCG_REG_AT, TCG_REG_SP, 16);
1064 } else {
1065 tcg_out_movi(s, TCG_TYPE_I32, sp_args, mem_index);
1068 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_st_helpers[s_bits]);
1069 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
1070 tcg_out_nop(s);
1072 label2_ptr = s->code_ptr;
1073 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
1074 tcg_out_nop(s);
1076 /* label1: fast path */
1077 reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
1079 tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
1080 offsetof(CPUState, tlb_table[mem_index][0].addend));
1081 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
1082 #else
1083 if (GUEST_BASE == (int16_t)GUEST_BASE) {
1084 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_A0, addr_regl, GUEST_BASE);
1085 } else {
1086 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, GUEST_BASE);
1087 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
1090 #endif
1092 switch(opc) {
1093 case 0:
1094 tcg_out_opc_imm(s, OPC_SB, data_reg1, TCG_REG_A0, 0);
1095 break;
1096 case 1:
1097 if (TCG_NEED_BSWAP) {
1098 tcg_out_bswap16(s, TCG_REG_T0, data_reg1);
1099 tcg_out_opc_imm(s, OPC_SH, TCG_REG_T0, TCG_REG_A0, 0);
1100 } else {
1101 tcg_out_opc_imm(s, OPC_SH, data_reg1, TCG_REG_A0, 0);
1103 break;
1104 case 2:
1105 if (TCG_NEED_BSWAP) {
1106 tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1107 tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
1108 } else {
1109 tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
1111 break;
1112 case 3:
1113 if (TCG_NEED_BSWAP) {
1114 tcg_out_bswap32(s, TCG_REG_T0, data_reg2);
1115 tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
1116 tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1117 tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 4);
1118 } else {
1119 tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
1120 tcg_out_opc_imm(s, OPC_SW, data_reg2, TCG_REG_A0, 4);
1122 break;
1123 default:
1124 tcg_abort();
1127 #if defined(CONFIG_SOFTMMU)
1128 reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
1129 #endif
1132 static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1133 const TCGArg *args, const int *const_args)
1135 switch(opc) {
1136 case INDEX_op_exit_tb:
1137 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_V0, args[0]);
1138 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, (tcg_target_long)tb_ret_addr);
1139 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1140 tcg_out_nop(s);
1141 break;
1142 case INDEX_op_goto_tb:
1143 if (s->tb_jmp_offset) {
1144 /* direct jump method */
1145 tcg_abort();
1146 } else {
1147 /* indirect jump method */
1148 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, (tcg_target_long)(s->tb_next + args[0]));
1149 tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_AT, TCG_REG_AT, 0);
1150 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1152 tcg_out_nop(s);
1153 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1154 break;
1155 case INDEX_op_call:
1156 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, args[0], 0);
1157 tcg_out_nop(s);
1158 break;
1159 case INDEX_op_jmp:
1160 tcg_out_opc_reg(s, OPC_JR, 0, args[0], 0);
1161 tcg_out_nop(s);
1162 break;
1163 case INDEX_op_br:
1164 tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, args[0]);
1165 break;
1167 case INDEX_op_mov_i32:
1168 tcg_out_mov(s, TCG_TYPE_I32, args[0], args[1]);
1169 break;
1170 case INDEX_op_movi_i32:
1171 tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1172 break;
1174 case INDEX_op_ld8u_i32:
1175 tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]);
1176 break;
1177 case INDEX_op_ld8s_i32:
1178 tcg_out_ldst(s, OPC_LB, args[0], args[1], args[2]);
1179 break;
1180 case INDEX_op_ld16u_i32:
1181 tcg_out_ldst(s, OPC_LHU, args[0], args[1], args[2]);
1182 break;
1183 case INDEX_op_ld16s_i32:
1184 tcg_out_ldst(s, OPC_LH, args[0], args[1], args[2]);
1185 break;
1186 case INDEX_op_ld_i32:
1187 tcg_out_ldst(s, OPC_LW, args[0], args[1], args[2]);
1188 break;
1189 case INDEX_op_st8_i32:
1190 tcg_out_ldst(s, OPC_SB, args[0], args[1], args[2]);
1191 break;
1192 case INDEX_op_st16_i32:
1193 tcg_out_ldst(s, OPC_SH, args[0], args[1], args[2]);
1194 break;
1195 case INDEX_op_st_i32:
1196 tcg_out_ldst(s, OPC_SW, args[0], args[1], args[2]);
1197 break;
1199 case INDEX_op_add_i32:
1200 if (const_args[2]) {
1201 tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], args[2]);
1202 } else {
1203 tcg_out_opc_reg(s, OPC_ADDU, args[0], args[1], args[2]);
1205 break;
1206 case INDEX_op_add2_i32:
1207 if (const_args[4]) {
1208 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], args[4]);
1209 } else {
1210 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, args[2], args[4]);
1212 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, TCG_REG_AT, args[2]);
1213 if (const_args[5]) {
1214 tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], args[5]);
1215 } else {
1216 tcg_out_opc_reg(s, OPC_ADDU, args[1], args[3], args[5]);
1218 tcg_out_opc_reg(s, OPC_ADDU, args[1], args[1], TCG_REG_T0);
1219 tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
1220 break;
1221 case INDEX_op_sub_i32:
1222 if (const_args[2]) {
1223 tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], -args[2]);
1224 } else {
1225 tcg_out_opc_reg(s, OPC_SUBU, args[0], args[1], args[2]);
1227 break;
1228 case INDEX_op_sub2_i32:
1229 if (const_args[4]) {
1230 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], -args[4]);
1231 } else {
1232 tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, args[2], args[4]);
1234 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, args[2], TCG_REG_AT);
1235 if (const_args[5]) {
1236 tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], -args[5]);
1237 } else {
1238 tcg_out_opc_reg(s, OPC_SUBU, args[1], args[3], args[5]);
1240 tcg_out_opc_reg(s, OPC_SUBU, args[1], args[1], TCG_REG_T0);
1241 tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
1242 break;
1243 case INDEX_op_mul_i32:
1244 tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
1245 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1246 break;
1247 case INDEX_op_mulu2_i32:
1248 tcg_out_opc_reg(s, OPC_MULTU, 0, args[2], args[3]);
1249 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1250 tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
1251 break;
1252 case INDEX_op_div_i32:
1253 tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1254 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1255 break;
1256 case INDEX_op_divu_i32:
1257 tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1258 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1259 break;
1260 case INDEX_op_rem_i32:
1261 tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1262 tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1263 break;
1264 case INDEX_op_remu_i32:
1265 tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1266 tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1267 break;
1269 case INDEX_op_and_i32:
1270 if (const_args[2]) {
1271 tcg_out_opc_imm(s, OPC_ANDI, args[0], args[1], args[2]);
1272 } else {
1273 tcg_out_opc_reg(s, OPC_AND, args[0], args[1], args[2]);
1275 break;
1276 case INDEX_op_or_i32:
1277 if (const_args[2]) {
1278 tcg_out_opc_imm(s, OPC_ORI, args[0], args[1], args[2]);
1279 } else {
1280 tcg_out_opc_reg(s, OPC_OR, args[0], args[1], args[2]);
1282 break;
1283 case INDEX_op_nor_i32:
1284 tcg_out_opc_reg(s, OPC_NOR, args[0], args[1], args[2]);
1285 break;
1286 case INDEX_op_not_i32:
1287 tcg_out_opc_reg(s, OPC_NOR, args[0], TCG_REG_ZERO, args[1]);
1288 break;
1289 case INDEX_op_xor_i32:
1290 if (const_args[2]) {
1291 tcg_out_opc_imm(s, OPC_XORI, args[0], args[1], args[2]);
1292 } else {
1293 tcg_out_opc_reg(s, OPC_XOR, args[0], args[1], args[2]);
1295 break;
1297 case INDEX_op_sar_i32:
1298 if (const_args[2]) {
1299 tcg_out_opc_sa(s, OPC_SRA, args[0], args[1], args[2]);
1300 } else {
1301 tcg_out_opc_reg(s, OPC_SRAV, args[0], args[2], args[1]);
1303 break;
1304 case INDEX_op_shl_i32:
1305 if (const_args[2]) {
1306 tcg_out_opc_sa(s, OPC_SLL, args[0], args[1], args[2]);
1307 } else {
1308 tcg_out_opc_reg(s, OPC_SLLV, args[0], args[2], args[1]);
1310 break;
1311 case INDEX_op_shr_i32:
1312 if (const_args[2]) {
1313 tcg_out_opc_sa(s, OPC_SRL, args[0], args[1], args[2]);
1314 } else {
1315 tcg_out_opc_reg(s, OPC_SRLV, args[0], args[2], args[1]);
1317 break;
1319 case INDEX_op_ext8s_i32:
1320 tcg_out_ext8s(s, args[0], args[1]);
1321 break;
1322 case INDEX_op_ext16s_i32:
1323 tcg_out_ext16s(s, args[0], args[1]);
1324 break;
1326 case INDEX_op_brcond_i32:
1327 tcg_out_brcond(s, args[2], args[0], args[1], args[3]);
1328 break;
1329 case INDEX_op_brcond2_i32:
1330 tcg_out_brcond2(s, args[4], args[0], args[1], args[2], args[3], args[5]);
1331 break;
1333 case INDEX_op_setcond_i32:
1334 tcg_out_setcond(s, args[3], args[0], args[1], args[2]);
1335 break;
1336 case INDEX_op_setcond2_i32:
1337 tcg_out_setcond2(s, args[5], args[0], args[1], args[2], args[3], args[4]);
1338 break;
1340 case INDEX_op_qemu_ld8u:
1341 tcg_out_qemu_ld(s, args, 0);
1342 break;
1343 case INDEX_op_qemu_ld8s:
1344 tcg_out_qemu_ld(s, args, 0 | 4);
1345 break;
1346 case INDEX_op_qemu_ld16u:
1347 tcg_out_qemu_ld(s, args, 1);
1348 break;
1349 case INDEX_op_qemu_ld16s:
1350 tcg_out_qemu_ld(s, args, 1 | 4);
1351 break;
1352 case INDEX_op_qemu_ld32:
1353 tcg_out_qemu_ld(s, args, 2);
1354 break;
1355 case INDEX_op_qemu_ld64:
1356 tcg_out_qemu_ld(s, args, 3);
1357 break;
1358 case INDEX_op_qemu_st8:
1359 tcg_out_qemu_st(s, args, 0);
1360 break;
1361 case INDEX_op_qemu_st16:
1362 tcg_out_qemu_st(s, args, 1);
1363 break;
1364 case INDEX_op_qemu_st32:
1365 tcg_out_qemu_st(s, args, 2);
1366 break;
1367 case INDEX_op_qemu_st64:
1368 tcg_out_qemu_st(s, args, 3);
1369 break;
1371 default:
1372 tcg_abort();
1376 static const TCGTargetOpDef mips_op_defs[] = {
1377 { INDEX_op_exit_tb, { } },
1378 { INDEX_op_goto_tb, { } },
1379 { INDEX_op_call, { "C" } },
1380 { INDEX_op_jmp, { "r" } },
1381 { INDEX_op_br, { } },
1383 { INDEX_op_mov_i32, { "r", "r" } },
1384 { INDEX_op_movi_i32, { "r" } },
1385 { INDEX_op_ld8u_i32, { "r", "r" } },
1386 { INDEX_op_ld8s_i32, { "r", "r" } },
1387 { INDEX_op_ld16u_i32, { "r", "r" } },
1388 { INDEX_op_ld16s_i32, { "r", "r" } },
1389 { INDEX_op_ld_i32, { "r", "r" } },
1390 { INDEX_op_st8_i32, { "rZ", "r" } },
1391 { INDEX_op_st16_i32, { "rZ", "r" } },
1392 { INDEX_op_st_i32, { "rZ", "r" } },
1394 { INDEX_op_add_i32, { "r", "rZ", "rJZ" } },
1395 { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
1396 { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
1397 { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
1398 { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
1399 { INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
1400 { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
1401 { INDEX_op_sub_i32, { "r", "rZ", "rJZ" } },
1403 { INDEX_op_and_i32, { "r", "rZ", "rIZ" } },
1404 { INDEX_op_nor_i32, { "r", "rZ", "rZ" } },
1405 { INDEX_op_not_i32, { "r", "rZ" } },
1406 { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
1407 { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
1409 { INDEX_op_shl_i32, { "r", "rZ", "riZ" } },
1410 { INDEX_op_shr_i32, { "r", "rZ", "riZ" } },
1411 { INDEX_op_sar_i32, { "r", "rZ", "riZ" } },
1413 { INDEX_op_ext8s_i32, { "r", "rZ" } },
1414 { INDEX_op_ext16s_i32, { "r", "rZ" } },
1416 { INDEX_op_brcond_i32, { "rZ", "rZ" } },
1417 { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
1418 { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
1420 { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1421 { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1422 { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
1424 #if TARGET_LONG_BITS == 32
1425 { INDEX_op_qemu_ld8u, { "L", "lZ" } },
1426 { INDEX_op_qemu_ld8s, { "L", "lZ" } },
1427 { INDEX_op_qemu_ld16u, { "L", "lZ" } },
1428 { INDEX_op_qemu_ld16s, { "L", "lZ" } },
1429 { INDEX_op_qemu_ld32, { "L", "lZ" } },
1430 { INDEX_op_qemu_ld64, { "L", "L", "lZ" } },
1432 { INDEX_op_qemu_st8, { "SZ", "SZ" } },
1433 { INDEX_op_qemu_st16, { "SZ", "SZ" } },
1434 { INDEX_op_qemu_st32, { "SZ", "SZ" } },
1435 { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ" } },
1436 #else
1437 { INDEX_op_qemu_ld8u, { "L", "lZ", "lZ" } },
1438 { INDEX_op_qemu_ld8s, { "L", "lZ", "lZ" } },
1439 { INDEX_op_qemu_ld16u, { "L", "lZ", "lZ" } },
1440 { INDEX_op_qemu_ld16s, { "L", "lZ", "lZ" } },
1441 { INDEX_op_qemu_ld32, { "L", "lZ", "lZ" } },
1442 { INDEX_op_qemu_ld64, { "L", "L", "lZ", "lZ" } },
1444 { INDEX_op_qemu_st8, { "SZ", "SZ", "SZ" } },
1445 { INDEX_op_qemu_st16, { "SZ", "SZ", "SZ" } },
1446 { INDEX_op_qemu_st32, { "SZ", "SZ", "SZ" } },
1447 { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ", "SZ" } },
1448 #endif
1449 { -1 },
1452 static int tcg_target_callee_save_regs[] = {
1453 #if 0 /* used for the global env (TCG_AREG0), so no need to save */
1454 TCG_REG_S0,
1455 #endif
1456 TCG_REG_S1,
1457 TCG_REG_S2,
1458 TCG_REG_S3,
1459 TCG_REG_S4,
1460 TCG_REG_S5,
1461 TCG_REG_S6,
1462 TCG_REG_S7,
1463 TCG_REG_GP,
1464 TCG_REG_FP,
1465 TCG_REG_RA, /* should be last for ABI compliance */
1468 /* Generate global QEMU prologue and epilogue code */
1469 static void tcg_target_qemu_prologue(TCGContext *s)
1471 int i, frame_size;
1473 /* reserve some stack space */
1474 frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1475 + TCG_STATIC_CALL_ARGS_SIZE;
1476 frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1477 ~(TCG_TARGET_STACK_ALIGN - 1);
1479 /* TB prologue */
1480 tcg_out_addi(s, TCG_REG_SP, -frame_size);
1481 for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1482 tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1483 TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1486 /* Call generated code */
1487 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_A0, 0);
1488 tcg_out_nop(s);
1489 tb_ret_addr = s->code_ptr;
1491 /* TB epilogue */
1492 for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1493 tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1494 TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1497 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
1498 tcg_out_addi(s, TCG_REG_SP, frame_size);
1501 static void tcg_target_init(TCGContext *s)
1503 tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
1504 tcg_regset_set(tcg_target_call_clobber_regs,
1505 (1 << TCG_REG_V0) |
1506 (1 << TCG_REG_V1) |
1507 (1 << TCG_REG_A0) |
1508 (1 << TCG_REG_A1) |
1509 (1 << TCG_REG_A2) |
1510 (1 << TCG_REG_A3) |
1511 (1 << TCG_REG_T1) |
1512 (1 << TCG_REG_T2) |
1513 (1 << TCG_REG_T3) |
1514 (1 << TCG_REG_T4) |
1515 (1 << TCG_REG_T5) |
1516 (1 << TCG_REG_T6) |
1517 (1 << TCG_REG_T7) |
1518 (1 << TCG_REG_T8) |
1519 (1 << TCG_REG_T9));
1521 tcg_regset_clear(s->reserved_regs);
1522 tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
1523 tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0); /* kernel use only */
1524 tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1); /* kernel use only */
1525 tcg_regset_set_reg(s->reserved_regs, TCG_REG_AT); /* internal use */
1526 tcg_regset_set_reg(s->reserved_regs, TCG_REG_T0); /* internal use */
1527 tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return address */
1528 tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */
1530 tcg_add_target_add_op_defs(mips_op_defs);