Statistics
| Branch: | Revision:

root / tcg / mips / tcg-target.c @ 6d8ff4d8

History | View | Annotate | Download (44.4 kB)

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
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
226
#if defined(CONFIG_SOFTMMU)
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_SLTI     = 0x0A << 26,
278
    OPC_SLTIU    = 0x0B << 26,
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
 */
319
static 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
 */
333
static 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 branch
346
 */
347
static inline void tcg_out_opc_br(TCGContext *s, int opc, int rt, int rs)
348
{
349
    /* We need to keep the offset unchanged for retranslation */
350
    uint16_t offset = (uint16_t)(*(uint32_t *) &s->code_ptr);
351

    
352
    tcg_out_opc_imm(s, opc, rt, rs, offset);
353
}
354

    
355
/*
356
 * Type sa
357
 */
358
static inline void tcg_out_opc_sa(TCGContext *s, int opc, int rd, int rt, int sa)
359
{
360
    int32_t inst;
361

    
362
    inst = opc;
363
    inst |= (rt & 0x1F) << 16;
364
    inst |= (rd & 0x1F) << 11;
365
    inst |= (sa & 0x1F) <<  6;
366
    tcg_out32(s, inst);
367

    
368
}
369

    
370
static inline void tcg_out_nop(TCGContext *s)
371
{
372
    tcg_out32(s, 0);
373
}
374

    
375
static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
376
{
377
    tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
378
}
379

    
380
static inline void tcg_out_movi(TCGContext *s, TCGType type,
381
                                int reg, int32_t arg)
382
{
383
    if (arg == (int16_t)arg) {
384
        tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
385
    } else if (arg == (uint16_t)arg) {
386
        tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
387
    } else {
388
        tcg_out_opc_imm(s, OPC_LUI, reg, 0, arg >> 16);
389
        tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0xffff);
390
    }
391
}
392

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

    
400
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
401
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0x00ff);
402

    
403
    tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
404
    tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
405
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
406
}
407

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

    
415
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
416
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff);
417

    
418
    tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
419
    tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
420
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
421
}
422

    
423
static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg)
424
{
425
    /* ret and arg must be different and can't be register at */
426
    if (ret == arg || ret == TCG_REG_AT || arg == TCG_REG_AT) {
427
        tcg_abort();
428
    }
429

    
430
    tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
431

    
432
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 24);
433
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
434

    
435
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, arg, 0xff00);
436
    tcg_out_opc_sa(s, OPC_SLL, TCG_REG_AT, TCG_REG_AT, 8);
437
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
438

    
439
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
440
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff00);
441
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
442
}
443

    
444
static inline void tcg_out_ldst(TCGContext *s, int opc, int arg,
445
                              int arg1, tcg_target_long arg2)
446
{
447
    if (arg2 == (int16_t) arg2) {
448
        tcg_out_opc_imm(s, opc, arg, arg1, arg2);
449
    } else {
450
        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, arg2);
451
        tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, TCG_REG_AT, arg1);
452
        tcg_out_opc_imm(s, opc, arg, TCG_REG_AT, 0);
453
    }
454
}
455

    
456
static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg,
457
                              int arg1, tcg_target_long arg2)
458
{
459
    tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
460
}
461

    
462
static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
463
                              int arg1, tcg_target_long arg2)
464
{
465
    tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
466
}
467

    
468
static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
469
{
470
    if (val == (int16_t)val) {
471
        tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
472
    } else {
473
        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, val);
474
        tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_REG_AT);
475
    }
476
}
477

    
478
static void tcg_out_brcond(TCGContext *s, TCGCond cond, int arg1,
479
                           int arg2, int label_index)
480
{
481
    TCGLabel *l = &s->labels[label_index];
482

    
483
    switch (cond) {
484
    case TCG_COND_EQ:
485
        tcg_out_opc_br(s, OPC_BEQ, arg1, arg2);
486
        break;
487
    case TCG_COND_NE:
488
        tcg_out_opc_br(s, OPC_BNE, arg1, arg2);
489
        break;
490
    case TCG_COND_LT:
491
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
492
        tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
493
        break;
494
    case TCG_COND_LTU:
495
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
496
        tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
497
        break;
498
    case TCG_COND_GE:
499
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
500
        tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
501
        break;
502
    case TCG_COND_GEU:
503
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
504
        tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
505
        break;
506
    case TCG_COND_LE:
507
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
508
        tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
509
        break;
510
    case TCG_COND_LEU:
511
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
512
        tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
513
        break;
514
    case TCG_COND_GT:
515
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
516
        tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
517
        break;
518
    case TCG_COND_GTU:
519
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
520
        tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
521
        break;
522
    default:
523
        tcg_abort();
524
        break;
525
    }
526
    if (l->has_value) {
527
        reloc_pc16(s->code_ptr - 4, l->u.value);
528
    } else {
529
        tcg_out_reloc(s, s->code_ptr - 4, R_MIPS_PC16, label_index, 0);
530
    }
531
    tcg_out_nop(s);
532
}
533

    
534
/* XXX: we implement it at the target level to avoid having to
535
   handle cross basic blocks temporaries */
