Add/Sub/Mul готовы (с большим трудом для каждого, не буду врать ^^ ).
Для Div/Sqrt у меня есть прототип, который должен имитировать специальную схему div FPU R5900 на двоичном уровне, но по каким-то странным причинам это работает не во всех случаях. time.
Тестовые примеры будут следующими (взято из журнала вывода программы на этапе Div):
Код: Выделить всё
TestPS2FloatDiv: 7F800000 / 7F800000 = 3F800000, Expected: 3F800000 - Pass
TestPS2FloatDiv: FF800000 / 7F800000 = BF800000, Expected: BF800000 - Pass
TestPS2FloatDiv: FF7FFFFF / 7F7FFFFF = BF800000, Expected: BF800000 - Pass
TestPS2FloatDiv: FFFFFFF3 / 3F800001 = FFFFFFD2, Expected: FFFFFFF1 - Fail
TestPS2FloatDiv: 3F800000 / 3F800001 = 3F7FFFFE, Expected: 3F7FFFFF - Fail
TestPS2FloatDiv: 3F800000 / 40A00000 = 3E32CB2D, Expected: 3E4CCCCD - Fail
TestPS2FloatDiv: 7F00FFF0 / 5FB504F3 = 5EB50207, Expected: 5EB66EE7 - Fail
TestPS2FloatDiv: 7FFFFFF0 / 5FB504F3 = 5FB1BFDD, Expected: 5FB504E8 - Fail
TestPS2FloatDiv: 3F800000 / 3E801000 = 407FDFFD, Expected: 407FE004 - Fail
TestPS2FloatDiv: 3F800000 / 3E802000 = 407FC010, Expected: 407FC010 - Pass
TestPS2FloatDiv: 3E800000 / 0 = 7FFFFFFF, Expected: 7FFFFFFF - Pass
TestPS2FloatDiv: 3E800000 / 80000000 = FFFFFFFF, Expected: FFFFFFFF - Pass
TestPS2FloatDiv: 3F800001 / 3F800001 = 3F800000, Expected: 3F800000 - Pass
TestPS2FloatDiv: 46E2A000 / 41A00000 = 44CDE596, Expected: 44B54CCC - Fail
TestPS2FloatDiv: 40851591 / 3F317210 = 40C00007, Expected: 40C00007 - Pass
TestPS2FloatDiv: 40851591 / 3F317211 = 40BFFD7F, Expected: 40C00006 - Fail
TestPS2FloatDiv: 40851591 / 3F317212 = 40BFFD7F, Expected: 40C00005 - Fail
TestPS2FloatDiv: 40851591 / 3F317213 = 40BFFD22, Expected: 40C00004 - Fail
TestPS2FloatDiv: 40851591 / 3F317214 = 40BFFD21, Expected: 40C00004 - Fail
TestPS2FloatDiv: 40851591 / 3F317215 = 40C00001, Expected: 40C00002 - Fail
TestPS2FloatDiv: 40851591 / 3F317216 = 40C00001, Expected: 40C00001 - Pass
TestPS2FloatDiv: 40851591 / 3F317217 = 40C00000, Expected: 40C00000 - Pass
TestPS2FloatDiv: 40851591 / 3F317218 = 40BFFFFF, Expected: 40BFFFFF - Pass
TestPS2FloatDiv: 40851591 / 3F317217 = 40C00000, Expected: 40C00000 - Pass
TestPS2FloatDiv: 40851591 / 3F317216 = 40C00001, Expected: 40C00001 - Pass
И здесь мне нужен ваш вклад. Я старался отладить все, что мог, но не смог найти никаких причин, почему вычисление мантиссы отклоняется, тем более что оно не всегда дает сбой. >
У меня тоже есть В целом у вас мало опыта работы с сумматорами CLA, но я постараюсь объяснить основные части.
Сейчас мы сосредоточимся на системе Div:
Здесь используется 24-проходный цикл с инициируемыми массивами, каждый из которых представляет четкую роль в этой системе:
Код: Выделить всё
public int[] R = new int[26];
public int[] Q = new int[26];
public int[] P = new int[26];
public int[] Sum = new int[26];
public int[] Divisor = new int[26];
public int[] Carry = new int[26];
public int[] Mult = new int[26];
Код: Выделить всё
for (i = 0; i 0 ? 1 : 0;
csaVal = csaRes;
}
Вы можете сказать: «Этот парень - урод, который подражает этому». , ну а Gran Turismo 4 нужно побитовое деление, чтобы игра не вылетала на лицензионных тестах (явно антиэмулятор). Поэтому у нас нет выбора.
Поэтому мы пытаемся смоделировать эту систему с 5 временными переменными:
Код: Выделить всё
private int Carry00;
private int Carry000;
private int Sum00;
private int Sum000;
private int Mult00;
Код: Выделить всё
public int CSA59bQSL(int csaVal)
{
int[] CarryArray = new int[4];
int[] SumArray = new int[4];
int i;
if (csaVal == 0)
{
SumArray[0] = Sum00;
CarryArray[0] = Carry00;
for (i = 1; i 31);
if (csaVal != 0)
{
SumArray[0] = Sum000;
CarryArray[0] = Carry000;
SumArray[1] = Sum00;
CarryArray[1] = Carry00;
for (i = 2; i 0x46E2A000 / 0x41A00000, она должна равняться -> 0x44B54CCC, наш делитель дает результат -> 0x44CDE596
При отладке цикла это двоичные значения частного/напоминания.
[code]Quotient[0] = 10000000000000000000000000
Reminder[0] = 1000000000000000000000000000000000000000000000000000
Quotient[1] = 11000000000000000000000000
Reminder[1] = 1100000000000000000000000010000000000000000000000000
Quotient[2] = 11000000000000000000000000
Reminder[2] = 1100000000000000000000000010100000000000000000000000
Quotient[3] = 11010000000000000000000000
Reminder[3] = 1101000000000000000000000011000000000000000000000000
Quotient[4] = 11001000000000000000000000
Reminder[4] = 1100100000000000000000000011000000000000000000000000
Quotient[5] = 11001100000000000000000000
Reminder[5] = 1100110000000000000000000011001000000000000000000000
Quotient[6] = 11001110000000000000000000
Reminder[6] = 1100111000000000000000000011001100000000000000000000
Quotient[7] = 11001110000000000000000000
Reminder[7] = 1100111000000000000000000011001101000000000000000000
Quotient[8] = 11001110000000000000000000
Reminder[8] = 1100111000000000000000000011001101100000000000000000
Quotient[9] = 11001101110000000000000000
Reminder[9] = 1100110111000000000000000011001101100000000000000000
Quotient[10] = 11001101111000000000000000
Reminder[10] = 1100110111100000000000000011001101110000000000000000
Quotient[11] = 11001101111100000000000000
Reminder[11] = 1100110111110000000000000011001101111000000000000000
Quotient[12] = 11001101111010000000000000
Reminder[12] = 1100110111101000000000000011001101111000000000000000
Quotient[13] = 11001101111010000000000000
Reminder[13] = 1100110111101000000000000011001101111001000000000000
Quotient[14] = 11001101111001100000000000
Reminder[14] = 1100110111100110000000000011001101111001000000000000
Quotient[15] = 11001101111001100000000000
Reminder[15] = 1100110111100110000000000011001101111001010000000000
Quotient[16] = 11001101111001011000000000
Reminder[16] = 1100110111100101100000000011001101111001010000000000
Quotient[17] = 11001101111001011100000000
Reminder[17] = 1100110111100101110000000011001101111001011000000000
Quotient[18] = 11001101111001011010000000
Reminder[18] = 1100110111100101101000000011001101111001011000000000
Quotient[19] = 11001101111001011010000000
Reminder[19] = 1100110111100101101000000011001101111001011001000000
Quotient[20] = 11001101111001011001100000
Reminder[20] = 1100110111100101100110000011001101111001011001000000
Quotient[21] = 11001101111001011001100000
Reminder[21] = 1100110111100101100110000011001101111001011001010000
Quotient[22] = 11001101111001011001011000
Reminder[22] = 1100110111100101100101100011001101111001011001010000
Quotient[23] = 11001101111001011001011100
Reminder[23] = 1100110111100101100101110011001101111001011001011000
Quotient[24] = 11001101111001011001011010
Reminder[24] = 1100110111100101100101101011001101111001011001011000
Теперь давайте возьмем одна работающая операция: -> 0x40851591 / 0x3F317218 = 0x40BFFFFF
И возьмем двоичный путь:
Код: Выделить всё
Quotient[0] = 10000000000000000000000000
Reminder[0] = 1000000000000000000000000000000000000000000000000000
Quotient[1] = 01000000000000000000000000
Reminder[1] = 0100000000000000000000000000000000000000000000000000
Quotient[2] = 01100000000000000000000000
Reminder[2] = 0110000000000000000000000001000000000000000000000000
Quotient[3] = 01100000000000000000000000
Reminder[3] = 0110000000000000000000000001010000000000000000000000
Quotient[4] = 01100000000000000000000000
Reminder[4] = 0110000000000000000000000001011000000000000000000000
Quotient[5] = 01100000000000000000000000
Reminder[5] = 0110000000000000000000000001011100000000000000000000
Quotient[6] = 01100000000000000000000000
Reminder[6] = 0110000000000000000000000001011110000000000000000000
Quotient[7] = 01100000000000000000000000
Reminder[7] = 0110000000000000000000000001011111000000000000000000
Quotient[8] = 01100000000000000000000000
Reminder[8] = 0110000000000000000000000001011111100000000000000000
Quotient[9] = 01100000000000000000000000
Reminder[9] = 0110000000000000000000000001011111110000000000000000
Quotient[10] = 01100000000000000000000000
Reminder[10] = 0110000000000000000000000001011111111000000000000000
Quotient[11] = 01100000000000000000000000
Reminder[11] = 0110000000000000000000000001011111111100000000000000
Quotient[12] = 01100000000000000000000000
Reminder[12] = 0110000000000000000000000001011111111110000000000000
Quotient[13] = 01100000000000000000000000
Reminder[13] = 0110000000000000000000000001011111111111000000000000
Quotient[14] = 01100000000000000000000000
Reminder[14] = 0110000000000000000000000001011111111111100000000000
Quotient[15] = 01100000000000000000000000
Reminder[15] = 0110000000000000000000000001011111111111110000000000
Quotient[16] = 01100000000000000000000000
Reminder[16] = 0110000000000000000000000001011111111111111000000000
Quotient[17] = 01100000000000000000000000
Reminder[17] = 0110000000000000000000000001011111111111111100000000
Quotient[18] = 01100000000000000000000000
Reminder[18] = 0110000000000000000000000001011111111111111110000000
Quotient[19] = 01100000000000000000000000
Reminder[19] = 0110000000000000000000000001011111111111111111000000
Quotient[20] = 01100000000000000000000000
Reminder[20] = 0110000000000000000000000001011111111111111111100000
Quotient[21] = 01100000000000000000000000
Reminder[21] = 0110000000000000000000000001011111111111111111110000
Quotient[22] = 01100000000000000000000000
Reminder[22] = 0110000000000000000000000001011111111111111111111000
Quotient[23] = 01011111111111111111111100
Reminder[23] = 0101111111111111111111110001011111111111111111111000
Quotient[24] = 01011111111111111111111110
Reminder[24] = 0101111111111111111111111001011111111111111111111100
Это также для справки о процессе Quotient, Reminder (называемом PQROTF), когда значение csaVal отличается от другого. чем 0:
Сначала мы оцениваем с помощью этой функции:
Код: Выделить всё
public void MultipleFormation(int csaVal)
{
int i;
if (csaVal == 0)
{
Mult00 = 0;
for (i = 0; i 16) & 1);
Sum[8] = (int)((floatDvd >> 15) & 1);
Sum[9] = ((floatDvd & 0x4000) != 0) ? 1 : 0;
Sum[10] = ((floatDvd & 0x2000) != 0) ? 1 : 0;
Sum[11] = ((floatDvd & 0x1000) != 0) ? 1 : 0;
Sum[12] = ((floatDvd & 0x800) != 0) ? 1 : 0;
Sum[13] = ((floatDvd & 0x400) != 0) ? 1 : 0;
Sum[14] = ((floatDvd & 0x200) != 0) ? 1 : 0;
Sum[15] = (int)((floatDvd >> 8) & 1);
Sum[16] = (int)((floatDvd >> 7) & 1);
Sum[17] = ((floatDvd & 0x40) != 0) ? 1 : 0;
Sum[18] = ((floatDvd & 0x20) != 0) ? 1 : 0;
Sum[19] = ((floatDvd & 0x10) != 0) ? 1 : 0;
Sum[20] = ((floatDvd & 8) != 0) ? 1 : 0;
Sum[21] = ((floatDvd & 4) != 0) ? 1 : 0;
Sum[22] = ((floatDvd & 2) != 0) ? 1 : 0;
Sum[23] = (int)(floatDvd & 1);
Sum[24] = 0;
Sum[25] = 0;
Dvsrexp = (byte)((floatDvs >> 23) & 0xFF);
Dvsrsign = (int)(floatDvs >> 31);
Divisor[0] = 1;
Divisor[1] = ((floatDvs & 0x400000) != 0) ? 1 : 0;
Divisor[2] = ((floatDvs & 0x200000) != 0) ? 1 : 0;
Divisor[3] = ((floatDvs & 0x100000) != 0) ? 1 : 0;
Divisor[4] = ((floatDvs & 0x80000) != 0) ? 1 : 0;
Divisor[5] = ((floatDvs & 0x40000) != 0) ? 1 : 0;
Divisor[6] = ((floatDvs & 0x20000) != 0) ? 1 : 0;
Divisor[7] = (int)((floatDvs >> 16) & 1);
Divisor[8] = (int)((floatDvs >> 15) & 1);
Divisor[9] = ((floatDvs & 0x4000) != 0) ? 1 : 0;
Divisor[10] = ((floatDvs & 0x2000) != 0) ? 1 : 0;
Divisor[11] = ((floatDvs & 0x1000) != 0) ? 1 : 0;
Divisor[12] = ((floatDvs & 0x800) != 0) ? 1 : 0;
Divisor[13] = ((floatDvs & 0x400) != 0) ? 1 : 0;
Divisor[14] = ((floatDvs & 0x200) != 0) ? 1 : 0;
Divisor[15] = (int)((floatDvs >> 8) & 1);
Divisor[16] = (int)((floatDvs >> 7) & 1);
Divisor[17] = ((floatDvs & 0x40) != 0) ? 1 : 0;
Divisor[18] = ((floatDvs & 0x20) != 0) ? 1 : 0;
Divisor[19] = ((floatDvs & 0x10) != 0) ? 1 : 0;
Divisor[20] = ((floatDvs & 8) != 0) ? 1 : 0;
Divisor[21] = ((floatDvs & 4) != 0) ? 1 : 0;
Divisor[22] = ((floatDvs & 2) != 0) ? 1 : 0;
Divisor[23] = (int)(floatDvs & 1);
Divisor[24] = 0;
Divisor[25] = 0;
if (!mode && Dvdtexp % 2 == 1)
{
for (i = 0; i
Подробнее здесь: [url]https://stackoverflow.com/questions/79314817/needs-help-debugging-finishing-a-emotionengine-ps2-cpu-divisor-sqrt-system-usi[/url]
Мобильная версия