Revision afa05235

b/configure
134 134
  else
135 135
    cpu="ppc"
136 136
  fi
137
elif check_define __mips__ ; then
138
  cpu="mips"
137 139
else
138 140
  cpu=`uname -m`
139 141
fi
140 142

  
141 143
target_list=""
142 144
case "$cpu" in
143
  alpha|cris|ia64|m68k|microblaze|mips|mips64|ppc|ppc64|sparc64)
145
  alpha|cris|ia64|m68k|microblaze|ppc|ppc64|sparc64)
144 146
    cpu="$cpu"
145 147
  ;;
146 148
  i386|i486|i586|i686|i86pc|BePC)
......
158 160
  parisc|parisc64)
159 161
    cpu="hppa"
160 162
  ;;
163
  mips*)
164
    cpu="mips"
165
  ;;
161 166
  s390*)
162 167
    cpu="s390"
163 168
  ;;
b/tcg/mips/tcg-target.c
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
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
/*
343
 * Type sa
344
 */
345
static inline void tcg_out_opc_sa(TCGContext *s, int opc, int rd, int rt, int sa)
346
{
347
    int32_t inst;
348

  
349
    inst = opc;
350
    inst |= (rt & 0x1F) << 16;
351
    inst |= (rd & 0x1F) << 11;
352
    inst |= (sa & 0x1F) <<  6;
353
    tcg_out32(s, inst);
354

  
355
}
356

  
357
static inline void tcg_out_nop(TCGContext *s)
358
{
359
    tcg_out32(s, 0);
360
}
361

  
362
static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
363
{
364
    tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
365
}
366

  
367
static inline void tcg_out_movi(TCGContext *s, TCGType type,
368
                                int reg, int32_t arg)
369
{
370
    if (arg == (int16_t)arg) {
371
        tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
372
    } else if (arg == (uint16_t)arg) {
373
        tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
374
    } else {
375
        tcg_out_opc_imm(s, OPC_LUI, reg, 0, arg >> 16);
376
        tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0xffff);
377
    }
378
}
379

  
380
static inline void tcg_out_bswap16(TCGContext *s, int ret, int arg)
381
{
382
    /* ret and arg can't be register at */
383
    if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
384
        tcg_abort();
385
    }
386

  
387
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
388
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0x00ff);
389

  
390
    tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
391
    tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
392
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
393
}
394

  
395
static inline void tcg_out_bswap16s(TCGContext *s, int ret, int arg)
396
{
397
    /* ret and arg can't be register at */
398
    if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
399
        tcg_abort();
400
    }
401

  
402
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
403
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff);
404

  
405
    tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
406
    tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
407
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
408
}
409

  
410
static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg)
411
{
412
    /* ret and arg must be different and can't be register at */
413
    if (ret == arg || ret == TCG_REG_AT || arg == TCG_REG_AT) {
414
        tcg_abort();
415
    }
416

  
417
    tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
418

  
419
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 24);
420
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
421

  
422
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, arg, 0xff00);
423
    tcg_out_opc_sa(s, OPC_SLL, TCG_REG_AT, TCG_REG_AT, 8);
424
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
425

  
426
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
427
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff00);
428
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
429
}
430

  
431
static inline void tcg_out_ldst(TCGContext *s, int opc, int arg,
432
                              int arg1, tcg_target_long arg2)
433
{
434
    if (arg2 == (int16_t) arg2) {
435
        tcg_out_opc_imm(s, opc, arg, arg1, arg2);
436
    } else {
437
        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, arg2);
438
        tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, TCG_REG_AT, arg1);
439
        tcg_out_opc_imm(s, opc, arg, TCG_REG_AT, 0);
440
    }
441
}
442

  
443
static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg,
444
                              int arg1, tcg_target_long arg2)
445
{
446
    tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
447
}
448

  
449
static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
450
                              int arg1, tcg_target_long arg2)
451
{
452
    tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
453
}
454

  
455
static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
456
{
457
    if (val == (int16_t)val) {
458
        tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
459
    } else {
460
        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, val);
461
        tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_REG_AT);
462
    }
463
}
464

  
465
static void tcg_out_brcond(TCGContext *s, int cond, int arg1,
466
                           int arg2, int label_index)
467
{
468
    TCGLabel *l = &s->labels[label_index];
469

  
470
    switch (cond) {
471
    case TCG_COND_EQ:
472
        tcg_out_opc_imm(s, OPC_BEQ, arg1, arg2, 0);
473
        break;
474
    case TCG_COND_NE:
475
        tcg_out_opc_imm(s, OPC_BNE, arg1, arg2, 0);
476
        break;
477
    case TCG_COND_LT:
478
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
479
        tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
480
        break;
481
    case TCG_COND_LTU:
482
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
483
        tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
484
        break;
485
    case TCG_COND_GE:
486
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
487
        tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
488
        break;
489
    case TCG_COND_GEU:
490
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
491
        tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
492
        break;
493
    case TCG_COND_LE:
494
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
495
        tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
496
        break;
497
    case TCG_COND_LEU:
498
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
499
        tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
500
        break;
501
    case TCG_COND_GT:
502
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
503
        tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
504
        break;
505
    case TCG_COND_GTU:
506
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
507
        tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
508
        break;
509
    default:
510
        tcg_abort();
511
        break;
512
    }
513
    if (l->has_value) {
514
        reloc_pc16(s->code_ptr - 4, l->u.value);
515
    } else {
516
        tcg_out_reloc(s, s->code_ptr - 4, R_MIPS_PC16, label_index, 0);
517
    }
518
    tcg_out_nop(s);
519
}
520

  
521
/* XXX: we implement it at the target level to avoid having to
522
   handle cross basic blocks temporaries */
