1*55131Storek /*- 2*55131Storek * Copyright (c) 1991 The Regents of the University of California. 3*55131Storek * All rights reserved. 4*55131Storek * 5*55131Storek * This code is derived from software contributed to the Computer Systems 6*55131Storek * Engineering Group at Lawrence Berkeley Laboratory and to the University 7*55131Storek * of California at Berkeley by Jef Poskanzer. 8*55131Storek * 9*55131Storek * %sccs.include.redist.c% 10*55131Storek * 11*55131Storek * @(#)raster_op.c 7.1 (Berkeley) 07/13/92 12*55131Storek * 13*55131Storek * from: $Header: raster_op.c,v 1.22 92/06/17 08:14:44 torek Exp $ 14*55131Storek */ 15*55131Storek 16*55131Storek /* 17*55131Storek * Bitblit routine for raster library. 18*55131Storek * 19*55131Storek * This raster-op is machined to exacting tolerances by skilled native 20*55131Storek * craftsmen with pride in their work. 21*55131Storek * 22*55131Storek * The various cases are broken down like this: 23*55131Storek * 24*55131Storek * src required 25*55131Storek * 1-bit to 1-bit 26*55131Storek * 1-bit to 8-bits 27*55131Storek * 8-bits to 8-bits 28*55131Storek * no src required 29*55131Storek * 1-bit no-src 30*55131Storek * 8-bits no-src 31*55131Storek */ 32*55131Storek 33*55131Storek #ifdef KERNEL 34*55131Storek #include "sys/types.h" 35*55131Storek #else 36*55131Storek #include <sys/types.h> 37*55131Storek #endif 38*55131Storek #include "raster.h" 39*55131Storek 40*55131Storek /* CONFIGURE: To save on executable size, you can configure out the seldom-used 41*55131Storek ** logical operations. With this variable set, the only operations implemented 42*55131Storek ** are: RAS_SRC, RAS_CLEAR, RAS_SET, RAS_INVERT, RAS_XOR, RAS_INVERTSRC. 43*55131Storek */ 44*55131Storek #ifdef KERNEL 45*55131Storek #define PARTIAL_LOGICAL_OPS 46*55131Storek #endif 47*55131Storek 48*55131Storek /* CONFIGURE: bcopy() is supposed to be the ultimately fastest way to move 49*55131Storek ** bytes, overlapping or not, ignoring the startup cost. Unfortunately 50*55131Storek ** this is not true on some systems. For example, on a Sun 3 running 51*55131Storek ** SunOS 3.5, bcopy() is about five times slower than a simple for loop 52*55131Storek ** on overlapping copies. And on a 4.1.1 SPARC, bcopy() is about 2/3rds 53*55131Storek ** as fast on backwards overlaps. So, only define this if your bcopy is ok. 54*55131Storek */ 55*55131Storek #undef BCOPY_FASTER 56*55131Storek 57*55131Storek /* End of configurable definitions. */ 58*55131Storek 59*55131Storek 60*55131Storek /* Definitions. */ 61*55131Storek 62*55131Storek /* Raster-op macros. These encapsulate the switch statements and so make 63*55131Storek ** the source code 16 times smaller. The pre and pst args are code 64*55131Storek ** fragments to put before and after the assignment in each case. They 65*55131Storek ** can be the beginning and end of a loop. If the pst fragment includes a 66*55131Storek ** masked assignment, for example to handle the left or right edge cases, 67*55131Storek ** a good optimizing compiler will simplify the boolean expressions very 68*55131Storek ** nicely - both cc and gcc on the SPARC will do this. 69*55131Storek */ 70*55131Storek 71*55131Storek #ifndef PARTIAL_LOGICAL_OPS 72*55131Storek 73*55131Storek #define ROP_DST(op,pre,d,pst) \ 74*55131Storek switch ( op ) \ 75*55131Storek { \ 76*55131Storek case RAS_CLEAR: \ 77*55131Storek pre \ 78*55131Storek (d) = 0; \ 79*55131Storek pst \ 80*55131Storek break; \ 81*55131Storek case RAS_INVERT: \ 82*55131Storek pre \ 83*55131Storek (d) = ~(d); \ 84*55131Storek pst \ 85*55131Storek break; \ 86*55131Storek case RAS_DST: \ 87*55131Storek /* noop */ \ 88*55131Storek break; \ 89*55131Storek case RAS_SET: \ 90*55131Storek pre \ 91*55131Storek (d) = ~0; \ 92*55131Storek pst \ 93*55131Storek break; \ 94*55131Storek default: \ 95*55131Storek return -1; \ 96*55131Storek } 97*55131Storek 98*55131Storek #define ROP_DSTCOLOR(op,pre,d,c,pst) \ 99*55131Storek switch ( op ) \ 100*55131Storek { \ 101*55131Storek case RAS_CLEAR: \ 102*55131Storek pre \ 103*55131Storek (d) = 0; \ 104*55131Storek pst \ 105*55131Storek break; \ 106*55131Storek case RAS_INVERT: \ 107*55131Storek pre \ 108*55131Storek (d) = ~(d); \ 109*55131Storek pst \ 110*55131Storek break; \ 111*55131Storek case RAS_DST: \ 112*55131Storek /* noop */ \ 113*55131Storek break; \ 114*55131Storek case RAS_SET: \ 115*55131Storek pre \ 116*55131Storek (d) = (c); \ 117*55131Storek pst \ 118*55131Storek break; \ 119*55131Storek default: \ 120*55131Storek return -1; \ 121*55131Storek } 122*55131Storek 123*55131Storek #define ROP_SRCDST(op,pre,s,d,pst) \ 124*55131Storek switch ( op ) \ 125*55131Storek { \ 126*55131Storek case RAS_NOTOR: \ 127*55131Storek pre \ 128*55131Storek (d) = ~( (s) | (d) ); \ 129*55131Storek pst \ 130*55131Storek break; \ 131*55131Storek case RAS_NOTSRC_AND_DST: \ 132*55131Storek pre \ 133*55131Storek (d) = ~(s) & (d); \ 134*55131Storek pst \ 135*55131Storek break; \ 136*55131Storek case RAS_INVERTSRC: \ 137*55131Storek pre \ 138*55131Storek (d) = ~(s); \ 139*55131Storek pst \ 140*55131Storek break; \ 141*55131Storek case RAS_SRC_AND_NOTDST: \ 142*55131Storek pre \ 143*55131Storek (d) = (s) & ~(d); \ 144*55131Storek pst \ 145*55131Storek break; \ 146*55131Storek case RAS_XOR: \ 147*55131Storek pre \ 148*55131Storek (d) = (s) ^ (d); \ 149*55131Storek pst \ 150*55131Storek break; \ 151*55131Storek case RAS_NOTAND: \ 152*55131Storek pre \ 153*55131Storek (d) = ~( (s) & (d) ); \ 154*55131Storek pst \ 155*55131Storek break; \ 156*55131Storek case RAS_AND: \ 157*55131Storek pre \ 158*55131Storek (d) = (s) & (d); \ 159*55131Storek pst \ 160*55131Storek break; \ 161*55131Storek case RAS_NOTXOR: \ 162*55131Storek pre \ 163*55131Storek (d) = ~( (s) ^ (d) ); \ 164*55131Storek pst \ 165*55131Storek break; \ 166*55131Storek case RAS_NOTSRC_OR_DST: \ 167*55131Storek pre \ 168*55131Storek (d) = ~(s) | (d); \ 169*55131Storek pst \ 170*55131Storek break; \ 171*55131Storek case RAS_SRC: \ 172*55131Storek pre \ 173*55131Storek (d) = (s); \ 174*55131Storek pst \ 175*55131Storek break; \ 176*55131Storek case RAS_SRC_OR_NOTDST: \ 177*55131Storek pre \ 178*55131Storek (d) = (s) | ~(d); \ 179*55131Storek pst \ 180*55131Storek break; \ 181*55131Storek case RAS_OR: \ 182*55131Storek pre \ 183*55131Storek (d) = (s) | (d); \ 184*55131Storek pst \ 185*55131Storek break; \ 186*55131Storek default: \ 187*55131Storek return -1; \ 188*55131Storek } 189*55131Storek 190*55131Storek #define ROP_SRCDSTCOLOR(op,pre,s,d,c,pst) \ 191*55131Storek switch ( op ) \ 192*55131Storek { \ 193*55131Storek case RAS_NOTOR: \ 194*55131Storek pre \ 195*55131Storek if ( s ) \ 196*55131Storek (d) = ~( (c) | (d) ); \ 197*55131Storek else \ 198*55131Storek (d) = ~(d); \ 199*55131Storek pst \ 200*55131Storek break; \ 201*55131Storek case RAS_NOTSRC_AND_DST: \ 202*55131Storek pre \ 203*55131Storek if ( s ) \ 204*55131Storek (d) = ~(c) & (d); \ 205*55131Storek pst \ 206*55131Storek break; \ 207*55131Storek case RAS_INVERTSRC: \ 208*55131Storek pre \ 209*55131Storek if ( s ) \ 210*55131Storek (d) = ~(c); \ 211*55131Storek else \ 212*55131Storek (d) = ~0; \ 213*55131Storek pst \ 214*55131Storek break; \ 215*55131Storek case RAS_SRC_AND_NOTDST: \ 216*55131Storek pre \ 217*55131Storek if ( s ) \ 218*55131Storek (d) = (c) & ~(d); \ 219*55131Storek else \ 220*55131Storek (d) = 0; \ 221*55131Storek pst \ 222*55131Storek break; \ 223*55131Storek case RAS_XOR: \ 224*55131Storek pre \ 225*55131Storek if ( s ) \ 226*55131Storek (d) = (c) ^ (d); \ 227*55131Storek pst \ 228*55131Storek break; \ 229*55131Storek case RAS_NOTAND: \ 230*55131Storek pre \ 231*55131Storek if ( s ) \ 232*55131Storek (d) = ~( (c) & (d) ); \ 233*55131Storek else \ 234*55131Storek (d) = ~0; \ 235*55131Storek pst \ 236*55131Storek break; \ 237*55131Storek case RAS_AND: \ 238*55131Storek pre \ 239*55131Storek if ( s ) \ 240*55131Storek (d) = (c) & (d); \ 241*55131Storek else \ 242*55131Storek (d) = 0; \ 243*55131Storek pst \ 244*55131Storek break; \ 245*55131Storek case RAS_NOTXOR: \ 246*55131Storek pre \ 247*55131Storek if ( s ) \ 248*55131Storek (d) = ~( (c) ^ (d) ); \ 249*55131Storek else \ 250*55131Storek (d) = ~(d); \ 251*55131Storek pst \ 252*55131Storek break; \ 253*55131Storek case RAS_NOTSRC_OR_DST: \ 254*55131Storek pre \ 255*55131Storek if ( s ) \ 256*55131Storek (d) = ~(c) | (d); \ 257*55131Storek else \ 258*55131Storek (d) = ~0; \ 259*55131Storek pst \ 260*55131Storek break; \ 261*55131Storek case RAS_SRC: \ 262*55131Storek pre \ 263*55131Storek if ( s ) \ 264*55131Storek (d) = (c); \ 265*55131Storek else \ 266*55131Storek (d) = 0; \ 267*55131Storek pst \ 268*55131Storek break; \ 269*55131Storek case RAS_SRC_OR_NOTDST: \ 270*55131Storek pre \ 271*55131Storek if ( s ) \ 272*55131Storek (d) = (c) | ~(d); \ 273*55131Storek else \ 274*55131Storek (d) = ~(d); \ 275*55131Storek pst \ 276*55131Storek break; \ 277*55131Storek case RAS_OR: \ 278*55131Storek pre \ 279*55131Storek if ( s ) \ 280*55131Storek (d) = (c) | (d); \ 281*55131Storek pst \ 282*55131Storek break; \ 283*55131Storek default: \ 284*55131Storek return -1; \ 285*55131Storek } 286*55131Storek 287*55131Storek #else /*PARTIAL_LOGICAL_OPS*/ 288*55131Storek 289*55131Storek #define ROP_DST(op,pre,d,pst) \ 290*55131Storek switch ( op ) \ 291*55131Storek { \ 292*55131Storek case RAS_CLEAR: \ 293*55131Storek pre \ 294*55131Storek (d) = 0; \ 295*55131Storek pst \ 296*55131Storek break; \ 297*55131Storek case RAS_INVERT: \ 298*55131Storek pre \ 299*55131Storek (d) = ~(d); \ 300*55131Storek pst \ 301*55131Storek break; \ 302*55131Storek case RAS_SET: \ 303*55131Storek pre \ 304*55131Storek (d) = ~0; \ 305*55131Storek pst \ 306*55131Storek break; \ 307*55131Storek default: \ 308*55131Storek return -1; \ 309*55131Storek } 310*55131Storek 311*55131Storek #define ROP_DSTCOLOR(op,pre,d,c,pst) \ 312*55131Storek switch ( op ) \ 313*55131Storek { \ 314*55131Storek case RAS_CLEAR: \ 315*55131Storek pre \ 316*55131Storek (d) = 0; \ 317*55131Storek pst \ 318*55131Storek break; \ 319*55131Storek case RAS_INVERT: \ 320*55131Storek pre \ 321*55131Storek (d) = ~(d); \ 322*55131Storek pst \ 323*55131Storek break; \ 324*55131Storek case RAS_SET: \ 325*55131Storek pre \ 326*55131Storek (d) = (c); \ 327*55131Storek pst \ 328*55131Storek break; \ 329*55131Storek default: \ 330*55131Storek return -1; \ 331*55131Storek } 332*55131Storek 333*55131Storek #define ROP_SRCDST(op,pre,s,d,pst) \ 334*55131Storek switch ( op ) \ 335*55131Storek { \ 336*55131Storek case RAS_INVERTSRC: \ 337*55131Storek pre \ 338*55131Storek (d) = ~(s); \ 339*55131Storek pst \ 340*55131Storek break; \ 341*55131Storek case RAS_XOR: \ 342*55131Storek pre \ 343*55131Storek (d) = (s) ^ (d); \ 344*55131Storek pst \ 345*55131Storek break; \ 346*55131Storek case RAS_SRC: \ 347*55131Storek pre \ 348*55131Storek (d) = (s); \ 349*55131Storek pst \ 350*55131Storek break; \ 351*55131Storek default: \ 352*55131Storek return -1; \ 353*55131Storek } 354*55131Storek 355*55131Storek #define ROP_SRCDSTCOLOR(op,pre,s,d,c,pst) \ 356*55131Storek switch ( op ) \ 357*55131Storek { \ 358*55131Storek case RAS_INVERTSRC: \ 359*55131Storek pre \ 360*55131Storek if ( s ) \ 361*55131Storek (d) = ~(c); \ 362*55131Storek else \ 363*55131Storek (d) = ~0; \ 364*55131Storek pst \ 365*55131Storek break; \ 366*55131Storek case RAS_XOR: \ 367*55131Storek pre \ 368*55131Storek if ( s ) \ 369*55131Storek (d) = (c) ^ (d); \ 370*55131Storek pst \ 371*55131Storek break; \ 372*55131Storek case RAS_SRC: \ 373*55131Storek pre \ 374*55131Storek if ( s ) \ 375*55131Storek (d) = (c); \ 376*55131Storek else \ 377*55131Storek (d) = 0; \ 378*55131Storek pst \ 379*55131Storek break; \ 380*55131Storek default: \ 381*55131Storek return -1; \ 382*55131Storek } 383*55131Storek 384*55131Storek #endif /*PARTIAL_LOGICAL_OPS*/ 385*55131Storek 386*55131Storek 387*55131Storek /* Variables. */ 388*55131Storek 389*55131Storek static int needsrc[16] = { 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0 }; 390*55131Storek /* CLEAR INVERT DST SET */ 391*55131Storek 392*55131Storek #ifdef MSBIT_FIRST 393*55131Storek 394*55131Storek u_long raster_bitmask[32] = { 395*55131Storek 0x80000000, 0x40000000, 0x20000000, 0x10000000, 396*55131Storek 0x08000000, 0x04000000, 0x02000000, 0x01000000, 397*55131Storek 0x00800000, 0x00400000, 0x00200000, 0x00100000, 398*55131Storek 0x00080000, 0x00040000, 0x00020000, 0x00010000, 399*55131Storek 0x00008000, 0x00004000, 0x00002000, 0x00001000, 400*55131Storek 0x00000800, 0x00000400, 0x00000200, 0x00000100, 401*55131Storek 0x00000080, 0x00000040, 0x00000020, 0x00000010, 402*55131Storek 0x00000008, 0x00000004, 0x00000002, 0x00000001 }; 403*55131Storek 404*55131Storek #ifdef MSBYTE_FIRST 405*55131Storek static u_long leftmask[32] = { 406*55131Storek 0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 407*55131Storek 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000, 408*55131Storek 0xff000000, 0xff800000, 0xffc00000, 0xffe00000, 409*55131Storek 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 410*55131Storek 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000, 411*55131Storek 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00, 412*55131Storek 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 413*55131Storek 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe }; 414*55131Storek static u_long rightmask[32] = { 415*55131Storek 0x00000000, 0x00000001, 0x00000003, 0x00000007, 416*55131Storek 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, 417*55131Storek 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, 418*55131Storek 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 419*55131Storek 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, 420*55131Storek 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff, 421*55131Storek 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, 422*55131Storek 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff }; 423*55131Storek #endif /*MSBYTE_FIRST*/ 424*55131Storek 425*55131Storek #else /*MSBIT_FIRST*/ 426*55131Storek 427*55131Storek u_long raster_bitmask[32] = { 428*55131Storek 0x00000001, 0x00000002, 0x00000004, 0x00000008, 429*55131Storek 0x00000010, 0x00000020, 0x00000040, 0x00000080, 430*55131Storek 0x00000100, 0x00000200, 0x00000400, 0x00000800, 431*55131Storek 0x00001000, 0x00002000, 0x00004000, 0x00008000, 432*55131Storek 0x00010000, 0x00020000, 0x00040000, 0x00080000, 433*55131Storek 0x00100000, 0x00200000, 0x00400000, 0x00800000, 434*55131Storek 0x01000000, 0x02000000, 0x04000000, 0x08000000, 435*55131Storek 0x10000000, 0x20000000, 0x40000000, 0x80000000 }; 436*55131Storek 437*55131Storek #ifndef MSBYTE_FIRST 438*55131Storek static u_long leftmask[32] = { 439*55131Storek 0x00000000, 0x00000001, 0x00000003, 0x00000007, 440*55131Storek 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, 441*55131Storek 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, 442*55131Storek 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 443*55131Storek 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, 444*55131Storek 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff, 445*55131Storek 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, 446*55131Storek 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff }; 447*55131Storek static u_long rightmask[32] = { 448*55131Storek 0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 449*55131Storek 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000, 450*55131Storek 0xff000000, 0xff800000, 0xffc00000, 0xffe00000, 451*55131Storek 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 452*55131Storek 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000, 453*55131Storek 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00, 454*55131Storek 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 455*55131Storek 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe }; 456*55131Storek #endif /*not MSBYTE_FIRST*/ 457*55131Storek 458*55131Storek #endif /*MSBIT_FIRST*/ 459*55131Storek 460*55131Storek /* (The odd combinations MSBIT+~MSBYTE and ~MSBIT+MSBYTE could be added.) */ 461*55131Storek 462*55131Storek #ifdef MSBYTE_FIRST 463*55131Storek static u_long bytemask[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff }; 464*55131Storek #else /*MSBYTE_FIRST*/ 465*55131Storek static u_long bytemask[4] = { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }; 466*55131Storek #endif /*MSBYTE_FIRST*/ 467*55131Storek 468*55131Storek 469*55131Storek /* Forward routines. */ 470*55131Storek 471*55131Storek static int raster_blit(); 472*55131Storek 473*55131Storek 474*55131Storek /* Raster operations. */ 475*55131Storek 476*55131Storek /* Performs a bitblit. Returns 0 on success, -1 on failure. */ 477*55131Storek int 478*55131Storek raster_op( dst, dx, dy, w, h, rop, src, sx, sy ) 479*55131Storek struct raster* dst; 480*55131Storek int dx, dy, w, h, rop; 481*55131Storek struct raster* src; 482*55131Storek int sx, sy; 483*55131Storek { 484*55131Storek if ( dst == (struct raster*) 0 ) 485*55131Storek return -1; /* no destination */ 486*55131Storek 487*55131Storek if ( needsrc[RAS_GETOP( rop )] ) 488*55131Storek { 489*55131Storek /* Two-operand blit. */ 490*55131Storek if ( src == (struct raster*) 0 ) 491*55131Storek return -1; /* no source */ 492*55131Storek 493*55131Storek /* Clip against source. */ 494*55131Storek if ( sx < 0 ) 495*55131Storek { 496*55131Storek w += sx; 497*55131Storek sx = 0; 498*55131Storek } 499*55131Storek if ( sy < 0 ) 500*55131Storek { 501*55131Storek h += sy; 502*55131Storek sy = 0; 503*55131Storek } 504*55131Storek if ( sx + w > src->width ) 505*55131Storek w = src->width - sx; 506*55131Storek if ( sy + h > src->height ) 507*55131Storek h = src->height - sy; 508*55131Storek 509*55131Storek /* Clip against dest. */ 510*55131Storek if ( dx < 0 ) 511*55131Storek { 512*55131Storek w += dx; 513*55131Storek sx -= dx; 514*55131Storek dx = 0; 515*55131Storek } 516*55131Storek if ( dy < 0 ) 517*55131Storek { 518*55131Storek h += dy; 519*55131Storek sy -= dy; 520*55131Storek dy = 0; 521*55131Storek } 522*55131Storek if ( dx + w > dst->width ) 523*55131Storek w = dst->width - dx; 524*55131Storek if ( dy + h > dst->height ) 525*55131Storek h = dst->height - dy; 526*55131Storek 527*55131Storek if ( w <= 0 || h <= 0 ) 528*55131Storek return 0; /* nothing to do */ 529*55131Storek 530*55131Storek return raster_op_noclip( dst, dx, dy, w, h, rop, src, sx, sy ); 531*55131Storek } 532*55131Storek 533*55131Storek /* No source necessary - one-operand blit. */ 534*55131Storek if ( src != (struct raster*) 0 ) 535*55131Storek return -1; /* unwanted source */ 536*55131Storek 537*55131Storek /* Clip against dest. */ 538*55131Storek if ( dx < 0 ) 539*55131Storek { 540*55131Storek w += dx; 541*55131Storek dx = 0; 542*55131Storek } 543*55131Storek if ( dy < 0 ) 544*55131Storek { 545*55131Storek h += dy; 546*55131Storek dy = 0; 547*55131Storek } 548*55131Storek if ( dx + w > dst->width ) 549*55131Storek w = dst->width - dx; 550*55131Storek if ( dy + h > dst->height ) 551*55131Storek h = dst->height - dy; 552*55131Storek 553*55131Storek if ( w <= 0 || h <= 0 ) 554*55131Storek return 0; /* nothing to do */ 555*55131Storek 556*55131Storek return raster_op_nosrc_noclip( dst, dx, dy, w, h, rop ); 557*55131Storek } 558*55131Storek 559*55131Storek /* Semi-public routine to do a bitblit without clipping. Returns 0 on 560*55131Storek ** success, -1 on failure. 561*55131Storek */ 562*55131Storek int 563*55131Storek raster_op_noclip( dst, dx, dy, w, h, rop, src, sx, sy ) 564*55131Storek struct raster* dst; 565*55131Storek int dx, dy, w, h, rop; 566*55131Storek struct raster* src; 567*55131Storek int sx, sy; 568*55131Storek { 569*55131Storek int op; 570*55131Storek 571*55131Storek op = RAS_GETOP( rop ); 572*55131Storek 573*55131Storek if ( src->depth == 1 ) 574*55131Storek { 575*55131Storek /* One-bit to ? blit. */ 576*55131Storek if ( dst->depth == 1 ) 577*55131Storek { 578*55131Storek /* One to one blit. */ 579*55131Storek u_long* srclin1; 580*55131Storek u_long* dstlin1; 581*55131Storek int srcleftignore, srcrightignore, srclongs; 582*55131Storek int dstleftignore, dstrightignore, dstlongs; 583*55131Storek 584*55131Storek srclin1 = RAS_ADDR( src, sx, sy ); 585*55131Storek dstlin1 = RAS_ADDR( dst, dx, dy ); 586*55131Storek 587*55131Storek #ifdef BCOPY_FASTER 588*55131Storek /* Special-case full-width to full-width copies. */ 589*55131Storek if ( op == RAS_SRC && src->width == w && dst->width == w && 590*55131Storek src->linelongs == dst->linelongs && src->linelongs == w >> 5 ) 591*55131Storek { 592*55131Storek bcopy( 593*55131Storek (char*) srclin1, (char*) dstlin1, 594*55131Storek h * src->linelongs * sizeof(u_long) ); 595*55131Storek return 0; 596*55131Storek } 597*55131Storek #endif /*BCOPY_FASTER*/ 598*55131Storek 599*55131Storek srcleftignore = ( sx & 31 ); 600*55131Storek srclongs = ( srcleftignore + w + 31 ) >> 5; 601*55131Storek srcrightignore = ( srclongs * 32 - w - srcleftignore ) & 31; 602*55131Storek dstleftignore = ( dx & 31 ); 603*55131Storek dstlongs = ( dstleftignore + w + 31 ) >> 5; 604*55131Storek dstrightignore = ( dstlongs * 32 - w - dstleftignore ) & 31; 605*55131Storek 606*55131Storek return raster_blit( 607*55131Storek src, srclin1, srcleftignore, srcrightignore, srclongs, 608*55131Storek dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op ); 609*55131Storek } 610*55131Storek 611*55131Storek else 612*55131Storek { 613*55131Storek /* One to eight, using the color in the rop. This could 614*55131Storek ** probably be sped up by handling each four-bit source nybble 615*55131Storek ** as a group, indexing into a 16-element runtime-constructed 616*55131Storek ** table of longwords. 617*55131Storek */ 618*55131Storek u_long* srclin1; 619*55131Storek u_long* dstlin1; 620*55131Storek u_long* srclin2; 621*55131Storek u_long* srclin; 622*55131Storek u_long* dstlin; 623*55131Storek register u_long* srclong; 624*55131Storek register u_long* dstlong; 625*55131Storek register u_long color, dl; 626*55131Storek register int srcbit, dstbyte, i; 627*55131Storek 628*55131Storek color = RAS_GETCOLOR( rop ); 629*55131Storek if ( color == 0 ) 630*55131Storek color = 255; 631*55131Storek 632*55131Storek /* Make 32 bits of color so we can do the ROP without shifting. */ 633*55131Storek color |= ( color << 24 ) | ( color << 16 ) | ( color << 8 ); 634*55131Storek 635*55131Storek /* Don't have to worry about overlapping blits here. */ 636*55131Storek srclin1 = RAS_ADDR( src, sx, sy ); 637*55131Storek srclin2 = srclin1 + h * src->linelongs; 638*55131Storek dstlin1 = RAS_ADDR( dst, dx, dy ); 639*55131Storek srclin = srclin1; 640*55131Storek dstlin = dstlin1; 641*55131Storek while ( srclin != srclin2 ) 642*55131Storek { 643*55131Storek srclong = srclin; 644*55131Storek srcbit = sx & 31; 645*55131Storek dstlong = dstlin; 646*55131Storek dstbyte = dx & 3; 647*55131Storek i = w; 648*55131Storek 649*55131Storek /* WARNING: this code is KNOWN TO FAIL on Sun 3's / CG2's. */ 650*55131Storek ROP_SRCDSTCOLOR( 651*55131Storek /*op*/ op, 652*55131Storek /*pre*/ while ( i > 0 ) 653*55131Storek { 654*55131Storek dl = *dstlong;, 655*55131Storek /*s*/ *srclong & raster_bitmask[srcbit], 656*55131Storek /*d*/ dl, 657*55131Storek /*c*/ color, 658*55131Storek /*pst*/ *dstlong = ( *dstlong & ~bytemask[dstbyte] ) | 659*55131Storek ( dl & bytemask[dstbyte] ); 660*55131Storek if ( srcbit == 31 ) 661*55131Storek { 662*55131Storek srcbit = 0; 663*55131Storek ++srclong; 664*55131Storek } 665*55131Storek else 666*55131Storek ++srcbit; 667*55131Storek if ( dstbyte == 3 ) 668*55131Storek { 669*55131Storek dstbyte = 0; 670*55131Storek ++dstlong; 671*55131Storek } 672*55131Storek else 673*55131Storek ++dstbyte; 674*55131Storek --i; 675*55131Storek } ) 676*55131Storek 677*55131Storek srclin += src->linelongs; 678*55131Storek dstlin += dst->linelongs; 679*55131Storek } 680*55131Storek } 681*55131Storek } 682*55131Storek 683*55131Storek else 684*55131Storek { 685*55131Storek /* Eight to eight blit. */ 686*55131Storek u_long* srclin1; 687*55131Storek u_long* dstlin1; 688*55131Storek int srcleftignore, srcrightignore, srclongs; 689*55131Storek int dstleftignore, dstrightignore, dstlongs; 690*55131Storek 691*55131Storek if ( dst->depth != 8 ) 692*55131Storek return -1; /* depth mismatch */ 693*55131Storek 694*55131Storek srclin1 = RAS_ADDR( src, sx, sy ); 695*55131Storek dstlin1 = RAS_ADDR( dst, dx, dy ); 696*55131Storek 697*55131Storek #ifdef BCOPY_FASTER 698*55131Storek /* Special-case full-width to full-width copies. */ 699*55131Storek if ( op == RAS_SRC && src->width == w && dst->width == w && 700*55131Storek src->linelongs == dst->linelongs && src->linelongs == w >> 2 ) 701*55131Storek { 702*55131Storek bcopy( (char*) srclin1, (char*) dstlin1, 703*55131Storek h * src->linelongs * sizeof(u_long) ); 704*55131Storek return 0; 705*55131Storek } 706*55131Storek #endif /*BCOPY_FASTER*/ 707*55131Storek 708*55131Storek srcleftignore = ( sx & 3 ) * 8; 709*55131Storek srclongs = ( srcleftignore + w * 8 + 31 ) >> 5; 710*55131Storek srcrightignore = ( srclongs * 32 - w * 8 - srcleftignore ) & 31; 711*55131Storek dstleftignore = ( dx & 3 ) * 8; 712*55131Storek dstlongs = ( dstleftignore + w * 8 + 31 ) >> 5; 713*55131Storek dstrightignore = ( dstlongs * 32 - w * 8 - dstleftignore ) & 31; 714*55131Storek 715*55131Storek return raster_blit( 716*55131Storek src, srclin1, srcleftignore, srcrightignore, srclongs, 717*55131Storek dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op ); 718*55131Storek } 719*55131Storek 720*55131Storek return 0; 721*55131Storek } 722*55131Storek 723*55131Storek /* Semi-public routine to do a no-src bitblit without clipping. Returns 0 724*55131Storek ** on success, -1 on failure. 725*55131Storek */ 726*55131Storek int 727*55131Storek raster_op_nosrc_noclip( dst, dx, dy, w, h, rop ) 728*55131Storek struct raster* dst; 729*55131Storek int dx, dy, w, h, rop; 730*55131Storek { 731*55131Storek int op; 732*55131Storek 733*55131Storek op = RAS_GETOP( rop ); 734*55131Storek 735*55131Storek if ( dst->depth == 1 ) 736*55131Storek { 737*55131Storek /* One-bit no-src blit. */ 738*55131Storek u_long* dstlin1; 739*55131Storek u_long* dstlin2; 740*55131Storek u_long* dstlin; 741*55131Storek int dstleftignore, dstrightignore, dstlongs; 742*55131Storek u_long dl, lm, nlm, rm, nrm; 743*55131Storek register u_long* dstlong2; 744*55131Storek register u_long* dstlong; 745*55131Storek 746*55131Storek dstlin1 = RAS_ADDR( dst, dx, dy ); 747*55131Storek 748*55131Storek #ifdef BCOPY_FASTER 749*55131Storek /* Special-case full-width clears. */ 750*55131Storek if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 5 ) 751*55131Storek { 752*55131Storek bzero( (char*) dstlin1, h * dst->linelongs * sizeof(u_long) ); 753*55131Storek return 0; 754*55131Storek } 755*55131Storek #endif /*BCOPY_FASTER*/ 756*55131Storek 757*55131Storek dstleftignore = ( dx & 31 ); 758*55131Storek dstlongs = ( dstleftignore + w + 31 ) >> 5; 759*55131Storek dstrightignore = ( dstlongs * 32 - w - dstleftignore ) & 31; 760*55131Storek 761*55131Storek dstlin2 = dstlin1 + h * dst->linelongs; 762*55131Storek dstlin = dstlin1; 763*55131Storek 764*55131Storek if ( dstlongs == 1 ) 765*55131Storek { 766*55131Storek /* It fits into a single longword. */ 767*55131Storek lm = leftmask[dstleftignore] | rightmask[dstrightignore]; 768*55131Storek nlm = ~lm; 769*55131Storek while ( dstlin != dstlin2 ) 770*55131Storek { 771*55131Storek ROP_DST( 772*55131Storek /*op*/ op, 773*55131Storek /*pre*/ dl = *dstlin;, 774*55131Storek /*d*/ dl, 775*55131Storek /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); ) 776*55131Storek 777*55131Storek dstlin += dst->linelongs; 778*55131Storek } 779*55131Storek } 780*55131Storek else 781*55131Storek { 782*55131Storek lm = leftmask[dstleftignore]; 783*55131Storek rm = rightmask[dstrightignore]; 784*55131Storek nrm = ~rm; 785*55131Storek nlm = ~lm; 786*55131Storek 787*55131Storek while ( dstlin != dstlin2 ) 788*55131Storek { 789*55131Storek dstlong = dstlin; 790*55131Storek dstlong2 = dstlong + dstlongs; 791*55131Storek if ( dstrightignore != 0 ) 792*55131Storek --dstlong2; 793*55131Storek 794*55131Storek /* Leading edge. */ 795*55131Storek if ( dstleftignore != 0 ) 796*55131Storek { 797*55131Storek ROP_DST( 798*55131Storek /*op*/ op, 799*55131Storek /*pre*/ dl = *dstlong;, 800*55131Storek /*d*/ dl, 801*55131Storek /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); ) 802*55131Storek ++dstlong; 803*55131Storek } 804*55131Storek 805*55131Storek /* Main rop. */ 806*55131Storek ROP_DST( 807*55131Storek /*op*/ op, 808*55131Storek /*pre*/ while ( dstlong != dstlong2 ) 809*55131Storek {, 810*55131Storek /*d*/ *dstlong, 811*55131Storek /*pst*/ ++dstlong; 812*55131Storek } ) 813*55131Storek 814*55131Storek /* Trailing edge. */ 815*55131Storek if ( dstrightignore != 0 ) 816*55131Storek { 817*55131Storek ROP_DST( 818*55131Storek /*op*/ op, 819*55131Storek /*pre*/ dl = *dstlong;, 820*55131Storek /*d*/ dl, 821*55131Storek /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); ) 822*55131Storek } 823*55131Storek 824*55131Storek dstlin += dst->linelongs; 825*55131Storek } 826*55131Storek } 827*55131Storek } 828*55131Storek 829*55131Storek else 830*55131Storek { 831*55131Storek /* Eight-bit no-src blit. */ 832*55131Storek register u_long color; 833*55131Storek u_long* dstlin1; 834*55131Storek u_long* dstlin2; 835*55131Storek u_long* dstlin; 836*55131Storek int dstleftignore, dstrightignore, dstlongs; 837*55131Storek u_long dl, lm, nlm, rm, nrm; 838*55131Storek register u_long* dstlong2; 839*55131Storek register u_long* dstlong; 840*55131Storek 841*55131Storek dstlin1 = RAS_ADDR( dst, dx, dy ); 842*55131Storek 843*55131Storek #ifdef BCOPY_FASTER 844*55131Storek /* Special-case full-width clears. */ 845*55131Storek if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 2 ) 846*55131Storek { 847*55131Storek bzero( (char*) dstlin1, h * dst->linelongs * sizeof(u_long) ); 848*55131Storek return 0; 849*55131Storek } 850*55131Storek #endif /*BCOPY_FASTER*/ 851*55131Storek 852*55131Storek color = RAS_GETCOLOR( rop ); 853*55131Storek if ( color == 0 ) 854*55131Storek color = 255; 855*55131Storek 856*55131Storek /* Make 32 bits of color so we can do the ROP without shifting. */ 857*55131Storek color |= ( color << 24 ) | ( color << 16 ) | ( color << 8 ); 858*55131Storek 859*55131Storek dstleftignore = ( dx & 3 ) * 8; 860*55131Storek dstlongs = ( dstleftignore + w * 8 + 31 ) >> 5; 861*55131Storek dstrightignore = ( dstlongs * 32 - w * 8 - dstleftignore ) & 31; 862*55131Storek 863*55131Storek dstlin2 = dstlin1 + h * dst->linelongs; 864*55131Storek dstlin = dstlin1; 865*55131Storek 866*55131Storek if ( dstlongs == 1 ) 867*55131Storek { 868*55131Storek /* It fits into a single longword. */ 869*55131Storek lm = leftmask[dstleftignore] | rightmask[dstrightignore]; 870*55131Storek nlm = ~lm; 871*55131Storek while ( dstlin != dstlin2 ) 872*55131Storek { 873*55131Storek ROP_DSTCOLOR( 874*55131Storek /*op*/ op, 875*55131Storek /*pre*/ dl = *dstlin;, 876*55131Storek /*d*/ dl, 877*55131Storek /*c*/ color, 878*55131Storek /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); ) 879*55131Storek 880*55131Storek dstlin += dst->linelongs; 881*55131Storek } 882*55131Storek } 883*55131Storek else 884*55131Storek { 885*55131Storek lm = leftmask[dstleftignore]; 886*55131Storek rm = rightmask[dstrightignore]; 887*55131Storek nrm = ~rm; 888*55131Storek nlm = ~lm; 889*55131Storek while ( dstlin != dstlin2 ) 890*55131Storek { 891*55131Storek dstlong = dstlin; 892*55131Storek dstlong2 = dstlong + dstlongs; 893*55131Storek if ( dstrightignore != 0 ) 894*55131Storek --dstlong2; 895*55131Storek 896*55131Storek /* Leading edge. */ 897*55131Storek if ( dstleftignore != 0 ) 898*55131Storek { 899*55131Storek ROP_DSTCOLOR( 900*55131Storek /*op*/ op, 901*55131Storek /*pre*/ dl = *dstlong;, 902*55131Storek /*d*/ dl, 903*55131Storek /*c*/ color, 904*55131Storek /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); ) 905*55131Storek ++dstlong; 906*55131Storek } 907*55131Storek 908*55131Storek /* Main rop. */ 909*55131Storek ROP_DSTCOLOR( 910*55131Storek /*op*/ op, 911*55131Storek /*pre*/ while ( dstlong != dstlong2 ) 912*55131Storek {, 913*55131Storek /*d*/ *dstlong, 914*55131Storek /*c*/ color, 915*55131Storek /*pst*/ ++dstlong; 916*55131Storek } ) 917*55131Storek 918*55131Storek /* Trailing edge. */ 919*55131Storek if ( dstrightignore != 0 ) 920*55131Storek { 921*55131Storek ROP_DSTCOLOR( 922*55131Storek /*op*/ op, 923*55131Storek /*pre*/ dl = *dstlong;, 924*55131Storek /*d*/ dl, 925*55131Storek /*c*/ color, 926*55131Storek /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); ) 927*55131Storek } 928*55131Storek 929*55131Storek dstlin += dst->linelongs; 930*55131Storek } 931*55131Storek } 932*55131Storek } 933*55131Storek 934*55131Storek return 0; 935*55131Storek } 936*55131Storek 937*55131Storek /* This is a general bitblit routine, handling overlapping source and 938*55131Storek ** destination. It's used for both the 1-to-1 and 8-to-8 cases. 939*55131Storek */ 940*55131Storek static int 941*55131Storek raster_blit( src, srclin1, srcleftignore, srcrightignore, srclongs, dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op ) 942*55131Storek struct raster* src; 943*55131Storek u_long* srclin1; 944*55131Storek int srcleftignore, srcrightignore, srclongs; 945*55131Storek struct raster* dst; 946*55131Storek u_long* dstlin1; 947*55131Storek int dstleftignore, dstrightignore, dstlongs; 948*55131Storek int h, op; 949*55131Storek { 950*55131Storek u_long* srclin2; 951*55131Storek u_long* dstlin2; 952*55131Storek int srclininc, dstlininc; 953*55131Storek u_long* srclin; 954*55131Storek u_long* dstlin; 955*55131Storek register int prevleftshift, currrightshift; 956*55131Storek int longinc; 957*55131Storek register u_long* srclong; 958*55131Storek register u_long* dstlong; 959*55131Storek register u_long* dstlong2; 960*55131Storek register u_long dl, lm, nlm, rm, nrm; 961*55131Storek 962*55131Storek prevleftshift = ( srcleftignore - dstleftignore ) & 31; 963*55131Storek 964*55131Storek srclin2 = srclin1 + h * src->linelongs; 965*55131Storek dstlin2 = dstlin1 + h * dst->linelongs; 966*55131Storek srclininc = src->linelongs; 967*55131Storek dstlininc = dst->linelongs; 968*55131Storek longinc = 1; 969*55131Storek 970*55131Storek /* Check for overlaps. */ 971*55131Storek if ( ( dstlin1 >= srclin1 && dstlin1 < srclin1 + srclongs ) || 972*55131Storek ( srclin1 >= dstlin1 && srclin1 < dstlin1 + dstlongs ) ) 973*55131Storek { 974*55131Storek /* Horizontal overlap. Should we reverse? */ 975*55131Storek if ( srclin1 < dstlin1 ) 976*55131Storek { 977*55131Storek longinc = -1; 978*55131Storek srclin1 += srclongs - 1; 979*55131Storek srclin2 += srclongs - 1; 980*55131Storek dstlin1 += dstlongs - 1; 981*55131Storek } 982*55131Storek } 983*55131Storek else if ( ( dstlin1 >= srclin1 && dstlin1 < srclin2 ) || 984*55131Storek ( srclin1 >= dstlin1 && srclin1 < dstlin2 ) ) 985*55131Storek { 986*55131Storek /* Vertical overlap. Should we reverse? */ 987*55131Storek if ( srclin1 < dstlin1 ) 988*55131Storek { 989*55131Storek srclin2 = srclin1 - srclininc; 990*55131Storek srclin1 += ( h - 1 ) * srclininc; 991*55131Storek dstlin1 += ( h - 1 ) * dstlininc; 992*55131Storek srclininc = -srclininc; 993*55131Storek dstlininc = -dstlininc; 994*55131Storek } 995*55131Storek } 996*55131Storek srclin = srclin1; 997*55131Storek dstlin = dstlin1; 998*55131Storek 999*55131Storek if ( prevleftshift == 0 ) 1000*55131Storek { 1001*55131Storek /* The bits line up, no shifting necessary. */ 1002*55131Storek if ( dstlongs == 1 ) 1003*55131Storek { 1004*55131Storek /* It all fits into a single longword. */ 1005*55131Storek lm = leftmask[dstleftignore] | rightmask[dstrightignore]; 1006*55131Storek nlm = ~lm; 1007*55131Storek while ( srclin != srclin2 ) 1008*55131Storek { 1009*55131Storek ROP_SRCDST( 1010*55131Storek /*op*/ op, 1011*55131Storek /*pre*/ dl = *dstlin;, 1012*55131Storek /*s*/ *srclin, 1013*55131Storek /*d*/ dl, 1014*55131Storek /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); ) 1015*55131Storek 1016*55131Storek srclin += srclininc; 1017*55131Storek dstlin += dstlininc; 1018*55131Storek } 1019*55131Storek } 1020*55131Storek else 1021*55131Storek { 1022*55131Storek /* Multiple longwords. */ 1023*55131Storek lm = leftmask[dstleftignore]; 1024*55131Storek rm = rightmask[dstrightignore]; 1025*55131Storek nrm = ~rm; 1026*55131Storek nlm = ~lm; 1027*55131Storek if ( longinc == 1 ) 1028*55131Storek { 1029*55131Storek /* Left to right. */ 1030*55131Storek while ( srclin != srclin2 ) 1031*55131Storek { 1032*55131Storek srclong = srclin; 1033*55131Storek dstlong = dstlin; 1034*55131Storek dstlong2 = dstlong + dstlongs; 1035*55131Storek if ( dstrightignore != 0 ) 1036*55131Storek --dstlong2; 1037*55131Storek 1038*55131Storek /* Leading edge. */ 1039*55131Storek if ( dstleftignore != 0 ) 1040*55131Storek { 1041*55131Storek ROP_SRCDST( 1042*55131Storek /*op*/ op, 1043*55131Storek /*pre*/ dl = *dstlong;, 1044*55131Storek /*s*/ *srclong, 1045*55131Storek /*d*/ dl, 1046*55131Storek /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); ) 1047*55131Storek ++srclong; 1048*55131Storek ++dstlong; 1049*55131Storek } 1050*55131Storek 1051*55131Storek /* Main rop. */ 1052*55131Storek ROP_SRCDST( 1053*55131Storek /*op*/ op, 1054*55131Storek /*pre*/ while ( dstlong != dstlong2 ) 1055*55131Storek {, 1056*55131Storek /*s*/ *srclong, 1057*55131Storek /*d*/ *dstlong, 1058*55131Storek /*pst*/ ++srclong; 1059*55131Storek ++dstlong; 1060*55131Storek } ) 1061*55131Storek 1062*55131Storek /* Trailing edge. */ 1063*55131Storek if ( dstrightignore != 0 ) 1064*55131Storek { 1065*55131Storek ROP_SRCDST( 1066*55131Storek /*op*/ op, 1067*55131Storek /*pre*/ dl = *dstlong;, 1068*55131Storek /*s*/ *srclong, 1069*55131Storek /*d*/ dl, 1070*55131Storek /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); ) 1071*55131Storek } 1072*55131Storek 1073*55131Storek srclin += srclininc; 1074*55131Storek dstlin += dstlininc; 1075*55131Storek } 1076*55131Storek } 1077*55131Storek else 1078*55131Storek { 1079*55131Storek /* Right to left. */ 1080*55131Storek while ( srclin != srclin2 ) 1081*55131Storek { 1082*55131Storek srclong = srclin; 1083*55131Storek dstlong = dstlin; 1084*55131Storek dstlong2 = dstlong - dstlongs; 1085*55131Storek if ( dstleftignore != 0 ) 1086*55131Storek ++dstlong2; 1087*55131Storek 1088*55131Storek /* Leading edge. */ 1089*55131Storek if ( dstrightignore != 0 ) 1090*55131Storek { 1091*55131Storek ROP_SRCDST( 1092*55131Storek /*op*/ op, 1093*55131Storek /*pre*/ dl = *dstlong;, 1094*55131Storek /*s*/ *srclong, 1095*55131Storek /*d*/ dl, 1096*55131Storek /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); ) 1097*55131Storek --srclong; 1098*55131Storek --dstlong; 1099*55131Storek } 1100*55131Storek 1101*55131Storek /* Main rop. */ 1102*55131Storek ROP_SRCDST( 1103*55131Storek /*op*/ op, 1104*55131Storek /*pre*/ while ( dstlong != dstlong2 ) 1105*55131Storek {, 1106*55131Storek /*s*/ *srclong, 1107*55131Storek /*d*/ *dstlong, 1108*55131Storek /*pst*/ --srclong; 1109*55131Storek --dstlong; 1110*55131Storek } ) 1111*55131Storek 1112*55131Storek /* Trailing edge. */ 1113*55131Storek if ( dstleftignore != 0 ) 1114*55131Storek { 1115*55131Storek ROP_SRCDST( 1116*55131Storek /*op*/ op, 1117*55131Storek /*pre*/ dl = *dstlong;, 1118*55131Storek /*s*/ *srclong, 1119*55131Storek /*d*/ dl, 1120*55131Storek /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); ) 1121*55131Storek } 1122*55131Storek 1123*55131Storek srclin += srclininc; 1124*55131Storek dstlin += dstlininc; 1125*55131Storek } 1126*55131Storek } 1127*55131Storek } 1128*55131Storek } 1129*55131Storek 1130*55131Storek else 1131*55131Storek { 1132*55131Storek /* General case, with shifting and everything. */ 1133*55131Storek register u_long sl, prevsl; 1134*55131Storek 1135*55131Storek currrightshift = 32 - prevleftshift; 1136*55131Storek if ( srclongs == 1 && dstlongs == 1 ) 1137*55131Storek { 1138*55131Storek /* It fits into a single longword, with a shift. */ 1139*55131Storek lm = leftmask[dstleftignore] | rightmask[dstrightignore]; 1140*55131Storek nlm = ~lm; 1141*55131Storek if ( srcleftignore > dstleftignore ) 1142*55131Storek { 1143*55131Storek while ( srclin != srclin2 ) 1144*55131Storek { 1145*55131Storek ROP_SRCDST( 1146*55131Storek /*op*/ op, 1147*55131Storek /*pre*/ dl = *dstlin;, 1148*55131Storek /*s*/ *srclin << prevleftshift, 1149*55131Storek /*d*/ dl, 1150*55131Storek /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); ) 1151*55131Storek 1152*55131Storek srclin += srclininc; 1153*55131Storek dstlin += dstlininc; 1154*55131Storek } 1155*55131Storek } 1156*55131Storek else 1157*55131Storek { 1158*55131Storek while ( srclin != srclin2 ) 1159*55131Storek { 1160*55131Storek ROP_SRCDST( 1161*55131Storek /*op*/ op, 1162*55131Storek /*pre*/ dl = *dstlin;, 1163*55131Storek /*s*/ *srclin >> currrightshift, 1164*55131Storek /*d*/ dl, 1165*55131Storek /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); ) 1166*55131Storek 1167*55131Storek srclin += srclininc; 1168*55131Storek dstlin += dstlininc; 1169*55131Storek } 1170*55131Storek } 1171*55131Storek } 1172*55131Storek else 1173*55131Storek { 1174*55131Storek /* Multiple longwords. */ 1175*55131Storek lm = leftmask[dstleftignore]; 1176*55131Storek rm = rightmask[dstrightignore]; 1177*55131Storek nrm = ~rm; 1178*55131Storek nlm = ~lm; 1179*55131Storek if ( longinc == 1 ) 1180*55131Storek { 1181*55131Storek /* Left to right. */ 1182*55131Storek while ( srclin != srclin2 ) 1183*55131Storek { 1184*55131Storek srclong = srclin; 1185*55131Storek dstlong = dstlin; 1186*55131Storek dstlong2 = dstlong + dstlongs; 1187*55131Storek if ( srcleftignore > dstleftignore ) 1188*55131Storek prevsl = *srclong++ << prevleftshift; 1189*55131Storek else 1190*55131Storek prevsl = 0; 1191*55131Storek if ( dstrightignore != 0 ) 1192*55131Storek --dstlong2; 1193*55131Storek 1194*55131Storek /* Leading edge. */ 1195*55131Storek if ( dstleftignore != 0 ) 1196*55131Storek { 1197*55131Storek ROP_SRCDST( 1198*55131Storek /*op*/ op, 1199*55131Storek /*pre*/ sl = *srclong; 1200*55131Storek dl = *dstlong;, 1201*55131Storek /*s*/ prevsl | ( sl >> currrightshift ), 1202*55131Storek /*d*/ dl, 1203*55131Storek /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); ) 1204*55131Storek prevsl = sl << prevleftshift; 1205*55131Storek ++srclong; 1206*55131Storek ++dstlong; 1207*55131Storek } 1208*55131Storek 1209*55131Storek /* Main rop. */ 1210*55131Storek ROP_SRCDST( 1211*55131Storek /*op*/ op, 1212*55131Storek /*pre*/ while ( dstlong != dstlong2 ) 1213*55131Storek { 1214*55131Storek sl = *srclong;, 1215*55131Storek /*s*/ prevsl | ( sl >> currrightshift ), 1216*55131Storek /*d*/ *dstlong, 1217*55131Storek /*pst*/ prevsl = sl << prevleftshift; 1218*55131Storek ++srclong; 1219*55131Storek ++dstlong; 1220*55131Storek } ) 1221*55131Storek 1222*55131Storek /* Trailing edge. */ 1223*55131Storek if ( dstrightignore != 0 ) 1224*55131Storek { 1225*55131Storek ROP_SRCDST( 1226*55131Storek /*op*/ op, 1227*55131Storek /*pre*/ dl = *dstlong;, 1228*55131Storek /*s*/ prevsl | ( *srclong >> currrightshift ), 1229*55131Storek /*d*/ dl, 1230*55131Storek /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); ) 1231*55131Storek } 1232*55131Storek 1233*55131Storek srclin += srclininc; 1234*55131Storek dstlin += dstlininc; 1235*55131Storek } 1236*55131Storek } 1237*55131Storek else 1238*55131Storek { 1239*55131Storek /* Right to left. */ 1240*55131Storek while ( srclin != srclin2 ) 1241*55131Storek { 1242*55131Storek srclong = srclin; 1243*55131Storek dstlong = dstlin; 1244*55131Storek dstlong2 = dstlong - dstlongs; 1245*55131Storek if ( srcrightignore > dstrightignore ) 1246*55131Storek prevsl = *srclong-- >> currrightshift; 1247*55131Storek else 1248*55131Storek prevsl = 0; 1249*55131Storek if ( dstleftignore != 0 ) 1250*55131Storek ++dstlong2; 1251*55131Storek 1252*55131Storek /* Leading edge. */ 1253*55131Storek if ( dstrightignore != 0 ) 1254*55131Storek { 1255*55131Storek ROP_SRCDST( 1256*55131Storek /*op*/ op, 1257*55131Storek /*pre*/ sl = *srclong; 1258*55131Storek dl = *dstlong;, 1259*55131Storek /*s*/ prevsl | ( sl << prevleftshift ), 1260*55131Storek /*d*/ dl, 1261*55131Storek /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); ) 1262*55131Storek prevsl = sl >> currrightshift; 1263*55131Storek --srclong; 1264*55131Storek --dstlong; 1265*55131Storek } 1266*55131Storek 1267*55131Storek /* Main rop. */ 1268*55131Storek ROP_SRCDST( 1269*55131Storek /*op*/ op, 1270*55131Storek /*pre*/ while ( dstlong != dstlong2 ) 1271*55131Storek { 1272*55131Storek sl = *srclong;, 1273*55131Storek /*s*/ prevsl | ( sl << prevleftshift ), 1274*55131Storek /*d*/ *dstlong, 1275*55131Storek /*pst*/ prevsl = sl >> currrightshift; 1276*55131Storek --srclong; 1277*55131Storek --dstlong; 1278*55131Storek } ) 1279*55131Storek 1280*55131Storek /* Trailing edge. */ 1281*55131Storek if ( dstleftignore != 0 ) 1282*55131Storek { 1283*55131Storek ROP_SRCDST( 1284*55131Storek /*op*/ op, 1285*55131Storek /*pre*/ dl = *dstlong;, 1286*55131Storek /*s*/ prevsl | ( *srclong << prevleftshift ), 1287*55131Storek /*d*/ dl, 1288*55131Storek /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); ) 1289*55131Storek } 1290*55131Storek 1291*55131Storek srclin += srclininc; 1292*55131Storek dstlin += dstlininc; 1293*55131Storek } 1294*55131Storek } 1295*55131Storek } 1296*55131Storek } 1297*55131Storek 1298*55131Storek return 0; 1299*55131Storek } 1300