Sergey_Aleksandrovi4 1 28 августа, 2017 Опубликовано 28 августа, 2017 · Жалоба Здравствуйте. В проекте функция реализована как ассемблерная процедура. Состоит из одной инструкции и хотелось бы преобразовать её в макрос, чтобы не тратить такты на вход и выход. Реализована в *.s файле в виде SECTION .text:CODE:NOROOT(2) PUBLIC MULSHIFT32 THUMB MULSHIFT32 smull r2, r0, r1, r0 BX lr Далее используется в *.c файлах как обычная функция b2 = MULSHIFT32(*cptr++, a1 - a2) << (s1); Не зная тонкостей синтаксиса ассемблера IAR попробовал "в лоб" реализовать таким образом MULSHIFT32 MACRO smull r2, r0, r1, r0 ENDM Линкер ругается на неизвестное имя MULSHIFT32. Ключевые слова PUBLIC и EXTERN вызывают ошибку. Кто подскажет, как этот макрос правильно оформить, чтобы можно было использовать его вне *.s-файла? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 29 28 августа, 2017 Опубликовано 28 августа, 2017 · Жалоба Не занимайтесь ерундой. Умножать с нужной разрядностью - дело компилятора. int32_t x=1L,y=2L; int64_t z; z = (int64_t)x*y; Дадут вам // 106 int32_t x=1L,y=2L; MOVS R0,#+1 STR R0,[SP, #+4] MOVS R0,#+2 STR R0,[SP, #+0] // 107 int64_t z; // 108 z = (int64_t)x*y; LDR R0,[SP, #+4] LDR R1,[SP, #+0] SMULL R0,R1,R1,R0 STRD R0,R1,[SP, #+8] Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Sergey_Aleksandrovi4 1 28 августа, 2017 Опубликовано 28 августа, 2017 · Жалоба VladislavS, спасибо за идею. Это не совсем то, что нужно, но получилось слегка ускорить алгоритм. Создал обычный макрос #define MULSHIFT32(arg1, arg2) ((((long long)arg1)*((long long)arg2))>>32) Всё-равно получается избыточно, если верить листингу. Было до b0 = a0 + a7; b7 = MULSHIFT32(*cptr++, a0 - a7) << 1; 0x59ac0: 0xf8d4 0xa010 LDR.W R10, [R4, #0x10] b0 = a0 + a7; b7 = MULSHIFT32(*cptr++, a0 - a7) << 1; 0x59ac4: 0x1846 ADDS R6, R0, R1 b0 = a0 + a7; b7 = MULSHIFT32(*cptr++, a0 - a7) << 1; 0x59ac6: 0x1a09 SUBS R1, R1, R0 0x59ac8: 0xf855 0x0b04 LDR.W R0, [R5], #0x4 0x59acc: 0xf7fd 0xf9ea BL MULSHIFT32 ; 0x56ea4 MULSHIFT32: 0x56ea4: 0xfb81 0x2000 SMULL R2, R0, R1, R0 0x56ea8: 0x4770 BX LR 0x59ad0: 0x4680 MOV R8, R0 0x59ad2: 0xea4f 0x0848 LSL.W R8, R8, #1 Стало после b0 = a0 + a7; b7 = MULSHIFT32(*cptr++, a0 - a7) << 1; 0x58dee: 0xf851 0x6b04 LDR.W R6, [R1], #0x4 0x58df2: 0x17f7 ASRS R7, R6, #31 0x58df4: 0x17e5 ASRS R5, R4, #31 0x58df6: 0x17d3 ASRS R3, R2, #31 0x58df8: 0x1aa2 SUBS R2, R4, R2 0x58dfa: 0xeb65 0x0303 SBC.W R3, R5, R3 0x58dfe: 0x4634 MOV R4, R6 0x58e00: 0x463d MOV R5, R7 0x58e02: 0xfba2 0x6704 UMULL R6, R7, R2, R4 0x58e06: 0xfb02 0x7705 MLA R7, R2, R5, R7 0x58e0a: 0xfb03 0x7704 MLA R7, R3, R4, R7 0x58e0e: 0x46b8 MOV R8, R7 0x58e10: 0xea4f 0x0848 LSL.W R8, R8, #1 В моём случае объявить, как в Вашем примере 64-битную переменную и положить в неё результат 32х32 не получится. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 28 августа, 2017 Опубликовано 28 августа, 2017 · Жалоба Из любопытства попробовал на GCC вот такое: #define MULSHIFT32(arg1, arg2) ((((long long)arg1)*((long long)arg2))>>32) int volatile a0, a7, b7, ar[2]; void f(void) { int* cptr = ar; b7 = MULSHIFT32(*cptr++, a0) << 1; } Получилось вот что: 0x0800146E 4D72 LDR r5,[pc,#456]; @0x08001638 0x08001470 686B LDR r3,[r5,#0x04] 0x08001472 68E8 LDR r0,[r5,#0x0C] 0x08001474 FB830100 SMULL r0,r1,r3,r0 0x08001478 184A ADDS r2,r1,r1 0x0800147A 612A STR r2,[r5,#0x10] А если написать вот так b7 = MULSHIFT32(*cptr++, a0 - a7) << 1; То получается АдЪ: 0x0800146E 4D77 LDR r5,[pc,#476]; @0x0800164C 0x08001470 6868 LDR r0,[r5,#0x04] 0x08001472 68AE LDR r6,[r5,#0x08] 0x08001474 68EC LDR r4,[r5,#0x0C] 0x08001476 17C1 ASRS r1,r0,#31 0x08001478 1B80 SUBS r0,r0,r6 0x0800147A EB6171E6 SBC r1,r1,r6,ASR #31 0x0800147E FB04F201 MUL r2,r4,r1 0x08001482 17E3 ASRS r3,r4,#31 0x08001484 FB002303 MLA r3,r0,r3,r2 0x08001488 FBA40100 UMULL r0,r1,r4,r0 0x0800148C 185C ADDS r4,r3,r1 0x0800148E 1922 ADDS r2,r4,r4 0x08001490 616A STR r2,[r5,#0x14] Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 187 28 августа, 2017 Опубликовано 28 августа, 2017 · Жалоба #define MULSHIFT32(arg1, arg2) ((((long long)arg1)*((long long)arg2))>>32) Если Вам нужны только старшие 32 бита (как следует из этого макроса), то всё просто: #define MULSHIFT32(x, y) __SMMUL(x, y) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 29 28 августа, 2017 Опубликовано 28 августа, 2017 · Жалоба Во-первых, очень некрасиво не показывать типы используемых переменных и желаемого результата. Во-вторых, разберитесь с размерностью вычислений. Написанный вами макрос делает совсем не то что вы хотите. В-третьих, ваш mulshift32, судя по всему, это банальное int32_t x=1L,y=2L; int32_t z; z = ((int64_t)x*y)>>32; Поверьте, компилятор сделает всё лучше вас, особенно с оптимизацией. Только не мешайте ему. // int32_t x=1L,y=2L; MOVS R0,#+1 MOVS R1,#+2 // int32_t z; // z = ((int64_t)x*y)>>32; SMULL R0,R1,R1,R0 В-четвёртых, вместо x и y можете ставить что угодно, только с соблюдением типов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 187 28 августа, 2017 Опубликовано 28 августа, 2017 · Жалоба Поверьте, компилятор сделает всё лучше вас, особенно с оптимизацией. Только не мешайте ему. Вангую, что автор не сам ваяет, а пытается запустить/портировать готовое, где уже есть много MULSHIFT32()... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 29 28 августа, 2017 Опубликовано 28 августа, 2017 · Жалоба Дарю #define MULSHIFT32(arg1, arg2) (((int64_t)(int32_t)(arg1)*(int32_t)(arg2))>>32) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 29 августа, 2017 Опубликовано 29 августа, 2017 · Жалоба Кстати, если в моём эксперименте с GCC сделать так #define MULSHIFT32(a, b) (((long long)(a) * (b)) >> 32) то код генерится вменяемый. Очевидно, в первоначальном варианте макроса не хватает скобок вокруг аргументов. На первый взгляд, в данном случае неважно, но, возможно, я что-то не заметил. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Sergey_Aleksandrovi4 1 29 августа, 2017 Опубликовано 29 августа, 2017 · Жалоба jcxz, всё верно, чужие библиотеки. Портирую mp3-декодер Helix. В очередной раз) Если Вам нужны только старшие 32 бита (как следует из этого макроса), то всё просто: #define MULSHIFT32(x, y) __SMMUL(x, y) Спасибо. Даже забыл, что в IAR есть intrinsic-ассемблер, как всё просто оказывается. Дарю #define MULSHIFT32(arg1, arg2) (((int64_t)(int32_t)(arg1)*(int32_t)(arg2))>>32) Спасибо за подарок. Прогнал оба варианта на разных уровнях оптимизации. По оси ординат разница выполнения алгоритма в мс. Time( __SMMUL(x, y)) - Time((((int64_t)(int32_t)(arg1)*(int32_t)(arg2))>>32)). Без оптимизации паритет, на умеренной оптимизации использование интринсик-функции __SMMUL(x, y) оказывается более быстрым, в случае максимальной оптимизации по скорости выигрывает решение от VladislavS. Разница не существенная, в районе 1%. Дизассемблер для каждой из реализаций. Алгоритм раскладывается в одни и те же инструкции, но с использованием разных РОН. b0 = a0 + a7; b7 = MULSHIFT32(*cptr++, a0 - a7) << 1; 0x59830: 0x1979 ADDS R1, R7, R5 b0 = a0 + a7; b7 = MULSHIFT32(*cptr++, a0 - a7) << 1; 0x59832: 0x1bed SUBS R5, R5, R7 0x59834: 0xf852 0x7b04 LDR.W R7, [R2], #0x4 0x59838: 0xfb57 0xfc05 SMMUL R12, R7, R5 0x5983c: 0xea4f 0x0c4c LSL.W R12, R12, #1 b0 = a0 + a7; b7 = MULSHIFT32(*cptr++, a0 - a7) << 1; 0x59906: 0x1978 ADDS R0, R7, R5 b0 = a0 + a7; b7 = MULSHIFT32(*cptr++, a0 - a7) << 1; 0x59908: 0xf853 0xcb04 LDR.W R12, [R3], #0x4 0x5990c: 0x1bed SUBS R5, R5, R7 0x5990e: 0xfb5c 0xfc05 SMMUL R12, R12, R5 0x59912: 0xea4f 0x0c4c LSL.W R12, R12, #1 И хотя первоначальный вопрос про синтаксис макросов остался открытым, но задача решена другими средствами. Спасибо за помощь! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 29 августа, 2017 Опубликовано 29 августа, 2017 · Жалоба И хотя первоначальный вопрос про синтаксис макросов остался открытым, но задача решена другими средствами. Спасибо за помощь! Имеется в виду вот этот вопрос? Кто подскажет, как этот макрос правильно оформить, чтобы можно было использовать его вне *.s-файла? Тогда ответ такой: никак. Это макросы ассемблера, фактически текстовая подстановка в пределах ассемблерного файла. Ни разу не видел, чтобы такие вещи действовали в сишных файлах. И уж точно на уровне линкера ничего этого быть не может. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 187 29 августа, 2017 Опубликовано 29 августа, 2017 · Жалоба jcxz, всё верно, чужие библиотеки. Портирую mp3-декодер Helix. В очередной раз) Ну вот я так и думал, что Helix ;) И макрос этот я запостил как раз из своего работающего проекта на Helix :rolleyes: Что ваяете, если не секрет? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Sergey_Aleksandrovi4 1 29 августа, 2017 Опубликовано 29 августа, 2017 · Жалоба Это макросы ассемблера, фактически текстовая подстановка в пределах ассемблерного файла. Вот оно что. Спасибо. С ARM-ассемблером пару раз в жизни сталкивался, не знал про эти тонкости. jcxz, в двух словах - интерактивная игрушка для детей, ничего серьёзного. Кодек этот давно ещё портировал на cortex M3 (не без помощи здешних форумчан). Теперь перевожу на cortex M4, ну и решил по-максимуму из него выжать и закрыть тему навсегда. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 187 30 августа, 2017 Опубликовано 30 августа, 2017 · Жалоба Дарю #define MULSHIFT32(arg1, arg2) (((int64_t)(int32_t)(arg1)*(int32_t)(arg2))>>32) __SMMUL() может быть чуть-чуть лучше если нужно ещё и округление результата: __SMMULR(). Правда без возможности предварительного сдвига результата влево на 1 бит, это округление редко бывает полезным. :( Не знаю почему в системе команд не предусмотрена опция сдвига влево результата на 1 бит. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 29 30 августа, 2017 Опубликовано 30 августа, 2017 · Жалоба Если есть возможность не уходить от чистого С/C++, то лучше от него не уходить. Чтобы не возникало потом таких тем как эта. Вот что заставило автора того кода ассемблерную функцию применить? Компилятор не знал команду smmul или программист не смог ему объяснить что он хочет? Я ставлю на второе. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться