[pk, sim] added interrupt support to sim; added timer interrupt
[riscv-isa-sim.git] / riscv / processor.cc
1 #include "processor.h"
2 #include <bfd.h>
3 #include <dis-asm.h>
4 #include <cmath>
5 #include <cstdlib>
6 #include <iostream>
7 #include "common.h"
8 #include "config.h"
9 #include "sim.h"
10 #include "softfloat.h"
11
12 processor_t::processor_t(sim_t* _sim, char* _mem, size_t _memsz)
13 : sim(_sim), mmu(_mem,_memsz)
14 {
15 memset(R,0,sizeof(R));
16 memset(FR,0,sizeof(FR));
17 pc = 0;
18 ebase = 0;
19 epc = 0;
20 badvaddr = 0;
21 tid = 0;
22 pcr_k0 = 0;
23 pcr_k1 = 0;
24 count = 0;
25 compare = 0;
26 interrupts_pending = 0;
27 set_sr(SR_S | (support_64bit ? SR_SX : 0));
28 set_fsr(0);
29
30 memset(counters,0,sizeof(counters));
31
32 // a few assumptions about endianness, including freg_t union
33 static_assert(BYTE_ORDER == LITTLE_ENDIAN);
34 static_assert(sizeof(freg_t) == 8);
35 static_assert(sizeof(reg_t) == 8);
36
37 static_assert(sizeof(insn_t) == 4);
38 static_assert(sizeof(uint128_t) == 16 && sizeof(int128_t) == 16);
39 }
40
41 void processor_t::init(uint32_t _id)
42 {
43 id = _id;
44 }
45
46 void processor_t::set_sr(uint32_t val)
47 {
48 sr = val & ~SR_ZERO;
49 if(!support_64bit)
50 sr &= ~(SR_SX | SR_UX);
51
52 gprlen = ((sr & SR_S) ? (sr & SR_SX) : (sr & SR_UX)) ? 64 : 32;
53 }
54
55 void processor_t::set_fsr(uint32_t val)
56 {
57 fsr = val & ~FSR_ZERO;
58 softfloat_roundingMode = (fsr & FSR_RD) >> FSR_RD_SHIFT;
59 }
60
61 void processor_t::step(size_t n, bool noisy)
62 {
63 size_t i = 0;
64 while(1) try
65 {
66 for( ; i < n; i++)
67 {
68 uint32_t interrupts = interrupts_pending & ((sr & SR_IM) >> SR_IM_SHIFT);
69 if((sr & SR_ET) && interrupts)
70 {
71 for(int i = 0; interrupts; i++, interrupts >>= 1)
72 if(interrupts & 1)
73 throw trap_t(16+i);
74 }
75
76 insn_t insn = mmu.load_insn(pc);
77
78 reg_t npc = pc+sizeof(insn);
79
80 if(noisy)
81 disasm(insn,pc);
82
83 #include "execute.h"
84
85 pc = npc;
86 R[0] = 0;
87
88 if(count++ == compare)
89 interrupts_pending |= 1 << TIMER_IRQ;
90 }
91 return;
92 }
93 catch(trap_t t)
94 {
95 i++;
96 take_trap(t,noisy);
97 }
98 }
99
100 void processor_t::take_trap(trap_t t, bool noisy)
101 {
102 demand(t < NUM_TRAPS, "internal error: bad trap number %d", int(t));
103 demand(sr & SR_ET, "error mode on core %d!\ntrap %s, pc 0x%016llx",
104 id, trap_name(t), (unsigned long long)pc);
105 if(noisy)
106 printf("core %3d: trap %s, pc 0x%016llx\n",
107 id, trap_name(t), (unsigned long long)pc);
108
109 set_sr((((sr & ~SR_ET) | SR_S) & ~SR_PS) | ((sr & SR_S) ? SR_PS : 0));
110 epc = pc;
111 pc = ebase + t*128;
112 badvaddr = mmu.get_badvaddr();
113 }
114
115 void processor_t::disasm(insn_t insn, reg_t pc)
116 {
117 printf("core %3d: 0x%016llx (0x%08x) ",id,(unsigned long long)pc,insn.bits);
118
119 #ifdef RISCV_HAVE_LIBOPCODES
120 disassemble_info info;
121 INIT_DISASSEMBLE_INFO(info, stdout, fprintf);
122 info.flavour = bfd_target_unknown_flavour;
123 info.arch = bfd_arch_mips;
124 info.mach = 101; // XXX bfd_mach_mips_riscv requires modified bfd.h
125 info.endian = BFD_ENDIAN_LITTLE;
126 info.buffer = (bfd_byte*)&insn;
127 info.buffer_length = sizeof(insn);
128 info.buffer_vma = pc;
129
130 demand(print_insn_little_mips(pc, &info) == sizeof(insn), "disasm bug!");
131 #else
132 printf("unknown");
133 #endif
134 printf("\n");
135 }