-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdecode.c
341 lines (305 loc) · 11 KB
/
decode.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
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
/*
* File: decode.c
* Description: Module responsible for decoding instructions in the XM-23p Emulator.
* It extracts opcode and operands from instructions and gives them an internal exec. number.
*
* Author: Abdulla Sadoun
*
* - Date: 26/06/2024
*
*/
#include "xm23p.h"
unsigned short BreakpointValue; // breakpoint value (global variable)
#define LTCASE 0x7
#define STCASE 0x6
#define SUB_LD 0x0
#define MOV_CLRCC 0x3
#define LCEX 0x4
#define OFFBIT 6
int decode(){ // decode function
/*
function to decode the instruction
- it decodes the instruction based on the opcode
- it returns an number indicating the internal instruction
number for the execute function
- it decodes in layers to distinguish and seperate functions
*/
enum { BLCase, BEQtoBRA, ADDtoST, MOVLtoMOVH, LLDR1, LLDR2, LSTR1, LSTR2}; // grouped into shared first 3 bits
/*if((E_Start_Addresses-2) == BreakpointValue){ // extra breakpoint check
printf("Breakpoint reached3\n");
return Error;
}
if((RegistersValue[PC]) == BreakpointValue){ // extra breakpoint check
printf("Breakpoint reached4\n");
return Error;
}*/
//printf("decoded@%x instruction:%x ", (int) RegistersValue[PC]-2, IMARValue); // debugger printf
unsigned short opcode = ((IMARValue>>13)&0x07); // get first 3 bits of the instruction
offsetbuff = ((IMARValue>>7)&0x7f); // get the offset bit (LDR-STR)
switch (opcode) { // first 3 bits cases
case BLCase:
//offsetbuff = ((IMARValue) & 0x1FFF); // get the offset
return BLdecode(); // BL internal number sent to execute
case BEQtoBRA:
return betweenBEQandBRA(IMARValue); // go to further filtering
case ADDtoST:
return betweenADDandST(IMARValue); // go to further filtering
case MOVLtoMOVH:
return betweenMOVLandMOVH(IMARValue); // go to further filtering
case LLDR1:
return LDRdecode(); // LDR internal number sent to execute
case LLDR2:
return LDRdecode(); // LDR internal number sent to execute
case LSTR1:
return STRdecode(); // STR internal number sent to execute
case LSTR2:
return STRdecode(); // STR internal number sent to execute
default:
printf("Error - instruction not yet implemented\n");
return Error;
}
}
int BLdecode(){
/*
function to decode the BL instruction
- it extracts the offset from the instruction
- it calls function to handle sign extensions
- it returns the internal instruction number
*/
offsetbuff = ((IMARValue) & 0x1FFF); // get the offset
//offsetbuff = offsetbuff << 1; // shift the offsetbuff to the left to get even value
offsetbuff = SignExt(offsetbuff, BIT_NUMBER_12); //Sign-extend the offsetbuffer
return BL; // return the internal instruction number
}
int betweenADDandST(unsigned short IMARValue){
/*
decoding function for ADD to ST instructions
- it decodes the instruction based on the opcode
- it returns an number indicating the internal instruction
- it decodes functions between ADD and ST and sets their
buffers for the execute function
- will do further decoding (Layer2 and Layer3) if necessary
- L2 refers to Layer 2
- L3 refers to Layer 3
*/
unsigned short opcode = ((IMARValue>>10)&0x07); // get L2 opcode
prpobuff = ((IMARValue>>9)&0x01); // get the PRPO bits
decbuff = ((IMARValue>>8)&0x01); // get the decrement bit
incbuff = ((IMARValue>>7)&0x01); // get increment bit
wbbuff = ((IMARValue>>6)&0x01); // get the word/byte bit
srcbuff = ((IMARValue>>3)&0x07); // get the source register
dstbuff = ((IMARValue)&0x07); // get the destination register
if (opcode == LTCASE || opcode == STCASE) { // LD or ST case
//unsigned short opcode = ((IMARValue>>10)&0x01); // L3 opcode
prpobuff = ((IMARValue>>9)&0x01); // get the PRPO bits
decbuff = ((IMARValue>>8)&0x01); // get the decrement bit
incbuff = ((IMARValue>>7)&0x01); // get increment bit
wbbuff = ((IMARValue>>6)&0x01); // get the word/byte bit
srcbuff = ((IMARValue>>3)&0x07); // get the source register
dstbuff = ((IMARValue)&0x07); // get the destination register
//printf("opcodeLDST: %x or %d\n", opcode); // debugger printf
if (opcode == 6) { // LD case
return LD;
} else if(opcode == 7){ // ST case
return ST;
} else {
printf("instruction not yet implemented\n");
return Error;
}
} else if (opcode == MOV_CLRCC) { // MOV to CLRCC case
// get L3 opcode
//enum{LMOV, LSWAP, LSRA, LRRC, LSWPB, LSXT, LSETPRI, LSVC, LSETCC, LCLRCC}; // local opcode cases
enum{LMOV, LSWAP, LSRALSXT, LSETPRILCLRCC, LSVC, LSETCC, LCLRCC}; // local opcode cases
opcode = ((IMARValue>>7)&0x07);
// set buffers for SETCC and CLRCC
vbuff = ((IMARValue>>4)&0x01); // get the overflow bit
nbuff = ((IMARValue>>2)&0x01); // get the negative bit
zbuff = ((IMARValue>>1)&0x01); // get the zero bit
cbuff = (IMARValue&0x01); // get the carry bit
switch (opcode) { // L3 opcode cases
case LMOV:
return MOV;
case LSWAP:
return SWAP;
case LSRALSXT:
opcode = ((IMARValue>>3)&0x07); // get the L4 opcode
enum{LSRA, LRRC, LSWPB, LSXT}; // local L4 opcode cases
switch (opcode) {// L4 opcode cases
case LSRA:
return SRA;
case LRRC:
return RRC;
case LSWPB:
return SWPB;
case LSXT:
return SXT;
default:
printf("instruction not yet implemented\n");
return Error;
}
case LSETPRILCLRCC:
opcode = (IMARValue >> 4) & 0xf;
if (opcode == 8){
return SETPRI;
} else if (opcode == 9){
return SVC;
} else if (opcode == 10 || opcode == 11){
return SETCC;
} else if (opcode == 12 || opcode <= 13){
return CLRCC;
} else {
printf("instruction not yet implemented\n");
return Error;
}
default:
printf("instruction not yet implemented\n");
break;
return Error;
}
} else if (opcode == LCEX) { // CEX case
// extracting operands
condition_prefix_buff = ((IMARValue >> 6) & 0x0F); // get condition prefix
tcountbuff = ((IMARValue>>3)&0x07); // get true bits
fcountbuff = ((IMARValue)&0x07); // get false bits
return CEX;
} else { // ADD to BIS case
rcbuff = ((IMARValue>>7)&0x01); // get the register constant bit
wbbuff = ((IMARValue>>6)&0x01); // get the word/byte bit
srcbuff = ((IMARValue>>3)&0x07); // get the source register
dstbuff = ((IMARValue)&0x07); // get the destination register
opcode = ((IMARValue>>8)&0x0F); // get the L3 opcode
enum{LADD, LADDC, LSUB, LSUBC, // loacl L3 pcode cases
LDADD, LCMP, LXOR, LAND,
LOR, LBIT, LBIC, LBIS};
switch (opcode) { // opcode cases
case LADD:
return ADD;
case LADDC:
return ADDC;
case LSUB:
return SUB;
case LSUBC:
return SUBC;
case LDADD:
return DADD;
case LCMP:
return CMP;
case LXOR:
return XOR;
case LAND:
return AND;
case LOR:
return OR;
case LBIT:
return BIT;
case LBIC:
return BIC;
case LBIS:
return BIS;
default:
printf("instruction not yet implemented\n");
return Error;
}
}
}
int betweenMOVLandMOVH(unsigned short IMARValue){
/*
function to decode the instruction between MOVL and MOVH
- it decodes the instruction based on the opcode
- it returns an number indicating the internal instruction
- it decodes functions between MOVL and MOVH and sets their
buffers for the execute function
*/
unsigned short opcode = ((IMARValue>>11)&0x03); // get the Layer2 opcode
dstbuff = ((IMARValue)&0x07); // get the destination register
bitsbuff = ((IMARValue>>3)&0xFF); // get the bits
enum{LMOVL, LMOVLZ, LMOVLS, LMOVH}; // local L2 opcode cases
switch (opcode) { // opcode cases
case LMOVL:
return MOVL;
case LMOVLZ:
return MOVLZ;
case LMOVLS:
return MOVLS;
case LMOVH:
return MOVH;
default:
printf("instruction not yet implemented\n");
return Error;
}
}
int betweenBEQandBRA(unsigned short IMARValue){
/*
function to decode the instruction between BEQ and BRA
- it decodes the instruction based on the opcode
- it returns an number indicating the internal instruction
- it decodes functions between BEQ and BRA and sets their
buffers for the execute function
*/
unsigned short opcode = (IMARValue >> 10) & 0x07; // add a shift to get layer 2 opcode
offsetbuff = ((IMARValue) & 0x03FF); // get the offset
//offsetbuff = offsetbuff << 1;
offsetbuff = SignExt(offsetbuff, BIT_NUMBER_9); // Sign-extend the offsetbuffer (was 9 bits)
enum {LBEQBZ, LBNEBNZ, LBCBHS, // local L2 opcode cases
LBNCBLO, LBN, LBGE, LBLT, LBRA};
switch (opcode) { // opcode cases
case LBEQBZ:
return BEQBZ;
case LBNEBNZ:
return BNEBNZ;
case LBCBHS:
return BCBHS;
case LBNCBLO:
return BNCBLO;
case LBN:
return BN;
case LBGE:
return BGE;
case LBLT:
return BLT;
case LBRA:
return BRA;
default:
printf("instruction not yet implemented\n");
return Error;
}
}
int LDRdecode(){
/*
function to decode the LDR instruction
- it extracts the offset from the instruction
- it calls function to handle sign extensions
- it returns the internal instruction number
*/
wbbuff = ((IMARValue>>6)&0x01); // get the word/byte bit
srcbuff = ((IMARValue>>3)&0x07); // get the source register
dstbuff = ((IMARValue)&0x07); // get the destination register
offsetbuff = ((IMARValue>>7)&0x7F); // get the offset
offsetbuff = SignExt(offsetbuff, BIT_NUMBER_6);
return LDR;
}
int STRdecode(){
/*
function to decode the STR instruction
- it extracts the offset from the instruction
- it calls function to handle sign extensions
- it returns the internal instruction number
*/
wbbuff = ((IMARValue>>6)&0x01); // get the word/byte bit
srcbuff = ((IMARValue>>3)&0x07); // get the source register
dstbuff = ((IMARValue)&0x07); // get the destination register
offsetbuff = ((IMARValue>>7)&0x7F); // get the offset
offsetbuff = SignExt(offsetbuff, BIT_NUMBER_6);
return STR;
}
short SignExt(short offset, int msb) {
/*
Sign extension function to handle sign extensions
- it extends the sign of the offset if the msb is set
- it returns the offset
*/
if ((offset >> msb) & 0x01) {
offset |= ((0xFFFF) << msb); // Extend the sign if the msb is set
}
return offset << 1;
}