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
27 #if defined(TCG_TARGET_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
28 # define TCG_NEED_BSWAP 0
30 # define TCG_NEED_BSWAP 1
34 static const char * const tcg_target_reg_names
[TCG_TARGET_NB_REGS
] = {
70 /* check if we really need so many registers :P */
71 static const int tcg_target_reg_alloc_order
[] = {
97 static const int tcg_target_call_iarg_regs
[4] = {
104 static const int tcg_target_call_oarg_regs
[2] = {
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
)
137 disp
= target
- (tcg_target_long
) pc
- 4;
138 if (disp
!= (disp
<< 14) >> 14) {
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)) {
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
)
172 reloc_lo16(code_ptr
, value
);
175 reloc_hi16(code_ptr
, value
);
178 reloc_pc16(code_ptr
, value
);
181 reloc_pc26(code_ptr
, value
);
188 /* maximum number of register used for input function arguments */
189 static inline int tcg_target_get_call_iarg_regs_count(int flags
)
194 /* parse target specific constraints */
195 static int target_parse_constraint(TCGArgConstraint
*ct
, const char **pct_str
)
202 ct
->ct
|= TCG_CT_REG
;
203 tcg_regset_set(ct
->u
.regs
, 0xffffffff);
206 ct
->ct
|= TCG_CT_REG
;
207 tcg_regset_clear(ct
->u
.regs
);
208 tcg_regset_set_reg(ct
->u
.regs
, TCG_REG_T9
);
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
);
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
);
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
);
230 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_A2
);
234 ct
->ct
|= TCG_CT_CONST_U16
;
237 ct
->ct
|= TCG_CT_CONST_S16
;
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
;
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
)
259 if (ct
& TCG_CT_CONST
)
261 else if ((ct
& TCG_CT_CONST_ZERO
) && val
== 0)
263 else if ((ct
& TCG_CT_CONST_U16
) && val
== (uint16_t)val
)
265 else if ((ct
& TCG_CT_CONST_S16
) && val
== (int16_t)val
)
271 /* instruction opcodes */
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,
285 OPC_LBU
= 0x24 << 26,
286 OPC_LHU
= 0x25 << 26,
287 OPC_LWU
= 0x27 << 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,
324 static inline void tcg_out_opc_reg(TCGContext
*s
, int opc
, int rd
, int rs
, int rt
)
329 inst
|= (rs
& 0x1F) << 21;
330 inst
|= (rt
& 0x1F) << 16;
331 inst
|= (rd
& 0x1F) << 11;
338 static inline void tcg_out_opc_imm(TCGContext
*s
, int opc
, int rt
, int rs
, int imm
)
343 inst
|= (rs
& 0x1F) << 21;
344 inst
|= (rt
& 0x1F) << 16;
345 inst
|= (imm
& 0xffff);
352 static inline void tcg_out_opc_br(TCGContext
*s
, int opc
, int rt
, int rs
)
354 /* We pay attention here to not modify the branch target by reading
355 the existing value and using it again. This ensure that caches and
356 memory are kept coherent during retranslation. */
357 uint16_t offset
= (uint16_t)(*(uint32_t *) s
->code_ptr
);
359 tcg_out_opc_imm(s
, opc
, rt
, rs
, offset
);
365 static inline void tcg_out_opc_sa(TCGContext
*s
, int opc
, int rd
, int rt
, int sa
)
370 inst
|= (rt
& 0x1F) << 16;
371 inst
|= (rd
& 0x1F) << 11;
372 inst
|= (sa
& 0x1F) << 6;
377 static inline void tcg_out_nop(TCGContext
*s
)
382 static inline void tcg_out_mov(TCGContext
*s
, TCGType type
, int ret
, int arg
)
384 tcg_out_opc_reg(s
, OPC_ADDU
, ret
, arg
, TCG_REG_ZERO
);
387 static inline void tcg_out_movi(TCGContext
*s
, TCGType type
,
388 int reg
, int32_t arg
)
390 if (arg
== (int16_t)arg
) {
391 tcg_out_opc_imm(s
, OPC_ADDIU
, reg
, TCG_REG_ZERO
, arg
);
392 } else if (arg
== (uint16_t)arg
) {
393 tcg_out_opc_imm(s
, OPC_ORI
, reg
, TCG_REG_ZERO
, arg
);
395 tcg_out_opc_imm(s
, OPC_LUI
, reg
, 0, arg
>> 16);
396 tcg_out_opc_imm(s
, OPC_ORI
, reg
, reg
, arg
& 0xffff);
400 static inline void tcg_out_bswap16(TCGContext
*s
, int ret
, int arg
)
402 /* ret and arg can't be register at */
403 if (ret
== TCG_REG_AT
|| arg
== TCG_REG_AT
) {
407 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_AT
, arg
, 8);
408 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_AT
, TCG_REG_AT
, 0x00ff);
410 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 8);
411 tcg_out_opc_imm(s
, OPC_ANDI
, ret
, ret
, 0xff00);
412 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
415 static inline void tcg_out_bswap16s(TCGContext
*s
, int ret
, int arg
)
417 /* ret and arg can't be register at */
418 if (ret
== TCG_REG_AT
|| arg
== TCG_REG_AT
) {
422 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_AT
, arg
, 8);
423 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_AT
, TCG_REG_AT
, 0xff);
425 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 24);
426 tcg_out_opc_sa(s
, OPC_SRA
, ret
, ret
, 16);
427 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
430 static inline void tcg_out_bswap32(TCGContext
*s
, int ret
, int arg
)
432 /* ret and arg must be different and can't be register at */
433 if (ret
== arg
|| ret
== TCG_REG_AT
|| arg
== TCG_REG_AT
) {
437 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 24);
439 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_AT
, arg
, 24);
440 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
442 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_AT
, arg
, 0xff00);
443 tcg_out_opc_sa(s
, OPC_SLL
, TCG_REG_AT
, TCG_REG_AT
, 8);
444 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
446 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_AT
, arg
, 8);
447 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_AT
, TCG_REG_AT
, 0xff00);
448 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
451 static inline void tcg_out_ext8s(TCGContext
*s
, int ret
, int arg
)
453 #ifdef _MIPS_ARCH_MIPS32R2
454 tcg_out_opc_reg(s
, OPC_SEB
, ret
, 0, arg
);
456 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 24);
457 tcg_out_opc_sa(s
, OPC_SRA
, ret
, ret
, 24);
461 static inline void tcg_out_ext16s(TCGContext
*s
, int ret
, int arg
)
463 #ifdef _MIPS_ARCH_MIPS32R2
464 tcg_out_opc_reg(s
, OPC_SEH
, ret
, 0, arg
);
466 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 16);
467 tcg_out_opc_sa(s
, OPC_SRA
, ret
, ret
, 16);
471 static inline void tcg_out_ldst(TCGContext
*s
, int opc
, int arg
,
472 int arg1
, tcg_target_long arg2
)
474 if (arg2
== (int16_t) arg2
) {
475 tcg_out_opc_imm(s
, opc
, arg
, arg1
, arg2
);
477 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_AT
, arg2
);
478 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_AT
, TCG_REG_AT
, arg1
);
479 tcg_out_opc_imm(s
, opc
, arg
, TCG_REG_AT
, 0);
483 static inline void tcg_out_ld(TCGContext
*s
, TCGType type
, int arg
,
484 int arg1
, tcg_target_long arg2
)
486 tcg_out_ldst(s
, OPC_LW
, arg
, arg1
, arg2
);
489 static inline void tcg_out_st(TCGContext
*s
, TCGType type
, int arg
,
490 int arg1
, tcg_target_long arg2
)
492 tcg_out_ldst(s
, OPC_SW
, arg
, arg1
, arg2
);
495 static inline void tcg_out_addi(TCGContext
*s
, int reg
, tcg_target_long val
)
497 if (val
== (int16_t)val
) {
498 tcg_out_opc_imm(s
, OPC_ADDIU
, reg
, reg
, val
);
500 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_AT
, val
);
501 tcg_out_opc_reg(s
, OPC_ADDU
, reg
, reg
, TCG_REG_AT
);
505 static void tcg_out_brcond(TCGContext
*s
, TCGCond cond
, int arg1
,
506 int arg2
, int label_index
)
508 TCGLabel
*l
= &s
->labels
[label_index
];
512 tcg_out_opc_br(s
, OPC_BEQ
, arg1
, arg2
);
515 tcg_out_opc_br(s
, OPC_BNE
, arg1
, arg2
);
518 tcg_out_opc_reg(s
, OPC_SLT
, TCG_REG_AT
, arg1
, arg2
);
519 tcg_out_opc_br(s
, OPC_BNE
, TCG_REG_AT
, TCG_REG_ZERO
);
522 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_AT
, arg1
, arg2
);
523 tcg_out_opc_br(s
, OPC_BNE
, TCG_REG_AT
, TCG_REG_ZERO
);
526 tcg_out_opc_reg(s
, OPC_SLT
, TCG_REG_AT
, arg1
, arg2
);
527 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_AT
, TCG_REG_ZERO
);
530 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_AT
, arg1
, arg2
);
531 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_AT
, TCG_REG_ZERO
);
534 tcg_out_opc_reg(s
, OPC_SLT
, TCG_REG_AT
, arg2
, arg1
);
535 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_AT
, TCG_REG_ZERO
);
538 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_AT
, arg2
, arg1
);
539 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_AT
, TCG_REG_ZERO
);
542 tcg_out_opc_reg(s
, OPC_SLT
, TCG_REG_AT
, arg2
, arg1
);
543 tcg_out_opc_br(s
, OPC_BNE
, TCG_REG_AT
, TCG_REG_ZERO
);
546 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_AT
, arg2
, arg1
);
547 tcg_out_opc_br(s
, OPC_BNE
, TCG_REG_AT
, TCG_REG_ZERO
);
554 reloc_pc16(s
->code_ptr
- 4, l
->u
.value
);
556 tcg_out_reloc(s
, s
->code_ptr
- 4, R_MIPS_PC16
, label_index
, 0);
561 /* XXX: we implement it at the target level to avoid having to
562 handle cross basic blocks temporaries */
563 static void tcg_out_brcond2(TCGContext
*s
, TCGCond cond
, int arg1
,
564 int arg2
, int arg3
, int arg4
, int label_index
)
570 tcg_out_brcond(s
, TCG_COND_NE
, arg2
, arg4
, label_index
);
571 tcg_out_brcond(s
, TCG_COND_NE
, arg1
, arg3
, label_index
);
577 tcg_out_brcond(s
, TCG_COND_LT
, arg2
, arg4
, label_index
);
581 tcg_out_brcond(s
, TCG_COND_GT
, arg2
, arg4
, label_index
);
585 tcg_out_brcond(s
, TCG_COND_LTU
, arg2
, arg4
, label_index
);
589 tcg_out_brcond(s
, TCG_COND_GTU
, arg2
, arg4
, label_index
);
595 label_ptr
= s
->code_ptr
;
596 tcg_out_opc_br(s
, OPC_BNE
, arg2
, arg4
);
601 tcg_out_brcond(s
, TCG_COND_EQ
, arg1
, arg3
, label_index
);
605 tcg_out_brcond(s
, TCG_COND_LTU
, arg1
, arg3
, label_index
);
609 tcg_out_brcond(s
, TCG_COND_LEU
, arg1
, arg3
, label_index
);
613 tcg_out_brcond(s
, TCG_COND_GTU
, arg1
, arg3
, label_index
);
617 tcg_out_brcond(s
, TCG_COND_GEU
, arg1
, arg3
, label_index
);
623 reloc_pc16(label_ptr
, (tcg_target_long
) s
->code_ptr
);
626 static void tcg_out_setcond(TCGContext
*s
, TCGCond cond
, int ret
,
632 tcg_out_opc_imm(s
, OPC_SLTIU
, ret
, arg2
, 1);
633 } else if (arg2
== 0) {
634 tcg_out_opc_imm(s
, OPC_SLTIU
, ret
, arg1
, 1);
636 tcg_out_opc_reg(s
, OPC_XOR
, ret
, arg1
, arg2
);
637 tcg_out_opc_imm(s
, OPC_SLTIU
, ret
, ret
, 1);
642 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, TCG_REG_ZERO
, arg2
);
643 } else if (arg2
== 0) {
644 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, TCG_REG_ZERO
, arg1
);
646 tcg_out_opc_reg(s
, OPC_XOR
, ret
, arg1
, arg2
);
647 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, TCG_REG_ZERO
, ret
);
651 tcg_out_opc_reg(s
, OPC_SLT
, ret
, arg1
, arg2
);
654 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, arg1
, arg2
);
657 tcg_out_opc_reg(s
, OPC_SLT
, ret
, arg1
, arg2
);
658 tcg_out_opc_imm(s
, OPC_XORI
, ret
, ret
, 1);
661 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, arg1
, arg2
);
662 tcg_out_opc_imm(s
, OPC_XORI
, ret
, ret
, 1);
665 tcg_out_opc_reg(s
, OPC_SLT
, ret
, arg2
, arg1
);
666 tcg_out_opc_imm(s
, OPC_XORI
, ret
, ret
, 1);
669 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, arg2
, arg1
);
670 tcg_out_opc_imm(s
, OPC_XORI
, ret
, ret
, 1);
673 tcg_out_opc_reg(s
, OPC_SLT
, ret
, arg2
, arg1
);
676 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, arg2
, arg1
);
684 /* XXX: we implement it at the target level to avoid having to
685 handle cross basic blocks temporaries */
686 static void tcg_out_setcond2(TCGContext
*s
, TCGCond cond
, int ret
,
687 int arg1
, int arg2
, int arg3
, int arg4
)
691 tcg_out_setcond(s
, TCG_COND_EQ
, TCG_REG_AT
, arg2
, arg4
);
692 tcg_out_setcond(s
, TCG_COND_EQ
, TCG_REG_T0
, arg1
, arg3
);
693 tcg_out_opc_reg(s
, OPC_AND
, ret
, TCG_REG_AT
, TCG_REG_T0
);
696 tcg_out_setcond(s
, TCG_COND_NE
, TCG_REG_AT
, arg2
, arg4
);
697 tcg_out_setcond(s
, TCG_COND_NE
, TCG_REG_T0
, arg1
, arg3
);
698 tcg_out_opc_reg(s
, OPC_OR
, ret
, TCG_REG_AT
, TCG_REG_T0
);
702 tcg_out_setcond(s
, TCG_COND_LT
, TCG_REG_AT
, arg2
, arg4
);
706 tcg_out_setcond(s
, TCG_COND_GT
, TCG_REG_AT
, arg2
, arg4
);
710 tcg_out_setcond(s
, TCG_COND_LTU
, TCG_REG_AT
, arg2
, arg4
);
714 tcg_out_setcond(s
, TCG_COND_GTU
, TCG_REG_AT
, arg2
, arg4
);
721 tcg_out_setcond(s
, TCG_COND_EQ
, TCG_REG_T0
, arg2
, arg4
);
726 tcg_out_setcond(s
, TCG_COND_LTU
, ret
, arg1
, arg3
);
730 tcg_out_setcond(s
, TCG_COND_LEU
, ret
, arg1
, arg3
);
734 tcg_out_setcond(s
, TCG_COND_GTU
, ret
, arg1
, arg3
);
738 tcg_out_setcond(s
, TCG_COND_GEU
, ret
, arg1
, arg3
);
744 tcg_out_opc_reg(s
, OPC_AND
, ret
, ret
, TCG_REG_T0
);
745 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
748 #if defined(CONFIG_SOFTMMU)
750 #include "../../softmmu_defs.h"
752 static void *qemu_ld_helpers
[4] = {
759 static void *qemu_st_helpers
[4] = {
767 static void tcg_out_qemu_ld(TCGContext
*s
, const TCGArg
*args
,
770 int addr_regl
, addr_reg1
, addr_meml
;
771 int data_regl
, data_regh
, data_reg1
, data_reg2
;
772 int mem_index
, s_bits
;
773 #if defined(CONFIG_SOFTMMU)
774 void *label1_ptr
, *label2_ptr
;
777 #if TARGET_LONG_BITS == 64
778 # if defined(CONFIG_SOFTMMU)
781 int addr_regh
, addr_reg2
, addr_memh
;
789 #if TARGET_LONG_BITS == 64
796 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
797 data_reg1
= data_regh
;
798 data_reg2
= data_regl
;
800 data_reg1
= data_regl
;
801 data_reg2
= data_regh
;
804 data_reg1
= data_regl
;
807 #if TARGET_LONG_BITS == 64
808 # if defined(TCG_TARGET_WORDS_BIGENDIAN)
809 addr_reg1
= addr_regh
;
810 addr_reg2
= addr_regl
;
814 addr_reg1
= addr_regl
;
815 addr_reg2
= addr_regh
;
820 addr_reg1
= addr_regl
;
824 #if defined(CONFIG_SOFTMMU)
825 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_A0
, addr_regl
, TARGET_PAGE_BITS
- CPU_TLB_ENTRY_BITS
);
826 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_A0
, TCG_REG_A0
, (CPU_TLB_SIZE
- 1) << CPU_TLB_ENTRY_BITS
);
827 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_A0
, TCG_REG_A0
, TCG_AREG0
);
828 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_AT
, TCG_REG_A0
,
829 offsetof(CPUState
, tlb_table
[mem_index
][0].addr_read
) + addr_meml
);
830 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_T0
, TARGET_PAGE_MASK
| ((1 << s_bits
) - 1));
831 tcg_out_opc_reg(s
, OPC_AND
, TCG_REG_T0
, TCG_REG_T0
, addr_regl
);
833 # if TARGET_LONG_BITS == 64
834 label3_ptr
= s
->code_ptr
;
835 tcg_out_opc_br(s
, OPC_BNE
, TCG_REG_T0
, TCG_REG_AT
);
838 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_AT
, TCG_REG_A0
,
839 offsetof(CPUState
, tlb_table
[mem_index
][0].addr_read
) + addr_memh
);
841 label1_ptr
= s
->code_ptr
;
842 tcg_out_opc_br(s
, OPC_BEQ
, addr_regh
, TCG_REG_AT
);
845 reloc_pc16(label3_ptr
, (tcg_target_long
) s
->code_ptr
);
847 label1_ptr
= s
->code_ptr
;
848 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_T0
, TCG_REG_AT
);
853 sp_args
= TCG_REG_A0
;
854 tcg_out_mov(s
, TCG_TYPE_I32
, sp_args
++, addr_reg1
);
855 # if TARGET_LONG_BITS == 64
856 tcg_out_mov(s
, TCG_TYPE_I32
, sp_args
++, addr_reg2
);
858 tcg_out_movi(s
, TCG_TYPE_I32
, sp_args
++, mem_index
);
859 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_T9
, (tcg_target_long
)qemu_ld_helpers
[s_bits
]);
860 tcg_out_opc_reg(s
, OPC_JALR
, TCG_REG_RA
, TCG_REG_T9
, 0);
865 tcg_out_opc_imm(s
, OPC_ANDI
, data_reg1
, TCG_REG_V0
, 0xff);
868 tcg_out_ext8s(s
, data_reg1
, TCG_REG_V0
);
871 tcg_out_opc_imm(s
, OPC_ANDI
, data_reg1
, TCG_REG_V0
, 0xffff);
874 tcg_out_ext16s(s
, data_reg1
, TCG_REG_V0
);
877 tcg_out_mov(s
, TCG_TYPE_I32
, data_reg1
, TCG_REG_V0
);
880 tcg_out_mov(s
, TCG_TYPE_I32
, data_reg2
, TCG_REG_V1
);
881 tcg_out_mov(s
, TCG_TYPE_I32
, data_reg1
, TCG_REG_V0
);
887 label2_ptr
= s
->code_ptr
;
888 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_ZERO
, TCG_REG_ZERO
);
891 /* label1: fast path */
892 reloc_pc16(label1_ptr
, (tcg_target_long
) s
->code_ptr
);
894 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_A0
, TCG_REG_A0
,
895 offsetof(CPUState
, tlb_table
[mem_index
][0].addend
));
896 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_V0
, TCG_REG_A0
, addr_regl
);
898 if (GUEST_BASE
== (int16_t)GUEST_BASE
) {
899 tcg_out_opc_imm(s
, OPC_ADDIU
, TCG_REG_V0
, addr_regl
, GUEST_BASE
);
901 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_V0
, GUEST_BASE
);
902 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_V0
, TCG_REG_V0
, addr_regl
);
908 tcg_out_opc_imm(s
, OPC_LBU
, data_reg1
, TCG_REG_V0
, 0);
911 tcg_out_opc_imm(s
, OPC_LB
, data_reg1
, TCG_REG_V0
, 0);
914 if (TCG_NEED_BSWAP
) {
915 tcg_out_opc_imm(s
, OPC_LHU
, TCG_REG_T0
, TCG_REG_V0
, 0);
916 tcg_out_bswap16(s
, data_reg1
, TCG_REG_T0
);
918 tcg_out_opc_imm(s
, OPC_LHU
, data_reg1
, TCG_REG_V0
, 0);
922 if (TCG_NEED_BSWAP
) {
923 tcg_out_opc_imm(s
, OPC_LHU
, TCG_REG_T0
, TCG_REG_V0
, 0);
924 tcg_out_bswap16s(s
, data_reg1
, TCG_REG_T0
);
926 tcg_out_opc_imm(s
, OPC_LH
, data_reg1
, TCG_REG_V0
, 0);
930 if (TCG_NEED_BSWAP
) {
931 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_T0
, TCG_REG_V0
, 0);
932 tcg_out_bswap32(s
, data_reg1
, TCG_REG_T0
);
934 tcg_out_opc_imm(s
, OPC_LW
, data_reg1
, TCG_REG_V0
, 0);
938 if (TCG_NEED_BSWAP
) {
939 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_T0
, TCG_REG_V0
, 4);
940 tcg_out_bswap32(s
, data_reg1
, TCG_REG_T0
);
941 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_T0
, TCG_REG_V0
, 0);
942 tcg_out_bswap32(s
, data_reg2
, TCG_REG_T0
);
944 tcg_out_opc_imm(s
, OPC_LW
, data_reg1
, TCG_REG_V0
, 0);
945 tcg_out_opc_imm(s
, OPC_LW
, data_reg2
, TCG_REG_V0
, 4);
952 #if defined(CONFIG_SOFTMMU)
953 reloc_pc16(label2_ptr
, (tcg_target_long
) s
->code_ptr
);
957 static void tcg_out_qemu_st(TCGContext
*s
, const TCGArg
*args
,
960 int addr_regl
, addr_reg1
, addr_meml
;
961 int data_regl
, data_regh
, data_reg1
, data_reg2
;
962 int mem_index
, s_bits
;
963 #if defined(CONFIG_SOFTMMU)
964 uint8_t *label1_ptr
, *label2_ptr
;
967 #if TARGET_LONG_BITS == 64
968 # if defined(CONFIG_SOFTMMU)
971 int addr_regh
, addr_reg2
, addr_memh
;
977 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
978 data_reg1
= data_regh
;
979 data_reg2
= data_regl
;
981 data_reg1
= data_regl
;
982 data_reg2
= data_regh
;
985 data_reg1
= data_regl
;
990 #if TARGET_LONG_BITS == 64
992 # if defined(TCG_TARGET_WORDS_BIGENDIAN)
993 addr_reg1
= addr_regh
;
994 addr_reg2
= addr_regl
;
998 addr_reg1
= addr_regl
;
999 addr_reg2
= addr_regh
;
1004 addr_reg1
= addr_regl
;
1010 #if defined(CONFIG_SOFTMMU)
1011 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_A0
, addr_regl
, TARGET_PAGE_BITS
- CPU_TLB_ENTRY_BITS
);
1012 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_A0
, TCG_REG_A0
, (CPU_TLB_SIZE
- 1) << CPU_TLB_ENTRY_BITS
);
1013 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_A0
, TCG_REG_A0
, TCG_AREG0
);
1014 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_AT
, TCG_REG_A0
,
1015 offsetof(CPUState
, tlb_table
[mem_index
][0].addr_write
) + addr_meml
);
1016 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_T0
, TARGET_PAGE_MASK
| ((1 << s_bits
) - 1));
1017 tcg_out_opc_reg(s
, OPC_AND
, TCG_REG_T0
, TCG_REG_T0
, addr_regl
);
1019 # if TARGET_LONG_BITS == 64
1020 label3_ptr
= s
->code_ptr
;
1021 tcg_out_opc_br(s
, OPC_BNE
, TCG_REG_T0
, TCG_REG_AT
);
1024 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_AT
, TCG_REG_A0
,
1025 offsetof(CPUState
, tlb_table
[mem_index
][0].addr_write
) + addr_memh
);
1027 label1_ptr
= s
->code_ptr
;
1028 tcg_out_opc_br(s
, OPC_BEQ
, addr_regh
, TCG_REG_AT
);
1031 reloc_pc16(label3_ptr
, (tcg_target_long
) s
->code_ptr
);
1033 label1_ptr
= s
->code_ptr
;
1034 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_T0
, TCG_REG_AT
);
1039 sp_args
= TCG_REG_A0
;
1040 tcg_out_mov(s
, TCG_TYPE_I32
, sp_args
++, addr_reg1
);
1041 # if TARGET_LONG_BITS == 64
1042 tcg_out_mov(s
, TCG_TYPE_I32
, sp_args
++, addr_reg2
);
1046 tcg_out_opc_imm(s
, OPC_ANDI
, sp_args
++, data_reg1
, 0xff);
1049 tcg_out_opc_imm(s
, OPC_ANDI
, sp_args
++, data_reg1
, 0xffff);
1052 tcg_out_mov(s
, TCG_TYPE_I32
, sp_args
++, data_reg1
);
1055 sp_args
= (sp_args
+ 1) & ~1;
1056 tcg_out_mov(s
, TCG_TYPE_I32
, sp_args
++, data_reg1
);
1057 tcg_out_mov(s
, TCG_TYPE_I32
, sp_args
++, data_reg2
);
1062 if (sp_args
> TCG_REG_A3
) {
1063 /* Push mem_index on the stack */
1064 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_AT
, mem_index
);
1065 tcg_out_st(s
, TCG_TYPE_I32
, TCG_REG_AT
, TCG_REG_SP
, 16);
1067 tcg_out_movi(s
, TCG_TYPE_I32
, sp_args
, mem_index
);
1070 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_T9
, (tcg_target_long
)qemu_st_helpers
[s_bits
]);
1071 tcg_out_opc_reg(s
, OPC_JALR
, TCG_REG_RA
, TCG_REG_T9
, 0);
1074 label2_ptr
= s
->code_ptr
;
1075 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_ZERO
, TCG_REG_ZERO
);
1078 /* label1: fast path */
1079 reloc_pc16(label1_ptr
, (tcg_target_long
) s
->code_ptr
);
1081 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_A0
, TCG_REG_A0
,
1082 offsetof(CPUState
, tlb_table
[mem_index
][0].addend
));
1083 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_A0
, TCG_REG_A0
, addr_regl
);
1085 if (GUEST_BASE
== (int16_t)GUEST_BASE
) {
1086 tcg_out_opc_imm(s
, OPC_ADDIU
, TCG_REG_A0
, addr_regl
, GUEST_BASE
);
1088 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_A0
, GUEST_BASE
);
1089 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_A0
, TCG_REG_A0
, addr_regl
);
1096 tcg_out_opc_imm(s
, OPC_SB
, data_reg1
, TCG_REG_A0
, 0);
1099 if (TCG_NEED_BSWAP
) {
1100 tcg_out_bswap16(s
, TCG_REG_T0
, data_reg1
);
1101 tcg_out_opc_imm(s
, OPC_SH
, TCG_REG_T0
, TCG_REG_A0
, 0);
1103 tcg_out_opc_imm(s
, OPC_SH
, data_reg1
, TCG_REG_A0
, 0);
1107 if (TCG_NEED_BSWAP
) {
1108 tcg_out_bswap32(s
, TCG_REG_T0
, data_reg1
);
1109 tcg_out_opc_imm(s
, OPC_SW
, TCG_REG_T0
, TCG_REG_A0
, 0);
1111 tcg_out_opc_imm(s
, OPC_SW
, data_reg1
, TCG_REG_A0
, 0);
1115 if (TCG_NEED_BSWAP
) {
1116 tcg_out_bswap32(s
, TCG_REG_T0
, data_reg2
);
1117 tcg_out_opc_imm(s
, OPC_SW
, TCG_REG_T0
, TCG_REG_A0
, 0);
1118 tcg_out_bswap32(s
, TCG_REG_T0
, data_reg1
);
1119 tcg_out_opc_imm(s
, OPC_SW
, TCG_REG_T0
, TCG_REG_A0
, 4);
1121 tcg_out_opc_imm(s
, OPC_SW
, data_reg1
, TCG_REG_A0
, 0);
1122 tcg_out_opc_imm(s
, OPC_SW
, data_reg2
, TCG_REG_A0
, 4);
1129 #if defined(CONFIG_SOFTMMU)
1130 reloc_pc16(label2_ptr
, (tcg_target_long
) s
->code_ptr
);
1134 static inline void tcg_out_op(TCGContext
*s
, TCGOpcode opc
,
1135 const TCGArg
*args
, const int *const_args
)
1138 case INDEX_op_exit_tb
:
1139 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_V0
, args
[0]);
1140 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_AT
, (tcg_target_long
)tb_ret_addr
);
1141 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_AT
, 0);
1144 case INDEX_op_goto_tb
:
1145 if (s
->tb_jmp_offset
) {
1146 /* direct jump method */
1149 /* indirect jump method */
1150 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_AT
, (tcg_target_long
)(s
->tb_next
+ args
[0]));
1151 tcg_out_ld(s
, TCG_TYPE_PTR
, TCG_REG_AT
, TCG_REG_AT
, 0);
1152 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_AT
, 0);
1155 s
->tb_next_offset
[args
[0]] = s
->code_ptr
- s
->code_buf
;
1158 tcg_out_opc_reg(s
, OPC_JALR
, TCG_REG_RA
, args
[0], 0);
1162 tcg_out_opc_reg(s
, OPC_JR
, 0, args
[0], 0);
1166 tcg_out_brcond(s
, TCG_COND_EQ
, TCG_REG_ZERO
, TCG_REG_ZERO
, args
[0]);
1169 case INDEX_op_mov_i32
:
1170 tcg_out_mov(s
, TCG_TYPE_I32
, args
[0], args
[1]);
1172 case INDEX_op_movi_i32
:
1173 tcg_out_movi(s
, TCG_TYPE_I32
, args
[0], args
[1]);
1176 case INDEX_op_ld8u_i32
:
1177 tcg_out_ldst(s
, OPC_LBU
, args
[0], args
[1], args
[2]);
1179 case INDEX_op_ld8s_i32
:
1180 tcg_out_ldst(s
, OPC_LB
, args
[0], args
[1], args
[2]);
1182 case INDEX_op_ld16u_i32
:
1183 tcg_out_ldst(s
, OPC_LHU
, args
[0], args
[1], args
[2]);
1185 case INDEX_op_ld16s_i32
:
1186 tcg_out_ldst(s
, OPC_LH
, args
[0], args
[1], args
[2]);
1188 case INDEX_op_ld_i32
:
1189 tcg_out_ldst(s
, OPC_LW
, args
[0], args
[1], args
[2]);
1191 case INDEX_op_st8_i32
:
1192 tcg_out_ldst(s
, OPC_SB
, args
[0], args
[1], args
[2]);
1194 case INDEX_op_st16_i32
:
1195 tcg_out_ldst(s
, OPC_SH
, args
[0], args
[1], args
[2]);
1197 case INDEX_op_st_i32
:
1198 tcg_out_ldst(s
, OPC_SW
, args
[0], args
[1], args
[2]);
1201 case INDEX_op_add_i32
:
1202 if (const_args
[2]) {
1203 tcg_out_opc_imm(s
, OPC_ADDIU
, args
[0], args
[1], args
[2]);
1205 tcg_out_opc_reg(s
, OPC_ADDU
, args
[0], args
[1], args
[2]);
1208 case INDEX_op_add2_i32
:
1209 if (const_args
[4]) {
1210 tcg_out_opc_imm(s
, OPC_ADDIU
, TCG_REG_AT
, args
[2], args
[4]);
1212 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_AT
, args
[2], args
[4]);
1214 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_T0
, TCG_REG_AT
, args
[2]);
1215 if (const_args
[5]) {
1216 tcg_out_opc_imm(s
, OPC_ADDIU
, args
[1], args
[3], args
[5]);
1218 tcg_out_opc_reg(s
, OPC_ADDU
, args
[1], args
[3], args
[5]);
1220 tcg_out_opc_reg(s
, OPC_ADDU
, args
[1], args
[1], TCG_REG_T0
);
1221 tcg_out_mov(s
, TCG_TYPE_I32
, args
[0], TCG_REG_AT
);
1223 case INDEX_op_sub_i32
:
1224 if (const_args
[2]) {
1225 tcg_out_opc_imm(s
, OPC_ADDIU
, args
[0], args
[1], -args
[2]);
1227 tcg_out_opc_reg(s
, OPC_SUBU
, args
[0], args
[1], args
[2]);
1230 case INDEX_op_sub2_i32
:
1231 if (const_args
[4]) {
1232 tcg_out_opc_imm(s
, OPC_ADDIU
, TCG_REG_AT
, args
[2], -args
[4]);
1234 tcg_out_opc_reg(s
, OPC_SUBU
, TCG_REG_AT
, args
[2], args
[4]);
1236 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_T0
, args
[2], TCG_REG_AT
);
1237 if (const_args
[5]) {
1238 tcg_out_opc_imm(s
, OPC_ADDIU
, args
[1], args
[3], -args
[5]);
1240 tcg_out_opc_reg(s
, OPC_SUBU
, args
[1], args
[3], args
[5]);
1242 tcg_out_opc_reg(s
, OPC_SUBU
, args
[1], args
[1], TCG_REG_T0
);
1243 tcg_out_mov(s
, TCG_TYPE_I32
, args
[0], TCG_REG_AT
);
1245 case INDEX_op_mul_i32
:
1246 tcg_out_opc_reg(s
, OPC_MULT
, 0, args
[1], args
[2]);
1247 tcg_out_opc_reg(s
, OPC_MFLO
, args
[0], 0, 0);
1249 case INDEX_op_mulu2_i32
:
1250 tcg_out_opc_reg(s
, OPC_MULTU
, 0, args
[2], args
[3]);
1251 tcg_out_opc_reg(s
, OPC_MFLO
, args
[0], 0, 0);
1252 tcg_out_opc_reg(s
, OPC_MFHI
, args
[1], 0, 0);
1254 case INDEX_op_div_i32
:
1255 tcg_out_opc_reg(s
, OPC_DIV
, 0, args
[1], args
[2]);
1256 tcg_out_opc_reg(s
, OPC_MFLO
, args
[0], 0, 0);
1258 case INDEX_op_divu_i32
:
1259 tcg_out_opc_reg(s
, OPC_DIVU
, 0, args
[1], args
[2]);
1260 tcg_out_opc_reg(s
, OPC_MFLO
, args
[0], 0, 0);
1262 case INDEX_op_rem_i32
:
1263 tcg_out_opc_reg(s
, OPC_DIV
, 0, args
[1], args
[2]);
1264 tcg_out_opc_reg(s
, OPC_MFHI
, args
[0], 0, 0);
1266 case INDEX_op_remu_i32
:
1267 tcg_out_opc_reg(s
, OPC_DIVU
, 0, args
[1], args
[2]);
1268 tcg_out_opc_reg(s
, OPC_MFHI
, args
[0], 0, 0);
1271 case INDEX_op_and_i32
:
1272 if (const_args
[2]) {
1273 tcg_out_opc_imm(s
, OPC_ANDI
, args
[0], args
[1], args
[2]);
1275 tcg_out_opc_reg(s
, OPC_AND
, args
[0], args
[1], args
[2]);
1278 case INDEX_op_or_i32
:
1279 if (const_args
[2]) {
1280 tcg_out_opc_imm(s
, OPC_ORI
, args
[0], args
[1], args
[2]);
1282 tcg_out_opc_reg(s
, OPC_OR
, args
[0], args
[1], args
[2]);
1285 case INDEX_op_nor_i32
:
1286 tcg_out_opc_reg(s
, OPC_NOR
, args
[0], args
[1], args
[2]);
1288 case INDEX_op_not_i32
:
1289 tcg_out_opc_reg(s
, OPC_NOR
, args
[0], TCG_REG_ZERO
, args
[1]);
1291 case INDEX_op_xor_i32
:
1292 if (const_args
[2]) {
1293 tcg_out_opc_imm(s
, OPC_XORI
, args
[0], args
[1], args
[2]);
1295 tcg_out_opc_reg(s
, OPC_XOR
, args
[0], args
[1], args
[2]);
1299 case INDEX_op_sar_i32
:
1300 if (const_args
[2]) {
1301 tcg_out_opc_sa(s
, OPC_SRA
, args
[0], args
[1], args
[2]);
1303 tcg_out_opc_reg(s
, OPC_SRAV
, args
[0], args
[2], args
[1]);
1306 case INDEX_op_shl_i32
:
1307 if (const_args
[2]) {
1308 tcg_out_opc_sa(s
, OPC_SLL
, args
[0], args
[1], args
[2]);
1310 tcg_out_opc_reg(s
, OPC_SLLV
, args
[0], args
[2], args
[1]);
1313 case INDEX_op_shr_i32
:
1314 if (const_args
[2]) {
1315 tcg_out_opc_sa(s
, OPC_SRL
, args
[0], args
[1], args
[2]);
1317 tcg_out_opc_reg(s
, OPC_SRLV
, args
[0], args
[2], args
[1]);
1321 case INDEX_op_ext8s_i32
:
1322 tcg_out_ext8s(s
, args
[0], args
[1]);
1324 case INDEX_op_ext16s_i32
:
1325 tcg_out_ext16s(s
, args
[0], args
[1]);
1328 case INDEX_op_brcond_i32
:
1329 tcg_out_brcond(s
, args
[2], args
[0], args
[1], args
[3]);
1331 case INDEX_op_brcond2_i32
:
1332 tcg_out_brcond2(s
, args
[4], args
[0], args
[1], args
[2], args
[3], args
[5]);
1335 case INDEX_op_setcond_i32
:
1336 tcg_out_setcond(s
, args
[3], args
[0], args
[1], args
[2]);
1338 case INDEX_op_setcond2_i32
:
1339 tcg_out_setcond2(s
, args
[5], args
[0], args
[1], args
[2], args
[3], args
[4]);
1342 case INDEX_op_qemu_ld8u
:
1343 tcg_out_qemu_ld(s
, args
, 0);
1345 case INDEX_op_qemu_ld8s
:
1346 tcg_out_qemu_ld(s
, args
, 0 | 4);
1348 case INDEX_op_qemu_ld16u
:
1349 tcg_out_qemu_ld(s
, args
, 1);
1351 case INDEX_op_qemu_ld16s
:
1352 tcg_out_qemu_ld(s
, args
, 1 | 4);
1354 case INDEX_op_qemu_ld32
:
1355 tcg_out_qemu_ld(s
, args
, 2);
1357 case INDEX_op_qemu_ld64
:
1358 tcg_out_qemu_ld(s
, args
, 3);
1360 case INDEX_op_qemu_st8
:
1361 tcg_out_qemu_st(s
, args
, 0);
1363 case INDEX_op_qemu_st16
:
1364 tcg_out_qemu_st(s
, args
, 1);
1366 case INDEX_op_qemu_st32
:
1367 tcg_out_qemu_st(s
, args
, 2);
1369 case INDEX_op_qemu_st64
:
1370 tcg_out_qemu_st(s
, args
, 3);
1378 static const TCGTargetOpDef mips_op_defs
[] = {
1379 { INDEX_op_exit_tb
, { } },
1380 { INDEX_op_goto_tb
, { } },
1381 { INDEX_op_call
, { "C" } },
1382 { INDEX_op_jmp
, { "r" } },
1383 { INDEX_op_br
, { } },
1385 { INDEX_op_mov_i32
, { "r", "r" } },
1386 { INDEX_op_movi_i32
, { "r" } },
1387 { INDEX_op_ld8u_i32
, { "r", "r" } },
1388 { INDEX_op_ld8s_i32
, { "r", "r" } },
1389 { INDEX_op_ld16u_i32
, { "r", "r" } },
1390 { INDEX_op_ld16s_i32
, { "r", "r" } },
1391 { INDEX_op_ld_i32
, { "r", "r" } },
1392 { INDEX_op_st8_i32
, { "rZ", "r" } },
1393 { INDEX_op_st16_i32
, { "rZ", "r" } },
1394 { INDEX_op_st_i32
, { "rZ", "r" } },
1396 { INDEX_op_add_i32
, { "r", "rZ", "rJZ" } },
1397 { INDEX_op_mul_i32
, { "r", "rZ", "rZ" } },
1398 { INDEX_op_mulu2_i32
, { "r", "r", "rZ", "rZ" } },
1399 { INDEX_op_div_i32
, { "r", "rZ", "rZ" } },
1400 { INDEX_op_divu_i32
, { "r", "rZ", "rZ" } },
1401 { INDEX_op_rem_i32
, { "r", "rZ", "rZ" } },
1402 { INDEX_op_remu_i32
, { "r", "rZ", "rZ" } },
1403 { INDEX_op_sub_i32
, { "r", "rZ", "rJZ" } },
1405 { INDEX_op_and_i32
, { "r", "rZ", "rIZ" } },
1406 { INDEX_op_nor_i32
, { "r", "rZ", "rZ" } },
1407 { INDEX_op_not_i32
, { "r", "rZ" } },
1408 { INDEX_op_or_i32
, { "r", "rZ", "rIZ" } },
1409 { INDEX_op_xor_i32
, { "r", "rZ", "rIZ" } },
1411 { INDEX_op_shl_i32
, { "r", "rZ", "riZ" } },
1412 { INDEX_op_shr_i32
, { "r", "rZ", "riZ" } },
1413 { INDEX_op_sar_i32
, { "r", "rZ", "riZ" } },
1415 { INDEX_op_ext8s_i32
, { "r", "rZ" } },
1416 { INDEX_op_ext16s_i32
, { "r", "rZ" } },
1418 { INDEX_op_brcond_i32
, { "rZ", "rZ" } },
1419 { INDEX_op_setcond_i32
, { "r", "rZ", "rZ" } },
1420 { INDEX_op_setcond2_i32
, { "r", "rZ", "rZ", "rZ", "rZ" } },
1422 { INDEX_op_add2_i32
, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1423 { INDEX_op_sub2_i32
, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1424 { INDEX_op_brcond2_i32
, { "rZ", "rZ", "rZ", "rZ" } },
1426 #if TARGET_LONG_BITS == 32
1427 { INDEX_op_qemu_ld8u
, { "L", "lZ" } },
1428 { INDEX_op_qemu_ld8s
, { "L", "lZ" } },
1429 { INDEX_op_qemu_ld16u
, { "L", "lZ" } },
1430 { INDEX_op_qemu_ld16s
, { "L", "lZ" } },
1431 { INDEX_op_qemu_ld32
, { "L", "lZ" } },
1432 { INDEX_op_qemu_ld64
, { "L", "L", "lZ" } },
1434 { INDEX_op_qemu_st8
, { "SZ", "SZ" } },
1435 { INDEX_op_qemu_st16
, { "SZ", "SZ" } },
1436 { INDEX_op_qemu_st32
, { "SZ", "SZ" } },
1437 { INDEX_op_qemu_st64
, { "SZ", "SZ", "SZ" } },
1439 { INDEX_op_qemu_ld8u
, { "L", "lZ", "lZ" } },
1440 { INDEX_op_qemu_ld8s
, { "L", "lZ", "lZ" } },
1441 { INDEX_op_qemu_ld16u
, { "L", "lZ", "lZ" } },
1442 { INDEX_op_qemu_ld16s
, { "L", "lZ", "lZ" } },
1443 { INDEX_op_qemu_ld32
, { "L", "lZ", "lZ" } },
1444 { INDEX_op_qemu_ld64
, { "L", "L", "lZ", "lZ" } },
1446 { INDEX_op_qemu_st8
, { "SZ", "SZ", "SZ" } },
1447 { INDEX_op_qemu_st16
, { "SZ", "SZ", "SZ" } },
1448 { INDEX_op_qemu_st32
, { "SZ", "SZ", "SZ" } },
1449 { INDEX_op_qemu_st64
, { "SZ", "SZ", "SZ", "SZ" } },
1454 static int tcg_target_callee_save_regs
[] = {
1455 #if 0 /* used for the global env (TCG_AREG0), so no need to save */
1467 TCG_REG_RA
, /* should be last for ABI compliance */
1470 /* Generate global QEMU prologue and epilogue code */
1471 static void tcg_target_qemu_prologue(TCGContext
*s
)
1475 /* reserve some stack space */
1476 frame_size
= ARRAY_SIZE(tcg_target_callee_save_regs
) * 4
1477 + TCG_STATIC_CALL_ARGS_SIZE
;
1478 frame_size
= (frame_size
+ TCG_TARGET_STACK_ALIGN
- 1) &
1479 ~(TCG_TARGET_STACK_ALIGN
- 1);
1482 tcg_out_addi(s
, TCG_REG_SP
, -frame_size
);
1483 for(i
= 0 ; i
< ARRAY_SIZE(tcg_target_callee_save_regs
) ; i
++) {
1484 tcg_out_st(s
, TCG_TYPE_I32
, tcg_target_callee_save_regs
[i
],
1485 TCG_REG_SP
, TCG_STATIC_CALL_ARGS_SIZE
+ i
* 4);
1488 /* Call generated code */
1489 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_A0
, 0);
1491 tb_ret_addr
= s
->code_ptr
;
1494 for(i
= 0 ; i
< ARRAY_SIZE(tcg_target_callee_save_regs
) ; i
++) {
1495 tcg_out_ld(s
, TCG_TYPE_I32
, tcg_target_callee_save_regs
[i
],
1496 TCG_REG_SP
, TCG_STATIC_CALL_ARGS_SIZE
+ i
* 4);
1499 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_RA
, 0);
1500 tcg_out_addi(s
, TCG_REG_SP
, frame_size
);
1503 static void tcg_target_init(TCGContext
*s
)
1505 tcg_regset_set(tcg_target_available_regs
[TCG_TYPE_I32
], 0xffffffff);
1506 tcg_regset_set(tcg_target_call_clobber_regs
,
1523 tcg_regset_clear(s
->reserved_regs
);
1524 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_ZERO
); /* zero register */
1525 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_K0
); /* kernel use only */
1526 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_K1
); /* kernel use only */
1527 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_AT
); /* internal use */
1528 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_T0
); /* internal use */
1529 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_RA
); /* return address */
1530 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_SP
); /* stack pointer */
1532 tcg_add_target_add_op_defs(mips_op_defs
);