Skip to content

Commit

Permalink
Fix: #1339
Browse files Browse the repository at this point in the history
* A bug in ExpressionSimplifier.Conversion.cs was causing loss of
  information, which led to `CONVERSION(x, int32, real32)` to be
  rewritten as `CONVERSION(x, word32, real32)` which is not the
  desired operation.

* Fixing that bug exposed many `CONVERSION`-related problems
  across many architectures.
  • Loading branch information
uxmal committed Apr 18, 2024
1 parent 6cadc29 commit 2e44fb5
Show file tree
Hide file tree
Showing 177 changed files with 166,697 additions and 158,940 deletions.
8 changes: 4 additions & 4 deletions src/Arch/CompactRisc/Cr16Rewriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,8 @@ public IEnumerator<RtlInstructionCluster> GetEnumerator()
case Mnemonic.movzw: RewriteMovzx(PrimitiveType.Word16); break;
case Mnemonic.mulb: RewriteMul(PrimitiveType.Byte); break;
case Mnemonic.mulw: RewriteMul(PrimitiveType.Word16); break;
case Mnemonic.mulsb: RewriteMuls(PrimitiveType.Byte); break;
case Mnemonic.mulsw: RewriteMuls(PrimitiveType.Word16); break;
case Mnemonic.mulsb: RewriteMuls(PrimitiveType.Int8, PrimitiveType.Int16); break;
case Mnemonic.mulsw: RewriteMuls(PrimitiveType.Int16, PrimitiveType.Int32); break;
case Mnemonic.muluw: RewriteMulu(PrimitiveType.Word16); break;
case Mnemonic.orb: RewriteOr(PrimitiveType.Byte); break;
case Mnemonic.ord: RewriteOr(PrimitiveType.Word32); break;
Expand Down Expand Up @@ -556,11 +556,11 @@ private void RewriteMul(PrimitiveType dt)
Assign(Operand(1), m.SMul(left, right));
}

private void RewriteMuls(PrimitiveType dt)
private void RewriteMuls(PrimitiveType dt, PrimitiveType dtResult)
{
var left = SliceRp(instr.Operands[1], dt);
var right = MaybeSlice(0, dt);
Assign(Operand(1), m.SMul(PrimitiveType.Int32, left, right));
Assign(Operand(1), m.SMul(dtResult, left, right));
}

private Expression SliceRp(MachineOperand op, PrimitiveType dt)
Expand Down
10 changes: 5 additions & 5 deletions src/Arch/CompactRisc/Cr16cDisassembler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -704,9 +704,9 @@ static Cr16cDisassembler()
Nyi("Fmt2 3 ZZ ope 6 loadb (rrp) disp20 4 src (rrp) 4 dest reg 20 src disp 4"),
Instr(Mnemonic.loadb, abs24_b, R4),
Nyi("Fmt2 3 ZZ ope 8 loadd (reg) disp20 4 src (reg) 4 dest rp 20 src disp 4"),
Instr(Mnemonic.loadd, rp_disp20_d, R4),
Instr(Mnemonic.loadd, rp_disp20_d, rp4),
Nyi("Fmt2 3 ZZ ope 10 loadd (rrp) disp20 4 src (rrp) 4 dest rp 20 src disp 4"),
Instr(Mnemonic.loadd, abs24_d, R4),
Instr(Mnemonic.loadd, abs24_d, rp4),
Nyi("Fmt2 3 ZZ ope 12 loadw (reg) disp20 4 src (reg) 4 dest reg 20 src disp 4"),
Instr(Mnemonic.loadw, rp_disp20_w, R4),
Nyi("Fmt2 3 ZZ ope 14 loadw (rrp) disp20 4 src (rrp) 4 dest reg 20 src disp 4"),
Expand Down Expand Up @@ -1033,15 +1033,15 @@ static Cr16cDisassembler()
Nyi("Fmt17 2 ZZ loadb(prp) disp14 4 src(prp) 4 dest reg 14 src disp"),
Nyi("Fmt17 2 ZZ loadd(prp) disp14 4 src(prp) 4 dest rp 14 src disp"),
Nyi("Fmt17 2 ZZ loadw(prp) disp14 4 src(prp) 4 dest reg 14 src disp")),
Instr(Mnemonic.loadd, abs20_d, R4),
Instr(Mnemonic.loadd, abs20_d, rp4),

Instr(Mnemonic.loadb, abs20_b, R4),
Instr(Mnemonic.loadw, abs20_w, R4),
Instr(Mnemonic.loadb, abs20_rel_b, R4),
Instr(Mnemonic.loadb, abs20_rel_b, R4),

Instr(Mnemonic.loadd, abs20_rel_d, R4),
Instr(Mnemonic.loadd, abs20_rel_d, R4),
Instr(Mnemonic.loadd, abs20_rel_d, rp4),
Instr(Mnemonic.loadd, abs20_rel_d, rp4),
Instr(Mnemonic.loadw, abs20_rel_w, R4),
Instr(Mnemonic.loadw, abs20_rel_w, R4));

Expand Down
26 changes: 19 additions & 7 deletions src/Arch/M68k/Rewriter.Alu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,25 +176,37 @@ public void RewriteExt()
{
PrimitiveType dtSrc;
PrimitiveType dtDst;
Identifier result;
var dReg = binder.EnsureRegister((RegisterStorage) instr.Operands[0]);
if (instr.DataWidth!.Size == 4)
{
dtSrc = PrimitiveType.Int16;
dtDst = PrimitiveType.Int32;
m.Assign(
dReg,
m.Convert(
m.Slice(dReg, dtSrc),
dtSrc, dtDst));
result = dReg;
}
else
{
dtSrc = PrimitiveType.SByte;
dtDst = PrimitiveType.Int16;
result = binder.CreateTemporary(dtDst);
m.Assign(result, m.Convert(
m.Slice(dReg, dtSrc),
dtSrc, dtDst));
m.Assign(
dReg,
m.Dpb(
dReg,
result,
0));
}
var dReg = binder.EnsureRegister((RegisterStorage) instr.Operands[0]);
m.Assign(
dReg,
m.Convert(
m.Slice(dReg, dtSrc),
dtSrc, dtDst));
m.Assign(
binder.EnsureFlagGroup(Registers.ZN),
m.Cond(dReg));
m.Cond(result));
}

public void RewriteExtb()
Expand Down
2 changes: 1 addition & 1 deletion src/Arch/M68k/Rewriter.Fpu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ private void RewriteFmovecr()
if (fpuRomConstants.TryGetValue(n, out double d))
{
src = Constant.Real64(d);
src.DataType = PrimitiveType.Real80;
src.DataType = PrimitiveType.Real96;
}
else
{
Expand Down
54 changes: 45 additions & 9 deletions src/Arch/MSP430/Msp430Rewriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ private Expression RewriteMovDst(MachineOperand op, Expression src)
}
else
{
src = MaybeExtend(src, dst.DataType);
m.Assign(dst, src);
}
return dst;
Expand All @@ -310,7 +311,7 @@ private Expression RewriteMovDst(MachineOperand op, Expression src)
{
ea = Address.Ptr16((ushort) mop.Offset);
}
m.Assign(m.Mem(mop.Width, ea), src);
m.Assign(m.Mem(mop.Width, ea), MaybeSlice(src, mop.Width));
return src;
case AddressOperand aop:
var mem = m.Mem(op.Width, aop.Address);
Expand All @@ -320,6 +321,8 @@ private Expression RewriteMovDst(MachineOperand op, Expression src)
throw new NotImplementedException($"Unknown operand type {op.GetType().Name} ({op})");
}



private void EmitCc(Expression exp, FlagGroupStorage? grf)
{
if (grf != null)
Expand All @@ -328,6 +331,34 @@ private void EmitCc(Expression exp, FlagGroupStorage? grf)
}
}


private Expression MaybeExtend(Expression exp, DataType dt)
{
if (dt.BitSize > exp.DataType.BitSize)
{
var tmp = binder.CreateTemporary(dt);
m.Assign(tmp, m.ExtendZ(exp, dt));
return tmp;
}
return exp;
}

