155131Storek /*-
2*63321Sbostic * Copyright (c) 1991, 1993
3*63321Sbostic * The Regents of the University of California. 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*63321Sbostic * @(#)raster_op.c 8.1 (Berkeley) 06/11/93
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>
3456539Sbostic #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
raster_op(dst,dx,dy,w,h,rop,src,sx,sy)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
raster_op_noclip(dst,dx,dy,w,h,rop,src,sx,sy)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
raster_op_nosrc_noclip(dst,dx,dy,w,h,rop)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
raster_blit(src,srclin1,srcleftignore,srcrightignore,srclongs,dst,dstlin1,dstleftignore,dstrightignore,dstlongs,h,op)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