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