сборка 68k - очистить, начиная с адреса эффективно - PullRequest
0 голосов
/ 28 июня 2018

Это мой фрагмент для очистки данных с адреса ЭКРАНА до 600 байт.

    lea SCREEN,a3
    move.w  #(600/4)-1,d0   ; bytes / 4 bytes (long)
clear_data:
   clr.l    (a3)+
   dbra d0,clear_data

Это работает, однако мне интересно, как добиться того же результата без циклического повторения в 600/4 раза. В основном, я думаю, чтобы указать на экран и сделать что-то вроде

; point PC to SCREEN ?
dcb.b 600,0

Возможно ли?

ОТМЕНИТЬ ОТВЕТ ОТВЕТА

Все еще используя программный код, этот цикл примерно в 2 раза быстрее (украдено из курса RamJam):

    lea SCREEN,a3
    move.w  #(600/32)-1,d0   ; bytes / 32 bytes (long*8)
clear_data:
    clr.l    (a3)+
    clr.l    (a3)+
    clr.l    (a3)+
    clr.l    (a3)+
    clr.l    (a3)+
    clr.l    (a3)+
    clr.l    (a3)+
    clr.l    (a3)+
    dbra d0,clear_data

Однако, как отметил Питер в ответе, использование блиттера (если оно предусмотрено аппаратным обеспечением) может радикально оптимизировать производительность.

Ответы [ 2 ]

0 голосов
/ 29 августа 2018

Используйте MOVEM, чтобы действительно прожечь память настроек!

Я рекомендую вам не использовать CLR.L; если вы посмотрите на часы, вы обнаружите, что они неэффективны. Лучше загрузить регистр со значением, которое вы хотите установить в память, а затем MOVE.L, (A0) +

Однако для максимальной скорости используйте MOVEM.L , чтобы установить / очистить большие области памяти. Это в 2–3 раза быстрее, чем при использовании CLR или стандартного MOVE.L

Вот пример подпрограммы, которая устанавливает 64-байтовые блоки, затем устанавливает любые оставшиеся длинные слова, но может быть настраиваемой.

         ORG     $2000
         MOVE.L  #MEMSTART,A0        ; memory to clear
         MOVE.L  #ZEROS,A1           ; value to set memory to e.g. 0
         MOVE.L  #600,D7             ; number of bytes
         BSR     SETBLOCK
         STOP    #2700

SETBLOCK
         ; MOVEM doesn't support destination = (Ax)+, 
         ; does support destination = -(Ax)
         ADD.L   D7,A0               ; so start at end

         LSR.L   #2,D7               ; divide by 4 for Long words.
         MOVE.L  D7,D6
         LSR.L   #4,D6               ; # of 16 longword blocks 
         BEQ.S   NOBLOCK             ; branch if no none
         SUBQ.L  #1,D6               ; one less so DBRA works
         MOVEM.L (A1),D0-D4/A2-A4    ; 8 registers = 32 bytes 

ZAPBLOCK MOVEM.L D0-D4/A2-A4,-(A0)   ; 8 x 4 = 32 bytes
         MOVEM.L D0-D4/A2-A4,-(A0)   ; 8 x 4 again for 64 bytes
         DBRA    D6,ZAPBLOCK         ; loop ends when D7=-1
NOBLOCK  AND.W   #$0F,D7             ; how many long words left
         BEQ.S   NONE
         ; do any remainder
         SUBQ.W  #1,D7               ; 1 less so DBRA works
         MOVE.L  (A1),D0             ; pattern in D0 if not there b4
ZAP      MOVE.L  D0,-(A0)            ; set memory long word at a time
         DBRA    D7,ZAP
NONE
         RTS

ZEROS    DC.L    0,0,0,0,0,0,0,0      ; 8x4 = 32
         ORG     $2500
MEMSTART DS.B    600

В этом примере используются D0-D4 и A2-A4, чтобы получить 8 регистров для установки 32 байтов за раз, повторяется дважды для 64 байтов. Нет причин, по которым вы не можете добавить больше инструкций MOVEM в цикл ZAPBLOCK для записи в 128, 256 или более байтов для каждой итерации цикла, соответственно изменяя инструкции LSR / AND.

Обратите внимание, что DBRA работает только со словами, поэтому будет установлено только 65 КБ x размера блока. Это можно исправить, например, используя SUBQ и BGT вместо DBRA.

Почему-то я вспоминаю, что инструкция CLR выполняла чтение и запись на некоторых 68k

Сроки

Сравнение 3 альтернатив, предполагая стандарт 68000 с 16-битной шиной данных ...

  1. Использование CLR

    LOOP:  
           CLR (A0)+      12+8
            DBRA D7,LOOP   10/14
    

30 циклов для каждого длинного слова, 20 для длинного слова с несколькими очистками.

  1. Использование MOVE.L

        MOVEQ #0,D0        ; 4
    LOOP:
        MOVE.L D0,(A0)+    ; 12
        DBRA   D7,LOOP     ; 10/14
    

22 цикла на длинное слово, 12 на длинное слово с несколькими операциями MOVE.L.

  1. Использование MOVEM.L

    LOOP:
        MOVEM.L  D0-D4/A2-A4,-(A0)    ;  8+8*8 = 72
        MOVEM.L  D0-D4/A2-A4,-(A0)    ;  8+8*8 = 72
        DBRA     D6,LOOP              ;  10/14
    

154 циклов / итерация, но только около 9,5 циклов на длинное слово . Это, вероятно, конкурирует с производительностью аппаратного блиттера.

0 голосов
/ 28 июня 2018

Нет, хранение 4 байтов за раз в цикле, вероятно, почти так же хорошо, как вы можете получить. Возможно, немного разверните, чтобы уменьшить накладные расходы цикла, если этот жесткий цикл не максимизирует пропускную способность памяти на любом оборудовании m68k, которое вам нужно. А может и нет: @jasonharper комментирует, что более поздние микросхемы m68k имеют специальную поддержку циклов из двух инструкций.


dcb.b 600,0 - это элемент времени сборки, который собирает байты в ваш выходной файл.

Вы не можете "запустить" его во время выполнения. Помните, что источник asm не запускается напрямую; это способ создания двоичных файлов, содержащих машинный код m68k и / или данные.

Вы можете использовать директивы данных, смешанные с инструкциями, для «ручного» кодирования инструкций, указав нужные байты машинного кода, но 600 байтов нулей будут просто декодироваться как некоторые инструкции m68k. (Я не проверял, как 00 00 декодирует на m68k.)


Некоторые компьютеры на базе m68k имели аппаратные чипы для работы с большими блоками памяти. Это обычно называлось блиттером (Wikipedia) . например некоторые настольные компьютеры Atari m68k, например Mega STe, имели чип BLiTTER.

Вы можете запустить несколько инструкций на ЦПУ, чтобы запрограммировать блиттер на очистку или копирование большого блока памяти, в то время как ЦП продолжал выполнять другие инструкции. Это в основном механизм копирования DMA.

...