|
|
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: static uchar *tabs[4][4] =
353: {
354: { 0, (uchar*)tab01, (uchar*)tab02, (uchar*)tab03},
355: {(uchar*)tab10, 0, (uchar*)tab12, (uchar*)tab13},
356: {(uchar*)tab20, (uchar*)tab21, 0, (uchar*)tab23},
357: {(uchar*)tab30, (uchar*)tab31, (uchar*)tab32, 0},
358: };
359:
360: static uchar tabosiz[4][4] = /* size in bytes of entries */
361: {
362: { 0, 2, 4, 4},
363: { 1, 0, 2, 4},
364: { 1, 1, 0, 2},
365: { 1, 1, 1, 0},
366: };
367:
368: enum {
369: Progmax = 800, /* max number of words in a bitblt prog */
370: Progmaxnoconv = 50, /* max number of words when no conversion */
371: };
372:
373: static void
374: interpret(Type *pc)
375: {
376: ulong *As, *Ad;
377: ulong Rs, Rd, Rt, Ru;
378: long Ri, Ro;
379: uchar *AT;
380: int osiz, sha, shb, tmp;
381:
382: #ifdef TEST
383: ulong *Aslow, *Ashigh, *Adlow, *Adhigh;
384: void prprog(void);
385:
386: Rs = lrand();
387: Rd = lrand();
388: Rt = lrand();
389: Ru = lrand();
390: Ri = lrand();
391: Ro = lrand();
392: sha = lrand();
393: shb = lrand();
394: As = 0;
395: Ad = 0;
396: AT = 0;
397: Aslow = gaddr(cursm, curr.min);
398: Ashigh = gaddr(cursm, sub(curr.max, Pt(1,1)));
399: Adlow = gaddr(curdm, curpt);
400: Adhigh = gaddr(curdm, sub(add(curpt, sub(curr.max,curr.min)),Pt(1,1)));
401: #endif
402:
403: loop:
404: #ifdef TEST
405: switch(*pc) {
406: case load_Rs_P:
407: case load_Rt_P:
408: case load_Ru_P:
409: case load_Rd:
410: case load_Rs:
411: case load_Rt:
412: if(As < Aslow || As > Ashigh){
413: print("load from bad As %ux\n", As);
414: errplace:
415: print("src bitmap base %ux zero %d width %d r %d %d %d %d\n",
416: cursm->base, cursm->zero, cursm->width,
417: cursm->r.min.x, cursm->r.min.y,
418: cursm->r.max.x, cursm->r.max.y);
419: print("dst bitmap base %ux zero %d width %d r %d %d %d %d\n",
420: curdm->base, curdm->zero, curdm->width,
421: curdm->r.min.x, curdm->r.min.y,
422: curdm->r.max.x, curdm->r.max.y);
423: print("p %d %d r %d %d %d %d f %d\n",
424: curpt.x, curpt.y, curr.min.x, curr.min.y,
425: curr.max.x, curr.max.y, curf);
426: prprog();
427: exits("fail");
428: }
429: break;
430: case load_Rd_D:
431: case load_Rs_D:
432: case load_Rt_D:
433: if(As-1 < Aslow || As-1 > Ashigh){
434: print("load from bad As-1 %ux\n", As-1);
435: goto errplace;
436: }
437: break;
438: case fetch_Rd_P:
439: case fetch_Rd:
440: if(Ad < Adlow || Ad > Adhigh){
441: print("fetch from bad Ad %ux\n", Ad);
442: goto errplace;
443: }
444: break;
445: case store_Rs_P:
446: case store_Rs:
447: if(Ad < Adlow || Ad > Adhigh){
448: print("store to bad Ad %ux\n", Ad);
449: goto errplace;
450: }
451: break;
452: case fetch_Rd_D:
453: case store_Rs_D:
454: if(Ad-1 < Adlow || Ad-1 > Adhigh){
455: print("fetch from bad Ad-1 %ux\n", Ad-1);
456: prprog();
457: }
458: break;
459: }
460: #endif
461: switch(*pc++) {
462: default:
463: #ifdef TEST
464: print("unknown opcode %d\n", pc[-1]);
465: goto errplace;
466: #else
467: return;
468: #endif
469: case field:
470: /* Rs gets Rd where mask bits are 0s, Rs where mask bits are 1s */
471: Rs = ((Rs ^ Rd) & *pc++) ^ Rd;
472: break;
473:
474: case lsha_RsRt:
475: Rs = Rt << sha;
476: break;
477:
478: case lshb_RsRt:
479: Rs = Rt << shb;
480: break;
481:
482: case lsh_RsRd:
483: Rs = Rd << *pc++;
484: break;
485:
486: case lsh_RtRt: /* arg = shift amount */
487: Rt <<= *pc++;
488: break;
489:
490: case lsha_RtRt:
491: Rt <<= sha;
492: break;
493:
494: case lsha_RtRu:
495: Rt = Ru << sha;
496: break;
497:
498: case lshb_RtRu:
499: Rt = Ru << shb;
500: break;
501:
502: case rsha_RsRt:
503: Rs = Rt >> sha;
504: break;
505:
506: case rshb_RsRt:
507: Rs = Rt >> shb;
508: break;
509:
510: case rsha_RtRu:
511: Rt = Ru >> sha;
512: break;
513:
514: case rshb_RtRu:
515: Rt = Ru >> shb;
516: break;
517:
518: case orlsha_RsRt:
519: Rs |= Rt << sha;
520: break;
521:
522: case orlshb_RsRt:
523: Rs |= Rt << shb;
524: break;
525:
526: case orlsh_RsRd: /* arg = shift amount */
527: Rs |= Rd << *pc++;
528: break;
529:
530: case orrsha_RsRt:
531: Rs |= Rt >> sha;
532: break;
533:
534: case orrshb_RsRt:
535: Rs |= Rt >> shb;
536: break;
537:
538: case orrsha_RtRu:
539: Rt |= Ru >> sha;
540: break;
541:
542: case orrshb_RtRu:
543: Rt |= Ru >> shb;
544: break;
545:
546: case or_RsRd:
547: Rs |= Rd;
548: break;
549:
550: case add_As:
551: As = (ulong*)((char*)As + (long)*pc++);
552: break;
553:
554: case add_Ad:
555: Ad = (ulong*)((char*)Ad + (long)*pc++);
556: break;
557:
558: case initsd:
559: As = (ulong*)pc[0];
560: Ad = (ulong*)pc[1];
561: pc += 2;
562: break;
563:
564: case ilabel:
565: /* initialize inner loop count */
566: Ri = *pc++;
567: break;
568:
569: case olabel:
570: /* initialize outer loop count */
571: Ro = *pc++;
572: break;
573:
574: case iloop:
575: /* decrement inner loop count, loop back if still positive */
576: Ri--;
577: if(Ri > 0) {
578: pc = (Type*)pc[0];
579: break;
580: }
581: pc++;
582: break;
583:
584: case oloop:
585: /* decrement outer loop count, loop back if still positive */
586: Ro--;
587: if(Ro > 0) {
588: pc = (Type*)pc[0];
589: break;
590: }
591: pc++;
592: break;
593:
594: case rts:
595: return;
596:
597: case load_Rs_P:
598: Rs = *As++;
599: break;
600:
601: case load_Rt_P:
602: Rt = *As++;
603: break;
604:
605: case load_Ru_P:
606: Ru = *As++;
607: break;
608:
609: case load_Rd_D:
610: Rd = *--As;
611: break;
612:
613: case load_Rs_D:
614: Rs = *--As;
615: break;
616:
617: case load_Rt_D:
618: Rt = *--As;
619: break;
620:
621: case load_Rd:
622: Rd = *As;
623: break;
624:
625: case load_Rs:
626: Rs = *As;
627: break;
628:
629: case load_Rt:
630: Rt = *As;
631: break;
632:
633: case fetch_Rd_P:
634: Rd = *Ad++;
635: break;
636:
637: case fetch_Rd_D:
638: Rd = *--Ad;
639: break;
640:
641: case fetch_Rd:
642: Rd = *Ad;
643: break;
644:
645: case store_Rs_P:
646: *Ad++ = Rs;
647: break;
648:
649: case store_Rs_D:
650: *--Ad = Rs;
651: break;
652:
653: case store_Rs:
654: *Ad = Rs;
655: break;
656:
657: case inittab:
658: AT = (uchar*)pc[0];
659: osiz = (long)pc[1];
660: pc += 2;
661: break;
662:
663: case initsh:
664: sha = (long)pc[0];
665: shb = (long)pc[1];
666: pc += 2;
667: break;
668:
669: case table_RdRt:
670: /*
671: * Starting at offset arg1 in Rt, take arg2 bits,
672: * and use it to look up in table AT, putting answer in Rd
673: */
674: tmp = (long)pc[1];
675: Rd = (Rt >> (32-((long)pc[0]+tmp))) & ((1<<tmp)-1);
676: switch(osiz){
677: case 1:
678: Rd = AT[Rd];
679: break;
680: case 2:
681: Rd = ((ushort*)AT)[Rd];
682: break;
683: case 4:
684: Rd = ((ulong*)AT)[Rd];
685: break;
686: }
687: pc += 2;
688: break;
689:
690: case table_RsRt:
691: /* like table_RdRt, but answer goes in Rs */
692: tmp = (long)pc[1];
693: Rs = (Rt >> (32-((long)pc[0]+tmp))) & ((1<<tmp)-1);
694: switch(osiz){
695: case 1:
696: Rs = AT[Rs];
697: break;
698: case 2:
699: Rs = ((ushort*)AT)[Rs];
700: break;
701: case 4:
702: Rs = ((ulong*)AT)[Rs];
703: break;
704: }
705: pc += 2;
706: break;
707:
708:
709: case assemble:
710: /*
711: * Move low arg2 bits of Rd into offset arg1 in Rs.
712: * Can assume that high bits of Rd are zero,
713: * and target field of Rs is zero if offset != 0
714: */
715: tmp = (long)pc[0];
716: if(tmp == 0)
717: Rs = Rd << (32-pc[1]);
718: else
719: Rs |= Rd << (32-(tmp+pc[1]));
720: pc += 2;
721: break;
722:
723: case assemblex:
724: /*
725: * Like assemble, but fields will be moved into
726: * proper position by later Assemblex's
727: */
728: tmp = (long)pc[0];
729: if(tmp == 0)
730: Rs = Rd;
731: else
732: Rs = (Rs << pc[1]) | Rd;
733: pc += 2;
734: break;
735:
736: case Ozero:
737: Rs = 0;
738: break;
739:
740: case ODnorS:
741: Rs = ~(Rd|Rs);
742: break;
743:
744: case ODandnotS:
745: Rs = Rd & ~Rs;
746: break;
747:
748: case OnotS:
749: Rs = ~Rs;
750: break;
751:
752: case OnotDandS:
753: Rs = ~Rd & Rs;
754: break;
755:
756: case OnotD:
757: Rs = ~Rd;
758: break;
759:
760: case ODxorS:
761: Rs ^= Rd;
762: break;
763:
764: case ODnandS:
765: Rs = ~(Rd & Rs);
766: break;
767:
768: case ODandS:
769: Rs &= Rd;
770: break;
771:
772: case ODxnorS:
773: Rs = ~(Rd ^ Rs);
774: break;
775:
776: case OD:
777: Rs = Rd;
778: break;
779:
780: case ODornotS:
781: Rs = Rd | ~Rs;
782: break;
783:
784: case OnotDorS:
785: Rs |= ~Rd;
786: break;
787:
788: case ODorS:
789: Rs |= Rd;
790: break;
791:
792: case OF:
793: Rs = ~0L;
794: break;
795: }
796: goto loop;
797: }
798:
799: #ifdef TEST
800: void
801: prprog(void)
802: {
803: int osiz;
804: Type *pc;
805: pc = (Type *)mem;
806:
807: loop:
808: switch(*pc++) {
809: default:
810: print("unknown opcode %d\n", pc[-1]);
811: exits("unknown opcode");
812: case field:
813: print("Rs = ((Rs ^ Rd) & 0x%lux) ^ Rd\n", *pc++);
814: break;
815:
816: case lsha_RsRt:
817: print("Rs = Rt << sha\n");
818: break;
819:
820: case lshb_RsRt:
821: print("Rs = Rt << shb\n");
822: break;
823:
824: case lsh_RsRd:
825: print("Rs = Rd << %d\n", *pc++);
826: break;
827:
828: case lsh_RtRt:
829: print("Rt <<= %d\n", *pc++);
830: break;
831:
832: case lsha_RtRt:
833: print("Rt <<= sha\n");
834: break;
835:
836: case lsha_RtRu:
837: print("Rt = Ru << sha\n");
838: break;
839:
840: case lshb_RtRu:
841: print("Rt = Ru << shb\n");
842: break;
843:
844: case rsha_RsRt:
845: print("Rs = Rt >> sha\n");
846: break;
847:
848: case rshb_RsRt:
849: print("Rs = Rt >> shb\n");
850: break;
851:
852: case rsha_RtRu:
853: print("Rt = Ru >> sha\n");
854: break;
855:
856: case rshb_RtRu:
857: print("Rt = Ru >> shb\n");
858: break;
859:
860: case orlsha_RsRt:
861: print("Rs |= Rt << sha\n");
862: break;
863:
864: case orlshb_RsRt:
865: print("Rs |= Rt << shb\n");
866: break;
867:
868: case orlsh_RsRd:
869: print("Rs |= Rd << %d\n", *pc++);
870: break;
871:
872: case orrsha_RsRt:
873: print("Rs |= Rt >> sha\n");
874: break;
875:
876: case orrshb_RsRt:
877: print("Rs |= Rt >> shb\n");
878: break;
879:
880: case orrsha_RtRu:
881: print("Rt |= Ru >> sha\n");
882: break;
883:
884: case orrshb_RtRu:
885: print("Rt |= Ru >> shb\n");
886: break;
887:
888: case or_RsRd:
889: print("Rs |= Rd\n");
890: break;
891:
892: case add_As:
893: print("As += %d\n", (long)*pc++);
894: break;
895:
896: case add_Ad:
897: print("Ad += %d\n", (long)*pc++);
898: break;
899:
900: case initsd:
901: print("As = 0x%lux\n", (ulong*)pc[0]);
902: print("Ad = 0x%lux\n", (ulong*)pc[1]);
903: pc += 2;
904: break;
905:
906: case ilabel:
907: print("Ri = %d\n", *pc++);
908: break;
909:
910: case olabel:
911: print("Ro = %d\n", *pc++);
912: break;
913:
914: case iloop:
915: print("if(--Ri > 0) goto 0x%lux\n", *pc++);
916: break;
917:
918: case oloop:
919: print("if(--Ro > 0) goto 0x%lux\n", *pc++);
920: break;
921:
922: case rts:
923: print("return\n");
924: return;
925:
926: case load_Rs_P:
927: print("Rs = *As++\n");
928: break;
929:
930: case load_Rt_P:
931: print("Rt = *As++\n");
932: break;
933:
934: case load_Ru_P:
935: print("Ru = *As++\n");
936: break;
937:
938: case load_Rd_D:
939: print("Rd = *--As\n");
940: break;
941:
942: case load_Rs_D:
943: print("Rs = *--As\n");
944: break;
945:
946: case load_Rt_D:
947: print("Rt = *--As\n");
948: break;
949:
950: case load_Rd:
951: print("Rd = *As\n");
952: break;
953:
954: case load_Rs:
955: print("Rs = *As\n");
956: break;
957:
958: case load_Rt:
959: print("Rt = *As\n");
960: break;
961:
962: case fetch_Rd_P:
963: print("Rd = *Ad++\n");
964: break;
965:
966: case fetch_Rd_D:
967: print("Rd = *--Ad\n");
968: break;
969:
970: case fetch_Rd:
971: print("Rd = *Ad\n");
972: break;
973:
974: case store_Rs_P:
975: print("*Ad++ = Rs\n");
976: break;
977:
978: case store_Rs_D:
979: print("*--Ad = Rs\n");
980: break;
981:
982: case store_Rs:
983: print("*Ad = Rs\n");
984: break;
985:
986: case inittab:
987: print("AT = 0x%lux (%d byte entries)\n", pc[0],pc[1]);
988: osiz = pc[1];
989: pc += 2;
990: break;
991:
992: case initsh:
993: print("sha = %d\n", (long)pc[0]);
994: print("shb = %d\n", (long)pc[1]);
995: pc += 2;
996: break;
997:
998: case table_RdRt:
999: switch(osiz){
1000: case 1:
1001: print("Rd = ((char*)AT)[Rt{%d..%d}]\n", pc[0], pc[0]+pc[1]-1);
1002: break;
1003: case 2:
1004: print("Rd = ((short*)AT)[Rt{%d..%d}]\n", pc[0], pc[0]+pc[1]-1);
1005: break;
1006: case 4:
1007: print("Rd = ((long*)AT)[Rt{%d..%d}]\n", pc[0], pc[0]+pc[1]-1);
1008: break;
1009: default:
1010: print("bad osiz for table_RdRt\n");
1011: }
1012: pc += 2;
1013: break;
1014:
1015: case table_RsRt:
1016: switch(osiz){
1017: case 1:
1018: print("Rs = ((char*)AT)[Rt{%d..%d}]\n", pc[0], pc[0]+pc[1]-1);
1019: break;
1020: case 2:
1021: print("Rs = ((short*)AT)[Rt{%d..%d}]\n", pc[0], pc[0]+pc[1]-1);
1022: break;
1023: case 4:
1024: print("Rs = ((long*)AT)[Rt{%d..%d}]\n", pc[0], pc[0]+pc[1]-1);
1025: break;
1026: default:
1027: print("bad osiz for table_RdRt\n");
1028: }
1029: pc += 2;
1030: break;
1031:
1032: case assemble:
1033: /*
1034: * Move low arg2 bits of Rd into offset arg1 in Rs.
1035: * Can assume that high bits of Rd are zero,
1036: * and target field of Rs is zero if offset != 0
1037: */
1038: if(pc[0] == 0)
1039: print("Rs = Rd << %d\n", (32-(long)pc[1]));
1040: else
1041: print("Rs |= Rd << %d\n", (32-((long)pc[0]+(long)pc[1])));
1042: pc += 2;
1043: break;
1044:
1045: case assemblex:
1046: /*
1047: * Like assemble, but fields will be moved into
1048: * proper position by later Assemblex's
1049: */
1050: if(pc[0] == 0)
1051: print("Rs = Rd\n");
1052: else
1053: print("Rs = (Rs << %d) | Rd\n", pc[1]);
1054: pc += 2;
1055: break;
1056:
1057: case Ozero:
1058: print("Rs = 0\n");
1059: break;
1060:
1061: case ODnorS:
1062: print("Rs = ~(Rd|Rs)\n");
1063: break;
1064:
1065: case ODandnotS:
1066: print("Rs = Rd & ~Rs\n");
1067: break;
1068:
1069: case OnotS:
1070: print("Rs = ~Rs\n");
1071: break;
1072:
1073: case OnotDandS:
1074: print("Rs = ~Rd & Rs\n");
1075: break;
1076:
1077: case OnotD:
1078: print("Rs = ~Rd\n");
1079: break;
1080:
1081: case ODxorS:
1082: print("Rs ^= Rd\n");
1083: break;
1084:
1085: case ODnandS:
1086: print("Rs = ~(Rd & Rs)\n");
1087: break;
1088:
1089: case ODandS:
1090: print("Rs &= Rd\n");
1091: break;
1092:
1093: case ODxnorS:
1094: print("Rs = ~(Rd ^ Rs)\n");
1095: break;
1096:
1097: case OD:
1098: print("Rs = Rd\n");
1099: break;
1100:
1101: case ODornotS:
1102: print("Rs = Rd | ~Rs\n");
1103: break;
1104:
1105: case OnotDorS:
1106: print("Rs |= ~Rd\n");
1107: break;
1108:
1109: case ODorS:
1110: print("Rs |= Rd\n");
1111: break;
1112:
1113: case OF:
1114: print("Rs = ~0L\n");
1115: break;
1116: }
1117: goto loop;
1118: }
1119: #endif
1120:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.