1 /*
2  * cfb copy area
3  */
4 
5 /*
6 
7 Copyright (c) 1989  X Consortium
8 
9 Permission is hereby granted, free of charge, to any person obtaining a copy
10 of this software and associated documentation files (the "Software"), to deal
11 in the Software without restriction, including without limitation the rights
12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the Software is
14 furnished to do so, subject to the following conditions:
15 
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18 
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
22 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 
26 Except as contained in this notice, the name of the X Consortium shall not be
27 used in advertising or otherwise to promote the sale, use or other dealings
28 in this Software without prior written authorization from the X Consortium.
29 
30 Author: Keith Packard
31 
32 */
33 /* $XConsortium: cfbblt.c,v 1.13 94/04/17 20:28:44 dpw Exp $ */
34 /* $XFree86: xc/programs/Xserver/cfb/cfbblt.c,v 3.1 1996/12/09 11:50:52 dawes Exp $ */
35 
36 #include	"X.h"
37 #include	"Xmd.h"
38 #include	"Xproto.h"
39 #include	"gcstruct.h"
40 #include	"windowstr.h"
41 #include	"scrnintstr.h"
42 #include	"pixmapstr.h"
43 #include	"regionstr.h"
44 #include	"cfb.h"
45 #include	"cfbmskbits.h"
46 #include	"cfb8bit.h"
47 #include	"fastblt.h"
48 #include	"mergerop.h"
49 
50 #ifdef notdef /* XXX fails right now, walks off end of pixmaps */
51 #if defined (FAST_UNALIGNED_READS) && PSZ == 8
52 #define DO_UNALIGNED_BITBLT
53 #endif
54 #endif
55 
56 #if defined(FAST_MEMCPY) && (MROP == Mcopy) && PSZ == 8
57 #define DO_MEMCPY
58 #endif
59 
60 void
61 MROP_NAME(cfbDoBitblt)(pSrc, pDst, alu, prgnDst, pptSrc, planemask)
62     DrawablePtr	    pSrc, pDst;
63     int		    alu;
64     RegionPtr	    prgnDst;
65     DDXPointPtr	    pptSrc;
66     unsigned long   planemask;
67 {
68     unsigned long *psrcBase, *pdstBase;
69 				/* start of src and dst bitmaps */
70     int widthSrc, widthDst;	/* add to get to same position in next line */
71 
72     BoxPtr pbox;
73     int nbox;
74 
75     BoxPtr pboxTmp, pboxNext, pboxBase, pboxNew1, pboxNew2;
76 				/* temporaries for shuffling rectangles */
77     DDXPointPtr pptTmp, pptNew1, pptNew2;
78 				/* shuffling boxes entails shuffling the
79 				   source points too */
80     int w, h;
81     int xdir;			/* 1 = left right, -1 = right left/ */
82     int ydir;			/* 1 = top down, -1 = bottom up */
83 
84     unsigned long *psrcLine, *pdstLine;
85 				/* pointers to line with current src and dst */
86     register unsigned long *psrc;/* pointer to current src longword */
87     register unsigned long *pdst;/* pointer to current dst longword */
88 
89     MROP_DECLARE_REG()
90 
91 				/* following used for looping through a line */
92     unsigned long startmask, endmask;	/* masks for writing ends of dst */
93     int nlMiddle;		/* whole longwords in dst */
94     int xoffSrc, xoffDst;
95     register int leftShift, rightShift;
96     register unsigned long bits;
97     register unsigned long bits1;
98     register int nl;		/* temp copy of nlMiddle */
99 
100 				/* place to store full source word */
101     int nstart;			/* number of ragged bits at start of dst */
102     int nend;			/* number of ragged bits at end of dst */
103     int srcStartOver;		/* pulling nstart bits from src
104 				   overflows into the next word? */
105     int careful;
106     int tmpSrc;
107 #if PSZ == 24
108 #ifdef DO_MEMCPY
109     int w2;
110 #endif
111 #endif
112 
113     MROP_INITIALIZE(alu,planemask);
114 
115     cfbGetLongWidthAndPointer (pSrc, widthSrc, psrcBase)
116 
117     cfbGetLongWidthAndPointer (pDst, widthDst, pdstBase)
118 
119     /* XXX we have to err on the side of safety when both are windows,
120      * because we don't know if IncludeInferiors is being used.
121      */
122     careful = ((pSrc == pDst) ||
123 	       ((pSrc->type == DRAWABLE_WINDOW) &&
124 		(pDst->type == DRAWABLE_WINDOW)));
125 
126     pbox = REGION_RECTS(prgnDst);
127     nbox = REGION_NUM_RECTS(prgnDst);
128 
129     pboxNew1 = NULL;
130     pptNew1 = NULL;
131     pboxNew2 = NULL;
132     pptNew2 = NULL;
133     if (careful && (pptSrc->y < pbox->y1))
134     {
135         /* walk source botttom to top */
136 	ydir = -1;
137 	widthSrc = -widthSrc;
138 	widthDst = -widthDst;
139 
140 	if (nbox > 1)
141 	{
142 	    /* keep ordering in each band, reverse order of bands */
143 	    pboxNew1 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox);
144 	    if(!pboxNew1)
145 		return;
146 	    pptNew1 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox);
147 	    if(!pptNew1)
148 	    {
149 	        DEALLOCATE_LOCAL(pboxNew1);
150 	        return;
151 	    }
152 	    pboxBase = pboxNext = pbox+nbox-1;
153 	    while (pboxBase >= pbox)
154 	    {
155 	        while ((pboxNext >= pbox) &&
156 		       (pboxBase->y1 == pboxNext->y1))
157 		    pboxNext--;
158 	        pboxTmp = pboxNext+1;
159 	        pptTmp = pptSrc + (pboxTmp - pbox);
160 	        while (pboxTmp <= pboxBase)
161 	        {
162 		    *pboxNew1++ = *pboxTmp++;
163 		    *pptNew1++ = *pptTmp++;
164 	        }
165 	        pboxBase = pboxNext;
166 	    }
167 	    pboxNew1 -= nbox;
168 	    pbox = pboxNew1;
169 	    pptNew1 -= nbox;
170 	    pptSrc = pptNew1;
171         }
172     }
173     else
174     {
175 	/* walk source top to bottom */
176 	ydir = 1;
177     }
178 
179     if (careful && (pptSrc->x < pbox->x1))
180     {
181 	/* walk source right to left */
182         xdir = -1;
183 
184 	if (nbox > 1)
185 	{
186 	    /* reverse order of rects in each band */
187 	    pboxNew2 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox);
188 	    pptNew2 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox);
189 	    if(!pboxNew2 || !pptNew2)
190 	    {
191 		if (pptNew2) DEALLOCATE_LOCAL(pptNew2);
192 		if (pboxNew2) DEALLOCATE_LOCAL(pboxNew2);
193 		if (pboxNew1)
194 		{
195 		    DEALLOCATE_LOCAL(pptNew1);
196 		    DEALLOCATE_LOCAL(pboxNew1);
197 		}
198 	        return;
199 	    }
200 	    pboxBase = pboxNext = pbox;
201 	    while (pboxBase < pbox+nbox)
202 	    {
203 	        while ((pboxNext < pbox+nbox) &&
204 		       (pboxNext->y1 == pboxBase->y1))
205 		    pboxNext++;
206 	        pboxTmp = pboxNext;
207 	        pptTmp = pptSrc + (pboxTmp - pbox);
208 	        while (pboxTmp != pboxBase)
209 	        {
210 		    *pboxNew2++ = *--pboxTmp;
211 		    *pptNew2++ = *--pptTmp;
212 	        }
213 	        pboxBase = pboxNext;
214 	    }
215 	    pboxNew2 -= nbox;
216 	    pbox = pboxNew2;
217 	    pptNew2 -= nbox;
218 	    pptSrc = pptNew2;
219 	}
220     }
221     else
222     {
223 	/* walk source left to right */
224         xdir = 1;
225     }
226 
227     while(nbox--)
228     {
229 	w = pbox->x2 - pbox->x1;
230 	h = pbox->y2 - pbox->y1;
231 
232 #if PSZ == 24
233 #ifdef DO_MEMCPY
234 	w2 = w * 3;
235 #endif
236 #endif
237 	if (ydir == -1) /* start at last scanline of rectangle */
238 	{
239 	    psrcLine = psrcBase + ((pptSrc->y+h-1) * -widthSrc);
240 	    pdstLine = pdstBase + ((pbox->y2-1) * -widthDst);
241 	}
242 	else /* start at first scanline */
243 	{
244 	    psrcLine = psrcBase + (pptSrc->y * widthSrc);
245 	    pdstLine = pdstBase + (pbox->y1 * widthDst);
246 	}
247 #if PSZ == 24
248 	if (w == 1 && ((pbox->x1 & 3) == 0  ||  (pbox->x1 & 3) == 3))
249 #else
250 	if ((pbox->x1 & PIM) + w <= PPW)
251 #endif
252 	{
253 	    maskpartialbits (pbox->x1, w, endmask);
254 	    startmask = 0;
255 	    nlMiddle = 0;
256 	}
257 	else
258 	{
259 	    maskbits(pbox->x1, w, startmask, endmask, nlMiddle);
260 	}
261 
262 #ifdef DO_MEMCPY
263 	/* If the src and dst scanline don't overlap, do forward case.  */
264 
265 	if ((xdir == 1) || (pptSrc->y != pbox->y1)
266 		|| (pptSrc->x + w <= pbox->x1))
267 	{
268 #if PSZ == 24
269 	    char *psrc = (char *) psrcLine + (pptSrc->x * 3);
270 	    char *pdst = (char *) pdstLine + (pbox->x1 * 3);
271 #else
272 	    char *psrc = (char *) psrcLine + pptSrc->x;
273 	    char *pdst = (char *) pdstLine + pbox->x1;
274 #endif
275 	    while (h--)
276 	    {
277 #if PSZ == 24
278 	    	memcpy(pdst, psrc, w2);
279 #else
280 	    	memcpy(pdst, psrc, w);
281 #endif
282 		pdst += widthDst << PWSH;
283 		psrc += widthSrc << PWSH;
284 	    }
285 	}
286 #else /* ! DO_MEMCPY */
287 	if (xdir == 1)
288 	{
289 #if PSZ == 24
290 	    xoffSrc = (4 - pptSrc->x) & 3;
291 	    xoffDst = (4 - pbox->x1) & 3;
292 	    pdstLine += (pbox->x1 * 3) >> 2;
293 	    psrcLine += (pptSrc->x * 3) >> 2;
294 #else
295 	    xoffSrc = pptSrc->x & PIM;
296 	    xoffDst = pbox->x1 & PIM;
297 	    pdstLine += (pbox->x1 >> PWSH);
298 	    psrcLine += (pptSrc->x >> PWSH);
299 #endif
300 #ifdef DO_UNALIGNED_BITBLT
301 	    nl = xoffSrc - xoffDst;
302 	    psrcLine = (unsigned long *)
303 			(((unsigned char *) psrcLine) + nl);
304 #else
305 	    if (xoffSrc == xoffDst)
306 #endif
307 	    {
308 		while (h--)
309 		{
310 		    psrc = psrcLine;
311 		    pdst = pdstLine;
312 		    pdstLine += widthDst;
313 		    psrcLine += widthSrc;
314 		    if (startmask)
315 		    {
316 			*pdst = MROP_MASK(*psrc, *pdst, startmask);
317 			psrc++;
318 			pdst++;
319 		    }
320 		    nl = nlMiddle;
321 
322 #ifdef LARGE_INSTRUCTION_CACHE
323 #ifdef FAST_CONSTANT_OFFSET_MODE
324 
325 		    psrc += nl & (UNROLL-1);
326 		    pdst += nl & (UNROLL-1);
327 
328 #define BodyOdd(n) pdst[-n] = MROP_SOLID (psrc[-n], pdst[-n]);
329 #define BodyEven(n) pdst[-n] = MROP_SOLID (psrc[-n], pdst[-n]);
330 
331 #define LoopReset \
332 pdst += UNROLL; \
333 psrc += UNROLL;
334 
335 #else
336 
337 #define BodyOdd(n)  *pdst = MROP_SOLID (*psrc, *pdst); pdst++; psrc++;
338 #define BodyEven(n) BodyOdd(n)
339 
340 #define LoopReset   ;
341 
342 #endif
343 		    PackedLoop
344 
345 #undef BodyOdd
346 #undef BodyEven
347 #undef LoopReset
348 
349 #else
350 #ifdef NOTDEF
351 		    /* you'd think this would be faster --
352 		     * a single instruction instead of 6
353 		     * but measurements show it to be ~15% slower
354 		     */
355 		    while ((nl -= 6) >= 0)
356 		    {
357 			asm ("moveml %1+,#0x0c0f;moveml#0x0c0f,%0"
358 			     : "=m" (*(char *)pdst)
359 			     : "m" (*(char *)psrc)
360 			     : "d0", "d1", "d2", "d3",
361 			       "a2", "a3");
362 			pdst += 6;
363 		    }
364 		    nl += 6;
365 		    while (nl--)
366 			*pdst++ = *psrc++;
367 #endif
368 		    DuffL(nl, label1,
369 			    *pdst = MROP_SOLID (*psrc, *pdst);
370 			    pdst++; psrc++;)
371 #endif
372 
373 		    if (endmask)
374 			*pdst = MROP_MASK(*psrc, *pdst, endmask);
375 		}
376 	    }
377 #ifndef DO_UNALIGNED_BITBLT
378 	    else
379 	    {
380 		if (xoffSrc > xoffDst)
381 		{
382 #if PSZ == 24
383 		    leftShift = (xoffSrc - xoffDst) << 3;
384 #else
385 #if PGSZ == 32
386 		    leftShift = (xoffSrc - xoffDst) << (5 - PWSH);
387 #else /* PGSZ == 64 */
388 		    leftShift = (xoffSrc - xoffDst) << (6 - PWSH);
389 #endif /* PGSZ */
390 #endif
391 		    rightShift = PGSZ - leftShift;
392 		}
393 		else
394 		{
395 #if PSZ == 24
396 		    rightShift = (xoffDst - xoffSrc) << 3;
397 #else
398 #if PGSZ == 32
399 		    rightShift = (xoffDst - xoffSrc) << (5 - PWSH);
400 #else /* PGSZ == 64 */
401 		    rightShift = (xoffDst - xoffSrc) << (6 - PWSH);
402 #endif /* PGSZ */
403 #endif
404 		    leftShift = PGSZ - rightShift;
405 		}
406 		while (h--)
407 		{
408 		    psrc = psrcLine;
409 		    pdst = pdstLine;
410 		    pdstLine += widthDst;
411 		    psrcLine += widthSrc;
412 		    bits = 0;
413 		    if (xoffSrc > xoffDst)
414 			bits = *psrc++;
415 		    if (startmask)
416 		    {
417 			bits1 = BitLeft(bits,leftShift);
418 			bits = *psrc++;
419 			bits1 |= BitRight(bits,rightShift);
420 			*pdst = MROP_MASK(bits1, *pdst, startmask);
421 			pdst++;
422 		    }
423 		    nl = nlMiddle;
424 
425 #ifdef LARGE_INSTRUCTION_CACHE
426 		    bits1 = bits;
427 
428 #ifdef FAST_CONSTANT_OFFSET_MODE
429 
430 		    psrc += nl & (UNROLL-1);
431 		    pdst += nl & (UNROLL-1);
432 
433 #define BodyOdd(n) \
434 bits = psrc[-n]; \
435 pdst[-n] = MROP_SOLID(BitLeft(bits1, leftShift) | BitRight(bits, rightShift), pdst[-n]);
436 
437 #define BodyEven(n) \
438 bits1 = psrc[-n]; \
439 pdst[-n] = MROP_SOLID(BitLeft(bits, leftShift) | BitRight(bits1, rightShift), pdst[-n]);
440 
441 #define LoopReset \
442 pdst += UNROLL; \
443 psrc += UNROLL;
444 
445 #else
446 
447 #define BodyOdd(n) \
448 bits = *psrc++; \
449 *pdst = MROP_SOLID(BitLeft(bits1, leftShift) | BitRight(bits, rightShift), *pdst); \
450 pdst++;
451 
452 #define BodyEven(n) \
453 bits1 = *psrc++; \
454 *pdst = MROP_SOLID(BitLeft(bits, leftShift) | BitRight(bits1, rightShift), *pdst); \
455 pdst++;
456 
457 #define LoopReset   ;
458 
459 #endif	/* !FAST_CONSTANT_OFFSET_MODE */
460 
461 		    PackedLoop
462 
463 #undef BodyOdd
464 #undef BodyEven
465 #undef LoopReset
466 
467 #else
468 		    DuffL (nl,label2,
469 			bits1 = BitLeft(bits, leftShift);
470 			bits = *psrc++;
471 			*pdst = MROP_SOLID (bits1 | BitRight(bits, rightShift), *pdst);
472 			pdst++;
473 		    )
474 #endif
475 
476 		    if (endmask)
477 		    {
478 			bits1 = BitLeft(bits, leftShift);
479 			if (BitLeft(endmask, rightShift))
480 			{
481 			    bits = *psrc;
482 			    bits1 |= BitRight(bits, rightShift);
483 			}
484 			*pdst = MROP_MASK (bits1, *pdst, endmask);
485 		    }
486 		}
487 	    }
488 #endif /* DO_UNALIGNED_BITBLT */
489 	}
490 #endif /* ! DO_MEMCPY */
491 	else	/* xdir == -1 */
492 	{
493 #if PSZ == 24
494 	    xoffSrc = (pptSrc->x + w) & 3;
495 	    xoffDst = pbox->x2 & 3;
496 	    pdstLine += ((pbox->x2 * 3 - 1) >> 2) + 1;
497 	    psrcLine += (((pptSrc->x+w) * 3 - 1) >> 2) + 1;
498 #else
499 	    xoffSrc = (pptSrc->x + w - 1) & PIM;
500 	    xoffDst = (pbox->x2 - 1) & PIM;
501 	    pdstLine += ((pbox->x2-1) >> PWSH) + 1;
502 	    psrcLine += ((pptSrc->x+w - 1) >> PWSH) + 1;
503 #endif
504 #ifdef DO_UNALIGNED_BITBLT
505 #if PSZ == 24
506 	    nl = xoffDst - xoffSrc;
507 #else
508 	    nl = xoffSrc - xoffDst;
509 #endif
510 	    psrcLine = (unsigned long *)
511 			(((unsigned char *) psrcLine) + nl);
512 #else
513 	    if (xoffSrc == xoffDst)
514 #endif
515 	    {
516 		while (h--)
517 		{
518 		    psrc = psrcLine;
519 		    pdst = pdstLine;
520 		    pdstLine += widthDst;
521 		    psrcLine += widthSrc;
522 		    if (endmask)
523 		    {
524 			pdst--;
525 			psrc--;
526 			*pdst = MROP_MASK (*psrc, *pdst, endmask);
527 		    }
528 		    nl = nlMiddle;
529 
530 #ifdef LARGE_INSTRUCTION_CACHE
531 #ifdef FAST_CONSTANT_OFFSET_MODE
532 		    psrc -= nl & (UNROLL - 1);
533 		    pdst -= nl & (UNROLL - 1);
534 
535 #define BodyOdd(n) pdst[n-1] = MROP_SOLID (psrc[n-1], pdst[n-1]);
536 
537 #define BodyEven(n) BodyOdd(n)
538 
539 #define LoopReset \
540 pdst -= UNROLL;\
541 psrc -= UNROLL;
542 
543 #else
544 
545 #define BodyOdd(n)  --pdst; --psrc; *pdst = MROP_SOLID(*psrc, *pdst);
546 #define BodyEven(n) BodyOdd(n)
547 #define LoopReset   ;
548 
549 #endif
550 		    PackedLoop
551 
552 #undef BodyOdd
553 #undef BodyEven
554 #undef LoopReset
555 
556 #else
557 		    DuffL(nl,label3,
558 			 --pdst; --psrc; *pdst = MROP_SOLID (*psrc, *pdst);)
559 #endif
560 
561 		    if (startmask)
562 		    {
563 			--pdst;
564 			--psrc;
565 			*pdst = MROP_MASK(*psrc, *pdst, startmask);
566 		    }
567 		}
568 	    }
569 #ifndef DO_UNALIGNED_BITBLT
570 	    else
571 	    {
572 		if (xoffDst > xoffSrc)
573 		{
574 #if PSZ == 24
575 		    leftShift = (xoffDst - xoffSrc) << 3;
576 		    rightShift = PGSZ - leftShift;
577 #else
578 #if PGSZ == 32
579 		    rightShift = (xoffDst - xoffSrc) << (5 - PWSH);
580 #else /* PGSZ == 64 */
581 		    rightShift = (xoffDst - xoffSrc) << (6 - PWSH);
582 #endif /* PGSZ */
583 		    leftShift = PGSZ - rightShift;
584 #endif
585 		}
586 		else
587 		{
588 #if PSZ == 24
589 		    rightShift = (xoffSrc - xoffDst) << 3;
590 		    leftShift = PGSZ - rightShift;
591 #else
592 #if PGSZ == 32
593 		    leftShift = (xoffSrc - xoffDst) << (5 - PWSH);
594 #else /* PGSZ == 64 */
595 		    leftShift = (xoffSrc - xoffDst) << (6 - PWSH);
596 #endif /* PGSZ */
597 		    rightShift = PGSZ - leftShift;
598 #endif
599 		}
600 		while (h--)
601 		{
602 		    psrc = psrcLine;
603 		    pdst = pdstLine;
604 		    pdstLine += widthDst;
605 		    psrcLine += widthSrc;
606 		    bits = 0;
607 #if PSZ == 24
608 		    if (xoffSrc > xoffDst)
609 #else
610 		    if (xoffDst > xoffSrc)
611 #endif
612 			bits = *--psrc;
613 		    if (endmask)
614 		    {
615 			bits1 = BitRight(bits, rightShift);
616 			bits = *--psrc;
617 			bits1 |= BitLeft(bits, leftShift);
618 			pdst--;
619 			*pdst = MROP_MASK(bits1, *pdst, endmask);
620 		    }
621 		    nl = nlMiddle;
622 
623 #ifdef LARGE_INSTRUCTION_CACHE
624 		    bits1 = bits;
625 #ifdef FAST_CONSTANT_OFFSET_MODE
626 		    psrc -= nl & (UNROLL - 1);
627 		    pdst -= nl & (UNROLL - 1);
628 
629 #define BodyOdd(n) \
630 bits = psrc[n-1]; \
631 pdst[n-1] = MROP_SOLID(BitRight(bits1, rightShift) | BitLeft(bits, leftShift),pdst[n-1]);
632 
633 #define BodyEven(n) \
634 bits1 = psrc[n-1]; \
635 pdst[n-1] = MROP_SOLID(BitRight(bits, rightShift) | BitLeft(bits1, leftShift),pdst[n-1]);
636 
637 #define LoopReset \
638 pdst -= UNROLL; \
639 psrc -= UNROLL;
640 
641 #else
642 
643 #define BodyOdd(n) \
644 bits = *--psrc; --pdst; \
645 *pdst = MROP_SOLID(BitRight(bits1, rightShift) | BitLeft(bits, leftShift),*pdst);
646 
647 #define BodyEven(n) \
648 bits1 = *--psrc; --pdst; \
649 *pdst = MROP_SOLID(BitRight(bits, rightShift) | BitLeft(bits1, leftShift),*pdst);
650 
651 #define LoopReset   ;
652 
653 #endif
654 
655 		    PackedLoop
656 
657 #undef BodyOdd
658 #undef BodyEven
659 #undef LoopReset
660 
661 #else
662 		    DuffL (nl, label4,
663 			bits1 = BitRight(bits, rightShift);
664 			bits = *--psrc;
665 			--pdst;
666 			*pdst = MROP_SOLID(bits1 | BitLeft(bits, leftShift),*pdst);
667 		    )
668 #endif
669 
670 		    if (startmask)
671 		    {
672 			bits1 = BitRight(bits, rightShift);
673 			if (BitRight (startmask, leftShift))
674 			{
675 			    bits = *--psrc;
676 			    bits1 |= BitLeft(bits, leftShift);
677 			}
678 			--pdst;
679 			*pdst = MROP_MASK(bits1, *pdst, startmask);
680 		    }
681 		}
682 	    }
683 #endif
684 	}
685 	pbox++;
686 	pptSrc++;
687     }
688     if (pboxNew2)
689     {
690 	DEALLOCATE_LOCAL(pptNew2);
691 	DEALLOCATE_LOCAL(pboxNew2);
692     }
693     if (pboxNew1)
694     {
695 	DEALLOCATE_LOCAL(pptNew1);
696 	DEALLOCATE_LOCAL(pboxNew1);
697     }
698 }
699