1 /*
2 * This file is part of libbdplus
3 * Copyright (C) 2008-2010 Accident
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see
17 * <http://www.gnu.org/licenses/>.
18 */
19
20 #include "dlx_internal.h"
21
22 #include "interface.h"
23 #include "trap_helper.h"
24
25 #include "util/macro.h"
26 #include "util/logging.h"
27
28 #include <stdlib.h>
29 #include <string.h>
30
31
32 #define DLX_START_ADDR 0x1000
33
34
35 #define OPERAND_D( I) ((((I) >> 0x13) & 0x7C) >> 2)
36 #define OPERAND_S1(I) ((((I) >> 0x0E) & 0x7C) >> 2)
37 #define OPERAND_S2(I) ((((I) >> 0x09) & 0x7C) >> 2)
38
39 #define OPERAND_UI(I) ((uint16_t)(I) & 0xFFFF)
40 #define OPERAND_SI(I) ((int16_t)(I) & 0xFFFF)
41 #define OPERAND_UJ(I) ((I) & 0x3FFFFFF)
42 #define OPERAND_SJ(I) (((I)& 0x2000000) ? (((I) & 0x3ffffff) | 0xFC000000) : ((I) & 0x3FFFFFF))
43
44 #define OP_RTYPE( I, op1, op2, op3) (op1) = OPERAND_D(I); (op2) = OPERAND_S1(I); (op3) = OPERAND_S2(I);
45 #define OP_ITYPE_U(I, op1, op2, op3) (op1) = OPERAND_D(I); (op2) = OPERAND_S1(I); (op3) = OPERAND_UI(I);
46 #define OP_ITYPE_S(I, op1, op2, op3) (op1) = OPERAND_D(I); (op2) = OPERAND_S1(I); (op3) = OPERAND_SI(I);
47 #define OP_JTYPE_U(I, op1) (op1) = OPERAND_UJ(I)
48 #define OP_JTYPE_S(I, op1) (op1) = OPERAND_SJ(I)
49
50
51 // Load results of DiscoveryRAM and DeviceDescovery (1,3) from snapshops?
52 //#define DLX_LOAD_FROM_SNAPSHOT
53
54 /*
55 *
56 */
57
dlx_initVM(struct bdplus_s * plus)58 VM *dlx_initVM(struct bdplus_s *plus)
59 {
60 VM *vm = calloc(1, sizeof(VM));
61 if (!vm) {
62 return NULL;
63 }
64
65 vm->size = DLX_MEMORY_SIZE;
66 vm->addr = (uint8_t *)malloc(vm->size);
67 if (!vm->addr) {
68 X_FREE(vm);
69 return NULL;
70 }
71
72 // Make sure memory is all zero
73 memset(vm->addr, 0, vm->size);
74
75 // Setup PC to the start
76 dlx_setPC(vm, DLX_START_ADDR);
77
78 vm->plus = plus;
79
80 return vm;
81 }
82
dlx_freeVM(VM ** vm)83 void dlx_freeVM(VM **vm)
84 {
85 if (vm && *vm) {
86 free_sha_ctx(&(*vm)->sha_ctx_head, NULL);
87
88 X_FREE((*vm)->addr);
89 X_FREE((*vm));
90 }
91 }
92
dlx_getApp(VM * vm)93 struct bdplus_s *dlx_getApp(VM *vm)
94 {
95 return vm->plus;
96 }
97
dlx_getAddr(VM * vm)98 uint8_t *dlx_getAddr(VM *vm)
99 {
100 return vm->addr;
101 }
102
dlx_getAddrSize(VM * vm)103 uint32_t dlx_getAddrSize(VM *vm)
104 {
105 return vm->size;
106 }
107
108 /*
109 *
110 */
111
dlx_setPC(VM * vm,unsigned int PC)112 uint32_t dlx_setPC(VM *vm, unsigned int PC)
113 {
114 uint32_t old;
115
116 old = vm->PC;
117
118 BD_DEBUG(DBG_BDPLUS,"[dlx] setPC (%p, %08X -> %08X)\n", vm, old, PC);
119
120 vm->PC = PC;
121
122 if (!vm->code_start)
123 vm->code_start = PC;
124
125 return old;
126
127 }
128
129
dlx_getPC(VM * vm)130 uint32_t dlx_getPC(VM *vm)
131 {
132
133 BD_DEBUG(DBG_BDPLUS,"[dlx] getPC (%p): %08X\n", vm, vm->PC);
134 return vm->PC;
135
136 }
137
138
dlx_setWD(VM * vm,int32_t WD)139 int32_t dlx_setWD(VM *vm, int32_t WD)
140 {
141 int32_t old;
142
143 old = vm->WD;
144
145 BD_DEBUG(DBG_BDPLUS,"[dlx] setWD (%p, %08X -> %08X)\n", vm, old, WD);
146
147 vm->WD = WD;
148 return old;
149
150 }
151
152
dlx_getWD(VM * vm)153 int32_t dlx_getWD(VM *vm)
154 {
155
156 BD_DEBUG(DBG_BDPLUS,"[dlx] getWD (%p): %08X\n", vm, vm->WD);
157 return vm->WD;
158
159 }
160
dlx_setIF(VM * vm,uint32_t IF)161 uint32_t dlx_setIF(VM *vm, uint32_t IF)
162 {
163 uint32_t old;
164
165 old = vm->IF;
166
167 BD_DEBUG(DBG_BDPLUS,"[dlx] setIF (%p, %08X -> %08X)\n", vm, old, IF);
168
169 vm->IF = IF;
170 return old;
171
172 }
173
174
dlx_getIF(VM * vm)175 uint32_t dlx_getIF(VM *vm)
176 {
177
178 BD_DEBUG(DBG_BDPLUS,"[dlx] getIF (%p): %08X\n", vm, vm->IF);
179 return vm->IF;
180
181 }
182
183
184
dlx_getStart(VM * vm)185 uint32_t dlx_getStart(VM *vm)
186 {
187 return vm->code_start;
188 }
189
190
191
192
193 // Format Bits
194 // 31-26 25-21 20-16 15-11 10-6 5-0
195 // R-type 0x0 Rs1 Rs2 Rd unused opcode
196 // I-type opcode Rs1 Rd |------immediate-----|
197 // J-type opcode |-------------------value---------------|
198 //
199 // Return code:
200 // 0 Instruction execution ok (STEP_I)
201 // 1 Trap
202 // 2 Break
203 // -1 Unknown opcode
204 // -2 PC trace failed
205 // -3 WD trace failed
206 // -4 IF trace failed
dlx_run(VM * vm,int32_t flags)207 int32_t dlx_run(VM *vm, int32_t flags)
208 {
209 uint32_t I, C, d, s1, s2, U_Iimm, U_Jimm;
210 int16_t S_Iimm;
211 int32_t S_Jimm;
212
213 if (!vm || !vm->addr) return -1;
214
215 // Clear last-trap holder. Just for dlx_last_trap() calls.
216 vm->trap = 0;
217
218 if (flags != BD_STEP_I) {
219 BD_DEBUG(DBG_DLX,"[dlx] running VM %p\n", vm);
220 }
221
222 do {
223
224 vm->PC &= ADDR_MASK4;
225 I = FETCH4(&vm->addr[vm->PC]);
226
227
228 // INSTF magic to confuse everything.
229 I ^= vm->IF;
230
231
232 vm->PC += 4;
233 vm->PC &= ADDR_MASK4;
234
235 vm->num_instructions++;
236
237 C = I >> 0x1A; // command
238
239 switch(C) {
240
241 case 0x00: // NOP
242 case 0x3B: // NOP
243 case 0x3C: // NOP
244 case 0x3D: // NOP
245 case 0x3E: // NOP
246 case 0x3F: // NOP
247 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): NOP\n", vm->PC-4, C);
248 vm->WD-=1;
249 break;
250
251 case 0x01: // ADD | R-type | Rd = Rs1 + Rs2
252 OP_RTYPE(I, d, s1, s2);
253 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): ADD (R%-2d = R%-2d + R%-2d): %d = %d + %d\n"
254 , vm->PC-4, C,
255 d,s1,s2,vm->R[s1]+vm->R[s2],vm->R[s1],vm->R[s2]);
256 vm->R[d] = vm->R[s1] + vm->R[s2];
257 vm->WD-=1;
258 break;
259
260 case 0x02: // SUB | R-type | Rd = Rs1 - Rs2
261 OP_RTYPE(I, d, s1, s2);
262 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SUB (R%-2d = R%-2d - R%-2d): %08X = %08X - %08X\n"
263 , vm->PC-4, C,
264 d,s1,s2,vm->R[s1]-vm->R[s2],vm->R[s1],vm->R[s2]);
265 vm->R[d] = vm->R[s1] - vm->R[s2];
266 vm->WD-=1;
267 break;
268
269 case 0x03: // MUL | R-type | Rd = Rs1 * Rs2
270 OP_RTYPE(I, d, s1, s2);
271 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): MUL (R%-2d = R%-2d * R%-2d): %08X = %08X * %08X\n"
272 , vm->PC-4, C,
273 d,s1,s2,vm->R[s1]*vm->R[s2],vm->R[s1],vm->R[s2]);
274 vm->R[d] = vm->R[s1] * vm->R[s2];
275 vm->WD-=4;
276 break;
277
278 case 0x04: // DIV | R-type | Rd = signed(Rs1) / signed(Rs2)
279 OP_RTYPE(I, d, s1, s2);
280 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): DIV (R%-2d = R%-2d / R%-2d): %08X = %08X / %08X\n"
281 , vm->PC-4, C,
282 d,s1,s2,(vm->R[s2] ? (int32_t)vm->R[s1]/(int32_t)vm->R[s2] : 0),vm->R[s1],vm->R[s2]);
283 if (vm->R[s2])
284 vm->R[d] = (int32_t)vm->R[s1] / (int32_t)vm->R[s2];
285 else
286 vm->R[d] = 0; // Division by 0?
287 vm->WD-=16;
288 break;
289
290 case 0x05: // DIVU | R-type | Rd = unsigned(Rs1) / unsigned(Rs2)
291 OP_RTYPE(I, d, s1, s2);
292 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): DIVU(R%-2d = R%-2d / R%-2d): %08X = %08X / %08X\n"
293 , vm->PC-4, C,
294 d,s1,s2,(vm->R[s2] ? vm->R[s1]/vm->R[s2] : 0),vm->R[s1],vm->R[s2]);
295 if (vm->R[s2])
296 vm->R[d] = vm->R[s1] / vm->R[s2];
297 else
298 vm->R[d] = 0;
299 vm->WD-=16;
300 break;
301
302 case 0x06: // SLL | R-type | Rd = Rs1 << (Rs2 & 0x1F)
303 OP_RTYPE(I, d, s1, s2);
304 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SLL (R%-2d = R%-2d << R%-2d): %08X = %08X << %d\n"
305 , vm->PC-4, C,
306 d,s1,s2,vm->R[s1]<<(vm->R[s2]&0x1F),vm->R[s1],vm->R[s2]);
307 vm->R[d] = vm->R[s1] << (vm->R[s2]&0x1F);
308 vm->WD-=1;
309 break;
310
311 case 0x07: // SRL | R-type | Rd = Rs1 >> (Rs2 & 0x1F)
312 OP_RTYPE(I, d, s1, s2);
313 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SRL (R%-2d = R%-2d >> R%-2d): %08X = %08X >> %d\n"
314 , vm->PC-4, C,
315 d,s1,s2,vm->R[s1]>>(vm->R[s2]&0x1F),vm->R[s1],vm->R[s2]);
316 vm->R[d] = vm->R[s1] >> (vm->R[s2]&0x1F);
317 vm->WD-=1;
318 break;
319
320 case 0x08: // SRA | R-type | SRL and SRA perform identically if Rs1 is positive. If Rs1 is negative (bit 31 == 1), 1's are shifted in from the left for SRA and SRAI.
321 OP_RTYPE(I, d, s1, s2);
322 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SRA (R%-2d = R%-2d >> R%-2d): %08X = %08X >> %d\n"
323 , vm->PC-4, C,
324 d,s1,s2,(int32_t)vm->R[s1]>>(vm->R[s2]&0x1F),vm->R[s1],vm->R[s2]);
325 vm->R[d] = (int32_t)vm->R[s1] >> (vm->R[s2]&0x1F);
326 vm->WD-=1;
327 break;
328
329 case 0x09: // AND | R-type | Rd = Rs1 & Rs2
330 OP_RTYPE(I, d, s1, s2);
331 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): AND (R%-2d = R%-2d & R%-2d): %08X = %08X & %08X\n"
332 , vm->PC-4, C,
333 d,s1,s2,vm->R[s1]&vm->R[s2],vm->R[s1],vm->R[s2]);
334 vm->R[d] = vm->R[s1] & vm->R[s2];
335 vm->WD-=1;
336 break;
337
338 case 0x0A: // OR | R-type | Rd = Rs1 | Rs2
339 OP_RTYPE(I, d, s1, s2);
340 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): OR (R%-2d = R%-2d | R%-2d): %08X = %08X | %08X\n"
341 , vm->PC-4, C,
342 d,s1,s2,vm->R[s1]|vm->R[s2],vm->R[s1],vm->R[s2]);
343 vm->R[d] = vm->R[s1] | vm->R[s2];
344 vm->WD-=1;
345 break;
346
347 case 0x0B: // XOR | R-type | Rd = Rs1 ^ Rs2
348 OP_RTYPE(I, d, s1, s2);
349 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): XOR (R%-2d = R%-2d ^ R%-2d): %08X = %08X ^ %08X\n"
350 , vm->PC-4, C,
351 d,s1,s2,vm->R[s1]^vm->R[s2],vm->R[s1],vm->R[s2]);
352 vm->R[d] = vm->R[s1] ^ vm->R[s2];
353 vm->WD-=1;
354 break;
355
356 case 0x0C: // SEQ | R-type | Rd = (Rs1 == Rs2 ? 1 : 0)
357 OP_RTYPE(I, d, s1, s2);
358 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SEQ (R%-2d = (R%-2d == R%-2d)): %08X = (%08X == %d)\n"
359 , vm->PC-4, C,
360 d,s1,s2,vm->R[s1]==vm->R[s2] ? 1 : 0, vm->R[s1], vm->R[s2]);
361 vm->R[d] = vm->R[s1] == vm->R[s2] ? 1 : 0;
362 vm->WD-=1;
363 break;
364
365 case 0x0D: // SNE | R-type | Rd = (Rs1 != Rs2 ? 1 : 0)
366 OP_RTYPE(I, d, s1, s2);
367 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SNE (R%-2d = (R%-2d != R%-2d)): %08X = (%08X != %08X)\n"
368 , vm->PC-4, C,
369 d,s1,s2,vm->R[s1]!=vm->R[s2] ? 1 : 0, vm->R[s1], vm->R[s2]);
370 vm->R[d] = vm->R[s1] != vm->R[s2] ? 1 : 0;
371 vm->WD-=1;
372 break;
373
374 case 0x0E: // SLT | R-type | Rd = (Rs1 < Rs2 ? 1 : 0) [signed]
375 OP_RTYPE(I, d, s1, s2);
376 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SLT (R%-2d = (R%-2d < R%-2d)): %08X = (%08X < %08X)\n"
377 , vm->PC-4, C,
378 d,s1,s2,(int32_t)vm->R[s1]<(int32_t)vm->R[s2] ? 1 : 0,
379 vm->R[s1], vm->R[s2]);
380 vm->R[d] = (int32_t)vm->R[s1] < (int32_t)vm->R[s2] ? 1 : 0;
381 vm->WD-=1;
382 break;
383
384 case 0x0F: // SBT | R-type | Rd = (Rs1 < Rs2 ? 1 : 0)
385 OP_RTYPE(I, d, s1, s2);
386 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SBT (R%-2d = (R%-2d < R%-2d)): %08X = (%08X < %08X)\n"
387 , vm->PC-4, C,
388 d,s1,s2,vm->R[s1]<vm->R[s2] ? 1 : 0, vm->R[s1], vm->R[s2]);
389 vm->R[d] = vm->R[s1] < vm->R[s2] ? 1 : 0;
390 vm->WD-=1;
391 break;
392
393 case 0x10: // SGT | R-type | Rd = (Rs1 > Rs2 ? 1 : 0) [signed]
394 OP_RTYPE(I, d, s1, s2);
395 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SGT (R%-2d = (R%-2d > R%-2d)): %08X = (%08X < %08X)\n"
396 , vm->PC-4, C,
397 d,s1,s2,(int32_t)vm->R[s1]>(int32_t)vm->R[s2] ? 1 : 0,
398 vm->R[s1], vm->R[s2]);
399 vm->R[d] = (int32_t)vm->R[s1] > (int32_t)vm->R[s2] ? 1 : 0;
400 vm->WD-=1;
401 break;
402
403 case 0x11: // SAT | R-type | Rd = (Rs1 > Rs2 ? 1 : 0)
404 OP_RTYPE(I, d, s1, s2);
405 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SAT (R%-2d = (R%-2d > R%-2d)): %08X = (%08X > %08X)\n"
406 , vm->PC-4, C,
407 d,s1,s2,vm->R[s1]>vm->R[s2] ? 1 : 0, vm->R[s1], vm->R[s2]);
408 vm->R[d] = vm->R[s1] > vm->R[s2] ? 1 : 0;
409 vm->WD-=1;
410 break;
411
412 case 0x12: // SLE | R-type | Rd = (Rs1 <= Rs2 ? 1 : 0) [signed]
413 OP_RTYPE(I, d, s1, s2);
414 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SLE (R%-2d = (R%-2d <= R%-2d)): %08X = (%08X <= %08X)\n"
415 , vm->PC-4, C,
416 d,s1,s2,(int32_t)vm->R[s1]<=(int32_t)vm->R[s2] ? 1 : 0,
417 vm->R[s1], vm->R[s2]);
418 vm->R[d] = (int32_t)vm->R[s1] <= (int32_t)vm->R[s2] ? 1 : 0;
419 vm->WD-=1;
420 break;
421
422 case 0x13: // SBE | R-type | Rd =(unsigned(Rs1) <= unsigned(Rs2) ? 1 : 0)
423 OP_RTYPE(I, d, s1, s2);
424 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SBE (R%-2d = (R%-2d <= R%-2d)): %08X = (%08X <= %08X)\n"
425 , vm->PC-4, C,
426 d,s1,s2,vm->R[s1]<=vm->R[s2] ? 1 : 0, vm->R[s1], vm->R[s2]);
427 vm->R[d] = vm->R[s1] <= vm->R[s2] ? 1 : 0;
428 vm->WD-=1;
429 break;
430
431 case 0x14: // SGE | R-type | Rd = (Rs1 >= Rs2 ? 1 : 0) [signed]
432 OP_RTYPE(I, d, s1, s2);
433 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SGE (R%-2d = (R%-2d >= R%-2d)): %08X = (%08X >= %08X)\n"
434 , vm->PC-4, C,
435 d,s1,s2,(int32_t)vm->R[s1]>=(int32_t)vm->R[s2] ? 1 : 0,
436 vm->R[s1], vm->R[s2]);
437 vm->R[d] = (int32_t)vm->R[s1] >= (int32_t)vm->R[s2] ? 1 : 0;
438 vm->WD-=1;
439 break;
440
441 case 0x15: // SAE | R-type | Rd =(unsigned(Rs1) >= unsigned(Rs2) ? 1 : 0)
442 OP_RTYPE(I, d, s1, s2);
443 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SAE (R%-2d = (R%-2d >= R%-2d)): %08X = (%08X >= %08X)\n"
444 , vm->PC-4, C,
445 d,s1,s2,vm->R[s1]>=vm->R[s2] ? 1 : 0, vm->R[s1], vm->R[s2]);
446 vm->R[d] = vm->R[s1] >= vm->R[s2] ? 1 : 0;
447 vm->WD-=1;
448 break;
449
450 case 0x16: // JR | I-type | PC = Rs1
451 s1 = OPERAND_S1(I);
452 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): JR (PC = R%-2d): PC=%08X\n"
453 , vm->PC-4, C,
454 s1,vm->R[s1] & ADDR_MASK4);
455 vm->PC = vm->R[s1] & ADDR_MASK4;
456 vm->WD-=2;
457 break;
458
459 case 0x17: // JALR | I-type | R31 = PC + 4 ; PC = Rs1
460 s1 = OPERAND_S1(I);
461 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): JALR(R31 = PC; PC = R%-2d): PC=%08X\n"
462 , vm->PC-4, C,
463 s1,vm->R[s1]);
464 vm->R[31] = vm->PC;
465 vm->PC = vm->R[s1] & ADDR_MASK4;
466 vm->WD-=3;
467 break;
468
469 case 0x18: // ADDIE | I-type | Rd = Rs1 + extend(immediate)
470 OP_ITYPE_S(I, d, s1, S_Iimm);
471 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X):ADDIE(R%-2d = R%-2d + %04X): %d = %d + %d\n"
472 , vm->PC-4, C,
473 d,s1,S_Iimm,vm->R[s1]+S_Iimm,vm->R[s1],S_Iimm);
474 vm->R[d] = vm->R[s1] + S_Iimm;
475 vm->WD-=1;
476 break;
477
478 case 0x19: // ADDI | I-type | Rd = Rs1 + immediate
479 OP_ITYPE_U(I, d, s1, U_Iimm);
480 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): ADDI(R%-2d = R%-2d + %04X): %d = %d + %d\n"
481 , vm->PC-4, C,
482 d,s1,U_Iimm,vm->R[s1]+U_Iimm,vm->R[s1],U_Iimm);
483 vm->R[d] = vm->R[s1] + U_Iimm;
484 vm->WD-=1;
485 break;
486
487 case 0x1A: // SUBIE | I-type | Rd = Rs1 - extended(immediate)
488 OP_ITYPE_S(I, d, s1, S_Iimm);
489 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X):SUBIE(R%-2d = R%-2d - %04X): %08X = %08X - %d\n"
490 , vm->PC-4, C,
491 d,s1,S_Iimm,
492 vm->R[s1] - S_Iimm,
493 vm->R[s1], S_Iimm);
494 vm->R[d] = vm->R[s1] - S_Iimm;
495 vm->WD-=1;
496 break;
497
498 case 0x1B: // SUBI | I-type | Rd = Rs1 - immediate
499 OP_ITYPE_U(I, d, s1, U_Iimm);
500 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SUBI(R%-2d = R%-2d - %04X): %08X = %08X - %d\n"
501 , vm->PC-4, C,
502 d,s1,U_Iimm,
503 vm->R[s1] - U_Iimm,
504 vm->R[s1], U_Iimm);
505 vm->R[d] = vm->R[s1] - U_Iimm;
506 vm->WD-=1;
507 break;
508
509 case 0x1C: // SLLI | I-type | Rd = Rs1 << (immediate & 0x1F)
510 OP_ITYPE_U(I, d, s1, U_Iimm);
511 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SLLI(R%-2d = R%-2d << %02X): %08X = %08X << %d\n"
512 , vm->PC-4, C,
513 d,s1,U_Iimm&0x1F,vm->R[s1]<<(U_Iimm&0x1F),vm->R[s1],U_Iimm&0x1F);
514 vm->R[d] = vm->R[s1] << (U_Iimm&0x1F);
515 vm->WD-=1;
516 break;
517
518 case 0x1D: // SRLI | I-type | Rd = Rs1 >> (immediate & 0x1F)
519 OP_ITYPE_U(I, d, s1, U_Iimm);
520 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SRLI(R%-2d = R%-2d >> %02X): %08X = %08X >> %d\n"
521 , vm->PC-4, C,
522 d,s1,U_Iimm&0x1F,vm->R[s1]>>(U_Iimm&0x1F),vm->R[s1],U_Iimm&0x1F);
523 vm->R[d] = vm->R[s1] >> (U_Iimm&0x1F);
524 vm->WD-=1;
525 break;
526
527 case 0x1E: // SRAI | I-type | as SRLI & sign extend
528 OP_ITYPE_U(I, d, s1, U_Iimm);
529 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SRLI(R%-2d = R%-2d >> %04X): %08X = %08X >> %d\n"
530 , vm->PC-4, C,
531 d,s1,U_Iimm,(int32_t)vm->R[s1]>>(U_Iimm&0x1F),vm->R[s1],U_Iimm);
532 vm->R[d] = (int32_t)vm->R[s1] >> (U_Iimm&0x1F);
533 vm->WD-=1;
534 break;
535
536 case 0x1F: // ANDI | I-type | Rd = Rs1 & immediate
537 OP_ITYPE_U(I, d, s1, U_Iimm);
538 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): ANDI(R%-2d = R%-2d & %04X): %08X = %08X & %d\n"
539 , vm->PC-4, C,
540 d,s1,U_Iimm,vm->R[s1]&U_Iimm,vm->R[s1],U_Iimm);
541 vm->R[d] = vm->R[s1] & U_Iimm;
542 vm->WD-=1;
543 break;
544
545 case 0x20: // ORI | I-type | Rd = Rs1 | immediate
546 OP_ITYPE_U(I, d, s1, U_Iimm);
547 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): ORI (R%-2d = R%-2d | %04X): %08X = %08X | %d\n"
548 , vm->PC-4, C,
549 d,s1,U_Iimm,vm->R[s1]|U_Iimm,vm->R[s1],U_Iimm);
550 vm->R[d] = vm->R[s1] | U_Iimm;
551 vm->WD-=1;
552 break;
553
554 case 0x21: // XORI | I-type | Rd = Rs1 ^ immediate
555 OP_ITYPE_U(I, d, s1, U_Iimm);
556 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): XORI(R%-2d = R%-2d ^ %04X): %08X = %08X ^ %d\n"
557 , vm->PC-4, C,
558 d,s1,U_Iimm,vm->R[s1]^U_Iimm,vm->R[s1],U_Iimm);
559 vm->R[d] = vm->R[s1] ^ U_Iimm;
560 vm->WD-=1;
561 break;
562
563 case 0x22: // SEQI | I-type | Rd = (Rs1 == extend(immediate) ? 1 : 0)
564 OP_ITYPE_S(I, d, s1, S_Iimm);
565 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SEQI(R%-2d = (R%-2d == %04X)): %08X = (%08X == %d)\n"
566 , vm->PC-4, C,
567 d,s1,S_Iimm,vm->R[s1]==(uint32_t)(int32_t)S_Iimm ? 1 : 0, vm->R[s1], S_Iimm);
568 vm->R[d] = (vm->R[s1] == (uint32_t)(int32_t)S_Iimm) ? 1 : 0;
569 vm->WD-=1;
570 break;
571
572 case 0x23: // SNEI | I-type | Rd = (Rs1 != extend(immediate) ? 1 : 0)
573 OP_ITYPE_S(I, d, s1, S_Iimm);
574 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SNEI(R%-2d = (R%-2d != %04X)): %08X = (%08X != %d)\n"
575 , vm->PC-4, C,
576 d,s1,S_Iimm,(int32_t)vm->R[s1]!=(int32_t)S_Iimm ? 1 : 0, vm->R[s1], S_Iimm);
577 vm->R[d] = (vm->R[s1] != (uint32_t)(int32_t)S_Iimm) ? 1 : 0;
578 vm->WD-=1;
579 break;
580
581 case 0x24: // SLI | I-type | Rd = (Rs1 < extend(immediate) ? 1 : 0)
582 OP_ITYPE_S(I, d, s1, S_Iimm);
583 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SLI (R%-2d = (R%-2d < %04X)): %08X = (%08X < %d)\n"
584 , vm->PC-4, C,
585 d,s1,S_Iimm,(int32_t)vm->R[s1]<S_Iimm ? 1 : 0, vm->R[s1], S_Iimm);
586 vm->R[d] = ((int32_t)vm->R[s1] < S_Iimm) ? 1 : 0;
587 vm->WD-=1;
588 break;
589
590 case 0x25: // SBI | I-type | Rd = (Rs1 < extend(immediate) ? 1 : 0)
591 OP_ITYPE_U(I, d, s1, U_Iimm);
592 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SBI (R%-2d = (R%-2d < %04X)): %08X = (%08X < %d)\n"
593 , vm->PC-4, C,
594 d,s1,U_Iimm,vm->R[s1]<U_Iimm ? 1 : 0, vm->R[s1], U_Iimm);
595 vm->R[d] = (vm->R[s1] < U_Iimm) ? 1 : 0;
596 vm->WD-=1;
597 break;
598
599 case 0x26: // SGI | I-type | Rd = (Rs1 > extend(immediate) ? 1 : 0)
600 OP_ITYPE_S(I, d, s1, S_Iimm);
601 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SGI (R%-2d = (R%-2d > %04X)): %08X = (%08X > %d)\n"
602 , vm->PC-4, C,
603 d,s1,S_Iimm,(int32_t)vm->R[s1]>S_Iimm ? 1 : 0, vm->R[s1], S_Iimm);
604 vm->R[d] = ((int32_t)vm->R[s1] > S_Iimm) ? 1 : 0;
605 vm->WD-=1;
606 break;
607
608 case 0x27: // SAI | I-type | Rd = (Rs1 > extend(immediate) ? 1 : 0)
609 OP_ITYPE_U(I, d, s1, U_Iimm);
610 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SAI (R%-2d = (R%-2d > %04X)): %08X = (%08X > %d)\n"
611 , vm->PC-4, C,
612 d,s1,U_Iimm,vm->R[s1]>U_Iimm ? 1 : 0, vm->R[s1], U_Iimm);
613 vm->R[d] = (vm->R[s1] > U_Iimm) ? 1 : 0;
614 vm->WD-=1;
615 break;
616
617 case 0x28: // SLEI | I-type | Rd = (Rs1 <= extend(immediate) ? 1 : 0)
618 OP_ITYPE_S(I, d, s1, S_Iimm);
619 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SLEI(R%-2d = (R%-2d <= %04X)): %08X = (%08X <= %d)\n"
620 , vm->PC-4, C,
621 d,s1,S_Iimm,(int32_t)vm->R[s1]<=S_Iimm ? 1 :0, vm->R[s1], S_Iimm);
622 vm->R[d] = ((int32_t)vm->R[s1] <= S_Iimm) ? 1 : 0;
623 vm->WD-=1;
624 break;
625
626 case 0x29: // SBEI | I-type | Rd = (Rs1 <= unsigned(immediate) ? 1 : 0)
627 OP_ITYPE_U(I, d, s1, U_Iimm);
628 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SBEI(R%-2d = (R%-2d <= %04X)): %08X = (%08X <= %d)\n"
629 , vm->PC-4, C,
630 d,s1,U_Iimm,vm->R[s1]<=U_Iimm ? 1 : 0, vm->R[s1], U_Iimm);
631 vm->R[d] = (vm->R[s1] <= U_Iimm) ? 1 : 0;
632 vm->WD-=1;
633 break;
634
635 case 0x2A: // SGEI | I-type | Rd = (Rs1 >= extend(immediate) ? 1 : 0)
636 OP_ITYPE_S(I, d, s1, S_Iimm);
637 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SGEI (R%-2d = (R%-2d >= %04X)): %08X = (%08X >= %d)\n"
638 , vm->PC-4, C,
639 d,s1,S_Iimm,(int32_t)vm->R[s1]>=S_Iimm ? 1 :0, vm->R[s1], S_Iimm);
640 vm->R[d] = ((int32_t)vm->R[s1] >= S_Iimm) ? 1 : 0;
641 vm->WD-=1;
642 break;
643
644 case 0x2B: // SAEI | I-type | Rd = (Rs1 >= extend(immediate) ? 1 : 0)
645 OP_ITYPE_U(I, d, s1, U_Iimm);
646 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SAEI(R%-2d = (R%-2d >= %04X)): %08X = (%08X >= %d)\n"
647 , vm->PC-4, C,
648 d,s1,U_Iimm,vm->R[s1]>=U_Iimm ? 1 : 0, vm->R[s1], U_Iimm);
649 vm->R[d] = (vm->R[s1] >= U_Iimm) ? 1 : 0;
650 vm->WD-=1;
651 break;
652
653 case 0x2C: // J | J-type | PC += extend(value)
654 OP_JTYPE_S(I, S_Jimm);
655 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): J (PC += %07X): %08X = %08X + %d\n"
656 , vm->PC-4, C,
657 S_Jimm, (vm->PC+S_Jimm)&ADDR_MASK4, vm->PC, S_Jimm);
658
659 vm->PC = (vm->PC + S_Jimm) & ADDR_MASK4;
660
661 //if (S_Jimm == -4) return -1;
662 vm->WD-=2;
663 break;
664
665 case 0x2D: // JAL | J-type | R31 = PC + 4 ; PC += extend(value)
666 OP_JTYPE_S(I, S_Jimm);
667 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): JAL (R31 = %08X ; PC += %04X): %08X = PC + %d\n"
668 , vm->PC-4, C,
669 vm->PC,
670 S_Jimm,
671 vm->PC + S_Jimm,
672 S_Jimm);
673 vm->R[31] = vm->PC;
674 vm->PC = (vm->PC + S_Jimm) & ADDR_MASK4;
675 vm->WD-=3;
676 break;
677
678 case 0x2E: // BEQZ | I-type | PC += (Rs1 == 0 ? extend(immediate) : 0)
679 s1 = OPERAND_S1(I);
680 S_Iimm = OPERAND_SI(I);
681 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): BEQZ(PC += %04X if !R%-2d): %08X = PC + %d if !%d\n"
682 , vm->PC-4, C,
683 S_Iimm,
684 s1,
685 vm->PC + (!vm->R[s1] ? S_Iimm : 0),
686 S_Iimm,
687 vm->R[s1]);
688 vm->PC = (vm->PC + (!vm->R[s1] ? S_Iimm : 0)) & ADDR_MASK4;
689 vm->WD-=2;
690 break;
691
692 case 0x2F: // BNEZ | I-type | PC += (Rs1 != 0 ? extend(immediate) : 0)
693 s1 = OPERAND_S1(I);
694 S_Iimm = OPERAND_SI(I);
695 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): BNEZ(PC += %04X if R%-2d): %08X += %d if %d\n"
696 , vm->PC-4, C,
697 S_Iimm, s1, vm->PC, vm->R[s1] ? S_Iimm : 0, vm->R[s1]);
698
699 vm->PC = (vm->PC + (vm->R[s1] ? S_Iimm : 0)) & ADDR_MASK4;
700 vm->WD-=2;
701 break;
702
703 case 0x30: // LHI | I-type | Rd = immediate << 16
704 d = OPERAND_D(I);
705 U_Iimm = OPERAND_UI(I);
706 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): LHI (R%-2d = %04X << 16): %08X = %08X << 16\n"
707 , vm->PC-4, C,
708 d, U_Iimm, U_Iimm << 16, U_Iimm);
709
710 vm->R[d] = U_Iimm << 16;
711 vm->WD-=1;
712 break;
713
714 case 0x31: // LBE | I-type | Rd = extend(MEM[Rs1 + extend(immediate)] && 0xFF)
715 OP_ITYPE_S(I, d, s1, S_Iimm);
716 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): LBE (R%-2d = [R%-2d + %04X]c): %08X = [%08X + %d]\n"
717 , vm->PC-4, C,
718 d, s1, S_Iimm,
719 (int8_t)(vm->addr[ (vm->R[s1] + S_Iimm) & ADDR_MASK1 ]&0xff),
720 vm->R[s1], S_Iimm);
721
722 vm->R[d] = (int8_t)(vm->addr[ (vm->R[s1] + S_Iimm) & ADDR_MASK1 ]&0xff);
723 vm->WD-=4;
724 break;
725
726 case 0x32: // LB | I-type | Rd = MEM[Rs1 + extend(immediate)]
727 OP_ITYPE_S(I, d, s1, S_Iimm);
728 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): LB (R%-2d = [R%-2d + %04X]c): %08X = %08X + %d\n"
729 , vm->PC-4, C,
730 d, s1, S_Iimm, vm->addr[ ( vm->R[s1] + S_Iimm) & ADDR_MASK1 ]&0xff,
731 vm->R[s1], S_Iimm);
732
733 vm->R[d] = vm->addr[ (vm->R[s1] + S_Iimm) & ADDR_MASK1 ]&0xff;
734 vm->WD-=4;
735 break;
736
737 case 0x33: // LWE | I-type | Rd = extend(MEM[Rs1 + extend(immediate)] && 0xFFFF) (?)
738 OP_ITYPE_S(I, d, s1, S_Iimm);
739 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): LWE (R%-2d = [R%-2d + %04X]s): %08X = %08X + %d\n"
740 , vm->PC-4, C,
741 d, s1, S_Iimm, FETCHS2( &vm->addr[ vm->R[s1] + S_Iimm ] ),
742 vm->R[s1], S_Iimm);
743
744 vm->R[d] = FETCHS2(&vm->addr[ (vm->R[s1] + S_Iimm) & ADDR_MASK2 ]);
745 vm->WD-=4;
746 break;
747
748 case 0x34: // LW | I-type | Rd = MEM[Rs1 + extend(immediate)] && 0xFFFF)
749 OP_ITYPE_S(I, d, s1, S_Iimm);
750 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): LW (R%-2d = [R%-2d + %04X]s): %08X = %08X + %d\n"
751 , vm->PC-4, C,
752 d, s1, S_Iimm, FETCHU2( &vm->addr[ vm->R[s1] + S_Iimm ] ),
753 vm->R[s1], S_Iimm);
754
755 vm->R[d] = FETCHU2(&vm->addr[ (vm->R[s1] + S_Iimm) & ADDR_MASK2 ]);
756 vm->WD-=4;
757 break;
758
759 case 0x35: // LDW | I-type | Rd = MEM[Rs1 + extend(immediate)]
760 OP_ITYPE_S(I, d, s1, S_Iimm);
761 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): LDW (R%-2d = [R%-2d + %02X]l): %08X = %08X + %d\n"
762 , vm->PC-4, C,
763 d,s1,S_Iimm,
764 FETCH4( &vm->addr[ ( vm->R[s1] + S_Iimm ) & ADDR_MASK4 ] ),
765 vm->R[s1], S_Iimm);
766
767 vm->R[d] = FETCH4( &vm->addr[ (vm->R[s1] + S_Iimm) & ADDR_MASK4 ] );
768 vm->WD-=2;
769 break;
770
771 case 0x36: // SB | I-type | MEM[Rs1 + extend(immediate)]c = (u_char) Rd
772 OP_ITYPE_S(I, d, s1, S_Iimm);
773 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SB ([R%-2d + %04X]c = R%-2d): [ %08X + %d ] = %02X\n"
774 , vm->PC-4, C,
775 s1, S_Iimm, d,
776 vm->R[s1], S_Iimm, vm->R[d] & 0xFF);
777
778 vm->addr[ (vm->R[s1] + S_Iimm) & ADDR_MASK1 ] = vm->R[d]&0xFF;
779 vm->WD-=4;
780 break;
781
782 case 0x37: // SW | I-type | MEM[Rs1 + extend(immediate)]s = (uint16) Rd
783 OP_ITYPE_S(I, d, s1, S_Iimm);
784 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SW ([R%-2d + %04X]s = R%-2d): [ %08X + %d ] = %04X\n"
785 , vm->PC-4, C,
786 s1, S_Iimm, d,
787 vm->R[s1], S_Iimm, vm->R[d] & 0xFFFF);
788
789 STORE2(&vm->addr[ (vm->R[s1] + S_Iimm) & ADDR_MASK2 ], vm->R[d]);
790 vm->WD-=4;
791 break;
792
793 case 0x38: // SDW | I-type | MEM[Rs1 + extend(immediate)] = (uint32) Rd
794 OP_ITYPE_S(I, d, s1, S_Iimm);
795 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): SDW ([R%-2d + %02X] = R%-2d): %08X = %08X\n"
796 , vm->PC-4, C,
797 s1,S_Iimm,d,
798 (vm->R[s1] + S_Iimm) & ADDR_MASK4,
799 vm->R[d]);
800
801 STORE4(&vm->addr[ (vm->R[s1] + S_Iimm) & ADDR_MASK4 ], vm->R[d]);
802 vm->WD-=2;
803 break;
804
805 case 0x39: // TRAP | J-type | trap[immediate]
806 OP_JTYPE_U(I, U_Jimm);
807 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): TRAP([%02X]): TRAP %d\n"
808 , vm->PC-4, C,
809 U_Jimm, U_Jimm);
810
811 vm->trap = U_Jimm;
812
813 //vm->WD=0x7fffffff;
814 // TRAP resets WD, trap might also set it, like trap_Finished().
815 if (vm->event_processing)
816 dlx_setWD(vm, 0x7FFFFFFF);
817
818 // Call the above layer to deal with the trap.
819 interface_trap(vm, U_Jimm);
820
821 vm->num_traps++;
822
823 if ((vm->WD <= 0) &&
824 !vm->event_processing) {
825
826 BD_DEBUG(DBG_DLX, "[dlx] trap expired WD %08X. WD reset\n", vm->WD);
827 dlx_setWD(vm, 0xFA0); // 4000
828 }
829
830 return 1; // Return TRAP reached.
831 break;
832
833 case 0x3A: // INSTF | I-type | IF = Rs1
834 s1 = OPERAND_S1(I);
835 BD_DEBUG(DBG_DLX,"[dlx] %08X (I=%02X): INSTF(IF = R%-2d): IF = %08X\n"
836 , vm->PC-4, C,
837 s1,
838 vm->R[s1]);
839
840 vm->IF = vm->R[s1];
841 vm->WD-=6;
842 break;
843
844 default:
845 BD_DEBUG(DBG_DLX,"[dlx] %08X fetch %08X (I=%02X); UNKNOWN\n", vm->PC, I, C);
846 return -1;
847 }
848
849 // According to DLX specifications, R0 is always 0, and read-only
850 if (vm->R[0]) BD_DEBUG(DBG_DLX,"[dlx] WARNING R0 (%08X) not 0!\n", vm->R[0]);
851 vm->R[0] = 0;
852
853 if (vm->WD <= 0) {
854 BD_DEBUG(DBG_DLX,"[dlx] BREAK! PC=%08X. WD=%08X (old R28 %08X, event %d)\n",
855 vm->PC, vm->WD, vm->R[28], vm->event_processing);
856
857 // What do we actually do on breaks?
858
859 vm->num_breaks++;
860
861 if (vm->event_processing) {
862 vm->R[28] = dlx_getPC(vm);
863 }
864 dlx_setWD(vm, 0xFA0); // 4000
865
866 return 2; // Reached BREAK
867 }
868
869 // If we run per STEP_I, this runs once
870 // If we run per trap, we loop until trap's return
871
872 } while(flags == BD_STEP_TRAP); // do until trap etc
873
874
875 return 0;
876 }
877
878
879