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