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