-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdataprocessing.c
236 lines (213 loc) · 7.08 KB
/
dataprocessing.c
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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
#include "dataprocessing.h"
/**
* Executes respective functions according to the OpCode
* @param reg First operand register
* @param op Second operand
* @return Result to be stored in the destination register
*/
uint32_t and(uint32_t reg, uint32_t op) {
return reg & op;
}
uint32_t eor(uint32_t reg, uint32_t op) {
return reg ^ op;
}
uint32_t sub(uint32_t reg, uint32_t op) {
return reg - op;
}
uint32_t add(uint32_t reg, uint32_t op) {
return reg + op;
}
uint32_t orr(uint32_t reg, uint32_t op) {
return reg | op;
}
/**
* Gets the last bit from the instruction
* @param result 32 bit instruction
* @return The last bit extended to 32 bits
*/
uint32_t getLastBit(uint32_t result) {
return getBits(result, LAST_BIT, ONE_BIT);
}
/**
* Selects which data processing instruction to execute and
* sets CPSR flags if needed
* @param registers Points to registers in the memory
* @param instruction 32-bit instruction
*/
void dataProcessing(uint32_t *registers, uint32_t instruction) {
uint32_t result;
uint32_t tempCarry;
switch (dataPInstr.opcode) {
case AND_OPCODE:
result = and(registers[dataPInstr.rn], instruction);
tempCarry = carryout;
registers[dataPInstr.rd] = result;
break;
case EOR_OPCODE:
result = eor(registers[dataPInstr.rn], instruction);
tempCarry = carryout;
registers[dataPInstr.rd] = result;
break;
case ORR_OPCODE:
result = orr(registers[dataPInstr.rn], instruction);
tempCarry = carryout;
registers[dataPInstr.rd] = result;
break;
case ADD_OPCODE:
result = add(registers[dataPInstr.rn], instruction);
tempCarry = getLastBit(result);
registers[dataPInstr.rd] = result;
break;
case SUB_OPCODE:
result = sub(registers[dataPInstr.rn], instruction);
tempCarry = (uint32_t) (getLastBit(result) == 0);
registers[dataPInstr.rd] = result;
break;
case RSB_OPCODE:
result = sub(instruction, registers[dataPInstr.rn]);
tempCarry = (uint32_t) (getLastBit(result) == 0);
registers[dataPInstr.rd] = result;
break;
case TST_OPCODE:
result = and(registers[dataPInstr.rn], instruction);
tempCarry = carryout;
break;
case TEQ_OPCODE:
result = eor(registers[dataPInstr.rn], instruction);
tempCarry = carryout;
break;
case CMP_OPCODE:
result = sub(registers[dataPInstr.rn], instruction);
tempCarry = (uint32_t) (getLastBit(result) == 0);
break;
case MOV_OPCODE:
result = instruction;
tempCarry = 0;
registers[dataPInstr.rd] = result;
break;
default:
return;
}
//if the S bit is 1
if (dataPInstr.s) {
registers[CPSR] = (uint32_t) (result == 0) << Z;
registers[CPSR] |= getLastBit(result) << N;
registers[CPSR] |= tempCarry << C;
}
}
/**
* Accepts the instruction as a string and calculates the binary
* format by parsing the string and executing the data processing
* instruction according to the given opcode
* @param instruction The instruction to be converted to binary
* @param address Keeps track of the current address
* of the instruction
* @return Binary form of the instruction
*/
uint32_t andAssembler(char *instruction, uint32_t address) {
char *savePtr;
char *destReg = strtok_r(instruction, ",", &savePtr);
uint32_t destRegIdx = readRegisterIndex(destReg);
char *regN = strtok_r(NULL, ",", &savePtr);
uint32_t regNIdx = readRegisterIndex(regN);
instr = DATAPROC_INSTR + (AND << OP_START) + (regNIdx << RN_START) +
(destRegIdx << RD_START);
readOperand2(savePtr);
return instr;
}
uint32_t eorAssembler(char *instruction, uint32_t address) {
char *savePtr;
char *destReg = strtok_r(instruction, ",", &savePtr);
uint32_t destRegIdx = readRegisterIndex(destReg);
char *regN = strtok_r(NULL, ",", &savePtr);
uint32_t regNIdx = readRegisterIndex(regN);
instr = DATAPROC_INSTR + (EOR << OP_START) + (regNIdx << RN_START) +
(destRegIdx << RD_START);
readOperand2(savePtr);
return instr;
}
uint32_t subAssembler(char *instruction, uint32_t address) {
char *savePtr;
char *destReg = strtok_r(instruction, ",", &savePtr);
uint32_t destRegIdx = readRegisterIndex(destReg);
char *regN = strtok_r(NULL, ",", &savePtr);
uint32_t regNIdx = readRegisterIndex(regN);
instr = DATAPROC_INSTR + (SUB << OP_START) + (regNIdx << RN_START) +
(destRegIdx << RD_START);
readOperand2(savePtr);
return instr;
}
uint32_t rsbAssembler(char *instruction, uint32_t address) {
char *savePtr;
char *destReg = strtok_r(instruction, ",", &savePtr);
uint32_t destRegIdx = readRegisterIndex(destReg);
char *regN = strtok_r(NULL, ",", &savePtr);
uint32_t regNIdx = readRegisterIndex(regN);
instr = DATAPROC_INSTR + (RSB << OP_START) + (regNIdx << RN_START) +
(destRegIdx << RD_START);
readOperand2(savePtr);
return instr;
}
uint32_t addAssembler(char *instruction, uint32_t address) {
char *savePtr;
char *destReg = strtok_r(instruction, ",", &savePtr);
uint32_t destRegIdx = readRegisterIndex(destReg);
char *regN = strtok_r(NULL, ",", &savePtr);
uint32_t regNIdx = readRegisterIndex(regN);
instr = DATAPROC_INSTR + (ADD << OP_START) + (regNIdx << RN_START) +
(destRegIdx << RD_START);
readOperand2(savePtr);
return instr;
}
uint32_t orrAssembler(char *instruction, uint32_t address) {
char *savePtr;
char *destReg = strtok_r(instruction, ",", &savePtr);
uint32_t destRegIdx = readRegisterIndex(destReg);
char *regN = strtok_r(NULL, ",", &savePtr);
uint32_t regNIdx = readRegisterIndex(regN);
instr = DATAPROC_INSTR + (ORR << OP_START) + (regNIdx << RN_START) +
(destRegIdx << RD_START);
readOperand2(savePtr);
return instr;
}
uint32_t tstAssembler(char *instruction, uint32_t address) {
char *savePtr;
char *regN = strtok_r(instruction, ",", &savePtr);
uint32_t regNIdx = readRegisterIndex(regN);
instr = DATAPROC_INSTR + (TST << OP_START) + (1 << SET_START) +
(regNIdx << RN_START);
readOperand2(savePtr);
return instr;
}
uint32_t teqAssembler(char *instruction, uint32_t address) {
char *savePtr;
char *regN = strtok_r(instruction, " ,", &savePtr);
uint32_t regNIdx = readRegisterIndex(regN);
instr = DATAPROC_INSTR + (TEQ << OP_START) + (1 << SET_START) +
(regNIdx << RN_START);
readOperand2(savePtr);
return instr;
}
uint32_t cmpAssembler(char *instruction, uint32_t address) {
char *savePtr;
char *regN = strtok_r(instruction, ",", &savePtr);
uint32_t regNIdx = readRegisterIndex(regN);
instr = DATAPROC_INSTR + (CMP << OP_START) + (1 << SET_START) +
(regNIdx << RN_START);
readOperand2(savePtr);
return instr;
}
uint32_t lslAssembler(char *instruction, uint32_t address) {
char *savePtr;
uint32_t regN = readRegisterIndex(strtok_r(instruction, ",", &savePtr));
char *expr = strtok_r(NULL, ",", &savePtr);
expr++;
instr = DATAPROC_INSTR + (MOV << OP_START) + (regN << RD_START) + regN;
uint32_t cnst = (uint32_t) strtol(expr, NULL, 0);
cnst &= MAX_CONST;
instr += cnst << SHIFT_INT;
return instr;
}
uint32_t andeqAssembler(char *instruction, uint32_t address) {
return 0;
}