155131Storek /*- 255131Storek * Copyright (c) 1991 The Regents of the University of California. 355131Storek * All rights reserved. 455131Storek * 555131Storek * This code is derived from software contributed to the Computer Systems 655131Storek * Engineering Group at Lawrence Berkeley Laboratory and to the University 755131Storek * of California at Berkeley by Jef Poskanzer. 855131Storek * 955131Storek * %sccs.include.redist.c% 1055131Storek * 11*56539Sbostic * @(#)raster_op.c 7.2 (Berkeley) 10/11/92 1255131Storek * 1355131Storek * from: $Header: raster_op.c,v 1.22 92/06/17 08:14:44 torek Exp $ 1455131Storek */ 1555131Storek 1655131Storek /* 1755131Storek * Bitblit routine for raster library. 1855131Storek * 1955131Storek * This raster-op is machined to exacting tolerances by skilled native 2055131Storek * craftsmen with pride in their work. 2155131Storek * 2255131Storek * The various cases are broken down like this: 2355131Storek * 2455131Storek * src required 2555131Storek * 1-bit to 1-bit 2655131Storek * 1-bit to 8-bits 2755131Storek * 8-bits to 8-bits 2855131Storek * no src required 2955131Storek * 1-bit no-src 3055131Storek * 8-bits no-src 3155131Storek */ 3255131Storek 3355131Storek #include <sys/types.h> 34*56539Sbostic #include <sparc/rcons/raster.h> 3555131Storek 3655131Storek /* CONFIGURE: To save on executable size, you can configure out the seldom-used 3755131Storek ** logical operations. With this variable set, the only operations implemented 3855131Storek ** are: RAS_SRC, RAS_CLEAR, RAS_SET, RAS_INVERT, RAS_XOR, RAS_INVERTSRC. 3955131Storek */ 4055131Storek #ifdef KERNEL 4155131Storek #define PARTIAL_LOGICAL_OPS 4255131Storek #endif 4355131Storek 4455131Storek /* CONFIGURE: bcopy() is supposed to be the ultimately fastest way to move 4555131Storek ** bytes, overlapping or not, ignoring the startup cost. Unfortunately 4655131Storek ** this is not true on some systems. For example, on a Sun 3 running 4755131Storek ** SunOS 3.5, bcopy() is about five times slower than a simple for loop 4855131Storek ** on overlapping copies. And on a 4.1.1 SPARC, bcopy() is about 2/3rds 4955131Storek ** as fast on backwards overlaps. So, only define this if your bcopy is ok. 5055131Storek */ 5155131Storek #undef BCOPY_FASTER 5255131Storek 5355131Storek /* End of configurable definitions. */ 5455131Storek 5555131Storek 5655131Storek /* Definitions. */ 5755131Storek 5855131Storek /* Raster-op macros. These encapsulate the switch statements and so make 5955131Storek ** the source code 16 times smaller. The pre and pst args are code 6055131Storek ** fragments to put before and after the assignment in each case. They 6155131Storek ** can be the beginning and end of a loop. If the pst fragment includes a 6255131Storek ** masked assignment, for example to handle the left or right edge cases, 6355131Storek ** a good optimizing compiler will simplify the boolean expressions very 6455131Storek ** nicely - both cc and gcc on the SPARC will do this. 6555131Storek */ 6655131Storek 6755131Storek #ifndef PARTIAL_LOGICAL_OPS 6855131Storek 6955131Storek #define ROP_DST(op,pre,d,pst) \ 7055131Storek switch ( op ) \ 7155131Storek { \ 7255131Storek case RAS_CLEAR: \ 7355131Storek pre \ 7455131Storek (d) = 0; \ 7555131Storek pst \ 7655131Storek break; \ 7755131Storek case RAS_INVERT: \ 7855131Storek pre \ 7955131Storek (d) = ~(d); \ 8055131Storek pst \ 8155131Storek break; \ 8255131Storek case RAS_DST: \ 8355131Storek /* noop */ \ 8455131Storek break; \ 8555131Storek case RAS_SET: \ 8655131Storek pre \ 8755131Storek (d) = ~0; \ 8855131Storek pst \ 8955131Storek break; \ 9055131Storek default: \ 9155131Storek return -1; \ 9255131Storek } 9355131Storek 9455131Storek #define ROP_DSTCOLOR(op,pre,d,c,pst) \ 9555131Storek switch ( op ) \ 9655131Storek { \ 9755131Storek case RAS_CLEAR: \ 9855131Storek pre \ 9955131Storek (d) = 0; \ 10055131Storek pst \ 10155131Storek break; \ 10255131Storek case RAS_INVERT: \ 10355131Storek pre \ 10455131Storek (d) = ~(d); \ 10555131Storek pst \ 10655131Storek break; \ 10755131Storek case RAS_DST: \ 10855131Storek /* noop */ \ 10955131Storek break; \ 11055131Storek case RAS_SET: \ 11155131Storek pre \ 11255131Storek (d) = (c); \ 11355131Storek pst \ 11455131Storek break; \ 11555131Storek default: \ 11655131Storek return -1; \ 11755131Storek } 11855131Storek 11955131Storek #define ROP_SRCDST(op,pre,s,d,pst) \ 12055131Storek switch ( op ) \ 12155131Storek { \ 12255131Storek case RAS_NOTOR: \ 12355131Storek pre \ 12455131Storek (d) = ~( (s) | (d) ); \ 12555131Storek pst \ 12655131Storek break; \ 12755131Storek case RAS_NOTSRC_AND_DST: \ 12855131Storek pre \ 12955131Storek (d) = ~(s) & (d); \ 13055131Storek pst \ 13155131Storek break; \ 13255131Storek case RAS_INVERTSRC: \ 13355131Storek pre \ 13455131Storek (d) = ~(s); \ 13555131Storek pst \ 13655131Storek break; \ 13755131Storek case RAS_SRC_AND_NOTDST: \ 13855131Storek pre \ 13955131Storek (d) = (s) & ~(d); \ 14055131Storek pst \ 14155131Storek break; \ 14255131Storek case RAS_XOR: \ 14355131Storek pre \ 14455131Storek (d) = (s) ^ (d); \ 14555131Storek pst \ 14655131Storek break; \ 14755131Storek case RAS_NOTAND: \ 14855131Storek pre \ 14955131Storek (d) = ~( (s) & (d) ); \ 15055131Storek pst \ 15155131Storek break; \ 15255131Storek case RAS_AND: \ 15355131Storek pre \ 15455131Storek (d) = (s) & (d); \ 15555131Storek pst \ 15655131Storek break; \ 15755131Storek case RAS_NOTXOR: \ 15855131Storek pre \ 15955131Storek (d) = ~( (s) ^ (d) ); \ 16055131Storek pst \ 16155131Storek break; \ 16255131Storek case RAS_NOTSRC_OR_DST: \ 16355131Storek pre \ 16455131Storek (d) = ~(s) | (d); \ 16555131Storek pst \ 16655131Storek break; \ 16755131Storek case RAS_SRC: \ 16855131Storek pre \ 16955131Storek (d) = (s); \ 17055131Storek pst \ 17155131Storek break; \ 17255131Storek case RAS_SRC_OR_NOTDST: \ 17355131Storek pre \ 17455131Storek (d) = (s) | ~(d); \ 17555131Storek pst \ 17655131Storek break; \ 17755131Storek case RAS_OR: \ 17855131Storek pre \ 17955131Storek (d) = (s) | (d); \ 18055131Storek pst \ 18155131Storek break; \ 18255131Storek default: \ 18355131Storek return -1; \ 18455131Storek } 18555131Storek 18655131Storek #define ROP_SRCDSTCOLOR(op,pre,s,d,c,pst) \ 18755131Storek switch ( op ) \ 18855131Storek { \ 18955131Storek case RAS_NOTOR: \ 19055131Storek pre \ 19155131Storek if ( s ) \ 19255131Storek (d) = ~( (c) | (d) ); \ 19355131Storek else \ 19455131Storek (d) = ~(d); \ 19555131Storek pst \ 19655131Storek break; \ 19755131Storek case RAS_NOTSRC_AND_DST: \ 19855131Storek pre \ 19955131Storek if ( s ) \ 20055131Storek (d) = ~(c) & (d); \ 20155131Storek pst \ 20255131Storek break; \ 20355131Storek case RAS_INVERTSRC: \ 20455131Storek pre \ 20555131Storek if ( s ) \ 20655131Storek (d) = ~(c); \ 20755131Storek else \ 20855131Storek (d) = ~0; \ 20955131Storek pst \ 21055131Storek break; \ 21155131Storek case RAS_SRC_AND_NOTDST: \ 21255131Storek pre \ 21355131Storek if ( s ) \ 21455131Storek (d) = (c) & ~(d); \ 21555131Storek else \ 21655131Storek (d) = 0; \ 21755131Storek pst \ 21855131Storek break; \ 21955131Storek case RAS_XOR: \ 22055131Storek pre \ 22155131Storek if ( s ) \ 22255131Storek (d) = (c) ^ (d); \ 22355131Storek pst \ 22455131Storek break; \ 22555131Storek case RAS_NOTAND: \ 22655131Storek pre \ 22755131Storek if ( s ) \ 22855131Storek (d) = ~( (c) & (d) ); \ 22955131Storek else \ 23055131Storek (d) = ~0; \ 23155131Storek pst \ 23255131Storek break; \ 23355131Storek case RAS_AND: \ 23455131Storek pre \ 23555131Storek if ( s ) \ 23655131Storek (d) = (c) & (d); \ 23755131Storek else \ 23855131Storek (d) = 0; \ 23955131Storek pst \ 24055131Storek break; \ 24155131Storek case RAS_NOTXOR: \ 24255131Storek pre \ 24355131Storek if ( s ) \ 24455131Storek (d) = ~( (c) ^ (d) ); \ 24555131Storek else \ 24655131Storek (d) = ~(d); \ 24755131Storek pst \ 24855131Storek break; \ 24955131Storek case RAS_NOTSRC_OR_DST: \ 25055131Storek pre \ 25155131Storek if ( s ) \ 25255131Storek (d) = ~(c) | (d); \ 25355131Storek else \ 25455131Storek (d) = ~0; \ 25555131Storek pst \ 25655131Storek break; \ 25755131Storek case RAS_SRC: \ 25855131Storek pre \ 25955131Storek if ( s ) \ 26055131Storek (d) = (c); \ 26155131Storek else \ 26255131Storek (d) = 0; \ 26355131Storek pst \ 26455131Storek break; \ 26555131Storek case RAS_SRC_OR_NOTDST: \ 26655131Storek pre \ 26755131Storek if ( s ) \ 26855131Storek (d) = (c) | ~(d); \ 26955131Storek else \ 27055131Storek (d) = ~(d); \ 27155131Storek pst \ 27255131Storek break; \ 27355131Storek case RAS_OR: \ 27455131Storek pre \ 27555131Storek if ( s ) \ 27655131Storek (d) = (c) | (d); \ 27755131Storek pst \ 27855131Storek break; \ 27955131Storek default: \ 28055131Storek return -1; \ 28155131Storek } 28255131Storek 28355131Storek #else /*PARTIAL_LOGICAL_OPS*/ 28455131Storek 28555131Storek #define ROP_DST(op,pre,d,pst) \ 28655131Storek switch ( op ) \ 28755131Storek { \ 28855131Storek case RAS_CLEAR: \ 28955131Storek pre \ 29055131Storek (d) = 0; \ 29155131Storek pst \ 29255131Storek break; \ 29355131Storek case RAS_INVERT: \ 29455131Storek pre \ 29555131Storek (d) = ~(d); \ 29655131Storek pst \ 29755131Storek break; \ 29855131Storek case RAS_SET: \ 29955131Storek pre \ 30055131Storek (d) = ~0; \ 30155131Storek pst \ 30255131Storek break; \ 30355131Storek default: \ 30455131Storek return -1; \ 30555131Storek } 30655131Storek 30755131Storek #define ROP_DSTCOLOR(op,pre,d,c,pst) \ 30855131Storek switch ( op ) \ 30955131Storek { \ 31055131Storek case RAS_CLEAR: \ 31155131Storek pre \ 31255131Storek (d) = 0; \ 31355131Storek pst \ 31455131Storek break; \ 31555131Storek case RAS_INVERT: \ 31655131Storek pre \ 31755131Storek (d) = ~(d); \ 31855131Storek pst \ 31955131Storek break; \ 32055131Storek case RAS_SET: \ 32155131Storek pre \ 32255131Storek (d) = (c); \ 32355131Storek pst \ 32455131Storek break; \ 32555131Storek default: \ 32655131Storek return -1; \ 32755131Storek } 32855131Storek 32955131Storek #define ROP_SRCDST(op,pre,s,d,pst) \ 33055131Storek switch ( op ) \ 33155131Storek { \ 33255131Storek case RAS_INVERTSRC: \ 33355131Storek pre \ 33455131Storek (d) = ~(s); \ 33555131Storek pst \ 33655131Storek break; \ 33755131Storek case RAS_XOR: \ 33855131Storek pre \ 33955131Storek (d) = (s) ^ (d); \ 34055131Storek pst \ 34155131Storek break; \ 34255131Storek case RAS_SRC: \ 34355131Storek pre \ 34455131Storek (d) = (s); \ 34555131Storek pst \ 34655131Storek break; \ 34755131Storek default: \ 34855131Storek return -1; \ 34955131Storek } 35055131Storek 35155131Storek #define ROP_SRCDSTCOLOR(op,pre,s,d,c,pst) \ 35255131Storek switch ( op ) \ 35355131Storek { \ 35455131Storek case RAS_INVERTSRC: \ 35555131Storek pre \ 35655131Storek if ( s ) \ 35755131Storek (d) = ~(c); \ 35855131Storek else \ 35955131Storek (d) = ~0; \ 36055131Storek pst \ 36155131Storek break; \ 36255131Storek case RAS_XOR: \ 36355131Storek pre \ 36455131Storek if ( s ) \ 36555131Storek (d) = (c) ^ (d); \ 36655131Storek pst \ 36755131Storek break; \ 36855131Storek case RAS_SRC: \ 36955131Storek pre \ 37055131Storek if ( s ) \ 37155131Storek (d) = (c); \ 37255131Storek else \ 37355131Storek (d) = 0; \ 37455131Storek pst \ 37555131Storek break; \ 37655131Storek default: \ 37755131Storek return -1; \ 37855131Storek } 37955131Storek 38055131Storek #endif /*PARTIAL_LOGICAL_OPS*/ 38155131Storek 38255131Storek 38355131Storek /* Variables. */ 38455131Storek 38555131Storek static int needsrc[16] = { 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0 }; 38655131Storek /* CLEAR INVERT DST SET */ 38755131Storek 38855131Storek #ifdef MSBIT_FIRST 38955131Storek 39055131Storek u_long raster_bitmask[32] = { 39155131Storek 0x80000000, 0x40000000, 0x20000000, 0x10000000, 39255131Storek 0x08000000, 0x04000000, 0x02000000, 0x01000000, 39355131Storek 0x00800000, 0x00400000, 0x00200000, 0x00100000, 39455131Storek 0x00080000, 0x00040000, 0x00020000, 0x00010000, 39555131Storek 0x00008000, 0x00004000, 0x00002000, 0x00001000, 39655131Storek 0x00000800, 0x00000400, 0x00000200, 0x00000100, 39755131Storek 0x00000080, 0x00000040, 0x00000020, 0x00000010, 39855131Storek 0x00000008, 0x00000004, 0x00000002, 0x00000001 }; 39955131Storek 40055131Storek #ifdef MSBYTE_FIRST 40155131Storek static u_long leftmask[32] = { 40255131Storek 0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 40355131Storek 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000, 40455131Storek 0xff000000, 0xff800000, 0xffc00000, 0xffe00000, 40555131Storek 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 40655131Storek 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000, 40755131Storek 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00, 40855131Storek 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 40955131Storek 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe }; 41055131Storek static u_long rightmask[32] = { 41155131Storek 0x00000000, 0x00000001, 0x00000003, 0x00000007, 41255131Storek 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, 41355131Storek 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, 41455131Storek 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 41555131Storek 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, 41655131Storek 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff, 41755131Storek 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, 41855131Storek 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff }; 41955131Storek #endif /*MSBYTE_FIRST*/ 42055131Storek 42155131Storek #else /*MSBIT_FIRST*/ 42255131Storek 42355131Storek u_long raster_bitmask[32] = { 42455131Storek 0x00000001, 0x00000002, 0x00000004, 0x00000008, 42555131Storek 0x00000010, 0x00000020, 0x00000040, 0x00000080, 42655131Storek 0x00000100, 0x00000200, 0x00000400, 0x00000800, 42755131Storek 0x00001000, 0x00002000, 0x00004000, 0x00008000, 42855131Storek 0x00010000, 0x00020000, 0x00040000, 0x00080000, 42955131Storek 0x00100000, 0x00200000, 0x00400000, 0x00800000, 43055131Storek 0x01000000, 0x02000000, 0x04000000, 0x08000000, 43155131Storek 0x10000000, 0x20000000, 0x40000000, 0x80000000 }; 43255131Storek 43355131Storek #ifndef MSBYTE_FIRST 43455131Storek static u_long leftmask[32] = { 43555131Storek 0x00000000, 0x00000001, 0x00000003, 0x00000007, 43655131Storek 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, 43755131Storek 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, 43855131Storek 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 43955131Storek 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, 44055131Storek 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff, 44155131Storek 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, 44255131Storek 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff }; 44355131Storek static u_long rightmask[32] = { 44455131Storek 0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 44555131Storek 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000, 44655131Storek 0xff000000, 0xff800000, 0xffc00000, 0xffe00000, 44755131Storek 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 44855131Storek 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000, 44955131Storek 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00, 45055131Storek 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 45155131Storek 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe }; 45255131Storek #endif /*not MSBYTE_FIRST*/ 45355131Storek 45455131Storek #endif /*MSBIT_FIRST*/ 45555131Storek 45655131Storek /* (The odd combinations MSBIT+~MSBYTE and ~MSBIT+MSBYTE could be added.) */ 45755131Storek 45855131Storek #ifdef MSBYTE_FIRST 45955131Storek static u_long bytemask[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff }; 46055131Storek #else /*MSBYTE_FIRST*/ 46155131Storek static u_long bytemask[4] = { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }; 46255131Storek #endif /*MSBYTE_FIRST*/ 46355131Storek 46455131Storek 46555131Storek /* Forward routines. */ 46655131Storek 46755131Storek static int raster_blit(); 46855131Storek 46955131Storek 47055131Storek /* Raster operations. */ 47155131Storek 47255131Storek /* Performs a bitblit. Returns 0 on success, -1 on failure. */ 47355131Storek int 47455131Storek raster_op( dst, dx, dy, w, h, rop, src, sx, sy ) 47555131Storek struct raster* dst; 47655131Storek int dx, dy, w, h, rop; 47755131Storek struct raster* src; 47855131Storek int sx, sy; 47955131Storek { 48055131Storek if ( dst == (struct raster*) 0 ) 48155131Storek return -1; /* no destination */ 48255131Storek 48355131Storek if ( needsrc[RAS_GETOP( rop )] ) 48455131Storek { 48555131Storek /* Two-operand blit. */ 48655131Storek if ( src == (struct raster*) 0 ) 48755131Storek return -1; /* no source */ 48855131Storek 48955131Storek /* Clip against source. */ 49055131Storek if ( sx < 0 ) 49155131Storek { 49255131Storek w += sx; 49355131Storek sx = 0; 49455131Storek } 49555131Storek if ( sy < 0 ) 49655131Storek { 49755131Storek h += sy; 49855131Storek sy = 0; 49955131Storek } 50055131Storek if ( sx + w > src->width ) 50155131Storek w = src->width - sx; 50255131Storek if ( sy + h > src->height ) 50355131Storek h = src->height - sy; 50455131Storek 50555131Storek /* Clip against dest. */ 50655131Storek if ( dx < 0 ) 50755131Storek { 50855131Storek w += dx; 50955131Storek sx -= dx; 51055131Storek dx = 0; 51155131Storek } 51255131Storek if ( dy < 0 ) 51355131Storek { 51455131Storek h += dy; 51555131Storek sy -= dy; 51655131Storek dy = 0; 51755131Storek } 51855131Storek if ( dx + w > dst->width ) 51955131Storek w = dst->width - dx; 52055131Storek if ( dy + h > dst->height ) 52155131Storek h = dst->height - dy; 52255131Storek 52355131Storek if ( w <= 0 || h <= 0 ) 52455131Storek return 0; /* nothing to do */ 52555131Storek 52655131Storek return raster_op_noclip( dst, dx, dy, w, h, rop, src, sx, sy ); 52755131Storek } 52855131Storek 52955131Storek /* No source necessary - one-operand blit. */ 53055131Storek if ( src != (struct raster*) 0 ) 53155131Storek return -1; /* unwanted source */ 53255131Storek 53355131Storek /* Clip against dest. */ 53455131Storek if ( dx < 0 ) 53555131Storek { 53655131Storek w += dx; 53755131Storek dx = 0; 53855131Storek } 53955131Storek if ( dy < 0 ) 54055131Storek { 54155131Storek h += dy; 54255131Storek dy = 0; 54355131Storek } 54455131Storek if ( dx + w > dst->width ) 54555131Storek w = dst->width - dx; 54655131Storek if ( dy + h > dst->height ) 54755131Storek h = dst->height - dy; 54855131Storek 54955131Storek if ( w <= 0 || h <= 0 ) 55055131Storek return 0; /* nothing to do */ 55155131Storek 55255131Storek return raster_op_nosrc_noclip( dst, dx, dy, w, h, rop ); 55355131Storek } 55455131Storek 55555131Storek /* Semi-public routine to do a bitblit without clipping. Returns 0 on 55655131Storek ** success, -1 on failure. 55755131Storek */ 55855131Storek int 55955131Storek raster_op_noclip( dst, dx, dy, w, h, rop, src, sx, sy ) 56055131Storek struct raster* dst; 56155131Storek int dx, dy, w, h, rop; 56255131Storek struct raster* src; 56355131Storek int sx, sy; 56455131Storek { 56555131Storek int op; 56655131Storek 56755131Storek op = RAS_GETOP( rop ); 56855131Storek 56955131Storek if ( src->depth == 1 ) 57055131Storek { 57155131Storek /* One-bit to ? blit. */ 57255131Storek if ( dst->depth == 1 ) 57355131Storek { 57455131Storek /* One to one blit. */ 57555131Storek u_long* srclin1; 57655131Storek u_long* dstlin1; 57755131Storek int srcleftignore, srcrightignore, srclongs; 57855131Storek int dstleftignore, dstrightignore, dstlongs; 57955131Storek 58055131Storek srclin1 = RAS_ADDR( src, sx, sy ); 58155131Storek dstlin1 = RAS_ADDR( dst, dx, dy ); 58255131Storek 58355131Storek #ifdef BCOPY_FASTER 58455131Storek /* Special-case full-width to full-width copies. */ 58555131Storek if ( op == RAS_SRC && src->width == w && dst->width == w && 58655131Storek src->linelongs == dst->linelongs && src->linelongs == w >> 5 ) 58755131Storek { 58855131Storek bcopy( 58955131Storek (char*) srclin1, (char*) dstlin1, 59055131Storek h * src->linelongs * sizeof(u_long) ); 59155131Storek return 0; 59255131Storek } 59355131Storek #endif /*BCOPY_FASTER*/ 59455131Storek 59555131Storek srcleftignore = ( sx & 31 ); 59655131Storek srclongs = ( srcleftignore + w + 31 ) >> 5; 59755131Storek srcrightignore = ( srclongs * 32 - w - srcleftignore ) & 31; 59855131Storek dstleftignore = ( dx & 31 ); 59955131Storek dstlongs = ( dstleftignore + w + 31 ) >> 5; 60055131Storek dstrightignore = ( dstlongs * 32 - w - dstleftignore ) & 31; 60155131Storek 60255131Storek return raster_blit( 60355131Storek src, srclin1, srcleftignore, srcrightignore, srclongs, 60455131Storek dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op ); 60555131Storek } 60655131Storek 60755131Storek else 60855131Storek { 60955131Storek /* One to eight, using the color in the rop. This could 61055131Storek ** probably be sped up by handling each four-bit source nybble 61155131Storek ** as a group, indexing into a 16-element runtime-constructed 61255131Storek ** table of longwords. 61355131Storek */ 61455131Storek u_long* srclin1; 61555131Storek u_long* dstlin1; 61655131Storek u_long* srclin2; 61755131Storek u_long* srclin; 61855131Storek u_long* dstlin; 61955131Storek register u_long* srclong; 62055131Storek register u_long* dstlong; 62155131Storek register u_long color, dl; 62255131Storek register int srcbit, dstbyte, i; 62355131Storek 62455131Storek color = RAS_GETCOLOR( rop ); 62555131Storek if ( color == 0 ) 62655131Storek color = 255; 62755131Storek 62855131Storek /* Make 32 bits of color so we can do the ROP without shifting. */ 62955131Storek color |= ( color << 24 ) | ( color << 16 ) | ( color << 8 ); 63055131Storek 63155131Storek /* Don't have to worry about overlapping blits here. */ 63255131Storek srclin1 = RAS_ADDR( src, sx, sy ); 63355131Storek srclin2 = srclin1 + h * src->linelongs; 63455131Storek dstlin1 = RAS_ADDR( dst, dx, dy ); 63555131Storek srclin = srclin1; 63655131Storek dstlin = dstlin1; 63755131Storek while ( srclin != srclin2 ) 63855131Storek { 63955131Storek srclong = srclin; 64055131Storek srcbit = sx & 31; 64155131Storek dstlong = dstlin; 64255131Storek dstbyte = dx & 3; 64355131Storek i = w; 64455131Storek 64555131Storek /* WARNING: this code is KNOWN TO FAIL on Sun 3's / CG2's. */ 64655131Storek ROP_SRCDSTCOLOR( 64755131Storek /*op*/ op, 64855131Storek /*pre*/ while ( i > 0 ) 64955131Storek { 65055131Storek dl = *dstlong;, 65155131Storek /*s*/ *srclong & raster_bitmask[srcbit], 65255131Storek /*d*/ dl, 65355131Storek /*c*/ color, 65455131Storek /*pst*/ *dstlong = ( *dstlong & ~bytemask[dstbyte] ) | 65555131Storek ( dl & bytemask[dstbyte] ); 65655131Storek if ( srcbit == 31 ) 65755131Storek { 65855131Storek srcbit = 0; 65955131Storek ++srclong; 66055131Storek } 66155131Storek else 66255131Storek ++srcbit; 66355131Storek if ( dstbyte == 3 ) 66455131Storek { 66555131Storek dstbyte = 0; 66655131Storek ++dstlong; 66755131Storek } 66855131Storek else 66955131Storek ++dstbyte; 67055131Storek --i; 67155131Storek } ) 67255131Storek 67355131Storek srclin += src->linelongs; 67455131Storek dstlin += dst->linelongs; 67555131Storek } 67655131Storek } 67755131Storek } 67855131Storek 67955131Storek else 68055131Storek { 68155131Storek /* Eight to eight blit. */ 68255131Storek u_long* srclin1; 68355131Storek u_long* dstlin1; 68455131Storek int srcleftignore, srcrightignore, srclongs; 68555131Storek int dstleftignore, dstrightignore, dstlongs; 68655131Storek 68755131Storek if ( dst->depth != 8 ) 68855131Storek return -1; /* depth mismatch */ 68955131Storek 69055131Storek srclin1 = RAS_ADDR( src, sx, sy ); 69155131Storek dstlin1 = RAS_ADDR( dst, dx, dy ); 69255131Storek 69355131Storek #ifdef BCOPY_FASTER 69455131Storek /* Special-case full-width to full-width copies. */ 69555131Storek if ( op == RAS_SRC && src->width == w && dst->width == w && 69655131Storek src->linelongs == dst->linelongs && src->linelongs == w >> 2 ) 69755131Storek { 69855131Storek bcopy( (char*) srclin1, (char*) dstlin1, 69955131Storek h * src->linelongs * sizeof(u_long) ); 70055131Storek return 0; 70155131Storek } 70255131Storek #endif /*BCOPY_FASTER*/ 70355131Storek 70455131Storek srcleftignore = ( sx & 3 ) * 8; 70555131Storek srclongs = ( srcleftignore + w * 8 + 31 ) >> 5; 70655131Storek srcrightignore = ( srclongs * 32 - w * 8 - srcleftignore ) & 31; 70755131Storek dstleftignore = ( dx & 3 ) * 8; 70855131Storek dstlongs = ( dstleftignore + w * 8 + 31 ) >> 5; 70955131Storek dstrightignore = ( dstlongs * 32 - w * 8 - dstleftignore ) & 31; 71055131Storek 71155131Storek return raster_blit( 71255131Storek src, srclin1, srcleftignore, srcrightignore, srclongs, 71355131Storek dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op ); 71455131Storek } 71555131Storek 71655131Storek return 0; 71755131Storek } 71855131Storek 71955131Storek /* Semi-public routine to do a no-src bitblit without clipping. Returns 0 72055131Storek ** on success, -1 on failure. 72155131Storek */ 72255131Storek int 72355131Storek raster_op_nosrc_noclip( dst, dx, dy, w, h, rop ) 72455131Storek struct raster* dst; 72555131Storek int dx, dy, w, h, rop; 72655131Storek { 72755131Storek int op; 72855131Storek 72955131Storek op = RAS_GETOP( rop ); 73055131Storek 73155131Storek if ( dst->depth == 1 ) 73255131Storek { 73355131Storek /* One-bit no-src blit. */ 73455131Storek u_long* dstlin1; 73555131Storek u_long* dstlin2; 73655131Storek u_long* dstlin; 73755131Storek int dstleftignore, dstrightignore, dstlongs; 73855131Storek u_long dl, lm, nlm, rm, nrm; 73955131Storek register u_long* dstlong2; 74055131Storek register u_long* dstlong; 74155131Storek 74255131Storek dstlin1 = RAS_ADDR( dst, dx, dy ); 74355131Storek 74455131Storek #ifdef BCOPY_FASTER 74555131Storek /* Special-case full-width clears. */ 74655131Storek if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 5 ) 74755131Storek { 74855131Storek bzero( (char*) dstlin1, h * dst->linelongs * sizeof(u_long) ); 74955131Storek return 0; 75055131Storek } 75155131Storek #endif /*BCOPY_FASTER*/ 75255131Storek 75355131Storek dstleftignore = ( dx & 31 ); 75455131Storek dstlongs = ( dstleftignore + w + 31 ) >> 5; 75555131Storek dstrightignore = ( dstlongs * 32 - w - dstleftignore ) & 31; 75655131Storek 75755131Storek dstlin2 = dstlin1 + h * dst->linelongs; 75855131Storek dstlin = dstlin1; 75955131Storek 76055131Storek if ( dstlongs == 1 ) 76155131Storek { 76255131Storek /* It fits into a single longword. */ 76355131Storek lm = leftmask[dstleftignore] | rightmask[dstrightignore]; 76455131Storek nlm = ~lm; 76555131Storek while ( dstlin != dstlin2 ) 76655131Storek { 76755131Storek ROP_DST( 76855131Storek /*op*/ op, 76955131Storek /*pre*/ dl = *dstlin;, 77055131Storek /*d*/ dl, 77155131Storek /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); ) 77255131Storek 77355131Storek dstlin += dst->linelongs; 77455131Storek } 77555131Storek } 77655131Storek else 77755131Storek { 77855131Storek lm = leftmask[dstleftignore]; 77955131Storek rm = rightmask[dstrightignore]; 78055131Storek nrm = ~rm; 78155131Storek nlm = ~lm; 78255131Storek 78355131Storek while ( dstlin != dstlin2 ) 78455131Storek { 78555131Storek dstlong = dstlin; 78655131Storek dstlong2 = dstlong + dstlongs; 78755131Storek if ( dstrightignore != 0 ) 78855131Storek --dstlong2; 78955131Storek 79055131Storek /* Leading edge. */ 79155131Storek if ( dstleftignore != 0 ) 79255131Storek { 79355131Storek ROP_DST( 79455131Storek /*op*/ op, 79555131Storek /*pre*/ dl = *dstlong;, 79655131Storek /*d*/ dl, 79755131Storek /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); ) 79855131Storek ++dstlong; 79955131Storek } 80055131Storek 80155131Storek /* Main rop. */ 80255131Storek ROP_DST( 80355131Storek /*op*/ op, 80455131Storek /*pre*/ while ( dstlong != dstlong2 ) 80555131Storek {, 80655131Storek /*d*/ *dstlong, 80755131Storek /*pst*/ ++dstlong; 80855131Storek } ) 80955131Storek 81055131Storek /* Trailing edge. */ 81155131Storek if ( dstrightignore != 0 ) 81255131Storek { 81355131Storek ROP_DST( 81455131Storek /*op*/ op, 81555131Storek /*pre*/ dl = *dstlong;, 81655131Storek /*d*/ dl, 81755131Storek /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); ) 81855131Storek } 81955131Storek 82055131Storek dstlin += dst->linelongs; 82155131Storek } 82255131Storek } 82355131Storek } 82455131Storek 82555131Storek else 82655131Storek { 82755131Storek /* Eight-bit no-src blit. */ 82855131Storek register u_long color; 82955131Storek u_long* dstlin1; 83055131Storek u_long* dstlin2; 83155131Storek u_long* dstlin; 83255131Storek int dstleftignore, dstrightignore, dstlongs; 83355131Storek u_long dl, lm, nlm, rm, nrm; 83455131Storek register u_long* dstlong2; 83555131Storek register u_long* dstlong; 83655131Storek 83755131Storek dstlin1 = RAS_ADDR( dst, dx, dy ); 83855131Storek 83955131Storek #ifdef BCOPY_FASTER 84055131Storek /* Special-case full-width clears. */ 84155131Storek if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 2 ) 84255131Storek { 84355131Storek bzero( (char*) dstlin1, h * dst->linelongs * sizeof(u_long) ); 84455131Storek return 0; 84555131Storek } 84655131Storek #endif /*BCOPY_FASTER*/ 84755131Storek 84855131Storek color = RAS_GETCOLOR( rop ); 84955131Storek if ( color == 0 ) 85055131Storek color = 255; 85155131Storek 85255131Storek /* Make 32 bits of color so we can do the ROP without shifting. */ 85355131Storek color |= ( color << 24 ) | ( color << 16 ) | ( color << 8 ); 85455131Storek 85555131Storek dstleftignore = ( dx & 3 ) * 8; 85655131Storek dstlongs = ( dstleftignore + w * 8 + 31 ) >> 5; 85755131Storek dstrightignore = ( dstlongs * 32 - w * 8 - dstleftignore ) & 31; 85855131Storek 85955131Storek dstlin2 = dstlin1 + h * dst->linelongs; 86055131Storek dstlin = dstlin1; 86155131Storek 86255131Storek if ( dstlongs == 1 ) 86355131Storek { 86455131Storek /* It fits into a single longword. */ 86555131Storek lm = leftmask[dstleftignore] | rightmask[dstrightignore]; 86655131Storek nlm = ~lm; 86755131Storek while ( dstlin != dstlin2 ) 86855131Storek { 86955131Storek ROP_DSTCOLOR( 87055131Storek /*op*/ op, 87155131Storek /*pre*/ dl = *dstlin;, 87255131Storek /*d*/ dl, 87355131Storek /*c*/ color, 87455131Storek /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); ) 87555131Storek 87655131Storek dstlin += dst->linelongs; 87755131Storek } 87855131Storek } 87955131Storek else 88055131Storek { 88155131Storek lm = leftmask[dstleftignore]; 88255131Storek rm = rightmask[dstrightignore]; 88355131Storek nrm = ~rm; 88455131Storek nlm = ~lm; 88555131Storek while ( dstlin != dstlin2 ) 88655131Storek { 88755131Storek dstlong = dstlin; 88855131Storek dstlong2 = dstlong + dstlongs; 88955131Storek if ( dstrightignore != 0 ) 89055131Storek --dstlong2; 89155131Storek 89255131Storek /* Leading edge. */ 89355131Storek if ( dstleftignore != 0 ) 89455131Storek { 89555131Storek ROP_DSTCOLOR( 89655131Storek /*op*/ op, 89755131Storek /*pre*/ dl = *dstlong;, 89855131Storek /*d*/ dl, 89955131Storek /*c*/ color, 90055131Storek /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); ) 90155131Storek ++dstlong; 90255131Storek } 90355131Storek 90455131Storek /* Main rop. */ 90555131Storek ROP_DSTCOLOR( 90655131Storek /*op*/ op, 90755131Storek /*pre*/ while ( dstlong != dstlong2 ) 90855131Storek {, 90955131Storek /*d*/ *dstlong, 91055131Storek /*c*/ color, 91155131Storek /*pst*/ ++dstlong; 91255131Storek } ) 91355131Storek 91455131Storek /* Trailing edge. */ 91555131Storek if ( dstrightignore != 0 ) 91655131Storek { 91755131Storek ROP_DSTCOLOR( 91855131Storek /*op*/ op, 91955131Storek /*pre*/ dl = *dstlong;, 92055131Storek /*d*/ dl, 92155131Storek /*c*/ color, 92255131Storek /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); ) 92355131Storek } 92455131Storek 92555131Storek dstlin += dst->linelongs; 92655131Storek } 92755131Storek } 92855131Storek } 92955131Storek 93055131Storek return 0; 93155131Storek } 93255131Storek 93355131Storek /* This is a general bitblit routine, handling overlapping source and 93455131Storek ** destination. It's used for both the 1-to-1 and 8-to-8 cases. 93555131Storek */ 93655131Storek static int 93755131Storek raster_blit( src, srclin1, srcleftignore, srcrightignore, srclongs, dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op ) 93855131Storek struct raster* src; 93955131Storek u_long* srclin1; 94055131Storek int srcleftignore, srcrightignore, srclongs; 94155131Storek struct raster* dst; 94255131Storek u_long* dstlin1; 94355131Storek int dstleftignore, dstrightignore, dstlongs; 94455131Storek int h, op; 94555131Storek { 94655131Storek u_long* srclin2; 94755131Storek u_long* dstlin2; 94855131Storek int srclininc, dstlininc; 94955131Storek u_long* srclin; 95055131Storek u_long* dstlin; 95155131Storek register int prevleftshift, currrightshift; 95255131Storek int longinc; 95355131Storek register u_long* srclong; 95455131Storek register u_long* dstlong; 95555131Storek register u_long* dstlong2; 95655131Storek register u_long dl, lm, nlm, rm, nrm; 95755131Storek 95855131Storek prevleftshift = ( srcleftignore - dstleftignore ) & 31; 95955131Storek 96055131Storek srclin2 = srclin1 + h * src->linelongs; 96155131Storek dstlin2 = dstlin1 + h * dst->linelongs; 96255131Storek srclininc = src->linelongs; 96355131Storek dstlininc = dst->linelongs; 96455131Storek longinc = 1; 96555131Storek 96655131Storek /* Check for overlaps. */ 96755131Storek if ( ( dstlin1 >= srclin1 && dstlin1 < srclin1 + srclongs ) || 96855131Storek ( srclin1 >= dstlin1 && srclin1 < dstlin1 + dstlongs ) ) 96955131Storek { 97055131Storek /* Horizontal overlap. Should we reverse? */ 97155131Storek if ( srclin1 < dstlin1 ) 97255131Storek { 97355131Storek longinc = -1; 97455131Storek srclin1 += srclongs - 1; 97555131Storek srclin2 += srclongs - 1; 97655131Storek dstlin1 += dstlongs - 1; 97755131Storek } 97855131Storek } 97955131Storek else if ( ( dstlin1 >= srclin1 && dstlin1 < srclin2 ) || 98055131Storek ( srclin1 >= dstlin1 && srclin1 < dstlin2 ) ) 98155131Storek { 98255131Storek /* Vertical overlap. Should we reverse? */ 98355131Storek if ( srclin1 < dstlin1 ) 98455131Storek { 98555131Storek srclin2 = srclin1 - srclininc; 98655131Storek srclin1 += ( h - 1 ) * srclininc; 98755131Storek dstlin1 += ( h - 1 ) * dstlininc; 98855131Storek srclininc = -srclininc; 98955131Storek dstlininc = -dstlininc; 99055131Storek } 99155131Storek } 99255131Storek srclin = srclin1; 99355131Storek dstlin = dstlin1; 99455131Storek 99555131Storek if ( prevleftshift == 0 ) 99655131Storek { 99755131Storek /* The bits line up, no shifting necessary. */ 99855131Storek if ( dstlongs == 1 ) 99955131Storek { 100055131Storek /* It all fits into a single longword. */ 100155131Storek lm = leftmask[dstleftignore] | rightmask[dstrightignore]; 100255131Storek nlm = ~lm; 100355131Storek while ( srclin != srclin2 ) 100455131Storek { 100555131Storek ROP_SRCDST( 100655131Storek /*op*/ op, 100755131Storek /*pre*/ dl = *dstlin;, 100855131Storek /*s*/ *srclin, 100955131Storek /*d*/ dl, 101055131Storek /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); ) 101155131Storek 101255131Storek srclin += srclininc; 101355131Storek dstlin += dstlininc; 101455131Storek } 101555131Storek } 101655131Storek else 101755131Storek { 101855131Storek /* Multiple longwords. */ 101955131Storek lm = leftmask[dstleftignore]; 102055131Storek rm = rightmask[dstrightignore]; 102155131Storek nrm = ~rm; 102255131Storek nlm = ~lm; 102355131Storek if ( longinc == 1 ) 102455131Storek { 102555131Storek /* Left to right. */ 102655131Storek while ( srclin != srclin2 ) 102755131Storek { 102855131Storek srclong = srclin; 102955131Storek dstlong = dstlin; 103055131Storek dstlong2 = dstlong + dstlongs; 103155131Storek if ( dstrightignore != 0 ) 103255131Storek --dstlong2; 103355131Storek 103455131Storek /* Leading edge. */ 103555131Storek if ( dstleftignore != 0 ) 103655131Storek { 103755131Storek ROP_SRCDST( 103855131Storek /*op*/ op, 103955131Storek /*pre*/ dl = *dstlong;, 104055131Storek /*s*/ *srclong, 104155131Storek /*d*/ dl, 104255131Storek /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); ) 104355131Storek ++srclong; 104455131Storek ++dstlong; 104555131Storek } 104655131Storek 104755131Storek /* Main rop. */ 104855131Storek ROP_SRCDST( 104955131Storek /*op*/ op, 105055131Storek /*pre*/ while ( dstlong != dstlong2 ) 105155131Storek {, 105255131Storek /*s*/ *srclong, 105355131Storek /*d*/ *dstlong, 105455131Storek /*pst*/ ++srclong; 105555131Storek ++dstlong; 105655131Storek } ) 105755131Storek 105855131Storek /* Trailing edge. */ 105955131Storek if ( dstrightignore != 0 ) 106055131Storek { 106155131Storek ROP_SRCDST( 106255131Storek /*op*/ op, 106355131Storek /*pre*/ dl = *dstlong;, 106455131Storek /*s*/ *srclong, 106555131Storek /*d*/ dl, 106655131Storek /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); ) 106755131Storek } 106855131Storek 106955131Storek srclin += srclininc; 107055131Storek dstlin += dstlininc; 107155131Storek } 107255131Storek } 107355131Storek else 107455131Storek { 107555131Storek /* Right to left. */ 107655131Storek while ( srclin != srclin2 ) 107755131Storek { 107855131Storek srclong = srclin; 107955131Storek dstlong = dstlin; 108055131Storek dstlong2 = dstlong - dstlongs; 108155131Storek if ( dstleftignore != 0 ) 108255131Storek ++dstlong2; 108355131Storek 108455131Storek /* Leading edge. */ 108555131Storek if ( dstrightignore != 0 ) 108655131Storek { 108755131Storek ROP_SRCDST( 108855131Storek /*op*/ op, 108955131Storek /*pre*/ dl = *dstlong;, 109055131Storek /*s*/ *srclong, 109155131Storek /*d*/ dl, 109255131Storek /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); ) 109355131Storek --srclong; 109455131Storek --dstlong; 109555131Storek } 109655131Storek 109755131Storek /* Main rop. */ 109855131Storek ROP_SRCDST( 109955131Storek /*op*/ op, 110055131Storek /*pre*/ while ( dstlong != dstlong2 ) 110155131Storek {, 110255131Storek /*s*/ *srclong, 110355131Storek /*d*/ *dstlong, 110455131Storek /*pst*/ --srclong; 110555131Storek --dstlong; 110655131Storek } ) 110755131Storek 110855131Storek /* Trailing edge. */ 110955131Storek if ( dstleftignore != 0 ) 111055131Storek { 111155131Storek ROP_SRCDST( 111255131Storek /*op*/ op, 111355131Storek /*pre*/ dl = *dstlong;, 111455131Storek /*s*/ *srclong, 111555131Storek /*d*/ dl, 111655131Storek /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); ) 111755131Storek } 111855131Storek 111955131Storek srclin += srclininc; 112055131Storek dstlin += dstlininc; 112155131Storek } 112255131Storek } 112355131Storek } 112455131Storek } 112555131Storek 112655131Storek else 112755131Storek { 112855131Storek /* General case, with shifting and everything. */ 112955131Storek register u_long sl, prevsl; 113055131Storek 113155131Storek currrightshift = 32 - prevleftshift; 113255131Storek if ( srclongs == 1 && dstlongs == 1 ) 113355131Storek { 113455131Storek /* It fits into a single longword, with a shift. */ 113555131Storek lm = leftmask[dstleftignore] | rightmask[dstrightignore]; 113655131Storek nlm = ~lm; 113755131Storek if ( srcleftignore > dstleftignore ) 113855131Storek { 113955131Storek while ( srclin != srclin2 ) 114055131Storek { 114155131Storek ROP_SRCDST( 114255131Storek /*op*/ op, 114355131Storek /*pre*/ dl = *dstlin;, 114455131Storek /*s*/ *srclin << prevleftshift, 114555131Storek /*d*/ dl, 114655131Storek /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); ) 114755131Storek 114855131Storek srclin += srclininc; 114955131Storek dstlin += dstlininc; 115055131Storek } 115155131Storek } 115255131Storek else 115355131Storek { 115455131Storek while ( srclin != srclin2 ) 115555131Storek { 115655131Storek ROP_SRCDST( 115755131Storek /*op*/ op, 115855131Storek /*pre*/ dl = *dstlin;, 115955131Storek /*s*/ *srclin >> currrightshift, 116055131Storek /*d*/ dl, 116155131Storek /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); ) 116255131Storek 116355131Storek srclin += srclininc; 116455131Storek dstlin += dstlininc; 116555131Storek } 116655131Storek } 116755131Storek } 116855131Storek else 116955131Storek { 117055131Storek /* Multiple longwords. */ 117155131Storek lm = leftmask[dstleftignore]; 117255131Storek rm = rightmask[dstrightignore]; 117355131Storek nrm = ~rm; 117455131Storek nlm = ~lm; 117555131Storek if ( longinc == 1 ) 117655131Storek { 117755131Storek /* Left to right. */ 117855131Storek while ( srclin != srclin2 ) 117955131Storek { 118055131Storek srclong = srclin; 118155131Storek dstlong = dstlin; 118255131Storek dstlong2 = dstlong + dstlongs; 118355131Storek if ( srcleftignore > dstleftignore ) 118455131Storek prevsl = *srclong++ << prevleftshift; 118555131Storek else 118655131Storek prevsl = 0; 118755131Storek if ( dstrightignore != 0 ) 118855131Storek --dstlong2; 118955131Storek 119055131Storek /* Leading edge. */ 119155131Storek if ( dstleftignore != 0 ) 119255131Storek { 119355131Storek ROP_SRCDST( 119455131Storek /*op*/ op, 119555131Storek /*pre*/ sl = *srclong; 119655131Storek dl = *dstlong;, 119755131Storek /*s*/ prevsl | ( sl >> currrightshift ), 119855131Storek /*d*/ dl, 119955131Storek /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); ) 120055131Storek prevsl = sl << prevleftshift; 120155131Storek ++srclong; 120255131Storek ++dstlong; 120355131Storek } 120455131Storek 120555131Storek /* Main rop. */ 120655131Storek ROP_SRCDST( 120755131Storek /*op*/ op, 120855131Storek /*pre*/ while ( dstlong != dstlong2 ) 120955131Storek { 121055131Storek sl = *srclong;, 121155131Storek /*s*/ prevsl | ( sl >> currrightshift ), 121255131Storek /*d*/ *dstlong, 121355131Storek /*pst*/ prevsl = sl << prevleftshift; 121455131Storek ++srclong; 121555131Storek ++dstlong; 121655131Storek } ) 121755131Storek 121855131Storek /* Trailing edge. */ 121955131Storek if ( dstrightignore != 0 ) 122055131Storek { 122155131Storek ROP_SRCDST( 122255131Storek /*op*/ op, 122355131Storek /*pre*/ dl = *dstlong;, 122455131Storek /*s*/ prevsl | ( *srclong >> currrightshift ), 122555131Storek /*d*/ dl, 122655131Storek /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); ) 122755131Storek } 122855131Storek 122955131Storek srclin += srclininc; 123055131Storek dstlin += dstlininc; 123155131Storek } 123255131Storek } 123355131Storek else 123455131Storek { 123555131Storek /* Right to left. */ 123655131Storek while ( srclin != srclin2 ) 123755131Storek { 123855131Storek srclong = srclin; 123955131Storek dstlong = dstlin; 124055131Storek dstlong2 = dstlong - dstlongs; 124155131Storek if ( srcrightignore > dstrightignore ) 124255131Storek prevsl = *srclong-- >> currrightshift; 124355131Storek else 124455131Storek prevsl = 0; 124555131Storek if ( dstleftignore != 0 ) 124655131Storek ++dstlong2; 124755131Storek 124855131Storek /* Leading edge. */ 124955131Storek if ( dstrightignore != 0 ) 125055131Storek { 125155131Storek ROP_SRCDST( 125255131Storek /*op*/ op, 125355131Storek /*pre*/ sl = *srclong; 125455131Storek dl = *dstlong;, 125555131Storek /*s*/ prevsl | ( sl << prevleftshift ), 125655131Storek /*d*/ dl, 125755131Storek /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); ) 125855131Storek prevsl = sl >> currrightshift; 125955131Storek --srclong; 126055131Storek --dstlong; 126155131Storek } 126255131Storek 126355131Storek /* Main rop. */ 126455131Storek ROP_SRCDST( 126555131Storek /*op*/ op, 126655131Storek /*pre*/ while ( dstlong != dstlong2 ) 126755131Storek { 126855131Storek sl = *srclong;, 126955131Storek /*s*/ prevsl | ( sl << prevleftshift ), 127055131Storek /*d*/ *dstlong, 127155131Storek /*pst*/ prevsl = sl >> currrightshift; 127255131Storek --srclong; 127355131Storek --dstlong; 127455131Storek } ) 127555131Storek 127655131Storek /* Trailing edge. */ 127755131Storek if ( dstleftignore != 0 ) 127855131Storek { 127955131Storek ROP_SRCDST( 128055131Storek /*op*/ op, 128155131Storek /*pre*/ dl = *dstlong;, 128255131Storek /*s*/ prevsl | ( *srclong << prevleftshift ), 128355131Storek /*d*/ dl, 128455131Storek /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); ) 128555131Storek } 128655131Storek 128755131Storek srclin += srclininc; 128855131Storek dstlin += dstlininc; 128955131Storek } 129055131Storek } 129155131Storek } 129255131Storek } 129355131Storek 129455131Storek return 0; 129555131Storek } 1296