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_ANDI
= 0x0C << 26,
278 OPC_ORI
= 0x0D << 26,
279 OPC_XORI
= 0x0E << 26,
280 OPC_LUI
= 0x0F << 26,
284 OPC_LBU
= 0x24 << 26,
285 OPC_LHU
= 0x25 << 26,
286 OPC_LWU
= 0x27 << 26,
290 OPC_SLL
= OPC_SPECIAL
| 0x00,
291 OPC_SRL
= OPC_SPECIAL
| 0x02,
292 OPC_SRA
= OPC_SPECIAL
| 0x03,
293 OPC_SLLV
= OPC_SPECIAL
| 0x04,
294 OPC_SRLV
= OPC_SPECIAL
| 0x06,
295 OPC_SRAV
= OPC_SPECIAL
| 0x07,
296 OPC_JR
= OPC_SPECIAL
| 0x08,
297 OPC_JALR
= OPC_SPECIAL
| 0x09,
298 OPC_MFHI
= OPC_SPECIAL
| 0x10,
299 OPC_MFLO
= OPC_SPECIAL
| 0x12,
300 OPC_MULT
= OPC_SPECIAL
| 0x18,
301 OPC_MULTU
= OPC_SPECIAL
| 0x19,
302 OPC_DIV
= OPC_SPECIAL
| 0x1A,
303 OPC_DIVU
= OPC_SPECIAL
| 0x1B,
304 OPC_ADDU
= OPC_SPECIAL
| 0x21,
305 OPC_SUBU
= OPC_SPECIAL
| 0x23,
306 OPC_AND
= OPC_SPECIAL
| 0x24,
307 OPC_OR
= OPC_SPECIAL
| 0x25,
308 OPC_XOR
= OPC_SPECIAL
| 0x26,
309 OPC_NOR
= OPC_SPECIAL
| 0x27,
310 OPC_SLT
= OPC_SPECIAL
| 0x2A,
311 OPC_SLTU
= OPC_SPECIAL
| 0x2B,
317 static inline void tcg_out_opc_reg(TCGContext
*s
, int opc
, int rd
, int rs
, int rt
)
322 inst
|= (rs
& 0x1F) << 21;
323 inst
|= (rt
& 0x1F) << 16;
324 inst
|= (rd
& 0x1F) << 11;
331 static inline void tcg_out_opc_imm(TCGContext
*s
, int opc
, int rt
, int rs
, int imm
)
336 inst
|= (rs
& 0x1F) << 21;
337 inst
|= (rt
& 0x1F) << 16;
338 inst
|= (imm
& 0xffff);
345 static inline void tcg_out_opc_sa(TCGContext
*s
, int opc
, int rd
, int rt
, int sa
)
350 inst
|= (rt
& 0x1F) << 16;
351 inst
|= (rd
& 0x1F) << 11;
352 inst
|= (sa
& 0x1F) << 6;
357 static inline void tcg_out_nop(TCGContext
*s
)
362 static inline void tcg_out_mov(TCGContext
*s
, int ret
, int arg
)
364 tcg_out_opc_reg(s
, OPC_ADDU
, ret
, arg
, TCG_REG_ZERO
);
367 static inline void tcg_out_movi(TCGContext
*s
, TCGType type
,
368 int reg
, int32_t arg
)
370 if (arg
== (int16_t)arg
) {
371 tcg_out_opc_imm(s
, OPC_ADDIU
, reg
, TCG_REG_ZERO
, arg
);
372 } else if (arg
== (uint16_t)arg
) {
373 tcg_out_opc_imm(s
, OPC_ORI
, reg
, TCG_REG_ZERO
, arg
);
375 tcg_out_opc_imm(s
, OPC_LUI
, reg
, 0, arg
>> 16);
376 tcg_out_opc_imm(s
, OPC_ORI
, reg
, reg
, arg
& 0xffff);
380 static inline void tcg_out_bswap16(TCGContext
*s
, int ret
, int arg
)
382 /* ret and arg can't be register at */
383 if (ret
== TCG_REG_AT
|| arg
== TCG_REG_AT
) {
387 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_AT
, arg
, 8);
388 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_AT
, TCG_REG_AT
, 0x00ff);
390 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 8);
391 tcg_out_opc_imm(s
, OPC_ANDI
, ret
, ret
, 0xff00);
392 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
395 static inline void tcg_out_bswap16s(TCGContext
*s
, int ret
, int arg
)
397 /* ret and arg can't be register at */
398 if (ret
== TCG_REG_AT
|| arg
== TCG_REG_AT
) {
402 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_AT
, arg
, 8);
403 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_AT
, TCG_REG_AT
, 0xff);
405 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 24);
406 tcg_out_opc_sa(s
, OPC_SRA
, ret
, ret
, 16);
407 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
410 static inline void tcg_out_bswap32(TCGContext
*s
, int ret
, int arg
)
412 /* ret and arg must be different and can't be register at */
413 if (ret
== arg
|| ret
== TCG_REG_AT
|| arg
== TCG_REG_AT
) {
417 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 24);
419 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_AT
, arg
, 24);
420 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
422 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_AT
, arg
, 0xff00);
423 tcg_out_opc_sa(s
, OPC_SLL
, TCG_REG_AT
, TCG_REG_AT
, 8);
424 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
426 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_AT
, arg
, 8);
427 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_AT
, TCG_REG_AT
, 0xff00);
428 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
431 static inline void tcg_out_ldst(TCGContext
*s
, int opc
, int arg
,
432 int arg1
, tcg_target_long arg2
)
434 if (arg2
== (int16_t) arg2
) {
435 tcg_out_opc_imm(s
, opc
, arg
, arg1
, arg2
);
437 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_AT
, arg2
);
438 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_AT
, TCG_REG_AT
, arg1
);
439 tcg_out_opc_imm(s
, opc
, arg
, TCG_REG_AT
, 0);
443 static inline void tcg_out_ld(TCGContext
*s
, TCGType type
, int arg
,
444 int arg1
, tcg_target_long arg2
)
446 tcg_out_ldst(s
, OPC_LW
, arg
, arg1
, arg2
);
449 static inline void tcg_out_st(TCGContext
*s
, TCGType type
, int arg
,
450 int arg1
, tcg_target_long arg2
)
452 tcg_out_ldst(s
, OPC_SW
, arg
, arg1
, arg2
);
455 static inline void tcg_out_addi(TCGContext
*s
, int reg
, tcg_target_long val
)
457 if (val
== (int16_t)val
) {
458 tcg_out_opc_imm(s
, OPC_ADDIU
, reg
, reg
, val
);
460 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_AT
, val
);
461 tcg_out_opc_reg(s
, OPC_ADDU
, reg
, reg
, TCG_REG_AT
);
465 static void tcg_out_brcond(TCGContext
*s
, int cond
, int arg1
,
466 int arg2
, int label_index
)
468 TCGLabel
*l
= &s
->labels
[label_index
];
472 tcg_out_opc_imm(s
, OPC_BEQ
, arg1
, arg2
, 0);
475 tcg_out_opc_imm(s
, OPC_BNE
, arg1
, arg2
, 0);
478 tcg_out_opc_reg(s
, OPC_SLT
, TCG_REG_AT
, arg1
, arg2
);
479 tcg_out_opc_imm(s
, OPC_BNE
, TCG_REG_AT
, TCG_REG_ZERO
, 0);
482 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_AT
, arg1
, arg2
);
483 tcg_out_opc_imm(s
, OPC_BNE
, TCG_REG_AT
, TCG_REG_ZERO
, 0);
486 tcg_out_opc_reg(s
, OPC_SLT
, TCG_REG_AT
, arg1
, arg2
);
487 tcg_out_opc_imm(s
, OPC_BEQ
, TCG_REG_AT
, TCG_REG_ZERO
, 0);
490 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_AT
, arg1
, arg2
);
491 tcg_out_opc_imm(s
, OPC_BEQ
, TCG_REG_AT
, TCG_REG_ZERO
, 0);
494 tcg_out_opc_reg(s
, OPC_SLT
, TCG_REG_AT
, arg2
, arg1
);
495 tcg_out_opc_imm(s
, OPC_BEQ
, TCG_REG_AT
, TCG_REG_ZERO
, 0);
498 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_AT
, arg2
, arg1
);
499 tcg_out_opc_imm(s
, OPC_BEQ
, TCG_REG_AT
, TCG_REG_ZERO
, 0);
502 tcg_out_opc_reg(s
, OPC_SLT
, TCG_REG_AT
, arg2
, arg1
);
503 tcg_out_opc_imm(s
, OPC_BNE
, TCG_REG_AT
, TCG_REG_ZERO
, 0);
506 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_AT
, arg2
, arg1
);
507 tcg_out_opc_imm(s
, OPC_BNE
, TCG_REG_AT
, TCG_REG_ZERO
, 0);
514 reloc_pc16(s
->code_ptr
- 4, l
->u
.value
);
516 tcg_out_reloc(s
, s
->code_ptr
- 4, R_MIPS_PC16
, label_index
, 0);
521 /* XXX: we implement it at the target level to avoid having to
522 handle cross basic blocks temporaries */
523 static void tcg_out_brcond2(TCGContext
*s
, int cond
, int arg1
,
524 int arg2
, int arg3
, int arg4
, int label_index
)
530 tcg_out_brcond(s
, TCG_COND_NE
, arg2
, arg4
, label_index
);
531 tcg_out_brcond(s
, TCG_COND_NE
, arg1
, arg3
, label_index
);
537 tcg_out_brcond(s
, TCG_COND_LT
, arg2
, arg4
, label_index
);
541 tcg_out_brcond(s
, TCG_COND_GT
, arg2
, arg4
, label_index
);
545 tcg_out_brcond(s
, TCG_COND_LTU
, arg2
, arg4
, label_index
);
549 tcg_out_brcond(s
, TCG_COND_GTU
, arg2
, arg4
, label_index
);
555 label_ptr
= s
->code_ptr
;
556 tcg_out_opc_imm(s
, OPC_BNE
, arg2
, arg4
, 0);
561 tcg_out_brcond(s
, TCG_COND_EQ
, arg1
, arg3
, label_index
);
565 tcg_out_brcond(s
, TCG_COND_LTU
, arg1
, arg3
, label_index
);
569 tcg_out_brcond(s
, TCG_COND_LEU
, arg1
, arg3
, label_index
);
573 tcg_out_brcond(s
, TCG_COND_GTU
, arg1
, arg3
, label_index
);
577 tcg_out_brcond(s
, TCG_COND_GEU
, arg1
, arg3
, label_index
);
583 reloc_pc16(label_ptr
, (tcg_target_long
) s
->code_ptr
);
586 #if defined(CONFIG_SOFTMMU)
588 #include "../../softmmu_defs.h"
590 static void *qemu_ld_helpers
[4] = {
597 static void *qemu_st_helpers
[4] = {
605 static void tcg_out_qemu_ld(TCGContext
*s
, const TCGArg
*args
,
608 int addr_regl
, addr_reg1
, addr_meml
;
609 int data_regl
, data_regh
, data_reg1
, data_reg2
;
610 int mem_index
, s_bits
;
611 #if defined(CONFIG_SOFTMMU)
612 void *label1_ptr
, *label2_ptr
;
615 #if TARGET_LONG_BITS == 64
616 # if defined(CONFIG_SOFTMMU)
619 int addr_regh
, addr_reg2
, addr_memh
;
627 #if TARGET_LONG_BITS == 64
634 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
635 data_reg1
= data_regh
;
636 data_reg2
= data_regl
;
638 data_reg1
= data_regl
;
639 data_reg2
= data_regh
;
642 data_reg1
= data_regl
;
645 #if TARGET_LONG_BITS == 64
646 # if defined(TCG_TARGET_WORDS_BIGENDIAN)
647 addr_reg1
= addr_regh
;
648 addr_reg2
= addr_regl
;
652 addr_reg1
= addr_regl
;
653 addr_reg2
= addr_regh
;
658 addr_reg1
= addr_regl
;
662 #if defined(CONFIG_SOFTMMU)
663 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_A0
, addr_regl
, TARGET_PAGE_BITS
- CPU_TLB_ENTRY_BITS
);
664 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_A0
, TCG_REG_A0
, (CPU_TLB_SIZE
- 1) << CPU_TLB_ENTRY_BITS
);
665 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_A0
, TCG_REG_A0
, TCG_AREG0
);
666 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_AT
, TCG_REG_A0
,
667 offsetof(CPUState
, tlb_table
[mem_index
][0].addr_read
) + addr_meml
);
668 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_T0
, TARGET_PAGE_MASK
| ((1 << s_bits
) - 1));
669 tcg_out_opc_reg(s
, OPC_AND
, TCG_REG_T0
, TCG_REG_T0
, addr_regl
);
671 # if TARGET_LONG_BITS == 64
672 label3_ptr
= s
->code_ptr
;
673 tcg_out_opc_imm(s
, OPC_BNE
, TCG_REG_T0
, TCG_REG_AT
, 0);
676 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_AT
, TCG_REG_A0
,
677 offsetof(CPUState
, tlb_table
[mem_index
][0].addr_read
) + addr_memh
);
679 label1_ptr
= s
->code_ptr
;
680 tcg_out_opc_imm(s
, OPC_BEQ
, addr_regh
, TCG_REG_AT
, 0);
683 reloc_pc16(label3_ptr
, (tcg_target_long
) s
->code_ptr
);
685 label1_ptr
= s
->code_ptr
;
686 tcg_out_opc_imm(s
, OPC_BEQ
, TCG_REG_T0
, TCG_REG_AT
, 0);
691 sp_args
= TCG_REG_A0
;
692 tcg_out_mov(s
, sp_args
++, addr_reg1
);
693 # if TARGET_LONG_BITS == 64
694 tcg_out_mov(s
, sp_args
++, addr_reg2
);
696 tcg_out_movi(s
, TCG_TYPE_I32
, sp_args
++, mem_index
);
697 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_T9
, (tcg_target_long
)qemu_ld_helpers
[s_bits
]);
698 tcg_out_opc_reg(s
, OPC_JALR
, TCG_REG_RA
, TCG_REG_T9
, 0);
703 tcg_out_opc_imm(s
, OPC_ANDI
, data_reg1
, TCG_REG_V0
, 0xff);
706 tcg_out_opc_sa(s
, OPC_SLL
, TCG_REG_V0
, TCG_REG_V0
, 24);
707 tcg_out_opc_sa(s
, OPC_SRA
, data_reg1
, TCG_REG_V0
, 24);
710 tcg_out_opc_imm(s
, OPC_ANDI
, data_reg1
, TCG_REG_V0
, 0xffff);
713 tcg_out_opc_sa(s
, OPC_SLL
, TCG_REG_V0
, TCG_REG_V0
, 16);
714 tcg_out_opc_sa(s
, OPC_SRA
, data_reg1
, TCG_REG_V0
, 16);
717 tcg_out_mov(s
, data_reg1
, TCG_REG_V0
);
720 tcg_out_mov(s
, data_reg2
, TCG_REG_V1
);
721 tcg_out_mov(s
, data_reg1
, TCG_REG_V0
);
727 label2_ptr
= s
->code_ptr
;
728 tcg_out_opc_imm(s
, OPC_BEQ
, TCG_REG_ZERO
, TCG_REG_ZERO
, 0);
731 /* label1: fast path */
732 reloc_pc16(label1_ptr
, (tcg_target_long
) s
->code_ptr
);
734 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_V0
, TCG_REG_A0
,
735 offsetof(CPUState
, tlb_table
[mem_index
][0].addend
) + addr_meml
);
736 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_V0
, TCG_REG_V0
, addr_regl
);
738 addr_reg1
= TCG_REG_V0
;
743 tcg_out_opc_imm(s
, OPC_LBU
, data_reg1
, addr_reg1
, 0);
746 tcg_out_opc_imm(s
, OPC_LB
, data_reg1
, addr_reg1
, 0);
749 if (TCG_NEED_BSWAP
) {
750 tcg_out_opc_imm(s
, OPC_LHU
, TCG_REG_T0
, addr_reg1
, 0);
751 tcg_out_bswap16(s
, data_reg1
, TCG_REG_T0
);
753 tcg_out_opc_imm(s
, OPC_LHU
, data_reg1
, addr_reg1
, 0);
757 if (TCG_NEED_BSWAP
) {
758 tcg_out_opc_imm(s
, OPC_LHU
, TCG_REG_T0
, addr_reg1
, 0);
759 tcg_out_bswap16s(s
, data_reg1
, TCG_REG_T0
);
761 tcg_out_opc_imm(s
, OPC_LH
, data_reg1
, addr_reg1
, 0);
765 if (TCG_NEED_BSWAP
) {
766 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_T0
, addr_reg1
, 0);
767 tcg_out_bswap32(s
, data_reg1
, TCG_REG_T0
);
769 tcg_out_opc_imm(s
, OPC_LW
, data_reg1
, addr_reg1
, 0);
773 #if !defined(CONFIG_SOFTMMU)
774 tcg_out_mov(s
, TCG_REG_V0
, addr_reg1
);
775 addr_reg1
= TCG_REG_V0
;
777 if (TCG_NEED_BSWAP
) {
778 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_T0
, addr_reg1
, 4);
779 tcg_out_bswap32(s
, data_reg1
, TCG_REG_T0
);
780 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_T0
, addr_reg1
, 0);
781 tcg_out_bswap32(s
, data_reg2
, TCG_REG_T0
);
783 tcg_out_opc_imm(s
, OPC_LW
, data_reg1
, addr_reg1
, 0);
784 tcg_out_opc_imm(s
, OPC_LW
, data_reg2
, addr_reg1
, 4);
791 #if defined(CONFIG_SOFTMMU)
792 reloc_pc16(label2_ptr
, (tcg_target_long
) s
->code_ptr
);
796 static void tcg_out_qemu_st(TCGContext
*s
, const TCGArg
*args
,
799 int addr_regl
, addr_reg1
, addr_meml
;
800 int data_regl
, data_regh
, data_reg1
, data_reg2
;
801 int mem_index
, s_bits
;
802 #if defined(CONFIG_SOFTMMU)
803 uint8_t *label1_ptr
, *label2_ptr
;
806 #if TARGET_LONG_BITS == 64
807 # if defined(CONFIG_SOFTMMU)
810 int addr_regh
, addr_reg2
, addr_memh
;
816 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
817 data_reg1
= data_regh
;
818 data_reg2
= data_regl
;
820 data_reg1
= data_regl
;
821 data_reg2
= data_regh
;
824 data_reg1
= data_regl
;
829 #if TARGET_LONG_BITS == 64
831 # if defined(TCG_TARGET_WORDS_BIGENDIAN)
832 addr_reg1
= addr_regh
;
833 addr_reg2
= addr_regl
;
837 addr_reg1
= addr_regl
;
838 addr_reg2
= addr_regh
;
843 addr_reg1
= addr_regl
;
849 #if defined(CONFIG_SOFTMMU)
850 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_A0
, addr_regl
, TARGET_PAGE_BITS
- CPU_TLB_ENTRY_BITS
);
851 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_A0
, TCG_REG_A0
, (CPU_TLB_SIZE
- 1) << CPU_TLB_ENTRY_BITS
);
852 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_A0
, TCG_REG_A0
, TCG_AREG0
);
853 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_AT
, TCG_REG_A0
,
854 offsetof(CPUState
, tlb_table
[mem_index
][0].addr_write
) + addr_meml
);
855 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_T0
, TARGET_PAGE_MASK
| ((1 << s_bits
) - 1));
856 tcg_out_opc_reg(s
, OPC_AND
, TCG_REG_T0
, TCG_REG_T0
, addr_regl
);
858 # if TARGET_LONG_BITS == 64
859 label3_ptr
= s
->code_ptr
;
860 tcg_out_opc_imm(s
, OPC_BNE
, TCG_REG_T0
, TCG_REG_AT
, 0);
863 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_AT
, TCG_REG_A0
,
864 offsetof(CPUState
, tlb_table
[mem_index
][0].addr_write
) + addr_memh
);
866 label1_ptr
= s
->code_ptr
;
867 tcg_out_opc_imm(s
, OPC_BEQ
, addr_regh
, TCG_REG_AT
, 0);
870 reloc_pc16(label3_ptr
, (tcg_target_long
) s
->code_ptr
);
872 label1_ptr
= s
->code_ptr
;
873 tcg_out_opc_imm(s
, OPC_BEQ
, TCG_REG_T0
, TCG_REG_AT
, 0);
878 sp_args
= TCG_REG_A0
;
879 tcg_out_mov(s
, sp_args
++, addr_reg1
);
880 # if TARGET_LONG_BITS == 64
881 tcg_out_mov(s
, sp_args
++, addr_reg2
);
885 tcg_out_opc_imm(s
, OPC_ANDI
, sp_args
++, data_reg1
, 0xff);
888 tcg_out_opc_imm(s
, OPC_ANDI
, sp_args
++, data_reg1
, 0xffff);
891 tcg_out_mov(s
, sp_args
++, data_reg1
);
894 sp_args
= (sp_args
+ 1) & ~1;
895 tcg_out_mov(s
, sp_args
++, data_reg1
);
896 tcg_out_mov(s
, sp_args
++, data_reg2
);
901 if (sp_args
> TCG_REG_A3
) {
902 /* Push mem_index on the stack */
903 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_AT
, mem_index
);
904 tcg_out_st(s
, TCG_TYPE_I32
, TCG_REG_AT
, TCG_REG_SP
, 16);
906 tcg_out_movi(s
, TCG_TYPE_I32
, sp_args
, mem_index
);
909 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_T9
, (tcg_target_long
)qemu_st_helpers
[s_bits
]);
910 tcg_out_opc_reg(s
, OPC_JALR
, TCG_REG_RA
, TCG_REG_T9
, 0);
913 label2_ptr
= s
->code_ptr
;
914 tcg_out_opc_imm(s
, OPC_BEQ
, TCG_REG_ZERO
, TCG_REG_ZERO
, 0);
917 /* label1: fast path */
918 reloc_pc16(label1_ptr
, (tcg_target_long
) s
->code_ptr
);
920 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_A0
, TCG_REG_A0
,
921 offsetof(CPUState
, tlb_table
[mem_index
][0].addend
) + addr_meml
);
922 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_A0
, TCG_REG_A0
, addr_regl
);
924 addr_reg1
= TCG_REG_A0
;
929 tcg_out_opc_imm(s
, OPC_SB
, data_reg1
, addr_reg1
, 0);
932 if (TCG_NEED_BSWAP
) {
933 tcg_out_bswap16(s
, TCG_REG_T0
, data_reg1
);
934 tcg_out_opc_imm(s
, OPC_SH
, TCG_REG_T0
, addr_reg1
, 0);
936 tcg_out_opc_imm(s
, OPC_SH
, data_reg1
, addr_reg1
, 0);
940 if (TCG_NEED_BSWAP
) {
941 tcg_out_bswap32(s
, TCG_REG_T0
, data_reg1
);
942 tcg_out_opc_imm(s
, OPC_SW
, TCG_REG_T0
, addr_reg1
, 0);
944 tcg_out_opc_imm(s
, OPC_SW
, data_reg1
, addr_reg1
, 0);
948 if (TCG_NEED_BSWAP
) {
949 tcg_out_bswap32(s
, TCG_REG_T0
, data_reg2
);
950 tcg_out_opc_imm(s
, OPC_SW
, TCG_REG_T0
, addr_reg1
, 0);
951 tcg_out_bswap32(s
, TCG_REG_T0
, data_reg1
);
952 tcg_out_opc_imm(s
, OPC_SW
, TCG_REG_T0
, addr_reg1
, 4);
954 tcg_out_opc_imm(s
, OPC_SW
, data_reg1
, addr_reg1
, 0);
955 tcg_out_opc_imm(s
, OPC_SW
, data_reg2
, addr_reg1
, 4);
962 #if defined(CONFIG_SOFTMMU)
963 reloc_pc16(label2_ptr
, (tcg_target_long
) s
->code_ptr
);
967 static inline void tcg_out_op(TCGContext
*s
, int opc
,
968 const TCGArg
*args
, const int *const_args
)
971 case INDEX_op_exit_tb
:
972 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_V0
, args
[0]);
973 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_AT
, (tcg_target_long
)tb_ret_addr
);
974 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_AT
, 0);
977 case INDEX_op_goto_tb
:
978 if (s
->tb_jmp_offset
) {
979 /* direct jump method */
982 /* indirect jump method */
983 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_AT
, (tcg_target_long
)(s
->tb_next
+ args
[0]));
984 tcg_out_ld(s
, TCG_TYPE_PTR
, TCG_REG_AT
, TCG_REG_AT
, 0);
985 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_AT
, 0);
988 s
->tb_next_offset
[args
[0]] = s
->code_ptr
- s
->code_buf
;
991 tcg_out_opc_reg(s
, OPC_JALR
, TCG_REG_RA
, args
[0], 0);
995 tcg_out_opc_reg(s
, OPC_JR
, 0, args
[0], 0);
999 tcg_out_brcond(s
, TCG_COND_EQ
, TCG_REG_ZERO
, TCG_REG_ZERO
, args
[0]);
1002 case INDEX_op_mov_i32
:
1003 tcg_out_mov(s
, args
[0], args
[1]);
1005 case INDEX_op_movi_i32
:
1006 tcg_out_movi(s
, TCG_TYPE_I32
, args
[0], args
[1]);
1009 case INDEX_op_ld8u_i32
:
1010 tcg_out_ldst(s
, OPC_LBU
, args
[0], args
[1], args
[2]);
1012 case INDEX_op_ld8s_i32
:
1013 tcg_out_ldst(s
, OPC_LB
, args
[0], args
[1], args
[2]);
1015 case INDEX_op_ld16u_i32
:
1016 tcg_out_ldst(s
, OPC_LHU
, args
[0], args
[1], args
[2]);
1018 case INDEX_op_ld16s_i32
:
1019 tcg_out_ldst(s
, OPC_LH
, args
[0], args
[1], args
[2]);
1021 case INDEX_op_ld_i32
:
1022 tcg_out_ldst(s
, OPC_LW
, args
[0], args
[1], args
[2]);
1024 case INDEX_op_st8_i32
:
1025 tcg_out_ldst(s
, OPC_SB
, args
[0], args
[1], args
[2]);
1027 case INDEX_op_st16_i32
:
1028 tcg_out_ldst(s
, OPC_SH
, args
[0], args
[1], args
[2]);
1030 case INDEX_op_st_i32
:
1031 tcg_out_ldst(s
, OPC_SW
, args
[0], args
[1], args
[2]);
1034 case INDEX_op_add_i32
:
1035 if (const_args
[2]) {
1036 tcg_out_opc_imm(s
, OPC_ADDIU
, args
[0], args
[1], args
[2]);
1038 tcg_out_opc_reg(s
, OPC_ADDU
, args
[0], args
[1], args
[2]);
1041 case INDEX_op_add2_i32
:
1042 if (const_args
[4]) {
1043 tcg_out_opc_imm(s
, OPC_ADDIU
, TCG_REG_AT
, args
[2], args
[4]);
1045 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_AT
, args
[2], args
[4]);
1047 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_T0
, TCG_REG_AT
, args
[2]);
1048 if (const_args
[5]) {
1049 tcg_out_opc_imm(s
, OPC_ADDIU
, args
[1], args
[3], args
[5]);
1051 tcg_out_opc_reg(s
, OPC_ADDU
, args
[1], args
[3], args
[5]);
1053 tcg_out_opc_reg(s
, OPC_ADDU
, args
[1], args
[1], TCG_REG_T0
);
1054 tcg_out_mov(s
, args
[0], TCG_REG_AT
);
1056 case INDEX_op_sub_i32
:
1057 if (const_args
[2]) {
1058 tcg_out_opc_imm(s
, OPC_ADDIU
, args
[0], args
[1], -args
[2]);
1060 tcg_out_opc_reg(s
, OPC_SUBU
, args
[0], args
[1], args
[2]);
1063 case INDEX_op_sub2_i32
:
1064 if (const_args
[4]) {
1065 tcg_out_opc_imm(s
, OPC_ADDIU
, TCG_REG_AT
, args
[2], -args
[4]);
1067 tcg_out_opc_reg(s
, OPC_SUBU
, TCG_REG_AT
, args
[2], args
[4]);
1069 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_T0
, args
[2], TCG_REG_AT
);
1070 if (const_args
[5]) {
1071 tcg_out_opc_imm(s
, OPC_ADDIU
, args
[1], args
[3], -args
[5]);
1073 tcg_out_opc_reg(s
, OPC_SUBU
, args
[1], args
[3], args
[5]);
1075 tcg_out_opc_reg(s
, OPC_SUBU
, args
[1], args
[1], TCG_REG_T0
);
1076 tcg_out_mov(s
, args
[0], TCG_REG_AT
);
1078 case INDEX_op_mul_i32
:
1079 tcg_out_opc_reg(s
, OPC_MULT
, 0, args
[1], args
[2]);
1080 tcg_out_opc_reg(s
, OPC_MFLO
, args
[0], 0, 0);
1082 case INDEX_op_mulu2_i32
:
1083 tcg_out_opc_reg(s
, OPC_MULTU
, 0, args
[2], args
[3]);
1084 tcg_out_opc_reg(s
, OPC_MFLO
, args
[0], 0, 0);
1085 tcg_out_opc_reg(s
, OPC_MFHI
, args
[1], 0, 0);
1087 case INDEX_op_div_i32
:
1088 tcg_out_opc_reg(s
, OPC_DIV
, 0, args
[1], args
[2]);
1089 tcg_out_opc_reg(s
, OPC_MFLO
, args
[0], 0, 0);
1091 case INDEX_op_divu_i32
:
1092 tcg_out_opc_reg(s
, OPC_DIVU
, 0, args
[1], args
[2]);
1093 tcg_out_opc_reg(s
, OPC_MFLO
, args
[0], 0, 0);
1095 case INDEX_op_rem_i32
:
1096 tcg_out_opc_reg(s
, OPC_DIV
, 0, args
[1], args
[2]);
1097 tcg_out_opc_reg(s
, OPC_MFHI
, args
[0], 0, 0);
1099 case INDEX_op_remu_i32
:
1100 tcg_out_opc_reg(s
, OPC_DIVU
, 0, args
[1], args
[2]);
1101 tcg_out_opc_reg(s
, OPC_MFHI
, args
[0], 0, 0);
1104 case INDEX_op_and_i32
:
1105 if (const_args
[2]) {
1106 tcg_out_opc_imm(s
, OPC_ANDI
, args
[0], args
[1], args
[2]);
1108 tcg_out_opc_reg(s
, OPC_AND
, args
[0], args
[1], args
[2]);
1111 case INDEX_op_or_i32
:
1112 if (const_args
[2]) {
1113 tcg_out_opc_imm(s
, OPC_ORI
, args
[0], args
[1], args
[2]);
1115 tcg_out_opc_reg(s
, OPC_OR
, args
[0], args
[1], args
[2]);
1118 case INDEX_op_not_i32
:
1119 tcg_out_opc_reg(s
, OPC_NOR
, args
[0], args
[1], args
[1]);
1121 case INDEX_op_xor_i32
:
1122 if (const_args
[2]) {
1123 tcg_out_opc_imm(s
, OPC_XORI
, args
[0], args
[1], args
[2]);
1125 tcg_out_opc_reg(s
, OPC_XOR
, args
[0], args
[1], args
[2]);
1129 case INDEX_op_sar_i32
:
1130 if (const_args
[2]) {
1131 tcg_out_opc_sa(s
, OPC_SRA
, args
[0], args
[1], args
[2]);
1133 tcg_out_opc_reg(s
, OPC_SRAV
, args
[0], args
[2], args
[1]);
1136 case INDEX_op_shl_i32
:
1137 if (const_args
[2]) {
1138 tcg_out_opc_sa(s
, OPC_SLL
, args
[0], args
[1], args
[2]);
1140 tcg_out_opc_reg(s
, OPC_SLLV
, args
[0], args
[2], args
[1]);
1143 case INDEX_op_shr_i32
:
1144 if (const_args
[2]) {
1145 tcg_out_opc_sa(s
, OPC_SRL
, args
[0], args
[1], args
[2]);
1147 tcg_out_opc_reg(s
, OPC_SRLV
, args
[0], args
[2], args
[1]);
1151 case INDEX_op_brcond_i32
:
1152 tcg_out_brcond(s
, args
[2], args
[0], args
[1], args
[3]);
1154 case INDEX_op_brcond2_i32
:
1155 tcg_out_brcond2(s
, args
[4], args
[0], args
[1], args
[2], args
[3], args
[5]);
1158 case INDEX_op_qemu_ld8u
:
1159 tcg_out_qemu_ld(s
, args
, 0);
1161 case INDEX_op_qemu_ld8s
:
1162 tcg_out_qemu_ld(s
, args
, 0 | 4);
1164 case INDEX_op_qemu_ld16u
:
1165 tcg_out_qemu_ld(s
, args
, 1);
1167 case INDEX_op_qemu_ld16s
:
1168 tcg_out_qemu_ld(s
, args
, 1 | 4);
1170 case INDEX_op_qemu_ld32u
:
1171 tcg_out_qemu_ld(s
, args
, 2);
1173 case INDEX_op_qemu_ld64
:
1174 tcg_out_qemu_ld(s
, args
, 3);
1176 case INDEX_op_qemu_st8
:
1177 tcg_out_qemu_st(s
, args
, 0);
1179 case INDEX_op_qemu_st16
:
1180 tcg_out_qemu_st(s
, args
, 1);
1182 case INDEX_op_qemu_st32
:
1183 tcg_out_qemu_st(s
, args
, 2);
1185 case INDEX_op_qemu_st64
:
1186 tcg_out_qemu_st(s
, args
, 3);
1194 static const TCGTargetOpDef mips_op_defs
[] = {
1195 { INDEX_op_exit_tb
, { } },
1196 { INDEX_op_goto_tb
, { } },
1197 { INDEX_op_call
, { "C" } },
1198 { INDEX_op_jmp
, { "r" } },
1199 { INDEX_op_br
, { } },
1201 { INDEX_op_mov_i32
, { "r", "r" } },
1202 { INDEX_op_movi_i32
, { "r" } },
1203 { INDEX_op_ld8u_i32
, { "r", "r" } },
1204 { INDEX_op_ld8s_i32
, { "r", "r" } },
1205 { INDEX_op_ld16u_i32
, { "r", "r" } },
1206 { INDEX_op_ld16s_i32
, { "r", "r" } },
1207 { INDEX_op_ld_i32
, { "r", "r" } },
1208 { INDEX_op_st8_i32
, { "rZ", "r" } },
1209 { INDEX_op_st16_i32
, { "rZ", "r" } },
1210 { INDEX_op_st_i32
, { "rZ", "r" } },
1212 { INDEX_op_add_i32
, { "r", "rZ", "rJZ" } },
1213 { INDEX_op_mul_i32
, { "r", "rZ", "rZ" } },
1214 { INDEX_op_mulu2_i32
, { "r", "r", "rZ", "rZ" } },
1215 { INDEX_op_div_i32
, { "r", "rZ", "rZ" } },
1216 { INDEX_op_divu_i32
, { "r", "rZ", "rZ" } },
1217 { INDEX_op_rem_i32
, { "r", "rZ", "rZ" } },
1218 { INDEX_op_remu_i32
, { "r", "rZ", "rZ" } },
1219 { INDEX_op_sub_i32
, { "r", "rZ", "rJZ" } },
1221 { INDEX_op_and_i32
, { "r", "rZ", "rIZ" } },
1222 { INDEX_op_not_i32
, { "r", "rZ" } },
1223 { INDEX_op_or_i32
, { "r", "rZ", "rIZ" } },
1224 { INDEX_op_xor_i32
, { "r", "rZ", "rIZ" } },
1226 { INDEX_op_shl_i32
, { "r", "rZ", "riZ" } },
1227 { INDEX_op_shr_i32
, { "r", "rZ", "riZ" } },
1228 { INDEX_op_sar_i32
, { "r", "rZ", "riZ" } },
1230 { INDEX_op_brcond_i32
, { "rZ", "rZ" } },
1232 { INDEX_op_add2_i32
, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1233 { INDEX_op_sub2_i32
, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1234 { INDEX_op_brcond2_i32
, { "rZ", "rZ", "rZ", "rZ" } },
1236 #if TARGET_LONG_BITS == 32
1237 { INDEX_op_qemu_ld8u
, { "L", "lZ" } },
1238 { INDEX_op_qemu_ld8s
, { "L", "lZ" } },
1239 { INDEX_op_qemu_ld16u
, { "L", "lZ" } },
1240 { INDEX_op_qemu_ld16s
, { "L", "lZ" } },
1241 { INDEX_op_qemu_ld32u
, { "L", "lZ" } },
1242 { INDEX_op_qemu_ld64
, { "L", "L", "lZ" } },
1244 { INDEX_op_qemu_st8
, { "SZ", "SZ" } },
1245 { INDEX_op_qemu_st16
, { "SZ", "SZ" } },
1246 { INDEX_op_qemu_st32
, { "SZ", "SZ" } },
1247 { INDEX_op_qemu_st64
, { "SZ", "SZ", "SZ" } },
1249 { INDEX_op_qemu_ld8u
, { "L", "lZ", "lZ" } },
1250 { INDEX_op_qemu_ld8s
, { "L", "lZ", "lZ" } },
1251 { INDEX_op_qemu_ld16u
, { "L", "lZ", "lZ" } },
1252 { INDEX_op_qemu_ld16s
, { "L", "lZ", "lZ" } },
1253 { INDEX_op_qemu_ld32u
, { "L", "lZ", "lZ" } },
1254 { INDEX_op_qemu_ld64
, { "L", "L", "lZ", "lZ" } },
1256 { INDEX_op_qemu_st8
, { "SZ", "SZ", "SZ" } },
1257 { INDEX_op_qemu_st16
, { "SZ", "SZ", "SZ" } },
1258 { INDEX_op_qemu_st32
, { "SZ", "SZ", "SZ" } },
1259 { INDEX_op_qemu_st64
, { "SZ", "SZ", "SZ", "SZ" } },
1264 static int tcg_target_callee_save_regs
[] = {
1274 /* TCG_REG_FP, */ /* currently used for the global env, so np
1276 TCG_REG_RA
, /* should be last for ABI compliance */
1279 /* Generate global QEMU prologue and epilogue code */
1280 void tcg_target_qemu_prologue(TCGContext
*s
)
1284 /* reserve some stack space */
1285 frame_size
= ARRAY_SIZE(tcg_target_callee_save_regs
) * 4
1286 + TCG_STATIC_CALL_ARGS_SIZE
;
1287 frame_size
= (frame_size
+ TCG_TARGET_STACK_ALIGN
- 1) &
1288 ~(TCG_TARGET_STACK_ALIGN
- 1);
1291 tcg_out_addi(s
, TCG_REG_SP
, -frame_size
);
1292 for(i
= 0 ; i
< ARRAY_SIZE(tcg_target_callee_save_regs
) ; i
++) {
1293 tcg_out_st(s
, TCG_TYPE_I32
, tcg_target_callee_save_regs
[i
],
1294 TCG_REG_SP
, TCG_STATIC_CALL_ARGS_SIZE
+ i
* 4);
1297 /* Call generated code */
1298 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_A0
, 0);
1300 tb_ret_addr
= s
->code_ptr
;
1303 for(i
= 0 ; i
< ARRAY_SIZE(tcg_target_callee_save_regs
) ; i
++) {
1304 tcg_out_ld(s
, TCG_TYPE_I32
, tcg_target_callee_save_regs
[i
],
1305 TCG_REG_SP
, TCG_STATIC_CALL_ARGS_SIZE
+ i
* 4);
1308 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_RA
, 0);
1309 tcg_out_addi(s
, TCG_REG_SP
, frame_size
);
1312 void tcg_target_init(TCGContext
*s
)
1314 tcg_regset_set(tcg_target_available_regs
[TCG_TYPE_I32
], 0xffffffff);
1315 tcg_regset_set(tcg_target_call_clobber_regs
,
1332 tcg_regset_clear(s
->reserved_regs
);
1333 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_ZERO
); /* zero register */
1334 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_K0
); /* kernel use only */
1335 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_K1
); /* kernel use only */
1336 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_AT
); /* internal use */
1337 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_T0
); /* internal use */
1338 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_RA
); /* return address */
1339 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_SP
); /* stack pointer */
1341 tcg_add_target_add_op_defs(mips_op_defs
);