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