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 #ifdef HOST_WORDS_BIGENDIAN
33 #if TCG_TARGET_REG_BITS == 32
34 # define LO_OFF (MIPS_BE * 4)
35 # define HI_OFF (4 - LO_OFF)
37 /* To assert at compile-time that these values are never used
38 for TCG_TARGET_REG_BITS == 64. */
40 # define LO_OFF link_error()
41 # define HI_OFF link_error()
44 #ifdef CONFIG_DEBUG_TCG
45 static const char * const tcg_target_reg_names
[TCG_TARGET_NB_REGS
] = {
81 #define TCG_TMP0 TCG_REG_AT
82 #define TCG_TMP1 TCG_REG_T9
83 #define TCG_TMP2 TCG_REG_T8
84 #define TCG_TMP3 TCG_REG_T7
86 #ifndef CONFIG_SOFTMMU
87 #define TCG_GUEST_BASE_REG TCG_REG_S1
90 /* check if we really need so many registers :P */
91 static const int tcg_target_reg_alloc_order
[] = {
92 /* Call saved registers. */
103 /* Call clobbered registers. */
113 /* Argument registers, opposite order of allocation. */
124 static const TCGReg tcg_target_call_iarg_regs
[] = {
129 #if _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64
137 static const TCGReg tcg_target_call_oarg_regs
[2] = {
142 static tcg_insn_unit
*tb_ret_addr
;
143 static tcg_insn_unit
*bswap32_addr
;
144 static tcg_insn_unit
*bswap32u_addr
;
145 static tcg_insn_unit
*bswap64_addr
;
147 static inline uint32_t reloc_pc16_val(tcg_insn_unit
*pc
, tcg_insn_unit
*target
)
149 /* Let the compiler perform the right-shift as part of the arithmetic. */
150 ptrdiff_t disp
= target
- (pc
+ 1);
151 tcg_debug_assert(disp
== (int16_t)disp
);
152 return disp
& 0xffff;
155 static inline void reloc_pc16(tcg_insn_unit
*pc
, tcg_insn_unit
*target
)
157 *pc
= deposit32(*pc
, 0, 16, reloc_pc16_val(pc
, target
));
160 static inline uint32_t reloc_26_val(tcg_insn_unit
*pc
, tcg_insn_unit
*target
)
162 tcg_debug_assert((((uintptr_t)pc
^ (uintptr_t)target
) & 0xf0000000) == 0);
163 return ((uintptr_t)target
>> 2) & 0x3ffffff;
166 static inline void reloc_26(tcg_insn_unit
*pc
, tcg_insn_unit
*target
)
168 *pc
= deposit32(*pc
, 0, 26, reloc_26_val(pc
, target
));
171 static void patch_reloc(tcg_insn_unit
*code_ptr
, int type
,
172 intptr_t value
, intptr_t addend
)
174 tcg_debug_assert(type
== R_MIPS_PC16
);
175 tcg_debug_assert(addend
== 0);
176 reloc_pc16(code_ptr
, (tcg_insn_unit
*)value
);
179 #define TCG_CT_CONST_ZERO 0x100
180 #define TCG_CT_CONST_U16 0x200 /* Unsigned 16-bit: 0 - 0xffff. */
181 #define TCG_CT_CONST_S16 0x400 /* Signed 16-bit: -32768 - 32767 */
182 #define TCG_CT_CONST_P2M1 0x800 /* Power of 2 minus 1. */
183 #define TCG_CT_CONST_N16 0x1000 /* "Negatable" 16-bit: -32767 - 32767 */
184 #define TCG_CT_CONST_WSZ 0x2000 /* word size */
186 static inline bool is_p2m1(tcg_target_long val
)
188 return val
&& ((val
+ 1) & val
) == 0;
191 /* parse target specific constraints */
192 static const char *target_parse_constraint(TCGArgConstraint
*ct
,
193 const char *ct_str
, TCGType type
)
197 ct
->ct
|= TCG_CT_REG
;
198 ct
->u
.regs
= 0xffffffff;
200 case 'L': /* qemu_ld input arg constraint */
201 ct
->ct
|= TCG_CT_REG
;
202 ct
->u
.regs
= 0xffffffff;
203 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_A0
);
204 #if defined(CONFIG_SOFTMMU)
205 if (TCG_TARGET_REG_BITS
< TARGET_LONG_BITS
) {
206 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_A2
);
210 case 'S': /* qemu_st constraint */
211 ct
->ct
|= TCG_CT_REG
;
212 ct
->u
.regs
= 0xffffffff;
213 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_A0
);
214 #if defined(CONFIG_SOFTMMU)
215 if (TCG_TARGET_REG_BITS
< TARGET_LONG_BITS
) {
216 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_A2
);
217 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_A3
);
219 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_A1
);
224 ct
->ct
|= TCG_CT_CONST_U16
;
227 ct
->ct
|= TCG_CT_CONST_S16
;
230 ct
->ct
|= TCG_CT_CONST_P2M1
;
233 ct
->ct
|= TCG_CT_CONST_N16
;
236 ct
->ct
|= TCG_CT_CONST_WSZ
;
239 /* We are cheating a bit here, using the fact that the register
240 ZERO is also the register number 0. Hence there is no need
241 to check for const_args in each instruction. */
242 ct
->ct
|= TCG_CT_CONST_ZERO
;
250 /* test if a constant matches the constraint */
251 static inline int tcg_target_const_match(tcg_target_long val
, TCGType type
,
252 const TCGArgConstraint
*arg_ct
)
256 if (ct
& TCG_CT_CONST
) {
258 } else if ((ct
& TCG_CT_CONST_ZERO
) && val
== 0) {
260 } else if ((ct
& TCG_CT_CONST_U16
) && val
== (uint16_t)val
) {
262 } else if ((ct
& TCG_CT_CONST_S16
) && val
== (int16_t)val
) {
264 } else if ((ct
& TCG_CT_CONST_N16
) && val
>= -32767 && val
<= 32767) {
266 } else if ((ct
& TCG_CT_CONST_P2M1
)
267 && use_mips32r2_instructions
&& is_p2m1(val
)) {
269 } else if ((ct
& TCG_CT_CONST_WSZ
)
270 && val
== (type
== TCG_TYPE_I32
? 32 : 64)) {
276 /* instruction opcodes */
282 OPC_BLEZ
= 006 << 26,
283 OPC_BGTZ
= 007 << 26,
284 OPC_ADDIU
= 011 << 26,
285 OPC_SLTI
= 012 << 26,
286 OPC_SLTIU
= 013 << 26,
287 OPC_ANDI
= 014 << 26,
289 OPC_XORI
= 016 << 26,
291 OPC_DADDIU
= 031 << 26,
304 OPC_SPECIAL
= 000 << 26,
305 OPC_SLL
= OPC_SPECIAL
| 000,
306 OPC_SRL
= OPC_SPECIAL
| 002,
307 OPC_ROTR
= OPC_SPECIAL
| 002 | (1 << 21),
308 OPC_SRA
= OPC_SPECIAL
| 003,
309 OPC_SLLV
= OPC_SPECIAL
| 004,
310 OPC_SRLV
= OPC_SPECIAL
| 006,
311 OPC_ROTRV
= OPC_SPECIAL
| 006 | 0100,
312 OPC_SRAV
= OPC_SPECIAL
| 007,
313 OPC_JR_R5
= OPC_SPECIAL
| 010,
314 OPC_JALR
= OPC_SPECIAL
| 011,
315 OPC_MOVZ
= OPC_SPECIAL
| 012,
316 OPC_MOVN
= OPC_SPECIAL
| 013,
317 OPC_SYNC
= OPC_SPECIAL
| 017,
318 OPC_MFHI
= OPC_SPECIAL
| 020,
319 OPC_MFLO
= OPC_SPECIAL
| 022,
320 OPC_DSLLV
= OPC_SPECIAL
| 024,
321 OPC_DSRLV
= OPC_SPECIAL
| 026,
322 OPC_DROTRV
= OPC_SPECIAL
| 026 | 0100,
323 OPC_DSRAV
= OPC_SPECIAL
| 027,
324 OPC_MULT
= OPC_SPECIAL
| 030,
325 OPC_MUL_R6
= OPC_SPECIAL
| 030 | 0200,
326 OPC_MUH
= OPC_SPECIAL
| 030 | 0300,
327 OPC_MULTU
= OPC_SPECIAL
| 031,
328 OPC_MULU
= OPC_SPECIAL
| 031 | 0200,
329 OPC_MUHU
= OPC_SPECIAL
| 031 | 0300,
330 OPC_DIV
= OPC_SPECIAL
| 032,
331 OPC_DIV_R6
= OPC_SPECIAL
| 032 | 0200,
332 OPC_MOD
= OPC_SPECIAL
| 032 | 0300,
333 OPC_DIVU
= OPC_SPECIAL
| 033,
334 OPC_DIVU_R6
= OPC_SPECIAL
| 033 | 0200,
335 OPC_MODU
= OPC_SPECIAL
| 033 | 0300,
336 OPC_DMULT
= OPC_SPECIAL
| 034,
337 OPC_DMUL
= OPC_SPECIAL
| 034 | 0200,
338 OPC_DMUH
= OPC_SPECIAL
| 034 | 0300,
339 OPC_DMULTU
= OPC_SPECIAL
| 035,
340 OPC_DMULU
= OPC_SPECIAL
| 035 | 0200,
341 OPC_DMUHU
= OPC_SPECIAL
| 035 | 0300,
342 OPC_DDIV
= OPC_SPECIAL
| 036,
343 OPC_DDIV_R6
= OPC_SPECIAL
| 036 | 0200,
344 OPC_DMOD
= OPC_SPECIAL
| 036 | 0300,
345 OPC_DDIVU
= OPC_SPECIAL
| 037,
346 OPC_DDIVU_R6
= OPC_SPECIAL
| 037 | 0200,
347 OPC_DMODU
= OPC_SPECIAL
| 037 | 0300,
348 OPC_ADDU
= OPC_SPECIAL
| 041,
349 OPC_SUBU
= OPC_SPECIAL
| 043,
350 OPC_AND
= OPC_SPECIAL
| 044,
351 OPC_OR
= OPC_SPECIAL
| 045,
352 OPC_XOR
= OPC_SPECIAL
| 046,
353 OPC_NOR
= OPC_SPECIAL
| 047,
354 OPC_SLT
= OPC_SPECIAL
| 052,
355 OPC_SLTU
= OPC_SPECIAL
| 053,
356 OPC_DADDU
= OPC_SPECIAL
| 055,
357 OPC_DSUBU
= OPC_SPECIAL
| 057,
358 OPC_SELEQZ
= OPC_SPECIAL
| 065,
359 OPC_SELNEZ
= OPC_SPECIAL
| 067,
360 OPC_DSLL
= OPC_SPECIAL
| 070,
361 OPC_DSRL
= OPC_SPECIAL
| 072,
362 OPC_DROTR
= OPC_SPECIAL
| 072 | (1 << 21),
363 OPC_DSRA
= OPC_SPECIAL
| 073,
364 OPC_DSLL32
= OPC_SPECIAL
| 074,
365 OPC_DSRL32
= OPC_SPECIAL
| 076,
366 OPC_DROTR32
= OPC_SPECIAL
| 076 | (1 << 21),
367 OPC_DSRA32
= OPC_SPECIAL
| 077,
368 OPC_CLZ_R6
= OPC_SPECIAL
| 0120,
369 OPC_DCLZ_R6
= OPC_SPECIAL
| 0122,
371 OPC_REGIMM
= 001 << 26,
372 OPC_BLTZ
= OPC_REGIMM
| (000 << 16),
373 OPC_BGEZ
= OPC_REGIMM
| (001 << 16),
375 OPC_SPECIAL2
= 034 << 26,
376 OPC_MUL_R5
= OPC_SPECIAL2
| 002,
377 OPC_CLZ
= OPC_SPECIAL2
| 040,
378 OPC_DCLZ
= OPC_SPECIAL2
| 044,
380 OPC_SPECIAL3
= 037 << 26,
381 OPC_EXT
= OPC_SPECIAL3
| 000,
382 OPC_DEXTM
= OPC_SPECIAL3
| 001,
383 OPC_DEXTU
= OPC_SPECIAL3
| 002,
384 OPC_DEXT
= OPC_SPECIAL3
| 003,
385 OPC_INS
= OPC_SPECIAL3
| 004,
386 OPC_DINSM
= OPC_SPECIAL3
| 005,
387 OPC_DINSU
= OPC_SPECIAL3
| 006,
388 OPC_DINS
= OPC_SPECIAL3
| 007,
389 OPC_WSBH
= OPC_SPECIAL3
| 00240,
390 OPC_DSBH
= OPC_SPECIAL3
| 00244,
391 OPC_DSHD
= OPC_SPECIAL3
| 00544,
392 OPC_SEB
= OPC_SPECIAL3
| 02040,
393 OPC_SEH
= OPC_SPECIAL3
| 03040,
395 /* MIPS r6 doesn't have JR, JALR should be used instead */
396 OPC_JR
= use_mips32r6_instructions
? OPC_JALR
: OPC_JR_R5
,
399 * MIPS r6 replaces MUL with an alternative encoding which is
400 * backwards-compatible at the assembly level.
402 OPC_MUL
= use_mips32r6_instructions
? OPC_MUL_R6
: OPC_MUL_R5
,
404 /* MIPS r6 introduced names for weaker variants of SYNC. These are
405 backward compatible to previous architecture revisions. */
406 OPC_SYNC_WMB
= OPC_SYNC
| 0x04 << 5,
407 OPC_SYNC_MB
= OPC_SYNC
| 0x10 << 5,
408 OPC_SYNC_ACQUIRE
= OPC_SYNC
| 0x11 << 5,
409 OPC_SYNC_RELEASE
= OPC_SYNC
| 0x12 << 5,
410 OPC_SYNC_RMB
= OPC_SYNC
| 0x13 << 5,
412 /* Aliases for convenience. */
413 ALIAS_PADD
= sizeof(void *) == 4 ? OPC_ADDU
: OPC_DADDU
,
414 ALIAS_PADDI
= sizeof(void *) == 4 ? OPC_ADDIU
: OPC_DADDIU
,
415 ALIAS_TSRL
= TARGET_LONG_BITS
== 32 || TCG_TARGET_REG_BITS
== 32
416 ? OPC_SRL
: OPC_DSRL
,
422 static inline void tcg_out_opc_reg(TCGContext
*s
, MIPSInsn opc
,
423 TCGReg rd
, TCGReg rs
, TCGReg rt
)
428 inst
|= (rs
& 0x1F) << 21;
429 inst
|= (rt
& 0x1F) << 16;
430 inst
|= (rd
& 0x1F) << 11;
437 static inline void tcg_out_opc_imm(TCGContext
*s
, MIPSInsn opc
,
438 TCGReg rt
, TCGReg rs
, TCGArg imm
)
443 inst
|= (rs
& 0x1F) << 21;
444 inst
|= (rt
& 0x1F) << 16;
445 inst
|= (imm
& 0xffff);
452 static inline void tcg_out_opc_bf(TCGContext
*s
, MIPSInsn opc
, TCGReg rt
,
453 TCGReg rs
, int msb
, int lsb
)
458 inst
|= (rs
& 0x1F) << 21;
459 inst
|= (rt
& 0x1F) << 16;
460 inst
|= (msb
& 0x1F) << 11;
461 inst
|= (lsb
& 0x1F) << 6;
465 static inline void tcg_out_opc_bf64(TCGContext
*s
, MIPSInsn opc
, MIPSInsn opm
,
466 MIPSInsn oph
, TCGReg rt
, TCGReg rs
,
473 } else if (msb
>= 32) {
477 tcg_out_opc_bf(s
, opc
, rt
, rs
, msb
, lsb
);
483 static inline void tcg_out_opc_br(TCGContext
*s
, MIPSInsn opc
,
484 TCGReg rt
, TCGReg rs
)
486 /* We pay attention here to not modify the branch target by reading
487 the existing value and using it again. This ensure that caches and
488 memory are kept coherent during retranslation. */
489 uint16_t offset
= (uint16_t)*s
->code_ptr
;
491 tcg_out_opc_imm(s
, opc
, rt
, rs
, offset
);
497 static inline void tcg_out_opc_sa(TCGContext
*s
, MIPSInsn opc
,
498 TCGReg rd
, TCGReg rt
, TCGArg sa
)
503 inst
|= (rt
& 0x1F) << 16;
504 inst
|= (rd
& 0x1F) << 11;
505 inst
|= (sa
& 0x1F) << 6;
510 static void tcg_out_opc_sa64(TCGContext
*s
, MIPSInsn opc1
, MIPSInsn opc2
,
511 TCGReg rd
, TCGReg rt
, TCGArg sa
)
515 inst
= (sa
& 32 ? opc2
: opc1
);
516 inst
|= (rt
& 0x1F) << 16;
517 inst
|= (rd
& 0x1F) << 11;
518 inst
|= (sa
& 0x1F) << 6;
524 * Returns true if the branch was in range and the insn was emitted.
526 static bool tcg_out_opc_jmp(TCGContext
*s
, MIPSInsn opc
, void *target
)
528 uintptr_t dest
= (uintptr_t)target
;
529 uintptr_t from
= (uintptr_t)s
->code_ptr
+ 4;
532 /* The pc-region branch happens within the 256MB region of
533 the delay slot (thus the +4). */
534 if ((from
^ dest
) & -(1 << 28)) {
537 tcg_debug_assert((dest
& 3) == 0);
540 inst
|= (dest
>> 2) & 0x3ffffff;
545 static inline void tcg_out_nop(TCGContext
*s
)
550 static inline void tcg_out_dsll(TCGContext
*s
, TCGReg rd
, TCGReg rt
, TCGArg sa
)
552 tcg_out_opc_sa64(s
, OPC_DSLL
, OPC_DSLL32
, rd
, rt
, sa
);
555 static inline void tcg_out_dsrl(TCGContext
*s
, TCGReg rd
, TCGReg rt
, TCGArg sa
)
557 tcg_out_opc_sa64(s
, OPC_DSRL
, OPC_DSRL32
, rd
, rt
, sa
);
560 static inline void tcg_out_dsra(TCGContext
*s
, TCGReg rd
, TCGReg rt
, TCGArg sa
)
562 tcg_out_opc_sa64(s
, OPC_DSRA
, OPC_DSRA32
, rd
, rt
, sa
);
565 static inline void tcg_out_mov(TCGContext
*s
, TCGType type
,
566 TCGReg ret
, TCGReg arg
)
568 /* Simple reg-reg move, optimising out the 'do nothing' case */
570 tcg_out_opc_reg(s
, OPC_OR
, ret
, arg
, TCG_REG_ZERO
);
574 static void tcg_out_movi(TCGContext
*s
, TCGType type
,
575 TCGReg ret
, tcg_target_long arg
)
577 if (TCG_TARGET_REG_BITS
== 64 && type
== TCG_TYPE_I32
) {
580 if (arg
== (int16_t)arg
) {
581 tcg_out_opc_imm(s
, OPC_ADDIU
, ret
, TCG_REG_ZERO
, arg
);
584 if (arg
== (uint16_t)arg
) {
585 tcg_out_opc_imm(s
, OPC_ORI
, ret
, TCG_REG_ZERO
, arg
);
588 if (TCG_TARGET_REG_BITS
== 32 || arg
== (int32_t)arg
) {
589 tcg_out_opc_imm(s
, OPC_LUI
, ret
, TCG_REG_ZERO
, arg
>> 16);
591 tcg_out_movi(s
, TCG_TYPE_I32
, ret
, arg
>> 31 >> 1);
592 if (arg
& 0xffff0000ull
) {
593 tcg_out_dsll(s
, ret
, ret
, 16);
594 tcg_out_opc_imm(s
, OPC_ORI
, ret
, ret
, arg
>> 16);
595 tcg_out_dsll(s
, ret
, ret
, 16);
597 tcg_out_dsll(s
, ret
, ret
, 32);
601 tcg_out_opc_imm(s
, OPC_ORI
, ret
, ret
, arg
& 0xffff);
605 static inline void tcg_out_bswap16(TCGContext
*s
, TCGReg ret
, TCGReg arg
)
607 if (use_mips32r2_instructions
) {
608 tcg_out_opc_reg(s
, OPC_WSBH
, ret
, 0, arg
);
610 /* ret and arg can't be register at */
611 if (ret
== TCG_TMP0
|| arg
== TCG_TMP0
) {
615 tcg_out_opc_sa(s
, OPC_SRL
, TCG_TMP0
, arg
, 8);
616 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 8);
617 tcg_out_opc_imm(s
, OPC_ANDI
, ret
, ret
, 0xff00);
618 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_TMP0
);
622 static inline void tcg_out_bswap16s(TCGContext
*s
, TCGReg ret
, TCGReg arg
)
624 if (use_mips32r2_instructions
) {
625 tcg_out_opc_reg(s
, OPC_WSBH
, ret
, 0, arg
);
626 tcg_out_opc_reg(s
, OPC_SEH
, ret
, 0, ret
);
628 /* ret and arg can't be register at */
629 if (ret
== TCG_TMP0
|| arg
== TCG_TMP0
) {
633 tcg_out_opc_sa(s
, OPC_SRL
, TCG_TMP0
, arg
, 8);
634 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 24);
635 tcg_out_opc_sa(s
, OPC_SRA
, ret
, ret
, 16);
636 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_TMP0
);
640 static void tcg_out_bswap_subr(TCGContext
*s
, tcg_insn_unit
*sub
)
642 bool ok
= tcg_out_opc_jmp(s
, OPC_JAL
, sub
);
643 tcg_debug_assert(ok
);
646 static void tcg_out_bswap32(TCGContext
*s
, TCGReg ret
, TCGReg arg
)
648 if (use_mips32r2_instructions
) {
649 tcg_out_opc_reg(s
, OPC_WSBH
, ret
, 0, arg
);
650 tcg_out_opc_sa(s
, OPC_ROTR
, ret
, ret
, 16);
652 tcg_out_bswap_subr(s
, bswap32_addr
);
653 /* delay slot -- never omit the insn, like tcg_out_mov might. */
654 tcg_out_opc_reg(s
, OPC_OR
, TCG_TMP0
, arg
, TCG_REG_ZERO
);
655 tcg_out_mov(s
, TCG_TYPE_I32
, ret
, TCG_TMP3
);
659 static void tcg_out_bswap32u(TCGContext
*s
, TCGReg ret
, TCGReg arg
)
661 if (use_mips32r2_instructions
) {
662 tcg_out_opc_reg(s
, OPC_DSBH
, ret
, 0, arg
);
663 tcg_out_opc_reg(s
, OPC_DSHD
, ret
, 0, ret
);
664 tcg_out_dsrl(s
, ret
, ret
, 32);
666 tcg_out_bswap_subr(s
, bswap32u_addr
);
667 /* delay slot -- never omit the insn, like tcg_out_mov might. */
668 tcg_out_opc_reg(s
, OPC_OR
, TCG_TMP0
, arg
, TCG_REG_ZERO
);
669 tcg_out_mov(s
, TCG_TYPE_I32
, ret
, TCG_TMP3
);
673 static void tcg_out_bswap64(TCGContext
*s
, TCGReg ret
, TCGReg arg
)
675 if (use_mips32r2_instructions
) {
676 tcg_out_opc_reg(s
, OPC_DSBH
, ret
, 0, arg
);
677 tcg_out_opc_reg(s
, OPC_DSHD
, ret
, 0, ret
);
679 tcg_out_bswap_subr(s
, bswap64_addr
);
680 /* delay slot -- never omit the insn, like tcg_out_mov might. */
681 tcg_out_opc_reg(s
, OPC_OR
, TCG_TMP0
, arg
, TCG_REG_ZERO
);
682 tcg_out_mov(s
, TCG_TYPE_I32
, ret
, TCG_TMP3
);
686 static inline void tcg_out_ext8s(TCGContext
*s
, TCGReg ret
, TCGReg arg
)
688 if (use_mips32r2_instructions
) {
689 tcg_out_opc_reg(s
, OPC_SEB
, ret
, 0, arg
);
691 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 24);
692 tcg_out_opc_sa(s
, OPC_SRA
, ret
, ret
, 24);
696 static inline void tcg_out_ext16s(TCGContext
*s
, TCGReg ret
, TCGReg arg
)
698 if (use_mips32r2_instructions
) {
699 tcg_out_opc_reg(s
, OPC_SEH
, ret
, 0, arg
);
701 tcg_out_opc_sa(s
, OPC_SLL
, ret
, arg
, 16);
702 tcg_out_opc_sa(s
, OPC_SRA
, ret
, ret
, 16);
706 static inline void tcg_out_ext32u(TCGContext
*s
, TCGReg ret
, TCGReg arg
)
708 if (use_mips32r2_instructions
) {
709 tcg_out_opc_bf(s
, OPC_DEXT
, ret
, arg
, 31, 0);
711 tcg_out_dsll(s
, ret
, arg
, 32);
712 tcg_out_dsrl(s
, ret
, ret
, 32);
716 static void tcg_out_ldst(TCGContext
*s
, MIPSInsn opc
, TCGReg data
,
717 TCGReg addr
, intptr_t ofs
)
721 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_TMP0
, ofs
- lo
);
722 if (addr
!= TCG_REG_ZERO
) {
723 tcg_out_opc_reg(s
, ALIAS_PADD
, TCG_TMP0
, TCG_TMP0
, addr
);
727 tcg_out_opc_imm(s
, opc
, data
, addr
, lo
);
730 static inline void tcg_out_ld(TCGContext
*s
, TCGType type
, TCGReg arg
,
731 TCGReg arg1
, intptr_t arg2
)
733 MIPSInsn opc
= OPC_LD
;
734 if (TCG_TARGET_REG_BITS
== 32 || type
== TCG_TYPE_I32
) {
737 tcg_out_ldst(s
, opc
, arg
, arg1
, arg2
);
740 static inline void tcg_out_st(TCGContext
*s
, TCGType type
, TCGReg arg
,
741 TCGReg arg1
, intptr_t arg2
)
743 MIPSInsn opc
= OPC_SD
;
744 if (TCG_TARGET_REG_BITS
== 32 || type
== TCG_TYPE_I32
) {
747 tcg_out_ldst(s
, opc
, arg
, arg1
, arg2
);
750 static inline bool tcg_out_sti(TCGContext
*s
, TCGType type
, TCGArg val
,
751 TCGReg base
, intptr_t ofs
)
754 tcg_out_st(s
, type
, TCG_REG_ZERO
, base
, ofs
);
760 static void tcg_out_addsub2(TCGContext
*s
, TCGReg rl
, TCGReg rh
, TCGReg al
,
761 TCGReg ah
, TCGArg bl
, TCGArg bh
, bool cbl
,
762 bool cbh
, bool is_sub
)
764 TCGReg th
= TCG_TMP1
;
766 /* If we have a negative constant such that negating it would
767 make the high part zero, we can (usually) eliminate one insn. */
768 if (cbl
&& cbh
&& bh
== -1 && bl
!= 0) {
774 /* By operating on the high part first, we get to use the final
775 carry operation to move back from the temporary. */
777 tcg_out_opc_reg(s
, (is_sub
? OPC_SUBU
: OPC_ADDU
), th
, ah
, bh
);
778 } else if (bh
!= 0 || ah
== rl
) {
779 tcg_out_opc_imm(s
, OPC_ADDIU
, th
, ah
, (is_sub
? -bh
: bh
));
784 /* Note that tcg optimization should eliminate the bl == 0 case. */
787 tcg_out_opc_imm(s
, OPC_SLTIU
, TCG_TMP0
, al
, bl
);
788 tcg_out_opc_imm(s
, OPC_ADDIU
, rl
, al
, -bl
);
790 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_TMP0
, al
, bl
);
791 tcg_out_opc_reg(s
, OPC_SUBU
, rl
, al
, bl
);
793 tcg_out_opc_reg(s
, OPC_SUBU
, rh
, th
, TCG_TMP0
);
796 tcg_out_opc_imm(s
, OPC_ADDIU
, rl
, al
, bl
);
797 tcg_out_opc_imm(s
, OPC_SLTIU
, TCG_TMP0
, rl
, bl
);
798 } else if (rl
== al
&& rl
== bl
) {
799 tcg_out_opc_sa(s
, OPC_SRL
, TCG_TMP0
, al
, 31);
800 tcg_out_opc_reg(s
, OPC_ADDU
, rl
, al
, bl
);
802 tcg_out_opc_reg(s
, OPC_ADDU
, rl
, al
, bl
);
803 tcg_out_opc_reg(s
, OPC_SLTU
, TCG_TMP0
, rl
, (rl
== bl
? al
: bl
));
805 tcg_out_opc_reg(s
, OPC_ADDU
, rh
, th
, TCG_TMP0
);
809 /* Bit 0 set if inversion required; bit 1 set if swapping required. */
810 #define MIPS_CMP_INV 1
811 #define MIPS_CMP_SWAP 2
813 static const uint8_t mips_cmp_map
[16] = {
816 [TCG_COND_GE
] = MIPS_CMP_INV
,
817 [TCG_COND_GEU
] = MIPS_CMP_INV
,
818 [TCG_COND_LE
] = MIPS_CMP_INV
| MIPS_CMP_SWAP
,
819 [TCG_COND_LEU
] = MIPS_CMP_INV
| MIPS_CMP_SWAP
,
820 [TCG_COND_GT
] = MIPS_CMP_SWAP
,
821 [TCG_COND_GTU
] = MIPS_CMP_SWAP
,
824 static void tcg_out_setcond(TCGContext
*s
, TCGCond cond
, TCGReg ret
,
825 TCGReg arg1
, TCGReg arg2
)
827 MIPSInsn s_opc
= OPC_SLTU
;
833 tcg_out_opc_reg(s
, OPC_XOR
, ret
, arg1
, arg2
);
836 tcg_out_opc_imm(s
, OPC_SLTIU
, ret
, arg1
, 1);
841 tcg_out_opc_reg(s
, OPC_XOR
, ret
, arg1
, arg2
);
844 tcg_out_opc_reg(s
, OPC_SLTU
, ret
, TCG_REG_ZERO
, arg1
);
858 cmp_map
= mips_cmp_map
[cond
];
859 if (cmp_map
& MIPS_CMP_SWAP
) {
864 tcg_out_opc_reg(s
, s_opc
, ret
, arg1
, arg2
);
865 if (cmp_map
& MIPS_CMP_INV
) {
866 tcg_out_opc_imm(s
, OPC_XORI
, ret
, ret
, 1);
876 static void tcg_out_brcond(TCGContext
*s
, TCGCond cond
, TCGReg arg1
,
877 TCGReg arg2
, TCGLabel
*l
)
879 static const MIPSInsn b_zero
[16] = {
880 [TCG_COND_LT
] = OPC_BLTZ
,
881 [TCG_COND_GT
] = OPC_BGTZ
,
882 [TCG_COND_LE
] = OPC_BLEZ
,
883 [TCG_COND_GE
] = OPC_BGEZ
,
886 MIPSInsn s_opc
= OPC_SLTU
;
903 b_opc
= b_zero
[cond
];
915 cmp_map
= mips_cmp_map
[cond
];
916 if (cmp_map
& MIPS_CMP_SWAP
) {
921 tcg_out_opc_reg(s
, s_opc
, TCG_TMP0
, arg1
, arg2
);
922 b_opc
= (cmp_map
& MIPS_CMP_INV
? OPC_BEQ
: OPC_BNE
);
932 tcg_out_opc_br(s
, b_opc
, arg1
, arg2
);
934 reloc_pc16(s
->code_ptr
- 1, l
->u
.value_ptr
);
936 tcg_out_reloc(s
, s
->code_ptr
- 1, R_MIPS_PC16
, l
, 0);
941 static TCGReg
tcg_out_reduce_eq2(TCGContext
*s
, TCGReg tmp0
, TCGReg tmp1
,
942 TCGReg al
, TCGReg ah
,
943 TCGReg bl
, TCGReg bh
)
945 /* Merge highpart comparison into AH. */
948 tcg_out_opc_reg(s
, OPC_XOR
, tmp0
, ah
, bh
);
954 /* Merge lowpart comparison into AL. */
957 tcg_out_opc_reg(s
, OPC_XOR
, tmp1
, al
, bl
);
963 /* Merge high and low part comparisons into AL. */
966 tcg_out_opc_reg(s
, OPC_OR
, tmp0
, ah
, al
);
975 static void tcg_out_setcond2(TCGContext
*s
, TCGCond cond
, TCGReg ret
,
976 TCGReg al
, TCGReg ah
, TCGReg bl
, TCGReg bh
)
978 TCGReg tmp0
= TCG_TMP0
;
981 tcg_debug_assert(ret
!= TCG_TMP0
);
982 if (ret
== ah
|| ret
== bh
) {
983 tcg_debug_assert(ret
!= TCG_TMP1
);
990 tmp1
= tcg_out_reduce_eq2(s
, tmp0
, tmp1
, al
, ah
, bl
, bh
);
991 tcg_out_setcond(s
, cond
, ret
, tmp1
, TCG_REG_ZERO
);
995 tcg_out_setcond(s
, TCG_COND_EQ
, tmp0
, ah
, bh
);
996 tcg_out_setcond(s
, tcg_unsigned_cond(cond
), tmp1
, al
, bl
);
997 tcg_out_opc_reg(s
, OPC_AND
, tmp1
, tmp1
, tmp0
);
998 tcg_out_setcond(s
, tcg_high_cond(cond
), tmp0
, ah
, bh
);
999 tcg_out_opc_reg(s
, OPC_OR
, ret
, tmp1
, tmp0
);
1004 static void tcg_out_brcond2(TCGContext
*s
, TCGCond cond
, TCGReg al
, TCGReg ah
,
1005 TCGReg bl
, TCGReg bh
, TCGLabel
*l
)
1007 TCGCond b_cond
= TCG_COND_NE
;
1008 TCGReg tmp
= TCG_TMP1
;
1010 /* With branches, we emit between 4 and 9 insns with 2 or 3 branches.
1011 With setcond, we emit between 3 and 10 insns and only 1 branch,
1012 which ought to get better branch prediction. */
1017 tmp
= tcg_out_reduce_eq2(s
, TCG_TMP0
, TCG_TMP1
, al
, ah
, bl
, bh
);
1021 /* Minimize code size by preferring a compare not requiring INV. */
1022 if (mips_cmp_map
[cond
] & MIPS_CMP_INV
) {
1023 cond
= tcg_invert_cond(cond
);
1024 b_cond
= TCG_COND_EQ
;
1026 tcg_out_setcond2(s
, cond
, tmp
, al
, ah
, bl
, bh
);
1030 tcg_out_brcond(s
, b_cond
, tmp
, TCG_REG_ZERO
, l
);
1033 static void tcg_out_movcond(TCGContext
*s
, TCGCond cond
, TCGReg ret
,
1034 TCGReg c1
, TCGReg c2
, TCGReg v1
, TCGReg v2
)
1038 /* If one of the values is zero, put it last to match SEL*Z instructions */
1039 if (use_mips32r6_instructions
&& v1
== 0) {
1042 cond
= tcg_invert_cond(cond
);
1051 tcg_out_opc_reg(s
, OPC_XOR
, TCG_TMP0
, c1
, c2
);
1057 /* Minimize code size by preferring a compare not requiring INV. */
1058 if (mips_cmp_map
[cond
] & MIPS_CMP_INV
) {
1059 cond
= tcg_invert_cond(cond
);
1062 tcg_out_setcond(s
, cond
, TCG_TMP0
, c1
, c2
);
1067 if (use_mips32r6_instructions
) {
1068 MIPSInsn m_opc_t
= eqz
? OPC_SELEQZ
: OPC_SELNEZ
;
1069 MIPSInsn m_opc_f
= eqz
? OPC_SELNEZ
: OPC_SELEQZ
;
1072 tcg_out_opc_reg(s
, m_opc_f
, TCG_TMP1
, v2
, c1
);
1074 tcg_out_opc_reg(s
, m_opc_t
, ret
, v1
, c1
);
1076 tcg_out_opc_reg(s
, OPC_OR
, ret
, ret
, TCG_TMP1
);
1079 MIPSInsn m_opc
= eqz
? OPC_MOVZ
: OPC_MOVN
;
1081 tcg_out_opc_reg(s
, m_opc
, ret
, v1
, c1
);
1083 /* This should be guaranteed via constraints */
1084 tcg_debug_assert(v2
== ret
);
1088 static void tcg_out_call_int(TCGContext
*s
, tcg_insn_unit
*arg
, bool tail
)
1090 /* Note that the ABI requires the called function's address to be
1091 loaded into T9, even if a direct branch is in range. */
1092 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_T9
, (uintptr_t)arg
);
1094 /* But do try a direct branch, allowing the cpu better insn prefetch. */
1096 if (!tcg_out_opc_jmp(s
, OPC_J
, arg
)) {
1097 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_T9
, 0);
1100 if (!tcg_out_opc_jmp(s
, OPC_JAL
, arg
)) {
1101 tcg_out_opc_reg(s
, OPC_JALR
, TCG_REG_RA
, TCG_REG_T9
, 0);
1106 static void tcg_out_call(TCGContext
*s
, tcg_insn_unit
*arg
)
1108 tcg_out_call_int(s
, arg
, false);
1112 #if defined(CONFIG_SOFTMMU)
1113 #include "tcg-ldst.inc.c"
1115 static void * const qemu_ld_helpers
[16] = {
1116 [MO_UB
] = helper_ret_ldub_mmu
,
1117 [MO_SB
] = helper_ret_ldsb_mmu
,
1118 [MO_LEUW
] = helper_le_lduw_mmu
,
1119 [MO_LESW
] = helper_le_ldsw_mmu
,
1120 [MO_LEUL
] = helper_le_ldul_mmu
,
1121 [MO_LEQ
] = helper_le_ldq_mmu
,
1122 [MO_BEUW
] = helper_be_lduw_mmu
,
1123 [MO_BESW
] = helper_be_ldsw_mmu
,
1124 [MO_BEUL
] = helper_be_ldul_mmu
,
1125 [MO_BEQ
] = helper_be_ldq_mmu
,
1126 #if TCG_TARGET_REG_BITS == 64
1127 [MO_LESL
] = helper_le_ldsl_mmu
,
1128 [MO_BESL
] = helper_be_ldsl_mmu
,
1132 static void * const qemu_st_helpers
[16] = {
1133 [MO_UB
] = helper_ret_stb_mmu
,
1134 [MO_LEUW
] = helper_le_stw_mmu
,
1135 [MO_LEUL
] = helper_le_stl_mmu
,
1136 [MO_LEQ
] = helper_le_stq_mmu
,
1137 [MO_BEUW
] = helper_be_stw_mmu
,
1138 [MO_BEUL
] = helper_be_stl_mmu
,
1139 [MO_BEQ
] = helper_be_stq_mmu
,
1142 /* Helper routines for marshalling helper function arguments into
1143 * the correct registers and stack.
1144 * I is where we want to put this argument, and is updated and returned
1145 * for the next call. ARG is the argument itself.
1147 * We provide routines for arguments which are: immediate, 32 bit
1148 * value in register, 16 and 8 bit values in register (which must be zero
1149 * extended before use) and 64 bit value in a lo:hi register pair.
1152 static int tcg_out_call_iarg_reg(TCGContext
*s
, int i
, TCGReg arg
)
1154 if (i
< ARRAY_SIZE(tcg_target_call_iarg_regs
)) {
1155 tcg_out_mov(s
, TCG_TYPE_REG
, tcg_target_call_iarg_regs
[i
], arg
);
1157 /* For N32 and N64, the initial offset is different. But there
1158 we also have 8 argument register so we don't run out here. */
1159 tcg_debug_assert(TCG_TARGET_REG_BITS
== 32);
1160 tcg_out_st(s
, TCG_TYPE_REG
, arg
, TCG_REG_SP
, 4 * i
);
1165 static int tcg_out_call_iarg_reg8(TCGContext
*s
, int i
, TCGReg arg
)
1167 TCGReg tmp
= TCG_TMP0
;
1168 if (i
< ARRAY_SIZE(tcg_target_call_iarg_regs
)) {
1169 tmp
= tcg_target_call_iarg_regs
[i
];
1171 tcg_out_opc_imm(s
, OPC_ANDI
, tmp
, arg
, 0xff);
1172 return tcg_out_call_iarg_reg(s
, i
, tmp
);
1175 static int tcg_out_call_iarg_reg16(TCGContext
*s
, int i
, TCGReg arg
)
1177 TCGReg tmp
= TCG_TMP0
;
1178 if (i
< ARRAY_SIZE(tcg_target_call_iarg_regs
)) {
1179 tmp
= tcg_target_call_iarg_regs
[i
];
1181 tcg_out_opc_imm(s
, OPC_ANDI
, tmp
, arg
, 0xffff);
1182 return tcg_out_call_iarg_reg(s
, i
, tmp
);
1185 static int tcg_out_call_iarg_imm(TCGContext
*s
, int i
, TCGArg arg
)
1187 TCGReg tmp
= TCG_TMP0
;
1191 if (i
< ARRAY_SIZE(tcg_target_call_iarg_regs
)) {
1192 tmp
= tcg_target_call_iarg_regs
[i
];
1194 tcg_out_movi(s
, TCG_TYPE_REG
, tmp
, arg
);
1196 return tcg_out_call_iarg_reg(s
, i
, tmp
);
1199 static int tcg_out_call_iarg_reg2(TCGContext
*s
, int i
, TCGReg al
, TCGReg ah
)
1201 tcg_debug_assert(TCG_TARGET_REG_BITS
== 32);
1203 i
= tcg_out_call_iarg_reg(s
, i
, (MIPS_BE
? ah
: al
));
1204 i
= tcg_out_call_iarg_reg(s
, i
, (MIPS_BE
? al
: ah
));
1208 /* Perform the tlb comparison operation. The complete host address is
1209 placed in BASE. Clobbers TMP0, TMP1, TMP2, A0. */
1210 static void tcg_out_tlb_load(TCGContext
*s
, TCGReg base
, TCGReg addrl
,
1211 TCGReg addrh
, TCGMemOpIdx oi
,
1212 tcg_insn_unit
*label_ptr
[2], bool is_load
)
1214 TCGMemOp opc
= get_memop(oi
);
1215 unsigned s_bits
= opc
& MO_SIZE
;
1216 unsigned a_bits
= get_alignment_bits(opc
);
1218 int mem_index
= get_mmuidx(oi
);
1221 ? offsetof(CPUArchState
, tlb_table
[mem_index
][0].addr_read
)
1222 : offsetof(CPUArchState
, tlb_table
[mem_index
][0].addr_write
));
1223 int add_off
= offsetof(CPUArchState
, tlb_table
[mem_index
][0].addend
);
1225 tcg_out_opc_sa(s
, ALIAS_TSRL
, TCG_REG_A0
, addrl
,
1226 TARGET_PAGE_BITS
- CPU_TLB_ENTRY_BITS
);
1227 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_REG_A0
, TCG_REG_A0
,
1228 (CPU_TLB_SIZE
- 1) << CPU_TLB_ENTRY_BITS
);
1229 tcg_out_opc_reg(s
, ALIAS_PADD
, TCG_REG_A0
, TCG_REG_A0
, TCG_AREG0
);
1231 /* Compensate for very large offsets. */
1232 if (add_off
>= 0x8000) {
1233 /* Most target env are smaller than 32k; none are larger than 64k.
1234 Simplify the logic here merely to offset by 0x7ff0, giving us a
1235 range just shy of 64k. Check this assumption. */
1236 QEMU_BUILD_BUG_ON(offsetof(CPUArchState
,
1237 tlb_table
[NB_MMU_MODES
- 1][1])
1239 tcg_out_opc_imm(s
, ALIAS_PADDI
, TCG_REG_A0
, TCG_REG_A0
, 0x7ff0);
1244 /* We don't currently support unaligned accesses.
1245 We could do so with mips32r6. */
1246 if (a_bits
< s_bits
) {
1250 mask
= (target_ulong
)TARGET_PAGE_MASK
| ((1 << a_bits
) - 1);
1252 /* Load the (low half) tlb comparator. Mask the page bits, keeping the
1253 alignment bits to compare against. */
1254 if (TCG_TARGET_REG_BITS
< TARGET_LONG_BITS
) {
1255 tcg_out_ld(s
, TCG_TYPE_I32
, TCG_TMP0
, TCG_REG_A0
, cmp_off
+ LO_OFF
);
1256 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_TMP1
, mask
);
1259 (TARGET_LONG_BITS
== 64 ? OPC_LD
1260 : TCG_TARGET_REG_BITS
== 64 ? OPC_LWU
: OPC_LW
),
1261 TCG_TMP0
, TCG_REG_A0
, cmp_off
);
1262 tcg_out_movi(s
, TCG_TYPE_TL
, TCG_TMP1
, mask
);
1263 /* No second compare is required here;
1264 load the tlb addend for the fast path. */
1265 tcg_out_ld(s
, TCG_TYPE_PTR
, TCG_TMP2
, TCG_REG_A0
, add_off
);
1267 tcg_out_opc_reg(s
, OPC_AND
, TCG_TMP1
, TCG_TMP1
, addrl
);
1269 /* Zero extend a 32-bit guest address for a 64-bit host. */
1270 if (TCG_TARGET_REG_BITS
> TARGET_LONG_BITS
) {
1271 tcg_out_ext32u(s
, base
, addrl
);
1275 label_ptr
[0] = s
->code_ptr
;
1276 tcg_out_opc_br(s
, OPC_BNE
, TCG_TMP1
, TCG_TMP0
);
1278 /* Load and test the high half tlb comparator. */
1279 if (TCG_TARGET_REG_BITS
< TARGET_LONG_BITS
) {
1281 tcg_out_ld(s
, TCG_TYPE_I32
, TCG_TMP0
, TCG_REG_A0
, cmp_off
+ HI_OFF
);
1283 /* Load the tlb addend for the fast path. */
1284 tcg_out_ld(s
, TCG_TYPE_PTR
, TCG_TMP2
, TCG_REG_A0
, add_off
);
1286 label_ptr
[1] = s
->code_ptr
;
1287 tcg_out_opc_br(s
, OPC_BNE
, addrh
, TCG_TMP0
);
1291 tcg_out_opc_reg(s
, ALIAS_PADD
, base
, TCG_TMP2
, addrl
);
1294 static void add_qemu_ldst_label(TCGContext
*s
, int is_ld
, TCGMemOpIdx oi
,
1296 TCGReg datalo
, TCGReg datahi
,
1297 TCGReg addrlo
, TCGReg addrhi
,
1298 void *raddr
, tcg_insn_unit
*label_ptr
[2])
1300 TCGLabelQemuLdst
*label
= new_ldst_label(s
);
1302 label
->is_ld
= is_ld
;
1305 label
->datalo_reg
= datalo
;
1306 label
->datahi_reg
= datahi
;
1307 label
->addrlo_reg
= addrlo
;
1308 label
->addrhi_reg
= addrhi
;
1309 label
->raddr
= raddr
;
1310 label
->label_ptr
[0] = label_ptr
[0];
1311 if (TCG_TARGET_REG_BITS
< TARGET_LONG_BITS
) {
1312 label
->label_ptr
[1] = label_ptr
[1];
1316 static void tcg_out_qemu_ld_slow_path(TCGContext
*s
, TCGLabelQemuLdst
*l
)
1318 TCGMemOpIdx oi
= l
->oi
;
1319 TCGMemOp opc
= get_memop(oi
);
1323 /* resolve label address */
1324 reloc_pc16(l
->label_ptr
[0], s
->code_ptr
);
1325 if (TCG_TARGET_REG_BITS
< TARGET_LONG_BITS
) {
1326 reloc_pc16(l
->label_ptr
[1], s
->code_ptr
);
1330 if (TCG_TARGET_REG_BITS
< TARGET_LONG_BITS
) {
1331 i
= tcg_out_call_iarg_reg2(s
, i
, l
->addrlo_reg
, l
->addrhi_reg
);
1333 i
= tcg_out_call_iarg_reg(s
, i
, l
->addrlo_reg
);
1335 i
= tcg_out_call_iarg_imm(s
, i
, oi
);
1336 i
= tcg_out_call_iarg_imm(s
, i
, (intptr_t)l
->raddr
);
1337 tcg_out_call_int(s
, qemu_ld_helpers
[opc
& (MO_BSWAP
| MO_SSIZE
)], false);
1339 tcg_out_mov(s
, TCG_TYPE_PTR
, tcg_target_call_iarg_regs
[0], TCG_AREG0
);
1342 if (TCG_TARGET_REG_BITS
== 32 && (opc
& MO_SIZE
) == MO_64
) {
1343 /* We eliminated V0 from the possible output registers, so it
1344 cannot be clobbered here. So we must move V1 first. */
1346 tcg_out_mov(s
, TCG_TYPE_I32
, v0
, TCG_REG_V1
);
1349 tcg_out_mov(s
, TCG_TYPE_I32
, l
->datahi_reg
, TCG_REG_V1
);
1353 reloc_pc16(s
->code_ptr
, l
->raddr
);
1354 tcg_out_opc_br(s
, OPC_BEQ
, TCG_REG_ZERO
, TCG_REG_ZERO
);
1356 if (TCG_TARGET_REG_BITS
== 64 && l
->type
== TCG_TYPE_I32
) {
1357 /* we always sign-extend 32-bit loads */
1358 tcg_out_opc_sa(s
, OPC_SLL
, v0
, TCG_REG_V0
, 0);
1360 tcg_out_opc_reg(s
, OPC_OR
, v0
, TCG_REG_V0
, TCG_REG_ZERO
);
1364 static void tcg_out_qemu_st_slow_path(TCGContext
*s
, TCGLabelQemuLdst
*l
)
1366 TCGMemOpIdx oi
= l
->oi
;
1367 TCGMemOp opc
= get_memop(oi
);
1368 TCGMemOp s_bits
= opc
& MO_SIZE
;
1371 /* resolve label address */
1372 reloc_pc16(l
->label_ptr
[0], s
->code_ptr
);
1373 if (TCG_TARGET_REG_BITS
< TARGET_LONG_BITS
) {
1374 reloc_pc16(l
->label_ptr
[1], s
->code_ptr
);
1378 if (TCG_TARGET_REG_BITS
< TARGET_LONG_BITS
) {
1379 i
= tcg_out_call_iarg_reg2(s
, i
, l
->addrlo_reg
, l
->addrhi_reg
);
1381 i
= tcg_out_call_iarg_reg(s
, i
, l
->addrlo_reg
);
1385 i
= tcg_out_call_iarg_reg8(s
, i
, l
->datalo_reg
);
1388 i
= tcg_out_call_iarg_reg16(s
, i
, l
->datalo_reg
);
1391 i
= tcg_out_call_iarg_reg(s
, i
, l
->datalo_reg
);
1394 if (TCG_TARGET_REG_BITS
== 32) {
1395 i
= tcg_out_call_iarg_reg2(s
, i
, l
->datalo_reg
, l
->datahi_reg
);
1397 i
= tcg_out_call_iarg_reg(s
, i
, l
->datalo_reg
);
1403 i
= tcg_out_call_iarg_imm(s
, i
, oi
);
1405 /* Tail call to the store helper. Thus force the return address
1406 computation to take place in the return address register. */
1407 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_RA
, (intptr_t)l
->raddr
);
1408 i
= tcg_out_call_iarg_reg(s
, i
, TCG_REG_RA
);
1409 tcg_out_call_int(s
, qemu_st_helpers
[opc
& (MO_BSWAP
| MO_SIZE
)], true);
1411 tcg_out_mov(s
, TCG_TYPE_PTR
, tcg_target_call_iarg_regs
[0], TCG_AREG0
);
1415 static void tcg_out_qemu_ld_direct(TCGContext
*s
, TCGReg lo
, TCGReg hi
,
1416 TCGReg base
, TCGMemOp opc
, bool is_64
)
1418 switch (opc
& (MO_SSIZE
| MO_BSWAP
)) {
1420 tcg_out_opc_imm(s
, OPC_LBU
, lo
, base
, 0);
1423 tcg_out_opc_imm(s
, OPC_LB
, lo
, base
, 0);
1425 case MO_UW
| MO_BSWAP
:
1426 tcg_out_opc_imm(s
, OPC_LHU
, TCG_TMP1
, base
, 0);
1427 tcg_out_bswap16(s
, lo
, TCG_TMP1
);
1430 tcg_out_opc_imm(s
, OPC_LHU
, lo
, base
, 0);
1432 case MO_SW
| MO_BSWAP
:
1433 tcg_out_opc_imm(s
, OPC_LHU
, TCG_TMP1
, base
, 0);
1434 tcg_out_bswap16s(s
, lo
, TCG_TMP1
);
1437 tcg_out_opc_imm(s
, OPC_LH
, lo
, base
, 0);
1439 case MO_UL
| MO_BSWAP
:
1440 if (TCG_TARGET_REG_BITS
== 64 && is_64
) {
1441 if (use_mips32r2_instructions
) {
1442 tcg_out_opc_imm(s
, OPC_LWU
, lo
, base
, 0);
1443 tcg_out_bswap32u(s
, lo
, lo
);
1445 tcg_out_bswap_subr(s
, bswap32u_addr
);
1447 tcg_out_opc_imm(s
, OPC_LWU
, TCG_TMP0
, base
, 0);
1448 tcg_out_mov(s
, TCG_TYPE_I64
, lo
, TCG_TMP3
);
1453 case MO_SL
| MO_BSWAP
:
1454 if (use_mips32r2_instructions
) {
1455 tcg_out_opc_imm(s
, OPC_LW
, lo
, base
, 0);
1456 tcg_out_bswap32(s
, lo
, lo
);
1458 tcg_out_bswap_subr(s
, bswap32_addr
);
1460 tcg_out_opc_imm(s
, OPC_LW
, TCG_TMP0
, base
, 0);
1461 tcg_out_mov(s
, TCG_TYPE_I32
, lo
, TCG_TMP3
);
1465 if (TCG_TARGET_REG_BITS
== 64 && is_64
) {
1466 tcg_out_opc_imm(s
, OPC_LWU
, lo
, base
, 0);
1471 tcg_out_opc_imm(s
, OPC_LW
, lo
, base
, 0);
1473 case MO_Q
| MO_BSWAP
:
1474 if (TCG_TARGET_REG_BITS
== 64) {
1475 if (use_mips32r2_instructions
) {
1476 tcg_out_opc_imm(s
, OPC_LD
, lo
, base
, 0);
1477 tcg_out_bswap64(s
, lo
, lo
);
1479 tcg_out_bswap_subr(s
, bswap64_addr
);
1481 tcg_out_opc_imm(s
, OPC_LD
, TCG_TMP0
, base
, 0);
1482 tcg_out_mov(s
, TCG_TYPE_I64
, lo
, TCG_TMP3
);
1484 } else if (use_mips32r2_instructions
) {
1485 tcg_out_opc_imm(s
, OPC_LW
, TCG_TMP0
, base
, 0);
1486 tcg_out_opc_imm(s
, OPC_LW
, TCG_TMP1
, base
, 4);
1487 tcg_out_opc_reg(s
, OPC_WSBH
, TCG_TMP0
, 0, TCG_TMP0
);
1488 tcg_out_opc_reg(s
, OPC_WSBH
, TCG_TMP1
, 0, TCG_TMP1
);
1489 tcg_out_opc_sa(s
, OPC_ROTR
, MIPS_BE
? lo
: hi
, TCG_TMP0
, 16);
1490 tcg_out_opc_sa(s
, OPC_ROTR
, MIPS_BE
? hi
: lo
, TCG_TMP1
, 16);
1492 tcg_out_bswap_subr(s
, bswap32_addr
);
1494 tcg_out_opc_imm(s
, OPC_LW
, TCG_TMP0
, base
, 0);
1495 tcg_out_opc_imm(s
, OPC_LW
, TCG_TMP0
, base
, 4);
1496 tcg_out_bswap_subr(s
, bswap32_addr
);
1498 tcg_out_mov(s
, TCG_TYPE_I32
, MIPS_BE
? lo
: hi
, TCG_TMP3
);
1499 tcg_out_mov(s
, TCG_TYPE_I32
, MIPS_BE
? hi
: lo
, TCG_TMP3
);
1503 /* Prefer to load from offset 0 first, but allow for overlap. */
1504 if (TCG_TARGET_REG_BITS
== 64) {
1505 tcg_out_opc_imm(s
, OPC_LD
, lo
, base
, 0);
1506 } else if (MIPS_BE
? hi
!= base
: lo
== base
) {
1507 tcg_out_opc_imm(s
, OPC_LW
, hi
, base
, HI_OFF
);
1508 tcg_out_opc_imm(s
, OPC_LW
, lo
, base
, LO_OFF
);
1510 tcg_out_opc_imm(s
, OPC_LW
, lo
, base
, LO_OFF
);
1511 tcg_out_opc_imm(s
, OPC_LW
, hi
, base
, HI_OFF
);
1519 static void tcg_out_qemu_ld(TCGContext
*s
, const TCGArg
*args
, bool is_64
)
1521 TCGReg addr_regl
, addr_regh
__attribute__((unused
));
1522 TCGReg data_regl
, data_regh
;
1525 #if defined(CONFIG_SOFTMMU)
1526 tcg_insn_unit
*label_ptr
[2];
1528 TCGReg base
= TCG_REG_A0
;
1530 data_regl
= *args
++;
1531 data_regh
= (TCG_TARGET_REG_BITS
== 32 && is_64
? *args
++ : 0);
1532 addr_regl
= *args
++;
1533 addr_regh
= (TCG_TARGET_REG_BITS
< TARGET_LONG_BITS
? *args
++ : 0);
1535 opc
= get_memop(oi
);
1537 #if defined(CONFIG_SOFTMMU)
1538 tcg_out_tlb_load(s
, base
, addr_regl
, addr_regh
, oi
, label_ptr
, 1);
1539 tcg_out_qemu_ld_direct(s
, data_regl
, data_regh
, base
, opc
, is_64
);
1540 add_qemu_ldst_label(s
, 1, oi
,
1541 (is_64
? TCG_TYPE_I64
: TCG_TYPE_I32
),
1542 data_regl
, data_regh
, addr_regl
, addr_regh
,
1543 s
->code_ptr
, label_ptr
);
1545 if (TCG_TARGET_REG_BITS
> TARGET_LONG_BITS
) {
1546 tcg_out_ext32u(s
, base
, addr_regl
);
1549 if (guest_base
== 0 && data_regl
!= addr_regl
) {
1551 } else if (guest_base
== (int16_t)guest_base
) {
1552 tcg_out_opc_imm(s
, ALIAS_PADDI
, base
, addr_regl
, guest_base
);
1554 tcg_out_opc_reg(s
, ALIAS_PADD
, base
, TCG_GUEST_BASE_REG
, addr_regl
);
1556 tcg_out_qemu_ld_direct(s
, data_regl
, data_regh
, base
, opc
, is_64
);
1560 static void tcg_out_qemu_st_direct(TCGContext
*s
, TCGReg lo
, TCGReg hi
,
1561 TCGReg base
, TCGMemOp opc
)
1563 /* Don't clutter the code below with checks to avoid bswapping ZERO. */
1564 if ((lo
| hi
) == 0) {
1568 switch (opc
& (MO_SIZE
| MO_BSWAP
)) {
1570 tcg_out_opc_imm(s
, OPC_SB
, lo
, base
, 0);
1573 case MO_16
| MO_BSWAP
:
1574 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_TMP1
, lo
, 0xffff);
1575 tcg_out_bswap16(s
, TCG_TMP1
, TCG_TMP1
);
1579 tcg_out_opc_imm(s
, OPC_SH
, lo
, base
, 0);
1582 case MO_32
| MO_BSWAP
:
1583 tcg_out_bswap32(s
, TCG_TMP3
, lo
);
1587 tcg_out_opc_imm(s
, OPC_SW
, lo
, base
, 0);
1590 case MO_64
| MO_BSWAP
:
1591 if (TCG_TARGET_REG_BITS
== 64) {
1592 tcg_out_bswap64(s
, TCG_TMP3
, lo
);
1593 tcg_out_opc_imm(s
, OPC_SD
, TCG_TMP3
, base
, 0);
1594 } else if (use_mips32r2_instructions
) {
1595 tcg_out_opc_reg(s
, OPC_WSBH
, TCG_TMP0
, 0, MIPS_BE
? lo
: hi
);
1596 tcg_out_opc_reg(s
, OPC_WSBH
, TCG_TMP1
, 0, MIPS_BE
? hi
: lo
);
1597 tcg_out_opc_sa(s
, OPC_ROTR
, TCG_TMP0
, TCG_TMP0
, 16);
1598 tcg_out_opc_sa(s
, OPC_ROTR
, TCG_TMP1
, TCG_TMP1
, 16);
1599 tcg_out_opc_imm(s
, OPC_SW
, TCG_TMP0
, base
, 0);
1600 tcg_out_opc_imm(s
, OPC_SW
, TCG_TMP1
, base
, 4);
1602 tcg_out_bswap32(s
, TCG_TMP3
, MIPS_BE
? lo
: hi
);
1603 tcg_out_opc_imm(s
, OPC_SW
, TCG_TMP3
, base
, 0);
1604 tcg_out_bswap32(s
, TCG_TMP3
, MIPS_BE
? hi
: lo
);
1605 tcg_out_opc_imm(s
, OPC_SW
, TCG_TMP3
, base
, 4);
1609 if (TCG_TARGET_REG_BITS
== 64) {
1610 tcg_out_opc_imm(s
, OPC_SD
, lo
, base
, 0);
1612 tcg_out_opc_imm(s
, OPC_SW
, MIPS_BE
? hi
: lo
, base
, 0);
1613 tcg_out_opc_imm(s
, OPC_SW
, MIPS_BE
? lo
: hi
, base
, 4);
1622 static void tcg_out_qemu_st(TCGContext
*s
, const TCGArg
*args
, bool is_64
)
1624 TCGReg addr_regl
, addr_regh
__attribute__((unused
));
1625 TCGReg data_regl
, data_regh
;
1628 #if defined(CONFIG_SOFTMMU)
1629 tcg_insn_unit
*label_ptr
[2];
1631 TCGReg base
= TCG_REG_A0
;
1633 data_regl
= *args
++;
1634 data_regh
= (TCG_TARGET_REG_BITS
== 32 && is_64
? *args
++ : 0);
1635 addr_regl
= *args
++;
1636 addr_regh
= (TCG_TARGET_REG_BITS
< TARGET_LONG_BITS
? *args
++ : 0);
1638 opc
= get_memop(oi
);
1640 #if defined(CONFIG_SOFTMMU)
1641 tcg_out_tlb_load(s
, base
, addr_regl
, addr_regh
, oi
, label_ptr
, 0);
1642 tcg_out_qemu_st_direct(s
, data_regl
, data_regh
, base
, opc
);
1643 add_qemu_ldst_label(s
, 0, oi
,
1644 (is_64
? TCG_TYPE_I64
: TCG_TYPE_I32
),
1645 data_regl
, data_regh
, addr_regl
, addr_regh
,
1646 s
->code_ptr
, label_ptr
);
1649 if (TCG_TARGET_REG_BITS
> TARGET_LONG_BITS
) {
1650 tcg_out_ext32u(s
, base
, addr_regl
);
1653 if (guest_base
== 0) {
1655 } else if (guest_base
== (int16_t)guest_base
) {
1656 tcg_out_opc_imm(s
, ALIAS_PADDI
, base
, addr_regl
, guest_base
);
1658 tcg_out_opc_reg(s
, ALIAS_PADD
, base
, TCG_GUEST_BASE_REG
, addr_regl
);
1660 tcg_out_qemu_st_direct(s
, data_regl
, data_regh
, base
, opc
);
1664 static void tcg_out_mb(TCGContext
*s
, TCGArg a0
)
1666 static const MIPSInsn sync
[] = {
1667 /* Note that SYNC_MB is a slightly weaker than SYNC 0,
1668 as the former is an ordering barrier and the latter
1669 is a completion barrier. */
1670 [0 ... TCG_MO_ALL
] = OPC_SYNC_MB
,
1671 [TCG_MO_LD_LD
] = OPC_SYNC_RMB
,
1672 [TCG_MO_ST_ST
] = OPC_SYNC_WMB
,
1673 [TCG_MO_LD_ST
] = OPC_SYNC_RELEASE
,
1674 [TCG_MO_LD_ST
| TCG_MO_ST_ST
] = OPC_SYNC_RELEASE
,
1675 [TCG_MO_LD_ST
| TCG_MO_LD_LD
] = OPC_SYNC_ACQUIRE
,
1677 tcg_out32(s
, sync
[a0
& TCG_MO_ALL
]);
1680 static void tcg_out_clz(TCGContext
*s
, MIPSInsn opcv2
, MIPSInsn opcv6
,
1681 int width
, TCGReg a0
, TCGReg a1
, TCGArg a2
)
1683 if (use_mips32r6_instructions
) {
1685 tcg_out_opc_reg(s
, opcv6
, a0
, a1
, 0);
1687 tcg_out_opc_reg(s
, opcv6
, TCG_TMP0
, a1
, 0);
1688 tcg_out_movcond(s
, TCG_COND_EQ
, a0
, a1
, 0, a2
, TCG_TMP0
);
1692 tcg_out_opc_reg(s
, opcv2
, a0
, a1
, a1
);
1693 } else if (a0
== a2
) {
1694 tcg_out_opc_reg(s
, opcv2
, TCG_TMP0
, a1
, a1
);
1695 tcg_out_opc_reg(s
, OPC_MOVN
, a0
, TCG_TMP0
, a1
);
1696 } else if (a0
!= a1
) {
1697 tcg_out_opc_reg(s
, opcv2
, a0
, a1
, a1
);
1698 tcg_out_opc_reg(s
, OPC_MOVZ
, a0
, a2
, a1
);
1700 tcg_out_opc_reg(s
, opcv2
, TCG_TMP0
, a1
, a1
);
1701 tcg_out_opc_reg(s
, OPC_MOVZ
, TCG_TMP0
, a2
, a1
);
1702 tcg_out_mov(s
, TCG_TYPE_REG
, a0
, TCG_TMP0
);
1707 static inline void tcg_out_op(TCGContext
*s
, TCGOpcode opc
,
1708 const TCGArg
*args
, const int *const_args
)
1720 case INDEX_op_exit_tb
:
1722 TCGReg b0
= TCG_REG_ZERO
;
1726 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_V0
, a0
& ~0xffff);
1729 if (!tcg_out_opc_jmp(s
, OPC_J
, tb_ret_addr
)) {
1730 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_TMP0
,
1731 (uintptr_t)tb_ret_addr
);
1732 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_TMP0
, 0);
1734 tcg_out_opc_imm(s
, OPC_ORI
, TCG_REG_V0
, b0
, a0
& 0xffff);
1737 case INDEX_op_goto_tb
:
1738 if (s
->tb_jmp_insn_offset
) {
1739 /* direct jump method */
1740 s
->tb_jmp_insn_offset
[a0
] = tcg_current_code_size(s
);
1741 /* Avoid clobbering the address during retranslation. */
1742 tcg_out32(s
, OPC_J
| (*(uint32_t *)s
->code_ptr
& 0x3ffffff));
1744 /* indirect jump method */
1745 tcg_out_ld(s
, TCG_TYPE_PTR
, TCG_TMP0
, TCG_REG_ZERO
,
1746 (uintptr_t)(s
->tb_jmp_target_addr
+ a0
));
1747 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_TMP0
, 0);
1750 s
->tb_jmp_reset_offset
[a0
] = tcg_current_code_size(s
);
1752 case INDEX_op_goto_ptr
:
1753 /* jmp to the given host address (could be epilogue) */
1754 tcg_out_opc_reg(s
, OPC_JR
, 0, a0
, 0);
1758 tcg_out_brcond(s
, TCG_COND_EQ
, TCG_REG_ZERO
, TCG_REG_ZERO
,
1762 case INDEX_op_ld8u_i32
:
1763 case INDEX_op_ld8u_i64
:
1766 case INDEX_op_ld8s_i32
:
1767 case INDEX_op_ld8s_i64
:
1770 case INDEX_op_ld16u_i32
:
1771 case INDEX_op_ld16u_i64
:
1774 case INDEX_op_ld16s_i32
:
1775 case INDEX_op_ld16s_i64
:
1778 case INDEX_op_ld_i32
:
1779 case INDEX_op_ld32s_i64
:
1782 case INDEX_op_ld32u_i64
:
1785 case INDEX_op_ld_i64
:
1788 case INDEX_op_st8_i32
:
1789 case INDEX_op_st8_i64
:
1792 case INDEX_op_st16_i32
:
1793 case INDEX_op_st16_i64
:
1796 case INDEX_op_st_i32
:
1797 case INDEX_op_st32_i64
:
1800 case INDEX_op_st_i64
:
1803 tcg_out_ldst(s
, i1
, a0
, a1
, a2
);
1806 case INDEX_op_add_i32
:
1807 i1
= OPC_ADDU
, i2
= OPC_ADDIU
;
1809 case INDEX_op_add_i64
:
1810 i1
= OPC_DADDU
, i2
= OPC_DADDIU
;
1812 case INDEX_op_or_i32
:
1813 case INDEX_op_or_i64
:
1814 i1
= OPC_OR
, i2
= OPC_ORI
;
1816 case INDEX_op_xor_i32
:
1817 case INDEX_op_xor_i64
:
1818 i1
= OPC_XOR
, i2
= OPC_XORI
;
1821 tcg_out_opc_imm(s
, i2
, a0
, a1
, a2
);
1825 tcg_out_opc_reg(s
, i1
, a0
, a1
, a2
);
1828 case INDEX_op_sub_i32
:
1829 i1
= OPC_SUBU
, i2
= OPC_ADDIU
;
1831 case INDEX_op_sub_i64
:
1832 i1
= OPC_DSUBU
, i2
= OPC_DADDIU
;
1835 tcg_out_opc_imm(s
, i2
, a0
, a1
, -a2
);
1839 case INDEX_op_and_i32
:
1840 if (c2
&& a2
!= (uint16_t)a2
) {
1841 int msb
= ctz32(~a2
) - 1;
1842 tcg_debug_assert(use_mips32r2_instructions
);
1843 tcg_debug_assert(is_p2m1(a2
));
1844 tcg_out_opc_bf(s
, OPC_EXT
, a0
, a1
, msb
, 0);
1847 i1
= OPC_AND
, i2
= OPC_ANDI
;
1849 case INDEX_op_and_i64
:
1850 if (c2
&& a2
!= (uint16_t)a2
) {
1851 int msb
= ctz64(~a2
) - 1;
1852 tcg_debug_assert(use_mips32r2_instructions
);
1853 tcg_debug_assert(is_p2m1(a2
));
1854 tcg_out_opc_bf64(s
, OPC_DEXT
, OPC_DEXTM
, OPC_DEXTU
, a0
, a1
, msb
, 0);
1857 i1
= OPC_AND
, i2
= OPC_ANDI
;
1859 case INDEX_op_nor_i32
:
1860 case INDEX_op_nor_i64
:
1864 case INDEX_op_mul_i32
:
1865 if (use_mips32_instructions
) {
1866 tcg_out_opc_reg(s
, OPC_MUL
, a0
, a1
, a2
);
1869 i1
= OPC_MULT
, i2
= OPC_MFLO
;
1871 case INDEX_op_mulsh_i32
:
1872 if (use_mips32r6_instructions
) {
1873 tcg_out_opc_reg(s
, OPC_MUH
, a0
, a1
, a2
);
1876 i1
= OPC_MULT
, i2
= OPC_MFHI
;
1878 case INDEX_op_muluh_i32
:
1879 if (use_mips32r6_instructions
) {
1880 tcg_out_opc_reg(s
, OPC_MUHU
, a0
, a1
, a2
);
1883 i1
= OPC_MULTU
, i2
= OPC_MFHI
;
1885 case INDEX_op_div_i32
:
1886 if (use_mips32r6_instructions
) {
1887 tcg_out_opc_reg(s
, OPC_DIV_R6
, a0
, a1
, a2
);
1890 i1
= OPC_DIV
, i2
= OPC_MFLO
;
1892 case INDEX_op_divu_i32
:
1893 if (use_mips32r6_instructions
) {
1894 tcg_out_opc_reg(s
, OPC_DIVU_R6
, a0
, a1
, a2
);
1897 i1
= OPC_DIVU
, i2
= OPC_MFLO
;
1899 case INDEX_op_rem_i32
:
1900 if (use_mips32r6_instructions
) {
1901 tcg_out_opc_reg(s
, OPC_MOD
, a0
, a1
, a2
);
1904 i1
= OPC_DIV
, i2
= OPC_MFHI
;
1906 case INDEX_op_remu_i32
:
1907 if (use_mips32r6_instructions
) {
1908 tcg_out_opc_reg(s
, OPC_MODU
, a0
, a1
, a2
);
1911 i1
= OPC_DIVU
, i2
= OPC_MFHI
;
1913 case INDEX_op_mul_i64
:
1914 if (use_mips32r6_instructions
) {
1915 tcg_out_opc_reg(s
, OPC_DMUL
, a0
, a1
, a2
);
1918 i1
= OPC_DMULT
, i2
= OPC_MFLO
;
1920 case INDEX_op_mulsh_i64
:
1921 if (use_mips32r6_instructions
) {
1922 tcg_out_opc_reg(s
, OPC_DMUH
, a0
, a1
, a2
);
1925 i1
= OPC_DMULT
, i2
= OPC_MFHI
;
1927 case INDEX_op_muluh_i64
:
1928 if (use_mips32r6_instructions
) {
1929 tcg_out_opc_reg(s
, OPC_DMUHU
, a0
, a1
, a2
);
1932 i1
= OPC_DMULTU
, i2
= OPC_MFHI
;
1934 case INDEX_op_div_i64
:
1935 if (use_mips32r6_instructions
) {
1936 tcg_out_opc_reg(s
, OPC_DDIV_R6
, a0
, a1
, a2
);
1939 i1
= OPC_DDIV
, i2
= OPC_MFLO
;
1941 case INDEX_op_divu_i64
:
1942 if (use_mips32r6_instructions
) {
1943 tcg_out_opc_reg(s
, OPC_DDIVU_R6
, a0
, a1
, a2
);
1946 i1
= OPC_DDIVU
, i2
= OPC_MFLO
;
1948 case INDEX_op_rem_i64
:
1949 if (use_mips32r6_instructions
) {
1950 tcg_out_opc_reg(s
, OPC_DMOD
, a0
, a1
, a2
);
1953 i1
= OPC_DDIV
, i2
= OPC_MFHI
;
1955 case INDEX_op_remu_i64
:
1956 if (use_mips32r6_instructions
) {
1957 tcg_out_opc_reg(s
, OPC_DMODU
, a0
, a1
, a2
);
1960 i1
= OPC_DDIVU
, i2
= OPC_MFHI
;
1962 tcg_out_opc_reg(s
, i1
, 0, a1
, a2
);
1963 tcg_out_opc_reg(s
, i2
, a0
, 0, 0);
1966 case INDEX_op_muls2_i32
:
1969 case INDEX_op_mulu2_i32
:
1972 case INDEX_op_muls2_i64
:
1975 case INDEX_op_mulu2_i64
:
1978 tcg_out_opc_reg(s
, i1
, 0, a2
, args
[3]);
1979 tcg_out_opc_reg(s
, OPC_MFLO
, a0
, 0, 0);
1980 tcg_out_opc_reg(s
, OPC_MFHI
, a1
, 0, 0);
1983 case INDEX_op_not_i32
:
1984 case INDEX_op_not_i64
:
1987 case INDEX_op_bswap16_i32
:
1988 case INDEX_op_bswap16_i64
:
1991 case INDEX_op_ext8s_i32
:
1992 case INDEX_op_ext8s_i64
:
1995 case INDEX_op_ext16s_i32
:
1996 case INDEX_op_ext16s_i64
:
1999 tcg_out_opc_reg(s
, i1
, a0
, TCG_REG_ZERO
, a1
);
2002 case INDEX_op_bswap32_i32
:
2003 tcg_out_bswap32(s
, a0
, a1
);
2005 case INDEX_op_bswap32_i64
:
2006 tcg_out_bswap32u(s
, a0
, a1
);
2008 case INDEX_op_bswap64_i64
:
2009 tcg_out_bswap64(s
, a0
, a1
);
2011 case INDEX_op_extrh_i64_i32
:
2012 tcg_out_dsra(s
, a0
, a1
, 32);
2014 case INDEX_op_ext32s_i64
:
2015 case INDEX_op_ext_i32_i64
:
2016 case INDEX_op_extrl_i64_i32
:
2017 tcg_out_opc_sa(s
, OPC_SLL
, a0
, a1
, 0);
2019 case INDEX_op_ext32u_i64
:
2020 case INDEX_op_extu_i32_i64
:
2021 tcg_out_ext32u(s
, a0
, a1
);
2024 case INDEX_op_sar_i32
:
2025 i1
= OPC_SRAV
, i2
= OPC_SRA
;
2027 case INDEX_op_shl_i32
:
2028 i1
= OPC_SLLV
, i2
= OPC_SLL
;
2030 case INDEX_op_shr_i32
:
2031 i1
= OPC_SRLV
, i2
= OPC_SRL
;
2033 case INDEX_op_rotr_i32
:
2034 i1
= OPC_ROTRV
, i2
= OPC_ROTR
;
2037 tcg_out_opc_sa(s
, i2
, a0
, a1
, a2
);
2041 tcg_out_opc_reg(s
, i1
, a0
, a2
, a1
);
2043 case INDEX_op_rotl_i32
:
2045 tcg_out_opc_sa(s
, OPC_ROTR
, a0
, a1
, 32 - a2
);
2047 tcg_out_opc_reg(s
, OPC_SUBU
, TCG_TMP0
, TCG_REG_ZERO
, a2
);
2048 tcg_out_opc_reg(s
, OPC_ROTRV
, a0
, TCG_TMP0
, a1
);
2051 case INDEX_op_sar_i64
:
2053 tcg_out_dsra(s
, a0
, a1
, a2
);
2058 case INDEX_op_shl_i64
:
2060 tcg_out_dsll(s
, a0
, a1
, a2
);
2065 case INDEX_op_shr_i64
:
2067 tcg_out_dsrl(s
, a0
, a1
, a2
);
2072 case INDEX_op_rotr_i64
:
2074 tcg_out_opc_sa64(s
, OPC_DROTR
, OPC_DROTR32
, a0
, a1
, a2
);
2079 case INDEX_op_rotl_i64
:
2081 tcg_out_opc_sa64(s
, OPC_DROTR
, OPC_DROTR32
, a0
, a1
, 64 - a2
);
2083 tcg_out_opc_reg(s
, OPC_DSUBU
, TCG_TMP0
, TCG_REG_ZERO
, a2
);
2084 tcg_out_opc_reg(s
, OPC_DROTRV
, a0
, TCG_TMP0
, a1
);
2088 case INDEX_op_clz_i32
:
2089 tcg_out_clz(s
, OPC_CLZ
, OPC_CLZ_R6
, 32, a0
, a1
, a2
);
2091 case INDEX_op_clz_i64
:
2092 tcg_out_clz(s
, OPC_DCLZ
, OPC_DCLZ_R6
, 64, a0
, a1
, a2
);
2095 case INDEX_op_deposit_i32
:
2096 tcg_out_opc_bf(s
, OPC_INS
, a0
, a2
, args
[3] + args
[4] - 1, args
[3]);
2098 case INDEX_op_deposit_i64
:
2099 tcg_out_opc_bf64(s
, OPC_DINS
, OPC_DINSM
, OPC_DINSU
, a0
, a2
,
2100 args
[3] + args
[4] - 1, args
[3]);
2102 case INDEX_op_extract_i32
:
2103 tcg_out_opc_bf(s
, OPC_EXT
, a0
, a1
, args
[3] - 1, a2
);
2105 case INDEX_op_extract_i64
:
2106 tcg_out_opc_bf64(s
, OPC_DEXT
, OPC_DEXTM
, OPC_DEXTU
, a0
, a1
,
2110 case INDEX_op_brcond_i32
:
2111 case INDEX_op_brcond_i64
:
2112 tcg_out_brcond(s
, a2
, a0
, a1
, arg_label(args
[3]));
2114 case INDEX_op_brcond2_i32
:
2115 tcg_out_brcond2(s
, args
[4], a0
, a1
, a2
, args
[3], arg_label(args
[5]));
2118 case INDEX_op_movcond_i32
:
2119 case INDEX_op_movcond_i64
:
2120 tcg_out_movcond(s
, args
[5], a0
, a1
, a2
, args
[3], args
[4]);
2123 case INDEX_op_setcond_i32
:
2124 case INDEX_op_setcond_i64
:
2125 tcg_out_setcond(s
, args
[3], a0
, a1
, a2
);
2127 case INDEX_op_setcond2_i32
:
2128 tcg_out_setcond2(s
, args
[5], a0
, a1
, a2
, args
[3], args
[4]);
2131 case INDEX_op_qemu_ld_i32
:
2132 tcg_out_qemu_ld(s
, args
, false);
2134 case INDEX_op_qemu_ld_i64
:
2135 tcg_out_qemu_ld(s
, args
, true);
2137 case INDEX_op_qemu_st_i32
:
2138 tcg_out_qemu_st(s
, args
, false);
2140 case INDEX_op_qemu_st_i64
:
2141 tcg_out_qemu_st(s
, args
, true);
2144 case INDEX_op_add2_i32
:
2145 tcg_out_addsub2(s
, a0
, a1
, a2
, args
[3], args
[4], args
[5],
2146 const_args
[4], const_args
[5], false);
2148 case INDEX_op_sub2_i32
:
2149 tcg_out_addsub2(s
, a0
, a1
, a2
, args
[3], args
[4], args
[5],
2150 const_args
[4], const_args
[5], true);
2156 case INDEX_op_mov_i32
: /* Always emitted via tcg_out_mov. */
2157 case INDEX_op_mov_i64
:
2158 case INDEX_op_movi_i32
: /* Always emitted via tcg_out_movi. */
2159 case INDEX_op_movi_i64
:
2160 case INDEX_op_call
: /* Always emitted via tcg_out_call. */
2166 static const TCGTargetOpDef
*tcg_target_op_def(TCGOpcode op
)
2168 static const TCGTargetOpDef r
= { .args_ct_str
= { "r" } };
2169 static const TCGTargetOpDef r_r
= { .args_ct_str
= { "r", "r" } };
2170 static const TCGTargetOpDef r_L
= { .args_ct_str
= { "r", "L" } };
2171 static const TCGTargetOpDef rZ_r
= { .args_ct_str
= { "rZ", "r" } };
2172 static const TCGTargetOpDef SZ_S
= { .args_ct_str
= { "SZ", "S" } };
2173 static const TCGTargetOpDef rZ_rZ
= { .args_ct_str
= { "rZ", "rZ" } };
2174 static const TCGTargetOpDef r_r_L
= { .args_ct_str
= { "r", "r", "L" } };
2175 static const TCGTargetOpDef r_L_L
= { .args_ct_str
= { "r", "L", "L" } };
2176 static const TCGTargetOpDef r_r_ri
= { .args_ct_str
= { "r", "r", "ri" } };
2177 static const TCGTargetOpDef r_r_rI
= { .args_ct_str
= { "r", "r", "rI" } };
2178 static const TCGTargetOpDef r_r_rJ
= { .args_ct_str
= { "r", "r", "rJ" } };
2179 static const TCGTargetOpDef SZ_S_S
= { .args_ct_str
= { "SZ", "S", "S" } };
2180 static const TCGTargetOpDef SZ_SZ_S
2181 = { .args_ct_str
= { "SZ", "SZ", "S" } };
2182 static const TCGTargetOpDef SZ_SZ_S_S
2183 = { .args_ct_str
= { "SZ", "SZ", "S", "S" } };
2184 static const TCGTargetOpDef r_rZ_rN
2185 = { .args_ct_str
= { "r", "rZ", "rN" } };
2186 static const TCGTargetOpDef r_rZ_rZ
2187 = { .args_ct_str
= { "r", "rZ", "rZ" } };
2188 static const TCGTargetOpDef r_r_rIK
2189 = { .args_ct_str
= { "r", "r", "rIK" } };
2190 static const TCGTargetOpDef r_r_rWZ
2191 = { .args_ct_str
= { "r", "r", "rWZ" } };
2192 static const TCGTargetOpDef r_r_r_r
2193 = { .args_ct_str
= { "r", "r", "r", "r" } };
2194 static const TCGTargetOpDef r_r_L_L
2195 = { .args_ct_str
= { "r", "r", "L", "L" } };
2196 static const TCGTargetOpDef dep
2197 = { .args_ct_str
= { "r", "0", "rZ" } };
2198 static const TCGTargetOpDef movc
2199 = { .args_ct_str
= { "r", "rZ", "rZ", "rZ", "0" } };
2200 static const TCGTargetOpDef movc_r6
2201 = { .args_ct_str
= { "r", "rZ", "rZ", "rZ", "rZ" } };
2202 static const TCGTargetOpDef add2
2203 = { .args_ct_str
= { "r", "r", "rZ", "rZ", "rN", "rN" } };
2204 static const TCGTargetOpDef br2
2205 = { .args_ct_str
= { "rZ", "rZ", "rZ", "rZ" } };
2206 static const TCGTargetOpDef setc2
2207 = { .args_ct_str
= { "r", "rZ", "rZ", "rZ", "rZ" } };
2210 case INDEX_op_goto_ptr
:
2213 case INDEX_op_ld8u_i32
:
2214 case INDEX_op_ld8s_i32
:
2215 case INDEX_op_ld16u_i32
:
2216 case INDEX_op_ld16s_i32
:
2217 case INDEX_op_ld_i32
:
2218 case INDEX_op_not_i32
:
2219 case INDEX_op_bswap16_i32
:
2220 case INDEX_op_bswap32_i32
:
2221 case INDEX_op_ext8s_i32
:
2222 case INDEX_op_ext16s_i32
:
2223 case INDEX_op_extract_i32
:
2224 case INDEX_op_ld8u_i64
:
2225 case INDEX_op_ld8s_i64
:
2226 case INDEX_op_ld16u_i64
:
2227 case INDEX_op_ld16s_i64
:
2228 case INDEX_op_ld32s_i64
:
2229 case INDEX_op_ld32u_i64
:
2230 case INDEX_op_ld_i64
:
2231 case INDEX_op_not_i64
:
2232 case INDEX_op_bswap16_i64
:
2233 case INDEX_op_bswap32_i64
:
2234 case INDEX_op_bswap64_i64
:
2235 case INDEX_op_ext8s_i64
:
2236 case INDEX_op_ext16s_i64
:
2237 case INDEX_op_ext32s_i64
:
2238 case INDEX_op_ext32u_i64
:
2239 case INDEX_op_ext_i32_i64
:
2240 case INDEX_op_extu_i32_i64
:
2241 case INDEX_op_extrl_i64_i32
:
2242 case INDEX_op_extrh_i64_i32
:
2243 case INDEX_op_extract_i64
:
2246 case INDEX_op_st8_i32
:
2247 case INDEX_op_st16_i32
:
2248 case INDEX_op_st_i32
:
2249 case INDEX_op_st8_i64
:
2250 case INDEX_op_st16_i64
:
2251 case INDEX_op_st32_i64
:
2252 case INDEX_op_st_i64
:
2255 case INDEX_op_add_i32
:
2256 case INDEX_op_add_i64
:
2258 case INDEX_op_sub_i32
:
2259 case INDEX_op_sub_i64
:
2261 case INDEX_op_mul_i32
:
2262 case INDEX_op_mulsh_i32
:
2263 case INDEX_op_muluh_i32
:
2264 case INDEX_op_div_i32
:
2265 case INDEX_op_divu_i32
:
2266 case INDEX_op_rem_i32
:
2267 case INDEX_op_remu_i32
:
2268 case INDEX_op_nor_i32
:
2269 case INDEX_op_setcond_i32
:
2270 case INDEX_op_mul_i64
:
2271 case INDEX_op_mulsh_i64
:
2272 case INDEX_op_muluh_i64
:
2273 case INDEX_op_div_i64
:
2274 case INDEX_op_divu_i64
:
2275 case INDEX_op_rem_i64
:
2276 case INDEX_op_remu_i64
:
2277 case INDEX_op_nor_i64
:
2278 case INDEX_op_setcond_i64
:
2280 case INDEX_op_muls2_i32
:
2281 case INDEX_op_mulu2_i32
:
2282 case INDEX_op_muls2_i64
:
2283 case INDEX_op_mulu2_i64
:
2285 case INDEX_op_and_i32
:
2286 case INDEX_op_and_i64
:
2288 case INDEX_op_or_i32
:
2289 case INDEX_op_xor_i32
:
2290 case INDEX_op_or_i64
:
2291 case INDEX_op_xor_i64
:
2293 case INDEX_op_shl_i32
:
2294 case INDEX_op_shr_i32
:
2295 case INDEX_op_sar_i32
:
2296 case INDEX_op_rotr_i32
:
2297 case INDEX_op_rotl_i32
:
2298 case INDEX_op_shl_i64
:
2299 case INDEX_op_shr_i64
:
2300 case INDEX_op_sar_i64
:
2301 case INDEX_op_rotr_i64
:
2302 case INDEX_op_rotl_i64
:
2304 case INDEX_op_clz_i32
:
2305 case INDEX_op_clz_i64
:
2308 case INDEX_op_deposit_i32
:
2309 case INDEX_op_deposit_i64
:
2311 case INDEX_op_brcond_i32
:
2312 case INDEX_op_brcond_i64
:
2314 case INDEX_op_movcond_i32
:
2315 case INDEX_op_movcond_i64
:
2316 return use_mips32r6_instructions
? &movc_r6
: &movc
;
2318 case INDEX_op_add2_i32
:
2319 case INDEX_op_sub2_i32
:
2321 case INDEX_op_setcond2_i32
:
2323 case INDEX_op_brcond2_i32
:
2326 case INDEX_op_qemu_ld_i32
:
2327 return (TCG_TARGET_REG_BITS
== 64 || TARGET_LONG_BITS
== 32
2329 case INDEX_op_qemu_st_i32
:
2330 return (TCG_TARGET_REG_BITS
== 64 || TARGET_LONG_BITS
== 32
2332 case INDEX_op_qemu_ld_i64
:
2333 return (TCG_TARGET_REG_BITS
== 64 ? &r_L
2334 : TARGET_LONG_BITS
== 32 ? &r_r_L
: &r_r_L_L
);
2335 case INDEX_op_qemu_st_i64
:
2336 return (TCG_TARGET_REG_BITS
== 64 ? &SZ_S
2337 : TARGET_LONG_BITS
== 32 ? &SZ_SZ_S
: &SZ_SZ_S_S
);
2344 static const int tcg_target_callee_save_regs
[] = {
2345 TCG_REG_S0
, /* used for the global env (TCG_AREG0) */
2354 TCG_REG_RA
, /* should be last for ABI compliance */
2357 /* The Linux kernel doesn't provide any information about the available
2358 instruction set. Probe it using a signal handler. */
2361 #ifndef use_movnz_instructions
2362 bool use_movnz_instructions
= false;
2365 #ifndef use_mips32_instructions
2366 bool use_mips32_instructions
= false;
2369 #ifndef use_mips32r2_instructions
2370 bool use_mips32r2_instructions
= false;
2373 static volatile sig_atomic_t got_sigill
;
2375 static void sigill_handler(int signo
, siginfo_t
*si
, void *data
)
2377 /* Skip the faulty instruction */
2378 ucontext_t
*uc
= (ucontext_t
*)data
;
2379 uc
->uc_mcontext
.pc
+= 4;
2384 static void tcg_target_detect_isa(void)
2386 struct sigaction sa_old
, sa_new
;
2388 memset(&sa_new
, 0, sizeof(sa_new
));
2389 sa_new
.sa_flags
= SA_SIGINFO
;
2390 sa_new
.sa_sigaction
= sigill_handler
;
2391 sigaction(SIGILL
, &sa_new
, &sa_old
);
2393 /* Probe for movn/movz, necessary to implement movcond. */
2394 #ifndef use_movnz_instructions
2396 asm volatile(".set push\n"
2398 "movn $zero, $zero, $zero\n"
2399 "movz $zero, $zero, $zero\n"
2402 use_movnz_instructions
= !got_sigill
;
2405 /* Probe for MIPS32 instructions. As no subsetting is allowed
2406 by the specification, it is only necessary to probe for one
2407 of the instructions. */
2408 #ifndef use_mips32_instructions
2410 asm volatile(".set push\n"
2412 "mul $zero, $zero\n"
2415 use_mips32_instructions
= !got_sigill
;
2418 /* Probe for MIPS32r2 instructions if MIPS32 instructions are
2419 available. As no subsetting is allowed by the specification,
2420 it is only necessary to probe for one of the instructions. */
2421 #ifndef use_mips32r2_instructions
2422 if (use_mips32_instructions
) {
2424 asm volatile(".set push\n"
2426 "seb $zero, $zero\n"
2429 use_mips32r2_instructions
= !got_sigill
;
2433 sigaction(SIGILL
, &sa_old
, NULL
);
2436 static tcg_insn_unit
*align_code_ptr(TCGContext
*s
)
2438 uintptr_t p
= (uintptr_t)s
->code_ptr
;
2441 s
->code_ptr
= (void *)p
;
2446 /* Stack frame parameters. */
2447 #define REG_SIZE (TCG_TARGET_REG_BITS / 8)
2448 #define SAVE_SIZE ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE)
2449 #define TEMP_SIZE (CPU_TEMP_BUF_NLONGS * (int)sizeof(long))
2451 #define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \
2452 + TCG_TARGET_STACK_ALIGN - 1) \
2453 & -TCG_TARGET_STACK_ALIGN)
2454 #define SAVE_OFS (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE)
2456 /* We're expecting to be able to use an immediate for frame allocation. */
2457 QEMU_BUILD_BUG_ON(FRAME_SIZE
> 0x7fff);
2459 /* Generate global QEMU prologue and epilogue code */
2460 static void tcg_target_qemu_prologue(TCGContext
*s
)
2464 tcg_set_frame(s
, TCG_REG_SP
, TCG_STATIC_CALL_ARGS_SIZE
, TEMP_SIZE
);
2467 tcg_out_opc_imm(s
, ALIAS_PADDI
, TCG_REG_SP
, TCG_REG_SP
, -FRAME_SIZE
);
2468 for (i
= 0; i
< ARRAY_SIZE(tcg_target_callee_save_regs
); i
++) {
2469 tcg_out_st(s
, TCG_TYPE_REG
, tcg_target_callee_save_regs
[i
],
2470 TCG_REG_SP
, SAVE_OFS
+ i
* REG_SIZE
);
2473 #ifndef CONFIG_SOFTMMU
2475 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_GUEST_BASE_REG
, guest_base
);
2476 tcg_regset_set_reg(s
->reserved_regs
, TCG_GUEST_BASE_REG
);
2480 /* Call generated code */
2481 tcg_out_opc_reg(s
, OPC_JR
, 0, tcg_target_call_iarg_regs
[1], 0);
2483 tcg_out_mov(s
, TCG_TYPE_PTR
, TCG_AREG0
, tcg_target_call_iarg_regs
[0]);
2486 * Return path for goto_ptr. Set return value to 0, a-la exit_tb,
2487 * and fall through to the rest of the epilogue.
2489 s
->code_gen_epilogue
= s
->code_ptr
;
2490 tcg_out_mov(s
, TCG_TYPE_REG
, TCG_REG_V0
, TCG_REG_ZERO
);
2493 tb_ret_addr
= s
->code_ptr
;
2494 for (i
= 0; i
< ARRAY_SIZE(tcg_target_callee_save_regs
); i
++) {
2495 tcg_out_ld(s
, TCG_TYPE_REG
, tcg_target_callee_save_regs
[i
],
2496 TCG_REG_SP
, SAVE_OFS
+ i
* REG_SIZE
);
2499 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_RA
, 0);
2501 tcg_out_opc_imm(s
, ALIAS_PADDI
, TCG_REG_SP
, TCG_REG_SP
, FRAME_SIZE
);
2503 if (use_mips32r2_instructions
) {
2507 /* Bswap subroutines: Input in TCG_TMP0, output in TCG_TMP3;
2508 clobbers TCG_TMP1, TCG_TMP2. */
2511 * bswap32 -- 32-bit swap (signed result for mips64). a0 = abcd.
2513 bswap32_addr
= align_code_ptr(s
);
2514 /* t3 = (ssss)d000 */
2515 tcg_out_opc_sa(s
, OPC_SLL
, TCG_TMP3
, TCG_TMP0
, 24);
2517 tcg_out_opc_sa(s
, OPC_SRL
, TCG_TMP1
, TCG_TMP0
, 24);
2519 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_TMP2
, TCG_TMP0
, 0xff00);
2521 tcg_out_opc_reg(s
, OPC_OR
, TCG_TMP3
, TCG_TMP3
, TCG_TMP1
);
2523 tcg_out_opc_sa(s
, OPC_SRL
, TCG_TMP1
, TCG_TMP0
, 8);
2525 tcg_out_opc_sa(s
, OPC_SLL
, TCG_TMP2
, TCG_TMP2
, 8);
2527 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_TMP1
, TCG_TMP1
, 0xff00);
2529 tcg_out_opc_reg(s
, OPC_OR
, TCG_TMP3
, TCG_TMP3
, TCG_TMP2
);
2530 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_RA
, 0);
2531 /* t3 = dcba -- delay slot */
2532 tcg_out_opc_reg(s
, OPC_OR
, TCG_TMP3
, TCG_TMP3
, TCG_TMP1
);
2534 if (TCG_TARGET_REG_BITS
== 32) {
2539 * bswap32u -- unsigned 32-bit swap. a0 = ....abcd.
2541 bswap32u_addr
= align_code_ptr(s
);
2542 /* t1 = (0000)000d */
2543 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_TMP1
, TCG_TMP0
, 0xff);
2545 tcg_out_opc_sa(s
, OPC_SRL
, TCG_TMP3
, TCG_TMP0
, 24);
2546 /* t1 = (0000)d000 */
2547 tcg_out_dsll(s
, TCG_TMP1
, TCG_TMP1
, 24);
2549 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_TMP2
, TCG_TMP0
, 0xff00);
2551 tcg_out_opc_reg(s
, OPC_OR
, TCG_TMP3
, TCG_TMP3
, TCG_TMP1
);
2553 tcg_out_opc_sa(s
, OPC_SRL
, TCG_TMP1
, TCG_TMP0
, 8);
2555 tcg_out_opc_sa(s
, OPC_SLL
, TCG_TMP2
, TCG_TMP2
, 8);
2557 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_TMP1
, TCG_TMP1
, 0xff00);
2559 tcg_out_opc_reg(s
, OPC_OR
, TCG_TMP3
, TCG_TMP3
, TCG_TMP2
);
2560 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_RA
, 0);
2561 /* t3 = dcba -- delay slot */
2562 tcg_out_opc_reg(s
, OPC_OR
, TCG_TMP3
, TCG_TMP3
, TCG_TMP1
);
2565 * bswap64 -- 64-bit swap. a0 = abcdefgh
2567 bswap64_addr
= align_code_ptr(s
);
2569 tcg_out_dsll(s
, TCG_TMP3
, TCG_TMP0
, 56);
2571 tcg_out_dsrl(s
, TCG_TMP1
, TCG_TMP0
, 56);
2574 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_TMP2
, TCG_TMP0
, 0xff00);
2576 tcg_out_opc_reg(s
, OPC_OR
, TCG_TMP3
, TCG_TMP3
, TCG_TMP1
);
2578 tcg_out_dsrl(s
, TCG_TMP1
, TCG_TMP0
, 40);
2580 tcg_out_dsll(s
, TCG_TMP2
, TCG_TMP2
, 40);
2582 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_TMP1
, TCG_TMP1
, 0xff00);
2585 tcg_out_opc_reg(s
, OPC_OR
, TCG_TMP3
, TCG_TMP3
, TCG_TMP2
);
2587 tcg_out_dsrl(s
, TCG_TMP2
, TCG_TMP0
, 32);
2589 tcg_out_opc_reg(s
, OPC_OR
, TCG_TMP3
, TCG_TMP3
, TCG_TMP1
);
2592 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_TMP1
, TCG_TMP2
, 0xff00);
2594 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_TMP2
, TCG_TMP2
, 0x00ff);
2596 tcg_out_dsll(s
, TCG_TMP1
, TCG_TMP1
, 8);
2598 tcg_out_dsll(s
, TCG_TMP2
, TCG_TMP2
, 24);
2601 tcg_out_opc_reg(s
, OPC_OR
, TCG_TMP3
, TCG_TMP3
, TCG_TMP1
);
2603 tcg_out_dsrl(s
, TCG_TMP1
, TCG_TMP0
, 16);
2605 tcg_out_opc_reg(s
, OPC_OR
, TCG_TMP3
, TCG_TMP3
, TCG_TMP2
);
2608 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_TMP2
, TCG_TMP1
, 0x00ff);
2610 tcg_out_opc_imm(s
, OPC_ANDI
, TCG_TMP1
, TCG_TMP1
, 0xff00);
2612 tcg_out_dsll(s
, TCG_TMP2
, TCG_TMP2
, 40);
2614 tcg_out_dsll(s
, TCG_TMP1
, TCG_TMP1
, 24);
2617 tcg_out_opc_reg(s
, OPC_OR
, TCG_TMP3
, TCG_TMP3
, TCG_TMP2
);
2618 tcg_out_opc_reg(s
, OPC_JR
, 0, TCG_REG_RA
, 0);
2619 /* t3 = hgfedcba -- delay slot */
2620 tcg_out_opc_reg(s
, OPC_OR
, TCG_TMP3
, TCG_TMP3
, TCG_TMP1
);
2623 static void tcg_target_init(TCGContext
*s
)
2625 tcg_target_detect_isa();
2626 tcg_target_available_regs
[TCG_TYPE_I32
] = 0xffffffff;
2627 if (TCG_TARGET_REG_BITS
== 64) {
2628 tcg_target_available_regs
[TCG_TYPE_I64
] = 0xffffffff;
2631 tcg_target_call_clobber_regs
= 0;
2632 tcg_regset_set_reg(tcg_target_call_clobber_regs
, TCG_REG_V0
);
2633 tcg_regset_set_reg(tcg_target_call_clobber_regs
, TCG_REG_V1
);
2634 tcg_regset_set_reg(tcg_target_call_clobber_regs
, TCG_REG_A0
);
2635 tcg_regset_set_reg(tcg_target_call_clobber_regs
, TCG_REG_A1
);
2636 tcg_regset_set_reg(tcg_target_call_clobber_regs
, TCG_REG_A2
);
2637 tcg_regset_set_reg(tcg_target_call_clobber_regs
, TCG_REG_A3
);
2638 tcg_regset_set_reg(tcg_target_call_clobber_regs
, TCG_REG_T0
);
2639 tcg_regset_set_reg(tcg_target_call_clobber_regs
, TCG_REG_T1
);
2640 tcg_regset_set_reg(tcg_target_call_clobber_regs
, TCG_REG_T2
);
2641 tcg_regset_set_reg(tcg_target_call_clobber_regs
, TCG_REG_T3
);
2642 tcg_regset_set_reg(tcg_target_call_clobber_regs
, TCG_REG_T4
);
2643 tcg_regset_set_reg(tcg_target_call_clobber_regs
, TCG_REG_T5
);
2644 tcg_regset_set_reg(tcg_target_call_clobber_regs
, TCG_REG_T6
);
2645 tcg_regset_set_reg(tcg_target_call_clobber_regs
, TCG_REG_T7
);
2646 tcg_regset_set_reg(tcg_target_call_clobber_regs
, TCG_REG_T8
);
2647 tcg_regset_set_reg(tcg_target_call_clobber_regs
, TCG_REG_T9
);
2649 s
->reserved_regs
= 0;
2650 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_ZERO
); /* zero register */
2651 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_K0
); /* kernel use only */
2652 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_K1
); /* kernel use only */
2653 tcg_regset_set_reg(s
->reserved_regs
, TCG_TMP0
); /* internal use */
2654 tcg_regset_set_reg(s
->reserved_regs
, TCG_TMP1
); /* internal use */
2655 tcg_regset_set_reg(s
->reserved_regs
, TCG_TMP2
); /* internal use */
2656 tcg_regset_set_reg(s
->reserved_regs
, TCG_TMP3
); /* internal use */
2657 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_RA
); /* return address */
2658 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_SP
); /* stack pointer */
2659 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_GP
); /* global pointer */
2662 void tb_target_set_jmp_target(uintptr_t tc_ptr
, uintptr_t jmp_addr
,
2665 atomic_set((uint32_t *)jmp_addr
, deposit32(OPC_J
, 0, 26, addr
>> 2));
2666 flush_icache_range(jmp_addr
, jmp_addr
+ 4);
2671 uint8_t fde_def_cfa
[4];
2672 uint8_t fde_reg_ofs
[ARRAY_SIZE(tcg_target_callee_save_regs
) * 2];
2675 #define ELF_HOST_MACHINE EM_MIPS
2676 /* GDB doesn't appear to require proper setting of ELF_HOST_FLAGS,
2677 which is good because they're really quite complicated for MIPS. */
2679 static const DebugFrame debug_frame
= {
2680 .h
.cie
.len
= sizeof(DebugFrameCIE
) - 4, /* length after .len member */
2683 .h
.cie
.code_align
= 1,
2684 .h
.cie
.data_align
= -(TCG_TARGET_REG_BITS
/ 8) & 0x7f, /* sleb128 */
2685 .h
.cie
.return_column
= TCG_REG_RA
,
2687 /* Total FDE size does not include the "len" member. */
2688 .h
.fde
.len
= sizeof(DebugFrame
) - offsetof(DebugFrame
, h
.fde
.cie_offset
),
2691 12, TCG_REG_SP
, /* DW_CFA_def_cfa sp, ... */
2692 (FRAME_SIZE
& 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
2696 0x80 + 16, 9, /* DW_CFA_offset, s0, -72 */
2697 0x80 + 17, 8, /* DW_CFA_offset, s2, -64 */
2698 0x80 + 18, 7, /* DW_CFA_offset, s3, -56 */
2699 0x80 + 19, 6, /* DW_CFA_offset, s4, -48 */
2700 0x80 + 20, 5, /* DW_CFA_offset, s5, -40 */
2701 0x80 + 21, 4, /* DW_CFA_offset, s6, -32 */
2702 0x80 + 22, 3, /* DW_CFA_offset, s7, -24 */
2703 0x80 + 30, 2, /* DW_CFA_offset, s8, -16 */
2704 0x80 + 31, 1, /* DW_CFA_offset, ra, -8 */
2708 void tcg_register_jit(void *buf
, size_t buf_size
)
2710 tcg_register_jit_int(buf
, buf_size
, &debug_frame
, sizeof(debug_frame
));