home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Exec 4 / CD_Magazyn_EXEC_nr_4.iso / Recent / util / boot / NewCMQ060.lha / NewCMQ060 / src / CMQ060.ASM
Assembly Source File  |  2000-09-11  |  24KB  |  1,154 lines

  1. ; FILE: Source:CMQ060.ASM          REV: 10 --- ultrafast CopyMemQuick060
  2. ; History
  3. ;  0      Based on CMQ060 v1.4 by Dirk Busse.
  4. ;  1      Fixed major bug from the patch install: If the memory was
  5. ;         allocated near 64k boundary CMQ060 trashed innocent memory.
  6. ;  2      Removed two pipeline stalls from bigcopy. Speedup for all big
  7. ;         copies.
  8. ;  3      Optimized non-move16 copy loop, now it uses movem instead of
  9. ;         move.l. Speedup for big unaligned copies.
  10. ;  4      Unrolled the bigcopy-loops to do 256 bytes per iteration.
  11. ;         Speedup for all big copies.
  12. ;  5      Added MorphOS check, it makes no sense to slow down MorphOS with
  13. ;         m68k patches.
  14. ;  6      Now pick move-loop for 68040 since it's faster (Thanks Chip!).
  15. ;  7      Added odd-movem-defect test to patch init: If the bus controller
  16. ;         fail to supply correct data for odd-movem burst line read, will
  17. ;         install patch without movem. Special thanks to Harald Frank who
  18. ;         patiently explained the problem to me.
  19. ;  8      Oops, forgot to set up the special MMU & Cache setup in the odd-
  20. ;         movem-defect test. Barfed with native ppc.library for example.
  21. ;  9      Fixed comments, made the source compile with PhxAss.
  22. ;  10     Reordered pflusha + movec dn,tc properly.
  23. ;
  24.  
  25.     include    "exec/types.i"
  26.     include    "exec/libraries.i"
  27.     include    "exec/memory.i"
  28.     include    "exec/execbase.i"
  29.     include    "exec/exec_lib.i"
  30. call    MACRO
  31.     jsr    (_LVO\1,a6)
  32.     ENDM
  33.  
  34.  
  35. USE_MOVE16    EQU    1        ; use move16 ?
  36. SAFE_MOVE16    EQU    1        ; don't use move16 for 24bit mem ?
  37. USE_MOVEM    EQU    1        ; use movem ?
  38. SAFE_MOVEM    EQU    1        ; include odd-movem-defect test ?
  39.  
  40. SPEEDTEST    EQU    0        ; enable to speedtest
  41.  
  42.  
  43.     IFNE    SPEEDTEST
  44. _LVOSubTime    EQU    -$30
  45. _LVOReadEClock    EQU    -$3C
  46.  
  47. Main    move.l    (4).w,a6
  48.     call    Forbid
  49.  
  50.     move.l    d0,d7
  51.  
  52.     lea    (DeviceList,a6),a0
  53.     lea    (.timername,pc),a1
  54.     call    FindName
  55.     move.l    d0,d6
  56.  
  57.     move.l    #500000/100/2/2,d3
  58.  
  59.     lea    _src+0,a2
  60.     lea    _dst+8,a3
  61.     ;move.l    #65536+3,d2
  62.     ;move.l    #32768,d2
  63.     ;move.l    #3,d2
  64.     move.l    #4096,d2
  65.  
  66.     ;lea    Quickest,a4
  67.     lea    PatchStart,a4
  68.     subq.l    #1,d7
  69.     beq.b    .skip
  70.     ;lea    new_CopyMemQuick,a4
  71.     lea    new_CopyMem,a4
  72. .skip
  73.     call    CacheClearU
  74.  
  75.     exg    d6,a6
  76.     lea    (.start,pc),a0
  77.     call    ReadEClock
  78.     exg    d6,a6
  79.     bra.b    .loop
  80.  
  81.     CNOP    0,4
  82. .loop
  83.     REPT    16
  84.     move.l    a2,a0
  85.     move.l    a3,a1
  86.     move.l    d2,d0
  87.     jsr    (a4)
  88.     ENDR
  89.  
  90.     subq.l    #1,d3
  91.     bne    .loop
  92.  
  93.     exg    d6,a6
  94.     lea    (.end,pc),a0
  95.     call    ReadEClock
  96.     exg    d6,a6
  97.     call    Permit
  98.     move.l    d0,d2
  99.  
  100.     exg    d6,a6
  101.     lea    (.end,pc),a0
  102.     lea    (.start,pc),a1
  103.     call    SubTime
  104.     exg    d6,a6
  105.  
  106.     move.l    (.end+4,pc),d0
  107.     mulu.l    #1000000,d1:d0
  108.     divu.l    d2,d1:d0
  109.     rts
  110.  
  111. .timername    dc.b    'timer.device',0
  112.  
  113.     CNOP    0,4
  114. .start    ds.l    2
  115. .end    ds.l    2
  116.  
  117.  
  118.     SECTION    TEST,BSS
  119.  
  120. _src    ds.b    32768*2
  121. _dst    ds.b    32768*2
  122.     ds.b    32768            ; sanity
  123.  
  124.  
  125.     SECTION    B,CODE
  126.  
  127.     ELSE
  128.  
  129. Main    move.l    (4).w,a6
  130.     btst    #AFB_68040,(AttnFlags+1,a6)
  131.     bne.b    .ok040plus
  132. .nomem    moveq    #20,d0
  133.     rts
  134.  
  135.     dc.b    '$VER: CMQ060'
  136.     IFEQ    SAFE_MOVE16
  137.     dc.b    '_Move16'
  138.     ENDC
  139.     dc.b    ' 1.5 (11.9.2000)',0
  140. .morphosname
  141.     dc.b    'MorphOS',0
  142.     CNOP    0,2
  143.  
  144. .ok040plus
  145.     lea    (.morphosname,pc),a1
  146.     call    FindResident
  147.     tst.l    d0
  148.     beq.b    .no_morphos
  149.     moveq    #5,d0
  150.     rts
  151. .no_morphos
  152.     IFNE    USE_MOVEM
  153.  
  154.     lea    (.testcode,pc),a5
  155.     call    Disable
  156.     call    Supervisor
  157.     call    Enable
  158.     ; d0 = status
  159.  
  160.     ; movem routine defines
  161.     lea    (COPY,pc),a5
  162.     move.w    #COPY_SIZEOF,d6
  163.     move.w    #new_CopyMemQuick-COPY,d7
  164.  
  165.     tst.l    d0            ; can we use movem ?
  166.     beq.b    .use_movem
  167.  
  168.     ; move routine defines
  169.     lea    (COPY_MOVE,pc),a5
  170.     move.w    #COPY_MOVE_SIZEOF,d6
  171.     move.w    #new_CopyMemQuick_MOVE-COPY_MOVE,d7
  172. .use_movem
  173.     moveq    #15,d0
  174.     moveq    #MEMF_PUBLIC,d1
  175.     add.w    d6,d0
  176.     moveq    #8,d2
  177.     call    AllocMem
  178.     and.l    d0,d2
  179.     add.l    d2,d0            ; d0 = address aligned to 16
  180.     beq    .nomem
  181.     move.l    a5,a0
  182.     move.l    d0,a1
  183.     move.l    d0,a2
  184.     move.w    d6,d0            ; kindof a hack :-)
  185.     bsr    _smallcopy
  186.     move.w    #_LVOCopyMem,a0        ; some nice code reuse here...
  187.     bsr.b    .sfunc
  188.     move.w    #_LVOCopyMemQuick,a0
  189. .sfunc    move.l    a2,d0
  190.     add.w    d7,a2
  191.     move.l    a6,a1
  192.     call    SetFunction
  193.     moveq    #0,d0
  194.     rts
  195.  
  196. .testcode
  197.     ori.w    #$0700,sr
  198.  
  199.     moveq    #0,d0
  200.  
  201.     tst.b    (AttnFlags+1,a6)
  202.     bmi.b    .has_060
  203.  
  204.     ; test 060
  205.     movec    vbr,a0
  206.     lea    (.illegal,pc),a1
  207.     move.l    ($10,a0),-(sp)
  208.     move.l    ($2C,a0),-(sp)
  209.     move.l    a1,($10,a0)
  210.     move.l    a1,($2C,a0)
  211.     cpusha    bc
  212.     cinva    bc
  213.  
  214.     dc.w    $4E7A,$1008        ; movec buscr,d1
  215.     dc.w    $4E7A,$1808        ; movec pcr,d1
  216. .exitillegal
  217.     nop
  218.     move.l    (sp)+,($2C,a0)
  219.     move.l    (sp)+,($10,a0)
  220.     cpusha    bc
  221.     cinva    bc
  222. .has_060
  223.  
  224.     IFNE    SAFE_MOVEM
  225.  
  226.     ; figure out if to use movem or not
  227.     ; ---------------------------------
  228.     ;
  229.     ; Use move-loop for 68040.
  230.     ;
  231.     ; For 68060 this code tries to trigger the
  232.     ; movem-at-odd-address-burst-line-read bug of
  233.     ; some CPU cards (early Cyberstorm models?).
  234.     ;
  235.     ; Some amiga 060 turbo cards don't have special
  236.     ; hardware to handle writebuffer burst write
  237.     ; -> undefined behavior.
  238.     ;
  239.     ; This routine will disable MMU mapping, set up
  240.     ; transparent translation so that whole system
  241.     ; memory is marked "non-cacheable, imprecise"
  242.     ; and then probe whole system memory with 68060
  243.     ; Store Buffer, using skip of 512K.
  244.     ;
  245. .testbeg
  246.     tst.l    d0            ; got 68040 ?
  247.     bne    .texit            ; yep, don't bother
  248.  
  249.     movec    itt0,d1
  250.     movec    itt1,d2
  251.     movec    dtt0,d3
  252.     movec    dtt1,d4
  253.     movec    cacr,d5
  254.     movec    tc,d6
  255.     movem.l    d1-d6/a6,-(sp)
  256.  
  257.     cpusha    bc
  258.     cinva    bc
  259.     move.l    #$00FFC000,d1        ; LAmask=$ff E=%1 S=%10 (Ignore FC2 when matching), CM=%00 (Cacheable, Writethrough), W=%0 (R/W)1
  260.     move.l    #$00FFC060,d2        ; LAmask=$ff E=%1 S=%10 (Ignore FC2 when matching), CM=%11 (Cache-Inhibited, Imprecise Exception Model)), W=%0 (R/W)
  261.     move.l    #(1<<31)|(1<<15),d5    ; EDC = 1 (Enable Data Cache), ESB = 0 (Disable Store Buffer), EIC = 1 (Enable Instruction Cache)
  262.     and.w    #~$8000,d6        ; Mask out E-bit
  263.     movec    d1,itt0
  264.     movec    d1,itt1
  265.     movec    d2,dtt0
  266.     movec    d2,dtt1
  267.     movec    d5,cacr
  268.     pflusha
  269.     movec    d6,tc
  270.     cpusha    bc
  271.  
  272.     lea    (MemList,a6),a4
  273.     move.l    #$5555aaaa,d6
  274.     move.l    #$aaaa5555,d7
  275.  
  276. .scan    move.l    (a4),a4
  277.     tst.l    (a4)
  278.     beq    .scandone
  279.  
  280.     ; only PUBLIC memory areas
  281.     btst    #MEMB_PUBLIC,(MH_ATTRIBUTES+1,a4)
  282.     beq.b    .scan
  283.  
  284.     ; figure out scan area
  285.     moveq    #4+15,d0
  286.     moveq    #-(12*4),d1
  287.     add.l    (MH_LOWER,a4),d0
  288.     add.l    (MH_UPPER,a4),d1
  289.     and.w    #-16,d0            ; align to cacheline
  290.     and.w    #-16,d1
  291.  
  292.     ; sanity check
  293.     cmp.l    d1,d0
  294.     bhs.b    .scan
  295.  
  296.     subq.l    #4,d0            ; get back one longword
  297.     subq.l    #4,d1
  298.     move.l    d0,a6
  299.  
  300. ;line1 -+-------- line2 --------+-------- line3 --------+- line4 --
  301. ;       |                       |                       |
  302. ;2,$3333,$0000,$1111,$2222,$3333,$0000,$1111,$2222,$3333,$0000,$1111
  303.  
  304.     movem.l    d1/a4,-(sp)
  305. .testloop
  306.     ; is the address inside this code?
  307.     lea    (.testend,pc),a0    ; testend < addr ?
  308.     cmp.l    a0,a6
  309.     bhi.b    .not_inside
  310.     lea    (.testbeg,pc),a0    ; testbeg < addr ?
  311.     cmp.l    a0,a6
  312.     bls.b    .inside
  313. .not_inside
  314.     ; is the stack somewhere close?
  315.     lea    (8192,a7),a0        ; testend < addr ?
  316.     cmp.l    a0,a6
  317.     bhi.b    .not_inside2
  318.     lea    (-8192,a7),a0        ; testbeg < addr ?
  319.     cmp.l    a0,a6
  320.     bls.b    .inside
  321. .not_inside2
  322.     ; backup the memory
  323.     movem.l    (a6),d0-d5/a0-a5
  324.     movem.l    d0-d5/a0-a5,-(sp)
  325.     cpusha    dc
  326.  
  327.     ; turn on store buffer
  328.     move.l    #(1<<31)|(1<<29)|(1<<15),d0 ; EDC = 1 (Enable Data Cache), ESB = 1 (Enable Store Buffer), EIC = 1 (Enable Instruction Cache)
  329.     movec    d0,cacr
  330.  
  331.     addq.l    #1,a6
  332.     bsr.b    .anaali
  333.  
  334.     addq.l    #2,a6
  335.     bsr.b    .anaali
  336.  
  337.     subq.l    #3,a6
  338.  
  339.     ; turn off store buffer
  340.     move.l    #(1<<31)|(1<<15),d0    ; EDC = 1 (Enable Data Cache), ESB = 0 (Disable Store Buffer), EIC = 1 (Enable Instruction Cache)
  341.     movec    d0,cacr
  342.  
  343.     ; restore orig memory
  344.     movem.l    (sp)+,d0-d5/a0-a5
  345.     movem.l    d0-d5/a0-a5,(a6)
  346.     cpusha    dc
  347. .inside
  348.     ; advance 512K
  349.     add.l    #$80000,a6
  350.     cmp.l    (sp),a6            ; (sp) = upper limit
  351.     blo    .testloop
  352.  
  353.     movem.l    (sp)+,d1/a4
  354.     bra    .scan
  355. .anaali
  356.     bsr.b    .flush
  357.     ; write a test bitset
  358.     ; make sure we actually do read the memory
  359.     ; instead of the cache
  360.     bsr.b    .writeset
  361.     ; read the test bitset back & analyze result
  362.     bsr.b    .anal
  363.     ; trash the set...
  364.     exg    d6,d7
  365.     bsr.b    .writeset
  366.     exg    d6,d7
  367.     ; write the bitset with movem
  368.     move.l    d6,a0
  369.     move.l    d7,a1
  370.     move.l    d6,a2
  371.     movem.l    d0-d5/a0-a4,(a6)
  372.     ; make sure we actually do read the memory
  373.     ; instead of the cache
  374.     bsr.b    .flush
  375.     ; read the test bitset back & analyze result
  376.     bsr.b    .anal            ; must not bra!
  377.     rts
  378.  
  379. .writeset    move.l    d6,(a6)            ; d0
  380.     move.l    d7,(1*4,a6)        ; d1
  381.     move.l    d6,(2*4,a6)        ; d2
  382.     move.l    d7,(3*4,a6)        ; d3
  383.     move.l    d6,(4*4,a6)        ; d4
  384.     move.l    d7,(5*4,a6)        ; d5
  385.     move.l    d6,(6*4,a6)        ; a0
  386.     move.l    d7,(7*4,a6)        ; a1
  387.     move.l    d6,(8*4,a6)        ; a2
  388.     move.l    d7,(9*4,a6)        ; a3
  389.     move.l    d6,(10*4,a6)        ; a4
  390.  
  391. .flush    lea    (4,a6),a2
  392.     lea    (4+16,a6),a1
  393.     lea    (4+32,a6),a0
  394.     cpushl    dc,(a6)
  395.     cpushl    dc,(a2)
  396.     cpushl    dc,(a1)
  397.     cpushl    dc,(a0)
  398.     rts
  399.  
  400. .anal    movem.l    (a6),d0-d5/a0-a4
  401.     cmp.l    d6,d0
  402.     bne.b    .use_move
  403.     cmp.l    d7,d1
  404.     bne.b    .use_move
  405.     cmp.l    d6,d2
  406.     bne.b    .use_move
  407.     cmp.l    d7,d3
  408.     bne.b    .use_move
  409.     cmp.l    d6,d4
  410.     bne.b    .use_move
  411.     cmp.l    d7,d5
  412.     bne.b    .use_move
  413.     cmp.l    d6,a0
  414.     bne.b    .use_move
  415.     cmp.l    d7,a1
  416.     bne.b    .use_move
  417.     cmp.l    d6,a2
  418.     bne.b    .use_move
  419.     cmp.l    d7,a3
  420.     bne.b    .use_move
  421.     cmp.l    d6,a4
  422.     beq.b    .flush
  423. .use_move
  424.     addq.l    #2*4,sp            ; pop return addresses
  425.     ; align a6 to orig
  426.     move.l    a6,d0
  427.     and.w    #-4,d0
  428.     move.l    d0,a6
  429.  
  430.     ; turn off store buffer
  431.     move.l    #(1<<31)|(1<<15),d0    ; EDC = 1 (Enable Data Cache), ESB = 0 (Disable Store Buffer), EIC = 1 (Enable Instruction Cache)
  432.     movec    d0,cacr
  433.  
  434.     ; restore orig memory
  435.     movem.l    (sp)+,d0-d5/a0-a5
  436.     movem.l    d0-d5/a0-a5,(a6)
  437.     cpusha    dc
  438.  
  439.     addq.l    #2*4,sp            ; pop stack
  440.  
  441.     ; indicate move-mode
  442.     moveq    #1,d0
  443.     dc.w    $51FA            ; trapf.w #x
  444. .scandone
  445.     moveq    #0,d0
  446.  
  447.     movem.l    (sp)+,d1-d6/a6
  448.     cpusha    bc
  449.     movec    d1,itt0
  450.     movec    d2,itt1
  451.     movec    d3,dtt0
  452.     movec    d4,dtt1
  453.     movec    d5,cacr
  454.     pflusha
  455.     movec    d6,tc
  456.     cpusha    bc
  457.     cinva    bc
  458. .texit
  459.     ENDC
  460.  
  461.     nop
  462.     rte
  463.  
  464. .illegal
  465.     ; oops, this is a 68040
  466.  
  467.     lea    (.exitillegal,pc),a1
  468.     moveq    #1,d0
  469.     move.l    a1,(2,sp)
  470.     nop
  471.     rte
  472. .testend
  473.  
  474.     ELSE
  475.  
  476.     ; NOTE: d0.l = 0
  477.     IFD    _PHXASS_
  478.     move.w    #COPY_SIZEOF+8+7,d0
  479.     ELSE
  480.     move.w    #(COPY_SIZEOF+8+7)&-8,d0
  481.     ENDC
  482.     moveq    #MEMF_PUBLIC,d1
  483.     moveq    #8,d2
  484.     call    AllocMem
  485.     and.l    d0,d2
  486.     add.l    d2,d0            ; d0 = address aligned to 16
  487.     beq.b    .nomem
  488.     lea    (COPY,pc),a0
  489.     move.l    d0,a1
  490.     move.l    d0,a2
  491.     move.w    #COPY_SIZEOF,d0        ; kindof a hack :-)
  492.     bsr.b    _smallcopy
  493.     move.w    #_LVOCopyMem,a0        ; some nice code reuse here...
  494.     bsr.b    .sfunc
  495.     move.w    #_LVOCopyMemQuick,a0
  496. .sfunc    move.l    a2,d0
  497.     lea    (new_CopyMemQuick-COPY,a2),a2
  498.     move.l    a6,a1
  499.     call    SetFunction
  500.     moveq    #0,d0
  501.     rts
  502.  
  503.     ENDC
  504.  
  505.     ENDC
  506.  
  507.  
  508.     IFD    _PHXASS_
  509.     CNOP    0,16
  510.     ENDC
  511.  
  512. COPY
  513. new_CopyMem
  514.     tst.l    d0            ; zero len copy?
  515.     beq.b    _exit            ; yep, quit
  516.     move.w    a1,d1
  517.     btst    #0,d1            ; destination aligned by 2?
  518.     beq.b    .dst_align2        ; yep, try 4
  519.     move.b    (a0)+,(a1)+        ; do the byte
  520.     subq.l    #1,d0            ; sub count
  521.     beq.b    _exit            ; was the only byte, quit!
  522.     move.w    a1,d1
  523. .dst_align2
  524.     btst    #1,d1            ; destination aligned by 4?
  525.     beq.b    .dst_align4        ; yep, try big copy
  526.  
  527.     cmpi.l    #1,d0
  528.     bne.b    .not_byte
  529. .copy_byte
  530.     move.b    (a0)+,(a1)+        ; copy last byte
  531.     rts
  532. .not_byte
  533.     move.w    (a0)+,(a1)+        ; do the word
  534.     subq.l    #2,d0            ; sub count
  535.     beq.b    _exit            ; was the only word, quit!
  536. .dst_align4
  537.     ; now destination is longword aligned
  538.     cmpi.l    #(2048+16),d0        ; worth the trouble?
  539.     bcc.b    _bigcopy        ; yep, do fast copy
  540. _smallcopy
  541.     move.w    d0,d1
  542.     lsr.w    #2,d1
  543.     beq.b    .nolongs
  544. .copy    move.l    (a0)+,(a1)+
  545.     subq.w    #1,d1
  546.     bne.b    .copy
  547. .nolongs
  548.     btst    #1,d0            ; long copy done, one word left?
  549.     beq.b    .no_last_word        ; nope
  550.     move.w    (a0)+,(a1)+        ; copy last word
  551. .no_last_word
  552.     btst    #0,d0            ; one byte left?
  553.     beq.b    .no_last_byte        ; nope
  554.     move.b    (a0)+,(a1)+        ; copy last byte
  555. .no_last_byte
  556. _exit    rts
  557.  
  558. _bigcopy
  559.     IFNE    USE_MOVE16
  560.     IFNE    SAFE_MOVE16
  561.     cmp.l    #$01000000,a0
  562.     bcs.b    .bigcopy_nomove16
  563.     move.w    a1,d1
  564.     cmp.l    #$01000000,a1
  565.     bcs.b    .bigcopy_nomove16
  566.     ELSE
  567.     move.w    a1,d1
  568.     ENDC
  569.  
  570.     btst    #2,d1            ; destination aligned by 8?
  571.     beq.b    .dst_align8        ; yep, try 16
  572.     move.l    (a0)+,(a1)+        ; nope, make it!
  573.     addq.w    #4,d1
  574.     subq.l    #4,d0
  575. .dst_align8
  576.     btst    #3,d1            ; destination aligned by 16?
  577.     beq.b    .dst_align16        ; yep, try source
  578.     move.l    (a0)+,(a1)+        ; nope, make it!
  579.     move.l    (a0)+,(a1)+
  580.     subq.l    #8,d0
  581. .dst_align16
  582.     move.w    a0,d1
  583.     and.w    #15,d1            ; source aligned by 16?
  584.     bne.b    .bigcopy_nomove16    ; nope, so lets use normal copy
  585.  
  586.     ; source: aligned by 16
  587.     ; destination: aligned by 16
  588.  
  589.     move.l    d0,d1
  590.     lsr.l    #8,d1            ; copy 256 bytes per go
  591. .copy256
  592.     REPT    16
  593.     move16    (a0)+,(a1)+
  594.     ENDR
  595.     subq.l    #1,d1
  596.     bne.b    .copy256
  597.     and.w    #255,d0            ; handle rest if needed
  598.     bne    _smallcopy
  599.     rts
  600.  
  601. .bigcopy_nomove16
  602.     ENDC
  603.  
  604.     IFNE    USE_MOVEM
  605.  
  606.     ; unrolled movem.l loop, using 12 registers
  607.     movem.l    d0/d2-d7/a2-a6,-(sp)
  608.     lsr.l    #8,d0            ; copy 256 bytes per go
  609. .mcopy256
  610.     movem.l    (a0)+,d1-d7/a2-a6    ; 12*4=48
  611.     movem.l    d1-d7/a2-a6,(a1)
  612.     movem.l    (a0)+,d1-d7/a2-a6    ; 12*4=48
  613.     movem.l    d1-d7/a2-a6,(1*48,a1)
  614.     movem.l    (a0)+,d1-d7/a2-a6    ; 12*4=48
  615.     movem.l    d1-d7/a2-a6,(2*48,a1)
  616.     movem.l    (a0)+,d1-d7/a2-a6    ; 12*4=48
  617.     movem.l    d1-d7/a2-a6,(3*48,a1)
  618.     movem.l    (a0)+,d1-d7/a2-a6    ; 12*4=48
  619.     movem.l    d1-d7/a2-a6,(4*48,a1)
  620.     movem.l    (a0)+,d1-d4        ; 4*4=16
  621.     movem.l    d1-d4,(5*48,a1)
  622.     subq.l    #1,d0
  623.     lea    (256,a1),a1
  624.     bne.b    .mcopy256
  625.     movem.l    (sp)+,d0/d2-d7/a2-a6
  626.     and.w    #255,d0            ; handle rest if needed
  627.  
  628.     ELSE
  629.  
  630.     ; unrolled move.l loop
  631.     move.l    d0,d1
  632.     lsr.l    #6,d1            ; copy 64 bytes per go
  633. .mcopy64
  634.     REPT    16
  635.     move.l    (a0)+,(a1)+
  636.     ENDR
  637.     subq.l    #1,d1
  638.     bne.b    .mcopy64
  639.     and.w    #63,d0            ; handle rest if needed
  640.  
  641.     ENDC
  642.     bne    _smallcopy
  643.     rts
  644.  
  645.  
  646.     IFD    _PHXASS_
  647.     CNOP    0,16
  648.     ELSE
  649.     IFGT    16-((*-COPY)&15)
  650.     dcb.w    (16-((*-COPY)&15))>>1,$51FC
  651.     ENDC
  652.     ENDC
  653.  
  654. new_CopyMemQuick
  655.     lsr.l    #2,d0            ; bytes -> longswords
  656.     cmpi.l    #(2048+16)>>2,d0    ; worth the trouble?
  657.     bcc.b    .bigcopy        ; yep, do fast copy
  658.     tst.w    d0
  659.     beq.b    .exit            ; nothing to copy, quit!
  660. .smallcopy
  661. .copy    move.l    (a0)+,(a1)+
  662.     subq.w    #1,d0
  663.     bne.b    .copy
  664. .exit    rts
  665.  
  666. .bigcopy
  667.     IFNE    USE_MOVE16
  668.     IFNE    SAFE_MOVE16
  669.     cmp.l    #$01000000,a0
  670.     bcs.b    .bigcopy_nomove16
  671.     move.w    a1,d1
  672.     cmp.l    #$01000000,a1
  673.     bcs.b    .bigcopy_nomove16
  674.     ELSE
  675.     move.w    a1,d1
  676.     ENDC
  677.  
  678.     btst    #2,d1            ; destination aligned by 8?
  679.     beq.b    .dst_align8        ; yep, try 16
  680.     move.l    (a0)+,(a1)+        ; nope, make it!
  681.     addq.w    #4,d1
  682.     subq.l    #4>>2,d0
  683. .dst_align8
  684.     btst    #3,d1            ; destination aligned by 16?
  685.     beq.b    .dst_align16        ; yep, try source
  686.     move.l    (a0)+,(a1)+        ; nope, make it!
  687.     move.l    (a0)+,(a1)+
  688.     subq.l    #8>>2,d0
  689. .dst_align16
  690.     move.w    a0,d1
  691.     and.w    #15,d1            ; source aligned by 16?
  692.     bne.b    .bigcopy_nomove16    ; nope, so lets use normal copy
  693.  
  694.     ; source: aligned by 16
  695.     ; destination: aligned by 16
  696.  
  697.     move.l    d0,d1
  698.     lsr.l    #8-2,d1            ; copy 256 bytes per go
  699. .copy256
  700.     REPT    16
  701.     move16    (a0)+,(a1)+
  702.     ENDR
  703.     subq.l    #1,d1
  704.     bne.b    .copy256
  705.     and.w    #255>>2,d0        ; handle rest if needed
  706.     bne    .smallcopy
  707.     rts
  708.  
  709. .bigcopy_nomove16
  710.     ENDC
  711.  
  712.     IFNE    USE_MOVEM
  713.  
  714.     ; unrolled movem.l loop, using 12 registers
  715.     movem.l    d0/d2-d7/a2-a6,-(sp)
  716.     lsr.l    #8-2,d0            ; copy 256 bytes per go
  717. .mcopy256
  718.     movem.l    (a0)+,d1-d7/a2-a6    ; 12*4=48
  719.     movem.l    d1-d7/a2-a6,(a1)
  720.     movem.l    (a0)+,d1-d7/a2-a6    ; 12*4=48
  721.     movem.l    d1-d7/a2-a6,(1*48,a1)
  722.     movem.l    (a0)+,d1-d7/a2-a6    ; 12*4=48
  723.     movem.l    d1-d7/a2-a6,(2*48,a1)
  724.     movem.l    (a0)+,d1-d7/a2-a6    ; 12*4=48
  725.     movem.l    d1-d7/a2-a6,(3*48,a1)
  726.     movem.l    (a0)+,d1-d7/a2-a6    ; 12*4=48
  727.     movem.l    d1-d7/a2-a6,(4*48,a1)
  728.     movem.l    (a0)+,d1-d4        ; 4*4=16
  729.     movem.l    d1-d4,(5*48,a1)
  730.     subq.l    #1,d0
  731.     lea    (256,a1),a1
  732.     bne.b    .mcopy256
  733.     movem.l    (sp)+,d0/d2-d7/a2-a6
  734.     and.w    #255>>2,d0        ; handle rest if needed
  735.  
  736.     ELSE
  737.  
  738.     ; unrolled move.l loop
  739.     move.l    d0,d1
  740.     lsr.l    #6-2,d1            ; copy 64 bytes per go
  741. .mcopy64
  742.     REPT    16
  743.     move.l    (a0)+,(a1)+
  744.     ENDR
  745.     subq.l    #1,d1
  746.     bne.b    .mcopy64
  747.     and.w    #63>>2,d0        ; handle rest if needed
  748.  
  749.     ENDC
  750.     bne    .smallcopy
  751.     rts
  752.  
  753.  
  754. COPY_SIZEOF    EQU    (*-COPY)
  755.  
  756.  
  757.     IFNE    USE_MOVEM&SAFE_MOVEM
  758.  
  759.  
  760.     IFD    _PHXASS_
  761.     CNOP    0,16
  762.     ENDC
  763. COPY_MOVE
  764. new_CopyMem_MOVE
  765.     tst.l    d0            ; zero len copy?
  766.     beq.b    .exit            ; yep, quit
  767.     move.w    a1,d1
  768.     btst    #0,d1            ; destination aligned by 2?
  769.     beq.b    .dst_align2        ; yep, try 4
  770.     move.b    (a0)+,(a1)+        ; do the byte
  771.     subq.l    #1,d0            ; sub count
  772.     beq.b    .exit            ; was the only byte, quit!
  773.     move.w    a1,d1
  774. .dst_align2
  775.     btst    #1,d1            ; destination aligned by 4?
  776.     beq.b    .dst_align4        ; yep, try big copy
  777.  
  778.     cmpi.l    #1,d0
  779.     bne.b    .not_byte
  780. .copy_byte
  781.     move.b    (a0)+,(a1)+        ; copy last byte
  782.     rts
  783. .not_byte
  784.     move.w    (a0)+,(a1)+        ; do the word
  785.     subq.l    #2,d0            ; sub count
  786.     beq.b    .exit            ; was the only word, quit!
  787. .dst_align4
  788.     ; now destination is longword aligned
  789.     cmpi.l    #(2048+16),d0        ; worth the trouble?
  790.     bcc.b    .bigcopy        ; yep, do fast copy
  791. .smallcopy
  792.     move.w    d0,d1
  793.     lsr.w    #2,d1
  794.     beq.b    .nolongs
  795. .copy    move.l    (a0)+,(a1)+
  796.     subq.w    #1,d1
  797.     bne.b    .copy
  798. .nolongs
  799.     btst    #1,d0            ; long copy done, one word left?
  800.     beq.b    .no_last_word        ; nope
  801.     move.w    (a0)+,(a1)+        ; copy last word
  802. .no_last_word
  803.     btst    #0,d0            ; one byte left?
  804.     beq.b    .no_last_byte        ; nope
  805.     move.b    (a0)+,(a1)+        ; copy last byte
  806. .no_last_byte
  807. .exit    rts
  808.  
  809. .bigcopy
  810.     IFNE    USE_MOVE16
  811.     IFNE    SAFE_MOVE16
  812.     cmp.l    #$01000000,a0
  813.     bcs.b    .bigcopy_nomove16
  814.     move.w    a1,d1
  815.     cmp.l    #$01000000,a1
  816.     bcs.b    .bigcopy_nomove16
  817.     ELSE
  818.     move.w    a1,d1
  819.     ENDC
  820.  
  821.     btst    #2,d1            ; destination aligned by 8?
  822.     beq.b    .dst_align8        ; yep, try 16
  823.     move.l    (a0)+,(a1)+        ; nope, make it!
  824.     addq.w    #4,d1
  825.     subq.l    #4,d0
  826. .dst_align8
  827.     btst    #3,d1            ; destination aligned by 16?
  828.     beq.b    .dst_align16        ; yep, try source
  829.     move.l    (a0)+,(a1)+        ; nope, make it!
  830.     move.l    (a0)+,(a1)+
  831.     subq.l    #8,d0
  832. .dst_align16
  833.     move.w    a0,d1
  834.     and.w    #15,d1            ; source aligned by 16?
  835.     bne.b    .bigcopy_nomove16    ; nope, so lets use normal copy
  836.  
  837.     ; source: aligned by 16
  838.     ; destination: aligned by 16
  839.  
  840.     move.l    d0,d1
  841.     lsr.l    #8,d1            ; copy 256 bytes per go
  842. .copy256
  843.     REPT    16
  844.     move16    (a0)+,(a1)+
  845.     ENDR
  846.     subq.l    #1,d1
  847.     bne.b    .copy256
  848.     and.w    #255,d0            ; handle rest if needed
  849.     bne    .smallcopy
  850.     rts
  851.  
  852. .bigcopy_nomove16
  853.     ENDC
  854.  
  855.     ; unrolled move.l loop
  856.     move.l    d0,d1
  857.     lsr.l    #6,d1            ; copy 64 bytes per go
  858. .mcopy64
  859.     REPT    16
  860.     move.l    (a0)+,(a1)+
  861.     ENDR
  862.     subq.l    #1,d1
  863.     bne.b    .mcopy64
  864.     and.w    #63,d0            ; handle rest if needed
  865.     bne    .smallcopy
  866.     rts
  867.  
  868.  
  869.     IFD    _PHXASS_
  870.     CNOP    0,16
  871.     ELSE
  872.     IFGT    16-((*-COPY_MOVE)&15)
  873.     dcb.w    (16-((*-COPY_MOVE)&15))>>1,$51FC
  874.     ENDC
  875.     ENDC
  876.  
  877. new_CopyMemQuick_MOVE
  878.     lsr.l    #2,d0            ; bytes -> longswords
  879.     cmpi.l    #(2048+16)>>2,d0    ; worth the trouble?
  880.     bcc.b    .bigcopy        ; yep, do fast copy
  881.     tst.w    d0
  882.     beq.b    .exit            ; nothing to copy, quit!
  883. .smallcopy
  884. .copy    move.l    (a0)+,(a1)+
  885.     subq.w    #1,d0
  886.     bne.b    .copy
  887. .exit    rts
  888.  
  889. .bigcopy
  890.     IFNE    USE_MOVE16
  891.     IFNE    SAFE_MOVE16
  892.     cmp.l    #$01000000,a0
  893.     bcs.b    .bigcopy_nomove16
  894.     move.w    a1,d1
  895.     cmp.l    #$01000000,a1
  896.     bcs.b    .bigcopy_nomove16
  897.     ELSE
  898.     move.w    a1,d1
  899.     ENDC
  900.  
  901.     btst    #2,d1            ; destination aligned by 8?
  902.     beq.b    .dst_align8        ; yep, try 16
  903.     move.l    (a0)+,(a1)+        ; nope, make it!
  904.     addq.w    #4,d1
  905.     subq.l    #4>>2,d0
  906. .dst_align8
  907.     btst    #3,d1            ; destination aligned by 16?
  908.     beq.b    .dst_align16        ; yep, try source
  909.     move.l    (a0)+,(a1)+        ; nope, make it!
  910.     move.l    (a0)+,(a1)+
  911.     subq.l    #8>>2,d0
  912. .dst_align16
  913.     move.w    a0,d1
  914.     and.w    #15,d1            ; source aligned by 16?
  915.     bne.b    .bigcopy_nomove16    ; nope, so lets use normal copy
  916.  
  917.     ; source: aligned by 16
  918.     ; destination: aligned by 16
  919.  
  920.     move.l    d0,d1
  921.     lsr.l    #8-2,d1            ; copy 256 bytes per go
  922. .copy256
  923.     REPT    16
  924.     move16    (a0)+,(a1)+
  925.     ENDR
  926.     subq.l    #1,d1
  927.     bne.b    .copy256
  928.     and.w    #255>>2,d0        ; handle rest if needed
  929.     bne    .smallcopy
  930.     rts
  931.  
  932. .bigcopy_nomove16
  933.     ENDC
  934.  
  935.     ; unrolled move.l loop
  936.     move.l    d0,d1
  937.     lsr.l    #6-2,d1            ; copy 64 bytes per go
  938. .mcopy64
  939.     REPT    16
  940.     move.l    (a0)+,(a1)+
  941.     ENDR
  942.     subq.l    #1,d1
  943.     bne.b    .mcopy64
  944.     and.w    #63>>2,d0        ; handle rest if needed
  945.     bne    .smallcopy
  946.     rts
  947.  
  948.  
  949. COPY_MOVE_SIZEOF    EQU    (*-COPY_MOVE)
  950.  
  951.     ENDC
  952.  
  953.  
  954.     IFNE    SPEEDTEST
  955.  
  956.     SECTION    C,CODE
  957.  
  958. *******************************************
  959. *            CopyMemQuicker060            *
  960. * Uses Move16 only in Adresses >$00ffffff *
  961. *                                         *
  962. *            Include File V1.4            *
  963. *          written by Dirk Busse          *
  964. *               3. Apr. 1999              *
  965. *******************************************
  966.  
  967. PatchStart
  968.  
  969.         tst.l   d0
  970.         beq.b   squit
  971.         move.w  a1,d1   ;Zieladresse nach d1 (nur die ersten zwei Bits werden benötigt)
  972.         btst    #0,d1
  973.         beq.b   .skip1
  974.         move.b  (a0)+,(a1)+    ;Zieladresse auf EVEN setzen
  975.         subq.l  #1,d0
  976.         beq.b   squit
  977.         move.w  a1,d1
  978. .skip1  btst    #1,d1
  979.         beq.b   .skip2
  980.         cmpi.l  #1,d0
  981.         bne.b   .two
  982.         move.b  (a0)+,(a1)+
  983.         rts
  984.  
  985. ;  cnop 0,4
  986.  
  987. .two    move.w  (a0)+,(a1)+    ;Zieladresse auf LONG setzen
  988.         subq.l  #2,d0
  989.         beq.b   squit
  990. .skip2
  991.         cmpi.l  #%0000100000010000,d0 ;prüfen, ob d0 >=2064
  992.         bcc.b   bigmove
  993.  
  994. smlmove move.l  d0,d1
  995.         lsr.w   #2,d1          ;d0 ist hier nur noch maximal 12Bit lang
  996.         beq.b   .nolong
  997. .loop   move.l  (a0)+,(a1)+
  998.         subq.w  #1,d1
  999.         bne.b   .loop
  1000.  
  1001. .nolong btst    #1,d0
  1002.         beq.b   .skip
  1003.         move.w  (a0)+,(a1)+    ;letztes Word uebertragen
  1004. .skip   btst    #0,d0
  1005.         beq.b   squit
  1006.         move.b  (a0)+,(a1)+    ;letztes Byte uebertragen
  1007. squit   rts
  1008.  
  1009. ;  cnop 0,4
  1010.  
  1011. bigmove cmp.l  #$01000000,a0 ;Ist Quelladresse >$00ffffff ?
  1012.         bcs.b   bigmov
  1013.         cmp.l  #$01000000,a1 ;Ist Zieladresse >$00ffffff ?
  1014.         bcs.b   bigmov
  1015.         move.w  a1,d1
  1016.         btst    #2,d1
  1017.         beq.b   .skip1
  1018.         subq.l  #%100,d0       ;Zieladresse auf 8-Byte-Block legen
  1019.         move.l  (a0)+,(a1)+
  1020.         move.w  a1,d1
  1021. .skip1  btst    #3,d1
  1022.         beq.b   .dest16
  1023.         subq.l  #%1000,d0       ;Zieladresse auf 16-Byte-Block legen
  1024.         move.l  (a0)+,(a1)+
  1025.         move.l  (a0)+,(a1)+
  1026. .dest16 move.w  a0,d1
  1027.         andi.b  #15,d1
  1028.         bne.b   bigmov     ;wenn Quelladresse nicht im 16-Byte-Block liegt
  1029.  
  1030.         move.l  d0,d1
  1031.         lsr.l   #7,d1
  1032. .loop   move16  (a0)+,(a1)+
  1033.         move16  (a0)+,(a1)+
  1034.         move16  (a0)+,(a1)+
  1035.         move16  (a0)+,(a1)+
  1036.         move16  (a0)+,(a1)+
  1037.         move16  (a0)+,(a1)+
  1038.         move16  (a0)+,(a1)+
  1039.         move16  (a0)+,(a1)+
  1040.         subq.l  #1,d1
  1041.         bne.b   .loop
  1042.         and.w   #%0000000001111111,d0 ;die oberen 16 Bits werden ab hier nichtmehr berücksichtigt
  1043.         bne.b   smlmove
  1044.         rts
  1045.  
  1046. ;  cnop 0,4
  1047.  
  1048. bigmov  move.l  d0,d1
  1049.         lsr.l   #6,d1
  1050. .loop   move.l  (a0)+,(a1)+
  1051.         move.l  (a0)+,(a1)+
  1052.         move.l  (a0)+,(a1)+
  1053.         move.l  (a0)+,(a1)+
  1054.         move.l  (a0)+,(a1)+
  1055.         move.l  (a0)+,(a1)+
  1056.         move.l  (a0)+,(a1)+
  1057.         move.l  (a0)+,(a1)+
  1058.         move.l  (a0)+,(a1)+
  1059.         move.l  (a0)+,(a1)+
  1060.         move.l  (a0)+,(a1)+
  1061.         move.l  (a0)+,(a1)+
  1062.         move.l  (a0)+,(a1)+
  1063.         move.l  (a0)+,(a1)+
  1064.         move.l  (a0)+,(a1)+
  1065.         move.l  (a0)+,(a1)+
  1066.         subq.l  #1,d1
  1067.         bne.b   .loop
  1068.         and.w   #%0000000000111111,d0 ;die oberen 16 Bits werden ab hier nichtmehr berücksichtigt
  1069.         bne     smlmove
  1070.         rts
  1071.  
  1072.   cnop 0,4
  1073. **************************************************************************
  1074.  
  1075. Quickest
  1076.         lsr.l   #2,d0
  1077.         cmpi.l  #%0000001000000100,d0 ;prüfen, ob d0 >=2064/4
  1078.         bcc.b   bigmo16
  1079.  
  1080. smlmovQ tst.w   d0          ;d0 ist hier nur noch maximal 10 Bit lang
  1081.         beq.b   squitQ
  1082. sloopQ  move.l  (a0)+,(a1)+
  1083.         subq.w  #1,d0
  1084.         bne.b   sloopQ
  1085. squitQ  rts
  1086.  
  1087. ;  cnop 0,4
  1088.  
  1089. bigmo16 cmp.l  #$01000000,a0 ;Ist Quelladresse >$00ffffff ?
  1090.         bcs.b   bigmovQ
  1091.         cmp.l  #$01000000,a1 ;Ist Zieladresse >$00ffffff ?
  1092.         bcs.b   bigmovQ
  1093.         move.w  a1,d1
  1094.         btst    #2,d1
  1095.         beq.b   .skip1
  1096.         subq.l  #1,d0       ;Zieladresse auf 8-Byte-Block legen
  1097.         move.l  (a0)+,(a1)+
  1098.         move.w  a1,d1
  1099. .skip1  btst    #3,d1
  1100.         beq.b   .dest16
  1101.         subq.l  #2,d0       ;Zieladresse auf 16-Byte-Block legen
  1102.         move.l  (a0)+,(a1)+
  1103.         move.l  (a0)+,(a1)+
  1104. .dest16 move.w  a0,d1
  1105.         andi.b  #15,d1
  1106.         bne.b   bigmovQ     ;wenn Quelladresse nicht im 16-Byte-Block liegt
  1107.  
  1108.         move.l  d0,d1
  1109.         lsr.l   #5,d1
  1110. .loop   move16  (a0)+,(a1)+
  1111.         move16  (a0)+,(a1)+
  1112.         move16  (a0)+,(a1)+
  1113.         move16  (a0)+,(a1)+
  1114.         move16  (a0)+,(a1)+
  1115.         move16  (a0)+,(a1)+
  1116.         move16  (a0)+,(a1)+
  1117.         move16  (a0)+,(a1)+
  1118.         subq.l  #1,d1
  1119.         bne.b   .loop
  1120.         and.w   #%0000000000011111,d0 ;die oberen 16 Bits werden ab hier nichtmehr berücksichtigt
  1121.         bne.b   sloopQ
  1122.         rts
  1123.  
  1124. ;  cnop 0,4
  1125.  
  1126. bigmovQ move.l  d0,d1
  1127.         lsr.l   #4,d1
  1128. .loop   move.l  (a0)+,(a1)+
  1129.         move.l  (a0)+,(a1)+
  1130.         move.l  (a0)+,(a1)+
  1131.         move.l  (a0)+,(a1)+
  1132.         move.l  (a0)+,(a1)+
  1133.         move.l  (a0)+,(a1)+
  1134.         move.l  (a0)+,(a1)+
  1135.         move.l  (a0)+,(a1)+
  1136.         move.l  (a0)+,(a1)+
  1137.         move.l  (a0)+,(a1)+
  1138.         move.l  (a0)+,(a1)+
  1139.         move.l  (a0)+,(a1)+
  1140.         move.l  (a0)+,(a1)+
  1141.         move.l  (a0)+,(a1)+
  1142.         move.l  (a0)+,(a1)+
  1143.         move.l  (a0)+,(a1)+
  1144.         subq.l  #1,d1
  1145.         bne.b   .loop
  1146.         and.w   #%0000000000001111,d0 ;die oberen 16 Bits werden ab hier nichtmehr berücksichtigt
  1147.         bne     sloopQ
  1148.         rts
  1149.  
  1150.   cnop 0,4
  1151.  
  1152. PatchEnd
  1153.     ENDC
  1154.