реклама на сайте
подробности

 
 
> Необычное использование аппаратного умножителя
Rst7
сообщение May 7 2008, 17:14
Сообщение #1


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Вот, сижу, мастерю один проектик. Понадобилось сделать Хаффмана. В принципе, ничего сложного, однако работа с битовыми полями - это всегда узкое место процов с отсутствием комманд для обработки данных такого класса. Например, при упаковке по Хаффману необходима процедура, которая запишет в выходной поток n бит значения - вызывается примерно так:
Код
write_bits(huff->codes[val],huff->bits[val])

где первый параметр - код, а второй - собственно его размер в битах. Вот обычно эта функция - write_bits и несет основные затраты по времени выполнения. Почему так происходит - понятно, надо сдвигать входные биты в нужное положение, вычислять новое положение в буфере и т.д.

Посему, сразу кодить не стал, сел - подумал... biggrin.gif

И вот что надумал...

У нас есть аппаратный умножитель, который за 2 такта даст нам сдвинутый сразу в двух направлениях байт - и влево, и вправо. Конечно, в качестве множителя надо использовать маску - 0x01,0x02,...,0x80 и в результате, после выполнения комманды MUL в R0 будем иметь байт данных, сдвинутый влево, в R1 - сдвинутый вправо. Это уже отлично, одной коммандой мы готовим данные для OR с текущим байтом и для занесения следующих данных в накопитель. Однако, соответствующую текущему моменту маску еще надо получить. Она зависит как от текущей битовой позиции в выходном буфере, так и от размера битовых данных. Опять пришлось поразмышлять. Размышления натолкнули на идею хранить битовую позицию в буфере тоже в виде маски:
Код
0x80(биты 7...0 свободны),0x40(бит 7 с данными, биты 6...0 свободны),....,0x01(биты 7...1 с данными, бит 0 свободен)


Если размер символа в битах тоже задать в виде маски, то происходит чудо wink.gif - умножение (аппаратное, конечно) размера на битовую позицию даст новую позицию и она же является необходимым (точнее, в 2 раза меньше) множителем для сдвига символа. Причем, в зависимости, от того, какой байт результата, старший или младший, не равен 0 - то это и есть выбор двух альтернатив - новый символ требует перехода через границу байта или не требует.
Осталась маленькая тонкость, что новая позиция как множитель данных в 2 раза меньше (т.е. сдвинута вправо). Можно конечно сдвинуть при помощи LSL, но лучше использовать тот факт, что FMUL - есть Rs*Rd<<1, это поможет в оптимизации.

Букаф много (могут ниасилить), посему код:

Код
//Кластеризация вручную, при необходимости изготавливается нормальная структура
struct
{
  char bitstream_byte;
  char bitstream_bit;
  char *bitstream;
};

//Инициализация битового потока
//p - указатель на первый байт выходного буфера
void init_bitstream(char *p)
{
  bitstream_byte=0;
  bitstream_bit=0x80;
  bitstream=p;
}

//Финализация потока - слив неслитого
//bp - указатель на первый байт выходного буфера (для расчета размера)
//на выходе - размер потока в байтах
unsigned int finish_bitstream(char *bp)
{
  char *p=bitstream;
  if (bitstream_bit!=0x80) *p++=bitstream_byte;
  return p-bp;
}

void write_bits_by_mask(char sym, char msb);

