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 #if defined(CONFIG_SOFTMMU)
226 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_A0
);
227 # if TARGET_LONG_BITS == 64
228 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_A1
);
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_SPECIAL
= 0x00 << 26,
274 OPC_BEQ
= 0x04 << 26,
275 OPC_BNE
= 0x05 << 26,
276 OPC_ADDIU
= 0x09 << 26,
277 OPC_SLTI
= 0x0A << 26,
278 OPC_SLTIU
= 0x0B << 26,
279 OPC_ANDI
= 0x0C << 26,
280 OPC_ORI
= 0x0D << 26,
281 OPC_XORI
= 0x0E << 26,
282 OPC_LUI
= 0x0F << 26,
286 OPC_LBU
= 0x24 << 26,
287 OPC_LHU
= 0x25 << 26,
288 OPC_LWU
= 0x27 << 26,
292 OPC_SLL
= OPC_SPECIAL
| 0x00,
293 OPC_SRL
= OPC_SPECIAL
| 0x02,
294 OPC_SRA
= OPC_SPECIAL
| 0x03,
295 OPC_SLLV
= OPC_SPECIAL
| 0x04,
296 OPC_SRLV
= OPC_SPECIAL
| 0x06,
297 OPC_SRAV
= OPC_SPECIAL
| 0x07,
298 OPC_JR
= OPC_SPECIAL
| 0x08,
299 OPC_JALR
= OPC_SPECIAL
| 0x09,
300 OPC_MFHI
= OPC_SPECIAL
| 0x10,
301 OPC_MFLO
= OPC_SPECIAL
| 0x12,
302 OPC_MULT
= OPC_SPECIAL
| 0x18,
303 OPC_MULTU
= OPC_SPECIAL
| 0x19,
304 OPC_DIV
= OPC_SPECIAL
| 0x1A,
305 OPC_DIVU
= OPC_SPECIAL
| 0x1B,
306 OPC_ADDU
= OPC_SPECIAL
| 0x21,
307 OPC_SUBU
= OPC_SPECIAL
| 0x23,
308 OPC_AND
= OPC_SPECIAL
| 0x24,
309 OPC_OR
= OPC_SPECIAL
| 0x25,
310 OPC_XOR
= OPC_SPECIAL
| 0x26,
311 OPC_NOR
= OPC_SPECIAL
| 0x27,
312 OPC_SLT
= OPC_SPECIAL
| 0x2A,
313 OPC_SLTU
= OPC_SPECIAL
| 0x2B,
319 static inline void tcg_out_opc_reg(TCGContext
*s
, int opc
, int rd
, int rs
, int rt
)
324 inst
|= (rs
& 0x1F) << 21;
325 inst
|= (rt
& 0x1F) << 16;
326 inst
|= (rd
& 0x1F) << 11;
333 static inline void tcg_out_opc_imm(TCGContext
*s
, int opc
, int rt
, int rs
, int imm
)
338 inst
|= (rs
& 0x1F) << 21;
339 inst
|= (rt
& 0x1F) << 16;
340 inst
|= (imm
& 0xffff);
347 static inline void tcg_out_opc_sa(TCGContext
*s
, int opc
, int rd
, int rt
, int sa
)
352 inst
|= (rt
& 0x1F) << 16;
353 inst
|= (rd
& 0x1F) << 11;
354 inst
|= (sa
& 0x1F) << 6;
359 static inline void tcg_out_nop(TCGContext
*s
)
364 static inline void tcg_out_mov(TCGContext
*s
, int ret
, int arg
)
366 tcg_out_opc_reg(s
, OPC_ADDU
, ret
, arg
, TCG_REG_ZERO
);
369 static inline void tcg_out_movi(TCGContext
*s
, TCGType type
,
370 int reg
, int32_t arg
)
372 if (arg
== (int16_t)arg
) {
373 tcg_out_opc_imm(s
, OPC_ADDIU
, reg
, TCG_REG_ZERO
, arg
);
374 } else if (arg
== (uint16_t)arg
) {
375 tcg_out_opc_imm(s
, OPC_ORI
, reg
, TCG_REG_ZERO
, arg
);
377 tcg_out_opc_imm(s
, OPC_LUI
, reg
, 0, arg
>> 16);
378 tcg_out_opc_imm(s
, OPC_ORI
, reg
, reg
, arg
& 0xffff);
382 static inline void tcg_out_bswap16(TCGContext
*s
, int ret
, int arg
)
384 /* ret and arg can't be register at */
385 if (ret
== TCG_REG_AT
|| arg
== TCG_REG_AT
) {
389 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_AT
, arg
, 8);
390 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_AT
, TCG_REG_AT
, 0x00ff);
392 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 8);
393 tcg_out_opc_imm(s
, OPC_ANDI
, ret
, ret
, 0xff00);
394 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
397 static inline void tcg_out_bswap16s(TCGContext
*s
, int ret
, int arg
)
399 /* ret and arg can't be register at */
400 if (ret
== TCG_REG_AT
|| arg
== TCG_REG_AT
) {
404 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_AT
, arg
, 8);
405 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_AT
, TCG_REG_AT
, 0xff);
407 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 24);
408 tcg_out_opc_sa(s
, OPC_SRA
, ret
, ret
, 16);
409 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
412 static inline void tcg_out_bswap32(TCGContext
*s
, int ret
, int arg
)
414 /* ret and arg must be different and can't be register at */
415 if (ret
== arg
|| ret
== TCG_REG_AT
|| arg
== TCG_REG_AT
) {
419 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 24);
421 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_AT
, arg
, 24);
422 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
424 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_AT
, arg
, 0xff00);
425 tcg_out_opc_sa(s
, OPC_SLL
, TCG_REG_AT
, TCG_REG_AT
, 8);
426 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
428 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_AT
, arg
, 8);
429 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_AT
, TCG_REG_AT
, 0xff00);
430 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
433 static inline void tcg_out_ldst(TCGContext
*s
, int opc
, int arg
,
434 int arg1
, tcg_target_long arg2
)
436 if (arg2
== (int16_t) arg2
) {
437 tcg_out_opc_imm(s
, opc
, arg
, arg1
, arg2
);
439 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_AT
, arg2
);
440 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_AT
, TCG_REG_AT
, arg1
);
441 tcg_out_opc_imm(s
, opc
, arg
, TCG_REG_AT
, 0);
445 static inline void tcg_out_ld(TCGContext
*s
, TCGType type
, int arg
,
446 int arg1
, tcg_target_long arg2
)
448 tcg_out_ldst(s
, OPC_LW
, arg
, arg1
, arg2
);
451 static inline void tcg_out_st(TCGContext
*s
, TCGType type
, int arg
,
452 int arg1
, tcg_target_long arg2
)
454 tcg_out_ldst(s
, OPC_SW
, arg
, arg1
, arg2
);
457 static inline void tcg_out_addi(TCGContext
*s
, int reg
, tcg_target_long val
)
459 if (val
== (int16_t)val
) {
460 tcg_out_opc_imm(s
, OPC_ADDIU
, reg
, reg
, val
);
462 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_AT
, val
);
463 tcg_out_opc_reg(s
, OPC_ADDU
, reg
, reg
, TCG_REG_AT
);
467 static void tcg_out_brcond(TCGContext
*s
, TCGCond cond
, int arg1
,
468 int arg2
, int label_index
)
470 TCGLabel
*l
= &s
->labels
[label_index
];
474 tcg_out_opc_imm(s
, OPC_BEQ
, arg1
, arg2
, 0);
477 tcg_out_opc_imm(s
, OPC_BNE
, arg1
, arg2
, 0);
480 tcg_out_opc_reg(s
, OPC_SLT
, TCG_REG_AT
, arg1
, arg2
);
481 tcg_out_opc_imm(s
, OPC_BNE
, TCG_REG_AT
, TCG_REG_ZERO
, 0);
484 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_AT
, arg1
, arg2
);
485 tcg_out_opc_imm(s
, OPC_BNE
, TCG_REG_AT
, TCG_REG_ZERO
, 0);
488 tcg_out_opc_reg(s
, OPC_SLT
, TCG_REG_AT
, arg1
, arg2
);
489 tcg_out_opc_imm(s
, OPC_BEQ
, TCG_REG_AT
, TCG_REG_ZERO
, 0);
492 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_AT
, arg1
, arg2
);
493 tcg_out_opc_imm(s
, OPC_BEQ
, TCG_REG_AT
, TCG_REG_ZERO
, 0);
496 tcg_out_opc_reg(s
, OPC_SLT
, TCG_REG_AT
, arg2
, arg1
);
497 tcg_out_opc_imm(s
, OPC_BEQ
, TCG_REG_AT
, TCG_REG_ZERO
, 0);
500 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_AT
, arg2
, arg1
);
501 tcg_out_opc_imm(s
, OPC_BEQ
, TCG_REG_AT
, TCG_REG_ZERO
, 0);
504 tcg_out_opc_reg(s
, OPC_SLT
, TCG_REG_AT
, arg2
, arg1
);
505 tcg_out_opc_imm(s
, OPC_BNE
, TCG_REG_AT
, TCG_REG_ZERO
, 0);
508 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_AT
, arg2
, arg1
);
509 tcg_out_opc_imm(s
, OPC_BNE
, TCG_REG_AT
, TCG_REG_ZERO
, 0);
516 reloc_pc16(s
->code_ptr
- 4, l
->u
.value
);
518 tcg_out_reloc(s
, s
->code_ptr
- 4, R_MIPS_PC16
, label_index
, 0);
523 /* XXX: we implement it at the target level to avoid having to
524 handle cross basic blocks temporaries */
525 static void tcg_out_brcond2(TCGContext
*s
, TCGCond cond
, int arg1
,
526 int arg2
, int arg3
, int arg4
, int label_index
)
532 tcg_out_brcond(s
, TCG_COND_NE
, arg2
, arg4
, label_index
);
533 tcg_out_brcond(s
, TCG_COND_NE
, arg1
, arg3
, label_index
);
539 tcg_out_brcond(s
, TCG_COND_LT
, arg2
, arg4
, label_index
);
543 tcg_out_brcond(s
, TCG_COND_GT
, arg2
, arg4
, label_index
);
547 tcg_out_brcond(s
, TCG_COND_LTU
, arg2
, arg4
, label_index
);
551 tcg_out_brcond(s
, TCG_COND_GTU
, arg2
, arg4
, label_index
);
557 label_ptr
= s
->code_ptr
;
558 tcg_out_opc_imm(s
, OPC_BNE
, arg2
, arg4
, 0);
563 tcg_out_brcond(s
, TCG_COND_EQ
, arg1
, arg3
, label_index
);
567 tcg_out_brcond(s
, TCG_COND_LTU
, arg1
, arg3
, label_index
);
571 tcg_out_brcond(s
, TCG_COND_LEU
, arg1
, arg3
, label_index
);
575 tcg_out_brcond(s
, TCG_COND_GTU
, arg1
, arg3
, label_index
);
579 tcg_out_brcond(s
, TCG_COND_GEU
, arg1
, arg3
, label_index
);
585 reloc_pc16(label_ptr
, (tcg_target_long
) s
->code_ptr
);
588 static void tcg_out_setcond(TCGContext
*s
, TCGCond cond
, int ret
,
594 tcg_out_opc_imm(s
, OPC_SLTIU
, ret
, arg2
, 1);
595 } else if (arg2
== 0) {
596 tcg_out_opc_imm(s
, OPC_SLTIU
, ret
, arg1
, 1);
598 tcg_out_opc_reg(s
, OPC_XOR
, ret
, arg1
, arg2
);
599 tcg_out_opc_imm(s
, OPC_SLTIU
, ret
, ret
, 1);
604 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, TCG_REG_ZERO
, arg2
);
605 } else if (arg2
== 0) {
606 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, TCG_REG_ZERO
, arg1
);
608 tcg_out_opc_reg(s
, OPC_XOR
, ret
, arg1
, arg2
);
609 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, TCG_REG_ZERO
, ret
);
613 tcg_out_opc_reg(s
, OPC_SLT
, ret
, arg1
, arg2
);
616 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, arg1
, arg2
);
619 tcg_out_opc_reg(s
, OPC_SLT
, ret
, arg1
, arg2
);
620 tcg_out_opc_imm(s
, OPC_XORI
, ret
, ret
, 1);
623 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, arg1
, arg2
);
624 tcg_out_opc_imm(s
, OPC_XORI
, ret
, ret
, 1);
627 tcg_out_opc_reg(s
, OPC_SLT
, ret
, arg2
, arg1
);
628 tcg_out_opc_imm(s
, OPC_XORI
, ret
, ret
, 1);
631 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, arg2
, arg1
);
632 tcg_out_opc_imm(s
, OPC_XORI
, ret
, ret
, 1);
635 tcg_out_opc_reg(s
, OPC_SLT
, ret
, arg2
, arg1
);
638 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, arg2
, arg1
);
646 /* XXX: we implement it at the target level to avoid having to
647 handle cross basic blocks temporaries */
648 static void tcg_out_setcond2(TCGContext
*s
, TCGCond cond
, int ret
,
649 int arg1
, int arg2
, int arg3
, int arg4
)
653 tcg_out_setcond(s
, TCG_COND_EQ
, TCG_REG_AT
, arg2
, arg4
);
654 tcg_out_setcond(s
, TCG_COND_EQ
, TCG_REG_T0
, arg1
, arg3
);
655 tcg_out_opc_reg(s
, OPC_AND
, ret
, TCG_REG_AT
, TCG_REG_T0
);
658 tcg_out_setcond(s
, TCG_COND_NE
, TCG_REG_AT
, arg2
, arg4
);
659 tcg_out_setcond(s
, TCG_COND_NE
, TCG_REG_T0
, arg1
, arg3
);
660 tcg_out_opc_reg(s
, OPC_OR
, ret
, TCG_REG_AT
, TCG_REG_T0
);
664 tcg_out_setcond(s
, TCG_COND_LT
, TCG_REG_AT
, arg2
, arg4
);
668 tcg_out_setcond(s
, TCG_COND_GT
, TCG_REG_AT
, arg2
, arg4
);
672 tcg_out_setcond(s
, TCG_COND_LTU
, TCG_REG_AT
, arg2
, arg4
);
676 tcg_out_setcond(s
, TCG_COND_GTU
, TCG_REG_AT
, arg2
, arg4
);
683 tcg_out_setcond(s
, TCG_COND_EQ
, TCG_REG_T0
, arg2
, arg4
);
688 tcg_out_setcond(s
, TCG_COND_LTU
, ret
, arg1
, arg3
);
692 tcg_out_setcond(s
, TCG_COND_LEU
, ret
, arg1
, arg3
);
696 tcg_out_setcond(s
, TCG_COND_GTU
, ret
, arg1
, arg3
);
700 tcg_out_setcond(s
, TCG_COND_GEU
, ret
, arg1
, arg3
);
706 tcg_out_opc_reg(s
, OPC_AND
, ret
, ret
, TCG_REG_T0
);
707 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
710 #if defined(CONFIG_SOFTMMU)
712 #include "../../softmmu_defs.h"
714 static void *qemu_ld_helpers
[4] = {
721 static void *qemu_st_helpers
[4] = {
729 static void tcg_out_qemu_ld(TCGContext
*s
, const TCGArg
*args
,
732 int addr_regl
, addr_reg1
, addr_meml
;
733 int data_regl
, data_regh
, data_reg1
, data_reg2
;
734 int mem_index
, s_bits
;
735 #if defined(CONFIG_SOFTMMU)
736 void *label1_ptr
, *label2_ptr
;
739 #if TARGET_LONG_BITS == 64
740 # if defined(CONFIG_SOFTMMU)
743 int addr_regh
, addr_reg2
, addr_memh
;
751 #if TARGET_LONG_BITS == 64
758 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
759 data_reg1
= data_regh
;
760 data_reg2
= data_regl
;
762 data_reg1
= data_regl
;
763 data_reg2
= data_regh
;
766 data_reg1
= data_regl
;
769 #if TARGET_LONG_BITS == 64
770 # if defined(TCG_TARGET_WORDS_BIGENDIAN)
771 addr_reg1
= addr_regh
;
772 addr_reg2
= addr_regl
;
776 addr_reg1
= addr_regl
;
777 addr_reg2
= addr_regh
;
782 addr_reg1
= addr_regl
;
786 #if defined(CONFIG_SOFTMMU)
787 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_A0
, addr_regl
, TARGET_PAGE_BITS
- CPU_TLB_ENTRY_BITS
);
788 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_A0
, TCG_REG_A0
, (CPU_TLB_SIZE
- 1) << CPU_TLB_ENTRY_BITS
);
789 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_A0
, TCG_REG_A0
, TCG_AREG0
);
790 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_AT
, TCG_REG_A0
,
791 offsetof(CPUState
, tlb_table
[mem_index
][0].addr_read
) + addr_meml
);
792 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_T0
, TARGET_PAGE_MASK
| ((1 << s_bits
) - 1));
793 tcg_out_opc_reg(s
, OPC_AND
, TCG_REG_T0
, TCG_REG_T0
, addr_regl
);
795 # if TARGET_LONG_BITS == 64
796 label3_ptr
= s
->code_ptr
;
797 tcg_out_opc_imm(s
, OPC_BNE
, TCG_REG_T0
, TCG_REG_AT
, 0);
800 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_AT
, TCG_REG_A0
,
801 offsetof(CPUState
, tlb_table
[mem_index
][0].addr_read
) + addr_memh
);
803 label1_ptr
= s
->code_ptr
;
804 tcg_out_opc_imm(s
, OPC_BEQ
, addr_regh
, TCG_REG_AT
, 0);
807 reloc_pc16(label3_ptr
, (tcg_target_long
) s
->code_ptr
);
809 label1_ptr
= s
->code_ptr
;
810 tcg_out_opc_imm(s
, OPC_BEQ
, TCG_REG_T0
, TCG_REG_AT
, 0);
815 sp_args
= TCG_REG_A0
;
816 tcg_out_mov(s
, sp_args
++, addr_reg1
);
817 # if TARGET_LONG_BITS == 64
818 tcg_out_mov(s
, sp_args
++, addr_reg2
);
820 tcg_out_movi(s
, TCG_TYPE_I32
, sp_args
++, mem_index
);
821 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_T9
, (tcg_target_long
)qemu_ld_helpers
[s_bits
]);
822 tcg_out_opc_reg(s
, OPC_JALR
, TCG_REG_RA
, TCG_REG_T9
, 0);
827 tcg_out_opc_imm(s
, OPC_ANDI
, data_reg1
, TCG_REG_V0
, 0xff);
830 tcg_out_opc_sa(s
, OPC_SLL
, TCG_REG_V0
, TCG_REG_V0
, 24);
831 tcg_out_opc_sa(s
, OPC_SRA
, data_reg1
, TCG_REG_V0
, 24);
834 tcg_out_opc_imm(s
, OPC_ANDI
, data_reg1
, TCG_REG_V0
, 0xffff);
837 tcg_out_opc_sa(s
, OPC_SLL
, TCG_REG_V0
, TCG_REG_V0
, 16);
838 tcg_out_opc_sa(s
, OPC_SRA
, data_reg1
, TCG_REG_V0
, 16);
841 tcg_out_mov(s
, data_reg1
, TCG_REG_V0
);
844 tcg_out_mov(s
, data_reg2
, TCG_REG_V1
);
845 tcg_out_mov(s
, data_reg1
, TCG_REG_V0
);
851 label2_ptr
= s
->code_ptr
;
852 tcg_out_opc_imm(s
, OPC_BEQ
, TCG_REG_ZERO
, TCG_REG_ZERO
, 0);
855 /* label1: fast path */
856 reloc_pc16(label1_ptr
, (tcg_target_long
) s
->code_ptr
);
858 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_A0
, TCG_REG_A0
,
859 offsetof(CPUState
, tlb_table
[mem_index
][0].addend
) + addr_meml
);
860 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_V0
, TCG_REG_A0
, addr_regl
);
862 addr_reg1
= TCG_REG_V0
;
867 tcg_out_opc_imm(s
, OPC_LBU
, data_reg1
, addr_reg1
, 0);
870 tcg_out_opc_imm(s
, OPC_LB
, data_reg1
, addr_reg1
, 0);
873 if (TCG_NEED_BSWAP
) {
874 tcg_out_opc_imm(s
, OPC_LHU
, TCG_REG_T0
, addr_reg1
, 0);
875 tcg_out_bswap16(s
, data_reg1
, TCG_REG_T0
);
877 tcg_out_opc_imm(s
, OPC_LHU
, data_reg1
, addr_reg1
, 0);
881 if (TCG_NEED_BSWAP
) {
882 tcg_out_opc_imm(s
, OPC_LHU
, TCG_REG_T0
, addr_reg1
, 0);
883 tcg_out_bswap16s(s
, data_reg1
, TCG_REG_T0
);
885 tcg_out_opc_imm(s
, OPC_LH
, data_reg1
, addr_reg1
, 0);
889 if (TCG_NEED_BSWAP
) {
890 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_T0
, addr_reg1
, 0);
891 tcg_out_bswap32(s
, data_reg1
, TCG_REG_T0
);
893 tcg_out_opc_imm(s
, OPC_LW
, data_reg1
, addr_reg1
, 0);
897 #if !defined(CONFIG_SOFTMMU)
898 tcg_out_mov(s
, TCG_REG_V0
, addr_reg1
);
899 addr_reg1
= TCG_REG_V0
;
901 if (TCG_NEED_BSWAP
) {
902 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_T0
, addr_reg1
, 4);
903 tcg_out_bswap32(s
, data_reg1
, TCG_REG_T0
);
904 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_T0
, addr_reg1
, 0);
905 tcg_out_bswap32(s
, data_reg2
, TCG_REG_T0
);
907 tcg_out_opc_imm(s
, OPC_LW
, data_reg1
, addr_reg1
, 0);
908 tcg_out_opc_imm(s
, OPC_LW
, data_reg2
, addr_reg1
, 4);
915 #if defined(CONFIG_SOFTMMU)
916 reloc_pc16(label2_ptr
, (tcg_target_long
) s
->code_ptr
);
920 static void tcg_out_qemu_st(TCGContext
*s
, const TCGArg
*args
,
923 int addr_regl
, addr_reg1
, addr_meml
;
924 int data_regl
, data_regh
, data_reg1
, data_reg2
;
925 int mem_index
, s_bits
;
926 #if defined(CONFIG_SOFTMMU)
927 uint8_t *label1_ptr
, *label2_ptr
;
930 #if TARGET_LONG_BITS == 64
931 # if defined(CONFIG_SOFTMMU)
934 int addr_regh
, addr_reg2
, addr_memh
;
940 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
941 data_reg1
= data_regh
;
942 data_reg2
= data_regl
;
944 data_reg1
= data_regl
;
945 data_reg2
= data_regh
;
948 data_reg1
= data_regl
;
953 #if TARGET_LONG_BITS == 64
955 # if defined(TCG_TARGET_WORDS_BIGENDIAN)
956 addr_reg1
= addr_regh
;
957 addr_reg2
= addr_regl
;
961 addr_reg1
= addr_regl
;
962 addr_reg2
= addr_regh
;
967 addr_reg1
= addr_regl
;
973 #if defined(CONFIG_SOFTMMU)
974 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_A0
, addr_regl
, TARGET_PAGE_BITS
- CPU_TLB_ENTRY_BITS
);
975 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_A0
, TCG_REG_A0
, (CPU_TLB_SIZE
- 1) << CPU_TLB_ENTRY_BITS
);
976 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_A0
, TCG_REG_A0
, TCG_AREG0
);
977 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_AT
, TCG_REG_A0
,
978 offsetof(CPUState
, tlb_table
[mem_index
][0].addr_write
) + addr_meml
);
979 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_T0
, TARGET_PAGE_MASK
| ((1 << s_bits
) - 1));
980 tcg_out_opc_reg(s
, OPC_AND
, TCG_REG_T0
, TCG_REG_T0
, addr_regl
);
982 # if TARGET_LONG_BITS == 64
983 label3_ptr
= s
->code_ptr
;
984 tcg_out_opc_imm(s
, OPC_BNE
, TCG_REG_T0
, TCG_REG_AT
, 0);
987 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_AT
, TCG_REG_A0
,
988 offsetof(CPUState
, tlb_table
[mem_index
][0].addr_write
) + addr_memh
);
990 label1_ptr
= s
->code_ptr
;
991 tcg_out_opc_imm(s
, OPC_BEQ
, addr_regh
, TCG_REG_AT
, 0);
994 reloc_pc16(label3_ptr
, (tcg_target_long
) s
->code_ptr
);
996 label1_ptr
= s
->code_ptr
;
997 tcg_out_opc_imm(s
, OPC_BEQ
, TCG_REG_T0
, TCG_REG_AT
, 0);
1002 sp_args
= TCG_REG_A0
;
1003 tcg_out_mov(s
, sp_args
++, addr_reg1
);
1004 # if TARGET_LONG_BITS == 64
1005 tcg_out_mov(s
, sp_args
++, addr_reg2
);
1009 tcg_out_opc_imm(s
, OPC_ANDI
, sp_args
++, data_reg1
, 0xff);
1012 tcg_out_opc_imm(s
, OPC_ANDI
, sp_args
++, data_reg1
, 0xffff);
1015 tcg_out_mov(s
, sp_args
++, data_reg1
);
1018 sp_args
= (sp_args
+ 1) & ~1;
1019 tcg_out_mov(s
, sp_args
++, data_reg1
);
1020 tcg_out_mov(s
, sp_args
++, data_reg2
);
1025 if (sp_args
> TCG_REG_A3
) {
1026 /* Push mem_index on the stack */
1027 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_AT
, mem_index
);
1028 tcg_out_st(s
, TCG_TYPE_I32
, TCG_REG_AT
, TCG_REG_SP
, 16);
1030 tcg_out_movi(s
, TCG_TYPE_I32
, sp_args
, mem_index
);
1033 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_T9
, (tcg_target_long
)qemu_st_helpers
[s_bits
]);
1034 tcg_out_opc_reg(s
, OPC_JALR
, TCG_REG_RA
, TCG_REG_T9
, 0);
1037 label2_ptr
= s
->code_ptr
;
1038 tcg_out_opc_imm(s
, OPC_BEQ
, TCG_REG_ZERO
, TCG_REG_ZERO
, 0);
1041 /* label1: fast path */
1042 reloc_pc16(label1_ptr
, (tcg_target_long
) s
->code_ptr
);
1044 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_A0
, TCG_REG_A0
,
1045 offsetof(CPUState
, tlb_table
[mem_index
][0].addend
) + addr_meml
);
1046 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_A0
, TCG_REG_A0
, addr_regl
);
1048 addr_reg1
= TCG_REG_A0
;
1053 tcg_out_opc_imm(s
, OPC_SB
, data_reg1
, addr_reg1
, 0);
1056 if (TCG_NEED_BSWAP
) {
1057 tcg_out_bswap16(s
, TCG_REG_T0
, data_reg1
);
1058 tcg_out_opc_imm(s
, OPC_SH
, TCG_REG_T0
, addr_reg1
, 0);
1060 tcg_out_opc_imm(s
, OPC_SH
, data_reg1
, addr_reg1
, 0);
1064 if (TCG_NEED_BSWAP
) {
1065 tcg_out_bswap32(s
, TCG_REG_T0
, data_reg1
);
1066 tcg_out_opc_imm(s
, OPC_SW
, TCG_REG_T0
, addr_reg1
, 0);
1068 tcg_out_opc_imm(s
, OPC_SW
, data_reg1
, addr_reg1
, 0);
1072 if (TCG_NEED_BSWAP
) {
1073 tcg_out_bswap32(s
, TCG_REG_T0
, data_reg2
);
1074 tcg_out_opc_imm(s
, OPC_SW
, TCG_REG_T0
, addr_reg1
, 0);
1075 tcg_out_bswap32(s
, TCG_REG_T0
, data_reg1
);
1076 tcg_out_opc_imm(s
, OPC_SW
, TCG_REG_T0
, addr_reg1
, 4);
1078 tcg_out_opc_imm(s
, OPC_SW
, data_reg1
, addr_reg1
, 0);
1079 tcg_out_opc_imm(s
, OPC_SW
, data_reg2
, addr_reg1
, 4);
1086 #if defined(CONFIG_SOFTMMU)
1087 reloc_pc16(label2_ptr
, (tcg_target_long
) s
->code_ptr
);
1091 static inline void tcg_out_op(TCGContext
*s
, TCGOpcode opc
,
1092 const TCGArg
*args
, const int *const_args
)
1095 case INDEX_op_exit_tb
:
1096 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_V0
, args
[0]);
1097 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_AT
, (tcg_target_long
)tb_ret_addr
);
1098 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_AT
, 0);
1101 case INDEX_op_goto_tb
:
1102 if (s
->tb_jmp_offset
) {
1103 /* direct jump method */
1106 /* indirect jump method */
1107 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_AT
, (tcg_target_long
)(s
->tb_next
+ args
[0]));
1108 tcg_out_ld(s
, TCG_TYPE_PTR
, TCG_REG_AT
, TCG_REG_AT
, 0);
1109 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_AT
, 0);
1112 s
->tb_next_offset
[args
[0]] = s
->code_ptr
- s
->code_buf
;
1115 tcg_out_opc_reg(s
, OPC_JALR
, TCG_REG_RA
, args
[0], 0);
1119 tcg_out_opc_reg(s
, OPC_JR
, 0, args
[0], 0);
1123 tcg_out_brcond(s
, TCG_COND_EQ
, TCG_REG_ZERO
, TCG_REG_ZERO
, args
[0]);
1126 case INDEX_op_mov_i32
:
1127 tcg_out_mov(s
, args
[0], args
[1]);
1129 case INDEX_op_movi_i32
:
1130 tcg_out_movi(s
, TCG_TYPE_I32
, args
[0], args
[1]);
1133 case INDEX_op_ld8u_i32
:
1134 tcg_out_ldst(s
, OPC_LBU
, args
[0], args
[1], args
[2]);
1136 case INDEX_op_ld8s_i32
:
1137 tcg_out_ldst(s
, OPC_LB
, args
[0], args
[1], args
[2]);
1139 case INDEX_op_ld16u_i32
:
1140 tcg_out_ldst(s
, OPC_LHU
, args
[0], args
[1], args
[2]);
1142 case INDEX_op_ld16s_i32
:
1143 tcg_out_ldst(s
, OPC_LH
, args
[0], args
[1], args
[2]);
1145 case INDEX_op_ld_i32
:
1146 tcg_out_ldst(s
, OPC_LW
, args
[0], args
[1], args
[2]);
1148 case INDEX_op_st8_i32
:
1149 tcg_out_ldst(s
, OPC_SB
, args
[0], args
[1], args
[2]);
1151 case INDEX_op_st16_i32
:
1152 tcg_out_ldst(s
, OPC_SH
, args
[0], args
[1], args
[2]);
1154 case INDEX_op_st_i32
:
1155 tcg_out_ldst(s
, OPC_SW
, args
[0], args
[1], args
[2]);
1158 case INDEX_op_add_i32
:
1159 if (const_args
[2]) {
1160 tcg_out_opc_imm(s
, OPC_ADDIU
, args
[0], args
[1], args
[2]);
1162 tcg_out_opc_reg(s
, OPC_ADDU
, args
[0], args
[1], args
[2]);
1165 case INDEX_op_add2_i32
:
1166 if (const_args
[4]) {
1167 tcg_out_opc_imm(s
, OPC_ADDIU
, TCG_REG_AT
, args
[2], args
[4]);
1169 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_AT
, args
[2], args
[4]);
1171 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_T0
, TCG_REG_AT
, args
[2]);
1172 if (const_args
[5]) {
1173 tcg_out_opc_imm(s
, OPC_ADDIU
, args
[1], args
[3], args
[5]);
1175 tcg_out_opc_reg(s
, OPC_ADDU
, args
[1], args
[3], args
[5]);
1177 tcg_out_opc_reg(s
, OPC_ADDU
, args
[1], args
[1], TCG_REG_T0
);
1178 tcg_out_mov(s
, args
[0], TCG_REG_AT
);
1180 case INDEX_op_sub_i32
:
1181 if (const_args
[2]) {
1182 tcg_out_opc_imm(s
, OPC_ADDIU
, args
[0], args
[1], -args
[2]);
1184 tcg_out_opc_reg(s
, OPC_SUBU
, args
[0], args
[1], args
[2]);
1187 case INDEX_op_sub2_i32
:
1188 if (const_args
[4]) {
1189 tcg_out_opc_imm(s
, OPC_ADDIU
, TCG_REG_AT
, args
[2], -args
[4]);
1191 tcg_out_opc_reg(s
, OPC_SUBU
, TCG_REG_AT
, args
[2], args
[4]);
1193 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_T0
, args
[2], TCG_REG_AT
);
1194 if (const_args
[5]) {
1195 tcg_out_opc_imm(s
, OPC_ADDIU
, args
[1], args
[3], -args
[5]);
1197 tcg_out_opc_reg(s
, OPC_SUBU
, args
[1], args
[3], args
[5]);
1199 tcg_out_opc_reg(s
, OPC_SUBU
, args
[1], args
[1], TCG_REG_T0
);
1200 tcg_out_mov(s
, args
[0], TCG_REG_AT
);
1202 case INDEX_op_mul_i32
:
1203 tcg_out_opc_reg(s
, OPC_MULT
, 0, args
[1], args
[2]);
1204 tcg_out_opc_reg(s
, OPC_MFLO
, args
[0], 0, 0);
1206 case INDEX_op_mulu2_i32
:
1207 tcg_out_opc_reg(s
, OPC_MULTU
, 0, args
[2], args
[3]);
1208 tcg_out_opc_reg(s
, OPC_MFLO
, args
[0], 0, 0);
1209 tcg_out_opc_reg(s
, OPC_MFHI
, args
[1], 0, 0);
1211 case INDEX_op_div_i32
:
1212 tcg_out_opc_reg(s
, OPC_DIV
, 0, args
[1], args
[2]);
1213 tcg_out_opc_reg(s
, OPC_MFLO
, args
[0], 0, 0);
1215 case INDEX_op_divu_i32
:
1216 tcg_out_opc_reg(s
, OPC_DIVU
, 0, args
[1], args
[2]);
1217 tcg_out_opc_reg(s
, OPC_MFLO
, args
[0], 0, 0);
1219 case INDEX_op_rem_i32
:
1220 tcg_out_opc_reg(s
, OPC_DIV
, 0, args
[1], args
[2]);
1221 tcg_out_opc_reg(s
, OPC_MFHI
, args
[0], 0, 0);
1223 case INDEX_op_remu_i32
:
1224 tcg_out_opc_reg(s
, OPC_DIVU
, 0, args
[1], args
[2]);
1225 tcg_out_opc_reg(s
, OPC_MFHI
, args
[0], 0, 0);
1228 case INDEX_op_and_i32
:
1229 if (const_args
[2]) {
1230 tcg_out_opc_imm(s
, OPC_ANDI
, args
[0], args
[1], args
[2]);
1232 tcg_out_opc_reg(s
, OPC_AND
, args
[0], args
[1], args
[2]);
1235 case INDEX_op_or_i32
:
1236 if (const_args
[2]) {
1237 tcg_out_opc_imm(s
, OPC_ORI
, args
[0], args
[1], args
[2]);
1239 tcg_out_opc_reg(s
, OPC_OR
, args
[0], args
[1], args
[2]);
1242 case INDEX_op_nor_i32
:
1243 tcg_out_opc_reg(s
, OPC_NOR
, args
[0], args
[1], args
[2]);
1245 case INDEX_op_not_i32
:
1246 tcg_out_opc_reg(s
, OPC_NOR
, args
[0], TCG_REG_ZERO
, args
[1]);
1248 case INDEX_op_xor_i32
:
1249 if (const_args
[2]) {
1250 tcg_out_opc_imm(s
, OPC_XORI
, args
[0], args
[1], args
[2]);
1252 tcg_out_opc_reg(s
, OPC_XOR
, args
[0], args
[1], args
[2]);
1256 case INDEX_op_sar_i32
:
1257 if (const_args
[2]) {
1258 tcg_out_opc_sa(s
, OPC_SRA
, args
[0], args
[1], args
[2]);
1260 tcg_out_opc_reg(s
, OPC_SRAV
, args
[0], args
[2], args
[1]);
1263 case INDEX_op_shl_i32
:
1264 if (const_args
[2]) {
1265 tcg_out_opc_sa(s
, OPC_SLL
, args
[0], args
[1], args
[2]);
1267 tcg_out_opc_reg(s
, OPC_SLLV
, args
[0], args
[2], args
[1]);
1270 case INDEX_op_shr_i32
:
1271 if (const_args
[2]) {
1272 tcg_out_opc_sa(s
, OPC_SRL
, args
[0], args
[1], args
[2]);
1274 tcg_out_opc_reg(s
, OPC_SRLV
, args
[0], args
[2], args
[1]);
1278 case INDEX_op_brcond_i32
:
1279 tcg_out_brcond(s
, args
[2], args
[0], args
[1], args
[3]);
1281 case INDEX_op_brcond2_i32
:
1282 tcg_out_brcond2(s
, args
[4], args
[0], args
[1], args
[2], args
[3], args
[5]);
1285 case INDEX_op_setcond_i32
:
1286 tcg_out_setcond(s
, args
[3], args
[0], args
[1], args
[2]);
1288 case INDEX_op_setcond2_i32
:
1289 tcg_out_setcond2(s
, args
[5], args
[0], args
[1], args
[2], args
[3], args
[4]);
1292 case INDEX_op_qemu_ld8u
:
1293 tcg_out_qemu_ld(s
, args
, 0);
1295 case INDEX_op_qemu_ld8s
:
1296 tcg_out_qemu_ld(s
, args
, 0 | 4);
1298 case INDEX_op_qemu_ld16u
:
1299 tcg_out_qemu_ld(s
, args
, 1);
1301 case INDEX_op_qemu_ld16s
:
1302 tcg_out_qemu_ld(s
, args
, 1 | 4);
1304 case INDEX_op_qemu_ld32
:
1305 tcg_out_qemu_ld(s
, args
, 2);
1307 case INDEX_op_qemu_ld64
:
1308 tcg_out_qemu_ld(s
, args
, 3);
1310 case INDEX_op_qemu_st8
:
1311 tcg_out_qemu_st(s
, args
, 0);
1313 case INDEX_op_qemu_st16
:
1314 tcg_out_qemu_st(s
, args
, 1);
1316 case INDEX_op_qemu_st32
:
1317 tcg_out_qemu_st(s
, args
, 2);
1319 case INDEX_op_qemu_st64
:
1320 tcg_out_qemu_st(s
, args
, 3);
1328 static const TCGTargetOpDef mips_op_defs
[] = {
1329 { INDEX_op_exit_tb
, { } },
1330 { INDEX_op_goto_tb
, { } },
1331 { INDEX_op_call
, { "C" } },
1332 { INDEX_op_jmp
, { "r" } },
1333 { INDEX_op_br
, { } },
1335 { INDEX_op_mov_i32
, { "r", "r" } },
1336 { INDEX_op_movi_i32
, { "r" } },
1337 { INDEX_op_ld8u_i32
, { "r", "r" } },
1338 { INDEX_op_ld8s_i32
, { "r", "r" } },
1339 { INDEX_op_ld16u_i32
, { "r", "r" } },
1340 { INDEX_op_ld16s_i32
, { "r", "r" } },
1341 { INDEX_op_ld_i32
, { "r", "r" } },
1342 { INDEX_op_st8_i32
, { "rZ", "r" } },
1343 { INDEX_op_st16_i32
, { "rZ", "r" } },
1344 { INDEX_op_st_i32
, { "rZ", "r" } },
1346 { INDEX_op_add_i32
, { "r", "rZ", "rJZ" } },
1347 { INDEX_op_mul_i32
, { "r", "rZ", "rZ" } },
1348 { INDEX_op_mulu2_i32
, { "r", "r", "rZ", "rZ" } },
1349 { INDEX_op_div_i32
, { "r", "rZ", "rZ" } },
1350 { INDEX_op_divu_i32
, { "r", "rZ", "rZ" } },
1351 { INDEX_op_rem_i32
, { "r", "rZ", "rZ" } },
1352 { INDEX_op_remu_i32
, { "r", "rZ", "rZ" } },
1353 { INDEX_op_sub_i32
, { "r", "rZ", "rJZ" } },
1355 { INDEX_op_and_i32
, { "r", "rZ", "rIZ" } },
1356 { INDEX_op_nor_i32
, { "r", "rZ", "rZ" } },
1357 { INDEX_op_not_i32
, { "r", "rZ" } },
1358 { INDEX_op_or_i32
, { "r", "rZ", "rIZ" } },
1359 { INDEX_op_xor_i32
, { "r", "rZ", "rIZ" } },
1361 { INDEX_op_shl_i32
, { "r", "rZ", "riZ" } },
1362 { INDEX_op_shr_i32
, { "r", "rZ", "riZ" } },
1363 { INDEX_op_sar_i32
, { "r", "rZ", "riZ" } },
1365 { INDEX_op_brcond_i32
, { "rZ", "rZ" } },
1366 { INDEX_op_setcond_i32
, { "r", "rZ", "rZ" } },
1367 { INDEX_op_setcond2_i32
, { "r", "rZ", "rZ", "rZ", "rZ" } },
1369 { INDEX_op_add2_i32
, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1370 { INDEX_op_sub2_i32
, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1371 { INDEX_op_brcond2_i32
, { "rZ", "rZ", "rZ", "rZ" } },
1373 #if TARGET_LONG_BITS == 32
1374 { INDEX_op_qemu_ld8u
, { "L", "lZ" } },
1375 { INDEX_op_qemu_ld8s
, { "L", "lZ" } },
1376 { INDEX_op_qemu_ld16u
, { "L", "lZ" } },
1377 { INDEX_op_qemu_ld16s
, { "L", "lZ" } },
1378 { INDEX_op_qemu_ld32
, { "L", "lZ" } },
1379 { INDEX_op_qemu_ld64
, { "L", "L", "lZ" } },
1381 { INDEX_op_qemu_st8
, { "SZ", "SZ" } },
1382 { INDEX_op_qemu_st16
, { "SZ", "SZ" } },
1383 { INDEX_op_qemu_st32
, { "SZ", "SZ" } },
1384 { INDEX_op_qemu_st64
, { "SZ", "SZ", "SZ" } },
1386 { INDEX_op_qemu_ld8u
, { "L", "lZ", "lZ" } },
1387 { INDEX_op_qemu_ld8s
, { "L", "lZ", "lZ" } },
1388 { INDEX_op_qemu_ld16u
, { "L", "lZ", "lZ" } },
1389 { INDEX_op_qemu_ld16s
, { "L", "lZ", "lZ" } },
1390 { INDEX_op_qemu_ld32
, { "L", "lZ", "lZ" } },
1391 { INDEX_op_qemu_ld64
, { "L", "L", "lZ", "lZ" } },
1393 { INDEX_op_qemu_st8
, { "SZ", "SZ", "SZ" } },
1394 { INDEX_op_qemu_st16
, { "SZ", "SZ", "SZ" } },
1395 { INDEX_op_qemu_st32
, { "SZ", "SZ", "SZ" } },
1396 { INDEX_op_qemu_st64
, { "SZ", "SZ", "SZ", "SZ" } },
1401 static int tcg_target_callee_save_regs
[] = {
1411 /* TCG_REG_FP, */ /* currently used for the global env, so np
1413 TCG_REG_RA
, /* should be last for ABI compliance */
1416 /* Generate global QEMU prologue and epilogue code */
1417 void tcg_target_qemu_prologue(TCGContext
*s
)
1421 /* reserve some stack space */
1422 frame_size
= ARRAY_SIZE(tcg_target_callee_save_regs
) * 4
1423 + TCG_STATIC_CALL_ARGS_SIZE
;
1424 frame_size
= (frame_size
+ TCG_TARGET_STACK_ALIGN
- 1) &
1425 ~(TCG_TARGET_STACK_ALIGN
- 1);
1428 tcg_out_addi(s
, TCG_REG_SP
, -frame_size
);
1429 for(i
= 0 ; i
< ARRAY_SIZE(tcg_target_callee_save_regs
) ; i
++) {
1430 tcg_out_st(s
, TCG_TYPE_I32
, tcg_target_callee_save_regs
[i
],
1431 TCG_REG_SP
, TCG_STATIC_CALL_ARGS_SIZE
+ i
* 4);
1434 /* Call generated code */
1435 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_A0
, 0);
1437 tb_ret_addr
= s
->code_ptr
;
1440 for(i
= 0 ; i
< ARRAY_SIZE(tcg_target_callee_save_regs
) ; i
++) {
1441 tcg_out_ld(s
, TCG_TYPE_I32
, tcg_target_callee_save_regs
[i
],
1442 TCG_REG_SP
, TCG_STATIC_CALL_ARGS_SIZE
+ i
* 4);
1445 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_RA
, 0);
1446 tcg_out_addi(s
, TCG_REG_SP
, frame_size
);
1449 void tcg_target_init(TCGContext
*s
)
1451 tcg_regset_set(tcg_target_available_regs
[TCG_TYPE_I32
], 0xffffffff);
1452 tcg_regset_set(tcg_target_call_clobber_regs
,
1469 tcg_regset_clear(s
->reserved_regs
);
1470 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_ZERO
); /* zero register */
1471 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_K0
); /* kernel use only */
1472 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_K1
); /* kernel use only */
1473 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_AT
); /* internal use */
1474 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_T0
); /* internal use */
1475 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_RA
); /* return address */
1476 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_SP
); /* stack pointer */
1478 tcg_add_target_add_op_defs(mips_op_defs
);