]> git.proxmox.com Git - mirror_qemu.git/blame - tcg/mips/tcg-target.c.inc
Merge tag 'pull-tcg-20230116' of https://gitlab.com/rth7680/qemu into staging
[mirror_qemu.git] / tcg / mips / tcg-target.c.inc
CommitLineData
afa05235
AJ
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
23a79c11
RH
27#include "../tcg-ldst.c.inc"
28
e03b5686 29#if HOST_BIG_ENDIAN
9d8bf2d1 30# define MIPS_BE 1
afa05235 31#else
9d8bf2d1 32# define MIPS_BE 0
afa05235
AJ
33#endif
34
f0d70331
JG
35#if TCG_TARGET_REG_BITS == 32
36# define LO_OFF (MIPS_BE * 4)
37# define HI_OFF (4 - LO_OFF)
38#else
39/* To assert at compile-time that these values are never used
40 for TCG_TARGET_REG_BITS == 64. */
8df8d529 41int link_error(void);
f0d70331
JG
42# define LO_OFF link_error()
43# define HI_OFF link_error()
44#endif
9d8bf2d1 45
8d8fdbae 46#ifdef CONFIG_DEBUG_TCG
afa05235
AJ
47static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
48 "zero",
49 "at",
50 "v0",
51 "v1",
52 "a0",
53 "a1",
54 "a2",
55 "a3",
56 "t0",
57 "t1",
58 "t2",
59 "t3",
60 "t4",
61 "t5",
62 "t6",
63 "t7",
64 "s0",
65 "s1",
66 "s2",
67 "s3",
68 "s4",
69 "s5",
70 "s6",
71 "s7",
72 "t8",
73 "t9",
74 "k0",
75 "k1",
76 "gp",
77 "sp",
41883904 78 "s8",
afa05235
AJ
79 "ra",
80};
81#endif
82
6c530e32 83#define TCG_TMP0 TCG_REG_AT
f216a35f 84#define TCG_TMP1 TCG_REG_T9
bb08afe9
JG
85#define TCG_TMP2 TCG_REG_T8
86#define TCG_TMP3 TCG_REG_T7
6c530e32 87
4df9cac5
JB
88#ifndef CONFIG_SOFTMMU
89#define TCG_GUEST_BASE_REG TCG_REG_S1
90#endif
91
afa05235 92/* check if we really need so many registers :P */
2dc7553d 93static const int tcg_target_reg_alloc_order[] = {
41883904 94 /* Call saved registers. */
afa05235
AJ
95 TCG_REG_S0,
96 TCG_REG_S1,
97 TCG_REG_S2,
98 TCG_REG_S3,
99 TCG_REG_S4,
100 TCG_REG_S5,
101 TCG_REG_S6,
102 TCG_REG_S7,
41883904
RH
103 TCG_REG_S8,
104
105 /* Call clobbered registers. */
afa05235
AJ
106 TCG_REG_T4,
107 TCG_REG_T5,
108 TCG_REG_T6,
109 TCG_REG_T7,
110 TCG_REG_T8,
111 TCG_REG_T9,
41883904 112 TCG_REG_V1,
afa05235 113 TCG_REG_V0,
41883904
RH
114
115 /* Argument registers, opposite order of allocation. */
999b9416
JG
116 TCG_REG_T3,
117 TCG_REG_T2,
118 TCG_REG_T1,
119 TCG_REG_T0,
41883904
RH
120 TCG_REG_A3,
121 TCG_REG_A2,
122 TCG_REG_A1,
123 TCG_REG_A0,
afa05235
AJ
124};
125
999b9416 126static const TCGReg tcg_target_call_iarg_regs[] = {
afa05235
AJ
127 TCG_REG_A0,
128 TCG_REG_A1,
129 TCG_REG_A2,
999b9416
JG
130 TCG_REG_A3,
131#if _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64
132 TCG_REG_T0,
133 TCG_REG_T1,
134 TCG_REG_T2,
135 TCG_REG_T3,
136#endif
afa05235
AJ
137};
138
5a0eed37 139static const TCGReg tcg_target_call_oarg_regs[2] = {
afa05235
AJ
140 TCG_REG_V0,
141 TCG_REG_V1
142};
143
df5af130
RH
144static const tcg_insn_unit *tb_ret_addr;
145static const tcg_insn_unit *bswap32_addr;
146static const tcg_insn_unit *bswap32u_addr;
147static const tcg_insn_unit *bswap64_addr;
afa05235 148
df5af130 149static bool reloc_pc16(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
afa05235 150{
ae0218e3 151 /* Let the compiler perform the right-shift as part of the arithmetic. */
df5af130
RH
152 const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
153 ptrdiff_t disp = target - (src_rx + 1);
91a7fd1f 154 if (disp == (int16_t)disp) {
df5af130 155 *src_rw = deposit32(*src_rw, 0, 16, disp);
91a7fd1f
RH
156 return true;
157 }
158 return false;
afa05235
AJ
159}
160
6ac17786 161static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
2ba7fae2 162 intptr_t value, intptr_t addend)
afa05235 163{
eabb7b91
AJ
164 tcg_debug_assert(type == R_MIPS_PC16);
165 tcg_debug_assert(addend == 0);
91a7fd1f 166 return reloc_pc16(code_ptr, (const tcg_insn_unit *)value);
afa05235
AJ
167}
168
1c418268 169#define TCG_CT_CONST_ZERO 0x100
070603f6
RH
170#define TCG_CT_CONST_U16 0x200 /* Unsigned 16-bit: 0 - 0xffff. */
171#define TCG_CT_CONST_S16 0x400 /* Signed 16-bit: -32768 - 32767 */
172#define TCG_CT_CONST_P2M1 0x800 /* Power of 2 minus 1. */
173#define TCG_CT_CONST_N16 0x1000 /* "Negatable" 16-bit: -32767 - 32767 */
2a1d9d41 174#define TCG_CT_CONST_WSZ 0x2000 /* word size */
1c418268 175
51800e43
RH
176#define ALL_GENERAL_REGS 0xffffffffu
177#define NOA0_REGS (ALL_GENERAL_REGS & ~(1 << TCG_REG_A0))
178
179#ifdef CONFIG_SOFTMMU
180#define ALL_QLOAD_REGS \
181 (NOA0_REGS & ~((TCG_TARGET_REG_BITS < TARGET_LONG_BITS) << TCG_REG_A2))
182#define ALL_QSTORE_REGS \
183 (NOA0_REGS & ~(TCG_TARGET_REG_BITS < TARGET_LONG_BITS \
184 ? (1 << TCG_REG_A2) | (1 << TCG_REG_A3) \
185 : (1 << TCG_REG_A1)))
186#else
187#define ALL_QLOAD_REGS NOA0_REGS
188#define ALL_QSTORE_REGS NOA0_REGS
189#endif
190
191
10d4af58 192static bool is_p2m1(tcg_target_long val)
1c418268
RH
193{
194 return val && ((val + 1) & val) == 0;
195}
196
afa05235 197/* test if a constant matches the constraint */
a4fbbd77 198static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
afa05235 199{
1c418268 200 if (ct & TCG_CT_CONST) {
afa05235 201 return 1;
1c418268 202 } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
afa05235 203 return 1;
1c418268 204 } else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val) {
afa05235 205 return 1;
1c418268 206 } else if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val) {
afa05235 207 return 1;
070603f6
RH
208 } else if ((ct & TCG_CT_CONST_N16) && val >= -32767 && val <= 32767) {
209 return 1;
1c418268
RH
210 } else if ((ct & TCG_CT_CONST_P2M1)
211 && use_mips32r2_instructions && is_p2m1(val)) {
212 return 1;
2a1d9d41
RH
213 } else if ((ct & TCG_CT_CONST_WSZ)
214 && val == (type == TCG_TYPE_I32 ? 32 : 64)) {
215 return 1;
1c418268
RH
216 }
217 return 0;
afa05235
AJ
218}
219
220/* instruction opcodes */
ac0f3b12 221typedef enum {
57a701fc
JG
222 OPC_J = 002 << 26,
223 OPC_JAL = 003 << 26,
224 OPC_BEQ = 004 << 26,
225 OPC_BNE = 005 << 26,
226 OPC_BLEZ = 006 << 26,
227 OPC_BGTZ = 007 << 26,
228 OPC_ADDIU = 011 << 26,
229 OPC_SLTI = 012 << 26,
230 OPC_SLTIU = 013 << 26,
231 OPC_ANDI = 014 << 26,
232 OPC_ORI = 015 << 26,
233 OPC_XORI = 016 << 26,
234 OPC_LUI = 017 << 26,
23a79c11
RH
235 OPC_BNEL = 025 << 26,
236 OPC_BNEZALC_R6 = 030 << 26,
57a701fc 237 OPC_DADDIU = 031 << 26,
23a79c11
RH
238 OPC_LDL = 032 << 26,
239 OPC_LDR = 033 << 26,
57a701fc
JG
240 OPC_LB = 040 << 26,
241 OPC_LH = 041 << 26,
23a79c11 242 OPC_LWL = 042 << 26,
57a701fc
JG
243 OPC_LW = 043 << 26,
244 OPC_LBU = 044 << 26,
245 OPC_LHU = 045 << 26,
23a79c11 246 OPC_LWR = 046 << 26,
57a701fc
JG
247 OPC_LWU = 047 << 26,
248 OPC_SB = 050 << 26,
249 OPC_SH = 051 << 26,
23a79c11 250 OPC_SWL = 052 << 26,
57a701fc 251 OPC_SW = 053 << 26,
23a79c11
RH
252 OPC_SDL = 054 << 26,
253 OPC_SDR = 055 << 26,
254 OPC_SWR = 056 << 26,
57a701fc
JG
255 OPC_LD = 067 << 26,
256 OPC_SD = 077 << 26,
257
258 OPC_SPECIAL = 000 << 26,
259 OPC_SLL = OPC_SPECIAL | 000,
260 OPC_SRL = OPC_SPECIAL | 002,
261 OPC_ROTR = OPC_SPECIAL | 002 | (1 << 21),
262 OPC_SRA = OPC_SPECIAL | 003,
263 OPC_SLLV = OPC_SPECIAL | 004,
264 OPC_SRLV = OPC_SPECIAL | 006,
265 OPC_ROTRV = OPC_SPECIAL | 006 | 0100,
266 OPC_SRAV = OPC_SPECIAL | 007,
267 OPC_JR_R5 = OPC_SPECIAL | 010,
268 OPC_JALR = OPC_SPECIAL | 011,
269 OPC_MOVZ = OPC_SPECIAL | 012,
270 OPC_MOVN = OPC_SPECIAL | 013,
271 OPC_SYNC = OPC_SPECIAL | 017,
272 OPC_MFHI = OPC_SPECIAL | 020,
273 OPC_MFLO = OPC_SPECIAL | 022,
274 OPC_DSLLV = OPC_SPECIAL | 024,
275 OPC_DSRLV = OPC_SPECIAL | 026,
276 OPC_DROTRV = OPC_SPECIAL | 026 | 0100,
277 OPC_DSRAV = OPC_SPECIAL | 027,
278 OPC_MULT = OPC_SPECIAL | 030,
279 OPC_MUL_R6 = OPC_SPECIAL | 030 | 0200,
280 OPC_MUH = OPC_SPECIAL | 030 | 0300,
281 OPC_MULTU = OPC_SPECIAL | 031,
282 OPC_MULU = OPC_SPECIAL | 031 | 0200,
283 OPC_MUHU = OPC_SPECIAL | 031 | 0300,
284 OPC_DIV = OPC_SPECIAL | 032,
285 OPC_DIV_R6 = OPC_SPECIAL | 032 | 0200,
286 OPC_MOD = OPC_SPECIAL | 032 | 0300,
287 OPC_DIVU = OPC_SPECIAL | 033,
288 OPC_DIVU_R6 = OPC_SPECIAL | 033 | 0200,
289 OPC_MODU = OPC_SPECIAL | 033 | 0300,
290 OPC_DMULT = OPC_SPECIAL | 034,
291 OPC_DMUL = OPC_SPECIAL | 034 | 0200,
292 OPC_DMUH = OPC_SPECIAL | 034 | 0300,
293 OPC_DMULTU = OPC_SPECIAL | 035,
294 OPC_DMULU = OPC_SPECIAL | 035 | 0200,
295 OPC_DMUHU = OPC_SPECIAL | 035 | 0300,
296 OPC_DDIV = OPC_SPECIAL | 036,
297 OPC_DDIV_R6 = OPC_SPECIAL | 036 | 0200,
298 OPC_DMOD = OPC_SPECIAL | 036 | 0300,
299 OPC_DDIVU = OPC_SPECIAL | 037,
300 OPC_DDIVU_R6 = OPC_SPECIAL | 037 | 0200,
301 OPC_DMODU = OPC_SPECIAL | 037 | 0300,
302 OPC_ADDU = OPC_SPECIAL | 041,
303 OPC_SUBU = OPC_SPECIAL | 043,
304 OPC_AND = OPC_SPECIAL | 044,
305 OPC_OR = OPC_SPECIAL | 045,
306 OPC_XOR = OPC_SPECIAL | 046,
307 OPC_NOR = OPC_SPECIAL | 047,
308 OPC_SLT = OPC_SPECIAL | 052,
309 OPC_SLTU = OPC_SPECIAL | 053,
310 OPC_DADDU = OPC_SPECIAL | 055,
311 OPC_DSUBU = OPC_SPECIAL | 057,
312 OPC_SELEQZ = OPC_SPECIAL | 065,
313 OPC_SELNEZ = OPC_SPECIAL | 067,
314 OPC_DSLL = OPC_SPECIAL | 070,
315 OPC_DSRL = OPC_SPECIAL | 072,
316 OPC_DROTR = OPC_SPECIAL | 072 | (1 << 21),
317 OPC_DSRA = OPC_SPECIAL | 073,
318 OPC_DSLL32 = OPC_SPECIAL | 074,
319 OPC_DSRL32 = OPC_SPECIAL | 076,
320 OPC_DROTR32 = OPC_SPECIAL | 076 | (1 << 21),
321 OPC_DSRA32 = OPC_SPECIAL | 077,
2a1d9d41
RH
322 OPC_CLZ_R6 = OPC_SPECIAL | 0120,
323 OPC_DCLZ_R6 = OPC_SPECIAL | 0122,
57a701fc
JG
324
325 OPC_REGIMM = 001 << 26,
326 OPC_BLTZ = OPC_REGIMM | (000 << 16),
327 OPC_BGEZ = OPC_REGIMM | (001 << 16),
328
329 OPC_SPECIAL2 = 034 << 26,
330 OPC_MUL_R5 = OPC_SPECIAL2 | 002,
2a1d9d41
RH
331 OPC_CLZ = OPC_SPECIAL2 | 040,
332 OPC_DCLZ = OPC_SPECIAL2 | 044,
57a701fc
JG
333
334 OPC_SPECIAL3 = 037 << 26,
335 OPC_EXT = OPC_SPECIAL3 | 000,
336 OPC_DEXTM = OPC_SPECIAL3 | 001,
337 OPC_DEXTU = OPC_SPECIAL3 | 002,
338 OPC_DEXT = OPC_SPECIAL3 | 003,
339 OPC_INS = OPC_SPECIAL3 | 004,
340 OPC_DINSM = OPC_SPECIAL3 | 005,
341 OPC_DINSU = OPC_SPECIAL3 | 006,
342 OPC_DINS = OPC_SPECIAL3 | 007,
343 OPC_WSBH = OPC_SPECIAL3 | 00240,
344 OPC_DSBH = OPC_SPECIAL3 | 00244,
345 OPC_DSHD = OPC_SPECIAL3 | 00544,
346 OPC_SEB = OPC_SPECIAL3 | 02040,
347 OPC_SEH = OPC_SPECIAL3 | 03040,
6e0d0969
JH
348
349 /* MIPS r6 doesn't have JR, JALR should be used instead */
350 OPC_JR = use_mips32r6_instructions ? OPC_JALR : OPC_JR_R5,
bc6d0c22
JH
351
352 /*
353 * MIPS r6 replaces MUL with an alternative encoding which is
354 * backwards-compatible at the assembly level.
355 */
356 OPC_MUL = use_mips32r6_instructions ? OPC_MUL_R6 : OPC_MUL_R5,
6f0b9910
PK
357
358 /* MIPS r6 introduced names for weaker variants of SYNC. These are
359 backward compatible to previous architecture revisions. */
a4e57084 360 OPC_SYNC_WMB = OPC_SYNC | 0x04 << 6,
361 OPC_SYNC_MB = OPC_SYNC | 0x10 << 6,
362 OPC_SYNC_ACQUIRE = OPC_SYNC | 0x11 << 6,
363 OPC_SYNC_RELEASE = OPC_SYNC | 0x12 << 6,
364 OPC_SYNC_RMB = OPC_SYNC | 0x13 << 6,
57a701fc
JG
365
366 /* Aliases for convenience. */
367 ALIAS_PADD = sizeof(void *) == 4 ? OPC_ADDU : OPC_DADDU,
368 ALIAS_PADDI = sizeof(void *) == 4 ? OPC_ADDIU : OPC_DADDIU,
369 ALIAS_TSRL = TARGET_LONG_BITS == 32 || TCG_TARGET_REG_BITS == 32
370 ? OPC_SRL : OPC_DSRL,
ac0f3b12 371} MIPSInsn;
afa05235
AJ
372
373/*
374 * Type reg
375 */
10d4af58
RH
376static void tcg_out_opc_reg(TCGContext *s, MIPSInsn opc,
377 TCGReg rd, TCGReg rs, TCGReg rt)
afa05235
AJ
378{
379 int32_t inst;
380
381 inst = opc;
382 inst |= (rs & 0x1F) << 21;
383 inst |= (rt & 0x1F) << 16;
384 inst |= (rd & 0x1F) << 11;
385 tcg_out32(s, inst);
386}
387
388/*
389 * Type immediate
390 */
10d4af58
RH
391static void tcg_out_opc_imm(TCGContext *s, MIPSInsn opc,
392 TCGReg rt, TCGReg rs, TCGArg imm)
afa05235
AJ
393{
394 int32_t inst;
395
396 inst = opc;
397 inst |= (rs & 0x1F) << 21;
398 inst |= (rt & 0x1F) << 16;
399 inst |= (imm & 0xffff);
400 tcg_out32(s, inst);
401}
402
1c418268
RH
403/*
404 * Type bitfield
405 */
10d4af58
RH
406static void tcg_out_opc_bf(TCGContext *s, MIPSInsn opc, TCGReg rt,
407 TCGReg rs, int msb, int lsb)
1c418268
RH
408{
409 int32_t inst;
410
411 inst = opc;
412 inst |= (rs & 0x1F) << 21;
413 inst |= (rt & 0x1F) << 16;
414 inst |= (msb & 0x1F) << 11;
415 inst |= (lsb & 0x1F) << 6;
416 tcg_out32(s, inst);
417}
418
10d4af58
RH
419static void tcg_out_opc_bf64(TCGContext *s, MIPSInsn opc, MIPSInsn opm,
420 MIPSInsn oph, TCGReg rt, TCGReg rs,
0119b192
JG
421 int msb, int lsb)
422{
423 if (lsb >= 32) {
424 opc = oph;
425 msb -= 32;
426 lsb -= 32;
427 } else if (msb >= 32) {
428 opc = opm;
429 msb -= 32;
430 }
431 tcg_out_opc_bf(s, opc, rt, rs, msb, lsb);
432}
433
6d8ff4d8
AJ
434/*
435 * Type branch
436 */
10d4af58 437static void tcg_out_opc_br(TCGContext *s, MIPSInsn opc, TCGReg rt, TCGReg rs)
6d8ff4d8 438{
8c1b0792 439 tcg_out_opc_imm(s, opc, rt, rs, 0);
6d8ff4d8
AJ
440}
441
afa05235
AJ
442/*
443 * Type sa
444 */
10d4af58
RH
445static void tcg_out_opc_sa(TCGContext *s, MIPSInsn opc,
446 TCGReg rd, TCGReg rt, TCGArg sa)
afa05235
AJ
447{
448 int32_t inst;
449
450 inst = opc;
451 inst |= (rt & 0x1F) << 16;
452 inst |= (rd & 0x1F) << 11;
453 inst |= (sa & 0x1F) << 6;
454 tcg_out32(s, inst);
455
456}
457
0119b192
JG
458static void tcg_out_opc_sa64(TCGContext *s, MIPSInsn opc1, MIPSInsn opc2,
459 TCGReg rd, TCGReg rt, TCGArg sa)
460{
461 int32_t inst;
462
463 inst = (sa & 32 ? opc2 : opc1);
464 inst |= (rt & 0x1F) << 16;
465 inst |= (rd & 0x1F) << 11;
466 inst |= (sa & 0x1F) << 6;
467 tcg_out32(s, inst);
468}
469
f8c9eddb
RH
470/*
471 * Type jump.
472 * Returns true if the branch was in range and the insn was emitted.
473 */
2be7d76b 474static bool tcg_out_opc_jmp(TCGContext *s, MIPSInsn opc, const void *target)
f8c9eddb
RH
475{
476 uintptr_t dest = (uintptr_t)target;
df5af130 477 uintptr_t from = (uintptr_t)tcg_splitwx_to_rx(s->code_ptr) + 4;
f8c9eddb
RH
478 int32_t inst;
479
480 /* The pc-region branch happens within the 256MB region of
481 the delay slot (thus the +4). */
482 if ((from ^ dest) & -(1 << 28)) {
483 return false;
484 }
eabb7b91 485 tcg_debug_assert((dest & 3) == 0);
f8c9eddb
RH
486
487 inst = opc;
488 inst |= (dest >> 2) & 0x3ffffff;
489 tcg_out32(s, inst);
490 return true;
491}
492
10d4af58 493static void tcg_out_nop(TCGContext *s)
afa05235
AJ
494{
495 tcg_out32(s, 0);
496}
497
10d4af58 498static void tcg_out_dsll(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa)
0119b192
JG
499{
500 tcg_out_opc_sa64(s, OPC_DSLL, OPC_DSLL32, rd, rt, sa);
501}
502
10d4af58 503static void tcg_out_dsrl(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa)
0119b192
JG
504{
505 tcg_out_opc_sa64(s, OPC_DSRL, OPC_DSRL32, rd, rt, sa);
506}
507
10d4af58 508static void tcg_out_dsra(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa)
0119b192
JG
509{
510 tcg_out_opc_sa64(s, OPC_DSRA, OPC_DSRA32, rd, rt, sa);
511}
512
10d4af58 513static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
afa05235 514{
18fec301
AJ
515 /* Simple reg-reg move, optimising out the 'do nothing' case */
516 if (ret != arg) {
2294d05d 517 tcg_out_opc_reg(s, OPC_OR, ret, arg, TCG_REG_ZERO);
18fec301 518 }
78113e83 519 return true;
afa05235
AJ
520}
521
2294d05d
JG
522static void tcg_out_movi(TCGContext *s, TCGType type,
523 TCGReg ret, tcg_target_long arg)
afa05235 524{
2294d05d
JG
525 if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) {
526 arg = (int32_t)arg;
527 }
afa05235 528 if (arg == (int16_t)arg) {
2294d05d
JG
529 tcg_out_opc_imm(s, OPC_ADDIU, ret, TCG_REG_ZERO, arg);
530 return;
531 }
532 if (arg == (uint16_t)arg) {
533 tcg_out_opc_imm(s, OPC_ORI, ret, TCG_REG_ZERO, arg);
534 return;
535 }
536 if (TCG_TARGET_REG_BITS == 32 || arg == (int32_t)arg) {
537 tcg_out_opc_imm(s, OPC_LUI, ret, TCG_REG_ZERO, arg >> 16);
afa05235 538 } else {
2294d05d
JG
539 tcg_out_movi(s, TCG_TYPE_I32, ret, arg >> 31 >> 1);
540 if (arg & 0xffff0000ull) {
541 tcg_out_dsll(s, ret, ret, 16);
542 tcg_out_opc_imm(s, OPC_ORI, ret, ret, arg >> 16);
543 tcg_out_dsll(s, ret, ret, 16);
544 } else {
545 tcg_out_dsll(s, ret, ret, 32);
7dae901d 546 }
afa05235 547 }
2294d05d
JG
548 if (arg & 0xffff) {
549 tcg_out_opc_imm(s, OPC_ORI, ret, ret, arg & 0xffff);
550 }
afa05235
AJ
551}
552
27362b7b 553static void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg, int flags)
afa05235 554{
27362b7b
RH
555 /* ret and arg can't be register tmp0 */
556 tcg_debug_assert(ret != TCG_TMP0);
557 tcg_debug_assert(arg != TCG_TMP0);
558
559 /* With arg = abcd: */
988902fc 560 if (use_mips32r2_instructions) {
27362b7b
RH
561 tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg); /* badc */
562 if (flags & TCG_BSWAP_OS) {
563 tcg_out_opc_reg(s, OPC_SEH, ret, 0, ret); /* ssdc */
564 } else if ((flags & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) {
565 tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xffff); /* 00dc */
988902fc 566 }
27362b7b 567 return;
988902fc 568 }
afa05235 569
27362b7b
RH
570 tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8); /* 0abc */
571 if (!(flags & TCG_BSWAP_IZ)) {
572 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, TCG_TMP0, 0x00ff); /* 000c */
573 }
574 if (flags & TCG_BSWAP_OS) {
575 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24); /* d000 */
576 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16); /* ssd0 */
988902fc 577 } else {
27362b7b
RH
578 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8); /* bcd0 */
579 if (flags & TCG_BSWAP_OZ) {
580 tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00); /* 00d0 */
988902fc 581 }
988902fc 582 }
27362b7b 583 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0); /* ssdc */
afa05235
AJ
584}
585
df5af130 586static void tcg_out_bswap_subr(TCGContext *s, const tcg_insn_unit *sub)
bb08afe9 587{
d7fc9f48
RH
588 if (!tcg_out_opc_jmp(s, OPC_JAL, sub)) {
589 tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP1, (uintptr_t)sub);
590 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_TMP1, 0);
591 }
bb08afe9
JG
592}
593
1fce6534 594static void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg, int flags)
afa05235 595{
988902fc
AJ
596 if (use_mips32r2_instructions) {
597 tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
598 tcg_out_opc_sa(s, OPC_ROTR, ret, ret, 16);
1fce6534
RH
599 if (flags & TCG_BSWAP_OZ) {
600 tcg_out_opc_bf(s, OPC_DEXT, ret, ret, 31, 0);
601 }
988902fc 602 } else {
1fce6534
RH
603 if (flags & TCG_BSWAP_OZ) {
604 tcg_out_bswap_subr(s, bswap32u_addr);
605 } else {
606 tcg_out_bswap_subr(s, bswap32_addr);
607 }
7f54eaa3
JG
608 /* delay slot -- never omit the insn, like tcg_out_mov might. */
609 tcg_out_opc_reg(s, OPC_OR, TCG_TMP0, arg, TCG_REG_ZERO);
610 tcg_out_mov(s, TCG_TYPE_I32, ret, TCG_TMP3);
0119b192
JG
611 }
612}
613
614static void tcg_out_bswap64(TCGContext *s, TCGReg ret, TCGReg arg)
615{
616 if (use_mips32r2_instructions) {
617 tcg_out_opc_reg(s, OPC_DSBH, ret, 0, arg);
618 tcg_out_opc_reg(s, OPC_DSHD, ret, 0, ret);
619 } else {
7f54eaa3
JG
620 tcg_out_bswap_subr(s, bswap64_addr);
621 /* delay slot -- never omit the insn, like tcg_out_mov might. */
622 tcg_out_opc_reg(s, OPC_OR, TCG_TMP0, arg, TCG_REG_ZERO);
623 tcg_out_mov(s, TCG_TYPE_I32, ret, TCG_TMP3);
0119b192
JG
624 }
625}
626
10d4af58 627static void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg)
0119b192
JG
628{
629 if (use_mips32r2_instructions) {
630 tcg_out_opc_bf(s, OPC_DEXT, ret, arg, 31, 0);
631 } else {
632 tcg_out_dsll(s, ret, arg, 32);
633 tcg_out_dsrl(s, ret, ret, 32);
634 }
635}
636
ac0f3b12 637static void tcg_out_ldst(TCGContext *s, MIPSInsn opc, TCGReg data,
f9a71632 638 TCGReg addr, intptr_t ofs)
afa05235 639{
f9a71632
RH
640 int16_t lo = ofs;
641 if (ofs != lo) {
6c530e32 642 tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, ofs - lo);
f9a71632 643 if (addr != TCG_REG_ZERO) {
32b69707 644 tcg_out_opc_reg(s, ALIAS_PADD, TCG_TMP0, TCG_TMP0, addr);
f9a71632 645 }
6c530e32 646 addr = TCG_TMP0;
afa05235 647 }
f9a71632 648 tcg_out_opc_imm(s, opc, data, addr, lo);
afa05235
AJ
649}
650
10d4af58
RH
651static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
652 TCGReg arg1, intptr_t arg2)
afa05235 653{
32b69707
JG
654 MIPSInsn opc = OPC_LD;
655 if (TCG_TARGET_REG_BITS == 32 || type == TCG_TYPE_I32) {
656 opc = OPC_LW;
657 }
658 tcg_out_ldst(s, opc, arg, arg1, arg2);
afa05235
AJ
659}
660
10d4af58
RH
661static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
662 TCGReg arg1, intptr_t arg2)
afa05235 663{
32b69707
JG
664 MIPSInsn opc = OPC_SD;
665 if (TCG_TARGET_REG_BITS == 32 || type == TCG_TYPE_I32) {
666 opc = OPC_SW;
667 }
668 tcg_out_ldst(s, opc, arg, arg1, arg2);
afa05235
AJ
669}
670
10d4af58
RH
671static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
672 TCGReg base, intptr_t ofs)
59d7c14e
RH
673{
674 if (val == 0) {
675 tcg_out_st(s, type, TCG_REG_ZERO, base, ofs);
676 return true;
677 }
678 return false;
679}
680
d9f26847
AJ
681static void tcg_out_addsub2(TCGContext *s, TCGReg rl, TCGReg rh, TCGReg al,
682 TCGReg ah, TCGArg bl, TCGArg bh, bool cbl,
683 bool cbh, bool is_sub)
684{
685 TCGReg th = TCG_TMP1;
686
687 /* If we have a negative constant such that negating it would
688 make the high part zero, we can (usually) eliminate one insn. */
689 if (cbl && cbh && bh == -1 && bl != 0) {
690 bl = -bl;
691 bh = 0;
692 is_sub = !is_sub;
693 }
694
695 /* By operating on the high part first, we get to use the final
696 carry operation to move back from the temporary. */
697 if (!cbh) {
698 tcg_out_opc_reg(s, (is_sub ? OPC_SUBU : OPC_ADDU), th, ah, bh);
699 } else if (bh != 0 || ah == rl) {
700 tcg_out_opc_imm(s, OPC_ADDIU, th, ah, (is_sub ? -bh : bh));
701 } else {
702 th = ah;
703 }
704
705 /* Note that tcg optimization should eliminate the bl == 0 case. */
706 if (is_sub) {
707 if (cbl) {
708 tcg_out_opc_imm(s, OPC_SLTIU, TCG_TMP0, al, bl);
709 tcg_out_opc_imm(s, OPC_ADDIU, rl, al, -bl);
710 } else {
711 tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, al, bl);
712 tcg_out_opc_reg(s, OPC_SUBU, rl, al, bl);
713 }
714 tcg_out_opc_reg(s, OPC_SUBU, rh, th, TCG_TMP0);
715 } else {
716 if (cbl) {
717 tcg_out_opc_imm(s, OPC_ADDIU, rl, al, bl);
718 tcg_out_opc_imm(s, OPC_SLTIU, TCG_TMP0, rl, bl);
719 } else if (rl == al && rl == bl) {
161dec9d 720 tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, al, TCG_TARGET_REG_BITS - 1);
d9f26847
AJ
721 tcg_out_opc_reg(s, OPC_ADDU, rl, al, bl);
722 } else {
723 tcg_out_opc_reg(s, OPC_ADDU, rl, al, bl);
724 tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, rl, (rl == bl ? al : bl));
725 }
726 tcg_out_opc_reg(s, OPC_ADDU, rh, th, TCG_TMP0);
727 }
728}
729
fd1cf666
RH
730/* Bit 0 set if inversion required; bit 1 set if swapping required. */
731#define MIPS_CMP_INV 1
732#define MIPS_CMP_SWAP 2
733
734static const uint8_t mips_cmp_map[16] = {
735 [TCG_COND_LT] = 0,
736 [TCG_COND_LTU] = 0,
737 [TCG_COND_GE] = MIPS_CMP_INV,
738 [TCG_COND_GEU] = MIPS_CMP_INV,
739 [TCG_COND_LE] = MIPS_CMP_INV | MIPS_CMP_SWAP,
740 [TCG_COND_LEU] = MIPS_CMP_INV | MIPS_CMP_SWAP,
741 [TCG_COND_GT] = MIPS_CMP_SWAP,
742 [TCG_COND_GTU] = MIPS_CMP_SWAP,
743};
744
745static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
746 TCGReg arg1, TCGReg arg2)
747{
748 MIPSInsn s_opc = OPC_SLTU;
749 int cmp_map;
750
751 switch (cond) {
752 case TCG_COND_EQ:
753 if (arg2 != 0) {
754 tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
755 arg1 = ret;
756 }
757 tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, 1);
758 break;
759
760 case TCG_COND_NE:
761 if (arg2 != 0) {
762 tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
763 arg1 = ret;
764 }
765 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg1);
766 break;
767
768 case TCG_COND_LT:
769 case TCG_COND_GE:
770 case TCG_COND_LE:
771 case TCG_COND_GT:
772 s_opc = OPC_SLT;
773 /* FALLTHRU */
774
775 case TCG_COND_LTU:
776 case TCG_COND_GEU:
777 case TCG_COND_LEU:
778 case TCG_COND_GTU:
779 cmp_map = mips_cmp_map[cond];
780 if (cmp_map & MIPS_CMP_SWAP) {
781 TCGReg t = arg1;
782 arg1 = arg2;
783 arg2 = t;
784 }
785 tcg_out_opc_reg(s, s_opc, ret, arg1, arg2);
786 if (cmp_map & MIPS_CMP_INV) {
787 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
788 }
789 break;
790
791 default:
792 tcg_abort();
793 break;
794 }
795}
796
c068896f 797static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
bec16311 798 TCGReg arg2, TCGLabel *l)
afa05235 799{
c068896f
RH
800 static const MIPSInsn b_zero[16] = {
801 [TCG_COND_LT] = OPC_BLTZ,
802 [TCG_COND_GT] = OPC_BGTZ,
803 [TCG_COND_LE] = OPC_BLEZ,
804 [TCG_COND_GE] = OPC_BGEZ,
805 };
806
c068896f
RH
807 MIPSInsn s_opc = OPC_SLTU;
808 MIPSInsn b_opc;
809 int cmp_map;
afa05235
AJ
810
811 switch (cond) {
812 case TCG_COND_EQ:
c068896f 813 b_opc = OPC_BEQ;
afa05235
AJ
814 break;
815 case TCG_COND_NE:
c068896f 816 b_opc = OPC_BNE;
afa05235 817 break;
c068896f 818
afa05235 819 case TCG_COND_LT:
c068896f 820 case TCG_COND_GT:
afa05235 821 case TCG_COND_LE:
c068896f 822 case TCG_COND_GE:
0f46c064 823 if (arg2 == 0) {
c068896f
RH
824 b_opc = b_zero[cond];
825 arg2 = arg1;
826 arg1 = 0;
827 break;
0f46c064 828 }
c068896f
RH
829 s_opc = OPC_SLT;
830 /* FALLTHRU */
831
832 case TCG_COND_LTU:
833 case TCG_COND_GTU:
afa05235 834 case TCG_COND_LEU:
c068896f
RH
835 case TCG_COND_GEU:
836 cmp_map = mips_cmp_map[cond];
837 if (cmp_map & MIPS_CMP_SWAP) {
838 TCGReg t = arg1;
839 arg1 = arg2;
840 arg2 = t;
0f46c064 841 }
c068896f
RH
842 tcg_out_opc_reg(s, s_opc, TCG_TMP0, arg1, arg2);
843 b_opc = (cmp_map & MIPS_CMP_INV ? OPC_BEQ : OPC_BNE);
844 arg1 = TCG_TMP0;
845 arg2 = TCG_REG_ZERO;
afa05235 846 break;
c068896f 847
afa05235
AJ
848 default:
849 tcg_abort();
850 break;
851 }
c068896f
RH
852
853 tcg_out_opc_br(s, b_opc, arg1, arg2);
91a7fd1f 854 tcg_out_reloc(s, s->code_ptr - 1, R_MIPS_PC16, l, 0);
afa05235
AJ
855 tcg_out_nop(s);
856}
857
1db1c4d7
RH
858static TCGReg tcg_out_reduce_eq2(TCGContext *s, TCGReg tmp0, TCGReg tmp1,
859 TCGReg al, TCGReg ah,
860 TCGReg bl, TCGReg bh)
861{
862 /* Merge highpart comparison into AH. */
863 if (bh != 0) {
864 if (ah != 0) {
865 tcg_out_opc_reg(s, OPC_XOR, tmp0, ah, bh);
866 ah = tmp0;
867 } else {
868 ah = bh;
869 }
870 }
871 /* Merge lowpart comparison into AL. */
872 if (bl != 0) {
873 if (al != 0) {
874 tcg_out_opc_reg(s, OPC_XOR, tmp1, al, bl);
875 al = tmp1;
876 } else {
877 al = bl;
878 }
879 }
880 /* Merge high and low part comparisons into AL. */
881 if (ah != 0) {
882 if (al != 0) {
883 tcg_out_opc_reg(s, OPC_OR, tmp0, ah, al);
884 al = tmp0;
885 } else {
886 al = ah;
887 }
888 }
889 return al;
890}
891
9a2f0bfe
RH
892static void tcg_out_setcond2(TCGContext *s, TCGCond cond, TCGReg ret,
893 TCGReg al, TCGReg ah, TCGReg bl, TCGReg bh)
894{
895 TCGReg tmp0 = TCG_TMP0;
896 TCGReg tmp1 = ret;
897
eabb7b91 898 tcg_debug_assert(ret != TCG_TMP0);
9a2f0bfe 899 if (ret == ah || ret == bh) {
eabb7b91 900 tcg_debug_assert(ret != TCG_TMP1);
9a2f0bfe
RH
901 tmp1 = TCG_TMP1;
902 }
903
904 switch (cond) {
905 case TCG_COND_EQ:
906 case TCG_COND_NE:
1db1c4d7
RH
907 tmp1 = tcg_out_reduce_eq2(s, tmp0, tmp1, al, ah, bl, bh);
908 tcg_out_setcond(s, cond, ret, tmp1, TCG_REG_ZERO);
9a2f0bfe
RH
909 break;
910
911 default:
912 tcg_out_setcond(s, TCG_COND_EQ, tmp0, ah, bh);
913 tcg_out_setcond(s, tcg_unsigned_cond(cond), tmp1, al, bl);
914 tcg_out_opc_reg(s, OPC_AND, tmp1, tmp1, tmp0);
915 tcg_out_setcond(s, tcg_high_cond(cond), tmp0, ah, bh);
916 tcg_out_opc_reg(s, OPC_OR, ret, tmp1, tmp0);
917 break;
918 }
919}
920
3401fd25 921static void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGReg al, TCGReg ah,
bec16311 922 TCGReg bl, TCGReg bh, TCGLabel *l)
3401fd25
RH
923{
924 TCGCond b_cond = TCG_COND_NE;
925 TCGReg tmp = TCG_TMP1;
926
927 /* With branches, we emit between 4 and 9 insns with 2 or 3 branches.
928 With setcond, we emit between 3 and 10 insns and only 1 branch,
929 which ought to get better branch prediction. */
930 switch (cond) {
931 case TCG_COND_EQ:
932 case TCG_COND_NE:
933 b_cond = cond;
934 tmp = tcg_out_reduce_eq2(s, TCG_TMP0, TCG_TMP1, al, ah, bl, bh);
afa05235 935 break;
afa05235 936
afa05235 937 default:
5d831be2 938 /* Minimize code size by preferring a compare not requiring INV. */
3401fd25
RH
939 if (mips_cmp_map[cond] & MIPS_CMP_INV) {
940 cond = tcg_invert_cond(cond);
941 b_cond = TCG_COND_EQ;
942 }
943 tcg_out_setcond2(s, cond, tmp, al, ah, bl, bh);
944 break;
afa05235
AJ
945 }
946
bec16311 947 tcg_out_brcond(s, b_cond, tmp, TCG_REG_ZERO, l);
afa05235
AJ
948}
949
7d7c4930 950static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
137d6390 951 TCGReg c1, TCGReg c2, TCGReg v1, TCGReg v2)
7d7c4930 952{
137d6390
JH
953 bool eqz = false;
954
955 /* If one of the values is zero, put it last to match SEL*Z instructions */
956 if (use_mips32r6_instructions && v1 == 0) {
957 v1 = v2;
958 v2 = 0;
959 cond = tcg_invert_cond(cond);
960 }
33fac20b 961
7d7c4930
AJ
962 switch (cond) {
963 case TCG_COND_EQ:
137d6390 964 eqz = true;
33fac20b 965 /* FALLTHRU */
7d7c4930 966 case TCG_COND_NE:
33fac20b 967 if (c2 != 0) {
6c530e32 968 tcg_out_opc_reg(s, OPC_XOR, TCG_TMP0, c1, c2);
33fac20b 969 c1 = TCG_TMP0;
7d7c4930
AJ
970 }
971 break;
33fac20b 972
7d7c4930 973 default:
5d831be2 974 /* Minimize code size by preferring a compare not requiring INV. */
33fac20b
RH
975 if (mips_cmp_map[cond] & MIPS_CMP_INV) {
976 cond = tcg_invert_cond(cond);
137d6390 977 eqz = true;
33fac20b
RH
978 }
979 tcg_out_setcond(s, cond, TCG_TMP0, c1, c2);
980 c1 = TCG_TMP0;
7d7c4930
AJ
981 break;
982 }
33fac20b 983
137d6390
JH
984 if (use_mips32r6_instructions) {
985 MIPSInsn m_opc_t = eqz ? OPC_SELEQZ : OPC_SELNEZ;
986 MIPSInsn m_opc_f = eqz ? OPC_SELNEZ : OPC_SELEQZ;
987
988 if (v2 != 0) {
989 tcg_out_opc_reg(s, m_opc_f, TCG_TMP1, v2, c1);
990 }
991 tcg_out_opc_reg(s, m_opc_t, ret, v1, c1);
992 if (v2 != 0) {
993 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP1);
994 }
995 } else {
996 MIPSInsn m_opc = eqz ? OPC_MOVZ : OPC_MOVN;
997
998 tcg_out_opc_reg(s, m_opc, ret, v1, c1);
999
1000 /* This should be guaranteed via constraints */
1001 tcg_debug_assert(v2 == ret);
1002 }
7d7c4930
AJ
1003}
1004
2be7d76b 1005static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail)
9d8bf2d1
RH
1006{
1007 /* Note that the ABI requires the called function's address to be
1008 loaded into T9, even if a direct branch is in range. */
1009 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T9, (uintptr_t)arg);
1010
1011 /* But do try a direct branch, allowing the cpu better insn prefetch. */
ce0236cf
RH
1012 if (tail) {
1013 if (!tcg_out_opc_jmp(s, OPC_J, arg)) {
1014 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_T9, 0);
1015 }
1016 } else {
1017 if (!tcg_out_opc_jmp(s, OPC_JAL, arg)) {
1018 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
1019 }
9d8bf2d1 1020 }
ce0236cf 1021}
9d8bf2d1 1022
cee44b03
RH
1023static void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg,
1024 const TCGHelperInfo *info)
ce0236cf
RH
1025{
1026 tcg_out_call_int(s, arg, false);
9d8bf2d1
RH
1027 tcg_out_nop(s);
1028}
1029
afa05235 1030#if defined(CONFIG_SOFTMMU)
4b473e0c 1031static void * const qemu_ld_helpers[(MO_SSIZE | MO_BSWAP) + 1] = {
ce0236cf
RH
1032 [MO_UB] = helper_ret_ldub_mmu,
1033 [MO_SB] = helper_ret_ldsb_mmu,
1034 [MO_LEUW] = helper_le_lduw_mmu,
1035 [MO_LESW] = helper_le_ldsw_mmu,
1036 [MO_LEUL] = helper_le_ldul_mmu,
fc313c64 1037 [MO_LEUQ] = helper_le_ldq_mmu,
ce0236cf
RH
1038 [MO_BEUW] = helper_be_lduw_mmu,
1039 [MO_BESW] = helper_be_ldsw_mmu,
1040 [MO_BEUL] = helper_be_ldul_mmu,
fc313c64 1041 [MO_BEUQ] = helper_be_ldq_mmu,
f0d70331
JG
1042#if TCG_TARGET_REG_BITS == 64
1043 [MO_LESL] = helper_le_ldsl_mmu,
1044 [MO_BESL] = helper_be_ldsl_mmu,
1045#endif
e141ab52
BS
1046};
1047
4b473e0c 1048static void * const qemu_st_helpers[(MO_SIZE | MO_BSWAP) + 1] = {
ce0236cf
RH
1049 [MO_UB] = helper_ret_stb_mmu,
1050 [MO_LEUW] = helper_le_stw_mmu,
1051 [MO_LEUL] = helper_le_stl_mmu,
fc313c64 1052 [MO_LEUQ] = helper_le_stq_mmu,
ce0236cf
RH
1053 [MO_BEUW] = helper_be_stw_mmu,
1054 [MO_BEUL] = helper_be_stl_mmu,
fc313c64 1055 [MO_BEUQ] = helper_be_stq_mmu,
e141ab52 1056};
afa05235 1057
9d8bf2d1
RH
1058/* Helper routines for marshalling helper function arguments into
1059 * the correct registers and stack.
1060 * I is where we want to put this argument, and is updated and returned
1061 * for the next call. ARG is the argument itself.
1062 *
1063 * We provide routines for arguments which are: immediate, 32 bit
1064 * value in register, 16 and 8 bit values in register (which must be zero
1065 * extended before use) and 64 bit value in a lo:hi register pair.
1066 */
1067
1068static int tcg_out_call_iarg_reg(TCGContext *s, int i, TCGReg arg)
afa05235 1069{
9d8bf2d1
RH
1070 if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
1071 tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[i], arg);
1072 } else {
f0d70331
JG
1073 /* For N32 and N64, the initial offset is different. But there
1074 we also have 8 argument register so we don't run out here. */
1075 tcg_debug_assert(TCG_TARGET_REG_BITS == 32);
9d8bf2d1
RH
1076 tcg_out_st(s, TCG_TYPE_REG, arg, TCG_REG_SP, 4 * i);
1077 }
1078 return i + 1;
1079}
afa05235 1080
9d8bf2d1
RH
1081static int tcg_out_call_iarg_reg8(TCGContext *s, int i, TCGReg arg)
1082{
6c530e32 1083 TCGReg tmp = TCG_TMP0;
9d8bf2d1
RH
1084 if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
1085 tmp = tcg_target_call_iarg_regs[i];
1086 }
1087 tcg_out_opc_imm(s, OPC_ANDI, tmp, arg, 0xff);
1088 return tcg_out_call_iarg_reg(s, i, tmp);
1089}
1090
1091static int tcg_out_call_iarg_reg16(TCGContext *s, int i, TCGReg arg)
1092{
6c530e32 1093 TCGReg tmp = TCG_TMP0;
9d8bf2d1
RH
1094 if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
1095 tmp = tcg_target_call_iarg_regs[i];
1096 }
1097 tcg_out_opc_imm(s, OPC_ANDI, tmp, arg, 0xffff);
1098 return tcg_out_call_iarg_reg(s, i, tmp);
1099}
1100
1101static int tcg_out_call_iarg_imm(TCGContext *s, int i, TCGArg arg)
1102{
6c530e32 1103 TCGReg tmp = TCG_TMP0;
9d8bf2d1
RH
1104 if (arg == 0) {
1105 tmp = TCG_REG_ZERO;
afa05235 1106 } else {
9d8bf2d1
RH
1107 if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
1108 tmp = tcg_target_call_iarg_regs[i];
1109 }
1110 tcg_out_movi(s, TCG_TYPE_REG, tmp, arg);
afa05235 1111 }
9d8bf2d1
RH
1112 return tcg_out_call_iarg_reg(s, i, tmp);
1113}
1114
1115static int tcg_out_call_iarg_reg2(TCGContext *s, int i, TCGReg al, TCGReg ah)
1116{
f0d70331 1117 tcg_debug_assert(TCG_TARGET_REG_BITS == 32);
9d8bf2d1
RH
1118 i = (i + 1) & ~1;
1119 i = tcg_out_call_iarg_reg(s, i, (MIPS_BE ? ah : al));
1120 i = tcg_out_call_iarg_reg(s, i, (MIPS_BE ? al : ah));
1121 return i;
1122}
1123
269bd5d8
RH
1124/* We expect to use a 16-bit negative offset from ENV. */
1125QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0);
1126QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -32768);
1127
ac33373e
RH
1128/*
1129 * Perform the tlb comparison operation.
1130 * The complete host address is placed in BASE.
1131 * Clobbers TMP0, TMP1, TMP2, TMP3.
1132 */
9d8bf2d1 1133static void tcg_out_tlb_load(TCGContext *s, TCGReg base, TCGReg addrl,
9002ffcb 1134 TCGReg addrh, MemOpIdx oi,
9d8bf2d1
RH
1135 tcg_insn_unit *label_ptr[2], bool is_load)
1136{
14776ab5 1137 MemOp opc = get_memop(oi);
85aa8081 1138 unsigned a_bits = get_alignment_bits(opc);
d9e52834
RH
1139 unsigned s_bits = opc & MO_SIZE;
1140 unsigned a_mask = (1 << a_bits) - 1;
1141 unsigned s_mask = (1 << s_bits) - 1;
81dfaf1a 1142 int mem_index = get_mmuidx(oi);
269bd5d8
RH
1143 int fast_off = TLB_MASK_TABLE_OFS(mem_index);
1144 int mask_off = fast_off + offsetof(CPUTLBDescFast, mask);
1145 int table_off = fast_off + offsetof(CPUTLBDescFast, table);
ac33373e
RH
1146 int add_off = offsetof(CPUTLBEntry, addend);
1147 int cmp_off = (is_load ? offsetof(CPUTLBEntry, addr_read)
1148 : offsetof(CPUTLBEntry, addr_write));
d9e52834 1149 target_ulong tlb_mask;
9d8bf2d1 1150
ac33373e 1151 /* Load tlb_mask[mmu_idx] and tlb_table[mmu_idx]. */
269bd5d8
RH
1152 tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_AREG0, mask_off);
1153 tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP1, TCG_AREG0, table_off);
ac33373e
RH
1154
1155 /* Extract the TLB index from the address into TMP3. */
1156 tcg_out_opc_sa(s, ALIAS_TSRL, TCG_TMP3, addrl,
1157 TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
1158 tcg_out_opc_reg(s, OPC_AND, TCG_TMP3, TCG_TMP3, TCG_TMP0);
1159
1160 /* Add the tlb_table pointer, creating the CPUTLBEntry address in TMP3. */
1161 tcg_out_opc_reg(s, ALIAS_PADD, TCG_TMP3, TCG_TMP3, TCG_TMP1);
1162
ac33373e 1163 /* Load the (low-half) tlb comparator. */
f0d70331 1164 if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
d9e52834 1165 tcg_out_ldst(s, OPC_LW, TCG_TMP0, TCG_TMP3, cmp_off + LO_OFF);
f0d70331 1166 } else {
ac33373e
RH
1167 tcg_out_ldst(s, (TARGET_LONG_BITS == 64 ? OPC_LD
1168 : TCG_TARGET_REG_BITS == 64 ? OPC_LWU : OPC_LW),
1169 TCG_TMP0, TCG_TMP3, cmp_off);
5eb4f645 1170 }
9d8bf2d1 1171
f0d70331
JG
1172 /* Zero extend a 32-bit guest address for a 64-bit host. */
1173 if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
1174 tcg_out_ext32u(s, base, addrl);
1175 addrl = base;
1176 }
d9e52834
RH
1177
1178 /*
1179 * Mask the page bits, keeping the alignment bits to compare against.
1180 * For unaligned accesses, compare against the end of the access to
1181 * verify that it does not cross a page boundary.
1182 */
1183 tlb_mask = (target_ulong)TARGET_PAGE_MASK | a_mask;
1184 tcg_out_movi(s, TCG_TYPE_I32, TCG_TMP1, tlb_mask);
1185 if (a_mask >= s_mask) {
1186 tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, addrl);
1187 } else {
1188 tcg_out_opc_imm(s, ALIAS_PADDI, TCG_TMP2, addrl, s_mask - a_mask);
1189 tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, TCG_TMP2);
1190 }
1191
1192 if (TCG_TARGET_REG_BITS >= TARGET_LONG_BITS) {
1193 /* Load the tlb addend for the fast path. */
1194 tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP2, TCG_TMP3, add_off);
1195 }
f0d70331 1196
9d8bf2d1 1197 label_ptr[0] = s->code_ptr;
6c530e32 1198 tcg_out_opc_br(s, OPC_BNE, TCG_TMP1, TCG_TMP0);
afa05235 1199
5eb4f645 1200 /* Load and test the high half tlb comparator. */
f0d70331 1201 if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
9d8bf2d1 1202 /* delay slot */
d9e52834 1203 tcg_out_ldst(s, OPC_LW, TCG_TMP0, TCG_TMP3, cmp_off + HI_OFF);
5eb4f645 1204
f0d70331 1205 /* Load the tlb addend for the fast path. */
ac33373e 1206 tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP2, TCG_TMP3, add_off);
afa05235 1207
9d8bf2d1 1208 label_ptr[1] = s->code_ptr;
5eb4f645 1209 tcg_out_opc_br(s, OPC_BNE, addrh, TCG_TMP0);
9d8bf2d1 1210 }
afa05235 1211
9d8bf2d1 1212 /* delay slot */
f0d70331 1213 tcg_out_opc_reg(s, ALIAS_PADD, base, TCG_TMP2, addrl);
9d8bf2d1 1214}
afa05235 1215
9002ffcb 1216static void add_qemu_ldst_label(TCGContext *s, int is_ld, MemOpIdx oi,
f0d70331 1217 TCGType ext,
9d8bf2d1
RH
1218 TCGReg datalo, TCGReg datahi,
1219 TCGReg addrlo, TCGReg addrhi,
3972ef6f 1220 void *raddr, tcg_insn_unit *label_ptr[2])
9d8bf2d1
RH
1221{
1222 TCGLabelQemuLdst *label = new_ldst_label(s);
1223
1224 label->is_ld = is_ld;
3972ef6f 1225 label->oi = oi;
f0d70331 1226 label->type = ext;
9d8bf2d1
RH
1227 label->datalo_reg = datalo;
1228 label->datahi_reg = datahi;
1229 label->addrlo_reg = addrlo;
1230 label->addrhi_reg = addrhi;
e5e2e4c7 1231 label->raddr = tcg_splitwx_to_rx(raddr);
9d8bf2d1 1232 label->label_ptr[0] = label_ptr[0];
f0d70331 1233 if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
9d8bf2d1
RH
1234 label->label_ptr[1] = label_ptr[1];
1235 }
1236}
1237
aeee05f5 1238static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
9d8bf2d1 1239{
df5af130 1240 const tcg_insn_unit *tgt_rx = tcg_splitwx_to_rx(s->code_ptr);
9002ffcb 1241 MemOpIdx oi = l->oi;
14776ab5 1242 MemOp opc = get_memop(oi);
ce0236cf 1243 TCGReg v0;
9d8bf2d1
RH
1244 int i;
1245
1246 /* resolve label address */
df5af130 1247 if (!reloc_pc16(l->label_ptr[0], tgt_rx)
91a7fd1f 1248 || (TCG_TARGET_REG_BITS < TARGET_LONG_BITS
df5af130 1249 && !reloc_pc16(l->label_ptr[1], tgt_rx))) {
91a7fd1f 1250 return false;
9d8bf2d1
RH
1251 }
1252
ce0236cf 1253 i = 1;
f0d70331 1254 if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
9d8bf2d1
RH
1255 i = tcg_out_call_iarg_reg2(s, i, l->addrlo_reg, l->addrhi_reg);
1256 } else {
1257 i = tcg_out_call_iarg_reg(s, i, l->addrlo_reg);
1258 }
3972ef6f 1259 i = tcg_out_call_iarg_imm(s, i, oi);
ce0236cf 1260 i = tcg_out_call_iarg_imm(s, i, (intptr_t)l->raddr);
2b7ec66f 1261 tcg_out_call_int(s, qemu_ld_helpers[opc & (MO_BSWAP | MO_SSIZE)], false);
ce0236cf
RH
1262 /* delay slot */
1263 tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
9d8bf2d1 1264
ce0236cf 1265 v0 = l->datalo_reg;
f0d70331 1266 if (TCG_TARGET_REG_BITS == 32 && (opc & MO_SIZE) == MO_64) {
9d8bf2d1
RH
1267 /* We eliminated V0 from the possible output registers, so it
1268 cannot be clobbered here. So we must move V1 first. */
ce0236cf
RH
1269 if (MIPS_BE) {
1270 tcg_out_mov(s, TCG_TYPE_I32, v0, TCG_REG_V1);
1271 v0 = l->datahi_reg;
1272 } else {
1273 tcg_out_mov(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_V1);
1274 }
afa05235
AJ
1275 }
1276
6d8ff4d8 1277 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
91a7fd1f
RH
1278 if (!reloc_pc16(s->code_ptr - 1, l->raddr)) {
1279 return false;
1280 }
a31aa4ce 1281
ce0236cf 1282 /* delay slot */
f0d70331
JG
1283 if (TCG_TARGET_REG_BITS == 64 && l->type == TCG_TYPE_I32) {
1284 /* we always sign-extend 32-bit loads */
1285 tcg_out_opc_sa(s, OPC_SLL, v0, TCG_REG_V0, 0);
1286 } else {
1287 tcg_out_opc_reg(s, OPC_OR, v0, TCG_REG_V0, TCG_REG_ZERO);
1288 }
aeee05f5 1289 return true;
9d8bf2d1 1290}
afa05235 1291
aeee05f5 1292static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
9d8bf2d1 1293{
df5af130 1294 const tcg_insn_unit *tgt_rx = tcg_splitwx_to_rx(s->code_ptr);
9002ffcb 1295 MemOpIdx oi = l->oi;
14776ab5
TN
1296 MemOp opc = get_memop(oi);
1297 MemOp s_bits = opc & MO_SIZE;
9d8bf2d1
RH
1298 int i;
1299
1300 /* resolve label address */
df5af130 1301 if (!reloc_pc16(l->label_ptr[0], tgt_rx)
91a7fd1f 1302 || (TCG_TARGET_REG_BITS < TARGET_LONG_BITS
df5af130 1303 && !reloc_pc16(l->label_ptr[1], tgt_rx))) {
91a7fd1f 1304 return false;
9d8bf2d1 1305 }
afa05235 1306
ce0236cf 1307 i = 1;
f0d70331 1308 if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
9d8bf2d1 1309 i = tcg_out_call_iarg_reg2(s, i, l->addrlo_reg, l->addrhi_reg);
cc01cc8e 1310 } else {
9d8bf2d1
RH
1311 i = tcg_out_call_iarg_reg(s, i, l->addrlo_reg);
1312 }
1313 switch (s_bits) {
1314 case MO_8:
1315 i = tcg_out_call_iarg_reg8(s, i, l->datalo_reg);
1316 break;
1317 case MO_16:
1318 i = tcg_out_call_iarg_reg16(s, i, l->datalo_reg);
1319 break;
1320 case MO_32:
1321 i = tcg_out_call_iarg_reg(s, i, l->datalo_reg);
1322 break;
1323 case MO_64:
f0d70331
JG
1324 if (TCG_TARGET_REG_BITS == 32) {
1325 i = tcg_out_call_iarg_reg2(s, i, l->datalo_reg, l->datahi_reg);
1326 } else {
1327 i = tcg_out_call_iarg_reg(s, i, l->datalo_reg);
1328 }
9d8bf2d1
RH
1329 break;
1330 default:
1331 tcg_abort();
cc01cc8e 1332 }
3972ef6f 1333 i = tcg_out_call_iarg_imm(s, i, oi);
9d8bf2d1 1334
ce0236cf
RH
1335 /* Tail call to the store helper. Thus force the return address
1336 computation to take place in the return address register. */
1337 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RA, (intptr_t)l->raddr);
1338 i = tcg_out_call_iarg_reg(s, i, TCG_REG_RA);
2b7ec66f 1339 tcg_out_call_int(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)], true);
ce0236cf
RH
1340 /* delay slot */
1341 tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
aeee05f5 1342 return true;
9d8bf2d1 1343}
23a79c11
RH
1344
1345#else
1346
1347static void tcg_out_test_alignment(TCGContext *s, bool is_ld, TCGReg addrlo,
1348 TCGReg addrhi, unsigned a_bits)
1349{
1350 unsigned a_mask = (1 << a_bits) - 1;
1351 TCGLabelQemuLdst *l = new_ldst_label(s);
1352
1353 l->is_ld = is_ld;
1354 l->addrlo_reg = addrlo;
1355 l->addrhi_reg = addrhi;
1356
1357 /* We are expecting a_bits to max out at 7, much lower than ANDI. */
1358 tcg_debug_assert(a_bits < 16);
1359 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, addrlo, a_mask);
1360
1361 l->label_ptr[0] = s->code_ptr;
1362 if (use_mips32r6_instructions) {
1363 tcg_out_opc_br(s, OPC_BNEZALC_R6, TCG_REG_ZERO, TCG_TMP0);
1364 } else {
1365 tcg_out_opc_br(s, OPC_BNEL, TCG_TMP0, TCG_REG_ZERO);
1366 tcg_out_nop(s);
1367 }
1368
1369 l->raddr = tcg_splitwx_to_rx(s->code_ptr);
1370}
1371
1372static bool tcg_out_fail_alignment(TCGContext *s, TCGLabelQemuLdst *l)
1373{
1374 void *target;
1375
1376 if (!reloc_pc16(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
1377 return false;
1378 }
1379
1380 if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
1381 /* A0 is env, A1 is skipped, A2:A3 is the uint64_t address. */
1382 TCGReg a2 = MIPS_BE ? l->addrhi_reg : l->addrlo_reg;
1383 TCGReg a3 = MIPS_BE ? l->addrlo_reg : l->addrhi_reg;
1384
1385 if (a3 != TCG_REG_A2) {
1386 tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_A2, a2);
1387 tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_A3, a3);
1388 } else if (a2 != TCG_REG_A3) {
1389 tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_A3, a3);
1390 tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_A2, a2);
1391 } else {
1392 tcg_out_mov(s, TCG_TYPE_I32, TCG_TMP0, TCG_REG_A2);
1393 tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_A2, TCG_REG_A3);
1394 tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_A3, TCG_TMP0);
1395 }
1396 } else {
1397 tcg_out_mov(s, TCG_TYPE_TL, TCG_REG_A1, l->addrlo_reg);
1398 }
1399 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A0, TCG_AREG0);
1400
1401 /*
1402 * Tail call to the helper, with the return address back inline.
1403 * We have arrived here via BNEL, so $31 is already set.
1404 */
1405 target = (l->is_ld ? helper_unaligned_ld : helper_unaligned_st);
1406 tcg_out_call_int(s, target, true);
1407 return true;
1408}
1409
1410static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1411{
1412 return tcg_out_fail_alignment(s, l);
1413}
1414
1415static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1416{
1417 return tcg_out_fail_alignment(s, l);
1418}
1419#endif /* SOFTMMU */
afa05235 1420
bb08afe9 1421static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi,
14776ab5 1422 TCGReg base, MemOp opc, bool is_64)
9d8bf2d1 1423{
4214a8cb 1424 switch (opc & (MO_SSIZE | MO_BSWAP)) {
9d8bf2d1 1425 case MO_UB:
bb08afe9 1426 tcg_out_opc_imm(s, OPC_LBU, lo, base, 0);
afa05235 1427 break;
9d8bf2d1 1428 case MO_SB:
bb08afe9 1429 tcg_out_opc_imm(s, OPC_LB, lo, base, 0);
afa05235 1430 break;
9d8bf2d1 1431 case MO_UW | MO_BSWAP:
6c530e32 1432 tcg_out_opc_imm(s, OPC_LHU, TCG_TMP1, base, 0);
27362b7b 1433 tcg_out_bswap16(s, lo, TCG_TMP1, TCG_BSWAP_IZ | TCG_BSWAP_OZ);
afa05235 1434 break;
9d8bf2d1 1435 case MO_UW:
bb08afe9 1436 tcg_out_opc_imm(s, OPC_LHU, lo, base, 0);
afa05235 1437 break;
9d8bf2d1 1438 case MO_SW | MO_BSWAP:
6c530e32 1439 tcg_out_opc_imm(s, OPC_LHU, TCG_TMP1, base, 0);
27362b7b 1440 tcg_out_bswap16(s, lo, TCG_TMP1, TCG_BSWAP_IZ | TCG_BSWAP_OS);
afa05235 1441 break;
9d8bf2d1 1442 case MO_SW:
bb08afe9 1443 tcg_out_opc_imm(s, OPC_LH, lo, base, 0);
9d8bf2d1
RH
1444 break;
1445 case MO_UL | MO_BSWAP:
f0d70331
JG
1446 if (TCG_TARGET_REG_BITS == 64 && is_64) {
1447 if (use_mips32r2_instructions) {
1448 tcg_out_opc_imm(s, OPC_LWU, lo, base, 0);
1fce6534 1449 tcg_out_bswap32(s, lo, lo, TCG_BSWAP_IZ | TCG_BSWAP_OZ);
f0d70331
JG
1450 } else {
1451 tcg_out_bswap_subr(s, bswap32u_addr);
1452 /* delay slot */
1453 tcg_out_opc_imm(s, OPC_LWU, TCG_TMP0, base, 0);
1454 tcg_out_mov(s, TCG_TYPE_I64, lo, TCG_TMP3);
1455 }
1456 break;
1457 }
1458 /* FALLTHRU */
1459 case MO_SL | MO_BSWAP:
bb08afe9
JG
1460 if (use_mips32r2_instructions) {
1461 tcg_out_opc_imm(s, OPC_LW, lo, base, 0);
1fce6534 1462 tcg_out_bswap32(s, lo, lo, 0);
bb08afe9
JG
1463 } else {
1464 tcg_out_bswap_subr(s, bswap32_addr);
1465 /* delay slot */
1466 tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, base, 0);
1467 tcg_out_mov(s, TCG_TYPE_I32, lo, TCG_TMP3);
1468 }
9d8bf2d1
RH
1469 break;
1470 case MO_UL:
f0d70331
JG
1471 if (TCG_TARGET_REG_BITS == 64 && is_64) {
1472 tcg_out_opc_imm(s, OPC_LWU, lo, base, 0);
1473 break;
1474 }
1475 /* FALLTHRU */
1476 case MO_SL:
bb08afe9 1477 tcg_out_opc_imm(s, OPC_LW, lo, base, 0);
9d8bf2d1 1478 break;
fc313c64 1479 case MO_UQ | MO_BSWAP:
f0d70331
JG
1480 if (TCG_TARGET_REG_BITS == 64) {
1481 if (use_mips32r2_instructions) {
1482 tcg_out_opc_imm(s, OPC_LD, lo, base, 0);
1483 tcg_out_bswap64(s, lo, lo);
1484 } else {
1485 tcg_out_bswap_subr(s, bswap64_addr);
1486 /* delay slot */
1487 tcg_out_opc_imm(s, OPC_LD, TCG_TMP0, base, 0);
1488 tcg_out_mov(s, TCG_TYPE_I64, lo, TCG_TMP3);
1489 }
1490 } else if (use_mips32r2_instructions) {
bb08afe9
JG
1491 tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, base, 0);
1492 tcg_out_opc_imm(s, OPC_LW, TCG_TMP1, base, 4);
1493 tcg_out_opc_reg(s, OPC_WSBH, TCG_TMP0, 0, TCG_TMP0);
1494 tcg_out_opc_reg(s, OPC_WSBH, TCG_TMP1, 0, TCG_TMP1);
1495 tcg_out_opc_sa(s, OPC_ROTR, MIPS_BE ? lo : hi, TCG_TMP0, 16);
1496 tcg_out_opc_sa(s, OPC_ROTR, MIPS_BE ? hi : lo, TCG_TMP1, 16);
1497 } else {
1498 tcg_out_bswap_subr(s, bswap32_addr);
1499 /* delay slot */
1500 tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, base, 0);
1501 tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, base, 4);
1502 tcg_out_bswap_subr(s, bswap32_addr);
1503 /* delay slot */
1504 tcg_out_mov(s, TCG_TYPE_I32, MIPS_BE ? lo : hi, TCG_TMP3);
1505 tcg_out_mov(s, TCG_TYPE_I32, MIPS_BE ? hi : lo, TCG_TMP3);
1506 }
9d8bf2d1 1507 break;
fc313c64 1508 case MO_UQ:
bb08afe9 1509 /* Prefer to load from offset 0 first, but allow for overlap. */
f0d70331
JG
1510 if (TCG_TARGET_REG_BITS == 64) {
1511 tcg_out_opc_imm(s, OPC_LD, lo, base, 0);
1512 } else if (MIPS_BE ? hi != base : lo == base) {
bb08afe9
JG
1513 tcg_out_opc_imm(s, OPC_LW, hi, base, HI_OFF);
1514 tcg_out_opc_imm(s, OPC_LW, lo, base, LO_OFF);
1515 } else {
1516 tcg_out_opc_imm(s, OPC_LW, lo, base, LO_OFF);
1517 tcg_out_opc_imm(s, OPC_LW, hi, base, HI_OFF);
1518 }
afa05235
AJ
1519 break;
1520 default:
1521 tcg_abort();
1522 }
afa05235
AJ
1523}
1524
d9e52834 1525static void tcg_out_qemu_ld_unalign(TCGContext *s, TCGReg lo, TCGReg hi,
23a79c11
RH
1526 TCGReg base, MemOp opc, bool is_64)
1527{
1528 const MIPSInsn lw1 = MIPS_BE ? OPC_LWL : OPC_LWR;
1529 const MIPSInsn lw2 = MIPS_BE ? OPC_LWR : OPC_LWL;
1530 const MIPSInsn ld1 = MIPS_BE ? OPC_LDL : OPC_LDR;
1531 const MIPSInsn ld2 = MIPS_BE ? OPC_LDR : OPC_LDL;
1532
1533 bool sgn = (opc & MO_SIGN);
1534
1535 switch (opc & (MO_SSIZE | MO_BSWAP)) {
1536 case MO_SW | MO_BE:
1537 case MO_UW | MO_BE:
1538 tcg_out_opc_imm(s, sgn ? OPC_LB : OPC_LBU, TCG_TMP0, base, 0);
1539 tcg_out_opc_imm(s, OPC_LBU, lo, base, 1);
1540 if (use_mips32r2_instructions) {
1541 tcg_out_opc_bf(s, OPC_INS, lo, TCG_TMP0, 31, 8);
1542 } else {
1543 tcg_out_opc_sa(s, OPC_SLL, TCG_TMP0, TCG_TMP0, 8);
1544 tcg_out_opc_reg(s, OPC_OR, lo, TCG_TMP0, TCG_TMP1);
1545 }
1546 break;
1547
1548 case MO_SW | MO_LE:
1549 case MO_UW | MO_LE:
1550 if (use_mips32r2_instructions && lo != base) {
1551 tcg_out_opc_imm(s, OPC_LBU, lo, base, 0);
1552 tcg_out_opc_imm(s, sgn ? OPC_LB : OPC_LBU, TCG_TMP0, base, 1);
1553 tcg_out_opc_bf(s, OPC_INS, lo, TCG_TMP0, 31, 8);
1554 } else {
1555 tcg_out_opc_imm(s, OPC_LBU, TCG_TMP0, base, 0);
1556 tcg_out_opc_imm(s, sgn ? OPC_LB : OPC_LBU, TCG_TMP1, base, 1);
1557 tcg_out_opc_sa(s, OPC_SLL, TCG_TMP1, TCG_TMP1, 8);
1558 tcg_out_opc_reg(s, OPC_OR, lo, TCG_TMP0, TCG_TMP1);
1559 }
1560 break;
1561
1562 case MO_SL:
1563 case MO_UL:
1564 tcg_out_opc_imm(s, lw1, lo, base, 0);
1565 tcg_out_opc_imm(s, lw2, lo, base, 3);
1566 if (TCG_TARGET_REG_BITS == 64 && is_64 && !sgn) {
1567 tcg_out_ext32u(s, lo, lo);
1568 }
1569 break;
1570
1571 case MO_UL | MO_BSWAP:
1572 case MO_SL | MO_BSWAP:
1573 if (use_mips32r2_instructions) {
1574 tcg_out_opc_imm(s, lw1, lo, base, 0);
1575 tcg_out_opc_imm(s, lw2, lo, base, 3);
1576 tcg_out_bswap32(s, lo, lo,
1577 TCG_TARGET_REG_BITS == 64 && is_64
1578 ? (sgn ? TCG_BSWAP_OS : TCG_BSWAP_OZ) : 0);
1579 } else {
1580 const tcg_insn_unit *subr =
1581 (TCG_TARGET_REG_BITS == 64 && is_64 && !sgn
1582 ? bswap32u_addr : bswap32_addr);
1583
1584 tcg_out_opc_imm(s, lw1, TCG_TMP0, base, 0);
1585 tcg_out_bswap_subr(s, subr);
1586 /* delay slot */
1587 tcg_out_opc_imm(s, lw2, TCG_TMP0, base, 3);
1588 tcg_out_mov(s, is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32, lo, TCG_TMP3);
1589 }
1590 break;
1591
1592 case MO_UQ:
1593 if (TCG_TARGET_REG_BITS == 64) {
1594 tcg_out_opc_imm(s, ld1, lo, base, 0);
1595 tcg_out_opc_imm(s, ld2, lo, base, 7);
1596 } else {
1597 tcg_out_opc_imm(s, lw1, MIPS_BE ? hi : lo, base, 0 + 0);
1598 tcg_out_opc_imm(s, lw2, MIPS_BE ? hi : lo, base, 0 + 3);
1599 tcg_out_opc_imm(s, lw1, MIPS_BE ? lo : hi, base, 4 + 0);
1600 tcg_out_opc_imm(s, lw2, MIPS_BE ? lo : hi, base, 4 + 3);
1601 }
1602 break;
1603
1604 case MO_UQ | MO_BSWAP:
1605 if (TCG_TARGET_REG_BITS == 64) {
1606 if (use_mips32r2_instructions) {
1607 tcg_out_opc_imm(s, ld1, lo, base, 0);
1608 tcg_out_opc_imm(s, ld2, lo, base, 7);
1609 tcg_out_bswap64(s, lo, lo);
1610 } else {
1611 tcg_out_opc_imm(s, ld1, TCG_TMP0, base, 0);
1612 tcg_out_bswap_subr(s, bswap64_addr);
1613 /* delay slot */
1614 tcg_out_opc_imm(s, ld2, TCG_TMP0, base, 7);
1615 tcg_out_mov(s, TCG_TYPE_I64, lo, TCG_TMP3);
1616 }
1617 } else if (use_mips32r2_instructions) {
1618 tcg_out_opc_imm(s, lw1, TCG_TMP0, base, 0 + 0);
1619 tcg_out_opc_imm(s, lw2, TCG_TMP0, base, 0 + 3);
1620 tcg_out_opc_imm(s, lw1, TCG_TMP1, base, 4 + 0);
1621 tcg_out_opc_imm(s, lw2, TCG_TMP1, base, 4 + 3);
1622 tcg_out_opc_reg(s, OPC_WSBH, TCG_TMP0, 0, TCG_TMP0);
1623 tcg_out_opc_reg(s, OPC_WSBH, TCG_TMP1, 0, TCG_TMP1);
1624 tcg_out_opc_sa(s, OPC_ROTR, MIPS_BE ? lo : hi, TCG_TMP0, 16);
1625 tcg_out_opc_sa(s, OPC_ROTR, MIPS_BE ? hi : lo, TCG_TMP1, 16);
1626 } else {
1627 tcg_out_opc_imm(s, lw1, TCG_TMP0, base, 0 + 0);
1628 tcg_out_bswap_subr(s, bswap32_addr);
1629 /* delay slot */
1630 tcg_out_opc_imm(s, lw2, TCG_TMP0, base, 0 + 3);
1631 tcg_out_opc_imm(s, lw1, TCG_TMP0, base, 4 + 0);
1632 tcg_out_mov(s, TCG_TYPE_I32, MIPS_BE ? lo : hi, TCG_TMP3);
1633 tcg_out_bswap_subr(s, bswap32_addr);
1634 /* delay slot */
1635 tcg_out_opc_imm(s, lw2, TCG_TMP0, base, 4 + 3);
1636 tcg_out_mov(s, TCG_TYPE_I32, MIPS_BE ? hi : lo, TCG_TMP3);
1637 }
1638 break;
1639
1640 default:
1641 g_assert_not_reached();
1642 }
1643}
1644
fbef2cc8 1645static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64)
afa05235 1646{
9d8bf2d1
RH
1647 TCGReg addr_regl, addr_regh __attribute__((unused));
1648 TCGReg data_regl, data_regh;
9002ffcb 1649 MemOpIdx oi;
14776ab5 1650 MemOp opc;
afa05235 1651#if defined(CONFIG_SOFTMMU)
9d8bf2d1 1652 tcg_insn_unit *label_ptr[2];
23a79c11 1653#else
afa05235 1654#endif
d9e52834 1655 unsigned a_bits, s_bits;
bb08afe9 1656 TCGReg base = TCG_REG_A0;
9d8bf2d1 1657
afa05235 1658 data_regl = *args++;
f0d70331 1659 data_regh = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0);
afa05235 1660 addr_regl = *args++;
f0d70331 1661 addr_regh = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0);
59227d5d
RH
1662 oi = *args++;
1663 opc = get_memop(oi);
d9e52834
RH
1664 a_bits = get_alignment_bits(opc);
1665 s_bits = opc & MO_SIZE;
9d8bf2d1 1666
d9e52834
RH
1667 /*
1668 * R6 removes the left/right instructions but requires the
1669 * system to support misaligned memory accesses.
1670 */
0834c9ea 1671#if defined(CONFIG_SOFTMMU)
81dfaf1a 1672 tcg_out_tlb_load(s, base, addr_regl, addr_regh, oi, label_ptr, 1);
d9e52834
RH
1673 if (use_mips32r6_instructions || a_bits >= s_bits) {
1674 tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc, is_64);
1675 } else {
1676 tcg_out_qemu_ld_unalign(s, data_regl, data_regh, base, opc, is_64);
1677 }
f0d70331
JG
1678 add_qemu_ldst_label(s, 1, oi,
1679 (is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32),
1680 data_regl, data_regh, addr_regl, addr_regh,
3972ef6f 1681 s->code_ptr, label_ptr);
0834c9ea 1682#else
f0d70331
JG
1683 if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
1684 tcg_out_ext32u(s, base, addr_regl);
1685 addr_regl = base;
1686 }
b76f21a7 1687 if (guest_base == 0 && data_regl != addr_regl) {
9d8bf2d1 1688 base = addr_regl;
b76f21a7 1689 } else if (guest_base == (int16_t)guest_base) {
f0d70331 1690 tcg_out_opc_imm(s, ALIAS_PADDI, base, addr_regl, guest_base);
0834c9ea 1691 } else {
4df9cac5 1692 tcg_out_opc_reg(s, ALIAS_PADD, base, TCG_GUEST_BASE_REG, addr_regl);
0834c9ea 1693 }
23a79c11
RH
1694 if (use_mips32r6_instructions) {
1695 if (a_bits) {
1696 tcg_out_test_alignment(s, true, addr_regl, addr_regh, a_bits);
1697 }
1698 tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc, is_64);
1699 } else {
1700 if (a_bits && a_bits != s_bits) {
1701 tcg_out_test_alignment(s, true, addr_regl, addr_regh, a_bits);
1702 }
1703 if (a_bits >= s_bits) {
1704 tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc, is_64);
1705 } else {
1706 tcg_out_qemu_ld_unalign(s, data_regl, data_regh, base, opc, is_64);
1707 }
1708 }
9d8bf2d1
RH
1709#endif
1710}
afa05235 1711
bb08afe9 1712static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg lo, TCGReg hi,
14776ab5 1713 TCGReg base, MemOp opc)
9d8bf2d1 1714{
bb08afe9
JG
1715 /* Don't clutter the code below with checks to avoid bswapping ZERO. */
1716 if ((lo | hi) == 0) {
1717 opc &= ~MO_BSWAP;
1718 }
1719
4214a8cb 1720 switch (opc & (MO_SIZE | MO_BSWAP)) {
9d8bf2d1 1721 case MO_8:
bb08afe9 1722 tcg_out_opc_imm(s, OPC_SB, lo, base, 0);
9d8bf2d1 1723 break;
afa05235 1724
9d8bf2d1 1725 case MO_16 | MO_BSWAP:
27362b7b 1726 tcg_out_bswap16(s, TCG_TMP1, lo, 0);
bb08afe9 1727 lo = TCG_TMP1;
9d8bf2d1
RH
1728 /* FALLTHRU */
1729 case MO_16:
bb08afe9 1730 tcg_out_opc_imm(s, OPC_SH, lo, base, 0);
afa05235 1731 break;
9d8bf2d1
RH
1732
1733 case MO_32 | MO_BSWAP:
1fce6534 1734 tcg_out_bswap32(s, TCG_TMP3, lo, 0);
bb08afe9 1735 lo = TCG_TMP3;
9d8bf2d1
RH
1736 /* FALLTHRU */
1737 case MO_32:
bb08afe9 1738 tcg_out_opc_imm(s, OPC_SW, lo, base, 0);
afa05235 1739 break;
9d8bf2d1
RH
1740
1741 case MO_64 | MO_BSWAP:
f0d70331
JG
1742 if (TCG_TARGET_REG_BITS == 64) {
1743 tcg_out_bswap64(s, TCG_TMP3, lo);
1744 tcg_out_opc_imm(s, OPC_SD, TCG_TMP3, base, 0);
1745 } else if (use_mips32r2_instructions) {
bb08afe9
JG
1746 tcg_out_opc_reg(s, OPC_WSBH, TCG_TMP0, 0, MIPS_BE ? lo : hi);
1747 tcg_out_opc_reg(s, OPC_WSBH, TCG_TMP1, 0, MIPS_BE ? hi : lo);
1748 tcg_out_opc_sa(s, OPC_ROTR, TCG_TMP0, TCG_TMP0, 16);
1749 tcg_out_opc_sa(s, OPC_ROTR, TCG_TMP1, TCG_TMP1, 16);
1750 tcg_out_opc_imm(s, OPC_SW, TCG_TMP0, base, 0);
1751 tcg_out_opc_imm(s, OPC_SW, TCG_TMP1, base, 4);
1752 } else {
1fce6534 1753 tcg_out_bswap32(s, TCG_TMP3, MIPS_BE ? lo : hi, 0);
bb08afe9 1754 tcg_out_opc_imm(s, OPC_SW, TCG_TMP3, base, 0);
1fce6534 1755 tcg_out_bswap32(s, TCG_TMP3, MIPS_BE ? hi : lo, 0);
bb08afe9
JG
1756 tcg_out_opc_imm(s, OPC_SW, TCG_TMP3, base, 4);
1757 }
afa05235 1758 break;
9d8bf2d1 1759 case MO_64:
f0d70331
JG
1760 if (TCG_TARGET_REG_BITS == 64) {
1761 tcg_out_opc_imm(s, OPC_SD, lo, base, 0);
1762 } else {
1763 tcg_out_opc_imm(s, OPC_SW, MIPS_BE ? hi : lo, base, 0);
1764 tcg_out_opc_imm(s, OPC_SW, MIPS_BE ? lo : hi, base, 4);
1765 }
afa05235 1766 break;
9d8bf2d1 1767
afa05235
AJ
1768 default:
1769 tcg_abort();
1770 }
9d8bf2d1 1771}
afa05235 1772
d9e52834 1773static void tcg_out_qemu_st_unalign(TCGContext *s, TCGReg lo, TCGReg hi,
23a79c11
RH
1774 TCGReg base, MemOp opc)
1775{
1776 const MIPSInsn sw1 = MIPS_BE ? OPC_SWL : OPC_SWR;
1777 const MIPSInsn sw2 = MIPS_BE ? OPC_SWR : OPC_SWL;
1778 const MIPSInsn sd1 = MIPS_BE ? OPC_SDL : OPC_SDR;
1779 const MIPSInsn sd2 = MIPS_BE ? OPC_SDR : OPC_SDL;
1780
1781 /* Don't clutter the code below with checks to avoid bswapping ZERO. */
1782 if ((lo | hi) == 0) {
1783 opc &= ~MO_BSWAP;
1784 }
1785
1786 switch (opc & (MO_SIZE | MO_BSWAP)) {
1787 case MO_16 | MO_BE:
1788 tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, lo, 8);
1789 tcg_out_opc_imm(s, OPC_SB, TCG_TMP0, base, 0);
1790 tcg_out_opc_imm(s, OPC_SB, lo, base, 1);
1791 break;
1792
1793 case MO_16 | MO_LE:
1794 tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, lo, 8);
1795 tcg_out_opc_imm(s, OPC_SB, lo, base, 0);
1796 tcg_out_opc_imm(s, OPC_SB, TCG_TMP0, base, 1);
1797 break;
1798
1799 case MO_32 | MO_BSWAP:
1800 tcg_out_bswap32(s, TCG_TMP3, lo, 0);
1801 lo = TCG_TMP3;
1802 /* fall through */
1803 case MO_32:
1804 tcg_out_opc_imm(s, sw1, lo, base, 0);
1805 tcg_out_opc_imm(s, sw2, lo, base, 3);
1806 break;
1807
1808 case MO_64 | MO_BSWAP:
1809 if (TCG_TARGET_REG_BITS == 64) {
1810 tcg_out_bswap64(s, TCG_TMP3, lo);
1811 lo = TCG_TMP3;
1812 } else if (use_mips32r2_instructions) {
1813 tcg_out_opc_reg(s, OPC_WSBH, TCG_TMP0, 0, MIPS_BE ? hi : lo);
1814 tcg_out_opc_reg(s, OPC_WSBH, TCG_TMP1, 0, MIPS_BE ? lo : hi);
1815 tcg_out_opc_sa(s, OPC_ROTR, TCG_TMP0, TCG_TMP0, 16);
1816 tcg_out_opc_sa(s, OPC_ROTR, TCG_TMP1, TCG_TMP1, 16);
1817 hi = MIPS_BE ? TCG_TMP0 : TCG_TMP1;
1818 lo = MIPS_BE ? TCG_TMP1 : TCG_TMP0;
1819 } else {
1820 tcg_out_bswap32(s, TCG_TMP3, MIPS_BE ? lo : hi, 0);
1821 tcg_out_opc_imm(s, sw1, TCG_TMP3, base, 0 + 0);
1822 tcg_out_opc_imm(s, sw2, TCG_TMP3, base, 0 + 3);
1823 tcg_out_bswap32(s, TCG_TMP3, MIPS_BE ? hi : lo, 0);
1824 tcg_out_opc_imm(s, sw1, TCG_TMP3, base, 4 + 0);
1825 tcg_out_opc_imm(s, sw2, TCG_TMP3, base, 4 + 3);
1826 break;
1827 }
1828 /* fall through */
1829 case MO_64:
1830 if (TCG_TARGET_REG_BITS == 64) {
1831 tcg_out_opc_imm(s, sd1, lo, base, 0);
1832 tcg_out_opc_imm(s, sd2, lo, base, 7);
1833 } else {
1834 tcg_out_opc_imm(s, sw1, MIPS_BE ? hi : lo, base, 0 + 0);
1835 tcg_out_opc_imm(s, sw2, MIPS_BE ? hi : lo, base, 0 + 3);
1836 tcg_out_opc_imm(s, sw1, MIPS_BE ? lo : hi, base, 4 + 0);
1837 tcg_out_opc_imm(s, sw2, MIPS_BE ? lo : hi, base, 4 + 3);
1838 }
1839 break;
1840
1841 default:
1842 tcg_abort();
1843 }
1844}
fbef2cc8 1845static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64)
9d8bf2d1
RH
1846{
1847 TCGReg addr_regl, addr_regh __attribute__((unused));
bb08afe9 1848 TCGReg data_regl, data_regh;
9002ffcb 1849 MemOpIdx oi;
14776ab5 1850 MemOp opc;
9d8bf2d1
RH
1851#if defined(CONFIG_SOFTMMU)
1852 tcg_insn_unit *label_ptr[2];
9d8bf2d1 1853#endif
d9e52834 1854 unsigned a_bits, s_bits;
bb08afe9 1855 TCGReg base = TCG_REG_A0;
9d8bf2d1
RH
1856
1857 data_regl = *args++;
f0d70331 1858 data_regh = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0);
9d8bf2d1 1859 addr_regl = *args++;
f0d70331 1860 addr_regh = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0);
59227d5d
RH
1861 oi = *args++;
1862 opc = get_memop(oi);
d9e52834
RH
1863 a_bits = get_alignment_bits(opc);
1864 s_bits = opc & MO_SIZE;
afa05235 1865
d9e52834
RH
1866 /*
1867 * R6 removes the left/right instructions but requires the
1868 * system to support misaligned memory accesses.
1869 */
9d8bf2d1 1870#if defined(CONFIG_SOFTMMU)
81dfaf1a 1871 tcg_out_tlb_load(s, base, addr_regl, addr_regh, oi, label_ptr, 0);
d9e52834
RH
1872 if (use_mips32r6_instructions || a_bits >= s_bits) {
1873 tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc);
1874 } else {
1875 tcg_out_qemu_st_unalign(s, data_regl, data_regh, base, opc);
1876 }
f0d70331
JG
1877 add_qemu_ldst_label(s, 0, oi,
1878 (is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32),
1879 data_regl, data_regh, addr_regl, addr_regh,
3972ef6f 1880 s->code_ptr, label_ptr);
cc01cc8e 1881#else
f0d70331
JG
1882 if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
1883 tcg_out_ext32u(s, base, addr_regl);
1884 addr_regl = base;
1885 }
b76f21a7 1886 if (guest_base == 0) {
9d8bf2d1 1887 base = addr_regl;
f0d70331
JG
1888 } else if (guest_base == (int16_t)guest_base) {
1889 tcg_out_opc_imm(s, ALIAS_PADDI, base, addr_regl, guest_base);
cc01cc8e 1890 } else {
4df9cac5 1891 tcg_out_opc_reg(s, ALIAS_PADD, base, TCG_GUEST_BASE_REG, addr_regl);
afa05235 1892 }
23a79c11
RH
1893 if (use_mips32r6_instructions) {
1894 if (a_bits) {
1895 tcg_out_test_alignment(s, true, addr_regl, addr_regh, a_bits);
1896 }
1897 tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc);
1898 } else {
1899 if (a_bits && a_bits != s_bits) {
1900 tcg_out_test_alignment(s, true, addr_regl, addr_regh, a_bits);
1901 }
1902 if (a_bits >= s_bits) {
1903 tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc);
1904 } else {
1905 tcg_out_qemu_st_unalign(s, data_regl, data_regh, base, opc);
1906 }
1907 }
afa05235
AJ
1908#endif
1909}
1910
6f0b9910
PK
1911static void tcg_out_mb(TCGContext *s, TCGArg a0)
1912{
1913 static const MIPSInsn sync[] = {
1914 /* Note that SYNC_MB is a slightly weaker than SYNC 0,
1915 as the former is an ordering barrier and the latter
1916 is a completion barrier. */
1917 [0 ... TCG_MO_ALL] = OPC_SYNC_MB,
1918 [TCG_MO_LD_LD] = OPC_SYNC_RMB,
1919 [TCG_MO_ST_ST] = OPC_SYNC_WMB,
1920 [TCG_MO_LD_ST] = OPC_SYNC_RELEASE,
1921 [TCG_MO_LD_ST | TCG_MO_ST_ST] = OPC_SYNC_RELEASE,
1922 [TCG_MO_LD_ST | TCG_MO_LD_LD] = OPC_SYNC_ACQUIRE,
1923 };
1924 tcg_out32(s, sync[a0 & TCG_MO_ALL]);
1925}
1926
2a1d9d41
RH
1927static void tcg_out_clz(TCGContext *s, MIPSInsn opcv2, MIPSInsn opcv6,
1928 int width, TCGReg a0, TCGReg a1, TCGArg a2)
1929{
1930 if (use_mips32r6_instructions) {
1931 if (a2 == width) {
1932 tcg_out_opc_reg(s, opcv6, a0, a1, 0);
1933 } else {
1934 tcg_out_opc_reg(s, opcv6, TCG_TMP0, a1, 0);
1935 tcg_out_movcond(s, TCG_COND_EQ, a0, a1, 0, a2, TCG_TMP0);
1936 }
1937 } else {
1938 if (a2 == width) {
1939 tcg_out_opc_reg(s, opcv2, a0, a1, a1);
1940 } else if (a0 == a2) {
1941 tcg_out_opc_reg(s, opcv2, TCG_TMP0, a1, a1);
1942 tcg_out_opc_reg(s, OPC_MOVN, a0, TCG_TMP0, a1);
1943 } else if (a0 != a1) {
1944 tcg_out_opc_reg(s, opcv2, a0, a1, a1);
1945 tcg_out_opc_reg(s, OPC_MOVZ, a0, a2, a1);
1946 } else {
1947 tcg_out_opc_reg(s, opcv2, TCG_TMP0, a1, a1);
1948 tcg_out_opc_reg(s, OPC_MOVZ, TCG_TMP0, a2, a1);
1949 tcg_out_mov(s, TCG_TYPE_REG, a0, TCG_TMP0);
1950 }
1951 }
1952}
1953
10d4af58
RH
1954static void tcg_out_op(TCGContext *s, TCGOpcode opc,
1955 const TCGArg args[TCG_MAX_OP_ARGS],
1956 const int const_args[TCG_MAX_OP_ARGS])
afa05235 1957{
4f048535 1958 MIPSInsn i1, i2;
22ee3a98
RH
1959 TCGArg a0, a1, a2;
1960 int c2;
1961
51800e43
RH
1962 /*
1963 * Note that many operands use the constraint set "rZ".
1964 * We make use of the fact that 0 is the ZERO register,
1965 * and hence such cases need not check for const_args.
1966 */
22ee3a98
RH
1967 a0 = args[0];
1968 a1 = args[1];
1969 a2 = args[2];
1970 c2 = const_args[2];
1971
1972 switch (opc) {
afa05235 1973 case INDEX_op_exit_tb:
7dae901d 1974 {
7dae901d
RH
1975 TCGReg b0 = TCG_REG_ZERO;
1976
0119b192 1977 a0 = (intptr_t)a0;
7dae901d
RH
1978 if (a0 & ~0xffff) {
1979 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, a0 & ~0xffff);
1980 b0 = TCG_REG_V0;
1981 }
1982 if (!tcg_out_opc_jmp(s, OPC_J, tb_ret_addr)) {
6c530e32 1983 tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0,
7dae901d 1984 (uintptr_t)tb_ret_addr);
6c530e32 1985 tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
7dae901d
RH
1986 }
1987 tcg_out_opc_imm(s, OPC_ORI, TCG_REG_V0, b0, a0 & 0xffff);
f8c9eddb 1988 }
afa05235
AJ
1989 break;
1990 case INDEX_op_goto_tb:
5a8f0a5d
RH
1991 /* indirect jump method */
1992 tcg_debug_assert(s->tb_jmp_insn_offset == 0);
1993 tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_REG_ZERO,
1994 (uintptr_t)(s->tb_jmp_target_addr + a0));
1995 tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
afa05235 1996 tcg_out_nop(s);
9f754620 1997 set_jmp_reset_offset(s, a0);
afa05235 1998 break;
5786e068
AJ
1999 case INDEX_op_goto_ptr:
2000 /* jmp to the given host address (could be epilogue) */
2001 tcg_out_opc_reg(s, OPC_JR, 0, a0, 0);
2002 tcg_out_nop(s);
2003 break;
afa05235 2004 case INDEX_op_br:
bec16311
RH
2005 tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO,
2006 arg_label(a0));
afa05235
AJ
2007 break;
2008
afa05235 2009 case INDEX_op_ld8u_i32:
0119b192 2010 case INDEX_op_ld8u_i64:
4f048535
RH
2011 i1 = OPC_LBU;
2012 goto do_ldst;
afa05235 2013 case INDEX_op_ld8s_i32:
0119b192 2014 case INDEX_op_ld8s_i64:
4f048535
RH
2015 i1 = OPC_LB;
2016 goto do_ldst;
afa05235 2017 case INDEX_op_ld16u_i32:
0119b192 2018 case INDEX_op_ld16u_i64:
4f048535
RH
2019 i1 = OPC_LHU;
2020 goto do_ldst;
afa05235 2021 case INDEX_op_ld16s_i32:
0119b192 2022 case INDEX_op_ld16s_i64:
4f048535
RH
2023 i1 = OPC_LH;
2024 goto do_ldst;
afa05235 2025 case INDEX_op_ld_i32:
0119b192 2026 case INDEX_op_ld32s_i64:
4f048535
RH
2027 i1 = OPC_LW;
2028 goto do_ldst;
0119b192
JG
2029 case INDEX_op_ld32u_i64:
2030 i1 = OPC_LWU;
2031 goto do_ldst;
2032 case INDEX_op_ld_i64:
2033 i1 = OPC_LD;
2034 goto do_ldst;
afa05235 2035 case INDEX_op_st8_i32:
0119b192 2036 case INDEX_op_st8_i64:
4f048535
RH
2037 i1 = OPC_SB;
2038 goto do_ldst;
afa05235 2039 case INDEX_op_st16_i32:
0119b192 2040 case INDEX_op_st16_i64:
4f048535
RH
2041 i1 = OPC_SH;
2042 goto do_ldst;
afa05235 2043 case INDEX_op_st_i32:
0119b192 2044 case INDEX_op_st32_i64:
4f048535 2045 i1 = OPC_SW;
0119b192
JG
2046 goto do_ldst;
2047 case INDEX_op_st_i64:
2048 i1 = OPC_SD;
4f048535
RH
2049 do_ldst:
2050 tcg_out_ldst(s, i1, a0, a1, a2);
afa05235
AJ
2051 break;
2052
2053 case INDEX_op_add_i32:
4f048535
RH
2054 i1 = OPC_ADDU, i2 = OPC_ADDIU;
2055 goto do_binary;
0119b192
JG
2056 case INDEX_op_add_i64:
2057 i1 = OPC_DADDU, i2 = OPC_DADDIU;
2058 goto do_binary;
4f048535 2059 case INDEX_op_or_i32:
0119b192 2060 case INDEX_op_or_i64:
4f048535
RH
2061 i1 = OPC_OR, i2 = OPC_ORI;
2062 goto do_binary;
2063 case INDEX_op_xor_i32:
0119b192 2064 case INDEX_op_xor_i64:
4f048535
RH
2065 i1 = OPC_XOR, i2 = OPC_XORI;
2066 do_binary:
22ee3a98 2067 if (c2) {
4f048535
RH
2068 tcg_out_opc_imm(s, i2, a0, a1, a2);
2069 break;
afa05235 2070 }
4f048535
RH
2071 do_binaryv:
2072 tcg_out_opc_reg(s, i1, a0, a1, a2);
afa05235 2073 break;
4f048535 2074
afa05235 2075 case INDEX_op_sub_i32:
0119b192
JG
2076 i1 = OPC_SUBU, i2 = OPC_ADDIU;
2077 goto do_subtract;
2078 case INDEX_op_sub_i64:
2079 i1 = OPC_DSUBU, i2 = OPC_DADDIU;
2080 do_subtract:
22ee3a98 2081 if (c2) {
0119b192 2082 tcg_out_opc_imm(s, i2, a0, a1, -a2);
4f048535 2083 break;
afa05235 2084 }
0119b192 2085 goto do_binaryv;
4f048535
RH
2086 case INDEX_op_and_i32:
2087 if (c2 && a2 != (uint16_t)a2) {
2088 int msb = ctz32(~a2) - 1;
eabb7b91
AJ
2089 tcg_debug_assert(use_mips32r2_instructions);
2090 tcg_debug_assert(is_p2m1(a2));
4f048535
RH
2091 tcg_out_opc_bf(s, OPC_EXT, a0, a1, msb, 0);
2092 break;
2093 }
2094 i1 = OPC_AND, i2 = OPC_ANDI;
2095 goto do_binary;
0119b192
JG
2096 case INDEX_op_and_i64:
2097 if (c2 && a2 != (uint16_t)a2) {
2098 int msb = ctz64(~a2) - 1;
2099 tcg_debug_assert(use_mips32r2_instructions);
2100 tcg_debug_assert(is_p2m1(a2));
2101 tcg_out_opc_bf64(s, OPC_DEXT, OPC_DEXTM, OPC_DEXTU, a0, a1, msb, 0);
2102 break;
2103 }
2104 i1 = OPC_AND, i2 = OPC_ANDI;
2105 goto do_binary;
4f048535 2106 case INDEX_op_nor_i32:
0119b192 2107 case INDEX_op_nor_i64:
4f048535
RH
2108 i1 = OPC_NOR;
2109 goto do_binaryv;
2110
afa05235 2111 case INDEX_op_mul_i32:
988902fc 2112 if (use_mips32_instructions) {
22ee3a98 2113 tcg_out_opc_reg(s, OPC_MUL, a0, a1, a2);
4f048535 2114 break;
988902fc 2115 }
4f048535
RH
2116 i1 = OPC_MULT, i2 = OPC_MFLO;
2117 goto do_hilo1;
3c9a8f17 2118 case INDEX_op_mulsh_i32:
bc6d0c22
JH
2119 if (use_mips32r6_instructions) {
2120 tcg_out_opc_reg(s, OPC_MUH, a0, a1, a2);
2121 break;
2122 }
4f048535
RH
2123 i1 = OPC_MULT, i2 = OPC_MFHI;
2124 goto do_hilo1;
3c9a8f17 2125 case INDEX_op_muluh_i32:
bc6d0c22
JH
2126 if (use_mips32r6_instructions) {
2127 tcg_out_opc_reg(s, OPC_MUHU, a0, a1, a2);
2128 break;
2129 }
4f048535
RH
2130 i1 = OPC_MULTU, i2 = OPC_MFHI;
2131 goto do_hilo1;
afa05235 2132 case INDEX_op_div_i32:
bc6d0c22
JH
2133 if (use_mips32r6_instructions) {
2134 tcg_out_opc_reg(s, OPC_DIV_R6, a0, a1, a2);
2135 break;
2136 }
4f048535
RH
2137 i1 = OPC_DIV, i2 = OPC_MFLO;
2138 goto do_hilo1;
afa05235 2139 case INDEX_op_divu_i32:
bc6d0c22
JH
2140 if (use_mips32r6_instructions) {
2141 tcg_out_opc_reg(s, OPC_DIVU_R6, a0, a1, a2);
2142 break;
2143 }
4f048535
RH
2144 i1 = OPC_DIVU, i2 = OPC_MFLO;
2145 goto do_hilo1;
afa05235 2146 case INDEX_op_rem_i32:
bc6d0c22
JH
2147 if (use_mips32r6_instructions) {
2148 tcg_out_opc_reg(s, OPC_MOD, a0, a1, a2);
2149 break;
2150 }
4f048535
RH
2151 i1 = OPC_DIV, i2 = OPC_MFHI;
2152 goto do_hilo1;
afa05235 2153 case INDEX_op_remu_i32:
bc6d0c22
JH
2154 if (use_mips32r6_instructions) {
2155 tcg_out_opc_reg(s, OPC_MODU, a0, a1, a2);
2156 break;
2157 }
4f048535 2158 i1 = OPC_DIVU, i2 = OPC_MFHI;
0119b192
JG
2159 goto do_hilo1;
2160 case INDEX_op_mul_i64:
2161 if (use_mips32r6_instructions) {
2162 tcg_out_opc_reg(s, OPC_DMUL, a0, a1, a2);
2163 break;
2164 }
2165 i1 = OPC_DMULT, i2 = OPC_MFLO;
2166 goto do_hilo1;
2167 case INDEX_op_mulsh_i64:
2168 if (use_mips32r6_instructions) {
2169 tcg_out_opc_reg(s, OPC_DMUH, a0, a1, a2);
2170 break;
2171 }
2172 i1 = OPC_DMULT, i2 = OPC_MFHI;
2173 goto do_hilo1;
2174 case INDEX_op_muluh_i64:
2175 if (use_mips32r6_instructions) {
2176 tcg_out_opc_reg(s, OPC_DMUHU, a0, a1, a2);
2177 break;
2178 }
2179 i1 = OPC_DMULTU, i2 = OPC_MFHI;
2180 goto do_hilo1;
2181 case INDEX_op_div_i64:
2182 if (use_mips32r6_instructions) {
2183 tcg_out_opc_reg(s, OPC_DDIV_R6, a0, a1, a2);
2184 break;
2185 }
2186 i1 = OPC_DDIV, i2 = OPC_MFLO;
2187 goto do_hilo1;
2188 case INDEX_op_divu_i64:
2189 if (use_mips32r6_instructions) {
2190 tcg_out_opc_reg(s, OPC_DDIVU_R6, a0, a1, a2);
2191 break;
2192 }
2193 i1 = OPC_DDIVU, i2 = OPC_MFLO;
2194 goto do_hilo1;
2195 case INDEX_op_rem_i64:
2196 if (use_mips32r6_instructions) {
2197 tcg_out_opc_reg(s, OPC_DMOD, a0, a1, a2);
2198 break;
2199 }
2200 i1 = OPC_DDIV, i2 = OPC_MFHI;
2201 goto do_hilo1;
2202 case INDEX_op_remu_i64:
2203 if (use_mips32r6_instructions) {
2204 tcg_out_opc_reg(s, OPC_DMODU, a0, a1, a2);
2205 break;
2206 }
2207 i1 = OPC_DDIVU, i2 = OPC_MFHI;
4f048535
RH
2208 do_hilo1:
2209 tcg_out_opc_reg(s, i1, 0, a1, a2);
2210 tcg_out_opc_reg(s, i2, a0, 0, 0);
afa05235
AJ
2211 break;
2212
4f048535
RH
2213 case INDEX_op_muls2_i32:
2214 i1 = OPC_MULT;
2215 goto do_hilo2;
2216 case INDEX_op_mulu2_i32:
2217 i1 = OPC_MULTU;
0119b192
JG
2218 goto do_hilo2;
2219 case INDEX_op_muls2_i64:
2220 i1 = OPC_DMULT;
2221 goto do_hilo2;
2222 case INDEX_op_mulu2_i64:
2223 i1 = OPC_DMULTU;
4f048535
RH
2224 do_hilo2:
2225 tcg_out_opc_reg(s, i1, 0, a2, args[3]);
2226 tcg_out_opc_reg(s, OPC_MFLO, a0, 0, 0);
2227 tcg_out_opc_reg(s, OPC_MFHI, a1, 0, 0);
2b79487a 2228 break;
4f048535 2229
afa05235 2230 case INDEX_op_not_i32:
0119b192 2231 case INDEX_op_not_i64:
4f048535
RH
2232 i1 = OPC_NOR;
2233 goto do_unary;
4f048535 2234 case INDEX_op_ext8s_i32:
0119b192 2235 case INDEX_op_ext8s_i64:
4f048535
RH
2236 i1 = OPC_SEB;
2237 goto do_unary;
2238 case INDEX_op_ext16s_i32:
0119b192 2239 case INDEX_op_ext16s_i64:
4f048535
RH
2240 i1 = OPC_SEH;
2241 do_unary:
2242 tcg_out_opc_reg(s, i1, a0, TCG_REG_ZERO, a1);
afa05235
AJ
2243 break;
2244
27362b7b
RH
2245 case INDEX_op_bswap16_i32:
2246 case INDEX_op_bswap16_i64:
2247 tcg_out_bswap16(s, a0, a1, a2);
2248 break;
0119b192 2249 case INDEX_op_bswap32_i32:
1fce6534 2250 tcg_out_bswap32(s, a0, a1, 0);
0119b192
JG
2251 break;
2252 case INDEX_op_bswap32_i64:
1fce6534 2253 tcg_out_bswap32(s, a0, a1, a2);
0119b192
JG
2254 break;
2255 case INDEX_op_bswap64_i64:
2256 tcg_out_bswap64(s, a0, a1);
2257 break;
2258 case INDEX_op_extrh_i64_i32:
2259 tcg_out_dsra(s, a0, a1, 32);
2260 break;
2261 case INDEX_op_ext32s_i64:
2262 case INDEX_op_ext_i32_i64:
2263 case INDEX_op_extrl_i64_i32:
2264 tcg_out_opc_sa(s, OPC_SLL, a0, a1, 0);
2265 break;
2266 case INDEX_op_ext32u_i64:
2267 case INDEX_op_extu_i32_i64:
2268 tcg_out_ext32u(s, a0, a1);
2269 break;
2270
afa05235 2271 case INDEX_op_sar_i32:
4f048535
RH
2272 i1 = OPC_SRAV, i2 = OPC_SRA;
2273 goto do_shift;
afa05235 2274 case INDEX_op_shl_i32:
4f048535
RH
2275 i1 = OPC_SLLV, i2 = OPC_SLL;
2276 goto do_shift;
afa05235 2277 case INDEX_op_shr_i32:
4f048535
RH
2278 i1 = OPC_SRLV, i2 = OPC_SRL;
2279 goto do_shift;
2280 case INDEX_op_rotr_i32:
2281 i1 = OPC_ROTRV, i2 = OPC_ROTR;
2282 do_shift:
22ee3a98 2283 if (c2) {
4f048535 2284 tcg_out_opc_sa(s, i2, a0, a1, a2);
0119b192 2285 break;
afa05235 2286 }
0119b192
JG
2287 do_shiftv:
2288 tcg_out_opc_reg(s, i1, a0, a2, a1);
afa05235 2289 break;
9a152519 2290 case INDEX_op_rotl_i32:
22ee3a98
RH
2291 if (c2) {
2292 tcg_out_opc_sa(s, OPC_ROTR, a0, a1, 32 - a2);
9a152519 2293 } else {
22ee3a98
RH
2294 tcg_out_opc_reg(s, OPC_SUBU, TCG_TMP0, TCG_REG_ZERO, a2);
2295 tcg_out_opc_reg(s, OPC_ROTRV, a0, TCG_TMP0, a1);
9a152519
AJ
2296 }
2297 break;
0119b192
JG
2298 case INDEX_op_sar_i64:
2299 if (c2) {
2300 tcg_out_dsra(s, a0, a1, a2);
2301 break;
2302 }
2303 i1 = OPC_DSRAV;
2304 goto do_shiftv;
2305 case INDEX_op_shl_i64:
2306 if (c2) {
2307 tcg_out_dsll(s, a0, a1, a2);
2308 break;
2309 }
2310 i1 = OPC_DSLLV;
2311 goto do_shiftv;
2312 case INDEX_op_shr_i64:
2313 if (c2) {
2314 tcg_out_dsrl(s, a0, a1, a2);
2315 break;
2316 }
2317 i1 = OPC_DSRLV;
2318 goto do_shiftv;
2319 case INDEX_op_rotr_i64:
2320 if (c2) {
2321 tcg_out_opc_sa64(s, OPC_DROTR, OPC_DROTR32, a0, a1, a2);
2322 break;
2323 }
2324 i1 = OPC_DROTRV;
2325 goto do_shiftv;
2326 case INDEX_op_rotl_i64:
2327 if (c2) {
2328 tcg_out_opc_sa64(s, OPC_DROTR, OPC_DROTR32, a0, a1, 64 - a2);
2329 } else {
2330 tcg_out_opc_reg(s, OPC_DSUBU, TCG_TMP0, TCG_REG_ZERO, a2);
2331 tcg_out_opc_reg(s, OPC_DROTRV, a0, TCG_TMP0, a1);
2332 }
c1cf85c9
AJ
2333 break;
2334
2a1d9d41
RH
2335 case INDEX_op_clz_i32:
2336 tcg_out_clz(s, OPC_CLZ, OPC_CLZ_R6, 32, a0, a1, a2);
2337 break;
2338 case INDEX_op_clz_i64:
2339 tcg_out_clz(s, OPC_DCLZ, OPC_DCLZ_R6, 64, a0, a1, a2);
2340 break;
2341
04f71aa3 2342 case INDEX_op_deposit_i32:
22ee3a98 2343 tcg_out_opc_bf(s, OPC_INS, a0, a2, args[3] + args[4] - 1, args[3]);
04f71aa3 2344 break;
0119b192
JG
2345 case INDEX_op_deposit_i64:
2346 tcg_out_opc_bf64(s, OPC_DINS, OPC_DINSM, OPC_DINSU, a0, a2,
2347 args[3] + args[4] - 1, args[3]);
2348 break;
befbb3ce 2349 case INDEX_op_extract_i32:
2f5a5f57 2350 tcg_out_opc_bf(s, OPC_EXT, a0, a1, args[3] - 1, a2);
befbb3ce
RH
2351 break;
2352 case INDEX_op_extract_i64:
2353 tcg_out_opc_bf64(s, OPC_DEXT, OPC_DEXTM, OPC_DEXTU, a0, a1,
2f5a5f57 2354 args[3] - 1, a2);
befbb3ce 2355 break;
04f71aa3 2356
afa05235 2357 case INDEX_op_brcond_i32:
0119b192 2358 case INDEX_op_brcond_i64:
bec16311 2359 tcg_out_brcond(s, a2, a0, a1, arg_label(args[3]));
afa05235
AJ
2360 break;
2361 case INDEX_op_brcond2_i32:
bec16311 2362 tcg_out_brcond2(s, args[4], a0, a1, a2, args[3], arg_label(args[5]));
afa05235
AJ
2363 break;
2364
7d7c4930 2365 case INDEX_op_movcond_i32:
0119b192 2366 case INDEX_op_movcond_i64:
137d6390 2367 tcg_out_movcond(s, args[5], a0, a1, a2, args[3], args[4]);
7d7c4930
AJ
2368 break;
2369
4cb26382 2370 case INDEX_op_setcond_i32:
0119b192 2371 case INDEX_op_setcond_i64:
22ee3a98 2372 tcg_out_setcond(s, args[3], a0, a1, a2);
4cb26382 2373 break;
434254aa 2374 case INDEX_op_setcond2_i32:
22ee3a98 2375 tcg_out_setcond2(s, args[5], a0, a1, a2, args[3], args[4]);
434254aa 2376 break;
4cb26382 2377
fbef2cc8
RH
2378 case INDEX_op_qemu_ld_i32:
2379 tcg_out_qemu_ld(s, args, false);
afa05235 2380 break;
fbef2cc8
RH
2381 case INDEX_op_qemu_ld_i64:
2382 tcg_out_qemu_ld(s, args, true);
afa05235 2383 break;
fbef2cc8
RH
2384 case INDEX_op_qemu_st_i32:
2385 tcg_out_qemu_st(s, args, false);
afa05235 2386 break;
fbef2cc8
RH
2387 case INDEX_op_qemu_st_i64:
2388 tcg_out_qemu_st(s, args, true);
afa05235
AJ
2389 break;
2390
741f117d
RH
2391 case INDEX_op_add2_i32:
2392 tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2393 const_args[4], const_args[5], false);
2394 break;
2395 case INDEX_op_sub2_i32:
2396 tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2397 const_args[4], const_args[5], true);
2398 break;
2399
6f0b9910
PK
2400 case INDEX_op_mb:
2401 tcg_out_mb(s, a0);
2402 break;
96d0ee7f 2403 case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
0119b192 2404 case INDEX_op_mov_i64:
96d0ee7f 2405 case INDEX_op_call: /* Always emitted via tcg_out_call. */
afa05235
AJ
2406 default:
2407 tcg_abort();
2408 }
2409}
2410
0263330b 2411static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
89b2e37e 2412{
89b2e37e
RH
2413 switch (op) {
2414 case INDEX_op_goto_ptr:
0263330b 2415 return C_O0_I1(r);
afa05235 2416
89b2e37e
RH
2417 case INDEX_op_ld8u_i32:
2418 case INDEX_op_ld8s_i32:
2419 case INDEX_op_ld16u_i32:
2420 case INDEX_op_ld16s_i32:
2421 case INDEX_op_ld_i32:
2422 case INDEX_op_not_i32:
2423 case INDEX_op_bswap16_i32:
2424 case INDEX_op_bswap32_i32:
2425 case INDEX_op_ext8s_i32:
2426 case INDEX_op_ext16s_i32:
2427 case INDEX_op_extract_i32:
2428 case INDEX_op_ld8u_i64:
2429 case INDEX_op_ld8s_i64:
2430 case INDEX_op_ld16u_i64:
2431 case INDEX_op_ld16s_i64:
2432 case INDEX_op_ld32s_i64:
2433 case INDEX_op_ld32u_i64:
2434 case INDEX_op_ld_i64:
2435 case INDEX_op_not_i64:
2436 case INDEX_op_bswap16_i64:
2437 case INDEX_op_bswap32_i64:
2438 case INDEX_op_bswap64_i64:
2439 case INDEX_op_ext8s_i64:
2440 case INDEX_op_ext16s_i64:
2441 case INDEX_op_ext32s_i64:
2442 case INDEX_op_ext32u_i64:
2443 case INDEX_op_ext_i32_i64:
2444 case INDEX_op_extu_i32_i64:
2445 case INDEX_op_extrl_i64_i32:
2446 case INDEX_op_extrh_i64_i32:
2447 case INDEX_op_extract_i64:
0263330b 2448 return C_O1_I1(r, r);
afa05235 2449
89b2e37e
RH
2450 case INDEX_op_st8_i32:
2451 case INDEX_op_st16_i32:
2452 case INDEX_op_st_i32:
2453 case INDEX_op_st8_i64:
2454 case INDEX_op_st16_i64:
2455 case INDEX_op_st32_i64:
2456 case INDEX_op_st_i64:
0263330b 2457 return C_O0_I2(rZ, r);
6f0b9910 2458
89b2e37e
RH
2459 case INDEX_op_add_i32:
2460 case INDEX_op_add_i64:
0263330b 2461 return C_O1_I2(r, r, rJ);
89b2e37e
RH
2462 case INDEX_op_sub_i32:
2463 case INDEX_op_sub_i64:
0263330b 2464 return C_O1_I2(r, rZ, rN);
89b2e37e
RH
2465 case INDEX_op_mul_i32:
2466 case INDEX_op_mulsh_i32:
2467 case INDEX_op_muluh_i32:
2468 case INDEX_op_div_i32:
2469 case INDEX_op_divu_i32:
2470 case INDEX_op_rem_i32:
2471 case INDEX_op_remu_i32:
2472 case INDEX_op_nor_i32:
2473 case INDEX_op_setcond_i32:
2474 case INDEX_op_mul_i64:
2475 case INDEX_op_mulsh_i64:
2476 case INDEX_op_muluh_i64:
2477 case INDEX_op_div_i64:
2478 case INDEX_op_divu_i64:
2479 case INDEX_op_rem_i64:
2480 case INDEX_op_remu_i64:
2481 case INDEX_op_nor_i64:
2482 case INDEX_op_setcond_i64:
0263330b 2483 return C_O1_I2(r, rZ, rZ);
89b2e37e
RH
2484 case INDEX_op_muls2_i32:
2485 case INDEX_op_mulu2_i32:
2486 case INDEX_op_muls2_i64:
2487 case INDEX_op_mulu2_i64:
0263330b 2488 return C_O2_I2(r, r, r, r);
89b2e37e
RH
2489 case INDEX_op_and_i32:
2490 case INDEX_op_and_i64:
0263330b 2491 return C_O1_I2(r, r, rIK);
89b2e37e
RH
2492 case INDEX_op_or_i32:
2493 case INDEX_op_xor_i32:
2494 case INDEX_op_or_i64:
2495 case INDEX_op_xor_i64:
0263330b 2496 return C_O1_I2(r, r, rI);
89b2e37e
RH
2497 case INDEX_op_shl_i32:
2498 case INDEX_op_shr_i32:
2499 case INDEX_op_sar_i32:
2500 case INDEX_op_rotr_i32:
2501 case INDEX_op_rotl_i32:
2502 case INDEX_op_shl_i64:
2503 case INDEX_op_shr_i64:
2504 case INDEX_op_sar_i64:
2505 case INDEX_op_rotr_i64:
2506 case INDEX_op_rotl_i64:
0263330b 2507 return C_O1_I2(r, r, ri);
89b2e37e
RH
2508 case INDEX_op_clz_i32:
2509 case INDEX_op_clz_i64:
0263330b 2510 return C_O1_I2(r, r, rWZ);
afa05235 2511
89b2e37e
RH
2512 case INDEX_op_deposit_i32:
2513 case INDEX_op_deposit_i64:
0263330b 2514 return C_O1_I2(r, 0, rZ);
89b2e37e
RH
2515 case INDEX_op_brcond_i32:
2516 case INDEX_op_brcond_i64:
0263330b 2517 return C_O0_I2(rZ, rZ);
89b2e37e
RH
2518 case INDEX_op_movcond_i32:
2519 case INDEX_op_movcond_i64:
0263330b
RH
2520 return (use_mips32r6_instructions
2521 ? C_O1_I4(r, rZ, rZ, rZ, rZ)
2522 : C_O1_I4(r, rZ, rZ, rZ, 0));
89b2e37e
RH
2523 case INDEX_op_add2_i32:
2524 case INDEX_op_sub2_i32:
0263330b 2525 return C_O2_I4(r, r, rZ, rZ, rN, rN);
89b2e37e 2526 case INDEX_op_setcond2_i32:
0263330b 2527 return C_O1_I4(r, rZ, rZ, rZ, rZ);
89b2e37e 2528 case INDEX_op_brcond2_i32:
0263330b 2529 return C_O0_I4(rZ, rZ, rZ, rZ);
89b2e37e
RH
2530
2531 case INDEX_op_qemu_ld_i32:
2532 return (TCG_TARGET_REG_BITS == 64 || TARGET_LONG_BITS == 32
0263330b 2533 ? C_O1_I1(r, L) : C_O1_I2(r, L, L));
89b2e37e
RH
2534 case INDEX_op_qemu_st_i32:
2535 return (TCG_TARGET_REG_BITS == 64 || TARGET_LONG_BITS == 32
0263330b 2536 ? C_O0_I2(SZ, S) : C_O0_I3(SZ, S, S));
89b2e37e 2537 case INDEX_op_qemu_ld_i64:
0263330b
RH
2538 return (TCG_TARGET_REG_BITS == 64 ? C_O1_I1(r, L)
2539 : TARGET_LONG_BITS == 32 ? C_O2_I1(r, r, L)
2540 : C_O2_I2(r, r, L, L));
89b2e37e 2541 case INDEX_op_qemu_st_i64:
0263330b
RH
2542 return (TCG_TARGET_REG_BITS == 64 ? C_O0_I2(SZ, S)
2543 : TARGET_LONG_BITS == 32 ? C_O0_I3(SZ, SZ, S)
2544 : C_O0_I4(SZ, SZ, S, S));
89b2e37e
RH
2545
2546 default:
0263330b 2547 g_assert_not_reached();
f69d277e 2548 }
f69d277e
RH
2549}
2550
d453ec78 2551static const int tcg_target_callee_save_regs[] = {
cea5f9a2 2552 TCG_REG_S0, /* used for the global env (TCG_AREG0) */
afa05235
AJ
2553 TCG_REG_S1,
2554 TCG_REG_S2,
2555 TCG_REG_S3,
2556 TCG_REG_S4,
2557 TCG_REG_S5,
2558 TCG_REG_S6,
2559 TCG_REG_S7,
41883904 2560 TCG_REG_S8,
afa05235
AJ
2561 TCG_REG_RA, /* should be last for ABI compliance */
2562};
2563
988902fc
AJ
2564/* The Linux kernel doesn't provide any information about the available
2565 instruction set. Probe it using a signal handler. */
2566
988902fc
AJ
2567
2568#ifndef use_movnz_instructions
2569bool use_movnz_instructions = false;
2570#endif
2571
2572#ifndef use_mips32_instructions
2573bool use_mips32_instructions = false;
2574#endif
2575
2576#ifndef use_mips32r2_instructions
2577bool use_mips32r2_instructions = false;
2578#endif
2579
2580static volatile sig_atomic_t got_sigill;
2581
2582static void sigill_handler(int signo, siginfo_t *si, void *data)
2583{
2584 /* Skip the faulty instruction */
2585 ucontext_t *uc = (ucontext_t *)data;
2586 uc->uc_mcontext.pc += 4;
2587
2588 got_sigill = 1;
2589}
2590
2591static void tcg_target_detect_isa(void)
2592{
2593 struct sigaction sa_old, sa_new;
2594
2595 memset(&sa_new, 0, sizeof(sa_new));
2596 sa_new.sa_flags = SA_SIGINFO;
2597 sa_new.sa_sigaction = sigill_handler;
2598 sigaction(SIGILL, &sa_new, &sa_old);
2599
2600 /* Probe for movn/movz, necessary to implement movcond. */
2601#ifndef use_movnz_instructions
2602 got_sigill = 0;
2603 asm volatile(".set push\n"
2604 ".set mips32\n"
2605 "movn $zero, $zero, $zero\n"
2606 "movz $zero, $zero, $zero\n"
2607 ".set pop\n"
2608 : : : );
2609 use_movnz_instructions = !got_sigill;
2610#endif
2611
2612 /* Probe for MIPS32 instructions. As no subsetting is allowed
2613 by the specification, it is only necessary to probe for one
2614 of the instructions. */
2615#ifndef use_mips32_instructions
2616 got_sigill = 0;
2617 asm volatile(".set push\n"
2618 ".set mips32\n"
2619 "mul $zero, $zero\n"
2620 ".set pop\n"
2621 : : : );
2622 use_mips32_instructions = !got_sigill;
2623#endif
2624
2625 /* Probe for MIPS32r2 instructions if MIPS32 instructions are
2626 available. As no subsetting is allowed by the specification,
2627 it is only necessary to probe for one of the instructions. */
2628#ifndef use_mips32r2_instructions
2629 if (use_mips32_instructions) {
2630 got_sigill = 0;
2631 asm volatile(".set push\n"
2632 ".set mips32r2\n"
2633 "seb $zero, $zero\n"
2634 ".set pop\n"
2635 : : : );
2636 use_mips32r2_instructions = !got_sigill;
2637 }
2638#endif
2639
2640 sigaction(SIGILL, &sa_old, NULL);
2641}
2642
bb08afe9
JG
2643static tcg_insn_unit *align_code_ptr(TCGContext *s)
2644{
2645 uintptr_t p = (uintptr_t)s->code_ptr;
2646 if (p & 15) {
2647 p = (p + 15) & -16;
2648 s->code_ptr = (void *)p;
2649 }
2650 return s->code_ptr;
2651}
2652
0973b1cf
JG
2653/* Stack frame parameters. */
2654#define REG_SIZE (TCG_TARGET_REG_BITS / 8)
2655#define SAVE_SIZE ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE)
2656#define TEMP_SIZE (CPU_TEMP_BUF_NLONGS * (int)sizeof(long))
2657
2658#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \
2659 + TCG_TARGET_STACK_ALIGN - 1) \
2660 & -TCG_TARGET_STACK_ALIGN)
2661#define SAVE_OFS (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE)
2662
2663/* We're expecting to be able to use an immediate for frame allocation. */
2664QEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7fff);
2665
afa05235 2666/* Generate global QEMU prologue and epilogue code */
e4d58b41 2667static void tcg_target_qemu_prologue(TCGContext *s)
afa05235 2668{
0973b1cf
JG
2669 int i;
2670
2671 tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE);
afa05235
AJ
2672
2673 /* TB prologue */
0973b1cf
JG
2674 tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE);
2675 for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
2676 tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
2677 TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
afa05235
AJ
2678 }
2679
4df9cac5
JB
2680#ifndef CONFIG_SOFTMMU
2681 if (guest_base) {
2682 tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base);
2683 tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
2684 }
2685#endif
2686
afa05235 2687 /* Call generated code */
ea15fb06 2688 tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1], 0);
0973b1cf 2689 /* delay slot */
cea5f9a2 2690 tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
afa05235 2691
5786e068
AJ
2692 /*
2693 * Return path for goto_ptr. Set return value to 0, a-la exit_tb,
2694 * and fall through to the rest of the epilogue.
2695 */
c8bc1168 2696 tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr);
5786e068
AJ
2697 tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_V0, TCG_REG_ZERO);
2698
afa05235 2699 /* TB epilogue */
df5af130 2700 tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr);
0973b1cf
JG
2701 for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
2702 tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
2703 TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
afa05235
AJ
2704 }
2705
2706 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
bb08afe9 2707 /* delay slot */
0973b1cf 2708 tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE);
bb08afe9
JG
2709
2710 if (use_mips32r2_instructions) {
2711 return;
2712 }
2713
7f54eaa3 2714 /* Bswap subroutines: Input in TCG_TMP0, output in TCG_TMP3;
bb08afe9
JG
2715 clobbers TCG_TMP1, TCG_TMP2. */
2716
2717 /*
2718 * bswap32 -- 32-bit swap (signed result for mips64). a0 = abcd.
2719 */
df5af130 2720 bswap32_addr = tcg_splitwx_to_rx(align_code_ptr(s));
bb08afe9
JG
2721 /* t3 = (ssss)d000 */
2722 tcg_out_opc_sa(s, OPC_SLL, TCG_TMP3, TCG_TMP0, 24);
2723 /* t1 = 000a */
2724 tcg_out_opc_sa(s, OPC_SRL, TCG_TMP1, TCG_TMP0, 24);
2725 /* t2 = 00c0 */
2726 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP0, 0xff00);
2727 /* t3 = d00a */
2728 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2729 /* t1 = 0abc */
2730 tcg_out_opc_sa(s, OPC_SRL, TCG_TMP1, TCG_TMP0, 8);
2731 /* t2 = 0c00 */
2732 tcg_out_opc_sa(s, OPC_SLL, TCG_TMP2, TCG_TMP2, 8);
2733 /* t1 = 00b0 */
2734 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
2735 /* t3 = dc0a */
2736 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
2737 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
2738 /* t3 = dcba -- delay slot */
2739 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
7f54eaa3
JG
2740
2741 if (TCG_TARGET_REG_BITS == 32) {
2742 return;
2743 }
2744
2745 /*
2746 * bswap32u -- unsigned 32-bit swap. a0 = ....abcd.
2747 */
df5af130 2748 bswap32u_addr = tcg_splitwx_to_rx(align_code_ptr(s));
7f54eaa3
JG
2749 /* t1 = (0000)000d */
2750 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP0, 0xff);
2751 /* t3 = 000a */
2752 tcg_out_opc_sa(s, OPC_SRL, TCG_TMP3, TCG_TMP0, 24);
2753 /* t1 = (0000)d000 */
2754 tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 24);
2755 /* t2 = 00c0 */
2756 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP0, 0xff00);
2757 /* t3 = d00a */
2758 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2759 /* t1 = 0abc */
2760 tcg_out_opc_sa(s, OPC_SRL, TCG_TMP1, TCG_TMP0, 8);
2761 /* t2 = 0c00 */
2762 tcg_out_opc_sa(s, OPC_SLL, TCG_TMP2, TCG_TMP2, 8);
2763 /* t1 = 00b0 */
2764 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
2765 /* t3 = dc0a */
2766 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
2767 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
2768 /* t3 = dcba -- delay slot */
2769 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2770
2771 /*
2772 * bswap64 -- 64-bit swap. a0 = abcdefgh
2773 */
df5af130 2774 bswap64_addr = tcg_splitwx_to_rx(align_code_ptr(s));
7f54eaa3
JG
2775 /* t3 = h0000000 */
2776 tcg_out_dsll(s, TCG_TMP3, TCG_TMP0, 56);
2777 /* t1 = 0000000a */
2778 tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 56);
2779
2780 /* t2 = 000000g0 */
2781 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP0, 0xff00);
2782 /* t3 = h000000a */
2783 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2784 /* t1 = 00000abc */
2785 tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 40);
2786 /* t2 = 0g000000 */
2787 tcg_out_dsll(s, TCG_TMP2, TCG_TMP2, 40);
2788 /* t1 = 000000b0 */
2789 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
2790
2791 /* t3 = hg00000a */
2792 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
2793 /* t2 = 0000abcd */
2794 tcg_out_dsrl(s, TCG_TMP2, TCG_TMP0, 32);
2795 /* t3 = hg0000ba */
2796 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2797
2798 /* t1 = 000000c0 */
2799 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP2, 0xff00);
2800 /* t2 = 0000000d */
2801 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP2, 0x00ff);
2802 /* t1 = 00000c00 */
2803 tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 8);
2804 /* t2 = 0000d000 */
2805 tcg_out_dsll(s, TCG_TMP2, TCG_TMP2, 24);
2806
2807 /* t3 = hg000cba */
2808 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2809 /* t1 = 00abcdef */
2810 tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 16);
2811 /* t3 = hg00dcba */
2812 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
2813
2814 /* t2 = 0000000f */
2815 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP1, 0x00ff);
2816 /* t1 = 000000e0 */
2817 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
2818 /* t2 = 00f00000 */
2819 tcg_out_dsll(s, TCG_TMP2, TCG_TMP2, 40);
2820 /* t1 = 000e0000 */
2821 tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 24);
2822
2823 /* t3 = hgf0dcba */
2824 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
2825 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
2826 /* t3 = hgfedcba -- delay slot */
2827 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
afa05235
AJ
2828}
2829
e4d58b41 2830static void tcg_target_init(TCGContext *s)
afa05235 2831{
988902fc 2832 tcg_target_detect_isa();
d21369f5 2833 tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff;
999b9416 2834 if (TCG_TARGET_REG_BITS == 64) {
d21369f5
RH
2835 tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff;
2836 }
2837
2838 tcg_target_call_clobber_regs = 0;
2839 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V0);
2840 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V1);
2841 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A0);
2842 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A1);
2843 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A2);
2844 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A3);
2845 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T0);
2846 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T1);
2847 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T2);
2848 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T3);
2849 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T4);
2850 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T5);
2851 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T6);
2852 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T7);
2853 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T8);
2854 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T9);
afa05235 2855
ccb1bb66 2856 s->reserved_regs = 0;
afa05235
AJ
2857 tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
2858 tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0); /* kernel use only */
2859 tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1); /* kernel use only */
6c530e32
RH
2860 tcg_regset_set_reg(s->reserved_regs, TCG_TMP0); /* internal use */
2861 tcg_regset_set_reg(s->reserved_regs, TCG_TMP1); /* internal use */
bb08afe9
JG
2862 tcg_regset_set_reg(s->reserved_regs, TCG_TMP2); /* internal use */
2863 tcg_regset_set_reg(s->reserved_regs, TCG_TMP3); /* internal use */
afa05235
AJ
2864 tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return address */
2865 tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */
3314e008 2866 tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP); /* global pointer */
afa05235 2867}
b6bfeea9 2868
98d69076
JG
2869typedef struct {
2870 DebugFrameHeader h;
2871 uint8_t fde_def_cfa[4];
2872 uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
2873} DebugFrame;
2874
2875#define ELF_HOST_MACHINE EM_MIPS
2876/* GDB doesn't appear to require proper setting of ELF_HOST_FLAGS,
2877 which is good because they're really quite complicated for MIPS. */
2878
2879static const DebugFrame debug_frame = {
2880 .h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */
2881 .h.cie.id = -1,
2882 .h.cie.version = 1,
2883 .h.cie.code_align = 1,
2884 .h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */
2885 .h.cie.return_column = TCG_REG_RA,
2886
2887 /* Total FDE size does not include the "len" member. */
2888 .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
2889
2890 .fde_def_cfa = {
2891 12, TCG_REG_SP, /* DW_CFA_def_cfa sp, ... */
2892 (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
2893 (FRAME_SIZE >> 7)
2894 },
2895 .fde_reg_ofs = {
2896 0x80 + 16, 9, /* DW_CFA_offset, s0, -72 */
2897 0x80 + 17, 8, /* DW_CFA_offset, s2, -64 */
2898 0x80 + 18, 7, /* DW_CFA_offset, s3, -56 */
2899 0x80 + 19, 6, /* DW_CFA_offset, s4, -48 */
2900 0x80 + 20, 5, /* DW_CFA_offset, s5, -40 */
2901 0x80 + 21, 4, /* DW_CFA_offset, s6, -32 */
2902 0x80 + 22, 3, /* DW_CFA_offset, s7, -24 */
2903 0x80 + 30, 2, /* DW_CFA_offset, s8, -16 */
2904 0x80 + 31, 1, /* DW_CFA_offset, ra, -8 */
2905 }
2906};
2907
755bf9e5 2908void tcg_register_jit(const void *buf, size_t buf_size)
98d69076
JG
2909{
2910 tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
2911}