@@ -35,13 +35,13 @@ enum_string!(pub PseudoOpcode, {
35
35
} ) ;
36
36
37
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" ,
38
+ A => "A" ,
39
+ B => "B" ,
40
+ AB => "AB" ,
41
+ BA => "BA" ,
42
+ F => "F" ,
43
+ X => "X" ,
44
+ I => "I" ,
45
45
} ) ;
46
46
47
47
impl Default for Modifier {
@@ -52,6 +52,8 @@ impl Default for Modifier {
52
52
53
53
impl Modifier {
54
54
pub fn from_context ( opcode : Opcode , a_mode : AddressMode , b_mode : AddressMode ) -> Modifier {
55
+ /// Implemented based on the ICWS '94 document,
56
+ /// section A.2.1.2: ICWS'88 to ICWS'94 Conversion
55
57
use Opcode :: * ;
56
58
57
59
match opcode {
@@ -67,6 +69,7 @@ impl Modifier {
67
69
Mov | Cmp | Seq | Sne => Modifier :: I ,
68
70
Slt => Modifier :: B ,
69
71
Add | Sub | Mul | Div | Mod => Modifier :: F ,
72
+ _ => unreachable ! ( ) ,
70
73
}
71
74
}
72
75
}
@@ -75,14 +78,14 @@ impl Modifier {
75
78
}
76
79
77
80
enum_string ! ( pub AddressMode , {
78
- Immediate => "#" ,
79
- Direct => "$" ,
80
- IndirectA => "*" ,
81
- IndirectB => "@" ,
82
- PreDecIndirectA => "{" ,
83
- PreDecIndirectB => "<" ,
84
- PostIncIndirectA => "}" ,
85
- PostIncIndirectB => ">" ,
81
+ Immediate => "#" ,
82
+ Direct => "$" ,
83
+ IndirectA => "*" ,
84
+ IndirectB => "@" ,
85
+ PreDecIndirectA => "{" ,
86
+ PreDecIndirectB => "<" ,
87
+ PostIncIndirectA => "}" ,
88
+ PostIncIndirectB => ">" ,
86
89
} ) ;
87
90
88
91
impl Default for AddressMode {
@@ -214,8 +217,20 @@ impl PartialEq for Core {
214
217
215
218
#[ cfg( test) ]
216
219
mod tests {
220
+ use itertools:: iproduct;
221
+ use lazy_static:: lazy_static;
222
+
223
+ use std:: str:: FromStr ;
224
+
217
225
use super :: * ;
218
226
227
+ lazy_static ! {
228
+ static ref all_modes: vec:: Vec <AddressMode > = [ "#" , "$" , "@" , "<" , ">" , "*" , "{" , "}" ]
229
+ . iter( )
230
+ . map( |mode_str| AddressMode :: from_str( mode_str) . unwrap( ) )
231
+ . collect( ) ;
232
+ }
233
+
219
234
#[ test]
220
235
fn default_instruction ( ) {
221
236
let expected_instruction = Instruction {
@@ -233,4 +248,61 @@ mod tests {
233
248
234
249
assert_eq ! ( Instruction :: default ( ) , expected_instruction)
235
250
}
251
+
252
+ #[ test]
253
+ fn dat_from_context ( ) {
254
+ for ( & a_mode, & b_mode) in iproduct ! ( all_modes. iter( ) , all_modes. iter( ) ) {
255
+ assert_eq ! (
256
+ Modifier :: from_context( Opcode :: Dat , a_mode, b_mode) ,
257
+ Modifier :: F
258
+ ) ;
259
+ }
260
+ }
261
+
262
+ #[ test]
263
+ fn modifier_b_from_context ( ) {
264
+ use Opcode :: * ;
265
+
266
+ let opcodes = [ Jmp , Jmz , Jmn , Djn , Spl , Nop ] ;
267
+
268
+ for ( & a_mode, & b_mode) in iproduct ! ( all_modes. iter( ) , all_modes. iter( ) ) {
269
+ for & opcode in opcodes. iter ( ) {
270
+ assert_eq ! ( Modifier :: from_context( opcode, a_mode, b_mode) , Modifier :: B ) ;
271
+ }
272
+ }
273
+
274
+ let a_modes: vec:: Vec < AddressMode > = [ "$" , "@" , "<" , ">" , "*" , "{" , "}" ]
275
+ . iter ( )
276
+ . map ( |mode_str| AddressMode :: from_str ( mode_str) . unwrap ( ) )
277
+ . collect ( ) ;
278
+
279
+ for & a_mode in a_modes. iter ( ) {
280
+ for & b_mode in all_modes. iter ( ) {
281
+ assert_eq ! (
282
+ Modifier :: from_context( Opcode :: Slt , a_mode, b_mode) ,
283
+ Modifier :: B
284
+ )
285
+ }
286
+ }
287
+
288
+ // TODO Mov, Cmp. Seq, Sne -> B
289
+ }
290
+
291
+ #[ test]
292
+ fn modifier_ab_from_context ( ) {
293
+ use Opcode :: * ;
294
+
295
+ let opcodes = [ Mov , Cmp , Seq , Sne , Add , Sub , Mul , Div , Mod , Slt ] ;
296
+
297
+ for & b_mode in all_modes. iter ( ) {
298
+ for & opcode in opcodes. iter ( ) {
299
+ assert_eq ! (
300
+ Modifier :: from_context( opcode, AddressMode :: Immediate , b_mode) ,
301
+ Modifier :: AB
302
+ ) ;
303
+ }
304
+ }
305
+ }
306
+
307
+ // TODO Mode I
236
308
}
0 commit comments