523
static void tcg_out_brcond2(TCGContext *s, int cond, int arg1,
524
                            int arg2, int arg3, int arg4, int label_index)
525
{
526
    void *label_ptr;
527

  
528
    switch(cond) {
529
    case TCG_COND_NE:
530
        tcg_out_brcond(s, TCG_COND_NE, arg2, arg4, label_index);
531
        tcg_out_brcond(s, TCG_COND_NE, arg1, arg3, label_index);
532
        return;
533
    case TCG_COND_EQ:
534
        break;
535
    case TCG_COND_LT:
536
    case TCG_COND_LE:
537
        tcg_out_brcond(s, TCG_COND_LT, arg2, arg4, label_index);
538
        break;
539
    case TCG_COND_GT:
540
    case TCG_COND_GE:
541
        tcg_out_brcond(s, TCG_COND_GT, arg2, arg4, label_index);
542
        break;
543
    case TCG_COND_LTU:
544
    case TCG_COND_LEU:
545
        tcg_out_brcond(s, TCG_COND_LTU, arg2, arg4, label_index);
546
        break;
547
    case TCG_COND_GTU:
548
    case TCG_COND_GEU:
549
        tcg_out_brcond(s, TCG_COND_GTU, arg2, arg4, label_index);
550
        break;
551
    default:
552
        tcg_abort();
553
    }
554

  
555
    label_ptr = s->code_ptr;
556
    tcg_out_opc_imm(s, OPC_BNE, arg2, arg4, 0);
557
    tcg_out_nop(s);
558

  
559
    switch(cond) {
560
    case TCG_COND_EQ:
561
        tcg_out_brcond(s, TCG_COND_EQ, arg1, arg3, label_index);
562
        break;
563
    case TCG_COND_LT:
564
    case TCG_COND_LTU:
565
        tcg_out_brcond(s, TCG_COND_LTU, arg1, arg3, label_index);
566
        break;
567
    case TCG_COND_LE:
568
    case TCG_COND_LEU:
569
        tcg_out_brcond(s, TCG_COND_LEU, arg1, arg3, label_index);
570
        break;
571
    case TCG_COND_GT:
572
    case TCG_COND_GTU:
573
        tcg_out_brcond(s, TCG_COND_GTU, arg1, arg3, label_index);
574
        break;
575
    case TCG_COND_GE:
576
    case TCG_COND_GEU:
577
        tcg_out_brcond(s, TCG_COND_GEU, arg1, arg3, label_index);
578
        break;
579
    default:
580
        tcg_abort();
581
    }
582

  
583
    reloc_pc16(label_ptr, (tcg_target_long) s->code_ptr);
584
}
585

  
586
#if defined(CONFIG_SOFTMMU)
587

  
588
#include "../../softmmu_defs.h"
589

  
590
static void *qemu_ld_helpers[4] = {
591
    __ldb_mmu,
592
    __ldw_mmu,
593
    __ldl_mmu,
594
    __ldq_mmu,
595
};
596

  
597
static void *qemu_st_helpers[4] = {
598
    __stb_mmu,
599
    __stw_mmu,
600
    __stl_mmu,
601
    __stq_mmu,
602
};
603
#endif
604

  
605
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
606
                            int opc)
607
{
608
    int addr_regl, addr_reg1, addr_meml;
609
    int data_regl, data_regh, data_reg1, data_reg2;
610
    int mem_index, s_bits;
611
#if defined(CONFIG_SOFTMMU)
612
    void *label1_ptr, *label2_ptr;
613
    int sp_args;
614
#endif
615
#if TARGET_LONG_BITS == 64
616
# if defined(CONFIG_SOFTMMU)
617
    uint8_t *label3_ptr;
618
# endif
619
    int addr_regh, addr_reg2, addr_memh;
620
#endif
621
    data_regl = *args++;
622
    if (opc == 3)
623
        data_regh = *args++;
624
    else
625
        data_regh = 0;
626
    addr_regl = *args++;
627
#if TARGET_LONG_BITS == 64
628
    addr_regh = *args++;
629
#endif
630
    mem_index = *args;
631
    s_bits = opc & 3;
632

  
633
    if (opc == 3) {
634
#if defined(TCG_TARGET_WORDS_BIGENDIAN)
635
        data_reg1 = data_regh;
636
        data_reg2 = data_regl;
637
#else
638
        data_reg1 = data_regl;
639
        data_reg2 = data_regh;
640
#endif
641
    } else {
642
        data_reg1 = data_regl;
643
        data_reg2 = 0;
644
    }
645
#if TARGET_LONG_BITS == 64
646
# if defined(TCG_TARGET_WORDS_BIGENDIAN)
647
    addr_reg1 = addr_regh;
648
    addr_reg2 = addr_regl;
649
    addr_memh = 0;
650
    addr_meml = 4;
651
# else
652
    addr_reg1 = addr_regl;
653
    addr_reg2 = addr_regh;
654
    addr_memh = 4;
655
    addr_meml = 0;
656
# endif
657
#else
658
    addr_reg1 = addr_regl;
659
    addr_meml = 0;
660
#endif
661

  
662
#if defined(CONFIG_SOFTMMU)
663
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
664
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
665
    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
666
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
667
                    offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_meml);
