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