Skip to content

Commit 7f5b14d

Browse files
Implement opcode modifier table
1 parent 7c57a7f commit 7f5b14d

File tree

4 files changed

+59
-8
lines changed

4 files changed

+59
-8
lines changed

src/data/redcode.pest

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Line = { Instruction? ~ NEWLINE }
88

99
Instruction = _{ Operation ~ Field ~ ("," ~ Field)? }
1010

11-
Operation = ${ Opcode }
11+
Operation = ${ Opcode ~ ("." ~ Modifier)? }
1212

1313
Field = !{ AddressMode? ~ Expr }
1414

@@ -18,7 +18,7 @@ Opcode = {
1818
^"SLT" | ^"SPL" | ^"NOP" | ^"ORG" | ^"EQU" | ^"END"
1919
}
2020

21-
Modifier = { ^"A" | ^"B" | ^"AB" | ^"BA" | ^"F" | ^"X" | ^"I" }
21+
Modifier = { ^"AB" | ^"BA" | ^"A" | ^"B" | ^"F" | ^"X" | ^"I" }
2222

2323
AddressMode = { "#" | "$" | "*" | "@" | "{" | "<" | "}" | ">" }
2424

src/load_file.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,46 @@ enum_string!(pub PseudoOpcode, {
3434
End => "END",
3535
});
3636

37+
enum_string!(pub Modifier, {
38+
A => "A",
39+
B => "B",
40+
AB => "AB",
41+
BA => "BA",
42+
F => "F",
43+
X => "X",
44+
I => "I",
45+
});
46+
47+
impl Default for Modifier {
48+
fn default() -> Modifier {
49+
Modifier::F
50+
}
51+
}
52+
53+
impl Modifier {
54+
pub fn from_context(opcode: Opcode, a_mode: AddressMode, b_mode: AddressMode) -> Modifier {
55+
use Opcode::*;
56+
57+
match opcode {
58+
Dat => Modifier::F,
59+
Jmp | Jmz | Jmn | Djn | Spl | Nop => Modifier::B,
60+
opcode => {
61+
if a_mode == AddressMode::Immediate {
62+
Modifier::AB
63+
} else if b_mode == AddressMode::Immediate {
64+
Modifier::B
65+
} else {
66+
match opcode {
67+
Mov | Cmp | Seq | Sne => Modifier::I,
68+
Slt => Modifier::B,
69+
Add | Sub | Mul | Div | Mod => Modifier::F,
70+
}
71+
}
72+
}
73+
}
74+
}
75+
}
76+
3777
enum_string!(pub AddressMode, {
3878
Immediate => "#",
3979
Direct => "$",
@@ -82,14 +122,17 @@ impl ToString for Field {
82122
#[derive(Copy, Clone, Default, Debug, PartialEq)]
83123
pub struct Instruction {
84124
pub opcode: Opcode,
125+
pub modifier: Modifier,
85126
pub field_a: Field,
86127
pub field_b: Field,
87128
}
88129

89130
impl Instruction {
90131
pub fn new(opcode: Opcode, field_a: Field, field_b: Field) -> Instruction {
132+
let modifier = Modifier::from_context(opcode, field_a.address_mode, field_b.address_mode);
91133
Instruction {
92134
opcode,
135+
modifier,
93136
field_a,
94137
field_b,
95138
}
@@ -177,6 +220,7 @@ mod tests {
177220
fn default_instruction() {
178221
let expected_instruction = Instruction {
179222
opcode: Opcode::Dat,
223+
modifier: Modifier::F,
180224
field_a: Field {
181225
address_mode: AddressMode::Direct,
182226
value: 0,

src/parser.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use pest::{
66
Parser,
77
};
88

9-
use crate::load_file::{AddressMode, Core, Field, Instruction, Opcode};
9+
use crate::load_file::{AddressMode, Core, Field, Instruction, Modifier, Opcode};
1010

1111
pub struct Error {
1212
details: String,
@@ -72,6 +72,11 @@ fn parse_instruction(mut instruction_pairs: Pairs<Rule>) -> Instruction {
7272
.expect("Opcode must be first pair in Instruction"),
7373
);
7474

75+
let maybe_modifier = instruction_pairs
76+
.peek()
77+
.filter(|pair| pair.as_rule() == Rule::Modifier)
78+
.map(|pair| Modifier::from_str(pair.as_str()).expect("Invalid Modifier"));
79+
7580
let field_a = parse_field(
7681
instruction_pairs
7782
.next()
@@ -83,8 +88,13 @@ fn parse_instruction(mut instruction_pairs: Pairs<Rule>) -> Instruction {
8388
.filter(|pair| pair.as_rule() == Rule::Field)
8489
.map_or_else(Field::default, parse_field);
8590

91+
let modifier = maybe_modifier.unwrap_or_else(|| {
92+
Modifier::from_context(opcode, field_a.address_mode, field_b.address_mode)
93+
});
94+
8695
Instruction {
8796
opcode,
97+
modifier,
8898
field_a,
8999
field_b,
90100
}
@@ -95,8 +105,6 @@ fn parse_opcode(opcode_pair: &Pair<Rule>) -> Opcode {
95105
}
96106

97107
fn parse_field(field_pair: Pair<Rule>) -> Field {
98-
dbg!(&field_pair);
99-
100108
let field_pairs = field_pair.into_inner();
101109

102110
let address_mode = field_pairs
@@ -183,7 +191,6 @@ mod tests {
183191
]
184192
.iter()
185193
{
186-
dbg!(test_input);
187194
parses_to! {
188195
parser: RedcodeParser,
189196
input: test_input,

src/util.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ macro_rules! enum_string {
2020

2121
impl std::string::ToString for $name {
2222
fn to_string(&self) -> String {
23-
use self::$name::*;
23+
use $name::*;
2424
match *self {
2525
$($variant => $value,)*
2626
}.to_owned()
@@ -30,7 +30,7 @@ macro_rules! enum_string {
3030
impl std::str::FromStr for $name {
3131
type Err = String;
3232
fn from_str(input_str: &str) -> Result<Self, Self::Err> {
33-
use self::$name::*;
33+
use $name::*;
3434
match input_str {
3535
$($value => Ok($variant),)*
3636
_ => Err(format!(

0 commit comments

Comments
 (0)