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