]> git.proxmox.com Git - mirror_qemu.git/blame - tcg/mips/tcg-target.inc.c
tcg-mips: Move bswap code to a subroutine
[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;
afa05235 128
ae0218e3 129static inline uint32_t reloc_pc16_val(tcg_insn_unit *pc, tcg_insn_unit *target)
afa05235 130{
ae0218e3
RH
131 /* Let the compiler perform the right-shift as part of the arithmetic. */
132 ptrdiff_t disp = target - (pc + 1);
eabb7b91 133 tcg_debug_assert(disp == (int16_t)disp);
ae0218e3 134 return disp & 0xffff;
afa05235
AJ
135}
136
ae0218e3 137static inline void reloc_pc16(tcg_insn_unit *pc, tcg_insn_unit *target)
afa05235 138{
ae0218e3 139 *pc = deposit32(*pc, 0, 16, reloc_pc16_val(pc, target));
afa05235
AJ
140}
141
ae0218e3 142static inline uint32_t reloc_26_val(tcg_insn_unit *pc, tcg_insn_unit *target)
afa05235 143{
eabb7b91 144 tcg_debug_assert((((uintptr_t)pc ^ (uintptr_t)target) & 0xf0000000) == 0);
ae0218e3 145 return ((uintptr_t)target >> 2) & 0x3ffffff;
afa05235
AJ
146}
147
ae0218e3 148static inline void reloc_26(tcg_insn_unit *pc, tcg_insn_unit *target)
afa05235 149{
ae0218e3 150 *pc = deposit32(*pc, 0, 26, reloc_26_val(pc, target));
afa05235
AJ
151}
152
ae0218e3 153static void patch_reloc(tcg_insn_unit *code_ptr, int type,
2ba7fae2 154 intptr_t value, intptr_t addend)
afa05235 155{
eabb7b91
AJ
156 tcg_debug_assert(type == R_MIPS_PC16);
157 tcg_debug_assert(addend == 0);
ae0218e3 158 reloc_pc16(code_ptr, (tcg_insn_unit *)value);
afa05235
AJ
159}
160
1c418268 161#define TCG_CT_CONST_ZERO 0x100
070603f6
RH
162#define TCG_CT_CONST_U16 0x200 /* Unsigned 16-bit: 0 - 0xffff. */
163#define TCG_CT_CONST_S16 0x400 /* Signed 16-bit: -32768 - 32767 */
164#define TCG_CT_CONST_P2M1 0x800 /* Power of 2 minus 1. */
165#define TCG_CT_CONST_N16 0x1000 /* "Negatable" 16-bit: -32767 - 32767 */
1c418268
RH
166
167static inline bool is_p2m1(tcg_target_long val)
168{
169 return val && ((val + 1) & val) == 0;
170}
171
afa05235
AJ
172/* parse target specific constraints */
173static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
174{
175 const char *ct_str;
176
177 ct_str = *pct_str;
178 switch(ct_str[0]) {
179 case 'r':
180 ct->ct |= TCG_CT_REG;
181 tcg_regset_set(ct->u.regs, 0xffffffff);
182 break;
bb08afe9 183 case 'L': /* qemu_ld input arg constraint */
afa05235
AJ
184 ct->ct |= TCG_CT_REG;
185 tcg_regset_set(ct->u.regs, 0xffffffff);
afa05235 186 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
9d8bf2d1
RH
187#if defined(CONFIG_SOFTMMU)
188 if (TARGET_LONG_BITS == 64) {
189 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
190 }
afa05235
AJ
191#endif
192 break;
193 case 'S': /* qemu_st constraint */
194 ct->ct |= TCG_CT_REG;
195 tcg_regset_set(ct->u.regs, 0xffffffff);
afa05235 196 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
cc01cc8e 197#if defined(CONFIG_SOFTMMU)
9d8bf2d1
RH
198 if (TARGET_LONG_BITS == 32) {
199 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1);
200 } else {
201 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
202 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A3);
203 }
afa05235
AJ
204#endif
205 break;
206 case 'I':
207 ct->ct |= TCG_CT_CONST_U16;
208 break;
209 case 'J':
210 ct->ct |= TCG_CT_CONST_S16;
211 break;
1c418268
RH
212 case 'K':
213 ct->ct |= TCG_CT_CONST_P2M1;
214 break;
070603f6
RH
215 case 'N':
216 ct->ct |= TCG_CT_CONST_N16;
217 break;
afa05235
AJ
218 case 'Z':
219 /* We are cheating a bit here, using the fact that the register
220 ZERO is also the register number 0. Hence there is no need
221 to check for const_args in each instruction. */
222 ct->ct |= TCG_CT_CONST_ZERO;
223 break;
224 default:
225 return -1;
226 }
227 ct_str++;
228 *pct_str = ct_str;
229 return 0;
230}
231
232/* test if a constant matches the constraint */
f6c6afc1 233static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
afa05235
AJ
234 const TCGArgConstraint *arg_ct)
235{
236 int ct;
237 ct = arg_ct->ct;
1c418268 238 if (ct & TCG_CT_CONST) {
afa05235 239 return 1;
1c418268 240 } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
afa05235 241 return 1;
1c418268 242 } else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val) {
afa05235 243 return 1;
1c418268 244 } else if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val) {
afa05235 245 return 1;
070603f6
RH
246 } else if ((ct & TCG_CT_CONST_N16) && val >= -32767 && val <= 32767) {
247 return 1;
1c418268
RH
248 } else if ((ct & TCG_CT_CONST_P2M1)
249 && use_mips32r2_instructions && is_p2m1(val)) {
250 return 1;
251 }
252 return 0;
afa05235
AJ
253}
254
255/* instruction opcodes */
ac0f3b12 256typedef enum {
f8c9eddb
RH
257 OPC_J = 0x02 << 26,
258 OPC_JAL = 0x03 << 26,
afa05235
AJ
259 OPC_BEQ = 0x04 << 26,
260 OPC_BNE = 0x05 << 26,
0f46c064
AJ
261 OPC_BLEZ = 0x06 << 26,
262 OPC_BGTZ = 0x07 << 26,
afa05235 263 OPC_ADDIU = 0x09 << 26,
4cb26382
AJ
264 OPC_SLTI = 0x0A << 26,
265 OPC_SLTIU = 0x0B << 26,
afa05235
AJ
266 OPC_ANDI = 0x0C << 26,
267 OPC_ORI = 0x0D << 26,
268 OPC_XORI = 0x0E << 26,
269 OPC_LUI = 0x0F << 26,
270 OPC_LB = 0x20 << 26,
271 OPC_LH = 0x21 << 26,
272 OPC_LW = 0x23 << 26,
273 OPC_LBU = 0x24 << 26,
274 OPC_LHU = 0x25 << 26,
275 OPC_LWU = 0x27 << 26,
276 OPC_SB = 0x28 << 26,
277 OPC_SH = 0x29 << 26,
278 OPC_SW = 0x2B << 26,
116348de
AJ
279
280 OPC_SPECIAL = 0x00 << 26,
afa05235
AJ
281 OPC_SLL = OPC_SPECIAL | 0x00,
282 OPC_SRL = OPC_SPECIAL | 0x02,
9a152519 283 OPC_ROTR = OPC_SPECIAL | (0x01 << 21) | 0x02,
afa05235
AJ
284 OPC_SRA = OPC_SPECIAL | 0x03,
285 OPC_SLLV = OPC_SPECIAL | 0x04,
286 OPC_SRLV = OPC_SPECIAL | 0x06,
9a152519 287 OPC_ROTRV = OPC_SPECIAL | (0x01 << 6) | 0x06,
afa05235 288 OPC_SRAV = OPC_SPECIAL | 0x07,
6e0d0969 289 OPC_JR_R5 = OPC_SPECIAL | 0x08,
afa05235 290 OPC_JALR = OPC_SPECIAL | 0x09,
7d7c4930
AJ
291 OPC_MOVZ = OPC_SPECIAL | 0x0A,
292 OPC_MOVN = OPC_SPECIAL | 0x0B,
6f0b9910 293 OPC_SYNC = OPC_SPECIAL | 0x0F,
afa05235
AJ
294 OPC_MFHI = OPC_SPECIAL | 0x10,
295 OPC_MFLO = OPC_SPECIAL | 0x12,
296 OPC_MULT = OPC_SPECIAL | 0x18,
bc6d0c22
JH
297 OPC_MUL_R6 = OPC_SPECIAL | (0x02 << 6) | 0x18,
298 OPC_MUH = OPC_SPECIAL | (0x03 << 6) | 0x18,
afa05235 299 OPC_MULTU = OPC_SPECIAL | 0x19,
bc6d0c22
JH
300 OPC_MULU = OPC_SPECIAL | (0x02 << 6) | 0x19,
301 OPC_MUHU = OPC_SPECIAL | (0x03 << 6) | 0x19,
afa05235 302 OPC_DIV = OPC_SPECIAL | 0x1A,
bc6d0c22
JH
303 OPC_DIV_R6 = OPC_SPECIAL | (0x02 << 6) | 0x1A,
304 OPC_MOD = OPC_SPECIAL | (0x03 << 6) | 0x1A,
afa05235 305 OPC_DIVU = OPC_SPECIAL | 0x1B,
bc6d0c22
JH
306 OPC_DIVU_R6 = OPC_SPECIAL | (0x02 << 6) | 0x1B,
307 OPC_MODU = OPC_SPECIAL | (0x03 << 6) | 0x1B,
afa05235
AJ
308 OPC_ADDU = OPC_SPECIAL | 0x21,
309 OPC_SUBU = OPC_SPECIAL | 0x23,
310 OPC_AND = OPC_SPECIAL | 0x24,
311 OPC_OR = OPC_SPECIAL | 0x25,
312 OPC_XOR = OPC_SPECIAL | 0x26,
313 OPC_NOR = OPC_SPECIAL | 0x27,
314 OPC_SLT = OPC_SPECIAL | 0x2A,
315 OPC_SLTU = OPC_SPECIAL | 0x2B,
137d6390
JH
316 OPC_SELEQZ = OPC_SPECIAL | 0x35,
317 OPC_SELNEZ = OPC_SPECIAL | 0x37,
116348de 318
0f46c064
AJ
319 OPC_REGIMM = 0x01 << 26,
320 OPC_BLTZ = OPC_REGIMM | (0x00 << 16),
321 OPC_BGEZ = OPC_REGIMM | (0x01 << 16),
322
3585317f 323 OPC_SPECIAL2 = 0x1c << 26,
bc6d0c22 324 OPC_MUL_R5 = OPC_SPECIAL2 | 0x002,
3585317f 325
116348de 326 OPC_SPECIAL3 = 0x1f << 26,
1c418268 327 OPC_EXT = OPC_SPECIAL3 | 0x000,
04f71aa3 328 OPC_INS = OPC_SPECIAL3 | 0x004,
c1cf85c9 329 OPC_WSBH = OPC_SPECIAL3 | 0x0a0,
116348de
AJ
330 OPC_SEB = OPC_SPECIAL3 | 0x420,
331 OPC_SEH = OPC_SPECIAL3 | 0x620,
6e0d0969
JH
332
333 /* MIPS r6 doesn't have JR, JALR should be used instead */
334 OPC_JR = use_mips32r6_instructions ? OPC_JALR : OPC_JR_R5,
bc6d0c22
JH
335
336 /*
337 * MIPS r6 replaces MUL with an alternative encoding which is
338 * backwards-compatible at the assembly level.
339 */
340 OPC_MUL = use_mips32r6_instructions ? OPC_MUL_R6 : OPC_MUL_R5,
6f0b9910
PK
341
342 /* MIPS r6 introduced names for weaker variants of SYNC. These are
343 backward compatible to previous architecture revisions. */
344 OPC_SYNC_WMB = OPC_SYNC | 0x04 << 5,
345 OPC_SYNC_MB = OPC_SYNC | 0x10 << 5,
346 OPC_SYNC_ACQUIRE = OPC_SYNC | 0x11 << 5,
347 OPC_SYNC_RELEASE = OPC_SYNC | 0x12 << 5,
348 OPC_SYNC_RMB = OPC_SYNC | 0x13 << 5,
ac0f3b12 349} MIPSInsn;
afa05235
AJ
350
351/*
352 * Type reg
353 */
ac0f3b12 354static inline void tcg_out_opc_reg(TCGContext *s, MIPSInsn opc,
5a0eed37 355 TCGReg rd, TCGReg rs, TCGReg rt)
afa05235
AJ
356{
357 int32_t inst;
358
359 inst = opc;
360 inst |= (rs & 0x1F) << 21;
361 inst |= (rt & 0x1F) << 16;
362 inst |= (rd & 0x1F) << 11;
363 tcg_out32(s, inst);
364}
365
366/*
367 * Type immediate
368 */
ac0f3b12 369static inline void tcg_out_opc_imm(TCGContext *s, MIPSInsn opc,
5a0eed37 370 TCGReg rt, TCGReg rs, TCGArg imm)
afa05235
AJ
371{
372 int32_t inst;
373
374 inst = opc;
375 inst |= (rs & 0x1F) << 21;
376 inst |= (rt & 0x1F) << 16;
377 inst |= (imm & 0xffff);
378 tcg_out32(s, inst);
379}
380
1c418268
RH
381/*
382 * Type bitfield
383 */
ac0f3b12 384static inline void tcg_out_opc_bf(TCGContext *s, MIPSInsn opc, TCGReg rt,
1c418268
RH
385 TCGReg rs, int msb, int lsb)
386{
387 int32_t inst;
388
389 inst = opc;
390 inst |= (rs & 0x1F) << 21;
391 inst |= (rt & 0x1F) << 16;
392 inst |= (msb & 0x1F) << 11;
393 inst |= (lsb & 0x1F) << 6;
394 tcg_out32(s, inst);
395}
396
6d8ff4d8
AJ
397/*
398 * Type branch
399 */
ac0f3b12 400static inline void tcg_out_opc_br(TCGContext *s, MIPSInsn opc,
5a0eed37 401 TCGReg rt, TCGReg rs)
6d8ff4d8 402{
56779034
AJ
403 /* We pay attention here to not modify the branch target by reading
404 the existing value and using it again. This ensure that caches and
405 memory are kept coherent during retranslation. */
ae0218e3 406 uint16_t offset = (uint16_t)*s->code_ptr;
6d8ff4d8
AJ
407
408 tcg_out_opc_imm(s, opc, rt, rs, offset);
409}
410
afa05235
AJ
411/*
412 * Type sa
413 */
ac0f3b12 414static inline void tcg_out_opc_sa(TCGContext *s, MIPSInsn opc,
5a0eed37 415 TCGReg rd, TCGReg rt, TCGArg sa)
afa05235
AJ
416{
417 int32_t inst;
418
419 inst = opc;
420 inst |= (rt & 0x1F) << 16;
421 inst |= (rd & 0x1F) << 11;
422 inst |= (sa & 0x1F) << 6;
423 tcg_out32(s, inst);
424
425}
426
f8c9eddb
RH
427/*
428 * Type jump.
429 * Returns true if the branch was in range and the insn was emitted.
430 */
ac0f3b12 431static bool tcg_out_opc_jmp(TCGContext *s, MIPSInsn opc, void *target)
f8c9eddb
RH
432{
433 uintptr_t dest = (uintptr_t)target;
434 uintptr_t from = (uintptr_t)s->code_ptr + 4;
435 int32_t inst;
436
437 /* The pc-region branch happens within the 256MB region of
438 the delay slot (thus the +4). */
439 if ((from ^ dest) & -(1 << 28)) {
440 return false;
441 }
eabb7b91 442 tcg_debug_assert((dest & 3) == 0);
f8c9eddb
RH
443
444 inst = opc;
445 inst |= (dest >> 2) & 0x3ffffff;
446 tcg_out32(s, inst);
447 return true;
448}
449
afa05235
AJ
450static inline void tcg_out_nop(TCGContext *s)
451{
452 tcg_out32(s, 0);
453}
454
2a534aff
RH
455static inline void tcg_out_mov(TCGContext *s, TCGType type,
456 TCGReg ret, TCGReg arg)
afa05235 457{
18fec301
AJ
458 /* Simple reg-reg move, optimising out the 'do nothing' case */
459 if (ret != arg) {
460 tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
461 }
afa05235
AJ
462}
463
464static inline void tcg_out_movi(TCGContext *s, TCGType type,
2a534aff 465 TCGReg reg, tcg_target_long arg)
afa05235
AJ
466{
467 if (arg == (int16_t)arg) {
468 tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
469 } else if (arg == (uint16_t)arg) {
470 tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
471 } else {
7dae901d
RH
472 tcg_out_opc_imm(s, OPC_LUI, reg, TCG_REG_ZERO, arg >> 16);
473 if (arg & 0xffff) {
474 tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0xffff);
475 }
afa05235
AJ
476 }
477}
478
5a0eed37 479static inline void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg)
afa05235 480{
988902fc
AJ
481 if (use_mips32r2_instructions) {
482 tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
483 } else {
484 /* ret and arg can't be register at */
6c530e32 485 if (ret == TCG_TMP0 || arg == TCG_TMP0) {
988902fc
AJ
486 tcg_abort();
487 }
afa05235 488
6c530e32 489 tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8);
988902fc
AJ
490 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
491 tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
6c530e32 492 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
988902fc 493 }
afa05235
AJ
494}
495
5a0eed37 496static inline void tcg_out_bswap16s(TCGContext *s, TCGReg ret, TCGReg arg)
afa05235 497{
988902fc
AJ
498 if (use_mips32r2_instructions) {
499 tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
500 tcg_out_opc_reg(s, OPC_SEH, ret, 0, ret);
501 } else {
502 /* ret and arg can't be register at */
6c530e32 503 if (ret == TCG_TMP0 || arg == TCG_TMP0) {
988902fc
AJ
504 tcg_abort();
505 }
afa05235 506
6c530e32 507 tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8);
988902fc
AJ
508 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
509 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
6c530e32 510 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
988902fc 511 }
afa05235
AJ
512}
513
bb08afe9
JG
514static void tcg_out_bswap_subr(TCGContext *s, tcg_insn_unit *sub)
515{
516 bool ok = tcg_out_opc_jmp(s, OPC_JAL, sub);
517 tcg_debug_assert(ok);
518}
519
520static void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg)
afa05235 521{
988902fc
AJ
522 if (use_mips32r2_instructions) {
523 tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
524 tcg_out_opc_sa(s, OPC_ROTR, ret, ret, 16);
525 } else {
bb08afe9
JG
526 tcg_out_bswap_subr(s, bswap32_addr);
527 /* delay slot -- never omit the insn, like tcg_out_mov might. */
528 tcg_out_opc_reg(s, OPC_OR, TCG_TMP0, arg, TCG_REG_ZERO);
529 tcg_out_mov(s, TCG_TYPE_I32, ret, TCG_TMP3);
988902fc 530 }
afa05235
AJ
531}
532
5a0eed37 533static inline void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg)
116348de 534{
988902fc
AJ
535 if (use_mips32r2_instructions) {
536 tcg_out_opc_reg(s, OPC_SEB, ret, 0, arg);
537 } else {
538 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
539 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 24);
540 }
116348de
AJ
541}
542
5a0eed37 543static inline void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg)
116348de 544{
988902fc
AJ
545 if (use_mips32r2_instructions) {
546 tcg_out_opc_reg(s, OPC_SEH, ret, 0, arg);
547 } else {
548 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 16);
549 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
550 }
116348de
AJ
551}
552
ac0f3b12 553static void tcg_out_ldst(TCGContext *s, MIPSInsn opc, TCGReg data,
f9a71632 554 TCGReg addr, intptr_t ofs)
afa05235 555{
f9a71632
RH
556 int16_t lo = ofs;
557 if (ofs != lo) {
6c530e32 558 tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, ofs - lo);
f9a71632 559 if (addr != TCG_REG_ZERO) {
6c530e32 560 tcg_out_opc_reg(s, OPC_ADDU, TCG_TMP0, TCG_TMP0, addr);
f9a71632 561 }
6c530e32 562 addr = TCG_TMP0;
afa05235 563 }
f9a71632 564 tcg_out_opc_imm(s, opc, data, addr, lo);
afa05235
AJ
565}
566
2a534aff 567static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
a05b5b9b 568 TCGReg arg1, intptr_t arg2)
afa05235
AJ
569{
570 tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
571}
572
2a534aff 573static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
a05b5b9b 574 TCGReg arg1, intptr_t arg2)
afa05235
AJ
575{
576 tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
577}
578
59d7c14e
RH
579static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
580 TCGReg base, intptr_t ofs)
581{
582 if (val == 0) {
583 tcg_out_st(s, type, TCG_REG_ZERO, base, ofs);
584 return true;
585 }
586 return false;
587}
588
5a0eed37 589static inline void tcg_out_addi(TCGContext *s, TCGReg reg, TCGArg val)
afa05235
AJ
590{
591 if (val == (int16_t)val) {
592 tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
593 } else {
6c530e32
RH
594 tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, val);
595 tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_TMP0);
afa05235
AJ
596 }
597}
598
d9f26847
AJ
599static void tcg_out_addsub2(TCGContext *s, TCGReg rl, TCGReg rh, TCGReg al,
600 TCGReg ah, TCGArg bl, TCGArg bh, bool cbl,
601 bool cbh, bool is_sub)
602{
603 TCGReg th = TCG_TMP1;
604
605 /* If we have a negative constant such that negating it would
606 make the high part zero, we can (usually) eliminate one insn. */
607 if (cbl && cbh && bh == -1 && bl != 0) {
608 bl = -bl;
609 bh = 0;
610 is_sub = !is_sub;
611 }
612
613 /* By operating on the high part first, we get to use the final
614 carry operation to move back from the temporary. */
615 if (!cbh) {
616 tcg_out_opc_reg(s, (is_sub ? OPC_SUBU : OPC_ADDU), th, ah, bh);
617 } else if (bh != 0 || ah == rl) {
618 tcg_out_opc_imm(s, OPC_ADDIU, th, ah, (is_sub ? -bh : bh));
619 } else {
620 th = ah;
621 }
622
623 /* Note that tcg optimization should eliminate the bl == 0 case. */
624 if (is_sub) {
625 if (cbl) {
626 tcg_out_opc_imm(s, OPC_SLTIU, TCG_TMP0, al, bl);
627 tcg_out_opc_imm(s, OPC_ADDIU, rl, al, -bl);
628 } else {
629 tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, al, bl);
630 tcg_out_opc_reg(s, OPC_SUBU, rl, al, bl);
631 }
632 tcg_out_opc_reg(s, OPC_SUBU, rh, th, TCG_TMP0);
633 } else {
634 if (cbl) {
635 tcg_out_opc_imm(s, OPC_ADDIU, rl, al, bl);
636 tcg_out_opc_imm(s, OPC_SLTIU, TCG_TMP0, rl, bl);
637 } else if (rl == al && rl == bl) {
638 tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, al, 31);
639 tcg_out_opc_reg(s, OPC_ADDU, rl, al, bl);
640 } else {
641 tcg_out_opc_reg(s, OPC_ADDU, rl, al, bl);
642 tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, rl, (rl == bl ? al : bl));
643 }
644 tcg_out_opc_reg(s, OPC_ADDU, rh, th, TCG_TMP0);
645 }
646}
647
fd1cf666
RH
648/* Bit 0 set if inversion required; bit 1 set if swapping required. */
649#define MIPS_CMP_INV 1
650#define MIPS_CMP_SWAP 2
651
652static const uint8_t mips_cmp_map[16] = {
653 [TCG_COND_LT] = 0,
654 [TCG_COND_LTU] = 0,
655 [TCG_COND_GE] = MIPS_CMP_INV,
656 [TCG_COND_GEU] = MIPS_CMP_INV,
657 [TCG_COND_LE] = MIPS_CMP_INV | MIPS_CMP_SWAP,
658 [TCG_COND_LEU] = MIPS_CMP_INV | MIPS_CMP_SWAP,
659 [TCG_COND_GT] = MIPS_CMP_SWAP,
660 [TCG_COND_GTU] = MIPS_CMP_SWAP,
661};
662
663static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
664 TCGReg arg1, TCGReg arg2)
665{
666 MIPSInsn s_opc = OPC_SLTU;
667 int cmp_map;
668
669 switch (cond) {
670 case TCG_COND_EQ:
671 if (arg2 != 0) {
672 tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
673 arg1 = ret;
674 }
675 tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, 1);
676 break;
677
678 case TCG_COND_NE:
679 if (arg2 != 0) {
680 tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
681 arg1 = ret;
682 }
683 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg1);
684 break;
685
686 case TCG_COND_LT:
687 case TCG_COND_GE:
688 case TCG_COND_LE:
689 case TCG_COND_GT:
690 s_opc = OPC_SLT;
691 /* FALLTHRU */
692
693 case TCG_COND_LTU:
694 case TCG_COND_GEU:
695 case TCG_COND_LEU:
696 case TCG_COND_GTU:
697 cmp_map = mips_cmp_map[cond];
698 if (cmp_map & MIPS_CMP_SWAP) {
699 TCGReg t = arg1;
700 arg1 = arg2;
701 arg2 = t;
702 }
703 tcg_out_opc_reg(s, s_opc, ret, arg1, arg2);
704 if (cmp_map & MIPS_CMP_INV) {
705 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
706 }
707 break;
708
709 default:
710 tcg_abort();
711 break;
712 }
713}
714
c068896f 715static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
bec16311 716 TCGReg arg2, TCGLabel *l)
afa05235 717{
c068896f
RH
718 static const MIPSInsn b_zero[16] = {
719 [TCG_COND_LT] = OPC_BLTZ,
720 [TCG_COND_GT] = OPC_BGTZ,
721 [TCG_COND_LE] = OPC_BLEZ,
722 [TCG_COND_GE] = OPC_BGEZ,
723 };
724
c068896f
RH
725 MIPSInsn s_opc = OPC_SLTU;
726 MIPSInsn b_opc;
727 int cmp_map;
afa05235
AJ
728
729 switch (cond) {
730 case TCG_COND_EQ:
c068896f 731 b_opc = OPC_BEQ;
afa05235
AJ
732 break;
733 case TCG_COND_NE:
c068896f 734 b_opc = OPC_BNE;
afa05235 735 break;
c068896f 736
afa05235 737 case TCG_COND_LT:
c068896f 738 case TCG_COND_GT:
afa05235 739 case TCG_COND_LE:
c068896f 740 case TCG_COND_GE:
0f46c064 741 if (arg2 == 0) {
c068896f
RH
742 b_opc = b_zero[cond];
743 arg2 = arg1;
744 arg1 = 0;
745 break;
0f46c064 746 }
c068896f
RH
747 s_opc = OPC_SLT;
748 /* FALLTHRU */
749
750 case TCG_COND_LTU:
751 case TCG_COND_GTU:
afa05235 752 case TCG_COND_LEU:
c068896f
RH
753 case TCG_COND_GEU:
754 cmp_map = mips_cmp_map[cond];
755 if (cmp_map & MIPS_CMP_SWAP) {
756 TCGReg t = arg1;
757 arg1 = arg2;
758 arg2 = t;
0f46c064 759 }
c068896f
RH
760 tcg_out_opc_reg(s, s_opc, TCG_TMP0, arg1, arg2);
761 b_opc = (cmp_map & MIPS_CMP_INV ? OPC_BEQ : OPC_BNE);
762 arg1 = TCG_TMP0;
763 arg2 = TCG_REG_ZERO;
afa05235 764 break;
c068896f 765
afa05235
AJ
766 default:
767 tcg_abort();
768 break;
769 }
c068896f
RH
770
771 tcg_out_opc_br(s, b_opc, arg1, arg2);
afa05235 772 if (l->has_value) {
ae0218e3 773 reloc_pc16(s->code_ptr - 1, l->u.value_ptr);
afa05235 774 } else {
bec16311 775 tcg_out_reloc(s, s->code_ptr - 1, R_MIPS_PC16, l, 0);
afa05235
AJ
776 }
777 tcg_out_nop(s);
778}
779
1db1c4d7
RH
780static TCGReg tcg_out_reduce_eq2(TCGContext *s, TCGReg tmp0, TCGReg tmp1,
781 TCGReg al, TCGReg ah,
782 TCGReg bl, TCGReg bh)
783{
784 /* Merge highpart comparison into AH. */
785 if (bh != 0) {
786 if (ah != 0) {
787 tcg_out_opc_reg(s, OPC_XOR, tmp0, ah, bh);
788 ah = tmp0;
789 } else {
790 ah = bh;
791 }
792 }
793 /* Merge lowpart comparison into AL. */
794 if (bl != 0) {
795 if (al != 0) {
796 tcg_out_opc_reg(s, OPC_XOR, tmp1, al, bl);
797 al = tmp1;
798 } else {
799 al = bl;
800 }
801 }
802 /* Merge high and low part comparisons into AL. */
803 if (ah != 0) {
804 if (al != 0) {
805 tcg_out_opc_reg(s, OPC_OR, tmp0, ah, al);
806 al = tmp0;
807 } else {
808 al = ah;
809 }
810 }
811 return al;
812}
813
9a2f0bfe
RH
814static void tcg_out_setcond2(TCGContext *s, TCGCond cond, TCGReg ret,
815 TCGReg al, TCGReg ah, TCGReg bl, TCGReg bh)
816{
817 TCGReg tmp0 = TCG_TMP0;
818 TCGReg tmp1 = ret;
819
eabb7b91 820 tcg_debug_assert(ret != TCG_TMP0);
9a2f0bfe 821 if (ret == ah || ret == bh) {
eabb7b91 822 tcg_debug_assert(ret != TCG_TMP1);
9a2f0bfe
RH
823 tmp1 = TCG_TMP1;
824 }
825
826 switch (cond) {
827 case TCG_COND_EQ:
828 case TCG_COND_NE:
1db1c4d7
RH
829 tmp1 = tcg_out_reduce_eq2(s, tmp0, tmp1, al, ah, bl, bh);
830 tcg_out_setcond(s, cond, ret, tmp1, TCG_REG_ZERO);
9a2f0bfe
RH
831 break;
832
833 default:
834 tcg_out_setcond(s, TCG_COND_EQ, tmp0, ah, bh);
835 tcg_out_setcond(s, tcg_unsigned_cond(cond), tmp1, al, bl);
836 tcg_out_opc_reg(s, OPC_AND, tmp1, tmp1, tmp0);
837 tcg_out_setcond(s, tcg_high_cond(cond), tmp0, ah, bh);
838 tcg_out_opc_reg(s, OPC_OR, ret, tmp1, tmp0);
839 break;
840 }
841}
842
3401fd25 843static void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGReg al, TCGReg ah,
bec16311 844 TCGReg bl, TCGReg bh, TCGLabel *l)
3401fd25
RH
845{
846 TCGCond b_cond = TCG_COND_NE;
847 TCGReg tmp = TCG_TMP1;
848
849 /* With branches, we emit between 4 and 9 insns with 2 or 3 branches.
850 With setcond, we emit between 3 and 10 insns and only 1 branch,
851 which ought to get better branch prediction. */
852 switch (cond) {
853 case TCG_COND_EQ:
854 case TCG_COND_NE:
855 b_cond = cond;
856 tmp = tcg_out_reduce_eq2(s, TCG_TMP0, TCG_TMP1, al, ah, bl, bh);
afa05235 857 break;
afa05235 858
afa05235 859 default:
5d831be2 860 /* Minimize code size by preferring a compare not requiring INV. */
3401fd25
RH
861 if (mips_cmp_map[cond] & MIPS_CMP_INV) {
862 cond = tcg_invert_cond(cond);
863 b_cond = TCG_COND_EQ;
864 }
865 tcg_out_setcond2(s, cond, tmp, al, ah, bl, bh);
866 break;
afa05235
AJ
867 }
868
bec16311 869 tcg_out_brcond(s, b_cond, tmp, TCG_REG_ZERO, l);
afa05235
AJ
870}
871
7d7c4930 872static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
137d6390 873 TCGReg c1, TCGReg c2, TCGReg v1, TCGReg v2)
7d7c4930 874{
137d6390
JH
875 bool eqz = false;
876
877 /* If one of the values is zero, put it last to match SEL*Z instructions */
878 if (use_mips32r6_instructions && v1 == 0) {
879 v1 = v2;
880 v2 = 0;
881 cond = tcg_invert_cond(cond);
882 }
33fac20b 883
7d7c4930
AJ
884 switch (cond) {
885 case TCG_COND_EQ:
137d6390 886 eqz = true;
33fac20b 887 /* FALLTHRU */
7d7c4930 888 case TCG_COND_NE:
33fac20b 889 if (c2 != 0) {
6c530e32 890 tcg_out_opc_reg(s, OPC_XOR, TCG_TMP0, c1, c2);
33fac20b 891 c1 = TCG_TMP0;
7d7c4930
AJ
892 }
893 break;
33fac20b 894
7d7c4930 895 default:
5d831be2 896 /* Minimize code size by preferring a compare not requiring INV. */
33fac20b
RH
897 if (mips_cmp_map[cond] & MIPS_CMP_INV) {
898 cond = tcg_invert_cond(cond);
137d6390 899 eqz = true;
33fac20b
RH
900 }
901 tcg_out_setcond(s, cond, TCG_TMP0, c1, c2);
902 c1 = TCG_TMP0;
7d7c4930
AJ
903 break;
904 }
33fac20b 905
137d6390
JH
906 if (use_mips32r6_instructions) {
907 MIPSInsn m_opc_t = eqz ? OPC_SELEQZ : OPC_SELNEZ;
908 MIPSInsn m_opc_f = eqz ? OPC_SELNEZ : OPC_SELEQZ;
909
910 if (v2 != 0) {
911 tcg_out_opc_reg(s, m_opc_f, TCG_TMP1, v2, c1);
912 }
913 tcg_out_opc_reg(s, m_opc_t, ret, v1, c1);
914 if (v2 != 0) {
915 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP1);
916 }
917 } else {
918 MIPSInsn m_opc = eqz ? OPC_MOVZ : OPC_MOVN;
919
920 tcg_out_opc_reg(s, m_opc, ret, v1, c1);
921
922 /* This should be guaranteed via constraints */
923 tcg_debug_assert(v2 == ret);
924 }
7d7c4930
AJ
925}
926
ce0236cf 927static void tcg_out_call_int(TCGContext *s, tcg_insn_unit *arg, bool tail)
9d8bf2d1
RH
928{
929 /* Note that the ABI requires the called function's address to be
930 loaded into T9, even if a direct branch is in range. */
931 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T9, (uintptr_t)arg);
932
933 /* But do try a direct branch, allowing the cpu better insn prefetch. */
ce0236cf
RH
934 if (tail) {
935 if (!tcg_out_opc_jmp(s, OPC_J, arg)) {
936 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_T9, 0);
937 }
938 } else {
939 if (!tcg_out_opc_jmp(s, OPC_JAL, arg)) {
940 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
941 }
9d8bf2d1 942 }
ce0236cf 943}
9d8bf2d1 944
ce0236cf
RH
945static void tcg_out_call(TCGContext *s, tcg_insn_unit *arg)
946{
947 tcg_out_call_int(s, arg, false);
9d8bf2d1
RH
948 tcg_out_nop(s);
949}
950
afa05235 951#if defined(CONFIG_SOFTMMU)
ce0236cf
RH
952static void * const qemu_ld_helpers[16] = {
953 [MO_UB] = helper_ret_ldub_mmu,
954 [MO_SB] = helper_ret_ldsb_mmu,
955 [MO_LEUW] = helper_le_lduw_mmu,
956 [MO_LESW] = helper_le_ldsw_mmu,
957 [MO_LEUL] = helper_le_ldul_mmu,
958 [MO_LEQ] = helper_le_ldq_mmu,
959 [MO_BEUW] = helper_be_lduw_mmu,
960 [MO_BESW] = helper_be_ldsw_mmu,
961 [MO_BEUL] = helper_be_ldul_mmu,
962 [MO_BEQ] = helper_be_ldq_mmu,
e141ab52
BS
963};
964
ce0236cf
RH
965static void * const qemu_st_helpers[16] = {
966 [MO_UB] = helper_ret_stb_mmu,
967 [MO_LEUW] = helper_le_stw_mmu,
968 [MO_LEUL] = helper_le_stl_mmu,
969 [MO_LEQ] = helper_le_stq_mmu,
970 [MO_BEUW] = helper_be_stw_mmu,
971 [MO_BEUL] = helper_be_stl_mmu,
972 [MO_BEQ] = helper_be_stq_mmu,
e141ab52 973};
afa05235 974
9d8bf2d1
RH
975/* Helper routines for marshalling helper function arguments into
976 * the correct registers and stack.
977 * I is where we want to put this argument, and is updated and returned
978 * for the next call. ARG is the argument itself.
979 *
980 * We provide routines for arguments which are: immediate, 32 bit
981 * value in register, 16 and 8 bit values in register (which must be zero
982 * extended before use) and 64 bit value in a lo:hi register pair.
983 */
984
985static int tcg_out_call_iarg_reg(TCGContext *s, int i, TCGReg arg)
afa05235 986{
9d8bf2d1
RH
987 if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
988 tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[i], arg);
989 } else {
990 tcg_out_st(s, TCG_TYPE_REG, arg, TCG_REG_SP, 4 * i);
991 }
992 return i + 1;
993}
afa05235 994
9d8bf2d1
RH
995static int tcg_out_call_iarg_reg8(TCGContext *s, int i, TCGReg arg)
996{
6c530e32 997 TCGReg tmp = TCG_TMP0;
9d8bf2d1
RH
998 if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
999 tmp = tcg_target_call_iarg_regs[i];
1000 }
1001 tcg_out_opc_imm(s, OPC_ANDI, tmp, arg, 0xff);
1002 return tcg_out_call_iarg_reg(s, i, tmp);
1003}
1004
1005static int tcg_out_call_iarg_reg16(TCGContext *s, int i, TCGReg arg)
1006{
6c530e32 1007 TCGReg tmp = TCG_TMP0;
9d8bf2d1
RH
1008 if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
1009 tmp = tcg_target_call_iarg_regs[i];
1010 }
1011 tcg_out_opc_imm(s, OPC_ANDI, tmp, arg, 0xffff);
1012 return tcg_out_call_iarg_reg(s, i, tmp);
1013}
1014
1015static int tcg_out_call_iarg_imm(TCGContext *s, int i, TCGArg arg)
1016{
6c530e32 1017 TCGReg tmp = TCG_TMP0;
9d8bf2d1
RH
1018 if (arg == 0) {
1019 tmp = TCG_REG_ZERO;
afa05235 1020 } else {
9d8bf2d1
RH
1021 if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
1022 tmp = tcg_target_call_iarg_regs[i];
1023 }
1024 tcg_out_movi(s, TCG_TYPE_REG, tmp, arg);
afa05235 1025 }
9d8bf2d1
RH
1026 return tcg_out_call_iarg_reg(s, i, tmp);
1027}
1028
1029static int tcg_out_call_iarg_reg2(TCGContext *s, int i, TCGReg al, TCGReg ah)
1030{
1031 i = (i + 1) & ~1;
1032 i = tcg_out_call_iarg_reg(s, i, (MIPS_BE ? ah : al));
1033 i = tcg_out_call_iarg_reg(s, i, (MIPS_BE ? al : ah));
1034 return i;
1035}
1036
1037/* Perform the tlb comparison operation. The complete host address is
bb08afe9 1038 placed in BASE. Clobbers TMP0, TMP1, A0. */
9d8bf2d1 1039static void tcg_out_tlb_load(TCGContext *s, TCGReg base, TCGReg addrl,
81dfaf1a 1040 TCGReg addrh, TCGMemOpIdx oi,
9d8bf2d1
RH
1041 tcg_insn_unit *label_ptr[2], bool is_load)
1042{
85aa8081
RH
1043 TCGMemOp opc = get_memop(oi);
1044 unsigned s_bits = opc & MO_SIZE;
1045 unsigned a_bits = get_alignment_bits(opc);
81dfaf1a 1046 int mem_index = get_mmuidx(oi);
9d8bf2d1
RH
1047 int cmp_off
1048 = (is_load
1049 ? offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)
1050 : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write));
1051 int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend);
1052
1053 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addrl,
1054 TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
1055 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0,
1056 (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
afa05235 1057 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
afa05235 1058
9d8bf2d1
RH
1059 /* Compensate for very large offsets. */
1060 if (add_off >= 0x8000) {
1061 /* Most target env are smaller than 32k; none are larger than 64k.
1062 Simplify the logic here merely to offset by 0x7ff0, giving us a
1063 range just shy of 64k. Check this assumption. */
1064 QEMU_BUILD_BUG_ON(offsetof(CPUArchState,
1065 tlb_table[NB_MMU_MODES - 1][1])
1066 > 0x7ff0 + 0x7fff);
1067 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_A0, TCG_REG_A0, 0x7ff0);
1068 cmp_off -= 0x7ff0;
1069 add_off -= 0x7ff0;
1070 }
1071
5eb4f645
JH
1072 /* Load the (low half) tlb comparator. */
1073 tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, TCG_REG_A0,
1074 cmp_off + (TARGET_LONG_BITS == 64 ? LO_OFF : 0));
9d8bf2d1 1075
85aa8081
RH
1076 /* We don't currently support unaligned accesses.
1077 We could do so with mips32r6. */
1078 if (a_bits < s_bits) {
1079 a_bits = s_bits;
1080 }
9d8bf2d1 1081 /* Mask the page bits, keeping the alignment bits to compare against.
5eb4f645 1082 In between on 32-bit targets, load the tlb addend for the fast path. */
6c530e32 1083 tcg_out_movi(s, TCG_TYPE_I32, TCG_TMP1,
85aa8081 1084 TARGET_PAGE_MASK | ((1 << a_bits) - 1));
5eb4f645
JH
1085 if (TARGET_LONG_BITS == 32) {
1086 tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0, add_off);
1087 }
6c530e32 1088 tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, addrl);
9d8bf2d1
RH
1089
1090 label_ptr[0] = s->code_ptr;
6c530e32 1091 tcg_out_opc_br(s, OPC_BNE, TCG_TMP1, TCG_TMP0);
afa05235 1092
5eb4f645 1093 /* Load and test the high half tlb comparator. */
9d8bf2d1
RH
1094 if (TARGET_LONG_BITS == 64) {
1095 /* delay slot */
5eb4f645
JH
1096 tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, TCG_REG_A0, cmp_off + HI_OFF);
1097
1098 /* Load the tlb addend for the fast path. We can't do it earlier with
1099 64-bit targets or we'll clobber a0 before reading the high half tlb
1100 comparator. */
1101 tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0, add_off);
afa05235 1102
9d8bf2d1 1103 label_ptr[1] = s->code_ptr;
5eb4f645 1104 tcg_out_opc_br(s, OPC_BNE, addrh, TCG_TMP0);
9d8bf2d1 1105 }
afa05235 1106
9d8bf2d1
RH
1107 /* delay slot */
1108 tcg_out_opc_reg(s, OPC_ADDU, base, TCG_REG_A0, addrl);
1109}
afa05235 1110
3972ef6f 1111static void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOpIdx oi,
9d8bf2d1
RH
1112 TCGReg datalo, TCGReg datahi,
1113 TCGReg addrlo, TCGReg addrhi,
3972ef6f 1114 void *raddr, tcg_insn_unit *label_ptr[2])
9d8bf2d1
RH
1115{
1116 TCGLabelQemuLdst *label = new_ldst_label(s);
1117
1118 label->is_ld = is_ld;
3972ef6f 1119 label->oi = oi;
9d8bf2d1
RH
1120 label->datalo_reg = datalo;
1121 label->datahi_reg = datahi;
1122 label->addrlo_reg = addrlo;
1123 label->addrhi_reg = addrhi;
9d8bf2d1
RH
1124 label->raddr = raddr;
1125 label->label_ptr[0] = label_ptr[0];
1126 if (TARGET_LONG_BITS == 64) {
1127 label->label_ptr[1] = label_ptr[1];
1128 }
1129}
1130
1131static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1132{
a8f13961 1133 TCGMemOpIdx oi = l->oi;
3972ef6f 1134 TCGMemOp opc = get_memop(oi);
ce0236cf 1135 TCGReg v0;
9d8bf2d1
RH
1136 int i;
1137
1138 /* resolve label address */
1139 reloc_pc16(l->label_ptr[0], s->code_ptr);
1140 if (TARGET_LONG_BITS == 64) {
1141 reloc_pc16(l->label_ptr[1], s->code_ptr);
1142 }
1143
ce0236cf 1144 i = 1;
9d8bf2d1
RH
1145 if (TARGET_LONG_BITS == 64) {
1146 i = tcg_out_call_iarg_reg2(s, i, l->addrlo_reg, l->addrhi_reg);
1147 } else {
1148 i = tcg_out_call_iarg_reg(s, i, l->addrlo_reg);
1149 }
3972ef6f 1150 i = tcg_out_call_iarg_imm(s, i, oi);
ce0236cf 1151 i = tcg_out_call_iarg_imm(s, i, (intptr_t)l->raddr);
2b7ec66f 1152 tcg_out_call_int(s, qemu_ld_helpers[opc & (MO_BSWAP | MO_SSIZE)], false);
ce0236cf
RH
1153 /* delay slot */
1154 tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
9d8bf2d1 1155
ce0236cf
RH
1156 v0 = l->datalo_reg;
1157 if ((opc & MO_SIZE) == MO_64) {
9d8bf2d1
RH
1158 /* We eliminated V0 from the possible output registers, so it
1159 cannot be clobbered here. So we must move V1 first. */
ce0236cf
RH
1160 if (MIPS_BE) {
1161 tcg_out_mov(s, TCG_TYPE_I32, v0, TCG_REG_V1);
1162 v0 = l->datahi_reg;
1163 } else {
1164 tcg_out_mov(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_V1);
1165 }
afa05235
AJ
1166 }
1167
9d8bf2d1 1168 reloc_pc16(s->code_ptr, l->raddr);
6d8ff4d8 1169 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
ce0236cf
RH
1170 /* delay slot */
1171 tcg_out_mov(s, TCG_TYPE_REG, v0, TCG_REG_V0);
9d8bf2d1 1172}
afa05235 1173
9d8bf2d1
RH
1174static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1175{
a8f13961 1176 TCGMemOpIdx oi = l->oi;
3972ef6f 1177 TCGMemOp opc = get_memop(oi);
9d8bf2d1
RH
1178 TCGMemOp s_bits = opc & MO_SIZE;
1179 int i;
1180
1181 /* resolve label address */
1182 reloc_pc16(l->label_ptr[0], s->code_ptr);
1183 if (TARGET_LONG_BITS == 64) {
1184 reloc_pc16(l->label_ptr[1], s->code_ptr);
1185 }
afa05235 1186
ce0236cf 1187 i = 1;
9d8bf2d1
RH
1188 if (TARGET_LONG_BITS == 64) {
1189 i = tcg_out_call_iarg_reg2(s, i, l->addrlo_reg, l->addrhi_reg);
cc01cc8e 1190 } else {
9d8bf2d1
RH
1191 i = tcg_out_call_iarg_reg(s, i, l->addrlo_reg);
1192 }
1193 switch (s_bits) {
1194 case MO_8:
1195 i = tcg_out_call_iarg_reg8(s, i, l->datalo_reg);
1196 break;
1197 case MO_16:
1198 i = tcg_out_call_iarg_reg16(s, i, l->datalo_reg);
1199 break;
1200 case MO_32:
1201 i = tcg_out_call_iarg_reg(s, i, l->datalo_reg);
1202 break;
1203 case MO_64:
1204 i = tcg_out_call_iarg_reg2(s, i, l->datalo_reg, l->datahi_reg);
1205 break;
1206 default:
1207 tcg_abort();
cc01cc8e 1208 }
3972ef6f 1209 i = tcg_out_call_iarg_imm(s, i, oi);
9d8bf2d1 1210
ce0236cf
RH
1211 /* Tail call to the store helper. Thus force the return address
1212 computation to take place in the return address register. */
1213 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RA, (intptr_t)l->raddr);
1214 i = tcg_out_call_iarg_reg(s, i, TCG_REG_RA);
2b7ec66f 1215 tcg_out_call_int(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)], true);
ce0236cf
RH
1216 /* delay slot */
1217 tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
9d8bf2d1 1218}
afa05235
AJ
1219#endif
1220
bb08afe9 1221static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi,
9d8bf2d1
RH
1222 TCGReg base, TCGMemOp opc)
1223{
4214a8cb 1224 switch (opc & (MO_SSIZE | MO_BSWAP)) {
9d8bf2d1 1225 case MO_UB:
bb08afe9 1226 tcg_out_opc_imm(s, OPC_LBU, lo, base, 0);
afa05235 1227 break;
9d8bf2d1 1228 case MO_SB:
bb08afe9 1229 tcg_out_opc_imm(s, OPC_LB, lo, base, 0);
afa05235 1230 break;
9d8bf2d1 1231 case MO_UW | MO_BSWAP:
6c530e32 1232 tcg_out_opc_imm(s, OPC_LHU, TCG_TMP1, base, 0);
bb08afe9 1233 tcg_out_bswap16(s, lo, TCG_TMP1);
afa05235 1234 break;
9d8bf2d1 1235 case MO_UW:
bb08afe9 1236 tcg_out_opc_imm(s, OPC_LHU, lo, base, 0);
afa05235 1237 break;
9d8bf2d1 1238 case MO_SW | MO_BSWAP:
6c530e32 1239 tcg_out_opc_imm(s, OPC_LHU, TCG_TMP1, base, 0);
bb08afe9 1240 tcg_out_bswap16s(s, lo, TCG_TMP1);
afa05235 1241 break;
9d8bf2d1 1242 case MO_SW:
bb08afe9 1243 tcg_out_opc_imm(s, OPC_LH, lo, base, 0);
9d8bf2d1
RH
1244 break;
1245 case MO_UL | MO_BSWAP:
bb08afe9
JG
1246 if (use_mips32r2_instructions) {
1247 tcg_out_opc_imm(s, OPC_LW, lo, base, 0);
1248 tcg_out_bswap32(s, lo, lo);
1249 } else {
1250 tcg_out_bswap_subr(s, bswap32_addr);
1251 /* delay slot */
1252 tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, base, 0);
1253 tcg_out_mov(s, TCG_TYPE_I32, lo, TCG_TMP3);
1254 }
9d8bf2d1
RH
1255 break;
1256 case MO_UL:
bb08afe9 1257 tcg_out_opc_imm(s, OPC_LW, lo, base, 0);
9d8bf2d1
RH
1258 break;
1259 case MO_Q | MO_BSWAP:
bb08afe9
JG
1260 if (use_mips32r2_instructions) {
1261 tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, base, 0);
1262 tcg_out_opc_imm(s, OPC_LW, TCG_TMP1, base, 4);
1263 tcg_out_opc_reg(s, OPC_WSBH, TCG_TMP0, 0, TCG_TMP0);
1264 tcg_out_opc_reg(s, OPC_WSBH, TCG_TMP1, 0, TCG_TMP1);
1265 tcg_out_opc_sa(s, OPC_ROTR, MIPS_BE ? lo : hi, TCG_TMP0, 16);
1266 tcg_out_opc_sa(s, OPC_ROTR, MIPS_BE ? hi : lo, TCG_TMP1, 16);
1267 } else {
1268 tcg_out_bswap_subr(s, bswap32_addr);
1269 /* delay slot */
1270 tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, base, 0);
1271 tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, base, 4);
1272 tcg_out_bswap_subr(s, bswap32_addr);
1273 /* delay slot */
1274 tcg_out_mov(s, TCG_TYPE_I32, MIPS_BE ? lo : hi, TCG_TMP3);
1275 tcg_out_mov(s, TCG_TYPE_I32, MIPS_BE ? hi : lo, TCG_TMP3);
1276 }
9d8bf2d1
RH
1277 break;
1278 case MO_Q:
bb08afe9
JG
1279 /* Prefer to load from offset 0 first, but allow for overlap. */
1280 if (MIPS_BE ? hi != base : lo == base) {
1281 tcg_out_opc_imm(s, OPC_LW, hi, base, HI_OFF);
1282 tcg_out_opc_imm(s, OPC_LW, lo, base, LO_OFF);
1283 } else {
1284 tcg_out_opc_imm(s, OPC_LW, lo, base, LO_OFF);
1285 tcg_out_opc_imm(s, OPC_LW, hi, base, HI_OFF);
1286 }
afa05235
AJ
1287 break;
1288 default:
1289 tcg_abort();
1290 }
afa05235
AJ
1291}
1292
fbef2cc8 1293static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64)
afa05235 1294{
9d8bf2d1
RH
1295 TCGReg addr_regl, addr_regh __attribute__((unused));
1296 TCGReg data_regl, data_regh;
59227d5d 1297 TCGMemOpIdx oi;
fbef2cc8 1298 TCGMemOp opc;
afa05235 1299#if defined(CONFIG_SOFTMMU)
9d8bf2d1 1300 tcg_insn_unit *label_ptr[2];
afa05235 1301#endif
bb08afe9 1302 TCGReg base = TCG_REG_A0;
9d8bf2d1 1303
afa05235 1304 data_regl = *args++;
fbef2cc8 1305 data_regh = (is_64 ? *args++ : 0);
afa05235 1306 addr_regl = *args++;
9d8bf2d1 1307 addr_regh = (TARGET_LONG_BITS == 64 ? *args++ : 0);
59227d5d
RH
1308 oi = *args++;
1309 opc = get_memop(oi);
9d8bf2d1 1310
0834c9ea 1311#if defined(CONFIG_SOFTMMU)
81dfaf1a 1312 tcg_out_tlb_load(s, base, addr_regl, addr_regh, oi, label_ptr, 1);
9d8bf2d1 1313 tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc);
3972ef6f
RH
1314 add_qemu_ldst_label(s, 1, oi, data_regl, data_regh, addr_regl, addr_regh,
1315 s->code_ptr, label_ptr);
0834c9ea 1316#else
b76f21a7 1317 if (guest_base == 0 && data_regl != addr_regl) {
9d8bf2d1 1318 base = addr_regl;
b76f21a7
LV
1319 } else if (guest_base == (int16_t)guest_base) {
1320 tcg_out_opc_imm(s, OPC_ADDIU, base, addr_regl, guest_base);
0834c9ea 1321 } else {
b76f21a7 1322 tcg_out_movi(s, TCG_TYPE_PTR, base, guest_base);
9d8bf2d1 1323 tcg_out_opc_reg(s, OPC_ADDU, base, base, addr_regl);
0834c9ea 1324 }
9d8bf2d1
RH
1325 tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc);
1326#endif
1327}
afa05235 1328
bb08afe9 1329static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg lo, TCGReg hi,
9d8bf2d1
RH
1330 TCGReg base, TCGMemOp opc)
1331{
bb08afe9
JG
1332 /* Don't clutter the code below with checks to avoid bswapping ZERO. */
1333 if ((lo | hi) == 0) {
1334 opc &= ~MO_BSWAP;
1335 }
1336
4214a8cb 1337 switch (opc & (MO_SIZE | MO_BSWAP)) {
9d8bf2d1 1338 case MO_8:
bb08afe9 1339 tcg_out_opc_imm(s, OPC_SB, lo, base, 0);
9d8bf2d1 1340 break;
afa05235 1341
9d8bf2d1 1342 case MO_16 | MO_BSWAP:
bb08afe9 1343 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, lo, 0xffff);
6c530e32 1344 tcg_out_bswap16(s, TCG_TMP1, TCG_TMP1);
bb08afe9 1345 lo = TCG_TMP1;
9d8bf2d1
RH
1346 /* FALLTHRU */
1347 case MO_16:
bb08afe9 1348 tcg_out_opc_imm(s, OPC_SH, lo, base, 0);
afa05235 1349 break;
9d8bf2d1
RH
1350
1351 case MO_32 | MO_BSWAP:
bb08afe9
JG
1352 tcg_out_bswap32(s, TCG_TMP3, lo);
1353 lo = TCG_TMP3;
9d8bf2d1
RH
1354 /* FALLTHRU */
1355 case MO_32:
bb08afe9 1356 tcg_out_opc_imm(s, OPC_SW, lo, base, 0);
afa05235 1357 break;
9d8bf2d1
RH
1358
1359 case MO_64 | MO_BSWAP:
bb08afe9
JG
1360 if (use_mips32r2_instructions) {
1361 tcg_out_opc_reg(s, OPC_WSBH, TCG_TMP0, 0, MIPS_BE ? lo : hi);
1362 tcg_out_opc_reg(s, OPC_WSBH, TCG_TMP1, 0, MIPS_BE ? hi : lo);
1363 tcg_out_opc_sa(s, OPC_ROTR, TCG_TMP0, TCG_TMP0, 16);
1364 tcg_out_opc_sa(s, OPC_ROTR, TCG_TMP1, TCG_TMP1, 16);
1365 tcg_out_opc_imm(s, OPC_SW, TCG_TMP0, base, 0);
1366 tcg_out_opc_imm(s, OPC_SW, TCG_TMP1, base, 4);
1367 } else {
1368 tcg_out_bswap32(s, TCG_TMP3, MIPS_BE ? lo : hi);
1369 tcg_out_opc_imm(s, OPC_SW, TCG_TMP3, base, 0);
1370 tcg_out_bswap32(s, TCG_TMP3, MIPS_BE ? hi : lo);
1371 tcg_out_opc_imm(s, OPC_SW, TCG_TMP3, base, 4);
1372 }
afa05235 1373 break;
9d8bf2d1 1374 case MO_64:
bb08afe9
JG
1375 tcg_out_opc_imm(s, OPC_SW, MIPS_BE ? hi : lo, base, 0);
1376 tcg_out_opc_imm(s, OPC_SW, MIPS_BE ? lo : hi, base, 4);
afa05235 1377 break;
9d8bf2d1 1378
afa05235
AJ
1379 default:
1380 tcg_abort();
1381 }
9d8bf2d1 1382}
afa05235 1383
fbef2cc8 1384static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64)
9d8bf2d1
RH
1385{
1386 TCGReg addr_regl, addr_regh __attribute__((unused));
bb08afe9 1387 TCGReg data_regl, data_regh;
59227d5d 1388 TCGMemOpIdx oi;
fbef2cc8 1389 TCGMemOp opc;
9d8bf2d1
RH
1390#if defined(CONFIG_SOFTMMU)
1391 tcg_insn_unit *label_ptr[2];
9d8bf2d1 1392#endif
bb08afe9 1393 TCGReg base = TCG_REG_A0;
9d8bf2d1
RH
1394
1395 data_regl = *args++;
fbef2cc8 1396 data_regh = (is_64 ? *args++ : 0);
9d8bf2d1
RH
1397 addr_regl = *args++;
1398 addr_regh = (TARGET_LONG_BITS == 64 ? *args++ : 0);
59227d5d
RH
1399 oi = *args++;
1400 opc = get_memop(oi);
afa05235 1401
9d8bf2d1 1402#if defined(CONFIG_SOFTMMU)
81dfaf1a 1403 tcg_out_tlb_load(s, base, addr_regl, addr_regh, oi, label_ptr, 0);
9d8bf2d1 1404 tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc);
3972ef6f
RH
1405 add_qemu_ldst_label(s, 0, oi, data_regl, data_regh, addr_regl, addr_regh,
1406 s->code_ptr, label_ptr);
cc01cc8e 1407#else
b76f21a7 1408 if (guest_base == 0) {
9d8bf2d1 1409 base = addr_regl;
cc01cc8e 1410 } else {
b76f21a7
LV
1411 if (guest_base == (int16_t)guest_base) {
1412 tcg_out_opc_imm(s, OPC_ADDIU, base, addr_regl, guest_base);
afa05235 1413 } else {
b76f21a7 1414 tcg_out_movi(s, TCG_TYPE_PTR, base, guest_base);
9d8bf2d1 1415 tcg_out_opc_reg(s, OPC_ADDU, base, base, addr_regl);
afa05235 1416 }
afa05235 1417 }
9d8bf2d1 1418 tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc);
afa05235
AJ
1419#endif
1420}
1421
6f0b9910
PK
1422static void tcg_out_mb(TCGContext *s, TCGArg a0)
1423{
1424 static const MIPSInsn sync[] = {
1425 /* Note that SYNC_MB is a slightly weaker than SYNC 0,
1426 as the former is an ordering barrier and the latter
1427 is a completion barrier. */
1428 [0 ... TCG_MO_ALL] = OPC_SYNC_MB,
1429 [TCG_MO_LD_LD] = OPC_SYNC_RMB,
1430 [TCG_MO_ST_ST] = OPC_SYNC_WMB,
1431 [TCG_MO_LD_ST] = OPC_SYNC_RELEASE,
1432 [TCG_MO_LD_ST | TCG_MO_ST_ST] = OPC_SYNC_RELEASE,
1433 [TCG_MO_LD_ST | TCG_MO_LD_LD] = OPC_SYNC_ACQUIRE,
1434 };
1435 tcg_out32(s, sync[a0 & TCG_MO_ALL]);
1436}
1437
a9751609 1438static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
afa05235
AJ
1439 const TCGArg *args, const int *const_args)
1440{
4f048535 1441 MIPSInsn i1, i2;
22ee3a98
RH
1442 TCGArg a0, a1, a2;
1443 int c2;
1444
1445 a0 = args[0];
1446 a1 = args[1];
1447 a2 = args[2];
1448 c2 = const_args[2];
1449
1450 switch (opc) {
afa05235 1451 case INDEX_op_exit_tb:
7dae901d 1452 {
7dae901d
RH
1453 TCGReg b0 = TCG_REG_ZERO;
1454
1455 if (a0 & ~0xffff) {
1456 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, a0 & ~0xffff);
1457 b0 = TCG_REG_V0;
1458 }
1459 if (!tcg_out_opc_jmp(s, OPC_J, tb_ret_addr)) {
6c530e32 1460 tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0,
7dae901d 1461 (uintptr_t)tb_ret_addr);
6c530e32 1462 tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
7dae901d
RH
1463 }
1464 tcg_out_opc_imm(s, OPC_ORI, TCG_REG_V0, b0, a0 & 0xffff);
f8c9eddb 1465 }
afa05235
AJ
1466 break;
1467 case INDEX_op_goto_tb:
f309101c 1468 if (s->tb_jmp_insn_offset) {
afa05235 1469 /* direct jump method */
f309101c 1470 s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s);
b6bfeea9
RH
1471 /* Avoid clobbering the address during retranslation. */
1472 tcg_out32(s, OPC_J | (*(uint32_t *)s->code_ptr & 0x3ffffff));
afa05235
AJ
1473 } else {
1474 /* indirect jump method */
6c530e32 1475 tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_REG_ZERO,
f309101c 1476 (uintptr_t)(s->tb_jmp_target_addr + a0));
6c530e32 1477 tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
afa05235
AJ
1478 }
1479 tcg_out_nop(s);
f309101c 1480 s->tb_jmp_reset_offset[a0] = tcg_current_code_size(s);
afa05235 1481 break;
afa05235 1482 case INDEX_op_br:
bec16311
RH
1483 tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO,
1484 arg_label(a0));
afa05235
AJ
1485 break;
1486
afa05235 1487 case INDEX_op_ld8u_i32:
4f048535
RH
1488 i1 = OPC_LBU;
1489 goto do_ldst;
afa05235 1490 case INDEX_op_ld8s_i32:
4f048535
RH
1491 i1 = OPC_LB;
1492 goto do_ldst;
afa05235 1493 case INDEX_op_ld16u_i32:
4f048535
RH
1494 i1 = OPC_LHU;
1495 goto do_ldst;
afa05235 1496 case INDEX_op_ld16s_i32:
4f048535
RH
1497 i1 = OPC_LH;
1498 goto do_ldst;
afa05235 1499 case INDEX_op_ld_i32:
4f048535
RH
1500 i1 = OPC_LW;
1501 goto do_ldst;
afa05235 1502 case INDEX_op_st8_i32:
4f048535
RH
1503 i1 = OPC_SB;
1504 goto do_ldst;
afa05235 1505 case INDEX_op_st16_i32:
4f048535
RH
1506 i1 = OPC_SH;
1507 goto do_ldst;
afa05235 1508 case INDEX_op_st_i32:
4f048535
RH
1509 i1 = OPC_SW;
1510 do_ldst:
1511 tcg_out_ldst(s, i1, a0, a1, a2);
afa05235
AJ
1512 break;
1513
1514 case INDEX_op_add_i32:
4f048535
RH
1515 i1 = OPC_ADDU, i2 = OPC_ADDIU;
1516 goto do_binary;
1517 case INDEX_op_or_i32:
1518 i1 = OPC_OR, i2 = OPC_ORI;
1519 goto do_binary;
1520 case INDEX_op_xor_i32:
1521 i1 = OPC_XOR, i2 = OPC_XORI;
1522 do_binary:
22ee3a98 1523 if (c2) {
4f048535
RH
1524 tcg_out_opc_imm(s, i2, a0, a1, a2);
1525 break;
afa05235 1526 }
4f048535
RH
1527 do_binaryv:
1528 tcg_out_opc_reg(s, i1, a0, a1, a2);
afa05235 1529 break;
4f048535 1530
afa05235 1531 case INDEX_op_sub_i32:
22ee3a98
RH
1532 if (c2) {
1533 tcg_out_opc_imm(s, OPC_ADDIU, a0, a1, -a2);
4f048535 1534 break;
afa05235 1535 }
4f048535
RH
1536 i1 = OPC_SUBU;
1537 goto do_binary;
1538 case INDEX_op_and_i32:
1539 if (c2 && a2 != (uint16_t)a2) {
1540 int msb = ctz32(~a2) - 1;
eabb7b91
AJ
1541 tcg_debug_assert(use_mips32r2_instructions);
1542 tcg_debug_assert(is_p2m1(a2));
4f048535
RH
1543 tcg_out_opc_bf(s, OPC_EXT, a0, a1, msb, 0);
1544 break;
1545 }
1546 i1 = OPC_AND, i2 = OPC_ANDI;
1547 goto do_binary;
1548 case INDEX_op_nor_i32:
1549 i1 = OPC_NOR;
1550 goto do_binaryv;
1551
afa05235 1552 case INDEX_op_mul_i32:
988902fc 1553 if (use_mips32_instructions) {
22ee3a98 1554 tcg_out_opc_reg(s, OPC_MUL, a0, a1, a2);
4f048535 1555 break;
988902fc 1556 }
4f048535
RH
1557 i1 = OPC_MULT, i2 = OPC_MFLO;
1558 goto do_hilo1;
3c9a8f17 1559 case INDEX_op_mulsh_i32:
bc6d0c22
JH
1560 if (use_mips32r6_instructions) {
1561 tcg_out_opc_reg(s, OPC_MUH, a0, a1, a2);
1562 break;
1563 }
4f048535
RH
1564 i1 = OPC_MULT, i2 = OPC_MFHI;
1565 goto do_hilo1;
3c9a8f17 1566 case INDEX_op_muluh_i32:
bc6d0c22
JH
1567 if (use_mips32r6_instructions) {
1568 tcg_out_opc_reg(s, OPC_MUHU, a0, a1, a2);
1569 break;
1570 }
4f048535
RH
1571 i1 = OPC_MULTU, i2 = OPC_MFHI;
1572 goto do_hilo1;
afa05235 1573 case INDEX_op_div_i32:
bc6d0c22
JH
1574 if (use_mips32r6_instructions) {
1575 tcg_out_opc_reg(s, OPC_DIV_R6, a0, a1, a2);
1576 break;
1577 }
4f048535
RH
1578 i1 = OPC_DIV, i2 = OPC_MFLO;
1579 goto do_hilo1;
afa05235 1580 case INDEX_op_divu_i32:
bc6d0c22
JH
1581 if (use_mips32r6_instructions) {
1582 tcg_out_opc_reg(s, OPC_DIVU_R6, a0, a1, a2);
1583 break;
1584 }
4f048535
RH
1585 i1 = OPC_DIVU, i2 = OPC_MFLO;
1586 goto do_hilo1;
afa05235 1587 case INDEX_op_rem_i32:
bc6d0c22
JH
1588 if (use_mips32r6_instructions) {
1589 tcg_out_opc_reg(s, OPC_MOD, a0, a1, a2);
1590 break;
1591 }
4f048535
RH
1592 i1 = OPC_DIV, i2 = OPC_MFHI;
1593 goto do_hilo1;
afa05235 1594 case INDEX_op_remu_i32:
bc6d0c22
JH
1595 if (use_mips32r6_instructions) {
1596 tcg_out_opc_reg(s, OPC_MODU, a0, a1, a2);
1597 break;
1598 }
4f048535
RH
1599 i1 = OPC_DIVU, i2 = OPC_MFHI;
1600 do_hilo1:
1601 tcg_out_opc_reg(s, i1, 0, a1, a2);
1602 tcg_out_opc_reg(s, i2, a0, 0, 0);
afa05235
AJ
1603 break;
1604
4f048535
RH
1605 case INDEX_op_muls2_i32:
1606 i1 = OPC_MULT;
1607 goto do_hilo2;
1608 case INDEX_op_mulu2_i32:
1609 i1 = OPC_MULTU;
1610 do_hilo2:
1611 tcg_out_opc_reg(s, i1, 0, a2, args[3]);
1612 tcg_out_opc_reg(s, OPC_MFLO, a0, 0, 0);
1613 tcg_out_opc_reg(s, OPC_MFHI, a1, 0, 0);
2b79487a 1614 break;
4f048535 1615
afa05235 1616 case INDEX_op_not_i32:
4f048535
RH
1617 i1 = OPC_NOR;
1618 goto do_unary;
1619 case INDEX_op_bswap16_i32:
1620 i1 = OPC_WSBH;
1621 goto do_unary;
1622 case INDEX_op_ext8s_i32:
1623 i1 = OPC_SEB;
1624 goto do_unary;
1625 case INDEX_op_ext16s_i32:
1626 i1 = OPC_SEH;
1627 do_unary:
1628 tcg_out_opc_reg(s, i1, a0, TCG_REG_ZERO, a1);
afa05235
AJ
1629 break;
1630
1631 case INDEX_op_sar_i32:
4f048535
RH
1632 i1 = OPC_SRAV, i2 = OPC_SRA;
1633 goto do_shift;
afa05235 1634 case INDEX_op_shl_i32:
4f048535
RH
1635 i1 = OPC_SLLV, i2 = OPC_SLL;
1636 goto do_shift;
afa05235 1637 case INDEX_op_shr_i32:
4f048535
RH
1638 i1 = OPC_SRLV, i2 = OPC_SRL;
1639 goto do_shift;
1640 case INDEX_op_rotr_i32:
1641 i1 = OPC_ROTRV, i2 = OPC_ROTR;
1642 do_shift:
22ee3a98 1643 if (c2) {
4f048535 1644 tcg_out_opc_sa(s, i2, a0, a1, a2);
afa05235 1645 } else {
4f048535 1646 tcg_out_opc_reg(s, i1, a0, a2, a1);
afa05235
AJ
1647 }
1648 break;
9a152519 1649 case INDEX_op_rotl_i32:
22ee3a98
RH
1650 if (c2) {
1651 tcg_out_opc_sa(s, OPC_ROTR, a0, a1, 32 - a2);
9a152519 1652 } else {
22ee3a98
RH
1653 tcg_out_opc_reg(s, OPC_SUBU, TCG_TMP0, TCG_REG_ZERO, a2);
1654 tcg_out_opc_reg(s, OPC_ROTRV, a0, TCG_TMP0, a1);
9a152519
AJ
1655 }
1656 break;
afa05235 1657
c1cf85c9 1658 case INDEX_op_bswap32_i32:
bb08afe9 1659 tcg_out_bswap32(s, a0, a1);
c1cf85c9
AJ
1660 break;
1661
04f71aa3 1662 case INDEX_op_deposit_i32:
22ee3a98 1663 tcg_out_opc_bf(s, OPC_INS, a0, a2, args[3] + args[4] - 1, args[3]);
04f71aa3
AJ
1664 break;
1665
afa05235 1666 case INDEX_op_brcond_i32:
bec16311 1667 tcg_out_brcond(s, a2, a0, a1, arg_label(args[3]));
afa05235
AJ
1668 break;
1669 case INDEX_op_brcond2_i32:
bec16311 1670 tcg_out_brcond2(s, args[4], a0, a1, a2, args[3], arg_label(args[5]));
afa05235
AJ
1671 break;
1672
7d7c4930 1673 case INDEX_op_movcond_i32:
137d6390 1674 tcg_out_movcond(s, args[5], a0, a1, a2, args[3], args[4]);
7d7c4930
AJ
1675 break;
1676
4cb26382 1677 case INDEX_op_setcond_i32:
22ee3a98 1678 tcg_out_setcond(s, args[3], a0, a1, a2);
4cb26382 1679 break;
434254aa 1680 case INDEX_op_setcond2_i32:
22ee3a98 1681 tcg_out_setcond2(s, args[5], a0, a1, a2, args[3], args[4]);
434254aa 1682 break;
4cb26382 1683
fbef2cc8
RH
1684 case INDEX_op_qemu_ld_i32:
1685 tcg_out_qemu_ld(s, args, false);
afa05235 1686 break;
fbef2cc8
RH
1687 case INDEX_op_qemu_ld_i64:
1688 tcg_out_qemu_ld(s, args, true);
afa05235 1689 break;
fbef2cc8
RH
1690 case INDEX_op_qemu_st_i32:
1691 tcg_out_qemu_st(s, args, false);
afa05235 1692 break;
fbef2cc8
RH
1693 case INDEX_op_qemu_st_i64:
1694 tcg_out_qemu_st(s, args, true);
afa05235
AJ
1695 break;
1696
741f117d
RH
1697 case INDEX_op_add2_i32:
1698 tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
1699 const_args[4], const_args[5], false);
1700 break;
1701 case INDEX_op_sub2_i32:
1702 tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
1703 const_args[4], const_args[5], true);
1704 break;
1705
6f0b9910
PK
1706 case INDEX_op_mb:
1707 tcg_out_mb(s, a0);
1708 break;
96d0ee7f
RH
1709 case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
1710 case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi. */
1711 case INDEX_op_call: /* Always emitted via tcg_out_call. */
afa05235
AJ
1712 default:
1713 tcg_abort();
1714 }
1715}
1716
1717static const TCGTargetOpDef mips_op_defs[] = {
1718 { INDEX_op_exit_tb, { } },
1719 { INDEX_op_goto_tb, { } },
afa05235
AJ
1720 { INDEX_op_br, { } },
1721
afa05235
AJ
1722 { INDEX_op_ld8u_i32, { "r", "r" } },
1723 { INDEX_op_ld8s_i32, { "r", "r" } },
1724 { INDEX_op_ld16u_i32, { "r", "r" } },
1725 { INDEX_op_ld16s_i32, { "r", "r" } },
1726 { INDEX_op_ld_i32, { "r", "r" } },
1727 { INDEX_op_st8_i32, { "rZ", "r" } },
1728 { INDEX_op_st16_i32, { "rZ", "r" } },
1729 { INDEX_op_st_i32, { "rZ", "r" } },
1730
2ceb3a9e 1731 { INDEX_op_add_i32, { "r", "rZ", "rJ" } },
afa05235 1732 { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
bc6d0c22 1733#if !use_mips32r6_instructions
174d4d21 1734 { INDEX_op_muls2_i32, { "r", "r", "rZ", "rZ" } },
afa05235 1735 { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
bc6d0c22 1736#endif
3c9a8f17
RH
1737 { INDEX_op_mulsh_i32, { "r", "rZ", "rZ" } },
1738 { INDEX_op_muluh_i32, { "r", "rZ", "rZ" } },
afa05235
AJ
1739 { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
1740 { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
1741 { INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
1742 { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
070603f6 1743 { INDEX_op_sub_i32, { "r", "rZ", "rN" } },
afa05235 1744
1c418268 1745 { INDEX_op_and_i32, { "r", "rZ", "rIK" } },
2b79487a 1746 { INDEX_op_nor_i32, { "r", "rZ", "rZ" } },
afa05235
AJ
1747 { INDEX_op_not_i32, { "r", "rZ" } },
1748 { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
1749 { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
1750
2ceb3a9e
AJ
1751 { INDEX_op_shl_i32, { "r", "rZ", "ri" } },
1752 { INDEX_op_shr_i32, { "r", "rZ", "ri" } },
1753 { INDEX_op_sar_i32, { "r", "rZ", "ri" } },
9a152519
AJ
1754 { INDEX_op_rotr_i32, { "r", "rZ", "ri" } },
1755 { INDEX_op_rotl_i32, { "r", "rZ", "ri" } },
afa05235 1756
c1cf85c9
AJ
1757 { INDEX_op_bswap16_i32, { "r", "r" } },
1758 { INDEX_op_bswap32_i32, { "r", "r" } },
1759
116348de
AJ
1760 { INDEX_op_ext8s_i32, { "r", "rZ" } },
1761 { INDEX_op_ext16s_i32, { "r", "rZ" } },
1762
04f71aa3
AJ
1763 { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
1764
afa05235 1765 { INDEX_op_brcond_i32, { "rZ", "rZ" } },
137d6390
JH
1766#if use_mips32r6_instructions
1767 { INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
1768#else
7d7c4930 1769 { INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rZ", "0" } },
137d6390 1770#endif
4cb26382 1771 { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
434254aa 1772 { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
afa05235 1773
741f117d 1774 { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rN", "rN" } },
070603f6 1775 { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rN", "rN" } },
afa05235
AJ
1776 { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
1777
1778#if TARGET_LONG_BITS == 32
bb08afe9 1779 { INDEX_op_qemu_ld_i32, { "r", "LZ" } },
fbef2cc8 1780 { INDEX_op_qemu_st_i32, { "SZ", "SZ" } },
bb08afe9 1781 { INDEX_op_qemu_ld_i64, { "r", "r", "LZ" } },
fbef2cc8 1782 { INDEX_op_qemu_st_i64, { "SZ", "SZ", "SZ" } },
afa05235 1783#else
bb08afe9 1784 { INDEX_op_qemu_ld_i32, { "r", "LZ", "LZ" } },
fbef2cc8 1785 { INDEX_op_qemu_st_i32, { "SZ", "SZ", "SZ" } },
bb08afe9 1786 { INDEX_op_qemu_ld_i64, { "r", "r", "LZ", "LZ" } },
fbef2cc8 1787 { INDEX_op_qemu_st_i64, { "SZ", "SZ", "SZ", "SZ" } },
afa05235 1788#endif
6f0b9910
PK
1789
1790 { INDEX_op_mb, { } },
afa05235
AJ
1791 { -1 },
1792};
1793
1794static int tcg_target_callee_save_regs[] = {
cea5f9a2 1795 TCG_REG_S0, /* used for the global env (TCG_AREG0) */
afa05235
AJ
1796 TCG_REG_S1,
1797 TCG_REG_S2,
1798 TCG_REG_S3,
1799 TCG_REG_S4,
1800 TCG_REG_S5,
1801 TCG_REG_S6,
1802 TCG_REG_S7,
41883904 1803 TCG_REG_S8,
afa05235
AJ
1804 TCG_REG_RA, /* should be last for ABI compliance */
1805};
1806
988902fc
AJ
1807/* The Linux kernel doesn't provide any information about the available
1808 instruction set. Probe it using a signal handler. */
1809
988902fc
AJ
1810
1811#ifndef use_movnz_instructions
1812bool use_movnz_instructions = false;
1813#endif
1814
1815#ifndef use_mips32_instructions
1816bool use_mips32_instructions = false;
1817#endif
1818
1819#ifndef use_mips32r2_instructions
1820bool use_mips32r2_instructions = false;
1821#endif
1822
1823static volatile sig_atomic_t got_sigill;
1824
1825static void sigill_handler(int signo, siginfo_t *si, void *data)
1826{
1827 /* Skip the faulty instruction */
1828 ucontext_t *uc = (ucontext_t *)data;
1829 uc->uc_mcontext.pc += 4;
1830
1831 got_sigill = 1;
1832}
1833
1834static void tcg_target_detect_isa(void)
1835{
1836 struct sigaction sa_old, sa_new;
1837
1838 memset(&sa_new, 0, sizeof(sa_new));
1839 sa_new.sa_flags = SA_SIGINFO;
1840 sa_new.sa_sigaction = sigill_handler;
1841 sigaction(SIGILL, &sa_new, &sa_old);
1842
1843 /* Probe for movn/movz, necessary to implement movcond. */
1844#ifndef use_movnz_instructions
1845 got_sigill = 0;
1846 asm volatile(".set push\n"
1847 ".set mips32\n"
1848 "movn $zero, $zero, $zero\n"
1849 "movz $zero, $zero, $zero\n"
1850 ".set pop\n"
1851 : : : );
1852 use_movnz_instructions = !got_sigill;
1853#endif
1854
1855 /* Probe for MIPS32 instructions. As no subsetting is allowed
1856 by the specification, it is only necessary to probe for one
1857 of the instructions. */
1858#ifndef use_mips32_instructions
1859 got_sigill = 0;
1860 asm volatile(".set push\n"
1861 ".set mips32\n"
1862 "mul $zero, $zero\n"
1863 ".set pop\n"
1864 : : : );
1865 use_mips32_instructions = !got_sigill;
1866#endif
1867
1868 /* Probe for MIPS32r2 instructions if MIPS32 instructions are
1869 available. As no subsetting is allowed by the specification,
1870 it is only necessary to probe for one of the instructions. */
1871#ifndef use_mips32r2_instructions
1872 if (use_mips32_instructions) {
1873 got_sigill = 0;
1874 asm volatile(".set push\n"
1875 ".set mips32r2\n"
1876 "seb $zero, $zero\n"
1877 ".set pop\n"
1878 : : : );
1879 use_mips32r2_instructions = !got_sigill;
1880 }
1881#endif
1882
1883 sigaction(SIGILL, &sa_old, NULL);
1884}
1885
bb08afe9
JG
1886static tcg_insn_unit *align_code_ptr(TCGContext *s)
1887{
1888 uintptr_t p = (uintptr_t)s->code_ptr;
1889 if (p & 15) {
1890 p = (p + 15) & -16;
1891 s->code_ptr = (void *)p;
1892 }
1893 return s->code_ptr;
1894}
1895
afa05235 1896/* Generate global QEMU prologue and epilogue code */
e4d58b41 1897static void tcg_target_qemu_prologue(TCGContext *s)
afa05235
AJ
1898{
1899 int i, frame_size;
1900
0d0b53a6 1901 /* reserve some stack space, also for TCG temps. */
afa05235 1902 frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
0d0b53a6
AJ
1903 + TCG_STATIC_CALL_ARGS_SIZE
1904 + CPU_TEMP_BUF_NLONGS * sizeof(long);
afa05235
AJ
1905 frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1906 ~(TCG_TARGET_STACK_ALIGN - 1);
e809c0dc
AJ
1907 tcg_set_frame(s, TCG_REG_SP, ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1908 + TCG_STATIC_CALL_ARGS_SIZE,
0d0b53a6 1909 CPU_TEMP_BUF_NLONGS * sizeof(long));
afa05235
AJ
1910
1911 /* TB prologue */
1912 tcg_out_addi(s, TCG_REG_SP, -frame_size);
1913 for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1914 tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1915 TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1916 }
1917
1918 /* Call generated code */
ea15fb06 1919 tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1], 0);
cea5f9a2 1920 tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
afa05235
AJ
1921 tb_ret_addr = s->code_ptr;
1922
1923 /* TB epilogue */
1924 for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1925 tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1926 TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1927 }
1928
1929 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
bb08afe9 1930 /* delay slot */
afa05235 1931 tcg_out_addi(s, TCG_REG_SP, frame_size);
bb08afe9
JG
1932
1933 if (use_mips32r2_instructions) {
1934 return;
1935 }
1936
1937 /* Bswap subroutine: Input in TCG_TMP0, output in TCG_TMP3;
1938 clobbers TCG_TMP1, TCG_TMP2. */
1939
1940 /*
1941 * bswap32 -- 32-bit swap (signed result for mips64). a0 = abcd.
1942 */
1943 bswap32_addr = align_code_ptr(s);
1944 /* t3 = (ssss)d000 */
1945 tcg_out_opc_sa(s, OPC_SLL, TCG_TMP3, TCG_TMP0, 24);
1946 /* t1 = 000a */
1947 tcg_out_opc_sa(s, OPC_SRL, TCG_TMP1, TCG_TMP0, 24);
1948 /* t2 = 00c0 */
1949 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP0, 0xff00);
1950 /* t3 = d00a */
1951 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
1952 /* t1 = 0abc */
1953 tcg_out_opc_sa(s, OPC_SRL, TCG_TMP1, TCG_TMP0, 8);
1954 /* t2 = 0c00 */
1955 tcg_out_opc_sa(s, OPC_SLL, TCG_TMP2, TCG_TMP2, 8);
1956 /* t1 = 00b0 */
1957 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
1958 /* t3 = dc0a */
1959 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
1960 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
1961 /* t3 = dcba -- delay slot */
1962 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
afa05235
AJ
1963}
1964
e4d58b41 1965static void tcg_target_init(TCGContext *s)
afa05235 1966{
988902fc 1967 tcg_target_detect_isa();
afa05235
AJ
1968 tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
1969 tcg_regset_set(tcg_target_call_clobber_regs,
1970 (1 << TCG_REG_V0) |
1971 (1 << TCG_REG_V1) |
1972 (1 << TCG_REG_A0) |
1973 (1 << TCG_REG_A1) |
1974 (1 << TCG_REG_A2) |
1975 (1 << TCG_REG_A3) |
41883904 1976 (1 << TCG_REG_T0) |
afa05235
AJ
1977 (1 << TCG_REG_T1) |
1978 (1 << TCG_REG_T2) |
1979 (1 << TCG_REG_T3) |
1980 (1 << TCG_REG_T4) |
1981 (1 << TCG_REG_T5) |
1982 (1 << TCG_REG_T6) |
1983 (1 << TCG_REG_T7) |
1984 (1 << TCG_REG_T8) |
1985 (1 << TCG_REG_T9));
1986
1987 tcg_regset_clear(s->reserved_regs);
1988 tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
1989 tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0); /* kernel use only */
1990 tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1); /* kernel use only */
6c530e32
RH
1991 tcg_regset_set_reg(s->reserved_regs, TCG_TMP0); /* internal use */
1992 tcg_regset_set_reg(s->reserved_regs, TCG_TMP1); /* internal use */
bb08afe9
JG
1993 tcg_regset_set_reg(s->reserved_regs, TCG_TMP2); /* internal use */
1994 tcg_regset_set_reg(s->reserved_regs, TCG_TMP3); /* internal use */
afa05235
AJ
1995 tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return address */
1996 tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */
3314e008 1997 tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP); /* global pointer */
afa05235
AJ
1998
1999 tcg_add_target_add_op_defs(mips_op_defs);
2000}
b6bfeea9
RH
2001
2002void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
2003{
c82460a5 2004 atomic_set((uint32_t *)jmp_addr, deposit32(OPC_J, 0, 26, addr >> 2));
b6bfeea9
RH
2005 flush_icache_range(jmp_addr, jmp_addr + 4);
2006}