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