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