@@ -4,7 +4,7 @@ use crate::memory;
4
4
use crate :: opcode:: * ;
5
5
use crate :: registers;
6
6
7
- #[ derive( Debug ) ]
7
+ #[ derive( Debug , Clone , Copy ) ]
8
8
pub struct CPU {
9
9
// integer registers
10
10
pub xregs : registers:: XREGS ,
@@ -54,7 +54,6 @@ impl CPU {
54
54
LB => exec_lb ( self , instr) ,
55
55
LH => exec_lh ( self , instr) ,
56
56
LW => exec_lw ( self , instr) ,
57
- LD => exec_ld ( self , instr) ,
58
57
LBU => exec_lbu ( self , instr) ,
59
58
LHU => exec_lhu ( self , instr) ,
60
59
LWU => exec_lwu ( self , instr) ,
@@ -64,7 +63,6 @@ impl CPU {
64
63
SB => exec_sb ( self , instr) ,
65
64
SH => exec_sh ( self , instr) ,
66
65
SW => exec_sw ( self , instr) ,
67
- SD => exec_sd ( self , instr) ,
68
66
_ => panic ! ( ) ,
69
67
} ,
70
68
I_TYPE => match funct3 {
@@ -115,7 +113,7 @@ impl CPU {
115
113
// see page 64 at https://riscv.org/wp-content/uploads/2016/06/riscv-spec-v2.1.pdf
116
114
pub fn exec_lui ( cpu : & mut CPU , instr : u32 ) {
117
115
let imm = ( imm_u ( instr) as i32 ) as u32 ;
118
- cpu. xregs . regs [ rd ( instr) as usize ] = imm;
116
+ cpu. xregs . regs [ rd ( instr) as usize ] = imm | ( cpu . xregs . regs [ rd ( instr ) as usize ] & 0xfff ) ;
119
117
}
120
118
pub fn exec_auipc ( cpu : & mut CPU , instr : u32 ) {
121
119
let imm = imm_u ( instr) as i32 ;
@@ -132,23 +130,87 @@ pub fn exec_jalr(cpu: &mut CPU, instr: u32) {
132
130
// ignore the last 1 bit with 0xfffffffe
133
131
cpu. pc = ( cpu. xregs . regs [ rs1 ( instr) as usize ] as i32 ) . wrapping_add ( imm) as u32 & 0xfffffffe ;
134
132
}
135
- pub fn exec_beq ( cpu : & mut CPU , instr : u32 ) { }
136
- pub fn exec_bne ( cpu : & mut CPU , instr : u32 ) { }
137
- pub fn exec_blt ( cpu : & mut CPU , instr : u32 ) { }
138
- pub fn exec_bge ( cpu : & mut CPU , instr : u32 ) { }
139
- pub fn exec_bltu ( cpu : & mut CPU , instr : u32 ) { }
140
- pub fn exec_bgeu ( cpu : & mut CPU , instr : u32 ) { }
141
- pub fn exec_lb ( cpu : & mut CPU , instr : u32 ) { }
142
- pub fn exec_lh ( cpu : & mut CPU , instr : u32 ) { }
143
- pub fn exec_lw ( cpu : & mut CPU , instr : u32 ) { }
144
- pub fn exec_ld ( cpu : & mut CPU , instr : u32 ) { }
145
- pub fn exec_lbu ( cpu : & mut CPU , instr : u32 ) { }
146
- pub fn exec_lhu ( cpu : & mut CPU , instr : u32 ) { }
147
- pub fn exec_lwu ( cpu : & mut CPU , instr : u32 ) { }
133
+ pub fn exec_beq ( cpu : & mut CPU , instr : u32 ) {
134
+ let imm = imm_b ( instr) as i32 ;
135
+ if cpu. xregs . regs [ rs1 ( instr) as usize ] == cpu. xregs . regs [ rs2 ( instr) as usize ] {
136
+ cpu. pc = cpu. pc . wrapping_add ( imm as u32 ) . wrapping_sub ( 4 ) ;
137
+ }
138
+ }
139
+ pub fn exec_bne ( cpu : & mut CPU , instr : u32 ) {
140
+ let imm = imm_b ( instr) as i32 ;
141
+ if cpu. xregs . regs [ rs1 ( instr) as usize ] != cpu. xregs . regs [ rs2 ( instr) as usize ] {
142
+ cpu. pc = cpu. pc . wrapping_add ( imm as u32 ) . wrapping_sub ( 4 ) ;
143
+ }
144
+ }
145
+ pub fn exec_blt ( cpu : & mut CPU , instr : u32 ) {
146
+ let imm = imm_b ( instr) as i32 ;
147
+ if ( cpu. xregs . regs [ rs1 ( instr) as usize ] as i32 ) < ( cpu. xregs . regs [ rs2 ( instr) as usize ] as i32 ) {
148
+ cpu. pc = cpu. pc . wrapping_add ( imm as u32 ) . wrapping_sub ( 4 ) ;
149
+ }
150
+ }
151
+ pub fn exec_bge ( cpu : & mut CPU , instr : u32 ) {
152
+ let imm = imm_b ( instr) as i32 ;
153
+ if ( cpu. xregs . regs [ rs1 ( instr) as usize ] as i32 ) >= ( cpu. xregs . regs [ rs2 ( instr) as usize ] as i32 )
154
+ {
155
+ cpu. pc = cpu. pc . wrapping_add ( imm as u32 ) . wrapping_sub ( 4 ) ;
156
+ }
157
+ }
158
+ pub fn exec_bltu ( cpu : & mut CPU , instr : u32 ) {
159
+ let imm = imm_b ( instr) as i32 ;
160
+ if cpu. xregs . regs [ rs1 ( instr) as usize ] < cpu. xregs . regs [ rs2 ( instr) as usize ] {
161
+ cpu. pc = cpu. pc . wrapping_add ( imm as u32 ) . wrapping_sub ( 4 ) ;
162
+ }
163
+ }
164
+ pub fn exec_bgeu ( cpu : & mut CPU , instr : u32 ) {
165
+ let imm = imm_b ( instr) as i32 ;
166
+ if cpu. xregs . regs [ rs1 ( instr) as usize ] >= rs2 ( instr) {
167
+ cpu. pc = cpu. pc . wrapping_add ( imm as u32 ) . wrapping_sub ( 4 ) ;
168
+ }
169
+ }
170
+ pub fn exec_lb ( cpu : & mut CPU , instr : u32 ) {
171
+ let imm = imm_i ( instr) as i32 ;
172
+ let load_i8 = cpu. bus . load (
173
+ ( cpu. xregs . regs [ rs1 ( instr) as usize ] as i32 ) . wrapping_add ( imm) as u32 ,
174
+ 8 ,
175
+ ) as i32 ;
176
+ cpu. xregs . regs [ rd ( instr) as usize ] = ( ( load_i8 << 26 ) >> 26 ) as u32 ;
177
+ }
178
+ pub fn exec_lh ( cpu : & mut CPU , instr : u32 ) {
179
+ let imm = imm_i ( instr) as i32 ;
180
+ let load_i16 = cpu. bus . load (
181
+ ( cpu. xregs . regs [ rs1 ( instr) as usize ] as i32 ) . wrapping_add ( imm) as u32 ,
182
+ 16 ,
183
+ ) as i32 ;
184
+ cpu. xregs . regs [ rd ( instr) as usize ] = ( ( load_i16 << 16 ) >> 16 ) as u32 ;
185
+ }
186
+ pub fn exec_lw ( cpu : & mut CPU , instr : u32 ) {
187
+ let imm = imm_i ( instr) as i32 ;
188
+ cpu. xregs . regs [ rd ( instr) as usize ] = cpu. bus . load (
189
+ ( cpu. xregs . regs [ rs1 ( instr) as usize ] as i32 ) . wrapping_add ( imm) as u32 ,
190
+ 32 ,
191
+ ) ;
192
+ }
193
+ pub fn exec_lbu ( cpu : & mut CPU , instr : u32 ) {
194
+ let imm = imm_i ( instr) as u32 ;
195
+ cpu. xregs . regs [ rd ( instr) as usize ] = cpu
196
+ . bus
197
+ . load ( cpu. xregs . regs [ rs1 ( instr) as usize ] . wrapping_add ( imm) , 8 ) ;
198
+ }
199
+ pub fn exec_lhu ( cpu : & mut CPU , instr : u32 ) {
200
+ let imm = imm_i ( instr) as u32 ;
201
+ cpu. xregs . regs [ rd ( instr) as usize ] = cpu
202
+ . bus
203
+ . load ( cpu. xregs . regs [ rs1 ( instr) as usize ] . wrapping_add ( imm) , 16 ) ;
204
+ }
205
+ pub fn exec_lwu ( cpu : & mut CPU , instr : u32 ) {
206
+ let imm = imm_i ( instr) as u32 ;
207
+ cpu. xregs . regs [ rd ( instr) as usize ] = cpu
208
+ . bus
209
+ . load ( cpu. xregs . regs [ rs1 ( instr) as usize ] . wrapping_add ( imm) , 32 ) ;
210
+ }
148
211
pub fn exec_sb ( cpu : & mut CPU , instr : u32 ) { }
149
212
pub fn exec_sh ( cpu : & mut CPU , instr : u32 ) { }
150
213
pub fn exec_sw ( cpu : & mut CPU , instr : u32 ) { }
151
- pub fn exec_sd ( cpu : & mut CPU , instr : u32 ) { }
152
214
pub fn exec_addi ( cpu : & mut CPU , instr : u32 ) {
153
215
let imm = imm_i ( instr) ;
154
216
cpu. xregs . regs [ rd ( instr) as usize ] = cpu. xregs . regs [ rs1 ( instr) as usize ] + imm as u32 ;
@@ -176,15 +238,18 @@ pub fn exec_andi(cpu: &mut CPU, instr: u32) {
176
238
}
177
239
pub fn exec_slli ( cpu : & mut CPU , instr : u32 ) {
178
240
let imm = imm_i ( instr) ;
179
- cpu. xregs . regs [ rd ( instr) as usize ] = cpu. xregs . regs [ rs1 ( instr) as usize ] << imm as u32 ;
241
+ // shift-by-immediate takes only the lower 5 bits
242
+ cpu. xregs . regs [ rd ( instr) as usize ] = cpu. xregs . regs [ rs1 ( instr) as usize ] << ( imm & 0x1f ) as u32 ;
180
243
}
181
244
pub fn exec_srli ( cpu : & mut CPU , instr : u32 ) {
182
245
let imm = imm_i ( instr) ;
183
- cpu. xregs . regs [ rd ( instr) as usize ] = cpu. xregs . regs [ rs1 ( instr) as usize ] >> imm as u32 ;
246
+ // shift-by-immediate takes only the lower 5 bits
247
+ cpu. xregs . regs [ rd ( instr) as usize ] = cpu. xregs . regs [ rs1 ( instr) as usize ] >> ( imm & 0x1f ) as u32 ;
184
248
}
185
249
pub fn exec_srai ( cpu : & mut CPU , instr : u32 ) {
186
250
let imm = imm_i ( instr) ;
187
- cpu. xregs . regs [ rd ( instr) as usize ] = ( cpu. xregs . regs [ rs1 ( instr) as usize ] as i32 >> imm) as u32 ;
251
+ cpu. xregs . regs [ rd ( instr) as usize ] =
252
+ ( cpu. xregs . regs [ rs1 ( instr) as usize ] as i32 >> ( imm & 0x1f ) ) as u32 ;
188
253
}
189
254
pub fn exec_add ( cpu : & mut CPU , instr : u32 ) {
190
255
cpu. xregs . regs [ rd ( instr) as usize ] = ( cpu. xregs . regs [ rs1 ( instr) as usize ] as i32
0 commit comments