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 #include "tcg-be-ldst.h"
29 #ifdef HOST_WORDS_BIGENDIAN
35 #define LO_OFF (MIPS_BE * 4)
36 #define HI_OFF (4 - LO_OFF)
38 #ifdef CONFIG_DEBUG_TCG
39 static const char * const tcg_target_reg_names
[TCG_TARGET_NB_REGS
] = {
75 #define TCG_TMP0 TCG_REG_AT
76 #define TCG_TMP1 TCG_REG_T9
78 /* check if we really need so many registers :P */
79 static const int tcg_target_reg_alloc_order
[] = {
80 /* Call saved registers. */
91 /* Call clobbered registers. */
105 /* Argument registers, opposite order of allocation. */
112 static const TCGReg tcg_target_call_iarg_regs
[4] = {
119 static const TCGReg tcg_target_call_oarg_regs
[2] = {
124 static tcg_insn_unit
*tb_ret_addr
;
126 static inline uint32_t reloc_pc16_val(tcg_insn_unit
*pc
, tcg_insn_unit
*target
)
128 /* Let the compiler perform the right-shift as part of the arithmetic. */
129 ptrdiff_t disp
= target
- (pc
+ 1);
130 tcg_debug_assert(disp
== (int16_t)disp
);
131 return disp
& 0xffff;
134 static inline void reloc_pc16(tcg_insn_unit
*pc
, tcg_insn_unit
*target
)
136 *pc
= deposit32(*pc
, 0, 16, reloc_pc16_val(pc
, target
));
139 static inline uint32_t reloc_26_val(tcg_insn_unit
*pc
, tcg_insn_unit
*target
)
141 tcg_debug_assert((((uintptr_t)pc
^ (uintptr_t)target
) & 0xf0000000) == 0);
142 return ((uintptr_t)target
>> 2) & 0x3ffffff;
145 static inline void reloc_26(tcg_insn_unit
*pc
, tcg_insn_unit
*target
)
147 *pc
= deposit32(*pc
, 0, 26, reloc_26_val(pc
, target
));
150 static void patch_reloc(tcg_insn_unit
*code_ptr
, int type
,
151 intptr_t value
, intptr_t addend
)
153 tcg_debug_assert(type
== R_MIPS_PC16
);
154 tcg_debug_assert(addend
== 0);
155 reloc_pc16(code_ptr
, (tcg_insn_unit
*)value
);
158 #define TCG_CT_CONST_ZERO 0x100
159 #define TCG_CT_CONST_U16 0x200 /* Unsigned 16-bit: 0 - 0xffff. */
160 #define TCG_CT_CONST_S16 0x400 /* Signed 16-bit: -32768 - 32767 */
161 #define TCG_CT_CONST_P2M1 0x800 /* Power of 2 minus 1. */
162 #define TCG_CT_CONST_N16 0x1000 /* "Negatable" 16-bit: -32767 - 32767 */
164 static inline bool is_p2m1(tcg_target_long val
)
166 return val
&& ((val
+ 1) & val
) == 0;
169 /* parse target specific constraints */
170 static int target_parse_constraint(TCGArgConstraint
*ct
, const char **pct_str
)
177 ct
->ct
|= TCG_CT_REG
;
178 tcg_regset_set(ct
->u
.regs
, 0xffffffff);
180 case 'L': /* qemu_ld output arg constraint */
181 ct
->ct
|= TCG_CT_REG
;
182 tcg_regset_set(ct
->u
.regs
, 0xffffffff);
183 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_V0
);
185 case 'l': /* qemu_ld input arg constraint */
186 ct
->ct
|= TCG_CT_REG
;
187 tcg_regset_set(ct
->u
.regs
, 0xffffffff);
188 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_A0
);
189 #if defined(CONFIG_SOFTMMU)
190 if (TARGET_LONG_BITS
== 64) {
191 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_A2
);
195 case 'S': /* qemu_st constraint */
196 ct
->ct
|= TCG_CT_REG
;
197 tcg_regset_set(ct
->u
.regs
, 0xffffffff);
198 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_A0
);
199 #if defined(CONFIG_SOFTMMU)
200 if (TARGET_LONG_BITS
== 32) {
201 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_A1
);
203 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_A2
);
204 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_A3
);
209 ct
->ct
|= TCG_CT_CONST_U16
;
212 ct
->ct
|= TCG_CT_CONST_S16
;
215 ct
->ct
|= TCG_CT_CONST_P2M1
;
218 ct
->ct
|= TCG_CT_CONST_N16
;
221 /* We are cheating a bit here, using the fact that the register
222 ZERO is also the register number 0. Hence there is no need
223 to check for const_args in each instruction. */
224 ct
->ct
|= TCG_CT_CONST_ZERO
;
234 /* test if a constant matches the constraint */
235 static inline int tcg_target_const_match(tcg_target_long val
, TCGType type
,
236 const TCGArgConstraint
*arg_ct
)
240 if (ct
& TCG_CT_CONST
) {
242 } else if ((ct
& TCG_CT_CONST_ZERO
) && val
== 0) {
244 } else if ((ct
& TCG_CT_CONST_U16
) && val
== (uint16_t)val
) {
246 } else if ((ct
& TCG_CT_CONST_S16
) && val
== (int16_t)val
) {
248 } else if ((ct
& TCG_CT_CONST_N16
) && val
>= -32767 && val
<= 32767) {
250 } else if ((ct
& TCG_CT_CONST_P2M1
)
251 && use_mips32r2_instructions
&& is_p2m1(val
)) {
257 /* instruction opcodes */
260 OPC_JAL
= 0x03 << 26,
261 OPC_BEQ
= 0x04 << 26,
262 OPC_BNE
= 0x05 << 26,
263 OPC_BLEZ
= 0x06 << 26,
264 OPC_BGTZ
= 0x07 << 26,
265 OPC_ADDIU
= 0x09 << 26,
266 OPC_SLTI
= 0x0A << 26,
267 OPC_SLTIU
= 0x0B << 26,
268 OPC_ANDI
= 0x0C << 26,
269 OPC_ORI
= 0x0D << 26,
270 OPC_XORI
= 0x0E << 26,
271 OPC_LUI
= 0x0F << 26,
275 OPC_LBU
= 0x24 << 26,
276 OPC_LHU
= 0x25 << 26,
277 OPC_LWU
= 0x27 << 26,
282 OPC_SPECIAL
= 0x00 << 26,
283 OPC_SLL
= OPC_SPECIAL
| 0x00,
284 OPC_SRL
= OPC_SPECIAL
| 0x02,
285 OPC_ROTR
= OPC_SPECIAL
| (0x01 << 21) | 0x02,
286 OPC_SRA
= OPC_SPECIAL
| 0x03,
287 OPC_SLLV
= OPC_SPECIAL
| 0x04,
288 OPC_SRLV
= OPC_SPECIAL
| 0x06,
289 OPC_ROTRV
= OPC_SPECIAL
| (0x01 << 6) | 0x06,
290 OPC_SRAV
= OPC_SPECIAL
| 0x07,
291 OPC_JR_R5
= OPC_SPECIAL
| 0x08,
292 OPC_JALR
= OPC_SPECIAL
| 0x09,
293 OPC_MOVZ
= OPC_SPECIAL
| 0x0A,
294 OPC_MOVN
= OPC_SPECIAL
| 0x0B,
295 OPC_MFHI
= OPC_SPECIAL
| 0x10,
296 OPC_MFLO
= OPC_SPECIAL
| 0x12,
297 OPC_MULT
= OPC_SPECIAL
| 0x18,
298 OPC_MUL_R6
= OPC_SPECIAL
| (0x02 << 6) | 0x18,
299 OPC_MUH
= OPC_SPECIAL
| (0x03 << 6) | 0x18,
300 OPC_MULTU
= OPC_SPECIAL
| 0x19,
301 OPC_MULU
= OPC_SPECIAL
| (0x02 << 6) | 0x19,
302 OPC_MUHU
= OPC_SPECIAL
| (0x03 << 6) | 0x19,
303 OPC_DIV
= OPC_SPECIAL
| 0x1A,
304 OPC_DIV_R6
= OPC_SPECIAL
| (0x02 << 6) | 0x1A,
305 OPC_MOD
= OPC_SPECIAL
| (0x03 << 6) | 0x1A,
306 OPC_DIVU
= OPC_SPECIAL
| 0x1B,
307 OPC_DIVU_R6
= OPC_SPECIAL
| (0x02 << 6) | 0x1B,
308 OPC_MODU
= OPC_SPECIAL
| (0x03 << 6) | 0x1B,
309 OPC_ADDU
= OPC_SPECIAL
| 0x21,
310 OPC_SUBU
= OPC_SPECIAL
| 0x23,
311 OPC_AND
= OPC_SPECIAL
| 0x24,
312 OPC_OR
= OPC_SPECIAL
| 0x25,
313 OPC_XOR
= OPC_SPECIAL
| 0x26,
314 OPC_NOR
= OPC_SPECIAL
| 0x27,
315 OPC_SLT
= OPC_SPECIAL
| 0x2A,
316 OPC_SLTU
= OPC_SPECIAL
| 0x2B,
317 OPC_SELEQZ
= OPC_SPECIAL
| 0x35,
318 OPC_SELNEZ
= OPC_SPECIAL
| 0x37,
320 OPC_REGIMM
= 0x01 << 26,
321 OPC_BLTZ
= OPC_REGIMM
| (0x00 << 16),
322 OPC_BGEZ
= OPC_REGIMM
| (0x01 << 16),
324 OPC_SPECIAL2
= 0x1c << 26,
325 OPC_MUL_R5
= OPC_SPECIAL2
| 0x002,
327 OPC_SPECIAL3
= 0x1f << 26,
328 OPC_EXT
= OPC_SPECIAL3
| 0x000,
329 OPC_INS
= OPC_SPECIAL3
| 0x004,
330 OPC_WSBH
= OPC_SPECIAL3
| 0x0a0,
331 OPC_SEB
= OPC_SPECIAL3
| 0x420,
332 OPC_SEH
= OPC_SPECIAL3
| 0x620,
334 /* MIPS r6 doesn't have JR, JALR should be used instead */
335 OPC_JR
= use_mips32r6_instructions
? OPC_JALR
: OPC_JR_R5
,
338 * MIPS r6 replaces MUL with an alternative encoding which is
339 * backwards-compatible at the assembly level.
341 OPC_MUL
= use_mips32r6_instructions
? OPC_MUL_R6
: OPC_MUL_R5
,
347 static inline void tcg_out_opc_reg(TCGContext
*s
, MIPSInsn opc
,
348 TCGReg rd
, TCGReg rs
, TCGReg rt
)
353 inst
|= (rs
& 0x1F) << 21;
354 inst
|= (rt
& 0x1F) << 16;
355 inst
|= (rd
& 0x1F) << 11;
362 static inline void tcg_out_opc_imm(TCGContext
*s
, MIPSInsn opc
,
363 TCGReg rt
, TCGReg rs
, TCGArg imm
)
368 inst
|= (rs
& 0x1F) << 21;
369 inst
|= (rt
& 0x1F) << 16;
370 inst
|= (imm
& 0xffff);
377 static inline void tcg_out_opc_bf(TCGContext
*s
, MIPSInsn opc
, TCGReg rt
,
378 TCGReg rs
, int msb
, int lsb
)
383 inst
|= (rs
& 0x1F) << 21;
384 inst
|= (rt
& 0x1F) << 16;
385 inst
|= (msb
& 0x1F) << 11;
386 inst
|= (lsb
& 0x1F) << 6;
393 static inline void tcg_out_opc_br(TCGContext
*s
, MIPSInsn opc
,
394 TCGReg rt
, TCGReg rs
)
396 /* We pay attention here to not modify the branch target by reading
397 the existing value and using it again. This ensure that caches and
398 memory are kept coherent during retranslation. */
399 uint16_t offset
= (uint16_t)*s
->code_ptr
;
401 tcg_out_opc_imm(s
, opc
, rt
, rs
, offset
);
407 static inline void tcg_out_opc_sa(TCGContext
*s
, MIPSInsn opc
,
408 TCGReg rd
, TCGReg rt
, TCGArg sa
)
413 inst
|= (rt
& 0x1F) << 16;
414 inst
|= (rd
& 0x1F) << 11;
415 inst
|= (sa
& 0x1F) << 6;
422 * Returns true if the branch was in range and the insn was emitted.
424 static bool tcg_out_opc_jmp(TCGContext
*s
, MIPSInsn opc
, void *target
)
426 uintptr_t dest
= (uintptr_t)target
;
427 uintptr_t from
= (uintptr_t)s
->code_ptr
+ 4;
430 /* The pc-region branch happens within the 256MB region of
431 the delay slot (thus the +4). */
432 if ((from
^ dest
) & -(1 << 28)) {
435 tcg_debug_assert((dest
& 3) == 0);
438 inst
|= (dest
>> 2) & 0x3ffffff;
443 static inline void tcg_out_nop(TCGContext
*s
)
448 static inline void tcg_out_mov(TCGContext
*s
, TCGType type
,
449 TCGReg ret
, TCGReg arg
)
451 /* Simple reg-reg move, optimising out the 'do nothing' case */
453 tcg_out_opc_reg(s
, OPC_ADDU
, ret
, arg
, TCG_REG_ZERO
);
457 static inline void tcg_out_movi(TCGContext
*s
, TCGType type
,
458 TCGReg reg
, tcg_target_long arg
)
460 if (arg
== (int16_t)arg
) {
461 tcg_out_opc_imm(s
, OPC_ADDIU
, reg
, TCG_REG_ZERO
, arg
);
462 } else if (arg
== (uint16_t)arg
) {
463 tcg_out_opc_imm(s
, OPC_ORI
, reg
, TCG_REG_ZERO
, arg
);
465 tcg_out_opc_imm(s
, OPC_LUI
, reg
, TCG_REG_ZERO
, arg
>> 16);
467 tcg_out_opc_imm(s
, OPC_ORI
, reg
, reg
, arg
& 0xffff);
472 static inline void tcg_out_bswap16(TCGContext
*s
, TCGReg ret
, TCGReg arg
)
474 if (use_mips32r2_instructions
) {
475 tcg_out_opc_reg(s
, OPC_WSBH
, ret
, 0, arg
);
477 /* ret and arg can't be register at */
478 if (ret
== TCG_TMP0
|| arg
== TCG_TMP0
) {
482 tcg_out_opc_sa(s
, OPC_SRL
, TCG_TMP0
, arg
, 8);
483 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 8);
484 tcg_out_opc_imm(s
, OPC_ANDI
, ret
, ret
, 0xff00);
485 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_TMP0
);
489 static inline void tcg_out_bswap16s(TCGContext
*s
, TCGReg ret
, TCGReg arg
)
491 if (use_mips32r2_instructions
) {
492 tcg_out_opc_reg(s
, OPC_WSBH
, ret
, 0, arg
);
493 tcg_out_opc_reg(s
, OPC_SEH
, ret
, 0, ret
);
495 /* ret and arg can't be register at */
496 if (ret
== TCG_TMP0
|| arg
== TCG_TMP0
) {
500 tcg_out_opc_sa(s
, OPC_SRL
, TCG_TMP0
, arg
, 8);
501 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 24);
502 tcg_out_opc_sa(s
, OPC_SRA
, ret
, ret
, 16);
503 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_TMP0
);
507 static inline void tcg_out_bswap32(TCGContext
*s
, TCGReg ret
, TCGReg arg
)
509 if (use_mips32r2_instructions
) {
510 tcg_out_opc_reg(s
, OPC_WSBH
, ret
, 0, arg
);
511 tcg_out_opc_sa(s
, OPC_ROTR
, ret
, ret
, 16);
513 /* ret and arg must be different and can't be register at */
514 if (ret
== arg
|| ret
== TCG_TMP0
|| arg
== TCG_TMP0
) {
518 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 24);
520 tcg_out_opc_sa(s
, OPC_SRL
, TCG_TMP0
, arg
, 24);
521 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_TMP0
);
523 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_TMP0
, arg
, 0xff00);
524 tcg_out_opc_sa(s
, OPC_SLL
, TCG_TMP0
, TCG_TMP0
, 8);
525 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_TMP0
);
527 tcg_out_opc_sa(s
, OPC_SRL
, TCG_TMP0
, arg
, 8);
528 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_TMP0
, TCG_TMP0
, 0xff00);
529 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_TMP0
);
533 static inline void tcg_out_ext8s(TCGContext
*s
, TCGReg ret
, TCGReg arg
)
535 if (use_mips32r2_instructions
) {
536 tcg_out_opc_reg(s
, OPC_SEB
, ret
, 0, arg
);
538 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 24);
539 tcg_out_opc_sa(s
, OPC_SRA
, ret
, ret
, 24);
543 static inline void tcg_out_ext16s(TCGContext
*s
, TCGReg ret
, TCGReg arg
)
545 if (use_mips32r2_instructions
) {
546 tcg_out_opc_reg(s
, OPC_SEH
, ret
, 0, arg
);
548 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 16);
549 tcg_out_opc_sa(s
, OPC_SRA
, ret
, ret
, 16);
553 static void tcg_out_ldst(TCGContext
*s
, MIPSInsn opc
, TCGReg data
,
554 TCGReg addr
, intptr_t ofs
)
558 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_TMP0
, ofs
- lo
);
559 if (addr
!= TCG_REG_ZERO
) {
560 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_TMP0
, TCG_TMP0
, addr
);
564 tcg_out_opc_imm(s
, opc
, data
, addr
, lo
);
567 static inline void tcg_out_ld(TCGContext
*s
, TCGType type
, TCGReg arg
,
568 TCGReg arg1
, intptr_t arg2
)
570 tcg_out_ldst(s
, OPC_LW
, arg
, arg1
, arg2
);
573 static inline void tcg_out_st(TCGContext
*s
, TCGType type
, TCGReg arg
,
574 TCGReg arg1
, intptr_t arg2
)
576 tcg_out_ldst(s
, OPC_SW
, arg
, arg1
, arg2
);
579 static inline bool tcg_out_sti(TCGContext
*s
, TCGType type
, TCGArg val
,
580 TCGReg base
, intptr_t ofs
)
583 tcg_out_st(s
, type
, TCG_REG_ZERO
, base
, ofs
);
589 static inline void tcg_out_addi(TCGContext
*s
, TCGReg reg
, TCGArg val
)
591 if (val
== (int16_t)val
) {
592 tcg_out_opc_imm(s
, OPC_ADDIU
, reg
, reg
, val
);
594 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_TMP0
, val
);
595 tcg_out_opc_reg(s
, OPC_ADDU
, reg
, reg
, TCG_TMP0
);
599 static void tcg_out_addsub2(TCGContext
*s
, TCGReg rl
, TCGReg rh
, TCGReg al
,
600 TCGReg ah
, TCGArg bl
, TCGArg bh
, bool cbl
,
601 bool cbh
, bool is_sub
)
603 TCGReg th
= TCG_TMP1
;
605 /* If we have a negative constant such that negating it would
606 make the high part zero, we can (usually) eliminate one insn. */
607 if (cbl
&& cbh
&& bh
== -1 && bl
!= 0) {
613 /* By operating on the high part first, we get to use the final
614 carry operation to move back from the temporary. */
616 tcg_out_opc_reg(s
, (is_sub
? OPC_SUBU
: OPC_ADDU
), th
, ah
, bh
);
617 } else if (bh
!= 0 || ah
== rl
) {
618 tcg_out_opc_imm(s
, OPC_ADDIU
, th
, ah
, (is_sub
? -bh
: bh
));
623 /* Note that tcg optimization should eliminate the bl == 0 case. */
626 tcg_out_opc_imm(s
, OPC_SLTIU
, TCG_TMP0
, al
, bl
);
627 tcg_out_opc_imm(s
, OPC_ADDIU
, rl
, al
, -bl
);
629 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_TMP0
, al
, bl
);
630 tcg_out_opc_reg(s
, OPC_SUBU
, rl
, al
, bl
);
632 tcg_out_opc_reg(s
, OPC_SUBU
, rh
, th
, TCG_TMP0
);
635 tcg_out_opc_imm(s
, OPC_ADDIU
, rl
, al
, bl
);
636 tcg_out_opc_imm(s
, OPC_SLTIU
, TCG_TMP0
, rl
, bl
);
637 } else if (rl
== al
&& rl
== bl
) {
638 tcg_out_opc_sa(s
, OPC_SRL
, TCG_TMP0
, al
, 31);
639 tcg_out_opc_reg(s
, OPC_ADDU
, rl
, al
, bl
);
641 tcg_out_opc_reg(s
, OPC_ADDU
, rl
, al
, bl
);
642 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_TMP0
, rl
, (rl
== bl
? al
: bl
));
644 tcg_out_opc_reg(s
, OPC_ADDU
, rh
, th
, TCG_TMP0
);
648 /* Bit 0 set if inversion required; bit 1 set if swapping required. */
649 #define MIPS_CMP_INV 1
650 #define MIPS_CMP_SWAP 2
652 static const uint8_t mips_cmp_map
[16] = {
655 [TCG_COND_GE
] = MIPS_CMP_INV
,
656 [TCG_COND_GEU
] = MIPS_CMP_INV
,
657 [TCG_COND_LE
] = MIPS_CMP_INV
| MIPS_CMP_SWAP
,
658 [TCG_COND_LEU
] = MIPS_CMP_INV
| MIPS_CMP_SWAP
,
659 [TCG_COND_GT
] = MIPS_CMP_SWAP
,
660 [TCG_COND_GTU
] = MIPS_CMP_SWAP
,
663 static void tcg_out_setcond(TCGContext
*s
, TCGCond cond
, TCGReg ret
,
664 TCGReg arg1
, TCGReg arg2
)
666 MIPSInsn s_opc
= OPC_SLTU
;
672 tcg_out_opc_reg(s
, OPC_XOR
, ret
, arg1
, arg2
);
675 tcg_out_opc_imm(s
, OPC_SLTIU
, ret
, arg1
, 1);
680 tcg_out_opc_reg(s
, OPC_XOR
, ret
, arg1
, arg2
);
683 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, TCG_REG_ZERO
, arg1
);
697 cmp_map
= mips_cmp_map
[cond
];
698 if (cmp_map
& MIPS_CMP_SWAP
) {
703 tcg_out_opc_reg(s
, s_opc
, ret
, arg1
, arg2
);
704 if (cmp_map
& MIPS_CMP_INV
) {
705 tcg_out_opc_imm(s
, OPC_XORI
, ret
, ret
, 1);
715 static void tcg_out_brcond(TCGContext
*s
, TCGCond cond
, TCGReg arg1
,
716 TCGReg arg2
, TCGLabel
*l
)
718 static const MIPSInsn b_zero
[16] = {
719 [TCG_COND_LT
] = OPC_BLTZ
,
720 [TCG_COND_GT
] = OPC_BGTZ
,
721 [TCG_COND_LE
] = OPC_BLEZ
,
722 [TCG_COND_GE
] = OPC_BGEZ
,
725 MIPSInsn s_opc
= OPC_SLTU
;
742 b_opc
= b_zero
[cond
];
754 cmp_map
= mips_cmp_map
[cond
];
755 if (cmp_map
& MIPS_CMP_SWAP
) {
760 tcg_out_opc_reg(s
, s_opc
, TCG_TMP0
, arg1
, arg2
);
761 b_opc
= (cmp_map
& MIPS_CMP_INV
? OPC_BEQ
: OPC_BNE
);
771 tcg_out_opc_br(s
, b_opc
, arg1
, arg2
);
773 reloc_pc16(s
->code_ptr
- 1, l
->u
.value_ptr
);
775 tcg_out_reloc(s
, s
->code_ptr
- 1, R_MIPS_PC16
, l
, 0);
780 static TCGReg
tcg_out_reduce_eq2(TCGContext
*s
, TCGReg tmp0
, TCGReg tmp1
,
781 TCGReg al
, TCGReg ah
,
782 TCGReg bl
, TCGReg bh
)
784 /* Merge highpart comparison into AH. */
787 tcg_out_opc_reg(s
, OPC_XOR
, tmp0
, ah
, bh
);
793 /* Merge lowpart comparison into AL. */
796 tcg_out_opc_reg(s
, OPC_XOR
, tmp1
, al
, bl
);
802 /* Merge high and low part comparisons into AL. */
805 tcg_out_opc_reg(s
, OPC_OR
, tmp0
, ah
, al
);
814 static void tcg_out_setcond2(TCGContext
*s
, TCGCond cond
, TCGReg ret
,
815 TCGReg al
, TCGReg ah
, TCGReg bl
, TCGReg bh
)
817 TCGReg tmp0
= TCG_TMP0
;
820 tcg_debug_assert(ret
!= TCG_TMP0
);
821 if (ret
== ah
|| ret
== bh
) {
822 tcg_debug_assert(ret
!= TCG_TMP1
);
829 tmp1
= tcg_out_reduce_eq2(s
, tmp0
, tmp1
, al
, ah
, bl
, bh
);
830 tcg_out_setcond(s
, cond
, ret
, tmp1
, TCG_REG_ZERO
);
834 tcg_out_setcond(s
, TCG_COND_EQ
, tmp0
, ah
, bh
);
835 tcg_out_setcond(s
, tcg_unsigned_cond(cond
), tmp1
, al
, bl
);
836 tcg_out_opc_reg(s
, OPC_AND
, tmp1
, tmp1
, tmp0
);
837 tcg_out_setcond(s
, tcg_high_cond(cond
), tmp0
, ah
, bh
);
838 tcg_out_opc_reg(s
, OPC_OR
, ret
, tmp1
, tmp0
);
843 static void tcg_out_brcond2(TCGContext
*s
, TCGCond cond
, TCGReg al
, TCGReg ah
,
844 TCGReg bl
, TCGReg bh
, TCGLabel
*l
)
846 TCGCond b_cond
= TCG_COND_NE
;
847 TCGReg tmp
= TCG_TMP1
;
849 /* With branches, we emit between 4 and 9 insns with 2 or 3 branches.
850 With setcond, we emit between 3 and 10 insns and only 1 branch,
851 which ought to get better branch prediction. */
856 tmp
= tcg_out_reduce_eq2(s
, TCG_TMP0
, TCG_TMP1
, al
, ah
, bl
, bh
);
860 /* Minimize code size by preferring a compare not requiring INV. */
861 if (mips_cmp_map
[cond
] & MIPS_CMP_INV
) {
862 cond
= tcg_invert_cond(cond
);
863 b_cond
= TCG_COND_EQ
;
865 tcg_out_setcond2(s
, cond
, tmp
, al
, ah
, bl
, bh
);
869 tcg_out_brcond(s
, b_cond
, tmp
, TCG_REG_ZERO
, l
);
872 static void tcg_out_movcond(TCGContext
*s
, TCGCond cond
, TCGReg ret
,
873 TCGReg c1
, TCGReg c2
, TCGReg v1
, TCGReg v2
)
877 /* If one of the values is zero, put it last to match SEL*Z instructions */
878 if (use_mips32r6_instructions
&& v1
== 0) {
881 cond
= tcg_invert_cond(cond
);
890 tcg_out_opc_reg(s
, OPC_XOR
, TCG_TMP0
, c1
, c2
);
896 /* Minimize code size by preferring a compare not requiring INV. */
897 if (mips_cmp_map
[cond
] & MIPS_CMP_INV
) {
898 cond
= tcg_invert_cond(cond
);
901 tcg_out_setcond(s
, cond
, TCG_TMP0
, c1
, c2
);
906 if (use_mips32r6_instructions
) {
907 MIPSInsn m_opc_t
= eqz
? OPC_SELEQZ
: OPC_SELNEZ
;
908 MIPSInsn m_opc_f
= eqz
? OPC_SELNEZ
: OPC_SELEQZ
;
911 tcg_out_opc_reg(s
, m_opc_f
, TCG_TMP1
, v2
, c1
);
913 tcg_out_opc_reg(s
, m_opc_t
, ret
, v1
, c1
);
915 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_TMP1
);
918 MIPSInsn m_opc
= eqz
? OPC_MOVZ
: OPC_MOVN
;
920 tcg_out_opc_reg(s
, m_opc
, ret
, v1
, c1
);
922 /* This should be guaranteed via constraints */
923 tcg_debug_assert(v2
== ret
);
927 static void tcg_out_call_int(TCGContext
*s
, tcg_insn_unit
*arg
, bool tail
)
929 /* Note that the ABI requires the called function's address to be
930 loaded into T9, even if a direct branch is in range. */
931 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_T9
, (uintptr_t)arg
);
933 /* But do try a direct branch, allowing the cpu better insn prefetch. */
935 if (!tcg_out_opc_jmp(s
, OPC_J
, arg
)) {
936 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_T9
, 0);
939 if (!tcg_out_opc_jmp(s
, OPC_JAL
, arg
)) {
940 tcg_out_opc_reg(s
, OPC_JALR
, TCG_REG_RA
, TCG_REG_T9
, 0);
945 static void tcg_out_call(TCGContext
*s
, tcg_insn_unit
*arg
)
947 tcg_out_call_int(s
, arg
, false);
951 #if defined(CONFIG_SOFTMMU)
952 static void * const qemu_ld_helpers
[16] = {
953 [MO_UB
] = helper_ret_ldub_mmu
,
954 [MO_SB
] = helper_ret_ldsb_mmu
,
955 [MO_LEUW
] = helper_le_lduw_mmu
,
956 [MO_LESW
] = helper_le_ldsw_mmu
,
957 [MO_LEUL
] = helper_le_ldul_mmu
,
958 [MO_LEQ
] = helper_le_ldq_mmu
,
959 [MO_BEUW
] = helper_be_lduw_mmu
,
960 [MO_BESW
] = helper_be_ldsw_mmu
,
961 [MO_BEUL
] = helper_be_ldul_mmu
,
962 [MO_BEQ
] = helper_be_ldq_mmu
,
965 static void * const qemu_st_helpers
[16] = {
966 [MO_UB
] = helper_ret_stb_mmu
,
967 [MO_LEUW
] = helper_le_stw_mmu
,
968 [MO_LEUL
] = helper_le_stl_mmu
,
969 [MO_LEQ
] = helper_le_stq_mmu
,
970 [MO_BEUW
] = helper_be_stw_mmu
,
971 [MO_BEUL
] = helper_be_stl_mmu
,
972 [MO_BEQ
] = helper_be_stq_mmu
,
975 /* Helper routines for marshalling helper function arguments into
976 * the correct registers and stack.
977 * I is where we want to put this argument, and is updated and returned
978 * for the next call. ARG is the argument itself.
980 * We provide routines for arguments which are: immediate, 32 bit
981 * value in register, 16 and 8 bit values in register (which must be zero
982 * extended before use) and 64 bit value in a lo:hi register pair.
985 static int tcg_out_call_iarg_reg(TCGContext
*s
, int i
, TCGReg arg
)
987 if (i
< ARRAY_SIZE(tcg_target_call_iarg_regs
)) {
988 tcg_out_mov(s
, TCG_TYPE_REG
, tcg_target_call_iarg_regs
[i
], arg
);
990 tcg_out_st(s
, TCG_TYPE_REG
, arg
, TCG_REG_SP
, 4 * i
);
995 static int tcg_out_call_iarg_reg8(TCGContext
*s
, int i
, TCGReg arg
)
997 TCGReg tmp
= TCG_TMP0
;
998 if (i
< ARRAY_SIZE(tcg_target_call_iarg_regs
)) {
999 tmp
= tcg_target_call_iarg_regs
[i
];
1001 tcg_out_opc_imm(s
, OPC_ANDI
, tmp
, arg
, 0xff);
1002 return tcg_out_call_iarg_reg(s
, i
, tmp
);
1005 static int tcg_out_call_iarg_reg16(TCGContext
*s
, int i
, TCGReg arg
)
1007 TCGReg tmp
= TCG_TMP0
;
1008 if (i
< ARRAY_SIZE(tcg_target_call_iarg_regs
)) {
1009 tmp
= tcg_target_call_iarg_regs
[i
];
1011 tcg_out_opc_imm(s
, OPC_ANDI
, tmp
, arg
, 0xffff);
1012 return tcg_out_call_iarg_reg(s
, i
, tmp
);
1015 static int tcg_out_call_iarg_imm(TCGContext
*s
, int i
, TCGArg arg
)
1017 TCGReg tmp
= TCG_TMP0
;
1021 if (i
< ARRAY_SIZE(tcg_target_call_iarg_regs
)) {
1022 tmp
= tcg_target_call_iarg_regs
[i
];
1024 tcg_out_movi(s
, TCG_TYPE_REG
, tmp
, arg
);
1026 return tcg_out_call_iarg_reg(s
, i
, tmp
);
1029 static int tcg_out_call_iarg_reg2(TCGContext
*s
, int i
, TCGReg al
, TCGReg ah
)
1032 i
= tcg_out_call_iarg_reg(s
, i
, (MIPS_BE
? ah
: al
));
1033 i
= tcg_out_call_iarg_reg(s
, i
, (MIPS_BE
? al
: ah
));
1037 /* Perform the tlb comparison operation. The complete host address is
1038 placed in BASE. Clobbers AT, T0, A0. */
1039 static void tcg_out_tlb_load(TCGContext
*s
, TCGReg base
, TCGReg addrl
,
1040 TCGReg addrh
, TCGMemOpIdx oi
,
1041 tcg_insn_unit
*label_ptr
[2], bool is_load
)
1043 TCGMemOp s_bits
= get_memop(oi
) & MO_SIZE
;
1044 int mem_index
= get_mmuidx(oi
);
1047 ? offsetof(CPUArchState
, tlb_table
[mem_index
][0].addr_read
)
1048 : offsetof(CPUArchState
, tlb_table
[mem_index
][0].addr_write
));
1049 int add_off
= offsetof(CPUArchState
, tlb_table
[mem_index
][0].addend
);
1051 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_A0
, addrl
,
1052 TARGET_PAGE_BITS
- CPU_TLB_ENTRY_BITS
);
1053 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_A0
, TCG_REG_A0
,
1054 (CPU_TLB_SIZE
- 1) << CPU_TLB_ENTRY_BITS
);
1055 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_A0
, TCG_REG_A0
, TCG_AREG0
);
1057 /* Compensate for very large offsets. */
1058 if (add_off
>= 0x8000) {
1059 /* Most target env are smaller than 32k; none are larger than 64k.
1060 Simplify the logic here merely to offset by 0x7ff0, giving us a
1061 range just shy of 64k. Check this assumption. */
1062 QEMU_BUILD_BUG_ON(offsetof(CPUArchState
,
1063 tlb_table
[NB_MMU_MODES
- 1][1])
1065 tcg_out_opc_imm(s
, OPC_ADDIU
, TCG_REG_A0
, TCG_REG_A0
, 0x7ff0);
1070 /* Load the (low half) tlb comparator. */
1071 tcg_out_opc_imm(s
, OPC_LW
, TCG_TMP0
, TCG_REG_A0
,
1072 cmp_off
+ (TARGET_LONG_BITS
== 64 ? LO_OFF
: 0));
1074 /* Mask the page bits, keeping the alignment bits to compare against.
1075 In between on 32-bit targets, load the tlb addend for the fast path. */
1076 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_TMP1
,
1077 TARGET_PAGE_MASK
| ((1 << s_bits
) - 1));
1078 if (TARGET_LONG_BITS
== 32) {
1079 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_A0
, TCG_REG_A0
, add_off
);
1081 tcg_out_opc_reg(s
, OPC_AND
, TCG_TMP1
, TCG_TMP1
, addrl
);
1083 label_ptr
[0] = s
->code_ptr
;
1084 tcg_out_opc_br(s
, OPC_BNE
, TCG_TMP1
, TCG_TMP0
);
1086 /* Load and test the high half tlb comparator. */
1087 if (TARGET_LONG_BITS
== 64) {
1089 tcg_out_opc_imm(s
, OPC_LW
, TCG_TMP0
, TCG_REG_A0
, cmp_off
+ HI_OFF
);
1091 /* Load the tlb addend for the fast path. We can't do it earlier with
1092 64-bit targets or we'll clobber a0 before reading the high half tlb
1094 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_A0
, TCG_REG_A0
, add_off
);
1096 label_ptr
[1] = s
->code_ptr
;
1097 tcg_out_opc_br(s
, OPC_BNE
, addrh
, TCG_TMP0
);
1101 tcg_out_opc_reg(s
, OPC_ADDU
, base
, TCG_REG_A0
, addrl
);
1104 static void add_qemu_ldst_label(TCGContext
*s
, int is_ld
, TCGMemOpIdx oi
,
1105 TCGReg datalo
, TCGReg datahi
,
1106 TCGReg addrlo
, TCGReg addrhi
,
1107 void *raddr
, tcg_insn_unit
*label_ptr
[2])
1109 TCGLabelQemuLdst
*label
= new_ldst_label(s
);
1111 label
->is_ld
= is_ld
;
1113 label
->datalo_reg
= datalo
;
1114 label
->datahi_reg
= datahi
;
1115 label
->addrlo_reg
= addrlo
;
1116 label
->addrhi_reg
= addrhi
;
1117 label
->raddr
= raddr
;
1118 label
->label_ptr
[0] = label_ptr
[0];
1119 if (TARGET_LONG_BITS
== 64) {
1120 label
->label_ptr
[1] = label_ptr
[1];
1124 static void tcg_out_qemu_ld_slow_path(TCGContext
*s
, TCGLabelQemuLdst
*l
)
1126 TCGMemOpIdx oi
= l
->oi
;
1127 TCGMemOp opc
= get_memop(oi
);
1131 /* resolve label address */
1132 reloc_pc16(l
->label_ptr
[0], s
->code_ptr
);
1133 if (TARGET_LONG_BITS
== 64) {
1134 reloc_pc16(l
->label_ptr
[1], s
->code_ptr
);
1138 if (TARGET_LONG_BITS
== 64) {
1139 i
= tcg_out_call_iarg_reg2(s
, i
, l
->addrlo_reg
, l
->addrhi_reg
);
1141 i
= tcg_out_call_iarg_reg(s
, i
, l
->addrlo_reg
);
1143 i
= tcg_out_call_iarg_imm(s
, i
, oi
);
1144 i
= tcg_out_call_iarg_imm(s
, i
, (intptr_t)l
->raddr
);
1145 tcg_out_call_int(s
, qemu_ld_helpers
[opc
& (MO_BSWAP
| MO_SSIZE
)], false);
1147 tcg_out_mov(s
, TCG_TYPE_PTR
, tcg_target_call_iarg_regs
[0], TCG_AREG0
);
1150 if ((opc
& MO_SIZE
) == MO_64
) {
1151 /* We eliminated V0 from the possible output registers, so it
1152 cannot be clobbered here. So we must move V1 first. */
1154 tcg_out_mov(s
, TCG_TYPE_I32
, v0
, TCG_REG_V1
);
1157 tcg_out_mov(s
, TCG_TYPE_I32
, l
->datahi_reg
, TCG_REG_V1
);
1161 reloc_pc16(s
->code_ptr
, l
->raddr
);
1162 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_ZERO
, TCG_REG_ZERO
);
1164 tcg_out_mov(s
, TCG_TYPE_REG
, v0
, TCG_REG_V0
);
1167 static void tcg_out_qemu_st_slow_path(TCGContext
*s
, TCGLabelQemuLdst
*l
)
1169 TCGMemOpIdx oi
= l
->oi
;
1170 TCGMemOp opc
= get_memop(oi
);
1171 TCGMemOp s_bits
= opc
& MO_SIZE
;
1174 /* resolve label address */
1175 reloc_pc16(l
->label_ptr
[0], s
->code_ptr
);
1176 if (TARGET_LONG_BITS
== 64) {
1177 reloc_pc16(l
->label_ptr
[1], s
->code_ptr
);
1181 if (TARGET_LONG_BITS
== 64) {
1182 i
= tcg_out_call_iarg_reg2(s
, i
, l
->addrlo_reg
, l
->addrhi_reg
);
1184 i
= tcg_out_call_iarg_reg(s
, i
, l
->addrlo_reg
);
1188 i
= tcg_out_call_iarg_reg8(s
, i
, l
->datalo_reg
);
1191 i
= tcg_out_call_iarg_reg16(s
, i
, l
->datalo_reg
);
1194 i
= tcg_out_call_iarg_reg(s
, i
, l
->datalo_reg
);
1197 i
= tcg_out_call_iarg_reg2(s
, i
, l
->datalo_reg
, l
->datahi_reg
);
1202 i
= tcg_out_call_iarg_imm(s
, i
, oi
);
1204 /* Tail call to the store helper. Thus force the return address
1205 computation to take place in the return address register. */
1206 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_RA
, (intptr_t)l
->raddr
);
1207 i
= tcg_out_call_iarg_reg(s
, i
, TCG_REG_RA
);
1208 tcg_out_call_int(s
, qemu_st_helpers
[opc
& (MO_BSWAP
| MO_SIZE
)], true);
1210 tcg_out_mov(s
, TCG_TYPE_PTR
, tcg_target_call_iarg_regs
[0], TCG_AREG0
);
1214 static void tcg_out_qemu_ld_direct(TCGContext
*s
, TCGReg datalo
, TCGReg datahi
,
1215 TCGReg base
, TCGMemOp opc
)
1217 switch (opc
& (MO_SSIZE
| MO_BSWAP
)) {
1219 tcg_out_opc_imm(s
, OPC_LBU
, datalo
, base
, 0);
1222 tcg_out_opc_imm(s
, OPC_LB
, datalo
, base
, 0);
1224 case MO_UW
| MO_BSWAP
:
1225 tcg_out_opc_imm(s
, OPC_LHU
, TCG_TMP1
, base
, 0);
1226 tcg_out_bswap16(s
, datalo
, TCG_TMP1
);
1229 tcg_out_opc_imm(s
, OPC_LHU
, datalo
, base
, 0);
1231 case MO_SW
| MO_BSWAP
:
1232 tcg_out_opc_imm(s
, OPC_LHU
, TCG_TMP1
, base
, 0);
1233 tcg_out_bswap16s(s
, datalo
, TCG_TMP1
);
1236 tcg_out_opc_imm(s
, OPC_LH
, datalo
, base
, 0);
1238 case MO_UL
| MO_BSWAP
:
1239 tcg_out_opc_imm(s
, OPC_LW
, TCG_TMP1
, base
, 0);
1240 tcg_out_bswap32(s
, datalo
, TCG_TMP1
);
1243 tcg_out_opc_imm(s
, OPC_LW
, datalo
, base
, 0);
1245 case MO_Q
| MO_BSWAP
:
1246 tcg_out_opc_imm(s
, OPC_LW
, TCG_TMP1
, base
, HI_OFF
);
1247 tcg_out_bswap32(s
, datalo
, TCG_TMP1
);
1248 tcg_out_opc_imm(s
, OPC_LW
, TCG_TMP1
, base
, LO_OFF
);
1249 tcg_out_bswap32(s
, datahi
, TCG_TMP1
);
1252 tcg_out_opc_imm(s
, OPC_LW
, datalo
, base
, LO_OFF
);
1253 tcg_out_opc_imm(s
, OPC_LW
, datahi
, base
, HI_OFF
);
1260 static void tcg_out_qemu_ld(TCGContext
*s
, const TCGArg
*args
, bool is_64
)
1262 TCGReg addr_regl
, addr_regh
__attribute__((unused
));
1263 TCGReg data_regl
, data_regh
;
1266 #if defined(CONFIG_SOFTMMU)
1267 tcg_insn_unit
*label_ptr
[2];
1269 /* Note that we've eliminated V0 from the output registers,
1270 so we won't overwrite the base register during loading. */
1271 TCGReg base
= TCG_REG_V0
;
1273 data_regl
= *args
++;
1274 data_regh
= (is_64
? *args
++ : 0);
1275 addr_regl
= *args
++;
1276 addr_regh
= (TARGET_LONG_BITS
== 64 ? *args
++ : 0);
1278 opc
= get_memop(oi
);
1280 #if defined(CONFIG_SOFTMMU)
1281 tcg_out_tlb_load(s
, base
, addr_regl
, addr_regh
, oi
, label_ptr
, 1);
1282 tcg_out_qemu_ld_direct(s
, data_regl
, data_regh
, base
, opc
);
1283 add_qemu_ldst_label(s
, 1, oi
, data_regl
, data_regh
, addr_regl
, addr_regh
,
1284 s
->code_ptr
, label_ptr
);
1286 if (guest_base
== 0 && data_regl
!= addr_regl
) {
1288 } else if (guest_base
== (int16_t)guest_base
) {
1289 tcg_out_opc_imm(s
, OPC_ADDIU
, base
, addr_regl
, guest_base
);
1291 tcg_out_movi(s
, TCG_TYPE_PTR
, base
, guest_base
);
1292 tcg_out_opc_reg(s
, OPC_ADDU
, base
, base
, addr_regl
);
1294 tcg_out_qemu_ld_direct(s
, data_regl
, data_regh
, base
, opc
);
1298 static void tcg_out_qemu_st_direct(TCGContext
*s
, TCGReg datalo
, TCGReg datahi
,
1299 TCGReg base
, TCGMemOp opc
)
1301 switch (opc
& (MO_SIZE
| MO_BSWAP
)) {
1303 tcg_out_opc_imm(s
, OPC_SB
, datalo
, base
, 0);
1306 case MO_16
| MO_BSWAP
:
1307 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_TMP1
, datalo
, 0xffff);
1308 tcg_out_bswap16(s
, TCG_TMP1
, TCG_TMP1
);
1312 tcg_out_opc_imm(s
, OPC_SH
, datalo
, base
, 0);
1315 case MO_32
| MO_BSWAP
:
1316 tcg_out_bswap32(s
, TCG_TMP1
, datalo
);
1320 tcg_out_opc_imm(s
, OPC_SW
, datalo
, base
, 0);
1323 case MO_64
| MO_BSWAP
:
1324 tcg_out_bswap32(s
, TCG_TMP1
, datalo
);
1325 tcg_out_opc_imm(s
, OPC_SW
, TCG_TMP1
, base
, HI_OFF
);
1326 tcg_out_bswap32(s
, TCG_TMP1
, datahi
);
1327 tcg_out_opc_imm(s
, OPC_SW
, TCG_TMP1
, base
, LO_OFF
);
1330 tcg_out_opc_imm(s
, OPC_SW
, datalo
, base
, LO_OFF
);
1331 tcg_out_opc_imm(s
, OPC_SW
, datahi
, base
, HI_OFF
);
1339 static void tcg_out_qemu_st(TCGContext
*s
, const TCGArg
*args
, bool is_64
)
1341 TCGReg addr_regl
, addr_regh
__attribute__((unused
));
1342 TCGReg data_regl
, data_regh
, base
;
1345 #if defined(CONFIG_SOFTMMU)
1346 tcg_insn_unit
*label_ptr
[2];
1349 data_regl
= *args
++;
1350 data_regh
= (is_64
? *args
++ : 0);
1351 addr_regl
= *args
++;
1352 addr_regh
= (TARGET_LONG_BITS
== 64 ? *args
++ : 0);
1354 opc
= get_memop(oi
);
1356 #if defined(CONFIG_SOFTMMU)
1357 /* Note that we eliminated the helper's address argument,
1358 so we can reuse that for the base. */
1359 base
= (TARGET_LONG_BITS
== 32 ? TCG_REG_A1
: TCG_REG_A2
);
1360 tcg_out_tlb_load(s
, base
, addr_regl
, addr_regh
, oi
, label_ptr
, 0);
1361 tcg_out_qemu_st_direct(s
, data_regl
, data_regh
, base
, opc
);
1362 add_qemu_ldst_label(s
, 0, oi
, data_regl
, data_regh
, addr_regl
, addr_regh
,
1363 s
->code_ptr
, label_ptr
);
1365 if (guest_base
== 0) {
1369 if (guest_base
== (int16_t)guest_base
) {
1370 tcg_out_opc_imm(s
, OPC_ADDIU
, base
, addr_regl
, guest_base
);
1372 tcg_out_movi(s
, TCG_TYPE_PTR
, base
, guest_base
);
1373 tcg_out_opc_reg(s
, OPC_ADDU
, base
, base
, addr_regl
);
1376 tcg_out_qemu_st_direct(s
, data_regl
, data_regh
, base
, opc
);
1380 static inline void tcg_out_op(TCGContext
*s
, TCGOpcode opc
,
1381 const TCGArg
*args
, const int *const_args
)
1393 case INDEX_op_exit_tb
:
1395 TCGReg b0
= TCG_REG_ZERO
;
1398 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_V0
, a0
& ~0xffff);
1401 if (!tcg_out_opc_jmp(s
, OPC_J
, tb_ret_addr
)) {
1402 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_TMP0
,
1403 (uintptr_t)tb_ret_addr
);
1404 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_TMP0
, 0);
1406 tcg_out_opc_imm(s
, OPC_ORI
, TCG_REG_V0
, b0
, a0
& 0xffff);
1409 case INDEX_op_goto_tb
:
1410 if (s
->tb_jmp_insn_offset
) {
1411 /* direct jump method */
1412 s
->tb_jmp_insn_offset
[a0
] = tcg_current_code_size(s
);
1413 /* Avoid clobbering the address during retranslation. */
1414 tcg_out32(s
, OPC_J
| (*(uint32_t *)s
->code_ptr
& 0x3ffffff));
1416 /* indirect jump method */
1417 tcg_out_ld(s
, TCG_TYPE_PTR
, TCG_TMP0
, TCG_REG_ZERO
,
1418 (uintptr_t)(s
->tb_jmp_target_addr
+ a0
));
1419 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_TMP0
, 0);
1422 s
->tb_jmp_reset_offset
[a0
] = tcg_current_code_size(s
);
1425 tcg_out_brcond(s
, TCG_COND_EQ
, TCG_REG_ZERO
, TCG_REG_ZERO
,
1429 case INDEX_op_ld8u_i32
:
1432 case INDEX_op_ld8s_i32
:
1435 case INDEX_op_ld16u_i32
:
1438 case INDEX_op_ld16s_i32
:
1441 case INDEX_op_ld_i32
:
1444 case INDEX_op_st8_i32
:
1447 case INDEX_op_st16_i32
:
1450 case INDEX_op_st_i32
:
1453 tcg_out_ldst(s
, i1
, a0
, a1
, a2
);
1456 case INDEX_op_add_i32
:
1457 i1
= OPC_ADDU
, i2
= OPC_ADDIU
;
1459 case INDEX_op_or_i32
:
1460 i1
= OPC_OR
, i2
= OPC_ORI
;
1462 case INDEX_op_xor_i32
:
1463 i1
= OPC_XOR
, i2
= OPC_XORI
;
1466 tcg_out_opc_imm(s
, i2
, a0
, a1
, a2
);
1470 tcg_out_opc_reg(s
, i1
, a0
, a1
, a2
);
1473 case INDEX_op_sub_i32
:
1475 tcg_out_opc_imm(s
, OPC_ADDIU
, a0
, a1
, -a2
);
1480 case INDEX_op_and_i32
:
1481 if (c2
&& a2
!= (uint16_t)a2
) {
1482 int msb
= ctz32(~a2
) - 1;
1483 tcg_debug_assert(use_mips32r2_instructions
);
1484 tcg_debug_assert(is_p2m1(a2
));
1485 tcg_out_opc_bf(s
, OPC_EXT
, a0
, a1
, msb
, 0);
1488 i1
= OPC_AND
, i2
= OPC_ANDI
;
1490 case INDEX_op_nor_i32
:
1494 case INDEX_op_mul_i32
:
1495 if (use_mips32_instructions
) {
1496 tcg_out_opc_reg(s
, OPC_MUL
, a0
, a1
, a2
);
1499 i1
= OPC_MULT
, i2
= OPC_MFLO
;
1501 case INDEX_op_mulsh_i32
:
1502 if (use_mips32r6_instructions
) {
1503 tcg_out_opc_reg(s
, OPC_MUH
, a0
, a1
, a2
);
1506 i1
= OPC_MULT
, i2
= OPC_MFHI
;
1508 case INDEX_op_muluh_i32
:
1509 if (use_mips32r6_instructions
) {
1510 tcg_out_opc_reg(s
, OPC_MUHU
, a0
, a1
, a2
);
1513 i1
= OPC_MULTU
, i2
= OPC_MFHI
;
1515 case INDEX_op_div_i32
:
1516 if (use_mips32r6_instructions
) {
1517 tcg_out_opc_reg(s
, OPC_DIV_R6
, a0
, a1
, a2
);
1520 i1
= OPC_DIV
, i2
= OPC_MFLO
;
1522 case INDEX_op_divu_i32
:
1523 if (use_mips32r6_instructions
) {
1524 tcg_out_opc_reg(s
, OPC_DIVU_R6
, a0
, a1
, a2
);
1527 i1
= OPC_DIVU
, i2
= OPC_MFLO
;
1529 case INDEX_op_rem_i32
:
1530 if (use_mips32r6_instructions
) {
1531 tcg_out_opc_reg(s
, OPC_MOD
, a0
, a1
, a2
);
1534 i1
= OPC_DIV
, i2
= OPC_MFHI
;
1536 case INDEX_op_remu_i32
:
1537 if (use_mips32r6_instructions
) {
1538 tcg_out_opc_reg(s
, OPC_MODU
, a0
, a1
, a2
);
1541 i1
= OPC_DIVU
, i2
= OPC_MFHI
;
1543 tcg_out_opc_reg(s
, i1
, 0, a1
, a2
);
1544 tcg_out_opc_reg(s
, i2
, a0
, 0, 0);
1547 case INDEX_op_muls2_i32
:
1550 case INDEX_op_mulu2_i32
:
1553 tcg_out_opc_reg(s
, i1
, 0, a2
, args
[3]);
1554 tcg_out_opc_reg(s
, OPC_MFLO
, a0
, 0, 0);
1555 tcg_out_opc_reg(s
, OPC_MFHI
, a1
, 0, 0);
1558 case INDEX_op_not_i32
:
1561 case INDEX_op_bswap16_i32
:
1564 case INDEX_op_ext8s_i32
:
1567 case INDEX_op_ext16s_i32
:
1570 tcg_out_opc_reg(s
, i1
, a0
, TCG_REG_ZERO
, a1
);
1573 case INDEX_op_sar_i32
:
1574 i1
= OPC_SRAV
, i2
= OPC_SRA
;
1576 case INDEX_op_shl_i32
:
1577 i1
= OPC_SLLV
, i2
= OPC_SLL
;
1579 case INDEX_op_shr_i32
:
1580 i1
= OPC_SRLV
, i2
= OPC_SRL
;
1582 case INDEX_op_rotr_i32
:
1583 i1
= OPC_ROTRV
, i2
= OPC_ROTR
;
1586 tcg_out_opc_sa(s
, i2
, a0
, a1
, a2
);
1588 tcg_out_opc_reg(s
, i1
, a0
, a2
, a1
);
1591 case INDEX_op_rotl_i32
:
1593 tcg_out_opc_sa(s
, OPC_ROTR
, a0
, a1
, 32 - a2
);
1595 tcg_out_opc_reg(s
, OPC_SUBU
, TCG_TMP0
, TCG_REG_ZERO
, a2
);
1596 tcg_out_opc_reg(s
, OPC_ROTRV
, a0
, TCG_TMP0
, a1
);
1600 case INDEX_op_bswap32_i32
:
1601 tcg_out_opc_reg(s
, OPC_WSBH
, a0
, 0, a1
);
1602 tcg_out_opc_sa(s
, OPC_ROTR
, a0
, a0
, 16);
1605 case INDEX_op_deposit_i32
:
1606 tcg_out_opc_bf(s
, OPC_INS
, a0
, a2
, args
[3] + args
[4] - 1, args
[3]);
1609 case INDEX_op_brcond_i32
:
1610 tcg_out_brcond(s
, a2
, a0
, a1
, arg_label(args
[3]));
1612 case INDEX_op_brcond2_i32
:
1613 tcg_out_brcond2(s
, args
[4], a0
, a1
, a2
, args
[3], arg_label(args
[5]));
1616 case INDEX_op_movcond_i32
:
1617 tcg_out_movcond(s
, args
[5], a0
, a1
, a2
, args
[3], args
[4]);
1620 case INDEX_op_setcond_i32
:
1621 tcg_out_setcond(s
, args
[3], a0
, a1
, a2
);
1623 case INDEX_op_setcond2_i32
:
1624 tcg_out_setcond2(s
, args
[5], a0
, a1
, a2
, args
[3], args
[4]);
1627 case INDEX_op_qemu_ld_i32
:
1628 tcg_out_qemu_ld(s
, args
, false);
1630 case INDEX_op_qemu_ld_i64
:
1631 tcg_out_qemu_ld(s
, args
, true);
1633 case INDEX_op_qemu_st_i32
:
1634 tcg_out_qemu_st(s
, args
, false);
1636 case INDEX_op_qemu_st_i64
:
1637 tcg_out_qemu_st(s
, args
, true);
1640 case INDEX_op_add2_i32
:
1641 tcg_out_addsub2(s
, a0
, a1
, a2
, args
[3], args
[4], args
[5],
1642 const_args
[4], const_args
[5], false);
1644 case INDEX_op_sub2_i32
:
1645 tcg_out_addsub2(s
, a0
, a1
, a2
, args
[3], args
[4], args
[5],
1646 const_args
[4], const_args
[5], true);
1649 case INDEX_op_mov_i32
: /* Always emitted via tcg_out_mov. */
1650 case INDEX_op_movi_i32
: /* Always emitted via tcg_out_movi. */
1651 case INDEX_op_call
: /* Always emitted via tcg_out_call. */
1657 static const TCGTargetOpDef mips_op_defs
[] = {
1658 { INDEX_op_exit_tb
, { } },
1659 { INDEX_op_goto_tb
, { } },
1660 { INDEX_op_br
, { } },
1662 { INDEX_op_ld8u_i32
, { "r", "r" } },
1663 { INDEX_op_ld8s_i32
, { "r", "r" } },
1664 { INDEX_op_ld16u_i32
, { "r", "r" } },
1665 { INDEX_op_ld16s_i32
, { "r", "r" } },
1666 { INDEX_op_ld_i32
, { "r", "r" } },
1667 { INDEX_op_st8_i32
, { "rZ", "r" } },
1668 { INDEX_op_st16_i32
, { "rZ", "r" } },
1669 { INDEX_op_st_i32
, { "rZ", "r" } },
1671 { INDEX_op_add_i32
, { "r", "rZ", "rJ" } },
1672 { INDEX_op_mul_i32
, { "r", "rZ", "rZ" } },
1673 #if !use_mips32r6_instructions
1674 { INDEX_op_muls2_i32
, { "r", "r", "rZ", "rZ" } },
1675 { INDEX_op_mulu2_i32
, { "r", "r", "rZ", "rZ" } },
1677 { INDEX_op_mulsh_i32
, { "r", "rZ", "rZ" } },
1678 { INDEX_op_muluh_i32
, { "r", "rZ", "rZ" } },
1679 { INDEX_op_div_i32
, { "r", "rZ", "rZ" } },
1680 { INDEX_op_divu_i32
, { "r", "rZ", "rZ" } },
1681 { INDEX_op_rem_i32
, { "r", "rZ", "rZ" } },
1682 { INDEX_op_remu_i32
, { "r", "rZ", "rZ" } },
1683 { INDEX_op_sub_i32
, { "r", "rZ", "rN" } },
1685 { INDEX_op_and_i32
, { "r", "rZ", "rIK" } },
1686 { INDEX_op_nor_i32
, { "r", "rZ", "rZ" } },
1687 { INDEX_op_not_i32
, { "r", "rZ" } },
1688 { INDEX_op_or_i32
, { "r", "rZ", "rIZ" } },
1689 { INDEX_op_xor_i32
, { "r", "rZ", "rIZ" } },
1691 { INDEX_op_shl_i32
, { "r", "rZ", "ri" } },
1692 { INDEX_op_shr_i32
, { "r", "rZ", "ri" } },
1693 { INDEX_op_sar_i32
, { "r", "rZ", "ri" } },
1694 { INDEX_op_rotr_i32
, { "r", "rZ", "ri" } },
1695 { INDEX_op_rotl_i32
, { "r", "rZ", "ri" } },
1697 { INDEX_op_bswap16_i32
, { "r", "r" } },
1698 { INDEX_op_bswap32_i32
, { "r", "r" } },
1700 { INDEX_op_ext8s_i32
, { "r", "rZ" } },
1701 { INDEX_op_ext16s_i32
, { "r", "rZ" } },
1703 { INDEX_op_deposit_i32
, { "r", "0", "rZ" } },
1705 { INDEX_op_brcond_i32
, { "rZ", "rZ" } },
1706 #if use_mips32r6_instructions
1707 { INDEX_op_movcond_i32
, { "r", "rZ", "rZ", "rZ", "rZ" } },
1709 { INDEX_op_movcond_i32
, { "r", "rZ", "rZ", "rZ", "0" } },
1711 { INDEX_op_setcond_i32
, { "r", "rZ", "rZ" } },
1712 { INDEX_op_setcond2_i32
, { "r", "rZ", "rZ", "rZ", "rZ" } },
1714 { INDEX_op_add2_i32
, { "r", "r", "rZ", "rZ", "rN", "rN" } },
1715 { INDEX_op_sub2_i32
, { "r", "r", "rZ", "rZ", "rN", "rN" } },
1716 { INDEX_op_brcond2_i32
, { "rZ", "rZ", "rZ", "rZ" } },
1718 #if TARGET_LONG_BITS == 32
1719 { INDEX_op_qemu_ld_i32
, { "L", "lZ" } },
1720 { INDEX_op_qemu_st_i32
, { "SZ", "SZ" } },
1721 { INDEX_op_qemu_ld_i64
, { "L", "L", "lZ" } },
1722 { INDEX_op_qemu_st_i64
, { "SZ", "SZ", "SZ" } },
1724 { INDEX_op_qemu_ld_i32
, { "L", "lZ", "lZ" } },
1725 { INDEX_op_qemu_st_i32
, { "SZ", "SZ", "SZ" } },
1726 { INDEX_op_qemu_ld_i64
, { "L", "L", "lZ", "lZ" } },
1727 { INDEX_op_qemu_st_i64
, { "SZ", "SZ", "SZ", "SZ" } },
1732 static int tcg_target_callee_save_regs
[] = {
1733 TCG_REG_S0
, /* used for the global env (TCG_AREG0) */
1742 TCG_REG_RA
, /* should be last for ABI compliance */
1745 /* The Linux kernel doesn't provide any information about the available
1746 instruction set. Probe it using a signal handler. */
1749 #ifndef use_movnz_instructions
1750 bool use_movnz_instructions
= false;
1753 #ifndef use_mips32_instructions
1754 bool use_mips32_instructions
= false;
1757 #ifndef use_mips32r2_instructions
1758 bool use_mips32r2_instructions
= false;
1761 static volatile sig_atomic_t got_sigill
;
1763 static void sigill_handler(int signo
, siginfo_t
*si
, void *data
)
1765 /* Skip the faulty instruction */
1766 ucontext_t
*uc
= (ucontext_t
*)data
;
1767 uc
->uc_mcontext
.pc
+= 4;
1772 static void tcg_target_detect_isa(void)
1774 struct sigaction sa_old
, sa_new
;
1776 memset(&sa_new
, 0, sizeof(sa_new
));
1777 sa_new
.sa_flags
= SA_SIGINFO
;
1778 sa_new
.sa_sigaction
= sigill_handler
;
1779 sigaction(SIGILL
, &sa_new
, &sa_old
);
1781 /* Probe for movn/movz, necessary to implement movcond. */
1782 #ifndef use_movnz_instructions
1784 asm volatile(".set push\n"
1786 "movn $zero, $zero, $zero\n"
1787 "movz $zero, $zero, $zero\n"
1790 use_movnz_instructions
= !got_sigill
;
1793 /* Probe for MIPS32 instructions. As no subsetting is allowed
1794 by the specification, it is only necessary to probe for one
1795 of the instructions. */
1796 #ifndef use_mips32_instructions
1798 asm volatile(".set push\n"
1800 "mul $zero, $zero\n"
1803 use_mips32_instructions
= !got_sigill
;
1806 /* Probe for MIPS32r2 instructions if MIPS32 instructions are
1807 available. As no subsetting is allowed by the specification,
1808 it is only necessary to probe for one of the instructions. */
1809 #ifndef use_mips32r2_instructions
1810 if (use_mips32_instructions
) {
1812 asm volatile(".set push\n"
1814 "seb $zero, $zero\n"
1817 use_mips32r2_instructions
= !got_sigill
;
1821 sigaction(SIGILL
, &sa_old
, NULL
);
1824 /* Generate global QEMU prologue and epilogue code */
1825 static void tcg_target_qemu_prologue(TCGContext
*s
)
1829 /* reserve some stack space, also for TCG temps. */
1830 frame_size
= ARRAY_SIZE(tcg_target_callee_save_regs
) * 4
1831 + TCG_STATIC_CALL_ARGS_SIZE
1832 + CPU_TEMP_BUF_NLONGS
* sizeof(long);
1833 frame_size
= (frame_size
+ TCG_TARGET_STACK_ALIGN
- 1) &
1834 ~(TCG_TARGET_STACK_ALIGN
- 1);
1835 tcg_set_frame(s
, TCG_REG_SP
, ARRAY_SIZE(tcg_target_callee_save_regs
) * 4
1836 + TCG_STATIC_CALL_ARGS_SIZE
,
1837 CPU_TEMP_BUF_NLONGS
* sizeof(long));
1840 tcg_out_addi(s
, TCG_REG_SP
, -frame_size
);
1841 for(i
= 0 ; i
< ARRAY_SIZE(tcg_target_callee_save_regs
) ; i
++) {
1842 tcg_out_st(s
, TCG_TYPE_I32
, tcg_target_callee_save_regs
[i
],
1843 TCG_REG_SP
, TCG_STATIC_CALL_ARGS_SIZE
+ i
* 4);
1846 /* Call generated code */
1847 tcg_out_opc_reg(s
, OPC_JR
, 0, tcg_target_call_iarg_regs
[1], 0);
1848 tcg_out_mov(s
, TCG_TYPE_PTR
, TCG_AREG0
, tcg_target_call_iarg_regs
[0]);
1849 tb_ret_addr
= s
->code_ptr
;
1852 for(i
= 0 ; i
< ARRAY_SIZE(tcg_target_callee_save_regs
) ; i
++) {
1853 tcg_out_ld(s
, TCG_TYPE_I32
, tcg_target_callee_save_regs
[i
],
1854 TCG_REG_SP
, TCG_STATIC_CALL_ARGS_SIZE
+ i
* 4);
1857 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_RA
, 0);
1858 tcg_out_addi(s
, TCG_REG_SP
, frame_size
);
1861 static void tcg_target_init(TCGContext
*s
)
1863 tcg_target_detect_isa();
1864 tcg_regset_set(tcg_target_available_regs
[TCG_TYPE_I32
], 0xffffffff);
1865 tcg_regset_set(tcg_target_call_clobber_regs
,
1883 tcg_regset_clear(s
->reserved_regs
);
1884 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_ZERO
); /* zero register */
1885 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_K0
); /* kernel use only */
1886 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_K1
); /* kernel use only */
1887 tcg_regset_set_reg(s
->reserved_regs
, TCG_TMP0
); /* internal use */
1888 tcg_regset_set_reg(s
->reserved_regs
, TCG_TMP1
); /* internal use */
1889 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_RA
); /* return address */
1890 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_SP
); /* stack pointer */
1891 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_GP
); /* global pointer */
1893 tcg_add_target_add_op_defs(mips_op_defs
);
1896 void tb_set_jmp_target1(uintptr_t jmp_addr
, uintptr_t addr
)
1898 atomic_set((uint32_t *)jmp_addr
, deposit32(OPC_J
, 0, 26, addr
>> 2));
1899 flush_icache_range(jmp_addr
, jmp_addr
+ 4);