Statistics
| Branch: | Revision:

root / tcg / mips / tcg-target.c @ 434254aa

History | View | Annotate | Download (43.7 kB)

1 afa05235 Aurelien Jarno
/*
2 afa05235 Aurelien Jarno
 * Tiny Code Generator for QEMU
3 afa05235 Aurelien Jarno
 *
4 afa05235 Aurelien Jarno
 * Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org>
5 afa05235 Aurelien Jarno
 * Copyright (c) 2009 Aurelien Jarno <aurelien@aurel32.net>
6 afa05235 Aurelien Jarno
 * Based on i386/tcg-target.c - Copyright (c) 2008 Fabrice Bellard
7 afa05235 Aurelien Jarno
 *
8 afa05235 Aurelien Jarno
 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 afa05235 Aurelien Jarno
 * of this software and associated documentation files (the "Software"), to deal
10 afa05235 Aurelien Jarno
 * in the Software without restriction, including without limitation the rights
11 afa05235 Aurelien Jarno
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 afa05235 Aurelien Jarno
 * copies of the Software, and to permit persons to whom the Software is
13 afa05235 Aurelien Jarno
 * furnished to do so, subject to the following conditions:
14 afa05235 Aurelien Jarno
 *
15 afa05235 Aurelien Jarno
 * The above copyright notice and this permission notice shall be included in
16 afa05235 Aurelien Jarno
 * all copies or substantial portions of the Software.
17 afa05235 Aurelien Jarno
 *
18 afa05235 Aurelien Jarno
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 afa05235 Aurelien Jarno
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 afa05235 Aurelien Jarno
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 afa05235 Aurelien Jarno
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 afa05235 Aurelien Jarno
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 afa05235 Aurelien Jarno
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 afa05235 Aurelien Jarno
 * THE SOFTWARE.
25 afa05235 Aurelien Jarno
 */
26 afa05235 Aurelien Jarno
27 afa05235 Aurelien Jarno
#if defined(TCG_TARGET_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
28 afa05235 Aurelien Jarno
# define TCG_NEED_BSWAP 0
29 afa05235 Aurelien Jarno
#else
30 afa05235 Aurelien Jarno
# define TCG_NEED_BSWAP 1
31 afa05235 Aurelien Jarno
#endif
32 afa05235 Aurelien Jarno
33 afa05235 Aurelien Jarno
#ifndef NDEBUG
34 afa05235 Aurelien Jarno
static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
35 afa05235 Aurelien Jarno
    "zero",
36 afa05235 Aurelien Jarno
    "at",
37 afa05235 Aurelien Jarno
    "v0",
38 afa05235 Aurelien Jarno
    "v1",
39 afa05235 Aurelien Jarno
    "a0",
40 afa05235 Aurelien Jarno
    "a1",
41 afa05235 Aurelien Jarno
    "a2",
42 afa05235 Aurelien Jarno
    "a3",
43 afa05235 Aurelien Jarno
    "t0",
44 afa05235 Aurelien Jarno
    "t1",
45 afa05235 Aurelien Jarno
    "t2",
46 afa05235 Aurelien Jarno
    "t3",
47 afa05235 Aurelien Jarno
    "t4",
48 afa05235 Aurelien Jarno
    "t5",
49 afa05235 Aurelien Jarno
    "t6",
50 afa05235 Aurelien Jarno
    "t7",
51 afa05235 Aurelien Jarno
    "s0",
52 afa05235 Aurelien Jarno
    "s1",
53 afa05235 Aurelien Jarno
    "s2",
54 afa05235 Aurelien Jarno
    "s3",
55 afa05235 Aurelien Jarno
    "s4",
56 afa05235 Aurelien Jarno
    "s5",
57 afa05235 Aurelien Jarno
    "s6",
58 afa05235 Aurelien Jarno
    "s7",
59 afa05235 Aurelien Jarno
    "t8",
60 afa05235 Aurelien Jarno
    "t9",
61 afa05235 Aurelien Jarno
    "k0",
62 afa05235 Aurelien Jarno
    "k1",
63 afa05235 Aurelien Jarno
    "gp",
64 afa05235 Aurelien Jarno
    "sp",
65 afa05235 Aurelien Jarno
    "fp",
66 afa05235 Aurelien Jarno
    "ra",
67 afa05235 Aurelien Jarno
};
68 afa05235 Aurelien Jarno
#endif
69 afa05235 Aurelien Jarno
70 afa05235 Aurelien Jarno
/* check if we really need so many registers :P */
71 afa05235 Aurelien Jarno
static const int tcg_target_reg_alloc_order[] = {
72 afa05235 Aurelien Jarno
    TCG_REG_S0,
73 afa05235 Aurelien Jarno
    TCG_REG_S1,
74 afa05235 Aurelien Jarno
    TCG_REG_S2,
75 afa05235 Aurelien Jarno
    TCG_REG_S3,
76 afa05235 Aurelien Jarno
    TCG_REG_S4,
77 afa05235 Aurelien Jarno
    TCG_REG_S5,
78 afa05235 Aurelien Jarno
    TCG_REG_S6,
79 afa05235 Aurelien Jarno
    TCG_REG_S7,
80 afa05235 Aurelien Jarno
    TCG_REG_T1,
81 afa05235 Aurelien Jarno
    TCG_REG_T2,
82 afa05235 Aurelien Jarno
    TCG_REG_T3,
83 afa05235 Aurelien Jarno
    TCG_REG_T4,
84 afa05235 Aurelien Jarno
    TCG_REG_T5,
85 afa05235 Aurelien Jarno
    TCG_REG_T6,
86 afa05235 Aurelien Jarno
    TCG_REG_T7,
87 afa05235 Aurelien Jarno
    TCG_REG_T8,
88 afa05235 Aurelien Jarno
    TCG_REG_T9,
89 afa05235 Aurelien Jarno
    TCG_REG_A0,
90 afa05235 Aurelien Jarno
    TCG_REG_A1,
91 afa05235 Aurelien Jarno
    TCG_REG_A2,
92 afa05235 Aurelien Jarno
    TCG_REG_A3,
93 afa05235 Aurelien Jarno
    TCG_REG_V0,
94 afa05235 Aurelien Jarno
    TCG_REG_V1
95 afa05235 Aurelien Jarno
};
96 afa05235 Aurelien Jarno
97 afa05235 Aurelien Jarno
static const int tcg_target_call_iarg_regs[4] = {
98 afa05235 Aurelien Jarno
    TCG_REG_A0,
99 afa05235 Aurelien Jarno
    TCG_REG_A1,
100 afa05235 Aurelien Jarno
    TCG_REG_A2,
101 afa05235 Aurelien Jarno
    TCG_REG_A3
102 afa05235 Aurelien Jarno
};
103 afa05235 Aurelien Jarno
104 afa05235 Aurelien Jarno
static const int tcg_target_call_oarg_regs[2] = {
105 afa05235 Aurelien Jarno
    TCG_REG_V0,
106 afa05235 Aurelien Jarno
    TCG_REG_V1
107 afa05235 Aurelien Jarno
};
108 afa05235 Aurelien Jarno
109 afa05235 Aurelien Jarno
static uint8_t *tb_ret_addr;
110 afa05235 Aurelien Jarno
111 afa05235 Aurelien Jarno
static inline uint32_t reloc_lo16_val (void *pc, tcg_target_long target)
112 afa05235 Aurelien Jarno
{
113 afa05235 Aurelien Jarno
    return target & 0xffff;
114 afa05235 Aurelien Jarno
}
115 afa05235 Aurelien Jarno
116 afa05235 Aurelien Jarno
static inline void reloc_lo16 (void *pc, tcg_target_long target)
117 afa05235 Aurelien Jarno
{
118 afa05235 Aurelien Jarno
    *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
119 afa05235 Aurelien Jarno
                       | reloc_lo16_val(pc, target);
120 afa05235 Aurelien Jarno
}
121 afa05235 Aurelien Jarno
122 afa05235 Aurelien Jarno
static inline uint32_t reloc_hi16_val (void *pc, tcg_target_long target)
123 afa05235 Aurelien Jarno
{
124 afa05235 Aurelien Jarno
    return (target >> 16) & 0xffff;
125 afa05235 Aurelien Jarno
}
126 afa05235 Aurelien Jarno
127 afa05235 Aurelien Jarno
static inline void reloc_hi16 (void *pc, tcg_target_long target)
128 afa05235 Aurelien Jarno
{
129 afa05235 Aurelien Jarno
    *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
130 afa05235 Aurelien Jarno
                       | reloc_hi16_val(pc, target);
131 afa05235 Aurelien Jarno
}
132 afa05235 Aurelien Jarno
133 afa05235 Aurelien Jarno
static inline uint32_t reloc_pc16_val (void *pc, tcg_target_long target)
134 afa05235 Aurelien Jarno
{
135 afa05235 Aurelien Jarno
    int32_t disp;
136 afa05235 Aurelien Jarno
137 afa05235 Aurelien Jarno
    disp = target - (tcg_target_long) pc - 4;
138 afa05235 Aurelien Jarno
    if (disp != (disp << 14) >> 14) {
139 afa05235 Aurelien Jarno
        tcg_abort ();
140 afa05235 Aurelien Jarno
    }
141 afa05235 Aurelien Jarno
142 afa05235 Aurelien Jarno
    return (disp >> 2) & 0xffff;
143 afa05235 Aurelien Jarno
}
144 afa05235 Aurelien Jarno
145 afa05235 Aurelien Jarno
static inline void reloc_pc16 (void *pc, tcg_target_long target)
146 afa05235 Aurelien Jarno
{
147 afa05235 Aurelien Jarno
    *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
148 afa05235 Aurelien Jarno
                       | reloc_pc16_val(pc, target);
149 afa05235 Aurelien Jarno
}
150 afa05235 Aurelien Jarno
151 afa05235 Aurelien Jarno
static inline uint32_t reloc_26_val (void *pc, tcg_target_long target)
152 afa05235 Aurelien Jarno
{
153 afa05235 Aurelien Jarno
    if ((((tcg_target_long)pc + 4) & 0xf0000000) != (target & 0xf0000000)) {
154 afa05235 Aurelien Jarno
        tcg_abort ();
155 afa05235 Aurelien Jarno
    }
156 afa05235 Aurelien Jarno
157 afa05235 Aurelien Jarno
    return (target >> 2) & 0x3ffffff;
158 afa05235 Aurelien Jarno
}
159 afa05235 Aurelien Jarno
160 afa05235 Aurelien Jarno
static inline void reloc_pc26 (void *pc, tcg_target_long target)
161 afa05235 Aurelien Jarno
{
162 afa05235 Aurelien Jarno
    *(uint32_t *) pc = (*(uint32_t *) pc & ~0x3ffffff)
163 afa05235 Aurelien Jarno
                       | reloc_26_val(pc, target);
164 afa05235 Aurelien Jarno
}
165 afa05235 Aurelien Jarno
166 afa05235 Aurelien Jarno
static void patch_reloc(uint8_t *code_ptr, int type,
167 afa05235 Aurelien Jarno
                        tcg_target_long value, tcg_target_long addend)
