|
|
1.1 ! root 1: typedef ushort Type; ! 2: ! 3: /* ! 4: * See the comments at the beginning of bb.c and bbc.h ! 5: * for an outline of how this bitblt works ! 6: ! 7: * Registers ! 8: * in addition to the registers of the abstract machine, ! 9: * we use RY as a scratch register, and AT to hold the ! 10: * address of the table given in Inittab. ! 11: */ ! 12: /* A registers */ ! 13: #define As 0 ! 14: #define Ad 1 ! 15: #define AT 2 /* conversion table */ ! 16: #define Ao 3 /* Ro in abstract machine */ ! 17: #define Au 4 /* Ru in abstract machine */ ! 18: /* D registers */ ! 19: #define Rs 0 ! 20: #define Rd 1 ! 21: #define Rt 2 ! 22: #define Ri 3 ! 23: #define Ra 4 /* shift a */ ! 24: #define Rb 5 /* shift b */ ! 25: #define RX 6 /* scratch */ ! 26: #define RY 7 /* scratch */ ! 27: ! 28: /* ! 29: * Addressing modes ! 30: */ ! 31: /* use Rx by itself to get Dn mode */ ! 32: #define AR(n) ((1<<3)|n) /* An */ ! 33: #define AI(n) ((2<<3)|n) /* (An) */ ! 34: #define AIPOST(n) ((3<<3)|n) /* (An)+ */ ! 35: #define AIPRE(n) ((4<<3)|n) /* -(An) */ ! 36: #define AID(n) ((5<<3)|n) /* d16(An) */ ! 37: #define AIX(n) ((6<<3)|n) /* (An+Xm) with following word */ ! 38: #define AIXEXT(m) ((m<<12)|(1<<11)) /* scale factor 1 */ ! 39: #define AIX2EXT(m) ((m<<12)|(1<<11)|(1<<9)) /* scale factor 2 */ ! 40: #define AIX4EXT(m) ((m<<12)|(1<<11)|(2<<9)) /* scale factor 4 */ ! 41: #define IMML ((7<<3)|4) /* immediate long (following) */ ! 42: #define ABSW ((7<<3)|0) /* absolute short address */ ! 43: ! 44: /* generate `a', `size' bits wide, into bit position `shift' */ ! 45: /* the SMM version is used when there might be extra bits in `a' */ ! 46: #define SM(a,size,shift) ((a)<<(shift)) ! 47: #define SMM(a,size,shift) (((a)&(1<<(size))-1)<<(shift)) ! 48: /* ! 49: * Instructions ! 50: * They operate on long words, unless suffixed by 'w' or 'b' ! 51: * The 'I' instructions must be followed by immediate data (bigendian) ! 52: */ ! 53: ! 54: #define MOVE(dmode,smode) (SM(2,4,12)|SMM(dmode,3,9)|SMM((dmode>>3),3,6)|SM(smode,6,0)) ! 55: #define MOVEw(dmode,smode) (SM(3,4,12)|SMM(dmode,3,9)|SMM((dmode>>3),3,6)|SM(smode,6,0)) ! 56: #define MOVEb(dmode,smode) (SM(1,4,12)|SMM(dmode,3,9)|SMM((dmode>>3),3,6)|SM(smode,6,0)) ! 57: #define MOVEQ(dreg,v) (SM(0x7,4,12)|SM(dreg,3,9)|SM(v,8,0)) ! 58: /* MOVEQ sign-extends the 8-bit value; make sure it is masked to 8 bits */ ! 59: ! 60: #define AND(dreg,smode) (SM(0xC,4,12)|SM(dreg,3,9)|SM(2,3,6)|SM(smode,6,0)) ! 61: #define ANDI(dmode) (SM(0x02,8,8)|SM(2,2,6)|SM(dmode,6,0)) ! 62: #define ANDIw(dmode) (SM(0x02,8,8)|SM(1,2,6)|SM(dmode,6,0)) ! 63: ! 64: /* the 68020 gnot.h defines an OR */ ! 65: #undef OR ! 66: #define OR(dreg,smode) (SM(0x8,4,12)|SM(dreg,3,9)|SM(2,3,6)|SM(smode,6,0)) ! 67: #define XOR(dmode,sreg) (SM(0xB,4,12)|SM(sreg,3,9)|SM(6,3,6)|SM(dmode,6,0)) ! 68: #define NOT(dmode) (SM(0x46,8,8)|SM(2,2,6)|SM(dmode,6,0)) ! 69: #define CLR(dmode) (SM(0x42,8,8)|SM(2,2,6)|SM(dmode,6,0)) ! 70: ! 71: /* LS[LR] can shift 1-8 (n==8 gets smashed to 0, which is the right encoding) */ ! 72: /* else have to put shift amount in reg and use LS[LR]R */ ! 73: #define LSL(dreg,n) (SM(0xE,4,12)|SMM(n,3,9)|SM(1,1,8)|SM(0x11,5,3)|SM(dreg,3,0)) ! 74: #define LSLR(dreg,rn) (SM(0xE,4,12)|SM(rn,3,9)|SM(1,1,8)|SM(0x15,5,3)|SM(dreg,3,0)) ! 75: ! 76: #define LSR(dreg,n) (SM(0xE,4,12)|SMM(n,3,9)|SM(0,1,8)|SM(0x11,5,3)|SM(dreg,3,0)) ! 77: #define LSRR(dreg,rn) (SM(0xE,4,12)|SM(rn,3,9)|SM(0,1,8)|SM(0x15,5,3)|SM(dreg,3,0)) ! 78: ! 79: #define ADDA(dareg,smode) (SM(0xD,4,12)|SM(dareg,3,9)|SM(7,3,6)|SM(smode,6,0)) ! 80: #define ADDQ(dmode,v) (SM(0x5,4,12)|SMM(v,3,9)|SM(0,1,8)|SM(2,2,6)|SM(dmode,6,0)) ! 81: #define SUBQ(dmode,v) (SM(0x5,4,12)|SMM(v,3,9)|SM(1,1,8)|SM(2,2,6)|SM(dmode,6,0)) ! 82: #define LEA(dareg,smode) (SM(0x4,4,12)|SM(dareg,3,9)|SM(7,3,6)|SM(smode,6,0)) ! 83: ! 84: /* BFEXTU and BFINS each must be followed by BFIELD */ ! 85: #define BFEXTU(smode) (SM(0xE9,8,8)|SM(3,2,6)|SM(smode,6,0)) ! 86: #define BFINS(dmode) (SM(0xEF,8,8)|SM(3,2,6)|SM(dmode,6,0)) ! 87: ! 88: /* low part of r is dst for BFEXTU, src for BFINS */ ! 89: /* offset is from high order bit; w==0 means width of 32 */ ! 90: #define BFIELD(r,o,w) (SM(r,3,12)|SM(o,5,6)|SMM(w,5,0)) ! 91: ! 92: #define DBF(countreg) (SM(0x5,4,12)|SM(0x39,6,3)|SM(countreg,3,0)) ! 93: ! 94: #define BCC(cond,d8) (SM(0x6,4,12)|SM(cond,4,8)|SMM(d8,8,0)) ! 95: ! 96: #define RTS 0x4E75 ! 97: ! 98: /* ! 99: * Macros for assembling the operations of the abstract machine. ! 100: * Each assumes that ushort *p points to the next location where ! 101: * an instruction should be assembled. ! 102: * These macros can use RY as a scratch register, but no others. ! 103: */ ! 104: ! 105: #define Two(h,l) *(long *)p = (long)(((h)<<16)|(l)); p += 2 ! 106: #define Lsh(r,n) if(n != 0) { \ ! 107: if(n <= 8) \ ! 108: *p++ = LSL(r,n); \ ! 109: else { \ ! 110: *p++ = MOVEQ(RX,n); *p++ = LSLR(r,RX); \ ! 111: } \ ! 112: } ! 113: #define Rsh(r,n) if(n != 0) { \ ! 114: if(n <= 8) \ ! 115: *p++ = LSR(r,n); \ ! 116: else { \ ! 117: *p++ = MOVEQ(RX,n); *p++ = LSRR(r,RX); \ ! 118: } \ ! 119: } ! 120: #define Lsha(r) *p++ = LSLR(r,Ra) ! 121: #define Lshb(r) *p++ = LSLR(r,Rb) ! 122: #define Rsha(r) *p++ = LSRR(r,Ra) ! 123: #define Rshb(r) *p++ = LSRR(r,Rb) ! 124: #define Andcon(r,c) *p++ = ANDI(r); *(long *)p = (long)(c); p += 2 ! 125: #define Movecon(r,c) *p++ = MOVE(r,IMML); *(long *)p = (long)(c); p += 2 ! 126: #define Moveacon(dareg,c) *p++ = MOVE(AR(dareg),IMML); *(long *)p = (long)(c); p += 2 ! 127: /* Addacon assumes value added will fit in a short */ ! 128: #define Addacon(dareg,c) *p++ = LEA(dareg,AID(dareg)); *p++ = c ! 129: /* Bcc assumes distance to branch is less than short offset */ ! 130: #define Bcc(cond,lp) *p++ = BCC(cond,0); *p++ = ((char*)(lp))-(((char*)p)) ! 131: #define Ofield(c) *p++ = XOR(Rs,Rd); Andcon(Rs,c); *p++ = XOR(Rs,Rd) ! 132: #define Olsha_RsRt *p++ = MOVE(Rs,Rt); Lsha(Rs) ! 133: #define Olshb_RsRt *p++ = MOVE(Rs,Rt); Lshb(Rs) ! 134: #define Olsh_RsRd(c) *p++ = MOVE(Rs,Rd); Lsh(Rs,c) ! 135: #define Olsh_RtRt(c) Lsh(Rt,c) ! 136: #define Olsha_RtRt Lsha(Rt) ! 137: #define Olsha_RtRu Two(MOVE(Rt,AR(Au)),LSLR(Rt,Ra)) ! 138: #define Olshb_RtRu Two(MOVE(Rt,AR(Au)),LSLR(Rt,Rb)) ! 139: #define Orsha_RsRt Two(MOVE(Rs,Rt),LSRR(Rs,Ra)) ! 140: #define Orshb_RsRt Two(MOVE(Rs,Rt),LSRR(Rs,Rb)) ! 141: #define Orsha_RtRu Two(MOVE(Rt,AR(Au)),LSRR(Rt,Ra)) ! 142: #define Orshb_RtRu Two(MOVE(Rt,AR(Au)),LSRR(Rt,Rb)) ! 143: #define Oorlsha_RsRt Two(MOVE(RY,Rt),LSLR(RY,Ra)); *p++ = OR(Rs,RY) ! 144: #define Oorlshb_RsRt Two(MOVE(RY,Rt),LSLR(RY,Rb)); *p++ = OR(Rs,RY) ! 145: #define Oorlsh_RsRd(c) *p++ = MOVE(RY,Rd); Lsh(RY,c); *p++ = OR(Rs,RY) ! 146: #define Oorrsha_RsRt Two(MOVE(RY,Rt),LSRR(RY,Ra)); *p++ = OR(Rs,RY) ! 147: #define Oorrshb_RsRt Two(MOVE(RY,Rt),LSRR(RY,Rb)); *p++ = OR(Rs,RY) ! 148: #define Oorrsha_RtRu Two(MOVE(RY,AR(Au)),LSRR(RY,Ra)); *p++ = OR(Rt,RY) ! 149: #define Oorrshb_RtRu Two(MOVE(RY,AR(Au)),LSRR(RY,Rb)); *p++ = OR(Rt,RY) ! 150: #define Oor_RsRd *p++ = OR(Rs,Rd) ! 151: #define Add_As(c) Addacon(As,c) ! 152: #define Add_Ad(c) Addacon(Ad,c) ! 153: #define Initsd(s,d) *p++ = MOVE(AR(As),IMML); *(long *)p = (long) (s); p += 2; \ ! 154: *p++ = MOVE(AR(Ad),IMML); *(long *)p = (long) (d); p += 2 ! 155: #define Initsh(a,b) *p++ = MOVEQ(Ra,a); *p++ = MOVEQ(Rb,b) ! 156: ! 157: /* ! 158: * use DBF instruction. assume counts < 16k ! 159: */ ! 160: #define Ilabel(c) tmp = (c)-1; Movecon(Ri,tmp) ! 161: #define Olabel(c) Moveacon(Ao,(c)) ! 162: #define Iloop(lp) *p++ = DBF(Ri); *p++ = ((char*)(lp))-((char*)p) ! 163: #define Oloop(lp) *p++ = SUBQ(AR(Ao),1); *p++ = MOVE(Rs,AR(Ao)); \ ! 164: Bcc(0x6,lp) /* Bne */ ! 165: ! 166: #define Orts *p++ = RTS ! 167: #define Nop /* nothing */ ! 168: ! 169: /* ! 170: * Load and Fetch macros: arg is ignored for this architecture ! 171: */ ! 172: ! 173: #define Load_Rs_P *p++ = MOVE(Rs,AIPOST(As)) ! 174: #define Load_Rt_P *p++ = MOVE(Rt,AIPOST(As)) ! 175: #define Loadzx_Rt_P *p++ = MOVE(Rt,AIPOST(As)) ! 176: #define Loador_Rt_P *p++ = MOVE(Rt,AIPOST(As)) ! 177: #define Load_Ru_P *p++ = MOVE(AR(Au),AIPOST(As)) ! 178: #define Load_Rd_D(f) *p++ = MOVE(Rd,AIPRE(As)) ! 179: #define Load_Rs_D(f) *p++ = MOVE(Rs,AIPRE(As)) ! 180: #define Load_Rt_D(f) *p++ = MOVE(Rt,AIPRE(As)) ! 181: #define Loadzx_Rt_D(f) *p++ = MOVE(Rt,AIPRE(As)) ! 182: #define Load_Rd(f) *p++ = MOVE(Rd,AI(As)) ! 183: #define Load_Rs(f) *p++ = MOVE(Rs,AI(As)) ! 184: #define Load_Rt(f) *p++ = MOVE(Rt,AI(As)) ! 185: #define Loadzx_Rt(f) *p++ = MOVE(Rt,AI(As)) ! 186: #define Fetch_Rd_P(f) *p++ = MOVE(Rd,AIPOST(Ad)) ! 187: #define Fetch_Rd_D(f) *p++ = MOVE(Rd,AIPRE(Ad)) ! 188: #define Fetch_Rd(f) *p++ = MOVE(Rd,AI(Ad)) ! 189: #define Store_Rs_P *p++ = MOVE(AIPOST(Ad),Rs) ! 190: #define Store_Rs_D *p++ = MOVE(AIPRE(Ad),Rs) ! 191: #define Store_Rs *p++ = MOVE(AI(Ad),Rs) ! 192: ! 193: #define HAVEBF ! 194: #define Bfextu_RdAd(o,w) *p++ = BFEXTU(AI(Ad)); *p++ = BFIELD(Rd,o,w) ! 195: #define Bfextu_RsAs(o,w) *p++ = BFEXTU(AI(As)); *p++ = BFIELD(Rs,o,w) ! 196: #define Bfins_AdRs(o,w) *p++ = BFINS(AI(Ad)); *p++ = BFIELD(Rs,o,w) ! 197: ! 198: #define Inittab(t,s) *p++ = MOVE(AR(AT),IMML); *(long *)p = (long) t; p += 2 ! 199: ! 200: /* look up n bits at offset o in Rt; move table entry (1<<l bytes long) to Rd */ ! 201: #define Table_RdRt(o,n,l) Two(BFEXTU(Rt),BFIELD(Rd,o,n)); \ ! 202: if(osiz==1) { \ ! 203: Two(MOVEb(Rd,AIX(AT)),AIXEXT(Rd)); \ ! 204: } else if(osiz==2) { \ ! 205: Two(MOVEw(Rd,AIX(AT)),AIX2EXT(Rd)); \ ! 206: } else { \ ! 207: Two(MOVE(Rd,AIX(AT)),AIX4EXT(Rd)); \ ! 208: } ! 209: ! 210: #define Table_RsRt(o,n,l) Two(BFEXTU(Rt),BFIELD(Rs,o,n)); \ ! 211: if(osiz==1) { \ ! 212: Two(MOVEb(Rs,AIX(AT)),AIXEXT(Rs)); \ ! 213: } else if(osiz==2) { \ ! 214: Two(MOVEw(Rs,AIX(AT)),AIX2EXT(Rs)); \ ! 215: } else { \ ! 216: Two(MOVE(Rs,AIX(AT)),AIX4EXT(Rs)); \ ! 217: } ! 218: ! 219: /* emit code to assemble low n bits of Rd into offset o in Rs */ ! 220: #define Assemble(o,n) \ ! 221: if((o) == 0) { \ ! 222: Olsh_RsRd(32-(n)); \ ! 223: } else if((o) == 32-(n)) { \ ! 224: *p++ = OR(Rs,Rd); \ ! 225: } else { \ ! 226: Oorlsh_RsRd(32-((o)+(n))); \ ! 227: } ! 228: /* emit code to assemble low n bits of Rd into offset o in Rs. ! 229: this works by shifting Rd as we go, it only works if ! 230: the whole word will eventually be filled */ ! 231: #define Assemblex(o,n) \ ! 232: if((o) == 0) { \ ! 233: *p++ = MOVE(Rs,Rd); \ ! 234: } else { \ ! 235: Lsh(Rs,n); \ ! 236: *p++ = OR(Rs,Rd); \ ! 237: } ! 238: ! 239: #define Extrainit ! 240: ! 241: extern void flushvirtpage(void *); ! 242: extern void bbdflush(void *, int); ! 243: ! 244: #define Execandfree(memstart,onstack) \ ! 245: if(onstack) { \ ! 246: flushvirtpage(memstart); \ ! 247: (*(void (*)(void))memstart)(); \ ! 248: } else { \ ! 249: tmp = (p-memstart) * sizeof(Type); \ ! 250: bbdflush(memstart, tmp); \ ! 251: (*(void (*)(void))memstart)(); \ ! 252: bbfree(memstart, tmp); \ ! 253: } ! 254: ! 255: /* emit code seq at fi (at most 3 shorts) */ ! 256: #define Emitop \ ! 257: *(long *)p = *(long *)fi; \ ! 258: p[2] = fi[2]; \ ! 259: p = (Type*)(((char *)p)+fin) ! 260: ! 261: typedef struct Fstr ! 262: { ! 263: short fetchs; ! 264: short fetchd; ! 265: int n; ! 266: Type instr[4]; ! 267: } Fstr; ! 268: ! 269: Fstr fstr[16] = ! 270: { ! 271: [0] 0,0,2, /* Zero */ ! 272: { CLR(Rs), 0, 0, 0 }, ! 273: ! 274: [1] 1,1,4, /* DnorS */ ! 275: { OR(Rs,Rd), NOT(Rs), 0, 0}, ! 276: ! 277: [2] 1,1,4, /* DandnotS */ ! 278: { NOT(Rs), AND(Rs,Rd), 0, 0}, ! 279: ! 280: [3] 1,0,2, /* notS */ ! 281: { NOT(Rs), 0, 0, 0}, ! 282: ! 283: [4] 1,1,6, /* notDandS */ ! 284: { NOT(Rs), OR(Rs,Rd), NOT(Rs), 0}, ! 285: ! 286: [5] 0,1,4, /* notD */ ! 287: { MOVE(Rs,Rd), NOT(Rs), 0, 0}, ! 288: ! 289: [6] 1,1,2, /* DxorS */ ! 290: { XOR(Rs,Rd), 0, 0, 0}, ! 291: ! 292: [7] 1,1,4, /* DnandS */ ! 293: { AND(Rs,Rd), NOT(Rs), 0, 0}, ! 294: ! 295: [8] 1,1,2, /* DandS */ ! 296: { AND(Rs,Rd), 0, 0, 0}, ! 297: ! 298: [9] 1,1,4, /* DxnorS */ ! 299: { XOR(Rs,Rd), NOT(Rs), 0, 0}, ! 300: ! 301: [10] 0,1,2, /* D */ ! 302: { MOVE(Rs,Rd), 0, 0, 0}, ! 303: ! 304: [11] 1,1,4, /* DornotS */ ! 305: { NOT(Rs), OR(Rs,Rd), 0, 0}, ! 306: ! 307: [12] 1,0,0, /* S */ ! 308: { 0, 0, 0, 0}, ! 309: ! 310: [13] 1,1,6, /* notDorS */ ! 311: { NOT(Rs), AND(Rs,Rd), NOT(Rs), 0}, ! 312: ! 313: [14] 1,1,2, /* DorS */ ! 314: { OR(Rs,Rd), 0, 0, 0}, ! 315: ! 316: [15] 0,0,4, /* F */ ! 317: { CLR(Rs), NOT(Rs), 0, 0}, ! 318: }; ! 319: ! 320: #include "tabs.h" ! 321: static uchar *tabs[4][4] = ! 322: { ! 323: { 0, (uchar*)tab01, (uchar*)tab02, (uchar*)tab03}, ! 324: {(uchar*)tab10, 0, (uchar*)tab12, (uchar*)tab13}, ! 325: {(uchar*)tab20, (uchar*)tab21, 0, (uchar*)tab23}, ! 326: {(uchar*)tab30, (uchar*)tab31, (uchar*)tab32, 0}, ! 327: }; ! 328: ! 329: static uchar tabosiz[4][4] = /* size in bytes of entries */ ! 330: { ! 331: { 0, 2, 4, 4}, ! 332: { 1, 0, 2, 4}, ! 333: { 1, 1, 0, 2}, ! 334: { 1, 1, 1, 0}, ! 335: }; ! 336: ! 337: enum { ! 338: Progmax = 1600, /* max number of Type units in a bitblt prog */ ! 339: /* should be bigger if want 0->5 conversion */ ! 340: Progmaxnoconv = 80, /* max number of Type units when no conversion */ ! 341: }; ! 342: ! 343: #ifdef TEST ! 344: ! 345: void ! 346: prprog(void) ! 347: { ! 348: abort(); /* use db */ ! 349: } ! 350: ! 351: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.