buildsys: Remove MIPS TCG backend
We removed support for MIPS host. Remove the now unreachable TCG host code. Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20260511135312.38705-6-philmd@linaro.org>
Philippe Mathieu-Daudé committed
May 11, 2026 at 11:19 UTC
586663f1fa29e5ba009a5e35df305bdecb60a138
12 files changed
+2
-3013
MAINTAINERS
-9
@@ -4148,15 +4148,6 @@ M: WANG Xuerui <git@xen0n.name>
4148
S: Maintained
4149
F: tcg/loongarch64/
4150
4151
-MIPS TCG target
4152
-M: Philippe Mathieu-Daudé <philmd@linaro.org>
4153
-R: Aurelien Jarno <aurelien@aurel32.net>
4154
-R: Huacai Chen <chenhuacai@kernel.org>
4155
-R: Jiaxun Yang <jiaxun.yang@flygoat.com>
4156
-R: Aleksandar Rikalo <arikalo@gmail.com>
4157
-S: Odd Fixes
4158
-F: tcg/mips64/
4159
-
4151
PPC TCG target
4152
M: Richard Henderson <richard.henderson@linaro.org>
4153
S: Odd Fixes
common-user/host/mips64/safe-syscall.inc.S
deleted
-114
@@ -1,114 +0,0 @@
1
-/*
2
- * safe-syscall.inc.S : host-specific assembly fragment
3
- * to handle signals occurring at the same time as system calls.
4
- * This is intended to be included by common-user/safe-syscall.S
5
- *
6
- * Written by Richard Henderson <richard.henderson@linaro.org>
7
- * Copyright (C) 2021 Linaro, Inc.
8
- *
9
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
10
- * See the COPYING file in the top-level directory.
11
- */
12
-
13
-#include "sys/regdef.h"
14
-#include "sys/asm.h"
15
-
16
- .text
17
- .set nomips16
18
- .set reorder
19
-
20
- .global safe_syscall_start
21
- .global safe_syscall_end
22
- .type safe_syscall_start, @function
23
- .type safe_syscall_end, @function
24
-
25
- /*
26
- * This is the entry point for making a system call. The calling
27
- * convention here is that of a C varargs function with the
28
- * first argument an 'int *' to the signal_pending flag, the
29
- * second one the system call number (as a 'long'), and all further
30
- * arguments being syscall arguments (also 'long').
31
- */
32
-
33
-/* 1 * 8 for s0 save; 1 * 8 for align. */
34
-#define FRAME 16
35
-#define OFS_S0 0
36
-
37
-
38
-NESTED(safe_syscall_base, FRAME, ra)
39
- .cfi_startproc
40
- PTR_ADDIU sp, sp, -FRAME
41
- .cfi_adjust_cfa_offset FRAME
42
- REG_S s0, OFS_S0(sp)
43
- .cfi_rel_offset s0, OFS_S0
44
- /*
45
- * The syscall calling convention is nearly the same as C:
46
- * we enter with a0 == &signal_pending
47
- * a1 == syscall number
48
- * a2 ... a7 == syscall arguments
49
- * and return the result in a0
50
- * and the syscall instruction needs
51
- * v0 == syscall number
52
- * a0 ... a5 == syscall arguments
53
- * and returns the result in v0
54
- * Shuffle everything around appropriately.
55
- */
56
- move s0, a0 /* signal_pending pointer */
57
- move v0, a1 /* syscall number */
58
- move a0, a2 /* syscall arguments */
59
- move a1, a3
60
- move a2, a4
61
- move a3, a5
62
- move a4, a6
63
- move a5, a7
64
-
65
- /*
66
- * This next sequence of code works in conjunction with the
67
- * rewind_if_safe_syscall_function(). If a signal is taken
68
- * and the interrupted PC is anywhere between 'safe_syscall_start'
69
- * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
70
- * The code sequence must therefore be able to cope with this, and
71
- * the syscall instruction must be the final one in the sequence.
72
- */
73
-safe_syscall_start:
74
- /* If signal_pending is non-zero, don't do the call */
75
- lw t1, 0(s0)
76
- bnez t1, 2f
77
- syscall
78
-safe_syscall_end:
79
-
80
- /* code path for having successfully executed the syscall */
81
- REG_L s0, OFS_S0(sp)
82
- PTR_ADDIU sp, sp, FRAME
83
- .cfi_remember_state
84
- .cfi_adjust_cfa_offset -FRAME
85
- .cfi_restore s0
86
- bnez a3, 1f
87
- jr ra
88
- .cfi_restore_state
89
-
90
- /* code path when we didn't execute the syscall */
91
-2: REG_L s0, OFS_S0(sp)
92
- PTR_ADDIU sp, sp, FRAME
93
- .cfi_adjust_cfa_offset -FRAME
94
- .cfi_restore s0
95
- li v0, QEMU_ERESTARTSYS
96
-
97
- /* code path setting errno */
98
- /*
99
- * We didn't setup GP on entry, optimistic of the syscall success.
100
- * We must do so now to load the address of the helper, as required
101
- * by the ABI, into t9.
102
- *
103
- * Note that SETUP_GPX and SETUP_GPX64 are themselves conditional,
104
- * so we can simply let the one that's not empty succeed.
105
- */
106
-1: USE_ALT_CP(t0)
107
- SETUP_GPX(t1)
108
- SETUP_GPX64(t0, t1)
109
- move a0, v0
110
- PTR_LA t9, safe_syscall_set_errno_tail
111
- jr t9
112
-
113
- .cfi_endproc
114
-END(safe_syscall_base)
include/user/thunk.h
+1
-1
@@ -115,7 +115,7 @@ static inline int thunk_type_size(const argtype *type_ptr, int is_host)
115
if (is_host) {
116
#if defined(HOST_X86_64)
117
return 8;
118
-#elif defined(HOST_MIPS) || defined(HOST_SPARC64)
118
+#elif defined(HOST_SPARC64)
119
return 4;
120
#elif defined(HOST_PPC)
121
return sizeof(void *);
linux-user/include/host/mips64/host-signal.h
deleted
-75
@@ -1,75 +0,0 @@
1
-/*
2
- * host-signal.h: signal info dependent on the host architecture
3
- *
4
- * Copyright (c) 2003-2005 Fabrice Bellard
5
- * Copyright (c) 2021 Linaro Limited
6
- *
7
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
8
- * See the COPYING file in the top-level directory.
9
- */
10
-
11
-#ifndef MIPS_HOST_SIGNAL_H
12
-#define MIPS_HOST_SIGNAL_H
13
-
14
-/* The third argument to a SA_SIGINFO handler is ucontext_t. */
15
-typedef ucontext_t host_sigcontext;
16
-
17
-static inline uintptr_t host_signal_pc(host_sigcontext *uc)
18
-{
19
- return uc->uc_mcontext.pc;
20
-}
21
-
22
-static inline void host_signal_set_pc(host_sigcontext *uc, uintptr_t pc)
23
-{
24
- uc->uc_mcontext.pc = pc;
25
-}
26
-
27
-static inline void *host_signal_mask(host_sigcontext *uc)
28
-{
29
- return &uc->uc_sigmask;
30
-}
31
-
32
-#if defined(__misp16) || defined(__mips_micromips)
33
-#error "Unsupported encoding"
34
-#endif
35
-
36
-static inline bool host_signal_write(siginfo_t *info, host_sigcontext *uc)
37
-{
38
- uint32_t insn = *(uint32_t *)host_signal_pc(uc);
39
-
40
- /* Detect all store instructions at program counter. */
41
- switch ((insn >> 26) & 077) {
42
- case 050: /* SB */
43
- case 051: /* SH */
44
- case 052: /* SWL */
45
- case 053: /* SW */
46
- case 054: /* SDL */
47
- case 055: /* SDR */
48
- case 056: /* SWR */
49
- case 070: /* SC */
50
- case 071: /* SWC1 */
51
- case 074: /* SCD */
52
- case 075: /* SDC1 */
53
- case 077: /* SD */
54
-#if !defined(__mips_isa_rev) || __mips_isa_rev < 6
55
- case 072: /* SWC2 */
56
- case 076: /* SDC2 */
57
-#endif
58
- return true;
59
- case 023: /* COP1X */
60
- /*
61
- * Required in all versions of MIPS64 since
62
- * MIPS64r1 and subsequent versions of MIPS32r2.
63
- */
64
- switch (insn & 077) {
65
- case 010: /* SWXC1 */
66
- case 011: /* SDXC1 */
67
- case 015: /* SUXC1 */
68
- return true;
69
- }
70
- break;
71
- }
72
- return false;
73
-}
74
-
75
-#endif
linux-user/mmap.c
+1
-1
@@ -1351,7 +1351,7 @@ static inline abi_ulong target_shmlba(CPUArchState *cpu_env)
1351
}
1352
#endif
1353
1354
-#if defined(__mips__) || defined(__sparc__)
1354
+#if defined(__sparc__)
1355
#define HOST_FORCE_SHMLBA 1
1356
#else
1357
#define HOST_FORCE_SHMLBA 0
tcg/mips64/tcg-target-con-set.h
deleted
-30
@@ -1,30 +0,0 @@
1
-/* SPDX-License-Identifier: MIT */
2
-/*
3
- * Define MIPS target-specific constraint sets.
4
- * Copyright (c) 2021 Linaro
5
- */
6
-
7
-/*
8
- * C_On_Im(...) defines a constraint set with <n> outputs and <m> inputs.
9
- * Each operand should be a sequence of constraint letters as defined by
10
- * tcg-target-con-str.h; the constraint combination is inclusive or.
11
- */
12
-C_O0_I1(r)
13
-C_O0_I2(r, rz)
14
-C_O0_I2(rz, r)
15
-C_O0_I3(rz, rz, r)
16
-C_O0_I4(r, r, rz, rz)
17
-C_O1_I1(r, r)
18
-C_O1_I2(r, 0, rz)
19
-C_O1_I2(r, r, r)
20
-C_O1_I2(r, r, ri)
21
-C_O1_I2(r, r, rI)
22
-C_O1_I2(r, r, rIK)
23
-C_O1_I2(r, r, rJ)
24
-C_O1_I2(r, r, rz)
25
-C_O1_I2(r, r, rzW)
26
-C_O1_I4(r, r, rz, rz, 0)
27
-C_O1_I4(r, r, rz, rz, rz)
28
-C_O1_I4(r, r, r, rz, rz)
29
-C_O2_I1(r, r, r)
30
-C_O2_I2(r, r, r, r)
tcg/mips64/tcg-target-con-str.h
deleted
-20
@@ -1,20 +0,0 @@
1
-/* SPDX-License-Identifier: MIT */
2
-/*
3
- * Define MIPS target-specific operand constraints.
4
- * Copyright (c) 2021 Linaro
5
- */
6
-
7
-/*
8
- * Define constraint letters for register sets:
9
- * REGS(letter, register_mask)
10
- */
11
-REGS('r', ALL_GENERAL_REGS)
12
-
13
-/*
14
- * Define constraint letters for constants:
15
- * CONST(letter, TCG_CT_CONST_* bit set)
16
- */
17
-CONST('I', TCG_CT_CONST_U16)
18
-CONST('J', TCG_CT_CONST_S16)
19
-CONST('K', TCG_CT_CONST_P2M1)
20
-CONST('W', TCG_CT_CONST_WSZ)
tcg/mips64/tcg-target-has.h
deleted
-69
@@ -1,69 +0,0 @@
1
-/* SPDX-License-Identifier: MIT */
2
-/*
3
- * Define target-specific opcode support
4
- * Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org>
5
- * Copyright (c) 2009 Aurelien Jarno <aurelien@aurel32.net>
6
- */
7
-
8
-#ifndef TCG_TARGET_HAS_H
9
-#define TCG_TARGET_HAS_H
10
-
11
-/* MOVN/MOVZ instructions detection */
12
-#if (defined(__mips_isa_rev) && (__mips_isa_rev >= 1)) || \
13
- defined(_MIPS_ARCH_LOONGSON2E) || defined(_MIPS_ARCH_LOONGSON2F) || \
14
- defined(_MIPS_ARCH_MIPS4)
15
-#define use_movnz_instructions 1
16
-#else
17
-extern bool use_movnz_instructions;
18
-#endif
19
-
20
-/* MIPS32 instruction set detection */
21
-#if defined(__mips_isa_rev) && (__mips_isa_rev >= 1)
22
-#define use_mips32_instructions 1
23
-#else
24
-extern bool use_mips32_instructions;
25
-#endif
26
-
27
-/* MIPS32R2 instruction set detection */
28
-#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
29
-#define use_mips32r2_instructions 1
30
-#else
31
-extern bool use_mips32r2_instructions;
32
-#endif
33
-
34
-/* MIPS32R6 instruction set detection */
35
-#if defined(__mips_isa_rev) && (__mips_isa_rev >= 6)
36
-#define use_mips32r6_instructions 1
37
-#else
38
-#define use_mips32r6_instructions 0
39
-#endif
40
-
41
-/* optional instructions */
42
-#define TCG_TARGET_HAS_extr_i64_i32 1
43
-#define TCG_TARGET_HAS_ext32s_i64 1
44
-#define TCG_TARGET_HAS_ext32u_i64 1
45
-
46
-/* optional instructions detected at runtime */
47
-#define TCG_TARGET_HAS_qemu_ldst_i128 0
48
-#define TCG_TARGET_HAS_tst 0
49
-
50
-#define TCG_TARGET_extract_valid(type, ofs, len) use_mips32r2_instructions
51
-#define TCG_TARGET_deposit_valid(type, ofs, len) use_mips32r2_instructions
52
-
53
-static inline bool
54
-tcg_target_sextract_valid(TCGType type, unsigned ofs, unsigned len)
55
-{
56
- if (ofs == 0) {
57
- switch (len) {
58
- case 8:
59
- case 16:
60
- return use_mips32r2_instructions;
61
- case 32:
62
- return type == TCG_TYPE_I64;
63
- }
64
- }
65
- return false;
66
-}
67
-#define TCG_TARGET_sextract_valid tcg_target_sextract_valid
68
-
69
-#endif
tcg/mips64/tcg-target-mo.h
deleted
-13
@@ -1,13 +0,0 @@
1
-/* SPDX-License-Identifier: MIT */
2
-/*
3
- * Define target-specific memory model
4
- * Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org>
5
- * Copyright (c) 2009 Aurelien Jarno <aurelien@aurel32.net>
6
- */
7
-
8
-#ifndef TCG_TARGET_MO_H
9
-#define TCG_TARGET_MO_H
10
-
11
-#define TCG_TARGET_DEFAULT_MO 0
12
-
13
-#endif
tcg/mips64/tcg-target-opc.h.inc
deleted
-1
@@ -1 +0,0 @@
1
-/* No target specific opcodes. */
tcg/mips64/tcg-target.c.inc
deleted
-2605
@@ -1,2605 +0,0 @@
1
-/*
2
- * Tiny Code Generator for QEMU
3
- *
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
7
- *
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:
14
- *
15
- * The above copyright notice and this permission notice shall be included in
16
- * all copies or substantial portions of the Software.
17
- *
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
24
- * THE SOFTWARE.
25
- */
26
-
27
-/* used for function call generation */
28
-#define TCG_TARGET_STACK_ALIGN 16
29
-#define TCG_TARGET_CALL_STACK_OFFSET 0
30
-#define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_NORMAL
31
-#define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL
32
-#define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL
33
-#define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_EVEN
34
-
35
-#ifdef CONFIG_DEBUG_TCG
36
-static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
37
- "zero",
38
- "at",
39
- "v0",
40
- "v1",
41
- "a0",
42
- "a1",
43
- "a2",
44
- "a3",
45
- "t0",
46
- "t1",
47
- "t2",
48
- "t3",
49
- "t4",
50
- "t5",
51
- "t6",
52
- "t7",
53
- "s0",
54
- "s1",
55
- "s2",
56
- "s3",
57
- "s4",
58
- "s5",
59
- "s6",
60
- "s7",
61
- "t8",
62
- "t9",
63
- "k0",
64
- "k1",
65
- "gp",
66
- "sp",
67
- "s8",
68
- "ra",
69
-};
70
-#endif
71
-
72
-#define TCG_TMP0 TCG_REG_AT
73
-#define TCG_TMP1 TCG_REG_T9
74
-#define TCG_TMP2 TCG_REG_T8
75
-#define TCG_TMP3 TCG_REG_T7
76
-
77
-#define TCG_GUEST_BASE_REG TCG_REG_S7
78
-#define TCG_REG_TB TCG_REG_S6
79
-
80
-/* check if we really need so many registers :P */
81
-static const int tcg_target_reg_alloc_order[] = {
82
- /* Call saved registers. */
83
- TCG_REG_S0,
84
- TCG_REG_S1,
85
- TCG_REG_S2,
86
- TCG_REG_S3,
87
- TCG_REG_S4,
88
- TCG_REG_S5,
89
- TCG_REG_S6,
90
- TCG_REG_S7,
91
- TCG_REG_S8,
92
-
93
- /* Call clobbered registers. */
94
- TCG_REG_T4,
95
- TCG_REG_T5,
96
- TCG_REG_T6,
97
- TCG_REG_T7,
98
- TCG_REG_T8,
99
- TCG_REG_T9,
100
- TCG_REG_V1,
101
- TCG_REG_V0,
102
-
103
- /* Argument registers, opposite order of allocation. */
104
- TCG_REG_T3,
105
- TCG_REG_T2,
106
- TCG_REG_T1,
107
- TCG_REG_T0,
108
- TCG_REG_A3,
109
- TCG_REG_A2,
110
- TCG_REG_A1,
111
- TCG_REG_A0,
112
-};
113
-
114
-static const TCGReg tcg_target_call_iarg_regs[] = {
115
- TCG_REG_A0,
116
- TCG_REG_A1,
117
- TCG_REG_A2,
118
- TCG_REG_A3,
119
- TCG_REG_T0,
120
- TCG_REG_T1,
121
- TCG_REG_T2,
122
- TCG_REG_T3,
123
-};
124
-
125
-static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot)
126
-{
127
- tcg_debug_assert(kind == TCG_CALL_RET_NORMAL);
128
- tcg_debug_assert(slot >= 0 && slot <= 1);
129
- return TCG_REG_V0 + slot;
130
-}
131
-
132
-static const tcg_insn_unit *tb_ret_addr;
133
-static const tcg_insn_unit *bswap32_addr;
134
-static const tcg_insn_unit *bswap32u_addr;
135
-static const tcg_insn_unit *bswap64_addr;
136
-
137
-static bool reloc_pc16(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
138
-{
139
- /* Let the compiler perform the right-shift as part of the arithmetic. */
140
- const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
141
- ptrdiff_t disp = target - (src_rx + 1);
142
- if (disp == (int16_t)disp) {
143
- *src_rw = deposit32(*src_rw, 0, 16, disp);
144
- return true;
145
- }
146
- return false;
147
-}
148
-
149
-static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
150
- intptr_t value, intptr_t addend)
151
-{
152
- value += addend;
153
- switch (type) {
154
- case R_MIPS_PC16:
155
- return reloc_pc16(code_ptr, (const tcg_insn_unit *)value);
156
- case R_MIPS_16:
157
- if (value != (int16_t)value) {
158
- return false;
159
- }
160
- *code_ptr = deposit32(*code_ptr, 0, 16, value);
161
- return true;
162
- }
163
- g_assert_not_reached();
164
-}
165
-
166
-#define TCG_CT_CONST_U16 0x100 /* Unsigned 16-bit: 0 - 0xffff. */
167
-#define TCG_CT_CONST_S16 0x200 /* Signed 16-bit: -32768 - 32767 */
168
-#define TCG_CT_CONST_P2M1 0x400 /* Power of 2 minus 1. */
169
-#define TCG_CT_CONST_WSZ 0x800 /* word size */
170
-
171
-#define ALL_GENERAL_REGS 0xffffffffu
172
-
173
-static bool is_p2m1(tcg_target_long val)
174
-{
175
- return val && ((val + 1) & val) == 0;
176
-}
177
-
178
-/* test if a constant matches the constraint */
179
-static bool tcg_target_const_match(int64_t val, int ct,
180
- TCGType type, TCGCond cond, int vece)
181
-{
182
- if (ct & TCG_CT_CONST) {
183
- return 1;
184
- } else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val) {
185
- return 1;
186
- } else if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val) {
187
- return 1;
188
- } else if ((ct & TCG_CT_CONST_P2M1)
189
- && use_mips32r2_instructions && is_p2m1(val)) {
190
- return 1;
191
- } else if ((ct & TCG_CT_CONST_WSZ)
192
- && val == (type == TCG_TYPE_I32 ? 32 : 64)) {
193
- return 1;
194
- }
195
- return 0;
196
-}
197
-
198
-/* instruction opcodes */
199
-typedef enum {
200
- OPC_J = 002 << 26,
201
- OPC_JAL = 003 << 26,
202
- OPC_BEQ = 004 << 26,
203
- OPC_BNE = 005 << 26,
204
- OPC_BLEZ = 006 << 26,
205
- OPC_BGTZ = 007 << 26,
206
- OPC_ADDIU = 011 << 26,
207
- OPC_SLTI = 012 << 26,
208
- OPC_SLTIU = 013 << 26,
209
- OPC_ANDI = 014 << 26,
210
- OPC_ORI = 015 << 26,
211
- OPC_XORI = 016 << 26,
212
- OPC_LUI = 017 << 26,
213
- OPC_BNEL = 025 << 26,
214
- OPC_BNEZALC_R6 = 030 << 26,
215
- OPC_DADDIU = 031 << 26,
216
- OPC_LDL = 032 << 26,
217
- OPC_LDR = 033 << 26,
218
- OPC_LB = 040 << 26,
219
- OPC_LH = 041 << 26,
220
- OPC_LWL = 042 << 26,
221
- OPC_LW = 043 << 26,
222
- OPC_LBU = 044 << 26,
223
- OPC_LHU = 045 << 26,
224
- OPC_LWR = 046 << 26,
225
- OPC_LWU = 047 << 26,
226
- OPC_SB = 050 << 26,
227
- OPC_SH = 051 << 26,
228
- OPC_SWL = 052 << 26,
229
- OPC_SW = 053 << 26,
230
- OPC_SDL = 054 << 26,
231
- OPC_SDR = 055 << 26,
232
- OPC_SWR = 056 << 26,
233
- OPC_LD = 067 << 26,
234
- OPC_SD = 077 << 26,
235
-
236
- OPC_SPECIAL = 000 << 26,
237
- OPC_SLL = OPC_SPECIAL | 000,
238
- OPC_SRL = OPC_SPECIAL | 002,
239
- OPC_ROTR = OPC_SPECIAL | 002 | (1 << 21),
240
- OPC_SRA = OPC_SPECIAL | 003,
241
- OPC_SLLV = OPC_SPECIAL | 004,
242
- OPC_SRLV = OPC_SPECIAL | 006,
243
- OPC_ROTRV = OPC_SPECIAL | 006 | 0100,
244
- OPC_SRAV = OPC_SPECIAL | 007,
245
- OPC_JR_R5 = OPC_SPECIAL | 010,
246
- OPC_JALR = OPC_SPECIAL | 011,
247
- OPC_MOVZ = OPC_SPECIAL | 012,
248
- OPC_MOVN = OPC_SPECIAL | 013,
249
- OPC_SYNC = OPC_SPECIAL | 017,
250
- OPC_MFHI = OPC_SPECIAL | 020,
251
- OPC_MFLO = OPC_SPECIAL | 022,
252
- OPC_DSLLV = OPC_SPECIAL | 024,
253
- OPC_DSRLV = OPC_SPECIAL | 026,
254
- OPC_DROTRV = OPC_SPECIAL | 026 | 0100,
255
- OPC_DSRAV = OPC_SPECIAL | 027,
256
- OPC_MULT = OPC_SPECIAL | 030,
257
- OPC_MUL_R6 = OPC_SPECIAL | 030 | 0200,
258
- OPC_MUH = OPC_SPECIAL | 030 | 0300,
259
- OPC_MULTU = OPC_SPECIAL | 031,
260
- OPC_MULU = OPC_SPECIAL | 031 | 0200,
261
- OPC_MUHU = OPC_SPECIAL | 031 | 0300,
262
- OPC_DIV = OPC_SPECIAL | 032,
263
- OPC_DIV_R6 = OPC_SPECIAL | 032 | 0200,
264
- OPC_MOD = OPC_SPECIAL | 032 | 0300,
265
- OPC_DIVU = OPC_SPECIAL | 033,
266
- OPC_DIVU_R6 = OPC_SPECIAL | 033 | 0200,
267
- OPC_MODU = OPC_SPECIAL | 033 | 0300,
268
- OPC_DMULT = OPC_SPECIAL | 034,
269
- OPC_DMUL = OPC_SPECIAL | 034 | 0200,
270
- OPC_DMUH = OPC_SPECIAL | 034 | 0300,
271
- OPC_DMULTU = OPC_SPECIAL | 035,
272
- OPC_DMULU = OPC_SPECIAL | 035 | 0200,
273
- OPC_DMUHU = OPC_SPECIAL | 035 | 0300,
274
- OPC_DDIV = OPC_SPECIAL | 036,
275
- OPC_DDIV_R6 = OPC_SPECIAL | 036 | 0200,
276
- OPC_DMOD = OPC_SPECIAL | 036 | 0300,
277
- OPC_DDIVU = OPC_SPECIAL | 037,
278
- OPC_DDIVU_R6 = OPC_SPECIAL | 037 | 0200,
279
- OPC_DMODU = OPC_SPECIAL | 037 | 0300,
280
- OPC_ADDU = OPC_SPECIAL | 041,
281
- OPC_SUBU = OPC_SPECIAL | 043,
282
- OPC_AND = OPC_SPECIAL | 044,
283
- OPC_OR = OPC_SPECIAL | 045,
284
- OPC_XOR = OPC_SPECIAL | 046,
285
- OPC_NOR = OPC_SPECIAL | 047,
286
- OPC_SLT = OPC_SPECIAL | 052,
287
- OPC_SLTU = OPC_SPECIAL | 053,
288
- OPC_DADDU = OPC_SPECIAL | 055,
289
- OPC_DSUBU = OPC_SPECIAL | 057,
290
- OPC_SELEQZ = OPC_SPECIAL | 065,
291
- OPC_SELNEZ = OPC_SPECIAL | 067,
292
- OPC_DSLL = OPC_SPECIAL | 070,
293
- OPC_DSRL = OPC_SPECIAL | 072,
294
- OPC_DROTR = OPC_SPECIAL | 072 | (1 << 21),
295
- OPC_DSRA = OPC_SPECIAL | 073,
296
- OPC_DSLL32 = OPC_SPECIAL | 074,
297
- OPC_DSRL32 = OPC_SPECIAL | 076,
298
- OPC_DROTR32 = OPC_SPECIAL | 076 | (1 << 21),
299
- OPC_DSRA32 = OPC_SPECIAL | 077,
300
- OPC_CLZ_R6 = OPC_SPECIAL | 0120,
301
- OPC_DCLZ_R6 = OPC_SPECIAL | 0122,
302
-
303
- OPC_REGIMM = 001 << 26,
304
- OPC_BLTZ = OPC_REGIMM | (000 << 16),
305
- OPC_BGEZ = OPC_REGIMM | (001 << 16),
306
-
307
- OPC_SPECIAL2 = 034 << 26,
308
- OPC_MUL_R5 = OPC_SPECIAL2 | 002,
309
- OPC_CLZ = OPC_SPECIAL2 | 040,
310
- OPC_DCLZ = OPC_SPECIAL2 | 044,
311
-
312
- OPC_SPECIAL3 = 037 << 26,
313
- OPC_EXT = OPC_SPECIAL3 | 000,
314
- OPC_DEXTM = OPC_SPECIAL3 | 001,
315
- OPC_DEXTU = OPC_SPECIAL3 | 002,
316
- OPC_DEXT = OPC_SPECIAL3 | 003,
317
- OPC_INS = OPC_SPECIAL3 | 004,
318
- OPC_DINSM = OPC_SPECIAL3 | 005,
319
- OPC_DINSU = OPC_SPECIAL3 | 006,
320
- OPC_DINS = OPC_SPECIAL3 | 007,
321
- OPC_WSBH = OPC_SPECIAL3 | 00240,
322
- OPC_DSBH = OPC_SPECIAL3 | 00244,
323
- OPC_DSHD = OPC_SPECIAL3 | 00544,
324
- OPC_SEB = OPC_SPECIAL3 | 02040,
325
- OPC_SEH = OPC_SPECIAL3 | 03040,
326
-
327
- /* MIPS r6 doesn't have JR, JALR should be used instead */
328
- OPC_JR = use_mips32r6_instructions ? OPC_JALR : OPC_JR_R5,
329
-
330
- /*
331
- * MIPS r6 replaces MUL with an alternative encoding which is
332
- * backwards-compatible at the assembly level.
333
- */
334
- OPC_MUL = use_mips32r6_instructions ? OPC_MUL_R6 : OPC_MUL_R5,
335
-
336
- /* MIPS r6 introduced names for weaker variants of SYNC. These are
337
- backward compatible to previous architecture revisions. */
338
- OPC_SYNC_WMB = OPC_SYNC | 0x04 << 6,
339
- OPC_SYNC_MB = OPC_SYNC | 0x10 << 6,
340
- OPC_SYNC_ACQUIRE = OPC_SYNC | 0x11 << 6,
341
- OPC_SYNC_RELEASE = OPC_SYNC | 0x12 << 6,
342
- OPC_SYNC_RMB = OPC_SYNC | 0x13 << 6,
343
-} MIPSInsn;
344
-
345
-/*
346
- * Type reg
347
- */
348
-static void tcg_out_opc_reg(TCGContext *s, MIPSInsn opc,
349
- TCGReg rd, TCGReg rs, TCGReg rt)
350
-{
351
- int32_t inst;
352
-
353
- inst = opc;
354
- inst |= (rs & 0x1F) << 21;
355
- inst |= (rt & 0x1F) << 16;
356
- inst |= (rd & 0x1F) << 11;
357
- tcg_out32(s, inst);
358
-}
359
-
360
-/*
361
- * Type immediate
362
- */
363
-static void tcg_out_opc_imm(TCGContext *s, MIPSInsn opc,
364
- TCGReg rt, TCGReg rs, TCGArg imm)
365
-{
366
- int32_t inst;
367
-
368
- inst = opc;
369
- inst |= (rs & 0x1F) << 21;
370
- inst |= (rt & 0x1F) << 16;
371
- inst |= (imm & 0xffff);
372
- tcg_out32(s, inst);
373
-}
374
-
375
-/*
376
- * Type bitfield
377
- */
378
-static void tcg_out_opc_bf(TCGContext *s, MIPSInsn opc, TCGReg rt,
379
- TCGReg rs, int msb, int lsb)
380
-{
381
- int32_t inst;
382
-
383
- inst = opc;
384
- inst |= (rs & 0x1F) << 21;
385
- inst |= (rt & 0x1F) << 16;
386
- inst |= (msb & 0x1F) << 11;
387
- inst |= (lsb & 0x1F) << 6;
388
- tcg_out32(s, inst);
389
-}
390
-
391
-static void tcg_out_opc_bf64(TCGContext *s, MIPSInsn opc, MIPSInsn opm,
392
- MIPSInsn oph, TCGReg rt, TCGReg rs,
393
- int msb, int lsb)
394
-{
395
- if (lsb >= 32) {
396
- opc = oph;
397
- msb -= 32;
398
- lsb -= 32;
399
- } else if (msb >= 32) {
400
- opc = opm;
401
- msb -= 32;
402
- }
403
- tcg_out_opc_bf(s, opc, rt, rs, msb, lsb);
404
-}
405
-
406
-/*
407
- * Type branch
408
- */
409
-static void tcg_out_opc_br(TCGContext *s, MIPSInsn opc, TCGReg rt, TCGReg rs)
410
-{
411
- tcg_out_opc_imm(s, opc, rt, rs, 0);
412
-}
413
-
414
-/*
415
- * Type sa
416
- */
417
-static void tcg_out_opc_sa(TCGContext *s, MIPSInsn opc,
418
- TCGReg rd, TCGReg rt, TCGArg sa)
419
-{
420
- int32_t inst;
421
-
422
- inst = opc;
423
- inst |= (rt & 0x1F) << 16;
424
- inst |= (rd & 0x1F) << 11;
425
- inst |= (sa & 0x1F) << 6;
426
- tcg_out32(s, inst);
427
-
428
-}
429
-
430
-static void tcg_out_opc_sa64(TCGContext *s, MIPSInsn opc1, MIPSInsn opc2,
431
- TCGReg rd, TCGReg rt, TCGArg sa)
432
-{
433
- int32_t inst;
434
-
435
- inst = (sa & 32 ? opc2 : opc1);
436
- inst |= (rt & 0x1F) << 16;
437
- inst |= (rd & 0x1F) << 11;
438
- inst |= (sa & 0x1F) << 6;
439
- tcg_out32(s, inst);
440
-}
441
-
442
-/*
443
- * Type jump.
444
- * Returns true if the branch was in range and the insn was emitted.
445
- */
446
-static bool tcg_out_opc_jmp(TCGContext *s, MIPSInsn opc, const void *target)
447
-{
448
- uintptr_t dest = (uintptr_t)target;
449
- uintptr_t from = (uintptr_t)tcg_splitwx_to_rx(s->code_ptr) + 4;
450
- int32_t inst;
451
-
452
- /* The pc-region branch happens within the 256MB region of
453
- the delay slot (thus the +4). */
454
- if ((from ^ dest) & -(1 << 28)) {
455
- return false;
456
- }
457
- tcg_debug_assert((dest & 3) == 0);
458
-
459
- inst = opc;
460
- inst |= (dest >> 2) & 0x3ffffff;
461
- tcg_out32(s, inst);
462
- return true;
463
-}
464
-
465
-static void tcg_out_nop(TCGContext *s)
466
-{
467
- tcg_out32(s, 0);
468
-}
469
-
470
-static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
471
-{
472
- memset(p, 0, count * sizeof(tcg_insn_unit));
473
-}
474
-
475
-static void tcg_out_dsll(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa)
476
-{
477
- tcg_out_opc_sa64(s, OPC_DSLL, OPC_DSLL32, rd, rt, sa);
478
-}
479
-
480
-static void tcg_out_dsrl(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa)
481
-{
482
- tcg_out_opc_sa64(s, OPC_DSRL, OPC_DSRL32, rd, rt, sa);
483
-}
484
-
485
-static void tcg_out_dsra(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa)
486
-{
487
- tcg_out_opc_sa64(s, OPC_DSRA, OPC_DSRA32, rd, rt, sa);
488
-}
489
-
490
-static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
491
-{
492
- /* Simple reg-reg move, optimising out the 'do nothing' case */
493
- if (ret != arg) {
494
- tcg_out_opc_reg(s, OPC_OR, ret, arg, TCG_REG_ZERO);
495
- }
496
- return true;
497
-}
498
-
499
-static bool tcg_out_movi_one(TCGContext *s, TCGReg ret, tcg_target_long arg)
500
-{
501
- if (arg == (int16_t)arg) {
502
- tcg_out_opc_imm(s, OPC_ADDIU, ret, TCG_REG_ZERO, arg);
503
- return true;
504
- }
505
- if (arg == (uint16_t)arg) {
506
- tcg_out_opc_imm(s, OPC_ORI, ret, TCG_REG_ZERO, arg);
507
- return true;
508
- }
509
- if (arg == (int32_t)arg && (arg & 0xffff) == 0) {
510
- tcg_out_opc_imm(s, OPC_LUI, ret, TCG_REG_ZERO, arg >> 16);
511
- return true;
512
- }
513
- return false;
514
-}
515
-
516
-static bool tcg_out_movi_two(TCGContext *s, TCGReg ret, tcg_target_long arg)
517
-{
518
- /*
519
- * All signed 32-bit constants are loadable with two immediates,
520
- * and everything else requires more work.
521
- */
522
- if (arg == (int32_t)arg) {
523
- if (!tcg_out_movi_one(s, ret, arg)) {
524
- tcg_out_opc_imm(s, OPC_LUI, ret, TCG_REG_ZERO, arg >> 16);
525
- tcg_out_opc_imm(s, OPC_ORI, ret, ret, arg & 0xffff);
526
- }
527
- return true;
528
- }
529
- return false;
530
-}
531
-
532
-static void tcg_out_movi_pool(TCGContext *s, TCGReg ret,
533
- tcg_target_long arg, TCGReg tbreg)
534
-{
535
- new_pool_label(s, arg, R_MIPS_16, s->code_ptr, tcg_tbrel_diff(s, NULL));
536
- tcg_out_opc_imm(s, OPC_LD, ret, tbreg, 0);
537
-}
538
-
539
-static void tcg_out_movi_int(TCGContext *s, TCGType type, TCGReg ret,
540
- tcg_target_long arg, TCGReg tbreg)
541
-{
542
- tcg_target_long tmp;
543
- int sh, lo;
544
-
545
- if (type == TCG_TYPE_I32) {
546
- arg = (int32_t)arg;
547
- }
548
-
549
- /* Load all 32-bit constants. */
550
- if (tcg_out_movi_two(s, ret, arg)) {
551
- return;
552
- }
553
-
554
- /* Load addresses within 2GB of TB with 1 or 3 insns. */
555
- tmp = tcg_tbrel_diff(s, (void *)arg);
556
- if (tmp == (int16_t)tmp) {
557
- tcg_out_opc_imm(s, OPC_DADDIU, ret, tbreg, tmp);
558
- return;
559
- }
560
- if (tcg_out_movi_two(s, ret, tmp)) {
561
- tcg_out_opc_reg(s, OPC_DADDU, ret, ret, tbreg);
562
- return;
563
- }
564
-
565
- /*
566
- * Load bitmasks with a right-shift. This is good for things
567
- * like 0x0fff_ffff_ffff_fff0: ADDUI r,0,0xff00 + DSRL r,r,4.
568
- * or similarly using LUI. For this to work, bit 31 must be set.
569
- */
570
- if (arg > 0 && (int32_t)arg < 0) {
571
- sh = clz64(arg);
572
- if (tcg_out_movi_one(s, ret, arg << sh)) {
573
- tcg_out_dsrl(s, ret, ret, sh);
574
- return;
575
- }
576
- }
577
-
578
- /*
579
- * Load slightly larger constants using left-shift.
580
- * Limit this sequence to 3 insns to avoid too much expansion.
581
- */
582
- sh = ctz64(arg);
583
- if (sh && tcg_out_movi_two(s, ret, arg >> sh)) {
584
- tcg_out_dsll(s, ret, ret, sh);
585
- return;
586
- }
587
-
588
- /*
589
- * Load slightly larger constants using left-shift and add/or.
590
- * Prefer addi with a negative immediate when that would produce
591
- * a larger shift. For this to work, bits 15 and 16 must be set.
592
- */
593
- lo = arg & 0xffff;
594
- if (lo) {
595
- if ((arg & 0x18000) == 0x18000) {
596
- lo = (int16_t)arg;
597
- }
598
- tmp = arg - lo;
599
- sh = ctz64(tmp);
600
- tmp >>= sh;
601
- if (tcg_out_movi_one(s, ret, tmp)) {
602
- tcg_out_dsll(s, ret, ret, sh);
603
- tcg_out_opc_imm(s, lo < 0 ? OPC_DADDIU : OPC_ORI, ret, ret, lo);
604
- return;
605
- }
606
- }
607
-
608
- /* Otherwise, put 64-bit constants into the constant pool. */
609
- tcg_out_movi_pool(s, ret, arg, tbreg);
610
-}
611
-
612
-static void tcg_out_movi(TCGContext *s, TCGType type,
613
- TCGReg ret, tcg_target_long arg)
614
-{
615
- tcg_out_movi_int(s, type, ret, arg, TCG_REG_TB);
616
-}
617
-
618
-static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rs)
619
-{
620
- tcg_debug_assert(use_mips32r2_instructions);
621
- tcg_out_opc_reg(s, OPC_SEB, rd, TCG_REG_ZERO, rs);
622
-}
623
-
624
-static void tcg_out_ext8u(TCGContext *s, TCGReg rd, TCGReg rs)
625
-{
626
- tcg_out_opc_imm(s, OPC_ANDI, rd, rs, 0xff);
627
-}
628
-
629
-static void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rs)
630
-{
631
- tcg_debug_assert(use_mips32r2_instructions);
632
- tcg_out_opc_reg(s, OPC_SEH, rd, TCG_REG_ZERO, rs);
633
-}
634
-
635
-static void tcg_out_ext16u(TCGContext *s, TCGReg rd, TCGReg rs)
636
-{
637
- tcg_out_opc_imm(s, OPC_ANDI, rd, rs, 0xffff);
638
-}
639
-
640
-static void tcg_out_ext32s(TCGContext *s, TCGReg rd, TCGReg rs)
641
-{
642
- tcg_out_opc_sa(s, OPC_SLL, rd, rs, 0);
643
-}
644
-
645
-static void tcg_out_exts_i32_i64(TCGContext *s, TCGReg rd, TCGReg rs)
646
-{
647
- if (rd != rs) {
648
- tcg_out_ext32s(s, rd, rs);
649
- }
650
-}
651
-
652
-static void tcg_out_extu_i32_i64(TCGContext *s, TCGReg rd, TCGReg rs)
653
-{
654
- tcg_out_ext32u(s, rd, rs);
655
-}
656
-
657
-static void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg rd, TCGReg rs)
658
-{
659
- tcg_out_ext32s(s, rd, rs);
660
-}
661
-
662
-static bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2)
663
-{
664
- return false;
665
-}
666
-
667
-static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
668
- tcg_target_long imm)
669
-{
670
- /* This function is only used for passing structs by reference. */
671
- g_assert_not_reached();
672
-}
673
-
674
-static void tcg_out_bswap_subr(TCGContext *s, const tcg_insn_unit *sub)
675
-{
676
- if (!tcg_out_opc_jmp(s, OPC_JAL, sub)) {
677
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP1, (uintptr_t)sub);
678
- tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_TMP1, 0);
679
- }
680
-}
681
-
682
-static void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg)
683
-{
684
- if (use_mips32r2_instructions) {
685
- tcg_out_opc_bf(s, OPC_DEXT, ret, arg, 31, 0);
686
- } else {
687
- tcg_out_dsll(s, ret, arg, 32);
688
- tcg_out_dsrl(s, ret, ret, 32);
689
- }
690
-}
691
-
692
-static void tcg_out_ldst(TCGContext *s, MIPSInsn opc, TCGReg data,
693
- TCGReg addr, intptr_t ofs)
694
-{
695
- int16_t lo = ofs;
696
- if (ofs != lo) {
697
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, ofs - lo);
698
- if (addr != TCG_REG_ZERO) {
699
- tcg_out_opc_reg(s, OPC_DADDU, TCG_TMP0, TCG_TMP0, addr);
700
- }
701
- addr = TCG_TMP0;
702
- }
703
- tcg_out_opc_imm(s, opc, data, addr, lo);
704
-}
705
-
706
-static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
707
- TCGReg arg1, intptr_t arg2)
708
-{
709
- MIPSInsn opc = type == TCG_TYPE_I32 ? OPC_LW : OPC_LD;
710
- tcg_out_ldst(s, opc, arg, arg1, arg2);
711
-}
712
-
713
-static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
714
- TCGReg arg1, intptr_t arg2)
715
-{
716
- MIPSInsn opc = type == TCG_TYPE_I32 ? OPC_SW : OPC_SD;
717
- tcg_out_ldst(s, opc, arg, arg1, arg2);
718
-}
719
-
720
-static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
721
- TCGReg base, intptr_t ofs)
722
-{
723
- if (val == 0) {
724
- tcg_out_st(s, type, TCG_REG_ZERO, base, ofs);
725
- return true;
726
- }
727
- return false;
728
-}
729
-
730
-#define SETCOND_INV TCG_TARGET_NB_REGS
731
-#define SETCOND_NEZ (SETCOND_INV << 1)
732
-#define SETCOND_FLAGS (SETCOND_INV | SETCOND_NEZ)
733
-
734
-static int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret,
735
- TCGReg arg1, TCGReg arg2)
736
-{
737
- int flags = 0;
738
-
739
- switch (cond) {
740
- case TCG_COND_EQ: /* -> NE */
741
- case TCG_COND_GE: /* -> LT */
742
- case TCG_COND_GEU: /* -> LTU */
743
- case TCG_COND_LE: /* -> GT */
744
- case TCG_COND_LEU: /* -> GTU */
745
- cond = tcg_invert_cond(cond);
746
- flags ^= SETCOND_INV;
747
- break;
748
- default:
749
- break;
750
- }
751
-
752
- switch (cond) {
753
- case TCG_COND_NE:
754
- flags |= SETCOND_NEZ;
755
- if (arg2 == 0) {
756
- return arg1 | flags;
757
- }
758
- tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
759
- break;
760
- case TCG_COND_LT:
761
- tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
762
- break;
763
- case TCG_COND_LTU:
764
- tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
765
- break;
766
- case TCG_COND_GT:
767
- tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
768
- break;
769
- case TCG_COND_GTU:
770
- tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
771
- break;
772
- default:
773
- g_assert_not_reached();
774
- }
775
- return ret | flags;
776
-}
777
-
778
-static void tcg_out_setcond_end(TCGContext *s, TCGReg ret, int tmpflags)
779
-{
780
- if (tmpflags != ret) {
781
- TCGReg tmp = tmpflags & ~SETCOND_FLAGS;
782
-
783
- switch (tmpflags & SETCOND_FLAGS) {
784
- case SETCOND_INV:
785
- /* Intermediate result is boolean: simply invert. */
786
- tcg_out_opc_imm(s, OPC_XORI, ret, tmp, 1);
787
- break;
788
- case SETCOND_NEZ:
789
- /* Intermediate result is zero/non-zero: test != 0. */
790
- tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp);
791
- break;
792
- case SETCOND_NEZ | SETCOND_INV:
793
- /* Intermediate result is zero/non-zero: test == 0. */
794
- tcg_out_opc_imm(s, OPC_SLTIU, ret, tmp, 1);
795
- break;
796
- default:
797
- g_assert_not_reached();
798
- }
799
- }
800
-}
801
-
802
-static void tgen_setcond(TCGContext *s, TCGType type, TCGCond cond,
803
- TCGReg ret, TCGReg arg1, TCGReg arg2)
804
-{
805
- int tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2);
806
- tcg_out_setcond_end(s, ret, tmpflags);
807
-}
808
-
809
-static const TCGOutOpSetcond outop_setcond = {
810
- .base.static_constraint = C_O1_I2(r, r, rz),
811
- .out_rrr = tgen_setcond,
812
-};
813
-
814
-static void tgen_negsetcond(TCGContext *s, TCGType type, TCGCond cond,
815
- TCGReg ret, TCGReg arg1, TCGReg arg2)
816
-{
817
- int tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2);
818
- TCGReg tmp = tmpflags & ~SETCOND_FLAGS;
819
-
820
- /* If intermediate result is zero/non-zero: test != 0. */
821
- if (tmpflags & SETCOND_NEZ) {
822
- tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp);
823
- tmp = ret;
824
- }
825
- /* Produce the 0/-1 result. */
826
- if (tmpflags & SETCOND_INV) {
827
- tcg_out_opc_imm(s, OPC_ADDIU, ret, tmp, -1);
828
- } else {
829
- tcg_out_opc_reg(s, OPC_SUBU, ret, TCG_REG_ZERO, tmp);
830
- }
831
-}
832
-
833
-static const TCGOutOpSetcond outop_negsetcond = {
834
- .base.static_constraint = C_O1_I2(r, r, rz),
835
- .out_rrr = tgen_negsetcond,
836
-};
837
-
838
-static void tgen_brcond(TCGContext *s, TCGType type, TCGCond cond,
839
- TCGReg arg1, TCGReg arg2, TCGLabel *l)
840
-{
841
- static const MIPSInsn b_zero[16] = {
842
- [TCG_COND_LT] = OPC_BLTZ,
843
- [TCG_COND_GT] = OPC_BGTZ,
844
- [TCG_COND_LE] = OPC_BLEZ,
845
- [TCG_COND_GE] = OPC_BGEZ,
846
- };
847
-
848
- MIPSInsn b_opc = 0;
849
-
850
- switch (cond) {
851
- case TCG_COND_EQ:
852
- b_opc = OPC_BEQ;
853
- break;
854
- case TCG_COND_NE:
855
- b_opc = OPC_BNE;
856
- break;
857
- case TCG_COND_LT:
858
- case TCG_COND_GT:
859
- case TCG_COND_LE:
860
- case TCG_COND_GE:
861
- if (arg2 == 0) {
862
- b_opc = b_zero[cond];
863
- arg2 = arg1;
864
- arg1 = 0;
865
- }
866
- break;
867
- default:
868
- break;
869
- }
870
-
871
- if (b_opc == 0) {
872
- int tmpflags = tcg_out_setcond_int(s, cond, TCG_TMP0, arg1, arg2);
873
-
874
- arg2 = TCG_REG_ZERO;
875
- arg1 = tmpflags & ~SETCOND_FLAGS;
876
- b_opc = tmpflags & SETCOND_INV ? OPC_BEQ : OPC_BNE;
877
- }
878
-
879
- tcg_out_reloc(s, s->code_ptr, R_MIPS_PC16, l, 0);
880
- tcg_out_opc_br(s, b_opc, arg1, arg2);
881
- tcg_out_nop(s);
882
-}
883
-
884
-static const TCGOutOpBrcond outop_brcond = {
885
- .base.static_constraint = C_O0_I2(r, rz),
886
- .out_rr = tgen_brcond,
887
-};
888
-
889
-void tcg_out_br(TCGContext *s, TCGLabel *l)
890
-{
891
- tgen_brcond(s, TCG_TYPE_I32, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, l);
892
-}
893
-
894
-static void tgen_movcond(TCGContext *s, TCGType type, TCGCond cond,
895
- TCGReg ret, TCGReg c1, TCGArg c2, bool const_c2,
896
- TCGArg v1, bool const_v1, TCGArg v2, bool const_v2)
897
-{
898
- int tmpflags;
899
- bool eqz;
900
-
901
- /* If one of the values is zero, put it last to match SEL*Z instructions */
902
- if (use_mips32r6_instructions && v1 == 0) {
903
- v1 = v2;
904
- v2 = 0;
905
- cond = tcg_invert_cond(cond);
906
- }
907
-
908
- tmpflags = tcg_out_setcond_int(s, cond, TCG_TMP0, c1, c2);
909
- c1 = tmpflags & ~SETCOND_FLAGS;
910
- eqz = tmpflags & SETCOND_INV;
911
-
912
- if (use_mips32r6_instructions) {
913
- MIPSInsn m_opc_t = eqz ? OPC_SELEQZ : OPC_SELNEZ;
914
- MIPSInsn m_opc_f = eqz ? OPC_SELNEZ : OPC_SELEQZ;
915
-
916
- if (v2 != 0) {
917
- tcg_out_opc_reg(s, m_opc_f, TCG_TMP1, v2, c1);
918
- }
919
- tcg_out_opc_reg(s, m_opc_t, ret, v1, c1);
920
- if (v2 != 0) {
921
- tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP1);
922
- }
923
- return;
924
- }
925
-
926
- /* This should be guaranteed via constraints */
927
- tcg_debug_assert(v2 == ret);
928
-
929
- if (use_movnz_instructions) {
930
- MIPSInsn m_opc = eqz ? OPC_MOVZ : OPC_MOVN;
931
- tcg_out_opc_reg(s, m_opc, ret, v1, c1);
932
- } else {
933
- /* Invert the condition in order to branch over the move. */
934
- MIPSInsn b_opc = eqz ? OPC_BNE : OPC_BEQ;
935
- tcg_out_opc_imm(s, b_opc, c1, TCG_REG_ZERO, 2);
936
- tcg_out_nop(s);
937
- /* Open-code tcg_out_mov, without the nop-move check. */
938
- tcg_out_opc_reg(s, OPC_OR, ret, v1, TCG_REG_ZERO);
939
- }
940
-}
941
-
942
-static const TCGOutOpMovcond outop_movcond = {
943
- .base.static_constraint = (use_mips32r6_instructions
944
- ? C_O1_I4(r, r, rz, rz, rz)
945
- : C_O1_I4(r, r, rz, rz, 0)),
946
- .out = tgen_movcond,
947
-};
948
-
949
-static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail)
950
-{
951
- /*
952
- * Note that __mips_abicalls requires the called function's address
953
- * to be loaded into $25 (t9), even if a direct branch is in range.
954
- *
955
- * We can re-use helper addresses often; always drop the pointer
956
- * into the constant pool.
957
- */
958
- tcg_out_movi_pool(s, TCG_REG_T9, (uintptr_t)arg, TCG_REG_TB);
959
-
960
- if (tail) {
961
- if (!tcg_out_opc_jmp(s, OPC_J, arg)) {
962
- tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_T9, 0);
963
- }
964
- } else {
965
- if (!tcg_out_opc_jmp(s, OPC_JAL, arg)) {
966
- tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
967
- }
968
- }
969
-}
970
-
971
-static void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg,
972
- const TCGHelperInfo *info)
973
-{
974
- tcg_out_call_int(s, arg, false);
975
- tcg_out_nop(s);
976
-}
977
-
978
-/* We have four temps, we might as well expose three of them. */
979
-static const TCGLdstHelperParam ldst_helper_param = {
980
- .ntmp = 3, .tmp = { TCG_TMP0, TCG_TMP1, TCG_TMP2 }
981
-};
982
-
983
-static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
984
-{
985
- const tcg_insn_unit *tgt_rx = tcg_splitwx_to_rx(s->code_ptr);
986
- MemOp opc = get_memop(l->oi);
987
-
988
- /* resolve label address */
989
- if (!reloc_pc16(l->label_ptr[0], tgt_rx)
990
- || (l->label_ptr[1] && !reloc_pc16(l->label_ptr[1], tgt_rx))) {
991
- return false;
992
- }
993
-
994
- tcg_out_ld_helper_args(s, l, &ldst_helper_param);
995
-
996
- tcg_out_call_int(s, qemu_ld_helpers[opc & MO_SSIZE], false);
997
- /* delay slot */
998
- tcg_out_nop(s);
999
-
1000
- tcg_out_ld_helper_ret(s, l, true, &ldst_helper_param);
1001
-
1002
- tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
1003
- if (!reloc_pc16(s->code_ptr - 1, l->raddr)) {
1004
- return false;
1005
- }
1006
-
1007
- /* delay slot */
1008
- tcg_out_nop(s);
1009
- return true;
1010
-}
1011
-
1012
-static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1013
-{
1014
- const tcg_insn_unit *tgt_rx = tcg_splitwx_to_rx(s->code_ptr);
1015
- MemOp opc = get_memop(l->oi);
1016
-
1017
- /* resolve label address */
1018
- if (!reloc_pc16(l->label_ptr[0], tgt_rx)
1019
- || (l->label_ptr[1] && !reloc_pc16(l->label_ptr[1], tgt_rx))) {
1020
- return false;
1021
- }
1022
-
1023
- tcg_out_st_helper_args(s, l, &ldst_helper_param);
1024
-
1025
- tcg_out_call_int(s, qemu_st_helpers[opc & MO_SIZE], false);
1026
- /* delay slot */
1027
- tcg_out_nop(s);
1028
-
1029
- tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
1030
- if (!reloc_pc16(s->code_ptr - 1, l->raddr)) {
1031
- return false;
1032
- }
1033
-
1034
- /* delay slot */
1035
- tcg_out_nop(s);
1036
- return true;
1037
-}
1038
-
1039
-typedef struct {
1040
- TCGReg base;
1041
- TCGAtomAlign aa;
1042
-} HostAddress;
1043
-
1044
-bool tcg_target_has_memory_bswap(MemOp memop)
1045
-{
1046
- return false;
1047
-}
1048
-
1049
-/* We expect to use a 16-bit negative offset from ENV. */
1050
-#define MIN_TLB_MASK_TABLE_OFS -32768
1051
-
1052
-/*
1053
- * For system-mode, perform the TLB load and compare.
1054
- * For user-mode, perform any required alignment tests.
1055
- * In both cases, return a TCGLabelQemuLdst structure if the slow path
1056
- * is required and fill in @h with the host address for the fast path.
1057
- */
1058
-static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
1059
- TCGReg addr, MemOpIdx oi, bool is_ld)
1060
-{
1061
- TCGType addr_type = s->addr_type;
1062
- TCGLabelQemuLdst *ldst = NULL;
1063
- MemOp opc = get_memop(oi);
1064
- MemOp a_bits;
1065
- unsigned s_bits = opc & MO_SIZE;
1066
- unsigned a_mask;
1067
- TCGReg base;
1068
-
1069
- h->aa = atom_and_align_for_opc(s, opc, MO_ATOM_IFALIGN, false);
1070
- a_bits = h->aa.align;
1071
- a_mask = (1 << a_bits) - 1;
1072
-
1073
- if (tcg_use_softmmu) {
1074
- unsigned s_mask = (1 << s_bits) - 1;
1075
- int mem_index = get_mmuidx(oi);
1076
- int fast_off = tlb_mask_table_ofs(s, mem_index);
1077
- int mask_off = fast_off + offsetof(CPUTLBDescFast, mask);
1078
- int table_off = fast_off + offsetof(CPUTLBDescFast, table);
1079
- int add_off = offsetof(CPUTLBEntry, addend);
1080
- int cmp_off = is_ld ? offsetof(CPUTLBEntry, addr_read)
1081
- : offsetof(CPUTLBEntry, addr_write);
1082
-
1083
- ldst = new_ldst_label(s);
1084
- ldst->is_ld = is_ld;
1085
- ldst->oi = oi;
1086
- ldst->addr_reg = addr;
1087
-
1088
- /* Load tlb_mask[mmu_idx] and tlb_table[mmu_idx]. */
1089
- tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_AREG0, mask_off);
1090
- tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP1, TCG_AREG0, table_off);
1091
-
1092
- /* Extract the TLB index from the address into TMP3. */
1093
- if (addr_type == TCG_TYPE_I32) {
1094
- tcg_out_opc_sa(s, OPC_SRL, TCG_TMP3, addr,
1095
- TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
1096
- } else {
1097
- tcg_out_dsrl(s, TCG_TMP3, addr, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
1098
- }
1099
- tcg_out_opc_reg(s, OPC_AND, TCG_TMP3, TCG_TMP3, TCG_TMP0);
1100
-
1101
- /* Add the tlb_table pointer, creating the CPUTLBEntry address. */
1102
- tcg_out_opc_reg(s, OPC_DADDU, TCG_TMP3, TCG_TMP3, TCG_TMP1);
1103
-
1104
- /* Load the tlb comparator. */
1105
- if (addr_type == TCG_TYPE_I32) {
1106
- tcg_out_ld(s, TCG_TYPE_I32, TCG_TMP0, TCG_TMP3,
1107
- cmp_off + HOST_BIG_ENDIAN * 4);
1108
- } else {
1109
- tcg_out_ld(s, TCG_TYPE_REG, TCG_TMP0, TCG_TMP3, cmp_off);
1110
- }
1111
-
1112
- /* Load the tlb addend for the fast path. */
1113
- tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP3, TCG_TMP3, add_off);
1114
-
1115
- /*
1116
- * Mask the page bits, keeping the alignment bits to compare against.
1117
- * For unaligned accesses, compare against the end of the access to
1118
- * verify that it does not cross a page boundary.
1119
- */
1120
- tcg_out_movi(s, addr_type, TCG_TMP1, TARGET_PAGE_MASK | a_mask);
1121
- if (a_mask < s_mask) {
1122
- tcg_out_opc_imm(s, (addr_type == TCG_TYPE_I32
1123
- ? OPC_ADDIU : OPC_DADDIU),
1124
- TCG_TMP2, addr, s_mask - a_mask);
1125
- tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, TCG_TMP2);
1126
- } else {
1127
- tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, addr);
1128
- }
1129
-
1130
- /* Zero extend a 32-bit guest address for a 64-bit host. */
1131
- if (addr_type == TCG_TYPE_I32) {
1132
- tcg_out_ext32u(s, TCG_TMP2, addr);
1133
- addr = TCG_TMP2;
1134
- }
1135
-
1136
- ldst->label_ptr[0] = s->code_ptr;
1137
- tcg_out_opc_br(s, OPC_BNE, TCG_TMP1, TCG_TMP0);
1138
-
1139
- /* delay slot */
1140
- base = TCG_TMP3;
1141
- tcg_out_opc_reg(s, OPC_DADDU, base, TCG_TMP3, addr);
1142
- } else {
1143
- if (a_mask && (use_mips32r6_instructions || a_bits != s_bits)) {
1144
- ldst = new_ldst_label(s);
1145
-
1146
- ldst->is_ld = is_ld;
1147
- ldst->oi = oi;
1148
- ldst->addr_reg = addr;
1149
-
1150
- /* We are expecting a_bits to max out at 7, much lower than ANDI. */
1151
- tcg_debug_assert(a_bits < 16);
1152
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, addr, a_mask);
1153
-
1154
- ldst->label_ptr[0] = s->code_ptr;
1155
- if (use_mips32r6_instructions) {
1156
- tcg_out_opc_br(s, OPC_BNEZALC_R6, TCG_REG_ZERO, TCG_TMP0);
1157
- } else {
1158
- tcg_out_opc_br(s, OPC_BNEL, TCG_TMP0, TCG_REG_ZERO);
1159
- tcg_out_nop(s);
1160
- }
1161
- }
1162
-
1163
- base = addr;
1164
- if (addr_type == TCG_TYPE_I32) {
1165
- tcg_out_ext32u(s, TCG_REG_A0, base);
1166
- base = TCG_REG_A0;
1167
- }
1168
- if (guest_base) {
1169
- if (guest_base == (int16_t)guest_base) {
1170
- tcg_out_opc_imm(s, OPC_DADDIU, TCG_REG_A0, base, guest_base);
1171
- } else {
1172
- tcg_out_opc_reg(s, OPC_DADDU, TCG_REG_A0, base,
1173
- TCG_GUEST_BASE_REG);
1174
- }
1175
- base = TCG_REG_A0;
1176
- }
1177
- }
1178
-
1179
- h->base = base;
1180
- return ldst;
1181
-}
1182
-
1183
-static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi,
1184
- TCGReg base, MemOp opc, TCGType type)
1185
-{
1186
- switch (opc & MO_SSIZE) {
1187
- case MO_UB:
1188
- tcg_out_opc_imm(s, OPC_LBU, lo, base, 0);
1189
- break;
1190
- case MO_SB:
1191
- tcg_out_opc_imm(s, OPC_LB, lo, base, 0);
1192
- break;
1193
- case MO_UW:
1194
- tcg_out_opc_imm(s, OPC_LHU, lo, base, 0);
1195
- break;
1196
- case MO_SW:
1197
- tcg_out_opc_imm(s, OPC_LH, lo, base, 0);
1198
- break;
1199
- case MO_UL:
1200
- if (type == TCG_TYPE_I64) {
1201
- tcg_out_opc_imm(s, OPC_LWU, lo, base, 0);
1202
- break;
1203
- }
1204
- /* FALLTHRU */
1205
- case MO_SL:
1206
- tcg_out_opc_imm(s, OPC_LW, lo, base, 0);
1207
- break;
1208
- case MO_UQ:
1209
- tcg_out_opc_imm(s, OPC_LD, lo, base, 0);
1210
- break;
1211
- default:
1212
- g_assert_not_reached();
1213
- }
1214
-}
1215
-
1216
-static void tcg_out_qemu_ld_unalign(TCGContext *s, TCGReg lo, TCGReg hi,
1217
- TCGReg base, MemOp opc, TCGType type)
1218
-{
1219
- const MIPSInsn lw1 = HOST_BIG_ENDIAN ? OPC_LWL : OPC_LWR;
1220
- const MIPSInsn lw2 = HOST_BIG_ENDIAN ? OPC_LWR : OPC_LWL;
1221
- const MIPSInsn ld1 = HOST_BIG_ENDIAN ? OPC_LDL : OPC_LDR;
1222
- const MIPSInsn ld2 = HOST_BIG_ENDIAN ? OPC_LDR : OPC_LDL;
1223
- bool sgn = opc & MO_SIGN;
1224
-
1225
- switch (opc & MO_SIZE) {
1226
- case MO_16:
1227
- if (HOST_BIG_ENDIAN) {
1228
- tcg_out_opc_imm(s, sgn ? OPC_LB : OPC_LBU, TCG_TMP0, base, 0);
1229
- tcg_out_opc_imm(s, OPC_LBU, lo, base, 1);
1230
- if (use_mips32r2_instructions) {
1231
- tcg_out_opc_bf(s, OPC_INS, lo, TCG_TMP0, 31, 8);
1232
- } else {
1233
- tcg_out_opc_sa(s, OPC_SLL, TCG_TMP0, TCG_TMP0, 8);
1234
- tcg_out_opc_reg(s, OPC_OR, lo, lo, TCG_TMP0);
1235
- }
1236
- } else if (use_mips32r2_instructions && lo != base) {
1237
- tcg_out_opc_imm(s, OPC_LBU, lo, base, 0);
1238
- tcg_out_opc_imm(s, sgn ? OPC_LB : OPC_LBU, TCG_TMP0, base, 1);
1239
- tcg_out_opc_bf(s, OPC_INS, lo, TCG_TMP0, 31, 8);
1240
- } else {
1241
- tcg_out_opc_imm(s, OPC_LBU, TCG_TMP0, base, 0);
1242
- tcg_out_opc_imm(s, sgn ? OPC_LB : OPC_LBU, TCG_TMP1, base, 1);
1243
- tcg_out_opc_sa(s, OPC_SLL, TCG_TMP1, TCG_TMP1, 8);
1244
- tcg_out_opc_reg(s, OPC_OR, lo, TCG_TMP0, TCG_TMP1);
1245
- }
1246
- break;
1247
-
1248
- case MO_32:
1249
- tcg_out_opc_imm(s, lw1, lo, base, 0);
1250
- tcg_out_opc_imm(s, lw2, lo, base, 3);
1251
- if (type == TCG_TYPE_I64 && !sgn) {
1252
- tcg_out_ext32u(s, lo, lo);
1253
- }
1254
- break;
1255
-
1256
- case MO_64:
1257
- tcg_out_opc_imm(s, ld1, lo, base, 0);
1258
- tcg_out_opc_imm(s, ld2, lo, base, 7);
1259
- break;
1260
-
1261
- default:
1262
- g_assert_not_reached();
1263
- }
1264
-}
1265
-
1266
-static void tgen_qemu_ld(TCGContext *s, TCGType type, TCGReg data,
1267
- TCGReg addr, MemOpIdx oi)
1268
-{
1269
- MemOp opc = get_memop(oi);
1270
- TCGLabelQemuLdst *ldst;
1271
- HostAddress h;
1272
-
1273
- ldst = prepare_host_addr(s, &h, addr, oi, true);
1274
-
1275
- if (use_mips32r6_instructions || h.aa.align >= (opc & MO_SIZE)) {
1276
- tcg_out_qemu_ld_direct(s, data, 0, h.base, opc, type);
1277
- } else {
1278
- tcg_out_qemu_ld_unalign(s, data, 0, h.base, opc, type);
1279
- }
1280
-
1281
- if (ldst) {
1282
- ldst->type = type;
1283
- ldst->datalo_reg = data;
1284
- ldst->datahi_reg = 0;
1285
- ldst->raddr = tcg_splitwx_to_rx(s->code_ptr);
1286
- }
1287
-}
1288
-
1289
-static const TCGOutOpQemuLdSt outop_qemu_ld = {
1290
- .base.static_constraint = C_O1_I1(r, r),
1291
- .out = tgen_qemu_ld,
1292
-};
1293
-
1294
-static const TCGOutOpQemuLdSt2 outop_qemu_ld2 = {
1295
- .base.static_constraint = C_NotImplemented,
1296
-};
1297
-
1298
-static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg lo, TCGReg hi,
1299
- TCGReg base, MemOp opc)
1300
-{
1301
- switch (opc & MO_SIZE) {
1302
- case MO_8:
1303
- tcg_out_opc_imm(s, OPC_SB, lo, base, 0);
1304
- break;
1305
- case MO_16:
1306
- tcg_out_opc_imm(s, OPC_SH, lo, base, 0);
1307
- break;
1308
- case MO_32:
1309
- tcg_out_opc_imm(s, OPC_SW, lo, base, 0);
1310
- break;
1311
- case MO_64:
1312
- tcg_out_opc_imm(s, OPC_SD, lo, base, 0);
1313
- break;
1314
- default:
1315
- g_assert_not_reached();
1316
- }
1317
-}
1318
-
1319
-static void tcg_out_qemu_st_unalign(TCGContext *s, TCGReg lo, TCGReg hi,
1320
- TCGReg base, MemOp opc)
1321
-{
1322
- const MIPSInsn sw1 = HOST_BIG_ENDIAN ? OPC_SWL : OPC_SWR;
1323
- const MIPSInsn sw2 = HOST_BIG_ENDIAN ? OPC_SWR : OPC_SWL;
1324
- const MIPSInsn sd1 = HOST_BIG_ENDIAN ? OPC_SDL : OPC_SDR;
1325
- const MIPSInsn sd2 = HOST_BIG_ENDIAN ? OPC_SDR : OPC_SDL;
1326
-
1327
- switch (opc & MO_SIZE) {
1328
- case MO_16:
1329
- tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, lo, 8);
1330
- tcg_out_opc_imm(s, OPC_SB, HOST_BIG_ENDIAN ? TCG_TMP0 : lo, base, 0);
1331
- tcg_out_opc_imm(s, OPC_SB, HOST_BIG_ENDIAN ? lo : TCG_TMP0, base, 1);
1332
- break;
1333
-
1334
- case MO_32:
1335
- tcg_out_opc_imm(s, sw1, lo, base, 0);
1336
- tcg_out_opc_imm(s, sw2, lo, base, 3);
1337
- break;
1338
-
1339
- case MO_64:
1340
- tcg_out_opc_imm(s, sd1, lo, base, 0);
1341
- tcg_out_opc_imm(s, sd2, lo, base, 7);
1342
- break;
1343
-
1344
- default:
1345
- g_assert_not_reached();
1346
- }
1347
-}
1348
-
1349
-static void tgen_qemu_st(TCGContext *s, TCGType type, TCGReg data,
1350
- TCGReg addr, MemOpIdx oi)
1351
-{
1352
- MemOp opc = get_memop(oi);
1353
- TCGLabelQemuLdst *ldst;
1354
- HostAddress h;
1355
-
1356
- ldst = prepare_host_addr(s, &h, addr, oi, false);
1357
-
1358
- if (use_mips32r6_instructions || h.aa.align >= (opc & MO_SIZE)) {
1359
- tcg_out_qemu_st_direct(s, data, 0, h.base, opc);
1360
- } else {
1361
- tcg_out_qemu_st_unalign(s, data, 0, h.base, opc);
1362
- }
1363
-
1364
- if (ldst) {
1365
- ldst->type = type;
1366
- ldst->datalo_reg = data;
1367
- ldst->datahi_reg = 0;
1368
- ldst->raddr = tcg_splitwx_to_rx(s->code_ptr);
1369
- }
1370
-}
1371
-
1372
-static const TCGOutOpQemuLdSt outop_qemu_st = {
1373
- .base.static_constraint = C_O0_I2(rz, r),
1374
- .out = tgen_qemu_st,
1375
-};
1376
-
1377
-static const TCGOutOpQemuLdSt2 outop_qemu_st2 = {
1378
- .base.static_constraint = C_NotImplemented,
1379
-};
1380
-
1381
-static void tcg_out_mb(TCGContext *s, unsigned a0)
1382
-{
1383
- static const MIPSInsn sync[] = {
1384
- /* Note that SYNC_MB is a slightly weaker than SYNC 0,
1385
- as the former is an ordering barrier and the latter
1386
- is a completion barrier. */
1387
- [0 ... TCG_MO_ALL] = OPC_SYNC_MB,
1388
- [TCG_MO_LD_LD] = OPC_SYNC_RMB,
1389
- [TCG_MO_ST_ST] = OPC_SYNC_WMB,
1390
- [TCG_MO_LD_ST] = OPC_SYNC_RELEASE,
1391
- [TCG_MO_LD_ST | TCG_MO_ST_ST] = OPC_SYNC_RELEASE,
1392
- [TCG_MO_LD_ST | TCG_MO_LD_LD] = OPC_SYNC_ACQUIRE,
1393
- };
1394
- tcg_out32(s, sync[a0 & TCG_MO_ALL]);
1395
-}
1396
-
1397
-static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
1398
-{
1399
- TCGReg base = TCG_REG_ZERO;
1400
- int16_t lo = 0;
1401
-
1402
- if (a0) {
1403
- intptr_t ofs = tcg_tbrel_diff(s, (void *)a0);
1404
- lo = ofs;
1405
- if (ofs == lo) {
1406
- base = TCG_REG_TB;
1407
- } else {
1408
- base = TCG_REG_V0;
1409
- tcg_out_movi(s, TCG_TYPE_PTR, base, ofs - lo);
1410
- tcg_out_opc_reg(s, OPC_DADDU, base, base, TCG_REG_TB);
1411
- }
1412
- }
1413
- if (!tcg_out_opc_jmp(s, OPC_J, tb_ret_addr)) {
1414
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, (uintptr_t)tb_ret_addr);
1415
- tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
1416
- }
1417
- /* delay slot */
1418
- tcg_out_opc_imm(s, OPC_DADDIU, TCG_REG_V0, base, lo);
1419
-}
1420
-
1421
-static void tcg_out_goto_tb(TCGContext *s, int which)
1422
-{
1423
- intptr_t ofs = get_jmp_target_addr(s, which);
1424
- TCGReg base, dest;
1425
-
1426
- /* indirect jump method */
1427
- dest = TCG_REG_TB;
1428
- base = TCG_REG_TB;
1429
- ofs = tcg_tbrel_diff(s, (void *)ofs);
1430
- tcg_out_ld(s, TCG_TYPE_PTR, dest, base, ofs);
1431
- tcg_out_opc_reg(s, OPC_JR, 0, dest, 0);
1432
- /* delay slot */
1433
- tcg_out_nop(s);
1434
-
1435
- set_jmp_reset_offset(s, which);
1436
- /* For the unlinked case, need to reset TCG_REG_TB. */
1437
- tcg_out_ldst(s, OPC_DADDIU, TCG_REG_TB, TCG_REG_TB,
1438
- -tcg_current_code_size(s));
1439
-}
1440
-
1441
-static void tcg_out_goto_ptr(TCGContext *s, TCGReg a0)
1442
-{
1443
- tcg_out_opc_reg(s, OPC_JR, 0, a0, 0);
1444
- tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_TB, a0);
1445
-}
1446
-
1447
-void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
1448
- uintptr_t jmp_rx, uintptr_t jmp_rw)
1449
-{
1450
- /* Always indirect, nothing to do */
1451
-}
1452
-
1453
-
1454
-static void tgen_add(TCGContext *s, TCGType type,
1455
- TCGReg a0, TCGReg a1, TCGReg a2)
1456
-{
1457
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_ADDU : OPC_DADDU;
1458
- tcg_out_opc_reg(s, insn, a0, a1, a2);
1459
-}
1460
-
1461
-static void tgen_addi(TCGContext *s, TCGType type,
1462
- TCGReg a0, TCGReg a1, tcg_target_long a2)
1463
-{
1464
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_ADDIU : OPC_DADDIU;
1465
- tcg_out_opc_imm(s, insn, a0, a1, a2);
1466
-}
1467
-
1468
-static const TCGOutOpBinary outop_add = {
1469
- .base.static_constraint = C_O1_I2(r, r, rJ),
1470
- .out_rrr = tgen_add,
1471
- .out_rri = tgen_addi,
1472
-};
1473
-
1474
-static const TCGOutOpBinary outop_addco = {
1475
- .base.static_constraint = C_NotImplemented,
1476
-};
1477
-
1478
-static const TCGOutOpAddSubCarry outop_addci = {
1479
- .base.static_constraint = C_NotImplemented,
1480
-};
1481
-
1482
-static const TCGOutOpBinary outop_addcio = {
1483
- .base.static_constraint = C_NotImplemented,
1484
-};
1485
-
1486
-static void tcg_out_set_carry(TCGContext *s)
1487
-{
1488
- g_assert_not_reached();
1489
-}
1490
-
1491
-static void tgen_and(TCGContext *s, TCGType type,
1492
- TCGReg a0, TCGReg a1, TCGReg a2)
1493
-{
1494
- tcg_out_opc_reg(s, OPC_AND, a0, a1, a2);
1495
-}
1496
-
1497
-static void tgen_andi(TCGContext *s, TCGType type,
1498
- TCGReg a0, TCGReg a1, tcg_target_long a2)
1499
-{
1500
- int msb;
1501
-
1502
- if (a2 == (uint16_t)a2) {
1503
- tcg_out_opc_imm(s, OPC_ANDI, a0, a1, a2);
1504
- return;
1505
- }
1506
-
1507
- tcg_debug_assert(use_mips32r2_instructions);
1508
- tcg_debug_assert(is_p2m1(a2));
1509
- msb = ctz64(~a2) - 1;
1510
- if (type == TCG_TYPE_I32) {
1511
- tcg_out_opc_bf(s, OPC_EXT, a0, a1, msb, 0);
1512
- } else {
1513
- tcg_out_opc_bf64(s, OPC_DEXT, OPC_DEXTM, OPC_DEXTU, a0, a1, msb, 0);
1514
- }
1515
-}
1516
-
1517
-static const TCGOutOpBinary outop_and = {
1518
- .base.static_constraint = C_O1_I2(r, r, rIK),
1519
- .out_rrr = tgen_and,
1520
- .out_rri = tgen_andi,
1521
-};
1522
-
1523
-static const TCGOutOpBinary outop_andc = {
1524
- .base.static_constraint = C_NotImplemented,
1525
-};
1526
-
1527
-static void tgen_clz(TCGContext *s, TCGType type,
1528
- TCGReg a0, TCGReg a1, TCGReg a2)
1529
-{
1530
- if (use_mips32r6_instructions) {
1531
- MIPSInsn opcv6 = type == TCG_TYPE_I32 ? OPC_CLZ_R6 : OPC_DCLZ_R6;
1532
- tcg_out_opc_reg(s, opcv6, TCG_TMP0, a1, 0);
1533
- tgen_movcond(s, TCG_TYPE_REG, TCG_COND_EQ, a0, a1, a2, false,
1534
- TCG_TMP0, false, TCG_REG_ZERO, false);
1535
- } else {
1536
- MIPSInsn opcv2 = type == TCG_TYPE_I32 ? OPC_CLZ : OPC_DCLZ;
1537
- if (a0 == a2) {
1538
- tcg_out_opc_reg(s, opcv2, TCG_TMP0, a1, a1);
1539
- tcg_out_opc_reg(s, OPC_MOVN, a0, TCG_TMP0, a1);
1540
- } else if (a0 != a1) {
1541
- tcg_out_opc_reg(s, opcv2, a0, a1, a1);
1542
- tcg_out_opc_reg(s, OPC_MOVZ, a0, a2, a1);
1543
- } else {
1544
- tcg_out_opc_reg(s, opcv2, TCG_TMP0, a1, a1);
1545
- tcg_out_opc_reg(s, OPC_MOVZ, TCG_TMP0, a2, a1);
1546
- tcg_out_mov(s, type, a0, TCG_TMP0);
1547
- }
1548
- }
1549
-}
1550
-
1551
-static void tgen_clzi(TCGContext *s, TCGType type,
1552
- TCGReg a0, TCGReg a1, tcg_target_long a2)
1553
-{
1554
- if (a2 == 0) {
1555
- tgen_clz(s, type, a0, a1, TCG_REG_ZERO);
1556
- } else if (use_mips32r6_instructions) {
1557
- MIPSInsn opcv6 = type == TCG_TYPE_I32 ? OPC_CLZ_R6 : OPC_DCLZ_R6;
1558
- tcg_out_opc_reg(s, opcv6, a0, a1, 0);
1559
- } else {
1560
- MIPSInsn opcv2 = type == TCG_TYPE_I32 ? OPC_CLZ : OPC_DCLZ;
1561
- tcg_out_opc_reg(s, opcv2, a0, a1, a1);
1562
- }
1563
-}
1564
-
1565
-static TCGConstraintSetIndex cset_clz(TCGType type, unsigned flags)
1566
-{
1567
- return use_mips32r2_instructions ? C_O1_I2(r, r, rzW) : C_NotImplemented;
1568
-}
1569
-
1570
-static const TCGOutOpBinary outop_clz = {
1571
- .base.static_constraint = C_Dynamic,
1572
- .base.dynamic_constraint = cset_clz,
1573
- .out_rrr = tgen_clz,
1574
- .out_rri = tgen_clzi,
1575
-};
1576
-
1577
-static const TCGOutOpUnary outop_ctpop = {
1578
- .base.static_constraint = C_NotImplemented,
1579
-};
1580
-
1581
-static const TCGOutOpBinary outop_ctz = {
1582
- .base.static_constraint = C_NotImplemented,
1583
-};
1584
-
1585
-static void tgen_divs(TCGContext *s, TCGType type,
1586
- TCGReg a0, TCGReg a1, TCGReg a2)
1587
-{
1588
- if (use_mips32r6_instructions) {
1589
- if (type == TCG_TYPE_I32) {
1590
- tcg_out_opc_reg(s, OPC_DIV_R6, a0, a1, a2);
1591
- } else {
1592
- tcg_out_opc_reg(s, OPC_DDIV_R6, a0, a1, a2);
1593
- }
1594
- } else {
1595
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_DIV : OPC_DDIV;
1596
- tcg_out_opc_reg(s, insn, 0, a1, a2);
1597
- tcg_out_opc_reg(s, OPC_MFLO, a0, 0, 0);
1598
- }
1599
-}
1600
-
1601
-static const TCGOutOpBinary outop_divs = {
1602
- .base.static_constraint = C_O1_I2(r, r, r),
1603
- .out_rrr = tgen_divs,
1604
-};
1605
-
1606
-static const TCGOutOpDivRem outop_divs2 = {
1607
- .base.static_constraint = C_NotImplemented,
1608
-};
1609
-
1610
-static void tgen_divu(TCGContext *s, TCGType type,
1611
- TCGReg a0, TCGReg a1, TCGReg a2)
1612
-{
1613
- if (use_mips32r6_instructions) {
1614
- if (type == TCG_TYPE_I32) {
1615
- tcg_out_opc_reg(s, OPC_DIVU_R6, a0, a1, a2);
1616
- } else {
1617
- tcg_out_opc_reg(s, OPC_DDIVU_R6, a0, a1, a2);
1618
- }
1619
- } else {
1620
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_DIVU : OPC_DDIVU;
1621
- tcg_out_opc_reg(s, insn, 0, a1, a2);
1622
- tcg_out_opc_reg(s, OPC_MFLO, a0, 0, 0);
1623
- }
1624
-}
1625
-
1626
-static const TCGOutOpBinary outop_divu = {
1627
- .base.static_constraint = C_O1_I2(r, r, r),
1628
- .out_rrr = tgen_divu,
1629
-};
1630
-
1631
-static const TCGOutOpDivRem outop_divu2 = {
1632
- .base.static_constraint = C_NotImplemented,
1633
-};
1634
-
1635
-static const TCGOutOpBinary outop_eqv = {
1636
- .base.static_constraint = C_NotImplemented,
1637
-};
1638
-
1639
-static void tgen_extrh_i64_i32(TCGContext *s, TCGType t, TCGReg a0, TCGReg a1)
1640
-{
1641
- tcg_out_dsra(s, a0, a1, 32);
1642
-}
1643
-
1644
-static const TCGOutOpUnary outop_extrh_i64_i32 = {
1645
- .base.static_constraint = C_O1_I1(r, r),
1646
- .out_rr = tgen_extrh_i64_i32,
1647
-};
1648
-
1649
-static void tgen_mul(TCGContext *s, TCGType type,
1650
- TCGReg a0, TCGReg a1, TCGReg a2)
1651
-{
1652
- MIPSInsn insn;
1653
-
1654
- if (type == TCG_TYPE_I32) {
1655
- if (use_mips32_instructions) {
1656
- tcg_out_opc_reg(s, OPC_MUL, a0, a1, a2);
1657
- return;
1658
- }
1659
- insn = OPC_MULT;
1660
- } else {
1661
- if (use_mips32r6_instructions) {
1662
- tcg_out_opc_reg(s, OPC_DMUL, a0, a1, a2);
1663
- return;
1664
- }
1665
- insn = OPC_DMULT;
1666
- }
1667
- tcg_out_opc_reg(s, insn, 0, a1, a2);
1668
- tcg_out_opc_reg(s, OPC_MFLO, a0, 0, 0);
1669
-}
1670
-
1671
-static const TCGOutOpBinary outop_mul = {
1672
- .base.static_constraint = C_O1_I2(r, r, r),
1673
- .out_rrr = tgen_mul,
1674
-};
1675
-
1676
-static void tgen_muls2(TCGContext *s, TCGType type,
1677
- TCGReg a0, TCGReg a1, TCGReg a2, TCGReg a3)
1678
-{
1679
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_MULT : OPC_DMULT;
1680
- tcg_out_opc_reg(s, insn, 0, a2, a3);
1681
- tcg_out_opc_reg(s, OPC_MFLO, a0, 0, 0);
1682
- tcg_out_opc_reg(s, OPC_MFHI, a1, 0, 0);
1683
-}
1684
-
1685
-static TCGConstraintSetIndex cset_mul2(TCGType type, unsigned flags)
1686
-{
1687
- return use_mips32r6_instructions ? C_NotImplemented : C_O2_I2(r, r, r, r);
1688
-}
1689
-
1690
-static const TCGOutOpMul2 outop_muls2 = {
1691
- .base.static_constraint = C_Dynamic,
1692
- .base.dynamic_constraint = cset_mul2,
1693
- .out_rrrr = tgen_muls2,
1694
-};
1695
-
1696
-static void tgen_mulsh(TCGContext *s, TCGType type,
1697
- TCGReg a0, TCGReg a1, TCGReg a2)
1698
-{
1699
- if (use_mips32r6_instructions) {
1700
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_MUH : OPC_DMUH;
1701
- tcg_out_opc_reg(s, insn, a0, a1, a2);
1702
- } else {
1703
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_MULT : OPC_DMULT;
1704
- tcg_out_opc_reg(s, insn, 0, a1, a2);
1705
- tcg_out_opc_reg(s, OPC_MFHI, a0, 0, 0);
1706
- }
1707
-}
1708
-
1709
-static const TCGOutOpBinary outop_mulsh = {
1710
- .base.static_constraint = C_O1_I2(r, r, r),
1711
- .out_rrr = tgen_mulsh,
1712
-};
1713
-
1714
-static void tgen_mulu2(TCGContext *s, TCGType type,
1715
- TCGReg a0, TCGReg a1, TCGReg a2, TCGReg a3)
1716
-{
1717
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_MULTU : OPC_DMULTU;
1718
- tcg_out_opc_reg(s, insn, 0, a2, a3);
1719
- tcg_out_opc_reg(s, OPC_MFLO, a0, 0, 0);
1720
- tcg_out_opc_reg(s, OPC_MFHI, a1, 0, 0);
1721
-}
1722
-
1723
-static const TCGOutOpMul2 outop_mulu2 = {
1724
- .base.static_constraint = C_Dynamic,
1725
- .base.dynamic_constraint = cset_mul2,
1726
- .out_rrrr = tgen_mulu2,
1727
-};
1728
-
1729
-static void tgen_muluh(TCGContext *s, TCGType type,
1730
- TCGReg a0, TCGReg a1, TCGReg a2)
1731
-{
1732
- if (use_mips32r6_instructions) {
1733
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_MUHU : OPC_DMUHU;
1734
- tcg_out_opc_reg(s, insn, a0, a1, a2);
1735
- } else {
1736
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_MULTU : OPC_DMULTU;
1737
- tcg_out_opc_reg(s, insn, 0, a1, a2);
1738
- tcg_out_opc_reg(s, OPC_MFHI, a0, 0, 0);
1739
- }
1740
-}
1741
-
1742
-static const TCGOutOpBinary outop_muluh = {
1743
- .base.static_constraint = C_O1_I2(r, r, r),
1744
- .out_rrr = tgen_muluh,
1745
-};
1746
-
1747
-static const TCGOutOpBinary outop_nand = {
1748
- .base.static_constraint = C_NotImplemented,
1749
-};
1750
-
1751
-static void tgen_nor(TCGContext *s, TCGType type,
1752
- TCGReg a0, TCGReg a1, TCGReg a2)
1753
-{
1754
- tcg_out_opc_reg(s, OPC_NOR, a0, a1, a2);
1755
-}
1756
-
1757
-static const TCGOutOpBinary outop_nor = {
1758
- .base.static_constraint = C_O1_I2(r, r, r),
1759
- .out_rrr = tgen_nor,
1760
-};
1761
-
1762
-static void tgen_or(TCGContext *s, TCGType type,
1763
- TCGReg a0, TCGReg a1, TCGReg a2)
1764
-{
1765
- tcg_out_opc_reg(s, OPC_OR, a0, a1, a2);
1766
-}
1767
-
1768
-static void tgen_ori(TCGContext *s, TCGType type,
1769
- TCGReg a0, TCGReg a1, tcg_target_long a2)
1770
-{
1771
- tcg_out_opc_imm(s, OPC_ORI, a0, a1, a2);
1772
-}
1773
-
1774
-static const TCGOutOpBinary outop_or = {
1775
- .base.static_constraint = C_O1_I2(r, r, rI),
1776
- .out_rrr = tgen_or,
1777
- .out_rri = tgen_ori,
1778
-};
1779
-
1780
-static const TCGOutOpBinary outop_orc = {
1781
- .base.static_constraint = C_NotImplemented,
1782
-};
1783
-
1784
-static void tgen_rems(TCGContext *s, TCGType type,
1785
- TCGReg a0, TCGReg a1, TCGReg a2)
1786
-{
1787
- if (use_mips32r6_instructions) {
1788
- if (type == TCG_TYPE_I32) {
1789
- tcg_out_opc_reg(s, OPC_MOD, a0, a1, a2);
1790
- } else {
1791
- tcg_out_opc_reg(s, OPC_DMOD, a0, a1, a2);
1792
- }
1793
- } else {
1794
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_DIV : OPC_DDIV;
1795
- tcg_out_opc_reg(s, insn, 0, a1, a2);
1796
- tcg_out_opc_reg(s, OPC_MFHI, a0, 0, 0);
1797
- }
1798
-}
1799
-
1800
-static const TCGOutOpBinary outop_rems = {
1801
- .base.static_constraint = C_O1_I2(r, r, r),
1802
- .out_rrr = tgen_rems,
1803
-};
1804
-
1805
-static void tgen_remu(TCGContext *s, TCGType type,
1806
- TCGReg a0, TCGReg a1, TCGReg a2)
1807
-{
1808
- if (use_mips32r6_instructions) {
1809
- if (type == TCG_TYPE_I32) {
1810
- tcg_out_opc_reg(s, OPC_MODU, a0, a1, a2);
1811
- } else {
1812
- tcg_out_opc_reg(s, OPC_DMODU, a0, a1, a2);
1813
- }
1814
- } else {
1815
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_DIVU : OPC_DDIVU;
1816
- tcg_out_opc_reg(s, insn, 0, a1, a2);
1817
- tcg_out_opc_reg(s, OPC_MFHI, a0, 0, 0);
1818
- }
1819
-}
1820
-
1821
-static const TCGOutOpBinary outop_remu = {
1822
- .base.static_constraint = C_O1_I2(r, r, r),
1823
- .out_rrr = tgen_remu,
1824
-};
1825
-
1826
-static const TCGOutOpBinary outop_rotl = {
1827
- .base.static_constraint = C_NotImplemented,
1828
-};
1829
-
1830
-static TCGConstraintSetIndex cset_rotr(TCGType type, unsigned flags)
1831
-{
1832
- return use_mips32r2_instructions ? C_O1_I2(r, r, ri) : C_NotImplemented;
1833
-}
1834
-
1835
-static void tgen_rotr(TCGContext *s, TCGType type,
1836
- TCGReg a0, TCGReg a1, TCGReg a2)
1837
-{
1838
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_ROTRV : OPC_DROTRV;
1839
- tcg_out_opc_reg(s, insn, a0, a1, a2);
1840
-}
1841
-
1842
-static void tgen_rotri(TCGContext *s, TCGType type,
1843
- TCGReg a0, TCGReg a1, tcg_target_long a2)
1844
-{
1845
- if (type == TCG_TYPE_I32) {
1846
- tcg_out_opc_sa(s, OPC_ROTR, a0, a1, a2);
1847
- } else {
1848
- tcg_out_opc_sa64(s, OPC_DROTR, OPC_DROTR32, a0, a1, a2);
1849
- }
1850
-}
1851
-
1852
-static const TCGOutOpBinary outop_rotr = {
1853
- .base.static_constraint = C_Dynamic,
1854
- .base.dynamic_constraint = cset_rotr,
1855
- .out_rrr = tgen_rotr,
1856
- .out_rri = tgen_rotri,
1857
-};
1858
-
1859
-static void tgen_sar(TCGContext *s, TCGType type,
1860
- TCGReg a0, TCGReg a1, TCGReg a2)
1861
-{
1862
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_SRAV : OPC_DSRAV;
1863
- tcg_out_opc_reg(s, insn, a0, a1, a2);
1864
-}
1865
-
1866
-static void tgen_sari(TCGContext *s, TCGType type,
1867
- TCGReg a0, TCGReg a1, tcg_target_long a2)
1868
-{
1869
- if (type == TCG_TYPE_I32) {
1870
- tcg_out_opc_sa(s, OPC_SRA, a0, a1, a2);
1871
- } else {
1872
- tcg_out_dsra(s, a0, a1, a2);
1873
- }
1874
-}
1875
-
1876
-static const TCGOutOpBinary outop_sar = {
1877
- .base.static_constraint = C_O1_I2(r, r, ri),
1878
- .out_rrr = tgen_sar,
1879
- .out_rri = tgen_sari,
1880
-};
1881
-
1882
-static void tgen_shl(TCGContext *s, TCGType type,
1883
- TCGReg a0, TCGReg a1, TCGReg a2)
1884
-{
1885
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_SLLV : OPC_DSLLV;
1886
- tcg_out_opc_reg(s, insn, a0, a1, a2);
1887
-}
1888
-
1889
-static void tgen_shli(TCGContext *s, TCGType type,
1890
- TCGReg a0, TCGReg a1, tcg_target_long a2)
1891
-{
1892
- if (type == TCG_TYPE_I32) {
1893
- tcg_out_opc_sa(s, OPC_SLL, a0, a1, a2);
1894
- } else {
1895
- tcg_out_dsll(s, a0, a1, a2);
1896
- }
1897
-}
1898
-
1899
-static const TCGOutOpBinary outop_shl = {
1900
- .base.static_constraint = C_O1_I2(r, r, ri),
1901
- .out_rrr = tgen_shl,
1902
- .out_rri = tgen_shli,
1903
-};
1904
-
1905
-static void tgen_shr(TCGContext *s, TCGType type,
1906
- TCGReg a0, TCGReg a1, TCGReg a2)
1907
-{
1908
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_SRLV : OPC_DSRLV;
1909
- tcg_out_opc_reg(s, insn, a0, a1, a2);
1910
-}
1911
-
1912
-static void tgen_shri(TCGContext *s, TCGType type,
1913
- TCGReg a0, TCGReg a1, tcg_target_long a2)
1914
-{
1915
- if (type == TCG_TYPE_I32) {
1916
- tcg_out_opc_sa(s, OPC_SRL, a0, a1, a2);
1917
- } else {
1918
- tcg_out_dsrl(s, a0, a1, a2);
1919
- }
1920
-}
1921
-
1922
-static const TCGOutOpBinary outop_shr = {
1923
- .base.static_constraint = C_O1_I2(r, r, ri),
1924
- .out_rrr = tgen_shr,
1925
- .out_rri = tgen_shri,
1926
-};
1927
-
1928
-static void tgen_sub(TCGContext *s, TCGType type,
1929
- TCGReg a0, TCGReg a1, TCGReg a2)
1930
-{
1931
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_SUBU : OPC_DSUBU;
1932
- tcg_out_opc_reg(s, insn, a0, a1, a2);
1933
-}
1934
-
1935
-static const TCGOutOpSubtract outop_sub = {
1936
- .base.static_constraint = C_O1_I2(r, r, r),
1937
- .out_rrr = tgen_sub,
1938
-};
1939
-
1940
-static const TCGOutOpAddSubCarry outop_subbo = {
1941
- .base.static_constraint = C_NotImplemented,
1942
-};
1943
-
1944
-static const TCGOutOpAddSubCarry outop_subbi = {
1945
- .base.static_constraint = C_NotImplemented,
1946
-};
1947
-
1948
-static const TCGOutOpAddSubCarry outop_subbio = {
1949
- .base.static_constraint = C_NotImplemented,
1950
-};
1951
-
1952
-static void tcg_out_set_borrow(TCGContext *s)
1953
-{
1954
- g_assert_not_reached();
1955
-}
1956
-
1957
-static void tgen_xor(TCGContext *s, TCGType type,
1958
- TCGReg a0, TCGReg a1, TCGReg a2)
1959
-{
1960
- tcg_out_opc_reg(s, OPC_XOR, a0, a1, a2);
1961
-}
1962
-
1963
-static void tgen_xori(TCGContext *s, TCGType type,
1964
- TCGReg a0, TCGReg a1, tcg_target_long a2)
1965
-{
1966
- tcg_out_opc_imm(s, OPC_XORI, a0, a1, a2);
1967
-}
1968
-
1969
-static const TCGOutOpBinary outop_xor = {
1970
- .base.static_constraint = C_O1_I2(r, r, rI),
1971
- .out_rrr = tgen_xor,
1972
- .out_rri = tgen_xori,
1973
-};
1974
-
1975
-static void tgen_bswap16(TCGContext *s, TCGType type,
1976
- TCGReg ret, TCGReg arg, unsigned flags)
1977
-{
1978
- /* With arg = abcd: */
1979
- if (use_mips32r2_instructions) {
1980
- tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg); /* badc */
1981
- if (flags & TCG_BSWAP_OS) {
1982
- tcg_out_opc_reg(s, OPC_SEH, ret, 0, ret); /* ssdc */
1983
- } else if ((flags & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) {
1984
- tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xffff); /* 00dc */
1985
- }
1986
- return;
1987
- }
1988
-
1989
- tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8); /* 0abc */
1990
- if (!(flags & TCG_BSWAP_IZ)) {
1991
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, TCG_TMP0, 0x00ff); /* 000c */
1992
- }
1993
- if (flags & TCG_BSWAP_OS) {
1994
- tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24); /* d000 */
1995
- tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16); /* ssd0 */
1996
- } else {
1997
- tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8); /* bcd0 */
1998
- if (flags & TCG_BSWAP_OZ) {
1999
- tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00); /* 00d0 */
2000
- }
2001
- }
2002
- tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0); /* ssdc */
2003
-}
2004
-
2005
-static const TCGOutOpBswap outop_bswap16 = {
2006
- .base.static_constraint = C_O1_I1(r, r),
2007
- .out_rr = tgen_bswap16,
2008
-};
2009
-
2010
-static void tgen_bswap32(TCGContext *s, TCGType type,
2011
- TCGReg ret, TCGReg arg, unsigned flags)
2012
-{
2013
- if (use_mips32r2_instructions) {
2014
- tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
2015
- tcg_out_opc_sa(s, OPC_ROTR, ret, ret, 16);
2016
- if (flags & TCG_BSWAP_OZ) {
2017
- tcg_out_opc_bf(s, OPC_DEXT, ret, ret, 31, 0);
2018
- }
2019
- } else {
2020
- if (flags & TCG_BSWAP_OZ) {
2021
- tcg_out_bswap_subr(s, bswap32u_addr);
2022
- } else {
2023
- tcg_out_bswap_subr(s, bswap32_addr);
2024
- }
2025
- /* delay slot -- never omit the insn, like tcg_out_mov might. */
2026
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP0, arg, TCG_REG_ZERO);
2027
- tcg_out_mov(s, TCG_TYPE_I32, ret, TCG_TMP3);
2028
- }
2029
-}
2030
-
2031
-static const TCGOutOpBswap outop_bswap32 = {
2032
- .base.static_constraint = C_O1_I1(r, r),
2033
- .out_rr = tgen_bswap32,
2034
-};
2035
-
2036
-static void tgen_bswap64(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
2037
-{
2038
- if (use_mips32r2_instructions) {
2039
- tcg_out_opc_reg(s, OPC_DSBH, ret, 0, arg);
2040
- tcg_out_opc_reg(s, OPC_DSHD, ret, 0, ret);
2041
- } else {
2042
- tcg_out_bswap_subr(s, bswap64_addr);
2043
- /* delay slot -- never omit the insn, like tcg_out_mov might. */
2044
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP0, arg, TCG_REG_ZERO);
2045
- tcg_out_mov(s, TCG_TYPE_I32, ret, TCG_TMP3);
2046
- }
2047
-}
2048
-
2049
-static const TCGOutOpUnary outop_bswap64 = {
2050
- .base.static_constraint = C_O1_I1(r, r),
2051
- .out_rr = tgen_bswap64,
2052
-};
2053
-
2054
-static void tgen_neg(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1)
2055
-{
2056
- tgen_sub(s, type, a0, TCG_REG_ZERO, a1);
2057
-}
2058
-
2059
-static const TCGOutOpUnary outop_neg = {
2060
- .base.static_constraint = C_O1_I1(r, r),
2061
- .out_rr = tgen_neg,
2062
-};
2063
-
2064
-static void tgen_not(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1)
2065
-{
2066
- tgen_nor(s, type, a0, TCG_REG_ZERO, a1);
2067
-}
2068
-
2069
-static const TCGOutOpUnary outop_not = {
2070
- .base.static_constraint = C_O1_I1(r, r),
2071
- .out_rr = tgen_not,
2072
-};
2073
-
2074
-static void tgen_deposit(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
2075
- TCGReg a2, unsigned ofs, unsigned len)
2076
-{
2077
- if (type == TCG_TYPE_I32) {
2078
- tcg_out_opc_bf(s, OPC_INS, a0, a2, ofs + len - 1, ofs);
2079
- } else {
2080
- tcg_out_opc_bf64(s, OPC_DINS, OPC_DINSM, OPC_DINSU, a0, a2,
2081
- ofs + len - 1, ofs);
2082
- }
2083
-}
2084
-
2085
-static const TCGOutOpDeposit outop_deposit = {
2086
- .base.static_constraint = C_O1_I2(r, 0, rz),
2087
- .out_rrr = tgen_deposit,
2088
-};
2089
-
2090
-static void tgen_extract(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
2091
- unsigned ofs, unsigned len)
2092
-{
2093
- if (ofs == 0 && len <= 16) {
2094
- tcg_out_opc_imm(s, OPC_ANDI, a0, a1, (1 << len) - 1);
2095
- } else if (type == TCG_TYPE_I32) {
2096
- tcg_out_opc_bf(s, OPC_EXT, a0, a1, len - 1, ofs);
2097
- } else {
2098
- tcg_out_opc_bf64(s, OPC_DEXT, OPC_DEXTM, OPC_DEXTU,
2099
- a0, a1, len - 1, ofs);
2100
- }
2101
-}
2102
-
2103
-static const TCGOutOpExtract outop_extract = {
2104
- .base.static_constraint = C_O1_I1(r, r),
2105
- .out_rr = tgen_extract,
2106
-};
2107
-
2108
-static void tgen_sextract(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
2109
- unsigned ofs, unsigned len)
2110
-{
2111
- if (ofs == 0) {
2112
- switch (len) {
2113
- case 8:
2114
- tcg_out_ext8s(s, type, a0, a1);
2115
- return;
2116
- case 16:
2117
- tcg_out_ext16s(s, type, a0, a1);
2118
- return;
2119
- case 32:
2120
- tcg_out_ext32s(s, a0, a1);
2121
- return;
2122
- }
2123
- }
2124
- g_assert_not_reached();
2125
-}
2126
-
2127
-static const TCGOutOpExtract outop_sextract = {
2128
- .base.static_constraint = C_O1_I1(r, r),
2129
- .out_rr = tgen_sextract,
2130
-};
2131
-
2132
-static const TCGOutOpExtract2 outop_extract2 = {
2133
- .base.static_constraint = C_NotImplemented,
2134
-};
2135
-
2136
-static void tgen_ld8u(TCGContext *s, TCGType type, TCGReg dest,
2137
- TCGReg base, ptrdiff_t offset)
2138
-{
2139
- tcg_out_ldst(s, OPC_LBU, dest, base, offset);
2140
-}
2141
-
2142
-static const TCGOutOpLoad outop_ld8u = {
2143
- .base.static_constraint = C_O1_I1(r, r),
2144
- .out = tgen_ld8u,
2145
-};
2146
-
2147
-static void tgen_ld8s(TCGContext *s, TCGType type, TCGReg dest,
2148
- TCGReg base, ptrdiff_t offset)
2149
-{
2150
- tcg_out_ldst(s, OPC_LB, dest, base, offset);
2151
-}
2152
-
2153
-static const TCGOutOpLoad outop_ld8s = {
2154
- .base.static_constraint = C_O1_I1(r, r),
2155
- .out = tgen_ld8s,
2156
-};
2157
-
2158
-static void tgen_ld16u(TCGContext *s, TCGType type, TCGReg dest,
2159
- TCGReg base, ptrdiff_t offset)
2160
-{
2161
- tcg_out_ldst(s, OPC_LHU, dest, base, offset);
2162
-}
2163
-
2164
-static const TCGOutOpLoad outop_ld16u = {
2165
- .base.static_constraint = C_O1_I1(r, r),
2166
- .out = tgen_ld16u,
2167
-};
2168
-
2169
-static void tgen_ld16s(TCGContext *s, TCGType type, TCGReg dest,
2170
- TCGReg base, ptrdiff_t offset)
2171
-{
2172
- tcg_out_ldst(s, OPC_LH, dest, base, offset);
2173
-}
2174
-
2175
-static const TCGOutOpLoad outop_ld16s = {
2176
- .base.static_constraint = C_O1_I1(r, r),
2177
- .out = tgen_ld16s,
2178
-};
2179
-
2180
-static void tgen_ld32u(TCGContext *s, TCGType type, TCGReg dest,
2181
- TCGReg base, ptrdiff_t offset)
2182
-{
2183
- tcg_out_ldst(s, OPC_LWU, dest, base, offset);
2184
-}
2185
-
2186
-static const TCGOutOpLoad outop_ld32u = {
2187
- .base.static_constraint = C_O1_I1(r, r),
2188
- .out = tgen_ld32u,
2189
-};
2190
-
2191
-static void tgen_ld32s(TCGContext *s, TCGType type, TCGReg dest,
2192
- TCGReg base, ptrdiff_t offset)
2193
-{
2194
- tcg_out_ldst(s, OPC_LW, dest, base, offset);
2195
-}
2196
-
2197
-static const TCGOutOpLoad outop_ld32s = {
2198
- .base.static_constraint = C_O1_I1(r, r),
2199
- .out = tgen_ld32s,
2200
-};
2201
-
2202
-static void tgen_st8_r(TCGContext *s, TCGType type, TCGReg data,
2203
- TCGReg base, ptrdiff_t offset)
2204
-{
2205
- tcg_out_ldst(s, OPC_SB, data, base, offset);
2206
-}
2207
-
2208
-static const TCGOutOpStore outop_st8 = {
2209
- .base.static_constraint = C_O0_I2(rz, r),
2210
- .out_r = tgen_st8_r,
2211
-};
2212
-
2213
-static void tgen_st16_r(TCGContext *s, TCGType type, TCGReg data,
2214
- TCGReg base, ptrdiff_t offset)
2215
-{
2216
- tcg_out_ldst(s, OPC_SH, data, base, offset);
2217
-}
2218
-
2219
-static const TCGOutOpStore outop_st16 = {
2220
- .base.static_constraint = C_O0_I2(rz, r),
2221
- .out_r = tgen_st16_r,
2222
-};
2223
-
2224
-static const TCGOutOpStore outop_st = {
2225
- .base.static_constraint = C_O0_I2(rz, r),
2226
- .out_r = tcg_out_st,
2227
-};
2228
-
2229
-
2230
-static TCGConstraintSetIndex
2231
-tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
2232
-{
2233
- return C_NotImplemented;
2234
-}
2235
-
2236
-static const int tcg_target_callee_save_regs[] = {
2237
- TCG_REG_S0,
2238
- TCG_REG_S1,
2239
- TCG_REG_S2,
2240
- TCG_REG_S3,
2241
- TCG_REG_S4,
2242
- TCG_REG_S5,
2243
- TCG_REG_S6, /* used for the tb base (TCG_REG_TB) */
2244
- TCG_REG_S7, /* used for guest_base */
2245
- TCG_REG_S8, /* used for the global env (TCG_AREG0) */
2246
- TCG_REG_RA, /* should be last for ABI compliance */
2247
-};
2248
-
2249
-/* The Linux kernel doesn't provide any information about the available
2250
- instruction set. Probe it using a signal handler. */
2251
-
2252
-
2253
-#ifndef use_movnz_instructions
2254
-bool use_movnz_instructions = false;
2255
-#endif
2256
-
2257
-#ifndef use_mips32_instructions
2258
-bool use_mips32_instructions = false;
2259
-#endif
2260
-
2261
-#ifndef use_mips32r2_instructions
2262
-bool use_mips32r2_instructions = false;
2263
-#endif
2264
-
2265
-static volatile sig_atomic_t got_sigill;
2266
-
2267
-static void sigill_handler(int signo, siginfo_t *si, void *data)
2268
-{
2269
- /* Skip the faulty instruction */
2270
- ucontext_t *uc = (ucontext_t *)data;
2271
- uc->uc_mcontext.pc += 4;
2272
-
2273
- got_sigill = 1;
2274
-}
2275
-
2276
-static void tcg_target_detect_isa(void)
2277
-{
2278
- struct sigaction sa_old, sa_new;
2279
-
2280
- memset(&sa_new, 0, sizeof(sa_new));
2281
- sa_new.sa_flags = SA_SIGINFO;
2282
- sa_new.sa_sigaction = sigill_handler;
2283
- sigaction(SIGILL, &sa_new, &sa_old);
2284
-
2285
- /* Probe for movn/movz, necessary to implement movcond. */
2286
-#ifndef use_movnz_instructions
2287
- got_sigill = 0;
2288
- asm volatile(".set push\n"
2289
- ".set mips32\n"
2290
- "movn $zero, $zero, $zero\n"
2291
- "movz $zero, $zero, $zero\n"
2292
- ".set pop\n"
2293
- : : : );
2294
- use_movnz_instructions = !got_sigill;
2295
-#endif
2296
-
2297
- /* Probe for MIPS32 instructions. As no subsetting is allowed
2298
- by the specification, it is only necessary to probe for one
2299
- of the instructions. */
2300
-#ifndef use_mips32_instructions
2301
- got_sigill = 0;
2302
- asm volatile(".set push\n"
2303
- ".set mips32\n"
2304
- "mul $zero, $zero\n"
2305
- ".set pop\n"
2306
- : : : );
2307
- use_mips32_instructions = !got_sigill;
2308
-#endif
2309
-
2310
- /* Probe for MIPS32r2 instructions if MIPS32 instructions are
2311
- available. As no subsetting is allowed by the specification,
2312
- it is only necessary to probe for one of the instructions. */
2313
-#ifndef use_mips32r2_instructions
2314
- if (use_mips32_instructions) {
2315
- got_sigill = 0;
2316
- asm volatile(".set push\n"
2317
- ".set mips32r2\n"
2318
- "seb $zero, $zero\n"
2319
- ".set pop\n"
2320
- : : : );
2321
- use_mips32r2_instructions = !got_sigill;
2322
- }
2323
-#endif
2324
-
2325
- sigaction(SIGILL, &sa_old, NULL);
2326
-}
2327
-
2328
-static tcg_insn_unit *align_code_ptr(TCGContext *s)
2329
-{
2330
- uintptr_t p = (uintptr_t)s->code_ptr;
2331
- if (p & 15) {
2332
- p = (p + 15) & -16;
2333
- s->code_ptr = (void *)p;
2334
- }
2335
- return s->code_ptr;
2336
-}
2337
-
2338
-/* Stack frame parameters. */
2339
-#define REG_SIZE 8
2340
-#define SAVE_SIZE ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE)
2341
-#define TEMP_SIZE (CPU_TEMP_BUF_NLONGS * (int)sizeof(long))
2342
-
2343
-#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \
2344
- + TCG_TARGET_STACK_ALIGN - 1) \
2345
- & -TCG_TARGET_STACK_ALIGN)
2346
-#define SAVE_OFS (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE)
2347
-
2348
-/* We're expecting to be able to use an immediate for frame allocation. */
2349
-QEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7fff);
2350
-
2351
-/* Generate global QEMU prologue and epilogue code */
2352
-static void tcg_target_qemu_prologue(TCGContext *s)
2353
-{
2354
- int i;
2355
-
2356
- tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE);
2357
-
2358
- /* TB prologue */
2359
- tcg_out_opc_imm(s, OPC_DADDIU, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE);
2360
- for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
2361
- tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
2362
- TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
2363
- }
2364
-
2365
- if (!tcg_use_softmmu && guest_base != (int16_t)guest_base) {
2366
- /*
2367
- * The function call abi for n32 and n64 will have loaded $25 (t9)
2368
- * with the address of the prologue, so we can use that instead
2369
- * of TCG_REG_TB.
2370
- */
2371
-#if !defined(__mips_abicalls)
2372
-# error "Unknown mips abi"
2373
-#endif
2374
- tcg_out_movi_int(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base,
2375
- TCG_REG_T9);
2376
- tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
2377
- }
2378
-
2379
- tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_TB, tcg_target_call_iarg_regs[1]);
2380
-
2381
- /* Call generated code */
2382
- tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1], 0);
2383
- /* delay slot */
2384
- tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
2385
-
2386
- /*
2387
- * Return path for goto_ptr. Set return value to 0, a-la exit_tb,
2388
- * and fall through to the rest of the epilogue.
2389
- */
2390
- tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr);
2391
- tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_V0, TCG_REG_ZERO);
2392
-
2393
- /* TB epilogue */
2394
- tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr);
2395
- for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
2396
- tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
2397
- TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
2398
- }
2399
-
2400
- tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
2401
- /* delay slot */
2402
- tcg_out_opc_imm(s, OPC_DADDIU, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE);
2403
-
2404
- if (use_mips32r2_instructions) {
2405
- return;
2406
- }
2407
-
2408
- /* Bswap subroutines: Input in TCG_TMP0, output in TCG_TMP3;
2409
- clobbers TCG_TMP1, TCG_TMP2. */
2410
-
2411
- /*
2412
- * bswap32 -- 32-bit swap (signed result for mips64). a0 = abcd.
2413
- */
2414
- bswap32_addr = tcg_splitwx_to_rx(align_code_ptr(s));
2415
- /* t3 = (ssss)d000 */
2416
- tcg_out_opc_sa(s, OPC_SLL, TCG_TMP3, TCG_TMP0, 24);
2417
- /* t1 = 000a */
2418
- tcg_out_opc_sa(s, OPC_SRL, TCG_TMP1, TCG_TMP0, 24);
2419
- /* t2 = 00c0 */
2420
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP0, 0xff00);
2421
- /* t3 = d00a */
2422
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2423
- /* t1 = 0abc */
2424
- tcg_out_opc_sa(s, OPC_SRL, TCG_TMP1, TCG_TMP0, 8);
2425
- /* t2 = 0c00 */
2426
- tcg_out_opc_sa(s, OPC_SLL, TCG_TMP2, TCG_TMP2, 8);
2427
- /* t1 = 00b0 */
2428
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
2429
- /* t3 = dc0a */
2430
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
2431
- tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
2432
- /* t3 = dcba -- delay slot */
2433
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2434
-
2435
- /*
2436
- * bswap32u -- unsigned 32-bit swap. a0 = ....abcd.
2437
- */
2438
- bswap32u_addr = tcg_splitwx_to_rx(align_code_ptr(s));
2439
- /* t1 = (0000)000d */
2440
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP0, 0xff);
2441
- /* t3 = 000a */
2442
- tcg_out_opc_sa(s, OPC_SRL, TCG_TMP3, TCG_TMP0, 24);
2443
- /* t1 = (0000)d000 */
2444
- tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 24);
2445
- /* t2 = 00c0 */
2446
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP0, 0xff00);
2447
- /* t3 = d00a */
2448
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2449
- /* t1 = 0abc */
2450
- tcg_out_opc_sa(s, OPC_SRL, TCG_TMP1, TCG_TMP0, 8);
2451
- /* t2 = 0c00 */
2452
- tcg_out_opc_sa(s, OPC_SLL, TCG_TMP2, TCG_TMP2, 8);
2453
- /* t1 = 00b0 */
2454
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
2455
- /* t3 = dc0a */
2456
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
2457
- tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
2458
- /* t3 = dcba -- delay slot */
2459
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2460
-
2461
- /*
2462
- * bswap64 -- 64-bit swap. a0 = abcdefgh
2463
- */
2464
- bswap64_addr = tcg_splitwx_to_rx(align_code_ptr(s));
2465
- /* t3 = h0000000 */
2466
- tcg_out_dsll(s, TCG_TMP3, TCG_TMP0, 56);
2467
- /* t1 = 0000000a */
2468
- tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 56);
2469
-
2470
- /* t2 = 000000g0 */
2471
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP0, 0xff00);
2472
- /* t3 = h000000a */
2473
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2474
- /* t1 = 00000abc */
2475
- tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 40);
2476
- /* t2 = 0g000000 */
2477
- tcg_out_dsll(s, TCG_TMP2, TCG_TMP2, 40);
2478
- /* t1 = 000000b0 */
2479
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
2480
-
2481
- /* t3 = hg00000a */
2482
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
2483
- /* t2 = 0000abcd */
2484
- tcg_out_dsrl(s, TCG_TMP2, TCG_TMP0, 32);
2485
- /* t3 = hg0000ba */
2486
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2487
-
2488
- /* t1 = 000000c0 */
2489
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP2, 0xff00);
2490
- /* t2 = 0000000d */
2491
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP2, 0x00ff);
2492
- /* t1 = 00000c00 */
2493
- tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 8);
2494
- /* t2 = 0000d000 */
2495
- tcg_out_dsll(s, TCG_TMP2, TCG_TMP2, 24);
2496
-
2497
- /* t3 = hg000cba */
2498
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2499
- /* t1 = 00abcdef */
2500
- tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 16);
2501
- /* t3 = hg00dcba */
2502
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
2503
-
2504
- /* t2 = 0000000f */
2505
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP1, 0x00ff);
2506
- /* t1 = 000000e0 */
2507
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
2508
- /* t2 = 00f00000 */
2509
- tcg_out_dsll(s, TCG_TMP2, TCG_TMP2, 40);
2510
- /* t1 = 000e0000 */
2511
- tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 24);
2512
-
2513
- /* t3 = hgf0dcba */
2514
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
2515
- tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
2516
- /* t3 = hgfedcba -- delay slot */
2517
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2518
-}
2519
-
2520
-static void tcg_out_tb_start(TCGContext *s)
2521
-{
2522
- /* nothing to do */
2523
-}
2524
-
2525
-static void tcg_target_init(TCGContext *s)
2526
-{
2527
- tcg_target_detect_isa();
2528
- tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff;
2529
- tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff;
2530
-
2531
- tcg_target_call_clobber_regs = 0;
2532
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V0);
2533
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V1);
2534
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A0);
2535
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A1);
2536
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A2);
2537
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A3);
2538
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T0);
2539
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T1);
2540
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T2);
2541
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T3);
2542
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T4);
2543
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T5);
2544
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T6);
2545
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T7);
2546
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T8);
2547
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T9);
2548
-
2549
- s->reserved_regs = 0;
2550
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
2551
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0); /* kernel use only */
2552
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1); /* kernel use only */
2553
- tcg_regset_set_reg(s->reserved_regs, TCG_TMP0); /* internal use */
2554
- tcg_regset_set_reg(s->reserved_regs, TCG_TMP1); /* internal use */
2555
- tcg_regset_set_reg(s->reserved_regs, TCG_TMP2); /* internal use */
2556
- tcg_regset_set_reg(s->reserved_regs, TCG_TMP3); /* internal use */
2557
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return address */
2558
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */
2559
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP); /* global pointer */
2560
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_TB); /* tc->tc_ptr */
2561
-}
2562
-
2563
-typedef struct {
2564
- DebugFrameHeader h;
2565
- uint8_t fde_def_cfa[4];
2566
- uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
2567
-} DebugFrame;
2568
-
2569
-#define ELF_HOST_MACHINE EM_MIPS
2570
-/* GDB doesn't appear to require proper setting of ELF_HOST_FLAGS,
2571
- which is good because they're really quite complicated for MIPS. */
2572
-
2573
-static const DebugFrame debug_frame = {
2574
- .h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */
2575
- .h.cie.id = -1,
2576
- .h.cie.version = 1,
2577
- .h.cie.code_align = 1,
2578
- .h.cie.data_align = -REG_SIZE & 0x7f, /* sleb128 */
2579
- .h.cie.return_column = TCG_REG_RA,
2580
-
2581
- /* Total FDE size does not include the "len" member. */
2582
- .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
2583
-
2584
- .fde_def_cfa = {
2585
- 12, TCG_REG_SP, /* DW_CFA_def_cfa sp, ... */
2586
- (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
2587
- (FRAME_SIZE >> 7)
2588
- },
2589
- .fde_reg_ofs = {
2590
- 0x80 + 16, 9, /* DW_CFA_offset, s0, -72 */
2591
- 0x80 + 17, 8, /* DW_CFA_offset, s2, -64 */
2592
- 0x80 + 18, 7, /* DW_CFA_offset, s3, -56 */
2593
- 0x80 + 19, 6, /* DW_CFA_offset, s4, -48 */
2594
- 0x80 + 20, 5, /* DW_CFA_offset, s5, -40 */
2595
- 0x80 + 21, 4, /* DW_CFA_offset, s6, -32 */
2596
- 0x80 + 22, 3, /* DW_CFA_offset, s7, -24 */
2597
- 0x80 + 30, 2, /* DW_CFA_offset, s8, -16 */
2598
- 0x80 + 31, 1, /* DW_CFA_offset, ra, -8 */
2599
- }
2600
-};
2601
-
2602
-void tcg_register_jit(const void *buf, size_t buf_size)
2603
-{
2604
- tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
2605
-}
tcg/mips64/tcg-target.h
deleted
-75
@@ -1,75 +0,0 @@
1
-/*
2
- * Tiny Code Generator for QEMU
3
- *
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
7
- *
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:
14
- *
15
- * The above copyright notice and this permission notice shall be included in
16
- * all copies or substantial portions of the Software.
17
- *
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
24
- * THE SOFTWARE.
25
- */
26
-
27
-#ifndef MIPS_TCG_TARGET_H
28
-#define MIPS_TCG_TARGET_H
29
-
30
-#define TCG_TARGET_INSN_UNIT_SIZE 4
31
-#define TCG_TARGET_NB_REGS 32
32
-
33
-#define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1)
34
-
35
-typedef enum {
36
- TCG_REG_ZERO = 0,
37
- TCG_REG_AT,
38
- TCG_REG_V0,
39
- TCG_REG_V1,
40
- TCG_REG_A0,
41
- TCG_REG_A1,
42
- TCG_REG_A2,
43
- TCG_REG_A3,
44
- TCG_REG_T0,
45
- TCG_REG_T1,
46
- TCG_REG_T2,
47
- TCG_REG_T3,
48
- TCG_REG_T4,
49
- TCG_REG_T5,
50
- TCG_REG_T6,
51
- TCG_REG_T7,
52
- TCG_REG_S0,
53
- TCG_REG_S1,
54
- TCG_REG_S2,
55
- TCG_REG_S3,
56
- TCG_REG_S4,
57
- TCG_REG_S5,
58
- TCG_REG_S6,
59
- TCG_REG_S7,
60
- TCG_REG_T8,
61
- TCG_REG_T9,
62
- TCG_REG_K0,
63
- TCG_REG_K1,
64
- TCG_REG_GP,
65
- TCG_REG_SP,
66
- TCG_REG_S8,
67
- TCG_REG_RA,
68
-
69
- TCG_REG_CALL_STACK = TCG_REG_SP,
70
- TCG_AREG0 = TCG_REG_S8,
71
-} TCGReg;
72
-
73
-#define TCG_REG_ZERO TCG_REG_ZERO
74
-
75
-#endif