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