|
|
1.1 root 1: typedef long Type;
2:
3: /*
4: * This C version compiles for an abstract machine, and an interpreter
5: * is used to execute the program. The program consists of opcdoes
6: * from the following enumeration. Some opcodes take arguments: arguments
7: * are put in longs immediately following the opcode.
8: *
9: * Here is a description of the abstract machine. The `word' size is
10: * WBITS bits, usually 32.
11: *
12: * word registers:
13: * Rs holds word from source bitmap, then a word from
14: * source bitmap that may straddle a word boundary,
15: * and finally, result of doing the Rs op Rd operation,
16: * prior to storing in destination bitmap
17: * Rd holds word from destination bitmap
18: * Rt used to hold some bits from a source bitmap that will
19: * be used to make a properly aligned source word later
20: * Ru an additional register used in converting bitblts to
21: * hold some source bits (to avoid the need to fetch a
22: * source word more than once)
23: * Ri inner loop count: how many more words in row
24: * Ro outer loop count: how many more rows
25: *
26: * address registers:
27: * As address in source bitmap
28: * Ad address in destination bitmap
29: * AT address of a conversion table
30: *
31: * small constant registers (These don't change after they are set.
32: * In most implementations, these values are
33: * not in explicit registers, but rather, the
34: * values are encoded in the instructions that use them.)
35: *
36: * sha shift value a
37: * shb shift value b
38: * osiz number of bytes in conversion table entries
39: *
40: * operations:
41: * The operations of the abstract machine are the following:
42: * enumeration. Many of them take an argument or two.
43: *
44: * field(m): replace Rs with a value that has Rs contents where
45: * the mask m has 1's, and has Rd contents where mask m
46: * 0's.
47: *
48: * [lr]sh_RxRy(c): replace Rx with Ry shifted logically left
49: * or right by c (for various Rx, Ry)
50: *
51: * [lr]sh[ab]_RxRy: replace Rx with Ry shifted logically left
52: * or right by value of sha or shb (for various Rx, Ry)
53: *
54: * [lr]shb_RxRy: replace Rx with Ry shifted logically left
55: * or right by value of shb (for various Rx, Ry)
56: *
57: * or[lr]sh_RxRy(c): OR into Rx the value of Ry shifted logically
58: * left or right by c (for various Rx, Ry)
59: *
60: * or[lr]sh[ab]_RxRy: OR into Rx the value of Ry shifted logically
61: * left or right by value of sha or shb (for various Rx, Ry)
62: *
63: * add_A[sd](c): add the argument number of bytes to the address in
64: * As or Ad
65: *
66: * or_RsRd: replace Rs with Rs|Rd
67: *
68: * Initsd(s,d): init As and Ad from the given arguments
69: *
70: * [io]label(c): set Ri or Ro to c
71: *
72: * [io]loop(a): decrement Ri or Ro, and if it is still > 0, go to
73: * address a
74: *
75: * rts: return to caller
76: *
77: * load_Rx: load Rx with value at address in As (various Rx).
78: * [On machines where the real machine registers are
79: * bigger than WBITS, the load_ operations need
80: * can do whatever they like with the upper bits of
81: * the register. There is also a need for some
82: * loadzx_ operations, which must fill the upper bits
83: * with zeros, and loador_ operations which must leave
84: * the high order bits alone, but can assume that the
85: * low WBITS bits are zero.]
86: *
87: * load_Rx_P: like OLoad_Rx, then postincrement As by one word
88: *
89: * load_Rx_D: like OLoad_Rx, but predecrement As by one word first
90: *
91: * fetch_Rd, OFetch_Rd_P, OFetch_Rd_D: like Loads, but use Ad
92: * as the address register (and all fetches go to Rd)
93: *
94: * store_Rs, OStore_Rs_P, OStore_Rs_D: like Loads, but store the
95: * word in Rs into memory, using address in Ad
96: *
97: * inittab(a,s): set At to a, and osiz to s.
98: *
99: * initsh(a,b): set sha to a, shb to b
100: *
101: * table_R[ds]Rt(o,n,l): starting at offset o in Rt (high order bit of word
102: * is offset 0), take n bits, and use it to look up a (1<<l) byte
103: * entry in table AT, putting answer in Rd or Rs. If WBITS is less
104: * than the real register size, the upper bits must be zeroed.
105: * [It is guaranteed that (1<<l) == osiz, so l can be ignored.]
106: *
107: * assemble(o,n): move low n bits of Rd into offset o in Rs.
108: * Can assume that high bits of Rd are zero, and target field
109: * of Rs is zero if offset != 0
110: *
111: * assemblex(o,n): if o is 0, copy Rd to Rs; else shift Rs left n
112: * and OR Rd into it. [This will give the same effect as
113: * assemble, because it will be used in a sequence that
114: * builds a whole word, such as: assemblex(0,16), assemblex(16,16)
115: *
116: * Ozero, ODnorS, etc.: replace Rs with value of Rs op Rd, where
117: * op is one of the 16 bitblt opcodes
118: */
119: enum
120: {
121: field, /* arg = field mask */
122: lsha_RsRt,
123: lshb_RsRt,
124: lsh_RsRd, /* arg = shift amount */
125: lsh_RtRt, /* arg = shift amount */
126: lsha_RtRt,
127: lsha_RtRu,
128: lshb_RtRu,
129: rsha_RsRt,
130: rshb_RsRt,
131: rsha_RtRu,
132: rshb_RtRu,
133: orlsha_RsRt,
134: orlshb_RsRt,
135: orlsh_RsRd, /* arg = shift amount */
136: orrsha_RsRt,
137: orrshb_RsRt,
138: orrsha_RtRu,
139: orrshb_RtRu,
140: or_RsRd,
141: add_As, /* arg = add amount */
142: add_Ad, /* arg = add amount */
143: initsd, /* arg1 = value for As; arg2 = value for Ad */
144: ilabel, /* arg = inner loop count value for Ri */
145: olabel, /* arg = outer loop count value for Ro */
146: iloop, /* arg = pointer to beginning of inner loop */
147: oloop, /* arg = pointer to beginning of outer loop */
148: rts,
149: load_Rs_P,
150: load_Rt_P,
151: load_Ru_P,
152: load_Rd_D,
153: load_Rs_D,
154: load_Rt_D,
155: load_Rd,
156: load_Rs,
157: load_Rt,
158: fetch_Rd_P,
159: fetch_Rd_D,
160: fetch_Rd,
161: store_Rs_P,
162: store_Rs_D,
163: store_Rs,
164: inittab, /* arg1 = table addr; arg2 = entry size (bytes) */
165: initsh, /* arg1 = shift amount a, arg2 = shift amount b */
166: table_RdRt, /* arg1 = offset, arg2 = nbits */
167: table_RsRt, /* arg1 = offset, arg2 = nbits */
168: assemble, /* arg1 = offset, arg2 = nbits */
169: assemblex, /* arg1 = offset, arg2 = nbits */
170: Ozero,
171: ODnorS,
172: ODandnotS,
173: OnotS,
174: OnotDandS,
175: OnotD,
176: ODxorS,
177: ODnandS,
178: ODandS,
179: ODxnorS,
180: OD,
181: ODornotS,
182: OnotDorS,
183: ODorS,
184: OF,
185: };
186:
187: /*
188: * Macros for assembling the operations of the abstract machine.
189: * Each assumes that Type *p points to the next location where
190: * an instruction should be assembled. The macros may also make
191: * use of these other variable values:
192: *
193: * tab value of AT register in abstract machine
194: * osiz value of osiz register in abstract machine
195: * sha value of sha register in abstract machine
196: * shb value of shb register in abstract machine
197: *
198: * Furthermore, there is a long called tmp which can be used for
199: * the duration of any macro.
200: *
201: * For the most part, the macros required are the same as the
202: * operations in the abstract machine (without a leading O,
203: * or with a lowercase initial letter). However, instead of
204: * macros for the bitblt opcodes Ozero, ..., OF, there is a
205: * macro called Emitop, which can use implicit arguments
206: * fi and fin (see Emitop, below).
207: *
208: * Some of the load macros take an argument f, which will be 1
209: * if the result of the load will be used by the next instruction.
210: * (Some architectures will require a Noop to be emitted when
211: * f is 1.)
212: *
213: * Finally, two other required macros are Extrainit, which can
214: * be used to do any implementation-specific initialization,
215: * and Execandfree(start,onstack), which must actually execute
216: * the compiled program and free the memory. If onstack is
217: * true, the program was compiled into a local array, so no
218: * memory need be freed. Otherwise, the space was obtained with
219: * bbmalloc, and must be freed by bbfree.
220: */
221:
222: #define Ofield(c) *p++ = field; *p++ = (c)
223: #define Olsha_RsRt *p++ = lsha_RsRt
224: #define Olshb_RsRt *p++ = lshb_RsRt
225: #define Olsh_RsRd(c) *p++ = lsh_RsRd; *p++ = (c)
226: #define Olsh_RtRt(c) *p++ = lsh_RtRt; *p++ = (c)
227: #define Olsha_RtRt *p++ = lsha_RtRt
228: #define Olsha_RtRu *p++ = lsha_RtRu
229: #define Olshb_RtRu *p++ = lshb_RtRu
230: #define Orsha_RsRt *p++ = rsha_RsRt
231: #define Orshb_RsRt *p++ = rshb_RsRt
232: #define Orsha_RtRu *p++ = rsha_RtRu
233: #define Orshb_RtRu *p++ = rshb_RtRu
234: #define Oorlsha_RsRt *p++ = orlsha_RsRt
235: #define Oorlshb_RsRt *p++ = orlshb_RsRt
236: #define Oorlsh_RsRd(c) *p++ = orlsh_RsRd; *p++ = (c)
237: #define Oorrsha_RsRt *p++ = orrsha_RsRt
238: #define Oorrshb_RsRt *p++ = orrshb_RsRt
239: #define Oorrsha_RtRu *p++ = orrsha_RtRu
240: #define Oorrshb_RtRu *p++ = orrshb_RtRu
241: #define Oor_RsRd *p++ = or_RsRd
242: #define Add_As(c) *p++ = add_As; *p++ = (c)
243: #define Add_Ad(c) *p++ = add_Ad; *p++ = (c)
244: #define Initsd(s,d) *p++ = initsd; *p++ = ((ulong)(s)); *p++ = ((ulong)(d))
245: #define Initsh(a,b) *p++ = initsh; *p++ = (a); *p++ = (b)
246: #define Extrainit
247: #define Ilabel(c) *p++ = ilabel; *p++ = (c)
248: #define Olabel(c) *p++ = olabel; *p++ = (c)
249: #define Iloop(lp) *p++ = iloop; *p++ = ((ulong)(lp))
250: #define Oloop(lp) *p++ = oloop; *p++ = ((ulong)(lp))
251: #define Orts *p++ = rts
252: #define Load_Rs_P *p++ = load_Rs_P
253: #define Load_Rt_P *p++ = load_Rt_P
254: #define Loadzx_Rt_P *p++ = load_Rt_P
255: #define Loador_Rt_P *p++ = load_Rt_P
256: #define Load_Ru_P *p++ = load_Ru_P
257: #define Load_Rd_D(f) *p++ = load_Rd_D
258: #define Load_Rs_D(f) *p++ = load_Rs_D
259: #define Load_Rt_D(f) *p++ = load_Rt_D
260: #define Loadzx_Rt_D(f) *p++ = load_Rt_D
261: #define Load_Rd(f) *p++ = load_Rd
262: #define Load_Rs(f) *p++ = load_Rs
263: #define Load_Rt(f) *p++ = load_Rt
264: #define Loadzx_Rt(f) *p++ = load_Rt
265: #define Fetch_Rd_P(f) *p++ = fetch_Rd_P
266: #define Fetch_Rd_D(f) *p++ = fetch_Rd_D
267: #define Fetch_Rd(f) *p++ = fetch_Rd
268: #define Store_Rs_P *p++ = store_Rs_P
269: #define Store_Rs_D *p++ = store_Rs_D
270: #define Store_Rs *p++ = store_Rs
271: #define Nop
272: #define Inittab(t,s) *p++ = inittab; *p++ = ((ulong)(t)); *p++ = (s)
273: #define Table_RdRt(o,n,l) *p++ = table_RdRt; *p++ = (o); *p++ = (n)
274: #define Table_RsRt(o,n,l) *p++ = table_RsRt; *p++ = (o); *p++ = (n)
275: #define Assemble(o,n) *p++ = assemble; *p++ = (o); *p++ = (n)
276: #define Assemblex(o,n) *p++ = assemble; *p++ = (o); *p++ = (n)
277:
278: #define Execandfree(memstart,onstack) \
279: interpret(memstart); \
280: if(!onstack) \
281: bbfree(memstart, (p-memstart) * sizeof(Type));
282:
283:
284: /*
285: * Emitop can assume that fi points at &fstr[op].instr, and
286: * that fin contains fstr[op].n, where op is the desired
287: * bitblt opcode as declared in gnot.h
288: */
289:
290: #define Emitop if(fin) *p++ = *fi;
291:
292: typedef struct Fstr
293: {
294: char fetchs;
295: char fetchd;
296: short n;
297: Type instr[1];
298: } Fstr;
299:
300: Fstr fstr[16] =
301: {
302: [0] 0,0,1, /* Zero */
303: {Ozero},
304:
305: [1] 1,1,1, /* DnorS */
306: {ODnorS},
307:
308: [2] 1,1,1, /* DandnotS */
309: {ODandnotS},
310:
311: [3] 1,0,1, /* notS */
312: {OnotS},
313:
314: [4] 1,1,1, /* notDandS */
315: {OnotDandS},
316:
317: [5] 0,1,1, /* notD */
318: {OnotD},
319:
320: [6] 1,1,1, /* DxorS */
321: {ODxorS},
322:
323: [7] 1,1,1, /* DnandS */
324: {ODnandS},
325:
326: [8] 1,1,1, /* DandS */
327: {ODandS},
328:
329: [9] 1,1,1, /* DxnorS */
330: {ODxnorS},
331:
332: [10] 0,1,1, /* D */
333: {OD},
334:
335: [11] 1,1,1, /* DornotS */
336: {ODornotS},
337:
338: [12] 1,0,0, /* S */
339: {0},
340:
341: [13] 1,1,1, /* notDorS */
342: {OnotDorS},
343:
344: [14] 1,1,1, /* DorS */
345: {ODorS},
346:
347: [15] 0,0,1, /* F */
348: {OF},
349: };
350:
351: #include "tabs.h"
352:
353: enum {
354: Progmax = 800, /* max number of words in a bitblt prog */
355: Progmaxnoconv = 50, /* max number of words when no conversion */
356: };
357:
358: static void
359: interpret(Type *pc)
360: {
361: ulong *As, *Ad;
362: ulong Rs, Rd, Rt, Ru;
363: long Ri, Ro;
364: uchar *AT;
365: int osiz, sha, shb, tmp;
366:
367: #ifdef TEST
368: ulong *Aslow, *Ashigh, *Adlow, *Adhigh;
369: void prprog(void);
370:
371: Rs = lrand();
372: Rd = lrand();
373: Rt = lrand();
374: Ru = lrand();
375: Ri = lrand();
376: Ro = lrand();
377: sha = lrand();
378: shb = lrand();
379: As = 0;
380: Ad = 0;
381: AT = 0;
382: Aslow = gaddr(cursm, curr.min);
383: Ashigh = gaddr(cursm, sub(curr.max, Pt(1,1)));
384: Adlow = gaddr(curdm, curpt);
385: Adhigh = gaddr(curdm, sub(add(curpt, sub(curr.max,curr.min)),Pt(1,1)));
386: #endif
387:
388: loop:
389: #ifdef TEST
390: switch(*pc) {
391: case load_Rs_P:
392: case load_Rt_P:
393: case load_Ru_P:
394: case load_Rd:
395: case load_Rs:
396: case load_Rt:
397: if(As < Aslow || As > Ashigh){
398: print("load from bad As %ux\n", As);
399: errplace:
400: print("src bitmap base %ux zero %d width %d r %d %d %d %d\n",
401: cursm->base, cursm->zero, cursm->width,
402: cursm->r.min.x, cursm->r.min.y,
403: cursm->r.max.x, cursm->r.max.y);
404: print("dst bitmap base %ux zero %d width %d r %d %d %d %d\n",
405: curdm->base, curdm->zero, curdm->width,
406: curdm->r.min.x, curdm->r.min.y,
407: curdm->r.max.x, curdm->r.max.y);
408: print("p %d %d r %d %d %d %d f %d\n",
409: curpt.x, curpt.y, curr.min.x, curr.min.y,
410: curr.max.x, curr.max.y, curf);
411: prprog();
412: exits("fail");
413: }
414: break;
415: case load_Rd_D:
416: case load_Rs_D:
417: case load_Rt_D:
418: if(As-1 < Aslow || As-1 > Ashigh){
419: print("load from bad As-1 %ux\n", As-1);
420: goto errplace;
421: }
422: break;
423: case fetch_Rd_P:
424: case fetch_Rd:
425: if(Ad < Adlow || Ad > Adhigh){
426: print("fetch from bad Ad %ux\n", Ad);
427: goto errplace;
428: }
429: break;
430: case store_Rs_P:
431: case store_Rs:
432: if(Ad < Adlow || Ad > Adhigh){
433: print("store to bad Ad %ux\n", Ad);
434: goto errplace;
435: }
436: break;
437: case fetch_Rd_D:
438: case store_Rs_D:
439: if(Ad-1 < Adlow || Ad-1 > Adhigh){
440: print("fetch from bad Ad-1 %ux\n", Ad-1);
441: prprog();
442: }
443: break;
444: }
445: #endif
446: switch(*pc++) {
447: default:
448: #ifdef TEST
449: print("unknown opcode %d\n", pc[-1]);
450: goto errplace;
451: #else
452: return;
453: #endif
454: case field:
455: /* Rs gets Rd where mask bits are 0s, Rs where mask bits are 1s */
456: Rs = ((Rs ^ Rd) & *pc++) ^ Rd;
457: break;
458:
459: case lsha_RsRt:
460: Rs = Rt << sha;
461: break;
462:
463: case lshb_RsRt:
464: Rs = Rt << shb;
465: break;
466:
467: case lsh_RsRd:
468: Rs = Rd << *pc++;
469: break;
470:
471: case lsh_RtRt: /* arg = shift amount */
472: Rt <<= *pc++;
473: break;
474:
475: case lsha_RtRt:
476: Rt <<= sha;
477: break;
478:
479: case lsha_RtRu:
480: Rt = Ru << sha;
481: break;
482:
483: case lshb_RtRu:
484: Rt = Ru << shb;
485: break;
486:
487: case rsha_RsRt:
488: Rs = Rt >> sha;
489: break;
490:
491: case rshb_RsRt:
492: Rs = Rt >> shb;
493: break;
494:
495: case rsha_RtRu:
496: Rt = Ru >> sha;
497: break;
498:
499: case rshb_RtRu:
500: Rt = Ru >> shb;
501: break;
502:
503: case orlsha_RsRt:
504: Rs |= Rt << sha;
505: break;
506:
507: case orlshb_RsRt:
508: Rs |= Rt << shb;
509: break;
510:
511: case orlsh_RsRd: /* arg = shift amount */
512: Rs |= Rd << *pc++;
513: break;
514:
515: case orrsha_RsRt:
516: Rs |= Rt >> sha;
517: break;
518:
519: case orrshb_RsRt:
520: Rs |= Rt >> shb;
521: break;
522:
523: case orrsha_RtRu:
524: Rt |= Ru >> sha;
525: break;
526:
527: case orrshb_RtRu:
528: Rt |= Ru >> shb;
529: break;
530:
531: case or_RsRd:
532: Rs |= Rd;
533: break;
534:
535: case add_As:
536: As = (ulong*)((char*)As + (long)*pc++);
537: break;
538:
539: case add_Ad:
540: Ad = (ulong*)((char*)Ad + (long)*pc++);
541: break;
542:
543: case initsd:
544: As = (ulong*)pc[0];
545: Ad = (ulong*)pc[1];
546: pc += 2;
547: break;
548:
549: case ilabel:
550: /* initialize inner loop count */
551: Ri = *pc++;
552: break;
553:
554: case olabel:
555: /* initialize outer loop count */
556: Ro = *pc++;
557: break;
558:
559: case iloop:
560: /* decrement inner loop count, loop back if still positive */
561: Ri--;
562: if(Ri > 0) {
563: pc = (Type*)pc[0];
564: break;
565: }
566: pc++;
567: break;
568:
569: case oloop:
570: /* decrement outer loop count, loop back if still positive */
571: Ro--;
572: if(Ro > 0) {
573: pc = (Type*)pc[0];
574: break;
575: }
576: pc++;
577: break;
578:
579: case rts:
580: return;
581:
582: case load_Rs_P:
583: Rs = *As++;
584: break;
585:
586: case load_Rt_P:
587: Rt = *As++;
588: break;
589:
590: case load_Ru_P:
591: Ru = *As++;
592: break;
593:
594: case load_Rd_D:
595: Rd = *--As;
596: break;
597:
598: case load_Rs_D:
599: Rs = *--As;
600: break;
601:
602: case load_Rt_D:
603: Rt = *--As;
604: break;
605:
606: case load_Rd:
607: Rd = *As;
608: break;
609:
610: case load_Rs:
611: Rs = *As;
612: break;
613:
614: case load_Rt:
615: Rt = *As;
616: break;
617:
618: case fetch_Rd_P:
619: Rd = *Ad++;
620: break;
621:
622: case fetch_Rd_D:
623: Rd = *--Ad;
624: break;
625:
626: case fetch_Rd:
627: Rd = *Ad;
628: break;
629:
630: case store_Rs_P:
631: *Ad++ = Rs;
632: break;
633:
634: case store_Rs_D:
635: *--Ad = Rs;
636: break;
637:
638: case store_Rs:
639: *Ad = Rs;
640: break;
641:
642: case inittab:
643: AT = (uchar*)pc[0];
644: osiz = (long)pc[1];
645: pc += 2;
646: break;
647:
648: case initsh:
649: sha = (long)pc[0];
650: shb = (long)pc[1];
651: pc += 2;
652: break;
653:
654: case table_RdRt:
655: /*
656: * Starting at offset arg1 in Rt, take arg2 bits,
657: * and use it to look up in table AT, putting answer in Rd
658: */
659: tmp = (long)pc[1];
660: Rd = (Rt >> (32-((long)pc[0]+tmp))) & ((1<<tmp)-1);
661: switch(osiz){
662: case 1:
663: Rd = AT[Rd];
664: break;
665: case 2:
666: Rd = ((ushort*)AT)[Rd];
667: break;
668: case 4:
669: Rd = ((ulong*)AT)[Rd];
670: break;
671: }
672: pc += 2;
673: break;
674:
675: case table_RsRt:
676: /* like table_RdRt, but answer goes in Rs */
677: tmp = (long)pc[1];
678: Rs = (Rt >> (32-((long)pc[0]+tmp))) & ((1<<tmp)-1);
679: switch(osiz){
680: case 1:
681: Rs = AT[Rs];
682: break;
683: case 2:
684: Rs = ((ushort*)AT)[Rs];
685: break;
686: case 4:
687: Rs = ((ulong*)AT)[Rs];
688: break;
689: }
690: pc += 2;
691: break;
692:
693:
694: case assemble:
695: /*
696: * Move low arg2 bits of Rd into offset arg1 in Rs.
697: * Can assume that high bits of Rd are zero,
698: * and target field of Rs is zero if offset != 0
699: */
700: tmp = (long)pc[0];
701: if(tmp == 0)
702: Rs = Rd << (32-pc[1]);
703: else
704: Rs |= Rd << (32-(tmp+pc[1]));
705: pc += 2;
706: break;
707:
708: case assemblex:
709: /*
710: * Like assemble, but fields will be moved into
711: * proper position by later Assemblex's
712: */
713: tmp = (long)pc[0];
714: if(tmp == 0)
715: Rs = Rd;
716: else
717: Rs = (Rs << pc[1]) | Rd;
718: pc += 2;
719: break;
720:
721: case Ozero:
722: Rs = 0;
723: break;
724:
725: case ODnorS:
726: Rs = ~(Rd|Rs);
727: break;
728:
729: case ODandnotS:
730: Rs = Rd & ~Rs;
731: break;
732:
733: case OnotS:
734: Rs = ~Rs;
735: break;
736:
737: case OnotDandS:
738: Rs = ~Rd & Rs;
739: break;
740:
741: case OnotD:
742: Rs = ~Rd;
743: break;
744:
745: case ODxorS:
746: Rs ^= Rd;
747: break;
748:
749: case ODnandS:
750: Rs = ~(Rd & Rs);
751: break;
752:
753: case ODandS:
754: Rs &= Rd;
755: break;
756:
757: case ODxnorS:
758: Rs = ~(Rd ^ Rs);
759: break;
760:
761: case OD:
762: Rs = Rd;
763: break;
764:
765: case ODornotS:
766: Rs = Rd | ~Rs;
767: break;
768:
769: case OnotDorS:
770: Rs |= ~Rd;
771: break;
772:
773: case ODorS:
774: Rs |= Rd;
775: break;
776:
777: case OF:
778: Rs = ~0L;
779: break;
780: }
781: goto loop;
782: }
783:
784: #ifdef TEST
785: void
786: prprog(void)
787: {
788: Type *pc;
789: int osiz;
790:
791: pc = (Type *)mem;
792:
793: loop:
794: switch(*pc++) {
795: default:
796: print("unknown opcode %d\n", pc[-1]);
797: exits("unknown opcode");
798: case field:
799: print("Rs = ((Rs ^ Rd) & 0x%lux) ^ Rd\n", *pc++);
800: break;
801:
802: case lsha_RsRt:
803: print("Rs = Rt << sha\n");
804: break;
805:
806: case lshb_RsRt:
807: print("Rs = Rt << shb\n");
808: break;
809:
810: case lsh_RsRd:
811: print("Rs = Rd << %d\n", *pc++);
812: break;
813:
814: case lsh_RtRt:
815: print("Rt <<= %d\n", *pc++);
816: break;
817:
818: case lsha_RtRt:
819: print("Rt <<= sha\n");
820: break;
821:
822: case lsha_RtRu:
823: print("Rt = Ru << sha\n");
824: break;
825:
826: case lshb_RtRu:
827: print("Rt = Ru << shb\n");
828: break;
829:
830: case rsha_RsRt:
831: print("Rs = Rt >> sha\n");
832: break;
833:
834: case rshb_RsRt:
835: print("Rs = Rt >> shb\n");
836: break;
837:
838: case rsha_RtRu:
839: print("Rt = Ru >> sha\n");
840: break;
841:
842: case rshb_RtRu:
843: print("Rt = Ru >> shb\n");
844: break;
845:
846: case orlsha_RsRt:
847: print("Rs |= Rt << sha\n");
848: break;
849:
850: case orlshb_RsRt:
851: print("Rs |= Rt << shb\n");
852: break;
853:
854: case orlsh_RsRd:
855: print("Rs |= Rd << %d\n", *pc++);
856: break;
857:
858: case orrsha_RsRt:
859: print("Rs |= Rt >> sha\n");
860: break;
861:
862: case orrshb_RsRt:
863: print("Rs |= Rt >> shb\n");
864: break;
865:
866: case orrsha_RtRu:
867: print("Rt |= Ru >> sha\n");
868: break;
869:
870: case orrshb_RtRu:
871: print("Rt |= Ru >> shb\n");
872: break;
873:
874: case or_RsRd:
875: print("Rs |= Rd\n");
876: break;
877:
878: case add_As:
879: print("As += %d\n", (long)*pc++);
880: break;
881:
882: case add_Ad:
883: print("Ad += %d\n", (long)*pc++);
884: break;
885:
886: case initsd:
887: print("As = 0x%lux\n", (ulong*)pc[0]);
888: print("Ad = 0x%lux\n", (ulong*)pc[1]);
889: pc += 2;
890: break;
891:
892: case ilabel:
893: print("Ri = %d\n", *pc++);
894: break;
895:
896: case olabel:
897: print("Ro = %d\n", *pc++);
898: break;
899:
900: case iloop:
901: print("if(--Ri > 0) goto 0x%lux\n", *pc++);
902: break;
903:
904: case oloop:
905: print("if(--Ro > 0) goto 0x%lux\n", *pc++);
906: break;
907:
908: case rts:
909: print("return\n");
910: return;
911:
912: case load_Rs_P:
913: print("Rs = *As++\n");
914: break;
915:
916: case load_Rt_P:
917: print("Rt = *As++\n");
918: break;
919:
920: case load_Ru_P:
921: print("Ru = *As++\n");
922: break;
923:
924: case load_Rd_D:
925: print("Rd = *--As\n");
926: break;
927:
928: case load_Rs_D:
929: print("Rs = *--As\n");
930: break;
931:
932: case load_Rt_D:
933: print("Rt = *--As\n");
934: break;
935:
936: case load_Rd:
937: print("Rd = *As\n");
938: break;
939:
940: case load_Rs:
941: print("Rs = *As\n");
942: break;
943:
944: case load_Rt:
945: print("Rt = *As\n");
946: break;
947:
948: case fetch_Rd_P:
949: print("Rd = *Ad++\n");
950: break;
951:
952: case fetch_Rd_D:
953: print("Rd = *--Ad\n");
954: break;
955:
956: case fetch_Rd:
957: print("Rd = *Ad\n");
958: break;
959:
960: case store_Rs_P:
961: print("*Ad++ = Rs\n");
962: break;
963:
964: case store_Rs_D:
965: print("*--Ad = Rs\n");
966: break;
967:
968: case store_Rs:
969: print("*Ad = Rs\n");
970: break;
971:
972: case inittab:
973: print("AT = 0x%lux (%d byte entries)\n", pc[0],pc[1]);
974: osiz = pc[1];
975: pc += 2;
976: break;
977:
978: case initsh:
979: print("sha = %d\n", (long)pc[0]);
980: print("shb = %d\n", (long)pc[1]);
981: pc += 2;
982: break;
983:
984: case table_RdRt:
985: switch(osiz){
986: case 1:
987: print("Rd = ((char*)AT)[Rt{%d..%d}]\n", pc[0], pc[0]+pc[1]-1);
988: break;
989: case 2:
990: print("Rd = ((short*)AT)[Rt{%d..%d}]\n", pc[0], pc[0]+pc[1]-1);
991: break;
992: case 4:
993: print("Rd = ((long*)AT)[Rt{%d..%d}]\n", pc[0], pc[0]+pc[1]-1);
994: break;
995: default:
996: print("bad osiz for table_RdRt\n");
997: }
998: pc += 2;
999: break;
1000:
1001: case table_RsRt:
1002: switch(osiz){
1003: case 1:
1004: print("Rs = ((char*)AT)[Rt{%d..%d}]\n", pc[0], pc[0]+pc[1]-1);
1005: break;
1006: case 2:
1007: print("Rs = ((short*)AT)[Rt{%d..%d}]\n", pc[0], pc[0]+pc[1]-1);
1008: break;
1009: case 4:
1010: print("Rs = ((long*)AT)[Rt{%d..%d}]\n", pc[0], pc[0]+pc[1]-1);
1011: break;
1012: default:
1013: print("bad osiz for table_RdRt\n");
1014: }
1015: pc += 2;
1016: break;
1017:
1018: case assemble:
1019: /*
1020: * Move low arg2 bits of Rd into offset arg1 in Rs.
1021: * Can assume that high bits of Rd are zero,
1022: * and target field of Rs is zero if offset != 0
1023: */
1024: if(pc[0] == 0)
1025: print("Rs = Rd << %d\n", (32-(long)pc[1]));
1026: else
1027: print("Rs |= Rd << %d\n", (32-((long)pc[0]+(long)pc[1])));
1028: pc += 2;
1029: break;
1030:
1031: case assemblex:
1032: /*
1033: * Like assemble, but fields will be moved into
1034: * proper position by later Assemblex's
1035: */
1036: if(pc[0] == 0)
1037: print("Rs = Rd\n");
1038: else
1039: print("Rs = (Rs << %d) | Rd\n", pc[1]);
1040: pc += 2;
1041: break;
1042:
1043: case Ozero:
1044: print("Rs = 0\n");
1045: break;
1046:
1047: case ODnorS:
1048: print("Rs = ~(Rd|Rs)\n");
1049: break;
1050:
1051: case ODandnotS:
1052: print("Rs = Rd & ~Rs\n");
1053: break;
1054:
1055: case OnotS:
1056: print("Rs = ~Rs\n");
1057: break;
1058:
1059: case OnotDandS:
1060: print("Rs = ~Rd & Rs\n");
1061: break;
1062:
1063: case OnotD:
1064: print("Rs = ~Rd\n");
1065: break;
1066:
1067: case ODxorS:
1068: print("Rs ^= Rd\n");
1069: break;
1070:
1071: case ODnandS:
1072: print("Rs = ~(Rd & Rs)\n");
1073: break;
1074:
1075: case ODandS:
1076: print("Rs &= Rd\n");
1077: break;
1078:
1079: case ODxnorS:
1080: print("Rs = ~(Rd ^ Rs)\n");
1081: break;
1082:
1083: case OD:
1084: print("Rs = Rd\n");
1085: break;
1086:
1087: case ODornotS:
1088: print("Rs = Rd | ~Rs\n");
1089: break;
1090:
1091: case OnotDorS:
1092: print("Rs |= ~Rd\n");
1093: break;
1094:
1095: case ODorS:
1096: print("Rs |= Rd\n");
1097: break;
1098:
1099: case OF:
1100: print("Rs = ~0L\n");
1101: break;
1102: }
1103: goto loop;
1104: }
1105: #endif
1106:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.