|
|
1.1 ! root 1: typedef long 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 RF to hold ~0 always, RX as a scratch register, ! 10: * Rc as a scratch register for forming constants, and ! 11: * AT to hold the address of the table given in Inittab. ! 12: */ ! 13: #define R0 0 ! 14: #define As 19 ! 15: #define Ad 20 ! 16: #define Rs 21 ! 17: #define Rd 22 ! 18: #define Rt 23 ! 19: #define Ru 24 ! 20: #define Ri 25 ! 21: #define Ro 26 ! 22: #define Rc 27 /* const temporary */ ! 23: #define RF 16 /* ~0 */ ! 24: #define RX 17 /* scratch */ ! 25: #define AT 18 /* conversion table */ ! 26: ! 27: /* ! 28: * Instructions ! 29: */ ! 30: /* Inst2a */ ! 31: #define SETHI 0x04 ! 32: /* Inst2b */ ! 33: #define BG 0x0A ! 34: /* Inst3 2 */ ! 35: #define ADD 0x00 ! 36: #define SUB 0x04 ! 37: #define AND 0x01 ! 38: #define OR 0x02 ! 39: #define XOR 0x03 ! 40: #define ANDN 0x05 ! 41: #define ORN 0x06 ! 42: #define SUBcc 0x14 ! 43: #define SLL 0x25 ! 44: #define SRL 0x26 ! 45: #define JMPL 0x38 ! 46: /* Inst3 3 */ ! 47: #define LD 0x00 ! 48: #define LDUB 0x01 ! 49: #define LDUH 0x02 ! 50: #define ST 0x04 ! 51: ! 52: /* ! 53: * Generate `a', `size' bits wide, into bit position `shift'. ! 54: * (to save execution time, the onus is on the caller to make sure that ! 55: * `a' fits in `size') ! 56: */ ! 57: #define SM(a,size,shift) ((a)<<(shift)) ! 58: ! 59: #define Inst2a(rd,op2,i) (SM(rd,5,25)|SM(op2,4,22)|SM(i,22,0)) ! 60: #define Inst2b(a,cond,op2,d) Inst2a(SM(a,1,4)|SM(cond,4,0), op2, d) ! 61: ! 62: #define Inst3X(op,rd,op3,rs1) (SM(op,2,30)|SM(rd,5,25)|SM(op3,6,19)|SM(rs1,5,14)) ! 63: #define Inst3a(op,rd,op3,rs1,i,asi,rs2) (Inst3X(op,rd,op3,rs1)|SM(i,1,13)|SM(asi,8,5)|SM(rs2,5,0)) ! 64: #define Inst3b(op,rd,op3,rs1,i,si) (Inst3X(op,rd,op3,rs1)|SM(i,1,13)|SM(si,13,0)) ! 65: #define Inst3c(op,rd,op3,rs1,opf,rs2) (Inst3X(op,rd,op3,rs1)|SM(opf,9,5)|SM(rs2,5,0)) ! 66: ! 67: #define OpConst(Rdst,Rsrc,op,c) /* Rdst = Rsrc op c */ \ ! 68: if(((ulong)(c)) <= 0xFFF) \ ! 69: *p++ = Inst3b(2,Rdst,op,Rsrc,1,(c)); \ ! 70: else { \ ! 71: RConst(Rc,(c)); \ ! 72: *p++ = Inst3a(2,Rdst,op,Rsrc,0,0,Rc); \ ! 73: } ! 74: ! 75: #define RConst(Rdst,c) /* Rdst = c; c is large */ \ ! 76: *p++ = Inst2a(Rdst,SETHI,((ulong)(c))>>10); \ ! 77: *p++ = Inst3b(2,Rdst,OR,Rdst,1,(c)&0x3FF) ! 78: ! 79: ! 80: /* ! 81: * Macros for assembling the operations of the abstract machine. ! 82: * Each assumes that ulong *p points to the next location where ! 83: * an instruction should be assembled. ! 84: * These macros can use RX as a scratch register, but no others. ! 85: * They can assume RF holds ~0 and R0 holds 0. ! 86: */ ! 87: ! 88: #define Ofield(c) *p++ = Inst3a(2,Rs,XOR,Rs,0,0,Rd); \ ! 89: RConst(Rc,(c)); \ ! 90: *p++ = Inst3a(2,Rs,AND,Rs,0,0,Rc); \ ! 91: *p++ = Inst3a(2,Rs,XOR,Rs,0,0,Rd) ! 92: ! 93: #define Olsha_RsRt *p++ = Inst3a(2,Rs,SLL,Rt,1,0,sha) ! 94: #define Olshb_RsRt *p++ = Inst3a(2,Rs,SLL,Rt,1,0,shb) ! 95: #define Olsh_RsRd(c) *p++ = Inst3a(2,Rs,SLL,Rd,1,0,(c)) ! 96: #define Olsh_RtRt(c) *p++ = Inst3a(2,Rt,SLL,Rt,1,0,(c)) ! 97: #define Olsha_RtRt *p++ = Inst3a(2,Rt,SLL,Rt,1,0,sha) ! 98: #define Olsha_RtRu *p++ = Inst3a(2,Rt,SLL,Ru,1,0,sha) ! 99: #define Olshb_RtRu *p++ = Inst3a(2,Rt,SLL,Ru,1,0,shb) ! 100: #define Orsha_RsRt *p++ = Inst3a(2,Rs,SRL,Rt,1,0,sha) ! 101: #define Orshb_RsRt *p++ = Inst3a(2,Rs,SRL,Rt,1,0,shb) ! 102: #define Orsha_RtRu *p++ = Inst3a(2,Rt,SRL,Ru,1,0,sha) ! 103: #define Orshb_RtRu *p++ = Inst3a(2,Rt,SRL,Ru,1,0,shb) ! 104: #define Oorlsha_RsRt *p++ = Inst3a(2,RX,SLL,Rt,1,0,sha); \ ! 105: *p++ = Inst3a(2,Rs,OR,Rs,0,0,RX) ! 106: #define Oorlshb_RsRt *p++ = Inst3a(2,RX,SLL,Rt,1,0,shb); \ ! 107: *p++ = Inst3a(2,Rs,OR,Rs,0,0,RX) ! 108: #define Oorlsh_RsRd(c) *p++ = Inst3a(2,RX,SLL,Rd,1,0,(c)); \ ! 109: *p++ = Inst3a(2,Rs,OR,Rs,0,0,RX) ! 110: #define Oorrsha_RsRt *p++ = Inst3a(2,RX,SRL,Rt,1,0,sha); \ ! 111: *p++ = Inst3a(2,Rs,OR,Rs,0,0,RX) ! 112: #define Oorrshb_RsRt *p++ = Inst3a(2,RX,SRL,Rt,1,0,shb); \ ! 113: *p++ = Inst3a(2,Rs,OR,Rs,0,0,RX) ! 114: #define Oorrsha_RtRu *p++ = Inst3a(2,RX,SRL,Ru,1,0,sha); \ ! 115: *p++ = Inst3a(2,Rt,OR,Rt,0,0,RX) ! 116: #define Oorrshb_RtRu *p++ = Inst3a(2,RX,SRL,Ru,1,0,shb); \ ! 117: *p++ = Inst3a(2,Rt,OR,Rt,0,0,RX) ! 118: #define Oor_RsRd *p++ = Inst3a(2,Rs,OR,Rd,0,0,Rs) ! 119: ! 120: #define Add_As(c) OpConst(As,As,ADD,(c)) ! 121: ! 122: #define Add_Ad(c) OpConst(Ad,Ad,ADD,(c)) ! 123: ! 124: #define Initsd(s,d) RConst(As,((ulong)(s))); \ ! 125: RConst(Ad,((ulong)(d))) ! 126: ! 127: #define Initsh(a,b) ! 128: ! 129: /* Put all ones in RF */ ! 130: #define Extrainit *p++ = Inst3b(2,RF,ORN,R0,1,0) ! 131: ! 132: #define Ilabel(c) RConst(Ri,(c)) ! 133: ! 134: #define Olabel(c) RConst(Ro,(c)) ! 135: ! 136: #define Iloop(lp) *p++ = Inst3b(2,Ri,SUBcc,Ri,1,1); \ ! 137: *p = Inst2b(0,BG,0x2,((lp)-p)&0x3FFFFF); p++; \ ! 138: Nop ! 139: ! 140: #define Oloop(lp) *p++ = Inst3b(2,Ro,SUBcc,Ro,1,1); \ ! 141: *p = Inst2b(0,BG,0x2,((lp)-p)&0x3FFFFF); p++; \ ! 142: Nop ! 143: ! 144: #define Orts *p++ = Inst3b(2,R0,JMPL,15,1,8); \ ! 145: Nop ! 146: ! 147: /* ! 148: * In the predecrement versions, it's as easy to do the decrement afterwards ! 149: * in the (virtual) delay slot, which will go faster on some versions ! 150: */ ! 151: ! 152: #define Load_Rs_P *p++ = Inst3b(3,Rs,LD,As,1,0); *p++ = Inst3b(2,As,ADD,As,1,4) ! 153: #define Load_Rt_P *p++ = Inst3b(3,Rt,LD,As,1,0); *p++ = Inst3b(2,As,ADD,As,1,4) ! 154: #define Loadzx_Rt_P *p++ = Inst3b(3,Rt,LD,As,1,0); *p++ = Inst3b(2,As,ADD,As,1,4) ! 155: #define Loador_Rt_P *p++ = Inst3b(3,Rt,LD,As,1,0); *p++ = Inst3b(2,As,ADD,As,1,4) ! 156: #define Load_Ru_P *p++ = Inst3b(3,Ru,LD,As,1,0); *p++ = Inst3b(2,As,ADD,As,1,4) ! 157: #define Load_Rd_D(f) *p++ = Inst3b(3,Rd,LD,As,1,(-4)&0x1FFF); *p++ = Inst3b(2,As,SUB,As,1,4) ! 158: #define Load_Rs_D(f) *p++ = Inst3b(3,Rs,LD,As,1,(-4)&0x1FFF); *p++ = Inst3b(2,As,SUB,As,1,4) ! 159: #define Load_Rt_D(f) *p++ = Inst3b(3,Rt,LD,As,1,(-4)&0x1FFF); *p++ = Inst3b(2,As,SUB,As,1,4) ! 160: #define Loadzx_Rt_D(f) *p++ = Inst3b(3,Rt,LD,As,1,(-4)&0x1FFF); *p++ = Inst3b(2,As,SUB,As,1,4) ! 161: #define Load_Rd(f) *p++ = Inst3b(3,Rd,LD,As,1,0) ! 162: #define Load_Rs(f) *p++ = Inst3b(3,Rs,LD,As,1,0) ! 163: #define Load_Rt(f) *p++ = Inst3b(3,Rt,LD,As,1,0) ! 164: #define Loadzx_Rt(f) *p++ = Inst3b(3,Rt,LD,As,1,0) ! 165: #define Fetch_Rd_P(f) *p++ = Inst3b(3,Rd,LD,Ad,1,0); *p++ = Inst3b(2,Ad,ADD,Ad,1,4) ! 166: #define Fetch_Rd_D(f) *p++ = Inst3b(3,Rd,LD,Ad,1,(-4)&0x1FFF); *p++ = Inst3b(2,Ad,SUB,Ad,1,4) ! 167: #define Fetch_Rd(f) *p++ = Inst3b(3,Rd,LD,Ad,1,0); ! 168: #define Store_Rs_P *p++ = Inst3b(3,Rs,ST,Ad,1,0); *p++ = Inst3b(2,Ad,ADD,Ad,1,4) ! 169: #define Store_Rs_D *p++ = Inst3b(3,Rs,ST,Ad,1,(-4)&0x1FFF); *p++ = Inst3b(2,Ad,SUB,Ad,1,4) ! 170: #define Store_Rs *p++ = Inst3b(3,Rs,ST,Ad,1,0) ! 171: #define Nop *p++ = Inst3a(2,R0,OR,R0,0,0,R0) ! 172: ! 173: #define Inittab(t,s) RConst(AT,((ulong)(t))) ! 174: ! 175: /* emit code to look up n bits at offset o; table entries are 1<<l bytes long */ ! 176: #define Table_RdRt(o,n,l) \ ! 177: tmp = 32-((o)+(n))-(l); \ ! 178: if(tmp >= 0) \ ! 179: *p++ = Inst3a(2,Rd,SRL,Rt,1,0,tmp); \ ! 180: else if((l) > 0) \ ! 181: *p++ = Inst3a(2,Rd,SLL,Rt,1,0,l); \ ! 182: else \ ! 183: *p++ = Inst3a(2,Rd,ADD,Rt,0,0,R0); \ ! 184: *p++ = Inst3b(2,Rd,AND,Rd,1,((1<<(n))-1)<<(l)); \ ! 185: if(osiz==1) *p++ = Inst3b(3,Rd,LDUB,Rd,0,AT); \ ! 186: else if(osiz==2) *p++ = Inst3b(3,Rd,LDUH,Rd,0,AT); \ ! 187: else *p++ = Inst3b(3,Rd,LD,Rd,0,AT); \ ! 188: ! 189: #define Table_RsRt(o,n,l) \ ! 190: tmp = 32-((o)+(n))-(l); \ ! 191: *p++ = Inst3a(2,Rs,SRL,Rt,1,0,tmp); \ ! 192: if(tmp >= 0) \ ! 193: *p++ = Inst3a(2,Rs,SRL,Rt,1,0,tmp); \ ! 194: else if((l) > 0) \ ! 195: *p++ = Inst3a(2,Rs,SLL,Rt,1,0,l); \ ! 196: else \ ! 197: *p++ = Inst3a(2,Rs,ADD,Rt,0,0,R0); \ ! 198: if(osiz==1) *p++ = Inst3b(3,Rs,LDUB,Rs,0,AT); \ ! 199: else if(osiz==2) *p++ = Inst3b(3,Rs,LDUH,Rs,0,AT); \ ! 200: else *p++ = Inst3b(3,Rs,LD,Rs,0,AT); \ ! 201: ! 202: /* emit code to assemble low n bits of Rd into offset o in Rs */ ! 203: #define Assemble(o,n) \ ! 204: if((o) == 0) { \ ! 205: Olsh_RsRd(32-(n)); \ ! 206: } else if((o) == 32-(n)) { \ ! 207: *p++ = Inst3a(2,Rs,OR,Rs,0,0,Rd); \ ! 208: } else { \ ! 209: Oorlsh_RsRd(32-((o)+(n))); \ ! 210: } ! 211: ! 212: /* emit code to assemble low n bits of Rd into offset o in Rs. ! 213: this works by shifting Rd as we go, it only works if ! 214: the whole word will eventually be filled */ ! 215: #define Assemblex(o,n) \ ! 216: if((o) == 0) { \ ! 217: *p++ = Inst3a(2,Rs,OR,Rd,0,0,R0); \ ! 218: } else { \ ! 219: *p++ = Inst3a(2,Rs,SLL,Rs,1,0,n); \ ! 220: *p++ = Inst3a(2,Rs,OR,Rd,0,0,Rs); \ ! 221: } ! 222: ! 223: #define Execandfree(memstart,onstack) \ ! 224: (*(void (*)(void))memstart)(); \ ! 225: if(!onstack) \ ! 226: bbfree(memstart, (p-memstart) * sizeof(Type)); ! 227: ! 228: #define Emitop \ ! 229: p[0] = fi[0]; \ ! 230: p[1] = fi[1]; \ ! 231: p = (Type*)(((char *)p)+fin) ! 232: ! 233: typedef struct Fstr ! 234: { ! 235: char fetchs; ! 236: char fetchd; ! 237: short n; ! 238: Type instr[2]; ! 239: } Fstr; ! 240: ! 241: Fstr fstr[16] = ! 242: { ! 243: [0] 0,0,4, /* Zero */ ! 244: { Inst3a(2,Rs,ADD,R0,0,0,R0), 0 }, ! 245: ! 246: [1] 1,1,8, /* DnorS */ ! 247: { Inst3a(2,Rs,OR,Rs,0,0,Rd), Inst3a(2,Rs,XOR,Rs,0,0,RF) }, ! 248: ! 249: [2] 1,1,4, /* DandnotS */ ! 250: { Inst3a(2,Rs,ANDN,Rd,0,0,Rs), 0 }, ! 251: ! 252: [3] 1,0,4, /* notS */ ! 253: { Inst3a(2,Rs,XOR,Rs,0,0,RF), 0 }, ! 254: ! 255: [4] 1,1,4, /* notDandS */ ! 256: { Inst3a(2,Rs,ANDN,Rs,0,0,Rd), 0 }, ! 257: ! 258: [5] 0,1,4, /* notD */ ! 259: { Inst3a(2,Rs,XOR,Rd,0,0,RF), 0 }, ! 260: ! 261: [6] 1,1,4, /* DxorS */ ! 262: { Inst3a(2,Rs,XOR,Rd,0,0,Rs), 0 }, ! 263: ! 264: [7] 1,1,8, /* DnandS */ ! 265: { Inst3a(2,Rs,AND,Rd,0,0,Rs), Inst3a(2,Rs,XOR,Rs,0,0,RF) }, ! 266: ! 267: [8] 1,1,4, /* DandS */ ! 268: { Inst3a(2,Rs,AND,Rd,0,0,Rs), 0 }, ! 269: ! 270: [9] 1,1,8, /* DxnorS */ ! 271: { Inst3a(2,Rs,XOR,Rd,0,0,Rs), Inst3a(2,Rs,XOR,Rs,0,0,RF) }, ! 272: ! 273: [10] 0,1,4, /* D */ ! 274: { Inst3a(2,Rs,ADD,Rd,0,0,R0), 0 }, ! 275: ! 276: [11] 1,1,4, /* DornotS */ ! 277: { Inst3a(2,Rs,ORN,Rd,0,0,Rs), 0 }, ! 278: ! 279: [12] 1,0,0, /* S */ ! 280: {0, 0}, ! 281: ! 282: [13] 1,1,4, /* notDorS */ ! 283: { Inst3a(2,Rs,ORN,Rs,0,0,Rd), 0 }, ! 284: ! 285: [14] 1,1,4, /* DorS */ ! 286: { Inst3a(2,Rs,OR,Rd,0,0,Rs), 0 }, ! 287: ! 288: [15] 0,0,4, /* F */ ! 289: { Inst3a(2,Rs,OR,R0,0,0,RF), 0 }, ! 290: }; ! 291: ! 292: #include "tabs.h" ! 293: static uchar *tabs[4][4] = ! 294: { ! 295: { 0, (uchar*)tab01, (uchar*)tab02, (uchar*)tab03}, ! 296: {(uchar*)tab10, 0, (uchar*)tab12, (uchar*)tab13}, ! 297: {(uchar*)tab20, (uchar*)tab21, 0, (uchar*)tab23}, ! 298: {(uchar*)tab30, (uchar*)tab31, (uchar*)tab32, 0}, ! 299: }; ! 300: ! 301: static uchar tabosiz[4][4] = /* size in bytes of entries */ ! 302: { ! 303: { 0, 2, 4, 4}, ! 304: { 1, 0, 2, 4}, ! 305: { 1, 1, 0, 2}, ! 306: { 1, 1, 1, 0}, ! 307: }; ! 308: ! 309: enum { ! 310: Progmax = 1000, /* max number of bytes in a bitblt prog */ ! 311: Progmaxnoconv = 70, /* max number of Type units when no conversion */ ! 312: }; ! 313: ! 314: ! 315: #ifdef TEST ! 316: void ! 317: prprog(void) ! 318: { ! 319: abort(); /* use db */ ! 320: } ! 321: ! 322: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.