aboutsummaryrefslogtreecommitdiffstats
path: root/emulator/qtools/opcode.h
blob: c8b67a6d8a0bff0195db657111254b726671b895 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// 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