fxos: improve analysis of move-register when value is known

This commit is contained in:
Lephenixnoir 2023-12-26 16:07:36 +01:00
parent eacdf9da99
commit 9b817fe808
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
5 changed files with 38 additions and 16 deletions

View File

@ -30,10 +30,7 @@ struct ProgramState
setBottom();
}
RelConst getRegister(int n) const
{
return ((unsigned)n >= 16) ? RelConstDomain().bottom() : m_regs[n];
}
RelConst getRegister(CpuRegister reg) const;
// TODO: More value in program state

View File

@ -89,7 +89,9 @@ public:
}
/* Get the register number for r0 ... r15, -1 for other registers. */
int getR() const;
int getRn() const;
/* Make an r0 ... r15 register name from its number. */
static CpuRegister makeRn(int n);
private:
CpuRegisterName m_name;
@ -160,7 +162,7 @@ struct AsmOperand
std::string str() const;
/* Is this operand a register? */
bool isReg() const
bool isRegister() const
{
return m_kind == Reg;
}

View File

@ -12,6 +12,14 @@
namespace FxOS {
RelConst ProgramState::getRegister(CpuRegister reg) const
{
int n = reg.getRn();
if(n >= 0)
return m_regs[n];
return RelConstDomain().top();
}
void ProgramState::setFunctionInit()
{
// TODO: Analysis: Set symbolic parameters at function entry
@ -45,8 +53,9 @@ void ProgramState::applyDiff(ProgramStateDiff const &diff)
case ProgramStateDiff::BaseType::RegisterUpdate: {
CpuRegister reg = diff.registerName();
if(reg.getR() >= 0)
m_regs[reg.getR()] = diff.registerValue();
int n = reg.getRn();
if(n >= 0)
m_regs[n] = diff.registerValue();
break;
}
}
@ -69,7 +78,7 @@ void ProgramState::joinWith(ProgramState const &other)
RelConstDomain RCD;
for(int i = 0; i < 16; i++) {
m_regs[i] = RCD.join(m_regs[i], other.getRegister(i));
m_regs[i] = RCD.join(m_regs[i], other.m_regs[i]);
}
}
@ -78,7 +87,7 @@ bool ProgramState::le(ProgramState const &other) const
RelConstDomain RCD;
for(int i = 0; i < 16; i++) {
if(!RCD.le(m_regs[i], other.getRegister(i)))
if(!RCD.le(m_regs[i], other.m_regs[i]))
return false;
}
return true;
@ -202,12 +211,16 @@ static ProgramStateDiff interpretInstruction(
AsmOperand src = asmins.operand(0);
AsmOperand dst = asmins.operand(1);
if(!dst.isReg())
if(!dst.isRegister())
diff.setNoOp();
else if(src.isConstant()) {
RelConst c = RCD.constant(computeConstantOperand(ins, src));
diff.setRegisterUpdate(dst.base(), c);
}
else if(src.isRegister()) {
RelConst v = PS.getRegister(src.base());
diff.setRegisterUpdate(dst.base(), v);
}
else
diff.setRegisterTouched(dst.base());
break;
@ -231,7 +244,7 @@ static ProgramStateDiff interpretInstruction(
case AsmInstruction::SH_shll16:
case AsmInstruction::SH_shlr16: {
AsmOperand op = asmins.operand(0);
assert(op.isReg());
assert(op.isRegister());
diff.setRegisterTouched(op.base());
break;
}

View File

@ -53,7 +53,7 @@ std::string CpuRegister::str() const noexcept
return regnames[i];
}
int CpuRegister::getR() const
int CpuRegister::getRn() const
{
if(m_name >= R0 && m_name <= R7)
return m_name - R0;
@ -63,6 +63,15 @@ int CpuRegister::getR() const
return -1;
}
CpuRegister CpuRegister::makeRn(int n)
{
assert(n >= 0 && n < 16 && "makeRn: invalid number");
CpuRegister r;
int name = (n >= 8) ? (R8 + (n - 8)) : (R0 + n);
r.m_name = static_cast<CpuRegisterName>(name);
return r;
}
//---
// Instruction operands
//---

View File

@ -246,7 +246,8 @@ static void viewProgramState(ProgramState const &PS, std::string lineStart)
RelConstDomain RCD;
std::cout << "\e[36m";
viewStrings(std::views::iota(0, 16) | std::views::transform([&](int i) {
return fmt::format("r{}:{}", i, PS.getRegister(i).str(false));
auto ri = CpuRegister::makeRn(i);
return fmt::format("r{}:{}", i, PS.getRegister(ri).str(false));
}),
opts);
std::cout << "\e[0m";
@ -306,8 +307,8 @@ void viewAssemblyInstruction(
case AsmInstruction::SH_jmp:
case AsmInstruction::SH_jsr:
if(PS) {
int n = ins.opcode().operand(0).base().getR();
RelConst target = PS->getRegister(n);
CpuRegister targetReg = ins.opcode().operand(0).base();
RelConst target = PS->getRegister(targetReg);
comments.emplace_back(
target.str(false), fmt::fg(fmt::terminal_color::yellow));
}