668
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
669
    tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
670

  
671
# if TARGET_LONG_BITS == 64
672
    label3_ptr = s->code_ptr;
673
    tcg_out_opc_imm(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT, 0);
674
    tcg_out_nop(s);
675

  
676
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
677
                    offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_memh);
678

  
679
    label1_ptr = s->code_ptr;
680
    tcg_out_opc_imm(s, OPC_BEQ, addr_regh, TCG_REG_AT, 0);
681
    tcg_out_nop(s);
682

  
683
    reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
684
# else
685
    label1_ptr = s->code_ptr;
686
    tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT, 0);
687
    tcg_out_nop(s);
688
# endif
689

  
690
    /* slow path */
691
    sp_args = TCG_REG_A0;
692
    tcg_out_mov(s, sp_args++, addr_reg1);
693
# if TARGET_LONG_BITS == 64
694
    tcg_out_mov(s, sp_args++, addr_reg2);
695
# endif
696
    tcg_out_movi(s, TCG_TYPE_I32, sp_args++, mem_index);
697
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]);
698
    tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
699
    tcg_out_nop(s);
700

  
701
    switch(opc) {
702
    case 0:
703
        tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xff);
704
        break;
705
    case 0 | 4:
706
        tcg_out_opc_sa(s, OPC_SLL, TCG_REG_V0, TCG_REG_V0, 24);
707
        tcg_out_opc_sa(s, OPC_SRA, data_reg1, TCG_REG_V0, 24);
708
        break;
709
    case 1:
710
        tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xffff);
711
        break;
712
    case 1 | 4:
713
        tcg_out_opc_sa(s, OPC_SLL, TCG_REG_V0, TCG_REG_V0, 16);
714
        tcg_out_opc_sa(s, OPC_SRA, data_reg1, TCG_REG_V0, 16);
715
        break;
716
    case 2:
717
        tcg_out_mov(s, data_reg1, TCG_REG_V0);
718
        break;
719
    case 3:
720
        tcg_out_mov(s, data_reg2, TCG_REG_V1);
721
        tcg_out_mov(s, data_reg1, TCG_REG_V0);
722
        break;
723
    default:
724
        tcg_abort();
725
    }
726

  
727
    label2_ptr = s->code_ptr;
728
    tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO, 0);
729
    tcg_out_nop(s);
730

  
731
    /* label1: fast path */
732
    reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
733

  
734
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_V0, TCG_REG_A0,
735
                    offsetof(CPUState, tlb_table[mem_index][0].addend) + addr_meml);
736
    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_V0, addr_regl);
737

  
738
    addr_reg1 = TCG_REG_V0;
739
#endif
740

  
741
    switch(opc) {
742
    case 0:
743
        tcg_out_opc_imm(s, OPC_LBU, data_reg1, addr_reg1, 0);
744
        break;
745
    case 0 | 4:
746
        tcg_out_opc_imm(s, OPC_LB, data_reg1, addr_reg1, 0);
747
        break;
748
    case 1:
749
        if (TCG_NEED_BSWAP) {
750
            tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, addr_reg1, 0);
751
            tcg_out_bswap16(s, data_reg1, TCG_REG_T0);
752
        } else {
753
            tcg_out_opc_imm(s, OPC_LHU, data_reg1, addr_reg1, 0);
754
        }
755
        break;
756
    case 1 | 4:
757
        if (TCG_NEED_BSWAP) {
758
            tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, addr_reg1, 0);
759
            tcg_out_bswap16s(s, data_reg1, TCG_REG_T0);
760
        } else {
761
            tcg_out_opc_imm(s, OPC_LH, data_reg1, addr_reg1, 0);
762
        }
763
        break;
764
    case 2:
765
        if (TCG_NEED_BSWAP) {
766
            tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, addr_reg1, 0);
767
            tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
768
        } else {
769
            tcg_out_opc_imm(s, OPC_LW, data_reg1, addr_reg1, 0);
770
        }
771
        break;
772
    case 3:
773
#if !defined(CONFIG_SOFTMMU)
774
        tcg_out_mov(s, TCG_REG_V0, addr_reg1);
775
        addr_reg1 = TCG_REG_V0;
776
#endif
777
        if (TCG_NEED_BSWAP) {
778
            tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, addr_reg1, 4);
779
            tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
780
            tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, addr_reg1, 0);