//Запись n бит из символа sym, необходимо, чтобы неиспользуемые биты равнялись 0
void write_n_bits(char sym, char n)
{
  //Генерация обратной маски
  static __flash const char mask[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
  write_bits_by_mask(sym,mask[n-1]);
}

//Записать в битовый поток биты из sym
//Биты записываются от 0 до бита, определенного установленным битом в msb в обратном порядке
//msb=0x80 sym=0000000a
//msb=0x40 sym=000000ab
//msb=0x20 sym=00000abc
//msb=0x10 sym=0000abcd
//msb=0x08 sym=000abcde
//msb=0x04 sym=00abcdef
//msb=0x02 sym=0abcdefg
//msb=0x01 sym=abcdefgh
//Запись идет от 7 к 0, например запись символов 000abcde, 0000xyzt будет лежать в байтах как
//[abcdexyz][t.......]
//Если есть возможность хранить msb, лучше применять эту функцию, меньше накладных расходов
void write_bits_by_mask(char sym, char msb)
{
  char b=bitstream_byte;
  char m=bitstream_bit;
  char *p=bitstream;
  //--> Если есть возможнось, эта часть инлайнится во внешний цикл
  unsigned short i;
  i=__multiply_unsigned(m,msb); //ih - множитель для sym, чтобы согласовать положение
  if (i>>8)
  {
    //Требуется сдвиг влево
    m=i>>8;
    i=__fractional_multiply_unsigned(sym,m);
    b|=i;
  }
  else
  {
    //Требуется сдвиг вправо
    m=i;
    i=__fractional_multiply_unsigned(sym,m);
    b|=i>>8;
    *p++=b;
    b=i;
  }
  //<-- Конец части для инлайна
  bitstream=p;
  bitstream_byte=b;
  bitstream_bit=m;
}


Компилятор - IAR 5.10

Ну и листинг, который особо радует глаз (приведу только внутренности функции write_bits_by_mask)
Код
     54          void write_bits_by_mask(char sym, char msb)
   \                     write_bits_by_mask:
     55          {
   \   00000000   2F5B               MOV     R21, R27
   \   00000002   2F6A               MOV     R22, R26
   \   00000004   2F20               MOV     R18, R16
     56            char b=bitstream_byte;
   \   00000006   ....               LDI     R30, LOW(_A_bitstream_byte)
   \   00000008   ....               LDI     R31, (_A_bitstream_byte) >> 8
   \   0000000A   8130               LD      R19, Z
     57            char m=bitstream_bit;
     58            char *p=bitstream;
   \   0000000C   81A2               LDD     R26, Z+2
   \   0000000E   81B3               LDD     R27, Z+3
   \   00000010   8101               LDD     R16, Z+1
     59            //--> Если есть возможнось, эта часть инлайнится во внешний цикл
     60            unsigned short i;
     61            i=__multiply_unsigned(m,msb); //ih - множитель для sym, чтобы согласовать положение
   \   00000012   9F01               MUL     R16, R17
     62            if (i>>8)
   \   00000014   2011               TST     R1
   \   00000016   F021               BREQ    ??write_bits_by_mask_0
     63            {
     64              //Требуется сдвиг влево
     65              m=i>>8;
   \   00000018   2D41               MOV     R20, R1
     66              i=__fractional_multiply_unsigned(sym,m);
     67              b|=i;
   \   0000001A   032C               FMUL    R18, R20
   \   0000001C   2930               OR      R19, R0
   \   0000001E   C005               RJMP    ??write_bits_by_mask_1
     68            }
     69            else
     70            {
     71              //Требуется сдвиг вправо
     72              m=i;
   \                     ??write_bits_by_mask_0:
   \   00000020   2D40               MOV     R20, R0
     73              i=__fractional_multiply_unsigned(sym,m);
   \   00000022   032C               FMUL    R18, R20
     74              b|=i>>8;
     75              *p++=b;
   \   00000024   2931               OR      R19, R1
   \   00000026   933D               ST      X+, R19
     76              b=i;
   \   00000028   2D30               MOV     R19, R0
     77            }
     78            //<-- Конец части для инлайна
     79            bitstream=p;
   \                     ??write_bits_by_mask_1:
   \   0000002A   83A2               STD     Z+2, R26
   \   0000002C   83B3               STD     Z+3, R27
     80            bitstream_byte=b;
   \   0000002E   8330               ST      Z, R19
     81            bitstream_bit=m;
   \   00000030   8341               STD     Z+1, R20
     82          }
   \   00000032   2FA6               MOV     R26, R22
   \   00000034   2FB5               MOV     R27, R21
   \   00000036   9508               RET


Конечно, если есть возможность, выжимку кода необходимо вставлять прямо в цикл генерации символов, чтобы меньше оверхеда было на загрузку/выгрузку. В этом случае добавление битового поля будет занимать 10 или 12 тактов, в зависимости от того, происходит переход через границу байта или не происходит.

Опять же, если есть возможность, надо хранить размеры символов в виде масок, а не в обычном виде - это уберет оверхед на функцию write_n_bits (7 тактов).

Такая функция, кстати, будет полезна тем, кто пишет вывод пропорциональных символов на графический дисплей - вывод можно здорово ускорить.

Вообще, подобный подход можно использовать там, где необходимо организовывать сдвиги на произвольное количество бит.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Rst7
сообщение Jan 28 2009, 06:57
Сообщение #2


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
Поэтому м.б. не
; выполнил все Си-шные соглашения. Но если вы мне их напомните - могу
; подкорректировать код.


Для IAR:
Вход:
Делимое R17:R16
Делитель R19:R18
Выход:
Частное R17:R16

Можно не сохранять регистры R0...R3,R16...R23,R30,R31.

Никаких предустановленных регистров нет.

Но на самом деле, по алгоритму - там надо было решать вопрос не коррекцией на +1 и -1, а добавить значащих бит в таблицу обратных величин в диапазоне 0x80-0xFF. Тогда нет необходимости в лишней проверке.

Через пару дней положу новый вариант.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
galjoen
сообщение Jan 28 2009, 15:53
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 841
Регистрация: 10-05-07
Из: Чебоксары (Россия)
Пользователь №: 27 640



Цитата(Rst7 @ Jan 28 2009, 09:57) *
Но на самом деле, по алгоритму - там надо было решать вопрос не коррекцией на +1 и -1, а добавить значащих бит в таблицу обратных величин в диапазоне 0x80-0xFF. Тогда нет необходимости в лишней проверке.

Я попробовал что-то подобное промоделировать на компьютере - у меня не получилось. Формулу, по которой таблицы вычисляются, менял. Всё равно результат на еденичку пляшет. Я даже дополнительно сдвигал на 1 разряд налево приведённый делитель (старший бит всё равно всегда 1 равен) - всё равно с ошибками получалсь. Т.е. без коррекции видимо не обойтись...

Вообще меня не столько быстрое делении интересует, как быстрое вычисление арктангенса. Точнее быстрый переход от декартовых координат к полярным (там и деление конечно используется). С вычислением амплитуды проблем нет, а вот угол...
Go to the top of the page
 
+Quote Post
galjoen
сообщение Jan 30 2009, 10:06
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 841
Регистрация: 10-05-07
Из: Чебоксары (Россия)
Пользователь №: 27 640



Сделал 50-ти тактовую версию беззнакового деления 16/16. Но с ошибками. Ошибки в "правильную" сторону и не больше чем на 1. Т.е. что-то вроде округления.
CODE

.DEF RG00=R2 ; регистр всегда равный 0x00
;.DEF RGFF=R3 ; реги
;.DEF RBN0=R4 ; чётный регистр в диапазоне 2..15
;.DEF RBN1=R5 ; нечётный регистр в диапазоне 2..15 (пара к предыдущему)
.DEF RBN0=R22 ; чётный регистр IAR!
.DEF RBN1=R23 ; нечётный регистр (пара к предыдущему) IAR!
.DEF RBN2=R3 ; чётный регистр в диапазоне 2..15 IAR!
.DEF RBX0=R16 ; чётный регистр в диапазоне 16..25
.DEF RBX1=R17 ; нечётный регистр в диапазоне 16..25 (пара к предыдущему)
.DEF RBX2=R18 ; чётный регистр в диапазоне 16..25
.DEF RBX3=R19 ; нечётный регистр в диапазоне 16..25 (пара к предыдущему)
.DEF RBX4=R20 ; чётный регистр в диапазоне 16..25
.DEF RBX5=R21 ; нечётный регистр в диапазоне 16..25 (пара к предыдущему)
.DEF ZL=R30
.DEF ZH=R31
eor RG00,RG00 ; RG00=0x00
ldi RBX0,0xFF
out 0x3D,RBX0
out 0x3E,RG00
dfdf: rcall f16d
rjmp dfdf


f16d:
; RBX1:RBX0=R17:R16=делимое=a + возвращаем результат
; RBX3:RBX2=R19:18=делитель=b
; RBX5:RBX4=R21:R20=результат=с, но возвращаем в RBX1:RBX0
eor RG00,RG00 ; RG00=0x00 (хотя я обычно делаю это
; только один раз при инициализации)
ldi ZH,high(tb_3e<<1) ; ст. байт адреса таблиц (3 шт.)
cpi RBX3,1
brcc f16d1 ; C=0 - делим не на байт

f16db: ; делим слово на байт (0==RBX3)
cpi RBX2,0x02 ; проверим случаи 0 и 1
brcs f16db01
; прочтем из таблицы соответствующий сдвигатель
mov ZL,RBX2 ; мл. байт делителя
lpm RBN2,Z ; s - сдвиг
; приведём делитель в диапазон 0x100..0x1FF (по сдвигателю)
mul RBX2,RBN2 ; делитель
mov ZL,R0 ; ZL=приведённый делитель
cpi ZL,0 ; его проверим на 0x100
breq f16db1 ; Z=1 получилось 0x100 - не множим
; получим обратную величину из таблицы по делителю
inc ZH ; ук-ль на мл. байты обратной
lpm RBN0,Z ; мл. байт обратной из таблицы
inc ZH ; ук-ль на ст. байты
lpm RBN1,Z ; ст. байт обратной из таблицы
; множим делимое на обратную величину (результат в ZH:ZL, RBX5:RBX4)
mul RBN1,RBX1 ; ст. б. обратного * ст. байт делимого
movw ZH:ZL,R1:R0 ; щас результат получим в ZH:ZL
mul RBN0,RBX0 ; мл. б. обратного * мл. б. делимого
movw RBX5:RBX4,R1:R0
mul RBN1,RBX0 ; ст. б. обратного * мл. б. делимого
add RBX5,R0
adc ZL,R1
adc ZH,RG00
mul RBN0,RBX1 ; мл. б. обратного * ст. б. делимого
add RBX5,R0
adc ZL,R1
adc ZH,RG00 ; ZH:ZL=несдвинутый результат
; сдвинем результат назад на величину сдвигателя s (RBN2)
mul ZH,RBN2 ; ст. байт
movw RBX1:RBX0,R1:R0
mul ZL,RBN2 ; мл. байт
or RBX0,R1 ; RBX5:RBX4= нескорректированный результат
ret ; [50]
f16db1:; приведённый делитель, это 0x100
mul RBX0,RBN2
mov ZL,R1
mul RBX1,RBN2
movw RBX1:RBX0,R1:R0
or RBX0,ZL
ret

f16db01: ; делитель = 0..1
cpi RBX2,0 ; проверим делитель - 0 или 1
brne f16db11 ; Z=0 - (результат)=(делимому)
or RBX0,RBX1 ; проверим деление 0 на 0
ldi RBX0,0xFF ; это переполнение при
ldi RBX0,0xFF ; делении на 0 такое
brne f16db11 ; Z=0 - щас не 0/0
ldi RBX0,0x01 ; при делении 0 на
ldi RBX1,0x00 ; 0 результат =1
f16db11: ; делили на 0
ret

f16d1: breq f16dp ; делим на 0x100..0x1FF
f16wd: ; делим на 0x200..0xFFFF
; прочтем из таблицы соответствующий сдвигатель
mov ZL,RBX3 ; ст. байт делителя
lpm RBN2,Z ; s - сдвиг
; приведём делитель в диапазон 0x100..0x1FF (по сдвигателю)
mul RBX3,RBN2 ; ст. байт делителя
mov ZL,R0
mul RBX2,RBN2 ; мл. байт делителя
or ZL,R1 ; ZL=приведённый делитель
breq f16wd1 ; Z=1 получилось 0x100 - не множим
; получим обратную величину из таблицы по приведённому делителю
inc ZH ; ук-ль на мл. байты обратной
lpm RBN0,Z ; мл. байт обратной из таблицы
inc ZH ; ук-ль на ст. байты
lpm RBN1,Z ; ст. байт обратной из таблицы
; множим делимое на обратную величину (результат в ZH:ZL, RBX5:RBX4)
mul RBN1,RBX1 ; ст. б. обратного * ст. байт делимого
movw ZH:ZL,R1:R0 ; щас результат получим в ZH:ZL
mul RBN0,RBX0 ; мл. б. обратного * мл. б. делимого
movw RBX5:RBX4,R1:R0
mul RBN1,RBX0 ; ст. б. обратного * мл. б. делимого
add RBX5,R0
adc ZL,R1
adc ZH,RG00
mul RBN0,RBX1 ; мл. б. обратного * ст. б. делимого
add RBX5,R0
adc ZL,R1
adc ZH,RG00 ; ZH:ZL=несдвинутый результат
; сдвинем результат назад на величину сдвигателя s (RBN2)
mul ZH,RBN2 ; токо ст. байт т.к. результат в этом
mov RBX0,R1 ; случае м.б. токо однобайтовый
ldi RBX1,0 ; RBX5:RBX4= нескорректированный результат
ret ; [49]

f16wd1: ; приведённый делитель 0x100. Но не из делителя 0x100.
mul RBX1,RBN2 ; мл. байт делимого * сдвигатель
mov RBX0,R1 ; мл. байт результата
ldi RBX1,0 ; ст. байт рез-та точно =0
ret

f16dp: ; делим слово на 0x100..0x1FF
cpi RBX2,0
breq f16dp1 ; делим слово на 0x100
mov ZL,RBX2 ; мл. байт делителя (уже приведённого)
; получим обратную величину из таблицы по делителю
inc ZH ; ук-ль на мл. байты обратной
lpm RBN0,Z ; мл. байт обратной из таблицы
inc ZH ; ук-ль на ст. байты
lpm RBN1,Z ; ст. байт обратной из таблицы
; множим делимое на обратную величину (результат в ZH:ZL, RBX5:RBX4)
mul RBN1,RBX1 ; ст. б. обратного * ст. байт делимого
movw ZH:ZL,R1:R0 ; щас результат получим в ZH:ZL
mul RBN0,RBX0 ; мл. б. обратного * мл. б. делимого
movw RBX5:RBX4,R1:R0
mul RBN1,RBX0 ; ст. б. обратного * мл. б. делимого
add RBX5,R0
adc ZL,R1
adc ZH,RG00
mul RBN0,RBX1 ; мл. б. обратного * ст. б. делимого
add RBX5,R0
adc ZL,R1
adc ZH,RG00 ; ZH:ZL=несдвинутый результат
; сдвинем результат, в нашем случае >>8
mov RBX0,ZH
ldi RBX1,0
ret ; [40]
f16dp1: ; делим на 0x100
mov RBX0,RBX1 ; мл. байт результата
ldi RBX1,0 ; ст. байт рез-та точно =0
ret

ENDCOD: ; эта метка токо шоб корректировался выровненный адрес
.org ((ENDCOD+0x7F)&0xFF80)
tb_3e:
; таблица сдвигателей
.db 0xFF, 0x00, 0x80, 0x80, 0x40, 0x40, 0x40, 0x40 ; 00..07
.db 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 ; 08..0F
.db 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 ; 10..17
.db 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 ; 18..1F
.db 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 ; 20..27
.db 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 ; 28..2F
.db 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 ; 30..37
.db 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 ; 38..3F
.db 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 ; 40..47
.db 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 ; 48..4F
.db 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 ; 50..57
.db 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 ; 58..5F
.db 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 ; 60..67
.db 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 ; 68..6F
.db 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 ; 70..77
.db 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 ; 78..7F
.db 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 ; 80..87
.db 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 ; 88..8F
.db 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 ; 90..97
.db 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 ; 98..9F
.db 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 ; A0..A7
.db 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 ; A8..AF
.db 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 ; B0..B7
.db 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 ; B8..BF
.db 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 ; C0..C7
.db 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 ; C8..CF
.db 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 ; D0..D7
.db 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 ; D8..DF
.db 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 ; E0..E7
.db 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 ; E8..EF
.db 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 ; F0..F7
.db 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 ; F8..FF
; младший байт обратных величин
.db 0xFF, 0x01, 0x04, 0x09, 0x10, 0x19, 0x24, 0x30 ; 00..07
.db 0x3F, 0x4F, 0x61, 0x75, 0x8A, 0xA1, 0xBA, 0xD5 ; 08..0F
.db 0xF1, 0x10, 0x2F, 0x51, 0x74, 0x98, 0xBE, 0xE6 ; 10..17
.db 0x0F, 0x3A, 0x66, 0x94, 0xC3, 0xF4, 0x26, 0x5A ; 18..1F
.db 0x8F, 0xC5, 0xFD, 0x36, 0x71, 0xAD, 0xEA, 0x28 ; 20..27
.db 0x68, 0xA9, 0xEC, 0x30, 0x75, 0xBB, 0x02, 0x4B ; 28..2F
.db 0x95, 0xE0, 0x2C, 0x79, 0xC8, 0x18, 0x69, 0xBB ; 30..37
.db 0x0E, 0x62, 0xB7, 0x0E, 0x65, 0xBD, 0x17, 0x72 ; 38..3F
.db 0xCD, 0x2A, 0x88, 0xE6, 0x46, 0xA7, 0x08, 0x6B ; 40..47
.db 0xCF, 0x33, 0x99, 0xFF, 0x66, 0xCF, 0x38, 0xA2 ; 48..4F
.db 0x0D, 0x79, 0xE5, 0x53, 0xC1, 0x31, 0xA1, 0x12 ; 50..57
.db 0x83, 0xF6, 0x6A, 0xDE, 0x53, 0xC9, 0x3F, 0xB7 ; 58..5F
.db 0x2F, 0xA8, 0x22, 0x9C, 0x18, 0x94, 0x10, 0x8E ; 60..67
.db 0x0C, 0x8B, 0x0A, 0x8B, 0x0C, 0x8D, 0x10, 0x93 ; 68..6F
.db 0x17, 0x9B, 0x20, 0xA6, 0x2D, 0xB4, 0x3B, 0xC4 ; 70..77
.db 0x4D, 0xD6, 0x61, 0xEC, 0x77, 0x03, 0x90, 0x1D ; 78..7F
.db 0xAB, 0x3A, 0xC9, 0x58, 0xE9, 0x7A, 0x0B, 0x9D ; 80..87
.db 0x30, 0xC3, 0x56, 0xEA, 0x7F, 0x14, 0xAA, 0x41 ; 88..8F
.db 0xD8, 0x6F, 0x07, 0x9F, 0x38, 0xD2, 0x6C, 0x06 ; 90..97
.db 0xA1, 0x3D, 0xD9, 0x75, 0x12, 0xAF, 0x4D, 0xEC ; 98..9F
.db 0x8A, 0x2A, 0xC9, 0x6A, 0x0A, 0xAB, 0x4D, 0xEF ; A0..A7
.db 0x91, 0x34, 0xD8, 0x7B, 0x20, 0xC4, 0x69, 0x0F ; A8..AF
.db 0xB5, 0x5B, 0x02, 0xA9, 0x50, 0xF8, 0xA1, 0x49 ; B0..B7
.db 0xF3, 0x9C, 0x46, 0xF0, 0x9B, 0x46, 0xF2, 0x9D ; B8..BF
.db 0x4A, 0xF6, 0xA3, 0x51, 0xFE, 0xAC, 0x5B, 0x0A ; C0..C7
.db 0xB9, 0x68, 0x18, 0xC8, 0x79, 0x2A, 0xDB, 0x8C ; C8..CF
.db 0x3E, 0xF1, 0xA3, 0x56, 0x09, 0xBD, 0x71, 0x25 ; D0..D7
.db 0xD9, 0x8E, 0x43, 0xF9, 0xAF, 0x65, 0x1B, 0xD2 ; D8..DF
.db 0x89, 0x40, 0xF8, 0xB0, 0x68, 0x21, 0xDA, 0x93 ; E0..E7
.db 0x4C, 0x06, 0xC0, 0x7A, 0x35, 0xEF, 0xAA, 0x66 ; E8..EF
.db 0x22, 0xDD, 0x9A, 0x56, 0x13, 0xD0, 0x8D, 0x4B ; F0..F7
.db 0x09, 0xC7, 0x85, 0x44, 0x03, 0xC2, 0x81, 0x41 ; F8..FF
; старший байт обратных величин
.db 0xFF, 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9 ; 00..07
.db 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1 ; 08..0F
.db 0xF0, 0xF0, 0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA ; 10..17
.db 0xEA, 0xE9, 0xE8, 0xE7, 0xE6, 0xE5, 0xE5, 0xE4 ; 18..1F
.db 0xE3, 0xE2, 0xE1, 0xE1, 0xE0, 0xDF, 0xDE, 0xDE ; 20..27
.db 0xDD, 0xDC, 0xDB, 0xDB, 0xDA, 0xD9, 0xD9, 0xD8 ; 28..2F
.db 0xD7, 0xD6, 0xD6, 0xD5, 0xD4, 0xD4, 0xD3, 0xD2 ; 30..37
.db 0xD2, 0xD1, 0xD0, 0xD0, 0xCF, 0xCE, 0xCE, 0xCD ; 38..3F
.db 0xCC, 0xCC, 0xCB, 0xCA, 0xCA, 0xC9, 0xC9, 0xC8 ; 40..47
.db 0xC7, 0xC7, 0xC6, 0xC5, 0xC5, 0xC4, 0xC4, 0xC3 ; 48..4F
.db 0xC3, 0xC2, 0xC1, 0xC1, 0xC0, 0xC0, 0xBF, 0xBF ; 50..57
.db 0xBE, 0xBD, 0xBD, 0xBC, 0xBC, 0xBB, 0xBB, 0xBA ; 58..5F
.db 0xBA, 0xB9, 0xB9, 0xB8, 0xB8, 0xB7, 0xB7, 0xB6 ; 60..67
.db 0xB6, 0xB5, 0xB5, 0xB4, 0xB4, 0xB3, 0xB3, 0xB2 ; 68..6F
.db 0xB2, 0xB1, 0xB1, 0xB0, 0xB0, 0xAF, 0xAF, 0xAE ; 70..77
.db 0xAE, 0xAD, 0xAD, 0xAC, 0xAC, 0xAC, 0xAB, 0xAB ; 78..7F
.db 0xAA, 0xAA, 0xA9, 0xA9, 0xA8, 0xA8, 0xA8, 0xA7 ; 80..87
.db 0xA7, 0xA6, 0xA6, 0xA5, 0xA5, 0xA5, 0xA4, 0xA4 ; 88..8F
.db 0xA3, 0xA3, 0xA3, 0xA2, 0xA2, 0xA1, 0xA1, 0xA1 ; 90..97
.db 0xA0, 0xA0, 0x9F, 0x9F, 0x9F, 0x9E, 0x9E, 0x9D ; 98..9F
.db 0x9D, 0x9D, 0x9C, 0x9C, 0x9C, 0x9B, 0x9B, 0x9A ; A0..A7
.db 0x9A, 0x9A, 0x99, 0x99, 0x99, 0x98, 0x98, 0x98 ; A8..AF
.db 0x97, 0x97, 0x97, 0x96, 0x96, 0x95, 0x95, 0x95 ; B0..B7
.db 0x94, 0x94, 0x94, 0x93, 0x93, 0x93, 0x92, 0x92 ; B8..BF
.db 0x92, 0x91, 0x91, 0x91, 0x90, 0x90, 0x90, 0x90 ; C0..C7
.db 0x8F, 0x8F, 0x8F, 0x8E, 0x8E, 0x8E, 0x8D, 0x8D ; C8..CF
.db 0x8D, 0x8C, 0x8C, 0x8C, 0x8C, 0x8B, 0x8B, 0x8B ; D0..D7
.db 0x8A, 0x8A, 0x8A, 0x89, 0x89, 0x89, 0x89, 0x88 ; D8..DF
.db 0x88, 0x88, 0x87, 0x87, 0x87, 0x87, 0x86, 0x86 ; E0..E7
.db 0x86, 0x86, 0x85, 0x85, 0x85, 0x84, 0x84, 0x84 ; E8..EF
.db 0x84, 0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x82 ; F0..F7
.db 0x82, 0x81, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80 ; F8..FF
;
;Для IAR:
;Вход:
;Делимое R17:R16
;Делитель R19:R18
;Выход:
;Частное R17:R16
;Можно не сохранять регистры R0...R3,R16...R23,R30,R31.
;Никаких предустановленных регистров нет.

; Версия 2.0
; Изменения:
; 1. Убрал коррекцию.
; 2. Считает не точно. Иногда ошибается на 1 в большую сторону.
; Зависит от соотношения делимое/делитель. Получается что-то вроде
; округления результата.
; 3. В худшем случае 50 тактов.
; 4. Делитель привожу в диапазон 0x100..0x1FF. В рассчётах не использую
; старший бит т.к. он всегда =1.
; 5. Соответственно пересчитал таблицу сдвигателей.
; 6. Таблицу обратных величин считаю по формуле
; ((0x1000000/(0x100+i+0))+1).
; Пока не всё проверил (на компьютере всё). Перепроверю - тогда выложу
; ещё раз.

Подробные комментарии внутри. Внизу.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Rst7   Необычное использование аппаратного умножителя   May 7 2008, 17:14
- - SasaVitebsk   Цитата(Rst7 @ May 7 2008, 21:14) Вообще, ...   May 7 2008, 18:22
- - Rst7   ЦитатаПравда если есть возможность организовывать ...   May 7 2008, 18:50
|- - galjoen   А вот мне только-что мысль пришла - ещё не проверя...   May 7 2008, 19:49
|- - Rst7   Цитата(galjoen @ May 7 2008, 22:49) А вот...   May 8 2008, 07:24
- - vet   galjoen 2*255 = 510 = 0x01FE, 7 бит=1 3*255 = 765 ...   May 8 2008, 04:22
- - vet   сдвигами четность все равно шустрее выйдет: Код M...   May 8 2008, 07:54
|- - Rst7   Цитата(vet @ May 8 2008, 09:54) сдвигами ...   Dec 13 2008, 21:05
|- - singlskv   Цитата(Rst7 @ Dec 14 2008, 00:05) Случайн...   Dec 14 2008, 19:11
|- - Rst7   Цитата(singlskv @ Dec 14 2008, 21:11) ИМХ...   Dec 14 2008, 19:57
|- - singlskv   Цитата(Rst7 @ Dec 14 2008, 22:57) Да вооб...   Dec 14 2008, 20:08
|- - Rst7   Цитата(singlskv @ Dec 14 2008, 22:08) я в...   Dec 14 2008, 21:38
- - Rst7   Цитатасдвигами четность все равно шустрее выйдет: ...   May 8 2008, 08:00
- - _Pasha   Америки не открою, и особой экзотики в использован...   May 29 2008, 19:41
- - ae_   Как быть, когда результат (zL:zH)/yH > 255? про...   May 31 2008, 11:55
|- - _Pasha   Цитата(ae_ @ May 31 2008, 14:55) Как быть...   May 31 2008, 18:57
- - Rst7   Ну, продолжим наши игры. На этот раз под руки попа...   Jan 23 2009, 15:21
|- - galjoen   Цитата(Rst7 @ Jan 23 2009, 18:21) Ну, про...   Jan 27 2009, 10:38
- - Rst7   ЦитатаЯ собственно собираюсь переписать всё на асм...   Jan 27 2009, 11:22
|- - galjoen   Цитата(Rst7 @ Jan 27 2009, 14:22) Гм. Я р...   Jan 27 2009, 12:11
- - Rst7   ЦитатаПриведём (преобразуем) ваш вариант к такому ...   Jan 27 2009, 12:51
|- - galjoen   Цитата(Rst7 @ Jan 27 2009, 15:51) Почему?...   Jan 27 2009, 14:41
- - Rst7   ЦитатаНе совпадает с тем, что в описании. Где не ...   Jan 27 2009, 14:58
|- - galjoen   Цитата(Rst7 @ Jan 27 2009, 17:58) Ну вот...   Jan 28 2009, 05:25


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th August 2025 - 06:36
Рейтинг@Mail.ru


Страница сгенерированна за 0.01464 секунд с 7
ELECTRONIX ©2004-2016