Commit 0a916f64 authored by Kai Rese's avatar Kai Rese
Browse files

fix little endian code generation

parent b1465dc8
......@@ -3,26 +3,26 @@ use crate::program::instruction::InstructionStatement;
use crate::program::statement::Statement;
pub fn assemble(statements: &[Statement]) -> Result<Vec<u8>, ErrorVec> {
let mut output = Vec::<u8>::with_capacity(256);
let mut output = Vec::<u8>::new();
let mut errors = ErrorVec::new();
let mut register_symbols: Vec<(&str, u8)> = vec![
("reg0", 0),
("reg1", 1),
("reg2", 2),
("reg3", 3),
("reg4", 4),
("reg5", 5),
("reg6", 6),
("reg7", 7),
("reg8", 8),
("reg9", 9),
("reg10", 10),
("reg11", 11),
("reg12", 12),
("reg13", 13),
("reg14", 14),
("reg15", 15),
let mut register_symbols: Vec<(&str, u16)> = vec![
("reg0", 0x0),
("reg1", 0x1),
("reg2", 0x2),
("reg3", 0x3),
("reg4", 0x4),
("reg5", 0x5),
("reg6", 0x6),
("reg7", 0x7),
("reg8", 0x8),
("reg9", 0x9),
("reg10", 0xa),
("reg11", 0xb),
("reg12", 0xc),
("reg13", 0xd),
("reg14", 0xe),
("reg15", 0xf),
];
let mut label_symbols = Vec::<(&str, usize)>::new();
let mut curr_position: usize = 0;
......@@ -58,7 +58,7 @@ pub fn assemble(statements: &[Statement]) -> Result<Vec<u8>, ErrorVec> {
if let Statement::Instruction(instruction) = statement {
let line_number = index + 1;
curr_position += 2;
let code = match instruction {
let assembled_instruction = match instruction {
InstructionStatement::AddReg(identifier) => {
encode_3_reg(line_number, &register_symbols, 0x0, *identifier)
}
......@@ -129,17 +129,13 @@ pub fn assemble(statements: &[Statement]) -> Result<Vec<u8>, ErrorVec> {
InstructionStatement::BoolTable(arguments) => {
encode_2_reg_imm(line_number, &register_symbols, 0xd, *arguments)
}
InstructionStatement::Stop => Ok((0x0f, 0x00)),
InstructionStatement::Data((first, _)) => Ok((
((*first as usize >> 8) & 0xff) as u8,
(*first as usize & 0xff) as u8,
)),
InstructionStatement::Stop => Ok(0xf000),
InstructionStatement::Data((first, _)) => Ok(*first as u16),
};
match code {
Ok((low, high)) => {
output.push(low);
output.push(high);
match assembled_instruction {
Ok(data) => {
output.extend_from_slice(&data.to_le_bytes()[..]);
}
Err(error) => errors.push(error),
}
......@@ -155,71 +151,69 @@ pub fn assemble(statements: &[Statement]) -> Result<Vec<u8>, ErrorVec> {
fn encode_3_reg<'a>(
line_number: usize,
register_symbols: &'a [(&str, u8)],
code: u8,
register_symbols: &'a [(&str, u16)],
opcode: u16,
identifier: (&'a str, &'a str, &'a str),
) -> Result<(u8, u8), Error> {
let low_byte: u8 = code | (get_identifier(line_number, register_symbols, identifier.0)? << 4);
let high_byte: u8 = get_identifier(line_number, register_symbols, identifier.1)?
| (get_identifier(line_number, register_symbols, identifier.2)? << 4);
Ok((low_byte, high_byte))
) -> Result<u16, Error> {
Ok((opcode << 12)
| (get_identifier(line_number, register_symbols, identifier.0)? << 8)
| (get_identifier(line_number, register_symbols, identifier.1)? << 4)
| get_identifier(line_number, register_symbols, identifier.2)?)
}
fn encode_reg_imm<'a>(
line_number: usize,
register_symbols: &'a [(&str, u8)],
code: u8,
register_symbols: &'a [(&str, u16)],
opcode: u16,
arguments: (&'a str, isize),
signed: bool,
) -> Result<(u8, u8), Error> {
let low_byte: u8 = code | (get_identifier(line_number, register_symbols, arguments.0)? << 4);
) -> Result<u16, Error> {
assert_range(line_number, arguments.1, 8, signed)?;
let high_byte: u8 = arguments.1 as u8;
Ok((low_byte, high_byte))
Ok((opcode << 12)
| (get_identifier(line_number, register_symbols, arguments.0)? << 8)
| (arguments.1 as u16 & 0x00ff))
}
fn encode_reg_target<'a>(
line_number: usize,
register_symbols: &'a [(&str, u8)],
register_symbols: &'a [(&str, u16)],
label_symbols: &'a [(&str, usize)],
ip: usize,
code: u8,
opcode: u16,
arguments: (&'a str, Option<&'a str>, isize),
) -> Result<(u8, u8), Error> {
) -> Result<u16, Error> {
let target =
get_target_address(line_number, label_symbols, arguments.1, ip)? as isize + arguments.2;
assert_range(line_number, target, 8, true)?;
let low_byte: u8 = code | (get_identifier(line_number, &register_symbols, arguments.0)? << 4);
let high_byte: u8 = target as u8;
Ok((low_byte, high_byte))
Ok((opcode << 12)
| (get_identifier(line_number, &register_symbols, arguments.0)? << 8)
| (target as u16 & 0x00ff))
}
fn encode_target<'a>(
line_number: usize,
label_symbols: &[(&str, usize)],
ip: usize,
code: u8,
opcode: u16,
arguments: (Option<&'a str>, isize),
) -> Result<(u8, u8), Error> {
) -> Result<u16, Error> {
let target =
get_target_address(line_number, label_symbols, arguments.0, ip)? as isize + arguments.1;
assert_range(line_number, target, 12, true)?;
let low_byte: u8 = code | ((target & 0xf) << 4) as u8;
let high_byte: u8 = (target >> 4) as u8;
Ok((low_byte, high_byte))
Ok((opcode << 12) | (target as u16 & 0x0fff))
}
fn encode_2_reg_imm<'a>(
line_number: usize,
register_symbols: &[(&str, u8)],
code: u8,
register_symbols: &[(&str, u16)],
opcode: u16,
arguments: (&'a str, &'a str, isize),
) -> Result<(u8, u8), Error> {
let low_byte: u8 = code | (get_identifier(line_number, register_symbols, arguments.0)? << 4);
) -> Result<u16, Error> {
assert_range(line_number, arguments.2, 4, false)?;
let high_byte: u8 =
get_identifier(line_number, register_symbols, arguments.1)? | (arguments.2 << 4) as u8;
Ok((low_byte, high_byte))
Ok((opcode << 12)
| (get_identifier(line_number, register_symbols, arguments.0)? << 8)
| (get_identifier(line_number, register_symbols, arguments.1)? << 4)
| (arguments.2 as u16 & 0x000f))
}
fn get_target_address<'a>(
......@@ -238,9 +232,9 @@ fn get_target_address<'a>(
fn get_identifier<'a>(
line_number: usize,
register_symbols: &[(&str, u8)],
register_symbols: &[(&str, u16)],
key: &'a str,
) -> Result<u8, Error> {
) -> Result<u16, Error> {
if let Ok(index) = register_symbols.binary_search_by(|entry| entry.0.cmp(key)) {
Ok(register_symbols[index].1)
} else {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment