Loading Cargo.toml +7 −2 Original line number Diff line number Diff line # Cargo.toml # By: John Jekel # Copyright (C) 2023 John Jekel # See the LICENSE file at the root of the project for licensing info. # # LEGv8 Cargo manifest # [package] name = "legv8" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] [lib] Loading lib/lib.rs +1 −1 Original line number Diff line number Diff line /* lib.rs * By: John Jekel * Copyright (C) 2022-2023 John Jekel * Copyright (C) 2023 John Jekel * See the LICENSE file at the root of the project for licensing info. * * LEGv8 Library Loading src/legv8assemble.rs +38 −26 Original line number Diff line number Diff line /* legv8assembles.rs * By: John Jekel * Copyright (C) 2022-2023 John Jekel * Copyright (C) 2023 John Jekel * See the LICENSE file at the root of the project for licensing info. * * Assembles individual LEGv8 instructions Loading Loading @@ -69,7 +69,9 @@ impl ConvenientlyBitAccessible for u32 { /* Functions */ fn main() { eprintln!("\x1b[1m\x1b[35mlegv8assemble\x1b[0m, by \x1b[96mJohn Jekel\x1b[0m (2023)\n"); eprintln!("\x1b[1m\x1b[35mlegv8assemble\x1b[0m, by \x1b[96mJZJ\x1b[0m :)"); eprintln!("Copyright (C) 2023 John Jekel"); eprintln!("See the LICENSE file at the root of the project for licensing info.\n"); eprintln!("\x1b[90mAt the prompt, enter a LEGv8 instruction to assemble, or press Ctrl+C to exit...\x1b[0m"); let stdin = std::io::stdin(); Loading Loading @@ -394,21 +396,25 @@ fn assemble(instruction_string: &str) -> Option<(InstructionType, u32)> { //Determine the immediate/address to use from the 4th token depending on the instruction_type match instruction_type { InstructionType::I => { if let Some(immediate) = smart_parse_uint(tokens[3]) { if immediate > 0b111111111111 {//Too large for the field to hold if let Some(immediate) = smart_parse_immediate(tokens[3]) { //The field is 12 bits, so immediate must be between -2048 and +2047 if (immediate < -2048) || (immediate > 2047) {//Too large for the field to hold return None; } instruction.set_bits(immediate, 21, 10); let masked_immediate = (immediate as u32) & 0b111111111111; instruction.set_bits(masked_immediate as u32, 21, 10); } else { return None; } }, InstructionType::D => { if let Some(address) = smart_parse_uint(tokens[3]) { if address > 0b111111111 {//Too large for the field to hold if let Some(address) = smart_parse_immediate(tokens[3]) { //The field is 9 bits, so address must be between -512 and +511 if (address < -512) || (address > 511) {//Too large for the field to hold return None; } instruction.set_bits(address, 20, 12); let masked_address = (address as u32) & 0b111111111; instruction.set_bits(masked_address, 20, 12); } else { return None; } Loading @@ -418,11 +424,13 @@ fn assemble(instruction_string: &str) -> Option<(InstructionType, u32)> { //Determine the branch address to use from the second token if the instruction type is B if matches!(instruction_type, InstructionType::B) { if let Some(address) = smart_parse_uint(tokens[1]) { if address > 0b11111111111111111111111111 {//Too large for the field to hold if let Some(address) = smart_parse_immediate(tokens[1]) { //The field is 26 bits, so address must be between -33554432 and 33554431 if (address < -33554432) || (address > 33554431) {//Too large for the field to hold return None; } instruction.set_bits(address, 25, 0); let masked_address = (address as u32) & 0b11111111111111111111111111; instruction.set_bits(masked_address, 25, 0); } else { return None; } Loading @@ -431,21 +439,25 @@ fn assemble(instruction_string: &str) -> Option<(InstructionType, u32)> { //Determine the branch address/immediate to use from the third token if the instruction type is CB or IM respectively match instruction_type { InstructionType::CB => { if let Some(address) = smart_parse_uint(tokens[2]) { if address > 0b1111111111111111111 {//Too large for the field to hold if let Some(address) = smart_parse_immediate(tokens[2]) { //The field is 19 bits, so address must be between -262144 and 262143 if (address < -262144) || (address > 262143) {//Too large for the field to hold return None; } instruction.set_bits(address, 23, 5); let masked_address = (address as u32) & 0b1111111111111111111; instruction.set_bits(masked_address, 23, 5); } else { return None; } }, InstructionType::IM => { if let Some(address) = smart_parse_uint(tokens[2]) { if address > 0b1111111111111111 {//Too large for the field to hold if let Some(immediate) = smart_parse_immediate(tokens[2]) { //The field is 16 bits, so immediate must be between -32768 and 32767 if (immediate < -32768) || (immediate > 32767) {//Too large for the field to hold return None; } instruction.set_bits(address, 20, 5); let masked_immediate = (immediate as u32) & 0b1111111111111111; instruction.set_bits(masked_immediate, 20, 5); } else { return None; } Loading @@ -461,7 +473,7 @@ fn assemble(instruction_string: &str) -> Option<(InstructionType, u32)> { } //There are only 4 valid shift amounts that can come after match smart_parse_uint(tokens[4]) { match smart_parse_immediate(tokens[4]) { Some(0) => { instruction.set_bits(0b00, 22, 21); }, Some(16) => { instruction.set_bits(0b01, 22, 21); }, Some(32) => { instruction.set_bits(0b10, 22, 21); }, Loading Loading @@ -493,20 +505,20 @@ fn parse_register(register_token: &str) -> Option<u32> { } } fn smart_parse_uint(uint_string: &str) -> Option<u32> { fn smart_parse_immediate(uint_string: &str) -> Option<i32> { if let Some(binary_uint_string) = uint_string.strip_prefix("0b") { return u32::from_str_radix(binary_uint_string, 2).ok(); return i32::from_str_radix(binary_uint_string, 2).ok(); } else if let Some(binary_uint_string) = uint_string.strip_prefix("0B") { return u32::from_str_radix(binary_uint_string, 2).ok(); return i32::from_str_radix(binary_uint_string, 2).ok(); } else if let Some(hex_uint_string) = uint_string.strip_prefix("0x") { return u32::from_str_radix(hex_uint_string, 16).ok(); return i32::from_str_radix(hex_uint_string, 16).ok(); } else if let Some(hex_uint_string) = uint_string.strip_prefix("0X") { return u32::from_str_radix(hex_uint_string, 16).ok(); return i32::from_str_radix(hex_uint_string, 16).ok(); } else if let Some(oct_uint_string) = uint_string.strip_prefix("0o") { return u32::from_str_radix(oct_uint_string, 8).ok(); return i32::from_str_radix(oct_uint_string, 8).ok(); } else if let Some(oct_uint_string) = uint_string.strip_prefix("0O") { return u32::from_str_radix(oct_uint_string, 8).ok(); } else if let Some(dec_uint) = uint_string.parse::<u32>().ok() { return i32::from_str_radix(oct_uint_string, 8).ok(); } else if let Some(dec_uint) = uint_string.parse::<i32>().ok() { return Some(dec_uint); } else { return None; Loading src/legv8disassemble.rs +2 −1 Original line number Diff line number Diff line /* legv8disassemble.rs * By: John Jekel * Copyright (C) 2022-2023 John Jekel * Copyright (C) 2023 John Jekel * See the LICENSE file at the root of the project for licensing info. * * Disassembles individual LEGv8 instructions Loading Loading @@ -34,5 +34,6 @@ /* Functions */ fn main() { eprintln!("Coming soon!"); todo!(); } src/legv8emulator.rs +2 −1 Original line number Diff line number Diff line /* legv8emulator.rs * By: John Jekel * Copyright (C) 2022-2023 John Jekel * Copyright (C) 2023 John Jekel * See the LICENSE file at the root of the project for licensing info. * * Emulates a LEGv8 system Loading Loading @@ -35,5 +35,6 @@ fn main() { //TODO use HashMap for sparse memory since we don't care about performance eprintln!("Coming soon!"); todo!(); } Loading
Cargo.toml +7 −2 Original line number Diff line number Diff line # Cargo.toml # By: John Jekel # Copyright (C) 2023 John Jekel # See the LICENSE file at the root of the project for licensing info. # # LEGv8 Cargo manifest # [package] name = "legv8" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] [lib] Loading
lib/lib.rs +1 −1 Original line number Diff line number Diff line /* lib.rs * By: John Jekel * Copyright (C) 2022-2023 John Jekel * Copyright (C) 2023 John Jekel * See the LICENSE file at the root of the project for licensing info. * * LEGv8 Library Loading
src/legv8assemble.rs +38 −26 Original line number Diff line number Diff line /* legv8assembles.rs * By: John Jekel * Copyright (C) 2022-2023 John Jekel * Copyright (C) 2023 John Jekel * See the LICENSE file at the root of the project for licensing info. * * Assembles individual LEGv8 instructions Loading Loading @@ -69,7 +69,9 @@ impl ConvenientlyBitAccessible for u32 { /* Functions */ fn main() { eprintln!("\x1b[1m\x1b[35mlegv8assemble\x1b[0m, by \x1b[96mJohn Jekel\x1b[0m (2023)\n"); eprintln!("\x1b[1m\x1b[35mlegv8assemble\x1b[0m, by \x1b[96mJZJ\x1b[0m :)"); eprintln!("Copyright (C) 2023 John Jekel"); eprintln!("See the LICENSE file at the root of the project for licensing info.\n"); eprintln!("\x1b[90mAt the prompt, enter a LEGv8 instruction to assemble, or press Ctrl+C to exit...\x1b[0m"); let stdin = std::io::stdin(); Loading Loading @@ -394,21 +396,25 @@ fn assemble(instruction_string: &str) -> Option<(InstructionType, u32)> { //Determine the immediate/address to use from the 4th token depending on the instruction_type match instruction_type { InstructionType::I => { if let Some(immediate) = smart_parse_uint(tokens[3]) { if immediate > 0b111111111111 {//Too large for the field to hold if let Some(immediate) = smart_parse_immediate(tokens[3]) { //The field is 12 bits, so immediate must be between -2048 and +2047 if (immediate < -2048) || (immediate > 2047) {//Too large for the field to hold return None; } instruction.set_bits(immediate, 21, 10); let masked_immediate = (immediate as u32) & 0b111111111111; instruction.set_bits(masked_immediate as u32, 21, 10); } else { return None; } }, InstructionType::D => { if let Some(address) = smart_parse_uint(tokens[3]) { if address > 0b111111111 {//Too large for the field to hold if let Some(address) = smart_parse_immediate(tokens[3]) { //The field is 9 bits, so address must be between -512 and +511 if (address < -512) || (address > 511) {//Too large for the field to hold return None; } instruction.set_bits(address, 20, 12); let masked_address = (address as u32) & 0b111111111; instruction.set_bits(masked_address, 20, 12); } else { return None; } Loading @@ -418,11 +424,13 @@ fn assemble(instruction_string: &str) -> Option<(InstructionType, u32)> { //Determine the branch address to use from the second token if the instruction type is B if matches!(instruction_type, InstructionType::B) { if let Some(address) = smart_parse_uint(tokens[1]) { if address > 0b11111111111111111111111111 {//Too large for the field to hold if let Some(address) = smart_parse_immediate(tokens[1]) { //The field is 26 bits, so address must be between -33554432 and 33554431 if (address < -33554432) || (address > 33554431) {//Too large for the field to hold return None; } instruction.set_bits(address, 25, 0); let masked_address = (address as u32) & 0b11111111111111111111111111; instruction.set_bits(masked_address, 25, 0); } else { return None; } Loading @@ -431,21 +439,25 @@ fn assemble(instruction_string: &str) -> Option<(InstructionType, u32)> { //Determine the branch address/immediate to use from the third token if the instruction type is CB or IM respectively match instruction_type { InstructionType::CB => { if let Some(address) = smart_parse_uint(tokens[2]) { if address > 0b1111111111111111111 {//Too large for the field to hold if let Some(address) = smart_parse_immediate(tokens[2]) { //The field is 19 bits, so address must be between -262144 and 262143 if (address < -262144) || (address > 262143) {//Too large for the field to hold return None; } instruction.set_bits(address, 23, 5); let masked_address = (address as u32) & 0b1111111111111111111; instruction.set_bits(masked_address, 23, 5); } else { return None; } }, InstructionType::IM => { if let Some(address) = smart_parse_uint(tokens[2]) { if address > 0b1111111111111111 {//Too large for the field to hold if let Some(immediate) = smart_parse_immediate(tokens[2]) { //The field is 16 bits, so immediate must be between -32768 and 32767 if (immediate < -32768) || (immediate > 32767) {//Too large for the field to hold return None; } instruction.set_bits(address, 20, 5); let masked_immediate = (immediate as u32) & 0b1111111111111111; instruction.set_bits(masked_immediate, 20, 5); } else { return None; } Loading @@ -461,7 +473,7 @@ fn assemble(instruction_string: &str) -> Option<(InstructionType, u32)> { } //There are only 4 valid shift amounts that can come after match smart_parse_uint(tokens[4]) { match smart_parse_immediate(tokens[4]) { Some(0) => { instruction.set_bits(0b00, 22, 21); }, Some(16) => { instruction.set_bits(0b01, 22, 21); }, Some(32) => { instruction.set_bits(0b10, 22, 21); }, Loading Loading @@ -493,20 +505,20 @@ fn parse_register(register_token: &str) -> Option<u32> { } } fn smart_parse_uint(uint_string: &str) -> Option<u32> { fn smart_parse_immediate(uint_string: &str) -> Option<i32> { if let Some(binary_uint_string) = uint_string.strip_prefix("0b") { return u32::from_str_radix(binary_uint_string, 2).ok(); return i32::from_str_radix(binary_uint_string, 2).ok(); } else if let Some(binary_uint_string) = uint_string.strip_prefix("0B") { return u32::from_str_radix(binary_uint_string, 2).ok(); return i32::from_str_radix(binary_uint_string, 2).ok(); } else if let Some(hex_uint_string) = uint_string.strip_prefix("0x") { return u32::from_str_radix(hex_uint_string, 16).ok(); return i32::from_str_radix(hex_uint_string, 16).ok(); } else if let Some(hex_uint_string) = uint_string.strip_prefix("0X") { return u32::from_str_radix(hex_uint_string, 16).ok(); return i32::from_str_radix(hex_uint_string, 16).ok(); } else if let Some(oct_uint_string) = uint_string.strip_prefix("0o") { return u32::from_str_radix(oct_uint_string, 8).ok(); return i32::from_str_radix(oct_uint_string, 8).ok(); } else if let Some(oct_uint_string) = uint_string.strip_prefix("0O") { return u32::from_str_radix(oct_uint_string, 8).ok(); } else if let Some(dec_uint) = uint_string.parse::<u32>().ok() { return i32::from_str_radix(oct_uint_string, 8).ok(); } else if let Some(dec_uint) = uint_string.parse::<i32>().ok() { return Some(dec_uint); } else { return None; Loading
src/legv8disassemble.rs +2 −1 Original line number Diff line number Diff line /* legv8disassemble.rs * By: John Jekel * Copyright (C) 2022-2023 John Jekel * Copyright (C) 2023 John Jekel * See the LICENSE file at the root of the project for licensing info. * * Disassembles individual LEGv8 instructions Loading Loading @@ -34,5 +34,6 @@ /* Functions */ fn main() { eprintln!("Coming soon!"); todo!(); }
src/legv8emulator.rs +2 −1 Original line number Diff line number Diff line /* legv8emulator.rs * By: John Jekel * Copyright (C) 2022-2023 John Jekel * Copyright (C) 2023 John Jekel * See the LICENSE file at the root of the project for licensing info. * * Emulates a LEGv8 system Loading Loading @@ -35,5 +35,6 @@ fn main() { //TODO use HashMap for sparse memory since we don't care about performance eprintln!("Coming soon!"); todo!(); }