private Expression MaybeSlice(Expression exp, DataType dt)
{
if (dt.BitSize < exp.DataType.BitSize)
{
var tmp = binder.CreateTemporary(dt);
m.Assign(tmp, m.Slice(exp, dt));
exp = tmp;
}
return exp;
}

private Constant WordAligned(DataType width)
{
return m.Int32(((width.Size + 1) / 2) * 2);
}

private void RewriteAdcSbc(Func<Expression, Expression, Expression> fn)
{
var c = binder.EnsureFlagGroup(this.arch.GetFlagGroup(arch.Registers.sr, (uint)FlagM.CF));
Expand Down Expand Up @@ -356,9 +387,12 @@ private void RewriteBinop(Func<Expression,Expression,Expression> fn, FlagGroupSt

private void RewriteBit()
{
var left = RewriteOp(instr.Operands[1]);
var right = RewriteOp(instr.Operands[0]);
var tmp = binder.CreateTemporary(instr.Operands[0].Width);
var op0 = instr.Operands[0];
var op1 = instr.Operands[1];
var dtResult = (op0.Width.BitSize < op1.Width.BitSize ? op1 : op0).Width;
var left = MaybeExtend(RewriteOp(op1), dtResult);
var right = MaybeExtend(RewriteOp(op0), dtResult);
var tmp = binder.CreateTemporary(dtResult);
var grf = binder.EnsureFlagGroup(arch.GetFlagGroup(arch.Registers.sr, (uint)(FlagM.NF | FlagM.ZF)));
var c = binder.EnsureFlagGroup(arch.GetFlagGroup(arch.Registers.sr, (uint)FlagM.CF));
var v = binder.EnsureFlagGroup(arch.GetFlagGroup(arch.Registers.sr, (uint)FlagM.VF));
Expand Down Expand Up @@ -459,8 +493,9 @@ private void RewritePopm()
var sp = binder.EnsureRegister(arch.Registers.sp);
while (c > 0)
{
m.Assign(binder.EnsureRegister(arch.Registers.GpRegisters[iReg]), m.Mem16(sp));
m.Assign(sp, m.IAdd(sp, m.Int32(2)));
var reg = arch.Registers.GpRegisters[iReg];
m.Assign(binder.EnsureRegister(reg), MaybeExtend(m.Mem16(sp), reg.DataType));
m.Assign(sp, m.IAdd(sp, WordAligned(reg.Width)));
++iReg;
--c;
}
Expand All @@ -470,7 +505,7 @@ private void RewritePush()
{
var src = RewriteOp(instr.Operands[0]);
var sp = binder.EnsureRegister(arch.Registers.sp);
m.Assign(sp, m.ISub(sp, m.Int32(2)));
m.Assign(sp, m.ISub(sp, WordAligned(src.DataType)));
m.Assign(m.Mem16(sp), src);
}

Expand All @@ -486,8 +521,9 @@ private void RewritePushm()
}
while (c > 0)
{
m.Assign(sp, m.ISub(sp, m.Int32(2)));
m.Assign(m.Mem16(sp), binder.EnsureRegister(arch.Registers.GpRegisters[iReg]));
var reg = arch.Registers.GpRegisters[iReg];
m.Assign(sp, m.ISub(sp, WordAligned(reg.Width)));
m.Assign(m.Mem(reg.DataType, sp), binder.EnsureRegister(reg));
--iReg;
--c;
}
Expand Down
4 changes: 2 additions & 2 deletions src/Arch/Padauk/PadaukRewriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ private Expression EmitAssignment(int iop, Expression src, Func<Expression, Expr
if (mem.Indirect)
{
ea = binder.CreateTemporary(PrimitiveType.Ptr16);
m.Assign(ea, m.Mem8(Address.Ptr16((ushort) mem.Offset)));
m.Assign(ea, m.Mem16(Address.Ptr16((ushort) mem.Offset)));
}
else
{
Expand Down Expand Up @@ -190,7 +190,7 @@ private Expression Op(int iop)
if (mem.Indirect)
{
var tmp = binder.CreateTemporary(PrimitiveType.Ptr16);
m.Assign(tmp, m.Mem8(Address.Ptr16((ushort) mem.Offset)));
m.Assign(tmp, m.Mem16(Address.Ptr16((ushort) mem.Offset)));
return m.Mem8(tmp);
}
else
Expand Down
2 changes: 1 addition & 1 deletion src/Arch/Qualcomm/HexagonDisassembler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3583,7 +3583,7 @@ static HexagonDisassembler()
/*
1,0,0,0, 0,0,1,1, I,I,I,s,s,s,s,s,P,P,j,j,j,j,j,j,I,I,I,x,x,x,x,x,"Rxx=insert(Rss,#u6,#U6)"
*/
var decoder_83 = Assign(RR0, Apply(Mnemonic.insert, R16, uw_8L6, uw_21L3_5L3));
var decoder_83 = Assign(RR0, Apply(Mnemonic.insert, RR16, uw_8L6, uw_21L3_5L3));
/*
1,0,0,0, 0,1,0,0, 0,0,-,s,s,s,s,s,P,P,-,-,-,-,-,-,0,0,-,d,d,d,d,d,"Rdd=vsxtbh(Rs)"
1,0,0,0, 0,1,0,0, 0,0,-,s,s,s,s,s,P,P,-,-,-,-,-,-,0,1,-,d,d,d,d,d,"Rdd=vzxtbh(Rs)"
Expand Down
9 changes: 5 additions & 4 deletions src/Arch/Qualcomm/HexagonRewriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ private void OperandDst(MachineOperand op, Action<Expression, Expression> write,
var dt = app.Width;
switch (app.Mnemonic)
{
case Mnemonic.abs: return m.Fn(CommonOps.Abs.MakeInstance(PrimitiveType.Int32), ops);
case Mnemonic.abs: return m.Fn(CommonOps.Abs.MakeInstance(PrimitiveType.Create(Domain.SignedInt, dt.BitSize)), ops);
case Mnemonic.add: return RewriteAdd(ops[0], ops[1]);
case Mnemonic.addasl: return RewriteAddAsl(ops[0], ops[1], ops[2]);
case Mnemonic.allocframe: RewriteAllocFrame(app.Operands[0]); return null;
Expand Down Expand Up @@ -405,7 +405,7 @@ private void OperandDst(MachineOperand op, Action<Expression, Expression> write,
case Mnemonic.extract: return RewriteExtract(Domain.SignedInt, ops[0], app.Operands);
case Mnemonic.extractu: return RewriteExtract(Domain.UnsignedInt, ops[0], app.Operands);
case Mnemonic.fastcorner9: return m.Fn(fastcorner9_intrinsic, ops);
case Mnemonic.insert: return m.FnVariadic(insert_intrinsic, ops);
case Mnemonic.insert: return m.FnVariadic(insert_intrinsic.MakeInstance(ops[0].DataType), ops);
case Mnemonic.immext: return null;
case Mnemonic.l2fetch: return RewriteL2Fetch(ops);
case Mnemonic.loop0: RewriteLoop(0, ops); return null;
Expand Down Expand Up @@ -823,10 +823,11 @@ private Expression RewriteVectorIntrinsic(IntrinsicProcedure intrinsic, Primitiv
private static readonly IntrinsicProcedure isync_intrinsic = IntrinsicBuilder.SideEffect("__isync")
.Void();
private static readonly IntrinsicProcedure insert_intrinsic = IntrinsicBuilder.Pure("__insert")
.Param(PrimitiveType.Word32)
.GenericTypes("T")
.Param("T")
.Param(PrimitiveType.Int32)
.Param(PrimitiveType.Int32)
.Returns(PrimitiveType.Word32);
.Returns("T");

private static readonly IntrinsicProcedure l2fetch_intrinsic = IntrinsicBuilder.SideEffect("__l2fetch")
.GenericTypes("T", "U")
Expand Down
11 changes: 6 additions & 5 deletions src/Arch/X86/Rewriter/X86Rewriter.Alu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -952,13 +952,14 @@ private void RewritePusha()

private void RewritePushf()
{
var flags = binder.EnsureFlagGroup(
Registers.eflags,
(uint) (FlagM.SF | FlagM.CF | FlagM.ZF | FlagM.DF | FlagM.OF | FlagM.PF),
"SCZDOP",
PrimitiveType.Byte);
RewritePush(
dasm.Current.dataWidth,
binder.EnsureFlagGroup(
Registers.eflags,
(uint)(FlagM.SF | FlagM.CF | FlagM.ZF | FlagM.DF | FlagM.OF | FlagM.PF),
"SCZDOP",
PrimitiveType.Byte));
flags);
}

private void RewriteNeg()
Expand Down
4 changes: 2 additions & 2 deletions src/Arch/X86/Rewriter/X86Rewriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1290,12 +1290,12 @@ static X86Rewriter()
.Returns("T");
sidt_intrinsic = new IntrinsicBuilder("__sidt", true)
.GenericTypes("T")
.Void();
.Returns("T");
significand_intrinsic = UnaryIntrinsic("__significand", PrimitiveType.Real64);
sin_intrinsic = UnaryIntrinsic("sin", PrimitiveType.Real64); //$REVIEW math.h
sldt_intrinsic = new IntrinsicBuilder("__sldt", true)
.GenericTypes("T")
.Void();
.Returns("T");
smsw_intrinsic = new IntrinsicBuilder("__smsw", true)
.GenericTypes("T")
.Returns("T");
Expand Down
5 changes: 4 additions & 1 deletion src/Core/ProcessorState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,10 @@ public Expression GetValue(MemoryAccess access, IMemory memory)
if (GetStackOffset(access.EffectiveAddress, out var stackOffset))
{
if (stackState.TryGetValue(stackOffset, out var value))
return value;
{
if (value.DataType.BitSize == access.DataType.BitSize)
return value;
}
}
return InvalidConstant.Create(access.DataType);
}
Expand Down
8 changes: 8 additions & 0 deletions src/Decompiler/Analysis/TrashedRegisterFinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,14 @@ public Expression GetValue(MemoryAccess access, IMemory memory)
var offset = this.GetFrameOffset(access.EffectiveAddress);
if (offset.HasValue && StackState.TryGetValue(offset.Value, out Expression? value))
{
if (value.DataType is StructureType str)
{
var ptrStr = new Pointer(str, access.EffectiveAddress.DataType.BitSize);
value = new MemoryAccess(
access.MemoryId,
new UnaryExpression(Operator.AddrOf, ptrStr, value),
access.DataType);
}
return value;
}
return InvalidConstant.Create(access.DataType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public virtual (Expression, bool) VisitConversion(Conversion conversion)
return (exp, true);
}
}
conversion = new Conversion(exp, exp.DataType, conversion.DataType);
conversion = new Conversion(exp, conversion.SourceDataType, conversion.DataType);
}
exp = convertConvertRule.Match(conversion);
if (exp is not null)
Expand Down
4 changes: 2 additions & 2 deletions src/Environments/Gameboy/GameboyRewriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -690,11 +690,11 @@ private void Rewrite_xor()
private readonly static IntrinsicProcedure reset_bit_intrinsic = new IntrinsicBuilder("__reset_bit", false)
.Param(PrimitiveType.Byte)
.Param(PrimitiveType.Byte)
.Returns(PrimitiveType.Bool);
.Returns(PrimitiveType.Byte);
private readonly static IntrinsicProcedure set_bit_intrinsic = new IntrinsicBuilder("__set_bit", false)
.Param(PrimitiveType.Byte)
.Param(PrimitiveType.Byte)
.Returns(PrimitiveType.Bool);
.Returns(PrimitiveType.Byte);
private readonly static IntrinsicProcedure stop_intrinsic = new IntrinsicBuilder("__stop", true, new ProcedureCharacteristics
{
Terminates = true
Expand Down
2 changes: 1 addition & 1 deletion src/UnitTests/Arch/CompactRisc/Cr16DisassemblerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ public void Cr16Dasm_loadb_rp()
[Test]
public void Cr16Dasm_loadd_abs20()
{
AssertCode("loadd\t(0x012345),r6", "61874523");
AssertCode("loadd\t(0x012345),(r7,r6)", "61874523");
}

[Test]
Expand Down
Loading

0 comments on commit 2e44fb5

Please sign in to comment.