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
77 #define TCG_TMP2 TCG_REG_T8
78 #define TCG_TMP3 TCG_REG_T7
80 /* check if we really need so many registers :P */
81 static const int tcg_target_reg_alloc_order
[] = {
82 /* Call saved registers. */
93 /* Call clobbered registers. */
107 /* Argument registers, opposite order of allocation. */
114 static const TCGReg tcg_target_call_iarg_regs
[4] = {
121 static const TCGReg tcg_target_call_oarg_regs
[2] = {
126 static tcg_insn_unit
*tb_ret_addr
;
127 static tcg_insn_unit
*bswap32_addr
;
129 static inline uint32_t reloc_pc16_val(tcg_insn_unit
*pc
, tcg_insn_unit
*target
)
131 /* Let the compiler perform the right-shift as part of the arithmetic. */
132 ptrdiff_t disp
= target
- (pc
+ 1);
133 tcg_debug_assert(disp
== (int16_t)disp
);
134 return disp
& 0xffff;
137 static inline void reloc_pc16(tcg_insn_unit
*pc
, tcg_insn_unit
*target
)
139 *pc
= deposit32(*pc
, 0, 16, reloc_pc16_val(pc
, target
));
142 static inline uint32_t reloc_26_val(tcg_insn_unit
*pc
, tcg_insn_unit
*target
)
144 tcg_debug_assert((((uintptr_t)pc
^ (uintptr_t)target
) & 0xf0000000) == 0);
145 return ((uintptr_t)target
>> 2) & 0x3ffffff;
148 static inline void reloc_26(tcg_insn_unit
*pc
, tcg_insn_unit
*target
)
150 *pc
= deposit32(*pc
, 0, 26, reloc_26_val(pc
, target
));
153 static void patch_reloc(tcg_insn_unit
*code_ptr
, int type
,
154 intptr_t value
, intptr_t addend
)
156 tcg_debug_assert(type
== R_MIPS_PC16
);
157 tcg_debug_assert(addend
== 0);
158 reloc_pc16(code_ptr
, (tcg_insn_unit
*)value
);
161 #define TCG_CT_CONST_ZERO 0x100
162 #define TCG_CT_CONST_U16 0x200 /* Unsigned 16-bit: 0 - 0xffff. */
163 #define TCG_CT_CONST_S16 0x400 /* Signed 16-bit: -32768 - 32767 */
164 #define TCG_CT_CONST_P2M1 0x800 /* Power of 2 minus 1. */
165 #define TCG_CT_CONST_N16 0x1000 /* "Negatable" 16-bit: -32767 - 32767 */
167 static inline bool is_p2m1(tcg_target_long val
)
169 return val
&& ((val
+ 1) & val
) == 0;
172 /* parse target specific constraints */
173 static int target_parse_constraint(TCGArgConstraint
*ct
, const char **pct_str
)
180 ct
->ct
|= TCG_CT_REG
;
181 tcg_regset_set(ct
->u
.regs
, 0xffffffff);
183 case 'L': /* qemu_ld input arg constraint */
184 ct
->ct
|= TCG_CT_REG
;
185 tcg_regset_set(ct
->u
.regs
, 0xffffffff);
186 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_A0
);
187 #if defined(CONFIG_SOFTMMU)
188 if (TARGET_LONG_BITS
== 64) {
189 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_A2
);
193 case 'S': /* qemu_st constraint */
194 ct
->ct
|= TCG_CT_REG
;
195 tcg_regset_set(ct
->u
.regs
, 0xffffffff);
196 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_A0
);
197 #if defined(CONFIG_SOFTMMU)
198 if (TARGET_LONG_BITS
== 32) {
199 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_A1
);
201 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_A2
);
202 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_A3
);
207 ct
->ct
|= TCG_CT_CONST_U16
;
210 ct
->ct
|= TCG_CT_CONST_S16
;
213 ct
->ct
|= TCG_CT_CONST_P2M1
;
216 ct
->ct
|= TCG_CT_CONST_N16
;
219 /* We are cheating a bit here, using the fact that the register
220 ZERO is also the register number 0. Hence there is no need
221 to check for const_args in each instruction. */
222 ct
->ct
|= TCG_CT_CONST_ZERO
;
232 /* test if a constant matches the constraint */
233 static inline int tcg_target_const_match(tcg_target_long val
, TCGType type
,
234 const TCGArgConstraint
*arg_ct
)
238 if (ct
& TCG_CT_CONST
) {
240 } else if ((ct
& TCG_CT_CONST_ZERO
) && val
== 0) {
242 } else if ((ct
& TCG_CT_CONST_U16
) && val
== (uint16_t)val
) {
244 } else if ((ct
& TCG_CT_CONST_S16
) && val
== (int16_t)val
) {
246 } else if ((ct
& TCG_CT_CONST_N16
) && val
>= -32767 && val
<= 32767) {
248 } else if ((ct
& TCG_CT_CONST_P2M1
)
249 && use_mips32r2_instructions
&& is_p2m1(val
)) {
255 /* instruction opcodes */
258 OPC_JAL
= 0x03 << 26,
259 OPC_BEQ
= 0x04 << 26,
260 OPC_BNE
= 0x05 << 26,
261 OPC_BLEZ
= 0x06 << 26,
262 OPC_BGTZ
= 0x07 << 26,
263 OPC_ADDIU
= 0x09 << 26,
264 OPC_SLTI
= 0x0A << 26,
265 OPC_SLTIU
= 0x0B << 26,
266 OPC_ANDI
= 0x0C << 26,
267 OPC_ORI
= 0x0D << 26,
268 OPC_XORI
= 0x0E << 26,
269 OPC_LUI
= 0x0F << 26,
273 OPC_LBU
= 0x24 << 26,
274 OPC_LHU
= 0x25 << 26,
275 OPC_LWU
= 0x27 << 26,
280 OPC_SPECIAL
= 0x00 << 26,
281 OPC_SLL
= OPC_SPECIAL
| 0x00,
282 OPC_SRL
= OPC_SPECIAL
| 0x02,
283 OPC_ROTR
= OPC_SPECIAL
| (0x01 << 21) | 0x02,
284 OPC_SRA
= OPC_SPECIAL
| 0x03,
285 OPC_SLLV
= OPC_SPECIAL
| 0x04,
286 OPC_SRLV
= OPC_SPECIAL
| 0x06,
287 OPC_ROTRV
= OPC_SPECIAL
| (0x01 << 6) | 0x06,
288 OPC_SRAV
= OPC_SPECIAL
| 0x07,
289 OPC_JR_R5
= OPC_SPECIAL
| 0x08,
290 OPC_JALR
= OPC_SPECIAL
| 0x09,
291 OPC_MOVZ
= OPC_SPECIAL
| 0x0A,
292 OPC_MOVN
= OPC_SPECIAL
| 0x0B,
293 OPC_SYNC
= OPC_SPECIAL
| 0x0F,
294 OPC_MFHI
= OPC_SPECIAL
| 0x10,
295 OPC_MFLO
= OPC_SPECIAL
| 0x12,
296 OPC_MULT
= OPC_SPECIAL
| 0x18,
297 OPC_MUL_R6
= OPC_SPECIAL
| (0x02 << 6) | 0x18,
298 OPC_MUH
= OPC_SPECIAL
| (0x03 << 6) | 0x18,
299 OPC_MULTU
= OPC_SPECIAL
| 0x19,
300 OPC_MULU
= OPC_SPECIAL
| (0x02 << 6) | 0x19,
301 OPC_MUHU
= OPC_SPECIAL
| (0x03 << 6) | 0x19,
302 OPC_DIV
= OPC_SPECIAL
| 0x1A,
303 OPC_DIV_R6
= OPC_SPECIAL
| (0x02 << 6) | 0x1A,
304 OPC_MOD
= OPC_SPECIAL
| (0x03 << 6) | 0x1A,
305 OPC_DIVU
= OPC_SPECIAL
| 0x1B,
306 OPC_DIVU_R6
= OPC_SPECIAL
| (0x02 << 6) | 0x1B,
307 OPC_MODU
= OPC_SPECIAL
| (0x03 << 6) | 0x1B,
308 OPC_ADDU
= OPC_SPECIAL
| 0x21,
309 OPC_SUBU
= OPC_SPECIAL
| 0x23,
310 OPC_AND
= OPC_SPECIAL
| 0x24,
311 OPC_OR
= OPC_SPECIAL
| 0x25,
312 OPC_XOR
= OPC_SPECIAL
| 0x26,
313 OPC_NOR
= OPC_SPECIAL
| 0x27,
314 OPC_SLT
= OPC_SPECIAL
| 0x2A,
315 OPC_SLTU
= OPC_SPECIAL
| 0x2B,
316 OPC_SELEQZ
= OPC_SPECIAL
| 0x35,
317 OPC_SELNEZ
= OPC_SPECIAL
| 0x37,
319 OPC_REGIMM
= 0x01 << 26,
320 OPC_BLTZ
= OPC_REGIMM
| (0x00 << 16),
321 OPC_BGEZ
= OPC_REGIMM
| (0x01 << 16),
323 OPC_SPECIAL2
= 0x1c << 26,
324 OPC_MUL_R5
= OPC_SPECIAL2
| 0x002,
326 OPC_SPECIAL3
= 0x1f << 26,
327 OPC_EXT
= OPC_SPECIAL3
| 0x000,
328 OPC_INS
= OPC_SPECIAL3
| 0x004,
329 OPC_WSBH
= OPC_SPECIAL3
| 0x0a0,
330 OPC_SEB
= OPC_SPECIAL3
| 0x420,
331 OPC_SEH
= OPC_SPECIAL3
| 0x620,
333 /* MIPS r6 doesn't have JR, JALR should be used instead */
334 OPC_JR
= use_mips32r6_instructions
? OPC_JALR
: OPC_JR_R5
,
337 * MIPS r6 replaces MUL with an alternative encoding which is
338 * backwards-compatible at the assembly level.
340 OPC_MUL
= use_mips32r6_instructions
? OPC_MUL_R6
: OPC_MUL_R5
,
342 /* MIPS r6 introduced names for weaker variants of SYNC. These are
343 backward compatible to previous architecture revisions. */
344 OPC_SYNC_WMB
= OPC_SYNC
| 0x04 << 5,
345 OPC_SYNC_MB
= OPC_SYNC
| 0x10 << 5,
346 OPC_SYNC_ACQUIRE
= OPC_SYNC
| 0x11 << 5,
347 OPC_SYNC_RELEASE
= OPC_SYNC
| 0x12 << 5,
348 OPC_SYNC_RMB
= OPC_SYNC
| 0x13 << 5,
354 static inline void tcg_out_opc_reg(TCGContext
*s
, MIPSInsn opc
,
355 TCGReg rd
, TCGReg rs
, TCGReg rt
)
360 inst
|= (rs
& 0x1F) << 21;
361 inst
|= (rt
& 0x1F) << 16;
362 inst
|= (rd
& 0x1F) << 11;
369 static inline void tcg_out_opc_imm(TCGContext
*s
, MIPSInsn opc
,
370 TCGReg rt
, TCGReg rs
, TCGArg imm
)
375 inst
|= (rs
& 0x1F) << 21;
376 inst
|= (rt
& 0x1F) << 16;
377 inst
|= (imm
& 0xffff);
384 static inline void tcg_out_opc_bf(TCGContext
*s
, MIPSInsn opc
, TCGReg rt
,
385 TCGReg rs
, int msb
, int lsb
)
390 inst
|= (rs
& 0x1F) << 21;
391 inst
|= (rt
& 0x1F) << 16;
392 inst
|= (msb
& 0x1F) << 11;
393 inst
|= (lsb
& 0x1F) << 6;
400 static inline void tcg_out_opc_br(TCGContext
*s
, MIPSInsn opc
,
401 TCGReg rt
, TCGReg rs
)
403 /* We pay attention here to not modify the branch target by reading
404 the existing value and using it again. This ensure that caches and
405 memory are kept coherent during retranslation. */
406 uint16_t offset
= (uint16_t)*s
->code_ptr
;
408 tcg_out_opc_imm(s
, opc
, rt
, rs
, offset
);
414 static inline void tcg_out_opc_sa(TCGContext
*s
, MIPSInsn opc
,
415 TCGReg rd
, TCGReg rt
, TCGArg sa
)
420 inst
|= (rt
& 0x1F) << 16;
421 inst
|= (rd
& 0x1F) << 11;
422 inst
|= (sa
& 0x1F) << 6;
429 * Returns true if the branch was in range and the insn was emitted.
431 static bool tcg_out_opc_jmp(TCGContext
*s
, MIPSInsn opc
, void *target
)
433 uintptr_t dest
= (uintptr_t)target
;
434 uintptr_t from
= (uintptr_t)s
->code_ptr
+ 4;
437 /* The pc-region branch happens within the 256MB region of
438 the delay slot (thus the +4). */
439 if ((from
^ dest
) & -(1 << 28)) {
442 tcg_debug_assert((dest
& 3) == 0);
445 inst
|= (dest
>> 2) & 0x3ffffff;
450 static inline void tcg_out_nop(TCGContext
*s
)
455 static inline void tcg_out_mov(TCGContext
*s
, TCGType type
,
456 TCGReg ret
, TCGReg arg
)
458 /* Simple reg-reg move, optimising out the 'do nothing' case */
460 tcg_out_opc_reg(s
, OPC_ADDU
, ret
, arg
, TCG_REG_ZERO
);
464 static inline void tcg_out_movi(TCGContext
*s
, TCGType type
,
465 TCGReg reg
, tcg_target_long arg
)
467 if (arg
== (int16_t)arg
) {
468 tcg_out_opc_imm(s
, OPC_ADDIU
, reg
, TCG_REG_ZERO
, arg
);
469 } else if (arg
== (uint16_t)arg
) {
470 tcg_out_opc_imm(s
, OPC_ORI
, reg
, TCG_REG_ZERO
, arg
);
472 tcg_out_opc_imm(s
, OPC_LUI
, reg
, TCG_REG_ZERO
, arg
>> 16);
474 tcg_out_opc_imm(s
, OPC_ORI
, reg
, reg
, arg
& 0xffff);
479 static inline void tcg_out_bswap16(TCGContext
*s
, TCGReg ret
, TCGReg arg
)
481 if (use_mips32r2_instructions
) {
482 tcg_out_opc_reg(s
, OPC_WSBH
, ret
, 0, arg
);
484 /* ret and arg can't be register at */
485 if (ret
== TCG_TMP0
|| arg
== TCG_TMP0
) {
489 tcg_out_opc_sa(s
, OPC_SRL
, TCG_TMP0
, arg
, 8);
490 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 8);
491 tcg_out_opc_imm(s
, OPC_ANDI
, ret
, ret
, 0xff00);
492 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_TMP0
);
496 static inline void tcg_out_bswap16s(TCGContext
*s
, TCGReg ret
, TCGReg arg
)
498 if (use_mips32r2_instructions
) {
499 tcg_out_opc_reg(s
, OPC_WSBH
, ret
, 0, arg
);
500 tcg_out_opc_reg(s
, OPC_SEH
, ret
, 0, ret
);
502 /* ret and arg can't be register at */
503 if (ret
== TCG_TMP0
|| arg
== TCG_TMP0
) {
507 tcg_out_opc_sa(s
, OPC_SRL
, TCG_TMP0
, arg
, 8);
508 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 24);
509 tcg_out_opc_sa(s
, OPC_SRA
, ret
, ret
, 16);
510 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_TMP0
);
514 static void tcg_out_bswap_subr(TCGContext
*s
, tcg_insn_unit
*sub
)
516 bool ok
= tcg_out_opc_jmp(s
, OPC_JAL
, sub
);
517 tcg_debug_assert(ok
);
520 static void tcg_out_bswap32(TCGContext
*s
, TCGReg ret
, TCGReg arg
)
522 if (use_mips32r2_instructions
) {
523 tcg_out_opc_reg(s
, OPC_WSBH
, ret
, 0, arg
);
524 tcg_out_opc_sa(s
, OPC_ROTR
, ret
, ret
, 16);
526 tcg_out_bswap_subr(s
, bswap32_addr
);
527 /* delay slot -- never omit the insn, like tcg_out_mov might. */
528 tcg_out_opc_reg(s
, OPC_OR
, TCG_TMP0
, arg
, TCG_REG_ZERO
);
529 tcg_out_mov(s
, TCG_TYPE_I32
, ret
, TCG_TMP3
);
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 TMP0, TMP1, 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 opc
= get_memop(oi
);
1044 unsigned s_bits
= opc
& MO_SIZE
;
1045 unsigned a_bits
= get_alignment_bits(opc
);
1046 int mem_index
= get_mmuidx(oi
);
1049 ? offsetof(CPUArchState
, tlb_table
[mem_index
][0].addr_read
)
1050 : offsetof(CPUArchState
, tlb_table
[mem_index
][0].addr_write
));
1051 int add_off
= offsetof(CPUArchState
, tlb_table
[mem_index
][0].addend
);
1053 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_A0
, addrl
,
1054 TARGET_PAGE_BITS
- CPU_TLB_ENTRY_BITS
);
1055 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_A0
, TCG_REG_A0
,
1056 (CPU_TLB_SIZE
- 1) << CPU_TLB_ENTRY_BITS
);
1057 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_A0
, TCG_REG_A0
, TCG_AREG0
);
1059 /* Compensate for very large offsets. */
1060 if (add_off
>= 0x8000) {
1061 /* Most target env are smaller than 32k; none are larger than 64k.
1062 Simplify the logic here merely to offset by 0x7ff0, giving us a
1063 range just shy of 64k. Check this assumption. */
1064 QEMU_BUILD_BUG_ON(offsetof(CPUArchState
,
1065 tlb_table
[NB_MMU_MODES
- 1][1])
1067 tcg_out_opc_imm(s
, OPC_ADDIU
, TCG_REG_A0
, TCG_REG_A0
, 0x7ff0);
1072 /* Load the (low half) tlb comparator. */
1073 tcg_out_opc_imm(s
, OPC_LW
, TCG_TMP0
, TCG_REG_A0
,
1074 cmp_off
+ (TARGET_LONG_BITS
== 64 ? LO_OFF
: 0));
1076 /* We don't currently support unaligned accesses.
1077 We could do so with mips32r6. */
1078 if (a_bits
< s_bits
) {
1081 /* Mask the page bits, keeping the alignment bits to compare against.
1082 In between on 32-bit targets, load the tlb addend for the fast path. */
1083 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_TMP1
,
1084 TARGET_PAGE_MASK
| ((1 << a_bits
) - 1));
1085 if (TARGET_LONG_BITS
== 32) {
1086 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_A0
, TCG_REG_A0
, add_off
);
1088 tcg_out_opc_reg(s
, OPC_AND
, TCG_TMP1
, TCG_TMP1
, addrl
);
1090 label_ptr
[0] = s
->code_ptr
;
1091 tcg_out_opc_br(s
, OPC_BNE
, TCG_TMP1
, TCG_TMP0
);
1093 /* Load and test the high half tlb comparator. */
1094 if (TARGET_LONG_BITS
== 64) {
1096 tcg_out_opc_imm(s
, OPC_LW
, TCG_TMP0
, TCG_REG_A0
, cmp_off
+ HI_OFF
);
1098 /* Load the tlb addend for the fast path. We can't do it earlier with
1099 64-bit targets or we'll clobber a0 before reading the high half tlb
1101 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_A0
, TCG_REG_A0
, add_off
);
1103 label_ptr
[1] = s
->code_ptr
;
1104 tcg_out_opc_br(s
, OPC_BNE
, addrh
, TCG_TMP0
);
1108 tcg_out_opc_reg(s
, OPC_ADDU
, base
, TCG_REG_A0
, addrl
);
1111 static void add_qemu_ldst_label(TCGContext
*s
, int is_ld
, TCGMemOpIdx oi
,
1112 TCGReg datalo
, TCGReg datahi
,
1113 TCGReg addrlo
, TCGReg addrhi
,
1114 void *raddr
, tcg_insn_unit
*label_ptr
[2])
1116 TCGLabelQemuLdst
*label
= new_ldst_label(s
);
1118 label
->is_ld
= is_ld
;
1120 label
->datalo_reg
= datalo
;
1121 label
->datahi_reg
= datahi
;
1122 label
->addrlo_reg
= addrlo
;
1123 label
->addrhi_reg
= addrhi
;
1124 label
->raddr
= raddr
;
1125 label
->label_ptr
[0] = label_ptr
[0];
1126 if (TARGET_LONG_BITS
== 64) {
1127 label
->label_ptr
[1] = label_ptr
[1];
1131 static void tcg_out_qemu_ld_slow_path(TCGContext
*s
, TCGLabelQemuLdst
*l
)
1133 TCGMemOpIdx oi
= l
->oi
;
1134 TCGMemOp opc
= get_memop(oi
);
1138 /* resolve label address */
1139 reloc_pc16(l
->label_ptr
[0], s
->code_ptr
);
1140 if (TARGET_LONG_BITS
== 64) {
1141 reloc_pc16(l
->label_ptr
[1], s
->code_ptr
);
1145 if (TARGET_LONG_BITS
== 64) {
1146 i
= tcg_out_call_iarg_reg2(s
, i
, l
->addrlo_reg
, l
->addrhi_reg
);
1148 i
= tcg_out_call_iarg_reg(s
, i
, l
->addrlo_reg
);
1150 i
= tcg_out_call_iarg_imm(s
, i
, oi
);
1151 i
= tcg_out_call_iarg_imm(s
, i
, (intptr_t)l
->raddr
);
1152 tcg_out_call_int(s
, qemu_ld_helpers
[opc
& (MO_BSWAP
| MO_SSIZE
)], false);
1154 tcg_out_mov(s
, TCG_TYPE_PTR
, tcg_target_call_iarg_regs
[0], TCG_AREG0
);
1157 if ((opc
& MO_SIZE
) == MO_64
) {
1158 /* We eliminated V0 from the possible output registers, so it
1159 cannot be clobbered here. So we must move V1 first. */
1161 tcg_out_mov(s
, TCG_TYPE_I32
, v0
, TCG_REG_V1
);
1164 tcg_out_mov(s
, TCG_TYPE_I32
, l
->datahi_reg
, TCG_REG_V1
);
1168 reloc_pc16(s
->code_ptr
, l
->raddr
);
1169 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_ZERO
, TCG_REG_ZERO
);
1171 tcg_out_mov(s
, TCG_TYPE_REG
, v0
, TCG_REG_V0
);
1174 static void tcg_out_qemu_st_slow_path(TCGContext
*s
, TCGLabelQemuLdst
*l
)
1176 TCGMemOpIdx oi
= l
->oi
;
1177 TCGMemOp opc
= get_memop(oi
);
1178 TCGMemOp s_bits
= opc
& MO_SIZE
;
1181 /* resolve label address */
1182 reloc_pc16(l
->label_ptr
[0], s
->code_ptr
);
1183 if (TARGET_LONG_BITS
== 64) {
1184 reloc_pc16(l
->label_ptr
[1], s
->code_ptr
);
1188 if (TARGET_LONG_BITS
== 64) {
1189 i
= tcg_out_call_iarg_reg2(s
, i
, l
->addrlo_reg
, l
->addrhi_reg
);
1191 i
= tcg_out_call_iarg_reg(s
, i
, l
->addrlo_reg
);
1195 i
= tcg_out_call_iarg_reg8(s
, i
, l
->datalo_reg
);
1198 i
= tcg_out_call_iarg_reg16(s
, i
, l
->datalo_reg
);
1201 i
= tcg_out_call_iarg_reg(s
, i
, l
->datalo_reg
);
1204 i
= tcg_out_call_iarg_reg2(s
, i
, l
->datalo_reg
, l
->datahi_reg
);
1209 i
= tcg_out_call_iarg_imm(s
, i
, oi
);
1211 /* Tail call to the store helper. Thus force the return address
1212 computation to take place in the return address register. */
1213 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_RA
, (intptr_t)l
->raddr
);
1214 i
= tcg_out_call_iarg_reg(s
, i
, TCG_REG_RA
);
1215 tcg_out_call_int(s
, qemu_st_helpers
[opc
& (MO_BSWAP
| MO_SIZE
)], true);
1217 tcg_out_mov(s
, TCG_TYPE_PTR
, tcg_target_call_iarg_regs
[0], TCG_AREG0
);
1221 static void tcg_out_qemu_ld_direct(TCGContext
*s
, TCGReg lo
, TCGReg hi
,
1222 TCGReg base
, TCGMemOp opc
)
1224 switch (opc
& (MO_SSIZE
| MO_BSWAP
)) {
1226 tcg_out_opc_imm(s
, OPC_LBU
, lo
, base
, 0);
1229 tcg_out_opc_imm(s
, OPC_LB
, lo
, base
, 0);
1231 case MO_UW
| MO_BSWAP
:
1232 tcg_out_opc_imm(s
, OPC_LHU
, TCG_TMP1
, base
, 0);
1233 tcg_out_bswap16(s
, lo
, TCG_TMP1
);
1236 tcg_out_opc_imm(s
, OPC_LHU
, lo
, base
, 0);
1238 case MO_SW
| MO_BSWAP
:
1239 tcg_out_opc_imm(s
, OPC_LHU
, TCG_TMP1
, base
, 0);
1240 tcg_out_bswap16s(s
, lo
, TCG_TMP1
);
1243 tcg_out_opc_imm(s
, OPC_LH
, lo
, base
, 0);
1245 case MO_UL
| MO_BSWAP
:
1246 if (use_mips32r2_instructions
) {
1247 tcg_out_opc_imm(s
, OPC_LW
, lo
, base
, 0);
1248 tcg_out_bswap32(s
, lo
, lo
);
1250 tcg_out_bswap_subr(s
, bswap32_addr
);
1252 tcg_out_opc_imm(s
, OPC_LW
, TCG_TMP0
, base
, 0);
1253 tcg_out_mov(s
, TCG_TYPE_I32
, lo
, TCG_TMP3
);
1257 tcg_out_opc_imm(s
, OPC_LW
, lo
, base
, 0);
1259 case MO_Q
| MO_BSWAP
:
1260 if (use_mips32r2_instructions
) {
1261 tcg_out_opc_imm(s
, OPC_LW
, TCG_TMP0
, base
, 0);
1262 tcg_out_opc_imm(s
, OPC_LW
, TCG_TMP1
, base
, 4);
1263 tcg_out_opc_reg(s
, OPC_WSBH
, TCG_TMP0
, 0, TCG_TMP0
);
1264 tcg_out_opc_reg(s
, OPC_WSBH
, TCG_TMP1
, 0, TCG_TMP1
);
1265 tcg_out_opc_sa(s
, OPC_ROTR
, MIPS_BE
? lo
: hi
, TCG_TMP0
, 16);
1266 tcg_out_opc_sa(s
, OPC_ROTR
, MIPS_BE
? hi
: lo
, TCG_TMP1
, 16);
1268 tcg_out_bswap_subr(s
, bswap32_addr
);
1270 tcg_out_opc_imm(s
, OPC_LW
, TCG_TMP0
, base
, 0);
1271 tcg_out_opc_imm(s
, OPC_LW
, TCG_TMP0
, base
, 4);
1272 tcg_out_bswap_subr(s
, bswap32_addr
);
1274 tcg_out_mov(s
, TCG_TYPE_I32
, MIPS_BE
? lo
: hi
, TCG_TMP3
);
1275 tcg_out_mov(s
, TCG_TYPE_I32
, MIPS_BE
? hi
: lo
, TCG_TMP3
);
1279 /* Prefer to load from offset 0 first, but allow for overlap. */
1280 if (MIPS_BE
? hi
!= base
: lo
== base
) {
1281 tcg_out_opc_imm(s
, OPC_LW
, hi
, base
, HI_OFF
);
1282 tcg_out_opc_imm(s
, OPC_LW
, lo
, base
, LO_OFF
);
1284 tcg_out_opc_imm(s
, OPC_LW
, lo
, base
, LO_OFF
);
1285 tcg_out_opc_imm(s
, OPC_LW
, hi
, base
, HI_OFF
);
1293 static void tcg_out_qemu_ld(TCGContext
*s
, const TCGArg
*args
, bool is_64
)
1295 TCGReg addr_regl
, addr_regh
__attribute__((unused
));
1296 TCGReg data_regl
, data_regh
;
1299 #if defined(CONFIG_SOFTMMU)
1300 tcg_insn_unit
*label_ptr
[2];
1302 TCGReg base
= TCG_REG_A0
;
1304 data_regl
= *args
++;
1305 data_regh
= (is_64
? *args
++ : 0);
1306 addr_regl
= *args
++;
1307 addr_regh
= (TARGET_LONG_BITS
== 64 ? *args
++ : 0);
1309 opc
= get_memop(oi
);
1311 #if defined(CONFIG_SOFTMMU)
1312 tcg_out_tlb_load(s
, base
, addr_regl
, addr_regh
, oi
, label_ptr
, 1);
1313 tcg_out_qemu_ld_direct(s
, data_regl
, data_regh
, base
, opc
);
1314 add_qemu_ldst_label(s
, 1, oi
, data_regl
, data_regh
, addr_regl
, addr_regh
,
1315 s
->code_ptr
, label_ptr
);
1317 if (guest_base
== 0 && data_regl
!= addr_regl
) {
1319 } else if (guest_base
== (int16_t)guest_base
) {
1320 tcg_out_opc_imm(s
, OPC_ADDIU
, base
, addr_regl
, guest_base
);
1322 tcg_out_movi(s
, TCG_TYPE_PTR
, base
, guest_base
);
1323 tcg_out_opc_reg(s
, OPC_ADDU
, base
, base
, addr_regl
);
1325 tcg_out_qemu_ld_direct(s
, data_regl
, data_regh
, base
, opc
);
1329 static void tcg_out_qemu_st_direct(TCGContext
*s
, TCGReg lo
, TCGReg hi
,
1330 TCGReg base
, TCGMemOp opc
)
1332 /* Don't clutter the code below with checks to avoid bswapping ZERO. */
1333 if ((lo
| hi
) == 0) {
1337 switch (opc
& (MO_SIZE
| MO_BSWAP
)) {
1339 tcg_out_opc_imm(s
, OPC_SB
, lo
, base
, 0);
1342 case MO_16
| MO_BSWAP
:
1343 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_TMP1
, lo
, 0xffff);
1344 tcg_out_bswap16(s
, TCG_TMP1
, TCG_TMP1
);
1348 tcg_out_opc_imm(s
, OPC_SH
, lo
, base
, 0);
1351 case MO_32
| MO_BSWAP
:
1352 tcg_out_bswap32(s
, TCG_TMP3
, lo
);
1356 tcg_out_opc_imm(s
, OPC_SW
, lo
, base
, 0);
1359 case MO_64
| MO_BSWAP
:
1360 if (use_mips32r2_instructions
) {
1361 tcg_out_opc_reg(s
, OPC_WSBH
, TCG_TMP0
, 0, MIPS_BE
? lo
: hi
);
1362 tcg_out_opc_reg(s
, OPC_WSBH
, TCG_TMP1
, 0, MIPS_BE
? hi
: lo
);
1363 tcg_out_opc_sa(s
, OPC_ROTR
, TCG_TMP0
, TCG_TMP0
, 16);
1364 tcg_out_opc_sa(s
, OPC_ROTR
, TCG_TMP1
, TCG_TMP1
, 16);
1365 tcg_out_opc_imm(s
, OPC_SW
, TCG_TMP0
, base
, 0);
1366 tcg_out_opc_imm(s
, OPC_SW
, TCG_TMP1
, base
, 4);
1368 tcg_out_bswap32(s
, TCG_TMP3
, MIPS_BE
? lo
: hi
);
1369 tcg_out_opc_imm(s
, OPC_SW
, TCG_TMP3
, base
, 0);
1370 tcg_out_bswap32(s
, TCG_TMP3
, MIPS_BE
? hi
: lo
);
1371 tcg_out_opc_imm(s
, OPC_SW
, TCG_TMP3
, base
, 4);
1375 tcg_out_opc_imm(s
, OPC_SW
, MIPS_BE
? hi
: lo
, base
, 0);
1376 tcg_out_opc_imm(s
, OPC_SW
, MIPS_BE
? lo
: hi
, base
, 4);
1384 static void tcg_out_qemu_st(TCGContext
*s
, const TCGArg
*args
, bool is_64
)
1386 TCGReg addr_regl
, addr_regh
__attribute__((unused
));
1387 TCGReg data_regl
, data_regh
;
1390 #if defined(CONFIG_SOFTMMU)
1391 tcg_insn_unit
*label_ptr
[2];
1393 TCGReg base
= TCG_REG_A0
;
1395 data_regl
= *args
++;
1396 data_regh
= (is_64
? *args
++ : 0);
1397 addr_regl
= *args
++;
1398 addr_regh
= (TARGET_LONG_BITS
== 64 ? *args
++ : 0);
1400 opc
= get_memop(oi
);
1402 #if defined(CONFIG_SOFTMMU)
1403 tcg_out_tlb_load(s
, base
, addr_regl
, addr_regh
, oi
, label_ptr
, 0);
1404 tcg_out_qemu_st_direct(s
, data_regl
, data_regh
, base
, opc
);
1405 add_qemu_ldst_label(s
, 0, oi
, data_regl
, data_regh
, addr_regl
, addr_regh
,
1406 s
->code_ptr
, label_ptr
);
1408 if (guest_base
== 0) {
1411 if (guest_base
== (int16_t)guest_base
) {
1412 tcg_out_opc_imm(s
, OPC_ADDIU
, base
, addr_regl
, guest_base
);
1414 tcg_out_movi(s
, TCG_TYPE_PTR
, base
, guest_base
);
1415 tcg_out_opc_reg(s
, OPC_ADDU
, base
, base
, addr_regl
);
1418 tcg_out_qemu_st_direct(s
, data_regl
, data_regh
, base
, opc
);
1422 static void tcg_out_mb(TCGContext
*s
, TCGArg a0
)
1424 static const MIPSInsn sync
[] = {
1425 /* Note that SYNC_MB is a slightly weaker than SYNC 0,
1426 as the former is an ordering barrier and the latter
1427 is a completion barrier. */
1428 [0 ... TCG_MO_ALL
] = OPC_SYNC_MB
,
1429 [TCG_MO_LD_LD
] = OPC_SYNC_RMB
,
1430 [TCG_MO_ST_ST
] = OPC_SYNC_WMB
,
1431 [TCG_MO_LD_ST
] = OPC_SYNC_RELEASE
,
1432 [TCG_MO_LD_ST
| TCG_MO_ST_ST
] = OPC_SYNC_RELEASE
,
1433 [TCG_MO_LD_ST
| TCG_MO_LD_LD
] = OPC_SYNC_ACQUIRE
,
1435 tcg_out32(s
, sync
[a0
& TCG_MO_ALL
]);
1438 static inline void tcg_out_op(TCGContext
*s
, TCGOpcode opc
,
1439 const TCGArg
*args
, const int *const_args
)
1451 case INDEX_op_exit_tb
:
1453 TCGReg b0
= TCG_REG_ZERO
;
1456 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_V0
, a0
& ~0xffff);
1459 if (!tcg_out_opc_jmp(s
, OPC_J
, tb_ret_addr
)) {
1460 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_TMP0
,
1461 (uintptr_t)tb_ret_addr
);
1462 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_TMP0
, 0);
1464 tcg_out_opc_imm(s
, OPC_ORI
, TCG_REG_V0
, b0
, a0
& 0xffff);
1467 case INDEX_op_goto_tb
:
1468 if (s
->tb_jmp_insn_offset
) {
1469 /* direct jump method */
1470 s
->tb_jmp_insn_offset
[a0
] = tcg_current_code_size(s
);
1471 /* Avoid clobbering the address during retranslation. */
1472 tcg_out32(s
, OPC_J
| (*(uint32_t *)s
->code_ptr
& 0x3ffffff));
1474 /* indirect jump method */
1475 tcg_out_ld(s
, TCG_TYPE_PTR
, TCG_TMP0
, TCG_REG_ZERO
,
1476 (uintptr_t)(s
->tb_jmp_target_addr
+ a0
));
1477 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_TMP0
, 0);
1480 s
->tb_jmp_reset_offset
[a0
] = tcg_current_code_size(s
);
1483 tcg_out_brcond(s
, TCG_COND_EQ
, TCG_REG_ZERO
, TCG_REG_ZERO
,
1487 case INDEX_op_ld8u_i32
:
1490 case INDEX_op_ld8s_i32
:
1493 case INDEX_op_ld16u_i32
:
1496 case INDEX_op_ld16s_i32
:
1499 case INDEX_op_ld_i32
:
1502 case INDEX_op_st8_i32
:
1505 case INDEX_op_st16_i32
:
1508 case INDEX_op_st_i32
:
1511 tcg_out_ldst(s
, i1
, a0
, a1
, a2
);
1514 case INDEX_op_add_i32
:
1515 i1
= OPC_ADDU
, i2
= OPC_ADDIU
;
1517 case INDEX_op_or_i32
:
1518 i1
= OPC_OR
, i2
= OPC_ORI
;
1520 case INDEX_op_xor_i32
:
1521 i1
= OPC_XOR
, i2
= OPC_XORI
;
1524 tcg_out_opc_imm(s
, i2
, a0
, a1
, a2
);
1528 tcg_out_opc_reg(s
, i1
, a0
, a1
, a2
);
1531 case INDEX_op_sub_i32
:
1533 tcg_out_opc_imm(s
, OPC_ADDIU
, a0
, a1
, -a2
);
1538 case INDEX_op_and_i32
:
1539 if (c2
&& a2
!= (uint16_t)a2
) {
1540 int msb
= ctz32(~a2
) - 1;
1541 tcg_debug_assert(use_mips32r2_instructions
);
1542 tcg_debug_assert(is_p2m1(a2
));
1543 tcg_out_opc_bf(s
, OPC_EXT
, a0
, a1
, msb
, 0);
1546 i1
= OPC_AND
, i2
= OPC_ANDI
;
1548 case INDEX_op_nor_i32
:
1552 case INDEX_op_mul_i32
:
1553 if (use_mips32_instructions
) {
1554 tcg_out_opc_reg(s
, OPC_MUL
, a0
, a1
, a2
);
1557 i1
= OPC_MULT
, i2
= OPC_MFLO
;
1559 case INDEX_op_mulsh_i32
:
1560 if (use_mips32r6_instructions
) {
1561 tcg_out_opc_reg(s
, OPC_MUH
, a0
, a1
, a2
);
1564 i1
= OPC_MULT
, i2
= OPC_MFHI
;
1566 case INDEX_op_muluh_i32
:
1567 if (use_mips32r6_instructions
) {
1568 tcg_out_opc_reg(s
, OPC_MUHU
, a0
, a1
, a2
);
1571 i1
= OPC_MULTU
, i2
= OPC_MFHI
;
1573 case INDEX_op_div_i32
:
1574 if (use_mips32r6_instructions
) {
1575 tcg_out_opc_reg(s
, OPC_DIV_R6
, a0
, a1
, a2
);
1578 i1
= OPC_DIV
, i2
= OPC_MFLO
;
1580 case INDEX_op_divu_i32
:
1581 if (use_mips32r6_instructions
) {
1582 tcg_out_opc_reg(s
, OPC_DIVU_R6
, a0
, a1
, a2
);
1585 i1
= OPC_DIVU
, i2
= OPC_MFLO
;
1587 case INDEX_op_rem_i32
:
1588 if (use_mips32r6_instructions
) {
1589 tcg_out_opc_reg(s
, OPC_MOD
, a0
, a1
, a2
);
1592 i1
= OPC_DIV
, i2
= OPC_MFHI
;
1594 case INDEX_op_remu_i32
:
1595 if (use_mips32r6_instructions
) {
1596 tcg_out_opc_reg(s
, OPC_MODU
, a0
, a1
, a2
);
1599 i1
= OPC_DIVU
, i2
= OPC_MFHI
;
1601 tcg_out_opc_reg(s
, i1
, 0, a1
, a2
);
1602 tcg_out_opc_reg(s
, i2
, a0
, 0, 0);
1605 case INDEX_op_muls2_i32
:
1608 case INDEX_op_mulu2_i32
:
1611 tcg_out_opc_reg(s
, i1
, 0, a2
, args
[3]);
1612 tcg_out_opc_reg(s
, OPC_MFLO
, a0
, 0, 0);
1613 tcg_out_opc_reg(s
, OPC_MFHI
, a1
, 0, 0);
1616 case INDEX_op_not_i32
:
1619 case INDEX_op_bswap16_i32
:
1622 case INDEX_op_ext8s_i32
:
1625 case INDEX_op_ext16s_i32
:
1628 tcg_out_opc_reg(s
, i1
, a0
, TCG_REG_ZERO
, a1
);
1631 case INDEX_op_sar_i32
:
1632 i1
= OPC_SRAV
, i2
= OPC_SRA
;
1634 case INDEX_op_shl_i32
:
1635 i1
= OPC_SLLV
, i2
= OPC_SLL
;
1637 case INDEX_op_shr_i32
:
1638 i1
= OPC_SRLV
, i2
= OPC_SRL
;
1640 case INDEX_op_rotr_i32
:
1641 i1
= OPC_ROTRV
, i2
= OPC_ROTR
;
1644 tcg_out_opc_sa(s
, i2
, a0
, a1
, a2
);
1646 tcg_out_opc_reg(s
, i1
, a0
, a2
, a1
);
1649 case INDEX_op_rotl_i32
:
1651 tcg_out_opc_sa(s
, OPC_ROTR
, a0
, a1
, 32 - a2
);
1653 tcg_out_opc_reg(s
, OPC_SUBU
, TCG_TMP0
, TCG_REG_ZERO
, a2
);
1654 tcg_out_opc_reg(s
, OPC_ROTRV
, a0
, TCG_TMP0
, a1
);
1658 case INDEX_op_bswap32_i32
:
1659 tcg_out_bswap32(s
, a0
, a1
);
1662 case INDEX_op_deposit_i32
:
1663 tcg_out_opc_bf(s
, OPC_INS
, a0
, a2
, args
[3] + args
[4] - 1, args
[3]);
1666 case INDEX_op_brcond_i32
:
1667 tcg_out_brcond(s
, a2
, a0
, a1
, arg_label(args
[3]));
1669 case INDEX_op_brcond2_i32
:
1670 tcg_out_brcond2(s
, args
[4], a0
, a1
, a2
, args
[3], arg_label(args
[5]));
1673 case INDEX_op_movcond_i32
:
1674 tcg_out_movcond(s
, args
[5], a0
, a1
, a2
, args
[3], args
[4]);
1677 case INDEX_op_setcond_i32
:
1678 tcg_out_setcond(s
, args
[3], a0
, a1
, a2
);
1680 case INDEX_op_setcond2_i32
:
1681 tcg_out_setcond2(s
, args
[5], a0
, a1
, a2
, args
[3], args
[4]);
1684 case INDEX_op_qemu_ld_i32
:
1685 tcg_out_qemu_ld(s
, args
, false);
1687 case INDEX_op_qemu_ld_i64
:
1688 tcg_out_qemu_ld(s
, args
, true);
1690 case INDEX_op_qemu_st_i32
:
1691 tcg_out_qemu_st(s
, args
, false);
1693 case INDEX_op_qemu_st_i64
:
1694 tcg_out_qemu_st(s
, args
, true);
1697 case INDEX_op_add2_i32
:
1698 tcg_out_addsub2(s
, a0
, a1
, a2
, args
[3], args
[4], args
[5],
1699 const_args
[4], const_args
[5], false);
1701 case INDEX_op_sub2_i32
:
1702 tcg_out_addsub2(s
, a0
, a1
, a2
, args
[3], args
[4], args
[5],
1703 const_args
[4], const_args
[5], true);
1709 case INDEX_op_mov_i32
: /* Always emitted via tcg_out_mov. */
1710 case INDEX_op_movi_i32
: /* Always emitted via tcg_out_movi. */
1711 case INDEX_op_call
: /* Always emitted via tcg_out_call. */
1717 static const TCGTargetOpDef mips_op_defs
[] = {
1718 { INDEX_op_exit_tb
, { } },
1719 { INDEX_op_goto_tb
, { } },
1720 { INDEX_op_br
, { } },
1722 { INDEX_op_ld8u_i32
, { "r", "r" } },
1723 { INDEX_op_ld8s_i32
, { "r", "r" } },
1724 { INDEX_op_ld16u_i32
, { "r", "r" } },
1725 { INDEX_op_ld16s_i32
, { "r", "r" } },
1726 { INDEX_op_ld_i32
, { "r", "r" } },
1727 { INDEX_op_st8_i32
, { "rZ", "r" } },
1728 { INDEX_op_st16_i32
, { "rZ", "r" } },
1729 { INDEX_op_st_i32
, { "rZ", "r" } },
1731 { INDEX_op_add_i32
, { "r", "rZ", "rJ" } },
1732 { INDEX_op_mul_i32
, { "r", "rZ", "rZ" } },
1733 #if !use_mips32r6_instructions
1734 { INDEX_op_muls2_i32
, { "r", "r", "rZ", "rZ" } },
1735 { INDEX_op_mulu2_i32
, { "r", "r", "rZ", "rZ" } },
1737 { INDEX_op_mulsh_i32
, { "r", "rZ", "rZ" } },
1738 { INDEX_op_muluh_i32
, { "r", "rZ", "rZ" } },
1739 { INDEX_op_div_i32
, { "r", "rZ", "rZ" } },
1740 { INDEX_op_divu_i32
, { "r", "rZ", "rZ" } },
1741 { INDEX_op_rem_i32
, { "r", "rZ", "rZ" } },
1742 { INDEX_op_remu_i32
, { "r", "rZ", "rZ" } },
1743 { INDEX_op_sub_i32
, { "r", "rZ", "rN" } },
1745 { INDEX_op_and_i32
, { "r", "rZ", "rIK" } },
1746 { INDEX_op_nor_i32
, { "r", "rZ", "rZ" } },
1747 { INDEX_op_not_i32
, { "r", "rZ" } },
1748 { INDEX_op_or_i32
, { "r", "rZ", "rIZ" } },
1749 { INDEX_op_xor_i32
, { "r", "rZ", "rIZ" } },
1751 { INDEX_op_shl_i32
, { "r", "rZ", "ri" } },
1752 { INDEX_op_shr_i32
, { "r", "rZ", "ri" } },
1753 { INDEX_op_sar_i32
, { "r", "rZ", "ri" } },
1754 { INDEX_op_rotr_i32
, { "r", "rZ", "ri" } },
1755 { INDEX_op_rotl_i32
, { "r", "rZ", "ri" } },
1757 { INDEX_op_bswap16_i32
, { "r", "r" } },
1758 { INDEX_op_bswap32_i32
, { "r", "r" } },
1760 { INDEX_op_ext8s_i32
, { "r", "rZ" } },
1761 { INDEX_op_ext16s_i32
, { "r", "rZ" } },
1763 { INDEX_op_deposit_i32
, { "r", "0", "rZ" } },
1765 { INDEX_op_brcond_i32
, { "rZ", "rZ" } },
1766 #if use_mips32r6_instructions
1767 { INDEX_op_movcond_i32
, { "r", "rZ", "rZ", "rZ", "rZ" } },
1769 { INDEX_op_movcond_i32
, { "r", "rZ", "rZ", "rZ", "0" } },
1771 { INDEX_op_setcond_i32
, { "r", "rZ", "rZ" } },
1772 { INDEX_op_setcond2_i32
, { "r", "rZ", "rZ", "rZ", "rZ" } },
1774 { INDEX_op_add2_i32
, { "r", "r", "rZ", "rZ", "rN", "rN" } },
1775 { INDEX_op_sub2_i32
, { "r", "r", "rZ", "rZ", "rN", "rN" } },
1776 { INDEX_op_brcond2_i32
, { "rZ", "rZ", "rZ", "rZ" } },
1778 #if TARGET_LONG_BITS == 32
1779 { INDEX_op_qemu_ld_i32
, { "r", "LZ" } },
1780 { INDEX_op_qemu_st_i32
, { "SZ", "SZ" } },
1781 { INDEX_op_qemu_ld_i64
, { "r", "r", "LZ" } },
1782 { INDEX_op_qemu_st_i64
, { "SZ", "SZ", "SZ" } },
1784 { INDEX_op_qemu_ld_i32
, { "r", "LZ", "LZ" } },
1785 { INDEX_op_qemu_st_i32
, { "SZ", "SZ", "SZ" } },
1786 { INDEX_op_qemu_ld_i64
, { "r", "r", "LZ", "LZ" } },
1787 { INDEX_op_qemu_st_i64
, { "SZ", "SZ", "SZ", "SZ" } },
1790 { INDEX_op_mb
, { } },
1794 static int tcg_target_callee_save_regs
[] = {
1795 TCG_REG_S0
, /* used for the global env (TCG_AREG0) */
1804 TCG_REG_RA
, /* should be last for ABI compliance */
1807 /* The Linux kernel doesn't provide any information about the available
1808 instruction set. Probe it using a signal handler. */
1811 #ifndef use_movnz_instructions
1812 bool use_movnz_instructions
= false;
1815 #ifndef use_mips32_instructions
1816 bool use_mips32_instructions
= false;
1819 #ifndef use_mips32r2_instructions
1820 bool use_mips32r2_instructions
= false;
1823 static volatile sig_atomic_t got_sigill
;
1825 static void sigill_handler(int signo
, siginfo_t
*si
, void *data
)
1827 /* Skip the faulty instruction */
1828 ucontext_t
*uc
= (ucontext_t
*)data
;
1829 uc
->uc_mcontext
.pc
+= 4;
1834 static void tcg_target_detect_isa(void)
1836 struct sigaction sa_old
, sa_new
;
1838 memset(&sa_new
, 0, sizeof(sa_new
));
1839 sa_new
.sa_flags
= SA_SIGINFO
;
1840 sa_new
.sa_sigaction
= sigill_handler
;
1841 sigaction(SIGILL
, &sa_new
, &sa_old
);
1843 /* Probe for movn/movz, necessary to implement movcond. */
1844 #ifndef use_movnz_instructions
1846 asm volatile(".set push\n"
1848 "movn $zero, $zero, $zero\n"
1849 "movz $zero, $zero, $zero\n"
1852 use_movnz_instructions
= !got_sigill
;
1855 /* Probe for MIPS32 instructions. As no subsetting is allowed
1856 by the specification, it is only necessary to probe for one
1857 of the instructions. */
1858 #ifndef use_mips32_instructions
1860 asm volatile(".set push\n"
1862 "mul $zero, $zero\n"
1865 use_mips32_instructions
= !got_sigill
;
1868 /* Probe for MIPS32r2 instructions if MIPS32 instructions are
1869 available. As no subsetting is allowed by the specification,
1870 it is only necessary to probe for one of the instructions. */
1871 #ifndef use_mips32r2_instructions
1872 if (use_mips32_instructions
) {
1874 asm volatile(".set push\n"
1876 "seb $zero, $zero\n"
1879 use_mips32r2_instructions
= !got_sigill
;
1883 sigaction(SIGILL
, &sa_old
, NULL
);
1886 static tcg_insn_unit
*align_code_ptr(TCGContext
*s
)
1888 uintptr_t p
= (uintptr_t)s
->code_ptr
;
1891 s
->code_ptr
= (void *)p
;
1896 /* Generate global QEMU prologue and epilogue code */
1897 static void tcg_target_qemu_prologue(TCGContext
*s
)
1901 /* reserve some stack space, also for TCG temps. */
1902 frame_size
= ARRAY_SIZE(tcg_target_callee_save_regs
) * 4
1903 + TCG_STATIC_CALL_ARGS_SIZE
1904 + CPU_TEMP_BUF_NLONGS
* sizeof(long);
1905 frame_size
= (frame_size
+ TCG_TARGET_STACK_ALIGN
- 1) &
1906 ~(TCG_TARGET_STACK_ALIGN
- 1);
1907 tcg_set_frame(s
, TCG_REG_SP
, ARRAY_SIZE(tcg_target_callee_save_regs
) * 4
1908 + TCG_STATIC_CALL_ARGS_SIZE
,
1909 CPU_TEMP_BUF_NLONGS
* sizeof(long));
1912 tcg_out_addi(s
, TCG_REG_SP
, -frame_size
);
1913 for(i
= 0 ; i
< ARRAY_SIZE(tcg_target_callee_save_regs
) ; i
++) {
1914 tcg_out_st(s
, TCG_TYPE_I32
, tcg_target_callee_save_regs
[i
],
1915 TCG_REG_SP
, TCG_STATIC_CALL_ARGS_SIZE
+ i
* 4);
1918 /* Call generated code */
1919 tcg_out_opc_reg(s
, OPC_JR
, 0, tcg_target_call_iarg_regs
[1], 0);
1920 tcg_out_mov(s
, TCG_TYPE_PTR
, TCG_AREG0
, tcg_target_call_iarg_regs
[0]);
1921 tb_ret_addr
= s
->code_ptr
;
1924 for(i
= 0 ; i
< ARRAY_SIZE(tcg_target_callee_save_regs
) ; i
++) {
1925 tcg_out_ld(s
, TCG_TYPE_I32
, tcg_target_callee_save_regs
[i
],
1926 TCG_REG_SP
, TCG_STATIC_CALL_ARGS_SIZE
+ i
* 4);
1929 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_RA
, 0);
1931 tcg_out_addi(s
, TCG_REG_SP
, frame_size
);
1933 if (use_mips32r2_instructions
) {
1937 /* Bswap subroutine: Input in TCG_TMP0, output in TCG_TMP3;
1938 clobbers TCG_TMP1, TCG_TMP2. */
1941 * bswap32 -- 32-bit swap (signed result for mips64). a0 = abcd.
1943 bswap32_addr
= align_code_ptr(s
);
1944 /* t3 = (ssss)d000 */
1945 tcg_out_opc_sa(s
, OPC_SLL
, TCG_TMP3
, TCG_TMP0
, 24);
1947 tcg_out_opc_sa(s
, OPC_SRL
, TCG_TMP1
, TCG_TMP0
, 24);
1949 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_TMP2
, TCG_TMP0
, 0xff00);
1951 tcg_out_opc_reg(s
, OPC_OR
, TCG_TMP3
, TCG_TMP3
, TCG_TMP1
);
1953 tcg_out_opc_sa(s
, OPC_SRL
, TCG_TMP1
, TCG_TMP0
, 8);
1955 tcg_out_opc_sa(s
, OPC_SLL
, TCG_TMP2
, TCG_TMP2
, 8);
1957 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_TMP1
, TCG_TMP1
, 0xff00);
1959 tcg_out_opc_reg(s
, OPC_OR
, TCG_TMP3
, TCG_TMP3
, TCG_TMP2
);
1960 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_RA
, 0);
1961 /* t3 = dcba -- delay slot */
1962 tcg_out_opc_reg(s
, OPC_OR
, TCG_TMP3
, TCG_TMP3
, TCG_TMP1
);
1965 static void tcg_target_init(TCGContext
*s
)
1967 tcg_target_detect_isa();
1968 tcg_regset_set(tcg_target_available_regs
[TCG_TYPE_I32
], 0xffffffff);
1969 tcg_regset_set(tcg_target_call_clobber_regs
,
1987 tcg_regset_clear(s
->reserved_regs
);
1988 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_ZERO
); /* zero register */
1989 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_K0
); /* kernel use only */
1990 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_K1
); /* kernel use only */
1991 tcg_regset_set_reg(s
->reserved_regs
, TCG_TMP0
); /* internal use */
1992 tcg_regset_set_reg(s
->reserved_regs
, TCG_TMP1
); /* internal use */
1993 tcg_regset_set_reg(s
->reserved_regs
, TCG_TMP2
); /* internal use */
1994 tcg_regset_set_reg(s
->reserved_regs
, TCG_TMP3
); /* internal use */
1995 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_RA
); /* return address */
1996 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_SP
); /* stack pointer */
1997 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_GP
); /* global pointer */
1999 tcg_add_target_add_op_defs(mips_op_defs
);
2002 void tb_set_jmp_target1(uintptr_t jmp_addr
, uintptr_t addr
)
2004 atomic_set((uint32_t *)jmp_addr
, deposit32(OPC_J
, 0, 26, addr
>> 2));
2005 flush_icache_range(jmp_addr
, jmp_addr
+ 4);