xref: /qemu/target/cris/translate_v10.c.inc (revision 83ecdb18)
1/*
2 *  CRISv10 emulation for qemu: main translation routines.
3 *
4 *  Copyright (c) 2010 AXIS Communications AB
5 *  Written by Edgar E. Iglesias.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include "qemu/osdep.h"
22#include "crisv10-decode.h"
23
24static const char * const regnames_v10[] =
25{
26    "$r0", "$r1", "$r2", "$r3",
27    "$r4", "$r5", "$r6", "$r7",
28    "$r8", "$r9", "$r10", "$r11",
29    "$r12", "$r13", "$sp", "$pc",
30};
31
32static const char * const pregnames_v10[] =
33{
34    "$bz", "$vr", "$p2", "$p3",
35    "$wz", "$ccr", "$p6-prefix", "$mof",
36    "$dz", "$ibr", "$irp", "$srp",
37    "$bar", "$dccr", "$brp", "$usp",
38};
39
40/* We need this table to handle preg-moves with implicit width.  */
41static const int preg_sizes_v10[] = {
42    1, /* bz.  */
43    1, /* vr.  */
44    1, /* pid. */
45    1, /* srs. */
46    2, /* wz.  */
47    2, 2, 4,
48    4, 4, 4, 4,
49    4, 4, 4, 4,
50};
51
52static inline int dec10_size(unsigned int size)
53{
54    size++;
55    if (size == 3)
56        size++;
57    return size;
58}
59
60static inline void cris_illegal_insn(DisasContext *dc)
61{
62    qemu_log_mask(LOG_GUEST_ERROR, "illegal insn at pc=%x\n", dc->pc);
63    t_gen_raise_exception(EXCP_BREAK);
64    dc->base.is_jmp = DISAS_NORETURN;
65}
66
67static void gen_store_v10_conditional(DisasContext *dc, TCGv addr, TCGv val,
68                       unsigned int size, int mem_index)
69{
70    TCGLabel *l1 = gen_new_label();
71    TCGv taddr = tcg_temp_new();
72    TCGv tval = tcg_temp_new();
73    TCGv t1 = tcg_temp_new();
74    dc->postinc = 0;
75    cris_evaluate_flags(dc);
76
77    tcg_gen_mov_tl(taddr, addr);
78    tcg_gen_mov_tl(tval, val);
79
80    /* Store only if F flag isn't set */
81    tcg_gen_andi_tl(t1, cpu_PR[PR_CCS], F_FLAG_V10);
82    tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
83
84    tcg_gen_qemu_st_tl(tval, taddr, mem_index, ctz32(size) | MO_TE);
85
86    gen_set_label(l1);
87    tcg_gen_shri_tl(t1, t1, 1);  /* shift F to P position */
88    tcg_gen_or_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], t1); /*P=F*/
89}
90
91static void gen_store_v10(DisasContext *dc, TCGv addr, TCGv val,
92                       unsigned int size)
93{
94    int mem_index = cpu_mmu_index(&dc->cpu->env, false);
95
96    /* If we get a fault on a delayslot we must keep the jmp state in
97       the cpu-state to be able to re-execute the jmp.  */
98    if (dc->delayed_branch == 1) {
99        cris_store_direct_jmp(dc);
100    }
101
102    /* Conditional writes. */
103    if (dc->flags_x) {
104        gen_store_v10_conditional(dc, addr, val, size, mem_index);
105        return;
106    }
107
108    tcg_gen_qemu_st_tl(val, addr, mem_index, ctz32(size) | MO_TE);
109}
110
111
112/* Prefix flag and register are used to handle the more complex
113   addressing modes.  */
114static void cris_set_prefix(DisasContext *dc)
115{
116    dc->clear_prefix = 0;
117    dc->tb_flags |= PFIX_FLAG;
118    tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], PFIX_FLAG);
119
120    /* prefix insns don't clear the x flag.  */
121    dc->clear_x = 0;
122    cris_lock_irq(dc);
123}
124
125static void crisv10_prepare_memaddr(DisasContext *dc,
126                                    TCGv addr, unsigned int size)
127{
128    if (dc->tb_flags & PFIX_FLAG) {
129        tcg_gen_mov_tl(addr, cpu_PR[PR_PREFIX]);
130    } else {
131        tcg_gen_mov_tl(addr, cpu_R[dc->src]);
132    }
133}
134
135static unsigned int crisv10_post_memaddr(DisasContext *dc, unsigned int size)
136{
137    unsigned int insn_len = 0;
138
139    if (dc->tb_flags & PFIX_FLAG) {
140        if (dc->mode == CRISV10_MODE_AUTOINC) {
141            tcg_gen_mov_tl(cpu_R[dc->src], cpu_PR[PR_PREFIX]);
142        }
143    } else {
144        if (dc->mode == CRISV10_MODE_AUTOINC) {
145            if (dc->src == 15) {
146                insn_len += size & ~1;
147            } else {
148                tcg_gen_addi_tl(cpu_R[dc->src], cpu_R[dc->src], size);
149            }
150        }
151    }
152    return insn_len;
153}
154
155static int dec10_prep_move_m(CPUCRISState *env, DisasContext *dc,
156                             int s_ext, int memsize, TCGv dst)
157{
158    unsigned int rs;
159    uint32_t imm;
160    int is_imm;
161    int insn_len = 0;
162
163    rs = dc->src;
164    is_imm = rs == 15 && !(dc->tb_flags & PFIX_FLAG);
165    LOG_DIS("rs=%d rd=%d is_imm=%d mode=%d pfix=%d\n",
166             rs, dc->dst, is_imm, dc->mode, dc->tb_flags & PFIX_FLAG);
167
168    /* Load [$rs] onto T1.  */
169    if (is_imm) {
170        if (memsize != 4) {
171            if (s_ext) {
172                if (memsize == 1)
173                    imm = cpu_ldsb_code(env, dc->pc + 2);
174                else
175                    imm = cpu_ldsw_code(env, dc->pc + 2);
176            } else {
177                if (memsize == 1)
178                    imm = cpu_ldub_code(env, dc->pc + 2);
179                else
180                    imm = cpu_lduw_code(env, dc->pc + 2);
181            }
182        } else
183            imm = cpu_ldl_code(env, dc->pc + 2);
184
185        tcg_gen_movi_tl(dst, imm);
186
187        if (dc->mode == CRISV10_MODE_AUTOINC) {
188            insn_len += memsize;
189            if (memsize == 1)
190                insn_len++;
191            tcg_gen_addi_tl(cpu_R[15], cpu_R[15], insn_len);
192        }
193    } else {
194        TCGv addr;
195
196        addr = tcg_temp_new();
197        cris_flush_cc_state(dc);
198        crisv10_prepare_memaddr(dc, addr, memsize);
199        gen_load(dc, dst, addr, memsize, 0);
200        if (s_ext)
201            t_gen_sext(dst, dst, memsize);
202        else
203            t_gen_zext(dst, dst, memsize);
204        insn_len += crisv10_post_memaddr(dc, memsize);
205    }
206
207    if (dc->mode == CRISV10_MODE_INDIRECT && (dc->tb_flags & PFIX_FLAG)) {
208        dc->dst = dc->src;
209    }
210    return insn_len;
211}
212
213static unsigned int dec10_quick_imm(DisasContext *dc)
214{
215    int32_t imm, simm;
216    int op;
217    TCGv c;
218
219    /* sign extend.  */
220    imm = dc->ir & ((1 << 6) - 1);
221    simm = (int8_t) (imm << 2);
222    simm >>= 2;
223    switch (dc->opcode) {
224        case CRISV10_QIMM_BDAP_R0:
225        case CRISV10_QIMM_BDAP_R1:
226        case CRISV10_QIMM_BDAP_R2:
227        case CRISV10_QIMM_BDAP_R3:
228            simm = (int8_t)dc->ir;
229            LOG_DIS("bdap %d $r%d\n", simm, dc->dst);
230            LOG_DIS("pc=%x mode=%x quickimm %d r%d r%d\n",
231                     dc->pc, dc->mode, dc->opcode, dc->src, dc->dst);
232            cris_set_prefix(dc);
233            if (dc->dst == 15) {
234                tcg_gen_movi_tl(cpu_PR[PR_PREFIX], dc->pc + 2 + simm);
235            } else {
236                tcg_gen_addi_tl(cpu_PR[PR_PREFIX], cpu_R[dc->dst], simm);
237            }
238            break;
239
240        case CRISV10_QIMM_MOVEQ:
241            LOG_DIS("moveq %d, $r%d\n", simm, dc->dst);
242
243            cris_cc_mask(dc, CC_MASK_NZVC);
244            c = tcg_constant_tl(simm);
245            cris_alu(dc, CC_OP_MOVE, cpu_R[dc->dst],
246                     cpu_R[dc->dst], c, 4);
247            break;
248        case CRISV10_QIMM_CMPQ:
249            LOG_DIS("cmpq %d, $r%d\n", simm, dc->dst);
250
251            cris_cc_mask(dc, CC_MASK_NZVC);
252            c = tcg_constant_tl(simm);
253            cris_alu(dc, CC_OP_CMP, cpu_R[dc->dst],
254                     cpu_R[dc->dst], c, 4);
255            break;
256        case CRISV10_QIMM_ADDQ:
257            LOG_DIS("addq %d, $r%d\n", imm, dc->dst);
258
259            cris_cc_mask(dc, CC_MASK_NZVC);
260            c = tcg_constant_tl(imm);
261            cris_alu(dc, CC_OP_ADD, cpu_R[dc->dst],
262                     cpu_R[dc->dst], c, 4);
263            break;
264        case CRISV10_QIMM_ANDQ:
265            LOG_DIS("andq %d, $r%d\n", simm, dc->dst);
266
267            cris_cc_mask(dc, CC_MASK_NZVC);
268            c = tcg_constant_tl(simm);
269            cris_alu(dc, CC_OP_AND, cpu_R[dc->dst],
270                     cpu_R[dc->dst], c, 4);
271            break;
272        case CRISV10_QIMM_ASHQ:
273            LOG_DIS("ashq %d, $r%d\n", simm, dc->dst);
274
275            cris_cc_mask(dc, CC_MASK_NZVC);
276            op = imm & (1 << 5);
277            imm &= 0x1f;
278            c = tcg_constant_tl(imm);
279            if (op) {
280                cris_alu(dc, CC_OP_ASR, cpu_R[dc->dst],
281                          cpu_R[dc->dst], c, 4);
282            } else {
283                /* BTST */
284                cris_update_cc_op(dc, CC_OP_FLAGS, 4);
285                gen_helper_btst(cpu_PR[PR_CCS], cpu_env, cpu_R[dc->dst],
286                           c, cpu_PR[PR_CCS]);
287            }
288            break;
289        case CRISV10_QIMM_LSHQ:
290            LOG_DIS("lshq %d, $r%d\n", simm, dc->dst);
291
292            op = CC_OP_LSL;
293            if (imm & (1 << 5)) {
294                op = CC_OP_LSR;
295            }
296            imm &= 0x1f;
297            cris_cc_mask(dc, CC_MASK_NZVC);
298            c = tcg_constant_tl(imm);
299            cris_alu(dc, op, cpu_R[dc->dst],
300                     cpu_R[dc->dst], c, 4);
301            break;
302        case CRISV10_QIMM_SUBQ:
303            LOG_DIS("subq %d, $r%d\n", imm, dc->dst);
304
305            cris_cc_mask(dc, CC_MASK_NZVC);
306            c = tcg_constant_tl(imm);
307            cris_alu(dc, CC_OP_SUB, cpu_R[dc->dst],
308                     cpu_R[dc->dst], c, 4);
309            break;
310        case CRISV10_QIMM_ORQ:
311            LOG_DIS("andq %d, $r%d\n", simm, dc->dst);
312
313            cris_cc_mask(dc, CC_MASK_NZVC);
314            c = tcg_constant_tl(simm);
315            cris_alu(dc, CC_OP_OR, cpu_R[dc->dst],
316                     cpu_R[dc->dst], c, 4);
317            break;
318
319        case CRISV10_QIMM_BCC_R0:
320        case CRISV10_QIMM_BCC_R1:
321        case CRISV10_QIMM_BCC_R2:
322        case CRISV10_QIMM_BCC_R3:
323            imm = dc->ir & 0xff;
324            /* bit 0 is a sign bit.  */
325            if (imm & 1) {
326                imm |= 0xffffff00;   /* sign extend.  */
327                imm &= ~1;           /* get rid of the sign bit.  */
328            }
329            imm += 2;
330            LOG_DIS("b%s %d\n", cc_name(dc->cond), imm);
331
332            cris_cc_mask(dc, 0);
333            cris_prepare_cc_branch(dc, imm, dc->cond);
334            break;
335
336        default:
337            LOG_DIS("pc=%x mode=%x quickimm %d r%d r%d\n",
338                     dc->pc, dc->mode, dc->opcode, dc->src, dc->dst);
339            cpu_abort(CPU(dc->cpu), "Unhandled quickimm\n");
340            break;
341    }
342    return 2;
343}
344
345static unsigned int dec10_setclrf(DisasContext *dc)
346{
347    uint32_t flags;
348    unsigned int set = ~dc->opcode & 1;
349
350    flags = EXTRACT_FIELD(dc->ir, 0, 3)
351            | (EXTRACT_FIELD(dc->ir, 12, 15) << 4);
352    LOG_DIS("%s set=%d flags=%x\n", __func__, set, flags);
353
354
355    if (flags & X_FLAG) {
356        if (set)
357            dc->flags_x = X_FLAG;
358        else
359            dc->flags_x = 0;
360    }
361
362    cris_evaluate_flags (dc);
363    cris_update_cc_op(dc, CC_OP_FLAGS, 4);
364    cris_update_cc_x(dc);
365    tcg_gen_movi_tl(cc_op, dc->cc_op);
366
367    if (set) {
368        tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], flags);
369    } else {
370        tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS],
371                        ~(flags|F_FLAG_V10|P_FLAG_V10));
372    }
373
374    dc->flags_uptodate = 1;
375    dc->clear_x = 0;
376    cris_lock_irq(dc);
377    return 2;
378}
379
380static inline void dec10_reg_prep_sext(DisasContext *dc, int size, int sext,
381                                       TCGv dd, TCGv ds, TCGv sd, TCGv ss)
382{
383    if (sext) {
384        t_gen_sext(dd, sd, size);
385        t_gen_sext(ds, ss, size);
386    } else {
387        t_gen_zext(dd, sd, size);
388        t_gen_zext(ds, ss, size);
389    }
390}
391
392static void dec10_reg_alu(DisasContext *dc, int op, int size, int sext)
393{
394    TCGv t[2];
395
396    t[0] = tcg_temp_new();
397    t[1] = tcg_temp_new();
398    dec10_reg_prep_sext(dc, size, sext,
399                        t[0], t[1], cpu_R[dc->dst], cpu_R[dc->src]);
400
401    if (op == CC_OP_LSL || op == CC_OP_LSR || op == CC_OP_ASR) {
402        tcg_gen_andi_tl(t[1], t[1], 63);
403    }
404
405    assert(dc->dst != 15);
406    cris_alu(dc, op, cpu_R[dc->dst], t[0], t[1], size);
407}
408
409static void dec10_reg_bound(DisasContext *dc, int size)
410{
411    TCGv t;
412
413    t = tcg_temp_new();
414    t_gen_zext(t, cpu_R[dc->src], size);
415    cris_alu(dc, CC_OP_BOUND, cpu_R[dc->dst], cpu_R[dc->dst], t, 4);
416}
417
418static void dec10_reg_mul(DisasContext *dc, int size, int sext)
419{
420    int op = sext ? CC_OP_MULS : CC_OP_MULU;
421    TCGv t[2];
422
423    t[0] = tcg_temp_new();
424    t[1] = tcg_temp_new();
425    dec10_reg_prep_sext(dc, size, sext,
426                        t[0], t[1], cpu_R[dc->dst], cpu_R[dc->src]);
427
428    cris_alu(dc, op, cpu_R[dc->dst], t[0], t[1], 4);
429}
430
431
432static void dec10_reg_movs(DisasContext *dc)
433{
434    int size = (dc->size & 1) + 1;
435    TCGv t;
436
437    LOG_DIS("movx.%d $r%d, $r%d\n", size, dc->src, dc->dst);
438    cris_cc_mask(dc, CC_MASK_NZVC);
439
440    t = tcg_temp_new();
441    if (dc->ir & 32)
442        t_gen_sext(t, cpu_R[dc->src], size);
443    else
444        t_gen_zext(t, cpu_R[dc->src], size);
445
446    cris_alu(dc, CC_OP_MOVE, cpu_R[dc->dst], cpu_R[dc->dst], t, 4);
447}
448
449static void dec10_reg_alux(DisasContext *dc, int op)
450{
451    int size = (dc->size & 1) + 1;
452    TCGv t;
453
454    LOG_DIS("movx.%d $r%d, $r%d\n", size, dc->src, dc->dst);
455    cris_cc_mask(dc, CC_MASK_NZVC);
456
457    t = tcg_temp_new();
458    if (dc->ir & 32)
459        t_gen_sext(t, cpu_R[dc->src], size);
460    else
461        t_gen_zext(t, cpu_R[dc->src], size);
462
463    cris_alu(dc, op, cpu_R[dc->dst], cpu_R[dc->dst], t, 4);
464}
465
466static void dec10_reg_mov_pr(DisasContext *dc)
467{
468    LOG_DIS("move p%d r%d sz=%d\n", dc->dst, dc->src, preg_sizes_v10[dc->dst]);
469    cris_lock_irq(dc);
470    if (dc->src == 15) {
471        tcg_gen_mov_tl(env_btarget, cpu_PR[dc->dst]);
472        cris_prepare_jmp(dc, JMP_INDIRECT);
473        return;
474    }
475    if (dc->dst == PR_CCS) {
476        cris_evaluate_flags(dc);
477    }
478    cris_alu(dc, CC_OP_MOVE, cpu_R[dc->src],
479                 cpu_R[dc->src], cpu_PR[dc->dst], preg_sizes_v10[dc->dst]);
480}
481
482static void dec10_reg_abs(DisasContext *dc)
483{
484    TCGv t0;
485
486    LOG_DIS("abs $r%u, $r%u\n", dc->src, dc->dst);
487
488    assert(dc->dst != 15);
489    t0 = tcg_temp_new();
490    tcg_gen_sari_tl(t0, cpu_R[dc->src], 31);
491    tcg_gen_xor_tl(cpu_R[dc->dst], cpu_R[dc->src], t0);
492    tcg_gen_sub_tl(t0, cpu_R[dc->dst], t0);
493
494    cris_alu(dc, CC_OP_MOVE, cpu_R[dc->dst], cpu_R[dc->dst], t0, 4);
495}
496
497static void dec10_reg_swap(DisasContext *dc)
498{
499    TCGv t0;
500
501    LOG_DIS("not $r%d, $r%d\n", dc->src, dc->dst);
502
503    cris_cc_mask(dc, CC_MASK_NZVC);
504    t0 = tcg_temp_new();
505    tcg_gen_mov_tl(t0, cpu_R[dc->src]);
506    if (dc->dst & 8)
507        tcg_gen_not_tl(t0, t0);
508    if (dc->dst & 4)
509        t_gen_swapw(t0, t0);
510    if (dc->dst & 2)
511        t_gen_swapb(t0, t0);
512    if (dc->dst & 1)
513        t_gen_swapr(t0, t0);
514    cris_alu(dc, CC_OP_MOVE, cpu_R[dc->src], cpu_R[dc->src], t0, 4);
515}
516
517static void dec10_reg_scc(DisasContext *dc)
518{
519    int cond = dc->dst;
520
521    LOG_DIS("s%s $r%u\n", cc_name(cond), dc->src);
522
523    gen_tst_cc(dc, cpu_R[dc->src], cond);
524    tcg_gen_setcondi_tl(TCG_COND_NE, cpu_R[dc->src], cpu_R[dc->src], 0);
525
526    cris_cc_mask(dc, 0);
527}
528
529static unsigned int dec10_reg(DisasContext *dc)
530{
531    TCGv t;
532    unsigned int insn_len = 2;
533    unsigned int size = dec10_size(dc->size);
534    unsigned int tmp;
535
536    if (dc->size != 3) {
537        switch (dc->opcode) {
538            case CRISV10_REG_MOVE_R:
539                LOG_DIS("move.%d $r%d, $r%d\n", dc->size, dc->src, dc->dst);
540                cris_cc_mask(dc, CC_MASK_NZVC);
541                dec10_reg_alu(dc, CC_OP_MOVE, size, 0);
542                if (dc->dst == 15) {
543                    tcg_gen_mov_tl(env_btarget, cpu_R[dc->dst]);
544                    cris_prepare_jmp(dc, JMP_INDIRECT);
545                    dc->delayed_branch = 1;
546                }
547                break;
548            case CRISV10_REG_MOVX:
549                cris_cc_mask(dc, CC_MASK_NZVC);
550                dec10_reg_movs(dc);
551                break;
552            case CRISV10_REG_ADDX:
553                cris_cc_mask(dc, CC_MASK_NZVC);
554                dec10_reg_alux(dc, CC_OP_ADD);
555                break;
556            case CRISV10_REG_SUBX:
557                cris_cc_mask(dc, CC_MASK_NZVC);
558                dec10_reg_alux(dc, CC_OP_SUB);
559                break;
560            case CRISV10_REG_ADD:
561                LOG_DIS("add $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
562                cris_cc_mask(dc, CC_MASK_NZVC);
563                dec10_reg_alu(dc, CC_OP_ADD, size, 0);
564                break;
565            case CRISV10_REG_SUB:
566                LOG_DIS("sub $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
567                cris_cc_mask(dc, CC_MASK_NZVC);
568                dec10_reg_alu(dc, CC_OP_SUB, size, 0);
569                break;
570            case CRISV10_REG_CMP:
571                LOG_DIS("cmp $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
572                cris_cc_mask(dc, CC_MASK_NZVC);
573                dec10_reg_alu(dc, CC_OP_CMP, size, 0);
574                break;
575            case CRISV10_REG_BOUND:
576                LOG_DIS("bound $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
577                cris_cc_mask(dc, CC_MASK_NZVC);
578                dec10_reg_bound(dc, size);
579                break;
580            case CRISV10_REG_AND:
581                LOG_DIS("and $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
582                cris_cc_mask(dc, CC_MASK_NZVC);
583                dec10_reg_alu(dc, CC_OP_AND, size, 0);
584                break;
585            case CRISV10_REG_ADDI:
586                if (dc->src == 15) {
587                    /* nop.  */
588                    return 2;
589                }
590                t = tcg_temp_new();
591                LOG_DIS("addi r%d r%d size=%d\n", dc->src, dc->dst, dc->size);
592                tcg_gen_shli_tl(t, cpu_R[dc->dst], dc->size & 3);
593                tcg_gen_add_tl(cpu_R[dc->src], cpu_R[dc->src], t);
594                break;
595            case CRISV10_REG_LSL:
596                LOG_DIS("lsl $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
597                cris_cc_mask(dc, CC_MASK_NZVC);
598                dec10_reg_alu(dc, CC_OP_LSL, size, 0);
599                break;
600            case CRISV10_REG_LSR:
601                LOG_DIS("lsr $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
602                cris_cc_mask(dc, CC_MASK_NZVC);
603                dec10_reg_alu(dc, CC_OP_LSR, size, 0);
604                break;
605            case CRISV10_REG_ASR:
606                LOG_DIS("asr $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
607                cris_cc_mask(dc, CC_MASK_NZVC);
608                dec10_reg_alu(dc, CC_OP_ASR, size, 1);
609                break;
610            case CRISV10_REG_OR:
611                LOG_DIS("or $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
612                cris_cc_mask(dc, CC_MASK_NZVC);
613                dec10_reg_alu(dc, CC_OP_OR, size, 0);
614                break;
615            case CRISV10_REG_NEG:
616                LOG_DIS("neg $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
617                cris_cc_mask(dc, CC_MASK_NZVC);
618                dec10_reg_alu(dc, CC_OP_NEG, size, 0);
619                break;
620            case CRISV10_REG_BIAP:
621                LOG_DIS("BIAP pc=%x reg %d r%d r%d size=%d\n", dc->pc,
622                         dc->opcode, dc->src, dc->dst, size);
623                switch (size) {
624                    case 4: tmp = 2; break;
625                    case 2: tmp = 1; break;
626                    case 1: tmp = 0; break;
627                    default:
628                        cpu_abort(CPU(dc->cpu), "Unhandled BIAP");
629                        break;
630                }
631
632                t = tcg_temp_new();
633                tcg_gen_shli_tl(t, cpu_R[dc->dst], tmp);
634                if (dc->src == 15) {
635                    tcg_gen_addi_tl(cpu_PR[PR_PREFIX], t, ((dc->pc +2)| 1) + 1);
636                } else {
637                    tcg_gen_add_tl(cpu_PR[PR_PREFIX], cpu_R[dc->src], t);
638                }
639                cris_set_prefix(dc);
640                break;
641
642            default:
643                LOG_DIS("pc=%x reg %d r%d r%d\n", dc->pc,
644                         dc->opcode, dc->src, dc->dst);
645                cpu_abort(CPU(dc->cpu), "Unhandled opcode");
646                break;
647        }
648    } else {
649        switch (dc->opcode) {
650            case CRISV10_REG_MOVX:
651                cris_cc_mask(dc, CC_MASK_NZVC);
652                dec10_reg_movs(dc);
653                break;
654            case CRISV10_REG_ADDX:
655                cris_cc_mask(dc, CC_MASK_NZVC);
656                dec10_reg_alux(dc, CC_OP_ADD);
657                break;
658            case CRISV10_REG_SUBX:
659                cris_cc_mask(dc, CC_MASK_NZVC);
660                dec10_reg_alux(dc, CC_OP_SUB);
661                break;
662            case CRISV10_REG_MOVE_SPR_R:
663                cris_evaluate_flags(dc);
664                cris_cc_mask(dc, 0);
665                dec10_reg_mov_pr(dc);
666                break;
667            case CRISV10_REG_MOVE_R_SPR:
668                LOG_DIS("move r%d p%d\n", dc->src, dc->dst);
669                cris_evaluate_flags(dc);
670                if (dc->src != 11) /* fast for srp.  */
671                    dc->cpustate_changed = 1;
672                t_gen_mov_preg_TN(dc, dc->dst, cpu_R[dc->src]);
673                break;
674            case CRISV10_REG_SETF:
675            case CRISV10_REG_CLEARF:
676                dec10_setclrf(dc);
677                break;
678            case CRISV10_REG_SWAP:
679                dec10_reg_swap(dc);
680                break;
681            case CRISV10_REG_ABS:
682                cris_cc_mask(dc, CC_MASK_NZVC);
683                dec10_reg_abs(dc);
684                break;
685            case CRISV10_REG_LZ:
686                LOG_DIS("lz $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
687                cris_cc_mask(dc, CC_MASK_NZVC);
688                dec10_reg_alu(dc, CC_OP_LZ, 4, 0);
689                break;
690            case CRISV10_REG_XOR:
691                LOG_DIS("xor $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
692                cris_cc_mask(dc, CC_MASK_NZVC);
693                dec10_reg_alu(dc, CC_OP_XOR, 4, 0);
694                break;
695            case CRISV10_REG_BTST:
696                LOG_DIS("btst $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
697                cris_cc_mask(dc, CC_MASK_NZVC);
698                cris_update_cc_op(dc, CC_OP_FLAGS, 4);
699                gen_helper_btst(cpu_PR[PR_CCS], cpu_env, cpu_R[dc->dst],
700                           cpu_R[dc->src], cpu_PR[PR_CCS]);
701                break;
702            case CRISV10_REG_DSTEP:
703                LOG_DIS("dstep $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
704                cris_cc_mask(dc, CC_MASK_NZVC);
705                cris_alu(dc, CC_OP_DSTEP, cpu_R[dc->dst],
706                            cpu_R[dc->dst], cpu_R[dc->src], 4);
707                break;
708            case CRISV10_REG_MSTEP:
709                LOG_DIS("mstep $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
710                cris_evaluate_flags(dc);
711                cris_cc_mask(dc, CC_MASK_NZVC);
712                cris_alu(dc, CC_OP_MSTEP, cpu_R[dc->dst],
713                            cpu_R[dc->dst], cpu_R[dc->src], 4);
714                break;
715            case CRISV10_REG_SCC:
716                dec10_reg_scc(dc);
717                break;
718            default:
719                LOG_DIS("pc=%x reg %d r%d r%d\n", dc->pc,
720                         dc->opcode, dc->src, dc->dst);
721                cpu_abort(CPU(dc->cpu), "Unhandled opcode");
722                break;
723        }
724    }
725    return insn_len;
726}
727
728static unsigned int dec10_ind_move_m_r(CPUCRISState *env, DisasContext *dc,
729                                       unsigned int size)
730{
731    unsigned int insn_len = 2;
732    TCGv t;
733
734    LOG_DIS("%s: move.%d [$r%d], $r%d\n", __func__,
735             size, dc->src, dc->dst);
736
737    cris_cc_mask(dc, CC_MASK_NZVC);
738    t = tcg_temp_new();
739    insn_len += dec10_prep_move_m(env, dc, 0, size, t);
740    cris_alu(dc, CC_OP_MOVE, cpu_R[dc->dst], cpu_R[dc->dst], t, size);
741    if (dc->dst == 15) {
742        tcg_gen_mov_tl(env_btarget, cpu_R[dc->dst]);
743        cris_prepare_jmp(dc, JMP_INDIRECT);
744        dc->delayed_branch = 1;
745    }
746
747    return insn_len;
748}
749
750static unsigned int dec10_ind_move_r_m(DisasContext *dc, unsigned int size)
751{
752    unsigned int insn_len = 2;
753    TCGv addr;
754
755    LOG_DIS("move.%d $r%d, [$r%d]\n", dc->size, dc->src, dc->dst);
756    addr = tcg_temp_new();
757    crisv10_prepare_memaddr(dc, addr, size);
758    gen_store_v10(dc, addr, cpu_R[dc->dst], size);
759    insn_len += crisv10_post_memaddr(dc, size);
760
761    return insn_len;
762}
763
764static unsigned int dec10_ind_move_m_pr(CPUCRISState *env, DisasContext *dc)
765{
766    unsigned int insn_len = 2, rd = dc->dst;
767    TCGv t;
768
769    LOG_DIS("move.%d $p%d, [$r%d]\n", dc->size, dc->dst, dc->src);
770    cris_lock_irq(dc);
771
772    t = tcg_temp_new();
773    insn_len += dec10_prep_move_m(env, dc, 0, 4, t);
774    if (rd == 15) {
775        tcg_gen_mov_tl(env_btarget, t);
776        cris_prepare_jmp(dc, JMP_INDIRECT);
777        dc->delayed_branch = 1;
778    } else {
779        tcg_gen_mov_tl(cpu_PR[rd], t);
780        dc->cpustate_changed = 1;
781    }
782    return insn_len;
783}
784
785static unsigned int dec10_ind_move_pr_m(DisasContext *dc)
786{
787    unsigned int insn_len = 2, size = preg_sizes_v10[dc->dst];
788    TCGv addr, t0;
789
790    LOG_DIS("move.%d $p%d, [$r%d]\n", dc->size, dc->dst, dc->src);
791
792    addr = tcg_temp_new();
793    crisv10_prepare_memaddr(dc, addr, size);
794    if (dc->dst == PR_CCS) {
795        t0 = tcg_temp_new();
796        cris_evaluate_flags(dc);
797        tcg_gen_andi_tl(t0, cpu_PR[PR_CCS], ~PFIX_FLAG);
798        gen_store_v10(dc, addr, t0, size);
799    } else {
800        gen_store_v10(dc, addr, cpu_PR[dc->dst], size);
801    }
802    insn_len += crisv10_post_memaddr(dc, size);
803    cris_lock_irq(dc);
804
805    return insn_len;
806}
807
808static void dec10_movem_r_m(DisasContext *dc)
809{
810    int i, pfix = dc->tb_flags & PFIX_FLAG;
811    TCGv addr, t0;
812
813    LOG_DIS("%s r%d, [r%d] pi=%d ir=%x\n", __func__,
814              dc->dst, dc->src, dc->postinc, dc->ir);
815
816    addr = tcg_temp_new();
817    t0 = tcg_temp_new();
818    crisv10_prepare_memaddr(dc, addr, 4);
819    tcg_gen_mov_tl(t0, addr);
820    for (i = dc->dst; i >= 0; i--) {
821        if ((pfix && dc->mode == CRISV10_MODE_AUTOINC) && dc->src == i) {
822            gen_store_v10(dc, addr, t0, 4);
823        } else {
824            gen_store_v10(dc, addr, cpu_R[i], 4);
825        }
826        tcg_gen_addi_tl(addr, addr, 4);
827    }
828
829    if (pfix && dc->mode == CRISV10_MODE_AUTOINC) {
830        tcg_gen_mov_tl(cpu_R[dc->src], t0);
831    }
832
833    if (!pfix && dc->mode == CRISV10_MODE_AUTOINC) {
834        tcg_gen_mov_tl(cpu_R[dc->src], addr);
835    }
836}
837
838static void dec10_movem_m_r(DisasContext *dc)
839{
840    int i, pfix = dc->tb_flags & PFIX_FLAG;
841    TCGv addr, t0;
842
843    LOG_DIS("%s [r%d], r%d pi=%d ir=%x\n", __func__,
844              dc->src, dc->dst, dc->postinc, dc->ir);
845
846    addr = tcg_temp_new();
847    t0 = tcg_temp_new();
848    crisv10_prepare_memaddr(dc, addr, 4);
849    tcg_gen_mov_tl(t0, addr);
850    for (i = dc->dst; i >= 0; i--) {
851        gen_load(dc, cpu_R[i], addr, 4, 0);
852        tcg_gen_addi_tl(addr, addr, 4);
853    }
854
855    if (pfix && dc->mode == CRISV10_MODE_AUTOINC) {
856        tcg_gen_mov_tl(cpu_R[dc->src], t0);
857    }
858
859    if (!pfix && dc->mode == CRISV10_MODE_AUTOINC) {
860        tcg_gen_mov_tl(cpu_R[dc->src], addr);
861    }
862}
863
864static int dec10_ind_alu(CPUCRISState *env, DisasContext *dc,
865                         int op, unsigned int size)
866{
867    int insn_len = 0;
868    int rd = dc->dst;
869    TCGv t[2];
870
871    cris_alu_m_alloc_temps(t);
872    insn_len += dec10_prep_move_m(env, dc, 0, size, t[0]);
873    cris_alu(dc, op, cpu_R[dc->dst], cpu_R[rd], t[0], size);
874    if (dc->dst == 15) {
875        tcg_gen_mov_tl(env_btarget, cpu_R[dc->dst]);
876        cris_prepare_jmp(dc, JMP_INDIRECT);
877        dc->delayed_branch = 1;
878        return insn_len;
879    }
880    return insn_len;
881}
882
883static int dec10_ind_bound(CPUCRISState *env, DisasContext *dc,
884                           unsigned int size)
885{
886    int insn_len = 0;
887    int rd = dc->dst;
888    TCGv t;
889
890    t = tcg_temp_new();
891    insn_len += dec10_prep_move_m(env, dc, 0, size, t);
892    cris_alu(dc, CC_OP_BOUND, cpu_R[dc->dst], cpu_R[rd], t, 4);
893    if (dc->dst == 15) {
894        tcg_gen_mov_tl(env_btarget, cpu_R[dc->dst]);
895        cris_prepare_jmp(dc, JMP_INDIRECT);
896        dc->delayed_branch = 1;
897    }
898
899    return insn_len;
900}
901
902static int dec10_alux_m(CPUCRISState *env, DisasContext *dc, int op)
903{
904    unsigned int size = (dc->size & 1) ? 2 : 1;
905    unsigned int sx = !!(dc->size & 2);
906    int insn_len = 2;
907    int rd = dc->dst;
908    TCGv t;
909
910    LOG_DIS("addx size=%d sx=%d op=%d %d\n", size, sx, dc->src, dc->dst);
911
912    t = tcg_temp_new();
913
914    cris_cc_mask(dc, CC_MASK_NZVC);
915    insn_len += dec10_prep_move_m(env, dc, sx, size, t);
916    cris_alu(dc, op, cpu_R[dc->dst], cpu_R[rd], t, 4);
917    if (dc->dst == 15) {
918        tcg_gen_mov_tl(env_btarget, cpu_R[dc->dst]);
919        cris_prepare_jmp(dc, JMP_INDIRECT);
920        dc->delayed_branch = 1;
921    }
922
923    return insn_len;
924}
925
926static int dec10_dip(CPUCRISState *env, DisasContext *dc)
927{
928    int insn_len = 2;
929    uint32_t imm;
930
931    LOG_DIS("dip pc=%x opcode=%d r%d r%d\n",
932              dc->pc, dc->opcode, dc->src, dc->dst);
933    if (dc->src == 15) {
934        imm = cpu_ldl_code(env, dc->pc + 2);
935        tcg_gen_movi_tl(cpu_PR[PR_PREFIX], imm);
936        if (dc->postinc)
937            insn_len += 4;
938        tcg_gen_addi_tl(cpu_R[15], cpu_R[15], insn_len - 2);
939    } else {
940        gen_load(dc, cpu_PR[PR_PREFIX], cpu_R[dc->src], 4, 0);
941        if (dc->postinc)
942            tcg_gen_addi_tl(cpu_R[dc->src], cpu_R[dc->src], 4);
943    }
944
945    cris_set_prefix(dc);
946    return insn_len;
947}
948
949static int dec10_bdap_m(CPUCRISState *env, DisasContext *dc, int size)
950{
951    int insn_len = 2;
952    int rd = dc->dst;
953
954    LOG_DIS("bdap_m pc=%x opcode=%d r%d r%d sz=%d\n",
955              dc->pc, dc->opcode, dc->src, dc->dst, size);
956
957    assert(dc->dst != 15);
958#if 0
959    /* 8bit embedded offset?  */
960    if (!dc->postinc && (dc->ir & (1 << 11))) {
961        int simm = dc->ir & 0xff;
962
963        /* cpu_abort(CPU(dc->cpu), "Unhandled opcode"); */
964        /* sign extended.  */
965        simm = (int8_t)simm;
966
967        tcg_gen_addi_tl(cpu_PR[PR_PREFIX], cpu_R[dc->dst], simm);
968
969        cris_set_prefix(dc);
970        return insn_len;
971    }
972#endif
973    /* Now the rest of the modes are truly indirect.  */
974    insn_len += dec10_prep_move_m(env, dc, 1, size, cpu_PR[PR_PREFIX]);
975    tcg_gen_add_tl(cpu_PR[PR_PREFIX], cpu_PR[PR_PREFIX], cpu_R[rd]);
976    cris_set_prefix(dc);
977    return insn_len;
978}
979
980static unsigned int dec10_ind(CPUCRISState *env, DisasContext *dc)
981{
982    unsigned int insn_len = 2;
983    unsigned int size = dec10_size(dc->size);
984    uint32_t imm;
985    int32_t simm;
986    TCGv t[2], c;
987
988    if (dc->size != 3) {
989        switch (dc->opcode) {
990            case CRISV10_IND_MOVE_M_R:
991                return dec10_ind_move_m_r(env, dc, size);
992            case CRISV10_IND_MOVE_R_M:
993                return dec10_ind_move_r_m(dc, size);
994            case CRISV10_IND_CMP:
995                LOG_DIS("cmp size=%d op=%d %d\n",  size, dc->src, dc->dst);
996                cris_cc_mask(dc, CC_MASK_NZVC);
997                insn_len += dec10_ind_alu(env, dc, CC_OP_CMP, size);
998                break;
999            case CRISV10_IND_TEST:
1000                LOG_DIS("test size=%d op=%d %d\n",  size, dc->src, dc->dst);
1001
1002                cris_evaluate_flags(dc);
1003                cris_cc_mask(dc, CC_MASK_NZVC);
1004                cris_alu_m_alloc_temps(t);
1005                insn_len += dec10_prep_move_m(env, dc, 0, size, t[0]);
1006                tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~3);
1007                c = tcg_constant_tl(0);
1008                cris_alu(dc, CC_OP_CMP, cpu_R[dc->dst],
1009                         t[0], c, size);
1010                break;
1011            case CRISV10_IND_ADD:
1012                LOG_DIS("add size=%d op=%d %d\n",  size, dc->src, dc->dst);
1013                cris_cc_mask(dc, CC_MASK_NZVC);
1014                insn_len += dec10_ind_alu(env, dc, CC_OP_ADD, size);
1015                break;
1016            case CRISV10_IND_SUB:
1017                LOG_DIS("sub size=%d op=%d %d\n",  size, dc->src, dc->dst);
1018                cris_cc_mask(dc, CC_MASK_NZVC);
1019                insn_len += dec10_ind_alu(env, dc, CC_OP_SUB, size);
1020                break;
1021            case CRISV10_IND_BOUND:
1022                LOG_DIS("bound size=%d op=%d %d\n",  size, dc->src, dc->dst);
1023                cris_cc_mask(dc, CC_MASK_NZVC);
1024                insn_len += dec10_ind_bound(env, dc, size);
1025                break;
1026            case CRISV10_IND_AND:
1027                LOG_DIS("and size=%d op=%d %d\n",  size, dc->src, dc->dst);
1028                cris_cc_mask(dc, CC_MASK_NZVC);
1029                insn_len += dec10_ind_alu(env, dc, CC_OP_AND, size);
1030                break;
1031            case CRISV10_IND_OR:
1032                LOG_DIS("or size=%d op=%d %d\n",  size, dc->src, dc->dst);
1033                cris_cc_mask(dc, CC_MASK_NZVC);
1034                insn_len += dec10_ind_alu(env, dc, CC_OP_OR, size);
1035                break;
1036            case CRISV10_IND_MOVX:
1037                insn_len = dec10_alux_m(env, dc, CC_OP_MOVE);
1038                break;
1039            case CRISV10_IND_ADDX:
1040                insn_len = dec10_alux_m(env, dc, CC_OP_ADD);
1041                break;
1042            case CRISV10_IND_SUBX:
1043                insn_len = dec10_alux_m(env, dc, CC_OP_SUB);
1044                break;
1045            case CRISV10_IND_CMPX:
1046                insn_len = dec10_alux_m(env, dc, CC_OP_CMP);
1047                break;
1048            case CRISV10_IND_MUL:
1049                /* This is a reg insn coded in the mem indir space.  */
1050                LOG_DIS("mul pc=%x opcode=%d\n", dc->pc, dc->opcode);
1051                cris_cc_mask(dc, CC_MASK_NZVC);
1052                dec10_reg_mul(dc, size, dc->ir & (1 << 10));
1053                break;
1054            case CRISV10_IND_BDAP_M:
1055                insn_len = dec10_bdap_m(env, dc, size);
1056                break;
1057            default:
1058            /*
1059             * ADDC for v17:
1060             *
1061             * Instruction format: ADDC [Rs],Rd
1062             *
1063             *  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+-+
1064             *  |Destination(Rd)| 1   0   0   1   1   0   1   0 |   Source(Rs)|
1065             *  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+--+--+
1066             *
1067             * Instruction format: ADDC [Rs+],Rd
1068             *
1069             *  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+-+
1070             *  |Destination(Rd)| 1   1   0   1   1   0   1   0 |   Source(Rs)|
1071             *  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+-+
1072             */
1073                if (dc->opcode == CRISV17_IND_ADDC && dc->size == 2 &&
1074                    env->pregs[PR_VR] == 17) {
1075                    LOG_DIS("addc op=%d %d\n",  dc->src, dc->dst);
1076                    cris_cc_mask(dc, CC_MASK_NZVC);
1077                    insn_len += dec10_ind_alu(env, dc, CC_OP_ADDC, size);
1078                    break;
1079                }
1080
1081                LOG_DIS("pc=%x var-ind.%d %d r%d r%d\n",
1082                          dc->pc, size, dc->opcode, dc->src, dc->dst);
1083                cpu_abort(CPU(dc->cpu), "Unhandled opcode");
1084                break;
1085        }
1086        return insn_len;
1087    }
1088
1089    switch (dc->opcode) {
1090        case CRISV10_IND_MOVE_M_SPR:
1091            insn_len = dec10_ind_move_m_pr(env, dc);
1092            break;
1093        case CRISV10_IND_MOVE_SPR_M:
1094            insn_len = dec10_ind_move_pr_m(dc);
1095            break;
1096        case CRISV10_IND_JUMP_M:
1097            if (dc->src == 15) {
1098                LOG_DIS("jump.%d %d r%d r%d direct\n", size,
1099                         dc->opcode, dc->src, dc->dst);
1100                imm = cpu_ldl_code(env, dc->pc + 2);
1101                if (dc->mode == CRISV10_MODE_AUTOINC)
1102                    insn_len += size;
1103
1104                c = tcg_constant_tl(dc->pc + insn_len);
1105                t_gen_mov_preg_TN(dc, dc->dst, c);
1106                dc->jmp_pc = imm;
1107                cris_prepare_jmp(dc, JMP_DIRECT);
1108                dc->delayed_branch--; /* v10 has no dslot here.  */
1109            } else {
1110                if (dc->dst == 14) {
1111                    LOG_DIS("break %d\n", dc->src);
1112                    cris_evaluate_flags(dc);
1113                    tcg_gen_movi_tl(env_pc, dc->pc + 2);
1114                    c = tcg_constant_tl(dc->src + 2);
1115                    t_gen_mov_env_TN(trap_vector, c);
1116                    t_gen_raise_exception(EXCP_BREAK);
1117                    dc->base.is_jmp = DISAS_NORETURN;
1118                    return insn_len;
1119                }
1120                LOG_DIS("%d: jump.%d %d r%d r%d\n", __LINE__, size,
1121                         dc->opcode, dc->src, dc->dst);
1122                t[0] = tcg_temp_new();
1123                c = tcg_constant_tl(dc->pc + insn_len);
1124                t_gen_mov_preg_TN(dc, dc->dst, c);
1125                crisv10_prepare_memaddr(dc, t[0], size);
1126                gen_load(dc, env_btarget, t[0], 4, 0);
1127                insn_len += crisv10_post_memaddr(dc, size);
1128                cris_prepare_jmp(dc, JMP_INDIRECT);
1129                dc->delayed_branch--; /* v10 has no dslot here.  */
1130            }
1131            break;
1132
1133        case CRISV10_IND_MOVEM_R_M:
1134            LOG_DIS("movem_r_m pc=%x opcode=%d r%d r%d\n",
1135                        dc->pc, dc->opcode, dc->dst, dc->src);
1136            dec10_movem_r_m(dc);
1137            break;
1138        case CRISV10_IND_MOVEM_M_R:
1139            LOG_DIS("movem_m_r pc=%x opcode=%d\n", dc->pc, dc->opcode);
1140            dec10_movem_m_r(dc);
1141            break;
1142        case CRISV10_IND_JUMP_R:
1143            LOG_DIS("jmp pc=%x opcode=%d r%d r%d\n",
1144                        dc->pc, dc->opcode, dc->dst, dc->src);
1145            tcg_gen_mov_tl(env_btarget, cpu_R[dc->src]);
1146            c = tcg_constant_tl(dc->pc + insn_len);
1147            t_gen_mov_preg_TN(dc, dc->dst, c);
1148            cris_prepare_jmp(dc, JMP_INDIRECT);
1149            dc->delayed_branch--; /* v10 has no dslot here.  */
1150            break;
1151        case CRISV10_IND_MOVX:
1152            insn_len = dec10_alux_m(env, dc, CC_OP_MOVE);
1153            break;
1154        case CRISV10_IND_ADDX:
1155            insn_len = dec10_alux_m(env, dc, CC_OP_ADD);
1156            break;
1157        case CRISV10_IND_SUBX:
1158            insn_len = dec10_alux_m(env, dc, CC_OP_SUB);
1159            break;
1160        case CRISV10_IND_CMPX:
1161            insn_len = dec10_alux_m(env, dc, CC_OP_CMP);
1162            break;
1163        case CRISV10_IND_DIP:
1164            insn_len = dec10_dip(env, dc);
1165            break;
1166        case CRISV10_IND_BCC_M:
1167
1168            cris_cc_mask(dc, 0);
1169            simm = cpu_ldsw_code(env, dc->pc + 2);
1170            simm += 4;
1171
1172            LOG_DIS("bcc_m: b%s %x\n", cc_name(dc->cond), dc->pc + simm);
1173            cris_prepare_cc_branch(dc, simm, dc->cond);
1174            insn_len = 4;
1175            break;
1176        default:
1177            LOG_DIS("ERROR pc=%x opcode=%d\n", dc->pc, dc->opcode);
1178            cpu_abort(CPU(dc->cpu), "Unhandled opcode");
1179            break;
1180    }
1181
1182    return insn_len;
1183}
1184
1185static unsigned int crisv10_decoder(CPUCRISState *env, DisasContext *dc)
1186{
1187    unsigned int insn_len = 2;
1188
1189    /* Load a halfword onto the instruction register.  */
1190    dc->ir = cpu_lduw_code(env, dc->pc);
1191
1192    /* Now decode it.  */
1193    dc->opcode   = EXTRACT_FIELD(dc->ir, 6, 9);
1194    dc->mode     = EXTRACT_FIELD(dc->ir, 10, 11);
1195    dc->src      = EXTRACT_FIELD(dc->ir, 0, 3);
1196    dc->size     = EXTRACT_FIELD(dc->ir, 4, 5);
1197    dc->cond = dc->dst = EXTRACT_FIELD(dc->ir, 12, 15);
1198    dc->postinc  = EXTRACT_FIELD(dc->ir, 10, 10);
1199
1200    dc->clear_prefix = 1;
1201
1202    /* FIXME: What if this insn insn't 2 in length??  */
1203    if (dc->src == 15 || dc->dst == 15)
1204        tcg_gen_movi_tl(cpu_R[15], dc->pc + 2);
1205
1206    switch (dc->mode) {
1207        case CRISV10_MODE_QIMMEDIATE:
1208            insn_len = dec10_quick_imm(dc);
1209            break;
1210        case CRISV10_MODE_REG:
1211            insn_len = dec10_reg(dc);
1212            break;
1213        case CRISV10_MODE_AUTOINC:
1214        case CRISV10_MODE_INDIRECT:
1215            insn_len = dec10_ind(env, dc);
1216            break;
1217    }
1218
1219    if (dc->clear_prefix && dc->tb_flags & PFIX_FLAG) {
1220        dc->tb_flags &= ~PFIX_FLAG;
1221        tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~PFIX_FLAG);
1222        if (dc->tb_flags != dc->base.tb->flags) {
1223            dc->cpustate_changed = 1;
1224        }
1225    }
1226
1227    /* CRISv10 locks out interrupts on dslots.  */
1228    if (dc->delayed_branch == 2) {
1229        cris_lock_irq(dc);
1230    }
1231    return insn_len;
1232}
1233
1234void cris_initialize_crisv10_tcg(void)
1235{
1236    int i;
1237
1238    cc_x = tcg_global_mem_new(cpu_env,
1239                              offsetof(CPUCRISState, cc_x), "cc_x");
1240    cc_src = tcg_global_mem_new(cpu_env,
1241                                offsetof(CPUCRISState, cc_src), "cc_src");
1242    cc_dest = tcg_global_mem_new(cpu_env,
1243                                 offsetof(CPUCRISState, cc_dest),
1244                                 "cc_dest");
1245    cc_result = tcg_global_mem_new(cpu_env,
1246                                   offsetof(CPUCRISState, cc_result),
1247                                   "cc_result");
1248    cc_op = tcg_global_mem_new(cpu_env,
1249                               offsetof(CPUCRISState, cc_op), "cc_op");
1250    cc_size = tcg_global_mem_new(cpu_env,
1251                                 offsetof(CPUCRISState, cc_size),
1252                                 "cc_size");
1253    cc_mask = tcg_global_mem_new(cpu_env,
1254                                 offsetof(CPUCRISState, cc_mask),
1255                                 "cc_mask");
1256
1257    env_pc = tcg_global_mem_new(cpu_env,
1258                                offsetof(CPUCRISState, pc),
1259                                "pc");
1260    env_btarget = tcg_global_mem_new(cpu_env,
1261                                     offsetof(CPUCRISState, btarget),
1262                                     "btarget");
1263    env_btaken = tcg_global_mem_new(cpu_env,
1264                                    offsetof(CPUCRISState, btaken),
1265                                    "btaken");
1266    for (i = 0; i < 16; i++) {
1267        cpu_R[i] = tcg_global_mem_new(cpu_env,
1268                                      offsetof(CPUCRISState, regs[i]),
1269                                      regnames_v10[i]);
1270    }
1271    for (i = 0; i < 16; i++) {
1272        cpu_PR[i] = tcg_global_mem_new(cpu_env,
1273                                       offsetof(CPUCRISState, pregs[i]),
1274                                       pregnames_v10[i]);
1275    }
1276}
1277