user_mode_riscv/
cpu.rs

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 // Trap type specific value
72}
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
103/*
104
105Register	ABI Name	Description	Saver
106x0	        zero	    hardwired zero	-
107x1	        ra	        return address	Caller
108x2	        sp	        stack pointer	Callee
109x3	        gp	        global pointer	-
110x4	        tp	        thread pointer	-
111x5-7	    t0-2	    temporary registers	Caller
112x8	        s0 / fp	    Callee
113x9	        s1	        saved register	Callee
114x10-11	    a0-1	    function arguments / return values	Caller
115x12-17	    a2-7	    function arguments	Caller
116x18-27	    s2-11	    saved registers	Callee
117x28-31	    t3-6	    temporary registers	Caller
118
119 */
120
121pub 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, // @TODO: Should support multiple address reservations
198    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        // the stack moves grows in a downwards direction apparently
272        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; // make sure x0 is still zero!
287
288            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        // only consider the bottom 32 bits of the register
296        f32::from_bits(self.f[reg].to_bits() as u32)
297    }
298
299    pub fn set_f32(&mut self, reg: usize, f: f32) {
300        // the Risc V spec says that setting the f register with a 32 bit float should
301        // set the top 32 bits of the register to 1
302        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), // FCLASS_S
528                        _ => 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), // FCLASS.D
558                        _ => 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; // [1:0]
684        let funct3 = (halfword >> 13) & 0x7; // [15:13]
685
686        // println!("op = {:?} funct3 = {:?}", op, funct3);
687
688        match op {
689            0 => match funct3 {
690                0 => {
691                    // C.ADDI4SPN
692                    // addi rd+8, x2, nzuimm
693                    let rd = (halfword >> 2) & 0x7; // [4:2]
694                    let nzuimm =
695                        ((halfword >> 7) & 0x30) | // nzuimm[5:4] <= [12:11]
696                            ((halfword >> 1) & 0x3c0) | // nzuimm{9:6] <= [10:7]
697                            ((halfword >> 4) & 0x4) | // nzuimm[2] <= [6]
698                            ((halfword >> 2) & 0x8); // nzuimm[3] <= [5]
699                    // nzuimm == 0 is reserved instruction
700                    if nzuimm != 0 {
701                        return (nzuimm << 20) | (2 << 15) | ((rd + 8) << 7) | 0x13;
702                    }
703                },
704                1 => {
705                    // @TODO: Support C.LQ for 128-bit
706                    // C.FLD for 32, 64-bit
707                    // fld rd+8, offset(rs1+8)
708                    let rd = (halfword >> 2) & 0x7; // [4:2]
709                    let rs1 = (halfword >> 7) & 0x7; // [9:7]
710                    let offset =
711                        ((halfword >> 7) & 0x38) | // offset[5:3] <= [12:10]
712                            ((halfword << 1) & 0xc0); // offset[7:6] <= [6:5]
713                    return (offset << 20) | ((rs1 + 8) << 15) | (3 << 12) | ((rd + 8) << 7) | 0x7;
714                },
715                2 => {
716                    // C.LW
717                    // lw rd+8, offset(rs1+8)
718                    let rs1 = (halfword >> 7) & 0x7; // [9:7]
719                    let rd = (halfword >> 2) & 0x7; // [4:2]
720                    let offset =
721                        ((halfword >> 7) & 0x38) | // offset[5:3] <= [12:10]
722                            ((halfword >> 4) & 0x4) | // offset[2] <= [6]
723                            ((halfword << 1) & 0x40); // offset[6] <= [5]
724                    return (offset << 20) | ((rs1 + 8) << 15) | (2 << 12) | ((rd + 8) << 7) | 0x3;
725                },
726                3 => {
727                    // @TODO: Support C.FLW in 32-bit mode
728                    // C.LD in 64-bit mode
729                    // ld rd+8, offset(rs1+8)
730                    let rs1 = (halfword >> 7) & 0x7; // [9:7]
731                    let rd = (halfword >> 2) & 0x7; // [4:2]
732                    let offset =
733                        ((halfword >> 7) & 0x38) | // offset[5:3] <= [12:10]
734                            ((halfword << 1) & 0xc0); // offset[7:6] <= [6:5]
735                    return (offset << 20) | ((rs1 + 8) << 15) | (3 << 12) | ((rd + 8) << 7) | 0x3;
736                },
737                4 => {
738                    // Reserved
739                },
740                5 => {
741                    // C.FSD
742                    // fsd rs2+8, offset(rs1+8)
743                    let rs1 = (halfword >> 7) & 0x7; // [9:7]
744                    let rs2 = (halfword >> 2) & 0x7; // [4:2]
745                    let offset =
746                        ((halfword >> 7) & 0x38) | // uimm[5:3] <= [12:10]
747                            ((halfword << 1) & 0xc0); // uimm[7:6] <= [6:5]
748                    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                    // C.SW
754                    // sw rs2+8, offset(rs1+8)
755                    let rs1 = (halfword >> 7) & 0x7; // [9:7]
756                    let rs2 = (halfword >> 2) & 0x7; // [4:2]
757                    let offset =
758                        ((halfword >> 7) & 0x38) | // offset[5:3] <= [12:10]
759                            ((halfword << 1) & 0x40) | // offset[6] <= [5]
760                            ((halfword >> 4) & 0x4); // offset[2] <= [6]
761                    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                    // @TODO: Support C.FSW in 32-bit mode
767                    // C.SD
768                    // sd rs2+8, offset(rs1+8)
769                    let rs1 = (halfword >> 7) & 0x7; // [9:7]
770                    let rs2 = (halfword >> 2) & 0x7; // [4:2]
771                    let offset =
772                        ((halfword >> 7) & 0x38) | // uimm[5:3] <= [12:10]
773                            ((halfword << 1) & 0xc0); // uimm[7:6] <= [6:5]
774                    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                _ => {} // Not happens
779            },
780            1 => {
781                match funct3 {
782                    0 => {
783                        let r = (halfword >> 7) & 0x1f; // [11:7]
784                        let imm = match halfword & 0x1000 {
785                            0x1000 => 0xffffffc0,
786                            _ => 0
787                        } | // imm[31:6] <= [12]
788                            ((halfword >> 7) & 0x20) | // imm[5] <= [12]
789                            ((halfword >> 2) & 0x1f); // imm[4:0] <= [6:2]
790                        if r == 0 && imm == 0 {
791                            // C.NOP
792                            // addi x0, x0, 0
793                            return 0x13;
794                        } else if r != 0 {
795                            // C.ADDI
796                            // addi r, r, imm
797                            return (imm << 20) | (r << 15) | (r << 7) | 0x13;
798                        }
799                        // @TODO: Support HINTs
800                        // r == 0 and imm != 0 is HINTs
801                    },
802                    1 => {
803                        // @TODO: Support C.JAL in 32-bit mode
804                        // C.ADDIW
805                        // addiw r, r, imm
806                        let r = (halfword >> 7) & 0x1f;
807                        let imm = match halfword & 0x1000 {
808                            0x1000 => 0xffffffc0,
809                            _ => 0
810                        } | // imm[31:6] <= [12]
811                            ((halfword >> 7) & 0x20) | // imm[5] <= [12]
812                            ((halfword >> 2) & 0x1f); // imm[4:0] <= [6:2]
813                        if r != 0 {
814                            return (imm << 20) | (r << 15) | (r << 7) | 0x1b;
815                        }
816                        // r == 0 is reserved instruction
817                    },
818                    2 => {
819                        // C.LI
820                        // addi rd, x0, imm
821                        let r = (halfword >> 7) & 0x1f;
822                        let imm = match halfword & 0x1000 {
823                            0x1000 => 0xffffffc0,
824                            _ => 0
825                        } | // imm[31:6] <= [12]
826                            ((halfword >> 7) & 0x20) | // imm[5] <= [12]
827                            ((halfword >> 2) & 0x1f); // imm[4:0] <= [6:2]
828                        if r != 0 {
829                            return (imm << 20) | (r << 7) | 0x13;
830                        }
831                        // @TODO: Support HINTs
832                        // r == 0 is for HINTs
833                    },
834                    3 => {
835                        let r = (halfword >> 7) & 0x1f; // [11:7]
836                        if r == 2 {
837                            // C.ADDI16SP
838                            // addi r, r, nzimm
839                            let imm = match halfword & 0x1000 {
840                                0x1000 => 0xfffffc00,
841                                _ => 0
842                            } | // imm[31:10] <= [12]
843                                ((halfword >> 3) & 0x200) | // imm[9] <= [12]
844                                ((halfword >> 2) & 0x10) | // imm[4] <= [6]
845                                ((halfword << 1) & 0x40) | // imm[6] <= [5]
846                                ((halfword << 4) & 0x180) | // imm[8:7] <= [4:3]
847                                ((halfword << 3) & 0x20); // imm[5] <= [2]
848                            if imm != 0 {
849                                return (imm << 20) | (r << 15) | (r << 7) | 0x13;
850                            }
851                            // imm == 0 is for reserved instruction
852                        }
853                        if r != 0 && r != 2 {
854                            // C.LUI
855                            // lui r, nzimm
856                            let nzimm = match halfword & 0x1000 {
857                                0x1000 => 0xfffc0000,
858                                _ => 0
859                            } | // nzimm[31:18] <= [12]
860                                ((halfword << 5) & 0x20000) | // nzimm[17] <= [12]
861                                ((halfword << 10) & 0x1f000); // nzimm[16:12] <= [6:2]
862                            if nzimm != 0 {
863                                return nzimm | (r << 7) | 0x37;
864                            }
865                            // nzimm == 0 is for reserved instruction
866                        }
867                    },
868                    4 => {
869                        let funct2 = (halfword >> 10) & 0x3; // [11:10]
870                        match funct2 {
871                            0 => {
872                                // C.SRLI
873                                // c.srli rs1+8, rs1+8, shamt
874                                let shamt =
875                                    ((halfword >> 7) & 0x20) | // shamt[5] <= [12]
876                                        ((halfword >> 2) & 0x1f); // shamt[4:0] <= [6:2]
877                                let rs1 = (halfword >> 7) & 0x7; // [9:7]
878                                return (shamt << 20) | ((rs1 + 8) << 15) | (5 << 12) | ((rs1 + 8) << 7) | 0x13;
879                            },
880                            1 => {
881                                // C.SRAI
882                                // srai rs1+8, rs1+8, shamt
883                                let shamt =
884                                    ((halfword >> 7) & 0x20) | // shamt[5] <= [12]
885                                        ((halfword >> 2) & 0x1f); // shamt[4:0] <= [6:2]
886                                let rs1 = (halfword >> 7) & 0x7; // [9:7]
887                                return (0x20 << 25) | (shamt << 20) | ((rs1 + 8) << 15) | (5 << 12) | ((rs1 + 8) << 7) | 0x13;
888                            },
889                            2 => {
890                                // C.ANDI
891                                // andi, r+8, r+8, imm
892                                let r = (halfword >> 7) & 0x7; // [9:7]
893                                let imm = match halfword & 0x1000 {
894                                    0x1000 => 0xffffffc0,
895                                    _ => 0
896                                } | // imm[31:6] <= [12]
897                                    ((halfword >> 7) & 0x20) | // imm[5] <= [12]
898                                    ((halfword >> 2) & 0x1f); // imm[4:0] <= [6:2]
899                                return (imm << 20) | ((r + 8) << 15) | (7 << 12) | ((r + 8) << 7) | 0x13;
900                            },
901                            3 => {
902                                let funct1 = (halfword >> 12) & 1; // [12]
903                                let funct2_2 = (halfword >> 5) & 0x3; // [6:5]
904                                let rs1 = (halfword >> 7) & 0x7;
905                                let rs2 = (halfword >> 2) & 0x7;
906                                match funct1 {
907                                    0 => match funct2_2 {
908                                        0 => {
909                                            // C.SUB
910                                            // sub rs1+8, rs1+8, rs2+8
911                                            return (0x20 << 25) | ((rs2 + 8) << 20) | ((rs1 + 8) << 15) | ((rs1 + 8) << 7) | 0x33;
912                                        },
913                                        1 => {
914                                            // C.XOR
915                                            // xor rs1+8, rs1+8, rs2+8
916                                            return ((rs2 + 8) << 20) | ((rs1 + 8) << 15) | (4 << 12) | ((rs1 + 8) << 7) | 0x33;
917                                        },
918                                        2 => {
919                                            // C.OR
920                                            // or rs1+8, rs1+8, rs2+8
921                                            return ((rs2 + 8) << 20) | ((rs1 + 8) << 15) | (6 << 12) | ((rs1 + 8) << 7) | 0x33;
922                                        },
923                                        3 => {
924                                            // C.AND
925                                            // and rs1+8, rs1+8, rs2+8
926                                            return ((rs2 + 8) << 20) | ((rs1 + 8) << 15) | (7 << 12) | ((rs1 + 8) << 7) | 0x33;
927                                        },
928                                        _ => {} // Not happens
929                                    },
930                                    1 => match funct2_2 {
931                                        0 => {
932                                            // C.SUBW
933                                            // subw r1+8, r1+8, r2+8
934                                            return (0x20 << 25) | ((rs2 + 8) << 20) | ((rs1 + 8) << 15) | ((rs1 + 8) << 7) | 0x3b;
935                                        },
936                                        1 => {
937                                            // C.ADDW
938                                            // addw r1+8, r1+8, r2+8
939                                            return ((rs2 + 8) << 20) | ((rs1 + 8) << 15) | ((rs1 + 8) << 7) | 0x3b;
940                                        },
941                                        2 => {
942                                            // Reserved
943                                        },
944                                        3 => {
945                                            // Reserved
946                                        },
947                                        _ => {} // Not happens
948                                    },
949                                    _ => {} // No happens
950                                };
951                            },
952                            _ => {} // not happens
953                        };
954                    },
955                    5 => {
956                        // C.J
957                        // jal x0, imm
958                        let offset =
959                            match halfword & 0x1000 {
960                                0x1000 => 0xfffff000,
961                                _ => 0
962                            } | // offset[31:12] <= [12]
963                                ((halfword >> 1) & 0x800) | // offset[11] <= [12]
964                                ((halfword >> 7) & 0x10) | // offset[4] <= [11]
965                                ((halfword >> 1) & 0x300) | // offset[9:8] <= [10:9]
966                                ((halfword << 2) & 0x400) | // offset[10] <= [8]
967                                ((halfword >> 1) & 0x40) | // offset[6] <= [7]
968                                ((halfword << 1) & 0x80) | // offset[7] <= [6]
969                                ((halfword >> 2) & 0xe) | // offset[3:1] <= [5:3]
970                                ((halfword << 3) & 0x20); // offset[5] <= [2]
971                        let imm =
972                            ((offset >> 1) & 0x80000) | // imm[19] <= offset[20]
973                                ((offset << 8) & 0x7fe00) | // imm[18:9] <= offset[10:1]
974                                ((offset >> 3) & 0x100) | // imm[8] <= offset[11]
975                                ((offset >> 12) & 0xff); // imm[7:0] <= offset[19:12]
976                        return (imm << 12) | 0x6f;
977                    },
978                    6 => {
979                        // C.BEQZ
980                        // beq r+8, x0, offset
981                        let r = (halfword >> 7) & 0x7;
982                        let offset =
983                            match halfword & 0x1000 {
984                                0x1000 => 0xfffffe00,
985                                _ => 0
986                            } | // offset[31:9] <= [12]
987                                ((halfword >> 4) & 0x100) | // offset[8] <= [12]
988                                ((halfword >> 7) & 0x18) | // offset[4:3] <= [11:10]
989                                ((halfword << 1) & 0xc0) | // offset[7:6] <= [6:5]
990                                ((halfword >> 2) & 0x6) | // offset[2:1] <= [4:3]
991                                ((halfword << 3) & 0x20); // offset[5] <= [2]
992                        let imm2 =
993                            ((offset >> 6) & 0x40) | // imm2[6] <= [12]
994                                ((offset >> 5) & 0x3f); // imm2[5:0] <= [10:5]
995                        let imm1 =
996                            (offset & 0x1e) | // imm1[4:1] <= [4:1]
997                                ((offset >> 11) & 0x1); // imm1[0] <= [11]
998                        return (imm2 << 25) | ((r + 8) << 20) | (imm1 << 7) | 0x63;
999                    },
1000                    7 => {
1001                        // C.BNEZ
1002                        // bne r+8, x0, offset
1003                        let r = (halfword >> 7) & 0x7;
1004                        let offset =
1005                            match halfword & 0x1000 {
1006                                0x1000 => 0xfffffe00,
1007                                _ => 0
1008                            } | // offset[31:9] <= [12]
1009                                ((halfword >> 4) & 0x100) | // offset[8] <= [12]
1010                                ((halfword >> 7) & 0x18) | // offset[4:3] <= [11:10]
1011                                ((halfword << 1) & 0xc0) | // offset[7:6] <= [6:5]
1012                                ((halfword >> 2) & 0x6) | // offset[2:1] <= [4:3]
1013                                ((halfword << 3) & 0x20); // offset[5] <= [2]
1014                        let imm2 =
1015                            ((offset >> 6) & 0x40) | // imm2[6] <= [12]
1016                                ((offset >> 5) & 0x3f); // imm2[5:0] <= [10:5]
1017                        let imm1 =
1018                            (offset & 0x1e) | // imm1[4:1] <= [4:1]
1019                                ((offset >> 11) & 0x1); // imm1[0] <= [11]
1020                        return (imm2 << 25) | ((r + 8) << 20) | (1 << 12) | (imm1 << 7) | 0x63;
1021                    },
1022                    _ => {} // No happens
1023                };
1024            },
1025            2 => {
1026                match funct3 {
1027                    0 => {
1028                        // C.SLLI
1029                        // slli r, r, shamt
1030                        let r = (halfword >> 7) & 0x1f;
1031                        let shamt =
1032                            ((halfword >> 7) & 0x20) | // imm[5] <= [12]
1033                                ((halfword >> 2) & 0x1f); // imm[4:0] <= [6:2]
1034                        //if r != 0 {
1035                            return (shamt << 20) | (r << 15) | (1 << 12) | (r << 7) | 0x13;
1036                        //}
1037                        // r == 0 is reserved instruction?
1038                    },
1039                    1 => {
1040                        // C.FLDSP
1041                        // fld rd, offset(x2)
1042                        let rd = (halfword >> 7) & 0x1f;
1043                        let offset =
1044                            ((halfword >> 7) & 0x20) | // offset[5] <= [12]
1045                                ((halfword >> 2) & 0x18) | // offset[4:3] <= [6:5]
1046                                ((halfword << 4) & 0x1c0); // offset[8:6] <= [4:2]
1047                        //if rd != 0 {
1048                        return (offset << 20) | (2 << 15) | (3 << 12) | (rd << 7) | 0x7;
1049                        //}
1050                        // rd == 0 is reseved instruction
1051                    },
1052                    2 => {
1053                        // C.LWSP
1054                        // lw r, offset(x2)
1055                        let r = (halfword >> 7) & 0x1f;
1056                        let offset =
1057                            ((halfword >> 7) & 0x20) | // offset[5] <= [12]
1058                                ((halfword >> 2) & 0x1c) | // offset[4:2] <= [6:4]
1059                                ((halfword << 4) & 0xc0); // offset[7:6] <= [3:2]
1060                        //if r != 0 {
1061                            return (offset << 20) | (2 << 15) | (2 << 12) | (r << 7) | 0x3;
1062                        //}
1063                        // r == 0 is reseved instruction
1064                    },
1065                    3 => {
1066                        // @TODO: Support C.FLWSP in 32-bit mode
1067                        // C.LDSP
1068                        // ld rd, offset(x2)
1069                        let rd = (halfword >> 7) & 0x1f;
1070                        let offset =
1071                            ((halfword >> 7) & 0x20) | // offset[5] <= [12]
1072                                ((halfword >> 2) & 0x18) | // offset[4:3] <= [6:5]
1073                                ((halfword << 4) & 0x1c0); // offset[8:6] <= [4:2]
1074                        //if rd != 0 {
1075                            return (offset << 20) | (2 << 15) | (3 << 12) | (rd << 7) | 0x3;
1076                        //}
1077                        // rd == 0 is reseved instruction
1078                    },
1079                    4 => {
1080                        let funct1 = (halfword >> 12) & 1; // [12]
1081                        let rs1 = (halfword >> 7) & 0x1f; // [11:7]
1082                        let rs2 = (halfword >> 2) & 0x1f; // [6:2]
1083                        match funct1 {
1084                            0 => {
1085                                if rs1 != 0 && rs2 == 0 {
1086                                    // C.JR
1087                                    // jalr x0, 0(rs1)
1088                                    return (rs1 << 15) | 0x67;
1089                                }
1090                                // rs1 == 0 is reserved instruction
1091                                if rs1 != 0 && rs2 != 0 {
1092                                    // C.MV
1093                                    // add rs1, x0, rs2
1094                                    // println!("C.MV RS1:{:x} RS2:{:x}", rs1, rs2);
1095                                    return (rs2 << 20) | (rs1 << 7) | 0x33;
1096                                }
1097                                // rs1 == 0 && rs2 != 0 is Hints
1098                                // @TODO: Support Hints
1099                            },
1100                            1 => {
1101                                if rs1 == 0 && rs2 == 0 {
1102                                    // C.EBREAK
1103                                    // ebreak
1104                                    return 0x00100073;
1105                                }
1106                                if rs1 != 0 && rs2 == 0 {
1107                                    // C.JALR
1108                                    // jalr x1, 0(rs1)
1109                                    return (rs1 << 15) | (1 << 7) | 0x67;
1110                                }
1111                                if rs1 != 0 && rs2 != 0 {
1112                                    // C.ADD
1113                                    // add rs1, rs1, rs2
1114                                    return (rs2 << 20) | (rs1 << 15) | (rs1 << 7) | 0x33;
1115                                }
1116                                // rs1 == 0 && rs2 != 0 is Hists
1117                                // @TODO: Supports Hinsts
1118                            },
1119                            _ => {} // Not happens
1120                        };
1121                    },
1122                    5 => {
1123                        // @TODO: Implement
1124                        // C.FSDSP
1125                        // fsd rs2, offset(x2)
1126                        let rs2 = (halfword >> 2) & 0x1f; // [6:2]
1127                        let offset =
1128                            ((halfword >> 7) & 0x38) | // offset[5:3] <= [12:10]
1129                                ((halfword >> 1) & 0x1c0); // offset[8:6] <= [9:7]
1130                        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                        // C.SWSP
1136                        // sw rs2, offset(x2)
1137                        let rs2 = (halfword >> 2) & 0x1f; // [6:2]
1138                        let offset =
1139                            ((halfword >> 7) & 0x3c) | // offset[5:2] <= [12:9]
1140                                ((halfword >> 1) & 0xc0); // offset[7:6] <= [8:7]
1141                        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                        // @TODO: Support C.FSWSP in 32-bit mode
1147                        // C.SDSP
1148                        // sd rs, offset(x2)
1149                        let rs2 = (halfword >> 2) & 0x1f; // [6:2]
1150                        let offset =
1151                            ((halfword >> 7) & 0x38) | // offset[5:3] <= [12:10]
1152                                ((halfword >> 1) & 0x1c0); // offset[8:6] <= [9:7]
1153                        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                    _ => {} // Never happens
1158                };
1159            },
1160            _ => {} // Never happens
1161        };
1162        0xffffffff // Return invalid value
1163    }
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            // @TODO: Mask should consider of 32-bit mode
1189            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; // from qemu
1220            },
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        // println!("read_fflags: {:#x} nx={:?}", flags, inexact);
1275        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        // println!("write_fflags value = {:#x}", value);
1289
1290        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
1327// while this is a "machine" mode instruction it is needed for the official tests to pass
1328const 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 mpp = (status >> 11) & 0x3;
1336        let mprv = 0;
1337        // Override MIE[3] with MPIE[7], set MPIE[7] to 1, set MPP[12:11] to 0
1338        // and override MPRV[17]
1339        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]; // addi a0,a0,1
1353        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        // println!("opcode = {:?}", opcode);
1381
1382        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        //println!("opcode = {:#x?}", opcode);
1392
1393        match Cpu::decode(opcode) {
1394            Some(instruction) => assert_eq!(instruction.name, "SRAI"),
1395            _ => panic!("invalid instruction")
1396        }
1397    }
1398}