реклама на сайте
подробности

 
 
> gcc 4.2.2 и умножение int 16x16
_Pasha
сообщение May 29 2008, 03:47
Сообщение #1


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Доброго времени!
Подскажите, как заставить компилятор в Winavr генерить правильный код.
Нужно
Код
int16_t Xarg,Yarg,Zarg;
........................
Zarg= (Xarg*Yarg) >>16;


Приведение к 32-битам - это безумное количество кода.
Надо, чтоб генерился код примерно такой (имена регистров не важны):
Код
lds r16,Xarg
lds r17,Xarg+1
lds r18,Yarg
lds r19,Yarg+1
clr r6 //9
// дальше стандартное знаковое умножение
muls r17,19
movw r4,r0
mul 16,r18
movw r2,r0
mulsu r19,r16
sbc r5,r6
add r3,r0
adc r4,r1
adc r5,r6
mulsu r17,r18
sbc r5,r6
add r3,r0
adc r4,r1
adc r5,r6
// и выделение старшей части 32-битного результата
sts Zarg,r4
sts Zarg+1,r5
// итого 22+9 = 31 такт


Бился головой о стену - ниасилил компилер такой красоты. А очень надо. Если кто уже получал такое чистым Си, поделитесь, пожалуйста, опытом.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
_Pasha
сообщение Jun 1 2008, 09:27
Сообщение #2


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Какая же все-таки грабляндия эта арифметика!
Привожу правильный и проверенный на всем множестве код для операции
(int16_t) = (int16_t)*(uint8_t)/256
в виде AVR gnu-as
Код
#define arg1L  r16
#define arg1H r17
#define scalar r18
#define NULL_REG r6
scale16x8:
  clr       NULL_REG
//...........................
  mul     arg1L,scalar
  mov    r2,r1
  mulsu  arg1H,scalar
  adc     r0,r2
  adc     r1,NULL_REG

; result in r0:r1


Итого 7 тактов.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 1 2008, 14:04
Сообщение #3


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(_Pasha @ Jun 1 2008, 15:27) *
Какая же все-таки грабляндия эта арифметика!
Привожу правильный и проверенный на всем множестве код для операции


Переписал для inline асссемблера:

Код
static inline uint16_t scale16x8(uint16_t a, uint8_t b)
{
    uint16_t result;
    uint8_t tmp;
/*
%A0 - low byte of result,
%B0 - hi byte of result,
%1  - tmp
%A2 - low byte of the first operand,
%B2 - hi byte of the first operand,
%3 - second operand
*/

    asm (
        "clr    %1 \n\t"
        "mul    %A2,%3 \n\t"
        "mov    r2,r1 \n\t"
        "mulsu    %B2,%3 \n\t"
        "adc    r0,r2 \n\t"
        "adc    r1,%1 \n\t"
        "movw    %A0, r0 \n\t"
        "clr    __zero_reg__ \n\t"
        : "=&r" (result), "=&r" (tmp)
        : "a" (a), "a" (b)
    );

    return result;
}


Добавил зачистку __zero_reg__, так положено.

Только вот что-то не сходится:

Код
int scale_test(void)
{
    uint16_t a = 0;
    uint8_t b = 0;
    while (TRUE)
    {
        if (scale16x8(a, b) != ((unsigned long)a*b/256))
        {
            nokia_puts_p("a = ");
            nokia_put_word(a);
            nokia_puts_p(",  b = ");
            nokia_put_word(b);
            return FALSE;
        }
        if (a == 0xFFFF && b == 0xFF) return TRUE;
        if (!++b) a++;
    }
}


Ошибка при a=0x8000 и b=1.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
singlskv
сообщение Jun 1 2008, 14:22
Сообщение #4


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(AHTOXA @ Jun 1 2008, 18:04) *
Ошибка при a=0x8000 и b=1.
У Вас
static inline uint16_t scale16x8(uint16_t a , uint8_t b )
а было:
(int16_t) = (int16_t )*(uint8_t)/256
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 1 2008, 15:47
Сообщение #5


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(singlskv @ Jun 1 2008, 20:22) *
У Вас
static inline uint16_t scale16x8(uint16_t a , uint8_t b )
а было:
(int16_t) = (int16_t )*(uint8_t)/256


Точно! Виноват :-)
Исправил:

Код
static inline int16_t scale16x8(int16_t a, uint8_t b)
{
    int16_t result;
    uint8_t tmp;
/*
%A0 - low byte of result,
%B0 - hi byte of result,
%1  - tmp
%A2 - low byte of the first operand,
%B2 - hi byte of the first operand,
%3 - second operand
*/

    asm (
        "clr    %1 \n\t"
        "mul    %A2,%3 \n\t"
        "mov    r2,r1 \n\t"
        "mulsu    %B2,%3 \n\t"
        "adc    r0,r2 \n\t"
        "adc    r1,%1 \n\t"
        "movw    %A0, r0 \n\t"
        "clr    __zero_reg__ \n\t"
        : "=&r" (result), "=&r" (tmp)
        : "a" (a), "a" (b)
    );

    return result;
}

int scale_test(void)
{
    int16_t i = -32768;
    uint8_t b = 0;
    int16_t i1, i2;
    while (TRUE)
    {
        i1 = scale16x8(i, b);
        i2 = (signed long)i*b/256;
        if (i1 != i2)
        {
            nokia_puts_p("   a = ");
            nokia_put_int(i);
            nokia_puts_p(",   b = ");
            nokia_put_word(b);
            return FALSE;
        }
        b++;
        if (!b)
        {
            i++;
        }
        if ((i == 32767) && (b == 0xFF)) break;
    }
    return TRUE;
}


