Проблема умножения матрицы единиц VFP на iPhone

Я пытаюсь написать умножение Matrix3x3, используя вектор с плавающей запятой на iPhone, однако я сталкиваюсь с некоторыми проблемами. Это моя первая попытка написать любую сборку ARM, так что это может быть неудачное простое решение, которого я не вижу.

В настоящее время у меня есть небольшое приложение, работающее с использованием математической библиотеки, которую я написал. Я изучаю преимущества использования векторного блока с плавающей запятой, поэтому я умножил свою матрицу и преобразовал ее в asm. Раньше приложение запускалось без проблем, однако теперь все мои объекты будут случайным образом исчезать. Похоже, это вызвано тем, что в какой-то момент моя матрица умножается на NAN.

Вот код

IMatrix3x3 operator*(IMatrix3x3 & _A, IMatrix3x3 & _B)
{
    IMatrix3x3 C;

    //C++ code for the simulator
#if TARGET_IPHONE_SIMULATOR == true
    C.A0 = _A.A0 * _B.A0 + _A.A1 * _B.B0 + _A.A2 * _B.C0;
    C.A1 = _A.A0 * _B.A1 + _A.A1 * _B.B1 + _A.A2 * _B.C1;
    C.A2 = _A.A0 * _B.A2 + _A.A1 * _B.B2 + _A.A2 * _B.C2;

    C.B0 = _A.B0 * _B.A0 + _A.B1 * _B.B0 + _A.B2 * _B.C0;
    C.B1 = _A.B0 * _B.A1 + _A.B1 * _B.B1 + _A.B2 * _B.C1;
    C.B2 = _A.B0 * _B.A2 + _A.B1 * _B.B2 + _A.B2 * _B.C2;

    C.C0 = _A.C0 * _B.A0 + _A.C1 * _B.B0 + _A.C2 * _B.C0;
    C.C1 = _A.C0 * _B.A1 + _A.C1 * _B.B1 + _A.C2 * _B.C1;
    C.C2 = _A.C0 * _B.A2 + _A.C1 * _B.B2 + _A.C2 * _B.C2;

//VPU ARM asm for the device
#else   
    //create a pointer to the Matrices
    IMatrix3x3 * pA = &_A;
    IMatrix3x3 * pB = &_B;
    IMatrix3x3 * pC = &C;

//asm code
asm volatile(
             //turn on a vector depth of 3
             "fmrx r0, fpscr \n\t"
             "bic r0, r0, #0x00370000 \n\t"
             "orr r0, r0, #0x00020000 \n\t"
             "fmxr fpscr, r0 \n\t"

             //load matrix B into the vector bank
             "fldmias %1, {s8-s16} \n\t"

             //load the first row of A into the scalar bank
             "fldmias %0!, {s0-s2} \n\t"

             //calulate C.A0, C.A1 and C.A2
             "fmuls s17, s8, s0 \n\t"
             "fmacs s17, s11, s1 \n\t"
             "fmacs s17, s14, s2 \n\t"

             //save this into the output
             "fstmias %2!, {s17-s19} \n\t"

             //load the second row of A into the scalar bank
             "fldmias %0!, {s0-s2} \n\t"

             //calulate C.B0, C.B1 and C.B2
             "fmuls s17, s8, s0 \n\t"
             "fmacs s17, s11, s1 \n\t"
             "fmacs s17, s14, s2 \n\t"

             //save this into the output
             "fstmias %2!, {s17-s19} \n\t"

             //load the third row of A into the scalar bank
             "fldmias %0!, {s0-s2} \n\t"

             //calulate C.C0, C.C1 and C.C2
             "fmuls s17, s8, s0 \n\t"
             "fmacs s17, s11, s1 \n\t"
             "fmacs s17, s14, s2 \n\t"

             //save this into the output
             "fstmias %2!, {s17-s19} \n\t"

             //set the vector depth back to 1
             "fmrx r0, fpscr \n\t"
             "bic r0, r0, #0x00370000 \n\t"
             "orr r0, r0, #0x00000000 \n\t"
             "fmxr fpscr, r0 \n\t"

             //pass  the inputs and set the clobber list
             : "+r"(pA), "+r"(pB), "+r" (pC) :
             :"cc", "memory","s0", "s1", "s2", "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19"
             );
#endif
    return C;
}

Насколько я вижу, это имеет смысл. Во время отладки мне удалось заметить, что если бы я сказал _A = C до возврата и после ASM, _A не обязательно будет равно C, что только усилило мое замешательство. Я думал, что это, возможно, связано с тем, что указатели, которые я даю на VFPU, инкриминируются такими строками, как "fldmias %0!, {s0-s2} \n\t", однако мое понимание asm недостаточно хорошо, чтобы правильно понять проблему или увидеть альтернативный подход к этой строке кода. .

В любом случае, я надеялся, что кто-то с большим пониманием, чем я, сможет увидеть решение, и любая помощь будет очень признательна, спасибо :-)

Изменить: я обнаружил, что pC кажется NULL, когда ассемблерный код срабатывает, несмотря на то, что он установлен pC = &C. Я предполагаю, что это связано с тем, что компилятор перестраивает код в поместье, которое его нарушает? Я пробовал различные методы, которые я видел, чтобы остановить это (например, добавление всего соответствующего в список ввода - думал, что это даже не должно быть необходимо, так как я указываю "память" в списке уничтожения), и я все еще получаю те же проблемы.

Изменить № 2: верно, проблема с памятью, похоже, была вызвана тем, что я не включил "r0" в список засорения, однако исправление этого (если оно действительно исправлено), похоже, не решило проблему. Я заметил, что умножение матрицы вращения на единичную матрицу работает неправильно и вместо 1 дает 0,88 в качестве последней записи в матрице:

| 0.88 0.48 0 |     | 1 0 0 |     | 0.88 0.48 0   |
|-0.48 0.88 0 |  *  | 0 1 0 |  =  |-0.48 0.88 0   |
| 0    0    1 |     | 0 0 1 |     | 0    0    0.88|

Тогда я подумал, что моя логика где-то неверна, поэтому я прошелся по сборке. все вроде нормально до последнего "fmacs s17, s14, s2\n\t", где:

s0 = 0    s14 = 0    s17 = 0
s1 = 0    s15 = 0    s18 = 0
s2 = 1    s16 = 1    s19 = 0

поэтому наверняка fmacs выполняет операцию:

s17 = s17 + s14 * s2 = 0 + 0 * 1 = 0
s18 = s18 + s15 * s2 = 0 + 0 * 1 = 0
s19 = s19 + s16 * s2 = 0 + 1 * 1 = 1

Однако результат дает s19 = 0.88, что меня еще больше смутило: я неправильно понимаю, как работает fmacs? (P.S. извините за вопрос, который стал очень длинным :-P)


person AzCopey    schedule 26.04.2010    source источник


Ответы (1)


Решил проблему! Я не знал, что банки векторов были "круговыми".

Банки 0-7, 8-15, 16-23 и 24-31 могут содержать векторы длиной до 8 и могут использоваться как векторы, просто указав, что вы используете s16 с длиной, например, 4. Однако в моем случае я использовал s14 с длиной 3, предполагая, что это даст мне s14, s15 и s16, но вместо этого, поскольку он круговой, он откатится к s8 - другими словами, я использовал s14, s15 и s8 .

Мне потребовалось много времени, чтобы увидеть это, поэтому, надеюсь, если у кого-то еще есть похожая проблема, они найдут это :-)

person AzCopey    schedule 29.04.2010