536
static void tcg_out_brcond2(TCGContext *s, TCGCond cond, int arg1,
537
                            int arg2, int arg3, int arg4, int label_index)
538
{
539
    void *label_ptr;
540

    
541
    switch(cond) {
542
    case TCG_COND_NE:
543
        tcg_out_brcond(s, TCG_COND_NE, arg2, arg4, label_index);
544
        tcg_out_brcond(s, TCG_COND_NE, arg1, arg3, label_index);
545
        return;
546
    case TCG_COND_EQ:
547
        break;
548
    case TCG_COND_LT:
549
    case TCG_COND_LE:
550
        tcg_out_brcond(s, TCG_COND_LT, arg2, arg4, label_index);
551
        break;
552
    case TCG_COND_GT:
553
    case TCG_COND_GE:
554
        tcg_out_brcond(s, TCG_COND_GT, arg2, arg4, label_index);
555
        break;
556
    case TCG_COND_LTU:
557
    case TCG_COND_LEU:
558
        tcg_out_brcond(s, TCG_COND_LTU, arg2, arg4, label_index);
559
        break;
560
    case TCG_COND_GTU:
561
    case TCG_COND_GEU:
562
        tcg_out_brcond(s, TCG_COND_GTU, arg2, arg4, label_index);
563
        break;
564
    default:
565
        tcg_abort();
566
    }
567

    
568
    label_ptr = s->code_ptr;
569
    tcg_out_opc_br(s, OPC_BNE, arg2, arg4);
570
    tcg_out_nop(s);
571

    
572
    switch(cond) {
573
    case TCG_COND_EQ:
574
        tcg_out_brcond(s, TCG_COND_EQ, arg1, arg3, label_index);
575
        break;
576
    case TCG_COND_LT:
577
    case TCG_COND_LTU:
578
        tcg_out_brcond(s, TCG_COND_LTU, arg1, arg3, label_index);
579
        break;
580
    case TCG_COND_LE:
581
    case TCG_COND_LEU:
582
        tcg_out_brcond(s, TCG_COND_LEU, arg1, arg3, label_index);
583
        break;
584
    case TCG_COND_GT:
585
    case TCG_COND_GTU:
586
        tcg_out_brcond(s, TCG_COND_GTU, arg1, arg3, label_index);
587
        break;
588
    case TCG_COND_GE:
589
    case TCG_COND_GEU:
590
        tcg_out_brcond(s, TCG_COND_GEU, arg1, arg3, label_index);
591
        break;
592
    default:
593
        tcg_abort();
594
    }
595

    
596
    reloc_pc16(label_ptr, (tcg_target_long) s->code_ptr);
597
}
598

    
599
static void tcg_out_setcond(TCGContext *s, TCGCond cond, int ret,
600
                            int arg1, int arg2)
601
{
602
    switch (cond) {
603
    case TCG_COND_EQ:
604
        if (arg1 == 0) {
605
            tcg_out_opc_imm(s, OPC_SLTIU, ret, arg2, 1);
606
        } else if (arg2 == 0) {
607
            tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, 1);
608
        } else {
609
            tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
610
            tcg_out_opc_imm(s, OPC_SLTIU, ret, ret, 1);
611
        }
612
        break;
613
    case TCG_COND_NE:
614
        if (arg1 == 0) {
615
            tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg2);
616
        } else if (arg2 == 0) {
617
            tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg1);
618
        } else {
619
            tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
620
            tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, ret);
621
        }
622
        break;
623
    case TCG_COND_LT:
624
        tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
625
        break;
626
    case TCG_COND_LTU:
627
        tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
628
        break;
629
    case TCG_COND_GE:
630
        tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
631
        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
632
        break;
633
    case TCG_COND_GEU:
634
        tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
635
        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
636
        break;
637
    case TCG_COND_LE:
638
        tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
639
        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
640
        break;
641
    case TCG_COND_LEU:
642
        tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
643
        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
644
        break;
645
    case TCG_COND_GT:
646
        tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
647
        break;
648
    case TCG_COND_GTU:
649
        tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
650
        break;
651
    default:
652
        tcg_abort();
653
        break;
654
    }
655
}
656

    
657
/* XXX: we implement it at the target level to avoid having to
658
   handle cross basic blocks temporaries */
659
static void tcg_out_setcond2(TCGContext *s, TCGCond cond, int ret,
660
                             int arg1, int arg2, int arg3, int arg4)
661
{
662
    switch (cond) {
663
    case TCG_COND_EQ:
664
        tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_AT, arg2, arg4);
665
        tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg1, arg3);
666
        tcg_out_opc_reg(s, OPC_AND, ret, TCG_REG_AT, TCG_REG_T0);
667
        return;
668
    case TCG_COND_NE:
669
        tcg_out_setcond(s, TCG_COND_NE, TCG_REG_AT, arg2, arg4);
670
        tcg_out_setcond(s, TCG_COND_NE, TCG_REG_T0, arg1, arg3);
671
        tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_AT, TCG_REG_T0);
672
        return;
673
    case TCG_COND_LT:
674
    case TCG_COND_LE:
675
        tcg_out_setcond(s, TCG_COND_LT, TCG_REG_AT, arg2, arg4);
676
        break;
677
    case TCG_COND_GT:
