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