Рейтинг@Mail.ru
Перейти к содержанию

Уважаемые посетители! Если у вас возникают проблемы с входом, регистрацией или сменой пароля, обращайтесь в эту тему (там можно писать без регистрации) с указанием где возникла проблема - на сайте или форуме.

Авторизация  
Kefka

Многоядерные процессоры игровых платформ (PC, Xbox360, PS3)

Рекомендуемые сообщения

[quote]Ляпота! Denim, а что сейчас конкретно исследуем на кафедре и какие лично у Вас выводы, по обсуждаемым на вашей кафедре вопросам? [/quote]

Много чего исследуем. У нас очень большой штат из самых разнообразных сотрудников. Лично я сейчас работаю в команде по разработке искуственного интеллекта. Вы будете смеяться, но наша команда делает роботов. :) Для каких нужд, сказать не могу, увы комерческая тайна. Но все на полном серьезе, и у нас хорошее финансирование. :mrgreen:

[quote]Хотя репу я почесал, никто мне вот на это и не ответил: А по теме, я вот думаю, а на что действительно рассчитывала Сони, соглашаясь на Целл, кто-нибудь знает? В чём подвох? Рассчитывали лобировать рынок засчёт успешности бренда? Зачем им такой риск? Дабы сделать узко-специальный код и укрепиться в монополизме потеряв немного в процентах рынка? Где ответ?[/quote]

Вобще я зарекся тут дальше обсуждать этот вопрос, если вы не заметели. Но моя точка зрения проста: Sony разработала интерестный процессор, отличную числодробилку, и я думаю что в приставках и мультимедийных устройствах этот процессор будет на высоте. Вот и вся моя позиция.

И вы так говорите "[i]а на что действительно рассчитывала Сони, соглашаясь на Целл, кто-нибудь знает?[/i]" - как буд-то пришли IBM с Toshiba и предложили Сони использовать их проц в их игровой приставке. Сони сама его разрабатывала наряду с остальными и они знали на что идут и что из всего этого получиться. Осталось немного подождать и мы сами все увидим. Все это гадание на кофейной гуще никому не нужно.

Заявление про монополизм я, если честно, не понял. Извините.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Denim, начнём. Роботов для следующей части MGS? С какой последней проблемой вы столкнулись? Где можно прочесть про вашу работу, хотя бы косвенно? Очень интересно!

А что может быть интересного в числедробилке на игровой консоли? Выводить по десять видео-роликов на экран одновременно? Как это вообще может улучшить(ускорить, усложнить графически) саму игру, которая по сути, будет работать на одном главном ядре, супротив трёх полноценных ядер на 360? Вопрос на засыпку. Только не надо отписываться фразами я не понимаю о чём Вы, да что Вы такое говорите и прочее, как Вы делали раньше. Ладно? Простые вопросы, простые ответы. :lol:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
[quote]А что может быть интересного в числедробилке на игровой консоли? Выводить по десять видео-роликов на экран одновременно? Как это вообще может улучшить(ускорить, усложнить графически) саму игру, которая по сути, будет работать на одном главном ядре, супротив трёх полноценных ядер на 360? Вопрос на засыпку.[/quote]

Числодробилка нужна например для: просчета физики, AI, звука, опять же выполнять какие-то небольшие задачи 3d дабы помочь графической карте. Мало? И вы ошибаетесь если думаете, что игра будет работать только на одном PPE, а все SPE будут простаивать. Как раз они-то и будут заниматься всей вспомогательной работой. SPE не просто векторные процессоры, у них гораздо большая функциональность. Можете рассматривать их как упрощенные процессоры только более низкого класса чем PPE. Главное ядро будет работать с ОС и руководить распределением задач между остальными SPE.

В случае же с X360, имеются просто три основных ядра, на одном будет висеть ОС, другие же отданы под что угодно. Вы поймите, сравнивать эти архитектуры немного не корректно. Да, программировать под боксовые PowerPC легче, потому-что это давно устаявшаяся и отработанная платформа. Но не значит что легче писать игру которая бы задействовала все три ядра на полную катушку. Ничего нового посути в ней нет. В случае с Cell придеться извращаться, потому как новая архитектура, но все решаемо, сони уже написала все необходимые библиотеки, и грамотно написанный движок может выжать из этого процессора намного больше чем из трех ядер 360. Удасться ли это реализовать или нет, покажет время.

Процы обоих систем могут обрабатывать по два потока на ядро (практически то же самое что и P4 с HT), только в случае с 360 мы имеет три ядра (и соответсвенно максимальное количество потоков = 6), а у Cell одно и потока всего два, но у Cell есть еще 8 вспомогательных процессоров которые могут быстро обрабатывать данные полученные от этих потоков, а вот у 360 одно ядро на обработку двух потоков и все. Вы видите картину? В каких-то задачах оба процессора будут иметь одинаковую производительность, но в случае с Большими потоковыми данными Cell будет иметь приемущество из за особенностей работы SPE с данными, потому-что пока одно из ядер 360 будет считать какой-то кусок, 8 SPE целла разбирут его на маленькие куски, прожуют и приступят к следующей задаче.

Вобщем тут можно говорить и говорить на эту тему, залазя все глубже в технические аспекты, но мне если честно надоело. Я не преподаватель все все разжевывать. Так что читайте, смотрите, пробуйте.

[size=75]Добавлено 17 Dec 2005, 5:09:[/size]

Все, не буду больше ничего отвечать. Хватит жевать про Фому и Ерему. Удачи.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Вода, вода, вода и снова коронное надоело, больше не буду... Попытка не пытка. Пока что старые(пару месяцев назад) РАЗЖЁВАННЫЕ посты Багамута, которые вы при желании можете здесь найти, для меня звучат убедительнее, там хоть пара фактов, про то, что разбираться с этими числодробилками замучаешься и толку от них как от козла молока.
Я верю, что "просто" 3 полноценных ядра, намного более производительнее в играх, где не важна потоковость данных, чем 1 ядро, на которое возлагается ось и восемь неуниверсальных числодробилок. Это моё личное ИМХО. А если вспомнить про видеочип пс3, то просто плакать хочется, ещё до выхода консоли.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Лень внимательно читать все посты.
Но скажу вотчто.
Можетбыть как-только выйдет PS3 CELL будет наиболее производительным процессором. Факт в том, что ПК рынок, в отличие от PS на месте не стоит и развивается планомерно развитию всей КИ (чтобы не говорили епучие критики, пророчествующие смерти ПК то после выхода PS, то после PS2->Xbox->xbox360->ps3-> херня!)
Когда выходили Пс2 или Хбох они тоже были наиболее производительными в области игроприложений. И херли! Время идет, сейчас все приставки по качеству графики (не считая толькозапущенного box360, но и тот уйдет год-через полтора.) сосут у ПК. Я не говорю что ПС3 и Cell отстой. Просто наивно полагать что в течении ближайших 5 лет ПК индустрия будет стоять на месте.
И не говорите что на оптимизацию-запуск в серию-отладку-падение цен для одной линейки процессоров потратится 4-5 лет. За это время соответствующая линейка процессоров (не забывайте про видео, которое на ПС уже к выходу будет для ПК нормой) поменяется 50 раз.
Вобщем ПК апгрейдится, приставка нет тчк

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
[quote name="mansel"](... епучие критики ... PS2->Xbox->xbox360->ps3-> херня!)
[/quote]
а херня это что? nintendo rev? :lol:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
[b]2 Denim[/b]

[i]Ray-tracing и анимация частиц, плюс может обрабатывать и шейдеры[/i]
Рейтрейсинга в PS3 скорее всего (99% даю) НЕ будет (того, о котором вы говорите). Слишком мала мощность, чтобы изобразить хоть что-то, похожее на то, что сможет отрендерить RSX. Смысла нет.
Анимация частиц? Можно, да. Игры будут из одних частиц, чтобы Cell задействовать на полную :).
О каких-таких "шейдерах" вы говорите? Если о вершинных, то я же писал о том, что [b]часть[/b] их [b]может[/b] исполняться на Cell и над этим работают.

[i]Лично я сейчас работаю в команде по разработке искуственного интеллекта[/i]
С вас интеллект для роботов пишут, вероятно? А то более сложные алгоритмы труднее делать, боятся, что не получится :gigi:. Ничего личного, но так выпячивать свои "достоинства" непорядочно. Членами здесь меряться не будем.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
[b]PBS[/b]

[quote]Вода, вода, вода и снова коронное надоело, больше не буду... Попытка не пытка. Пока что старые(пару месяцев назад) РАЗЖЁВАННЫЕ посты Багамута, которые вы при желании можете здесь найти, для меня звучат убедительнее, там хоть пара фактов, про то, что разбираться с этими числодробилками замучаешься и толку от них как от козла молока. [/quote]
Вам что конкретно нужно, уважаемый? Чтобы я вас переубедил в том что Cell достойная архитектура? Видать у меня на пальцах не получается вам это разъяснить. Походу вам нужны технические термины? Почитайте куче обзоров этого процессора на зарубежных сайтах, не без известными людьми, которыве все сходяться в одном мнении, что это достойный процессор.
Можно ссылочки на эти Разжеванные посты Багамута посмотреть?
И еще, разбираться с процессором будет не легко но все сопроводительное ПО для программирования под него уже написанно и разработчики получают полную поддержку от STI. Так что не так все страшно, человек он ко всему привыкает, и к новым способам прогаммирования в том числе.

[b]Enemy First[/b]

[quote]Ray-tracing и анимация частиц, плюс может обрабатывать и шейдеры
Рейтрейсинга в PS3 скорее всего (99% даю) НЕ будет (того, о котором вы говорите). Слишком мала мощность, чтобы изобразить хоть что-то, похожее на то, что сможет отрендерить RSX. Смысла нет.
Анимация частиц? Можно, да. Игры будут из одних частиц, чтобы Cell задействовать на полную Улыбка.
О каких-таких "шейдерах" вы говорите? Если о вершинных, то я же писал о том, что часть их может исполняться на Cell и над этим работают. [/quote]
Если вы внимательно читали мой ответ, то могли заметить что я привел те возможности которыми обладает Cell, а не только, как вы написали - Тесселяция поверхностей и освещение. Я просто показал вам чем еще может заниматься процессор в 3d кроме того что вы написали. И не надо говорить что он будет делать это очень медленно. Не будет.

[quote]С вас интеллект для роботов пишут, вероятно? А то более сложные алгоритмы труднее делать, боятся, что не получится Гыгы. Ничего личного, но так выпячивать свои "достоинства" непорядочно. Членами здесь меряться не будем.[/quote]

Нет, не сменя пишут. Вы предлагаете свою кандидатуру? Тогда робот не то что простые действия сделать не сможет, а даже нормально передвигаться. Упрется лбом в стену и будет толкать с пеной у рта. Ничего личного. :wink:

И членами тут никто не меряется, человек задал мне вопрос чем я занимаюсь, я ему ответил. Вот и все.