168 afa05235 Aurelien Jarno
{
169 afa05235 Aurelien Jarno
    value += addend;
170 afa05235 Aurelien Jarno
    switch(type) {
171 afa05235 Aurelien Jarno
    case R_MIPS_LO16:
172 afa05235 Aurelien Jarno
        reloc_lo16(code_ptr, value);
173 afa05235 Aurelien Jarno
        break;
174 afa05235 Aurelien Jarno
    case R_MIPS_HI16:
175 afa05235 Aurelien Jarno
        reloc_hi16(code_ptr, value);
176 afa05235 Aurelien Jarno
        break;
177 afa05235 Aurelien Jarno
    case R_MIPS_PC16:
178 afa05235 Aurelien Jarno
        reloc_pc16(code_ptr, value);
179 afa05235 Aurelien Jarno
        break;
180 afa05235 Aurelien Jarno
    case R_MIPS_26:
181 afa05235 Aurelien Jarno
        reloc_pc26(code_ptr, value);
182 afa05235 Aurelien Jarno
        break;
183 afa05235 Aurelien Jarno
    default:
184 afa05235 Aurelien Jarno
        tcg_abort();
185 afa05235 Aurelien Jarno
    }
186 afa05235 Aurelien Jarno
}
187 afa05235 Aurelien Jarno
188 afa05235 Aurelien Jarno
/* maximum number of register used for input function arguments */
189 afa05235 Aurelien Jarno
static inline int tcg_target_get_call_iarg_regs_count(int flags)
190 afa05235 Aurelien Jarno
{
191 afa05235 Aurelien Jarno
    return 4;
192 afa05235 Aurelien Jarno
}
193 afa05235 Aurelien Jarno
194 afa05235 Aurelien Jarno
/* parse target specific constraints */
195 afa05235 Aurelien Jarno
static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
196 afa05235 Aurelien Jarno
{
197 afa05235 Aurelien Jarno
    const char *ct_str;
198 afa05235 Aurelien Jarno
199 afa05235 Aurelien Jarno
    ct_str = *pct_str;
200 afa05235 Aurelien Jarno
    switch(ct_str[0]) {
201 afa05235 Aurelien Jarno
    case 'r':
202 afa05235 Aurelien Jarno
        ct->ct |= TCG_CT_REG;
203 afa05235 Aurelien Jarno
        tcg_regset_set(ct->u.regs, 0xffffffff);
204 afa05235 Aurelien Jarno
        break;
205 afa05235 Aurelien Jarno
    case 'C':
206 afa05235 Aurelien Jarno
        ct->ct |= TCG_CT_REG;
207 afa05235 Aurelien Jarno
        tcg_regset_clear(ct->u.regs);
208 afa05235 Aurelien Jarno
        tcg_regset_set_reg(ct->u.regs, TCG_REG_T9);
209 afa05235 Aurelien Jarno
        break;
210 afa05235 Aurelien Jarno
    case 'L': /* qemu_ld output arg constraint */
211 afa05235 Aurelien Jarno
        ct->ct |= TCG_CT_REG;
212 afa05235 Aurelien Jarno
        tcg_regset_set(ct->u.regs, 0xffffffff);
213 afa05235 Aurelien Jarno
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_V0);
214 afa05235 Aurelien Jarno
        break;
215 afa05235 Aurelien Jarno
    case 'l': /* qemu_ld input arg constraint */
216 afa05235 Aurelien Jarno
        ct->ct |= TCG_CT_REG;
217 afa05235 Aurelien Jarno
        tcg_regset_set(ct->u.regs, 0xffffffff);
218 afa05235 Aurelien Jarno
#if defined(CONFIG_SOFTMMU)
219 afa05235 Aurelien Jarno
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
220 afa05235 Aurelien Jarno
#endif
221 afa05235 Aurelien Jarno
        break;
222 afa05235 Aurelien Jarno
    case 'S': /* qemu_st constraint */
223 afa05235 Aurelien Jarno
        ct->ct |= TCG_CT_REG;
224 afa05235 Aurelien Jarno
        tcg_regset_set(ct->u.regs, 0xffffffff);
225 afa05235 Aurelien Jarno
#if defined(CONFIG_SOFTMMU)
226 afa05235 Aurelien Jarno
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
227 afa05235 Aurelien Jarno
# if TARGET_LONG_BITS == 64
228 afa05235 Aurelien Jarno
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1);
229 afa05235 Aurelien Jarno
# endif
230 afa05235 Aurelien Jarno
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
231 afa05235 Aurelien Jarno
#endif
232 afa05235 Aurelien Jarno
        break;
233 afa05235 Aurelien Jarno
    case 'I':
234 afa05235 Aurelien Jarno
        ct->ct |= TCG_CT_CONST_U16;
235 afa05235 Aurelien Jarno
        break;
236 afa05235 Aurelien Jarno
    case 'J':
237 afa05235 Aurelien Jarno
        ct->ct |= TCG_CT_CONST_S16;
238 afa05235 Aurelien Jarno
        break;
239 afa05235 Aurelien Jarno
    case 'Z':
240 afa05235 Aurelien Jarno
        /* We are cheating a bit here, using the fact that the register
241 afa05235 Aurelien Jarno
           ZERO is also the register number 0. Hence there is no need
242 afa05235 Aurelien Jarno
           to check for const_args in each instruction. */
243 afa05235 Aurelien Jarno
        ct->ct |= TCG_CT_CONST_ZERO;
244 afa05235 Aurelien Jarno
        break;
245 afa05235 Aurelien Jarno
    default:
246 afa05235 Aurelien Jarno
        return -1;
247 afa05235 Aurelien Jarno
    }
248 afa05235 Aurelien Jarno
    ct_str++;
249 afa05235 Aurelien Jarno
    *pct_str = ct_str;
250 afa05235 Aurelien Jarno
    return 0;
251 afa05235 Aurelien Jarno
}
252 afa05235 Aurelien Jarno
253 afa05235 Aurelien Jarno
/* test if a constant matches the constraint */
254 afa05235 Aurelien Jarno
static inline int tcg_target_const_match(tcg_target_long val,
255 afa05235 Aurelien Jarno
                                         const TCGArgConstraint *arg_ct)
256 afa05235 Aurelien Jarno
{
257 afa05235 Aurelien Jarno
    int ct;
258 afa05235 Aurelien Jarno
    ct = arg_ct->ct;
259 afa05235 Aurelien Jarno
    if (ct & TCG_CT_CONST)
260 afa05235 Aurelien Jarno
        return 1;
261 afa05235 Aurelien Jarno
    else if ((ct & TCG_CT_CONST_ZERO) && val == 0)
262 afa05235 Aurelien Jarno
        return 1;
263 afa05235 Aurelien Jarno
    else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val)
264 afa05235 Aurelien Jarno
        return 1;
265 afa05235 Aurelien Jarno
    else if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val)
266 afa05235 Aurelien Jarno
        return 1;
267 afa05235 Aurelien Jarno
    else
268 afa05235 Aurelien Jarno
        return 0;
269 afa05235 Aurelien Jarno
}
270 afa05235 Aurelien Jarno
271 afa05235 Aurelien Jarno
/* instruction opcodes */
272 afa05235 Aurelien Jarno
enum {
273 afa05235 Aurelien Jarno
    OPC_SPECIAL  = 0x00 << 26,
274 afa05235 Aurelien Jarno
    OPC_BEQ      = 0x04 << 26,
275 afa05235 Aurelien Jarno
    OPC_BNE      = 0x05 << 26,
276 afa05235 Aurelien Jarno
    OPC_ADDIU    = 0x09 << 26,
277 4cb26382 Aurelien Jarno
    OPC_SLTI     = 0x0A << 26,
278 4cb26382 Aurelien Jarno
    OPC_SLTIU    = 0x0B << 26,
279 afa05235 Aurelien Jarno
    OPC_ANDI     = 0x0C << 26,
280 afa05235 Aurelien Jarno
    OPC_ORI      = 0x0D << 26,
281 afa05235 Aurelien Jarno
    OPC_XORI     = 0x0E << 26,
282 afa05235 Aurelien Jarno
    OPC_LUI      = 0x0F << 26,
283 afa05235 Aurelien Jarno
    OPC_LB       = 0x20 << 26,
284 afa05235 Aurelien Jarno
    OPC_LH       = 0x21 << 26,
285 afa05235 Aurelien Jarno
    OPC_LW       = 0x23 << 26,
286 afa05235 Aurelien Jarno
    OPC_LBU      = 0x24 << 26,
287 afa05235 Aurelien Jarno
    OPC_LHU      = 0x25 << 26,
288 afa05235 Aurelien Jarno
    OPC_LWU      = 0x27 << 26,
289 afa05235 Aurelien Jarno
    OPC_SB       = 0x28 << 26,
290 afa05235 Aurelien Jarno
    OPC_SH       = 0x29 << 26,
291 afa05235 Aurelien Jarno
    OPC_SW       = 0x2B << 26,
292 afa05235 Aurelien Jarno
    OPC_SLL      = OPC_SPECIAL | 0x00,
293 afa05235 Aurelien Jarno
    OPC_SRL      = OPC_SPECIAL | 0x02,
294 afa05235 Aurelien Jarno
    OPC_SRA      = OPC_SPECIAL | 0x03,
295 afa05235 Aurelien Jarno
    OPC_SLLV     = OPC_SPECIAL | 0x04,
296 afa05235 Aurelien Jarno
    OPC_SRLV     = OPC_SPECIAL | 0x06,
297 afa05235 Aurelien Jarno
    OPC_SRAV     = OPC_SPECIAL | 0x07,
298 afa05235 Aurelien Jarno
    OPC_JR       = OPC_SPECIAL | 0x08,
299 afa05235 Aurelien Jarno
    OPC_JALR     = OPC_SPECIAL | 0x09,
300 afa05235 Aurelien Jarno
    OPC_MFHI     = OPC_SPECIAL | 0x10,
301 afa05235 Aurelien Jarno
    OPC_MFLO     = OPC_SPECIAL | 0x12,
302 afa05235 Aurelien Jarno
    OPC_MULT     = OPC_SPECIAL | 0x18,
303 afa05235 Aurelien Jarno
    OPC_MULTU    = OPC_SPECIAL | 0x19,
304 afa05235 Aurelien Jarno
    OPC_DIV      = OPC_SPECIAL | 0x1A,
305 afa05235 Aurelien Jarno
    OPC_DIVU     = OPC_SPECIAL | 0x1B,
306 afa05235 Aurelien Jarno
    OPC_ADDU     = OPC_SPECIAL | 0x21,
307 afa05235 Aurelien Jarno
    OPC_SUBU     = OPC_SPECIAL | 0x23,
308 afa05235 Aurelien Jarno
    OPC_AND      = OPC_SPECIAL | 0x24,
309 afa05235 Aurelien Jarno
    OPC_OR       = OPC_SPECIAL | 0x25,
310 afa05235 Aurelien Jarno
    OPC_XOR      = OPC_SPECIAL | 0x26,
311 afa05235 Aurelien Jarno
    OPC_NOR      = OPC_SPECIAL | 0x27,
312 afa05235 Aurelien Jarno
    OPC_SLT      = OPC_SPECIAL | 0x2A,
313 afa05235 Aurelien Jarno
    OPC_SLTU     = OPC_SPECIAL | 0x2B,
314 afa05235 Aurelien Jarno
};
315 afa05235 Aurelien Jarno
316 afa05235 Aurelien Jarno
/*
317 afa05235 Aurelien Jarno
 * Type reg
318 afa05235 Aurelien Jarno
 */
319 afa05235 Aurelien Jarno
static inline void tcg_out_opc_reg(TCGContext *s, int opc, int rd, int rs, int rt)
320 afa05235 Aurelien Jarno
{
321 afa05235 Aurelien Jarno
    int32_t inst;
322 afa05235 Aurelien Jarno
323 afa05235 Aurelien Jarno
    inst = opc;
324 afa05235 Aurelien Jarno
    inst |= (rs & 0x1F) << 21;
325 afa05235 Aurelien Jarno
    inst |= (rt & 0x1F) << 16;
326 afa05235 Aurelien Jarno
    inst |= (rd & 0x1F) << 11;
327 afa05235 Aurelien Jarno
    tcg_out32(s, inst);
328 afa05235 Aurelien Jarno
}
329 afa05235 Aurelien Jarno
330 afa05235 Aurelien Jarno
/*
331 afa05235 Aurelien Jarno
 * Type immediate
332 afa05235 Aurelien Jarno
 */
333 afa05235 Aurelien Jarno
static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int imm)
334 afa05235 Aurelien Jarno
{
335 afa05235 Aurelien Jarno
    int32_t inst;
336 afa05235 Aurelien Jarno
337 afa05235 Aurelien Jarno
    inst = opc;
338 afa05235 Aurelien Jarno
    inst |= (rs & 0x1F) << 21;
339 afa05235 Aurelien Jarno
    inst |= (rt & 0x1F) << 16;
340 afa05235 Aurelien Jarno
    inst |= (imm & 0xffff);
341 afa05235 Aurelien Jarno
    tcg_out32(s, inst);
342 afa05235 Aurelien Jarno
}
343 afa05235 Aurelien Jarno
344 afa05235 Aurelien Jarno
/*
345 afa05235 Aurelien Jarno
 * Type sa
346 afa05235 Aurelien Jarno
 */
