@@ -183,6 +183,16 @@ impl X86Opnd {
183
183
_ => 0
184
184
}
185
185
}
186
+
187
+ pub fn num_bits ( & self ) -> u8 {
188
+ match self {
189
+ X86Opnd :: Reg ( reg) => reg. num_bits ,
190
+ X86Opnd :: Imm ( imm) => imm. num_bits ,
191
+ X86Opnd :: UImm ( uimm) => uimm. num_bits ,
192
+ X86Opnd :: Mem ( mem) => mem. num_bits ,
193
+ _ => unreachable ! ( )
194
+ }
195
+ }
186
196
}
187
197
188
198
// Instruction pointer
@@ -524,8 +534,6 @@ impl CodeBlock
524
534
525
535
/// Allocate a new label with a given name
526
536
pub fn new_label ( & mut self , name : String ) -> usize {
527
- // assert (cb->num_labels < MAX_LABELS);
528
-
529
537
// This label doesn't have an address yet
530
538
self . label_addrs . push ( 0 ) ;
531
539
self . label_names . push ( name) ;
@@ -559,10 +567,10 @@ impl CodeBlock
559
567
let ref_pos = label_ref. pos ;
560
568
let label_idx = label_ref. label_idx ;
561
569
assert ! ( ref_pos < self . mem_size) ;
562
- // assert (label_idx < MAX_LABELS);
563
570
564
571
let label_addr = self . label_addrs [ label_idx] ;
565
572
assert ! ( label_addr < self . mem_size) ;
573
+
566
574
// Compute the offset from the reference's end to the label
567
575
let offset = ( label_addr as i64 ) - ( ( ref_pos + 4 ) as i64 ) ;
568
576
@@ -709,10 +717,10 @@ fn write_rm(cb: &mut CodeBlock, sz_pref: bool, rex_w: bool, r_opnd: X86Opnd, rm_
709
717
// MODRM.reg (3 bits)
710
718
// MODRM.rm (3 bits)
711
719
712
- // assert (
713
- // !(opExt != 0xFF && r_opnd.type != OPND_NONE) &&
714
- // "opcode extension and register operand present"
715
- // );
720
+ assert ! (
721
+ ! ( op_ext != 0xff && !matches! ( r_opnd, X86Opnd :: None ) ) ,
722
+ "opcode extension and register operand present"
723
+ ) ;
716
724
717
725
// Encode the mod field
718
726
let rm_mod = match rm_opnd {
@@ -787,12 +795,9 @@ fn write_rm(cb: &mut CodeBlock, sz_pref: bool, rex_w: bool, r_opnd: X86Opnd, rm_
787
795
788
796
// Encode a mul-like single-operand RM instruction
789
797
fn write_rm_unary ( cb: & mut CodeBlock , op_mem_reg_8 : u8 , op_mem_reg_pref : u8 , op_ext : u8 , opnd : X86Opnd ) {
790
- let opnd_size = match opnd {
791
- X86Opnd :: Reg ( reg) => reg. num_bits ,
792
- X86Opnd :: Mem ( mem) => mem. num_bits ,
793
- _ => unreachable ! ( )
794
- } ;
798
+ assert ! ( matches!( opnd, X86Opnd :: Reg ( _) | X86Opnd :: Mem ( _) ) ) ;
795
799
800
+ let opnd_size = opnd. num_bits ( ) ;
796
801
assert ! ( opnd_size == 8 || opnd_size == 16 || opnd_size == 32 || opnd_size == 64 ) ;
797
802
798
803
if opnd_size == 8 {
@@ -806,13 +811,10 @@ fn write_rm_unary(cb: &mut CodeBlock, op_mem_reg_8: u8, op_mem_reg_pref: u8, op_
806
811
807
812
// Encode an add-like RM instruction with multiple possible encodings
808
813
fn write_rm_multi ( cb : & mut CodeBlock , op_mem_reg8 : u8 , op_mem_reg_pref : u8 , op_reg_mem8 : u8 , op_reg_mem_pref : u8 , op_mem_imm8 : u8 , op_mem_imm_sml : u8 , op_mem_imm_lrg : u8 , op_ext_imm : u8 , opnd0 : X86Opnd , opnd1 : X86Opnd ) {
809
- // Check the size of opnd0
810
- let opnd_size = match opnd0 {
811
- X86Opnd :: Reg ( reg) => reg. num_bits ,
812
- X86Opnd :: Mem ( mem) => mem. num_bits ,
813
- _ => unreachable ! ( )
814
- } ;
814
+ assert ! ( matches!( opnd0, X86Opnd :: Reg ( _) | X86Opnd :: Mem ( _) ) ) ;
815
815
816
+ // Check the size of opnd0
817
+ let opnd_size = opnd0. num_bits ( ) ;
816
818
assert ! ( opnd_size == 8 || opnd_size == 16 || opnd_size == 32 || opnd_size == 64 ) ;
817
819
818
820
// Check the size of opnd1
@@ -1161,12 +1163,11 @@ pub fn jmp32(cb: &mut CodeBlock, offset: i32) {
1161
1163
1162
1164
/// lea - Load Effective Address
1163
1165
pub fn lea ( cb : & mut CodeBlock , dst : X86Opnd , src : X86Opnd ) {
1164
- match dst {
1165
- X86Opnd :: Reg ( reg) => {
1166
- assert ! ( reg. num_bits == 64 ) ;
1167
- write_rm ( cb, false , true , dst, src, 0xff , 1 , & [ 0x8d ] ) ;
1168
- } ,
1169
- _ => unreachable ! ( )
1166
+ if let X86Opnd :: Reg ( reg) = dst {
1167
+ assert ! ( reg. num_bits == 64 ) ;
1168
+ write_rm ( cb, false , true , dst, src, 0xff , 1 , & [ 0x8d ] ) ;
1169
+ } else {
1170
+ unreachable ! ( ) ;
1170
1171
}
1171
1172
}
1172
1173
@@ -1248,17 +1249,15 @@ pub fn mov(cb: &mut CodeBlock, dst: X86Opnd, src: X86Opnd) {
1248
1249
/// movsx - Move with sign extension (signed integers)
1249
1250
pub fn movsx ( cb : & mut CodeBlock , dst : X86Opnd , src : X86Opnd ) {
1250
1251
if let X86Opnd :: Reg ( dst_reg) = dst {
1251
- let src_num_bits = match src {
1252
- X86Opnd :: Reg ( reg) => reg. num_bits ,
1253
- X86Opnd :: Mem ( mem) => mem. num_bits ,
1254
- _ => unreachable ! ( )
1255
- } ;
1252
+ assert ! ( matches!( src, X86Opnd :: Reg ( _) | X86Opnd :: Mem ( _) ) ) ;
1256
1253
1257
- assert ! ( src_num_bits < dst_reg. num_bits) ;
1254
+ let src_num_bits = src. num_bits ( ) ;
1255
+ let dst_num_bits = dst. num_bits ( ) ;
1256
+ assert ! ( src_num_bits < dst_num_bits) ;
1258
1257
1259
1258
match src_num_bits {
1260
- 8 => write_rm ( cb, dst_reg . num_bits == 16 , dst_reg . num_bits == 64 , dst, src, 0xff , 2 , & [ 0x0f , 0xbe ] ) ,
1261
- 16 => write_rm ( cb, dst_reg . num_bits == 16 , dst_reg . num_bits == 64 , dst, src, 0xff , 2 , & [ 0x0f , 0xbf ] ) ,
1259
+ 8 => write_rm ( cb, dst_num_bits == 16 , dst_num_bits == 64 , dst, src, 0xff , 2 , & [ 0x0f , 0xbe ] ) ,
1260
+ 16 => write_rm ( cb, dst_num_bits == 16 , dst_num_bits == 64 , dst, src, 0xff , 2 , & [ 0x0f , 0xbf ] ) ,
1262
1261
32 => write_rm ( cb, false , true , dst, src, 0xff , 1 , & [ 0x63 ] ) ,
1263
1262
_ => unreachable ! ( )
1264
1263
} ;
@@ -1413,29 +1412,26 @@ pub fn ret(cb: &mut CodeBlock) {
1413
1412
1414
1413
// Encode a single-operand shift instruction
1415
1414
fn write_shift ( cb : & mut CodeBlock , op_mem_one_pref : u8 , op_mem_cl_pref : u8 , op_mem_imm_pref : u8 , op_ext : u8 , opnd0 : X86Opnd , opnd1 : X86Opnd ) {
1416
- // Check the size of opnd0
1417
- let opnd_size = match opnd0 {
1418
- X86Opnd :: Reg ( reg) => reg. num_bits ,
1419
- X86Opnd :: Mem ( mem) => mem. num_bits ,
1420
- _ => unreachable ! ( )
1421
- } ;
1415
+ assert ! ( matches!( opnd0, X86Opnd :: Reg ( _) | X86Opnd :: Mem ( _) ) ) ;
1422
1416
1417
+ // Check the size of opnd0
1418
+ let opnd_size = opnd0. num_bits ( ) ;
1423
1419
assert ! ( opnd_size == 16 || opnd_size == 32 || opnd_size == 64 ) ;
1420
+
1424
1421
let sz_pref = opnd_size == 16 ;
1425
1422
let rex_w = opnd_size == 64 ;
1426
1423
1427
- match opnd1 {
1428
- X86Opnd :: Imm ( imm) => {
1429
- if imm. value == 1 {
1430
- write_rm ( cb, sz_pref, rex_w, X86Opnd :: None , opnd0, op_ext, 1 , & [ op_mem_one_pref] ) ;
1431
- } else {
1432
- assert ! ( imm. num_bits <= 8 ) ;
1433
- write_rm ( cb, sz_pref, rex_w, X86Opnd :: None , opnd0, op_ext, 1 , & [ op_mem_imm_pref] ) ;
1434
- cb. write_byte ( imm. value as u8 ) ;
1435
- }
1436
- } ,
1437
- _ => unreachable ! ( )
1438
- } ;
1424
+ if let X86Opnd :: Imm ( imm) = opnd1 {
1425
+ if imm. value == 1 {
1426
+ write_rm ( cb, sz_pref, rex_w, X86Opnd :: None , opnd0, op_ext, 1 , & [ op_mem_one_pref] ) ;
1427
+ } else {
1428
+ assert ! ( imm. num_bits <= 8 ) ;
1429
+ write_rm ( cb, sz_pref, rex_w, X86Opnd :: None , opnd0, op_ext, 1 , & [ op_mem_imm_pref] ) ;
1430
+ cb. write_byte ( imm. value as u8 ) ;
1431
+ }
1432
+ } else {
1433
+ unreachable ! ( ) ;
1434
+ }
1439
1435
}
1440
1436
1441
1437
// sal - Shift arithmetic left
@@ -1525,11 +1521,8 @@ fn resize_opnd(opnd: X86Opnd, num_bits: u8) -> X86Opnd {
1525
1521
1526
1522
/// test - Logical Compare
1527
1523
pub fn test ( cb : & mut CodeBlock , rm_opnd : X86Opnd , test_opnd : X86Opnd ) {
1528
- let rm_num_bits = match rm_opnd {
1529
- X86Opnd :: Reg ( reg) => reg. num_bits ,
1530
- X86Opnd :: Mem ( mem) => mem. num_bits ,
1531
- _ => unreachable ! ( )
1532
- } ;
1524
+ assert ! ( matches!( rm_opnd, X86Opnd :: Reg ( _) | X86Opnd :: Mem ( _) ) ) ;
1525
+ let rm_num_bits = rm_opnd. num_bits ( ) ;
1533
1526
1534
1527
match test_opnd {
1535
1528
X86Opnd :: UImm ( uimm) => {
0 commit comments