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

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

|
Вот, сижу, мастерю один проектик. Понадобилось сделать Хаффмана. В принципе, ничего сложного, однако работа с битовыми полями - это всегда узкое место процов с отсутствием комманд для обработки данных такого класса. Например, при упаковке по Хаффману необходима процедура, которая запишет в выходной поток n бит значения - вызывается примерно так: Код write_bits(huff->codes[val],huff->bits[val]) где первый параметр - код, а второй - собственно его размер в битах. Вот обычно эта функция - write_bits и несет основные затраты по времени выполнения. Почему так происходит - понятно, надо сдвигать входные биты в нужное положение, вычислять новое положение в буфере и т.д. Посему, сразу кодить не стал, сел - подумал... И вот что надумал... У нас есть аппаратный умножитель, который за 2 такта даст нам сдвинутый сразу в двух направлениях байт - и влево, и вправо. Конечно, в качестве множителя надо использовать маску - 0x01,0x02,...,0x80 и в результате, после выполнения комманды MUL в R0 будем иметь байт данных, сдвинутый влево, в R1 - сдвинутый вправо. Это уже отлично, одной коммандой мы готовим данные для OR с текущим байтом и для занесения следующих данных в накопитель. Однако, соответствующую текущему моменту маску еще надо получить. Она зависит как от текущей битовой позиции в выходном буфере, так и от размера битовых данных. Опять пришлось поразмышлять. Размышления натолкнули на идею хранить битовую позицию в буфере тоже в виде маски: Код 0x80(биты 7...0 свободны),0x40(бит 7 с данными, биты 6...0 свободны),....,0x01(биты 7...1 с данными, бит 0 свободен) Если размер символа в битах тоже задать в виде маски, то происходит чудо  - умножение (аппаратное, конечно) размера на битовую позицию даст новую позицию и она же является необходимым (точнее, в 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 тактов). Такая функция, кстати, будет полезна тем, кто пишет вывод пропорциональных символов на графический дисплей - вывод можно здорово ускорить. Вообще, подобный подход можно использовать там, где необходимо организовывать сдвиги на произвольное количество бит.
--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
|
|
|
|
|
 |
Ответов
|
Jan 28 2009, 06:57
|

Йа моск ;)
     
Группа: Модераторы
Сообщений: 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. Тогда нет необходимости в лишней проверке. Через пару дней положу новый вариант.
--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
|
|
|
|
|
Jan 28 2009, 15:53
|
Знающий
   
Группа: Свой
Сообщений: 841
Регистрация: 10-05-07
Из: Чебоксары (Россия)
Пользователь №: 27 640

|
Цитата(Rst7 @ Jan 28 2009, 09:57)  Но на самом деле, по алгоритму - там надо было решать вопрос не коррекцией на +1 и -1, а добавить значащих бит в таблицу обратных величин в диапазоне 0x80-0xFF. Тогда нет необходимости в лишней проверке. Я попробовал что-то подобное промоделировать на компьютере - у меня не получилось. Формулу, по которой таблицы вычисляются, менял. Всё равно результат на еденичку пляшет. Я даже дополнительно сдвигал на 1 разряд налево приведённый делитель (старший бит всё равно всегда 1 равен) - всё равно с ошибками получалсь. Т.е. без коррекции видимо не обойтись... Вообще меня не столько быстрое делении интересует, как быстрое вычисление арктангенса. Точнее быстрый переход от декартовых координат к полярным (там и деление конечно используется). С вычислением амплитуды проблем нет, а вот угол...
|
|
|
|
|
Jan 30 2009, 10:06
|
Знающий
   
Группа: Свой
Сообщений: 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). ; Пока не всё проверил (на компьютере всё). Перепроверю - тогда выложу ; ещё раз.
Подробные комментарии внутри. Внизу.
|
|
|
|
Сообщений в этой теме
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
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|