347 afa05235 Aurelien Jarno
static inline void tcg_out_opc_sa(TCGContext *s, int opc, int rd, int rt, int sa)
348 afa05235 Aurelien Jarno
{
349 afa05235 Aurelien Jarno
    int32_t inst;
350 afa05235 Aurelien Jarno
351 afa05235 Aurelien Jarno
    inst = opc;
352 afa05235 Aurelien Jarno
    inst |= (rt & 0x1F) << 16;
353 afa05235 Aurelien Jarno
    inst |= (rd & 0x1F) << 11;
354 afa05235 Aurelien Jarno
    inst |= (sa & 0x1F) <<  6;
355 afa05235 Aurelien Jarno
    tcg_out32(s, inst);
356 afa05235 Aurelien Jarno
357 afa05235 Aurelien Jarno
}
358 afa05235 Aurelien Jarno
359 afa05235 Aurelien Jarno
static inline void tcg_out_nop(TCGContext *s)
360 afa05235 Aurelien Jarno
{
361 afa05235 Aurelien Jarno
    tcg_out32(s, 0);
362 afa05235 Aurelien Jarno
}
363 afa05235 Aurelien Jarno
364 afa05235 Aurelien Jarno
static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
365 afa05235 Aurelien Jarno
{
366 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
367 afa05235 Aurelien Jarno
}
368 afa05235 Aurelien Jarno
369 afa05235 Aurelien Jarno
static inline void tcg_out_movi(TCGContext *s, TCGType type,
370 afa05235 Aurelien Jarno
                                int reg, int32_t arg)
371 afa05235 Aurelien Jarno
{
372 afa05235 Aurelien Jarno
    if (arg == (int16_t)arg) {
373 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
374 afa05235 Aurelien Jarno
    } else if (arg == (uint16_t)arg) {
375 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
376 afa05235 Aurelien Jarno
    } else {
377 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_LUI, reg, 0, arg >> 16);
378 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0xffff);
379 afa05235 Aurelien Jarno
    }
380 afa05235 Aurelien Jarno
}
381 afa05235 Aurelien Jarno
382 afa05235 Aurelien Jarno
static inline void tcg_out_bswap16(TCGContext *s, int ret, int arg)
383 afa05235 Aurelien Jarno
{
384 afa05235 Aurelien Jarno
    /* ret and arg can't be register at */
385 afa05235 Aurelien Jarno
    if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
386 afa05235 Aurelien Jarno
        tcg_abort();
387 afa05235 Aurelien Jarno
    }
388 afa05235 Aurelien Jarno
389 afa05235 Aurelien Jarno
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
390 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0x00ff);
391 afa05235 Aurelien Jarno
392 afa05235 Aurelien Jarno
    tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
393 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
394 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
395 afa05235 Aurelien Jarno
}
396 afa05235 Aurelien Jarno
397 afa05235 Aurelien Jarno
static inline void tcg_out_bswap16s(TCGContext *s, int ret, int arg)
398 afa05235 Aurelien Jarno
{
399 afa05235 Aurelien Jarno
    /* ret and arg can't be register at */
400 afa05235 Aurelien Jarno
    if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
401 afa05235 Aurelien Jarno
        tcg_abort();
402 afa05235 Aurelien Jarno
    }
403 afa05235 Aurelien Jarno
404 afa05235 Aurelien Jarno
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
405 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff);
406 afa05235 Aurelien Jarno
407 afa05235 Aurelien Jarno
    tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
408 afa05235 Aurelien Jarno
    tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
409 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
410 afa05235 Aurelien Jarno
}
411 afa05235 Aurelien Jarno
412 afa05235 Aurelien Jarno
static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg)
413 afa05235 Aurelien Jarno
{
414 afa05235 Aurelien Jarno
    /* ret and arg must be different and can't be register at */
415 afa05235 Aurelien Jarno
    if (ret == arg || ret == TCG_REG_AT || arg == TCG_REG_AT) {
416 afa05235 Aurelien Jarno
        tcg_abort();
417 afa05235 Aurelien Jarno
    }
418 afa05235 Aurelien Jarno
419 afa05235 Aurelien Jarno
    tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
420 afa05235 Aurelien Jarno
421 afa05235 Aurelien Jarno
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 24);
422 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
423 afa05235 Aurelien Jarno
424 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, arg, 0xff00);
425 afa05235 Aurelien Jarno
    tcg_out_opc_sa(s, OPC_SLL, TCG_REG_AT, TCG_REG_AT, 8);
426 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
427 afa05235 Aurelien Jarno
428 afa05235 Aurelien Jarno
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
429 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff00);
430 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
431 afa05235 Aurelien Jarno
}
432 afa05235 Aurelien Jarno
433 afa05235 Aurelien Jarno
static inline void tcg_out_ldst(TCGContext *s, int opc, int arg,
434 afa05235 Aurelien Jarno
                              int arg1, tcg_target_long arg2)
435 afa05235 Aurelien Jarno
{
436 afa05235 Aurelien Jarno
    if (arg2 == (int16_t) arg2) {
437 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, opc, arg, arg1, arg2);
438 afa05235 Aurelien Jarno
    } else {
439 afa05235 Aurelien Jarno
        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, arg2);
440 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, TCG_REG_AT, arg1);
441 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, opc, arg, TCG_REG_AT, 0);
442 afa05235 Aurelien Jarno
    }
443 afa05235 Aurelien Jarno
}
444 afa05235 Aurelien Jarno
445 afa05235 Aurelien Jarno
static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg,
446 afa05235 Aurelien Jarno
                              int arg1, tcg_target_long arg2)
447 afa05235 Aurelien Jarno
{
448 afa05235 Aurelien Jarno
    tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
449 afa05235 Aurelien Jarno
}
450 afa05235 Aurelien Jarno
451 afa05235 Aurelien Jarno
static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
452 afa05235 Aurelien Jarno
                              int arg1, tcg_target_long arg2)
453 afa05235 Aurelien Jarno
{
454 afa05235 Aurelien Jarno
    tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
455 afa05235 Aurelien Jarno
}
456 afa05235 Aurelien Jarno
457 afa05235 Aurelien Jarno
static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
458 afa05235 Aurelien Jarno
{
459 afa05235 Aurelien Jarno
    if (val == (int16_t)val) {
460 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
461 afa05235 Aurelien Jarno
    } else {
462 afa05235 Aurelien Jarno
        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, val);
463 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_REG_AT);
464 afa05235 Aurelien Jarno
    }
465 afa05235 Aurelien Jarno
}
466 afa05235 Aurelien Jarno
467 afa05235 Aurelien Jarno
static void tcg_out_brcond(TCGContext *s, int cond, int arg1,
468 afa05235 Aurelien Jarno
                           int arg2, int label_index)
469 afa05235 Aurelien Jarno
{
470 afa05235 Aurelien Jarno
    TCGLabel *l = &s->labels[label_index];
471 afa05235 Aurelien Jarno
472 afa05235 Aurelien Jarno
    switch (cond) {
473 afa05235 Aurelien Jarno
    case TCG_COND_EQ:
474 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_BEQ, arg1, arg2, 0);
475 afa05235 Aurelien Jarno
        break;
476 afa05235 Aurelien Jarno
    case TCG_COND_NE:
477 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_BNE, arg1, arg2, 0);
478 afa05235 Aurelien Jarno
        break;
479 afa05235 Aurelien Jarno
    case TCG_COND_LT:
480 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
481 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
482 afa05235 Aurelien Jarno
        break;
483 afa05235 Aurelien Jarno
    case TCG_COND_LTU:
484 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
485 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
486 afa05235 Aurelien Jarno
        break;
487 afa05235 Aurelien Jarno
    case TCG_COND_GE:
488 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
489 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
490 afa05235 Aurelien Jarno
        break;
491 afa05235 Aurelien Jarno
    case TCG_COND_GEU:
492 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
493 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
494 afa05235 Aurelien Jarno
        break;
495 afa05235 Aurelien Jarno
    case TCG_COND_LE:
496 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
497 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
498 afa05235 Aurelien Jarno
        break;
499 afa05235 Aurelien Jarno
    case TCG_COND_LEU:
500 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
501 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
502 afa05235 Aurelien Jarno
        break;
503 afa05235 Aurelien Jarno
    case TCG_COND_GT:
504 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
505 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
506 afa05235 Aurelien Jarno
        break;
507 afa05235 Aurelien Jarno
    case TCG_COND_GTU:
508 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
509 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
510 afa05235 Aurelien Jarno
        break;
511 afa05235 Aurelien Jarno
    default:
512 afa05235 Aurelien Jarno
        tcg_abort();
513 afa05235 Aurelien Jarno
        break;
514 afa05235 Aurelien Jarno
    }
515 afa05235 Aurelien Jarno
    if (l->has_value) {
516 afa05235 Aurelien Jarno
        reloc_pc16(s->code_ptr - 4, l->u.value);
517 afa05235 Aurelien Jarno
    } else {
518 afa05235 Aurelien Jarno
        tcg_out_reloc(s, s->code_ptr - 4, R_MIPS_PC16, label_index, 0);
519 afa05235 Aurelien Jarno
    }
520 afa05235 Aurelien Jarno
    tcg_out_nop(s);
521 afa05235 Aurelien Jarno
}
522 afa05235 Aurelien Jarno
523 afa05235 Aurelien Jarno
/* XXX: we implement it at the target level to avoid having to
524 afa05235 Aurelien Jarno
   handle cross basic blocks temporaries */
525 afa05235 Aurelien Jarno
static void tcg_out_brcond2(TCGContext *s, int cond, int arg1,
526 afa05235 Aurelien Jarno
                            int arg2, int arg3, int arg4, int label_index)
527 afa05235 Aurelien Jarno
{
528 afa05235 Aurelien Jarno
    void *label_ptr;
529 afa05235 Aurelien Jarno
530 afa05235 Aurelien Jarno
    switch(cond) {
531 afa05235 Aurelien Jarno
    case TCG_COND_NE:
532 afa05235 Aurelien Jarno
        tcg_out_brcond(s, TCG_COND_NE, arg2, arg4, label_index);
533 afa05235 Aurelien Jarno
        tcg_out_brcond(s, TCG_COND_NE, arg1, arg3, label_index);
534 afa05235 Aurelien Jarno
        return;
535 afa05235 Aurelien Jarno
    case TCG_COND_EQ:
536 afa05235 Aurelien Jarno
        break;
537 afa05235 Aurelien Jarno
    case TCG_COND_LT:
538 afa05235 Aurelien Jarno
    case TCG_COND_LE:
539 afa05235 Aurelien Jarno
        tcg_out_brcond(s, TCG_COND_LT, arg2, arg4, label_index);
540 afa05235 Aurelien Jarno
        break;
541 afa05235 Aurelien Jarno
    case TCG_COND_GT:
542 afa05235 Aurelien Jarno
    case TCG_COND_GE:
543 afa05235 Aurelien Jarno
        tcg_out_brcond(s, TCG_COND_GT, arg2, arg4, label_index);
544 afa05235 Aurelien Jarno
        break;
545 afa05235 Aurelien Jarno
    case TCG_COND_LTU:
546 afa05235 Aurelien Jarno
    case TCG_COND_LEU:
547 afa05235 Aurelien Jarno
        tcg_out_brcond(s, TCG_COND_LTU, arg2, arg4, label_index);
548 afa05235 Aurelien Jarno
        break;
549 afa05235 Aurelien Jarno
    case TCG_COND_GTU:
550 afa05235 Aurelien Jarno
    case TCG_COND_GEU:
551 afa05235 Aurelien Jarno
        tcg_out_brcond(s, TCG_COND_GTU, arg2, arg4, label_index);
552 afa05235 Aurelien Jarno
        break;
553 afa05235 Aurelien Jarno
    default:
554 afa05235 Aurelien Jarno
        tcg_abort();
555 afa05235 Aurelien Jarno
    }
556 afa05235 Aurelien Jarno
557 afa05235 Aurelien Jarno
    label_ptr = s->code_ptr;
558 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_BNE, arg2, arg4, 0);
559 afa05235 Aurelien Jarno
    tcg_out_nop(s);
