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 need to keep the offset unchanged for retranslation */
355 uint16_t offset
= (uint16_t)(*(uint32_t *) &s
->code_ptr
);
357 tcg_out_opc_imm(s
, opc
, rt
, rs
, offset
);
363 static inline void tcg_out_opc_sa(TCGContext
*s
, int opc
, int rd
, int rt
, int sa
)
368 inst
|= (rt
& 0x1F) << 16;
369 inst
|= (rd
& 0x1F) << 11;
370 inst
|= (sa
& 0x1F) << 6;
375 static inline void tcg_out_nop(TCGContext
*s
)
380 static inline void tcg_out_mov(TCGContext
*s
, TCGType type
, int ret
, int arg
)
382 tcg_out_opc_reg(s
, OPC_ADDU
, ret
, arg
, TCG_REG_ZERO
);
385 static inline void tcg_out_movi(TCGContext
*s
, TCGType type
,
386 int reg
, int32_t arg
)
388 if (arg
== (int16_t)arg
) {
389 tcg_out_opc_imm(s
, OPC_ADDIU
, reg
, TCG_REG_ZERO
, arg
);
390 } else if (arg
== (uint16_t)arg
) {
391 tcg_out_opc_imm(s
, OPC_ORI
, reg
, TCG_REG_ZERO
, arg
);
393 tcg_out_opc_imm(s
, OPC_LUI
, reg
, 0, arg
>> 16);
394 tcg_out_opc_imm(s
, OPC_ORI
, reg
, reg
, arg
& 0xffff);
398 static inline void tcg_out_bswap16(TCGContext
*s
, int ret
, int arg
)
400 /* ret and arg can't be register at */
401 if (ret
== TCG_REG_AT
|| arg
== TCG_REG_AT
) {
405 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_AT
, arg
, 8);
406 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_AT
, TCG_REG_AT
, 0x00ff);
408 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 8);
409 tcg_out_opc_imm(s
, OPC_ANDI
, ret
, ret
, 0xff00);
410 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
413 static inline void tcg_out_bswap16s(TCGContext
*s
, int ret
, int arg
)
415 /* ret and arg can't be register at */
416 if (ret
== TCG_REG_AT
|| arg
== TCG_REG_AT
) {
420 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_AT
, arg
, 8);
421 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_AT
, TCG_REG_AT
, 0xff);
423 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 24);
424 tcg_out_opc_sa(s
, OPC_SRA
, ret
, ret
, 16);
425 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
428 static inline void tcg_out_bswap32(TCGContext
*s
, int ret
, int arg
)
430 /* ret and arg must be different and can't be register at */
431 if (ret
== arg
|| ret
== TCG_REG_AT
|| arg
== TCG_REG_AT
) {
435 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 24);
437 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_AT
, arg
, 24);
438 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
440 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_AT
, arg
, 0xff00);
441 tcg_out_opc_sa(s
, OPC_SLL
, TCG_REG_AT
, TCG_REG_AT
, 8);
442 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
444 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_AT
, arg
, 8);
445 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_AT
, TCG_REG_AT
, 0xff00);
446 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
449 static inline void tcg_out_ext8s(TCGContext
*s
, int ret
, int arg
)
451 #ifdef _MIPS_ARCH_MIPS32R2
452 tcg_out_opc_reg(s
, OPC_SEB
, ret
, 0, arg
);
454 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 24);
455 tcg_out_opc_sa(s
, OPC_SRA
, ret
, ret
, 24);
459 static inline void tcg_out_ext16s(TCGContext
*s
, int ret
, int arg
)
461 #ifdef _MIPS_ARCH_MIPS32R2
462 tcg_out_opc_reg(s
, OPC_SEH
, ret
, 0, arg
);
464 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 16);
465 tcg_out_opc_sa(s
, OPC_SRA
, ret
, ret
, 16);
469 static inline void tcg_out_ldst(TCGContext
*s
, int opc
, int arg
,
470 int arg1
, tcg_target_long arg2
)
472 if (arg2
== (int16_t) arg2
) {
473 tcg_out_opc_imm(s
, opc
, arg
, arg1
, arg2
);
475 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_AT
, arg2
);
476 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_AT
, TCG_REG_AT
, arg1
);
477 tcg_out_opc_imm(s
, opc
, arg
, TCG_REG_AT
, 0);
481 static inline void tcg_out_ld(TCGContext
*s
, TCGType type
, int arg
,
482 int arg1
, tcg_target_long arg2
)
484 tcg_out_ldst(s
, OPC_LW
, arg
, arg1
, arg2
);
487 static inline void tcg_out_st(TCGContext
*s
, TCGType type
, int arg
,
488 int arg1
, tcg_target_long arg2
)
490 tcg_out_ldst(s
, OPC_SW
, arg
, arg1
, arg2
);
493 static inline void tcg_out_addi(TCGContext
*s
, int reg
, tcg_target_long val
)
495 if (val
== (int16_t)val
) {
496 tcg_out_opc_imm(s
, OPC_ADDIU
, reg
, reg
, val
);
498 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_AT
, val
);
499 tcg_out_opc_reg(s
, OPC_ADDU
, reg
, reg
, TCG_REG_AT
);
503 static void tcg_out_brcond(TCGContext
*s
, TCGCond cond
, int arg1
,
504 int arg2
, int label_index
)
506 TCGLabel
*l
= &s
->labels
[label_index
];
510 tcg_out_opc_br(s
, OPC_BEQ
, arg1
, arg2
);
513 tcg_out_opc_br(s
, OPC_BNE
, arg1
, arg2
);
516 tcg_out_opc_reg(s
, OPC_SLT
, TCG_REG_AT
, arg1
, arg2
);
517 tcg_out_opc_br(s
, OPC_BNE
, TCG_REG_AT
, TCG_REG_ZERO
);
520 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_AT
, arg1
, arg2
);
521 tcg_out_opc_br(s
, OPC_BNE
, TCG_REG_AT
, TCG_REG_ZERO
);
524 tcg_out_opc_reg(s
, OPC_SLT
, TCG_REG_AT
, arg1
, arg2
);
525 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_AT
, TCG_REG_ZERO
);
528 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_AT
, arg1
, arg2
);
529 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_AT
, TCG_REG_ZERO
);
532 tcg_out_opc_reg(s
, OPC_SLT
, TCG_REG_AT
, arg2
, arg1
);
533 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_AT
, TCG_REG_ZERO
);
536 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_AT
, arg2
, arg1
);
537 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_AT
, TCG_REG_ZERO
);
540 tcg_out_opc_reg(s
, OPC_SLT
, TCG_REG_AT
, arg2
, arg1
);
541 tcg_out_opc_br(s
, OPC_BNE
, TCG_REG_AT
, TCG_REG_ZERO
);
544 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_AT
, arg2
, arg1
);
545 tcg_out_opc_br(s
, OPC_BNE
, TCG_REG_AT
, TCG_REG_ZERO
);
552 reloc_pc16(s
->code_ptr
- 4, l
->u
.value
);
554 tcg_out_reloc(s
, s
->code_ptr
- 4, R_MIPS_PC16
, label_index
, 0);
559 /* XXX: we implement it at the target level to avoid having to
560 handle cross basic blocks temporaries */
561 static void tcg_out_brcond2(TCGContext
*s
, TCGCond cond
, int arg1
,
562 int arg2
, int arg3
, int arg4
, int label_index
)
568 tcg_out_brcond(s
, TCG_COND_NE
, arg2
, arg4
, label_index
);
569 tcg_out_brcond(s
, TCG_COND_NE
, arg1
, arg3
, label_index
);
575 tcg_out_brcond(s
, TCG_COND_LT
, arg2
, arg4
, label_index
);
579 tcg_out_brcond(s
, TCG_COND_GT
, arg2
, arg4
, label_index
);
583 tcg_out_brcond(s
, TCG_COND_LTU
, arg2
, arg4
, label_index
);
587 tcg_out_brcond(s
, TCG_COND_GTU
, arg2
, arg4
, label_index
);
593 label_ptr
= s
->code_ptr
;
594 tcg_out_opc_br(s
, OPC_BNE
, arg2
, arg4
);
599 tcg_out_brcond(s
, TCG_COND_EQ
, arg1
, arg3
, label_index
);
603 tcg_out_brcond(s
, TCG_COND_LTU
, arg1
, arg3
, label_index
);
607 tcg_out_brcond(s
, TCG_COND_LEU
, arg1
, arg3
, label_index
);
611 tcg_out_brcond(s
, TCG_COND_GTU
, arg1
, arg3
, label_index
);
615 tcg_out_brcond(s
, TCG_COND_GEU
, arg1
, arg3
, label_index
);
621 reloc_pc16(label_ptr
, (tcg_target_long
) s
->code_ptr
);
624 static void tcg_out_setcond(TCGContext
*s
, TCGCond cond
, int ret
,
630 tcg_out_opc_imm(s
, OPC_SLTIU
, ret
, arg2
, 1);
631 } else if (arg2
== 0) {
632 tcg_out_opc_imm(s
, OPC_SLTIU
, ret
, arg1
, 1);
634 tcg_out_opc_reg(s
, OPC_XOR
, ret
, arg1
, arg2
);
635 tcg_out_opc_imm(s
, OPC_SLTIU
, ret
, ret
, 1);
640 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, TCG_REG_ZERO
, arg2
);
641 } else if (arg2
== 0) {
642 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, TCG_REG_ZERO
, arg1
);
644 tcg_out_opc_reg(s
, OPC_XOR
, ret
, arg1
, arg2
);
645 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, TCG_REG_ZERO
, ret
);
649 tcg_out_opc_reg(s
, OPC_SLT
, ret
, arg1
, arg2
);
652 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, arg1
, arg2
);
655 tcg_out_opc_reg(s
, OPC_SLT
, ret
, arg1
, arg2
);
656 tcg_out_opc_imm(s
, OPC_XORI
, ret
, ret
, 1);
659 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, arg1
, arg2
);
660 tcg_out_opc_imm(s
, OPC_XORI
, ret
, ret
, 1);
663 tcg_out_opc_reg(s
, OPC_SLT
, ret
, arg2
, arg1
);
664 tcg_out_opc_imm(s
, OPC_XORI
, ret
, ret
, 1);
667 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, arg2
, arg1
);
668 tcg_out_opc_imm(s
, OPC_XORI
, ret
, ret
, 1);
671 tcg_out_opc_reg(s
, OPC_SLT
, ret
, arg2
, arg1
);
674 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, arg2
, arg1
);
682 /* XXX: we implement it at the target level to avoid having to
683 handle cross basic blocks temporaries */
684 static void tcg_out_setcond2(TCGContext
*s
, TCGCond cond
, int ret
,
685 int arg1
, int arg2
, int arg3
, int arg4
)
689 tcg_out_setcond(s
, TCG_COND_EQ
, TCG_REG_AT
, arg2
, arg4
);
690 tcg_out_setcond(s
, TCG_COND_EQ
, TCG_REG_T0
, arg1
, arg3
);
691 tcg_out_opc_reg(s
, OPC_AND
, ret
, TCG_REG_AT
, TCG_REG_T0
);
694 tcg_out_setcond(s
, TCG_COND_NE
, TCG_REG_AT
, arg2
, arg4
);
695 tcg_out_setcond(s
, TCG_COND_NE
, TCG_REG_T0
, arg1
, arg3
);
696 tcg_out_opc_reg(s
, OPC_OR
, ret
, TCG_REG_AT
, TCG_REG_T0
);
700 tcg_out_setcond(s
, TCG_COND_LT
, TCG_REG_AT
, arg2
, arg4
);
704 tcg_out_setcond(s
, TCG_COND_GT
, TCG_REG_AT
, arg2
, arg4
);
708 tcg_out_setcond(s
, TCG_COND_LTU
, TCG_REG_AT
, arg2
, arg4
);
712 tcg_out_setcond(s
, TCG_COND_GTU
, TCG_REG_AT
, arg2
, arg4
);
719 tcg_out_setcond(s
, TCG_COND_EQ
, TCG_REG_T0
, arg2
, arg4
);
724 tcg_out_setcond(s
, TCG_COND_LTU
, ret
, arg1
, arg3
);
728 tcg_out_setcond(s
, TCG_COND_LEU
, ret
, arg1
, arg3
);
732 tcg_out_setcond(s
, TCG_COND_GTU
, ret
, arg1
, arg3
);
736 tcg_out_setcond(s
, TCG_COND_GEU
, ret
, arg1
, arg3
);
742 tcg_out_opc_reg(s
, OPC_AND
, ret
, ret
, TCG_REG_T0
);
743 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
746 #if defined(CONFIG_SOFTMMU)
748 #include "../../softmmu_defs.h"
750 static void *qemu_ld_helpers
[4] = {
757 static void *qemu_st_helpers
[4] = {
765 static void tcg_out_qemu_ld(TCGContext
*s
, const TCGArg
*args
,
768 int addr_regl
, addr_reg1
, addr_meml
;
769 int data_regl
, data_regh
, data_reg1
, data_reg2
;
770 int mem_index
, s_bits
;
771 #if defined(CONFIG_SOFTMMU)
772 void *label1_ptr
, *label2_ptr
;
775 #if TARGET_LONG_BITS == 64
776 # if defined(CONFIG_SOFTMMU)
779 int addr_regh
, addr_reg2
, addr_memh
;
787 #if TARGET_LONG_BITS == 64
794 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
795 data_reg1
= data_regh
;
796 data_reg2
= data_regl
;
798 data_reg1
= data_regl
;
799 data_reg2
= data_regh
;
802 data_reg1
= data_regl
;
805 #if TARGET_LONG_BITS == 64
806 # if defined(TCG_TARGET_WORDS_BIGENDIAN)
807 addr_reg1
= addr_regh
;
808 addr_reg2
= addr_regl
;
812 addr_reg1
= addr_regl
;
813 addr_reg2
= addr_regh
;
818 addr_reg1
= addr_regl
;
822 #if defined(CONFIG_SOFTMMU)
823 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_A0
, addr_regl
, TARGET_PAGE_BITS
- CPU_TLB_ENTRY_BITS
);
824 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_A0
, TCG_REG_A0
, (CPU_TLB_SIZE
- 1) << CPU_TLB_ENTRY_BITS
);
825 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_A0
, TCG_REG_A0
, TCG_AREG0
);
826 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_AT
, TCG_REG_A0
,
827 offsetof(CPUState
, tlb_table
[mem_index
][0].addr_read
) + addr_meml
);
828 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_T0
, TARGET_PAGE_MASK
| ((1 << s_bits
) - 1));
829 tcg_out_opc_reg(s
, OPC_AND
, TCG_REG_T0
, TCG_REG_T0
, addr_regl
);
831 # if TARGET_LONG_BITS == 64
832 label3_ptr
= s
->code_ptr
;
833 tcg_out_opc_br(s
, OPC_BNE
, TCG_REG_T0
, TCG_REG_AT
);
836 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_AT
, TCG_REG_A0
,
837 offsetof(CPUState
, tlb_table
[mem_index
][0].addr_read
) + addr_memh
);
839 label1_ptr
= s
->code_ptr
;
840 tcg_out_opc_br(s
, OPC_BEQ
, addr_regh
, TCG_REG_AT
);
843 reloc_pc16(label3_ptr
, (tcg_target_long
) s
->code_ptr
);
845 label1_ptr
= s
->code_ptr
;
846 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_T0
, TCG_REG_AT
);
851 sp_args
= TCG_REG_A0
;
852 tcg_out_mov(s
, TCG_TYPE_I32
, sp_args
++, addr_reg1
);
853 # if TARGET_LONG_BITS == 64
854 tcg_out_mov(s
, TCG_TYPE_I32
, sp_args
++, addr_reg2
);
856 tcg_out_movi(s
, TCG_TYPE_I32
, sp_args
++, mem_index
);
857 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_T9
, (tcg_target_long
)qemu_ld_helpers
[s_bits
]);
858 tcg_out_opc_reg(s
, OPC_JALR
, TCG_REG_RA
, TCG_REG_T9
, 0);
863 tcg_out_opc_imm(s
, OPC_ANDI
, data_reg1
, TCG_REG_V0
, 0xff);
866 tcg_out_ext8s(s
, data_reg1
, TCG_REG_V0
);
869 tcg_out_opc_imm(s
, OPC_ANDI
, data_reg1
, TCG_REG_V0
, 0xffff);
872 tcg_out_ext16s(s
, data_reg1
, TCG_REG_V0
);
875 tcg_out_mov(s
, TCG_TYPE_I32
, data_reg1
, TCG_REG_V0
);
878 tcg_out_mov(s
, TCG_TYPE_I32
, data_reg2
, TCG_REG_V1
);
879 tcg_out_mov(s
, TCG_TYPE_I32
, data_reg1
, TCG_REG_V0
);
885 label2_ptr
= s
->code_ptr
;
886 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_ZERO
, TCG_REG_ZERO
);
889 /* label1: fast path */
890 reloc_pc16(label1_ptr
, (tcg_target_long
) s
->code_ptr
);
892 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_A0
, TCG_REG_A0
,
893 offsetof(CPUState
, tlb_table
[mem_index
][0].addend
));
894 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_V0
, TCG_REG_A0
, addr_regl
);
896 if (GUEST_BASE
== (int16_t)GUEST_BASE
) {
897 tcg_out_opc_imm(s
, OPC_ADDIU
, TCG_REG_V0
, addr_regl
, GUEST_BASE
);
899 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_V0
, GUEST_BASE
);
900 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_V0
, TCG_REG_V0
, addr_regl
);
906 tcg_out_opc_imm(s
, OPC_LBU
, data_reg1
, TCG_REG_V0
, 0);
909 tcg_out_opc_imm(s
, OPC_LB
, data_reg1
, TCG_REG_V0
, 0);
912 if (TCG_NEED_BSWAP
) {
913 tcg_out_opc_imm(s
, OPC_LHU
, TCG_REG_T0
, TCG_REG_V0
, 0);
914 tcg_out_bswap16(s
, data_reg1
, TCG_REG_T0
);
916 tcg_out_opc_imm(s
, OPC_LHU
, data_reg1
, TCG_REG_V0
, 0);
920 if (TCG_NEED_BSWAP
) {
921 tcg_out_opc_imm(s
, OPC_LHU
, TCG_REG_T0
, TCG_REG_V0
, 0);
922 tcg_out_bswap16s(s
, data_reg1
, TCG_REG_T0
);
924 tcg_out_opc_imm(s
, OPC_LH
, data_reg1
, TCG_REG_V0
, 0);
928 if (TCG_NEED_BSWAP
) {
929 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_T0
, TCG_REG_V0
, 0);
930 tcg_out_bswap32(s
, data_reg1
, TCG_REG_T0
);
932 tcg_out_opc_imm(s
, OPC_LW
, data_reg1
, TCG_REG_V0
, 0);
936 if (TCG_NEED_BSWAP
) {
937 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_T0
, TCG_REG_V0
, 4);
938 tcg_out_bswap32(s
, data_reg1
, TCG_REG_T0
);
939 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_T0
, TCG_REG_V0
, 0);
940 tcg_out_bswap32(s
, data_reg2
, TCG_REG_T0
);
942 tcg_out_opc_imm(s
, OPC_LW
, data_reg1
, TCG_REG_V0
, 0);
943 tcg_out_opc_imm(s
, OPC_LW
, data_reg2
, TCG_REG_V0
, 4);
950 #if defined(CONFIG_SOFTMMU)
951 reloc_pc16(label2_ptr
, (tcg_target_long
) s
->code_ptr
);
955 static void tcg_out_qemu_st(TCGContext
*s
, const TCGArg
*args
,
958 int addr_regl
, addr_reg1
, addr_meml
;
959 int data_regl
, data_regh
, data_reg1
, data_reg2
;
960 int mem_index
, s_bits
;
961 #if defined(CONFIG_SOFTMMU)
962 uint8_t *label1_ptr
, *label2_ptr
;
965 #if TARGET_LONG_BITS == 64
966 # if defined(CONFIG_SOFTMMU)
969 int addr_regh
, addr_reg2
, addr_memh
;
975 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
976 data_reg1
= data_regh
;
977 data_reg2
= data_regl
;
979 data_reg1
= data_regl
;
980 data_reg2
= data_regh
;
983 data_reg1
= data_regl
;
988 #if TARGET_LONG_BITS == 64
990 # if defined(TCG_TARGET_WORDS_BIGENDIAN)
991 addr_reg1
= addr_regh
;
992 addr_reg2
= addr_regl
;
996 addr_reg1
= addr_regl
;
997 addr_reg2
= addr_regh
;
1002 addr_reg1
= addr_regl
;
1008 #if defined(CONFIG_SOFTMMU)
1009 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_A0
, addr_regl
, TARGET_PAGE_BITS
- CPU_TLB_ENTRY_BITS
);
1010 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_A0
, TCG_REG_A0
, (CPU_TLB_SIZE
- 1) << CPU_TLB_ENTRY_BITS
);
1011 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_A0
, TCG_REG_A0
, TCG_AREG0
);
1012 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_AT
, TCG_REG_A0
,
1013 offsetof(CPUState
, tlb_table
[mem_index
][0].addr_write
) + addr_meml
);
1014 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_T0
, TARGET_PAGE_MASK
| ((1 << s_bits
) - 1));
1015 tcg_out_opc_reg(s
, OPC_AND
, TCG_REG_T0
, TCG_REG_T0
, addr_regl
);
1017 # if TARGET_LONG_BITS == 64
1018 label3_ptr
= s
->code_ptr
;
1019 tcg_out_opc_br(s
, OPC_BNE
, TCG_REG_T0
, TCG_REG_AT
);
1022 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_AT
, TCG_REG_A0
,
1023 offsetof(CPUState
, tlb_table
[mem_index
][0].addr_write
) + addr_memh
);
1025 label1_ptr
= s
->code_ptr
;
1026 tcg_out_opc_br(s
, OPC_BEQ
, addr_regh
, TCG_REG_AT
);
1029 reloc_pc16(label3_ptr
, (tcg_target_long
) s
->code_ptr
);
1031 label1_ptr
= s
->code_ptr
;
1032 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_T0
, TCG_REG_AT
);
1037 sp_args
= TCG_REG_A0
;
1038 tcg_out_mov(s
, TCG_TYPE_I32
, sp_args
++, addr_reg1
);
1039 # if TARGET_LONG_BITS == 64
1040 tcg_out_mov(s
, TCG_TYPE_I32
, sp_args
++, addr_reg2
);
1044 tcg_out_opc_imm(s
, OPC_ANDI
, sp_args
++, data_reg1
, 0xff);
1047 tcg_out_opc_imm(s
, OPC_ANDI
, sp_args
++, data_reg1
, 0xffff);
1050 tcg_out_mov(s
, TCG_TYPE_I32
, sp_args
++, data_reg1
);
1053 sp_args
= (sp_args
+ 1) & ~1;
1054 tcg_out_mov(s
, TCG_TYPE_I32
, sp_args
++, data_reg1
);
1055 tcg_out_mov(s
, TCG_TYPE_I32
, sp_args
++, data_reg2
);
1060 if (sp_args
> TCG_REG_A3
) {
1061 /* Push mem_index on the stack */
1062 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_AT
, mem_index
);
1063 tcg_out_st(s
, TCG_TYPE_I32
, TCG_REG_AT
, TCG_REG_SP
, 16);
1065 tcg_out_movi(s
, TCG_TYPE_I32
, sp_args
, mem_index
);
1068 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_T9
, (tcg_target_long
)qemu_st_helpers
[s_bits
]);
1069 tcg_out_opc_reg(s
, OPC_JALR
, TCG_REG_RA
, TCG_REG_T9
, 0);
1072 label2_ptr
= s
->code_ptr
;
1073 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_ZERO
, TCG_REG_ZERO
);
1076 /* label1: fast path */
1077 reloc_pc16(label1_ptr
, (tcg_target_long
) s
->code_ptr
);
1079 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_A0
, TCG_REG_A0
,
1080 offsetof(CPUState
, tlb_table
[mem_index
][0].addend
));
1081 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_A0
, TCG_REG_A0
, addr_regl
);
1083 if (GUEST_BASE
== (int16_t)GUEST_BASE
) {
1084 tcg_out_opc_imm(s
, OPC_ADDIU
, TCG_REG_A0
, addr_regl
, GUEST_BASE
);
1086 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_A0
, GUEST_BASE
);
1087 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_A0
, TCG_REG_A0
, addr_regl
);
1094 tcg_out_opc_imm(s
, OPC_SB
, data_reg1
, TCG_REG_A0
, 0);
1097 if (TCG_NEED_BSWAP
) {
1098 tcg_out_bswap16(s
, TCG_REG_T0
, data_reg1
);
1099 tcg_out_opc_imm(s
, OPC_SH
, TCG_REG_T0
, TCG_REG_A0
, 0);
1101 tcg_out_opc_imm(s
, OPC_SH
, data_reg1
, TCG_REG_A0
, 0);
1105 if (TCG_NEED_BSWAP
) {
1106 tcg_out_bswap32(s
, TCG_REG_T0
, data_reg1
);
1107 tcg_out_opc_imm(s
, OPC_SW
, TCG_REG_T0
, TCG_REG_A0
, 0);
1109 tcg_out_opc_imm(s
, OPC_SW
, data_reg1
, TCG_REG_A0
, 0);
1113 if (TCG_NEED_BSWAP
) {
1114 tcg_out_bswap32(s
, TCG_REG_T0
, data_reg2
);
1115 tcg_out_opc_imm(s
, OPC_SW
, TCG_REG_T0
, TCG_REG_A0
, 0);
1116 tcg_out_bswap32(s
, TCG_REG_T0
, data_reg1
);
1117 tcg_out_opc_imm(s
, OPC_SW
, TCG_REG_T0
, TCG_REG_A0
, 4);
1119 tcg_out_opc_imm(s
, OPC_SW
, data_reg1
, TCG_REG_A0
, 0);
1120 tcg_out_opc_imm(s
, OPC_SW
, data_reg2
, TCG_REG_A0
, 4);
1127 #if defined(CONFIG_SOFTMMU)
1128 reloc_pc16(label2_ptr
, (tcg_target_long
) s
->code_ptr
);
1132 static inline void tcg_out_op(TCGContext
*s
, TCGOpcode opc
,
1133 const TCGArg
*args
, const int *const_args
)
1136 case INDEX_op_exit_tb
:
1137 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_V0
, args
[0]);
1138 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_AT
, (tcg_target_long
)tb_ret_addr
);
1139 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_AT
, 0);
1142 case INDEX_op_goto_tb
:
1143 if (s
->tb_jmp_offset
) {
1144 /* direct jump method */
1147 /* indirect jump method */
1148 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_AT
, (tcg_target_long
)(s
->tb_next
+ args
[0]));
1149 tcg_out_ld(s
, TCG_TYPE_PTR
, TCG_REG_AT
, TCG_REG_AT
, 0);
1150 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_AT
, 0);
1153 s
->tb_next_offset
[args
[0]] = s
->code_ptr
- s
->code_buf
;
1156 tcg_out_opc_reg(s
, OPC_JALR
, TCG_REG_RA
, args
[0], 0);
1160 tcg_out_opc_reg(s
, OPC_JR
, 0, args
[0], 0);
1164 tcg_out_brcond(s
, TCG_COND_EQ
, TCG_REG_ZERO
, TCG_REG_ZERO
, args
[0]);
1167 case INDEX_op_mov_i32
:
1168 tcg_out_mov(s
, TCG_TYPE_I32
, args
[0], args
[1]);
1170 case INDEX_op_movi_i32
:
1171 tcg_out_movi(s
, TCG_TYPE_I32
, args
[0], args
[1]);
1174 case INDEX_op_ld8u_i32
:
1175 tcg_out_ldst(s
, OPC_LBU
, args
[0], args
[1], args
[2]);
1177 case INDEX_op_ld8s_i32
:
1178 tcg_out_ldst(s
, OPC_LB
, args
[0], args
[1], args
[2]);
1180 case INDEX_op_ld16u_i32
:
1181 tcg_out_ldst(s
, OPC_LHU
, args
[0], args
[1], args
[2]);
1183 case INDEX_op_ld16s_i32
:
1184 tcg_out_ldst(s
, OPC_LH
, args
[0], args
[1], args
[2]);
1186 case INDEX_op_ld_i32
:
1187 tcg_out_ldst(s
, OPC_LW
, args
[0], args
[1], args
[2]);
1189 case INDEX_op_st8_i32
:
1190 tcg_out_ldst(s
, OPC_SB
, args
[0], args
[1], args
[2]);
1192 case INDEX_op_st16_i32
:
1193 tcg_out_ldst(s
, OPC_SH
, args
[0], args
[1], args
[2]);
1195 case INDEX_op_st_i32
:
1196 tcg_out_ldst(s
, OPC_SW
, args
[0], args
[1], args
[2]);
1199 case INDEX_op_add_i32
:
1200 if (const_args
[2]) {
1201 tcg_out_opc_imm(s
, OPC_ADDIU
, args
[0], args
[1], args
[2]);
1203 tcg_out_opc_reg(s
, OPC_ADDU
, args
[0], args
[1], args
[2]);
1206 case INDEX_op_add2_i32
:
1207 if (const_args
[4]) {
1208 tcg_out_opc_imm(s
, OPC_ADDIU
, TCG_REG_AT
, args
[2], args
[4]);
1210 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_AT
, args
[2], args
[4]);
1212 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_T0
, TCG_REG_AT
, args
[2]);
1213 if (const_args
[5]) {
1214 tcg_out_opc_imm(s
, OPC_ADDIU
, args
[1], args
[3], args
[5]);
1216 tcg_out_opc_reg(s
, OPC_ADDU
, args
[1], args
[3], args
[5]);
1218 tcg_out_opc_reg(s
, OPC_ADDU
, args
[1], args
[1], TCG_REG_T0
);
1219 tcg_out_mov(s
, TCG_TYPE_I32
, args
[0], TCG_REG_AT
);
1221 case INDEX_op_sub_i32
:
1222 if (const_args
[2]) {
1223 tcg_out_opc_imm(s
, OPC_ADDIU
, args
[0], args
[1], -args
[2]);
1225 tcg_out_opc_reg(s
, OPC_SUBU
, args
[0], args
[1], args
[2]);
1228 case INDEX_op_sub2_i32
:
1229 if (const_args
[4]) {
1230 tcg_out_opc_imm(s
, OPC_ADDIU
, TCG_REG_AT
, args
[2], -args
[4]);
1232 tcg_out_opc_reg(s
, OPC_SUBU
, TCG_REG_AT
, args
[2], args
[4]);
1234 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_T0
, args
[2], TCG_REG_AT
);
1235 if (const_args
[5]) {
1236 tcg_out_opc_imm(s
, OPC_ADDIU
, args
[1], args
[3], -args
[5]);
1238 tcg_out_opc_reg(s
, OPC_SUBU
, args
[1], args
[3], args
[5]);
1240 tcg_out_opc_reg(s
, OPC_SUBU
, args
[1], args
[1], TCG_REG_T0
);
1241 tcg_out_mov(s
, TCG_TYPE_I32
, args
[0], TCG_REG_AT
);
1243 case INDEX_op_mul_i32
:
1244 tcg_out_opc_reg(s
, OPC_MULT
, 0, args
[1], args
[2]);
1245 tcg_out_opc_reg(s
, OPC_MFLO
, args
[0], 0, 0);
1247 case INDEX_op_mulu2_i32
:
1248 tcg_out_opc_reg(s
, OPC_MULTU
, 0, args
[2], args
[3]);
1249 tcg_out_opc_reg(s
, OPC_MFLO
, args
[0], 0, 0);
1250 tcg_out_opc_reg(s
, OPC_MFHI
, args
[1], 0, 0);
1252 case INDEX_op_div_i32
:
1253 tcg_out_opc_reg(s
, OPC_DIV
, 0, args
[1], args
[2]);
1254 tcg_out_opc_reg(s
, OPC_MFLO
, args
[0], 0, 0);
1256 case INDEX_op_divu_i32
:
1257 tcg_out_opc_reg(s
, OPC_DIVU
, 0, args
[1], args
[2]);
1258 tcg_out_opc_reg(s
, OPC_MFLO
, args
[0], 0, 0);
1260 case INDEX_op_rem_i32
:
1261 tcg_out_opc_reg(s
, OPC_DIV
, 0, args
[1], args
[2]);
1262 tcg_out_opc_reg(s
, OPC_MFHI
, args
[0], 0, 0);
1264 case INDEX_op_remu_i32
:
1265 tcg_out_opc_reg(s
, OPC_DIVU
, 0, args
[1], args
[2]);
1266 tcg_out_opc_reg(s
, OPC_MFHI
, args
[0], 0, 0);
1269 case INDEX_op_and_i32
:
1270 if (const_args
[2]) {
1271 tcg_out_opc_imm(s
, OPC_ANDI
, args
[0], args
[1], args
[2]);
1273 tcg_out_opc_reg(s
, OPC_AND
, args
[0], args
[1], args
[2]);
1276 case INDEX_op_or_i32
:
1277 if (const_args
[2]) {
1278 tcg_out_opc_imm(s
, OPC_ORI
, args
[0], args
[1], args
[2]);
1280 tcg_out_opc_reg(s
, OPC_OR
, args
[0], args
[1], args
[2]);
1283 case INDEX_op_nor_i32
:
1284 tcg_out_opc_reg(s
, OPC_NOR
, args
[0], args
[1], args
[2]);
1286 case INDEX_op_not_i32
:
1287 tcg_out_opc_reg(s
, OPC_NOR
, args
[0], TCG_REG_ZERO
, args
[1]);
1289 case INDEX_op_xor_i32
:
1290 if (const_args
[2]) {
1291 tcg_out_opc_imm(s
, OPC_XORI
, args
[0], args
[1], args
[2]);
1293 tcg_out_opc_reg(s
, OPC_XOR
, args
[0], args
[1], args
[2]);
1297 case INDEX_op_sar_i32
:
1298 if (const_args
[2]) {
1299 tcg_out_opc_sa(s
, OPC_SRA
, args
[0], args
[1], args
[2]);
1301 tcg_out_opc_reg(s
, OPC_SRAV
, args
[0], args
[2], args
[1]);
1304 case INDEX_op_shl_i32
:
1305 if (const_args
[2]) {
1306 tcg_out_opc_sa(s
, OPC_SLL
, args
[0], args
[1], args
[2]);
1308 tcg_out_opc_reg(s
, OPC_SLLV
, args
[0], args
[2], args
[1]);
1311 case INDEX_op_shr_i32
:
1312 if (const_args
[2]) {
1313 tcg_out_opc_sa(s
, OPC_SRL
, args
[0], args
[1], args
[2]);
1315 tcg_out_opc_reg(s
, OPC_SRLV
, args
[0], args
[2], args
[1]);
1319 case INDEX_op_ext8s_i32
:
1320 tcg_out_ext8s(s
, args
[0], args
[1]);
1322 case INDEX_op_ext16s_i32
:
1323 tcg_out_ext16s(s
, args
[0], args
[1]);
1326 case INDEX_op_brcond_i32
:
1327 tcg_out_brcond(s
, args
[2], args
[0], args
[1], args
[3]);
1329 case INDEX_op_brcond2_i32
:
1330 tcg_out_brcond2(s
, args
[4], args
[0], args
[1], args
[2], args
[3], args
[5]);
1333 case INDEX_op_setcond_i32
:
1334 tcg_out_setcond(s
, args
[3], args
[0], args
[1], args
[2]);
1336 case INDEX_op_setcond2_i32
:
1337 tcg_out_setcond2(s
, args
[5], args
[0], args
[1], args
[2], args
[3], args
[4]);
1340 case INDEX_op_qemu_ld8u
:
1341 tcg_out_qemu_ld(s
, args
, 0);
1343 case INDEX_op_qemu_ld8s
:
1344 tcg_out_qemu_ld(s
, args
, 0 | 4);
1346 case INDEX_op_qemu_ld16u
:
1347 tcg_out_qemu_ld(s
, args
, 1);
1349 case INDEX_op_qemu_ld16s
:
1350 tcg_out_qemu_ld(s
, args
, 1 | 4);
1352 case INDEX_op_qemu_ld32
:
1353 tcg_out_qemu_ld(s
, args
, 2);
1355 case INDEX_op_qemu_ld64
:
1356 tcg_out_qemu_ld(s
, args
, 3);
1358 case INDEX_op_qemu_st8
:
1359 tcg_out_qemu_st(s
, args
, 0);
1361 case INDEX_op_qemu_st16
:
1362 tcg_out_qemu_st(s
, args
, 1);
1364 case INDEX_op_qemu_st32
:
1365 tcg_out_qemu_st(s
, args
, 2);
1367 case INDEX_op_qemu_st64
:
1368 tcg_out_qemu_st(s
, args
, 3);
1376 static const TCGTargetOpDef mips_op_defs
[] = {
1377 { INDEX_op_exit_tb
, { } },
1378 { INDEX_op_goto_tb
, { } },
1379 { INDEX_op_call
, { "C" } },
1380 { INDEX_op_jmp
, { "r" } },
1381 { INDEX_op_br
, { } },
1383 { INDEX_op_mov_i32
, { "r", "r" } },
1384 { INDEX_op_movi_i32
, { "r" } },
1385 { INDEX_op_ld8u_i32
, { "r", "r" } },
1386 { INDEX_op_ld8s_i32
, { "r", "r" } },
1387 { INDEX_op_ld16u_i32
, { "r", "r" } },
1388 { INDEX_op_ld16s_i32
, { "r", "r" } },
1389 { INDEX_op_ld_i32
, { "r", "r" } },
1390 { INDEX_op_st8_i32
, { "rZ", "r" } },
1391 { INDEX_op_st16_i32
, { "rZ", "r" } },
1392 { INDEX_op_st_i32
, { "rZ", "r" } },
1394 { INDEX_op_add_i32
, { "r", "rZ", "rJZ" } },
1395 { INDEX_op_mul_i32
, { "r", "rZ", "rZ" } },
1396 { INDEX_op_mulu2_i32
, { "r", "r", "rZ", "rZ" } },
1397 { INDEX_op_div_i32
, { "r", "rZ", "rZ" } },
1398 { INDEX_op_divu_i32
, { "r", "rZ", "rZ" } },
1399 { INDEX_op_rem_i32
, { "r", "rZ", "rZ" } },
1400 { INDEX_op_remu_i32
, { "r", "rZ", "rZ" } },
1401 { INDEX_op_sub_i32
, { "r", "rZ", "rJZ" } },
1403 { INDEX_op_and_i32
, { "r", "rZ", "rIZ" } },
1404 { INDEX_op_nor_i32
, { "r", "rZ", "rZ" } },
1405 { INDEX_op_not_i32
, { "r", "rZ" } },
1406 { INDEX_op_or_i32
, { "r", "rZ", "rIZ" } },
1407 { INDEX_op_xor_i32
, { "r", "rZ", "rIZ" } },
1409 { INDEX_op_shl_i32
, { "r", "rZ", "riZ" } },
1410 { INDEX_op_shr_i32
, { "r", "rZ", "riZ" } },
1411 { INDEX_op_sar_i32
, { "r", "rZ", "riZ" } },
1413 { INDEX_op_ext8s_i32
, { "r", "rZ" } },
1414 { INDEX_op_ext16s_i32
, { "r", "rZ" } },
1416 { INDEX_op_brcond_i32
, { "rZ", "rZ" } },
1417 { INDEX_op_setcond_i32
, { "r", "rZ", "rZ" } },
1418 { INDEX_op_setcond2_i32
, { "r", "rZ", "rZ", "rZ", "rZ" } },
1420 { INDEX_op_add2_i32
, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1421 { INDEX_op_sub2_i32
, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1422 { INDEX_op_brcond2_i32
, { "rZ", "rZ", "rZ", "rZ" } },
1424 #if TARGET_LONG_BITS == 32
1425 { INDEX_op_qemu_ld8u
, { "L", "lZ" } },
1426 { INDEX_op_qemu_ld8s
, { "L", "lZ" } },
1427 { INDEX_op_qemu_ld16u
, { "L", "lZ" } },
1428 { INDEX_op_qemu_ld16s
, { "L", "lZ" } },
1429 { INDEX_op_qemu_ld32
, { "L", "lZ" } },
1430 { INDEX_op_qemu_ld64
, { "L", "L", "lZ" } },
1432 { INDEX_op_qemu_st8
, { "SZ", "SZ" } },
1433 { INDEX_op_qemu_st16
, { "SZ", "SZ" } },
1434 { INDEX_op_qemu_st32
, { "SZ", "SZ" } },
1435 { INDEX_op_qemu_st64
, { "SZ", "SZ", "SZ" } },
1437 { INDEX_op_qemu_ld8u
, { "L", "lZ", "lZ" } },
1438 { INDEX_op_qemu_ld8s
, { "L", "lZ", "lZ" } },
1439 { INDEX_op_qemu_ld16u
, { "L", "lZ", "lZ" } },
1440 { INDEX_op_qemu_ld16s
, { "L", "lZ", "lZ" } },
1441 { INDEX_op_qemu_ld32
, { "L", "lZ", "lZ" } },
1442 { INDEX_op_qemu_ld64
, { "L", "L", "lZ", "lZ" } },
1444 { INDEX_op_qemu_st8
, { "SZ", "SZ", "SZ" } },
1445 { INDEX_op_qemu_st16
, { "SZ", "SZ", "SZ" } },
1446 { INDEX_op_qemu_st32
, { "SZ", "SZ", "SZ" } },
1447 { INDEX_op_qemu_st64
, { "SZ", "SZ", "SZ", "SZ" } },
1452 static int tcg_target_callee_save_regs
[] = {
1453 #if 0 /* used for the global env (TCG_AREG0), so no need to save */
1465 TCG_REG_RA
, /* should be last for ABI compliance */
1468 /* Generate global QEMU prologue and epilogue code */
1469 static void tcg_target_qemu_prologue(TCGContext
*s
)
1473 /* reserve some stack space */
1474 frame_size
= ARRAY_SIZE(tcg_target_callee_save_regs
) * 4
1475 + TCG_STATIC_CALL_ARGS_SIZE
;
1476 frame_size
= (frame_size
+ TCG_TARGET_STACK_ALIGN
- 1) &
1477 ~(TCG_TARGET_STACK_ALIGN
- 1);
1480 tcg_out_addi(s
, TCG_REG_SP
, -frame_size
);
1481 for(i
= 0 ; i
< ARRAY_SIZE(tcg_target_callee_save_regs
) ; i
++) {
1482 tcg_out_st(s
, TCG_TYPE_I32
, tcg_target_callee_save_regs
[i
],
1483 TCG_REG_SP
, TCG_STATIC_CALL_ARGS_SIZE
+ i
* 4);
1486 /* Call generated code */
1487 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_A0
, 0);
1489 tb_ret_addr
= s
->code_ptr
;
1492 for(i
= 0 ; i
< ARRAY_SIZE(tcg_target_callee_save_regs
) ; i
++) {
1493 tcg_out_ld(s
, TCG_TYPE_I32
, tcg_target_callee_save_regs
[i
],
1494 TCG_REG_SP
, TCG_STATIC_CALL_ARGS_SIZE
+ i
* 4);
1497 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_RA
, 0);
1498 tcg_out_addi(s
, TCG_REG_SP
, frame_size
);
1501 static void tcg_target_init(TCGContext
*s
)
1503 tcg_regset_set(tcg_target_available_regs
[TCG_TYPE_I32
], 0xffffffff);
1504 tcg_regset_set(tcg_target_call_clobber_regs
,
1521 tcg_regset_clear(s
->reserved_regs
);
1522 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_ZERO
); /* zero register */
1523 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_K0
); /* kernel use only */
1524 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_K1
); /* kernel use only */
1525 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_AT
); /* internal use */
1526 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_T0
); /* internal use */
1527 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_RA
); /* return address */
1528 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_SP
); /* stack pointer */
1530 tcg_add_target_add_op_defs(mips_op_defs
);