Skip to content

Commit b4c9da9

Browse files
committed
Add tests for currently implemented instructions
1 parent e418601 commit b4c9da9

File tree

2 files changed

+156
-7
lines changed

2 files changed

+156
-7
lines changed

src/assembler/lexer.rs

Lines changed: 155 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
22
assembler::{MaybeUnresolvedInstr, Op, PseudoOp, Token},
3-
defs::LC3Word,
3+
defs::{LC3Word, RegAddr},
44
instruction::{ADD_OPCODE, AND_OPCODE, ALL_JUMP_OPCODES, BRANCH_OPCODE, JSR_OPCODE, ALL_LOAD_OPCODES, ALL_STORE_OPCODES, TRAP_OPCODE, NOT_OPCODE},
55
};
66
use anyhow::{bail, Result};
@@ -26,7 +26,7 @@ pub fn prefix_label_pass(token_chain: &[Token]) -> (Option<&str>, &[Token]) {
2626
/// the asm op. If the line consists only of a comment, then an empty Vec is returned
2727
#[inline]
2828
pub fn construct_instruction_pass(token_chain: &[Token]) -> Result<Vec<MaybeUnresolvedInstr>> {
29-
let result: Vec<MaybeUnresolvedInstr> = Vec::new();
29+
let mut result: Vec<MaybeUnresolvedInstr> = Vec::new();
3030

3131
let operation = &token_chain[0];
3232

@@ -76,6 +76,7 @@ pub fn construct_instruction_pass(token_chain: &[Token]) -> Result<Vec<MaybeUnre
7676
let max_mask = const { 1 << (MAX_OFFSET_LEN + 1) };
7777
if *num < max_mask {
7878
instr.value |= num << SHIFT;
79+
instr.value |= 1 << MAX_OFFSET_LEN;
7980
Ok(())
8081
} else {
8182
bail!("TOO BIG")
@@ -100,27 +101,27 @@ pub fn construct_instruction_pass(token_chain: &[Token]) -> Result<Vec<MaybeUnre
100101
[check_reg::<9>, check_reg::<6>, check_reg_or_offset::<0, 5>].as_slice()),
101102
Op::LD => (
102103
ALL_LOAD_OPCODES[0],
103-
[check_reg::<9>, check_offset::<0, 0>].as_slice()
104+
[check_reg::<9>, check_offset::<0, 9>].as_slice()
104105
),
105106
Op::LDI => (
106107
ALL_LOAD_OPCODES[1],
107-
[check_reg::<9>, check_offset::<0, 0>].as_slice()
108+
[check_reg::<9>, check_offset::<0, 9>].as_slice()
108109
),
109110
Op::LDR => (
110111
ALL_LOAD_OPCODES[2],
111112
[check_reg::<9>, check_reg::<6>, check_offset::<0, 6>].as_slice()
112113
),
113114
Op::LEA => (
114115
ALL_LOAD_OPCODES[3],
115-
[check_reg::<9>, check_offset::<0, 0>].as_slice()
116+
[check_reg::<9>, check_offset::<0, 9>].as_slice()
116117
),
117118
Op::ST => (
118119
ALL_STORE_OPCODES[0],
119-
[check_reg::<9>, check_offset::<0, 0>].as_slice()
120+
[check_reg::<9>, check_offset::<0, 9>].as_slice()
120121
),
121122
Op::STI => (
122123
ALL_STORE_OPCODES[1],
123-
[check_reg::<9>, check_offset::<0, 0>].as_slice()
124+
[check_reg::<9>, check_offset::<0, 9>].as_slice()
124125
),
125126
Op::STR => (
126127
ALL_STORE_OPCODES[2],
@@ -142,6 +143,8 @@ pub fn construct_instruction_pass(token_chain: &[Token]) -> Result<Vec<MaybeUnre
142143
for (process, token) in sequence.iter().zip(&token_chain[1..]) {
143144
process(token, &mut instr)?;
144145
}
146+
147+
result.push(instr);
145148
} else if operation.is_meta() {
146149
todo!()
147150
} else if !operation.is_comment() {
@@ -176,4 +179,149 @@ mod test {
176179
assert_eq!(label.unwrap(), "LABEL1");
177180
assert_eq!(instr[0], Token::INSTR(Op::ILLEGAL));
178181
}
182+
183+
#[test]
184+
fn lex_and_instr() {
185+
let test_vec = vec![
186+
Token::STRING("LABEL1".to_string()),
187+
Token::INSTR(Op::AND),
188+
Token::REGISTER(RegAddr::Zero),
189+
Token::REGISTER(RegAddr::One),
190+
Token::REGISTER(RegAddr::Zero)
191+
];
192+
let (label, instr) = lexer(&test_vec);
193+
194+
assert_eq!(label.unwrap(), "LABEL1");
195+
assert_eq!(instr.unwrap().first().unwrap().value, 0b0101000001000000);
196+
197+
let test_vec = vec![
198+
Token::INSTR(Op::AND),
199+
Token::REGISTER(RegAddr::Three),
200+
Token::REGISTER(RegAddr::One),
201+
Token::NUM(0b10011)
202+
];
203+
let (label, instr) = lexer(&test_vec);
204+
205+
assert_eq!(label, None);
206+
assert_eq!(instr.unwrap().first().unwrap().value, 0b0101011001110011);
207+
}
208+
209+
#[test]
210+
fn lex_add_instr() {
211+
let test_vec = vec![
212+
Token::STRING("LABEL1".to_string()),
213+
Token::INSTR(Op::ADD),
214+
Token::REGISTER(RegAddr::Zero),
215+
Token::REGISTER(RegAddr::One),
216+
Token::REGISTER(RegAddr::Zero)
217+
];
218+
let (label, instr) = lexer(&test_vec);
219+
220+
assert_eq!(label.unwrap(), "LABEL1");
221+
assert_eq!(instr.unwrap().first().unwrap().value, 0b0001000001000000);
222+
223+
let test_vec = vec![
224+
Token::INSTR(Op::ADD),
225+
Token::REGISTER(RegAddr::Three),
226+
Token::REGISTER(RegAddr::One),
227+
Token::NUM(0b10011)
228+
];
229+
let (label, instr) = lexer(&test_vec);
230+
231+
assert_eq!(label, None);
232+
assert_eq!(instr.unwrap().first().unwrap().value, 0b0001011001110011);
233+
}
234+
235+
#[test]
236+
fn lex_load_instrs() {
237+
let test_vec = vec![
238+
Token::INSTR(Op::LD),
239+
Token::REGISTER(RegAddr::Five),
240+
Token::NUM(0b000111000)
241+
];
242+
let (label, instr) = lexer(&test_vec);
243+
244+
assert_eq!(label, None);
245+
assert_eq!(instr.unwrap().first().unwrap().value, 0b0010101000111000);
246+
247+
let test_vec = vec![
248+
Token::INSTR(Op::LDI),
249+
Token::REGISTER(RegAddr::Five),
250+
Token::NUM(0b000111000)
251+
];
252+
let (label, instr) = lexer(&test_vec);
253+
254+
assert_eq!(label, None);
255+
assert_eq!(instr.unwrap().first().unwrap().value, 0b1010101000111000);
256+
257+
let test_vec = vec![
258+
Token::INSTR(Op::LDR),
259+
Token::REGISTER(RegAddr::Five),
260+
Token::REGISTER(RegAddr::Two),
261+
Token::NUM(0b111000)
262+
];
263+
let (label, instr) = lexer(&test_vec);
264+
265+
assert_eq!(label, None);
266+
assert_eq!(instr.unwrap().first().unwrap().value, 0b0110101010111000);
267+
268+
let test_vec = vec![
269+
Token::INSTR(Op::LEA),
270+
Token::REGISTER(RegAddr::Five),
271+
Token::NUM(0b000111000)
272+
];
273+
let (label, instr) = lexer(&test_vec);
274+
275+
assert_eq!(label, None);
276+
assert_eq!(instr.unwrap().first().unwrap().value, 0b1110101000111000);
277+
}
278+
279+
#[test]
280+
fn lex_store_instrs() {
281+
let test_vec = vec![
282+
Token::INSTR(Op::ST),
283+
Token::REGISTER(RegAddr::Five),
284+
Token::NUM(0b000111000)
285+
];
286+
let (label, instr) = lexer(&test_vec);
287+
288+
assert_eq!(label, None);
289+
assert_eq!(instr.unwrap().first().unwrap().value, 0b0011101000111000);
290+
291+
let test_vec = vec![
292+
Token::INSTR(Op::STI),
293+
Token::REGISTER(RegAddr::Five),
294+
Token::NUM(0b000111000)
295+
];
296+
let (label, instr) = lexer(&test_vec);
297+
298+
assert_eq!(label, None);
299+
assert_eq!(instr.unwrap().first().unwrap().value, 0b1011101000111000);
300+
301+
let test_vec = vec![
302+
Token::INSTR(Op::STR),
303+
Token::REGISTER(RegAddr::Five),
304+
Token::REGISTER(RegAddr::Two),
305+
Token::NUM(0b111000)
306+
];
307+
let (label, instr) = lexer(&test_vec);
308+
309+
assert_eq!(label, None);
310+
assert_eq!(instr.unwrap().first().unwrap().value, 0b0111101010111000);
311+
}
312+
313+
#[test]
314+
fn lex_not_instr() {
315+
let test_vec = vec![
316+
Token::INSTR(Op::NOT),
317+
Token::REGISTER(RegAddr::Five),
318+
Token::REGISTER(RegAddr::Zero),
319+
];
320+
let (label, instr) = lexer(&test_vec);
321+
322+
assert_eq!(label, None);
323+
// This is the value that should be produced. Currently this fails, as there is no way to
324+
// insert arbitrary bits into instructions when forming them.
325+
assert_eq!(instr.unwrap().first().unwrap().value, 0b1001101000111111);
326+
}
179327
}

src/assembler/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use strum_macros::EnumDiscriminants;
55
pub mod lexer;
66
pub mod tokenizer;
77

8+
#[derive(Debug, Clone, Eq, PartialEq)]
89
pub struct MaybeUnresolvedInstr {
910
value: LC3Word,
1011
///Label, Start offset, End offset

0 commit comments

Comments
 (0)