-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathgalangarm7tdmi.h
More file actions
184 lines (165 loc) · 5.6 KB
/
galangarm7tdmi.h
File metadata and controls
184 lines (165 loc) · 5.6 KB
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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#ifndef GALANGARM7TDMI_H
#define GALANGARM7TDMI_H
#include "galanguage.h"
#include "gaparameter.h"
#include "gamnemonic.h"
/* ARM7TDMI is the 32-bit instruction set casually
* known as ARM32.
*
* Unique features:
* Variable length Thumb or Thumb2 instruction set when PC is odd.
* 4-bit condition code for each instruction, most significant nybble.
* Little and Big endian modes.
*
* Identification:
* Most significant nybble is most often E to always execute an extraction.
* Most significant nybble is never F, which is undefined.
* Many instructions are undefined.
*
*
* We subclass GAMnemonic to handle condition codes, which apply to all
* instructions on this architecture. GAParameterARM7TDMIReg represents
* a register, preferring to use sp/lr/pc to r13/r14/15,
* but accepting either.
*/
//Main language class for ARM7TDMI.
class GALangARM7TDMI : public GALanguage {
public:
GALangARM7TDMI();
//MVN and MOV ignore Op1.
QString dataopcodes[16]={
"and", "eor", "sub", "rsb",
"add", "adc", "sbc", "rsc",
"tst", "teq", "cmp", "cmn",
"orr", "mov", "bic", "mvn"
};
QString datahelp[16]={
"AND",
"XOR",
"Subtract",
"Reversed Subtract",
"Add",
"Add w/ Carry",
"Subtract w/ Carry",
"Reverse Subtract w/ Carry",
"AND, but result is not written.",
"EOR, but result is not written.",
"SUB, but result is not written.",
"ADD, but result is not written.",
"OR",
"Move", //Ignores Op1!
"Bit Clear",
"Not" //Ignores Op1!
};
};
/* ARM7TDMI instructions have an optional condition code,
* which comes after the verb name. We have to subclass GAMnemonic
* to implement it.
*/
class GAMnemonicARM7TDMI : public GAMnemonic {
public:
//Simple constructor.
GAMnemonicARM7TDMI(QString mnemonic,
uint32_t length, //Always 4.
const char *opcode,
//Optional arguments default to null.
const char *opcodemask=0,
const char *invertmask=0);
//Does the Mnemonic match bytes? If so, decode it.
int match(GAInstruction &ins, uint64_t adr, uint32_t &len,
const char *bytes) override;
//Does the Mnemonic match parameters? If so, encode it.
int match(GAInstruction &ins, uint64_t adr, QString verb,
QList<GAParserOperand> ops) override;
//Used for arm condition codes.
QString conditionString="";
uint8_t conditionCode=0xE;
const QString conditions[16]{
"eq", "ne", "cs", "cc",
"mi", "pl", "vs", "vc",
"hi", "ls", "ge", "lt",
"gt", "le", "al", "illegal"
};
GAParameterGroup* shift(); //ARM7TDMI shift parameter.
private:
bool hasShift=false; //Used to check that bit 7 is zero if bit4 is set.
};
//Represents an ARM register.
class GAParameterARM7TDMIReg : public GAParameter {
public:
GAParameterARM7TDMIReg(const char* mask, const char* dirmask=0);
int match(GAParserOperand *op, int len) override;
QString decode(GALanguage *lang, uint64_t adr, const char *bytes, int inslen) override;
void encode(GALanguage *lang,
uint64_t adr, QByteArray &bytes,
GAParserOperand op,
int inslen
) override;
private:
const QString regnames[19]={
"r0", "r1", "r2", "r3",
"r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11",
"r12",
"sp", //r13
"lr", //r14
"pc", //r15
"r13", "r14", "r15"
};
const char* dirmask=0;
};
/* Represents a shifted (non-immediate) alteration of Op2 of a data operation.
* This does not include the op2 source register. That is a separate field.
* See section 4.5.2.
*/
class GAParameterARM7TDMIShift : public GAParameter {
public:
GAParameterARM7TDMIShift(const char* mask="\xf0\x0f\x00\x00");
int match(GAParserOperand *op, int len) override;
QString decode(GALanguage *lang, uint64_t adr, const char *bytes, int inslen) override;
void encode(GALanguage *lang,
uint64_t adr, QByteArray &bytes,
GAParserOperand op,
int inslen
) override;
private:
uint8_t shiftregistermode=0; //Register or amount?
uint8_t shifttype=0xff; //Index in set below.
uint8_t shiftregister=0xff; //Which register?
uint8_t shiftamount=0xff; //5-bit amount.
const QString names[4]={
"lsl", "lsr", "asr", "ror"
};
const QString regnames[19]={
"r0", "r1", "r2", "r3",
"r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11",
"r12",
"sp", //r13
"lr", //r14
"pc", //r15
"r13", "r14", "r15"
};
};
/* Represents a rotated immediate from an ARM7TDMI data processing instruction.
* The low 8 bits represent the immediate value, and the upper 4 bits are the
* rotation.
*
* The rotation is in multiples of two bits. Is it applied by rotating the base
* to the right.
*/
class GAParameterARM7TDMIImmediate : public GAParameter
{
public:
GAParameterARM7TDMIImmediate(const char* mask="\xff\x0f\x00\x00");
int match(GAParserOperand *op, int len) override;
QString decode(GALanguage *lang, uint64_t adr, const char *bytes, int inslen) override;
void encode(GALanguage *lang,
uint64_t adr, QByteArray &bytes,
GAParserOperand op,
int inslen
) override;
uint32_t dec(uint64_t base, uint32_t rotate);
bool enc(uint32_t val, uint64_t *base, uint32_t *rotate);
};
#endif // GALANGARM7TDMI_H