1use std::ptr::null_mut;
2
3use instruction::Instruction;
4use rv64ua::*;
5use rv64ud::*;
6use rv64uf::*;
7use rv64ui::*;
8use rv64um::*;
9use std::fmt::{Debug, Formatter};
10use std::fmt;
11
12pub mod instruction;
13mod rv64ui;
14mod rv64um;
15mod rv64ua;
16mod rv64uf;
17mod rv64ud;
18
19const CSR_CAPACITY: usize = 4096;
20const _CSR_USTATUS_ADDRESS: u16 = 0x000;
21const CSR_FFLAGS_ADDRESS: u16 = 0x001;
22const CSR_FRM_ADDRESS: u16 = 0x002;
23const CSR_FCSR_ADDRESS: u16 = 0x003;
24const _CSR_UIE_ADDRESS: u16 = 0x004;
25const _CSR_UTVEC_ADDRESS: u16 = 0x005;
26const _CSR_USCRATCH_ADDRESS: u16 = 0x040;
27const _CSR_UEPC_ADDRESS: u16 = 0x041;
28const _CSR_UCAUSE_ADDRESS: u16 = 0x042;
29const _CSR_UTVAL_ADDRESS: u16 = 0x043;
30const _CSR_UIP_ADDRESS: u16 = 0x044;
31const CSR_SSTATUS_ADDRESS: u16 = 0x100;
32const _CSR_SEDELEG_ADDRESS: u16 = 0x102;
33const _SR_SIDELEG_ADDRESS: u16 = 0x103;
34const CSR_SIE_ADDRESS: u16 = 0x104;
35const _CSR_STVEC_ADDRESS: u16 = 0x105;
36const _CSR_SSCRATCH_ADDRESS: u16 = 0x140;
37const _CSR_SEPC_ADDRESS: u16 = 0x141;
38const _CSR_SCAUSE_ADDRESS: u16 = 0x142;
39const _CSR_STVAL_ADDRESS: u16 = 0x143;
40const CSR_SIP_ADDRESS: u16 = 0x144;
41const _CSR_SATP_ADDRESS: u16 = 0x180;
42const CSR_MSTATUS_ADDRESS: u16 = 0x300;
43const _CSR_MISA_ADDRESS: u16 = 0x301;
44const _CSR_MEDELEG_ADDRESS: u16 = 0x302;
45const CSR_MIDELEG_ADDRESS: u16 = 0x303;
46const CSR_MIE_ADDRESS: u16 = 0x304;
47
48const _CSR_MTVEC_ADDRESS: u16 = 0x305;
49const _CSR_MSCRATCH_ADDRESS: u16 = 0x340;
50const CSR_MEPC_ADDRESS: u16 = 0x341;
51const _CSR_MCAUSE_ADDRESS: u16 = 0x342;
52const _CSR_MTVAL_ADDRESS: u16 = 0x343;
53const CSR_MIP_ADDRESS: u16 = 0x344;
54const _CSR_PMPCFG0_ADDRESS: u16 = 0x3a0;
55const _CSR_PMPADDR0_ADDRESS: u16 = 0x3b0;
56const _CSR_MCYCLE_ADDRESS: u16 = 0xb00;
57const _CSR_CYCLE_ADDRESS: u16 = 0xc00;
58const CSR_TIME_ADDRESS: u16 = 0xc01;
59const _CSR_INSERT_ADDRESS: u16 = 0xc02;
60const _CSR_MHARTID_ADDRESS: u16 = 0xf14;
61
62#[derive(Clone, Debug)]
63pub enum Xlen {
64 Bit32,
65 Bit64
66}
67
68#[derive(Debug)]
69pub struct Trap {
70 pub trap_type: TrapType,
71 pub value: u64 }
73
74#[allow(dead_code)]
75#[derive(Debug)]
76pub enum TrapType {
77 InstructionAddressMisaligned,
78 InstructionAccessFault,
79 IllegalInstruction,
80 Breakpoint,
81 LoadAddressMisaligned,
82 LoadAccessFault,
83 StoreAddressMisaligned,
84 StoreAccessFault,
85 EnvironmentCallFromUMode,
86 EnvironmentCallFromSMode,
87 EnvironmentCallFromMMode,
88 InstructionPageFault,
89 LoadPageFault,
90 StorePageFault,
91 UserSoftwareInterrupt,
92 SupervisorSoftwareInterrupt,
93 MachineSoftwareInterrupt,
94 UserTimerInterrupt,
95 SupervisorTimerInterrupt,
96 MachineTimerInterrupt,
97 UserExternalInterrupt,
98 SupervisorExternalInterrupt,
99 MachineExternalInterrupt,
100 Stop
101}
102
103pub enum Register {
122 ZERO = 0,
123 RA = 1,
124 SP = 2,
125 GP = 3,
126 TP = 4,
127 T0 = 5,
128 T1 = 6,
129 T2 = 7,
130 FP = 8,
131 S1 = 9,
132 A0 = 10,
133 A1 = 11,
134 A2 = 12,
135 A3 = 13,
136 A4 = 14,
137 A5 = 15,
138 A6 = 16,
139 A7 = 17,
140 S2 = 18,
141 S3 = 19,
142 S4 = 20,
143 S5 = 21,
144 S6 = 22,
145 S7 = 23,
146 S8 = 24,
147 S9 = 25,
148 S10 = 26,
149 S11 = 27,
150 T3 = 28,
151 T4 = 29,
152 T5 = 30,
153 T6 = 31
154}
155
156pub enum FpRegister {
157 FT0 = 0,
158 FT1 = 1,
159 FT2 = 2,
160 FT3 = 3,
161 FT4 = 4,
162 FT5 = 5,
163 FT6 = 6,
164 FT7 = 7,
165 FS0 = 8,
166 FS1 = 9,
167 FA0 = 10,
168 FA1 = 11,
169 FA2 = 12,
170 FA3 = 13,
171 FA4 = 14,
172 FA5 = 15,
173 FA6 = 16,
174 FA7 = 17,
175 FS2 = 18,
176 FS3 = 19,
177 FS4 = 20,
178 FS5 = 21,
179 FS6 = 22,
180 FS7 = 23,
181 FS8 = 24,
182 FS9 = 25,
183 FS10 = 26,
184 FS11 = 27,
185 FT8 = 28,
186 FT9 = 29,
187 FT10 = 30,
188 FT11 = 31
189}
190
191pub struct Cpu {
192 pub pc: *mut u8,
193 pub x: [i64; 32],
194 pub f: [f64; 32],
195 xlen: Xlen,
196 pub csr: [u64; CSR_CAPACITY],
197 reservation: u64, is_reservation_set: bool,
199 stack: Option<Vec<u8>>,
200 ecall_handler: Option<Instruction>
201}
202
203impl Debug for Cpu {
204 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
205 f.debug_struct("Cpu")
206 .field("pc", &self.pc)
207 .field("fcsr", &self.csr[CSR_FCSR_ADDRESS as usize])
208 .field("x", &self.x)
209 .field("f", &self.f)
210 .finish()
211 }
212}
213
214impl Cpu {
215 pub fn new() -> Self {
216 Cpu {
217 pc: null_mut(),
218 x: [0; 32],
219 f: [0.0; 32],
220 xlen: Xlen::Bit64,
221 csr: [0; CSR_CAPACITY],
222 reservation: 0,
223 is_reservation_set: false,
224 stack: None,
225 ecall_handler: None
226 }
227 }
228
229 pub fn fetch(&mut self) -> u32 {
230 unsafe {
231 let result = *(self.pc as *const u32);
232 match result & 3 {
233 3 => {
234 self.pc = self.pc.add(4);
235
236 result
237 },
238 _ => {
239 self.pc = self.pc.add(2);
240
241 Cpu::uncompress(result & 0xffff)
242 }
243 }
244 }
245 }
246
247 pub fn update_pc(&mut self, new_pc: *mut u32) {
248 self.pc = new_pc as *mut u8;
249 }
250
251 pub fn set_ecall_handler(&mut self, handler: Option<Instruction>) {
252 self.ecall_handler = handler;
253 }
254
255 pub fn get_pc(&self) -> usize {
256 self.pc as usize
257 }
258
259 pub fn get_register(&self, register: Register) -> i64 {
260 self.x[register as usize]
261 }
262
263 pub fn set_register(&mut self, register: Register, value: i64) {
264 self.x[register as usize] = value;
265 }
266
267 pub fn set_stack(&mut self, stack: Vec<u8>) {
268 let len = stack.len();
269 let sp = stack.as_ptr() as i64;
270 self.stack = Some(stack);
271 self.x[Register::SP as usize] = sp + len as i64;
273 }
274
275 pub fn remove_stack(&mut self) {
276 self.stack = None;
277 self.x[Register::SP as usize] = 0;
278 }
279 pub fn tick(&mut self) -> Result<(), Trap> {
280 let instruction_address = self.pc;
281 self.csr[CSR_TIME_ADDRESS as usize] = self.csr[CSR_TIME_ADDRESS as usize].wrapping_add(1);
282
283 let word = self.fetch();
284 if let Some(instruction) = Cpu::decode(word) {
285 let result = (instruction.operation)(self, word, instruction_address);
286 self.x[0] = 0; result
289 } else {
290 Err(Trap { trap_type: TrapType::IllegalInstruction, value: word as u64 })
291 }
292 }
293
294 pub fn get_f32(&mut self, reg: usize) -> f32 {
295 f32::from_bits(self.f[reg].to_bits() as u32)
297 }
298
299 pub fn set_f32(&mut self, reg: usize, f: f32) {
300 self.f[reg] = f64::from_bits(0xffffffff00000000 | f.to_bits() as u64);
303 }
304
305 pub fn decode(word: u32) -> Option<&'static Instruction> {
306 match word & 0x7f {
307 0b0110111 => Some(&LUI),
308
309 0b0010111 => Some(&AUIPC),
310
311 0b1101111 => Some(&JAL),
312
313 0b1100111 => Some(&JALR),
314
315 0b1100011 => match (word >> 12) & 7 {
316 0b000 => Some(&BEQ),
317 0b001 => Some(&BNE),
318 0b100 => Some(&BLT),
319 0b101 => Some(&BGE),
320 0b110 => Some(&BLTU),
321 0b111 => Some(&BGEU),
322 _ => None
323 },
324
325 0b0000011 => match (word >> 12) & 7 {
326 0b000 => Some(&LB),
327 0b001 => Some(&LH),
328 0b010 => Some(&LW),
329 0b100 => Some(&LBU),
330 0b101 => Some(&LHU),
331 0b110 => Some(&LWU),
332 0b011 => Some(&LD),
333 _ => None
334 },
335
336 0b0100011 => match (word >> 12) & 7 {
337 0b000 => Some(&SB),
338 0b001 => Some(&SH),
339 0b010 => Some(&SW),
340 0b011 => Some(&SD),
341 _ => None
342 },
343
344 0b0010011 => match (word >> 12) & 7 {
345 0b000 => Some(&ADDI),
346 0b010 => Some(&SLTI),
347 0b011 => Some(&SLTIU),
348 0b100 => Some(&XORI),
349 0b110 => Some(&ORI),
350 0b111 => Some(&ANDI),
351 0b001 => match word >> 25 {
352 0b0000000 => Some(&SLLI),
353 0b0000001 => Some(&SLLI),
354 _ => None
355 },
356 0b101 => match word >> 25 {
357 0b0000000 => Some(&SRLI),
358 0b0000001 => Some(&SRLI),
359 0b0100000 => Some(&SRAI),
360 0b0100001 => Some(&SRAI),
361 _ => None
362 },
363 _ => None
364 },
365
366 0b0110011 => match (word >> 12) & 7 {
367 0b000 => match word >> 25 {
368 0b0000000 => Some(&ADD),
369 0b0000001 => Some(&MUL),
370 0b0100000 => Some(&SUB),
371 _ => None
372 },
373 0b001 => match word >> 25 {
374 0b0000000 => Some(&SLL),
375 0b0000001 => Some(&MULH),
376 _ => None
377 },
378 0b010 => match word >> 25 {
379 0b0000000 => Some(&SLT),
380 0b0000001 => Some(&MULHSU),
381 _ => None
382 },
383 0b011 => match word >> 25 {
384 0b0000000 => Some(&SLTU),
385 0b0000001 => Some(&MULHU),
386 _ => None
387 },
388 0b100 => match word >> 25 {
389 0b0000000 => Some(&XOR),
390 0b0000001 => Some(&DIV),
391 _ => None
392 ,}
393 0b111 => match word >> 25 {
394 0b0000000 => Some(&AND),
395 0b0000001 => Some(&REMU),
396 _ => None
397 },
398 0b101 => match word >> 25 {
399 0b0000000 => Some(&SRL),
400 0b0000001 => Some(&DIVU),
401 0b0100000 => Some(&SRA),
402 _ => None
403 },
404 0b110 => match word >> 25 {
405 0b0000000 => Some(&OR),
406 0b0000001 => Some(&REM),
407 _ => None
408 },
409 _ => None
410 },
411
412 0b0011011 => match (word >> 12) & 7 {
413 0b000 => Some(&ADDIW),
414 0b001 => match word >> 25 {
415 0b0000000 =>Some(&SLLIW),
416 _ => None
417 },
418 0b101 => match word >> 25 {
419 0b0000000 => Some(&SRLIW),
420 0b0100000 => Some(&SRAIW),
421 _ => None
422 },
423 _ => None
424 },
425
426 0b0111011 => match (word >> 12) & 7 {
427 0b000 => match word >> 25 {
428 0b0000000 => Some(&ADDW),
429 0b0000001 => Some(&MULW),
430 0b0100000 => Some(&SUBW),
431 _ => None
432 },
433 0b001 => match word >> 25 {
434 0b0000000 => Some(&SLLW),
435 _ => None
436 },
437 0b101 => match word >> 25 {
438 0b0000000 => Some(&SRLW),
439 0b0000001 => Some(&DIVUW),
440 0b0100000 => Some(&SRAW),
441 _ => None
442 },
443 0b100 => match word >> 25 {
444 0b0000001 => Some(&DIVW),
445 _ => None
446 },
447 0b110 => match word >> 25 {
448 0b0000001 => Some(&REMW),
449 _ => None
450 },
451 0b111 => match word >> 25 {
452 0b0000001 => Some(&REMUW),
453 _ => None
454 },
455 _ => None
456 },
457
458 0b0000111 => match (word >> 12) & 7 {
459 0b010 => Some(&FLW),
460 0b011 => Some(&FLD),
461 _ => None
462 },
463
464 0b0100111 => match (word >> 12) & 7 {
465 0b010 => Some(&FSW),
466 0b011 => Some(&FSD),
467 _ => None
468 },
469
470 0b1010011 => match word >> 25 {
471 0b0000000 => Some(&FADD_S),
472 0b0000001 => Some(&FADD_D),
473 0b0000100 => Some(&FSUB_S),
474 0b0000101 => Some(&FSUB_D),
475 0b0001000 => Some(&FMUL_S),
476 0b0001001 => Some(&FMUL_D),
477 0b0001100 => Some(&FDIV_S),
478 0b0001101 => Some(&FDIV_D),
479 0b0101100 => match (word >> 20) & 31 {
480 0b00000 => Some(&FSQRT_S),
481 _ => None
482 },
483 0b0101101 => match (word >> 20) & 31 {
484 0b00000 => Some(&FSQRT_D),
485 _ => None
486 },
487 0b0010000 => match (word >> 12) & 3 {
488 0b000 => Some(&FSGNJ_S),
489 0b001 => Some(&FSGNJN_S),
490 0b010 => Some(&FSGNJX_S),
491 _ => None
492 },
493 0b0010001 => match (word >> 12) & 3 {
494 0b000 => Some(&FSGNJ_D),
495 0b001 => Some(&FSGNJN_D),
496 0b010 => Some(&FSGNJX_D),
497 _ => None
498 },
499 0b0010100 => match (word >> 12) & 3 {
500 0b000 => Some(&FMIN_S),
501 0b001 => Some(&FMAX_S),
502 _ => None
503 },
504 0b1100000 => match (word >> 20) & 31 {
505 0b00000 => Some(&FCVT_W_S),
506 0b00001 => Some(&FCVT_WU_S),
507 0b00010 => Some(&FCVT_L_S),
508 0b00011 => Some(&FCVT_LU_S),
509 _ => None
510 },
511 0b1110000 => match (word >> 20) & 31 {
512 0b00000 => match (word >> 12) & 3 {
513 0b000 => Some(&FMV_X_W),
514 _ => None
515 },
516 _ => None
517 },
518 0b1010000 => match (word >> 12) & 3 {
519 0b010 => Some(&FEQ_S),
520 0b001 => Some(&FLT_S),
521 0b000 => Some(&FLE_S),
522 _ => None
523 },
524 0b1111000 => match (word >> 20) & 31 {
525 0b00000 => match (word >> 12) & 3 {
526 0b000 => Some(&FMV_W_X),
527 0b001 => Some(&UNIMPLEMENTED), _ => None
529 },
530 _ => None
531 },
532 0b1101000 => match (word >> 20) & 31 {
533 0b00000 => Some(&FCVT_S_W),
534 0b00001 => Some(&FCVT_S_WU),
535 0b00010 => Some(&FCVT_S_L),
536 0b00011 => Some(&FCVT_S_LU),
537 _ => None
538 },
539 0b0100000 => match (word >> 20) & 31 {
540 0b00001 => Some(&FCVT_S_D),
541 _ => None
542 },
543 0b0100001 => match (word >> 20) & 31 {
544 0b00000 => Some(&FCVT_D_S),
545 _ => None
546 },
547
548 0b1010001 => match (word >> 12) & 3 {
549 0b010 => Some(&FEQ_D),
550 0b001 => Some(&FLT_D),
551 0b000 => Some(&FLE_D),
552 _ => None
553 },
554 0b1110001 => match (word >> 20) & 31 {
555 0b00000 => match (word >> 12) & 3 {
556 0b000 => Some(&FMV_X_D),
557 0b001 => Some(&UNIMPLEMENTED), _ => None
559 },
560 _ => None
561 },
562 0b1100001 => match (word >> 20) & 31 {
563 0b00000 => Some(&FCVT_W_D),
564 0b00001 => Some(&FCVT_WU_D),
565 0b00010 => Some(&FCVT_L_D),
566 0b00011 => Some(&FCVT_LU_D),
567 _ => None
568 },
569 0b1101001 => match (word >> 20) & 31 {
570 0b00000 => Some(&FCVT_D_W),
571 0b00001 => Some(&FCVT_D_WU),
572 0b00010 => Some(&FCVT_D_L),
573 0b00011 => Some(&FCVT_D_LU),
574 _ => None
575 },
576 0b1111001 => match (word >> 20) & 31 {
577 0b00000 => match (word >> 12) & 3 {
578 0b000 => Some(&FMV_D_X),
579 _ => None
580 },
581 _ => None
582 },
583
584 0b0010101 => match (word >> 12) & 3 {
585 0b000 => Some(&FMIN_D),
586 0b001 => Some(&FMAX_D),
587 _ => None
588 },
589
590 _ => None
591 },
592
593 0b1000011 => match (word >> 25) & 3 {
594 0b00 => Some(&FMADD_S),
595 0b01 => Some(&FMADD_D),
596 _ => None
597 },
598
599
600 0b1000111 => match (word >> 25) & 3 {
601 0b00 => Some(&FMSUB_S),
602 0b01 => Some(&FMSUB_D),
603 _ => None
604 },
605
606 0b1001011 => match (word >> 25) & 3 {
607 0b00 => Some(&FNMSUB_S),
608 0b01 => Some(&FNMSUB_D),
609 _ => None
610 },
611
612 0b1001111 => match (word >> 25) & 3 {
613 0b00 => Some(&FNMADD_S),
614 0b01 => Some(&FNMADD_D),
615 _ => None
616 },
617
618 0b0001111 => match (word >> 12) & 7 {
619 0b000 => Some(&FENCE),
620 0b001 => Some(&FENCE_I),
621 _ => None
622 },
623
624 0b0101111 => match (word >> 12) & 7 {
625 0b010 => match word >> 27 {
626 0b00010 => match (word >> 20) & 0x1f {
627 0b00000 => Some(&LR_W),
628 _ => None
629 },
630 0b00011 => Some(&SC_W),
631 0b00001 => Some(&AMOSWAP_W),
632 0b00000 => Some(&AMOADD_W),
633 0b00100 => Some(&AMOXOR_W),
634 0b01100 => Some(&AMOAND_W),
635 0b01000 => Some(&AMOOR_W),
636 0b10000 => Some(&AMOMIN_W),
637 0b10100 => Some(&AMOMAX_W),
638 0b11000 => Some(&AMOMINU_W),
639 0b11100 => Some(&AMOMAXU_W),
640 _ => None
641 },
642 0b011 => match word >> 27 {
643 0b00010 => match (word >> 20) & 0x1f {
644 0b00000 => Some(&LR_D),
645 _ => None
646 },
647 0b00011 => Some(&SC_D),
648 0b00001 => Some(&AMOSWAP_D),
649 0b00000 => Some(&AMOADD_D),
650 0b00100 => Some(&AMOXOR_D),
651 0b01100 => Some(&AMOAND_D),
652 0b01000 => Some(&AMOOR_D),
653 0b10000 => Some(&AMOMIN_D),
654 0b10100 => Some(&AMOMAX_D),
655 0b11000 => Some(&AMOMINU_D),
656 0b11100 => Some(&AMOMAXU_D),
657 _ => None
658 },
659 _ => None
660 },
661
662 0b1110011 => match (word >> 12) & 7 {
663 0b000 => match word {
664 0b00000000000000000000000001110011 => Some(&ECALL),
665 0b00000000000100000000000001110011 => Some(&EBREAK),
666 0b00110000001000000000000001110011 => Some(&MRET),
667 _ => None
668 },
669 0b001 => Some(&CSRRW),
670 0b010 => Some(&CSRRS),
671 0b011 => Some(&CSRRC),
672 0b101 => Some(&CSRRWI),
673 0b110 => Some(&CSRRSI),
674 0b111 => Some(&CSRRCI),
675 _ => None
676 },
677
678 _ => None
679 }
680 }
681
682 pub fn uncompress(halfword: u32) -> u32 {
683 let op = halfword & 0x3; let funct3 = (halfword >> 13) & 0x7; match op {
689 0 => match funct3 {
690 0 => {
691 let rd = (halfword >> 2) & 0x7; let nzuimm =
695 ((halfword >> 7) & 0x30) | ((halfword >> 1) & 0x3c0) | ((halfword >> 4) & 0x4) | ((halfword >> 2) & 0x8); if nzuimm != 0 {
701 return (nzuimm << 20) | (2 << 15) | ((rd + 8) << 7) | 0x13;
702 }
703 },
704 1 => {
705 let rd = (halfword >> 2) & 0x7; let rs1 = (halfword >> 7) & 0x7; let offset =
711 ((halfword >> 7) & 0x38) | ((halfword << 1) & 0xc0); return (offset << 20) | ((rs1 + 8) << 15) | (3 << 12) | ((rd + 8) << 7) | 0x7;
714 },
715 2 => {
716 let rs1 = (halfword >> 7) & 0x7; let rd = (halfword >> 2) & 0x7; let offset =
721 ((halfword >> 7) & 0x38) | ((halfword >> 4) & 0x4) | ((halfword << 1) & 0x40); return (offset << 20) | ((rs1 + 8) << 15) | (2 << 12) | ((rd + 8) << 7) | 0x3;
725 },
726 3 => {
727 let rs1 = (halfword >> 7) & 0x7; let rd = (halfword >> 2) & 0x7; let offset =
733 ((halfword >> 7) & 0x38) | ((halfword << 1) & 0xc0); return (offset << 20) | ((rs1 + 8) << 15) | (3 << 12) | ((rd + 8) << 7) | 0x3;
736 },
737 4 => {
738 },
740 5 => {
741 let rs1 = (halfword >> 7) & 0x7; let rs2 = (halfword >> 2) & 0x7; let offset =
746 ((halfword >> 7) & 0x38) | ((halfword << 1) & 0xc0); let imm11_5 = (offset >> 5) & 0x7f;
749 let imm4_0 = offset & 0x1f;
750 return (imm11_5 << 25) | ((rs2 + 8) << 20) | ((rs1 + 8) << 15) | (3 << 12) | (imm4_0 << 7) | 0x27;
751 },
752 6 => {
753 let rs1 = (halfword >> 7) & 0x7; let rs2 = (halfword >> 2) & 0x7; let offset =
758 ((halfword >> 7) & 0x38) | ((halfword << 1) & 0x40) | ((halfword >> 4) & 0x4); let imm11_5 = (offset >> 5) & 0x7f;
762 let imm4_0 = offset & 0x1f;
763 return (imm11_5 << 25) | ((rs2 + 8) << 20) | ((rs1 + 8) << 15) | (2 << 12) | (imm4_0 << 7) | 0x23;
764 },
765 7 => {
766 let rs1 = (halfword >> 7) & 0x7; let rs2 = (halfword >> 2) & 0x7; let offset =
772 ((halfword >> 7) & 0x38) | ((halfword << 1) & 0xc0); let imm11_5 = (offset >> 5) & 0x7f;
775 let imm4_0 = offset & 0x1f;
776 return (imm11_5 << 25) | ((rs2 + 8) << 20) | ((rs1 + 8) << 15) | (3 << 12) | (imm4_0 << 7) | 0x23;
777 },
778 _ => {} },
780 1 => {
781 match funct3 {
782 0 => {
783 let r = (halfword >> 7) & 0x1f; let imm = match halfword & 0x1000 {
785 0x1000 => 0xffffffc0,
786 _ => 0
787 } | ((halfword >> 7) & 0x20) | ((halfword >> 2) & 0x1f); if r == 0 && imm == 0 {
791 return 0x13;
794 } else if r != 0 {
795 return (imm << 20) | (r << 15) | (r << 7) | 0x13;
798 }
799 },
802 1 => {
803 let r = (halfword >> 7) & 0x1f;
807 let imm = match halfword & 0x1000 {
808 0x1000 => 0xffffffc0,
809 _ => 0
810 } | ((halfword >> 7) & 0x20) | ((halfword >> 2) & 0x1f); if r != 0 {
814 return (imm << 20) | (r << 15) | (r << 7) | 0x1b;
815 }
816 },
818 2 => {
819 let r = (halfword >> 7) & 0x1f;
822 let imm = match halfword & 0x1000 {
823 0x1000 => 0xffffffc0,
824 _ => 0
825 } | ((halfword >> 7) & 0x20) | ((halfword >> 2) & 0x1f); if r != 0 {
829 return (imm << 20) | (r << 7) | 0x13;
830 }
831 },
834 3 => {
835 let r = (halfword >> 7) & 0x1f; if r == 2 {
837 let imm = match halfword & 0x1000 {
840 0x1000 => 0xfffffc00,
841 _ => 0
842 } | ((halfword >> 3) & 0x200) | ((halfword >> 2) & 0x10) | ((halfword << 1) & 0x40) | ((halfword << 4) & 0x180) | ((halfword << 3) & 0x20); if imm != 0 {
849 return (imm << 20) | (r << 15) | (r << 7) | 0x13;
850 }
851 }
853 if r != 0 && r != 2 {
854 let nzimm = match halfword & 0x1000 {
857 0x1000 => 0xfffc0000,
858 _ => 0
859 } | ((halfword << 5) & 0x20000) | ((halfword << 10) & 0x1f000); if nzimm != 0 {
863 return nzimm | (r << 7) | 0x37;
864 }
865 }
867 },
868 4 => {
869 let funct2 = (halfword >> 10) & 0x3; match funct2 {
871 0 => {
872 let shamt =
875 ((halfword >> 7) & 0x20) | ((halfword >> 2) & 0x1f); let rs1 = (halfword >> 7) & 0x7; return (shamt << 20) | ((rs1 + 8) << 15) | (5 << 12) | ((rs1 + 8) << 7) | 0x13;
879 },
880 1 => {
881 let shamt =
884 ((halfword >> 7) & 0x20) | ((halfword >> 2) & 0x1f); let rs1 = (halfword >> 7) & 0x7; return (0x20 << 25) | (shamt << 20) | ((rs1 + 8) << 15) | (5 << 12) | ((rs1 + 8) << 7) | 0x13;
888 },
889 2 => {
890 let r = (halfword >> 7) & 0x7; let imm = match halfword & 0x1000 {
894 0x1000 => 0xffffffc0,
895 _ => 0
896 } | ((halfword >> 7) & 0x20) | ((halfword >> 2) & 0x1f); return (imm << 20) | ((r + 8) << 15) | (7 << 12) | ((r + 8) << 7) | 0x13;
900 },
901 3 => {
902 let funct1 = (halfword >> 12) & 1; let funct2_2 = (halfword >> 5) & 0x3; let rs1 = (halfword >> 7) & 0x7;
905 let rs2 = (halfword >> 2) & 0x7;
906 match funct1 {
907 0 => match funct2_2 {
908 0 => {
909 return (0x20 << 25) | ((rs2 + 8) << 20) | ((rs1 + 8) << 15) | ((rs1 + 8) << 7) | 0x33;
912 },
913 1 => {
914 return ((rs2 + 8) << 20) | ((rs1 + 8) << 15) | (4 << 12) | ((rs1 + 8) << 7) | 0x33;
917 },
918 2 => {
919 return ((rs2 + 8) << 20) | ((rs1 + 8) << 15) | (6 << 12) | ((rs1 + 8) << 7) | 0x33;
922 },
923 3 => {
924 return ((rs2 + 8) << 20) | ((rs1 + 8) << 15) | (7 << 12) | ((rs1 + 8) << 7) | 0x33;
927 },
928 _ => {} },
930 1 => match funct2_2 {
931 0 => {
932 return (0x20 << 25) | ((rs2 + 8) << 20) | ((rs1 + 8) << 15) | ((rs1 + 8) << 7) | 0x3b;
935 },
936 1 => {
937 return ((rs2 + 8) << 20) | ((rs1 + 8) << 15) | ((rs1 + 8) << 7) | 0x3b;
940 },
941 2 => {
942 },
944 3 => {
945 },
947 _ => {} },
949 _ => {} };
951 },
952 _ => {} };
954 },
955 5 => {
956 let offset =
959 match halfword & 0x1000 {
960 0x1000 => 0xfffff000,
961 _ => 0
962 } | ((halfword >> 1) & 0x800) | ((halfword >> 7) & 0x10) | ((halfword >> 1) & 0x300) | ((halfword << 2) & 0x400) | ((halfword >> 1) & 0x40) | ((halfword << 1) & 0x80) | ((halfword >> 2) & 0xe) | ((halfword << 3) & 0x20); let imm =
972 ((offset >> 1) & 0x80000) | ((offset << 8) & 0x7fe00) | ((offset >> 3) & 0x100) | ((offset >> 12) & 0xff); return (imm << 12) | 0x6f;
977 },
978 6 => {
979 let r = (halfword >> 7) & 0x7;
982 let offset =
983 match halfword & 0x1000 {
984 0x1000 => 0xfffffe00,
985 _ => 0
986 } | ((halfword >> 4) & 0x100) | ((halfword >> 7) & 0x18) | ((halfword << 1) & 0xc0) | ((halfword >> 2) & 0x6) | ((halfword << 3) & 0x20); let imm2 =
993 ((offset >> 6) & 0x40) | ((offset >> 5) & 0x3f); let imm1 =
996 (offset & 0x1e) | ((offset >> 11) & 0x1); return (imm2 << 25) | ((r + 8) << 20) | (imm1 << 7) | 0x63;
999 },
1000 7 => {
1001 let r = (halfword >> 7) & 0x7;
1004 let offset =
1005 match halfword & 0x1000 {
1006 0x1000 => 0xfffffe00,
1007 _ => 0
1008 } | ((halfword >> 4) & 0x100) | ((halfword >> 7) & 0x18) | ((halfword << 1) & 0xc0) | ((halfword >> 2) & 0x6) | ((halfword << 3) & 0x20); let imm2 =
1015 ((offset >> 6) & 0x40) | ((offset >> 5) & 0x3f); let imm1 =
1018 (offset & 0x1e) | ((offset >> 11) & 0x1); return (imm2 << 25) | ((r + 8) << 20) | (1 << 12) | (imm1 << 7) | 0x63;
1021 },
1022 _ => {} };
1024 },
1025 2 => {
1026 match funct3 {
1027 0 => {
1028 let r = (halfword >> 7) & 0x1f;
1031 let shamt =
1032 ((halfword >> 7) & 0x20) | ((halfword >> 2) & 0x1f); return (shamt << 20) | (r << 15) | (1 << 12) | (r << 7) | 0x13;
1036 },
1039 1 => {
1040 let rd = (halfword >> 7) & 0x1f;
1043 let offset =
1044 ((halfword >> 7) & 0x20) | ((halfword >> 2) & 0x18) | ((halfword << 4) & 0x1c0); return (offset << 20) | (2 << 15) | (3 << 12) | (rd << 7) | 0x7;
1049 },
1052 2 => {
1053 let r = (halfword >> 7) & 0x1f;
1056 let offset =
1057 ((halfword >> 7) & 0x20) | ((halfword >> 2) & 0x1c) | ((halfword << 4) & 0xc0); return (offset << 20) | (2 << 15) | (2 << 12) | (r << 7) | 0x3;
1062 },
1065 3 => {
1066 let rd = (halfword >> 7) & 0x1f;
1070 let offset =
1071 ((halfword >> 7) & 0x20) | ((halfword >> 2) & 0x18) | ((halfword << 4) & 0x1c0); return (offset << 20) | (2 << 15) | (3 << 12) | (rd << 7) | 0x3;
1076 },
1079 4 => {
1080 let funct1 = (halfword >> 12) & 1; let rs1 = (halfword >> 7) & 0x1f; let rs2 = (halfword >> 2) & 0x1f; match funct1 {
1084 0 => {
1085 if rs1 != 0 && rs2 == 0 {
1086 return (rs1 << 15) | 0x67;
1089 }
1090 if rs1 != 0 && rs2 != 0 {
1092 return (rs2 << 20) | (rs1 << 7) | 0x33;
1096 }
1097 },
1100 1 => {
1101 if rs1 == 0 && rs2 == 0 {
1102 return 0x00100073;
1105 }
1106 if rs1 != 0 && rs2 == 0 {
1107 return (rs1 << 15) | (1 << 7) | 0x67;
1110 }
1111 if rs1 != 0 && rs2 != 0 {
1112 return (rs2 << 20) | (rs1 << 15) | (rs1 << 7) | 0x33;
1115 }
1116 },
1119 _ => {} };
1121 },
1122 5 => {
1123 let rs2 = (halfword >> 2) & 0x1f; let offset =
1128 ((halfword >> 7) & 0x38) | ((halfword >> 1) & 0x1c0); let imm11_5 = (offset >> 5) & 0x3f;
1131 let imm4_0 = offset & 0x1f;
1132 return (imm11_5 << 25) | (rs2 << 20) | (2 << 15) | (3 << 12) | (imm4_0 << 7) | 0x27;
1133 },
1134 6 => {
1135 let rs2 = (halfword >> 2) & 0x1f; let offset =
1139 ((halfword >> 7) & 0x3c) | ((halfword >> 1) & 0xc0); let imm11_5 = (offset >> 5) & 0x3f;
1142 let imm4_0 = offset & 0x1f;
1143 return (imm11_5 << 25) | (rs2 << 20) | (2 << 15) | (2 << 12) | (imm4_0 << 7) | 0x23;
1144 },
1145 7 => {
1146 let rs2 = (halfword >> 2) & 0x1f; let offset =
1151 ((halfword >> 7) & 0x38) | ((halfword >> 1) & 0x1c0); let imm11_5 = (offset >> 5) & 0x3f;
1154 let imm4_0 = offset & 0x1f;
1155 return (imm11_5 << 25) | (rs2 << 20) | (2 << 15) | (3 << 12) | (imm4_0 << 7) | 0x23;
1156 },
1157 _ => {} };
1159 },
1160 _ => {} };
1162 0xffffffff }
1164
1165 pub fn sign_extend(&self, value: i64) -> i64 {
1166 match self.xlen {
1167 Xlen::Bit32 => value as i32 as i64,
1168 Xlen::Bit64 => value
1169 }
1170 }
1171
1172 pub fn unsigned_data(&self, value: i64) -> u64 {
1173 match self.xlen {
1174 Xlen::Bit32 => (value & 0xffffffff) as u64,
1175 Xlen::Bit64 => value as u64
1176 }
1177 }
1178
1179 pub fn most_negative(&self) -> i64 {
1180 match self.xlen {
1181 Xlen::Bit32 => i32::MIN as i64,
1182 Xlen::Bit64 => i64::MIN
1183 }
1184 }
1185
1186 pub fn read_csr(&self, address: u16) -> u64 {
1187 match address {
1188 CSR_FFLAGS_ADDRESS => self.read_fflags(),
1190 CSR_FRM_ADDRESS => (self.csr[CSR_FCSR_ADDRESS as usize] >> 5) & 0x7,
1191 CSR_SSTATUS_ADDRESS => self.csr[CSR_MSTATUS_ADDRESS as usize] & 0x80000003000de162,
1192 CSR_SIE_ADDRESS => self.csr[CSR_MIE_ADDRESS as usize] & 0x222,
1193 CSR_SIP_ADDRESS => self.csr[CSR_MIP_ADDRESS as usize] & 0x222,
1194 CSR_FCSR_ADDRESS => self.csr[CSR_FCSR_ADDRESS as usize] & 0xff,
1195 _ => self.csr[address as usize]
1196 }
1197 }
1198
1199 pub fn write_csr(&mut self, address: u16, value: u64) {
1200 match address {
1201 CSR_FFLAGS_ADDRESS => self.write_fflags(value),
1202 CSR_FRM_ADDRESS => {
1203 self.csr[CSR_FCSR_ADDRESS as usize] &= !0xe0;
1204 self.csr[CSR_FCSR_ADDRESS as usize] |= (value << 5) & 0xe0;
1205 },
1206 CSR_SSTATUS_ADDRESS => {
1207 self.csr[CSR_MSTATUS_ADDRESS as usize] &= !0x80000003000de162;
1208 self.csr[CSR_MSTATUS_ADDRESS as usize] |= value & 0x80000003000de162;
1209 },
1210 CSR_SIE_ADDRESS => {
1211 self.csr[CSR_MIE_ADDRESS as usize] &= !0x222;
1212 self.csr[CSR_MIE_ADDRESS as usize] |= value & 0x222;
1213 },
1214 CSR_SIP_ADDRESS => {
1215 self.csr[CSR_MIP_ADDRESS as usize] &= !0x222;
1216 self.csr[CSR_MIP_ADDRESS as usize] |= value & 0x222;
1217 },
1218 CSR_MIDELEG_ADDRESS => {
1219 self.csr[address as usize] = value & 0x666; },
1221 _ => {
1222 self.csr[address as usize] = value;
1223 }
1224 };
1225 }
1226
1227 pub fn set_fcsr_nx(&mut self) {
1228 let flags = self.read_fflags();
1229 self.write_fflags(flags | 1);
1230 }
1231
1232 pub fn set_fcsr_dz(&mut self) {
1233 let flags = self.read_fflags();
1234 self.write_fflags(flags | 8);
1235 }
1236
1237 pub fn set_fcsr_nv(&mut self) {
1238 let flags = self.read_fflags();
1239 self.write_fflags(flags | 16);
1240 }
1241
1242 #[cfg(target_arch = "x86_64")]
1243 fn read_fflags(&self) -> u64 {
1244 use core::arch::x86_64::*;
1245 let intel = unsafe { _mm_getcsr() };
1246
1247 let inexact = match intel & _MM_EXCEPT_INEXACT {
1248 _MM_EXCEPT_INEXACT => 1,
1249 _ => 0
1250 };
1251
1252 let underflow = match intel & _MM_EXCEPT_UNDERFLOW {
1253 _MM_EXCEPT_UNDERFLOW => 2,
1254 _ => 0
1255 };
1256
1257 let overflow = match intel & _MM_EXCEPT_OVERFLOW {
1258 _MM_EXCEPT_OVERFLOW => 4,
1259 _ => 0
1260 };
1261
1262 let div_by_zero = match intel & _MM_EXCEPT_DIV_ZERO {
1263 _MM_EXCEPT_DIV_ZERO => 8,
1264 _ => 0
1265 };
1266
1267 let invalid_op = match intel & _MM_EXCEPT_INVALID {
1268 _MM_EXCEPT_INVALID => 16,
1269 _ => 0
1270 };
1271
1272 let flags = self.csr[CSR_FCSR_ADDRESS as usize] & !0x1f;
1273
1274 flags | inexact | underflow | overflow | div_by_zero | invalid_op
1276 }
1277
1278 #[cfg(not(target_arch = "x86_64"))]
1279 fn read_fflags(&self) -> u64 {
1280 self.csr[CSR_FCSR_ADDRESS as usize] & 0x1f
1281 }
1282
1283 #[cfg(target_arch = "x86_64")]
1284 fn write_fflags(&mut self, value: u64) {
1285 use core::arch::x86_64::*;
1286 let mut flags = unsafe { _mm_getcsr() } & !_MM_EXCEPT_MASK;
1287
1288 if value & 1 == 1 {
1291 flags = flags | _MM_EXCEPT_INEXACT;
1292 }
1293 if value & 2 == 2 {
1294 flags = flags | _MM_EXCEPT_OVERFLOW;
1295 }
1296 if value & 4 == 4 {
1297 flags = flags | _MM_EXCEPT_OVERFLOW;
1298 }
1299 if value & 8 == 8 {
1300 flags = flags | _MM_EXCEPT_DIV_ZERO;
1301 }
1302 if value & 16 == 16 {
1303 flags = flags | _MM_EXCEPT_INVALID;
1304 }
1305
1306 unsafe { _mm_setcsr(flags); }
1307 }
1308
1309 #[cfg(not(target_arch = "x86_64"))]
1310 fn write_fflags(&mut self, value: u64) {
1311 self.csr[CSR_FCSR_ADDRESS as usize] &= !0x1f;
1312 self.csr[CSR_FCSR_ADDRESS as usize] |= value & 0x1f;
1313 }
1314}
1315
1316
1317pub const UNIMPLEMENTED: Instruction = Instruction {
1318 name: "UNIMP",
1319 operation: |_cpu, word, _address| {
1320 Err(Trap{
1321 trap_type: TrapType::IllegalInstruction,
1322 value: word as u64
1323 })
1324 }
1325};
1326
1327const MRET: Instruction = Instruction {
1329 name: "MRET",
1330 operation: |cpu, _word, _address| {
1331 cpu.pc = cpu.read_csr(CSR_MEPC_ADDRESS) as *mut u8;
1332
1333 let status = cpu.read_csr(CSR_MSTATUS_ADDRESS);
1334 let mpie = (status >> 7) & 1;
1335 let mprv = 0;
1337 let new_status = (status & !0x21888) | (mprv << 17) | (mpie << 3) | (1 << 7);
1340 cpu.write_csr(CSR_MSTATUS_ADDRESS, new_status);
1341 Ok(())
1342 }
1343};
1344
1345#[cfg(test)]
1346mod test_cpu {
1347 use super::*;
1348
1349 #[test]
1350 fn babys_first_instruction() {
1351 let mut cpu = Cpu::new();
1352 let mut instruction= vec![0x00000505]; cpu.update_pc(&mut instruction[0]);
1354 let pc1 = cpu.get_pc();
1355 assert_eq!(cpu.x[10], 0);
1356 cpu.tick().ok().expect("cpu failure");
1357 assert_eq!(cpu.x[10], 1);
1358 let pc2 = cpu.get_pc();
1359 assert_eq!(2, pc2 - pc1);
1360 }
1361
1362 #[test]
1363 fn two_compressed_instruction() {
1364 let mut cpu = Cpu::new();
1365 let mut instruction= vec![0x05050505];
1366 cpu.update_pc(&mut instruction[0]);
1367 let pc1 = cpu.get_pc();
1368 assert_eq!(cpu.x[10], 0);
1369 cpu.tick().ok().expect("cpu failure");
1370 assert_eq!(cpu.x[10], 1);
1371 cpu.tick().ok().expect("cpu failure");
1372 assert_eq!(cpu.x[10], 2);
1373 let pc2 = cpu.get_pc();
1374 assert_eq!(4, pc2 - pc1);
1375 }
1376
1377 #[test]
1378 fn decode_fld_compressed_instruction() {
1379 let opcode = Cpu::uncompress(0x3022);
1380 match Cpu::decode(opcode) {
1383 Some(instruction) => assert_eq!(instruction.name, "FLD"),
1384 _ => panic!("invalid instruction")
1385 }
1386 }
1387
1388 #[test]
1389 fn decode_srai_compressed_instruction() {
1390 let opcode = Cpu::uncompress(0x9561);
1391 match Cpu::decode(opcode) {
1394 Some(instruction) => assert_eq!(instruction.name, "SRAI"),
1395 _ => panic!("invalid instruction")
1396 }
1397 }
1398}