summaryrefslogtreecommitdiff
path: root/src/instructions/rvi/mem.rs
blob: 3f89d7051a3fed34b53c6b64a3b9b814a56a6498 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use crate::{
    consts::{Addr, Byte, DWord, Word},
    core::Core,
    instructions::{Instruction, InstructionResult},
    mem::PageNum,
};

// TODO: Support misaligned memory access
pub fn sd(core: &mut Core, instr: Instruction) -> InstructionResult {
    let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_s());

    if !addr.is_multiple_of(std::mem::size_of::<DWord>() as Addr) {
        return InstructionResult::Exception(());
    }

    let page = (addr / 4096) as PageNum;
    let offset = (addr / 8 & ((4096 / 8 as Addr) - 1)) as u16;
    let value = core.reg_read(instr.rs2());

    match core.mem.write_dword(page, offset, value) {
        Ok(_) => {
            core.advance_pc();
            InstructionResult::Normal
        }
        Err(_) => InstructionResult::Exception(()),
    }
}

pub fn ld(core: &mut Core, instr: Instruction) -> InstructionResult {
    let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_i());

    if !addr.is_multiple_of(std::mem::size_of::<DWord>() as Addr) {
        return InstructionResult::Exception(());
    }

    let page = (addr / 4096) as PageNum;
    let offset = (addr / 8 & ((4096 / 8 as Addr) - 1)) as u16;

    match core.mem.read_dword(page, offset) {
        Ok(x) => {
            core.reg_write(instr.rd(), x);
            core.advance_pc();
            InstructionResult::Normal
        }
        Err(_) => InstructionResult::Exception(()),
    }
}

pub fn sw(core: &mut Core, instr: Instruction) -> InstructionResult {
    let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_s());

    if !addr.is_multiple_of(std::mem::size_of::<Word>() as Addr) {
        return InstructionResult::Exception(());
    }

    let page = (addr / 4096) as PageNum;
    let offset = (addr / 4 & ((4096 / 4 as Addr) - 1)) as u16;
    let value = core.reg_read(instr.rs2()) as Word;

    match core.mem.write_word(page, offset, value) {
        Ok(_) => {
            core.advance_pc();
            InstructionResult::Normal
        }
        Err(_) => InstructionResult::Exception(()),
    }
}

pub fn sb(core: &mut Core, instr: Instruction) -> InstructionResult {
    let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_s());

    let page = (addr / 4096) as PageNum;
    let offset = (addr & (4096 as Addr - 1)) as u16;
    let value = core.reg_read(instr.rs2()) as Byte;

    match core.mem.write_byte(page, offset, value) {
        Ok(_) => {
            core.advance_pc();
            InstructionResult::Normal
        }
        Err(_) => InstructionResult::Exception(()),
    }
}

pub fn lb(core: &mut Core, instr: Instruction) -> InstructionResult {
    let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_i());

    let page = (addr / 4096) as PageNum;
    let offset = (addr & (4096 as Addr - 1)) as u16;

    match core.mem.read_byte(page, offset) {
        Ok(x) => {
            let x = x as i8 as i64 as DWord;
            core.reg_write(instr.rd(), x);
            core.advance_pc();
            InstructionResult::Normal
        }
        Err(_) => InstructionResult::Exception(()),
    }
}

pub fn lbu(core: &mut Core, instr: Instruction) -> InstructionResult {
    let addr = core.reg_read(instr.rs1()).wrapping_add(instr.imm_i());

    let page = (addr / 4096) as PageNum;
    let offset = (addr & (4096 as Addr - 1)) as u16;

    match core.mem.read_byte(page, offset) {
        Ok(x) => {
            let x = x as DWord;
            core.reg_write(instr.rd(), x);
            core.advance_pc();
            InstructionResult::Normal
        }
        Err(_) => InstructionResult::Exception(()),
    }
}