678
    case TCG_COND_GE:
679
        tcg_out_setcond(s, TCG_COND_GT, TCG_REG_AT, arg2, arg4);
680
        break;
681
    case TCG_COND_LTU:
682
    case TCG_COND_LEU:
683
        tcg_out_setcond(s, TCG_COND_LTU, TCG_REG_AT, arg2, arg4);
684
        break;
685
    case TCG_COND_GTU:
686
    case TCG_COND_GEU:
687
        tcg_out_setcond(s, TCG_COND_GTU, TCG_REG_AT, arg2, arg4);
688
        break;
689
    default:
690
        tcg_abort();
691
        break;
692
    }
693

    
694
    tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg2, arg4);
695

    
696
    switch(cond) {
697
    case TCG_COND_LT:
698
    case TCG_COND_LTU:
699
        tcg_out_setcond(s, TCG_COND_LTU, ret, arg1, arg3);
700
        break;
701
    case TCG_COND_LE:
702
    case TCG_COND_LEU:
703
        tcg_out_setcond(s, TCG_COND_LEU, ret, arg1, arg3);
704
        break;
705
    case TCG_COND_GT:
706
    case TCG_COND_GTU:
707
        tcg_out_setcond(s, TCG_COND_GTU, ret, arg1, arg3);
708
        break;
709
    case TCG_COND_GE:
710
    case TCG_COND_GEU:
711
        tcg_out_setcond(s, TCG_COND_GEU, ret, arg1, arg3);
712
        break;
713
    default:
714
        tcg_abort();
715
    }
716

    
717
    tcg_out_opc_reg(s, OPC_AND, ret, ret, TCG_REG_T0);
718
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
719
}
720

    
721
#if defined(CONFIG_SOFTMMU)
722

    
723
#include "../../softmmu_defs.h"
724

    
725
static void *qemu_ld_helpers[4] = {
726
    __ldb_mmu,
727
    __ldw_mmu,
728
    __ldl_mmu,
729
    __ldq_mmu,
730
};
731

    
732
static void *qemu_st_helpers[4] = {
733
    __stb_mmu,
734
    __stw_mmu,
735
    __stl_mmu,
736
    __stq_mmu,
737
};
738
#endif
739

    
740
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
741
                            int opc)
742
{
743
    int addr_regl, addr_reg1, addr_meml;
744
    int data_regl, data_regh, data_reg1, data_reg2;
745
    int mem_index, s_bits;
746
#if defined(CONFIG_SOFTMMU)
747
    void *label1_ptr, *label2_ptr;
748
    int sp_args;
749
#endif
750
#if TARGET_LONG_BITS == 64
751
# if defined(CONFIG_SOFTMMU)
752
    uint8_t *label3_ptr;
753
# endif
754
    int addr_regh, addr_reg2, addr_memh;
755
#endif
756
    data_regl = *args++;
757
    if (opc == 3)
758
        data_regh = *args++;
759
    else
760
        data_regh = 0;
761
    addr_regl = *args++;
762
#if TARGET_LONG_BITS == 64
763
    addr_regh = *args++;
764
#endif
765
    mem_index = *args;
766
    s_bits = opc & 3;
767

    
768
    if (opc == 3) {
769
#if defined(TCG_TARGET_WORDS_BIGENDIAN)
770
        data_reg1 = data_regh;
771
        data_reg2 = data_regl;
772
#else
773
        data_reg1 = data_regl;
774
        data_reg2 = data_regh;
775
#endif
776
    } else {
777
        data_reg1 = data_regl;
778
        data_reg2 = 0;
779
    }
780
#if TARGET_LONG_BITS == 64
781
# if defined(TCG_TARGET_WORDS_BIGENDIAN)
782
    addr_reg1 = addr_regh;
783
    addr_reg2 = addr_regl;
784
    addr_memh = 0;
785
    addr_meml = 4;
786
# else
787
    addr_reg1 = addr_regl;
788
    addr_reg2 = addr_regh;
789
    addr_memh = 4;
790
    addr_meml = 0;
791
# endif
792
#else
793
    addr_reg1 = addr_regl;
794
    addr_meml = 0;
795
#endif
796

    
797
#if defined(CONFIG_SOFTMMU)
798
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
799
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
800
    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
801
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
802
                    offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_meml);
803
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
804
    tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
805

    
806
# if TARGET_LONG_BITS == 64
807
    label3_ptr = s->code_ptr;
808
    tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
809
    tcg_out_nop(s);
810

    
811
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
812
                    offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_memh);
813

    
814
    label1_ptr = s->code_ptr;
815
    tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
816
    tcg_out_nop(s);
817

    
818
    reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
819
# else
820
    label1_ptr = s->code_ptr;
821
    tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
822
    tcg_out_nop(s);
823
# endif
824

    
825
    /* slow path */
826
    sp_args = TCG_REG_A0;
827
    tcg_out_mov(s, sp_args++, addr_reg1);
828
# if TARGET_LONG_BITS == 64
829
    tcg_out_mov(s, sp_args++, addr_reg2);
830
# endif
831
    tcg_out_movi(s, TCG_TYPE_I32, sp_args++, mem_index);
832
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]);
833
    tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
834
    tcg_out_nop(s);
