|
|
1.1 ! root 1: /* BITBLT() Moves bits around on the screen, and does a LOT of it ! 2: * ! 3: * WARNING ! 4: * WARNING: to any future modifier of this code. This is highly ! 5: * hand optimized code, it pushes the frame pointer and ! 6: * references locals off the stack pointer, ! 7: * and it even simulates register ! 8: * allocation. Be very careful if you edit this. ! 9: */ ! 10: ! 11: #include <jerq.h> ! 12: /* alignment codes for narrow rectangles */ ! 13: #define S_STRADDLE 0x4 /* source straddles a word boundary */ ! 14: #define D_STRADDLE 0x8 /* dest straddles a word boundary */ ! 15: #define LEFTDIR 8 ! 16: #define NOSHIFT 4 ! 17: #define DAMMIT 4 /* you'll see why */ ! 18: #undef sw ! 19: #define DX1 m ! 20: ! 21: bitblt(sm,r,dm,p,fc) ! 22: Bitmap *sm,*dm; ! 23: Rectangle r; ! 24: Point p; ! 25: int fc; ! 26: { ! 27: register Word *source,*dest; /* %r8-%r7 */ ! 28: register Word sw, dw; /* %r6-%r5 */ ! 29: register UWord m; /* %r4 */ ! 30: register int i; /* %r3 */ ! 31: ! 32: int a,b,j,h,w,dx1,px31,rx31; ! 33: unsigned int mask1,mask2,mask3,mask4,ntmask1,ntmask2; ! 34: int dummy1, dummy2; /* for future use, CANNOT CHANGE */ ! 35: /* NUMBER OF LOCALS DUE TO %fp */ ! 36: /* TRICKS */ ! 37: /* clip to the source Bitmap */ ! 38: if(r.origin.x < sm->rect.origin.x) ! 39: r.origin.x=sm->rect.origin.x; ! 40: if(r.corner.x > sm->rect.corner.x) ! 41: r.corner.x=sm->rect.corner.x; ! 42: if(r.origin.y < sm->rect.origin.y) ! 43: r.origin.y=sm->rect.origin.y; ! 44: if(r.corner.y > sm->rect.corner.y) ! 45: r.corner.y=sm->rect.corner.y; ! 46: /* ! 47: * If the sm->rect and r are disjoint, r is now degenerate, ! 48: * due to the clipping, and the next clipping code will reject it. ! 49: * This is safe because we will only increase origin or decrease corner. ! 50: */ ! 51: /* clip to the destination Bitmap */ ! 52: if(p.x < dm->rect.origin.x){ ! 53: r.origin.x+=dm->rect.origin.x-p.x; ! 54: p.x=dm->rect.origin.x; ! 55: } ! 56: if(p.y < dm->rect.origin.y){ ! 57: r.origin.y+=dm->rect.origin.y-p.y; ! 58: p.y=dm->rect.origin.y; ! 59: } ! 60: if(r.corner.x-r.origin.x > dm->rect.corner.x-p.x) ! 61: r.corner.x=r.origin.x+(dm->rect.corner.x-p.x); ! 62: if(r.corner.y-r.origin.y > dm->rect.corner.y-p.y) ! 63: r.corner.y=r.origin.y+(dm->rect.corner.y-p.y); ! 64: i = r.corner.y - r.origin.y; /* going to be h */ ! 65: dw = r.corner.x - r.origin.x - 1; /* going to be dx1 */ ! 66: if (i <= 0 || dw < 0) ! 67: return; ! 68: if (dw < 32) ! 69: goto narrow; ! 70: DX1 = dw; ! 71: h = i; ! 72: ntmask1 = topbits[p.x & 0x1f]; ! 73: mask1 = ~ntmask1; ! 74: mask2 = topbits[((p.x+DX1) & 31) + 1]; ! 75: ntmask2 = ~mask2; ! 76: w = ((p.x+DX1) >> 5) - (p.x >> 5); /* inner loop+1: sub 1 later*/ ! 77: sw = ((sm->width - w) << 2); /* sleazy hack to avoid shift */ ! 78: dw = ((dm->width - w) << 2); /* in outer, inner loops */ ! 79: if (sm == dm) { /* may have to mess with loop order */ ! 80: if (r.origin.y < p.y) { /* swap top with bottom */ ! 81: r.origin.y += i-1; ! 82: p.y += i-1; ! 83: if (r.origin.x < p.x) { /* swap left with right */ ! 84: fc |= LEFTDIR; ! 85: r.origin.x = r.origin.x + DX1; ! 86: p.x = p.x + DX1; ! 87: sw = -sw; ! 88: dw = -dw; ! 89: } ! 90: else ! 91: { ! 92: sw -= (sm->width << 3); /* -(w+n) == (w-n) - 2*w */ ! 93: dw -= (dm->width << 3) ; ! 94: } ! 95: } ! 96: else ! 97: { ! 98: if (r.origin.x < p.x) { /* swap left with right */ ! 99: fc |= LEFTDIR; ! 100: r.origin.x = r.origin.x + DX1; ! 101: p.x = p.x + DX1; ! 102: sw = (sm->width + w) << 2; ! 103: dw = (dm->width + w) << 2; ! 104: } ! 105: } ! 106: } ! 107: w--; /* subtract the 1 like we promised */ ! 108: px31 = p.x & 0x1f; /* commonly used expression */ ! 109: rx31 = r.origin.x & 0x1f; /* commonly used expression */ ! 110: dest = addr(dm,p); ! 111: source = addr(sm,r.origin); ! 112: a = px31 - rx31; ! 113: if(a == 0) ! 114: fc |= NOSHIFT; ! 115: else if (a < 0) ! 116: a += 32; ! 117: /* a == 0 means no shift, remember that */ ! 118: b = 32 - a; ! 119: switch (fc) { ! 120: ! 121: case F_OR | NOSHIFT | LEFTDIR: ! 122: b = w>>2; ! 123: w = w&3; ! 124: m = h; /* m is free => use it */ ! 125: do { ! 126: *dest-- |= mask2 & *source--; ! 127: if ((i = b) > 0) do { ! 128: *dest |= *source; ! 129: *(dest-1) |= *(source-1); ! 130: *(dest-2) |= *(source-2); ! 131: *(dest-3) |= *(source-3); ! 132: dest -= 4; ! 133: source -= 4; ! 134: } while (--i > 0); ! 135: if ((i = w) > 0) do { ! 136: *dest-- |= *source--; ! 137: } while (--i > 0); ! 138: *dest |= mask1 & *source; ! 139: asm(" ADDW2 %r6,%r8"); /*source += sw; */ ! 140: asm(" ADDW2 %r5,%r7"); /*dest += dw; */ ! 141: } while (--m != 0); ! 142: break; ! 143: case F_OR | LEFTDIR: ! 144: if ((px31) < (rx31)) ! 145: source++; /* adjust for pipeline */ ! 146: do { ! 147: m = *source--; /* m is a free register */ ! 148: *dest-- |= (((m >> a) | (*source << b)) & mask2); ! 149: if ((i=w) > 0) do { ! 150: m = (*source--) >> a; ! 151: *dest-- |= m | (*source << b); ! 152: } while (--i > 0); ! 153: m = *source; /* m is a free register */ ! 154: *dest |= (((m >> a) | (*(source-1) << b)) & mask1); ! 155: asm(" addw2 %r6,%r8"); /*source += sw; */ ! 156: asm(" addw2 %r5,%r7"); /*dest += dw; */ ! 157: } while (--h > 0); ! 158: break; ! 159: case F_OR | NOSHIFT: ! 160: b = w>>2; ! 161: w = w&3; ! 162: m = h; /* m is free => use it */ ! 163: do { ! 164: *dest++ |= (mask1 & *source++); ! 165: if ((i = b) > 0) do { ! 166: *dest |= *source; ! 167: *(dest+1) |= *(source+1); ! 168: *(dest+2) |= *(source+2); ! 169: *(dest+3) |= *(source+3); ! 170: dest += 4; ! 171: source += 4; ! 172: } while (--i > 0); ! 173: if ((i = w) > 0) do { ! 174: *dest++ |= *source++; ! 175: } while (--i > 0); ! 176: *dest |= (mask2 & *source); ! 177: asm(" addw2 %r6,%r8"); /*source += sw; */ ! 178: asm(" addw2 %r5,%r7"); /*dest += dw; */ ! 179: } while (--m != 0); ! 180: break; ! 181: case F_OR: ! 182: if ((px31) > (rx31)) ! 183: source--; /* adjust for pipeline */ ! 184: do { ! 185: m = *source++; /* m is a free register */ ! 186: *dest++ |= (((m << b) | (*source >> a)) & mask1); ! 187: if ((i=w) > 0) do { ! 188: m = (*source++) << b; ! 189: *dest++ |= m | (*source >> a); ! 190: } while (--i > 0); ! 191: m = *source; /* m is a free register */ ! 192: *dest |= (((m << b) | (*(source+1) >> a)) & mask2); ! 193: asm(" addw2 %r6,%r8"); /*source += sw; */ ! 194: asm(" addw2 %r5,%r7"); /*dest += dw; */ ! 195: } while (--h > 0); ! 196: break; ! 197: case F_CLR | NOSHIFT | LEFTDIR: ! 198: b = w>>2; ! 199: w = w&3; ! 200: m = h; /* m is free => use it */ ! 201: do { ! 202: *dest-- &= ~(mask2 & *source--); ! 203: if ((i = b) > 0) do { ! 204: *dest &= ~(*source); ! 205: *(dest-1) &= ~(*(source-1)); ! 206: *(dest-2) &= ~(*(source-2)); ! 207: *(dest-3) &= ~(*(source-3)); ! 208: dest -= 4; ! 209: source -= 4; ! 210: } while (--i > 0); ! 211: if ((i = w) > 0) do { ! 212: *dest-- &= ~(*source--); ! 213: } while (--i > 0); ! 214: *dest &= ~(mask1 & *source); ! 215: asm(" addw2 %r6,%r8"); /*source += sw; */ ! 216: asm(" addw2 %r5,%r7"); /*dest += dw; */ ! 217: } while (--m != 0); ! 218: break; ! 219: case F_CLR | LEFTDIR: ! 220: if ((px31) < (rx31)) ! 221: source++; /* adjust for pipeline */ ! 222: do { ! 223: m = *source--; /* m is a free register */ ! 224: *dest-- &= ~((((m >> a) | (*source << b)) & mask2)); ! 225: if ((i=w) > 0) do { ! 226: m = (*source--) >> a; ! 227: *dest-- &= ~(m | (*source << b)); ! 228: } while (--i > 0); ! 229: m = *source; /* m is a free register */ ! 230: *dest &= ~((((m >> a) | (*(source-1) << b)) & mask1)); ! 231: asm(" addw2 %r6,%r8"); /*source += sw; */ ! 232: asm(" addw2 %r5,%r7"); /*dest += dw; */ ! 233: } while (--h > 0); ! 234: break; ! 235: case F_CLR | NOSHIFT: ! 236: b = w>>2; ! 237: w = w&3; ! 238: m = h; /* m is free => use it */ ! 239: do { ! 240: *dest++ &= ~((mask1 & *source++)); ! 241: if ((i = b) > 0) do { ! 242: *dest &= ~(*source); ! 243: *(dest+1) &= ~(*(source+1)); ! 244: *(dest+2) &= ~(*(source+2)); ! 245: *(dest+3) &= ~(*(source+3)); ! 246: dest += 4; ! 247: source += 4; ! 248: } while (--i > 0); ! 249: if ((i = w) > 0) do { ! 250: *dest++ &= ~(*source++); ! 251: } while (--i > 0); ! 252: *dest &= ~((mask2 & *source)); ! 253: asm(" addw2 %r6,%r8"); /*source += sw; */ ! 254: asm(" addw2 %r5,%r7"); /*dest += dw; */ ! 255: } while (--m != 0); ! 256: break; ! 257: case F_CLR: ! 258: if ((px31) > (rx31)) ! 259: source--; /* adjust for pipeline */ ! 260: do { ! 261: m = *source++; /* m is a free register */ ! 262: *dest++ &= ~((((m << b) | (*source >> a)) & mask1)); ! 263: if ((i=w) > 0) do { ! 264: m = (*source++) << b; ! 265: *dest++ &= ~(m | (*source >> a)); ! 266: } while (--i > 0); ! 267: m = *source; /* m is a free register */ ! 268: *dest &= ~((((m << b) | (*(source+1) >> a)) & mask2)); ! 269: asm(" addw2 %r6,%r8"); /*source += sw; */ ! 270: asm(" addw2 %r5,%r7"); /*dest += dw; */ ! 271: } while (--h > 0); ! 272: break; ! 273: case F_XOR | NOSHIFT | LEFTDIR: ! 274: b = w>>2; ! 275: w = w&3; ! 276: m = h; /* m is free => use it */ ! 277: do { ! 278: *dest-- ^= mask2 & *source--; ! 279: if ((i = b) > 0) do { ! 280: *dest ^= *source; ! 281: *(dest-1) ^= *(source-1); ! 282: *(dest-2) ^= *(source-2); ! 283: *(dest-3) ^= *(source-3); ! 284: dest -= 4; ! 285: source -= 4; ! 286: } while (--i > 0); ! 287: if ((i = w) > 0) do { ! 288: *dest-- ^= *source--; ! 289: } while (--i > 0); ! 290: *dest ^= mask1 & *source; ! 291: asm(" addw2 %r6,%r8"); /*source += sw; */ ! 292: asm(" addw2 %r5,%r7"); /*dest += dw; */ ! 293: } while (--m != 0); ! 294: break; ! 295: case F_XOR | LEFTDIR: ! 296: if ((px31) < (rx31)) ! 297: source++; /* adjust for pipeline */ ! 298: do { ! 299: m = *source--; /* m is a free register */ ! 300: *dest-- ^= (((m >> a) | (*source << b)) & mask2); ! 301: if ((i=w) > 0) do { ! 302: m = (*source--) >> a; ! 303: *dest-- ^= m | (*source << b); ! 304: } while (--i > 0); ! 305: m = *source; /* m is a free register */ ! 306: *dest ^= (((m >> a) | (*(source-1) << b)) & mask1); ! 307: asm(" addw2 %r6,%r8"); /*source += sw; */ ! 308: asm(" addw2 %r5,%r7"); /*dest += dw; */ ! 309: } while (--h > 0); ! 310: break; ! 311: case F_XOR | NOSHIFT: ! 312: b = w>>2; ! 313: w = w&3; ! 314: m = h; /* m is free => use it */ ! 315: do { ! 316: *dest++ ^= (mask1 & *source++); ! 317: if ((i = b) > 0) do { ! 318: *dest ^= *source; ! 319: *(dest+1) ^= *(source+1); ! 320: *(dest+2) ^= *(source+2); ! 321: *(dest+3) ^= *(source+3); ! 322: dest += 4; ! 323: source += 4; ! 324: } while (--i > 0); ! 325: if ((i = w) > 0) do { ! 326: *dest++ ^= *source++; ! 327: } while (--i > 0); ! 328: *dest ^= (mask2 & *source); ! 329: asm(" addw2 %r6,%r8"); /*source += sw; */ ! 330: asm(" addw2 %r5,%r7"); /*dest += dw; */ ! 331: } while (--m != 0); ! 332: break; ! 333: case F_XOR: ! 334: if ((px31) > (rx31)) ! 335: source--; /* adjust for pipeline */ ! 336: asm(" PUSHW %ap"); ! 337: m = topbits[a]; ! 338: asm(" MCOMW %r4, %r1"); ! 339: asm(" MOVW %r4, %r2"); ! 340: asm(" MOVW 0(%fp),%ap"); ! 341: asm(" PUSHW %fp"); ! 342: asm("BW_XORLOOP:"); ! 343: asm(" ROTW %ap, 0(%r8), %r4"); ! 344: asm(" ANDW2 %r2,%r4"); ! 345: asm(" ADDW2 &4,%r8"); ! 346: asm(" ROTW %ap,0(%r8),%r0"); ! 347: asm(" ANDW3 %r0,%r1,%fp"); ! 348: asm(" ORW2 %r4,%fp"); ! 349: asm(" ANDW2 -0x28(%sp),%fp"); ! 350: asm(" XORW2 %fp,0(%r7)"); ! 351: asm(" ADDW2 &4,%r7"); ! 352: /* if (i = w) */ ! 353: asm(" MOVW -0x38(%sp),%r3"); ! 354: asm(" BEB BW_XORINNER"); ! 355: do{ ! 356: asm(" ANDW3 %r2,%r0,%r4"); ! 357: asm(" ADDW2 &4,%r8"); ! 358: asm(" ROTW %ap, 0(%r8),%r0"); ! 359: asm(" ANDW3 %r0,%r1,%fp"); ! 360: asm(" ORW2 %r4,%fp"); ! 361: asm(" XORW2 %fp,0(%r7)"); ! 362: asm(" ADDW2 &4, %r7"); ! 363: } while (--i > 0); ! 364: asm("BW_XORINNER:"); ! 365: asm(" ROTW %ap, 0(%r8),%r4"); ! 366: asm(" ANDW2 %r2,%r4"); ! 367: asm(" LRSW3 %ap, 4(%r8),%r0"); ! 368: asm(" ORW2 %r4,%r0"); ! 369: asm(" ANDW2 -0x24(%sp),%r0"); ! 370: asm(" XORW2 %r0,0(%r7)"); ! 371: asm(" ADDW2 %r6,%r8"); /*source += sw; */ ! 372: asm(" ADDW2 %r5,%r7"); /*dest += dw; */ ! 373: /* } while (--h > 0); */ ! 374: asm(" DECW -0x3c(%sp)"); ! 375: asm(" BGB BW_XORLOOP"); ! 376: ! 377: asm(" POPW %fp"); ! 378: asm(" POPW %ap"); ! 379: ! 380: /* above is similar to: ! 381: /* do { ! 382: /* m = *source++ << b; /* m is a free register */ ! 383: /* *dest++ ^= ((m & LMASK) | ((*source >> a)& RMASK) & mask1); ! 384: /* if ((i=w) > 0) do { ! 385: /* m = ((*source++) << b) & LMASK; ! 386: /* *dest++ ^= m | ((*source >> a)&RMASK); ! 387: /* } while (--i > 0); ! 388: /* m = *source; /* m is a free register */ ! 389: /* *dest ^= (((m << b) | (*(source+1) >> a)) & mask2); ! 390: /* asm(" addw2 %r6,%r8"); /*source += sw; */ ! 391: /* asm(" addw2 %r5,%r7"); /*dest += dw; */ ! 392: /* } while (--h > 0); */ ! 393: break; ! 394: case F_STORE | NOSHIFT | LEFTDIR: ! 395: b = w>>2; ! 396: w = w&3; ! 397: m = h; /* m is free => use it */ ! 398: do { ! 399: *dest = (ntmask2 & *dest) | (mask2 & *source--); ! 400: --dest; ! 401: if ((i = b) > 0) do { ! 402: *dest = *source; ! 403: *(dest-1) = *(source-1); ! 404: *(dest-2) = *(source-2); ! 405: *(dest-3) = *(source-3); ! 406: dest -= 4; ! 407: source -= 4; ! 408: } while (--i > 0); ! 409: if ((i = w) > 0) do { ! 410: *dest-- = *source--; ! 411: } while (--i > 0); ! 412: *dest = (ntmask1 & *dest) | (mask1 & *source); ! 413: asm(" addw2 %r6,%r8"); /*source += sw; */ ! 414: asm(" addw2 %r5,%r7"); /*dest += dw; */ ! 415: } while (--m != 0); ! 416: break; ! 417: case F_STORE | LEFTDIR: ! 418: if ((px31) < (rx31)) ! 419: source++; /* adjust for pipeline */ ! 420: do { ! 421: m = *source--; /* m is a free register */ ! 422: *dest = (((m >> a) | (*source << b)) & mask2) | ! 423: (*dest & ntmask2); ! 424: --dest; ! 425: if ((i=w) > 0) do { ! 426: m = (*source--) >> a; ! 427: *dest-- = m | (*source << b); ! 428: } while (--i > 0); ! 429: m = *source; /* m is a free register */ ! 430: *dest = (((m >> a) | (*(source-1) << b)) & mask1) | ! 431: (*dest & ntmask1); ! 432: asm(" addw2 %r6,%r8"); /*source += sw; */ ! 433: asm(" addw2 %r5,%r7"); /*dest += dw; */ ! 434: } while (--h > 0); ! 435: break; ! 436: case F_STORE | NOSHIFT: ! 437: if (w > 25) ! 438: goto widestore; ! 439: i = 25 - w; ! 440: m = (i << 2) + (i << 1); ! 441: ! 442: asm(" LLSW3 &0x2,0x10(%fp),%r0"); /* bytewidth in r0*/ ! 443: asm(" ADDW2 &4,%r0"); /* r0 +=4 for loop offsets */ ! 444: asm(" MOVAW B_FS_N,%r1"); ! 445: asm(" ADDW2 %r4,%r1"); /* r1 += &label, or jump addr*/ ! 446: m = h; /* m is free reg, use it as height */ ! 447: asm(" MOVW 0x20(%fp),%r2"); /* r2 = mask1 */ ! 448: asm(" PUSHW %ap"); /* save fp and ap */ ! 449: asm(" MOVW 0x24(%fp),%ap"); /* ap = mask2 */ ! 450: asm(" PUSHW %fp"); ! 451: asm(" MOVW %r1,%fp"); /* put jump index into fp */ ! 452: ! 453: do{ ! 454: ! 455: asm(" XORW3 0(%r7),0(%r8),%r1"); ! 456: asm(" ANDW2 %r2,%r1"); ! 457: asm(" XORW2 %r1,0(%r7)"); ! 458: ! 459: asm(" JMP 0(%fp)"); ! 460: asm("B_FS_N: "); /* label */ ! 461: asm(" MOVW 0x64(%r8),0x64(%r7)"); ! 462: asm(" MOVW 0x60(%r8),0x60(%r7)"); asm(" MOVW 0x5c(%r8),0x5c(%r7)"); ! 463: asm(" MOVW 0x58(%r8),0x58(%r7)"); asm(" MOVW 0x54(%r8),0x54(%r7)"); ! 464: asm(" MOVW 0x50(%r8),0x50(%r7)"); asm(" MOVW 0x4c(%r8),0x4c(%r7)"); asm(" MOVW 0x48(%r8),0x48(%r7)"); asm(" MOVW 0x44(%r8),0x44(%r7)"); ! 465: asm(" MOVW 0x40(%r8),0x40(%r7)"); asm(" MOVW 0x3c(%r8),0x3c(%r7)"); asm(" MOVW 0x38(%r8),0x38(%r7)"); asm(" MOVW 0x34(%r8),0x34(%r7)"); ! 466: asm(" MOVW 0x30(%r8),0x30(%r7)"); asm(" MOVW 0x2c(%r8),0x2c(%r7)"); asm(" MOVW 0x28(%r8),0x28(%r7)"); asm(" MOVW 0x24(%r8),0x24(%r7)"); ! 467: asm(" MOVW 0x20(%r8),0x20(%r7)"); asm(" MOVW 0x1c(%r8),0x1c(%r7)"); asm(" MOVW 0x18(%r8),0x18(%r7)"); ! 468: asm(" MOVW 0x14(%r8),0x14(%r7)"); ! 469: asm(" MOVW 0x10(%r8),0x10(%r7)"); ! 470: asm(" MOVW 0xc(%r8),0xc(%r7)"); ! 471: asm(" MOVW 0x8(%r8),0x8(%r7)"); ! 472: asm(" MOVW 0x4(%r8),0x4(%r7)"); ! 473: asm(" ADDW2 %r0,%r8"); ! 474: asm(" ADDW2 %r0,%r7"); ! 475: asm(" XORW3 0(%r7),0(%r8),%r1"); ! 476: asm(" ANDW2 %ap,%r1"); /* ap has mask2 */ ! 477: asm(" XORW2 %r1,0(%r7)"); ! 478: asm(" ADDW2 %r6,%r8"); ! 479: asm(" ADDW2 %r5,%r7"); ! 480: } while (--m != 0); ! 481: asm(" POPW %fp"); ! 482: asm(" POPW %ap"); ! 483: break; ! 484: /* ABOVE ALMOST EQUAL TO : */ ! 485: widestore: ! 486: b = w >> 2; ! 487: w = w & 3; ! 488: m = h; ! 489: do { ! 490: *dest = (ntmask1 & *dest) | (mask1 & *source++); ! 491: dest++; ! 492: if ((i = b) > 0) do { ! 493: *dest = *source; ! 494: *(dest+1) = *(source+1); ! 495: *(dest+2) = *(source+2); ! 496: *(dest+3) = *(source+3); ! 497: dest += 4; ! 498: source += 4; ! 499: } while (--i > 0); ! 500: if ((i = w) > 0) do { ! 501: *dest++ = *source++; ! 502: } while (--i > 0); ! 503: *dest = (ntmask2 & *dest) | (mask2 & *source); ! 504: asm(" addw2 %r6,%r8"); ! 505: asm(" addw2 %r5,%r7"); ! 506: } while (--m != 0); ! 507: break; ! 508: case F_STORE: ! 509: if ((px31) > (rx31)) ! 510: source--; /* adjust for pipeline */ ! 511: do { ! 512: m = *source++; /* m is a free register */ ! 513: *dest = (((m << b) | (*source >> a)) & mask1) | ! 514: (*dest & ntmask1); ! 515: dest++; ! 516: if ((i=w) > 0) do { ! 517: m = (*source++) << b; ! 518: *dest++ = m | (*source >> a); ! 519: } while (--i > 0); ! 520: m = *source; /* m is a free register */ ! 521: *dest = (((m << b) | (*(source+1) >> a)) & mask2) | ! 522: (*dest & ntmask2); ! 523: asm(" addw2 %r6,%r8"); /*source += sw; */ ! 524: asm(" addw2 %r5,%r7"); /*dest += dw; */ ! 525: } while (--h > 0); ! 526: break; ! 527: } ! 528: ! 529: return; ! 530: narrow: ! 531: /* ! 532: * width is 32 bits or less. There are four basic cases ! 533: * (in addition to the function code), which depend on whether ! 534: * the source and dest straddle word boundaries or not ! 535: */ ! 536: ! 537: m = p.x & 31; /* commonly used expression */ ! 538: sw = r.origin.x & 31; /* commonly used expression */ ! 539: if (sw + dw > 31) /* if source is NOT aligned */ ! 540: { ! 541: fc |= S_STRADDLE; ! 542: mask1 = ONES >> sw; ! 543: mask2 = topbits[((sw + dw) & 31) + 1]; ! 544: } ! 545: ! 546: if (m + dw > 31) /* if dest is NOT aligned */ ! 547: { ! 548: fc |= D_STRADDLE; ! 549: mask3 = ONES >> m; ! 550: mask4 = topbits[((m + dw) & 31) + 1]; ! 551: } ! 552: px31 = m; ! 553: m = m - sw; ! 554: a = dw; ! 555: ! 556: if ((sm == dm) && (r.origin.y < p.y)) ! 557: { /* may have to mess with loop order */ ! 558: r.origin.y += i-1; ! 559: p.y += i-1; ! 560: sw = -(sm->width << 2); /* sleazy hack to avoid shift */ ! 561: dw = -(dm->width << 2); /* in outer, inner loops */ ! 562: } ! 563: else ! 564: { ! 565: sw = sm->width << 2; ! 566: dw = dm->width << 2; ! 567: } ! 568: ! 569: source = addr(sm,r.origin); ! 570: dest = addr(dm,p); ! 571: ! 572: switch(fc) ! 573: { ! 574: case F_STORE: ! 575: mask1 = topbits[a+1] >> (px31); ! 576: asm(" MOVW 0x20(%fp),%r1"); ! 577: do { ! 578: asm(" ROTW %r4,0(%r8),%r2"); ! 579: asm(" XORW2 0(%r7),%r2"); ! 580: asm(" ANDW2 %r1,%r2"); ! 581: asm(" XORW2 %r2,0(%r7)"); ! 582: asm(" ADDW2 %r6, %r8"); ! 583: asm(" ADDW2 %r5, %r7"); ! 584: } while (--i > 0); ! 585: break; ! 586: case F_STORE | S_STRADDLE: ! 587: mask4 = 32 - m; /* REALLY the other shift count */ ! 588: mask3 = topbits[a+1] >> px31; ! 589: asm(" PUSHW %ap"); /* store ap on stack */ ! 590: asm(" MOVW 0x28(%fp),%r0"); /* put mask3 in r0 */ ! 591: asm(" MOVW 0x2c(%fp),%ap"); /* put other shift in ap */ ! 592: ! 593: do { ! 594: asm(" LLSW3 %ap,0(%r8),%r1"); /* 32-m,lft shft */ ! 595: asm(" LRSW3 %r4,4(%r8),%r2"); /* m, right shift */ ! 596: asm(" ORW2 %r2, %r1"); ! 597: asm(" XORW2 0(%r7),%r1"); ! 598: asm(" ANDW2 %r0,%r1"); ! 599: asm(" XORW2 %r1,0(%r7)"); ! 600: asm(" ADDW2 %r6, %r8"); ! 601: asm(" ADDW2 %r5, %r7"); ! 602: } while (--i > 0); ! 603: asm(" POPW %ap"); /* restore ap from stack */ ! 604: break; ! 605: case F_STORE | D_STRADDLE: ! 606: asm(" PUSHW %ap"); /* store ap on stack */ ! 607: asm(" MOVW 0x28(%fp),%r0"); /* put mask3 in r0 */ ! 608: asm(" MOVW 0x2c(%fp),%ap"); /* put mask4 in ap */ ! 609: do { ! 610: asm(" ROTW %r4,0(%r8),%r1"); ! 611: asm(" XORW3 0(%r7),%r1,%r2"); ! 612: asm(" ANDW2 %r0,%r2"); ! 613: asm(" XORW2 %r2,0(%r7)"); ! 614: asm(" XORW2 4(%r7),%r1"); ! 615: asm(" ANDW2 %ap,%r1"); ! 616: asm(" XORW2 %r1,4(%r7)"); ! 617: asm(" ADDW2 %r6, %r8"); ! 618: asm(" ADDW2 %r5, %r7"); ! 619: } while (--i > 0); ! 620: asm(" POPW %ap"); /* restore ap from stack */ ! 621: break; ! 622: case F_STORE | S_STRADDLE | D_STRADDLE: ! 623: asm(" PUSHW %ap"); /* store ap on stack */ ! 624: asm(" SUBW3 %r4,&0x20,%ap"); /* right shift distance */ ! 625: asm(" MOVW 0x20(%fp),%r0"); /* r0 <- mask1 */ ! 626: asm(" MOVW 0x24(%fp),%r2"); /* r2 <- mask2 */ ! 627: asm(" PUSHW %fp"); /* store fp on stack */ ! 628: do { ! 629: asm(" ANDW3 %r0, 0(%r8), %r1"); ! 630: asm(" ANDW3 %r2, 4(%r8),%ap"); ! 631: asm(" ORW2 %ap, %r1"); ! 632: asm(" ROTW %r4, %r1, %r1"); ! 633: asm(" XORW3 0(%r7), %r1, %ap"); ! 634: asm(" ANDW2 0x28(%fp), %ap"); ! 635: asm(" XORW2 %ap, 0(%r7)"); ! 636: asm(" XORW2 4(%r7), %r1"); ! 637: asm(" ANDW2 0x2c(%fp), %r1"); ! 638: asm(" XORW2 %r1, 4(%r7)"); ! 639: asm(" ADDW2 %r6, %r8"); ! 640: asm(" ADDW2 %r5, %r7"); ! 641: } while (--i > 0); ! 642: asm(" POPW %fp"); /* restore fp from stack */ ! 643: asm(" POPW %ap"); /* restore ap from stack */ ! 644: break; ! 645: case F_OR: ! 646: mask1 = topbits[a+1] >> px31; ! 647: asm(" MOVW 0x20(%fp),%r1"); /* mask1 */ ! 648: do { ! 649: asm(" ROTW %r4,0(%r8),%r2"); ! 650: asm(" ANDW2 %r1,%r2"); ! 651: asm(" ORW2 %r2,0(%r7)"); ! 652: asm(" ADDW2 %r6, %r8"); ! 653: asm(" ADDW2 %r5, %r7"); ! 654: } while (--i > 0); ! 655: break; ! 656: case F_OR | S_STRADDLE: ! 657: asm(" MOVW 0x20(%fp),%r0"); /* store mask1 in a reg */ ! 658: asm(" PUSHW %ap"); /* store ap on stack */ ! 659: asm(" MOVW 0x24(%fp),%ap"); /* store mask1 in a reg */ ! 660: ! 661: do { ! 662: asm(" ANDW3 %r0,0(%r8),%r2"); /* x20(fp)=mask1 */ ! 663: asm(" ANDW3 %ap,4(%r8),%r1"); /* x24(fp)=mask2 */ ! 664: asm(" ORW2 %r2,%r1"); ! 665: asm(" ROTW %r4,%r1,%r1"); ! 666: asm(" ORW2 %r1,0(%r7)"); ! 667: asm(" ADDW2 %r6, %r8"); ! 668: asm(" ADDW2 %r5, %r7"); ! 669: } while (--i > 0); ! 670: asm(" POPW %ap"); /* restore ap from stack */ ! 671: break; ! 672: case F_OR | D_STRADDLE: ! 673: if (a <= 16) /* very narrow, 17 bits max */ ! 674: { ! 675: asm(" MOVW &0xffff0000,%r2"); ! 676: asm(" ORW3 0x28(%fp),0x2c(%fp),%r0"); /* compute mask */ ! 677: do { ! 678: asm(" ROTW %r4,0(%r8),%r1"); ! 679: asm(" ANDW2 %r0,%r1"); /* mask */ ! 680: asm(" ORH2 %r1,2(%r7)"); ! 681: asm(" ANDW2 %r2, %r1"); ! 682: asm(" ORW2 %r1, 4(%r7)"); ! 683: asm(" ADDW2 %r6, %r8"); ! 684: asm(" ADDW2 %r5, %r7"); ! 685: } while (--i > 0); ! 686: } ! 687: else ! 688: { ! 689: asm(" MOVW 0x28(%fp),%r0"); /* store mask3 in a reg */ ! 690: asm(" PUSHW %ap"); /* store ap on stack */ ! 691: asm(" MOVW 0x2c(%fp),%ap"); /* store mask4 in a reg */ ! 692: do { ! 693: asm(" ROTW %r4,0(%r8),%r1"); ! 694: asm(" ANDW3 %r0,%r1,%r2"); ! 695: asm(" ORW2 %r2,0(%r7)"); ! 696: asm(" ANDW2 %ap,%r1"); ! 697: asm(" ORW2 %r1,4(%r7)"); ! 698: asm(" ADDW2 %r6, %r8"); ! 699: asm(" ADDW2 %r5, %r7"); ! 700: } while (--i > 0); ! 701: asm(" POPW %ap"); /* restore ap from stack */ ! 702: } ! 703: break; ! 704: case F_OR | S_STRADDLE | D_STRADDLE: ! 705: asm(" MOVW 0x20(%fp),%r0"); /* store mask1 in a reg */ ! 706: asm(" PUSHW %ap"); /* store ap on stack */ ! 707: asm(" MOVW 0x24(%fp),%ap"); /* store mask2 in a reg */ ! 708: if (a > 16){ /* not super narrow */ ! 709: do { ! 710: asm(" ANDW3 %r0,0(%r8),%r1"); ! 711: asm(" ANDW3 %ap,4(%r8),%r2"); ! 712: asm(" ORW2 %r2,%r1"); ! 713: asm(" ROTW %r4,%r1,%r1"); ! 714: asm(" ANDW3 0x28(%fp),%r1,%r2"); ! 715: asm(" ORW2 %r2,0(%r7)"); ! 716: asm(" ANDW2 0x2c(%fp),%r1"); ! 717: asm(" ORW2 %r1,4(%r7)"); ! 718: asm(" ADDW2 %r6, %r8"); ! 719: asm(" ADDW2 %r5, %r7"); ! 720: } while (--i > 0); ! 721: } ! 722: else ! 723: { ! 724: do { ! 725: asm(" ANDW3 %r0,0(%r8),%r1"); ! 726: asm(" ANDW3 %ap,4(%r8),%r2"); ! 727: asm(" ORW2 %r2,%r1"); ! 728: asm(" ROTW %r4,%r1,%r1"); ! 729: asm(" ORH2 %r1,2(%r7)"); ! 730: asm(" ANDW2 &0xffff0000,%r1"); ! 731: asm(" ORW2 %r1,4(%r7)"); ! 732: asm(" ADDW2 %r6, %r8"); ! 733: asm(" ADDW2 %r5, %r7"); ! 734: } while (--i > 0); ! 735: } ! 736: asm(" POPW %ap"); /* restore ap from stack */ ! 737: break; ! 738: case F_CLR: ! 739: mask1 = topbits[a+1] >> px31; ! 740: asm(" MOVW 0x20(%fp),%r1"); /* mask1 */ ! 741: do { ! 742: asm(" ROTW %r4,0(%r8),%r2"); ! 743: asm(" ANDW2 %r1,%r2"); ! 744: asm(" MCOMW %r2,%r2"); ! 745: asm(" ANDW2 %r2,0(%r7)"); ! 746: asm(" ADDW2 %r6, %r8"); ! 747: asm(" ADDW2 %r5, %r7"); ! 748: } while (--i > 0); ! 749: break; ! 750: case F_CLR | S_STRADDLE: ! 751: asm(" MOVW 0x20(%fp),%r0"); /* store mask1 in a reg */ ! 752: asm(" PUSHW %ap"); /* store ap on stack */ ! 753: asm(" MOVW 0x24(%fp),%ap"); /* store mask1 in a reg */ ! 754: ! 755: do { ! 756: asm(" ANDW3 %r0,0(%r8),%r2"); /* x20(fp)=mask1 */ ! 757: asm(" ANDW3 %ap,4(%r8),%r1"); /* x24(fp)=mask2 */ ! 758: asm(" ORW2 %r2,%r1"); ! 759: asm(" ROTW %r4,%r1,%r1"); ! 760: asm(" MCOMW %r1,%r1"); ! 761: asm(" ANDW2 %r1,0(%r7)"); ! 762: asm(" ADDW2 %r6, %r8"); ! 763: asm(" ADDW2 %r5, %r7"); ! 764: } while (--i > 0); ! 765: asm(" POPW %ap"); /* restore ap from stack */ ! 766: break; ! 767: case F_CLR | D_STRADDLE: ! 768: if (a <= 16) /* very narrow, 17 bits max */ ! 769: { ! 770: asm(" MOVW &0xffff,%r2"); ! 771: asm(" ORW3 0x28(%fp),0x2c(%fp),%r0"); /* compute mask */ ! 772: do { ! 773: asm(" ROTW %r4,0(%r8),%r1"); ! 774: asm(" ANDW2 %r0,%r1"); /* mask */ ! 775: asm(" MCOMW %r1,%r1"); ! 776: asm(" ANDH2 %r1,2(%r7)"); ! 777: asm(" ORW2 %r2,%r1"); ! 778: asm(" ANDW2 %r1,4(%r7)"); ! 779: asm(" ADDW2 %r6, %r8"); ! 780: asm(" ADDW2 %r5, %r7"); ! 781: } while (--i > 0); ! 782: } ! 783: else ! 784: { ! 785: asm(" MOVW 0x28(%fp),%r0"); /* store mask3 in a reg */ ! 786: asm(" PUSHW %ap"); /* store ap on stack */ ! 787: asm(" MOVW 0x2c(%fp),%ap"); /* store mask4 in a reg */ ! 788: do { ! 789: asm(" ROTW %r4,0(%r8),%r1"); ! 790: asm(" ANDW3 %r0,%r1,%r2"); ! 791: asm(" MCOMW %r2,%r2"); ! 792: asm(" ANDW2 %r2,0(%r7)"); ! 793: asm(" ANDW2 %ap,%r1"); ! 794: asm(" MCOMW %r1,%r1"); ! 795: asm(" ANDW2 %r1,4(%r7)"); ! 796: asm(" ADDW2 %r6, %r8"); ! 797: asm(" ADDW2 %r5, %r7"); ! 798: } while (--i > 0); ! 799: asm(" POPW %ap"); /* restore ap from stack */ ! 800: } ! 801: break; ! 802: case F_CLR | S_STRADDLE | D_STRADDLE: ! 803: asm(" MOVW 0x20(%fp),%r0"); /* store mask1 in a reg */ ! 804: asm(" PUSHW %ap"); /* store ap on stack */ ! 805: asm(" MOVW 0x24(%fp),%ap"); /* store mask2 in a reg */ ! 806: if (a > 16){ /* not super narrow */ ! 807: do { ! 808: asm(" ANDW3 %r0,0(%r8),%r1"); ! 809: asm(" ANDW3 %ap,4(%r8),%r2"); ! 810: asm(" ORW2 %r2,%r1"); ! 811: asm(" ROTW %r4,%r1,%r1"); ! 812: asm(" ANDW3 0x28(%fp),%r1,%r2"); ! 813: asm(" MCOMW %r2,%r2"); ! 814: asm(" ANDW2 %r2,0(%r7)"); ! 815: asm(" ANDW2 0x2c(%fp),%r1"); ! 816: asm(" MCOMW %r1,%r1"); ! 817: asm(" ANDW2 %r1,4(%r7)"); ! 818: asm(" ADDW2 %r6, %r8"); ! 819: asm(" ADDW2 %r5, %r7"); ! 820: } while (--i > 0); ! 821: } ! 822: else ! 823: { ! 824: do { ! 825: asm(" ANDW3 %r0,0(%r8),%r1"); ! 826: asm(" ANDW3 %ap,4(%r8),%r2"); ! 827: asm(" ORW2 %r2,%r1"); ! 828: asm(" ROTW %r4,%r1,%r1"); ! 829: asm(" MCOMW %r1,%r1"); ! 830: asm(" ANDH2 %r1,2(%r7)"); ! 831: asm(" ORW2 &0xffff,%r1"); ! 832: asm(" ANDW2 %r1,4(%r7)"); ! 833: asm(" ADDW2 %r6, %r8"); ! 834: asm(" ADDW2 %r5, %r7"); ! 835: } while (--i > 0); ! 836: } ! 837: asm(" POPW %ap"); /* restore ap from stack */ ! 838: break; ! 839: case F_XOR: ! 840: mask1 = topbits[a+1] >> px31; ! 841: asm(" MOVW 0x20(%fp),%r1"); /* mask1 */ ! 842: do { ! 843: asm(" ROTW %r4,0(%r8),%r2"); ! 844: asm(" ANDW2 %r1,%r2"); ! 845: asm(" XORW2 %r2,0(%r7)"); ! 846: asm(" ADDW2 %r6, %r8"); ! 847: asm(" ADDW2 %r5, %r7"); ! 848: } while (--i > 0); ! 849: break; ! 850: case F_XOR | S_STRADDLE: ! 851: asm(" MOVW 0x20(%fp),%r0"); /* store mask1 in a reg */ ! 852: asm(" PUSHW %ap"); /* store ap on stack */ ! 853: asm(" MOVW 0x24(%fp),%ap"); /* store mask1 in a reg */ ! 854: ! 855: do { ! 856: asm(" ANDW3 %r0,0(%r8),%r2"); /* x20(fp)=mask1 */ ! 857: asm(" ANDW3 %ap,4(%r8),%r1"); /* x24(fp)=mask2 */ ! 858: asm(" ORW2 %r2,%r1"); ! 859: asm(" ROTW %r4,%r1,%r1"); ! 860: asm(" XORW2 %r1,0(%r7)"); ! 861: asm(" ADDW2 %r6, %r8"); ! 862: asm(" ADDW2 %r5, %r7"); ! 863: } while (--i > 0); ! 864: asm(" POPW %ap"); /* restore ap from stack */ ! 865: break; ! 866: case F_XOR | D_STRADDLE: ! 867: if (a <= 16) /* very narrow, 17 bits max */ ! 868: { ! 869: asm(" MOVW &0xffff0000,%r2"); ! 870: asm(" ORW3 0x28(%fp),0x2c(%fp),%r0"); /* compute mask */ ! 871: do { ! 872: asm(" ROTW %r4,0(%r8),%r1"); ! 873: asm(" ANDW2 %r0,%r1"); /* mask */ ! 874: asm(" XORH2 %r1,2(%r7)"); ! 875: asm(" ANDW2 %r2,%r1"); ! 876: asm(" XORW2 %r1,4(%r7)"); ! 877: asm(" ADDW2 %r6, %r8"); ! 878: asm(" ADDW2 %r5, %r7"); ! 879: } while (--i > 0); ! 880: } ! 881: else ! 882: { ! 883: asm(" MOVW 0x28(%fp),%r0"); /* store mask3 in a reg */ ! 884: asm(" PUSHW %ap"); /* store ap on stack */ ! 885: asm(" MOVW 0x2c(%fp),%ap"); /* store mask4 in a reg */ ! 886: do { ! 887: asm(" ROTW %r4,0(%r8),%r1"); ! 888: asm(" ANDW3 %r0,%r1,%r2"); ! 889: asm(" XORW2 %r2,0(%r7)"); ! 890: asm(" ANDW2 %ap,%r1"); ! 891: asm(" XORW2 %r1,4(%r7)"); ! 892: asm(" ADDW2 %r6, %r8"); ! 893: asm(" ADDW2 %r5, %r7"); ! 894: } while (--i > 0); ! 895: asm(" POPW %ap"); /* restore ap from stack */ ! 896: } ! 897: break; ! 898: case F_XOR | S_STRADDLE | D_STRADDLE: ! 899: asm(" MOVW 0x20(%fp),%r0"); /* store mask1 in a reg */ ! 900: asm(" PUSHW %ap"); /* store ap on stack */ ! 901: asm(" MOVW 0x24(%fp),%ap"); /* store mask2 in a reg */ ! 902: if (a > 16){ /* not super narrow */ ! 903: do { ! 904: asm(" ANDW3 %r0,0(%r8),%r1"); ! 905: asm(" ANDW3 %ap,4(%r8),%r2"); ! 906: asm(" ORW2 %r2,%r1"); ! 907: asm(" ROTW %r4,%r1,%r1"); ! 908: asm(" ANDW3 0x28(%fp),%r1,%r2"); ! 909: asm(" XORW2 %r2,0(%r7)"); ! 910: asm(" ANDW2 0x2c(%fp),%r1"); ! 911: asm(" XORW2 %r1,4(%r7)"); ! 912: asm(" ADDW2 %r6, %r8"); ! 913: asm(" ADDW2 %r5, %r7"); ! 914: } while (--i > 0); ! 915: } ! 916: else ! 917: { ! 918: do { ! 919: asm(" ANDW3 %r0,0(%r8),%r1"); ! 920: asm(" ANDW3 %ap,4(%r8),%r2"); ! 921: asm(" ORW2 %r2,%r1"); ! 922: asm(" ROTW %r4,%r1,%r1"); ! 923: asm(" XORH2 %r1,2(%r7)"); ! 924: asm(" ANDW2 &0xffff0000,%r1"); ! 925: asm(" XORW2 %r1,4(%r7)"); ! 926: asm(" ADDW2 %r6, %r8"); ! 927: asm(" ADDW2 %r5, %r7"); ! 928: } while (--i > 0); ! 929: } ! 930: asm(" POPW %ap"); /* restore ap from stack */ ! 931: break; ! 932: } ! 933: return; ! 934: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.