]> git.ipfire.org Git - thirdparty/qemu.git/blame - tcg/mips/tcg-target.c
tcg-mips: Fix subtract immediate range
[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
5a0eed37
AJ
570static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGArg arg1,
571 TCGArg arg2, int label_index)
afa05235
AJ
572{
573 TCGLabel *l = &s->labels[label_index];
574
575 switch (cond) {
576 case TCG_COND_EQ:
6d8ff4d8 577 tcg_out_opc_br(s, OPC_BEQ, arg1, arg2);
afa05235
AJ
578 break;
579 case TCG_COND_NE:
6d8ff4d8 580 tcg_out_opc_br(s, OPC_BNE, arg1, arg2);
afa05235
AJ
581 break;
582 case TCG_COND_LT:
0f46c064
AJ
583 if (arg2 == 0) {
584 tcg_out_opc_br(s, OPC_BLTZ, 0, arg1);
585 } else {
6c530e32
RH
586 tcg_out_opc_reg(s, OPC_SLT, TCG_TMP0, arg1, arg2);
587 tcg_out_opc_br(s, OPC_BNE, TCG_TMP0, TCG_REG_ZERO);
0f46c064 588 }
afa05235
AJ
589 break;
590 case TCG_COND_LTU:
6c530e32
RH
591 tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, arg1, arg2);
592 tcg_out_opc_br(s, OPC_BNE, TCG_TMP0, TCG_REG_ZERO);
afa05235
AJ
593 break;
594 case TCG_COND_GE:
0f46c064
AJ
595 if (arg2 == 0) {
596 tcg_out_opc_br(s, OPC_BGEZ, 0, arg1);
597 } else {
6c530e32
RH
598 tcg_out_opc_reg(s, OPC_SLT, TCG_TMP0, arg1, arg2);
599 tcg_out_opc_br(s, OPC_BEQ, TCG_TMP0, TCG_REG_ZERO);
0f46c064 600 }
afa05235
AJ
601 break;
602 case TCG_COND_GEU:
6c530e32
RH
603 tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, arg1, arg2);
604 tcg_out_opc_br(s, OPC_BEQ, TCG_TMP0, TCG_REG_ZERO);
afa05235
AJ
605 break;
606 case TCG_COND_LE:
0f46c064
AJ
607 if (arg2 == 0) {
608 tcg_out_opc_br(s, OPC_BLEZ, 0, arg1);
609 } else {
6c530e32
RH
610 tcg_out_opc_reg(s, OPC_SLT, TCG_TMP0, arg2, arg1);
611 tcg_out_opc_br(s, OPC_BEQ, TCG_TMP0, TCG_REG_ZERO);
0f46c064 612 }
afa05235
AJ
613 break;
614 case TCG_COND_LEU:
6c530e32
RH
615 tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, arg2, arg1);
616 tcg_out_opc_br(s, OPC_BEQ, TCG_TMP0, TCG_REG_ZERO);
afa05235
AJ
617 break;
618 case TCG_COND_GT:
0f46c064
AJ
619 if (arg2 == 0) {
620 tcg_out_opc_br(s, OPC_BGTZ, 0, arg1);
621 } else {
6c530e32
RH
622 tcg_out_opc_reg(s, OPC_SLT, TCG_TMP0, arg2, arg1);
623 tcg_out_opc_br(s, OPC_BNE, TCG_TMP0, TCG_REG_ZERO);
0f46c064 624 }
afa05235
AJ
625 break;
626 case TCG_COND_GTU:
6c530e32
RH
627 tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, arg2, arg1);
628 tcg_out_opc_br(s, OPC_BNE, TCG_TMP0, TCG_REG_ZERO);
afa05235
AJ
629 break;
630 default:
631 tcg_abort();
632 break;
633 }
634 if (l->has_value) {
ae0218e3 635 reloc_pc16(s->code_ptr - 1, l->u.value_ptr);
afa05235 636 } else {
ae0218e3 637 tcg_out_reloc(s, s->code_ptr - 1, R_MIPS_PC16, label_index, 0);
afa05235
AJ
638 }
639 tcg_out_nop(s);
640}
641
642/* XXX: we implement it at the target level to avoid having to
643 handle cross basic blocks temporaries */
5a0eed37
AJ
644static void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGArg arg1,
645 TCGArg arg2, TCGArg arg3, TCGArg arg4,
646 int label_index)
afa05235 647{
ae0218e3 648 tcg_insn_unit *label_ptr;
afa05235
AJ
649
650 switch(cond) {
651 case TCG_COND_NE:
652 tcg_out_brcond(s, TCG_COND_NE, arg2, arg4, label_index);
653 tcg_out_brcond(s, TCG_COND_NE, arg1, arg3, label_index);
654 return;
655 case TCG_COND_EQ:
656 break;
657 case TCG_COND_LT:
658 case TCG_COND_LE:
659 tcg_out_brcond(s, TCG_COND_LT, arg2, arg4, label_index);
660 break;
661 case TCG_COND_GT:
662 case TCG_COND_GE:
663 tcg_out_brcond(s, TCG_COND_GT, arg2, arg4, label_index);
664 break;
665 case TCG_COND_LTU:
666 case TCG_COND_LEU:
667 tcg_out_brcond(s, TCG_COND_LTU, arg2, arg4, label_index);
668 break;
669 case TCG_COND_GTU:
670 case TCG_COND_GEU:
671 tcg_out_brcond(s, TCG_COND_GTU, arg2, arg4, label_index);
672 break;
673 default:
674 tcg_abort();
675 }
676
677 label_ptr = s->code_ptr;
6d8ff4d8 678 tcg_out_opc_br(s, OPC_BNE, arg2, arg4);
afa05235
AJ
679 tcg_out_nop(s);
680
681 switch(cond) {
682 case TCG_COND_EQ:
683 tcg_out_brcond(s, TCG_COND_EQ, arg1, arg3, label_index);
684 break;
685 case TCG_COND_LT:
686 case TCG_COND_LTU:
687 tcg_out_brcond(s, TCG_COND_LTU, arg1, arg3, label_index);
688 break;
689 case TCG_COND_LE:
690 case TCG_COND_LEU:
691 tcg_out_brcond(s, TCG_COND_LEU, arg1, arg3, label_index);
692 break;
693 case TCG_COND_GT:
694 case TCG_COND_GTU:
695 tcg_out_brcond(s, TCG_COND_GTU, arg1, arg3, label_index);
696 break;
697 case TCG_COND_GE:
698 case TCG_COND_GEU:
699 tcg_out_brcond(s, TCG_COND_GEU, arg1, arg3, label_index);
700 break;
701 default:
702 tcg_abort();
703 }
704
ae0218e3 705 reloc_pc16(label_ptr, s->code_ptr);
afa05235
AJ
706}
707
7d7c4930
AJ
708static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
709 TCGArg c1, TCGArg c2, TCGArg v)
710{
711 switch (cond) {
712 case TCG_COND_EQ:
713 if (c1 == 0) {
714 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, c2);
715 } else if (c2 == 0) {
716 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, c1);
717 } else {
6c530e32
RH
718 tcg_out_opc_reg(s, OPC_XOR, TCG_TMP0, c1, c2);
719 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_TMP0);
7d7c4930
AJ
720 }
721 break;
722 case TCG_COND_NE:
723 if (c1 == 0) {
724 tcg_out_opc_reg(s, OPC_MOVN, ret, v, c2);
725 } else if (c2 == 0) {
726 tcg_out_opc_reg(s, OPC_MOVN, ret, v, c1);
727 } else {
6c530e32
RH
728 tcg_out_opc_reg(s, OPC_XOR, TCG_TMP0, c1, c2);
729 tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_TMP0);
7d7c4930
AJ
730 }
731 break;
732 case TCG_COND_LT:
6c530e32
RH
733 tcg_out_opc_reg(s, OPC_SLT, TCG_TMP0, c1, c2);
734 tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_TMP0);
7d7c4930
AJ
735 break;
736 case TCG_COND_LTU:
6c530e32
RH
737 tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, c1, c2);
738 tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_TMP0);
7d7c4930
AJ
739 break;
740 case TCG_COND_GE:
6c530e32
RH
741 tcg_out_opc_reg(s, OPC_SLT, TCG_TMP0, c1, c2);
742 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_TMP0);
7d7c4930
AJ
743 break;
744 case TCG_COND_GEU:
6c530e32
RH
745 tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, c1, c2);
746 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_TMP0);
7d7c4930
AJ
747 break;
748 case TCG_COND_LE:
6c530e32
RH
749 tcg_out_opc_reg(s, OPC_SLT, TCG_TMP0, c2, c1);
750 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_TMP0);
7d7c4930
AJ
751 break;
752 case TCG_COND_LEU:
6c530e32
RH
753 tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, c2, c1);
754 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_TMP0);
7d7c4930
AJ
755 break;
756 case TCG_COND_GT:
6c530e32
RH
757 tcg_out_opc_reg(s, OPC_SLT, TCG_TMP0, c2, c1);
758 tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_TMP0);
7d7c4930
AJ
759 break;
760 case TCG_COND_GTU:
6c530e32
RH
761 tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, c2, c1);
762 tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_TMP0);
7d7c4930
AJ
763 break;
764 default:
765 tcg_abort();
766 break;
767 }
768}
769
5a0eed37
AJ
770static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
771 TCGArg arg1, TCGArg arg2)
4cb26382
AJ
772{
773 switch (cond) {
774 case TCG_COND_EQ:
775 if (arg1 == 0) {
776 tcg_out_opc_imm(s, OPC_SLTIU, ret, arg2, 1);
777 } else if (arg2 == 0) {
778 tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, 1);
779 } else {
434254aa
AJ
780 tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
781 tcg_out_opc_imm(s, OPC_SLTIU, ret, ret, 1);
4cb26382
AJ
782 }
783 break;
784 case TCG_COND_NE:
785 if (arg1 == 0) {
786 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg2);
787 } else if (arg2 == 0) {
788 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg1);
789 } else {
434254aa
AJ
790 tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
791 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, ret);
4cb26382
AJ
792 }
793 break;
794 case TCG_COND_LT:
795 tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
796 break;
797 case TCG_COND_LTU:
798 tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
799 break;
800 case TCG_COND_GE:
434254aa
AJ
801 tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
802 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
4cb26382
AJ
803 break;
804 case TCG_COND_GEU:
434254aa
AJ
805 tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
806 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
4cb26382
AJ
807 break;
808 case TCG_COND_LE:
434254aa
AJ
809 tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
810 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
4cb26382
AJ
811 break;
812 case TCG_COND_LEU:
434254aa
AJ
813 tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
814 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
4cb26382
AJ
815 break;
816 case TCG_COND_GT:
817 tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
818 break;
819 case TCG_COND_GTU:
820 tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
821 break;
822 default:
823 tcg_abort();
824 break;
825 }
826}
827
434254aa
AJ
828/* XXX: we implement it at the target level to avoid having to
829 handle cross basic blocks temporaries */
5a0eed37
AJ
830static void tcg_out_setcond2(TCGContext *s, TCGCond cond, TCGReg ret,
831 TCGArg arg1, TCGArg arg2, TCGArg arg3, TCGArg arg4)
434254aa
AJ
832{
833 switch (cond) {
834 case TCG_COND_EQ:
6c530e32
RH
835 tcg_out_setcond(s, TCG_COND_EQ, TCG_TMP0, arg2, arg4);
836 tcg_out_setcond(s, TCG_COND_EQ, TCG_TMP1, arg1, arg3);
837 tcg_out_opc_reg(s, OPC_AND, ret, TCG_TMP0, TCG_TMP1);
434254aa
AJ
838 return;
839 case TCG_COND_NE:
6c530e32
RH
840 tcg_out_setcond(s, TCG_COND_NE, TCG_TMP0, arg2, arg4);
841 tcg_out_setcond(s, TCG_COND_NE, TCG_TMP1, arg1, arg3);
842 tcg_out_opc_reg(s, OPC_OR, ret, TCG_TMP0, TCG_TMP1);
434254aa
AJ
843 return;
844 case TCG_COND_LT:
845 case TCG_COND_LE:
6c530e32 846 tcg_out_setcond(s, TCG_COND_LT, TCG_TMP0, arg2, arg4);
434254aa
AJ
847 break;
848 case TCG_COND_GT:
849 case TCG_COND_GE:
6c530e32 850 tcg_out_setcond(s, TCG_COND_GT, TCG_TMP0, arg2, arg4);
434254aa
AJ
851 break;
852 case TCG_COND_LTU:
853 case TCG_COND_LEU:
6c530e32 854 tcg_out_setcond(s, TCG_COND_LTU, TCG_TMP0, arg2, arg4);
434254aa
AJ
855 break;
856 case TCG_COND_GTU:
857 case TCG_COND_GEU:
6c530e32 858 tcg_out_setcond(s, TCG_COND_GTU, TCG_TMP0, arg2, arg4);
434254aa
AJ
859 break;
860 default:
861 tcg_abort();
862 break;
863 }
864
6c530e32 865 tcg_out_setcond(s, TCG_COND_EQ, TCG_TMP1, arg2, arg4);
434254aa
AJ
866
867 switch(cond) {
868 case TCG_COND_LT:
869 case TCG_COND_LTU:
870 tcg_out_setcond(s, TCG_COND_LTU, ret, arg1, arg3);
871 break;
872 case TCG_COND_LE:
873 case TCG_COND_LEU:
874 tcg_out_setcond(s, TCG_COND_LEU, ret, arg1, arg3);
875 break;
876 case TCG_COND_GT:
877 case TCG_COND_GTU:
878 tcg_out_setcond(s, TCG_COND_GTU, ret, arg1, arg3);
879 break;
880 case TCG_COND_GE:
881 case TCG_COND_GEU:
882 tcg_out_setcond(s, TCG_COND_GEU, ret, arg1, arg3);
883 break;
884 default:
885 tcg_abort();
886 }
887
6c530e32
RH
888 tcg_out_opc_reg(s, OPC_AND, ret, ret, TCG_TMP1);
889 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
434254aa
AJ
890}
891
ce0236cf 892static void tcg_out_call_int(TCGContext *s, tcg_insn_unit *arg, bool tail)
9d8bf2d1
RH
893{
894 /* Note that the ABI requires the called function's address to be
895 loaded into T9, even if a direct branch is in range. */
896 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T9, (uintptr_t)arg);
897
898 /* But do try a direct branch, allowing the cpu better insn prefetch. */
ce0236cf
RH
899 if (tail) {
900 if (!tcg_out_opc_jmp(s, OPC_J, arg)) {
901 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_T9, 0);
902 }
903 } else {
904 if (!tcg_out_opc_jmp(s, OPC_JAL, arg)) {
905 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
906 }
9d8bf2d1 907 }
ce0236cf 908}
9d8bf2d1 909
ce0236cf
RH
910static void tcg_out_call(TCGContext *s, tcg_insn_unit *arg)
911{
912 tcg_out_call_int(s, arg, false);
9d8bf2d1
RH
913 tcg_out_nop(s);
914}
915
afa05235 916#if defined(CONFIG_SOFTMMU)
ce0236cf
RH
917static void * const qemu_ld_helpers[16] = {
918 [MO_UB] = helper_ret_ldub_mmu,
919 [MO_SB] = helper_ret_ldsb_mmu,
920 [MO_LEUW] = helper_le_lduw_mmu,
921 [MO_LESW] = helper_le_ldsw_mmu,
922 [MO_LEUL] = helper_le_ldul_mmu,
923 [MO_LEQ] = helper_le_ldq_mmu,
924 [MO_BEUW] = helper_be_lduw_mmu,
925 [MO_BESW] = helper_be_ldsw_mmu,
926 [MO_BEUL] = helper_be_ldul_mmu,
927 [MO_BEQ] = helper_be_ldq_mmu,
e141ab52
BS
928};
929
ce0236cf
RH
930static void * const qemu_st_helpers[16] = {
931 [MO_UB] = helper_ret_stb_mmu,
932 [MO_LEUW] = helper_le_stw_mmu,
933 [MO_LEUL] = helper_le_stl_mmu,
934 [MO_LEQ] = helper_le_stq_mmu,
935 [MO_BEUW] = helper_be_stw_mmu,
936 [MO_BEUL] = helper_be_stl_mmu,
937 [MO_BEQ] = helper_be_stq_mmu,
e141ab52 938};
afa05235 939
9d8bf2d1
RH
940/* Helper routines for marshalling helper function arguments into
941 * the correct registers and stack.
942 * I is where we want to put this argument, and is updated and returned
943 * for the next call. ARG is the argument itself.
944 *
945 * We provide routines for arguments which are: immediate, 32 bit
946 * value in register, 16 and 8 bit values in register (which must be zero
947 * extended before use) and 64 bit value in a lo:hi register pair.
948 */
949
950static int tcg_out_call_iarg_reg(TCGContext *s, int i, TCGReg arg)
afa05235 951{
9d8bf2d1
RH
952 if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
953 tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[i], arg);
954 } else {
955 tcg_out_st(s, TCG_TYPE_REG, arg, TCG_REG_SP, 4 * i);
956 }
957 return i + 1;
958}
afa05235 959
9d8bf2d1
RH
960static int tcg_out_call_iarg_reg8(TCGContext *s, int i, TCGReg arg)
961{
6c530e32 962 TCGReg tmp = TCG_TMP0;
9d8bf2d1
RH
963 if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
964 tmp = tcg_target_call_iarg_regs[i];
965 }
966 tcg_out_opc_imm(s, OPC_ANDI, tmp, arg, 0xff);
967 return tcg_out_call_iarg_reg(s, i, tmp);
968}
969
970static int tcg_out_call_iarg_reg16(TCGContext *s, int i, TCGReg arg)
971{
6c530e32 972 TCGReg tmp = TCG_TMP0;
9d8bf2d1
RH
973 if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
974 tmp = tcg_target_call_iarg_regs[i];
975 }
976 tcg_out_opc_imm(s, OPC_ANDI, tmp, arg, 0xffff);
977 return tcg_out_call_iarg_reg(s, i, tmp);
978}
979
980static int tcg_out_call_iarg_imm(TCGContext *s, int i, TCGArg arg)
981{
6c530e32 982 TCGReg tmp = TCG_TMP0;
9d8bf2d1
RH
983 if (arg == 0) {
984 tmp = TCG_REG_ZERO;
afa05235 985 } else {
9d8bf2d1
RH
986 if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
987 tmp = tcg_target_call_iarg_regs[i];
988 }
989 tcg_out_movi(s, TCG_TYPE_REG, tmp, arg);
afa05235 990 }
9d8bf2d1
RH
991 return tcg_out_call_iarg_reg(s, i, tmp);
992}
993
994static int tcg_out_call_iarg_reg2(TCGContext *s, int i, TCGReg al, TCGReg ah)
995{
996 i = (i + 1) & ~1;
997 i = tcg_out_call_iarg_reg(s, i, (MIPS_BE ? ah : al));
998 i = tcg_out_call_iarg_reg(s, i, (MIPS_BE ? al : ah));
999 return i;
1000}
1001
1002/* Perform the tlb comparison operation. The complete host address is
1003 placed in BASE. Clobbers AT, T0, A0. */
1004static void tcg_out_tlb_load(TCGContext *s, TCGReg base, TCGReg addrl,
1005 TCGReg addrh, int mem_index, TCGMemOp s_bits,
1006 tcg_insn_unit *label_ptr[2], bool is_load)
1007{
1008 int cmp_off
1009 = (is_load
1010 ? offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)
1011 : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write));
1012 int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend);
1013
1014 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addrl,
1015 TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
1016 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0,
1017 (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
afa05235 1018 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
afa05235 1019
9d8bf2d1
RH
1020 /* Compensate for very large offsets. */
1021 if (add_off >= 0x8000) {
1022 /* Most target env are smaller than 32k; none are larger than 64k.
1023 Simplify the logic here merely to offset by 0x7ff0, giving us a
1024 range just shy of 64k. Check this assumption. */
1025 QEMU_BUILD_BUG_ON(offsetof(CPUArchState,
1026 tlb_table[NB_MMU_MODES - 1][1])
1027 > 0x7ff0 + 0x7fff);
1028 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_A0, TCG_REG_A0, 0x7ff0);
1029 cmp_off -= 0x7ff0;
1030 add_off -= 0x7ff0;
1031 }
1032
1033 /* Load the tlb comparator. */
6c530e32 1034 tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, TCG_REG_A0, cmp_off + LO_OFF);
9d8bf2d1
RH
1035 if (TARGET_LONG_BITS == 64) {
1036 tcg_out_opc_imm(s, OPC_LW, base, TCG_REG_A0, cmp_off + HI_OFF);
1037 }
1038
1039 /* Mask the page bits, keeping the alignment bits to compare against.
1040 In between, load the tlb addend for the fast path. */
6c530e32 1041 tcg_out_movi(s, TCG_TYPE_I32, TCG_TMP1,
9d8bf2d1
RH
1042 TARGET_PAGE_MASK | ((1 << s_bits) - 1));
1043 tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0, add_off);
6c530e32 1044 tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, addrl);
9d8bf2d1
RH
1045
1046 label_ptr[0] = s->code_ptr;
6c530e32 1047 tcg_out_opc_br(s, OPC_BNE, TCG_TMP1, TCG_TMP0);
afa05235 1048
9d8bf2d1
RH
1049 if (TARGET_LONG_BITS == 64) {
1050 /* delay slot */
1051 tcg_out_nop(s);
afa05235 1052
9d8bf2d1
RH
1053 label_ptr[1] = s->code_ptr;
1054 tcg_out_opc_br(s, OPC_BNE, addrh, base);
1055 }
afa05235 1056
9d8bf2d1
RH
1057 /* delay slot */
1058 tcg_out_opc_reg(s, OPC_ADDU, base, TCG_REG_A0, addrl);
1059}
afa05235 1060
9d8bf2d1
RH
1061static void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOp opc,
1062 TCGReg datalo, TCGReg datahi,
1063 TCGReg addrlo, TCGReg addrhi,
1064 int mem_index, void *raddr,
1065 tcg_insn_unit *label_ptr[2])
1066{
1067 TCGLabelQemuLdst *label = new_ldst_label(s);
1068
1069 label->is_ld = is_ld;
1070 label->opc = opc;
1071 label->datalo_reg = datalo;
1072 label->datahi_reg = datahi;
1073 label->addrlo_reg = addrlo;
1074 label->addrhi_reg = addrhi;
1075 label->mem_index = mem_index;
1076 label->raddr = raddr;
1077 label->label_ptr[0] = label_ptr[0];
1078 if (TARGET_LONG_BITS == 64) {
1079 label->label_ptr[1] = label_ptr[1];
1080 }
1081}
1082
1083static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1084{
1085 TCGMemOp opc = l->opc;
ce0236cf 1086 TCGReg v0;
9d8bf2d1
RH
1087 int i;
1088
1089 /* resolve label address */
1090 reloc_pc16(l->label_ptr[0], s->code_ptr);
1091 if (TARGET_LONG_BITS == 64) {
1092 reloc_pc16(l->label_ptr[1], s->code_ptr);
1093 }
1094
ce0236cf 1095 i = 1;
9d8bf2d1
RH
1096 if (TARGET_LONG_BITS == 64) {
1097 i = tcg_out_call_iarg_reg2(s, i, l->addrlo_reg, l->addrhi_reg);
1098 } else {
1099 i = tcg_out_call_iarg_reg(s, i, l->addrlo_reg);
1100 }
1101 i = tcg_out_call_iarg_imm(s, i, l->mem_index);
ce0236cf
RH
1102 i = tcg_out_call_iarg_imm(s, i, (intptr_t)l->raddr);
1103 tcg_out_call_int(s, qemu_ld_helpers[opc], false);
1104 /* delay slot */
1105 tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
9d8bf2d1 1106
ce0236cf
RH
1107 v0 = l->datalo_reg;
1108 if ((opc & MO_SIZE) == MO_64) {
9d8bf2d1
RH
1109 /* We eliminated V0 from the possible output registers, so it
1110 cannot be clobbered here. So we must move V1 first. */
ce0236cf
RH
1111 if (MIPS_BE) {
1112 tcg_out_mov(s, TCG_TYPE_I32, v0, TCG_REG_V1);
1113 v0 = l->datahi_reg;
1114 } else {
1115 tcg_out_mov(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_V1);
1116 }
afa05235
AJ
1117 }
1118
9d8bf2d1 1119 reloc_pc16(s->code_ptr, l->raddr);
6d8ff4d8 1120 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
ce0236cf
RH
1121 /* delay slot */
1122 tcg_out_mov(s, TCG_TYPE_REG, v0, TCG_REG_V0);
9d8bf2d1 1123}
afa05235 1124
9d8bf2d1
RH
1125static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1126{
1127 TCGMemOp opc = l->opc;
1128 TCGMemOp s_bits = opc & MO_SIZE;
1129 int i;
1130
1131 /* resolve label address */
1132 reloc_pc16(l->label_ptr[0], s->code_ptr);
1133 if (TARGET_LONG_BITS == 64) {
1134 reloc_pc16(l->label_ptr[1], s->code_ptr);
1135 }
afa05235 1136
ce0236cf 1137 i = 1;
9d8bf2d1
RH
1138 if (TARGET_LONG_BITS == 64) {
1139 i = tcg_out_call_iarg_reg2(s, i, l->addrlo_reg, l->addrhi_reg);
cc01cc8e 1140 } else {
9d8bf2d1
RH
1141 i = tcg_out_call_iarg_reg(s, i, l->addrlo_reg);
1142 }
1143 switch (s_bits) {
1144 case MO_8:
1145 i = tcg_out_call_iarg_reg8(s, i, l->datalo_reg);
1146 break;
1147 case MO_16:
1148 i = tcg_out_call_iarg_reg16(s, i, l->datalo_reg);
1149 break;
1150 case MO_32:
1151 i = tcg_out_call_iarg_reg(s, i, l->datalo_reg);
1152 break;
1153 case MO_64:
1154 i = tcg_out_call_iarg_reg2(s, i, l->datalo_reg, l->datahi_reg);
1155 break;
1156 default:
1157 tcg_abort();
cc01cc8e 1158 }
9d8bf2d1 1159 i = tcg_out_call_iarg_imm(s, i, l->mem_index);
9d8bf2d1 1160
ce0236cf
RH
1161 /* Tail call to the store helper. Thus force the return address
1162 computation to take place in the return address register. */
1163 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RA, (intptr_t)l->raddr);
1164 i = tcg_out_call_iarg_reg(s, i, TCG_REG_RA);
1165 tcg_out_call_int(s, qemu_st_helpers[opc], true);
1166 /* delay slot */
1167 tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
9d8bf2d1 1168}
afa05235
AJ
1169#endif
1170
9d8bf2d1
RH
1171static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
1172 TCGReg base, TCGMemOp opc)
1173{
1174 switch (opc) {
1175 case MO_UB:
1176 tcg_out_opc_imm(s, OPC_LBU, datalo, base, 0);
afa05235 1177 break;
9d8bf2d1
RH
1178 case MO_SB:
1179 tcg_out_opc_imm(s, OPC_LB, datalo, base, 0);
afa05235 1180 break;
9d8bf2d1 1181 case MO_UW | MO_BSWAP:
6c530e32
RH
1182 tcg_out_opc_imm(s, OPC_LHU, TCG_TMP1, base, 0);
1183 tcg_out_bswap16(s, datalo, TCG_TMP1);
afa05235 1184 break;
9d8bf2d1
RH
1185 case MO_UW:
1186 tcg_out_opc_imm(s, OPC_LHU, datalo, base, 0);
afa05235 1187 break;
9d8bf2d1 1188 case MO_SW | MO_BSWAP:
6c530e32
RH
1189 tcg_out_opc_imm(s, OPC_LHU, TCG_TMP1, base, 0);
1190 tcg_out_bswap16s(s, datalo, TCG_TMP1);
afa05235 1191 break;
9d8bf2d1
RH
1192 case MO_SW:
1193 tcg_out_opc_imm(s, OPC_LH, datalo, base, 0);
1194 break;
1195 case MO_UL | MO_BSWAP:
6c530e32
RH
1196 tcg_out_opc_imm(s, OPC_LW, TCG_TMP1, base, 0);
1197 tcg_out_bswap32(s, datalo, TCG_TMP1);
9d8bf2d1
RH
1198 break;
1199 case MO_UL:
1200 tcg_out_opc_imm(s, OPC_LW, datalo, base, 0);
1201 break;
1202 case MO_Q | MO_BSWAP:
6c530e32
RH
1203 tcg_out_opc_imm(s, OPC_LW, TCG_TMP1, base, HI_OFF);
1204 tcg_out_bswap32(s, datalo, TCG_TMP1);
1205 tcg_out_opc_imm(s, OPC_LW, TCG_TMP1, base, LO_OFF);
1206 tcg_out_bswap32(s, datahi, TCG_TMP1);
9d8bf2d1
RH
1207 break;
1208 case MO_Q:
1209 tcg_out_opc_imm(s, OPC_LW, datalo, base, LO_OFF);
1210 tcg_out_opc_imm(s, OPC_LW, datahi, base, HI_OFF);
afa05235
AJ
1211 break;
1212 default:
1213 tcg_abort();
1214 }
afa05235
AJ
1215}
1216
fbef2cc8 1217static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64)
afa05235 1218{
9d8bf2d1
RH
1219 TCGReg addr_regl, addr_regh __attribute__((unused));
1220 TCGReg data_regl, data_regh;
fbef2cc8 1221 TCGMemOp opc;
afa05235 1222#if defined(CONFIG_SOFTMMU)
9d8bf2d1
RH
1223 tcg_insn_unit *label_ptr[2];
1224 int mem_index;
1225 TCGMemOp s_bits;
afa05235 1226#endif
9d8bf2d1
RH
1227 /* Note that we've eliminated V0 from the output registers,
1228 so we won't overwrite the base register during loading. */
1229 TCGReg base = TCG_REG_V0;
1230
afa05235 1231 data_regl = *args++;
fbef2cc8 1232 data_regh = (is_64 ? *args++ : 0);
afa05235 1233 addr_regl = *args++;
9d8bf2d1 1234 addr_regh = (TARGET_LONG_BITS == 64 ? *args++ : 0);
fbef2cc8 1235 opc = *args++;
9d8bf2d1 1236
0834c9ea 1237#if defined(CONFIG_SOFTMMU)
afa05235 1238 mem_index = *args;
9d8bf2d1 1239 s_bits = opc & MO_SIZE;
0834c9ea 1240
9d8bf2d1
RH
1241 tcg_out_tlb_load(s, base, addr_regl, addr_regh, mem_index,
1242 s_bits, label_ptr, 1);
1243 tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc);
1244 add_qemu_ldst_label(s, 1, opc, data_regl, data_regh, addr_regl, addr_regh,
1245 mem_index, s->code_ptr, label_ptr);
0834c9ea 1246#else
9d8bf2d1
RH
1247 if (GUEST_BASE == 0 && data_regl != addr_regl) {
1248 base = addr_regl;
1249 } else if (GUEST_BASE == (int16_t)GUEST_BASE) {
1250 tcg_out_opc_imm(s, OPC_ADDIU, base, addr_regl, GUEST_BASE);
0834c9ea 1251 } else {
9d8bf2d1
RH
1252 tcg_out_movi(s, TCG_TYPE_PTR, base, GUEST_BASE);
1253 tcg_out_opc_reg(s, OPC_ADDU, base, base, addr_regl);
0834c9ea 1254 }
9d8bf2d1
RH
1255 tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc);
1256#endif
1257}
afa05235 1258
9d8bf2d1
RH
1259static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
1260 TCGReg base, TCGMemOp opc)
1261{
1262 switch (opc) {
1263 case MO_8:
1264 tcg_out_opc_imm(s, OPC_SB, datalo, base, 0);
1265 break;
afa05235 1266
9d8bf2d1 1267 case MO_16 | MO_BSWAP:
6c530e32
RH
1268 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, datalo, 0xffff);
1269 tcg_out_bswap16(s, TCG_TMP1, TCG_TMP1);
1270 datalo = TCG_TMP1;
9d8bf2d1
RH
1271 /* FALLTHRU */
1272 case MO_16:
1273 tcg_out_opc_imm(s, OPC_SH, datalo, base, 0);
afa05235 1274 break;
9d8bf2d1
RH
1275
1276 case MO_32 | MO_BSWAP:
6c530e32
RH
1277 tcg_out_bswap32(s, TCG_TMP1, datalo);
1278 datalo = TCG_TMP1;
9d8bf2d1
RH
1279 /* FALLTHRU */
1280 case MO_32:
1281 tcg_out_opc_imm(s, OPC_SW, datalo, base, 0);
afa05235 1282 break;
9d8bf2d1
RH
1283
1284 case MO_64 | MO_BSWAP:
6c530e32
RH
1285 tcg_out_bswap32(s, TCG_TMP1, datalo);
1286 tcg_out_opc_imm(s, OPC_SW, TCG_TMP1, base, HI_OFF);
1287 tcg_out_bswap32(s, TCG_TMP1, datahi);
1288 tcg_out_opc_imm(s, OPC_SW, TCG_TMP1, base, LO_OFF);
afa05235 1289 break;
9d8bf2d1
RH
1290 case MO_64:
1291 tcg_out_opc_imm(s, OPC_SW, datalo, base, LO_OFF);
1292 tcg_out_opc_imm(s, OPC_SW, datahi, base, HI_OFF);
afa05235 1293 break;
9d8bf2d1 1294
afa05235
AJ
1295 default:
1296 tcg_abort();
1297 }
9d8bf2d1 1298}
afa05235 1299
fbef2cc8 1300static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64)
9d8bf2d1
RH
1301{
1302 TCGReg addr_regl, addr_regh __attribute__((unused));
1303 TCGReg data_regl, data_regh, base;
fbef2cc8 1304 TCGMemOp opc;
9d8bf2d1
RH
1305#if defined(CONFIG_SOFTMMU)
1306 tcg_insn_unit *label_ptr[2];
1307 int mem_index;
1308 TCGMemOp s_bits;
1309#endif
1310
1311 data_regl = *args++;
fbef2cc8 1312 data_regh = (is_64 ? *args++ : 0);
9d8bf2d1
RH
1313 addr_regl = *args++;
1314 addr_regh = (TARGET_LONG_BITS == 64 ? *args++ : 0);
fbef2cc8 1315 opc = *args++;
afa05235 1316
9d8bf2d1
RH
1317#if defined(CONFIG_SOFTMMU)
1318 mem_index = *args;
1319 s_bits = opc & 3;
afa05235 1320
9d8bf2d1
RH
1321 /* Note that we eliminated the helper's address argument,
1322 so we can reuse that for the base. */
1323 base = (TARGET_LONG_BITS == 32 ? TCG_REG_A1 : TCG_REG_A2);
1324 tcg_out_tlb_load(s, base, addr_regl, addr_regh, mem_index,
1325 s_bits, label_ptr, 1);
1326 tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc);
1327 add_qemu_ldst_label(s, 0, opc, data_regl, data_regh, addr_regl, addr_regh,
1328 mem_index, s->code_ptr, label_ptr);
cc01cc8e 1329#else
9d8bf2d1
RH
1330 if (GUEST_BASE == 0) {
1331 base = addr_regl;
cc01cc8e 1332 } else {
9d8bf2d1
RH
1333 base = TCG_REG_A0;
1334 if (GUEST_BASE == (int16_t)GUEST_BASE) {
1335 tcg_out_opc_imm(s, OPC_ADDIU, base, addr_regl, GUEST_BASE);
afa05235 1336 } else {
9d8bf2d1
RH
1337 tcg_out_movi(s, TCG_TYPE_PTR, base, GUEST_BASE);
1338 tcg_out_opc_reg(s, OPC_ADDU, base, base, addr_regl);
afa05235 1339 }
afa05235 1340 }
9d8bf2d1 1341 tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc);
afa05235
AJ
1342#endif
1343}
1344
a9751609 1345static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
afa05235
AJ
1346 const TCGArg *args, const int *const_args)
1347{
1348 switch(opc) {
1349 case INDEX_op_exit_tb:
7dae901d
RH
1350 {
1351 uintptr_t a0 = args[0];
1352 TCGReg b0 = TCG_REG_ZERO;
1353
1354 if (a0 & ~0xffff) {
1355 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, a0 & ~0xffff);
1356 b0 = TCG_REG_V0;
1357 }
1358 if (!tcg_out_opc_jmp(s, OPC_J, tb_ret_addr)) {
6c530e32 1359 tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0,
7dae901d 1360 (uintptr_t)tb_ret_addr);
6c530e32 1361 tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
7dae901d
RH
1362 }
1363 tcg_out_opc_imm(s, OPC_ORI, TCG_REG_V0, b0, a0 & 0xffff);
f8c9eddb 1364 }
afa05235
AJ
1365 break;
1366 case INDEX_op_goto_tb:
1367 if (s->tb_jmp_offset) {
1368 /* direct jump method */
1369 tcg_abort();
1370 } else {
1371 /* indirect jump method */
6c530e32 1372 tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_REG_ZERO,
f9a71632 1373 (uintptr_t)(s->tb_next + args[0]));
6c530e32 1374 tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
afa05235
AJ
1375 }
1376 tcg_out_nop(s);
ae0218e3 1377 s->tb_next_offset[args[0]] = tcg_current_code_size(s);
afa05235 1378 break;
afa05235
AJ
1379 case INDEX_op_br:
1380 tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, args[0]);
1381 break;
1382
afa05235 1383 case INDEX_op_ld8u_i32:
116348de 1384 tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]);
afa05235
AJ
1385 break;
1386 case INDEX_op_ld8s_i32:
1387 tcg_out_ldst(s, OPC_LB, args[0], args[1], args[2]);
1388 break;
1389 case INDEX_op_ld16u_i32:
1390 tcg_out_ldst(s, OPC_LHU, args[0], args[1], args[2]);
1391 break;
1392 case INDEX_op_ld16s_i32:
1393 tcg_out_ldst(s, OPC_LH, args[0], args[1], args[2]);
1394 break;
1395 case INDEX_op_ld_i32:
1396 tcg_out_ldst(s, OPC_LW, args[0], args[1], args[2]);
1397 break;
1398 case INDEX_op_st8_i32:
1399 tcg_out_ldst(s, OPC_SB, args[0], args[1], args[2]);
1400 break;
1401 case INDEX_op_st16_i32:
1402 tcg_out_ldst(s, OPC_SH, args[0], args[1], args[2]);
1403 break;
1404 case INDEX_op_st_i32:
1405 tcg_out_ldst(s, OPC_SW, args[0], args[1], args[2]);
1406 break;
1407
1408 case INDEX_op_add_i32:
1409 if (const_args[2]) {
1410 tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], args[2]);
1411 } else {
1412 tcg_out_opc_reg(s, OPC_ADDU, args[0], args[1], args[2]);
1413 }
1414 break;
1415 case INDEX_op_add2_i32:
1416 if (const_args[4]) {
6c530e32 1417 tcg_out_opc_imm(s, OPC_ADDIU, TCG_TMP0, args[2], args[4]);
afa05235 1418 } else {
6c530e32 1419 tcg_out_opc_reg(s, OPC_ADDU, TCG_TMP0, args[2], args[4]);
afa05235 1420 }
6c530e32 1421 tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP1, TCG_TMP0, args[2]);
afa05235
AJ
1422 if (const_args[5]) {
1423 tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], args[5]);
1424 } else {
1425 tcg_out_opc_reg(s, OPC_ADDU, args[1], args[3], args[5]);
1426 }
6c530e32
RH
1427 tcg_out_opc_reg(s, OPC_ADDU, args[1], args[1], TCG_TMP1);
1428 tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_TMP0);
afa05235
AJ
1429 break;
1430 case INDEX_op_sub_i32:
1431 if (const_args[2]) {
1432 tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], -args[2]);
1433 } else {
1434 tcg_out_opc_reg(s, OPC_SUBU, args[0], args[1], args[2]);
1435 }
1436 break;
1437 case INDEX_op_sub2_i32:
1438 if (const_args[4]) {
6c530e32 1439 tcg_out_opc_imm(s, OPC_ADDIU, TCG_TMP0, args[2], -args[4]);
afa05235 1440 } else {
6c530e32 1441 tcg_out_opc_reg(s, OPC_SUBU, TCG_TMP0, args[2], args[4]);
afa05235 1442 }
6c530e32 1443 tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP1, args[2], TCG_TMP0);
afa05235
AJ
1444 if (const_args[5]) {
1445 tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], -args[5]);
1446 } else {
1447 tcg_out_opc_reg(s, OPC_SUBU, args[1], args[3], args[5]);
1448 }
6c530e32
RH
1449 tcg_out_opc_reg(s, OPC_SUBU, args[1], args[1], TCG_TMP1);
1450 tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_TMP0);
afa05235
AJ
1451 break;
1452 case INDEX_op_mul_i32:
988902fc
AJ
1453 if (use_mips32_instructions) {
1454 tcg_out_opc_reg(s, OPC_MUL, args[0], args[1], args[2]);
1455 } else {
1456 tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
1457 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1458 }
afa05235 1459 break;
174d4d21
AJ
1460 case INDEX_op_muls2_i32:
1461 tcg_out_opc_reg(s, OPC_MULT, 0, args[2], args[3]);
1462 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1463 tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
1464 break;
afa05235
AJ
1465 case INDEX_op_mulu2_i32:
1466 tcg_out_opc_reg(s, OPC_MULTU, 0, args[2], args[3]);
1467 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1468 tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
1469 break;
3c9a8f17
RH
1470 case INDEX_op_mulsh_i32:
1471 tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
1472 tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1473 break;
1474 case INDEX_op_muluh_i32:
1475 tcg_out_opc_reg(s, OPC_MULTU, 0, args[1], args[2]);
1476 tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1477 break;
afa05235
AJ
1478 case INDEX_op_div_i32:
1479 tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1480 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1481 break;
1482 case INDEX_op_divu_i32:
1483 tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1484 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1485 break;
1486 case INDEX_op_rem_i32:
1487 tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1488 tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1489 break;
1490 case INDEX_op_remu_i32:
1491 tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1492 tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1493 break;
1494
1495 case INDEX_op_and_i32:
1496 if (const_args[2]) {
1c418268
RH
1497 if (args[2] == (uint16_t)args[2]) {
1498 tcg_out_opc_imm(s, OPC_ANDI, args[0], args[1], args[2]);
1499 } else {
1500 int msb = ctz32(~args[2]) - 1;
1501 assert(use_mips32r2_instructions);
1502 assert(is_p2m1(args[2]));
1503 tcg_out_opc_bf(s, OPC_EXT, args[0], args[1], msb, 0);
1504 }
afa05235
AJ
1505 } else {
1506 tcg_out_opc_reg(s, OPC_AND, args[0], args[1], args[2]);
1507 }
1508 break;
1509 case INDEX_op_or_i32:
1510 if (const_args[2]) {
1511 tcg_out_opc_imm(s, OPC_ORI, args[0], args[1], args[2]);
1512 } else {
1513 tcg_out_opc_reg(s, OPC_OR, args[0], args[1], args[2]);
1514 }
1515 break;
2b79487a
AJ
1516 case INDEX_op_nor_i32:
1517 tcg_out_opc_reg(s, OPC_NOR, args[0], args[1], args[2]);
1518 break;
afa05235 1519 case INDEX_op_not_i32:
489722cf 1520 tcg_out_opc_reg(s, OPC_NOR, args[0], TCG_REG_ZERO, args[1]);
afa05235
AJ
1521 break;
1522 case INDEX_op_xor_i32:
1523 if (const_args[2]) {
1524 tcg_out_opc_imm(s, OPC_XORI, args[0], args[1], args[2]);
1525 } else {
1526 tcg_out_opc_reg(s, OPC_XOR, args[0], args[1], args[2]);
1527 }
1528 break;
1529
1530 case INDEX_op_sar_i32:
1531 if (const_args[2]) {
1532 tcg_out_opc_sa(s, OPC_SRA, args[0], args[1], args[2]);
1533 } else {
1534 tcg_out_opc_reg(s, OPC_SRAV, args[0], args[2], args[1]);
1535 }
1536 break;
1537 case INDEX_op_shl_i32:
1538 if (const_args[2]) {
1539 tcg_out_opc_sa(s, OPC_SLL, args[0], args[1], args[2]);
1540 } else {
1541 tcg_out_opc_reg(s, OPC_SLLV, args[0], args[2], args[1]);
1542 }
1543 break;
1544 case INDEX_op_shr_i32:
1545 if (const_args[2]) {
1546 tcg_out_opc_sa(s, OPC_SRL, args[0], args[1], args[2]);
1547 } else {
1548 tcg_out_opc_reg(s, OPC_SRLV, args[0], args[2], args[1]);
1549 }
1550 break;
9a152519
AJ
1551 case INDEX_op_rotl_i32:
1552 if (const_args[2]) {
1553 tcg_out_opc_sa(s, OPC_ROTR, args[0], args[1], 0x20 - args[2]);
1554 } else {
6c530e32
RH
1555 tcg_out_movi(s, TCG_TYPE_I32, TCG_TMP0, 32);
1556 tcg_out_opc_reg(s, OPC_SUBU, TCG_TMP0, TCG_TMP0, args[2]);
1557 tcg_out_opc_reg(s, OPC_ROTRV, args[0], TCG_TMP0, args[1]);
9a152519
AJ
1558 }
1559 break;
1560 case INDEX_op_rotr_i32:
1561 if (const_args[2]) {
1562 tcg_out_opc_sa(s, OPC_ROTR, args[0], args[1], args[2]);
1563 } else {
1564 tcg_out_opc_reg(s, OPC_ROTRV, args[0], args[2], args[1]);
1565 }
1566 break;
afa05235 1567
c1cf85c9 1568 case INDEX_op_bswap16_i32:
df81ff51 1569 tcg_out_opc_reg(s, OPC_WSBH, args[0], 0, args[1]);
c1cf85c9
AJ
1570 break;
1571 case INDEX_op_bswap32_i32:
df81ff51
AJ
1572 tcg_out_opc_reg(s, OPC_WSBH, args[0], 0, args[1]);
1573 tcg_out_opc_sa(s, OPC_ROTR, args[0], args[0], 16);
c1cf85c9
AJ
1574 break;
1575
116348de 1576 case INDEX_op_ext8s_i32:
3207bf25 1577 tcg_out_opc_reg(s, OPC_SEB, args[0], 0, args[1]);
116348de
AJ
1578 break;
1579 case INDEX_op_ext16s_i32:
3207bf25 1580 tcg_out_opc_reg(s, OPC_SEH, args[0], 0, args[1]);
116348de
AJ
1581 break;
1582
04f71aa3 1583 case INDEX_op_deposit_i32:
1c418268
RH
1584 tcg_out_opc_bf(s, OPC_INS, args[0], args[2],
1585 args[3] + args[4] - 1, args[3]);
04f71aa3
AJ
1586 break;
1587
afa05235
AJ
1588 case INDEX_op_brcond_i32:
1589 tcg_out_brcond(s, args[2], args[0], args[1], args[3]);
1590 break;
1591 case INDEX_op_brcond2_i32:
1592 tcg_out_brcond2(s, args[4], args[0], args[1], args[2], args[3], args[5]);
1593 break;
1594
7d7c4930
AJ
1595 case INDEX_op_movcond_i32:
1596 tcg_out_movcond(s, args[5], args[0], args[1], args[2], args[3]);
1597 break;
1598
4cb26382
AJ
1599 case INDEX_op_setcond_i32:
1600 tcg_out_setcond(s, args[3], args[0], args[1], args[2]);
1601 break;
434254aa
AJ
1602 case INDEX_op_setcond2_i32:
1603 tcg_out_setcond2(s, args[5], args[0], args[1], args[2], args[3], args[4]);
1604 break;
4cb26382 1605
fbef2cc8
RH
1606 case INDEX_op_qemu_ld_i32:
1607 tcg_out_qemu_ld(s, args, false);
afa05235 1608 break;
fbef2cc8
RH
1609 case INDEX_op_qemu_ld_i64:
1610 tcg_out_qemu_ld(s, args, true);
afa05235 1611 break;
fbef2cc8
RH
1612 case INDEX_op_qemu_st_i32:
1613 tcg_out_qemu_st(s, args, false);
afa05235 1614 break;
fbef2cc8
RH
1615 case INDEX_op_qemu_st_i64:
1616 tcg_out_qemu_st(s, args, true);
afa05235
AJ
1617 break;
1618
96d0ee7f
RH
1619 case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
1620 case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi. */
1621 case INDEX_op_call: /* Always emitted via tcg_out_call. */
afa05235
AJ
1622 default:
1623 tcg_abort();
1624 }
1625}
1626
1627static const TCGTargetOpDef mips_op_defs[] = {
1628 { INDEX_op_exit_tb, { } },
1629 { INDEX_op_goto_tb, { } },
afa05235
AJ
1630 { INDEX_op_br, { } },
1631
afa05235
AJ
1632 { INDEX_op_ld8u_i32, { "r", "r" } },
1633 { INDEX_op_ld8s_i32, { "r", "r" } },
1634 { INDEX_op_ld16u_i32, { "r", "r" } },
1635 { INDEX_op_ld16s_i32, { "r", "r" } },
1636 { INDEX_op_ld_i32, { "r", "r" } },
1637 { INDEX_op_st8_i32, { "rZ", "r" } },
1638 { INDEX_op_st16_i32, { "rZ", "r" } },
1639 { INDEX_op_st_i32, { "rZ", "r" } },
1640
2ceb3a9e 1641 { INDEX_op_add_i32, { "r", "rZ", "rJ" } },
afa05235 1642 { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
174d4d21 1643 { INDEX_op_muls2_i32, { "r", "r", "rZ", "rZ" } },
afa05235 1644 { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
3c9a8f17
RH
1645 { INDEX_op_mulsh_i32, { "r", "rZ", "rZ" } },
1646 { INDEX_op_muluh_i32, { "r", "rZ", "rZ" } },
afa05235
AJ
1647 { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
1648 { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
1649 { INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
1650 { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
070603f6 1651 { INDEX_op_sub_i32, { "r", "rZ", "rN" } },
afa05235 1652
1c418268 1653 { INDEX_op_and_i32, { "r", "rZ", "rIK" } },
2b79487a 1654 { INDEX_op_nor_i32, { "r", "rZ", "rZ" } },
afa05235
AJ
1655 { INDEX_op_not_i32, { "r", "rZ" } },
1656 { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
1657 { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
1658
2ceb3a9e
AJ
1659 { INDEX_op_shl_i32, { "r", "rZ", "ri" } },
1660 { INDEX_op_shr_i32, { "r", "rZ", "ri" } },
1661 { INDEX_op_sar_i32, { "r", "rZ", "ri" } },
9a152519
AJ
1662 { INDEX_op_rotr_i32, { "r", "rZ", "ri" } },
1663 { INDEX_op_rotl_i32, { "r", "rZ", "ri" } },
afa05235 1664
c1cf85c9
AJ
1665 { INDEX_op_bswap16_i32, { "r", "r" } },
1666 { INDEX_op_bswap32_i32, { "r", "r" } },
1667
116348de
AJ
1668 { INDEX_op_ext8s_i32, { "r", "rZ" } },
1669 { INDEX_op_ext16s_i32, { "r", "rZ" } },
1670
04f71aa3
AJ
1671 { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
1672
afa05235 1673 { INDEX_op_brcond_i32, { "rZ", "rZ" } },
7d7c4930 1674 { INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rZ", "0" } },
4cb26382 1675 { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
434254aa 1676 { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
afa05235 1677
2ceb3a9e 1678 { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJ", "rJ" } },
070603f6 1679 { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rN", "rN" } },
afa05235
AJ
1680 { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
1681
1682#if TARGET_LONG_BITS == 32
fbef2cc8
RH
1683 { INDEX_op_qemu_ld_i32, { "L", "lZ" } },
1684 { INDEX_op_qemu_st_i32, { "SZ", "SZ" } },
1685 { INDEX_op_qemu_ld_i64, { "L", "L", "lZ" } },
1686 { INDEX_op_qemu_st_i64, { "SZ", "SZ", "SZ" } },
afa05235 1687#else
fbef2cc8
RH
1688 { INDEX_op_qemu_ld_i32, { "L", "lZ", "lZ" } },
1689 { INDEX_op_qemu_st_i32, { "SZ", "SZ", "SZ" } },
1690 { INDEX_op_qemu_ld_i64, { "L", "L", "lZ", "lZ" } },
1691 { INDEX_op_qemu_st_i64, { "SZ", "SZ", "SZ", "SZ" } },
afa05235
AJ
1692#endif
1693 { -1 },
1694};
1695
1696static int tcg_target_callee_save_regs[] = {
cea5f9a2 1697 TCG_REG_S0, /* used for the global env (TCG_AREG0) */
afa05235
AJ
1698 TCG_REG_S1,
1699 TCG_REG_S2,
1700 TCG_REG_S3,
1701 TCG_REG_S4,
1702 TCG_REG_S5,
1703 TCG_REG_S6,
1704 TCG_REG_S7,
41883904 1705 TCG_REG_S8,
afa05235
AJ
1706 TCG_REG_RA, /* should be last for ABI compliance */
1707};
1708
988902fc
AJ
1709/* The Linux kernel doesn't provide any information about the available
1710 instruction set. Probe it using a signal handler. */
1711
1712#include <signal.h>
1713
1714#ifndef use_movnz_instructions
1715bool use_movnz_instructions = false;
1716#endif
1717
1718#ifndef use_mips32_instructions
1719bool use_mips32_instructions = false;
1720#endif
1721
1722#ifndef use_mips32r2_instructions
1723bool use_mips32r2_instructions = false;
1724#endif
1725
1726static volatile sig_atomic_t got_sigill;
1727
1728static void sigill_handler(int signo, siginfo_t *si, void *data)
1729{
1730 /* Skip the faulty instruction */
1731 ucontext_t *uc = (ucontext_t *)data;
1732 uc->uc_mcontext.pc += 4;
1733
1734 got_sigill = 1;
1735}
1736
1737static void tcg_target_detect_isa(void)
1738{
1739 struct sigaction sa_old, sa_new;
1740
1741 memset(&sa_new, 0, sizeof(sa_new));
1742 sa_new.sa_flags = SA_SIGINFO;
1743 sa_new.sa_sigaction = sigill_handler;
1744 sigaction(SIGILL, &sa_new, &sa_old);
1745
1746 /* Probe for movn/movz, necessary to implement movcond. */
1747#ifndef use_movnz_instructions
1748 got_sigill = 0;
1749 asm volatile(".set push\n"
1750 ".set mips32\n"
1751 "movn $zero, $zero, $zero\n"
1752 "movz $zero, $zero, $zero\n"
1753 ".set pop\n"
1754 : : : );
1755 use_movnz_instructions = !got_sigill;
1756#endif
1757
1758 /* Probe for MIPS32 instructions. As no subsetting is allowed
1759 by the specification, it is only necessary to probe for one
1760 of the instructions. */
1761#ifndef use_mips32_instructions
1762 got_sigill = 0;
1763 asm volatile(".set push\n"
1764 ".set mips32\n"
1765 "mul $zero, $zero\n"
1766 ".set pop\n"
1767 : : : );
1768 use_mips32_instructions = !got_sigill;
1769#endif
1770
1771 /* Probe for MIPS32r2 instructions if MIPS32 instructions are
1772 available. As no subsetting is allowed by the specification,
1773 it is only necessary to probe for one of the instructions. */
1774#ifndef use_mips32r2_instructions
1775 if (use_mips32_instructions) {
1776 got_sigill = 0;
1777 asm volatile(".set push\n"
1778 ".set mips32r2\n"
1779 "seb $zero, $zero\n"
1780 ".set pop\n"
1781 : : : );
1782 use_mips32r2_instructions = !got_sigill;
1783 }
1784#endif
1785
1786 sigaction(SIGILL, &sa_old, NULL);
1787}
1788
afa05235 1789/* Generate global QEMU prologue and epilogue code */
e4d58b41 1790static void tcg_target_qemu_prologue(TCGContext *s)
afa05235
AJ
1791{
1792 int i, frame_size;
1793
0d0b53a6 1794 /* reserve some stack space, also for TCG temps. */
afa05235 1795 frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
0d0b53a6
AJ
1796 + TCG_STATIC_CALL_ARGS_SIZE
1797 + CPU_TEMP_BUF_NLONGS * sizeof(long);
afa05235
AJ
1798 frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1799 ~(TCG_TARGET_STACK_ALIGN - 1);
e809c0dc
AJ
1800 tcg_set_frame(s, TCG_REG_SP, ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1801 + TCG_STATIC_CALL_ARGS_SIZE,
0d0b53a6 1802 CPU_TEMP_BUF_NLONGS * sizeof(long));
afa05235
AJ
1803
1804 /* TB prologue */
1805 tcg_out_addi(s, TCG_REG_SP, -frame_size);
1806 for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1807 tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1808 TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1809 }
1810
1811 /* Call generated code */
ea15fb06 1812 tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1], 0);
cea5f9a2 1813 tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
afa05235
AJ
1814 tb_ret_addr = s->code_ptr;
1815
1816 /* TB epilogue */
1817 for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1818 tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1819 TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1820 }
1821
1822 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
1823 tcg_out_addi(s, TCG_REG_SP, frame_size);
1824}
1825
e4d58b41 1826static void tcg_target_init(TCGContext *s)
afa05235 1827{
988902fc 1828 tcg_target_detect_isa();
afa05235
AJ
1829 tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
1830 tcg_regset_set(tcg_target_call_clobber_regs,
1831 (1 << TCG_REG_V0) |
1832 (1 << TCG_REG_V1) |
1833 (1 << TCG_REG_A0) |
1834 (1 << TCG_REG_A1) |
1835 (1 << TCG_REG_A2) |
1836 (1 << TCG_REG_A3) |
41883904 1837 (1 << TCG_REG_T0) |
afa05235
AJ
1838 (1 << TCG_REG_T1) |
1839 (1 << TCG_REG_T2) |
1840 (1 << TCG_REG_T3) |
1841 (1 << TCG_REG_T4) |
1842 (1 << TCG_REG_T5) |
1843 (1 << TCG_REG_T6) |
1844 (1 << TCG_REG_T7) |
1845 (1 << TCG_REG_T8) |
1846 (1 << TCG_REG_T9));
1847
1848 tcg_regset_clear(s->reserved_regs);
1849 tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
1850 tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0); /* kernel use only */
1851 tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1); /* kernel use only */
6c530e32
RH
1852 tcg_regset_set_reg(s->reserved_regs, TCG_TMP0); /* internal use */
1853 tcg_regset_set_reg(s->reserved_regs, TCG_TMP1); /* internal use */
afa05235
AJ
1854 tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return address */
1855 tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */
3314e008 1856 tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP); /* global pointer */
afa05235
AJ
1857
1858 tcg_add_target_add_op_defs(mips_op_defs);
1859}