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