560 afa05235 Aurelien Jarno
561 afa05235 Aurelien Jarno
    switch(cond) {
562 afa05235 Aurelien Jarno
    case TCG_COND_EQ:
563 afa05235 Aurelien Jarno
        tcg_out_brcond(s, TCG_COND_EQ, arg1, arg3, label_index);
564 afa05235 Aurelien Jarno
        break;
565 afa05235 Aurelien Jarno
    case TCG_COND_LT:
566 afa05235 Aurelien Jarno
    case TCG_COND_LTU:
567 afa05235 Aurelien Jarno
        tcg_out_brcond(s, TCG_COND_LTU, arg1, arg3, label_index);
568 afa05235 Aurelien Jarno
        break;
569 afa05235 Aurelien Jarno
    case TCG_COND_LE:
570 afa05235 Aurelien Jarno
    case TCG_COND_LEU:
571 afa05235 Aurelien Jarno
        tcg_out_brcond(s, TCG_COND_LEU, arg1, arg3, label_index);
572 afa05235 Aurelien Jarno
        break;
573 afa05235 Aurelien Jarno
    case TCG_COND_GT:
574 afa05235 Aurelien Jarno
    case TCG_COND_GTU:
575 afa05235 Aurelien Jarno
        tcg_out_brcond(s, TCG_COND_GTU, arg1, arg3, label_index);
576 afa05235 Aurelien Jarno
        break;
577 afa05235 Aurelien Jarno
    case TCG_COND_GE:
578 afa05235 Aurelien Jarno
    case TCG_COND_GEU:
579 afa05235 Aurelien Jarno
        tcg_out_brcond(s, TCG_COND_GEU, arg1, arg3, label_index);
580 afa05235 Aurelien Jarno
        break;
581 afa05235 Aurelien Jarno
    default:
582 afa05235 Aurelien Jarno
        tcg_abort();
583 afa05235 Aurelien Jarno
    }
584 afa05235 Aurelien Jarno
585 afa05235 Aurelien Jarno
    reloc_pc16(label_ptr, (tcg_target_long) s->code_ptr);
586 afa05235 Aurelien Jarno
}
587 afa05235 Aurelien Jarno
588 4cb26382 Aurelien Jarno
static void tcg_out_setcond(TCGContext *s, int cond, int ret,
589 4cb26382 Aurelien Jarno
                            int arg1, int arg2)
590 4cb26382 Aurelien Jarno
{
591 4cb26382 Aurelien Jarno
    switch (cond) {
592 4cb26382 Aurelien Jarno
    case TCG_COND_EQ:
593 4cb26382 Aurelien Jarno
        if (arg1 == 0) {
594 4cb26382 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_SLTIU, ret, arg2, 1);
595 4cb26382 Aurelien Jarno
        } else if (arg2 == 0) {
596 4cb26382 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, 1);
597 4cb26382 Aurelien Jarno
        } else {
598 434254aa Aurelien Jarno
            tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
599 434254aa Aurelien Jarno
            tcg_out_opc_imm(s, OPC_SLTIU, ret, ret, 1);
600 4cb26382 Aurelien Jarno
        }
601 4cb26382 Aurelien Jarno
        break;
602 4cb26382 Aurelien Jarno
    case TCG_COND_NE:
603 4cb26382 Aurelien Jarno
        if (arg1 == 0) {
604 4cb26382 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg2);
605 4cb26382 Aurelien Jarno
        } else if (arg2 == 0) {
606 4cb26382 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg1);
607 4cb26382 Aurelien Jarno
        } else {
608 434254aa Aurelien Jarno
            tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
609 434254aa Aurelien Jarno
            tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, ret);
610 4cb26382 Aurelien Jarno
        }
611 4cb26382 Aurelien Jarno
        break;
612 4cb26382 Aurelien Jarno
    case TCG_COND_LT:
613 4cb26382 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
614 4cb26382 Aurelien Jarno
        break;
615 4cb26382 Aurelien Jarno
    case TCG_COND_LTU:
616 4cb26382 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
617 4cb26382 Aurelien Jarno
        break;
618 4cb26382 Aurelien Jarno
    case TCG_COND_GE:
619 434254aa Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
620 434254aa Aurelien Jarno
        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
621 4cb26382 Aurelien Jarno
        break;
622 4cb26382 Aurelien Jarno
    case TCG_COND_GEU:
623 434254aa Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
624 434254aa Aurelien Jarno
        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
625 4cb26382 Aurelien Jarno
        break;
626 4cb26382 Aurelien Jarno
    case TCG_COND_LE:
627 434254aa Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
628 434254aa Aurelien Jarno
        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
629 4cb26382 Aurelien Jarno
        break;
630 4cb26382 Aurelien Jarno
    case TCG_COND_LEU:
631 434254aa Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
632 434254aa Aurelien Jarno
        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
633 4cb26382 Aurelien Jarno
        break;
634 4cb26382 Aurelien Jarno
    case TCG_COND_GT:
635 4cb26382 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
636 4cb26382 Aurelien Jarno
        break;
637 4cb26382 Aurelien Jarno
    case TCG_COND_GTU:
638 4cb26382 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
639 4cb26382 Aurelien Jarno
        break;
640 4cb26382 Aurelien Jarno
    default:
641 4cb26382 Aurelien Jarno
        tcg_abort();
642 4cb26382 Aurelien Jarno
        break;
643 4cb26382 Aurelien Jarno
    }
644 4cb26382 Aurelien Jarno
}
645 4cb26382 Aurelien Jarno
646 434254aa Aurelien Jarno
/* XXX: we implement it at the target level to avoid having to
647 434254aa Aurelien Jarno
   handle cross basic blocks temporaries */
648 434254aa Aurelien Jarno
static void tcg_out_setcond2(TCGContext *s, int cond, int ret,
649 434254aa Aurelien Jarno
                             int arg1, int arg2, int arg3, int arg4)
650 434254aa Aurelien Jarno
{
651 434254aa Aurelien Jarno
    switch (cond) {
652 434254aa Aurelien Jarno
    case TCG_COND_EQ:
653 434254aa Aurelien Jarno
        tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_AT, arg2, arg4);
654 434254aa Aurelien Jarno
        tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg1, arg3);
655 434254aa Aurelien Jarno
        tcg_out_opc_reg(s, OPC_AND, ret, TCG_REG_AT, TCG_REG_T0);
656 434254aa Aurelien Jarno
        return;
657 434254aa Aurelien Jarno
    case TCG_COND_NE:
658 434254aa Aurelien Jarno
        tcg_out_setcond(s, TCG_COND_NE, TCG_REG_AT, arg2, arg4);
659 434254aa Aurelien Jarno
        tcg_out_setcond(s, TCG_COND_NE, TCG_REG_T0, arg1, arg3);
660 434254aa Aurelien Jarno
        tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_AT, TCG_REG_T0);
661 434254aa Aurelien Jarno
        return;
662 434254aa Aurelien Jarno
    case TCG_COND_LT:
663 434254aa Aurelien Jarno
    case TCG_COND_LE:
664 434254aa Aurelien Jarno
        tcg_out_setcond(s, TCG_COND_LT, TCG_REG_AT, arg2, arg4);
665 434254aa Aurelien Jarno
        break;
666 434254aa Aurelien Jarno
    case TCG_COND_GT:
667 434254aa Aurelien Jarno
    case TCG_COND_GE:
668 434254aa Aurelien Jarno
        tcg_out_setcond(s, TCG_COND_GT, TCG_REG_AT, arg2, arg4);
669 434254aa Aurelien Jarno
        break;
670 434254aa Aurelien Jarno
    case TCG_COND_LTU:
671 434254aa Aurelien Jarno
    case TCG_COND_LEU:
672 434254aa Aurelien Jarno
        tcg_out_setcond(s, TCG_COND_LTU, TCG_REG_AT, arg2, arg4);
673 434254aa Aurelien Jarno
        break;
674 434254aa Aurelien Jarno
    case TCG_COND_GTU:
675 434254aa Aurelien Jarno
    case TCG_COND_GEU:
676 434254aa Aurelien Jarno
        tcg_out_setcond(s, TCG_COND_GTU, TCG_REG_AT, arg2, arg4);
677 434254aa Aurelien Jarno
        break;
678 434254aa Aurelien Jarno
    default:
679 434254aa Aurelien Jarno
        tcg_abort();
680 434254aa Aurelien Jarno
        break;
681 434254aa Aurelien Jarno
    }
682 434254aa Aurelien Jarno
683 434254aa Aurelien Jarno
    tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg2, arg4);
684 434254aa Aurelien Jarno
685 434254aa Aurelien Jarno
    switch(cond) {
686 434254aa Aurelien Jarno
    case TCG_COND_LT:
687 434254aa Aurelien Jarno
    case TCG_COND_LTU:
688 434254aa Aurelien Jarno
        tcg_out_setcond(s, TCG_COND_LTU, ret, arg1, arg3);
689 434254aa Aurelien Jarno
        break;
690 434254aa Aurelien Jarno
    case TCG_COND_LE:
691 434254aa Aurelien Jarno
    case TCG_COND_LEU:
692 434254aa Aurelien Jarno
        tcg_out_setcond(s, TCG_COND_LEU, ret, arg1, arg3);
693 434254aa Aurelien Jarno
        break;
694 434254aa Aurelien Jarno
    case TCG_COND_GT:
695 434254aa Aurelien Jarno
    case TCG_COND_GTU:
696 434254aa Aurelien Jarno
        tcg_out_setcond(s, TCG_COND_GTU, ret, arg1, arg3);
697 434254aa Aurelien Jarno
        break;
698 434254aa Aurelien Jarno
    case TCG_COND_GE:
699 434254aa Aurelien Jarno
    case TCG_COND_GEU:
700 434254aa Aurelien Jarno
        tcg_out_setcond(s, TCG_COND_GEU, ret, arg1, arg3);
701 434254aa Aurelien Jarno
        break;
702 434254aa Aurelien Jarno
    default:
703 434254aa Aurelien Jarno
        tcg_abort();
704 434254aa Aurelien Jarno
    }
705 434254aa Aurelien Jarno
706 434254aa Aurelien Jarno
    tcg_out_opc_reg(s, OPC_AND, ret, ret, TCG_REG_T0);
707 434254aa Aurelien Jarno
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
708 434254aa Aurelien Jarno
}
709 434254aa Aurelien Jarno
710 afa05235 Aurelien Jarno
#if defined(CONFIG_SOFTMMU)
711 afa05235 Aurelien Jarno
712 afa05235 Aurelien Jarno
#include "../../softmmu_defs.h"
713 afa05235 Aurelien Jarno
714 afa05235 Aurelien Jarno
static void *qemu_ld_helpers[4] = {
715 afa05235 Aurelien Jarno
    __ldb_mmu,
716 afa05235 Aurelien Jarno
    __ldw_mmu,
717 afa05235 Aurelien Jarno
    __ldl_mmu,
718 afa05235 Aurelien Jarno
    __ldq_mmu,
719 afa05235 Aurelien Jarno
};
720 afa05235 Aurelien Jarno
721 afa05235 Aurelien Jarno
static void *qemu_st_helpers[4] = {
722 afa05235 Aurelien Jarno
    __stb_mmu,
723 afa05235 Aurelien Jarno
    __stw_mmu,
724 afa05235 Aurelien Jarno
    __stl_mmu,
725 afa05235 Aurelien Jarno
    __stq_mmu,
726 afa05235 Aurelien Jarno
};
727 afa05235 Aurelien Jarno
#endif
728 afa05235 Aurelien Jarno
729 afa05235 Aurelien Jarno
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
730 afa05235 Aurelien Jarno
                            int opc)
