[xcc,sim,opcodes] more rvc instructions and bug fixes
[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 #include "platform.h" // softfloat isNaNF32UI, etc.
12 #include "internals.h" // ditto
13
14 processor_t::processor_t(sim_t* _sim, char* _mem, size_t _memsz)
15 : sim(_sim), mmu(_mem,_memsz)
16 {
17 memset(XPR,0,sizeof(XPR));
18 memset(FPR,0,sizeof(FPR));
19 pc = 0;
20 evec = 0;
21 epc = 0;
22 badvaddr = 0;
23 cause = 0;
24 pcr_k0 = 0;
25 pcr_k1 = 0;
26 tohost = 0;
27 fromhost = 0;
28 count = 0;
29 compare = 0;
30 set_sr(SR_S | SR_SX); // SX ignored if 64b mode not supported
31 set_fsr(0);
32
33 memset(counters,0,sizeof(counters));
34
35 // vector stuff
36 utidx = -1;
37 vlmax = 8;
38 vl = 0;
39 nxpr_all = 256;
40 nfpr_all = 256;
41 nxpr_use = 0;
42 nfpr_use = 0;
43 for (int i=0; i<MAX_UTS; i++)
44 uts[i] = NULL;
45
46 // a few assumptions about endianness, including freg_t union
47 static_assert(BYTE_ORDER == LITTLE_ENDIAN);
48 static_assert(sizeof(freg_t) == 8);
49 static_assert(sizeof(reg_t) == 8);
50
51 static_assert(sizeof(insn_t) == 4);
52 static_assert(sizeof(uint128_t) == 16 && sizeof(int128_t) == 16);
53 }
54
55 void processor_t::init(uint32_t _id, char* _mem, size_t _memsz)
56 {
57 id = _id;
58
59 for (int i=0; i<MAX_UTS; i++)
60 {
61 uts[i] = new processor_t(sim, _mem, _memsz);
62 uts[i]->set_sr(uts[i]->sr | SR_EF);
63 uts[i]->set_sr(uts[i]->sr | SR_EV);
64 uts[i]->utidx = i;
65 }
66 }
67
68 void processor_t::set_sr(uint32_t val)
69 {
70 sr = val & ~SR_ZERO;
71 #ifndef RISCV_ENABLE_64BIT
72 sr &= ~(SR_SX | SR_UX);
73 #endif
74 #ifndef RISCV_ENABLE_FPU
75 sr &= ~SR_EF;
76 #endif
77 #ifndef RISCV_ENABLE_RVC
78 sr &= ~SR_EC;
79 #endif
80 #ifndef RISCV_ENABLE_VEC
81 sr &= ~SR_EV;
82 #endif
83
84 xprlen = ((sr & SR_S) ? (sr & SR_SX) : (sr & SR_UX)) ? 64 : 32;
85 }
86
87 void processor_t::set_fsr(uint32_t val)
88 {
89 fsr = val & ~FSR_ZERO;
90 }
91
92 void processor_t::vcfg()
93 {
94 if (nxpr_use == 0 && nfpr_use == 0)
95 vlmax = 8;
96 else if (nfpr_use == 0)
97 vlmax = (nxpr_all-1) / (nxpr_use-1);
98 else if (nxpr_use == 0)
99 vlmax = (nfpr_all-1) / (nfpr_use-1);
100 else
101 vlmax = std::min((nxpr_all-1) / (nxpr_use-1), (nfpr_all-1) / (nfpr_use-1));
102
103 vlmax = std::min(vlmax, MAX_UTS);
104 }
105
106 void processor_t::setvl(int vlapp)
107 {
108 vl = std::min(vlmax, vlapp);
109 }
110
111 void processor_t::step(size_t n, bool noisy)
112 {
113 size_t i = 0;
114 while(1) try
115 {
116 for( ; i < n; i++)
117 {
118 uint32_t interrupts = (cause & CAUSE_IP) >> CAUSE_IP_SHIFT;
119 interrupts &= (sr & SR_IM) >> SR_IM_SHIFT;
120 if(interrupts && (sr & SR_ET))
121 take_trap(trap_interrupt,noisy);
122
123 insn_t insn = mmu.load_insn(pc, sr & SR_EC);
124
125 reg_t npc = pc + insn_length(insn);
126
127 if(noisy)
128 disasm(insn,pc);
129
130 #include "execute.h"
131
132 pc = npc;
133 XPR[0] = 0;
134
135 if(count++ == compare)
136 cause |= 1 << (TIMER_IRQ+CAUSE_IP_SHIFT);
137 }
138 return;
139 }
140 catch(trap_t t)
141 {
142 i++;
143 take_trap(t,noisy);
144 }
145 catch(vt_command_t cmd)
146 {
147 if (cmd == vt_command_stop)
148 return;
149 }
150 }
151
152 void processor_t::take_trap(trap_t t, bool noisy)
153 {
154 demand(t < NUM_TRAPS, "internal error: bad trap number %d", int(t));
155 demand(sr & SR_ET, "error mode on core %d!\ntrap %s, pc 0x%016llx",
156 id, trap_name(t), (unsigned long long)pc);
157 if(noisy)
158 printf("core %3d: trap %s, pc 0x%016llx\n",
159 id, trap_name(t), (unsigned long long)pc);
160
161 set_sr((((sr & ~SR_ET) | SR_S) & ~SR_PS) | ((sr & SR_S) ? SR_PS : 0));
162 cause = (cause & ~CAUSE_EXCCODE) | (t << CAUSE_EXCCODE_SHIFT);
163 epc = pc;
164 pc = evec;
165 badvaddr = mmu.get_badvaddr();
166 }
167
168 void processor_t::disasm(insn_t insn, reg_t pc)
169 {
170 printf("core %3d: 0x%016llx (0x%08x) ",id,(unsigned long long)pc,insn.bits);
171
172 #ifdef RISCV_HAVE_LIBOPCODES
173 disassemble_info info;
174 INIT_DISASSEMBLE_INFO(info, stdout, fprintf);
175 info.flavour = bfd_target_unknown_flavour;
176 info.arch = bfd_arch_mips;
177 info.mach = 101; // XXX bfd_mach_mips_riscv requires modified bfd.h
178 info.endian = BFD_ENDIAN_LITTLE;
179 info.buffer = (bfd_byte*)&insn;
180 info.buffer_length = sizeof(insn);
181 info.buffer_vma = pc;
182
183 int ret = print_insn_little_mips(pc, &info);
184 demand(ret == (INSN_IS_RVC(insn.bits) ? 2 : 4), "disasm bug!");
185 #else
186 printf("unknown");
187 #endif
188 printf("\n");
189 }