forked from utdscheld/name
-
Notifications
You must be signed in to change notification settings - Fork 0
/
assemble_instruction.rs
112 lines (99 loc) · 4.09 KB
/
assemble_instruction.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use crate::assembler::assembly_helpers::{
arg_configuration_is_ok, translate_identifier_to_address,
};
use crate::assembler::assembly_utils::*;
use crate::definitions::structs::LineComponent;
use name_core::instruction::information::{ArgumentType, InstructionInformation, InstructionType};
use name_core::structs::Symbol;
// Big logic for instruction assembly - this is the main driver code for actual packing of instructions once parsed.
pub fn assemble_instruction(
info: &InstructionInformation,
arguments: &Vec<LineComponent>,
symbol_table: &Vec<Symbol>,
current_address: &u32,
) -> Result<Option<u32>, String> {
let has_alternate_configurations: bool = info.alt_args.is_some();
// Find proper argument configuration early
let configuration_to_use: &[ArgumentType];
let existing_configuration_works: bool = arg_configuration_is_ok(arguments, info.args);
if !has_alternate_configurations {
if !existing_configuration_works {
return Err(format!(" - Bad arguments provided during operand checks."));
} else {
configuration_to_use = info.args;
}
} else if !existing_configuration_works {
let found_configuration = info
.alt_args
.unwrap()
.iter()
.find(|config| arg_configuration_is_ok(arguments, config));
match found_configuration {
Some(configuration) => configuration_to_use = configuration,
None => return Err(" - Bad arguments provided; Alternative argument configurations exist, but none matched.".to_string()),
}
} else {
configuration_to_use = info.args;
}
match info.instruction_type {
InstructionType::RType => {
let funct: u32 = info.funct_code.expect("Improper implmentation of instructions (funct field undefined for R-type instr)\nIf you are a student reading this, understand this error comes entirely from a fundamental failure in the codebase of this vscode extension.") as u32;
let (rd, rs, rt, shamt) = match assign_r_type_arguments(arguments, configuration_to_use)
{
Ok((rd, rs, rt, shamt)) => (rd, rs, rt, shamt),
Err(e) => return Err(e),
};
match assemble_r_type(rd, rs, rt, shamt, funct) {
Ok(packed_instr) => {
return Ok(Some(packed_instr));
}
Err(e) => {
return Err(e);
}
}
}
InstructionType::IType => {
let opcode: u32 = info.op_code as u32;
let (rs, rt, imm) = match assign_i_type_arguments(
arguments,
configuration_to_use,
symbol_table,
current_address,
) {
Ok((rs, rt, imm)) => (rs, rt, imm),
Err(e) => return Err(e),
};
if imm.is_none() && configuration_to_use.contains(&ArgumentType::BranchLabel) {
return Ok(None);
}
match assemble_i_type(opcode, rs, rt, imm) {
Ok(packed_instr) => {
return Ok(Some(packed_instr));
}
Err(e) => {
return Err(e);
}
}
}
InstructionType::JType => {
let opcode: u32 = info.op_code as u32;
let identifier = match assign_j_type_arguments(arguments, configuration_to_use) {
Ok(identifier) => identifier,
Err(e) => return Err(e),
};
let address = match translate_identifier_to_address(&identifier, symbol_table) {
Some(addr) => addr >> 2,
None => return Ok(None), // Unresolved symbol (forward reference)
};
let assembled_output = assemble_j_type(opcode, Some(address));
match assembled_output {
Ok(_) => {
return assembled_output;
}
Err(e) => {
return Err(e);
}
}
}
}
}