f5b6de1b6123b6c5f19c4afc2c7db4a01d53b832
[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(XPR,0,sizeof(XPR));
16 memset(FPR,0,sizeof(FPR));
17 pc = 0;
18 evec = 0;
19 epc = 0;
20 badvaddr = 0;
21 cause = 0;
22 pcr_k0 = 0;
23 pcr_k1 = 0;
24 tohost = 0;
25 fromhost = 0;
26 count = 0;
27 compare = 0;
28 set_sr(SR_S | SR_SX); // SX ignored if 64b mode not supported
29 set_fsr(0);
30
31 memset(counters,0,sizeof(counters));
32
33 // a few assumptions about endianness, including freg_t union
34 static_assert(BYTE_ORDER == LITTLE_ENDIAN);
35 static_assert(sizeof(freg_t) == 8);
36 static_assert(sizeof(reg_t) == 8);
37
38 static_assert(sizeof(insn_t) == 4);
39 static_assert(sizeof(uint128_t) == 16 && sizeof(int128_t) == 16);
40 }
41
42 void processor_t::init(uint32_t _id)
43 {
44 id = _id;
45 }
46
47 void processor_t::set_sr(uint32_t val)
48 {
49 sr = val & ~SR_ZERO;
50 #ifndef RISCV_ENABLE_64BIT
51 sr &= ~(SR_SX | SR_UX);
52 #endif
53 #ifndef RISCV_ENABLE_64BIT
54 sr &= ~SR_EF;
55 #endif
56
57 xprlen = ((sr & SR_S) ? (sr & SR_SX) : (sr & SR_UX)) ? 64 : 32;
58 }
59
60 void processor_t::set_fsr(uint32_t val)
61 {
62 fsr = val & ~FSR_ZERO;
63 }
64
65 void processor_t::step(size_t n, bool noisy)
66 {
67 size_t i = 0;
68 while(1) try
69 {
70 for( ; i < n; i++)
71 {
72 uint32_t interrupts = (cause & CAUSE_IP) >> CAUSE_IP_SHIFT;
73 interrupts &= (sr & SR_IM) >> SR_IM_SHIFT;
74 if(interrupts && (sr & SR_ET))
75 take_trap(trap_interrupt,noisy);
76
77 insn_t insn = mmu.load_insn(pc);
78
79 reg_t npc = pc+sizeof(insn);
80
81 if(noisy)
82 disasm(insn,pc);
83
84 #include "execute.h"
85
86 pc = npc;
87 XPR[0] = 0;
88
89 if(count++ == compare)
90 cause |= 1 << (TIMER_IRQ+CAUSE_IP_SHIFT);
91 }
92 return;
93 }
94 catch(trap_t t)
95 {
96 i++;
97 take_trap(t,noisy);
98 }
99 }
100
101 void processor_t::take_trap(trap_t t, bool noisy)
102 {
103 demand(t < NUM_TRAPS, "internal error: bad trap number %d", int(t));
104 demand(sr & SR_ET, "error mode on core %d!\ntrap %s, pc 0x%016llx",
105 id, trap_name(t), (unsigned long long)pc);
106 if(noisy)
107 printf("core %3d: trap %s, pc 0x%016llx\n",
108 id, trap_name(t), (unsigned long long)pc);
109
110 set_sr((((sr & ~SR_ET) | SR_S) & ~SR_PS) | ((sr & SR_S) ? SR_PS : 0));
111 cause = (cause & ~CAUSE_EXCCODE) | (t << CAUSE_EXCCODE_SHIFT);
112 epc = pc;
113 pc = evec;
114 badvaddr = mmu.get_badvaddr();
115 }
116
117 void processor_t::disasm(insn_t insn, reg_t pc)
118 {
119 printf("core %3d: 0x%016llx (0x%08x) ",id,(unsigned long long)pc,insn.bits);
120
121 #ifdef RISCV_HAVE_LIBOPCODES
122 disassemble_info info;
123 INIT_DISASSEMBLE_INFO(info, stdout, fprintf);
124 info.flavour = bfd_target_unknown_flavour;
125 info.arch = bfd_arch_mips;
126 info.mach = 101; // XXX bfd_mach_mips_riscv requires modified bfd.h
127 info.endian = BFD_ENDIAN_LITTLE;
128 info.buffer = (bfd_byte*)&insn;
129 info.buffer_length = sizeof(insn);
130 info.buffer_vma = pc;
131
132 demand(print_insn_little_mips(pc, &info) == sizeof(insn), "disasm bug!");
133 #else
134 printf("unknown");
135 #endif
136 printf("\n");
137 }