835

    
836
    switch(opc) {
837
    case 0:
838
        tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xff);
839
        break;
840
    case 0 | 4:
841
        tcg_out_opc_sa(s, OPC_SLL, TCG_REG_V0, TCG_REG_V0, 24);
842
        tcg_out_opc_sa(s, OPC_SRA, data_reg1, TCG_REG_V0, 24);
843
        break;
844
    case 1:
845
        tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xffff);
846
        break;
847
    case 1 | 4:
848
        tcg_out_opc_sa(s, OPC_SLL, TCG_REG_V0, TCG_REG_V0, 16);
849
        tcg_out_opc_sa(s, OPC_SRA, data_reg1, TCG_REG_V0, 16);
850
        break;
851
    case 2:
852
        tcg_out_mov(s, data_reg1, TCG_REG_V0);
853
        break;
854
    case 3:
855
        tcg_out_mov(s, data_reg2, TCG_REG_V1);
856
        tcg_out_mov(s, data_reg1, TCG_REG_V0);
857
        break;
858
    default:
859
        tcg_abort();
860
    }
861

    
862
    label2_ptr = s->code_ptr;
863
    tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
864
    tcg_out_nop(s);
865

    
866
    /* label1: fast path */
867
    reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
868

    
869
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
870
                    offsetof(CPUState, tlb_table[mem_index][0].addend) + addr_meml);
871
    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_A0, addr_regl);
872
#else
873
    if (GUEST_BASE == (int16_t)GUEST_BASE) {
874
        tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_V0, addr_reg1, GUEST_BASE);
875
    } else {
876
        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, GUEST_BASE);
877
        tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_V0, addr_reg1);
878
    }
879
#endif
880

    
881
    switch(opc) {
882
    case 0:
883
        tcg_out_opc_imm(s, OPC_LBU, data_reg1, TCG_REG_V0, 0);
884
        break;
885
    case 0 | 4:
886
        tcg_out_opc_imm(s, OPC_LB, data_reg1, TCG_REG_V0, 0);
887
        break;
888
    case 1:
889
        if (TCG_NEED_BSWAP) {
890
            tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
891
            tcg_out_bswap16(s, data_reg1, TCG_REG_T0);
892
        } else {
893
            tcg_out_opc_imm(s, OPC_LHU, data_reg1, TCG_REG_V0, 0);
894
        }
895
        break;
896
    case 1 | 4:
897
        if (TCG_NEED_BSWAP) {
898
            tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
899
            tcg_out_bswap16s(s, data_reg1, TCG_REG_T0);
900
        } else {
901
            tcg_out_opc_imm(s, OPC_LH, data_reg1, TCG_REG_V0, 0);
902
        }
903
        break;
904
    case 2:
905
        if (TCG_NEED_BSWAP) {
906
            tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
907
            tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
908
        } else {
909
            tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
910
        }
911
        break;
912
    case 3:
913
        if (TCG_NEED_BSWAP) {
914
            tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 4);
915
            tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
916
            tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
917
            tcg_out_bswap32(s, data_reg2, TCG_REG_T0);
918
        } else {
919
            tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
920
            tcg_out_opc_imm(s, OPC_LW, data_reg2, TCG_REG_V0, 4);
921
        }
922
        break;
923
    default:
924
        tcg_abort();
925
    }
926

    
927
#if defined(CONFIG_SOFTMMU)
928
    reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
929
#endif
930
}
931

    
932
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
933
                            int opc)
934
{
935
    int addr_regl, addr_reg1, addr_meml;
936
    int data_regl, data_regh, data_reg1, data_reg2;
937
    int mem_index, s_bits;
938
#if defined(CONFIG_SOFTMMU)
939
    uint8_t *label1_ptr, *label2_ptr;
940
    int sp_args;
941
#endif
942
#if TARGET_LONG_BITS == 64
943
# if defined(CONFIG_SOFTMMU)
944
    uint8_t *label3_ptr;
945
# endif
946
    int addr_regh, addr_reg2, addr_memh;
947
#endif
948

    
949
    data_regl = *args++;
950
    if (opc == 3) {
951
        data_regh = *args++;
952
#if defined(TCG_TARGET_WORDS_BIGENDIAN)
953
        data_reg1 = data_regh;
954
        data_reg2 = data_regl;
955
#else
956
        data_reg1 = data_regl;
957
        data_reg2 = data_regh;
958
#endif
959
    } else {
960
        data_reg1 = data_regl;
961
        data_reg2 = 0;
962
        data_regh = 0;
963
    }
964
    addr_regl = *args++;
965
#if TARGET_LONG_BITS == 64
966
    addr_regh = *args++;
967
# if defined(TCG_TARGET_WORDS_BIGENDIAN)
968
    addr_reg1 = addr_regh;
969
    addr_reg2 = addr_regl;
970
    addr_memh = 0;
971
    addr_meml = 4;
972
# else
973
    addr_reg1 = addr_regl;
974
    addr_reg2 = addr_regh;
975
    addr_memh = 4;
976
    addr_meml = 0;
977
# endif
978
#else
979
    addr_reg1 = addr_regl;
980
    addr_meml = 0;
981
#endif
982
    mem_index = *args;
983
    s_bits = opc;
984

    
985
#if defined(CONFIG_SOFTMMU)
986
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
987
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
988
    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
989
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
990
                    offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_meml);
