]>
Witch of Git - jade-mouse/blob - toolchain/src/inst/decode.rs
1 use crate::inst
::{Addr
, Cond
, Half
, Inst
, LdSt
, Op1
, Op2
, OpC
, Reg
, Size
, I5
, I7
, U4
, U7
};
2 use bitmatch
::bitmatch
;
10 fn decode(code
: &mut impl Read
) -> io
::Result
<Inst
>;
13 impl Decode
for Inst
{
15 fn decode(code
: &mut impl Read
) -> io
::Result
<Inst
> {
17 let x
= read_1_byte(code
)?
;
23 "000?_????" => return Err(reserved()),
24 "0ooo_aabb" => Alu2(reg(a
), op2(o
), reg(b
)),
25 "1000_aabb" if a
== b
=> Jalr(reg(a
)),
26 "1000_aabb" => Move(reg(a
), reg(b
)),
27 "1001_aaoo" => Alu1(reg(a
), op1(o
)),
28 "101f_aabb" => Mem(ldst(f
), reg(a
), Addr
::Reg(reg(b
))),
30 let y
= read_1_byte(code
).map_err(reject_eof
)?
;
32 match bitpack
!("xxxx_xxxx yyyy_yyyy") {
33 "00_0000 iiii_iiii" => JumpI(i
as i8),
34 "01_aabb fiii_iiii" if a
== b
=> Mem(ldst(f
), reg(a
), fixed(i
)),
35 "0o_aabb oiii_iiii" => Branch(cond(o
, a
, b
), i7(i
)),
36 "10_aa00 iiii_iiii" => AddI(reg(a
), i
as i8),
37 "10_aa01 oooo_iiii" => AluCompact(reg(a
), op_c(o
), U4(i
as u8)),
38 "10_aa10 iiii_iiii" => LdImm(Half
::Low
, reg(a
), i
as u8),
39 "10_aa11 iiii_iiii" => LdImm(Half
::High
, reg(a
), i
as u8),
40 "11_aabb wpsi_iiii" => Mem(
57 fn fixed(x
: u16) -> Addr
{
58 Addr
::Fixed(U7(x
as u8))
62 I7(((x
as i8) << 1) >> 1)
66 I5(((x
as i8) << 3) >> 3)
69 fn read_1_byte(r
: &mut impl Read
) -> io
::Result
<u8> {
71 r
.read_exact(&mut result
[..])?
;
75 fn reject_eof(err
: io
::Error
) -> io
::Error
{
76 if err
.kind() == io
::ErrorKind
::UnexpectedEof
{
78 io
::ErrorKind
::InvalidInput
,
79 "instruction missing second byte",
86 fn reg(r
: impl TryInto
<u8, Error
= impl Debug
>) -> Reg
{
87 match r
.try_into().unwrap
() & 3 {
95 fn cond(o
: u16, a
: u16, b
: u16) -> Cond
{
96 let (a
, b
) = (reg(a
), reg(b
));
97 debug_assert_ne
!(a
, b
);
99 (0, true) => Cond
::Eql(a
, b
),
100 (0, false) => Cond
::Neq(a
, b
),
101 (1, true) => Cond
::Test(a
, b
),
102 (1, false) => Cond
::TestNot(a
, b
),
103 (2, _
) => Cond
::Lt(a
, b
),
104 (3, _
) => Cond
::Ult(a
, b
),
105 _
=> unreachable
!("invalid op"),
109 fn ldst(l
: impl TryInto
<u8, Error
= impl Debug
>) -> LdSt
{
110 match l
.try_into().unwrap
() & 1 {
116 fn op1(o
: u8) -> Op1
{
122 _
=> unreachable
!("invalid Op1 value"),
126 fn op2(o
: u8) -> Op2
{
134 _
=> unreachable
!("invalid Op2 value"),
138 fn op_c(c
: u16) -> OpC
{
151 fn size(u
: u16) -> Size
{
158 fn reserved() -> io
::Error
{
159 io
::Error
::new(io
::ErrorKind
::InvalidInput
, "reserved instruction")