731 afa05235 Aurelien Jarno
{
732 afa05235 Aurelien Jarno
    int addr_regl, addr_reg1, addr_meml;
733 afa05235 Aurelien Jarno
    int data_regl, data_regh, data_reg1, data_reg2;
734 afa05235 Aurelien Jarno
    int mem_index, s_bits;
735 afa05235 Aurelien Jarno
#if defined(CONFIG_SOFTMMU)
736 afa05235 Aurelien Jarno
    void *label1_ptr, *label2_ptr;
737 afa05235 Aurelien Jarno
    int sp_args;
738 afa05235 Aurelien Jarno
#endif
739 afa05235 Aurelien Jarno
#if TARGET_LONG_BITS == 64
740 afa05235 Aurelien Jarno
# if defined(CONFIG_SOFTMMU)
741 afa05235 Aurelien Jarno
    uint8_t *label3_ptr;
742 afa05235 Aurelien Jarno
# endif
743 afa05235 Aurelien Jarno
    int addr_regh, addr_reg2, addr_memh;
744 afa05235 Aurelien Jarno
#endif
745 afa05235 Aurelien Jarno
    data_regl = *args++;
746 afa05235 Aurelien Jarno
    if (opc == 3)
747 afa05235 Aurelien Jarno
        data_regh = *args++;
748 afa05235 Aurelien Jarno
    else
749 afa05235 Aurelien Jarno
        data_regh = 0;
750 afa05235 Aurelien Jarno
    addr_regl = *args++;
751 afa05235 Aurelien Jarno
#if TARGET_LONG_BITS == 64
752 afa05235 Aurelien Jarno
    addr_regh = *args++;
753 afa05235 Aurelien Jarno
#endif
754 afa05235 Aurelien Jarno
    mem_index = *args;
755 afa05235 Aurelien Jarno
    s_bits = opc & 3;
756 afa05235 Aurelien Jarno
757 afa05235 Aurelien Jarno
    if (opc == 3) {
758 afa05235 Aurelien Jarno
#if defined(TCG_TARGET_WORDS_BIGENDIAN)
759 afa05235 Aurelien Jarno
        data_reg1 = data_regh;
760 afa05235 Aurelien Jarno
        data_reg2 = data_regl;
761 afa05235 Aurelien Jarno
#else
762 afa05235 Aurelien Jarno
        data_reg1 = data_regl;
763 afa05235 Aurelien Jarno
        data_reg2 = data_regh;
764 afa05235 Aurelien Jarno
#endif
765 afa05235 Aurelien Jarno
    } else {
766 afa05235 Aurelien Jarno
        data_reg1 = data_regl;
767 afa05235 Aurelien Jarno
        data_reg2 = 0;
768 afa05235 Aurelien Jarno
    }
769 afa05235 Aurelien Jarno
#if TARGET_LONG_BITS == 64
770 afa05235 Aurelien Jarno
# if defined(TCG_TARGET_WORDS_BIGENDIAN)
771 afa05235 Aurelien Jarno
    addr_reg1 = addr_regh;
772 afa05235 Aurelien Jarno
    addr_reg2 = addr_regl;
773 afa05235 Aurelien Jarno
    addr_memh = 0;
774 afa05235 Aurelien Jarno
    addr_meml = 4;
775 afa05235 Aurelien Jarno
# else
776 afa05235 Aurelien Jarno
    addr_reg1 = addr_regl;
777 afa05235 Aurelien Jarno
    addr_reg2 = addr_regh;
778 afa05235 Aurelien Jarno
    addr_memh = 4;
779 afa05235 Aurelien Jarno
    addr_meml = 0;
780 afa05235 Aurelien Jarno
# endif
781 afa05235 Aurelien Jarno
#else
782 afa05235 Aurelien Jarno
    addr_reg1 = addr_regl;
783 afa05235 Aurelien Jarno
    addr_meml = 0;
784 afa05235 Aurelien Jarno
#endif
785 afa05235 Aurelien Jarno
786 afa05235 Aurelien Jarno
#if defined(CONFIG_SOFTMMU)
787 afa05235 Aurelien Jarno
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
788 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
789 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
790 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
791 afa05235 Aurelien Jarno
                    offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_meml);
792 afa05235 Aurelien Jarno
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
793 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
794 afa05235 Aurelien Jarno
795 afa05235 Aurelien Jarno
# if TARGET_LONG_BITS == 64
796 afa05235 Aurelien Jarno
    label3_ptr = s->code_ptr;
797 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT, 0);
798 afa05235 Aurelien Jarno
    tcg_out_nop(s);
799 afa05235 Aurelien Jarno
800 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
801 afa05235 Aurelien Jarno
                    offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_memh);
802 afa05235 Aurelien Jarno
803 afa05235 Aurelien Jarno
    label1_ptr = s->code_ptr;
804 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_BEQ, addr_regh, TCG_REG_AT, 0);
805 afa05235 Aurelien Jarno
    tcg_out_nop(s);
806 afa05235 Aurelien Jarno
807 afa05235 Aurelien Jarno
    reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
808 afa05235 Aurelien Jarno
# else
809 afa05235 Aurelien Jarno
    label1_ptr = s->code_ptr;
810 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT, 0);
811 afa05235 Aurelien Jarno
    tcg_out_nop(s);
812 afa05235 Aurelien Jarno
# endif
813 afa05235 Aurelien Jarno
814 afa05235 Aurelien Jarno
    /* slow path */
815 afa05235 Aurelien Jarno
    sp_args = TCG_REG_A0;
816 afa05235 Aurelien Jarno
    tcg_out_mov(s, sp_args++, addr_reg1);
817 afa05235 Aurelien Jarno
# if TARGET_LONG_BITS == 64
818 afa05235 Aurelien Jarno
    tcg_out_mov(s, sp_args++, addr_reg2);
819 afa05235 Aurelien Jarno
# endif
820 afa05235 Aurelien Jarno
    tcg_out_movi(s, TCG_TYPE_I32, sp_args++, mem_index);
821 afa05235 Aurelien Jarno
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]);
822 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
823 afa05235 Aurelien Jarno
    tcg_out_nop(s);
824 afa05235 Aurelien Jarno
825 afa05235 Aurelien Jarno
    switch(opc) {
826 afa05235 Aurelien Jarno
    case 0:
827 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xff);
828 afa05235 Aurelien Jarno
        break;
829 afa05235 Aurelien Jarno
    case 0 | 4:
830 afa05235 Aurelien Jarno
        tcg_out_opc_sa(s, OPC_SLL, TCG_REG_V0, TCG_REG_V0, 24);
831 afa05235 Aurelien Jarno
        tcg_out_opc_sa(s, OPC_SRA, data_reg1, TCG_REG_V0, 24);
832 afa05235 Aurelien Jarno
        break;
833 afa05235 Aurelien Jarno
    case 1:
834 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xffff);
835 afa05235 Aurelien Jarno
        break;
836 afa05235 Aurelien Jarno
    case 1 | 4:
837 afa05235 Aurelien Jarno
        tcg_out_opc_sa(s, OPC_SLL, TCG_REG_V0, TCG_REG_V0, 16);
838 afa05235 Aurelien Jarno
        tcg_out_opc_sa(s, OPC_SRA, data_reg1, TCG_REG_V0, 16);
839 afa05235 Aurelien Jarno
        break;
840 afa05235 Aurelien Jarno
    case 2:
841 afa05235 Aurelien Jarno
        tcg_out_mov(s, data_reg1, TCG_REG_V0);
842 afa05235 Aurelien Jarno
        break;
843 afa05235 Aurelien Jarno
    case 3:
844 afa05235 Aurelien Jarno
        tcg_out_mov(s, data_reg2, TCG_REG_V1);
845 afa05235 Aurelien Jarno
        tcg_out_mov(s, data_reg1, TCG_REG_V0);
846 afa05235 Aurelien Jarno
        break;
847 afa05235 Aurelien Jarno
    default:
848 afa05235 Aurelien Jarno
        tcg_abort();
849 afa05235 Aurelien Jarno
    }
850 afa05235 Aurelien Jarno
851 afa05235 Aurelien Jarno
    label2_ptr = s->code_ptr;
852 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO, 0);
853 afa05235 Aurelien Jarno
    tcg_out_nop(s);
854 afa05235 Aurelien Jarno
855 afa05235 Aurelien Jarno
    /* label1: fast path */
856 afa05235 Aurelien Jarno
    reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
857 afa05235 Aurelien Jarno
858 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_V0, TCG_REG_A0,
859 afa05235 Aurelien Jarno
                    offsetof(CPUState, tlb_table[mem_index][0].addend) + addr_meml);
860 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_V0, addr_regl);
861 afa05235 Aurelien Jarno
862 afa05235 Aurelien Jarno
    addr_reg1 = TCG_REG_V0;
863 afa05235 Aurelien Jarno
#endif
864 afa05235 Aurelien Jarno
865 afa05235 Aurelien Jarno
    switch(opc) {
866 afa05235 Aurelien Jarno
    case 0:
867 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_LBU, data_reg1, addr_reg1, 0);
868 afa05235 Aurelien Jarno
        break;
869 afa05235 Aurelien Jarno
    case 0 | 4:
870 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_LB, data_reg1, addr_reg1, 0);
871 afa05235 Aurelien Jarno
        break;
872 afa05235 Aurelien Jarno
    case 1:
873 afa05235 Aurelien Jarno
        if (TCG_NEED_BSWAP) {
874 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, addr_reg1, 0);
875 afa05235 Aurelien Jarno
            tcg_out_bswap16(s, data_reg1, TCG_REG_T0);
876 afa05235 Aurelien Jarno
        } else {
877 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_LHU, data_reg1, addr_reg1, 0);
878 afa05235 Aurelien Jarno
        }
879 afa05235 Aurelien Jarno
        break;
880 afa05235 Aurelien Jarno
    case 1 | 4:
881 afa05235 Aurelien Jarno
        if (TCG_NEED_BSWAP) {
882 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, addr_reg1, 0);
883 afa05235 Aurelien Jarno
            tcg_out_bswap16s(s, data_reg1, TCG_REG_T0);
884 afa05235 Aurelien Jarno
        } else {
885 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_LH, data_reg1, addr_reg1, 0);
886 afa05235 Aurelien Jarno
        }
887 afa05235 Aurelien Jarno
        break;
888 afa05235 Aurelien Jarno
    case 2:
889 afa05235 Aurelien Jarno
        if (TCG_NEED_BSWAP) {
890 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, addr_reg1, 0);
891 afa05235 Aurelien Jarno
            tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
892 afa05235 Aurelien Jarno
        } else {
893 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_LW, data_reg1, addr_reg1, 0);
894 afa05235 Aurelien Jarno
        }
895 afa05235 Aurelien Jarno
        break;
896 afa05235 Aurelien Jarno
    case 3:
897 afa05235 Aurelien Jarno
#if !defined(CONFIG_SOFTMMU)
898 afa05235 Aurelien Jarno
        tcg_out_mov(s, TCG_REG_V0, addr_reg1);
899 afa05235 Aurelien Jarno
        addr_reg1 = TCG_REG_V0;
900 afa05235 Aurelien Jarno
#endif
901 afa05235 Aurelien Jarno
        if (TCG_NEED_BSWAP) {
902 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, addr_reg1, 4);
903 afa05235 Aurelien Jarno
            tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
904 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, addr_reg1, 0);
905 afa05235 Aurelien Jarno
            tcg_out_bswap32(s, data_reg2, TCG_REG_T0);
906 afa05235 Aurelien Jarno
        } else {
907 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_LW, data_reg1, addr_reg1, 0);
908 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_LW, data_reg2, addr_reg1, 4);
909 afa05235 Aurelien Jarno
        }
910 afa05235 Aurelien Jarno
        break;
911 afa05235 Aurelien Jarno
    default:
912 afa05235 Aurelien Jarno
        tcg_abort();
913 afa05235 Aurelien Jarno
    }
914 afa05235 Aurelien Jarno
915 afa05235 Aurelien Jarno
#if defined(CONFIG_SOFTMMU)
916 afa05235 Aurelien Jarno
    reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
917 afa05235 Aurelien Jarno
#endif
918 afa05235 Aurelien Jarno
}
919 afa05235 Aurelien Jarno
920 afa05235 Aurelien Jarno
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
921 afa05235 Aurelien Jarno
                            int opc)