Но всё равно, выдаёт ошибку при i=-32768 и b=1... Опять я где-то что-то проглядел? smile.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jun 1 2008, 20:06
Сообщение #6


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(AHTOXA @ Jun 1 2008, 18:47) *
Но всё равно, выдаёт ошибку при i=-32768 и b=1... Опять я где-то что-то проглядел? smile.gif


a14.gif
Про b=1 - это хорошо... Легкая неадекватность поведения замечена.
А вот про -32768 то есть 0x8000, предлагаю извлечь дополнительный код из него lol.gif
bb-offtopic.gif
Меняю стакан соломы на обратный билет с Марса...
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 2 2008, 03:57
Сообщение #7


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(_Pasha @ Jun 2 2008, 02:06) *
Про b=1 - это хорошо... Легкая неадекватность поведения замечена.


То есть, функция таки работает не "во всём множестве"? :-)

Цитата
А вот про -32768 то есть 0x8000, предлагаю извлечь дополнительный код из него lol.gif


А зачем? :-) Или -32768 не бывает? smile.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jun 2 2008, 05:19
Сообщение #8


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(AHTOXA @ Jun 2 2008, 06:57) *
То есть, функция таки работает не "во всём множестве"? :-)
А зачем? :-) Или -32768 не бывает? smile.gif


Таки да. Каюсь, не проверил оные значения ввиду нехватки времени и отсутсвия их практической ценности в целевом проекте.

На самом деле с единицей оказалось все правильно. Возьмем -32767=0x8001 smile.gif
Для того, чтобы доказать, что 0x8001 >>8 != 0x80, приведем его в беззнаковый вид.
Дополнительный код даст 0x7fff, операция сдвига на 8 бит даст 0x7f. Извлекаем обратно дополнительный код из результата, получаем 0x81. При расширении знака в старший байт имеем 0xFF81, что и наблюдаеццо в симуляторе. Как ни странно. Хотя здравый смысл подсказывает, что signed 0x8001 >>8 = 0xFF80.

-32768 - счастливое исключение smile.gif Поскольку +32768 в двух байтах не бывает, попытка привести к беззнаковому умножению 16*8 тоже ни к чему не приведет.
Но на этом беда не заканчивается. Однобайтовый int8_t тоже ведь имеет встроенный баг 0x80. Видимо, придется обрабатывать как исключение. Но проще съехать с базара и сказать Таки да! Не на всем множестве! biggrin.gif
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 2 2008, 06:10
Сообщение #9


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(_Pasha @ Jun 2 2008, 11:19) *
Но проще съехать с базара и сказать Таки да! Не на всем множестве! biggrin.gif


Я отнюдь не наезжаю, боже упаси! Просто хочу знать границы применимости smile.gif Что выходит на данный момент?
Нельзя применять при b=1 и при a=-32768?


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jun 2 2008, 06:30
Сообщение #10


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(AHTOXA @ Jun 2 2008, 09:10) *
Нельзя применять при b=1 и при a=-32768?


Прочтите внимательно предыдущий пост.
Я показал, что при b=1 можно применять. Но результат несколько неожиданный.

При a=-32768 нельзя.
P.S. Если выдает ошибку при b=1, то это бага компилятора, которая заключается в безусловной подмене операции /256 операцией взятия старшего байта с последующим знаковым расширением. Согласитесь, что операции сразу в дополнительном коде и беззнаковые с последующим получением отрицательного числа должны давать одинаковый результат на множестве [-32767..+32767]
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- _Pasha   gcc 4.2.2 и умножение int 16x16   May 29 2008, 03:47
- - aesok   Цитата(_Pasha @ May 29 2008, 07:47) Бился...   May 29 2008, 05:57
|- - _Pasha   Цитата(aesok @ May 29 2008, 08:57) Нужно ...   May 29 2008, 06:47
|- - aesok   Цитата(_Pasha @ May 29 2008, 10:47) Оптим...   May 29 2008, 07:03
- - _Pasha   Я всегда использую -Os, но здесь некоторый кусок к...   May 29 2008, 07:17
- - singlskv   Цитата(_Pasha @ May 29 2008, 07:47) Бился...   May 29 2008, 08:42
|- - _Pasha   Цитата(singlskv @ May 29 2008, 11:42) А п...   May 29 2008, 09:05
|- - AHTOXA   Цитата(_Pasha @ Jun 2 2008, 12:30) Прочти...   Jun 2 2008, 07:54
|- - _Pasha   Цитата(AHTOXA @ Jun 2 2008, 10:54) Для че...   Jun 2 2008, 08:10
- - AHTOXA   Я добрался до АВРки, продолжаю Урезал осетра, зап...   Jun 3 2008, 17:20
|- - aesok   Цитата(AHTOXA @ Jun 3 2008, 21:20) Интере...   Jun 3 2008, 18:57
- - _Pasha   Это глюки не компилера, а отладчика, в котором Вы ...   Jun 3 2008, 18:49
- - AHTOXA   Цитата(_Pasha @ Jun 4 2008, 00:49) Это гл...   Jun 4 2008, 03:12
- - _Pasha   Цитата(_Pasha @ Jun 3 2008, 21:49) Бит SR...   Jun 4 2008, 05:55
- - AHTOXA   Цитата(_Pasha @ Jun 4 2008, 11:55) Короче...   Jun 4 2008, 07:53
- - AHTOXA   Я лопух:-) Цитата(AHTOXA @ Jun 4 2008, 13...   Jun 5 2008, 17:19


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 19:06
Рейтинг@Mail.ru


Страница сгенерированна за 0.01496 секунд с 7
ELECTRONIX ©2004-2016