@@ -63,111 +63,124 @@ fn pseudo_ops() {
63
63
) ;
64
64
}
65
65
66
- #[ test]
67
- fn add ( ) {
68
- single_instruction_tests ( & [
69
- ( "ADD R0 R0 R0" , 0x1000 ) ,
70
- ( "ADD R1 R2 R3" , 0x1283 ) ,
71
- ( "ADD R4 R5 R6" , 0x1946 ) ,
72
- ( "ADD R7 R7 #0" , 0x1FE0 ) ,
73
- ( "ADD R7 R7 #1" , 0x1FE1 ) ,
74
- ( "ADD R7 R7 #15" , 0x1FEF ) ,
75
- ( "ADD R7 R7 #-1" , 0x1FFF ) ,
76
- ] ) ;
77
- }
66
+ mod single_instruction {
67
+ use super :: * ;
78
68
79
- #[ test]
80
- fn and ( ) {
81
- single_instruction_tests ( & [
82
- ( "AND R0 R0 R0" , 0x5000 ) ,
83
- ( "AND R1 R2 R3" , 0x5283 ) ,
84
- ( "AND R4 R5 R6" , 0x5946 ) ,
85
- ( "AND R7 R7 #0" , 0x5FE0 ) ,
86
- ( "AND R7 R7 #1" , 0x5FE1 ) ,
87
- ( "AND R7 R7 #15" , 0x5FEF ) ,
88
- ( "AND R7 R7 #-1" , 0x5FFF ) ,
89
- ] ) ;
90
- }
69
+ fn single_instruction_test ( input : & str , expected : Word ) {
70
+ let input = format ! ( ".ORIG x3000\n {}\n .END" , input) ;
71
+ test ( input. as_str ( ) , 0x3000 , & [ expected] ) ;
72
+ }
91
73
92
- #[ test]
93
- fn jmp ( ) {
94
- single_instruction_tests ( & [
95
- ( "JMP R0" , 0xC000 ) ,
96
- ( "JMP R1" , 0xC040 ) ,
97
- ( "JMP R2" , 0xC080 ) ,
98
- ( "JMP R3" , 0xC0C0 ) ,
99
- ( "JMP R4" , 0xC100 ) ,
100
- ( "JMP R5" , 0xC140 ) ,
101
- ( "JMP R6" , 0xC180 ) ,
102
- ( "JMP R7" , 0xC1C0 ) ,
103
- ] )
104
- }
74
+ macro_rules! single_instruction_tests {
75
+ ( $tests_name: ident
76
+ $(
77
+ $test_name: ident: $instruction: expr => $expected: expr
78
+ ) ,+
79
+ $( , ) *
80
+ ) => {
81
+ mod $tests_name {
82
+ use super :: * ;
83
+
84
+ $(
85
+ #[ test]
86
+ fn $test_name( ) {
87
+ single_instruction_test( $instruction, $expected) ;
88
+ }
89
+ ) +
90
+ }
91
+ } ;
92
+ }
105
93
106
- #[ test]
107
- fn jsrr ( ) {
108
- single_instruction_tests ( & [
109
- ( "JSRR R0" , 0x4000 ) ,
110
- ( "JSRR R1" , 0x4040 ) ,
111
- ( "JSRR R2" , 0x4080 ) ,
112
- ( "JSRR R3" , 0x40C0 ) ,
113
- ( "JSRR R4" , 0x4100 ) ,
114
- ( "JSRR R5" , 0x4140 ) ,
115
- ( "JSRR R6" , 0x4180 ) ,
116
- ( "JSRR R7" , 0x41C0 ) ,
117
- ] )
118
- }
94
+ single_instruction_tests ! { add
95
+ minimal: "ADD R0 R0 R0" => 0x1000 ,
96
+ r1_2_3: "ADD R1 R2 R3" => 0x1283 ,
97
+ r4_5_6: "ADD R4 R5 R6" => 0x1946 ,
98
+ r7_imm: "ADD R7 R7 #0" => 0x1FE0 ,
99
+ nonzero_imm: "ADD R7 R7 #1" => 0x1FE1 ,
100
+ max_imm: "ADD R7 R7 #15" => 0x1FEF ,
101
+ neg_imm: "ADD R7 R7 #-1" => 0x1FFF ,
102
+ }
119
103
120
- #[ test]
121
- fn rti ( ) {
122
- single_instruction_test ( "RTI" , 0x8000 ) ;
123
- }
104
+ single_instruction_tests ! { and
105
+ minimal: "AND R0 R0 R0" => 0x5000 ,
106
+ r1_2_3: "AND R1 R2 R3" => 0x5283 ,
107
+ r4_5_6: "AND R4 R5 R6" => 0x5946 ,
108
+ r7_imm: "AND R7 R7 #0" => 0x5FE0 ,
109
+ nonzero_imm: "AND R7 R7 #1" => 0x5FE1 ,
110
+ max_imm: "AND R7 R7 #15" => 0x5FEF ,
111
+ neg_imm: "AND R7 R7 #-1" => 0x5FFF ,
112
+ }
124
113
125
- #[ test]
126
- fn ret ( ) {
127
- single_instruction_test ( "RET" , 0xC1C0 ) ;
128
- }
114
+ single_instruction_tests ! { jmp
115
+ r0: "JMP R0" => 0xC000 ,
116
+ r1: "JMP R1" => 0xC040 ,
117
+ r2: "JMP R2" => 0xC080 ,
118
+ r3: "JMP R3" => 0xC0C0 ,
119
+ r4: "JMP R4" => 0xC100 ,
120
+ r5: "JMP R5" => 0xC140 ,
121
+ r6: "JMP R6" => 0xC180 ,
122
+ r7: "JMP R7" => 0xC1C0 ,
123
+ }
129
124
130
- # [ test ]
131
- fn ldr ( ) {
132
- single_instruction_tests ( & [
133
- ( "LDR R0 R0 #0" , 0x6000 ) ,
134
- ( "LDR R1 R2 #3" , 0x6283 ) ,
135
- ( "LDR R3 R4 #31" , 0x671F ) ,
136
- ( "LDR R5 R6 #-1" , 0x6BBF ) ,
137
- ( "LDR R7 R7 #-32" , 0x6FE0 ) ,
138
- ] )
139
- }
125
+ single_instruction_tests ! { jsrr
126
+ r0 : "JSRR R0" => 0x4000 ,
127
+ r1 : "JSRR R1" => 0x4040 ,
128
+ r2 : "JSRR R2" => 0x4080 ,
129
+ r3 : "JSRR R3" => 0x40C0 ,
130
+ r4 : "JSRR R4" => 0x4100 ,
131
+ r5 : "JSRR R5" => 0x4140 ,
132
+ r6 : "JSRR R6" => 0x4180 ,
133
+ r7 : "JSRR R7" => 0x41C0 ,
134
+ }
140
135
141
- #[ test]
142
- fn not ( ) {
143
- single_instruction_tests ( & [
144
- ( "NOT R0 R1" , 0x907F ) ,
145
- ( "NOT R2 R3" , 0x94FF ) ,
146
- ( "NOT R4 R5" , 0x997F ) ,
147
- ( "NOT R6 R7" , 0x9DFF ) ,
148
- ] )
149
- }
136
+ #[ test]
137
+ fn rti ( ) {
138
+ single_instruction_test ( "RTI" , 0x8000 ) ;
139
+ }
150
140
151
- #[ test]
152
- fn str ( ) {
153
- single_instruction_tests ( & [
154
- ( "STR R0 R0 #0" , 0x7000 ) ,
155
- ( "STR R1 R2 #3" , 0x7283 ) ,
156
- ( "STR R3 R4 #31" , 0x771F ) ,
157
- ( "STR R5 R6 #-1" , 0x7BBF ) ,
158
- ( "STR R7 R7 #-32" , 0x7FE0 ) ,
159
- ] )
160
- }
141
+ #[ test]
142
+ fn ret ( ) {
143
+ single_instruction_test ( "RET" , 0xC1C0 ) ;
144
+ }
161
145
162
- #[ test]
163
- fn trap ( ) {
164
- single_instruction_tests ( & [
165
- ( "TRAP x00" , 0xF000 ) ,
166
- ( "TRAP x25" , 0xF025 ) ,
167
- ( "TRAP xFF" , 0xF0FF ) ,
168
- ( "TRAP #37" , 0xF025 ) ,
169
- ] )
170
- }
146
+ single_instruction_tests ! { ldr
147
+ minimal: "LDR R0 R0 #0" => 0x6000 ,
148
+ r1_2: "LDR R1 R2 #3" => 0x6283 ,
149
+ max_imm: "LDR R3 R4 #31" => 0x671F ,
150
+ neg_imm: "LDR R5 R6 #-1" => 0x6BBF ,
151
+ min_imm: "LDR R7 R7 #-32" => 0x6FE0 ,
152
+ }
153
+
154
+ single_instruction_tests ! { not
155
+ r0_1: "NOT R0 R1" => 0x907F ,
156
+ r2_3: "NOT R2 R3" => 0x94FF ,
157
+ r4_5: "NOT R4 R5" => 0x997F ,
158
+ r6_7: "NOT R6 R7" => 0x9DFF ,
159
+ }
160
+
161
+ single_instruction_tests ! { str
162
+ minimal: "STR R0 R0 #0" => 0x7000 ,
163
+ r1_2: "STR R1 R2 #3" => 0x7283 ,
164
+ max_imm: "STR R3 R4 #31" => 0x771F ,
165
+ neg_imm: "STR R5 R6 #-1" => 0x7BBF ,
166
+ min_imm: "STR R7 R7 #-32" => 0x7FE0 ,
167
+ }
168
+
169
+ single_instruction_tests ! { trap
170
+ minimal: "TRAP x00" => 0xF000 ,
171
+ halt: "TRAP x25" => 0xF025 ,
172
+ max: "TRAP xFF" => 0xF0FF ,
173
+ decimal: "TRAP #37" => 0xF025 ,
174
+ }
175
+
176
+ single_instruction_tests ! { named_traps
177
+ getc: "GETC" => 0xF020 ,
178
+ out: "OUT" => 0xF021 ,
179
+ puts: "PUTS" => 0xF022 ,
180
+ in_: "IN" => 0xF023 ,
181
+ putsp: "PUTSP" => 0xF024 ,
182
+ halt: "HALT" => 0xF025 ,
183
+ }
171
184
172
185
// TODO: BR
173
186
// TODO: JSR
@@ -176,9 +189,10 @@ fn trap() {
176
189
// TODO: ST
177
190
// TODO: STI
178
191
// TODO: LEA
179
- // TODO: Named TRAPs
180
192
// TODO: Pseudo-ops
181
193
194
+ }
195
+
182
196
fn test ( input : & str , orig : usize , expected_mem : & [ Word ] ) {
183
197
let lexer = Lexer :: new ( input) ;
184
198
let cst = parse ( lexer, Lenient ) ;
@@ -195,18 +209,6 @@ fn test(input: &str, orig: usize, expected_mem: &[Word]) {
195
209
}
196
210
}
197
211
198
- fn single_instruction_tests ( tests : & [ ( & str , Word ) ] ) {
199
- for ( input, expected) in tests {
200
- single_instruction_test ( input, * expected) ;
201
- }
202
- }
203
-
204
- fn single_instruction_test ( input : & str , expected : Word ) {
205
- let input = format ! ( ".ORIG x3000\n {}\n .END" , input) ;
206
- test ( input. as_str ( ) , 0x3000 , & [ expected] ) ;
207
- }
208
-
209
-
210
212
fn assert_mem ( mem : & MemoryDump , location : usize , expected : Word ) {
211
213
let actual = mem[ location] ;
212
214
assert_eq ! ( expected, actual, "differed at {:#x}: expected {:#x}, was {:#x}" , location, expected, actual) ;
0 commit comments