]> Git Repo - qemu.git/blob - target/unicore32/translate.c
Merge remote-tracking branch 'remotes/thibault/tags/samuel-thibault' into staging
[qemu.git] / target / unicore32 / translate.c
1 /*
2  *  UniCore32 translation
3  *
4  * Copyright (C) 2010-2012 Guan Xuetao
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation, or (at your option) any
9  * later version. See the COPYING file in the top-level directory.
10  */
11 #include "qemu/osdep.h"
12
13 #include "cpu.h"
14 #include "disas/disas.h"
15 #include "exec/exec-all.h"
16 #include "tcg-op.h"
17 #include "qemu/log.h"
18 #include "exec/cpu_ldst.h"
19
20 #include "exec/helper-proto.h"
21 #include "exec/helper-gen.h"
22
23 #include "trace-tcg.h"
24 #include "exec/log.h"
25
26
27 /* internal defines */
28 typedef struct DisasContext {
29     target_ulong pc;
30     int is_jmp;
31     /* Nonzero if this instruction has been conditionally skipped.  */
32     int condjmp;
33     /* The label that will be jumped to when the instruction is skipped.  */
34     TCGLabel *condlabel;
35     struct TranslationBlock *tb;
36     int singlestep_enabled;
37 #ifndef CONFIG_USER_ONLY
38     int user;
39 #endif
40 } DisasContext;
41
42 #ifndef CONFIG_USER_ONLY
43 #define IS_USER(s)      (s->user)
44 #else
45 #define IS_USER(s)      1
46 #endif
47
48 /* These instructions trap after executing, so defer them until after the
49    conditional executions state has been updated.  */
50 #define DISAS_SYSCALL 5
51
52 static TCGv_env cpu_env;
53 static TCGv_i32 cpu_R[32];
54
55 /* FIXME:  These should be removed.  */
56 static TCGv cpu_F0s, cpu_F1s;
57 static TCGv_i64 cpu_F0d, cpu_F1d;
58
59 #include "exec/gen-icount.h"
60
61 static const char *regnames[] = {
62       "r00", "r01", "r02", "r03", "r04", "r05", "r06", "r07",
63       "r08", "r09", "r10", "r11", "r12", "r13", "r14", "r15",
64       "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
65       "r24", "r25", "r26", "r27", "r28", "r29", "r30", "pc" };
66
67 /* initialize TCG globals.  */
68 void uc32_translate_init(void)
69 {
70     int i;
71
72     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
73     tcg_ctx.tcg_env = cpu_env;
74
75     for (i = 0; i < 32; i++) {
76         cpu_R[i] = tcg_global_mem_new_i32(cpu_env,
77                                 offsetof(CPUUniCore32State, regs[i]), regnames[i]);
78     }
79 }
80
81 static int num_temps;
82
83 /* Allocate a temporary variable.  */
84 static TCGv_i32 new_tmp(void)
85 {
86     num_temps++;
87     return tcg_temp_new_i32();
88 }
89
90 /* Release a temporary variable.  */
91 static void dead_tmp(TCGv tmp)
92 {
93     tcg_temp_free(tmp);
94     num_temps--;
95 }
96
97 static inline TCGv load_cpu_offset(int offset)
98 {
99     TCGv tmp = new_tmp();
100     tcg_gen_ld_i32(tmp, cpu_env, offset);
101     return tmp;
102 }
103
104 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUUniCore32State, name))
105
106 static inline void store_cpu_offset(TCGv var, int offset)
107 {
108     tcg_gen_st_i32(var, cpu_env, offset);
109     dead_tmp(var);
110 }
111
112 #define store_cpu_field(var, name) \
113     store_cpu_offset(var, offsetof(CPUUniCore32State, name))
114
115 /* Set a variable to the value of a CPU register.  */
116 static void load_reg_var(DisasContext *s, TCGv var, int reg)
117 {
118     if (reg == 31) {
119         uint32_t addr;
120         /* normaly, since we updated PC */
121         addr = (long)s->pc;
122         tcg_gen_movi_i32(var, addr);
123     } else {
124         tcg_gen_mov_i32(var, cpu_R[reg]);
125     }
126 }
127
128 /* Create a new temporary and set it to the value of a CPU register.  */
129 static inline TCGv load_reg(DisasContext *s, int reg)
130 {
131     TCGv tmp = new_tmp();
132     load_reg_var(s, tmp, reg);
133     return tmp;
134 }
135
136 /* Set a CPU register.  The source must be a temporary and will be
137    marked as dead.  */
138 static void store_reg(DisasContext *s, int reg, TCGv var)
139 {
140     if (reg == 31) {
141         tcg_gen_andi_i32(var, var, ~3);
142         s->is_jmp = DISAS_JUMP;
143     }
144     tcg_gen_mov_i32(cpu_R[reg], var);
145     dead_tmp(var);
146 }
147
148 /* Value extensions.  */
149 #define gen_uxtb(var)           tcg_gen_ext8u_i32(var, var)
150 #define gen_uxth(var)           tcg_gen_ext16u_i32(var, var)
151 #define gen_sxtb(var)           tcg_gen_ext8s_i32(var, var)
152 #define gen_sxth(var)           tcg_gen_ext16s_i32(var, var)
153
154 #define UCOP_REG_M              (((insn) >>  0) & 0x1f)
155 #define UCOP_REG_N              (((insn) >> 19) & 0x1f)
156 #define UCOP_REG_D              (((insn) >> 14) & 0x1f)
157 #define UCOP_REG_S              (((insn) >>  9) & 0x1f)
158 #define UCOP_REG_LO             (((insn) >> 14) & 0x1f)
159 #define UCOP_REG_HI             (((insn) >>  9) & 0x1f)
160 #define UCOP_SH_OP              (((insn) >>  6) & 0x03)
161 #define UCOP_SH_IM              (((insn) >>  9) & 0x1f)
162 #define UCOP_OPCODES            (((insn) >> 25) & 0x0f)
163 #define UCOP_IMM_9              (((insn) >>  0) & 0x1ff)
164 #define UCOP_IMM10              (((insn) >>  0) & 0x3ff)
165 #define UCOP_IMM14              (((insn) >>  0) & 0x3fff)
166 #define UCOP_COND               (((insn) >> 25) & 0x0f)
167 #define UCOP_CMOV_COND          (((insn) >> 19) & 0x0f)
168 #define UCOP_CPNUM              (((insn) >> 10) & 0x0f)
169 #define UCOP_UCF64_FMT          (((insn) >> 24) & 0x03)
170 #define UCOP_UCF64_FUNC         (((insn) >>  6) & 0x0f)
171 #define UCOP_UCF64_COND         (((insn) >>  6) & 0x0f)
172
173 #define UCOP_SET(i)             ((insn) & (1 << (i)))
174 #define UCOP_SET_P              UCOP_SET(28)
175 #define UCOP_SET_U              UCOP_SET(27)
176 #define UCOP_SET_B              UCOP_SET(26)
177 #define UCOP_SET_W              UCOP_SET(25)
178 #define UCOP_SET_L              UCOP_SET(24)
179 #define UCOP_SET_S              UCOP_SET(24)
180
181 #define ILLEGAL         cpu_abort(CPU(cpu),                             \
182                         "Illegal UniCore32 instruction %x at line %d!", \
183                         insn, __LINE__)
184
185 #ifndef CONFIG_USER_ONLY
186 static void disas_cp0_insn(CPUUniCore32State *env, DisasContext *s,
187         uint32_t insn)
188 {
189     UniCore32CPU *cpu = uc32_env_get_cpu(env);
190     TCGv tmp, tmp2, tmp3;
191     if ((insn & 0xfe000000) == 0xe0000000) {
192         tmp2 = new_tmp();
193         tmp3 = new_tmp();
194         tcg_gen_movi_i32(tmp2, UCOP_REG_N);
195         tcg_gen_movi_i32(tmp3, UCOP_IMM10);
196         if (UCOP_SET_L) {
197             tmp = new_tmp();
198             gen_helper_cp0_get(tmp, cpu_env, tmp2, tmp3);
199             store_reg(s, UCOP_REG_D, tmp);
200         } else {
201             tmp = load_reg(s, UCOP_REG_D);
202             gen_helper_cp0_set(cpu_env, tmp, tmp2, tmp3);
203             dead_tmp(tmp);
204         }
205         dead_tmp(tmp2);
206         dead_tmp(tmp3);
207         return;
208     }
209     ILLEGAL;
210 }
211
212 static void disas_ocd_insn(CPUUniCore32State *env, DisasContext *s,
213         uint32_t insn)
214 {
215     UniCore32CPU *cpu = uc32_env_get_cpu(env);
216     TCGv tmp;
217
218     if ((insn & 0xff003fff) == 0xe1000400) {
219         /*
220          * movc rd, pp.nn, #imm9
221          *      rd: UCOP_REG_D
222          *      nn: UCOP_REG_N (must be 0)
223          *      imm9: 0
224          */
225         if (UCOP_REG_N == 0) {
226             tmp = new_tmp();
227             tcg_gen_movi_i32(tmp, 0);
228             store_reg(s, UCOP_REG_D, tmp);
229             return;
230         } else {
231             ILLEGAL;
232         }
233     }
234     if ((insn & 0xff003fff) == 0xe0000401) {
235         /*
236          * movc pp.nn, rn, #imm9
237          *      rn: UCOP_REG_D
238          *      nn: UCOP_REG_N (must be 1)
239          *      imm9: 1
240          */
241         if (UCOP_REG_N == 1) {
242             tmp = load_reg(s, UCOP_REG_D);
243             gen_helper_cp1_putc(tmp);
244             dead_tmp(tmp);
245             return;
246         } else {
247             ILLEGAL;
248         }
249     }
250     ILLEGAL;
251 }
252 #endif
253
254 static inline void gen_set_asr(TCGv var, uint32_t mask)
255 {
256     TCGv tmp_mask = tcg_const_i32(mask);
257     gen_helper_asr_write(cpu_env, var, tmp_mask);
258     tcg_temp_free_i32(tmp_mask);
259 }
260 /* Set NZCV flags from the high 4 bits of var.  */
261 #define gen_set_nzcv(var) gen_set_asr(var, ASR_NZCV)
262
263 static void gen_exception(int excp)
264 {
265     TCGv tmp = new_tmp();
266     tcg_gen_movi_i32(tmp, excp);
267     gen_helper_exception(cpu_env, tmp);
268     dead_tmp(tmp);
269 }
270
271 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUUniCore32State, CF))
272
273 /* Set CF to the top bit of var.  */
274 static void gen_set_CF_bit31(TCGv var)
275 {
276     TCGv tmp = new_tmp();
277     tcg_gen_shri_i32(tmp, var, 31);
278     gen_set_CF(tmp);
279     dead_tmp(tmp);
280 }
281
282 /* Set N and Z flags from var.  */
283 static inline void gen_logic_CC(TCGv var)
284 {
285     tcg_gen_st_i32(var, cpu_env, offsetof(CPUUniCore32State, NF));
286     tcg_gen_st_i32(var, cpu_env, offsetof(CPUUniCore32State, ZF));
287 }
288
289 /* dest = T0 + T1 + CF. */
290 static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
291 {
292     TCGv tmp;
293     tcg_gen_add_i32(dest, t0, t1);
294     tmp = load_cpu_field(CF);
295     tcg_gen_add_i32(dest, dest, tmp);
296     dead_tmp(tmp);
297 }
298
299 /* dest = T0 - T1 + CF - 1.  */
300 static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
301 {
302     TCGv tmp;
303     tcg_gen_sub_i32(dest, t0, t1);
304     tmp = load_cpu_field(CF);
305     tcg_gen_add_i32(dest, dest, tmp);
306     tcg_gen_subi_i32(dest, dest, 1);
307     dead_tmp(tmp);
308 }
309
310 static void shifter_out_im(TCGv var, int shift)
311 {
312     TCGv tmp = new_tmp();
313     if (shift == 0) {
314         tcg_gen_andi_i32(tmp, var, 1);
315     } else {
316         tcg_gen_shri_i32(tmp, var, shift);
317         if (shift != 31) {
318             tcg_gen_andi_i32(tmp, tmp, 1);
319         }
320     }
321     gen_set_CF(tmp);
322     dead_tmp(tmp);
323 }
324
325 /* Shift by immediate.  Includes special handling for shift == 0.  */
326 static inline void gen_uc32_shift_im(TCGv var, int shiftop, int shift,
327         int flags)
328 {
329     switch (shiftop) {
330     case 0: /* LSL */
331         if (shift != 0) {
332             if (flags) {
333                 shifter_out_im(var, 32 - shift);
334             }
335             tcg_gen_shli_i32(var, var, shift);
336         }
337         break;
338     case 1: /* LSR */
339         if (shift == 0) {
340             if (flags) {
341                 tcg_gen_shri_i32(var, var, 31);
342                 gen_set_CF(var);
343             }
344             tcg_gen_movi_i32(var, 0);
345         } else {
346             if (flags) {
347                 shifter_out_im(var, shift - 1);
348             }
349             tcg_gen_shri_i32(var, var, shift);
350         }
351         break;
352     case 2: /* ASR */
353         if (shift == 0) {
354             shift = 32;
355         }
356         if (flags) {
357             shifter_out_im(var, shift - 1);
358         }
359         if (shift == 32) {
360             shift = 31;
361         }
362         tcg_gen_sari_i32(var, var, shift);
363         break;
364     case 3: /* ROR/RRX */
365         if (shift != 0) {
366             if (flags) {
367                 shifter_out_im(var, shift - 1);
368             }
369             tcg_gen_rotri_i32(var, var, shift); break;
370         } else {
371             TCGv tmp = load_cpu_field(CF);
372             if (flags) {
373                 shifter_out_im(var, 0);
374             }
375             tcg_gen_shri_i32(var, var, 1);
376             tcg_gen_shli_i32(tmp, tmp, 31);
377             tcg_gen_or_i32(var, var, tmp);
378             dead_tmp(tmp);
379         }
380     }
381 };
382
383 static inline void gen_uc32_shift_reg(TCGv var, int shiftop,
384                                      TCGv shift, int flags)
385 {
386     if (flags) {
387         switch (shiftop) {
388         case 0:
389             gen_helper_shl_cc(var, cpu_env, var, shift);
390             break;
391         case 1:
392             gen_helper_shr_cc(var, cpu_env, var, shift);
393             break;
394         case 2:
395             gen_helper_sar_cc(var, cpu_env, var, shift);
396             break;
397         case 3:
398             gen_helper_ror_cc(var, cpu_env, var, shift);
399             break;
400         }
401     } else {
402         switch (shiftop) {
403         case 0:
404             gen_helper_shl(var, var, shift);
405             break;
406         case 1:
407             gen_helper_shr(var, var, shift);
408             break;
409         case 2:
410             gen_helper_sar(var, var, shift);
411             break;
412         case 3:
413             tcg_gen_andi_i32(shift, shift, 0x1f);
414             tcg_gen_rotr_i32(var, var, shift);
415             break;
416         }
417     }
418     dead_tmp(shift);
419 }
420
421 static void gen_test_cc(int cc, TCGLabel *label)
422 {
423     TCGv tmp;
424     TCGv tmp2;
425     TCGLabel *inv;
426
427     switch (cc) {
428     case 0: /* eq: Z */
429         tmp = load_cpu_field(ZF);
430         tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
431         break;
432     case 1: /* ne: !Z */
433         tmp = load_cpu_field(ZF);
434         tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
435         break;
436     case 2: /* cs: C */
437         tmp = load_cpu_field(CF);
438         tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
439         break;
440     case 3: /* cc: !C */
441         tmp = load_cpu_field(CF);
442         tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
443         break;
444     case 4: /* mi: N */
445         tmp = load_cpu_field(NF);
446         tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
447         break;
448     case 5: /* pl: !N */
449         tmp = load_cpu_field(NF);
450         tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
451         break;
452     case 6: /* vs: V */
453         tmp = load_cpu_field(VF);
454         tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
455         break;
456     case 7: /* vc: !V */
457         tmp = load_cpu_field(VF);
458         tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
459         break;
460     case 8: /* hi: C && !Z */
461         inv = gen_new_label();
462         tmp = load_cpu_field(CF);
463         tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
464         dead_tmp(tmp);
465         tmp = load_cpu_field(ZF);
466         tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
467         gen_set_label(inv);
468         break;
469     case 9: /* ls: !C || Z */
470         tmp = load_cpu_field(CF);
471         tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
472         dead_tmp(tmp);
473         tmp = load_cpu_field(ZF);
474         tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
475         break;
476     case 10: /* ge: N == V -> N ^ V == 0 */
477         tmp = load_cpu_field(VF);
478         tmp2 = load_cpu_field(NF);
479         tcg_gen_xor_i32(tmp, tmp, tmp2);
480         dead_tmp(tmp2);
481         tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
482         break;
483     case 11: /* lt: N != V -> N ^ V != 0 */
484         tmp = load_cpu_field(VF);
485         tmp2 = load_cpu_field(NF);
486         tcg_gen_xor_i32(tmp, tmp, tmp2);
487         dead_tmp(tmp2);
488         tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
489         break;
490     case 12: /* gt: !Z && N == V */
491         inv = gen_new_label();
492         tmp = load_cpu_field(ZF);
493         tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
494         dead_tmp(tmp);
495         tmp = load_cpu_field(VF);
496         tmp2 = load_cpu_field(NF);
497         tcg_gen_xor_i32(tmp, tmp, tmp2);
498         dead_tmp(tmp2);
499         tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
500         gen_set_label(inv);
501         break;
502     case 13: /* le: Z || N != V */
503         tmp = load_cpu_field(ZF);
504         tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
505         dead_tmp(tmp);
506         tmp = load_cpu_field(VF);
507         tmp2 = load_cpu_field(NF);
508         tcg_gen_xor_i32(tmp, tmp, tmp2);
509         dead_tmp(tmp2);
510         tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
511         break;
512     default:
513         fprintf(stderr, "Bad condition code 0x%x\n", cc);
514         abort();
515     }
516     dead_tmp(tmp);
517 }
518
519 static const uint8_t table_logic_cc[16] = {
520     1, /* and */    1, /* xor */    0, /* sub */    0, /* rsb */
521     0, /* add */    0, /* adc */    0, /* sbc */    0, /* rsc */
522     1, /* andl */   1, /* xorl */   0, /* cmp */    0, /* cmn */
523     1, /* orr */    1, /* mov */    1, /* bic */    1, /* mvn */
524 };
525
526 /* Set PC state from an immediate address.  */
527 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
528 {
529     s->is_jmp = DISAS_UPDATE;
530     tcg_gen_movi_i32(cpu_R[31], addr & ~3);
531 }
532
533 /* Set PC state from var.  var is marked as dead.  */
534 static inline void gen_bx(DisasContext *s, TCGv var)
535 {
536     s->is_jmp = DISAS_UPDATE;
537     tcg_gen_andi_i32(cpu_R[31], var, ~3);
538     dead_tmp(var);
539 }
540
541 static inline void store_reg_bx(DisasContext *s, int reg, TCGv var)
542 {
543     store_reg(s, reg, var);
544 }
545
546 static inline TCGv gen_ld8s(TCGv addr, int index)
547 {
548     TCGv tmp = new_tmp();
549     tcg_gen_qemu_ld8s(tmp, addr, index);
550     return tmp;
551 }
552
553 static inline TCGv gen_ld8u(TCGv addr, int index)
554 {
555     TCGv tmp = new_tmp();
556     tcg_gen_qemu_ld8u(tmp, addr, index);
557     return tmp;
558 }
559
560 static inline TCGv gen_ld16s(TCGv addr, int index)
561 {
562     TCGv tmp = new_tmp();
563     tcg_gen_qemu_ld16s(tmp, addr, index);
564     return tmp;
565 }
566
567 static inline TCGv gen_ld16u(TCGv addr, int index)
568 {
569     TCGv tmp = new_tmp();
570     tcg_gen_qemu_ld16u(tmp, addr, index);
571     return tmp;
572 }
573
574 static inline TCGv gen_ld32(TCGv addr, int index)
575 {
576     TCGv tmp = new_tmp();
577     tcg_gen_qemu_ld32u(tmp, addr, index);
578     return tmp;
579 }
580
581 static inline void gen_st8(TCGv val, TCGv addr, int index)
582 {
583     tcg_gen_qemu_st8(val, addr, index);
584     dead_tmp(val);
585 }
586
587 static inline void gen_st16(TCGv val, TCGv addr, int index)
588 {
589     tcg_gen_qemu_st16(val, addr, index);
590     dead_tmp(val);
591 }
592
593 static inline void gen_st32(TCGv val, TCGv addr, int index)
594 {
595     tcg_gen_qemu_st32(val, addr, index);
596     dead_tmp(val);
597 }
598
599 static inline void gen_set_pc_im(uint32_t val)
600 {
601     tcg_gen_movi_i32(cpu_R[31], val);
602 }
603
604 /* Force a TB lookup after an instruction that changes the CPU state.  */
605 static inline void gen_lookup_tb(DisasContext *s)
606 {
607     tcg_gen_movi_i32(cpu_R[31], s->pc & ~1);
608     s->is_jmp = DISAS_UPDATE;
609 }
610
611 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
612         TCGv var)
613 {
614     int val;
615     TCGv offset;
616
617     if (UCOP_SET(29)) {
618         /* immediate */
619         val = UCOP_IMM14;
620         if (!UCOP_SET_U) {
621             val = -val;
622         }
623         if (val != 0) {
624             tcg_gen_addi_i32(var, var, val);
625         }
626     } else {
627         /* shift/register */
628         offset = load_reg(s, UCOP_REG_M);
629         gen_uc32_shift_im(offset, UCOP_SH_OP, UCOP_SH_IM, 0);
630         if (!UCOP_SET_U) {
631             tcg_gen_sub_i32(var, var, offset);
632         } else {
633             tcg_gen_add_i32(var, var, offset);
634         }
635         dead_tmp(offset);
636     }
637 }
638
639 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
640         TCGv var)
641 {
642     int val;
643     TCGv offset;
644
645     if (UCOP_SET(26)) {
646         /* immediate */
647         val = (insn & 0x1f) | ((insn >> 4) & 0x3e0);
648         if (!UCOP_SET_U) {
649             val = -val;
650         }
651         if (val != 0) {
652             tcg_gen_addi_i32(var, var, val);
653         }
654     } else {
655         /* register */
656         offset = load_reg(s, UCOP_REG_M);
657         if (!UCOP_SET_U) {
658             tcg_gen_sub_i32(var, var, offset);
659         } else {
660             tcg_gen_add_i32(var, var, offset);
661         }
662         dead_tmp(offset);
663     }
664 }
665
666 static inline long ucf64_reg_offset(int reg)
667 {
668     if (reg & 1) {
669         return offsetof(CPUUniCore32State, ucf64.regs[reg >> 1])
670           + offsetof(CPU_DoubleU, l.upper);
671     } else {
672         return offsetof(CPUUniCore32State, ucf64.regs[reg >> 1])
673           + offsetof(CPU_DoubleU, l.lower);
674     }
675 }
676
677 #define ucf64_gen_ld32(reg)      load_cpu_offset(ucf64_reg_offset(reg))
678 #define ucf64_gen_st32(var, reg) store_cpu_offset(var, ucf64_reg_offset(reg))
679
680 /* UniCore-F64 single load/store I_offset */
681 static void do_ucf64_ldst_i(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
682 {
683     UniCore32CPU *cpu = uc32_env_get_cpu(env);
684     int offset;
685     TCGv tmp;
686     TCGv addr;
687
688     addr = load_reg(s, UCOP_REG_N);
689     if (!UCOP_SET_P && !UCOP_SET_W) {
690         ILLEGAL;
691     }
692
693     if (UCOP_SET_P) {
694         offset = UCOP_IMM10 << 2;
695         if (!UCOP_SET_U) {
696             offset = -offset;
697         }
698         if (offset != 0) {
699             tcg_gen_addi_i32(addr, addr, offset);
700         }
701     }
702
703     if (UCOP_SET_L) { /* load */
704         tmp = gen_ld32(addr, IS_USER(s));
705         ucf64_gen_st32(tmp, UCOP_REG_D);
706     } else { /* store */
707         tmp = ucf64_gen_ld32(UCOP_REG_D);
708         gen_st32(tmp, addr, IS_USER(s));
709     }
710
711     if (!UCOP_SET_P) {
712         offset = UCOP_IMM10 << 2;
713         if (!UCOP_SET_U) {
714             offset = -offset;
715         }
716         if (offset != 0) {
717             tcg_gen_addi_i32(addr, addr, offset);
718         }
719     }
720     if (UCOP_SET_W) {
721         store_reg(s, UCOP_REG_N, addr);
722     } else {
723         dead_tmp(addr);
724     }
725 }
726
727 /* UniCore-F64 load/store multiple words */
728 static void do_ucf64_ldst_m(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
729 {
730     UniCore32CPU *cpu = uc32_env_get_cpu(env);
731     unsigned int i;
732     int j, n, freg;
733     TCGv tmp;
734     TCGv addr;
735
736     if (UCOP_REG_D != 0) {
737         ILLEGAL;
738     }
739     if (UCOP_REG_N == 31) {
740         ILLEGAL;
741     }
742     if ((insn << 24) == 0) {
743         ILLEGAL;
744     }
745
746     addr = load_reg(s, UCOP_REG_N);
747
748     n = 0;
749     for (i = 0; i < 8; i++) {
750         if (UCOP_SET(i)) {
751             n++;
752         }
753     }
754
755     if (UCOP_SET_U) {
756         if (UCOP_SET_P) { /* pre increment */
757             tcg_gen_addi_i32(addr, addr, 4);
758         } /* unnecessary to do anything when post increment */
759     } else {
760         if (UCOP_SET_P) { /* pre decrement */
761             tcg_gen_addi_i32(addr, addr, -(n * 4));
762         } else { /* post decrement */
763             if (n != 1) {
764                 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
765             }
766         }
767     }
768
769     freg = ((insn >> 8) & 3) << 3; /* freg should be 0, 8, 16, 24 */
770
771     for (i = 0, j = 0; i < 8; i++, freg++) {
772         if (!UCOP_SET(i)) {
773             continue;
774         }
775
776         if (UCOP_SET_L) { /* load */
777             tmp = gen_ld32(addr, IS_USER(s));
778             ucf64_gen_st32(tmp, freg);
779         } else { /* store */
780             tmp = ucf64_gen_ld32(freg);
781             gen_st32(tmp, addr, IS_USER(s));
782         }
783
784         j++;
785         /* unnecessary to add after the last transfer */
786         if (j != n) {
787             tcg_gen_addi_i32(addr, addr, 4);
788         }
789     }
790
791     if (UCOP_SET_W) { /* write back */
792         if (UCOP_SET_U) {
793             if (!UCOP_SET_P) { /* post increment */
794                 tcg_gen_addi_i32(addr, addr, 4);
795             } /* unnecessary to do anything when pre increment */
796         } else {
797             if (UCOP_SET_P) {
798                 /* pre decrement */
799                 if (n != 1) {
800                     tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
801                 }
802             } else {
803                 /* post decrement */
804                 tcg_gen_addi_i32(addr, addr, -(n * 4));
805             }
806         }
807         store_reg(s, UCOP_REG_N, addr);
808     } else {
809         dead_tmp(addr);
810     }
811 }
812
813 /* UniCore-F64 mrc/mcr */
814 static void do_ucf64_trans(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
815 {
816     UniCore32CPU *cpu = uc32_env_get_cpu(env);
817     TCGv tmp;
818
819     if ((insn & 0xfe0003ff) == 0xe2000000) {
820         /* control register */
821         if ((UCOP_REG_N != UC32_UCF64_FPSCR) || (UCOP_REG_D == 31)) {
822             ILLEGAL;
823         }
824         if (UCOP_SET(24)) {
825             /* CFF */
826             tmp = new_tmp();
827             gen_helper_ucf64_get_fpscr(tmp, cpu_env);
828             store_reg(s, UCOP_REG_D, tmp);
829         } else {
830             /* CTF */
831             tmp = load_reg(s, UCOP_REG_D);
832             gen_helper_ucf64_set_fpscr(cpu_env, tmp);
833             dead_tmp(tmp);
834             gen_lookup_tb(s);
835         }
836         return;
837     }
838     if ((insn & 0xfe0003ff) == 0xe0000000) {
839         /* general register */
840         if (UCOP_REG_D == 31) {
841             ILLEGAL;
842         }
843         if (UCOP_SET(24)) { /* MFF */
844             tmp = ucf64_gen_ld32(UCOP_REG_N);
845             store_reg(s, UCOP_REG_D, tmp);
846         } else { /* MTF */
847             tmp = load_reg(s, UCOP_REG_D);
848             ucf64_gen_st32(tmp, UCOP_REG_N);
849         }
850         return;
851     }
852     if ((insn & 0xfb000000) == 0xe9000000) {
853         /* MFFC */
854         if (UCOP_REG_D != 31) {
855             ILLEGAL;
856         }
857         if (UCOP_UCF64_COND & 0x8) {
858             ILLEGAL;
859         }
860
861         tmp = new_tmp();
862         tcg_gen_movi_i32(tmp, UCOP_UCF64_COND);
863         if (UCOP_SET(26)) {
864             tcg_gen_ld_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_N));
865             tcg_gen_ld_i64(cpu_F1d, cpu_env, ucf64_reg_offset(UCOP_REG_M));
866             gen_helper_ucf64_cmpd(cpu_F0d, cpu_F1d, tmp, cpu_env);
867         } else {
868             tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_N));
869             tcg_gen_ld_i32(cpu_F1s, cpu_env, ucf64_reg_offset(UCOP_REG_M));
870             gen_helper_ucf64_cmps(cpu_F0s, cpu_F1s, tmp, cpu_env);
871         }
872         dead_tmp(tmp);
873         return;
874     }
875     ILLEGAL;
876 }
877
878 /* UniCore-F64 convert instructions */
879 static void do_ucf64_fcvt(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
880 {
881     UniCore32CPU *cpu = uc32_env_get_cpu(env);
882
883     if (UCOP_UCF64_FMT == 3) {
884         ILLEGAL;
885     }
886     if (UCOP_REG_N != 0) {
887         ILLEGAL;
888     }
889     switch (UCOP_UCF64_FUNC) {
890     case 0: /* cvt.s */
891         switch (UCOP_UCF64_FMT) {
892         case 1 /* d */:
893             tcg_gen_ld_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_M));
894             gen_helper_ucf64_df2sf(cpu_F0s, cpu_F0d, cpu_env);
895             tcg_gen_st_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_D));
896             break;
897         case 2 /* w */:
898             tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_M));
899             gen_helper_ucf64_si2sf(cpu_F0s, cpu_F0s, cpu_env);
900             tcg_gen_st_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_D));
901             break;
902         default /* s */:
903             ILLEGAL;
904             break;
905         }
906         break;
907     case 1: /* cvt.d */
908         switch (UCOP_UCF64_FMT) {
909         case 0 /* s */:
910             tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_M));
911             gen_helper_ucf64_sf2df(cpu_F0d, cpu_F0s, cpu_env);
912             tcg_gen_st_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_D));
913             break;
914         case 2 /* w */:
915             tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_M));
916             gen_helper_ucf64_si2df(cpu_F0d, cpu_F0s, cpu_env);
917             tcg_gen_st_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_D));
918             break;
919         default /* d */:
920             ILLEGAL;
921             break;
922         }
923         break;
924     case 4: /* cvt.w */
925         switch (UCOP_UCF64_FMT) {
926         case 0 /* s */:
927             tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_M));
928             gen_helper_ucf64_sf2si(cpu_F0s, cpu_F0s, cpu_env);
929             tcg_gen_st_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_D));
930             break;
931         case 1 /* d */:
932             tcg_gen_ld_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_M));
933             gen_helper_ucf64_df2si(cpu_F0s, cpu_F0d, cpu_env);
934             tcg_gen_st_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_D));
935             break;
936     default /* w */:
937             ILLEGAL;
938             break;
939         }
940         break;
941     default:
942         ILLEGAL;
943     }
944 }
945
946 /* UniCore-F64 compare instructions */
947 static void do_ucf64_fcmp(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
948 {
949     UniCore32CPU *cpu = uc32_env_get_cpu(env);
950
951     if (UCOP_SET(25)) {
952         ILLEGAL;
953     }
954     if (UCOP_REG_D != 0) {
955         ILLEGAL;
956     }
957
958     ILLEGAL; /* TODO */
959     if (UCOP_SET(24)) {
960         tcg_gen_ld_i64(cpu_F0d, cpu_env, ucf64_reg_offset(UCOP_REG_N));
961         tcg_gen_ld_i64(cpu_F1d, cpu_env, ucf64_reg_offset(UCOP_REG_M));
962         /* gen_helper_ucf64_cmpd(cpu_F0d, cpu_F1d, cpu_env); */
963     } else {
964         tcg_gen_ld_i32(cpu_F0s, cpu_env, ucf64_reg_offset(UCOP_REG_N));
965         tcg_gen_ld_i32(cpu_F1s, cpu_env, ucf64_reg_offset(UCOP_REG_M));
966         /* gen_helper_ucf64_cmps(cpu_F0s, cpu_F1s, cpu_env); */
967     }
968 }
969
970 #define gen_helper_ucf64_movs(x, y)      do { } while (0)
971 #define gen_helper_ucf64_movd(x, y)      do { } while (0)
972
973 #define UCF64_OP1(name)    do {                           \
974         if (UCOP_REG_N != 0) {                            \
975             ILLEGAL;                                      \
976         }                                                 \
977         switch (UCOP_UCF64_FMT) {                         \
978         case 0 /* s */:                                   \
979             tcg_gen_ld_i32(cpu_F0s, cpu_env,              \
980                            ucf64_reg_offset(UCOP_REG_M)); \
981             gen_helper_ucf64_##name##s(cpu_F0s, cpu_F0s); \
982             tcg_gen_st_i32(cpu_F0s, cpu_env,              \
983                            ucf64_reg_offset(UCOP_REG_D)); \
984             break;                                        \
985         case 1 /* d */:                                   \
986             tcg_gen_ld_i64(cpu_F0d, cpu_env,              \
987                            ucf64_reg_offset(UCOP_REG_M)); \
988             gen_helper_ucf64_##name##d(cpu_F0d, cpu_F0d); \
989             tcg_gen_st_i64(cpu_F0d, cpu_env,              \
990                            ucf64_reg_offset(UCOP_REG_D)); \
991             break;                                        \
992         case 2 /* w */:                                   \
993             ILLEGAL;                                      \
994             break;                                        \
995         }                                                 \
996     } while (0)
997
998 #define UCF64_OP2(name)    do {                           \
999         switch (UCOP_UCF64_FMT) {                         \
1000         case 0 /* s */:                                   \
1001             tcg_gen_ld_i32(cpu_F0s, cpu_env,              \
1002                            ucf64_reg_offset(UCOP_REG_N)); \
1003             tcg_gen_ld_i32(cpu_F1s, cpu_env,              \
1004                            ucf64_reg_offset(UCOP_REG_M)); \
1005             gen_helper_ucf64_##name##s(cpu_F0s,           \
1006                            cpu_F0s, cpu_F1s, cpu_env);    \
1007             tcg_gen_st_i32(cpu_F0s, cpu_env,              \
1008                            ucf64_reg_offset(UCOP_REG_D)); \
1009             break;                                        \
1010         case 1 /* d */:                                   \
1011             tcg_gen_ld_i64(cpu_F0d, cpu_env,              \
1012                            ucf64_reg_offset(UCOP_REG_N)); \
1013             tcg_gen_ld_i64(cpu_F1d, cpu_env,              \
1014                            ucf64_reg_offset(UCOP_REG_M)); \
1015             gen_helper_ucf64_##name##d(cpu_F0d,           \
1016                            cpu_F0d, cpu_F1d, cpu_env);    \
1017             tcg_gen_st_i64(cpu_F0d, cpu_env,              \
1018                            ucf64_reg_offset(UCOP_REG_D)); \
1019             break;                                        \
1020         case 2 /* w */:                                   \
1021             ILLEGAL;                                      \
1022             break;                                        \
1023         }                                                 \
1024     } while (0)
1025
1026 /* UniCore-F64 data processing */
1027 static void do_ucf64_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1028 {
1029     UniCore32CPU *cpu = uc32_env_get_cpu(env);
1030
1031     if (UCOP_UCF64_FMT == 3) {
1032         ILLEGAL;
1033     }
1034     switch (UCOP_UCF64_FUNC) {
1035     case 0: /* add */
1036         UCF64_OP2(add);
1037         break;
1038     case 1: /* sub */
1039         UCF64_OP2(sub);
1040         break;
1041     case 2: /* mul */
1042         UCF64_OP2(mul);
1043         break;
1044     case 4: /* div */
1045         UCF64_OP2(div);
1046         break;
1047     case 5: /* abs */
1048         UCF64_OP1(abs);
1049         break;
1050     case 6: /* mov */
1051         UCF64_OP1(mov);
1052         break;
1053     case 7: /* neg */
1054         UCF64_OP1(neg);
1055         break;
1056     default:
1057         ILLEGAL;
1058     }
1059 }
1060
1061 /* Disassemble an F64 instruction */
1062 static void disas_ucf64_insn(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1063 {
1064     UniCore32CPU *cpu = uc32_env_get_cpu(env);
1065
1066     if (!UCOP_SET(29)) {
1067         if (UCOP_SET(26)) {
1068             do_ucf64_ldst_m(env, s, insn);
1069         } else {
1070             do_ucf64_ldst_i(env, s, insn);
1071         }
1072     } else {
1073         if (UCOP_SET(5)) {
1074             switch ((insn >> 26) & 0x3) {
1075             case 0:
1076                 do_ucf64_datap(env, s, insn);
1077                 break;
1078             case 1:
1079                 ILLEGAL;
1080                 break;
1081             case 2:
1082                 do_ucf64_fcvt(env, s, insn);
1083                 break;
1084             case 3:
1085                 do_ucf64_fcmp(env, s, insn);
1086                 break;
1087             }
1088         } else {
1089             do_ucf64_trans(env, s, insn);
1090         }
1091     }
1092 }
1093
1094 static inline bool use_goto_tb(DisasContext *s, uint32_t dest)
1095 {
1096 #ifndef CONFIG_USER_ONLY
1097     return (s->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
1098 #else
1099     return true;
1100 #endif
1101 }
1102
1103 static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
1104 {
1105     if (use_goto_tb(s, dest)) {
1106         tcg_gen_goto_tb(n);
1107         gen_set_pc_im(dest);
1108         tcg_gen_exit_tb((uintptr_t)s->tb + n);
1109     } else {
1110         gen_set_pc_im(dest);
1111         tcg_gen_exit_tb(0);
1112     }
1113 }
1114
1115 static inline void gen_jmp(DisasContext *s, uint32_t dest)
1116 {
1117     if (unlikely(s->singlestep_enabled)) {
1118         /* An indirect jump so that we still trigger the debug exception.  */
1119         gen_bx_im(s, dest);
1120     } else {
1121         gen_goto_tb(s, 0, dest);
1122         s->is_jmp = DISAS_TB_JUMP;
1123     }
1124 }
1125
1126 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
1127 static int gen_set_psr(DisasContext *s, uint32_t mask, int bsr, TCGv t0)
1128 {
1129     TCGv tmp;
1130     if (bsr) {
1131         /* ??? This is also undefined in system mode.  */
1132         if (IS_USER(s)) {
1133             return 1;
1134         }
1135
1136         tmp = load_cpu_field(bsr);
1137         tcg_gen_andi_i32(tmp, tmp, ~mask);
1138         tcg_gen_andi_i32(t0, t0, mask);
1139         tcg_gen_or_i32(tmp, tmp, t0);
1140         store_cpu_field(tmp, bsr);
1141     } else {
1142         gen_set_asr(t0, mask);
1143     }
1144     dead_tmp(t0);
1145     gen_lookup_tb(s);
1146     return 0;
1147 }
1148
1149 /* Generate an old-style exception return. Marks pc as dead. */
1150 static void gen_exception_return(DisasContext *s, TCGv pc)
1151 {
1152     TCGv tmp;
1153     store_reg(s, 31, pc);
1154     tmp = load_cpu_field(bsr);
1155     gen_set_asr(tmp, 0xffffffff);
1156     dead_tmp(tmp);
1157     s->is_jmp = DISAS_UPDATE;
1158 }
1159
1160 static void disas_coproc_insn(CPUUniCore32State *env, DisasContext *s,
1161         uint32_t insn)
1162 {
1163     UniCore32CPU *cpu = uc32_env_get_cpu(env);
1164
1165     switch (UCOP_CPNUM) {
1166 #ifndef CONFIG_USER_ONLY
1167     case 0:
1168         disas_cp0_insn(env, s, insn);
1169         break;
1170     case 1:
1171         disas_ocd_insn(env, s, insn);
1172         break;
1173 #endif
1174     case 2:
1175         disas_ucf64_insn(env, s, insn);
1176         break;
1177     default:
1178         /* Unknown coprocessor. */
1179         cpu_abort(CPU(cpu), "Unknown coprocessor!");
1180     }
1181 }
1182
1183 /* data processing instructions */
1184 static void do_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1185 {
1186     UniCore32CPU *cpu = uc32_env_get_cpu(env);
1187     TCGv tmp;
1188     TCGv tmp2;
1189     int logic_cc;
1190
1191     if (UCOP_OPCODES == 0x0f || UCOP_OPCODES == 0x0d) {
1192         if (UCOP_SET(23)) { /* CMOV instructions */
1193             if ((UCOP_CMOV_COND == 0xe) || (UCOP_CMOV_COND == 0xf)) {
1194                 ILLEGAL;
1195             }
1196             /* if not always execute, we generate a conditional jump to
1197                next instruction */
1198             s->condlabel = gen_new_label();
1199             gen_test_cc(UCOP_CMOV_COND ^ 1, s->condlabel);
1200             s->condjmp = 1;
1201         }
1202     }
1203
1204     logic_cc = table_logic_cc[UCOP_OPCODES] & (UCOP_SET_S >> 24);
1205
1206     if (UCOP_SET(29)) {
1207         unsigned int val;
1208         /* immediate operand */
1209         val = UCOP_IMM_9;
1210         if (UCOP_SH_IM) {
1211             val = (val >> UCOP_SH_IM) | (val << (32 - UCOP_SH_IM));
1212         }
1213         tmp2 = new_tmp();
1214         tcg_gen_movi_i32(tmp2, val);
1215         if (logic_cc && UCOP_SH_IM) {
1216             gen_set_CF_bit31(tmp2);
1217         }
1218    } else {
1219         /* register */
1220         tmp2 = load_reg(s, UCOP_REG_M);
1221         if (UCOP_SET(5)) {
1222             tmp = load_reg(s, UCOP_REG_S);
1223             gen_uc32_shift_reg(tmp2, UCOP_SH_OP, tmp, logic_cc);
1224         } else {
1225             gen_uc32_shift_im(tmp2, UCOP_SH_OP, UCOP_SH_IM, logic_cc);
1226         }
1227     }
1228
1229     if (UCOP_OPCODES != 0x0f && UCOP_OPCODES != 0x0d) {
1230         tmp = load_reg(s, UCOP_REG_N);
1231     } else {
1232         TCGV_UNUSED(tmp);
1233     }
1234
1235     switch (UCOP_OPCODES) {
1236     case 0x00:
1237         tcg_gen_and_i32(tmp, tmp, tmp2);
1238         if (logic_cc) {
1239             gen_logic_CC(tmp);
1240         }
1241         store_reg_bx(s, UCOP_REG_D, tmp);
1242         break;
1243     case 0x01:
1244         tcg_gen_xor_i32(tmp, tmp, tmp2);
1245         if (logic_cc) {
1246             gen_logic_CC(tmp);
1247         }
1248         store_reg_bx(s, UCOP_REG_D, tmp);
1249         break;
1250     case 0x02:
1251         if (UCOP_SET_S && UCOP_REG_D == 31) {
1252             /* SUBS r31, ... is used for exception return.  */
1253             if (IS_USER(s)) {
1254                 ILLEGAL;
1255             }
1256             gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
1257             gen_exception_return(s, tmp);
1258         } else {
1259             if (UCOP_SET_S) {
1260                 gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
1261             } else {
1262                 tcg_gen_sub_i32(tmp, tmp, tmp2);
1263             }
1264             store_reg_bx(s, UCOP_REG_D, tmp);
1265         }
1266         break;
1267     case 0x03:
1268         if (UCOP_SET_S) {
1269             gen_helper_sub_cc(tmp, cpu_env, tmp2, tmp);
1270         } else {
1271             tcg_gen_sub_i32(tmp, tmp2, tmp);
1272         }
1273         store_reg_bx(s, UCOP_REG_D, tmp);
1274         break;
1275     case 0x04:
1276         if (UCOP_SET_S) {
1277             gen_helper_add_cc(tmp, cpu_env, tmp, tmp2);
1278         } else {
1279             tcg_gen_add_i32(tmp, tmp, tmp2);
1280         }
1281         store_reg_bx(s, UCOP_REG_D, tmp);
1282         break;
1283     case 0x05:
1284         if (UCOP_SET_S) {
1285             gen_helper_adc_cc(tmp, cpu_env, tmp, tmp2);
1286         } else {
1287             gen_add_carry(tmp, tmp, tmp2);
1288         }
1289         store_reg_bx(s, UCOP_REG_D, tmp);
1290         break;
1291     case 0x06:
1292         if (UCOP_SET_S) {
1293             gen_helper_sbc_cc(tmp, cpu_env, tmp, tmp2);
1294         } else {
1295             gen_sub_carry(tmp, tmp, tmp2);
1296         }
1297         store_reg_bx(s, UCOP_REG_D, tmp);
1298         break;
1299     case 0x07:
1300         if (UCOP_SET_S) {
1301             gen_helper_sbc_cc(tmp, cpu_env, tmp2, tmp);
1302         } else {
1303             gen_sub_carry(tmp, tmp2, tmp);
1304         }
1305         store_reg_bx(s, UCOP_REG_D, tmp);
1306         break;
1307     case 0x08:
1308         if (UCOP_SET_S) {
1309             tcg_gen_and_i32(tmp, tmp, tmp2);
1310             gen_logic_CC(tmp);
1311         }
1312         dead_tmp(tmp);
1313         break;
1314     case 0x09:
1315         if (UCOP_SET_S) {
1316             tcg_gen_xor_i32(tmp, tmp, tmp2);
1317             gen_logic_CC(tmp);
1318         }
1319         dead_tmp(tmp);
1320         break;
1321     case 0x0a:
1322         if (UCOP_SET_S) {
1323             gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
1324         }
1325         dead_tmp(tmp);
1326         break;
1327     case 0x0b:
1328         if (UCOP_SET_S) {
1329             gen_helper_add_cc(tmp, cpu_env, tmp, tmp2);
1330         }
1331         dead_tmp(tmp);
1332         break;
1333     case 0x0c:
1334         tcg_gen_or_i32(tmp, tmp, tmp2);
1335         if (logic_cc) {
1336             gen_logic_CC(tmp);
1337         }
1338         store_reg_bx(s, UCOP_REG_D, tmp);
1339         break;
1340     case 0x0d:
1341         if (logic_cc && UCOP_REG_D == 31) {
1342             /* MOVS r31, ... is used for exception return.  */
1343             if (IS_USER(s)) {
1344                 ILLEGAL;
1345             }
1346             gen_exception_return(s, tmp2);
1347         } else {
1348             if (logic_cc) {
1349                 gen_logic_CC(tmp2);
1350             }
1351             store_reg_bx(s, UCOP_REG_D, tmp2);
1352         }
1353         break;
1354     case 0x0e:
1355         tcg_gen_andc_i32(tmp, tmp, tmp2);
1356         if (logic_cc) {
1357             gen_logic_CC(tmp);
1358         }
1359         store_reg_bx(s, UCOP_REG_D, tmp);
1360         break;
1361     default:
1362     case 0x0f:
1363         tcg_gen_not_i32(tmp2, tmp2);
1364         if (logic_cc) {
1365             gen_logic_CC(tmp2);
1366         }
1367         store_reg_bx(s, UCOP_REG_D, tmp2);
1368         break;
1369     }
1370     if (UCOP_OPCODES != 0x0f && UCOP_OPCODES != 0x0d) {
1371         dead_tmp(tmp2);
1372     }
1373 }
1374
1375 /* multiply */
1376 static void do_mult(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1377 {
1378     TCGv tmp, tmp2, tmp3, tmp4;
1379
1380     if (UCOP_SET(27)) {
1381         /* 64 bit mul */
1382         tmp = load_reg(s, UCOP_REG_M);
1383         tmp2 = load_reg(s, UCOP_REG_N);
1384         if (UCOP_SET(26)) {
1385             tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2);
1386         } else {
1387             tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2);
1388         }
1389         if (UCOP_SET(25)) { /* mult accumulate */
1390             tmp3 = load_reg(s, UCOP_REG_LO);
1391             tmp4 = load_reg(s, UCOP_REG_HI);
1392             tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, tmp3, tmp4);
1393             dead_tmp(tmp3);
1394             dead_tmp(tmp4);
1395         }
1396         store_reg(s, UCOP_REG_LO, tmp);
1397         store_reg(s, UCOP_REG_HI, tmp2);
1398     } else {
1399         /* 32 bit mul */
1400         tmp = load_reg(s, UCOP_REG_M);
1401         tmp2 = load_reg(s, UCOP_REG_N);
1402         tcg_gen_mul_i32(tmp, tmp, tmp2);
1403         dead_tmp(tmp2);
1404         if (UCOP_SET(25)) {
1405             /* Add */
1406             tmp2 = load_reg(s, UCOP_REG_S);
1407             tcg_gen_add_i32(tmp, tmp, tmp2);
1408             dead_tmp(tmp2);
1409         }
1410         if (UCOP_SET_S) {
1411             gen_logic_CC(tmp);
1412         }
1413         store_reg(s, UCOP_REG_D, tmp);
1414     }
1415 }
1416
1417 /* miscellaneous instructions */
1418 static void do_misc(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1419 {
1420     UniCore32CPU *cpu = uc32_env_get_cpu(env);
1421     unsigned int val;
1422     TCGv tmp;
1423
1424     if ((insn & 0xffffffe0) == 0x10ffc120) {
1425         /* Trivial implementation equivalent to bx.  */
1426         tmp = load_reg(s, UCOP_REG_M);
1427         gen_bx(s, tmp);
1428         return;
1429     }
1430
1431     if ((insn & 0xfbffc000) == 0x30ffc000) {
1432         /* PSR = immediate */
1433         val = UCOP_IMM_9;
1434         if (UCOP_SH_IM) {
1435             val = (val >> UCOP_SH_IM) | (val << (32 - UCOP_SH_IM));
1436         }
1437         tmp = new_tmp();
1438         tcg_gen_movi_i32(tmp, val);
1439         if (gen_set_psr(s, ~ASR_RESERVED, UCOP_SET_B, tmp)) {
1440             ILLEGAL;
1441         }
1442         return;
1443     }
1444
1445     if ((insn & 0xfbffffe0) == 0x12ffc020) {
1446         /* PSR.flag = reg */
1447         tmp = load_reg(s, UCOP_REG_M);
1448         if (gen_set_psr(s, ASR_NZCV, UCOP_SET_B, tmp)) {
1449             ILLEGAL;
1450         }
1451         return;
1452     }
1453
1454     if ((insn & 0xfbffffe0) == 0x10ffc020) {
1455         /* PSR = reg */
1456         tmp = load_reg(s, UCOP_REG_M);
1457         if (gen_set_psr(s, ~ASR_RESERVED, UCOP_SET_B, tmp)) {
1458             ILLEGAL;
1459         }
1460         return;
1461     }
1462
1463     if ((insn & 0xfbf83fff) == 0x10f80000) {
1464         /* reg = PSR */
1465         if (UCOP_SET_B) {
1466             if (IS_USER(s)) {
1467                 ILLEGAL;
1468             }
1469             tmp = load_cpu_field(bsr);
1470         } else {
1471             tmp = new_tmp();
1472             gen_helper_asr_read(tmp, cpu_env);
1473         }
1474         store_reg(s, UCOP_REG_D, tmp);
1475         return;
1476     }
1477
1478     if ((insn & 0xfbf83fe0) == 0x12f80120) {
1479         /* clz */
1480         tmp = load_reg(s, UCOP_REG_M);
1481         if (UCOP_SET(26)) {
1482             gen_helper_clo(tmp, tmp);
1483         } else {
1484             gen_helper_clz(tmp, tmp);
1485         }
1486         store_reg(s, UCOP_REG_D, tmp);
1487         return;
1488     }
1489
1490     /* otherwise */
1491     ILLEGAL;
1492 }
1493
1494 /* load/store I_offset and R_offset */
1495 static void do_ldst_ir(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1496 {
1497     unsigned int mmu_idx;
1498     TCGv tmp;
1499     TCGv tmp2;
1500
1501     tmp2 = load_reg(s, UCOP_REG_N);
1502     mmu_idx = (IS_USER(s) || (!UCOP_SET_P && UCOP_SET_W));
1503
1504     /* immediate */
1505     if (UCOP_SET_P) {
1506         gen_add_data_offset(s, insn, tmp2);
1507     }
1508
1509     if (UCOP_SET_L) {
1510         /* load */
1511         if (UCOP_SET_B) {
1512             tmp = gen_ld8u(tmp2, mmu_idx);
1513         } else {
1514             tmp = gen_ld32(tmp2, mmu_idx);
1515         }
1516     } else {
1517         /* store */
1518         tmp = load_reg(s, UCOP_REG_D);
1519         if (UCOP_SET_B) {
1520             gen_st8(tmp, tmp2, mmu_idx);
1521         } else {
1522             gen_st32(tmp, tmp2, mmu_idx);
1523         }
1524     }
1525     if (!UCOP_SET_P) {
1526         gen_add_data_offset(s, insn, tmp2);
1527         store_reg(s, UCOP_REG_N, tmp2);
1528     } else if (UCOP_SET_W) {
1529         store_reg(s, UCOP_REG_N, tmp2);
1530     } else {
1531         dead_tmp(tmp2);
1532     }
1533     if (UCOP_SET_L) {
1534         /* Complete the load.  */
1535         if (UCOP_REG_D == 31) {
1536             gen_bx(s, tmp);
1537         } else {
1538             store_reg(s, UCOP_REG_D, tmp);
1539         }
1540     }
1541 }
1542
1543 /* SWP instruction */
1544 static void do_swap(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1545 {
1546     UniCore32CPU *cpu = uc32_env_get_cpu(env);
1547     TCGv addr;
1548     TCGv tmp;
1549     TCGv tmp2;
1550
1551     if ((insn & 0xff003fe0) != 0x40000120) {
1552         ILLEGAL;
1553     }
1554
1555     /* ??? This is not really atomic.  However we know
1556        we never have multiple CPUs running in parallel,
1557        so it is good enough.  */
1558     addr = load_reg(s, UCOP_REG_N);
1559     tmp = load_reg(s, UCOP_REG_M);
1560     if (UCOP_SET_B) {
1561         tmp2 = gen_ld8u(addr, IS_USER(s));
1562         gen_st8(tmp, addr, IS_USER(s));
1563     } else {
1564         tmp2 = gen_ld32(addr, IS_USER(s));
1565         gen_st32(tmp, addr, IS_USER(s));
1566     }
1567     dead_tmp(addr);
1568     store_reg(s, UCOP_REG_D, tmp2);
1569 }
1570
1571 /* load/store hw/sb */
1572 static void do_ldst_hwsb(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1573 {
1574     UniCore32CPU *cpu = uc32_env_get_cpu(env);
1575     TCGv addr;
1576     TCGv tmp;
1577
1578     if (UCOP_SH_OP == 0) {
1579         do_swap(env, s, insn);
1580         return;
1581     }
1582
1583     addr = load_reg(s, UCOP_REG_N);
1584     if (UCOP_SET_P) {
1585         gen_add_datah_offset(s, insn, addr);
1586     }
1587
1588     if (UCOP_SET_L) { /* load */
1589         switch (UCOP_SH_OP) {
1590         case 1:
1591             tmp = gen_ld16u(addr, IS_USER(s));
1592             break;
1593         case 2:
1594             tmp = gen_ld8s(addr, IS_USER(s));
1595             break;
1596         default: /* see do_swap */
1597         case 3:
1598             tmp = gen_ld16s(addr, IS_USER(s));
1599             break;
1600         }
1601     } else { /* store */
1602         if (UCOP_SH_OP != 1) {
1603             ILLEGAL;
1604         }
1605         tmp = load_reg(s, UCOP_REG_D);
1606         gen_st16(tmp, addr, IS_USER(s));
1607     }
1608     /* Perform base writeback before the loaded value to
1609        ensure correct behavior with overlapping index registers. */
1610     if (!UCOP_SET_P) {
1611         gen_add_datah_offset(s, insn, addr);
1612         store_reg(s, UCOP_REG_N, addr);
1613     } else if (UCOP_SET_W) {
1614         store_reg(s, UCOP_REG_N, addr);
1615     } else {
1616         dead_tmp(addr);
1617     }
1618     if (UCOP_SET_L) {
1619         /* Complete the load.  */
1620         store_reg(s, UCOP_REG_D, tmp);
1621     }
1622 }
1623
1624 /* load/store multiple words */
1625 static void do_ldst_m(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1626 {
1627     UniCore32CPU *cpu = uc32_env_get_cpu(env);
1628     unsigned int val, i, mmu_idx;
1629     int j, n, reg, user, loaded_base;
1630     TCGv tmp;
1631     TCGv tmp2;
1632     TCGv addr;
1633     TCGv loaded_var;
1634
1635     if (UCOP_SET(7)) {
1636         ILLEGAL;
1637     }
1638     /* XXX: store correct base if write back */
1639     user = 0;
1640     if (UCOP_SET_B) { /* S bit in instruction table */
1641         if (IS_USER(s)) {
1642             ILLEGAL; /* only usable in supervisor mode */
1643         }
1644         if (UCOP_SET(18) == 0) { /* pc reg */
1645             user = 1;
1646         }
1647     }
1648
1649     mmu_idx = (IS_USER(s) || (!UCOP_SET_P && UCOP_SET_W));
1650     addr = load_reg(s, UCOP_REG_N);
1651
1652     /* compute total size */
1653     loaded_base = 0;
1654     TCGV_UNUSED(loaded_var);
1655     n = 0;
1656     for (i = 0; i < 6; i++) {
1657         if (UCOP_SET(i)) {
1658             n++;
1659         }
1660     }
1661     for (i = 9; i < 19; i++) {
1662         if (UCOP_SET(i)) {
1663             n++;
1664         }
1665     }
1666     /* XXX: test invalid n == 0 case ? */
1667     if (UCOP_SET_U) {
1668         if (UCOP_SET_P) {
1669             /* pre increment */
1670             tcg_gen_addi_i32(addr, addr, 4);
1671         } else {
1672             /* post increment */
1673         }
1674     } else {
1675         if (UCOP_SET_P) {
1676             /* pre decrement */
1677             tcg_gen_addi_i32(addr, addr, -(n * 4));
1678         } else {
1679             /* post decrement */
1680             if (n != 1) {
1681                 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
1682             }
1683         }
1684     }
1685
1686     j = 0;
1687     reg = UCOP_SET(6) ? 16 : 0;
1688     for (i = 0; i < 19; i++, reg++) {
1689         if (i == 6) {
1690             i = i + 3;
1691         }
1692         if (UCOP_SET(i)) {
1693             if (UCOP_SET_L) { /* load */
1694                 tmp = gen_ld32(addr, mmu_idx);
1695                 if (reg == 31) {
1696                     gen_bx(s, tmp);
1697                 } else if (user) {
1698                     tmp2 = tcg_const_i32(reg);
1699                     gen_helper_set_user_reg(cpu_env, tmp2, tmp);
1700                     tcg_temp_free_i32(tmp2);
1701                     dead_tmp(tmp);
1702                 } else if (reg == UCOP_REG_N) {
1703                     loaded_var = tmp;
1704                     loaded_base = 1;
1705                 } else {
1706                     store_reg(s, reg, tmp);
1707                 }
1708             } else { /* store */
1709                 if (reg == 31) {
1710                     /* special case: r31 = PC + 4 */
1711                     val = (long)s->pc;
1712                     tmp = new_tmp();
1713                     tcg_gen_movi_i32(tmp, val);
1714                 } else if (user) {
1715                     tmp = new_tmp();
1716                     tmp2 = tcg_const_i32(reg);
1717                     gen_helper_get_user_reg(tmp, cpu_env, tmp2);
1718                     tcg_temp_free_i32(tmp2);
1719                 } else {
1720                     tmp = load_reg(s, reg);
1721                 }
1722                 gen_st32(tmp, addr, mmu_idx);
1723             }
1724             j++;
1725             /* no need to add after the last transfer */
1726             if (j != n) {
1727                 tcg_gen_addi_i32(addr, addr, 4);
1728             }
1729         }
1730     }
1731     if (UCOP_SET_W) { /* write back */
1732         if (UCOP_SET_U) {
1733             if (UCOP_SET_P) {
1734                 /* pre increment */
1735             } else {
1736                 /* post increment */
1737                 tcg_gen_addi_i32(addr, addr, 4);
1738             }
1739         } else {
1740             if (UCOP_SET_P) {
1741                 /* pre decrement */
1742                 if (n != 1) {
1743                     tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
1744                 }
1745             } else {
1746                 /* post decrement */
1747                 tcg_gen_addi_i32(addr, addr, -(n * 4));
1748             }
1749         }
1750         store_reg(s, UCOP_REG_N, addr);
1751     } else {
1752         dead_tmp(addr);
1753     }
1754     if (loaded_base) {
1755         store_reg(s, UCOP_REG_N, loaded_var);
1756     }
1757     if (UCOP_SET_B && !user) {
1758         /* Restore ASR from BSR.  */
1759         tmp = load_cpu_field(bsr);
1760         gen_set_asr(tmp, 0xffffffff);
1761         dead_tmp(tmp);
1762         s->is_jmp = DISAS_UPDATE;
1763     }
1764 }
1765
1766 /* branch (and link) */
1767 static void do_branch(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
1768 {
1769     UniCore32CPU *cpu = uc32_env_get_cpu(env);
1770     unsigned int val;
1771     int32_t offset;
1772     TCGv tmp;
1773
1774     if (UCOP_COND == 0xf) {
1775         ILLEGAL;
1776     }
1777
1778     if (UCOP_COND != 0xe) {
1779         /* if not always execute, we generate a conditional jump to
1780            next instruction */
1781         s->condlabel = gen_new_label();
1782         gen_test_cc(UCOP_COND ^ 1, s->condlabel);
1783         s->condjmp = 1;
1784     }
1785
1786     val = (int32_t)s->pc;
1787     if (UCOP_SET_L) {
1788         tmp = new_tmp();
1789         tcg_gen_movi_i32(tmp, val);
1790         store_reg(s, 30, tmp);
1791     }
1792     offset = (((int32_t)insn << 8) >> 8);
1793     val += (offset << 2); /* unicore is pc+4 */
1794     gen_jmp(s, val);
1795 }
1796
1797 static void disas_uc32_insn(CPUUniCore32State *env, DisasContext *s)
1798 {
1799     UniCore32CPU *cpu = uc32_env_get_cpu(env);
1800     unsigned int insn;
1801
1802     insn = cpu_ldl_code(env, s->pc);
1803     s->pc += 4;
1804
1805     /* UniCore instructions class:
1806      * AAAB BBBC xxxx xxxx xxxx xxxD xxEx xxxx
1807      * AAA  : see switch case
1808      * BBBB : opcodes or cond or PUBW
1809      * C    : S OR L
1810      * D    : 8
1811      * E    : 5
1812      */
1813     switch (insn >> 29) {
1814     case 0x0:
1815         if (UCOP_SET(5) && UCOP_SET(8) && !UCOP_SET(28)) {
1816             do_mult(env, s, insn);
1817             break;
1818         }
1819
1820         if (UCOP_SET(8)) {
1821             do_misc(env, s, insn);
1822             break;
1823         }
1824     case 0x1:
1825         if (((UCOP_OPCODES >> 2) == 2) && !UCOP_SET_S) {
1826             do_misc(env, s, insn);
1827             break;
1828         }
1829         do_datap(env, s, insn);
1830         break;
1831
1832     case 0x2:
1833         if (UCOP_SET(8) && UCOP_SET(5)) {
1834             do_ldst_hwsb(env, s, insn);
1835             break;
1836         }
1837         if (UCOP_SET(8) || UCOP_SET(5)) {
1838             ILLEGAL;
1839         }
1840     case 0x3:
1841         do_ldst_ir(env, s, insn);
1842         break;
1843
1844     case 0x4:
1845         if (UCOP_SET(8)) {
1846             ILLEGAL; /* extended instructions */
1847         }
1848         do_ldst_m(env, s, insn);
1849         break;
1850     case 0x5:
1851         do_branch(env, s, insn);
1852         break;
1853     case 0x6:
1854         /* Coprocessor.  */
1855         disas_coproc_insn(env, s, insn);
1856         break;
1857     case 0x7:
1858         if (!UCOP_SET(28)) {
1859             disas_coproc_insn(env, s, insn);
1860             break;
1861         }
1862         if ((insn & 0xff000000) == 0xff000000) { /* syscall */
1863             gen_set_pc_im(s->pc);
1864             s->is_jmp = DISAS_SYSCALL;
1865             break;
1866         }
1867         ILLEGAL;
1868     }
1869 }
1870
1871 /* generate intermediate code for basic block 'tb'.  */
1872 void gen_intermediate_code(CPUUniCore32State *env, TranslationBlock *tb)
1873 {
1874     UniCore32CPU *cpu = uc32_env_get_cpu(env);
1875     CPUState *cs = CPU(cpu);
1876     DisasContext dc1, *dc = &dc1;
1877     target_ulong pc_start;
1878     uint32_t next_page_start;
1879     int num_insns;
1880     int max_insns;
1881
1882     /* generate intermediate code */
1883     num_temps = 0;
1884
1885     pc_start = tb->pc;
1886
1887     dc->tb = tb;
1888
1889     dc->is_jmp = DISAS_NEXT;
1890     dc->pc = pc_start;
1891     dc->singlestep_enabled = cs->singlestep_enabled;
1892     dc->condjmp = 0;
1893     cpu_F0s = tcg_temp_new_i32();
1894     cpu_F1s = tcg_temp_new_i32();
1895     cpu_F0d = tcg_temp_new_i64();
1896     cpu_F1d = tcg_temp_new_i64();
1897     next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
1898     num_insns = 0;
1899     max_insns = tb->cflags & CF_COUNT_MASK;
1900     if (max_insns == 0) {
1901         max_insns = CF_COUNT_MASK;
1902     }
1903     if (max_insns > TCG_MAX_INSNS) {
1904         max_insns = TCG_MAX_INSNS;
1905     }
1906
1907 #ifndef CONFIG_USER_ONLY
1908     if ((env->uncached_asr & ASR_M) == ASR_MODE_USER) {
1909         dc->user = 1;
1910     } else {
1911         dc->user = 0;
1912     }
1913 #endif
1914
1915     gen_tb_start(tb);
1916     do {
1917         tcg_gen_insn_start(dc->pc);
1918         num_insns++;
1919
1920         if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
1921             gen_set_pc_im(dc->pc);
1922             gen_exception(EXCP_DEBUG);
1923             dc->is_jmp = DISAS_JUMP;
1924             /* The address covered by the breakpoint must be included in
1925                [tb->pc, tb->pc + tb->size) in order to for it to be
1926                properly cleared -- thus we increment the PC here so that
1927                the logic setting tb->size below does the right thing.  */
1928             dc->pc += 4;
1929             goto done_generating;
1930         }
1931
1932         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
1933             gen_io_start();
1934         }
1935
1936         disas_uc32_insn(env, dc);
1937
1938         if (num_temps) {
1939             fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
1940             num_temps = 0;
1941         }
1942
1943         if (dc->condjmp && !dc->is_jmp) {
1944             gen_set_label(dc->condlabel);
1945             dc->condjmp = 0;
1946         }
1947         /* Translation stops when a conditional branch is encountered.
1948          * Otherwise the subsequent code could get translated several times.
1949          * Also stop translation when a page boundary is reached.  This
1950          * ensures prefetch aborts occur at the right place.  */
1951     } while (!dc->is_jmp && !tcg_op_buf_full() &&
1952              !cs->singlestep_enabled &&
1953              !singlestep &&
1954              dc->pc < next_page_start &&
1955              num_insns < max_insns);
1956
1957     if (tb->cflags & CF_LAST_IO) {
1958         if (dc->condjmp) {
1959             /* FIXME:  This can theoretically happen with self-modifying
1960                code.  */
1961             cpu_abort(cs, "IO on conditional branch instruction");
1962         }
1963         gen_io_end();
1964     }
1965
1966     /* At this stage dc->condjmp will only be set when the skipped
1967        instruction was a conditional branch or trap, and the PC has
1968        already been written.  */
1969     if (unlikely(cs->singlestep_enabled)) {
1970         /* Make sure the pc is updated, and raise a debug exception.  */
1971         if (dc->condjmp) {
1972             if (dc->is_jmp == DISAS_SYSCALL) {
1973                 gen_exception(UC32_EXCP_PRIV);
1974             } else {
1975                 gen_exception(EXCP_DEBUG);
1976             }
1977             gen_set_label(dc->condlabel);
1978         }
1979         if (dc->condjmp || !dc->is_jmp) {
1980             gen_set_pc_im(dc->pc);
1981             dc->condjmp = 0;
1982         }
1983         if (dc->is_jmp == DISAS_SYSCALL && !dc->condjmp) {
1984             gen_exception(UC32_EXCP_PRIV);
1985         } else {
1986             gen_exception(EXCP_DEBUG);
1987         }
1988     } else {
1989         /* While branches must always occur at the end of an IT block,
1990            there are a few other things that can cause us to terminate
1991            the TB in the middel of an IT block:
1992             - Exception generating instructions (bkpt, swi, undefined).
1993             - Page boundaries.
1994             - Hardware watchpoints.
1995            Hardware breakpoints have already been handled and skip this code.
1996          */
1997         switch (dc->is_jmp) {
1998         case DISAS_NEXT:
1999             gen_goto_tb(dc, 1, dc->pc);
2000             break;
2001         default:
2002         case DISAS_JUMP:
2003         case DISAS_UPDATE:
2004             /* indicate that the hash table must be used to find the next TB */
2005             tcg_gen_exit_tb(0);
2006             break;
2007         case DISAS_TB_JUMP:
2008             /* nothing more to generate */
2009             break;
2010         case DISAS_SYSCALL:
2011             gen_exception(UC32_EXCP_PRIV);
2012             break;
2013         }
2014         if (dc->condjmp) {
2015             gen_set_label(dc->condlabel);
2016             gen_goto_tb(dc, 1, dc->pc);
2017             dc->condjmp = 0;
2018         }
2019     }
2020
2021 done_generating:
2022     gen_tb_end(tb, num_insns);
2023
2024 #ifdef DEBUG_DISAS
2025     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
2026         && qemu_log_in_addr_range(pc_start)) {
2027         qemu_log_lock();
2028         qemu_log("----------------\n");
2029         qemu_log("IN: %s\n", lookup_symbol(pc_start));
2030         log_target_disas(cs, pc_start, dc->pc - pc_start, 0);
2031         qemu_log("\n");
2032         qemu_log_unlock();
2033     }
2034 #endif
2035     tb->size = dc->pc - pc_start;
2036     tb->icount = num_insns;
2037 }
2038
2039 static const char *cpu_mode_names[16] = {
2040     "USER", "REAL", "INTR", "PRIV", "UM14", "UM15", "UM16", "TRAP",
2041     "UM18", "UM19", "UM1A", "EXTN", "UM1C", "UM1D", "UM1E", "SUSR"
2042 };
2043
2044 #undef UCF64_DUMP_STATE
2045 #ifdef UCF64_DUMP_STATE
2046 static void cpu_dump_state_ucf64(CPUUniCore32State *env, FILE *f,
2047         fprintf_function cpu_fprintf, int flags)
2048 {
2049     int i;
2050     union {
2051         uint32_t i;
2052         float s;
2053     } s0, s1;
2054     CPU_DoubleU d;
2055     /* ??? This assumes float64 and double have the same layout.
2056        Oh well, it's only debug dumps.  */
2057     union {
2058         float64 f64;
2059         double d;
2060     } d0;
2061
2062     for (i = 0; i < 16; i++) {
2063         d.d = env->ucf64.regs[i];
2064         s0.i = d.l.lower;
2065         s1.i = d.l.upper;
2066         d0.f64 = d.d;
2067         cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g)",
2068                     i * 2, (int)s0.i, s0.s,
2069                     i * 2 + 1, (int)s1.i, s1.s);
2070         cpu_fprintf(f, " d%02d=%" PRIx64 "(%8g)\n",
2071                     i, (uint64_t)d0.f64, d0.d);
2072     }
2073     cpu_fprintf(f, "FPSCR: %08x\n", (int)env->ucf64.xregs[UC32_UCF64_FPSCR]);
2074 }
2075 #else
2076 #define cpu_dump_state_ucf64(env, file, pr, flags)      do { } while (0)
2077 #endif
2078
2079 void uc32_cpu_dump_state(CPUState *cs, FILE *f,
2080                          fprintf_function cpu_fprintf, int flags)
2081 {
2082     UniCore32CPU *cpu = UNICORE32_CPU(cs);
2083     CPUUniCore32State *env = &cpu->env;
2084     int i;
2085     uint32_t psr;
2086
2087     for (i = 0; i < 32; i++) {
2088         cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
2089         if ((i % 4) == 3) {
2090             cpu_fprintf(f, "\n");
2091         } else {
2092             cpu_fprintf(f, " ");
2093         }
2094     }
2095     psr = cpu_asr_read(env);
2096     cpu_fprintf(f, "PSR=%08x %c%c%c%c %s\n",
2097                 psr,
2098                 psr & (1 << 31) ? 'N' : '-',
2099                 psr & (1 << 30) ? 'Z' : '-',
2100                 psr & (1 << 29) ? 'C' : '-',
2101                 psr & (1 << 28) ? 'V' : '-',
2102                 cpu_mode_names[psr & 0xf]);
2103
2104     cpu_dump_state_ucf64(env, f, cpu_fprintf, flags);
2105 }
2106
2107 void restore_state_to_opc(CPUUniCore32State *env, TranslationBlock *tb,
2108                           target_ulong *data)
2109 {
2110     env->regs[31] = data[0];
2111 }
This page took 0.147245 seconds and 4 git commands to generate.