991
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
992
    tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
993

    
994
# if TARGET_LONG_BITS == 64
995
    label3_ptr = s->code_ptr;
996
    tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
997
    tcg_out_nop(s);
998

    
999
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
1000
                    offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_memh);
1001

    
1002
    label1_ptr = s->code_ptr;
1003
    tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
1004
    tcg_out_nop(s);
1005

    
1006
    reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
1007
# else
1008
    label1_ptr = s->code_ptr;
1009
    tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
1010
    tcg_out_nop(s);
1011
# endif
1012

    
1013
    /* slow path */
1014
    sp_args = TCG_REG_A0;
1015
    tcg_out_mov(s, sp_args++, addr_reg1);
1016
# if TARGET_LONG_BITS == 64
1017
    tcg_out_mov(s, sp_args++, addr_reg2);
1018
# endif
1019
    switch(opc) {
1020
    case 0:
1021
        tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xff);
1022
        break;
1023
    case 1:
1024
        tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xffff);
1025
        break;
1026
    case 2:
1027
        tcg_out_mov(s, sp_args++, data_reg1);
1028
        break;
1029
    case 3:
1030
        sp_args = (sp_args + 1) & ~1;
1031
        tcg_out_mov(s, sp_args++, data_reg1);
1032
        tcg_out_mov(s, sp_args++, data_reg2);
1033
        break;
1034
    default:
1035
        tcg_abort();
1036
    }
1037
    if (sp_args > TCG_REG_A3) {
1038
        /* Push mem_index on the stack */
1039
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, mem_index);
1040
        tcg_out_st(s, TCG_TYPE_I32, TCG_REG_AT, TCG_REG_SP, 16);
1041
    } else {
1042
        tcg_out_movi(s, TCG_TYPE_I32, sp_args, mem_index);
1043
    }
1044

    
1045
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_st_helpers[s_bits]);
1046
    tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
1047
    tcg_out_nop(s);
1048

    
1049
    label2_ptr = s->code_ptr;
1050
    tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
1051
    tcg_out_nop(s);
1052

    
1053
    /* label1: fast path */
1054
    reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
1055

    
1056
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
1057
                    offsetof(CPUState, tlb_table[mem_index][0].addend) + addr_meml);
1058
    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
1059
#else
1060
    if (GUEST_BASE == (int16_t)GUEST_BASE) {
1061
        tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_A0, addr_reg1, GUEST_BASE);
1062
    } else {
1063
        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, GUEST_BASE);
1064
        tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_reg1);
1065
    }
1066

    
1067
#endif
1068

    
1069
    switch(opc) {
1070
    case 0:
1071
        tcg_out_opc_imm(s, OPC_SB, data_reg1, TCG_REG_A0, 0);
1072
        break;
1073
    case 1:
1074
        if (TCG_NEED_BSWAP) {
1075
            tcg_out_bswap16(s, TCG_REG_T0, data_reg1);
1076
            tcg_out_opc_imm(s, OPC_SH, TCG_REG_T0, TCG_REG_A0, 0);
1077
        } else {
1078
            tcg_out_opc_imm(s, OPC_SH, data_reg1, TCG_REG_A0, 0);
1079
        }
1080
        break;
1081
    case 2:
1082
        if (TCG_NEED_BSWAP) {
1083
            tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1084
            tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
1085
        } else {
1086
            tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
1087
        }
1088
        break;
1089
    case 3:
1090
        if (TCG_NEED_BSWAP) {
1091
            tcg_out_bswap32(s, TCG_REG_T0, data_reg2);
1092
            tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
1093
            tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1094
            tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 4);
1095
        } else {
1096
            tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
1097
            tcg_out_opc_imm(s, OPC_SW, data_reg2, TCG_REG_A0, 4);
1098
        }
1099
        break;
1100
    default:
1101
        tcg_abort();
1102
    }
1103

    
1104
#if defined(CONFIG_SOFTMMU)
1105
    reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
1106
#endif
1107
}
1108

    
1109
static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1110
                              const TCGArg *args, const int *const_args)
1111
{
1112
    switch(opc) {
1113
    case INDEX_op_exit_tb:
1114
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_V0, args[0]);
1115
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, (tcg_target_long)tb_ret_addr);
1116
        tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1117
        tcg_out_nop(s);
1118
        break;
1119
    case INDEX_op_goto_tb:
1120
        if (s->tb_jmp_offset) {
1121
            /* direct jump method */
1122
            tcg_abort();
1123
        } else {
1124
            /* indirect jump method */
1125
            tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, (tcg_target_long)(s->tb_next + args[0]));
1126
            tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_AT, TCG_REG_AT, 0);
1127
            tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1128
        }
1129
        tcg_out_nop(s);
1130
        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1131
        break;
1132
    case INDEX_op_call:
1133
        tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, args[0], 0);
1134
        tcg_out_nop(s);
1135
        break;
1136
    case INDEX_op_jmp:
1137
        tcg_out_opc_reg(s, OPC_JR, 0, args[0], 0);
1138
        tcg_out_nop(s);
1139
        break;
