tcg/mips: implement the not_i32 op the same way as gcc
[qemu/aliguori-queue.git] / tcg / mips / tcg-target.c
blob7744281ff85b7c9d2ef75629349f3d70a1a4af83
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 #if defined(CONFIG_SOFTMMU)
226 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
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_SPECIAL = 0x00 << 26,
274 OPC_BEQ = 0x04 << 26,
275 OPC_BNE = 0x05 << 26,
276 OPC_ADDIU = 0x09 << 26,
277 OPC_SLTI = 0x0A << 26,
278 OPC_SLTIU = 0x0B << 26,
279 OPC_ANDI = 0x0C << 26,
280 OPC_ORI = 0x0D << 26,
281 OPC_XORI = 0x0E << 26,
282 OPC_LUI = 0x0F << 26,
283 OPC_LB = 0x20 << 26,
284 OPC_LH = 0x21 << 26,
285 OPC_LW = 0x23 << 26,
286 OPC_LBU = 0x24 << 26,
287 OPC_LHU = 0x25 << 26,
288 OPC_LWU = 0x27 << 26,
289 OPC_SB = 0x28 << 26,
290 OPC_SH = 0x29 << 26,
291 OPC_SW = 0x2B << 26,
292 OPC_SLL = OPC_SPECIAL | 0x00,
293 OPC_SRL = OPC_SPECIAL | 0x02,
294 OPC_SRA = OPC_SPECIAL | 0x03,
295 OPC_SLLV = OPC_SPECIAL | 0x04,
296 OPC_SRLV = OPC_SPECIAL | 0x06,
297 OPC_SRAV = OPC_SPECIAL | 0x07,
298 OPC_JR = OPC_SPECIAL | 0x08,
299 OPC_JALR = OPC_SPECIAL | 0x09,
300 OPC_MFHI = OPC_SPECIAL | 0x10,
301 OPC_MFLO = OPC_SPECIAL | 0x12,
302 OPC_MULT = OPC_SPECIAL | 0x18,
303 OPC_MULTU = OPC_SPECIAL | 0x19,
304 OPC_DIV = OPC_SPECIAL | 0x1A,
305 OPC_DIVU = OPC_SPECIAL | 0x1B,
306 OPC_ADDU = OPC_SPECIAL | 0x21,
307 OPC_SUBU = OPC_SPECIAL | 0x23,
308 OPC_AND = OPC_SPECIAL | 0x24,
309 OPC_OR = OPC_SPECIAL | 0x25,
310 OPC_XOR = OPC_SPECIAL | 0x26,
311 OPC_NOR = OPC_SPECIAL | 0x27,
312 OPC_SLT = OPC_SPECIAL | 0x2A,
313 OPC_SLTU = OPC_SPECIAL | 0x2B,
317 * Type reg
319 static inline void tcg_out_opc_reg(TCGContext *s, int opc, int rd, int rs, int rt)
321 int32_t inst;
323 inst = opc;
324 inst |= (rs & 0x1F) << 21;
325 inst |= (rt & 0x1F) << 16;
326 inst |= (rd & 0x1F) << 11;
327 tcg_out32(s, inst);
331 * Type immediate
333 static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int imm)
335 int32_t inst;
337 inst = opc;
338 inst |= (rs & 0x1F) << 21;
339 inst |= (rt & 0x1F) << 16;
340 inst |= (imm & 0xffff);
341 tcg_out32(s, inst);
345 * Type sa
347 static inline void tcg_out_opc_sa(TCGContext *s, int opc, int rd, int rt, int sa)
349 int32_t inst;
351 inst = opc;
352 inst |= (rt & 0x1F) << 16;
353 inst |= (rd & 0x1F) << 11;
354 inst |= (sa & 0x1F) << 6;
355 tcg_out32(s, inst);
359 static inline void tcg_out_nop(TCGContext *s)
361 tcg_out32(s, 0);
364 static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
366 tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
369 static inline void tcg_out_movi(TCGContext *s, TCGType type,
370 int reg, int32_t arg)
372 if (arg == (int16_t)arg) {
373 tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
374 } else if (arg == (uint16_t)arg) {
375 tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
376 } else {
377 tcg_out_opc_imm(s, OPC_LUI, reg, 0, arg >> 16);
378 tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0xffff);
382 static inline void tcg_out_bswap16(TCGContext *s, int ret, int arg)
384 /* ret and arg can't be register at */
385 if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
386 tcg_abort();
389 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
390 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0x00ff);
392 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
393 tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
394 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
397 static inline void tcg_out_bswap16s(TCGContext *s, int ret, int arg)
399 /* ret and arg can't be register at */
400 if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
401 tcg_abort();
404 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
405 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff);
407 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
408 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
409 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
412 static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg)
414 /* ret and arg must be different and can't be register at */
415 if (ret == arg || ret == TCG_REG_AT || arg == TCG_REG_AT) {
416 tcg_abort();
419 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
421 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 24);
422 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
424 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, arg, 0xff00);
425 tcg_out_opc_sa(s, OPC_SLL, TCG_REG_AT, TCG_REG_AT, 8);
426 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
428 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
429 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff00);
430 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
433 static inline void tcg_out_ldst(TCGContext *s, int opc, int arg,
434 int arg1, tcg_target_long arg2)
436 if (arg2 == (int16_t) arg2) {
437 tcg_out_opc_imm(s, opc, arg, arg1, arg2);
438 } else {
439 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, arg2);
440 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, TCG_REG_AT, arg1);
441 tcg_out_opc_imm(s, opc, arg, TCG_REG_AT, 0);
445 static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg,
446 int arg1, tcg_target_long arg2)
448 tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
451 static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
452 int arg1, tcg_target_long arg2)
454 tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
457 static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
459 if (val == (int16_t)val) {
460 tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
461 } else {
462 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, val);
463 tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_REG_AT);
467 static void tcg_out_brcond(TCGContext *s, TCGCond cond, int arg1,
468 int arg2, int label_index)
470 TCGLabel *l = &s->labels[label_index];
472 switch (cond) {
473 case TCG_COND_EQ:
474 tcg_out_opc_imm(s, OPC_BEQ, arg1, arg2, 0);
475 break;
476 case TCG_COND_NE:
477 tcg_out_opc_imm(s, OPC_BNE, arg1, arg2, 0);
478 break;
479 case TCG_COND_LT:
480 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
481 tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
482 break;
483 case TCG_COND_LTU:
484 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
485 tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
486 break;
487 case TCG_COND_GE:
488 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
489 tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
490 break;
491 case TCG_COND_GEU:
492 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
493 tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
494 break;
495 case TCG_COND_LE:
496 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
497 tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
498 break;
499 case TCG_COND_LEU:
500 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
501 tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
502 break;
503 case TCG_COND_GT:
504 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
505 tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
506 break;
507 case TCG_COND_GTU:
508 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
509 tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
510 break;
511 default:
512 tcg_abort();
513 break;
515 if (l->has_value) {
516 reloc_pc16(s->code_ptr - 4, l->u.value);
517 } else {
518 tcg_out_reloc(s, s->code_ptr - 4, R_MIPS_PC16, label_index, 0);
520 tcg_out_nop(s);
523 /* XXX: we implement it at the target level to avoid having to
524 handle cross basic blocks temporaries */
525 static void tcg_out_brcond2(TCGContext *s, TCGCond cond, int arg1,
526 int arg2, int arg3, int arg4, int label_index)
528 void *label_ptr;
530 switch(cond) {
531 case TCG_COND_NE:
532 tcg_out_brcond(s, TCG_COND_NE, arg2, arg4, label_index);
533 tcg_out_brcond(s, TCG_COND_NE, arg1, arg3, label_index);
534 return;
535 case TCG_COND_EQ:
536 break;
537 case TCG_COND_LT:
538 case TCG_COND_LE:
539 tcg_out_brcond(s, TCG_COND_LT, arg2, arg4, label_index);
540 break;
541 case TCG_COND_GT:
542 case TCG_COND_GE:
543 tcg_out_brcond(s, TCG_COND_GT, arg2, arg4, label_index);
544 break;
545 case TCG_COND_LTU:
546 case TCG_COND_LEU:
547 tcg_out_brcond(s, TCG_COND_LTU, arg2, arg4, label_index);
548 break;
549 case TCG_COND_GTU:
550 case TCG_COND_GEU:
551 tcg_out_brcond(s, TCG_COND_GTU, arg2, arg4, label_index);
552 break;
553 default:
554 tcg_abort();
557 label_ptr = s->code_ptr;
558 tcg_out_opc_imm(s, OPC_BNE, arg2, arg4, 0);
559 tcg_out_nop(s);
561 switch(cond) {
562 case TCG_COND_EQ:
563 tcg_out_brcond(s, TCG_COND_EQ, arg1, arg3, label_index);
564 break;
565 case TCG_COND_LT:
566 case TCG_COND_LTU:
567 tcg_out_brcond(s, TCG_COND_LTU, arg1, arg3, label_index);
568 break;
569 case TCG_COND_LE:
570 case TCG_COND_LEU:
571 tcg_out_brcond(s, TCG_COND_LEU, arg1, arg3, label_index);
572 break;
573 case TCG_COND_GT:
574 case TCG_COND_GTU:
575 tcg_out_brcond(s, TCG_COND_GTU, arg1, arg3, label_index);
576 break;
577 case TCG_COND_GE:
578 case TCG_COND_GEU:
579 tcg_out_brcond(s, TCG_COND_GEU, arg1, arg3, label_index);
580 break;
581 default:
582 tcg_abort();
585 reloc_pc16(label_ptr, (tcg_target_long) s->code_ptr);
588 static void tcg_out_setcond(TCGContext *s, TCGCond cond, int ret,
589 int arg1, int arg2)
591 switch (cond) {
592 case TCG_COND_EQ:
593 if (arg1 == 0) {
594 tcg_out_opc_imm(s, OPC_SLTIU, ret, arg2, 1);
595 } else if (arg2 == 0) {
596 tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, 1);
597 } else {
598 tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
599 tcg_out_opc_imm(s, OPC_SLTIU, ret, ret, 1);
601 break;
602 case TCG_COND_NE:
603 if (arg1 == 0) {
604 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg2);
605 } else if (arg2 == 0) {
606 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg1);
607 } else {
608 tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
609 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, ret);
611 break;
612 case TCG_COND_LT:
613 tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
614 break;
615 case TCG_COND_LTU:
616 tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
617 break;
618 case TCG_COND_GE:
619 tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
620 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
621 break;
622 case TCG_COND_GEU:
623 tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
624 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
625 break;
626 case TCG_COND_LE:
627 tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
628 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
629 break;
630 case TCG_COND_LEU:
631 tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
632 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
633 break;
634 case TCG_COND_GT:
635 tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
636 break;
637 case TCG_COND_GTU:
638 tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
639 break;
640 default:
641 tcg_abort();
642 break;
646 /* XXX: we implement it at the target level to avoid having to
647 handle cross basic blocks temporaries */
648 static void tcg_out_setcond2(TCGContext *s, TCGCond cond, int ret,
649 int arg1, int arg2, int arg3, int arg4)
651 switch (cond) {
652 case TCG_COND_EQ:
653 tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_AT, arg2, arg4);
654 tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg1, arg3);
655 tcg_out_opc_reg(s, OPC_AND, ret, TCG_REG_AT, TCG_REG_T0);
656 return;
657 case TCG_COND_NE:
658 tcg_out_setcond(s, TCG_COND_NE, TCG_REG_AT, arg2, arg4);
659 tcg_out_setcond(s, TCG_COND_NE, TCG_REG_T0, arg1, arg3);
660 tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_AT, TCG_REG_T0);
661 return;
662 case TCG_COND_LT:
663 case TCG_COND_LE:
664 tcg_out_setcond(s, TCG_COND_LT, TCG_REG_AT, arg2, arg4);
665 break;
666 case TCG_COND_GT:
667 case TCG_COND_GE:
668 tcg_out_setcond(s, TCG_COND_GT, TCG_REG_AT, arg2, arg4);
669 break;
670 case TCG_COND_LTU:
671 case TCG_COND_LEU:
672 tcg_out_setcond(s, TCG_COND_LTU, TCG_REG_AT, arg2, arg4);
673 break;
674 case TCG_COND_GTU:
675 case TCG_COND_GEU:
676 tcg_out_setcond(s, TCG_COND_GTU, TCG_REG_AT, arg2, arg4);
677 break;
678 default:
679 tcg_abort();
680 break;
683 tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg2, arg4);
685 switch(cond) {
686 case TCG_COND_LT:
687 case TCG_COND_LTU:
688 tcg_out_setcond(s, TCG_COND_LTU, ret, arg1, arg3);
689 break;
690 case TCG_COND_LE:
691 case TCG_COND_LEU:
692 tcg_out_setcond(s, TCG_COND_LEU, ret, arg1, arg3);
693 break;
694 case TCG_COND_GT:
695 case TCG_COND_GTU:
696 tcg_out_setcond(s, TCG_COND_GTU, ret, arg1, arg3);
697 break;
698 case TCG_COND_GE:
699 case TCG_COND_GEU:
700 tcg_out_setcond(s, TCG_COND_GEU, ret, arg1, arg3);
701 break;
702 default:
703 tcg_abort();
706 tcg_out_opc_reg(s, OPC_AND, ret, ret, TCG_REG_T0);
707 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
710 #if defined(CONFIG_SOFTMMU)
712 #include "../../softmmu_defs.h"
714 static void *qemu_ld_helpers[4] = {
715 __ldb_mmu,
716 __ldw_mmu,
717 __ldl_mmu,
718 __ldq_mmu,
721 static void *qemu_st_helpers[4] = {
722 __stb_mmu,
723 __stw_mmu,
724 __stl_mmu,
725 __stq_mmu,
727 #endif
729 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
730 int opc)
732 int addr_regl, addr_reg1, addr_meml;
733 int data_regl, data_regh, data_reg1, data_reg2;
734 int mem_index, s_bits;
735 #if defined(CONFIG_SOFTMMU)
736 void *label1_ptr, *label2_ptr;
737 int sp_args;
738 #endif
739 #if TARGET_LONG_BITS == 64
740 # if defined(CONFIG_SOFTMMU)
741 uint8_t *label3_ptr;
742 # endif
743 int addr_regh, addr_reg2, addr_memh;
744 #endif
745 data_regl = *args++;
746 if (opc == 3)
747 data_regh = *args++;
748 else
749 data_regh = 0;
750 addr_regl = *args++;
751 #if TARGET_LONG_BITS == 64
752 addr_regh = *args++;
753 #endif
754 mem_index = *args;
755 s_bits = opc & 3;
757 if (opc == 3) {
758 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
759 data_reg1 = data_regh;
760 data_reg2 = data_regl;
761 #else
762 data_reg1 = data_regl;
763 data_reg2 = data_regh;
764 #endif
765 } else {
766 data_reg1 = data_regl;
767 data_reg2 = 0;
769 #if TARGET_LONG_BITS == 64
770 # if defined(TCG_TARGET_WORDS_BIGENDIAN)
771 addr_reg1 = addr_regh;
772 addr_reg2 = addr_regl;
773 addr_memh = 0;
774 addr_meml = 4;
775 # else
776 addr_reg1 = addr_regl;
777 addr_reg2 = addr_regh;
778 addr_memh = 4;
779 addr_meml = 0;
780 # endif
781 #else
782 addr_reg1 = addr_regl;
783 addr_meml = 0;
784 #endif
786 #if defined(CONFIG_SOFTMMU)
787 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
788 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
789 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
790 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
791 offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_meml);
792 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
793 tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
795 # if TARGET_LONG_BITS == 64
796 label3_ptr = s->code_ptr;
797 tcg_out_opc_imm(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT, 0);
798 tcg_out_nop(s);
800 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
801 offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_memh);
803 label1_ptr = s->code_ptr;
804 tcg_out_opc_imm(s, OPC_BEQ, addr_regh, TCG_REG_AT, 0);
805 tcg_out_nop(s);
807 reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
808 # else
809 label1_ptr = s->code_ptr;
810 tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT, 0);
811 tcg_out_nop(s);
812 # endif
814 /* slow path */
815 sp_args = TCG_REG_A0;
816 tcg_out_mov(s, sp_args++, addr_reg1);
817 # if TARGET_LONG_BITS == 64
818 tcg_out_mov(s, sp_args++, addr_reg2);
819 # endif
820 tcg_out_movi(s, TCG_TYPE_I32, sp_args++, mem_index);
821 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]);
822 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
823 tcg_out_nop(s);
825 switch(opc) {
826 case 0:
827 tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xff);
828 break;
829 case 0 | 4:
830 tcg_out_opc_sa(s, OPC_SLL, TCG_REG_V0, TCG_REG_V0, 24);
831 tcg_out_opc_sa(s, OPC_SRA, data_reg1, TCG_REG_V0, 24);
832 break;
833 case 1:
834 tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xffff);
835 break;
836 case 1 | 4:
837 tcg_out_opc_sa(s, OPC_SLL, TCG_REG_V0, TCG_REG_V0, 16);
838 tcg_out_opc_sa(s, OPC_SRA, data_reg1, TCG_REG_V0, 16);
839 break;
840 case 2:
841 tcg_out_mov(s, data_reg1, TCG_REG_V0);
842 break;
843 case 3:
844 tcg_out_mov(s, data_reg2, TCG_REG_V1);
845 tcg_out_mov(s, data_reg1, TCG_REG_V0);
846 break;
847 default:
848 tcg_abort();
851 label2_ptr = s->code_ptr;
852 tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO, 0);
853 tcg_out_nop(s);
855 /* label1: fast path */
856 reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
858 tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
859 offsetof(CPUState, tlb_table[mem_index][0].addend) + addr_meml);
860 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_A0, addr_regl);
862 addr_reg1 = TCG_REG_V0;
863 #endif
865 switch(opc) {
866 case 0:
867 tcg_out_opc_imm(s, OPC_LBU, data_reg1, addr_reg1, 0);
868 break;
869 case 0 | 4:
870 tcg_out_opc_imm(s, OPC_LB, data_reg1, addr_reg1, 0);
871 break;
872 case 1:
873 if (TCG_NEED_BSWAP) {
874 tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, addr_reg1, 0);
875 tcg_out_bswap16(s, data_reg1, TCG_REG_T0);
876 } else {
877 tcg_out_opc_imm(s, OPC_LHU, data_reg1, addr_reg1, 0);
879 break;
880 case 1 | 4:
881 if (TCG_NEED_BSWAP) {
882 tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, addr_reg1, 0);
883 tcg_out_bswap16s(s, data_reg1, TCG_REG_T0);
884 } else {
885 tcg_out_opc_imm(s, OPC_LH, data_reg1, addr_reg1, 0);
887 break;
888 case 2:
889 if (TCG_NEED_BSWAP) {
890 tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, addr_reg1, 0);
891 tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
892 } else {
893 tcg_out_opc_imm(s, OPC_LW, data_reg1, addr_reg1, 0);
895 break;
896 case 3:
897 #if !defined(CONFIG_SOFTMMU)
898 tcg_out_mov(s, TCG_REG_V0, addr_reg1);
899 addr_reg1 = TCG_REG_V0;
900 #endif
901 if (TCG_NEED_BSWAP) {
902 tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, addr_reg1, 4);
903 tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
904 tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, addr_reg1, 0);
905 tcg_out_bswap32(s, data_reg2, TCG_REG_T0);
906 } else {
907 tcg_out_opc_imm(s, OPC_LW, data_reg1, addr_reg1, 0);
908 tcg_out_opc_imm(s, OPC_LW, data_reg2, addr_reg1, 4);
910 break;
911 default:
912 tcg_abort();
915 #if defined(CONFIG_SOFTMMU)
916 reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
917 #endif
920 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
921 int opc)
923 int addr_regl, addr_reg1, addr_meml;
924 int data_regl, data_regh, data_reg1, data_reg2;
925 int mem_index, s_bits;
926 #if defined(CONFIG_SOFTMMU)
927 uint8_t *label1_ptr, *label2_ptr;
928 int sp_args;
929 #endif
930 #if TARGET_LONG_BITS == 64
931 # if defined(CONFIG_SOFTMMU)
932 uint8_t *label3_ptr;
933 # endif
934 int addr_regh, addr_reg2, addr_memh;
935 #endif
937 data_regl = *args++;
938 if (opc == 3) {
939 data_regh = *args++;
940 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
941 data_reg1 = data_regh;
942 data_reg2 = data_regl;
943 #else
944 data_reg1 = data_regl;
945 data_reg2 = data_regh;
946 #endif
947 } else {
948 data_reg1 = data_regl;
949 data_reg2 = 0;
950 data_regh = 0;
952 addr_regl = *args++;
953 #if TARGET_LONG_BITS == 64
954 addr_regh = *args++;
955 # if defined(TCG_TARGET_WORDS_BIGENDIAN)
956 addr_reg1 = addr_regh;
957 addr_reg2 = addr_regl;
958 addr_memh = 0;
959 addr_meml = 4;
960 # else
961 addr_reg1 = addr_regl;
962 addr_reg2 = addr_regh;
963 addr_memh = 4;
964 addr_meml = 0;
965 # endif
966 #else
967 addr_reg1 = addr_regl;
968 addr_meml = 0;
969 #endif
970 mem_index = *args;
971 s_bits = opc;
973 #if defined(CONFIG_SOFTMMU)
974 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
975 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
976 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
977 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
978 offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_meml);
979 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
980 tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
982 # if TARGET_LONG_BITS == 64
983 label3_ptr = s->code_ptr;
984 tcg_out_opc_imm(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT, 0);
985 tcg_out_nop(s);
987 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
988 offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_memh);
990 label1_ptr = s->code_ptr;
991 tcg_out_opc_imm(s, OPC_BEQ, addr_regh, TCG_REG_AT, 0);
992 tcg_out_nop(s);
994 reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
995 # else
996 label1_ptr = s->code_ptr;
997 tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT, 0);
998 tcg_out_nop(s);
999 # endif
1001 /* slow path */
1002 sp_args = TCG_REG_A0;
1003 tcg_out_mov(s, sp_args++, addr_reg1);
1004 # if TARGET_LONG_BITS == 64
1005 tcg_out_mov(s, sp_args++, addr_reg2);
1006 # endif
1007 switch(opc) {
1008 case 0:
1009 tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xff);
1010 break;
1011 case 1:
1012 tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xffff);
1013 break;
1014 case 2:
1015 tcg_out_mov(s, sp_args++, data_reg1);
1016 break;
1017 case 3:
1018 sp_args = (sp_args + 1) & ~1;
1019 tcg_out_mov(s, sp_args++, data_reg1);
1020 tcg_out_mov(s, sp_args++, data_reg2);
1021 break;
1022 default:
1023 tcg_abort();
1025 if (sp_args > TCG_REG_A3) {
1026 /* Push mem_index on the stack */
1027 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, mem_index);
1028 tcg_out_st(s, TCG_TYPE_I32, TCG_REG_AT, TCG_REG_SP, 16);
1029 } else {
1030 tcg_out_movi(s, TCG_TYPE_I32, sp_args, mem_index);
1033 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_st_helpers[s_bits]);
1034 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
1035 tcg_out_nop(s);
1037 label2_ptr = s->code_ptr;
1038 tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO, 0);
1039 tcg_out_nop(s);
1041 /* label1: fast path */
1042 reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
1044 tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
1045 offsetof(CPUState, tlb_table[mem_index][0].addend) + addr_meml);
1046 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
1048 addr_reg1 = TCG_REG_A0;
1049 #endif
1051 switch(opc) {
1052 case 0:
1053 tcg_out_opc_imm(s, OPC_SB, data_reg1, addr_reg1, 0);
1054 break;
1055 case 1:
1056 if (TCG_NEED_BSWAP) {
1057 tcg_out_bswap16(s, TCG_REG_T0, data_reg1);
1058 tcg_out_opc_imm(s, OPC_SH, TCG_REG_T0, addr_reg1, 0);
1059 } else {
1060 tcg_out_opc_imm(s, OPC_SH, data_reg1, addr_reg1, 0);
1062 break;
1063 case 2:
1064 if (TCG_NEED_BSWAP) {
1065 tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1066 tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, addr_reg1, 0);
1067 } else {
1068 tcg_out_opc_imm(s, OPC_SW, data_reg1, addr_reg1, 0);
1070 break;
1071 case 3:
1072 if (TCG_NEED_BSWAP) {
1073 tcg_out_bswap32(s, TCG_REG_T0, data_reg2);
1074 tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, addr_reg1, 0);
1075 tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1076 tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, addr_reg1, 4);
1077 } else {
1078 tcg_out_opc_imm(s, OPC_SW, data_reg1, addr_reg1, 0);
1079 tcg_out_opc_imm(s, OPC_SW, data_reg2, addr_reg1, 4);
1081 break;
1082 default:
1083 tcg_abort();
1086 #if defined(CONFIG_SOFTMMU)
1087 reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
1088 #endif
1091 static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1092 const TCGArg *args, const int *const_args)
1094 switch(opc) {
1095 case INDEX_op_exit_tb:
1096 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_V0, args[0]);
1097 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, (tcg_target_long)tb_ret_addr);
1098 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1099 tcg_out_nop(s);
1100 break;
1101 case INDEX_op_goto_tb:
1102 if (s->tb_jmp_offset) {
1103 /* direct jump method */
1104 tcg_abort();
1105 } else {
1106 /* indirect jump method */
1107 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, (tcg_target_long)(s->tb_next + args[0]));
1108 tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_AT, TCG_REG_AT, 0);
1109 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1111 tcg_out_nop(s);
1112 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1113 break;
1114 case INDEX_op_call:
1115 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, args[0], 0);
1116 tcg_out_nop(s);
1117 break;
1118 case INDEX_op_jmp:
1119 tcg_out_opc_reg(s, OPC_JR, 0, args[0], 0);
1120 tcg_out_nop(s);
1121 break;
1122 case INDEX_op_br:
1123 tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, args[0]);
1124 break;
1126 case INDEX_op_mov_i32:
1127 tcg_out_mov(s, args[0], args[1]);
1128 break;
1129 case INDEX_op_movi_i32:
1130 tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1131 break;
1133 case INDEX_op_ld8u_i32:
1134 tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]);
1135 break;
1136 case INDEX_op_ld8s_i32:
1137 tcg_out_ldst(s, OPC_LB, args[0], args[1], args[2]);
1138 break;
1139 case INDEX_op_ld16u_i32:
1140 tcg_out_ldst(s, OPC_LHU, args[0], args[1], args[2]);
1141 break;
1142 case INDEX_op_ld16s_i32:
1143 tcg_out_ldst(s, OPC_LH, args[0], args[1], args[2]);
1144 break;
1145 case INDEX_op_ld_i32:
1146 tcg_out_ldst(s, OPC_LW, args[0], args[1], args[2]);
1147 break;
1148 case INDEX_op_st8_i32:
1149 tcg_out_ldst(s, OPC_SB, args[0], args[1], args[2]);
1150 break;
1151 case INDEX_op_st16_i32:
1152 tcg_out_ldst(s, OPC_SH, args[0], args[1], args[2]);
1153 break;
1154 case INDEX_op_st_i32:
1155 tcg_out_ldst(s, OPC_SW, args[0], args[1], args[2]);
1156 break;
1158 case INDEX_op_add_i32:
1159 if (const_args[2]) {
1160 tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], args[2]);
1161 } else {
1162 tcg_out_opc_reg(s, OPC_ADDU, args[0], args[1], args[2]);
1164 break;
1165 case INDEX_op_add2_i32:
1166 if (const_args[4]) {
1167 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], args[4]);
1168 } else {
1169 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, args[2], args[4]);
1171 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, TCG_REG_AT, args[2]);
1172 if (const_args[5]) {
1173 tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], args[5]);
1174 } else {
1175 tcg_out_opc_reg(s, OPC_ADDU, args[1], args[3], args[5]);
1177 tcg_out_opc_reg(s, OPC_ADDU, args[1], args[1], TCG_REG_T0);
1178 tcg_out_mov(s, args[0], TCG_REG_AT);
1179 break;
1180 case INDEX_op_sub_i32:
1181 if (const_args[2]) {
1182 tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], -args[2]);
1183 } else {
1184 tcg_out_opc_reg(s, OPC_SUBU, args[0], args[1], args[2]);
1186 break;
1187 case INDEX_op_sub2_i32:
1188 if (const_args[4]) {
1189 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], -args[4]);
1190 } else {
1191 tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, args[2], args[4]);
1193 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, args[2], TCG_REG_AT);
1194 if (const_args[5]) {
1195 tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], -args[5]);
1196 } else {
1197 tcg_out_opc_reg(s, OPC_SUBU, args[1], args[3], args[5]);
1199 tcg_out_opc_reg(s, OPC_SUBU, args[1], args[1], TCG_REG_T0);
1200 tcg_out_mov(s, args[0], TCG_REG_AT);
1201 break;
1202 case INDEX_op_mul_i32:
1203 tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
1204 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1205 break;
1206 case INDEX_op_mulu2_i32:
1207 tcg_out_opc_reg(s, OPC_MULTU, 0, args[2], args[3]);
1208 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1209 tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
1210 break;
1211 case INDEX_op_div_i32:
1212 tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1213 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1214 break;
1215 case INDEX_op_divu_i32:
1216 tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1217 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1218 break;
1219 case INDEX_op_rem_i32:
1220 tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1221 tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1222 break;
1223 case INDEX_op_remu_i32:
1224 tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1225 tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1226 break;
1228 case INDEX_op_and_i32:
1229 if (const_args[2]) {
1230 tcg_out_opc_imm(s, OPC_ANDI, args[0], args[1], args[2]);
1231 } else {
1232 tcg_out_opc_reg(s, OPC_AND, args[0], args[1], args[2]);
1234 break;
1235 case INDEX_op_or_i32:
1236 if (const_args[2]) {
1237 tcg_out_opc_imm(s, OPC_ORI, args[0], args[1], args[2]);
1238 } else {
1239 tcg_out_opc_reg(s, OPC_OR, args[0], args[1], args[2]);
1241 break;
1242 case INDEX_op_nor_i32:
1243 tcg_out_opc_reg(s, OPC_NOR, args[0], args[1], args[2]);
1244 break;
1245 case INDEX_op_not_i32:
1246 tcg_out_opc_reg(s, OPC_NOR, args[0], TCG_REG_ZERO, args[1]);
1247 break;
1248 case INDEX_op_xor_i32:
1249 if (const_args[2]) {
1250 tcg_out_opc_imm(s, OPC_XORI, args[0], args[1], args[2]);
1251 } else {
1252 tcg_out_opc_reg(s, OPC_XOR, args[0], args[1], args[2]);
1254 break;
1256 case INDEX_op_sar_i32:
1257 if (const_args[2]) {
1258 tcg_out_opc_sa(s, OPC_SRA, args[0], args[1], args[2]);
1259 } else {
1260 tcg_out_opc_reg(s, OPC_SRAV, args[0], args[2], args[1]);
1262 break;
1263 case INDEX_op_shl_i32:
1264 if (const_args[2]) {
1265 tcg_out_opc_sa(s, OPC_SLL, args[0], args[1], args[2]);
1266 } else {
1267 tcg_out_opc_reg(s, OPC_SLLV, args[0], args[2], args[1]);
1269 break;
1270 case INDEX_op_shr_i32:
1271 if (const_args[2]) {
1272 tcg_out_opc_sa(s, OPC_SRL, args[0], args[1], args[2]);
1273 } else {
1274 tcg_out_opc_reg(s, OPC_SRLV, args[0], args[2], args[1]);
1276 break;
1278 case INDEX_op_brcond_i32:
1279 tcg_out_brcond(s, args[2], args[0], args[1], args[3]);
1280 break;
1281 case INDEX_op_brcond2_i32:
1282 tcg_out_brcond2(s, args[4], args[0], args[1], args[2], args[3], args[5]);
1283 break;
1285 case INDEX_op_setcond_i32:
1286 tcg_out_setcond(s, args[3], args[0], args[1], args[2]);
1287 break;
1288 case INDEX_op_setcond2_i32:
1289 tcg_out_setcond2(s, args[5], args[0], args[1], args[2], args[3], args[4]);
1290 break;
1292 case INDEX_op_qemu_ld8u:
1293 tcg_out_qemu_ld(s, args, 0);
1294 break;
1295 case INDEX_op_qemu_ld8s:
1296 tcg_out_qemu_ld(s, args, 0 | 4);
1297 break;
1298 case INDEX_op_qemu_ld16u:
1299 tcg_out_qemu_ld(s, args, 1);
1300 break;
1301 case INDEX_op_qemu_ld16s:
1302 tcg_out_qemu_ld(s, args, 1 | 4);
1303 break;
1304 case INDEX_op_qemu_ld32:
1305 tcg_out_qemu_ld(s, args, 2);
1306 break;
1307 case INDEX_op_qemu_ld64:
1308 tcg_out_qemu_ld(s, args, 3);
1309 break;
1310 case INDEX_op_qemu_st8:
1311 tcg_out_qemu_st(s, args, 0);
1312 break;
1313 case INDEX_op_qemu_st16:
1314 tcg_out_qemu_st(s, args, 1);
1315 break;
1316 case INDEX_op_qemu_st32:
1317 tcg_out_qemu_st(s, args, 2);
1318 break;
1319 case INDEX_op_qemu_st64:
1320 tcg_out_qemu_st(s, args, 3);
1321 break;
1323 default:
1324 tcg_abort();
1328 static const TCGTargetOpDef mips_op_defs[] = {
1329 { INDEX_op_exit_tb, { } },
1330 { INDEX_op_goto_tb, { } },
1331 { INDEX_op_call, { "C" } },
1332 { INDEX_op_jmp, { "r" } },
1333 { INDEX_op_br, { } },
1335 { INDEX_op_mov_i32, { "r", "r" } },
1336 { INDEX_op_movi_i32, { "r" } },
1337 { INDEX_op_ld8u_i32, { "r", "r" } },
1338 { INDEX_op_ld8s_i32, { "r", "r" } },
1339 { INDEX_op_ld16u_i32, { "r", "r" } },
1340 { INDEX_op_ld16s_i32, { "r", "r" } },
1341 { INDEX_op_ld_i32, { "r", "r" } },
1342 { INDEX_op_st8_i32, { "rZ", "r" } },
1343 { INDEX_op_st16_i32, { "rZ", "r" } },
1344 { INDEX_op_st_i32, { "rZ", "r" } },
1346 { INDEX_op_add_i32, { "r", "rZ", "rJZ" } },
1347 { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
1348 { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
1349 { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
1350 { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
1351 { INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
1352 { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
1353 { INDEX_op_sub_i32, { "r", "rZ", "rJZ" } },
1355 { INDEX_op_and_i32, { "r", "rZ", "rIZ" } },
1356 { INDEX_op_nor_i32, { "r", "rZ", "rZ" } },
1357 { INDEX_op_not_i32, { "r", "rZ" } },
1358 { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
1359 { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
1361 { INDEX_op_shl_i32, { "r", "rZ", "riZ" } },
1362 { INDEX_op_shr_i32, { "r", "rZ", "riZ" } },
1363 { INDEX_op_sar_i32, { "r", "rZ", "riZ" } },
1365 { INDEX_op_brcond_i32, { "rZ", "rZ" } },
1366 { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
1367 { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
1369 { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1370 { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1371 { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
1373 #if TARGET_LONG_BITS == 32
1374 { INDEX_op_qemu_ld8u, { "L", "lZ" } },
1375 { INDEX_op_qemu_ld8s, { "L", "lZ" } },
1376 { INDEX_op_qemu_ld16u, { "L", "lZ" } },
1377 { INDEX_op_qemu_ld16s, { "L", "lZ" } },
1378 { INDEX_op_qemu_ld32, { "L", "lZ" } },
1379 { INDEX_op_qemu_ld64, { "L", "L", "lZ" } },
1381 { INDEX_op_qemu_st8, { "SZ", "SZ" } },
1382 { INDEX_op_qemu_st16, { "SZ", "SZ" } },
1383 { INDEX_op_qemu_st32, { "SZ", "SZ" } },
1384 { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ" } },
1385 #else
1386 { INDEX_op_qemu_ld8u, { "L", "lZ", "lZ" } },
1387 { INDEX_op_qemu_ld8s, { "L", "lZ", "lZ" } },
1388 { INDEX_op_qemu_ld16u, { "L", "lZ", "lZ" } },
1389 { INDEX_op_qemu_ld16s, { "L", "lZ", "lZ" } },
1390 { INDEX_op_qemu_ld32, { "L", "lZ", "lZ" } },
1391 { INDEX_op_qemu_ld64, { "L", "L", "lZ", "lZ" } },
1393 { INDEX_op_qemu_st8, { "SZ", "SZ", "SZ" } },
1394 { INDEX_op_qemu_st16, { "SZ", "SZ", "SZ" } },
1395 { INDEX_op_qemu_st32, { "SZ", "SZ", "SZ" } },
1396 { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ", "SZ" } },
1397 #endif
1398 { -1 },
1401 static int tcg_target_callee_save_regs[] = {
1402 TCG_REG_S0,
1403 TCG_REG_S1,
1404 TCG_REG_S2,
1405 TCG_REG_S3,
1406 TCG_REG_S4,
1407 TCG_REG_S5,
1408 TCG_REG_S6,
1409 TCG_REG_S7,
1410 TCG_REG_GP,
1411 /* TCG_REG_FP, */ /* currently used for the global env, so np
1412 need to save */
1413 TCG_REG_RA, /* should be last for ABI compliance */
1416 /* Generate global QEMU prologue and epilogue code */
1417 void tcg_target_qemu_prologue(TCGContext *s)
1419 int i, frame_size;
1421 /* reserve some stack space */
1422 frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1423 + TCG_STATIC_CALL_ARGS_SIZE;
1424 frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1425 ~(TCG_TARGET_STACK_ALIGN - 1);
1427 /* TB prologue */
1428 tcg_out_addi(s, TCG_REG_SP, -frame_size);
1429 for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1430 tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1431 TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1434 /* Call generated code */
1435 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_A0, 0);
1436 tcg_out_nop(s);
1437 tb_ret_addr = s->code_ptr;
1439 /* TB epilogue */
1440 for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1441 tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1442 TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1445 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
1446 tcg_out_addi(s, TCG_REG_SP, frame_size);
1449 void tcg_target_init(TCGContext *s)
1451 tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
1452 tcg_regset_set(tcg_target_call_clobber_regs,
1453 (1 << TCG_REG_V0) |
1454 (1 << TCG_REG_V1) |
1455 (1 << TCG_REG_A0) |
1456 (1 << TCG_REG_A1) |
1457 (1 << TCG_REG_A2) |
1458 (1 << TCG_REG_A3) |
1459 (1 << TCG_REG_T1) |
1460 (1 << TCG_REG_T2) |
1461 (1 << TCG_REG_T3) |
1462 (1 << TCG_REG_T4) |
1463 (1 << TCG_REG_T5) |
1464 (1 << TCG_REG_T6) |
1465 (1 << TCG_REG_T7) |
1466 (1 << TCG_REG_T8) |
1467 (1 << TCG_REG_T9));
1469 tcg_regset_clear(s->reserved_regs);
1470 tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
1471 tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0); /* kernel use only */
1472 tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1); /* kernel use only */
1473 tcg_regset_set_reg(s->reserved_regs, TCG_REG_AT); /* internal use */
1474 tcg_regset_set_reg(s->reserved_regs, TCG_REG_T0); /* internal use */
1475 tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return address */
1476 tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */
1478 tcg_add_target_add_op_defs(mips_op_defs);