From e56e8a2e02c6454d4537c6062c18dd405af26fc3 Mon Sep 17 00:00:00 2001
From: Clo91eaf <Clo91eaf@qq.com>
Date: Thu, 14 Mar 2024 21:03:08 +0800
Subject: [PATCH] fmt.

---
 src/bus.rs                |   90 +-
 src/cpu.rs                | 6546 ++++++++++++++++++-------------------
 src/csr.rs                |  367 ++-
 src/devices/clint.rs      |  204 +-
 src/devices/mod.rs        |    4 +-
 src/devices/plic.rs       |  272 +-
 src/devices/uart.rs       |  168 +-
 src/devices/virtio_blk.rs |  770 +++--
 src/dram.rs               |  186 +-
 src/emulator.rs           |  258 +-
 src/exception.rs          |  400 ++-
 src/interrupt.rs          |  308 +-
 12 files changed, 4715 insertions(+), 4858 deletions(-)

diff --git a/src/bus.rs b/src/bus.rs
index 33ce2bf..4fc91ee 100644
--- a/src/bus.rs
+++ b/src/bus.rs
@@ -46,59 +46,59 @@ const DRAM_END: u64 = DRAM_BASE + DRAM_SIZE;
 
 /// The system bus.
 pub struct Bus {
-    pub clint: Clint,
-    pub plic: Plic,
-    pub uart: Uart,
-    pub virtio: Virtio,
-    dram: Dram,
-    pub rom: Rom,
+  pub clint: Clint,
+  pub plic: Plic,
+  pub uart: Uart,
+  pub virtio: Virtio,
+  dram: Dram,
+  pub rom: Rom,
 }
 
 impl Bus {
-    /// Create a new bus object.
-    pub fn new() -> Bus {
-        Self {
-            clint: Clint::new(),
-            plic: Plic::new(),
-            uart: Uart::new(),
-            virtio: Virtio::new(),
-            dram: Dram::new(),
-            rom: Rom::new(),
-        }
+  /// Create a new bus object.
+  pub fn new() -> Bus {
+    Self {
+      clint: Clint::new(),
+      plic: Plic::new(),
+      uart: Uart::new(),
+      virtio: Virtio::new(),
+      dram: Dram::new(),
+      rom: Rom::new(),
     }
+  }
 
-    /// Set the binary data to the memory.
-    pub fn initialize_dram(&mut self, data: Vec<u8>) {
-        self.dram.initialize(data);
-    }
+  /// Set the binary data to the memory.
+  pub fn initialize_dram(&mut self, data: Vec<u8>) {
+    self.dram.initialize(data);
+  }
 
-    /// Set the binary data to the virtIO disk.
-    pub fn initialize_disk(&mut self, data: Vec<u8>) {
-        self.virtio.initialize(data);
-    }
+  /// Set the binary data to the virtIO disk.
+  pub fn initialize_disk(&mut self, data: Vec<u8>) {
+    self.virtio.initialize(data);
+  }
 
-    /// Load a `size`-bit data from the device that connects to the system bus.
-    pub fn read(&mut self, addr: u64, size: u8) -> Result<u64, Exception> {
-        match addr {
-            MROM_BASE..=MROM_END => self.rom.read(addr, size),
-            CLINT_BASE..=CLINT_END => self.clint.read(addr, size),
-            PLIC_BASE..=PLIC_END => self.plic.read(addr, size),
-            UART_BASE..=UART_END => self.uart.read(addr, size),
-            VIRTIO_BASE..=VIRTIO_END => self.virtio.read(addr, size),
-            DRAM_BASE..=DRAM_END => self.dram.read(addr, size),
-            _ => Err(Exception::LoadAccessFault),
-        }
+  /// Load a `size`-bit data from the device that connects to the system bus.
+  pub fn read(&mut self, addr: u64, size: u8) -> Result<u64, Exception> {
+    match addr {
+      MROM_BASE..=MROM_END => self.rom.read(addr, size),
+      CLINT_BASE..=CLINT_END => self.clint.read(addr, size),
+      PLIC_BASE..=PLIC_END => self.plic.read(addr, size),
+      UART_BASE..=UART_END => self.uart.read(addr, size),
+      VIRTIO_BASE..=VIRTIO_END => self.virtio.read(addr, size),
+      DRAM_BASE..=DRAM_END => self.dram.read(addr, size),
+      _ => Err(Exception::LoadAccessFault),
     }
+  }
 
-    /// Store a `size`-bit data to the device that connects to the system bus.
-    pub fn write(&mut self, addr: u64, value: u64, size: u8) -> Result<(), Exception> {
-        match addr {
-            CLINT_BASE..=CLINT_END => self.clint.write(addr, value, size),
-            PLIC_BASE..=PLIC_END => self.plic.write(addr, value, size),
-            UART_BASE..=UART_END => self.uart.write(addr, value as u8, size),
-            VIRTIO_BASE..=VIRTIO_END => self.virtio.write(addr, value as u32, size),
-            DRAM_BASE..=DRAM_END => self.dram.write(addr, value, size),
-            _ => Err(Exception::StoreAMOAccessFault),
-        }
+  /// Store a `size`-bit data to the device that connects to the system bus.
+  pub fn write(&mut self, addr: u64, value: u64, size: u8) -> Result<(), Exception> {
+    match addr {
+      CLINT_BASE..=CLINT_END => self.clint.write(addr, value, size),
+      PLIC_BASE..=PLIC_END => self.plic.write(addr, value, size),
+      UART_BASE..=UART_END => self.uart.write(addr, value as u8, size),
+      VIRTIO_BASE..=VIRTIO_END => self.virtio.write(addr, value as u32, size),
+      DRAM_BASE..=DRAM_END => self.dram.write(addr, value, size),
+      _ => Err(Exception::StoreAMOAccessFault),
     }
+  }
 }
diff --git a/src/cpu.rs b/src/cpu.rs
index 759dc40..2eb1257 100644
--- a/src/cpu.rs
+++ b/src/cpu.rs
@@ -7,15 +7,15 @@ use std::fmt;
 use std::num::FpCategory;
 
 use crate::{
-    bus::{Bus, DRAM_BASE},
-    csr::*,
-    devices::{
-        uart::UART_IRQ,
-        virtio_blk::{Virtio, VIRTIO_IRQ},
-    },
-    dram::DRAM_SIZE,
-    exception::Exception,
-    interrupt::Interrupt,
+  bus::{Bus, DRAM_BASE},
+  csr::*,
+  devices::{
+    uart::UART_IRQ,
+    virtio_blk::{Virtio, VIRTIO_IRQ},
+  },
+  dram::DRAM_SIZE,
+  exception::Exception,
+  interrupt::Interrupt,
 };
 
 /// The number of registers.
@@ -37,151 +37,149 @@ pub const DOUBLEWORD: u8 = 64;
 pub const POINTER_TO_DTB: u64 = 0x1020;
 
 macro_rules! inst_count {
-    ($cpu:ident, $inst_name:expr) => {
-        if $cpu.is_count {
-            *$cpu.inst_counter.entry($inst_name.to_string()).or_insert(0) += 1;
-        }
-    };
+  ($cpu:ident, $inst_name:expr) => {
+    if $cpu.is_count {
+      *$cpu.inst_counter.entry($inst_name.to_string()).or_insert(0) += 1;
+    }
+  };
 }
 
 /// Access type that is used in the virtual address translation process. It decides which exception
 /// should raises (InstructionPageFault, LoadPageFault or StoreAMOPageFault).
 #[derive(Debug, PartialEq, PartialOrd)]
 pub enum AccessType {
-    /// Raises the exception InstructionPageFault. It is used for an instruction fetch.
-    Instruction,
-    /// Raises the exception LoadPageFault.
-    Load,
-    /// Raises the exception StoreAMOPageFault.
-    Store,
+  /// Raises the exception InstructionPageFault. It is used for an instruction fetch.
+  Instruction,
+  /// Raises the exception LoadPageFault.
+  Load,
+  /// Raises the exception StoreAMOPageFault.
+  Store,
 }
 
 /// The privileged mode.
 #[derive(Debug, PartialEq, PartialOrd, Eq, Copy, Clone)]
 pub enum Mode {
-    User = 0b00,
-    Supervisor = 0b01,
-    Machine = 0b11,
-    Debug,
+  User = 0b00,
+  Supervisor = 0b01,
+  Machine = 0b11,
+  Debug,
 }
 
 /// The integer registers.
 #[derive(Debug)]
 pub struct XRegisters {
-    xregs: [u64; REGISTERS_COUNT],
+  xregs: [u64; REGISTERS_COUNT],
 }
 
 impl XRegisters {
-    /// Create a new `XRegisters` object.
-    pub fn new() -> Self {
-        let mut xregs = [0; REGISTERS_COUNT];
-        // The stack pointer is set in the default maximum memory size + the start address of dram.
-        xregs[2] = DRAM_BASE + DRAM_SIZE;
-        // From riscv-pk:
-        // https://github.com/riscv/riscv-pk/blob/master/machine/mentry.S#L233-L235
-        //   save a0 and a1; arguments from previous boot loader stage:
-        //   // li x10, 0
-        //   // li x11, 0
-        //
-        // void init_first_hart(uintptr_t hartid, uintptr_t dtb)
-        //   x10 (a0): hartid
-        //   x11 (a1): pointer to dtb
-        //
-        // So, we need to set registers register to the state as they are when a bootloader finished.
-        xregs[10] = 0;
-        xregs[11] = POINTER_TO_DTB;
-        Self { xregs }
-    }
-
-    /// Read the value from a register.
-    pub fn read(&self, index: u64) -> u64 {
-        self.xregs[index as usize]
-    }
-
-    /// Write the value to a register.
-    pub fn write(&mut self, index: u64, value: u64) {
-        // Register x0 is hardwired with all bits equal to 0.
-        if index != 0 {
-            self.xregs[index as usize] = value;
-        }
+  /// Create a new `XRegisters` object.
+  pub fn new() -> Self {
+    let mut xregs = [0; REGISTERS_COUNT];
+    // The stack pointer is set in the default maximum memory size + the start address of dram.
+    xregs[2] = DRAM_BASE + DRAM_SIZE;
+    // From riscv-pk:
+    // https://github.com/riscv/riscv-pk/blob/master/machine/mentry.S#L233-L235
+    //   save a0 and a1; arguments from previous boot loader stage:
+    //   // li x10, 0
+    //   // li x11, 0
+    //
+    // void init_first_hart(uintptr_t hartid, uintptr_t dtb)
+    //   x10 (a0): hartid
+    //   x11 (a1): pointer to dtb
+    //
+    // So, we need to set registers register to the state as they are when a bootloader finished.
+    xregs[10] = 0;
+    xregs[11] = POINTER_TO_DTB;
+    Self { xregs }
+  }
+
+  /// Read the value from a register.
+  pub fn read(&self, index: u64) -> u64 {
+    self.xregs[index as usize]
+  }
+
+  /// Write the value to a register.
+  pub fn write(&mut self, index: u64, value: u64) {
+    // Register x0 is hardwired with all bits equal to 0.
+    if index != 0 {
+      self.xregs[index as usize] = value;
     }
+  }
 }
 
 impl fmt::Display for XRegisters {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let abi = [
-            "zero", " ra ", " sp ", " gp ", " tp ", " t0 ", " t1 ", " t2 ", " s0 ", " s1 ", " a0 ",
-            " a1 ", " a2 ", " a3 ", " a4 ", " a5 ", " a6 ", " a7 ", " s2 ", " s3 ", " s4 ", " s5 ",
-            " s6 ", " s7 ", " s8 ", " s9 ", " s10", " s11", " t3 ", " t4 ", " t5 ", " t6 ",
-        ];
-        let mut output = String::from("");
-        for i in (0..REGISTERS_COUNT).step_by(4) {
-            output = format!(
-                "{}\n{}",
-                output,
-                format!(
-                    "x{:02}({})={:>#18x} x{:02}({})={:>#18x} x{:02}({})={:>#18x} x{:02}({})={:>#18x}",
-                    i,
-                    abi[i],
-                    self.read(i as u64),
-                    i + 1,
-                    abi[i + 1],
-                    self.read(i as u64 + 1),
-                    i + 2,
-                    abi[i + 2],
-                    self.read(i as u64 + 2),
-                    i + 3,
-                    abi[i + 3],
-                    self.read(i as u64 + 3),
-                )
-            );
-        }
-        write!(f, "{}", output)
+  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+    let abi = [
+      "zero", " ra ", " sp ", " gp ", " tp ", " t0 ", " t1 ", " t2 ", " s0 ", " s1 ", " a0 ", " a1 ", " a2 ", " a3 ",
+      " a4 ", " a5 ", " a6 ", " a7 ", " s2 ", " s3 ", " s4 ", " s5 ", " s6 ", " s7 ", " s8 ", " s9 ", " s10", " s11",
+      " t3 ", " t4 ", " t5 ", " t6 ",
+    ];
+    let mut output = String::from("");
+    for i in (0..REGISTERS_COUNT).step_by(4) {
+      output = format!(
+        "{}\n{}",
+        output,
+        format!(
+          "x{:02}({})={:>#18x} x{:02}({})={:>#18x} x{:02}({})={:>#18x} x{:02}({})={:>#18x}",
+          i,
+          abi[i],
+          self.read(i as u64),
+          i + 1,
+          abi[i + 1],
+          self.read(i as u64 + 1),
+          i + 2,
+          abi[i + 2],
+          self.read(i as u64 + 2),
+          i + 3,
+          abi[i + 3],
+          self.read(i as u64 + 3),
+        )
+      );
     }
+    write!(f, "{}", output)
+  }
 }
 
 /// The floating-point registers.
 #[derive(Debug)]
 pub struct FRegisters {
-    fregs: [f64; REGISTERS_COUNT],
+  fregs: [f64; REGISTERS_COUNT],
 }
 
 impl FRegisters {
-    /// Create a new `FRegisters` object.
-    pub fn new() -> Self {
-        Self {
-            fregs: [0.0; REGISTERS_COUNT],
-        }
+  /// Create a new `FRegisters` object.
+  pub fn new() -> Self {
+    Self {
+      fregs: [0.0; REGISTERS_COUNT],
     }
+  }
 
-    /// Read the value from a register.
-    pub fn read(&self, index: u64) -> f64 {
-        self.fregs[index as usize]
-    }
+  /// Read the value from a register.
+  pub fn read(&self, index: u64) -> f64 {
+    self.fregs[index as usize]
+  }
 
-    /// Write the value to a register.
-    pub fn write(&mut self, index: u64, value: f64) {
-        self.fregs[index as usize] = value;
-    }
+  /// Write the value to a register.
+  pub fn write(&mut self, index: u64, value: f64) {
+    self.fregs[index as usize] = value;
+  }
 }
 
 impl fmt::Display for FRegisters {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let abi = [
-            // ft0-7: FP temporaries
-            " ft0", " ft1", " ft2", " ft3", " ft4", " ft5", " ft6", " ft7",
-            // fs0-1: FP saved registers
-            " fs0", " fs1", // fa0-1: FP arguments/return values
-            " fa0", " fa1", // fa2–7: FP arguments
-            " fa2", " fa3", " fa4", " fa5", " fa6", " fa7",
-            // fs2–11: FP saved registers
-            " fs2", " fs3", " fs4", " fs5", " fs6", " fs7", " fs8", " fs9", "fs10", "fs11",
-            // ft8–11: FP temporaries
-            " ft8", " ft9", "ft10", "ft11",
-        ];
-        let mut output = String::from("");
-        for i in (0..REGISTERS_COUNT).step_by(4) {
-            output = format!(
+  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+    let abi = [
+      // ft0-7: FP temporaries
+      " ft0", " ft1", " ft2", " ft3", " ft4", " ft5", " ft6", " ft7", // fs0-1: FP saved registers
+      " fs0", " fs1", // fa0-1: FP arguments/return values
+      " fa0", " fa1", // fa2–7: FP arguments
+      " fa2", " fa3", " fa4", " fa5", " fa6", " fa7", // fs2–11: FP saved registers
+      " fs2", " fs3", " fs4", " fs5", " fs6", " fs7", " fs8", " fs9", "fs10", "fs11",
+      // ft8–11: FP temporaries
+      " ft8", " ft9", "ft10", "ft11",
+    ];
+    let mut output = String::from("");
+    for i in (0..REGISTERS_COUNT).step_by(4) {
+      output = format!(
                 "{}\n{}",
                 output,
                 format!(
@@ -202,97 +200,84 @@ impl fmt::Display for FRegisters {
                     prec=8,
                 )
             );
-        }
-        // Remove the first new line.
-        output.remove(0);
-        write!(f, "{}", output)
     }
+    // Remove the first new line.
+    output.remove(0);
+    write!(f, "{}", output)
+  }
 }
 
 /// The CPU to contain registers, a program counter, status, and a privileged mode.
 pub struct Cpu {
-    /// 64-bit integer registers.
-    pub xregs: XRegisters,
-    /// 64-bit floating-point registers.
-    pub fregs: FRegisters,
-    /// Program counter.
-    pub pc: u64,
-    /// Control and status registers (CSR).
-    pub state: State,
-    /// Privilege level.
-    pub mode: Mode,
-    /// System bus.
-    pub bus: Bus,
-    /// SV39 paging flag.
-    enable_paging: bool,
-    /// Physical page number (PPN) × PAGE_SIZE (4096).
-    page_table: u64,
-    /// A set of bytes that subsumes the bytes in the addressed word used in
-    /// load-reserved/store-conditional instructions.
-    reservation_set: Vec<u64>,
-    /// Idle state. True when WFI is called, and becomes false when an interrupt happens.
-    pub idle: bool,
-    /// Counter of each instructions for debug.
-    pub inst_counter: BTreeMap<String, u64>,
-    /// The count flag. Count the number of each instruction executed.
-    pub is_count: bool,
-    /// Previous instruction. This is for debug.
-    pub pre_inst: u64,
+  /// 64-bit integer registers.
+  pub xregs: XRegisters,
+  /// 64-bit floating-point registers.
+  pub fregs: FRegisters,
+  /// Program counter.
+  pub pc: u64,
+  /// Control and status registers (CSR).
+  pub state: State,
+  /// Privilege level.
+  pub mode: Mode,
+  /// System bus.
+  pub bus: Bus,
+  /// SV39 paging flag.
+  enable_paging: bool,
+  /// Physical page number (PPN) × PAGE_SIZE (4096).
+  page_table: u64,
+  /// A set of bytes that subsumes the bytes in the addressed word used in
+  /// load-reserved/store-conditional instructions.
+  reservation_set: Vec<u64>,
+  /// Idle state. True when WFI is called, and becomes false when an interrupt happens.
+  pub idle: bool,
+  /// Counter of each instructions for debug.
+  pub inst_counter: BTreeMap<String, u64>,
+  /// The count flag. Count the number of each instruction executed.
+  pub is_count: bool,
+  /// Previous instruction. This is for debug.
+  pub pre_inst: u64,
 }
 
 impl Cpu {
-    /// Create a new `Cpu` object.
-    pub fn new() -> Cpu {
-        Cpu {
-            xregs: XRegisters::new(),
-            fregs: FRegisters::new(),
-            pc: 0,
-            state: State::new(),
-            mode: Mode::Machine,
-            bus: Bus::new(),
-            enable_paging: false,
-            page_table: 0,
-            reservation_set: Vec::new(),
-            idle: false,
-            inst_counter: BTreeMap::new(),
-            is_count: false,
-            pre_inst: 0,
-        }
+  /// Create a new `Cpu` object.
+  pub fn new() -> Cpu {
+    Cpu {
+      xregs: XRegisters::new(),
+      fregs: FRegisters::new(),
+      pc: 0,
+      state: State::new(),
+      mode: Mode::Machine,
+      bus: Bus::new(),
+      enable_paging: false,
+      page_table: 0,
+      reservation_set: Vec::new(),
+      idle: false,
+      inst_counter: BTreeMap::new(),
+      is_count: false,
+      pre_inst: 0,
     }
+  }
 
-    fn debug(&self, _inst: u64, _name: &str) {
-        /*
-        if (((0x20_0000_0000 & self.pc) >> 37) == 1) && (self.pc & 0xf0000000_00000000) == 0 {
-            println!(
-                "[user]    {} pc: {:#x}, inst: {:#x}, is_inst 16? {} x[0x1c] {:#x}",
-                name,
-                self.pc,
-                inst,
-                // Check if an instruction is one of the compressed instructions.
-                inst & 0b11 == 0 || inst & 0b11 == 1 || inst & 0b11 == 2,
-                self.xregs.read(0x1c),
-            );
-            return;
-        }
-
-        if (self.pc & 0xf0000000_00000000) != 0 {
-            return;
-            /*
-            println!(
-                "[kernel]  {} pc: {:#x}, inst: {:#x}, is_inst 16? {} x[0x1c] {:#x}",
-                name,
-                self.pc,
-                inst,
-                // Check if an instruction is one of the compressed instructions.
-                inst & 0b11 == 0 || inst & 0b11 == 1 || inst & 0b11 == 2,
-                self.xregs.read(0x1c),
-            );
-            return;
-            */
-        }
+  fn debug(&self, _inst: u64, _name: &str) {
+    /*
+    if (((0x20_0000_0000 & self.pc) >> 37) == 1) && (self.pc & 0xf0000000_00000000) == 0 {
+        println!(
+            "[user]    {} pc: {:#x}, inst: {:#x}, is_inst 16? {} x[0x1c] {:#x}",
+            name,
+            self.pc,
+            inst,
+            // Check if an instruction is one of the compressed instructions.
+            inst & 0b11 == 0 || inst & 0b11 == 1 || inst & 0b11 == 2,
+            self.xregs.read(0x1c),
+        );
+        return;
+    }
 
+    if (self.pc & 0xf0000000_00000000) != 0 {
+        return;
+        /*
         println!(
-            "[machine] {} pc: {:#x}, inst: {:#x}, is_inst 16? {} x[0x1c] {:#x}",
+            "[kernel]  {} pc: {:#x}, inst: {:#x}, is_inst 16? {} x[0x1c] {:#x}",
             name,
             self.pc,
             inst,
@@ -300,779 +285,760 @@ impl Cpu {
             inst & 0b11 == 0 || inst & 0b11 == 1 || inst & 0b11 == 2,
             self.xregs.read(0x1c),
         );
+        return;
         */
     }
 
-    /// Reset CPU states.
-    pub fn reset(&mut self) {
-        self.pc = 0;
-        self.mode = Mode::Machine;
-        self.state.reset();
-        for i in 0..REGISTERS_COUNT {
-            self.xregs.write(i as u64, 0);
-            self.fregs.write(i as u64, 0.0);
-        }
+    println!(
+        "[machine] {} pc: {:#x}, inst: {:#x}, is_inst 16? {} x[0x1c] {:#x}",
+        name,
+        self.pc,
+        inst,
+        // Check if an instruction is one of the compressed instructions.
+        inst & 0b11 == 0 || inst & 0b11 == 1 || inst & 0b11 == 2,
+        self.xregs.read(0x1c),
+    );
+    */
+  }
+
+  /// Reset CPU states.
+  pub fn reset(&mut self) {
+    self.pc = 0;
+    self.mode = Mode::Machine;
+    self.state.reset();
+    for i in 0..REGISTERS_COUNT {
+      self.xregs.write(i as u64, 0);
+      self.fregs.write(i as u64, 0.0);
     }
-
-    /// Check interrupt flags for all devices that can interrupt.
-    pub fn check_pending_interrupt(&mut self) -> Option<Interrupt> {
-        // global interrupt: PLIC (Platform Local Interrupt Controller) dispatches global
-        //                   interrupts to multiple harts.
-        // local interrupt: CLINT (Core Local Interrupter) dispatches local interrupts to a hart
-        //                  which directly connected to CLINT.
-
-        // 3.1.6.1 Privilege and Global Interrupt-Enable Stack in mstatus register
-        // "When a hart is executing in privilege mode x, interrupts are globally enabled when
-        // xIE=1 and globally disabled when xIE=0."
-        match self.mode {
-            Mode::Machine => {
-                // Check if the MIE bit is enabled.
-                if self.state.read_mstatus(MSTATUS_MIE) == 0 {
-                    return None;
-                }
-            }
-            Mode::Supervisor => {
-                // Check if the SIE bit is enabled.
-                if self.state.read_sstatus(XSTATUS_SIE) == 0 {
-                    return None;
-                }
-            }
-            _ => {}
+  }
+
+  /// Check interrupt flags for all devices that can interrupt.
+  pub fn check_pending_interrupt(&mut self) -> Option<Interrupt> {
+    // global interrupt: PLIC (Platform Local Interrupt Controller) dispatches global
+    //                   interrupts to multiple harts.
+    // local interrupt: CLINT (Core Local Interrupter) dispatches local interrupts to a hart
+    //                  which directly connected to CLINT.
+
+    // 3.1.6.1 Privilege and Global Interrupt-Enable Stack in mstatus register
+    // "When a hart is executing in privilege mode x, interrupts are globally enabled when
+    // xIE=1 and globally disabled when xIE=0."
+    match self.mode {
+      Mode::Machine => {
+        // Check if the MIE bit is enabled.
+        if self.state.read_mstatus(MSTATUS_MIE) == 0 {
+          return None;
         }
-
-        // TODO: Take interrupts based on priorities.
-
-        // Check external interrupt for uart and virtio.
-        let irq;
-        if self.bus.uart.is_interrupting() {
-            irq = UART_IRQ;
-        } else if self.bus.virtio.is_interrupting() {
-            // An interrupt is raised after a disk access is done.
-            Virtio::disk_access(self).expect("failed to access the disk");
-            irq = VIRTIO_IRQ;
-        } else {
-            irq = 0;
+      }
+      Mode::Supervisor => {
+        // Check if the SIE bit is enabled.
+        if self.state.read_sstatus(XSTATUS_SIE) == 0 {
+          return None;
         }
+      }
+      _ => {}
+    }
 
-        if irq != 0 {
-            // TODO: assume that hart is 0
-            // TODO: write a value to MCLAIM if the mode is machine
-            self.bus.plic.update_pending(irq);
-            self.state.write(MIP, self.state.read(MIP) | SEIP_BIT);
-        }
+    // TODO: Take interrupts based on priorities.
+
+    // Check external interrupt for uart and virtio.
+    let irq;
+    if self.bus.uart.is_interrupting() {
+      irq = UART_IRQ;
+    } else if self.bus.virtio.is_interrupting() {
+      // An interrupt is raised after a disk access is done.
+      Virtio::disk_access(self).expect("failed to access the disk");
+      irq = VIRTIO_IRQ;
+    } else {
+      irq = 0;
+    }
 
-        // 3.1.9 Machine Interrupt Registers (mip and mie)
-        // "An interrupt i will be taken if bit i is set in both mip and mie, and if interrupts are
-        // globally enabled. By default, M-mode interrupts are globally enabled if the hart’s
-        // current privilege mode is less than M, or if the current privilege mode is M and the MIE
-        // bit in the mstatus register is set. If bit i in mideleg is set, however, interrupts are
-        // considered to be globally enabled if the hart’s current privilege mode equals the
-        // delegated privilege mode (S or U) and that mode’s interrupt enable bit (SIE or UIE in
-        // mstatus) is set, or if the current privilege mode is less than the delegated privilege
-        // mode."
-        let pending = self.state.read(MIE) & self.state.read(MIP);
-
-        if (pending & MEIP_BIT) != 0 {
-            self.state.write(MIP, self.state.read(MIP) & !MEIP_BIT);
-            return Some(Interrupt::MachineExternalInterrupt);
-        }
-        if (pending & MSIP_BIT) != 0 {
-            self.state.write(MIP, self.state.read(MIP) & !MSIP_BIT);
-            return Some(Interrupt::MachineSoftwareInterrupt);
-        }
-        if (pending & MTIP_BIT) != 0 {
-            self.state.write(MIP, self.state.read(MIP) & !MTIP_BIT);
-            return Some(Interrupt::MachineTimerInterrupt);
-        }
-        if (pending & SEIP_BIT) != 0 {
-            self.state.write(MIP, self.state.read(MIP) & !SEIP_BIT);
-            return Some(Interrupt::SupervisorExternalInterrupt);
-        }
-        if (pending & SSIP_BIT) != 0 {
-            self.state.write(MIP, self.state.read(MIP) & !SSIP_BIT);
-            return Some(Interrupt::SupervisorSoftwareInterrupt);
-        }
-        if (pending & STIP_BIT) != 0 {
-            self.state.write(MIP, self.state.read(MIP) & !STIP_BIT);
-            return Some(Interrupt::SupervisorTimerInterrupt);
-        }
+    if irq != 0 {
+      // TODO: assume that hart is 0
+      // TODO: write a value to MCLAIM if the mode is machine
+      self.bus.plic.update_pending(irq);
+      self.state.write(MIP, self.state.read(MIP) | SEIP_BIT);
+    }
 
-        return None;
+    // 3.1.9 Machine Interrupt Registers (mip and mie)
+    // "An interrupt i will be taken if bit i is set in both mip and mie, and if interrupts are
+    // globally enabled. By default, M-mode interrupts are globally enabled if the hart’s
+    // current privilege mode is less than M, or if the current privilege mode is M and the MIE
+    // bit in the mstatus register is set. If bit i in mideleg is set, however, interrupts are
+    // considered to be globally enabled if the hart’s current privilege mode equals the
+    // delegated privilege mode (S or U) and that mode’s interrupt enable bit (SIE or UIE in
+    // mstatus) is set, or if the current privilege mode is less than the delegated privilege
+    // mode."
+    let pending = self.state.read(MIE) & self.state.read(MIP);
+
+    if (pending & MEIP_BIT) != 0 {
+      self.state.write(MIP, self.state.read(MIP) & !MEIP_BIT);
+      return Some(Interrupt::MachineExternalInterrupt);
+    }
+    if (pending & MSIP_BIT) != 0 {
+      self.state.write(MIP, self.state.read(MIP) & !MSIP_BIT);
+      return Some(Interrupt::MachineSoftwareInterrupt);
+    }
+    if (pending & MTIP_BIT) != 0 {
+      self.state.write(MIP, self.state.read(MIP) & !MTIP_BIT);
+      return Some(Interrupt::MachineTimerInterrupt);
+    }
+    if (pending & SEIP_BIT) != 0 {
+      self.state.write(MIP, self.state.read(MIP) & !SEIP_BIT);
+      return Some(Interrupt::SupervisorExternalInterrupt);
+    }
+    if (pending & SSIP_BIT) != 0 {
+      self.state.write(MIP, self.state.read(MIP) & !SSIP_BIT);
+      return Some(Interrupt::SupervisorSoftwareInterrupt);
+    }
+    if (pending & STIP_BIT) != 0 {
+      self.state.write(MIP, self.state.read(MIP) & !STIP_BIT);
+      return Some(Interrupt::SupervisorTimerInterrupt);
     }
 
-    /// Update the physical page number (PPN) and the addressing mode.
-    fn update_paging(&mut self) {
-        // Read the physical page number (PPN) of the root page table, i.e., its
-        // supervisor physical address divided by 4 KiB.
-        self.page_table = self.state.read_bits(SATP, ..44) * PAGE_SIZE;
+    return None;
+  }
 
-        // Read the MODE field, which selects the current address-translation scheme.
-        let mode = self.state.read_bits(SATP, 60..);
+  /// Update the physical page number (PPN) and the addressing mode.
+  fn update_paging(&mut self) {
+    // Read the physical page number (PPN) of the root page table, i.e., its
+    // supervisor physical address divided by 4 KiB.
+    self.page_table = self.state.read_bits(SATP, ..44) * PAGE_SIZE;
 
-        // Enable the SV39 paging if the value of the mode field is 8.
-        if mode == 8 {
-            self.enable_paging = true;
-        } else {
-            self.enable_paging = false;
-        }
-    }
+    // Read the MODE field, which selects the current address-translation scheme.
+    let mode = self.state.read_bits(SATP, 60..);
 
-    /// Translate a virtual address to a physical address for the paged virtual-memory system.
-    fn translate(&mut self, addr: u64, access_type: AccessType) -> Result<u64, Exception> {
-        if !self.enable_paging || self.mode == Mode::Machine {
-            return Ok(addr);
-        }
+    // Enable the SV39 paging if the value of the mode field is 8.
+    if mode == 8 {
+      self.enable_paging = true;
+    } else {
+      self.enable_paging = false;
+    }
+  }
 
-        // 4.3.2 Virtual Address Translation Process
-        // (The RISC-V Instruction Set Manual Volume II-Privileged Architecture_20190608)
-        // A virtual address va is translated into a physical address pa as follows:
-        let levels = 3;
-        let vpn = [
-            (addr >> 12) & 0x1ff,
-            (addr >> 21) & 0x1ff,
-            (addr >> 30) & 0x1ff,
-        ];
-
-        // 1. Let a be satp.ppn × PAGESIZE, and let i = LEVELS − 1. (For Sv32, PAGESIZE=212
-        //    and LEVELS=2.)
-        let mut a = self.page_table;
-        let mut i: i64 = levels - 1;
-        let mut pte;
-        loop {
-            // 2. Let pte be the value of the PTE at address a+va.vpn[i]×PTESIZE. (For Sv32,
-            //    PTESIZE=4.) If accessing pte violates a PMA or PMP check, raise an access
-            //    exception corresponding to the original access type.
-            pte = self.bus.read(a + vpn[i as usize] * 8, DOUBLEWORD)?;
-
-            // 3. If pte.v = 0, or if pte.r = 0 and pte.w = 1, stop and raise a page-fault
-            //    exception corresponding to the original access type.
-            let v = pte & 1;
-            let r = (pte >> 1) & 1;
-            let w = (pte >> 2) & 1;
-            let x = (pte >> 3) & 1;
-            if v == 0 || (r == 0 && w == 1) {
-                match access_type {
-                    AccessType::Instruction => return Err(Exception::InstructionPageFault(addr)),
-                    AccessType::Load => return Err(Exception::LoadPageFault(addr)),
-                    AccessType::Store => return Err(Exception::StoreAMOPageFault(addr)),
-                }
-            }
+  /// Translate a virtual address to a physical address for the paged virtual-memory system.
+  fn translate(&mut self, addr: u64, access_type: AccessType) -> Result<u64, Exception> {
+    if !self.enable_paging || self.mode == Mode::Machine {
+      return Ok(addr);
+    }
 
-            // 4. Otherwise, the PTE is valid. If pte.r = 1 or pte.x = 1, go to step 5.
-            //    Otherwise, this PTE is a pointer to the next level of the page table.
-            //    Let i = i − 1. If i < 0, stop and raise a page-fault exception
-            //    corresponding to the original access type. Otherwise,
-            //    let a = pte.ppn × PAGESIZE and go to step 2.
-            if r == 1 || x == 1 {
-                break;
-            }
-            i -= 1;
-            let ppn = (pte >> 10) & 0x0fff_ffff_ffff;
-            a = ppn * PAGE_SIZE;
-            if i < 0 {
-                match access_type {
-                    AccessType::Instruction => return Err(Exception::InstructionPageFault(addr)),
-                    AccessType::Load => return Err(Exception::LoadPageFault(addr)),
-                    AccessType::Store => return Err(Exception::StoreAMOPageFault(addr)),
-                }
-            }
+    // 4.3.2 Virtual Address Translation Process
+    // (The RISC-V Instruction Set Manual Volume II-Privileged Architecture_20190608)
+    // A virtual address va is translated into a physical address pa as follows:
+    let levels = 3;
+    let vpn = [(addr >> 12) & 0x1ff, (addr >> 21) & 0x1ff, (addr >> 30) & 0x1ff];
+
+    // 1. Let a be satp.ppn × PAGESIZE, and let i = LEVELS − 1. (For Sv32, PAGESIZE=212
+    //    and LEVELS=2.)
+    let mut a = self.page_table;
+    let mut i: i64 = levels - 1;
+    let mut pte;
+    loop {
+      // 2. Let pte be the value of the PTE at address a+va.vpn[i]×PTESIZE. (For Sv32,
+      //    PTESIZE=4.) If accessing pte violates a PMA or PMP check, raise an access
+      //    exception corresponding to the original access type.
+      pte = self.bus.read(a + vpn[i as usize] * 8, DOUBLEWORD)?;
+
+      // 3. If pte.v = 0, or if pte.r = 0 and pte.w = 1, stop and raise a page-fault
+      //    exception corresponding to the original access type.
+      let v = pte & 1;
+      let r = (pte >> 1) & 1;
+      let w = (pte >> 2) & 1;
+      let x = (pte >> 3) & 1;
+      if v == 0 || (r == 0 && w == 1) {
+        match access_type {
+          AccessType::Instruction => return Err(Exception::InstructionPageFault(addr)),
+          AccessType::Load => return Err(Exception::LoadPageFault(addr)),
+          AccessType::Store => return Err(Exception::StoreAMOPageFault(addr)),
         }
-        // TODO: implement step 5
-        // 5. A leaf PTE has been found. Determine if the requested memory access is
-        //    allowed by the pte.r, pte.w, pte.x, and pte.u bits, given the current
-        //    privilege mode and the value of the SUM and MXR fields of the mstatus
-        //    register. If not, stop and raise a page-fault exception corresponding
-        //    to the original access type.
-
-        // 3.1.6.3 Memory Privilege in mstatus Register
-        // "The MXR (Make eXecutable Readable) bit modifies the privilege with which loads access
-        // virtual memory. When MXR=0, only loads from pages marked readable (R=1 in Figure 4.15)
-        // will succeed. When MXR=1, loads from pages marked either readable or executable
-        // (R=1 or X=1) will succeed. MXR has no effect when page-based virtual memory is not in
-        // effect. MXR is hardwired to 0 if S-mode is not supported."
-
-        // "The SUM (permit Supervisor User Memory access) bit modifies the privilege with which
-        // S-mode loads and stores access virtual memory. When SUM=0, S-mode memory accesses to
-        // pages that are accessible by U-mode (U=1 in Figure 4.15) will fault. When SUM=1, these
-        // accesses are permitted.  SUM has no effect when page-based virtual memory is not in
-        // effect. Note that, while SUM is ordinarily ignored when not executing in S-mode, it is
-        // in effect when MPRV=1 and MPP=S. SUM is hardwired to 0 if S-mode is not supported."
-
-        // 6. If i > 0 and pte.ppn[i−1:0] != 0, this is a misaligned superpage; stop and
-        //    raise a page-fault exception corresponding to the original access type.
-        let ppn = [
-            (pte >> 10) & 0x1ff,
-            (pte >> 19) & 0x1ff,
-            (pte >> 28) & 0x03ff_ffff,
-        ];
-        if i > 0 {
-            for j in (0..i).rev() {
-                if ppn[j as usize] != 0 {
-                    // A misaligned superpage.
-                    match access_type {
-                        AccessType::Instruction => {
-                            return Err(Exception::InstructionPageFault(addr))
-                        }
-                        AccessType::Load => return Err(Exception::LoadPageFault(addr)),
-                        AccessType::Store => return Err(Exception::StoreAMOPageFault(addr)),
-                    }
-                }
-            }
+      }
+
+      // 4. Otherwise, the PTE is valid. If pte.r = 1 or pte.x = 1, go to step 5.
+      //    Otherwise, this PTE is a pointer to the next level of the page table.
+      //    Let i = i − 1. If i < 0, stop and raise a page-fault exception
+      //    corresponding to the original access type. Otherwise,
+      //    let a = pte.ppn × PAGESIZE and go to step 2.
+      if r == 1 || x == 1 {
+        break;
+      }
+      i -= 1;
+      let ppn = (pte >> 10) & 0x0fff_ffff_ffff;
+      a = ppn * PAGE_SIZE;
+      if i < 0 {
+        match access_type {
+          AccessType::Instruction => return Err(Exception::InstructionPageFault(addr)),
+          AccessType::Load => return Err(Exception::LoadPageFault(addr)),
+          AccessType::Store => return Err(Exception::StoreAMOPageFault(addr)),
         }
-
-        // 7. If pte.a = 0, or if the memory access is a store and pte.d = 0, either raise
-        //    a page-fault exception corresponding to the original access type, or:
-        //    • Set pte.a to 1 and, if the memory access is a store, also set pte.d to 1.
-        //    • If this access violates a PMA or PMP check, raise an access exception
-        //    corresponding to the original access type.
-        //    • This update and the loading of pte in step 2 must be atomic; in particular,
-        //    no intervening store to the PTE may be perceived to have occurred in-between.
-        let a = (pte >> 6) & 1;
-        let d = (pte >> 7) & 1;
-        if a == 0 || (access_type == AccessType::Store && d == 0) {
-            // Set pte.a to 1 and, if the memory access is a store, also set pte.d to 1.
-            pte = pte
-                | (1 << 6)
-                | if access_type == AccessType::Store {
-                    1 << 7
-                } else {
-                    0
-                };
-
-            // TODO: PMA or PMP check.
-
-            // Update the value of address satp.ppn × PAGESIZE + va.vpn[i] × PTESIZE with new pte
-            // value.
-            // TODO: If this is enabled, running xv6 fails.
-            //self.bus.write(self.page_table + vpn[i as usize] * 8, pte, 64)?;
+      }
+    }
+    // TODO: implement step 5
+    // 5. A leaf PTE has been found. Determine if the requested memory access is
+    //    allowed by the pte.r, pte.w, pte.x, and pte.u bits, given the current
+    //    privilege mode and the value of the SUM and MXR fields of the mstatus
+    //    register. If not, stop and raise a page-fault exception corresponding
+    //    to the original access type.
+
+    // 3.1.6.3 Memory Privilege in mstatus Register
+    // "The MXR (Make eXecutable Readable) bit modifies the privilege with which loads access
+    // virtual memory. When MXR=0, only loads from pages marked readable (R=1 in Figure 4.15)
+    // will succeed. When MXR=1, loads from pages marked either readable or executable
+    // (R=1 or X=1) will succeed. MXR has no effect when page-based virtual memory is not in
+    // effect. MXR is hardwired to 0 if S-mode is not supported."
+
+    // "The SUM (permit Supervisor User Memory access) bit modifies the privilege with which
+    // S-mode loads and stores access virtual memory. When SUM=0, S-mode memory accesses to
+    // pages that are accessible by U-mode (U=1 in Figure 4.15) will fault. When SUM=1, these
+    // accesses are permitted.  SUM has no effect when page-based virtual memory is not in
+    // effect. Note that, while SUM is ordinarily ignored when not executing in S-mode, it is
+    // in effect when MPRV=1 and MPP=S. SUM is hardwired to 0 if S-mode is not supported."
+
+    // 6. If i > 0 and pte.ppn[i−1:0] != 0, this is a misaligned superpage; stop and
+    //    raise a page-fault exception corresponding to the original access type.
+    let ppn = [(pte >> 10) & 0x1ff, (pte >> 19) & 0x1ff, (pte >> 28) & 0x03ff_ffff];
+    if i > 0 {
+      for j in (0..i).rev() {
+        if ppn[j as usize] != 0 {
+          // A misaligned superpage.
+          match access_type {
+            AccessType::Instruction => return Err(Exception::InstructionPageFault(addr)),
+            AccessType::Load => return Err(Exception::LoadPageFault(addr)),
+            AccessType::Store => return Err(Exception::StoreAMOPageFault(addr)),
+          }
         }
+      }
+    }
 
-        // 8. The translation is successful. The translated physical address is given as
-        //    follows:
-        //    • pa.pgoff = va.pgoff.
-        //    • If i > 0, then this is a superpage translation and pa.ppn[i−1:0] =
-        //    va.vpn[i−1:0].
-        //    • pa.ppn[LEVELS−1:i] = pte.ppn[LEVELS−1:i].
-        let offset = addr & 0xfff;
-        match i {
-            0 => {
-                let ppn = (pte >> 10) & 0x0fff_ffff_ffff;
-                Ok((ppn << 12) | offset)
-            }
-            1 => {
-                // Superpage translation. A superpage is a memory page of larger size than an
-                // ordinary page (4 KiB). It reduces TLB misses and improves performance.
-                Ok((ppn[2] << 30) | (ppn[1] << 21) | (vpn[0] << 12) | offset)
-            }
-            2 => {
-                // Superpage translation. A superpage is a memory page of larger size than an
-                // ordinary page (4 KiB). It reduces TLB misses and improves performance.
-                Ok((ppn[2] << 30) | (vpn[1] << 21) | (vpn[0] << 12) | offset)
-            }
-            _ => match access_type {
-                AccessType::Instruction => return Err(Exception::InstructionPageFault(addr)),
-                AccessType::Load => return Err(Exception::LoadPageFault(addr)),
-                AccessType::Store => return Err(Exception::StoreAMOPageFault(addr)),
-            },
-        }
+    // 7. If pte.a = 0, or if the memory access is a store and pte.d = 0, either raise
+    //    a page-fault exception corresponding to the original access type, or:
+    //    • Set pte.a to 1 and, if the memory access is a store, also set pte.d to 1.
+    //    • If this access violates a PMA or PMP check, raise an access exception
+    //    corresponding to the original access type.
+    //    • This update and the loading of pte in step 2 must be atomic; in particular,
+    //    no intervening store to the PTE may be perceived to have occurred in-between.
+    let a = (pte >> 6) & 1;
+    let d = (pte >> 7) & 1;
+    if a == 0 || (access_type == AccessType::Store && d == 0) {
+      // Set pte.a to 1 and, if the memory access is a store, also set pte.d to 1.
+      pte = pte | (1 << 6) | if access_type == AccessType::Store { 1 << 7 } else { 0 };
+
+      // TODO: PMA or PMP check.
+
+      // Update the value of address satp.ppn × PAGESIZE + va.vpn[i] × PTESIZE with new pte
+      // value.
+      // TODO: If this is enabled, running xv6 fails.
+      //self.bus.write(self.page_table + vpn[i as usize] * 8, pte, 64)?;
     }
 
-    /// Read `size`-bit data from the system bus with the translation a virtual address to a physical address
-    /// if it is enabled.
-    fn read(&mut self, v_addr: u64, size: u8) -> Result<u64, Exception> {
-        let previous_mode = self.mode;
-
-        // 3.1.6.3 Memory Privilege in mstatus Register
-        // "When MPRV=1, load and store memory addresses are translated and protected, and
-        // endianness is applied, as though the current privilege mode were set to MPP."
-        if self.state.read_mstatus(MSTATUS_MPRV) == 1 {
-            self.mode = match self.state.read_mstatus(MSTATUS_MPP) {
-                0b00 => Mode::User,
-                0b01 => Mode::Supervisor,
-                0b11 => Mode::Machine,
-                _ => Mode::Debug,
-            };
-        }
+    // 8. The translation is successful. The translated physical address is given as
+    //    follows:
+    //    • pa.pgoff = va.pgoff.
+    //    • If i > 0, then this is a superpage translation and pa.ppn[i−1:0] =
+    //    va.vpn[i−1:0].
+    //    • pa.ppn[LEVELS−1:i] = pte.ppn[LEVELS−1:i].
+    let offset = addr & 0xfff;
+    match i {
+      0 => {
+        let ppn = (pte >> 10) & 0x0fff_ffff_ffff;
+        Ok((ppn << 12) | offset)
+      }
+      1 => {
+        // Superpage translation. A superpage is a memory page of larger size than an
+        // ordinary page (4 KiB). It reduces TLB misses and improves performance.
+        Ok((ppn[2] << 30) | (ppn[1] << 21) | (vpn[0] << 12) | offset)
+      }
+      2 => {
+        // Superpage translation. A superpage is a memory page of larger size than an
+        // ordinary page (4 KiB). It reduces TLB misses and improves performance.
+        Ok((ppn[2] << 30) | (vpn[1] << 21) | (vpn[0] << 12) | offset)
+      }
+      _ => match access_type {
+        AccessType::Instruction => return Err(Exception::InstructionPageFault(addr)),
+        AccessType::Load => return Err(Exception::LoadPageFault(addr)),
+        AccessType::Store => return Err(Exception::StoreAMOPageFault(addr)),
+      },
+    }
+  }
+
+  /// Read `size`-bit data from the system bus with the translation a virtual address to a physical address
+  /// if it is enabled.
+  fn read(&mut self, v_addr: u64, size: u8) -> Result<u64, Exception> {
+    let previous_mode = self.mode;
+
+    // 3.1.6.3 Memory Privilege in mstatus Register
+    // "When MPRV=1, load and store memory addresses are translated and protected, and
+    // endianness is applied, as though the current privilege mode were set to MPP."
+    if self.state.read_mstatus(MSTATUS_MPRV) == 1 {
+      self.mode = match self.state.read_mstatus(MSTATUS_MPP) {
+        0b00 => Mode::User,
+        0b01 => Mode::Supervisor,
+        0b11 => Mode::Machine,
+        _ => Mode::Debug,
+      };
+    }
 
-        let p_addr = self.translate(v_addr, AccessType::Load)?;
-        let result = self.bus.read(p_addr, size);
+    let p_addr = self.translate(v_addr, AccessType::Load)?;
+    let result = self.bus.read(p_addr, size);
 
-        if self.state.read_mstatus(MSTATUS_MPRV) == 1 {
-            self.mode = previous_mode;
-        }
+    if self.state.read_mstatus(MSTATUS_MPRV) == 1 {
+      self.mode = previous_mode;
+    }
 
-        result
+    result
+  }
+
+  /// Write `size`-bit data to the system bus with the translation a virtual address to a physical
+  /// address if it is enabled.
+  fn write(&mut self, v_addr: u64, value: u64, size: u8) -> Result<(), Exception> {
+    let previous_mode = self.mode;
+
+    // 3.1.6.3 Memory Privilege in mstatus Register
+    // "When MPRV=1, load and store memory addresses are translated and protected, and
+    // endianness is applied, as though the current privilege mode were set to MPP."
+    if self.state.read_mstatus(MSTATUS_MPRV) == 1 {
+      self.mode = match self.state.read_mstatus(MSTATUS_MPP) {
+        0b00 => Mode::User,
+        0b01 => Mode::Supervisor,
+        0b11 => Mode::Machine,
+        _ => Mode::Debug,
+      };
     }
 
-    /// Write `size`-bit data to the system bus with the translation a virtual address to a physical
-    /// address if it is enabled.
-    fn write(&mut self, v_addr: u64, value: u64, size: u8) -> Result<(), Exception> {
-        let previous_mode = self.mode;
-
-        // 3.1.6.3 Memory Privilege in mstatus Register
-        // "When MPRV=1, load and store memory addresses are translated and protected, and
-        // endianness is applied, as though the current privilege mode were set to MPP."
-        if self.state.read_mstatus(MSTATUS_MPRV) == 1 {
-            self.mode = match self.state.read_mstatus(MSTATUS_MPP) {
-                0b00 => Mode::User,
-                0b01 => Mode::Supervisor,
-                0b11 => Mode::Machine,
-                _ => Mode::Debug,
-            };
-        }
+    // "The SC must fail if a write from some other device to the bytes accessed by the LR can
+    // be observed to occur between the LR and SC."
+    if self.reservation_set.contains(&v_addr) {
+      self.reservation_set.retain(|&x| x != v_addr);
+    }
 
-        // "The SC must fail if a write from some other device to the bytes accessed by the LR can
-        // be observed to occur between the LR and SC."
-        if self.reservation_set.contains(&v_addr) {
-            self.reservation_set.retain(|&x| x != v_addr);
-        }
+    let p_addr = self.translate(v_addr, AccessType::Store)?;
+    let result = self.bus.write(p_addr, value, size);
 
-        let p_addr = self.translate(v_addr, AccessType::Store)?;
-        let result = self.bus.write(p_addr, value, size);
+    if self.state.read_mstatus(MSTATUS_MPRV) == 1 {
+      self.mode = previous_mode;
+    }
 
-        if self.state.read_mstatus(MSTATUS_MPRV) == 1 {
-            self.mode = previous_mode;
-        }
+    result
+  }
 
-        result
+  /// Fetch the `size`-bit next instruction from the memory at the current program counter.
+  pub fn fetch(&mut self, size: u8) -> Result<u64, Exception> {
+    if size != HALFWORD && size != WORD {
+      return Err(Exception::InstructionAccessFault);
     }
 
-    /// Fetch the `size`-bit next instruction from the memory at the current program counter.
-    pub fn fetch(&mut self, size: u8) -> Result<u64, Exception> {
-        if size != HALFWORD && size != WORD {
-            return Err(Exception::InstructionAccessFault);
-        }
-
-        let p_pc = self.translate(self.pc, AccessType::Instruction)?;
+    let p_pc = self.translate(self.pc, AccessType::Instruction)?;
 
-        // The result of the read method can be `Exception::LoadAccessFault`. In fetch(), an error
-        // should be `Exception::InstructionAccessFault`.
-        match self.bus.read(p_pc, size) {
-            Ok(value) => Ok(value),
-            Err(_) => Err(Exception::InstructionAccessFault),
-        }
+    // The result of the read method can be `Exception::LoadAccessFault`. In fetch(), an error
+    // should be `Exception::InstructionAccessFault`.
+    match self.bus.read(p_pc, size) {
+      Ok(value) => Ok(value),
+      Err(_) => Err(Exception::InstructionAccessFault),
     }
-
-    /// Execute a cycle on peripheral devices.
-    pub fn devices_increment(&mut self) {
-        // TODO: mtime in Clint and TIME in CSR should be the same value.
-        // Increment the timer register (mtimer) in Clint.
-        self.bus.clint.increment(&mut self.state);
-        // Increment the value in the TIME and CYCLE registers in CSR.
-        self.state.increment_time();
+  }
+
+  /// Execute a cycle on peripheral devices.
+  pub fn devices_increment(&mut self) {
+    // TODO: mtime in Clint and TIME in CSR should be the same value.
+    // Increment the timer register (mtimer) in Clint.
+    self.bus.clint.increment(&mut self.state);
+    // Increment the value in the TIME and CYCLE registers in CSR.
+    self.state.increment_time();
+  }
+
+  /// Execute an instruction. Raises an exception if something is wrong, otherwise, returns
+  /// the instruction executed in this cycle.
+  pub fn execute(&mut self) -> Result<u64, Exception> {
+    // WFI is called and pending interrupts don't exist.
+    if self.idle {
+      return Ok(0);
     }
 
-    /// Execute an instruction. Raises an exception if something is wrong, otherwise, returns
-    /// the instruction executed in this cycle.
-    pub fn execute(&mut self) -> Result<u64, Exception> {
-        // WFI is called and pending interrupts don't exist.
-        if self.idle {
-            return Ok(0);
+    // Fetch.
+    let inst16 = self.fetch(HALFWORD)?;
+    let inst;
+    match inst16 & 0b11 {
+      0 | 1 | 2 => {
+        if inst16 == 0 {
+          // Unimplemented instruction, since all bits are 0.
+          return Err(Exception::IllegalInstruction(inst16));
         }
-
-        // Fetch.
-        let inst16 = self.fetch(HALFWORD)?;
-        let inst;
-        match inst16 & 0b11 {
-            0 | 1 | 2 => {
-                if inst16 == 0 {
-                    // Unimplemented instruction, since all bits are 0.
-                    return Err(Exception::IllegalInstruction(inst16));
-                }
-                inst = inst16;
-                self.execute_compressed(inst)?;
-                // Add 2 bytes to the program counter.
-                self.pc += 2;
-            }
-            _ => {
-                inst = self.fetch(WORD)?;
-                self.execute_general(inst)?;
-                // Add 4 bytes to the program counter.
-                self.pc += 4;
-            }
-        }
-        self.pre_inst = inst;
-        Ok(inst)
+        inst = inst16;
+        self.execute_compressed(inst)?;
+        // Add 2 bytes to the program counter.
+        self.pc += 2;
+      }
+      _ => {
+        inst = self.fetch(WORD)?;
+        self.execute_general(inst)?;
+        // Add 4 bytes to the program counter.
+        self.pc += 4;
+      }
     }
-
-    /// Execute a compressed instruction. Raised an exception if something is wrong, otherwise,
-    /// returns a fetched instruction. It also increments the program counter by 2 bytes.
-    pub fn execute_compressed(&mut self, inst: u64) -> Result<(), Exception> {
-        // 2. Decode.
-        let opcode = inst & 0x3;
-        let funct3 = (inst >> 13) & 0x7;
-
-        // 3. Execute.
-        // Compressed instructions have 3-bit field for popular registers, which correspond to
-        // registers x8 to x15.
-        match opcode {
-            0 => {
-                // Quadrant 0.
-                match funct3 {
-                    0x0 => {
-                        // c.addi4spn
-                        // Expands to addi rd, x2, nzuimm, where rd=rd'+8.
-                        inst_count!(self, "c.addi4spn");
-                        self.debug(inst, "c.addi4spn");
-
-                        let rd = ((inst >> 2) & 0x7) + 8;
-                        // nzuimm[5:4|9:6|2|3] = inst[12:11|10:7|6|5]
-                        let nzuimm = ((inst >> 1) & 0x3c0) // znuimm[9:6]
+    self.pre_inst = inst;
+    Ok(inst)
+  }
+
+  /// Execute a compressed instruction. Raised an exception if something is wrong, otherwise,
+  /// returns a fetched instruction. It also increments the program counter by 2 bytes.
+  pub fn execute_compressed(&mut self, inst: u64) -> Result<(), Exception> {
+    // 2. Decode.
+    let opcode = inst & 0x3;
+    let funct3 = (inst >> 13) & 0x7;
+
+    // 3. Execute.
+    // Compressed instructions have 3-bit field for popular registers, which correspond to
+    // registers x8 to x15.
+    match opcode {
+      0 => {
+        // Quadrant 0.
+        match funct3 {
+          0x0 => {
+            // c.addi4spn
+            // Expands to addi rd, x2, nzuimm, where rd=rd'+8.
+            inst_count!(self, "c.addi4spn");
+            self.debug(inst, "c.addi4spn");
+
+            let rd = ((inst >> 2) & 0x7) + 8;
+            // nzuimm[5:4|9:6|2|3] = inst[12:11|10:7|6|5]
+            let nzuimm = ((inst >> 1) & 0x3c0) // znuimm[9:6]
                             | ((inst >> 7) & 0x30) // znuimm[5:4]
                             | ((inst >> 2) & 0x8) // znuimm[3]
                             | ((inst >> 4) & 0x4); // znuimm[2]
-                        if nzuimm == 0 {
-                            return Err(Exception::IllegalInstruction(inst));
-                        }
-                        self.xregs
-                            .write(rd, self.xregs.read(2).wrapping_add(nzuimm));
-                    }
-                    0x1 => {
-                        // c.fld
-                        // Expands to fld rd, offset(rs1), where rd=rd'+8 and rs1=rs1'+8.
-                        inst_count!(self, "c.fld");
-                        self.debug(inst, "c.fld");
-
-                        let rd = ((inst >> 2) & 0x7) + 8;
-                        let rs1 = ((inst >> 7) & 0x7) + 8;
-                        // offset[5:3|7:6] = isnt[12:10|6:5]
-                        let offset = ((inst << 1) & 0xc0) // imm[7:6]
+            if nzuimm == 0 {
+              return Err(Exception::IllegalInstruction(inst));
+            }
+            self.xregs.write(rd, self.xregs.read(2).wrapping_add(nzuimm));
+          }
+          0x1 => {
+            // c.fld
+            // Expands to fld rd, offset(rs1), where rd=rd'+8 and rs1=rs1'+8.
+            inst_count!(self, "c.fld");
+            self.debug(inst, "c.fld");
+
+            let rd = ((inst >> 2) & 0x7) + 8;
+            let rs1 = ((inst >> 7) & 0x7) + 8;
+            // offset[5:3|7:6] = isnt[12:10|6:5]
+            let offset = ((inst << 1) & 0xc0) // imm[7:6]
                             | ((inst >> 7) & 0x38); // imm[5:3]
-                        let val = f64::from_bits(
-                            self.read(self.xregs.read(rs1).wrapping_add(offset), DOUBLEWORD)?,
-                        );
-                        self.fregs.write(rd, val);
-                    }
-                    0x2 => {
-                        // c.lw
-                        // Expands to lw rd, offset(rs1), where rd=rd'+8 and rs1=rs1'+8.
-                        inst_count!(self, "c.lw");
-                        self.debug(inst, "c.lw");
-
-                        let rd = ((inst >> 2) & 0x7) + 8;
-                        let rs1 = ((inst >> 7) & 0x7) + 8;
-                        // offset[5:3|2|6] = isnt[12:10|6|5]
-                        let offset = ((inst << 1) & 0x40) // imm[6]
+            let val = f64::from_bits(self.read(self.xregs.read(rs1).wrapping_add(offset), DOUBLEWORD)?);
+            self.fregs.write(rd, val);
+          }
+          0x2 => {
+            // c.lw
+            // Expands to lw rd, offset(rs1), where rd=rd'+8 and rs1=rs1'+8.
+            inst_count!(self, "c.lw");
+            self.debug(inst, "c.lw");
+
+            let rd = ((inst >> 2) & 0x7) + 8;
+            let rs1 = ((inst >> 7) & 0x7) + 8;
+            // offset[5:3|2|6] = isnt[12:10|6|5]
+            let offset = ((inst << 1) & 0x40) // imm[6]
                             | ((inst >> 7) & 0x38) // imm[5:3]
                             | ((inst >> 4) & 0x4); // imm[2]
-                        let addr = self.xregs.read(rs1).wrapping_add(offset);
-                        let val = self.read(addr, WORD)?;
-                        self.xregs.write(rd, val as i32 as i64 as u64);
-                    }
-                    0x3 => {
-                        // c.ld
-                        // Expands to ld rd, offset(rs1), where rd=rd'+8 and rs1=rs1'+8.
-                        inst_count!(self, "c.ld");
-                        self.debug(inst, "c.ld");
-
-                        let rd = ((inst >> 2) & 0x7) + 8;
-                        let rs1 = ((inst >> 7) & 0x7) + 8;
-                        // offset[5:3|7:6] = isnt[12:10|6:5]
-                        let offset = ((inst << 1) & 0xc0) // imm[7:6]
+            let addr = self.xregs.read(rs1).wrapping_add(offset);
+            let val = self.read(addr, WORD)?;
+            self.xregs.write(rd, val as i32 as i64 as u64);
+          }
+          0x3 => {
+            // c.ld
+            // Expands to ld rd, offset(rs1), where rd=rd'+8 and rs1=rs1'+8.
+            inst_count!(self, "c.ld");
+            self.debug(inst, "c.ld");
+
+            let rd = ((inst >> 2) & 0x7) + 8;
+            let rs1 = ((inst >> 7) & 0x7) + 8;
+            // offset[5:3|7:6] = isnt[12:10|6:5]
+            let offset = ((inst << 1) & 0xc0) // imm[7:6]
                             | ((inst >> 7) & 0x38); // imm[5:3]
-                        let addr = self.xregs.read(rs1).wrapping_add(offset);
-                        let val = self.read(addr, DOUBLEWORD)?;
-                        self.xregs.write(rd, val);
-                    }
-                    0x4 => {
-                        // Reserved.
-                        panic!("reserved");
-                    }
-                    0x5 => {
-                        // c.fsd
-                        // Expands to fsd rs2, offset(rs1), where rs2=rs2'+8 and rs1=rs1'+8.
-                        inst_count!(self, "c.fsd");
-                        self.debug(inst, "c.fsd");
-
-                        let rs2 = ((inst >> 2) & 0x7) + 8;
-                        let rs1 = ((inst >> 7) & 0x7) + 8;
-                        // offset[5:3|7:6] = isnt[12:10|6:5]
-                        let offset = ((inst << 1) & 0xc0) // imm[7:6]
+            let addr = self.xregs.read(rs1).wrapping_add(offset);
+            let val = self.read(addr, DOUBLEWORD)?;
+            self.xregs.write(rd, val);
+          }
+          0x4 => {
+            // Reserved.
+            panic!("reserved");
+          }
+          0x5 => {
+            // c.fsd
+            // Expands to fsd rs2, offset(rs1), where rs2=rs2'+8 and rs1=rs1'+8.
+            inst_count!(self, "c.fsd");
+            self.debug(inst, "c.fsd");
+
+            let rs2 = ((inst >> 2) & 0x7) + 8;
+            let rs1 = ((inst >> 7) & 0x7) + 8;
+            // offset[5:3|7:6] = isnt[12:10|6:5]
+            let offset = ((inst << 1) & 0xc0) // imm[7:6]
                             | ((inst >> 7) & 0x38); // imm[5:3]
-                        let addr = self.xregs.read(rs1).wrapping_add(offset);
-                        self.write(addr, self.fregs.read(rs2).to_bits() as u64, DOUBLEWORD)?;
-                    }
-                    0x6 => {
-                        // c.sw
-                        // Expands to sw rs2, offset(rs1), where rs2=rs2'+8 and rs1=rs1'+8.
-                        inst_count!(self, "c.sw");
-                        self.debug(inst, "c.sw");
-
-                        let rs2 = ((inst >> 2) & 0x7) + 8;
-                        let rs1 = ((inst >> 7) & 0x7) + 8;
-                        // offset[5:3|2|6] = isnt[12:10|6|5]
-                        let offset = ((inst << 1) & 0x40) // imm[6]
+            let addr = self.xregs.read(rs1).wrapping_add(offset);
+            self.write(addr, self.fregs.read(rs2).to_bits() as u64, DOUBLEWORD)?;
+          }
+          0x6 => {
+            // c.sw
+            // Expands to sw rs2, offset(rs1), where rs2=rs2'+8 and rs1=rs1'+8.
+            inst_count!(self, "c.sw");
+            self.debug(inst, "c.sw");
+
+            let rs2 = ((inst >> 2) & 0x7) + 8;
+            let rs1 = ((inst >> 7) & 0x7) + 8;
+            // offset[5:3|2|6] = isnt[12:10|6|5]
+            let offset = ((inst << 1) & 0x40) // imm[6]
                             | ((inst >> 7) & 0x38) // imm[5:3]
                             | ((inst >> 4) & 0x4); // imm[2]
-                        let addr = self.xregs.read(rs1).wrapping_add(offset);
-                        self.write(addr, self.xregs.read(rs2), WORD)?;
-                    }
-                    0x7 => {
-                        // c.sd
-                        // Expands to sd rs2, offset(rs1), where rs2=rs2'+8 and rs1=rs1'+8.
-                        inst_count!(self, "c.sd");
-                        self.debug(inst, "c.sd");
-
-                        let rs2 = ((inst >> 2) & 0x7) + 8;
-                        let rs1 = ((inst >> 7) & 0x7) + 8;
-                        // offset[5:3|7:6] = isnt[12:10|6:5]
-                        let offset = ((inst << 1) & 0xc0) // imm[7:6]
+            let addr = self.xregs.read(rs1).wrapping_add(offset);
+            self.write(addr, self.xregs.read(rs2), WORD)?;
+          }
+          0x7 => {
+            // c.sd
+            // Expands to sd rs2, offset(rs1), where rs2=rs2'+8 and rs1=rs1'+8.
+            inst_count!(self, "c.sd");
+            self.debug(inst, "c.sd");
+
+            let rs2 = ((inst >> 2) & 0x7) + 8;
+            let rs1 = ((inst >> 7) & 0x7) + 8;
+            // offset[5:3|7:6] = isnt[12:10|6:5]
+            let offset = ((inst << 1) & 0xc0) // imm[7:6]
                             | ((inst >> 7) & 0x38); // imm[5:3]
-                        let addr = self.xregs.read(rs1).wrapping_add(offset);
-                        self.write(addr, self.xregs.read(rs2), DOUBLEWORD)?;
-                    }
-                    _ => {
-                        return Err(Exception::IllegalInstruction(inst));
-                    }
-                }
+            let addr = self.xregs.read(rs1).wrapping_add(offset);
+            self.write(addr, self.xregs.read(rs2), DOUBLEWORD)?;
+          }
+          _ => {
+            return Err(Exception::IllegalInstruction(inst));
+          }
+        }
+      }
+      1 => {
+        // Quadrant 1.
+        match funct3 {
+          0x0 => {
+            // c.addi
+            // Expands to addi rd, rd, nzimm.
+            inst_count!(self, "c.addi");
+            self.debug(inst, "c.addi");
+
+            let rd = (inst >> 7) & 0x1f;
+            // nzimm[5|4:0] = inst[12|6:2]
+            let mut nzimm = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f);
+            // Sign-extended.
+            nzimm = match (nzimm & 0x20) == 0 {
+              true => nzimm,
+              false => (0xc0 | nzimm) as i8 as i64 as u64,
+            };
+            if rd != 0 {
+              self.xregs.write(rd, self.xregs.read(rd).wrapping_add(nzimm));
             }
-            1 => {
-                // Quadrant 1.
-                match funct3 {
-                    0x0 => {
-                        // c.addi
-                        // Expands to addi rd, rd, nzimm.
-                        inst_count!(self, "c.addi");
-                        self.debug(inst, "c.addi");
-
-                        let rd = (inst >> 7) & 0x1f;
-                        // nzimm[5|4:0] = inst[12|6:2]
-                        let mut nzimm = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f);
-                        // Sign-extended.
-                        nzimm = match (nzimm & 0x20) == 0 {
-                            true => nzimm,
-                            false => (0xc0 | nzimm) as i8 as i64 as u64,
-                        };
-                        if rd != 0 {
-                            self.xregs
-                                .write(rd, self.xregs.read(rd).wrapping_add(nzimm));
-                        }
-                    }
-                    0x1 => {
-                        // c.addiw
-                        // Expands to addiw rd, rd, imm
-                        // "The immediate can be zero for C.ADDIW, where this corresponds to sext.w
-                        // rd"
-                        inst_count!(self, "c.addiw");
-                        self.debug(inst, "c.addiw");
-
-                        let rd = (inst >> 7) & 0x1f;
-                        // imm[5|4:0] = inst[12|6:2]
-                        let mut imm = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f);
-                        // Sign-extended.
-                        imm = match (imm & 0x20) == 0 {
-                            true => imm,
-                            false => (0xc0 | imm) as i8 as i64 as u64,
-                        };
-                        if rd != 0 {
-                            self.xregs.write(
-                                rd,
-                                self.xregs.read(rd).wrapping_add(imm) as i32 as i64 as u64,
-                            );
-                        }
-                    }
-                    0x2 => {
-                        // c.li
-                        // Expands to addi rd, x0, imm.
-                        inst_count!(self, "c.li");
-                        self.debug(inst, "c.li");
-
-                        let rd = (inst >> 7) & 0x1f;
-                        // imm[5|4:0] = inst[12|6:2]
-                        let mut imm = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f);
-                        // Sign-extended.
-                        imm = match (imm & 0x20) == 0 {
-                            true => imm,
-                            false => (0xc0 | imm) as i8 as i64 as u64,
-                        };
-                        if rd != 0 {
-                            self.xregs.write(rd, imm);
-                        }
-                    }
-                    0x3 => {
-                        let rd = (inst >> 7) & 0x1f;
-                        match rd {
-                            0 => {}
-                            2 => {
-                                // c.addi16sp
-                                // Expands to addi x2, x2, nzimm
-                                inst_count!(self, "c.addi16sp");
-                                self.debug(inst, "c.addi16sp");
-
-                                // nzimm[9|4|6|8:7|5] = inst[12|6|5|4:3|2]
-                                let mut nzimm = ((inst >> 3) & 0x200) // nzimm[9]
+          }
+          0x1 => {
+            // c.addiw
+            // Expands to addiw rd, rd, imm
+            // "The immediate can be zero for C.ADDIW, where this corresponds to sext.w
+            // rd"
+            inst_count!(self, "c.addiw");
+            self.debug(inst, "c.addiw");
+
+            let rd = (inst >> 7) & 0x1f;
+            // imm[5|4:0] = inst[12|6:2]
+            let mut imm = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f);
+            // Sign-extended.
+            imm = match (imm & 0x20) == 0 {
+              true => imm,
+              false => (0xc0 | imm) as i8 as i64 as u64,
+            };
+            if rd != 0 {
+              self
+                .xregs
+                .write(rd, self.xregs.read(rd).wrapping_add(imm) as i32 as i64 as u64);
+            }
+          }
+          0x2 => {
+            // c.li
+            // Expands to addi rd, x0, imm.
+            inst_count!(self, "c.li");
+            self.debug(inst, "c.li");
+
+            let rd = (inst >> 7) & 0x1f;
+            // imm[5|4:0] = inst[12|6:2]
+            let mut imm = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f);
+            // Sign-extended.
+            imm = match (imm & 0x20) == 0 {
+              true => imm,
+              false => (0xc0 | imm) as i8 as i64 as u64,
+            };
+            if rd != 0 {
+              self.xregs.write(rd, imm);
+            }
+          }
+          0x3 => {
+            let rd = (inst >> 7) & 0x1f;
+            match rd {
+              0 => {}
+              2 => {
+                // c.addi16sp
+                // Expands to addi x2, x2, nzimm
+                inst_count!(self, "c.addi16sp");
+                self.debug(inst, "c.addi16sp");
+
+                // nzimm[9|4|6|8:7|5] = inst[12|6|5|4:3|2]
+                let mut nzimm = ((inst >> 3) & 0x200) // nzimm[9]
                                     | ((inst >> 2) & 0x10) // nzimm[4]
                                     | ((inst << 1) & 0x40) // nzimm[6]
                                     | ((inst << 4) & 0x180) // nzimm[8:7]
                                     | ((inst << 3) & 0x20); // nzimm[5]
-                                nzimm = match (nzimm & 0x200) == 0 {
-                                    true => nzimm,
-                                    // Sign-extended.
-                                    false => (0xfc00 | nzimm) as i16 as i32 as i64 as u64,
-                                };
-                                if nzimm != 0 {
-                                    self.xregs.write(2, self.xregs.read(2).wrapping_add(nzimm));
-                                }
-                            }
-                            _ => {
-                                // c.lui
-                                // Expands to lui rd, nzimm.
-                                inst_count!(self, "c.lui");
-                                self.debug(inst, "c.lui");
-
-                                // nzimm[17|16:12] = inst[12|6:2]
-                                let mut nzimm = ((inst << 5) & 0x20000) | ((inst << 10) & 0x1f000);
-                                // Sign-extended.
-                                nzimm = match (nzimm & 0x20000) == 0 {
-                                    true => nzimm,
-                                    false => (0xfffc0000 | nzimm) as i32 as i64 as u64,
-                                };
-                                if nzimm != 0 {
-                                    self.xregs.write(rd, nzimm);
-                                }
-                            }
-                        }
-                    }
-                    0x4 => {
-                        let funct2 = (inst >> 10) & 0x3;
-                        match funct2 {
-                            0x0 => {
-                                // c.srli
-                                // Expands to srli rd, rd, shamt, where rd=rd'+8.
-                                inst_count!(self, "c.srli");
-                                self.debug(inst, "c.srli");
-
-                                let rd = ((inst >> 7) & 0b111) + 8;
-                                // shamt[5|4:0] = inst[12|6:2]
-                                let shamt = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f);
-                                self.xregs.write(rd, self.xregs.read(rd) >> shamt);
-                            }
-                            0x1 => {
-                                // c.srai
-                                // Expands to srai rd, rd, shamt, where rd=rd'+8.
-                                inst_count!(self, "c.srai");
-                                self.debug(inst, "c.srai");
-
-                                let rd = ((inst >> 7) & 0b111) + 8;
-                                // shamt[5|4:0] = inst[12|6:2]
-                                let shamt = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f);
-                                self.xregs
-                                    .write(rd, ((self.xregs.read(rd) as i64) >> shamt) as u64);
-                            }
-                            0x2 => {
-                                // c.andi
-                                // Expands to andi rd, rd, imm, where rd=rd'+8.
-                                inst_count!(self, "c.andi");
-                                self.debug(inst, "c.andi");
-
-                                let rd = ((inst >> 7) & 0b111) + 8;
-                                // imm[5|4:0] = inst[12|6:2]
-                                let mut imm = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f);
-                                // Sign-extended.
-                                imm = match (imm & 0x20) == 0 {
-                                    true => imm,
-                                    false => (0xc0 | imm) as i8 as i64 as u64,
-                                };
-                                self.xregs.write(rd, self.xregs.read(rd) & imm);
-                            }
-                            0x3 => {
-                                match ((inst >> 12) & 0b1, (inst >> 5) & 0b11) {
-                                    (0x0, 0x0) => {
-                                        // c.sub
-                                        // Expands to sub rd, rd, rs2, rd=rd'+8 and rs2=rs2'+8.
-                                        inst_count!(self, "c.sub");
-                                        self.debug(inst, "c.sub");
-
-                                        let rd = ((inst >> 7) & 0b111) + 8;
-                                        let rs2 = ((inst >> 2) & 0b111) + 8;
-                                        self.xregs.write(
-                                            rd,
-                                            self.xregs.read(rd).wrapping_sub(self.xregs.read(rs2)),
-                                        );
-                                    }
-                                    (0x0, 0x1) => {
-                                        // c.xor
-                                        // Expands to xor rd, rd, rs2, rd=rd'+8 and rs2=rs2'+8.
-                                        inst_count!(self, "c.xor");
-                                        self.debug(inst, "c.xor");
-
-                                        let rd = ((inst >> 7) & 0b111) + 8;
-                                        let rs2 = ((inst >> 2) & 0b111) + 8;
-                                        self.xregs
-                                            .write(rd, self.xregs.read(rd) ^ self.xregs.read(rs2));
-                                    }
-                                    (0x0, 0x2) => {
-                                        // c.or
-                                        // Expands to or rd, rd, rs2, rd=rd'+8 and rs2=rs2'+8.
-                                        inst_count!(self, "c.or");
-                                        self.debug(inst, "c.or");
-
-                                        let rd = ((inst >> 7) & 0b111) + 8;
-                                        let rs2 = ((inst >> 2) & 0b111) + 8;
-                                        self.xregs
-                                            .write(rd, self.xregs.read(rd) | self.xregs.read(rs2));
-                                    }
-                                    (0x0, 0x3) => {
-                                        // c.and
-                                        // Expands to and rd, rd, rs2, rd=rd'+8 and rs2=rs2'+8.
-                                        inst_count!(self, "c.and");
-                                        self.debug(inst, "c.and");
-
-                                        let rd = ((inst >> 7) & 0b111) + 8;
-                                        let rs2 = ((inst >> 2) & 0b111) + 8;
-                                        self.xregs
-                                            .write(rd, self.xregs.read(rd) & self.xregs.read(rs2));
-                                    }
-                                    (0x1, 0x0) => {
-                                        // c.subw
-                                        // Expands to subw rd, rd, rs2, rd=rd'+8 and rs2=rs2'+8.
-                                        inst_count!(self, "c.subw");
-                                        self.debug(inst, "c.subw");
-
-                                        let rd = ((inst >> 7) & 0b111) + 8;
-                                        let rs2 = ((inst >> 2) & 0b111) + 8;
-                                        self.xregs.write(
-                                            rd,
-                                            self.xregs.read(rd).wrapping_sub(self.xregs.read(rs2))
-                                                as i32
-                                                as i64
-                                                as u64,
-                                        );
-                                    }
-                                    (0x1, 0x1) => {
-                                        // c.addw
-                                        // Expands to addw rd, rd, rs2, rd=rd'+8 and rs2=rs2'+8.
-                                        inst_count!(self, "c.addw");
-                                        self.debug(inst, "c.andw");
-
-                                        let rd = ((inst >> 7) & 0b111) + 8;
-                                        let rs2 = ((inst >> 2) & 0b111) + 8;
-                                        self.xregs.write(
-                                            rd,
-                                            self.xregs.read(rd).wrapping_add(self.xregs.read(rs2))
-                                                as i32
-                                                as i64
-                                                as u64,
-                                        );
-                                    }
-                                    _ => {
-                                        return Err(Exception::IllegalInstruction(inst));
-                                    }
-                                }
-                            }
-                            _ => {
-                                return Err(Exception::IllegalInstruction(inst));
-                            }
-                        }
-                    }
-                    0x5 => {
-                        // c.j
-                        // Expands to jal x0, offset.
-                        inst_count!(self, "c.j");
-                        self.debug(inst, "c.j");
-
-                        // offset[11|4|9:8|10|6|7|3:1|5] = inst[12|11|10:9|8|7|6|5:3|2]
-                        let mut offset = ((inst >> 1) & 0x800) // offset[11]
+                nzimm = match (nzimm & 0x200) == 0 {
+                  true => nzimm,
+                  // Sign-extended.
+                  false => (0xfc00 | nzimm) as i16 as i32 as i64 as u64,
+                };
+                if nzimm != 0 {
+                  self.xregs.write(2, self.xregs.read(2).wrapping_add(nzimm));
+                }
+              }
+              _ => {
+                // c.lui
+                // Expands to lui rd, nzimm.
+                inst_count!(self, "c.lui");
+                self.debug(inst, "c.lui");
+
+                // nzimm[17|16:12] = inst[12|6:2]
+                let mut nzimm = ((inst << 5) & 0x20000) | ((inst << 10) & 0x1f000);
+                // Sign-extended.
+                nzimm = match (nzimm & 0x20000) == 0 {
+                  true => nzimm,
+                  false => (0xfffc0000 | nzimm) as i32 as i64 as u64,
+                };
+                if nzimm != 0 {
+                  self.xregs.write(rd, nzimm);
+                }
+              }
+            }
+          }
+          0x4 => {
+            let funct2 = (inst >> 10) & 0x3;
+            match funct2 {
+              0x0 => {
+                // c.srli
+                // Expands to srli rd, rd, shamt, where rd=rd'+8.
+                inst_count!(self, "c.srli");
+                self.debug(inst, "c.srli");
+
+                let rd = ((inst >> 7) & 0b111) + 8;
+                // shamt[5|4:0] = inst[12|6:2]
+                let shamt = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f);
+                self.xregs.write(rd, self.xregs.read(rd) >> shamt);
+              }
+              0x1 => {
+                // c.srai
+                // Expands to srai rd, rd, shamt, where rd=rd'+8.
+                inst_count!(self, "c.srai");
+                self.debug(inst, "c.srai");
+
+                let rd = ((inst >> 7) & 0b111) + 8;
+                // shamt[5|4:0] = inst[12|6:2]
+                let shamt = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f);
+                self.xregs.write(rd, ((self.xregs.read(rd) as i64) >> shamt) as u64);
+              }
+              0x2 => {
+                // c.andi
+                // Expands to andi rd, rd, imm, where rd=rd'+8.
+                inst_count!(self, "c.andi");
+                self.debug(inst, "c.andi");
+
+                let rd = ((inst >> 7) & 0b111) + 8;
+                // imm[5|4:0] = inst[12|6:2]
+                let mut imm = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f);
+                // Sign-extended.
+                imm = match (imm & 0x20) == 0 {
+                  true => imm,
+                  false => (0xc0 | imm) as i8 as i64 as u64,
+                };
+                self.xregs.write(rd, self.xregs.read(rd) & imm);
+              }
+              0x3 => {
+                match ((inst >> 12) & 0b1, (inst >> 5) & 0b11) {
+                  (0x0, 0x0) => {
+                    // c.sub
+                    // Expands to sub rd, rd, rs2, rd=rd'+8 and rs2=rs2'+8.
+                    inst_count!(self, "c.sub");
+                    self.debug(inst, "c.sub");
+
+                    let rd = ((inst >> 7) & 0b111) + 8;
+                    let rs2 = ((inst >> 2) & 0b111) + 8;
+                    self
+                      .xregs
+                      .write(rd, self.xregs.read(rd).wrapping_sub(self.xregs.read(rs2)));
+                  }
+                  (0x0, 0x1) => {
+                    // c.xor
+                    // Expands to xor rd, rd, rs2, rd=rd'+8 and rs2=rs2'+8.
+                    inst_count!(self, "c.xor");
+                    self.debug(inst, "c.xor");
+
+                    let rd = ((inst >> 7) & 0b111) + 8;
+                    let rs2 = ((inst >> 2) & 0b111) + 8;
+                    self.xregs.write(rd, self.xregs.read(rd) ^ self.xregs.read(rs2));
+                  }
+                  (0x0, 0x2) => {
+                    // c.or
+                    // Expands to or rd, rd, rs2, rd=rd'+8 and rs2=rs2'+8.
+                    inst_count!(self, "c.or");
+                    self.debug(inst, "c.or");
+
+                    let rd = ((inst >> 7) & 0b111) + 8;
+                    let rs2 = ((inst >> 2) & 0b111) + 8;
+                    self.xregs.write(rd, self.xregs.read(rd) | self.xregs.read(rs2));
+                  }
+                  (0x0, 0x3) => {
+                    // c.and
+                    // Expands to and rd, rd, rs2, rd=rd'+8 and rs2=rs2'+8.
+                    inst_count!(self, "c.and");
+                    self.debug(inst, "c.and");
+
+                    let rd = ((inst >> 7) & 0b111) + 8;
+                    let rs2 = ((inst >> 2) & 0b111) + 8;
+                    self.xregs.write(rd, self.xregs.read(rd) & self.xregs.read(rs2));
+                  }
+                  (0x1, 0x0) => {
+                    // c.subw
+                    // Expands to subw rd, rd, rs2, rd=rd'+8 and rs2=rs2'+8.
+                    inst_count!(self, "c.subw");
+                    self.debug(inst, "c.subw");
+
+                    let rd = ((inst >> 7) & 0b111) + 8;
+                    let rs2 = ((inst >> 2) & 0b111) + 8;
+                    self.xregs.write(
+                      rd,
+                      self.xregs.read(rd).wrapping_sub(self.xregs.read(rs2)) as i32 as i64 as u64,
+                    );
+                  }
+                  (0x1, 0x1) => {
+                    // c.addw
+                    // Expands to addw rd, rd, rs2, rd=rd'+8 and rs2=rs2'+8.
+                    inst_count!(self, "c.addw");
+                    self.debug(inst, "c.andw");
+
+                    let rd = ((inst >> 7) & 0b111) + 8;
+                    let rs2 = ((inst >> 2) & 0b111) + 8;
+                    self.xregs.write(
+                      rd,
+                      self.xregs.read(rd).wrapping_add(self.xregs.read(rs2)) as i32 as i64 as u64,
+                    );
+                  }
+                  _ => {
+                    return Err(Exception::IllegalInstruction(inst));
+                  }
+                }
+              }
+              _ => {
+                return Err(Exception::IllegalInstruction(inst));
+              }
+            }
+          }
+          0x5 => {
+            // c.j
+            // Expands to jal x0, offset.
+            inst_count!(self, "c.j");
+            self.debug(inst, "c.j");
+
+            // offset[11|4|9:8|10|6|7|3:1|5] = inst[12|11|10:9|8|7|6|5:3|2]
+            let mut offset = ((inst >> 1) & 0x800) // offset[11]
                             | ((inst << 2) & 0x400) // offset[10]
                             | ((inst >> 1) & 0x300) // offset[9:8]
                             | ((inst << 1) & 0x80) // offset[7]
@@ -1081,2491 +1047,2397 @@ impl Cpu {
                             | ((inst >> 7) & 0x10) // offset[4]
                             | ((inst >> 2) & 0xe); // offset[3:1]
 
-                        // Sign-extended.
-                        offset = match (offset & 0x800) == 0 {
-                            true => offset,
-                            false => (0xf000 | offset) as i16 as i64 as u64,
-                        };
-                        self.pc = self.pc.wrapping_add(offset).wrapping_sub(2);
-                    }
-                    0x6 => {
-                        // c.beqz
-                        // Expands to beq rs1, x0, offset, rs1=rs1'+8.
-                        inst_count!(self, "c.beqz");
-                        self.debug(inst, "c.beqz");
-
-                        let rs1 = ((inst >> 7) & 0b111) + 8;
-                        // offset[8|4:3|7:6|2:1|5] = inst[12|11:10|6:5|4:3|2]
-                        let mut offset = ((inst >> 4) & 0x100) // offset[8]
+            // Sign-extended.
+            offset = match (offset & 0x800) == 0 {
+              true => offset,
+              false => (0xf000 | offset) as i16 as i64 as u64,
+            };
+            self.pc = self.pc.wrapping_add(offset).wrapping_sub(2);
+          }
+          0x6 => {
+            // c.beqz
+            // Expands to beq rs1, x0, offset, rs1=rs1'+8.
+            inst_count!(self, "c.beqz");
+            self.debug(inst, "c.beqz");
+
+            let rs1 = ((inst >> 7) & 0b111) + 8;
+            // offset[8|4:3|7:6|2:1|5] = inst[12|11:10|6:5|4:3|2]
+            let mut offset = ((inst >> 4) & 0x100) // offset[8]
                             | ((inst << 1) & 0xc0) // offset[7:6]
                             | ((inst << 3) & 0x20) // offset[5]
                             | ((inst >> 7) & 0x18) // offset[4:3]
                             | ((inst >> 2) & 0x6); // offset[2:1]
                                                    // Sign-extended.
-                        offset = match (offset & 0x100) == 0 {
-                            true => offset,
-                            false => (0xfe00 | offset) as i16 as i64 as u64,
-                        };
-                        if self.xregs.read(rs1) == 0 {
-                            self.pc = self.pc.wrapping_add(offset).wrapping_sub(2);
-                        }
-                    }
-                    0x7 => {
-                        // c.bnez
-                        // Expands to bne rs1, x0, offset, rs1=rs1'+8.
-                        inst_count!(self, "c.bnez");
-                        self.debug(inst, "c.beez");
-
-                        let rs1 = ((inst >> 7) & 0b111) + 8;
-                        // offset[8|4:3|7:6|2:1|5] = inst[12|11:10|6:5|4:3|2]
-                        let mut offset = ((inst >> 4) & 0x100) // offset[8]
+            offset = match (offset & 0x100) == 0 {
+              true => offset,
+              false => (0xfe00 | offset) as i16 as i64 as u64,
+            };
+            if self.xregs.read(rs1) == 0 {
+              self.pc = self.pc.wrapping_add(offset).wrapping_sub(2);
+            }
+          }
+          0x7 => {
+            // c.bnez
+            // Expands to bne rs1, x0, offset, rs1=rs1'+8.
+            inst_count!(self, "c.bnez");
+            self.debug(inst, "c.beez");
+
+            let rs1 = ((inst >> 7) & 0b111) + 8;
+            // offset[8|4:3|7:6|2:1|5] = inst[12|11:10|6:5|4:3|2]
+            let mut offset = ((inst >> 4) & 0x100) // offset[8]
                             | ((inst << 1) & 0xc0) // offset[7:6]
                             | ((inst << 3) & 0x20) // offset[5]
                             | ((inst >> 7) & 0x18) // offset[4:3]
                             | ((inst >> 2) & 0x6); // offset[2:1]
                                                    // Sign-extended.
-                        offset = match (offset & 0x100) == 0 {
-                            true => offset,
-                            false => (0xfe00 | offset) as i16 as i64 as u64,
-                        };
-                        if self.xregs.read(rs1) != 0 {
-                            self.pc = self.pc.wrapping_add(offset).wrapping_sub(2);
-                        }
-                    }
-                    _ => {
-                        return Err(Exception::IllegalInstruction(inst));
-                    }
-                }
+            offset = match (offset & 0x100) == 0 {
+              true => offset,
+              false => (0xfe00 | offset) as i16 as i64 as u64,
+            };
+            if self.xregs.read(rs1) != 0 {
+              self.pc = self.pc.wrapping_add(offset).wrapping_sub(2);
             }
-            2 => {
-                // Quadrant 2.
-                match funct3 {
-                    0x0 => {
-                        // c.slli
-                        // Expands to slli rd, rd, shamt.
-                        inst_count!(self, "c.slli");
-                        self.debug(inst, "c.slli");
-
-                        let rd = (inst >> 7) & 0x1f;
-                        // shamt[5|4:0] = inst[12|6:2]
-                        let shamt = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f);
-                        if rd != 0 {
-                            self.xregs.write(rd, self.xregs.read(rd) << shamt);
-                        }
-                    }
-                    0x1 => {
-                        // c.fldsp
-                        // Expands to fld rd, offset(x2).
-                        inst_count!(self, "c.fldsp");
-                        self.debug(inst, "c.fldsp");
-
-                        let rd = (inst >> 7) & 0x1f;
-                        // offset[5|4:3|8:6] = inst[12|6:5|4:2]
-                        let offset = ((inst << 4) & 0x1c0) // offset[8:6]
+          }
+          _ => {
+            return Err(Exception::IllegalInstruction(inst));
+          }
+        }
+      }
+      2 => {
+        // Quadrant 2.
+        match funct3 {
+          0x0 => {
+            // c.slli
+            // Expands to slli rd, rd, shamt.
+            inst_count!(self, "c.slli");
+            self.debug(inst, "c.slli");
+
+            let rd = (inst >> 7) & 0x1f;
+            // shamt[5|4:0] = inst[12|6:2]
+            let shamt = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f);
+            if rd != 0 {
+              self.xregs.write(rd, self.xregs.read(rd) << shamt);
+            }
+          }
+          0x1 => {
+            // c.fldsp
+            // Expands to fld rd, offset(x2).
+            inst_count!(self, "c.fldsp");
+            self.debug(inst, "c.fldsp");
+
+            let rd = (inst >> 7) & 0x1f;
+            // offset[5|4:3|8:6] = inst[12|6:5|4:2]
+            let offset = ((inst << 4) & 0x1c0) // offset[8:6]
                             | ((inst >> 7) & 0x20) // offset[5]
                             | ((inst >> 2) & 0x18); // offset[4:3]
-                        let val =
-                            f64::from_bits(self.read(self.xregs.read(2) + offset, DOUBLEWORD)?);
-                        self.fregs.write(rd, val);
-                    }
-                    0x2 => {
-                        // c.lwsp
-                        // Expands to lw rd, offset(x2).
-                        inst_count!(self, "c.lwsp");
-                        self.debug(inst, "c.lwsp");
-
-                        let rd = (inst >> 7) & 0x1f;
-                        // offset[5|4:2|7:6] = inst[12|6:4|3:2]
-                        let offset = ((inst << 4) & 0xc0) // offset[7:6]
+            let val = f64::from_bits(self.read(self.xregs.read(2) + offset, DOUBLEWORD)?);
+            self.fregs.write(rd, val);
+          }
+          0x2 => {
+            // c.lwsp
+            // Expands to lw rd, offset(x2).
+            inst_count!(self, "c.lwsp");
+            self.debug(inst, "c.lwsp");
+
+            let rd = (inst >> 7) & 0x1f;
+            // offset[5|4:2|7:6] = inst[12|6:4|3:2]
+            let offset = ((inst << 4) & 0xc0) // offset[7:6]
                             | ((inst >> 7) & 0x20) // offset[5]
                             | ((inst >> 2) & 0x1c); // offset[4:2]
-                        let val = self.read(self.xregs.read(2).wrapping_add(offset), WORD)?;
-                        self.xregs.write(rd, val as i32 as i64 as u64);
-                    }
-                    0x3 => {
-                        // c.ldsp
-                        // Expands to ld rd, offset(x2).
-                        inst_count!(self, "c.ldsp");
-                        self.debug(inst, "c.ldsp");
-
-                        let rd = (inst >> 7) & 0x1f;
-                        // offset[5|4:3|8:6] = inst[12|6:5|4:2]
-                        let offset = ((inst << 4) & 0x1c0) // offset[8:6]
+            let val = self.read(self.xregs.read(2).wrapping_add(offset), WORD)?;
+            self.xregs.write(rd, val as i32 as i64 as u64);
+          }
+          0x3 => {
+            // c.ldsp
+            // Expands to ld rd, offset(x2).
+            inst_count!(self, "c.ldsp");
+            self.debug(inst, "c.ldsp");
+
+            let rd = (inst >> 7) & 0x1f;
+            // offset[5|4:3|8:6] = inst[12|6:5|4:2]
+            let offset = ((inst << 4) & 0x1c0) // offset[8:6]
                             | ((inst >> 7) & 0x20) // offset[5]
                             | ((inst >> 2) & 0x18); // offset[4:3]
-                        let val = self.read(self.xregs.read(2).wrapping_add(offset), DOUBLEWORD)?;
-                        self.xregs.write(rd, val);
-                    }
-                    0x4 => {
-                        match ((inst >> 12) & 0x1, (inst >> 2) & 0x1f) {
-                            (0, 0) => {
-                                // c.jr
-                                // Expands to jalr x0, 0(rs1).
-                                inst_count!(self, "c.jr");
-                                self.debug(inst, "c.jr");
-
-                                let rs1 = (inst >> 7) & 0x1f;
-                                if rs1 != 0 {
-                                    self.pc = self.xregs.read(rs1).wrapping_sub(2);
-                                }
-                            }
-                            (0, _) => {
-                                // c.mv
-                                // Expands to add rd, x0, rs2.
-                                inst_count!(self, "c.mv");
-                                self.debug(inst, "c.mv");
-
-                                let rd = (inst >> 7) & 0x1f;
-                                let rs2 = (inst >> 2) & 0x1f;
-                                if rs2 != 0 {
-                                    self.xregs.write(rd, self.xregs.read(rs2));
-                                }
-                            }
-                            (1, 0) => {
-                                let rd = (inst >> 7) & 0x1f;
-                                if rd == 0 {
-                                    // c.ebreak
-                                    // Expands to ebreak.
-                                    inst_count!(self, "c.ebreak");
-                                    self.debug(inst, "c.ebreak");
-
-                                    return Err(Exception::Breakpoint);
-                                } else {
-                                    // c.jalr
-                                    // Expands to jalr x1, 0(rs1).
-                                    inst_count!(self, "c.jalr");
-                                    self.debug(inst, "c.jalr");
-
-                                    let rs1 = (inst >> 7) & 0x1f;
-                                    let t = self.pc.wrapping_add(2);
-                                    self.pc = self.xregs.read(rs1).wrapping_sub(2);
-                                    self.xregs.write(1, t);
-                                }
-                            }
-                            (1, _) => {
-                                // c.add
-                                // Expands to add rd, rd, rs2.
-                                inst_count!(self, "c.add");
-                                self.debug(inst, "c.add");
-
-                                let rd = (inst >> 7) & 0x1f;
-                                let rs2 = (inst >> 2) & 0x1f;
-                                if rs2 != 0 {
-                                    self.xregs.write(
-                                        rd,
-                                        self.xregs.read(rd).wrapping_add(self.xregs.read(rs2)),
-                                    );
-                                }
-                            }
-                            (_, _) => {
-                                return Err(Exception::IllegalInstruction(inst));
-                            }
-                        }
-                    }
-                    0x5 => {
-                        // c.fsdsp
-                        // Expands to fsd rs2, offset(x2).
-                        inst_count!(self, "c.fsdsp");
-                        self.debug(inst, "c.fsdsp");
-
-                        let rs2 = (inst >> 2) & 0x1f;
-                        // offset[5:3|8:6] = isnt[12:10|9:7]
-                        let offset = ((inst >> 1) & 0x1c0) // offset[8:6]
+            let val = self.read(self.xregs.read(2).wrapping_add(offset), DOUBLEWORD)?;
+            self.xregs.write(rd, val);
+          }
+          0x4 => {
+            match ((inst >> 12) & 0x1, (inst >> 2) & 0x1f) {
+              (0, 0) => {
+                // c.jr
+                // Expands to jalr x0, 0(rs1).
+                inst_count!(self, "c.jr");
+                self.debug(inst, "c.jr");
+
+                let rs1 = (inst >> 7) & 0x1f;
+                if rs1 != 0 {
+                  self.pc = self.xregs.read(rs1).wrapping_sub(2);
+                }
+              }
+              (0, _) => {
+                // c.mv
+                // Expands to add rd, x0, rs2.
+                inst_count!(self, "c.mv");
+                self.debug(inst, "c.mv");
+
+                let rd = (inst >> 7) & 0x1f;
+                let rs2 = (inst >> 2) & 0x1f;
+                if rs2 != 0 {
+                  self.xregs.write(rd, self.xregs.read(rs2));
+                }
+              }
+              (1, 0) => {
+                let rd = (inst >> 7) & 0x1f;
+                if rd == 0 {
+                  // c.ebreak
+                  // Expands to ebreak.
+                  inst_count!(self, "c.ebreak");
+                  self.debug(inst, "c.ebreak");
+
+                  return Err(Exception::Breakpoint);
+                } else {
+                  // c.jalr
+                  // Expands to jalr x1, 0(rs1).
+                  inst_count!(self, "c.jalr");
+                  self.debug(inst, "c.jalr");
+
+                  let rs1 = (inst >> 7) & 0x1f;
+                  let t = self.pc.wrapping_add(2);
+                  self.pc = self.xregs.read(rs1).wrapping_sub(2);
+                  self.xregs.write(1, t);
+                }
+              }
+              (1, _) => {
+                // c.add
+                // Expands to add rd, rd, rs2.
+                inst_count!(self, "c.add");
+                self.debug(inst, "c.add");
+
+                let rd = (inst >> 7) & 0x1f;
+                let rs2 = (inst >> 2) & 0x1f;
+                if rs2 != 0 {
+                  self
+                    .xregs
+                    .write(rd, self.xregs.read(rd).wrapping_add(self.xregs.read(rs2)));
+                }
+              }
+              (_, _) => {
+                return Err(Exception::IllegalInstruction(inst));
+              }
+            }
+          }
+          0x5 => {
+            // c.fsdsp
+            // Expands to fsd rs2, offset(x2).
+            inst_count!(self, "c.fsdsp");
+            self.debug(inst, "c.fsdsp");
+
+            let rs2 = (inst >> 2) & 0x1f;
+            // offset[5:3|8:6] = isnt[12:10|9:7]
+            let offset = ((inst >> 1) & 0x1c0) // offset[8:6]
                             | ((inst >> 7) & 0x38); // offset[5:3]
-                        let addr = self.xregs.read(2).wrapping_add(offset);
-                        self.write(addr, self.fregs.read(rs2).to_bits(), DOUBLEWORD)?;
-                    }
-                    0x6 => {
-                        // c.swsp
-                        // Expands to sw rs2, offset(x2).
-                        inst_count!(self, "c.swsp");
-                        self.debug(inst, "c.swsp");
-
-                        let rs2 = (inst >> 2) & 0x1f;
-                        // offset[5:2|7:6] = inst[12:9|8:7]
-                        let offset = ((inst >> 1) & 0xc0) // offset[7:6]
+            let addr = self.xregs.read(2).wrapping_add(offset);
+            self.write(addr, self.fregs.read(rs2).to_bits(), DOUBLEWORD)?;
+          }
+          0x6 => {
+            // c.swsp
+            // Expands to sw rs2, offset(x2).
+            inst_count!(self, "c.swsp");
+            self.debug(inst, "c.swsp");
+
+            let rs2 = (inst >> 2) & 0x1f;
+            // offset[5:2|7:6] = inst[12:9|8:7]
+            let offset = ((inst >> 1) & 0xc0) // offset[7:6]
                             | ((inst >> 7) & 0x3c); // offset[5:2]
-                        let addr = self.xregs.read(2).wrapping_add(offset);
-                        self.write(addr, self.xregs.read(rs2), WORD)?;
-                    }
-                    0x7 => {
-                        // c.sdsp
-                        // Expands to sd rs2, offset(x2).
-                        inst_count!(self, "c.sdsp");
-                        self.debug(inst, "c.sdsp");
-
-                        let rs2 = (inst >> 2) & 0x1f;
-                        // offset[5:3|8:6] = isnt[12:10|9:7]
-                        let offset = ((inst >> 1) & 0x1c0) // offset[8:6]
+            let addr = self.xregs.read(2).wrapping_add(offset);
+            self.write(addr, self.xregs.read(rs2), WORD)?;
+          }
+          0x7 => {
+            // c.sdsp
+            // Expands to sd rs2, offset(x2).
+            inst_count!(self, "c.sdsp");
+            self.debug(inst, "c.sdsp");
+
+            let rs2 = (inst >> 2) & 0x1f;
+            // offset[5:3|8:6] = isnt[12:10|9:7]
+            let offset = ((inst >> 1) & 0x1c0) // offset[8:6]
                             | ((inst >> 7) & 0x38); // offset[5:3]
-                        let addr = self.xregs.read(2).wrapping_add(offset);
-                        self.write(addr, self.xregs.read(rs2), DOUBLEWORD)?;
-                    }
-                    _ => {
-                        return Err(Exception::IllegalInstruction(inst));
-                    }
-                }
+            let addr = self.xregs.read(2).wrapping_add(offset);
+            self.write(addr, self.xregs.read(rs2), DOUBLEWORD)?;
+          }
+          _ => {
+            return Err(Exception::IllegalInstruction(inst));
+          }
+        }
+      }
+      _ => {
+        return Err(Exception::IllegalInstruction(inst));
+      }
+    }
+    Ok(())
+  }
+
+  /// Execute a general-purpose instruction. Raises an exception if something is wrong,
+  /// otherwise, returns a fetched instruction. It also increments the program counter by 4 bytes.
+  fn execute_general(&mut self, inst: u64) -> Result<(), Exception> {
+    // 2. Decode.
+    let opcode = inst & 0x0000007f;
+    let rd = (inst & 0x00000f80) >> 7;
+    let rs1 = (inst & 0x000f8000) >> 15;
+    let rs2 = (inst & 0x01f00000) >> 20;
+    let funct3 = (inst & 0x00007000) >> 12;
+    let funct7 = (inst & 0xfe000000) >> 25;
+
+    // 3. Execute.
+    match opcode {
+      0x03 => {
+        // RV32I and RV64I
+        // imm[11:0] = inst[31:20]
+        let offset = ((inst as i32 as i64) >> 20) as u64;
+        let addr = self.xregs.read(rs1).wrapping_add(offset);
+        match funct3 {
+          0x0 => {
+            // lb
+            inst_count!(self, "lb");
+            self.debug(inst, "lb");
+
+            let val = self.read(addr, BYTE)?;
+            self.xregs.write(rd, val as i8 as i64 as u64);
+          }
+          0x1 => {
+            // lh
+            inst_count!(self, "lh");
+            self.debug(inst, "lh");
+
+            let val = self.read(addr, HALFWORD)?;
+            self.xregs.write(rd, val as i16 as i64 as u64);
+          }
+          0x2 => {
+            // lw
+            inst_count!(self, "lw");
+            self.debug(inst, "lw");
+
+            let val = self.read(addr, WORD)?;
+            self.xregs.write(rd, val as i32 as i64 as u64);
+          }
+          0x3 => {
+            // ld
+            inst_count!(self, "ld");
+            self.debug(inst, "ld");
+
+            let val = self.read(addr, DOUBLEWORD)?;
+            self.xregs.write(rd, val);
+          }
+          0x4 => {
+            // lbu
+            inst_count!(self, "lbu");
+            self.debug(inst, "lbu");
+
+            let val = self.read(addr, BYTE)?;
+            self.xregs.write(rd, val);
+          }
+          0x5 => {
+            // lhu
+            inst_count!(self, "lhu");
+            self.debug(inst, "lhu");
+
+            let val = self.read(addr, HALFWORD)?;
+            self.xregs.write(rd, val);
+          }
+          0x6 => {
+            // lwu
+            inst_count!(self, "lwu");
+            self.debug(inst, "lwu");
+
+            let val = self.read(addr, WORD)?;
+            self.xregs.write(rd, val);
+          }
+          _ => {
+            return Err(Exception::IllegalInstruction(inst));
+          }
+        }
+      }
+      0x07 => {
+        // RV32D and RV64D
+        // imm[11:0] = inst[31:20]
+        let offset = ((inst as i32 as i64) >> 20) as u64;
+        let addr = self.xregs.read(rs1).wrapping_add(offset);
+        match funct3 {
+          0x2 => {
+            // flw
+            inst_count!(self, "flw");
+            self.debug(inst, "flw");
+
+            let val = f32::from_bits(self.read(addr, WORD)? as u32);
+            self.fregs.write(rd, val as f64);
+          }
+          0x3 => {
+            // fld
+            inst_count!(self, "fld");
+            self.debug(inst, "fld");
+
+            let val = f64::from_bits(self.read(addr, DOUBLEWORD)?);
+            self.fregs.write(rd, val);
+          }
+          _ => {
+            return Err(Exception::IllegalInstruction(inst));
+          }
+        }
+      }
+      0x0f => {
+        // RV32I and RV64I
+        // fence instructions are not supported yet because this emulator executes an
+        // instruction sequentially on a single thread.
+        // fence.i is a part of the Zifencei extension.
+        match funct3 {
+          0x0 => {
+            // fence
+            inst_count!(self, "fence");
+            self.debug(inst, "fence");
+          }
+          0x1 => {
+            // fence.i
+            inst_count!(self, "fence.i");
+            self.debug(inst, "fence.i");
+          }
+          _ => {
+            return Err(Exception::IllegalInstruction(inst));
+          }
+        }
+      }
+      0x13 => {
+        // RV32I and RV64I
+        // imm[11:0] = inst[31:20]
+        let imm = ((inst as i32 as i64) >> 20) as u64;
+        let funct6 = funct7 >> 1;
+        match funct3 {
+          0x0 => {
+            // addi
+            inst_count!(self, "addi");
+            self.debug(inst, "addi");
+
+            self.xregs.write(rd, self.xregs.read(rs1).wrapping_add(imm));
+          }
+          0x1 => {
+            // slli
+            inst_count!(self, "slli");
+            self.debug(inst, "slli");
+
+            // shamt size is 5 bits for RV32I and 6 bits for RV64I.
+            let shamt = (inst >> 20) & 0x3f;
+            self.xregs.write(rd, self.xregs.read(rs1) << shamt);
+          }
+          0x2 => {
+            // slti
+            inst_count!(self, "slti");
+            self.debug(inst, "slti");
+
+            self.xregs.write(
+              rd,
+              if (self.xregs.read(rs1) as i64) < (imm as i64) {
+                1
+              } else {
+                0
+              },
+            );
+          }
+          0x3 => {
+            // sltiu
+            inst_count!(self, "sltiu");
+            self.debug(inst, "sltiu");
+
+            self.xregs.write(rd, if self.xregs.read(rs1) < imm { 1 } else { 0 });
+          }
+          0x4 => {
+            // xori
+            inst_count!(self, "xori");
+            self.debug(inst, "xori");
+
+            self.xregs.write(rd, self.xregs.read(rs1) ^ imm);
+          }
+          0x5 => {
+            match funct6 {
+              0x00 => {
+                // srli
+                inst_count!(self, "srli");
+                self.debug(inst, "srli");
+
+                // shamt size is 5 bits for RV32I and 6 bits for RV64I.
+                let shamt = (inst >> 20) & 0x3f;
+                self.xregs.write(rd, self.xregs.read(rs1) >> shamt);
+              }
+              0x10 => {
+                // srai
+                inst_count!(self, "srai");
+                self.debug(inst, "srai");
+
+                // shamt size is 5 bits for RV32I and 6 bits for RV64I.
+                let shamt = (inst >> 20) & 0x3f;
+                self.xregs.write(rd, ((self.xregs.read(rs1) as i64) >> shamt) as u64);
+              }
+              _ => {
+                return Err(Exception::IllegalInstruction(inst));
+              }
             }
-            _ => {
+          }
+          0x6 => {
+            // ori
+            inst_count!(self, "ori");
+            self.debug(inst, "ori");
+
+            self.xregs.write(rd, self.xregs.read(rs1) | imm);
+          }
+          0x7 => {
+            // andi
+            inst_count!(self, "andi");
+            self.debug(inst, "andi");
+
+            self.xregs.write(rd, self.xregs.read(rs1) & imm);
+          }
+          _ => {
+            return Err(Exception::IllegalInstruction(inst));
+          }
+        }
+      }
+      0x17 => {
+        // RV32I
+        // auipc
+        inst_count!(self, "auipc");
+        self.debug(inst, "auipc");
+
+        // AUIPC forms a 32-bit offset from the 20-bit U-immediate, filling
+        // in the lowest 12 bits with zeros.
+        // imm[31:12] = inst[31:12]
+        let imm = (inst & 0xfffff000) as i32 as i64 as u64;
+        self.xregs.write(rd, self.pc.wrapping_add(imm));
+      }
+      0x1b => {
+        // RV64I
+        // imm[11:0] = inst[31:20]
+        let imm = ((inst as i32 as i64) >> 20) as u64;
+        match funct3 {
+          0x0 => {
+            // addiw
+            inst_count!(self, "addiw");
+            self.debug(inst, "addiw");
+
+            self
+              .xregs
+              .write(rd, self.xregs.read(rs1).wrapping_add(imm) as i32 as i64 as u64);
+          }
+          0x1 => {
+            // slliw
+            inst_count!(self, "slliw");
+            self.debug(inst, "slliw");
+
+            // "SLLIW, SRLIW, and SRAIW encodings with imm[5] ̸= 0 are reserved."
+            let shamt = (imm & 0x1f) as u32;
+            self
+              .xregs
+              .write(rd, (self.xregs.read(rs1) << shamt) as i32 as i64 as u64);
+          }
+          0x5 => {
+            match funct7 {
+              0x00 => {
+                // srliw
+                inst_count!(self, "srliw");
+                self.debug(inst, "srliw");
+
+                // "SLLIW, SRLIW, and SRAIW encodings with imm[5] ̸= 0 are reserved."
+                let shamt = (imm & 0x1f) as u32;
+                self
+                  .xregs
+                  .write(rd, ((self.xregs.read(rs1) as u32) >> shamt) as i32 as i64 as u64)
+              }
+              0x20 => {
+                // sraiw
+                inst_count!(self, "sraiw");
+                self.debug(inst, "sraiw");
+
+                // "SLLIW, SRLIW, and SRAIW encodings with imm[5] ̸= 0 are reserved."
+                let shamt = (imm & 0x1f) as u32;
+                self
+                  .xregs
+                  .write(rd, ((self.xregs.read(rs1) as i32) >> shamt) as i64 as u64);
+              }
+              _ => {
                 return Err(Exception::IllegalInstruction(inst));
+              }
             }
+          }
+          _ => {
+            return Err(Exception::IllegalInstruction(inst));
+          }
         }
-        Ok(())
-    }
-
-    /// Execute a general-purpose instruction. Raises an exception if something is wrong,
-    /// otherwise, returns a fetched instruction. It also increments the program counter by 4 bytes.
-    fn execute_general(&mut self, inst: u64) -> Result<(), Exception> {
-        // 2. Decode.
-        let opcode = inst & 0x0000007f;
-        let rd = (inst & 0x00000f80) >> 7;
-        let rs1 = (inst & 0x000f8000) >> 15;
-        let rs2 = (inst & 0x01f00000) >> 20;
-        let funct3 = (inst & 0x00007000) >> 12;
-        let funct7 = (inst & 0xfe000000) >> 25;
-
-        // 3. Execute.
-        match opcode {
-            0x03 => {
-                // RV32I and RV64I
-                // imm[11:0] = inst[31:20]
-                let offset = ((inst as i32 as i64) >> 20) as u64;
-                let addr = self.xregs.read(rs1).wrapping_add(offset);
-                match funct3 {
-                    0x0 => {
-                        // lb
-                        inst_count!(self, "lb");
-                        self.debug(inst, "lb");
-
-                        let val = self.read(addr, BYTE)?;
-                        self.xregs.write(rd, val as i8 as i64 as u64);
-                    }
-                    0x1 => {
-                        // lh
-                        inst_count!(self, "lh");
-                        self.debug(inst, "lh");
-
-                        let val = self.read(addr, HALFWORD)?;
-                        self.xregs.write(rd, val as i16 as i64 as u64);
-                    }
-                    0x2 => {
-                        // lw
-                        inst_count!(self, "lw");
-                        self.debug(inst, "lw");
-
-                        let val = self.read(addr, WORD)?;
-                        self.xregs.write(rd, val as i32 as i64 as u64);
-                    }
-                    0x3 => {
-                        // ld
-                        inst_count!(self, "ld");
-                        self.debug(inst, "ld");
-
-                        let val = self.read(addr, DOUBLEWORD)?;
-                        self.xregs.write(rd, val);
-                    }
-                    0x4 => {
-                        // lbu
-                        inst_count!(self, "lbu");
-                        self.debug(inst, "lbu");
-
-                        let val = self.read(addr, BYTE)?;
-                        self.xregs.write(rd, val);
-                    }
-                    0x5 => {
-                        // lhu
-                        inst_count!(self, "lhu");
-                        self.debug(inst, "lhu");
-
-                        let val = self.read(addr, HALFWORD)?;
-                        self.xregs.write(rd, val);
-                    }
-                    0x6 => {
-                        // lwu
-                        inst_count!(self, "lwu");
-                        self.debug(inst, "lwu");
-
-                        let val = self.read(addr, WORD)?;
-                        self.xregs.write(rd, val);
-                    }
-                    _ => {
-                        return Err(Exception::IllegalInstruction(inst));
-                    }
-                }
+      }
+      0x23 => {
+        // RV32I
+        // offset[11:5|4:0] = inst[31:25|11:7]
+        let offset = (((inst & 0xfe000000) as i32 as i64 >> 20) as u64) | ((inst >> 7) & 0x1f);
+        let addr = self.xregs.read(rs1).wrapping_add(offset);
+        match funct3 {
+          0x0 => {
+            // sb
+            inst_count!(self, "sb");
+            self.debug(inst, "sb");
+
+            self.write(addr, self.xregs.read(rs2), BYTE)?
+          }
+          0x1 => {
+            // sh
+            inst_count!(self, "sh");
+            self.debug(inst, "sh");
+
+            self.write(addr, self.xregs.read(rs2), HALFWORD)?
+          }
+          0x2 => {
+            // sw
+            inst_count!(self, "sw");
+            self.debug(inst, "sw");
+
+            self.write(addr, self.xregs.read(rs2), WORD)?
+          }
+          0x3 => {
+            // sd
+            inst_count!(self, "sd");
+            self.debug(inst, "sd");
+
+            self.write(addr, self.xregs.read(rs2), DOUBLEWORD)?
+          }
+          _ => {
+            return Err(Exception::IllegalInstruction(inst));
+          }
+        }
+      }
+      0x27 => {
+        // RV32F and RV64F
+        // offset[11:5|4:0] = inst[31:25|11:7]
+        let offset = ((((inst as i32 as i64) >> 20) as u64) & 0xfe0) | ((inst >> 7) & 0x1f);
+        let addr = self.xregs.read(rs1).wrapping_add(offset);
+        match funct3 {
+          0x2 => {
+            // fsw
+            inst_count!(self, "fsw");
+            self.debug(inst, "fsw");
+
+            self.write(addr, (self.fregs.read(rs2) as f32).to_bits() as u64, WORD)?
+          }
+          0x3 => {
+            // fsd
+            inst_count!(self, "fsd");
+            self.debug(inst, "fsd");
+
+            self.write(addr, self.fregs.read(rs2).to_bits() as u64, DOUBLEWORD)?
+          }
+          _ => {
+            return Err(Exception::IllegalInstruction(inst));
+          }
+        }
+      }
+      0x2f => {
+        // RV32A and RV64A
+        let funct5 = (funct7 & 0b1111100) >> 2;
+        // TODO: Handle `aq` and `rl`.
+        let _aq = (funct7 & 0b0000010) >> 1; // acquire access
+        let _rl = funct7 & 0b0000001; // release access
+        match (funct3, funct5) {
+          (0x2, 0x00) => {
+            // amoadd.w
+            inst_count!(self, "amoadd.w");
+            self.debug(inst, "amoadd.w");
+
+            let addr = self.xregs.read(rs1);
+            // "For AMOs, the A extension requires that the address held in rs1 be
+            // naturally aligned to the size of the operand (i.e., eight-byte aligned
+            // for 64-bit words and four-byte aligned for 32-bit words). If the
+            // address is not naturally aligned, an address-misaligned exception or
+            // an access-fault exception will be generated."
+            if addr % 4 != 0 {
+              return Err(Exception::LoadAddressMisaligned);
             }
-            0x07 => {
-                // RV32D and RV64D
-                // imm[11:0] = inst[31:20]
-                let offset = ((inst as i32 as i64) >> 20) as u64;
-                let addr = self.xregs.read(rs1).wrapping_add(offset);
-                match funct3 {
-                    0x2 => {
-                        // flw
-                        inst_count!(self, "flw");
-                        self.debug(inst, "flw");
-
-                        let val = f32::from_bits(self.read(addr, WORD)? as u32);
-                        self.fregs.write(rd, val as f64);
-                    }
-                    0x3 => {
-                        // fld
-                        inst_count!(self, "fld");
-                        self.debug(inst, "fld");
-
-                        let val = f64::from_bits(self.read(addr, DOUBLEWORD)?);
-                        self.fregs.write(rd, val);
-                    }
-                    _ => {
-                        return Err(Exception::IllegalInstruction(inst));
-                    }
-                }
+            let t = self.read(addr, WORD)?;
+            self.write(addr, t.wrapping_add(self.xregs.read(rs2)), WORD)?;
+            self.xregs.write(rd, t as i32 as i64 as u64);
+          }
+          (0x3, 0x00) => {
+            // amoadd.d
+            inst_count!(self, "amoadd.d");
+            self.debug(inst, "amoadd.d");
+
+            let addr = self.xregs.read(rs1);
+            if addr % 8 != 0 {
+              return Err(Exception::LoadAddressMisaligned);
             }
-            0x0f => {
-                // RV32I and RV64I
-                // fence instructions are not supported yet because this emulator executes an
-                // instruction sequentially on a single thread.
-                // fence.i is a part of the Zifencei extension.
-                match funct3 {
-                    0x0 => {
-                        // fence
-                        inst_count!(self, "fence");
-                        self.debug(inst, "fence");
-                    }
-                    0x1 => {
-                        // fence.i
-                        inst_count!(self, "fence.i");
-                        self.debug(inst, "fence.i");
-                    }
-                    _ => {
-                        return Err(Exception::IllegalInstruction(inst));
-                    }
-                }
+            let t = self.read(addr, DOUBLEWORD)?;
+            self.write(addr, t.wrapping_add(self.xregs.read(rs2)), DOUBLEWORD)?;
+            self.xregs.write(rd, t);
+          }
+          (0x2, 0x01) => {
+            // amoswap.w
+            inst_count!(self, "amoswap.w");
+            self.debug(inst, "amoswap.w");
+
+            let addr = self.xregs.read(rs1);
+            if addr % 4 != 0 {
+              return Err(Exception::LoadAddressMisaligned);
             }
-            0x13 => {
-                // RV32I and RV64I
-                // imm[11:0] = inst[31:20]
-                let imm = ((inst as i32 as i64) >> 20) as u64;
-                let funct6 = funct7 >> 1;
-                match funct3 {
-                    0x0 => {
-                        // addi
-                        inst_count!(self, "addi");
-                        self.debug(inst, "addi");
-
-                        self.xregs.write(rd, self.xregs.read(rs1).wrapping_add(imm));
-                    }
-                    0x1 => {
-                        // slli
-                        inst_count!(self, "slli");
-                        self.debug(inst, "slli");
-
-                        // shamt size is 5 bits for RV32I and 6 bits for RV64I.
-                        let shamt = (inst >> 20) & 0x3f;
-                        self.xregs.write(rd, self.xregs.read(rs1) << shamt);
-                    }
-                    0x2 => {
-                        // slti
-                        inst_count!(self, "slti");
-                        self.debug(inst, "slti");
-
-                        self.xregs.write(
-                            rd,
-                            if (self.xregs.read(rs1) as i64) < (imm as i64) {
-                                1
-                            } else {
-                                0
-                            },
-                        );
-                    }
-                    0x3 => {
-                        // sltiu
-                        inst_count!(self, "sltiu");
-                        self.debug(inst, "sltiu");
-
-                        self.xregs
-                            .write(rd, if self.xregs.read(rs1) < imm { 1 } else { 0 });
-                    }
-                    0x4 => {
-                        // xori
-                        inst_count!(self, "xori");
-                        self.debug(inst, "xori");
-
-                        self.xregs.write(rd, self.xregs.read(rs1) ^ imm);
-                    }
-                    0x5 => {
-                        match funct6 {
-                            0x00 => {
-                                // srli
-                                inst_count!(self, "srli");
-                                self.debug(inst, "srli");
-
-                                // shamt size is 5 bits for RV32I and 6 bits for RV64I.
-                                let shamt = (inst >> 20) & 0x3f;
-                                self.xregs.write(rd, self.xregs.read(rs1) >> shamt);
-                            }
-                            0x10 => {
-                                // srai
-                                inst_count!(self, "srai");
-                                self.debug(inst, "srai");
-
-                                // shamt size is 5 bits for RV32I and 6 bits for RV64I.
-                                let shamt = (inst >> 20) & 0x3f;
-                                self.xregs
-                                    .write(rd, ((self.xregs.read(rs1) as i64) >> shamt) as u64);
-                            }
-                            _ => {
-                                return Err(Exception::IllegalInstruction(inst));
-                            }
-                        }
-                    }
-                    0x6 => {
-                        // ori
-                        inst_count!(self, "ori");
-                        self.debug(inst, "ori");
-
-                        self.xregs.write(rd, self.xregs.read(rs1) | imm);
-                    }
-                    0x7 => {
-                        // andi
-                        inst_count!(self, "andi");
-                        self.debug(inst, "andi");
-
-                        self.xregs.write(rd, self.xregs.read(rs1) & imm);
-                    }
-                    _ => {
-                        return Err(Exception::IllegalInstruction(inst));
-                    }
-                }
+            let t = self.read(addr, WORD)?;
+            self.write(addr, self.xregs.read(rs2), WORD)?;
+            self.xregs.write(rd, t as i32 as i64 as u64);
+          }
+          (0x3, 0x01) => {
+            // amoswap.d
+            inst_count!(self, "amoswap.d");
+            self.debug(inst, "amoswap.d");
+
+            let addr = self.xregs.read(rs1);
+            if addr % 8 != 0 {
+              return Err(Exception::LoadAddressMisaligned);
             }
-            0x17 => {
-                // RV32I
-                // auipc
-                inst_count!(self, "auipc");
-                self.debug(inst, "auipc");
-
-                // AUIPC forms a 32-bit offset from the 20-bit U-immediate, filling
-                // in the lowest 12 bits with zeros.
-                // imm[31:12] = inst[31:12]
-                let imm = (inst & 0xfffff000) as i32 as i64 as u64;
-                self.xregs.write(rd, self.pc.wrapping_add(imm));
+            let t = self.read(addr, DOUBLEWORD)?;
+            self.write(addr, self.xregs.read(rs2), DOUBLEWORD)?;
+            self.xregs.write(rd, t);
+          }
+          (0x2, 0x02) => {
+            // lr.w
+            inst_count!(self, "lr.w");
+            self.debug(inst, "lr.w");
+
+            let addr = self.xregs.read(rs1);
+            // "For LR and SC, the A extension requires that the address held in rs1 be
+            // naturally aligned to the size of the operand (i.e., eight-byte aligned
+            // for 64-bit words and four-byte aligned for 32-bit words)."
+            if addr % 4 != 0 {
+              return Err(Exception::LoadAddressMisaligned);
             }
-            0x1b => {
-                // RV64I
-                // imm[11:0] = inst[31:20]
-                let imm = ((inst as i32 as i64) >> 20) as u64;
-                match funct3 {
-                    0x0 => {
-                        // addiw
-                        inst_count!(self, "addiw");
-                        self.debug(inst, "addiw");
-
-                        self.xregs.write(
-                            rd,
-                            self.xregs.read(rs1).wrapping_add(imm) as i32 as i64 as u64,
-                        );
-                    }
-                    0x1 => {
-                        // slliw
-                        inst_count!(self, "slliw");
-                        self.debug(inst, "slliw");
-
-                        // "SLLIW, SRLIW, and SRAIW encodings with imm[5] ̸= 0 are reserved."
-                        let shamt = (imm & 0x1f) as u32;
-                        self.xregs
-                            .write(rd, (self.xregs.read(rs1) << shamt) as i32 as i64 as u64);
-                    }
-                    0x5 => {
-                        match funct7 {
-                            0x00 => {
-                                // srliw
-                                inst_count!(self, "srliw");
-                                self.debug(inst, "srliw");
-
-                                // "SLLIW, SRLIW, and SRAIW encodings with imm[5] ̸= 0 are reserved."
-                                let shamt = (imm & 0x1f) as u32;
-                                self.xregs.write(
-                                    rd,
-                                    ((self.xregs.read(rs1) as u32) >> shamt) as i32 as i64 as u64,
-                                )
-                            }
-                            0x20 => {
-                                // sraiw
-                                inst_count!(self, "sraiw");
-                                self.debug(inst, "sraiw");
-
-                                // "SLLIW, SRLIW, and SRAIW encodings with imm[5] ̸= 0 are reserved."
-                                let shamt = (imm & 0x1f) as u32;
-                                self.xregs.write(
-                                    rd,
-                                    ((self.xregs.read(rs1) as i32) >> shamt) as i64 as u64,
-                                );
-                            }
-                            _ => {
-                                return Err(Exception::IllegalInstruction(inst));
-                            }
-                        }
-                    }
-                    _ => {
-                        return Err(Exception::IllegalInstruction(inst));
-                    }
-                }
+            let value = self.read(addr, WORD)?;
+            self.xregs.write(rd, value as i32 as i64 as u64);
+            self.reservation_set.push(addr);
+          }
+          (0x3, 0x02) => {
+            // lr.d
+            inst_count!(self, "lr.d");
+            self.debug(inst, "lr.d");
+
+            let addr = self.xregs.read(rs1);
+            // "For LR and SC, the A extension requires that the address held in rs1 be
+            // naturally aligned to the size of the operand (i.e., eight-byte aligned for
+            // 64-bit words and four-byte aligned for 32-bit words)."
+            if addr % 8 != 0 {
+              return Err(Exception::LoadAddressMisaligned);
             }
-            0x23 => {
-                // RV32I
-                // offset[11:5|4:0] = inst[31:25|11:7]
-                let offset =
-                    (((inst & 0xfe000000) as i32 as i64 >> 20) as u64) | ((inst >> 7) & 0x1f);
-                let addr = self.xregs.read(rs1).wrapping_add(offset);
-                match funct3 {
-                    0x0 => {
-                        // sb
-                        inst_count!(self, "sb");
-                        self.debug(inst, "sb");
-
-                        self.write(addr, self.xregs.read(rs2), BYTE)?
-                    }
-                    0x1 => {
-                        // sh
-                        inst_count!(self, "sh");
-                        self.debug(inst, "sh");
-
-                        self.write(addr, self.xregs.read(rs2), HALFWORD)?
-                    }
-                    0x2 => {
-                        // sw
-                        inst_count!(self, "sw");
-                        self.debug(inst, "sw");
-
-                        self.write(addr, self.xregs.read(rs2), WORD)?
-                    }
-                    0x3 => {
-                        // sd
-                        inst_count!(self, "sd");
-                        self.debug(inst, "sd");
-
-                        self.write(addr, self.xregs.read(rs2), DOUBLEWORD)?
-                    }
-                    _ => {
-                        return Err(Exception::IllegalInstruction(inst));
-                    }
-                }
+            let value = self.read(addr, DOUBLEWORD)?;
+            self.xregs.write(rd, value);
+            self.reservation_set.push(addr);
+          }
+          (0x2, 0x03) => {
+            // sc.w
+            inst_count!(self, "sc.w");
+            self.debug(inst, "sc.w");
+
+            let addr = self.xregs.read(rs1);
+            // "For LR and SC, the A extension requires that the address held in rs1 be
+            // naturally aligned to the size of the operand (i.e., eight-byte aligned for
+            // 64-bit words and four-byte aligned for 32-bit words)."
+            if addr % 4 != 0 {
+              return Err(Exception::StoreAMOAddressMisaligned);
             }
-            0x27 => {
-                // RV32F and RV64F
-                // offset[11:5|4:0] = inst[31:25|11:7]
-                let offset = ((((inst as i32 as i64) >> 20) as u64) & 0xfe0) | ((inst >> 7) & 0x1f);
-                let addr = self.xregs.read(rs1).wrapping_add(offset);
-                match funct3 {
-                    0x2 => {
-                        // fsw
-                        inst_count!(self, "fsw");
-                        self.debug(inst, "fsw");
-
-                        self.write(addr, (self.fregs.read(rs2) as f32).to_bits() as u64, WORD)?
-                    }
-                    0x3 => {
-                        // fsd
-                        inst_count!(self, "fsd");
-                        self.debug(inst, "fsd");
-
-                        self.write(addr, self.fregs.read(rs2).to_bits() as u64, DOUBLEWORD)?
-                    }
-                    _ => {
-                        return Err(Exception::IllegalInstruction(inst));
-                    }
-                }
+            if self.reservation_set.contains(&addr) {
+              // "Regardless of success or failure, executing an SC.W instruction
+              // invalidates any reservation held by this hart. "
+              self.reservation_set.retain(|&x| x != addr);
+              self.write(addr, self.xregs.read(rs2), WORD)?;
+              self.xregs.write(rd, 0);
+            } else {
+              self.reservation_set.retain(|&x| x != addr);
+              self.xregs.write(rd, 1);
+            };
+          }
+          (0x3, 0x03) => {
+            // sc.d
+            inst_count!(self, "sc.d");
+            self.debug(inst, "sc.d");
+
+            let addr = self.xregs.read(rs1);
+            // "For LR and SC, the A extension requires that the address held in rs1 be
+            // naturally aligned to the size of the operand (i.e., eight-byte aligned for
+            // 64-bit words and four-byte aligned for 32-bit words)."
+            if addr % 8 != 0 {
+              return Err(Exception::StoreAMOAddressMisaligned);
             }
-            0x2f => {
-                // RV32A and RV64A
-                let funct5 = (funct7 & 0b1111100) >> 2;
-                // TODO: Handle `aq` and `rl`.
-                let _aq = (funct7 & 0b0000010) >> 1; // acquire access
-                let _rl = funct7 & 0b0000001; // release access
-                match (funct3, funct5) {
-                    (0x2, 0x00) => {
-                        // amoadd.w
-                        inst_count!(self, "amoadd.w");
-                        self.debug(inst, "amoadd.w");
-
-                        let addr = self.xregs.read(rs1);
-                        // "For AMOs, the A extension requires that the address held in rs1 be
-                        // naturally aligned to the size of the operand (i.e., eight-byte aligned
-                        // for 64-bit words and four-byte aligned for 32-bit words). If the
-                        // address is not naturally aligned, an address-misaligned exception or
-                        // an access-fault exception will be generated."
-                        if addr % 4 != 0 {
-                            return Err(Exception::LoadAddressMisaligned);
-                        }
-                        let t = self.read(addr, WORD)?;
-                        self.write(addr, t.wrapping_add(self.xregs.read(rs2)), WORD)?;
-                        self.xregs.write(rd, t as i32 as i64 as u64);
-                    }
-                    (0x3, 0x00) => {
-                        // amoadd.d
-                        inst_count!(self, "amoadd.d");
-                        self.debug(inst, "amoadd.d");
-
-                        let addr = self.xregs.read(rs1);
-                        if addr % 8 != 0 {
-                            return Err(Exception::LoadAddressMisaligned);
-                        }
-                        let t = self.read(addr, DOUBLEWORD)?;
-                        self.write(addr, t.wrapping_add(self.xregs.read(rs2)), DOUBLEWORD)?;
-                        self.xregs.write(rd, t);
-                    }
-                    (0x2, 0x01) => {
-                        // amoswap.w
-                        inst_count!(self, "amoswap.w");
-                        self.debug(inst, "amoswap.w");
-
-                        let addr = self.xregs.read(rs1);
-                        if addr % 4 != 0 {
-                            return Err(Exception::LoadAddressMisaligned);
-                        }
-                        let t = self.read(addr, WORD)?;
-                        self.write(addr, self.xregs.read(rs2), WORD)?;
-                        self.xregs.write(rd, t as i32 as i64 as u64);
-                    }
-                    (0x3, 0x01) => {
-                        // amoswap.d
-                        inst_count!(self, "amoswap.d");
-                        self.debug(inst, "amoswap.d");
-
-                        let addr = self.xregs.read(rs1);
-                        if addr % 8 != 0 {
-                            return Err(Exception::LoadAddressMisaligned);
-                        }
-                        let t = self.read(addr, DOUBLEWORD)?;
-                        self.write(addr, self.xregs.read(rs2), DOUBLEWORD)?;
-                        self.xregs.write(rd, t);
-                    }
-                    (0x2, 0x02) => {
-                        // lr.w
-                        inst_count!(self, "lr.w");
-                        self.debug(inst, "lr.w");
-
-                        let addr = self.xregs.read(rs1);
-                        // "For LR and SC, the A extension requires that the address held in rs1 be
-                        // naturally aligned to the size of the operand (i.e., eight-byte aligned
-                        // for 64-bit words and four-byte aligned for 32-bit words)."
-                        if addr % 4 != 0 {
-                            return Err(Exception::LoadAddressMisaligned);
-                        }
-                        let value = self.read(addr, WORD)?;
-                        self.xregs.write(rd, value as i32 as i64 as u64);
-                        self.reservation_set.push(addr);
-                    }
-                    (0x3, 0x02) => {
-                        // lr.d
-                        inst_count!(self, "lr.d");
-                        self.debug(inst, "lr.d");
-
-                        let addr = self.xregs.read(rs1);
-                        // "For LR and SC, the A extension requires that the address held in rs1 be
-                        // naturally aligned to the size of the operand (i.e., eight-byte aligned for
-                        // 64-bit words and four-byte aligned for 32-bit words)."
-                        if addr % 8 != 0 {
-                            return Err(Exception::LoadAddressMisaligned);
-                        }
-                        let value = self.read(addr, DOUBLEWORD)?;
-                        self.xregs.write(rd, value);
-                        self.reservation_set.push(addr);
-                    }
-                    (0x2, 0x03) => {
-                        // sc.w
-                        inst_count!(self, "sc.w");
-                        self.debug(inst, "sc.w");
-
-                        let addr = self.xregs.read(rs1);
-                        // "For LR and SC, the A extension requires that the address held in rs1 be
-                        // naturally aligned to the size of the operand (i.e., eight-byte aligned for
-                        // 64-bit words and four-byte aligned for 32-bit words)."
-                        if addr % 4 != 0 {
-                            return Err(Exception::StoreAMOAddressMisaligned);
-                        }
-                        if self.reservation_set.contains(&addr) {
-                            // "Regardless of success or failure, executing an SC.W instruction
-                            // invalidates any reservation held by this hart. "
-                            self.reservation_set.retain(|&x| x != addr);
-                            self.write(addr, self.xregs.read(rs2), WORD)?;
-                            self.xregs.write(rd, 0);
-                        } else {
-                            self.reservation_set.retain(|&x| x != addr);
-                            self.xregs.write(rd, 1);
-                        };
-                    }
-                    (0x3, 0x03) => {
-                        // sc.d
-                        inst_count!(self, "sc.d");
-                        self.debug(inst, "sc.d");
-
-                        let addr = self.xregs.read(rs1);
-                        // "For LR and SC, the A extension requires that the address held in rs1 be
-                        // naturally aligned to the size of the operand (i.e., eight-byte aligned for
-                        // 64-bit words and four-byte aligned for 32-bit words)."
-                        if addr % 8 != 0 {
-                            return Err(Exception::StoreAMOAddressMisaligned);
-                        }
-                        if self.reservation_set.contains(&addr) {
-                            self.reservation_set.retain(|&x| x != addr);
-                            self.write(addr, self.xregs.read(rs2), DOUBLEWORD)?;
-                            self.xregs.write(rd, 0);
-                        } else {
-                            self.reservation_set.retain(|&x| x != addr);
-                            self.xregs.write(rd, 1);
-                        }
-                    }
-                    (0x2, 0x04) => {
-                        // amoxor.w
-                        inst_count!(self, "amoxor.w");
-                        self.debug(inst, "amoxor.w");
-
-                        let addr = self.xregs.read(rs1);
-                        if addr % 4 != 0 {
-                            return Err(Exception::LoadAddressMisaligned);
-                        }
-                        let t = self.read(addr, WORD)?;
-                        self.write(
-                            addr,
-                            (t as i32 ^ (self.xregs.read(rs2) as i32)) as i64 as u64,
-                            WORD,
-                        )?;
-                        self.xregs.write(rd, t as i32 as i64 as u64);
-                    }
-                    (0x3, 0x04) => {
-                        // amoxor.d
-                        inst_count!(self, "amoxor.d");
-                        self.debug(inst, "amoxor.d");
-
-                        let addr = self.xregs.read(rs1);
-                        if addr % 8 != 0 {
-                            return Err(Exception::LoadAddressMisaligned);
-                        }
-                        let t = self.read(addr, DOUBLEWORD)?;
-                        self.write(addr, t ^ self.xregs.read(rs2), DOUBLEWORD)?;
-                        self.xregs.write(rd, t);
-                    }
-                    (0x2, 0x08) => {
-                        // amoor.w
-                        inst_count!(self, "amoor.w");
-                        self.debug(inst, "amoor.w");
-
-                        let addr = self.xregs.read(rs1);
-                        if addr % 4 != 0 {
-                            return Err(Exception::LoadAddressMisaligned);
-                        }
-                        let t = self.read(addr, WORD)?;
-                        self.write(
-                            addr,
-                            (t as i32 | (self.xregs.read(rs2) as i32)) as i64 as u64,
-                            WORD,
-                        )?;
-                        self.xregs.write(rd, t as i32 as i64 as u64);
-                    }
-                    (0x3, 0x08) => {
-                        // amoor.d
-                        inst_count!(self, "amoor.d");
-                        self.debug(inst, "amoor.d");
-
-                        let addr = self.xregs.read(rs1);
-                        if addr % 8 != 0 {
-                            return Err(Exception::LoadAddressMisaligned);
-                        }
-                        let t = self.read(addr, DOUBLEWORD)?;
-                        self.write(addr, t | self.xregs.read(rs2), DOUBLEWORD)?;
-                        self.xregs.write(rd, t);
-                    }
-                    (0x2, 0x0c) => {
-                        // amoand.w
-                        inst_count!(self, "amoand.w");
-                        self.debug(inst, "amoand.w");
-
-                        let addr = self.xregs.read(rs1);
-                        if addr % 4 != 0 {
-                            return Err(Exception::LoadAddressMisaligned);
-                        }
-                        let t = self.read(addr, WORD)?;
-                        self.write(
-                            addr,
-                            (t as i32 & (self.xregs.read(rs2) as i32)) as u32 as u64,
-                            WORD,
-                        )?;
-                        self.xregs.write(rd, t as i32 as i64 as u64);
-                    }
-                    (0x3, 0x0c) => {
-                        // amoand.d
-                        inst_count!(self, "amoand.d");
-                        self.debug(inst, "amoand.d");
-
-                        let addr = self.xregs.read(rs1);
-                        if addr % 8 != 0 {
-                            return Err(Exception::LoadAddressMisaligned);
-                        }
-                        let t = self.read(addr, DOUBLEWORD)?;
-                        self.write(addr, t & self.xregs.read(rs2), DOUBLEWORD)?;
-                        self.xregs.write(rd, t);
-                    }
-                    (0x2, 0x10) => {
-                        // amomin.w
-                        inst_count!(self, "amomin.w");
-                        self.debug(inst, "amomin.w");
-
-                        let addr = self.xregs.read(rs1);
-                        if addr % 4 != 0 {
-                            return Err(Exception::LoadAddressMisaligned);
-                        }
-                        let t = self.read(addr, WORD)?;
-                        self.write(
-                            addr,
-                            cmp::min(t as i32, self.xregs.read(rs2) as i32) as i64 as u64,
-                            WORD,
-                        )?;
-                        self.xregs.write(rd, t as i32 as i64 as u64);
-                    }
-                    (0x3, 0x10) => {
-                        // amomin.d
-                        inst_count!(self, "amomin.d");
-                        self.debug(inst, "amomin.d");
-
-                        let addr = self.xregs.read(rs1);
-                        if addr % 8 != 0 {
-                            return Err(Exception::LoadAddressMisaligned);
-                        }
-                        let t = self.read(addr, DOUBLEWORD)?;
-                        self.write(
-                            addr,
-                            cmp::min(t as i64, self.xregs.read(rs2) as i64) as u64,
-                            DOUBLEWORD,
-                        )?;
-                        self.xregs.write(rd, t as u64);
-                    }
-                    (0x2, 0x14) => {
-                        // amomax.w
-                        inst_count!(self, "amomax.w");
-                        self.debug(inst, "amomax.w");
-
-                        let addr = self.xregs.read(rs1);
-                        if addr % 4 != 0 {
-                            return Err(Exception::LoadAddressMisaligned);
-                        }
-                        let t = self.read(addr, WORD)?;
-                        self.write(
-                            addr,
-                            cmp::max(t as i32, self.xregs.read(rs2) as i32) as i64 as u64,
-                            WORD,
-                        )?;
-                        self.xregs.write(rd, t as i32 as i64 as u64);
-                    }
-                    (0x3, 0x14) => {
-                        // amomax.d
-                        inst_count!(self, "amomax.d");
-                        self.debug(inst, "amomax.d");
-
-                        let addr = self.xregs.read(rs1);
-                        if addr % 8 != 0 {
-                            return Err(Exception::LoadAddressMisaligned);
-                        }
-                        let t = self.read(addr, DOUBLEWORD)?;
-                        self.write(
-                            addr,
-                            cmp::max(t as i64, self.xregs.read(rs2) as i64) as u64,
-                            DOUBLEWORD,
-                        )?;
-                        self.xregs.write(rd, t);
-                    }
-                    (0x2, 0x18) => {
-                        // amominu.w
-                        inst_count!(self, "amominu.w");
-                        self.debug(inst, "amominu.w");
-
-                        let addr = self.xregs.read(rs1);
-                        if addr % 4 != 0 {
-                            return Err(Exception::LoadAddressMisaligned);
-                        }
-                        let t = self.read(addr, WORD)?;
-                        self.write(
-                            addr,
-                            cmp::min(t as u32, self.xregs.read(rs2) as u32) as u64,
-                            WORD,
-                        )?;
-                        self.xregs.write(rd, t as i32 as i64 as u64);
-                    }
-                    (0x3, 0x18) => {
-                        // amominu.d
-                        inst_count!(self, "amominu.d");
-                        self.debug(inst, "amominu.d");
-
-                        let addr = self.xregs.read(rs1);
-                        if addr % 8 != 0 {
-                            return Err(Exception::LoadAddressMisaligned);
-                        }
-                        let t = self.read(addr, DOUBLEWORD)?;
-                        self.write(addr, cmp::min(t, self.xregs.read(rs2)), DOUBLEWORD)?;
-                        self.xregs.write(rd, t);
-                    }
-                    (0x2, 0x1c) => {
-                        // amomaxu.w
-                        inst_count!(self, "amomaxu.w");
-                        self.debug(inst, "amomaxu.w");
-
-                        let addr = self.xregs.read(rs1);
-                        if addr % 4 != 0 {
-                            return Err(Exception::LoadAddressMisaligned);
-                        }
-                        let t = self.read(addr, WORD)?;
-                        self.write(
-                            addr,
-                            cmp::max(t as u32, self.xregs.read(rs2) as u32) as u64,
-                            WORD,
-                        )?;
-                        self.xregs.write(rd, t as i32 as i64 as u64);
-                    }
-                    (0x3, 0x1c) => {
-                        // amomaxu.d
-                        inst_count!(self, "amomaxu.d");
-                        self.debug(inst, "amomaxu.d");
-
-                        let addr = self.xregs.read(rs1);
-                        if addr % 8 != 0 {
-                            return Err(Exception::LoadAddressMisaligned);
-                        }
-                        let t = self.read(addr, DOUBLEWORD)?;
-                        self.write(addr, cmp::max(t, self.xregs.read(rs2)), DOUBLEWORD)?;
-                        self.xregs.write(rd, t);
-                    }
-                    _ => {
-                        return Err(Exception::IllegalInstruction(inst));
-                    }
-                }
+            if self.reservation_set.contains(&addr) {
+              self.reservation_set.retain(|&x| x != addr);
+              self.write(addr, self.xregs.read(rs2), DOUBLEWORD)?;
+              self.xregs.write(rd, 0);
+            } else {
+              self.reservation_set.retain(|&x| x != addr);
+              self.xregs.write(rd, 1);
             }
-            0x33 => {
-                // RV64I and RV64M
-                match (funct3, funct7) {
-                    (0x0, 0x00) => {
-                        // add
-                        inst_count!(self, "add");
-                        self.debug(inst, "add");
-
-                        self.xregs
-                            .write(rd, self.xregs.read(rs1).wrapping_add(self.xregs.read(rs2)));
-                    }
-                    (0x0, 0x01) => {
-                        // mul
-                        inst_count!(self, "mul");
-                        self.debug(inst, "mul");
-
-                        self.xregs.write(
-                            rd,
-                            (self.xregs.read(rs1) as i64).wrapping_mul(self.xregs.read(rs2) as i64)
-                                as u64,
-                        );
-                    }
-                    (0x0, 0x20) => {
-                        // sub
-                        inst_count!(self, "sub");
-                        self.debug(inst, "sub");
-
-                        self.xregs
-                            .write(rd, self.xregs.read(rs1).wrapping_sub(self.xregs.read(rs2)));
-                    }
-                    (0x1, 0x00) => {
-                        // sll
-                        inst_count!(self, "sll");
-                        self.debug(inst, "sll");
-
-                        // "SLL, SRL, and SRA perform logical left, logical right, and arithmetic
-                        // right shifts on the value in register rs1 by the shift amount held in
-                        // register rs2. In RV64I, only the low 6 bits of rs2 are considered for the
-                        // shift amount."
-                        let shamt = self.xregs.read(rs2) & 0x3f;
-                        self.xregs.write(rd, self.xregs.read(rs1) << shamt);
-                    }
-                    (0x1, 0x01) => {
-                        // mulh
-                        inst_count!(self, "mulh");
-                        self.debug(inst, "mulh");
-
-                        // signed × signed
-                        self.xregs.write(
-                            rd,
-                            ((self.xregs.read(rs1) as i64 as i128)
-                                .wrapping_mul(self.xregs.read(rs2) as i64 as i128)
-                                >> 64) as u64,
-                        );
-                    }
-                    (0x2, 0x00) => {
-                        // slt
-                        inst_count!(self, "slt");
-                        self.debug(inst, "slt");
-
-                        self.xregs.write(
-                            rd,
-                            if (self.xregs.read(rs1) as i64) < (self.xregs.read(rs2) as i64) {
-                                1
-                            } else {
-                                0
-                            },
-                        );
-                    }
-                    (0x2, 0x01) => {
-                        // mulhsu
-                        inst_count!(self, "mulhsu");
-                        self.debug(inst, "mulhsu");
-
-                        // signed × unsigned
-                        self.xregs.write(
-                            rd,
-                            ((self.xregs.read(rs1) as i64 as i128 as u128)
-                                .wrapping_mul(self.xregs.read(rs2) as u128)
-                                >> 64) as u64,
-                        );
-                    }
-                    (0x3, 0x00) => {
-                        // sltu
-                        inst_count!(self, "sltu");
-                        self.debug(inst, "sltu");
-
-                        self.xregs.write(
-                            rd,
-                            if self.xregs.read(rs1) < self.xregs.read(rs2) {
-                                1
-                            } else {
-                                0
-                            },
-                        );
-                    }
-                    (0x3, 0x01) => {
-                        // mulhu
-                        inst_count!(self, "mulhu");
-                        self.debug(inst, "mulhu");
-
-                        // unsigned × unsigned
-                        self.xregs.write(
-                            rd,
-                            ((self.xregs.read(rs1) as u128)
-                                .wrapping_mul(self.xregs.read(rs2) as u128)
-                                >> 64) as u64,
-                        );
-                    }
-                    (0x4, 0x00) => {
-                        // xor
-                        inst_count!(self, "xor");
-                        self.debug(inst, "xor");
-
-                        self.xregs
-                            .write(rd, self.xregs.read(rs1) ^ self.xregs.read(rs2));
-                    }
-                    (0x4, 0x01) => {
-                        // div
-                        inst_count!(self, "div");
-                        self.debug(inst, "div");
-
-                        let dividend = self.xregs.read(rs1) as i64;
-                        let divisor = self.xregs.read(rs2) as i64;
-                        self.xregs.write(
-                            rd,
-                            if divisor == 0 {
-                                // Division by zero
-                                // Set DZ (Divide by Zero) flag to 1.
-                                self.state.write_bit(FCSR, 3, 1);
-                                // "The quotient of division by zero has all bits set"
-                                u64::MAX
-                            } else if dividend == i64::MIN && divisor == -1 {
-                                // Overflow
-                                // "The quotient of a signed division with overflow is equal to the
-                                // dividend"
-                                dividend as u64
-                            } else {
-                                // "division of rs1 by rs2, rounding towards zero"
-                                dividend.wrapping_div(divisor) as u64
-                            },
-                        );
-                    }
-                    (0x5, 0x00) => {
-                        // srl
-                        inst_count!(self, "srl");
-                        self.debug(inst, "srl");
-
-                        // "SLL, SRL, and SRA perform logical left, logical right, and arithmetic
-                        // right shifts on the value in register rs1 by the shift amount held in
-                        // register rs2. In RV64I, only the low 6 bits of rs2 are considered for the
-                        // shift amount."
-                        let shamt = self.xregs.read(rs2) & 0x3f;
-                        self.xregs.write(rd, self.xregs.read(rs1) >> shamt);
-                    }
-                    (0x5, 0x01) => {
-                        // divu
-                        inst_count!(self, "divu");
-                        self.debug(inst, "divu");
-
-                        let dividend = self.xregs.read(rs1);
-                        let divisor = self.xregs.read(rs2);
-                        self.xregs.write(
-                            rd,
-                            if divisor == 0 {
-                                // Division by zero
-                                // Set DZ (Divide by Zero) flag to 1.
-                                self.state.write_bit(FCSR, 3, 1);
-                                // "The quotient of division by zero has all bits set"
-                                u64::MAX
-                            } else {
-                                // "division of rs1 by rs2, rounding towards zero"
-                                dividend.wrapping_div(divisor)
-                            },
-                        );
-                    }
-                    (0x5, 0x20) => {
-                        // sra
-                        inst_count!(self, "sra");
-                        self.debug(inst, "sra");
-
-                        // "SLL, SRL, and SRA perform logical left, logical right, and arithmetic
-                        // right shifts on the value in register rs1 by the shift amount held in
-                        // register rs2. In RV64I, only the low 6 bits of rs2 are considered for the
-                        // shift amount."
-                        let shamt = self.xregs.read(rs2) & 0x3f;
-                        self.xregs
-                            .write(rd, ((self.xregs.read(rs1) as i64) >> shamt) as u64);
-                    }
-                    (0x6, 0x00) => {
-                        // or
-                        inst_count!(self, "or");
-                        self.debug(inst, "or");
-
-                        self.xregs
-                            .write(rd, self.xregs.read(rs1) | self.xregs.read(rs2));
-                    }
-                    (0x6, 0x01) => {
-                        // rem
-                        inst_count!(self, "rem");
-                        self.debug(inst, "rem");
-
-                        let dividend = self.xregs.read(rs1) as i64;
-                        let divisor = self.xregs.read(rs2) as i64;
-                        self.xregs.write(
-                            rd,
-                            if divisor == 0 {
-                                // Division by zero
-                                // "the remainder of division by zero equals the dividend"
-                                dividend as u64
-                            } else if dividend == i64::MIN && divisor == -1 {
-                                // Overflow
-                                // "the remainder is zero"
-                                0
-                            } else {
-                                // "provide the remainder of the corresponding division
-                                // operation"
-                                dividend.wrapping_rem(divisor) as u64
-                            },
-                        );
-                    }
-                    (0x7, 0x00) => {
-                        // and
-                        inst_count!(self, "and");
-                        self.debug(inst, "and");
-
-                        self.xregs
-                            .write(rd, self.xregs.read(rs1) & self.xregs.read(rs2));
-                    }
-                    (0x7, 0x01) => {
-                        // remu
-                        inst_count!(self, "remu");
-                        self.debug(inst, "remu");
-
-                        let dividend = self.xregs.read(rs1);
-                        let divisor = self.xregs.read(rs2);
-                        self.xregs.write(
-                            rd,
-                            if divisor == 0 {
-                                // Division by zero
-                                // "the remainder of division by zero equals the dividend"
-                                dividend
-                            } else {
-                                // "provide the remainder of the corresponding division
-                                // operation"
-                                dividend.wrapping_rem(divisor)
-                            },
-                        );
-                    }
-                    _ => {
-                        return Err(Exception::IllegalInstruction(inst));
-                    }
-                };
+          }
+          (0x2, 0x04) => {
+            // amoxor.w
+            inst_count!(self, "amoxor.w");
+            self.debug(inst, "amoxor.w");
+
+            let addr = self.xregs.read(rs1);
+            if addr % 4 != 0 {
+              return Err(Exception::LoadAddressMisaligned);
             }
-            0x37 => {
-                // RV32I
-                // lui
-                inst_count!(self, "lui");
-                self.debug(inst, "lui");
-
-                // "LUI places the U-immediate value in the top 20 bits of the destination
-                // register rd, filling in the lowest 12 bits with zeros."
-                self.xregs
-                    .write(rd, (inst & 0xfffff000) as i32 as i64 as u64);
+            let t = self.read(addr, WORD)?;
+            self.write(addr, (t as i32 ^ (self.xregs.read(rs2) as i32)) as i64 as u64, WORD)?;
+            self.xregs.write(rd, t as i32 as i64 as u64);
+          }
+          (0x3, 0x04) => {
+            // amoxor.d
+            inst_count!(self, "amoxor.d");
+            self.debug(inst, "amoxor.d");
+
+            let addr = self.xregs.read(rs1);
+            if addr % 8 != 0 {
+              return Err(Exception::LoadAddressMisaligned);
             }
-            0x3b => {
-                // RV64I and RV64M
-                match (funct3, funct7) {
-                    (0x0, 0x00) => {
-                        // addw
-                        inst_count!(self, "addw");
-                        self.debug(inst, "addw");
-
-                        self.xregs.write(
-                            rd,
-                            self.xregs.read(rs1).wrapping_add(self.xregs.read(rs2)) as i32 as i64
-                                as u64,
-                        );
-                    }
-                    (0x0, 0x01) => {
-                        // mulw
-                        inst_count!(self, "mulw");
-                        self.debug(inst, "mulw");
-
-                        let n1 = self.xregs.read(rs1) as i32;
-                        let n2 = self.xregs.read(rs2) as i32;
-                        let result = n1.wrapping_mul(n2);
-                        self.xregs.write(rd, result as i64 as u64);
-                    }
-                    (0x0, 0x20) => {
-                        // subw
-                        inst_count!(self, "subw");
-                        self.debug(inst, "subw");
-
-                        self.xregs.write(
-                            rd,
-                            ((self.xregs.read(rs1).wrapping_sub(self.xregs.read(rs2))) as i32)
-                                as u64,
-                        );
-                    }
-                    (0x1, 0x00) => {
-                        // sllw
-                        inst_count!(self, "sllw");
-                        self.debug(inst, "sllw");
-
-                        // The shift amount is given by rs2[4:0].
-                        let shamt = self.xregs.read(rs2) & 0x1f;
-                        self.xregs
-                            .write(rd, ((self.xregs.read(rs1)) << shamt) as i32 as i64 as u64);
-                    }
-                    (0x4, 0x01) => {
-                        // divw
-                        inst_count!(self, "divw");
-                        self.debug(inst, "divw");
-
-                        let dividend = self.xregs.read(rs1) as i32;
-                        let divisor = self.xregs.read(rs2) as i32;
-                        self.xregs.write(
-                            rd,
-                            if divisor == 0 {
-                                // Division by zero
-                                // Set DZ (Divide by Zero) flag to 1.
-                                self.state.write_bit(FCSR, 3, 1);
-                                // "The quotient of division by zero has all bits set"
-                                u64::MAX
-                            } else if dividend == i32::MIN && divisor == -1 {
-                                // Overflow
-                                // "The quotient of a signed division with overflow is equal to the
-                                // dividend"
-                                dividend as i64 as u64
-                            } else {
-                                // "division of rs1 by rs2, rounding towards zero"
-                                dividend.wrapping_div(divisor) as i64 as u64
-                            },
-                        );
-                    }
-                    (0x5, 0x00) => {
-                        // srlw
-                        inst_count!(self, "srlw");
-                        self.debug(inst, "srlw");
-
-                        // The shift amount is given by rs2[4:0].
-                        let shamt = self.xregs.read(rs2) & 0x1f;
-                        self.xregs.write(
-                            rd,
-                            ((self.xregs.read(rs1) as u32) >> shamt) as i32 as i64 as u64,
-                        );
-                    }
-                    (0x5, 0x01) => {
-                        // divuw
-                        inst_count!(self, "divuw");
-                        self.debug(inst, "divuw");
-
-                        let dividend = self.xregs.read(rs1) as u32;
-                        let divisor = self.xregs.read(rs2) as u32;
-                        self.xregs.write(
-                            rd,
-                            if divisor == 0 {
-                                // Division by zero
-                                // Set DZ (Divide by Zero) flag to 1.
-                                self.state.write_bit(FCSR, 3, 1);
-                                // "The quotient of division by zero has all bits set"
-                                u64::MAX
-                            } else {
-                                // "division of rs1 by rs2, rounding towards zero"
-                                dividend.wrapping_div(divisor) as i32 as i64 as u64
-                            },
-                        );
-                    }
-                    (0x5, 0x20) => {
-                        // sraw
-                        inst_count!(self, "sraw");
-                        self.debug(inst, "sraw");
-
-                        // The shift amount is given by rs2[4:0].
-                        let shamt = self.xregs.read(rs2) & 0x1f;
-                        self.xregs
-                            .write(rd, ((self.xregs.read(rs1) as i32) >> shamt) as i64 as u64);
-                    }
-                    (0x6, 0x01) => {
-                        // remw
-                        inst_count!(self, "remw");
-                        self.debug(inst, "remw");
-
-                        let dividend = self.xregs.read(rs1) as i32;
-                        let divisor = self.xregs.read(rs2) as i32;
-                        self.xregs.write(
-                            rd,
-                            if divisor == 0 {
-                                // Division by zero
-                                // "the remainder of division by zero equals the dividend"
-                                dividend as i64 as u64
-                            } else if dividend == i32::MIN && divisor == -1 {
-                                // Overflow
-                                // "the remainder is zero"
-                                0
-                            } else {
-                                // "provide the remainder of the corresponding division
-                                // operation"
-                                dividend.wrapping_rem(divisor) as i64 as u64
-                            },
-                        );
-                    }
-                    (0x7, 0x01) => {
-                        // remuw
-                        inst_count!(self, "remuw");
-                        self.debug(inst, "remuw");
-
-                        let dividend = self.xregs.read(rs1) as u32;
-                        let divisor = self.xregs.read(rs2) as u32;
-                        self.xregs.write(
-                            rd,
-                            if divisor == 0 {
-                                // Division by zero
-                                // "the remainder of division by zero equals the dividend"
-                                dividend as i32 as i64 as u64
-                            } else {
-                                // "provide the remainder of the corresponding division
-                                // operation"
-                                dividend.wrapping_rem(divisor) as i32 as i64 as u64
-                            },
-                        );
-                    }
-                    _ => {
-                        return Err(Exception::IllegalInstruction(inst));
-                    }
-                }
+            let t = self.read(addr, DOUBLEWORD)?;
+            self.write(addr, t ^ self.xregs.read(rs2), DOUBLEWORD)?;
+            self.xregs.write(rd, t);
+          }
+          (0x2, 0x08) => {
+            // amoor.w
+            inst_count!(self, "amoor.w");
+            self.debug(inst, "amoor.w");
+
+            let addr = self.xregs.read(rs1);
+            if addr % 4 != 0 {
+              return Err(Exception::LoadAddressMisaligned);
             }
-            0x43 => {
-                // RV32F and RV64F
-                // TODO: support the rounding mode encoding (rm).
-                let rs3 = ((inst & 0xf8000000) >> 27) as u64;
-                let funct2 = (inst & 0x03000000) >> 25;
-                match funct2 {
-                    0x0 => {
-                        // fmadd.s
-                        inst_count!(self, "fmadd.s");
-                        self.debug(inst, "fmadd.s");
-
-                        self.fregs.write(
-                            rd,
-                            (self.fregs.read(rs1) as f32)
-                                .mul_add(self.fregs.read(rs2) as f32, self.fregs.read(rs3) as f32)
-                                as f64,
-                        );
-                    }
-                    0x1 => {
-                        // fmadd.d
-                        inst_count!(self, "fmadd.d");
-                        self.debug(inst, "fmadd.d");
-
-                        self.fregs.write(
-                            rd,
-                            self.fregs
-                                .read(rs1)
-                                .mul_add(self.fregs.read(rs2), self.fregs.read(rs3)),
-                        );
-                    }
-                    _ => {
-                        return Err(Exception::IllegalInstruction(inst));
-                    }
-                }
+            let t = self.read(addr, WORD)?;
+            self.write(addr, (t as i32 | (self.xregs.read(rs2) as i32)) as i64 as u64, WORD)?;
+            self.xregs.write(rd, t as i32 as i64 as u64);
+          }
+          (0x3, 0x08) => {
+            // amoor.d
+            inst_count!(self, "amoor.d");
+            self.debug(inst, "amoor.d");
+
+            let addr = self.xregs.read(rs1);
+            if addr % 8 != 0 {
+              return Err(Exception::LoadAddressMisaligned);
             }
-            0x47 => {
-                // RV32F and RV64F
-                // TODO: support the rounding mode encoding (rm).
-                let rs3 = ((inst & 0xf8000000) >> 27) as u64;
-                let funct2 = (inst & 0x03000000) >> 25;
-                match funct2 {
-                    0x0 => {
-                        // fmsub.s
-                        inst_count!(self, "fmsub.s");
-                        self.debug(inst, "fmsub.s");
-
-                        self.fregs.write(
-                            rd,
-                            (self.fregs.read(rs1) as f32)
-                                .mul_add(self.fregs.read(rs2) as f32, -self.fregs.read(rs3) as f32)
-                                as f64,
-                        );
-                    }
-                    0x1 => {
-                        // fmsub.d
-                        inst_count!(self, "fmsub.d");
-                        self.debug(inst, "fmsub.d");
-
-                        self.fregs.write(
-                            rd,
-                            self.fregs
-                                .read(rs1)
-                                .mul_add(self.fregs.read(rs2), -self.fregs.read(rs3)),
-                        );
-                    }
-                    _ => {
-                        return Err(Exception::IllegalInstruction(inst));
-                    }
-                }
+            let t = self.read(addr, DOUBLEWORD)?;
+            self.write(addr, t | self.xregs.read(rs2), DOUBLEWORD)?;
+            self.xregs.write(rd, t);
+          }
+          (0x2, 0x0c) => {
+            // amoand.w
+            inst_count!(self, "amoand.w");
+            self.debug(inst, "amoand.w");
+
+            let addr = self.xregs.read(rs1);
+            if addr % 4 != 0 {
+              return Err(Exception::LoadAddressMisaligned);
             }
-            0x4b => {
-                // RV32F and RV64F
-                // TODO: support the rounding mode encoding (rm).
-                let rs3 = ((inst & 0xf8000000) >> 27) as u64;
-                let funct2 = (inst & 0x03000000) >> 25;
-                match funct2 {
-                    0x0 => {
-                        // fnmadd.s
-                        inst_count!(self, "fnmadd.s");
-                        self.debug(inst, "fnmadd.s");
-
-                        self.fregs.write(
-                            rd,
-                            (-self.fregs.read(rs1) as f32)
-                                .mul_add(self.fregs.read(rs2) as f32, self.fregs.read(rs3) as f32)
-                                as f64,
-                        );
-                    }
-                    0x1 => {
-                        // fnmadd.d
-                        inst_count!(self, "fnmadd.d");
-                        self.debug(inst, "fnmadd.d");
-
-                        self.fregs.write(
-                            rd,
-                            (-self.fregs.read(rs1))
-                                .mul_add(self.fregs.read(rs2), self.fregs.read(rs3)),
-                        );
-                    }
-                    _ => {
-                        return Err(Exception::IllegalInstruction(inst));
-                    }
-                }
+            let t = self.read(addr, WORD)?;
+            self.write(addr, (t as i32 & (self.xregs.read(rs2) as i32)) as u32 as u64, WORD)?;
+            self.xregs.write(rd, t as i32 as i64 as u64);
+          }
+          (0x3, 0x0c) => {
+            // amoand.d
+            inst_count!(self, "amoand.d");
+            self.debug(inst, "amoand.d");
+
+            let addr = self.xregs.read(rs1);
+            if addr % 8 != 0 {
+              return Err(Exception::LoadAddressMisaligned);
             }
-            0x4f => {
-                // RV32F and RV64F
-                // TODO: support the rounding mode encoding (rm).
-                let rs3 = ((inst & 0xf8000000) >> 27) as u64;
-                let funct2 = (inst & 0x03000000) >> 25;
-                match funct2 {
-                    0x0 => {
-                        // fnmsub.s
-                        inst_count!(self, "fnmsub.s");
-                        self.debug(inst, "fnmsub.s");
-
-                        self.fregs.write(
-                            rd,
-                            (-self.fregs.read(rs1) as f32)
-                                .mul_add(self.fregs.read(rs2) as f32, -self.fregs.read(rs3) as f32)
-                                as f64,
-                        );
-                    }
-                    0x1 => {
-                        // fnmsub.d
-                        inst_count!(self, "fnmsub.d");
-                        self.debug(inst, "fnmsub.d");
-
-                        self.fregs.write(
-                            rd,
-                            (-self.fregs.read(rs1))
-                                .mul_add(self.fregs.read(rs2), -self.fregs.read(rs3)),
-                        );
-                    }
-                    _ => {
-                        return Err(Exception::IllegalInstruction(inst));
-                    }
-                }
+            let t = self.read(addr, DOUBLEWORD)?;
+            self.write(addr, t & self.xregs.read(rs2), DOUBLEWORD)?;
+            self.xregs.write(rd, t);
+          }
+          (0x2, 0x10) => {
+            // amomin.w
+            inst_count!(self, "amomin.w");
+            self.debug(inst, "amomin.w");
+
+            let addr = self.xregs.read(rs1);
+            if addr % 4 != 0 {
+              return Err(Exception::LoadAddressMisaligned);
             }
-            0x53 => {
-                // RV32F and RV64F
-                // TODO: support the rounding mode encoding (rm).
-                // TODO: NaN Boxing of Narrower Values (Spec 12.2).
-                // TODO: set exception flags.
-
-                /*
-                 * Floating-point instructions align with the IEEE 754 (1985).
-                 * The format consist of three fields: a sign bit, a biased exponent, and a fraction.
-                 *
-                 * | sign(1) | exponent(8) | fraction(23) |
-                 * Ok => {}
-                 * 31                                     0
-                 *
-                 */
-
-                // Check the frm field is valid.
-                match self.state.read_bits(FCSR, 5..8) {
-                    0b000 => {}
-                    0b001 => {}
-                    0b010 => {}
-                    0b011 => {}
-                    0b100 => {}
-                    0b111 => {}
-                    _ => {
-                        return Err(Exception::IllegalInstruction(inst));
-                    }
-                }
+            let t = self.read(addr, WORD)?;
+            self.write(
+              addr,
+              cmp::min(t as i32, self.xregs.read(rs2) as i32) as i64 as u64,
+              WORD,
+            )?;
+            self.xregs.write(rd, t as i32 as i64 as u64);
+          }
+          (0x3, 0x10) => {
+            // amomin.d
+            inst_count!(self, "amomin.d");
+            self.debug(inst, "amomin.d");
+
+            let addr = self.xregs.read(rs1);
+            if addr % 8 != 0 {
+              return Err(Exception::LoadAddressMisaligned);
+            }
+            let t = self.read(addr, DOUBLEWORD)?;
+            self.write(addr, cmp::min(t as i64, self.xregs.read(rs2) as i64) as u64, DOUBLEWORD)?;
+            self.xregs.write(rd, t as u64);
+          }
+          (0x2, 0x14) => {
+            // amomax.w
+            inst_count!(self, "amomax.w");
+            self.debug(inst, "amomax.w");
+
+            let addr = self.xregs.read(rs1);
+            if addr % 4 != 0 {
+              return Err(Exception::LoadAddressMisaligned);
+            }
+            let t = self.read(addr, WORD)?;
+            self.write(
+              addr,
+              cmp::max(t as i32, self.xregs.read(rs2) as i32) as i64 as u64,
+              WORD,
+            )?;
+            self.xregs.write(rd, t as i32 as i64 as u64);
+          }
+          (0x3, 0x14) => {
+            // amomax.d
+            inst_count!(self, "amomax.d");
+            self.debug(inst, "amomax.d");
+
+            let addr = self.xregs.read(rs1);
+            if addr % 8 != 0 {
+              return Err(Exception::LoadAddressMisaligned);
+            }
+            let t = self.read(addr, DOUBLEWORD)?;
+            self.write(addr, cmp::max(t as i64, self.xregs.read(rs2) as i64) as u64, DOUBLEWORD)?;
+            self.xregs.write(rd, t);
+          }
+          (0x2, 0x18) => {
+            // amominu.w
+            inst_count!(self, "amominu.w");
+            self.debug(inst, "amominu.w");
+
+            let addr = self.xregs.read(rs1);
+            if addr % 4 != 0 {
+              return Err(Exception::LoadAddressMisaligned);
+            }
+            let t = self.read(addr, WORD)?;
+            self.write(addr, cmp::min(t as u32, self.xregs.read(rs2) as u32) as u64, WORD)?;
+            self.xregs.write(rd, t as i32 as i64 as u64);
+          }
+          (0x3, 0x18) => {
+            // amominu.d
+            inst_count!(self, "amominu.d");
+            self.debug(inst, "amominu.d");
+
+            let addr = self.xregs.read(rs1);
+            if addr % 8 != 0 {
+              return Err(Exception::LoadAddressMisaligned);
+            }
+            let t = self.read(addr, DOUBLEWORD)?;
+            self.write(addr, cmp::min(t, self.xregs.read(rs2)), DOUBLEWORD)?;
+            self.xregs.write(rd, t);
+          }
+          (0x2, 0x1c) => {
+            // amomaxu.w
+            inst_count!(self, "amomaxu.w");
+            self.debug(inst, "amomaxu.w");
+
+            let addr = self.xregs.read(rs1);
+            if addr % 4 != 0 {
+              return Err(Exception::LoadAddressMisaligned);
+            }
+            let t = self.read(addr, WORD)?;
+            self.write(addr, cmp::max(t as u32, self.xregs.read(rs2) as u32) as u64, WORD)?;
+            self.xregs.write(rd, t as i32 as i64 as u64);
+          }
+          (0x3, 0x1c) => {
+            // amomaxu.d
+            inst_count!(self, "amomaxu.d");
+            self.debug(inst, "amomaxu.d");
+
+            let addr = self.xregs.read(rs1);
+            if addr % 8 != 0 {
+              return Err(Exception::LoadAddressMisaligned);
+            }
+            let t = self.read(addr, DOUBLEWORD)?;
+            self.write(addr, cmp::max(t, self.xregs.read(rs2)), DOUBLEWORD)?;
+            self.xregs.write(rd, t);
+          }
+          _ => {
+            return Err(Exception::IllegalInstruction(inst));
+          }
+        }
+      }
+      0x33 => {
+        // RV64I and RV64M
+        match (funct3, funct7) {
+          (0x0, 0x00) => {
+            // add
+            inst_count!(self, "add");
+            self.debug(inst, "add");
+
+            self
+              .xregs
+              .write(rd, self.xregs.read(rs1).wrapping_add(self.xregs.read(rs2)));
+          }
+          (0x0, 0x01) => {
+            // mul
+            inst_count!(self, "mul");
+            self.debug(inst, "mul");
+
+            self.xregs.write(
+              rd,
+              (self.xregs.read(rs1) as i64).wrapping_mul(self.xregs.read(rs2) as i64) as u64,
+            );
+          }
+          (0x0, 0x20) => {
+            // sub
+            inst_count!(self, "sub");
+            self.debug(inst, "sub");
+
+            self
+              .xregs
+              .write(rd, self.xregs.read(rs1).wrapping_sub(self.xregs.read(rs2)));
+          }
+          (0x1, 0x00) => {
+            // sll
+            inst_count!(self, "sll");
+            self.debug(inst, "sll");
+
+            // "SLL, SRL, and SRA perform logical left, logical right, and arithmetic
+            // right shifts on the value in register rs1 by the shift amount held in
+            // register rs2. In RV64I, only the low 6 bits of rs2 are considered for the
+            // shift amount."
+            let shamt = self.xregs.read(rs2) & 0x3f;
+            self.xregs.write(rd, self.xregs.read(rs1) << shamt);
+          }
+          (0x1, 0x01) => {
+            // mulh
+            inst_count!(self, "mulh");
+            self.debug(inst, "mulh");
+
+            // signed × signed
+            self.xregs.write(
+              rd,
+              ((self.xregs.read(rs1) as i64 as i128).wrapping_mul(self.xregs.read(rs2) as i64 as i128) >> 64) as u64,
+            );
+          }
+          (0x2, 0x00) => {
+            // slt
+            inst_count!(self, "slt");
+            self.debug(inst, "slt");
+
+            self.xregs.write(
+              rd,
+              if (self.xregs.read(rs1) as i64) < (self.xregs.read(rs2) as i64) {
+                1
+              } else {
+                0
+              },
+            );
+          }
+          (0x2, 0x01) => {
+            // mulhsu
+            inst_count!(self, "mulhsu");
+            self.debug(inst, "mulhsu");
+
+            // signed × unsigned
+            self.xregs.write(
+              rd,
+              ((self.xregs.read(rs1) as i64 as i128 as u128).wrapping_mul(self.xregs.read(rs2) as u128) >> 64) as u64,
+            );
+          }
+          (0x3, 0x00) => {
+            // sltu
+            inst_count!(self, "sltu");
+            self.debug(inst, "sltu");
+
+            self.xregs.write(
+              rd,
+              if self.xregs.read(rs1) < self.xregs.read(rs2) {
+                1
+              } else {
+                0
+              },
+            );
+          }
+          (0x3, 0x01) => {
+            // mulhu
+            inst_count!(self, "mulhu");
+            self.debug(inst, "mulhu");
+
+            // unsigned × unsigned
+            self.xregs.write(
+              rd,
+              ((self.xregs.read(rs1) as u128).wrapping_mul(self.xregs.read(rs2) as u128) >> 64) as u64,
+            );
+          }
+          (0x4, 0x00) => {
+            // xor
+            inst_count!(self, "xor");
+            self.debug(inst, "xor");
+
+            self.xregs.write(rd, self.xregs.read(rs1) ^ self.xregs.read(rs2));
+          }
+          (0x4, 0x01) => {
+            // div
+            inst_count!(self, "div");
+            self.debug(inst, "div");
+
+            let dividend = self.xregs.read(rs1) as i64;
+            let divisor = self.xregs.read(rs2) as i64;
+            self.xregs.write(
+              rd,
+              if divisor == 0 {
+                // Division by zero
+                // Set DZ (Divide by Zero) flag to 1.
+                self.state.write_bit(FCSR, 3, 1);
+                // "The quotient of division by zero has all bits set"
+                u64::MAX
+              } else if dividend == i64::MIN && divisor == -1 {
+                // Overflow
+                // "The quotient of a signed division with overflow is equal to the
+                // dividend"
+                dividend as u64
+              } else {
+                // "division of rs1 by rs2, rounding towards zero"
+                dividend.wrapping_div(divisor) as u64
+              },
+            );
+          }
+          (0x5, 0x00) => {
+            // srl
+            inst_count!(self, "srl");
+            self.debug(inst, "srl");
+
+            // "SLL, SRL, and SRA perform logical left, logical right, and arithmetic
+            // right shifts on the value in register rs1 by the shift amount held in
+            // register rs2. In RV64I, only the low 6 bits of rs2 are considered for the
+            // shift amount."
+            let shamt = self.xregs.read(rs2) & 0x3f;
+            self.xregs.write(rd, self.xregs.read(rs1) >> shamt);
+          }
+          (0x5, 0x01) => {
+            // divu
+            inst_count!(self, "divu");
+            self.debug(inst, "divu");
+
+            let dividend = self.xregs.read(rs1);
+            let divisor = self.xregs.read(rs2);
+            self.xregs.write(
+              rd,
+              if divisor == 0 {
+                // Division by zero
+                // Set DZ (Divide by Zero) flag to 1.
+                self.state.write_bit(FCSR, 3, 1);
+                // "The quotient of division by zero has all bits set"
+                u64::MAX
+              } else {
+                // "division of rs1 by rs2, rounding towards zero"
+                dividend.wrapping_div(divisor)
+              },
+            );
+          }
+          (0x5, 0x20) => {
+            // sra
+            inst_count!(self, "sra");
+            self.debug(inst, "sra");
+
+            // "SLL, SRL, and SRA perform logical left, logical right, and arithmetic
+            // right shifts on the value in register rs1 by the shift amount held in
+            // register rs2. In RV64I, only the low 6 bits of rs2 are considered for the
+            // shift amount."
+            let shamt = self.xregs.read(rs2) & 0x3f;
+            self.xregs.write(rd, ((self.xregs.read(rs1) as i64) >> shamt) as u64);
+          }
+          (0x6, 0x00) => {
+            // or
+            inst_count!(self, "or");
+            self.debug(inst, "or");
+
+            self.xregs.write(rd, self.xregs.read(rs1) | self.xregs.read(rs2));
+          }
+          (0x6, 0x01) => {
+            // rem
+            inst_count!(self, "rem");
+            self.debug(inst, "rem");
+
+            let dividend = self.xregs.read(rs1) as i64;
+            let divisor = self.xregs.read(rs2) as i64;
+            self.xregs.write(
+              rd,
+              if divisor == 0 {
+                // Division by zero
+                // "the remainder of division by zero equals the dividend"
+                dividend as u64
+              } else if dividend == i64::MIN && divisor == -1 {
+                // Overflow
+                // "the remainder is zero"
+                0
+              } else {
+                // "provide the remainder of the corresponding division
+                // operation"
+                dividend.wrapping_rem(divisor) as u64
+              },
+            );
+          }
+          (0x7, 0x00) => {
+            // and
+            inst_count!(self, "and");
+            self.debug(inst, "and");
+
+            self.xregs.write(rd, self.xregs.read(rs1) & self.xregs.read(rs2));
+          }
+          (0x7, 0x01) => {
+            // remu
+            inst_count!(self, "remu");
+            self.debug(inst, "remu");
+
+            let dividend = self.xregs.read(rs1);
+            let divisor = self.xregs.read(rs2);
+            self.xregs.write(
+              rd,
+              if divisor == 0 {
+                // Division by zero
+                // "the remainder of division by zero equals the dividend"
+                dividend
+              } else {
+                // "provide the remainder of the corresponding division
+                // operation"
+                dividend.wrapping_rem(divisor)
+              },
+            );
+          }
+          _ => {
+            return Err(Exception::IllegalInstruction(inst));
+          }
+        };
+      }
+      0x37 => {
+        // RV32I
+        // lui
+        inst_count!(self, "lui");
+        self.debug(inst, "lui");
+
+        // "LUI places the U-immediate value in the top 20 bits of the destination
+        // register rd, filling in the lowest 12 bits with zeros."
+        self.xregs.write(rd, (inst & 0xfffff000) as i32 as i64 as u64);
+      }
+      0x3b => {
+        // RV64I and RV64M
+        match (funct3, funct7) {
+          (0x0, 0x00) => {
+            // addw
+            inst_count!(self, "addw");
+            self.debug(inst, "addw");
+
+            self.xregs.write(
+              rd,
+              self.xregs.read(rs1).wrapping_add(self.xregs.read(rs2)) as i32 as i64 as u64,
+            );
+          }
+          (0x0, 0x01) => {
+            // mulw
+            inst_count!(self, "mulw");
+            self.debug(inst, "mulw");
+
+            let n1 = self.xregs.read(rs1) as i32;
+            let n2 = self.xregs.read(rs2) as i32;
+            let result = n1.wrapping_mul(n2);
+            self.xregs.write(rd, result as i64 as u64);
+          }
+          (0x0, 0x20) => {
+            // subw
+            inst_count!(self, "subw");
+            self.debug(inst, "subw");
+
+            self.xregs.write(
+              rd,
+              ((self.xregs.read(rs1).wrapping_sub(self.xregs.read(rs2))) as i32) as u64,
+            );
+          }
+          (0x1, 0x00) => {
+            // sllw
+            inst_count!(self, "sllw");
+            self.debug(inst, "sllw");
+
+            // The shift amount is given by rs2[4:0].
+            let shamt = self.xregs.read(rs2) & 0x1f;
+            self
+              .xregs
+              .write(rd, ((self.xregs.read(rs1)) << shamt) as i32 as i64 as u64);
+          }
+          (0x4, 0x01) => {
+            // divw
+            inst_count!(self, "divw");
+            self.debug(inst, "divw");
+
+            let dividend = self.xregs.read(rs1) as i32;
+            let divisor = self.xregs.read(rs2) as i32;
+            self.xregs.write(
+              rd,
+              if divisor == 0 {
+                // Division by zero
+                // Set DZ (Divide by Zero) flag to 1.
+                self.state.write_bit(FCSR, 3, 1);
+                // "The quotient of division by zero has all bits set"
+                u64::MAX
+              } else if dividend == i32::MIN && divisor == -1 {
+                // Overflow
+                // "The quotient of a signed division with overflow is equal to the
+                // dividend"
+                dividend as i64 as u64
+              } else {
+                // "division of rs1 by rs2, rounding towards zero"
+                dividend.wrapping_div(divisor) as i64 as u64
+              },
+            );
+          }
+          (0x5, 0x00) => {
+            // srlw
+            inst_count!(self, "srlw");
+            self.debug(inst, "srlw");
+
+            // The shift amount is given by rs2[4:0].
+            let shamt = self.xregs.read(rs2) & 0x1f;
+            self
+              .xregs
+              .write(rd, ((self.xregs.read(rs1) as u32) >> shamt) as i32 as i64 as u64);
+          }
+          (0x5, 0x01) => {
+            // divuw
+            inst_count!(self, "divuw");
+            self.debug(inst, "divuw");
+
+            let dividend = self.xregs.read(rs1) as u32;
+            let divisor = self.xregs.read(rs2) as u32;
+            self.xregs.write(
+              rd,
+              if divisor == 0 {
+                // Division by zero
+                // Set DZ (Divide by Zero) flag to 1.
+                self.state.write_bit(FCSR, 3, 1);
+                // "The quotient of division by zero has all bits set"
+                u64::MAX
+              } else {
+                // "division of rs1 by rs2, rounding towards zero"
+                dividend.wrapping_div(divisor) as i32 as i64 as u64
+              },
+            );
+          }
+          (0x5, 0x20) => {
+            // sraw
+            inst_count!(self, "sraw");
+            self.debug(inst, "sraw");
+
+            // The shift amount is given by rs2[4:0].
+            let shamt = self.xregs.read(rs2) & 0x1f;
+            self
+              .xregs
+              .write(rd, ((self.xregs.read(rs1) as i32) >> shamt) as i64 as u64);
+          }
+          (0x6, 0x01) => {
+            // remw
+            inst_count!(self, "remw");
+            self.debug(inst, "remw");
+
+            let dividend = self.xregs.read(rs1) as i32;
+            let divisor = self.xregs.read(rs2) as i32;
+            self.xregs.write(
+              rd,
+              if divisor == 0 {
+                // Division by zero
+                // "the remainder of division by zero equals the dividend"
+                dividend as i64 as u64
+              } else if dividend == i32::MIN && divisor == -1 {
+                // Overflow
+                // "the remainder is zero"
+                0
+              } else {
+                // "provide the remainder of the corresponding division
+                // operation"
+                dividend.wrapping_rem(divisor) as i64 as u64
+              },
+            );
+          }
+          (0x7, 0x01) => {
+            // remuw
+            inst_count!(self, "remuw");
+            self.debug(inst, "remuw");
+
+            let dividend = self.xregs.read(rs1) as u32;
+            let divisor = self.xregs.read(rs2) as u32;
+            self.xregs.write(
+              rd,
+              if divisor == 0 {
+                // Division by zero
+                // "the remainder of division by zero equals the dividend"
+                dividend as i32 as i64 as u64
+              } else {
+                // "provide the remainder of the corresponding division
+                // operation"
+                dividend.wrapping_rem(divisor) as i32 as i64 as u64
+              },
+            );
+          }
+          _ => {
+            return Err(Exception::IllegalInstruction(inst));
+          }
+        }
+      }
+      0x43 => {
+        // RV32F and RV64F
+        // TODO: support the rounding mode encoding (rm).
+        let rs3 = ((inst & 0xf8000000) >> 27) as u64;
+        let funct2 = (inst & 0x03000000) >> 25;
+        match funct2 {
+          0x0 => {
+            // fmadd.s
+            inst_count!(self, "fmadd.s");
+            self.debug(inst, "fmadd.s");
+
+            self.fregs.write(
+              rd,
+              (self.fregs.read(rs1) as f32).mul_add(self.fregs.read(rs2) as f32, self.fregs.read(rs3) as f32) as f64,
+            );
+          }
+          0x1 => {
+            // fmadd.d
+            inst_count!(self, "fmadd.d");
+            self.debug(inst, "fmadd.d");
+
+            self.fregs.write(
+              rd,
+              self.fregs.read(rs1).mul_add(self.fregs.read(rs2), self.fregs.read(rs3)),
+            );
+          }
+          _ => {
+            return Err(Exception::IllegalInstruction(inst));
+          }
+        }
+      }
+      0x47 => {
+        // RV32F and RV64F
+        // TODO: support the rounding mode encoding (rm).
+        let rs3 = ((inst & 0xf8000000) >> 27) as u64;
+        let funct2 = (inst & 0x03000000) >> 25;
+        match funct2 {
+          0x0 => {
+            // fmsub.s
+            inst_count!(self, "fmsub.s");
+            self.debug(inst, "fmsub.s");
+
+            self.fregs.write(
+              rd,
+              (self.fregs.read(rs1) as f32).mul_add(self.fregs.read(rs2) as f32, -self.fregs.read(rs3) as f32) as f64,
+            );
+          }
+          0x1 => {
+            // fmsub.d
+            inst_count!(self, "fmsub.d");
+            self.debug(inst, "fmsub.d");
+
+            self.fregs.write(
+              rd,
+              self
+                .fregs
+                .read(rs1)
+                .mul_add(self.fregs.read(rs2), -self.fregs.read(rs3)),
+            );
+          }
+          _ => {
+            return Err(Exception::IllegalInstruction(inst));
+          }
+        }
+      }
+      0x4b => {
+        // RV32F and RV64F
+        // TODO: support the rounding mode encoding (rm).
+        let rs3 = ((inst & 0xf8000000) >> 27) as u64;
+        let funct2 = (inst & 0x03000000) >> 25;
+        match funct2 {
+          0x0 => {
+            // fnmadd.s
+            inst_count!(self, "fnmadd.s");
+            self.debug(inst, "fnmadd.s");
+
+            self.fregs.write(
+              rd,
+              (-self.fregs.read(rs1) as f32).mul_add(self.fregs.read(rs2) as f32, self.fregs.read(rs3) as f32) as f64,
+            );
+          }
+          0x1 => {
+            // fnmadd.d
+            inst_count!(self, "fnmadd.d");
+            self.debug(inst, "fnmadd.d");
+
+            self.fregs.write(
+              rd,
+              (-self.fregs.read(rs1)).mul_add(self.fregs.read(rs2), self.fregs.read(rs3)),
+            );
+          }
+          _ => {
+            return Err(Exception::IllegalInstruction(inst));
+          }
+        }
+      }
+      0x4f => {
+        // RV32F and RV64F
+        // TODO: support the rounding mode encoding (rm).
+        let rs3 = ((inst & 0xf8000000) >> 27) as u64;
+        let funct2 = (inst & 0x03000000) >> 25;
+        match funct2 {
+          0x0 => {
+            // fnmsub.s
+            inst_count!(self, "fnmsub.s");
+            self.debug(inst, "fnmsub.s");
+
+            self.fregs.write(
+              rd,
+              (-self.fregs.read(rs1) as f32).mul_add(self.fregs.read(rs2) as f32, -self.fregs.read(rs3) as f32) as f64,
+            );
+          }
+          0x1 => {
+            // fnmsub.d
+            inst_count!(self, "fnmsub.d");
+            self.debug(inst, "fnmsub.d");
+
+            self.fregs.write(
+              rd,
+              (-self.fregs.read(rs1)).mul_add(self.fregs.read(rs2), -self.fregs.read(rs3)),
+            );
+          }
+          _ => {
+            return Err(Exception::IllegalInstruction(inst));
+          }
+        }
+      }
+      0x53 => {
+        // RV32F and RV64F
+        // TODO: support the rounding mode encoding (rm).
+        // TODO: NaN Boxing of Narrower Values (Spec 12.2).
+        // TODO: set exception flags.
+
+        /*
+         * Floating-point instructions align with the IEEE 754 (1985).
+         * The format consist of three fields: a sign bit, a biased exponent, and a fraction.
+         *
+         * | sign(1) | exponent(8) | fraction(23) |
+         * Ok => {}
+         * 31                                     0
+         *
+         */
+
+        // Check the frm field is valid.
+        match self.state.read_bits(FCSR, 5..8) {
+          0b000 => {}
+          0b001 => {}
+          0b010 => {}
+          0b011 => {}
+          0b100 => {}
+          0b111 => {}
+          _ => {
+            return Err(Exception::IllegalInstruction(inst));
+          }
+        }
 
-                match funct7 {
-                    0x00 => {
-                        // fadd.s
-                        inst_count!(self, "fadd.s");
-                        self.debug(inst, "fadd.s");
-
-                        self.fregs.write(
-                            rd,
-                            (self.fregs.read(rs1) as f32 + self.fregs.read(rs2) as f32) as f64,
-                        )
-                    }
-                    0x01 => {
-                        // fadd.d
-                        inst_count!(self, "fadd.d");
-                        self.debug(inst, "fadd.d");
-
-                        self.fregs
-                            .write(rd, self.fregs.read(rs1) + self.fregs.read(rs2));
-                    }
-                    0x04 => {
-                        // fsub.s
-                        inst_count!(self, "fsub.s");
-                        self.debug(inst, "fsub.s");
-
-                        self.fregs.write(
-                            rd,
-                            (self.fregs.read(rs1) as f32 - self.fregs.read(rs2) as f32) as f64,
-                        )
-                    }
-                    0x05 => {
-                        // fsub.d
-                        inst_count!(self, "fsub.d");
-                        self.debug(inst, "fsub.d");
-
-                        self.fregs
-                            .write(rd, self.fregs.read(rs1) - self.fregs.read(rs2));
-                    }
-                    0x08 => {
-                        // fmul.s
-                        inst_count!(self, "fmul.s");
-                        self.debug(inst, "fmul.s");
-
-                        self.fregs.write(
-                            rd,
-                            (self.fregs.read(rs1) as f32 * self.fregs.read(rs2) as f32) as f64,
-                        )
-                    }
-                    0x09 => {
-                        // fmul.d
-                        inst_count!(self, "fmul.d");
-                        self.debug(inst, "fmul.d");
-
-                        self.fregs
-                            .write(rd, self.fregs.read(rs1) * self.fregs.read(rs2));
-                    }
-                    0x0c => {
-                        // fdiv.s
-                        inst_count!(self, "fdiv.s");
-                        self.debug(inst, "fdiv.s");
-
-                        self.fregs.write(
-                            rd,
-                            (self.fregs.read(rs1) as f32 / self.fregs.read(rs2) as f32) as f64,
-                        )
-                    }
-                    0x0d => {
-                        // fdiv.d
-                        inst_count!(self, "fdiv.d");
-                        self.debug(inst, "fdiv.d");
-
-                        self.fregs
-                            .write(rd, self.fregs.read(rs1) / self.fregs.read(rs2));
-                    }
-                    0x10 => {
-                        match funct3 {
-                            0x0 => {
-                                // fsgnj.s
-                                inst_count!(self, "fsgnj.s");
-                                self.debug(inst, "fsgnj.s");
-
-                                self.fregs
-                                    .write(rd, self.fregs.read(rs1).copysign(self.fregs.read(rs2)));
-                            }
-                            0x1 => {
-                                // fsgnjn.s
-                                inst_count!(self, "fsgnjn.s");
-                                self.debug(inst, "fsgnjn.s");
-
-                                self.fregs.write(
-                                    rd,
-                                    self.fregs.read(rs1).copysign(-self.fregs.read(rs2)),
-                                );
-                            }
-                            0x2 => {
-                                // fsgnjx.s
-                                inst_count!(self, "fsgnjx.s");
-                                self.debug(inst, "fsgnjx.s");
-
-                                let sign1 = (self.fregs.read(rs1) as f32).to_bits() & 0x80000000;
-                                let sign2 = (self.fregs.read(rs2) as f32).to_bits() & 0x80000000;
-                                let other = (self.fregs.read(rs1) as f32).to_bits() & 0x7fffffff;
-                                self.fregs
-                                    .write(rd, f32::from_bits((sign1 ^ sign2) | other) as f64);
-                            }
-                            _ => {
-                                return Err(Exception::IllegalInstruction(inst));
-                            }
-                        }
-                    }
-                    0x11 => {
-                        match funct3 {
-                            0x0 => {
-                                // fsgnj.d
-                                inst_count!(self, "fsgnj.d");
-                                self.debug(inst, "fsgnj.d");
-
-                                self.fregs
-                                    .write(rd, self.fregs.read(rs1).copysign(self.fregs.read(rs2)));
-                            }
-                            0x1 => {
-                                // fsgnjn.d
-                                inst_count!(self, "fsgnjn.d");
-                                self.debug(inst, "fsgnjn.d");
-
-                                self.fregs.write(
-                                    rd,
-                                    self.fregs.read(rs1).copysign(-self.fregs.read(rs2)),
-                                );
-                            }
-                            0x2 => {
-                                // fsgnjx.d
-                                inst_count!(self, "fsgnjx.d");
-                                self.debug(inst, "fsgnjx.d");
-
-                                let sign1 = self.fregs.read(rs1).to_bits() & 0x80000000_00000000;
-                                let sign2 = self.fregs.read(rs2).to_bits() & 0x80000000_00000000;
-                                let other = self.fregs.read(rs1).to_bits() & 0x7fffffff_ffffffff;
-                                self.fregs
-                                    .write(rd, f64::from_bits((sign1 ^ sign2) | other));
-                            }
-                            _ => {
-                                return Err(Exception::IllegalInstruction(inst));
-                            }
-                        }
-                    }
-                    0x14 => {
-                        match funct3 {
-                            0x0 => {
-                                // fmin.s
-                                inst_count!(self, "fmin.s");
-                                self.debug(inst, "fmin.s");
-
-                                self.fregs
-                                    .write(rd, self.fregs.read(rs1).min(self.fregs.read(rs2)));
-                            }
-                            0x1 => {
-                                // fmax.s
-                                inst_count!(self, "fmax.s");
-                                self.debug(inst, "fmax.s");
-
-                                self.fregs
-                                    .write(rd, self.fregs.read(rs1).max(self.fregs.read(rs2)));
-                            }
-                            _ => {
-                                return Err(Exception::IllegalInstruction(inst));
-                            }
-                        }
-                    }
-                    0x15 => {
-                        match funct3 {
-                            0x0 => {
-                                // fmin.d
-                                inst_count!(self, "fmin.d");
-                                self.debug(inst, "fmin.d");
-
-                                self.fregs
-                                    .write(rd, self.fregs.read(rs1).min(self.fregs.read(rs2)));
-                            }
-                            0x1 => {
-                                // fmax.d
-                                inst_count!(self, "fmax.d");
-                                self.debug(inst, "fmax.d");
-
-                                self.fregs
-                                    .write(rd, self.fregs.read(rs1).max(self.fregs.read(rs2)));
-                            }
-                            _ => {
-                                return Err(Exception::IllegalInstruction(inst));
-                            }
-                        }
-                    }
-                    0x20 => {
-                        // fcvt.s.d
-                        inst_count!(self, "fcvt.s.d");
-                        self.debug(inst, "fcvt.s.d");
-
-                        self.fregs.write(rd, self.fregs.read(rs1));
-                    }
-                    0x21 => {
-                        // fcvt.d.s
-                        inst_count!(self, "fcvt.d.s");
-                        self.debug(inst, "fcvt.d.s");
-
-                        self.fregs.write(rd, (self.fregs.read(rs1) as f32) as f64);
-                    }
-                    0x2c => {
-                        // fsqrt.s
-                        inst_count!(self, "fsqrt.s");
-                        self.debug(inst, "fsqrt.s");
-
-                        self.fregs
-                            .write(rd, (self.fregs.read(rs1) as f32).sqrt() as f64);
-                    }
-                    0x2d => {
-                        // fsqrt.d
-                        inst_count!(self, "fsqrt.d");
-                        self.debug(inst, "fsqrt.d");
-
-                        self.fregs.write(rd, self.fregs.read(rs1).sqrt());
-                    }
-                    0x50 => {
-                        match funct3 {
-                            0x0 => {
-                                // fle.s
-                                inst_count!(self, "fle.s");
-                                self.debug(inst, "fle.s");
-
-                                self.xregs.write(
-                                    rd,
-                                    if self.fregs.read(rs1) <= self.fregs.read(rs2) {
-                                        1
-                                    } else {
-                                        0
-                                    },
-                                );
-                            }
-                            0x1 => {
-                                // flt.s
-                                inst_count!(self, "flt.s");
-                                self.debug(inst, "flt.s");
-
-                                self.xregs.write(
-                                    rd,
-                                    if self.fregs.read(rs1) < self.fregs.read(rs2) {
-                                        1
-                                    } else {
-                                        0
-                                    },
-                                );
-                            }
-                            0x2 => {
-                                // feq.s
-                                inst_count!(self, "feq.s");
-                                self.debug(inst, "feq.s");
-
-                                self.xregs.write(
-                                    rd,
-                                    if self.fregs.read(rs1) == self.fregs.read(rs2) {
-                                        1
-                                    } else {
-                                        0
-                                    },
-                                );
-                            }
-                            _ => {
-                                return Err(Exception::IllegalInstruction(inst));
-                            }
-                        }
-                    }
-                    0x51 => {
-                        match funct3 {
-                            0x0 => {
-                                // fle.d
-                                inst_count!(self, "fle.d");
-                                self.debug(inst, "fle.d");
-
-                                self.xregs.write(
-                                    rd,
-                                    if self.fregs.read(rs1) <= self.fregs.read(rs2) {
-                                        1
-                                    } else {
-                                        0
-                                    },
-                                );
-                            }
-                            0x1 => {
-                                // flt.d
-                                inst_count!(self, "flt.d");
-                                self.debug(inst, "flt.d");
-
-                                self.xregs.write(
-                                    rd,
-                                    if self.fregs.read(rs1) < self.fregs.read(rs2) {
-                                        1
-                                    } else {
-                                        0
-                                    },
-                                );
-                            }
-                            0x2 => {
-                                // feq.d
-                                inst_count!(self, "feq.d");
-                                self.debug(inst, "feq.d");
-
-                                self.xregs.write(
-                                    rd,
-                                    if self.fregs.read(rs1) == self.fregs.read(rs2) {
-                                        1
-                                    } else {
-                                        0
-                                    },
-                                );
-                            }
-                            _ => {
-                                return Err(Exception::IllegalInstruction(inst));
-                            }
-                        }
-                    }
-                    0x60 => {
-                        match rs2 {
-                            0x0 => {
-                                // fcvt.w.s
-                                inst_count!(self, "fcvt.w.s");
-                                self.debug(inst, "fcvt.w.s");
-
-                                self.xregs.write(
-                                    rd,
-                                    ((self.fregs.read(rs1) as f32).round() as i32) as u64,
-                                );
-                            }
-                            0x1 => {
-                                // fcvt.wu.s
-                                inst_count!(self, "fcvt.wu.s");
-                                self.debug(inst, "fcvt.wu.s");
-
-                                self.xregs.write(
-                                    rd,
-                                    (((self.fregs.read(rs1) as f32).round() as u32) as i32) as u64,
-                                );
-                            }
-                            0x2 => {
-                                // fcvt.l.s
-                                inst_count!(self, "fcvt.l.s");
-                                self.debug(inst, "fcvt.l.s");
-
-                                self.xregs
-                                    .write(rd, (self.fregs.read(rs1) as f32).round() as u64);
-                            }
-                            0x3 => {
-                                // fcvt.lu.s
-                                inst_count!(self, "fcvt.lu.s");
-                                self.debug(inst, "fcvt.lu.s");
-
-                                self.xregs
-                                    .write(rd, (self.fregs.read(rs1) as f32).round() as u64);
-                            }
-                            _ => {
-                                return Err(Exception::IllegalInstruction(inst));
-                            }
-                        }
-                    }
-                    0x61 => {
-                        match rs2 {
-                            0x0 => {
-                                // fcvt.w.d
-                                inst_count!(self, "fcvt.w.d");
-                                self.debug(inst, "fcvt.w.d");
-
-                                self.xregs
-                                    .write(rd, (self.fregs.read(rs1).round() as i32) as u64);
-                            }
-                            0x1 => {
-                                // fcvt.wu.d
-                                inst_count!(self, "fcvt.wu.d");
-                                self.debug(inst, "fcvt.wu.d");
-
-                                self.xregs.write(
-                                    rd,
-                                    ((self.fregs.read(rs1).round() as u32) as i32) as u64,
-                                );
-                            }
-                            0x2 => {
-                                // fcvt.l.d
-                                inst_count!(self, "fcvt.l.d");
-                                self.debug(inst, "fcvt.l.d");
-
-                                self.xregs.write(rd, self.fregs.read(rs1).round() as u64);
-                            }
-                            0x3 => {
-                                // fcvt.lu.d
-                                inst_count!(self, "fcvt.lu.d");
-                                self.debug(inst, "fcvt.lu.d");
-
-                                self.xregs.write(rd, self.fregs.read(rs1).round() as u64);
-                            }
-                            _ => {
-                                return Err(Exception::IllegalInstruction(inst));
-                            }
-                        }
-                    }
-                    0x68 => {
-                        match rs2 {
-                            0x0 => {
-                                // fcvt.s.w
-                                inst_count!(self, "fcvt.s.w");
-                                self.debug(inst, "fcvt.s.w");
-
-                                self.fregs
-                                    .write(rd, ((self.xregs.read(rs1) as i32) as f32) as f64);
-                            }
-                            0x1 => {
-                                // fcvt.s.wu
-                                inst_count!(self, "fcvt.s.wu");
-                                self.debug(inst, "fcvt.s.wu");
-
-                                self.fregs
-                                    .write(rd, ((self.xregs.read(rs1) as u32) as f32) as f64);
-                            }
-                            0x2 => {
-                                // fcvt.s.l
-                                inst_count!(self, "fcvt.s.l");
-                                self.debug(inst, "fcvt.s.l");
-
-                                self.fregs.write(rd, (self.xregs.read(rs1) as f32) as f64);
-                            }
-                            0x3 => {
-                                // fcvt.s.lu
-                                inst_count!(self, "fcvt.s.lu");
-                                self.debug(inst, "fcvt.s.lu");
-
-                                self.fregs
-                                    .write(rd, ((self.xregs.read(rs1) as u64) as f32) as f64);
-                            }
-                            _ => {
-                                return Err(Exception::IllegalInstruction(inst));
-                            }
-                        }
-                    }
-                    0x69 => {
-                        match rs2 {
-                            0x0 => {
-                                // fcvt.d.w
-                                inst_count!(self, "fcvt.d.w");
-                                self.debug(inst, "fcvt.d.w");
-
-                                self.fregs.write(rd, (self.xregs.read(rs1) as i32) as f64);
-                            }
-                            0x1 => {
-                                // fcvt.d.wu
-                                inst_count!(self, "fcvt.d.wu");
-                                self.debug(inst, "fcvt.d.wu");
-
-                                self.fregs.write(rd, (self.xregs.read(rs1) as u32) as f64);
-                            }
-                            0x2 => {
-                                // fcvt.d.l
-                                inst_count!(self, "fcvt.d.l");
-                                self.debug(inst, "fcvt.d.l");
-
-                                self.fregs.write(rd, self.xregs.read(rs1) as f64);
-                            }
-                            0x3 => {
-                                // fcvt.d.lu
-                                inst_count!(self, "fcvt.d.lu");
-                                self.debug(inst, "fcvt.d.lu");
-
-                                self.fregs.write(rd, self.xregs.read(rs1) as f64);
-                            }
-                            _ => {
-                                return Err(Exception::IllegalInstruction(inst));
-                            }
-                        }
-                    }
-                    0x70 => {
-                        match funct3 {
-                            0x0 => {
-                                // fmv.x.w
-                                inst_count!(self, "fmv.x.w");
-                                self.debug(inst, "fmv.x.w");
-
-                                self.xregs.write(
-                                    rd,
-                                    (self.fregs.read(rs1).to_bits() & 0xffffffff) as i32 as i64
-                                        as u64,
-                                );
-                            }
-                            0x1 => {
-                                // fclass.s
-                                inst_count!(self, "fclass.s");
-                                self.debug(inst, "fclass.s");
-
-                                let f = self.fregs.read(rs1);
-                                match f.classify() {
-                                    FpCategory::Infinite => {
-                                        self.xregs
-                                            .write(rd, if f.is_sign_negative() { 0 } else { 7 });
-                                    }
-                                    FpCategory::Normal => {
-                                        self.xregs
-                                            .write(rd, if f.is_sign_negative() { 1 } else { 6 });
-                                    }
-                                    FpCategory::Subnormal => {
-                                        self.xregs
-                                            .write(rd, if f.is_sign_negative() { 2 } else { 5 });
-                                    }
-                                    FpCategory::Zero => {
-                                        self.xregs
-                                            .write(rd, if f.is_sign_negative() { 3 } else { 4 });
-                                    }
-                                    // don't support a signaling nan, only support a quiet nan.
-                                    FpCategory::Nan => self.xregs.write(rd, 9),
-                                }
-                            }
-                            _ => {
-                                return Err(Exception::IllegalInstruction(inst));
-                            }
-                        }
-                    }
-                    0x71 => {
-                        match funct3 {
-                            0x0 => {
-                                // fmv.x.d
-                                inst_count!(self, "fmv.x.d");
-                                self.debug(inst, "fmv.x.d");
-
-                                // "FMV.X.D and FMV.D.X do not modify the bits being transferred"
-                                self.xregs.write(rd, self.fregs.read(rs1).to_bits());
-                            }
-                            0x1 => {
-                                // fclass.d
-                                inst_count!(self, "fclass.d");
-                                self.debug(inst, "fclass.d");
-
-                                let f = self.fregs.read(rs1);
-                                match f.classify() {
-                                    FpCategory::Infinite => {
-                                        self.xregs
-                                            .write(rd, if f.is_sign_negative() { 0 } else { 7 });
-                                    }
-                                    FpCategory::Normal => {
-                                        self.xregs
-                                            .write(rd, if f.is_sign_negative() { 1 } else { 6 });
-                                    }
-                                    FpCategory::Subnormal => {
-                                        self.xregs
-                                            .write(rd, if f.is_sign_negative() { 2 } else { 5 });
-                                    }
-                                    FpCategory::Zero => {
-                                        self.xregs
-                                            .write(rd, if f.is_sign_negative() { 3 } else { 4 });
-                                    }
-                                    // don't support a signaling nan, only support a quiet nan.
-                                    FpCategory::Nan => self.xregs.write(rd, 9),
-                                }
-                            }
-                            _ => {
-                                return Err(Exception::IllegalInstruction(inst));
-                            }
-                        }
-                    }
-                    0x78 => {
-                        // fmv.w.x
-                        inst_count!(self, "fmv.w.x");
-                        self.debug(inst, "fmv.w.x");
-
-                        self.fregs
-                            .write(rd, f64::from_bits(self.xregs.read(rs1) & 0xffffffff));
-                    }
-                    0x79 => {
-                        // fmv.d.x
-                        inst_count!(self, "fmv.d.x");
-                        self.debug(inst, "fmv.d.x");
-
-                        // "FMV.X.D and FMV.D.X do not modify the bits being transferred"
-                        self.fregs.write(rd, f64::from_bits(self.xregs.read(rs1)));
-                    }
-                    _ => {
-                        return Err(Exception::IllegalInstruction(inst));
-                    }
+        match funct7 {
+          0x00 => {
+            // fadd.s
+            inst_count!(self, "fadd.s");
+            self.debug(inst, "fadd.s");
+
+            self
+              .fregs
+              .write(rd, (self.fregs.read(rs1) as f32 + self.fregs.read(rs2) as f32) as f64)
+          }
+          0x01 => {
+            // fadd.d
+            inst_count!(self, "fadd.d");
+            self.debug(inst, "fadd.d");
+
+            self.fregs.write(rd, self.fregs.read(rs1) + self.fregs.read(rs2));
+          }
+          0x04 => {
+            // fsub.s
+            inst_count!(self, "fsub.s");
+            self.debug(inst, "fsub.s");
+
+            self
+              .fregs
+              .write(rd, (self.fregs.read(rs1) as f32 - self.fregs.read(rs2) as f32) as f64)
+          }
+          0x05 => {
+            // fsub.d
+            inst_count!(self, "fsub.d");
+            self.debug(inst, "fsub.d");
+
+            self.fregs.write(rd, self.fregs.read(rs1) - self.fregs.read(rs2));
+          }
+          0x08 => {
+            // fmul.s
+            inst_count!(self, "fmul.s");
+            self.debug(inst, "fmul.s");
+
+            self
+              .fregs
+              .write(rd, (self.fregs.read(rs1) as f32 * self.fregs.read(rs2) as f32) as f64)
+          }
+          0x09 => {
+            // fmul.d
+            inst_count!(self, "fmul.d");
+            self.debug(inst, "fmul.d");
+
+            self.fregs.write(rd, self.fregs.read(rs1) * self.fregs.read(rs2));
+          }
+          0x0c => {
+            // fdiv.s
+            inst_count!(self, "fdiv.s");
+            self.debug(inst, "fdiv.s");
+
+            self
+              .fregs
+              .write(rd, (self.fregs.read(rs1) as f32 / self.fregs.read(rs2) as f32) as f64)
+          }
+          0x0d => {
+            // fdiv.d
+            inst_count!(self, "fdiv.d");
+            self.debug(inst, "fdiv.d");
+
+            self.fregs.write(rd, self.fregs.read(rs1) / self.fregs.read(rs2));
+          }
+          0x10 => {
+            match funct3 {
+              0x0 => {
+                // fsgnj.s
+                inst_count!(self, "fsgnj.s");
+                self.debug(inst, "fsgnj.s");
+
+                self
+                  .fregs
+                  .write(rd, self.fregs.read(rs1).copysign(self.fregs.read(rs2)));
+              }
+              0x1 => {
+                // fsgnjn.s
+                inst_count!(self, "fsgnjn.s");
+                self.debug(inst, "fsgnjn.s");
+
+                self
+                  .fregs
+                  .write(rd, self.fregs.read(rs1).copysign(-self.fregs.read(rs2)));
+              }
+              0x2 => {
+                // fsgnjx.s
+                inst_count!(self, "fsgnjx.s");
+                self.debug(inst, "fsgnjx.s");
+
+                let sign1 = (self.fregs.read(rs1) as f32).to_bits() & 0x80000000;
+                let sign2 = (self.fregs.read(rs2) as f32).to_bits() & 0x80000000;
+                let other = (self.fregs.read(rs1) as f32).to_bits() & 0x7fffffff;
+                self.fregs.write(rd, f32::from_bits((sign1 ^ sign2) | other) as f64);
+              }
+              _ => {
+                return Err(Exception::IllegalInstruction(inst));
+              }
+            }
+          }
+          0x11 => {
+            match funct3 {
+              0x0 => {
+                // fsgnj.d
+                inst_count!(self, "fsgnj.d");
+                self.debug(inst, "fsgnj.d");
+
+                self
+                  .fregs
+                  .write(rd, self.fregs.read(rs1).copysign(self.fregs.read(rs2)));
+              }
+              0x1 => {
+                // fsgnjn.d
+                inst_count!(self, "fsgnjn.d");
+                self.debug(inst, "fsgnjn.d");
+
+                self
+                  .fregs
+                  .write(rd, self.fregs.read(rs1).copysign(-self.fregs.read(rs2)));
+              }
+              0x2 => {
+                // fsgnjx.d
+                inst_count!(self, "fsgnjx.d");
+                self.debug(inst, "fsgnjx.d");
+
+                let sign1 = self.fregs.read(rs1).to_bits() & 0x80000000_00000000;
+                let sign2 = self.fregs.read(rs2).to_bits() & 0x80000000_00000000;
+                let other = self.fregs.read(rs1).to_bits() & 0x7fffffff_ffffffff;
+                self.fregs.write(rd, f64::from_bits((sign1 ^ sign2) | other));
+              }
+              _ => {
+                return Err(Exception::IllegalInstruction(inst));
+              }
+            }
+          }
+          0x14 => {
+            match funct3 {
+              0x0 => {
+                // fmin.s
+                inst_count!(self, "fmin.s");
+                self.debug(inst, "fmin.s");
+
+                self.fregs.write(rd, self.fregs.read(rs1).min(self.fregs.read(rs2)));
+              }
+              0x1 => {
+                // fmax.s
+                inst_count!(self, "fmax.s");
+                self.debug(inst, "fmax.s");
+
+                self.fregs.write(rd, self.fregs.read(rs1).max(self.fregs.read(rs2)));
+              }
+              _ => {
+                return Err(Exception::IllegalInstruction(inst));
+              }
+            }
+          }
+          0x15 => {
+            match funct3 {
+              0x0 => {
+                // fmin.d
+                inst_count!(self, "fmin.d");
+                self.debug(inst, "fmin.d");
+
+                self.fregs.write(rd, self.fregs.read(rs1).min(self.fregs.read(rs2)));
+              }
+              0x1 => {
+                // fmax.d
+                inst_count!(self, "fmax.d");
+                self.debug(inst, "fmax.d");
+
+                self.fregs.write(rd, self.fregs.read(rs1).max(self.fregs.read(rs2)));
+              }
+              _ => {
+                return Err(Exception::IllegalInstruction(inst));
+              }
+            }
+          }
+          0x20 => {
+            // fcvt.s.d
+            inst_count!(self, "fcvt.s.d");
+            self.debug(inst, "fcvt.s.d");
+
+            self.fregs.write(rd, self.fregs.read(rs1));
+          }
+          0x21 => {
+            // fcvt.d.s
+            inst_count!(self, "fcvt.d.s");
+            self.debug(inst, "fcvt.d.s");
+
+            self.fregs.write(rd, (self.fregs.read(rs1) as f32) as f64);
+          }
+          0x2c => {
+            // fsqrt.s
+            inst_count!(self, "fsqrt.s");
+            self.debug(inst, "fsqrt.s");
+
+            self.fregs.write(rd, (self.fregs.read(rs1) as f32).sqrt() as f64);
+          }
+          0x2d => {
+            // fsqrt.d
+            inst_count!(self, "fsqrt.d");
+            self.debug(inst, "fsqrt.d");
+
+            self.fregs.write(rd, self.fregs.read(rs1).sqrt());
+          }
+          0x50 => {
+            match funct3 {
+              0x0 => {
+                // fle.s
+                inst_count!(self, "fle.s");
+                self.debug(inst, "fle.s");
+
+                self.xregs.write(
+                  rd,
+                  if self.fregs.read(rs1) <= self.fregs.read(rs2) {
+                    1
+                  } else {
+                    0
+                  },
+                );
+              }
+              0x1 => {
+                // flt.s
+                inst_count!(self, "flt.s");
+                self.debug(inst, "flt.s");
+
+                self.xregs.write(
+                  rd,
+                  if self.fregs.read(rs1) < self.fregs.read(rs2) {
+                    1
+                  } else {
+                    0
+                  },
+                );
+              }
+              0x2 => {
+                // feq.s
+                inst_count!(self, "feq.s");
+                self.debug(inst, "feq.s");
+
+                self.xregs.write(
+                  rd,
+                  if self.fregs.read(rs1) == self.fregs.read(rs2) {
+                    1
+                  } else {
+                    0
+                  },
+                );
+              }
+              _ => {
+                return Err(Exception::IllegalInstruction(inst));
+              }
+            }
+          }
+          0x51 => {
+            match funct3 {
+              0x0 => {
+                // fle.d
+                inst_count!(self, "fle.d");
+                self.debug(inst, "fle.d");
+
+                self.xregs.write(
+                  rd,
+                  if self.fregs.read(rs1) <= self.fregs.read(rs2) {
+                    1
+                  } else {
+                    0
+                  },
+                );
+              }
+              0x1 => {
+                // flt.d
+                inst_count!(self, "flt.d");
+                self.debug(inst, "flt.d");
+
+                self.xregs.write(
+                  rd,
+                  if self.fregs.read(rs1) < self.fregs.read(rs2) {
+                    1
+                  } else {
+                    0
+                  },
+                );
+              }
+              0x2 => {
+                // feq.d
+                inst_count!(self, "feq.d");
+                self.debug(inst, "feq.d");
+
+                self.xregs.write(
+                  rd,
+                  if self.fregs.read(rs1) == self.fregs.read(rs2) {
+                    1
+                  } else {
+                    0
+                  },
+                );
+              }
+              _ => {
+                return Err(Exception::IllegalInstruction(inst));
+              }
+            }
+          }
+          0x60 => {
+            match rs2 {
+              0x0 => {
+                // fcvt.w.s
+                inst_count!(self, "fcvt.w.s");
+                self.debug(inst, "fcvt.w.s");
+
+                self
+                  .xregs
+                  .write(rd, ((self.fregs.read(rs1) as f32).round() as i32) as u64);
+              }
+              0x1 => {
+                // fcvt.wu.s
+                inst_count!(self, "fcvt.wu.s");
+                self.debug(inst, "fcvt.wu.s");
+
+                self
+                  .xregs
+                  .write(rd, (((self.fregs.read(rs1) as f32).round() as u32) as i32) as u64);
+              }
+              0x2 => {
+                // fcvt.l.s
+                inst_count!(self, "fcvt.l.s");
+                self.debug(inst, "fcvt.l.s");
+
+                self.xregs.write(rd, (self.fregs.read(rs1) as f32).round() as u64);
+              }
+              0x3 => {
+                // fcvt.lu.s
+                inst_count!(self, "fcvt.lu.s");
+                self.debug(inst, "fcvt.lu.s");
+
+                self.xregs.write(rd, (self.fregs.read(rs1) as f32).round() as u64);
+              }
+              _ => {
+                return Err(Exception::IllegalInstruction(inst));
+              }
+            }
+          }
+          0x61 => {
+            match rs2 {
+              0x0 => {
+                // fcvt.w.d
+                inst_count!(self, "fcvt.w.d");
+                self.debug(inst, "fcvt.w.d");
+
+                self.xregs.write(rd, (self.fregs.read(rs1).round() as i32) as u64);
+              }
+              0x1 => {
+                // fcvt.wu.d
+                inst_count!(self, "fcvt.wu.d");
+                self.debug(inst, "fcvt.wu.d");
+
+                self
+                  .xregs
+                  .write(rd, ((self.fregs.read(rs1).round() as u32) as i32) as u64);
+              }
+              0x2 => {
+                // fcvt.l.d
+                inst_count!(self, "fcvt.l.d");
+                self.debug(inst, "fcvt.l.d");
+
+                self.xregs.write(rd, self.fregs.read(rs1).round() as u64);
+              }
+              0x3 => {
+                // fcvt.lu.d
+                inst_count!(self, "fcvt.lu.d");
+                self.debug(inst, "fcvt.lu.d");
+
+                self.xregs.write(rd, self.fregs.read(rs1).round() as u64);
+              }
+              _ => {
+                return Err(Exception::IllegalInstruction(inst));
+              }
+            }
+          }
+          0x68 => {
+            match rs2 {
+              0x0 => {
+                // fcvt.s.w
+                inst_count!(self, "fcvt.s.w");
+                self.debug(inst, "fcvt.s.w");
+
+                self.fregs.write(rd, ((self.xregs.read(rs1) as i32) as f32) as f64);
+              }
+              0x1 => {
+                // fcvt.s.wu
+                inst_count!(self, "fcvt.s.wu");
+                self.debug(inst, "fcvt.s.wu");
+
+                self.fregs.write(rd, ((self.xregs.read(rs1) as u32) as f32) as f64);
+              }
+              0x2 => {
+                // fcvt.s.l
+                inst_count!(self, "fcvt.s.l");
+                self.debug(inst, "fcvt.s.l");
+
+                self.fregs.write(rd, (self.xregs.read(rs1) as f32) as f64);
+              }
+              0x3 => {
+                // fcvt.s.lu
+                inst_count!(self, "fcvt.s.lu");
+                self.debug(inst, "fcvt.s.lu");
+
+                self.fregs.write(rd, ((self.xregs.read(rs1) as u64) as f32) as f64);
+              }
+              _ => {
+                return Err(Exception::IllegalInstruction(inst));
+              }
+            }
+          }
+          0x69 => {
+            match rs2 {
+              0x0 => {
+                // fcvt.d.w
+                inst_count!(self, "fcvt.d.w");
+                self.debug(inst, "fcvt.d.w");
+
+                self.fregs.write(rd, (self.xregs.read(rs1) as i32) as f64);
+              }
+              0x1 => {
+                // fcvt.d.wu
+                inst_count!(self, "fcvt.d.wu");
+                self.debug(inst, "fcvt.d.wu");
+
+                self.fregs.write(rd, (self.xregs.read(rs1) as u32) as f64);
+              }
+              0x2 => {
+                // fcvt.d.l
+                inst_count!(self, "fcvt.d.l");
+                self.debug(inst, "fcvt.d.l");
+
+                self.fregs.write(rd, self.xregs.read(rs1) as f64);
+              }
+              0x3 => {
+                // fcvt.d.lu
+                inst_count!(self, "fcvt.d.lu");
+                self.debug(inst, "fcvt.d.lu");
+
+                self.fregs.write(rd, self.xregs.read(rs1) as f64);
+              }
+              _ => {
+                return Err(Exception::IllegalInstruction(inst));
+              }
+            }
+          }
+          0x70 => {
+            match funct3 {
+              0x0 => {
+                // fmv.x.w
+                inst_count!(self, "fmv.x.w");
+                self.debug(inst, "fmv.x.w");
+
+                self
+                  .xregs
+                  .write(rd, (self.fregs.read(rs1).to_bits() & 0xffffffff) as i32 as i64 as u64);
+              }
+              0x1 => {
+                // fclass.s
+                inst_count!(self, "fclass.s");
+                self.debug(inst, "fclass.s");
+
+                let f = self.fregs.read(rs1);
+                match f.classify() {
+                  FpCategory::Infinite => {
+                    self.xregs.write(rd, if f.is_sign_negative() { 0 } else { 7 });
+                  }
+                  FpCategory::Normal => {
+                    self.xregs.write(rd, if f.is_sign_negative() { 1 } else { 6 });
+                  }
+                  FpCategory::Subnormal => {
+                    self.xregs.write(rd, if f.is_sign_negative() { 2 } else { 5 });
+                  }
+                  FpCategory::Zero => {
+                    self.xregs.write(rd, if f.is_sign_negative() { 3 } else { 4 });
+                  }
+                  // don't support a signaling nan, only support a quiet nan.
+                  FpCategory::Nan => self.xregs.write(rd, 9),
                 }
+              }
+              _ => {
+                return Err(Exception::IllegalInstruction(inst));
+              }
             }
-            0x63 => {
-                // RV32I
-                // imm[12|10:5|4:1|11] = inst[31|30:25|11:8|7]
-                let imm = (((inst & 0x80000000) as i32 as i64 >> 19) as u64)
+          }
+          0x71 => {
+            match funct3 {
+              0x0 => {
+                // fmv.x.d
+                inst_count!(self, "fmv.x.d");
+                self.debug(inst, "fmv.x.d");
+
+                // "FMV.X.D and FMV.D.X do not modify the bits being transferred"
+                self.xregs.write(rd, self.fregs.read(rs1).to_bits());
+              }
+              0x1 => {
+                // fclass.d
+                inst_count!(self, "fclass.d");
+                self.debug(inst, "fclass.d");
+
+                let f = self.fregs.read(rs1);
+                match f.classify() {
+                  FpCategory::Infinite => {
+                    self.xregs.write(rd, if f.is_sign_negative() { 0 } else { 7 });
+                  }
+                  FpCategory::Normal => {
+                    self.xregs.write(rd, if f.is_sign_negative() { 1 } else { 6 });
+                  }
+                  FpCategory::Subnormal => {
+                    self.xregs.write(rd, if f.is_sign_negative() { 2 } else { 5 });
+                  }
+                  FpCategory::Zero => {
+                    self.xregs.write(rd, if f.is_sign_negative() { 3 } else { 4 });
+                  }
+                  // don't support a signaling nan, only support a quiet nan.
+                  FpCategory::Nan => self.xregs.write(rd, 9),
+                }
+              }
+              _ => {
+                return Err(Exception::IllegalInstruction(inst));
+              }
+            }
+          }
+          0x78 => {
+            // fmv.w.x
+            inst_count!(self, "fmv.w.x");
+            self.debug(inst, "fmv.w.x");
+
+            self.fregs.write(rd, f64::from_bits(self.xregs.read(rs1) & 0xffffffff));
+          }
+          0x79 => {
+            // fmv.d.x
+            inst_count!(self, "fmv.d.x");
+            self.debug(inst, "fmv.d.x");
+
+            // "FMV.X.D and FMV.D.X do not modify the bits being transferred"
+            self.fregs.write(rd, f64::from_bits(self.xregs.read(rs1)));
+          }
+          _ => {
+            return Err(Exception::IllegalInstruction(inst));
+          }
+        }
+      }
+      0x63 => {
+        // RV32I
+        // imm[12|10:5|4:1|11] = inst[31|30:25|11:8|7]
+        let imm = (((inst & 0x80000000) as i32 as i64 >> 19) as u64)
                     | ((inst & 0x80) << 4) // imm[11]
                     | ((inst >> 20) & 0x7e0) // imm[10:5]
                     | ((inst >> 7) & 0x1e); // imm[4:1]
 
-                match funct3 {
-                    0x0 => {
-                        // beq
-                        inst_count!(self, "beq");
-                        self.debug(inst, "beq");
-
-                        if self.xregs.read(rs1) == self.xregs.read(rs2) {
-                            self.pc = self.pc.wrapping_add(imm).wrapping_sub(4);
-                        }
-                    }
-                    0x1 => {
-                        // bne
-                        inst_count!(self, "bne");
-                        self.debug(inst, "bne");
-
-                        if self.xregs.read(rs1) != self.xregs.read(rs2) {
-                            self.pc = self.pc.wrapping_add(imm).wrapping_sub(4);
-                        }
-                    }
-                    0x4 => {
-                        // blt
-                        inst_count!(self, "blt");
-                        self.debug(inst, "blt");
-
-                        if (self.xregs.read(rs1) as i64) < (self.xregs.read(rs2) as i64) {
-                            self.pc = self.pc.wrapping_add(imm).wrapping_sub(4);
-                        }
-                    }
-                    0x5 => {
-                        // bge
-                        inst_count!(self, "bge");
-                        self.debug(inst, "bge");
-
-                        if (self.xregs.read(rs1) as i64) >= (self.xregs.read(rs2) as i64) {
-                            self.pc = self.pc.wrapping_add(imm).wrapping_sub(4);
-                        }
-                    }
-                    0x6 => {
-                        // bltu
-                        inst_count!(self, "bltu");
-                        self.debug(inst, "bltu");
-
-                        if self.xregs.read(rs1) < self.xregs.read(rs2) {
-                            self.pc = self.pc.wrapping_add(imm).wrapping_sub(4);
-                        }
-                    }
-                    0x7 => {
-                        // bgeu
-                        inst_count!(self, "bgeu");
-                        self.debug(inst, "bgeu");
-
-                        if self.xregs.read(rs1) >= self.xregs.read(rs2) {
-                            self.pc = self.pc.wrapping_add(imm).wrapping_sub(4);
-                        }
-                    }
-                    _ => {
-                        return Err(Exception::IllegalInstruction(inst));
-                    }
-                }
+        match funct3 {
+          0x0 => {
+            // beq
+            inst_count!(self, "beq");
+            self.debug(inst, "beq");
+
+            if self.xregs.read(rs1) == self.xregs.read(rs2) {
+              self.pc = self.pc.wrapping_add(imm).wrapping_sub(4);
+            }
+          }
+          0x1 => {
+            // bne
+            inst_count!(self, "bne");
+            self.debug(inst, "bne");
+
+            if self.xregs.read(rs1) != self.xregs.read(rs2) {
+              self.pc = self.pc.wrapping_add(imm).wrapping_sub(4);
+            }
+          }
+          0x4 => {
+            // blt
+            inst_count!(self, "blt");
+            self.debug(inst, "blt");
+
+            if (self.xregs.read(rs1) as i64) < (self.xregs.read(rs2) as i64) {
+              self.pc = self.pc.wrapping_add(imm).wrapping_sub(4);
+            }
+          }
+          0x5 => {
+            // bge
+            inst_count!(self, "bge");
+            self.debug(inst, "bge");
+
+            if (self.xregs.read(rs1) as i64) >= (self.xregs.read(rs2) as i64) {
+              self.pc = self.pc.wrapping_add(imm).wrapping_sub(4);
             }
-            0x67 => {
-                // jalr
-                inst_count!(self, "jalr");
-                self.debug(inst, "jalr");
+          }
+          0x6 => {
+            // bltu
+            inst_count!(self, "bltu");
+            self.debug(inst, "bltu");
+
+            if self.xregs.read(rs1) < self.xregs.read(rs2) {
+              self.pc = self.pc.wrapping_add(imm).wrapping_sub(4);
+            }
+          }
+          0x7 => {
+            // bgeu
+            inst_count!(self, "bgeu");
+            self.debug(inst, "bgeu");
+
+            if self.xregs.read(rs1) >= self.xregs.read(rs2) {
+              self.pc = self.pc.wrapping_add(imm).wrapping_sub(4);
+            }
+          }
+          _ => {
+            return Err(Exception::IllegalInstruction(inst));
+          }
+        }
+      }
+      0x67 => {
+        // jalr
+        inst_count!(self, "jalr");
+        self.debug(inst, "jalr");
 
-                let t = self.pc.wrapping_add(4);
+        let t = self.pc.wrapping_add(4);
 
-                let offset = (inst as i32 as i64) >> 20;
-                let target = ((self.xregs.read(rs1) as i64).wrapping_add(offset)) & !1;
+        let offset = (inst as i32 as i64) >> 20;
+        let target = ((self.xregs.read(rs1) as i64).wrapping_add(offset)) & !1;
 
-                self.pc = (target as u64).wrapping_sub(4);
+        self.pc = (target as u64).wrapping_sub(4);
 
-                self.xregs.write(rd, t);
-            }
-            0x6F => {
-                // jal
-                inst_count!(self, "jal");
-                self.debug(inst, "jal");
+        self.xregs.write(rd, t);
+      }
+      0x6F => {
+        // jal
+        inst_count!(self, "jal");
+        self.debug(inst, "jal");
 
-                self.xregs.write(rd, self.pc.wrapping_add(4));
+        self.xregs.write(rd, self.pc.wrapping_add(4));
 
-                // imm[20|10:1|11|19:12] = inst[31|30:21|20|19:12]
-                let offset = (((inst & 0x80000000) as i32 as i64 >> 11) as u64) // imm[20]
+        // imm[20|10:1|11|19:12] = inst[31|30:21|20|19:12]
+        let offset = (((inst & 0x80000000) as i32 as i64 >> 11) as u64) // imm[20]
                     | (inst & 0xff000) // imm[19:12]
                     | ((inst >> 9) & 0x800) // imm[11]
                     | ((inst >> 20) & 0x7fe); // imm[10:1]
 
-                self.pc = self.pc.wrapping_add(offset).wrapping_sub(4);
-            }
-            0x73 => {
-                // RV32I, RVZicsr, and supervisor ISA
-                let csr_addr = ((inst >> 20) & 0xfff) as u16;
-                match funct3 {
-                    0x0 => {
-                        match (rs2, funct7) {
-                            (0x0, 0x0) => {
-                                // ecall
-                                inst_count!(self, "ecall");
-                                self.debug(inst, "ecall");
-
-                                // Makes a request of the execution environment by raising an
-                                // environment call exception.
-                                match self.mode {
-                                    Mode::User => {
-                                        return Err(Exception::EnvironmentCallFromUMode);
-                                    }
-                                    Mode::Supervisor => {
-                                        return Err(Exception::EnvironmentCallFromSMode);
-                                    }
-                                    Mode::Machine => {
-                                        return Err(Exception::EnvironmentCallFromMMode);
-                                    }
-                                    _ => {
-                                        return Err(Exception::IllegalInstruction(inst));
-                                    }
-                                }
-                            }
-                            (0x1, 0x0) => {
-                                // ebreak
-                                inst_count!(self, "ebreak");
-                                self.debug(inst, "ebreak");
-
-                                // Makes a request of the debugger bu raising a Breakpoint
-                                // exception.
-                                return Err(Exception::Breakpoint);
-                            }
-                            (0x2, 0x0) => {
-                                // uret
-                                inst_count!(self, "uret");
-                                self.debug(inst, "uret");
-                                panic!("uret: not implemented yet. pc {}", self.pc);
-                            }
-                            (0x2, 0x8) => {
-                                // sret
-                                inst_count!(self, "sret");
-                                self.debug(inst, "sret");
-
-                                // "The RISC-V Reader" book says:
-                                // "Returns from a supervisor-mode exception handler. Sets the pc to
-                                // CSRs[sepc], the privilege mode to CSRs[sstatus].SPP,
-                                // CSRs[sstatus].SIE to CSRs[sstatus].SPIE, CSRs[sstatus].SPIE to
-                                // 1, and CSRs[sstatus].SPP to 0.", but the implementation in QEMU
-                                // and Spike use `mstatus` instead of `sstatus`.
-
-                                // Set the program counter to the supervisor exception program
-                                // counter (SEPC).
-                                self.pc = self.state.read(SEPC).wrapping_sub(4);
-
-                                // TODO: Check TSR field
-
-                                // Set the current privileged mode depending on a previous
-                                // privilege mode for supervisor mode (SPP, 8).
-                                self.mode = match self.state.read_sstatus(XSTATUS_SPP) {
-                                    0b0 => Mode::User,
-                                    0b1 => {
-                                        // If SPP != M-mode, SRET also sets MPRV=0.
-                                        self.state.write_mstatus(MSTATUS_MPRV, 0);
-                                        Mode::Supervisor
-                                    }
-                                    _ => Mode::Debug,
-                                };
-
-                                // Read a previous interrupt-enable bit for supervisor mode (SPIE,
-                                // 5), and set a global interrupt-enable bit for supervisor mode
-                                // (SIE, 1) to it.
-                                self.state.write_sstatus(
-                                    XSTATUS_SIE,
-                                    self.state.read_sstatus(XSTATUS_SPIE),
-                                );
-
-                                // Set a previous interrupt-enable bit for supervisor mode (SPIE,
-                                // 5) to 1.
-                                self.state.write_sstatus(XSTATUS_SPIE, 1);
-                                // Set a previous privilege mode for supervisor mode (SPP, 8) to 0.
-                                self.state.write_sstatus(XSTATUS_SPP, 0);
-                            }
-                            (0x2, 0x18) => {
-                                // mret
-                                inst_count!(self, "mret");
-                                self.debug(inst, "mret");
-
-                                // "The RISC-V Reader" book says:
-                                // "Returns from a machine-mode exception handler. Sets the pc to
-                                // CSRs[mepc], the privilege mode to CSRs[mstatus].MPP,
-                                // CSRs[mstatus].MIE to CSRs[mstatus].MPIE, and CSRs[mstatus].MPIE
-                                // to 1; and, if user mode is supported, sets CSRs[mstatus].MPP to
-                                // 0".
-
-                                // Set the program counter to the machine exception program
-                                // counter (MEPC).
-                                self.pc = self.state.read(MEPC).wrapping_sub(4);
-
-                                // Set the current privileged mode depending on a previous
-                                // privilege mode for machine  mode (MPP, 11..13).
-                                self.mode = match self.state.read_mstatus(MSTATUS_MPP) {
-                                    0b00 => {
-                                        // If MPP != M-mode, MRET also sets MPRV=0.
-                                        self.state.write_mstatus(MSTATUS_MPRV, 0);
-                                        Mode::User
-                                    }
-                                    0b01 => {
-                                        // If MPP != M-mode, MRET also sets MPRV=0.
-                                        self.state.write_mstatus(MSTATUS_MPRV, 0);
-                                        Mode::Supervisor
-                                    }
-                                    0b11 => Mode::Machine,
-                                    _ => Mode::Debug,
-                                };
-
-                                // Read a previous interrupt-enable bit for machine mode (MPIE, 7),
-                                // and set a global interrupt-enable bit for machine mode (MIE, 3)
-                                // to it.
-                                self.state.write_mstatus(
-                                    MSTATUS_MIE,
-                                    self.state.read_mstatus(MSTATUS_MPIE),
-                                );
-
-                                // Set a previous interrupt-enable bit for machine mode (MPIE, 7)
-                                // to 1.
-                                self.state.write_mstatus(MSTATUS_MPIE, 1);
-
-                                // Set a previous privilege mode for machine mode (MPP, 11..13) to
-                                // 0.
-                                self.state.write_mstatus(MSTATUS_MPP, Mode::User as u64);
-                            }
-                            (0x5, 0x8) => {
-                                // wfi
-                                inst_count!(self, "wfi");
-                                self.debug(inst, "wfi");
-                                // "provides a hint to the implementation that the current
-                                // hart can be stalled until an interrupt might need servicing."
-                                self.idle = true;
-                            }
-                            (_, 0x9) => {
-                                // sfence.vma
-                                inst_count!(self, "sfence.vma");
-                                self.debug(inst, "sfence.vma");
-                                // "SFENCE.VMA is used to synchronize updates to in-memory
-                                // memory-management data structures with current execution"
-                            }
-                            (_, 0x11) => {
-                                // hfence.bvma
-                                inst_count!(self, "hfence.bvma");
-                                self.debug(inst, "hfence.bvma");
-                            }
-                            (_, 0x51) => {
-                                // hfence.gvma
-                                inst_count!(self, "hfence.gvma");
-                                self.debug(inst, "hfence.gvma");
-                            }
-                            _ => {
-                                return Err(Exception::IllegalInstruction(inst));
-                            }
-                        }
-                    }
-                    0x1 => {
-                        // csrrw
-                        inst_count!(self, "csrrw");
-                        self.debug(inst, "csrrw");
-
-                        let t = self.state.read(csr_addr);
-                        self.state.write(csr_addr, self.xregs.read(rs1));
-                        self.xregs.write(rd, t);
-
-                        if csr_addr == SATP {
-                            self.update_paging();
-                        }
-                    }
-                    0x2 => {
-                        // csrrs
-                        inst_count!(self, "csrrs");
-                        self.debug(inst, "csrrs");
-
-                        let t = self.state.read(csr_addr);
-                        self.state.write(csr_addr, t | self.xregs.read(rs1));
-                        self.xregs.write(rd, t);
-
-                        if csr_addr == SATP {
-                            self.update_paging();
-                        }
-                    }
-                    0x3 => {
-                        // csrrc
-                        inst_count!(self, "csrrc");
-                        self.debug(inst, "csrrc");
-
-                        let t = self.state.read(csr_addr);
-                        self.state.write(csr_addr, t & (!self.xregs.read(rs1)));
-                        self.xregs.write(rd, t);
-
-                        if csr_addr == SATP {
-                            self.update_paging();
-                        }
-                    }
-                    0x5 => {
-                        // csrrwi
-                        inst_count!(self, "csrrwi");
-                        self.debug(inst, "csrrwi");
-
-                        let zimm = rs1;
-                        self.xregs.write(rd, self.state.read(csr_addr));
-                        self.state.write(csr_addr, zimm);
-
-                        if csr_addr == SATP {
-                            self.update_paging();
-                        }
-                    }
-                    0x6 => {
-                        // csrrsi
-                        inst_count!(self, "csrrsi");
-                        self.debug(inst, "csrrsi");
-
-                        let zimm = rs1;
-                        let t = self.state.read(csr_addr);
-                        self.state.write(csr_addr, t | zimm);
-                        self.xregs.write(rd, t);
-
-                        if csr_addr == SATP {
-                            self.update_paging();
-                        }
-                    }
-                    0x7 => {
-                        // csrrci
-                        inst_count!(self, "csrrci");
-                        self.debug(inst, "csrrci");
-
-                        let zimm = rs1;
-                        let t = self.state.read(csr_addr);
-                        self.state.write(csr_addr, t & (!zimm));
-                        self.xregs.write(rd, t);
-
-                        if csr_addr == SATP {
-                            self.update_paging();
-                        }
-                    }
-                    _ => {
-                        return Err(Exception::IllegalInstruction(inst));
-                    }
+        self.pc = self.pc.wrapping_add(offset).wrapping_sub(4);
+      }
+      0x73 => {
+        // RV32I, RVZicsr, and supervisor ISA
+        let csr_addr = ((inst >> 20) & 0xfff) as u16;
+        match funct3 {
+          0x0 => {
+            match (rs2, funct7) {
+              (0x0, 0x0) => {
+                // ecall
+                inst_count!(self, "ecall");
+                self.debug(inst, "ecall");
+
+                // Makes a request of the execution environment by raising an
+                // environment call exception.
+                match self.mode {
+                  Mode::User => {
+                    return Err(Exception::EnvironmentCallFromUMode);
+                  }
+                  Mode::Supervisor => {
+                    return Err(Exception::EnvironmentCallFromSMode);
+                  }
+                  Mode::Machine => {
+                    return Err(Exception::EnvironmentCallFromMMode);
+                  }
+                  _ => {
+                    return Err(Exception::IllegalInstruction(inst));
+                  }
                 }
-            }
-            _ => {
+              }
+              (0x1, 0x0) => {
+                // ebreak
+                inst_count!(self, "ebreak");
+                self.debug(inst, "ebreak");
+
+                // Makes a request of the debugger bu raising a Breakpoint
+                // exception.
+                return Err(Exception::Breakpoint);
+              }
+              (0x2, 0x0) => {
+                // uret
+                inst_count!(self, "uret");
+                self.debug(inst, "uret");
+                panic!("uret: not implemented yet. pc {}", self.pc);
+              }
+              (0x2, 0x8) => {
+                // sret
+                inst_count!(self, "sret");
+                self.debug(inst, "sret");
+
+                // "The RISC-V Reader" book says:
+                // "Returns from a supervisor-mode exception handler. Sets the pc to
+                // CSRs[sepc], the privilege mode to CSRs[sstatus].SPP,
+                // CSRs[sstatus].SIE to CSRs[sstatus].SPIE, CSRs[sstatus].SPIE to
+                // 1, and CSRs[sstatus].SPP to 0.", but the implementation in QEMU
+                // and Spike use `mstatus` instead of `sstatus`.
+
+                // Set the program counter to the supervisor exception program
+                // counter (SEPC).
+                self.pc = self.state.read(SEPC).wrapping_sub(4);
+
+                // TODO: Check TSR field
+
+                // Set the current privileged mode depending on a previous
+                // privilege mode for supervisor mode (SPP, 8).
+                self.mode = match self.state.read_sstatus(XSTATUS_SPP) {
+                  0b0 => Mode::User,
+                  0b1 => {
+                    // If SPP != M-mode, SRET also sets MPRV=0.
+                    self.state.write_mstatus(MSTATUS_MPRV, 0);
+                    Mode::Supervisor
+                  }
+                  _ => Mode::Debug,
+                };
+
+                // Read a previous interrupt-enable bit for supervisor mode (SPIE,
+                // 5), and set a global interrupt-enable bit for supervisor mode
+                // (SIE, 1) to it.
+                self
+                  .state
+                  .write_sstatus(XSTATUS_SIE, self.state.read_sstatus(XSTATUS_SPIE));
+
+                // Set a previous interrupt-enable bit for supervisor mode (SPIE,
+                // 5) to 1.
+                self.state.write_sstatus(XSTATUS_SPIE, 1);
+                // Set a previous privilege mode for supervisor mode (SPP, 8) to 0.
+                self.state.write_sstatus(XSTATUS_SPP, 0);
+              }
+              (0x2, 0x18) => {
+                // mret
+                inst_count!(self, "mret");
+                self.debug(inst, "mret");
+
+                // "The RISC-V Reader" book says:
+                // "Returns from a machine-mode exception handler. Sets the pc to
+                // CSRs[mepc], the privilege mode to CSRs[mstatus].MPP,
+                // CSRs[mstatus].MIE to CSRs[mstatus].MPIE, and CSRs[mstatus].MPIE
+                // to 1; and, if user mode is supported, sets CSRs[mstatus].MPP to
+                // 0".
+
+                // Set the program counter to the machine exception program
+                // counter (MEPC).
+                self.pc = self.state.read(MEPC).wrapping_sub(4);
+
+                // Set the current privileged mode depending on a previous
+                // privilege mode for machine  mode (MPP, 11..13).
+                self.mode = match self.state.read_mstatus(MSTATUS_MPP) {
+                  0b00 => {
+                    // If MPP != M-mode, MRET also sets MPRV=0.
+                    self.state.write_mstatus(MSTATUS_MPRV, 0);
+                    Mode::User
+                  }
+                  0b01 => {
+                    // If MPP != M-mode, MRET also sets MPRV=0.
+                    self.state.write_mstatus(MSTATUS_MPRV, 0);
+                    Mode::Supervisor
+                  }
+                  0b11 => Mode::Machine,
+                  _ => Mode::Debug,
+                };
+
+                // Read a previous interrupt-enable bit for machine mode (MPIE, 7),
+                // and set a global interrupt-enable bit for machine mode (MIE, 3)
+                // to it.
+                self
+                  .state
+                  .write_mstatus(MSTATUS_MIE, self.state.read_mstatus(MSTATUS_MPIE));
+
+                // Set a previous interrupt-enable bit for machine mode (MPIE, 7)
+                // to 1.
+                self.state.write_mstatus(MSTATUS_MPIE, 1);
+
+                // Set a previous privilege mode for machine mode (MPP, 11..13) to
+                // 0.
+                self.state.write_mstatus(MSTATUS_MPP, Mode::User as u64);
+              }
+              (0x5, 0x8) => {
+                // wfi
+                inst_count!(self, "wfi");
+                self.debug(inst, "wfi");
+                // "provides a hint to the implementation that the current
+                // hart can be stalled until an interrupt might need servicing."
+                self.idle = true;
+              }
+              (_, 0x9) => {
+                // sfence.vma
+                inst_count!(self, "sfence.vma");
+                self.debug(inst, "sfence.vma");
+                // "SFENCE.VMA is used to synchronize updates to in-memory
+                // memory-management data structures with current execution"
+              }
+              (_, 0x11) => {
+                // hfence.bvma
+                inst_count!(self, "hfence.bvma");
+                self.debug(inst, "hfence.bvma");
+              }
+              (_, 0x51) => {
+                // hfence.gvma
+                inst_count!(self, "hfence.gvma");
+                self.debug(inst, "hfence.gvma");
+              }
+              _ => {
                 return Err(Exception::IllegalInstruction(inst));
+              }
+            }
+          }
+          0x1 => {
+            // csrrw
+            inst_count!(self, "csrrw");
+            self.debug(inst, "csrrw");
+
+            let t = self.state.read(csr_addr);
+            self.state.write(csr_addr, self.xregs.read(rs1));
+            self.xregs.write(rd, t);
+
+            if csr_addr == SATP {
+              self.update_paging();
+            }
+          }
+          0x2 => {
+            // csrrs
+            inst_count!(self, "csrrs");
+            self.debug(inst, "csrrs");
+
+            let t = self.state.read(csr_addr);
+            self.state.write(csr_addr, t | self.xregs.read(rs1));
+            self.xregs.write(rd, t);
+
+            if csr_addr == SATP {
+              self.update_paging();
+            }
+          }
+          0x3 => {
+            // csrrc
+            inst_count!(self, "csrrc");
+            self.debug(inst, "csrrc");
+
+            let t = self.state.read(csr_addr);
+            self.state.write(csr_addr, t & (!self.xregs.read(rs1)));
+            self.xregs.write(rd, t);
+
+            if csr_addr == SATP {
+              self.update_paging();
+            }
+          }
+          0x5 => {
+            // csrrwi
+            inst_count!(self, "csrrwi");
+            self.debug(inst, "csrrwi");
+
+            let zimm = rs1;
+            self.xregs.write(rd, self.state.read(csr_addr));
+            self.state.write(csr_addr, zimm);
+
+            if csr_addr == SATP {
+              self.update_paging();
+            }
+          }
+          0x6 => {
+            // csrrsi
+            inst_count!(self, "csrrsi");
+            self.debug(inst, "csrrsi");
+
+            let zimm = rs1;
+            let t = self.state.read(csr_addr);
+            self.state.write(csr_addr, t | zimm);
+            self.xregs.write(rd, t);
+
+            if csr_addr == SATP {
+              self.update_paging();
+            }
+          }
+          0x7 => {
+            // csrrci
+            inst_count!(self, "csrrci");
+            self.debug(inst, "csrrci");
+
+            let zimm = rs1;
+            let t = self.state.read(csr_addr);
+            self.state.write(csr_addr, t & (!zimm));
+            self.xregs.write(rd, t);
+
+            if csr_addr == SATP {
+              self.update_paging();
             }
+          }
+          _ => {
+            return Err(Exception::IllegalInstruction(inst));
+          }
         }
-        Ok(())
+      }
+      _ => {
+        return Err(Exception::IllegalInstruction(inst));
+      }
     }
+    Ok(())
+  }
 }
diff --git a/src/csr.rs b/src/csr.rs
index a2634ef..c91b80e 100644
--- a/src/csr.rs
+++ b/src/csr.rs
@@ -82,15 +82,15 @@ const SSTATUS_MXR_MASK: u64 = 0x80000; // sstatus[19]
 const SSTATUS_UXL_MASK: u64 = 0x3_00000000; // sstatus[33:32]
 const SSTATUS_SD_MASK: u64 = 0x80000000_00000000; // sstatus[63]
 const SSTATUS_MASK: u64 = SSTATUS_SIE_MASK
-    | SSTATUS_SPIE_MASK
-    | SSTATUS_UBE_MASK
-    | SSTATUS_SPP_MASK
-    | SSTATUS_FS_MASK
-    | SSTATUS_XS_MASK
-    | SSTATUS_SUM_MASK
-    | SSTATUS_MXR_MASK
-    | SSTATUS_UXL_MASK
-    | SSTATUS_SD_MASK;
+  | SSTATUS_SPIE_MASK
+  | SSTATUS_UBE_MASK
+  | SSTATUS_SPP_MASK
+  | SSTATUS_FS_MASK
+  | SSTATUS_XS_MASK
+  | SSTATUS_SUM_MASK
+  | SSTATUS_MXR_MASK
+  | SSTATUS_UXL_MASK
+  | SSTATUS_SD_MASK;
 /// Global interrupt-enable bit for supervisor mode.
 pub const XSTATUS_SIE: CsrFieldRange = 1..=1;
 /// Previous interrupt-enable bit for supervisor mode.
@@ -171,51 +171,51 @@ pub const MEIP_BIT: u64 = 1 << 11;
 
 /// The state to contains all the CSRs.
 pub struct State {
-    csrs: [u64; CSR_SIZE],
+  csrs: [u64; CSR_SIZE],
 }
 
 impl fmt::Display for State {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(
-            f,
-            "{}",
-            format!(
-                "{}\n{}\n{}",
-                format!(
-                    "mstatus={:>#18x}   mtvec={:>#18x}    mepc={:>#18x}\n mcause={:>#18x} medeleg={:>#18x} mideleg={:>#18x}",
-                    self.read(MSTATUS),
-                    self.read(MTVEC),
-                    self.read(MEPC),
-                    self.read(MCAUSE),
-                    self.read(MEDELEG),
-                    self.read(MIDELEG),
-                ),
-                format!(
-                    "sstatus={:>#18x}   stvec={:>#18x}    sepc={:>#18x}\n scause={:>#18x} sedeleg={:>#18x} sideleg={:>#18x}",
-                    self.read(SSTATUS),
-                    self.read(STVEC),
-                    self.read(SEPC),
-                    self.read(SCAUSE),
-                    self.read(SEDELEG),
-                    self.read(SIDELEG),
-                ),
-                format!(
-                    "ustatus={:>#18x}   utvec={:>#18x}    uepc={:>#18x}\n ucause={:>#18x}",
-                    self.read(USTATUS),
-                    self.read(UTVEC),
-                    self.read(UEPC),
-                    self.read(UCAUSE),
-                ),
-            )
-        )
-    }
+  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+    write!(
+      f,
+      "{}",
+      format!(
+        "{}\n{}\n{}",
+        format!(
+          "mstatus={:>#18x}   mtvec={:>#18x}    mepc={:>#18x}\n mcause={:>#18x} medeleg={:>#18x} mideleg={:>#18x}",
+          self.read(MSTATUS),
+          self.read(MTVEC),
+          self.read(MEPC),
+          self.read(MCAUSE),
+          self.read(MEDELEG),
+          self.read(MIDELEG),
+        ),
+        format!(
+          "sstatus={:>#18x}   stvec={:>#18x}    sepc={:>#18x}\n scause={:>#18x} sedeleg={:>#18x} sideleg={:>#18x}",
+          self.read(SSTATUS),
+          self.read(STVEC),
+          self.read(SEPC),
+          self.read(SCAUSE),
+          self.read(SEDELEG),
+          self.read(SIDELEG),
+        ),
+        format!(
+          "ustatus={:>#18x}   utvec={:>#18x}    uepc={:>#18x}\n ucause={:>#18x}",
+          self.read(USTATUS),
+          self.read(UTVEC),
+          self.read(UEPC),
+          self.read(UCAUSE),
+        ),
+      )
+    )
+  }
 }
 
 impl State {
-    /// Create a new `state` object.
-    pub fn new() -> Self {
-        let mut csrs = [0; CSR_SIZE];
-        let misa: u64 = (2 << 62) | // MXL[1:0]=2 (XLEN is 64)
+  /// Create a new `state` object.
+  pub fn new() -> Self {
+    let mut csrs = [0; CSR_SIZE];
+    let misa: u64 = (2 << 62) | // MXL[1:0]=2 (XLEN is 64)
             (1 << 20) | // Extensions[20] (User mode implemented)
             (1 << 18) | // Extensions[18] (Supervisor mode implemented)
             (1 << 12) | // Extensions[12] (Integer Multiply/Divide extension)
@@ -224,151 +224,150 @@ impl State {
             (1 << 3) | // Extensions[3] (Double-precision floating-point extension)
             (1 << 2) | // Extensions[2] (Compressed extension)
             1; // Extensions[0] (Atomic extension)
-        csrs[MISA as usize] = misa;
-
-        Self { csrs }
+    csrs[MISA as usize] = misa;
+
+    Self { csrs }
+  }
+
+  /// Increment the value in the TIME register.
+  pub fn increment_time(&mut self) {
+    self.csrs[TIME as usize] = self.csrs[TIME as usize].wrapping_add(1);
+  }
+
+  /// Read the val from the CSR.
+  pub fn read(&self, addr: CsrAddress) -> u64 {
+    // 4.1 Supervisor CSRs
+    // "The supervisor should only view CSR state that should be visible to a supervisor-level
+    // operating system. In particular, there is no information about the existence (or
+    // non-existence) of higher privilege levels (machine level or other) visible in the CSRs
+    // accessible by the supervisor.  Many supervisor CSRs are a subset of the equivalent
+    // machine-mode CSR, and the machinemode chapter should be read first to help understand
+    // the supervisor-level CSR descriptions."
+    match addr {
+      SSTATUS => self.csrs[MSTATUS as usize] & SSTATUS_MASK,
+      SIE => self.csrs[MIE as usize] & self.csrs[MIDELEG as usize],
+      SIP => self.csrs[MIP as usize] & self.csrs[MIDELEG as usize],
+      _ => self.csrs[addr as usize],
     }
-
-    /// Increment the value in the TIME register.
-    pub fn increment_time(&mut self) {
-        self.csrs[TIME as usize] = self.csrs[TIME as usize].wrapping_add(1);
+  }
+
+  /// Write the val to the CSR.
+  pub fn write(&mut self, addr: CsrAddress, val: u64) {
+    // 4.1 Supervisor CSRs
+    // "The supervisor should only view CSR state that should be visible to a supervisor-level
+    // operating system. In particular, there is no information about the existence (or
+    // non-existence) of higher privilege levels (machine level or other) visible in the CSRs
+    // accessible by the supervisor.  Many supervisor CSRs are a subset of the equivalent
+    // machine-mode CSR, and the machinemode chapter should be read first to help understand
+    // the supervisor-level CSR descriptions."
+    match addr {
+      MVENDORID => {}
+      MARCHID => {}
+      MIMPID => {}
+      MHARTID => {}
+      SSTATUS => {
+        self.csrs[MSTATUS as usize] = (self.csrs[MSTATUS as usize] & !SSTATUS_MASK) | (val & SSTATUS_MASK);
+      }
+      SIE => {
+        self.csrs[MIE as usize] =
+          (self.csrs[MIE as usize] & !self.csrs[MIDELEG as usize]) | (val & self.csrs[MIDELEG as usize]);
+      }
+      SIP => {
+        let mask = SSIP_BIT & self.csrs[MIDELEG as usize];
+        self.csrs[MIP as usize] = (self.csrs[MIP as usize] & !mask) | (val & mask);
+      }
+      _ => self.csrs[addr as usize] = val,
     }
+  }
 
-    /// Read the val from the CSR.
-    pub fn read(&self, addr: CsrAddress) -> u64 {
-        // 4.1 Supervisor CSRs
-        // "The supervisor should only view CSR state that should be visible to a supervisor-level
-        // operating system. In particular, there is no information about the existence (or
-        // non-existence) of higher privilege levels (machine level or other) visible in the CSRs
-        // accessible by the supervisor.  Many supervisor CSRs are a subset of the equivalent
-        // machine-mode CSR, and the machinemode chapter should be read first to help understand
-        // the supervisor-level CSR descriptions."
-        match addr {
-            SSTATUS => self.csrs[MSTATUS as usize] & SSTATUS_MASK,
-            SIE => self.csrs[MIE as usize] & self.csrs[MIDELEG as usize],
-            SIP => self.csrs[MIP as usize] & self.csrs[MIDELEG as usize],
-            _ => self.csrs[addr as usize],
-        }
+  /// Read a bit from the CSR.
+  pub fn read_bit(&self, addr: CsrAddress, bit: usize) -> u64 {
+    if bit >= MXLEN {
+      // TODO: raise exception?
     }
 
-    /// Write the val to the CSR.
-    pub fn write(&mut self, addr: CsrAddress, val: u64) {
-        // 4.1 Supervisor CSRs
-        // "The supervisor should only view CSR state that should be visible to a supervisor-level
-        // operating system. In particular, there is no information about the existence (or
-        // non-existence) of higher privilege levels (machine level or other) visible in the CSRs
-        // accessible by the supervisor.  Many supervisor CSRs are a subset of the equivalent
-        // machine-mode CSR, and the machinemode chapter should be read first to help understand
-        // the supervisor-level CSR descriptions."
-        match addr {
-            MVENDORID => {}
-            MARCHID => {}
-            MIMPID => {}
-            MHARTID => {}
-            SSTATUS => {
-                self.csrs[MSTATUS as usize] =
-                    (self.csrs[MSTATUS as usize] & !SSTATUS_MASK) | (val & SSTATUS_MASK);
-            }
-            SIE => {
-                self.csrs[MIE as usize] = (self.csrs[MIE as usize] & !self.csrs[MIDELEG as usize])
-                    | (val & self.csrs[MIDELEG as usize]);
-            }
-            SIP => {
-                let mask = SSIP_BIT & self.csrs[MIDELEG as usize];
-                self.csrs[MIP as usize] = (self.csrs[MIP as usize] & !mask) | (val & mask);
-            }
-            _ => self.csrs[addr as usize] = val,
-        }
+    if (self.read(addr) & (1 << bit)) != 0 {
+      1
+    } else {
+      0
     }
+  }
 
-    /// Read a bit from the CSR.
-    pub fn read_bit(&self, addr: CsrAddress, bit: usize) -> u64 {
-        if bit >= MXLEN {
-            // TODO: raise exception?
-        }
-
-        if (self.read(addr) & (1 << bit)) != 0 {
-            1
-        } else {
-            0
-        }
-    }
+  /// Read a arbitrary length of bits from the CSR.
+  pub fn read_bits<T: RangeBounds<usize>>(&self, addr: CsrAddress, range: T) -> u64 {
+    let range = to_range(&range, MXLEN);
 
-    /// Read a arbitrary length of bits from the CSR.
-    pub fn read_bits<T: RangeBounds<usize>>(&self, addr: CsrAddress, range: T) -> u64 {
-        let range = to_range(&range, MXLEN);
+    if (range.start >= MXLEN) | (range.end > MXLEN) | (range.start >= range.end) {
+      // TODO: ranse exception?
+    }
 
-        if (range.start >= MXLEN) | (range.end > MXLEN) | (range.start >= range.end) {
-            // TODO: ranse exception?
-        }
+    // Bitmask for high bits.
+    let mut bitmask = 0;
+    if range.end != 64 {
+      bitmask = !0 << range.end;
+    }
 
-        // Bitmask for high bits.
-        let mut bitmask = 0;
-        if range.end != 64 {
-            bitmask = !0 << range.end;
-        }
+    // Shift away low bits.
+    (self.read(addr) as u64 & !bitmask) >> range.start
+  }
 
-        // Shift away low bits.
-        (self.read(addr) as u64 & !bitmask) >> range.start
+  /// Write a bit to the CSR.
+  pub fn write_bit(&mut self, addr: CsrAddress, bit: usize, val: u64) {
+    if bit >= MXLEN {
+      // TODO: raise exception?
     }
-
-    /// Write a bit to the CSR.
-    pub fn write_bit(&mut self, addr: CsrAddress, bit: usize, val: u64) {
-        if bit >= MXLEN {
-            // TODO: raise exception?
-        }
-        if val > 1 {
-            // TODO: raise exception
-        }
-
-        if val == 1 {
-            self.write(addr, self.read(addr) | 1 << bit);
-        } else if val == 0 {
-            self.write(addr, self.read(addr) & !(1 << bit));
-        }
+    if val > 1 {
+      // TODO: raise exception
     }
 
-    /// Write an arbitrary length of bits to the CSR.
-    pub fn write_bits<T: RangeBounds<usize>>(&mut self, addr: CsrAddress, range: T, val: u64) {
-        let range = to_range(&range, MXLEN);
+    if val == 1 {
+      self.write(addr, self.read(addr) | 1 << bit);
+    } else if val == 0 {
+      self.write(addr, self.read(addr) & !(1 << bit));
+    }
+  }
 
-        if (range.start >= MXLEN) | (range.end > MXLEN) | (range.start >= range.end) {
-            // TODO: ranse exception?
-        }
-        if (val >> (range.end - range.start)) != 0 {
-            // TODO: raise exception
-        }
+  /// Write an arbitrary length of bits to the CSR.
+  pub fn write_bits<T: RangeBounds<usize>>(&mut self, addr: CsrAddress, range: T, val: u64) {
+    let range = to_range(&range, MXLEN);
 
-        let bitmask = (!0 << range.end) | !(!0 << range.start);
-        // Set bits.
-        self.write(addr, (self.read(addr) & bitmask) | (val << range.start))
+    if (range.start >= MXLEN) | (range.end > MXLEN) | (range.start >= range.end) {
+      // TODO: ranse exception?
     }
-
-    /// Read bit(s) from a given field in the SSTATUS register.
-    pub fn read_sstatus(&self, range: CsrFieldRange) -> u64 {
-        self.read_bits(SSTATUS, range)
+    if (val >> (range.end - range.start)) != 0 {
+      // TODO: raise exception
     }
 
-    /// Read bit(s) from a given field in the MSTATUS register.
-    pub fn read_mstatus(&self, range: CsrFieldRange) -> u64 {
-        self.read_bits(MSTATUS, range)
-    }
+    let bitmask = (!0 << range.end) | !(!0 << range.start);
+    // Set bits.
+    self.write(addr, (self.read(addr) & bitmask) | (val << range.start))
+  }
 
-    /// Write bit(s) to a given field in the SSTATUS register.
-    pub fn write_sstatus(&mut self, range: CsrFieldRange, val: u64) {
-        self.write_bits(SSTATUS, range, val);
-    }
+  /// Read bit(s) from a given field in the SSTATUS register.
+  pub fn read_sstatus(&self, range: CsrFieldRange) -> u64 {
+    self.read_bits(SSTATUS, range)
+  }
 
-    /// Write bit(s) to a given field in the MSTATUS register.
-    pub fn write_mstatus(&mut self, range: CsrFieldRange, val: u64) {
-        self.write_bits(MSTATUS, range, val);
-    }
+  /// Read bit(s) from a given field in the MSTATUS register.
+  pub fn read_mstatus(&self, range: CsrFieldRange) -> u64 {
+    self.read_bits(MSTATUS, range)
+  }
 
-    /// Reset all the CSRs.
-    pub fn reset(&mut self) {
-        self.csrs = [0; CSR_SIZE];
+  /// Write bit(s) to a given field in the SSTATUS register.
+  pub fn write_sstatus(&mut self, range: CsrFieldRange, val: u64) {
+    self.write_bits(SSTATUS, range, val);
+  }
 
-        let misa: u64 = (2 << 62) | // MXL[1:0]=2 (XLEN is 64)
+  /// Write bit(s) to a given field in the MSTATUS register.
+  pub fn write_mstatus(&mut self, range: CsrFieldRange, val: u64) {
+    self.write_bits(MSTATUS, range, val);
+  }
+
+  /// Reset all the CSRs.
+  pub fn reset(&mut self) {
+    self.csrs = [0; CSR_SIZE];
+
+    let misa: u64 = (2 << 62) | // MXL[1:0]=2 (XLEN is 64)
             (1 << 18) | // Extensions[18] (Supervisor mode implemented)
             (1 << 12) | // Extensions[12] (Integer Multiply/Divide extension)
             (1 << 8) | // Extensions[8] (RV32I/64I/128I base ISA)
@@ -376,22 +375,22 @@ impl State {
             (1 << 3) | // Extensions[3] (Double-precision floating-point extension)
             (1 << 2) | // Extensions[2] (Compressed extension)
             1; // Extensions[0] (Atomic extension)
-        self.csrs[MISA as usize] = misa;
-    }
+    self.csrs[MISA as usize] = misa;
+  }
 }
 
 /// Convert the val implement `RangeBounds` to the `Range` struct.
 fn to_range<T: RangeBounds<usize>>(generic_range: &T, bit_length: usize) -> Range<usize> {
-    let start = match generic_range.start_bound() {
-        Bound::Excluded(&val) => val + 1,
-        Bound::Included(&val) => val,
-        Bound::Unbounded => 0,
-    };
-    let end = match generic_range.end_bound() {
-        Bound::Excluded(&val) => val,
-        Bound::Included(&val) => val + 1,
-        Bound::Unbounded => bit_length,
-    };
-
-    start..end
+  let start = match generic_range.start_bound() {
+    Bound::Excluded(&val) => val + 1,
+    Bound::Included(&val) => val,
+    Bound::Unbounded => 0,
+  };
+  let end = match generic_range.end_bound() {
+    Bound::Excluded(&val) => val,
+    Bound::Included(&val) => val + 1,
+    Bound::Unbounded => bit_length,
+  };
+
+  start..end
 }
diff --git a/src/devices/clint.rs b/src/devices/clint.rs
index 14ee554..ff0f23c 100644
--- a/src/devices/clint.rs
+++ b/src/devices/clint.rs
@@ -40,116 +40,116 @@ const MTIME_END: u64 = MTIME + 0x8;
 /// 0x4000 mtimecmp for hart 0 (8 bytes)
 /// 0xbff8 mtime (8 bytes)
 pub struct Clint {
-    /// Machine mode software interrupt pending register, used to assert a software interrupt for
-    /// a CPU.
-    msip: u32,
-    /// Memory mapped machine mode timer compare register, used to trigger an interrupt when
-    /// mtimecmp is greater than or equal to mtime. There is an mtimecmp dedicated to each CPU.
-    mtimecmp: u64,
-    /// Machine mode timer register which runs at a constant frequency.
-    mtime: u64,
+  /// Machine mode software interrupt pending register, used to assert a software interrupt for
+  /// a CPU.
+  msip: u32,
+  /// Memory mapped machine mode timer compare register, used to trigger an interrupt when
+  /// mtimecmp is greater than or equal to mtime. There is an mtimecmp dedicated to each CPU.
+  mtimecmp: u64,
+  /// Machine mode timer register which runs at a constant frequency.
+  mtime: u64,
 }
 
 impl Clint {
-    /// Create a new CLINT object.
-    pub fn new() -> Self {
-        Self {
-            msip: 0,
-            mtimecmp: 0,
-            mtime: 0,
-        }
+  /// Create a new CLINT object.
+  pub fn new() -> Self {
+    Self {
+      msip: 0,
+      mtimecmp: 0,
+      mtime: 0,
+    }
+  }
+
+  /// Increment the mtimer register. It's not a real-time value. The MTIP bit (MIP, 7) is enabled
+  /// when `mtime` is greater than or equal to `mtimecmp`.
+  pub fn increment(&mut self, state: &mut State) {
+    self.mtime = self.mtime.wrapping_add(1);
+    // Sync TIME csr.
+    //state.write(TIME, self.mtime);
+
+    if (self.msip & 1) != 0 {
+      // Enable the MSIP bit (MIP, 3).
+      state.write(MIP, state.read(MIP) | MSIP_BIT);
     }
 
-    /// Increment the mtimer register. It's not a real-time value. The MTIP bit (MIP, 7) is enabled
-    /// when `mtime` is greater than or equal to `mtimecmp`.
-    pub fn increment(&mut self, state: &mut State) {
-        self.mtime = self.mtime.wrapping_add(1);
-        // Sync TIME csr.
-        //state.write(TIME, self.mtime);
-
-        if (self.msip & 1) != 0 {
-            // Enable the MSIP bit (MIP, 3).
-            state.write(MIP, state.read(MIP) | MSIP_BIT);
-        }
-
-        // 3.1.10 Machine Timer Registers (mtime and mtimecmp)
-        // "The interrupt remains posted until mtimecmp becomes greater than mtime (typically as a
-        // result of writing mtimecmp)."
-        if self.mtimecmp > self.mtime {
-            // Clear the MTIP bit (MIP, 7).
-            state.write(MIP, state.read(MIP) & !MTIP_BIT);
-        }
-
-        // 3.1.10 Machine Timer Registers (mtime and mtimecmp)
-        // "A timer interrupt becomes pending whenever mtime contains a value greater than or equal
-        // to mtimecmp, treating the values as unsigned integers."
-        if self.mtime >= self.mtimecmp {
-            // Enable the MTIP bit (MIP, 7).
-            state.write(MIP, state.read(MIP) | MTIP_BIT);
-        }
+    // 3.1.10 Machine Timer Registers (mtime and mtimecmp)
+    // "The interrupt remains posted until mtimecmp becomes greater than mtime (typically as a
+    // result of writing mtimecmp)."
+    if self.mtimecmp > self.mtime {
+      // Clear the MTIP bit (MIP, 7).
+      state.write(MIP, state.read(MIP) & !MTIP_BIT);
     }
 
-    /// Load `size`-bit data from a register located at `addr` in CLINT.
-    pub fn read(&self, addr: u64, size: u8) -> Result<u64, Exception> {
-        // `reg` is the value of a target register in CLINT and `offset` is the byte of the start
-        // position in the register.
-        let (reg, offset) = match addr {
-            MSIP..=MSIP_END => (self.msip as u64, addr - MSIP),
-            MTIMECMP..=MTIMECMP_END => (self.mtimecmp, addr - MTIMECMP),
-            MTIME..=MTIME_END => (self.mtime, addr - MTIME),
-            _ => return Err(Exception::LoadAccessFault),
-        };
-
-        match size {
-            BYTE => Ok((reg >> (offset * 8)) & 0xff),
-            HALFWORD => Ok((reg >> (offset * 8)) & 0xffff),
-            WORD => Ok((reg >> (offset * 8)) & 0xffffffff),
-            DOUBLEWORD => Ok(reg),
-            _ => return Err(Exception::LoadAccessFault),
-        }
+    // 3.1.10 Machine Timer Registers (mtime and mtimecmp)
+    // "A timer interrupt becomes pending whenever mtime contains a value greater than or equal
+    // to mtimecmp, treating the values as unsigned integers."
+    if self.mtime >= self.mtimecmp {
+      // Enable the MTIP bit (MIP, 7).
+      state.write(MIP, state.read(MIP) | MTIP_BIT);
+    }
+  }
+
+  /// Load `size`-bit data from a register located at `addr` in CLINT.
+  pub fn read(&self, addr: u64, size: u8) -> Result<u64, Exception> {
+    // `reg` is the value of a target register in CLINT and `offset` is the byte of the start
+    // position in the register.
+    let (reg, offset) = match addr {
+      MSIP..=MSIP_END => (self.msip as u64, addr - MSIP),
+      MTIMECMP..=MTIMECMP_END => (self.mtimecmp, addr - MTIMECMP),
+      MTIME..=MTIME_END => (self.mtime, addr - MTIME),
+      _ => return Err(Exception::LoadAccessFault),
+    };
+
+    match size {
+      BYTE => Ok((reg >> (offset * 8)) & 0xff),
+      HALFWORD => Ok((reg >> (offset * 8)) & 0xffff),
+      WORD => Ok((reg >> (offset * 8)) & 0xffffffff),
+      DOUBLEWORD => Ok(reg),
+      _ => return Err(Exception::LoadAccessFault),
+    }
+  }
+
+  /// Store `size`-bit data to a register located at `addr` in CLINT.
+  pub fn write(&mut self, addr: u64, value: u64, size: u8) -> Result<(), Exception> {
+    // `reg` is the value of a target register in CLINT and `offset` is the byte of the start
+    // position in the register.
+    let (mut reg, offset) = match addr {
+      MSIP..=MSIP_END => (self.msip as u64, addr - MSIP),
+      MTIMECMP..=MTIMECMP_END => (self.mtimecmp, addr - MTIMECMP),
+      MTIME..=MTIME_END => (self.mtime, addr - MTIME),
+      _ => return Err(Exception::StoreAMOAccessFault),
+    };
+
+    // Calculate the new value of the target register based on `size` and `offset`.
+    match size {
+      BYTE => {
+        // Clear the target byte.
+        reg = reg & (!(0xff << (offset * 8)));
+        // Set the new `value` to the target byte.
+        reg = reg | ((value & 0xff) << (offset * 8));
+      }
+      HALFWORD => {
+        reg = reg & (!(0xffff << (offset * 8)));
+        reg = reg | ((value & 0xffff) << (offset * 8));
+      }
+      WORD => {
+        reg = reg & (!(0xffffffff << (offset * 8)));
+        reg = reg | ((value & 0xffffffff) << (offset * 8));
+      }
+      DOUBLEWORD => {
+        reg = value;
+      }
+      _ => return Err(Exception::StoreAMOAccessFault),
     }
 
-    /// Store `size`-bit data to a register located at `addr` in CLINT.
-    pub fn write(&mut self, addr: u64, value: u64, size: u8) -> Result<(), Exception> {
-        // `reg` is the value of a target register in CLINT and `offset` is the byte of the start
-        // position in the register.
-        let (mut reg, offset) = match addr {
-            MSIP..=MSIP_END => (self.msip as u64, addr - MSIP),
-            MTIMECMP..=MTIMECMP_END => (self.mtimecmp, addr - MTIMECMP),
-            MTIME..=MTIME_END => (self.mtime, addr - MTIME),
-            _ => return Err(Exception::StoreAMOAccessFault),
-        };
-
-        // Calculate the new value of the target register based on `size` and `offset`.
-        match size {
-            BYTE => {
-                // Clear the target byte.
-                reg = reg & (!(0xff << (offset * 8)));
-                // Set the new `value` to the target byte.
-                reg = reg | ((value & 0xff) << (offset * 8));
-            }
-            HALFWORD => {
-                reg = reg & (!(0xffff << (offset * 8)));
-                reg = reg | ((value & 0xffff) << (offset * 8));
-            }
-            WORD => {
-                reg = reg & (!(0xffffffff << (offset * 8)));
-                reg = reg | ((value & 0xffffffff) << (offset * 8));
-            }
-            DOUBLEWORD => {
-                reg = value;
-            }
-            _ => return Err(Exception::StoreAMOAccessFault),
-        }
-
-        // Store the new value to the target register.
-        match addr {
-            MSIP..=MSIP_END => self.msip = reg as u32,
-            MTIMECMP..=MTIMECMP_END => self.mtimecmp = reg,
-            MTIME..=MTIME_END => self.mtime = reg,
-            _ => return Err(Exception::StoreAMOAccessFault),
-        }
-
-        Ok(())
+    // Store the new value to the target register.
+    match addr {
+      MSIP..=MSIP_END => self.msip = reg as u32,
+      MTIMECMP..=MTIMECMP_END => self.mtimecmp = reg,
+      MTIME..=MTIME_END => self.mtime = reg,
+      _ => return Err(Exception::StoreAMOAccessFault),
     }
+
+    Ok(())
+  }
 }
diff --git a/src/devices/mod.rs b/src/devices/mod.rs
index 232a1ef..a7d4344 100644
--- a/src/devices/mod.rs
+++ b/src/devices/mod.rs
@@ -2,7 +2,5 @@
 
 pub mod clint;
 pub mod plic;
-pub mod virtio_blk;
 pub mod uart;
-
-
+pub mod virtio_blk;
diff --git a/src/devices/plic.rs b/src/devices/plic.rs
index 2d0ee44..c9786b6 100644
--- a/src/devices/plic.rs
+++ b/src/devices/plic.rs
@@ -65,157 +65,157 @@ const SOURCE_NUM: u64 = 1024;
 
 /// The platform-level-interrupt controller (PLIC).
 pub struct Plic {
-    /// The interrupt priority for each interrupt source. A priority value of 0 is reserved to mean
-    /// "never interrupt" and effectively disables the interrupt. Priority 1 is the lowest active
-    /// priority, and priority 7 is the highest.
-    priority: [u32; SOURCE_NUM as usize],
-    /// Interrupt pending bits. If bit 1 is set, a global interrupt 1 is pending. A pending bit in
-    /// the PLIC core can be cleared by setting the associated enable bit then performing a claim.
-    pending: [u32; 32],
-    /// Interrupt Enable Bit of Interrupt Source #0 to #1023 for 2 contexts.
-    enable: [u32; 64],
-    /// The settings of a interrupt priority threshold of each context. The PLIC will mask all PLIC
-    /// interrupts of a priority less than or equal to `threshold`.
-    threshold: [u32; 2],
-    /// The ID of the highest priority pending interrupt or zero if there is no pending interrupt
-    /// for each context.
-    claim: [u32; 2],
+  /// The interrupt priority for each interrupt source. A priority value of 0 is reserved to mean
+  /// "never interrupt" and effectively disables the interrupt. Priority 1 is the lowest active
+  /// priority, and priority 7 is the highest.
+  priority: [u32; SOURCE_NUM as usize],
+  /// Interrupt pending bits. If bit 1 is set, a global interrupt 1 is pending. A pending bit in
+  /// the PLIC core can be cleared by setting the associated enable bit then performing a claim.
+  pending: [u32; 32],
+  /// Interrupt Enable Bit of Interrupt Source #0 to #1023 for 2 contexts.
+  enable: [u32; 64],
+  /// The settings of a interrupt priority threshold of each context. The PLIC will mask all PLIC
+  /// interrupts of a priority less than or equal to `threshold`.
+  threshold: [u32; 2],
+  /// The ID of the highest priority pending interrupt or zero if there is no pending interrupt
+  /// for each context.
+  claim: [u32; 2],
 }
 
 impl Plic {
-    /// Create a new PLIC object.
-    pub fn new() -> Self {
-        Self {
-            priority: [0; 1024],
-            pending: [0; 32],
-            enable: [0; 64],
-            threshold: [0; 2],
-            claim: [0; 2],
-        }
+  /// Create a new PLIC object.
+  pub fn new() -> Self {
+    Self {
+      priority: [0; 1024],
+      pending: [0; 32],
+      enable: [0; 64],
+      threshold: [0; 2],
+      claim: [0; 2],
     }
-
-    /// Sets IRQ bit in `pending`.
-    pub fn update_pending(&mut self, irq: u64) {
-        let index = irq.wrapping_div(WORD_SIZE);
-        self.pending[index as usize] = self.pending[index as usize] | (1 << irq);
-
-        self.update_claim(irq);
+  }
+
+  /// Sets IRQ bit in `pending`.
+  pub fn update_pending(&mut self, irq: u64) {
+    let index = irq.wrapping_div(WORD_SIZE);
+    self.pending[index as usize] = self.pending[index as usize] | (1 << irq);
+
+    self.update_claim(irq);
+  }
+
+  /// Clears IRQ bit in `pending`.
+  fn clear_pending(&mut self, irq: u64) {
+    let index = irq.wrapping_div(WORD_SIZE);
+    self.pending[index as usize] = self.pending[index as usize] & !(1 << irq);
+
+    self.update_claim(0);
+  }
+
+  /// Sets IRQ bit in `claim` for context 1.
+  fn update_claim(&mut self, irq: u64) {
+    // TODO: Support highest priority to the `claim` register.
+    // claim[1] is claim/complete registers for S-mode (context 1). SCLAIM.
+    if self.is_enable(1, irq) || irq == 0 {
+      self.claim[1] = irq as u32;
     }
-
-    /// Clears IRQ bit in `pending`.
-    fn clear_pending(&mut self, irq: u64) {
-        let index = irq.wrapping_div(WORD_SIZE);
-        self.pending[index as usize] = self.pending[index as usize] & !(1 << irq);
-
-        self.update_claim(0);
+  }
+
+  /// Returns true if the enable bit for the `irq` of the `context` is set.
+  fn is_enable(&self, context: u64, irq: u64) -> bool {
+    let index = (irq.wrapping_rem(SOURCE_NUM)).wrapping_div(WORD_SIZE * 8);
+    let offset = (irq.wrapping_rem(SOURCE_NUM)).wrapping_rem(WORD_SIZE * 8);
+    return ((self.enable[(context * 32 + index) as usize] >> offset) & 1) == 1;
+  }
+
+  /// Load `size`-bit data from a register located at `addr` in PLIC.
+  pub fn read(&self, addr: u64, size: u8) -> Result<u64, Exception> {
+    // TODO: should support byte-base access.
+    if size != WORD {
+      return Err(Exception::LoadAccessFault);
     }
 
-    /// Sets IRQ bit in `claim` for context 1.
-    fn update_claim(&mut self, irq: u64) {
-        // TODO: Support highest priority to the `claim` register.
-        // claim[1] is claim/complete registers for S-mode (context 1). SCLAIM.
-        if self.is_enable(1, irq) || irq == 0 {
-            self.claim[1] = irq as u32;
+    match addr {
+      SOURCE_PRIORITY..=SOURCE_PRIORITY_END => {
+        if (addr - SOURCE_PRIORITY).wrapping_rem(WORD_SIZE) != 0 {
+          return Err(Exception::LoadAccessFault);
+        }
+        let index = (addr - SOURCE_PRIORITY).wrapping_div(WORD_SIZE);
+        Ok(self.priority[index as usize] as u64)
+      }
+      PENDING..=PENDING_END => {
+        if (addr - PENDING).wrapping_rem(WORD_SIZE) != 0 {
+          return Err(Exception::LoadAccessFault);
+        }
+        let index = (addr - PENDING).wrapping_div(WORD_SIZE);
+        Ok(self.pending[index as usize] as u64)
+      }
+      ENABLE..=ENABLE_END => {
+        if (addr - ENABLE).wrapping_rem(WORD_SIZE) != 0 {
+          return Err(Exception::LoadAccessFault);
         }
+        let index = (addr - ENABLE).wrapping_div(WORD_SIZE);
+        Ok(self.enable[index as usize] as u64)
+      }
+      THRESHOLD_AND_CLAIM..=THRESHOLD_AND_CLAIM_END => {
+        let context = (addr - THRESHOLD_AND_CLAIM).wrapping_div(CONTEXT_OFFSET);
+        let offset = addr - (THRESHOLD_AND_CLAIM + CONTEXT_OFFSET * context);
+        if offset == 0 {
+          Ok(self.threshold[context as usize] as u64)
+        } else if offset == 4 {
+          Ok(self.claim[context as usize] as u64)
+        } else {
+          return Err(Exception::LoadAccessFault);
+        }
+      }
+      _ => return Err(Exception::LoadAccessFault),
     }
+  }
 
-    /// Returns true if the enable bit for the `irq` of the `context` is set.
-    fn is_enable(&self, context: u64, irq: u64) -> bool {
-        let index = (irq.wrapping_rem(SOURCE_NUM)).wrapping_div(WORD_SIZE * 8);
-        let offset = (irq.wrapping_rem(SOURCE_NUM)).wrapping_rem(WORD_SIZE * 8);
-        return ((self.enable[(context * 32 + index) as usize] >> offset) & 1) == 1;
+  /// Store `size`-bit data to a register located at `addr` in PLIC.
+  pub fn write(&mut self, addr: u64, value: u64, size: u8) -> Result<(), Exception> {
+    // TODO: should support byte-base access.
+    if size != WORD {
+      return Err(Exception::StoreAMOAccessFault);
     }
 
-    /// Load `size`-bit data from a register located at `addr` in PLIC.
-    pub fn read(&self, addr: u64, size: u8) -> Result<u64, Exception> {
-        // TODO: should support byte-base access.
-        if size != WORD {
-            return Err(Exception::LoadAccessFault);
+    match addr {
+      SOURCE_PRIORITY..=SOURCE_PRIORITY_END => {
+        if (addr - SOURCE_PRIORITY).wrapping_rem(WORD_SIZE) != 0 {
+          return Err(Exception::StoreAMOAccessFault);
         }
-
-        match addr {
-            SOURCE_PRIORITY..=SOURCE_PRIORITY_END => {
-                if (addr - SOURCE_PRIORITY).wrapping_rem(WORD_SIZE) != 0 {
-                    return Err(Exception::LoadAccessFault);
-                }
-                let index = (addr - SOURCE_PRIORITY).wrapping_div(WORD_SIZE);
-                Ok(self.priority[index as usize] as u64)
-            }
-            PENDING..=PENDING_END => {
-                if (addr - PENDING).wrapping_rem(WORD_SIZE) != 0 {
-                    return Err(Exception::LoadAccessFault);
-                }
-                let index = (addr - PENDING).wrapping_div(WORD_SIZE);
-                Ok(self.pending[index as usize] as u64)
-            }
-            ENABLE..=ENABLE_END => {
-                if (addr - ENABLE).wrapping_rem(WORD_SIZE) != 0 {
-                    return Err(Exception::LoadAccessFault);
-                }
-                let index = (addr - ENABLE).wrapping_div(WORD_SIZE);
-                Ok(self.enable[index as usize] as u64)
-            }
-            THRESHOLD_AND_CLAIM..=THRESHOLD_AND_CLAIM_END => {
-                let context = (addr - THRESHOLD_AND_CLAIM).wrapping_div(CONTEXT_OFFSET);
-                let offset = addr - (THRESHOLD_AND_CLAIM + CONTEXT_OFFSET * context);
-                if offset == 0 {
-                    Ok(self.threshold[context as usize] as u64)
-                } else if offset == 4 {
-                    Ok(self.claim[context as usize] as u64)
-                } else {
-                    return Err(Exception::LoadAccessFault);
-                }
-            }
-            _ => return Err(Exception::LoadAccessFault),
+        let index = (addr - SOURCE_PRIORITY).wrapping_div(WORD_SIZE);
+        self.priority[index as usize] = value as u32;
+      }
+      PENDING..=PENDING_END => {
+        if (addr - PENDING).wrapping_rem(WORD_SIZE) != 0 {
+          return Err(Exception::StoreAMOAccessFault);
         }
-    }
-
-    /// Store `size`-bit data to a register located at `addr` in PLIC.
-    pub fn write(&mut self, addr: u64, value: u64, size: u8) -> Result<(), Exception> {
-        // TODO: should support byte-base access.
-        if size != WORD {
-            return Err(Exception::StoreAMOAccessFault);
+        let index = (addr - PENDING).wrapping_div(WORD_SIZE);
+        self.pending[index as usize] = value as u32;
+      }
+      ENABLE..=ENABLE_END => {
+        if (addr - ENABLE).wrapping_rem(WORD_SIZE) != 0 {
+          return Err(Exception::StoreAMOAccessFault);
         }
-
-        match addr {
-            SOURCE_PRIORITY..=SOURCE_PRIORITY_END => {
-                if (addr - SOURCE_PRIORITY).wrapping_rem(WORD_SIZE) != 0 {
-                    return Err(Exception::StoreAMOAccessFault);
-                }
-                let index = (addr - SOURCE_PRIORITY).wrapping_div(WORD_SIZE);
-                self.priority[index as usize] = value as u32;
-            }
-            PENDING..=PENDING_END => {
-                if (addr - PENDING).wrapping_rem(WORD_SIZE) != 0 {
-                    return Err(Exception::StoreAMOAccessFault);
-                }
-                let index = (addr - PENDING).wrapping_div(WORD_SIZE);
-                self.pending[index as usize] = value as u32;
-            }
-            ENABLE..=ENABLE_END => {
-                if (addr - ENABLE).wrapping_rem(WORD_SIZE) != 0 {
-                    return Err(Exception::StoreAMOAccessFault);
-                }
-                let index = (addr - ENABLE).wrapping_div(WORD_SIZE);
-                self.enable[index as usize] = value as u32;
-            }
-            THRESHOLD_AND_CLAIM..=THRESHOLD_AND_CLAIM_END => {
-                let context = (addr - THRESHOLD_AND_CLAIM).wrapping_div(CONTEXT_OFFSET);
-                let offset = addr - (THRESHOLD_AND_CLAIM + CONTEXT_OFFSET * context);
-                if offset == 0 {
-                    self.threshold[context as usize] = value as u32;
-                } else if offset == 4 {
-                    //self.claim[context as usize] = value as u32;
-
-                    // Clear pending bit.
-                    self.clear_pending(value);
-                } else {
-                    return Err(Exception::StoreAMOAccessFault);
-                }
-            }
-            _ => return Err(Exception::StoreAMOAccessFault),
+        let index = (addr - ENABLE).wrapping_div(WORD_SIZE);
+        self.enable[index as usize] = value as u32;
+      }
+      THRESHOLD_AND_CLAIM..=THRESHOLD_AND_CLAIM_END => {
+        let context = (addr - THRESHOLD_AND_CLAIM).wrapping_div(CONTEXT_OFFSET);
+        let offset = addr - (THRESHOLD_AND_CLAIM + CONTEXT_OFFSET * context);
+        if offset == 0 {
+          self.threshold[context as usize] = value as u32;
+        } else if offset == 4 {
+          //self.claim[context as usize] = value as u32;
+
+          // Clear pending bit.
+          self.clear_pending(value);
+        } else {
+          return Err(Exception::StoreAMOAccessFault);
         }
-
-        Ok(())
+      }
+      _ => return Err(Exception::StoreAMOAccessFault),
     }
+
+    Ok(())
+  }
 }
diff --git a/src/devices/uart.rs b/src/devices/uart.rs
index 97dee47..a43106e 100644
--- a/src/devices/uart.rs
+++ b/src/devices/uart.rs
@@ -5,8 +5,8 @@
 use std::io;
 use std::io::prelude::*;
 use std::sync::{
-    atomic::{AtomicBool, Ordering},
-    Arc, Condvar, Mutex,
+  atomic::{AtomicBool, Ordering},
+  Arc, Condvar, Mutex,
 };
 use std::thread;
 
@@ -49,99 +49,99 @@ const UART_LSR_TX: u8 = 1 << 5;
 
 /// The UART, the size of which is 0x100 (2**8).
 pub struct Uart {
-    uart: Arc<(Mutex<[u8; UART_SIZE as usize]>, Condvar)>,
-    interrupting: Arc<AtomicBool>,
+  uart: Arc<(Mutex<[u8; UART_SIZE as usize]>, Condvar)>,
+  interrupting: Arc<AtomicBool>,
 }
 
 impl Uart {
-    /// Create a new UART object.
-    pub fn new() -> Self {
-        let uart = Arc::new((Mutex::new([0; UART_SIZE as usize]), Condvar::new()));
-        let interrupting = Arc::new(AtomicBool::new(false));
-        {
-            let (uart, _cvar) = &*uart;
-            let mut uart = uart.lock().expect("failed to get an UART object");
-            // Transmitter hold register is empty. It allows input anytime.
-            uart[(UART_LSR - UART_BASE) as usize] |= UART_LSR_TX;
+  /// Create a new UART object.
+  pub fn new() -> Self {
+    let uart = Arc::new((Mutex::new([0; UART_SIZE as usize]), Condvar::new()));
+    let interrupting = Arc::new(AtomicBool::new(false));
+    {
+      let (uart, _cvar) = &*uart;
+      let mut uart = uart.lock().expect("failed to get an UART object");
+      // Transmitter hold register is empty. It allows input anytime.
+      uart[(UART_LSR - UART_BASE) as usize] |= UART_LSR_TX;
+    }
+
+    // Create a new thread for waiting for input.
+    let mut byte = [0; 1];
+    let cloned_uart = uart.clone();
+    let cloned_interrupting = interrupting.clone();
+    let _uart_thread_for_read = thread::spawn(move || loop {
+      match io::stdin().read(&mut byte) {
+        Ok(_) => {
+          let (uart, cvar) = &*cloned_uart;
+          let mut uart = uart.lock().expect("failed to get an UART object");
+          // Wait for the thread to start up.
+          while (uart[(UART_LSR - UART_BASE) as usize] & UART_LSR_RX) == 1 {
+            uart = cvar.wait(uart).expect("the mutex is poisoned");
+          }
+          uart[0] = byte[0];
+          cloned_interrupting.store(true, Ordering::Release);
+          // Data has been receive.
+          uart[(UART_LSR - UART_BASE) as usize] |= UART_LSR_RX;
+        }
+        Err(e) => {
+          println!("input via UART is error: {}", e);
         }
+      }
+    });
 
-        // Create a new thread for waiting for input.
-        let mut byte = [0; 1];
-        let cloned_uart = uart.clone();
-        let cloned_interrupting = interrupting.clone();
-        let _uart_thread_for_read = thread::spawn(move || loop {
-            match io::stdin().read(&mut byte) {
-                Ok(_) => {
-                    let (uart, cvar) = &*cloned_uart;
-                    let mut uart = uart.lock().expect("failed to get an UART object");
-                    // Wait for the thread to start up.
-                    while (uart[(UART_LSR - UART_BASE) as usize] & UART_LSR_RX) == 1 {
-                        uart = cvar.wait(uart).expect("the mutex is poisoned");
-                    }
-                    uart[0] = byte[0];
-                    cloned_interrupting.store(true, Ordering::Release);
-                    // Data has been receive.
-                    uart[(UART_LSR - UART_BASE) as usize] |= UART_LSR_RX;
-                }
-                Err(e) => {
-                    println!("input via UART is error: {}", e);
-                }
-            }
-        });
+    Self { uart, interrupting }
+  }
 
-        Self { uart, interrupting }
-    }
+  /// Return true if an interrupt is pending. Clear the interrupting flag by swapping a value.
+  pub fn is_interrupting(&self) -> bool {
+    self.interrupting.swap(false, Ordering::Acquire)
+  }
 
-    /// Return true if an interrupt is pending. Clear the interrupting flag by swapping a value.
-    pub fn is_interrupting(&self) -> bool {
-        self.interrupting.swap(false, Ordering::Acquire)
+  /// Read a byte from the receive holding register.
+  pub fn read(&mut self, index: u64, size: u8) -> Result<u64, Exception> {
+    if size != BYTE {
+      return Err(Exception::LoadAccessFault);
     }
 
-    /// Read a byte from the receive holding register.
-    pub fn read(&mut self, index: u64, size: u8) -> Result<u64, Exception> {
-        if size != BYTE {
-            return Err(Exception::LoadAccessFault);
-        }
-
-        let (uart, cvar) = &*self.uart;
-        let mut uart = uart.lock().expect("failed to get an UART object");
-        match index {
-            UART_RHR => {
-                cvar.notify_one();
-                uart[(UART_LSR - UART_BASE) as usize] &= !UART_LSR_RX;
-                Ok(uart[(UART_RHR - UART_BASE) as usize] as u64)
-            }
-            _ => Ok(uart[(index - UART_BASE) as usize] as u64),
-        }
+    let (uart, cvar) = &*self.uart;
+    let mut uart = uart.lock().expect("failed to get an UART object");
+    match index {
+      UART_RHR => {
+        cvar.notify_one();
+        uart[(UART_LSR - UART_BASE) as usize] &= !UART_LSR_RX;
+        Ok(uart[(UART_RHR - UART_BASE) as usize] as u64)
+      }
+      _ => Ok(uart[(index - UART_BASE) as usize] as u64),
     }
+  }
 
-    /// Write a byte to the transmit holding register.
-    pub fn write(&mut self, index: u64, value: u8, size: u8) -> Result<(), Exception> {
-        if size != BYTE {
-            return Err(Exception::StoreAMOAccessFault);
-        }
+  /// Write a byte to the transmit holding register.
+  pub fn write(&mut self, index: u64, value: u8, size: u8) -> Result<(), Exception> {
+    if size != BYTE {
+      return Err(Exception::StoreAMOAccessFault);
+    }
 
-        // An OS allows to write a byte to a UART when UART_LSR_TX is 1.
-        // e.g. (xv6):
-        //   // wait for Transmit Holding Empty to be set in LSR.
-        //   while((ReadReg(LSR) & (1 << 5)) == 0)
-        //   ;
-        //   WriteReg(THR, c);
-        //
-        // e.g. (riscv-pk):
-        //   while ((uart16550[UART_REG_LSR << uart16550_reg_shift] & UART_REG_STATUS_TX) == 0);
-        //   uart16550[UART_REG_QUEUE << uart16550_reg_shift] = ch;
-        let (uart, _cvar) = &*self.uart;
-        let mut uart = uart.lock().expect("failed to get an UART object");
-        match index {
-            UART_THR => {
-                print!("{}", value as char);
-                io::stdout().flush().expect("failed to flush stdout");
-            }
-            _ => {
-                uart[(index - UART_BASE) as usize] = value;
-            }
-        }
-        Ok(())
+    // An OS allows to write a byte to a UART when UART_LSR_TX is 1.
+    // e.g. (xv6):
+    //   // wait for Transmit Holding Empty to be set in LSR.
+    //   while((ReadReg(LSR) & (1 << 5)) == 0)
+    //   ;
+    //   WriteReg(THR, c);
+    //
+    // e.g. (riscv-pk):
+    //   while ((uart16550[UART_REG_LSR << uart16550_reg_shift] & UART_REG_STATUS_TX) == 0);
+    //   uart16550[UART_REG_QUEUE << uart16550_reg_shift] = ch;
+    let (uart, _cvar) = &*self.uart;
+    let mut uart = uart.lock().expect("failed to get an UART object");
+    match index {
+      UART_THR => {
+        print!("{}", value as char);
+        io::stdout().flush().expect("failed to flush stdout");
+      }
+      _ => {
+        uart[(index - UART_BASE) as usize] = value;
+      }
     }
+    Ok(())
+  }
 }
diff --git a/src/devices/virtio_blk.rs b/src/devices/virtio_blk.rs
index d5414c9..ac71511 100644
--- a/src/devices/virtio_blk.rs
+++ b/src/devices/virtio_blk.rs
@@ -150,37 +150,37 @@ const CONFIG_END: u64 = VIRTIO_BASE + 0x107;
 /// ```
 #[derive(Debug, Copy, Clone)]
 struct VirtqueueAddr {
-    /// The address that starts actual descriptors (16 bytes each).
-    desc_addr: u64,
-    /// The address that starts a ring of available descriptors.
-    avail_addr: u64,
-    /// The address that starts a ring of used descriptors.
-    used_addr: u64,
+  /// The address that starts actual descriptors (16 bytes each).
+  desc_addr: u64,
+  /// The address that starts a ring of available descriptors.
+  avail_addr: u64,
+  /// The address that starts a ring of used descriptors.
+  used_addr: u64,
 }
 
 impl VirtqueueAddr {
-    /// Create a new virtqueue descriptor based on the address that stores the content of the
-    /// descriptor.
-    fn new(virtio: &Virtio) -> Self {
-        // https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-240006
-        // Virtqueue Part   | Alignment | Size
-        // -------------------------------------------------
-        // Descriptor Table | 16        | 16∗(Queue Size)
-        // Available Ring   | 2         | 6 + 2∗(Queue Size)
-        // Used Ring        | 4         | 6 + 8∗(Queue Size)
-
-        let base_addr = virtio.queue_pfn as u64 * virtio.guest_page_size as u64;
-        let align = virtio.queue_align as u64;
-        let size = virtio.queue_num as u64;
-        let avail_ring_end = base_addr + (16 * size) + (6 + 2 * size);
-
-        Self {
-            desc_addr: base_addr,
-            avail_addr: base_addr + 16 * size,
-            // Used ring starts with the `queue_align` boundary after the available ring ends.
-            used_addr: (avail_ring_end.wrapping_div(align) + 1).wrapping_mul(align),
-        }
+  /// Create a new virtqueue descriptor based on the address that stores the content of the
+  /// descriptor.
+  fn new(virtio: &Virtio) -> Self {
+    // https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-240006
+    // Virtqueue Part   | Alignment | Size
+    // -------------------------------------------------
+    // Descriptor Table | 16        | 16∗(Queue Size)
+    // Available Ring   | 2         | 6 + 2∗(Queue Size)
+    // Used Ring        | 4         | 6 + 8∗(Queue Size)
+
+    let base_addr = virtio.queue_pfn as u64 * virtio.guest_page_size as u64;
+    let align = virtio.queue_align as u64;
+    let size = virtio.queue_num as u64;
+    let avail_ring_end = base_addr + (16 * size) + (6 + 2 * size);
+
+    Self {
+      desc_addr: base_addr,
+      avail_addr: base_addr + 16 * size,
+      // Used ring starts with the `queue_align` boundary after the available ring ends.
+      used_addr: (avail_ring_end.wrapping_div(align) + 1).wrapping_mul(align),
     }
+  }
 }
 
 /// "The descriptor table refers to the buffers the driver is using for the device. addr is a
@@ -208,27 +208,27 @@ impl VirtqueueAddr {
 /// ```
 #[derive(Debug)]
 struct VirtqDesc {
-    /// Address (guest-physical).
-    addr: u64,
-    /// Length.
-    len: u64,
-    /// The flags as indicated VIRTQ_DESC_F_NEXT/VIRTQ_DESC_F_WRITE/VIRTQ_DESC_F_INDIRECT.
-    flags: u64,
-    /// Next field if flags & NEXT.
-    next: u64,
+  /// Address (guest-physical).
+  addr: u64,
+  /// Length.
+  len: u64,
+  /// The flags as indicated VIRTQ_DESC_F_NEXT/VIRTQ_DESC_F_WRITE/VIRTQ_DESC_F_INDIRECT.
+  flags: u64,
+  /// Next field if flags & NEXT.
+  next: u64,
 }
 
 impl VirtqDesc {
-    /// Creates a new virtqueue descriptor based on the address that stores the content of the
-    /// descriptor.
-    fn new(cpu: &mut Cpu, addr: u64) -> Result<Self, Exception> {
-        Ok(Self {
-            addr: cpu.bus.read(addr, DOUBLEWORD)?,
-            len: cpu.bus.read(addr.wrapping_add(8), WORD)?,
-            flags: cpu.bus.read(addr.wrapping_add(12), HALFWORD)?,
-            next: cpu.bus.read(addr.wrapping_add(14), HALFWORD)?,
-        })
-    }
+  /// Creates a new virtqueue descriptor based on the address that stores the content of the
+  /// descriptor.
+  fn new(cpu: &mut Cpu, addr: u64) -> Result<Self, Exception> {
+    Ok(Self {
+      addr: cpu.bus.read(addr, DOUBLEWORD)?,
+      len: cpu.bus.read(addr.wrapping_add(8), WORD)?,
+      flags: cpu.bus.read(addr.wrapping_add(12), HALFWORD)?,
+      next: cpu.bus.read(addr.wrapping_add(14), HALFWORD)?,
+    })
+  }
 }
 
 /// "The driver uses the available ring to offer buffers to the device: each ring entry refers to
@@ -247,369 +247,361 @@ impl VirtqDesc {
 /// ```
 #[derive(Debug)]
 struct VirtqAvail {
-    idx: u16,
-    ring_start_addr: u64,
+  idx: u16,
+  ring_start_addr: u64,
 }
 
 impl VirtqAvail {
-    fn new(cpu: &mut Cpu, addr: u64) -> Result<Self, Exception> {
-        Ok(Self {
-            idx: cpu.bus.read(addr.wrapping_add(2), HALFWORD)? as u16,
-            ring_start_addr: addr.wrapping_add(4),
-        })
-    }
+  fn new(cpu: &mut Cpu, addr: u64) -> Result<Self, Exception> {
+    Ok(Self {
+      idx: cpu.bus.read(addr.wrapping_add(2), HALFWORD)? as u16,
+      ring_start_addr: addr.wrapping_add(4),
+    })
+  }
 }
 
 /// Paravirtualized drivers for IO virtualization.
 pub struct Virtio {
-    id: u64,
-    device_features: [u32; 2],
-    device_features_sel: u32,
-    driver_features: [u32; 2],
-    driver_features_sel: u32,
-    guest_page_size: u32,
-    queue_num: u32,
-    queue_align: u32,
-    queue_pfn: u32,
-    queue_notify: u32,
-    interrupt_status: u32,
-    status: u32,
-    config: [u8; 8],
-    disk: Vec<u8>,
-    virtqueue: Option<VirtqueueAddr>,
+  id: u64,
+  device_features: [u32; 2],
+  device_features_sel: u32,
+  driver_features: [u32; 2],
+  driver_features_sel: u32,
+  guest_page_size: u32,
+  queue_num: u32,
+  queue_align: u32,
+  queue_pfn: u32,
+  queue_notify: u32,
+  interrupt_status: u32,
+  status: u32,
+  config: [u8; 8],
+  disk: Vec<u8>,
+  virtqueue: Option<VirtqueueAddr>,
 }
 
 impl Virtio {
-    /// Creates a new virtio object.
-    pub fn new() -> Self {
-        let mut config = [0; 8];
-        // https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-2440004
-        // 5.2.4 Device configuration layout
-        // struct virtio_blk_config {
-        //   le64 capacity;
-        // }
-        //
-        // The value is based on QEMU's output:
-        // "virtio_blk virtio0: [vda] 204800 512-byte logical blocks (105 MB/100 MiB)"
-        // 204800 --> 0x32000
-        config[1] = 0x20;
-        config[2] = 0x03;
-
-        Self {
-            id: 0,
-            device_features: Virtio::device_features(),
-            device_features_sel: 0,
-            driver_features: [0; 2],
-            driver_features_sel: 0,
-            guest_page_size: 0,
-            queue_num: 0,
-            // default value to avoid division by 0.
-            queue_align: 0x1000,
-            queue_pfn: 0,
-            queue_notify: u32::MAX,
-            interrupt_status: 0,
-            status: 0,
-            config,
-            disk: Vec::new(),
-            virtqueue: None,
-        }
+  /// Creates a new virtio object.
+  pub fn new() -> Self {
+    let mut config = [0; 8];
+    // https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-2440004
+    // 5.2.4 Device configuration layout
+    // struct virtio_blk_config {
+    //   le64 capacity;
+    // }
+    //
+    // The value is based on QEMU's output:
+    // "virtio_blk virtio0: [vda] 204800 512-byte logical blocks (105 MB/100 MiB)"
+    // 204800 --> 0x32000
+    config[1] = 0x20;
+    config[2] = 0x03;
+
+    Self {
+      id: 0,
+      device_features: Virtio::device_features(),
+      device_features_sel: 0,
+      driver_features: [0; 2],
+      driver_features_sel: 0,
+      guest_page_size: 0,
+      queue_num: 0,
+      // default value to avoid division by 0.
+      queue_align: 0x1000,
+      queue_pfn: 0,
+      queue_notify: u32::MAX,
+      interrupt_status: 0,
+      status: 0,
+      config,
+      disk: Vec::new(),
+      virtqueue: None,
     }
-
-    /// Returns device features.
-    fn device_features() -> [u32; 2] {
-        let mut features = [0; 2];
-        // VIRTIO_F_IN_ORDER(Bit 35). This feature indicates that all buffers are used by the device
-        // in the same order in which they have been made available.
-        features[1] = features[1] | (1 << 3);
-        return features;
+  }
+
+  /// Returns device features.
+  fn device_features() -> [u32; 2] {
+    let mut features = [0; 2];
+    // VIRTIO_F_IN_ORDER(Bit 35). This feature indicates that all buffers are used by the device
+    // in the same order in which they have been made available.
+    features[1] = features[1] | (1 << 3);
+    return features;
+  }
+
+  /// Initializes a virtqueue once the device initialization is finished by setting the DRIVER_OK
+  /// status bit (0x4).
+  fn init_virtqueue(&mut self) {
+    let queue = VirtqueueAddr::new(self);
+    self.virtqueue = Some(queue);
+  }
+
+  /// Gets `VirtqueueAddr` struct if it exists. If not, creates a new one based on the virtio
+  /// configuration values.
+  fn virtqueue(&self) -> VirtqueueAddr {
+    match self.virtqueue {
+      Some(queue) => queue,
+      None => VirtqueueAddr::new(self),
     }
-
-    /// Initializes a virtqueue once the device initialization is finished by setting the DRIVER_OK
-    /// status bit (0x4).
-    fn init_virtqueue(&mut self) {
-        let queue = VirtqueueAddr::new(self);
-        self.virtqueue = Some(queue);
+  }
+
+  /// Resets the device when `status` is written to 0.
+  fn reset(&mut self) {
+    self.id = 0;
+    // 4.2.2.1 Device Requirements: MMIO Device Register Layout
+    // "Upon reset, the device MUST clear all bits in InterruptStatus and ready bits in the
+    // QueueReady register for all queues in the device."
+    self.interrupt_status = 0;
+  }
+
+  /// Returns true if an interrupt is pending.
+  pub fn is_interrupting(&mut self) -> bool {
+    if self.queue_notify != u32::MAX {
+      self.queue_notify = u32::MAX;
+      return true;
     }
-
-    /// Gets `VirtqueueAddr` struct if it exists. If not, creates a new one based on the virtio
-    /// configuration values.
-    fn virtqueue(&self) -> VirtqueueAddr {
-        match self.virtqueue {
-            Some(queue) => queue,
-            None => VirtqueueAddr::new(self),
+    false
+  }
+
+  /// Sets the binary in the virtio disk.
+  pub fn initialize(&mut self, binary: Vec<u8>) {
+    self.disk.extend(binary.iter().cloned());
+  }
+
+  /// Loads `size`-bit data from a register located at `addr` in the virtio block device.
+  pub fn read(&self, addr: u64, size: u8) -> Result<u64, Exception> {
+    // `reg` is the value of a target register in the virtio block device and `offset` is the
+    // byte of the start position in the register.
+    let (reg, offset) = match addr {
+      // A Little Endian equivalent of the “virt” string.
+      MAGIC..=MAGIC_END => (0x74726976, addr - MAGIC),
+      // Legacy devices (see 4.2.4 Legacy interface) used 0x1.
+      VERSION..=VERSION_END => (0x1, addr - VERSION),
+      // Block device.
+      DEVICE_ID..=DEVICE_ID_END => (0x2, addr - DEVICE_ID),
+      // See https://github.com/mit-pdos/xv6-riscv/blob/riscv/kernel/virtio_disk.c#L86
+      VENDOR_ID..=VENDOR_ID_END => (0x554d4551, addr - VENDOR_ID),
+      DEVICE_FEATURES..=DEVICE_FEATURES_END => (
+        self.device_features[self.device_features_sel as usize],
+        addr - DEVICE_FEATURES,
+      ),
+      QUEUE_NUM_MAX..=QUEUE_NUM_MAX_END => (QUEUE_SIZE as u32, addr - QUEUE_NUM_MAX),
+      QUEUE_PFN..=QUEUE_PFN_END => (self.queue_pfn, addr - QUEUE_PFN),
+      INTERRUPT_STATUS..=INTERRUPT_STATUS_END => (self.interrupt_status, addr - INTERRUPT_STATUS),
+      STATUS..=STATUS_END => (self.status, addr - STATUS),
+      CONFIG..=CONFIG_END => {
+        if size != BYTE {
+          return Err(Exception::StoreAMOAccessFault);
         }
-    }
-
-    /// Resets the device when `status` is written to 0.
-    fn reset(&mut self) {
-        self.id = 0;
-        // 4.2.2.1 Device Requirements: MMIO Device Register Layout
-        // "Upon reset, the device MUST clear all bits in InterruptStatus and ready bits in the
-        // QueueReady register for all queues in the device."
-        self.interrupt_status = 0;
-    }
-
-    /// Returns true if an interrupt is pending.
-    pub fn is_interrupting(&mut self) -> bool {
-        if self.queue_notify != u32::MAX {
-            self.queue_notify = u32::MAX;
-            return true;
+        let index = addr - CONFIG;
+        (self.config[index as usize] as u32, 0)
+      }
+      _ => return Err(Exception::LoadAccessFault),
+    };
+
+    let value = match size {
+      BYTE => (reg >> (offset * 8)) & 0xff,
+      HALFWORD => (reg >> (offset * 8)) & 0xffff,
+      WORD => (reg >> (offset * 8)) & 0xffffffff,
+      _ => return Err(Exception::LoadAccessFault),
+    };
+
+    Ok(value as u64)
+  }
+
+  /// Stores `size`-bit data to a register located at `addr` in the virtio block device.
+  pub fn write(&mut self, addr: u64, value: u32, size: u8) -> Result<(), Exception> {
+    // `reg` is the value of a target register in the virtio block device and `offset` is the
+    // byte of the start position in the register.
+    let (mut reg, offset) = match addr {
+      DEVICE_FEATURES_SEL..=DEVICE_FEATURES_SEL_END => (self.device_features_sel, addr - DEVICE_FEATURES_SEL),
+      DRIVER_FEATURES..=DRIVER_FEATURES_END => (
+        self.driver_features[self.driver_features_sel as usize],
+        addr - DRIVER_FEATURES,
+      ),
+      DRIVER_FEATURES_SEL..=DRIVER_FEATURES_SEL_END => (self.driver_features_sel, addr - DRIVER_FEATURES_SEL),
+      GUEST_PAGE_SIZE..=GUEST_PAGE_SIZE_END => (self.guest_page_size, addr - GUEST_PAGE_SIZE),
+      QUEUE_SEL..=QUEUE_SEL_END => {
+        if value != 0 {
+          panic!("Multiple virtual queues are not supported.");
         }
-        false
-    }
-
-    /// Sets the binary in the virtio disk.
-    pub fn initialize(&mut self, binary: Vec<u8>) {
-        self.disk.extend(binary.iter().cloned());
-    }
-
-    /// Loads `size`-bit data from a register located at `addr` in the virtio block device.
-    pub fn read(&self, addr: u64, size: u8) -> Result<u64, Exception> {
-        // `reg` is the value of a target register in the virtio block device and `offset` is the
-        // byte of the start position in the register.
-        let (reg, offset) = match addr {
-            // A Little Endian equivalent of the “virt” string.
-            MAGIC..=MAGIC_END => (0x74726976, addr - MAGIC),
-            // Legacy devices (see 4.2.4 Legacy interface) used 0x1.
-            VERSION..=VERSION_END => (0x1, addr - VERSION),
-            // Block device.
-            DEVICE_ID..=DEVICE_ID_END => (0x2, addr - DEVICE_ID),
-            // See https://github.com/mit-pdos/xv6-riscv/blob/riscv/kernel/virtio_disk.c#L86
-            VENDOR_ID..=VENDOR_ID_END => (0x554d4551, addr - VENDOR_ID),
-            DEVICE_FEATURES..=DEVICE_FEATURES_END => (
-                self.device_features[self.device_features_sel as usize],
-                addr - DEVICE_FEATURES,
-            ),
-            QUEUE_NUM_MAX..=QUEUE_NUM_MAX_END => (QUEUE_SIZE as u32, addr - QUEUE_NUM_MAX),
-            QUEUE_PFN..=QUEUE_PFN_END => (self.queue_pfn, addr - QUEUE_PFN),
-            INTERRUPT_STATUS..=INTERRUPT_STATUS_END => {
-                (self.interrupt_status, addr - INTERRUPT_STATUS)
-            }
-            STATUS..=STATUS_END => (self.status, addr - STATUS),
-            CONFIG..=CONFIG_END => {
-                if size != BYTE {
-                    return Err(Exception::StoreAMOAccessFault);
-                }
-                let index = addr - CONFIG;
-                (self.config[index as usize] as u32, 0)
-            }
-            _ => return Err(Exception::LoadAccessFault),
-        };
-
-        let value = match size {
-            BYTE => (reg >> (offset * 8)) & 0xff,
-            HALFWORD => (reg >> (offset * 8)) & 0xffff,
-            WORD => (reg >> (offset * 8)) & 0xffffffff,
-            _ => return Err(Exception::LoadAccessFault),
-        };
-
-        Ok(value as u64)
-    }
-
-    /// Stores `size`-bit data to a register located at `addr` in the virtio block device.
-    pub fn write(&mut self, addr: u64, value: u32, size: u8) -> Result<(), Exception> {
-        // `reg` is the value of a target register in the virtio block device and `offset` is the
-        // byte of the start position in the register.
-        let (mut reg, offset) = match addr {
-            DEVICE_FEATURES_SEL..=DEVICE_FEATURES_SEL_END => {
-                (self.device_features_sel, addr - DEVICE_FEATURES_SEL)
-            }
-            DRIVER_FEATURES..=DRIVER_FEATURES_END => (
-                self.driver_features[self.driver_features_sel as usize],
-                addr - DRIVER_FEATURES,
-            ),
-            DRIVER_FEATURES_SEL..=DRIVER_FEATURES_SEL_END => {
-                (self.driver_features_sel, addr - DRIVER_FEATURES_SEL)
-            }
-            GUEST_PAGE_SIZE..=GUEST_PAGE_SIZE_END => (self.guest_page_size, addr - GUEST_PAGE_SIZE),
-            QUEUE_SEL..=QUEUE_SEL_END => {
-                if value != 0 {
-                    panic!("Multiple virtual queues are not supported.");
-                }
-                return Ok(());
-            }
-            QUEUE_NUM..=QUEUE_NUM_END => (self.queue_num, addr - QUEUE_NUM),
-            QUEUE_ALIGN..=QUEUE_ALIGN_END => (self.queue_align, addr - QUEUE_ALIGN),
-            QUEUE_PFN..=QUEUE_PFN_END => (self.queue_pfn, addr - QUEUE_PFN),
-            QUEUE_NOTIFY..=QUEUE_NOTIFY_END => (self.queue_notify, addr - QUEUE_NOTIFY),
-            INTERRUPT_ACK..=INTERRUPT_ACK_END => {
-                (self.interrupt_status, addr - INTERRUPT_ACK)
-                /*
-                if (value & 0x1) == 1 {
-                    self.interrupt_status &= !0x1;
-                } else {
-                    panic!("unexpected value for INTERRUPT_ACK: {:#x}", value);
-                }
-                return Ok(());
-                */
-            }
-            STATUS..=STATUS_END => (self.status, addr - STATUS),
-            CONFIG..=CONFIG_END => {
-                if size != BYTE {
-                    return Err(Exception::StoreAMOAccessFault);
-                }
-                let index = addr - CONFIG;
-                self.config[index as usize] = (value >> (index * 8)) as u8;
-                return Ok(());
-            }
-            _ => return Err(Exception::StoreAMOAccessFault),
-        };
-
-        // Calculate the new value of the target register based on `size` and `offset`.
-        match size {
-            BYTE => {
-                // Clear the target byte.
-                reg = reg & (!(0xff << (offset * 8)));
-                // Set the new `value` to the target byte.
-                reg = reg | ((value & 0xff) << (offset * 8));
-            }
-            HALFWORD => {
-                reg = reg & (!(0xffff << (offset * 8)));
-                reg = reg | ((value & 0xffff) << (offset * 8));
-            }
-            WORD => {
-                reg = value;
-            }
-            _ => return Err(Exception::StoreAMOAccessFault),
+        return Ok(());
+      }
+      QUEUE_NUM..=QUEUE_NUM_END => (self.queue_num, addr - QUEUE_NUM),
+      QUEUE_ALIGN..=QUEUE_ALIGN_END => (self.queue_align, addr - QUEUE_ALIGN),
+      QUEUE_PFN..=QUEUE_PFN_END => (self.queue_pfn, addr - QUEUE_PFN),
+      QUEUE_NOTIFY..=QUEUE_NOTIFY_END => (self.queue_notify, addr - QUEUE_NOTIFY),
+      INTERRUPT_ACK..=INTERRUPT_ACK_END => {
+        (self.interrupt_status, addr - INTERRUPT_ACK)
+        /*
+        if (value & 0x1) == 1 {
+            self.interrupt_status &= !0x1;
+        } else {
+            panic!("unexpected value for INTERRUPT_ACK: {:#x}", value);
         }
-
-        // Store the new register value to the target register.
-        match addr {
-            DEVICE_FEATURES_SEL..=DEVICE_FEATURES_SEL_END => self.device_features_sel = reg,
-            DRIVER_FEATURES..=DRIVER_FEATURES_END => {
-                self.driver_features[self.driver_features_sel as usize] = reg
-            }
-            DRIVER_FEATURES_SEL..=DRIVER_FEATURES_SEL_END => self.driver_features_sel = reg,
-            GUEST_PAGE_SIZE..=GUEST_PAGE_SIZE_END => self.guest_page_size = reg,
-            QUEUE_NUM..=QUEUE_NUM_END => self.queue_num = reg,
-            QUEUE_ALIGN..=QUEUE_ALIGN_END => self.queue_align = reg,
-            QUEUE_PFN..=QUEUE_PFN_END => self.queue_pfn = reg,
-            QUEUE_NOTIFY..=QUEUE_NOTIFY_END => self.queue_notify = reg,
-            INTERRUPT_ACK..=INTERRUPT_ACK_END => self.interrupt_status = reg,
-            STATUS..=STATUS_END => {
-                self.status = reg;
-                // "Writing 0 into this field resets the device."
-                if self.status == 0 {
-                    self.reset();
-                }
-                // DRIVER_OK bit (4) was set, so initialize `VirtqueueAddr`.
-                if self.status & 0x4 == 1 {
-                    self.init_virtqueue();
-                }
-                // FAILED (128) bit. Indicates that something went wrong in the guest.
-                if (self.status & 128) == 1 {
-                    panic!("virtio: device status FAILED");
-                }
-            }
-            _ => return Err(Exception::StoreAMOAccessFault),
+        return Ok(());
+        */
+      }
+      STATUS..=STATUS_END => (self.status, addr - STATUS),
+      CONFIG..=CONFIG_END => {
+        if size != BYTE {
+          return Err(Exception::StoreAMOAccessFault);
         }
-
-        Ok(())
-    }
-
-    fn read_disk(&self, addr: u64) -> u64 {
-        self.disk[addr as usize] as u64
+        let index = addr - CONFIG;
+        self.config[index as usize] = (value >> (index * 8)) as u8;
+        return Ok(());
+      }
+      _ => return Err(Exception::StoreAMOAccessFault),
+    };
+
+    // Calculate the new value of the target register based on `size` and `offset`.
+    match size {
+      BYTE => {
+        // Clear the target byte.
+        reg = reg & (!(0xff << (offset * 8)));
+        // Set the new `value` to the target byte.
+        reg = reg | ((value & 0xff) << (offset * 8));
+      }
+      HALFWORD => {
+        reg = reg & (!(0xffff << (offset * 8)));
+        reg = reg | ((value & 0xffff) << (offset * 8));
+      }
+      WORD => {
+        reg = value;
+      }
+      _ => return Err(Exception::StoreAMOAccessFault),
     }
 
-    fn write_disk(&mut self, addr: u64, value: u64) {
-        self.disk[addr as usize] = value as u8
+    // Store the new register value to the target register.
+    match addr {
+      DEVICE_FEATURES_SEL..=DEVICE_FEATURES_SEL_END => self.device_features_sel = reg,
+      DRIVER_FEATURES..=DRIVER_FEATURES_END => self.driver_features[self.driver_features_sel as usize] = reg,
+      DRIVER_FEATURES_SEL..=DRIVER_FEATURES_SEL_END => self.driver_features_sel = reg,
+      GUEST_PAGE_SIZE..=GUEST_PAGE_SIZE_END => self.guest_page_size = reg,
+      QUEUE_NUM..=QUEUE_NUM_END => self.queue_num = reg,
+      QUEUE_ALIGN..=QUEUE_ALIGN_END => self.queue_align = reg,
+      QUEUE_PFN..=QUEUE_PFN_END => self.queue_pfn = reg,
+      QUEUE_NOTIFY..=QUEUE_NOTIFY_END => self.queue_notify = reg,
+      INTERRUPT_ACK..=INTERRUPT_ACK_END => self.interrupt_status = reg,
+      STATUS..=STATUS_END => {
+        self.status = reg;
+        // "Writing 0 into this field resets the device."
+        if self.status == 0 {
+          self.reset();
+        }
+        // DRIVER_OK bit (4) was set, so initialize `VirtqueueAddr`.
+        if self.status & 0x4 == 1 {
+          self.init_virtqueue();
+        }
+        // FAILED (128) bit. Indicates that something went wrong in the guest.
+        if (self.status & 128) == 1 {
+          panic!("virtio: device status FAILED");
+        }
+      }
+      _ => return Err(Exception::StoreAMOAccessFault),
     }
 
-    /// Accesses the disk via virtio. This is an associated function which takes a `cpu` object to
-    /// read and write with a memory directly (DMA).
-    pub fn disk_access(cpu: &mut Cpu) -> Result<(), Exception> {
-        // https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-1460002
-        // "Used Buffer Notification
-        //     - bit 0 - the interrupt was asserted because the device has used a buffer in at
-        //     least one of the active virtual queues."
-        cpu.bus.virtio.interrupt_status |= 0x1;
-
-        let virtq = cpu.bus.virtio.virtqueue();
-
-        let avail = VirtqAvail::new(cpu, virtq.avail_addr)?;
-
-        let head_index = cpu.bus.read(
-            avail.ring_start_addr + avail.idx as u64 % QUEUE_SIZE,
-            HALFWORD,
-        )?;
-
-        // First descriptor.
-        let desc0 = VirtqDesc::new(cpu, virtq.desc_addr + VRING_DESC_SIZE * head_index)?;
-        assert_eq!(desc0.flags & VIRTQ_DESC_F_NEXT, 1);
-
-        // Second descriptor.
-        let desc1 = VirtqDesc::new(cpu, virtq.desc_addr + VRING_DESC_SIZE * desc0.next)?;
-        assert_eq!(desc1.flags & VIRTQ_DESC_F_NEXT, 1);
-
-        // 5.2.6 Device Operation
-        // https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-2500006
-        // struct virtio_blk_req {
-        //   le32 type;
-        //   le32 reserved;
-        //   le64 sector;
-        //   u8 data[][512];
-        //   u8 status;
-        // };
-        let sector = cpu.bus.read(desc0.addr.wrapping_add(8), DOUBLEWORD)?;
-
-        // Write to a device if the second bit of `flags` is set.
-        match (desc1.flags & VIRTQ_DESC_F_WRITE) == 0 {
-            true => {
-                // Read memory data and write it to a disk.
-                for i in 0..desc1.len {
-                    let data = cpu.bus.read(desc1.addr + i, BYTE)?;
-                    cpu.bus.virtio.write_disk(sector * SECTOR_SIZE + i, data);
-                }
-            }
-            false => {
-                // Read disk data and write it to memory.
-                for i in 0..desc1.len {
-                    let data = cpu.bus.virtio.read_disk(sector * SECTOR_SIZE + i);
-                    cpu.bus.write(desc1.addr + i, data, BYTE)?;
-                }
-            }
-        };
-
-        // Third descriptor address.
-        let desc2 = VirtqDesc::new(cpu, virtq.desc_addr + VRING_DESC_SIZE * desc1.next)?;
-        assert_eq!(desc2.flags & VIRTQ_DESC_F_NEXT, 0);
-        // Tell success.
-        cpu.bus.write(desc2.addr, 0, BYTE)?;
-
-        // 2.6.7.2 Device Requirements: Used Buffer Notification Suppression
-        // https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-400007
-        // After the device writes a descriptor index into the used ring:
-        //   If flags is 1, the device SHOULD NOT send a notification.
-        //   If flags is 0, the device MUST send a notification.
-        // TODO: check the flags in the available ring.
-
-        // "The used ring is where the device returns buffers once it is done with them: it is only
-        // written to by the device, and read by the driver."
-        //
-        // https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-430008
-        //
-        // ```c
-        // #define VIRTQ_USED_F_NO_NOTIFY 1
-        // struct virtq_used {
-        //   le16 flags;
-        //   le16 idx;
-        //   struct virtq_used_elem ring[ /* Queue Size */];
-        //   le16 avail_event; /* Only if VIRTIO_F_EVENT_IDX */
-        // };
-        // ```
-        cpu.bus.write(
-            virtq
-                .used_addr
-                .wrapping_add(4)
-                .wrapping_add((cpu.bus.virtio.id as u64 % QUEUE_SIZE) * 8),
-            head_index,
-            WORD,
-        )?;
-
-        cpu.bus.virtio.id = cpu.bus.virtio.id.wrapping_add(1);
-        cpu.bus
-            .write(virtq.used_addr.wrapping_add(2), cpu.bus.virtio.id, HALFWORD)?;
-
-        Ok(())
-    }
+    Ok(())
+  }
+
+  fn read_disk(&self, addr: u64) -> u64 {
+    self.disk[addr as usize] as u64
+  }
+
+  fn write_disk(&mut self, addr: u64, value: u64) {
+    self.disk[addr as usize] = value as u8
+  }
+
+  /// Accesses the disk via virtio. This is an associated function which takes a `cpu` object to
+  /// read and write with a memory directly (DMA).
+  pub fn disk_access(cpu: &mut Cpu) -> Result<(), Exception> {
+    // https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-1460002
+    // "Used Buffer Notification
+    //     - bit 0 - the interrupt was asserted because the device has used a buffer in at
+    //     least one of the active virtual queues."
+    cpu.bus.virtio.interrupt_status |= 0x1;
+
+    let virtq = cpu.bus.virtio.virtqueue();
+
+    let avail = VirtqAvail::new(cpu, virtq.avail_addr)?;
+
+    let head_index = cpu
+      .bus
+      .read(avail.ring_start_addr + avail.idx as u64 % QUEUE_SIZE, HALFWORD)?;
+
+    // First descriptor.
+    let desc0 = VirtqDesc::new(cpu, virtq.desc_addr + VRING_DESC_SIZE * head_index)?;
+    assert_eq!(desc0.flags & VIRTQ_DESC_F_NEXT, 1);
+
+    // Second descriptor.
+    let desc1 = VirtqDesc::new(cpu, virtq.desc_addr + VRING_DESC_SIZE * desc0.next)?;
+    assert_eq!(desc1.flags & VIRTQ_DESC_F_NEXT, 1);
+
+    // 5.2.6 Device Operation
+    // https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-2500006
+    // struct virtio_blk_req {
+    //   le32 type;
+    //   le32 reserved;
+    //   le64 sector;
+    //   u8 data[][512];
+    //   u8 status;
+    // };
+    let sector = cpu.bus.read(desc0.addr.wrapping_add(8), DOUBLEWORD)?;
+
+    // Write to a device if the second bit of `flags` is set.
+    match (desc1.flags & VIRTQ_DESC_F_WRITE) == 0 {
+      true => {
+        // Read memory data and write it to a disk.
+        for i in 0..desc1.len {
+          let data = cpu.bus.read(desc1.addr + i, BYTE)?;
+          cpu.bus.virtio.write_disk(sector * SECTOR_SIZE + i, data);
+        }
+      }
+      false => {
+        // Read disk data and write it to memory.
+        for i in 0..desc1.len {
+          let data = cpu.bus.virtio.read_disk(sector * SECTOR_SIZE + i);
+          cpu.bus.write(desc1.addr + i, data, BYTE)?;
+        }
+      }
+    };
+
+    // Third descriptor address.
+    let desc2 = VirtqDesc::new(cpu, virtq.desc_addr + VRING_DESC_SIZE * desc1.next)?;
+    assert_eq!(desc2.flags & VIRTQ_DESC_F_NEXT, 0);
+    // Tell success.
+    cpu.bus.write(desc2.addr, 0, BYTE)?;
+
+    // 2.6.7.2 Device Requirements: Used Buffer Notification Suppression
+    // https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-400007
+    // After the device writes a descriptor index into the used ring:
+    //   If flags is 1, the device SHOULD NOT send a notification.
+    //   If flags is 0, the device MUST send a notification.
+    // TODO: check the flags in the available ring.
+
+    // "The used ring is where the device returns buffers once it is done with them: it is only
+    // written to by the device, and read by the driver."
+    //
+    // https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-430008
+    //
+    // ```c
+    // #define VIRTQ_USED_F_NO_NOTIFY 1
+    // struct virtq_used {
+    //   le16 flags;
+    //   le16 idx;
+    //   struct virtq_used_elem ring[ /* Queue Size */];
+    //   le16 avail_event; /* Only if VIRTIO_F_EVENT_IDX */
+    // };
+    // ```
+    cpu.bus.write(
+      virtq
+        .used_addr
+        .wrapping_add(4)
+        .wrapping_add((cpu.bus.virtio.id as u64 % QUEUE_SIZE) * 8),
+      head_index,
+      WORD,
+    )?;
+
+    cpu.bus.virtio.id = cpu.bus.virtio.id.wrapping_add(1);
+    cpu
+      .bus
+      .write(virtq.used_addr.wrapping_add(2), cpu.bus.virtio.id, HALFWORD)?;
+
+    Ok(())
+  }
 }
diff --git a/src/dram.rs b/src/dram.rs
index f5673a2..c2d421c 100644
--- a/src/dram.rs
+++ b/src/dram.rs
@@ -10,114 +10,114 @@ pub const DRAM_SIZE: u64 = 1024 * 1024 * 1024;
 /// The memory used by the emulator.
 #[derive(Debug)]
 pub struct Dram {
-    pub dram: Vec<u8>,
-    code_size: u64,
+  pub dram: Vec<u8>,
+  code_size: u64,
 }
 
 impl Dram {
-    /// Create a new memory object with default memory size.
-    pub fn new() -> Self {
-        Self {
-            dram: vec![0; DRAM_SIZE as usize],
-            code_size: 0,
-        }
+  /// Create a new memory object with default memory size.
+  pub fn new() -> Self {
+    Self {
+      dram: vec![0; DRAM_SIZE as usize],
+      code_size: 0,
     }
+  }
 
-    /// Set the binary in the memory.
-    pub fn initialize(&mut self, binary: Vec<u8>) {
-        self.code_size = binary.len() as u64;
-        self.dram.splice(..binary.len(), binary.iter().cloned());
-    }
+  /// Set the binary in the memory.
+  pub fn initialize(&mut self, binary: Vec<u8>) {
+    self.code_size = binary.len() as u64;
+    self.dram.splice(..binary.len(), binary.iter().cloned());
+  }
 
-    /// Load `size`-bit data from the memory.
-    pub fn read(&self, addr: u64, size: u8) -> Result<u64, Exception> {
-        match size {
-            BYTE => Ok(self.read8(addr)),
-            HALFWORD => Ok(self.read16(addr)),
-            WORD => Ok(self.read32(addr)),
-            DOUBLEWORD => Ok(self.read64(addr)),
-            _ => return Err(Exception::LoadAccessFault),
-        }
+  /// Load `size`-bit data from the memory.
+  pub fn read(&self, addr: u64, size: u8) -> Result<u64, Exception> {
+    match size {
+      BYTE => Ok(self.read8(addr)),
+      HALFWORD => Ok(self.read16(addr)),
+      WORD => Ok(self.read32(addr)),
+      DOUBLEWORD => Ok(self.read64(addr)),
+      _ => return Err(Exception::LoadAccessFault),
     }
+  }
 
-    /// Store `size`-bit data to the memory.
-    pub fn write(&mut self, addr: u64, value: u64, size: u8) -> Result<(), Exception> {
-        match size {
-            BYTE => self.write8(addr, value),
-            HALFWORD => self.write16(addr, value),
-            WORD => self.write32(addr, value),
-            DOUBLEWORD => self.write64(addr, value),
-            _ => return Err(Exception::StoreAMOAccessFault),
-        }
-        Ok(())
+  /// Store `size`-bit data to the memory.
+  pub fn write(&mut self, addr: u64, value: u64, size: u8) -> Result<(), Exception> {
+    match size {
+      BYTE => self.write8(addr, value),
+      HALFWORD => self.write16(addr, value),
+      WORD => self.write32(addr, value),
+      DOUBLEWORD => self.write64(addr, value),
+      _ => return Err(Exception::StoreAMOAccessFault),
     }
+    Ok(())
+  }
 
-    /// Write a byte to the memory.
-    fn write8(&mut self, addr: u64, val: u64) {
-        let index = (addr - DRAM_BASE) as usize;
-        self.dram[index] = val as u8
-    }
+  /// Write a byte to the memory.
+  fn write8(&mut self, addr: u64, val: u64) {
+    let index = (addr - DRAM_BASE) as usize;
+    self.dram[index] = val as u8
+  }
 
-    /// Write 2 bytes to the memory with little endian.
-    fn write16(&mut self, addr: u64, val: u64) {
-        let index = (addr - DRAM_BASE) as usize;
-        self.dram[index] = (val & 0xff) as u8;
-        self.dram[index + 1] = ((val >> 8) & 0xff) as u8;
-    }
+  /// Write 2 bytes to the memory with little endian.
+  fn write16(&mut self, addr: u64, val: u64) {
+    let index = (addr - DRAM_BASE) as usize;
+    self.dram[index] = (val & 0xff) as u8;
+    self.dram[index + 1] = ((val >> 8) & 0xff) as u8;
+  }
 
-    /// Write 4 bytes to the memory with little endian.
-    fn write32(&mut self, addr: u64, val: u64) {
-        let index = (addr - DRAM_BASE) as usize;
-        self.dram[index] = (val & 0xff) as u8;
-        self.dram[index + 1] = ((val >> 8) & 0xff) as u8;
-        self.dram[index + 2] = ((val >> 16) & 0xff) as u8;
-        self.dram[index + 3] = ((val >> 24) & 0xff) as u8;
-    }
+  /// Write 4 bytes to the memory with little endian.
+  fn write32(&mut self, addr: u64, val: u64) {
+    let index = (addr - DRAM_BASE) as usize;
+    self.dram[index] = (val & 0xff) as u8;
+    self.dram[index + 1] = ((val >> 8) & 0xff) as u8;
+    self.dram[index + 2] = ((val >> 16) & 0xff) as u8;
+    self.dram[index + 3] = ((val >> 24) & 0xff) as u8;
+  }
 
-    /// Write 8 bytes to the memory with little endian.
-    fn write64(&mut self, addr: u64, val: u64) {
-        let index = (addr - DRAM_BASE) as usize;
-        self.dram[index] = (val & 0xff) as u8;
-        self.dram[index + 1] = ((val >> 8) & 0xff) as u8;
-        self.dram[index + 2] = ((val >> 16) & 0xff) as u8;
-        self.dram[index + 3] = ((val >> 24) & 0xff) as u8;
-        self.dram[index + 4] = ((val >> 32) & 0xff) as u8;
-        self.dram[index + 5] = ((val >> 40) & 0xff) as u8;
-        self.dram[index + 6] = ((val >> 48) & 0xff) as u8;
-        self.dram[index + 7] = ((val >> 56) & 0xff) as u8;
-    }
+  /// Write 8 bytes to the memory with little endian.
+  fn write64(&mut self, addr: u64, val: u64) {
+    let index = (addr - DRAM_BASE) as usize;
+    self.dram[index] = (val & 0xff) as u8;
+    self.dram[index + 1] = ((val >> 8) & 0xff) as u8;
+    self.dram[index + 2] = ((val >> 16) & 0xff) as u8;
+    self.dram[index + 3] = ((val >> 24) & 0xff) as u8;
+    self.dram[index + 4] = ((val >> 32) & 0xff) as u8;
+    self.dram[index + 5] = ((val >> 40) & 0xff) as u8;
+    self.dram[index + 6] = ((val >> 48) & 0xff) as u8;
+    self.dram[index + 7] = ((val >> 56) & 0xff) as u8;
+  }
 
-    /// Read a byte from the memory.
-    fn read8(&self, addr: u64) -> u64 {
-        let index = (addr - DRAM_BASE) as usize;
-        self.dram[index] as u64
-    }
+  /// Read a byte from the memory.
+  fn read8(&self, addr: u64) -> u64 {
+    let index = (addr - DRAM_BASE) as usize;
+    self.dram[index] as u64
+  }
 
-    /// Read 2 bytes from the memory with little endian.
-    fn read16(&self, addr: u64) -> u64 {
-        let index = (addr - DRAM_BASE) as usize;
-        return (self.dram[index] as u64) | ((self.dram[index + 1] as u64) << 8);
-    }
+  /// Read 2 bytes from the memory with little endian.
+  fn read16(&self, addr: u64) -> u64 {
+    let index = (addr - DRAM_BASE) as usize;
+    return (self.dram[index] as u64) | ((self.dram[index + 1] as u64) << 8);
+  }
 
-    /// Read 4 bytes from the memory with little endian.
-    fn read32(&self, addr: u64) -> u64 {
-        let index = (addr - DRAM_BASE) as usize;
-        return (self.dram[index] as u64)
-            | ((self.dram[index + 1] as u64) << 8)
-            | ((self.dram[index + 2] as u64) << 16)
-            | ((self.dram[index + 3] as u64) << 24);
-    }
+  /// Read 4 bytes from the memory with little endian.
+  fn read32(&self, addr: u64) -> u64 {
+    let index = (addr - DRAM_BASE) as usize;
+    return (self.dram[index] as u64)
+      | ((self.dram[index + 1] as u64) << 8)
+      | ((self.dram[index + 2] as u64) << 16)
+      | ((self.dram[index + 3] as u64) << 24);
+  }
 
-    /// Read 8 bytes from the memory with little endian.
-    fn read64(&self, addr: u64) -> u64 {
-        let index = (addr - DRAM_BASE) as usize;
-        return (self.dram[index] as u64)
-            | ((self.dram[index + 1] as u64) << 8)
-            | ((self.dram[index + 2] as u64) << 16)
-            | ((self.dram[index + 3] as u64) << 24)
-            | ((self.dram[index + 4] as u64) << 32)
-            | ((self.dram[index + 5] as u64) << 40)
-            | ((self.dram[index + 6] as u64) << 48)
-            | ((self.dram[index + 7] as u64) << 56);
-    }
+  /// Read 8 bytes from the memory with little endian.
+  fn read64(&self, addr: u64) -> u64 {
+    let index = (addr - DRAM_BASE) as usize;
+    return (self.dram[index] as u64)
+      | ((self.dram[index + 1] as u64) << 8)
+      | ((self.dram[index + 2] as u64) << 16)
+      | ((self.dram[index + 3] as u64) << 24)
+      | ((self.dram[index + 4] as u64) << 32)
+      | ((self.dram[index + 5] as u64) << 40)
+      | ((self.dram[index + 6] as u64) << 48)
+      | ((self.dram[index + 7] as u64) << 56);
+  }
 }
diff --git a/src/emulator.rs b/src/emulator.rs
index 14af18b..177d038 100644
--- a/src/emulator.rs
+++ b/src/emulator.rs
@@ -5,148 +5,148 @@ use crate::exception::Trap;
 
 /// The emulator to hold a CPU.
 pub struct Emulator {
-    /// The CPU which is the core implementation of this emulator.
-    pub cpu: Cpu,
-    /// The debug flag. Output messages if it's true, otherwise output nothing.
-    pub is_debug: bool,
+  /// The CPU which is the core implementation of this emulator.
+  pub cpu: Cpu,
+  /// The debug flag. Output messages if it's true, otherwise output nothing.
+  pub is_debug: bool,
 }
 
 impl Emulator {
-    /// Constructor for an emulator.
-    pub fn new() -> Emulator {
-        Self {
-            cpu: Cpu::new(),
-            is_debug: false,
-        }
-    }
-
-    /// Reset CPU state.
-    pub fn reset(&mut self) {
-        self.cpu.reset()
-    }
-
-    /// Set binary data to the beginning of the DRAM from the emulator console.
-    pub fn initialize_dram(&mut self, data: Vec<u8>) {
-        self.cpu.bus.initialize_dram(data);
-    }
-
-    /// Set binary data to the virtio disk from the emulator console.
-    pub fn initialize_disk(&mut self, data: Vec<u8>) {
-        self.cpu.bus.initialize_disk(data);
+  /// Constructor for an emulator.
+  pub fn new() -> Emulator {
+    Self {
+      cpu: Cpu::new(),
+      is_debug: false,
     }
-
-    /// Set the program counter to the CPU field.
-    pub fn initialize_pc(&mut self, pc: u64) {
-        self.cpu.pc = pc;
+  }
+
+  /// Reset CPU state.
+  pub fn reset(&mut self) {
+    self.cpu.reset()
+  }
+
+  /// Set binary data to the beginning of the DRAM from the emulator console.
+  pub fn initialize_dram(&mut self, data: Vec<u8>) {
+    self.cpu.bus.initialize_dram(data);
+  }
+
+  /// Set binary data to the virtio disk from the emulator console.
+  pub fn initialize_disk(&mut self, data: Vec<u8>) {
+    self.cpu.bus.initialize_disk(data);
+  }
+
+  /// Set the program counter to the CPU field.
+  pub fn initialize_pc(&mut self, pc: u64) {
+    self.cpu.pc = pc;
+  }
+
+  /// Start executing the emulator with limited range of program. This method is for test.
+  /// No interrupts happen.
+  pub fn test_start(&mut self, start: u64, end: u64) {
+    println!("----- test start -----");
+    let mut count = 0;
+    loop {
+      count += 1;
+      if self.cpu.pc < start || end <= self.cpu.pc {
+        return;
+      }
+      // This is a workaround for unit tests to finish the execution.
+      if count > 1000 {
+        return;
+      }
+
+      match self.cpu.execute() {
+        Ok(inst) => {
+          println!("pc: {:#x}, inst: {:#x}", self.cpu.pc.wrapping_sub(4), inst);
+          Trap::Requested
+        }
+        Err(exception) => {
+          println!("pc: {:#x}, exception: {:?}", self.cpu.pc, exception);
+          exception.take_trap(&mut self.cpu)
+        }
+      };
     }
+  }
+
+  /// Start executing the emulator for debug.
+  fn debug_start(&mut self) {
+    let mut count = 0;
+    loop {
+      count += 1;
+      if self.cpu.is_count && count > 50000000 {
+        return;
+      }
+
+      // Run a cycle on peripheral devices.
+      self.cpu.devices_increment();
+
+      // Take an interrupt.
+      match self.cpu.check_pending_interrupt() {
+        Some(interrupt) => interrupt.take_trap(&mut self.cpu),
+        None => {}
+      }
+
+      // Execute an instruction.
+      let trap = match self.cpu.execute() {
+        Ok(inst) => {
+          if self.is_debug {
+            println!(
+              "pc: {:#x}, inst: {:#x}, is_inst 16? {} pre_inst: {:#x}",
+              self.cpu.pc.wrapping_sub(4),
+              inst,
+              // Check if an instruction is one of the compressed instructions.
+              inst & 0b11 == 0 || inst & 0b11 == 1 || inst & 0b11 == 2,
+              self.cpu.pre_inst,
+            );
+          }
+          // Return a placeholder trap.
+          Trap::Requested
+        }
+        Err(exception) => exception.take_trap(&mut self.cpu),
+      };
 
-    /// Start executing the emulator with limited range of program. This method is for test.
-    /// No interrupts happen.
-    pub fn test_start(&mut self, start: u64, end: u64) {
-        println!("----- test start -----");
-        let mut count = 0;
-        loop {
-            count += 1;
-            if self.cpu.pc < start || end <= self.cpu.pc {
-                return;
-            }
-            // This is a workaround for unit tests to finish the execution.
-            if count > 1000 {
-                return;
-            }
-
-            match self.cpu.execute() {
-                Ok(inst) => {
-                    println!("pc: {:#x}, inst: {:#x}", self.cpu.pc.wrapping_sub(4), inst);
-                    Trap::Requested
-                }
-                Err(exception) => {
-                    println!("pc: {:#x}, exception: {:?}", self.cpu.pc, exception);
-                    exception.take_trap(&mut self.cpu)
-                }
-            };
+      match trap {
+        Trap::Fatal => {
+          println!("pc: {:#x}, trap {:#?}", self.cpu.pc, trap);
+          return;
         }
+        _ => {}
+      }
     }
+  }
 
-    /// Start executing the emulator for debug.
-    fn debug_start(&mut self) {
-        let mut count = 0;
-        loop {
-            count += 1;
-            if self.cpu.is_count && count > 50000000 {
-                return;
-            }
-
-            // Run a cycle on peripheral devices.
-            self.cpu.devices_increment();
-
-            // Take an interrupt.
-            match self.cpu.check_pending_interrupt() {
-                Some(interrupt) => interrupt.take_trap(&mut self.cpu),
-                None => {}
-            }
-
-            // Execute an instruction.
-            let trap = match self.cpu.execute() {
-                Ok(inst) => {
-                    if self.is_debug {
-                        println!(
-                            "pc: {:#x}, inst: {:#x}, is_inst 16? {} pre_inst: {:#x}",
-                            self.cpu.pc.wrapping_sub(4),
-                            inst,
-                            // Check if an instruction is one of the compressed instructions.
-                            inst & 0b11 == 0 || inst & 0b11 == 1 || inst & 0b11 == 2,
-                            self.cpu.pre_inst,
-                        );
-                    }
-                    // Return a placeholder trap.
-                    Trap::Requested
-                }
-                Err(exception) => exception.take_trap(&mut self.cpu),
-            };
-
-            match trap {
-                Trap::Fatal => {
-                    println!("pc: {:#x}, trap {:#?}", self.cpu.pc, trap);
-                    return;
-                }
-                _ => {}
-            }
-        }
+  /// Start executing the emulator.
+  pub fn start(&mut self) {
+    if self.is_debug || self.cpu.is_count {
+      self.debug_start();
     }
 
-    /// Start executing the emulator.
-    pub fn start(&mut self) {
-        if self.is_debug || self.cpu.is_count {
-            self.debug_start();
+    loop {
+      // Run a cycle on peripheral devices.
+      self.cpu.devices_increment();
+
+      // Take an interrupt.
+      match self.cpu.check_pending_interrupt() {
+        Some(interrupt) => interrupt.take_trap(&mut self.cpu),
+        None => {}
+      }
+
+      // Execute an instruction.
+      let trap = match self.cpu.execute() {
+        Ok(_) => {
+          // Return a placeholder trap.
+          Trap::Requested
         }
+        Err(exception) => exception.take_trap(&mut self.cpu),
+      };
 
-        loop {
-            // Run a cycle on peripheral devices.
-            self.cpu.devices_increment();
-
-            // Take an interrupt.
-            match self.cpu.check_pending_interrupt() {
-                Some(interrupt) => interrupt.take_trap(&mut self.cpu),
-                None => {}
-            }
-
-            // Execute an instruction.
-            let trap = match self.cpu.execute() {
-                Ok(_) => {
-                    // Return a placeholder trap.
-                    Trap::Requested
-                }
-                Err(exception) => exception.take_trap(&mut self.cpu),
-            };
-
-            match trap {
-                Trap::Fatal => {
-                    println!("pc: {:#x}, trap {:#?}", self.cpu.pc, trap);
-                    return;
-                }
-                _ => {}
-            }
+      match trap {
+        Trap::Fatal => {
+          println!("pc: {:#x}, trap {:#?}", self.cpu.pc, trap);
+          return;
         }
+        _ => {}
+      }
     }
+  }
 }
diff --git a/src/exception.rs b/src/exception.rs
index 5f3092f..8355f93 100644
--- a/src/exception.rs
+++ b/src/exception.rs
@@ -1,75 +1,75 @@
 //! The exception module contains all the exception kinds and the function to handle exceptions.
 
 use crate::{
-    cpu::{Cpu, Mode},
-    csr::*,
+  cpu::{Cpu, Mode},
+  csr::*,
 };
 
 /// All the exception kinds.
 #[derive(Debug, PartialEq)]
 pub enum Exception {
-    /// With the addition of the C extension, no instructions can raise
-    /// instruction-address-misaligned exceptions.
-    InstructionAddressMisaligned,
-    InstructionAccessFault,
-    IllegalInstruction(u64),
-    Breakpoint,
-    LoadAddressMisaligned,
-    LoadAccessFault,
-    StoreAMOAddressMisaligned,
-    StoreAMOAccessFault,
-    EnvironmentCallFromUMode,
-    EnvironmentCallFromSMode,
-    EnvironmentCallFromMMode,
-    // Stores a trap value (the faulting address) for page fault exceptions.
-    InstructionPageFault(u64),
-    LoadPageFault(u64),
-    StoreAMOPageFault(u64),
+  /// With the addition of the C extension, no instructions can raise
+  /// instruction-address-misaligned exceptions.
+  InstructionAddressMisaligned,
+  InstructionAccessFault,
+  IllegalInstruction(u64),
+  Breakpoint,
+  LoadAddressMisaligned,
+  LoadAccessFault,
+  StoreAMOAddressMisaligned,
+  StoreAMOAccessFault,
+  EnvironmentCallFromUMode,
+  EnvironmentCallFromSMode,
+  EnvironmentCallFromMMode,
+  // Stores a trap value (the faulting address) for page fault exceptions.
+  InstructionPageFault(u64),
+  LoadPageFault(u64),
+  StoreAMOPageFault(u64),
 }
 
 /// All the trap kinds.
 #[derive(Debug)]
 pub enum Trap {
-    /// The trap is visible to, and handled by, software running inside the execution
-    /// environment.
-    Contained,
-    /// The trap is a synchronous exception that is an explicit call to the execution
-    /// environment requesting an action on behalf of software inside the execution environment.
-    Requested,
-    /// The trap is handled transparently by the execution environment and execution
-    /// resumes normally after the trap is handled.
-    Invisible,
-    /// The trap represents a fatal failure and causes the execution environment to terminate
-    /// execution.
-    Fatal,
+  /// The trap is visible to, and handled by, software running inside the execution
+  /// environment.
+  Contained,
+  /// The trap is a synchronous exception that is an explicit call to the execution
+  /// environment requesting an action on behalf of software inside the execution environment.
+  Requested,
+  /// The trap is handled transparently by the execution environment and execution
+  /// resumes normally after the trap is handled.
+  Invisible,
+  /// The trap represents a fatal failure and causes the execution environment to terminate
+  /// execution.
+  Fatal,
 }
 
 impl Exception {
-    fn exception_code(&self) -> u64 {
-        match self {
-            Exception::InstructionAddressMisaligned => 0,
-            Exception::InstructionAccessFault => 1,
-            Exception::IllegalInstruction(_) => 2,
-            Exception::Breakpoint => 3,
-            Exception::LoadAddressMisaligned => 4,
-            Exception::LoadAccessFault => 5,
-            Exception::StoreAMOAddressMisaligned => 6,
-            Exception::StoreAMOAccessFault => 7,
-            Exception::EnvironmentCallFromUMode => 8,
-            Exception::EnvironmentCallFromSMode => 9,
-            Exception::EnvironmentCallFromMMode => 11,
-            Exception::InstructionPageFault(_) => 12,
-            Exception::LoadPageFault(_) => 13,
-            Exception::StoreAMOPageFault(_) => 15,
-        }
+  fn exception_code(&self) -> u64 {
+    match self {
+      Exception::InstructionAddressMisaligned => 0,
+      Exception::InstructionAccessFault => 1,
+      Exception::IllegalInstruction(_) => 2,
+      Exception::Breakpoint => 3,
+      Exception::LoadAddressMisaligned => 4,
+      Exception::LoadAccessFault => 5,
+      Exception::StoreAMOAddressMisaligned => 6,
+      Exception::StoreAMOAccessFault => 7,
+      Exception::EnvironmentCallFromUMode => 8,
+      Exception::EnvironmentCallFromSMode => 9,
+      Exception::EnvironmentCallFromMMode => 11,
+      Exception::InstructionPageFault(_) => 12,
+      Exception::LoadPageFault(_) => 13,
+      Exception::StoreAMOPageFault(_) => 15,
     }
-
-    fn epc(&self, pc: u64) -> u64 {
-        // 3.2.1 Environment Call and Breakpoint
-        // "ECALL and EBREAK cause the receiving privilege mode’s epc register to be set to the
-        // address of the ECALL or EBREAK instruction itself, not the address of the following
-        // instruction."
-        match self {
+  }
+
+  fn epc(&self, pc: u64) -> u64 {
+    // 3.2.1 Environment Call and Breakpoint
+    // "ECALL and EBREAK cause the receiving privilege mode’s epc register to be set to the
+    // address of the ECALL or EBREAK instruction itself, not the address of the following
+    // instruction."
+    match self {
             Exception::Breakpoint
             | Exception::EnvironmentCallFromUMode
             | Exception::EnvironmentCallFromSMode
@@ -80,155 +80,151 @@ impl Exception {
             | Exception::StoreAMOPageFault(_) => pc,
             _ => pc.wrapping_add(4),
         }
+  }
+
+  fn trap_value(&self, pc: u64) -> u64 {
+    // 3.1.17 Machine Trap Value Register (mtval)
+    // 4.1.9 Supervisor Trap Value Register (stval)
+    // "When a hardware breakpoint is triggered, or an address-misaligned, access-fault, or
+    // page-fault exception occurs on an instruction fetch, load, or store, mtval (stval) is
+    // written with the faulting virtual address. On an illegal instruction trap, mtval (stval)
+    // may be written with the first XLEN or ILEN bits of the faulting instruction as described
+    // below. For other traps, mtval (stval) is set to zero, but a future standard may redefine
+    // mtval's (stval's) setting for other traps."
+    match self {
+      Exception::InstructionAddressMisaligned
+      | Exception::InstructionAccessFault
+      | Exception::Breakpoint
+      | Exception::LoadAddressMisaligned
+      | Exception::LoadAccessFault
+      | Exception::StoreAMOAddressMisaligned
+      | Exception::StoreAMOAccessFault => pc,
+      Exception::InstructionPageFault(val) | Exception::LoadPageFault(val) | Exception::StoreAMOPageFault(val) => *val,
+      Exception::IllegalInstruction(val) => *val,
+      _ => 0,
     }
-
-    fn trap_value(&self, pc: u64) -> u64 {
-        // 3.1.17 Machine Trap Value Register (mtval)
-        // 4.1.9 Supervisor Trap Value Register (stval)
-        // "When a hardware breakpoint is triggered, or an address-misaligned, access-fault, or
-        // page-fault exception occurs on an instruction fetch, load, or store, mtval (stval) is
-        // written with the faulting virtual address. On an illegal instruction trap, mtval (stval)
-        // may be written with the first XLEN or ILEN bits of the faulting instruction as described
-        // below. For other traps, mtval (stval) is set to zero, but a future standard may redefine
-        // mtval's (stval's) setting for other traps."
-        match self {
-            Exception::InstructionAddressMisaligned
-            | Exception::InstructionAccessFault
-            | Exception::Breakpoint
-            | Exception::LoadAddressMisaligned
-            | Exception::LoadAccessFault
-            | Exception::StoreAMOAddressMisaligned
-            | Exception::StoreAMOAccessFault => pc,
-            Exception::InstructionPageFault(val)
-            | Exception::LoadPageFault(val)
-            | Exception::StoreAMOPageFault(val) => *val,
-            Exception::IllegalInstruction(val) => *val,
-            _ => 0,
-        }
+  }
+
+  /// Update CSRs and the program counter depending on an exception.
+  pub fn take_trap(&self, cpu: &mut Cpu) -> Trap {
+    // 1.2 Privilege Levels
+    // "Traps that increase privilege level are termed vertical traps, while traps that remain
+    // at the same privilege level are termed horizontal traps."
+
+    let exception_pc = self.epc(cpu.pc);
+    let previous_mode = cpu.mode;
+    let cause = self.exception_code();
+
+    // 3.1.8 Machine Trap Delegation Registers (medeleg and mideleg)
+    // "By default, all traps at any privilege level are handled in machine mode"
+    // "To increase performance, implementations can provide individual read/write bits within
+    // medeleg and mideleg to indicate that certain exceptions and interrupts should be
+    // processed directly by a lower privilege level."
+    //
+    // "medeleg has a bit position allocated for every synchronous exception shown in Table 3.6
+    // on page 37, with the index of the bit position equal to the value returned in the mcause
+    // register (i.e., setting bit 8 allows user-mode environment calls to be delegated to a
+    // lower-privilege trap handler)."
+    if previous_mode <= Mode::Supervisor && ((cpu.state.read(MEDELEG) >> cause) & 1) == 1 {
+      // Handle the trap in S-mode.
+      cpu.mode = Mode::Supervisor;
+
+      // Set the program counter to the supervisor trap-handler base address (stvec).
+      cpu.pc = (cpu.state.read(STVEC) & !1) as u64;
+
+      // 4.1.9 Supervisor Exception Program Counter (sepc)
+      // "The low bit of sepc (sepc[0]) is always zero."
+      // "When a trap is taken into S-mode, sepc is written with the virtual address of
+      // the instruction that was interrupted or that encountered the exception.
+      // Otherwise, sepc is never written by the implementation, though it may be
+      // explicitly written by software."
+      cpu.state.write(SEPC, exception_pc & !1);
+
+      // 4.1.10 Supervisor Cause Register (scause)
+      // "When a trap is taken into S-mode, scause is written with a code indicating
+      // the event that caused the trap.  Otherwise, scause is never written by the
+      // implementation, though it may be explicitly written by software."
+      cpu.state.write(SCAUSE, cause);
+
+      // 4.1.11 Supervisor Trap Value (stval) Register
+      // "When a trap is taken into S-mode, stval is written with exception-specific
+      // information to assist software in handling the trap. Otherwise, stval is never
+      // written by the implementation, though it may be explicitly written by software."
+      cpu.state.write(STVAL, self.trap_value(exception_pc));
+
+      // Set a previous interrupt-enable bit for supervisor mode (SPIE, 5) to the value
+      // of a global interrupt-enable bit for supervisor mode (SIE, 1).
+      cpu
+        .state
+        .write_sstatus(XSTATUS_SPIE, cpu.state.read_sstatus(XSTATUS_SIE));
+      // Set a global interrupt-enable bit for supervisor mode (SIE, 1) to 0.
+      cpu.state.write_sstatus(XSTATUS_SIE, 0);
+      // 4.1.1 Supervisor Status Register (sstatus)
+      // "When a trap is taken, SPP is set to 0 if the trap originated from user mode, or
+      // 1 otherwise."
+      match previous_mode {
+        Mode::User => cpu.state.write_sstatus(XSTATUS_SPP, 0),
+        _ => cpu.state.write_sstatus(XSTATUS_SPP, 1),
+      }
+    } else {
+      // Handle the trap in M-mode.
+      cpu.mode = Mode::Machine;
+
+      // Set the program counter to the machine trap-handler base address (mtvec).
+      cpu.pc = (cpu.state.read(MTVEC) & !1) as u64;
+
+      // 3.1.15 Machine Exception Program Counter (mepc)
+      // "The low bit of mepc (mepc[0]) is always zero."
+      // "When a trap is taken into M-mode, mepc is written with the virtual address of
+      // the instruction that was interrupted or that encountered the exception.
+      // Otherwise, mepc is never written by the implementation, though it may be
+      // explicitly written by software."
+      cpu.state.write(MEPC, exception_pc & !1);
+
+      // 3.1.16 Machine Cause Register (mcause)
+      // "When a trap is taken into M-mode, mcause is written with a code indicating
+      // the event that caused the trap. Otherwise, mcause is never written by the
+      // implementation, though it may be explicitly written by software."
+      cpu.state.write(MCAUSE, cause);
+
+      // 3.1.17 Machine Trap Value (mtval) Register
+      // "When a trap is taken into M-mode, mtval is either set to zero or written with
+      // exception-specific information to assist software in handling the trap.
+      // Otherwise, mtval is never written by the implementation, though it may be
+      // explicitly written by software."
+      cpu.state.write(MTVAL, self.trap_value(exception_pc));
+
+      // Set a previous interrupt-enable bit for machine mode (MPIE, 7) to the value
+      // of a global interrupt-enable bit for machine mode (MIE, 3).
+      cpu
+        .state
+        .write_mstatus(MSTATUS_MPIE, cpu.state.read_mstatus(MSTATUS_MIE));
+      // Set a global interrupt-enable bit for machine mode (MIE, 3) to 0.
+      cpu.state.write_mstatus(MSTATUS_MIE, 0);
+      // When a trap is taken from privilege mode y into privilege mode x, xPIE is set
+      // to the value of x IE; x IE is set to 0; and xPP is set to y.
+      match previous_mode {
+        Mode::User => cpu.state.write_mstatus(MSTATUS_MPP, Mode::User as u64),
+        Mode::Supervisor => cpu.state.write_mstatus(MSTATUS_MPP, Mode::Supervisor as u64),
+        Mode::Machine => cpu.state.write_mstatus(MSTATUS_MPP, Mode::Machine as u64),
+        _ => panic!("previous privilege mode is invalid"),
+      }
     }
 
-    /// Update CSRs and the program counter depending on an exception.
-    pub fn take_trap(&self, cpu: &mut Cpu) -> Trap {
-        // 1.2 Privilege Levels
-        // "Traps that increase privilege level are termed vertical traps, while traps that remain
-        // at the same privilege level are termed horizontal traps."
-
-        let exception_pc = self.epc(cpu.pc);
-        let previous_mode = cpu.mode;
-        let cause = self.exception_code();
-
-        // 3.1.8 Machine Trap Delegation Registers (medeleg and mideleg)
-        // "By default, all traps at any privilege level are handled in machine mode"
-        // "To increase performance, implementations can provide individual read/write bits within
-        // medeleg and mideleg to indicate that certain exceptions and interrupts should be
-        // processed directly by a lower privilege level."
-        //
-        // "medeleg has a bit position allocated for every synchronous exception shown in Table 3.6
-        // on page 37, with the index of the bit position equal to the value returned in the mcause
-        // register (i.e., setting bit 8 allows user-mode environment calls to be delegated to a
-        // lower-privilege trap handler)."
-        if previous_mode <= Mode::Supervisor && ((cpu.state.read(MEDELEG) >> cause) & 1) == 1 {
-            // Handle the trap in S-mode.
-            cpu.mode = Mode::Supervisor;
-
-            // Set the program counter to the supervisor trap-handler base address (stvec).
-            cpu.pc = (cpu.state.read(STVEC) & !1) as u64;
-
-            // 4.1.9 Supervisor Exception Program Counter (sepc)
-            // "The low bit of sepc (sepc[0]) is always zero."
-            // "When a trap is taken into S-mode, sepc is written with the virtual address of
-            // the instruction that was interrupted or that encountered the exception.
-            // Otherwise, sepc is never written by the implementation, though it may be
-            // explicitly written by software."
-            cpu.state.write(SEPC, exception_pc & !1);
-
-            // 4.1.10 Supervisor Cause Register (scause)
-            // "When a trap is taken into S-mode, scause is written with a code indicating
-            // the event that caused the trap.  Otherwise, scause is never written by the
-            // implementation, though it may be explicitly written by software."
-            cpu.state.write(SCAUSE, cause);
-
-            // 4.1.11 Supervisor Trap Value (stval) Register
-            // "When a trap is taken into S-mode, stval is written with exception-specific
-            // information to assist software in handling the trap. Otherwise, stval is never
-            // written by the implementation, though it may be explicitly written by software."
-            cpu.state.write(STVAL, self.trap_value(exception_pc));
-
-            // Set a previous interrupt-enable bit for supervisor mode (SPIE, 5) to the value
-            // of a global interrupt-enable bit for supervisor mode (SIE, 1).
-            cpu.state
-                .write_sstatus(XSTATUS_SPIE, cpu.state.read_sstatus(XSTATUS_SIE));
-            // Set a global interrupt-enable bit for supervisor mode (SIE, 1) to 0.
-            cpu.state.write_sstatus(XSTATUS_SIE, 0);
-            // 4.1.1 Supervisor Status Register (sstatus)
-            // "When a trap is taken, SPP is set to 0 if the trap originated from user mode, or
-            // 1 otherwise."
-            match previous_mode {
-                Mode::User => cpu.state.write_sstatus(XSTATUS_SPP, 0),
-                _ => cpu.state.write_sstatus(XSTATUS_SPP, 1),
-            }
-        } else {
-            // Handle the trap in M-mode.
-            cpu.mode = Mode::Machine;
-
-            // Set the program counter to the machine trap-handler base address (mtvec).
-            cpu.pc = (cpu.state.read(MTVEC) & !1) as u64;
-
-            // 3.1.15 Machine Exception Program Counter (mepc)
-            // "The low bit of mepc (mepc[0]) is always zero."
-            // "When a trap is taken into M-mode, mepc is written with the virtual address of
-            // the instruction that was interrupted or that encountered the exception.
-            // Otherwise, mepc is never written by the implementation, though it may be
-            // explicitly written by software."
-            cpu.state.write(MEPC, exception_pc & !1);
-
-            // 3.1.16 Machine Cause Register (mcause)
-            // "When a trap is taken into M-mode, mcause is written with a code indicating
-            // the event that caused the trap. Otherwise, mcause is never written by the
-            // implementation, though it may be explicitly written by software."
-            cpu.state.write(MCAUSE, cause);
-
-            // 3.1.17 Machine Trap Value (mtval) Register
-            // "When a trap is taken into M-mode, mtval is either set to zero or written with
-            // exception-specific information to assist software in handling the trap.
-            // Otherwise, mtval is never written by the implementation, though it may be
-            // explicitly written by software."
-            cpu.state.write(MTVAL, self.trap_value(exception_pc));
-
-            // Set a previous interrupt-enable bit for machine mode (MPIE, 7) to the value
-            // of a global interrupt-enable bit for machine mode (MIE, 3).
-            cpu.state
-                .write_mstatus(MSTATUS_MPIE, cpu.state.read_mstatus(MSTATUS_MIE));
-            // Set a global interrupt-enable bit for machine mode (MIE, 3) to 0.
-            cpu.state.write_mstatus(MSTATUS_MIE, 0);
-            // When a trap is taken from privilege mode y into privilege mode x, xPIE is set
-            // to the value of x IE; x IE is set to 0; and xPP is set to y.
-            match previous_mode {
-                Mode::User => cpu.state.write_mstatus(MSTATUS_MPP, Mode::User as u64),
-                Mode::Supervisor => cpu
-                    .state
-                    .write_mstatus(MSTATUS_MPP, Mode::Supervisor as u64),
-                Mode::Machine => cpu.state.write_mstatus(MSTATUS_MPP, Mode::Machine as u64),
-                _ => panic!("previous privilege mode is invalid"),
-            }
-        }
-
-        match self {
-            Exception::InstructionAddressMisaligned | Exception::InstructionAccessFault => {
-                Trap::Fatal
-            }
-            Exception::IllegalInstruction(_) => Trap::Invisible,
-            Exception::Breakpoint => Trap::Requested,
-            Exception::LoadAddressMisaligned
-            | Exception::LoadAccessFault
-            | Exception::StoreAMOAddressMisaligned
-            | Exception::StoreAMOAccessFault => Trap::Fatal,
-            Exception::EnvironmentCallFromUMode
-            | Exception::EnvironmentCallFromSMode
-            | Exception::EnvironmentCallFromMMode => Trap::Fatal,
-            Exception::InstructionPageFault(_)
-            | Exception::LoadPageFault(_)
-            | Exception::StoreAMOPageFault(_) => Trap::Invisible,
-        }
+    match self {
+      Exception::InstructionAddressMisaligned | Exception::InstructionAccessFault => Trap::Fatal,
+      Exception::IllegalInstruction(_) => Trap::Invisible,
+      Exception::Breakpoint => Trap::Requested,
+      Exception::LoadAddressMisaligned
+      | Exception::LoadAccessFault
+      | Exception::StoreAMOAddressMisaligned
+      | Exception::StoreAMOAccessFault => Trap::Fatal,
+      Exception::EnvironmentCallFromUMode
+      | Exception::EnvironmentCallFromSMode
+      | Exception::EnvironmentCallFromMMode => Trap::Fatal,
+      Exception::InstructionPageFault(_) | Exception::LoadPageFault(_) | Exception::StoreAMOPageFault(_) => {
+        Trap::Invisible
+      }
     }
+  }
 }
diff --git a/src/interrupt.rs b/src/interrupt.rs
index c4b9805..75761c6 100644
--- a/src/interrupt.rs
+++ b/src/interrupt.rs
@@ -1,168 +1,168 @@
 //! The interrupt module contains all the interrupt kinds and the function to handle interrupts.
 
 use crate::{
-    cpu::{Cpu, Mode},
-    csr::*,
+  cpu::{Cpu, Mode},
+  csr::*,
 };
 
 /// All the interrupt kinds.
 #[derive(Debug)]
 pub enum Interrupt {
-    UserSoftwareInterrupt,
-    SupervisorSoftwareInterrupt,
-    MachineSoftwareInterrupt,
-    UserTimerInterrupt,
-    SupervisorTimerInterrupt,
-    MachineTimerInterrupt,
-    UserExternalInterrupt,
-    SupervisorExternalInterrupt,
-    MachineExternalInterrupt,
+  UserSoftwareInterrupt,
+  SupervisorSoftwareInterrupt,
+  MachineSoftwareInterrupt,
+  UserTimerInterrupt,
+  SupervisorTimerInterrupt,
+  MachineTimerInterrupt,
+  UserExternalInterrupt,
+  SupervisorExternalInterrupt,
+  MachineExternalInterrupt,
 }
 
 impl Interrupt {
-    fn exception_code(&self) -> u64 {
-        match self {
-            Interrupt::UserSoftwareInterrupt => 0,
-            Interrupt::SupervisorSoftwareInterrupt => 1,
-            Interrupt::MachineSoftwareInterrupt => 3,
-            Interrupt::UserTimerInterrupt => 4,
-            Interrupt::SupervisorTimerInterrupt => 5,
-            Interrupt::MachineTimerInterrupt => 7,
-            Interrupt::UserExternalInterrupt => 8,
-            Interrupt::SupervisorExternalInterrupt => 9,
-            Interrupt::MachineExternalInterrupt => 11,
-        }
+  fn exception_code(&self) -> u64 {
+    match self {
+      Interrupt::UserSoftwareInterrupt => 0,
+      Interrupt::SupervisorSoftwareInterrupt => 1,
+      Interrupt::MachineSoftwareInterrupt => 3,
+      Interrupt::UserTimerInterrupt => 4,
+      Interrupt::SupervisorTimerInterrupt => 5,
+      Interrupt::MachineTimerInterrupt => 7,
+      Interrupt::UserExternalInterrupt => 8,
+      Interrupt::SupervisorExternalInterrupt => 9,
+      Interrupt::MachineExternalInterrupt => 11,
     }
-
-    /// Update CSRs and the program counter depending on an interrupt.
-    pub fn take_trap(&self, cpu: &mut Cpu) {
-        // 1.2 Privilege Levels
-        // "Traps that increase privilege level are termed vertical traps, while traps that remain
-        // at the same privilege level are termed horizontal traps."
-
-        cpu.idle = false;
-
-        let exception_pc = cpu.pc;
-        let previous_mode = cpu.mode;
-        let cause = self.exception_code();
-
-        // 3.1.8 Machine Trap Delegation Registers (medeleg and mideleg)
-        // "By default, all traps at any privilege level are handled in machine mode To increase
-        // performance, implementations can provide individual read/write bits within medeleg and
-        // mideleg to indicate that certain exceptions and interrupts should be processed directly
-        // by a lower privilege level."
-        //
-        // "mideleg holds trap delegation bits for individual interrupts, with the layout of bits
-        // matching those in the mip register (i.e., STIP interrupt delegation control is located
-        // in bit 5)."
-        // TODO: Why should a M-mode timer interrupt be taken in M-mode?
-        if previous_mode <= Mode::Supervisor
-            && ((cpu.state.read(MIDELEG) >> cause) & 1) == 1
-            && cause != Interrupt::MachineTimerInterrupt.exception_code()
-        {
-            // Handle the trap in S-mode.
-            cpu.mode = Mode::Supervisor;
-
-            // Set the program counter to the supervisor trap-handler base address (stvec)
-            // depending on the mode.
-            let vector = match cpu.state.read_bit(STVEC, 0) {
-                1 => 4 * cause, // vectored mode
-                _ => 0,         // direct mode
-            };
-            cpu.pc = ((cpu.state.read(STVEC) & !1) + vector) as u64;
-
-            // 4.1.9 Supervisor Exception Program Counter (sepc)
-            // "The low bit of sepc (sepc[0]) is always zero."
-            // "When a trap is taken into S-mode, sepc is written with the virtual address of
-            // the instruction that was interrupted or that encountered the exception.
-            // Otherwise, sepc is never written by the implementation, though it may be
-            // explicitly written by software."
-            cpu.state.write(SEPC, exception_pc & !1);
-
-            // 4.1.10 Supervisor Cause Register (scause)
-            // "When a trap is taken into S-mode, scause is written with a code indicating
-            // the event that caused the trap.  Otherwise, scause is never written by the
-            // implementation, though it may be explicitly written by software."
-            cpu.state.write(SCAUSE, 1 << 63 | cause);
-
-            // 4.1.11 Supervisor Trap Value (stval) Register
-            // "When a trap is taken into S-mode, stval is written with exception-specific
-            // information to assist software in handling the trap. Otherwise, stval is never
-            // written by the implementation, though it may be explicitly written by software."
-            // "When a hardware breakpoint is triggered, or an instruction-fetch, load, or
-            // store address-misaligned, access, or page-fault exception occurs, stval is
-            // written with the faulting virtual address. On an illegal instruction trap,
-            // stval may be written with the first XLEN or ILEN bits of the faulting
-            // instruction as described below. For other exceptions, stval is set to zero."
-            cpu.state.write(STVAL, 0);
-
-            // Set a privious interrupt-enable bit for supervisor mode (SPIE, 5) to the value
-            // of a global interrupt-enable bit for supervisor mode (SIE, 1).
-            cpu.state
-                .write_sstatus(XSTATUS_SPIE, cpu.state.read_sstatus(XSTATUS_SIE));
-            // Set a global interrupt-enable bit for supervisor mode (SIE, 1) to 0.
-            cpu.state.write_sstatus(XSTATUS_SIE, 0);
-            // 4.1.1 Supervisor Status Register (sstatus)
-            // "When a trap is taken, SPP is set to 0 if the trap originated from user mode, or
-            // 1 otherwise."
-            match previous_mode {
-                Mode::User => cpu.state.write_sstatus(XSTATUS_SPP, 0),
-                _ => cpu.state.write_sstatus(XSTATUS_SPP, 1),
-            }
-        } else {
-            // Handle the trap in M-mode.
-            cpu.mode = Mode::Machine;
-
-            // Set the program counter to the machine trap-handler base address (mtvec)
-            // depending on the mode.
-            let vector = match cpu.state.read_bit(MTVEC, 0) {
-                1 => 4 * cause, // vectored mode
-                _ => 0,         // direct mode
-            };
-            cpu.pc = ((cpu.state.read(MTVEC) & !1) + vector) as u64;
-
-            // 3.1.15 Machine Exception Program Counter (mepc)
-            // "The low bit of mepc (mepc[0]) is always zero."
-            // "When a trap is taken into M-mode, mepc is written with the virtual address of
-            // the instruction that was interrupted or that encountered the exception.
-            // Otherwise, mepc is never written by the implementation, though it may be
-            // explicitly written by software."
-            cpu.state.write(MEPC, exception_pc & !1);
-
-            // 3.1.16 Machine Cause Register (mcause)
-            // "When a trap is taken into M-mode, mcause is written with a code indicating
-            // the event that caused the trap. Otherwise, mcause is never written by the
-            // implementation, though it may be explicitly written by software."
-            cpu.state.write(MCAUSE, 1 << 63 | cause);
-
-            // 3.1.17 Machine Trap Value (mtval) Register
-            // "When a trap is taken into M-mode, mtval is either set to zero or written with
-            // exception-specific information to assist software in handling the trap.
-            // Otherwise, mtval is never written by the implementation, though it may be
-            // explicitly written by software."
-            // "When a hardware breakpoint is triggered, or an instruction-fetch, load, or
-            // store address-misaligned, access, or page-fault exception occurs, mtval is
-            // written with the faulting virtual address. On an illegal instruction trap,
-            // mtval may be written with the first XLEN or ILEN bits of the faulting
-            // instruction as described below. For other traps, mtval is set to zero."
-            cpu.state.write(MTVAL, 0);
-
-            // Set a previous interrupt-enable bit for machine mode (MPIE, 7) to the value
-            // of a global interrupt-enable bit for machine mode (MIE, 3).
-            cpu.state
-                .write_mstatus(MSTATUS_MPIE, cpu.state.read_mstatus(MSTATUS_MIE));
-            // Set a global interrupt-enable bit for machine mode (MIE, 3) to 0.
-            cpu.state.write_mstatus(MSTATUS_MIE, 0);
-            // When a trap is taken from privilege mode y into privilege mode x, xPIE is set
-            // to the value of x IE; x IE is set to 0; and xPP is set to y.
-            match previous_mode {
-                Mode::User => cpu.state.write_mstatus(MSTATUS_MPP, Mode::User as u64),
-                Mode::Supervisor => cpu
-                    .state
-                    .write_mstatus(MSTATUS_MPP, Mode::Supervisor as u64),
-                Mode::Machine => cpu.state.write_mstatus(MSTATUS_MPP, Mode::Machine as u64),
-                _ => panic!("previous privilege mode is invalid"),
-            }
-        }
+  }
+
+  /// Update CSRs and the program counter depending on an interrupt.
+  pub fn take_trap(&self, cpu: &mut Cpu) {
+    // 1.2 Privilege Levels
+    // "Traps that increase privilege level are termed vertical traps, while traps that remain
+    // at the same privilege level are termed horizontal traps."
+
+    cpu.idle = false;
+
+    let exception_pc = cpu.pc;
+    let previous_mode = cpu.mode;
+    let cause = self.exception_code();
+
+    // 3.1.8 Machine Trap Delegation Registers (medeleg and mideleg)
+    // "By default, all traps at any privilege level are handled in machine mode To increase
+    // performance, implementations can provide individual read/write bits within medeleg and
+    // mideleg to indicate that certain exceptions and interrupts should be processed directly
+    // by a lower privilege level."
+    //
+    // "mideleg holds trap delegation bits for individual interrupts, with the layout of bits
+    // matching those in the mip register (i.e., STIP interrupt delegation control is located
+    // in bit 5)."
+    // TODO: Why should a M-mode timer interrupt be taken in M-mode?
+    if previous_mode <= Mode::Supervisor
+      && ((cpu.state.read(MIDELEG) >> cause) & 1) == 1
+      && cause != Interrupt::MachineTimerInterrupt.exception_code()
+    {
+      // Handle the trap in S-mode.
+      cpu.mode = Mode::Supervisor;
+
+      // Set the program counter to the supervisor trap-handler base address (stvec)
+      // depending on the mode.
+      let vector = match cpu.state.read_bit(STVEC, 0) {
+        1 => 4 * cause, // vectored mode
+        _ => 0,         // direct mode
+      };
+      cpu.pc = ((cpu.state.read(STVEC) & !1) + vector) as u64;
+
+      // 4.1.9 Supervisor Exception Program Counter (sepc)
+      // "The low bit of sepc (sepc[0]) is always zero."
+      // "When a trap is taken into S-mode, sepc is written with the virtual address of
+      // the instruction that was interrupted or that encountered the exception.
+      // Otherwise, sepc is never written by the implementation, though it may be
+      // explicitly written by software."
+      cpu.state.write(SEPC, exception_pc & !1);
+
+      // 4.1.10 Supervisor Cause Register (scause)
+      // "When a trap is taken into S-mode, scause is written with a code indicating
+      // the event that caused the trap.  Otherwise, scause is never written by the
+      // implementation, though it may be explicitly written by software."
+      cpu.state.write(SCAUSE, 1 << 63 | cause);
+
+      // 4.1.11 Supervisor Trap Value (stval) Register
+      // "When a trap is taken into S-mode, stval is written with exception-specific
+      // information to assist software in handling the trap. Otherwise, stval is never
+      // written by the implementation, though it may be explicitly written by software."
+      // "When a hardware breakpoint is triggered, or an instruction-fetch, load, or
+      // store address-misaligned, access, or page-fault exception occurs, stval is
+      // written with the faulting virtual address. On an illegal instruction trap,
+      // stval may be written with the first XLEN or ILEN bits of the faulting
+      // instruction as described below. For other exceptions, stval is set to zero."
+      cpu.state.write(STVAL, 0);
+
+      // Set a privious interrupt-enable bit for supervisor mode (SPIE, 5) to the value
+      // of a global interrupt-enable bit for supervisor mode (SIE, 1).
+      cpu
+        .state
+        .write_sstatus(XSTATUS_SPIE, cpu.state.read_sstatus(XSTATUS_SIE));
+      // Set a global interrupt-enable bit for supervisor mode (SIE, 1) to 0.
+      cpu.state.write_sstatus(XSTATUS_SIE, 0);
+      // 4.1.1 Supervisor Status Register (sstatus)
+      // "When a trap is taken, SPP is set to 0 if the trap originated from user mode, or
+      // 1 otherwise."
+      match previous_mode {
+        Mode::User => cpu.state.write_sstatus(XSTATUS_SPP, 0),
+        _ => cpu.state.write_sstatus(XSTATUS_SPP, 1),
+      }
+    } else {
+      // Handle the trap in M-mode.
+      cpu.mode = Mode::Machine;
+
+      // Set the program counter to the machine trap-handler base address (mtvec)
+      // depending on the mode.
+      let vector = match cpu.state.read_bit(MTVEC, 0) {
+        1 => 4 * cause, // vectored mode
+        _ => 0,         // direct mode
+      };
+      cpu.pc = ((cpu.state.read(MTVEC) & !1) + vector) as u64;
+
+      // 3.1.15 Machine Exception Program Counter (mepc)
+      // "The low bit of mepc (mepc[0]) is always zero."
+      // "When a trap is taken into M-mode, mepc is written with the virtual address of
+      // the instruction that was interrupted or that encountered the exception.
+      // Otherwise, mepc is never written by the implementation, though it may be
+      // explicitly written by software."
+      cpu.state.write(MEPC, exception_pc & !1);
+
+      // 3.1.16 Machine Cause Register (mcause)
+      // "When a trap is taken into M-mode, mcause is written with a code indicating
+      // the event that caused the trap. Otherwise, mcause is never written by the
+      // implementation, though it may be explicitly written by software."
+      cpu.state.write(MCAUSE, 1 << 63 | cause);
+
+      // 3.1.17 Machine Trap Value (mtval) Register
+      // "When a trap is taken into M-mode, mtval is either set to zero or written with
+      // exception-specific information to assist software in handling the trap.
+      // Otherwise, mtval is never written by the implementation, though it may be
+      // explicitly written by software."
+      // "When a hardware breakpoint is triggered, or an instruction-fetch, load, or
+      // store address-misaligned, access, or page-fault exception occurs, mtval is
+      // written with the faulting virtual address. On an illegal instruction trap,
+      // mtval may be written with the first XLEN or ILEN bits of the faulting
+      // instruction as described below. For other traps, mtval is set to zero."
+      cpu.state.write(MTVAL, 0);
+
+      // Set a previous interrupt-enable bit for machine mode (MPIE, 7) to the value
+      // of a global interrupt-enable bit for machine mode (MIE, 3).
+      cpu
+        .state
+        .write_mstatus(MSTATUS_MPIE, cpu.state.read_mstatus(MSTATUS_MIE));
+      // Set a global interrupt-enable bit for machine mode (MIE, 3) to 0.
+      cpu.state.write_mstatus(MSTATUS_MIE, 0);
+      // When a trap is taken from privilege mode y into privilege mode x, xPIE is set
+      // to the value of x IE; x IE is set to 0; and xPP is set to y.
+      match previous_mode {
+        Mode::User => cpu.state.write_mstatus(MSTATUS_MPP, Mode::User as u64),
+        Mode::Supervisor => cpu.state.write_mstatus(MSTATUS_MPP, Mode::Supervisor as u64),
+        Mode::Machine => cpu.state.write_mstatus(MSTATUS_MPP, Mode::Machine as u64),
+        _ => panic!("previous privilege mode is invalid"),
+      }
     }
+  }
 }