781
            tcg_out_bswap32(s, data_reg2, TCG_REG_T0);
782
        } else {
783
            tcg_out_opc_imm(s, OPC_LW, data_reg1, addr_reg1, 0);
784
            tcg_out_opc_imm(s, OPC_LW, data_reg2, addr_reg1, 4);
785
        }
786
        break;
787
    default:
788
        tcg_abort();
789
    }
790

  
791
#if defined(CONFIG_SOFTMMU)
792
    reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
793
#endif
794
}
795

  
796
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
797
                            int opc)
798
{
799
    int addr_regl, addr_reg1, addr_meml;
800
    int data_regl, data_regh, data_reg1, data_reg2;
801
    int mem_index, s_bits;
802
#if defined(CONFIG_SOFTMMU)
803
    uint8_t *label1_ptr, *label2_ptr;
804
    int sp_args;
805
#endif
806
#if TARGET_LONG_BITS == 64
807
# if defined(CONFIG_SOFTMMU)
808
    uint8_t *label3_ptr;
809
# endif
810
    int addr_regh, addr_reg2, addr_memh;
811
#endif
812

  
813
    data_regl = *args++;
814
    if (opc == 3) {
815
        data_regh = *args++;
816
#if defined(TCG_TARGET_WORDS_BIGENDIAN)
817
        data_reg1 = data_regh;
818
        data_reg2 = data_regl;
819
#else
820
        data_reg1 = data_regl;
821
        data_reg2 = data_regh;
822
#endif
823
    } else {
824
        data_reg1 = data_regl;
825
        data_reg2 = 0;
826
        data_regh = 0;
827
    }
828
    addr_regl = *args++;
829
#if TARGET_LONG_BITS == 64
830
    addr_regh = *args++;
831
# if defined(TCG_TARGET_WORDS_BIGENDIAN)
832
    addr_reg1 = addr_regh;
833
    addr_reg2 = addr_regl;
834
    addr_memh = 0;
835
    addr_meml = 4;
836
# else
837
    addr_reg1 = addr_regl;
838
    addr_reg2 = addr_regh;
839
    addr_memh = 4;
840
    addr_meml = 0;
841
# endif
842
#else
843
    addr_reg1 = addr_regl;
844
    addr_meml = 0;
845
#endif
846
    mem_index = *args;
847
    s_bits = opc;
848

  
849
#if defined(CONFIG_SOFTMMU)
850
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
851
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
852
    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
853
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
854
                    offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_meml);
855
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
856
    tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
857

  
858
# if TARGET_LONG_BITS == 64
859
    label3_ptr = s->code_ptr;
860
    tcg_out_opc_imm(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT, 0);
861
    tcg_out_nop(s);
862

  
863
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
864
                    offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_memh);
865

  
866
    label1_ptr = s->code_ptr;
867
    tcg_out_opc_imm(s, OPC_BEQ, addr_regh, TCG_REG_AT, 0);
868
    tcg_out_nop(s);
869

  
870
    reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
871
# else
872
    label1_ptr = s->code_ptr;
873
    tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT, 0);
874
    tcg_out_nop(s);
875
# endif
876

  
877
    /* slow path */
878
    sp_args = TCG_REG_A0;
879
    tcg_out_mov(s, sp_args++, addr_reg1);
880
# if TARGET_LONG_BITS == 64
881
    tcg_out_mov(s, sp_args++, addr_reg2);
882
# endif
883
    switch(opc) {
884
    case 0:
885
        tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xff);
886
        break;
887
    case 1:
888
        tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xffff);
889
        break;
890
    case 2:
891
        tcg_out_mov(s, sp_args++, data_reg1);
892
        break;
893
    case 3:
894
        sp_args = (sp_args + 1) & ~1;
895
        tcg_out_mov(s, sp_args++, data_reg1);
896
        tcg_out_mov(s, sp_args++, data_reg2);
897
        break;
898
    default:
899
        tcg_abort();
900
    }
901
    if (sp_args > TCG_REG_A3) {
902
        /* Push mem_index on the stack */
903
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, mem_index);
904
        tcg_out_st(s, TCG_TYPE_I32, TCG_REG_AT, TCG_REG_SP, 16);
905
    } else {
906
        tcg_out_movi(s, TCG_TYPE_I32, sp_args, mem_index);
907
    }
908

  
909
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_st_helpers[s_bits]);
910
    tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
911
    tcg_out_nop(s);
912

  
913
    label2_ptr = s->code_ptr;
914
    tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO, 0);
915
    tcg_out_nop(s);
916

  
917
    /* label1: fast path */
918
    reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
919

  
920
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
921
                    offsetof(CPUState, tlb_table[mem_index][0].addend) + addr_meml);
922
    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
923

  
924
    addr_reg1 = TCG_REG_A0;
