usb: use local path for local headers
[qemu.git] / tcg / mips / tcg-target.inc.c
blobca5f1d4894321eb43859fde3932fbd45238c12b7
1 /*
2 * Tiny Code Generator for QEMU
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
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:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
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.
27 #ifdef HOST_WORDS_BIGENDIAN
28 # define MIPS_BE 1
29 #else
30 # define MIPS_BE 0
31 #endif
33 #if TCG_TARGET_REG_BITS == 32
34 # define LO_OFF (MIPS_BE * 4)
35 # define HI_OFF (4 - LO_OFF)
36 #else
37 /* To assert at compile-time that these values are never used
38 for TCG_TARGET_REG_BITS == 64. */
39 int link_error(void);
40 # define LO_OFF link_error()
41 # define HI_OFF link_error()
42 #endif
44 #ifdef CONFIG_DEBUG_TCG
45 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
46 "zero",
47 "at",
48 "v0",
49 "v1",
50 "a0",
51 "a1",
52 "a2",
53 "a3",
54 "t0",
55 "t1",
56 "t2",
57 "t3",
58 "t4",
59 "t5",
60 "t6",
61 "t7",
62 "s0",
63 "s1",
64 "s2",
65 "s3",
66 "s4",
67 "s5",
68 "s6",
69 "s7",
70 "t8",
71 "t9",
72 "k0",
73 "k1",
74 "gp",
75 "sp",
76 "s8",
77 "ra",
79 #endif
81 #define TCG_TMP0 TCG_REG_AT
82 #define TCG_TMP1 TCG_REG_T9
83 #define TCG_TMP2 TCG_REG_T8
84 #define TCG_TMP3 TCG_REG_T7
86 #ifndef CONFIG_SOFTMMU
87 #define TCG_GUEST_BASE_REG TCG_REG_S1
88 #endif
90 /* check if we really need so many registers :P */
91 static const int tcg_target_reg_alloc_order[] = {
92 /* Call saved registers. */
93 TCG_REG_S0,
94 TCG_REG_S1,
95 TCG_REG_S2,
96 TCG_REG_S3,
97 TCG_REG_S4,
98 TCG_REG_S5,
99 TCG_REG_S6,
100 TCG_REG_S7,
101 TCG_REG_S8,
103 /* Call clobbered registers. */
104 TCG_REG_T4,
105 TCG_REG_T5,
106 TCG_REG_T6,
107 TCG_REG_T7,
108 TCG_REG_T8,
109 TCG_REG_T9,
110 TCG_REG_V1,
111 TCG_REG_V0,
113 /* Argument registers, opposite order of allocation. */
114 TCG_REG_T3,
115 TCG_REG_T2,
116 TCG_REG_T1,
117 TCG_REG_T0,
118 TCG_REG_A3,
119 TCG_REG_A2,
120 TCG_REG_A1,
121 TCG_REG_A0,
124 static const TCGReg tcg_target_call_iarg_regs[] = {
125 TCG_REG_A0,
126 TCG_REG_A1,
127 TCG_REG_A2,
128 TCG_REG_A3,
129 #if _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64
130 TCG_REG_T0,
131 TCG_REG_T1,
132 TCG_REG_T2,
133 TCG_REG_T3,
134 #endif
137 static const TCGReg tcg_target_call_oarg_regs[2] = {
138 TCG_REG_V0,
139 TCG_REG_V1
142 static tcg_insn_unit *tb_ret_addr;
143 static tcg_insn_unit *bswap32_addr;
144 static tcg_insn_unit *bswap32u_addr;
145 static tcg_insn_unit *bswap64_addr;
147 static inline uint32_t reloc_pc16_val(tcg_insn_unit *pc, tcg_insn_unit *target)
149 /* Let the compiler perform the right-shift as part of the arithmetic. */
150 ptrdiff_t disp = target - (pc + 1);
151 tcg_debug_assert(disp == (int16_t)disp);
152 return disp & 0xffff;
155 static inline void reloc_pc16(tcg_insn_unit *pc, tcg_insn_unit *target)
157 *pc = deposit32(*pc, 0, 16, reloc_pc16_val(pc, target));
160 static inline uint32_t reloc_26_val(tcg_insn_unit *pc, tcg_insn_unit *target)
162 tcg_debug_assert((((uintptr_t)pc ^ (uintptr_t)target) & 0xf0000000) == 0);
163 return ((uintptr_t)target >> 2) & 0x3ffffff;
166 static inline void reloc_26(tcg_insn_unit *pc, tcg_insn_unit *target)
168 *pc = deposit32(*pc, 0, 26, reloc_26_val(pc, target));
171 static void patch_reloc(tcg_insn_unit *code_ptr, int type,
172 intptr_t value, intptr_t addend)
174 tcg_debug_assert(type == R_MIPS_PC16);
175 tcg_debug_assert(addend == 0);
176 reloc_pc16(code_ptr, (tcg_insn_unit *)value);
179 #define TCG_CT_CONST_ZERO 0x100
180 #define TCG_CT_CONST_U16 0x200 /* Unsigned 16-bit: 0 - 0xffff. */
181 #define TCG_CT_CONST_S16 0x400 /* Signed 16-bit: -32768 - 32767 */
182 #define TCG_CT_CONST_P2M1 0x800 /* Power of 2 minus 1. */
183 #define TCG_CT_CONST_N16 0x1000 /* "Negatable" 16-bit: -32767 - 32767 */
184 #define TCG_CT_CONST_WSZ 0x2000 /* word size */
186 static inline bool is_p2m1(tcg_target_long val)
188 return val && ((val + 1) & val) == 0;
191 /* parse target specific constraints */
192 static const char *target_parse_constraint(TCGArgConstraint *ct,
193 const char *ct_str, TCGType type)
195 switch(*ct_str++) {
196 case 'r':
197 ct->ct |= TCG_CT_REG;
198 ct->u.regs = 0xffffffff;
199 break;
200 case 'L': /* qemu_ld input arg constraint */
201 ct->ct |= TCG_CT_REG;
202 ct->u.regs = 0xffffffff;
203 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
204 #if defined(CONFIG_SOFTMMU)
205 if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
206 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
208 #endif
209 break;
210 case 'S': /* qemu_st constraint */
211 ct->ct |= TCG_CT_REG;
212 ct->u.regs = 0xffffffff;
213 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
214 #if defined(CONFIG_SOFTMMU)
215 if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
216 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
217 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A3);
218 } else {
219 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1);
221 #endif
222 break;
223 case 'I':
224 ct->ct |= TCG_CT_CONST_U16;
225 break;
226 case 'J':
227 ct->ct |= TCG_CT_CONST_S16;
228 break;
229 case 'K':
230 ct->ct |= TCG_CT_CONST_P2M1;
231 break;
232 case 'N':
233 ct->ct |= TCG_CT_CONST_N16;
234 break;
235 case 'W':
236 ct->ct |= TCG_CT_CONST_WSZ;
237 break;
238 case 'Z':
239 /* We are cheating a bit here, using the fact that the register
240 ZERO is also the register number 0. Hence there is no need
241 to check for const_args in each instruction. */
242 ct->ct |= TCG_CT_CONST_ZERO;
243 break;
244 default:
245 return NULL;
247 return ct_str;
250 /* test if a constant matches the constraint */
251 static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
252 const TCGArgConstraint *arg_ct)
254 int ct;
255 ct = arg_ct->ct;
256 if (ct & TCG_CT_CONST) {
257 return 1;
258 } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
259 return 1;
260 } else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val) {
261 return 1;
262 } else if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val) {
263 return 1;
264 } else if ((ct & TCG_CT_CONST_N16) && val >= -32767 && val <= 32767) {
265 return 1;
266 } else if ((ct & TCG_CT_CONST_P2M1)
267 && use_mips32r2_instructions && is_p2m1(val)) {
268 return 1;
269 } else if ((ct & TCG_CT_CONST_WSZ)
270 && val == (type == TCG_TYPE_I32 ? 32 : 64)) {
271 return 1;
273 return 0;
276 /* instruction opcodes */
277 typedef enum {
278 OPC_J = 002 << 26,
279 OPC_JAL = 003 << 26,
280 OPC_BEQ = 004 << 26,
281 OPC_BNE = 005 << 26,
282 OPC_BLEZ = 006 << 26,
283 OPC_BGTZ = 007 << 26,
284 OPC_ADDIU = 011 << 26,
285 OPC_SLTI = 012 << 26,
286 OPC_SLTIU = 013 << 26,
287 OPC_ANDI = 014 << 26,
288 OPC_ORI = 015 << 26,
289 OPC_XORI = 016 << 26,
290 OPC_LUI = 017 << 26,
291 OPC_DADDIU = 031 << 26,
292 OPC_LB = 040 << 26,
293 OPC_LH = 041 << 26,
294 OPC_LW = 043 << 26,
295 OPC_LBU = 044 << 26,
296 OPC_LHU = 045 << 26,
297 OPC_LWU = 047 << 26,
298 OPC_SB = 050 << 26,
299 OPC_SH = 051 << 26,
300 OPC_SW = 053 << 26,
301 OPC_LD = 067 << 26,
302 OPC_SD = 077 << 26,
304 OPC_SPECIAL = 000 << 26,
305 OPC_SLL = OPC_SPECIAL | 000,
306 OPC_SRL = OPC_SPECIAL | 002,
307 OPC_ROTR = OPC_SPECIAL | 002 | (1 << 21),
308 OPC_SRA = OPC_SPECIAL | 003,
309 OPC_SLLV = OPC_SPECIAL | 004,
310 OPC_SRLV = OPC_SPECIAL | 006,
311 OPC_ROTRV = OPC_SPECIAL | 006 | 0100,
312 OPC_SRAV = OPC_SPECIAL | 007,
313 OPC_JR_R5 = OPC_SPECIAL | 010,
314 OPC_JALR = OPC_SPECIAL | 011,
315 OPC_MOVZ = OPC_SPECIAL | 012,
316 OPC_MOVN = OPC_SPECIAL | 013,
317 OPC_SYNC = OPC_SPECIAL | 017,
318 OPC_MFHI = OPC_SPECIAL | 020,
319 OPC_MFLO = OPC_SPECIAL | 022,
320 OPC_DSLLV = OPC_SPECIAL | 024,
321 OPC_DSRLV = OPC_SPECIAL | 026,
322 OPC_DROTRV = OPC_SPECIAL | 026 | 0100,
323 OPC_DSRAV = OPC_SPECIAL | 027,
324 OPC_MULT = OPC_SPECIAL | 030,
325 OPC_MUL_R6 = OPC_SPECIAL | 030 | 0200,
326 OPC_MUH = OPC_SPECIAL | 030 | 0300,
327 OPC_MULTU = OPC_SPECIAL | 031,
328 OPC_MULU = OPC_SPECIAL | 031 | 0200,
329 OPC_MUHU = OPC_SPECIAL | 031 | 0300,
330 OPC_DIV = OPC_SPECIAL | 032,
331 OPC_DIV_R6 = OPC_SPECIAL | 032 | 0200,
332 OPC_MOD = OPC_SPECIAL | 032 | 0300,
333 OPC_DIVU = OPC_SPECIAL | 033,
334 OPC_DIVU_R6 = OPC_SPECIAL | 033 | 0200,
335 OPC_MODU = OPC_SPECIAL | 033 | 0300,
336 OPC_DMULT = OPC_SPECIAL | 034,
337 OPC_DMUL = OPC_SPECIAL | 034 | 0200,
338 OPC_DMUH = OPC_SPECIAL | 034 | 0300,
339 OPC_DMULTU = OPC_SPECIAL | 035,
340 OPC_DMULU = OPC_SPECIAL | 035 | 0200,
341 OPC_DMUHU = OPC_SPECIAL | 035 | 0300,
342 OPC_DDIV = OPC_SPECIAL | 036,
343 OPC_DDIV_R6 = OPC_SPECIAL | 036 | 0200,
344 OPC_DMOD = OPC_SPECIAL | 036 | 0300,
345 OPC_DDIVU = OPC_SPECIAL | 037,
346 OPC_DDIVU_R6 = OPC_SPECIAL | 037 | 0200,
347 OPC_DMODU = OPC_SPECIAL | 037 | 0300,
348 OPC_ADDU = OPC_SPECIAL | 041,
349 OPC_SUBU = OPC_SPECIAL | 043,
350 OPC_AND = OPC_SPECIAL | 044,
351 OPC_OR = OPC_SPECIAL | 045,
352 OPC_XOR = OPC_SPECIAL | 046,
353 OPC_NOR = OPC_SPECIAL | 047,
354 OPC_SLT = OPC_SPECIAL | 052,
355 OPC_SLTU = OPC_SPECIAL | 053,
356 OPC_DADDU = OPC_SPECIAL | 055,
357 OPC_DSUBU = OPC_SPECIAL | 057,
358 OPC_SELEQZ = OPC_SPECIAL | 065,
359 OPC_SELNEZ = OPC_SPECIAL | 067,
360 OPC_DSLL = OPC_SPECIAL | 070,
361 OPC_DSRL = OPC_SPECIAL | 072,
362 OPC_DROTR = OPC_SPECIAL | 072 | (1 << 21),
363 OPC_DSRA = OPC_SPECIAL | 073,
364 OPC_DSLL32 = OPC_SPECIAL | 074,
365 OPC_DSRL32 = OPC_SPECIAL | 076,
366 OPC_DROTR32 = OPC_SPECIAL | 076 | (1 << 21),
367 OPC_DSRA32 = OPC_SPECIAL | 077,
368 OPC_CLZ_R6 = OPC_SPECIAL | 0120,
369 OPC_DCLZ_R6 = OPC_SPECIAL | 0122,
371 OPC_REGIMM = 001 << 26,
372 OPC_BLTZ = OPC_REGIMM | (000 << 16),
373 OPC_BGEZ = OPC_REGIMM | (001 << 16),
375 OPC_SPECIAL2 = 034 << 26,
376 OPC_MUL_R5 = OPC_SPECIAL2 | 002,
377 OPC_CLZ = OPC_SPECIAL2 | 040,
378 OPC_DCLZ = OPC_SPECIAL2 | 044,
380 OPC_SPECIAL3 = 037 << 26,
381 OPC_EXT = OPC_SPECIAL3 | 000,
382 OPC_DEXTM = OPC_SPECIAL3 | 001,
383 OPC_DEXTU = OPC_SPECIAL3 | 002,
384 OPC_DEXT = OPC_SPECIAL3 | 003,
385 OPC_INS = OPC_SPECIAL3 | 004,
386 OPC_DINSM = OPC_SPECIAL3 | 005,
387 OPC_DINSU = OPC_SPECIAL3 | 006,
388 OPC_DINS = OPC_SPECIAL3 | 007,
389 OPC_WSBH = OPC_SPECIAL3 | 00240,
390 OPC_DSBH = OPC_SPECIAL3 | 00244,
391 OPC_DSHD = OPC_SPECIAL3 | 00544,
392 OPC_SEB = OPC_SPECIAL3 | 02040,
393 OPC_SEH = OPC_SPECIAL3 | 03040,
395 /* MIPS r6 doesn't have JR, JALR should be used instead */
396 OPC_JR = use_mips32r6_instructions ? OPC_JALR : OPC_JR_R5,
399 * MIPS r6 replaces MUL with an alternative encoding which is
400 * backwards-compatible at the assembly level.
402 OPC_MUL = use_mips32r6_instructions ? OPC_MUL_R6 : OPC_MUL_R5,
404 /* MIPS r6 introduced names for weaker variants of SYNC. These are
405 backward compatible to previous architecture revisions. */
406 OPC_SYNC_WMB = OPC_SYNC | 0x04 << 5,
407 OPC_SYNC_MB = OPC_SYNC | 0x10 << 5,
408 OPC_SYNC_ACQUIRE = OPC_SYNC | 0x11 << 5,
409 OPC_SYNC_RELEASE = OPC_SYNC | 0x12 << 5,
410 OPC_SYNC_RMB = OPC_SYNC | 0x13 << 5,
412 /* Aliases for convenience. */
413 ALIAS_PADD = sizeof(void *) == 4 ? OPC_ADDU : OPC_DADDU,
414 ALIAS_PADDI = sizeof(void *) == 4 ? OPC_ADDIU : OPC_DADDIU,
415 ALIAS_TSRL = TARGET_LONG_BITS == 32 || TCG_TARGET_REG_BITS == 32
416 ? OPC_SRL : OPC_DSRL,
417 } MIPSInsn;
420 * Type reg
422 static inline void tcg_out_opc_reg(TCGContext *s, MIPSInsn opc,
423 TCGReg rd, TCGReg rs, TCGReg rt)
425 int32_t inst;
427 inst = opc;
428 inst |= (rs & 0x1F) << 21;
429 inst |= (rt & 0x1F) << 16;
430 inst |= (rd & 0x1F) << 11;
431 tcg_out32(s, inst);
435 * Type immediate
437 static inline void tcg_out_opc_imm(TCGContext *s, MIPSInsn opc,
438 TCGReg rt, TCGReg rs, TCGArg imm)
440 int32_t inst;
442 inst = opc;
443 inst |= (rs & 0x1F) << 21;
444 inst |= (rt & 0x1F) << 16;
445 inst |= (imm & 0xffff);
446 tcg_out32(s, inst);
450 * Type bitfield
452 static inline void tcg_out_opc_bf(TCGContext *s, MIPSInsn opc, TCGReg rt,
453 TCGReg rs, int msb, int lsb)
455 int32_t inst;
457 inst = opc;
458 inst |= (rs & 0x1F) << 21;
459 inst |= (rt & 0x1F) << 16;
460 inst |= (msb & 0x1F) << 11;
461 inst |= (lsb & 0x1F) << 6;
462 tcg_out32(s, inst);
465 static inline void tcg_out_opc_bf64(TCGContext *s, MIPSInsn opc, MIPSInsn opm,
466 MIPSInsn oph, TCGReg rt, TCGReg rs,
467 int msb, int lsb)
469 if (lsb >= 32) {
470 opc = oph;
471 msb -= 32;
472 lsb -= 32;
473 } else if (msb >= 32) {
474 opc = opm;
475 msb -= 32;
477 tcg_out_opc_bf(s, opc, rt, rs, msb, lsb);
481 * Type branch
483 static inline void tcg_out_opc_br(TCGContext *s, MIPSInsn opc,
484 TCGReg rt, TCGReg rs)
486 /* We pay attention here to not modify the branch target by reading
487 the existing value and using it again. This ensure that caches and
488 memory are kept coherent during retranslation. */
489 uint16_t offset = (uint16_t)*s->code_ptr;
491 tcg_out_opc_imm(s, opc, rt, rs, offset);
495 * Type sa
497 static inline void tcg_out_opc_sa(TCGContext *s, MIPSInsn opc,
498 TCGReg rd, TCGReg rt, TCGArg sa)
500 int32_t inst;
502 inst = opc;
503 inst |= (rt & 0x1F) << 16;
504 inst |= (rd & 0x1F) << 11;
505 inst |= (sa & 0x1F) << 6;
506 tcg_out32(s, inst);
510 static void tcg_out_opc_sa64(TCGContext *s, MIPSInsn opc1, MIPSInsn opc2,
511 TCGReg rd, TCGReg rt, TCGArg sa)
513 int32_t inst;
515 inst = (sa & 32 ? opc2 : opc1);
516 inst |= (rt & 0x1F) << 16;
517 inst |= (rd & 0x1F) << 11;
518 inst |= (sa & 0x1F) << 6;
519 tcg_out32(s, inst);
523 * Type jump.
524 * Returns true if the branch was in range and the insn was emitted.
526 static bool tcg_out_opc_jmp(TCGContext *s, MIPSInsn opc, void *target)
528 uintptr_t dest = (uintptr_t)target;
529 uintptr_t from = (uintptr_t)s->code_ptr + 4;
530 int32_t inst;
532 /* The pc-region branch happens within the 256MB region of
533 the delay slot (thus the +4). */
534 if ((from ^ dest) & -(1 << 28)) {
535 return false;
537 tcg_debug_assert((dest & 3) == 0);
539 inst = opc;
540 inst |= (dest >> 2) & 0x3ffffff;
541 tcg_out32(s, inst);
542 return true;
545 static inline void tcg_out_nop(TCGContext *s)
547 tcg_out32(s, 0);
550 static inline void tcg_out_dsll(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa)
552 tcg_out_opc_sa64(s, OPC_DSLL, OPC_DSLL32, rd, rt, sa);
555 static inline void tcg_out_dsrl(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa)
557 tcg_out_opc_sa64(s, OPC_DSRL, OPC_DSRL32, rd, rt, sa);
560 static inline void tcg_out_dsra(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa)
562 tcg_out_opc_sa64(s, OPC_DSRA, OPC_DSRA32, rd, rt, sa);
565 static inline void tcg_out_mov(TCGContext *s, TCGType type,
566 TCGReg ret, TCGReg arg)
568 /* Simple reg-reg move, optimising out the 'do nothing' case */
569 if (ret != arg) {
570 tcg_out_opc_reg(s, OPC_OR, ret, arg, TCG_REG_ZERO);
574 static void tcg_out_movi(TCGContext *s, TCGType type,
575 TCGReg ret, tcg_target_long arg)
577 if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) {
578 arg = (int32_t)arg;
580 if (arg == (int16_t)arg) {
581 tcg_out_opc_imm(s, OPC_ADDIU, ret, TCG_REG_ZERO, arg);
582 return;
584 if (arg == (uint16_t)arg) {
585 tcg_out_opc_imm(s, OPC_ORI, ret, TCG_REG_ZERO, arg);
586 return;
588 if (TCG_TARGET_REG_BITS == 32 || arg == (int32_t)arg) {
589 tcg_out_opc_imm(s, OPC_LUI, ret, TCG_REG_ZERO, arg >> 16);
590 } else {
591 tcg_out_movi(s, TCG_TYPE_I32, ret, arg >> 31 >> 1);
592 if (arg & 0xffff0000ull) {
593 tcg_out_dsll(s, ret, ret, 16);
594 tcg_out_opc_imm(s, OPC_ORI, ret, ret, arg >> 16);
595 tcg_out_dsll(s, ret, ret, 16);
596 } else {
597 tcg_out_dsll(s, ret, ret, 32);
600 if (arg & 0xffff) {
601 tcg_out_opc_imm(s, OPC_ORI, ret, ret, arg & 0xffff);
605 static inline void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg)
607 if (use_mips32r2_instructions) {
608 tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
609 } else {
610 /* ret and arg can't be register at */
611 if (ret == TCG_TMP0 || arg == TCG_TMP0) {
612 tcg_abort();
615 tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8);
616 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
617 tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
618 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
622 static inline void tcg_out_bswap16s(TCGContext *s, TCGReg ret, TCGReg arg)
624 if (use_mips32r2_instructions) {
625 tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
626 tcg_out_opc_reg(s, OPC_SEH, ret, 0, ret);
627 } else {
628 /* ret and arg can't be register at */
629 if (ret == TCG_TMP0 || arg == TCG_TMP0) {
630 tcg_abort();
633 tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8);
634 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
635 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
636 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
640 static void tcg_out_bswap_subr(TCGContext *s, tcg_insn_unit *sub)
642 bool ok = tcg_out_opc_jmp(s, OPC_JAL, sub);
643 tcg_debug_assert(ok);
646 static void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg)
648 if (use_mips32r2_instructions) {
649 tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
650 tcg_out_opc_sa(s, OPC_ROTR, ret, ret, 16);
651 } else {
652 tcg_out_bswap_subr(s, bswap32_addr);
653 /* delay slot -- never omit the insn, like tcg_out_mov might. */
654 tcg_out_opc_reg(s, OPC_OR, TCG_TMP0, arg, TCG_REG_ZERO);
655 tcg_out_mov(s, TCG_TYPE_I32, ret, TCG_TMP3);
659 static void tcg_out_bswap32u(TCGContext *s, TCGReg ret, TCGReg arg)
661 if (use_mips32r2_instructions) {
662 tcg_out_opc_reg(s, OPC_DSBH, ret, 0, arg);
663 tcg_out_opc_reg(s, OPC_DSHD, ret, 0, ret);
664 tcg_out_dsrl(s, ret, ret, 32);
665 } else {
666 tcg_out_bswap_subr(s, bswap32u_addr);
667 /* delay slot -- never omit the insn, like tcg_out_mov might. */
668 tcg_out_opc_reg(s, OPC_OR, TCG_TMP0, arg, TCG_REG_ZERO);
669 tcg_out_mov(s, TCG_TYPE_I32, ret, TCG_TMP3);
673 static void tcg_out_bswap64(TCGContext *s, TCGReg ret, TCGReg arg)
675 if (use_mips32r2_instructions) {
676 tcg_out_opc_reg(s, OPC_DSBH, ret, 0, arg);
677 tcg_out_opc_reg(s, OPC_DSHD, ret, 0, ret);
678 } else {
679 tcg_out_bswap_subr(s, bswap64_addr);
680 /* delay slot -- never omit the insn, like tcg_out_mov might. */
681 tcg_out_opc_reg(s, OPC_OR, TCG_TMP0, arg, TCG_REG_ZERO);
682 tcg_out_mov(s, TCG_TYPE_I32, ret, TCG_TMP3);
686 static inline void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg)
688 if (use_mips32r2_instructions) {
689 tcg_out_opc_reg(s, OPC_SEB, ret, 0, arg);
690 } else {
691 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
692 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 24);
696 static inline void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg)
698 if (use_mips32r2_instructions) {
699 tcg_out_opc_reg(s, OPC_SEH, ret, 0, arg);
700 } else {
701 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 16);
702 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
706 static inline void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg)
708 if (use_mips32r2_instructions) {
709 tcg_out_opc_bf(s, OPC_DEXT, ret, arg, 31, 0);
710 } else {
711 tcg_out_dsll(s, ret, arg, 32);
712 tcg_out_dsrl(s, ret, ret, 32);
716 static void tcg_out_ldst(TCGContext *s, MIPSInsn opc, TCGReg data,
717 TCGReg addr, intptr_t ofs)
719 int16_t lo = ofs;
720 if (ofs != lo) {
721 tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, ofs - lo);
722 if (addr != TCG_REG_ZERO) {
723 tcg_out_opc_reg(s, ALIAS_PADD, TCG_TMP0, TCG_TMP0, addr);
725 addr = TCG_TMP0;
727 tcg_out_opc_imm(s, opc, data, addr, lo);
730 static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
731 TCGReg arg1, intptr_t arg2)
733 MIPSInsn opc = OPC_LD;
734 if (TCG_TARGET_REG_BITS == 32 || type == TCG_TYPE_I32) {
735 opc = OPC_LW;
737 tcg_out_ldst(s, opc, arg, arg1, arg2);
740 static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
741 TCGReg arg1, intptr_t arg2)
743 MIPSInsn opc = OPC_SD;
744 if (TCG_TARGET_REG_BITS == 32 || type == TCG_TYPE_I32) {
745 opc = OPC_SW;
747 tcg_out_ldst(s, opc, arg, arg1, arg2);
750 static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
751 TCGReg base, intptr_t ofs)
753 if (val == 0) {
754 tcg_out_st(s, type, TCG_REG_ZERO, base, ofs);
755 return true;
757 return false;
760 static void tcg_out_addsub2(TCGContext *s, TCGReg rl, TCGReg rh, TCGReg al,
761 TCGReg ah, TCGArg bl, TCGArg bh, bool cbl,
762 bool cbh, bool is_sub)
764 TCGReg th = TCG_TMP1;
766 /* If we have a negative constant such that negating it would
767 make the high part zero, we can (usually) eliminate one insn. */
768 if (cbl && cbh && bh == -1 && bl != 0) {
769 bl = -bl;
770 bh = 0;
771 is_sub = !is_sub;
774 /* By operating on the high part first, we get to use the final
775 carry operation to move back from the temporary. */
776 if (!cbh) {
777 tcg_out_opc_reg(s, (is_sub ? OPC_SUBU : OPC_ADDU), th, ah, bh);
778 } else if (bh != 0 || ah == rl) {
779 tcg_out_opc_imm(s, OPC_ADDIU, th, ah, (is_sub ? -bh : bh));
780 } else {
781 th = ah;
784 /* Note that tcg optimization should eliminate the bl == 0 case. */
785 if (is_sub) {
786 if (cbl) {
787 tcg_out_opc_imm(s, OPC_SLTIU, TCG_TMP0, al, bl);
788 tcg_out_opc_imm(s, OPC_ADDIU, rl, al, -bl);
789 } else {
790 tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, al, bl);
791 tcg_out_opc_reg(s, OPC_SUBU, rl, al, bl);
793 tcg_out_opc_reg(s, OPC_SUBU, rh, th, TCG_TMP0);
794 } else {
795 if (cbl) {
796 tcg_out_opc_imm(s, OPC_ADDIU, rl, al, bl);
797 tcg_out_opc_imm(s, OPC_SLTIU, TCG_TMP0, rl, bl);
798 } else if (rl == al && rl == bl) {
799 tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, al, 31);
800 tcg_out_opc_reg(s, OPC_ADDU, rl, al, bl);
801 } else {
802 tcg_out_opc_reg(s, OPC_ADDU, rl, al, bl);
803 tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, rl, (rl == bl ? al : bl));
805 tcg_out_opc_reg(s, OPC_ADDU, rh, th, TCG_TMP0);
809 /* Bit 0 set if inversion required; bit 1 set if swapping required. */
810 #define MIPS_CMP_INV 1
811 #define MIPS_CMP_SWAP 2
813 static const uint8_t mips_cmp_map[16] = {
814 [TCG_COND_LT] = 0,
815 [TCG_COND_LTU] = 0,
816 [TCG_COND_GE] = MIPS_CMP_INV,
817 [TCG_COND_GEU] = MIPS_CMP_INV,
818 [TCG_COND_LE] = MIPS_CMP_INV | MIPS_CMP_SWAP,
819 [TCG_COND_LEU] = MIPS_CMP_INV | MIPS_CMP_SWAP,
820 [TCG_COND_GT] = MIPS_CMP_SWAP,
821 [TCG_COND_GTU] = MIPS_CMP_SWAP,
824 static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
825 TCGReg arg1, TCGReg arg2)
827 MIPSInsn s_opc = OPC_SLTU;
828 int cmp_map;
830 switch (cond) {
831 case TCG_COND_EQ:
832 if (arg2 != 0) {
833 tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
834 arg1 = ret;
836 tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, 1);
837 break;
839 case TCG_COND_NE:
840 if (arg2 != 0) {
841 tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
842 arg1 = ret;
844 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg1);
845 break;
847 case TCG_COND_LT:
848 case TCG_COND_GE:
849 case TCG_COND_LE:
850 case TCG_COND_GT:
851 s_opc = OPC_SLT;
852 /* FALLTHRU */
854 case TCG_COND_LTU:
855 case TCG_COND_GEU:
856 case TCG_COND_LEU:
857 case TCG_COND_GTU:
858 cmp_map = mips_cmp_map[cond];
859 if (cmp_map & MIPS_CMP_SWAP) {
860 TCGReg t = arg1;
861 arg1 = arg2;
862 arg2 = t;
864 tcg_out_opc_reg(s, s_opc, ret, arg1, arg2);
865 if (cmp_map & MIPS_CMP_INV) {
866 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
868 break;
870 default:
871 tcg_abort();
872 break;
876 static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
877 TCGReg arg2, TCGLabel *l)
879 static const MIPSInsn b_zero[16] = {
880 [TCG_COND_LT] = OPC_BLTZ,
881 [TCG_COND_GT] = OPC_BGTZ,
882 [TCG_COND_LE] = OPC_BLEZ,
883 [TCG_COND_GE] = OPC_BGEZ,
886 MIPSInsn s_opc = OPC_SLTU;
887 MIPSInsn b_opc;
888 int cmp_map;
890 switch (cond) {
891 case TCG_COND_EQ:
892 b_opc = OPC_BEQ;
893 break;
894 case TCG_COND_NE:
895 b_opc = OPC_BNE;
896 break;
898 case TCG_COND_LT:
899 case TCG_COND_GT:
900 case TCG_COND_LE:
901 case TCG_COND_GE:
902 if (arg2 == 0) {
903 b_opc = b_zero[cond];
904 arg2 = arg1;
905 arg1 = 0;
906 break;
908 s_opc = OPC_SLT;
909 /* FALLTHRU */
911 case TCG_COND_LTU:
912 case TCG_COND_GTU:
913 case TCG_COND_LEU:
914 case TCG_COND_GEU:
915 cmp_map = mips_cmp_map[cond];
916 if (cmp_map & MIPS_CMP_SWAP) {
917 TCGReg t = arg1;
918 arg1 = arg2;
919 arg2 = t;
921 tcg_out_opc_reg(s, s_opc, TCG_TMP0, arg1, arg2);
922 b_opc = (cmp_map & MIPS_CMP_INV ? OPC_BEQ : OPC_BNE);
923 arg1 = TCG_TMP0;
924 arg2 = TCG_REG_ZERO;
925 break;
927 default:
928 tcg_abort();
929 break;
932 tcg_out_opc_br(s, b_opc, arg1, arg2);
933 if (l->has_value) {
934 reloc_pc16(s->code_ptr - 1, l->u.value_ptr);
935 } else {
936 tcg_out_reloc(s, s->code_ptr - 1, R_MIPS_PC16, l, 0);
938 tcg_out_nop(s);
941 static TCGReg tcg_out_reduce_eq2(TCGContext *s, TCGReg tmp0, TCGReg tmp1,
942 TCGReg al, TCGReg ah,
943 TCGReg bl, TCGReg bh)
945 /* Merge highpart comparison into AH. */
946 if (bh != 0) {
947 if (ah != 0) {
948 tcg_out_opc_reg(s, OPC_XOR, tmp0, ah, bh);
949 ah = tmp0;
950 } else {
951 ah = bh;
954 /* Merge lowpart comparison into AL. */
955 if (bl != 0) {
956 if (al != 0) {
957 tcg_out_opc_reg(s, OPC_XOR, tmp1, al, bl);
958 al = tmp1;
959 } else {
960 al = bl;
963 /* Merge high and low part comparisons into AL. */
964 if (ah != 0) {
965 if (al != 0) {
966 tcg_out_opc_reg(s, OPC_OR, tmp0, ah, al);
967 al = tmp0;
968 } else {
969 al = ah;
972 return al;
975 static void tcg_out_setcond2(TCGContext *s, TCGCond cond, TCGReg ret,
976 TCGReg al, TCGReg ah, TCGReg bl, TCGReg bh)
978 TCGReg tmp0 = TCG_TMP0;
979 TCGReg tmp1 = ret;
981 tcg_debug_assert(ret != TCG_TMP0);
982 if (ret == ah || ret == bh) {
983 tcg_debug_assert(ret != TCG_TMP1);
984 tmp1 = TCG_TMP1;
987 switch (cond) {
988 case TCG_COND_EQ:
989 case TCG_COND_NE:
990 tmp1 = tcg_out_reduce_eq2(s, tmp0, tmp1, al, ah, bl, bh);
991 tcg_out_setcond(s, cond, ret, tmp1, TCG_REG_ZERO);
992 break;
994 default:
995 tcg_out_setcond(s, TCG_COND_EQ, tmp0, ah, bh);
996 tcg_out_setcond(s, tcg_unsigned_cond(cond), tmp1, al, bl);
997 tcg_out_opc_reg(s, OPC_AND, tmp1, tmp1, tmp0);
998 tcg_out_setcond(s, tcg_high_cond(cond), tmp0, ah, bh);
999 tcg_out_opc_reg(s, OPC_OR, ret, tmp1, tmp0);
1000 break;
1004 static void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGReg al, TCGReg ah,
1005 TCGReg bl, TCGReg bh, TCGLabel *l)
1007 TCGCond b_cond = TCG_COND_NE;
1008 TCGReg tmp = TCG_TMP1;
1010 /* With branches, we emit between 4 and 9 insns with 2 or 3 branches.
1011 With setcond, we emit between 3 and 10 insns and only 1 branch,
1012 which ought to get better branch prediction. */
1013 switch (cond) {
1014 case TCG_COND_EQ:
1015 case TCG_COND_NE:
1016 b_cond = cond;
1017 tmp = tcg_out_reduce_eq2(s, TCG_TMP0, TCG_TMP1, al, ah, bl, bh);
1018 break;
1020 default:
1021 /* Minimize code size by preferring a compare not requiring INV. */
1022 if (mips_cmp_map[cond] & MIPS_CMP_INV) {
1023 cond = tcg_invert_cond(cond);
1024 b_cond = TCG_COND_EQ;
1026 tcg_out_setcond2(s, cond, tmp, al, ah, bl, bh);
1027 break;
1030 tcg_out_brcond(s, b_cond, tmp, TCG_REG_ZERO, l);
1033 static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
1034 TCGReg c1, TCGReg c2, TCGReg v1, TCGReg v2)
1036 bool eqz = false;
1038 /* If one of the values is zero, put it last to match SEL*Z instructions */
1039 if (use_mips32r6_instructions && v1 == 0) {
1040 v1 = v2;
1041 v2 = 0;
1042 cond = tcg_invert_cond(cond);
1045 switch (cond) {
1046 case TCG_COND_EQ:
1047 eqz = true;
1048 /* FALLTHRU */
1049 case TCG_COND_NE:
1050 if (c2 != 0) {
1051 tcg_out_opc_reg(s, OPC_XOR, TCG_TMP0, c1, c2);
1052 c1 = TCG_TMP0;
1054 break;
1056 default:
1057 /* Minimize code size by preferring a compare not requiring INV. */
1058 if (mips_cmp_map[cond] & MIPS_CMP_INV) {
1059 cond = tcg_invert_cond(cond);
1060 eqz = true;
1062 tcg_out_setcond(s, cond, TCG_TMP0, c1, c2);
1063 c1 = TCG_TMP0;
1064 break;
1067 if (use_mips32r6_instructions) {
1068 MIPSInsn m_opc_t = eqz ? OPC_SELEQZ : OPC_SELNEZ;
1069 MIPSInsn m_opc_f = eqz ? OPC_SELNEZ : OPC_SELEQZ;
1071 if (v2 != 0) {
1072 tcg_out_opc_reg(s, m_opc_f, TCG_TMP1, v2, c1);
1074 tcg_out_opc_reg(s, m_opc_t, ret, v1, c1);
1075 if (v2 != 0) {
1076 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP1);
1078 } else {
1079 MIPSInsn m_opc = eqz ? OPC_MOVZ : OPC_MOVN;
1081 tcg_out_opc_reg(s, m_opc, ret, v1, c1);
1083 /* This should be guaranteed via constraints */
1084 tcg_debug_assert(v2 == ret);
1088 static void tcg_out_call_int(TCGContext *s, tcg_insn_unit *arg, bool tail)
1090 /* Note that the ABI requires the called function's address to be
1091 loaded into T9, even if a direct branch is in range. */
1092 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T9, (uintptr_t)arg);
1094 /* But do try a direct branch, allowing the cpu better insn prefetch. */
1095 if (tail) {
1096 if (!tcg_out_opc_jmp(s, OPC_J, arg)) {
1097 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_T9, 0);
1099 } else {
1100 if (!tcg_out_opc_jmp(s, OPC_JAL, arg)) {
1101 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
1106 static void tcg_out_call(TCGContext *s, tcg_insn_unit *arg)
1108 tcg_out_call_int(s, arg, false);
1109 tcg_out_nop(s);
1112 #if defined(CONFIG_SOFTMMU)
1113 #include "tcg-ldst.inc.c"
1115 static void * const qemu_ld_helpers[16] = {
1116 [MO_UB] = helper_ret_ldub_mmu,
1117 [MO_SB] = helper_ret_ldsb_mmu,
1118 [MO_LEUW] = helper_le_lduw_mmu,
1119 [MO_LESW] = helper_le_ldsw_mmu,
1120 [MO_LEUL] = helper_le_ldul_mmu,
1121 [MO_LEQ] = helper_le_ldq_mmu,
1122 [MO_BEUW] = helper_be_lduw_mmu,
1123 [MO_BESW] = helper_be_ldsw_mmu,
1124 [MO_BEUL] = helper_be_ldul_mmu,
1125 [MO_BEQ] = helper_be_ldq_mmu,
1126 #if TCG_TARGET_REG_BITS == 64
1127 [MO_LESL] = helper_le_ldsl_mmu,
1128 [MO_BESL] = helper_be_ldsl_mmu,
1129 #endif
1132 static void * const qemu_st_helpers[16] = {
1133 [MO_UB] = helper_ret_stb_mmu,
1134 [MO_LEUW] = helper_le_stw_mmu,
1135 [MO_LEUL] = helper_le_stl_mmu,
1136 [MO_LEQ] = helper_le_stq_mmu,
1137 [MO_BEUW] = helper_be_stw_mmu,
1138 [MO_BEUL] = helper_be_stl_mmu,
1139 [MO_BEQ] = helper_be_stq_mmu,
1142 /* Helper routines for marshalling helper function arguments into
1143 * the correct registers and stack.
1144 * I is where we want to put this argument, and is updated and returned
1145 * for the next call. ARG is the argument itself.
1147 * We provide routines for arguments which are: immediate, 32 bit
1148 * value in register, 16 and 8 bit values in register (which must be zero
1149 * extended before use) and 64 bit value in a lo:hi register pair.
1152 static int tcg_out_call_iarg_reg(TCGContext *s, int i, TCGReg arg)
1154 if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
1155 tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[i], arg);
1156 } else {
1157 /* For N32 and N64, the initial offset is different. But there
1158 we also have 8 argument register so we don't run out here. */
1159 tcg_debug_assert(TCG_TARGET_REG_BITS == 32);
1160 tcg_out_st(s, TCG_TYPE_REG, arg, TCG_REG_SP, 4 * i);
1162 return i + 1;
1165 static int tcg_out_call_iarg_reg8(TCGContext *s, int i, TCGReg arg)
1167 TCGReg tmp = TCG_TMP0;
1168 if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
1169 tmp = tcg_target_call_iarg_regs[i];
1171 tcg_out_opc_imm(s, OPC_ANDI, tmp, arg, 0xff);
1172 return tcg_out_call_iarg_reg(s, i, tmp);
1175 static int tcg_out_call_iarg_reg16(TCGContext *s, int i, TCGReg arg)
1177 TCGReg tmp = TCG_TMP0;
1178 if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
1179 tmp = tcg_target_call_iarg_regs[i];
1181 tcg_out_opc_imm(s, OPC_ANDI, tmp, arg, 0xffff);
1182 return tcg_out_call_iarg_reg(s, i, tmp);
1185 static int tcg_out_call_iarg_imm(TCGContext *s, int i, TCGArg arg)
1187 TCGReg tmp = TCG_TMP0;
1188 if (arg == 0) {
1189 tmp = TCG_REG_ZERO;
1190 } else {
1191 if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
1192 tmp = tcg_target_call_iarg_regs[i];
1194 tcg_out_movi(s, TCG_TYPE_REG, tmp, arg);
1196 return tcg_out_call_iarg_reg(s, i, tmp);
1199 static int tcg_out_call_iarg_reg2(TCGContext *s, int i, TCGReg al, TCGReg ah)
1201 tcg_debug_assert(TCG_TARGET_REG_BITS == 32);
1202 i = (i + 1) & ~1;
1203 i = tcg_out_call_iarg_reg(s, i, (MIPS_BE ? ah : al));
1204 i = tcg_out_call_iarg_reg(s, i, (MIPS_BE ? al : ah));
1205 return i;
1208 /* Perform the tlb comparison operation. The complete host address is
1209 placed in BASE. Clobbers TMP0, TMP1, TMP2, A0. */
1210 static void tcg_out_tlb_load(TCGContext *s, TCGReg base, TCGReg addrl,
1211 TCGReg addrh, TCGMemOpIdx oi,
1212 tcg_insn_unit *label_ptr[2], bool is_load)
1214 TCGMemOp opc = get_memop(oi);
1215 unsigned s_bits = opc & MO_SIZE;
1216 unsigned a_bits = get_alignment_bits(opc);
1217 target_ulong mask;
1218 int mem_index = get_mmuidx(oi);
1219 int cmp_off
1220 = (is_load
1221 ? offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)
1222 : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write));
1223 int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend);
1225 tcg_out_opc_sa(s, ALIAS_TSRL, TCG_REG_A0, addrl,
1226 TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
1227 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0,
1228 (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
1229 tcg_out_opc_reg(s, ALIAS_PADD, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
1231 /* Compensate for very large offsets. */
1232 while (add_off >= 0x8000) {
1233 /* Most target env are smaller than 32k, but a few are larger than 64k,
1234 * so handle an arbitrarily large offset.
1236 tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_A0, TCG_REG_A0, 0x7ff0);
1237 cmp_off -= 0x7ff0;
1238 add_off -= 0x7ff0;
1241 /* We don't currently support unaligned accesses.
1242 We could do so with mips32r6. */
1243 if (a_bits < s_bits) {
1244 a_bits = s_bits;
1247 mask = (target_ulong)TARGET_PAGE_MASK | ((1 << a_bits) - 1);
1249 /* Load the (low half) tlb comparator. Mask the page bits, keeping the
1250 alignment bits to compare against. */
1251 if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
1252 tcg_out_ld(s, TCG_TYPE_I32, TCG_TMP0, TCG_REG_A0, cmp_off + LO_OFF);
1253 tcg_out_movi(s, TCG_TYPE_I32, TCG_TMP1, mask);
1254 } else {
1255 tcg_out_ldst(s,
1256 (TARGET_LONG_BITS == 64 ? OPC_LD
1257 : TCG_TARGET_REG_BITS == 64 ? OPC_LWU : OPC_LW),
1258 TCG_TMP0, TCG_REG_A0, cmp_off);
1259 tcg_out_movi(s, TCG_TYPE_TL, TCG_TMP1, mask);
1260 /* No second compare is required here;
1261 load the tlb addend for the fast path. */
1262 tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP2, TCG_REG_A0, add_off);
1264 tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, addrl);
1266 /* Zero extend a 32-bit guest address for a 64-bit host. */
1267 if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
1268 tcg_out_ext32u(s, base, addrl);
1269 addrl = base;
1272 label_ptr[0] = s->code_ptr;
1273 tcg_out_opc_br(s, OPC_BNE, TCG_TMP1, TCG_TMP0);
1275 /* Load and test the high half tlb comparator. */
1276 if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
1277 /* delay slot */
1278 tcg_out_ld(s, TCG_TYPE_I32, TCG_TMP0, TCG_REG_A0, cmp_off + HI_OFF);
1280 /* Load the tlb addend for the fast path. */
1281 tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP2, TCG_REG_A0, add_off);
1283 label_ptr[1] = s->code_ptr;
1284 tcg_out_opc_br(s, OPC_BNE, addrh, TCG_TMP0);
1287 /* delay slot */
1288 tcg_out_opc_reg(s, ALIAS_PADD, base, TCG_TMP2, addrl);
1291 static void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOpIdx oi,
1292 TCGType ext,
1293 TCGReg datalo, TCGReg datahi,
1294 TCGReg addrlo, TCGReg addrhi,
1295 void *raddr, tcg_insn_unit *label_ptr[2])
1297 TCGLabelQemuLdst *label = new_ldst_label(s);
1299 label->is_ld = is_ld;
1300 label->oi = oi;
1301 label->type = ext;
1302 label->datalo_reg = datalo;
1303 label->datahi_reg = datahi;
1304 label->addrlo_reg = addrlo;
1305 label->addrhi_reg = addrhi;
1306 label->raddr = raddr;
1307 label->label_ptr[0] = label_ptr[0];
1308 if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
1309 label->label_ptr[1] = label_ptr[1];
1313 static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1315 TCGMemOpIdx oi = l->oi;
1316 TCGMemOp opc = get_memop(oi);
1317 TCGReg v0;
1318 int i;
1320 /* resolve label address */
1321 reloc_pc16(l->label_ptr[0], s->code_ptr);
1322 if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
1323 reloc_pc16(l->label_ptr[1], s->code_ptr);
1326 i = 1;
1327 if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
1328 i = tcg_out_call_iarg_reg2(s, i, l->addrlo_reg, l->addrhi_reg);
1329 } else {
1330 i = tcg_out_call_iarg_reg(s, i, l->addrlo_reg);
1332 i = tcg_out_call_iarg_imm(s, i, oi);
1333 i = tcg_out_call_iarg_imm(s, i, (intptr_t)l->raddr);
1334 tcg_out_call_int(s, qemu_ld_helpers[opc & (MO_BSWAP | MO_SSIZE)], false);
1335 /* delay slot */
1336 tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
1338 v0 = l->datalo_reg;
1339 if (TCG_TARGET_REG_BITS == 32 && (opc & MO_SIZE) == MO_64) {
1340 /* We eliminated V0 from the possible output registers, so it
1341 cannot be clobbered here. So we must move V1 first. */
1342 if (MIPS_BE) {
1343 tcg_out_mov(s, TCG_TYPE_I32, v0, TCG_REG_V1);
1344 v0 = l->datahi_reg;
1345 } else {
1346 tcg_out_mov(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_V1);
1350 reloc_pc16(s->code_ptr, l->raddr);
1351 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
1352 /* delay slot */
1353 if (TCG_TARGET_REG_BITS == 64 && l->type == TCG_TYPE_I32) {
1354 /* we always sign-extend 32-bit loads */
1355 tcg_out_opc_sa(s, OPC_SLL, v0, TCG_REG_V0, 0);
1356 } else {
1357 tcg_out_opc_reg(s, OPC_OR, v0, TCG_REG_V0, TCG_REG_ZERO);
1361 static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1363 TCGMemOpIdx oi = l->oi;
1364 TCGMemOp opc = get_memop(oi);
1365 TCGMemOp s_bits = opc & MO_SIZE;
1366 int i;
1368 /* resolve label address */
1369 reloc_pc16(l->label_ptr[0], s->code_ptr);
1370 if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
1371 reloc_pc16(l->label_ptr[1], s->code_ptr);
1374 i = 1;
1375 if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
1376 i = tcg_out_call_iarg_reg2(s, i, l->addrlo_reg, l->addrhi_reg);
1377 } else {
1378 i = tcg_out_call_iarg_reg(s, i, l->addrlo_reg);
1380 switch (s_bits) {
1381 case MO_8:
1382 i = tcg_out_call_iarg_reg8(s, i, l->datalo_reg);
1383 break;
1384 case MO_16:
1385 i = tcg_out_call_iarg_reg16(s, i, l->datalo_reg);
1386 break;
1387 case MO_32:
1388 i = tcg_out_call_iarg_reg(s, i, l->datalo_reg);
1389 break;
1390 case MO_64:
1391 if (TCG_TARGET_REG_BITS == 32) {
1392 i = tcg_out_call_iarg_reg2(s, i, l->datalo_reg, l->datahi_reg);
1393 } else {
1394 i = tcg_out_call_iarg_reg(s, i, l->datalo_reg);
1396 break;
1397 default:
1398 tcg_abort();
1400 i = tcg_out_call_iarg_imm(s, i, oi);
1402 /* Tail call to the store helper. Thus force the return address
1403 computation to take place in the return address register. */
1404 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RA, (intptr_t)l->raddr);
1405 i = tcg_out_call_iarg_reg(s, i, TCG_REG_RA);
1406 tcg_out_call_int(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)], true);
1407 /* delay slot */
1408 tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
1410 #endif
1412 static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi,
1413 TCGReg base, TCGMemOp opc, bool is_64)
1415 switch (opc & (MO_SSIZE | MO_BSWAP)) {
1416 case MO_UB:
1417 tcg_out_opc_imm(s, OPC_LBU, lo, base, 0);
1418 break;
1419 case MO_SB:
1420 tcg_out_opc_imm(s, OPC_LB, lo, base, 0);
1421 break;
1422 case MO_UW | MO_BSWAP:
1423 tcg_out_opc_imm(s, OPC_LHU, TCG_TMP1, base, 0);
1424 tcg_out_bswap16(s, lo, TCG_TMP1);
1425 break;
1426 case MO_UW:
1427 tcg_out_opc_imm(s, OPC_LHU, lo, base, 0);
1428 break;
1429 case MO_SW | MO_BSWAP:
1430 tcg_out_opc_imm(s, OPC_LHU, TCG_TMP1, base, 0);
1431 tcg_out_bswap16s(s, lo, TCG_TMP1);
1432 break;
1433 case MO_SW:
1434 tcg_out_opc_imm(s, OPC_LH, lo, base, 0);
1435 break;
1436 case MO_UL | MO_BSWAP:
1437 if (TCG_TARGET_REG_BITS == 64 && is_64) {
1438 if (use_mips32r2_instructions) {
1439 tcg_out_opc_imm(s, OPC_LWU, lo, base, 0);
1440 tcg_out_bswap32u(s, lo, lo);
1441 } else {
1442 tcg_out_bswap_subr(s, bswap32u_addr);
1443 /* delay slot */
1444 tcg_out_opc_imm(s, OPC_LWU, TCG_TMP0, base, 0);
1445 tcg_out_mov(s, TCG_TYPE_I64, lo, TCG_TMP3);
1447 break;
1449 /* FALLTHRU */
1450 case MO_SL | MO_BSWAP:
1451 if (use_mips32r2_instructions) {
1452 tcg_out_opc_imm(s, OPC_LW, lo, base, 0);
1453 tcg_out_bswap32(s, lo, lo);
1454 } else {
1455 tcg_out_bswap_subr(s, bswap32_addr);
1456 /* delay slot */
1457 tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, base, 0);
1458 tcg_out_mov(s, TCG_TYPE_I32, lo, TCG_TMP3);
1460 break;
1461 case MO_UL:
1462 if (TCG_TARGET_REG_BITS == 64 && is_64) {
1463 tcg_out_opc_imm(s, OPC_LWU, lo, base, 0);
1464 break;
1466 /* FALLTHRU */
1467 case MO_SL:
1468 tcg_out_opc_imm(s, OPC_LW, lo, base, 0);
1469 break;
1470 case MO_Q | MO_BSWAP:
1471 if (TCG_TARGET_REG_BITS == 64) {
1472 if (use_mips32r2_instructions) {
1473 tcg_out_opc_imm(s, OPC_LD, lo, base, 0);
1474 tcg_out_bswap64(s, lo, lo);
1475 } else {
1476 tcg_out_bswap_subr(s, bswap64_addr);
1477 /* delay slot */
1478 tcg_out_opc_imm(s, OPC_LD, TCG_TMP0, base, 0);
1479 tcg_out_mov(s, TCG_TYPE_I64, lo, TCG_TMP3);
1481 } else if (use_mips32r2_instructions) {
1482 tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, base, 0);
1483 tcg_out_opc_imm(s, OPC_LW, TCG_TMP1, base, 4);
1484 tcg_out_opc_reg(s, OPC_WSBH, TCG_TMP0, 0, TCG_TMP0);
1485 tcg_out_opc_reg(s, OPC_WSBH, TCG_TMP1, 0, TCG_TMP1);
1486 tcg_out_opc_sa(s, OPC_ROTR, MIPS_BE ? lo : hi, TCG_TMP0, 16);
1487 tcg_out_opc_sa(s, OPC_ROTR, MIPS_BE ? hi : lo, TCG_TMP1, 16);
1488 } else {
1489 tcg_out_bswap_subr(s, bswap32_addr);
1490 /* delay slot */
1491 tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, base, 0);
1492 tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, base, 4);
1493 tcg_out_bswap_subr(s, bswap32_addr);
1494 /* delay slot */
1495 tcg_out_mov(s, TCG_TYPE_I32, MIPS_BE ? lo : hi, TCG_TMP3);
1496 tcg_out_mov(s, TCG_TYPE_I32, MIPS_BE ? hi : lo, TCG_TMP3);
1498 break;
1499 case MO_Q:
1500 /* Prefer to load from offset 0 first, but allow for overlap. */
1501 if (TCG_TARGET_REG_BITS == 64) {
1502 tcg_out_opc_imm(s, OPC_LD, lo, base, 0);
1503 } else if (MIPS_BE ? hi != base : lo == base) {
1504 tcg_out_opc_imm(s, OPC_LW, hi, base, HI_OFF);
1505 tcg_out_opc_imm(s, OPC_LW, lo, base, LO_OFF);
1506 } else {
1507 tcg_out_opc_imm(s, OPC_LW, lo, base, LO_OFF);
1508 tcg_out_opc_imm(s, OPC_LW, hi, base, HI_OFF);
1510 break;
1511 default:
1512 tcg_abort();
1516 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64)
1518 TCGReg addr_regl, addr_regh __attribute__((unused));
1519 TCGReg data_regl, data_regh;
1520 TCGMemOpIdx oi;
1521 TCGMemOp opc;
1522 #if defined(CONFIG_SOFTMMU)
1523 tcg_insn_unit *label_ptr[2];
1524 #endif
1525 TCGReg base = TCG_REG_A0;
1527 data_regl = *args++;
1528 data_regh = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0);
1529 addr_regl = *args++;
1530 addr_regh = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0);
1531 oi = *args++;
1532 opc = get_memop(oi);
1534 #if defined(CONFIG_SOFTMMU)
1535 tcg_out_tlb_load(s, base, addr_regl, addr_regh, oi, label_ptr, 1);
1536 tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc, is_64);
1537 add_qemu_ldst_label(s, 1, oi,
1538 (is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32),
1539 data_regl, data_regh, addr_regl, addr_regh,
1540 s->code_ptr, label_ptr);
1541 #else
1542 if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
1543 tcg_out_ext32u(s, base, addr_regl);
1544 addr_regl = base;
1546 if (guest_base == 0 && data_regl != addr_regl) {
1547 base = addr_regl;
1548 } else if (guest_base == (int16_t)guest_base) {
1549 tcg_out_opc_imm(s, ALIAS_PADDI, base, addr_regl, guest_base);
1550 } else {
1551 tcg_out_opc_reg(s, ALIAS_PADD, base, TCG_GUEST_BASE_REG, addr_regl);
1553 tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc, is_64);
1554 #endif
1557 static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg lo, TCGReg hi,
1558 TCGReg base, TCGMemOp opc)
1560 /* Don't clutter the code below with checks to avoid bswapping ZERO. */
1561 if ((lo | hi) == 0) {
1562 opc &= ~MO_BSWAP;
1565 switch (opc & (MO_SIZE | MO_BSWAP)) {
1566 case MO_8:
1567 tcg_out_opc_imm(s, OPC_SB, lo, base, 0);
1568 break;
1570 case MO_16 | MO_BSWAP:
1571 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, lo, 0xffff);
1572 tcg_out_bswap16(s, TCG_TMP1, TCG_TMP1);
1573 lo = TCG_TMP1;
1574 /* FALLTHRU */
1575 case MO_16:
1576 tcg_out_opc_imm(s, OPC_SH, lo, base, 0);
1577 break;
1579 case MO_32 | MO_BSWAP:
1580 tcg_out_bswap32(s, TCG_TMP3, lo);
1581 lo = TCG_TMP3;
1582 /* FALLTHRU */
1583 case MO_32:
1584 tcg_out_opc_imm(s, OPC_SW, lo, base, 0);
1585 break;
1587 case MO_64 | MO_BSWAP:
1588 if (TCG_TARGET_REG_BITS == 64) {
1589 tcg_out_bswap64(s, TCG_TMP3, lo);
1590 tcg_out_opc_imm(s, OPC_SD, TCG_TMP3, base, 0);
1591 } else if (use_mips32r2_instructions) {
1592 tcg_out_opc_reg(s, OPC_WSBH, TCG_TMP0, 0, MIPS_BE ? lo : hi);
1593 tcg_out_opc_reg(s, OPC_WSBH, TCG_TMP1, 0, MIPS_BE ? hi : lo);
1594 tcg_out_opc_sa(s, OPC_ROTR, TCG_TMP0, TCG_TMP0, 16);
1595 tcg_out_opc_sa(s, OPC_ROTR, TCG_TMP1, TCG_TMP1, 16);
1596 tcg_out_opc_imm(s, OPC_SW, TCG_TMP0, base, 0);
1597 tcg_out_opc_imm(s, OPC_SW, TCG_TMP1, base, 4);
1598 } else {
1599 tcg_out_bswap32(s, TCG_TMP3, MIPS_BE ? lo : hi);
1600 tcg_out_opc_imm(s, OPC_SW, TCG_TMP3, base, 0);
1601 tcg_out_bswap32(s, TCG_TMP3, MIPS_BE ? hi : lo);
1602 tcg_out_opc_imm(s, OPC_SW, TCG_TMP3, base, 4);
1604 break;
1605 case MO_64:
1606 if (TCG_TARGET_REG_BITS == 64) {
1607 tcg_out_opc_imm(s, OPC_SD, lo, base, 0);
1608 } else {
1609 tcg_out_opc_imm(s, OPC_SW, MIPS_BE ? hi : lo, base, 0);
1610 tcg_out_opc_imm(s, OPC_SW, MIPS_BE ? lo : hi, base, 4);
1612 break;
1614 default:
1615 tcg_abort();
1619 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64)
1621 TCGReg addr_regl, addr_regh __attribute__((unused));
1622 TCGReg data_regl, data_regh;
1623 TCGMemOpIdx oi;
1624 TCGMemOp opc;
1625 #if defined(CONFIG_SOFTMMU)
1626 tcg_insn_unit *label_ptr[2];
1627 #endif
1628 TCGReg base = TCG_REG_A0;
1630 data_regl = *args++;
1631 data_regh = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0);
1632 addr_regl = *args++;
1633 addr_regh = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0);
1634 oi = *args++;
1635 opc = get_memop(oi);
1637 #if defined(CONFIG_SOFTMMU)
1638 tcg_out_tlb_load(s, base, addr_regl, addr_regh, oi, label_ptr, 0);
1639 tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc);
1640 add_qemu_ldst_label(s, 0, oi,
1641 (is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32),
1642 data_regl, data_regh, addr_regl, addr_regh,
1643 s->code_ptr, label_ptr);
1644 #else
1645 base = TCG_REG_A0;
1646 if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
1647 tcg_out_ext32u(s, base, addr_regl);
1648 addr_regl = base;
1650 if (guest_base == 0) {
1651 base = addr_regl;
1652 } else if (guest_base == (int16_t)guest_base) {
1653 tcg_out_opc_imm(s, ALIAS_PADDI, base, addr_regl, guest_base);
1654 } else {
1655 tcg_out_opc_reg(s, ALIAS_PADD, base, TCG_GUEST_BASE_REG, addr_regl);
1657 tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc);
1658 #endif
1661 static void tcg_out_mb(TCGContext *s, TCGArg a0)
1663 static const MIPSInsn sync[] = {
1664 /* Note that SYNC_MB is a slightly weaker than SYNC 0,
1665 as the former is an ordering barrier and the latter
1666 is a completion barrier. */
1667 [0 ... TCG_MO_ALL] = OPC_SYNC_MB,
1668 [TCG_MO_LD_LD] = OPC_SYNC_RMB,
1669 [TCG_MO_ST_ST] = OPC_SYNC_WMB,
1670 [TCG_MO_LD_ST] = OPC_SYNC_RELEASE,
1671 [TCG_MO_LD_ST | TCG_MO_ST_ST] = OPC_SYNC_RELEASE,
1672 [TCG_MO_LD_ST | TCG_MO_LD_LD] = OPC_SYNC_ACQUIRE,
1674 tcg_out32(s, sync[a0 & TCG_MO_ALL]);
1677 static void tcg_out_clz(TCGContext *s, MIPSInsn opcv2, MIPSInsn opcv6,
1678 int width, TCGReg a0, TCGReg a1, TCGArg a2)
1680 if (use_mips32r6_instructions) {
1681 if (a2 == width) {
1682 tcg_out_opc_reg(s, opcv6, a0, a1, 0);
1683 } else {
1684 tcg_out_opc_reg(s, opcv6, TCG_TMP0, a1, 0);
1685 tcg_out_movcond(s, TCG_COND_EQ, a0, a1, 0, a2, TCG_TMP0);
1687 } else {
1688 if (a2 == width) {
1689 tcg_out_opc_reg(s, opcv2, a0, a1, a1);
1690 } else if (a0 == a2) {
1691 tcg_out_opc_reg(s, opcv2, TCG_TMP0, a1, a1);
1692 tcg_out_opc_reg(s, OPC_MOVN, a0, TCG_TMP0, a1);
1693 } else if (a0 != a1) {
1694 tcg_out_opc_reg(s, opcv2, a0, a1, a1);
1695 tcg_out_opc_reg(s, OPC_MOVZ, a0, a2, a1);
1696 } else {
1697 tcg_out_opc_reg(s, opcv2, TCG_TMP0, a1, a1);
1698 tcg_out_opc_reg(s, OPC_MOVZ, TCG_TMP0, a2, a1);
1699 tcg_out_mov(s, TCG_TYPE_REG, a0, TCG_TMP0);
1704 static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1705 const TCGArg *args, const int *const_args)
1707 MIPSInsn i1, i2;
1708 TCGArg a0, a1, a2;
1709 int c2;
1711 a0 = args[0];
1712 a1 = args[1];
1713 a2 = args[2];
1714 c2 = const_args[2];
1716 switch (opc) {
1717 case INDEX_op_exit_tb:
1719 TCGReg b0 = TCG_REG_ZERO;
1721 a0 = (intptr_t)a0;
1722 if (a0 & ~0xffff) {
1723 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, a0 & ~0xffff);
1724 b0 = TCG_REG_V0;
1726 if (!tcg_out_opc_jmp(s, OPC_J, tb_ret_addr)) {
1727 tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0,
1728 (uintptr_t)tb_ret_addr);
1729 tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
1731 tcg_out_opc_imm(s, OPC_ORI, TCG_REG_V0, b0, a0 & 0xffff);
1733 break;
1734 case INDEX_op_goto_tb:
1735 if (s->tb_jmp_insn_offset) {
1736 /* direct jump method */
1737 s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s);
1738 /* Avoid clobbering the address during retranslation. */
1739 tcg_out32(s, OPC_J | (*(uint32_t *)s->code_ptr & 0x3ffffff));
1740 } else {
1741 /* indirect jump method */
1742 tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_REG_ZERO,
1743 (uintptr_t)(s->tb_jmp_target_addr + a0));
1744 tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
1746 tcg_out_nop(s);
1747 s->tb_jmp_reset_offset[a0] = tcg_current_code_size(s);
1748 break;
1749 case INDEX_op_goto_ptr:
1750 /* jmp to the given host address (could be epilogue) */
1751 tcg_out_opc_reg(s, OPC_JR, 0, a0, 0);
1752 tcg_out_nop(s);
1753 break;
1754 case INDEX_op_br:
1755 tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO,
1756 arg_label(a0));
1757 break;
1759 case INDEX_op_ld8u_i32:
1760 case INDEX_op_ld8u_i64:
1761 i1 = OPC_LBU;
1762 goto do_ldst;
1763 case INDEX_op_ld8s_i32:
1764 case INDEX_op_ld8s_i64:
1765 i1 = OPC_LB;
1766 goto do_ldst;
1767 case INDEX_op_ld16u_i32:
1768 case INDEX_op_ld16u_i64:
1769 i1 = OPC_LHU;
1770 goto do_ldst;
1771 case INDEX_op_ld16s_i32:
1772 case INDEX_op_ld16s_i64:
1773 i1 = OPC_LH;
1774 goto do_ldst;
1775 case INDEX_op_ld_i32:
1776 case INDEX_op_ld32s_i64:
1777 i1 = OPC_LW;
1778 goto do_ldst;
1779 case INDEX_op_ld32u_i64:
1780 i1 = OPC_LWU;
1781 goto do_ldst;
1782 case INDEX_op_ld_i64:
1783 i1 = OPC_LD;
1784 goto do_ldst;
1785 case INDEX_op_st8_i32:
1786 case INDEX_op_st8_i64:
1787 i1 = OPC_SB;
1788 goto do_ldst;
1789 case INDEX_op_st16_i32:
1790 case INDEX_op_st16_i64:
1791 i1 = OPC_SH;
1792 goto do_ldst;
1793 case INDEX_op_st_i32:
1794 case INDEX_op_st32_i64:
1795 i1 = OPC_SW;
1796 goto do_ldst;
1797 case INDEX_op_st_i64:
1798 i1 = OPC_SD;
1799 do_ldst:
1800 tcg_out_ldst(s, i1, a0, a1, a2);
1801 break;
1803 case INDEX_op_add_i32:
1804 i1 = OPC_ADDU, i2 = OPC_ADDIU;
1805 goto do_binary;
1806 case INDEX_op_add_i64:
1807 i1 = OPC_DADDU, i2 = OPC_DADDIU;
1808 goto do_binary;
1809 case INDEX_op_or_i32:
1810 case INDEX_op_or_i64:
1811 i1 = OPC_OR, i2 = OPC_ORI;
1812 goto do_binary;
1813 case INDEX_op_xor_i32:
1814 case INDEX_op_xor_i64:
1815 i1 = OPC_XOR, i2 = OPC_XORI;
1816 do_binary:
1817 if (c2) {
1818 tcg_out_opc_imm(s, i2, a0, a1, a2);
1819 break;
1821 do_binaryv:
1822 tcg_out_opc_reg(s, i1, a0, a1, a2);
1823 break;
1825 case INDEX_op_sub_i32:
1826 i1 = OPC_SUBU, i2 = OPC_ADDIU;
1827 goto do_subtract;
1828 case INDEX_op_sub_i64:
1829 i1 = OPC_DSUBU, i2 = OPC_DADDIU;
1830 do_subtract:
1831 if (c2) {
1832 tcg_out_opc_imm(s, i2, a0, a1, -a2);
1833 break;
1835 goto do_binaryv;
1836 case INDEX_op_and_i32:
1837 if (c2 && a2 != (uint16_t)a2) {
1838 int msb = ctz32(~a2) - 1;
1839 tcg_debug_assert(use_mips32r2_instructions);
1840 tcg_debug_assert(is_p2m1(a2));
1841 tcg_out_opc_bf(s, OPC_EXT, a0, a1, msb, 0);
1842 break;
1844 i1 = OPC_AND, i2 = OPC_ANDI;
1845 goto do_binary;
1846 case INDEX_op_and_i64:
1847 if (c2 && a2 != (uint16_t)a2) {
1848 int msb = ctz64(~a2) - 1;
1849 tcg_debug_assert(use_mips32r2_instructions);
1850 tcg_debug_assert(is_p2m1(a2));
1851 tcg_out_opc_bf64(s, OPC_DEXT, OPC_DEXTM, OPC_DEXTU, a0, a1, msb, 0);
1852 break;
1854 i1 = OPC_AND, i2 = OPC_ANDI;
1855 goto do_binary;
1856 case INDEX_op_nor_i32:
1857 case INDEX_op_nor_i64:
1858 i1 = OPC_NOR;
1859 goto do_binaryv;
1861 case INDEX_op_mul_i32:
1862 if (use_mips32_instructions) {
1863 tcg_out_opc_reg(s, OPC_MUL, a0, a1, a2);
1864 break;
1866 i1 = OPC_MULT, i2 = OPC_MFLO;
1867 goto do_hilo1;
1868 case INDEX_op_mulsh_i32:
1869 if (use_mips32r6_instructions) {
1870 tcg_out_opc_reg(s, OPC_MUH, a0, a1, a2);
1871 break;
1873 i1 = OPC_MULT, i2 = OPC_MFHI;
1874 goto do_hilo1;
1875 case INDEX_op_muluh_i32:
1876 if (use_mips32r6_instructions) {
1877 tcg_out_opc_reg(s, OPC_MUHU, a0, a1, a2);
1878 break;
1880 i1 = OPC_MULTU, i2 = OPC_MFHI;
1881 goto do_hilo1;
1882 case INDEX_op_div_i32:
1883 if (use_mips32r6_instructions) {
1884 tcg_out_opc_reg(s, OPC_DIV_R6, a0, a1, a2);
1885 break;
1887 i1 = OPC_DIV, i2 = OPC_MFLO;
1888 goto do_hilo1;
1889 case INDEX_op_divu_i32:
1890 if (use_mips32r6_instructions) {
1891 tcg_out_opc_reg(s, OPC_DIVU_R6, a0, a1, a2);
1892 break;
1894 i1 = OPC_DIVU, i2 = OPC_MFLO;
1895 goto do_hilo1;
1896 case INDEX_op_rem_i32:
1897 if (use_mips32r6_instructions) {
1898 tcg_out_opc_reg(s, OPC_MOD, a0, a1, a2);
1899 break;
1901 i1 = OPC_DIV, i2 = OPC_MFHI;
1902 goto do_hilo1;
1903 case INDEX_op_remu_i32:
1904 if (use_mips32r6_instructions) {
1905 tcg_out_opc_reg(s, OPC_MODU, a0, a1, a2);
1906 break;
1908 i1 = OPC_DIVU, i2 = OPC_MFHI;
1909 goto do_hilo1;
1910 case INDEX_op_mul_i64:
1911 if (use_mips32r6_instructions) {
1912 tcg_out_opc_reg(s, OPC_DMUL, a0, a1, a2);
1913 break;
1915 i1 = OPC_DMULT, i2 = OPC_MFLO;
1916 goto do_hilo1;
1917 case INDEX_op_mulsh_i64:
1918 if (use_mips32r6_instructions) {
1919 tcg_out_opc_reg(s, OPC_DMUH, a0, a1, a2);
1920 break;
1922 i1 = OPC_DMULT, i2 = OPC_MFHI;
1923 goto do_hilo1;
1924 case INDEX_op_muluh_i64:
1925 if (use_mips32r6_instructions) {
1926 tcg_out_opc_reg(s, OPC_DMUHU, a0, a1, a2);
1927 break;
1929 i1 = OPC_DMULTU, i2 = OPC_MFHI;
1930 goto do_hilo1;
1931 case INDEX_op_div_i64:
1932 if (use_mips32r6_instructions) {
1933 tcg_out_opc_reg(s, OPC_DDIV_R6, a0, a1, a2);
1934 break;
1936 i1 = OPC_DDIV, i2 = OPC_MFLO;
1937 goto do_hilo1;
1938 case INDEX_op_divu_i64:
1939 if (use_mips32r6_instructions) {
1940 tcg_out_opc_reg(s, OPC_DDIVU_R6, a0, a1, a2);
1941 break;
1943 i1 = OPC_DDIVU, i2 = OPC_MFLO;
1944 goto do_hilo1;
1945 case INDEX_op_rem_i64:
1946 if (use_mips32r6_instructions) {
1947 tcg_out_opc_reg(s, OPC_DMOD, a0, a1, a2);
1948 break;
1950 i1 = OPC_DDIV, i2 = OPC_MFHI;
1951 goto do_hilo1;
1952 case INDEX_op_remu_i64:
1953 if (use_mips32r6_instructions) {
1954 tcg_out_opc_reg(s, OPC_DMODU, a0, a1, a2);
1955 break;
1957 i1 = OPC_DDIVU, i2 = OPC_MFHI;
1958 do_hilo1:
1959 tcg_out_opc_reg(s, i1, 0, a1, a2);
1960 tcg_out_opc_reg(s, i2, a0, 0, 0);
1961 break;
1963 case INDEX_op_muls2_i32:
1964 i1 = OPC_MULT;
1965 goto do_hilo2;
1966 case INDEX_op_mulu2_i32:
1967 i1 = OPC_MULTU;
1968 goto do_hilo2;
1969 case INDEX_op_muls2_i64:
1970 i1 = OPC_DMULT;
1971 goto do_hilo2;
1972 case INDEX_op_mulu2_i64:
1973 i1 = OPC_DMULTU;
1974 do_hilo2:
1975 tcg_out_opc_reg(s, i1, 0, a2, args[3]);
1976 tcg_out_opc_reg(s, OPC_MFLO, a0, 0, 0);
1977 tcg_out_opc_reg(s, OPC_MFHI, a1, 0, 0);
1978 break;
1980 case INDEX_op_not_i32:
1981 case INDEX_op_not_i64:
1982 i1 = OPC_NOR;
1983 goto do_unary;
1984 case INDEX_op_bswap16_i32:
1985 case INDEX_op_bswap16_i64:
1986 i1 = OPC_WSBH;
1987 goto do_unary;
1988 case INDEX_op_ext8s_i32:
1989 case INDEX_op_ext8s_i64:
1990 i1 = OPC_SEB;
1991 goto do_unary;
1992 case INDEX_op_ext16s_i32:
1993 case INDEX_op_ext16s_i64:
1994 i1 = OPC_SEH;
1995 do_unary:
1996 tcg_out_opc_reg(s, i1, a0, TCG_REG_ZERO, a1);
1997 break;
1999 case INDEX_op_bswap32_i32:
2000 tcg_out_bswap32(s, a0, a1);
2001 break;
2002 case INDEX_op_bswap32_i64:
2003 tcg_out_bswap32u(s, a0, a1);
2004 break;
2005 case INDEX_op_bswap64_i64:
2006 tcg_out_bswap64(s, a0, a1);
2007 break;
2008 case INDEX_op_extrh_i64_i32:
2009 tcg_out_dsra(s, a0, a1, 32);
2010 break;
2011 case INDEX_op_ext32s_i64:
2012 case INDEX_op_ext_i32_i64:
2013 case INDEX_op_extrl_i64_i32:
2014 tcg_out_opc_sa(s, OPC_SLL, a0, a1, 0);
2015 break;
2016 case INDEX_op_ext32u_i64:
2017 case INDEX_op_extu_i32_i64:
2018 tcg_out_ext32u(s, a0, a1);
2019 break;
2021 case INDEX_op_sar_i32:
2022 i1 = OPC_SRAV, i2 = OPC_SRA;
2023 goto do_shift;
2024 case INDEX_op_shl_i32:
2025 i1 = OPC_SLLV, i2 = OPC_SLL;
2026 goto do_shift;
2027 case INDEX_op_shr_i32:
2028 i1 = OPC_SRLV, i2 = OPC_SRL;
2029 goto do_shift;
2030 case INDEX_op_rotr_i32:
2031 i1 = OPC_ROTRV, i2 = OPC_ROTR;
2032 do_shift:
2033 if (c2) {
2034 tcg_out_opc_sa(s, i2, a0, a1, a2);
2035 break;
2037 do_shiftv:
2038 tcg_out_opc_reg(s, i1, a0, a2, a1);
2039 break;
2040 case INDEX_op_rotl_i32:
2041 if (c2) {
2042 tcg_out_opc_sa(s, OPC_ROTR, a0, a1, 32 - a2);
2043 } else {
2044 tcg_out_opc_reg(s, OPC_SUBU, TCG_TMP0, TCG_REG_ZERO, a2);
2045 tcg_out_opc_reg(s, OPC_ROTRV, a0, TCG_TMP0, a1);
2047 break;
2048 case INDEX_op_sar_i64:
2049 if (c2) {
2050 tcg_out_dsra(s, a0, a1, a2);
2051 break;
2053 i1 = OPC_DSRAV;
2054 goto do_shiftv;
2055 case INDEX_op_shl_i64:
2056 if (c2) {
2057 tcg_out_dsll(s, a0, a1, a2);
2058 break;
2060 i1 = OPC_DSLLV;
2061 goto do_shiftv;
2062 case INDEX_op_shr_i64:
2063 if (c2) {
2064 tcg_out_dsrl(s, a0, a1, a2);
2065 break;
2067 i1 = OPC_DSRLV;
2068 goto do_shiftv;
2069 case INDEX_op_rotr_i64:
2070 if (c2) {
2071 tcg_out_opc_sa64(s, OPC_DROTR, OPC_DROTR32, a0, a1, a2);
2072 break;
2074 i1 = OPC_DROTRV;
2075 goto do_shiftv;
2076 case INDEX_op_rotl_i64:
2077 if (c2) {
2078 tcg_out_opc_sa64(s, OPC_DROTR, OPC_DROTR32, a0, a1, 64 - a2);
2079 } else {
2080 tcg_out_opc_reg(s, OPC_DSUBU, TCG_TMP0, TCG_REG_ZERO, a2);
2081 tcg_out_opc_reg(s, OPC_DROTRV, a0, TCG_TMP0, a1);
2083 break;
2085 case INDEX_op_clz_i32:
2086 tcg_out_clz(s, OPC_CLZ, OPC_CLZ_R6, 32, a0, a1, a2);
2087 break;
2088 case INDEX_op_clz_i64:
2089 tcg_out_clz(s, OPC_DCLZ, OPC_DCLZ_R6, 64, a0, a1, a2);
2090 break;
2092 case INDEX_op_deposit_i32:
2093 tcg_out_opc_bf(s, OPC_INS, a0, a2, args[3] + args[4] - 1, args[3]);
2094 break;
2095 case INDEX_op_deposit_i64:
2096 tcg_out_opc_bf64(s, OPC_DINS, OPC_DINSM, OPC_DINSU, a0, a2,
2097 args[3] + args[4] - 1, args[3]);
2098 break;
2099 case INDEX_op_extract_i32:
2100 tcg_out_opc_bf(s, OPC_EXT, a0, a1, args[3] - 1, a2);
2101 break;
2102 case INDEX_op_extract_i64:
2103 tcg_out_opc_bf64(s, OPC_DEXT, OPC_DEXTM, OPC_DEXTU, a0, a1,
2104 args[3] - 1, a2);
2105 break;
2107 case INDEX_op_brcond_i32:
2108 case INDEX_op_brcond_i64:
2109 tcg_out_brcond(s, a2, a0, a1, arg_label(args[3]));
2110 break;
2111 case INDEX_op_brcond2_i32:
2112 tcg_out_brcond2(s, args[4], a0, a1, a2, args[3], arg_label(args[5]));
2113 break;
2115 case INDEX_op_movcond_i32:
2116 case INDEX_op_movcond_i64:
2117 tcg_out_movcond(s, args[5], a0, a1, a2, args[3], args[4]);
2118 break;
2120 case INDEX_op_setcond_i32:
2121 case INDEX_op_setcond_i64:
2122 tcg_out_setcond(s, args[3], a0, a1, a2);
2123 break;
2124 case INDEX_op_setcond2_i32:
2125 tcg_out_setcond2(s, args[5], a0, a1, a2, args[3], args[4]);
2126 break;
2128 case INDEX_op_qemu_ld_i32:
2129 tcg_out_qemu_ld(s, args, false);
2130 break;
2131 case INDEX_op_qemu_ld_i64:
2132 tcg_out_qemu_ld(s, args, true);
2133 break;
2134 case INDEX_op_qemu_st_i32:
2135 tcg_out_qemu_st(s, args, false);
2136 break;
2137 case INDEX_op_qemu_st_i64:
2138 tcg_out_qemu_st(s, args, true);
2139 break;
2141 case INDEX_op_add2_i32:
2142 tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2143 const_args[4], const_args[5], false);
2144 break;
2145 case INDEX_op_sub2_i32:
2146 tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2147 const_args[4], const_args[5], true);
2148 break;
2150 case INDEX_op_mb:
2151 tcg_out_mb(s, a0);
2152 break;
2153 case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
2154 case INDEX_op_mov_i64:
2155 case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi. */
2156 case INDEX_op_movi_i64:
2157 case INDEX_op_call: /* Always emitted via tcg_out_call. */
2158 default:
2159 tcg_abort();
2163 static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
2165 static const TCGTargetOpDef r = { .args_ct_str = { "r" } };
2166 static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
2167 static const TCGTargetOpDef r_L = { .args_ct_str = { "r", "L" } };
2168 static const TCGTargetOpDef rZ_r = { .args_ct_str = { "rZ", "r" } };
2169 static const TCGTargetOpDef SZ_S = { .args_ct_str = { "SZ", "S" } };
2170 static const TCGTargetOpDef rZ_rZ = { .args_ct_str = { "rZ", "rZ" } };
2171 static const TCGTargetOpDef r_r_L = { .args_ct_str = { "r", "r", "L" } };
2172 static const TCGTargetOpDef r_L_L = { .args_ct_str = { "r", "L", "L" } };
2173 static const TCGTargetOpDef r_r_ri = { .args_ct_str = { "r", "r", "ri" } };
2174 static const TCGTargetOpDef r_r_rI = { .args_ct_str = { "r", "r", "rI" } };
2175 static const TCGTargetOpDef r_r_rJ = { .args_ct_str = { "r", "r", "rJ" } };
2176 static const TCGTargetOpDef SZ_S_S = { .args_ct_str = { "SZ", "S", "S" } };
2177 static const TCGTargetOpDef SZ_SZ_S
2178 = { .args_ct_str = { "SZ", "SZ", "S" } };
2179 static const TCGTargetOpDef SZ_SZ_S_S
2180 = { .args_ct_str = { "SZ", "SZ", "S", "S" } };
2181 static const TCGTargetOpDef r_rZ_rN
2182 = { .args_ct_str = { "r", "rZ", "rN" } };
2183 static const TCGTargetOpDef r_rZ_rZ
2184 = { .args_ct_str = { "r", "rZ", "rZ" } };
2185 static const TCGTargetOpDef r_r_rIK
2186 = { .args_ct_str = { "r", "r", "rIK" } };
2187 static const TCGTargetOpDef r_r_rWZ
2188 = { .args_ct_str = { "r", "r", "rWZ" } };
2189 static const TCGTargetOpDef r_r_r_r
2190 = { .args_ct_str = { "r", "r", "r", "r" } };
2191 static const TCGTargetOpDef r_r_L_L
2192 = { .args_ct_str = { "r", "r", "L", "L" } };
2193 static const TCGTargetOpDef dep
2194 = { .args_ct_str = { "r", "0", "rZ" } };
2195 static const TCGTargetOpDef movc
2196 = { .args_ct_str = { "r", "rZ", "rZ", "rZ", "0" } };
2197 static const TCGTargetOpDef movc_r6
2198 = { .args_ct_str = { "r", "rZ", "rZ", "rZ", "rZ" } };
2199 static const TCGTargetOpDef add2
2200 = { .args_ct_str = { "r", "r", "rZ", "rZ", "rN", "rN" } };
2201 static const TCGTargetOpDef br2
2202 = { .args_ct_str = { "rZ", "rZ", "rZ", "rZ" } };
2203 static const TCGTargetOpDef setc2
2204 = { .args_ct_str = { "r", "rZ", "rZ", "rZ", "rZ" } };
2206 switch (op) {
2207 case INDEX_op_goto_ptr:
2208 return &r;
2210 case INDEX_op_ld8u_i32:
2211 case INDEX_op_ld8s_i32:
2212 case INDEX_op_ld16u_i32:
2213 case INDEX_op_ld16s_i32:
2214 case INDEX_op_ld_i32:
2215 case INDEX_op_not_i32:
2216 case INDEX_op_bswap16_i32:
2217 case INDEX_op_bswap32_i32:
2218 case INDEX_op_ext8s_i32:
2219 case INDEX_op_ext16s_i32:
2220 case INDEX_op_extract_i32:
2221 case INDEX_op_ld8u_i64:
2222 case INDEX_op_ld8s_i64:
2223 case INDEX_op_ld16u_i64:
2224 case INDEX_op_ld16s_i64:
2225 case INDEX_op_ld32s_i64:
2226 case INDEX_op_ld32u_i64:
2227 case INDEX_op_ld_i64:
2228 case INDEX_op_not_i64:
2229 case INDEX_op_bswap16_i64:
2230 case INDEX_op_bswap32_i64:
2231 case INDEX_op_bswap64_i64:
2232 case INDEX_op_ext8s_i64:
2233 case INDEX_op_ext16s_i64:
2234 case INDEX_op_ext32s_i64:
2235 case INDEX_op_ext32u_i64:
2236 case INDEX_op_ext_i32_i64:
2237 case INDEX_op_extu_i32_i64:
2238 case INDEX_op_extrl_i64_i32:
2239 case INDEX_op_extrh_i64_i32:
2240 case INDEX_op_extract_i64:
2241 return &r_r;
2243 case INDEX_op_st8_i32:
2244 case INDEX_op_st16_i32:
2245 case INDEX_op_st_i32:
2246 case INDEX_op_st8_i64:
2247 case INDEX_op_st16_i64:
2248 case INDEX_op_st32_i64:
2249 case INDEX_op_st_i64:
2250 return &rZ_r;
2252 case INDEX_op_add_i32:
2253 case INDEX_op_add_i64:
2254 return &r_r_rJ;
2255 case INDEX_op_sub_i32:
2256 case INDEX_op_sub_i64:
2257 return &r_rZ_rN;
2258 case INDEX_op_mul_i32:
2259 case INDEX_op_mulsh_i32:
2260 case INDEX_op_muluh_i32:
2261 case INDEX_op_div_i32:
2262 case INDEX_op_divu_i32:
2263 case INDEX_op_rem_i32:
2264 case INDEX_op_remu_i32:
2265 case INDEX_op_nor_i32:
2266 case INDEX_op_setcond_i32:
2267 case INDEX_op_mul_i64:
2268 case INDEX_op_mulsh_i64:
2269 case INDEX_op_muluh_i64:
2270 case INDEX_op_div_i64:
2271 case INDEX_op_divu_i64:
2272 case INDEX_op_rem_i64:
2273 case INDEX_op_remu_i64:
2274 case INDEX_op_nor_i64:
2275 case INDEX_op_setcond_i64:
2276 return &r_rZ_rZ;
2277 case INDEX_op_muls2_i32:
2278 case INDEX_op_mulu2_i32:
2279 case INDEX_op_muls2_i64:
2280 case INDEX_op_mulu2_i64:
2281 return &r_r_r_r;
2282 case INDEX_op_and_i32:
2283 case INDEX_op_and_i64:
2284 return &r_r_rIK;
2285 case INDEX_op_or_i32:
2286 case INDEX_op_xor_i32:
2287 case INDEX_op_or_i64:
2288 case INDEX_op_xor_i64:
2289 return &r_r_rI;
2290 case INDEX_op_shl_i32:
2291 case INDEX_op_shr_i32:
2292 case INDEX_op_sar_i32:
2293 case INDEX_op_rotr_i32:
2294 case INDEX_op_rotl_i32:
2295 case INDEX_op_shl_i64:
2296 case INDEX_op_shr_i64:
2297 case INDEX_op_sar_i64:
2298 case INDEX_op_rotr_i64:
2299 case INDEX_op_rotl_i64:
2300 return &r_r_ri;
2301 case INDEX_op_clz_i32:
2302 case INDEX_op_clz_i64:
2303 return &r_r_rWZ;
2305 case INDEX_op_deposit_i32:
2306 case INDEX_op_deposit_i64:
2307 return &dep;
2308 case INDEX_op_brcond_i32:
2309 case INDEX_op_brcond_i64:
2310 return &rZ_rZ;
2311 case INDEX_op_movcond_i32:
2312 case INDEX_op_movcond_i64:
2313 return use_mips32r6_instructions ? &movc_r6 : &movc;
2315 case INDEX_op_add2_i32:
2316 case INDEX_op_sub2_i32:
2317 return &add2;
2318 case INDEX_op_setcond2_i32:
2319 return &setc2;
2320 case INDEX_op_brcond2_i32:
2321 return &br2;
2323 case INDEX_op_qemu_ld_i32:
2324 return (TCG_TARGET_REG_BITS == 64 || TARGET_LONG_BITS == 32
2325 ? &r_L : &r_L_L);
2326 case INDEX_op_qemu_st_i32:
2327 return (TCG_TARGET_REG_BITS == 64 || TARGET_LONG_BITS == 32
2328 ? &SZ_S : &SZ_S_S);
2329 case INDEX_op_qemu_ld_i64:
2330 return (TCG_TARGET_REG_BITS == 64 ? &r_L
2331 : TARGET_LONG_BITS == 32 ? &r_r_L : &r_r_L_L);
2332 case INDEX_op_qemu_st_i64:
2333 return (TCG_TARGET_REG_BITS == 64 ? &SZ_S
2334 : TARGET_LONG_BITS == 32 ? &SZ_SZ_S : &SZ_SZ_S_S);
2336 default:
2337 return NULL;
2341 static const int tcg_target_callee_save_regs[] = {
2342 TCG_REG_S0, /* used for the global env (TCG_AREG0) */
2343 TCG_REG_S1,
2344 TCG_REG_S2,
2345 TCG_REG_S3,
2346 TCG_REG_S4,
2347 TCG_REG_S5,
2348 TCG_REG_S6,
2349 TCG_REG_S7,
2350 TCG_REG_S8,
2351 TCG_REG_RA, /* should be last for ABI compliance */
2354 /* The Linux kernel doesn't provide any information about the available
2355 instruction set. Probe it using a signal handler. */
2358 #ifndef use_movnz_instructions
2359 bool use_movnz_instructions = false;
2360 #endif
2362 #ifndef use_mips32_instructions
2363 bool use_mips32_instructions = false;
2364 #endif
2366 #ifndef use_mips32r2_instructions
2367 bool use_mips32r2_instructions = false;
2368 #endif
2370 static volatile sig_atomic_t got_sigill;
2372 static void sigill_handler(int signo, siginfo_t *si, void *data)
2374 /* Skip the faulty instruction */
2375 ucontext_t *uc = (ucontext_t *)data;
2376 uc->uc_mcontext.pc += 4;
2378 got_sigill = 1;
2381 static void tcg_target_detect_isa(void)
2383 struct sigaction sa_old, sa_new;
2385 memset(&sa_new, 0, sizeof(sa_new));
2386 sa_new.sa_flags = SA_SIGINFO;
2387 sa_new.sa_sigaction = sigill_handler;
2388 sigaction(SIGILL, &sa_new, &sa_old);
2390 /* Probe for movn/movz, necessary to implement movcond. */
2391 #ifndef use_movnz_instructions
2392 got_sigill = 0;
2393 asm volatile(".set push\n"
2394 ".set mips32\n"
2395 "movn $zero, $zero, $zero\n"
2396 "movz $zero, $zero, $zero\n"
2397 ".set pop\n"
2398 : : : );
2399 use_movnz_instructions = !got_sigill;
2400 #endif
2402 /* Probe for MIPS32 instructions. As no subsetting is allowed
2403 by the specification, it is only necessary to probe for one
2404 of the instructions. */
2405 #ifndef use_mips32_instructions
2406 got_sigill = 0;
2407 asm volatile(".set push\n"
2408 ".set mips32\n"
2409 "mul $zero, $zero\n"
2410 ".set pop\n"
2411 : : : );
2412 use_mips32_instructions = !got_sigill;
2413 #endif
2415 /* Probe for MIPS32r2 instructions if MIPS32 instructions are
2416 available. As no subsetting is allowed by the specification,
2417 it is only necessary to probe for one of the instructions. */
2418 #ifndef use_mips32r2_instructions
2419 if (use_mips32_instructions) {
2420 got_sigill = 0;
2421 asm volatile(".set push\n"
2422 ".set mips32r2\n"
2423 "seb $zero, $zero\n"
2424 ".set pop\n"
2425 : : : );
2426 use_mips32r2_instructions = !got_sigill;
2428 #endif
2430 sigaction(SIGILL, &sa_old, NULL);
2433 static tcg_insn_unit *align_code_ptr(TCGContext *s)
2435 uintptr_t p = (uintptr_t)s->code_ptr;
2436 if (p & 15) {
2437 p = (p + 15) & -16;
2438 s->code_ptr = (void *)p;
2440 return s->code_ptr;
2443 /* Stack frame parameters. */
2444 #define REG_SIZE (TCG_TARGET_REG_BITS / 8)
2445 #define SAVE_SIZE ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE)
2446 #define TEMP_SIZE (CPU_TEMP_BUF_NLONGS * (int)sizeof(long))
2448 #define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \
2449 + TCG_TARGET_STACK_ALIGN - 1) \
2450 & -TCG_TARGET_STACK_ALIGN)
2451 #define SAVE_OFS (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE)
2453 /* We're expecting to be able to use an immediate for frame allocation. */
2454 QEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7fff);
2456 /* Generate global QEMU prologue and epilogue code */
2457 static void tcg_target_qemu_prologue(TCGContext *s)
2459 int i;
2461 tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE);
2463 /* TB prologue */
2464 tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE);
2465 for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
2466 tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
2467 TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
2470 #ifndef CONFIG_SOFTMMU
2471 if (guest_base) {
2472 tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base);
2473 tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
2475 #endif
2477 /* Call generated code */
2478 tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1], 0);
2479 /* delay slot */
2480 tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
2483 * Return path for goto_ptr. Set return value to 0, a-la exit_tb,
2484 * and fall through to the rest of the epilogue.
2486 s->code_gen_epilogue = s->code_ptr;
2487 tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_V0, TCG_REG_ZERO);
2489 /* TB epilogue */
2490 tb_ret_addr = s->code_ptr;
2491 for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
2492 tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
2493 TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
2496 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
2497 /* delay slot */
2498 tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE);
2500 if (use_mips32r2_instructions) {
2501 return;
2504 /* Bswap subroutines: Input in TCG_TMP0, output in TCG_TMP3;
2505 clobbers TCG_TMP1, TCG_TMP2. */
2508 * bswap32 -- 32-bit swap (signed result for mips64). a0 = abcd.
2510 bswap32_addr = align_code_ptr(s);
2511 /* t3 = (ssss)d000 */
2512 tcg_out_opc_sa(s, OPC_SLL, TCG_TMP3, TCG_TMP0, 24);
2513 /* t1 = 000a */
2514 tcg_out_opc_sa(s, OPC_SRL, TCG_TMP1, TCG_TMP0, 24);
2515 /* t2 = 00c0 */
2516 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP0, 0xff00);
2517 /* t3 = d00a */
2518 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2519 /* t1 = 0abc */
2520 tcg_out_opc_sa(s, OPC_SRL, TCG_TMP1, TCG_TMP0, 8);
2521 /* t2 = 0c00 */
2522 tcg_out_opc_sa(s, OPC_SLL, TCG_TMP2, TCG_TMP2, 8);
2523 /* t1 = 00b0 */
2524 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
2525 /* t3 = dc0a */
2526 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
2527 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
2528 /* t3 = dcba -- delay slot */
2529 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2531 if (TCG_TARGET_REG_BITS == 32) {
2532 return;
2536 * bswap32u -- unsigned 32-bit swap. a0 = ....abcd.
2538 bswap32u_addr = align_code_ptr(s);
2539 /* t1 = (0000)000d */
2540 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP0, 0xff);
2541 /* t3 = 000a */
2542 tcg_out_opc_sa(s, OPC_SRL, TCG_TMP3, TCG_TMP0, 24);
2543 /* t1 = (0000)d000 */
2544 tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 24);
2545 /* t2 = 00c0 */
2546 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP0, 0xff00);
2547 /* t3 = d00a */
2548 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2549 /* t1 = 0abc */
2550 tcg_out_opc_sa(s, OPC_SRL, TCG_TMP1, TCG_TMP0, 8);
2551 /* t2 = 0c00 */
2552 tcg_out_opc_sa(s, OPC_SLL, TCG_TMP2, TCG_TMP2, 8);
2553 /* t1 = 00b0 */
2554 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
2555 /* t3 = dc0a */
2556 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
2557 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
2558 /* t3 = dcba -- delay slot */
2559 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2562 * bswap64 -- 64-bit swap. a0 = abcdefgh
2564 bswap64_addr = align_code_ptr(s);
2565 /* t3 = h0000000 */
2566 tcg_out_dsll(s, TCG_TMP3, TCG_TMP0, 56);
2567 /* t1 = 0000000a */
2568 tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 56);
2570 /* t2 = 000000g0 */
2571 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP0, 0xff00);
2572 /* t3 = h000000a */
2573 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2574 /* t1 = 00000abc */
2575 tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 40);
2576 /* t2 = 0g000000 */
2577 tcg_out_dsll(s, TCG_TMP2, TCG_TMP2, 40);
2578 /* t1 = 000000b0 */
2579 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
2581 /* t3 = hg00000a */
2582 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
2583 /* t2 = 0000abcd */
2584 tcg_out_dsrl(s, TCG_TMP2, TCG_TMP0, 32);
2585 /* t3 = hg0000ba */
2586 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2588 /* t1 = 000000c0 */
2589 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP2, 0xff00);
2590 /* t2 = 0000000d */
2591 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP2, 0x00ff);
2592 /* t1 = 00000c00 */
2593 tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 8);
2594 /* t2 = 0000d000 */
2595 tcg_out_dsll(s, TCG_TMP2, TCG_TMP2, 24);
2597 /* t3 = hg000cba */
2598 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2599 /* t1 = 00abcdef */
2600 tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 16);
2601 /* t3 = hg00dcba */
2602 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
2604 /* t2 = 0000000f */
2605 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP1, 0x00ff);
2606 /* t1 = 000000e0 */
2607 tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
2608 /* t2 = 00f00000 */
2609 tcg_out_dsll(s, TCG_TMP2, TCG_TMP2, 40);
2610 /* t1 = 000e0000 */
2611 tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 24);
2613 /* t3 = hgf0dcba */
2614 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
2615 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
2616 /* t3 = hgfedcba -- delay slot */
2617 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2620 static void tcg_target_init(TCGContext *s)
2622 tcg_target_detect_isa();
2623 tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff;
2624 if (TCG_TARGET_REG_BITS == 64) {
2625 tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff;
2628 tcg_target_call_clobber_regs = 0;
2629 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V0);
2630 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V1);
2631 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A0);
2632 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A1);
2633 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A2);
2634 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A3);
2635 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T0);
2636 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T1);
2637 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T2);
2638 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T3);
2639 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T4);
2640 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T5);
2641 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T6);
2642 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T7);
2643 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T8);
2644 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T9);
2646 s->reserved_regs = 0;
2647 tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
2648 tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0); /* kernel use only */
2649 tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1); /* kernel use only */
2650 tcg_regset_set_reg(s->reserved_regs, TCG_TMP0); /* internal use */
2651 tcg_regset_set_reg(s->reserved_regs, TCG_TMP1); /* internal use */
2652 tcg_regset_set_reg(s->reserved_regs, TCG_TMP2); /* internal use */
2653 tcg_regset_set_reg(s->reserved_regs, TCG_TMP3); /* internal use */
2654 tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return address */
2655 tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */
2656 tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP); /* global pointer */
2659 void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_addr,
2660 uintptr_t addr)
2662 atomic_set((uint32_t *)jmp_addr, deposit32(OPC_J, 0, 26, addr >> 2));
2663 flush_icache_range(jmp_addr, jmp_addr + 4);
2666 typedef struct {
2667 DebugFrameHeader h;
2668 uint8_t fde_def_cfa[4];
2669 uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
2670 } DebugFrame;
2672 #define ELF_HOST_MACHINE EM_MIPS
2673 /* GDB doesn't appear to require proper setting of ELF_HOST_FLAGS,
2674 which is good because they're really quite complicated for MIPS. */
2676 static const DebugFrame debug_frame = {
2677 .h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */
2678 .h.cie.id = -1,
2679 .h.cie.version = 1,
2680 .h.cie.code_align = 1,
2681 .h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */
2682 .h.cie.return_column = TCG_REG_RA,
2684 /* Total FDE size does not include the "len" member. */
2685 .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
2687 .fde_def_cfa = {
2688 12, TCG_REG_SP, /* DW_CFA_def_cfa sp, ... */
2689 (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
2690 (FRAME_SIZE >> 7)
2692 .fde_reg_ofs = {
2693 0x80 + 16, 9, /* DW_CFA_offset, s0, -72 */
2694 0x80 + 17, 8, /* DW_CFA_offset, s2, -64 */
2695 0x80 + 18, 7, /* DW_CFA_offset, s3, -56 */
2696 0x80 + 19, 6, /* DW_CFA_offset, s4, -48 */
2697 0x80 + 20, 5, /* DW_CFA_offset, s5, -40 */
2698 0x80 + 21, 4, /* DW_CFA_offset, s6, -32 */
2699 0x80 + 22, 3, /* DW_CFA_offset, s7, -24 */
2700 0x80 + 30, 2, /* DW_CFA_offset, s8, -16 */
2701 0x80 + 31, 1, /* DW_CFA_offset, ra, -8 */
2705 void tcg_register_jit(void *buf, size_t buf_size)
2707 tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));