YJIT: expand bitwise shift support in x86 assembler (#8174)

This commit is contained in:
Maxime Chevalier-Boisvert 2023-08-04 14:57:56 -04:00 коммит произвёл GitHub
Родитель c4066af35e
Коммит 8d7861e3da
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 26 добавлений и 15 удалений

Просмотреть файл

@ -1223,8 +1223,8 @@ pub fn ret(cb: &mut CodeBlock) {
cb.write_byte(0xC3); cb.write_byte(0xC3);
} }
// Encode a single-operand shift instruction // Encode a bitwise shift instruction
fn write_shift(cb: &mut CodeBlock, op_mem_one_pref: u8, _op_mem_cl_pref: u8, op_mem_imm_pref: u8, op_ext: Option<u8>, opnd0: X86Opnd, opnd1: X86Opnd) { 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) {
assert!(matches!(opnd0, X86Opnd::Reg(_) | X86Opnd::Mem(_))); assert!(matches!(opnd0, X86Opnd::Reg(_) | X86Opnd::Mem(_)));
// Check the size of opnd0 // Check the size of opnd0
@ -1234,16 +1234,26 @@ fn write_shift(cb: &mut CodeBlock, op_mem_one_pref: u8, _op_mem_cl_pref: u8, op_
let sz_pref = opnd_size == 16; let sz_pref = opnd_size == 16;
let rex_w = opnd_size == 64; let rex_w = opnd_size == 64;
if let X86Opnd::UImm(imm) = opnd1 { match opnd1 {
if imm.value == 1 { X86Opnd::UImm(imm) => {
write_rm(cb, sz_pref, rex_w, X86Opnd::None, opnd0, op_ext, &[op_mem_one_pref]); if imm.value == 1 {
} else { write_rm(cb, sz_pref, rex_w, X86Opnd::None, opnd0, Some(op_ext), &[op_mem_one_pref]);
assert!(imm.num_bits <= 8); } else {
write_rm(cb, sz_pref, rex_w, X86Opnd::None, opnd0, op_ext, &[op_mem_imm_pref]); assert!(imm.num_bits <= 8);
cb.write_byte(imm.value as u8); write_rm(cb, sz_pref, rex_w, X86Opnd::None, opnd0, Some(op_ext), &[op_mem_imm_pref]);
cb.write_byte(imm.value as u8);
}
}
X86Opnd::Reg(reg) => {
// We can only use CL/RCX as the shift amount
assert!(reg.reg_no == RCX_REG.reg_no);
write_rm(cb, sz_pref, rex_w, X86Opnd::None, opnd0, Some(op_ext), &[op_mem_cl_pref]);
}
_ => {
unreachable!();
} }
} else {
unreachable!();
} }
} }
@ -1254,7 +1264,7 @@ pub fn sal(cb: &mut CodeBlock, opnd0: X86Opnd, opnd1: X86Opnd) {
0xD1, // opMemOnePref, 0xD1, // opMemOnePref,
0xD3, // opMemClPref, 0xD3, // opMemClPref,
0xC1, // opMemImmPref, 0xC1, // opMemImmPref,
Some(0x04), 0x04,
opnd0, opnd0,
opnd1 opnd1
); );
@ -1267,7 +1277,7 @@ pub fn sar(cb: &mut CodeBlock, opnd0: X86Opnd, opnd1: X86Opnd) {
0xD1, // opMemOnePref, 0xD1, // opMemOnePref,
0xD3, // opMemClPref, 0xD3, // opMemClPref,
0xC1, // opMemImmPref, 0xC1, // opMemImmPref,
Some(0x07), 0x07,
opnd0, opnd0,
opnd1 opnd1
); );
@ -1280,7 +1290,7 @@ pub fn shl(cb: &mut CodeBlock, opnd0: X86Opnd, opnd1: X86Opnd) {
0xD1, // opMemOnePref, 0xD1, // opMemOnePref,
0xD3, // opMemClPref, 0xD3, // opMemClPref,
0xC1, // opMemImmPref, 0xC1, // opMemImmPref,
Some(0x04), 0x04,
opnd0, opnd0,
opnd1 opnd1
); );
@ -1293,7 +1303,7 @@ pub fn shr(cb: &mut CodeBlock, opnd0: X86Opnd, opnd1: X86Opnd) {
0xD1, // opMemOnePref, 0xD1, // opMemOnePref,
0xD3, // opMemClPref, 0xD3, // opMemClPref,
0xC1, // opMemImmPref, 0xC1, // opMemImmPref,
Some(0x05), 0x05,
opnd0, opnd0,
opnd1 opnd1
); );

Просмотреть файл

@ -340,6 +340,7 @@ fn test_sal() {
check_bytes("d1e1", |cb| sal(cb, ECX, uimm_opnd(1))); check_bytes("d1e1", |cb| sal(cb, ECX, uimm_opnd(1)));
check_bytes("c1e505", |cb| sal(cb, EBP, uimm_opnd(5))); check_bytes("c1e505", |cb| sal(cb, EBP, uimm_opnd(5)));
check_bytes("d1642444", |cb| sal(cb, mem_opnd(32, RSP, 68), uimm_opnd(1))); check_bytes("d1642444", |cb| sal(cb, mem_opnd(32, RSP, 68), uimm_opnd(1)));
check_bytes("48d3e1", |cb| sal(cb, RCX, CL));
} }
#[test] #[test]