|
gcc 4.2.2 и умножение int 16x16 |
|
|
|
May 29 2008, 03:47
|
;
     
Группа: Участник
Сообщений: 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 такт Бился головой о стену - ниасилил компилер такой красоты. А очень надо. Если кто уже получал такое чистым Си, поделитесь, пожалуйста, опытом.
|
|
|
|
2 страниц
< 1 2
|
 |
Ответов
(15 - 24)
|
Jun 2 2008, 06:30
|
;
     
Группа: Участник
Сообщений: 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]
|
|
|
|
|
Jun 2 2008, 07:54
|

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

|
Цитата(_Pasha @ Jun 2 2008, 12:30)  Прочтите внимательно предыдущий пост. Я показал, что при b=1 можно применять. Но результат несколько неожиданный. Вот неожиданность меня и сбила с толку. Перечитал, понял  Цитата P.S. Если выдает ошибку при b=1, то это бага компилятора, которая заключается в безусловной подмене операции /256 операцией взятия старшего байта с последующим знаковым расширением. А это я вечерком проверю. Можно вопрос немного в сторону? Для чего применяется подобное масштабирование? Ну, пару примеров? А то вижу что штука хорошая, а куда применить - не могу придумать
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jun 2 2008, 08:10
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(AHTOXA @ Jun 2 2008, 10:54)  Для чего применяется подобное масштабирование? Например, выдаем биполярный сигнал через 10-бит PWM. Базовая линия сигнала (наш ноль) будет на отметке PWM_OFFSET=512. А на АЦП висит резистор громкости, 8-бит достаточно. Код #define PWM_OFFSET 512 uint8_t wrk; int16_t generator_out;
//................................ // having outgoing milestone :)
// read ADC wrk=ADCH; // output OCR1=scale16x8(generator_out,wrk)+ PWM_OFFSET; Проверил на своем gcc4.2.2 выражение c=(int32_t) a*b/256; компилится правильно при b=1, a=-32767, т.е. и в виде константного выражения и в виде реальных вычислений результат = 0xFFFFFF81
|
|
|
|
|
Jun 3 2008, 17:20
|

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

|
Я добрался до АВРки, продолжаю  Урезал осетра, запустил цикл с -32767... Упс, при a = -32766 и b = 128 пишет: ошибка, i1 = -16382, i2 = 49153. Я в шоке  Проверяю на куркуляторе - должно получиться -16383. Окей, ещё одна дырочка в области применения. Но это ерунда  Интереснее другое: как выражение Код i2 = (signed long)i*b/256; при i = -32766 и b = 128 дало 49153?! проверял с avr-gcc.exe (GCC) 4.3.0 20080111 (experimental) avr-gcc.exe (GCC) 4.4.0 20080530 (experimental) от klen-a и avr-gcc.exe (GCC) 4.1.2 (WinAVR 20070525) Это опять я глючу, или таки бага компилятора?
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jun 3 2008, 18:57
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Цитата(AHTOXA @ Jun 3 2008, 21:20)  Интереснее другое: как выражение Код i2 = (signed long)i*b/256; при i = -32766 и b = 128 дало 49153?! Ничего интересного: 49153 это 0xC001 или -16383. Убери unsigned из объявления переменой i2. Анатолий. PS: В следующий раз посылайте тестовые примеры полностью, с объявлениями перемеренных. Цитата(_Pasha @ Jun 3 2008, 22:49)  Это глюки не компилера, а отладчика, в котором Вы все это смотрели. Это глюки не отладчика а програмера. Надо правильно выбирать типы переменных.
Сообщение отредактировал aesok - Jun 3 2008, 18:58
|
|
|
|
|
Jun 4 2008, 03:12
|

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

|
Цитата(_Pasha @ Jun 4 2008, 00:49)  Это глюки не компилера, а отладчика, в котором Вы все это смотрели. Судите сами: 49153 = C001, опять же, в дополн коде получим 3FFF, т.е 16383 Я на железке смотрю, так сказать, живьём. Цитата(aesok @ Jun 4 2008, 00:57)  Убери unsigned из объявления переменой i2. Не могу. Его там нет  Мне что, тестовый пример пихать в каждое своё сообщение? Я его уже два раза приводил. PS. Я почти на 100% уверен, что глюк мой, а не компилятора. Только не могу понять где...
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jun 4 2008, 05:55
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(_Pasha @ Jun 3 2008, 21:49)  Бит SREG.C выскакивает в mulsu когда signed <0. Сейчас тоже позанимаюсь. Короче, не выходит каменный цветок. Куча исключений. 1. При b=0x80 врет на 1 2. Надо повнимательней к переполнениям, т.к. например -1 * 0xff /0x100 даже на "куркуляторе" дает чушь, напоминающую о необходимости обрабатывать исключения. Цитата(AHTOXA @ Jun 4 2008, 06:12)  PS. Я почти на 100% уверен, что глюк мой, а не компилятора. Только не могу понять где... Наверное, куда-то девается (игнорируется) знаковое расширение в старших байтах. GCC4.2.2 на аврстудии показывает все правильно.
|
|
|
|
|
Jun 4 2008, 07:53
|

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

|
Цитата(_Pasha @ Jun 4 2008, 11:55)  Короче, не выходит каменный цветок. Куча исключений. 1. При b=0x80 врет на 1 Ну ничего, всё равно пригодится. Для некритичных к точности но критичных ко времени вычислений (как в примере с ШИМом)  Цитата Наверное, куда-то девается (игнорируется) знаковое расширение в старших байтах. GCC4.2.2 на аврстудии показывает все правильно. Я уже всю голову сломал. Есть ф-я вывода int на дисплей: nokia_put_int(int i); есть два инта: Код int16_t i1; int16_t i2; i1 = scale16x8(i, b); i2 = (signed long)i*b/256; ... nokia_put_int(i1); nokia_put_int(i2); Первый int (i1, -16382 или C002) отображается нормально, в виде отрицательного значения. А вот i2 (-16383 или C001) - почему-то трактуется как unsigned... Вот и пойми тут, в чём разница... Ладно, вечерком ещё поковыряю...
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jun 5 2008, 17:19
|

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

|
Я лопух:-) Цитата(AHTOXA @ Jun 4 2008, 13:53)  есть два инта: Код int16_t i1; int16_t i2; i1 = scale16x8(i, b); i2 = (signed long)i*b/256; ... nokia_put_int(i1); nokia_put_int(i2); последняя строчка была: nokia_put_ uint(i2); Буковку проглядел
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|