922 afa05235 Aurelien Jarno
{
923 afa05235 Aurelien Jarno
    int addr_regl, addr_reg1, addr_meml;
924 afa05235 Aurelien Jarno
    int data_regl, data_regh, data_reg1, data_reg2;
925 afa05235 Aurelien Jarno
    int mem_index, s_bits;
926 afa05235 Aurelien Jarno
#if defined(CONFIG_SOFTMMU)
927 afa05235 Aurelien Jarno
    uint8_t *label1_ptr, *label2_ptr;
928 afa05235 Aurelien Jarno
    int sp_args;
929 afa05235 Aurelien Jarno
#endif
930 afa05235 Aurelien Jarno
#if TARGET_LONG_BITS == 64
931 afa05235 Aurelien Jarno
# if defined(CONFIG_SOFTMMU)
932 afa05235 Aurelien Jarno
    uint8_t *label3_ptr;
933 afa05235 Aurelien Jarno
# endif
934 afa05235 Aurelien Jarno
    int addr_regh, addr_reg2, addr_memh;
935 afa05235 Aurelien Jarno
#endif
936 afa05235 Aurelien Jarno
937 afa05235 Aurelien Jarno
    data_regl = *args++;
938 afa05235 Aurelien Jarno
    if (opc == 3) {
939 afa05235 Aurelien Jarno
        data_regh = *args++;
940 afa05235 Aurelien Jarno
#if defined(TCG_TARGET_WORDS_BIGENDIAN)
941 afa05235 Aurelien Jarno
        data_reg1 = data_regh;
942 afa05235 Aurelien Jarno
        data_reg2 = data_regl;
943 afa05235 Aurelien Jarno
#else
944 afa05235 Aurelien Jarno
        data_reg1 = data_regl;
945 afa05235 Aurelien Jarno
        data_reg2 = data_regh;
946 afa05235 Aurelien Jarno
#endif
947 afa05235 Aurelien Jarno
    } else {
948 afa05235 Aurelien Jarno
        data_reg1 = data_regl;
949 afa05235 Aurelien Jarno
        data_reg2 = 0;
950 afa05235 Aurelien Jarno
        data_regh = 0;
951 afa05235 Aurelien Jarno
    }
952 afa05235 Aurelien Jarno
    addr_regl = *args++;
953 afa05235 Aurelien Jarno
#if TARGET_LONG_BITS == 64
954 afa05235 Aurelien Jarno
    addr_regh = *args++;
955 afa05235 Aurelien Jarno
# if defined(TCG_TARGET_WORDS_BIGENDIAN)
956 afa05235 Aurelien Jarno
    addr_reg1 = addr_regh;
957 afa05235 Aurelien Jarno
    addr_reg2 = addr_regl;
958 afa05235 Aurelien Jarno
    addr_memh = 0;
959 afa05235 Aurelien Jarno
    addr_meml = 4;
960 afa05235 Aurelien Jarno
# else
961 afa05235 Aurelien Jarno
    addr_reg1 = addr_regl;
962 afa05235 Aurelien Jarno
    addr_reg2 = addr_regh;
963 afa05235 Aurelien Jarno
    addr_memh = 4;
964 afa05235 Aurelien Jarno
    addr_meml = 0;
965 afa05235 Aurelien Jarno
# endif
966 afa05235 Aurelien Jarno
#else
967 afa05235 Aurelien Jarno
    addr_reg1 = addr_regl;
968 afa05235 Aurelien Jarno
    addr_meml = 0;
969 afa05235 Aurelien Jarno
#endif
970 afa05235 Aurelien Jarno
    mem_index = *args;
971 afa05235 Aurelien Jarno
    s_bits = opc;
972 afa05235 Aurelien Jarno
973 afa05235 Aurelien Jarno
#if defined(CONFIG_SOFTMMU)
974 afa05235 Aurelien Jarno
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
975 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
976 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
977 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
978 afa05235 Aurelien Jarno
                    offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_meml);
979 afa05235 Aurelien Jarno
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
980 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
981 afa05235 Aurelien Jarno
982 afa05235 Aurelien Jarno
# if TARGET_LONG_BITS == 64
983 afa05235 Aurelien Jarno
    label3_ptr = s->code_ptr;
984 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT, 0);
985 afa05235 Aurelien Jarno
    tcg_out_nop(s);
986 afa05235 Aurelien Jarno
987 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
988 afa05235 Aurelien Jarno
                    offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_memh);
989 afa05235 Aurelien Jarno
990 afa05235 Aurelien Jarno
    label1_ptr = s->code_ptr;
991 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_BEQ, addr_regh, TCG_REG_AT, 0);
992 afa05235 Aurelien Jarno
    tcg_out_nop(s);
993 afa05235 Aurelien Jarno
994 afa05235 Aurelien Jarno
    reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
995 afa05235 Aurelien Jarno
# else
996 afa05235 Aurelien Jarno
    label1_ptr = s->code_ptr;
997 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT, 0);
998 afa05235 Aurelien Jarno
    tcg_out_nop(s);
999 afa05235 Aurelien Jarno
# endif
1000 afa05235 Aurelien Jarno
1001 afa05235 Aurelien Jarno
    /* slow path */
1002 afa05235 Aurelien Jarno
    sp_args = TCG_REG_A0;
1003 afa05235 Aurelien Jarno
    tcg_out_mov(s, sp_args++, addr_reg1);
1004 afa05235 Aurelien Jarno
# if TARGET_LONG_BITS == 64
1005 afa05235 Aurelien Jarno
    tcg_out_mov(s, sp_args++, addr_reg2);
1006 afa05235 Aurelien Jarno
# endif
1007 afa05235 Aurelien Jarno
    switch(opc) {
1008 afa05235 Aurelien Jarno
    case 0:
1009 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xff);
1010 afa05235 Aurelien Jarno
        break;
1011 afa05235 Aurelien Jarno
    case 1:
1012 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xffff);
1013 afa05235 Aurelien Jarno
        break;
1014 afa05235 Aurelien Jarno
    case 2:
1015 afa05235 Aurelien Jarno
        tcg_out_mov(s, sp_args++, data_reg1);
1016 afa05235 Aurelien Jarno
        break;
1017 afa05235 Aurelien Jarno
    case 3:
1018 afa05235 Aurelien Jarno
        sp_args = (sp_args + 1) & ~1;
1019 afa05235 Aurelien Jarno
        tcg_out_mov(s, sp_args++, data_reg1);
1020 afa05235 Aurelien Jarno
        tcg_out_mov(s, sp_args++, data_reg2);
1021 afa05235 Aurelien Jarno
        break;
1022 afa05235 Aurelien Jarno
    default:
1023 afa05235 Aurelien Jarno
        tcg_abort();
1024 afa05235 Aurelien Jarno
    }
1025 afa05235 Aurelien Jarno
    if (sp_args > TCG_REG_A3) {
1026 afa05235 Aurelien Jarno
        /* Push mem_index on the stack */
1027 afa05235 Aurelien Jarno
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, mem_index);
1028 afa05235 Aurelien Jarno
        tcg_out_st(s, TCG_TYPE_I32, TCG_REG_AT, TCG_REG_SP, 16);
1029 afa05235 Aurelien Jarno
    } else {
1030 afa05235 Aurelien Jarno
        tcg_out_movi(s, TCG_TYPE_I32, sp_args, mem_index);
1031 afa05235 Aurelien Jarno
    }
1032 afa05235 Aurelien Jarno
1033 afa05235 Aurelien Jarno
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_st_helpers[s_bits]);
1034 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
1035 afa05235 Aurelien Jarno
    tcg_out_nop(s);
1036 afa05235 Aurelien Jarno
1037 afa05235 Aurelien Jarno
    label2_ptr = s->code_ptr;
1038 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO, 0);
1039 afa05235 Aurelien Jarno
    tcg_out_nop(s);
1040 afa05235 Aurelien Jarno
1041 afa05235 Aurelien Jarno
    /* label1: fast path */
1042 afa05235 Aurelien Jarno
    reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
1043 afa05235 Aurelien Jarno
1044 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
1045 afa05235 Aurelien Jarno
                    offsetof(CPUState, tlb_table[mem_index][0].addend) + addr_meml);
1046 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
1047 afa05235 Aurelien Jarno
1048 afa05235 Aurelien Jarno
    addr_reg1 = TCG_REG_A0;
1049 afa05235 Aurelien Jarno
#endif
1050 afa05235 Aurelien Jarno
1051 afa05235 Aurelien Jarno
    switch(opc) {
1052 afa05235 Aurelien Jarno
    case 0:
1053 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_SB, data_reg1, addr_reg1, 0);
1054 afa05235 Aurelien Jarno
        break;
1055 afa05235 Aurelien Jarno
    case 1:
1056 afa05235 Aurelien Jarno
        if (TCG_NEED_BSWAP) {
1057 afa05235 Aurelien Jarno
            tcg_out_bswap16(s, TCG_REG_T0, data_reg1);
1058 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_SH, TCG_REG_T0, addr_reg1, 0);
1059 afa05235 Aurelien Jarno
        } else {
1060 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_SH, data_reg1, addr_reg1, 0);
1061 afa05235 Aurelien Jarno
        }
1062 afa05235 Aurelien Jarno
        break;
1063 afa05235 Aurelien Jarno
    case 2:
1064 afa05235 Aurelien Jarno
        if (TCG_NEED_BSWAP) {
1065 afa05235 Aurelien Jarno
            tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1066 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, addr_reg1, 0);
1067 afa05235 Aurelien Jarno
        } else {
1068 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_SW, data_reg1, addr_reg1, 0);
1069 afa05235 Aurelien Jarno
        }
1070 afa05235 Aurelien Jarno
        break;
1071 afa05235 Aurelien Jarno
    case 3:
1072 afa05235 Aurelien Jarno
        if (TCG_NEED_BSWAP) {
1073 afa05235 Aurelien Jarno
            tcg_out_bswap32(s, TCG_REG_T0, data_reg2);
1074 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, addr_reg1, 0);
1075 afa05235 Aurelien Jarno
            tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1076 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, addr_reg1, 4);
1077 afa05235 Aurelien Jarno
        } else {
1078 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_SW, data_reg1, addr_reg1, 0);
1079 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_SW, data_reg2, addr_reg1, 4);
1080 afa05235 Aurelien Jarno
        }
1081 afa05235 Aurelien Jarno
        break;
1082 afa05235 Aurelien Jarno
    default:
1083 afa05235 Aurelien Jarno
        tcg_abort();
1084 afa05235 Aurelien Jarno
    }
1085 afa05235 Aurelien Jarno
1086 afa05235 Aurelien Jarno
#if defined(CONFIG_SOFTMMU)
1087 afa05235 Aurelien Jarno
    reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
1088 afa05235 Aurelien Jarno
#endif
1089 afa05235 Aurelien Jarno
}
1090 afa05235 Aurelien Jarno
1091 afa05235 Aurelien Jarno
static inline void tcg_out_op(TCGContext *s, int opc,
1092 afa05235 Aurelien Jarno
                              const TCGArg *args, const int *const_args)
1093 afa05235 Aurelien Jarno
{
1094 afa05235 Aurelien Jarno
    switch(opc) {
1095 afa05235 Aurelien Jarno
    case INDEX_op_exit_tb:
1096 afa05235 Aurelien Jarno
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_V0, args[0]);
1097 afa05235 Aurelien Jarno
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, (tcg_target_long)tb_ret_addr);
1098 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1099 afa05235 Aurelien Jarno
        tcg_out_nop(s);
1100 afa05235 Aurelien Jarno
        break;
1101 afa05235 Aurelien Jarno
    case INDEX_op_goto_tb:
1102 afa05235 Aurelien Jarno
        if (s->tb_jmp_offset) {
1103 afa05235 Aurelien Jarno
            /* direct jump method */
1104 afa05235 Aurelien Jarno
            tcg_abort();
1105 afa05235 Aurelien Jarno
        } else {
1106 afa05235 Aurelien Jarno
            /* indirect jump method */
1107 afa05235 Aurelien Jarno
            tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, (tcg_target_long)(s->tb_next + args[0]));
1108 afa05235 Aurelien Jarno
            tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_AT, TCG_REG_AT, 0);
1109 afa05235 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1110 afa05235 Aurelien Jarno
        }
1111 afa05235 Aurelien Jarno
        tcg_out_nop(s);
1112 afa05235 Aurelien Jarno
        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1113 afa05235 Aurelien Jarno
        break;
1114 afa05235 Aurelien Jarno
    case INDEX_op_call:
1115 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, args[0], 0);
1116 afa05235 Aurelien Jarno
        tcg_out_nop(s);
1117 afa05235 Aurelien Jarno
        break;
1118 afa05235 Aurelien Jarno
    case INDEX_op_jmp:
1119 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_JR, 0, args[0], 0);
1120 afa05235 Aurelien Jarno
        tcg_out_nop(s);
1121 afa05235 Aurelien Jarno
        break;
1122 afa05235 Aurelien Jarno
    case INDEX_op_br:
1123 afa05235 Aurelien Jarno
        tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, args[0]);
1124 afa05235 Aurelien Jarno
        break;
1125 afa05235 Aurelien Jarno
1126 afa05235 Aurelien Jarno
    case INDEX_op_mov_i32:
1127 afa05235 Aurelien Jarno
        tcg_out_mov(s, args[0], args[1]);
1128 afa05235 Aurelien Jarno
        break;
1129 afa05235 Aurelien Jarno
    case INDEX_op_movi_i32:
1130 afa05235 Aurelien Jarno
        tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1131 afa05235 Aurelien Jarno
        break;
1132 afa05235 Aurelien Jarno
1133 afa05235 Aurelien Jarno
    case INDEX_op_ld8u_i32:
1134 afa05235 Aurelien Jarno
        tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]);
1135 afa05235 Aurelien Jarno
        break;
1136 afa05235 Aurelien Jarno
    case INDEX_op_ld8s_i32:
1137 afa05235 Aurelien Jarno
        tcg_out_ldst(s, OPC_LB, args[0], args[1], args[2]);
