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 */
261 OPC_BLEZ
= 006 << 26,
262 OPC_BGTZ
= 007 << 26,
263 OPC_ADDIU
= 011 << 26,
264 OPC_SLTI
= 012 << 26,
265 OPC_SLTIU
= 013 << 26,
266 OPC_ANDI
= 014 << 26,
268 OPC_XORI
= 016 << 26,
270 OPC_DADDIU
= 031 << 26,
283 OPC_SPECIAL
= 000 << 26,
284 OPC_SLL
= OPC_SPECIAL
| 000,
285 OPC_SRL
= OPC_SPECIAL
| 002,
286 OPC_ROTR
= OPC_SPECIAL
| 002 | (1 << 21),
287 OPC_SRA
= OPC_SPECIAL
| 003,
288 OPC_SLLV
= OPC_SPECIAL
| 004,
289 OPC_SRLV
= OPC_SPECIAL
| 006,
290 OPC_ROTRV
= OPC_SPECIAL
| 006 | 0100,
291 OPC_SRAV
= OPC_SPECIAL
| 007,
292 OPC_JR_R5
= OPC_SPECIAL
| 010,
293 OPC_JALR
= OPC_SPECIAL
| 011,
294 OPC_MOVZ
= OPC_SPECIAL
| 012,
295 OPC_MOVN
= OPC_SPECIAL
| 013,
296 OPC_SYNC
= OPC_SPECIAL
| 017,
297 OPC_MFHI
= OPC_SPECIAL
| 020,
298 OPC_MFLO
= OPC_SPECIAL
| 022,
299 OPC_DSLLV
= OPC_SPECIAL
| 024,
300 OPC_DSRLV
= OPC_SPECIAL
| 026,
301 OPC_DROTRV
= OPC_SPECIAL
| 026 | 0100,
302 OPC_DSRAV
= OPC_SPECIAL
| 027,
303 OPC_MULT
= OPC_SPECIAL
| 030,
304 OPC_MUL_R6
= OPC_SPECIAL
| 030 | 0200,
305 OPC_MUH
= OPC_SPECIAL
| 030 | 0300,
306 OPC_MULTU
= OPC_SPECIAL
| 031,
307 OPC_MULU
= OPC_SPECIAL
| 031 | 0200,
308 OPC_MUHU
= OPC_SPECIAL
| 031 | 0300,
309 OPC_DIV
= OPC_SPECIAL
| 032,
310 OPC_DIV_R6
= OPC_SPECIAL
| 032 | 0200,
311 OPC_MOD
= OPC_SPECIAL
| 032 | 0300,
312 OPC_DIVU
= OPC_SPECIAL
| 033,
313 OPC_DIVU_R6
= OPC_SPECIAL
| 033 | 0200,
314 OPC_MODU
= OPC_SPECIAL
| 033 | 0300,
315 OPC_DMULT
= OPC_SPECIAL
| 034,
316 OPC_DMUL
= OPC_SPECIAL
| 034 | 0200,
317 OPC_DMUH
= OPC_SPECIAL
| 034 | 0300,
318 OPC_DMULTU
= OPC_SPECIAL
| 035,
319 OPC_DMULU
= OPC_SPECIAL
| 035 | 0200,
320 OPC_DMUHU
= OPC_SPECIAL
| 035 | 0300,
321 OPC_DDIV
= OPC_SPECIAL
| 036,
322 OPC_DDIV_R6
= OPC_SPECIAL
| 036 | 0200,
323 OPC_DMOD
= OPC_SPECIAL
| 036 | 0300,
324 OPC_DDIVU
= OPC_SPECIAL
| 037,
325 OPC_DDIVU_R6
= OPC_SPECIAL
| 037 | 0200,
326 OPC_DMODU
= OPC_SPECIAL
| 037 | 0300,
327 OPC_ADDU
= OPC_SPECIAL
| 041,
328 OPC_SUBU
= OPC_SPECIAL
| 043,
329 OPC_AND
= OPC_SPECIAL
| 044,
330 OPC_OR
= OPC_SPECIAL
| 045,
331 OPC_XOR
= OPC_SPECIAL
| 046,
332 OPC_NOR
= OPC_SPECIAL
| 047,
333 OPC_SLT
= OPC_SPECIAL
| 052,
334 OPC_SLTU
= OPC_SPECIAL
| 053,
335 OPC_DADDU
= OPC_SPECIAL
| 055,
336 OPC_DSUBU
= OPC_SPECIAL
| 057,
337 OPC_SELEQZ
= OPC_SPECIAL
| 065,
338 OPC_SELNEZ
= OPC_SPECIAL
| 067,
339 OPC_DSLL
= OPC_SPECIAL
| 070,
340 OPC_DSRL
= OPC_SPECIAL
| 072,
341 OPC_DROTR
= OPC_SPECIAL
| 072 | (1 << 21),
342 OPC_DSRA
= OPC_SPECIAL
| 073,
343 OPC_DSLL32
= OPC_SPECIAL
| 074,
344 OPC_DSRL32
= OPC_SPECIAL
| 076,
345 OPC_DROTR32
= OPC_SPECIAL
| 076 | (1 << 21),
346 OPC_DSRA32
= OPC_SPECIAL
| 077,
348 OPC_REGIMM
= 001 << 26,
349 OPC_BLTZ
= OPC_REGIMM
| (000 << 16),
350 OPC_BGEZ
= OPC_REGIMM
| (001 << 16),
352 OPC_SPECIAL2
= 034 << 26,
353 OPC_MUL_R5
= OPC_SPECIAL2
| 002,
355 OPC_SPECIAL3
= 037 << 26,
356 OPC_EXT
= OPC_SPECIAL3
| 000,
357 OPC_DEXTM
= OPC_SPECIAL3
| 001,
358 OPC_DEXTU
= OPC_SPECIAL3
| 002,
359 OPC_DEXT
= OPC_SPECIAL3
| 003,
360 OPC_INS
= OPC_SPECIAL3
| 004,
361 OPC_DINSM
= OPC_SPECIAL3
| 005,
362 OPC_DINSU
= OPC_SPECIAL3
| 006,
363 OPC_DINS
= OPC_SPECIAL3
| 007,
364 OPC_WSBH
= OPC_SPECIAL3
| 00240,
365 OPC_DSBH
= OPC_SPECIAL3
| 00244,
366 OPC_DSHD
= OPC_SPECIAL3
| 00544,
367 OPC_SEB
= OPC_SPECIAL3
| 02040,
368 OPC_SEH
= OPC_SPECIAL3
| 03040,
370 /* MIPS r6 doesn't have JR, JALR should be used instead */
371 OPC_JR
= use_mips32r6_instructions
? OPC_JALR
: OPC_JR_R5
,
374 * MIPS r6 replaces MUL with an alternative encoding which is
375 * backwards-compatible at the assembly level.
377 OPC_MUL
= use_mips32r6_instructions
? OPC_MUL_R6
: OPC_MUL_R5
,
379 /* MIPS r6 introduced names for weaker variants of SYNC. These are
380 backward compatible to previous architecture revisions. */
381 OPC_SYNC_WMB
= OPC_SYNC
| 0x04 << 5,
382 OPC_SYNC_MB
= OPC_SYNC
| 0x10 << 5,
383 OPC_SYNC_ACQUIRE
= OPC_SYNC
| 0x11 << 5,
384 OPC_SYNC_RELEASE
= OPC_SYNC
| 0x12 << 5,
385 OPC_SYNC_RMB
= OPC_SYNC
| 0x13 << 5,
387 /* Aliases for convenience. */
388 ALIAS_PADD
= sizeof(void *) == 4 ? OPC_ADDU
: OPC_DADDU
,
389 ALIAS_PADDI
= sizeof(void *) == 4 ? OPC_ADDIU
: OPC_DADDIU
,
390 ALIAS_TSRL
= TARGET_LONG_BITS
== 32 || TCG_TARGET_REG_BITS
== 32
391 ? OPC_SRL
: OPC_DSRL
,
397 static inline void tcg_out_opc_reg(TCGContext
*s
, MIPSInsn opc
,
398 TCGReg rd
, TCGReg rs
, TCGReg rt
)
403 inst
|= (rs
& 0x1F) << 21;
404 inst
|= (rt
& 0x1F) << 16;
405 inst
|= (rd
& 0x1F) << 11;
412 static inline void tcg_out_opc_imm(TCGContext
*s
, MIPSInsn opc
,
413 TCGReg rt
, TCGReg rs
, TCGArg imm
)
418 inst
|= (rs
& 0x1F) << 21;
419 inst
|= (rt
& 0x1F) << 16;
420 inst
|= (imm
& 0xffff);
427 static inline void tcg_out_opc_bf(TCGContext
*s
, MIPSInsn opc
, TCGReg rt
,
428 TCGReg rs
, int msb
, int lsb
)
433 inst
|= (rs
& 0x1F) << 21;
434 inst
|= (rt
& 0x1F) << 16;
435 inst
|= (msb
& 0x1F) << 11;
436 inst
|= (lsb
& 0x1F) << 6;
443 static inline void tcg_out_opc_br(TCGContext
*s
, MIPSInsn opc
,
444 TCGReg rt
, TCGReg rs
)
446 /* We pay attention here to not modify the branch target by reading
447 the existing value and using it again. This ensure that caches and
448 memory are kept coherent during retranslation. */
449 uint16_t offset
= (uint16_t)*s
->code_ptr
;
451 tcg_out_opc_imm(s
, opc
, rt
, rs
, offset
);
457 static inline void tcg_out_opc_sa(TCGContext
*s
, MIPSInsn opc
,
458 TCGReg rd
, TCGReg rt
, TCGArg sa
)
463 inst
|= (rt
& 0x1F) << 16;
464 inst
|= (rd
& 0x1F) << 11;
465 inst
|= (sa
& 0x1F) << 6;
472 * Returns true if the branch was in range and the insn was emitted.
474 static bool tcg_out_opc_jmp(TCGContext
*s
, MIPSInsn opc
, void *target
)
476 uintptr_t dest
= (uintptr_t)target
;
477 uintptr_t from
= (uintptr_t)s
->code_ptr
+ 4;
480 /* The pc-region branch happens within the 256MB region of
481 the delay slot (thus the +4). */
482 if ((from
^ dest
) & -(1 << 28)) {
485 tcg_debug_assert((dest
& 3) == 0);
488 inst
|= (dest
>> 2) & 0x3ffffff;
493 static inline void tcg_out_nop(TCGContext
*s
)
498 static inline void tcg_out_mov(TCGContext
*s
, TCGType type
,
499 TCGReg ret
, TCGReg arg
)
501 /* Simple reg-reg move, optimising out the 'do nothing' case */
503 tcg_out_opc_reg(s
, OPC_ADDU
, ret
, arg
, TCG_REG_ZERO
);
507 static inline void tcg_out_movi(TCGContext
*s
, TCGType type
,
508 TCGReg reg
, tcg_target_long arg
)
510 if (arg
== (int16_t)arg
) {
511 tcg_out_opc_imm(s
, OPC_ADDIU
, reg
, TCG_REG_ZERO
, arg
);
512 } else if (arg
== (uint16_t)arg
) {
513 tcg_out_opc_imm(s
, OPC_ORI
, reg
, TCG_REG_ZERO
, arg
);
515 tcg_out_opc_imm(s
, OPC_LUI
, reg
, TCG_REG_ZERO
, arg
>> 16);
517 tcg_out_opc_imm(s
, OPC_ORI
, reg
, reg
, arg
& 0xffff);
522 static inline void tcg_out_bswap16(TCGContext
*s
, TCGReg ret
, TCGReg arg
)
524 if (use_mips32r2_instructions
) {
525 tcg_out_opc_reg(s
, OPC_WSBH
, ret
, 0, arg
);
527 /* ret and arg can't be register at */
528 if (ret
== TCG_TMP0
|| arg
== TCG_TMP0
) {
532 tcg_out_opc_sa(s
, OPC_SRL
, TCG_TMP0
, arg
, 8);
533 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 8);
534 tcg_out_opc_imm(s
, OPC_ANDI
, ret
, ret
, 0xff00);
535 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_TMP0
);
539 static inline void tcg_out_bswap16s(TCGContext
*s
, TCGReg ret
, TCGReg arg
)
541 if (use_mips32r2_instructions
) {
542 tcg_out_opc_reg(s
, OPC_WSBH
, ret
, 0, arg
);
543 tcg_out_opc_reg(s
, OPC_SEH
, ret
, 0, ret
);
545 /* ret and arg can't be register at */
546 if (ret
== TCG_TMP0
|| arg
== TCG_TMP0
) {
550 tcg_out_opc_sa(s
, OPC_SRL
, TCG_TMP0
, arg
, 8);
551 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 24);
552 tcg_out_opc_sa(s
, OPC_SRA
, ret
, ret
, 16);
553 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_TMP0
);
557 static void tcg_out_bswap_subr(TCGContext
*s
, tcg_insn_unit
*sub
)
559 bool ok
= tcg_out_opc_jmp(s
, OPC_JAL
, sub
);
560 tcg_debug_assert(ok
);
563 static void tcg_out_bswap32(TCGContext
*s
, TCGReg ret
, TCGReg arg
)
565 if (use_mips32r2_instructions
) {
566 tcg_out_opc_reg(s
, OPC_WSBH
, ret
, 0, arg
);
567 tcg_out_opc_sa(s
, OPC_ROTR
, ret
, ret
, 16);
569 tcg_out_bswap_subr(s
, bswap32_addr
);
570 /* delay slot -- never omit the insn, like tcg_out_mov might. */
571 tcg_out_opc_reg(s
, OPC_OR
, TCG_TMP0
, arg
, TCG_REG_ZERO
);
572 tcg_out_mov(s
, TCG_TYPE_I32
, ret
, TCG_TMP3
);
576 static inline void tcg_out_ext8s(TCGContext
*s
, TCGReg ret
, TCGReg arg
)
578 if (use_mips32r2_instructions
) {
579 tcg_out_opc_reg(s
, OPC_SEB
, ret
, 0, arg
);
581 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 24);
582 tcg_out_opc_sa(s
, OPC_SRA
, ret
, ret
, 24);
586 static inline void tcg_out_ext16s(TCGContext
*s
, TCGReg ret
, TCGReg arg
)
588 if (use_mips32r2_instructions
) {
589 tcg_out_opc_reg(s
, OPC_SEH
, ret
, 0, arg
);
591 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 16);
592 tcg_out_opc_sa(s
, OPC_SRA
, ret
, ret
, 16);
596 static void tcg_out_ldst(TCGContext
*s
, MIPSInsn opc
, TCGReg data
,
597 TCGReg addr
, intptr_t ofs
)
601 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_TMP0
, ofs
- lo
);
602 if (addr
!= TCG_REG_ZERO
) {
603 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_TMP0
, TCG_TMP0
, addr
);
607 tcg_out_opc_imm(s
, opc
, data
, addr
, lo
);
610 static inline void tcg_out_ld(TCGContext
*s
, TCGType type
, TCGReg arg
,
611 TCGReg arg1
, intptr_t arg2
)
613 tcg_out_ldst(s
, OPC_LW
, arg
, arg1
, arg2
);
616 static inline void tcg_out_st(TCGContext
*s
, TCGType type
, TCGReg arg
,
617 TCGReg arg1
, intptr_t arg2
)
619 tcg_out_ldst(s
, OPC_SW
, arg
, arg1
, arg2
);
622 static inline bool tcg_out_sti(TCGContext
*s
, TCGType type
, TCGArg val
,
623 TCGReg base
, intptr_t ofs
)
626 tcg_out_st(s
, type
, TCG_REG_ZERO
, base
, ofs
);
632 static inline void tcg_out_addi(TCGContext
*s
, TCGReg reg
, TCGArg val
)
634 if (val
== (int16_t)val
) {
635 tcg_out_opc_imm(s
, OPC_ADDIU
, reg
, reg
, val
);
637 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_TMP0
, val
);
638 tcg_out_opc_reg(s
, OPC_ADDU
, reg
, reg
, TCG_TMP0
);
642 static void tcg_out_addsub2(TCGContext
*s
, TCGReg rl
, TCGReg rh
, TCGReg al
,
643 TCGReg ah
, TCGArg bl
, TCGArg bh
, bool cbl
,
644 bool cbh
, bool is_sub
)
646 TCGReg th
= TCG_TMP1
;
648 /* If we have a negative constant such that negating it would
649 make the high part zero, we can (usually) eliminate one insn. */
650 if (cbl
&& cbh
&& bh
== -1 && bl
!= 0) {
656 /* By operating on the high part first, we get to use the final
657 carry operation to move back from the temporary. */
659 tcg_out_opc_reg(s
, (is_sub
? OPC_SUBU
: OPC_ADDU
), th
, ah
, bh
);
660 } else if (bh
!= 0 || ah
== rl
) {
661 tcg_out_opc_imm(s
, OPC_ADDIU
, th
, ah
, (is_sub
? -bh
: bh
));
666 /* Note that tcg optimization should eliminate the bl == 0 case. */
669 tcg_out_opc_imm(s
, OPC_SLTIU
, TCG_TMP0
, al
, bl
);
670 tcg_out_opc_imm(s
, OPC_ADDIU
, rl
, al
, -bl
);
672 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_TMP0
, al
, bl
);
673 tcg_out_opc_reg(s
, OPC_SUBU
, rl
, al
, bl
);
675 tcg_out_opc_reg(s
, OPC_SUBU
, rh
, th
, TCG_TMP0
);
678 tcg_out_opc_imm(s
, OPC_ADDIU
, rl
, al
, bl
);
679 tcg_out_opc_imm(s
, OPC_SLTIU
, TCG_TMP0
, rl
, bl
);
680 } else if (rl
== al
&& rl
== bl
) {
681 tcg_out_opc_sa(s
, OPC_SRL
, TCG_TMP0
, al
, 31);
682 tcg_out_opc_reg(s
, OPC_ADDU
, rl
, al
, bl
);
684 tcg_out_opc_reg(s
, OPC_ADDU
, rl
, al
, bl
);
685 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_TMP0
, rl
, (rl
== bl
? al
: bl
));
687 tcg_out_opc_reg(s
, OPC_ADDU
, rh
, th
, TCG_TMP0
);
691 /* Bit 0 set if inversion required; bit 1 set if swapping required. */
692 #define MIPS_CMP_INV 1
693 #define MIPS_CMP_SWAP 2
695 static const uint8_t mips_cmp_map
[16] = {
698 [TCG_COND_GE
] = MIPS_CMP_INV
,
699 [TCG_COND_GEU
] = MIPS_CMP_INV
,
700 [TCG_COND_LE
] = MIPS_CMP_INV
| MIPS_CMP_SWAP
,
701 [TCG_COND_LEU
] = MIPS_CMP_INV
| MIPS_CMP_SWAP
,
702 [TCG_COND_GT
] = MIPS_CMP_SWAP
,
703 [TCG_COND_GTU
] = MIPS_CMP_SWAP
,
706 static void tcg_out_setcond(TCGContext
*s
, TCGCond cond
, TCGReg ret
,
707 TCGReg arg1
, TCGReg arg2
)
709 MIPSInsn s_opc
= OPC_SLTU
;
715 tcg_out_opc_reg(s
, OPC_XOR
, ret
, arg1
, arg2
);
718 tcg_out_opc_imm(s
, OPC_SLTIU
, ret
, arg1
, 1);
723 tcg_out_opc_reg(s
, OPC_XOR
, ret
, arg1
, arg2
);
726 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, TCG_REG_ZERO
, arg1
);
740 cmp_map
= mips_cmp_map
[cond
];
741 if (cmp_map
& MIPS_CMP_SWAP
) {
746 tcg_out_opc_reg(s
, s_opc
, ret
, arg1
, arg2
);
747 if (cmp_map
& MIPS_CMP_INV
) {
748 tcg_out_opc_imm(s
, OPC_XORI
, ret
, ret
, 1);
758 static void tcg_out_brcond(TCGContext
*s
, TCGCond cond
, TCGReg arg1
,
759 TCGReg arg2
, TCGLabel
*l
)
761 static const MIPSInsn b_zero
[16] = {
762 [TCG_COND_LT
] = OPC_BLTZ
,
763 [TCG_COND_GT
] = OPC_BGTZ
,
764 [TCG_COND_LE
] = OPC_BLEZ
,
765 [TCG_COND_GE
] = OPC_BGEZ
,
768 MIPSInsn s_opc
= OPC_SLTU
;
785 b_opc
= b_zero
[cond
];
797 cmp_map
= mips_cmp_map
[cond
];
798 if (cmp_map
& MIPS_CMP_SWAP
) {
803 tcg_out_opc_reg(s
, s_opc
, TCG_TMP0
, arg1
, arg2
);
804 b_opc
= (cmp_map
& MIPS_CMP_INV
? OPC_BEQ
: OPC_BNE
);
814 tcg_out_opc_br(s
, b_opc
, arg1
, arg2
);
816 reloc_pc16(s
->code_ptr
- 1, l
->u
.value_ptr
);
818 tcg_out_reloc(s
, s
->code_ptr
- 1, R_MIPS_PC16
, l
, 0);
823 static TCGReg
tcg_out_reduce_eq2(TCGContext
*s
, TCGReg tmp0
, TCGReg tmp1
,
824 TCGReg al
, TCGReg ah
,
825 TCGReg bl
, TCGReg bh
)
827 /* Merge highpart comparison into AH. */
830 tcg_out_opc_reg(s
, OPC_XOR
, tmp0
, ah
, bh
);
836 /* Merge lowpart comparison into AL. */
839 tcg_out_opc_reg(s
, OPC_XOR
, tmp1
, al
, bl
);
845 /* Merge high and low part comparisons into AL. */
848 tcg_out_opc_reg(s
, OPC_OR
, tmp0
, ah
, al
);
857 static void tcg_out_setcond2(TCGContext
*s
, TCGCond cond
, TCGReg ret
,
858 TCGReg al
, TCGReg ah
, TCGReg bl
, TCGReg bh
)
860 TCGReg tmp0
= TCG_TMP0
;
863 tcg_debug_assert(ret
!= TCG_TMP0
);
864 if (ret
== ah
|| ret
== bh
) {
865 tcg_debug_assert(ret
!= TCG_TMP1
);
872 tmp1
= tcg_out_reduce_eq2(s
, tmp0
, tmp1
, al
, ah
, bl
, bh
);
873 tcg_out_setcond(s
, cond
, ret
, tmp1
, TCG_REG_ZERO
);
877 tcg_out_setcond(s
, TCG_COND_EQ
, tmp0
, ah
, bh
);
878 tcg_out_setcond(s
, tcg_unsigned_cond(cond
), tmp1
, al
, bl
);
879 tcg_out_opc_reg(s
, OPC_AND
, tmp1
, tmp1
, tmp0
);
880 tcg_out_setcond(s
, tcg_high_cond(cond
), tmp0
, ah
, bh
);
881 tcg_out_opc_reg(s
, OPC_OR
, ret
, tmp1
, tmp0
);
886 static void tcg_out_brcond2(TCGContext
*s
, TCGCond cond
, TCGReg al
, TCGReg ah
,
887 TCGReg bl
, TCGReg bh
, TCGLabel
*l
)
889 TCGCond b_cond
= TCG_COND_NE
;
890 TCGReg tmp
= TCG_TMP1
;
892 /* With branches, we emit between 4 and 9 insns with 2 or 3 branches.
893 With setcond, we emit between 3 and 10 insns and only 1 branch,
894 which ought to get better branch prediction. */
899 tmp
= tcg_out_reduce_eq2(s
, TCG_TMP0
, TCG_TMP1
, al
, ah
, bl
, bh
);
903 /* Minimize code size by preferring a compare not requiring INV. */
904 if (mips_cmp_map
[cond
] & MIPS_CMP_INV
) {
905 cond
= tcg_invert_cond(cond
);
906 b_cond
= TCG_COND_EQ
;
908 tcg_out_setcond2(s
, cond
, tmp
, al
, ah
, bl
, bh
);
912 tcg_out_brcond(s
, b_cond
, tmp
, TCG_REG_ZERO
, l
);
915 static void tcg_out_movcond(TCGContext
*s
, TCGCond cond
, TCGReg ret
,
916 TCGReg c1
, TCGReg c2
, TCGReg v1
, TCGReg v2
)
920 /* If one of the values is zero, put it last to match SEL*Z instructions */
921 if (use_mips32r6_instructions
&& v1
== 0) {
924 cond
= tcg_invert_cond(cond
);
933 tcg_out_opc_reg(s
, OPC_XOR
, TCG_TMP0
, c1
, c2
);
939 /* Minimize code size by preferring a compare not requiring INV. */
940 if (mips_cmp_map
[cond
] & MIPS_CMP_INV
) {
941 cond
= tcg_invert_cond(cond
);
944 tcg_out_setcond(s
, cond
, TCG_TMP0
, c1
, c2
);
949 if (use_mips32r6_instructions
) {
950 MIPSInsn m_opc_t
= eqz
? OPC_SELEQZ
: OPC_SELNEZ
;
951 MIPSInsn m_opc_f
= eqz
? OPC_SELNEZ
: OPC_SELEQZ
;
954 tcg_out_opc_reg(s
, m_opc_f
, TCG_TMP1
, v2
, c1
);
956 tcg_out_opc_reg(s
, m_opc_t
, ret
, v1
, c1
);
958 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_TMP1
);
961 MIPSInsn m_opc
= eqz
? OPC_MOVZ
: OPC_MOVN
;
963 tcg_out_opc_reg(s
, m_opc
, ret
, v1
, c1
);
965 /* This should be guaranteed via constraints */
966 tcg_debug_assert(v2
== ret
);
970 static void tcg_out_call_int(TCGContext
*s
, tcg_insn_unit
*arg
, bool tail
)
972 /* Note that the ABI requires the called function's address to be
973 loaded into T9, even if a direct branch is in range. */
974 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_T9
, (uintptr_t)arg
);
976 /* But do try a direct branch, allowing the cpu better insn prefetch. */
978 if (!tcg_out_opc_jmp(s
, OPC_J
, arg
)) {
979 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_T9
, 0);
982 if (!tcg_out_opc_jmp(s
, OPC_JAL
, arg
)) {
983 tcg_out_opc_reg(s
, OPC_JALR
, TCG_REG_RA
, TCG_REG_T9
, 0);
988 static void tcg_out_call(TCGContext
*s
, tcg_insn_unit
*arg
)
990 tcg_out_call_int(s
, arg
, false);
994 #if defined(CONFIG_SOFTMMU)
995 static void * const qemu_ld_helpers
[16] = {
996 [MO_UB
] = helper_ret_ldub_mmu
,
997 [MO_SB
] = helper_ret_ldsb_mmu
,
998 [MO_LEUW
] = helper_le_lduw_mmu
,
999 [MO_LESW
] = helper_le_ldsw_mmu
,
1000 [MO_LEUL
] = helper_le_ldul_mmu
,
1001 [MO_LEQ
] = helper_le_ldq_mmu
,
1002 [MO_BEUW
] = helper_be_lduw_mmu
,
1003 [MO_BESW
] = helper_be_ldsw_mmu
,
1004 [MO_BEUL
] = helper_be_ldul_mmu
,
1005 [MO_BEQ
] = helper_be_ldq_mmu
,
1008 static void * const qemu_st_helpers
[16] = {
1009 [MO_UB
] = helper_ret_stb_mmu
,
1010 [MO_LEUW
] = helper_le_stw_mmu
,
1011 [MO_LEUL
] = helper_le_stl_mmu
,
1012 [MO_LEQ
] = helper_le_stq_mmu
,
1013 [MO_BEUW
] = helper_be_stw_mmu
,
1014 [MO_BEUL
] = helper_be_stl_mmu
,
1015 [MO_BEQ
] = helper_be_stq_mmu
,
1018 /* Helper routines for marshalling helper function arguments into
1019 * the correct registers and stack.
1020 * I is where we want to put this argument, and is updated and returned
1021 * for the next call. ARG is the argument itself.
1023 * We provide routines for arguments which are: immediate, 32 bit
1024 * value in register, 16 and 8 bit values in register (which must be zero
1025 * extended before use) and 64 bit value in a lo:hi register pair.
1028 static int tcg_out_call_iarg_reg(TCGContext
*s
, int i
, TCGReg arg
)
1030 if (i
< ARRAY_SIZE(tcg_target_call_iarg_regs
)) {
1031 tcg_out_mov(s
, TCG_TYPE_REG
, tcg_target_call_iarg_regs
[i
], arg
);
1033 tcg_out_st(s
, TCG_TYPE_REG
, arg
, TCG_REG_SP
, 4 * i
);
1038 static int tcg_out_call_iarg_reg8(TCGContext
*s
, int i
, TCGReg arg
)
1040 TCGReg tmp
= TCG_TMP0
;
1041 if (i
< ARRAY_SIZE(tcg_target_call_iarg_regs
)) {
1042 tmp
= tcg_target_call_iarg_regs
[i
];
1044 tcg_out_opc_imm(s
, OPC_ANDI
, tmp
, arg
, 0xff);
1045 return tcg_out_call_iarg_reg(s
, i
, tmp
);
1048 static int tcg_out_call_iarg_reg16(TCGContext
*s
, int i
, TCGReg arg
)
1050 TCGReg tmp
= TCG_TMP0
;
1051 if (i
< ARRAY_SIZE(tcg_target_call_iarg_regs
)) {
1052 tmp
= tcg_target_call_iarg_regs
[i
];
1054 tcg_out_opc_imm(s
, OPC_ANDI
, tmp
, arg
, 0xffff);
1055 return tcg_out_call_iarg_reg(s
, i
, tmp
);
1058 static int tcg_out_call_iarg_imm(TCGContext
*s
, int i
, TCGArg arg
)
1060 TCGReg tmp
= TCG_TMP0
;
1064 if (i
< ARRAY_SIZE(tcg_target_call_iarg_regs
)) {
1065 tmp
= tcg_target_call_iarg_regs
[i
];
1067 tcg_out_movi(s
, TCG_TYPE_REG
, tmp
, arg
);
1069 return tcg_out_call_iarg_reg(s
, i
, tmp
);
1072 static int tcg_out_call_iarg_reg2(TCGContext
*s
, int i
, TCGReg al
, TCGReg ah
)
1075 i
= tcg_out_call_iarg_reg(s
, i
, (MIPS_BE
? ah
: al
));
1076 i
= tcg_out_call_iarg_reg(s
, i
, (MIPS_BE
? al
: ah
));
1080 /* Perform the tlb comparison operation. The complete host address is
1081 placed in BASE. Clobbers TMP0, TMP1, A0. */
1082 static void tcg_out_tlb_load(TCGContext
*s
, TCGReg base
, TCGReg addrl
,
1083 TCGReg addrh
, TCGMemOpIdx oi
,
1084 tcg_insn_unit
*label_ptr
[2], bool is_load
)
1086 TCGMemOp opc
= get_memop(oi
);
1087 unsigned s_bits
= opc
& MO_SIZE
;
1088 unsigned a_bits
= get_alignment_bits(opc
);
1089 int mem_index
= get_mmuidx(oi
);
1092 ? offsetof(CPUArchState
, tlb_table
[mem_index
][0].addr_read
)
1093 : offsetof(CPUArchState
, tlb_table
[mem_index
][0].addr_write
));
1094 int add_off
= offsetof(CPUArchState
, tlb_table
[mem_index
][0].addend
);
1096 tcg_out_opc_sa(s
, OPC_SRL
, TCG_REG_A0
, addrl
,
1097 TARGET_PAGE_BITS
- CPU_TLB_ENTRY_BITS
);
1098 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_A0
, TCG_REG_A0
,
1099 (CPU_TLB_SIZE
- 1) << CPU_TLB_ENTRY_BITS
);
1100 tcg_out_opc_reg(s
, OPC_ADDU
, TCG_REG_A0
, TCG_REG_A0
, TCG_AREG0
);
1102 /* Compensate for very large offsets. */
1103 if (add_off
>= 0x8000) {
1104 /* Most target env are smaller than 32k; none are larger than 64k.
1105 Simplify the logic here merely to offset by 0x7ff0, giving us a
1106 range just shy of 64k. Check this assumption. */
1107 QEMU_BUILD_BUG_ON(offsetof(CPUArchState
,
1108 tlb_table
[NB_MMU_MODES
- 1][1])
1110 tcg_out_opc_imm(s
, OPC_ADDIU
, TCG_REG_A0
, TCG_REG_A0
, 0x7ff0);
1115 /* Load the (low half) tlb comparator. */
1116 tcg_out_opc_imm(s
, OPC_LW
, TCG_TMP0
, TCG_REG_A0
,
1117 cmp_off
+ (TARGET_LONG_BITS
== 64 ? LO_OFF
: 0));
1119 /* We don't currently support unaligned accesses.
1120 We could do so with mips32r6. */
1121 if (a_bits
< s_bits
) {
1124 /* Mask the page bits, keeping the alignment bits to compare against.
1125 In between on 32-bit targets, load the tlb addend for the fast path. */
1126 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_TMP1
,
1127 TARGET_PAGE_MASK
| ((1 << a_bits
) - 1));
1128 if (TARGET_LONG_BITS
== 32) {
1129 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_A0
, TCG_REG_A0
, add_off
);
1131 tcg_out_opc_reg(s
, OPC_AND
, TCG_TMP1
, TCG_TMP1
, addrl
);
1133 label_ptr
[0] = s
->code_ptr
;
1134 tcg_out_opc_br(s
, OPC_BNE
, TCG_TMP1
, TCG_TMP0
);
1136 /* Load and test the high half tlb comparator. */
1137 if (TARGET_LONG_BITS
== 64) {
1139 tcg_out_opc_imm(s
, OPC_LW
, TCG_TMP0
, TCG_REG_A0
, cmp_off
+ HI_OFF
);
1141 /* Load the tlb addend for the fast path. We can't do it earlier with
1142 64-bit targets or we'll clobber a0 before reading the high half tlb
1144 tcg_out_opc_imm(s
, OPC_LW
, TCG_REG_A0
, TCG_REG_A0
, add_off
);
1146 label_ptr
[1] = s
->code_ptr
;
1147 tcg_out_opc_br(s
, OPC_BNE
, addrh
, TCG_TMP0
);
1151 tcg_out_opc_reg(s
, OPC_ADDU
, base
, TCG_REG_A0
, addrl
);
1154 static void add_qemu_ldst_label(TCGContext
*s
, int is_ld
, TCGMemOpIdx oi
,
1155 TCGReg datalo
, TCGReg datahi
,
1156 TCGReg addrlo
, TCGReg addrhi
,
1157 void *raddr
, tcg_insn_unit
*label_ptr
[2])
1159 TCGLabelQemuLdst
*label
= new_ldst_label(s
);
1161 label
->is_ld
= is_ld
;
1163 label
->datalo_reg
= datalo
;
1164 label
->datahi_reg
= datahi
;
1165 label
->addrlo_reg
= addrlo
;
1166 label
->addrhi_reg
= addrhi
;
1167 label
->raddr
= raddr
;
1168 label
->label_ptr
[0] = label_ptr
[0];
1169 if (TARGET_LONG_BITS
== 64) {
1170 label
->label_ptr
[1] = label_ptr
[1];
1174 static void tcg_out_qemu_ld_slow_path(TCGContext
*s
, TCGLabelQemuLdst
*l
)
1176 TCGMemOpIdx oi
= l
->oi
;
1177 TCGMemOp opc
= get_memop(oi
);
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
);
1193 i
= tcg_out_call_iarg_imm(s
, i
, oi
);
1194 i
= tcg_out_call_iarg_imm(s
, i
, (intptr_t)l
->raddr
);
1195 tcg_out_call_int(s
, qemu_ld_helpers
[opc
& (MO_BSWAP
| MO_SSIZE
)], false);
1197 tcg_out_mov(s
, TCG_TYPE_PTR
, tcg_target_call_iarg_regs
[0], TCG_AREG0
);
1200 if ((opc
& MO_SIZE
) == MO_64
) {
1201 /* We eliminated V0 from the possible output registers, so it
1202 cannot be clobbered here. So we must move V1 first. */
1204 tcg_out_mov(s
, TCG_TYPE_I32
, v0
, TCG_REG_V1
);
1207 tcg_out_mov(s
, TCG_TYPE_I32
, l
->datahi_reg
, TCG_REG_V1
);
1211 reloc_pc16(s
->code_ptr
, l
->raddr
);
1212 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_ZERO
, TCG_REG_ZERO
);
1214 tcg_out_mov(s
, TCG_TYPE_REG
, v0
, TCG_REG_V0
);
1217 static void tcg_out_qemu_st_slow_path(TCGContext
*s
, TCGLabelQemuLdst
*l
)
1219 TCGMemOpIdx oi
= l
->oi
;
1220 TCGMemOp opc
= get_memop(oi
);
1221 TCGMemOp s_bits
= opc
& MO_SIZE
;
1224 /* resolve label address */
1225 reloc_pc16(l
->label_ptr
[0], s
->code_ptr
);
1226 if (TARGET_LONG_BITS
== 64) {
1227 reloc_pc16(l
->label_ptr
[1], s
->code_ptr
);
1231 if (TARGET_LONG_BITS
== 64) {
1232 i
= tcg_out_call_iarg_reg2(s
, i
, l
->addrlo_reg
, l
->addrhi_reg
);
1234 i
= tcg_out_call_iarg_reg(s
, i
, l
->addrlo_reg
);
1238 i
= tcg_out_call_iarg_reg8(s
, i
, l
->datalo_reg
);
1241 i
= tcg_out_call_iarg_reg16(s
, i
, l
->datalo_reg
);
1244 i
= tcg_out_call_iarg_reg(s
, i
, l
->datalo_reg
);
1247 i
= tcg_out_call_iarg_reg2(s
, i
, l
->datalo_reg
, l
->datahi_reg
);
1252 i
= tcg_out_call_iarg_imm(s
, i
, oi
);
1254 /* Tail call to the store helper. Thus force the return address
1255 computation to take place in the return address register. */
1256 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_RA
, (intptr_t)l
->raddr
);
1257 i
= tcg_out_call_iarg_reg(s
, i
, TCG_REG_RA
);
1258 tcg_out_call_int(s
, qemu_st_helpers
[opc
& (MO_BSWAP
| MO_SIZE
)], true);
1260 tcg_out_mov(s
, TCG_TYPE_PTR
, tcg_target_call_iarg_regs
[0], TCG_AREG0
);
1264 static void tcg_out_qemu_ld_direct(TCGContext
*s
, TCGReg lo
, TCGReg hi
,
1265 TCGReg base
, TCGMemOp opc
)
1267 switch (opc
& (MO_SSIZE
| MO_BSWAP
)) {
1269 tcg_out_opc_imm(s
, OPC_LBU
, lo
, base
, 0);
1272 tcg_out_opc_imm(s
, OPC_LB
, lo
, base
, 0);
1274 case MO_UW
| MO_BSWAP
:
1275 tcg_out_opc_imm(s
, OPC_LHU
, TCG_TMP1
, base
, 0);
1276 tcg_out_bswap16(s
, lo
, TCG_TMP1
);
1279 tcg_out_opc_imm(s
, OPC_LHU
, lo
, base
, 0);
1281 case MO_SW
| MO_BSWAP
:
1282 tcg_out_opc_imm(s
, OPC_LHU
, TCG_TMP1
, base
, 0);
1283 tcg_out_bswap16s(s
, lo
, TCG_TMP1
);
1286 tcg_out_opc_imm(s
, OPC_LH
, lo
, base
, 0);
1288 case MO_UL
| MO_BSWAP
:
1289 if (use_mips32r2_instructions
) {
1290 tcg_out_opc_imm(s
, OPC_LW
, lo
, base
, 0);
1291 tcg_out_bswap32(s
, lo
, lo
);
1293 tcg_out_bswap_subr(s
, bswap32_addr
);
1295 tcg_out_opc_imm(s
, OPC_LW
, TCG_TMP0
, base
, 0);
1296 tcg_out_mov(s
, TCG_TYPE_I32
, lo
, TCG_TMP3
);
1300 tcg_out_opc_imm(s
, OPC_LW
, lo
, base
, 0);
1302 case MO_Q
| MO_BSWAP
:
1303 if (use_mips32r2_instructions
) {
1304 tcg_out_opc_imm(s
, OPC_LW
, TCG_TMP0
, base
, 0);
1305 tcg_out_opc_imm(s
, OPC_LW
, TCG_TMP1
, base
, 4);
1306 tcg_out_opc_reg(s
, OPC_WSBH
, TCG_TMP0
, 0, TCG_TMP0
);
1307 tcg_out_opc_reg(s
, OPC_WSBH
, TCG_TMP1
, 0, TCG_TMP1
);
1308 tcg_out_opc_sa(s
, OPC_ROTR
, MIPS_BE
? lo
: hi
, TCG_TMP0
, 16);
1309 tcg_out_opc_sa(s
, OPC_ROTR
, MIPS_BE
? hi
: lo
, TCG_TMP1
, 16);
1311 tcg_out_bswap_subr(s
, bswap32_addr
);
1313 tcg_out_opc_imm(s
, OPC_LW
, TCG_TMP0
, base
, 0);
1314 tcg_out_opc_imm(s
, OPC_LW
, TCG_TMP0
, base
, 4);
1315 tcg_out_bswap_subr(s
, bswap32_addr
);
1317 tcg_out_mov(s
, TCG_TYPE_I32
, MIPS_BE
? lo
: hi
, TCG_TMP3
);
1318 tcg_out_mov(s
, TCG_TYPE_I32
, MIPS_BE
? hi
: lo
, TCG_TMP3
);
1322 /* Prefer to load from offset 0 first, but allow for overlap. */
1323 if (MIPS_BE
? hi
!= base
: lo
== base
) {
1324 tcg_out_opc_imm(s
, OPC_LW
, hi
, base
, HI_OFF
);
1325 tcg_out_opc_imm(s
, OPC_LW
, lo
, base
, LO_OFF
);
1327 tcg_out_opc_imm(s
, OPC_LW
, lo
, base
, LO_OFF
);
1328 tcg_out_opc_imm(s
, OPC_LW
, hi
, base
, HI_OFF
);
1336 static void tcg_out_qemu_ld(TCGContext
*s
, const TCGArg
*args
, bool is_64
)
1338 TCGReg addr_regl
, addr_regh
__attribute__((unused
));
1339 TCGReg data_regl
, data_regh
;
1342 #if defined(CONFIG_SOFTMMU)
1343 tcg_insn_unit
*label_ptr
[2];
1345 TCGReg base
= TCG_REG_A0
;
1347 data_regl
= *args
++;
1348 data_regh
= (is_64
? *args
++ : 0);
1349 addr_regl
= *args
++;
1350 addr_regh
= (TARGET_LONG_BITS
== 64 ? *args
++ : 0);
1352 opc
= get_memop(oi
);
1354 #if defined(CONFIG_SOFTMMU)
1355 tcg_out_tlb_load(s
, base
, addr_regl
, addr_regh
, oi
, label_ptr
, 1);
1356 tcg_out_qemu_ld_direct(s
, data_regl
, data_regh
, base
, opc
);
1357 add_qemu_ldst_label(s
, 1, oi
, data_regl
, data_regh
, addr_regl
, addr_regh
,
1358 s
->code_ptr
, label_ptr
);
1360 if (guest_base
== 0 && data_regl
!= addr_regl
) {
1362 } else if (guest_base
== (int16_t)guest_base
) {
1363 tcg_out_opc_imm(s
, OPC_ADDIU
, base
, addr_regl
, guest_base
);
1365 tcg_out_movi(s
, TCG_TYPE_PTR
, base
, guest_base
);
1366 tcg_out_opc_reg(s
, OPC_ADDU
, base
, base
, addr_regl
);
1368 tcg_out_qemu_ld_direct(s
, data_regl
, data_regh
, base
, opc
);
1372 static void tcg_out_qemu_st_direct(TCGContext
*s
, TCGReg lo
, TCGReg hi
,
1373 TCGReg base
, TCGMemOp opc
)
1375 /* Don't clutter the code below with checks to avoid bswapping ZERO. */
1376 if ((lo
| hi
) == 0) {
1380 switch (opc
& (MO_SIZE
| MO_BSWAP
)) {
1382 tcg_out_opc_imm(s
, OPC_SB
, lo
, base
, 0);
1385 case MO_16
| MO_BSWAP
:
1386 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_TMP1
, lo
, 0xffff);
1387 tcg_out_bswap16(s
, TCG_TMP1
, TCG_TMP1
);
1391 tcg_out_opc_imm(s
, OPC_SH
, lo
, base
, 0);
1394 case MO_32
| MO_BSWAP
:
1395 tcg_out_bswap32(s
, TCG_TMP3
, lo
);
1399 tcg_out_opc_imm(s
, OPC_SW
, lo
, base
, 0);
1402 case MO_64
| MO_BSWAP
:
1403 if (use_mips32r2_instructions
) {
1404 tcg_out_opc_reg(s
, OPC_WSBH
, TCG_TMP0
, 0, MIPS_BE
? lo
: hi
);
1405 tcg_out_opc_reg(s
, OPC_WSBH
, TCG_TMP1
, 0, MIPS_BE
? hi
: lo
);
1406 tcg_out_opc_sa(s
, OPC_ROTR
, TCG_TMP0
, TCG_TMP0
, 16);
1407 tcg_out_opc_sa(s
, OPC_ROTR
, TCG_TMP1
, TCG_TMP1
, 16);
1408 tcg_out_opc_imm(s
, OPC_SW
, TCG_TMP0
, base
, 0);
1409 tcg_out_opc_imm(s
, OPC_SW
, TCG_TMP1
, base
, 4);
1411 tcg_out_bswap32(s
, TCG_TMP3
, MIPS_BE
? lo
: hi
);
1412 tcg_out_opc_imm(s
, OPC_SW
, TCG_TMP3
, base
, 0);
1413 tcg_out_bswap32(s
, TCG_TMP3
, MIPS_BE
? hi
: lo
);
1414 tcg_out_opc_imm(s
, OPC_SW
, TCG_TMP3
, base
, 4);
1418 tcg_out_opc_imm(s
, OPC_SW
, MIPS_BE
? hi
: lo
, base
, 0);
1419 tcg_out_opc_imm(s
, OPC_SW
, MIPS_BE
? lo
: hi
, base
, 4);
1427 static void tcg_out_qemu_st(TCGContext
*s
, const TCGArg
*args
, bool is_64
)
1429 TCGReg addr_regl
, addr_regh
__attribute__((unused
));
1430 TCGReg data_regl
, data_regh
;
1433 #if defined(CONFIG_SOFTMMU)
1434 tcg_insn_unit
*label_ptr
[2];
1436 TCGReg base
= TCG_REG_A0
;
1438 data_regl
= *args
++;
1439 data_regh
= (is_64
? *args
++ : 0);
1440 addr_regl
= *args
++;
1441 addr_regh
= (TARGET_LONG_BITS
== 64 ? *args
++ : 0);
1443 opc
= get_memop(oi
);
1445 #if defined(CONFIG_SOFTMMU)
1446 tcg_out_tlb_load(s
, base
, addr_regl
, addr_regh
, oi
, label_ptr
, 0);
1447 tcg_out_qemu_st_direct(s
, data_regl
, data_regh
, base
, opc
);
1448 add_qemu_ldst_label(s
, 0, oi
, data_regl
, data_regh
, addr_regl
, addr_regh
,
1449 s
->code_ptr
, label_ptr
);
1451 if (guest_base
== 0) {
1454 if (guest_base
== (int16_t)guest_base
) {
1455 tcg_out_opc_imm(s
, OPC_ADDIU
, base
, addr_regl
, guest_base
);
1457 tcg_out_movi(s
, TCG_TYPE_PTR
, base
, guest_base
);
1458 tcg_out_opc_reg(s
, OPC_ADDU
, base
, base
, addr_regl
);
1461 tcg_out_qemu_st_direct(s
, data_regl
, data_regh
, base
, opc
);
1465 static void tcg_out_mb(TCGContext
*s
, TCGArg a0
)
1467 static const MIPSInsn sync
[] = {
1468 /* Note that SYNC_MB is a slightly weaker than SYNC 0,
1469 as the former is an ordering barrier and the latter
1470 is a completion barrier. */
1471 [0 ... TCG_MO_ALL
] = OPC_SYNC_MB
,
1472 [TCG_MO_LD_LD
] = OPC_SYNC_RMB
,
1473 [TCG_MO_ST_ST
] = OPC_SYNC_WMB
,
1474 [TCG_MO_LD_ST
] = OPC_SYNC_RELEASE
,
1475 [TCG_MO_LD_ST
| TCG_MO_ST_ST
] = OPC_SYNC_RELEASE
,
1476 [TCG_MO_LD_ST
| TCG_MO_LD_LD
] = OPC_SYNC_ACQUIRE
,
1478 tcg_out32(s
, sync
[a0
& TCG_MO_ALL
]);
1481 static inline void tcg_out_op(TCGContext
*s
, TCGOpcode opc
,
1482 const TCGArg
*args
, const int *const_args
)
1494 case INDEX_op_exit_tb
:
1496 TCGReg b0
= TCG_REG_ZERO
;
1499 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_V0
, a0
& ~0xffff);
1502 if (!tcg_out_opc_jmp(s
, OPC_J
, tb_ret_addr
)) {
1503 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_TMP0
,
1504 (uintptr_t)tb_ret_addr
);
1505 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_TMP0
, 0);
1507 tcg_out_opc_imm(s
, OPC_ORI
, TCG_REG_V0
, b0
, a0
& 0xffff);
1510 case INDEX_op_goto_tb
:
1511 if (s
->tb_jmp_insn_offset
) {
1512 /* direct jump method */
1513 s
->tb_jmp_insn_offset
[a0
] = tcg_current_code_size(s
);
1514 /* Avoid clobbering the address during retranslation. */
1515 tcg_out32(s
, OPC_J
| (*(uint32_t *)s
->code_ptr
& 0x3ffffff));
1517 /* indirect jump method */
1518 tcg_out_ld(s
, TCG_TYPE_PTR
, TCG_TMP0
, TCG_REG_ZERO
,
1519 (uintptr_t)(s
->tb_jmp_target_addr
+ a0
));
1520 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_TMP0
, 0);
1523 s
->tb_jmp_reset_offset
[a0
] = tcg_current_code_size(s
);
1526 tcg_out_brcond(s
, TCG_COND_EQ
, TCG_REG_ZERO
, TCG_REG_ZERO
,
1530 case INDEX_op_ld8u_i32
:
1533 case INDEX_op_ld8s_i32
:
1536 case INDEX_op_ld16u_i32
:
1539 case INDEX_op_ld16s_i32
:
1542 case INDEX_op_ld_i32
:
1545 case INDEX_op_st8_i32
:
1548 case INDEX_op_st16_i32
:
1551 case INDEX_op_st_i32
:
1554 tcg_out_ldst(s
, i1
, a0
, a1
, a2
);
1557 case INDEX_op_add_i32
:
1558 i1
= OPC_ADDU
, i2
= OPC_ADDIU
;
1560 case INDEX_op_or_i32
:
1561 i1
= OPC_OR
, i2
= OPC_ORI
;
1563 case INDEX_op_xor_i32
:
1564 i1
= OPC_XOR
, i2
= OPC_XORI
;
1567 tcg_out_opc_imm(s
, i2
, a0
, a1
, a2
);
1571 tcg_out_opc_reg(s
, i1
, a0
, a1
, a2
);
1574 case INDEX_op_sub_i32
:
1576 tcg_out_opc_imm(s
, OPC_ADDIU
, a0
, a1
, -a2
);
1581 case INDEX_op_and_i32
:
1582 if (c2
&& a2
!= (uint16_t)a2
) {
1583 int msb
= ctz32(~a2
) - 1;
1584 tcg_debug_assert(use_mips32r2_instructions
);
1585 tcg_debug_assert(is_p2m1(a2
));
1586 tcg_out_opc_bf(s
, OPC_EXT
, a0
, a1
, msb
, 0);
1589 i1
= OPC_AND
, i2
= OPC_ANDI
;
1591 case INDEX_op_nor_i32
:
1595 case INDEX_op_mul_i32
:
1596 if (use_mips32_instructions
) {
1597 tcg_out_opc_reg(s
, OPC_MUL
, a0
, a1
, a2
);
1600 i1
= OPC_MULT
, i2
= OPC_MFLO
;
1602 case INDEX_op_mulsh_i32
:
1603 if (use_mips32r6_instructions
) {
1604 tcg_out_opc_reg(s
, OPC_MUH
, a0
, a1
, a2
);
1607 i1
= OPC_MULT
, i2
= OPC_MFHI
;
1609 case INDEX_op_muluh_i32
:
1610 if (use_mips32r6_instructions
) {
1611 tcg_out_opc_reg(s
, OPC_MUHU
, a0
, a1
, a2
);
1614 i1
= OPC_MULTU
, i2
= OPC_MFHI
;
1616 case INDEX_op_div_i32
:
1617 if (use_mips32r6_instructions
) {
1618 tcg_out_opc_reg(s
, OPC_DIV_R6
, a0
, a1
, a2
);
1621 i1
= OPC_DIV
, i2
= OPC_MFLO
;
1623 case INDEX_op_divu_i32
:
1624 if (use_mips32r6_instructions
) {
1625 tcg_out_opc_reg(s
, OPC_DIVU_R6
, a0
, a1
, a2
);
1628 i1
= OPC_DIVU
, i2
= OPC_MFLO
;
1630 case INDEX_op_rem_i32
:
1631 if (use_mips32r6_instructions
) {
1632 tcg_out_opc_reg(s
, OPC_MOD
, a0
, a1
, a2
);
1635 i1
= OPC_DIV
, i2
= OPC_MFHI
;
1637 case INDEX_op_remu_i32
:
1638 if (use_mips32r6_instructions
) {
1639 tcg_out_opc_reg(s
, OPC_MODU
, a0
, a1
, a2
);
1642 i1
= OPC_DIVU
, i2
= OPC_MFHI
;
1644 tcg_out_opc_reg(s
, i1
, 0, a1
, a2
);
1645 tcg_out_opc_reg(s
, i2
, a0
, 0, 0);
1648 case INDEX_op_muls2_i32
:
1651 case INDEX_op_mulu2_i32
:
1654 tcg_out_opc_reg(s
, i1
, 0, a2
, args
[3]);
1655 tcg_out_opc_reg(s
, OPC_MFLO
, a0
, 0, 0);
1656 tcg_out_opc_reg(s
, OPC_MFHI
, a1
, 0, 0);
1659 case INDEX_op_not_i32
:
1662 case INDEX_op_bswap16_i32
:
1665 case INDEX_op_ext8s_i32
:
1668 case INDEX_op_ext16s_i32
:
1671 tcg_out_opc_reg(s
, i1
, a0
, TCG_REG_ZERO
, a1
);
1674 case INDEX_op_sar_i32
:
1675 i1
= OPC_SRAV
, i2
= OPC_SRA
;
1677 case INDEX_op_shl_i32
:
1678 i1
= OPC_SLLV
, i2
= OPC_SLL
;
1680 case INDEX_op_shr_i32
:
1681 i1
= OPC_SRLV
, i2
= OPC_SRL
;
1683 case INDEX_op_rotr_i32
:
1684 i1
= OPC_ROTRV
, i2
= OPC_ROTR
;
1687 tcg_out_opc_sa(s
, i2
, a0
, a1
, a2
);
1689 tcg_out_opc_reg(s
, i1
, a0
, a2
, a1
);
1692 case INDEX_op_rotl_i32
:
1694 tcg_out_opc_sa(s
, OPC_ROTR
, a0
, a1
, 32 - a2
);
1696 tcg_out_opc_reg(s
, OPC_SUBU
, TCG_TMP0
, TCG_REG_ZERO
, a2
);
1697 tcg_out_opc_reg(s
, OPC_ROTRV
, a0
, TCG_TMP0
, a1
);
1701 case INDEX_op_bswap32_i32
:
1702 tcg_out_bswap32(s
, a0
, a1
);
1705 case INDEX_op_deposit_i32
:
1706 tcg_out_opc_bf(s
, OPC_INS
, a0
, a2
, args
[3] + args
[4] - 1, args
[3]);
1709 case INDEX_op_brcond_i32
:
1710 tcg_out_brcond(s
, a2
, a0
, a1
, arg_label(args
[3]));
1712 case INDEX_op_brcond2_i32
:
1713 tcg_out_brcond2(s
, args
[4], a0
, a1
, a2
, args
[3], arg_label(args
[5]));
1716 case INDEX_op_movcond_i32
:
1717 tcg_out_movcond(s
, args
[5], a0
, a1
, a2
, args
[3], args
[4]);
1720 case INDEX_op_setcond_i32
:
1721 tcg_out_setcond(s
, args
[3], a0
, a1
, a2
);
1723 case INDEX_op_setcond2_i32
:
1724 tcg_out_setcond2(s
, args
[5], a0
, a1
, a2
, args
[3], args
[4]);
1727 case INDEX_op_qemu_ld_i32
:
1728 tcg_out_qemu_ld(s
, args
, false);
1730 case INDEX_op_qemu_ld_i64
:
1731 tcg_out_qemu_ld(s
, args
, true);
1733 case INDEX_op_qemu_st_i32
:
1734 tcg_out_qemu_st(s
, args
, false);
1736 case INDEX_op_qemu_st_i64
:
1737 tcg_out_qemu_st(s
, args
, true);
1740 case INDEX_op_add2_i32
:
1741 tcg_out_addsub2(s
, a0
, a1
, a2
, args
[3], args
[4], args
[5],
1742 const_args
[4], const_args
[5], false);
1744 case INDEX_op_sub2_i32
:
1745 tcg_out_addsub2(s
, a0
, a1
, a2
, args
[3], args
[4], args
[5],
1746 const_args
[4], const_args
[5], true);
1752 case INDEX_op_mov_i32
: /* Always emitted via tcg_out_mov. */
1753 case INDEX_op_movi_i32
: /* Always emitted via tcg_out_movi. */
1754 case INDEX_op_call
: /* Always emitted via tcg_out_call. */
1760 static const TCGTargetOpDef mips_op_defs
[] = {
1761 { INDEX_op_exit_tb
, { } },
1762 { INDEX_op_goto_tb
, { } },
1763 { INDEX_op_br
, { } },
1765 { INDEX_op_ld8u_i32
, { "r", "r" } },
1766 { INDEX_op_ld8s_i32
, { "r", "r" } },
1767 { INDEX_op_ld16u_i32
, { "r", "r" } },
1768 { INDEX_op_ld16s_i32
, { "r", "r" } },
1769 { INDEX_op_ld_i32
, { "r", "r" } },
1770 { INDEX_op_st8_i32
, { "rZ", "r" } },
1771 { INDEX_op_st16_i32
, { "rZ", "r" } },
1772 { INDEX_op_st_i32
, { "rZ", "r" } },
1774 { INDEX_op_add_i32
, { "r", "rZ", "rJ" } },
1775 { INDEX_op_mul_i32
, { "r", "rZ", "rZ" } },
1776 #if !use_mips32r6_instructions
1777 { INDEX_op_muls2_i32
, { "r", "r", "rZ", "rZ" } },
1778 { INDEX_op_mulu2_i32
, { "r", "r", "rZ", "rZ" } },
1780 { INDEX_op_mulsh_i32
, { "r", "rZ", "rZ" } },
1781 { INDEX_op_muluh_i32
, { "r", "rZ", "rZ" } },
1782 { INDEX_op_div_i32
, { "r", "rZ", "rZ" } },
1783 { INDEX_op_divu_i32
, { "r", "rZ", "rZ" } },
1784 { INDEX_op_rem_i32
, { "r", "rZ", "rZ" } },
1785 { INDEX_op_remu_i32
, { "r", "rZ", "rZ" } },
1786 { INDEX_op_sub_i32
, { "r", "rZ", "rN" } },
1788 { INDEX_op_and_i32
, { "r", "rZ", "rIK" } },
1789 { INDEX_op_nor_i32
, { "r", "rZ", "rZ" } },
1790 { INDEX_op_not_i32
, { "r", "rZ" } },
1791 { INDEX_op_or_i32
, { "r", "rZ", "rIZ" } },
1792 { INDEX_op_xor_i32
, { "r", "rZ", "rIZ" } },
1794 { INDEX_op_shl_i32
, { "r", "rZ", "ri" } },
1795 { INDEX_op_shr_i32
, { "r", "rZ", "ri" } },
1796 { INDEX_op_sar_i32
, { "r", "rZ", "ri" } },
1797 { INDEX_op_rotr_i32
, { "r", "rZ", "ri" } },
1798 { INDEX_op_rotl_i32
, { "r", "rZ", "ri" } },
1800 { INDEX_op_bswap16_i32
, { "r", "r" } },
1801 { INDEX_op_bswap32_i32
, { "r", "r" } },
1803 { INDEX_op_ext8s_i32
, { "r", "rZ" } },
1804 { INDEX_op_ext16s_i32
, { "r", "rZ" } },
1806 { INDEX_op_deposit_i32
, { "r", "0", "rZ" } },
1808 { INDEX_op_brcond_i32
, { "rZ", "rZ" } },
1809 #if use_mips32r6_instructions
1810 { INDEX_op_movcond_i32
, { "r", "rZ", "rZ", "rZ", "rZ" } },
1812 { INDEX_op_movcond_i32
, { "r", "rZ", "rZ", "rZ", "0" } },
1814 { INDEX_op_setcond_i32
, { "r", "rZ", "rZ" } },
1815 { INDEX_op_setcond2_i32
, { "r", "rZ", "rZ", "rZ", "rZ" } },
1817 { INDEX_op_add2_i32
, { "r", "r", "rZ", "rZ", "rN", "rN" } },
1818 { INDEX_op_sub2_i32
, { "r", "r", "rZ", "rZ", "rN", "rN" } },
1819 { INDEX_op_brcond2_i32
, { "rZ", "rZ", "rZ", "rZ" } },
1821 #if TARGET_LONG_BITS == 32
1822 { INDEX_op_qemu_ld_i32
, { "r", "LZ" } },
1823 { INDEX_op_qemu_st_i32
, { "SZ", "SZ" } },
1824 { INDEX_op_qemu_ld_i64
, { "r", "r", "LZ" } },
1825 { INDEX_op_qemu_st_i64
, { "SZ", "SZ", "SZ" } },
1827 { INDEX_op_qemu_ld_i32
, { "r", "LZ", "LZ" } },
1828 { INDEX_op_qemu_st_i32
, { "SZ", "SZ", "SZ" } },
1829 { INDEX_op_qemu_ld_i64
, { "r", "r", "LZ", "LZ" } },
1830 { INDEX_op_qemu_st_i64
, { "SZ", "SZ", "SZ", "SZ" } },
1833 { INDEX_op_mb
, { } },
1837 static int tcg_target_callee_save_regs
[] = {
1838 TCG_REG_S0
, /* used for the global env (TCG_AREG0) */
1847 TCG_REG_RA
, /* should be last for ABI compliance */
1850 /* The Linux kernel doesn't provide any information about the available
1851 instruction set. Probe it using a signal handler. */
1854 #ifndef use_movnz_instructions
1855 bool use_movnz_instructions
= false;
1858 #ifndef use_mips32_instructions
1859 bool use_mips32_instructions
= false;
1862 #ifndef use_mips32r2_instructions
1863 bool use_mips32r2_instructions
= false;
1866 static volatile sig_atomic_t got_sigill
;
1868 static void sigill_handler(int signo
, siginfo_t
*si
, void *data
)
1870 /* Skip the faulty instruction */
1871 ucontext_t
*uc
= (ucontext_t
*)data
;
1872 uc
->uc_mcontext
.pc
+= 4;
1877 static void tcg_target_detect_isa(void)
1879 struct sigaction sa_old
, sa_new
;
1881 memset(&sa_new
, 0, sizeof(sa_new
));
1882 sa_new
.sa_flags
= SA_SIGINFO
;
1883 sa_new
.sa_sigaction
= sigill_handler
;
1884 sigaction(SIGILL
, &sa_new
, &sa_old
);
1886 /* Probe for movn/movz, necessary to implement movcond. */
1887 #ifndef use_movnz_instructions
1889 asm volatile(".set push\n"
1891 "movn $zero, $zero, $zero\n"
1892 "movz $zero, $zero, $zero\n"
1895 use_movnz_instructions
= !got_sigill
;
1898 /* Probe for MIPS32 instructions. As no subsetting is allowed
1899 by the specification, it is only necessary to probe for one
1900 of the instructions. */
1901 #ifndef use_mips32_instructions
1903 asm volatile(".set push\n"
1905 "mul $zero, $zero\n"
1908 use_mips32_instructions
= !got_sigill
;
1911 /* Probe for MIPS32r2 instructions if MIPS32 instructions are
1912 available. As no subsetting is allowed by the specification,
1913 it is only necessary to probe for one of the instructions. */
1914 #ifndef use_mips32r2_instructions
1915 if (use_mips32_instructions
) {
1917 asm volatile(".set push\n"
1919 "seb $zero, $zero\n"
1922 use_mips32r2_instructions
= !got_sigill
;
1926 sigaction(SIGILL
, &sa_old
, NULL
);
1929 static tcg_insn_unit
*align_code_ptr(TCGContext
*s
)
1931 uintptr_t p
= (uintptr_t)s
->code_ptr
;
1934 s
->code_ptr
= (void *)p
;
1939 /* Generate global QEMU prologue and epilogue code */
1940 static void tcg_target_qemu_prologue(TCGContext
*s
)
1944 /* reserve some stack space, also for TCG temps. */
1945 frame_size
= ARRAY_SIZE(tcg_target_callee_save_regs
) * 4
1946 + TCG_STATIC_CALL_ARGS_SIZE
1947 + CPU_TEMP_BUF_NLONGS
* sizeof(long);
1948 frame_size
= (frame_size
+ TCG_TARGET_STACK_ALIGN
- 1) &
1949 ~(TCG_TARGET_STACK_ALIGN
- 1);
1950 tcg_set_frame(s
, TCG_REG_SP
, ARRAY_SIZE(tcg_target_callee_save_regs
) * 4
1951 + TCG_STATIC_CALL_ARGS_SIZE
,
1952 CPU_TEMP_BUF_NLONGS
* sizeof(long));
1955 tcg_out_addi(s
, TCG_REG_SP
, -frame_size
);
1956 for(i
= 0 ; i
< ARRAY_SIZE(tcg_target_callee_save_regs
) ; i
++) {
1957 tcg_out_st(s
, TCG_TYPE_I32
, tcg_target_callee_save_regs
[i
],
1958 TCG_REG_SP
, TCG_STATIC_CALL_ARGS_SIZE
+ i
* 4);
1961 /* Call generated code */
1962 tcg_out_opc_reg(s
, OPC_JR
, 0, tcg_target_call_iarg_regs
[1], 0);
1963 tcg_out_mov(s
, TCG_TYPE_PTR
, TCG_AREG0
, tcg_target_call_iarg_regs
[0]);
1964 tb_ret_addr
= s
->code_ptr
;
1967 for(i
= 0 ; i
< ARRAY_SIZE(tcg_target_callee_save_regs
) ; i
++) {
1968 tcg_out_ld(s
, TCG_TYPE_I32
, tcg_target_callee_save_regs
[i
],
1969 TCG_REG_SP
, TCG_STATIC_CALL_ARGS_SIZE
+ i
* 4);
1972 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_RA
, 0);
1974 tcg_out_addi(s
, TCG_REG_SP
, frame_size
);
1976 if (use_mips32r2_instructions
) {
1980 /* Bswap subroutine: Input in TCG_TMP0, output in TCG_TMP3;
1981 clobbers TCG_TMP1, TCG_TMP2. */
1984 * bswap32 -- 32-bit swap (signed result for mips64). a0 = abcd.
1986 bswap32_addr
= align_code_ptr(s
);
1987 /* t3 = (ssss)d000 */
1988 tcg_out_opc_sa(s
, OPC_SLL
, TCG_TMP3
, TCG_TMP0
, 24);
1990 tcg_out_opc_sa(s
, OPC_SRL
, TCG_TMP1
, TCG_TMP0
, 24);
1992 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_TMP2
, TCG_TMP0
, 0xff00);
1994 tcg_out_opc_reg(s
, OPC_OR
, TCG_TMP3
, TCG_TMP3
, TCG_TMP1
);
1996 tcg_out_opc_sa(s
, OPC_SRL
, TCG_TMP1
, TCG_TMP0
, 8);
1998 tcg_out_opc_sa(s
, OPC_SLL
, TCG_TMP2
, TCG_TMP2
, 8);
2000 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_TMP1
, TCG_TMP1
, 0xff00);
2002 tcg_out_opc_reg(s
, OPC_OR
, TCG_TMP3
, TCG_TMP3
, TCG_TMP2
);
2003 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_RA
, 0);
2004 /* t3 = dcba -- delay slot */
2005 tcg_out_opc_reg(s
, OPC_OR
, TCG_TMP3
, TCG_TMP3
, TCG_TMP1
);
2008 static void tcg_target_init(TCGContext
*s
)
2010 tcg_target_detect_isa();
2011 tcg_regset_set(tcg_target_available_regs
[TCG_TYPE_I32
], 0xffffffff);
2012 tcg_regset_set(tcg_target_call_clobber_regs
,
2030 tcg_regset_clear(s
->reserved_regs
);
2031 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_ZERO
); /* zero register */
2032 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_K0
); /* kernel use only */
2033 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_K1
); /* kernel use only */
2034 tcg_regset_set_reg(s
->reserved_regs
, TCG_TMP0
); /* internal use */
2035 tcg_regset_set_reg(s
->reserved_regs
, TCG_TMP1
); /* internal use */
2036 tcg_regset_set_reg(s
->reserved_regs
, TCG_TMP2
); /* internal use */
2037 tcg_regset_set_reg(s
->reserved_regs
, TCG_TMP3
); /* internal use */
2038 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_RA
); /* return address */
2039 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_SP
); /* stack pointer */
2040 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_GP
); /* global pointer */
2042 tcg_add_target_add_op_defs(mips_op_defs
);
2045 void tb_set_jmp_target1(uintptr_t jmp_addr
, uintptr_t addr
)
2047 atomic_set((uint32_t *)jmp_addr
, deposit32(OPC_J
, 0, 26, addr
>> 2));
2048 flush_icache_range(jmp_addr
, jmp_addr
+ 4);