use super::super::instructions::{Operand, PtxInstruction, PtxOp, RoundingMode};
use super::super::registers::VirtualReg;
use super::super::types::PtxType;
use super::core::KernelBuilderCore;
pub trait PtxArithmetic: KernelBuilderCore {
fn mad_lo_u32(&mut self, a: VirtualReg, b: VirtualReg, c: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::U32);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::MadLo, PtxType::U32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a))
.src(Operand::Reg(b))
.src(Operand::Reg(c)),
);
dst
}
fn mul_wide_u32(&mut self, a: VirtualReg, b: u32) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::U64);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::MulWide, PtxType::U32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a))
.src(Operand::ImmU64(b as u64)),
);
dst
}
fn mul_wide_u32_reg(&mut self, a: VirtualReg, b: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::U64);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::MulWide, PtxType::U32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a))
.src(Operand::Reg(b)),
);
dst
}
fn add_u64(&mut self, a: VirtualReg, b: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::U64);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Add, PtxType::U64)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a))
.src(Operand::Reg(b)),
);
dst
}
fn add_u64_into(&mut self, dst: VirtualReg, a: VirtualReg, b: VirtualReg) {
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Add, PtxType::U64)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a))
.src(Operand::Reg(b)),
);
}
fn add_u32(&mut self, a: VirtualReg, b: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::U32);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Add, PtxType::U32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a))
.src(Operand::Reg(b)),
);
dst
}
fn add_u32_into(&mut self, dst: VirtualReg, a: VirtualReg, b: VirtualReg) {
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Add, PtxType::U32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a))
.src(Operand::Reg(b)),
);
}
fn sub_u32(&mut self, a: VirtualReg, b: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::U32);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Sub, PtxType::U32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a))
.src(Operand::Reg(b)),
);
dst
}
fn mul_u32(&mut self, a: VirtualReg, b: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::U32);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Mul, PtxType::U32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a))
.src(Operand::Reg(b)),
);
dst
}
fn add_f32(&mut self, a: VirtualReg, b: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::F32);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Add, PtxType::F32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a))
.src(Operand::Reg(b))
.rounding(RoundingMode::Rn),
);
dst
}
fn sub_f32(&mut self, a: VirtualReg, b: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::F32);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Sub, PtxType::F32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a))
.src(Operand::Reg(b))
.rounding(RoundingMode::Rn),
);
dst
}
fn mul_f32(&mut self, a: VirtualReg, b: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::F32);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Mul, PtxType::F32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a))
.src(Operand::Reg(b))
.rounding(RoundingMode::Rn),
);
dst
}
fn div_f32(&mut self, a: VirtualReg, b: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::F32);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Div, PtxType::F32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a))
.src(Operand::Reg(b))
.rounding(RoundingMode::Rn),
);
dst
}
fn fma_f32(&mut self, a: VirtualReg, b: VirtualReg, c: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::F32);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Fma, PtxType::F32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a))
.src(Operand::Reg(b))
.src(Operand::Reg(c))
.rounding(RoundingMode::Rn),
);
dst
}
fn fma_f32_into(&mut self, dst: VirtualReg, a: VirtualReg, b: VirtualReg, c: VirtualReg) {
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Fma, PtxType::F32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a))
.src(Operand::Reg(b))
.src(Operand::Reg(c))
.rounding(RoundingMode::Rn),
);
}
fn add_f64(&mut self, a: VirtualReg, b: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::F64);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Add, PtxType::F64)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a))
.src(Operand::Reg(b))
.rounding(RoundingMode::Rn),
);
dst
}
fn fma_f64(&mut self, a: VirtualReg, b: VirtualReg, c: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::F64);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Fma, PtxType::F64)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a))
.src(Operand::Reg(b))
.src(Operand::Reg(c))
.rounding(RoundingMode::Rn),
);
dst
}
fn cvt_f64_f32(&mut self, src: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::F64);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Cvt, PtxType::F64)
.dst(Operand::Reg(dst))
.src(Operand::Reg(src))
.with_src_type(PtxType::F32),
);
dst
}
fn cvt_f32_f64(&mut self, src: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::F32);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Cvt, PtxType::F32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(src))
.with_src_type(PtxType::F64)
.rounding(RoundingMode::Rn),
);
dst
}
fn neg_f32(&mut self, a: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::F32);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Neg, PtxType::F32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a)),
);
dst
}
fn abs_f32(&mut self, a: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::F32);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Abs, PtxType::F32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a)),
);
dst
}
fn sqrt_f32(&mut self, a: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::F32);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Sqrt, PtxType::F32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a))
.rounding(RoundingMode::Rn),
);
dst
}
fn rsqrt_f32(&mut self, a: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::F32);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Rsqrt, PtxType::F32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a)),
);
dst
}
fn rcp_f32(&mut self, a: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::F32);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Rcp, PtxType::F32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a)),
);
dst
}
fn ex2_f32(&mut self, a: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::F32);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Ex2, PtxType::F32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a)),
);
dst
}
fn lg2_f32(&mut self, a: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::F32);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Lg2, PtxType::F32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a)),
);
dst
}
fn sin_f32(&mut self, a: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::F32);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Sin, PtxType::F32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a)),
);
dst
}
fn cos_f32(&mut self, a: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::F32);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Cos, PtxType::F32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a)),
);
dst
}
fn min_f32(&mut self, a: VirtualReg, b: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::F32);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Min, PtxType::F32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a))
.src(Operand::Reg(b)),
);
dst
}
fn max_f32(&mut self, a: VirtualReg, b: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::F32);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Max, PtxType::F32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a))
.src(Operand::Reg(b)),
);
dst
}
fn dp4a_s32(&mut self, a: VirtualReg, b: VirtualReg, c: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::S32);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Dp4a, PtxType::S32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a))
.src(Operand::Reg(b))
.src(Operand::Reg(c)),
);
dst
}
fn dp4a_u32(&mut self, a: VirtualReg, b: VirtualReg, c: VirtualReg) -> VirtualReg {
let dst = self.registers_mut().allocate_virtual(PtxType::U32);
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Dp4a, PtxType::U32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a))
.src(Operand::Reg(b))
.src(Operand::Reg(c)),
);
dst
}
fn dp4a_s32_into(&mut self, dst: VirtualReg, a: VirtualReg, b: VirtualReg, c: VirtualReg) {
self.instructions_mut().push(
PtxInstruction::new(PtxOp::Dp4a, PtxType::S32)
.dst(Operand::Reg(dst))
.src(Operand::Reg(a))
.src(Operand::Reg(b))
.src(Operand::Reg(c)),
);
}
}
impl<T: KernelBuilderCore> PtxArithmetic for T {}
#[cfg(test)]
mod tests;