support inc r, # in assembler

This commit is contained in:
eiowlta 2023-07-20 16:53:30 +03:00
parent a049f839f2
commit 36a8432411
2 changed files with 93 additions and 8 deletions

View File

@ -65,6 +65,13 @@ size = @{
".32" ".32"
} }
incdec_amount = @{
"1" |
"2" |
"4" |
"8"
}
condition = @{ condition = @{
"ifz" | "ifz" |
"ifnz" | "ifnz" |
@ -83,6 +90,7 @@ instruction = {
instruction_conditional = { instruction_conditional = {
instruction_zero ~ size? | instruction_zero ~ size? |
instruction_one ~ size? ~ operand | instruction_one ~ size? ~ operand |
instruction_incdec ~ size? ~ operand ~ ("," ~ incdec_amount)? |
instruction_two ~ size? ~ operand ~ "," ~ operand instruction_two ~ size? ~ operand ~ "," ~ operand
} }
@ -99,8 +107,6 @@ instruction_zero = @{
} }
instruction_one = @{ instruction_one = @{
"inc" |
"dec" |
"not" | "not" |
"jmp" | "jmp" |
"call" | "call" |
@ -115,6 +121,11 @@ instruction_one = @{
"flp" "flp"
} }
instruction_incdec = @{
"inc" |
"dec"
}
instruction_two = @{ instruction_two = @{
"add" | "add" |
"sub" | "sub" |

View File

@ -168,8 +168,6 @@ enum InstructionZero {
#[derive(PartialEq, Debug, Clone, Copy)] #[derive(PartialEq, Debug, Clone, Copy)]
enum InstructionOne { enum InstructionOne {
// one operand // one operand
Inc,
Dec,
Not, Not,
Jmp, Jmp,
Call, Call,
@ -184,6 +182,13 @@ enum InstructionOne {
Flp, Flp,
} }
#[derive(PartialEq, Debug, Clone, Copy)]
enum InstructionIncDec {
// one or two operands
Inc,
Dec,
}
#[derive(PartialEq, Debug, Clone, Copy)] #[derive(PartialEq, Debug, Clone, Copy)]
enum InstructionTwo { enum InstructionTwo {
// two operands // two operands
@ -254,6 +259,13 @@ enum AstNode {
instruction: InstructionOne, instruction: InstructionOne,
operand: Box<AstNode>, operand: Box<AstNode>,
}, },
OperationIncDec {
size: Size,
condition: Condition,
instruction: InstructionIncDec,
lhs: Box<AstNode>,
rhs: Box<AstNode>,
},
OperationTwo { OperationTwo {
size: Size, size: Size,
condition: Condition, condition: Condition,
@ -713,6 +725,16 @@ fn parse_size(pair: &pest::iterators::Pair<Rule>) -> Size {
} }
} }
fn parse_incdec_amount(pair: pest::iterators::Pair<Rule>) -> AstNode {
match pair.as_str() {
"1" => AstNode::Immediate8(0),
"2" => AstNode::Immediate8(1),
"4" => AstNode::Immediate8(2),
"8" => AstNode::Immediate8(3),
_ => panic!("Unsupported increment/decrement: {}", pair.as_str()),
}
}
fn parse_condition(pair: &pest::iterators::Pair<Rule>) -> Condition { fn parse_condition(pair: &pest::iterators::Pair<Rule>) -> Condition {
match pair.as_str() { match pair.as_str() {
"ifz" => Condition::Zero, "ifz" => Condition::Zero,
@ -754,6 +776,21 @@ fn parse_instruction(pair: pest::iterators::Pair<Rule>) -> AstNode {
let operand_ast = build_ast_from_expression(operand); let operand_ast = build_ast_from_expression(operand);
parse_instruction_one(instruction_conditional_pair, operand_ast, size, condition) parse_instruction_one(instruction_conditional_pair, operand_ast, size, condition)
} }
Rule::instruction_incdec => {
if inner_pair.peek().unwrap().as_rule() == Rule::size {
size = parse_size(&inner_pair.next().unwrap());
}
*CURRENT_SIZE.lock().unwrap() = size;
let lhs = inner_pair.next().unwrap();
let lhs_ast = build_ast_from_expression(lhs);
let rhs_ast = if inner_pair.peek().is_some() {
let rhs = inner_pair.next().unwrap();
parse_incdec_amount(rhs)
} else {
AstNode::Immediate8(0)
};
parse_instruction_incdec(instruction_conditional_pair, lhs_ast, rhs_ast, size, condition)
}
Rule::instruction_two => { Rule::instruction_two => {
if inner_pair.peek().unwrap().as_rule() == Rule::size { if inner_pair.peek().unwrap().as_rule() == Rule::size {
size = parse_size(&inner_pair.next().unwrap()); size = parse_size(&inner_pair.next().unwrap());
@ -878,8 +915,6 @@ fn parse_instruction_one(pair: pest::iterators::Pair<Rule>, mut operand: AstNode
size: size, size: size,
condition: condition, condition: condition,
instruction: match pair.as_str() { instruction: match pair.as_str() {
"inc" => InstructionOne::Inc,
"dec" => InstructionOne::Dec,
"not" => InstructionOne::Not, "not" => InstructionOne::Not,
"jmp" => InstructionOne::Jmp, "jmp" => InstructionOne::Jmp,
"call" => InstructionOne::Call, "call" => InstructionOne::Call,
@ -925,6 +960,21 @@ fn parse_instruction_one(pair: pest::iterators::Pair<Rule>, mut operand: AstNode
} }
} }
fn parse_instruction_incdec(pair: pest::iterators::Pair<Rule>, lhs: AstNode, rhs: AstNode, size: Size, condition: Condition) -> AstNode {
AstNode::OperationIncDec {
size: size,
condition: condition,
instruction: match pair.as_str() {
"inc" => InstructionIncDec::Inc,
"dec" => InstructionIncDec::Dec,
_ => panic!("Unsupported conditional instruction (two): {}", pair.as_str()),
},
lhs: Box::new(lhs),
rhs: Box::new(rhs),
}
}
fn parse_instruction_two(pair: pest::iterators::Pair<Rule>, mut lhs: AstNode, mut rhs: AstNode, size: Size, condition: Condition) -> AstNode { fn parse_instruction_two(pair: pest::iterators::Pair<Rule>, mut lhs: AstNode, mut rhs: AstNode, size: Size, condition: Condition) -> AstNode {
AstNode::OperationTwo { AstNode::OperationTwo {
size: size, size: size,
@ -1055,8 +1105,6 @@ fn instruction_to_byte(node: &AstNode) -> u8 {
} }
AstNode::OperationOne {size, instruction, ..} => { AstNode::OperationOne {size, instruction, ..} => {
match instruction { match instruction {
InstructionOne::Inc => 0x11 | size_to_byte(size),
InstructionOne::Dec => 0x31 | size_to_byte(size),
InstructionOne::Not => 0x33 | size_to_byte(size), InstructionOne::Not => 0x33 | size_to_byte(size),
InstructionOne::Jmp => 0x08 | size_to_byte(size), InstructionOne::Jmp => 0x08 | size_to_byte(size),
InstructionOne::Call => 0x18 | size_to_byte(size), InstructionOne::Call => 0x18 | size_to_byte(size),
@ -1071,6 +1119,12 @@ fn instruction_to_byte(node: &AstNode) -> u8 {
InstructionOne::Flp => 0x3D | size_to_byte(size), InstructionOne::Flp => 0x3D | size_to_byte(size),
} }
} }
AstNode::OperationIncDec {size, instruction, ..} => {
match instruction {
InstructionIncDec::Inc => 0x11 | size_to_byte(size),
InstructionIncDec::Dec => 0x31 | size_to_byte(size),
}
}
AstNode::OperationTwo {size, instruction, ..} => { AstNode::OperationTwo {size, instruction, ..} => {
match instruction { match instruction {
InstructionTwo::Add => 0x01 | size_to_byte(size), InstructionTwo::Add => 0x01 | size_to_byte(size),
@ -1128,6 +1182,15 @@ fn condition_source_destination_to_byte(node: &AstNode) -> u8 {
_ => panic!("Attempting to parse a non-instruction AST node as an instruction: {:#?}", node), _ => panic!("Attempting to parse a non-instruction AST node as an instruction: {:#?}", node),
} }
} }
AstNode::OperationIncDec {lhs, ..} => {
match lhs.as_ref() {
AstNode::Register(_) => 0x00,
AstNode::RegisterPointer(_) => 0x01,
AstNode::Immediate8(_) | AstNode::Immediate16(_) | AstNode::Immediate32(_) | AstNode::LabelOperand {..} => 0x02,
AstNode::ImmediatePointer(_) | AstNode::LabelOperandPointer {..} => 0x03,
_ => panic!("Attempting to parse a non-instruction AST node as an instruction: {:#?}", node),
}
}
AstNode::OperationTwo {rhs, ..} => { AstNode::OperationTwo {rhs, ..} => {
match rhs.as_ref() { match rhs.as_ref() {
AstNode::Register(_) => 0x00, AstNode::Register(_) => 0x00,
@ -1142,6 +1205,12 @@ fn condition_source_destination_to_byte(node: &AstNode) -> u8 {
let destination: u8 = match node { let destination: u8 = match node {
AstNode::OperationZero {..} => 0x00, AstNode::OperationZero {..} => 0x00,
AstNode::OperationOne {..} => 0x00, AstNode::OperationOne {..} => 0x00,
AstNode::OperationIncDec { rhs, ..} => {
match rhs.as_ref() {
AstNode::Immediate8(n) => *n << 2,
_ => panic!(""),
}
}
AstNode::OperationTwo {lhs, ..} => { AstNode::OperationTwo {lhs, ..} => {
match lhs.as_ref() { match lhs.as_ref() {
AstNode::Register(_) => 0x00, AstNode::Register(_) => 0x00,
@ -1156,6 +1225,7 @@ fn condition_source_destination_to_byte(node: &AstNode) -> u8 {
let condition: u8 = match node { let condition: u8 = match node {
AstNode::OperationZero {condition, ..} => condition_to_bits(condition), AstNode::OperationZero {condition, ..} => condition_to_bits(condition),
AstNode::OperationOne {condition, ..} => condition_to_bits(condition), AstNode::OperationOne {condition, ..} => condition_to_bits(condition),
AstNode::OperationIncDec {condition, ..} => condition_to_bits(condition),
AstNode::OperationTwo {condition, ..} => condition_to_bits(condition), AstNode::OperationTwo {condition, ..} => condition_to_bits(condition),
_ => panic!("Attempting to parse a non-instruction AST node as an instruction: {:#?}", node), _ => panic!("Attempting to parse a non-instruction AST node as an instruction: {:#?}", node),
}; };
@ -1219,6 +1289,9 @@ fn node_to_immediate_values(node: &AstNode, instruction: &AssembledInstruction)
AstNode::OperationOne {operand, ..} => AstNode::OperationOne {operand, ..} =>
operand_to_immediate_value(instruction, operand.as_ref()), operand_to_immediate_value(instruction, operand.as_ref()),
AstNode::OperationIncDec {lhs, ..} =>
operand_to_immediate_value(instruction, lhs.as_ref()),
AstNode::OperationTwo {rhs, ..} => AstNode::OperationTwo {rhs, ..} =>
operand_to_immediate_value(instruction, rhs.as_ref()), operand_to_immediate_value(instruction, rhs.as_ref()),
@ -1229,6 +1302,7 @@ fn node_to_immediate_values(node: &AstNode, instruction: &AssembledInstruction)
match node { match node {
AstNode::OperationZero {..} => {} AstNode::OperationZero {..} => {}
AstNode::OperationOne {..} => {} AstNode::OperationOne {..} => {}
AstNode::OperationIncDec {..} => {}
AstNode::OperationTwo {lhs, ..} => AstNode::OperationTwo {lhs, ..} =>
operand_to_immediate_value(instruction, lhs.as_ref()), operand_to_immediate_value(instruction, lhs.as_ref()),