tcg/mips: kill warnings in user mode
[qemu.git] / tcg / mips / tcg-target.c
bloba09c0d6ca8933a9e9707a2276a20542a7fc9b8c7
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 # if (TARGET_LONG_BITS == 64)
221 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
222 # endif
223 #endif
224 break;
225 case 'S': /* qemu_st constraint */
226 ct->ct |= TCG_CT_REG;
227 tcg_regset_set(ct->u.regs, 0xffffffff);
228 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
229 #if defined(CONFIG_SOFTMMU)
230 # if (TARGET_LONG_BITS == 32)
231 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1);
232 # endif
233 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
234 # if TARGET_LONG_BITS == 64
235 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A3);
236 # endif
237 #endif
238 break;
239 case 'I':
240 ct->ct |= TCG_CT_CONST_U16;
241 break;
242 case 'J':
243 ct->ct |= TCG_CT_CONST_S16;
244 break;
245 case 'Z':
246 /* We are cheating a bit here, using the fact that the register
247 ZERO is also the register number 0. Hence there is no need
248 to check for const_args in each instruction. */
249 ct->ct |= TCG_CT_CONST_ZERO;
250 break;
251 default:
252 return -1;
254 ct_str++;
255 *pct_str = ct_str;
256 return 0;
259 /* test if a constant matches the constraint */
260 static inline int tcg_target_const_match(tcg_target_long val,
261 const TCGArgConstraint *arg_ct)
263 int ct;
264 ct = arg_ct->ct;
265 if (ct & TCG_CT_CONST)
266 return 1;
267 else if ((ct & TCG_CT_CONST_ZERO) && val == 0)
268 return 1;
269 else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val)
270 return 1;
271 else if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val)
272 return 1;
273 else
274 return 0;
277 /* instruction opcodes */
278 enum {
279 OPC_BEQ = 0x04 << 26,
280 OPC_BNE = 0x05 << 26,
281 OPC_ADDIU = 0x09 << 26,
282 OPC_SLTI = 0x0A << 26,
283 OPC_SLTIU = 0x0B << 26,
284 OPC_ANDI = 0x0C << 26,
285 OPC_ORI = 0x0D << 26,
286 OPC_XORI = 0x0E << 26,
287 OPC_LUI = 0x0F << 26,
288 OPC_LB = 0x20 << 26,
289 OPC_LH = 0x21 << 26,
290 OPC_LW = 0x23 << 26,
291 OPC_LBU = 0x24 << 26,
292 OPC_LHU = 0x25 << 26,
293 OPC_LWU = 0x27 << 26,
294 OPC_SB = 0x28 << 26,
295 OPC_SH = 0x29 << 26,
296 OPC_SW = 0x2B << 26,
298 OPC_SPECIAL = 0x00 << 26,
299 OPC_SLL = OPC_SPECIAL | 0x00,
300 OPC_SRL = OPC_SPECIAL | 0x02,
301 OPC_SRA = OPC_SPECIAL | 0x03,
302 OPC_SLLV = OPC_SPECIAL | 0x04,
303 OPC_SRLV = OPC_SPECIAL | 0x06,
304 OPC_SRAV = OPC_SPECIAL | 0x07,
305 OPC_JR = OPC_SPECIAL | 0x08,
306 OPC_JALR = OPC_SPECIAL | 0x09,
307 OPC_MFHI = OPC_SPECIAL | 0x10,
308 OPC_MFLO = OPC_SPECIAL | 0x12,
309 OPC_MULT = OPC_SPECIAL | 0x18,
310 OPC_MULTU = OPC_SPECIAL | 0x19,
311 OPC_DIV = OPC_SPECIAL | 0x1A,
312 OPC_DIVU = OPC_SPECIAL | 0x1B,
313 OPC_ADDU = OPC_SPECIAL | 0x21,
314 OPC_SUBU = OPC_SPECIAL | 0x23,
315 OPC_AND = OPC_SPECIAL | 0x24,
316 OPC_OR = OPC_SPECIAL | 0x25,
317 OPC_XOR = OPC_SPECIAL | 0x26,
318 OPC_NOR = OPC_SPECIAL | 0x27,
319 OPC_SLT = OPC_SPECIAL | 0x2A,
320 OPC_SLTU = OPC_SPECIAL | 0x2B,
322 OPC_SPECIAL3 = 0x1f << 26,
323 OPC_SEB = OPC_SPECIAL3 | 0x420,
324 OPC_SEH = OPC_SPECIAL3 | 0x620,
328 * Type reg
330 static inline void tcg_out_opc_reg(TCGContext *s, int opc, int rd, int rs, int rt)
332 int32_t inst;
334 inst = opc;
335 inst |= (rs & 0x1F) << 21;
336 inst |= (rt & 0x1F) << 16;
337 inst |= (rd & 0x1F) << 11;
338 tcg_out32(s, inst);
342 * Type immediate
344 static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int imm)
346 int32_t inst;
348 inst = opc;
349 inst |= (rs & 0x1F) << 21;
350 inst |= (rt & 0x1F) << 16;
351 inst |= (imm & 0xffff);
352 tcg_out32(s, inst);
356 * Type branch
358 static inline void tcg_out_opc_br(TCGContext *s, int opc, int rt, int rs)
360 /* We pay attention here to not modify the branch target by reading
361 the existing value and using it again. This ensure that caches and
362 memory are kept coherent during retranslation. */
363 uint16_t offset = (uint16_t)(*(uint32_t *) s->code_ptr);
365 tcg_out_opc_imm(s, opc, rt, rs, offset);
369 * Type sa
371 static inline void tcg_out_opc_sa(TCGContext *s, int opc, int rd, int rt, int sa)
373 int32_t inst;
375 inst = opc;
376 inst |= (rt & 0x1F) << 16;
377 inst |= (rd & 0x1F) << 11;
378 inst |= (sa & 0x1F) << 6;
379 tcg_out32(s, inst);
383 static inline void tcg_out_nop(TCGContext *s)
385 tcg_out32(s, 0);
388 static inline void tcg_out_mov(TCGContext *s, TCGType type,
389 TCGReg ret, TCGReg arg)
391 /* Simple reg-reg move, optimising out the 'do nothing' case */
392 if (ret != arg) {
393 tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
397 static inline void tcg_out_movi(TCGContext *s, TCGType type,
398 TCGReg reg, tcg_target_long arg)
400 if (arg == (int16_t)arg) {
401 tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
402 } else if (arg == (uint16_t)arg) {
403 tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
404 } else {
405 tcg_out_opc_imm(s, OPC_LUI, reg, 0, arg >> 16);
406 tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0xffff);
410 static inline void tcg_out_bswap16(TCGContext *s, int ret, int arg)
412 /* ret and arg can't be register at */
413 if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
414 tcg_abort();
417 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
418 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0x00ff);
420 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
421 tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
422 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
425 static inline void tcg_out_bswap16s(TCGContext *s, int ret, int arg)
427 /* ret and arg can't be register at */
428 if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
429 tcg_abort();
432 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
433 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff);
435 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
436 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
437 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
440 static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg)
442 /* ret and arg must be different and can't be register at */
443 if (ret == arg || ret == TCG_REG_AT || arg == TCG_REG_AT) {
444 tcg_abort();
447 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
449 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 24);
450 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
452 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, arg, 0xff00);
453 tcg_out_opc_sa(s, OPC_SLL, TCG_REG_AT, TCG_REG_AT, 8);
454 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
456 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
457 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff00);
458 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
461 static inline void tcg_out_ext8s(TCGContext *s, int ret, int arg)
463 #ifdef _MIPS_ARCH_MIPS32R2
464 tcg_out_opc_reg(s, OPC_SEB, ret, 0, arg);
465 #else
466 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
467 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 24);
468 #endif
471 static inline void tcg_out_ext16s(TCGContext *s, int ret, int arg)
473 #ifdef _MIPS_ARCH_MIPS32R2
474 tcg_out_opc_reg(s, OPC_SEH, ret, 0, arg);
475 #else
476 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 16);
477 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
478 #endif
481 static inline void tcg_out_ldst(TCGContext *s, int opc, int arg,
482 int arg1, tcg_target_long arg2)
484 if (arg2 == (int16_t) arg2) {
485 tcg_out_opc_imm(s, opc, arg, arg1, arg2);
486 } else {
487 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, arg2);
488 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, TCG_REG_AT, arg1);
489 tcg_out_opc_imm(s, opc, arg, TCG_REG_AT, 0);
493 static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
494 TCGReg arg1, tcg_target_long arg2)
496 tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
499 static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
500 TCGReg arg1, tcg_target_long arg2)
502 tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
505 static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
507 if (val == (int16_t)val) {
508 tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
509 } else {
510 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, val);
511 tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_REG_AT);
515 /* Helper routines for marshalling helper function arguments into
516 * the correct registers and stack.
517 * arg_num is where we want to put this argument, and is updated to be ready
518 * for the next call. arg is the argument itself. Note that arg_num 0..3 is
519 * real registers, 4+ on stack.
521 * We provide routines for arguments which are: immediate, 32 bit
522 * value in register, 16 and 8 bit values in register (which must be zero
523 * extended before use) and 64 bit value in a lo:hi register pair.
525 #define DEFINE_TCG_OUT_CALL_IARG(NAME, ARGPARAM) \
526 static inline void NAME(TCGContext *s, int *arg_num, ARGPARAM) \
528 if (*arg_num < 4) { \
529 DEFINE_TCG_OUT_CALL_IARG_GET_ARG(tcg_target_call_iarg_regs[*arg_num]); \
530 } else { \
531 DEFINE_TCG_OUT_CALL_IARG_GET_ARG(TCG_REG_AT); \
532 tcg_out_st(s, TCG_TYPE_I32, TCG_REG_AT, TCG_REG_SP, 4 * (*arg_num)); \
534 (*arg_num)++; \
536 #define DEFINE_TCG_OUT_CALL_IARG_GET_ARG(A) \
537 tcg_out_opc_imm(s, OPC_ANDI, A, arg, 0xff);
538 DEFINE_TCG_OUT_CALL_IARG(tcg_out_call_iarg_reg8, TCGReg arg)
539 #undef DEFINE_TCG_OUT_CALL_IARG_GET_ARG
540 #define DEFINE_TCG_OUT_CALL_IARG_GET_ARG(A) \
541 tcg_out_opc_imm(s, OPC_ANDI, A, arg, 0xffff);
542 DEFINE_TCG_OUT_CALL_IARG(tcg_out_call_iarg_reg16, TCGReg arg)
543 #undef DEFINE_TCG_OUT_CALL_IARG_GET_ARG
544 #define DEFINE_TCG_OUT_CALL_IARG_GET_ARG(A) \
545 tcg_out_movi(s, TCG_TYPE_I32, A, arg);
546 DEFINE_TCG_OUT_CALL_IARG(tcg_out_call_iarg_imm32, uint32_t arg)
547 #undef DEFINE_TCG_OUT_CALL_IARG_GET_ARG
549 /* We don't use the macro for this one to avoid an unnecessary reg-reg
550 move when storing to the stack. */
551 static inline void tcg_out_call_iarg_reg32(TCGContext *s, int *arg_num,
552 TCGReg arg)
554 if (*arg_num < 4) {
555 tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[*arg_num], arg);
556 } else {
557 tcg_out_st(s, TCG_TYPE_I32, arg, TCG_REG_SP, 4 * (*arg_num));
559 (*arg_num)++;
562 static inline void tcg_out_call_iarg_reg64(TCGContext *s, int *arg_num,
563 TCGReg arg_low, TCGReg arg_high)
565 (*arg_num) = (*arg_num + 1) & ~1;
567 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
568 tcg_out_call_iarg_reg32(s, arg_num, arg_high);
569 tcg_out_call_iarg_reg32(s, arg_num, arg_low);
570 #else
571 tcg_out_call_iarg_reg32(s, arg_num, arg_low);
572 tcg_out_call_iarg_reg32(s, arg_num, arg_high);
573 #endif
576 static void tcg_out_brcond(TCGContext *s, TCGCond cond, int arg1,
577 int arg2, int label_index)
579 TCGLabel *l = &s->labels[label_index];
581 switch (cond) {
582 case TCG_COND_EQ:
583 tcg_out_opc_br(s, OPC_BEQ, arg1, arg2);
584 break;
585 case TCG_COND_NE:
586 tcg_out_opc_br(s, OPC_BNE, arg1, arg2);
587 break;
588 case TCG_COND_LT:
589 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
590 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
591 break;
592 case TCG_COND_LTU:
593 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
594 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
595 break;
596 case TCG_COND_GE:
597 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
598 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
599 break;
600 case TCG_COND_GEU:
601 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
602 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
603 break;
604 case TCG_COND_LE:
605 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
606 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
607 break;
608 case TCG_COND_LEU:
609 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
610 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
611 break;
612 case TCG_COND_GT:
613 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
614 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
615 break;
616 case TCG_COND_GTU:
617 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
618 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
619 break;
620 default:
621 tcg_abort();
622 break;
624 if (l->has_value) {
625 reloc_pc16(s->code_ptr - 4, l->u.value);
626 } else {
627 tcg_out_reloc(s, s->code_ptr - 4, R_MIPS_PC16, label_index, 0);
629 tcg_out_nop(s);
632 /* XXX: we implement it at the target level to avoid having to
633 handle cross basic blocks temporaries */
634 static void tcg_out_brcond2(TCGContext *s, TCGCond cond, int arg1,
635 int arg2, int arg3, int arg4, int label_index)
637 void *label_ptr;
639 switch(cond) {
640 case TCG_COND_NE:
641 tcg_out_brcond(s, TCG_COND_NE, arg2, arg4, label_index);
642 tcg_out_brcond(s, TCG_COND_NE, arg1, arg3, label_index);
643 return;
644 case TCG_COND_EQ:
645 break;
646 case TCG_COND_LT:
647 case TCG_COND_LE:
648 tcg_out_brcond(s, TCG_COND_LT, arg2, arg4, label_index);
649 break;
650 case TCG_COND_GT:
651 case TCG_COND_GE:
652 tcg_out_brcond(s, TCG_COND_GT, arg2, arg4, label_index);
653 break;
654 case TCG_COND_LTU:
655 case TCG_COND_LEU:
656 tcg_out_brcond(s, TCG_COND_LTU, arg2, arg4, label_index);
657 break;
658 case TCG_COND_GTU:
659 case TCG_COND_GEU:
660 tcg_out_brcond(s, TCG_COND_GTU, arg2, arg4, label_index);
661 break;
662 default:
663 tcg_abort();
666 label_ptr = s->code_ptr;
667 tcg_out_opc_br(s, OPC_BNE, arg2, arg4);
668 tcg_out_nop(s);
670 switch(cond) {
671 case TCG_COND_EQ:
672 tcg_out_brcond(s, TCG_COND_EQ, arg1, arg3, label_index);
673 break;
674 case TCG_COND_LT:
675 case TCG_COND_LTU:
676 tcg_out_brcond(s, TCG_COND_LTU, arg1, arg3, label_index);
677 break;
678 case TCG_COND_LE:
679 case TCG_COND_LEU:
680 tcg_out_brcond(s, TCG_COND_LEU, arg1, arg3, label_index);
681 break;
682 case TCG_COND_GT:
683 case TCG_COND_GTU:
684 tcg_out_brcond(s, TCG_COND_GTU, arg1, arg3, label_index);
685 break;
686 case TCG_COND_GE:
687 case TCG_COND_GEU:
688 tcg_out_brcond(s, TCG_COND_GEU, arg1, arg3, label_index);
689 break;
690 default:
691 tcg_abort();
694 reloc_pc16(label_ptr, (tcg_target_long) s->code_ptr);
697 static void tcg_out_setcond(TCGContext *s, TCGCond cond, int ret,
698 int arg1, int arg2)
700 switch (cond) {
701 case TCG_COND_EQ:
702 if (arg1 == 0) {
703 tcg_out_opc_imm(s, OPC_SLTIU, ret, arg2, 1);
704 } else if (arg2 == 0) {
705 tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, 1);
706 } else {
707 tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
708 tcg_out_opc_imm(s, OPC_SLTIU, ret, ret, 1);
710 break;
711 case TCG_COND_NE:
712 if (arg1 == 0) {
713 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg2);
714 } else if (arg2 == 0) {
715 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg1);
716 } else {
717 tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
718 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, ret);
720 break;
721 case TCG_COND_LT:
722 tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
723 break;
724 case TCG_COND_LTU:
725 tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
726 break;
727 case TCG_COND_GE:
728 tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
729 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
730 break;
731 case TCG_COND_GEU:
732 tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
733 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
734 break;
735 case TCG_COND_LE:
736 tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
737 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
738 break;
739 case TCG_COND_LEU:
740 tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
741 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
742 break;
743 case TCG_COND_GT:
744 tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
745 break;
746 case TCG_COND_GTU:
747 tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
748 break;
749 default:
750 tcg_abort();
751 break;
755 /* XXX: we implement it at the target level to avoid having to
756 handle cross basic blocks temporaries */
757 static void tcg_out_setcond2(TCGContext *s, TCGCond cond, int ret,
758 int arg1, int arg2, int arg3, int arg4)
760 switch (cond) {
761 case TCG_COND_EQ:
762 tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_AT, arg2, arg4);
763 tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg1, arg3);
764 tcg_out_opc_reg(s, OPC_AND, ret, TCG_REG_AT, TCG_REG_T0);
765 return;
766 case TCG_COND_NE:
767 tcg_out_setcond(s, TCG_COND_NE, TCG_REG_AT, arg2, arg4);
768 tcg_out_setcond(s, TCG_COND_NE, TCG_REG_T0, arg1, arg3);
769 tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_AT, TCG_REG_T0);
770 return;
771 case TCG_COND_LT:
772 case TCG_COND_LE:
773 tcg_out_setcond(s, TCG_COND_LT, TCG_REG_AT, arg2, arg4);
774 break;
775 case TCG_COND_GT:
776 case TCG_COND_GE:
777 tcg_out_setcond(s, TCG_COND_GT, TCG_REG_AT, arg2, arg4);
778 break;
779 case TCG_COND_LTU:
780 case TCG_COND_LEU:
781 tcg_out_setcond(s, TCG_COND_LTU, TCG_REG_AT, arg2, arg4);
782 break;
783 case TCG_COND_GTU:
784 case TCG_COND_GEU:
785 tcg_out_setcond(s, TCG_COND_GTU, TCG_REG_AT, arg2, arg4);
786 break;
787 default:
788 tcg_abort();
789 break;
792 tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg2, arg4);
794 switch(cond) {
795 case TCG_COND_LT:
796 case TCG_COND_LTU:
797 tcg_out_setcond(s, TCG_COND_LTU, ret, arg1, arg3);
798 break;
799 case TCG_COND_LE:
800 case TCG_COND_LEU:
801 tcg_out_setcond(s, TCG_COND_LEU, ret, arg1, arg3);
802 break;
803 case TCG_COND_GT:
804 case TCG_COND_GTU:
805 tcg_out_setcond(s, TCG_COND_GTU, ret, arg1, arg3);
806 break;
807 case TCG_COND_GE:
808 case TCG_COND_GEU:
809 tcg_out_setcond(s, TCG_COND_GEU, ret, arg1, arg3);
810 break;
811 default:
812 tcg_abort();
815 tcg_out_opc_reg(s, OPC_AND, ret, ret, TCG_REG_T0);
816 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
819 #if defined(CONFIG_SOFTMMU)
821 #include "../../softmmu_defs.h"
823 /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
824 int mmu_idx) */
825 static const void * const qemu_ld_helpers[4] = {
826 helper_ldb_mmu,
827 helper_ldw_mmu,
828 helper_ldl_mmu,
829 helper_ldq_mmu,
832 /* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
833 uintxx_t val, int mmu_idx) */
834 static const void * const qemu_st_helpers[4] = {
835 helper_stb_mmu,
836 helper_stw_mmu,
837 helper_stl_mmu,
838 helper_stq_mmu,
840 #endif
842 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
843 int opc)
845 int addr_regl, data_regl, data_regh, data_reg1, data_reg2;
846 #if defined(CONFIG_SOFTMMU)
847 void *label1_ptr, *label2_ptr;
848 int arg_num;
849 int mem_index, s_bits;
850 int addr_meml;
851 # if TARGET_LONG_BITS == 64
852 uint8_t *label3_ptr;
853 int addr_regh, addr_memh;
854 # endif
855 #endif
856 data_regl = *args++;
857 if (opc == 3)
858 data_regh = *args++;
859 else
860 data_regh = 0;
861 addr_regl = *args++;
862 #if defined(CONFIG_SOFTMMU)
863 # if TARGET_LONG_BITS == 64
864 addr_regh = *args++;
865 # if defined(TCG_TARGET_WORDS_BIGENDIAN)
866 addr_memh = 0;
867 addr_meml = 4;
868 # else
869 addr_memh = 4;
870 addr_meml = 0;
871 # endif
872 # else
873 addr_meml = 0;
874 # endif
875 mem_index = *args;
876 s_bits = opc & 3;
877 #endif
879 if (opc == 3) {
880 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
881 data_reg1 = data_regh;
882 data_reg2 = data_regl;
883 #else
884 data_reg1 = data_regl;
885 data_reg2 = data_regh;
886 #endif
887 } else {
888 data_reg1 = data_regl;
889 data_reg2 = 0;
891 #if defined(CONFIG_SOFTMMU)
892 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
893 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
894 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
895 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
896 offsetof(CPUArchState, tlb_table[mem_index][0].addr_read) + addr_meml);
897 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
898 tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
900 # if TARGET_LONG_BITS == 64
901 label3_ptr = s->code_ptr;
902 tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
903 tcg_out_nop(s);
905 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
906 offsetof(CPUArchState, tlb_table[mem_index][0].addr_read) + addr_memh);
908 label1_ptr = s->code_ptr;
909 tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
910 tcg_out_nop(s);
912 reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
913 # else
914 label1_ptr = s->code_ptr;
915 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
916 tcg_out_nop(s);
917 # endif
919 /* slow path */
920 arg_num = 0;
921 tcg_out_call_iarg_reg32(s, &arg_num, TCG_AREG0);
922 # if TARGET_LONG_BITS == 64
923 tcg_out_call_iarg_reg64(s, &arg_num, addr_regl, addr_regh);
924 # else
925 tcg_out_call_iarg_reg32(s, &arg_num, addr_regl);
926 # endif
927 tcg_out_call_iarg_imm32(s, &arg_num, mem_index);
928 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]);
929 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
930 tcg_out_nop(s);
932 switch(opc) {
933 case 0:
934 tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xff);
935 break;
936 case 0 | 4:
937 tcg_out_ext8s(s, data_reg1, TCG_REG_V0);
938 break;
939 case 1:
940 tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xffff);
941 break;
942 case 1 | 4:
943 tcg_out_ext16s(s, data_reg1, TCG_REG_V0);
944 break;
945 case 2:
946 tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
947 break;
948 case 3:
949 tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_V1);
950 tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
951 break;
952 default:
953 tcg_abort();
956 label2_ptr = s->code_ptr;
957 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
958 tcg_out_nop(s);
960 /* label1: fast path */
961 reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
963 tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
964 offsetof(CPUArchState, tlb_table[mem_index][0].addend));
965 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_A0, addr_regl);
966 #else
967 if (GUEST_BASE == (int16_t)GUEST_BASE) {
968 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_V0, addr_regl, GUEST_BASE);
969 } else {
970 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, GUEST_BASE);
971 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_V0, addr_regl);
973 #endif
975 switch(opc) {
976 case 0:
977 tcg_out_opc_imm(s, OPC_LBU, data_reg1, TCG_REG_V0, 0);
978 break;
979 case 0 | 4:
980 tcg_out_opc_imm(s, OPC_LB, data_reg1, TCG_REG_V0, 0);
981 break;
982 case 1:
983 if (TCG_NEED_BSWAP) {
984 tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
985 tcg_out_bswap16(s, data_reg1, TCG_REG_T0);
986 } else {
987 tcg_out_opc_imm(s, OPC_LHU, data_reg1, TCG_REG_V0, 0);
989 break;
990 case 1 | 4:
991 if (TCG_NEED_BSWAP) {
992 tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
993 tcg_out_bswap16s(s, data_reg1, TCG_REG_T0);
994 } else {
995 tcg_out_opc_imm(s, OPC_LH, data_reg1, TCG_REG_V0, 0);
997 break;
998 case 2:
999 if (TCG_NEED_BSWAP) {
1000 tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
1001 tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
1002 } else {
1003 tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
1005 break;
1006 case 3:
1007 if (TCG_NEED_BSWAP) {
1008 tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 4);
1009 tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
1010 tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
1011 tcg_out_bswap32(s, data_reg2, TCG_REG_T0);
1012 } else {
1013 tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
1014 tcg_out_opc_imm(s, OPC_LW, data_reg2, TCG_REG_V0, 4);
1016 break;
1017 default:
1018 tcg_abort();
1021 #if defined(CONFIG_SOFTMMU)
1022 reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
1023 #endif
1026 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
1027 int opc)
1029 int addr_regl, data_regl, data_regh, data_reg1, data_reg2;
1030 #if defined(CONFIG_SOFTMMU)
1031 uint8_t *label1_ptr, *label2_ptr;
1032 int arg_num;
1033 int mem_index, s_bits;
1034 int addr_meml;
1035 #endif
1036 #if TARGET_LONG_BITS == 64
1037 # if defined(CONFIG_SOFTMMU)
1038 uint8_t *label3_ptr;
1039 int addr_regh, addr_memh;
1040 # endif
1041 #endif
1042 data_regl = *args++;
1043 if (opc == 3) {
1044 data_regh = *args++;
1045 } else {
1046 data_regh = 0;
1048 addr_regl = *args++;
1049 #if defined(CONFIG_SOFTMMU)
1050 # if TARGET_LONG_BITS == 64
1051 addr_regh = *args++;
1052 # if defined(TCG_TARGET_WORDS_BIGENDIAN)
1053 addr_memh = 0;
1054 addr_meml = 4;
1055 # else
1056 addr_memh = 4;
1057 addr_meml = 0;
1058 # endif
1059 # else
1060 addr_meml = 0;
1061 # endif
1062 mem_index = *args;
1063 s_bits = opc;
1064 #endif
1066 if (opc == 3) {
1067 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
1068 data_reg1 = data_regh;
1069 data_reg2 = data_regl;
1070 #else
1071 data_reg1 = data_regl;
1072 data_reg2 = data_regh;
1073 #endif
1074 } else {
1075 data_reg1 = data_regl;
1076 data_reg2 = 0;
1079 #if defined(CONFIG_SOFTMMU)
1080 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
1081 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
1082 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
1083 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
1084 offsetof(CPUArchState, tlb_table[mem_index][0].addr_write) + addr_meml);
1085 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
1086 tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
1088 # if TARGET_LONG_BITS == 64
1089 label3_ptr = s->code_ptr;
1090 tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
1091 tcg_out_nop(s);
1093 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
1094 offsetof(CPUArchState, tlb_table[mem_index][0].addr_write) + addr_memh);
1096 label1_ptr = s->code_ptr;
1097 tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
1098 tcg_out_nop(s);
1100 reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
1101 # else
1102 label1_ptr = s->code_ptr;
1103 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
1104 tcg_out_nop(s);
1105 # endif
1107 /* slow path */
1108 arg_num = 0;
1109 tcg_out_call_iarg_reg32(s, &arg_num, TCG_AREG0);
1110 # if TARGET_LONG_BITS == 64
1111 tcg_out_call_iarg_reg64(s, &arg_num, addr_regl, addr_regh);
1112 # else
1113 tcg_out_call_iarg_reg32(s, &arg_num, addr_regl);
1114 # endif
1115 switch(opc) {
1116 case 0:
1117 tcg_out_call_iarg_reg8(s, &arg_num, data_regl);
1118 break;
1119 case 1:
1120 tcg_out_call_iarg_reg16(s, &arg_num, data_regl);
1121 break;
1122 case 2:
1123 tcg_out_call_iarg_reg32(s, &arg_num, data_regl);
1124 break;
1125 case 3:
1126 tcg_out_call_iarg_reg64(s, &arg_num, data_regl, data_regh);
1127 break;
1128 default:
1129 tcg_abort();
1131 tcg_out_call_iarg_imm32(s, &arg_num, mem_index);
1132 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_st_helpers[s_bits]);
1133 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
1134 tcg_out_nop(s);
1136 label2_ptr = s->code_ptr;
1137 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
1138 tcg_out_nop(s);
1140 /* label1: fast path */
1141 reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
1143 tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
1144 offsetof(CPUArchState, tlb_table[mem_index][0].addend));
1145 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
1146 #else
1147 if (GUEST_BASE == (int16_t)GUEST_BASE) {
1148 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_A0, addr_regl, GUEST_BASE);
1149 } else {
1150 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, GUEST_BASE);
1151 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
1154 #endif
1156 switch(opc) {
1157 case 0:
1158 tcg_out_opc_imm(s, OPC_SB, data_reg1, TCG_REG_A0, 0);
1159 break;
1160 case 1:
1161 if (TCG_NEED_BSWAP) {
1162 tcg_out_bswap16(s, TCG_REG_T0, data_reg1);
1163 tcg_out_opc_imm(s, OPC_SH, TCG_REG_T0, TCG_REG_A0, 0);
1164 } else {
1165 tcg_out_opc_imm(s, OPC_SH, data_reg1, TCG_REG_A0, 0);
1167 break;
1168 case 2:
1169 if (TCG_NEED_BSWAP) {
1170 tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1171 tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
1172 } else {
1173 tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
1175 break;
1176 case 3:
1177 if (TCG_NEED_BSWAP) {
1178 tcg_out_bswap32(s, TCG_REG_T0, data_reg2);
1179 tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
1180 tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1181 tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 4);
1182 } else {
1183 tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
1184 tcg_out_opc_imm(s, OPC_SW, data_reg2, TCG_REG_A0, 4);
1186 break;
1187 default:
1188 tcg_abort();
1191 #if defined(CONFIG_SOFTMMU)
1192 reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
1193 #endif
1196 static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1197 const TCGArg *args, const int *const_args)
1199 switch(opc) {
1200 case INDEX_op_exit_tb:
1201 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_V0, args[0]);
1202 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, (tcg_target_long)tb_ret_addr);
1203 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1204 tcg_out_nop(s);
1205 break;
1206 case INDEX_op_goto_tb:
1207 if (s->tb_jmp_offset) {
1208 /* direct jump method */
1209 tcg_abort();
1210 } else {
1211 /* indirect jump method */
1212 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, (tcg_target_long)(s->tb_next + args[0]));
1213 tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_AT, TCG_REG_AT, 0);
1214 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1216 tcg_out_nop(s);
1217 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1218 break;
1219 case INDEX_op_call:
1220 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, args[0], 0);
1221 tcg_out_nop(s);
1222 break;
1223 case INDEX_op_jmp:
1224 tcg_out_opc_reg(s, OPC_JR, 0, args[0], 0);
1225 tcg_out_nop(s);
1226 break;
1227 case INDEX_op_br:
1228 tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, args[0]);
1229 break;
1231 case INDEX_op_mov_i32:
1232 tcg_out_mov(s, TCG_TYPE_I32, args[0], args[1]);
1233 break;
1234 case INDEX_op_movi_i32:
1235 tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1236 break;
1238 case INDEX_op_ld8u_i32:
1239 tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]);
1240 break;
1241 case INDEX_op_ld8s_i32:
1242 tcg_out_ldst(s, OPC_LB, args[0], args[1], args[2]);
1243 break;
1244 case INDEX_op_ld16u_i32:
1245 tcg_out_ldst(s, OPC_LHU, args[0], args[1], args[2]);
1246 break;
1247 case INDEX_op_ld16s_i32:
1248 tcg_out_ldst(s, OPC_LH, args[0], args[1], args[2]);
1249 break;
1250 case INDEX_op_ld_i32:
1251 tcg_out_ldst(s, OPC_LW, args[0], args[1], args[2]);
1252 break;
1253 case INDEX_op_st8_i32:
1254 tcg_out_ldst(s, OPC_SB, args[0], args[1], args[2]);
1255 break;
1256 case INDEX_op_st16_i32:
1257 tcg_out_ldst(s, OPC_SH, args[0], args[1], args[2]);
1258 break;
1259 case INDEX_op_st_i32:
1260 tcg_out_ldst(s, OPC_SW, args[0], args[1], args[2]);
1261 break;
1263 case INDEX_op_add_i32:
1264 if (const_args[2]) {
1265 tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], args[2]);
1266 } else {
1267 tcg_out_opc_reg(s, OPC_ADDU, args[0], args[1], args[2]);
1269 break;
1270 case INDEX_op_add2_i32:
1271 if (const_args[4]) {
1272 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], args[4]);
1273 } else {
1274 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, args[2], args[4]);
1276 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, TCG_REG_AT, args[2]);
1277 if (const_args[5]) {
1278 tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], args[5]);
1279 } else {
1280 tcg_out_opc_reg(s, OPC_ADDU, args[1], args[3], args[5]);
1282 tcg_out_opc_reg(s, OPC_ADDU, args[1], args[1], TCG_REG_T0);
1283 tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
1284 break;
1285 case INDEX_op_sub_i32:
1286 if (const_args[2]) {
1287 tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], -args[2]);
1288 } else {
1289 tcg_out_opc_reg(s, OPC_SUBU, args[0], args[1], args[2]);
1291 break;
1292 case INDEX_op_sub2_i32:
1293 if (const_args[4]) {
1294 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], -args[4]);
1295 } else {
1296 tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, args[2], args[4]);
1298 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, args[2], TCG_REG_AT);
1299 if (const_args[5]) {
1300 tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], -args[5]);
1301 } else {
1302 tcg_out_opc_reg(s, OPC_SUBU, args[1], args[3], args[5]);
1304 tcg_out_opc_reg(s, OPC_SUBU, args[1], args[1], TCG_REG_T0);
1305 tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
1306 break;
1307 case INDEX_op_mul_i32:
1308 tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
1309 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1310 break;
1311 case INDEX_op_mulu2_i32:
1312 tcg_out_opc_reg(s, OPC_MULTU, 0, args[2], args[3]);
1313 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1314 tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
1315 break;
1316 case INDEX_op_div_i32:
1317 tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1318 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1319 break;
1320 case INDEX_op_divu_i32:
1321 tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1322 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1323 break;
1324 case INDEX_op_rem_i32:
1325 tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1326 tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1327 break;
1328 case INDEX_op_remu_i32:
1329 tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1330 tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1331 break;
1333 case INDEX_op_and_i32:
1334 if (const_args[2]) {
1335 tcg_out_opc_imm(s, OPC_ANDI, args[0], args[1], args[2]);
1336 } else {
1337 tcg_out_opc_reg(s, OPC_AND, args[0], args[1], args[2]);
1339 break;
1340 case INDEX_op_or_i32:
1341 if (const_args[2]) {
1342 tcg_out_opc_imm(s, OPC_ORI, args[0], args[1], args[2]);
1343 } else {
1344 tcg_out_opc_reg(s, OPC_OR, args[0], args[1], args[2]);
1346 break;
1347 case INDEX_op_nor_i32:
1348 tcg_out_opc_reg(s, OPC_NOR, args[0], args[1], args[2]);
1349 break;
1350 case INDEX_op_not_i32:
1351 tcg_out_opc_reg(s, OPC_NOR, args[0], TCG_REG_ZERO, args[1]);
1352 break;
1353 case INDEX_op_xor_i32:
1354 if (const_args[2]) {
1355 tcg_out_opc_imm(s, OPC_XORI, args[0], args[1], args[2]);
1356 } else {
1357 tcg_out_opc_reg(s, OPC_XOR, args[0], args[1], args[2]);
1359 break;
1361 case INDEX_op_sar_i32:
1362 if (const_args[2]) {
1363 tcg_out_opc_sa(s, OPC_SRA, args[0], args[1], args[2]);
1364 } else {
1365 tcg_out_opc_reg(s, OPC_SRAV, args[0], args[2], args[1]);
1367 break;
1368 case INDEX_op_shl_i32:
1369 if (const_args[2]) {
1370 tcg_out_opc_sa(s, OPC_SLL, args[0], args[1], args[2]);
1371 } else {
1372 tcg_out_opc_reg(s, OPC_SLLV, args[0], args[2], args[1]);
1374 break;
1375 case INDEX_op_shr_i32:
1376 if (const_args[2]) {
1377 tcg_out_opc_sa(s, OPC_SRL, args[0], args[1], args[2]);
1378 } else {
1379 tcg_out_opc_reg(s, OPC_SRLV, args[0], args[2], args[1]);
1381 break;
1383 case INDEX_op_ext8s_i32:
1384 tcg_out_ext8s(s, args[0], args[1]);
1385 break;
1386 case INDEX_op_ext16s_i32:
1387 tcg_out_ext16s(s, args[0], args[1]);
1388 break;
1390 case INDEX_op_brcond_i32:
1391 tcg_out_brcond(s, args[2], args[0], args[1], args[3]);
1392 break;
1393 case INDEX_op_brcond2_i32:
1394 tcg_out_brcond2(s, args[4], args[0], args[1], args[2], args[3], args[5]);
1395 break;
1397 case INDEX_op_setcond_i32:
1398 tcg_out_setcond(s, args[3], args[0], args[1], args[2]);
1399 break;
1400 case INDEX_op_setcond2_i32:
1401 tcg_out_setcond2(s, args[5], args[0], args[1], args[2], args[3], args[4]);
1402 break;
1404 case INDEX_op_qemu_ld8u:
1405 tcg_out_qemu_ld(s, args, 0);
1406 break;
1407 case INDEX_op_qemu_ld8s:
1408 tcg_out_qemu_ld(s, args, 0 | 4);
1409 break;
1410 case INDEX_op_qemu_ld16u:
1411 tcg_out_qemu_ld(s, args, 1);
1412 break;
1413 case INDEX_op_qemu_ld16s:
1414 tcg_out_qemu_ld(s, args, 1 | 4);
1415 break;
1416 case INDEX_op_qemu_ld32:
1417 tcg_out_qemu_ld(s, args, 2);
1418 break;
1419 case INDEX_op_qemu_ld64:
1420 tcg_out_qemu_ld(s, args, 3);
1421 break;
1422 case INDEX_op_qemu_st8:
1423 tcg_out_qemu_st(s, args, 0);
1424 break;
1425 case INDEX_op_qemu_st16:
1426 tcg_out_qemu_st(s, args, 1);
1427 break;
1428 case INDEX_op_qemu_st32:
1429 tcg_out_qemu_st(s, args, 2);
1430 break;
1431 case INDEX_op_qemu_st64:
1432 tcg_out_qemu_st(s, args, 3);
1433 break;
1435 default:
1436 tcg_abort();
1440 static const TCGTargetOpDef mips_op_defs[] = {
1441 { INDEX_op_exit_tb, { } },
1442 { INDEX_op_goto_tb, { } },
1443 { INDEX_op_call, { "C" } },
1444 { INDEX_op_jmp, { "r" } },
1445 { INDEX_op_br, { } },
1447 { INDEX_op_mov_i32, { "r", "r" } },
1448 { INDEX_op_movi_i32, { "r" } },
1449 { INDEX_op_ld8u_i32, { "r", "r" } },
1450 { INDEX_op_ld8s_i32, { "r", "r" } },
1451 { INDEX_op_ld16u_i32, { "r", "r" } },
1452 { INDEX_op_ld16s_i32, { "r", "r" } },
1453 { INDEX_op_ld_i32, { "r", "r" } },
1454 { INDEX_op_st8_i32, { "rZ", "r" } },
1455 { INDEX_op_st16_i32, { "rZ", "r" } },
1456 { INDEX_op_st_i32, { "rZ", "r" } },
1458 { INDEX_op_add_i32, { "r", "rZ", "rJ" } },
1459 { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
1460 { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
1461 { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
1462 { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
1463 { INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
1464 { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
1465 { INDEX_op_sub_i32, { "r", "rZ", "rJ" } },
1467 { INDEX_op_and_i32, { "r", "rZ", "rI" } },
1468 { INDEX_op_nor_i32, { "r", "rZ", "rZ" } },
1469 { INDEX_op_not_i32, { "r", "rZ" } },
1470 { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
1471 { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
1473 { INDEX_op_shl_i32, { "r", "rZ", "ri" } },
1474 { INDEX_op_shr_i32, { "r", "rZ", "ri" } },
1475 { INDEX_op_sar_i32, { "r", "rZ", "ri" } },
1477 { INDEX_op_ext8s_i32, { "r", "rZ" } },
1478 { INDEX_op_ext16s_i32, { "r", "rZ" } },
1480 { INDEX_op_brcond_i32, { "rZ", "rZ" } },
1481 { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
1482 { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
1484 { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJ", "rJ" } },
1485 { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJ", "rJ" } },
1486 { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
1488 #if TARGET_LONG_BITS == 32
1489 { INDEX_op_qemu_ld8u, { "L", "lZ" } },
1490 { INDEX_op_qemu_ld8s, { "L", "lZ" } },
1491 { INDEX_op_qemu_ld16u, { "L", "lZ" } },
1492 { INDEX_op_qemu_ld16s, { "L", "lZ" } },
1493 { INDEX_op_qemu_ld32, { "L", "lZ" } },
1494 { INDEX_op_qemu_ld64, { "L", "L", "lZ" } },
1496 { INDEX_op_qemu_st8, { "SZ", "SZ" } },
1497 { INDEX_op_qemu_st16, { "SZ", "SZ" } },
1498 { INDEX_op_qemu_st32, { "SZ", "SZ" } },
1499 { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ" } },
1500 #else
1501 { INDEX_op_qemu_ld8u, { "L", "lZ", "lZ" } },
1502 { INDEX_op_qemu_ld8s, { "L", "lZ", "lZ" } },
1503 { INDEX_op_qemu_ld16u, { "L", "lZ", "lZ" } },
1504 { INDEX_op_qemu_ld16s, { "L", "lZ", "lZ" } },
1505 { INDEX_op_qemu_ld32, { "L", "lZ", "lZ" } },
1506 { INDEX_op_qemu_ld64, { "L", "L", "lZ", "lZ" } },
1508 { INDEX_op_qemu_st8, { "SZ", "SZ", "SZ" } },
1509 { INDEX_op_qemu_st16, { "SZ", "SZ", "SZ" } },
1510 { INDEX_op_qemu_st32, { "SZ", "SZ", "SZ" } },
1511 { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ", "SZ" } },
1512 #endif
1513 { -1 },
1516 static int tcg_target_callee_save_regs[] = {
1517 TCG_REG_S0, /* used for the global env (TCG_AREG0) */
1518 TCG_REG_S1,
1519 TCG_REG_S2,
1520 TCG_REG_S3,
1521 TCG_REG_S4,
1522 TCG_REG_S5,
1523 TCG_REG_S6,
1524 TCG_REG_S7,
1525 TCG_REG_GP,
1526 TCG_REG_FP,
1527 TCG_REG_RA, /* should be last for ABI compliance */
1530 /* Generate global QEMU prologue and epilogue code */
1531 static void tcg_target_qemu_prologue(TCGContext *s)
1533 int i, frame_size;
1535 /* reserve some stack space */
1536 frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1537 + TCG_STATIC_CALL_ARGS_SIZE;
1538 frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1539 ~(TCG_TARGET_STACK_ALIGN - 1);
1541 /* TB prologue */
1542 tcg_out_addi(s, TCG_REG_SP, -frame_size);
1543 for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1544 tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1545 TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1548 /* Call generated code */
1549 tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1], 0);
1550 tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
1551 tb_ret_addr = s->code_ptr;
1553 /* TB epilogue */
1554 for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1555 tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1556 TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1559 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
1560 tcg_out_addi(s, TCG_REG_SP, frame_size);
1563 static void tcg_target_init(TCGContext *s)
1565 tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
1566 tcg_regset_set(tcg_target_call_clobber_regs,
1567 (1 << TCG_REG_V0) |
1568 (1 << TCG_REG_V1) |
1569 (1 << TCG_REG_A0) |
1570 (1 << TCG_REG_A1) |
1571 (1 << TCG_REG_A2) |
1572 (1 << TCG_REG_A3) |
1573 (1 << TCG_REG_T1) |
1574 (1 << TCG_REG_T2) |
1575 (1 << TCG_REG_T3) |
1576 (1 << TCG_REG_T4) |
1577 (1 << TCG_REG_T5) |
1578 (1 << TCG_REG_T6) |
1579 (1 << TCG_REG_T7) |
1580 (1 << TCG_REG_T8) |
1581 (1 << TCG_REG_T9));
1583 tcg_regset_clear(s->reserved_regs);
1584 tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
1585 tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0); /* kernel use only */
1586 tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1); /* kernel use only */
1587 tcg_regset_set_reg(s->reserved_regs, TCG_REG_AT); /* internal use */
1588 tcg_regset_set_reg(s->reserved_regs, TCG_REG_T0); /* internal use */
1589 tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return address */
1590 tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */
1592 tcg_add_target_add_op_defs(mips_op_defs);
1593 tcg_set_frame(s, TCG_AREG0, offsetof(CPUArchState, temp_buf),
1594 CPU_TEMP_BUF_NLONGS * sizeof(long));