From 4647b9fe637571ecfbe8b5a8a96f2c22ae9add3b Mon Sep 17 00:00:00 2001 From: eiowlta Date: Fri, 21 Jul 2023 18:34:51 +0300 Subject: [PATCH] add support for optional optimization, shorter bit operations and register pointer offsets --- src/fox32.pest | 13 +- src/main.rs | 383 +++++++++++++++++++++++++++++++++++++------------ 2 files changed, 300 insertions(+), 96 deletions(-) diff --git a/src/fox32.pest b/src/fox32.pest index fa85d6d..19e593f 100644 --- a/src/fox32.pest +++ b/src/fox32.pest @@ -2,7 +2,7 @@ WHITESPACE = _{ " " | "\t" | "\n" | "\r" | "\x0B" | "\x0C" | "\xA0" | SPACE_SEPA COMMENT = _{ ";" ~ (!"\n" ~ ANY)* } assembly = { - SOI ~ (origin | include_bin_optional | include_bin | data | constant | label | instruction)* ~ EOI + SOI ~ (origin | include_bin_optional | include_bin | data | constant | label | instruction | opt)* ~ EOI } origin = { @@ -12,6 +12,13 @@ origin = { origin_padding = { "org.pad" ~ operand_value } origin_no_padding = { "org" ~ operand_value } +opton = { "opton" } +optoff = { "optoff" } +opt = { + opton | + optoff +} + include_bin = { "#include_bin" ~ immediate_str } include_bin_optional = { "#include_bin_optional" ~ immediate_str } @@ -48,7 +55,9 @@ operand = { operand_value } operand_value_ptr = { - operand_value + register ~ "+" ~ operand_value | + operand_value + } operand_value = { register | diff --git a/src/main.rs b/src/main.rs index 561ebe2..8e85925 100644 --- a/src/main.rs +++ b/src/main.rs @@ -246,33 +246,42 @@ enum LabelKind { Global, } +#[derive(PartialEq, Debug, Clone)] +struct OperationZero { + size: Size, + condition: Condition, + instruction: InstructionZero, +} +#[derive(PartialEq, Debug, Clone)] +struct OperationOne { + size: Size, + condition: Condition, + instruction: InstructionOne, + operand: Box, +} +#[derive(PartialEq, Debug, Clone)] +struct OperationIncDec { + size: Size, + condition: Condition, + instruction: InstructionIncDec, + lhs: Box, + rhs: Box, +} +#[derive(PartialEq, Debug, Clone)] +struct OperationTwo { + size: Size, + condition: Condition, + instruction: InstructionTwo, + lhs: Box, + rhs: Box, +} + #[derive(PartialEq, Debug, Clone)] enum AstNode { - OperationZero { - size: Size, - condition: Condition, - instruction: InstructionZero, - }, - OperationOne { - size: Size, - condition: Condition, - instruction: InstructionOne, - operand: Box, - }, - OperationIncDec { - size: Size, - condition: Condition, - instruction: InstructionIncDec, - lhs: Box, - rhs: Box, - }, - OperationTwo { - size: Size, - condition: Condition, - instruction: InstructionTwo, - lhs: Box, - rhs: Box, - }, + OperationZero(OperationZero) , + OperationOne (OperationOne), + OperationIncDec(OperationIncDec) , + OperationTwo (OperationTwo), Immediate8(u8), Immediate16(u16), @@ -280,6 +289,7 @@ enum AstNode { Register(u8), ImmediatePointer(u32), RegisterPointer(u8), + RegisterPointerOffset(u8, u8), Constant { name: String, @@ -314,6 +324,7 @@ enum AstNode { Origin(u32), OriginPadded(u32), + Optimize(bool) } fn format_address_table(m: &HashMap) -> String { @@ -364,7 +375,7 @@ fn main() { } println!("Parsing file..."); - let ast = match parse(&input_file) { + let mut ast = match parse(&input_file) { Ok(x) => x, Err(x) => { println!("{:#?}", x); @@ -376,7 +387,9 @@ fn main() { let mut current_address: u32 = 0; println!("Assembling..."); - for node in ast { + let mut optimize = false; + for mut node in ast { + node = optimize_node(node, &mut optimize); if let AstNode::LabelDefine {name, ..} = node { let mut address_table = LABEL_ADDRESSES.lock().unwrap(); if let Some(_) = address_table.get(&name) { @@ -404,6 +417,8 @@ fn main() { } else if let AstNode::IncludedBinary(binary_vec) = node { current_address += binary_vec.len() as u32; instructions.push(binary_vec.into()); + } else if let AstNode::Optimize(_) = node { + } else { let instruction = assemble_node(node); instruction.set_address(current_address); @@ -563,7 +578,6 @@ fn parse(source: &str) -> Result, Error> { fn build_ast_from_expression(pair: pest::iterators::Pair) -> AstNode { //println!("{:#?}\n\n", pair); // debug - let pair_rule = pair.as_rule(); let mut inner_pair = pair.into_inner(); *CURRENT_CONDITION.lock().unwrap() = Condition::Always; @@ -586,6 +600,7 @@ fn build_ast_from_expression(pair: pest::iterators::Pair) -> AstNode { Rule::constant => parse_constant(inner_pair), Rule::label => parse_label(inner_pair.next().unwrap(), inner_pair.next()), Rule::data => parse_data(inner_pair.next().unwrap()), + Rule::opt => parse_opt(inner_pair.next().unwrap()), Rule::origin => parse_origin(inner_pair.next().unwrap()), Rule::include_bin => include_binary_file(inner_pair.next().unwrap(), false), Rule::include_bin_optional => include_binary_file(inner_pair.next().unwrap(), true), @@ -686,7 +701,13 @@ fn parse_data(pair: pest::iterators::Pair) -> AstNode { _ => panic!("Unsupported data: {}", pair.as_str()), } } - +fn parse_opt(rule: pest::iterators::Pair) -> AstNode { + match rule.as_str() { + "opton"=>AstNode::Optimize(true), + "optoff"=>AstNode::Optimize(false), + _ => panic!("Unknown optimize flag {}", rule.as_str()) + } +} fn parse_origin(pair: pest::iterators::Pair) -> AstNode { //println!("{:#?}", pair); match pair.as_rule() { @@ -825,45 +846,67 @@ fn immediate_to_astnode(immediate: u32, size: Size, is_pointer: bool) -> AstNode } } +fn parse_immediate(pair: pest::iterators::Pair) -> u32 { + match pair.as_rule() { + Rule::immediate_bin => { + let body_bin_str = pair.into_inner().next().unwrap().as_str(); + u32::from_str_radix(&remove_underscores(body_bin_str), 2).unwrap() + } + Rule::immediate_hex => { + let body_hex_str = pair.into_inner().next().unwrap().as_str(); + u32::from_str_radix(&remove_underscores(body_hex_str), 16).unwrap() + } + Rule::immediate_dec => { + let dec_str = pair.as_span().as_str(); + remove_underscores(dec_str).parse::().unwrap() + } + Rule::immediate_char => { + let body_char_str = pair.into_inner().next().unwrap().as_str(); + body_char_str.chars().nth(0).unwrap() as u8 as u32 + } + _=> { + panic!() + } + } +} + +fn parse_register(pair: pest::iterators::Pair) -> u8 { + let register_num_pair = pair.into_inner().next().unwrap(); + let register_num = if register_num_pair.as_str() == "sp" { 32 } + else if register_num_pair.as_str() == "esp" { 33 } + else if register_num_pair.as_str() == "fp" { 34 } + else { register_num_pair.as_str().parse::().unwrap() }; + if register_num > 34 { panic!("register number out of range"); } + register_num +} + fn parse_operand(mut pair: pest::iterators::Pair, is_pointer: bool) -> AstNode { //println!("parse_operand: {:#?}", pair); // debug + // dbg!(&pair); let size = *CURRENT_SIZE.lock().unwrap(); + let pointer_offset = if is_pointer { // skip past the operand_value_ptr pair and look at its operand_value rule - pair = pair.into_inner().next().unwrap(); - } + let mut pairs = pair.into_inner(); + pair = pairs.next().unwrap(); + pairs.next() + // pair = pair.into_inner().next().unwrap(); + }else { + None + }; match pair.as_rule() { Rule::operand_value => { let mut inner_pair = pair.into_inner(); let operand_value_pair = inner_pair.next().unwrap(); match operand_value_pair.as_rule() { - Rule::immediate_bin => { - let body_bin_str = operand_value_pair.into_inner().next().unwrap().as_str(); - let immediate = u32::from_str_radix(&remove_underscores(body_bin_str), 2).unwrap(); - immediate_to_astnode(immediate, size, is_pointer) - } + Rule::immediate_bin| + Rule::immediate_char| + Rule::immediate_dec| Rule::immediate_hex => { - let body_hex_str = operand_value_pair.into_inner().next().unwrap().as_str(); - let immediate = u32::from_str_radix(&remove_underscores(body_hex_str), 16).unwrap(); - immediate_to_astnode(immediate, size, is_pointer) - } - Rule::immediate_dec => { - let dec_str = operand_value_pair.as_span().as_str(); - let immediate = remove_underscores(dec_str).parse::().unwrap(); - immediate_to_astnode(immediate, size, is_pointer) - } - Rule::immediate_char => { - let body_char_str = operand_value_pair.into_inner().next().unwrap().as_str(); - let immediate = body_char_str.chars().nth(0).unwrap() as u8 as u32; - immediate_to_astnode(immediate, size, is_pointer) + immediate_to_astnode(parse_immediate(operand_value_pair), size, is_pointer) } Rule::register => { - let register_num_pair = operand_value_pair.into_inner().next().unwrap(); - let register_num = if register_num_pair.as_str() == "sp" { 32 } - else if register_num_pair.as_str() == "esp" { 33 } - else if register_num_pair.as_str() == "fp" { 34 } - else { register_num_pair.as_str().parse::().unwrap() }; - if register_num > 34 { panic!("register number out of range"); } + let register_num = parse_register(operand_value_pair); if is_pointer { AstNode::RegisterPointer(register_num) } else { @@ -887,12 +930,25 @@ fn parse_operand(mut pair: pest::iterators::Pair, is_pointer: bool) -> Ast _ => todo!(), } } + Rule::register => { + let register_num = parse_register(pair); + let offset = if let Some(offset_pair) = pointer_offset { + parse_immediate(offset_pair.into_inner().next().unwrap()) + } else { + 0 + }; + if offset == 0 { + AstNode::RegisterPointer(register_num) + } else { + AstNode::RegisterPointerOffset(register_num, offset as u8) + } + } _ => panic!(), } } fn parse_instruction_zero(pair: pest::iterators::Pair, size: Size, condition: Condition) -> AstNode { - AstNode::OperationZero { + AstNode::OperationZero ( OperationZero { size: size, condition: condition, instruction: match pair.as_str() { @@ -906,12 +962,12 @@ fn parse_instruction_zero(pair: pest::iterators::Pair, size: Size, conditi "mse" => InstructionZero::Mse, "mcl" => InstructionZero::Mcl, _ => panic!("Unsupported conditional instruction (zero): {}", pair.as_str()), - }, - } + } + }) } fn parse_instruction_one(pair: pest::iterators::Pair, mut operand: AstNode, size: Size, condition: Condition) -> AstNode { - AstNode::OperationOne { + AstNode::OperationOne ( OperationOne { size: size, condition: condition, instruction: match pair.as_str() { @@ -956,12 +1012,12 @@ fn parse_instruction_one(pair: pest::iterators::Pair, mut operand: AstNode "flp" => InstructionOne::Flp, _ => panic!("Unsupported conditional instruction (one): {}", pair.as_str()), }, - operand: Box::new(operand), - } + operand: Box::new(operand) + }) } fn parse_instruction_incdec(pair: pest::iterators::Pair, lhs: AstNode, rhs: AstNode, size: Size, condition: Condition) -> AstNode { - AstNode::OperationIncDec { + AstNode::OperationIncDec ( OperationIncDec { size: size, condition: condition, instruction: match pair.as_str() { @@ -971,12 +1027,25 @@ fn parse_instruction_incdec(pair: pest::iterators::Pair, lhs: AstNode, rhs }, lhs: Box::new(lhs), rhs: Box::new(rhs), - } + }) } fn parse_instruction_two(pair: pest::iterators::Pair, mut lhs: AstNode, mut rhs: AstNode, size: Size, condition: Condition) -> AstNode { - AstNode::OperationTwo { + match pair.as_str() { + "sla" | + "sra" | + "srl" | + "rol" | + "ror" | + "bse" | + "bcl" | + "bts" => if let Some(value) = node_value(&rhs) { + rhs = AstNode::Immediate8(value as u8); + } + _=>() + } + AstNode::OperationTwo ( OperationTwo { size: size, condition: condition, instruction: match pair.as_str() { @@ -1025,7 +1094,7 @@ fn parse_instruction_two(pair: pest::iterators::Pair, mut lhs: AstNode, mu }, lhs: Box::new(lhs), rhs: Box::new(rhs), - } + }) } fn assemble_node(node: AstNode) -> AssembledInstruction { @@ -1060,12 +1129,14 @@ fn assemble_node(node: AstNode) -> AssembledInstruction { let mut instruction_data: Vec = Vec::new(); - instruction_data.push(condition_source_destination_to_byte(&node)); + let condition_source_destination = condition_source_destination_to_byte(&node); + instruction_data.push(condition_source_destination); instruction_data.push(instruction_to_byte(&node)); let mut instruction: AssembledInstruction = instruction_data.into(); - node_to_immediate_values(&node, &mut instruction); + //0x80 bit determines if we need to write the pointer offsets or not + node_to_immediate_values(&node, &mut instruction, condition_source_destination & 0x80 != 0); instruction } @@ -1090,7 +1161,7 @@ fn size_to_byte(size: Size) -> u8 { fn instruction_to_byte(node: &AstNode) -> u8 { match *node { - AstNode::OperationZero {size, instruction, ..} => { + AstNode::OperationZero (OperationZero{size, instruction, ..}) => { match instruction { InstructionZero::Nop => 0x00 | size_to_byte(size), InstructionZero::Halt => 0x10 | size_to_byte(size), @@ -1103,7 +1174,7 @@ fn instruction_to_byte(node: &AstNode) -> u8 { InstructionZero::Mcl => 0x1D | size_to_byte(size), } } - AstNode::OperationOne {size, instruction, ..} => { + AstNode::OperationOne (OperationOne{size, instruction, ..}) => { match instruction { InstructionOne::Not => 0x33 | size_to_byte(size), InstructionOne::Jmp => 0x08 | size_to_byte(size), @@ -1119,13 +1190,13 @@ fn instruction_to_byte(node: &AstNode) -> u8 { InstructionOne::Flp => 0x3D | size_to_byte(size), } } - AstNode::OperationIncDec {size, instruction, ..} => { + AstNode::OperationIncDec (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 (OperationTwo{size, instruction, ..}) => { match instruction { InstructionTwo::Add => 0x01 | size_to_byte(size), InstructionTwo::Sub => 0x21 | size_to_byte(size), @@ -1172,29 +1243,32 @@ fn condition_to_bits(condition: &Condition) -> u8 { fn condition_source_destination_to_byte(node: &AstNode) -> u8 { let source: u8 = match node { - AstNode::OperationZero {..} => 0x00, - AstNode::OperationOne {operand, ..} => { + AstNode::OperationZero (_) => 0x00, + AstNode::OperationOne (OperationOne{operand, ..}) => { match operand.as_ref() { AstNode::Register(_) => 0x00, AstNode::RegisterPointer(_) => 0x01, + AstNode::RegisterPointerOffset(_, _) => 0x81, 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::OperationIncDec {lhs, ..} => { + AstNode::OperationIncDec (OperationIncDec{lhs, ..}) => { match lhs.as_ref() { AstNode::Register(_) => 0x00, AstNode::RegisterPointer(_) => 0x01, + AstNode::RegisterPointerOffset(_, _) => 0x81, 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 (OperationTwo{rhs, ..}) => { match rhs.as_ref() { AstNode::Register(_) => 0x00, AstNode::RegisterPointer(_) => 0x01, + AstNode::RegisterPointerOffset(_, _) => 0x81, 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), @@ -1203,18 +1277,19 @@ fn condition_source_destination_to_byte(node: &AstNode) -> u8 { _ => panic!("Attempting to parse a non-instruction AST node as an instruction: {:#?}", node), }; let destination: u8 = match node { - AstNode::OperationZero {..} => 0x00, - AstNode::OperationOne {..} => 0x00, - AstNode::OperationIncDec { rhs, ..} => { + AstNode::OperationZero(_) => 0x00, + AstNode::OperationOne (_)=> 0x00, + AstNode::OperationIncDec (OperationIncDec{ rhs, ..}) => { match rhs.as_ref() { AstNode::Immediate8(n) => *n << 2, _ => panic!(""), } } - AstNode::OperationTwo {lhs, ..} => { + AstNode::OperationTwo (OperationTwo{lhs, ..}) => { match lhs.as_ref() { AstNode::Register(_) => 0x00, AstNode::RegisterPointer(_) => 0x04, + AstNode::RegisterPointerOffset(_, _) => 0x84, AstNode::Immediate8(_) | AstNode::Immediate16(_) | AstNode::Immediate32(_) | AstNode::LabelOperand {..} => 0x08, AstNode::ImmediatePointer(_) | AstNode::LabelOperandPointer {..} => 0x0C, _ => panic!("Attempting to parse a non-instruction AST node as an instruction: {:#?}", node), @@ -1223,10 +1298,10 @@ fn condition_source_destination_to_byte(node: &AstNode) -> u8 { _ => panic!("Attempting to parse a non-instruction AST node as an instruction: {:#?}", node), }; 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), + AstNode::OperationZero (OperationZero{condition, ..}) => condition_to_bits(condition), + AstNode::OperationOne (OperationOne{condition, ..}) => condition_to_bits(condition), + AstNode::OperationIncDec (OperationIncDec{condition, ..}) => condition_to_bits(condition), + AstNode::OperationTwo (OperationTwo{condition, ..}) => condition_to_bits(condition), _ => panic!("Attempting to parse a non-instruction AST node as an instruction: {:#?}", node), }; condition | source | destination @@ -1257,11 +1332,23 @@ fn generate_backpatch_immediate(name: &String, size: Size, instruction: &Assembl targets.push(BackpatchTarget::new(instruction, index, size, is_relative)); } -fn operand_to_immediate_value(instruction: &AssembledInstruction, node: &AstNode){ + +fn operand_to_immediate_value(instruction: &AssembledInstruction, node: &AstNode, pointer_offset: bool){ let mut vec = instruction.borrow_mut(); match *node { AstNode::Register (register) => vec.push(register), - AstNode::RegisterPointer(register) => vec.push(register), + AstNode::RegisterPointer(register) => { + vec.push(register); + if pointer_offset { + vec.push(0); + } + } + AstNode::RegisterPointerOffset(register, offset) => { + vec.push(register); + if pointer_offset { + vec.push(offset); + } + } AstNode::Immediate8 (immediate) => vec.push(immediate), AstNode::Immediate16 (immediate) => vec.extend_from_slice(&immediate.to_le_bytes()), @@ -1279,21 +1366,22 @@ fn operand_to_immediate_value(instruction: &AssembledInstruction, node: &AstNode _ => panic!("Attempting to parse a non-instruction AST node as an instruction: {:#?}", node), } + } -fn node_to_immediate_values(node: &AstNode, instruction: &AssembledInstruction) { +fn node_to_immediate_values(node: &AstNode, instruction: &AssembledInstruction, pointer_offset: bool) { { match node { AstNode::OperationZero {..} => {} - AstNode::OperationOne {operand, ..} => - operand_to_immediate_value(instruction, operand.as_ref()), + AstNode::OperationOne (OperationOne{operand, ..}) => + operand_to_immediate_value(instruction, operand.as_ref(), pointer_offset), - AstNode::OperationIncDec {lhs, ..} => - operand_to_immediate_value(instruction, lhs.as_ref()), + AstNode::OperationIncDec (OperationIncDec{lhs, ..}) => + operand_to_immediate_value(instruction, lhs.as_ref(), pointer_offset), - AstNode::OperationTwo {rhs, ..} => - operand_to_immediate_value(instruction, rhs.as_ref()), + AstNode::OperationTwo (OperationTwo{rhs, ..}) => + operand_to_immediate_value(instruction, rhs.as_ref(), pointer_offset), _ => panic!("Attempting to parse a non-instruction AST node as an instruction: {:#?}", node), } @@ -1304,9 +1392,116 @@ fn node_to_immediate_values(node: &AstNode, instruction: &AssembledInstruction) AstNode::OperationOne {..} => {} AstNode::OperationIncDec {..} => {} - AstNode::OperationTwo {lhs, ..} => - operand_to_immediate_value(instruction, lhs.as_ref()), + AstNode::OperationTwo (OperationTwo{lhs, ..}) => + operand_to_immediate_value(instruction, lhs.as_ref(), pointer_offset), _ => panic!("Attempting to parse a non-instruction AST node as an instruction: {:#?}", node), }; } + + +fn node_value(node: &AstNode) -> Option { + match *node { + AstNode::Immediate16(n) => Some(n as u32), + AstNode::Immediate32(n) => Some(n as u32), + AstNode::Immediate8(n) => Some(n as u32), + _ => None + } +} +fn optimize_node(node: AstNode, enabled: &mut bool) -> AstNode { + if let AstNode::Optimize(value) = node { + *enabled = value; + } + if *enabled { + match node { + AstNode::OperationTwo(mut n) => { + let v = node_value(&n.rhs); + if let Some(v) = v { + match n.instruction { + InstructionTwo::Add => { + match v { + 1 => return AstNode::OperationIncDec(OperationIncDec { size: n.size, condition: n.condition, instruction: InstructionIncDec::Inc, lhs: n.lhs, rhs: Box::new(AstNode::Immediate8(0)) }), + 2 => return AstNode::OperationIncDec(OperationIncDec { size: n.size, condition: n.condition, instruction: InstructionIncDec::Inc, lhs: n.lhs, rhs: Box::new(AstNode::Immediate8(1)) }), + 4 => return AstNode::OperationIncDec(OperationIncDec { size: n.size, condition: n.condition, instruction: InstructionIncDec::Inc, lhs: n.lhs, rhs: Box::new(AstNode::Immediate8(2)) }), + 8 => return AstNode::OperationIncDec(OperationIncDec { size: n.size, condition: n.condition, instruction: InstructionIncDec::Inc, lhs: n.lhs, rhs: Box::new(AstNode::Immediate8(3)) }), + _ => () + } + + }, + InstructionTwo::Sub => { + match v { + 1 => return AstNode::OperationIncDec(OperationIncDec { size: n.size, condition: n.condition, instruction: InstructionIncDec::Dec, lhs: n.lhs, rhs: Box::new(AstNode::Immediate8(0)) }), + 2 => return AstNode::OperationIncDec(OperationIncDec { size: n.size, condition: n.condition, instruction: InstructionIncDec::Dec, lhs: n.lhs, rhs: Box::new(AstNode::Immediate8(1)) }), + 4 => return AstNode::OperationIncDec(OperationIncDec { size: n.size, condition: n.condition, instruction: InstructionIncDec::Dec, lhs: n.lhs, rhs: Box::new(AstNode::Immediate8(2)) }), + 8 => return AstNode::OperationIncDec(OperationIncDec { size: n.size, condition: n.condition, instruction: InstructionIncDec::Dec, lhs: n.lhs, rhs: Box::new(AstNode::Immediate8(3)) }), + _ => () + } + + }, + InstructionTwo::Mov => { + if let Size::Word = n.size { + if let AstNode::Register(_) = *n.lhs { + if v <= 0xff { + n.size = Size::Byte; + n.instruction = InstructionTwo::Movz; + n.rhs = Box::new(AstNode::Immediate8(v as u8)); + } + + else if v <= 0xffff { + n.size = Size::Half; + n.instruction = InstructionTwo::Movz; + n.rhs = Box::new(AstNode::Immediate16(v as u16)); + } + } + + } + }, + InstructionTwo::Mul => { + if let Size::Word = n.size { + if v.is_power_of_two() { + n.instruction = InstructionTwo::Sla; + n.rhs = Box::new(AstNode::Immediate8(v.trailing_zeros() as u8)); + } + } + + }, + InstructionTwo::Idiv => { + if let Size::Word = n.size { + if v.is_power_of_two() { + n.instruction = InstructionTwo::Sra; + n.rhs = Box::new(AstNode::Immediate8(v.trailing_zeros() as u8)); + } + + } + }, + InstructionTwo::Div => { + if let Size::Word = n.size { + if v.is_power_of_two() { + n.instruction = InstructionTwo::Srl; + n.rhs = Box::new(AstNode::Immediate8(v.trailing_zeros() as u8)); + } + + } + }, + // InstructionTwo::Sla + // | InstructionTwo::Srl | InstructionTwo::Sra + // | InstructionTwo::Bcl | InstructionTwo::Bse + // | InstructionTwo::Bts + // | InstructionTwo::Ror | InstructionTwo::Rol + // => { + // n.rhs = Box::new(AstNode::Immediate8(v as u8)); + + // } + + _ => () + } + } + + AstNode::OperationTwo(n) + } + _=> node + } + } else { + node + } +} \ No newline at end of file