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