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 int 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 int 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 int tcg_target_call_oarg_regs[2] = {
105     TCG_REG_V0,
106     TCG_REG_V1
107 };
108 
109 static uint8_t *tb_ret_addr;
110 
reloc_lo16_val(void * pc,tcg_target_long target)111 static inline uint32_t reloc_lo16_val (void *pc, tcg_target_long target)
112 {
113     return target & 0xffff;
114 }
115 
reloc_lo16(void * pc,tcg_target_long target)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 
reloc_hi16_val(void * pc,tcg_target_long target)122 static inline uint32_t reloc_hi16_val (void *pc, tcg_target_long target)
123 {
124     return (target >> 16) & 0xffff;
125 }
126 
reloc_hi16(void * pc,tcg_target_long target)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 
reloc_pc16_val(void * pc,tcg_target_long target)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 
reloc_pc16(void * pc,tcg_target_long target)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 
reloc_26_val(void * pc,tcg_target_long target)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 
reloc_pc26(void * pc,tcg_target_long target)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 
patch_reloc(uint8_t * code_ptr,int type,tcg_target_long value,tcg_target_long addend)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 */
tcg_target_get_call_iarg_regs_count(int flags)189 static inline int tcg_target_get_call_iarg_regs_count(int flags)
190 {
191     return 4;
192 }
193 
194 /* parse target specific constraints */
target_parse_constraint(TCGArgConstraint * ct,const char ** pct_str)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 #endif
221         break;
222     case 'S': /* qemu_st constraint */
223         ct->ct |= TCG_CT_REG;
224         tcg_regset_set(ct->u.regs, 0xffffffff);
225 #if defined(CONFIG_SOFTMMU)
226         tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
227 # if TARGET_LONG_BITS == 64
228         tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1);
229 # endif
230         tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
231 #endif
232         break;
233     case 'I':
234         ct->ct |= TCG_CT_CONST_U16;
235         break;
236     case 'J':
237         ct->ct |= TCG_CT_CONST_S16;
238         break;
239     case 'Z':
240         /* We are cheating a bit here, using the fact that the register
241            ZERO is also the register number 0. Hence there is no need
242            to check for const_args in each instruction. */
243         ct->ct |= TCG_CT_CONST_ZERO;
244         break;
245     default:
246         return -1;
247     }
248     ct_str++;
249     *pct_str = ct_str;
250     return 0;
251 }
252 
253 /* test if a constant matches the constraint */
tcg_target_const_match(tcg_target_long val,const TCGArgConstraint * arg_ct)254 static inline int tcg_target_const_match(tcg_target_long val,
255                                          const TCGArgConstraint *arg_ct)
256 {
257     int ct;
258     ct = arg_ct->ct;
259     if (ct & TCG_CT_CONST)
260         return 1;
261     else if ((ct & TCG_CT_CONST_ZERO) && val == 0)
262         return 1;
263     else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val)
264         return 1;
265     else if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val)
266         return 1;
267     else
268         return 0;
269 }
270 
271 /* instruction opcodes */
272 enum {
273     OPC_SPECIAL  = 0x00 << 26,
274     OPC_BEQ      = 0x04 << 26,
275     OPC_BNE      = 0x05 << 26,
276     OPC_ADDIU    = 0x09 << 26,
277     OPC_ANDI     = 0x0C << 26,
278     OPC_ORI      = 0x0D << 26,
279     OPC_XORI     = 0x0E << 26,
280     OPC_LUI      = 0x0F << 26,
281     OPC_LB       = 0x20 << 26,
282     OPC_LH       = 0x21 << 26,
283     OPC_LW       = 0x23 << 26,
284     OPC_LBU      = 0x24 << 26,
285     OPC_LHU      = 0x25 << 26,
286     OPC_LWU      = 0x27 << 26,
287     OPC_SB       = 0x28 << 26,
288     OPC_SH       = 0x29 << 26,
289     OPC_SW       = 0x2B << 26,
290     OPC_SLL      = OPC_SPECIAL | 0x00,
291     OPC_SRL      = OPC_SPECIAL | 0x02,
292     OPC_SRA      = OPC_SPECIAL | 0x03,
293     OPC_SLLV     = OPC_SPECIAL | 0x04,
294     OPC_SRLV     = OPC_SPECIAL | 0x06,
295     OPC_SRAV     = OPC_SPECIAL | 0x07,
296     OPC_JR       = OPC_SPECIAL | 0x08,
297     OPC_JALR     = OPC_SPECIAL | 0x09,
298     OPC_MFHI     = OPC_SPECIAL | 0x10,
299     OPC_MFLO     = OPC_SPECIAL | 0x12,
300     OPC_MULT     = OPC_SPECIAL | 0x18,
301     OPC_MULTU    = OPC_SPECIAL | 0x19,
302     OPC_DIV      = OPC_SPECIAL | 0x1A,
303     OPC_DIVU     = OPC_SPECIAL | 0x1B,
304     OPC_ADDU     = OPC_SPECIAL | 0x21,
305     OPC_SUBU     = OPC_SPECIAL | 0x23,
306     OPC_AND      = OPC_SPECIAL | 0x24,
307     OPC_OR       = OPC_SPECIAL | 0x25,
308     OPC_XOR      = OPC_SPECIAL | 0x26,
309     OPC_NOR      = OPC_SPECIAL | 0x27,
310     OPC_SLT      = OPC_SPECIAL | 0x2A,
311     OPC_SLTU     = OPC_SPECIAL | 0x2B,
312 };
313 
314 /*
315  * Type reg
316  */
tcg_out_opc_reg(TCGContext * s,int opc,int rd,int rs,int rt)317 static inline void tcg_out_opc_reg(TCGContext *s, int opc, int rd, int rs, int rt)
318 {
319     int32_t inst;
320 
321     inst = opc;
322     inst |= (rs & 0x1F) << 21;
323     inst |= (rt & 0x1F) << 16;
324     inst |= (rd & 0x1F) << 11;
325     tcg_out32(s, inst);
326 }
327 
328 /*
329  * Type immediate
330  */
tcg_out_opc_imm(TCGContext * s,int opc,int rt,int rs,int imm)331 static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int imm)
332 {
333     int32_t inst;
334 
335     inst = opc;
336     inst |= (rs & 0x1F) << 21;
337     inst |= (rt & 0x1F) << 16;
338     inst |= (imm & 0xffff);
339     tcg_out32(s, inst);
340 }
341 
342 /*
343  * Type sa
344  */
tcg_out_opc_sa(TCGContext * s,int opc,int rd,int rt,int sa)345 static inline void tcg_out_opc_sa(TCGContext *s, int opc, int rd, int rt, int sa)
346 {
347     int32_t inst;
348 
349     inst = opc;
350     inst |= (rt & 0x1F) << 16;
351     inst |= (rd & 0x1F) << 11;
352     inst |= (sa & 0x1F) <<  6;
353     tcg_out32(s, inst);
354 
355 }
356 
tcg_out_nop(TCGContext * s)357 static inline void tcg_out_nop(TCGContext *s)
358 {
359     tcg_out32(s, 0);
360 }
361 
tcg_out_mov(TCGContext * s,int ret,int arg)362 static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
363 {
364     tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
365 }
366 
tcg_out_movi(TCGContext * s,TCGType type,int reg,int32_t arg)367 static inline void tcg_out_movi(TCGContext *s, TCGType type,
368                                 int reg, int32_t arg)
369 {
370     if (arg == (int16_t)arg) {
371         tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
372     } else if (arg == (uint16_t)arg) {
373         tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
374     } else {
375         tcg_out_opc_imm(s, OPC_LUI, reg, 0, arg >> 16);
376         tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0xffff);
377     }
378 }
379 
tcg_out_bswap16(TCGContext * s,int ret,int arg)380 static inline void tcg_out_bswap16(TCGContext *s, int ret, int arg)
381 {
382     /* ret and arg can't be register at */
383     if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
384         tcg_abort();
385     }
386 
387     tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
388     tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0x00ff);
389 
390     tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
391     tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
392     tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
393 }
394 
tcg_out_bswap16s(TCGContext * s,int ret,int arg)395 static inline void tcg_out_bswap16s(TCGContext *s, int ret, int arg)
396 {
397     /* ret and arg can't be register at */
398     if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
399         tcg_abort();
400     }
401 
402     tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
403     tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff);
404 
405     tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
406     tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
407     tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
408 }
409 
tcg_out_bswap32(TCGContext * s,int ret,int arg)410 static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg)
411 {
412     /* ret and arg must be different and can't be register at */
413     if (ret == arg || ret == TCG_REG_AT || arg == TCG_REG_AT) {
414         tcg_abort();
415     }
416 
417     tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
418 
419     tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 24);
420     tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
421 
422     tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, arg, 0xff00);
423     tcg_out_opc_sa(s, OPC_SLL, TCG_REG_AT, TCG_REG_AT, 8);
424     tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
425 
426     tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
427     tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff00);
428     tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
429 }
430 
tcg_out_ldst(TCGContext * s,int opc,int arg,int arg1,tcg_target_long arg2)431 static inline void tcg_out_ldst(TCGContext *s, int opc, int arg,
432                               int arg1, tcg_target_long arg2)
433 {
434     if (arg2 == (int16_t) arg2) {
435         tcg_out_opc_imm(s, opc, arg, arg1, arg2);
436     } else {
437         tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, arg2);
438         tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, TCG_REG_AT, arg1);
439         tcg_out_opc_imm(s, opc, arg, TCG_REG_AT, 0);
440     }
441 }
442 
tcg_out_ld(TCGContext * s,TCGType type,int arg,int arg1,tcg_target_long arg2)443 static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg,
444                               int arg1, tcg_target_long arg2)
445 {
446     tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
447 }
448 
tcg_out_st(TCGContext * s,TCGType type,int arg,int arg1,tcg_target_long arg2)449 static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
450                               int arg1, tcg_target_long arg2)
451 {
452     tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
453 }
454 
tcg_out_addi(TCGContext * s,int reg,tcg_target_long val)455 static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
456 {
457     if (val == (int16_t)val) {
458         tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
459     } else {
460         tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, val);
461         tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_REG_AT);
462     }
463 }
464 
tcg_out_brcond(TCGContext * s,int cond,int arg1,int arg2,int label_index)465 static void tcg_out_brcond(TCGContext *s, int cond, int arg1,
466                            int arg2, int label_index)
467 {
468     TCGLabel *l = &s->labels[label_index];
469 
470     switch (cond) {
471     case TCG_COND_EQ:
472         tcg_out_opc_imm(s, OPC_BEQ, arg1, arg2, 0);
473         break;
474     case TCG_COND_NE:
475         tcg_out_opc_imm(s, OPC_BNE, arg1, arg2, 0);
476         break;
477     case TCG_COND_LT:
478         tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
479         tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
480         break;
481     case TCG_COND_LTU:
482         tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
483         tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
484         break;
485     case TCG_COND_GE:
486         tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
487         tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
488         break;
489     case TCG_COND_GEU:
490         tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
491         tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
492         break;
493     case TCG_COND_LE:
494         tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
495         tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
496         break;
497     case TCG_COND_LEU:
498         tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
499         tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
500         break;
501     case TCG_COND_GT:
502         tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
503         tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
504         break;
505     case TCG_COND_GTU:
506         tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
507         tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
508         break;
509     default:
510         tcg_abort();
511         break;
512     }
513     if (l->has_value) {
514         reloc_pc16(s->code_ptr - 4, l->u.value);
515     } else {
516         tcg_out_reloc(s, s->code_ptr - 4, R_MIPS_PC16, label_index, 0);
517     }
518     tcg_out_nop(s);
519 }
520 
521 /* XXX: we implement it at the target level to avoid having to
522    handle cross basic blocks temporaries */
tcg_out_brcond2(TCGContext * s,int cond,int arg1,int arg2,int arg3,int arg4,int label_index)523 static void tcg_out_brcond2(TCGContext *s, int cond, int arg1,
524                             int arg2, int arg3, int arg4, int label_index)
525 {
526     void *label_ptr;
527 
528     switch(cond) {
529     case TCG_COND_NE:
530         tcg_out_brcond(s, TCG_COND_NE, arg2, arg4, label_index);
531         tcg_out_brcond(s, TCG_COND_NE, arg1, arg3, label_index);
532         return;
533     case TCG_COND_EQ:
534         break;
535     case TCG_COND_LT:
536     case TCG_COND_LE:
537         tcg_out_brcond(s, TCG_COND_LT, arg2, arg4, label_index);
538         break;
539     case TCG_COND_GT:
540     case TCG_COND_GE:
541         tcg_out_brcond(s, TCG_COND_GT, arg2, arg4, label_index);
542         break;
543     case TCG_COND_LTU:
544     case TCG_COND_LEU:
545         tcg_out_brcond(s, TCG_COND_LTU, arg2, arg4, label_index);
546         break;
547     case TCG_COND_GTU:
548     case TCG_COND_GEU:
549         tcg_out_brcond(s, TCG_COND_GTU, arg2, arg4, label_index);
550         break;
551     default:
552         tcg_abort();
553     }
554 
555     label_ptr = s->code_ptr;
556     tcg_out_opc_imm(s, OPC_BNE, arg2, arg4, 0);
557     tcg_out_nop(s);
558 
559     switch(cond) {
560     case TCG_COND_EQ:
561         tcg_out_brcond(s, TCG_COND_EQ, arg1, arg3, label_index);
562         break;
563     case TCG_COND_LT:
564     case TCG_COND_LTU:
565         tcg_out_brcond(s, TCG_COND_LTU, arg1, arg3, label_index);
566         break;
567     case TCG_COND_LE:
568     case TCG_COND_LEU:
569         tcg_out_brcond(s, TCG_COND_LEU, arg1, arg3, label_index);
570         break;
571     case TCG_COND_GT:
572     case TCG_COND_GTU:
573         tcg_out_brcond(s, TCG_COND_GTU, arg1, arg3, label_index);
574         break;
575     case TCG_COND_GE:
576     case TCG_COND_GEU:
577         tcg_out_brcond(s, TCG_COND_GEU, arg1, arg3, label_index);
578         break;
579     default:
580         tcg_abort();
581     }
582 
583     reloc_pc16(label_ptr, (tcg_target_long) s->code_ptr);
584 }
585 
586 #if defined(CONFIG_SOFTMMU)
587 
588 #include "../../softmmu_defs.h"
589 
590 static void *qemu_ld_helpers[4] = {
591     __ldb_mmu,
592     __ldw_mmu,
593     __ldl_mmu,
594     __ldq_mmu,
595 };
596 
597 static void *qemu_st_helpers[4] = {
598     __stb_mmu,
599     __stw_mmu,
600     __stl_mmu,
601     __stq_mmu,
602 };
603 #endif
604 
tcg_out_qemu_ld(TCGContext * s,const TCGArg * args,int opc)605 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
606                             int opc)
607 {
608     int addr_regl, addr_reg1, addr_meml;
609     int data_regl, data_regh, data_reg1, data_reg2;
610     int mem_index, s_bits;
611 #if defined(CONFIG_SOFTMMU)
612     void *label1_ptr, *label2_ptr;
613     int sp_args;
614 #endif
615 #if TARGET_LONG_BITS == 64
616 # if defined(CONFIG_SOFTMMU)
617     uint8_t *label3_ptr;
618 # endif
619     int addr_regh, addr_reg2, addr_memh;
620 #endif
621     data_regl = *args++;
622     if (opc == 3)
623         data_regh = *args++;
624     else
625         data_regh = 0;
626     addr_regl = *args++;
627 #if TARGET_LONG_BITS == 64
628     addr_regh = *args++;
629 #endif
630     mem_index = *args;
631     s_bits = opc & 3;
632 
633     if (opc == 3) {
634 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
635         data_reg1 = data_regh;
636         data_reg2 = data_regl;
637 #else
638         data_reg1 = data_regl;
639         data_reg2 = data_regh;
640 #endif
641     } else {
642         data_reg1 = data_regl;
643         data_reg2 = 0;
644     }
645 #if TARGET_LONG_BITS == 64
646 # if defined(TCG_TARGET_WORDS_BIGENDIAN)
647     addr_reg1 = addr_regh;
648     addr_reg2 = addr_regl;
649     addr_memh = 0;
650     addr_meml = 4;
651 # else
652     addr_reg1 = addr_regl;
653     addr_reg2 = addr_regh;
654     addr_memh = 4;
655     addr_meml = 0;
656 # endif
657 #else
658     addr_reg1 = addr_regl;
659     addr_meml = 0;
660 #endif
661 
662 #if defined(CONFIG_SOFTMMU)
663     tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
664     tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
665     tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
666     tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
667                     offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_meml);
668     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
669     tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
670 
671 # if TARGET_LONG_BITS == 64
672     label3_ptr = s->code_ptr;
673     tcg_out_opc_imm(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT, 0);
674     tcg_out_nop(s);
675 
676     tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
677                     offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_memh);
678 
679     label1_ptr = s->code_ptr;
680     tcg_out_opc_imm(s, OPC_BEQ, addr_regh, TCG_REG_AT, 0);
681     tcg_out_nop(s);
682 
683     reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
684 # else
685     label1_ptr = s->code_ptr;
686     tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT, 0);
687     tcg_out_nop(s);
688 # endif
689 
690     /* slow path */
691     sp_args = TCG_REG_A0;
692     tcg_out_mov(s, sp_args++, addr_reg1);
693 # if TARGET_LONG_BITS == 64
694     tcg_out_mov(s, sp_args++, addr_reg2);
695 # endif
696     tcg_out_movi(s, TCG_TYPE_I32, sp_args++, mem_index);
697     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]);
698     tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
699     tcg_out_nop(s);
700 
701     switch(opc) {
702     case 0:
703         tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xff);
704         break;
705     case 0 | 4:
706         tcg_out_opc_sa(s, OPC_SLL, TCG_REG_V0, TCG_REG_V0, 24);
707         tcg_out_opc_sa(s, OPC_SRA, data_reg1, TCG_REG_V0, 24);
708         break;
709     case 1:
710         tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xffff);
711         break;
712     case 1 | 4:
713         tcg_out_opc_sa(s, OPC_SLL, TCG_REG_V0, TCG_REG_V0, 16);
714         tcg_out_opc_sa(s, OPC_SRA, data_reg1, TCG_REG_V0, 16);
715         break;
716     case 2:
717         tcg_out_mov(s, data_reg1, TCG_REG_V0);
718         break;
719     case 3:
720         tcg_out_mov(s, data_reg2, TCG_REG_V1);
721         tcg_out_mov(s, data_reg1, TCG_REG_V0);
722         break;
723     default:
724         tcg_abort();
725     }
726 
727     label2_ptr = s->code_ptr;
728     tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO, 0);
729     tcg_out_nop(s);
730 
731     /* label1: fast path */
732     reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
733 
734     tcg_out_opc_imm(s, OPC_LW, TCG_REG_V0, TCG_REG_A0,
735                     offsetof(CPUState, tlb_table[mem_index][0].addend) + addr_meml);
736     tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_V0, addr_regl);
737 
738     addr_reg1 = TCG_REG_V0;
739 #endif
740 
741     switch(opc) {
742     case 0:
743         tcg_out_opc_imm(s, OPC_LBU, data_reg1, addr_reg1, 0);
744         break;
745     case 0 | 4:
746         tcg_out_opc_imm(s, OPC_LB, data_reg1, addr_reg1, 0);
747         break;
748     case 1:
749         if (TCG_NEED_BSWAP) {
750             tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, addr_reg1, 0);
751             tcg_out_bswap16(s, data_reg1, TCG_REG_T0);
752         } else {
753             tcg_out_opc_imm(s, OPC_LHU, data_reg1, addr_reg1, 0);
754         }
755         break;
756     case 1 | 4:
757         if (TCG_NEED_BSWAP) {
758             tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, addr_reg1, 0);
759             tcg_out_bswap16s(s, data_reg1, TCG_REG_T0);
760         } else {
761             tcg_out_opc_imm(s, OPC_LH, data_reg1, addr_reg1, 0);
762         }
763         break;
764     case 2:
765         if (TCG_NEED_BSWAP) {
766             tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, addr_reg1, 0);
767             tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
768         } else {
769             tcg_out_opc_imm(s, OPC_LW, data_reg1, addr_reg1, 0);
770         }
771         break;
772     case 3:
773 #if !defined(CONFIG_SOFTMMU)
774         tcg_out_mov(s, TCG_REG_V0, addr_reg1);
775         addr_reg1 = TCG_REG_V0;
776 #endif
777         if (TCG_NEED_BSWAP) {
778             tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, addr_reg1, 4);
779             tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
780             tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, addr_reg1, 0);
781             tcg_out_bswap32(s, data_reg2, TCG_REG_T0);
782         } else {
783             tcg_out_opc_imm(s, OPC_LW, data_reg1, addr_reg1, 0);
784             tcg_out_opc_imm(s, OPC_LW, data_reg2, addr_reg1, 4);
785         }
786         break;
787     default:
788         tcg_abort();
789     }
790 
791 #if defined(CONFIG_SOFTMMU)
792     reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
793 #endif
794 }
795 
tcg_out_qemu_st(TCGContext * s,const TCGArg * args,int opc)796 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
797                             int opc)
798 {
799     int addr_regl, addr_reg1, addr_meml;
800     int data_regl, data_regh, data_reg1, data_reg2;
801     int mem_index, s_bits;
802 #if defined(CONFIG_SOFTMMU)
803     uint8_t *label1_ptr, *label2_ptr;
804     int sp_args;
805 #endif
806 #if TARGET_LONG_BITS == 64
807 # if defined(CONFIG_SOFTMMU)
808     uint8_t *label3_ptr;
809 # endif
810     int addr_regh, addr_reg2, addr_memh;
811 #endif
812 
813     data_regl = *args++;
814     if (opc == 3) {
815         data_regh = *args++;
816 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
817         data_reg1 = data_regh;
818         data_reg2 = data_regl;
819 #else
820         data_reg1 = data_regl;
821         data_reg2 = data_regh;
822 #endif
823     } else {
824         data_reg1 = data_regl;
825         data_reg2 = 0;
826         data_regh = 0;
827     }
828     addr_regl = *args++;
829 #if TARGET_LONG_BITS == 64
830     addr_regh = *args++;
831 # if defined(TCG_TARGET_WORDS_BIGENDIAN)
832     addr_reg1 = addr_regh;
833     addr_reg2 = addr_regl;
834     addr_memh = 0;
835     addr_meml = 4;
836 # else
837     addr_reg1 = addr_regl;
838     addr_reg2 = addr_regh;
839     addr_memh = 4;
840     addr_meml = 0;
841 # endif
842 #else
843     addr_reg1 = addr_regl;
844     addr_meml = 0;
845 #endif
846     mem_index = *args;
847     s_bits = opc;
848 
849 #if defined(CONFIG_SOFTMMU)
850     tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
851     tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
852     tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
853     tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
854                     offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_meml);
855     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
856     tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
857 
858 # if TARGET_LONG_BITS == 64
859     label3_ptr = s->code_ptr;
860     tcg_out_opc_imm(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT, 0);
861     tcg_out_nop(s);
862 
863     tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
864                     offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_memh);
865 
866     label1_ptr = s->code_ptr;
867     tcg_out_opc_imm(s, OPC_BEQ, addr_regh, TCG_REG_AT, 0);
868     tcg_out_nop(s);
869 
870     reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
871 # else
872     label1_ptr = s->code_ptr;
873     tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT, 0);
874     tcg_out_nop(s);
875 # endif
876 
877     /* slow path */
878     sp_args = TCG_REG_A0;
879     tcg_out_mov(s, sp_args++, addr_reg1);
880 # if TARGET_LONG_BITS == 64
881     tcg_out_mov(s, sp_args++, addr_reg2);
882 # endif
883     switch(opc) {
884     case 0:
885         tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xff);
886         break;
887     case 1:
888         tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xffff);
889         break;
890     case 2:
891         tcg_out_mov(s, sp_args++, data_reg1);
892         break;
893     case 3:
894         sp_args = (sp_args + 1) & ~1;
895         tcg_out_mov(s, sp_args++, data_reg1);
896         tcg_out_mov(s, sp_args++, data_reg2);
897         break;
898     default:
899         tcg_abort();
900     }
901     if (sp_args > TCG_REG_A3) {
902         /* Push mem_index on the stack */
903         tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, mem_index);
904         tcg_out_st(s, TCG_TYPE_I32, TCG_REG_AT, TCG_REG_SP, 16);
905     } else {
906         tcg_out_movi(s, TCG_TYPE_I32, sp_args, mem_index);
907     }
908 
909     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_st_helpers[s_bits]);
910     tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
911     tcg_out_nop(s);
912 
913     label2_ptr = s->code_ptr;
914     tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO, 0);
915     tcg_out_nop(s);
916 
917     /* label1: fast path */
918     reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
919 
920     tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
921                     offsetof(CPUState, tlb_table[mem_index][0].addend) + addr_meml);
922     tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
923 
924     addr_reg1 = TCG_REG_A0;
925 #endif
926 
927     switch(opc) {
928     case 0:
929         tcg_out_opc_imm(s, OPC_SB, data_reg1, addr_reg1, 0);
930         break;
931     case 1:
932         if (TCG_NEED_BSWAP) {
933             tcg_out_bswap16(s, TCG_REG_T0, data_reg1);
934             tcg_out_opc_imm(s, OPC_SH, TCG_REG_T0, addr_reg1, 0);
935         } else {
936             tcg_out_opc_imm(s, OPC_SH, data_reg1, addr_reg1, 0);
937         }
938         break;
939     case 2:
940         if (TCG_NEED_BSWAP) {
941             tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
942             tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, addr_reg1, 0);
943         } else {
944             tcg_out_opc_imm(s, OPC_SW, data_reg1, addr_reg1, 0);
945         }
946         break;
947     case 3:
948         if (TCG_NEED_BSWAP) {
949             tcg_out_bswap32(s, TCG_REG_T0, data_reg2);
950             tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, addr_reg1, 0);
951             tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
952             tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, addr_reg1, 4);
953         } else {
954             tcg_out_opc_imm(s, OPC_SW, data_reg1, addr_reg1, 0);
955             tcg_out_opc_imm(s, OPC_SW, data_reg2, addr_reg1, 4);
956         }
957         break;
958     default:
959         tcg_abort();
960     }
961 
962 #if defined(CONFIG_SOFTMMU)
963     reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
964 #endif
965 }
966 
tcg_out_op(TCGContext * s,int opc,const TCGArg * args,const int * const_args)967 static inline void tcg_out_op(TCGContext *s, int opc,
968                               const TCGArg *args, const int *const_args)
969 {
970     switch(opc) {
971     case INDEX_op_exit_tb:
972         tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_V0, args[0]);
973         tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, (tcg_target_long)tb_ret_addr);
974         tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
975         tcg_out_nop(s);
976         break;
977     case INDEX_op_goto_tb:
978         if (s->tb_jmp_offset) {
979             /* direct jump method */
980             tcg_abort();
981         } else {
982             /* indirect jump method */
983             tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, (tcg_target_long)(s->tb_next + args[0]));
984             tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_AT, TCG_REG_AT, 0);
985             tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
986         }
987         tcg_out_nop(s);
988         s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
989         break;
990     case INDEX_op_call:
991         tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, args[0], 0);
992         tcg_out_nop(s);
993         break;
994     case INDEX_op_jmp:
995         tcg_out_opc_reg(s, OPC_JR, 0, args[0], 0);
996         tcg_out_nop(s);
997         break;
998     case INDEX_op_br:
999         tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, args[0]);
1000         break;
1001 
1002     case INDEX_op_mov_i32:
1003         tcg_out_mov(s, args[0], args[1]);
1004         break;
1005     case INDEX_op_movi_i32:
1006         tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1007         break;
1008 
1009     case INDEX_op_ld8u_i32:
1010 	tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]);
1011         break;
1012     case INDEX_op_ld8s_i32:
1013         tcg_out_ldst(s, OPC_LB, args[0], args[1], args[2]);
1014         break;
1015     case INDEX_op_ld16u_i32:
1016         tcg_out_ldst(s, OPC_LHU, args[0], args[1], args[2]);
1017         break;
1018     case INDEX_op_ld16s_i32:
1019         tcg_out_ldst(s, OPC_LH, args[0], args[1], args[2]);
1020         break;
1021     case INDEX_op_ld_i32:
1022         tcg_out_ldst(s, OPC_LW, args[0], args[1], args[2]);
1023         break;
1024     case INDEX_op_st8_i32:
1025         tcg_out_ldst(s, OPC_SB, args[0], args[1], args[2]);
1026         break;
1027     case INDEX_op_st16_i32:
1028         tcg_out_ldst(s, OPC_SH, args[0], args[1], args[2]);
1029         break;
1030     case INDEX_op_st_i32:
1031         tcg_out_ldst(s, OPC_SW, args[0], args[1], args[2]);
1032         break;
1033 
1034     case INDEX_op_add_i32:
1035         if (const_args[2]) {
1036             tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], args[2]);
1037         } else {
1038             tcg_out_opc_reg(s, OPC_ADDU, args[0], args[1], args[2]);
1039         }
1040         break;
1041     case INDEX_op_add2_i32:
1042         if (const_args[4]) {
1043             tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], args[4]);
1044         } else {
1045             tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, args[2], args[4]);
1046         }
1047         tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, TCG_REG_AT, args[2]);
1048         if (const_args[5]) {
1049             tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], args[5]);
1050         } else {
1051              tcg_out_opc_reg(s, OPC_ADDU, args[1], args[3], args[5]);
1052         }
1053         tcg_out_opc_reg(s, OPC_ADDU, args[1], args[1], TCG_REG_T0);
1054         tcg_out_mov(s, args[0], TCG_REG_AT);
1055         break;
1056     case INDEX_op_sub_i32:
1057         if (const_args[2]) {
1058             tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], -args[2]);
1059         } else {
1060             tcg_out_opc_reg(s, OPC_SUBU, args[0], args[1], args[2]);
1061         }
1062         break;
1063     case INDEX_op_sub2_i32:
1064         if (const_args[4]) {
1065             tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], -args[4]);
1066         } else {
1067             tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, args[2], args[4]);
1068         }
1069         tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, args[2], TCG_REG_AT);
1070         if (const_args[5]) {
1071             tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], -args[5]);
1072         } else {
1073              tcg_out_opc_reg(s, OPC_SUBU, args[1], args[3], args[5]);
1074         }
1075         tcg_out_opc_reg(s, OPC_SUBU, args[1], args[1], TCG_REG_T0);
1076         tcg_out_mov(s, args[0], TCG_REG_AT);
1077         break;
1078     case INDEX_op_mul_i32:
1079         tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
1080         tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1081         break;
1082     case INDEX_op_mulu2_i32:
1083         tcg_out_opc_reg(s, OPC_MULTU, 0, args[2], args[3]);
1084         tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1085         tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
1086         break;
1087     case INDEX_op_div_i32:
1088         tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1089         tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1090         break;
1091     case INDEX_op_divu_i32:
1092         tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1093         tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1094         break;
1095     case INDEX_op_rem_i32:
1096         tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1097         tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1098         break;
1099     case INDEX_op_remu_i32:
1100         tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1101         tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1102         break;
1103 
1104     case INDEX_op_and_i32:
1105         if (const_args[2]) {
1106             tcg_out_opc_imm(s, OPC_ANDI, args[0], args[1], args[2]);
1107         } else {
1108             tcg_out_opc_reg(s, OPC_AND, args[0], args[1], args[2]);
1109         }
1110         break;
1111     case INDEX_op_or_i32:
1112         if (const_args[2]) {
1113             tcg_out_opc_imm(s, OPC_ORI, args[0], args[1], args[2]);
1114         } else {
1115             tcg_out_opc_reg(s, OPC_OR, args[0], args[1], args[2]);
1116         }
1117         break;
1118     case INDEX_op_not_i32:
1119         tcg_out_opc_reg(s, OPC_NOR, args[0], args[1], args[1]);
1120         break;
1121     case INDEX_op_xor_i32:
1122         if (const_args[2]) {
1123             tcg_out_opc_imm(s, OPC_XORI, args[0], args[1], args[2]);
1124         } else {
1125             tcg_out_opc_reg(s, OPC_XOR, args[0], args[1], args[2]);
1126         }
1127         break;
1128 
1129     case INDEX_op_sar_i32:
1130         if (const_args[2]) {
1131             tcg_out_opc_sa(s, OPC_SRA, args[0], args[1], args[2]);
1132         } else {
1133             tcg_out_opc_reg(s, OPC_SRAV, args[0], args[2], args[1]);
1134         }
1135         break;
1136     case INDEX_op_shl_i32:
1137         if (const_args[2]) {
1138             tcg_out_opc_sa(s, OPC_SLL, args[0], args[1], args[2]);
1139         } else {
1140             tcg_out_opc_reg(s, OPC_SLLV, args[0], args[2], args[1]);
1141         }
1142         break;
1143     case INDEX_op_shr_i32:
1144         if (const_args[2]) {
1145             tcg_out_opc_sa(s, OPC_SRL, args[0], args[1], args[2]);
1146         } else {
1147             tcg_out_opc_reg(s, OPC_SRLV, args[0], args[2], args[1]);
1148         }
1149         break;
1150 
1151     case INDEX_op_brcond_i32:
1152         tcg_out_brcond(s, args[2], args[0], args[1], args[3]);
1153         break;
1154     case INDEX_op_brcond2_i32:
1155         tcg_out_brcond2(s, args[4], args[0], args[1], args[2], args[3], args[5]);
1156         break;
1157 
1158     case INDEX_op_qemu_ld8u:
1159         tcg_out_qemu_ld(s, args, 0);
1160         break;
1161     case INDEX_op_qemu_ld8s:
1162         tcg_out_qemu_ld(s, args, 0 | 4);
1163         break;
1164     case INDEX_op_qemu_ld16u:
1165         tcg_out_qemu_ld(s, args, 1);
1166         break;
1167     case INDEX_op_qemu_ld16s:
1168         tcg_out_qemu_ld(s, args, 1 | 4);
1169         break;
1170     case INDEX_op_qemu_ld32u:
1171         tcg_out_qemu_ld(s, args, 2);
1172         break;
1173     case INDEX_op_qemu_ld64:
1174         tcg_out_qemu_ld(s, args, 3);
1175         break;
1176     case INDEX_op_qemu_st8:
1177         tcg_out_qemu_st(s, args, 0);
1178         break;
1179     case INDEX_op_qemu_st16:
1180         tcg_out_qemu_st(s, args, 1);
1181         break;
1182     case INDEX_op_qemu_st32:
1183         tcg_out_qemu_st(s, args, 2);
1184         break;
1185     case INDEX_op_qemu_st64:
1186         tcg_out_qemu_st(s, args, 3);
1187         break;
1188 
1189     default:
1190         tcg_abort();
1191     }
1192 }
1193 
1194 static const TCGTargetOpDef mips_op_defs[] = {
1195     { INDEX_op_exit_tb, { } },
1196     { INDEX_op_goto_tb, { } },
1197     { INDEX_op_call, { "C" } },
1198     { INDEX_op_jmp, { "r" } },
1199     { INDEX_op_br, { } },
1200 
1201     { INDEX_op_mov_i32, { "r", "r" } },
1202     { INDEX_op_movi_i32, { "r" } },
1203     { INDEX_op_ld8u_i32, { "r", "r" } },
1204     { INDEX_op_ld8s_i32, { "r", "r" } },
1205     { INDEX_op_ld16u_i32, { "r", "r" } },
1206     { INDEX_op_ld16s_i32, { "r", "r" } },
1207     { INDEX_op_ld_i32, { "r", "r" } },
1208     { INDEX_op_st8_i32, { "rZ", "r" } },
1209     { INDEX_op_st16_i32, { "rZ", "r" } },
1210     { INDEX_op_st_i32, { "rZ", "r" } },
1211 
1212     { INDEX_op_add_i32, { "r", "rZ", "rJZ" } },
1213     { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
1214     { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
1215     { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
1216     { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
1217     { INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
1218     { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
1219     { INDEX_op_sub_i32, { "r", "rZ", "rJZ" } },
1220 
1221     { INDEX_op_and_i32, { "r", "rZ", "rIZ" } },
1222     { INDEX_op_not_i32, { "r", "rZ" } },
1223     { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
1224     { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
1225 
1226     { INDEX_op_shl_i32, { "r", "rZ", "riZ" } },
1227     { INDEX_op_shr_i32, { "r", "rZ", "riZ" } },
1228     { INDEX_op_sar_i32, { "r", "rZ", "riZ" } },
1229 
1230     { INDEX_op_brcond_i32, { "rZ", "rZ" } },
1231 
1232     { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1233     { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1234     { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
1235 
1236 #if TARGET_LONG_BITS == 32
1237     { INDEX_op_qemu_ld8u, { "L", "lZ" } },
1238     { INDEX_op_qemu_ld8s, { "L", "lZ" } },
1239     { INDEX_op_qemu_ld16u, { "L", "lZ" } },
1240     { INDEX_op_qemu_ld16s, { "L", "lZ" } },
1241     { INDEX_op_qemu_ld32u, { "L", "lZ" } },
1242     { INDEX_op_qemu_ld64, { "L", "L", "lZ" } },
1243 
1244     { INDEX_op_qemu_st8, { "SZ", "SZ" } },
1245     { INDEX_op_qemu_st16, { "SZ", "SZ" } },
1246     { INDEX_op_qemu_st32, { "SZ", "SZ" } },
1247     { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ" } },
1248 #else
1249     { INDEX_op_qemu_ld8u, { "L", "lZ", "lZ" } },
1250     { INDEX_op_qemu_ld8s, { "L", "lZ", "lZ" } },
1251     { INDEX_op_qemu_ld16u, { "L", "lZ", "lZ" } },
1252     { INDEX_op_qemu_ld16s, { "L", "lZ", "lZ" } },
1253     { INDEX_op_qemu_ld32u, { "L", "lZ", "lZ" } },
1254     { INDEX_op_qemu_ld64, { "L", "L", "lZ", "lZ" } },
1255 
1256     { INDEX_op_qemu_st8, { "SZ", "SZ", "SZ" } },
1257     { INDEX_op_qemu_st16, { "SZ", "SZ", "SZ" } },
1258     { INDEX_op_qemu_st32, { "SZ", "SZ", "SZ" } },
1259     { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ", "SZ" } },
1260 #endif
1261     { -1 },
1262 };
1263 
1264 static int tcg_target_callee_save_regs[] = {
1265     TCG_REG_S0,
1266     TCG_REG_S1,
1267     TCG_REG_S2,
1268     TCG_REG_S3,
1269     TCG_REG_S4,
1270     TCG_REG_S5,
1271     TCG_REG_S6,
1272     TCG_REG_S7,
1273     TCG_REG_GP,
1274     /* TCG_REG_FP, */ /* currently used for the global env, so np
1275                          need to save */
1276     TCG_REG_RA,       /* should be last for ABI compliance */
1277 };
1278 
1279 /* Generate global QEMU prologue and epilogue code */
tcg_target_qemu_prologue(TCGContext * s)1280 void tcg_target_qemu_prologue(TCGContext *s)
1281 {
1282     int i, frame_size;
1283 
1284     /* reserve some stack space */
1285     frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1286                  + TCG_STATIC_CALL_ARGS_SIZE;
1287     frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1288                  ~(TCG_TARGET_STACK_ALIGN - 1);
1289 
1290     /* TB prologue */
1291     tcg_out_addi(s, TCG_REG_SP, -frame_size);
1292     for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1293         tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1294                    TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1295     }
1296 
1297     /* Call generated code */
1298     tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_A0, 0);
1299     tcg_out_nop(s);
1300     tb_ret_addr = s->code_ptr;
1301 
1302     /* TB epilogue */
1303     for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1304         tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1305                    TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1306     }
1307 
1308     tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
1309     tcg_out_addi(s, TCG_REG_SP, frame_size);
1310 }
1311 
tcg_target_init(TCGContext * s)1312 void tcg_target_init(TCGContext *s)
1313 {
1314     tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
1315     tcg_regset_set(tcg_target_call_clobber_regs,
1316                    (1 << TCG_REG_V0) |
1317                    (1 << TCG_REG_V1) |
1318                    (1 << TCG_REG_A0) |
1319                    (1 << TCG_REG_A1) |
1320                    (1 << TCG_REG_A2) |
1321                    (1 << TCG_REG_A3) |
1322                    (1 << TCG_REG_T1) |
1323                    (1 << TCG_REG_T2) |
1324                    (1 << TCG_REG_T3) |
1325                    (1 << TCG_REG_T4) |
1326                    (1 << TCG_REG_T5) |
1327                    (1 << TCG_REG_T6) |
1328                    (1 << TCG_REG_T7) |
1329                    (1 << TCG_REG_T8) |
1330                    (1 << TCG_REG_T9));
1331 
1332     tcg_regset_clear(s->reserved_regs);
1333     tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
1334     tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0);   /* kernel use only */
1335     tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1);   /* kernel use only */
1336     tcg_regset_set_reg(s->reserved_regs, TCG_REG_AT);   /* internal use */
1337     tcg_regset_set_reg(s->reserved_regs, TCG_REG_T0);   /* internal use */
1338     tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA);   /* return address */
1339     tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);   /* stack pointer */
1340 
1341     tcg_add_target_add_op_defs(mips_op_defs);
1342 }
1343