1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
5 #include "arm.h"
6
7 static int dummy;
8 static char* shtype[4] =
9 {
10 "<<",
11 ">>",
12 "->",
13 "@>",
14 };
15 static char* cond[16] =
16 {
17 ".EQ", ".NE", ".HS", ".LO",
18 ".MI", ".PL", ".VS", ".VC",
19 ".HI", ".LS", ".GE", ".LT",
20 ".GT", ".LE", "", ".NO",
21 };
22
23 void Idp0(ulong);
24 void Idp1(ulong);
25 void Idp2(ulong);
26 void Idp3(ulong);
27
28 void Imul(ulong);
29 void Imula(ulong);
30 void Imull(ulong);
31
32 void Iswap(ulong);
33 void Imem1(ulong);
34 void Imem2(ulong);
35 void Ilsm(ulong inst);
36
37 void Ib(ulong);
38 void Ibl(ulong);
39
40 void Ssyscall(ulong);
41
42 Inst itab[] =
43 {
44 { Idp0, "AND", Iarith }, /* 00 - r,r,r */
45 { Idp0, "EOR", Iarith }, /* 01 */
46 { Idp0, "SUB", Iarith }, /* 02 */
47 { Idp0, "RSB", Iarith }, /* 03 */
48 { Idp0, "ADD", Iarith }, /* 04 */
49 { Idp0, "ADC", Iarith }, /* 05 */
50 { Idp0, "SBC", Iarith }, /* 06 */
51 { Idp0, "RSC", Iarith }, /* 07 */
52 { Idp0, "TST", Iarith }, /* 08 */
53 { Idp0, "TEQ", Iarith }, /* 09 */
54
55 { Idp0, "CMP", Iarith }, /* 10 */
56 { Idp0, "CMN", Iarith }, /* 11 */
57 { Idp0, "ORR", Iarith }, /* 12 */
58 { Idp0, "MOV", Iarith }, /* 13 */
59 { Idp0, "BIC", Iarith }, /* 14 */
60 { Idp0, "MVN", Iarith }, /* 15 */
61 { Idp1, "AND", Iarith }, /* 16 */
62 { Idp1, "EOR", Iarith }, /* 17 */
63 { Idp1, "SUB", Iarith }, /* 18 */
64 { Idp1, "RSB", Iarith }, /* 19 */
65
66 { Idp1, "ADD", Iarith }, /* 20 */
67 { Idp1, "ADC", Iarith }, /* 21 */
68 { Idp1, "SBC", Iarith }, /* 22 */
69 { Idp1, "RSC", Iarith }, /* 23 */
70 { Idp1, "TST", Iarith }, /* 24 */
71 { Idp1, "TEQ", Iarith }, /* 25 */
72 { Idp1, "CMP", Iarith }, /* 26 */
73 { Idp1, "CMN", Iarith }, /* 27 */
74 { Idp1, "ORR", Iarith }, /* 28 */
75 { Idp1, "MOV", Iarith }, /* 29 */
76
77 { Idp1, "BIC", Iarith }, /* 30 */
78 { Idp1, "MVN", Iarith }, /* 31 */
79 { Idp2, "AND", Iarith }, /* 32 */
80 { Idp2, "EOR", Iarith }, /* 33 */
81 { Idp2, "SUB", Iarith }, /* 34 */
82 { Idp2, "RSB", Iarith }, /* 35 */
83 { Idp2, "ADD", Iarith }, /* 36 */
84 { Idp2, "ADC", Iarith }, /* 37 */
85 { Idp2, "SBC", Iarith }, /* 38 */
86 { Idp2, "RSC", Iarith }, /* 39 */
87
88 { Idp2, "TST", Iarith }, /* 40 */
89 { Idp2, "TEQ", Iarith }, /* 41 */
90 { Idp2, "CMP", Iarith }, /* 42 */
91 { Idp2, "CMN", Iarith }, /* 43 */
92 { Idp2, "ORR", Iarith }, /* 44 */
93 { Idp2, "MOV", Iarith }, /* 45 */
94 { Idp2, "BIC", Iarith }, /* 46 */
95 { Idp2, "MVN", Iarith }, /* 47 */
96 { Idp3, "AND", Iarith }, /* 48 - i,r,r */
97 { Idp3, "EOR", Iarith }, /* 49 */
98
99 { Idp3, "SUB", Iarith }, /* 50 */
100 { Idp3, "RSB", Iarith }, /* 51 */
101 { Idp3, "ADD", Iarith }, /* 52 */
102 { Idp3, "ADC", Iarith }, /* 53 */
103 { Idp3, "SBC", Iarith }, /* 54 */
104 { Idp3, "RSC", Iarith }, /* 55 */
105 { Idp3, "TST", Iarith }, /* 56 */
106 { Idp3, "TEQ", Iarith }, /* 57 */
107 { Idp3, "CMP", Iarith }, /* 58 */
108 { Idp3, "CMN", Iarith }, /* 59 */
109
110 { Idp3, "ORR", Iarith }, /* 60 */
111 { Idp3, "MOV", Iarith }, /* 61 */
112 { Idp3, "BIC", Iarith }, /* 62 */
113 { Idp3, "MVN", Iarith }, /* 63 */
114 { Imul, "MUL", Iarith }, /* 64 */
115 { Imula, "MULA", Iarith }, /* 65 */
116
117 { Iswap, "SWPW", Imem }, /* 66 */
118 { Iswap, "SWPBU", Imem }, /* 67 */
119
120 { Imem2, "MOV", Imem }, /* 68 load/store h/sb */
121 { Imem2, "MOV", Imem }, /* 69 */
122 { Imem2, "MOV", Imem }, /* 70 */
123 { Imem2, "MOV", Imem }, /* 71 */
124
125 { Imem1, "MOVW", Imem }, /* 72 load/store w/ub i,r */
126 { Imem1, "MOVB", Imem }, /* 73 */
127 { Imem1, "MOVW", Imem }, /* 74 */
128 { Imem1, "MOVB", Imem }, /* 75 */
129 { Imem1, "MOVW", Imem }, /* 76 load/store r,r */
130 { Imem1, "MOVB", Imem }, /* 77 */
131 { Imem1, "MOVW", Imem }, /* 78 */
132 { Imem1, "MOVB", Imem }, /* 79 */
133
134 { Ilsm, "LDM", Imem }, /* 80 block move r,r */
135 { Ilsm, "STM", Imem }, /* 81 */
136 { Ib, "B", Ibranch }, /* 82 branch */
137 { Ibl, "BL", Ibranch }, /* 83 */
138 { Ssyscall, "SWI", Isyscall }, /* 84 co processor */
139 { undef, "undef" }, /* 85 */
140 { undef, "undef" }, /* 86 */
141 { undef, "undef" }, /* 87 */
142 { Imull, "MULLU", Iarith }, /* 88 */
143 { Imull, "MULALU", Iarith }, /* 89 */
144 { Imull, "MULL", Iarith }, /* 90 */
145 { Imull, "MULAL", Iarith }, /* 91 */
146 { undef, "undef" }, /* 92 */
147
148 { 0 }
149 };
150
151 int
runcmp(void)152 runcmp(void)
153 {
154 switch(reg.cond) {
155 case 0x0: /* eq */ return (reg.cc1 == reg.cc2);
156 case 0x1: /* ne */ return (reg.cc1 != reg.cc2);
157 case 0x2: /* hs */ return ((ulong)reg.cc1 >= (ulong)reg.cc2);
158 case 0x3: /* lo */ return ((ulong)reg.cc1 < (ulong)reg.cc2);
159 case 0x4: /* mi */ return (reg.cc1 - reg.cc2 < 0);
160 case 0x5: /* pl */ return (reg.cc1 - reg.cc2 >= 0);
161 case 0x8: /* hi */ return ((ulong)reg.cc1 > (ulong)reg.cc2);
162 case 0x9: /* ls */ return ((ulong)reg.cc1 <= (ulong)reg.cc2);
163 case 0xa: /* ge */ return (reg.cc1 >= reg.cc2);
164 case 0xb: /* lt */ return (reg.cc1 < reg.cc2);
165 case 0xc: /* gt */ return (reg.cc1 > reg.cc2);
166 case 0xd: /* le */ return (reg.cc1 <= reg.cc2);
167 case 0xe: /* al */ return 1;
168 case 0xf: /* nv */ return 0;
169 default:
170 Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n",
171 reg.cond, reg.cc1, reg.cc2);
172 undef(reg.ir);
173 return 0;
174 }
175 }
176
177 int
runteq(void)178 runteq(void)
179 {
180 long res = reg.cc1 ^ reg.cc2;
181 switch(reg.cond) {
182 case 0x0: /* eq */ return res == 0;
183 case 0x1: /* ne */ return res != 0;
184 case 0x4: /* mi */ return (res & SIGNBIT) != 0;
185 case 0x5: /* pl */ return (res & SIGNBIT) == 0;
186 case 0xe: /* al */ return 1;
187 case 0xf: /* nv */ return 0;
188 default:
189 Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n",
190 reg.cond, reg.cc1, reg.cc2);
191 undef(reg.ir);
192 return 0;
193 }
194 }
195
196 int
runtst(void)197 runtst(void)
198 {
199 long res = reg.cc1 & reg.cc2;
200 switch(reg.cond) {
201 case 0x0: /* eq */ return res == 0;
202 case 0x1: /* ne */ return res != 0;
203 case 0x4: /* mi */ return (res & SIGNBIT) != 0;
204 case 0x5: /* pl */ return (res & SIGNBIT) == 0;
205 case 0xe: /* al */ return 1;
206 case 0xf: /* nv */ return 0;
207 default:
208 Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n",
209 reg.cond, reg.cc1, reg.cc2);
210 undef(reg.ir);
211 return 0;
212 }
213 }
214
215 void
run(void)216 run(void)
217 {
218 int execute;
219
220 do {
221 if(trace)
222 Bflush(bioout);
223 reg.ar = reg.r[REGPC];
224 reg.ir = ifetch(reg.ar);
225 reg.class = armclass(reg.ir);
226 reg.ip = &itab[reg.class];
227 reg.cond = (reg.ir>>28) & 0xf;
228 switch(reg.compare_op) {
229 case CCcmp:
230 execute = runcmp();
231 break;
232 case CCteq:
233 execute = runteq();
234 break;
235 case CCtst:
236 execute = runtst();
237 break;
238 default:
239 Bprint(bioout, "unimplemented compare operation %x\n",
240 reg.compare_op);
241 return;
242 }
243
244 if(execute) {
245 reg.ip->count++;
246 (*reg.ip->func)(reg.ir);
247 } else {
248 if(trace)
249 itrace("%s%s IGNORED",
250 reg.ip->name, cond[reg.cond]);
251 }
252 reg.r[REGPC] += 4;
253 if(bplist)
254 brkchk(reg.r[REGPC], Instruction);
255 } while(--count);
256 }
257
258 void
undef(ulong inst)259 undef(ulong inst)
260 {
261 Bprint(bioout, "undefined instruction trap pc #%lux inst %.8lux class %d\n",
262 reg.r[REGPC], inst, reg.class);
263 longjmp(errjmp, 0);
264 }
265
266 long
shift(long v,int st,int sc,int isreg)267 shift(long v, int st, int sc, int isreg)
268 {
269 if(sc == 0) {
270 switch(st) {
271 case 0: /* logical left */
272 reg.cout = reg.cbit;
273 break;
274 case 1: /* logical right */
275 reg.cout = (v >> 31) & 1;
276 break;
277 case 2: /* arith right */
278 reg.cout = reg.cbit;
279 break;
280 case 3: /* rotate right */
281 if(isreg) {
282 reg.cout = reg.cbit;
283 }
284 else {
285 reg.cout = v & 1;
286 v = ((ulong)v >> 1) | (reg.cbit << 31);
287 }
288 }
289 }
290 else {
291 switch(st) {
292 case 0: /* logical left */
293 reg.cout = (v >> (32 - sc)) & 1;
294 v = v << sc;
295 break;
296 case 1: /* logical right */
297 reg.cout = (v >> (sc - 1)) & 1;
298 v = (ulong)v >> sc;
299 break;
300 case 2: /* arith right */
301 if(sc >= 32) {
302 reg.cout = (v >> 31) & 1;
303 if(reg.cout)
304 v = 0xFFFFFFFF;
305 else
306 v = 0;
307 }
308 else {
309 reg.cout = (v >> (sc - 1)) & 1;
310 v = (long)v >> sc;
311 }
312 break;
313 case 3: /* rotate right */
314 reg.cout = (v >> (sc - 1)) & 1;
315 v = (v << (32-sc)) | ((ulong)v >> sc);
316 break;
317 }
318 }
319 return v;
320 }
321
322 void
dpex(long inst,long o1,long o2,int rd)323 dpex(long inst, long o1, long o2, int rd)
324 {
325 int cbit;
326
327 cbit = 0;
328 switch((inst>>21) & 0xf) {
329 case 0: /* and */
330 reg.r[rd] = o1 & o2;
331 cbit = 1;
332 break;
333 case 1: /* eor */
334 reg.r[rd] = o1 ^ o2;
335 cbit = 1;
336 break;
337 case 2: /* sub */
338 reg.r[rd] = o1 - o2;
339 case 10: /* cmp */
340 if(inst & Sbit) {
341 reg.cc1 = o1;
342 reg.cc2 = o2;
343 reg.compare_op = CCcmp;
344 }
345 return;
346 case 3: /* rsb */
347 reg.r[rd] = o2 - o1;
348 if(inst & Sbit) {
349 reg.cc1 = o2;
350 reg.cc2 = o1;
351 reg.compare_op = CCcmp;
352 }
353 return;
354 case 4: /* add */
355 if(calltree && rd == REGPC && o2 == 0) {
356 Symbol s;
357
358 findsym(o1 + o2, CTEXT, &s);
359 Bprint(bioout, "%8lux return to %lux %s r0=%lux\n",
360 reg.r[REGPC], o1 + o2, s.name, reg.r[REGRET]);
361 }
362 reg.r[rd] = o1 + o2;
363 if(inst & Sbit) {
364 if(((uvlong)(ulong)o1 + (uvlong)(ulong)o2) & (1LL << 32))
365 reg.cbit = 1;
366 else
367 reg.cbit = 0;
368 reg.cc1 = o2;
369 reg.cc2 = -o1;
370 reg.compare_op = CCcmp;
371 }
372 return;
373 case 5: /* adc */
374 case 6: /* sbc */
375 case 7: /* rsc */
376 undef(inst);
377 case 8: /* tst */
378 if(inst & Sbit) {
379 reg.cc1 = o1;
380 reg.cc2 = o2;
381 reg.compare_op = CCtst;
382 }
383 return;
384 case 9: /* teq */
385 if(inst & Sbit) {
386 reg.cc1 = o1;
387 reg.cc2 = o2;
388 reg.compare_op = CCteq;
389 }
390 return;
391 case 11: /* cmn */
392 if(inst & Sbit) {
393 reg.cc1 = o1;
394 reg.cc2 = -o2;
395 reg.compare_op = CCcmp;
396 }
397 return;
398 case 12: /* orr */
399 reg.r[rd] = o1 | o2;
400 cbit = 1;
401 break;
402 case 13: /* mov */
403 reg.r[rd] = o2;
404 cbit = 1;
405 break;
406 case 14: /* bic */
407 reg.r[rd] = o1 & ~o2;
408 cbit = 1;
409 break;
410 case 15: /* mvn */
411 reg.r[rd] = ~o2;
412 cbit = 1;
413 break;
414 }
415 if(inst & Sbit) {
416 if(cbit)
417 reg.cbit = reg.cout;
418 reg.cc1 = reg.r[rd];
419 reg.cc2 = 0;
420 reg.compare_op = CCcmp;
421 }
422 }
423
424 /*
425 * data processing instruction R,R,R
426 */
427 void
Idp0(ulong inst)428 Idp0(ulong inst)
429 {
430 int rn, rd, rm;
431 long o1, o2;
432
433 rn = (inst>>16) & 0xf;
434 rd = (inst>>12) & 0xf;
435 rm = inst & 0xf;
436 o1 = reg.r[rn];
437 if(rn == REGPC)
438 o1 += 8;
439 o2 = reg.r[rm];
440 if(rm == REGPC)
441 o2 += 8;
442
443 dpex(inst, o1, o2, rd);
444 if(trace)
445 itrace("%s%s\tR%d,R%d,R%d =#%x",
446 reg.ip->name, cond[reg.cond],
447 rm, rn, rd,
448 reg.r[rd]);
449 if(rd == REGPC)
450 reg.r[rd] -= 4;
451 }
452
453 /*
454 * data processing instruction (R<>#),R,R
455 */
456 void
Idp1(ulong inst)457 Idp1(ulong inst)
458 {
459 int rn, rd, rm, st, sc;
460 long o1, o2;
461
462 rn = (inst>>16) & 0xf;
463 rd = (inst>>12) & 0xf;
464 rm = inst & 0xf;
465 st = (inst>>5) & 0x3;
466 sc = (inst>>7) & 0x1f;
467 o1 = reg.r[rn];
468 if(rn == REGPC)
469 o1 += 8;
470 o2 = reg.r[rm];
471 if(rm == REGPC)
472 o2 += 8;
473 o2 = shift(o2, st, sc, 0);
474 dpex(inst, o1, o2, rd);
475 if(trace)
476 itrace("%s%s\tR%d%s%d,R%d,R%d =#%x",
477 reg.ip->name, cond[reg.cond], rm, shtype[st], sc, rn, rd,
478 reg.r[rd]);
479 if(rd == REGPC)
480 reg.r[rd] -= 4;
481 }
482
483 /*
484 * data processing instruction (R<>R),R,R
485 */
486 void
Idp2(ulong inst)487 Idp2(ulong inst)
488 {
489 int rn, rd, rm, rs, st;
490 long o1, o2, o3;
491
492 rn = (inst>>16) & 0xf;
493 rd = (inst>>12) & 0xf;
494 rm = inst & 0xf;
495 st = (inst>>5) & 0x3;
496 rs = (inst>>8) & 0xf;
497 o1 = reg.r[rn];
498 if(rn == REGPC)
499 o1 += 8;
500 o2 = reg.r[rm];
501 if(rm == REGPC)
502 o2 += 8;
503 o3 = reg.r[rs];
504 if(rs == REGPC)
505 o3 += 8;
506 o2 = shift(o2, st, o3, 1);
507 dpex(inst, o1, o2, rd);
508 if(trace)
509 itrace("%s%s\tR%d%sR%d=%d,R%d,R%d =#%x",
510 reg.ip->name, cond[reg.cond], rm, shtype[st], rs, o3, rn, rd,
511 reg.r[rd]);
512 if(rd == REGPC)
513 reg.r[rd] -= 4;
514 }
515
516 /*
517 * data processing instruction #<>#,R,R
518 */
519 void
Idp3(ulong inst)520 Idp3(ulong inst)
521 {
522 int rn, rd, sc;
523 long o1, o2;
524
525 rn = (inst>>16) & 0xf;
526 rd = (inst>>12) & 0xf;
527 o1 = reg.r[rn];
528 if(rn == REGPC)
529 o1 += 8;
530 o2 = inst & 0xff;
531 sc = (inst>>7) & 0x1e;
532 o2 = (o2 >> sc) | (o2 << (32 - sc));
533
534 dpex(inst, o1, o2, rd);
535 if(trace)
536 itrace("%s%s\t#%x,R%d,R%d =#%x",
537 reg.ip->name, cond[reg.cond], o2, rn, rd,
538 reg.r[rd]);
539 if(rd == REGPC)
540 reg.r[rd] -= 4;
541 }
542
543 void
Imul(ulong inst)544 Imul(ulong inst)
545 {
546 int rs, rd, rm;
547
548 rd = (inst>>16) & 0xf;
549 rs = (inst>>8) & 0xf;
550 rm = inst & 0xf;
551
552 if(rd == REGPC || rs == REGPC || rm == REGPC || rd == rm)
553 undef(inst);
554
555 reg.r[rd] = reg.r[rm]*reg.r[rs];
556
557 if(trace)
558 itrace("%s%s\tR%d,R%d,R%d =#%x",
559 reg.ip->name, cond[reg.cond], rs, rm, rd,
560 reg.r[rd]);
561 }
562
563 void
Imull(ulong inst)564 Imull(ulong inst)
565 {
566 vlong v;
567 int rs, rd, rm, rn;
568
569 rd = (inst>>16) & 0xf;
570 rn = (inst>>12) & 0xf;
571 rs = (inst>>8) & 0xf;
572 rm = inst & 0xf;
573
574 if(rd == REGPC || rn == REGPC || rs == REGPC || rm == REGPC
575 || rd == rm || rn == rm || rd == rn)
576 undef(inst);
577
578 if(inst & (1<<22)){
579 v = (vlong)reg.r[rm] * (vlong)reg.r[rs];
580 if(inst & (1 << 21))
581 v += reg.r[rn];
582 }else{
583 v = (uvlong)(ulong)reg.r[rm] * (uvlong)(ulong)reg.r[rs];
584 if(inst & (1 << 21))
585 v += (ulong)reg.r[rn];
586 }
587 reg.r[rd] = v >> 32;
588 reg.r[rn] = v;
589
590 if(trace)
591 itrace("%s%s\tR%d,R%d,(R%d,R%d) =#%llx",
592 reg.ip->name, cond[reg.cond], rs, rm, rn, rd,
593 v);
594 }
595
596 void
Imula(ulong inst)597 Imula(ulong inst)
598 {
599 int rs, rd, rm, rn;
600
601 rd = (inst>>16) & 0xf;
602 rn = (inst>>12) & 0xf;
603 rs = (inst>>8) & 0xf;
604 rm = inst & 0xf;
605
606 if(rd == REGPC || rn == REGPC || rs == REGPC || rm == REGPC || rd == rm)
607 undef(inst);
608
609 reg.r[rd] = reg.r[rm]*reg.r[rs] + reg.r[rn];
610
611 if(trace)
612 itrace("%s%s\tR%d,R%d,R%d,R%d =#%x",
613 reg.ip->name, cond[reg.cond], rs, rm, rn, rd,
614 reg.r[rd]);
615 }
616
617 void
Iswap(ulong inst)618 Iswap(ulong inst)
619 {
620 int rn, rd, rm;
621 ulong address, value, bbit;
622
623 bbit = inst & (1<<22);
624 rn = (inst>>16) & 0xf;
625 rd = (inst>>12) & 0xf;
626 rm = (inst>>0) & 0xf;
627
628 address = reg.r[rn];
629 if(bbit) {
630 value = getmem_b(address);
631 putmem_b(address, reg.r[rm]);
632 } else {
633 value = getmem_w(address);
634 putmem_w(address, reg.r[rm]);
635 }
636 reg.r[rd] = value;
637
638 if(trace) {
639 char *bw, *dotc;
640
641 bw = "";
642 if(bbit)
643 bw = "B";
644 dotc = cond[reg.cond];
645
646 itrace("SWP%s%s\t#%x(R%d),R%d #%lux=#%x",
647 bw, dotc,
648 rn, rd,
649 address, value);
650 }
651 }
652
653 /*
654 * load/store word/byte
655 */
656 void
Imem1(ulong inst)657 Imem1(ulong inst)
658 {
659 int rn, rd, off, rm, sc, st;
660 ulong address, value, pbit, ubit, bbit, wbit, lbit, bit25;
661
662 bit25 = inst & (1<<25);
663 pbit = inst & (1<<24);
664 ubit = inst & (1<<23);
665 bbit = inst & (1<<22);
666 wbit = inst & (1<<21);
667 lbit = inst & (1<<20);
668 rn = (inst>>16) & 0xf;
669 rd = (inst>>12) & 0xf;
670
671 SET(st);
672 SET(sc);
673 SET(rm);
674 if(bit25) {
675 rm = inst & 0xf;
676 st = (inst>>5) & 0x3;
677 sc = (inst>>7) & 0x1f;
678 off = reg.r[rm];
679 if(rm == REGPC)
680 off += 8;
681 off = shift(off, st, sc, 0);
682 } else {
683 off = inst & 0xfff;
684 }
685 if(!ubit)
686 off = -off;
687 if(rn == REGPC)
688 off += 8;
689
690 address = reg.r[rn];
691 if(pbit)
692 address += off;
693
694 if(lbit) {
695 if(bbit)
696 value = getmem_b(address);
697 else
698 value = getmem_w(address);
699 if(rd == REGPC)
700 value -= 4;
701 reg.r[rd] = value;
702 } else {
703 value = reg.r[rd];
704 if(rd == REGPC)
705 value -= 4;
706 if(bbit)
707 putmem_b(address, value);
708 else
709 putmem_w(address, value);
710 }
711 if(!(pbit && !wbit))
712 reg.r[rn] += off;
713
714 if(trace) {
715 char *bw, *dotp, *dotc;
716
717 bw = "W";
718 if(bbit)
719 bw = "BU";
720 dotp = "";
721 if(!pbit)
722 dotp = ".P";
723 dotc = cond[reg.cond];
724
725 if(lbit) {
726 if(!bit25)
727 itrace("MOV%s%s%s\t#%x(R%d),R%d #%lux=#%x",
728 bw, dotp, dotc,
729 off, rn, rd,
730 address, value);
731 else
732 itrace("MOV%s%s%s\t(R%d%s%d)(R%d),R%d #%lux=#%x",
733 bw, dotp, dotc,
734 rm, shtype[st], sc, rn, rd,
735 address, value);
736 } else {
737 if(!bit25)
738 itrace("MOV%s%s%s\tR%d,#%x(R%d) #%lux=#%x",
739 bw, dotp, dotc,
740 rd, off, rn,
741 address, value);
742 else
743 itrace("MOV%s%s%s\tR%d,(R%d%s%d)(R%d) #%lux=#%x",
744 bw, dotp, dotc,
745 rd, rm, shtype[st], sc, rn,
746 address, value);
747 }
748 }
749 }
750
751 /*
752 * load/store unsigned byte/half word
753 */
754 void
Imem2(ulong inst)755 Imem2(ulong inst)
756 {
757 int rn, rd, off, rm;
758 ulong address, value, pbit, ubit, hbit, sbit, wbit, lbit, bit22;
759
760 pbit = inst & (1<<24);
761 ubit = inst & (1<<23);
762 bit22 = inst & (1<<22);
763 wbit = inst & (1<<21);
764 lbit = inst & (1<<20);
765 sbit = inst & (1<<6);
766 hbit = inst & (1<<5);
767 rn = (inst>>16) & 0xf;
768 rd = (inst>>12) & 0xf;
769
770 SET(rm);
771 if(bit22) {
772 off = ((inst>>4) & 0xf0) | (inst & 0xf);
773 } else {
774 rm = inst & 0xf;
775 off = reg.r[rm];
776 if(rm == REGPC)
777 off += 8;
778 }
779 if(!ubit)
780 off = -off;
781 if(rn == REGPC)
782 off += 8;
783
784 address = reg.r[rn];
785 if(pbit)
786 address += off;
787
788 if(lbit) {
789 if(hbit) {
790 value = getmem_h(address);
791 if(sbit && (value & 0x8000))
792 value |= 0xffff0000;
793 } else {
794 value = getmem_b(address);
795 if(value & 0x80)
796 value |= 0xffffff00;
797 }
798 if(rd == REGPC)
799 value -= 4;
800 reg.r[rd] = value;
801 } else {
802 value = reg.r[rd];
803 if(rd == REGPC)
804 value -= 4;
805 if(hbit) {
806 putmem_h(address, value);
807 } else {
808 putmem_b(address, value);
809 }
810 }
811 if(!(pbit && !wbit))
812 reg.r[rn] += off;
813
814 if(trace) {
815 char *hb, *dotp, *dotc;
816
817 hb = "B";
818 if(hbit)
819 hb = "H";
820 dotp = "";
821 if(!pbit)
822 dotp = ".P";
823 dotc = cond[reg.cond];
824
825 if(lbit) {
826 if(bit22)
827 itrace("MOV%s%s%s\t#%x(R%d),R%d #%lux=#%x",
828 hb, dotp, dotc,
829 off, rn, rd,
830 address, value);
831 else
832 itrace("MOV%s%s%s\t(R%d)(R%d),R%d #%lux=#%x",
833 hb, dotp, dotc,
834 rm, rn, rd,
835 address, value);
836 } else {
837 if(bit22)
838 itrace("MOV%s%s%s\tR%d,#%x(R%d) #%lux=#%x",
839 hb, dotp, dotc,
840 rd, off, rn,
841 address, value);
842 else
843 itrace("MOV%s%s%s\tR%d,(R%d)(R%d) #%lux=#%x",
844 hb, dotp, dotc,
845 rd, rm, rn,
846 address, value);
847 }
848 }
849 }
850
851 void
Ilsm(ulong inst)852 Ilsm(ulong inst)
853 {
854 char pbit, ubit, sbit, wbit, lbit;
855 int i, rn, reglist;
856 ulong address, predelta, postdelta;
857
858 pbit = (inst>>24) & 0x1;
859 ubit = (inst>>23) & 0x1;
860 sbit = (inst>>22) & 0x1;
861 wbit = (inst>>21) & 0x1;
862 lbit = (inst>>20) & 0x1;
863 rn = (inst>>16) & 0xf;
864 reglist = inst & 0xffff;
865
866 if(reglist & 0x8000)
867 undef(reg.ir);
868 if(sbit)
869 undef(reg.ir);
870
871 address = reg.r[rn];
872
873 if(pbit) {
874 predelta = 4;
875 postdelta = 0;
876 } else {
877 predelta = 0;
878 postdelta = 4;
879 }
880 if(ubit) {
881 for (i = 0; i < 16; ++i) {
882 if(!(reglist & (1 << i)))
883 continue;
884 address += predelta;
885 if(lbit)
886 reg.r[i] = getmem_w(address);
887 else
888 putmem_w(address, reg.r[i]);
889 address += postdelta;
890 }
891 } else {
892 for (i = 15; 0 <= i; --i) {
893 if(!(reglist & (1 << i)))
894 continue;
895 address -= predelta;
896 if(lbit)
897 reg.r[i] = getmem_w(address);
898 else
899 putmem_w(address, reg.r[i]);
900 address -= postdelta;
901 }
902 }
903 if(wbit) {
904 reg.r[rn] = address;
905 }
906
907 if(trace) {
908 itrace("%s.%c%c\tR%d=%lux%s, <%lux>",
909 (lbit ? "LDM" : "STM"), (ubit ? 'I' : 'D'), (pbit ? 'B' : 'A'),
910 rn, reg.r[rn], (wbit ? "!" : ""), reglist);
911 }
912 }
913
914 void
Ib(ulong inst)915 Ib(ulong inst)
916 {
917 long v;
918
919 v = inst & 0xffffff;
920 v = reg.r[REGPC] + 8 + ((v << 8) >> 6);
921 if(trace)
922 itrace("B%s\t#%lux", cond[reg.cond], v);
923 reg.r[REGPC] = v - 4;
924 }
925
926 void
Ibl(ulong inst)927 Ibl(ulong inst)
928 {
929 long v;
930 Symbol s;
931
932 v = inst & 0xffffff;
933 v = reg.r[REGPC] + 8 + ((v << 8) >> 6);
934 if(trace)
935 itrace("BL%s\t#%lux", cond[reg.cond], v);
936
937 if(calltree) {
938 findsym(v, CTEXT, &s);
939 Bprint(bioout, "%8lux %s(", reg.r[REGPC], s.name);
940 printparams(&s, reg.r[13]);
941 Bprint(bioout, "from ");
942 printsource(reg.r[REGPC]);
943 Bputc(bioout, '\n');
944 }
945
946 reg.r[REGLINK] = reg.r[REGPC] + 4;
947 reg.r[REGPC] = v - 4;
948 }
949