1140
    case INDEX_op_br:
1141
        tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, args[0]);
1142
        break;
1143

    
1144
    case INDEX_op_mov_i32:
1145
        tcg_out_mov(s, args[0], args[1]);
1146
        break;
1147
    case INDEX_op_movi_i32:
1148
        tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1149
        break;
1150

    
1151
    case INDEX_op_ld8u_i32:
1152
        tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]);
1153
        break;
1154
    case INDEX_op_ld8s_i32:
1155
        tcg_out_ldst(s, OPC_LB, args[0], args[1], args[2]);
1156
        break;
1157
    case INDEX_op_ld16u_i32:
1158
        tcg_out_ldst(s, OPC_LHU, args[0], args[1], args[2]);
1159
        break;
1160
    case INDEX_op_ld16s_i32:
1161
        tcg_out_ldst(s, OPC_LH, args[0], args[1], args[2]);
1162
        break;
1163
    case INDEX_op_ld_i32:
1164
        tcg_out_ldst(s, OPC_LW, args[0], args[1], args[2]);
1165
        break;
1166
    case INDEX_op_st8_i32:
1167
        tcg_out_ldst(s, OPC_SB, args[0], args[1], args[2]);
1168
        break;
1169
    case INDEX_op_st16_i32:
1170
        tcg_out_ldst(s, OPC_SH, args[0], args[1], args[2]);
1171
        break;
1172
    case INDEX_op_st_i32:
1173
        tcg_out_ldst(s, OPC_SW, args[0], args[1], args[2]);
1174
        break;
1175

    
1176
    case INDEX_op_add_i32:
1177
        if (const_args[2]) {
1178
            tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], args[2]);
1179
        } else {
1180
            tcg_out_opc_reg(s, OPC_ADDU, args[0], args[1], args[2]);
1181
        }
1182
        break;
1183
    case INDEX_op_add2_i32:
1184
        if (const_args[4]) {
1185
            tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], args[4]);
1186
        } else {
1187
            tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, args[2], args[4]);
1188
        }
1189
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, TCG_REG_AT, args[2]);
1190
        if (const_args[5]) {
1191
            tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], args[5]);
1192
        } else {
1193
             tcg_out_opc_reg(s, OPC_ADDU, args[1], args[3], args[5]);
1194
        }
1195
        tcg_out_opc_reg(s, OPC_ADDU, args[1], args[1], TCG_REG_T0);
1196
        tcg_out_mov(s, args[0], TCG_REG_AT);
1197
        break;
1198
    case INDEX_op_sub_i32:
1199
        if (const_args[2]) {
1200
            tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], -args[2]);
1201
        } else {
1202
            tcg_out_opc_reg(s, OPC_SUBU, args[0], args[1], args[2]);
1203
        }
1204
        break;
1205
    case INDEX_op_sub2_i32:
1206
        if (const_args[4]) {
1207
            tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], -args[4]);
1208
        } else {
1209
            tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, args[2], args[4]);
1210
        }
1211
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, args[2], TCG_REG_AT);
1212
        if (const_args[5]) {
1213
            tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], -args[5]);
1214
        } else {
1215
             tcg_out_opc_reg(s, OPC_SUBU, args[1], args[3], args[5]);
1216
        }
1217
        tcg_out_opc_reg(s, OPC_SUBU, args[1], args[1], TCG_REG_T0);
1218
        tcg_out_mov(s, args[0], TCG_REG_AT);
1219
        break;
1220
    case INDEX_op_mul_i32:
1221
        tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
1222
        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1223
        break;
1224
    case INDEX_op_mulu2_i32:
1225
        tcg_out_opc_reg(s, OPC_MULTU, 0, args[2], args[3]);
1226
        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1227
        tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
1228
        break;
1229
    case INDEX_op_div_i32:
1230
        tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1231
        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1232
        break;
1233
    case INDEX_op_divu_i32:
1234
        tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1235
        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1236
        break;
1237
    case INDEX_op_rem_i32:
1238
        tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1239
        tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1240
        break;
1241
    case INDEX_op_remu_i32:
1242
        tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1243
        tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1244
        break;
1245

    
1246
    case INDEX_op_and_i32:
1247
        if (const_args[2]) {
1248
            tcg_out_opc_imm(s, OPC_ANDI, args[0], args[1], args[2]);
1249
        } else {
1250
            tcg_out_opc_reg(s, OPC_AND, args[0], args[1], args[2]);
1251
        }
1252
        break;
1253
    case INDEX_op_or_i32:
1254
        if (const_args[2]) {
1255
            tcg_out_opc_imm(s, OPC_ORI, args[0], args[1], args[2]);
1256
        } else {
1257
            tcg_out_opc_reg(s, OPC_OR, args[0], args[1], args[2]);
1258
        }
1259
        break;
1260
    case INDEX_op_nor_i32:
1261
        tcg_out_opc_reg(s, OPC_NOR, args[0], args[1], args[2]);
1262
        break;
1263
    case INDEX_op_not_i32:
1264
        tcg_out_opc_reg(s, OPC_NOR, args[0], TCG_REG_ZERO, args[1]);
1265
        break;
1266
    case INDEX_op_xor_i32:
1267
        if (const_args[2]) {
1268
            tcg_out_opc_imm(s, OPC_XORI, args[0], args[1], args[2]);
1269
        } else {
1270
            tcg_out_opc_reg(s, OPC_XOR, args[0], args[1], args[2]);
1271
        }
1272
        break;
1273

    
1274
    case INDEX_op_sar_i32:
1275
        if (const_args[2]) {
1276
            tcg_out_opc_sa(s, OPC_SRA, args[0], args[1], args[2]);
1277
        } else {
1278
            tcg_out_opc_reg(s, OPC_SRAV, args[0], args[2], args[1]);
1279
        }
1280
        break;
1281
    case INDEX_op_shl_i32:
1282
        if (const_args[2]) {
1283
            tcg_out_opc_sa(s, OPC_SLL, args[0], args[1], args[2]);
1284
        } else {
1285
            tcg_out_opc_reg(s, OPC_SLLV, args[0], args[2], args[1]);
1286
        }
1287
        break;
1288
    case INDEX_op_shr_i32:
1289
        if (const_args[2]) {
1290
            tcg_out_opc_sa(s, OPC_SRL, args[0], args[1], args[2]);
1291
        } else {
1292
            tcg_out_opc_reg(s, OPC_SRLV, args[0], args[2], args[1]);
1293
        }
1294
        break;
1295

    
1296
    case INDEX_op_brcond_i32:
1297
        tcg_out_brcond(s, args[2], args[0], args[1], args[3]);
1298
        break;
1299
    case INDEX_op_brcond2_i32:
1300
        tcg_out_brcond2(s, args[4], args[0], args[1], args[2], args[3], args[5]);
1301
        break;
1302

    
1303
    case INDEX_op_setcond_i32:
1304
        tcg_out_setcond(s, args[3], args[0], args[1], args[2]);
1305
        break;
1306
    case INDEX_op_setcond2_i32:
1307
        tcg_out_setcond2(s, args[5], args[0], args[1], args[2], args[3], args[4]);
1308
        break;
1309

    
1310
    case INDEX_op_qemu_ld8u:
1311
        tcg_out_qemu_ld(s, args, 0);
1312
        break;
1313
    case INDEX_op_qemu_ld8s:
1314
        tcg_out_qemu_ld(s, args, 0 | 4);
1315
        break;
1316
    case INDEX_op_qemu_ld16u:
1317
        tcg_out_qemu_ld(s, args, 1);
1318
        break;
1319
    case INDEX_op_qemu_ld16s:
1320
        tcg_out_qemu_ld(s, args, 1 | 4);
1321
        break;
1322
    case INDEX_op_qemu_ld32:
1323
        tcg_out_qemu_ld(s, args, 2);
1324
        break;
1325
    case INDEX_op_qemu_ld64:
1326
        tcg_out_qemu_ld(s, args, 3);
1327
        break;
1328
    case INDEX_op_qemu_st8:
1329
        tcg_out_qemu_st(s, args, 0);
1330
        break;
1331
    case INDEX_op_qemu_st16:
1332
        tcg_out_qemu_st(s, args, 1);
1333
        break;
1334
    case INDEX_op_qemu_st32:
1335
        tcg_out_qemu_st(s, args, 2);
1336
        break;
1337
    case INDEX_op_qemu_st64:
1338
        tcg_out_qemu_st(s, args, 3);
1339
        break;
1340

    
1341
    default:
1342
        tcg_abort();
1343
    }
