]> git.proxmox.com Git - qemu.git/blob - tcg/mips/tcg-target.c
smc91c111: Fix receive starvation
[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-null.h"
28
29 #if defined(TCG_TARGET_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
30 # define TCG_NEED_BSWAP 0
31 #else
32 # define TCG_NEED_BSWAP 1
33 #endif
34
35 #ifndef NDEBUG
36 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
37 "zero",
38 "at",
39 "v0",
40 "v1",
41 "a0",
42 "a1",
43 "a2",
44 "a3",
45 "t0",
46 "t1",
47 "t2",
48 "t3",
49 "t4",
50 "t5",
51 "t6",
52 "t7",
53 "s0",
54 "s1",
55 "s2",
56 "s3",
57 "s4",
58 "s5",
59 "s6",
60 "s7",
61 "t8",
62 "t9",
63 "k0",
64 "k1",
65 "gp",
66 "sp",
67 "fp",
68 "ra",
69 };
70 #endif
71
72 /* check if we really need so many registers :P */
73 static const TCGReg tcg_target_reg_alloc_order[] = {
74 TCG_REG_S0,
75 TCG_REG_S1,
76 TCG_REG_S2,
77 TCG_REG_S3,
78 TCG_REG_S4,
79 TCG_REG_S5,
80 TCG_REG_S6,
81 TCG_REG_S7,
82 TCG_REG_T1,
83 TCG_REG_T2,
84 TCG_REG_T3,
85 TCG_REG_T4,
86 TCG_REG_T5,
87 TCG_REG_T6,
88 TCG_REG_T7,
89 TCG_REG_T8,
90 TCG_REG_T9,
91 TCG_REG_A0,
92 TCG_REG_A1,
93 TCG_REG_A2,
94 TCG_REG_A3,
95 TCG_REG_V0,
96 TCG_REG_V1
97 };
98
99 static const TCGReg tcg_target_call_iarg_regs[4] = {
100 TCG_REG_A0,
101 TCG_REG_A1,
102 TCG_REG_A2,
103 TCG_REG_A3
104 };
105
106 static const TCGReg tcg_target_call_oarg_regs[2] = {
107 TCG_REG_V0,
108 TCG_REG_V1
109 };
110
111 static uint8_t *tb_ret_addr;
112
113 static inline uint32_t reloc_lo16_val(void *pc, intptr_t target)
114 {
115 return target & 0xffff;
116 }
117
118 static inline void reloc_lo16(void *pc, intptr_t target)
119 {
120 *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
121 | reloc_lo16_val(pc, target);
122 }
123
124 static inline uint32_t reloc_hi16_val(void *pc, intptr_t target)
125 {
126 return (target >> 16) & 0xffff;
127 }
128
129 static inline void reloc_hi16(void *pc, intptr_t target)
130 {
131 *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
132 | reloc_hi16_val(pc, target);
133 }
134
135 static inline uint32_t reloc_pc16_val(void *pc, intptr_t target)
136 {
137 int32_t disp;
138
139 disp = target - (intptr_t)pc - 4;
140 if (disp != (disp << 14) >> 14) {
141 tcg_abort ();
142 }
143
144 return (disp >> 2) & 0xffff;
145 }
146
147 static inline void reloc_pc16 (void *pc, tcg_target_long target)
148 {
149 *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
150 | reloc_pc16_val(pc, target);
151 }
152
153 static inline uint32_t reloc_26_val (void *pc, tcg_target_long target)
154 {
155 if ((((tcg_target_long)pc + 4) & 0xf0000000) != (target & 0xf0000000)) {
156 tcg_abort ();
157 }
158
159 return (target >> 2) & 0x3ffffff;
160 }
161
162 static inline void reloc_pc26(void *pc, intptr_t target)
163 {
164 *(uint32_t *) pc = (*(uint32_t *) pc & ~0x3ffffff)
165 | reloc_26_val(pc, target);
166 }
167
168 static void patch_reloc(uint8_t *code_ptr, int type,
169 intptr_t value, intptr_t addend)
170 {
171 value += addend;
172 switch(type) {
173 case R_MIPS_LO16:
174 reloc_lo16(code_ptr, value);
175 break;
176 case R_MIPS_HI16:
177 reloc_hi16(code_ptr, value);
178 break;
179 case R_MIPS_PC16:
180 reloc_pc16(code_ptr, value);
181 break;
182 case R_MIPS_26:
183 reloc_pc26(code_ptr, value);
184 break;
185 default:
186 tcg_abort();
187 }
188 }
189
190 /* parse target specific constraints */
191 static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
192 {
193 const char *ct_str;
194
195 ct_str = *pct_str;
196 switch(ct_str[0]) {
197 case 'r':
198 ct->ct |= TCG_CT_REG;
199 tcg_regset_set(ct->u.regs, 0xffffffff);
200 break;
201 case 'C':
202 ct->ct |= TCG_CT_REG;
203 tcg_regset_clear(ct->u.regs);
204 tcg_regset_set_reg(ct->u.regs, TCG_REG_T9);
205 break;
206 case 'L': /* qemu_ld output arg constraint */
207 ct->ct |= TCG_CT_REG;
208 tcg_regset_set(ct->u.regs, 0xffffffff);
209 tcg_regset_reset_reg(ct->u.regs, TCG_REG_V0);
210 break;
211 case 'l': /* qemu_ld input arg constraint */
212 ct->ct |= TCG_CT_REG;
213 tcg_regset_set(ct->u.regs, 0xffffffff);
214 #if defined(CONFIG_SOFTMMU)
215 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
216 # if (TARGET_LONG_BITS == 64)
217 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
218 # endif
219 #endif
220 break;
221 case 'S': /* qemu_st constraint */
222 ct->ct |= TCG_CT_REG;
223 tcg_regset_set(ct->u.regs, 0xffffffff);
224 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
225 #if defined(CONFIG_SOFTMMU)
226 # if (TARGET_LONG_BITS == 32)
227 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1);
228 # endif
229 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
230 # if TARGET_LONG_BITS == 64
231 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A3);
232 # endif
233 #endif
234 break;
235 case 'I':
236 ct->ct |= TCG_CT_CONST_U16;
237 break;
238 case 'J':
239 ct->ct |= TCG_CT_CONST_S16;
240 break;
241 case 'Z':
242 /* We are cheating a bit here, using the fact that the register
243 ZERO is also the register number 0. Hence there is no need
244 to check for const_args in each instruction. */
245 ct->ct |= TCG_CT_CONST_ZERO;
246 break;
247 default:
248 return -1;
249 }
250 ct_str++;
251 *pct_str = ct_str;
252 return 0;
253 }
254
255 /* test if a constant matches the constraint */
256 static inline int tcg_target_const_match(tcg_target_long val,
257 const TCGArgConstraint *arg_ct)
258 {
259 int ct;
260 ct = arg_ct->ct;
261 if (ct & TCG_CT_CONST)
262 return 1;
263 else if ((ct & TCG_CT_CONST_ZERO) && val == 0)
264 return 1;
265 else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val)
266 return 1;
267 else if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val)
268 return 1;
269 else
270 return 0;
271 }
272
273 /* instruction opcodes */
274 enum {
275 OPC_BEQ = 0x04 << 26,
276 OPC_BNE = 0x05 << 26,
277 OPC_BLEZ = 0x06 << 26,
278 OPC_BGTZ = 0x07 << 26,
279 OPC_ADDIU = 0x09 << 26,
280 OPC_SLTI = 0x0A << 26,
281 OPC_SLTIU = 0x0B << 26,
282 OPC_ANDI = 0x0C << 26,
283 OPC_ORI = 0x0D << 26,
284 OPC_XORI = 0x0E << 26,
285 OPC_LUI = 0x0F << 26,
286 OPC_LB = 0x20 << 26,
287 OPC_LH = 0x21 << 26,
288 OPC_LW = 0x23 << 26,
289 OPC_LBU = 0x24 << 26,
290 OPC_LHU = 0x25 << 26,
291 OPC_LWU = 0x27 << 26,
292 OPC_SB = 0x28 << 26,
293 OPC_SH = 0x29 << 26,
294 OPC_SW = 0x2B << 26,
295
296 OPC_SPECIAL = 0x00 << 26,
297 OPC_SLL = OPC_SPECIAL | 0x00,
298 OPC_SRL = OPC_SPECIAL | 0x02,
299 OPC_ROTR = OPC_SPECIAL | (0x01 << 21) | 0x02,
300 OPC_SRA = OPC_SPECIAL | 0x03,
301 OPC_SLLV = OPC_SPECIAL | 0x04,
302 OPC_SRLV = OPC_SPECIAL | 0x06,
303 OPC_ROTRV = OPC_SPECIAL | (0x01 << 6) | 0x06,
304 OPC_SRAV = OPC_SPECIAL | 0x07,
305 OPC_JR = OPC_SPECIAL | 0x08,
306 OPC_JALR = OPC_SPECIAL | 0x09,
307 OPC_MOVZ = OPC_SPECIAL | 0x0A,
308 OPC_MOVN = OPC_SPECIAL | 0x0B,
309 OPC_MFHI = OPC_SPECIAL | 0x10,
310 OPC_MFLO = OPC_SPECIAL | 0x12,
311 OPC_MULT = OPC_SPECIAL | 0x18,
312 OPC_MULTU = OPC_SPECIAL | 0x19,
313 OPC_DIV = OPC_SPECIAL | 0x1A,
314 OPC_DIVU = OPC_SPECIAL | 0x1B,
315 OPC_ADDU = OPC_SPECIAL | 0x21,
316 OPC_SUBU = OPC_SPECIAL | 0x23,
317 OPC_AND = OPC_SPECIAL | 0x24,
318 OPC_OR = OPC_SPECIAL | 0x25,
319 OPC_XOR = OPC_SPECIAL | 0x26,
320 OPC_NOR = OPC_SPECIAL | 0x27,
321 OPC_SLT = OPC_SPECIAL | 0x2A,
322 OPC_SLTU = OPC_SPECIAL | 0x2B,
323
324 OPC_REGIMM = 0x01 << 26,
325 OPC_BLTZ = OPC_REGIMM | (0x00 << 16),
326 OPC_BGEZ = OPC_REGIMM | (0x01 << 16),
327
328 OPC_SPECIAL2 = 0x1c << 26,
329 OPC_MUL = OPC_SPECIAL2 | 0x002,
330
331 OPC_SPECIAL3 = 0x1f << 26,
332 OPC_INS = OPC_SPECIAL3 | 0x004,
333 OPC_WSBH = OPC_SPECIAL3 | 0x0a0,
334 OPC_SEB = OPC_SPECIAL3 | 0x420,
335 OPC_SEH = OPC_SPECIAL3 | 0x620,
336 };
337
338 /*
339 * Type reg
340 */
341 static inline void tcg_out_opc_reg(TCGContext *s, int opc,
342 TCGReg rd, TCGReg rs, TCGReg rt)
343 {
344 int32_t inst;
345
346 inst = opc;
347 inst |= (rs & 0x1F) << 21;
348 inst |= (rt & 0x1F) << 16;
349 inst |= (rd & 0x1F) << 11;
350 tcg_out32(s, inst);
351 }
352
353 /*
354 * Type immediate
355 */
356 static inline void tcg_out_opc_imm(TCGContext *s, int opc,
357 TCGReg rt, TCGReg rs, TCGArg imm)
358 {
359 int32_t inst;
360
361 inst = opc;
362 inst |= (rs & 0x1F) << 21;
363 inst |= (rt & 0x1F) << 16;
364 inst |= (imm & 0xffff);
365 tcg_out32(s, inst);
366 }
367
368 /*
369 * Type branch
370 */
371 static inline void tcg_out_opc_br(TCGContext *s, int opc,
372 TCGReg rt, TCGReg rs)
373 {
374 /* We pay attention here to not modify the branch target by reading
375 the existing value and using it again. This ensure that caches and
376 memory are kept coherent during retranslation. */
377 uint16_t offset = (uint16_t)(*(uint32_t *) s->code_ptr);
378
379 tcg_out_opc_imm(s, opc, rt, rs, offset);
380 }
381
382 /*
383 * Type sa
384 */
385 static inline void tcg_out_opc_sa(TCGContext *s, int opc,
386 TCGReg rd, TCGReg rt, TCGArg sa)
387 {
388 int32_t inst;
389
390 inst = opc;
391 inst |= (rt & 0x1F) << 16;
392 inst |= (rd & 0x1F) << 11;
393 inst |= (sa & 0x1F) << 6;
394 tcg_out32(s, inst);
395
396 }
397
398 static inline void tcg_out_nop(TCGContext *s)
399 {
400 tcg_out32(s, 0);
401 }
402
403 static inline void tcg_out_mov(TCGContext *s, TCGType type,
404 TCGReg ret, TCGReg arg)
405 {
406 /* Simple reg-reg move, optimising out the 'do nothing' case */
407 if (ret != arg) {
408 tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
409 }
410 }
411
412 static inline void tcg_out_movi(TCGContext *s, TCGType type,
413 TCGReg reg, tcg_target_long arg)
414 {
415 if (arg == (int16_t)arg) {
416 tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
417 } else if (arg == (uint16_t)arg) {
418 tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
419 } else {
420 tcg_out_opc_imm(s, OPC_LUI, reg, 0, arg >> 16);
421 tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0xffff);
422 }
423 }
424
425 static inline void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg)
426 {
427 if (use_mips32r2_instructions) {
428 tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
429 } else {
430 /* ret and arg can't be register at */
431 if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
432 tcg_abort();
433 }
434
435 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
436 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
437 tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
438 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
439 }
440 }
441
442 static inline void tcg_out_bswap16s(TCGContext *s, TCGReg ret, TCGReg arg)
443 {
444 if (use_mips32r2_instructions) {
445 tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
446 tcg_out_opc_reg(s, OPC_SEH, ret, 0, ret);
447 } else {
448 /* ret and arg can't be register at */
449 if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
450 tcg_abort();
451 }
452
453 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
454 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
455 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
456 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
457 }
458 }
459
460 static inline void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg)
461 {
462 if (use_mips32r2_instructions) {
463 tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
464 tcg_out_opc_sa(s, OPC_ROTR, ret, ret, 16);
465 } else {
466 /* ret and arg must be different and can't be register at */
467 if (ret == arg || ret == TCG_REG_AT || arg == TCG_REG_AT) {
468 tcg_abort();
469 }
470
471 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
472
473 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 24);
474 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
475
476 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, arg, 0xff00);
477 tcg_out_opc_sa(s, OPC_SLL, TCG_REG_AT, TCG_REG_AT, 8);
478 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
479
480 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
481 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff00);
482 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
483 }
484 }
485
486 static inline void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg)
487 {
488 if (use_mips32r2_instructions) {
489 tcg_out_opc_reg(s, OPC_SEB, ret, 0, arg);
490 } else {
491 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
492 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 24);
493 }
494 }
495
496 static inline void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg)
497 {
498 if (use_mips32r2_instructions) {
499 tcg_out_opc_reg(s, OPC_SEH, ret, 0, arg);
500 } else {
501 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 16);
502 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
503 }
504 }
505
506 static inline void tcg_out_ldst(TCGContext *s, int opc, TCGArg arg,
507 TCGReg arg1, TCGArg arg2)
508 {
509 if (arg2 == (int16_t) arg2) {
510 tcg_out_opc_imm(s, opc, arg, arg1, arg2);
511 } else {
512 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, arg2);
513 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, TCG_REG_AT, arg1);
514 tcg_out_opc_imm(s, opc, arg, TCG_REG_AT, 0);
515 }
516 }
517
518 static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
519 TCGReg arg1, intptr_t arg2)
520 {
521 tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
522 }
523
524 static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
525 TCGReg arg1, intptr_t arg2)
526 {
527 tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
528 }
529
530 static inline void tcg_out_addi(TCGContext *s, TCGReg reg, TCGArg val)
531 {
532 if (val == (int16_t)val) {
533 tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
534 } else {
535 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, val);
536 tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_REG_AT);
537 }
538 }
539
540 /* Helper routines for marshalling helper function arguments into
541 * the correct registers and stack.
542 * arg_num is where we want to put this argument, and is updated to be ready
543 * for the next call. arg is the argument itself. Note that arg_num 0..3 is
544 * real registers, 4+ on stack.
545 *
546 * We provide routines for arguments which are: immediate, 32 bit
547 * value in register, 16 and 8 bit values in register (which must be zero
548 * extended before use) and 64 bit value in a lo:hi register pair.
549 */
550 #define DEFINE_TCG_OUT_CALL_IARG(NAME, ARGPARAM) \
551 static inline void NAME(TCGContext *s, int *arg_num, ARGPARAM) \
552 { \
553 if (*arg_num < 4) { \
554 DEFINE_TCG_OUT_CALL_IARG_GET_ARG(tcg_target_call_iarg_regs[*arg_num]); \
555 } else { \
556 DEFINE_TCG_OUT_CALL_IARG_GET_ARG(TCG_REG_AT); \
557 tcg_out_st(s, TCG_TYPE_I32, TCG_REG_AT, TCG_REG_SP, 4 * (*arg_num)); \
558 } \
559 (*arg_num)++; \
560 }
561 #define DEFINE_TCG_OUT_CALL_IARG_GET_ARG(A) \
562 tcg_out_opc_imm(s, OPC_ANDI, A, arg, 0xff);
563 DEFINE_TCG_OUT_CALL_IARG(tcg_out_call_iarg_reg8, TCGReg arg)
564 #undef DEFINE_TCG_OUT_CALL_IARG_GET_ARG
565 #define DEFINE_TCG_OUT_CALL_IARG_GET_ARG(A) \
566 tcg_out_opc_imm(s, OPC_ANDI, A, arg, 0xffff);
567 DEFINE_TCG_OUT_CALL_IARG(tcg_out_call_iarg_reg16, TCGReg arg)
568 #undef DEFINE_TCG_OUT_CALL_IARG_GET_ARG
569 #define DEFINE_TCG_OUT_CALL_IARG_GET_ARG(A) \
570 tcg_out_movi(s, TCG_TYPE_I32, A, arg);
571 DEFINE_TCG_OUT_CALL_IARG(tcg_out_call_iarg_imm32, TCGArg arg)
572 #undef DEFINE_TCG_OUT_CALL_IARG_GET_ARG
573
574 /* We don't use the macro for this one to avoid an unnecessary reg-reg
575 move when storing to the stack. */
576 static inline void tcg_out_call_iarg_reg32(TCGContext *s, int *arg_num,
577 TCGReg arg)
578 {
579 if (*arg_num < 4) {
580 tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[*arg_num], arg);
581 } else {
582 tcg_out_st(s, TCG_TYPE_I32, arg, TCG_REG_SP, 4 * (*arg_num));
583 }
584 (*arg_num)++;
585 }
586
587 static inline void tcg_out_call_iarg_reg64(TCGContext *s, int *arg_num,
588 TCGReg arg_low, TCGReg arg_high)
589 {
590 (*arg_num) = (*arg_num + 1) & ~1;
591
592 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
593 tcg_out_call_iarg_reg32(s, arg_num, arg_high);
594 tcg_out_call_iarg_reg32(s, arg_num, arg_low);
595 #else
596 tcg_out_call_iarg_reg32(s, arg_num, arg_low);
597 tcg_out_call_iarg_reg32(s, arg_num, arg_high);
598 #endif
599 }
600
601 static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGArg arg1,
602 TCGArg arg2, int label_index)
603 {
604 TCGLabel *l = &s->labels[label_index];
605
606 switch (cond) {
607 case TCG_COND_EQ:
608 tcg_out_opc_br(s, OPC_BEQ, arg1, arg2);
609 break;
610 case TCG_COND_NE:
611 tcg_out_opc_br(s, OPC_BNE, arg1, arg2);
612 break;
613 case TCG_COND_LT:
614 if (arg2 == 0) {
615 tcg_out_opc_br(s, OPC_BLTZ, 0, arg1);
616 } else {
617 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
618 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
619 }
620 break;
621 case TCG_COND_LTU:
622 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
623 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
624 break;
625 case TCG_COND_GE:
626 if (arg2 == 0) {
627 tcg_out_opc_br(s, OPC_BGEZ, 0, arg1);
628 } else {
629 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
630 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
631 }
632 break;
633 case TCG_COND_GEU:
634 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
635 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
636 break;
637 case TCG_COND_LE:
638 if (arg2 == 0) {
639 tcg_out_opc_br(s, OPC_BLEZ, 0, arg1);
640 } else {
641 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
642 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
643 }
644 break;
645 case TCG_COND_LEU:
646 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
647 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
648 break;
649 case TCG_COND_GT:
650 if (arg2 == 0) {
651 tcg_out_opc_br(s, OPC_BGTZ, 0, arg1);
652 } else {
653 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
654 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
655 }
656 break;
657 case TCG_COND_GTU:
658 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
659 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
660 break;
661 default:
662 tcg_abort();
663 break;
664 }
665 if (l->has_value) {
666 reloc_pc16(s->code_ptr - 4, l->u.value);
667 } else {
668 tcg_out_reloc(s, s->code_ptr - 4, R_MIPS_PC16, label_index, 0);
669 }
670 tcg_out_nop(s);
671 }
672
673 /* XXX: we implement it at the target level to avoid having to
674 handle cross basic blocks temporaries */
675 static void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGArg arg1,
676 TCGArg arg2, TCGArg arg3, TCGArg arg4,
677 int label_index)
678 {
679 void *label_ptr;
680
681 switch(cond) {
682 case TCG_COND_NE:
683 tcg_out_brcond(s, TCG_COND_NE, arg2, arg4, label_index);
684 tcg_out_brcond(s, TCG_COND_NE, arg1, arg3, label_index);
685 return;
686 case TCG_COND_EQ:
687 break;
688 case TCG_COND_LT:
689 case TCG_COND_LE:
690 tcg_out_brcond(s, TCG_COND_LT, arg2, arg4, label_index);
691 break;
692 case TCG_COND_GT:
693 case TCG_COND_GE:
694 tcg_out_brcond(s, TCG_COND_GT, arg2, arg4, label_index);
695 break;
696 case TCG_COND_LTU:
697 case TCG_COND_LEU:
698 tcg_out_brcond(s, TCG_COND_LTU, arg2, arg4, label_index);
699 break;
700 case TCG_COND_GTU:
701 case TCG_COND_GEU:
702 tcg_out_brcond(s, TCG_COND_GTU, arg2, arg4, label_index);
703 break;
704 default:
705 tcg_abort();
706 }
707
708 label_ptr = s->code_ptr;
709 tcg_out_opc_br(s, OPC_BNE, arg2, arg4);
710 tcg_out_nop(s);
711
712 switch(cond) {
713 case TCG_COND_EQ:
714 tcg_out_brcond(s, TCG_COND_EQ, arg1, arg3, label_index);
715 break;
716 case TCG_COND_LT:
717 case TCG_COND_LTU:
718 tcg_out_brcond(s, TCG_COND_LTU, arg1, arg3, label_index);
719 break;
720 case TCG_COND_LE:
721 case TCG_COND_LEU:
722 tcg_out_brcond(s, TCG_COND_LEU, arg1, arg3, label_index);
723 break;
724 case TCG_COND_GT:
725 case TCG_COND_GTU:
726 tcg_out_brcond(s, TCG_COND_GTU, arg1, arg3, label_index);
727 break;
728 case TCG_COND_GE:
729 case TCG_COND_GEU:
730 tcg_out_brcond(s, TCG_COND_GEU, arg1, arg3, label_index);
731 break;
732 default:
733 tcg_abort();
734 }
735
736 reloc_pc16(label_ptr, (tcg_target_long) s->code_ptr);
737 }
738
739 static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
740 TCGArg c1, TCGArg c2, TCGArg v)
741 {
742 switch (cond) {
743 case TCG_COND_EQ:
744 if (c1 == 0) {
745 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, c2);
746 } else if (c2 == 0) {
747 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, c1);
748 } else {
749 tcg_out_opc_reg(s, OPC_XOR, TCG_REG_AT, c1, c2);
750 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_REG_AT);
751 }
752 break;
753 case TCG_COND_NE:
754 if (c1 == 0) {
755 tcg_out_opc_reg(s, OPC_MOVN, ret, v, c2);
756 } else if (c2 == 0) {
757 tcg_out_opc_reg(s, OPC_MOVN, ret, v, c1);
758 } else {
759 tcg_out_opc_reg(s, OPC_XOR, TCG_REG_AT, c1, c2);
760 tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_REG_AT);
761 }
762 break;
763 case TCG_COND_LT:
764 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, c1, c2);
765 tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_REG_AT);
766 break;
767 case TCG_COND_LTU:
768 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, c1, c2);
769 tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_REG_AT);
770 break;
771 case TCG_COND_GE:
772 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, c1, c2);
773 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_REG_AT);
774 break;
775 case TCG_COND_GEU:
776 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, c1, c2);
777 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_REG_AT);
778 break;
779 case TCG_COND_LE:
780 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, c2, c1);
781 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_REG_AT);
782 break;
783 case TCG_COND_LEU:
784 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, c2, c1);
785 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_REG_AT);
786 break;
787 case TCG_COND_GT:
788 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, c2, c1);
789 tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_REG_AT);
790 break;
791 case TCG_COND_GTU:
792 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, c2, c1);
793 tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_REG_AT);
794 break;
795 default:
796 tcg_abort();
797 break;
798 }
799 }
800
801 static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
802 TCGArg arg1, TCGArg arg2)
803 {
804 switch (cond) {
805 case TCG_COND_EQ:
806 if (arg1 == 0) {
807 tcg_out_opc_imm(s, OPC_SLTIU, ret, arg2, 1);
808 } else if (arg2 == 0) {
809 tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, 1);
810 } else {
811 tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
812 tcg_out_opc_imm(s, OPC_SLTIU, ret, ret, 1);
813 }
814 break;
815 case TCG_COND_NE:
816 if (arg1 == 0) {
817 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg2);
818 } else if (arg2 == 0) {
819 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg1);
820 } else {
821 tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
822 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, ret);
823 }
824 break;
825 case TCG_COND_LT:
826 tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
827 break;
828 case TCG_COND_LTU:
829 tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
830 break;
831 case TCG_COND_GE:
832 tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
833 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
834 break;
835 case TCG_COND_GEU:
836 tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
837 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
838 break;
839 case TCG_COND_LE:
840 tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
841 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
842 break;
843 case TCG_COND_LEU:
844 tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
845 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
846 break;
847 case TCG_COND_GT:
848 tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
849 break;
850 case TCG_COND_GTU:
851 tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
852 break;
853 default:
854 tcg_abort();
855 break;
856 }
857 }
858
859 /* XXX: we implement it at the target level to avoid having to
860 handle cross basic blocks temporaries */
861 static void tcg_out_setcond2(TCGContext *s, TCGCond cond, TCGReg ret,
862 TCGArg arg1, TCGArg arg2, TCGArg arg3, TCGArg arg4)
863 {
864 switch (cond) {
865 case TCG_COND_EQ:
866 tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_AT, arg2, arg4);
867 tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg1, arg3);
868 tcg_out_opc_reg(s, OPC_AND, ret, TCG_REG_AT, TCG_REG_T0);
869 return;
870 case TCG_COND_NE:
871 tcg_out_setcond(s, TCG_COND_NE, TCG_REG_AT, arg2, arg4);
872 tcg_out_setcond(s, TCG_COND_NE, TCG_REG_T0, arg1, arg3);
873 tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_AT, TCG_REG_T0);
874 return;
875 case TCG_COND_LT:
876 case TCG_COND_LE:
877 tcg_out_setcond(s, TCG_COND_LT, TCG_REG_AT, arg2, arg4);
878 break;
879 case TCG_COND_GT:
880 case TCG_COND_GE:
881 tcg_out_setcond(s, TCG_COND_GT, TCG_REG_AT, arg2, arg4);
882 break;
883 case TCG_COND_LTU:
884 case TCG_COND_LEU:
885 tcg_out_setcond(s, TCG_COND_LTU, TCG_REG_AT, arg2, arg4);
886 break;
887 case TCG_COND_GTU:
888 case TCG_COND_GEU:
889 tcg_out_setcond(s, TCG_COND_GTU, TCG_REG_AT, arg2, arg4);
890 break;
891 default:
892 tcg_abort();
893 break;
894 }
895
896 tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg2, arg4);
897
898 switch(cond) {
899 case TCG_COND_LT:
900 case TCG_COND_LTU:
901 tcg_out_setcond(s, TCG_COND_LTU, ret, arg1, arg3);
902 break;
903 case TCG_COND_LE:
904 case TCG_COND_LEU:
905 tcg_out_setcond(s, TCG_COND_LEU, ret, arg1, arg3);
906 break;
907 case TCG_COND_GT:
908 case TCG_COND_GTU:
909 tcg_out_setcond(s, TCG_COND_GTU, ret, arg1, arg3);
910 break;
911 case TCG_COND_GE:
912 case TCG_COND_GEU:
913 tcg_out_setcond(s, TCG_COND_GEU, ret, arg1, arg3);
914 break;
915 default:
916 tcg_abort();
917 }
918
919 tcg_out_opc_reg(s, OPC_AND, ret, ret, TCG_REG_T0);
920 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
921 }
922
923 #if defined(CONFIG_SOFTMMU)
924 /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
925 int mmu_idx) */
926 static const void * const qemu_ld_helpers[4] = {
927 helper_ldb_mmu,
928 helper_ldw_mmu,
929 helper_ldl_mmu,
930 helper_ldq_mmu,
931 };
932
933 /* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
934 uintxx_t val, int mmu_idx) */
935 static const void * const qemu_st_helpers[4] = {
936 helper_stb_mmu,
937 helper_stw_mmu,
938 helper_stl_mmu,
939 helper_stq_mmu,
940 };
941 #endif
942
943 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
944 int opc)
945 {
946 TCGReg addr_regl, data_regl, data_regh, data_reg1, data_reg2;
947 #if defined(CONFIG_SOFTMMU)
948 void *label1_ptr, *label2_ptr;
949 int arg_num;
950 int mem_index, s_bits;
951 int addr_meml;
952 # if TARGET_LONG_BITS == 64
953 uint8_t *label3_ptr;
954 TCGReg addr_regh;
955 int addr_memh;
956 # endif
957 #endif
958 data_regl = *args++;
959 if (opc == 3)
960 data_regh = *args++;
961 else
962 data_regh = 0;
963 addr_regl = *args++;
964 #if defined(CONFIG_SOFTMMU)
965 # if TARGET_LONG_BITS == 64
966 addr_regh = *args++;
967 # if defined(TCG_TARGET_WORDS_BIGENDIAN)
968 addr_memh = 0;
969 addr_meml = 4;
970 # else
971 addr_memh = 4;
972 addr_meml = 0;
973 # endif
974 # else
975 addr_meml = 0;
976 # endif
977 mem_index = *args;
978 s_bits = opc & 3;
979 #endif
980
981 if (opc == 3) {
982 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
983 data_reg1 = data_regh;
984 data_reg2 = data_regl;
985 #else
986 data_reg1 = data_regl;
987 data_reg2 = data_regh;
988 #endif
989 } else {
990 data_reg1 = data_regl;
991 data_reg2 = 0;
992 }
993 #if defined(CONFIG_SOFTMMU)
994 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
995 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
996 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
997 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
998 offsetof(CPUArchState, tlb_table[mem_index][0].addr_read) + addr_meml);
999 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
1000 tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
1001
1002 # if TARGET_LONG_BITS == 64
1003 label3_ptr = s->code_ptr;
1004 tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
1005 tcg_out_nop(s);
1006
1007 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
1008 offsetof(CPUArchState, tlb_table[mem_index][0].addr_read) + addr_memh);
1009
1010 label1_ptr = s->code_ptr;
1011 tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
1012 tcg_out_nop(s);
1013
1014 reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
1015 # else
1016 label1_ptr = s->code_ptr;
1017 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
1018 tcg_out_nop(s);
1019 # endif
1020
1021 /* slow path */
1022 arg_num = 0;
1023 tcg_out_call_iarg_reg32(s, &arg_num, TCG_AREG0);
1024 # if TARGET_LONG_BITS == 64
1025 tcg_out_call_iarg_reg64(s, &arg_num, addr_regl, addr_regh);
1026 # else
1027 tcg_out_call_iarg_reg32(s, &arg_num, addr_regl);
1028 # endif
1029 tcg_out_call_iarg_imm32(s, &arg_num, mem_index);
1030 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]);
1031 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
1032 tcg_out_nop(s);
1033
1034 switch(opc) {
1035 case 0:
1036 tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xff);
1037 break;
1038 case 0 | 4:
1039 tcg_out_ext8s(s, data_reg1, TCG_REG_V0);
1040 break;
1041 case 1:
1042 tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xffff);
1043 break;
1044 case 1 | 4:
1045 tcg_out_ext16s(s, data_reg1, TCG_REG_V0);
1046 break;
1047 case 2:
1048 tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
1049 break;
1050 case 3:
1051 tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_V1);
1052 tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
1053 break;
1054 default:
1055 tcg_abort();
1056 }
1057
1058 label2_ptr = s->code_ptr;
1059 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
1060 tcg_out_nop(s);
1061
1062 /* label1: fast path */
1063 reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
1064
1065 tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
1066 offsetof(CPUArchState, tlb_table[mem_index][0].addend));
1067 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_A0, addr_regl);
1068 #else
1069 if (GUEST_BASE == (int16_t)GUEST_BASE) {
1070 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_V0, addr_regl, GUEST_BASE);
1071 } else {
1072 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, GUEST_BASE);
1073 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_V0, addr_regl);
1074 }
1075 #endif
1076
1077 switch(opc) {
1078 case 0:
1079 tcg_out_opc_imm(s, OPC_LBU, data_reg1, TCG_REG_V0, 0);
1080 break;
1081 case 0 | 4:
1082 tcg_out_opc_imm(s, OPC_LB, data_reg1, TCG_REG_V0, 0);
1083 break;
1084 case 1:
1085 if (TCG_NEED_BSWAP) {
1086 tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
1087 tcg_out_bswap16(s, data_reg1, TCG_REG_T0);
1088 } else {
1089 tcg_out_opc_imm(s, OPC_LHU, data_reg1, TCG_REG_V0, 0);
1090 }
1091 break;
1092 case 1 | 4:
1093 if (TCG_NEED_BSWAP) {
1094 tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
1095 tcg_out_bswap16s(s, data_reg1, TCG_REG_T0);
1096 } else {
1097 tcg_out_opc_imm(s, OPC_LH, data_reg1, TCG_REG_V0, 0);
1098 }
1099 break;
1100 case 2:
1101 if (TCG_NEED_BSWAP) {
1102 tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
1103 tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
1104 } else {
1105 tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
1106 }
1107 break;
1108 case 3:
1109 if (TCG_NEED_BSWAP) {
1110 tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 4);
1111 tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
1112 tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
1113 tcg_out_bswap32(s, data_reg2, TCG_REG_T0);
1114 } else {
1115 tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
1116 tcg_out_opc_imm(s, OPC_LW, data_reg2, TCG_REG_V0, 4);
1117 }
1118 break;
1119 default:
1120 tcg_abort();
1121 }
1122
1123 #if defined(CONFIG_SOFTMMU)
1124 reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
1125 #endif
1126 }
1127
1128 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
1129 int opc)
1130 {
1131 TCGReg addr_regl, data_regl, data_regh, data_reg1, data_reg2;
1132 #if defined(CONFIG_SOFTMMU)
1133 uint8_t *label1_ptr, *label2_ptr;
1134 int arg_num;
1135 int mem_index, s_bits;
1136 int addr_meml;
1137 #endif
1138 #if TARGET_LONG_BITS == 64
1139 # if defined(CONFIG_SOFTMMU)
1140 uint8_t *label3_ptr;
1141 TCGReg addr_regh;
1142 int addr_memh;
1143 # endif
1144 #endif
1145 data_regl = *args++;
1146 if (opc == 3) {
1147 data_regh = *args++;
1148 } else {
1149 data_regh = 0;
1150 }
1151 addr_regl = *args++;
1152 #if defined(CONFIG_SOFTMMU)
1153 # if TARGET_LONG_BITS == 64
1154 addr_regh = *args++;
1155 # if defined(TCG_TARGET_WORDS_BIGENDIAN)
1156 addr_memh = 0;
1157 addr_meml = 4;
1158 # else
1159 addr_memh = 4;
1160 addr_meml = 0;
1161 # endif
1162 # else
1163 addr_meml = 0;
1164 # endif
1165 mem_index = *args;
1166 s_bits = opc;
1167 #endif
1168
1169 if (opc == 3) {
1170 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
1171 data_reg1 = data_regh;
1172 data_reg2 = data_regl;
1173 #else
1174 data_reg1 = data_regl;
1175 data_reg2 = data_regh;
1176 #endif
1177 } else {
1178 data_reg1 = data_regl;
1179 data_reg2 = 0;
1180 }
1181
1182 #if defined(CONFIG_SOFTMMU)
1183 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
1184 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
1185 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
1186 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
1187 offsetof(CPUArchState, tlb_table[mem_index][0].addr_write) + addr_meml);
1188 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
1189 tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
1190
1191 # if TARGET_LONG_BITS == 64
1192 label3_ptr = s->code_ptr;
1193 tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
1194 tcg_out_nop(s);
1195
1196 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
1197 offsetof(CPUArchState, tlb_table[mem_index][0].addr_write) + addr_memh);
1198
1199 label1_ptr = s->code_ptr;
1200 tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
1201 tcg_out_nop(s);
1202
1203 reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
1204 # else
1205 label1_ptr = s->code_ptr;
1206 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
1207 tcg_out_nop(s);
1208 # endif
1209
1210 /* slow path */
1211 arg_num = 0;
1212 tcg_out_call_iarg_reg32(s, &arg_num, TCG_AREG0);
1213 # if TARGET_LONG_BITS == 64
1214 tcg_out_call_iarg_reg64(s, &arg_num, addr_regl, addr_regh);
1215 # else
1216 tcg_out_call_iarg_reg32(s, &arg_num, addr_regl);
1217 # endif
1218 switch(opc) {
1219 case 0:
1220 tcg_out_call_iarg_reg8(s, &arg_num, data_regl);
1221 break;
1222 case 1:
1223 tcg_out_call_iarg_reg16(s, &arg_num, data_regl);
1224 break;
1225 case 2:
1226 tcg_out_call_iarg_reg32(s, &arg_num, data_regl);
1227 break;
1228 case 3:
1229 tcg_out_call_iarg_reg64(s, &arg_num, data_regl, data_regh);
1230 break;
1231 default:
1232 tcg_abort();
1233 }
1234 tcg_out_call_iarg_imm32(s, &arg_num, mem_index);
1235 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_st_helpers[s_bits]);
1236 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
1237 tcg_out_nop(s);
1238
1239 label2_ptr = s->code_ptr;
1240 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
1241 tcg_out_nop(s);
1242
1243 /* label1: fast path */
1244 reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
1245
1246 tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
1247 offsetof(CPUArchState, tlb_table[mem_index][0].addend));
1248 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
1249 #else
1250 if (GUEST_BASE == (int16_t)GUEST_BASE) {
1251 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_A0, addr_regl, GUEST_BASE);
1252 } else {
1253 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, GUEST_BASE);
1254 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
1255 }
1256
1257 #endif
1258
1259 switch(opc) {
1260 case 0:
1261 tcg_out_opc_imm(s, OPC_SB, data_reg1, TCG_REG_A0, 0);
1262 break;
1263 case 1:
1264 if (TCG_NEED_BSWAP) {
1265 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_T0, data_reg1, 0xffff);
1266 tcg_out_bswap16(s, TCG_REG_T0, TCG_REG_T0);
1267 tcg_out_opc_imm(s, OPC_SH, TCG_REG_T0, TCG_REG_A0, 0);
1268 } else {
1269 tcg_out_opc_imm(s, OPC_SH, data_reg1, TCG_REG_A0, 0);
1270 }
1271 break;
1272 case 2:
1273 if (TCG_NEED_BSWAP) {
1274 tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1275 tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
1276 } else {
1277 tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
1278 }
1279 break;
1280 case 3:
1281 if (TCG_NEED_BSWAP) {
1282 tcg_out_bswap32(s, TCG_REG_T0, data_reg2);
1283 tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
1284 tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1285 tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 4);
1286 } else {
1287 tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
1288 tcg_out_opc_imm(s, OPC_SW, data_reg2, TCG_REG_A0, 4);
1289 }
1290 break;
1291 default:
1292 tcg_abort();
1293 }
1294
1295 #if defined(CONFIG_SOFTMMU)
1296 reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
1297 #endif
1298 }
1299
1300 static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1301 const TCGArg *args, const int *const_args)
1302 {
1303 switch(opc) {
1304 case INDEX_op_exit_tb:
1305 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_V0, args[0]);
1306 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, (tcg_target_long)tb_ret_addr);
1307 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1308 tcg_out_nop(s);
1309 break;
1310 case INDEX_op_goto_tb:
1311 if (s->tb_jmp_offset) {
1312 /* direct jump method */
1313 tcg_abort();
1314 } else {
1315 /* indirect jump method */
1316 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, (tcg_target_long)(s->tb_next + args[0]));
1317 tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_AT, TCG_REG_AT, 0);
1318 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1319 }
1320 tcg_out_nop(s);
1321 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1322 break;
1323 case INDEX_op_call:
1324 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, args[0], 0);
1325 tcg_out_nop(s);
1326 break;
1327 case INDEX_op_br:
1328 tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, args[0]);
1329 break;
1330
1331 case INDEX_op_mov_i32:
1332 tcg_out_mov(s, TCG_TYPE_I32, args[0], args[1]);
1333 break;
1334 case INDEX_op_movi_i32:
1335 tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1336 break;
1337
1338 case INDEX_op_ld8u_i32:
1339 tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]);
1340 break;
1341 case INDEX_op_ld8s_i32:
1342 tcg_out_ldst(s, OPC_LB, args[0], args[1], args[2]);
1343 break;
1344 case INDEX_op_ld16u_i32:
1345 tcg_out_ldst(s, OPC_LHU, args[0], args[1], args[2]);
1346 break;
1347 case INDEX_op_ld16s_i32:
1348 tcg_out_ldst(s, OPC_LH, args[0], args[1], args[2]);
1349 break;
1350 case INDEX_op_ld_i32:
1351 tcg_out_ldst(s, OPC_LW, args[0], args[1], args[2]);
1352 break;
1353 case INDEX_op_st8_i32:
1354 tcg_out_ldst(s, OPC_SB, args[0], args[1], args[2]);
1355 break;
1356 case INDEX_op_st16_i32:
1357 tcg_out_ldst(s, OPC_SH, args[0], args[1], args[2]);
1358 break;
1359 case INDEX_op_st_i32:
1360 tcg_out_ldst(s, OPC_SW, args[0], args[1], args[2]);
1361 break;
1362
1363 case INDEX_op_add_i32:
1364 if (const_args[2]) {
1365 tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], args[2]);
1366 } else {
1367 tcg_out_opc_reg(s, OPC_ADDU, args[0], args[1], args[2]);
1368 }
1369 break;
1370 case INDEX_op_add2_i32:
1371 if (const_args[4]) {
1372 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], args[4]);
1373 } else {
1374 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, args[2], args[4]);
1375 }
1376 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, TCG_REG_AT, args[2]);
1377 if (const_args[5]) {
1378 tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], args[5]);
1379 } else {
1380 tcg_out_opc_reg(s, OPC_ADDU, args[1], args[3], args[5]);
1381 }
1382 tcg_out_opc_reg(s, OPC_ADDU, args[1], args[1], TCG_REG_T0);
1383 tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
1384 break;
1385 case INDEX_op_sub_i32:
1386 if (const_args[2]) {
1387 tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], -args[2]);
1388 } else {
1389 tcg_out_opc_reg(s, OPC_SUBU, args[0], args[1], args[2]);
1390 }
1391 break;
1392 case INDEX_op_sub2_i32:
1393 if (const_args[4]) {
1394 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], -args[4]);
1395 } else {
1396 tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, args[2], args[4]);
1397 }
1398 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, args[2], TCG_REG_AT);
1399 if (const_args[5]) {
1400 tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], -args[5]);
1401 } else {
1402 tcg_out_opc_reg(s, OPC_SUBU, args[1], args[3], args[5]);
1403 }
1404 tcg_out_opc_reg(s, OPC_SUBU, args[1], args[1], TCG_REG_T0);
1405 tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
1406 break;
1407 case INDEX_op_mul_i32:
1408 if (use_mips32_instructions) {
1409 tcg_out_opc_reg(s, OPC_MUL, args[0], args[1], args[2]);
1410 } else {
1411 tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
1412 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1413 }
1414 break;
1415 case INDEX_op_muls2_i32:
1416 tcg_out_opc_reg(s, OPC_MULT, 0, args[2], args[3]);
1417 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1418 tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
1419 break;
1420 case INDEX_op_mulu2_i32:
1421 tcg_out_opc_reg(s, OPC_MULTU, 0, args[2], args[3]);
1422 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1423 tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
1424 break;
1425 case INDEX_op_mulsh_i32:
1426 tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
1427 tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1428 break;
1429 case INDEX_op_muluh_i32:
1430 tcg_out_opc_reg(s, OPC_MULTU, 0, args[1], args[2]);
1431 tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1432 break;
1433 case INDEX_op_div_i32:
1434 tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1435 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1436 break;
1437 case INDEX_op_divu_i32:
1438 tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1439 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1440 break;
1441 case INDEX_op_rem_i32:
1442 tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1443 tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1444 break;
1445 case INDEX_op_remu_i32:
1446 tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1447 tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1448 break;
1449
1450 case INDEX_op_and_i32:
1451 if (const_args[2]) {
1452 tcg_out_opc_imm(s, OPC_ANDI, args[0], args[1], args[2]);
1453 } else {
1454 tcg_out_opc_reg(s, OPC_AND, args[0], args[1], args[2]);
1455 }
1456 break;
1457 case INDEX_op_or_i32:
1458 if (const_args[2]) {
1459 tcg_out_opc_imm(s, OPC_ORI, args[0], args[1], args[2]);
1460 } else {
1461 tcg_out_opc_reg(s, OPC_OR, args[0], args[1], args[2]);
1462 }
1463 break;
1464 case INDEX_op_nor_i32:
1465 tcg_out_opc_reg(s, OPC_NOR, args[0], args[1], args[2]);
1466 break;
1467 case INDEX_op_not_i32:
1468 tcg_out_opc_reg(s, OPC_NOR, args[0], TCG_REG_ZERO, args[1]);
1469 break;
1470 case INDEX_op_xor_i32:
1471 if (const_args[2]) {
1472 tcg_out_opc_imm(s, OPC_XORI, args[0], args[1], args[2]);
1473 } else {
1474 tcg_out_opc_reg(s, OPC_XOR, args[0], args[1], args[2]);
1475 }
1476 break;
1477
1478 case INDEX_op_sar_i32:
1479 if (const_args[2]) {
1480 tcg_out_opc_sa(s, OPC_SRA, args[0], args[1], args[2]);
1481 } else {
1482 tcg_out_opc_reg(s, OPC_SRAV, args[0], args[2], args[1]);
1483 }
1484 break;
1485 case INDEX_op_shl_i32:
1486 if (const_args[2]) {
1487 tcg_out_opc_sa(s, OPC_SLL, args[0], args[1], args[2]);
1488 } else {
1489 tcg_out_opc_reg(s, OPC_SLLV, args[0], args[2], args[1]);
1490 }
1491 break;
1492 case INDEX_op_shr_i32:
1493 if (const_args[2]) {
1494 tcg_out_opc_sa(s, OPC_SRL, args[0], args[1], args[2]);
1495 } else {
1496 tcg_out_opc_reg(s, OPC_SRLV, args[0], args[2], args[1]);
1497 }
1498 break;
1499 case INDEX_op_rotl_i32:
1500 if (const_args[2]) {
1501 tcg_out_opc_sa(s, OPC_ROTR, args[0], args[1], 0x20 - args[2]);
1502 } else {
1503 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, 32);
1504 tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, TCG_REG_AT, args[2]);
1505 tcg_out_opc_reg(s, OPC_ROTRV, args[0], TCG_REG_AT, args[1]);
1506 }
1507 break;
1508 case INDEX_op_rotr_i32:
1509 if (const_args[2]) {
1510 tcg_out_opc_sa(s, OPC_ROTR, args[0], args[1], args[2]);
1511 } else {
1512 tcg_out_opc_reg(s, OPC_ROTRV, args[0], args[2], args[1]);
1513 }
1514 break;
1515
1516 case INDEX_op_bswap16_i32:
1517 tcg_out_opc_reg(s, OPC_WSBH, args[0], 0, args[1]);
1518 break;
1519 case INDEX_op_bswap32_i32:
1520 tcg_out_opc_reg(s, OPC_WSBH, args[0], 0, args[1]);
1521 tcg_out_opc_sa(s, OPC_ROTR, args[0], args[0], 16);
1522 break;
1523
1524 case INDEX_op_ext8s_i32:
1525 tcg_out_opc_reg(s, OPC_SEB, args[0], 0, args[1]);
1526 break;
1527 case INDEX_op_ext16s_i32:
1528 tcg_out_opc_reg(s, OPC_SEH, args[0], 0, args[1]);
1529 break;
1530
1531 case INDEX_op_deposit_i32:
1532 tcg_out_opc_imm(s, OPC_INS, args[0], args[2],
1533 ((args[3] + args[4] - 1) << 11) | (args[3] << 6));
1534 break;
1535
1536 case INDEX_op_brcond_i32:
1537 tcg_out_brcond(s, args[2], args[0], args[1], args[3]);
1538 break;
1539 case INDEX_op_brcond2_i32:
1540 tcg_out_brcond2(s, args[4], args[0], args[1], args[2], args[3], args[5]);
1541 break;
1542
1543 case INDEX_op_movcond_i32:
1544 tcg_out_movcond(s, args[5], args[0], args[1], args[2], args[3]);
1545 break;
1546
1547 case INDEX_op_setcond_i32:
1548 tcg_out_setcond(s, args[3], args[0], args[1], args[2]);
1549 break;
1550 case INDEX_op_setcond2_i32:
1551 tcg_out_setcond2(s, args[5], args[0], args[1], args[2], args[3], args[4]);
1552 break;
1553
1554 case INDEX_op_qemu_ld8u:
1555 tcg_out_qemu_ld(s, args, 0);
1556 break;
1557 case INDEX_op_qemu_ld8s:
1558 tcg_out_qemu_ld(s, args, 0 | 4);
1559 break;
1560 case INDEX_op_qemu_ld16u:
1561 tcg_out_qemu_ld(s, args, 1);
1562 break;
1563 case INDEX_op_qemu_ld16s:
1564 tcg_out_qemu_ld(s, args, 1 | 4);
1565 break;
1566 case INDEX_op_qemu_ld32:
1567 tcg_out_qemu_ld(s, args, 2);
1568 break;
1569 case INDEX_op_qemu_ld64:
1570 tcg_out_qemu_ld(s, args, 3);
1571 break;
1572 case INDEX_op_qemu_st8:
1573 tcg_out_qemu_st(s, args, 0);
1574 break;
1575 case INDEX_op_qemu_st16:
1576 tcg_out_qemu_st(s, args, 1);
1577 break;
1578 case INDEX_op_qemu_st32:
1579 tcg_out_qemu_st(s, args, 2);
1580 break;
1581 case INDEX_op_qemu_st64:
1582 tcg_out_qemu_st(s, args, 3);
1583 break;
1584
1585 default:
1586 tcg_abort();
1587 }
1588 }
1589
1590 static const TCGTargetOpDef mips_op_defs[] = {
1591 { INDEX_op_exit_tb, { } },
1592 { INDEX_op_goto_tb, { } },
1593 { INDEX_op_call, { "C" } },
1594 { INDEX_op_br, { } },
1595
1596 { INDEX_op_mov_i32, { "r", "r" } },
1597 { INDEX_op_movi_i32, { "r" } },
1598 { INDEX_op_ld8u_i32, { "r", "r" } },
1599 { INDEX_op_ld8s_i32, { "r", "r" } },
1600 { INDEX_op_ld16u_i32, { "r", "r" } },
1601 { INDEX_op_ld16s_i32, { "r", "r" } },
1602 { INDEX_op_ld_i32, { "r", "r" } },
1603 { INDEX_op_st8_i32, { "rZ", "r" } },
1604 { INDEX_op_st16_i32, { "rZ", "r" } },
1605 { INDEX_op_st_i32, { "rZ", "r" } },
1606
1607 { INDEX_op_add_i32, { "r", "rZ", "rJ" } },
1608 { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
1609 { INDEX_op_muls2_i32, { "r", "r", "rZ", "rZ" } },
1610 { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
1611 { INDEX_op_mulsh_i32, { "r", "rZ", "rZ" } },
1612 { INDEX_op_muluh_i32, { "r", "rZ", "rZ" } },
1613 { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
1614 { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
1615 { INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
1616 { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
1617 { INDEX_op_sub_i32, { "r", "rZ", "rJ" } },
1618
1619 { INDEX_op_and_i32, { "r", "rZ", "rI" } },
1620 { INDEX_op_nor_i32, { "r", "rZ", "rZ" } },
1621 { INDEX_op_not_i32, { "r", "rZ" } },
1622 { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
1623 { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
1624
1625 { INDEX_op_shl_i32, { "r", "rZ", "ri" } },
1626 { INDEX_op_shr_i32, { "r", "rZ", "ri" } },
1627 { INDEX_op_sar_i32, { "r", "rZ", "ri" } },
1628 { INDEX_op_rotr_i32, { "r", "rZ", "ri" } },
1629 { INDEX_op_rotl_i32, { "r", "rZ", "ri" } },
1630
1631 { INDEX_op_bswap16_i32, { "r", "r" } },
1632 { INDEX_op_bswap32_i32, { "r", "r" } },
1633
1634 { INDEX_op_ext8s_i32, { "r", "rZ" } },
1635 { INDEX_op_ext16s_i32, { "r", "rZ" } },
1636
1637 { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
1638
1639 { INDEX_op_brcond_i32, { "rZ", "rZ" } },
1640 { INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rZ", "0" } },
1641 { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
1642 { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
1643
1644 { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJ", "rJ" } },
1645 { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJ", "rJ" } },
1646 { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
1647
1648 #if TARGET_LONG_BITS == 32
1649 { INDEX_op_qemu_ld8u, { "L", "lZ" } },
1650 { INDEX_op_qemu_ld8s, { "L", "lZ" } },
1651 { INDEX_op_qemu_ld16u, { "L", "lZ" } },
1652 { INDEX_op_qemu_ld16s, { "L", "lZ" } },
1653 { INDEX_op_qemu_ld32, { "L", "lZ" } },
1654 { INDEX_op_qemu_ld64, { "L", "L", "lZ" } },
1655
1656 { INDEX_op_qemu_st8, { "SZ", "SZ" } },
1657 { INDEX_op_qemu_st16, { "SZ", "SZ" } },
1658 { INDEX_op_qemu_st32, { "SZ", "SZ" } },
1659 { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ" } },
1660 #else
1661 { INDEX_op_qemu_ld8u, { "L", "lZ", "lZ" } },
1662 { INDEX_op_qemu_ld8s, { "L", "lZ", "lZ" } },
1663 { INDEX_op_qemu_ld16u, { "L", "lZ", "lZ" } },
1664 { INDEX_op_qemu_ld16s, { "L", "lZ", "lZ" } },
1665 { INDEX_op_qemu_ld32, { "L", "lZ", "lZ" } },
1666 { INDEX_op_qemu_ld64, { "L", "L", "lZ", "lZ" } },
1667
1668 { INDEX_op_qemu_st8, { "SZ", "SZ", "SZ" } },
1669 { INDEX_op_qemu_st16, { "SZ", "SZ", "SZ" } },
1670 { INDEX_op_qemu_st32, { "SZ", "SZ", "SZ" } },
1671 { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ", "SZ" } },
1672 #endif
1673 { -1 },
1674 };
1675
1676 static int tcg_target_callee_save_regs[] = {
1677 TCG_REG_S0, /* used for the global env (TCG_AREG0) */
1678 TCG_REG_S1,
1679 TCG_REG_S2,
1680 TCG_REG_S3,
1681 TCG_REG_S4,
1682 TCG_REG_S5,
1683 TCG_REG_S6,
1684 TCG_REG_S7,
1685 TCG_REG_FP,
1686 TCG_REG_RA, /* should be last for ABI compliance */
1687 };
1688
1689 /* The Linux kernel doesn't provide any information about the available
1690 instruction set. Probe it using a signal handler. */
1691
1692 #include <signal.h>
1693
1694 #ifndef use_movnz_instructions
1695 bool use_movnz_instructions = false;
1696 #endif
1697
1698 #ifndef use_mips32_instructions
1699 bool use_mips32_instructions = false;
1700 #endif
1701
1702 #ifndef use_mips32r2_instructions
1703 bool use_mips32r2_instructions = false;
1704 #endif
1705
1706 static volatile sig_atomic_t got_sigill;
1707
1708 static void sigill_handler(int signo, siginfo_t *si, void *data)
1709 {
1710 /* Skip the faulty instruction */
1711 ucontext_t *uc = (ucontext_t *)data;
1712 uc->uc_mcontext.pc += 4;
1713
1714 got_sigill = 1;
1715 }
1716
1717 static void tcg_target_detect_isa(void)
1718 {
1719 struct sigaction sa_old, sa_new;
1720
1721 memset(&sa_new, 0, sizeof(sa_new));
1722 sa_new.sa_flags = SA_SIGINFO;
1723 sa_new.sa_sigaction = sigill_handler;
1724 sigaction(SIGILL, &sa_new, &sa_old);
1725
1726 /* Probe for movn/movz, necessary to implement movcond. */
1727 #ifndef use_movnz_instructions
1728 got_sigill = 0;
1729 asm volatile(".set push\n"
1730 ".set mips32\n"
1731 "movn $zero, $zero, $zero\n"
1732 "movz $zero, $zero, $zero\n"
1733 ".set pop\n"
1734 : : : );
1735 use_movnz_instructions = !got_sigill;
1736 #endif
1737
1738 /* Probe for MIPS32 instructions. As no subsetting is allowed
1739 by the specification, it is only necessary to probe for one
1740 of the instructions. */
1741 #ifndef use_mips32_instructions
1742 got_sigill = 0;
1743 asm volatile(".set push\n"
1744 ".set mips32\n"
1745 "mul $zero, $zero\n"
1746 ".set pop\n"
1747 : : : );
1748 use_mips32_instructions = !got_sigill;
1749 #endif
1750
1751 /* Probe for MIPS32r2 instructions if MIPS32 instructions are
1752 available. As no subsetting is allowed by the specification,
1753 it is only necessary to probe for one of the instructions. */
1754 #ifndef use_mips32r2_instructions
1755 if (use_mips32_instructions) {
1756 got_sigill = 0;
1757 asm volatile(".set push\n"
1758 ".set mips32r2\n"
1759 "seb $zero, $zero\n"
1760 ".set pop\n"
1761 : : : );
1762 use_mips32r2_instructions = !got_sigill;
1763 }
1764 #endif
1765
1766 sigaction(SIGILL, &sa_old, NULL);
1767 }
1768
1769 /* Generate global QEMU prologue and epilogue code */
1770 static void tcg_target_qemu_prologue(TCGContext *s)
1771 {
1772 int i, frame_size;
1773
1774 /* reserve some stack space, also for TCG temps. */
1775 frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1776 + TCG_STATIC_CALL_ARGS_SIZE
1777 + CPU_TEMP_BUF_NLONGS * sizeof(long);
1778 frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1779 ~(TCG_TARGET_STACK_ALIGN - 1);
1780 tcg_set_frame(s, TCG_REG_SP, ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1781 + TCG_STATIC_CALL_ARGS_SIZE,
1782 CPU_TEMP_BUF_NLONGS * sizeof(long));
1783
1784 /* TB prologue */
1785 tcg_out_addi(s, TCG_REG_SP, -frame_size);
1786 for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1787 tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1788 TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1789 }
1790
1791 /* Call generated code */
1792 tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1], 0);
1793 tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
1794 tb_ret_addr = s->code_ptr;
1795
1796 /* TB epilogue */
1797 for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1798 tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1799 TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1800 }
1801
1802 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
1803 tcg_out_addi(s, TCG_REG_SP, frame_size);
1804 }
1805
1806 static void tcg_target_init(TCGContext *s)
1807 {
1808 tcg_target_detect_isa();
1809 tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
1810 tcg_regset_set(tcg_target_call_clobber_regs,
1811 (1 << TCG_REG_V0) |
1812 (1 << TCG_REG_V1) |
1813 (1 << TCG_REG_A0) |
1814 (1 << TCG_REG_A1) |
1815 (1 << TCG_REG_A2) |
1816 (1 << TCG_REG_A3) |
1817 (1 << TCG_REG_T1) |
1818 (1 << TCG_REG_T2) |
1819 (1 << TCG_REG_T3) |
1820 (1 << TCG_REG_T4) |
1821 (1 << TCG_REG_T5) |
1822 (1 << TCG_REG_T6) |
1823 (1 << TCG_REG_T7) |
1824 (1 << TCG_REG_T8) |
1825 (1 << TCG_REG_T9));
1826
1827 tcg_regset_clear(s->reserved_regs);
1828 tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
1829 tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0); /* kernel use only */
1830 tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1); /* kernel use only */
1831 tcg_regset_set_reg(s->reserved_regs, TCG_REG_AT); /* internal use */
1832 tcg_regset_set_reg(s->reserved_regs, TCG_REG_T0); /* internal use */
1833 tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return address */
1834 tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */
1835 tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP); /* global pointer */
1836
1837 tcg_add_target_add_op_defs(mips_op_defs);
1838 }