]>
Witch of Git - jade-mouse/blob - toolchain/src/cpu.rs
1 use crate::inst
::{Addr
, Cond
, Half
, Inst
, LdSt
, Op1
, Op2
, OpC
, Reg
, Size
};
2 use std
::ops
::{Index
, IndexMut
};
19 pub fn new() -> Self {
23 reg
: RegFile
{ values
: [0; 4] },
24 memory
: vec
![0; 1 << 16],
28 pub fn reg(&self, reg
: Reg
) -> u16 {
32 pub fn mem(&self) -> &[u8] {
36 pub fn mem_mut(&mut self) -> &mut [u8] {
40 pub fn run_inst(&mut self, inst
: &Inst
) {
42 Inst
::Halt
| Inst
::Nope
=> (),
43 Inst
::Alu2(rd
, op
, r2
) => {
44 self.reg
[rd
] = match op
{
45 Op2
::Add
=> self.reg
[rd
].wrapping_add(self.reg
[r2
]),
46 Op2
::Sub
=> self.reg
[rd
].wrapping_sub(self.reg
[r2
]),
47 Op2
::AddPc
=> self.pc
.wrapping_add(self.reg
[r2
]),
48 Op2
::And
=> self.reg
[rd
] & self.reg
[r2
],
49 Op2
::Or
=> self.reg
[rd
] | self.reg
[r2
],
50 Op2
::Xor
=> self.reg
[rd
] ^
self.reg
[r2
],
53 Inst
::Jalr(r
) => std
::mem
::swap(&mut self.pc
, &mut self.reg
[r
]),
54 Inst
::Move(rd
, r2
) => self.reg
[rd
] = self.reg
[r2
],
55 Inst
::Alu1(rd
, op
) => {
56 self.reg
[rd
] = match op
{
57 Op1
::Inc
=> self.reg
[rd
].wrapping_add(1),
58 Op1
::Dec
=> self.reg
[rd
].wrapping_sub(1),
59 Op1
::Neg
=> 0u16.wrapping_sub(self.reg
[rd
]), // negate :)
60 Op1
::Compl
=> !self.reg
[rd
],
63 Inst
::Mem(LdSt
::Ld
, r
, addr
) => {
64 if let Addr
::Extended
{
71 self.reg
[base
] = self.reg
[base
].wrapping_sub(size
.bytes());
73 let (addr0
, size
) = self.eval_addr(addr
);
74 self.reg
[r
] = self.load(addr0
, size
);
76 Inst
::Mem(LdSt
::St
, r
, addr
) => {
77 let (addr0
, size
) = self.eval_addr(addr
);
78 self.store(addr0
, size
, self.reg
[r
]);
79 if let Addr
::Extended
{
86 self.reg
[base
] = self.reg
[base
].wrapping_add(size
.bytes());
89 Inst
::Branch(cond
, offset
) => {
90 if self.eval_cond(cond
) {
91 self.pc
= self.pc
.offset(offset
);
94 Inst
::JumpI(offset
) => self.pc
= self.pc
.offset(offset
),
95 Inst
::AddI(rd
, i
) => self.reg
[rd
] = self.reg
[rd
].offset(i
),
96 Inst
::AluCompact(rd
, op
, i
) => {
97 self.reg
[rd
] = match op
{
98 OpC
::Lsl
=> self.reg
[rd
] << i
.get(),
99 OpC
::Lsr
=> self.reg
[rd
] >> i
.get(),
100 OpC
::Asr
=> (self.reg
[rd
] as i16 >> i
.get()) as u16,
101 OpC
::Rol
=> self.reg
[rd
].rotate_left(i
.get() as u32),
102 OpC
::Clr
=> self.reg
[rd
] & !(1 << i
.get()),
103 OpC
::Set
=> self.reg
[rd
] | (1 << i
.get()),
104 OpC
::Tog
=> self.reg
[rd
] ^
(1 << i
.get()),
105 OpC
::Ext
=> self.reg
[rd
] & (1 << i
.get()),
108 Inst
::LdImm(Half
::Low
, rd
, i
) => self.reg
[rd
] = self.reg
[rd
] & 0xFF00 | i
as u16,
109 Inst
::LdImm(Half
::High
, rd
, i
) => {
110 self.reg
[rd
] = self.reg
[rd
] & 0x00FF | (i
as u16) << 8
115 fn eval_addr(&self, addr
: Addr
) -> (u16, Size
) {
117 Addr
::Fixed(i
) => (i
.get() * 2, Size
::Word
),
118 Addr
::Reg(r
) => (self.reg
[r
], Size
::Word
),
120 base
, size
, offset
, ..
121 } => (self.reg
[base
].offset(offset
), size
),
125 fn load(&self, addr
: u16, size
: Size
) -> u16 {
127 Size
::Byte
=> self.memory
[addr
as usize] as u16,
128 Size
::Word
=> u16::from_le_bytes([
129 self.memory
[addr
as usize],
130 self.memory
[addr
.wrapping_add(1) as usize],
135 fn store(&mut self, addr
: u16, size
: Size
, value
: u16) {
137 Size
::Byte
=> self.memory
[addr
as usize] = value
as u8,
139 let [b0
, b1
] = value
.to_le_bytes();
140 self.memory
[addr
as usize] = b0
;
141 self.memory
[addr
.wrapping_add(1) as usize] = b1
;
146 fn eval_cond(&self, cond
: Cond
) -> bool
{
148 Cond
::Eql(a
, b
) => self.reg
[a
] == self.reg
[b
],
149 Cond
::Neq(a
, b
) => self.reg
[a
] != self.reg
[b
],
150 Cond
::Test(a
, b
) => self.reg
[a
] & self.reg
[b
] != 0,
151 Cond
::TestNot(a
, b
) => self.reg
[a
] & self.reg
[b
] == 0,
152 Cond
::Lt(a
, b
) => (self.reg
[a
] as i16) < self.reg
[b
] as i16,
153 Cond
::Ult(a
, b
) => self.reg
[a
] < self.reg
[b
],
158 impl Index
<Reg
> for RegFile
{
160 fn index(&self, index
: Reg
) -> &Self::Output
{
162 Reg
::R0
=> &self.values
[0],
163 Reg
::R1
=> &self.values
[1],
164 Reg
::R2
=> &self.values
[2],
165 Reg
::R3
=> &self.values
[3],
170 impl IndexMut
<Reg
> for RegFile
{
171 fn index_mut(&mut self, index
: Reg
) -> &mut Self::Output
{
173 Reg
::R0
=> &mut self.values
[0],
174 Reg
::R1
=> &mut self.values
[1],
175 Reg
::R2
=> &mut self.values
[2],
176 Reg
::R3
=> &mut self.values
[3],
181 impl std
::fmt
::Debug
for RegFile
{
182 fn fmt(&self, fmt
: &mut std
::fmt
::Formatter
) -> std
::fmt
::Result
{
183 fmt
.debug_struct("RegFile")
184 .field
("r0", &self[Reg
::R0
])
185 .field
("r1", &self[Reg
::R1
])
186 .field
("r2", &self[Reg
::R2
])
187 .field
("r3", &self[Reg
::R3
])
192 impl std
::fmt
::Debug
for Cpu
{
193 fn fmt(&self, fmt
: &mut std
::fmt
::Formatter
) -> std
::fmt
::Result
{
194 fmt
.debug_struct("Cpu")
195 .field
("init", &self.in
it
)
196 .field
("pc", &self.pc
)
197 .field
("reg", &self.reg
)
198 .field
("mem", &format_args
!("[...]"))
204 fn offset(&self, x
: impl Into
<i32>) -> Self;
207 impl OffsetExt
for u16 {
208 fn offset(&self, x
: impl Into
<i32>) -> Self {
209 self.wrapping_add(x
.into
() as u16)