1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include "qemu/osdep.h"
25#include "cpu.h"
26#include "tcg-op.h"
27#include "exec/exec-all.h"
28#include "disas/disas.h"
29#include "exec/helper-proto.h"
30#include "exec/helper-gen.h"
31#include "exec/log.h"
32#include "exec/cpu_ldst.h"
33#include "exec/translator.h"
34
35
36#define DISAS_JUMP DISAS_TARGET_0
37#define DISAS_UPDATE DISAS_TARGET_1
38#define DISAS_TB_JUMP DISAS_TARGET_2
39
40#define INSTRUCTION_FLG(func, flags) { (func), (flags) }
41#define INSTRUCTION(func) \
42 INSTRUCTION_FLG(func, 0)
43#define INSTRUCTION_NOP() \
44 INSTRUCTION_FLG(nop, 0)
45#define INSTRUCTION_UNIMPLEMENTED() \
46 INSTRUCTION_FLG(gen_excp, EXCP_UNIMPL)
47#define INSTRUCTION_ILLEGAL() \
48 INSTRUCTION_FLG(gen_excp, EXCP_ILLEGAL)
49
50
51#define INSN_R_TYPE 0x3A
52
53
54#define I_TYPE(instr, code) \
55 struct { \
56 uint8_t op; \
57 union { \
58 uint16_t u; \
59 int16_t s; \
60 } imm16; \
61 uint8_t b; \
62 uint8_t a; \
63 } (instr) = { \
64 .op = extract32((code), 0, 6), \
65 .imm16.u = extract32((code), 6, 16), \
66 .b = extract32((code), 22, 5), \
67 .a = extract32((code), 27, 5), \
68 }
69
70
71#define R_TYPE(instr, code) \
72 struct { \
73 uint8_t op; \
74 uint8_t imm5; \
75 uint8_t opx; \
76 uint8_t c; \
77 uint8_t b; \
78 uint8_t a; \
79 } (instr) = { \
80 .op = extract32((code), 0, 6), \
81 .imm5 = extract32((code), 6, 5), \
82 .opx = extract32((code), 11, 6), \
83 .c = extract32((code), 17, 5), \
84 .b = extract32((code), 22, 5), \
85 .a = extract32((code), 27, 5), \
86 }
87
88
89#define J_TYPE(instr, code) \
90 struct { \
91 uint8_t op; \
92 uint32_t imm26; \
93 } (instr) = { \
94 .op = extract32((code), 0, 6), \
95 .imm26 = extract32((code), 6, 26), \
96 }
97
98typedef struct DisasContext {
99 TCGv_ptr cpu_env;
100 TCGv *cpu_R;
101 TCGv_i32 zero;
102 int is_jmp;
103 target_ulong pc;
104 TranslationBlock *tb;
105 int mem_idx;
106 bool singlestep_enabled;
107} DisasContext;
108
109typedef struct Nios2Instruction {
110 void (*handler)(DisasContext *dc, uint32_t code, uint32_t flags);
111 uint32_t flags;
112} Nios2Instruction;
113
114static uint8_t get_opcode(uint32_t code)
115{
116 I_TYPE(instr, code);
117 return instr.op;
118}
119
120static uint8_t get_opxcode(uint32_t code)
121{
122 R_TYPE(instr, code);
123 return instr.opx;
124}
125
126static TCGv load_zero(DisasContext *dc)
127{
128 if (!dc->zero) {
129 dc->zero = tcg_const_i32(0);
130 }
131 return dc->zero;
132}
133
134static TCGv load_gpr(DisasContext *dc, uint8_t reg)
135{
136 if (likely(reg != R_ZERO)) {
137 return dc->cpu_R[reg];
138 } else {
139 return load_zero(dc);
140 }
141}
142
143static void t_gen_helper_raise_exception(DisasContext *dc,
144 uint32_t index)
145{
146 TCGv_i32 tmp = tcg_const_i32(index);
147
148 tcg_gen_movi_tl(dc->cpu_R[R_PC], dc->pc);
149 gen_helper_raise_exception(dc->cpu_env, tmp);
150 tcg_temp_free_i32(tmp);
151 dc->is_jmp = DISAS_UPDATE;
152}
153
154static bool use_goto_tb(DisasContext *dc, uint32_t dest)
155{
156 if (unlikely(dc->singlestep_enabled)) {
157 return false;
158 }
159
160#ifndef CONFIG_USER_ONLY
161 return (dc->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
162#else
163 return true;
164#endif
165}
166
167static void gen_goto_tb(DisasContext *dc, int n, uint32_t dest)
168{
169 TranslationBlock *tb = dc->tb;
170
171 if (use_goto_tb(dc, dest)) {
172 tcg_gen_goto_tb(n);
173 tcg_gen_movi_tl(dc->cpu_R[R_PC], dest);
174 tcg_gen_exit_tb(tb, n);
175 } else {
176 tcg_gen_movi_tl(dc->cpu_R[R_PC], dest);
177 tcg_gen_exit_tb(NULL, 0);
178 }
179}
180
181static void gen_excp(DisasContext *dc, uint32_t code, uint32_t flags)
182{
183 t_gen_helper_raise_exception(dc, flags);
184}
185
186static void gen_check_supervisor(DisasContext *dc)
187{
188 if (dc->tb->flags & CR_STATUS_U) {
189
190 t_gen_helper_raise_exception(dc, EXCP_SUPERI);
191 }
192}
193
194
195
196
197
198static void nop(DisasContext *dc, uint32_t code, uint32_t flags)
199{
200
201}
202
203
204
205
206static void jmpi(DisasContext *dc, uint32_t code, uint32_t flags)
207{
208 J_TYPE(instr, code);
209 gen_goto_tb(dc, 0, (dc->pc & 0xF0000000) | (instr.imm26 << 2));
210 dc->is_jmp = DISAS_TB_JUMP;
211}
212
213static void call(DisasContext *dc, uint32_t code, uint32_t flags)
214{
215 tcg_gen_movi_tl(dc->cpu_R[R_RA], dc->pc + 4);
216 jmpi(dc, code, flags);
217}
218
219
220
221
222
223static void gen_ldx(DisasContext *dc, uint32_t code, uint32_t flags)
224{
225 I_TYPE(instr, code);
226
227 TCGv addr = tcg_temp_new();
228 TCGv data;
229
230
231
232
233
234
235
236 if (likely(instr.b != R_ZERO)) {
237 data = dc->cpu_R[instr.b];
238 } else {
239 data = tcg_temp_new();
240 }
241
242 tcg_gen_addi_tl(addr, load_gpr(dc, instr.a), instr.imm16.s);
243 tcg_gen_qemu_ld_tl(data, addr, dc->mem_idx, flags);
244
245 if (unlikely(instr.b == R_ZERO)) {
246 tcg_temp_free(data);
247 }
248
249 tcg_temp_free(addr);
250}
251
252
253static void gen_stx(DisasContext *dc, uint32_t code, uint32_t flags)
254{
255 I_TYPE(instr, code);
256 TCGv val = load_gpr(dc, instr.b);
257
258 TCGv addr = tcg_temp_new();
259 tcg_gen_addi_tl(addr, load_gpr(dc, instr.a), instr.imm16.s);
260 tcg_gen_qemu_st_tl(val, addr, dc->mem_idx, flags);
261 tcg_temp_free(addr);
262}
263
264
265static void br(DisasContext *dc, uint32_t code, uint32_t flags)
266{
267 I_TYPE(instr, code);
268
269 gen_goto_tb(dc, 0, dc->pc + 4 + (instr.imm16.s & -4));
270 dc->is_jmp = DISAS_TB_JUMP;
271}
272
273static void gen_bxx(DisasContext *dc, uint32_t code, uint32_t flags)
274{
275 I_TYPE(instr, code);
276
277 TCGLabel *l1 = gen_new_label();
278 tcg_gen_brcond_tl(flags, dc->cpu_R[instr.a], dc->cpu_R[instr.b], l1);
279 gen_goto_tb(dc, 0, dc->pc + 4);
280 gen_set_label(l1);
281 gen_goto_tb(dc, 1, dc->pc + 4 + (instr.imm16.s & -4));
282 dc->is_jmp = DISAS_TB_JUMP;
283}
284
285
286#define gen_i_cmpxx(fname, op3) \
287static void (fname)(DisasContext *dc, uint32_t code, uint32_t flags) \
288{ \
289 I_TYPE(instr, (code)); \
290 tcg_gen_setcondi_tl(flags, (dc)->cpu_R[instr.b], (dc)->cpu_R[instr.a], \
291 (op3)); \
292}
293
294gen_i_cmpxx(gen_cmpxxsi, instr.imm16.s)
295gen_i_cmpxx(gen_cmpxxui, instr.imm16.u)
296
297
298#define gen_i_math_logic(fname, insn, resimm, op3) \
299static void (fname)(DisasContext *dc, uint32_t code, uint32_t flags) \
300{ \
301 I_TYPE(instr, (code)); \
302 if (unlikely(instr.b == R_ZERO)) { \
303 return; \
304 } else if (instr.a == R_ZERO) { \
305 tcg_gen_movi_tl(dc->cpu_R[instr.b], (resimm) ? (op3) : 0); \
306 } else { \
307 tcg_gen_##insn##_tl((dc)->cpu_R[instr.b], (dc)->cpu_R[instr.a], \
308 (op3)); \
309 } \
310}
311
312gen_i_math_logic(addi, addi, 1, instr.imm16.s)
313gen_i_math_logic(muli, muli, 0, instr.imm16.s)
314
315gen_i_math_logic(andi, andi, 0, instr.imm16.u)
316gen_i_math_logic(ori, ori, 1, instr.imm16.u)
317gen_i_math_logic(xori, xori, 1, instr.imm16.u)
318
319gen_i_math_logic(andhi, andi, 0, instr.imm16.u << 16)
320gen_i_math_logic(orhi , ori, 1, instr.imm16.u << 16)
321gen_i_math_logic(xorhi, xori, 1, instr.imm16.u << 16)
322
323
324static void handle_r_type_instr(DisasContext *dc, uint32_t code,
325 uint32_t flags);
326
327static const Nios2Instruction i_type_instructions[] = {
328 INSTRUCTION(call),
329 INSTRUCTION(jmpi),
330 INSTRUCTION_ILLEGAL(),
331 INSTRUCTION_FLG(gen_ldx, MO_UB),
332 INSTRUCTION(addi),
333 INSTRUCTION_FLG(gen_stx, MO_UB),
334 INSTRUCTION(br),
335 INSTRUCTION_FLG(gen_ldx, MO_SB),
336 INSTRUCTION_FLG(gen_cmpxxsi, TCG_COND_GE),
337 INSTRUCTION_ILLEGAL(),
338 INSTRUCTION_ILLEGAL(),
339 INSTRUCTION_FLG(gen_ldx, MO_UW),
340 INSTRUCTION(andi),
341 INSTRUCTION_FLG(gen_stx, MO_UW),
342 INSTRUCTION_FLG(gen_bxx, TCG_COND_GE),
343 INSTRUCTION_FLG(gen_ldx, MO_SW),
344 INSTRUCTION_FLG(gen_cmpxxsi, TCG_COND_LT),
345 INSTRUCTION_ILLEGAL(),
346 INSTRUCTION_ILLEGAL(),
347 INSTRUCTION_NOP(),
348 INSTRUCTION(ori),
349 INSTRUCTION_FLG(gen_stx, MO_UL),
350 INSTRUCTION_FLG(gen_bxx, TCG_COND_LT),
351 INSTRUCTION_FLG(gen_ldx, MO_UL),
352 INSTRUCTION_FLG(gen_cmpxxsi, TCG_COND_NE),
353 INSTRUCTION_ILLEGAL(),
354 INSTRUCTION_ILLEGAL(),
355 INSTRUCTION_NOP(),
356 INSTRUCTION(xori),
357 INSTRUCTION_ILLEGAL(),
358 INSTRUCTION_FLG(gen_bxx, TCG_COND_NE),
359 INSTRUCTION_ILLEGAL(),
360 INSTRUCTION_FLG(gen_cmpxxsi, TCG_COND_EQ),
361 INSTRUCTION_ILLEGAL(),
362 INSTRUCTION_ILLEGAL(),
363 INSTRUCTION_FLG(gen_ldx, MO_UB),
364 INSTRUCTION(muli),
365 INSTRUCTION_FLG(gen_stx, MO_UB),
366 INSTRUCTION_FLG(gen_bxx, TCG_COND_EQ),
367 INSTRUCTION_FLG(gen_ldx, MO_SB),
368 INSTRUCTION_FLG(gen_cmpxxui, TCG_COND_GEU),
369 INSTRUCTION_ILLEGAL(),
370 INSTRUCTION_ILLEGAL(),
371 INSTRUCTION_FLG(gen_ldx, MO_UW),
372 INSTRUCTION(andhi),
373 INSTRUCTION_FLG(gen_stx, MO_UW),
374 INSTRUCTION_FLG(gen_bxx, TCG_COND_GEU),
375 INSTRUCTION_FLG(gen_ldx, MO_SW),
376 INSTRUCTION_FLG(gen_cmpxxui, TCG_COND_LTU),
377 INSTRUCTION_ILLEGAL(),
378 INSTRUCTION_UNIMPLEMENTED(),
379 INSTRUCTION_NOP(),
380 INSTRUCTION(orhi),
381 INSTRUCTION_FLG(gen_stx, MO_SL),
382 INSTRUCTION_FLG(gen_bxx, TCG_COND_LTU),
383 INSTRUCTION_FLG(gen_ldx, MO_UL),
384 INSTRUCTION_UNIMPLEMENTED(),
385 INSTRUCTION_ILLEGAL(),
386 INSTRUCTION_FLG(handle_r_type_instr, 0),
387 INSTRUCTION_NOP(),
388 INSTRUCTION(xorhi),
389 INSTRUCTION_ILLEGAL(),
390 INSTRUCTION_ILLEGAL(),
391 INSTRUCTION_ILLEGAL(),
392};
393
394
395
396
397
398
399
400
401static void eret(DisasContext *dc, uint32_t code, uint32_t flags)
402{
403 tcg_gen_mov_tl(dc->cpu_R[CR_STATUS], dc->cpu_R[CR_ESTATUS]);
404 tcg_gen_mov_tl(dc->cpu_R[R_PC], dc->cpu_R[R_EA]);
405
406 dc->is_jmp = DISAS_JUMP;
407}
408
409
410static void ret(DisasContext *dc, uint32_t code, uint32_t flags)
411{
412 tcg_gen_mov_tl(dc->cpu_R[R_PC], dc->cpu_R[R_RA]);
413
414 dc->is_jmp = DISAS_JUMP;
415}
416
417
418static void bret(DisasContext *dc, uint32_t code, uint32_t flags)
419{
420 tcg_gen_mov_tl(dc->cpu_R[R_PC], dc->cpu_R[R_BA]);
421
422 dc->is_jmp = DISAS_JUMP;
423}
424
425
426static void jmp(DisasContext *dc, uint32_t code, uint32_t flags)
427{
428 R_TYPE(instr, code);
429
430 tcg_gen_mov_tl(dc->cpu_R[R_PC], load_gpr(dc, instr.a));
431
432 dc->is_jmp = DISAS_JUMP;
433}
434
435
436static void nextpc(DisasContext *dc, uint32_t code, uint32_t flags)
437{
438 R_TYPE(instr, code);
439
440 if (likely(instr.c != R_ZERO)) {
441 tcg_gen_movi_tl(dc->cpu_R[instr.c], dc->pc + 4);
442 }
443}
444
445
446
447
448
449static void callr(DisasContext *dc, uint32_t code, uint32_t flags)
450{
451 R_TYPE(instr, code);
452
453 tcg_gen_mov_tl(dc->cpu_R[R_PC], load_gpr(dc, instr.a));
454 tcg_gen_movi_tl(dc->cpu_R[R_RA], dc->pc + 4);
455
456 dc->is_jmp = DISAS_JUMP;
457}
458
459
460static void rdctl(DisasContext *dc, uint32_t code, uint32_t flags)
461{
462 R_TYPE(instr, code);
463
464 gen_check_supervisor(dc);
465
466 switch (instr.imm5 + CR_BASE) {
467 case CR_PTEADDR:
468 case CR_TLBACC:
469 case CR_TLBMISC:
470 {
471#if !defined(CONFIG_USER_ONLY)
472 if (likely(instr.c != R_ZERO)) {
473 tcg_gen_mov_tl(dc->cpu_R[instr.c], dc->cpu_R[instr.imm5 + CR_BASE]);
474#ifdef DEBUG_MMU
475 TCGv_i32 tmp = tcg_const_i32(instr.imm5 + CR_BASE);
476 gen_helper_mmu_read_debug(dc->cpu_R[instr.c], dc->cpu_env, tmp);
477 tcg_temp_free_i32(tmp);
478#endif
479 }
480#endif
481 break;
482 }
483
484 default:
485 if (likely(instr.c != R_ZERO)) {
486 tcg_gen_mov_tl(dc->cpu_R[instr.c], dc->cpu_R[instr.imm5 + CR_BASE]);
487 }
488 break;
489 }
490}
491
492
493static void wrctl(DisasContext *dc, uint32_t code, uint32_t flags)
494{
495 R_TYPE(instr, code);
496
497 gen_check_supervisor(dc);
498
499 switch (instr.imm5 + CR_BASE) {
500 case CR_PTEADDR:
501 case CR_TLBACC:
502 case CR_TLBMISC:
503 {
504#if !defined(CONFIG_USER_ONLY)
505 TCGv_i32 tmp = tcg_const_i32(instr.imm5 + CR_BASE);
506 gen_helper_mmu_write(dc->cpu_env, tmp, load_gpr(dc, instr.a));
507 tcg_temp_free_i32(tmp);
508#endif
509 break;
510 }
511
512 default:
513 tcg_gen_mov_tl(dc->cpu_R[instr.imm5 + CR_BASE], load_gpr(dc, instr.a));
514 break;
515 }
516
517
518#if !defined(CONFIG_USER_ONLY)
519 if ((instr.imm5 + CR_BASE) == CR_STATUS) {
520 gen_helper_check_interrupts(dc->cpu_env);
521 }
522#endif
523}
524
525
526static void gen_cmpxx(DisasContext *dc, uint32_t code, uint32_t flags)
527{
528 R_TYPE(instr, code);
529 if (likely(instr.c != R_ZERO)) {
530 tcg_gen_setcond_tl(flags, dc->cpu_R[instr.c], dc->cpu_R[instr.a],
531 dc->cpu_R[instr.b]);
532 }
533}
534
535
536#define gen_r_math_logic(fname, insn, op3) \
537static void (fname)(DisasContext *dc, uint32_t code, uint32_t flags) \
538{ \
539 R_TYPE(instr, (code)); \
540 if (likely(instr.c != R_ZERO)) { \
541 tcg_gen_##insn((dc)->cpu_R[instr.c], load_gpr((dc), instr.a), \
542 (op3)); \
543 } \
544}
545
546gen_r_math_logic(add, add_tl, load_gpr(dc, instr.b))
547gen_r_math_logic(sub, sub_tl, load_gpr(dc, instr.b))
548gen_r_math_logic(mul, mul_tl, load_gpr(dc, instr.b))
549
550gen_r_math_logic(and, and_tl, load_gpr(dc, instr.b))
551gen_r_math_logic(or, or_tl, load_gpr(dc, instr.b))
552gen_r_math_logic(xor, xor_tl, load_gpr(dc, instr.b))
553gen_r_math_logic(nor, nor_tl, load_gpr(dc, instr.b))
554
555gen_r_math_logic(srai, sari_tl, instr.imm5)
556gen_r_math_logic(srli, shri_tl, instr.imm5)
557gen_r_math_logic(slli, shli_tl, instr.imm5)
558gen_r_math_logic(roli, rotli_tl, instr.imm5)
559
560#define gen_r_mul(fname, insn) \
561static void (fname)(DisasContext *dc, uint32_t code, uint32_t flags) \
562{ \
563 R_TYPE(instr, (code)); \
564 if (likely(instr.c != R_ZERO)) { \
565 TCGv t0 = tcg_temp_new(); \
566 tcg_gen_##insn(t0, dc->cpu_R[instr.c], \
567 load_gpr(dc, instr.a), load_gpr(dc, instr.b)); \
568 tcg_temp_free(t0); \
569 } \
570}
571
572gen_r_mul(mulxss, muls2_tl)
573gen_r_mul(mulxuu, mulu2_tl)
574gen_r_mul(mulxsu, mulsu2_tl)
575
576#define gen_r_shift_s(fname, insn) \
577static void (fname)(DisasContext *dc, uint32_t code, uint32_t flags) \
578{ \
579 R_TYPE(instr, (code)); \
580 if (likely(instr.c != R_ZERO)) { \
581 TCGv t0 = tcg_temp_new(); \
582 tcg_gen_andi_tl(t0, load_gpr((dc), instr.b), 31); \
583 tcg_gen_##insn((dc)->cpu_R[instr.c], load_gpr((dc), instr.a), t0); \
584 tcg_temp_free(t0); \
585 } \
586}
587
588gen_r_shift_s(sra, sar_tl)
589gen_r_shift_s(srl, shr_tl)
590gen_r_shift_s(sll, shl_tl)
591gen_r_shift_s(rol, rotl_tl)
592gen_r_shift_s(ror, rotr_tl)
593
594static void divs(DisasContext *dc, uint32_t code, uint32_t flags)
595{
596 R_TYPE(instr, (code));
597
598
599 if (unlikely(instr.c == R_ZERO)) {
600 return;
601 }
602
603 TCGv t0 = tcg_temp_new();
604 TCGv t1 = tcg_temp_new();
605 TCGv t2 = tcg_temp_new();
606 TCGv t3 = tcg_temp_new();
607
608 tcg_gen_ext32s_tl(t0, load_gpr(dc, instr.a));
609 tcg_gen_ext32s_tl(t1, load_gpr(dc, instr.b));
610 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
611 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
612 tcg_gen_and_tl(t2, t2, t3);
613 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
614 tcg_gen_or_tl(t2, t2, t3);
615 tcg_gen_movi_tl(t3, 0);
616 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
617 tcg_gen_div_tl(dc->cpu_R[instr.c], t0, t1);
618 tcg_gen_ext32s_tl(dc->cpu_R[instr.c], dc->cpu_R[instr.c]);
619
620 tcg_temp_free(t3);
621 tcg_temp_free(t2);
622 tcg_temp_free(t1);
623 tcg_temp_free(t0);
624}
625
626static void divu(DisasContext *dc, uint32_t code, uint32_t flags)
627{
628 R_TYPE(instr, (code));
629
630
631 if (unlikely(instr.c == R_ZERO)) {
632 return;
633 }
634
635 TCGv t0 = tcg_temp_new();
636 TCGv t1 = tcg_temp_new();
637 TCGv t2 = tcg_const_tl(0);
638 TCGv t3 = tcg_const_tl(1);
639
640 tcg_gen_ext32u_tl(t0, load_gpr(dc, instr.a));
641 tcg_gen_ext32u_tl(t1, load_gpr(dc, instr.b));
642 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
643 tcg_gen_divu_tl(dc->cpu_R[instr.c], t0, t1);
644 tcg_gen_ext32s_tl(dc->cpu_R[instr.c], dc->cpu_R[instr.c]);
645
646 tcg_temp_free(t3);
647 tcg_temp_free(t2);
648 tcg_temp_free(t1);
649 tcg_temp_free(t0);
650}
651
652static const Nios2Instruction r_type_instructions[] = {
653 INSTRUCTION_ILLEGAL(),
654 INSTRUCTION(eret),
655 INSTRUCTION(roli),
656 INSTRUCTION(rol),
657 INSTRUCTION_NOP(),
658 INSTRUCTION(ret),
659 INSTRUCTION(nor),
660 INSTRUCTION(mulxuu),
661 INSTRUCTION_FLG(gen_cmpxx, TCG_COND_GE),
662 INSTRUCTION(bret),
663 INSTRUCTION_ILLEGAL(),
664 INSTRUCTION(ror),
665 INSTRUCTION_NOP(),
666 INSTRUCTION(jmp),
667 INSTRUCTION(and),
668 INSTRUCTION_ILLEGAL(),
669 INSTRUCTION_FLG(gen_cmpxx, TCG_COND_LT),
670 INSTRUCTION_ILLEGAL(),
671 INSTRUCTION(slli),
672 INSTRUCTION(sll),
673 INSTRUCTION_UNIMPLEMENTED(),
674 INSTRUCTION_ILLEGAL(),
675 INSTRUCTION(or),
676 INSTRUCTION(mulxsu),
677 INSTRUCTION_FLG(gen_cmpxx, TCG_COND_NE),
678 INSTRUCTION_ILLEGAL(),
679 INSTRUCTION(srli),
680 INSTRUCTION(srl),
681 INSTRUCTION(nextpc),
682 INSTRUCTION(callr),
683 INSTRUCTION(xor),
684 INSTRUCTION(mulxss),
685 INSTRUCTION_FLG(gen_cmpxx, TCG_COND_EQ),
686 INSTRUCTION_ILLEGAL(),
687 INSTRUCTION_ILLEGAL(),
688 INSTRUCTION_ILLEGAL(),
689 INSTRUCTION(divu),
690 INSTRUCTION(divs),
691 INSTRUCTION(rdctl),
692 INSTRUCTION(mul),
693 INSTRUCTION_FLG(gen_cmpxx, TCG_COND_GEU),
694 INSTRUCTION_NOP(),
695 INSTRUCTION_ILLEGAL(),
696 INSTRUCTION_ILLEGAL(),
697 INSTRUCTION_ILLEGAL(),
698 INSTRUCTION_FLG(gen_excp, EXCP_TRAP),
699 INSTRUCTION(wrctl),
700 INSTRUCTION_ILLEGAL(),
701 INSTRUCTION_FLG(gen_cmpxx, TCG_COND_LTU),
702 INSTRUCTION(add),
703 INSTRUCTION_ILLEGAL(),
704 INSTRUCTION_ILLEGAL(),
705 INSTRUCTION_FLG(gen_excp, EXCP_BREAK),
706 INSTRUCTION_ILLEGAL(),
707 INSTRUCTION(nop),
708 INSTRUCTION_ILLEGAL(),
709 INSTRUCTION_ILLEGAL(),
710 INSTRUCTION(sub),
711 INSTRUCTION(srai),
712 INSTRUCTION(sra),
713 INSTRUCTION_ILLEGAL(),
714 INSTRUCTION_ILLEGAL(),
715 INSTRUCTION_ILLEGAL(),
716 INSTRUCTION_ILLEGAL(),
717};
718
719static void handle_r_type_instr(DisasContext *dc, uint32_t code, uint32_t flags)
720{
721 uint8_t opx;
722 const Nios2Instruction *instr;
723
724 opx = get_opxcode(code);
725 if (unlikely(opx >= ARRAY_SIZE(r_type_instructions))) {
726 goto illegal_op;
727 }
728
729 instr = &r_type_instructions[opx];
730 instr->handler(dc, code, instr->flags);
731
732 return;
733
734illegal_op:
735 t_gen_helper_raise_exception(dc, EXCP_ILLEGAL);
736}
737
738static void handle_instruction(DisasContext *dc, CPUNios2State *env)
739{
740 uint32_t code;
741 uint8_t op;
742 const Nios2Instruction *instr;
743#if defined(CONFIG_USER_ONLY)
744
745 if (dc->pc >= 0x1000 && dc->pc < 0x2000) {
746 env->regs[R_PC] = dc->pc;
747 t_gen_helper_raise_exception(dc, 0xaa);
748 return;
749 }
750#endif
751 code = cpu_ldl_code(env, dc->pc);
752 op = get_opcode(code);
753
754 if (unlikely(op >= ARRAY_SIZE(i_type_instructions))) {
755 goto illegal_op;
756 }
757
758 dc->zero = NULL;
759
760 instr = &i_type_instructions[op];
761 instr->handler(dc, code, instr->flags);
762
763 if (dc->zero) {
764 tcg_temp_free(dc->zero);
765 }
766
767 return;
768
769illegal_op:
770 t_gen_helper_raise_exception(dc, EXCP_ILLEGAL);
771}
772
773static const char * const regnames[] = {
774 "zero", "at", "r2", "r3",
775 "r4", "r5", "r6", "r7",
776 "r8", "r9", "r10", "r11",
777 "r12", "r13", "r14", "r15",
778 "r16", "r17", "r18", "r19",
779 "r20", "r21", "r22", "r23",
780 "et", "bt", "gp", "sp",
781 "fp", "ea", "ba", "ra",
782 "status", "estatus", "bstatus", "ienable",
783 "ipending", "cpuid", "reserved0", "exception",
784 "pteaddr", "tlbacc", "tlbmisc", "reserved1",
785 "badaddr", "config", "mpubase", "mpuacc",
786 "reserved2", "reserved3", "reserved4", "reserved5",
787 "reserved6", "reserved7", "reserved8", "reserved9",
788 "reserved10", "reserved11", "reserved12", "reserved13",
789 "reserved14", "reserved15", "reserved16", "reserved17",
790 "rpc"
791};
792
793static TCGv cpu_R[NUM_CORE_REGS];
794
795#include "exec/gen-icount.h"
796
797static void gen_exception(DisasContext *dc, uint32_t excp)
798{
799 TCGv_i32 tmp = tcg_const_i32(excp);
800
801 tcg_gen_movi_tl(cpu_R[R_PC], dc->pc);
802 gen_helper_raise_exception(cpu_env, tmp);
803 tcg_temp_free_i32(tmp);
804 dc->is_jmp = DISAS_UPDATE;
805}
806
807
808void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
809{
810 CPUNios2State *env = cs->env_ptr;
811 DisasContext dc1, *dc = &dc1;
812 int num_insns;
813 int max_insns;
814
815
816 dc->cpu_env = cpu_env;
817 dc->cpu_R = cpu_R;
818 dc->is_jmp = DISAS_NEXT;
819 dc->pc = tb->pc;
820 dc->tb = tb;
821 dc->mem_idx = cpu_mmu_index(env, false);
822 dc->singlestep_enabled = cs->singlestep_enabled;
823
824
825 num_insns = 0;
826 if (cs->singlestep_enabled || singlestep) {
827 max_insns = 1;
828 } else {
829 int page_insns = (TARGET_PAGE_SIZE - (tb->pc & TARGET_PAGE_MASK)) / 4;
830 max_insns = tb_cflags(tb) & CF_COUNT_MASK;
831 if (max_insns == 0) {
832 max_insns = CF_COUNT_MASK;
833 }
834 if (max_insns > page_insns) {
835 max_insns = page_insns;
836 }
837 if (max_insns > TCG_MAX_INSNS) {
838 max_insns = TCG_MAX_INSNS;
839 }
840 }
841
842 gen_tb_start(tb);
843 do {
844 tcg_gen_insn_start(dc->pc);
845 num_insns++;
846
847 if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
848 gen_exception(dc, EXCP_DEBUG);
849
850
851
852
853 dc->pc += 4;
854 break;
855 }
856
857 if (num_insns == max_insns && (tb_cflags(tb) & CF_LAST_IO)) {
858 gen_io_start();
859 }
860
861
862 handle_instruction(dc, env);
863
864 dc->pc += 4;
865
866
867
868
869
870 } while (!dc->is_jmp &&
871 !tcg_op_buf_full() &&
872 num_insns < max_insns);
873
874 if (tb_cflags(tb) & CF_LAST_IO) {
875 gen_io_end();
876 }
877
878
879 switch (dc->is_jmp) {
880 case DISAS_NEXT:
881
882 tcg_gen_movi_tl(cpu_R[R_PC], dc->pc);
883 tcg_gen_exit_tb(NULL, 0);
884 break;
885
886 default:
887 case DISAS_JUMP:
888 case DISAS_UPDATE:
889
890 tcg_gen_exit_tb(NULL, 0);
891 break;
892
893 case DISAS_TB_JUMP:
894
895 break;
896 }
897
898
899 gen_tb_end(tb, num_insns);
900
901
902 tb->size = dc->pc - tb->pc;
903 tb->icount = num_insns;
904
905#ifdef DEBUG_DISAS
906 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
907 && qemu_log_in_addr_range(tb->pc)) {
908 qemu_log_lock();
909 qemu_log("IN: %s\n", lookup_symbol(tb->pc));
910 log_target_disas(cs, tb->pc, dc->pc - tb->pc);
911 qemu_log("\n");
912 qemu_log_unlock();
913 }
914#endif
915}
916
917void nios2_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
918 int flags)
919{
920 Nios2CPU *cpu = NIOS2_CPU(cs);
921 CPUNios2State *env = &cpu->env;
922 int i;
923
924 if (!env || !f) {
925 return;
926 }
927
928 cpu_fprintf(f, "IN: PC=%x %s\n",
929 env->regs[R_PC], lookup_symbol(env->regs[R_PC]));
930
931 for (i = 0; i < NUM_CORE_REGS; i++) {
932 cpu_fprintf(f, "%9s=%8.8x ", regnames[i], env->regs[i]);
933 if ((i + 1) % 4 == 0) {
934 cpu_fprintf(f, "\n");
935 }
936 }
937#if !defined(CONFIG_USER_ONLY)
938 cpu_fprintf(f, " mmu write: VPN=%05X PID %02X TLBACC %08X\n",
939 env->mmu.pteaddr_wr & CR_PTEADDR_VPN_MASK,
940 (env->mmu.tlbmisc_wr & CR_TLBMISC_PID_MASK) >> 4,
941 env->mmu.tlbacc_wr);
942#endif
943 cpu_fprintf(f, "\n\n");
944}
945
946void nios2_tcg_init(void)
947{
948 int i;
949
950 for (i = 0; i < NUM_CORE_REGS; i++) {
951 cpu_R[i] = tcg_global_mem_new(cpu_env,
952 offsetof(CPUNios2State, regs[i]),
953 regnames[i]);
954 }
955}
956
957void restore_state_to_opc(CPUNios2State *env, TranslationBlock *tb,
958 target_ulong *data)
959{
960 env->regs[R_PC] = data[0];
961}
962