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