blob: c8b67a6d8a0bff0195db657111254b726671b895 [file] [log] [blame]
// Copyright 2006 The Android Open Source Project
#ifndef OPCODE_H
#define OPCODE_H
#include <inttypes.h>
// Note: this list of opcodes must match the list used to initialize
// the opflags[] array in opcode.cpp.
enum Opcode {
OP_INVALID,
OP_UNDEFINED,
OP_ADC,
OP_ADD,
OP_AND,
OP_B,
OP_BL,
OP_BIC,
OP_BKPT,
OP_BLX,
OP_BX,
OP_CDP,
OP_CLZ,
OP_CMN,
OP_CMP,
OP_EOR,
OP_LDC,
OP_LDM,
OP_LDR,
OP_LDRB,
OP_LDRBT,
OP_LDRH,
OP_LDRSB,
OP_LDRSH,
OP_LDRT,
OP_MCR,
OP_MLA,
OP_MOV,
OP_MRC,
OP_MRS,
OP_MSR,
OP_MUL,
OP_MVN,
OP_ORR,
OP_PLD,
OP_RSB,
OP_RSC,
OP_SBC,
OP_SMLAL,
OP_SMULL,
OP_STC,
OP_STM,
OP_STR,
OP_STRB,
OP_STRBT,
OP_STRH,
OP_STRT,
OP_SUB,
OP_SWI,
OP_SWP,
OP_SWPB,
OP_TEQ,
OP_TST,
OP_UMLAL,
OP_UMULL,
// Define thumb opcodes
OP_THUMB_UNDEFINED,
OP_THUMB_ADC,
OP_THUMB_ADD,
OP_THUMB_AND,
OP_THUMB_ASR,
OP_THUMB_B,
OP_THUMB_BIC,
OP_THUMB_BKPT,
OP_THUMB_BL,
OP_THUMB_BLX,
OP_THUMB_BX,
OP_THUMB_CMN,
OP_THUMB_CMP,
OP_THUMB_EOR,
OP_THUMB_LDMIA,
OP_THUMB_LDR,
OP_THUMB_LDRB,
OP_THUMB_LDRH,
OP_THUMB_LDRSB,
OP_THUMB_LDRSH,
OP_THUMB_LSL,
OP_THUMB_LSR,
OP_THUMB_MOV,
OP_THUMB_MUL,
OP_THUMB_MVN,
OP_THUMB_NEG,
OP_THUMB_ORR,
OP_THUMB_POP,
OP_THUMB_PUSH,
OP_THUMB_ROR,
OP_THUMB_SBC,
OP_THUMB_STMIA,
OP_THUMB_STR,
OP_THUMB_STRB,
OP_THUMB_STRH,
OP_THUMB_SUB,
OP_THUMB_SWI,
OP_THUMB_TST,
OP_END // must be last
};
extern uint32_t opcode_flags[];
extern const char *opcode_names[];
// Define bit flags for the opcode categories
static const uint32_t kCatByte = 0x0001;
static const uint32_t kCatHalf = 0x0002;
static const uint32_t kCatWord = 0x0004;
static const uint32_t kCatLong = 0x0008;
static const uint32_t kCatNumBytes = (kCatByte | kCatHalf | kCatWord | kCatLong);
static const uint32_t kCatMultiple = 0x0010;
static const uint32_t kCatSigned = 0x0020;
static const uint32_t kCatLoad = 0x0040;
static const uint32_t kCatStore = 0x0080;
static const uint32_t kCatMemoryRef = (kCatLoad | kCatStore);
static const uint32_t kCatAlu = 0x0100;
static const uint32_t kCatBranch = 0x0200;
static const uint32_t kCatBranchLink = 0x0400;
static const uint32_t kCatBranchExch = 0x0800;
static const uint32_t kCatCoproc = 0x1000;
static const uint32_t kCatLoadMultiple = (kCatLoad | kCatMultiple);
static const uint32_t kCatStoreMultiple = (kCatStore | kCatMultiple);
inline bool isALU(Opcode op) { return (opcode_flags[op] & kCatAlu) != 0; }
inline bool isBranch(Opcode op) { return (opcode_flags[op] & kCatBranch) != 0; }
inline bool isBranchLink(Opcode op) {
return (opcode_flags[op] & kCatBranchLink) != 0;
}
inline bool isBranchExch(Opcode op) {
return (opcode_flags[op] & kCatBranchExch) != 0;
}
inline bool isLoad(Opcode op) { return (opcode_flags[op] & kCatLoad) != 0; }
inline bool isLoadMultiple(Opcode op) {
return (opcode_flags[op] & kCatLoadMultiple) == kCatLoadMultiple;
}
inline bool isStoreMultiple(Opcode op) {
return (opcode_flags[op] & kCatStoreMultiple) == kCatStoreMultiple;
}
inline bool isStore(Opcode op) { return (opcode_flags[op] & kCatStore) != 0; }
inline bool isSigned(Opcode op) { return (opcode_flags[op] & kCatSigned) != 0; }
inline bool isMemoryRef(Opcode op) {
return (opcode_flags[op] & kCatMemoryRef) != 0;
}
inline int getAccessSize(Opcode op) { return opcode_flags[op] & kCatNumBytes; }
inline bool isCoproc(Opcode op) { return (opcode_flags[op] & kCatCoproc) != 0; }
inline int getNumAccesses(Opcode op, uint32_t binary) {
extern int num_one_bits[];
int num_accesses = 0;
if (opcode_flags[op] & kCatNumBytes)
num_accesses = 1;
else if (opcode_flags[op] & kCatMultiple) {
num_accesses = num_one_bits[(binary >> 8) & 0xff]
+ num_one_bits[binary & 0xff];
}
return num_accesses;
}
#endif // OPCODE_H