@@ -82,11 +82,11 @@ pub fn decode_instruction(encoded_instr: u64) -> Result<Instruction, VirtualMach
82
82
_ => return Err ( VirtualMachineError :: InvalidPcUpdate ( pc_update_num) ) ,
83
83
} ;
84
84
85
- let res = match res_logic_num {
86
- 0 if matches ! ( pc_update , PcUpdate :: Jnz ) => Res :: Unconstrained ,
87
- 0 => Res :: Op1 ,
88
- 1 => Res :: Add ,
89
- 2 => Res :: Mul ,
85
+ let res = match ( res_logic_num, pc_update == PcUpdate :: Jnz ) {
86
+ ( 0 , true ) => Res :: Unconstrained ,
87
+ ( 0 , false ) => Res :: Op1 ,
88
+ ( 1 , false ) => Res :: Add ,
89
+ ( 2 , false ) => Res :: Mul ,
90
90
_ => return Err ( VirtualMachineError :: InvalidRes ( res_logic_num) ) ,
91
91
} ;
92
92
@@ -98,17 +98,38 @@ pub fn decode_instruction(encoded_instr: u64) -> Result<Instruction, VirtualMach
98
98
_ => return Err ( VirtualMachineError :: InvalidOpcode ( opcode_num) ) ,
99
99
} ;
100
100
101
- let ap_update = match ap_update_num {
102
- 0 if matches ! ( opcode , Opcode :: Call ) => ApUpdate :: Add2 ,
103
- 0 => ApUpdate :: Regular ,
104
- 1 => ApUpdate :: Add ,
105
- 2 => ApUpdate :: Add1 ,
101
+ let ap_update = match ( ap_update_num, opcode == Opcode :: Call ) {
102
+ ( 0 , true ) => ApUpdate :: Add2 ,
103
+ ( 0 , false ) => ApUpdate :: Regular ,
104
+ ( 1 , false ) => ApUpdate :: Add ,
105
+ ( 2 , false ) => ApUpdate :: Add1 ,
106
106
_ => return Err ( VirtualMachineError :: InvalidApUpdate ( ap_update_num) ) ,
107
107
} ;
108
108
109
109
let fp_update = match opcode {
110
- Opcode :: Call => FpUpdate :: APPlus2 ,
111
- Opcode :: Ret => FpUpdate :: Dst ,
110
+ Opcode :: Call => {
111
+ if off0 != 0
112
+ || off1 != 1
113
+ || ap_update != ApUpdate :: Add2
114
+ || dst_register != Register :: AP
115
+ || op0_register != Register :: AP
116
+ {
117
+ return Err ( VirtualMachineError :: InvalidOpcode ( opcode_num) ) ;
118
+ } ;
119
+ FpUpdate :: APPlus2
120
+ }
121
+ Opcode :: Ret => {
122
+ if off0 != -2
123
+ || off2 != -1
124
+ || dst_register != Register :: FP
125
+ || op1_addr != Op1Addr :: FP
126
+ || res != Res :: Op1
127
+ || pc_update != PcUpdate :: Jump
128
+ {
129
+ return Err ( VirtualMachineError :: InvalidOpcode ( opcode_num) ) ;
130
+ } ;
131
+ FpUpdate :: Dst
132
+ }
112
133
_ => FpUpdate :: Regular ,
113
134
} ;
114
135
@@ -199,56 +220,56 @@ mod decoder_test {
199
220
200
221
#[ test]
201
222
#[ cfg_attr( target_arch = "wasm32" , wasm_bindgen_test) ]
202
- fn decode_flags_call_add_jmp_add_imm_fp_fp ( ) {
223
+ fn decode_flags_nop_add_jmp_add_imm_fp_fp ( ) {
203
224
// 0| opcode|ap_update|pc_update|res_logic|op1_src|op0_reg|dst_reg
204
225
// 15|14 13 12| 11 10| 9 8 7| 6 5|4 3 2| 1| 0
205
- // | CALL | ADD| JUMP| ADD| IMM| FP| FP
206
- // 0 0 0 1 0 1 0 0 1 0 1 0 0 1 1 1
207
- // 0001 0100 1010 0111 = 0x14A7 ; offx = 0
208
- let inst = decode_instruction ( 0x14A7800080008000 ) . unwrap ( ) ;
226
+ // | NOp | ADD| JUMP| ADD| IMM| FP| FP
227
+ // 0 0 0 0 0 1 0 0 1 0 1 0 0 1 1 1
228
+ // 0000 0100 1010 0111 = 0x04A7 ; offx = 0
229
+ let inst = decode_instruction ( 0x04A7800080008000 ) . unwrap ( ) ;
209
230
assert_matches ! ( inst. dst_register, Register :: FP ) ;
210
231
assert_matches ! ( inst. op0_register, Register :: FP ) ;
211
232
assert_matches ! ( inst. op1_addr, Op1Addr :: Imm ) ;
212
233
assert_matches ! ( inst. res, Res :: Add ) ;
213
234
assert_matches ! ( inst. pc_update, PcUpdate :: Jump ) ;
214
235
assert_matches ! ( inst. ap_update, ApUpdate :: Add ) ;
215
- assert_matches ! ( inst. opcode, Opcode :: Call ) ;
216
- assert_matches ! ( inst. fp_update, FpUpdate :: APPlus2 ) ;
236
+ assert_matches ! ( inst. opcode, Opcode :: NOp ) ;
237
+ assert_matches ! ( inst. fp_update, FpUpdate :: Regular ) ;
217
238
}
218
239
219
240
#[ test]
220
241
#[ cfg_attr( target_arch = "wasm32" , wasm_bindgen_test) ]
221
- fn decode_flags_ret_add1_jmp_rel_mul_fp_ap_ap ( ) {
242
+ fn decode_flags_nop_add1_jmp_rel_mul_fp_ap_ap ( ) {
222
243
// 0| opcode|ap_update|pc_update|res_logic|op1_src|op0_reg|dst_reg
223
244
// 15|14 13 12| 11 10| 9 8 7| 6 5|4 3 2| 1| 0
224
- // | RET | ADD1| JUMP_REL| MUL| FP| AP| AP
225
- // 0 0 1 0 1 0 0 1 0 1 0 0 1 0 0 0
226
- // 0010 1001 0100 1000 = 0x2948 ; offx = 0
227
- let inst = decode_instruction ( 0x2948800080008000 ) . unwrap ( ) ;
245
+ // | NOp | ADD1| JUMP_REL| MUL| FP| AP| AP
246
+ // 0 0 0 0 1 0 0 1 0 1 0 0 1 0 0 0
247
+ // 0000 1001 0100 1000 = 0x0948 ; offx = 0
248
+ let inst = decode_instruction ( 0x0948800080008000 ) . unwrap ( ) ;
228
249
assert_matches ! ( inst. dst_register, Register :: AP ) ;
229
250
assert_matches ! ( inst. op0_register, Register :: AP ) ;
230
251
assert_matches ! ( inst. op1_addr, Op1Addr :: FP ) ;
231
252
assert_matches ! ( inst. res, Res :: Mul ) ;
232
253
assert_matches ! ( inst. pc_update, PcUpdate :: JumpRel ) ;
233
254
assert_matches ! ( inst. ap_update, ApUpdate :: Add1 ) ;
234
- assert_matches ! ( inst. opcode, Opcode :: Ret ) ;
235
- assert_matches ! ( inst. fp_update, FpUpdate :: Dst ) ;
255
+ assert_matches ! ( inst. opcode, Opcode :: NOp ) ;
256
+ assert_matches ! ( inst. fp_update, FpUpdate :: Regular ) ;
236
257
}
237
258
238
259
#[ test]
239
260
#[ cfg_attr( target_arch = "wasm32" , wasm_bindgen_test) ]
240
- fn decode_flags_assrt_add_jnz_mul_ap_ap_ap ( ) {
261
+ fn decode_flags_assrt_add_regular_mul_ap_ap_ap ( ) {
241
262
// 0| opcode|ap_update|pc_update|res_logic|op1_src|op0_reg|dst_reg
242
263
// 15|14 13 12| 11 10| 9 8 7| 6 5|4 3 2| 1| 0
243
- // |ASSRT_EQ| ADD| JNZ | MUL| AP| AP| AP
244
- // 0 1 0 0 1 0 1 0 0 1 0 1 0 0 0 0
245
- // 0100 1010 0101 0000 = 0x4A50 ; offx = 0
246
- let inst = decode_instruction ( 0x4A50800080008000 ) . unwrap ( ) ;
264
+ // |ASSRT_EQ| ADD| REGULAR | MUL| AP| AP| AP
265
+ // 0 1 0 0 1 0 0 0 0 1 0 1 0 0 0 0
266
+ // 0100 1000 0101 0000 = 0x4850 ; offx = 0
267
+ let inst = decode_instruction ( 0x4850800080008000 ) . unwrap ( ) ;
247
268
assert_matches ! ( inst. dst_register, Register :: AP ) ;
248
269
assert_matches ! ( inst. op0_register, Register :: AP ) ;
249
270
assert_matches ! ( inst. op1_addr, Op1Addr :: AP ) ;
250
271
assert_matches ! ( inst. res, Res :: Mul ) ;
251
- assert_matches ! ( inst. pc_update, PcUpdate :: Jnz ) ;
272
+ assert_matches ! ( inst. pc_update, PcUpdate :: Regular ) ;
252
273
assert_matches ! ( inst. ap_update, ApUpdate :: Add1 ) ;
253
274
assert_matches ! ( inst. opcode, Opcode :: AssertEq ) ;
254
275
assert_matches ! ( inst. fp_update, FpUpdate :: Regular ) ;
@@ -305,4 +326,70 @@ mod decoder_test {
305
326
assert_eq ! ( inst. off1, 0 ) ;
306
327
assert_eq ! ( inst. off2, 1 ) ;
307
328
}
329
+
330
+ #[ test]
331
+ #[ cfg_attr( target_arch = "wasm32" , wasm_bindgen_test) ]
332
+ fn decode_ret_cairo_standard ( ) {
333
+ // 0| opcode|ap_update|pc_update|res_logic|op1_src|op0_reg|dst_reg
334
+ // 15|14 13 12| 11 10| 9 8 7| 6 5|4 3 2| 1| 0
335
+ // | RET| REGULAR| JUMP| Op1| FP| FP| FP
336
+ // 0 0 1 0 0 0 0 0 1 0 0 0 1 0 1 1
337
+ // 0010 0000 1000 1011 = 0x208b; off0 = -2, off1 = -1
338
+ let inst = decode_instruction ( 0x208b7fff7fff7ffe ) . unwrap ( ) ;
339
+ assert_matches ! ( inst. opcode, Opcode :: Ret ) ;
340
+ assert_matches ! ( inst. off0, -2 ) ;
341
+ assert_matches ! ( inst. off1, -1 ) ;
342
+ assert_matches ! ( inst. dst_register, Register :: FP ) ;
343
+ assert_matches ! ( inst. op0_register, Register :: FP ) ;
344
+ assert_matches ! ( inst. op1_addr, Op1Addr :: FP ) ;
345
+ assert_matches ! ( inst. res, Res :: Op1 ) ;
346
+ assert_matches ! ( inst. pc_update, PcUpdate :: Jump ) ;
347
+ assert_matches ! ( inst. ap_update, ApUpdate :: Regular ) ;
348
+ assert_matches ! ( inst. fp_update, FpUpdate :: Dst ) ;
349
+ }
350
+
351
+ #[ test]
352
+ #[ cfg_attr( target_arch = "wasm32" , wasm_bindgen_test) ]
353
+ fn decode_call_cairo_standard ( ) {
354
+ // 0| opcode|ap_update|pc_update|res_logic|op1_src|op0_reg|dst_reg
355
+ // 15|14 13 12| 11 10| 9 8 7| 6 5|4 3 2| 1| 0
356
+ // | CALL| Add2| JumpRel| Op1| FP| FP| FP
357
+ // 0 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0
358
+ // 0001 0001 0000 0100 = 0x208b; off0 = 0, off1 = 1
359
+ let inst = decode_instruction ( 0x1104800180018000 ) . unwrap ( ) ;
360
+ assert_matches ! ( inst. opcode, Opcode :: Call ) ;
361
+ assert_matches ! ( inst. off0, 0 ) ;
362
+ assert_matches ! ( inst. off1, 1 ) ;
363
+ assert_matches ! ( inst. dst_register, Register :: AP ) ;
364
+ assert_matches ! ( inst. op0_register, Register :: AP ) ;
365
+ assert_matches ! ( inst. op1_addr, Op1Addr :: Imm ) ;
366
+ assert_matches ! ( inst. res, Res :: Op1 ) ;
367
+ assert_matches ! ( inst. pc_update, PcUpdate :: JumpRel ) ;
368
+ assert_matches ! ( inst. ap_update, ApUpdate :: Add2 ) ;
369
+ assert_matches ! ( inst. fp_update, FpUpdate :: APPlus2 ) ;
370
+ }
371
+
372
+ #[ test]
373
+ #[ cfg_attr( target_arch = "wasm32" , wasm_bindgen_test) ]
374
+ fn decode_ret_opcode_error ( ) {
375
+ // 0| opcode|ap_update|pc_update|res_logic|op1_src|op0_reg|dst_reg
376
+ // 15|14 13 12| 11 10| 9 8 7| 6 5|4 3 2| 1| 0
377
+ // | RET| REGULAR| JUMP| Op1| FP| FP| FP
378
+ // 0 0 1 0 0 0 0 0 1 0 0 0 1 0 1 1
379
+ // 0010 0000 1000 1011 = 0x208b; off0 = -1, off1 = -1
380
+ let error = decode_instruction ( 0x208b7fff7fff7fff ) ;
381
+ assert_matches ! ( error, Err ( VirtualMachineError :: InvalidOpcode ( 2 ) ) ) ;
382
+ }
383
+
384
+ #[ test]
385
+ #[ cfg_attr( target_arch = "wasm32" , wasm_bindgen_test) ]
386
+ fn decode_call_opcode_error ( ) {
387
+ // 0| opcode|ap_update|pc_update|res_logic|op1_src|op0_reg|dst_reg
388
+ // 15|14 13 12| 11 10| 9 8 7| 6 5|4 3 2| 1| 0
389
+ // | CALL| Add2| JumpRel| Op1| FP| FP| FP
390
+ // 0 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0
391
+ // 0001 0001 0000 0100 = 0x208b; off0 = 1, off1 = 1
392
+ let error = decode_instruction ( 0x1104800180018001 ) ;
393
+ assert_matches ! ( error, Err ( VirtualMachineError :: InvalidOpcode ( 1 ) ) ) ;
394
+ }
308
395
}
0 commit comments