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