1344
}
1345

    
1346
static const TCGTargetOpDef mips_op_defs[] = {
1347
    { INDEX_op_exit_tb, { } },
1348
    { INDEX_op_goto_tb, { } },
1349
    { INDEX_op_call, { "C" } },
1350
    { INDEX_op_jmp, { "r" } },
1351
    { INDEX_op_br, { } },
1352

    
1353
    { INDEX_op_mov_i32, { "r", "r" } },
1354
    { INDEX_op_movi_i32, { "r" } },
1355
    { INDEX_op_ld8u_i32, { "r", "r" } },
1356
    { INDEX_op_ld8s_i32, { "r", "r" } },
1357
    { INDEX_op_ld16u_i32, { "r", "r" } },
1358
    { INDEX_op_ld16s_i32, { "r", "r" } },
1359
    { INDEX_op_ld_i32, { "r", "r" } },
1360
    { INDEX_op_st8_i32, { "rZ", "r" } },
1361
    { INDEX_op_st16_i32, { "rZ", "r" } },
1362
    { INDEX_op_st_i32, { "rZ", "r" } },
1363

    
1364
    { INDEX_op_add_i32, { "r", "rZ", "rJZ" } },
1365
    { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
1366
    { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
1367
    { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
1368
    { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
1369
    { INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
1370
    { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
1371
    { INDEX_op_sub_i32, { "r", "rZ", "rJZ" } },
1372

    
1373
    { INDEX_op_and_i32, { "r", "rZ", "rIZ" } },
1374
    { INDEX_op_nor_i32, { "r", "rZ", "rZ" } },
1375
    { INDEX_op_not_i32, { "r", "rZ" } },
1376
    { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
1377
    { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
1378

    
1379
    { INDEX_op_shl_i32, { "r", "rZ", "riZ" } },
1380
    { INDEX_op_shr_i32, { "r", "rZ", "riZ" } },
1381
    { INDEX_op_sar_i32, { "r", "rZ", "riZ" } },
1382

    
1383
    { INDEX_op_brcond_i32, { "rZ", "rZ" } },
1384
    { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
1385
    { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
1386

    
1387
    { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1388
    { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1389
    { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
1390

    
1391
#if TARGET_LONG_BITS == 32
1392
    { INDEX_op_qemu_ld8u, { "L", "lZ" } },
1393
    { INDEX_op_qemu_ld8s, { "L", "lZ" } },
1394
    { INDEX_op_qemu_ld16u, { "L", "lZ" } },
1395
    { INDEX_op_qemu_ld16s, { "L", "lZ" } },
1396
    { INDEX_op_qemu_ld32, { "L", "lZ" } },
1397
    { INDEX_op_qemu_ld64, { "L", "L", "lZ" } },
1398

    
1399
    { INDEX_op_qemu_st8, { "SZ", "SZ" } },
1400
    { INDEX_op_qemu_st16, { "SZ", "SZ" } },
1401
    { INDEX_op_qemu_st32, { "SZ", "SZ" } },
1402
    { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ" } },
1403
#else
1404
    { INDEX_op_qemu_ld8u, { "L", "lZ", "lZ" } },
1405
    { INDEX_op_qemu_ld8s, { "L", "lZ", "lZ" } },
1406
    { INDEX_op_qemu_ld16u, { "L", "lZ", "lZ" } },
1407
    { INDEX_op_qemu_ld16s, { "L", "lZ", "lZ" } },
1408
    { INDEX_op_qemu_ld32, { "L", "lZ", "lZ" } },
1409
    { INDEX_op_qemu_ld64, { "L", "L", "lZ", "lZ" } },
1410

    
1411
    { INDEX_op_qemu_st8, { "SZ", "SZ", "SZ" } },
1412
    { INDEX_op_qemu_st16, { "SZ", "SZ", "SZ" } },
1413
    { INDEX_op_qemu_st32, { "SZ", "SZ", "SZ" } },
1414
    { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ", "SZ" } },
1415
#endif
1416
    { -1 },
1417
};
1418

    
1419
static int tcg_target_callee_save_regs[] = {
1420
    TCG_REG_S0,
1421
    TCG_REG_S1,
1422
    TCG_REG_S2,
1423
    TCG_REG_S3,
1424
    TCG_REG_S4,
1425
    TCG_REG_S5,
1426
    TCG_REG_S6,
1427
    TCG_REG_S7,
1428
    TCG_REG_GP,
1429
    /* TCG_REG_FP, */ /* currently used for the global env, so np
1430
                         need to save */
1431
    TCG_REG_RA,       /* should be last for ABI compliance */
1432
};
1433

    
1434
/* Generate global QEMU prologue and epilogue code */
1435
void tcg_target_qemu_prologue(TCGContext *s)
1436
{
1437
    int i, frame_size;
1438

    
1439
    /* reserve some stack space */
1440
    frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1441
                 + TCG_STATIC_CALL_ARGS_SIZE;
1442
    frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1443
                 ~(TCG_TARGET_STACK_ALIGN - 1);
1444

    
1445
    /* TB prologue */
1446
    tcg_out_addi(s, TCG_REG_SP, -frame_size);
1447
    for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1448
        tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1449
                   TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1450
    }
1451

    
1452
    /* Call generated code */
1453
    tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_A0, 0);
1454
    tcg_out_nop(s);
1455
    tb_ret_addr = s->code_ptr;
1456

    
1457
    /* TB epilogue */
1458
    for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1459
        tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1460
                   TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1461
    }
1462

    
1463
    tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
1464
    tcg_out_addi(s, TCG_REG_SP, frame_size);
1465
}
1466

    
1467
void tcg_target_init(TCGContext *s)
1468
{
1469
    tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
1470
    tcg_regset_set(tcg_target_call_clobber_regs,
1471
                   (1 << TCG_REG_V0) |
1472
                   (1 << TCG_REG_V1) |
1473
                   (1 << TCG_REG_A0) |
1474
                   (1 << TCG_REG_A1) |
1475
                   (1 << TCG_REG_A2) |
1476
                   (1 << TCG_REG_A3) |
1477
                   (1 << TCG_REG_T1) |
1478
                   (1 << TCG_REG_T2) |
1479
                   (1 << TCG_REG_T3) |
1480
                   (1 << TCG_REG_T4) |
1481
                   (1 << TCG_REG_T5) |
1482
                   (1 << TCG_REG_T6) |
1483
                   (1 << TCG_REG_T7) |
1484
                   (1 << TCG_REG_T8) |
1485
                   (1 << TCG_REG_T9));
1486

    
1487
    tcg_regset_clear(s->reserved_regs);
1488
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
1489
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0);   /* kernel use only */
1490
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1);   /* kernel use only */
1491
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_AT);   /* internal use */
1492
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_T0);   /* internal use */
1493
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA);   /* return address */
1494
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);   /* stack pointer */
1495

    
1496
    tcg_add_target_add_op_defs(mips_op_defs);
1497
}