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