]> git.ipfire.org Git - thirdparty/qemu.git/blame - tcg/mips/tcg-target.c
tcg: Change memory offsets to intptr_t
[thirdparty/qemu.git] / tcg / mips / tcg-target.c
CommitLineData
afa05235
AJ
1/*
2 * Tiny Code Generator for QEMU
3 *
4 * Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org>
5 * Copyright (c) 2009 Aurelien Jarno <aurelien@aurel32.net>
6 * Based on i386/tcg-target.c - Copyright (c) 2008 Fabrice Bellard
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 */
26
27#if defined(TCG_TARGET_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
28# define TCG_NEED_BSWAP 0
29#else
30# define TCG_NEED_BSWAP 1
31#endif
32
33#ifndef NDEBUG
34static 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 */
5a0eed37 71static const TCGReg tcg_target_reg_alloc_order[] = {
afa05235
AJ
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
5a0eed37 97static const TCGReg tcg_target_call_iarg_regs[4] = {
afa05235
AJ
98 TCG_REG_A0,
99 TCG_REG_A1,
100 TCG_REG_A2,
101 TCG_REG_A3
102};
103
5a0eed37 104static const TCGReg tcg_target_call_oarg_regs[2] = {
afa05235
AJ
105 TCG_REG_V0,
106 TCG_REG_V1
107};
108
109static uint8_t *tb_ret_addr;
110
111static inline uint32_t reloc_lo16_val (void *pc, tcg_target_long target)
112{
113 return target & 0xffff;
114}
115
116static 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
122static inline uint32_t reloc_hi16_val (void *pc, tcg_target_long target)
123{
124 return (target >> 16) & 0xffff;
125}
126
127static 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
133static 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
145static 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
151static 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
160static 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
166static 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
afa05235
AJ
188/* parse target specific constraints */
189static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
190{
191 const char *ct_str;
192
193 ct_str = *pct_str;
194 switch(ct_str[0]) {
195 case 'r':
196 ct->ct |= TCG_CT_REG;
197 tcg_regset_set(ct->u.regs, 0xffffffff);
198 break;
199 case 'C':
200 ct->ct |= TCG_CT_REG;
201 tcg_regset_clear(ct->u.regs);
202 tcg_regset_set_reg(ct->u.regs, TCG_REG_T9);
203 break;
204 case 'L': /* qemu_ld output arg constraint */
205 ct->ct |= TCG_CT_REG;
206 tcg_regset_set(ct->u.regs, 0xffffffff);
207 tcg_regset_reset_reg(ct->u.regs, TCG_REG_V0);
208 break;
209 case 'l': /* qemu_ld input arg constraint */
210 ct->ct |= TCG_CT_REG;
211 tcg_regset_set(ct->u.regs, 0xffffffff);
212#if defined(CONFIG_SOFTMMU)
213 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
89c33337 214# if (TARGET_LONG_BITS == 64)
18fec301
AJ
215 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
216# endif
afa05235
AJ
217#endif
218 break;
219 case 'S': /* qemu_st constraint */
220 ct->ct |= TCG_CT_REG;
221 tcg_regset_set(ct->u.regs, 0xffffffff);
afa05235 222 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
cc01cc8e 223#if defined(CONFIG_SOFTMMU)
89c33337 224# if (TARGET_LONG_BITS == 32)
afa05235
AJ
225 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1);
226# endif
227 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
89c33337 228# if TARGET_LONG_BITS == 64
18fec301
AJ
229 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A3);
230# endif
afa05235
AJ
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 */
254static 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 */
272enum {
afa05235
AJ
273 OPC_BEQ = 0x04 << 26,
274 OPC_BNE = 0x05 << 26,
0f46c064
AJ
275 OPC_BLEZ = 0x06 << 26,
276 OPC_BGTZ = 0x07 << 26,
afa05235 277 OPC_ADDIU = 0x09 << 26,
4cb26382
AJ
278 OPC_SLTI = 0x0A << 26,
279 OPC_SLTIU = 0x0B << 26,
afa05235
AJ
280 OPC_ANDI = 0x0C << 26,
281 OPC_ORI = 0x0D << 26,
282 OPC_XORI = 0x0E << 26,
283 OPC_LUI = 0x0F << 26,
284 OPC_LB = 0x20 << 26,
285 OPC_LH = 0x21 << 26,
286 OPC_LW = 0x23 << 26,
287 OPC_LBU = 0x24 << 26,
288 OPC_LHU = 0x25 << 26,
289 OPC_LWU = 0x27 << 26,
290 OPC_SB = 0x28 << 26,
291 OPC_SH = 0x29 << 26,
292 OPC_SW = 0x2B << 26,
116348de
AJ
293
294 OPC_SPECIAL = 0x00 << 26,
afa05235
AJ
295 OPC_SLL = OPC_SPECIAL | 0x00,
296 OPC_SRL = OPC_SPECIAL | 0x02,
9a152519 297 OPC_ROTR = OPC_SPECIAL | (0x01 << 21) | 0x02,
afa05235
AJ
298 OPC_SRA = OPC_SPECIAL | 0x03,
299 OPC_SLLV = OPC_SPECIAL | 0x04,
300 OPC_SRLV = OPC_SPECIAL | 0x06,
9a152519 301 OPC_ROTRV = OPC_SPECIAL | (0x01 << 6) | 0x06,
afa05235
AJ
302 OPC_SRAV = OPC_SPECIAL | 0x07,
303 OPC_JR = OPC_SPECIAL | 0x08,
304 OPC_JALR = OPC_SPECIAL | 0x09,
7d7c4930
AJ
305 OPC_MOVZ = OPC_SPECIAL | 0x0A,
306 OPC_MOVN = OPC_SPECIAL | 0x0B,
afa05235
AJ
307 OPC_MFHI = OPC_SPECIAL | 0x10,
308 OPC_MFLO = OPC_SPECIAL | 0x12,
309 OPC_MULT = OPC_SPECIAL | 0x18,
310 OPC_MULTU = OPC_SPECIAL | 0x19,
311 OPC_DIV = OPC_SPECIAL | 0x1A,
312 OPC_DIVU = OPC_SPECIAL | 0x1B,
313 OPC_ADDU = OPC_SPECIAL | 0x21,
314 OPC_SUBU = OPC_SPECIAL | 0x23,
315 OPC_AND = OPC_SPECIAL | 0x24,
316 OPC_OR = OPC_SPECIAL | 0x25,
317 OPC_XOR = OPC_SPECIAL | 0x26,
318 OPC_NOR = OPC_SPECIAL | 0x27,
319 OPC_SLT = OPC_SPECIAL | 0x2A,
320 OPC_SLTU = OPC_SPECIAL | 0x2B,
116348de 321
0f46c064
AJ
322 OPC_REGIMM = 0x01 << 26,
323 OPC_BLTZ = OPC_REGIMM | (0x00 << 16),
324 OPC_BGEZ = OPC_REGIMM | (0x01 << 16),
325
3585317f
AJ
326 OPC_SPECIAL2 = 0x1c << 26,
327 OPC_MUL = OPC_SPECIAL2 | 0x002,
328
116348de 329 OPC_SPECIAL3 = 0x1f << 26,
04f71aa3 330 OPC_INS = OPC_SPECIAL3 | 0x004,
c1cf85c9 331 OPC_WSBH = OPC_SPECIAL3 | 0x0a0,
116348de
AJ
332 OPC_SEB = OPC_SPECIAL3 | 0x420,
333 OPC_SEH = OPC_SPECIAL3 | 0x620,
afa05235
AJ
334};
335
336/*
337 * Type reg
338 */
5a0eed37
AJ
339static inline void tcg_out_opc_reg(TCGContext *s, int opc,
340 TCGReg rd, TCGReg rs, TCGReg rt)
afa05235
AJ
341{
342 int32_t inst;
343
344 inst = opc;
345 inst |= (rs & 0x1F) << 21;
346 inst |= (rt & 0x1F) << 16;
347 inst |= (rd & 0x1F) << 11;
348 tcg_out32(s, inst);
349}
350
351/*
352 * Type immediate
353 */
5a0eed37
AJ
354static inline void tcg_out_opc_imm(TCGContext *s, int opc,
355 TCGReg rt, TCGReg rs, TCGArg imm)
afa05235
AJ
356{
357 int32_t inst;
358
359 inst = opc;
360 inst |= (rs & 0x1F) << 21;
361 inst |= (rt & 0x1F) << 16;
362 inst |= (imm & 0xffff);
363 tcg_out32(s, inst);
364}
365
6d8ff4d8
AJ
366/*
367 * Type branch
368 */
5a0eed37
AJ
369static inline void tcg_out_opc_br(TCGContext *s, int opc,
370 TCGReg rt, TCGReg rs)
6d8ff4d8 371{
56779034
AJ
372 /* We pay attention here to not modify the branch target by reading
373 the existing value and using it again. This ensure that caches and
374 memory are kept coherent during retranslation. */
d43ffce1 375 uint16_t offset = (uint16_t)(*(uint32_t *) s->code_ptr);
6d8ff4d8
AJ
376
377 tcg_out_opc_imm(s, opc, rt, rs, offset);
378}
379
afa05235
AJ
380/*
381 * Type sa
382 */
5a0eed37
AJ
383static inline void tcg_out_opc_sa(TCGContext *s, int opc,
384 TCGReg rd, TCGReg rt, TCGArg sa)
afa05235
AJ
385{
386 int32_t inst;
387
388 inst = opc;
389 inst |= (rt & 0x1F) << 16;
390 inst |= (rd & 0x1F) << 11;
391 inst |= (sa & 0x1F) << 6;
392 tcg_out32(s, inst);
393
394}
395
396static inline void tcg_out_nop(TCGContext *s)
397{
398 tcg_out32(s, 0);
399}
400
2a534aff
RH
401static inline void tcg_out_mov(TCGContext *s, TCGType type,
402 TCGReg ret, TCGReg arg)
afa05235 403{
18fec301
AJ
404 /* Simple reg-reg move, optimising out the 'do nothing' case */
405 if (ret != arg) {
406 tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
407 }
afa05235
AJ
408}
409
410static inline void tcg_out_movi(TCGContext *s, TCGType type,
2a534aff 411 TCGReg reg, tcg_target_long arg)
afa05235
AJ
412{
413 if (arg == (int16_t)arg) {
414 tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
415 } else if (arg == (uint16_t)arg) {
416 tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
417 } else {
418 tcg_out_opc_imm(s, OPC_LUI, reg, 0, arg >> 16);
419 tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0xffff);
420 }
421}
422
5a0eed37 423static inline void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg)
afa05235 424{
8f06bf69 425#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
c1cf85c9
AJ
426 tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
427#else
afa05235
AJ
428 /* ret and arg can't be register at */
429 if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
430 tcg_abort();
431 }
432
433 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
afa05235
AJ
434 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
435 tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
436 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
c1cf85c9 437#endif
afa05235
AJ
438}
439
5a0eed37 440static inline void tcg_out_bswap16s(TCGContext *s, TCGReg ret, TCGReg arg)
afa05235 441{
8f06bf69 442#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
c1cf85c9
AJ
443 tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
444 tcg_out_opc_reg(s, OPC_SEH, ret, 0, ret);
445#else
afa05235
AJ
446 /* ret and arg can't be register at */
447 if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
448 tcg_abort();
449 }
450
451 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
afa05235
AJ
452 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
453 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
454 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
c1cf85c9 455#endif
afa05235
AJ
456}
457
5a0eed37 458static inline void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg)
afa05235 459{
8f06bf69 460#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
c1cf85c9
AJ
461 tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
462 tcg_out_opc_sa(s, OPC_ROTR, ret, ret, 16);
463#else
afa05235
AJ
464 /* ret and arg must be different and can't be register at */
465 if (ret == arg || ret == TCG_REG_AT || arg == TCG_REG_AT) {
466 tcg_abort();
467 }
468
469 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
470
471 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 24);
472 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
473
474 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, arg, 0xff00);
475 tcg_out_opc_sa(s, OPC_SLL, TCG_REG_AT, TCG_REG_AT, 8);
476 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
477
478 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
479 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff00);
480 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
c1cf85c9 481#endif
afa05235
AJ
482}
483
5a0eed37 484static inline void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg)
116348de 485{
8f06bf69 486#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
116348de
AJ
487 tcg_out_opc_reg(s, OPC_SEB, ret, 0, arg);
488#else
489 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
490 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 24);
491#endif
492}
493
5a0eed37 494static inline void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg)
116348de 495{
8f06bf69 496#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
116348de
AJ
497 tcg_out_opc_reg(s, OPC_SEH, ret, 0, arg);
498#else
499 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 16);
500 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
501#endif
502}
503
5a0eed37
AJ
504static inline void tcg_out_ldst(TCGContext *s, int opc, TCGArg arg,
505 TCGReg arg1, TCGArg arg2)
afa05235
AJ
506{
507 if (arg2 == (int16_t) arg2) {
508 tcg_out_opc_imm(s, opc, arg, arg1, arg2);
509 } else {
510 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, arg2);
511 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, TCG_REG_AT, arg1);
512 tcg_out_opc_imm(s, opc, arg, TCG_REG_AT, 0);
513 }
514}
515
2a534aff
RH
516static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
517 TCGReg arg1, tcg_target_long arg2)
afa05235
AJ
518{
519 tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
520}
521
2a534aff
RH
522static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
523 TCGReg arg1, tcg_target_long arg2)
afa05235
AJ
524{
525 tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
526}
527
5a0eed37 528static inline void tcg_out_addi(TCGContext *s, TCGReg reg, TCGArg val)
afa05235
AJ
529{
530 if (val == (int16_t)val) {
531 tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
532 } else {
533 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, val);
534 tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_REG_AT);
535 }
536}
537
18fec301
AJ
538/* Helper routines for marshalling helper function arguments into
539 * the correct registers and stack.
540 * arg_num is where we want to put this argument, and is updated to be ready
541 * for the next call. arg is the argument itself. Note that arg_num 0..3 is
542 * real registers, 4+ on stack.
543 *
544 * We provide routines for arguments which are: immediate, 32 bit
545 * value in register, 16 and 8 bit values in register (which must be zero
546 * extended before use) and 64 bit value in a lo:hi register pair.
547 */
548#define DEFINE_TCG_OUT_CALL_IARG(NAME, ARGPARAM) \
549 static inline void NAME(TCGContext *s, int *arg_num, ARGPARAM) \
550 { \
551 if (*arg_num < 4) { \
552 DEFINE_TCG_OUT_CALL_IARG_GET_ARG(tcg_target_call_iarg_regs[*arg_num]); \
553 } else { \
554 DEFINE_TCG_OUT_CALL_IARG_GET_ARG(TCG_REG_AT); \
555 tcg_out_st(s, TCG_TYPE_I32, TCG_REG_AT, TCG_REG_SP, 4 * (*arg_num)); \
556 } \
557 (*arg_num)++; \
558}
559#define DEFINE_TCG_OUT_CALL_IARG_GET_ARG(A) \
560 tcg_out_opc_imm(s, OPC_ANDI, A, arg, 0xff);
561DEFINE_TCG_OUT_CALL_IARG(tcg_out_call_iarg_reg8, TCGReg arg)
562#undef DEFINE_TCG_OUT_CALL_IARG_GET_ARG
563#define DEFINE_TCG_OUT_CALL_IARG_GET_ARG(A) \
564 tcg_out_opc_imm(s, OPC_ANDI, A, arg, 0xffff);
565DEFINE_TCG_OUT_CALL_IARG(tcg_out_call_iarg_reg16, TCGReg arg)
566#undef DEFINE_TCG_OUT_CALL_IARG_GET_ARG
567#define DEFINE_TCG_OUT_CALL_IARG_GET_ARG(A) \
568 tcg_out_movi(s, TCG_TYPE_I32, A, arg);
5a0eed37 569DEFINE_TCG_OUT_CALL_IARG(tcg_out_call_iarg_imm32, TCGArg arg)
18fec301
AJ
570#undef DEFINE_TCG_OUT_CALL_IARG_GET_ARG
571
572/* We don't use the macro for this one to avoid an unnecessary reg-reg
573 move when storing to the stack. */
574static inline void tcg_out_call_iarg_reg32(TCGContext *s, int *arg_num,
575 TCGReg arg)
576{
577 if (*arg_num < 4) {
578 tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[*arg_num], arg);
579 } else {
580 tcg_out_st(s, TCG_TYPE_I32, arg, TCG_REG_SP, 4 * (*arg_num));
581 }
582 (*arg_num)++;
583}
584
585static inline void tcg_out_call_iarg_reg64(TCGContext *s, int *arg_num,
586 TCGReg arg_low, TCGReg arg_high)
587{
588 (*arg_num) = (*arg_num + 1) & ~1;
589
590#if defined(TCG_TARGET_WORDS_BIGENDIAN)
591 tcg_out_call_iarg_reg32(s, arg_num, arg_high);
592 tcg_out_call_iarg_reg32(s, arg_num, arg_low);
593#else
594 tcg_out_call_iarg_reg32(s, arg_num, arg_low);
595 tcg_out_call_iarg_reg32(s, arg_num, arg_high);
596#endif
597}
598
5a0eed37
AJ
599static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGArg arg1,
600 TCGArg arg2, int label_index)
afa05235
AJ
601{
602 TCGLabel *l = &s->labels[label_index];
603
604 switch (cond) {
605 case TCG_COND_EQ:
6d8ff4d8 606 tcg_out_opc_br(s, OPC_BEQ, arg1, arg2);
afa05235
AJ
607 break;
608 case TCG_COND_NE:
6d8ff4d8 609 tcg_out_opc_br(s, OPC_BNE, arg1, arg2);
afa05235
AJ
610 break;
611 case TCG_COND_LT:
0f46c064
AJ
612 if (arg2 == 0) {
613 tcg_out_opc_br(s, OPC_BLTZ, 0, arg1);
614 } else {
615 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
616 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
617 }
afa05235
AJ
618 break;
619 case TCG_COND_LTU:
620 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
6d8ff4d8 621 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
afa05235
AJ
622 break;
623 case TCG_COND_GE:
0f46c064
AJ
624 if (arg2 == 0) {
625 tcg_out_opc_br(s, OPC_BGEZ, 0, arg1);
626 } else {
627 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
628 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
629 }
afa05235
AJ
630 break;
631 case TCG_COND_GEU:
632 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
6d8ff4d8 633 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
afa05235
AJ
634 break;
635 case TCG_COND_LE:
0f46c064
AJ
636 if (arg2 == 0) {
637 tcg_out_opc_br(s, OPC_BLEZ, 0, arg1);
638 } else {
639 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
640 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
641 }
afa05235
AJ
642 break;
643 case TCG_COND_LEU:
644 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
6d8ff4d8 645 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
afa05235
AJ
646 break;
647 case TCG_COND_GT:
0f46c064
AJ
648 if (arg2 == 0) {
649 tcg_out_opc_br(s, OPC_BGTZ, 0, arg1);
650 } else {
651 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
652 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
653 }
afa05235
AJ
654 break;
655 case TCG_COND_GTU:
656 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
6d8ff4d8 657 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
afa05235
AJ
658 break;
659 default:
660 tcg_abort();
661 break;
662 }
663 if (l->has_value) {
664 reloc_pc16(s->code_ptr - 4, l->u.value);
665 } else {
666 tcg_out_reloc(s, s->code_ptr - 4, R_MIPS_PC16, label_index, 0);
667 }
668 tcg_out_nop(s);
669}
670
671/* XXX: we implement it at the target level to avoid having to
672 handle cross basic blocks temporaries */
5a0eed37
AJ
673static void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGArg arg1,
674 TCGArg arg2, TCGArg arg3, TCGArg arg4,
675 int label_index)
afa05235
AJ
676{
677 void *label_ptr;
678
679 switch(cond) {
680 case TCG_COND_NE:
681 tcg_out_brcond(s, TCG_COND_NE, arg2, arg4, label_index);
682 tcg_out_brcond(s, TCG_COND_NE, arg1, arg3, label_index);
683 return;
684 case TCG_COND_EQ:
685 break;
686 case TCG_COND_LT:
687 case TCG_COND_LE:
688 tcg_out_brcond(s, TCG_COND_LT, arg2, arg4, label_index);
689 break;
690 case TCG_COND_GT:
691 case TCG_COND_GE:
692 tcg_out_brcond(s, TCG_COND_GT, arg2, arg4, label_index);
693 break;
694 case TCG_COND_LTU:
695 case TCG_COND_LEU:
696 tcg_out_brcond(s, TCG_COND_LTU, arg2, arg4, label_index);
697 break;
698 case TCG_COND_GTU:
699 case TCG_COND_GEU:
700 tcg_out_brcond(s, TCG_COND_GTU, arg2, arg4, label_index);
701 break;
702 default:
703 tcg_abort();
704 }
705
706 label_ptr = s->code_ptr;
6d8ff4d8 707 tcg_out_opc_br(s, OPC_BNE, arg2, arg4);
afa05235
AJ
708 tcg_out_nop(s);
709
710 switch(cond) {
711 case TCG_COND_EQ:
712 tcg_out_brcond(s, TCG_COND_EQ, arg1, arg3, label_index);
713 break;
714 case TCG_COND_LT:
715 case TCG_COND_LTU:
716 tcg_out_brcond(s, TCG_COND_LTU, arg1, arg3, label_index);
717 break;
718 case TCG_COND_LE:
719 case TCG_COND_LEU:
720 tcg_out_brcond(s, TCG_COND_LEU, arg1, arg3, label_index);
721 break;
722 case TCG_COND_GT:
723 case TCG_COND_GTU:
724 tcg_out_brcond(s, TCG_COND_GTU, arg1, arg3, label_index);
725 break;
726 case TCG_COND_GE:
727 case TCG_COND_GEU:
728 tcg_out_brcond(s, TCG_COND_GEU, arg1, arg3, label_index);
729 break;
730 default:
731 tcg_abort();
732 }
733
734 reloc_pc16(label_ptr, (tcg_target_long) s->code_ptr);
735}
736
7d7c4930
AJ
737static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
738 TCGArg c1, TCGArg c2, TCGArg v)
739{
740 switch (cond) {
741 case TCG_COND_EQ:
742 if (c1 == 0) {
743 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, c2);
744 } else if (c2 == 0) {
745 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, c1);
746 } else {
747 tcg_out_opc_reg(s, OPC_XOR, TCG_REG_AT, c1, c2);
748 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_REG_AT);
749 }
750 break;
751 case TCG_COND_NE:
752 if (c1 == 0) {
753 tcg_out_opc_reg(s, OPC_MOVN, ret, v, c2);
754 } else if (c2 == 0) {
755 tcg_out_opc_reg(s, OPC_MOVN, ret, v, c1);
756 } else {
757 tcg_out_opc_reg(s, OPC_XOR, TCG_REG_AT, c1, c2);
758 tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_REG_AT);
759 }
760 break;
761 case TCG_COND_LT:
762 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, c1, c2);
763 tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_REG_AT);
764 break;
765 case TCG_COND_LTU:
766 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, c1, c2);
767 tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_REG_AT);
768 break;
769 case TCG_COND_GE:
770 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, c1, c2);
771 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_REG_AT);
772 break;
773 case TCG_COND_GEU:
774 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, c1, c2);
775 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_REG_AT);
776 break;
777 case TCG_COND_LE:
778 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, c2, c1);
779 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_REG_AT);
780 break;
781 case TCG_COND_LEU:
782 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, c2, c1);
783 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_REG_AT);
784 break;
785 case TCG_COND_GT:
786 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, c2, c1);
787 tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_REG_AT);
788 break;
789 case TCG_COND_GTU:
790 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, c2, c1);
791 tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_REG_AT);
792 break;
793 default:
794 tcg_abort();
795 break;
796 }
797}
798
5a0eed37
AJ
799static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
800 TCGArg arg1, TCGArg arg2)
4cb26382
AJ
801{
802 switch (cond) {
803 case TCG_COND_EQ:
804 if (arg1 == 0) {
805 tcg_out_opc_imm(s, OPC_SLTIU, ret, arg2, 1);
806 } else if (arg2 == 0) {
807 tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, 1);
808 } else {
434254aa
AJ
809 tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
810 tcg_out_opc_imm(s, OPC_SLTIU, ret, ret, 1);
4cb26382
AJ
811 }
812 break;
813 case TCG_COND_NE:
814 if (arg1 == 0) {
815 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg2);
816 } else if (arg2 == 0) {
817 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg1);
818 } else {
434254aa
AJ
819 tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
820 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, ret);
4cb26382
AJ
821 }
822 break;
823 case TCG_COND_LT:
824 tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
825 break;
826 case TCG_COND_LTU:
827 tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
828 break;
829 case TCG_COND_GE:
434254aa
AJ
830 tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
831 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
4cb26382
AJ
832 break;
833 case TCG_COND_GEU:
434254aa
AJ
834 tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
835 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
4cb26382
AJ
836 break;
837 case TCG_COND_LE:
434254aa
AJ
838 tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
839 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
4cb26382
AJ
840 break;
841 case TCG_COND_LEU:
434254aa
AJ
842 tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
843 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
4cb26382
AJ
844 break;
845 case TCG_COND_GT:
846 tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
847 break;
848 case TCG_COND_GTU:
849 tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
850 break;
851 default:
852 tcg_abort();
853 break;
854 }
855}
856
434254aa
AJ
857/* XXX: we implement it at the target level to avoid having to
858 handle cross basic blocks temporaries */
5a0eed37
AJ
859static void tcg_out_setcond2(TCGContext *s, TCGCond cond, TCGReg ret,
860 TCGArg arg1, TCGArg arg2, TCGArg arg3, TCGArg arg4)
434254aa
AJ
861{
862 switch (cond) {
863 case TCG_COND_EQ:
864 tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_AT, arg2, arg4);
865 tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg1, arg3);
866 tcg_out_opc_reg(s, OPC_AND, ret, TCG_REG_AT, TCG_REG_T0);
867 return;
868 case TCG_COND_NE:
869 tcg_out_setcond(s, TCG_COND_NE, TCG_REG_AT, arg2, arg4);
870 tcg_out_setcond(s, TCG_COND_NE, TCG_REG_T0, arg1, arg3);
871 tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_AT, TCG_REG_T0);
872 return;
873 case TCG_COND_LT:
874 case TCG_COND_LE:
875 tcg_out_setcond(s, TCG_COND_LT, TCG_REG_AT, arg2, arg4);
876 break;
877 case TCG_COND_GT:
878 case TCG_COND_GE:
879 tcg_out_setcond(s, TCG_COND_GT, TCG_REG_AT, arg2, arg4);
880 break;
881 case TCG_COND_LTU:
882 case TCG_COND_LEU:
883 tcg_out_setcond(s, TCG_COND_LTU, TCG_REG_AT, arg2, arg4);
884 break;
885 case TCG_COND_GTU:
886 case TCG_COND_GEU:
887 tcg_out_setcond(s, TCG_COND_GTU, TCG_REG_AT, arg2, arg4);
888 break;
889 default:
890 tcg_abort();
891 break;
892 }
893
894 tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg2, arg4);
895
896 switch(cond) {
897 case TCG_COND_LT:
898 case TCG_COND_LTU:
899 tcg_out_setcond(s, TCG_COND_LTU, ret, arg1, arg3);
900 break;
901 case TCG_COND_LE:
902 case TCG_COND_LEU:
903 tcg_out_setcond(s, TCG_COND_LEU, ret, arg1, arg3);
904 break;
905 case TCG_COND_GT:
906 case TCG_COND_GTU:
907 tcg_out_setcond(s, TCG_COND_GTU, ret, arg1, arg3);
908 break;
909 case TCG_COND_GE:
910 case TCG_COND_GEU:
911 tcg_out_setcond(s, TCG_COND_GEU, ret, arg1, arg3);
912 break;
913 default:
914 tcg_abort();
915 }
916
917 tcg_out_opc_reg(s, OPC_AND, ret, ret, TCG_REG_T0);
918 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
919}
920
afa05235
AJ
921#if defined(CONFIG_SOFTMMU)
922
022c62cb 923#include "exec/softmmu_defs.h"
afa05235 924
e141ab52
BS
925/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
926 int mmu_idx) */
927static const void * const qemu_ld_helpers[4] = {
928 helper_ldb_mmu,
929 helper_ldw_mmu,
930 helper_ldl_mmu,
931 helper_ldq_mmu,
932};
933
934/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
935 uintxx_t val, int mmu_idx) */
936static const void * const qemu_st_helpers[4] = {
937 helper_stb_mmu,
938 helper_stw_mmu,
939 helper_stl_mmu,
940 helper_stq_mmu,
941};
e141ab52 942#endif
afa05235
AJ
943
944static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
945 int opc)
946{
5a0eed37 947 TCGReg addr_regl, data_regl, data_regh, data_reg1, data_reg2;
afa05235
AJ
948#if defined(CONFIG_SOFTMMU)
949 void *label1_ptr, *label2_ptr;
18fec301 950 int arg_num;
0834c9ea
AJ
951 int mem_index, s_bits;
952 int addr_meml;
953# if TARGET_LONG_BITS == 64
afa05235 954 uint8_t *label3_ptr;
5a0eed37
AJ
955 TCGReg addr_regh;
956 int addr_memh;
0834c9ea 957# endif
afa05235
AJ
958#endif
959 data_regl = *args++;
960 if (opc == 3)
961 data_regh = *args++;
962 else
963 data_regh = 0;
964 addr_regl = *args++;
0834c9ea
AJ
965#if defined(CONFIG_SOFTMMU)
966# if TARGET_LONG_BITS == 64
afa05235 967 addr_regh = *args++;
0834c9ea
AJ
968# if defined(TCG_TARGET_WORDS_BIGENDIAN)
969 addr_memh = 0;
970 addr_meml = 4;
971# else
972 addr_memh = 4;
973 addr_meml = 0;
974# endif
975# else
976 addr_meml = 0;
977# endif
afa05235
AJ
978 mem_index = *args;
979 s_bits = opc & 3;
0834c9ea 980#endif
afa05235
AJ
981
982 if (opc == 3) {
983#if defined(TCG_TARGET_WORDS_BIGENDIAN)
984 data_reg1 = data_regh;
985 data_reg2 = data_regl;
986#else
987 data_reg1 = data_regl;
988 data_reg2 = data_regh;
989#endif
990 } else {
991 data_reg1 = data_regl;
992 data_reg2 = 0;
993 }
afa05235
AJ
994#if defined(CONFIG_SOFTMMU)
995 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
996 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
997 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
998 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
9349b4f9 999 offsetof(CPUArchState, tlb_table[mem_index][0].addr_read) + addr_meml);
afa05235
AJ
1000 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
1001 tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
1002
1003# if TARGET_LONG_BITS == 64
1004 label3_ptr = s->code_ptr;
6d8ff4d8 1005 tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
afa05235
AJ
1006 tcg_out_nop(s);
1007
1008 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
9349b4f9 1009 offsetof(CPUArchState, tlb_table[mem_index][0].addr_read) + addr_memh);
afa05235
AJ
1010
1011 label1_ptr = s->code_ptr;
6d8ff4d8 1012 tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
afa05235
AJ
1013 tcg_out_nop(s);
1014
1015 reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
1016# else
1017 label1_ptr = s->code_ptr;
6d8ff4d8 1018 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
afa05235
AJ
1019 tcg_out_nop(s);
1020# endif
1021
1022 /* slow path */
18fec301 1023 arg_num = 0;
18fec301 1024 tcg_out_call_iarg_reg32(s, &arg_num, TCG_AREG0);
afa05235 1025# if TARGET_LONG_BITS == 64
18fec301
AJ
1026 tcg_out_call_iarg_reg64(s, &arg_num, addr_regl, addr_regh);
1027# else
1028 tcg_out_call_iarg_reg32(s, &arg_num, addr_regl);
afa05235 1029# endif
18fec301 1030 tcg_out_call_iarg_imm32(s, &arg_num, mem_index);
afa05235
AJ
1031 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]);
1032 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
1033 tcg_out_nop(s);
1034
1035 switch(opc) {
1036 case 0:
1037 tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xff);
1038 break;
1039 case 0 | 4:
116348de 1040 tcg_out_ext8s(s, data_reg1, TCG_REG_V0);
afa05235
AJ
1041 break;
1042 case 1:
1043 tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xffff);
1044 break;
1045 case 1 | 4:
116348de 1046 tcg_out_ext16s(s, data_reg1, TCG_REG_V0);
afa05235
AJ
1047 break;
1048 case 2:
3b6dac34 1049 tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
afa05235
AJ
1050 break;
1051 case 3:
3b6dac34
RH
1052 tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_V1);
1053 tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
afa05235
AJ
1054 break;
1055 default:
1056 tcg_abort();
1057 }
1058
1059 label2_ptr = s->code_ptr;
6d8ff4d8 1060 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
afa05235
AJ
1061 tcg_out_nop(s);
1062
1063 /* label1: fast path */
1064 reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
1065
cca1af8c 1066 tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
9349b4f9 1067 offsetof(CPUArchState, tlb_table[mem_index][0].addend));
cca1af8c 1068 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_A0, addr_regl);
cc01cc8e
AJ
1069#else
1070 if (GUEST_BASE == (int16_t)GUEST_BASE) {
ba0d89bb 1071 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_V0, addr_regl, GUEST_BASE);
cc01cc8e
AJ
1072 } else {
1073 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, GUEST_BASE);
ba0d89bb 1074 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_V0, addr_regl);
cc01cc8e 1075 }
afa05235
AJ
1076#endif
1077
1078 switch(opc) {
1079 case 0:
cc01cc8e 1080 tcg_out_opc_imm(s, OPC_LBU, data_reg1, TCG_REG_V0, 0);
afa05235
AJ
1081 break;
1082 case 0 | 4:
cc01cc8e 1083 tcg_out_opc_imm(s, OPC_LB, data_reg1, TCG_REG_V0, 0);
afa05235
AJ
1084 break;
1085 case 1:
1086 if (TCG_NEED_BSWAP) {
cc01cc8e 1087 tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
afa05235
AJ
1088 tcg_out_bswap16(s, data_reg1, TCG_REG_T0);
1089 } else {
cc01cc8e 1090 tcg_out_opc_imm(s, OPC_LHU, data_reg1, TCG_REG_V0, 0);
afa05235
AJ
1091 }
1092 break;
1093 case 1 | 4:
1094 if (TCG_NEED_BSWAP) {
cc01cc8e 1095 tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
afa05235
AJ
1096 tcg_out_bswap16s(s, data_reg1, TCG_REG_T0);
1097 } else {
cc01cc8e 1098 tcg_out_opc_imm(s, OPC_LH, data_reg1, TCG_REG_V0, 0);
afa05235
AJ
1099 }
1100 break;
1101 case 2:
1102 if (TCG_NEED_BSWAP) {
cc01cc8e 1103 tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
afa05235
AJ
1104 tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
1105 } else {
cc01cc8e 1106 tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
afa05235
AJ
1107 }
1108 break;
1109 case 3:
afa05235 1110 if (TCG_NEED_BSWAP) {
cc01cc8e 1111 tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 4);
afa05235 1112 tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
cc01cc8e 1113 tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
afa05235
AJ
1114 tcg_out_bswap32(s, data_reg2, TCG_REG_T0);
1115 } else {
cc01cc8e
AJ
1116 tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
1117 tcg_out_opc_imm(s, OPC_LW, data_reg2, TCG_REG_V0, 4);
afa05235
AJ
1118 }
1119 break;
1120 default:
1121 tcg_abort();
1122 }
1123
1124#if defined(CONFIG_SOFTMMU)
1125 reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
1126#endif
1127}
1128
1129static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
1130 int opc)
1131{
5a0eed37 1132 TCGReg addr_regl, data_regl, data_regh, data_reg1, data_reg2;
afa05235
AJ
1133#if defined(CONFIG_SOFTMMU)
1134 uint8_t *label1_ptr, *label2_ptr;
18fec301 1135 int arg_num;
0834c9ea
AJ
1136 int mem_index, s_bits;
1137 int addr_meml;
afa05235
AJ
1138#endif
1139#if TARGET_LONG_BITS == 64
1140# if defined(CONFIG_SOFTMMU)
1141 uint8_t *label3_ptr;
5a0eed37
AJ
1142 TCGReg addr_regh;
1143 int addr_memh;
0834c9ea 1144# endif
afa05235 1145#endif
afa05235
AJ
1146 data_regl = *args++;
1147 if (opc == 3) {
1148 data_regh = *args++;
afa05235 1149 } else {
afa05235
AJ
1150 data_regh = 0;
1151 }
1152 addr_regl = *args++;
0834c9ea
AJ
1153#if defined(CONFIG_SOFTMMU)
1154# if TARGET_LONG_BITS == 64
afa05235 1155 addr_regh = *args++;
0834c9ea 1156# if defined(TCG_TARGET_WORDS_BIGENDIAN)
afa05235
AJ
1157 addr_memh = 0;
1158 addr_meml = 4;
0834c9ea 1159# else
afa05235
AJ
1160 addr_memh = 4;
1161 addr_meml = 0;
0834c9ea
AJ
1162# endif
1163# else
afa05235 1164 addr_meml = 0;
0834c9ea 1165# endif
afa05235
AJ
1166 mem_index = *args;
1167 s_bits = opc;
0834c9ea
AJ
1168#endif
1169
1170 if (opc == 3) {
1171#if defined(TCG_TARGET_WORDS_BIGENDIAN)
1172 data_reg1 = data_regh;
1173 data_reg2 = data_regl;
1174#else
1175 data_reg1 = data_regl;
1176 data_reg2 = data_regh;
1177#endif
1178 } else {
1179 data_reg1 = data_regl;
1180 data_reg2 = 0;
1181 }
afa05235
AJ
1182
1183#if defined(CONFIG_SOFTMMU)
1184 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
1185 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
1186 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
1187 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
9349b4f9 1188 offsetof(CPUArchState, tlb_table[mem_index][0].addr_write) + addr_meml);
afa05235
AJ
1189 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
1190 tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
1191
1192# if TARGET_LONG_BITS == 64
1193 label3_ptr = s->code_ptr;
6d8ff4d8 1194 tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
afa05235
AJ
1195 tcg_out_nop(s);
1196
1197 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
9349b4f9 1198 offsetof(CPUArchState, tlb_table[mem_index][0].addr_write) + addr_memh);
afa05235
AJ
1199
1200 label1_ptr = s->code_ptr;
6d8ff4d8 1201 tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
afa05235
AJ
1202 tcg_out_nop(s);
1203
1204 reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
1205# else
1206 label1_ptr = s->code_ptr;
6d8ff4d8 1207 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
afa05235
AJ
1208 tcg_out_nop(s);
1209# endif
1210
1211 /* slow path */
18fec301 1212 arg_num = 0;
18fec301 1213 tcg_out_call_iarg_reg32(s, &arg_num, TCG_AREG0);
afa05235 1214# if TARGET_LONG_BITS == 64
18fec301
AJ
1215 tcg_out_call_iarg_reg64(s, &arg_num, addr_regl, addr_regh);
1216# else
1217 tcg_out_call_iarg_reg32(s, &arg_num, addr_regl);
afa05235
AJ
1218# endif
1219 switch(opc) {
1220 case 0:
18fec301 1221 tcg_out_call_iarg_reg8(s, &arg_num, data_regl);
afa05235
AJ
1222 break;
1223 case 1:
18fec301 1224 tcg_out_call_iarg_reg16(s, &arg_num, data_regl);
afa05235
AJ
1225 break;
1226 case 2:
18fec301 1227 tcg_out_call_iarg_reg32(s, &arg_num, data_regl);
afa05235
AJ
1228 break;
1229 case 3:
18fec301 1230 tcg_out_call_iarg_reg64(s, &arg_num, data_regl, data_regh);
afa05235
AJ
1231 break;
1232 default:
1233 tcg_abort();
1234 }
18fec301 1235 tcg_out_call_iarg_imm32(s, &arg_num, mem_index);
afa05235
AJ
1236 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_st_helpers[s_bits]);
1237 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
1238 tcg_out_nop(s);
1239
1240 label2_ptr = s->code_ptr;
6d8ff4d8 1241 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
afa05235
AJ
1242 tcg_out_nop(s);
1243
1244 /* label1: fast path */
1245 reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
1246
1247 tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
9349b4f9 1248 offsetof(CPUArchState, tlb_table[mem_index][0].addend));
afa05235 1249 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
cc01cc8e
AJ
1250#else
1251 if (GUEST_BASE == (int16_t)GUEST_BASE) {
ba0d89bb 1252 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_A0, addr_regl, GUEST_BASE);
cc01cc8e
AJ
1253 } else {
1254 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, GUEST_BASE);
ba0d89bb 1255 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
cc01cc8e 1256 }
afa05235 1257
afa05235
AJ
1258#endif
1259
1260 switch(opc) {
1261 case 0:
cc01cc8e 1262 tcg_out_opc_imm(s, OPC_SB, data_reg1, TCG_REG_A0, 0);
afa05235
AJ
1263 break;
1264 case 1:
1265 if (TCG_NEED_BSWAP) {
c1cf85c9
AJ
1266 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_T0, data_reg1, 0xffff);
1267 tcg_out_bswap16(s, TCG_REG_T0, TCG_REG_T0);
cc01cc8e 1268 tcg_out_opc_imm(s, OPC_SH, TCG_REG_T0, TCG_REG_A0, 0);
afa05235 1269 } else {
cc01cc8e 1270 tcg_out_opc_imm(s, OPC_SH, data_reg1, TCG_REG_A0, 0);
afa05235
AJ
1271 }
1272 break;
1273 case 2:
1274 if (TCG_NEED_BSWAP) {
1275 tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
cc01cc8e 1276 tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
afa05235 1277 } else {
cc01cc8e 1278 tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
afa05235
AJ
1279 }
1280 break;
1281 case 3:
1282 if (TCG_NEED_BSWAP) {
1283 tcg_out_bswap32(s, TCG_REG_T0, data_reg2);
cc01cc8e 1284 tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
afa05235 1285 tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
cc01cc8e 1286 tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 4);
afa05235 1287 } else {
cc01cc8e
AJ
1288 tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
1289 tcg_out_opc_imm(s, OPC_SW, data_reg2, TCG_REG_A0, 4);
afa05235
AJ
1290 }
1291 break;
1292 default:
1293 tcg_abort();
1294 }
1295
1296#if defined(CONFIG_SOFTMMU)
1297 reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
1298#endif
1299}
1300
a9751609 1301static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
afa05235
AJ
1302 const TCGArg *args, const int *const_args)
1303{
1304 switch(opc) {
1305 case INDEX_op_exit_tb:
1306 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_V0, args[0]);
1307 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, (tcg_target_long)tb_ret_addr);
1308 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1309 tcg_out_nop(s);
1310 break;
1311 case INDEX_op_goto_tb:
1312 if (s->tb_jmp_offset) {
1313 /* direct jump method */
1314 tcg_abort();
1315 } else {
1316 /* indirect jump method */
1317 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, (tcg_target_long)(s->tb_next + args[0]));
1318 tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_AT, TCG_REG_AT, 0);
1319 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1320 }
1321 tcg_out_nop(s);
1322 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1323 break;
1324 case INDEX_op_call:
1325 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, args[0], 0);
1326 tcg_out_nop(s);
1327 break;
afa05235
AJ
1328 case INDEX_op_br:
1329 tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, args[0]);
1330 break;
1331
1332 case INDEX_op_mov_i32:
3b6dac34 1333 tcg_out_mov(s, TCG_TYPE_I32, args[0], args[1]);
afa05235
AJ
1334 break;
1335 case INDEX_op_movi_i32:
1336 tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1337 break;
1338
1339 case INDEX_op_ld8u_i32:
116348de 1340 tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]);
afa05235
AJ
1341 break;
1342 case INDEX_op_ld8s_i32:
1343 tcg_out_ldst(s, OPC_LB, args[0], args[1], args[2]);
1344 break;
1345 case INDEX_op_ld16u_i32:
1346 tcg_out_ldst(s, OPC_LHU, args[0], args[1], args[2]);
1347 break;
1348 case INDEX_op_ld16s_i32:
1349 tcg_out_ldst(s, OPC_LH, args[0], args[1], args[2]);
1350 break;
1351 case INDEX_op_ld_i32:
1352 tcg_out_ldst(s, OPC_LW, args[0], args[1], args[2]);
1353 break;
1354 case INDEX_op_st8_i32:
1355 tcg_out_ldst(s, OPC_SB, args[0], args[1], args[2]);
1356 break;
1357 case INDEX_op_st16_i32:
1358 tcg_out_ldst(s, OPC_SH, args[0], args[1], args[2]);
1359 break;
1360 case INDEX_op_st_i32:
1361 tcg_out_ldst(s, OPC_SW, args[0], args[1], args[2]);
1362 break;
1363
1364 case INDEX_op_add_i32:
1365 if (const_args[2]) {
1366 tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], args[2]);
1367 } else {
1368 tcg_out_opc_reg(s, OPC_ADDU, args[0], args[1], args[2]);
1369 }
1370 break;
1371 case INDEX_op_add2_i32:
1372 if (const_args[4]) {
1373 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], args[4]);
1374 } else {
1375 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, args[2], args[4]);
1376 }
1377 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, TCG_REG_AT, args[2]);
1378 if (const_args[5]) {
1379 tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], args[5]);
1380 } else {
1381 tcg_out_opc_reg(s, OPC_ADDU, args[1], args[3], args[5]);
1382 }
1383 tcg_out_opc_reg(s, OPC_ADDU, args[1], args[1], TCG_REG_T0);
3b6dac34 1384 tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
afa05235
AJ
1385 break;
1386 case INDEX_op_sub_i32:
1387 if (const_args[2]) {
1388 tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], -args[2]);
1389 } else {
1390 tcg_out_opc_reg(s, OPC_SUBU, args[0], args[1], args[2]);
1391 }
1392 break;
1393 case INDEX_op_sub2_i32:
1394 if (const_args[4]) {
1395 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], -args[4]);
1396 } else {
1397 tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, args[2], args[4]);
1398 }
1399 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, args[2], TCG_REG_AT);
1400 if (const_args[5]) {
1401 tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], -args[5]);
1402 } else {
1403 tcg_out_opc_reg(s, OPC_SUBU, args[1], args[3], args[5]);
1404 }
1405 tcg_out_opc_reg(s, OPC_SUBU, args[1], args[1], TCG_REG_T0);
3b6dac34 1406 tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
afa05235
AJ
1407 break;
1408 case INDEX_op_mul_i32:
3585317f
AJ
1409#if defined(__mips_isa_rev) && (__mips_isa_rev >= 1)
1410 tcg_out_opc_reg(s, OPC_MUL, args[0], args[1], args[2]);
1411#else
afa05235
AJ
1412 tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
1413 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
3585317f 1414#endif
afa05235 1415 break;
174d4d21
AJ
1416 case INDEX_op_muls2_i32:
1417 tcg_out_opc_reg(s, OPC_MULT, 0, args[2], args[3]);
1418 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1419 tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
1420 break;
afa05235
AJ
1421 case INDEX_op_mulu2_i32:
1422 tcg_out_opc_reg(s, OPC_MULTU, 0, args[2], args[3]);
1423 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1424 tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
1425 break;
3c9a8f17
RH
1426 case INDEX_op_mulsh_i32:
1427 tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
1428 tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1429 break;
1430 case INDEX_op_muluh_i32:
1431 tcg_out_opc_reg(s, OPC_MULTU, 0, args[1], args[2]);
1432 tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1433 break;
afa05235
AJ
1434 case INDEX_op_div_i32:
1435 tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1436 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1437 break;
1438 case INDEX_op_divu_i32:
1439 tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1440 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1441 break;
1442 case INDEX_op_rem_i32:
1443 tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1444 tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1445 break;
1446 case INDEX_op_remu_i32:
1447 tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1448 tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1449 break;
1450
1451 case INDEX_op_and_i32:
1452 if (const_args[2]) {
1453 tcg_out_opc_imm(s, OPC_ANDI, args[0], args[1], args[2]);
1454 } else {
1455 tcg_out_opc_reg(s, OPC_AND, args[0], args[1], args[2]);
1456 }
1457 break;
1458 case INDEX_op_or_i32:
1459 if (const_args[2]) {
1460 tcg_out_opc_imm(s, OPC_ORI, args[0], args[1], args[2]);
1461 } else {
1462 tcg_out_opc_reg(s, OPC_OR, args[0], args[1], args[2]);
1463 }
1464 break;
2b79487a
AJ
1465 case INDEX_op_nor_i32:
1466 tcg_out_opc_reg(s, OPC_NOR, args[0], args[1], args[2]);
1467 break;
afa05235 1468 case INDEX_op_not_i32:
489722cf 1469 tcg_out_opc_reg(s, OPC_NOR, args[0], TCG_REG_ZERO, args[1]);
afa05235
AJ
1470 break;
1471 case INDEX_op_xor_i32:
1472 if (const_args[2]) {
1473 tcg_out_opc_imm(s, OPC_XORI, args[0], args[1], args[2]);
1474 } else {
1475 tcg_out_opc_reg(s, OPC_XOR, args[0], args[1], args[2]);
1476 }
1477 break;
1478
1479 case INDEX_op_sar_i32:
1480 if (const_args[2]) {
1481 tcg_out_opc_sa(s, OPC_SRA, args[0], args[1], args[2]);
1482 } else {
1483 tcg_out_opc_reg(s, OPC_SRAV, args[0], args[2], args[1]);
1484 }
1485 break;
1486 case INDEX_op_shl_i32:
1487 if (const_args[2]) {
1488 tcg_out_opc_sa(s, OPC_SLL, args[0], args[1], args[2]);
1489 } else {
1490 tcg_out_opc_reg(s, OPC_SLLV, args[0], args[2], args[1]);
1491 }
1492 break;
1493 case INDEX_op_shr_i32:
1494 if (const_args[2]) {
1495 tcg_out_opc_sa(s, OPC_SRL, args[0], args[1], args[2]);
1496 } else {
1497 tcg_out_opc_reg(s, OPC_SRLV, args[0], args[2], args[1]);
1498 }
1499 break;
9a152519
AJ
1500 case INDEX_op_rotl_i32:
1501 if (const_args[2]) {
1502 tcg_out_opc_sa(s, OPC_ROTR, args[0], args[1], 0x20 - args[2]);
1503 } else {
1504 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, 32);
1505 tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, TCG_REG_AT, args[2]);
1506 tcg_out_opc_reg(s, OPC_ROTRV, args[0], TCG_REG_AT, args[1]);
1507 }
1508 break;
1509 case INDEX_op_rotr_i32:
1510 if (const_args[2]) {
1511 tcg_out_opc_sa(s, OPC_ROTR, args[0], args[1], args[2]);
1512 } else {
1513 tcg_out_opc_reg(s, OPC_ROTRV, args[0], args[2], args[1]);
1514 }
1515 break;
afa05235 1516
c1cf85c9
AJ
1517 /* The bswap routines do not work on non-R2 CPU. In that case
1518 we let TCG generating the corresponding code. */
1519 case INDEX_op_bswap16_i32:
1520 tcg_out_bswap16(s, args[0], args[1]);
1521 break;
1522 case INDEX_op_bswap32_i32:
1523 tcg_out_bswap32(s, args[0], args[1]);
1524 break;
1525
116348de
AJ
1526 case INDEX_op_ext8s_i32:
1527 tcg_out_ext8s(s, args[0], args[1]);
1528 break;
1529 case INDEX_op_ext16s_i32:
1530 tcg_out_ext16s(s, args[0], args[1]);
1531 break;
1532
04f71aa3
AJ
1533 case INDEX_op_deposit_i32:
1534 tcg_out_opc_imm(s, OPC_INS, args[0], args[2],
1535 ((args[3] + args[4] - 1) << 11) | (args[3] << 6));
1536 break;
1537
afa05235
AJ
1538 case INDEX_op_brcond_i32:
1539 tcg_out_brcond(s, args[2], args[0], args[1], args[3]);
1540 break;
1541 case INDEX_op_brcond2_i32:
1542 tcg_out_brcond2(s, args[4], args[0], args[1], args[2], args[3], args[5]);
1543 break;
1544
7d7c4930
AJ
1545 case INDEX_op_movcond_i32:
1546 tcg_out_movcond(s, args[5], args[0], args[1], args[2], args[3]);
1547 break;
1548
4cb26382
AJ
1549 case INDEX_op_setcond_i32:
1550 tcg_out_setcond(s, args[3], args[0], args[1], args[2]);
1551 break;
434254aa
AJ
1552 case INDEX_op_setcond2_i32:
1553 tcg_out_setcond2(s, args[5], args[0], args[1], args[2], args[3], args[4]);
1554 break;
4cb26382 1555
afa05235
AJ
1556 case INDEX_op_qemu_ld8u:
1557 tcg_out_qemu_ld(s, args, 0);
1558 break;
1559 case INDEX_op_qemu_ld8s:
1560 tcg_out_qemu_ld(s, args, 0 | 4);
1561 break;
1562 case INDEX_op_qemu_ld16u:
1563 tcg_out_qemu_ld(s, args, 1);
1564 break;
1565 case INDEX_op_qemu_ld16s:
1566 tcg_out_qemu_ld(s, args, 1 | 4);
1567 break;
86feb1c8 1568 case INDEX_op_qemu_ld32:
afa05235
AJ
1569 tcg_out_qemu_ld(s, args, 2);
1570 break;
1571 case INDEX_op_qemu_ld64:
1572 tcg_out_qemu_ld(s, args, 3);
1573 break;
1574 case INDEX_op_qemu_st8:
1575 tcg_out_qemu_st(s, args, 0);
1576 break;
1577 case INDEX_op_qemu_st16:
1578 tcg_out_qemu_st(s, args, 1);
1579 break;
1580 case INDEX_op_qemu_st32:
1581 tcg_out_qemu_st(s, args, 2);
1582 break;
1583 case INDEX_op_qemu_st64:
1584 tcg_out_qemu_st(s, args, 3);
1585 break;
1586
1587 default:
1588 tcg_abort();
1589 }
1590}
1591
1592static const TCGTargetOpDef mips_op_defs[] = {
1593 { INDEX_op_exit_tb, { } },
1594 { INDEX_op_goto_tb, { } },
1595 { INDEX_op_call, { "C" } },
afa05235
AJ
1596 { INDEX_op_br, { } },
1597
1598 { INDEX_op_mov_i32, { "r", "r" } },
1599 { INDEX_op_movi_i32, { "r" } },
1600 { INDEX_op_ld8u_i32, { "r", "r" } },
1601 { INDEX_op_ld8s_i32, { "r", "r" } },
1602 { INDEX_op_ld16u_i32, { "r", "r" } },
1603 { INDEX_op_ld16s_i32, { "r", "r" } },
1604 { INDEX_op_ld_i32, { "r", "r" } },
1605 { INDEX_op_st8_i32, { "rZ", "r" } },
1606 { INDEX_op_st16_i32, { "rZ", "r" } },
1607 { INDEX_op_st_i32, { "rZ", "r" } },
1608
2ceb3a9e 1609 { INDEX_op_add_i32, { "r", "rZ", "rJ" } },
afa05235 1610 { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
174d4d21 1611 { INDEX_op_muls2_i32, { "r", "r", "rZ", "rZ" } },
afa05235 1612 { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
3c9a8f17
RH
1613 { INDEX_op_mulsh_i32, { "r", "rZ", "rZ" } },
1614 { INDEX_op_muluh_i32, { "r", "rZ", "rZ" } },
afa05235
AJ
1615 { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
1616 { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
1617 { INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
1618 { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
2ceb3a9e 1619 { INDEX_op_sub_i32, { "r", "rZ", "rJ" } },
afa05235 1620
2ceb3a9e 1621 { INDEX_op_and_i32, { "r", "rZ", "rI" } },
2b79487a 1622 { INDEX_op_nor_i32, { "r", "rZ", "rZ" } },
afa05235
AJ
1623 { INDEX_op_not_i32, { "r", "rZ" } },
1624 { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
1625 { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
1626
2ceb3a9e
AJ
1627 { INDEX_op_shl_i32, { "r", "rZ", "ri" } },
1628 { INDEX_op_shr_i32, { "r", "rZ", "ri" } },
1629 { INDEX_op_sar_i32, { "r", "rZ", "ri" } },
85711e6b 1630#if TCG_TARGET_HAS_rot_i32
9a152519
AJ
1631 { INDEX_op_rotr_i32, { "r", "rZ", "ri" } },
1632 { INDEX_op_rotl_i32, { "r", "rZ", "ri" } },
85711e6b 1633#endif
afa05235 1634
85711e6b 1635#if TCG_TARGET_HAS_bswap16_i32
c1cf85c9 1636 { INDEX_op_bswap16_i32, { "r", "r" } },
85711e6b
JH
1637#endif
1638#if TCG_TARGET_HAS_bswap32_i32
c1cf85c9 1639 { INDEX_op_bswap32_i32, { "r", "r" } },
85711e6b 1640#endif
c1cf85c9 1641
116348de
AJ
1642 { INDEX_op_ext8s_i32, { "r", "rZ" } },
1643 { INDEX_op_ext16s_i32, { "r", "rZ" } },
1644
85711e6b 1645#if TCG_TARGET_HAS_deposit_i32
04f71aa3 1646 { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
85711e6b 1647#endif
04f71aa3 1648
afa05235 1649 { INDEX_op_brcond_i32, { "rZ", "rZ" } },
85711e6b 1650#if TCG_TARGET_HAS_movcond_i32
7d7c4930 1651 { INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rZ", "0" } },
85711e6b 1652#endif
4cb26382 1653 { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
434254aa 1654 { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
afa05235 1655
2ceb3a9e
AJ
1656 { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJ", "rJ" } },
1657 { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJ", "rJ" } },
afa05235
AJ
1658 { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
1659
1660#if TARGET_LONG_BITS == 32
1661 { INDEX_op_qemu_ld8u, { "L", "lZ" } },
1662 { INDEX_op_qemu_ld8s, { "L", "lZ" } },
1663 { INDEX_op_qemu_ld16u, { "L", "lZ" } },
1664 { INDEX_op_qemu_ld16s, { "L", "lZ" } },
86feb1c8 1665 { INDEX_op_qemu_ld32, { "L", "lZ" } },
afa05235
AJ
1666 { INDEX_op_qemu_ld64, { "L", "L", "lZ" } },
1667
1668 { INDEX_op_qemu_st8, { "SZ", "SZ" } },
1669 { INDEX_op_qemu_st16, { "SZ", "SZ" } },
1670 { INDEX_op_qemu_st32, { "SZ", "SZ" } },
1671 { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ" } },
1672#else
1673 { INDEX_op_qemu_ld8u, { "L", "lZ", "lZ" } },
1674 { INDEX_op_qemu_ld8s, { "L", "lZ", "lZ" } },
1675 { INDEX_op_qemu_ld16u, { "L", "lZ", "lZ" } },
1676 { INDEX_op_qemu_ld16s, { "L", "lZ", "lZ" } },
86feb1c8 1677 { INDEX_op_qemu_ld32, { "L", "lZ", "lZ" } },
afa05235
AJ
1678 { INDEX_op_qemu_ld64, { "L", "L", "lZ", "lZ" } },
1679
1680 { INDEX_op_qemu_st8, { "SZ", "SZ", "SZ" } },
1681 { INDEX_op_qemu_st16, { "SZ", "SZ", "SZ" } },
1682 { INDEX_op_qemu_st32, { "SZ", "SZ", "SZ" } },
1683 { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ", "SZ" } },
1684#endif
1685 { -1 },
1686};
1687
1688static int tcg_target_callee_save_regs[] = {
cea5f9a2 1689 TCG_REG_S0, /* used for the global env (TCG_AREG0) */
afa05235
AJ
1690 TCG_REG_S1,
1691 TCG_REG_S2,
1692 TCG_REG_S3,
1693 TCG_REG_S4,
1694 TCG_REG_S5,
1695 TCG_REG_S6,
1696 TCG_REG_S7,
60bf84cf 1697 TCG_REG_FP,
afa05235
AJ
1698 TCG_REG_RA, /* should be last for ABI compliance */
1699};
1700
1701/* Generate global QEMU prologue and epilogue code */
e4d58b41 1702static void tcg_target_qemu_prologue(TCGContext *s)
afa05235
AJ
1703{
1704 int i, frame_size;
1705
0d0b53a6 1706 /* reserve some stack space, also for TCG temps. */
afa05235 1707 frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
0d0b53a6
AJ
1708 + TCG_STATIC_CALL_ARGS_SIZE
1709 + CPU_TEMP_BUF_NLONGS * sizeof(long);
afa05235
AJ
1710 frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1711 ~(TCG_TARGET_STACK_ALIGN - 1);
e809c0dc
AJ
1712 tcg_set_frame(s, TCG_REG_SP, ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1713 + TCG_STATIC_CALL_ARGS_SIZE,
0d0b53a6 1714 CPU_TEMP_BUF_NLONGS * sizeof(long));
afa05235
AJ
1715
1716 /* TB prologue */
1717 tcg_out_addi(s, TCG_REG_SP, -frame_size);
1718 for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1719 tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1720 TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1721 }
1722
1723 /* Call generated code */
ea15fb06 1724 tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1], 0);
cea5f9a2 1725 tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
afa05235
AJ
1726 tb_ret_addr = s->code_ptr;
1727
1728 /* TB epilogue */
1729 for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1730 tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1731 TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1732 }
1733
1734 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
1735 tcg_out_addi(s, TCG_REG_SP, frame_size);
1736}
1737
e4d58b41 1738static void tcg_target_init(TCGContext *s)
afa05235
AJ
1739{
1740 tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
1741 tcg_regset_set(tcg_target_call_clobber_regs,
1742 (1 << TCG_REG_V0) |
1743 (1 << TCG_REG_V1) |
1744 (1 << TCG_REG_A0) |
1745 (1 << TCG_REG_A1) |
1746 (1 << TCG_REG_A2) |
1747 (1 << TCG_REG_A3) |
1748 (1 << TCG_REG_T1) |
1749 (1 << TCG_REG_T2) |
1750 (1 << TCG_REG_T3) |
1751 (1 << TCG_REG_T4) |
1752 (1 << TCG_REG_T5) |
1753 (1 << TCG_REG_T6) |
1754 (1 << TCG_REG_T7) |
1755 (1 << TCG_REG_T8) |
1756 (1 << TCG_REG_T9));
1757
1758 tcg_regset_clear(s->reserved_regs);
1759 tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
1760 tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0); /* kernel use only */
1761 tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1); /* kernel use only */
1762 tcg_regset_set_reg(s->reserved_regs, TCG_REG_AT); /* internal use */
1763 tcg_regset_set_reg(s->reserved_regs, TCG_REG_T0); /* internal use */
1764 tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return address */
1765 tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */
3314e008 1766 tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP); /* global pointer */
afa05235
AJ
1767
1768 tcg_add_target_add_op_defs(mips_op_defs);
1769}