From d71a42cab362889424a5a5951a2f6e22d2ec80e8 Mon Sep 17 00:00:00 2001 From: Cassie Jones Date: Sat, 11 Jan 2020 18:29:53 -0500 Subject: [PATCH] Add support for binary, hex, and octal literals --- toolchain/src/inst/decode.rs | 4 +- toolchain/src/inst/parse.rs | 95 ++++++++++++++++++++---------------- toolchain/src/inst/test.rs | 18 +++++++ 3 files changed, 73 insertions(+), 44 deletions(-) diff --git a/toolchain/src/inst/decode.rs b/toolchain/src/inst/decode.rs index 6875cb9..46bbc55 100644 --- a/toolchain/src/inst/decode.rs +++ b/toolchain/src/inst/decode.rs @@ -103,7 +103,9 @@ impl Decode for Inst { 0b0001 => Inst::AluI(AluI::Ior(imm)), 0b0010 => Inst::AluI(AluI::Xor(imm)), 0b0011 => match imm >> 6 { - 0b00 | 0b01 | 0b11 => Inst::AluI(AluI::Add(AddImm::new(imm as i8).unwrap())), + 0b00 | 0b01 | 0b11 => { + Inst::AluI(AluI::Add(AddImm::new(imm as i8).unwrap())) + } 0b10 => { let imm3 = U3::new(imm & 7).unwrap(); Inst::AluI(AluI::Compact(op_compact(imm), imm3)) diff --git a/toolchain/src/inst/parse.rs b/toolchain/src/inst/parse.rs index 858a6bc..94574d7 100644 --- a/toolchain/src/inst/parse.rs +++ b/toolchain/src/inst/parse.rs @@ -2,44 +2,33 @@ use super::{AddImm, AluI, Data, Inst, Op1, OpI3, OpR, Reg, Special, Target, U3}; use nom::{ branch::alt, bytes::complete::tag_no_case, - character::complete::{char, digit1, one_of, space1}, + character::complete::{char, digit1, hex_digit1, oct_digit1, one_of, space1}, combinator::{complete, map, map_opt, map_res, opt, recognize, value}, + multi::many1, sequence::{pair, preceded}, IResult, }; use std::convert::TryFrom; pub fn parse_inst(s: &str) -> Option { - complete(inst())(s).ok().map(|x| x.1) + complete(inst)(s).ok().map(|x| x.1) } -pub fn box_alt< - 'a, - I: Clone + 'a, - O: 'a, - E: nom::error::ParseError + 'a, - List: nom::branch::Alt + 'a, ->( - l: List, -) -> Box IResult + 'a> { - Box::new(alt(l)) -} - -fn inst<'s>() -> impl Fn(&'s str) -> IResult<&'s str, Inst> { +pub fn inst(s: &str) -> IResult<&str, Inst> { alt(( - box_alt(( - fixed("trap", Inst::Trap), + alt(( + fixed("TRAP", Inst::Trap), fixed("JABS", Inst::Jump(Target::Abs)), fixed("CABS", Inst::Call(Target::Abs)), fixed("JOFF", Inst::Jump(Target::Off)), fixed("COFF", Inst::Call(Target::Off)), )), - box_alt(( + alt(( with_reg("SWAP", |r| Inst::Swap(r)), with_reg("GETR", |r| Inst::GetR(r)), with_reg("SETR", |r| Inst::SetR(r)), )), - box_alt(( + alt(( fixed("GET1", Inst::Get(Special::Data(Data::D1))), fixed("GET2", Inst::Get(Special::Data(Data::D2))), fixed("GETC", Inst::Get(Special::Code)), @@ -55,7 +44,7 @@ fn inst<'s>() -> impl Fn(&'s str) -> IResult<&'s str, Inst> { fixed("COMP", Inst::Alu1(Op1::Comp)), fixed("NEGT", Inst::Alu1(Op1::Negt)), )), - box_alt(( + alt(( with_reg("ISLT", |r| Inst::IsLt(r)), with_reg("ADDR", |r| Inst::AluR(OpR::Add, r)), with_reg("SUBR", |r| Inst::AluR(OpR::Sub, r)), @@ -66,19 +55,19 @@ fn inst<'s>() -> impl Fn(&'s str) -> IResult<&'s str, Inst> { with_reg("LSRR", |r| Inst::AluR(OpR::Lsr, r)), with_reg("ASRR", |r| Inst::AluR(OpR::Asr, r)), )), - box_alt(( + alt(( with_reg_bang("LD1U", |r, b| Inst::LdD(Data::D1, r, b)), with_reg_bang("ST1U", |r, b| Inst::StD(Data::D1, r, b)), with_reg_bang("LD2U", |r, b| Inst::LdD(Data::D2, r, b)), with_reg_bang("ST2U", |r, b| Inst::StD(Data::D2, r, b)), )), - box_alt(( + alt(( with_imm8("ANDI", |imm| Inst::AluI(AluI::And(imm))), with_imm8("IORI", |imm| Inst::AluI(AluI::Ior(imm))), with_imm8("XORI", |imm| Inst::AluI(AluI::Xor(imm))), )), with_add_imm("ADDI", |imm| Inst::AluI(AluI::Add(imm))), - box_alt(( + alt(( with_imm3("ROLI", |imm| Inst::AluI(AluI::Compact(OpI3::Rol, imm))), with_imm3("LSLI", |imm| Inst::AluI(AluI::Compact(OpI3::Lsl, imm))), with_imm3("LSRI", |imm| Inst::AluI(AluI::Compact(OpI3::Lsr, imm))), @@ -88,50 +77,70 @@ fn inst<'s>() -> impl Fn(&'s str) -> IResult<&'s str, Inst> { with_imm3("TOGI", |imm| Inst::AluI(AluI::Compact(OpI3::Tog, imm))), with_imm3("EXTI", |imm| Inst::AluI(AluI::Compact(OpI3::Ext, imm))), )), - box_alt(( + alt(( with_off("BEZI", |off| Inst::BEzI(off)), with_off("JOFI", |off| Inst::Jump(Target::OffImm(off))), with_off("COFI", |off| Inst::Call(Target::OffImm(off))), )), - )) + ))(s) } fn fixed<'s>(tag: &'s str, inst: Inst) -> impl Fn(&'s str) -> IResult<&'s str, Inst> { value(inst, tag_no_case(tag)) } -fn reg<'s>() -> impl Fn(&'s str) -> IResult<&'s str, Reg> { +fn reg(s: &str) -> IResult<&str, Reg> { let raw = preceded(tag_no_case("r"), digit1); let num = map_res(raw, |x: &str| x.parse()); - map_opt(num, Reg::new) + map_opt(num, Reg::new)(s) } -fn imm<'s>() -> impl Fn(&'s str) -> IResult<&'s str, i16> { +fn imm_dec(s: &str) -> IResult<&str, i16> { let text = recognize(pair(opt(one_of("+-")), digit1)); - map_res(preceded(char('#'), text), |x: &str| x.parse()) + let prefix = alt((tag_no_case("#d"), tag_no_case("#"))); + map_res(preceded(prefix, text), |x: &str| x.parse())(s) +} + +fn imm_hex(s: &str) -> IResult<&str, i16> { + let text = recognize(hex_digit1); + map_res(preceded(tag_no_case("#x"), text), |x| i16::from_str_radix(x, 16))(s) +} + +fn imm_oct(s: &str) -> IResult<&str, i16> { + let text = recognize(oct_digit1); + map_res(preceded(tag_no_case("#o"), text), |x| i16::from_str_radix(x, 8))(s) +} + +fn imm_bin(s: &str) -> IResult<&str, i16> { + let text = recognize(many1(one_of("01"))); + map_res(preceded(tag_no_case("#b"), text), |x| i16::from_str_radix(x, 2))(s) +} + +fn imm(s: &str) -> IResult<&str, i16> { + alt((imm_hex, imm_oct, imm_bin, imm_dec))(s) } -fn imm8<'s>() -> impl Fn(&'s str) -> IResult<&'s str, u8> { - map_res(imm(), TryFrom::try_from) +fn imm8(s: &str) -> IResult<&str, u8> { + map_res(imm, TryFrom::try_from)(s) } -fn add_imm<'s>() -> impl Fn(&'s str) -> IResult<&'s str, AddImm> { - map_opt(map_res(imm(), TryFrom::try_from), AddImm::new) +fn add_imm(s: &str) -> IResult<&str, AddImm> { + map_opt(map_res(imm, TryFrom::try_from), AddImm::new)(s) } -fn imm3<'s>() -> impl Fn(&'s str) -> IResult<&'s str, U3> { - map_opt(map_res(imm(), TryFrom::try_from), U3::new) +fn imm3(s: &str) -> IResult<&str, U3> { + map_opt(map_res(imm, TryFrom::try_from), U3::new)(s) } -fn imm_off<'s>() -> impl Fn(&'s str) -> IResult<&'s str, i8> { - map_res(imm(), TryFrom::try_from) +fn imm_off(s: &str) -> IResult<&str, i8> { + map_res(imm, TryFrom::try_from)(s) } fn with_reg<'s>( tag: &'s str, make_inst: impl Fn(Reg) -> Inst, ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> { - let reg = preceded(pair(tag_no_case(tag), space1), reg()); + let reg = preceded(pair(tag_no_case(tag), space1), reg); map(reg, make_inst) } @@ -140,7 +149,7 @@ fn with_reg_bang<'s>( make_inst: impl Fn(Reg, bool) -> Inst, ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> { let reg_bang = pair( - preceded(pair(tag_no_case(tag), space1), reg()), + preceded(pair(tag_no_case(tag), space1), reg), map(opt(char('!')), |x| x.is_some()), ); map(reg_bang, move |(r, b)| make_inst(r, b)) @@ -150,7 +159,7 @@ fn with_imm8<'s>( tag: &'s str, make_inst: impl Fn(u8) -> Inst, ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> { - let imm = preceded(pair(tag_no_case(tag), space1), imm8()); + let imm = preceded(pair(tag_no_case(tag), space1), imm8); map(imm, make_inst) } @@ -158,7 +167,7 @@ fn with_add_imm<'s>( tag: &'s str, make_inst: impl Fn(AddImm) -> Inst, ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> { - let imm = preceded(pair(tag_no_case(tag), space1), add_imm()); + let imm = preceded(pair(tag_no_case(tag), space1), add_imm); map(imm, make_inst) } @@ -166,7 +175,7 @@ fn with_imm3<'s>( tag: &'s str, make_inst: impl Fn(U3) -> Inst, ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> { - let imm = preceded(pair(tag_no_case(tag), space1), imm3()); + let imm = preceded(pair(tag_no_case(tag), space1), imm3); map(imm, make_inst) } @@ -174,6 +183,6 @@ fn with_off<'s>( tag: &'s str, make_inst: impl Fn(i8) -> Inst, ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> { - let imm = preceded(pair(tag_no_case(tag), space1), imm_off()); + let imm = preceded(pair(tag_no_case(tag), space1), imm_off); map(imm, make_inst) } diff --git a/toolchain/src/inst/test.rs b/toolchain/src/inst/test.rs index 71fb2ab..20fb028 100644 --- a/toolchain/src/inst/test.rs +++ b/toolchain/src/inst/test.rs @@ -190,6 +190,21 @@ fn alu_i() { "andi #-23" => !, "andi #256" => !, + "andi #d00" => "1111_0000 0000_0000", + "andi #D0000" => "1111_0000 0000_0000", + "andi #d10" => "1111_0000 0000_1010", + "andi #D255" => "1111_0000 1111_1111", + "andi #d-1" => !, + "andi #d-23" => !, + "andi #d256" => !, + + "andi #x00" => "1111_0000 0000_0000", + "andi #XFF" => "1111_0000 1111_1111", + "andi #xAA" => "1111_0000 1010_1010", + "andi #o177" => "1111_0000 0111_1111", + "andi #O177" => "1111_0000 0111_1111", + "andi #b11010000" => "1111_0000 1101_0000", + "iori #00" => "1111_0001 0000_0000", "iori #32" => "1111_0001 0010_0000", "iori #01" => "1111_0001 0000_0001", @@ -210,6 +225,9 @@ fn alu_i() { "addi #-64" => "1111_0011 1100_0000", "addi #-65" => !, "addi #-100" => !, + + "addi #x7F" => "1111_0011 0111_1111", + "addi #xFF" => !, } } -- 2.47.0