Интерестно, а чем занимаетесь вы, если не секрет?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Denim, ссылки в рубрике дезматч, 360 версус ПС3. Там полистайте.
А Вы тоже, дайте мне ссылки, вот на это - Походу вам нужны технические термины? Почитайте куче обзоров этого процессора на зарубежных сайтах, не без известными людьми, которыве все сходяться в одном мнении, что это достойный процессор.
Почитаю перед сном.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
[url=http://www.blachford.info/computer/Cell/Cell0_v2.html]Вот раз.[/url]
[url=http://gametomorrow.com/blog/index.php/2005/11/30/gpus-vs-cell/]Вот[/url]его графические возможности.
[url=http://www.3dnews.ru/cpu/cell/index.htm]Тут[/url] на русском обзорчик.

Если нужно еще, предоставлю еще. Пока прочитайте это.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Denim, я это всё читал, более того, часть из этого уже здесь обсуждалось, есть что-нибудь ещё?


Вот этого просто обвисли уши... сколько лет статье?

Если использовать Cell для построения видеокарты (возможен и такой вариант), то SPE могут служить пиксельными шейдерами и будут использоваться для конвейера просчёта. Не смейтесь. Сама IBM во время ISSCC 2005 заявила, что считает Cell комбинацией процессора и графического чипа. Благодаря прямой связи между всеми SPE с помощью шины EIB (о которой мы поговорим чуть ниже), а также локальной памяти в их составе, существует возможность динамически переключать различные процессорные элементы на выполнение той или иной части конвейера просчёта.

Чтобы не быть многословными, перечислим возможности использования SPE через запятую: просчёт физических моделей, тесселяция поверхностей высшего порядка в полигональные модели, инверсная кинематика, скелетная анимация, обработка воксельных данных, анимация частиц, компрессия/декомпрессия видеоданных в формате MPEG4 "на лету", просчёт алгоритма ray-tracing "на лету", преобразование аудиоданных из одного формата в другой "на лету", обработка алгоритмов шифрования, искусственного интеллекта… это предложение можно продолжать очень долго, но мы остановимся и перейдём к следующему элементу архитектуры Cell.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
В первой статье, в конце приводяться референсы и альтернативные статьи. Можете почитать еще там.

3dnews-овская статья была написана, как ибольшенство имеющихся в инете, в начале года, когда собственно процессор и был представлен общественности. За год его характеристики не поменялись, я вас уверяю. Так что написана статья год назад или вчера, особого значения не имеет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
[b]2 Denim[/b]

[i]И не надо говорить что он будет делать это очень медленно. Не будет.[/i]
Действительно. Не будет. О чем я вам и говорю. Не будет он рейтрейсинг всей сцены считать :).

Чем занимаюсь - не секрет. Дуракавалянием :).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
А вобще, давайте ка всетаки подождем выхода приставки. Все и разъясниться: целесообразно ли было ставить Cell на место ЦП или нет, справиться ли он с возложенными на него надеждами, будут ли игры лучше в целом. Я уже не однократно говорил, что сейчас гадать - зря тратить время. Но по всем прдварительным прогнозам, прока все ровно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
В 3dnews просто ламеры вислоухие сидят, древность статьи тут не причем :gigi:.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
[b]Enemy First[/b]

Не будет он делать рейтресинг, я слогласен. У одного его кишка тонка. Если несколько объеденить в кластер то будет толк. Но я лишь сказал, что процессор на это способен, и делает это быстрее всех существующих на данный момент. Те же пни делают это гораздо медленнее.

[size=75]Добавлено 17 Dec 2005, 18:07:[/size]

[i]В 3dnews просто ламеры вислоухие сидят[/i]
А какое для вас издание авторитеное, если не секрет?

[size=75]Добавлено 17 Dec 2005, 18:11:[/size]

[url=http://www.ixbt.com/consoles/xbvsps.shtml]Вот[/url] размышления IXBT по этому поводу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Denim, IXBT вообще ничего внятного не сказали, они как и Вы, выбрали нейтралитет, боясь ошибиться. Вы как будто с луны к нам свалились, мы ведь всё это читали и обсуждали тут, даже на форуме IXBT всё уже обсуждалось, революции у Сони не получится. Хотя когда были только первые анонсы Целл, года два назад или когда там, я ждал революции, не меньше. Увы и ах, снова пшик.

Хотя насчёт нейтралитета я поторопился... Роботы говорите? Ну-ну...

[quote name="Denim"]Блин, да в ней есть все что только туда можно было напихать! Я в шоке! :scare: :uzi: Xbox360 Must Die :beer: :beer:[/quote]

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
[quote name="Enemy First"]В 3dnews просто ламеры вислоухие сидят, древность статьи тут не причем :gigi:.[/quote]

И после всей этой ботвы, ещё находятся "оптимисты" на этом форуме, которые вопрошают: А когда Сони обманывала? Что? А? Все уши обвисли...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Я конечно понимаю, что щас пишу немного не в тему, но!
Почему вы обсуждаете работоспособность CELL'а, и сравниваете его с компьютерами, и предсказываете с пенои изо рта, когда компьютеры сравняются с PS3 по тех. характеристикам ? Ведь главное отличие ЗЫ3 и персонального компьютера совсем не в этом - ведь комп изначально и не предназначался для игр! а пс3 - игровая консоль, и, замечу, что игры там наверняка будут интереснее, чем на пк, да и хитовых игр там будет больше.(1~10 наверное). мое мнение - сравнивать тех.х. неприемлемо!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Infinity, мы здесь ещё сравниваем ещё и с 360, моё имхо, что пс3 ни капли не мощнее 360-ого и что компы довольно быстро обгонят консоли, как всегда. А про интересность игр тут никто не говорит, это в другую тему.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
кстати, gothic был прав. перемножение матриц рулит. не думал, что все будет настолько запущено. вот простенькое перемножение матриц:

[code]
for (i=0; i for (j=0; j exp[i*msize+j] = 0.0f;
for (k=0; k exp[i*msize+j] += a[i*msize+k] * b[k*msize+j];
}
}
[/code]

как вы думаете, как будут выглядеть эти 7 строк, соптимизированные для работы на SPE? ответ:

[size=59]/* @(#)86 1.3 src/workloads/matrix_mul/spu/block.c, sw.workloads, sdk_pub 10/11/05 15:29:21 */
/* -------------------------------------------------------------- */
/* (C) Copyright 2001,2005, */
/* International Business Machines Corporation, */
/* Sony Computer Entertainment Incorporated, */
/* Toshiba Corporation. */
/* */
/* All Rights Reserved. */
/* -------------------------------------------------------------- */
/* PROLOG END TAG zYx */

/*
* Matrix Multiply --- EUC
*
* block.c - Matrix Multiply with block partitioning
*/

#include
#include
#include
#include
#include
#include "atomic_inc_return.h"

#ifndef M
#define M 64 /* Size of the matrix block - M x M */
#endif

#define MAX_N 1024
#define MAX_TILES (MAX_N / M)

static unsigned int N;
static unsigned int ITER;
static unsigned int A_AREA, B_AREA, C_AREA;
static atomic_ea_t FINC_AREA2;

#define DIN_TAG 0
#define DOUT_TAG 2

#define DMA_Wait(TAG_ID)
{
mfc_write_tag_mask((1<<(TAG_ID)));
mfc_read_tag_status_all();
}

#define SwapInBuf()
{
OpA = InTag ? blkA1 : blkA0;
OpB = InTag ? blkB1 : blkB0;
InTag ^= 1;
InA = InTag ? blkA1 : blkA0;
InB = InTag ? blkB1 : blkB0;
}

#define SwapOutBuf()
{
OpC = (OutTag==DOUT_TAG) ? blkC1 : blkC0;
OutC = (OutTag==DOUT_TAG) ? blkC1 : blkC0;
OutTag ^= 1;
}

#ifdef _XLC

#define ALIGN8B
#define SPU_FMA(RT,RA,RB,RC) RT = spu_madd(RA, RB, RC)
#define SPU_FM(RT,RA,RB) RT = spu_mul(RA, RB)
#define SPU_LNOP

#else

#define ALIGN8B asm volatile(".align 3")

#define SPU_FMA(RT,RA,RB,RC)
asm volatile(".align 3");
asm volatile("fma %0,%1,%2,%3":"=r"(RT):"r"(RA),"r"(RB),"r"(RC))

#define SPU_FM(RT,RA,RB)
asm volatile(".align 3");
asm volatile("fm %0,%1,%2":"=r"(RT):"r"(RA),"r"(RB))

#define SPU_LNOP asm volatile("lnop")


#endif



#define StageCBAclr(OFFSET)
{
ALIGN8B;
SPU_FM(c0_0B,a00,b0_0B);
SPU_FM(c1_0B,a10,b0_0B);
SPU_FM(c2_0B,a20,b0_0B);
SPU_FM(c3_0B,a30,b0_0B);
SPU_FM(c0_1B,a00,b0_1B);
SPU_FM(c1_1B,a10,b0_1B);
SPU_FM(c2_1B,a20,b0_1B);
SPU_FM(c3_1B,a30,b0_1B);
SPU_FMA(c0_0B,a01,b1_0B,c0_0B);
SPU_FMA(c1_0B,a11,b1_0B,c1_0B);
SPU_FMA(c2_0B,a21,b1_0B,c2_0B); b0_0C = *((volatile vector float *)(ptrB+OFFSET+16));
SPU_FMA(c3_0B,a31,b1_0B,c3_0B); SPU_LNOP;
SPU_FMA(c0_1B,a01,b1_1B,c0_1B); b1_0C = *((volatile vector float *)(ptrB+M+OFFSET+16));
SPU_FMA(c1_1B,a11,b1_1B,c1_1B); b2_0C = *((volatile vector float *)(ptrB+2*M+OFFSET+16));
SPU_FMA(c2_1B,a21,b1_1B,c2_1B); b3_0C = *((volatile vector float *)(ptrB+3*M+OFFSET+16));
SPU_FMA(c3_1B,a31,b1_1B,c3_1B); SPU_LNOP;
SPU_FMA(c0_0B,a02,b2_0B,c0_0B); b0_1C = *((volatile vector float *)(ptrB+OFFSET+20));
SPU_FMA(c1_0B,a12,b2_0B,c1_0B); b1_1C = *((volatile vector float *)(ptrB+M+OFFSET+20));
SPU_FMA(c2_0B,a22,b2_0B,c2_0B); b2_1C = *((volatile vector float *)(ptrB+2*M+OFFSET+20));
SPU_FMA(c3_0B,a32,b2_0B,c3_0B); SPU_LNOP;
SPU_FMA(c0_1B,a02,b2_1B,c0_1B); b3_1C = *((volatile vector float *)(ptrB+3*M+OFFSET+20));
SPU_FMA(c1_1B,a12,b2_1B,c1_1B); *((volatile vector float *)(ptrC+OFFSET)) = c0_0A;
SPU_FMA(c2_1B,a22,b2_1B,c2_1B); *((volatile vector float *)(ptrC+M+OFFSET)) = c1_0A;
SPU_FMA(c3_1B,a32,b2_1B,c3_1B); SPU_LNOP;
SPU_FMA(c0_0B,a03,b3_0B,c0_0B); *((volatile vector float *)(ptrC+2*M+OFFSET)) = c2_0A;
SPU_FMA(c1_0B,a13,b3_0B,c1_0B); *((volatile vector float *)(ptrC+3*M+OFFSET)) = c3_0A;
SPU_FMA(c2_0B,a23,b3_0B,c2_0B); *((volatile vector float *)(ptrC+OFFSET+4)) = c0_1A;
SPU_FMA(c3_0B,a33,b3_0B,c3_0B); SPU_LNOP;
SPU_FMA(c0_1B,a03,b3_1B,c0_1B); *((volatile vector float *)(ptrC+M+OFFSET+4)) = c1_1A;
SPU_FMA(c1_1B,a13,b3_1B,c1_1B); *((volatile vector float *)(ptrC+2*M+OFFSET+4)) = c2_1A;
SPU_FMA(c2_1B,a23,b3_1B,c2_1B); *((volatile vector float *)(ptrC+3*M+OFFSET+4)) = c3_1A;
SPU_FMA(c3_1B,a33,b3_1B,c3_1B); SPU_LNOP;
}

#define StageACBclr(OFFSET)
{
SPU_FM(c0_0C,a00,b0_0C);
SPU_FM(c1_0C,a10,b0_0C);
SPU_FM(c2_0C,a20,b0_0C);
SPU_FM(c3_0C,a30,b0_0C);
SPU_FM(c0_1C,a00,b0_1C);
SPU_FM(c1_1C,a10,b0_1C);
SPU_FM(c2_1C,a20,b0_1C);
SPU_FM(c3_1C,a30,b0_1C);
SPU_FMA(c0_0C,a01,b1_0C,c0_0C);
SPU_FMA(c1_0C,a11,b1_0C,c1_0C);
SPU_FMA(c2_0C,a21,b1_0C,c2_0C); b0_0A = *((volatile vector float *)(ptrB+OFFSET+16));
SPU_FMA(c3_0C,a31,b1_0C,c3_0C); SPU_LNOP;
SPU_FMA(c0_1C,a01,b1_1C,c0_1C); b1_0A = *((volatile vector float *)(ptrB+M+OFFSET+16));
SPU_FMA(c1_1C,a11,b1_1C,c1_1C); b2_0A = *((volatile vector float *)(ptrB+2*M+OFFSET+16));
SPU_FMA(c2_1C,a21,b1_1C,c2_1C); b3_0A = *((volatile vector float *)(ptrB+3*M+OFFSET+16));
SPU_FMA(c3_1C,a31,b1_1C,c3_1C); SPU_LNOP;
SPU_FMA(c0_0C,a02,b2_0C,c0_0C); b0_1A = *((volatile vector float *)(ptrB+OFFSET+20));
SPU_FMA(c1_0C,a12,b2_0C,c1_0C); b1_1A = *((volatile vector float *)(ptrB+M+OFFSET+20));
SPU_FMA(c2_0C,a22,b2_0C,c2_0C); b2_1A = *((volatile vector float *)(ptrB+2*M+OFFSET+20));
SPU_FMA(c3_0C,a32,b2_0C,c3_0C); SPU_LNOP;
SPU_FMA(c0_1C,a02,b2_1C,c0_1C); b3_1A = *((volatile vector float *)(ptrB+3*M+OFFSET+20));
SPU_FMA(c1_1C,a12,b2_1C,c1_1C); *((volatile vector float *)(ptrC+OFFSET)) = c0_0B;
SPU_FMA(c2_1C,a22,b2_1C,c2_1C); *((volatile vector float *)(ptrC+M+OFFSET)) = c1_0B;
SPU_FMA(c3_1C,a32,b2_1C,c3_1C); SPU_LNOP;
SPU_FMA(c0_0C,a03,b3_0C,c0_0C); *((volatile vector float *)(ptrC+2*M+OFFSET)) = c2_0B;
SPU_FMA(c1_0C,a13,b3_0C,c1_0C); *((volatile vector float *)(ptrC+3*M+OFFSET)) = c3_0B;
SPU_FMA(c2_0C,a23,b3_0C,c2_0C); *((volatile vector float *)(ptrC+OFFSET+4)) = c0_1B;
SPU_FMA(c3_0C,a33,b3_0C,c3_0C); SPU_LNOP;
SPU_FMA(c0_1C,a03,b3_1C,c0_1C); *((volatile vector float *)(ptrC+M+OFFSET+4)) = c1_1B;
SPU_FMA(c1_1C,a13,b3_1C,c1_1C); *((volatile vector float *)(ptrC+2*M+OFFSET+4)) = c2_1B;
SPU_FMA(c2_1C,a23,b3_1C,c2_1C); *((volatile vector float *)(ptrC+3*M+OFFSET+4)) = c3_1B;
SPU_FMA(c3_1C,a33,b3_1C,c3_1C); SPU_LNOP;
}

#define StageBACclr(OFFSET)
{
SPU_FM(c0_0A,a00,b0_0A);
SPU_FM(c1_0A,a10,b0_0A);
SPU_FM(c2_0A,a20,b0_0A);
SPU_FM(c3_0A,a30,b0_0A);
SPU_FM(c0_1A,a00,b0_1A);
SPU_FM(c1_1A,a10,b0_1A);
SPU_FM(c2_1A,a20,b0_1A);
SPU_FM(c3_1A,a30,b0_1A);
SPU_FMA(c0_0A,a01,b1_0A,c0_0A);
SPU_FMA(c1_0A,a11,b1_0A,c1_0A);
SPU_FMA(c2_0A,a21,b1_0A,c2_0A); b0_0B = *((volatile vector float *)(ptrB+OFFSET+16));
SPU_FMA(c3_0A,a31,b1_0A,c3_0A); SPU_LNOP;
SPU_FMA(c0_1A,a01,b1_1A,c0_1A); b1_0B = *((volatile vector float *)(ptrB+M+OFFSET+16));
SPU_FMA(c1_1A,a11,b1_1A,c1_1A); b2_0B = *((volatile vector float *)(ptrB+2*M+OFFSET+16));
SPU_FMA(c2_1A,a21,b1_1A,c2_1A); b3_0B = *((volatile vector float *)(ptrB+3*M+OFFSET+16));
SPU_FMA(c3_1A,a31,b1_1A,c3_1A); SPU_LNOP;
SPU_FMA(c0_0A,a02,b2_0A,c0_0A); b0_1B = *((volatile vector float *)(ptrB+OFFSET+20));
SPU_FMA(c1_0A,a12,b2_0A,c1_0A); b1_1B = *((volatile vector float *)(ptrB+M+OFFSET+20));
SPU_FMA(c2_0A,a22,b2_0A,c2_0A); b2_1B = *((volatile vector float *)(ptrB+2*M+OFFSET+20));
SPU_FMA(c3_0A,a32,b2_0A,c3_0A); SPU_LNOP;
SPU_FMA(c0_1A,a02,b2_1A,c0_1A); b3_1B = *((volatile vector float *)(ptrB+3*M+OFFSET+20));
SPU_FMA(c1_1A,a12,b2_1A,c1_1A); *((volatile vector float *)(ptrC+OFFSET)) = c0_0C;
SPU_FMA(c2_1A,a22,b2_1A,c2_1A); *((volatile vector float *)(ptrC+M+OFFSET)) = c1_0C;
SPU_FMA(c3_1A,a32,b2_1A,c3_1A); SPU_LNOP;
SPU_FMA(c0_0A,a03,b3_0A,c0_0A); *((volatile vector float *)(ptrC+2*M+OFFSET)) = c2_0C;
SPU_FMA(c1_0A,a13,b3_0A,c1_0A); *((volatile vector float *)(ptrC+3*M+OFFSET)) = c3_0C;
SPU_FMA(c2_0A,a23,b3_0A,c2_0A); *((volatile vector float *)(ptrC+OFFSET+4)) = c0_1C;
SPU_FMA(c3_0A,a33,b3_0A,c3_0A); SPU_LNOP;
SPU_FMA(c0_1A,a03,b3_1A,c0_1A); *((volatile vector float *)(ptrC+M+OFFSET+4)) = c1_1C;
SPU_FMA(c1_1A,a13,b3_1A,c1_1A); *((volatile vector float *)(ptrC+2*M+OFFSET+4)) = c2_1C;
SPU_FMA(c2_1A,a23,b3_1A,c2_1A); *((volatile vector float *)(ptrC+3*M+OFFSET+4)) = c3_1C;
SPU_FMA(c3_1A,a33,b3_1A,c3_1A); SPU_LNOP;
}

#define StageCBA(OFFSET,OFFB)
{
ALIGN8B;
SPU_FMA(c0_0B,a00,b0_0B,c0_0B); c0_0C = *((volatile vector float *)(ptrC+OFFSET+16));
SPU_FMA(c1_0B,a10,b0_0B,c1_0B); c1_0C = *((volatile vector float *)(ptrC+M+OFFSET+16));
SPU_FMA(c2_0B,a20,b0_0B,c2_0B); c2_0C = *((volatile vector float *)(ptrC+2*M+OFFSET+16));
SPU_FMA(c3_0B,a30,b0_0B,c3_0B); SPU_LNOP;
SPU_FMA(c0_1B,a00,b0_1B,c0_1B); c3_0C = *((volatile vector float *)(ptrC+3*M+OFFSET+16));
SPU_FMA(c1_1B,a10,b0_1B,c1_1B); c0_1C = *((volatile vector float *)(ptrC+OFFSET+20));
SPU_FMA(c2_1B,a20,b0_1B,c2_1B); c1_1C = *((volatile vector float *)(ptrC+M+OFFSET+20));
SPU_FMA(c3_1B,a30,b0_1B,c3_1B); SPU_LNOP;
SPU_FMA(c0_0B,a01,b1_0B,c0_0B); c2_1C = *((volatile vector float *)(ptrC+2*M+OFFSET+20));
SPU_FMA(c1_0B,a11,b1_0B,c1_0B); c3_1C = *((volatile vector float *)(ptrC+3*M+OFFSET+20));
SPU_FMA(c2_0B,a21,b1_0B,c2_0B); b0_0C = *((volatile vector float *)(ptrB+OFFSET+OFFB*M+16));
SPU_FMA(c3_0B,a31,b1_0B,c3_0B); SPU_LNOP;
SPU_FMA(c0_1B,a01,b1_1B,c0_1B); b1_0C = *((volatile vector float *)(ptrB+M+OFFSET+OFFB*M+16));
SPU_FMA(c1_1B,a11,b1_1B,c1_1B); b2_0C = *((volatile vector float *)(ptrB+2*M+OFFSET+OFFB*M+16));
SPU_FMA(c2_1B,a21,b1_1B,c2_1B); b3_0C = *((volatile vector float *)(ptrB+3*M+OFFSET+OFFB*M+16));
SPU_FMA(c3_1B,a31,b1_1B,c3_1B); SPU_LNOP;
SPU_FMA(c0_0B,a02,b2_0B,c0_0B); b0_1C = *((volatile vector float *)(ptrB+OFFSET+OFFB*M+20));
SPU_FMA(c1_0B,a12,b2_0B,c1_0B); b1_1C = *((volatile vector float *)(ptrB+M+OFFSET+OFFB*M+20));
SPU_FMA(c2_0B,a22,b2_0B,c2_0B); b2_1C = *((volatile vector float *)(ptrB+2*M+OFFSET+OFFB*M+20));
SPU_FMA(c3_0B,a32,b2_0B,c3_0B); SPU_LNOP;
SPU_FMA(c0_1B,a02,b2_1B,c0_1B); b3_1C = *((volatile vector float *)(ptrB+3*M+OFFSET+OFFB*M+20));
SPU_FMA(c1_1B,a12,b2_1B,c1_1B); *((volatile vector float *)(ptrC+OFFSET)) = c0_0A;
SPU_FMA(c2_1B,a22,b2_1B,c2_1B); *((volatile vector float *)(ptrC+M+OFFSET)) = c1_0A;
SPU_FMA(c3_1B,a32,b2_1B,c3_1B); SPU_LNOP;
SPU_FMA(c0_0B,a03,b3_0B,c0_0B); *((volatile vector float *)(ptrC+2*M+OFFSET)) = c2_0A;
SPU_FMA(c1_0B,a13,b3_0B,c1_0B); *((volatile vector float *)(ptrC+3*M+OFFSET)) = c3_0A;
SPU_FMA(c2_0B,a23,b3_0B,c2_0B); *((volatile vector float *)(ptrC+OFFSET+4)) = c0_1A;
SPU_FMA(c3_0B,a33,b3_0B,c3_0B); SPU_LNOP;
SPU_FMA(c0_1B,a03,b3_1B,c0_1B); *((volatile vector float *)(ptrC+M+OFFSET+4)) = c1_1A;
SPU_FMA(c1_1B,a13,b3_1B,c1_1B); *((volatile vector float *)(ptrC+2*M+OFFSET+4)) = c2_1A;
SPU_FMA(c2_1B,a23,b3_1B,c2_1B); *((volatile vector float *)(ptrC+3*M+OFFSET+4)) = c3_1A;
SPU_FMA(c3_1B,a33,b3_1B,c3_1B); SPU_LNOP;
}

#define StageCBAmod(OFFSET,OFFB)
{
ALIGN8B;
SPU_FMA(c0_0B,a00,b0_0B,c0_0B); SPU_LNOP;
SPU_FMA(c1_0B,a10,b0_0B,c1_0B); b2_0B = *((volatile vector float *)(ptrB+2*M+OFFB*M+8 ));
SPU_FMA(c2_0B,a20,b0_0B,c2_0B); b2_1B = *((volatile vector float *)(ptrB+2*M+OFFB*M+12));
SPU_FMA(c3_0B,a30,b0_0B,c3_0B); b3_0B = *((volatile vector float *)(ptrB+3*M+OFFB*M+8 ));
SPU_FMA(c0_1B,a00,b0_1B,c0_1B); b3_1B = *((volatile vector float *)(ptrB+3*M+OFFB*M+12));
SPU_FMA(c1_1B,a10,b0_1B,c1_1B); c0_0C = *((volatile vector float *)(ptrC+OFFSET+16));
SPU_FMA(c2_1B,a20,b0_1B,c2_1B); c1_0C = *((volatile vector float *)(ptrC+M+OFFSET+16));
SPU_FMA(c3_1B,a30,b0_1B,c3_1B); c2_0C = *((volatile vector float *)(ptrC+2*M+OFFSET+16));
SPU_FMA(c0_0B,a01,b1_0B,c0_0B); c3_0C = *((volatile vector float *)(ptrC+3*M+OFFSET+16));
SPU_FMA(c1_0B,a11,b1_0B,c1_0B); SPU_LNOP;
SPU_FMA(c2_0B,a21,b1_0B,c2_0B); c0_1C = *((volatile vector float *)(ptrC+OFFSET+20));
SPU_FMA(c3_0B,a31,b1_0B,c3_0B); c1_1C = *((volatile vector float *)(ptrC+M+OFFSET+20));
SPU_FMA(c0_1B,a01,b1_1B,c0_1B); c2_1C = *((volatile vector float *)(ptrC+2*M+OFFSET+20));
SPU_FMA(c1_1B,a11,b1_1B,c1_1B); c3_1C = *((volatile vector float *)(ptrC+3*M+OFFSET+20));
SPU_FMA(c2_1B,a21,b1_1B,c2_1B); b0_0C = *((volatile vector float *)(ptrB+OFFSET+OFFB*M+16));
SPU_FMA(c3_1B,a31,b1_1B,c3_1B); b1_0C = *((volatile vector float *)(ptrB+M+OFFSET+OFFB*M+16));
SPU_FMA(c0_0B,a02,b2_0B,c0_0B); b2_0C = *((volatile vector float *)(ptrB+2*M+OFFSET+OFFB*M+16));
SPU_FMA(c1_0B,a12,b2_0B,c1_0B); b3_0C = *((volatile vector float *)(ptrB+3*M+OFFSET+OFFB*M+16));
SPU_FMA(c2_0B,a22,b2_0B,c2_0B); SPU_LNOP;
SPU_FMA(c3_0B,a32,b2_0B,c3_0B); b0_1C = *((volatile vector float *)(ptrB+OFFSET+OFFB*M+20));
SPU_FMA(c0_1B,a02,b2_1B,c0_1B); b1_1C = *((volatile vector float *)(ptrB+M+OFFSET+OFFB*M+20));
SPU_FMA(c1_1B,a12,b2_1B,c1_1B); b2_1C = *((volatile vector float *)(ptrB+2*M+OFFSET+OFFB*M+20));
SPU_FMA(c2_1B,a22,b2_1B,c2_1B); b3_1C = *((volatile vector float *)(ptrB+3*M+OFFSET+OFFB*M+20));
SPU_FMA(c3_1B,a32,b2_1B,c3_1B); *((volatile vector float *)(ptrC+OFFSET)) = c0_0A;
SPU_FMA(c0_0B,a03,b3_0B,c0_0B); *((volatile vector float *)(ptrC+M+OFFSET)) = c1_0A;
SPU_FMA(c1_0B,a13,b3_0B,c1_0B); *((volatile vector float *)(ptrC+2*M+OFFSET)) = c2_0A;
SPU_FMA(c2_0B,a23,b3_0B,c2_0B); *((volatile vector float *)(ptrC+3*M+OFFSET)) = c3_0A;
SPU_FMA(c3_0B,a33,b3_0B,c3_0B); SPU_LNOP;
SPU_FMA(c0_1B,a03,b3_1B,c0_1B); *((volatile vector float *)(ptrC+OFFSET+4)) = c0_1A;
SPU_FMA(c1_1B,a13,b3_1B,c1_1B); *((volatile vector float *)(ptrC+M+OFFSET+4)) = c1_1A;
SPU_FMA(c2_1B,a23,b3_1B,c2_1B); *((volatile vector float *)(ptrC+2*M+OFFSET+4)) = c2_1A;
SPU_FMA(c3_1B,a33,b3_1B,c3_1B); *((volatile vector float *)(ptrC+3*M+OFFSET+4)) = c3_1A;
}

#define StageACB(OFFSET,OFFB)
{
SPU_FMA(c0_0C,a00,b0_0C,c0_0C); c0_0A = *((volatile vector float *)(ptrC+OFFSET+16));
SPU_FMA(c1_0C,a10,b0_0C,c1_0C); c1_0A = *((volatile vector float *)(ptrC+M+OFFSET+16));
SPU_FMA(c2_0C,a20,b0_0C,c2_0C); c2_0A = *((volatile vector float *)(ptrC+2*M+OFFSET+16));
SPU_FMA(c3_0C,a30,b0_0C,c3_0C); SPU_LNOP;
SPU_FMA(c0_1C,a00,b0_1C,c0_1C); c3_0A = *((volatile vector float *)(ptrC+3*M+OFFSET+16));
SPU_FMA(c1_1C,a10,b0_1C,c1_1C); c0_1A = *((volatile vector float *)(ptrC+OFFSET+20));
SPU_FMA(c2_1C,a20,b0_1C,c2_1C); c1_1A = *((volatile vector float *)(ptrC+M+OFFSET+20));
SPU_FMA(c3_1C,a30,b0_1C,c3_1C); SPU_LNOP;
SPU_FMA(c0_0C,a01,b1_0C,c0_0C); c2_1A = *((volatile vector float *)(ptrC+2*M+OFFSET+20));
SPU_FMA(c1_0C,a11,b1_0C,c1_0C); c3_1A = *((volatile vector float *)(ptrC+3*M+OFFSET+20));
SPU_FMA(c2_0C,a21,b1_0C,c2_0C); b0_0A = *((volatile vector float *)(ptrB+OFFSET+OFFB*M+16));
SPU_FMA(c3_0C,a31,b1_0C,c3_0C); SPU_LNOP;
SPU_FMA(c0_1C,a01,b1_1C,c0_1C); b1_0A = *((volatile vector float *)(ptrB+M+OFFSET+OFFB*M+16));
SPU_FMA(c1_1C,a11,b1_1C,c1_1C); b2_0A = *((volatile vector float *)(ptrB+2*M+OFFSET+OFFB*M+16));
SPU_FMA(c2_1C,a21,b1_1C,c2_1C); b3_0A = *((volatile vector float *)(ptrB+3*M+OFFSET+OFFB*M+16));
SPU_FMA(c3_1C,a31,b1_1C,c3_1C); SPU_LNOP;
SPU_FMA(c0_0C,a02,b2_0C,c0_0C); b0_1A = *((volatile vector float *)(ptrB+OFFSET+OFFB*M+20));
SPU_FMA(c1_0C,a12,b2_0C,c1_0C); b1_1A = *((volatile vector float *)(ptrB+M+OFFSET+OFFB*M+20));
SPU_FMA(c2_0C,a22,b2_0C,c2_0C); b2_1A = *((volatile vector float *)(ptrB+2*M+OFFSET+OFFB*M+20));
SPU_FMA(c3_0C,a32,b2_0C,c3_0C); SPU_LNOP;
SPU_FMA(c0_1C,a02,b2_1C,c0_1C); b3_1A = *((volatile vector float *)(ptrB+3*M+OFFSET+OFFB*M+20));
SPU_FMA(c1_1C,a12,b2_1C,c1_1C); *((volatile vector float *)(ptrC+OFFSET)) = c0_0B;
SPU_FMA(c2_1C,a22,b2_1C,c2_1C); *((volatile vector float *)(ptrC+M+OFFSET)) = c1_0B;
SPU_FMA(c3_1C,a32,b2_1C,c3_1C); SPU_LNOP;
SPU_FMA(c0_0C,a03,b3_0C,c0_0C); *((volatile vector float *)(ptrC+2*M+OFFSET)) = c2_0B;
SPU_FMA(c1_0C,a13,b3_0C,c1_0C); *((volatile vector float *)(ptrC+3*M+OFFSET)) = c3_0B;
SPU_FMA(c2_0C,a23,b3_0C,c2_0C); *((volatile vector float *)(ptrC+OFFSET+4)) = c0_1B;
SPU_FMA(c3_0C,a33,b3_0C,c3_0C); SPU_LNOP;
SPU_FMA(c0_1C,a03,b3_1C,c0_1C); *((volatile vector float *)(ptrC+M+OFFSET+4)) = c1_1B;
SPU_FMA(c1_1C,a13,b3_1C,c1_1C); *((volatile vector float *)(ptrC+2*M+OFFSET+4)) = c2_1B;
SPU_FMA(c2_1C,a23,b3_1C,c2_1C); *((volatile vector float *)(ptrC+3*M+OFFSET+4)) = c3_1B;
SPU_FMA(c3_1C,a33,b3_1C,c3_1C); SPU_LNOP;
}

#define StageBAC(OFFSET,OFFB)
{
SPU_FMA(c0_0A,a00,b0_0A,c0_0A); c0_0B = *((volatile vector float *)(ptrC+OFFSET+16));
SPU_FMA(c1_0A,a10,b0_0A,c1_0A); c1_0B = *((volatile vector float *)(ptrC+M+OFFSET+16));
SPU_FMA(c2_0A,a20,b0_0A,c2_0A); c2_0B = *((volatile vector float *)(ptrC+2*M+OFFSET+16));
SPU_FMA(c3_0A,a30,b0_0A,c3_0A); SPU_LNOP;
SPU_FMA(c0_1A,a00,b0_1A,c0_1A); c3_0B = *((volatile vector float *)(ptrC+3*M+OFFSET+16));
SPU_FMA(c1_1A,a10,b0_1A,c1_1A); c0_1B = *((volatile vector float *)(ptrC+OFFSET+20));
SPU_FMA(c2_1A,a20,b0_1A,c2_1A); c1_1B = *((volatile vector float *)(ptrC+M+OFFSET+20));
SPU_FMA(c3_1A,a30,b0_1A,c3_1A); SPU_LNOP;
SPU_FMA(c0_0A,a01,b1_0A,c0_0A); c2_1B = *((volatile vector float *)(ptrC+2*M+OFFSET+20));
SPU_FMA(c1_0A,a11,b1_0A,c1_0A); c3_1B = *((volatile vector float *)(ptrC+3*M+OFFSET+20));
SPU_FMA(c2_0A,a21,b1_0A,c2_0A); b0_0B = *((volatile vector float *)(ptrB+OFFSET+OFFB*M+16));
SPU_FMA(c3_0A,a31,b1_0A,c3_0A); SPU_LNOP;
SPU_FMA(c0_1A,a01,b1_1A,c0_1A); b1_0B = *((volatile vector float *)(ptrB+M+OFFSET+OFFB*M+16));
SPU_FMA(c1_1A,a11,b1_1A,c1_1A); b2_0B = *((volatile vector float *)(ptrB+2*M+OFFSET+OFFB*M+16));
SPU_FMA(c2_1A,a21,b1_1A,c2_1A); b3_0B = *((volatile vector float *)(ptrB+3*M+OFFSET+OFFB*M+16));
SPU_FMA(c3_1A,a31,b1_1A,c3_1A); SPU_LNOP;
SPU_FMA(c0_0A,a02,b2_0A,c0_0A); b0_1B = *((volatile vector float *)(ptrB+OFFSET+OFFB*M+20));
SPU_FMA(c1_0A,a12,b2_0A,c1_0A); b1_1B = *((volatile vector float *)(ptrB+M+OFFSET+OFFB*M+20));
SPU_FMA(c2_0A,a22,b2_0A,c2_0A); b2_1B = *((volatile vector float *)(ptrB+2*M+OFFSET+OFFB*M+20));
SPU_FMA(c3_0A,a32,b2_0A,c3_0A); SPU_LNOP;
SPU_FMA(c0_1A,a02,b2_1A,c0_1A); b3_1B = *((volatile vector float *)(ptrB+3*M+OFFSET+OFFB*M+20));
SPU_FMA(c1_1A,a12,b2_1A,c1_1A); *((volatile vector float *)(ptrC+OFFSET)) = c0_0C;
SPU_FMA(c2_1A,a22,b2_1A,c2_1A); *((volatile vector float *)(ptrC+M+OFFSET)) = c1_0C;
SPU_FMA(c3_1A,a32,b2_1A,c3_1A); SPU_LNOP;
SPU_FMA(c0_0A,a03,b3_0A,c0_0A); *((volatile vector float *)(ptrC+2*M+OFFSET)) = c2_0C;
SPU_FMA(c1_0A,a13,b3_0A,c1_0A); *((volatile vector float *)(ptrC+3*M+OFFSET)) = c3_0C;
SPU_FMA(c2_0A,a23,b3_0A,c2_0A); *((volatile vector float *)(ptrC+OFFSET+4)) = c0_1C;
SPU_FMA(c3_0A,a33,b3_0A,c3_0A); SPU_LNOP;
SPU_FMA(c0_1A,a03,b3_1A,c0_1A); *((volatile vector float *)(ptrC+M+OFFSET+4)) = c1_1C;
SPU_FMA(c1_1A,a13,b3_1A,c1_1A); *((volatile vector float *)(ptrC+2*M+OFFSET+4)) = c2_1C;
SPU_FMA(c2_1A,a23,b3_1A,c2_1A); *((volatile vector float *)(ptrC+3*M+OFFSET+4)) = c3_1C;
SPU_FMA(c3_1A,a33,b3_1A,c3_1A); SPU_LNOP;
}

#define StageMISC(OFFA,OFFB)
{
SPU_FMA(c0_0B,a00,b0_0B,c0_0B); a0 = *((volatile vector float *)(ptrA+OFFA+4));
SPU_FMA(c1_0B,a10,b0_0B,c1_0B); a1 = *((volatile vector float *)(ptrA+M+OFFA+4));
SPU_FMA(c2_0B,a20,b0_0B,c2_0B); a2 = *((volatile vector float *)(ptrA+2*M+OFFA+4));
SPU_FMA(c3_0B,a30,b0_0B,c3_0B); a3 = *((volatile vector float *)(ptrA+3*M+OFFA+4));
SPU_FMA(c0_1B,a00,b0_1B,c0_1B); *((volatile vector float *)(ptrC+48 )) = c0_0A;
SPU_FMA(c1_1B,a10,b0_1B,c1_1B); *((volatile vector float *)(ptrC+M+48 )) = c1_0A;
SPU_FMA(c2_1B,a20,b0_1B,c2_1B); a00 = spu_shuffle(a0, a0, pat0);
SPU_FMA(c3_1B,a30,b0_1B,c3_1B); *((volatile vector float *)(ptrC+2*M+48 )) = c2_0A;
SPU_FMA(c0_0B,a01,b1_0B,c0_0B); *((volatile vector float *)(ptrC+3*M+48 )) = c3_0A;
SPU_FMA(c1_0B,a11,b1_0B,c1_0B); a10 = spu_shuffle(a1, a1, pat0);
SPU_FMA(c2_0B,a21,b1_0B,c2_0B); *((volatile vector float *)(ptrC+52)) = c0_1A;
SPU_FMA(c3_0B,a31,b1_0B,c3_0B); *((volatile vector float *)(ptrC+M+52)) = c1_1A;
SPU_FMA(c0_1B,a01,b1_1B,c0_1B); a20 = spu_shuffle(a2, a2, pat0);
SPU_FMA(c1_1B,a11,b1_1B,c1_1B); *((volatile vector float *)(ptrC+2*M+52)) = c2_1A;
SPU_FMA(c2_1B,a21,b1_1B,c2_1B); *((volatile vector float *)(ptrC+3*M+52)) = c3_1A;
SPU_FMA(c3_1B,a31,b1_1B,c3_1B); a30 = spu_shuffle(a3, a3, pat0);
SPU_FMA(c0_0B,a02,b2_0B,c0_0B); c0_0A = *((volatile vector float *)(ptrC));
SPU_FMA(c1_0B,a12,b2_0B,c1_0B); c1_0A = *((volatile vector float *)(ptrC+M));
SPU_FMA(c2_0B,a22,b2_0B,c2_0B); a01 = spu_shuffle(a0, a0, pat1);
SPU_FMA(c3_0B,a32,b2_0B,c3_0B); c2_0A = *((volatile vector float *)(ptrC+2*M));
SPU_FMA(c0_1B,a02,b2_1B,c0_1B); c3_0A = *((volatile vector float *)(ptrC+3*M));
SPU_FMA(c1_1B,a12,b2_1B,c1_1B); a11 = spu_shuffle(a1, a1, pat1);
SPU_FMA(c2_1B,a22,b2_1B,c2_1B); b0_0A = *((volatile vector float *)(ptrB+4*M+OFFB*M));
SPU_FMA(c3_1B,a32,b2_1B,c3_1B); b0_1A = *((volatile vector float *)(ptrB+4*M+OFFB*M+4));
SPU_FMA(c0_0B,a03,b3_0B,c0_0B); a21 = spu_shuffle(a2, a2, pat1);
SPU_FMA(c1_0B,a13,b3_0B,c1_0B); b1_0A = *((volatile vector float *)(ptrB+5*M+OFFB*M));
SPU_FMA(c2_0B,a23,b3_0B,c2_0B); b1_1A = *((volatile vector float *)(ptrB+5*M+OFFB*M+4));
SPU_FMA(c3_0B,a33,b3_0B,c3_0B); a31 = spu_shuffle(a3, a3, pat1);
SPU_FMA(c0_1B,a03,b3_1B,c0_1B); c0_1A = *((volatile vector float *)(ptrC+4));
SPU_FMA(c1_1B,a13,b3_1B,c1_1B); c1_1A = *((volatile vector float *)(ptrC+M+4));
SPU_FMA(c2_1B,a23,b3_1B,c2_1B); a02 = spu_shuffle(a0, a0, pat2);
SPU_FMA(c3_1B,a33,b3_1B,c3_1B); c2_1A = *((volatile vector float *)(ptrC+2*M+4));
SPU_FMA(c0_0A,a00,b0_0A,c0_0A); c3_1A = *((volatile vector float *)(ptrC+3*M+4));
SPU_FMA(c1_0A,a10,b0_0A,c1_0A); a12 = spu_shuffle(a1, a1, pat2);
SPU_FMA(c2_0A,a20,b0_0A,c2_0A); b2_0A = *((volatile vector float *)(ptrB+6*M+OFFB*M));
SPU_FMA(c3_0A,a30,b0_0A,c3_0A); b2_1A = *((volatile vector float *)(ptrB+6*M+OFFB*M+4));
SPU_FMA(c0_1A,a00,b0_1A,c0_1A); a22 = spu_shuffle(a2, a2, pat2);
SPU_FMA(c1_1A,a10,b0_1A,c1_1A); b3_0A = *((volatile vector float *)(ptrB+7*M+OFFB*M));
SPU_FMA(c2_1A,a20,b0_1A,c2_1A); b3_1A = *((volatile vector float *)(ptrB+7*M+OFFB*M+4));
SPU_FMA(c3_1A,a30,b0_1A,c3_1A); a32 = spu_shuffle(a3, a3, pat2);
SPU_FMA(c0_0A,a01,b1_0A,c0_0A); *((volatile vector float *)(ptrC+56)) = c0_0B;
SPU_FMA(c1_0A,a11,b1_0A,c1_0A); *((volatile vector float *)(ptrC+M+56)) = c1_0B;
SPU_FMA(c2_0A,a21,b1_0A,c2_0A); a03 = spu_shuffle(a0, a0, pat3);
SPU_FMA(c3_0A,a31,b1_0A,c3_0A); *((volatile vector float *)(ptrC+2*M+56)) = c2_0B;
SPU_FMA(c0_1A,a01,b1_1A,c0_1A); *((volatile vector float *)(ptrC+3*M+56)) = c3_0B;
SPU_FMA(c1_1A,a11,b1_1A,c1_1A); a13 = spu_shuffle(a1, a1, pat3);
SPU_FMA(c2_1A,a21,b1_1A,c2_1A); *((volatile vector float *)(ptrC+60)) = c0_1B;
SPU_FMA(c3_1A,a31,b1_1A,c3_1A); *((volatile vector float *)(ptrC+M+60)) = c1_1B;
SPU_FMA(c0_0A,a02,b2_0A,c0_0A); a23 = spu_shuffle(a2, a2, pat3);
SPU_FMA(c1_0A,a12,b2_0A,c1_0A); *((volatile vector float *)(ptrC+2*M+60)) = c2_1B;
SPU_FMA(c2_0A,a22,b2_0A,c2_0A); *((volatile vector float *)(ptrC+3*M+60)) = c3_1B;
SPU_FMA(c3_0A,a32,b2_0A,c3_0A); a33 = spu_shuffle(a3, a3, pat3);
SPU_FMA(c0_1A,a02,b2_1A,c0_1A); b0_0B = *((volatile vector float *)(ptrB+4*M+OFFB*M+8 ));
SPU_FMA(c1_1A,a12,b2_1A,c1_1A); b0_1B = *((volatile vector float *)(ptrB+4*M+OFFB*M+12));
SPU_FMA(c2_1A,a22,b2_1A,c2_1A); b1_0B = *((volatile vector float *)(ptrB+5*M+OFFB*M+8 ));
SPU_FMA(c3_1A,a32,b2_1A,c3_1A); b1_1B = *((volatile vector float *)(ptrB+5*M+OFFB*M+12));
SPU_FMA(c0_0A,a03,b3_0A,c0_0A); c0_0B = *((volatile vector float *)(ptrC+8 ));
SPU_FMA(c1_0A,a13,b3_0A,c1_0A); c1_0B = *((volatile vector float *)(ptrC+M+8 ));
SPU_FMA(c2_0A,a23,b3_0A,c2_0A); c2_0B = *((volatile vector float *)(ptrC+2*M+8 ));
SPU_FMA(c3_0A,a33,b3_0A,c3_0A); c3_0B = *((volatile vector float *)(ptrC+3*M+8 ));
SPU_FMA(c0_1A,a03,b3_1A,c0_1A); c0_1B = *((volatile vector float *)(ptrC+12));
SPU_FMA(c1_1A,a13,b3_1A,c1_1A); c1_1B = *((volatile vector float *)(ptrC+M+12));
SPU_FMA(c2_1A,a23,b3_1A,c2_1A); c2_1B = *((volatile vector float *)(ptrC+2*M+12));
SPU_FMA(c3_1A,a33,b3_1A,c3_1A); c3_1B = *((volatile vector float *)(ptrC+3*M+12));
}

#define StageMISCmod(OFFA,OFFB)
{
SPU_FMA(c0_0B,a00,b0_0B,c0_0B); a0 = *((volatile vector float *)(ptrA+OFFA+4));
SPU_FMA(c1_0B,a10,b0_0B,c1_0B); a1 = *((volatile vector float *)(ptrA+M+OFFA+4));
SPU_FMA(c2_0B,a20,b0_0B,c2_0B); a2 = *((volatile vector float *)(ptrA+2*M+OFFA+4));
SPU_FMA(c3_0B,a30,b0_0B,c3_0B); a3 = *((volatile vector float *)(ptrA+3*M+OFFA+4));
SPU_FMA(c0_1B,a00,b0_1B,c0_1B); *((volatile vector float *)(ptrC+48 )) = c0_0A;
SPU_FMA(c1_1B,a10,b0_1B,c1_1B); *((volatile vector float *)(ptrC+M+48 )) = c1_0A;
SPU_FMA(c2_1B,a20,b0_1B,c2_1B); a00 = spu_shuffle(a0, a0, pat0);
SPU_FMA(c3_1B,a30,b0_1B,c3_1B); *((volatile vector float *)(ptrC+2*M+48 )) = c2_0A;
SPU_FMA(c0_0B,a01,b1_0B,c0_0B); *((volatile vector float *)(ptrC+3*M+48 )) = c3_0A;
SPU_FMA(c1_0B,a11,b1_0B,c1_0B); a10 = spu_shuffle(a1, a1, pat0);
SPU_FMA(c2_0B,a21,b1_0B,c2_0B); *((volatile vector float *)(ptrC+52)) = c0_1A;
SPU_FMA(c3_0B,a31,b1_0B,c3_0B); *((volatile vector float *)(ptrC+M+52)) = c1_1A;
SPU_FMA(c0_1B,a01,b1_1B,c0_1B); a20 = spu_shuffle(a2, a2, pat0);
SPU_FMA(c1_1B,a11,b1_1B,c1_1B); *((volatile vector float *)(ptrC+2*M+52)) = c2_1A;
SPU_FMA(c2_1B,a21,b1_1B,c2_1B); *((volatile vector float *)(ptrC+3*M+52)) = c3_1A;
SPU_FMA(c3_1B,a31,b1_1B,c3_1B); a30 = spu_shuffle(a3, a3, pat0);
SPU_FMA(c0_0B,a02,b2_0B,c0_0B); c0_0A = *((volatile vector float *)(ptrC));
SPU_FMA(c1_0B,a12,b2_0B,c1_0B); c1_0A = *((volatile vector float *)(ptrC+M));
SPU_FMA(c2_0B,a22,b2_0B,c2_0B); a01 = spu_shuffle(a0, a0, pat1);
SPU_FMA(c3_0B,a32,b2_0B,c3_0B); c2_0A = *((volatile vector float *)(ptrC+2*M));
SPU_FMA(c0_1B,a02,b2_1B,c0_1B); c3_0A = *((volatile vector float *)(ptrC+3*M));
SPU_FMA(c1_1B,a12,b2_1B,c1_1B); a11 = spu_shuffle(a1, a1, pat1);
SPU_FMA(c2_1B,a22,b2_1B,c2_1B); b0_0A = *((volatile vector float *)(ptrB+4*M+OFFB*M));
SPU_FMA(c3_1B,a32,b2_1B,c3_1B); b0_1A = *((volatile vector float *)(ptrB+4*M+OFFB*M+4));
SPU_FMA(c0_0B,a03,b3_0B,c0_0B); a21 = spu_shuffle(a2, a2, pat1);
SPU_FMA(c1_0B,a13,b3_0B,c1_0B); b1_0A = *((volatile vector float *)(ptrB+5*M+OFFB*M));
SPU_FMA(c2_0B,a23,b3_0B,c2_0B); b1_1A = *((volatile vector float *)(ptrB+5*M+OFFB*M+4));
SPU_FMA(c3_0B,a33,b3_0B,c3_0B); a31 = spu_shuffle(a3, a3, pat1);
SPU_FMA(c0_1B,a03,b3_1B,c0_1B); c0_1A = *((volatile vector float *)(ptrC+4));
SPU_FMA(c1_1B,a13,b3_1B,c1_1B); c1_1A = *((volatile vector float *)(ptrC+M+4));
SPU_FMA(c2_1B,a23,b3_1B,c2_1B); a02 = spu_shuffle(a0, a0, pat2);
SPU_FMA(c3_1B,a33,b3_1B,c3_1B); c2_1A = *((volatile vector float *)(ptrC+2*M+4));
SPU_FMA(c0_0A,a00,b0_0A,c0_0A); c3_1A = *((volatile vector float *)(ptrC+3*M+4));
SPU_FMA(c1_0A,a10,b0_0A,c1_0A); a12 = spu_shuffle(a1, a1, pat2);
SPU_FMA(c2_0A,a20,b0_0A,c2_0A); b2_0A = *((volatile vector float *)(ptrB+6*M+OFFB*M));
SPU_FMA(c3_0A,a30,b0_0A,c3_0A); b2_1A = *((volatile vector float *)(ptrB+6*M+OFFB*M+4));
SPU_FMA(c0_1A,a00,b0_1A,c0_1A); a22 = spu_shuffle(a2, a2, pat2);
SPU_FMA(c1_1A,a10,b0_1A,c1_1A); b3_0A = *((volatile vector float *)(ptrB+7*M+OFFB*M));
SPU_FMA(c2_1A,a20,b0_1A,c2_1A); b3_1A = *((volatile vector float *)(ptrB+7*M+OFFB*M+4));
SPU_FMA(c3_1A,a30,b0_1A,c3_1A); a32 = spu_shuffle(a3, a3, pat2);
SPU_FMA(c0_0A,a01,b1_0A,c0_0A); *((volatile vector float *)(ptrC+56)) = c0_0B;
SPU_FMA(c1_0A,a11,b1_0A,c1_0A); *((volatile vector float *)(ptrC+M+56)) = c1_0B;
SPU_FMA(c2_0A,a21,b1_0A,c2_0A); a03 = spu_shuffle(a0, a0, pat3);
SPU_FMA(c3_0A,a31,b1_0A,c3_0A); *((volatile vector float *)(ptrC+2*M+56)) = c2_0B;
SPU_FMA(c0_1A,a01,b1_1A,c0_1A); *((volatile vector float *)(ptrC+3*M+56)) = c3_0B;
SPU_FMA(c1_1A,a11,b1_1A,c1_1A); a13 = spu_shuffle(a1, a1, pat3);
SPU_FMA(c2_1A,a21,b1_1A,c2_1A); *((volatile vector float *)(ptrC+60)) = c0_1B;
SPU_FMA(c3_1A,a31,b1_1A,c3_1A); *((volatile vector float *)(ptrC+M+60)) = c1_1B;
SPU_FMA(c0_0A,a02,b2_0A,c0_0A); a23 = spu_shuffle(a2, a2, pat3);
SPU_FMA(c1_0A,a12,b2_0A,c1_0A); *((volatile vector float *)(ptrC+2*M+60)) = c2_1B;
SPU_FMA(c2_0A,a22,b2_0A,c2_0A); *((volatile vector float *)(ptrC+3*M+60)) = c3_1B;
SPU_FMA(c3_0A,a32,b2_0A,c3_0A); a33 = spu_shuffle(a3, a3, pat3);
SPU_FMA(c0_1A,a02,b2_1A,c0_1A); b0_0B = *((volatile vector float *)(ptrB+4*M+OFFB*M+8 ));
SPU_FMA(c1_1A,a12,b2_1A,c1_1A); b0_1B = *((volatile vector float *)(ptrB+4*M+OFFB*M+12));
SPU_FMA(c2_1A,a22,b2_1A,c2_1A); b1_0B = *((volatile vector float *)(ptrB+5*M+OFFB*M+8 ));
SPU_FMA(c3_1A,a32,b2_1A,c3_1A); b1_1B = *((volatile vector float *)(ptrB+5*M+OFFB*M+12));
SPU_FMA(c0_0A,a03,b3_0A,c0_0A); c0_0B = *((volatile vector float *)(ptrC+8 ));
SPU_FMA(c1_0A,a13,b3_0A,c1_0A); c1_0B = *((volatile vector float *)(ptrC+M+8 ));
SPU_FMA(c2_0A,a23,b3_0A,c2_0A); c2_0B = *((volatile vector float *)(ptrC+2*M+8 ));
SPU_FMA(c3_0A,a33,b3_0A,c3_0A); c3_0B = *((volatile vector float *)(ptrC+3*M+8 ));
SPU_FMA(c0_1A,a03,b3_1A,c0_1A); b2_0B = *((volatile vector float *)(ptrB+6*M+OFFB*M+8 ));
SPU_FMA(c1_1A,a13,b3_1A,c1_1A); b2_1B = *((volatile vector float *)(ptrB+6*M+OFFB*M+12));
SPU_FMA(c2_1A,a23,b3_1A,c2_1A); b3_0B = *((volatile vector float *)(ptrB+7*M+OFFB*M+8 ));
SPU_FMA(c3_1A,a33,b3_1A,c3_1A); b3_1B = *((volatile vector float *)(ptrB+7*M+OFFB*M+12));
ALIGN8B;
c0_1B = *((volatile vector float *)(ptrC+12));
c1_1B = *((volatile vector float *)(ptrC+M+12));
c2_1B = *((volatile vector float *)(ptrC+2*M+12));
c3_1B = *((volatile vector float *)(ptrC+3*M+12));
ptrB += OFFB*M;
ALIGN8B;
}

#define StageMISCclr()
{
SPU_FM(c0_0B,a00,b0_0B); a0 = *((volatile vector float *)(ptrA+4));
SPU_FM(c1_0B,a10,b0_0B); a1 = *((volatile vector float *)(ptrA+M+4));
SPU_FM(c2_0B,a20,b0_0B); a2 = *((volatile vector float *)(ptrA+2*M+4));
SPU_FM(c3_0B,a30,b0_0B); a3 = *((volatile vector float *)(ptrA+3*M+4));
SPU_FM(c0_1B,a00,b0_1B); *((volatile vector float *)(ptrC+48 )) = c0_0A;
SPU_FM(c1_1B,a10,b0_1B); *((volatile vector float *)(ptrC+M+48 )) = c1_0A;
SPU_FM(c2_1B,a20,b0_1B); a00 = spu_shuffle(a0, a0, pat0);
SPU_FM(c3_1B,a30,b0_1B); *((volatile vector float *)(ptrC+2*M+48 )) = c2_0A;
SPU_FMA(c0_0B,a01,b1_0B,c0_0B); *((volatile vector float *)(ptrC+3*M+48 )) = c3_0A;
SPU_FMA(c1_0B,a11,b1_0B,c1_0B); a10 = spu_shuffle(a1, a1, pat0);
SPU_FMA(c2_0B,a21,b1_0B,c2_0B); *((volatile vector float *)(ptrC+52)) = c0_1A;
SPU_FMA(c3_0B,a31,b1_0B,c3_0B); *((volatile vector float *)(ptrC+M+52)) = c1_1A;
SPU_FMA(c0_1B,a01,b1_1B,c0_1B); a20 = spu_shuffle(a2, a2, pat0);
SPU_FMA(c1_1B,a11,b1_1B,c1_1B); *((volatile vector float *)(ptrC+2*M+52)) = c2_1A;
SPU_FMA(c2_1B,a21,b1_1B,c2_1B); *((volatile vector float *)(ptrC+3*M+52)) = c3_1A;
SPU_FMA(c3_1B,a31,b1_1B,c3_1B); a30 = spu_shuffle(a3, a3, pat0);
SPU_FMA(c0_0B,a02,b2_0B,c0_0B); c0_0A = *((volatile vector float *)(ptrC));
SPU_FMA(c1_0B,a12,b2_0B,c1_0B); c1_0A = *((volatile vector float *)(ptrC+M));
SPU_FMA(c2_0B,a22,b2_0B,c2_0B); a01 = spu_shuffle(a0, a0, pat1);
SPU_FMA(c3_0B,a32,b2_0B,c3_0B); c2_0A = *((volatile vector float *)(ptrC+2*M));
SPU_FMA(c0_1B,a02,b2_1B,c0_1B); c3_0A = *((volatile vector float *)(ptrC+3*M));
SPU_FMA(c1_1B,a12,b2_1B,c1_1B); a11 = spu_shuffle(a1, a1, pat1);
SPU_FMA(c2_1B,a22,b2_1B,c2_1B); b0_0A = *((volatile vector float *)(ptrB+4*M));
SPU_FMA(c3_1B,a32,b2_1B,c3_1B); b0_1A = *((volatile vector float *)(ptrB+4*M+4));
SPU_FMA(c0_0B,a03,b3_0B,c0_0B); a21 = spu_shuffle(a2, a2, pat1);
SPU_FMA(c1_0B,a13,b3_0B,c1_0B); b1_0A = *((volatile vector float *)(ptrB+5*M));
SPU_FMA(c2_0B,a23,b3_0B,c2_0B); b1_1A = *((volatile vector float *)(ptrB+5*M+4));
SPU_FMA(c3_0B,a33,b3_0B,c3_0B); a31 = spu_shuffle(a3, a3, pat1);
SPU_FMA(c0_1B,a03,b3_1B,c0_1B); c0_1A = *((volatile vector float *)(ptrC+4));
SPU_FMA(c1_1B,a13,b3_1B,c1_1B); c1_1A = *((volatile vector float *)(ptrC+M+4));
SPU_FMA(c2_1B,a23,b3_1B,c2_1B); a02 = spu_shuffle(a0, a0, pat2);
SPU_FMA(c3_1B,a33,b3_1B,c3_1B); c2_1A = *((volatile vector float *)(ptrC+2*M+4));
SPU_FMA(c0_0A,a00,b0_0A,c0_0A); c3_1A = *((volatile vector float *)(ptrC+3*M+4));
SPU_FMA(c1_0A,a10,b0_0A,c1_0A); a12 = spu_shuffle(a1, a1, pat2);
SPU_FMA(c2_0A,a20,b0_0A,c2_0A); b2_0A = *((volatile vector float *)(ptrB+6*M));
SPU_FMA(c3_0A,a30,b0_0A,c3_0A); b2_1A = *((volatile vector float *)(ptrB+6*M+4));
SPU_FMA(c0_1A,a00,b0_1A,c0_1A); a22 = spu_shuffle(a2, a2, pat2);
SPU_FMA(c1_1A,a10,b0_1A,c1_1A); b3_0A = *((volatile vector float *)(ptrB+7*M));
SPU_FMA(c2_1A,a20,b0_1A,c2_1A); b3_1A = *((volatile vector float *)(ptrB+7*M+4));
SPU_FMA(c3_1A,a30,b0_1A,c3_1A); a32 = spu_shuffle(a3, a3, pat2);
SPU_FMA(c0_0A,a01,b1_0A,c0_0A); *((volatile vector float *)(ptrC+56)) = c0_0B;
SPU_FMA(c1_0A,a11,b1_0A,c1_0A); *((volatile vector float *)(ptrC+M+56)) = c1_0B;
SPU_FMA(c2_0A,a21,b1_0A,c2_0A); a03 = spu_shuffle(a0, a0, pat3);
SPU_FMA(c3_0A,a31,b1_0A,c3_0A); *((volatile vector float *)(ptrC+2*M+56)) = c2_0B;
SPU_FMA(c0_1A,a01,b1_1A,c0_1A); *((volatile vector float *)(ptrC+3*M+56)) = c3_0B;
SPU_FMA(c1_1A,a11,b1_1A,c1_1A); a13 = spu_shuffle(a1, a1, pat3);
SPU_FMA(c2_1A,a21,b1_1A,c2_1A); *((volatile vector float *)(ptrC+60)) = c0_1B;
SPU_FMA(c3_1A,a31,b1_1A,c3_1A); *((volatile vector float *)(ptrC+M+60)) = c1_1B;
SPU_FMA(c0_0A,a02,b2_0A,c0_0A); a23 = spu_shuffle(a2, a2, pat3);
SPU_FMA(c1_0A,a12,b2_0A,c1_0A); *((volatile vector float *)(ptrC+2*M+60)) = c2_1B;
SPU_FMA(c2_0A,a22,b2_0A,c2_0A); *((volatile vector float *)(ptrC+3*M+60)) = c3_1B;
SPU_FMA(c3_0A,a32,b2_0A,c3_0A); a33 = spu_shuffle(a3, a3, pat3);
SPU_FMA(c0_1A,a02,b2_1A,c0_1A); b0_0B = *((volatile vector float *)(ptrB+4*M+8 ));
SPU_FMA(c1_1A,a12,b2_1A,c1_1A); b0_1B = *((volatile vector float *)(ptrB+4*M+12));
SPU_FMA(c2_1A,a22,b2_1A,c2_1A); b1_0B = *((volatile vector float *)(ptrB+5*M+8 ));
SPU_FMA(c3_1A,a32,b2_1A,c3_1A); b1_1B = *((volatile vector float *)(ptrB+5*M+12));
SPU_FMA(c0_0A,a03,b3_0A,c0_0A); c0_0B = *((volatile vector float *)(ptrC+8 ));
SPU_FMA(c1_0A,a13,b3_0A,c1_0A); c1_0B = *((volatile vector float *)(ptrC+M+8 ));
SPU_FMA(c2_0A,a23,b3_0A,c2_0A); c2_0B = *((volatile vector float *)(ptrC+2*M+8 ));
SPU_FMA(c3_0A,a33,b3_0A,c3_0A); c3_0B = *((volatile vector float *)(ptrC+3*M+8 ));
SPU_FMA(c0_1A,a03,b3_1A,c0_1A); b2_0B = *((volatile vector float *)(ptrB+6*M+8 ));
SPU_FMA(c1_1A,a13,b3_1A,c1_1A); b2_1B = *((volatile vector float *)(ptrB+6*M+12));
SPU_FMA(c2_1A,a23,b3_1A,c2_1A); b3_0B = *((volatile vector float *)(ptrB+7*M+8 ));
SPU_FMA(c3_1A,a33,b3_1A,c3_1A); b3_1B = *((volatile vector float *)(ptrB+7*M+12));
ALIGN8B;
c0_1B = *((volatile vector float *)(ptrC+12));
c1_1B = *((volatile vector float *)(ptrC+M+12));
c2_1B = *((volatile vector float *)(ptrC+2*M+12));
c3_1B = *((volatile vector float *)(ptrC+3*M+12));
}

#define Loads4RegSetA(OFFSET)
{
c0_0A = *((volatile vector float *)(ptrC+OFFSET));
c1_0A = *((volatile vector float *)(ptrC+M+OFFSET));
c2_0A = *((volatile vector float *)(ptrC+2*M+OFFSET));
c3_0A = *((volatile vector float *)(ptrC+3*M+OFFSET));
c0_1A = *((volatile vector float *)(ptrC+OFFSET+4));
c1_1A = *((volatile vector float *)(ptrC+M+OFFSET+4));
c2_1A = *((volatile vector float *)(ptrC+2*M+OFFSET+4));
c3_1A = *((volatile vector float *)(ptrC+3*M+OFFSET+4));
b0_0A = *((volatile vector float *)(ptrB+OFFSET));
b1_0A = *((volatile vector float *)(ptrB+M+OFFSET));
b2_0A = *((volatile vector float *)(ptrB+2*M+OFFSET));
b3_0A = *((volatile vector float *)(ptrB+3*M+OFFSET));
b0_1A = *((volatile vector float *)(ptrB+OFFSET+4));
b1_1A = *((volatile vector float *)(ptrB+M+OFFSET+4));
b2_1A = *((volatile vector float *)(ptrB+2*M+OFFSET+4));
b3_1A = *((volatile vector float *)(ptrB+3*M+OFFSET+4));
}

#define Loads4RegSetAClr(OFFSET)
{
b0_0A = *((volatile vector float *)(ptrB+OFFSET));
b1_0A = *((volatile vector float *)(ptrB+M+OFFSET));
b2_0A = *((volatile vector float *)(ptrB+2*M+OFFSET));
b3_0A = *((volatile vector float *)(ptrB+3*M+OFFSET));
b0_1A = *((volatile vector float *)(ptrB+OFFSET+4));
b1_1A = *((volatile vector float *)(ptrB+M+OFFSET+4));
b2_1A = *((volatile vector float *)(ptrB+2*M+OFFSET+4));
b3_1A = *((volatile vector float *)(ptrB+3*M+OFFSET+4));
}

#define Ops4RegSetAClr()
{
c0_0A = spu_mul( a00, b0_0A);
c1_0A = spu_mul( a10, b0_0A);
c2_0A = spu_mul( a20, b0_0A);
c3_0A = spu_mul( a30, b0_0A);
c0_1A = spu_mul( a00, b0_1A);
c1_1A = spu_mul( a10, b0_1A);
c2_1A = spu_mul( a20, b0_1A);
c3_1A = spu_mul( a30, b0_1A);
c0_0A = spu_madd(a01, b1_0A, c0_0A);
c1_0A = spu_madd(a11, b1_0A, c1_0A);
c2_0A = spu_madd(a21, b1_0A, c2_0A);
c3_0A = spu_madd(a31, b1_0A, c3_0A);
c0_1A = spu_madd(a01, b1_1A, c0_1A);
c1_1A = spu_madd(a11, b1_1A, c1_1A);
c2_1A = spu_madd(a21, b1_1A, c2_1A);
c3_1A = spu_madd(a31, b1_1A, c3_1A);
c0_0A = spu_madd(a02, b2_0A, c0_0A);
c1_0A = spu_madd(a12, b2_0A, c1_0A);
c2_0A = spu_madd(a22, b2_0A, c2_0A);
c3_0A = spu_madd(a32, b2_0A, c3_0A);
c0_1A = spu_madd(a02, b2_1A, c0_1A);
c1_1A = spu_madd(a12, b2_1A, c1_1A);
c2_1A = spu_madd(a22, b2_1A, c2_1A);
c3_1A = spu_madd(a32, b2_1A, c3_1A);
c0_0A = spu_madd(a03, b3_0A, c0_0A);
c1_0A = spu_madd(a13, b3_0A, c1_0A);
c2_0A = spu_madd(a23, b3_0A, c2_0A);
c3_0A = spu_madd(a33, b3_0A, c3_0A);
c0_1A = spu_madd(a03, b3_1A, c0_1A);
c1_1A = spu_madd(a13, b3_1A, c1_1A);
c2_1A = spu_madd(a23, b3_1A, c2_1A);
c3_1A = spu_madd(a33, b3_1A, c3_1A);
}

#define Ops4RegSetA()
{
c0_0A = spu_madd(a00, b0_0A, c0_0A);
c1_0A = spu_madd(a10, b0_0A, c1_0A);
c2_0A = spu_madd(a20, b0_0A, c2_0A);
c3_0A = spu_madd(a30, b0_0A, c3_0A);
c0_1A = spu_madd(a00, b0_1A, c0_1A);
c1_1A = spu_madd(a10, b0_1A, c1_1A);
c2_1A = spu_madd(a20, b0_1A, c2_1A);
c3_1A = spu_madd(a30, b0_1A, c3_1A);
c0_0A = spu_madd(a01, b1_0A, c0_0A);
c1_0A = spu_madd(a11, b1_0A, c1_0A);
c2_0A = spu_madd(a21, b1_0A, c2_0A);
c3_0A = spu_madd(a31, b1_0A, c3_0A);
c0_1A = spu_madd(a01, b1_1A, c0_1A);
c1_1A = spu_madd(a11, b1_1A, c1_1A);
c2_1A = spu_madd(a21, b1_1A, c2_1A);
c3_1A = spu_madd(a31, b1_1A, c3_1A);
c0_0A = spu_madd(a02, b2_0A, c0_0A);
c1_0A = spu_madd(a12, b2_0A, c1_0A);
c2_0A = spu_madd(a22, b2_0A, c2_0A);
c3_0A = spu_madd(a32, b2_0A, c3_0A);
c0_1A = spu_madd(a02, b2_1A, c0_1A);
c1_1A = spu_madd(a12, b2_1A, c1_1A);
c2_1A = spu_madd(a22, b2_1A, c2_1A);
c3_1A = spu_madd(a32, b2_1A, c3_1A);
c0_0A = spu_madd(a03, b3_0A, c0_0A);
c1_0A = spu_madd(a13, b3_0A, c1_0A);
c2_0A = spu_madd(a23, b3_0A, c2_0A);
c3_0A = spu_madd(a33, b3_0A, c3_0A);
c0_1A = spu_madd(a03, b3_1A, c0_1A);
c1_1A = spu_madd(a13, b3_1A, c1_1A);
c2_1A = spu_madd(a23, b3_1A, c2_1A);
c3_1A = spu_madd(a33, b3_1A, c3_1A);
}

#define Stores4RegSetA(OFFSET)
{
*((volatile vector float *)(ptrC+OFFSET)) = c0_0A;
*((volatile vector float *)(ptrC+M+OFFSET)) = c1_0A;
*((volatile vector float *)(ptrC+2*M+OFFSET)) = c2_0A;
*((volatile vector float *)(ptrC+3*M+OFFSET)) = c3_0A;
*((volatile vector float *)(ptrC+OFFSET+4)) = c0_1A;
*((volatile vector float *)(ptrC+M+OFFSET+4)) = c1_1A;
*((volatile vector float *)(ptrC+2*M+OFFSET+4)) = c2_1A;
*((volatile vector float *)(ptrC+3*M+OFFSET+4)) = c3_1A;
}

#define Loads4RegSetB(OFFSET)
{
c0_0B = *((volatile vector float *)(ptrC+OFFSET));
c1_0B = *((volatile vector float *)(ptrC+M+OFFSET));
c2_0B = *((volatile vector float *)(ptrC+2*M+OFFSET));
c3_0B = *((volatile vector float *)(ptrC+3*M+OFFSET));
c0_1B = *((volatile vector float *)(ptrC+OFFSET+4));
c1_1B = *((volatile vector float *)(ptrC+M+OFFSET+4));
c2_1B = *((volatile vector float *)(ptrC+2*M+OFFSET+4));
c3_1B = *((volatile vector float *)(ptrC+3*M+OFFSET+4));
b0_0B = *((volatile vector float *)(ptrB+OFFSET));
b1_0B = *((volatile vector float *)(ptrB+M+OFFSET));
b2_0B = *((volatile vector float *)(ptrB+2*M+OFFSET));
b3_0B = *((volatile vector float *)(ptrB+3*M+OFFSET));
b0_1B = *((volatile vector float *)(ptrB+OFFSET+4));
b1_1B = *((volatile vector float *)(ptrB+M+OFFSET+4));
b2_1B = *((volatile vector float *)(ptrB+2*M+OFFSET+4));
b3_1B = *((volatile vector float *)(ptrB+3*M+OFFSET+4));
}

#define Loads4RegSetBClr(OFFSET)
{
b0_0B = *((volatile vector float *)(ptrB+OFFSET));
b1_0B = *((volatile vector float *)(ptrB+M+OFFSET));
b2_0B = *((volatile vector float *)(ptrB+2*M+OFFSET));
b3_0B = *((volatile vector float *)(ptrB+3*M+OFFSET));
b0_1B = *((volatile vector float *)(ptrB+OFFSET+4));
b1_1B = *((volatile vector float *)(ptrB+M+OFFSET+4));
b2_1B = *((volatile vector float *)(ptrB+2*M+OFFSET+4));
b3_1B = *((volatile vector float *)(ptrB+3*M+OFFSET+4));
}

#define Ops4RegSetB()
{
c0_0B = spu_madd(a00, b0_0B, c0_0B);
c1_0B = spu_madd(a10, b0_0B, c1_0B);
c2_0B = spu_madd(a20, b0_0B, c2_0B);
c3_0B = spu_madd(a30, b0_0B, c3_0B);
c0_1B = spu_madd(a00, b0_1B, c0_1B);
c1_1B = spu_madd(a10, b0_1B, c1_1B);
c2_1B = spu_madd(a20, b0_1B, c2_1B);
c3_1B = spu_madd(a30, b0_1B, c3_1B);
c0_0B = spu_madd(a01, b1_0B, c0_0B);
c1_0B = spu_madd(a11, b1_0B, c1_0B);
c2_0B = spu_madd(a21, b1_0B, c2_0B);
c3_0B = spu_madd(a31, b1_0B, c3_0B);
c0_1B = spu_madd(a01, b1_1B, c0_1B);
c1_1B = spu_madd(a11, b1_1B, c1_1B);
c2_1B = spu_madd(a21, b1_1B, c2_1B);
c3_1B = spu_madd(a31, b1_1B, c3_1B);
c0_0B = spu_madd(a02, b2_0B, c0_0B); SPU_LNOP;
c1_0B = spu_madd(a12, b2_0B, c1_0B);
c2_0B = spu_madd(a22, b2_0B, c2_0B);
c3_0B = spu_madd(a32, b2_0B, c3_0B);
c0_1B = spu_madd(a02, b2_1B, c0_1B);
c1_1B = spu_madd(a12, b2_1B, c1_1B);
c2_1B = spu_madd(a22, b2_1B, c2_1B);
c3_1B = spu_madd(a32, b2_1B, c3_1B);
c0_0B = spu_madd(a03, b3_0B, c0_0B);
c1_0B = spu_madd(a13, b3_0B, c1_0B);
c2_0B = spu_madd(a23, b3_0B, c2_0B);
c3_0B = spu_madd(a33, b3_0B, c3_0B);
c0_1B = spu_madd(a03, b3_1B, c0_1B);
c1_1B = spu_madd(a13, b3_1B, c1_1B);
c2_1B = spu_madd(a23, b3_1B, c2_1B);
c3_1B = spu_madd(a33, b3_1B, c3_1B);
}

#define Stores4RegSetB(OFFSET)
{
*((volatile vector float *)(ptrC+OFFSET)) = c0_0B;
*((volatile vector float *)(ptrC+M+OFFSET)) = c1_0B;
*((volatile vector float *)(ptrC+2*M+OFFSET)) = c2_0B;
*((volatile vector float *)(ptrC+3*M+OFFSET)) = c3_0B;
*((volatile vector float *)(ptrC+OFFSET+4)) = c0_1B;
*((volatile vector float *)(ptrC+M+OFFSET+4)) = c1_1B;
*((volatile vector float *)(ptrC+2*M+OFFSET+4)) = c2_1B;
*((volatile vector float *)(ptrC+3*M+OFFSET+4)) = c3_1B;
}

float blkA0[M*M] __attribute__((aligned(128 )));
float blkB0[M*M] __attribute__((aligned(128 )));
float blkC0[M*M] __attribute__((aligned(128 )));
float blkA1[M*M] __attribute__((aligned(128 )));
float blkB1[M*M] __attribute__((aligned(128 )));
float blkC1[M*M] __attribute__((aligned(128 )));

// For synchronnization
char lsbuf[128] __attribute__((aligned(128 )));


static void Block_Fetch(volatile float *blkA, volatile float *blkB,
unsigned int by, unsigned int bx, unsigned int idx, unsigned int rtag)
{
unsigned int baseA, baseB;

baseA = A_AREA + 4*(by*M*N+idx*M*M);
baseB = B_AREA + 4*(bx*M*M+idx*M*N);

mfc_get(blkA, baseA, sizeof(float)*M*M, rtag, 0, 0);
mfc_get(blkB, baseB, sizeof(float)*M*M, rtag, 0, 0);
}




static void MatInit_MxM(volatile float *blkC, volatile float *blkA, volatile float *blkB)
{
unsigned int i;
volatile float *ptrA, *ptrB, *ptrC;

vector float a0, a1, a2, a3;

vector float a00, a01, a02, a03;
vector float a10, a11, a12, a13;
vector float a20, a21, a22, a23;
vector float a30, a31, a32, a33;

vector float b0_0A, b1_0A, b2_0A, b3_0A;
vector float c0_0A, c1_0A, c2_0A, c3_0A;
vector float b0_1A, b1_1A, b2_1A, b3_1A;
vector float c0_1A, c1_1A, c2_1A, c3_1A;

vector float b0_0B, b1_0B, b2_0B, b3_0B;
vector float c0_0B, c1_0B, c2_0B, c3_0B;
vector float b0_1B, b1_1B, b2_1B, b3_1B;
vector float c0_1B, c1_1B, c2_1B, c3_1B;

vector float b0_0C, b1_0C, b2_0C, b3_0C;
vector float c0_0C, c1_0C, c2_0C, c3_0C;
vector float b0_1C, b1_1C, b2_1C, b3_1C;
vector float c0_1C, c1_1C, c2_1C, c3_1C;

const vector unsigned char pat0 = VEC_LITERAL(vector unsigned char,
0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03,
0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03);

const vector unsigned char pat1 = VEC_LITERAL(vector unsigned char,
0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07,
0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07);

const vector unsigned char pat2 = VEC_LITERAL(vector unsigned char,
0x08, 0x09, 0x0a, 0x0b, 0x08, 0x09, 0x0a, 0x0b,
0x08, 0x09, 0x0a, 0x0b, 0x08, 0x09, 0x0a, 0x0b);

const vector unsigned char pat3 = VEC_LITERAL(vector unsigned char,
0x0c, 0x0d, 0x0e, 0x0f, 0x0c, 0x0d, 0x0e, 0x0f,
0x0c, 0x0d, 0x0e, 0x0f, 0x0c, 0x0d, 0x0e, 0x0f);

for(i=0; i ptrA = &blkA[i*M];
ptrB = &blkB[0];
ptrC = &blkC[i*M];
a0 = *((volatile vector float *)(ptrA));
a1 = *((volatile vector float *)(ptrA+M));
a2 = *((volatile vector float *)(ptrA+2*M));
a3 = *((volatile vector float *)(ptrA+3*M));
a00 = spu_shuffle(a0, a0, pat0);
a01 = spu_shuffle(a0, a0, pat1);
a02 = spu_shuffle(a0, a0, pat2);
a03 = spu_shuffle(a0, a0, pat3);
a10 = spu_shuffle(a1, a1, pat0);
a11 = spu_shuffle(a1, a1, pat1);
a12 = spu_shuffle(a1, a1, pat2);
a13 = spu_shuffle(a1, a1, pat3);
a20 = spu_shuffle(a2, a2, pat0);
a21 = spu_shuffle(a2, a2, pat1);
a22 = spu_shuffle(a2, a2, pat2);
a23 = spu_shuffle(a2, a2, pat3);
a30 = spu_shuffle(a3, a3, pat0);
a31 = spu_shuffle(a3, a3, pat1);
a32 = spu_shuffle(a3, a3, pat2);
a33 = spu_shuffle(a3, a3, pat3);
Loads4RegSetAClr(0);
Ops4RegSetAClr();
Loads4RegSetBClr(8 );
StageCBAclr(0);
StageACBclr(8 );
StageBACclr(16);
StageCBAclr(24);
StageACBclr(32);
StageBACclr(40);
StageMISCclr();
StageCBA(0,4);
StageACB(8,4);
StageBAC(16,4);
StageCBA(24,4);
StageACB(32,4);
StageBAC(40,4);
StageMISC(4,4);
StageCBAmod(0,8 );
StageACB(8,8 );
StageBAC(16,8 );
StageCBA(24,8 );
StageACB(32,8 );
StageBAC(40,8 );
StageMISC(8,8 );
StageCBAmod(0,12);
StageACB(8,12);
StageBAC(16,12);
StageCBA(24,12);
StageACB(32,12);
StageBAC(40,12);
StageMISC(12,12);
StageCBAmod(0,16);
StageACB(8,16);
StageBAC(16,16);
StageCBA(24,16);
StageACB(32,16);
StageBAC(40,16);
StageMISC(16,16);
StageCBAmod(0,20);
StageACB(8,20);
StageBAC(16,20);
StageCBA(24,20);
StageACB(32,20);
StageBAC(40,20);
StageMISC(20,20);
StageCBAmod(0,24);
StageACB(8,24);
StageBAC(16,24);
StageCBA(24,24);
StageACB(32,24);
StageBAC(40,24);
StageMISCmod(24,24);
StageCBA(0,4);
StageACB(8,4);
StageBAC(16,4);
StageCBA(24,4);
StageACB(32,4);
StageBAC(40,4);
StageMISC(28,4);
StageCBAmod(0,8 );
StageACB(8,8 );
StageBAC(16,8 );
StageCBA(24,8 );
StageACB(32,8 );
StageBAC(40,8 );
StageMISC(32,8 );
StageCBAmod(0,12);
StageACB(8,12);
StageBAC(16,12);
StageCBA(24,12);
StageACB(32,12);
StageBAC(40,12);
StageMISC(36,12);
StageCBAmod(0,16);
StageACB(8,16);
StageBAC(16,16);
StageCBA(24,16);
StageACB(32,16);
StageBAC(40,16);
StageMISC(40,16);
StageCBAmod(0,20);
StageACB(8,20);
StageBAC(16,20);
StageCBA(24,20);
StageACB(32,20);
StageBAC(40,20);
StageMISC(44,20);
StageCBAmod(0,24);
StageACB(8,24);
StageBAC(16,24);
StageCBA(24,24);
StageACB(32,24);
StageBAC(40,24);
StageMISCmod(48,24);
StageCBA(0,4);
StageACB(8,4);
StageBAC(16,4);
StageCBA(24,4);
StageACB(32,4);
StageBAC(40,4);
StageMISC(52,4);
StageCBAmod(0,8 );
StageACB(8,8 );
StageBAC(16,8 );
StageCBA(24,8 );
StageACB(32,8 );
StageBAC(40,8 );
StageMISC(56,8 );
StageCBAmod(0,12);
StageACB(8,12);
StageBAC(16,12);
StageCBA(24,12);
StageACB(32,12);
StageBAC(40,12);
Ops4RegSetB();
Stores4RegSetA(48 );
Stores4RegSetB(56);
}
}

static void MatMult_MxM(volatile float *blkC, volatile float *blkA, volatile float *blkB)
{
unsigned int i;
volatile float *ptrA, *ptrB, *ptrC;

vector float a0, a1, a2, a3;

vector float a00, a01, a02, a03;
vector float a10, a11, a12, a13;
vector float a20, a21, a22, a23;
vector float a30, a31, a32, a33;

vector float b0_0A, b1_0A, b2_0A, b3_0A;
vector float c0_0A, c1_0A, c2_0A, c3_0A;
vector float b0_1A, b1_1A, b2_1A, b3_1A;
vector float c0_1A, c1_1A, c2_1A, c3_1A;

vector float b0_0B, b1_0B, b2_0B, b3_0B;
vector float c0_0B, c1_0B, c2_0B, c3_0B;
vector float b0_1B, b1_1B, b2_1B, b3_1B;
vector float c0_1B, c1_1B, c2_1B, c3_1B;

vector float b0_0C, b1_0C, b2_0C, b3_0C;
vector float c0_0C, c1_0C, c2_0C, c3_0C;
vector float b0_1C, b1_1C, b2_1C, b3_1C;
vector float c0_1C, c1_1C, c2_1C, c3_1C;

const vector unsigned char pat0 = VEC_LITERAL(vector unsigned char,
0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03,
0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03);

const vector unsigned char pat1 = VEC_LITERAL(vector unsigned char,
0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07,
0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07);

const vector unsigned char pat2 = VEC_LITERAL(vector unsigned char,
0x08, 0x09, 0x0a, 0x0b, 0x08, 0x09, 0x0a, 0x0b,
0x08, 0x09, 0x0a, 0x0b, 0x08, 0x09, 0x0a, 0x0b);

const vector unsigned char pat3 = VEC_LITERAL(vector unsigned char,
0x0c, 0x0d, 0x0e, 0x0f, 0x0c, 0x0d, 0x0e, 0x0f,
0x0c, 0x0d, 0x0e, 0x0f, 0x0c, 0x0d, 0x0e, 0x0f);

for(i=0; i ptrA = &blkA[i*M];
ptrB = &blkB[0];
ptrC = &blkC[i*M];
a0 = *((volatile vector float *)(ptrA));
a1 = *((volatile vector float *)(ptrA+M));
a2 = *((volatile vector float *)(ptrA+2*M));
a3 = *((volatile vector float *)(ptrA+3*M));
a00 = spu_shuffle(a0, a0, pat0);
a01 = spu_shuffle(a0, a0, pat1);
a02 = spu_shuffle(a0, a0, pat2);
a03 = spu_shuffle(a0, a0, pat3);
a10 = spu_shuffle(a1, a1, pat0);
a11 = spu_shuffle(a1, a1, pat1);
a12 = spu_shuffle(a1, a1, pat2);
a13 = spu_shuffle(a1, a1, pat3);
a20 = spu_shuffle(a2, a2, pat0);
a21 = spu_shuffle(a2, a2, pat1);
a22 = spu_shuffle(a2, a2, pat2);
a23 = spu_shuffle(a2, a2, pat3);
a30 = spu_shuffle(a3, a3, pat0);
a31 = spu_shuffle(a3, a3, pat1);
a32 = spu_shuffle(a3, a3, pat2);
a33 = spu_shuffle(a3, a3, pat3);
Loads4RegSetA(0);
Ops4RegSetA();
Loads4RegSetB(8 );
StageCBA(0,0);
StageACB(8,0);
StageBAC(16,0);
StageCBA(24,0);
StageACB(32,0);
StageBAC(40,0);
StageMISC(0,0);
StageCBAmod(0,4);
StageACB(8,4);
StageBAC(16,4);
StageCBA(24,4);
StageACB(32,4);
StageBAC(40,4);
StageMISC(4,4);
StageCBAmod(0,8 );
StageACB(8,8 );
StageBAC(16,8 );
StageCBA(24,8 );
StageACB(32,8 );
StageBAC(40,8 );
StageMISC(8,8 );
StageCBAmod(0,12);
StageACB(8,12);
StageBAC(16,12);
StageCBA(24,12);
StageACB(32,12);
StageBAC(40,12);
StageMISC(12,12);
StageCBAmod(0,16);
StageACB(8,16);
StageBAC(16,16);
StageCBA(24,16);
StageACB(32,16);
StageBAC(40,16);
StageMISC(16,16);
StageCBAmod(0,20);
StageACB(8,20);
StageBAC(16,20);
StageCBA(24,20);
StageACB(32,20);
StageBAC(40,20);
StageMISC(20,20);
StageCBAmod(0,24);
StageACB(8,24);
StageBAC(16,24);
StageCBA(24,24);
StageACB(32,24);
StageBAC(40,24);
StageMISCmod(24,24);
StageCBA(0,4);
StageACB(8,4);
StageBAC(16,4);
StageCBA(24,4);
StageACB(32,4);
StageBAC(40,4);
StageMISC(28,4);
StageCBAmod(0,8 );
StageACB(8,8 );
StageBAC(16,8 );
StageCBA(24,8 );
StageACB(32,8 );
StageBAC(40,8 );
StageMISC(32,8 );
StageCBAmod(0,12);
StageACB(8,12);
StageBAC(16,12);
StageCBA(24,12);
StageACB(32,12);
StageBAC(40,12);
StageMISC(36,12);
StageCBAmod(0,16);
StageACB(8,16);
StageBAC(16,16);
StageCBA(24,16);
StageACB(32,16);
StageBAC(40,16);
StageMISC(40,16);
StageCBAmod(0,20);
StageACB(8,20);
StageBAC(16,20);
StageCBA(24,20);
StageACB(32,20);
StageBAC(40,20);
StageMISC(44,20);
StageCBAmod(0,24);
StageACB(8,24);
StageBAC(16,24);
StageCBA(24,24);
StageACB(32,24);
StageBAC(40,24);
StageMISCmod(48,24);
StageCBA(0,4);
StageACB(8,4);
StageBAC(16,4);
StageCBA(24,4);
StageACB(32,4);
StageBAC(40,4);
StageMISC(52,4);
StageCBAmod(0,8 );
StageACB(8,8 );
StageBAC(16,8 );
StageCBA(24,8 );
StageACB(32,8 );
StageBAC(40,8 );
StageMISC(56,8 );
StageCBAmod(0,12);
StageACB(8,12);
StageBAC(16,12);
StageCBA(24,12);
StageACB(32,12);
StageBAC(40,12);
Ops4RegSetB();
Stores4RegSetA(48 );
Stores4RegSetB(56);
}
}


static void Block_Store(volatile float *blkC, int by, int bx, int wtag)
{
unsigned int baseC;

baseC = C_AREA + 4*(by*M*N+bx*M*M);

mfc_put(blkC, baseC, sizeof(float)*M*M, wtag, 0, 0);
}


int main()
{
unsigned int i, j, k;
unsigned int i_next, j_next;

volatile float *InA, *InB;
volatile float *OpA, *OpB, *OpC;
volatile float *OutC;

unsigned int InTag = DIN_TAG;
unsigned int OutTag = DOUT_TAG;

unsigned int blkid = 0;
unsigned int shift, mask;
unsigned int blocks, tiles;

// Double Buffer Initialization
InA = blkA0;
InB = blkB0;
OpA = blkA0;
OpB = blkB0;
OpC = blkC0;
OutC = blkC0;

// Fetch working parameters from mailbox. The input
// parameters include:
// N = the size of the matrix
// ITER = number of times to perform matrix multiply
// FINC_AREA2 = pointer to synchronization counter
// A_AREA = pointer to input matrix A
// B_AREA = pointer to input matrix B
// C_AREA = pointer to output matrix C

N = spu_read_in_mbox();
ITER = spu_read_in_mbox();
FINC_AREA2 = (atomic_ea_t)spu_read_in_mbox();
A_AREA = spu_read_in_mbox();
B_AREA = spu_read_in_mbox();
C_AREA = spu_read_in_mbox();

tiles = N / M;
blocks = tiles * tiles;
mask = tiles - 1;
shift = 32 - spu_extract(spu_cntlz(spu_promote(mask, 0)), 0);

// Matrix Multiply with block partitioning
blkid = _atomic_inc_return(FINC_AREA2);
i = (blkid >> shift) & mask;
j = (blkid) & mask;
if (blkid >= ITER*blocks) exit(0);
Block_Fetch(InA, InB, i, j, 0, InTag);

while(1){
SwapInBuf();
Block_Fetch(InA, InB, i, j, 1, InTag);
DMA_Wait(InTag^1);
DMA_Wait(OutTag);
MatInit_MxM(OpC, OpA, OpB);
for(k=1;k<(N/M)-1;k++){
SwapInBuf();
Block_Fetch(InA, InB, i, j, k+1, InTag);
DMA_Wait(InTag^1);
MatMult_MxM(OpC, OpA, OpB);
}
// Epilogue for k==(N/M)-1
SwapInBuf();

blkid = _atomic_inc_return(FINC_AREA2);
i_next = (blkid >> shift) & mask;
j_next = (blkid) & mask;


if (blkid >= ITER*blocks) {
DMA_Wait(InTag^1);
MatMult_MxM(OpC, OpA, OpB);
Block_Store(OutC, i, j, OutTag);
DMA_Wait(OutTag);
break;
}

Block_Fetch(InA, InB, i_next, j_next, 0, InTag);
DMA_Wait(InTag^1);
MatMult_MxM(OpC, OpA, OpB);
Block_Store(OutC, i, j, OutTag);
i = i_next;
j = j_next;
SwapOutBuf();
}

return (0);
}
[/size]

и того 1257 строк, не считая кода, который обслуживает это хозяйство на PPE. думаю, что для того, чтобы оценить масштабы этого бедствия, не нужно даже быть программистом. очень рекомендую скопировать это в текстовый редактор и посмотреть как оно выглядит в нормальном размере.

и это еще кстати, весьма удачный и удобный для cell пример. благодаря аддитивным свойствам операций, используемых в перемножении матриц, такой код становится как вообще возможным, так и эффективным. страшно представить во что выльется вычисление детерминанта :gigi:.

ну как, энтузиазма не поубавилось :gigi:?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
За**ись!..
Но, может, инструментарий будет включать в себя компиляторы с упрощенным для некоторых стандартных операций синтаксисом?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
[quote name="Kefka"]Но, может, инструментарий будет включать в себя компиляторы с упрощенным для некоторых стандартных операций синтаксисом?[/quote]
это уже и есть компилятор с упощенным синтаксисом :gigi:.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Bagamut, не нужно так пугать народ (особенно не программистов) :)
1. Из всего этого кода - бОльшая часть касается работы самой программы (да да, все эти SPE, регистры 4-х кратной точности и т.п. лябуда), в которой используется умножение матриц.
2. Код самой функции значительно короче, хотя тоже состоит из сотни строчек :D
3. Не стоит забывать, что это [b]оптимизация[/b], а не простые пару циклов (как в твоем примере), которые точно также можно было бы написать на Cell.
4. Попробуй провести такую же оптимизацию (на уровне ассемблера), получится код, сравнимый с этим.
5. А вообще, зачем кому-то заморачиваться?
MatMult_MxM(OpC, OpA, OpB);
Мы же не смотрим на то, как реализована функция деления чисел с плавающей точкой в компиляторе для какого-нибудь C++. Вот тут не нужно нагружать голову ;)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Bahamut, а мне кажется, что ты гонишь. Вот это умножением матриц:

// Matrix Multiply with block partitioning
blkid = _atomic_inc_return(FINC_AREA2);
i = (blkid >> shift) & mask;
j = (blkid) & mask;
if (blkid >= ITER*blocks) exit(0);
Block_Fetch(InA, InB, i, j, 0, InTag);

while(1){
SwapInBuf();
Block_Fetch(InA, InB, i, j, 1, InTag);
DMA_Wait(InTag^1);
DMA_Wait(OutTag);
MatInit_MxM(OpC, OpA, OpB);
for(k=1;k<(N/M)-1;k++){
SwapInBuf();
Block_Fetch(InA, InB, i, j, k+1, InTag);
DMA_Wait(InTag^1);
MatMult_MxM(OpC, OpA, OpB);
}
// Epilogue for k==(N/M)-1
SwapInBuf();

blkid = _atomic_inc_return(FINC_AREA2);
i_next = (blkid >> shift) & mask;
j_next = (blkid) & mask;


if (blkid >= ITER*blocks) {
DMA_Wait(InTag^1);
MatMult_MxM(OpC, OpA, OpB);
Block_Store(OutC, i, j, OutTag);
DMA_Wait(OutTag);
break;
}

Block_Fetch(InA, InB, i_next, j_next, 0, InTag);
DMA_Wait(InTag^1);
MatMult_MxM(OpC, OpA, OpB);
Block_Store(OutC, i, j, OutTag);
i = i_next;
j = j_next;
SwapOutBuf();
}

А всё что сверху, это всё похоже на иницализационную ботву аля ассемблер.



JayDi, согласен с тобой. :agree:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
Авторизация  

  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу

×