forked from koniifer/ableos
adding imm operations is come cases
This commit is contained in:
parent
2dff9f7244
commit
ca1d471646
|
@ -1231,6 +1231,7 @@ impl<'a> Codegen<'a> {
|
||||||
|
|
||||||
let lsize = self.size_of(left.ty);
|
let lsize = self.size_of(left.ty);
|
||||||
let ty = ctx.ty().unwrap_or(left.ty);
|
let ty = ctx.ty().unwrap_or(left.ty);
|
||||||
|
|
||||||
let lhs = match std::mem::take(&mut ctx).loc() {
|
let lhs = match std::mem::take(&mut ctx).loc() {
|
||||||
Some(Loc::RegRef(reg)) if Loc::RegRef(reg) == left.loc => LinReg(reg, None),
|
Some(Loc::RegRef(reg)) if Loc::RegRef(reg) == left.loc => LinReg(reg, None),
|
||||||
Some(loc) => {
|
Some(loc) => {
|
||||||
|
@ -1241,12 +1242,30 @@ impl<'a> Codegen<'a> {
|
||||||
};
|
};
|
||||||
let right = self.expr_ctx(right, Ctx::Inferred(left.ty))?;
|
let right = self.expr_ctx(right, Ctx::Inferred(left.ty))?;
|
||||||
let rsize = self.size_of(right.ty);
|
let rsize = self.size_of(right.ty);
|
||||||
let rhs = self.loc_to_reg(right.loc, rsize);
|
|
||||||
|
|
||||||
let ty = self.assert_ty(expr.pos(), left.ty, right.ty);
|
let ty = self.assert_ty(expr.pos(), left.ty, right.ty);
|
||||||
let size = self.size_of(ty);
|
let size = self.size_of(ty);
|
||||||
let signed = bt::is_signed(ty);
|
let signed = bt::is_signed(ty);
|
||||||
|
|
||||||
|
if let Loc::Imm(mut imm) = right.loc
|
||||||
|
&& let Some(oper) = Self::imm_math_op(op, signed, size, false)
|
||||||
|
{
|
||||||
|
if matches!(op, T::Add | T::Sub) {
|
||||||
|
if bt::is_pointer(left.ty) {
|
||||||
|
let size = self.size_of(self.pointers[ty as usize]);
|
||||||
|
imm *= size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.code.encode(oper(lhs.0, lhs.0, imm));
|
||||||
|
break 'ops Some(Value {
|
||||||
|
ty,
|
||||||
|
loc: Loc::Reg(lhs),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let rhs = self.loc_to_reg(right.loc, rsize);
|
||||||
|
|
||||||
log::dbg!(
|
log::dbg!(
|
||||||
"binop: {} {} {}",
|
"binop: {} {} {}",
|
||||||
self.display_ty(ty),
|
self.display_ty(ty),
|
||||||
|
@ -1358,6 +1377,45 @@ impl<'a> Codegen<'a> {
|
||||||
Some(ops[size.ilog2() as usize])
|
Some(ops[size.ilog2() as usize])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn imm_math_op(
|
||||||
|
op: T,
|
||||||
|
signed: bool,
|
||||||
|
size: u64,
|
||||||
|
first_imm: bool,
|
||||||
|
) -> Option<fn(u8, u8, u64) -> (usize, [u8; instrs::MAX_SIZE])> {
|
||||||
|
use instrs as i;
|
||||||
|
|
||||||
|
macro_rules! def_op {
|
||||||
|
($name:ident |$a:ident, $b:ident, $c:ident| $($tt:tt)*) => {
|
||||||
|
macro_rules! $name {
|
||||||
|
($$($$op:ident),*) => {
|
||||||
|
[$$(
|
||||||
|
|$a, $b, $c: u64| i::$$op($($tt)*),
|
||||||
|
)*]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
def_op!(basic_op | a, b, c | a, b, c as _);
|
||||||
|
def_op!(sub_op | a, b, c | b, a, c.wrapping_neg() as _);
|
||||||
|
|
||||||
|
let ops = match op {
|
||||||
|
T::Add => basic_op!(addi8, addi16, addi32, addi64),
|
||||||
|
T::Sub if !first_imm => sub_op!(addi8, addi16, addi32, addi64),
|
||||||
|
T::Mul => basic_op!(muli8, muli16, muli32, muli64),
|
||||||
|
T::Band => return Some(i::andi),
|
||||||
|
T::Bor => return Some(i::ori),
|
||||||
|
T::Xor => return Some(i::xori),
|
||||||
|
T::Shr if signed && !first_imm => basic_op!(srui8, srui16, srui32, srui64),
|
||||||
|
T::Shr if !first_imm => basic_op!(srui8, srui16, srui32, srui64),
|
||||||
|
T::Shl if !first_imm => basic_op!(slui8, slui16, slui32, slui64),
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(ops[size.ilog2() as usize])
|
||||||
|
}
|
||||||
|
|
||||||
fn struct_op(&mut self, op: T, ty: Type, ctx: Ctx, left: Loc, right: Loc) -> Option<Value> {
|
fn struct_op(&mut self, op: T, ty: Type, ctx: Ctx, left: Loc, right: Loc) -> Option<Value> {
|
||||||
if let TypeKind::Struct(stuct) = TypeKind::from_ty(ty) {
|
if let TypeKind::Struct(stuct) = TypeKind::from_ty(ty) {
|
||||||
let dst = match ctx {
|
let dst = match ctx {
|
||||||
|
@ -1380,9 +1438,22 @@ impl<'a> Codegen<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let size = self.size_of(ty);
|
let size = self.size_of(ty);
|
||||||
let (lhs, owned) = self.loc_to_reg_ref(&left, size);
|
|
||||||
let rhs = self.loc_to_reg(right, size);
|
|
||||||
let signed = bt::is_signed(ty);
|
let signed = bt::is_signed(ty);
|
||||||
|
let (lhs, owned) = self.loc_to_reg_ref(&left, size);
|
||||||
|
|
||||||
|
if let Loc::Imm(imm) = right
|
||||||
|
&& let Some(op) = Self::imm_math_op(op, signed, size, false)
|
||||||
|
{
|
||||||
|
self.code.encode(op(lhs, lhs, imm));
|
||||||
|
return if let Ctx::Dest(dest) = ctx {
|
||||||
|
self.assign(dest.ty, dest.loc, owned.map_or(Loc::RegRef(lhs), Loc::Reg));
|
||||||
|
Some(Value::VOID)
|
||||||
|
} else {
|
||||||
|
Some(Value::new(ty, owned.map_or(Loc::RegRef(lhs), Loc::Reg)))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let rhs = self.loc_to_reg(right, size);
|
||||||
|
|
||||||
if let Some(op) = Self::math_op(op, signed, size) {
|
if let Some(op) = Self::math_op(op, signed, size) {
|
||||||
self.code.encode(op(lhs, lhs, rhs.0));
|
self.code.encode(op(lhs, lhs, rhs.0));
|
||||||
|
|
Loading…
Reference in a new issue