
Однако, вот такой вот код есть.
Код
#include "io430.h"
typedef signed char INT8;
typedef signed short INT16;
typedef signed long INT32;
typedef signed long long INT64;
typedef unsigned char UINT8;
typedef unsigned short UINT16;
typedef unsigned long UINT32;
typedef unsigned long long UINT64;
INT16 FilterSample(const INT16 sample );
const INT16 coeffs[4][2][3] ={
{{16384, -28354, 16384}, {16384, -28552, 14866}},
{{16384, -26784, 16384}, {16384, -25180, 11711}},
{{16384, -20728, 16384}, {16384, -20769, 7916}},
{{16384, 9571, 16384}, {16384, -16608, 4444}} };
INT16 state[2][2];
INT16 (*coef)[3];
int main( void )
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
coef = (INT16(*)[3])&coeffs[0][0][0];
FilterSample(783);
}
//#pragma optimize = none
INT16 FilterSample(const INT16 sample )
{
INT32 res = (INT32)coef[0][0] * sample;
for (UINT8 i = 0; i < 2; i++)
{
INT32 r1 = (INT32)state[0][i] * coef[0][i + 1];
INT32 r2 = (INT32)state[1][i] * coef[1][i + 1];
res += r1 - r2;
}
res = (INT16)(res >> 14);
return res;
}
typedef signed char INT8;
typedef signed short INT16;
typedef signed long INT32;
typedef signed long long INT64;
typedef unsigned char UINT8;
typedef unsigned short UINT16;
typedef unsigned long UINT32;
typedef unsigned long long UINT64;
INT16 FilterSample(const INT16 sample );
const INT16 coeffs[4][2][3] ={
{{16384, -28354, 16384}, {16384, -28552, 14866}},
{{16384, -26784, 16384}, {16384, -25180, 11711}},
{{16384, -20728, 16384}, {16384, -20769, 7916}},
{{16384, 9571, 16384}, {16384, -16608, 4444}} };
INT16 state[2][2];
INT16 (*coef)[3];
int main( void )
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
coef = (INT16(*)[3])&coeffs[0][0][0];
FilterSample(783);
}
//#pragma optimize = none
INT16 FilterSample(const INT16 sample )
{
INT32 res = (INT32)coef[0][0] * sample;
for (UINT8 i = 0; i < 2; i++)
{
INT32 r1 = (INT32)state[0][i] * coef[0][i + 1];
INT32 r2 = (INT32)state[1][i] * coef[1][i + 1];
res += r1 - r2;
}
res = (INT16)(res >> 14);
return res;
}
Конкретно интересует место
Код
INT32 r1 = (INT32)state[0][i] * coef[0][i + 1];
INT32 r2 = (INT32)state[1][i] * coef[1][i + 1];
res += r1 - r2;
INT32 r2 = (INT32)state[1][i] * coef[1][i + 1];
res += r1 - r2;
Тут все просто берется два произведения, берется разность между ними и интегрируется в переменной res.
Так вот листинг этой функции (FilterSample) с включенной оптимизацией выглядит вот так вот:
Код
FilterSample:
004048 120A push.w R10
00404A 120B push.w R11
00404C 1208 push.w R8
00404E 1209 push.w R9
004050 1206 push.w R6
INT32 res = (INT32)coef[0][0] * sample;
004052 421A 1108 mov.w &coef,R10
004056 1202 push.w SR
004058 C232 dint
00405A 4303 nop
00405C 4AA2 0132 mov.w @R10,&MPYS
004060 4C82 0138 mov.w R12,&OP2
004064 421C 013A mov.w &RESLO,R12
004068 421D 013C mov.w &RESHI,R13
00406C 4132 pop.w SR
for (UINT8 i = 0; i < 2; i++)
00406E 403E 1100 mov.w #0x1100,R14
004072 4A0B mov.w R10,R11
004074 522B add.w #0x4,R11
res += r1 - r2;
004076 1202 push.w SR
004078 C232 dint
00407A 4303 nop
00407C 4132 pop.w SR
00407E 580C add.w R8,R12
004080 690D addc.w R9,R13
004082 1202 push.w SR
004084 C232 dint
004086 4303 nop
004088 4E92 0004 0132 mov.w 0x4(R14),&MPYS
00408E 4A92 0008 0138 mov.w 0x8(R10),&OP2
004094 4218 013A mov.w &RESLO,R8
004098 4219 013C mov.w &RESHI,R9
00409C 4132 pop.w SR
00409E 880C sub.w R8,R12
0040A0 790D subc.w R9,R13
for (UINT8 i = 0; i < 2; i++)
0040A2 532A incd.w R10
0040A4 532E incd.w R14
004048 120A push.w R10
00404A 120B push.w R11
00404C 1208 push.w R8
00404E 1209 push.w R9
004050 1206 push.w R6
INT32 res = (INT32)coef[0][0] * sample;
004052 421A 1108 mov.w &coef,R10
004056 1202 push.w SR
004058 C232 dint
00405A 4303 nop
00405C 4AA2 0132 mov.w @R10,&MPYS
004060 4C82 0138 mov.w R12,&OP2
004064 421C 013A mov.w &RESLO,R12
004068 421D 013C mov.w &RESHI,R13
00406C 4132 pop.w SR
for (UINT8 i = 0; i < 2; i++)
00406E 403E 1100 mov.w #0x1100,R14
004072 4A0B mov.w R10,R11
004074 522B add.w #0x4,R11
res += r1 - r2;
004076 1202 push.w SR
004078 C232 dint
00407A 4303 nop
00407C 4132 pop.w SR
00407E 580C add.w R8,R12
004080 690D addc.w R9,R13
004082 1202 push.w SR
004084 C232 dint
004086 4303 nop
004088 4E92 0004 0132 mov.w 0x4(R14),&MPYS
00408E 4A92 0008 0138 mov.w 0x8(R10),&OP2
004094 4218 013A mov.w &RESLO,R8
004098 4219 013C mov.w &RESHI,R9
00409C 4132 pop.w SR
00409E 880C sub.w R8,R12
0040A0 790D subc.w R9,R13
for (UINT8 i = 0; i < 2; i++)
0040A2 532A incd.w R10
0040A4 532E incd.w R14
Почему я вижу только одно умножение??? Соответствующее рассчету r2. А умножение в рассчете r1 отсутствует, причем вся подготовка для него существует (в виде запрета прерывания, сохранение статусного регистра, затем его восстановления).
Я приаттачил проект, если кому интересно, точнее выдержку из рабочего проекта с интересующим кодом.
Интересно следующее, если отключить оптимизацию - работает, есть два умножения. Если включить опцию Hardware multiplier->Use only lib calls то тоже работает. В этом случае компайлер просто вызывает функции с умножением, а не инлайнит их как обычно, но работает.
Почему ИАР не умножает второй раз (точнее первый раз)?
Спасибо.
Нажмите для просмотра прикрепленного файла