|
Страница 1 из 1
|
[ Сообщений: 7 ] |
|
Автор |
Сообщение |
05 авг 2013, 18:35 |
|
|
Господа, кто-нибудь разбирался с данной инструкцией? В мануале заявляется, что это ones-tep division integer instruction. Суть работы этой инструкции том, что она выполняет как бы не полное деление целочсленных операндов, а как бы один шаг алгоритма деления, и благодаря этому, процессор, якобы, во время выполнения инструкции деления может отвечать на прерывания и прочие вещи, требующие незамедлительной обработки ( http://resource.renesas.com/lib/eng/e_l ... index.html, "Division instructions"). Сам же алгоритм деления заключается в следующем: 1. Делимое сдвигается влево (в сторону старших разрядов) на один бит. 2. Из получившегося числа вычитается делитель (сложение в complementary-two). Предположим есть два числа, 79 (0100 1111) и 5 (0101). 1. сдвигаем 79 влево на 1 бит. ((0100 1111)<<1 == 1001 1110). 2. вычитаем 3 (1001 1110 + 1 0011 == 1011 0001 == B1(16)== 177(10), имхо, не сильно похоже на остаток) Цитата: In 1-step division, the dividend is shifted 1 bit to the left, the divisor is subtracted from this, and the quotient bit is reflected in the Q bit according to whether the result is positive or negative. Я вручную попробовал поделить, и у меня не вышло ничего похожего на результат целочисленного деления. Пробовал также и псевдокод из мануала гонять, так же ничего похоже на результат не получается, даже после нескольких выполнений инструкции (сначала думал что неправильно перевел псевдокод, я заменял все свичи на if'ы, потом все-таки взял компилятор C и запустил пример из мануала как есть - тот же результат). Логика работы тоже непонятна. Код для вставки: Код: #include <stdio.h>
static signed int R[15];
static unsigned int Q,M,T,PC; //m - divisor, n - dividented number //Rn = Rn/Rm; void DIV1(char m, char n) /* DIV1 Rm,Rn */ { unsigned long tmp0, tmp2; unsigned char old_q, tmp1; old_q=Q; //sign into Q if(((0x80000000 & R[n])!=0)) { Q=1; } tmp2 = R[m]; //divisor R[n]<<=1; //divident<<=1; R[n]|=(unsigned long)T; //or with T bit. wtf is that needed. carry? switch(old_q) { case 0: switch(M){ case 0: tmp0=R[n]; //divident R[n]-=tmp2; //divident -=divisor tmp1=(R[n]>tmp0); //if (divident - divisor)> divident, then 1 to tmp1 switch(Q){ case 0: Q=tmp1; break; case 1: Q=(unsigned char)(tmp1==0); break; } break; case 1: tmp0=R[n]; R[n]+=tmp2; tmp1=(R[n]<tmp0); switch(Q){ case 0: Q=(unsigned char)(tmp1==0); break; case 1: Q=tmp1; break; } break; } break; case 1:
switch(M) { case 0: tmp0=R[n]; R[n]+=tmp2; tmp1=(R[n]<tmp0); switch(Q){ case 0: Q=tmp1; break; case 1: Q=(unsigned char)(tmp1==0); break; } break; case 1: tmp0=R[n]; R[n]-=tmp2; tmp1=(R[n]>tmp0); switch(Q){ case 0:Q=(unsigned char)(tmp1==0); break; case 1:Q=tmp1; break; } break; } break; } if(Q==M) T=1; else T=0; PC+=2;
}
void DIV0U() { M=Q=T=0; }
void SHLL16(int reg) { R[reg]<<=16; }
void EXTUW(char src, char dest) { R[dest] = R[src]&0x0000FFFF; }
main() { const int divident = 35; const int divisor = 5; R[0] = divisor; R[1] = divident; printf("Before:\n"); printf("Divisor, R[0]=%d\n", R[0]); printf("Divident, R[1]=%d\n", R[1]); SHLL16(0);// R0 ;Set divisor in upper 16 bits, clear lower 16 bits to 0 //TST R0,R0 ;Check for division by zero //BT ZERO_DIV ; //CMP/HS R0,R1 ;Check for overflow //BT OVER_DIV ; printf("R[0] after SHLL 0x%x\n", R[0]); DIV0U(); //DIV0U ;Flag initialization //.arepeat 16 ; int i=0; for (i = 0; i < 16; i++) { DIV1(0, 1); //DIV1 R0,R1 ;Repeat 16 times //.aendr ; //ROTCL R1 ; } EXTUW(1, 1); //R1 = quotient //Result in regsiter #1 printf("After:\n"); printf("R[0]=%d\n", R[0]); printf("Quotient: R[1]=%d, while must be %d\n", R[1], divident/divisor);
}
Буду благодарен любой помощи или наводке, ибо я не вкуриваю алгоритм этой инструкции вообще.
|
|
06 авг 2013, 06:25 |
|
Зарегистрирован: 24 июл 2007, 06:54 Сообщения: 492 Откуда: Embedded
|
А написать простенькую программку на АСМе на целевой процессор с выводом результата религия не позволяет? Обязательно надо штудировать зачастую неточные источники информации?
_________________ Tried so hard and got so far, but in the end, it doesn't even matter...
|
|
06 авг 2013, 09:16 |
|
Зарегистрирован: 28 дек 2012, 05:58 Сообщения: 19 Откуда: Курган
|
Чтобы пример из мануала заработал, надо перед выводом добавить забытую команду ROTCL - "проворачивание" влево через бит T. Я так понял, что команда DIV1 за каждый проход вычисляет один бит частного - T, который зависит от знака "остатка" - Q. После последнего её выполнения младший бит частного остаётся в Т.
Документация мутная какая-то. Совет написать программку на проц (если есть возможность) - очень дельный.
|
|
06 авг 2013, 15:45 |
|
|
Цитата: А написать простенькую программку на АСМе на целевой процессор с выводом результата религия не позволяет? Обязательно надо штудировать зачастую неточные источники информации? Почему, позволяет. Только для это слишком много телодвижений нужно сделать, чтобы эту простенькую программу в него залить. Цитата: Обязательно надо штудировать зачастую неточные источники информации? Ну если уж официальный мануал от самого производителя - неточный источник, то что уже тогда называть точным???
|
|
06 авг 2013, 23:01 |
|
Зарегистрирован: 24 июл 2007, 10:41 Сообщения: 570
|
|
|
07 авг 2013, 06:11 |
|
Зарегистрирован: 28 дек 2012, 05:58 Сообщения: 19 Откуда: Курган
|
rdc писал(а): Ну если уж официальный мануал от самого производителя - неточный источник, то что уже тогда называть точным??? Ошибки в документации - обычное явление. Хорошо, если её оперативно исправляют. Ну доки даже ещё ничего, вот примеры кода (или библиотеки) у производителей процессоров частенько такие, что ...
|
|
09 авг 2013, 14:14 |
|
Зарегистрирован: 22 июл 2007, 11:16 Сообщения: 787
|
Код: 0C176ECC 62F6 MOV.L @R15+, R2 0C176EE4 2008 TST R0, R0 0C176EE6 2F26 MOV.L R2, @-R15 0C176EE8 8945 BT h'0C176F76 0C176EEA E200 MOV #h'00, R2 0C176EEC 0019 DIV0U 0C176EEE 4124 ROTCL R1 0C176EF0 3204 DIV1 R0, R2 0C176EF2 4124 ROTCL R1 0C176EF4 3204 DIV1 R0, R2 0C176EF6 4124 ROTCL R1 0C176EF8 3204 DIV1 R0, R2 0C176EFA 4124 ROTCL R1 0C176EFC 3204 DIV1 R0, R2 0C176EFE 4124 ROTCL R1 0C176F00 3204 DIV1 R0, R2 0C176F02 4124 ROTCL R1 0C176F04 3204 DIV1 R0, R2 0C176F06 4124 ROTCL R1 0C176F08 3204 DIV1 R0, R2 0C176F0A 4124 ROTCL R1 0C176F0C 3204 DIV1 R0, R2 0C176F0E 4124 ROTCL R1 0C176F10 3204 DIV1 R0, R2 0C176F12 4124 ROTCL R1 0C176F14 3204 DIV1 R0, R2 0C176F16 4124 ROTCL R1 0C176F18 3204 DIV1 R0, R2 0C176F1A 4124 ROTCL R1 0C176F1C 3204 DIV1 R0, R2 0C176F1E 4124 ROTCL R1 0C176F20 3204 DIV1 R0, R2 0C176F22 4124 ROTCL R1 0C176F24 3204 DIV1 R0, R2 0C176F26 4124 ROTCL R1 0C176F28 3204 DIV1 R0, R2 0C176F2A 4124 ROTCL R1 0C176F2C 3204 DIV1 R0, R2 0C176F2E 4124 ROTCL R1 0C176F30 3204 DIV1 R0, R2 0C176F32 4124 ROTCL R1 0C176F34 3204 DIV1 R0, R2 0C176F36 4124 ROTCL R1 0C176F38 3204 DIV1 R0, R2 0C176F3A 4124 ROTCL R1 0C176F3C 3204 DIV1 R0, R2 0C176F3E 4124 ROTCL R1 0C176F40 3204 DIV1 R0, R2 0C176F42 4124 ROTCL R1 0C176F44 3204 DIV1 R0, R2 0C176F46 4124 ROTCL R1 0C176F48 3204 DIV1 R0, R2 0C176F4A 4124 ROTCL R1 0C176F4C 3204 DIV1 R0, R2 0C176F4E 4124 ROTCL R1 0C176F50 3204 DIV1 R0, R2 0C176F52 4124 ROTCL R1 0C176F54 3204 DIV1 R0, R2 0C176F56 4124 ROTCL R1 0C176F58 3204 DIV1 R0, R2 0C176F5A 4124 ROTCL R1 0C176F5C 3204 DIV1 R0, R2 0C176F5E 4124 ROTCL R1 0C176F60 3204 DIV1 R0, R2 0C176F62 4124 ROTCL R1 0C176F64 3204 DIV1 R0, R2 0C176F66 4124 ROTCL R1 0C176F68 3204 DIV1 R0, R2 0C176F6A 4124 ROTCL R1 0C176F6C 3204 DIV1 R0, R2 0C176F6E 4124 ROTCL R1 0C176F70 6013 MOV R1, R0 0C176F72 000B RTS 0C176F74 62F6 MOV.L @R15+, R2 берем любой готовый код и вынимаем процедуру деления. делаем в точности, как указано. ротсл там не просто так стоят
_________________ 1. Модератор всегда прав. 2. Если модератор не прав, см. п. 1.
|
|
|
|
Страница 1 из 1
|
[ Сообщений: 7 ] |
|
Кто сейчас на конференции |
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 60 |
|
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения
|
|