|
|
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.