Files
TheRock/rocm-systems/projects/rocprofiler-systems/external/dyninst/dataflowAPI/rose/semantics/BaseSemantics2.C
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

723 lines
27 KiB
C++

#include <algorithm>
#include "../util/StringUtility.h"
//#include "sage3basic.h"
#include "BaseSemantics2.h"
//#include "AsmUnparser_compat.h"
//#include "Diagnostics.h"
#include "RegisterStateGeneric.h"
#include "../util/Message.h"
namespace rose {
namespace BinaryAnalysis {
namespace InstructionSemantics2 {
using namespace Sawyer::Message::Common;
namespace BaseSemantics {
/*******************************************************************************************************************************
* Printing operator<<
*******************************************************************************************************************************/
std::ostream& operator<<(std::ostream &o, const Exception &x) {
x.print(o);
return o;
}
std::ostream& operator<<(std::ostream &o, const SValue &x) {
x.print(o);
return o;
}
std::ostream& operator<<(std::ostream &o, const SValue::WithFormatter &x)
{
x.print(o);
return o;
}
std::ostream& operator<<(std::ostream &o, const MemoryState &x) {
x.print(o);
return o;
}
std::ostream& operator<<(std::ostream &o, const MemoryState::WithFormatter &x)
{
x.print(o);
return o;
}
std::ostream& operator<<(std::ostream &o, const RegisterState &x) {
x.print(o);
return o;
}
std::ostream& operator<<(std::ostream &o, const RegisterState::WithFormatter &x)
{
x.print(o);
return o;
}
std::ostream& operator<<(std::ostream &o, const State &x) {
x.print(o);
return o;
}
std::ostream& operator<<(std::ostream &o, const State::WithFormatter &x)
{
x.print(o);
return o;
}
std::ostream& operator<<(std::ostream &o, const RiscOperators &x) {
x.print(o);
return o;
}
std::ostream& operator<<(std::ostream &o, const RiscOperators::WithFormatter &x)
{
x.print(o);
return o;
}
/*******************************************************************************************************************************
* Exceptions
*******************************************************************************************************************************/
void
Exception::print(std::ostream &o) const
{
o <<"rose::BinaryAnalysis::InstructionSemantics::BaseSemantics::Exception: " <<what();
//FIXME
//Some mechanism for printing the instruction here
//if (insn)
// o <<": " <<unparseInstructionWithAddress(insn);
o <<"\n";
}
/*******************************************************************************************************************************
* MemoryState
*******************************************************************************************************************************/
/*******************************************************************************************************************************
* State
*******************************************************************************************************************************/
void
State::clear() {
registers_->clear();
memory_->clear();
}
void
State::zero_registers() {
registers_->zero();
}
void
State::clear_memory() {
memory_->clear();
}
SValuePtr
State::readRegister(const RegisterDescriptor &desc, const SValuePtr &dflt, RiscOperators *ops) {
ASSERT_require(desc.is_valid());
ASSERT_not_null(dflt);
ASSERT_not_null(ops);
return registers_->readRegister(desc, dflt, ops);
}
void
State::writeRegister(const RegisterDescriptor &desc, const SValuePtr &value, RiscOperators *ops) {
ASSERT_require(desc.is_valid());
ASSERT_not_null(value);
ASSERT_not_null(ops);
registers_->writeRegister(desc, value, ops);
}
SValuePtr
State::readMemory(const SValuePtr &address, const SValuePtr &dflt, RiscOperators *addrOps, RiscOperators *valOps) {
ASSERT_not_null(address);
ASSERT_not_null(dflt);
ASSERT_not_null(addrOps);
ASSERT_not_null(valOps);
return memory_->readMemory(address, dflt, addrOps, valOps);
}
void
State::writeMemory(const SValuePtr &addr, const SValuePtr &value, RiscOperators *addrOps, RiscOperators *valOps) {
ASSERT_not_null(addr);
ASSERT_not_null(value);
ASSERT_not_null(addrOps);
ASSERT_not_null(valOps);
memory_->writeMemory(addr, value, addrOps, valOps);
}
void
State::printRegisters(std::ostream &stream, const std::string &prefix) {
Formatter fmt;
fmt.set_line_prefix(prefix);
printRegisters(stream, fmt);
}
void
State::printRegisters(std::ostream &stream, Formatter &fmt) const {
registers_->print(stream, fmt);
}
void
State::printMemory(std::ostream &stream, const std::string &prefix) const {
Formatter fmt;
fmt.set_line_prefix(prefix);
printMemory(stream, fmt);
}
void
State::printMemory(std::ostream &stream, Formatter &fmt) const {
memory_->print(stream, fmt);
}
bool
State::merge(const StatePtr &other, RiscOperators *ops) {
bool memoryChanged = memoryState()->merge(other->memoryState(), ops, ops);
bool registersChanged = registerState()->merge(other->registerState(), ops);
return memoryChanged || registersChanged;
}
void
State::print(std::ostream &stream, const std::string &prefix) const {
Formatter fmt;
fmt.set_line_prefix(prefix);
print(stream, fmt);
}
void
State::print(std::ostream &stream, Formatter &fmt) const
{
std::string prefix = fmt.get_line_prefix();
Indent indent(fmt);
stream <<prefix <<"registers:\n" <<(*registers_+fmt) <<prefix <<"memory:\n" <<(*memory_+fmt);
}
/*******************************************************************************************************************************
* RiscOperators
*******************************************************************************************************************************/
void
RiscOperators::startInstruction(SgAsmInstruction *insn) {
ASSERT_not_null(insn);
//FIXME
//Use fprintf/cout
//SAWYER_MESG(mlog[TRACE]) <<"starting instruction " <<unparseInstructionWithAddress(insn) <<"\n";
currentInsn_ = insn;
++nInsns_;
};
SValuePtr
RiscOperators::subtract(const SValuePtr &minuend, const SValuePtr &subtrahend) {
return add(minuend, negate(subtrahend));
}
SValuePtr
RiscOperators::equal(const SValuePtr &a, const SValuePtr &b) {
return isEqual(a, b);
}
SValuePtr
RiscOperators::isEqual(const SValuePtr &a, const SValuePtr &b) {
return equalToZero(xor_(a, b));
}
SValuePtr
RiscOperators::isNotEqual(const SValuePtr &a, const SValuePtr &b) {
return invert(isEqual(a, b));
}
SValuePtr
RiscOperators::isUnsignedLessThan(const SValuePtr &a, const SValuePtr &b) {
SValuePtr wideA = unsignedExtend(a, a->get_width()+1);
SValuePtr wideB = unsignedExtend(b, b->get_width()+1);
SValuePtr diff = subtract(wideA, wideB);
return extract(diff, diff->get_width()-1, diff->get_width()); // A < B iff sign(wideA - wideB) == -1
}
SValuePtr
RiscOperators::isUnsignedLessThanOrEqual(const SValuePtr &a, const SValuePtr &b) {
return or_(isUnsignedLessThan(a, b), isEqual(a, b));
}
SValuePtr
RiscOperators::isUnsignedGreaterThan(const SValuePtr &a, const SValuePtr &b) {
return invert(isUnsignedLessThanOrEqual(a, b));
}
SValuePtr
RiscOperators::isUnsignedGreaterThanOrEqual(const SValuePtr &a, const SValuePtr &b) {
return invert(isUnsignedLessThan(a, b));
}
SValuePtr
RiscOperators::isSignedLessThan(const SValuePtr &a, const SValuePtr &b) {
ASSERT_require(a->get_width() == b->get_width());
size_t nbits = a->get_width();
SValuePtr aIsNeg = extract(a, nbits-1, nbits);
SValuePtr bIsNeg = extract(b, nbits-1, nbits);
SValuePtr diff = subtract(signExtend(a, nbits+1), signExtend(b, nbits+1));
SValuePtr diffIsNeg = extract(diff, nbits, nbits+1); // sign bit
SValuePtr negPos = and_(aIsNeg, invert(bIsNeg)); // A is negative and B is non-negative?
SValuePtr sameSigns = invert(xor_(aIsNeg, bIsNeg)); // A and B are both negative or both non-negative?
SValuePtr result = or_(negPos, and_(sameSigns, diffIsNeg));
return result;
}
SValuePtr
RiscOperators::isSignedLessThanOrEqual(const SValuePtr &a, const SValuePtr &b) {
return or_(isSignedLessThan(a, b), isEqual(a, b));
}
SValuePtr
RiscOperators::isSignedGreaterThan(const SValuePtr &a, const SValuePtr &b) {
return invert(isSignedLessThanOrEqual(a, b));
}
SValuePtr
RiscOperators::isSignedGreaterThanOrEqual(const SValuePtr &a, const SValuePtr &b) {
return invert(isSignedLessThan(a, b));
}
SValuePtr
RiscOperators::fpFromInteger(const SValuePtr &/*intValue*/, SgAsmFloatType *fpType) {
ASSERT_not_null(fpType);
throw NotImplemented("fpFromInteger is not implemented", currentInstruction());
}
SValuePtr
RiscOperators::fpToInteger(const SValuePtr &/*fpValue*/, SgAsmFloatType *fpType, const SValuePtr &/*dflt*/) {
ASSERT_not_null(fpType);
throw NotImplemented("fpToInteger is not implemented", currentInstruction());
}
SValuePtr
RiscOperators::fpConvert(const SValuePtr &a, SgAsmFloatType *aType, SgAsmFloatType *retType) {
ASSERT_not_null(a);
ASSERT_not_null(aType);
ASSERT_not_null(retType);
if (aType == retType)
return a->copy();
throw NotImplemented("fpConvert is not implemented", currentInstruction());
}
SValuePtr
RiscOperators::fpIsNan(const SValuePtr &a, SgAsmFloatType *aType) {
// Value is NAN iff exponent bits are all set and significand is not zero.
ASSERT_not_null(a);
ASSERT_not_null(aType);
SValuePtr exponent = extract(a, aType->exponentBits().least(), aType->exponentBits().greatest()+1);
SValuePtr significand = extract(a, aType->significandBits().least(), aType->significandBits().greatest()+1);
return and_(equalToZero(invert(exponent)), invert(equalToZero(significand)));
}
SValuePtr
RiscOperators::fpIsDenormalized(const SValuePtr &a, SgAsmFloatType *aType) {
// Value is denormalized iff exponent is zero and significand is not zero.
ASSERT_not_null(a);
ASSERT_not_null(aType);
if (!aType->gradualUnderflow())
return boolean_(false);
SValuePtr exponent = extract(a, aType->exponentBits().least(), aType->exponentBits().greatest()+1);
SValuePtr significand = extract(a, aType->significandBits().least(), aType->significandBits().greatest()+1);
return and_(equalToZero(exponent), invert(equalToZero(significand)));
}
SValuePtr
RiscOperators::fpIsZero(const SValuePtr &a, SgAsmFloatType *aType) {
// Value is zero iff exponent and significand are both zero.
ASSERT_not_null(a);
ASSERT_not_null(aType);
SValuePtr exponent = extract(a, aType->exponentBits().least(), aType->exponentBits().greatest()+1);
SValuePtr significand = extract(a, aType->significandBits().least(), aType->significandBits().greatest()+1);
return and_(equalToZero(exponent), equalToZero(significand));
}
SValuePtr
RiscOperators::fpIsInfinity(const SValuePtr &a, SgAsmFloatType *aType) {
// Value is infinity iff exponent bits are all set and significand is zero.
ASSERT_not_null(a);
ASSERT_not_null(aType);
SValuePtr exponent = extract(a, aType->exponentBits().least(), aType->exponentBits().greatest()+1);
SValuePtr significand = extract(a, aType->significandBits().least(), aType->significandBits().greatest()+1);
return and_(equalToZero(invert(exponent)), equalToZero(significand));
}
SValuePtr
RiscOperators::fpSign(const SValuePtr &a, SgAsmFloatType *aType) {
ASSERT_not_null(a);
ASSERT_not_null(aType);
return extract(a, aType->signBit(), aType->signBit()+1);
}
SValuePtr
RiscOperators::fpEffectiveExponent(const SValuePtr &a, SgAsmFloatType *aType) {
ASSERT_not_null(a);
ASSERT_not_null(aType);
size_t expWidth = aType->exponentBits().size() + 1; // add a sign bit to the beginning
SValuePtr storedExponent = extract(a, aType->exponentBits().least(), aType->exponentBits().greatest()+1);
SValuePtr significand = extract(a, aType->significandBits().least(), aType->significandBits().greatest()+1);
SValuePtr retval = ite(equalToZero(storedExponent),
ite(equalToZero(significand),
// Stored exponent and significand are both zero, therefore value is zero
number_(expWidth, 0), // value is zero, therefore exponent is zero
// Stored exponent is zero but significand is not, therefore denormalized number.
// effective exponent is 1 - bias - (significandWidth - mssb(significand))
add(number_(expWidth, 1 - aType->exponentBias() - aType->significandBits().size()),
unsignedExtend(mostSignificantSetBit(significand), expWidth))),
// Stored exponent is non-zero so significand is normalized. Effective exponent is the stored
// exponent minus the bias.
subtract(unsignedExtend(storedExponent, expWidth),
number_(expWidth, aType->exponentBias())));
return retval;
}
SValuePtr
RiscOperators::fpAdd(const SValuePtr &/*a*/, const SValuePtr &/*b*/, SgAsmFloatType */*fpType*/) {
throw NotImplemented("fpAdd is not implemented", currentInstruction());
}
SValuePtr
RiscOperators::fpSubtract(const SValuePtr &/*a*/, const SValuePtr &/*b*/, SgAsmFloatType */*fpType*/) {
throw NotImplemented("fpSubtract is not implemented", currentInstruction());
}
SValuePtr
RiscOperators::fpMultiply(const SValuePtr &/*a*/, const SValuePtr &/*b*/, SgAsmFloatType */*fpType*/) {
throw NotImplemented("fpMultiply is not implemented", currentInstruction());
}
SValuePtr
RiscOperators::fpDivide(const SValuePtr &/*a*/, const SValuePtr &/*b*/, SgAsmFloatType */*fpType*/) {
throw NotImplemented("fpDivide is not implemented", currentInstruction());
}
SValuePtr
RiscOperators::fpSquareRoot(const SValuePtr &/*a*/, SgAsmFloatType */*aType*/) {
throw NotImplemented("fpSquareRoot is not implemented", currentInstruction());
}
SValuePtr
RiscOperators::fpRoundTowardZero(const SValuePtr &/*a*/, SgAsmFloatType */*aType*/) {
throw NotImplemented("fpRoundTowardZero is not implemented", currentInstruction());
}
SValuePtr
RiscOperators::readRegister(const RegisterDescriptor &reg, const SValuePtr &dflt_) {
SValuePtr dflt = dflt_;
ASSERT_not_null(currentState_);
ASSERT_not_null(dflt);
// If there's an lazily-updated initial state, then get its register, updating the initial state as a side effect.
if (initialState_)
dflt = initialState()->readRegister(reg, dflt, this);
return currentState_->readRegister(reg, dflt, this);
}
/*******************************************************************************************************************************
* Dispatcher
*******************************************************************************************************************************/
void
Dispatcher::advanceInstructionPointer(SgAsmInstruction *insn) {
RegisterDescriptor ipReg = instructionPointerRegister();
size_t nBits = ipReg.get_nbits();
BaseSemantics::SValuePtr ipValue;
if (!autoResetInstructionPointer_ && operators->currentState() && operators->currentState()->registerState()) {
BaseSemantics::RegisterStateGenericPtr grState =
dyncompat::dynamic_pointer_cast<BaseSemantics::RegisterStateGeneric>(operators->currentState()->registerState());
if (grState && grState->is_partly_stored(ipReg))
ipValue = operators->readRegister(ipReg);
}
if (!ipValue)
ipValue = operators->number_(nBits, insn->get_address());
ipValue = operators->add(ipValue, operators->number_(nBits, insn->get_size()));
operators->writeRegister(ipReg, ipValue);
}
void
Dispatcher::addressWidth(size_t nBits) {
ASSERT_require2(nBits==addrWidth_ || addrWidth_==0, "address width cannot be changed once it is set");
addrWidth_ = nBits;
}
void
Dispatcher::processInstruction(SgAsmInstruction *insn)
{
operators->startInstruction(insn);
InsnProcessor *iproc = iproc_lookup(insn);
try {
if (!iproc)
throw Exception("no dispatch ability for instruction", insn);
iproc->process(shared_from_this(), insn);
} catch (Exception &e) {
// If the exception was thrown by something that didn't have an instruction available, then add the instruction
if (!e.insn)
e.insn = insn;
throw e;
}
operators->finishInstruction(insn);
}
InsnProcessor *
Dispatcher::iproc_lookup(SgAsmInstruction *insn)
{
int key = iproc_key(insn);
ASSERT_require(key>=0);
return iproc_get(key);
}
void
Dispatcher::iproc_replace(SgAsmInstruction *insn, InsnProcessor *iproc)
{
iproc_set(iproc_key(insn), iproc);
}
void
Dispatcher::iproc_set(int key, InsnProcessor *iproc)
{
ASSERT_require(key>=0);
if ((size_t)key>=iproc_table.size())
iproc_table.resize(key+1, NULL);
iproc_table[key] = iproc;
}
InsnProcessor *
Dispatcher::iproc_get(int key)
{
if (key<0 || (size_t)key>=iproc_table.size())
return NULL;
return iproc_table[key];
}
const RegisterDescriptor &
Dispatcher::findRegister(const std::string &regname, size_t nbits/*=0*/, bool allowMissing) const
{
const RegisterDictionary *regdict = get_register_dictionary();
if (!regdict)
throw Exception("no register dictionary", currentInstruction());
const RegisterDescriptor *reg = regdict->lookup(regname);
if (!reg) {
if (allowMissing) {
static const RegisterDescriptor invalidRegister;
return invalidRegister;
}
std::ostringstream ss;
ss <<"Invalid register \"" <<regname <<"\" in dictionary \"" <<regdict->get_architecture_name() <<"\"";
throw Exception(ss.str(), currentInstruction());
}
if (nbits>0 && reg->get_nbits()!=nbits) {
std::ostringstream ss;
ss <<"Invalid " <<nbits <<"-bit register: \"" <<regname <<"\" is "
<<reg->get_nbits() <<" " <<(1==reg->get_nbits()?"byte":"bytes");
throw Exception(ss.str(), currentInstruction());
}
return *reg;
}
void
Dispatcher::decrementRegisters(SgAsmExpression */*e*/)
{
/*struct T1: AstSimpleProcessing {
RiscOperatorsPtr ops;
T1(const RiscOperatorsPtr &ops): ops(ops) {}
void visit(SgNode *node) {
if (SgAsmRegisterReferenceExpression *rre = isSgAsmRegisterReferenceExpression(node)) {
const RegisterDescriptor &reg = rre->get_descriptor();
if (rre->get_adjustment() < 0) {
SValuePtr adj = ops->number_(64, (int64_t)rre->get_adjustment());
if (reg.get_nbits() <= 64) {
adj = ops->unsignedExtend(adj, reg.get_nbits()); // truncate
} else {
adj = ops->signExtend(adj, reg.get_nbits()); // extend
}
ops->writeRegister(reg, ops->add(ops->readRegister(reg), adj));
}
}
}
} t1(operators);
t1.traverse(e, preorder);*/
}
void
Dispatcher::incrementRegisters(SgAsmExpression */*e*/)
{
/*struct T1: AstSimpleProcessing {
RiscOperatorsPtr ops;
T1(const RiscOperatorsPtr &ops): ops(ops) {}
void visit(SgNode *node) {
if (SgAsmRegisterReferenceExpression *rre = isSgAsmRegisterReferenceExpression(node)) {
const RegisterDescriptor &reg = rre->get_descriptor();
if (rre->get_adjustment() > 0) {
SValuePtr adj = ops->unsignedExtend(ops->number_(64, (int64_t)rre->get_adjustment()), reg.get_nbits());
ops->writeRegister(reg, ops->add(ops->readRegister(reg), adj));
}
}
}
} t1(operators);
t1.traverse(e, preorder);*/
}
SValuePtr
Dispatcher::effectiveAddress(SgAsmExpression *e, size_t nbits/*=0*/)
{
BaseSemantics::SValuePtr retval;
#if 1 // DEBUGGING [Robb P. Matzke 2015-08-04]
ASSERT_always_require(retval==NULL);
#endif
if (0==nbits)
nbits = addressWidth();
if (SgAsmMemoryReferenceExpression *mre = isSgAsmMemoryReferenceExpression(e)) {
retval = effectiveAddress(mre->get_address(), nbits);
} else if (SgAsmRegisterReferenceExpression *rre = isSgAsmRegisterReferenceExpression(e)) {
const RegisterDescriptor &reg = rre->get_descriptor();
retval = operators->readRegister(reg);
} else if (SgAsmBinaryAdd *op = isSgAsmBinaryAdd(e)) {
BaseSemantics::SValuePtr lhs = effectiveAddress(op->get_lhs(), nbits);
BaseSemantics::SValuePtr rhs = effectiveAddress(op->get_rhs(), nbits);
retval = operators->add(lhs, rhs);
} else if (SgAsmBinaryMultiply *op = isSgAsmBinaryMultiply(e)) {
BaseSemantics::SValuePtr lhs = effectiveAddress(op->get_lhs(), nbits);
BaseSemantics::SValuePtr rhs = effectiveAddress(op->get_rhs(), nbits);
retval = operators->unsignedMultiply(lhs, rhs);
} else if (SgAsmIntegerValueExpression *ival = isSgAsmIntegerValueExpression(e)) {
retval = operators->number_(ival->get_significantBits(), ival->get_value());
}
ASSERT_not_null(retval);
if (retval->get_width() < nbits) {
retval = operators->signExtend(retval, nbits);
} else if (retval->get_width() > nbits) {
retval = operators->extract(retval, 0, nbits);
}
return retval;
}
RegisterDescriptor
Dispatcher::segmentRegister(SgAsmMemoryReferenceExpression *mre)
{
if (mre!=NULL && mre->get_segment()!=NULL) {
if (SgAsmRegisterReferenceExpression *rre = isSgAsmRegisterReferenceExpression(mre->get_segment())) {
return rre->get_descriptor();
}
}
return RegisterDescriptor();
}
void
Dispatcher::write(SgAsmExpression *e, const SValuePtr &value, size_t addr_nbits/*=0*/)
{
ASSERT_not_null(e);
ASSERT_not_null(value);
if (SgAsmDirectRegisterExpression *re = isSgAsmDirectRegisterExpression(e)) {
operators->writeRegister(re->get_descriptor(), value);
} else if (SgAsmIndirectRegisterExpression *re = isSgAsmIndirectRegisterExpression(e)) {
SValuePtr offset = operators->readRegister(re->get_offset());
if (!offset->is_number()) {
std::string offset_name = get_register_dictionary()->lookup(re->get_offset());
offset_name = offset_name.empty() ? "" : "(" + offset_name + ") ";
throw Exception("indirect register offset " + offset_name + "must have a concrete value", NULL);
}
size_t idx = (offset->get_number() + re->get_index()) % re->get_modulus();
RegisterDescriptor reg = re->get_descriptor();
reg.set_major(reg.get_major() + re->get_stride().get_major() * idx);
reg.set_minor(reg.get_minor() + re->get_stride().get_minor() * idx);
reg.set_offset(reg.get_offset() + re->get_stride().get_offset() * idx);
reg.set_nbits(reg.get_nbits() + re->get_stride().get_nbits() * idx);
operators->writeRegister(reg, value);
} else if (SgAsmMemoryReferenceExpression *mre = isSgAsmMemoryReferenceExpression(e)) {
SValuePtr addr = effectiveAddress(mre, addr_nbits);
ASSERT_require(0==addrWidth_ || addr->get_width()==addrWidth_);
operators->writeMemory(segmentRegister(mre), addr, value, operators->boolean_(true));
} else {
ASSERT_not_implemented("[Robb P. Matzke 2014-10-07]");
}
}
SValuePtr
Dispatcher::read(SgAsmExpression *e, size_t value_nbits/*=0*/, size_t addr_nbits/*=0*/)
{
ASSERT_not_null(e);
if (0 == value_nbits) {
SgAsmType *expr_type = e->get_type();
ASSERT_not_null(expr_type);
value_nbits = expr_type->get_nBits();
ASSERT_require(value_nbits != 0);
}
SValuePtr retval;
if (SgAsmDirectRegisterExpression *re = isSgAsmDirectRegisterExpression(e)) {
retval = operators->readRegister(re->get_descriptor());
} else if (SgAsmIndirectRegisterExpression *re = isSgAsmIndirectRegisterExpression(e)) {
SValuePtr offset = operators->readRegister(re->get_offset());
if (!offset->is_number()) {
std::string offset_name = get_register_dictionary()->lookup(re->get_offset());
offset_name = offset_name.empty() ? "" : "(" + offset_name + ") ";
throw Exception("indirect register offset " + offset_name + "must have a concrete value", NULL);
}
size_t idx = (offset->get_number() + re->get_index()) % re->get_modulus();
RegisterDescriptor reg = re->get_descriptor();
reg.set_major(reg.get_major() + re->get_stride().get_major() * idx);
reg.set_minor(reg.get_minor() + re->get_stride().get_minor() * idx);
reg.set_offset(reg.get_offset() + re->get_stride().get_offset() * idx);
reg.set_nbits(reg.get_nbits() + re->get_stride().get_nbits() * idx);
retval = operators->readRegister(reg);
} else if (SgAsmMemoryReferenceExpression *mre = isSgAsmMemoryReferenceExpression(e)) {
BaseSemantics::SValuePtr addr = effectiveAddress(mre, addr_nbits);
ASSERT_require(0==addrWidth_ || addr->get_width()==addrWidth_);
BaseSemantics::SValuePtr dflt = undefined_(value_nbits);
retval = operators->readMemory(segmentRegister(mre), addr, dflt, operators->boolean_(true));
} else if (SgAsmValueExpression *ve = isSgAsmValueExpression(e)) {
uint64_t val = SageInterface::getAsmSignedConstant(ve);
retval = operators->number_(value_nbits, val);
} else if (SgAsmBinaryAdd *sum = isSgAsmBinaryAdd(e)) {
SgAsmExpression *lhs = sum->get_lhs();
SgAsmExpression *rhs = sum->get_rhs();
size_t nbits = std::max(lhs->get_nBits(), rhs->get_nBits());
retval = operators->add(operators->signExtend(read(lhs, lhs->get_nBits(), addr_nbits), nbits),
operators->signExtend(read(rhs, rhs->get_nBits(), addr_nbits), nbits));
} else if (SgAsmBinaryMultiply *product = isSgAsmBinaryMultiply(e)) {
SgAsmExpression *lhs = product->get_lhs();
SgAsmExpression *rhs = product->get_rhs();
retval = operators->unsignedMultiply(read(lhs, lhs->get_nBits()), read(rhs, rhs->get_nBits()));
} else if (SgAsmBinaryLsl *lshift = isSgAsmBinaryLsl(e)) {
SgAsmExpression *lhs = lshift->get_lhs();
SgAsmExpression *rhs = lshift->get_rhs();
size_t nbits = std::max(lhs->get_nBits(), rhs->get_nBits());
retval = operators->shiftLeft(read(lhs, lhs->get_nBits()), read(rhs, rhs->get_nBits()));
} else if(SgAsmBinaryAsr *asr = isSgAsmBinaryAsr(e)) {
SgAsmExpression *lhs = asr->get_lhs();
SgAsmExpression *rhs = asr->get_rhs();
retval = operators->shiftRightArithmetic(read(lhs, lhs->get_nBits()), read(rhs, rhs->get_nBits()));
} else if(SgAsmBinaryLsr *lsr = isSgAsmBinaryLsr(e)) {
SgAsmExpression *lhs = lsr->get_lhs();
SgAsmExpression *rhs = lsr->get_rhs();
retval = operators->shiftRight(read(lhs, lhs->get_nBits()), read(rhs, rhs->get_nBits()));
} else {
ASSERT_not_implemented(e->class_name());
}
// Make sure the return value is the requested width. The unsignedExtend() can expand or shrink values.
ASSERT_not_null(retval);
if (retval->get_width()!=value_nbits)
retval = operators->unsignedExtend(retval, value_nbits);
return retval;
}
} // namespace
} // namespace
} // namespace
} // namespace