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