summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/hsail/operand.hh14
1 files changed, 12 insertions, 2 deletions
diff --git a/src/arch/hsail/operand.hh b/src/arch/hsail/operand.hh
index 4d981ee00..3fbb0991a 100644
--- a/src/arch/hsail/operand.hh
+++ b/src/arch/hsail/operand.hh
@@ -591,7 +591,7 @@ class AddrOperandBase : public BaseOperand
virtual void calcVector(Wavefront *w, std::vector<Addr> &addrVec) = 0;
virtual uint64_t calcLane(Wavefront *w, int lane=0) = 0;
- uint64_t offset;
+ int64_t offset;
const char *name = nullptr;
StorageElement *storageElement;
};
@@ -627,14 +627,24 @@ RegAddrOperand<RegOperandType>::init(unsigned opOffset, const BrigObject *obj)
const BrigOperandAddress *op = (BrigOperandAddress*)baseOp;
storageElement = nullptr;
- offset = (uint64_t(op->offset.hi) << 32) | uint64_t(op->offset.lo);
reg.init(op->reg, obj);
if (reg.regFileChar == 's') {
+ // if the address expression is 32b, then the hi
+ // bits of the offset must be set to 0 in the BRIG
+ assert(!op->offset.hi);
+ /**
+ * the offset field of an HSAIL instruction may be negative
+ * so here we cast the raw bits we get from the BRIG file to
+ * a signed type to avoid address calculation errors
+ */
+ offset = (int32_t)(op->offset.lo);
reg.regOperandSize = sizeof(uint32_t);
registerType = Enums::RT_VECTOR;
}
else if (reg.regFileChar == 'd') {
+ offset = (int64_t)(((uint64_t)(op->offset.hi) << 32)
+ | (uint64_t)(op->offset.lo));
reg.regOperandSize = sizeof(uint64_t);
registerType = Enums::RT_VECTOR;
}