8000 Implement num_bits() for X86Opnd (#143) · kddnewton/ruby@c98c649 · GitHub
[go: up one dir, main page]

Skip to content

Commit c98c649

Browse files
kddnewtonmaximecb
andauthored
Implement num_bits() for X86Opnd (ruby#143)
* Implement num_bits() for X86Opnd Use it in places where we can just take advantage of assert!(matches!(operand, pattern)) * Update mod.rs Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com>
1 parent ef87a17 commit c98c649

File tree

1 file changed

+48
-55
lines changed

1 file changed

+48
-55
lines changed

yjit/src/asm/x86_64/mod.rs

Lines changed: 48 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,16 @@ impl X86Opnd {
183183
_ => 0
184184
}
185185
}
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+
}
186196
}
187197

188198
// Instruction pointer
@@ -524,8 +534,6 @@ impl CodeBlock
524534

525535
/// Allocate a new label with a given name
526536
pub fn new_label(&mut self, name: String) -> usize {
527-
// assert (cb->num_labels < MAX_LABELS);
528-
529537
// This label doesn't have an address yet
530538
self.label_addrs.push(0);
531539
self.label_names.push(name);
@@ -559,10 +567,10 @@ impl CodeBlock
559567
let ref_pos = label_ref.pos;
560568
let label_idx = label_ref.label_idx;
561569
assert!(ref_pos < self.mem_size);
562-
// assert (label_idx < MAX_LABELS);
563570

564571
let label_addr = self.label_addrs[label_idx];
565572
assert!(label_addr < self.mem_size);
573+
566574
// Compute the offset from the reference's end to the label
567575
let offset = (label_addr as i64) - ((ref_pos + 4) as i64);
568576

@@ -709,10 +717,10 @@ fn write_rm(cb: &mut CodeBlock, sz_pref: bool, rex_w: bool, r_opnd: X86Opnd, rm_
709717
// MODRM.reg (3 bits)
710718
// MODRM.rm (3 bits)
711719

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+
);
716724

717725
// Encode the mod field
718726
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_
787795

788796
// Encode a mul-like single-operand RM instruction
789797
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(_)));
795799

800+
let opnd_size = opnd.num_bits();
796801
assert!(opnd_size == 8 || opnd_size == 16 || opnd_size == 32 || opnd_size == 64);
797802

798803
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_
806811

807812
// Encode an add-like RM instruction with multiple possible encodings
808813
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(_)));
815815

816+
// Check the size of opnd0
817+
let opnd_size = opnd0.num_bits();
816818
assert!(opnd_size == 8 || opnd_size == 16 || opnd_size == 32 || opnd_size == 64);
817819

818820
// Check the size of opnd1
@@ -1161,12 +1163,11 @@ pub fn jmp32(cb: &mut CodeBlock, offset: i32) {
11611163

11621164
/// lea - Load Effective Address
11631165
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!();
11701171
}
11711172
}
11721173

@@ -1248,17 +1249,15 @@ pub fn mov(cb: &mut CodeBlock, dst: X86Opnd, src: X86Opnd) {
12481249
/// movsx - Move with sign extension (signed integers)
12491250
pub fn movsx(cb: &mut CodeBlock, dst: X86Opnd, src: X86Opnd) {
12501251
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(_)));
12561253

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);
12581257

12591258
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]),
12621261
32 => write_rm(cb, false, true, dst, src, 0xff, 1, &[0x63]),
12631262
_ => unreachable!()
12641263
};
@@ -1413,29 +1412,26 @@ pub fn ret(cb: &mut CodeBlock) {
14131412

14141413
// Encode a single-operand shift instruction
14151414
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(_)));
14221416

1417+
// Check the size of opnd0
1418+
let opnd_size = opnd0.num_bits();
14231419
assert!(opnd_size == 16 || opnd_size == 32 || opnd_size == 64);
1420+
14241421
let sz_pref = opnd_size == 16;
14251422
let rex_w = opnd_size == 64;
14261423

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+
}
14391435
}
14401436

14411437
// sal - Shift arithmetic left
@@ -1525,11 +1521,8 @@ fn resize_opnd(opnd: X86Opnd, num_bits: u8) -> X86Opnd {
15251521

15261522
/// test - Logical Compare
15271523
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();
15331526

15341527
match test_opnd {
15351528
X86Opnd::UImm(uimm) => {

0 commit comments

Comments
 (0)
0