925
#endif
926

  
927
    switch(opc) {
928
    case 0:
929
        tcg_out_opc_imm(s, OPC_SB, data_reg1, addr_reg1, 0);
930
        break;
931
    case 1:
932
        if (TCG_NEED_BSWAP) {
933
            tcg_out_bswap16(s, TCG_REG_T0, data_reg1);
934
            tcg_out_opc_imm(s, OPC_SH, TCG_REG_T0, addr_reg1, 0);
935
        } else {
936
            tcg_out_opc_imm(s, OPC_SH, data_reg1, addr_reg1, 0);
937
        }
938
        break;
939
    case 2:
940
        if (TCG_NEED_BSWAP) {
941
            tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
942
            tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, addr_reg1, 0);
943
        } else {
944
            tcg_out_opc_imm(s, OPC_SW, data_reg1, addr_reg1, 0);
945
        }
946
        break;
947
    case 3:
948
        if (TCG_NEED_BSWAP) {
949
            tcg_out_bswap32(s, TCG_REG_T0, data_reg2);
950
            tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, addr_reg1, 0);
951
            tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
952
            tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, addr_reg1, 4);
953
        } else {
954
            tcg_out_opc_imm(s, OPC_SW, data_reg1, addr_reg1, 0);
955
            tcg_out_opc_imm(s, OPC_SW, data_reg2, addr_reg1, 4);
956
        }
957
        break;
958
    default:
959
        tcg_abort();
960
    }
961

  
962
#if defined(CONFIG_SOFTMMU)
963
    reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
964
#endif
965
}
966

  
967
static inline void tcg_out_op(TCGContext *s, int opc,
968
                              const TCGArg *args, const int *const_args)
969
{
970
    switch(opc) {
971
    case INDEX_op_exit_tb:
972
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_V0, args[0]);
973
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, (tcg_target_long)tb_ret_addr);
974
        tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
975
        tcg_out_nop(s);
976
        break;
977
    case INDEX_op_goto_tb:
978
        if (s->tb_jmp_offset) {
979
            /* direct jump method */
980
            tcg_abort();
981
        } else {
982
            /* indirect jump method */
983
            tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, (tcg_target_long)(s->tb_next + args[0]));
984
            tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_AT, TCG_REG_AT, 0);
985
            tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
986
        }
987
        tcg_out_nop(s);
988
        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
989
        break;
990
    case INDEX_op_call:
991
        tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, args[0], 0);
992
        tcg_out_nop(s);
993
        break;
994
    case INDEX_op_jmp:
995
        tcg_out_opc_reg(s, OPC_JR, 0, args[0], 0);
996
        tcg_out_nop(s);
997
        break;
998
    case INDEX_op_br:
999
        tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, args[0]);
1000
        break;
1001

  
1002
    case INDEX_op_mov_i32:
1003
        tcg_out_mov(s, args[0], args[1]);
1004
        break;
1005
    case INDEX_op_movi_i32:
1006
        tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1007
        break;
1008

  
1009
    case INDEX_op_ld8u_i32:
1010
	tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]);
1011
        break;
1012
    case INDEX_op_ld8s_i32:
1013
        tcg_out_ldst(s, OPC_LB, args[0], args[1], args[2]);
1014
        break;
1015
    case INDEX_op_ld16u_i32:
1016
        tcg_out_ldst(s, OPC_LHU, args[0], args[1], args[2]);
1017
        break;
1018
    case INDEX_op_ld16s_i32:
1019
        tcg_out_ldst(s, OPC_LH, args[0], args[1], args[2]);
1020
        break;
1021
    case INDEX_op_ld_i32:
1022
        tcg_out_ldst(s, OPC_LW, args[0], args[1], args[2]);
1023
        break;
1024
    case INDEX_op_st8_i32:
1025
        tcg_out_ldst(s, OPC_SB, args[0], args[1], args[2]);
1026
        break;
1027
    case INDEX_op_st16_i32:
1028
        tcg_out_ldst(s, OPC_SH, args[0], args[1], args[2]);
1029
        break;
1030
    case INDEX_op_st_i32:
1031
        tcg_out_ldst(s, OPC_SW, args[0], args[1], args[2]);
1032
        break;
1033

  
1034
    case INDEX_op_add_i32:
1035
        if (const_args[2]) {
1036
            tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], args[2]);
1037
        } else {
1038
            tcg_out_opc_reg(s, OPC_ADDU, args[0], args[1], args[2]);
1039
        }
1040
        break;
1041
    case INDEX_op_add2_i32:
1042
        if (const_args[4]) {
1043
            tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], args[4]);
1044
        } else {
1045
            tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, args[2], args[4]);
1046
        }
1047
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, TCG_REG_AT, args[2]);
1048
        if (const_args[5]) {
1049
            tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], args[5]);
1050
        } else {
1051
             tcg_out_opc_reg(s, OPC_ADDU, args[1], args[3], args[5]);
1052
        }
1053
        tcg_out_opc_reg(s, OPC_ADDU, args[1], args[1], TCG_REG_T0);
1054
        tcg_out_mov(s, args[0], TCG_REG_AT);
1055
        break;
1056
    case INDEX_op_sub_i32:
1057
        if (const_args[2]) {
1058
            tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], -args[2]);
1059
        } else {
1060
            tcg_out_opc_reg(s, OPC_SUBU, args[0], args[1], args[2]);
1061
        }