1138 afa05235 Aurelien Jarno
        break;
1139 afa05235 Aurelien Jarno
    case INDEX_op_ld16u_i32:
1140 afa05235 Aurelien Jarno
        tcg_out_ldst(s, OPC_LHU, args[0], args[1], args[2]);
1141 afa05235 Aurelien Jarno
        break;
1142 afa05235 Aurelien Jarno
    case INDEX_op_ld16s_i32:
1143 afa05235 Aurelien Jarno
        tcg_out_ldst(s, OPC_LH, args[0], args[1], args[2]);
1144 afa05235 Aurelien Jarno
        break;
1145 afa05235 Aurelien Jarno
    case INDEX_op_ld_i32:
1146 afa05235 Aurelien Jarno
        tcg_out_ldst(s, OPC_LW, args[0], args[1], args[2]);
1147 afa05235 Aurelien Jarno
        break;
1148 afa05235 Aurelien Jarno
    case INDEX_op_st8_i32:
1149 afa05235 Aurelien Jarno
        tcg_out_ldst(s, OPC_SB, args[0], args[1], args[2]);
1150 afa05235 Aurelien Jarno
        break;
1151 afa05235 Aurelien Jarno
    case INDEX_op_st16_i32:
1152 afa05235 Aurelien Jarno
        tcg_out_ldst(s, OPC_SH, args[0], args[1], args[2]);
1153 afa05235 Aurelien Jarno
        break;
1154 afa05235 Aurelien Jarno
    case INDEX_op_st_i32:
1155 afa05235 Aurelien Jarno
        tcg_out_ldst(s, OPC_SW, args[0], args[1], args[2]);
1156 afa05235 Aurelien Jarno
        break;
1157 afa05235 Aurelien Jarno
1158 afa05235 Aurelien Jarno
    case INDEX_op_add_i32:
1159 afa05235 Aurelien Jarno
        if (const_args[2]) {
1160 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], args[2]);
1161 afa05235 Aurelien Jarno
        } else {
1162 afa05235 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_ADDU, args[0], args[1], args[2]);
1163 afa05235 Aurelien Jarno
        }
1164 afa05235 Aurelien Jarno
        break;
1165 afa05235 Aurelien Jarno
    case INDEX_op_add2_i32:
1166 afa05235 Aurelien Jarno
        if (const_args[4]) {
1167 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], args[4]);
1168 afa05235 Aurelien Jarno
        } else {
1169 afa05235 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, args[2], args[4]);
1170 afa05235 Aurelien Jarno
        }
1171 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, TCG_REG_AT, args[2]);
1172 afa05235 Aurelien Jarno
        if (const_args[5]) {
1173 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], args[5]);
1174 afa05235 Aurelien Jarno
        } else {
1175 afa05235 Aurelien Jarno
             tcg_out_opc_reg(s, OPC_ADDU, args[1], args[3], args[5]);
1176 afa05235 Aurelien Jarno
        }
1177 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_ADDU, args[1], args[1], TCG_REG_T0);
1178 afa05235 Aurelien Jarno
        tcg_out_mov(s, args[0], TCG_REG_AT);
1179 afa05235 Aurelien Jarno
        break;
1180 afa05235 Aurelien Jarno
    case INDEX_op_sub_i32:
1181 afa05235 Aurelien Jarno
        if (const_args[2]) {
1182 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], -args[2]);
1183 afa05235 Aurelien Jarno
        } else {
1184 afa05235 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_SUBU, args[0], args[1], args[2]);
1185 afa05235 Aurelien Jarno
        }
1186 afa05235 Aurelien Jarno
        break;
1187 afa05235 Aurelien Jarno
    case INDEX_op_sub2_i32:
1188 afa05235 Aurelien Jarno
        if (const_args[4]) {
1189 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], -args[4]);
1190 afa05235 Aurelien Jarno
        } else {
1191 afa05235 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, args[2], args[4]);
1192 afa05235 Aurelien Jarno
        }
1193 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, args[2], TCG_REG_AT);
1194 afa05235 Aurelien Jarno
        if (const_args[5]) {
1195 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], -args[5]);
1196 afa05235 Aurelien Jarno
        } else {
1197 afa05235 Aurelien Jarno
             tcg_out_opc_reg(s, OPC_SUBU, args[1], args[3], args[5]);
1198 afa05235 Aurelien Jarno
        }
1199 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SUBU, args[1], args[1], TCG_REG_T0);
1200 afa05235 Aurelien Jarno
        tcg_out_mov(s, args[0], TCG_REG_AT);
1201 afa05235 Aurelien Jarno
        break;
1202 afa05235 Aurelien Jarno
    case INDEX_op_mul_i32:
1203 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
1204 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1205 afa05235 Aurelien Jarno
        break;
1206 afa05235 Aurelien Jarno
    case INDEX_op_mulu2_i32:
1207 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_MULTU, 0, args[2], args[3]);
1208 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1209 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
1210 afa05235 Aurelien Jarno
        break;
1211 afa05235 Aurelien Jarno
    case INDEX_op_div_i32:
1212 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1213 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1214 afa05235 Aurelien Jarno
        break;
1215 afa05235 Aurelien Jarno
    case INDEX_op_divu_i32:
1216 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1217 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1218 afa05235 Aurelien Jarno
        break;
1219 afa05235 Aurelien Jarno
    case INDEX_op_rem_i32:
1220 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1221 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1222 afa05235 Aurelien Jarno
        break;
1223 afa05235 Aurelien Jarno
    case INDEX_op_remu_i32:
1224 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1225 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1226 afa05235 Aurelien Jarno
        break;
1227 afa05235 Aurelien Jarno
1228 afa05235 Aurelien Jarno
    case INDEX_op_and_i32:
1229 afa05235 Aurelien Jarno
        if (const_args[2]) {
1230 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_ANDI, args[0], args[1], args[2]);
1231 afa05235 Aurelien Jarno
        } else {
1232 afa05235 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_AND, args[0], args[1], args[2]);
1233 afa05235 Aurelien Jarno
        }
1234 afa05235 Aurelien Jarno
        break;
1235 afa05235 Aurelien Jarno
    case INDEX_op_or_i32:
1236 afa05235 Aurelien Jarno
        if (const_args[2]) {
1237 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_ORI, args[0], args[1], args[2]);
1238 afa05235 Aurelien Jarno
        } else {
1239 afa05235 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_OR, args[0], args[1], args[2]);
1240 afa05235 Aurelien Jarno
        }
1241 afa05235 Aurelien Jarno
        break;
1242 afa05235 Aurelien Jarno
    case INDEX_op_not_i32:
1243 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_NOR, args[0], args[1], args[1]);
1244 afa05235 Aurelien Jarno
        break;
1245 afa05235 Aurelien Jarno
    case INDEX_op_xor_i32:
1246 afa05235 Aurelien Jarno
        if (const_args[2]) {
1247 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_XORI, args[0], args[1], args[2]);
1248 afa05235 Aurelien Jarno
        } else {
1249 afa05235 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_XOR, args[0], args[1], args[2]);
1250 afa05235 Aurelien Jarno
        }
1251 afa05235 Aurelien Jarno
        break;
1252 afa05235 Aurelien Jarno
1253 afa05235 Aurelien Jarno
    case INDEX_op_sar_i32:
1254 afa05235 Aurelien Jarno
        if (const_args[2]) {
1255 afa05235 Aurelien Jarno
            tcg_out_opc_sa(s, OPC_SRA, args[0], args[1], args[2]);
1256 afa05235 Aurelien Jarno
        } else {
1257 afa05235 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_SRAV, args[0], args[2], args[1]);
1258 afa05235 Aurelien Jarno
        }
1259 afa05235 Aurelien Jarno
        break;
1260 afa05235 Aurelien Jarno
    case INDEX_op_shl_i32:
1261 afa05235 Aurelien Jarno
        if (const_args[2]) {
1262 afa05235 Aurelien Jarno
            tcg_out_opc_sa(s, OPC_SLL, args[0], args[1], args[2]);
1263 afa05235 Aurelien Jarno
        } else {
1264 afa05235 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_SLLV, args[0], args[2], args[1]);
1265 afa05235 Aurelien Jarno
        }
1266 afa05235 Aurelien Jarno
        break;
1267 afa05235 Aurelien Jarno
    case INDEX_op_shr_i32:
1268 afa05235 Aurelien Jarno
        if (const_args[2]) {
1269 afa05235 Aurelien Jarno
            tcg_out_opc_sa(s, OPC_SRL, args[0], args[1], args[2]);
1270 afa05235 Aurelien Jarno
        } else {
1271 afa05235 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_SRLV, args[0], args[2], args[1]);
1272 afa05235 Aurelien Jarno
        }
1273 afa05235 Aurelien Jarno
        break;
1274 afa05235 Aurelien Jarno
1275 afa05235 Aurelien Jarno
    case INDEX_op_brcond_i32:
1276 afa05235 Aurelien Jarno
        tcg_out_brcond(s, args[2], args[0], args[1], args[3]);
1277 afa05235 Aurelien Jarno
        break;
1278 afa05235 Aurelien Jarno
    case INDEX_op_brcond2_i32:
1279 afa05235 Aurelien Jarno
        tcg_out_brcond2(s, args[4], args[0], args[1], args[2], args[3], args[5]);
1280 afa05235 Aurelien Jarno
        break;
1281 afa05235 Aurelien Jarno
1282 4cb26382 Aurelien Jarno
    case INDEX_op_setcond_i32:
1283 4cb26382 Aurelien Jarno
        tcg_out_setcond(s, args[3], args[0], args[1], args[2]);
1284 4cb26382 Aurelien Jarno
        break;
1285 434254aa Aurelien Jarno
    case INDEX_op_setcond2_i32:
1286 434254aa Aurelien Jarno
        tcg_out_setcond2(s, args[5], args[0], args[1], args[2], args[3], args[4]);
1287 434254aa Aurelien Jarno
        break;
1288 4cb26382 Aurelien Jarno
1289 afa05235 Aurelien Jarno
    case INDEX_op_qemu_ld8u:
1290 afa05235 Aurelien Jarno
        tcg_out_qemu_ld(s, args, 0);
1291 afa05235 Aurelien Jarno
        break;
1292 afa05235 Aurelien Jarno
    case INDEX_op_qemu_ld8s:
1293 afa05235 Aurelien Jarno
        tcg_out_qemu_ld(s, args, 0 | 4);
1294 afa05235 Aurelien Jarno
        break;
1295 afa05235 Aurelien Jarno
    case INDEX_op_qemu_ld16u:
1296 afa05235 Aurelien Jarno
        tcg_out_qemu_ld(s, args, 1);
1297 afa05235 Aurelien Jarno
        break;
1298 afa05235 Aurelien Jarno
    case INDEX_op_qemu_ld16s:
1299 afa05235 Aurelien Jarno
        tcg_out_qemu_ld(s, args, 1 | 4);
1300 afa05235 Aurelien Jarno
        break;
1301 afa05235 Aurelien Jarno
    case INDEX_op_qemu_ld32u:
1302 afa05235 Aurelien Jarno
        tcg_out_qemu_ld(s, args, 2);
1303 afa05235 Aurelien Jarno
        break;
1304 afa05235 Aurelien Jarno
    case INDEX_op_qemu_ld64:
1305 afa05235 Aurelien Jarno
        tcg_out_qemu_ld(s, args, 3);
1306 afa05235 Aurelien Jarno
        break;
1307 afa05235 Aurelien Jarno
    case INDEX_op_qemu_st8:
1308 afa05235 Aurelien Jarno
        tcg_out_qemu_st(s, args, 0);
1309 afa05235 Aurelien Jarno
        break;
1310 afa05235 Aurelien Jarno
    case INDEX_op_qemu_st16:
1311 afa05235 Aurelien Jarno
        tcg_out_qemu_st(s, args, 1);
1312 afa05235 Aurelien Jarno
        break;
1313 afa05235 Aurelien Jarno
    case INDEX_op_qemu_st32:
1314 afa05235 Aurelien Jarno
        tcg_out_qemu_st(s, args, 2);
1315 afa05235 Aurelien Jarno
        break;
1316 afa05235 Aurelien Jarno
    case INDEX_op_qemu_st64:
1317 afa05235 Aurelien Jarno
        tcg_out_qemu_st(s, args, 3);
1318 afa05235 Aurelien Jarno
        break;
