Annotation of ntddk/src/video/displays/vga/i386/cblt.asm, revision 1.1

1.1     ! root        1:         page    ,132
        !             2:         title   BitBLT
        !             3: ;---------------------------Module-Header------------------------------;
        !             4: ; Module Name: cblt.asm
        !             5: ;
        !             6: ; Copyright (c) 1992 Microsoft Corporation
        !             7: ;-----------------------------------------------------------------------;
        !             8:         .386
        !             9: 
        !            10: ;!!! All the code to convert from color to mono in this file needs to
        !            11: ;!!! be deleted.  We don't need to do it anymore.
        !            12: 
        !            13: 
        !            14: 
        !            15: 
        !            16: ifndef  DOS_PLATFORM
        !            17:         .model  small,c
        !            18: else
        !            19: ifdef   STD_CALL
        !            20:         .model  small,c
        !            21: else
        !            22:         .model  small,pascal
        !            23: endif;  STD_CALL
        !            24: endif;  DOS_PLATFORM
        !            25: 
        !            26:         assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
        !            27:         assume fs:nothing,gs:nothing
        !            28: 
        !            29:         .code
        !            30: 
        !            31: _TEXT$01   SEGMENT DWORD USE32 PUBLIC 'CODE'
        !            32:            ASSUME  CS:FLAT, DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
        !            33: 
        !            34:         .xlist
        !            35:         include stdcall.inc         ; calling convention cmacros
        !            36: 
        !            37:         include i386\cmacFLAT.inc   ; FLATland cmacros
        !            38:         include i386\display.inc    ; Display specific structures
        !            39:         include i386\ppc.inc        ; Pack pel conversion structure
        !            40:         include i386\bitblt.inc     ; General definitions
        !            41:         include i386\ropdefs.inc    ; Rop definitions
        !            42:         include i386\egavga.inc   ; EGA register definitions
        !            43:         include i386\devdata.inc
        !            44:         .list
        !            45: 
        !            46:         extrn   roptable:byte
        !            47: ;-----------------------------Public-Routine----------------------------;
        !            48: ; CBLT
        !            49: ;
        !            50: ; Compile a BLT onto the stack.
        !            51: ;
        !            52: ; Entry:
        !            53: ;       EDI --> memory on stack to receive BLT program
        !            54: ;       EBP --> fr structure
        !            55: ; Returns:
        !            56: ;       Nothing
        !            57: ;-----------------------------------------------------------------------;
        !            58: 
        !            59: fr      equ     [ebp]                   ;For consistancy with other sources
        !            60: 
        !            61: cProc   cblt
        !            62: 
        !            63:         subttl  Compile - Outer Loop
        !            64:         page
        !            65: 
        !            66: ; If converting a packed pel format to planer format, add the code
        !            67: ; to convert one source scan into planer format
        !            68: 
        !            69:         test    fr.ppcBlt.fb,PPC_NEEDED
        !            70:         jz      no_pack_pel_conversion
        !            71:         mov     al,I_MOV_EBP_DWORD_I    ;Give conversion routine access
        !            72:         stosb                           ;  to conversion data
        !            73:         lea     eax,fr.ppcBlt
        !            74:         stosd
        !            75:         mov     al,I_CALL_DISP32        ;Call the static conversion code
        !            76:         stosb
        !            77:         mov     eax,fr.ppcBlt.pfnConvert
        !            78:         sub     eax,edi
        !            79:         sub     eax,4                   ;4 for length of displacement
        !            80:         stosd
        !            81: no_pack_pel_conversion:
        !            82: 
        !            83: ; Initialize plane indicator.
        !            84: 
        !            85:         mov     ax,(PLANE_1*256)+I_MOV_BL_BYTE_I
        !            86:         stosw
        !            87: 
        !            88: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !            89: ; Create the outerloop code.  The first part of this code will save
        !            90: ; the scan line count register, destination pointer, and the source
        !            91: ; pointer (if there is a source).
        !            92: ;
        !            93: ; The generated code should look like:
        !            94: ;
        !            95: ;       push    ecx             ;Save scan line count
        !            96: ;       push    edi             ;Save destination pointer
        !            97: ; <     push    esi     >       ;Save source pointer
        !            98: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !            99: 
        !           100:         mov     fr.pNextPlane,edi       ;Save address of next plane code
        !           101:         mov     bl,fr.the_flags
        !           102:         mov     ax,I_PUSH_ECX_PUSH_EDI  ;Save scan line count, destination ptr
        !           103:         stosw
        !           104:         test    bl,F0_SRC_PRESENT       ;Is a source needed?
        !           105:         jz      cblt_2020               ;  No
        !           106:         mov     al,I_PUSH_ESI           ;  Yes, save source pointer
        !           107:         stosb
        !           108: cblt_2020:
        !           109: 
        !           110:         subttl  Compile - Plane Selection
        !           111:         page
        !           112: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           113: ; If the destination device is color and the display is involved in
        !           114: ; the blt, then the color plane selection logic must be added in.
        !           115: ; If the destination is monochrome, then no plane logic is needed.
        !           116: ; Two color memory bitmaps will not cause the plane selection logic
        !           117: ; to be copied.
        !           118: ;
        !           119: ; The generated code should look like:
        !           120: ;
        !           121: ; <     push    ebx     >       ;Save plane index
        !           122: ; <     plane selection >       ;Select plane
        !           123: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           124: 
        !           125:         test    bl,F0_DEST_IS_COLOR     ;Is the destination color?
        !           126:         jz      cblt_pattern_fetch      ;  No
        !           127:         mov     al,I_PUSH_EBX           ;Save plane index
        !           128:         stosb
        !           129:         test    bl,F0_DEST_IS_DEV+F0_SRC_IS_DEV ;Is the device involved?
        !           130:         jz      cblt_pattern_fetch              ;  No
        !           131: 
        !           132: ; The device is involved for a color blt.  Copy the logic for selecting
        !           133: ; the read/write plane
        !           134: 
        !           135:         mov     esi,offset FLAT:cps     ;--> plane select logic
        !           136:         mov     ecx,LENGTH_CPS
        !           137:         rep     movsb
        !           138: 
        !           139:         subttl  Compile - Pattern Fetch
        !           140:         page
        !           141: 
        !           142: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           143: ; Set up any pattern fetch code that might be needed.
        !           144: ; The pattern code has many fixups, so it isn't taken from a
        !           145: ; template.  It is just stuffed as it is created.
        !           146: ;
        !           147: ; Entry:  None
        !           148: ;
        !           149: ; Exit:   DH = pattern
        !           150: ;
        !           151: ; Uses:   AX,BX,CX,DH,flags
        !           152: ;
        !           153: ; For solid color brushes:
        !           154: ;
        !           155: ;     mov     dh,color
        !           156: ;
        !           157: ; For monochrome brushes:
        !           158: ;
        !           159: ;     mov     ebx,12345678h       ;Load address of the brush
        !           160: ;     mov     dh,7[ebx]           ;Get next brush byte
        !           161: ;     mov     al,[12345678h]      ;Get brush index
        !           162: ;     add     al,direction        ;Add displacement to next byte (+1/-1)
        !           163: ;     and     al,00000111b        ;Keep it in range
        !           164: ;     mov     [12345678h],al      ;Store displacement to next plane's bits
        !           165: ;
        !           166: ; For color brushes:
        !           167: ;
        !           168: ;     mov     ebx,12345678h       ;Load address of the brush
        !           169: ;     mov     dh,7[bx]            ;Get next brush byte
        !           170: ;     mov     al,[12345678h]      ;Get brush index
        !           171: ;     add     al,SIZE Pattern     ;Add displacement to next plane's bits
        !           172: ;     and     al,00011111b        ;Keep it within the brush
        !           173: ;     mov     [12345678h],al      ;Store displacement to next plane's bits
        !           174: ;
        !           175: ;     The address of the increment for the brush is saved for
        !           176: ;     the plane looping logic if the destination is a three plane
        !           177: ;     color device.  For a four plane color device, the AND
        !           178: ;     automatically handles the wrap and no fixup is needed at
        !           179: ;     the end of the plane loop.
        !           180: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           181: 
        !           182: cblt_pattern_fetch:
        !           183:         test    bl,F0_PAT_PRESENT       ;Is a pattern needed?
        !           184:         jz      cblt_initial_byte_fetch ;  No, skip pattern code
        !           185:         mov     al,fr.brush_accel       ;Solid color needs no fetch logic
        !           186:         test    al,SOLID_BRUSH
        !           187:         jz      cblt_nonsolid_brush
        !           188:         and     al,MM_ALL
        !           189:         shl     eax,16
        !           190:         mov     ax,I_TEST_BL_BYTE_I
        !           191:         stosd
        !           192:         dec     edi                     ;Was only a three byte instruction
        !           193:         mov     eax,I_SETNZ_DH
        !           194:         stosd
        !           195:         dec     edi                     ;Was only a three byte instruction
        !           196:         mov     ax,I_NEG_DH
        !           197:         stosw
        !           198:         jmp     short cblt_initial_byte_fetch
        !           199: 
        !           200: cblt_nonsolid_brush:
        !           201:         mov     al,I_MOV_EBX_DWORD_I    ;mov ebx,lpPBrush
        !           202:         stosb
        !           203:         mov     eax,fr.lpPBrush
        !           204:         stosd
        !           205:         mov     ax,I_MOV_DH_EBX_DISP8   ;mov dh,pat_row[ebx]
        !           206:         stosw
        !           207:         mov     edx,edi                 ;Save address of the brush index
        !           208:         mov     al,fr.pat_row           ;Set initial pattern row
        !           209:         mov     bh,00000111b            ;Set brush index mask
        !           210:         and     al,bh                   ;Make sure it's legal at start
        !           211:         stosb
        !           212:         mov     al,I_MOV_AL_MEM
        !           213:         stosb                           ;mov al,[xxxxxxxx]
        !           214:         mov     eax,edx
        !           215:         stosd
        !           216:         mov     al,I_ADD_AL_BYTE_I
        !           217:         mov     ah,direction            ;Set brush index
        !           218:         errnz   INCREASE-1              ;Must be a 1
        !           219:         errnz   DECREASE+1              ;Must be a -1
        !           220: 
        !           221:         test    bl,F0_COLOR_PAT         ;Color pattern required?
        !           222:         jz      cblt_2060               ;  No
        !           223:         mov     fr.addr_brush_index,edx ;Save address of brush index
        !           224:         mov     ah,SIZE_PATTERN         ;Set increment to next plane
        !           225:         mov     bh,00011111b            ;Set brush index mask
        !           226: 
        !           227: cblt_2060:
        !           228:         stosw
        !           229:         mov     ah,bh                   ;and al,BrushIndexMask
        !           230:         mov     al,I_AND_AL_BYTE_I
        !           231:         stosw
        !           232:         mov     al,I_MOV_MEM_AL
        !           233:         stosb                           ;mov [xxxxxxxx],al
        !           234:         mov     eax,edx
        !           235:         stosd
        !           236: 
        !           237: 
        !           238:         subttl  Compile - Initial Byte Fetch
        !           239:         page
        !           240: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           241: ; Create the initial byte code.  This may consist of one or two
        !           242: ; initial fetches (if there is a source), followed by the required
        !           243: ; logic action.  The code should look something like:
        !           244: ;
        !           245: ; BLTouterloop:
        !           246: ;   <       mov     bp,mask_p   >   ;Load phase mask for entire loop
        !           247: ;   <       xor     bh,bh       >   ;Clear previous unused bits
        !           248: ;
        !           249: ; ; Perform first byte fetch
        !           250: ;
        !           251: ;   <       lodsb               >   ;Get source byte
        !           252: ;   <       color<==>mono munge >   ;Color <==> mono conversion
        !           253: ;   <       phase alignment     >   ;Align bits as needed
        !           254: ;
        !           255: ; ; If an optional second fetch is needed, perform one
        !           256: ;
        !           257: ;   <       lodsb               >   ;Get source byte
        !           258: ;   <       color to mono munge >   ;Color to mono munging
        !           259: ;   <       phase alignment     >   ;Align bits as needed
        !           260: ;
        !           261: ;           logical action          ;Perform logical action required
        !           262: ;
        !           263: ;           mov     ah,[edi]        ;Get destination
        !           264: ;           and     ax,cx           ;Saved unaltered bits
        !           265: ;           or      al,ah           ;  and mask in altered bits
        !           266: ;           stosb                   ;Save the result
        !           267: ;
        !           268: ; The starting address of the first fetch/logical combination will be
        !           269: ; saved so that the code can be copied later instead of recreating it
        !           270: ; (if there are two fecthes, the first fetch will not be copied)
        !           271: ;
        !           272: ; The length of the code up to the masking for altered/unaltered bits
        !           273: ; will be saved so the code can be copied into the inner loop.
        !           274: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           275: 
        !           276: cblt_initial_byte_fetch:
        !           277:         xor     dx,dx
        !           278:         or      dh,fr.phase_h           ;Is the phase 0? (also get the phase)
        !           279:         jz      cblt_3020               ;  Yes, so no phase alignment needed
        !           280:         mov     al,I_SIZE_OVERRIDE
        !           281:         stosb
        !           282:         mov     al,I_MOV_BP_WORD_I      ;Set up the phase mask
        !           283:         stosb
        !           284:         mov     ax,fr.mask_p            ;Place the mask into the instruction
        !           285:         stosw
        !           286:         mov     ax,I_XOR_BH_BH          ;Clear previous unused bits
        !           287:         stosw
        !           288: 
        !           289: cblt_3020:
        !           290:         mov     fr.start_fl,edi             ;Save starting address of action
        !           291:         test    fr.the_flags,F0_SRC_PRESENT ;Is there a source?
        !           292:         jz      cblt_4000                   ;  No, don't generate fetch code
        !           293: 
        !           294: 
        !           295: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           296: ; Generate the required sequence of instructions for a fetch
        !           297: ; sequence.  Only the minimum code required is generated.
        !           298: ;
        !           299: ; The code generated will look something like the following:
        !           300: ;
        !           301: ; BLTfetch:
        !           302: ;   <       lodsb                 > ;Get the next byte
        !           303: ;   <       color munging         > ;Mono <==> color munging
        !           304: ;
        !           305: ; ; If the phase alignment isn't zero, then generate the minimum
        !           306: ; ; phase alignment needed.  RORs or ROLs will be generated,
        !           307: ; ; depending on the fastest sequence.  If the phase alignment
        !           308: ; ; is zero, than no phase alignment code will be generated.
        !           309: ;
        !           310: ;   <       ror     al,n          > ;Rotate as needed
        !           311: ;   <       mov     ah,al         > ;Mask used, unused bits
        !           312: ;   <       and     ax,bp         > ;(BP) = phase mask
        !           313: ;   <       or      al,bh         > ;Mask in old unused bits
        !           314: ;   <       mov     bh,ah         > ;Save new unused bits
        !           315: ;
        !           316: ;
        !           317: ; The nice thing about the above is it is possible for the fetch to
        !           318: ; degenerate into a simple LODSB instruction.
        !           319: ;
        !           320: ; Currently:      BL = the_flags
        !           321: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           322: 
        !           323: cblt_3040:
        !           324:         mov     fr.moore_flags,0        ;Assume REP cannot be used
        !           325:         shl     bl,1                    ;Color conversion?
        !           326:         jnc     cblt_3180               ;  No, we were lucky this time
        !           327:         errnz   F0_GAG_CHOKE-10000000b
        !           328:         js      cblt_3100               ;Mono ==> color
        !           329:         errnz   F0_COLOR_PAT-01000000b
        !           330: 
        !           331:         subttl  Compile - Initial Byte Fetch, Color ==> Mono
        !           332:         page
        !           333: 
        !           334: ; !!!  Color to mono should not be needed anymore since the Engine will
        !           335: ; !!! not be calling me to do it!  Let's remove this code!
        !           336: 
        !           337: 
        !           338: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           339: ; Generate the code to go from color to mono.  Color to mono
        !           340: ; should map all colors that are background to 1's (white), and
        !           341: ; all colors which aren't background to 0's (black).  If the source
        !           342: ; is the display, then the color compare register will be used.
        !           343: ; If the source is a memory bitmap, each byte of the plane will be
        !           344: ; XORed with the color from that plane, with the results all ORed
        !           345: ; together.  The final result will then be complemented, giving
        !           346: ; the desired result.
        !           347: ;
        !           348: ; The generated code for bitmaps should look something like:
        !           349: ;
        !           350: ;     mov     al,next_plane[esi]            ;Get C1 byte of source
        !           351: ;     mov     ah,2*next_plane[esi]          ;Get C2 byte of source
        !           352: ;     xor     ax,C1BkColor+(C2BkColor*256)  ;XOR with plane's color
        !           353: ;     or      ah,al                         ;OR the result
        !           354: ;     mov     al,3*next_plane[esi]          ;Get C3 byte of source
        !           355: ;     xor     al,C3BkColor
        !           356: ;     or      ah,al
        !           357: ;     lodsb                                 ;Get C0 source
        !           358: ;     xor     al,C0BkColor                  ;XOR with C0BkColor
        !           359: ;     or      al,ah                         ;OR with previous result
        !           360: ;     not     al                            ;NOT to give 1's where background
        !           361: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           362: 
        !           363: cblt_3070:
        !           364:         test    bl,F0_SRC_IS_DEV SHL 1  ;If device, use color compare register
        !           365:         jz      cblt_3080               ;It's a memory bitmap
        !           366: 
        !           367: ; We're in luck, the color compare register can be used.  Set up
        !           368: ; for a color read, and use the normal mono fetch code.  Show the
        !           369: ; innerloop code that the REP instruction can be used if this is
        !           370: ; a source copy.
        !           371: 
        !           372:         mov     fr.moore_flags,F1_REP_OK
        !           373:         mov     ecx,edx                 ;Save dx
        !           374:         mov     ah,fr.bkColor.SPECIAL   ;Get SPECIAL byte of color
        !           375:         and     ah,MM_ALL
        !           376:         mov     al,GRAF_COL_COMP        ;Stuff color into compare register
        !           377:         mov     dx,EGA_BASE+GRAF_ADDR
        !           378:         out     dx,ax
        !           379:         mov     ax,GRAF_CDC             ;Set Color Don't Care register
        !           380:         out     dx,ax
        !           381:         mov     ax,M_COLOR_READ SHL 8 + GRAF_MODE
        !           382:         out     dx,ax
        !           383:         mov     edx,ecx
        !           384:         jmp     cblt_3180               ;Go generate mono fetch code
        !           385: 
        !           386: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           387: ;       The source is a memory bitmap.  Generate the code to compute
        !           388: ;       the result of the four planes:
        !           389: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           390: 
        !           391: cblt_3080:
        !           392:         mov     ax,I_MOV_AL_ESI_DISP32
        !           393:         stosw
        !           394:         mov     eax,fr.src.next_plane
        !           395:         stosd
        !           396:         mov     ebx,eax                 ;Save plane width
        !           397:         mov     ax,I_MOV_AH_ESI_DISP32
        !           398:         stosw
        !           399:         lea     eax,[ebx*2]
        !           400:         stosd
        !           401:         mov     al,I_SIZE_OVERRIDE
        !           402:         stosb
        !           403:         mov     al,I_XOR_AX_WORD_I
        !           404:         stosb
        !           405:         mov     al,fr.bkColor.SPECIAL   ;get the color index byte
        !           406:         mov     ah,al                   ;have the same in AH
        !           407:         and     ax,(C2_BIT shl 8) or C1_BIT
        !           408:         neg     al
        !           409:         sbb     al,al                   ;al will be 0ffh if plane bit is 1
        !           410:         neg     ah
        !           411:         sbb     ah,ah                   ;ah wil be 0ffh if plane bit is 1
        !           412:         stosw
        !           413:         mov     ax,I_OR_AH_AL
        !           414:         stosw
        !           415: 
        !           416:         mov     ax,I_MOV_AL_ESI_DISP32
        !           417:         stosw
        !           418:         lea     eax,[ebx*2][ebx]
        !           419:         stosd
        !           420:         mov     al,I_XOR_AL_BYTE_I
        !           421:         mov     ah,fr.bkColor.SPECIAL
        !           422:         and     ah,C3_BIT
        !           423:         neg     ah
        !           424:         sbb     ah,ah
        !           425:         stosw
        !           426:         mov     ax,I_OR_AH_AL
        !           427:         stosw
        !           428: 
        !           429:         mov     ax,I_LODSB+(I_XOR_AL_BYTE_I*256)
        !           430:         stosw
        !           431:         mov     al,fr.bkColor.SPECIAL
        !           432:         shr     al,1                    ;get C0_BIT into carry
        !           433:         sbb     al,al                   ;make it 0ffh if bit was set
        !           434:         .errnz C0_BIT - 00000001b
        !           435:         stosb                           ;save the modified value
        !           436:         errnz   pcol_C0
        !           437:         mov     ax,I_OR_AL_AH
        !           438:         stosw
        !           439:         mov     ax,I_NOT_AL
        !           440:         stosw
        !           441:         jmp     cblt_3240               ;Go create logic code
        !           442: 
        !           443:         subttl  Compile - Initial Byte Fetch, Mono ==> Color
        !           444:         page
        !           445: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           446: ; The conversion is mono to color.  Generate the code to
        !           447: ; do the conversion, and generate the table which will
        !           448: ; have the conversion values in it.
        !           449: ;
        !           450: ; When going from mono to color, 1 bits are considered to be
        !           451: ; the background color, and 0 bits are considered to be the
        !           452: ; foreground color.
        !           453: ;
        !           454: ; For each plane:
        !           455: ;
        !           456: ;   If the foreground=background=1, then 1 can be used in
        !           457: ;   place of the source.
        !           458: ;
        !           459: ;   If the foreground=background=0, then 0 can be used in
        !           460: ;   place of the source.
        !           461: ;
        !           462: ;   If the foreground=0 and background=1, then the source
        !           463: ;   can be used as is.
        !           464: ;
        !           465: ;   If the foreground=1 and background=0, then the source
        !           466: ;   must be complemented before using.
        !           467: ;
        !           468: ;   Looks like a boolean function to me.
        !           469: ;
        !           470: ; An AND mask and an XOR mask will be computed for each plane,
        !           471: ; based on the above.  The source will then be processed against
        !           472: ; the table.  The generated code should look like
        !           473: ;
        !           474: ;         lodsb
        !           475: ;         and     al,[xxxx]
        !           476: ;         xor     al,[xxxx+1]
        !           477: ;
        !           478: ; The table for munging the colors as stated above should look like:
        !           479: ;
        !           480: ;      BackGnd   ForeGnd    Result    AND  XOR
        !           481: ;         1         1         1        00   FF
        !           482: ;         0         0         0        00   00
        !           483: ;         1         0         S        FF   00
        !           484: ;         0         1     not S        FF   FF
        !           485: ;
        !           486: ; From this, it can be seen that the XOR mask is the same as the
        !           487: ; foreground color.  The AND mask is the XOR of the foreground
        !           488: ; and the background color.  Not too hard to compute
        !           489: ;
        !           490: ; It can also be seen that if the background color is white and the
        !           491: ; foreground (text) color is black, then the conversion needn't be
        !           492: ; generated (it just gives the source).  This is advantageous since
        !           493: ; it will allow phased aligned source copies to use REP MOVSW.
        !           494: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           495: 
        !           496: ; Check to see if the background color is black, and the
        !           497: ; foreground color is white.  This can be determined by
        !           498: ; looking at the accelerator flags in the physical color.
        !           499: 
        !           500: cblt_3100:
        !           501:         mov     ah,fr.TextColor.SPECIAL
        !           502:         xor     ah,MONO_BIT             ;Map black to white
        !           503:         and     ah,fr.bkColor.SPECIAL   ;AND in background color
        !           504:         cmp     ah,MONO_BIT+ONES_OR_ZEROS
        !           505:         jne     cblt_3110               ;Not black
        !           506:         mov     fr.moore_flags,F1_REP_OK+F1_NO_MUNGE ;Show reps as ok, no color munge table
        !           507:         jmp     short cblt_3180         ;Normal fetch required
        !           508: 
        !           509: ; No way around it.  The color conversion table and code
        !           510: ; must be generated.
        !           511: 
        !           512: cblt_3110:
        !           513:         mov     cl,fr.bkColor.SPECIAL   ;Get BackGround Colors
        !           514:         mov     ch,fr.TextColor.SPECIAL ;Get ForeGround Colors
        !           515:         xor     cl,ch
        !           516:         shr     cl,1
        !           517:         sbb     al,al
        !           518:         shr     ch,1
        !           519:         sbb     ah,ah
        !           520:         mov     word ptr fr.ajM2C.(pcol_C0 * 2),ax
        !           521:         shr     cl,1
        !           522:         sbb     al,al
        !           523:         shr     ch,1
        !           524:         sbb     ah,ah
        !           525:         mov     word ptr fr.ajM2C.(pcol_C1 * 2),ax
        !           526:         shr     cl,1
        !           527:         sbb     al,al
        !           528:         shr     ch,1
        !           529:         sbb     ah,ah
        !           530:         mov     word ptr fr.ajM2C.(pcol_C2 * 2),ax
        !           531:         shr     cl,1
        !           532:         sbb     al,al
        !           533:         shr     ch,1
        !           534:         sbb     ah,ah
        !           535:         mov     word ptr fr.ajM2C.(pcol_C3 * 2),ax
        !           536:         errnz   <TextColor - bkColor - 4>
        !           537: 
        !           538: ;       Generate the code for munging the color as stated above.
        !           539: 
        !           540:         mov     ax,I_LODSB
        !           541:         stosb                           ;lodsb
        !           542:         mov     ax,I_AND_AL_MEM         ;and al,[xxxx]
        !           543:         stosw
        !           544:         lea     eax,fr.ajM2C            ;  Set address of color munge
        !           545:         stosd
        !           546:         mov     ebx,eax                 ;  Save address
        !           547:         mov     ax,I_XOR_AL_MEM         ;xor al,[xxxx]
        !           548:         stosw
        !           549:         lea     eax,1[ebx]              ;  Set address of XOR mask
        !           550:         stosd
        !           551:         jmp     short cblt_3240
        !           552: 
        !           553: ; Just need to generate the normal fetch sequence (lodsb)
        !           554: 
        !           555: cblt_3180:
        !           556:         mov     al,I_LODSB              ;Generate source fetch
        !           557:         stosb
        !           558: 
        !           559:         subttl  Compile - Phase Alignment
        !           560:         page
        !           561: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           562: ; Generate the phase alignment if any.
        !           563: ;
        !           564: ; It is assumed that AL contains the source byte
        !           565: ;
        !           566: ; Currently:
        !           567: ;     DH = phase alignment
        !           568: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           569: 
        !           570: cblt_3240:
        !           571:         mov     ecx,edi                 ;end of fetch code
        !           572:         sub     ecx,fr.start_fl         ;start of fetch code
        !           573:         mov     fr.cFetchCode,ecx       ;save size of fetch code
        !           574:         xor     ecx,ecx                 ;Might have garbage in it
        !           575:         or      dh,dh                   ;Any phase alignment?
        !           576:         jz      cblt_3280               ;  No, so skip alignment
        !           577:         mov     cl,dh                   ;Get horizontal phase for rotating
        !           578:         mov     ax,I_ROL_AL_N           ;Assume rotate left n times
        !           579:         cmp     cl,5                    ;4 or less rotates?
        !           580:         jc      cblt_3260               ;  Yes
        !           581:         neg     cl                      ;  No, compute ROR count
        !           582:         add     cl,8
        !           583:         mov     ah,HIGH I_ROR_AL_N
        !           584:         errnz   <(LOW I_ROL_AL_N)-(LOW I_ROR_AL_N)>
        !           585: 
        !           586: cblt_3260:
        !           587:         stosw                           ;Stuff the phase alignment rotates
        !           588:         mov     al,cl                   ;  then the phase alignment code
        !           589:         stosb
        !           590: 
        !           591: ; Do not generate phase masking if there is only 1 src And only 1 dest byte.
        !           592: ; This is not just an optimization, see comments where these flags are set.
        !           593: 
        !           594:         xor     ch,ch
        !           595:         mov     al,fr.first_fetch
        !           596:         and     al,FF_ONLY_1_SRC_BYTE or FF_ONLY_1_DEST_BYTE
        !           597:         xor     al,FF_ONLY_1_SRC_BYTE or FF_ONLY_1_DEST_BYTE
        !           598:         jz      cblt_3280
        !           599:         mov     esi,offset FLAT:phase_align
        !           600:         mov     ecx,PHASE_ALIGN_LEN
        !           601:         rep     movsb
        !           602: 
        !           603: cblt_3280:
        !           604:         test    fr.first_fetch,FF_TWO_INIT_FETCHES  ;Generate another fetch?
        !           605:         jz      cblt_4000                           ;  No
        !           606: 
        !           607: ; A second fetch needs to be stuffed.  Copy the one just created.
        !           608: 
        !           609:         mov     esi,edi                 ;Get start of fetch logic
        !           610:         xchg    esi,fr.start_fl         ;Set new start, get old
        !           611:         mov     ecx,edi                 ;Compute how long fetch is
        !           612:         sub     ecx,esi                 ;  and move the bytes
        !           613:         rep     movsb
        !           614: 
        !           615:         subttl  Compile - ROP Generation
        !           616:         page
        !           617: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           618: ; Create the logic action code
        !           619: ;
        !           620: ; The given ROP will be converted into the actual code that
        !           621: ; performs the ROP.
        !           622: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           623: 
        !           624: ; Copy the ROP template into the BLT
        !           625: 
        !           626: cblt_4000:
        !           627:         mov     ax,fr.operands          ;Get back rop data
        !           628:         mov     bl,ah                   ;Get count of number of bits to move
        !           629:         and     ebx,HIGH ROPLength
        !           630:         shr     ebx,2
        !           631:         movzx   ecx,roptable+256[ebx] ;Get length into cx
        !           632:         errnz   ROPLength-0001110000000000b
        !           633: 
        !           634:         mov     ebx,eax                 ;Get offset of the template
        !           635:         and     ebx,ROPOffset
        !           636:         lea     esi,roptable[ebx]       ;--> the template
        !           637:         rep     movsb                   ;Move the template
        !           638: 
        !           639: cblt_4020:
        !           640:         mov     bx,ax                   ;Keep rop around
        !           641:         or      ah,ah                   ;Generate a negate?
        !           642:         jns     cblt_4040               ; No
        !           643:         mov     ax,I_NOT_AL
        !           644:         stosw
        !           645: 
        !           646: public cblt_4040
        !           647: cblt_4040:
        !           648:         mov     fr.end_fl,edi           ;Save end of fetch/logic operation
        !           649: 
        !           650:         subttl  Compile - Mask And Save
        !           651:         page
        !           652: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           653: ; Generate code to mask and save the result.  If the destination
        !           654: ; isn't in a register, it will be loaded from ES:[DI] first.  The
        !           655: ; mask operation will then be performed, and the result stored.
        !           656: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           657: 
        !           658:         mov     ax,I_MOV_AH_DEST        ; ah,[edi]
        !           659:         stosw
        !           660: 
        !           661:         mov     esi,offset FLAT:masked_store;Move rest of masked store template
        !           662:         movsb                           ;Move size override
        !           663:         movsd
        !           664:         movsw
        !           665:         errnz   MASKED_STORE_LEN-7      ;Must be seven bytes long
        !           666:         mov     ax,fr.start_mask        ;Stuff start mask into
        !           667:         xchg    ah,al                   ;  the template
        !           668: 
        !           669:         mov     [edi][MASKED_STORE_MASK],ax
        !           670: 
        !           671:         mov     fr.end_fls,edi          ;Save end of fetch/logic/store operation
        !           672: 
        !           673:         subttl  Compile - Inner Loop Generation
        !           674:         page
        !           675: ;-----------------------------------------------------------------------;
        !           676: ; Now for the hard stuff; The inner loop (said with a "gasp!").
        !           677: ;
        !           678: ; If there is no innerloop, then no code will be generated
        !           679: ; (now that's fast!).
        !           680: ;-----------------------------------------------------------------------;
        !           681: 
        !           682: cblt_5000:
        !           683:         mov     edx,fr.inner_loop_count ;Get the loop count
        !           684:         or      dx,dx                   ;If the count is null
        !           685:         jz      cblt_6000               ;  don't generate any code
        !           686: 
        !           687: ;!!! Since we no longer pass in the old style rops, we can;t enable this code
        !           688: ;!!! and shold remove/alter it someday.  Besides, most of it is in special.asm
        !           689: if 0                                    ;!!!
        !           690: 
        !           691: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           692: ; We have something for a loop count.  If this just happens to be
        !           693: ; a source copy (S) with a phase of zero, then the innerloop degenerates
        !           694: ; to a repeated MOVSB instruction.  This little special case is
        !           695: ; worth checking for and handling!
        !           696: ;
        !           697: ; Also, if this is one of the special cases {P, Pn, DDx, DDxn}, then it
        !           698: ; will also be special cased since these are all pattern fills (pattern,
        !           699: ; not pattern, 0, 1).
        !           700: ;
        !           701: ; The same code can be shared for these routines, with the exception
        !           702: ; that patterns use a STOSx instruction instead of a MOVSx instruction
        !           703: ; and need a value loaded in AX
        !           704: ;
        !           705: ; So we lied a little.  If a color conversion is going on, then the
        !           706: ; REP MOVSB might not be usable.  If the F1_REP_OK flag has been set, then
        !           707: ; we can use it.  The F1_REP_OK flag will be set for a mono ==> color
        !           708: ; conversion where the background color is white and the foreground
        !           709: ; color is black, or for a color ==> mono conversion with the screen
        !           710: ; as the source (the color compare register will be used).
        !           711: ;
        !           712: ; For the special cases {P, Pn, DDx, DDxn}, color conversion is
        !           713: ; not possible, so ignore it for them.
        !           714: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           715: 
        !           716:         mov     bl,byte ptr fr.Rop      ;Get the raster op
        !           717:         test    bl,EPS_INDEX            ;Can this be special cased?
        !           718:         jnz     cblt_5500               ;  No
        !           719:         errnz   <HIGH EPS_INDEX>
        !           720:         errnz   SPEC_PARSE_STR_INDEX    ;The special case index must be 0
        !           721: 
        !           722:         test    bl,EPS_OFF              ;Is this a source copy
        !           723:         jz      cblt_5040               ;  Yes
        !           724:         errnz   <SOURCE_COPY AND 11b>   ;Offset for source copy must be 0
        !           725: 
        !           726: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           727: ; We should have one of the following fill operations:
        !           728: ;
        !           729: ;   P       - Pattern
        !           730: ;   Pn      - NOT pattern
        !           731: ;   DDx     - 0 fill
        !           732: ;   DDxn    - 1 fill
        !           733: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           734: 
        !           735:         mov     ax,I_MOV_AL_0FFH        ;Assume this is a 0 or 1 fill
        !           736:         test    bl,01h                  ;Is it 0 or 1 fill?
        !           737:         jz      cblt_5020               ;  Yes, initialize AX with 0FFh
        !           738:         mov     ax,I_MOV_AL_DH          ;  No,  initialize AX with pattern
        !           739: 
        !           740:         errnz      PAT_COPY-0000000000100001b
        !           741:         errnz   NOTPAT_COPY-0000000000000001b
        !           742:         errnz    FILL_BLACK-0000000001000010b
        !           743:         errnz    FILL_WHITE-0000000001100010b
        !           744: 
        !           745: cblt_5020:
        !           746:         stosw
        !           747:         mov     ax,I_MOV_AH_AL
        !           748:         stosw
        !           749:         mov     si,I_STOSB              ;Set up for repeated code processor
        !           750:         test    bl,LogPar               ;If Pn or 0, then complement pattern
        !           751:         jnz     cblt_5060               ;  Is just P or 1
        !           752:         errnz   <HIGH LogPar>
        !           753:         mov     al,I_SIZE_OVERRIDE
        !           754:         stosb
        !           755:         mov     ax,I_NOT_AX             ;  Is Pn or 0, complement AX
        !           756:         stosw
        !           757:         jmp     short cblt_5060
        !           758: 
        !           759:         errnz      PAT_COPY-00100001b
        !           760:         errnz   NOTPAT_COPY-00000001b
        !           761:         errnz    FILL_BLACK-01000010b
        !           762:         errnz    FILL_WHITE-01100010b
        !           763: 
        !           764: 
        !           765: ; This is a source copy.  The phase must be zero for a source copy
        !           766: ; to be condensed into a REP MOVSx.
        !           767: 
        !           768: cblt_5040:
        !           769:         test    fr.phase_h,0FFh         ;Is horizontal phase zero?
        !           770:         jnz     cblt_5500               ;  No, can't condense source copy
        !           771:         mov     si,I_MOVSB              ;Set register for moving bytes
        !           772: 
        !           773: ; For a color conversion, F1_REP_OK must be set.
        !           774: 
        !           775:         test    fr.the_flags,F0_GAG_CHOKE   ;Color conversion?
        !           776:         jz      cblt_5060                   ;  No, rep is OK to use
        !           777:         test    fr.moore_flags,F1_REP_OK    ;  Yes, can we rep it?
        !           778:         jz      cblt_5500                   ;    No, do it the hard way
        !           779: 
        !           780: 
        !           781: ;-----------------------------------------------------------------------;
        !           782: ; This is a source copy or pattern fill.  Process an odd byte with
        !           783: ; a MOVSB or STOSB, then process the rest of the bytes with a REP
        !           784: ; MOVSW or a REP STOSW.  If the REP isn't needed, leave it out.
        !           785: ;
        !           786: ; Don't get caught on this like I did!  If the direction of the
        !           787: ; BLT is from right to left (decrementing addresses), then both
        !           788: ; the source and destination pointers must be decremented by one
        !           789: ; so that the next two bytes are processed, not the next byte and
        !           790: ; the byte just processed.  Also, after all words have been processed,
        !           791: ; the source and destination pointers must be incremented by one to
        !           792: ; point to the last byte (since the last MOVSW or STOSW would have
        !           793: ; decremented both pointers by 2).
        !           794: ;
        !           795: ; If the target machine is an 8086, then it would be well worth the
        !           796: ; extra logic to align the fields on word boundaries before the MOVSxs
        !           797: ; if at all possible.
        !           798: ;
        !           799: ; The generated code should look something like:
        !           800: ;
        !           801: ; WARP8:                               ;This code for moving left to right
        !           802: ;         movsb                        ;Process an odd byte
        !           803: ;         mov     ecx,gl_inner_loop_count/2 ;Set word count
        !           804: ;         rep                          ;If a count, then repeat is needed
        !           805: ;         movsw                        ;Move words until done
        !           806: ;
        !           807: ;
        !           808: ; WARP8:                               ;This code for moving left to right
        !           809: ;         movsb                        ;Process an odd byte
        !           810: ;         dec     si                   ;adjust pointer for moving words
        !           811: ;         dec     di
        !           812: ;         mov     ecx,gl_inner_loop_count/2 ;Set word count
        !           813: ;         rep                          ;If a count, then repeat is needed
        !           814: ;         movsw                        ;Move words until done
        !           815: ;         inc     si                   ;adjust since words were moved
        !           816: ;         inc     di
        !           817: ;
        !           818: ;
        !           819: ; Of course, if any part of the above routine isn't needed, it isn't
        !           820: ; generated (i.e. the generated code might just be a single MOVSB)
        !           821: ;-----------------------------------------------------------------------;
        !           822: 
        !           823: cblt_5060:
        !           824:         shr     edx,1                   ;Byte count / 2 for words
        !           825:         jnc     cblt_5080               ;  No odd byte to move
        !           826:         mov     ax,si                   ;  Odd byte, move it
        !           827:         stosb
        !           828: 
        !           829: cblt_5080:
        !           830:         jz      cblt_5140               ;No more bytes to move
        !           831:         xor     bx,bx                   ;Flag as stepping from left to right
        !           832:         cmp     bl,fr.step_direction    ;Moving from the right to the left?
        !           833:         errnz   STEPLEFT                ;  (left direction must be zero)
        !           834:         jnz     cblt_5100               ;  No
        !           835:         mov     ax,I_DEC_ESI_DEC_EDI    ;  Yes, decrement both pointers
        !           836:         stosw
        !           837:         mov     bx,I_INC_ESI_INC_EDI      ;Set up to increment the pointers later
        !           838: 
        !           839: 0cblt_5100:
        !           840:         cmp     edx,1                   ;Move one word or many words?
        !           841:         jz      cblt_5120               ;  Only one word
        !           842:         mov     al,I_MOV_ECX_DWORD_I    ;  Many words, load count
        !           843:         stosb
        !           844:         mov     eax,edx
        !           845:         stosd
        !           846:         mov     al,I_REP                ;a repeat instruction
        !           847:         stosb
        !           848: 
        !           849: cblt_5120:
        !           850:         mov     al,I_SIZE_OVERRIDE
        !           851:         stosb
        !           852:         mov     ax,si                   ;Set the word instruction
        !           853:         inc     ax
        !           854:         stosb
        !           855:         errnz   I_MOVSW-I_MOVSB-1       ;The word form of the instruction
        !           856:         errnz   I_STOSW-I_STOSB-1       ;  must be the byte form + 1
        !           857: 
        !           858:         or      bx,bx                   ;Need to increment the pointers?
        !           859:         jz      cblt_5140               ;  No
        !           860:         mov     ax,bx                   ;  Yes, increment both pointers
        !           861:         stosw
        !           862: 
        !           863: cblt_5140:
        !           864:         jmp     cblt_6000               ;Done setting up the innerloop
        !           865:         page
        !           866: 
        !           867: endif
        !           868: 
        !           869: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           870: ; There is some count for the innerloop of the BLT.  Generate the
        !           871: ; required BLT. Two or four copies of the BLT will be placed on the
        !           872: ; stack.   This allows the LOOP instruction at the end to be distributed
        !           873: ; over two or four bytes instead of 1, saving 11 or 12 clocks for each
        !           874: ; byte (for 4).  Multiply 12 clocks by ~ 16K and you save a lot of
        !           875: ; clocks!
        !           876: ;
        !           877: ; If there are less than four (two) bytes to be BLTed, then no looping
        !           878: ; instructions will be generated.  If there are more than four (two)
        !           879: ; bytes, then there is the possibility of an initial jump instruction
        !           880: ; to enter the loop to handle the modulo n result of the loop count.
        !           881: ;
        !           882: ; The innerloop code will look something like:
        !           883: ;
        !           884: ;   <       mov     cx,loopcount/n> ;load count if >n innerloop bytes
        !           885: ;   <       jmp     short ???     > ;If a first jump is needed, do one
        !           886: ;
        !           887: ; BLTloop:
        !           888: ;         replicate initial byte BLT code up to n times
        !           889: ;
        !           890: ;   <       loop    BLTloop >       ;Loop until all bytes processed
        !           891: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           892: 
        !           893: cblt_5500:
        !           894:         mov     ebx,fr.end_fl           ;Compute size of the fetch code
        !           895:         sub     ebx,fr.start_fl
        !           896:         inc     ebx                     ;A stosb will be appended
        !           897:         mov     esi,4                   ;Assume replication 4 times
        !           898:         mov     cl,2                    ;  (shift count two bits left)
        !           899:         cmp     ebx,32                  ;Small enough for 4 times?
        !           900:         jc      cblt_5520               ;  Yes, replicate 4 times
        !           901:         shr     esi,1                   ;  No,  replicate 2 times
        !           902:         dec     ecx
        !           903: 
        !           904: cblt_5520:
        !           905:         cmp     edx,esi                 ;Generate a loop? (edx = loopcount)
        !           906:         jle     cblt_5540               ;  No, just copy code
        !           907:         mov     al,I_MOV_ECX_DWORD_I
        !           908:         stosb                           ;mov cx,loopcount/n
        !           909:         mov     eax,edx                 ;Compute loop count
        !           910:         shr     eax,cl
        !           911:         stosd
        !           912:         shl     eax,cl                  ;See if loopcount MOD n is 0
        !           913:         sub     eax,edx
        !           914:         jz      cblt_5540               ;Zero, no odd count to handle
        !           915: 
        !           916:         page
        !           917: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           918: ; There is an odd portion of bytes to be processed.  Increment
        !           919: ; the loop counter for the odd pass through the loop and then
        !           920: ; compute the displacement for entering the loop.
        !           921: ;
        !           922: ; To compute the displacement, subtract the number of odd bytes
        !           923: ; from the modulus being used  (i.e. 4-3=1).  This gives the
        !           924: ; number of bytes to skip over the first time through the loop.
        !           925: ;
        !           926: ; Multiply this by the number of bytes for a logic sequence,
        !           927: ; and the result will be the displacement for the jump.
        !           928: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           929: 
        !           930:         inc     dword ptr [edi][-4]     ;Not zero, adjust for partial loop
        !           931:         add     eax,esi                 ;Compute where to enter the loop at
        !           932:         push    edx
        !           933:         mul     ebx
        !           934:         pop     edx
        !           935:         mov     ecx,eax
        !           936:         mov     al,I_JMP_DISP32         ;Stuff jump instruction
        !           937:         stosb
        !           938:         mov     eax,ecx                 ;Stuff displacement for jump
        !           939:         stosd
        !           940: 
        !           941: ;-----------------------------------------------------------------------;
        !           942: ; Currently:      EDX = loop count
        !           943: ;                 ESI = loop modulus
        !           944: ;                 EBX = size of one logic operation
        !           945: ;                 EDI --> next location in the loop
        !           946: ;-----------------------------------------------------------------------;
        !           947: 
        !           948: cblt_5540:
        !           949:         mov     ecx,ebx                 ;Set move count
        !           950:         mov     ebx,edx                 ;Set maximum for move
        !           951:         cmp     ebx,esi                 ;Is the max > what's left?
        !           952:         jle     cblt_5560               ;  No, just use what's left
        !           953:         mov     ebx,esi                 ;  Yes, copy the max
        !           954: 
        !           955: cblt_5560:
        !           956:         sub     edx,esi                 ;If dx > 0, then loop logic needed
        !           957:         mov     esi,fr.start_fl         ;--> fetch code to copy
        !           958:         mov     eax,ecx                 ;Save a copy of fetch length
        !           959:         rep     movsb                   ;Move fetch code and stuff stosb
        !           960:         mov     esi,edi                   ;--> new source (and top of loop)
        !           961:         sub     esi,eax
        !           962:         mov     byte ptr [edi][-1],I_STOSB
        !           963:         dec     ebx                     ;One copy has been made
        !           964:         push    edx
        !           965:         mul     ebx                     ;Compute # bytes left to move
        !           966:         pop     edx
        !           967:         mov     ecx,eax                 ;Set move count
        !           968:         rep     movsb                   ;Move the fetches
        !           969:         sub     esi,eax                 ;Restore pointer to start of loop
        !           970: 
        !           971:         page
        !           972: 
        !           973: ; The innermost BLT code has been created and needs the looping
        !           974: ; logic added to it.  If there is any looping to be done, then
        !           975: ; generate the loop code.  The code within the innerloop may be
        !           976: ; greater than 126 bytes, so a LOOP instruction may not be used
        !           977: ; in this case.
        !           978: 
        !           979: cblt_5580:
        !           980:         or      edx,edx                 ;Need a loop?
        !           981:         jle     cblt_6000               ;  No, don't generate one
        !           982:         mov     al,I_DEC_ECX
        !           983:         stosb
        !           984:         mov     ax,I_JNZ_DISP32
        !           985:         stosw
        !           986:         mov     eax,esi                 ;Compute offset of loop
        !           987:         sub     eax,edi
        !           988:         sub     eax,4                   ;Bias by DISP32
        !           989:         stosd
        !           990: 
        !           991: 
        !           992:         subttl  Compile - Last Byte Processing
        !           993:         page
        !           994: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !           995: ; All the innerloop stuff has been processed.  Now generate the code for
        !           996: ; the final byte if there is one.  This code is almost identical to the
        !           997: ; code for the first byte except there will only be one fetch (if a
        !           998: ; fetch is needed at all).
        !           999: ;
        !          1000: ; The code generated will look something like:
        !          1001: ;
        !          1002: ; <       fetch           >       ;Get source byte
        !          1003: ; <       align           >       ;Align source if needed
        !          1004: ;         action                  ;Perform desired action
        !          1005: ;         mask and store
        !          1006: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !          1007: 
        !          1008: cblt_6000:
        !          1009:         mov     dx,fr.last_mask         ;Get last byte mask
        !          1010:         or      dh,dh                   ;Is there a last byte to be processed?
        !          1011:         jz      cblt_6100               ;  No.
        !          1012: 
        !          1013:         mov     ecx,fr.end_fls          ;Get end of fetch/logic/store operation
        !          1014:         mov     esi,fr.start_fl         ;Get start of fetch/logic sequence
        !          1015:         sub     ecx,esi                 ;Compute length of the code
        !          1016:         test    fr.first_fetch,FF_NO_LAST_FETCH
        !          1017:         jz      cblt_include_fetch
        !          1018:         test    fr.the_flags,F0_SRC_PRESENT ; was there a fetch?
        !          1019:         jz      cblt_was_no_fetch
        !          1020:         cmp     fr.phase_h,0            ; Phase zero case is not combined
        !          1021:                                         ; into innerloop as it should be.
        !          1022:                                         ; If the final byte is full then we
        !          1023:                                         ; better not remove the lodsb ( i.e.
        !          1024:         je      cblt_include_fetch      ; 0 - 0 = 0 would make us think we could)
        !          1025: 
        !          1026:         mov     eax,fr.cFetchCode       ; don't copy the fetch (lodsb)
        !          1027:         add     esi,eax
        !          1028:         sub     ecx,eax
        !          1029: 
        !          1030: cblt_was_no_fetch:
        !          1031: cblt_include_fetch:
        !          1032: 
        !          1033:         rep     movsb                       ;Copy the fetch/action/store code
        !          1034:         xchg    dh,dl
        !          1035:         mov     [edi][MASKED_STORE_MASK],dx ;Stuff last byte mask into the code
        !          1036: skip_save:
        !          1037:         subttl  Compile - Looping Logic
        !          1038:         page
        !          1039: 
        !          1040: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !          1041: ; Looping logic.
        !          1042: ;
        !          1043: ; The looping logic must handle monochrome bitmaps, color bitmaps,
        !          1044: ; huge bitmaps, the device, the presence or absence of a source
        !          1045: ; or pattern, and mono <==> color interactions.
        !          1046: ;
        !          1047: ; The type of looping logic is always based on the destination.
        !          1048: ;
        !          1049: ; Plane Update Facts:
        !          1050: ;
        !          1051: ; 1)  If the destination device is color, then there will be
        !          1052: ;     logic for plane selection.  Plane selection is performed
        !          1053: ;     at the start of the loop for the display.  Plane selection
        !          1054: ;     for bitmaps is performed at the end of the loop in anticipation
        !          1055: ;     of the next plane.
        !          1056: ;
        !          1057: ;     The following applies when the destination is color:
        !          1058: ;
        !          1059: ;     a)  The destination update consists of:
        !          1060: ;
        !          1061: ;         1)  If the destination is the display, the next plane will
        !          1062: ;             be selected by the plane selection code at the start
        !          1063: ;             of the scan line loop.
        !          1064: ;
        !          1065: ;         2)  If not the display, then the PDevice must a bitmap.
        !          1066: ;             The next plane will be selected by updating the
        !          1067: ;             destination offset by the next_plane value.
        !          1068: ;
        !          1069: ;
        !          1070: ;     b)  If F0_GAG_CHOKE isn't specified, then there may be a source.
        !          1071: ;         If there is a source, it must be color, and the update
        !          1072: ;         consists of:
        !          1073: ;
        !          1074: ;         1)  If the source is the display, the next plane will be
        !          1075: ;             selected by the plane selection code at the start of
        !          1076: ;             the loop.
        !          1077: ;
        !          1078: ;         2)  If not the display, then the PDevice must a bitmap.
        !          1079: ;             The next plane will be selected by updating the
        !          1080: ;             destination offset by the next_plane value.
        !          1081: ;
        !          1082: ;
        !          1083: ;     c)  If F0_GAG_CHOKE is specified, then the source must be a
        !          1084: ;         monochrome bitmap which is undergoing mono to color
        !          1085: ;         conversion.  The AND & XOR mask table which is used
        !          1086: ;         for the conversion will have to be updated, unless
        !          1087: ;         the F1_NO_MUNGE flag is set indicating that the color
        !          1088: ;         conversion really wasn't needed.
        !          1089: ;
        !          1090: ;         The source's pointer will not be updated.  It will
        !          1091: ;         remain pointing to the same scan of the source until
        !          1092: ;         all planes of the destination have been processed.
        !          1093: ;
        !          1094: ;
        !          1095: ;     d)  In all cases, the plane mask rotation code will be
        !          1096: ;         generated.  If the plane indicator doesn't overflow,
        !          1097: ;         then start at the top of the scan line loop for the
        !          1098: ;         next plane.
        !          1099: ;
        !          1100: ;         If the plane indicator overflows, then:
        !          1101: ;
        !          1102: ;             1)  If there is a pattern present, it's a color
        !          1103: ;                 pattern fetch.  The index of which scan of
        !          1104: ;                 the brush to use will have to be updated.
        !          1105: ;
        !          1106: ;             2)  Enter the scan line update routine
        !          1107: ;
        !          1108: ;
        !          1109: ; 2)      If the destination is monochrome, then there will be no
        !          1110: ;         plane selection logic.
        !          1111: ;
        !          1112: ;         If F0_GAG_CHOKE is specified, then color ==> mono conversion
        !          1113: ;         is taking place.  Any plane selection logic is internal
        !          1114: ;         to the ROP byte fetch code.  Any color brush was pre-
        !          1115: ;         processed into a monochrome brush, so no brush updating
        !          1116: ;               need be done
        !          1117: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !          1118: 
        !          1119:         subttl  Looping Logic - Plane Selection
        !          1120:         page
        !          1121: 
        !          1122: ; Get saved parameters off of the stack.
        !          1123: ;
        !          1124: ; <       pop     ebx            > ;Get plane indicator
        !          1125: ; <       pop     esi            > ;Get source pointer
        !          1126: ;         pop     edi              ;Get destination pointer
        !          1127: ;         pop     ecx              ;Get loop count
        !          1128: 
        !          1129: cblt_6100:
        !          1130:         mov     bh,fr.the_flags         ;These flags will be used a lot
        !          1131:         test    bh,F0_DEST_IS_COLOR     ;Is the destination color?
        !          1132:         jz      cblt_6120               ;  No
        !          1133:         mov     al,I_POP_EBX            ;Restore plane index
        !          1134:         stosb
        !          1135: 
        !          1136: cblt_6120:
        !          1137:         test    bh,F0_SRC_PRESENT       ;Is a source needed?
        !          1138:         jz      cblt_6140               ;  No
        !          1139:         mov     al,I_POP_ESI            ;  Yes, get source pointer
        !          1140:         stosb
        !          1141: 
        !          1142: cblt_6140:
        !          1143:         mov     ax,I_POP_EDI_POP_ECX    ;Get destination pointer
        !          1144:         stosw                           ;Get loop count
        !          1145:         test    bh,F0_DEST_IS_COLOR     ;Color scanline update?
        !          1146:         jz      cblt_6300               ;  No, just do the mono scanline update
        !          1147: 
        !          1148: ; The scanline update is for color.  Generate the logic to update
        !          1149: ; a brush, perform plane selection, process mono ==> color conversion,
        !          1150: ; and test for plane overflow.
        !          1151: 
        !          1152: cblt_6160:
        !          1153:         or      bh,bh                   ;Color conversion?
        !          1154:         jns     cblt_6180               ;  No
        !          1155:         errnz   F0_GAG_CHOKE-10000000b
        !          1156: 
        !          1157:         page
        !          1158: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !          1159: ; The source is monochrome.  Handle mono ==> color conversion.
        !          1160: ; The AND & XOR mask table will need to be rotated for the next
        !          1161: ; pass over the source.
        !          1162: ;
        !          1163: ; The source scanline pointer will not be updated until all planes
        !          1164: ; have been processed for the current scan.
        !          1165: ;
        !          1166: ; If F1_NO_MUNGE has been specified, then the color conversion table
        !          1167: ; and the color conversion code was not generated, and no update
        !          1168: ; code will be needed.
        !          1169: ;
        !          1170: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !          1171: 
        !          1172:         test    fr.moore_flags,F1_NO_MUNGE  ;Is there really a conversion table?
        !          1173:         jnz     short cblt_6200             ;  No, so skip the code
        !          1174: 
        !          1175:         mov     al,I_MOV_EBP_DWORD_I        ;lea ebp,fr.ajM2C
        !          1176:         stosb
        !          1177:         lea     eax,fr.ajM2c                ;Get address of table
        !          1178:         stosd
        !          1179:         mov     esi,offset FLAT:rot_and_xor ;--> rotate code
        !          1180:         mov     cx,LEN_ROT_AND_XOR
        !          1181:         rep     movsb
        !          1182:         jmp     short cblt_6200
        !          1183: 
        !          1184: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !          1185: ; If there is a source, it must be color.  If it is a memory
        !          1186: ; bitmap, then the next plane must be selected, else it is
        !          1187: ; the display and the next plane will be selected through
        !          1188: ; the hardware registers.
        !          1189: ;
        !          1190: ; <       add     si,next_plane>
        !          1191: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !          1192: 
        !          1193: cblt_6180:
        !          1194:         test    bh,F0_SRC_PRESENT       ;Is there really a source?
        !          1195:         jz      cblt_6200               ;No source.
        !          1196:         test    bh,F0_SRC_IS_DEV        ;Is the source the display?
        !          1197:         jnz     cblt_6200               ;  Yes, use hardware plane selection
        !          1198:         mov     ax,I_ADD_ESI_DWORD_I    ;  No, generate plane update
        !          1199:         stosw                           ;Add si,next_plane
        !          1200:         mov     eax,fr.src.next_plane
        !          1201:         stosd
        !          1202: 
        !          1203: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !          1204: ; If the destination isn't the device, then it must be a color
        !          1205: ; memory bitamp, and it's pointer will have to be updated by
        !          1206: ; bmWidthPlanes.  If it is the display, then the next plane
        !          1207: ; will be selected through the hardware registers.
        !          1208: ;
        !          1209: ; <       add     di,next_plane>
        !          1210: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !          1211: 
        !          1212: cblt_6200:
        !          1213:         test    bh,F0_DEST_IS_DEV       ;Is the destination the display
        !          1214:         jnz     cblt_6220               ;  Yes, don't generate update code
        !          1215:         mov     ax,I_ADD_EDI_DWORD_I    ;  No, update bitmap to the next plane
        !          1216:         stosw
        !          1217:         mov     eax,fr.dest.next_plane
        !          1218:         stosd
        !          1219: 
        !          1220: 
        !          1221: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !          1222: ; The source and destination pointers have been updated.
        !          1223: ; Now generate the plane looping logic.
        !          1224: ;
        !          1225: ; <       shl     bl,1           > ;Select next plane
        !          1226: ; <       jnc     StartOfLoop    > ;  Yes, go process next
        !          1227: ; <       mov     bl,PLANE_1     > ;Reset plane indicator
        !          1228: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !          1229: 
        !          1230: cblt_6220:
        !          1231:         mov     ax,I_SHL_BL_1           ;Stuff plane looping logic
        !          1232:         stosw
        !          1233: 
        !          1234:         mov     edx,fr.pNextPlane       ;Compute relative offset of
        !          1235:         sub     edx,edi                 ;  start of loop
        !          1236:         sub     edx,6                   ;Bias offset by length of jnc inst.
        !          1237:         mov     ax,I_JNC_DISP32
        !          1238:         stosw                           ;jnc StartOfLoop
        !          1239:         mov     eax,edx
        !          1240:         stosd
        !          1241: 
        !          1242:         subttl  Looping Logic - Color Brush Update
        !          1243:         page
        !          1244: 
        !          1245: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !          1246: ; The plane update logic has been copied.  If a pattern was
        !          1247: ; involved for a color BLT, then the pattern index will need
        !          1248: ; to be updated to the next scanline for three plane mode.
        !          1249: ;
        !          1250: ; This will involve subtracting off 3*SIZE_PATTERN (MonoPlane),
        !          1251: ; and adding in the increment.  The result must be masked with
        !          1252: ; 00000111b to select the correct source.  Note that the update
        !          1253: ; can be done with an add instruction and a mask operation.
        !          1254: ;
        !          1255: ; inc   index+MonoPlane   inc-MonoPlane   result   AND 07h
        !          1256: ;
        !          1257: ;  1       0+32 = 32        1-32 = -31       1         1
        !          1258: ;  1       7+32 = 39        1-32 = -31       8         0
        !          1259: ; -1       0+32 = 32       -1-32 = -33      FF         7
        !          1260: ; -1       7+32 = 39       -1-32 = -33       6         6
        !          1261: ;
        !          1262: ; <       mov     al,[12345678] > ;Get brush index
        !          1263: ; <       add     al,n          > ;Add displacement to next byte
        !          1264: ; <       and     al,00000111b  > ;Keep it in range
        !          1265: ; <       mov     [12345678],al > ;Store displacement to next byte
        !          1266: ;
        !          1267: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !          1268: 
        !          1269:         test    bh,F0_PAT_PRESENT       ;Is a pattern involved?
        !          1270:         jz      cblt_6300               ;  No
        !          1271:         test    fr.brush_accel,SOLID_BRUSH
        !          1272:         jnz     cblt_6300               ;Solid color fetch needs no updating
        !          1273:         mov     al,I_MOV_AL_MEM
        !          1274:         stosb                           ;mov al,[xxxxxxxx]
        !          1275:         mov     edx,fr.addr_brush_index
        !          1276:         mov     eax,edx
        !          1277:         stosd
        !          1278:         mov     al,I_ADD_AL_BYTE_I
        !          1279:         mov     ah,fr.direction         ;add al,bais
        !          1280:         sub     ah,oem_brush_mono       ;Anybody ever fly one of these things?
        !          1281:         errnz   INCREASE-1              ;Must be a 1
        !          1282:         errnz   DECREASE+1              ;Must be a -1
        !          1283:         stosw
        !          1284:         mov     ax,0700h+I_AND_AL_BYTE_I        ;and al,00000111b
        !          1285:         stosw
        !          1286:         mov     al,I_MOV_MEM_AL
        !          1287:         stosb                           ;mov [xxxxxxxx],al
        !          1288:         mov     eax,edx
        !          1289:         stosd
        !          1290: 
        !          1291:         subttl  Looping Logic - Scan Line Update
        !          1292:         page
        !          1293: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !          1294: ; Generate the next scanline code.  The next scan line code must
        !          1295: ; handle monochrome bitmaps, the device, the presence or absence
        !          1296: ; of a source.
        !          1297: ;
        !          1298: ; Also color bitmaps, and mono <==> color interactions.
        !          1299: ;
        !          1300: ; <       add si,gl_src.next_scan> ;Normal source scan line update
        !          1301: ;         add di,gl_dest.next_scan ;Normal destination scan line update
        !          1302: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
        !          1303: 
        !          1304: ;!!! We have the problem in that this code assumes that cPlanes*cjBytesScan
        !          1305: ;!!! is the same as next_scan.  This might not always be the case, and we
        !          1306: ;!!! should do somehting about fixing this.  This would require pushing an
        !          1307: ;!!! extra copy of pScan_n_Plane0 and then adding next-scan to this when we
        !          1308: ;!!! have exhausted the planes for scan n
        !          1309: 
        !          1310: cblt_6300:
        !          1311:         test    bh,F0_SRC_PRESENT       ;Is there a source?
        !          1312:         jz      cblt_6340               ;  No, skip source processing
        !          1313:         mov     ax,I_ADD_ESI_DWORD_I    ;add esi,increment
        !          1314:         stosw
        !          1315:         mov     eax,fr.src.next_scan
        !          1316:         stosd
        !          1317: 
        !          1318: cblt_6340:
        !          1319:         mov     ax,I_ADD_EDI_DWORD_I    ;add edi,increment
        !          1320:         stosw
        !          1321:         mov     eax,fr.dest.next_scan
        !          1322:         stosd
        !          1323: 
        !          1324: ; Compile the scan line loop.  The code simply jumps to the start
        !          1325: ; of the outer loop if more scans exist to be processed.
        !          1326: 
        !          1327: cblt_6380:
        !          1328:         mov     al,I_DEC_ECX
        !          1329:         stosb
        !          1330:         mov     ax,I_JNZ_DISP32
        !          1331:         stosw
        !          1332:         mov     eax,fr.blt_addr         ;Compute relative offset of
        !          1333:         sub     eax,edi                 ;  start of loop
        !          1334:         sub     eax,4                   ;Adjust jump bias for DISP32
        !          1335:         stosd                           ;  and store it into jump
        !          1336: 
        !          1337: cblt_6420:
        !          1338:         mov     al,I_RET                ;Stuff the far return instruction
        !          1339:         stosb
        !          1340: 
        !          1341:      cRet    cblt
        !          1342: endProc cblt
        !          1343: 
        !          1344: _TEXT$01   ends
        !          1345: 
        !          1346:         end
        !          1347: 

unix.superglobalmegacorp.com

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