1062
        break;
1063
    case INDEX_op_sub2_i32:
1064
        if (const_args[4]) {
1065
            tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], -args[4]);
1066
        } else {
1067
            tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, args[2], args[4]);
1068
        }
1069
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, args[2], TCG_REG_AT);
1070
        if (const_args[5]) {
1071
            tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], -args[5]);
1072
        } else {
1073
             tcg_out_opc_reg(s, OPC_SUBU, args[1], args[3], args[5]);
1074
        }
1075
        tcg_out_opc_reg(s, OPC_SUBU, args[1], args[1], TCG_REG_T0);
1076
        tcg_out_mov(s, args[0], TCG_REG_AT);
1077
        break;
1078
    case INDEX_op_mul_i32:
1079
        tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
1080
        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1081
        break;
1082
    case INDEX_op_mulu2_i32:
1083
        tcg_out_opc_reg(s, OPC_MULTU, 0, args[2], args[3]);
1084
        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1085
        tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
1086
        break;
1087
    case INDEX_op_div_i32:
1088
        tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1089
        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1090
        break;
1091
    case INDEX_op_divu_i32:
1092
        tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1093
        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1094
        break;
1095
    case INDEX_op_rem_i32:
1096
        tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1097
        tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1098
        break;
1099
    case INDEX_op_remu_i32:
1100
        tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1101
        tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1102
        break;
1103

  
1104
    case INDEX_op_and_i32:
1105
        if (const_args[2]) {
1106
            tcg_out_opc_imm(s, OPC_ANDI, args[0], args[1], args[2]);
1107
        } else {
1108
            tcg_out_opc_reg(s, OPC_AND, args[0], args[1], args[2]);
1109
        }
1110
        break;
1111
    case INDEX_op_or_i32:
1112
        if (const_args[2]) {
1113
            tcg_out_opc_imm(s, OPC_ORI, args[0], args[1], args[2]);
1114
        } else {
1115
            tcg_out_opc_reg(s, OPC_OR, args[0], args[1], args[2]);
1116
        }
1117
        break;
1118
    case INDEX_op_not_i32:
1119
        tcg_out_opc_reg(s, OPC_NOR, args[0], args[1], args[1]);
1120
        break;
1121
    case INDEX_op_xor_i32:
1122
        if (const_args[2]) {
1123
            tcg_out_opc_imm(s, OPC_XORI, args[0], args[1], args[2]);
1124
        } else {
1125
            tcg_out_opc_reg(s, OPC_XOR, args[0], args[1], args[2]);
1126
        }
1127
        break;
1128

  
1129
    case INDEX_op_sar_i32:
1130
        if (const_args[2]) {
1131
            tcg_out_opc_sa(s, OPC_SRA, args[0], args[1], args[2]);
1132
        } else {
1133
            tcg_out_opc_reg(s, OPC_SRAV, args[0], args[2], args[1]);
1134
        }
1135
        break;
1136
    case INDEX_op_shl_i32:
1137
        if (const_args[2]) {
1138
            tcg_out_opc_sa(s, OPC_SLL, args[0], args[1], args[2]);
1139
        } else {
1140
            tcg_out_opc_reg(s, OPC_SLLV, args[0], args[2], args[1]);
1141
        }
1142
        break;
1143
    case INDEX_op_shr_i32:
1144
        if (const_args[2]) {
1145
            tcg_out_opc_sa(s, OPC_SRL, args[0], args[1], args[2]);
1146
        } else {
1147
            tcg_out_opc_reg(s, OPC_SRLV, args[0], args[2], args[1]);
1148
        }
1149
        break;
1150

  
1151
    case INDEX_op_brcond_i32:
1152
        tcg_out_brcond(s, args[2], args[0], args[1], args[3]);
1153
        break;
1154
    case INDEX_op_brcond2_i32:
1155
        tcg_out_brcond2(s, args[4], args[0], args[1], args[2], args[3], args[5]);
1156
        break;
1157

  
1158
    case INDEX_op_qemu_ld8u:
1159
        tcg_out_qemu_ld(s, args, 0);
1160
        break;
1161
    case INDEX_op_qemu_ld8s:
1162
        tcg_out_qemu_ld(s, args, 0 | 4);
1163
        break;
1164
    case INDEX_op_qemu_ld16u:
1165
        tcg_out_qemu_ld(s, args, 1);
1166
        break;
1167
    case INDEX_op_qemu_ld16s:
1168
        tcg_out_qemu_ld(s, args, 1 | 4);
1169
        break;
1170
    case INDEX_op_qemu_ld32u:
1171
        tcg_out_qemu_ld(s, args, 2);
1172
        break;
1173
    case INDEX_op_qemu_ld64:
1174
        tcg_out_qemu_ld(s, args, 3);
1175
        break;
1176
    case INDEX_op_qemu_st8:
1177
        tcg_out_qemu_st(s, args, 0);
1178
        break;
1179
    case INDEX_op_qemu_st16:
1180
        tcg_out_qemu_st(s, args, 1);
1181
        break;
1182
    case INDEX_op_qemu_st32:
1183
        tcg_out_qemu_st(s, args, 2);
1184
        break;
1185
    case INDEX_op_qemu_st64:
1186
        tcg_out_qemu_st(s, args, 3);
1187
        break;
1188

  
1189
    default:
1190
        tcg_abort();
1191
    }
1192
}
1193

  
1194
static const TCGTargetOpDef mips_op_defs[] = {
1195
    { INDEX_op_exit_tb, { } },
1196
    { INDEX_op_goto_tb, { } },
1197
    { INDEX_op_call, { "C" } },
1198
    { INDEX_op_jmp, { "r" } },
1199
    { INDEX_op_br, { } },
1200

  
1201
    { INDEX_op_mov_i32, { "r", "r" } },
1202
    { INDEX_op_movi_i32, { "r" } },
1203
    { INDEX_op_ld8u_i32, { "r", "r" } },
1204
    { INDEX_op_ld8s_i32, { "r", "r" } },
1205
    { INDEX_op_ld16u_i32, { "r", "r" } },
1206
    { INDEX_op_ld16s_i32, { "r", "r" } },
1207
    { INDEX_op_ld_i32, { "r", "r" } },
1208
    { INDEX_op_st8_i32, { "rZ", "r" } },
1209
    { INDEX_op_st16_i32, { "rZ", "r" } },
1210
    { INDEX_op_st_i32, { "rZ", "r" } },
1211

  
1212
    { INDEX_op_add_i32, { "r", "rZ", "rJZ" } },
1213
    { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
1214
    { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
1215
    { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
1216
    { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
1217
    { INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
1218
    { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
1219
    { INDEX_op_sub_i32, { "r", "rZ", "rJZ" } },
1220

  
1221
    { INDEX_op_and_i32, { "r", "rZ", "rIZ" } },
1222
    { INDEX_op_not_i32, { "r", "rZ" } },
1223
    { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
1224
    { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
1225

  
1226
    { INDEX_op_shl_i32, { "r", "rZ", "riZ" } },
1227
    { INDEX_op_shr_i32, { "r", "rZ", "riZ" } },
1228
    { INDEX_op_sar_i32, { "r", "rZ", "riZ" } },
1229

  
1230
    { INDEX_op_brcond_i32, { "rZ", "rZ" } },
1231

  
1232
    { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1233
    { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1234
    { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
1235

  
1236
#if TARGET_LONG_BITS == 32
1237
    { INDEX_op_qemu_ld8u, { "L", "lZ" } },
1238
    { INDEX_op_qemu_ld8s, { "L", "lZ" } },
1239
    { INDEX_op_qemu_ld16u, { "L", "lZ" } },
1240
    { INDEX_op_qemu_ld16s, { "L", "lZ" } },
1241
    { INDEX_op_qemu_ld32u, { "L", "lZ" } },
1242
    { INDEX_op_qemu_ld64, { "L", "L", "lZ" } },
1243

  
1244
    { INDEX_op_qemu_st8, { "SZ", "SZ" } },
1245
    { INDEX_op_qemu_st16, { "SZ", "SZ" } },
1246
    { INDEX_op_qemu_st32, { "SZ", "SZ" } },
1247
    { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ" } },
1248
#else
1249
    { INDEX_op_qemu_ld8u, { "L", "lZ", "lZ" } },
1250
    { INDEX_op_qemu_ld8s, { "L", "lZ", "lZ" } },
1251
    { INDEX_op_qemu_ld16u, { "L", "lZ", "lZ" } },
1252
    { INDEX_op_qemu_ld16s, { "L", "lZ", "lZ" } },
1253
    { INDEX_op_qemu_ld32u, { "L", "lZ", "lZ" } },
1254
    { INDEX_op_qemu_ld64, { "L", "L", "lZ", "lZ" } },
1255

  
1256
    { INDEX_op_qemu_st8, { "SZ", "SZ", "SZ" } },
1257
    { INDEX_op_qemu_st16, { "SZ", "SZ", "SZ" } },
1258
    { INDEX_op_qemu_st32, { "SZ", "SZ", "SZ" } },
1259
    { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ", "SZ" } },
1260
#endif
1261
    { -1 },
1262
};
1263

  
1264
static int tcg_target_callee_save_regs[] = {
1265
    TCG_REG_S0,
1266
    TCG_REG_S1,
1267
    TCG_REG_S2,
1268
    TCG_REG_S3,
1269
    TCG_REG_S4,
1270
    TCG_REG_S5,
1271
    TCG_REG_S6,
1272
    TCG_REG_S7,
1273
    TCG_REG_GP,
1274
    /* TCG_REG_FP, */ /* currently used for the global env, so np
1275
                         need to save */
1276
    TCG_REG_RA,       /* should be last for ABI compliance */
1277
};
1278

  
1279
/* Generate global QEMU prologue and epilogue code */
1280
void tcg_target_qemu_prologue(TCGContext *s)
1281
{
1282
    int i, frame_size;
1283

  
1284
    /* reserve some stack space */
1285
    frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1286
                 + TCG_STATIC_CALL_ARGS_SIZE;
1287
    frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1288
                 ~(TCG_TARGET_STACK_ALIGN - 1);
1289

  
1290
    /* TB prologue */
1291
    tcg_out_addi(s, TCG_REG_SP, -frame_size);
1292
    for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1293
        tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1294
                   TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1295
    }
1296

  
1297
    /* Call generated code */
1298
    tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_A0, 0);
1299
    tcg_out_nop(s);
1300
    tb_ret_addr = s->code_ptr;
1301

  
1302
    /* TB epilogue */
1303
    for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1304
        tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1305
                   TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1306
    }
1307

  
1308
    tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
1309
    tcg_out_addi(s, TCG_REG_SP, frame_size);
1310
}
1311

  
1312
void tcg_target_init(TCGContext *s)
1313
{
1314
    tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
1315
    tcg_regset_set(tcg_target_call_clobber_regs,
1316
                   (1 << TCG_REG_V0) |
1317
                   (1 << TCG_REG_V1) |
1318
                   (1 << TCG_REG_A0) |
1319
                   (1 << TCG_REG_A1) |
1320
                   (1 << TCG_REG_A2) |
1321
                   (1 << TCG_REG_A3) |
1322
                   (1 << TCG_REG_T1) |
1323
                   (1 << TCG_REG_T2) |
1324
                   (1 << TCG_REG_T3) |
1325
                   (1 << TCG_REG_T4) |
1326
                   (1 << TCG_REG_T5) |
1327
                   (1 << TCG_REG_T6) |
1328
                   (1 << TCG_REG_T7) |
1329
                   (1 << TCG_REG_T8) |
1330
                   (1 << TCG_REG_T9));
1331

  
1332
    tcg_regset_clear(s->reserved_regs);
1333
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
1334
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0);   /* kernel use only */
1335
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1);   /* kernel use only */
1336
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_AT);   /* internal use */
1337
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_T0);   /* internal use */
1338
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA);   /* return address */
1339
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);   /* stack pointer */
1340

  
1341
    tcg_add_target_add_op_defs(mips_op_defs);
1342
}
b/tcg/mips/tcg-target.h
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
#define TCG_TARGET_MIPS 1
27

  
28
#define TCG_TARGET_REG_BITS 32
29
#ifdef __MIPSEB__
30
# define TCG_TARGET_WORDS_BIGENDIAN
31
#endif
32

  
33
#define TCG_TARGET_NB_REGS 32
34

  
35
enum {
36
    TCG_REG_ZERO = 0,
37
    TCG_REG_AT,
38
    TCG_REG_V0,
39
    TCG_REG_V1,
40
    TCG_REG_A0,
41
    TCG_REG_A1,
42
    TCG_REG_A2,
43
    TCG_REG_A3,
44
    TCG_REG_T0,
45
    TCG_REG_T1,
46
    TCG_REG_T2,
47
    TCG_REG_T3,
48
    TCG_REG_T4,
49
    TCG_REG_T5,
50
    TCG_REG_T6,
51
    TCG_REG_T7,
52
    TCG_REG_S0,
53
    TCG_REG_S1,
54
    TCG_REG_S2,
55
    TCG_REG_S3,
56
    TCG_REG_S4,
57
    TCG_REG_S5,
58
    TCG_REG_S6,
59
    TCG_REG_S7,
60
    TCG_REG_T8,
61
    TCG_REG_T9,
62
    TCG_REG_K0,
63
    TCG_REG_K1,
64
    TCG_REG_GP,
65
    TCG_REG_SP,
66
    TCG_REG_FP,
67
    TCG_REG_RA,
68
};
69

  
70
#define TCG_CT_CONST_ZERO 0x100
71
#define TCG_CT_CONST_U16  0x200
72
#define TCG_CT_CONST_S16  0x400
73

  
74
/* used for function call generation */
75
#define TCG_REG_CALL_STACK TCG_REG_SP
76
#define TCG_TARGET_STACK_ALIGN 8
77
#define TCG_TARGET_CALL_STACK_OFFSET 16
78
#define TCG_TARGET_CALL_ALIGN_ARGS 1
79

  
80
/* optional instructions */
81
#define TCG_TARGET_HAS_div_i32
82
#define TCG_TARGET_HAS_not_i32
83
#undef TCG_TARGET_HAS_ext8s_i32
84
#undef TCG_TARGET_HAS_ext16s_i32
85
#undef TCG_TARGET_HAS_bswap32_i32
86
#undef TCG_TARGET_HAS_bswap16_i32
87
#undef TCG_TARGET_HAS_rot_i32
88

  
89
/* optional instructions automatically implemented */
90
#undef TCG_TARGET_HAS_neg_i32      /* sub  rd, zero, rt   */
91
#undef TCG_TARGET_HAS_ext8u_i32    /* andi rt, rs, 0xff   */
92
#undef TCG_TARGET_HAS_ext16u_i32   /* andi rt, rs, 0xffff */
93

  
94
/* Note: must be synced with dyngen-exec.h */
95
#define TCG_AREG0 TCG_REG_FP
96
#define TCG_AREG1 TCG_REG_S0
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff