2 * Tiny Code Generator for QEMU
4 * Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org>
5 * Copyright (c) 2009 Aurelien Jarno <aurelien@aurel32.net>
6 * Based on i386/tcg-target.c - Copyright (c) 2008 Fabrice Bellard
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 #if defined(TCG_TARGET_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
28 # define TCG_NEED_BSWAP 0
30 # define TCG_NEED_BSWAP 1
34 static const char * const tcg_target_reg_names
[TCG_TARGET_NB_REGS
] = {
70 /* check if we really need so many registers :P */
71 static const int tcg_target_reg_alloc_order
[] = {
97 static const int tcg_target_call_iarg_regs
[4] = {
104 static const int tcg_target_call_oarg_regs
[2] = {
109 static uint8_t *tb_ret_addr
;
111 static inline uint32_t reloc_lo16_val (void *pc
, tcg_target_long target
)
113 return target
& 0xffff;
116 static inline void reloc_lo16 (void *pc
, tcg_target_long target
)
118 *(uint32_t *) pc
= (*(uint32_t *) pc
& ~0xffff)
119 | reloc_lo16_val(pc
, target
);
122 static inline uint32_t reloc_hi16_val (void *pc
, tcg_target_long target
)
124 return (target
>> 16) & 0xffff;
127 static inline void reloc_hi16 (void *pc
, tcg_target_long target
)
129 *(uint32_t *) pc
= (*(uint32_t *) pc
& ~0xffff)
130 | reloc_hi16_val(pc
, target
);
133 static inline uint32_t reloc_pc16_val (void *pc
, tcg_target_long target
)
137 disp
= target
- (tcg_target_long
) pc
- 4;
138 if (disp
!= (disp
<< 14) >> 14) {
142 return (disp
>> 2) & 0xffff;
145 static inline void reloc_pc16 (void *pc
, tcg_target_long target
)
147 *(uint32_t *) pc
= (*(uint32_t *) pc
& ~0xffff)
148 | reloc_pc16_val(pc
, target
);
151 static inline uint32_t reloc_26_val (void *pc
, tcg_target_long target
)
153 if ((((tcg_target_long
)pc
+ 4) & 0xf0000000) != (target
& 0xf0000000)) {
157 return (target
>> 2) & 0x3ffffff;
160 static inline void reloc_pc26 (void *pc
, tcg_target_long target
)
162 *(uint32_t *) pc
= (*(uint32_t *) pc
& ~0x3ffffff)
163 | reloc_26_val(pc
, target
);
166 static void patch_reloc(uint8_t *code_ptr
, int type
,
167 tcg_target_long value
, tcg_target_long addend
)
172 reloc_lo16(code_ptr
, value
);
175 reloc_hi16(code_ptr
, value
);
178 reloc_pc16(code_ptr
, value
);
181 reloc_pc26(code_ptr
, value
);
188 /* maximum number of register used for input function arguments */
189 static inline int tcg_target_get_call_iarg_regs_count(int flags
)
194 /* parse target specific constraints */
195 static int target_parse_constraint(TCGArgConstraint
*ct
, const char **pct_str
)
202 ct
->ct
|= TCG_CT_REG
;
203 tcg_regset_set(ct
->u
.regs
, 0xffffffff);
206 ct
->ct
|= TCG_CT_REG
;
207 tcg_regset_clear(ct
->u
.regs
);
208 tcg_regset_set_reg(ct
->u
.regs
, TCG_REG_T9
);
210 case 'L': /* qemu_ld output arg constraint */
211 ct
->ct
|= TCG_CT_REG
;
212 tcg_regset_set(ct
->u
.regs
, 0xffffffff);
213 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_V0
);
215 case 'l': /* qemu_ld input arg constraint */
216 ct
->ct
|= TCG_CT_REG
;
217 tcg_regset_set(ct
->u
.regs
, 0xffffffff);
218 #if defined(CONFIG_SOFTMMU)
219 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_A0
);
222 case 'S': /* qemu_st constraint */
223 ct
->ct
|= TCG_CT_REG
;
224 tcg_regset_set(ct
->u
.regs
, 0xffffffff);
225 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_A0
);
226 #if defined(CONFIG_SOFTMMU)
227 # if TARGET_LONG_BITS == 64
228 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_A1
);
230 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_A2
);
234 ct
->ct
|= TCG_CT_CONST_U16
;
237 ct
->ct
|= TCG_CT_CONST_S16
;
240 /* We are cheating a bit here, using the fact that the register
241 ZERO is also the register number 0. Hence there is no need
242 to check for const_args in each instruction. */
243 ct
->ct
|= TCG_CT_CONST_ZERO
;
253 /* test if a constant matches the constraint */
254 static inline int tcg_target_const_match(tcg_target_long val
,
255 const TCGArgConstraint
*arg_ct
)
259 if (ct
& TCG_CT_CONST
)
261 else if ((ct
& TCG_CT_CONST_ZERO
) && val
== 0)
263 else if ((ct
& TCG_CT_CONST_U16
) && val
== (uint16_t)val
)
265 else if ((ct
& TCG_CT_CONST_S16
) && val
== (int16_t)val
)
271 /* instruction opcodes */
273 OPC_BEQ
= 0x04 << 26,
274 OPC_BNE
= 0x05 << 26,
275 OPC_ADDIU
= 0x09 << 26,
276 OPC_SLTI
= 0x0A << 26,
277 OPC_SLTIU
= 0x0B << 26,
278 OPC_ANDI
= 0x0C << 26,
279 OPC_ORI
= 0x0D << 26,
280 OPC_XORI
= 0x0E << 26,
281 OPC_LUI
= 0x0F << 26,
285 OPC_LBU
= 0x24 << 26,
286 OPC_LHU
= 0x25 << 26,
287 OPC_LWU
= 0x27 << 26,
292 OPC_SPECIAL
= 0x00 << 26,
293 OPC_SLL
= OPC_SPECIAL
| 0x00,
294 OPC_SRL
= OPC_SPECIAL
| 0x02,
295 OPC_SRA
= OPC_SPECIAL
| 0x03,
296 OPC_SLLV
= OPC_SPECIAL
| 0x04,
297 OPC_SRLV
= OPC_SPECIAL
| 0x06,
298 OPC_SRAV
= OPC_SPECIAL
| 0x07,
299 OPC_JR
= OPC_SPECIAL
| 0x08,
300 OPC_JALR
= OPC_SPECIAL
| 0x09,
301 OPC_MFHI
= OPC_SPECIAL
| 0x10,
302 OPC_MFLO
= OPC_SPECIAL
| 0x12,
303 OPC_MULT
= OPC_SPECIAL
| 0x18,
304 OPC_MULTU
= OPC_SPECIAL
| 0x19,
305 OPC_DIV
= OPC_SPECIAL
| 0x1A,
306 OPC_DIVU
= OPC_SPECIAL
| 0x1B,
307 OPC_ADDU
= OPC_SPECIAL
| 0x21,
308 OPC_SUBU
= OPC_SPECIAL
| 0x23,
309 OPC_AND
= OPC_SPECIAL
| 0x24,
310 OPC_OR
= OPC_SPECIAL
| 0x25,
311 OPC_XOR
= OPC_SPECIAL
| 0x26,
312 OPC_NOR
= OPC_SPECIAL
| 0x27,
313 OPC_SLT
= OPC_SPECIAL
| 0x2A,
314 OPC_SLTU
= OPC_SPECIAL
| 0x2B,
316 OPC_SPECIAL3
= 0x1f << 26,
317 OPC_SEB
= OPC_SPECIAL3
| 0x420,
318 OPC_SEH
= OPC_SPECIAL3
| 0x620,
324 static inline void tcg_out_opc_reg(TCGContext
*s
, int opc
, int rd
, int rs
, int rt
)
329 inst
|= (rs
& 0x1F) << 21;
330 inst
|= (rt
& 0x1F) << 16;
331 inst
|= (rd
& 0x1F) << 11;
338 static inline void tcg_out_opc_imm(TCGContext
*s
, int opc
, int rt
, int rs
, int imm
)
343 inst
|= (rs
& 0x1F) << 21;
344 inst
|= (rt
& 0x1F) << 16;
345 inst
|= (imm
& 0xffff);
352 static inline void tcg_out_opc_br(TCGContext
*s
, int opc
, int rt
, int rs
)
354 /* We pay attention here to not modify the branch target by reading
355 the existing value and using it again. This ensure that caches and
356 memory are kept coherent during retranslation. */
357 uint16_t offset
= (uint16_t)(*(uint32_t *) s
->code_ptr
);
359 tcg_out_opc_imm(s
, opc
, rt
, rs
, offset
);
365 static inline void tcg_out_opc_sa(TCGContext
*s
, int opc
, int rd
, int rt
, int sa
)
370 inst
|= (rt
& 0x1F) << 16;
371 inst
|= (rd
& 0x1F) << 11;
372 inst
|= (sa
& 0x1F) << 6;
377 static inline void tcg_out_nop(TCGContext
*s
)
382 static inline void tcg_out_mov(TCGContext
*s
, TCGType type
,
383 TCGReg ret
, TCGReg arg
)
385 tcg_out_opc_reg(s
, OPC_ADDU
, ret
, arg
, TCG_REG_ZERO
);
388 static inline void tcg_out_movi(TCGContext
*s
, TCGType type
,
389 TCGReg reg
, tcg_target_long arg
)
391 if (arg
== (int16_t)arg
) {
392 tcg_out_opc_imm(s
, OPC_ADDIU
, reg
, TCG_REG_ZERO
, arg
);
393 } else if (arg
== (uint16_t)arg
) {
394 tcg_out_opc_imm(s
, OPC_ORI
, reg
, TCG_REG_ZERO
, arg
);
396 tcg_out_opc_imm(s
, OPC_LUI
, reg
, 0, arg
>> 16);
397 tcg_out_opc_imm(s
, OPC_ORI
, reg
, reg
, arg
& 0xffff);
401 static inline void tcg_out_bswap16(TCGContext
*s
, int ret
, int arg
)
403 /* ret and arg can't be register at */
404 if (ret
== TCG_REG_AT
|| arg
== TCG_REG_AT
) {
408 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_AT
, arg
, 8);
409 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_AT
, TCG_REG_AT
, 0x00ff);
411 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 8);
412 tcg_out_opc_imm(s
, OPC_ANDI
, ret
, ret
, 0xff00);
413 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
416 static inline void tcg_out_bswap16s(TCGContext
*s
, int ret
, int arg
)
418 /* ret and arg can't be register at */
419 if (ret
== TCG_REG_AT
|| arg
== TCG_REG_AT
) {
423 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_AT
, arg
, 8);
424 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_AT
, TCG_REG_AT
, 0xff);
426 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 24);
427 tcg_out_opc_sa(s
, OPC_SRA
, ret
, ret
, 16);
428 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
431 static inline void tcg_out_bswap32(TCGContext
*s
, int ret
, int arg
)
433 /* ret and arg must be different and can't be register at */
434 if (ret
== arg
|| ret
== TCG_REG_AT
|| arg
== TCG_REG_AT
) {
438 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 24);
440 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_AT
, arg
, 24);
441 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
443 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_AT
, arg
, 0xff00);
444 tcg_out_opc_sa(s
, OPC_SLL
, TCG_REG_AT
, TCG_REG_AT
, 8);
445 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
447 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_AT
, arg
, 8);
448 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_AT
, TCG_REG_AT
, 0xff00);
449 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
452 static inline void tcg_out_ext8s(TCGContext
*s
, int ret
, int arg
)
454 #ifdef _MIPS_ARCH_MIPS32R2
455 tcg_out_opc_reg(s
, OPC_SEB
, ret
, 0, arg
);
457 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 24);
458 tcg_out_opc_sa(s
, OPC_SRA
, ret
, ret
, 24);
462 static inline void tcg_out_ext16s(TCGContext
*s
, int ret
, int arg
)
464 #ifdef _MIPS_ARCH_MIPS32R2
465 tcg_out_opc_reg(s
, OPC_SEH
, ret
, 0, arg
);
467 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 16);
468 tcg_out_opc_sa(s
, OPC_SRA
, ret
, ret
, 16);
472 static inline void tcg_out_ldst(TCGContext
*s
, int opc
, int arg
,
473 int arg1
, tcg_target_long arg2
)
475 if (arg2
== (int16_t) arg2
) {
476 tcg_out_opc_imm(s
, opc
, arg
, arg1
, arg2
);
478 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_AT
, arg2
);
479 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_AT
, TCG_REG_AT
, arg1
);
480 tcg_out_opc_imm(s
, opc
, arg
, TCG_REG_AT
, 0);
484 static inline void tcg_out_ld(TCGContext
*s
, TCGType type
, TCGReg arg
,
485 TCGReg arg1
, tcg_target_long arg2
)
487 tcg_out_ldst(s
, OPC_LW
, arg
, arg1
, arg2
);
490 static inline void tcg_out_st(TCGContext
*s
, TCGType type
, TCGReg arg
,
491 TCGReg arg1
, tcg_target_long arg2
)
493 tcg_out_ldst(s
, OPC_SW
, arg
, arg1
, arg2
);
496 static inline void tcg_out_addi(TCGContext
*s
, int reg
, tcg_target_long val
)
498 if (val
== (int16_t)val
) {
499 tcg_out_opc_imm(s
, OPC_ADDIU
, reg
, reg
, val
);
501 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_AT
, val
);
502 tcg_out_opc_reg(s
, OPC_ADDU
, reg
, reg
, TCG_REG_AT
);
506 static void tcg_out_brcond(TCGContext
*s
, TCGCond cond
, int arg1
,
507 int arg2
, int label_index
)
509 TCGLabel
*l
= &s
->labels
[label_index
];
513 tcg_out_opc_br(s
, OPC_BEQ
, arg1
, arg2
);
516 tcg_out_opc_br(s
, OPC_BNE
, arg1
, arg2
);
519 tcg_out_opc_reg(s
, OPC_SLT
, TCG_REG_AT
, arg1
, arg2
);
520 tcg_out_opc_br(s
, OPC_BNE
, TCG_REG_AT
, TCG_REG_ZERO
);
523 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_AT
, arg1
, arg2
);
524 tcg_out_opc_br(s
, OPC_BNE
, TCG_REG_AT
, TCG_REG_ZERO
);
527 tcg_out_opc_reg(s
, OPC_SLT
, TCG_REG_AT
, arg1
, arg2
);
528 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_AT
, TCG_REG_ZERO
);
531 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_AT
, arg1
, arg2
);
532 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_AT
, TCG_REG_ZERO
);
535 tcg_out_opc_reg(s
, OPC_SLT
, TCG_REG_AT
, arg2
, arg1
);
536 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_AT
, TCG_REG_ZERO
);
539 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_AT
, arg2
, arg1
);
540 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_AT
, TCG_REG_ZERO
);
543 tcg_out_opc_reg(s
, OPC_SLT
, TCG_REG_AT
, arg2
, arg1
);
544 tcg_out_opc_br(s
, OPC_BNE
, TCG_REG_AT
, TCG_REG_ZERO
);
547 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_AT
, arg2
, arg1
);
548 tcg_out_opc_br(s
, OPC_BNE
, TCG_REG_AT
, TCG_REG_ZERO
);
555 reloc_pc16(s
->code_ptr
- 4, l
->u
.value
);
557 tcg_out_reloc(s
, s
->code_ptr
- 4, R_MIPS_PC16
, label_index
, 0);
562 /* XXX: we implement it at the target level to avoid having to
563 handle cross basic blocks temporaries */
564 static void tcg_out_brcond2(TCGContext
*s
, TCGCond cond
, int arg1
,
565 int arg2
, int arg3
, int arg4
, int label_index
)
571 tcg_out_brcond(s
, TCG_COND_NE
, arg2
, arg4
, label_index
);
572 tcg_out_brcond(s
, TCG_COND_NE
, arg1
, arg3
, label_index
);
578 tcg_out_brcond(s
, TCG_COND_LT
, arg2
, arg4
, label_index
);
582 tcg_out_brcond(s
, TCG_COND_GT
, arg2
, arg4
, label_index
);
586 tcg_out_brcond(s
, TCG_COND_LTU
, arg2
, arg4
, label_index
);
590 tcg_out_brcond(s
, TCG_COND_GTU
, arg2
, arg4
, label_index
);
596 label_ptr
= s
->code_ptr
;
597 tcg_out_opc_br(s
, OPC_BNE
, arg2
, arg4
);
602 tcg_out_brcond(s
, TCG_COND_EQ
, arg1
, arg3
, label_index
);
606 tcg_out_brcond(s
, TCG_COND_LTU
, arg1
, arg3
, label_index
);
610 tcg_out_brcond(s
, TCG_COND_LEU
, arg1
, arg3
, label_index
);
614 tcg_out_brcond(s
, TCG_COND_GTU
, arg1
, arg3
, label_index
);
618 tcg_out_brcond(s
, TCG_COND_GEU
, arg1
, arg3
, label_index
);
624 reloc_pc16(label_ptr
, (tcg_target_long
) s
->code_ptr
);
627 static void tcg_out_setcond(TCGContext
*s
, TCGCond cond
, int ret
,
633 tcg_out_opc_imm(s
, OPC_SLTIU
, ret
, arg2
, 1);
634 } else if (arg2
== 0) {
635 tcg_out_opc_imm(s
, OPC_SLTIU
, ret
, arg1
, 1);
637 tcg_out_opc_reg(s
, OPC_XOR
, ret
, arg1
, arg2
);
638 tcg_out_opc_imm(s
, OPC_SLTIU
, ret
, ret
, 1);
643 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, TCG_REG_ZERO
, arg2
);
644 } else if (arg2
== 0) {
645 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, TCG_REG_ZERO
, arg1
);
647 tcg_out_opc_reg(s
, OPC_XOR
, ret
, arg1
, arg2
);
648 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, TCG_REG_ZERO
, ret
);
652 tcg_out_opc_reg(s
, OPC_SLT
, ret
, arg1
, arg2
);
655 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, arg1
, arg2
);
658 tcg_out_opc_reg(s
, OPC_SLT
, ret
, arg1
, arg2
);
659 tcg_out_opc_imm(s
, OPC_XORI
, ret
, ret
, 1);
662 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, arg1
, arg2
);
663 tcg_out_opc_imm(s
, OPC_XORI
, ret
, ret
, 1);
666 tcg_out_opc_reg(s
, OPC_SLT
, ret
, arg2
, arg1
);
667 tcg_out_opc_imm(s
, OPC_XORI
, ret
, ret
, 1);
670 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, arg2
, arg1
);
671 tcg_out_opc_imm(s
, OPC_XORI
, ret
, ret
, 1);
674 tcg_out_opc_reg(s
, OPC_SLT
, ret
, arg2
, arg1
);
677 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, arg2
, arg1
);
685 /* XXX: we implement it at the target level to avoid having to
686 handle cross basic blocks temporaries */
687 static void tcg_out_setcond2(TCGContext
*s
, TCGCond cond
, int ret
,
688 int arg1
, int arg2
, int arg3
, int arg4
)
692 tcg_out_setcond(s
, TCG_COND_EQ
, TCG_REG_AT
, arg2
, arg4
);
693 tcg_out_setcond(s
, TCG_COND_EQ
, TCG_REG_T0
, arg1
, arg3
);
694 tcg_out_opc_reg(s
, OPC_AND
, ret
, TCG_REG_AT
, TCG_REG_T0
);
697 tcg_out_setcond(s
, TCG_COND_NE
, TCG_REG_AT
, arg2
, arg4
);
698 tcg_out_setcond(s
, TCG_COND_NE
, TCG_REG_T0
, arg1
, arg3
);
699 tcg_out_opc_reg(s
, OPC_OR
, ret
, TCG_REG_AT
, TCG_REG_T0
);
703 tcg_out_setcond(s
, TCG_COND_LT
, TCG_REG_AT
, arg2
, arg4
);
707 tcg_out_setcond(s
, TCG_COND_GT
, TCG_REG_AT
, arg2
, arg4
);
711 tcg_out_setcond(s
, TCG_COND_LTU
, TCG_REG_AT
, arg2
, arg4
);
715 tcg_out_setcond(s
, TCG_COND_GTU
, TCG_REG_AT
, arg2
, arg4
);
722 tcg_out_setcond(s
, TCG_COND_EQ
, TCG_REG_T0
, arg2
, arg4
);
727 tcg_out_setcond(s
, TCG_COND_LTU
, ret
, arg1
, arg3
);
731 tcg_out_setcond(s
, TCG_COND_LEU
, ret
, arg1
, arg3
);
735 tcg_out_setcond(s
, TCG_COND_GTU
, ret
, arg1
, arg3
);
739 tcg_out_setcond(s
, TCG_COND_GEU
, ret
, arg1
, arg3
);
745 tcg_out_opc_reg(s
, OPC_AND
, ret
, ret
, TCG_REG_T0
);
746 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_REG_AT
);
749 #if defined(CONFIG_SOFTMMU)
751 #include "../../softmmu_defs.h"
753 static void *qemu_ld_helpers
[4] = {
760 static void *qemu_st_helpers
[4] = {
768 static void tcg_out_qemu_ld(TCGContext
*s
, const TCGArg
*args
,
771 int addr_regl
, addr_reg1
, addr_meml
;
772 int data_regl
, data_regh
, data_reg1
, data_reg2
;
773 int mem_index
, s_bits
;
774 #if defined(CONFIG_SOFTMMU)
775 void *label1_ptr
, *label2_ptr
;
778 #if TARGET_LONG_BITS == 64
779 # if defined(CONFIG_SOFTMMU)
782 int addr_regh
, addr_reg2
, addr_memh
;
790 #if TARGET_LONG_BITS == 64
797 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
798 data_reg1
= data_regh
;
799 data_reg2
= data_regl
;
801 data_reg1
= data_regl
;
802 data_reg2
= data_regh
;
805 data_reg1
= data_regl
;
808 #if TARGET_LONG_BITS == 64
809 # if defined(TCG_TARGET_WORDS_BIGENDIAN)
810 addr_reg1
= addr_regh
;
811 addr_reg2
= addr_regl
;
815 addr_reg1
= addr_regl
;
816 addr_reg2
= addr_regh
;
821 addr_reg1
= addr_regl
;
825 #if defined(CONFIG_SOFTMMU)
826 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_A0
, addr_regl
, TARGET_PAGE_BITS
- CPU_TLB_ENTRY_BITS
);
827 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_A0
, TCG_REG_A0
, (CPU_TLB_SIZE
- 1) << CPU_TLB_ENTRY_BITS
);
828 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_A0
, TCG_REG_A0
, TCG_AREG0
);
829 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_AT
, TCG_REG_A0
,
830 offsetof(CPUState
, tlb_table
[mem_index
][0].addr_read
) + addr_meml
);
831 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_T0
, TARGET_PAGE_MASK
| ((1 << s_bits
) - 1));
832 tcg_out_opc_reg(s
, OPC_AND
, TCG_REG_T0
, TCG_REG_T0
, addr_regl
);
834 # if TARGET_LONG_BITS == 64
835 label3_ptr
= s
->code_ptr
;
836 tcg_out_opc_br(s
, OPC_BNE
, TCG_REG_T0
, TCG_REG_AT
);
839 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_AT
, TCG_REG_A0
,
840 offsetof(CPUState
, tlb_table
[mem_index
][0].addr_read
) + addr_memh
);
842 label1_ptr
= s
->code_ptr
;
843 tcg_out_opc_br(s
, OPC_BEQ
, addr_regh
, TCG_REG_AT
);
846 reloc_pc16(label3_ptr
, (tcg_target_long
) s
->code_ptr
);
848 label1_ptr
= s
->code_ptr
;
849 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_T0
, TCG_REG_AT
);
854 sp_args
= TCG_REG_A0
;
855 tcg_out_mov(s
, TCG_TYPE_I32
, sp_args
++, addr_reg1
);
856 # if TARGET_LONG_BITS == 64
857 tcg_out_mov(s
, TCG_TYPE_I32
, sp_args
++, addr_reg2
);
859 tcg_out_movi(s
, TCG_TYPE_I32
, sp_args
++, mem_index
);
860 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_T9
, (tcg_target_long
)qemu_ld_helpers
[s_bits
]);
861 tcg_out_opc_reg(s
, OPC_JALR
, TCG_REG_RA
, TCG_REG_T9
, 0);
866 tcg_out_opc_imm(s
, OPC_ANDI
, data_reg1
, TCG_REG_V0
, 0xff);
869 tcg_out_ext8s(s
, data_reg1
, TCG_REG_V0
);
872 tcg_out_opc_imm(s
, OPC_ANDI
, data_reg1
, TCG_REG_V0
, 0xffff);
875 tcg_out_ext16s(s
, data_reg1
, TCG_REG_V0
);
878 tcg_out_mov(s
, TCG_TYPE_I32
, data_reg1
, TCG_REG_V0
);
881 tcg_out_mov(s
, TCG_TYPE_I32
, data_reg2
, TCG_REG_V1
);
882 tcg_out_mov(s
, TCG_TYPE_I32
, data_reg1
, TCG_REG_V0
);
888 label2_ptr
= s
->code_ptr
;
889 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_ZERO
, TCG_REG_ZERO
);
892 /* label1: fast path */
893 reloc_pc16(label1_ptr
, (tcg_target_long
) s
->code_ptr
);
895 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_A0
, TCG_REG_A0
,
896 offsetof(CPUState
, tlb_table
[mem_index
][0].addend
));
897 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_V0
, TCG_REG_A0
, addr_regl
);
899 if (GUEST_BASE
== (int16_t)GUEST_BASE
) {
900 tcg_out_opc_imm(s
, OPC_ADDIU
, TCG_REG_V0
, addr_regl
, GUEST_BASE
);
902 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_V0
, GUEST_BASE
);
903 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_V0
, TCG_REG_V0
, addr_regl
);
909 tcg_out_opc_imm(s
, OPC_LBU
, data_reg1
, TCG_REG_V0
, 0);
912 tcg_out_opc_imm(s
, OPC_LB
, data_reg1
, TCG_REG_V0
, 0);
915 if (TCG_NEED_BSWAP
) {
916 tcg_out_opc_imm(s
, OPC_LHU
, TCG_REG_T0
, TCG_REG_V0
, 0);
917 tcg_out_bswap16(s
, data_reg1
, TCG_REG_T0
);
919 tcg_out_opc_imm(s
, OPC_LHU
, data_reg1
, TCG_REG_V0
, 0);
923 if (TCG_NEED_BSWAP
) {
924 tcg_out_opc_imm(s
, OPC_LHU
, TCG_REG_T0
, TCG_REG_V0
, 0);
925 tcg_out_bswap16s(s
, data_reg1
, TCG_REG_T0
);
927 tcg_out_opc_imm(s
, OPC_LH
, data_reg1
, TCG_REG_V0
, 0);
931 if (TCG_NEED_BSWAP
) {
932 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_T0
, TCG_REG_V0
, 0);
933 tcg_out_bswap32(s
, data_reg1
, TCG_REG_T0
);
935 tcg_out_opc_imm(s
, OPC_LW
, data_reg1
, TCG_REG_V0
, 0);
939 if (TCG_NEED_BSWAP
) {
940 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_T0
, TCG_REG_V0
, 4);
941 tcg_out_bswap32(s
, data_reg1
, TCG_REG_T0
);
942 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_T0
, TCG_REG_V0
, 0);
943 tcg_out_bswap32(s
, data_reg2
, TCG_REG_T0
);
945 tcg_out_opc_imm(s
, OPC_LW
, data_reg1
, TCG_REG_V0
, 0);
946 tcg_out_opc_imm(s
, OPC_LW
, data_reg2
, TCG_REG_V0
, 4);
953 #if defined(CONFIG_SOFTMMU)
954 reloc_pc16(label2_ptr
, (tcg_target_long
) s
->code_ptr
);
958 static void tcg_out_qemu_st(TCGContext
*s
, const TCGArg
*args
,
961 int addr_regl
, addr_reg1
, addr_meml
;
962 int data_regl
, data_regh
, data_reg1
, data_reg2
;
963 int mem_index
, s_bits
;
964 #if defined(CONFIG_SOFTMMU)
965 uint8_t *label1_ptr
, *label2_ptr
;
968 #if TARGET_LONG_BITS == 64
969 # if defined(CONFIG_SOFTMMU)
972 int addr_regh
, addr_reg2
, addr_memh
;
978 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
979 data_reg1
= data_regh
;
980 data_reg2
= data_regl
;
982 data_reg1
= data_regl
;
983 data_reg2
= data_regh
;
986 data_reg1
= data_regl
;
991 #if TARGET_LONG_BITS == 64
993 # if defined(TCG_TARGET_WORDS_BIGENDIAN)
994 addr_reg1
= addr_regh
;
995 addr_reg2
= addr_regl
;
999 addr_reg1
= addr_regl
;
1000 addr_reg2
= addr_regh
;
1005 addr_reg1
= addr_regl
;
1011 #if defined(CONFIG_SOFTMMU)
1012 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_A0
, addr_regl
, TARGET_PAGE_BITS
- CPU_TLB_ENTRY_BITS
);
1013 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_A0
, TCG_REG_A0
, (CPU_TLB_SIZE
- 1) << CPU_TLB_ENTRY_BITS
);
1014 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_A0
, TCG_REG_A0
, TCG_AREG0
);
1015 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_AT
, TCG_REG_A0
,
1016 offsetof(CPUState
, tlb_table
[mem_index
][0].addr_write
) + addr_meml
);
1017 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_T0
, TARGET_PAGE_MASK
| ((1 << s_bits
) - 1));
1018 tcg_out_opc_reg(s
, OPC_AND
, TCG_REG_T0
, TCG_REG_T0
, addr_regl
);
1020 # if TARGET_LONG_BITS == 64
1021 label3_ptr
= s
->code_ptr
;
1022 tcg_out_opc_br(s
, OPC_BNE
, TCG_REG_T0
, TCG_REG_AT
);
1025 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_AT
, TCG_REG_A0
,
1026 offsetof(CPUState
, tlb_table
[mem_index
][0].addr_write
) + addr_memh
);
1028 label1_ptr
= s
->code_ptr
;
1029 tcg_out_opc_br(s
, OPC_BEQ
, addr_regh
, TCG_REG_AT
);
1032 reloc_pc16(label3_ptr
, (tcg_target_long
) s
->code_ptr
);
1034 label1_ptr
= s
->code_ptr
;
1035 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_T0
, TCG_REG_AT
);
1040 sp_args
= TCG_REG_A0
;
1041 tcg_out_mov(s
, TCG_TYPE_I32
, sp_args
++, addr_reg1
);
1042 # if TARGET_LONG_BITS == 64
1043 tcg_out_mov(s
, TCG_TYPE_I32
, sp_args
++, addr_reg2
);
1047 tcg_out_opc_imm(s
, OPC_ANDI
, sp_args
++, data_reg1
, 0xff);
1050 tcg_out_opc_imm(s
, OPC_ANDI
, sp_args
++, data_reg1
, 0xffff);
1053 tcg_out_mov(s
, TCG_TYPE_I32
, sp_args
++, data_reg1
);
1056 sp_args
= (sp_args
+ 1) & ~1;
1057 tcg_out_mov(s
, TCG_TYPE_I32
, sp_args
++, data_reg1
);
1058 tcg_out_mov(s
, TCG_TYPE_I32
, sp_args
++, data_reg2
);
1063 if (sp_args
> TCG_REG_A3
) {
1064 /* Push mem_index on the stack */
1065 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_AT
, mem_index
);
1066 tcg_out_st(s
, TCG_TYPE_I32
, TCG_REG_AT
, TCG_REG_SP
, 16);
1068 tcg_out_movi(s
, TCG_TYPE_I32
, sp_args
, mem_index
);
1071 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_T9
, (tcg_target_long
)qemu_st_helpers
[s_bits
]);
1072 tcg_out_opc_reg(s
, OPC_JALR
, TCG_REG_RA
, TCG_REG_T9
, 0);
1075 label2_ptr
= s
->code_ptr
;
1076 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_ZERO
, TCG_REG_ZERO
);
1079 /* label1: fast path */
1080 reloc_pc16(label1_ptr
, (tcg_target_long
) s
->code_ptr
);
1082 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_A0
, TCG_REG_A0
,
1083 offsetof(CPUState
, tlb_table
[mem_index
][0].addend
));
1084 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_A0
, TCG_REG_A0
, addr_regl
);
1086 if (GUEST_BASE
== (int16_t)GUEST_BASE
) {
1087 tcg_out_opc_imm(s
, OPC_ADDIU
, TCG_REG_A0
, addr_regl
, GUEST_BASE
);
1089 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_A0
, GUEST_BASE
);
1090 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_A0
, TCG_REG_A0
, addr_regl
);
1097 tcg_out_opc_imm(s
, OPC_SB
, data_reg1
, TCG_REG_A0
, 0);
1100 if (TCG_NEED_BSWAP
) {
1101 tcg_out_bswap16(s
, TCG_REG_T0
, data_reg1
);
1102 tcg_out_opc_imm(s
, OPC_SH
, TCG_REG_T0
, TCG_REG_A0
, 0);
1104 tcg_out_opc_imm(s
, OPC_SH
, data_reg1
, TCG_REG_A0
, 0);
1108 if (TCG_NEED_BSWAP
) {
1109 tcg_out_bswap32(s
, TCG_REG_T0
, data_reg1
);
1110 tcg_out_opc_imm(s
, OPC_SW
, TCG_REG_T0
, TCG_REG_A0
, 0);
1112 tcg_out_opc_imm(s
, OPC_SW
, data_reg1
, TCG_REG_A0
, 0);
1116 if (TCG_NEED_BSWAP
) {
1117 tcg_out_bswap32(s
, TCG_REG_T0
, data_reg2
);
1118 tcg_out_opc_imm(s
, OPC_SW
, TCG_REG_T0
, TCG_REG_A0
, 0);
1119 tcg_out_bswap32(s
, TCG_REG_T0
, data_reg1
);
1120 tcg_out_opc_imm(s
, OPC_SW
, TCG_REG_T0
, TCG_REG_A0
, 4);
1122 tcg_out_opc_imm(s
, OPC_SW
, data_reg1
, TCG_REG_A0
, 0);
1123 tcg_out_opc_imm(s
, OPC_SW
, data_reg2
, TCG_REG_A0
, 4);
1130 #if defined(CONFIG_SOFTMMU)
1131 reloc_pc16(label2_ptr
, (tcg_target_long
) s
->code_ptr
);
1135 static inline void tcg_out_op(TCGContext
*s
, TCGOpcode opc
,
1136 const TCGArg
*args
, const int *const_args
)
1139 case INDEX_op_exit_tb
:
1140 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_V0
, args
[0]);
1141 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_AT
, (tcg_target_long
)tb_ret_addr
);
1142 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_AT
, 0);
1145 case INDEX_op_goto_tb
:
1146 if (s
->tb_jmp_offset
) {
1147 /* direct jump method */
1150 /* indirect jump method */
1151 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_AT
, (tcg_target_long
)(s
->tb_next
+ args
[0]));
1152 tcg_out_ld(s
, TCG_TYPE_PTR
, TCG_REG_AT
, TCG_REG_AT
, 0);
1153 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_AT
, 0);
1156 s
->tb_next_offset
[args
[0]] = s
->code_ptr
- s
->code_buf
;
1159 tcg_out_opc_reg(s
, OPC_JALR
, TCG_REG_RA
, args
[0], 0);
1163 tcg_out_opc_reg(s
, OPC_JR
, 0, args
[0], 0);
1167 tcg_out_brcond(s
, TCG_COND_EQ
, TCG_REG_ZERO
, TCG_REG_ZERO
, args
[0]);
1170 case INDEX_op_mov_i32
:
1171 tcg_out_mov(s
, TCG_TYPE_I32
, args
[0], args
[1]);
1173 case INDEX_op_movi_i32
:
1174 tcg_out_movi(s
, TCG_TYPE_I32
, args
[0], args
[1]);
1177 case INDEX_op_ld8u_i32
:
1178 tcg_out_ldst(s
, OPC_LBU
, args
[0], args
[1], args
[2]);
1180 case INDEX_op_ld8s_i32
:
1181 tcg_out_ldst(s
, OPC_LB
, args
[0], args
[1], args
[2]);
1183 case INDEX_op_ld16u_i32
:
1184 tcg_out_ldst(s
, OPC_LHU
, args
[0], args
[1], args
[2]);
1186 case INDEX_op_ld16s_i32
:
1187 tcg_out_ldst(s
, OPC_LH
, args
[0], args
[1], args
[2]);
1189 case INDEX_op_ld_i32
:
1190 tcg_out_ldst(s
, OPC_LW
, args
[0], args
[1], args
[2]);
1192 case INDEX_op_st8_i32
:
1193 tcg_out_ldst(s
, OPC_SB
, args
[0], args
[1], args
[2]);
1195 case INDEX_op_st16_i32
:
1196 tcg_out_ldst(s
, OPC_SH
, args
[0], args
[1], args
[2]);
1198 case INDEX_op_st_i32
:
1199 tcg_out_ldst(s
, OPC_SW
, args
[0], args
[1], args
[2]);
1202 case INDEX_op_add_i32
:
1203 if (const_args
[2]) {
1204 tcg_out_opc_imm(s
, OPC_ADDIU
, args
[0], args
[1], args
[2]);
1206 tcg_out_opc_reg(s
, OPC_ADDU
, args
[0], args
[1], args
[2]);
1209 case INDEX_op_add2_i32
:
1210 if (const_args
[4]) {
1211 tcg_out_opc_imm(s
, OPC_ADDIU
, TCG_REG_AT
, args
[2], args
[4]);
1213 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_AT
, args
[2], args
[4]);
1215 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_T0
, TCG_REG_AT
, args
[2]);
1216 if (const_args
[5]) {
1217 tcg_out_opc_imm(s
, OPC_ADDIU
, args
[1], args
[3], args
[5]);
1219 tcg_out_opc_reg(s
, OPC_ADDU
, args
[1], args
[3], args
[5]);
1221 tcg_out_opc_reg(s
, OPC_ADDU
, args
[1], args
[1], TCG_REG_T0
);
1222 tcg_out_mov(s
, TCG_TYPE_I32
, args
[0], TCG_REG_AT
);
1224 case INDEX_op_sub_i32
:
1225 if (const_args
[2]) {
1226 tcg_out_opc_imm(s
, OPC_ADDIU
, args
[0], args
[1], -args
[2]);
1228 tcg_out_opc_reg(s
, OPC_SUBU
, args
[0], args
[1], args
[2]);
1231 case INDEX_op_sub2_i32
:
1232 if (const_args
[4]) {
1233 tcg_out_opc_imm(s
, OPC_ADDIU
, TCG_REG_AT
, args
[2], -args
[4]);
1235 tcg_out_opc_reg(s
, OPC_SUBU
, TCG_REG_AT
, args
[2], args
[4]);
1237 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_REG_T0
, args
[2], TCG_REG_AT
);
1238 if (const_args
[5]) {
1239 tcg_out_opc_imm(s
, OPC_ADDIU
, args
[1], args
[3], -args
[5]);
1241 tcg_out_opc_reg(s
, OPC_SUBU
, args
[1], args
[3], args
[5]);
1243 tcg_out_opc_reg(s
, OPC_SUBU
, args
[1], args
[1], TCG_REG_T0
);
1244 tcg_out_mov(s
, TCG_TYPE_I32
, args
[0], TCG_REG_AT
);
1246 case INDEX_op_mul_i32
:
1247 tcg_out_opc_reg(s
, OPC_MULT
, 0, args
[1], args
[2]);
1248 tcg_out_opc_reg(s
, OPC_MFLO
, args
[0], 0, 0);
1250 case INDEX_op_mulu2_i32
:
1251 tcg_out_opc_reg(s
, OPC_MULTU
, 0, args
[2], args
[3]);
1252 tcg_out_opc_reg(s
, OPC_MFLO
, args
[0], 0, 0);
1253 tcg_out_opc_reg(s
, OPC_MFHI
, args
[1], 0, 0);
1255 case INDEX_op_div_i32
:
1256 tcg_out_opc_reg(s
, OPC_DIV
, 0, args
[1], args
[2]);
1257 tcg_out_opc_reg(s
, OPC_MFLO
, args
[0], 0, 0);
1259 case INDEX_op_divu_i32
:
1260 tcg_out_opc_reg(s
, OPC_DIVU
, 0, args
[1], args
[2]);
1261 tcg_out_opc_reg(s
, OPC_MFLO
, args
[0], 0, 0);
1263 case INDEX_op_rem_i32
:
1264 tcg_out_opc_reg(s
, OPC_DIV
, 0, args
[1], args
[2]);
1265 tcg_out_opc_reg(s
, OPC_MFHI
, args
[0], 0, 0);
1267 case INDEX_op_remu_i32
:
1268 tcg_out_opc_reg(s
, OPC_DIVU
, 0, args
[1], args
[2]);
1269 tcg_out_opc_reg(s
, OPC_MFHI
, args
[0], 0, 0);
1272 case INDEX_op_and_i32
:
1273 if (const_args
[2]) {
1274 tcg_out_opc_imm(s
, OPC_ANDI
, args
[0], args
[1], args
[2]);
1276 tcg_out_opc_reg(s
, OPC_AND
, args
[0], args
[1], args
[2]);
1279 case INDEX_op_or_i32
:
1280 if (const_args
[2]) {
1281 tcg_out_opc_imm(s
, OPC_ORI
, args
[0], args
[1], args
[2]);
1283 tcg_out_opc_reg(s
, OPC_OR
, args
[0], args
[1], args
[2]);
1286 case INDEX_op_nor_i32
:
1287 tcg_out_opc_reg(s
, OPC_NOR
, args
[0], args
[1], args
[2]);
1289 case INDEX_op_not_i32
:
1290 tcg_out_opc_reg(s
, OPC_NOR
, args
[0], TCG_REG_ZERO
, args
[1]);
1292 case INDEX_op_xor_i32
:
1293 if (const_args
[2]) {
1294 tcg_out_opc_imm(s
, OPC_XORI
, args
[0], args
[1], args
[2]);
1296 tcg_out_opc_reg(s
, OPC_XOR
, args
[0], args
[1], args
[2]);
1300 case INDEX_op_sar_i32
:
1301 if (const_args
[2]) {
1302 tcg_out_opc_sa(s
, OPC_SRA
, args
[0], args
[1], args
[2]);
1304 tcg_out_opc_reg(s
, OPC_SRAV
, args
[0], args
[2], args
[1]);
1307 case INDEX_op_shl_i32
:
1308 if (const_args
[2]) {
1309 tcg_out_opc_sa(s
, OPC_SLL
, args
[0], args
[1], args
[2]);
1311 tcg_out_opc_reg(s
, OPC_SLLV
, args
[0], args
[2], args
[1]);
1314 case INDEX_op_shr_i32
:
1315 if (const_args
[2]) {
1316 tcg_out_opc_sa(s
, OPC_SRL
, args
[0], args
[1], args
[2]);
1318 tcg_out_opc_reg(s
, OPC_SRLV
, args
[0], args
[2], args
[1]);
1322 case INDEX_op_ext8s_i32
:
1323 tcg_out_ext8s(s
, args
[0], args
[1]);
1325 case INDEX_op_ext16s_i32
:
1326 tcg_out_ext16s(s
, args
[0], args
[1]);
1329 case INDEX_op_brcond_i32
:
1330 tcg_out_brcond(s
, args
[2], args
[0], args
[1], args
[3]);
1332 case INDEX_op_brcond2_i32
:
1333 tcg_out_brcond2(s
, args
[4], args
[0], args
[1], args
[2], args
[3], args
[5]);
1336 case INDEX_op_setcond_i32
:
1337 tcg_out_setcond(s
, args
[3], args
[0], args
[1], args
[2]);
1339 case INDEX_op_setcond2_i32
:
1340 tcg_out_setcond2(s
, args
[5], args
[0], args
[1], args
[2], args
[3], args
[4]);
1343 case INDEX_op_qemu_ld8u
:
1344 tcg_out_qemu_ld(s
, args
, 0);
1346 case INDEX_op_qemu_ld8s
:
1347 tcg_out_qemu_ld(s
, args
, 0 | 4);
1349 case INDEX_op_qemu_ld16u
:
1350 tcg_out_qemu_ld(s
, args
, 1);
1352 case INDEX_op_qemu_ld16s
:
1353 tcg_out_qemu_ld(s
, args
, 1 | 4);
1355 case INDEX_op_qemu_ld32
:
1356 tcg_out_qemu_ld(s
, args
, 2);
1358 case INDEX_op_qemu_ld64
:
1359 tcg_out_qemu_ld(s
, args
, 3);
1361 case INDEX_op_qemu_st8
:
1362 tcg_out_qemu_st(s
, args
, 0);
1364 case INDEX_op_qemu_st16
:
1365 tcg_out_qemu_st(s
, args
, 1);
1367 case INDEX_op_qemu_st32
:
1368 tcg_out_qemu_st(s
, args
, 2);
1370 case INDEX_op_qemu_st64
:
1371 tcg_out_qemu_st(s
, args
, 3);
1379 static const TCGTargetOpDef mips_op_defs
[] = {
1380 { INDEX_op_exit_tb
, { } },
1381 { INDEX_op_goto_tb
, { } },
1382 { INDEX_op_call
, { "C" } },
1383 { INDEX_op_jmp
, { "r" } },
1384 { INDEX_op_br
, { } },
1386 { INDEX_op_mov_i32
, { "r", "r" } },
1387 { INDEX_op_movi_i32
, { "r" } },
1388 { INDEX_op_ld8u_i32
, { "r", "r" } },
1389 { INDEX_op_ld8s_i32
, { "r", "r" } },
1390 { INDEX_op_ld16u_i32
, { "r", "r" } },
1391 { INDEX_op_ld16s_i32
, { "r", "r" } },
1392 { INDEX_op_ld_i32
, { "r", "r" } },
1393 { INDEX_op_st8_i32
, { "rZ", "r" } },
1394 { INDEX_op_st16_i32
, { "rZ", "r" } },
1395 { INDEX_op_st_i32
, { "rZ", "r" } },
1397 { INDEX_op_add_i32
, { "r", "rZ", "rJZ" } },
1398 { INDEX_op_mul_i32
, { "r", "rZ", "rZ" } },
1399 { INDEX_op_mulu2_i32
, { "r", "r", "rZ", "rZ" } },
1400 { INDEX_op_div_i32
, { "r", "rZ", "rZ" } },
1401 { INDEX_op_divu_i32
, { "r", "rZ", "rZ" } },
1402 { INDEX_op_rem_i32
, { "r", "rZ", "rZ" } },
1403 { INDEX_op_remu_i32
, { "r", "rZ", "rZ" } },
1404 { INDEX_op_sub_i32
, { "r", "rZ", "rJZ" } },
1406 { INDEX_op_and_i32
, { "r", "rZ", "rIZ" } },
1407 { INDEX_op_nor_i32
, { "r", "rZ", "rZ" } },
1408 { INDEX_op_not_i32
, { "r", "rZ" } },
1409 { INDEX_op_or_i32
, { "r", "rZ", "rIZ" } },
1410 { INDEX_op_xor_i32
, { "r", "rZ", "rIZ" } },
1412 { INDEX_op_shl_i32
, { "r", "rZ", "riZ" } },
1413 { INDEX_op_shr_i32
, { "r", "rZ", "riZ" } },
1414 { INDEX_op_sar_i32
, { "r", "rZ", "riZ" } },
1416 { INDEX_op_ext8s_i32
, { "r", "rZ" } },
1417 { INDEX_op_ext16s_i32
, { "r", "rZ" } },
1419 { INDEX_op_brcond_i32
, { "rZ", "rZ" } },
1420 { INDEX_op_setcond_i32
, { "r", "rZ", "rZ" } },
1421 { INDEX_op_setcond2_i32
, { "r", "rZ", "rZ", "rZ", "rZ" } },
1423 { INDEX_op_add2_i32
, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1424 { INDEX_op_sub2_i32
, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1425 { INDEX_op_brcond2_i32
, { "rZ", "rZ", "rZ", "rZ" } },
1427 #if TARGET_LONG_BITS == 32
1428 { INDEX_op_qemu_ld8u
, { "L", "lZ" } },
1429 { INDEX_op_qemu_ld8s
, { "L", "lZ" } },
1430 { INDEX_op_qemu_ld16u
, { "L", "lZ" } },
1431 { INDEX_op_qemu_ld16s
, { "L", "lZ" } },
1432 { INDEX_op_qemu_ld32
, { "L", "lZ" } },
1433 { INDEX_op_qemu_ld64
, { "L", "L", "lZ" } },
1435 { INDEX_op_qemu_st8
, { "SZ", "SZ" } },
1436 { INDEX_op_qemu_st16
, { "SZ", "SZ" } },
1437 { INDEX_op_qemu_st32
, { "SZ", "SZ" } },
1438 { INDEX_op_qemu_st64
, { "SZ", "SZ", "SZ" } },
1440 { INDEX_op_qemu_ld8u
, { "L", "lZ", "lZ" } },
1441 { INDEX_op_qemu_ld8s
, { "L", "lZ", "lZ" } },
1442 { INDEX_op_qemu_ld16u
, { "L", "lZ", "lZ" } },
1443 { INDEX_op_qemu_ld16s
, { "L", "lZ", "lZ" } },
1444 { INDEX_op_qemu_ld32
, { "L", "lZ", "lZ" } },
1445 { INDEX_op_qemu_ld64
, { "L", "L", "lZ", "lZ" } },
1447 { INDEX_op_qemu_st8
, { "SZ", "SZ", "SZ" } },
1448 { INDEX_op_qemu_st16
, { "SZ", "SZ", "SZ" } },
1449 { INDEX_op_qemu_st32
, { "SZ", "SZ", "SZ" } },
1450 { INDEX_op_qemu_st64
, { "SZ", "SZ", "SZ", "SZ" } },
1455 static int tcg_target_callee_save_regs
[] = {
1456 TCG_REG_S0
, /* used for the global env (TCG_AREG0) */
1466 TCG_REG_RA
, /* should be last for ABI compliance */
1469 /* Generate global QEMU prologue and epilogue code */
1470 static void tcg_target_qemu_prologue(TCGContext
*s
)
1474 /* reserve some stack space */
1475 frame_size
= ARRAY_SIZE(tcg_target_callee_save_regs
) * 4
1476 + TCG_STATIC_CALL_ARGS_SIZE
;
1477 frame_size
= (frame_size
+ TCG_TARGET_STACK_ALIGN
- 1) &
1478 ~(TCG_TARGET_STACK_ALIGN
- 1);
1481 tcg_out_addi(s
, TCG_REG_SP
, -frame_size
);
1482 for(i
= 0 ; i
< ARRAY_SIZE(tcg_target_callee_save_regs
) ; i
++) {
1483 tcg_out_st(s
, TCG_TYPE_I32
, tcg_target_callee_save_regs
[i
],
1484 TCG_REG_SP
, TCG_STATIC_CALL_ARGS_SIZE
+ i
* 4);
1487 /* Call generated code */
1488 tcg_out_opc_reg(s
, OPC_JR
, 0, tcg_target_call_iarg_regs
[1], 0);
1489 tcg_out_mov(s
, TCG_TYPE_PTR
, TCG_AREG0
, tcg_target_call_iarg_regs
[0]);
1490 tb_ret_addr
= s
->code_ptr
;
1493 for(i
= 0 ; i
< ARRAY_SIZE(tcg_target_callee_save_regs
) ; i
++) {
1494 tcg_out_ld(s
, TCG_TYPE_I32
, tcg_target_callee_save_regs
[i
],
1495 TCG_REG_SP
, TCG_STATIC_CALL_ARGS_SIZE
+ i
* 4);
1498 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_RA
, 0);
1499 tcg_out_addi(s
, TCG_REG_SP
, frame_size
);
1502 static void tcg_target_init(TCGContext
*s
)
1504 tcg_regset_set(tcg_target_available_regs
[TCG_TYPE_I32
], 0xffffffff);
1505 tcg_regset_set(tcg_target_call_clobber_regs
,
1522 tcg_regset_clear(s
->reserved_regs
);
1523 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_ZERO
); /* zero register */
1524 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_K0
); /* kernel use only */
1525 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_K1
); /* kernel use only */
1526 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_AT
); /* internal use */
1527 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_T0
); /* internal use */
1528 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_RA
); /* return address */
1529 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_SP
); /* stack pointer */
1531 tcg_add_target_add_op_defs(mips_op_defs
);
1532 tcg_set_frame(s
, TCG_AREG0
, offsetof(CPUState
, temp_buf
),
1533 CPU_TEMP_BUF_NLONGS
* sizeof(long));