Я пытаюсь написать умножение Matrix3x3, используя Vector Floating Point на 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, когда код asm был достигнут, несмотря на то, что он установлен pC = &C
. Я предполагаю, что это из-за того, что компилятор переставил код в усадьбе, которая его сломала? Я пробовал различные методы, которые я видел, чтобы остановить это (например, добавление всего подходящего в список ввода - думал, что это даже не нужно, так как я перечисляю «память» в списке клоббера), и я все еще получаю те же проблемы.
Редактирование # 2: Правильно, проблема с памятью, по-видимому, была вызвана мной, не включив "r0"
в список clobber, однако исправление этого (если оно действительно исправлено), похоже, не устранило проблему. Я заметил, что умножение матрицы вращения на единичную матрицу не работает правильно и вместо этого дает 0,88 в качестве последней записи в матрице вместо 1:
| 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)