Форум Эму-Россия
http://forum.emu-russia.net/

Div1 sh7750
http://forum.emu-russia.net/viewtopic.php?f=13&t=4847
Страница 1 из 1

Автор:  rdc [ 05 авг 2013, 18:35 ]
Заголовок сообщения:  Div1 sh7750

Господа, кто-нибудь разбирался с данной инструкцией?
В мануале заявляется, что это 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);

}


Буду благодарен любой помощи или наводке, ибо я не вкуриваю алгоритм этой инструкции вообще.

Автор:  HardWareMan [ 06 авг 2013, 06:25 ]
Заголовок сообщения:  Re: Div1 sh7750

А написать простенькую программку на АСМе на целевой процессор с выводом результата религия не позволяет? Обязательно надо штудировать зачастую неточные источники информации?

Автор:  qb60 [ 06 авг 2013, 09:16 ]
Заголовок сообщения:  Re: Div1 sh7750

Чтобы пример из мануала заработал, надо перед выводом добавить забытую команду ROTCL - "проворачивание" влево через бит T. Я так понял, что команда DIV1 за каждый проход вычисляет один бит частного - T, который зависит от знака "остатка" - Q. После последнего её выполнения младший бит частного остаётся в Т.

Документация мутная какая-то. Совет написать программку на проц (если есть возможность) - очень дельный.

Автор:  rdc [ 06 авг 2013, 15:45 ]
Заголовок сообщения:  Re: Div1 sh7750

Цитата:
А написать простенькую программку на АСМе на целевой процессор с выводом результата религия не позволяет? Обязательно надо штудировать зачастую неточные источники информации?

Почему, позволяет. Только для это слишком много телодвижений нужно сделать, чтобы эту простенькую программу в него залить.
Цитата:
Обязательно надо штудировать зачастую неточные источники информации?

Ну если уж официальный мануал от самого производителя - неточный источник, то что уже тогда называть точным???

Автор:  org [ 06 авг 2013, 23:01 ]
Заголовок сообщения:  Re: Div1 sh7750

Вот ещё мануал из Dreamcast SDK : http://ogamespec.com/download/SHC_PM.pdf

Автор:  qb60 [ 07 авг 2013, 06:11 ]
Заголовок сообщения:  Re: Div1 sh7750

rdc писал(а):
Ну если уж официальный мануал от самого производителя - неточный источник, то что уже тогда называть точным???
Ошибки в документации - обычное явление. Хорошо, если её оперативно исправляют.
Ну доки даже ещё ничего, вот примеры кода (или библиотеки) у производителей процессоров частенько такие, что ...

Автор:  CaH4e3 [ 09 авг 2013, 14:14 ]
Заголовок сообщения:  Re: Div1 sh7750

Код:
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 из 1 Часовой пояс: UTC + 3 часа [ Летнее время ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/