]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/5i/run.c
mothra: never snarf the "Go:" box
[plan9front.git] / sys / src / cmd / 5i / run.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }