mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 22:34:45 +00:00
add x86_64 Int neq support for gen_dev
This commit is contained in:
parent
2eae1a857b
commit
e064deca76
5 changed files with 134 additions and 1 deletions
|
@ -490,6 +490,16 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
|
|||
unimplemented!("registers equality not implemented yet for AArch64");
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn neq_reg64_reg64_reg64(
|
||||
_buf: &mut Vec<'_, u8>,
|
||||
_dst: AArch64GeneralReg,
|
||||
_src1: AArch64GeneralReg,
|
||||
_src2: AArch64GeneralReg,
|
||||
) {
|
||||
unimplemented!("registers non-equality not implemented yet for AArch64");
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn ret(buf: &mut Vec<'_, u8>) {
|
||||
ret_reg64(buf, AArch64GeneralReg::LR)
|
||||
|
|
|
@ -172,6 +172,13 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait> {
|
|||
src2: GeneralReg,
|
||||
);
|
||||
|
||||
fn neq_reg64_reg64_reg64(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
dst: GeneralReg,
|
||||
src1: GeneralReg,
|
||||
src2: GeneralReg,
|
||||
);
|
||||
|
||||
fn ret(buf: &mut Vec<'_, u8>);
|
||||
}
|
||||
|
||||
|
@ -842,6 +849,25 @@ impl<
|
|||
}
|
||||
}
|
||||
|
||||
fn build_neq(
|
||||
&mut self,
|
||||
dst: &Symbol,
|
||||
src1: &Symbol,
|
||||
src2: &Symbol,
|
||||
arg_layout: &Layout<'a>,
|
||||
) -> Result<(), String> {
|
||||
match arg_layout {
|
||||
Layout::Builtin(Builtin::Int64) => {
|
||||
let dst_reg = self.claim_general_reg(dst)?;
|
||||
let src1_reg = self.load_to_general_reg(src1)?;
|
||||
let src2_reg = self.load_to_general_reg(src2)?;
|
||||
ASM::neq_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
||||
Ok(())
|
||||
}
|
||||
x => Err(format!("NumNeq: layout, {:?}, not implemented yet", x)),
|
||||
}
|
||||
}
|
||||
|
||||
fn create_struct(
|
||||
&mut self,
|
||||
sym: &Symbol,
|
||||
|
|
|
@ -1096,6 +1096,17 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> for X86_64Assembler {
|
|||
sete_reg64(buf, dst);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn neq_reg64_reg64_reg64(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
dst: X86_64GeneralReg,
|
||||
src1: X86_64GeneralReg,
|
||||
src2: X86_64GeneralReg,
|
||||
) {
|
||||
cmp_reg64_reg64(buf, src1, src2);
|
||||
setne_reg64(buf, dst);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn ret(buf: &mut Vec<'_, u8>) {
|
||||
ret(buf);
|
||||
|
@ -1475,6 +1486,26 @@ fn sete_reg64(buf: &mut Vec<'_, u8>, reg: X86_64GeneralReg) {
|
|||
and_reg64_imm8(buf, reg, 1);
|
||||
}
|
||||
|
||||
/// `SETNE r/m64` -> Set byte if not equal (ZF=0).
|
||||
#[inline(always)]
|
||||
fn setne_reg64(buf: &mut Vec<'_, u8>, reg: X86_64GeneralReg) {
|
||||
// Follow `sete_reg64` implementation.
|
||||
// Change 94 => 95
|
||||
buf.reserve(7);
|
||||
|
||||
let reg_mod = reg as u8 % 8;
|
||||
use X86_64GeneralReg::*;
|
||||
match reg {
|
||||
RAX | RCX | RDX | RBX => buf.extend(&[0x0F, 0x95, 0xC0 + reg_mod]),
|
||||
RSP | RBP | RSI | RDI => buf.extend(&[REX, 0x0F, 0x95, 0xC0 + reg_mod]),
|
||||
R8 | R9 | R10 | R11 | R12 | R13 | R14 | R15 => {
|
||||
buf.extend(&[REX + 1, 0x0F, 0x95, 0xC0 + reg_mod])
|
||||
}
|
||||
}
|
||||
|
||||
and_reg64_imm8(buf, reg, 1);
|
||||
}
|
||||
|
||||
/// `RET` -> Near return to calling procedure.
|
||||
#[inline(always)]
|
||||
fn ret(buf: &mut Vec<'_, u8>) {
|
||||
|
@ -2074,6 +2105,46 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
// follow test_sete_reg64
|
||||
// refer it
|
||||
fn test_setne_reg64() {
|
||||
let arena = bumpalo::Bump::new();
|
||||
let mut buf = bumpalo::vec![in &arena];
|
||||
|
||||
let (reg, expected) = (
|
||||
X86_64GeneralReg::RAX,
|
||||
[
|
||||
0x0F, 0x95, 0xC0, // SETNE al ;
|
||||
0x48, 0x83, 0xE0, 0x01,
|
||||
],
|
||||
);
|
||||
buf.clear();
|
||||
setne_reg64(&mut buf, reg);
|
||||
assert_eq!(expected, &buf[..]);
|
||||
|
||||
for (reg, expected) in &[
|
||||
(
|
||||
X86_64GeneralReg::RSP,
|
||||
[
|
||||
// SETNE spl;
|
||||
0x40, 0x0F, 0x95, 0xC4, 0x48, 0x83, 0xE4, 0x01,
|
||||
],
|
||||
),
|
||||
(
|
||||
X86_64GeneralReg::R15,
|
||||
[
|
||||
// SETNE r15b;
|
||||
0x41, 0x0F, 0x95, 0xC7, 0x49, 0x83, 0xE7, 0x01,
|
||||
],
|
||||
),
|
||||
] {
|
||||
buf.clear();
|
||||
setne_reg64(&mut buf, *reg);
|
||||
assert_eq!(expected, &buf[..]);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ret() {
|
||||
let arena = bumpalo::Bump::new();
|
||||
|
|
|
@ -416,6 +416,23 @@ where
|
|||
);
|
||||
self.build_eq(sym, &args[0], &args[1], &arg_layouts[0])
|
||||
}
|
||||
LowLevel::NotEq => {
|
||||
debug_assert_eq!(
|
||||
2,
|
||||
args.len(),
|
||||
"NotEq: expected to have exactly two argument"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
arg_layouts[0], arg_layouts[1],
|
||||
"NotEq: expected all arguments of to have the same layout"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
Layout::Builtin(Builtin::Int1),
|
||||
*ret_layout,
|
||||
"NotEq: expected to have return layout of type I1"
|
||||
);
|
||||
self.build_neq(sym, &args[0], &args[1], &arg_layouts[0])
|
||||
}
|
||||
LowLevel::NumRound => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::NUM_ROUND[FloatWidth::F64].to_string(),
|
||||
|
@ -497,6 +514,15 @@ where
|
|||
arg_layout: &Layout<'a>,
|
||||
) -> Result<(), String>;
|
||||
|
||||
/// build_neq stores the result of `src1 != src2` into dst.
|
||||
fn build_neq(
|
||||
&mut self,
|
||||
dst: &Symbol,
|
||||
src1: &Symbol,
|
||||
src2: &Symbol,
|
||||
arg_layout: &Layout<'a>,
|
||||
) -> Result<(), String>;
|
||||
|
||||
/// literal_map gets the map from symbol to literal, used for lazy loading and literal folding.
|
||||
fn literal_map(&mut self) -> &mut MutMap<Symbol, Literal<'a>>;
|
||||
|
||||
|
|
|
@ -713,7 +713,7 @@ fn gen_int_eq() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn gen_int_neq() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue