-/* Copyright (c) 2007-2008 The Florida State University
+/*
+ * Copyright (c) 2010 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * Copyright (c) 2007-2008 The Florida State University
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
bool shift_carry_rs(uint32_t base, uint32_t shamt,
uint32_t type, uint32_t cfval) const;
- bool arm_add_carry(int32_t result, int32_t lhs, int32_t rhs) const;
- bool arm_sub_carry(int32_t result, int32_t lhs, int32_t rhs) const;
-
- bool arm_add_overflow(int32_t result, int32_t lhs, int32_t rhs) const;
- bool arm_sub_overflow(int32_t result, int32_t lhs, int32_t rhs) const;
-
// Constructor
- ArmStaticInst(const char *mnem, MachInst _machInst, OpClass __opClass)
+ ArmStaticInst(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass)
: StaticInst(mnem, _machInst, __opClass)
{
}
void printMemSymbol(std::ostream &os, const SymbolTable *symtab,
const std::string &prefix, const Addr addr,
const std::string &suffix) const;
+ void printShiftOperand(std::ostream &os, IntRegIndex rm,
+ bool immShift, uint32_t shiftAmt,
+ IntRegIndex rs, ArmShiftType type) const;
+ void printDataInst(std::ostream &os, bool withImm) const;
+ void printDataInst(std::ostream &os, bool withImm, bool immShift, bool s,
+ IntRegIndex rd, IntRegIndex rn, IntRegIndex rm,
+ IntRegIndex rs, uint32_t shiftAmt, ArmShiftType type,
+ uint32_t imm) const;
+
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+
+ static uint32_t
+ cpsrWriteByInstr(CPSR cpsr, uint32_t val,
+ uint8_t byteMask, bool affectState)
+ {
+ bool privileged = (cpsr.mode != MODE_USER);
+
+ uint32_t bitMask = 0;
+
+ if (bits(byteMask, 3)) {
+ unsigned lowIdx = affectState ? 24 : 27;
+ bitMask = bitMask | mask(31, lowIdx);
+ }
+ if (bits(byteMask, 2)) {
+ bitMask = bitMask | mask(19, 16);
+ }
+ if (bits(byteMask, 1)) {
+ unsigned highIdx = affectState ? 15 : 9;
+ unsigned lowIdx = privileged ? 8 : 9;
+ bitMask = bitMask | mask(highIdx, lowIdx);
+ }
+ if (bits(byteMask, 0)) {
+ if (privileged) {
+ bitMask = bitMask | mask(7, 6);
+ bitMask = bitMask | mask(5);
+ }
+ if (affectState)
+ bitMask = bitMask | (1 << 5);
+ }
+
+ return ((uint32_t)cpsr & ~bitMask) | (val & bitMask);
+ }
+
+ static uint32_t
+ spsrWriteByInstr(uint32_t spsr, uint32_t val,
+ uint8_t byteMask, bool affectState)
+ {
+ uint32_t bitMask = 0;
+
+ if (bits(byteMask, 3))
+ bitMask = bitMask | mask(31, 24);
+ if (bits(byteMask, 2))
+ bitMask = bitMask | mask(19, 16);
+ if (bits(byteMask, 1))
+ bitMask = bitMask | mask(15, 8);
+ if (bits(byteMask, 0))
+ bitMask = bitMask | mask(7, 0);
+
+ return ((spsr & ~bitMask) | (val & bitMask));
+ }
+
+ template<class XC>
+ static Addr
+ readPC(XC *xc)
+ {
+ Addr pc = xc->readPC();
+ Addr tBit = pc & (ULL(1) << PcTBitShift);
+ if (tBit)
+ return pc + 4;
+ else
+ return pc + 8;
+ }
+
+ // Perform an regular branch.
+ template<class XC>
+ static void
+ setNextPC(XC *xc, Addr val)
+ {
+ xc->setNextPC((xc->readNextPC() & PcModeMask) |
+ (val & ~PcModeMask));
+ }
+
+ // Perform an interworking branch.
+ template<class XC>
+ static void
+ setIWNextPC(XC *xc, Addr val)
+ {
+ Addr stateBits = xc->readPC() & PcModeMask;
+ Addr jBit = (ULL(1) << PcJBitShift);
+ Addr tBit = (ULL(1) << PcTBitShift);
+ bool thumbEE = (stateBits == (tBit | jBit));
+
+ Addr newPc = (val & ~PcModeMask);
+ if (thumbEE) {
+ if (bits(newPc, 0)) {
+ warn("Bad thumbEE interworking branch address %#x.\n", newPc);
+ } else {
+ newPc = newPc & ~mask(1);
+ }
+ } else {
+ if (bits(newPc, 0)) {
+ stateBits = tBit;
+ newPc = newPc & ~mask(1);
+ } else if (!bits(newPc, 1)) {
+ stateBits = 0;
+ } else {
+ warn("Bad interworking branch address %#x.\n", newPc);
+ }
+ }
+ newPc = newPc | stateBits;
+ xc->setNextPC(newPc);
+ }
+
+ // Perform an interworking branch in ARM mode, a regular branch
+ // otherwise.
+ template<class XC>
+ static void
+ setAIWNextPC(XC *xc, Addr val)
+ {
+ Addr stateBits = xc->readPC() & PcModeMask;
+ Addr jBit = (ULL(1) << PcJBitShift);
+ Addr tBit = (ULL(1) << PcTBitShift);
+ if (!jBit && !tBit) {
+ setIWNextPC(xc, val);
+ } else {
+ setNextPC(xc, val);
+ }
+ }
};
}