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