diff --git a/.gitignore b/.gitignore index 23818eaa..7b4aa614 100644 --- a/.gitignore +++ b/.gitignore @@ -26,4 +26,4 @@ name-ext/node_modules/* *.o !name-as/.artifacts/* name-fmt/node_modules/ -*.li +name-as/*.li diff --git a/name-as/.artifacts/mars_output.o b/name-as/.artifacts/mars_output.o index a76ca6b4..26487088 100644 Binary files a/name-as/.artifacts/mars_output.o and b/name-as/.artifacts/mars_output.o differ diff --git a/name-as/.artifacts/mips_test.asm b/name-as/.artifacts/mips_test.asm index d2fedd37..44f6db3a 100644 --- a/name-as/.artifacts/mips_test.asm +++ b/name-as/.artifacts/mips_test.asm @@ -1,12 +1,17 @@ main: - add $t1,$t2,$t3 + add $t0,$t2,$t3 sub $t4, $t5, $t6 sll $s0, $s0, 5 srl $s5, $s7, 10 xor $t7, $t8, $t9 lui $t0, 50 ori $t0, $t1, 50 + ori $t0, $t0, 0x50 + ori $t0, $t0, 050 + ori $t0, $t0, 0b1010 + lb $t0, 0x50($t1) lb $t0, 50($t1) + lb $t0, ($t1) beq $s0, $s0, test test: j test diff --git a/name-as/.artifacts/mips_test.o b/name-as/.artifacts/mips_test.o index 7b6ef953..5d5bb01d 100644 Binary files a/name-as/.artifacts/mips_test.o and b/name-as/.artifacts/mips_test.o differ diff --git a/name-as/Makefile b/name-as/Makefile index 536082cc..b728add8 100644 --- a/name-as/Makefile +++ b/name-as/Makefile @@ -25,7 +25,7 @@ run-gnu: build test: run $(CARGO) run -- $(GNUCFG) $(INPUT) gnu-$(OUTPUT) - md5sum $(OUTPUT) gnu-$(OUTPUT) + md5sum $(OUTPUT) .artifacts/mars_output.o gnu-$(OUTPUT) clean: $(CARGO) clean diff --git a/name-as/src/nma.rs b/name-as/src/nma.rs index 9e9fb573..16c1070e 100644 --- a/name-as/src/nma.rs +++ b/name-as/src/nma.rs @@ -26,6 +26,24 @@ fn mask_u32(n: u32, x: u8) -> Result { } } +fn base_parse(input: &str) -> Result { + if input.starts_with("0x") { + // Hexadecimal + u32::from_str_radix(&input[2..], 16).map_err(|_| "Failed to parse as hexadecimal") + } else if input.starts_with("0b") { + // Binary + u32::from_str_radix(&input[2..], 2).map_err(|_| "Failed to parse as binary") + } else if input.starts_with('0') && input.len() > 1 { + // Octal + u32::from_str_radix(&input[1..], 8).map_err(|_| "Failed to parse as octal") + } else { + // Decimal + input + .parse::() + .map_err(|_| "Failed to parse as decimal") + } +} + const TEXT_ADDRESS_BASE: u32 = 0x400000; const MIPS_INSTR_BYTE_WIDTH: u32 = 4; @@ -281,8 +299,8 @@ fn assemble_r(r_struct: R, r_args: Vec<&str>) -> Result { rd = assemble_reg(r_args[0])?; rs = 0; rt = assemble_reg(r_args[1])?; - shamt = match r_args[2].parse::() { - Ok(v) => v, + shamt = match base_parse(r_args[2]) { + Ok(v) => v as u8, Err(_) => return Err("Failed to parse shamt"), } } @@ -345,19 +363,28 @@ fn assemble_i( enforce_length(&i_args, 2)?; rs = 0; rt = assemble_reg(i_args[0])?; - imm = match i_args[1].parse::() { - Ok(v) => v, + imm = match base_parse(i_args[1]) { + Ok(v) => v as u16, Err(_) => return Err("Failed to parse imm"), } } IForm::RtImmRs => { - enforce_length(&i_args, 3)?; - rt = assemble_reg(i_args[0])?; - imm = match i_args[1].parse::() { - Ok(v) => v, + // Immediate can default to 0 if not included in instructions + // such as 'ld $t0, ($t1)' + let i_args_catch = if i_args.len() == 2 { + let mut c = i_args.clone(); + c.insert(1, "0"); + c + } else { + i_args + }; + enforce_length(&i_args_catch, 3)?; + rt = assemble_reg(i_args_catch[0])?; + imm = match base_parse(i_args_catch[1]) { + Ok(v) => v as u16, Err(_) => return Err("Failed to parse imm"), }; - rs = assemble_reg(i_args[2])?; + rs = assemble_reg(i_args_catch[2])?; } IForm::RsRtLabel => { enforce_length(&i_args, 3)?; @@ -373,8 +400,8 @@ fn assemble_i( enforce_length(&i_args, 3)?; rt = assemble_reg(i_args[0])?; rs = assemble_reg(i_args[1])?; - imm = match i_args[2].parse::() { - Ok(v) => v, + imm = match base_parse(i_args[2]) { + Ok(v) => v as u16, Err(_) => return Err("Failed to parse imm"), }; } @@ -533,8 +560,8 @@ pub fn assemble(program_arguments: &Args) -> Result<(), String> { if let Ok(instr_info) = r_operation(mnemonic) { println!("-----------------------------------"); println!( - "[R] {} - shamt [{:x}] - funct [{:x}]", - mnemonic, instr_info.shamt, instr_info.funct + "[R] {} - shamt [{:x}] - funct [{:x}] - args [{:?}]", + mnemonic, instr_info.shamt, instr_info.funct, args ); match assemble_r(instr_info, args) { Ok(assembled_r) => { @@ -546,7 +573,10 @@ pub fn assemble(program_arguments: &Args) -> Result<(), String> { } } else if let Ok(instr_info) = i_operation(mnemonic) { println!("-----------------------------------"); - println!("[I] {} - opcode [{:x}]", mnemonic, instr_info.opcode); + println!( + "[I] {} - opcode [{:x}] - args [{:?}]", + mnemonic, instr_info.opcode, args + ); match assemble_i(instr_info, args, &labels, current_addr) { Ok(assembled_i) => { @@ -558,7 +588,10 @@ pub fn assemble(program_arguments: &Args) -> Result<(), String> { } } else if let Ok(instr_info) = j_operation(mnemonic) { println!("-----------------------------------"); - println!("[J] {} - opcode [{:x}]", mnemonic, instr_info.opcode); + println!( + "[J] {} - opcode [{:x}] - args [{:?}]", + mnemonic, instr_info.opcode, args + ); match assemble_j(instr_info, args, &labels) { Ok(assembled_j) => { diff --git a/name-as/src/parser.rs b/name-as/src/parser.rs index 3404f34f..d3eda2dc 100644 --- a/name-as/src/parser.rs +++ b/name-as/src/parser.rs @@ -5,6 +5,10 @@ use pest_derive::Parser; #[grammar_inline = r#" alpha = _{ 'a'..'z' | 'A'..'Z' } digit = _{ '0'..'9' } +hex = _{ "0x" ~ (digit | 'a'..'f' | 'A'..'F')+ } +binary = _{ "0b" ~ ('0'..'1')+ } +decimal = _{ digit+ } +number = { hex | binary | decimal } WHITESPACE = _{ " " | NEWLINE } ident = @{ alpha ~ (alpha | digit)* } @@ -12,11 +16,11 @@ ident = @{ alpha ~ (alpha | digit)* } label = { ident ~ ":" } register = @{ "$" ~ ident } -instruction_arg = @{ ident | register | digit+ } +instruction_arg = @{ ident | register | number } standard_args = _{ instruction_arg ~ ("," ~ WHITESPACE* ~ instruction_arg){, 2} } -mem_access_args = _{ instruction_arg ~ "," ~ instruction_arg ~ "(" ~ instruction_arg ~ ")" } +mem_access_args = _{ instruction_arg ~ "," ~ number? ~ "(" ~ instruction_arg ~ ")" } instruction_args = _{ mem_access_args | standard_args } instruction = { ident ~ instruction_args }