vdugrafd 21.9 KB
Newer Older
Neil Turton's avatar
Neil Turton committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
; Copyright 1996 Acorn Computers Ltd
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
;     http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
; > $.Source.VduGrafD

;
; ARTHUR OPERATING SYSTEM - Vdu Drivers
; =======================
;
; Vdu driver code - Block Copy and Move
;
; Author R C Manby
; Date   2.10.86
;

; *****************************************************************************
;
;       BlockCopyMove - Copy/Move a rectangular area
;
; in:   OldCs marks start of area to copy/move
;       ICursor marks end of area to copy/move
;       NewPt is lower left of destination area
;       R2 = plot number &B8..&BF
;
; out:  R0..R11 corrupt
;

BlockCopyMove ROUT
        TST     R2, #3                          ; Do nowt on 'MoveOnly' codes
Kevin Bracey's avatar
Kevin Bracey committed
41
        MOVEQ   PC, R14
Neil Turton's avatar
Neil Turton committed
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136

        SaveRetAdr

        ADD     R0, WsPtr, #BgEcfStore          ; Select 'store' in background
        STR     R0, [WsPtr, #GColAdr]           ; to be used by HLine when
                                                ; clearing source & dest lines

; Build up source & destination data as follows
;
; R0   R1   R2   R3   R4    R5    R6    R7    R8
; SrcL,SrcB,SrcR,SrcT,DestL,DestB,DestR,DestT,CopyFlag

        AND     R8, R2, #2                      ; 0/2 means Move/Copy

        ADD     R11, WsPtr, #OldCsX
        LDMIA   R11, {R0,R1, R2,R3, R4,R5}      ; OldCs, ICursor, NewPt

        SortT   R0, R2, R6                      ; Order SrcL,SrcB,SrcR,SrcT
        SortT   R1, R3, R6                      ;       R0 , R1 , R2 , R3

        SUB     R6, R2, R0
        ADD     R6, R6, R4                      ; DestR := SrcR-SrcL+DestL

        SUB     R7, R3, R1
        ADD     R7, R7, R5                      ; DestT := SrcT-SrcB+DestB

        ADD     R11, WsPtr, #CMSrc
        STMIA   R11, {R0-R7,R8}                 ; Unclipped src & dest areas
                                                ; and CopyFlag
        LDR     R11, [WsPtr, #CursorFlags]
        TST     R11, #ClipBoxEnableBit
        BLNE    ClipBlockCopyMove

; now work out ACTUAL area to copy
; first, we window destination area

        LDR     R10, [WsPtr, #GWLCol]
        LDR     R11, [WsPtr, #GWRCol]

        SUBS    R8, R10, R4                     ; R8 = GWLCol - DestL
        ADDGT   R4, R4, R8                      ; if > 0 then DestL := GWLCol
        ADDGT   R0, R0, R8                      ; and adjust SrcL to match

        SUBS    R8, R6, R11                     ; R8 = DestR - GWRCol
        SUBGT   R6, R6, R8                      ; if > 0 then DestR := GWRCol
        SUBGT   R2, R2, R8                      ; and adjust SrcR to match

        CMP     R6, R4                          ; check DestR >= DestL
        BLT     EraseSource                     ; if not then just erase source
                                                ; if a block move

        STR     R4, [WsPtr, #CMDest2L]          ; save horizontal dest coords
        STR     R6, [WsPtr, #CMDest2R]          ; windowed at dest

        SUBS    R8, R10, R0                     ; R8 = GWLCol - SrcL
        ADDGT   R0, R0, R8                      ; if > 0 then SrcL := GWLCol
        ADDGT   R4, R4, R8                      ; and adjust DestL to match

        SUBS    R8, R2, R11                     ; R8 = SrcR - GWRCol
        SUBGT   R2, R2, R8                      ; if > 0 then SrcR := GWRCol
        SUBGT   R6, R6, R8                      ; and adjust DestR to match

        LDR     R10, [WsPtr, #GWBRow]
        LDR     R11, [WsPtr, #GWTRow]

        SUBS    R8, R10, R5                     ; R8 = GWBRow - DestB
        ADDGT   R5, R5, R8                      ; if > 0 then DestB := GWBRow
        ADDGT   R1, R1, R8                      ; and adjust SrcB to match

        SUBS    R8, R7, R11                     ; R8 = DestT - GWTRow
        SUBGT   R7, R7, R8                      ; if > 0 then DestT := GWTRow
        SUBGT   R3, R3, R8                      ; and adjust SrcT to match

        CMP     R7, R5                          ; check DestT >= DestB
        BLT     EraseSource                     ; if not then just erase source
                                                ; if a block move

        STR     R5, [WsPtr, #CMDest2B]          ; save vertical dest coords
        STR     R7, [WsPtr, #CMDest2T]          ; windowed at dest

        SUBS    R8, R10, R1                     ; R8 = GWBRow - SrcB
        ADDGT   R1, R1, R8                      ; if > 0 then SrcB := GWBRow
        ADDGT   R5, R5, R8                      ; and adjust DestB to match

        SUBS    R8, R3, R11                     ; R8 = SrcT - GWTRow
        SUBGT   R3, R3, R8                      ; if > 0 then SrcT := GWTRow
        SUBGT   R7, R7, R8                      ; and adjust DestT to match

; now R0-R3 is source windowed both ways
;     R4-R7 is dest   windowed both ways

        ADD     R8, WsPtr, #CMDest3L
        STMIA   R8, {R4-R7}                     ; save destination windowed
                                                ; both ways

137 138
        LDR     R9, [WsPtr, #VduSprite]

Neil Turton's avatar
Neil Turton committed
139 140 141 142 143 144 145
        CMP     R2, R0                          ; check SrcR >= SrcL
        SUBGES  R8, R3, R1                      ; and SrcT >= SrcB (R8=lines-1)
        BLT     EraseDest                       ; if not, then go to wiping out
                                                ; destination stage

        STR     R8, [WsPtr, #CMVertCount]       ; no. of vertical lines -1

146 147 148 149 150 151 152 153 154 155 156 157
        BL      CheckAcceleration               ; okay to accelerate?
        BNE     %FT05

; not redirected to sprite - try calling GraphicsV for some acceleration

        Push    "R2"
        Push    "R8"
        SUB     R14, R2, R0
        Push    "R0,R1,R4,R5,R14"               ; srcL,srcB,dstL,dstB,W-1,H-1
        MOV     R0, #GVRender_Sync
        MOV     R1, #GVRender_CopyRectangle
        MOV     R2, R13
Jeffrey Lee's avatar
Jeffrey Lee committed
158 159 160
        LDR     R4, [WsPtr, #CurrentGraphicsVDriver]
        MOV     R4, R4, LSL #24
        ORR     R4, R4, #GraphicsV_Render
161 162 163 164 165 166 167 168
        BL      CallGraphicsV                   ; (R0,R1,R2,R4->R4)
        TEQ     R4, #GraphicsV_Complete         ; did it do it?
        Pull    "R0,R1,R4"
        ADD     R13, R13, #3*4
        Pull    "R2"
        BEQ     EraseDest                       ; then go straight to erase

05      LDR     R9, [WsPtr, #Log2BPC]
Neil Turton's avatar
Neil Turton committed
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
        LDR     R10, [WsPtr, #XShftFactor]
        LDR     R11, [WsPtr, #NPix]

        MOV     R8, R6, LSR R10                 ; DestR word offset
        SUB     R8, R8, R4, LSR R10             ; -DestL word offset
        STR     R8, [WsPtr, #CMDestCount]       ; No. of dest words -1

        AND     R8, R6, R11                     ; R8 = DestR pixel offset
        ADD     R14, WsPtr,#RAMMaskTb
        LDR     R8, [R14, R8, LSL #2]           ; R8 = mask for right pixel
        SUB     R14, R8, #1             ; In rh mask, set all bits lower than
        ORR     R14, R14, R8            ; pixel, RHM := RHM OR (RHM-1)
        STR     R14, [WsPtr, #CMRMask]

        AND     R8, R4, R11                     ; R8 = DestL pixel offset
        ADD     R14, WsPtr, #RAMMaskTb
        LDR     R8, [R14, R8, LSL #2]           ; R8 = mask for left pixel
        RSB     R14, R8, #0             ; In lh mask, set all bits higher than
        ORR     R14, R14, R8            ; pixel, LHM := LHM OR (0-LHM)
        STR     R14, [WsPtr, #CMLMask]

        CMP     R0, R4                          ; test whether SrcL >= DestL
        BLT     SrcHLTDest

; source is to the right of dest, so start at left hand side

        AND     R8, R4, R11                     ; R8 = DestL pixel offset
        AND     R14, R0, R11                    ; R14 = SrcL pixel offset
        SUB     R11, R14, R8                    ; R11 = Src-Dest pixel offset
        MOV     R11, R11, LSL R9                ; R11 = Src-Dest bit offset

        CMP     R11, #0                         ; if rightshift < 0
        ADDLT   R11, R11, #32                   ; if < 0, correct result
        MOVGE   R10, #0
        MOVLT   R10, #-4                        ; and subtract 4 off src addr

        STR     R11, [WsPtr, #CMRShift]
        RSB     R11, R11, #32
        STR     R11, [WsPtr, #CMLShift]

        LDR     R6, [WsPtr, #LineLength]        ; (no longer need DestR)

        CMP     R1, R5                          ; if SrcB >= DestB
        RSBGE   R6, R6, #0                      ; then go upwards
        STR     R6, [WsPtr, #CMVertDir]

        MOVLT   R1, R3                          ; else go down
        MOVLT   R5, R7                          ; so use top coords

        BL      ScreenAddr                      ; R2 = address of src corner
        ADD     R2, R2, R10
        STR     R2, [WsPtr, #CMSourceAddr]

        MOV     R0, R4
        MOV     R1, R5
        BL      ScreenAddr                      ; R2 = address of dest corner
        STR     R2, [WsPtr, #CMDestAddr]

        ADD     R11, WsPtr, #CMStuff
        LDMIA   R11, {R0-R6}            ; src,dest,cnt,rtshf,lfshf,rtmsk,ltmsk
10
        TEQ     R2, #0                  ; only one word on a line ?
        ANDEQ   R5, R5, R6              ; then rightmask:=rightmask AND lftmask
        LDREQ   R14, [R0], #4           ; and load first word up
        BEQ     %FT45                   ; and do endword

; do first word

        LDMIA   R0!, {R11,R14}          ; load 2 words
        ShiftR  R11, R14, R3, R4        ; shift them
        AND     R11, R11, R6            ; AND with leftmask
        LDR     R10, [R1]               ; load word from dest
        BIC     R10, R10, R6            ; clear out bits in leftmask
        ORR     R10, R10, R11           ; OR in new bits
        STR     R10, [R1], #4
        SUBS    R2, R2, #1              ; decrement count
        BEQ     %FT40                   ; if zero, do finish word

        SUBS    R2, R2, #7              ; can we do 7 words ?
        BCC     %FT30                   ; no, then do 1 word at a time

; do 7 words at a time

        TEQ     R3, #0                  ; if rightshf = 0
        BEQ     %FT60                   ; then do non-shifting version
20
 [ {TRUE}                               ; TMD optimisation 12-May-93
        MOV     R5, R14, LSR R3
        LDMIA   R0!, {R6-R11,R14}
        ORR     R5, R5, R6, LSL R4
 |
        MOV     R5, R14
        LDMIA   R0!, {R6-R11,R14}       ; load next 7 words
        ShiftR  R5, R6, R3, R4
 ]
        ShiftR  R6, R7, R3, R4
        ShiftR  R7, R8, R3, R4
        ShiftR  R8, R9, R3, R4
        ShiftR  R9, R10, R3, R4
        ShiftR  R10, R11, R3, R4
        ShiftR  R11, R14, R3, R4
        STMIA   R1!, {R5-R11}
        SUBS    R2, R2, #7
        BCS     %BT20

30
        ADDS    R2, R2, #7
        BEQ     %FT40                   ; if count expired, do last word

; do 1 word at a time

35
        MOV     R5, R14
        LDR     R14, [R0], #4
        ShiftR  R5, R14, R3, R4
        STR     R5, [R1], #4
        SUBS    R2, R2, #1
        BNE     %BT35

; do last word

40
        LDR     R5, [WsPtr, #CMRMask]   ; load right mask
45

; now test if any bits would be used (so we don't go off end of memory)

        MOV     R11, #&FFFFFFFF
        TST     R5, R11, LSL R4         ; NE => safe to read from here
        LDRNE   R11, [R0], #4           ; R14 = left word; R11 = right word
        ShiftR  R14, R11, R3, R4        ; form single word
        AND     R14, R14, R5            ; mask source word
        LDR     R10, [R1]               ; load dest word
        BIC     R10, R10, R5            ; mask dest word
        ORR     R10, R10, R14           ; OR two words
        STR     R10, [R1], #4           ; store back

; now go on to next row

        LDR     R7, [WsPtr, #CMVertCount]
        SUBS    R7, R7, #1
        BCC     EraseDest               ; finished, so go to erase dest stage
        STR     R7, [WsPtr, #CMVertCount]
        ADD     R11, WsPtr, #CMStuff
        LDMIA   R11, {R0-R6}            ; load up info again
        LDR     R7, [WsPtr, #CMVertDir]
        ADD     R0, R0, R7              ; move source pointer
        ADD     R1, R1, R7              ; and dest pointer
        STMIA   R11, {R0,R1}            ; store these back
        B       %BT10                   ; and loop

; non-shifting version, for speed
; do 7 words at a time

60
        MOV     R5, R14
        LDMIA   R0!, {R6-R11,R14}       ; load next 7 words
        STMIA   R1!, {R5-R11}
        SUBS    R2, R2, #7
        BCS     %BT60
        ADDS    R2, R2, #7
        BNE     %BT35                   ; count not expired, do last few words
        B       %BT40                   ; count expired, do last word

; *****************************************************************************

; source is to the left of dest, so start at right hand side

SrcHLTDest ROUT
        MOV     R0, R2                          ; rt coords are relevant ones
        MOV     R4, R6

        AND     R8, R4, R11                     ; R8 = DestR pixel offset
        AND     R14, R0, R11                    ; R14 = SrcR pixel offset
        SUB     R11, R14, R8                    ; R11 = Src-Dest pixel offset
        MOV     R11, R11, LSL R9                ; R11 = Src-Dest bit offset

        RSB     R11, R11, #32                   ; R11 = leftshift
        CMP     R11, #32                        ; if >= 32
        SUBCS   R11, R11, #32                   ; then put in range
        MOVCC   R10, #4                         ; else add 4
        MOVCS   R10, #0                         ; to src addr

        STR     R11, [WsPtr, #CMLShift]
        RSB     R11, R11, #32
        STR     R11, [WsPtr, #CMRShift]

        LDR     R6, [WsPtr, #LineLength]        ; (no longer need R6)

        CMP     R1, R5                          ; if SrcB >= DestB
        RSBGE   R6, R6, #0                      ; then go upwards
        STR     R6, [WsPtr, #CMVertDir]

        MOVLT   R1, R3                          ; else go down
        MOVLT   R5, R7                          ; so use top coords

        BL      ScreenAddr                      ; R2 = address of src corner
        ADD     R2, R2, R10
        STR     R2, [WsPtr, #CMSourceAddr]

        MOV     R0, R4
        MOV     R1, R5
        BL      ScreenAddr                      ; R2 = address of dest corner
        STR     R2, [WsPtr, #CMDestAddr]

        ADD     R11, WsPtr, #CMStuff
        LDMIA   R11, {R0-R6}            ; src,dest,cnt,rtshf,lfshf,rtmsk,ltmsk
10
        TEQ     R2, #0                  ; only one word on a line ?
        ANDEQ   R6, R6, R5              ; then leftmask:=leftmask AND rightmask
        LDREQ   R5, [R0], #-4           ; and load first word up
        BEQ     %FT45                   ; and do endword

; do first word

        LDMDA   R0!, {R11,R14}          ; load 2 words
        ShiftL  R11, R14, R3, R4        ; shift them
        AND     R14, R14, R5            ; AND with rightmask
        LDR     R10, [R1]               ; load word from dest
        BIC     R10, R10, R5            ; clear out bits in rightmask
        ORR     R10, R10, R14           ; OR in new bits
        STR     R10, [R1], #-4
        MOV     R5, R11
        SUBS    R2, R2, #1              ; decrement count
        BEQ     %FT40                   ; if zero, do finish word

        SUBS    R2, R2, #7              ; can we do 7 words ?
        BCC     %FT30                   ; no, then do 1 word at a time

; do 7 words at a time

        TEQ     R4, #0                  ; if leftshf=0
        BEQ     %FT60                   ; then do non-shifting version
20
 [ {TRUE}                               ; TMD optimisation 12-May-93
        MOV     R14, R5, LSL R4
        LDMDA   R0!, {R5-R11}
        ORR     R14, R14, R11, LSR R3
 |
        MOV     R14, R5
        LDMDA   R0!, {R5-R11}           ; load next 7 words
        ShiftL  R11, R14, R3, R4
 ]
        ShiftL  R10, R11, R3, R4
        ShiftL  R9, R10, R3, R4
        ShiftL  R8, R9, R3, R4
        ShiftL  R7, R8, R3, R4
        ShiftL  R6, R7, R3, R4
        ShiftL  R5, R6, R3, R4
        STMDA   R1!, {R6-R11,R14}
        SUBS    R2, R2, #7
        BCS     %BT20

30
        ADDS    R2, R2, #7
        BEQ     %FT40                   ; if count expired, do last word

; do 1 word at a time

35
        MOV     R14, R5
        LDR     R5, [R0], #-4
        ShiftL  R5, R14, R3, R4
        STR     R14, [R1], #-4
        SUBS    R2, R2, #1
        BNE     %BT35

; do last word

40
        LDR     R6, [WsPtr, #CMLMask]   ; load left mask
45

; now test if any bits would be used (so we don't go off start of memory)

        MOV     R11, #&FFFFFFFF
        TST     R6, R11, LSR R3         ; NE => safe to read from here
        LDRNE   R11, [R0], #-4          ; R11 = left word; R5 = right word
        ShiftL  R11, R5, R3, R4         ; form single word
        AND     R5, R5, R6              ; mask source word
        LDR     R10, [R1]               ; load dest word
        BIC     R10, R10, R6            ; mask dest word
        ORR     R10, R10, R5            ; OR two words
        STR     R10, [R1], #-4          ; store back

; now go on to next row

        LDR     R7, [WsPtr, #CMVertCount]
        SUBS    R7, R7, #1
        BCC     EraseDest               ; finished, so go to erase dest stage
        STR     R7, [WsPtr, #CMVertCount]
        ADD     R11, WsPtr, #CMStuff
        LDMIA   R11, {R0-R6}            ; load up info again
        LDR     R7, [WsPtr, #CMVertDir]
        ADD     R0, R0, R7              ; move source pointer
        ADD     R1, R1, R7              ; and dest pointer
        STMIA   R11, {R0,R1}            ; store these back
        B       %BT10                   ; and loop

; non-shifting version, for speed
; do 7 words at a time

60
        MOV     R14, R5
        LDMDA   R0!, {R5-R11}           ; load next 8 words
474 475 476
      [ SupportARMX
        MOV     R11, R11                ; Dummy instruction for XScale weirdness
      ]
Neil Turton's avatar
Neil Turton committed
477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
        STMDA   R1!, {R6-R11,R14}
        SUBS    R2, R2, #7
        BCS     %BT60
        ADDS    R2, R2, #7
        BNE     %BT35                   ; count not expired, do last few words
        B       %BT40                   ; count expired, do last word

; *****************************************************************************

; Erase the area Dest2\Dest3

EraseDest ROUT

; first do the flat rectangle

        ADD     R8, WsPtr, #CMDest2L
        LDMIA   R8, {R0-R7}             ; R0..R3 = Dest2; R4..R7 = Dest3
        BL      EraseDifference

; and drop thru to ...

EraseSource
        LDR     R8, [WsPtr, #CMCopyFlag] ; 0 => move, 2 => copy
        TEQ     R8, #0                  ; is it a move
        Return  NE                      ; no, then exit

        ADD     R8, WsPtr, #CMSrc       ; R0..R3 = unclipped src
        LDMIA   R8, {R0-R7}             ; R4..R7 = unclipped dest

; window both source and destination in source domain

        LDR     R10, [WsPtr, #GWLCol]
        LDR     R11, [WsPtr, #GWRCol]

        SUBS    R8, R10, R0             ; R8 = GWLCol - SrcL
        ADDGT   R0, R0, R8              ; if > 0 then SrcL := GWLCol
        ADDGT   R4, R4, R8              ; and adjust DestL to match

        SUBS    R8, R2, R11             ; R8 = SrcR - GWRCol
        SUBGT   R2, R2, R8              ; if > 0 then SrcR := GWRCol
        SUBGT   R6, R6, R8              ; and adjust DestR to match

        CMP     R2, R0                  ; check SrcR >= SrcL
        Return  LT                      ; if not then nothing to erase

        LDR     R10, [WsPtr, #GWBRow]
        LDR     R11, [WsPtr, #GWTRow]

        SUBS    R8, R10, R1             ; R8 = GWBRow - SrcB
        ADDGT   R1, R1, R8              ; if > 0 then SrcB := GWBRow
        ADDGT   R5, R5, R8              ; and adjust DestB to match

        SUBS    R8, R3, R11             ; R8 = SrcT - GWTRow
        SUBGT   R3, R3, R8              ; if > 0 then SrcT := GWTRow
        SUBGT   R7, R7, R8              ; and adjust DestT to match

        CMP     R3, R1                  ; check SrcT >= SrcB
        Return  LT                      ; if not then nothing to erase

; now window the dest coords to the source

        CMP     R7, R3                  ; if DestT >= SrcT
        MOVGE   R7, R3                  ; then DestT := SrcT
        MOVLT   R5, R1                  ; else DestB := SrcB
        CMP     R6, R2                  ; if DestR >= SrcR
        MOVGE   R6, R2                  ; then DestR := SrcR
        MOVLT   R4, R0                  ; else DestL := SrcL

        Pull    R14

; and drop thru to ...

; *****************************************************************************
;
;       EraseDifference - Erase the difference between two rectangles with at
;                         least one vertical and one horizontal shared boundary
;
; in:   R0-R3 = larger one
;       R4-R7 = smaller one
;

EraseDifference ROUT

; first do the flat rectangle

        CMP     R6, R4                  ; check for Dest3 being null
        CMPGE   R7, R5
        BLT     RectFillA               ; if is, just clear Dest2

        Push    "R0-R7,R14"

        TEQ     R3, R7                  ; if Dest2T = Dest3T
        SUBEQ   R3, R5, #1              ; then top = Dest3B -1
        ADDNE   R1, R7, #1              ; else bottom = Dest3T +1
        CMP     R3, R1                  ; if top >= bottom
        BLGE    RectFillA

; now do the tall rectangle

        Pull    "R0-R7"

        TEQ     R3, R7                  ; if Dest2T = Dest3T
        MOVEQ   R1, R5                  ; then bottom = Dest3B
        MOVNE   R3, R7                  ; else top = Dest3T

        TEQ     R0, R4                  ; if Dest2L = Dest3L
        ADDEQ   R0, R6, #1              ; then left = Dest3R +1
        SUBNE   R2, R4, #1              ; else right = Dest3L -1

        CMP     R3, R1                  ; if top >= bottom
        CMPGE   R2, R0                  ; and right >= left
        BLGE    RectFillA               ; then fill it

        Pull    PC


        END