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