commit
6e2691f50b
|
@ -65,6 +65,13 @@ size = @{
|
|||
".32"
|
||||
}
|
||||
|
||||
incdec_amount = @{
|
||||
"1" |
|
||||
"2" |
|
||||
"4" |
|
||||
"8"
|
||||
}
|
||||
|
||||
condition = @{
|
||||
"ifz" |
|
||||
"ifnz" |
|
||||
|
@ -83,6 +90,7 @@ instruction = {
|
|||
instruction_conditional = {
|
||||
instruction_zero ~ size? |
|
||||
instruction_one ~ size? ~ operand |
|
||||
instruction_incdec ~ size? ~ operand ~ ("," ~ incdec_amount)? |
|
||||
instruction_two ~ size? ~ operand ~ "," ~ operand
|
||||
}
|
||||
|
||||
|
@ -99,8 +107,6 @@ instruction_zero = @{
|
|||
}
|
||||
|
||||
instruction_one = @{
|
||||
"inc" |
|
||||
"dec" |
|
||||
"not" |
|
||||
"jmp" |
|
||||
"call" |
|
||||
|
@ -115,6 +121,11 @@ instruction_one = @{
|
|||
"flp"
|
||||
}
|
||||
|
||||
instruction_incdec = @{
|
||||
"inc" |
|
||||
"dec"
|
||||
}
|
||||
|
||||
instruction_two = @{
|
||||
"add" |
|
||||
"sub" |
|
||||
|
|
86
src/main.rs
86
src/main.rs
|
@ -168,8 +168,6 @@ enum InstructionZero {
|
|||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
enum InstructionOne {
|
||||
// one operand
|
||||
Inc,
|
||||
Dec,
|
||||
Not,
|
||||
Jmp,
|
||||
Call,
|
||||
|
@ -184,6 +182,13 @@ enum InstructionOne {
|
|||
Flp,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
enum InstructionIncDec {
|
||||
// one or two operands
|
||||
Inc,
|
||||
Dec,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
enum InstructionTwo {
|
||||
// two operands
|
||||
|
@ -254,6 +259,13 @@ enum AstNode {
|
|||
instruction: InstructionOne,
|
||||
operand: Box<AstNode>,
|
||||
},
|
||||
OperationIncDec {
|
||||
size: Size,
|
||||
condition: Condition,
|
||||
instruction: InstructionIncDec,
|
||||
lhs: Box<AstNode>,
|
||||
rhs: Box<AstNode>,
|
||||
},
|
||||
OperationTwo {
|
||||
size: Size,
|
||||
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 {
|
||||
match pair.as_str() {
|
||||
"ifz" => Condition::Zero,
|
||||
|
@ -754,6 +776,21 @@ fn parse_instruction(pair: pest::iterators::Pair<Rule>) -> AstNode {
|
|||
let operand_ast = build_ast_from_expression(operand);
|
||||
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 => {
|
||||
if inner_pair.peek().unwrap().as_rule() == Rule::size {
|
||||
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,
|
||||
condition: condition,
|
||||
instruction: match pair.as_str() {
|
||||
"inc" => InstructionOne::Inc,
|
||||
"dec" => InstructionOne::Dec,
|
||||
"not" => InstructionOne::Not,
|
||||
"jmp" => InstructionOne::Jmp,
|
||||
"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 {
|
||||
AstNode::OperationTwo {
|
||||
size: size,
|
||||
|
@ -1055,8 +1105,6 @@ fn instruction_to_byte(node: &AstNode) -> u8 {
|
|||
}
|
||||
AstNode::OperationOne {size, 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::Jmp => 0x08 | 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),
|
||||
}
|
||||
}
|
||||
AstNode::OperationIncDec {size, instruction, ..} => {
|
||||
match instruction {
|
||||
InstructionIncDec::Inc => 0x11 | size_to_byte(size),
|
||||
InstructionIncDec::Dec => 0x31 | size_to_byte(size),
|
||||
}
|
||||
}
|
||||
AstNode::OperationTwo {size, instruction, ..} => {
|
||||
match instruction {
|
||||
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),
|
||||
}
|
||||
}
|
||||
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, ..} => {
|
||||
match rhs.as_ref() {
|
||||
AstNode::Register(_) => 0x00,
|
||||
|
@ -1142,6 +1205,12 @@ fn condition_source_destination_to_byte(node: &AstNode) -> u8 {
|
|||
let destination: u8 = match node {
|
||||
AstNode::OperationZero {..} => 0x00,
|
||||
AstNode::OperationOne {..} => 0x00,
|
||||
AstNode::OperationIncDec { rhs, ..} => {
|
||||
match rhs.as_ref() {
|
||||
AstNode::Immediate8(n) => *n << 2,
|
||||
_ => panic!(""),
|
||||
}
|
||||
}
|
||||
AstNode::OperationTwo {lhs, ..} => {
|
||||
match lhs.as_ref() {
|
||||
AstNode::Register(_) => 0x00,
|
||||
|
@ -1156,6 +1225,7 @@ fn condition_source_destination_to_byte(node: &AstNode) -> u8 {
|
|||
let condition: u8 = match node {
|
||||
AstNode::OperationZero {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),
|
||||
_ => 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, ..} =>
|
||||
operand_to_immediate_value(instruction, operand.as_ref()),
|
||||
|
||||
AstNode::OperationIncDec {lhs, ..} =>
|
||||
operand_to_immediate_value(instruction, lhs.as_ref()),
|
||||
|
||||
AstNode::OperationTwo {rhs, ..} =>
|
||||
operand_to_immediate_value(instruction, rhs.as_ref()),
|
||||
|
||||
|
@ -1229,6 +1302,7 @@ fn node_to_immediate_values(node: &AstNode, instruction: &AssembledInstruction)
|
|||
match node {
|
||||
AstNode::OperationZero {..} => {}
|
||||
AstNode::OperationOne {..} => {}
|
||||
AstNode::OperationIncDec {..} => {}
|
||||
|
||||
AstNode::OperationTwo {lhs, ..} =>
|
||||
operand_to_immediate_value(instruction, lhs.as_ref()),
|
||||
|
|
Loading…
Reference in New Issue
Block a user