1319 afa05235 Aurelien Jarno
1320 afa05235 Aurelien Jarno
    default:
1321 afa05235 Aurelien Jarno
        tcg_abort();
1322 afa05235 Aurelien Jarno
    }
1323 afa05235 Aurelien Jarno
}
1324 afa05235 Aurelien Jarno
1325 afa05235 Aurelien Jarno
static const TCGTargetOpDef mips_op_defs[] = {
1326 afa05235 Aurelien Jarno
    { INDEX_op_exit_tb, { } },
1327 afa05235 Aurelien Jarno
    { INDEX_op_goto_tb, { } },
1328 afa05235 Aurelien Jarno
    { INDEX_op_call, { "C" } },
1329 afa05235 Aurelien Jarno
    { INDEX_op_jmp, { "r" } },
1330 afa05235 Aurelien Jarno
    { INDEX_op_br, { } },
1331 afa05235 Aurelien Jarno
1332 afa05235 Aurelien Jarno
    { INDEX_op_mov_i32, { "r", "r" } },
1333 afa05235 Aurelien Jarno
    { INDEX_op_movi_i32, { "r" } },
1334 afa05235 Aurelien Jarno
    { INDEX_op_ld8u_i32, { "r", "r" } },
1335 afa05235 Aurelien Jarno
    { INDEX_op_ld8s_i32, { "r", "r" } },
1336 afa05235 Aurelien Jarno
    { INDEX_op_ld16u_i32, { "r", "r" } },
1337 afa05235 Aurelien Jarno
    { INDEX_op_ld16s_i32, { "r", "r" } },
1338 afa05235 Aurelien Jarno
    { INDEX_op_ld_i32, { "r", "r" } },
1339 afa05235 Aurelien Jarno
    { INDEX_op_st8_i32, { "rZ", "r" } },
1340 afa05235 Aurelien Jarno
    { INDEX_op_st16_i32, { "rZ", "r" } },
1341 afa05235 Aurelien Jarno
    { INDEX_op_st_i32, { "rZ", "r" } },
1342 afa05235 Aurelien Jarno
1343 afa05235 Aurelien Jarno
    { INDEX_op_add_i32, { "r", "rZ", "rJZ" } },
1344 afa05235 Aurelien Jarno
    { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
1345 afa05235 Aurelien Jarno
    { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
1346 afa05235 Aurelien Jarno
    { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
1347 afa05235 Aurelien Jarno
    { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
1348 afa05235 Aurelien Jarno
    { INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
1349 afa05235 Aurelien Jarno
    { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
1350 afa05235 Aurelien Jarno
    { INDEX_op_sub_i32, { "r", "rZ", "rJZ" } },
1351 afa05235 Aurelien Jarno
1352 afa05235 Aurelien Jarno
    { INDEX_op_and_i32, { "r", "rZ", "rIZ" } },
1353 afa05235 Aurelien Jarno
    { INDEX_op_not_i32, { "r", "rZ" } },
1354 afa05235 Aurelien Jarno
    { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
1355 afa05235 Aurelien Jarno
    { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
1356 afa05235 Aurelien Jarno
1357 afa05235 Aurelien Jarno
    { INDEX_op_shl_i32, { "r", "rZ", "riZ" } },
1358 afa05235 Aurelien Jarno
    { INDEX_op_shr_i32, { "r", "rZ", "riZ" } },
1359 afa05235 Aurelien Jarno
    { INDEX_op_sar_i32, { "r", "rZ", "riZ" } },
1360 afa05235 Aurelien Jarno
1361 afa05235 Aurelien Jarno
    { INDEX_op_brcond_i32, { "rZ", "rZ" } },
1362 4cb26382 Aurelien Jarno
    { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
1363 434254aa Aurelien Jarno
    { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
1364 afa05235 Aurelien Jarno
1365 afa05235 Aurelien Jarno
    { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1366 afa05235 Aurelien Jarno
    { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1367 afa05235 Aurelien Jarno
    { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
1368 afa05235 Aurelien Jarno
1369 afa05235 Aurelien Jarno
#if TARGET_LONG_BITS == 32
1370 afa05235 Aurelien Jarno
    { INDEX_op_qemu_ld8u, { "L", "lZ" } },
1371 afa05235 Aurelien Jarno
    { INDEX_op_qemu_ld8s, { "L", "lZ" } },
1372 afa05235 Aurelien Jarno
    { INDEX_op_qemu_ld16u, { "L", "lZ" } },
1373 afa05235 Aurelien Jarno
    { INDEX_op_qemu_ld16s, { "L", "lZ" } },
1374 afa05235 Aurelien Jarno
    { INDEX_op_qemu_ld32u, { "L", "lZ" } },
1375 afa05235 Aurelien Jarno
    { INDEX_op_qemu_ld64, { "L", "L", "lZ" } },
1376 afa05235 Aurelien Jarno
1377 afa05235 Aurelien Jarno
    { INDEX_op_qemu_st8, { "SZ", "SZ" } },
1378 afa05235 Aurelien Jarno
    { INDEX_op_qemu_st16, { "SZ", "SZ" } },
1379 afa05235 Aurelien Jarno
    { INDEX_op_qemu_st32, { "SZ", "SZ" } },
1380 afa05235 Aurelien Jarno
    { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ" } },
1381 afa05235 Aurelien Jarno
#else
1382 afa05235 Aurelien Jarno
    { INDEX_op_qemu_ld8u, { "L", "lZ", "lZ" } },
1383 afa05235 Aurelien Jarno
    { INDEX_op_qemu_ld8s, { "L", "lZ", "lZ" } },
1384 afa05235 Aurelien Jarno
    { INDEX_op_qemu_ld16u, { "L", "lZ", "lZ" } },
1385 afa05235 Aurelien Jarno
    { INDEX_op_qemu_ld16s, { "L", "lZ", "lZ" } },
1386 afa05235 Aurelien Jarno
    { INDEX_op_qemu_ld32u, { "L", "lZ", "lZ" } },
1387 afa05235 Aurelien Jarno
    { INDEX_op_qemu_ld64, { "L", "L", "lZ", "lZ" } },
1388 afa05235 Aurelien Jarno
1389 afa05235 Aurelien Jarno
    { INDEX_op_qemu_st8, { "SZ", "SZ", "SZ" } },
1390 afa05235 Aurelien Jarno
    { INDEX_op_qemu_st16, { "SZ", "SZ", "SZ" } },
1391 afa05235 Aurelien Jarno
    { INDEX_op_qemu_st32, { "SZ", "SZ", "SZ" } },
1392 afa05235 Aurelien Jarno
    { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ", "SZ" } },
1393 afa05235 Aurelien Jarno
#endif
1394 afa05235 Aurelien Jarno
    { -1 },
1395 afa05235 Aurelien Jarno
};
1396 afa05235 Aurelien Jarno
1397 afa05235 Aurelien Jarno
static int tcg_target_callee_save_regs[] = {
1398 afa05235 Aurelien Jarno
    TCG_REG_S0,
1399 afa05235 Aurelien Jarno
    TCG_REG_S1,
1400 afa05235 Aurelien Jarno
    TCG_REG_S2,
1401 afa05235 Aurelien Jarno
    TCG_REG_S3,
1402 afa05235 Aurelien Jarno
    TCG_REG_S4,
1403 afa05235 Aurelien Jarno
    TCG_REG_S5,
1404 afa05235 Aurelien Jarno
    TCG_REG_S6,
1405 afa05235 Aurelien Jarno
    TCG_REG_S7,
1406 afa05235 Aurelien Jarno
    TCG_REG_GP,
1407 afa05235 Aurelien Jarno
    /* TCG_REG_FP, */ /* currently used for the global env, so np
1408 afa05235 Aurelien Jarno
                         need to save */
1409 afa05235 Aurelien Jarno
    TCG_REG_RA,       /* should be last for ABI compliance */
1410 afa05235 Aurelien Jarno
};
1411 afa05235 Aurelien Jarno
1412 afa05235 Aurelien Jarno
/* Generate global QEMU prologue and epilogue code */
1413 afa05235 Aurelien Jarno
void tcg_target_qemu_prologue(TCGContext *s)
1414 afa05235 Aurelien Jarno
{
1415 afa05235 Aurelien Jarno
    int i, frame_size;
1416 afa05235 Aurelien Jarno
1417 afa05235 Aurelien Jarno
    /* reserve some stack space */
1418 afa05235 Aurelien Jarno
    frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1419 afa05235 Aurelien Jarno
                 + TCG_STATIC_CALL_ARGS_SIZE;
1420 afa05235 Aurelien Jarno
    frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1421 afa05235 Aurelien Jarno
                 ~(TCG_TARGET_STACK_ALIGN - 1);
1422 afa05235 Aurelien Jarno
1423 afa05235 Aurelien Jarno
    /* TB prologue */
1424 afa05235 Aurelien Jarno
    tcg_out_addi(s, TCG_REG_SP, -frame_size);
1425 afa05235 Aurelien Jarno
    for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1426 afa05235 Aurelien Jarno
        tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1427 afa05235 Aurelien Jarno
                   TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1428 afa05235 Aurelien Jarno
    }
1429 afa05235 Aurelien Jarno
1430 afa05235 Aurelien Jarno
    /* Call generated code */
1431 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_A0, 0);
1432 afa05235 Aurelien Jarno
    tcg_out_nop(s);
1433 afa05235 Aurelien Jarno
    tb_ret_addr = s->code_ptr;
1434 afa05235 Aurelien Jarno
1435 afa05235 Aurelien Jarno
    /* TB epilogue */
1436 afa05235 Aurelien Jarno
    for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1437 afa05235 Aurelien Jarno
        tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1438 afa05235 Aurelien Jarno
                   TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1439 afa05235 Aurelien Jarno
    }
1440 afa05235 Aurelien Jarno
1441 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
1442 afa05235 Aurelien Jarno
    tcg_out_addi(s, TCG_REG_SP, frame_size);
1443 afa05235 Aurelien Jarno
}
1444 afa05235 Aurelien Jarno
1445 afa05235 Aurelien Jarno
void tcg_target_init(TCGContext *s)
1446 afa05235 Aurelien Jarno
{
1447 afa05235 Aurelien Jarno
    tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
1448 afa05235 Aurelien Jarno
    tcg_regset_set(tcg_target_call_clobber_regs,
1449 afa05235 Aurelien Jarno
                   (1 << TCG_REG_V0) |
1450 afa05235 Aurelien Jarno
                   (1 << TCG_REG_V1) |
1451 afa05235 Aurelien Jarno
                   (1 << TCG_REG_A0) |
1452 afa05235 Aurelien Jarno
                   (1 << TCG_REG_A1) |
1453 afa05235 Aurelien Jarno
                   (1 << TCG_REG_A2) |
1454 afa05235 Aurelien Jarno
                   (1 << TCG_REG_A3) |
1455 afa05235 Aurelien Jarno
                   (1 << TCG_REG_T1) |
1456 afa05235 Aurelien Jarno
                   (1 << TCG_REG_T2) |
1457 afa05235 Aurelien Jarno
                   (1 << TCG_REG_T3) |
1458 afa05235 Aurelien Jarno
                   (1 << TCG_REG_T4) |
1459 afa05235 Aurelien Jarno
                   (1 << TCG_REG_T5) |
1460 afa05235 Aurelien Jarno
                   (1 << TCG_REG_T6) |
1461 afa05235 Aurelien Jarno
                   (1 << TCG_REG_T7) |
1462 afa05235 Aurelien Jarno
                   (1 << TCG_REG_T8) |
1463 afa05235 Aurelien Jarno
                   (1 << TCG_REG_T9));
1464 afa05235 Aurelien Jarno
1465 afa05235 Aurelien Jarno
    tcg_regset_clear(s->reserved_regs);
1466 afa05235 Aurelien Jarno
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
1467 afa05235 Aurelien Jarno
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0);   /* kernel use only */
1468 afa05235 Aurelien Jarno
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1);   /* kernel use only */
1469 afa05235 Aurelien Jarno
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_AT);   /* internal use */
1470 afa05235 Aurelien Jarno
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_T0);   /* internal use */
1471 afa05235 Aurelien Jarno
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA);   /* return address */
1472 afa05235 Aurelien Jarno
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);   /* stack pointer */
1473 afa05235 Aurelien Jarno
1474 afa05235 Aurelien Jarno
    tcg_add_target_add_op_defs(mips_op_defs);
1475 afa05235 Aurelien Jarno
}