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