Fix div (makes the euler example pass!)

This commit is contained in:
Jef
2019-06-13 13:24:40 +02:00
parent 353e6e737b
commit e2285b543a

View File

@@ -725,7 +725,7 @@ macro_rules! int_div {
let div = match div {
ValueLocation::Reg(div) => {
if saved.any(|(_, dst)| dst == div) {
if saved.clone().any(|dst| dst == div) {
let new = self.take_reg(I32).unwrap();
dynasm!(self.asm
; mov Rq(new.rq().unwrap()), Rq(div.rq().unwrap())
@@ -769,7 +769,7 @@ macro_rules! int_div {
let div = match div {
ValueLocation::Reg(div) => {
if saved.any(|(_, dst)| dst == div) {
if saved.clone().any(|dst| dst == div) {
let new = self.take_reg(I32).unwrap();
dynasm!(self.asm
; mov Rq(new.rq().unwrap()), Rq(div.rq().unwrap())
@@ -810,7 +810,7 @@ macro_rules! int_div {
let rem = match rem {
ValueLocation::Reg(rem) => {
if saved.any(|(_, dst)| dst == rem) {
if saved.clone().any(|dst| dst == rem) {
let new = self.take_reg(I32).unwrap();
dynasm!(self.asm
; mov Rq(new.rq().unwrap()), Rq(rem.rq().unwrap())
@@ -884,7 +884,7 @@ macro_rules! int_div {
let rem = match rem {
ValueLocation::Reg(rem) => {
if saved.any(|(_, dst)| dst == rem) {
if saved.clone().any(|dst| dst == rem) {
let new = self.take_reg(I32).unwrap();
dynasm!(self.asm
; mov Rq(new.rq().unwrap()), Rq(rem.rq().unwrap())
@@ -4361,11 +4361,13 @@ impl<'this, M: ModuleContext> Context<'this, M> {
);
// TODO: Do this without emitting `mov`
fn cleanup_gprs(&mut self, gprs: impl Iterator<Item = (GPR, GPR)>) {
for (src, dst) in gprs {
self.copy_value(ValueLocation::Reg(src), CCLoc::Reg(dst));
self.block_state.regs.release(src);
self.block_state.regs.mark_used(dst);
fn cleanup_gprs(&mut self, gprs: impl Iterator<Item = GPR>) {
for gpr in gprs {
dynasm!(self.asm
; pop Rq(gpr.rq().unwrap())
);
self.block_state.depth.free(1);
self.block_state.regs.mark_used(gpr);
}
}
@@ -4401,73 +4403,61 @@ impl<'this, M: ModuleContext> Context<'this, M> {
fn full_div(
&mut self,
dividend: ValueLocation,
divisor: ValueLocation,
mut divisor: ValueLocation,
do_div: impl FnOnce(&mut Self, ValueLocation),
) -> (
ValueLocation,
ValueLocation,
impl Iterator<Item = (GPR, GPR)> + Clone + 'this,
impl Iterator<Item = GPR> + Clone + 'this,
) {
// To stop `take_reg` from allocating either of these necessary registers
self.block_state.regs.mark_used(RAX);
self.block_state.regs.mark_used(RDX);
let divisor = if divisor == ValueLocation::Reg(RAX) || divisor == ValueLocation::Reg(RDX) {
let new_reg = self.take_reg(I32).unwrap();
if divisor == ValueLocation::Reg(RAX) || divisor == ValueLocation::Reg(RDX) {
let new_reg = self.take_reg(GPRType::Rq).unwrap();
self.copy_value(divisor, CCLoc::Reg(new_reg));
self.free_value(divisor);
ValueLocation::Reg(new_reg)
} else if let ValueLocation::Stack(_) = divisor {
divisor
} else {
ValueLocation::Reg(self.into_reg(I32, divisor).unwrap())
};
self.block_state.regs.release(RDX);
self.block_state.regs.release(RAX);
if let ValueLocation::Reg(r) = dividend {
self.block_state.regs.mark_used(r);
divisor = ValueLocation::Reg(new_reg);
}
self.block_state.regs.release(RAX);
self.block_state.regs.release(RDX);
let should_save_rax =
dividend != ValueLocation::Reg(RAX) && !self.block_state.regs.is_free(RAX);
let saved_rax = if should_save_rax {
let new_reg = self.take_reg(I32).unwrap();
dynasm!(self.asm
; mov Rq(new_reg.rq().unwrap()), rax
);
Some(new_reg)
} else {
let saved_rax = if self.block_state.regs.is_free(RAX) {
None
} else {
self.block_state.depth.reserve(1);
dynasm!(self.asm
; push rax
);
Some(())
};
let saved_rdx = if self.block_state.regs.is_free(RDX) {
None
} else {
self.block_state.depth.reserve(1);
dynasm!(self.asm
; push rdx
);
Some(())
};
self.block_state.regs.mark_used(RAX);
self.copy_value(dividend, CCLoc::Reg(RAX));
self.free_value(dividend);
let should_save_rdx = !self.block_state.regs.is_free(RDX);
let saved_rdx = if should_save_rdx {
let new_reg = self.take_reg(I32).unwrap();
dynasm!(self.asm
; mov Rq(new_reg.rq().unwrap()), rdx
);
Some(new_reg)
} else {
None
};
// To stop `take_reg` from allocating either of these necessary registers
self.block_state.regs.mark_used(RAX);
self.block_state.regs.mark_used(RDX);
do_div(self, divisor);
self.free_value(divisor);
self.block_state.regs.mark_used(RDX);
(
ValueLocation::Reg(RAX),
ValueLocation::Reg(RDX),
saved_rax
.map(|s| (s, RAX))
saved_rdx
.map(|_| RDX)
.into_iter()
.chain(saved_rdx.map(|s| (s, RDX))),
.chain(saved_rax.map(|_| RAX)),
)
}
@@ -4478,7 +4468,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
) -> (
ValueLocation,
ValueLocation,
impl Iterator<Item = (GPR, GPR)> + Clone + 'this,
impl Iterator<Item = GPR> + Clone + 'this,
) {
self.full_div(dividend, divisor, |this, divisor| match divisor {
ValueLocation::Stack(offset) => {
@@ -4488,14 +4478,14 @@ impl<'this, M: ModuleContext> Context<'this, M> {
; div DWORD [rsp + offset]
);
}
ValueLocation::Reg(_) | ValueLocation::Cond(_) => {
ValueLocation::Immediate(_) | ValueLocation::Reg(_) | ValueLocation::Cond(_) => {
let r = this.into_reg(I32, divisor).unwrap();
dynasm!(this.asm
; xor edx, edx
; div Rd(r.rq().unwrap())
);
this.free_value(ValueLocation::Reg(r));
}
ValueLocation::Immediate(_) => unreachable!(),
})
}
@@ -4506,7 +4496,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
) -> (
ValueLocation,
ValueLocation,
impl Iterator<Item = (GPR, GPR)> + Clone + 'this,
impl Iterator<Item = GPR> + Clone + 'this,
) {
self.full_div(dividend, divisor, |this, divisor| match divisor {
ValueLocation::Stack(offset) => {
@@ -4516,14 +4506,14 @@ impl<'this, M: ModuleContext> Context<'this, M> {
; idiv DWORD [rsp + offset]
);
}
ValueLocation::Reg(_) | ValueLocation::Cond(_) => {
ValueLocation::Immediate(_) | ValueLocation::Reg(_) | ValueLocation::Cond(_) => {
let r = this.into_reg(I32, divisor).unwrap();
dynasm!(this.asm
; cdq
; idiv Rd(r.rq().unwrap())
);
this.free_value(ValueLocation::Reg(r));
}
ValueLocation::Immediate(_) => unreachable!(),
})
}
@@ -4534,7 +4524,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
) -> (
ValueLocation,
ValueLocation,
impl Iterator<Item = (GPR, GPR)> + Clone + 'this,
impl Iterator<Item = GPR> + Clone + 'this,
) {
self.full_div(dividend, divisor, |this, divisor| match divisor {
ValueLocation::Stack(offset) => {
@@ -4544,14 +4534,13 @@ impl<'this, M: ModuleContext> Context<'this, M> {
; div QWORD [rsp + offset]
);
}
ValueLocation::Reg(_) | ValueLocation::Cond(_) => {
ValueLocation::Immediate(_) | ValueLocation::Reg(_) | ValueLocation::Cond(_) => {
let r = this.into_reg(I64, divisor).unwrap();
dynasm!(this.asm
; xor rdx, rdx
; div Rq(r.rq().unwrap())
);
}
ValueLocation::Immediate(_) => unreachable!(),
})
}
@@ -4562,7 +4551,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
) -> (
ValueLocation,
ValueLocation,
impl Iterator<Item = (GPR, GPR)> + Clone + 'this,
impl Iterator<Item = GPR> + Clone + 'this,
) {
self.full_div(dividend, divisor, |this, divisor| match divisor {
ValueLocation::Stack(offset) => {
@@ -4572,14 +4561,13 @@ impl<'this, M: ModuleContext> Context<'this, M> {
; idiv QWORD [rsp + offset]
);
}
ValueLocation::Reg(_) | ValueLocation::Cond(_) => {
ValueLocation::Immediate(_) | ValueLocation::Reg(_) | ValueLocation::Cond(_) => {
let r = this.into_reg(I64, divisor).unwrap();
dynasm!(this.asm
; cqo
; idiv Rq(r.rq().unwrap())
);
}
ValueLocation::Immediate(_) => unreachable!(),
})
}
@@ -5377,8 +5365,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
);
}
pub fn epilogue(&mut self) {
}
pub fn epilogue(&mut self) {}
pub fn trap(&mut self) {
let trap_label = self.trap_label();
@@ -5502,3 +5489,4 @@ impl IntoLabel for (LabelValue, LabelValue) {
Box::new(const_values(self.0, self.1))
}
}