Annotation of lucent/sys/src/libgnot/gbitblt.c, revision 1.1.1.1

1.1       root        1: #include       <u.h>
                      2: #include       <libc.h>
                      3: #include       <libg.h>
                      4: #include       "/sys/include/gnot.h"
                      5: /*
                      6:  * Compiling bitblt - for each call of gbitblt, generate
                      7:  * machine code for the specific arguments passed in,
                      8:  * then execute that code as a subroutine call.
                      9:  *
                     10:  * The files bb?.h (where ? is replaced by the
                     11:  * architectures single-letter code: v, k, etc., depending
                     12:  * on which of Tmips, Tsparc, etc., is defined) define macros
                     13:  * which define operations on an abstract machine.
                     14:  * If there is no architecture-specific file, bbc.h is used,
                     15:  * which interprets a program with the same operations as
                     16:  * the assumed abstract machine.  See bbc.h for a description
                     17:  * of the machine's registers and operations, and for the
                     18:  * macros that must be defined to make a new bb?.h
                     19:  *
                     20:  * The code will work for bitblts to and from any bitmaps
                     21:  * with ldepths 0, 1, 2, or 3.  Some of those conversions
                     22:  * may be #ifdef'd out, because no Plan 9 code currently
                     23:  * uses them, and the tables take up space.  The converting
                     24:  * bitblts will need work if they are to work with ldepths > 3.
                     25:  *
                     26:  * This file also contains a thorough bitblt tester.
                     27:  * When TEST is defined, a main program is created to
                     28:  * try forward and backward cases for all bitblt opcodes,
                     29:  * first on single pixels, and then on parts of the middle two rows
                     30:  * of random 4-row bitmaps.  If anything fails, it prints information
                     31:  * about the case that failed (or perhaps it will just die,
                     32:  * if bad code has been generated).
                     33:  * The testing programs takes as arguments two numbers: the source
                     34:  * and destination ldepths (both 0 by default).  A -s flag says to
                     35:  * use simpler, repeatable tests.  A -i num flag says how many
                     36:  * iterations to do for each opcode.
                     37:  */
                     38: 
                     39: /* Bitblt cases:
                     40:  * - bitmap overlap sometimes dictates that you go forward (f) through
                     41:  *   the bitmaps, sometimes backwards (b)
                     42:  * - different relative alignments of the source and destination
                     43:  *   starting points within a word require different code:
                     44:  *   the bit offsets may be the same (e), the source may start
                     45:  *   later in the word (g), or the source may start earlier in the word (l)
                     46:  * - when a row of the destination is all within one word (o), better
                     47:  *   code can be generated
                     48:  * - when the object machine has bitfield extraction/insertion instructions,
                     49:  *   it is better to do < 32bit wide bitblts using them (bf)
                     50:  * - if the source and destination bitmaps have different depths,
                     51:  *   it is either and expansion (exp) or a contraction (con) of pixels.
                     52:  *   These two cases aren't further differentiated into f vs. b, etc.
                     53:  */
                     54: 
                     55: /*
                     56:  * To calculate the potential size of the bitblt program, use the following
                     57:  * formulas:
                     58:  *  nonconverting max (bshg): X + 10L + 6S + 2F + 3E + 8LX + 3SX
                     59:  *  converting max (contracting by factor of 8, 32-bit memory accesses):
                     60:  *    X + XT + 46L + 48S + 96T + 64A + 32AX + 2F + 3E + 30LX + 48SX
                     61:  *
                     62:  * where X = Initsd+Extrainit+Iloop+Oloop+Rts  ; XT = Inittab
                     63:  *       E = Emitop  ;  F = Field
                     64:  *       L = load, fetch or store ; LX = extra if pre or post decrement
                     65:  *       S = shift (sha or shb)   ; SX = extra if OR too
                     66:  *       T = Table  ;  A = Assemble  ; AX = Assemblex
                     67:  */
                     68: enum
                     69: {
                     70:        Tfshe   = 0,    /* each of the triples must be in order e, l, g */
                     71:        Tfshl,
                     72:        Tfshg,
                     73: 
                     74:        Tbshe,
                     75:        Tbshl,
                     76:        Tbshg,
                     77: 
                     78:        Toshe,
                     79:        Toshl,
                     80:        Toshg,
                     81: 
                     82:        Tobf,
                     83: 
                     84:        Texp,
                     85: 
                     86:        Tcon,
                     87: 
                     88:        Tlast,          /* total number of cases */
                     89: };
                     90: 
                     91: #ifdef TEST
                     92: /*
                     93:  * globals used for testing
                     94:  */
                     95: int    FORCEFORW;
                     96: int    FORCEBAKW;
                     97: GBitmap        *curdm, *cursm;
                     98: Point  curpt;
                     99: Rectangle curr;
                    100: Fcode  curf;
                    101: void   *mem;
                    102: #endif
                    103: 
                    104: /*
                    105:  * set up to compile -DT$objtype
                    106:  */
                    107: #ifdef Tmips
                    108: #include       "bbv.h"
                    109: #else
                    110: #ifdef T68020
                    111: #include       "bb2.h"
                    112: #else
                    113: #ifdef Tsparc
                    114: #include       "bbk.h"
                    115: #else
                    116: #ifdef T386
                    117: #include       "bb8l.h"
                    118: #else
                    119: #ifdef Thobbit
                    120: #include       "bbcl.h"
                    121: #else
                    122: #include       "bbc.h"
                    123: #endif
                    124: #endif
                    125: #endif
                    126: #endif
                    127: #endif
                    128: 
                    129: /*
                    130:  * bitblt operates a 'word' at a time.
                    131:  * WBITS is the number of bits in a word
                    132:  * LWBITS=log2(WBITS),
                    133:  * W2L is the number of words in a long
                    134:  * WMASK has bits set for the low order word of a long
                    135:  * WType is a pointer to a word
                    136:  * if LENDIAN is true, then left-to-right in bitmap
                    137:  * means low-order-bit to high-order-bit within a word,
                    138:  * otherwise it is high-order-bit to low-order-bit.
                    139:  */
                    140: #ifndef WBITS
                    141: #define WBITS  32
                    142: #define LWBITS 5
                    143: #define        W2L     1
                    144: #define WMASK  ~0UL
                    145: typedef ulong  *WType;
                    146: #endif
                    147: /*
                    148:  * scrshl(v,o) shifts a word v by o bits screen-leftward
                    149:  * scrshr(v,o) shifts a word v by o bits screen-rightward
                    150:  * scrpix(v,i,l) gets the value of pixel i within word v when ldepth is l
                    151:  * scrmask(i,l) has ones for pixel i when ldepth is l
                    152:  */
                    153: #define scrshl(v,o)    (LENDIAN? ((v)>>(o)) : ((v)<<(o)))
                    154: #define scrshr(v,o)    (LENDIAN? ((v)<<(o)) : ((v)>>(o)))
                    155: #define scrpix(v,i,l)  (LENDIAN? (((v)>>((i)<<(l)))&((1<<(1<<(l)))-1)) : (((v)>>(32-(((i)+1)<<(l))))&((1<<(1<<(l)))-1)))
                    156: #define scrmask(i,l)   (LENDIAN? (((1<<(1<<(l)))-1)<<((i)<<(l))) : (((1<<(1<<(l)))-1)<<(32-(((i)+1)<<l))))
                    157: 
                    158: void
                    159: gbitblt(GBitmap *dm, Point pt, GBitmap *sm, Rectangle r, Fcode fcode)
                    160: {
                    161:        int     type;           /* category of bitblt: Tfshe or ... */
                    162:        int     width;          /* width in bits of dst */
                    163:        int     height;         /* height in pixels minus 1 */
                    164:        int     sh;             /* left shift of src to align with dst */
                    165:        int     soff;           /* bit offset of src start point */
                    166:        int     doff;           /* bit offset of dst start point */
                    167:        int     sc;             /* src words used so far */
                    168:        int     dc;             /* dst words used so far */
                    169:        int     le;             /* log expansion factor */
                    170:        int     sspan;          /* words between scanlines in src */
                    171:        int     dspan;          /* words between scanlines in dst */
                    172:        int     sdep;           /* src ldepth */
                    173:        int     ddep;           /* dst ldepth */
                    174:        int     onstack;        /* compiling to stack arena */
                    175:        int     backward;       /* does bitblt have to go backwards? */
                    176:        ulong*  saddr;          /* addr of word in src containing start point */
                    177:        ulong*  daddr;          /* addr of word in dst containing start point */
                    178:        ulong   lmask;          /* affected pixels in leftmost dst word */
                    179:        ulong   rmask;          /* affected pixels in rightmost dst word */
                    180:        Type*   lo;             /* addr in program for beginning of outer loop */
                    181:        Type*   li;             /* addr in program for beginning of inner loop */
                    182:        uchar   *tab;           /* conversion table */
                    183:        int     osiz;           /* size of table entries, in bytes */
                    184:        Type*   memstart;       /* start of program */
                    185:        Type*   p;              /* next free address in program */
                    186:        Type*   fi;             /* pointer to beginning of instrs for Rs f= Rd */
                    187:        int     fin;            /* number of Types to copy after fi */
                    188:        long    v;              /* for use in Emitop macro */
                    189:        int     c;              /* a count */
                    190:        int     fs;             /* if need to fetch source */
                    191:        int     fd;             /* if need to fetch dest */
                    192:        int     b;              /* for expansion: take b bits at a time from src */
                    193:        int     db;             /* number of bits yielded by table lookup */
                    194:        int     dl;             /* log2 number of bytes yielded by table lookup */
                    195:        int     sf;             /* a bit offset in src */
                    196:        int     df;             /* a bit offset in dst */
                    197:        int     firstd;         /* doing first part of dst ? */
                    198:        int     firsts;         /* doing first part of src ? */
                    199:        int     f;              /* int version of fcode */
                    200:        long    tmp;            /* for use by some macros */
                    201:        int     sha;            /* |sh|%32 */
                    202:        int     shb;            /* WBITS-sha, if sha!=0 */
                    203:        int     sfo;            /* bit offset origin (needed if WBITS==8) */
                    204:        Fstr    *pf;
                    205:        Type    arena[Progmaxnoconv];   /* for non-converting bitblts */
                    206: 
                    207:        onstack = bbonstack();
                    208:        gbitbltclip(&dm);
                    209: 
                    210: #ifdef TEST
                    211:        curdm = dm;
                    212:        cursm = sm;
                    213:        curpt = pt;
                    214:        curr = r;
                    215:        curf = fcode;
                    216: #endif
                    217: 
                    218:        width = r.max.x - r.min.x;
                    219:        if(width <= 0)
                    220:                return;
                    221:        height = r.max.y - r.min.y - 1;
                    222:        if(height < 0)
                    223:                return;
                    224:        ddep = dm->ldepth;
                    225:        pt.x <<= ddep;
                    226:        width <<= ddep;
                    227: 
                    228:        sdep = sm->ldepth;
                    229:        r.min.x <<= sdep;
                    230:        r.max.x <<= sdep;
                    231: 
                    232:        dspan = dm->width * W2L;
                    233:        sspan = sm->width * W2L;
                    234: 
                    235:        daddr = (ulong*)((WType)dm->base
                    236:                        + dm->zero*W2L + pt.y*dspan
                    237:                        + (pt.x >> LWBITS));
                    238:        saddr = (ulong*)((WType)sm->base
                    239:                        + sm->zero*W2L + r.min.y*sspan
                    240:                        + (r.min.x >> LWBITS));
                    241: 
                    242:        c = doff = pt.x & (WBITS-1);
                    243:        soff = r.min.x & (WBITS-1);
                    244: 
                    245:        pf = &fstr[(f = fcode&0xF)];
                    246:        fs = pf->fetchs;
                    247:        fd = pf->fetchd;
                    248:        fin = pf->n;
                    249:        fi = (Type *)pf->instr;
                    250: 
                    251:        if(ddep == sdep || !fs) {
                    252: #ifdef TEST
                    253:                if(!FORCEBAKW &&
                    254:                   (FORCEFORW || sm != dm || !fs || saddr > daddr ||
                    255:                    (saddr == daddr && soff > doff)))
                    256:                        backward = 0;
                    257:                else
                    258:                        backward = 1;
                    259: #else
                    260:                if(sm != dm || !fs || saddr > daddr ||
                    261:                  (saddr == daddr && soff > doff))
                    262:                        backward = 0;
                    263:                else
                    264:                        backward = 1;
                    265: #endif
                    266: #ifdef HAVEBF
                    267:                if(width <= WBITS) {
                    268:                        sh = 0;
                    269:                        type = Tobf;
                    270:                        if(backward) {
                    271:                                daddr = (ulong *)((WType)daddr + height*dspan);
                    272:                                saddr = (ulong *)((WType)saddr + height*sspan);
                    273:                        }
                    274:                        goto init;
                    275:                }
                    276: #else
                    277:                if(doff+width <= WBITS) {
                    278:                        type = Toshe;
                    279:                        if(backward) {
                    280:                                daddr = (ulong *)((WType)daddr + height*dspan);
                    281:                                saddr = (ulong *)((WType)saddr + height*sspan);
                    282:                        }
                    283:                }
                    284: #endif
                    285:                else {
                    286:                        if(!backward)
                    287:                                type = Tfshe;
                    288:                        else {
                    289:                                type = Tbshe;
                    290:                                doff = (WBITS-(doff+width)) & (WBITS-1);
                    291:                                soff = (WBITS-(soff+width)) & (WBITS-1);
                    292:                                daddr = (ulong*)((WType)dm->base
                    293:                                        + dm->zero*W2L + (pt.y+height)*dspan
                    294:                                        + ((pt.x + width+(WBITS-1))>>LWBITS));
                    295:                                saddr = (ulong*)((WType)sm->base
                    296:                                        + sm->zero*W2L + (r.max.y-1)*sspan
                    297:                                        + ((r.max.x + (WBITS-1))>>LWBITS));
                    298:                        }
                    299:                }
                    300:                if(fs) {
                    301:                        if((sh = soff - doff) != 0) {
                    302:                                if(sh < 0)
                    303:                                        type += Tbshl-Tbshe;
                    304:                                else
                    305:                                        type += Tbshg-Tbshe;
                    306:                        }
                    307:                } else
                    308:                        sh = 0;
                    309:        } else {
                    310:                if(sdep < 0 || sdep > 3 ||
                    311:                   ddep < 0 || ddep > 3 ||
                    312:                   (tab = tabs[sdep][ddep]) == 0)
                    313:                        return; /* sorry, conversion not enabled */
                    314:                
                    315:                osiz = tabosiz[sdep][ddep];
                    316:                le = ddep - sdep;
                    317:                if(le > 0) {
                    318:                        type = Texp;
                    319:                        sh = soff - (doff >> le);
                    320:                } else {
                    321:                        type = Tcon;
                    322:                        sh = soff - (doff << -le);
                    323:                }
                    324:                onstack = 0;
                    325:                backward = 0;
                    326:        }
                    327: 
                    328:        /* c has original doff (relative to beginning) */
                    329:        lmask = scrshr(WMASK,c);
                    330:        rmask = scrshl(WMASK,(WBITS - ((c+width) & (WBITS-1))))&WMASK;
                    331:        if(!rmask)
                    332:                rmask = WMASK;
                    333:        if(sh != 0) {
                    334:                if(sh > 0)
                    335:                        sha = sh;
                    336:                else
                    337:                        sha = (-sh)&(WBITS-1);
                    338:                shb = WBITS - sha;
                    339:        }
                    340: 
                    341:        /* init: set up constant regs and outer loop */
                    342:     init:
                    343:        if(onstack)
                    344:                memstart = arena;
                    345:        else
                    346:                memstart = (Type*)bbmalloc(Progmax * sizeof(Type));
                    347:        p = memstart;
                    348:        Initsd(saddr,daddr);
                    349:        if(sh) {
                    350:                Initsh(sha,shb);
                    351:        }
                    352:        Extrainit;
                    353: 
                    354:        if(height > 0) {
                    355:                Olabel(height+1);
                    356:                lo = p;
                    357:        }
                    358:        sc = 0;
                    359:        dc = 0;
                    360: 
                    361:        /* emit inner loop */
                    362:        switch(type){
                    363: #ifdef HAVEBF
                    364:        case Tobf:
                    365:                if(fd) {
                    366:                        Bfextu_RdAd(doff,width);
                    367:                }
                    368:                if(fs) {
                    369:                        Bfextu_RsAs(soff,width);
                    370:                }
                    371:                Emitop;
                    372:                Bfins_AdRs(doff,width);
                    373:                break;
                    374: #else
                    375:        case Toshe:
                    376:                /* one word dest, src and dest offsets same (or src not involved) */
                    377:                lmask &= rmask;
                    378:                if(fs) {
                    379:                        Load_Rs(0);
                    380:                }
                    381:                Fetch_Rd(1);
                    382:                Emitop;
                    383:                Ofield(lmask);
                    384:                Store_Rs;
                    385:                break;
                    386: 
                    387:        case Toshl:
                    388:                /* one word dest, src offset less than dest offset */
                    389:                lmask &= rmask;
                    390:                Loadzx_Rt(0);
                    391:                Fetch_Rd(0);
                    392:                Orsha_RsRt;
                    393:                Emitop;
                    394:                Ofield(lmask);
                    395:                Store_Rs;
                    396:                break;
                    397: 
                    398:        case Toshg:
                    399:                /* one word dest, src offset greater than dest offset */
                    400:                lmask &= rmask;
                    401:                if(sha+doff+width > WBITS) {
                    402:                        Load_Rt_P;
                    403:                        Olsha_RsRt;
                    404:                        Loadzx_Rt(0);
                    405:                        Fetch_Rd(0);
                    406:                        Oorrshb_RsRt;
                    407:                        if(backward)
                    408:                                sc--;
                    409:                        else
                    410:                                sc++;
                    411:                } else {
                    412:                        Load_Rt(0);
                    413:                        Fetch_Rd(0);
                    414:                        Olsha_RsRt;
                    415:                }
                    416:                Emitop;
                    417:                Ofield(lmask);
                    418:                Store_Rs;
                    419:                break;
                    420: #endif /* HAVEBF */
                    421: 
                    422:        case Tfshe:
                    423:                /* forward, src and dest offsets same (or src not involved) */
                    424:                Fetch_Rd(0);
                    425:                if(fs) {
                    426:                        Load_Rs_P;
                    427:                        sc++;
                    428:                } else {
                    429:                        Nop;
                    430:                }
                    431:                Emitop;
                    432:                Ofield(lmask);
                    433:                Store_Rs_P;
                    434:                dc++;
                    435:                width -= WBITS - doff;
                    436:        
                    437:                c = width >> LWBITS;
                    438:                if(c) {
                    439:                        if(f == Zero || f == F) {
                    440:                                /* set up Rs outside loop */
                    441:                                Emitop;
                    442:                        }
                    443:                        li = 0;
                    444:                        if(c > 1) {
                    445:                                Ilabel(c);
                    446:                                li = p;
                    447:                        }
                    448:                        if(fd) {
                    449:                                Fetch_Rd(!fs);
                    450:                        }
                    451:                        if(fs) {
                    452:                                Load_Rs_P;
                    453:                                sc += c;
                    454:                        }
                    455:                        if(!(f == Zero || f == F)) {
                    456:                                Emitop;
                    457:                        }
                    458:                        Store_Rs_P;
                    459:                        dc += c;
                    460:                        if(c > 1) {
                    461:                                Iloop(li);
                    462:                        }
                    463:                }
                    464:        
                    465:                if(width & (WBITS-1)) {
                    466:                        if(fs) {
                    467:                                Load_Rs(0);
                    468:                        }
                    469:                        Fetch_Rd(1);
                    470:                        Emitop;
                    471:                        Ofield(rmask);
                    472:                        Store_Rs;
                    473:                }
                    474:                break;
                    475: 
                    476:        case Tfshl:
                    477:                /* forward, src offset less than dest offset */
                    478:                Loadzx_Rt_P;
                    479:                Fetch_Rd(0);
                    480:                Orsha_RsRt;
                    481:                sc++;
                    482:                Emitop;
                    483:                Ofield(lmask);
                    484:                Store_Rs_P;
                    485:                dc++;
                    486:                width -= WBITS - doff;
                    487:        
                    488:                c = width >> LWBITS;
                    489:                if(c) {
                    490:                        li = 0;
                    491:                        if(c > 1) {
                    492:                                Ilabel(c);
                    493:                                li = p;
                    494:                        }
                    495:                        Olshb_RsRt;
                    496:                        Loadzx_Rt_P;
                    497:                        if(fd) {
                    498:                                Fetch_Rd(0);
                    499:                        }
                    500:                        Oorrsha_RsRt;
                    501:                        sc += c;
                    502:                        Emitop;
                    503:                        Store_Rs_P;
                    504:                        dc += c;
                    505:                        if(c > 1) {
                    506:                                Iloop(li);
                    507:                        }
                    508:                }
                    509:        
                    510:                width &= (WBITS-1);
                    511:                if(width) {
                    512:                        Olshb_RsRt;
                    513:                        if(width > sha) {
                    514:                                Loadzx_Rt(0);
                    515:                                Fetch_Rd(0);
                    516:                                Oorrsha_RsRt;
                    517:                        } else {
                    518:                                Fetch_Rd(1);
                    519:                        }
                    520:                        Emitop;
                    521:                        Ofield(rmask);
                    522:                        Store_Rs;
                    523:                }
                    524:                break;
                    525: 
                    526:        case Tfshg:
                    527:                /* forward, src offset greater than dest offset */
                    528:                Load_Rt_P;
                    529:                Olsha_RsRt;
                    530:                Loadzx_Rt_P;
                    531:                Fetch_Rd(0);
                    532:                Oorrshb_RsRt;
                    533:                sc += 2;
                    534:                Emitop;
                    535:                Ofield(lmask);
                    536:                Store_Rs_P;
                    537:                dc++;
                    538:                width -= WBITS - doff;
                    539:        
                    540:                c = width >> LWBITS;
                    541:                if(c) {
                    542:                        li = 0;
                    543:                        if(c > 1) {
                    544:                                Ilabel(c);
                    545:                                li = p;
                    546:                        }
                    547:                        Olsha_RsRt;
                    548:                        Loadzx_Rt_P;
                    549:                        if(fd) {
                    550:                                Fetch_Rd(0);
                    551:                        }
                    552:                        Oorrshb_RsRt;
                    553:                        sc += c;
                    554:                        Emitop;
                    555:                        Store_Rs_P;
                    556:                        dc += c;
                    557:                        if(c > 1) {
                    558:                                Iloop(li);
                    559:                        }
                    560:                }
                    561:        
                    562:                width &= WBITS-1;
                    563:                if(width) {
                    564:                        Olsha_RsRt;
                    565:                        if(width > shb) {
                    566:                                Loadzx_Rt(0);
                    567:                                Fetch_Rd(0);
                    568:                                Oorrshb_RsRt;
                    569:                        } else {
                    570:                                Fetch_Rd(1);
                    571:                        }
                    572:                        Emitop;
                    573:                        Ofield(rmask);
                    574:                        Store_Rs;
                    575:                }
                    576:                break;
                    577: 
                    578:        case Tbshe:
                    579:                /* backward, src and dest offsets same (or src not involved) */
                    580:                Load_Rs_D(0);
                    581:                sc++;
                    582:                Fetch_Rd_D(1);
                    583:                Emitop;
                    584:                Ofield(rmask);
                    585:                Store_Rs;
                    586:                dc++;
                    587:                width -= WBITS - doff;
                    588:        
                    589:                c = width >> LWBITS;
                    590:                if(c) {
                    591:                        li = 0;
                    592:                        if(c > 1) {
                    593:                                Ilabel(c);
                    594:                                li = p;
                    595:                        }
                    596:                        Load_Rs_D(0);
                    597:                        sc += c;
                    598:                        if(fd) {
                    599:                                Fetch_Rd_D(1);
                    600:                                Emitop;
                    601:                                Store_Rs;
                    602:                        } else {
                    603:                                Nop;
                    604:                                Emitop;
                    605:                                Store_Rs_D;
                    606:                        }
                    607:                        dc += c;
                    608:                        if(c > 1) {
                    609:                                Iloop(li);
                    610:                        }
                    611:                }
                    612:        
                    613:                if(width & (WBITS-1)) {
                    614:                        Load_Rs_D(0);
                    615:                        sc++;
                    616:                        Fetch_Rd_D(1);
                    617:                        dc++;
                    618:                        Emitop;
                    619:                        Ofield(lmask);
                    620:                        Store_Rs;
                    621:                }
                    622:                break;
                    623: 
                    624:        case Tbshl:
                    625:                /* backward, src offset less than dest offset */
                    626:                Loadzx_Rt_D(0);
                    627:                Fetch_Rd_D(0);
                    628:                Olsha_RsRt;
                    629:                sc++;
                    630:                Emitop;
                    631:                Ofield(rmask);
                    632:                Store_Rs;
                    633:                dc++;
                    634:                width -= WBITS - doff;
                    635:        
                    636:                c = width >> LWBITS;
                    637:                if(c) {
                    638:                        li = 0;
                    639:                        if(c > 1) {
                    640:                                Ilabel(c);
                    641:                                li = p;
                    642:                        }
                    643:                        Orshb_RsRt;
                    644:                        Loadzx_Rt_D(0);
                    645:                        if(fd) {
                    646:                                Fetch_Rd_D(0);
                    647:                        } else {
                    648:                                Nop;
                    649:                        }
                    650:                        Oorlsha_RsRt;
                    651:                        sc += c;
                    652:                        Emitop;
                    653:                        if(fd) {
                    654:                                Store_Rs;
                    655:                        } else {
                    656:                                Store_Rs_D;
                    657:                        }
                    658:                        dc += c;
                    659:                        if(c > 1) {
                    660:                                Iloop(li);
                    661:                        }
                    662:                }
                    663:        
                    664:                width &= (WBITS-1);
                    665:                if(width) {
                    666:                        Orshb_RsRt;
                    667:                        if(width > sha) {
                    668:                                Load_Rt_D(0);
                    669:                                Fetch_Rd_D(0);
                    670:                                Oorlsha_RsRt;
                    671:                                sc++;
                    672:                        } else {
                    673:                                Fetch_Rd_D(1);
                    674:                        }
                    675:                        dc++;
                    676:                        Emitop;
                    677:                        Ofield(lmask);
                    678:                        Store_Rs;
                    679:                }
                    680:                break;
                    681: 
                    682:        case Tbshg:
                    683:                /* backward, src offset greater than dest offset */
                    684:                Loadzx_Rt_D(0);
                    685:                Fetch_Rd_D(0);
                    686:                Orsha_RsRt;
                    687:                Loadzx_Rt_D(1);
                    688:                Oorlshb_RsRt;
                    689:                sc += 2;
                    690:                Emitop;
                    691:                Ofield(rmask);
                    692:                Store_Rs;
                    693:                dc++;
                    694:                width -= WBITS - doff;
                    695:        
                    696:                c = width >> LWBITS;
                    697:                if(c) {
                    698:                        li = 0;
                    699:                        if(c > 1) {
                    700:                                Ilabel(c);
                    701:                                li = p;
                    702:                        }
                    703:                        Orsha_RsRt;
                    704:                        Loadzx_Rt_D(0);
                    705:                        if(fd) {
                    706:                                Fetch_Rd_D(0);
                    707:                        } else {
                    708:                                Nop;
                    709:                        }
                    710:                        Oorlshb_RsRt;
                    711:                        sc += c;
                    712:                        Emitop;
                    713:                        if(fd) {
                    714:                                Store_Rs;
                    715:                        } else {
                    716:                                Store_Rs_D;
                    717:                        }
                    718:                        dc += c;
                    719:                        if(c > 1) {
                    720:                                Iloop(li);
                    721:                        }
                    722:                }
                    723:        
                    724:                width &= WBITS-1;
                    725:                if(width) {
                    726:                        Orsha_RsRt;
                    727:                        if(width > shb) {
                    728:                                Loadzx_Rt_D(0);
                    729:                                Fetch_Rd_D(0);
                    730:                                sc++;
                    731:                        } else {
                    732:                                Fetch_Rd_D(1);
                    733:                        }
                    734:                        dc++;
                    735:                        Oorlshb_RsRt;
                    736:                        Emitop;
                    737:                        Ofield(lmask);
                    738:                        Store_Rs;
                    739:                }
                    740:                break;
                    741: 
                    742:        case Texp:
                    743:                /* expansion: dest ldepth > src ldepth */
                    744:                if(WBITS == 8) {
                    745:                        b = 8 >> le;
                    746:                        /* db == 8, dl == 0 */
                    747:                } else {
                    748:                        b = (le <= 2) ? 8 : 32 / (1 << le);
                    749:                        db = b << le;
                    750:                        dl = (le <= 2) ? le : 2;
                    751:                }
                    752:                Inittab(tab,osiz);
                    753:        
                    754:                /*
                    755:                 * method:
                    756:                 * load the source a word at a time, into Rt;
                    757:                 * (if there is a shift, use Ru to hold next or last partial word,
                    758:                 *  or, if WBITS == 8, it is  <<8 in Rt)
                    759:                 * take b bits at a time from source and convert via table into Rd
                    760:                 * (each table lookup yields db bits, in 1<<dl bytes);
                    761:                 * assemble into Rs until have WBITS bits;
                    762:                 * fetch dest word into Rd, operate into Rs, store in dest
                    763:                 *
                    764:                 * this code needs reworking for expansion factor > 8
                    765:                 */
                    766: 
                    767:                if(WBITS == 8) {
                    768:                        if(sh == 0) {
                    769:                                Load_Rt_P;
                    770:                                sfo = 24;
                    771:                        } else if(sh > 0) {
                    772:                                Load_Rt_P;
                    773:                                Olsh_RtRt(8);
                    774:                                if((doff+width)>>le  > shb) {
                    775:                                        Loador_Rt_P;
                    776:                                        sc++;
                    777:                                }
                    778:                                /* relevant source bits: Rt[16+sh..23+sh] */
                    779:                                sfo = 16 + sh;
                    780:                        } else {
                    781:                                Load_Rt_P;
                    782:                                /* relevant source bits: Rt[16+(8+sh)..23+(8+sh) */
                    783:                                sfo = 24 + sh;
                    784:                        }
                    785:                        sf = 0;
                    786:                        firstd = 1;
                    787:                } else {
                    788:                        if(sh == 0) {
                    789:                                Load_Rt_P;
                    790:                        } else if(sh > 0) {
                    791:                                Load_Rt_P;
                    792:                                
                    793:                                Olsha_RtRt;
                    794:                                if((doff+width)>>le > shb) {
                    795:                                        Load_Ru_P;
                    796:                                        Oorrshb_RtRu;
                    797:                                        sc++;
                    798:                                }
                    799:                        } else {
                    800:                                Load_Ru_P;
                    801:                                Orsha_RtRu;
                    802:                        }
                    803:                        sf = (soff - sh) & ~(b-1);
                    804:                        firstd = 1;
                    805:                        firsts = 1;
                    806:                }
                    807:                sc++;
                    808:                while(sf < WBITS && width > 0) {
                    809:                        if(WBITS == 8) {
                    810:                                Table_RsRt(sf+sfo,b,0);
                    811:                                sf += b;
                    812:                        } else {
                    813:                                if(firstd)
                    814:                                        df = (sf << le) & (WBITS-1);
                    815:                                else
                    816:                                        df = 0;
                    817:                                while(df < WBITS) {
                    818:                                        Table_RdRt(sf,b,dl);
                    819:                                        if(df==0 || firsts) {
                    820:                                                c = WBITS - (df + db);
                    821:                                                Olsh_RsRd(c);
                    822:                                        } else if(df == WBITS - db) {
                    823:                                                Oor_RsRd;
                    824:                                        } else {
                    825:                                                c = WBITS - (df + db);
                    826:                                                Oorlsh_RsRd(c);
                    827:                                        }
                    828:                                        sf += b;
                    829:                                        df += db;
                    830:                                        firsts = 0;
                    831:                                }
                    832:                        }
                    833:                        Fetch_Rd(1);
                    834:                        Emitop;
                    835:                        if(firstd) {
                    836:                                width -= WBITS - doff;
                    837:                                if(width > 0 && lmask != WMASK) {
                    838:                                        Ofield(lmask);
                    839:                                } else if(width <= 0) {
                    840:                                        lmask &= rmask;
                    841:                                        Ofield(lmask);
                    842:                                }
                    843:                        } else {
                    844:                                width -= WBITS;
                    845:                                if(width < 0) {
                    846:                                        Ofield(rmask);
                    847:                                }
                    848:                        }
                    849:                        Store_Rs_P;
                    850:                        dc++;
                    851:                        firstd = 0;
                    852:                }
                    853:                if(width <= 0)
                    854:                        break;
                    855:        
                    856:                c = width >> (LWBITS+le);
                    857:                if(c) {
                    858:                        li = 0;
                    859:                        if(c > 1) {
                    860:                                Ilabel(c);
                    861:                                li = p;
                    862:                        }
                    863:                        if(WBITS == 8) {
                    864:                                Olsh_RtRt(8);
                    865:                                Loador_Rt_P;
                    866:                        } else {
                    867:                                if(sh == 0) {
                    868:                                        Load_Rt_P;
                    869:                                } else if(sh > 0) {
                    870:                                        Olsha_RtRu;
                    871:                                        Load_Ru_P;
                    872:                                        Oorrshb_RtRu;
                    873:                                } else {
                    874:                                        Olshb_RtRu;
                    875:                                        Load_Ru_P;
                    876:                                        Oorrsha_RtRu;
                    877:                                }
                    878:                        }
                    879:                        sc += c;
                    880:                        for(sf = 0; sf < WBITS;) {
                    881:                                if(WBITS == 8) {
                    882:                                        Table_RsRt(sf+sfo,b,0);
                    883:                                        sf += b;
                    884:                                } else {
                    885:                                        for(df = 0; df < WBITS;) {
                    886:                                                Table_RdRt(sf,b,dl);
                    887:                                                Assemblex(df,db);
                    888:                                                sf += b;
                    889:                                                df += db;
                    890:                                        }
                    891:                                }
                    892:                                if(fd) {
                    893:                                        Fetch_Rd(1);
                    894:                                }
                    895:                                Emitop;
                    896:                                Store_Rs_P;
                    897:                                dc += c;
                    898:                        }
                    899:                        if(c > 1) {
                    900:                                Iloop(li);
                    901:                        }
                    902:                }
                    903:                width -= c << (LWBITS+le);
                    904:                if(width <= 0)
                    905:                        break;
                    906: 
                    907:                if(WBITS == 8) {
                    908:                        if(sh == 0) {
                    909:                                Load_Rt_P;
                    910:                                sc++;
                    911:                        } else if(sh > 0) {
                    912:                                Olsh_RtRt(8);
                    913:                                if(width>>le  > shb) {
                    914:                                        Loador_Rt_P;
                    915:                                        sc++;
                    916:                                }
                    917:                        } else {
                    918:                                Olsh_RtRt(8);
                    919:                                if(width>>le > sha) {
                    920:                                        Loador_Rt_P;
                    921:                                        sc++;
                    922:                                }
                    923:                        }
                    924:                } else {
                    925:                        if(sh == 0) {
                    926:                                Load_Rt_P;
                    927:                                sc++;
                    928:                        } else if(sh > 0) {
                    929:                                Olsha_RtRu;
                    930:                                if(width>>le  > shb) {
                    931:                                        Load_Ru_P;
                    932:                                        Oorrshb_RtRu;
                    933:                                        sc++;
                    934:                                }
                    935:                        } else {
                    936:                                Olshb_RtRu;
                    937:                                if(width>>le > sha) {
                    938:                                        Load_Ru_P;
                    939:                                        Oorrsha_RtRu;
                    940:                                        sc++;
                    941:                                }
                    942:                        }
                    943:                }
                    944:                for(sf = 0; sf < WBITS && width > 0; ) {
                    945:                        if(WBITS == 8) {
                    946:                                Table_RsRt(sf+sfo,b,0);
                    947:                                sf += b;
                    948:                        } else {
                    949:                                for(df = 0; df < WBITS;) {
                    950:                                        Table_RdRt(sf,b,dl);
                    951:                                        Assemblex(df,db);
                    952:                                        sf += b;
                    953:                                        df += db;
                    954:                                }
                    955:                        }
                    956:                        Fetch_Rd(1);
                    957:                        Emitop;
                    958:                        width -= WBITS;
                    959:                        if(width < 0) {
                    960:                                Ofield(rmask);
                    961:                        }
                    962:                        Store_Rs_P;
                    963:                        dc++;
                    964:                }
                    965:                break;
                    966: 
                    967:        case Tcon:
                    968:                /* contraction: dest ldepth < src ldepth */
                    969:                db = 8 >> -le;
                    970:                Inittab(tab,osiz);
                    971:        
                    972:                /*
                    973:                 * method:
                    974:                 * load the source a word at a time, into Rt;
                    975:                 * (if there is a shift, use Ru to hold next or last partial word,
                    976:                 * or, if WBITS==8, it is <<8 in Rt)
                    977:                 * take 8 bits at a time from source and convert via table into Rd
                    978:                 * (each table lookup yields db bits, in 1 byte);
                    979:                 * assemble into Rs until have WBITS bits (takes several src words);
                    980:                 * fetch dest word into Rd, operate into Rs, store in dest
                    981:                 *
                    982:                 * Something should be done to improve this code, but
                    983:                 * it isn't used much.
                    984:                 */
                    985: 
                    986:                if(sh < 0) {
                    987:                        c = (-sh)/WBITS;
                    988:                        sh += c*WBITS;
                    989:                        if(WBITS == 8) sfo = 24 + sh;
                    990:                } else {
                    991:                        c = 0;
                    992:                        if(WBITS == 8) sfo = sh ? 16 + sh : 24;
                    993:                }
                    994:                firstd = 1;
                    995:                firsts = 1;
                    996:                for(df = c*db*(4/W2L); df < WBITS && df < doff + width; ) {
                    997:                        c = (doff + width - df) << -le;
                    998:                        /* c = number of source bits needed to fill rest */
                    999:                        if(WBITS == 8) {
                   1000:                                if(sh == 0) {
                   1001:                                        Load_Rt_P;
                   1002:                                        sc++;
                   1003:                                } else if(sh > 0) {
                   1004:                                        if(firsts) {
                   1005:                                                Load_Rt_P;
                   1006:                                                Olsh_RtRt(8);
                   1007:                                                sc++;
                   1008:                                        } else {
                   1009:                                                Olsh_RtRt(8);
                   1010:                                        }
                   1011:                                        if(shb < c) {
                   1012:                                                Loador_Rt_P;
                   1013:                                                sc++;
                   1014:                                        }
                   1015:                                } else {
                   1016:                                        if(firsts) {
                   1017:                                                Load_Rt_P;
                   1018:                                                sc++;
                   1019:                                        } else {
                   1020:                                                Olsh_RtRt(8);
                   1021:                                                if(sha < c) {
                   1022:                                                        Loador_Rt_P;
                   1023:                                                        sc++;
                   1024:                                                }
                   1025:                                        }
                   1026:                                }
                   1027:                        } else {
                   1028:                                if(sh == 0) {
                   1029:                                        Load_Rt_P;
                   1030:                                        sc++;
                   1031:                                } else if(sh > 0) {
                   1032:                                        if(firsts) {
                   1033:                                                Load_Rt_P;
                   1034:                                                Olsha_RtRt;
                   1035:                                                sc++;
                   1036:                                        } else {
                   1037:                                                Olsha_RtRu;
                   1038:                                        }
                   1039:                                        if(shb < c) {
                   1040:                                                Load_Ru_P;
                   1041:                                                sc++;
                   1042:                                                Oorrshb_RtRu;
                   1043:                                        }
                   1044:                                } else {
                   1045:                                        if(!firsts) {
                   1046:                                                Olshb_RtRu;
                   1047:                                        }
                   1048:                                        if(sha < c) {
                   1049:                                                Load_Ru_P;
                   1050:                                                sc++;
                   1051:                                                if(firsts) {
                   1052:                                                        Orsha_RtRu;
                   1053:                                                } else {
                   1054:                                                        Oorrsha_RtRu;
                   1055:                                                }
                   1056:                                        }
                   1057:                                }
                   1058:                        }
                   1059:                        firsts = 0;
                   1060:                        if(WBITS == 8) {
                   1061:                                Table_RdRt(sfo,8,0);
                   1062:                                if(firstd) {
                   1063:                                        Olsh_RsRd(8-(df+db));
                   1064:                                } else {
                   1065:                                        Assemble(df,db);
                   1066:                                }
                   1067:                                df += db;
                   1068:                                firstd = 0;
                   1069:                        } else {
                   1070:                                for(sf = 0; sf < WBITS; ) {
                   1071:                                        Table_RdRt(sf,8,0);
                   1072:                                        if(firstd) {
                   1073:                                                c = WBITS-(df+db);
                   1074:                                                Olsh_RsRd(c);
                   1075:                                        } else {
                   1076:                                                Assemble(df,db);
                   1077:                                        }
                   1078:                                        df += db;
                   1079:                                        sf += 8;
                   1080:                                        firstd = 0;
                   1081:                                }
                   1082:                        }
                   1083:                }
                   1084:                Fetch_Rd(1);
                   1085:                Emitop;
                   1086:                width -= WBITS - doff;
                   1087:                if(width > 0 && lmask != WMASK) {
                   1088:                                Ofield(lmask);
                   1089:                } else if(width <= 0) {
                   1090:                        lmask &= rmask;
                   1091:                        Ofield(lmask);
                   1092:                }
                   1093:                Store_Rs_P;
                   1094:                dc++;
                   1095:                if(width <= 0)
                   1096:                        break;
                   1097:        
                   1098:                c = width >> LWBITS;
                   1099:                if(c) {
                   1100:                        li = 0;
                   1101:                        if(c > 1) {
                   1102:                                Ilabel(c);
                   1103:                                li = p;
                   1104:                        }
                   1105:                        for(df = 0; df < WBITS; ) {
                   1106:                                if(WBITS == 8) {
                   1107:                                        if(sh == 0) {
                   1108:                                                Load_Rt_P;
                   1109:                                        } else {
                   1110:                                                Olsh_RtRt(8);
                   1111:                                                Loador_Rt_P;
                   1112:                                        }
                   1113:                                        sc += c;
                   1114:                                        Table_RdRt(sfo,8,0);
                   1115:                                        Assemble(df,db);
                   1116:                                        df += db;
                   1117:                                } else {
                   1118:                                        if(sh == 0) {
                   1119:                                                Load_Rt_P;
                   1120:                                        } else if(sh > 0) {
                   1121:                                                Olsha_RtRu;
                   1122:                                                Load_Ru_P;
                   1123:                                                Oorrshb_RtRu;
                   1124:                                        } else {
                   1125:                                                Olshb_RtRu;
                   1126:                                                Load_Ru_P;
                   1127:                                                Oorrsha_RtRu;
                   1128:                                        }
                   1129:                                        sc += c;
                   1130:                                        for(sf = 0; sf < WBITS; ) {
                   1131:                                                Table_RdRt(sf,8,0);
                   1132:                                                Assemblex(df,db);
                   1133:                                                df += db;
                   1134:                                                sf += 8;
                   1135:                                        }
                   1136:                                }
                   1137:                        }
                   1138:                        if(fd) {
                   1139:                                Fetch_Rd(1);
                   1140:                        }
                   1141:                        Emitop;
                   1142:                        Store_Rs_P;
                   1143:                        dc += c;
                   1144:                        if(c > 1) {
                   1145:                                Iloop(li);
                   1146:                        }
                   1147:                }
                   1148:        
                   1149:                width -= c << LWBITS;
                   1150:                if(width <= 0)
                   1151:                        break;
                   1152:        
                   1153:                for(df = 0; df < width; ) {
                   1154:                        c = (width - df) << -le;
                   1155:                        if(WBITS == 8) {
                   1156:                                if(sh == 0) {
                   1157:                                        Load_Rt_P;
                   1158:                                        sc++;
                   1159:                                } else if(sh > 0) {
                   1160:                                        Olsh_RtRt(8);
                   1161:                                        if(shb < c) {
                   1162:                                                sc++;
                   1163:                                                Loador_Rt_P;
                   1164:                                        }
                   1165:                                } else {
                   1166:                                        Olsh_RtRt(8);
                   1167:                                        if(sha < c) {
                   1168:                                                Loador_Rt_P;
                   1169:                                                sc++;
                   1170:                                        }
                   1171:                                }
                   1172:                                Table_RdRt(sfo,8,0);
                   1173:                                Assemble(df,db);
                   1174:                                df += db;
                   1175:                        } else {
                   1176:                                if(sh == 0) {
                   1177:                                        Load_Rt_P;
                   1178:                                        sc++;
                   1179:                                } else if(sh > 0) {
                   1180:                                        Olsha_RtRu;
                   1181:                                        if(shb < c) {
                   1182:                                                Load_Ru_P;
                   1183:                                                Oorrshb_RtRu;
                   1184:                                                sc++;
                   1185:                                        }
                   1186:                                } else {
                   1187:                                        Olshb_RtRu;
                   1188:                                        if(sha < c) {
                   1189:                                                Load_Ru_P;
                   1190:                                                Oorrsha_RtRu;
                   1191:                                                sc++;
                   1192:                                        }
                   1193:                                }
                   1194:                                for(sf = 0; sf < 32; ) {
                   1195:                                        Table_RdRt(sf,8,0);
                   1196:                                        Assemble(df,db);
                   1197:                                        df += db;
                   1198:                                        sf += 8;
                   1199:                                }
                   1200:                        }
                   1201:                }
                   1202:                Fetch_Rd(1);
                   1203:                Emitop;
                   1204:                Ofield(rmask);
                   1205:                Store_Rs_P;
                   1206:                dc++;
                   1207:                break;
                   1208: 
                   1209:        }
                   1210: 
                   1211:        /* finish outer loop, put in rts, and execute */
                   1212: 
                   1213:        if(height > 0) {
                   1214:                if(backward)
                   1215:                        c = (dc - dspan) * (WBITS/8);
                   1216:                else
                   1217:                        c = (dspan - dc) * (WBITS/8);
                   1218:                if(c) {
                   1219:                        Add_Ad(c);
                   1220:                }
                   1221:                if(fs) {
                   1222:                        if(backward)
                   1223:                                c = (sc - sspan) * (WBITS/8);
                   1224:                        else
                   1225:                                c = (sspan - sc) * (WBITS/8);
                   1226:                        if(c) {
                   1227:                                Add_As(c);
                   1228:                        }
                   1229:                }
                   1230:                Oloop(lo);
                   1231:        }
                   1232:        Orts;
                   1233: #ifdef TEST
                   1234:        if(onstack && p - memstart > Progmaxnoconv)
                   1235:                print("Increase Progmaxnoconv to at least %d!\n", p - memstart);
                   1236:        else if(p - memstart > Progmax)
                   1237:                print("Increase Progmax to at least %d!\n", p - memstart);
                   1238:        mem = memstart;
                   1239: #endif
                   1240:        bbexec((void*)memstart, (p-memstart)*sizeof(Type), onstack);
                   1241: }
                   1242: 
                   1243: #ifdef TEST
                   1244: void   prprog(void);
                   1245: GBitmap *bb1, *bb2;
                   1246: ulong  *src, *dst, *xdst, *xans;
                   1247: int    swds, dwds;
                   1248: long   ticks;
                   1249: int    timeit;
                   1250: 
                   1251: #ifdef BYTEREV
                   1252: ulong
                   1253: byterev(ulong v)
                   1254: {
                   1255:        return (v>>24)|((v>>8)&0x0000FF00)|((v<<8)&0x00FF0000)|(v<<24);
                   1256: }
                   1257: #endif
                   1258: #ifdef T386
                   1259: long _clock;
                   1260: #endif
                   1261: 
                   1262: long
                   1263: func(int f, long s, int sld, long d, int dld)
                   1264: {
                   1265:        long a;
                   1266:        int sh, i, db, sb;
                   1267: 
                   1268:        db = 1 << dld;
                   1269:        sb = 1 << sld;
                   1270:        sh = db - sb;
                   1271:        if(sh > 0) {
                   1272:                a = s;
                   1273:                for(i = sb; i<db; i += sb){
                   1274:                        a <<= sb;
                   1275:                        s |= a;
                   1276:                }
                   1277:        } else if(sh < 0)
                   1278:                s >>= -sh;
                   1279: 
                   1280:        switch(f){
                   1281:        case Zero:      d = 0;                  break;
                   1282:        case DnorS:     d = ~(d|s);             break;
                   1283:        case DandnotS:  d = d & ~s;             break;
                   1284:        case notS:      d = ~s;                 break;
                   1285:        case notDandS:  d = ~d & s;             break;
                   1286:        case notD:      d = ~d;                 break;
                   1287:        case DxorS:     d = d ^ s;              break;
                   1288:        case DnandS:    d = ~(d&s);             break;
                   1289:        case DandS:     d = d & s;              break;
                   1290:        case DxnorS:    d = ~(d^s);             break;
                   1291:        case S:         d = s;                  break;
                   1292:        case DornotS:   d = d | ~s;             break;
                   1293:        case D:         d = d;                  break;
                   1294:        case notDorS:   d = ~d | s;             break;
                   1295:        case DorS:      d = d | s;              break;
                   1296:        case F:         d = ~0;                 break;
                   1297:        }
                   1298: 
                   1299:        d &= ((1<<db)-1);
                   1300:        return d;
                   1301: }
                   1302: 
                   1303: void
                   1304: run(int fr, int to, int w, int op)
                   1305: {
                   1306:        int i, j, f, t, fy, ty;
                   1307:        extern long *_clock;
                   1308: 
                   1309:        fr += bb2->r.min.x;
                   1310:        to += bb1->r.min.x;
                   1311:        fy = bb2->r.min.y + 1;
                   1312:        ty = bb1->r.min.y + 1;
                   1313:        if(timeit) {
                   1314:                memcpy(dst, xdst, dwds * sizeof(long));
                   1315:                ticks -= *_clock;
                   1316:                gbitblt(bb1, Pt(to,ty), bb2, Rect(fr,fy,fr+w,fy+2), op);
                   1317:                ticks += *_clock;
                   1318:                return;
                   1319:        }
                   1320:        f = fr;
                   1321:        t = to;
                   1322:        memcpy(dst, xdst, dwds * sizeof(long));
                   1323:        for(i=0; i<w; i++) {
                   1324:                gbitblt(bb1, Pt(t,ty), bb2, Rect(f,fy,f+1,fy+1), op);
                   1325:                gbitblt(bb1, Pt(t,ty+1), bb2, Rect(f,fy+1,f+1,fy+2), op);
                   1326:                f++;
                   1327:                t++;
                   1328:        }
                   1329:        memcpy(xans, dst, dwds * sizeof(long));
                   1330: 
                   1331:        memcpy(dst, xdst, dwds * sizeof(long));
                   1332:        gbitblt(bb1, Pt(to,ty), bb2, Rect(fr,fy,fr+w,fy+2), op);
                   1333: 
                   1334:        if(memcmp(xans, dst, dwds * sizeof(long))) {
                   1335:                /*
                   1336:                 * print src and dst row offset, width in bits, and forw/back
                   1337:                 * then print for each of the four rows: the source (s),
                   1338:                 * the dest (d), the good value of the answer (g),
                   1339:                 * and the actual bad value of the answer (b)
                   1340:                 */
                   1341:                print("fr=%d to=%d w=%d fb=%d%d\n",
                   1342:                        fr, to, w, FORCEFORW, FORCEBAKW);
                   1343:                print("dst bitmap b %#lux, z %d, w %d, ld %d, r [%d,%d][%d,%d]\n",
                   1344:                        bb1->base, bb1->zero, bb1->width, bb1->ldepth,
                   1345:                        bb1->r.min.x, bb1->r.min.y, bb1->r.max.x, bb1->r.max.y);
                   1346:                print("src bitmap b %#lux, z %d, w %d, ld %d, r [%d,%d][%d,%d]\n",
                   1347:                        bb2->base, bb2->zero, bb2->width, bb2->ldepth,
                   1348:                        bb2->r.min.x, bb2->r.min.y, bb2->r.max.x, bb2->r.max.y);
                   1349:                for(j=0; 7*j < dwds; j++) {
                   1350:                        print("\ns");
                   1351:                        for(i=0; i<7 && 7*j+i < dwds; i++)
                   1352:                                print(" %.8lux", src[7*j + i]);
                   1353:                        print("\nd");
                   1354:                        for(i=0; i<7 && 7*j+i < dwds; i++)
                   1355:                                print(" %.8lux", xdst[7*j + i]);
                   1356:                        print("\ng");
                   1357:                        for(i=0; i<7 && 7*j+i < dwds; i++)
                   1358:                                print(" %.8lux", xans[7*j + i]);
                   1359:                        print("\nb");
                   1360:                        for(i=0; i<7 && 7*j+i < dwds; i++)
                   1361:                                print(" %.8lux", dst[7*j + i]);
                   1362:                        print("\n");
                   1363:                }
                   1364:                prprog();
                   1365:        }
                   1366: }
                   1367: 
                   1368: void
                   1369: main(int argc, char *argv[])
                   1370: {
                   1371:        int f, t, w, i, sld, dld, op, iters, simple;
                   1372:        ulong s, d, spix, dpix, apix, fpix, m, *ps, *pd;
                   1373:        Point sorg, dorg;
                   1374:        GBitmap *bs, *bd;
                   1375:        long seed;
                   1376:        char *ct;
                   1377: 
                   1378:        sld = 0;
                   1379:        dld = 0;
                   1380:        timeit = 0;
                   1381:        iters = 200;
                   1382:        simple = 0;
                   1383:        ARGBEGIN {
                   1384:        case 'i':
                   1385:                iters = atoi(ARGF());
                   1386:                break;
                   1387:        case 's':
                   1388:                simple = 1;
                   1389:                break;
                   1390:        case 't':
                   1391:                timeit = 1;
                   1392:                ct = ARGF();
                   1393:                if(ct)
                   1394:                        iters = atoi(ct);
                   1395:                break;
                   1396:        } ARGEND
                   1397:        if(argc > 0)
                   1398:                sld = atoi(argv[0]);
                   1399:        if(argc > 1)
                   1400:                dld = atoi(argv[1]);
                   1401:        if(sld < 0 || sld > 3 || dld < 0 || dld > 3 ||
                   1402:            (sld != dld && !tabs[sld][dld])){
                   1403:                print("conversion from ldepth %d to %d not enabled\n",
                   1404:                        sld, dld);
                   1405:                exits(0);
                   1406:        }
                   1407:        if(!timeit && !simple) {
                   1408:                seed = time(0);
                   1409:                print("seed %lux\n", seed); srand(seed);        /**/
                   1410:        }
                   1411: 
                   1412:        print("sld %d dld %d\n", sld, dld);
                   1413:        op = 1/*Zero*/;
                   1414: 
                   1415:        /* bitmaps for 1-bit tests */
                   1416:        bd = gballoc(Rect(0,0,32,1), dld);
                   1417:        bs = gballoc(Rect(0,0,32,1), sld);
                   1418:        for(i=0; i<bs->width; i++)
                   1419:                bs->base[i] = lrand();
                   1420: 
                   1421:        /* bitmaps for rect tests */
                   1422:        if(simple) {
                   1423:                dorg = Pt(0,0);
                   1424:                sorg = Pt(0,0);
                   1425:        } else {
                   1426:                dorg = Pt(nrand(63)-31,nrand(63)-31);
                   1427:                sorg = Pt(nrand(63)-31,nrand(63)-31);
                   1428:        }
                   1429:        bb1 = gballoc(Rpt(dorg,add(dorg,Pt(200,4))), dld);
                   1430:        bb2 = gballoc(Rpt(sorg,add(sorg,Pt(200,4))), sld);
                   1431:        dwds = bb1->width * Dy(bb1->r);
                   1432:        swds = bb2->width * Dy(bb2->r);
                   1433:        dst = bb1->base;
                   1434:        src = bb2->base;
                   1435:        xdst = malloc(dwds * sizeof(long));
                   1436:        xans =  malloc(dwds * sizeof(long));
                   1437:        for(i=0; i<swds; i++)
                   1438:                src[i] = lrand();
                   1439:        for(i=0; i<dwds; i++)
                   1440:                xdst[i] = lrand();
                   1441: loop:
                   1442:        print("Op %d\n", op);
                   1443:        if(!timeit) {
                   1444:                print("one pixel\n");
                   1445:                ps = bs->base;
                   1446:                pd = bd->base;
                   1447:                FORCEFORW = 1;
                   1448:                FORCEBAKW = 0;
                   1449:                for(i=0; i<1000; i++, FORCEFORW = !FORCEFORW, FORCEBAKW = !FORCEBAKW) {
                   1450:                        f = nrand(32 >> sld);
                   1451:                        t = nrand(32 >> dld);
                   1452:                        s = lrand();
                   1453:                        d = lrand();
                   1454:                        ps[0] = s;
                   1455:                        pd[0] = d;
                   1456: #ifdef BYTEREV
                   1457:                        spix = scrpix(byterev(s),f,sld);
                   1458:                        dpix = scrpix(byterev(d),t,dld);
                   1459: #else
                   1460:                        spix = scrpix(s,f,sld);
                   1461:                        dpix = scrpix(d,t,dld);
                   1462: #endif
                   1463:                        apix = func(op, spix, sld, dpix, dld);
                   1464:                        gbitblt(bd, Pt(t,0), bs, Rect(f,0,f+1,1), op);
                   1465:                        if(ps[0] != s) {
                   1466:                                print("bb src %.8lux %.8lux %d %d\n", ps[0], s, f, t);
                   1467:                                exits("error");
                   1468:                        }
                   1469:                        m = scrmask(t,dld);
                   1470: #ifdef BYTEREV
                   1471:                        m = byterev(m);
                   1472: #endif
                   1473:                        if((pd[0] & ~m) != (d & ~m)) {
                   1474:                                        print("bb dst1 %.8lux %.8lux\n",
                   1475:                                                s, d);
                   1476:                                        print("bb      %.8lux %.8lux %d %d\n",
                   1477:                                                ps[0], pd[0], f, t);
                   1478:                                        prprog();
                   1479:                                        exits("error");
                   1480:                        }
                   1481: #ifdef BYTEREV
                   1482:                        fpix = scrpix(byterev(pd[0]),t,dld);
                   1483: #else
                   1484:                        fpix = scrpix(pd[0],t,dld);
                   1485: #endif
                   1486:                        if(apix != fpix) {
                   1487:                                print("bb dst2 %.8lux %.8lux\n",
                   1488:                                        s, d);
                   1489:                                print("bb      %.8lux %.8lux %d %d\n",
                   1490:                                        ps[0], pd[0], f, t);
                   1491:                                print("bb      %.8lux %.8lux %.8lux %.8lux\n",
                   1492:                                        spix, dpix, apix, fpix);
                   1493:                                prprog();
                   1494:                                exits("error");
                   1495:                        }
                   1496:                }
                   1497:        }
                   1498: 
                   1499:        print("for\n");
                   1500:        FORCEFORW = 1;
                   1501:        FORCEBAKW = 0;
                   1502: 
                   1503:        for(i=0; i<iters; i++) {
                   1504:                f = nrand(64);
                   1505:                t = nrand(64);
                   1506:                w = nrand(130);
                   1507:                run(f, t, w, op);
                   1508:        }
                   1509: 
                   1510:        if(sld == dld) {
                   1511:                print("bak\n");
                   1512:                FORCEFORW = 0;
                   1513:                FORCEBAKW = 1;
                   1514:        
                   1515:                for(i=0; i<iters; i++) {
                   1516:                        f = nrand(64);
                   1517:                        t = nrand(64);
                   1518:                        w = nrand(130);
                   1519:                        run(f, t, w, op);
                   1520:                }
                   1521:        }
                   1522: 
                   1523:        if(op < F) {
                   1524:                op++;
                   1525:                goto loop;
                   1526:        }
                   1527:        if(timeit)
                   1528:                print("time: %d ticks\n", ticks);
                   1529:        exits(0);
                   1530: }
                   1531: 
                   1532: 
                   1533: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.