dimka76 63 9 декабря, 2022 Опубликовано 9 декабря, 2022 · Жалоба On 12/9/2022 at 10:31 AM, vvppvv said: Э не-е-ет, так не пойдёт. Иначе придётся распрощаться с оптимизацией IAR! Много лет назад я эти грабли уже проходил, "Странно, почему, когда включаешь оптимизацию, то программа перестаёт нормально работать?" Компилятор пасёт состояния всех регистров и переменных. Если он когда-то в R17 положил ноль, и больше его не трогал, то когда в следующий раз ему понадобится ноль в каком-нибудь порту, то он его с R17 и дёрнет. А там уже кака. Почитайте в руководстве компилятора соглашения о вызовах функций. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vvppvv 0 9 декабря, 2022 Опубликовано 9 декабря, 2022 · Жалоба 1 hour ago, quark said: После инструкции EOR R17,R16 имеем результат побитного сложения полубайтов в двух экземплярах - в старшем и младшем полубайтах R17 один и тот же. [ ....... ] Суммируем побитно 7-й и 1-й биты инструкцией SUBI R17,0xFE (на самом деле это ADDI R17,0x02). Имеем конечный результат в 7-м бите R17. Спасибо! )) 1 hour ago, dimka76 said: Почитайте в руководстве компилятора соглашения о вызовах функций. Ну, я как бы в курсе. Потому и написАл про "костыль", из-за которого функция якобы возвращает 2 байта. Из которых нужен один, а второй просто указывает компилятору, что где-то внутри функции он испорчен. Если есть цивилизованый способ как-то "обволятилить" R17, то подскажите? )) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 9 декабря, 2022 Опубликовано 9 декабря, 2022 · Жалоба 26 минут назад, vvppvv сказал: Если есть цивилизованый способ как-то "обволятилить" R17, то подскажите? ИАР всегда отличался неплохой документацией и эта документация всегда шла в комплекте. Там искали? На сайте IAR выложена документация от 2017 года, в которой английским по белому сказано: "никак". Если с тех пор ничего не поменялось - переходите на GCC, там компилятору можно объяснить все и он даже сам может выбрать наиболее подходящие регистры: asm volatile ( "LD %[tmp], %a[ptr]+ \n\t" "STS %B[OCR], %[tmp] \n\t" "LD %[tmp], %a[ptr]+ \n\t" "STS %A[OCR], %[tmp] \n\t" "LD %[tmp], %a[ptr]+ \n\t" "OUT %[port_b], %[tmp] \n\t" "LD %[tmp], %a[ptr]+ \n\t" "OUT %[port_c], %[tmp] \n\t" : [ptr]"+e"(pTmp), [tmp]"=r"(Tmp) : [OCR] "M" (_SFR_MEM_ADDR(OCR1A)) , [port_b] "I" (_SFR_IO_ADDR(PORTB)) , [port_c] "I" (_SFR_IO_ADDR(PORTC)) : ); . Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vvppvv 0 9 декабря, 2022 Опубликовано 9 декабря, 2022 · Жалоба Понятно. Раз никак, значит, никак. )) Я попытался переписать асемблер на Си. Все по алгоритму выше. точь в точь. Вместо R17 добавить локальный "ctemp". Но IAR почему-то зачудил. При оптимизации вобще все выкинул, кроме andi 0x7F. Если оптимизацию отключить совсем, получается почти хорошо: \ cSetParity: 380 { 381 char ctemp; 382 cin &= 0x7F; // сбросить 7-ой бит чётности в 0 \ 00000000 770F ANDI R16, 0x7F 383 ctemp = cin; \ 00000002 2F10 MOV R17, R16 384 __swap_nibbles(ctemp); \ 00000004 2F21 MOV R18, R17 \ 00000006 9522 SWAP R18 385 ctemp ^= cin; \ 00000008 2710 EOR R17, R16 386 ctemp &= 0xC3; \ 0000000A 7C13 ANDI R17, 0xC3 387 ctemp += 0x41; \ 0000000C 5B1F SUBI R17, 191 388 ctemp |= 0x7C; \ 0000000E 671C ORI R17, 0x7C 389 ctemp += 0x02; \ 00000010 5F1E SUBI R17, 254 390 ctemp &= 0x80; \ 00000012 7810 ANDI R17, 0x80 391 cin |= ctemp; \ 00000014 2B01 OR R16, R17 392 return cin; \ 00000016 9508 RET 393 } Почему "почти"? См. свап ниблов. Откуда-то вылез R18, который после нигде не фигурирует. Играясь "оптимизЭйшын левелами", я добился нужного результата в листинге, но меня это не устраивает. Когда результат зависит от настроения конкретного релиза компилятора. Так что останется инлайн ассемблер. Вопрос, к чему все мои извраты, ради каких-то 5 тактов? Просто это используется с большой скоростью, для передачи данных. Для массива 1 мегабайт, 5 тактов на 1 байт дадут общий выигрыш 5 миллионов тактов. Переходить на GCC... не уверен, что оно того стОит. Уж больно много лет я сижу в IAR. Да и оптимизирует он код по размеру просто чудовищно эффективно. А у меня часто быват проектики для самых мелких камешков, не влезло - следующий чип, а его или нет, или рублей на 50 дороже. 1000 изделий сразу тянут плюсом 50 тыщ рублей, на ровном месте, и пошло, поехало... (( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 9 декабря, 2022 Опубликовано 9 декабря, 2022 · Жалоба 34 минуты назад, vvppvv сказал: Почему "почти"? См. свап ниблов. Откуда-то вылез R18, который после нигде не фигурирует. Может быть стоило написать ctemp = __swap_nibbles(ctemp); ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vvppvv 0 12 декабря, 2022 Опубликовано 12 декабря, 2022 · Жалоба On 12/9/2022 at 4:22 PM, Сергей Борщ said: Может быть стоило написать ctemp = __swap_nibbles(ctemp); ? :-)) Спасибо! Ну, что тут скажешь. Поторопился. Посыпаю голову пеплом. Как всегда, компиллятор оказался не при чём, "дело было не в бобине..". При получении грамотных команд, компилятор выдал то, что хотелось. Причём, результат (генерируемый код) не меняется от настроек и уровня оптимизации. Теперь никакого инлайн-ассемблера не потребуется, и костылей к нему тоже. 377 char cSetParity (char cin) \ cSetParity: 378 { 379 char ctemp; 380 cin &= 0x7F; // сбросить 7-ой бит чётности в 0 \ 00000000 770F ANDI R16, 0x7F 381 ctemp = cin; \ 00000002 2F10 MOV R17, R16 382 ctemp = __swap_nibbles(ctemp); \ 00000004 9512 SWAP R17 383 ctemp ^= cin; \ 00000006 2710 EOR R17, R16 384 ctemp &= 0xC3; \ 00000008 7C13 ANDI R17, 0xC3 385 ctemp += 0x41; \ 0000000A 5B1F SUBI R17, 191 386 ctemp |= 0x7C; \ 0000000C 671C ORI R17, 0x7C 387 ctemp += 0x02; \ 0000000E 5F1E SUBI R17, 254 388 ctemp &= 0x80; \ 00000010 7810 ANDI R17, 0x80 389 cin |= ctemp; \ 00000012 2B01 OR R16, R17 390 return cin; \ 00000014 9508 RET 391 } Спасибо большое всем за алгоритмы и подсказки! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
quark 48 4 января, 2023 Опубликовано 4 января, 2023 (изменено) · Жалоба В 12.12.2022 в 08:48, vvppvv сказал: Спасибо большое всем за алгоритмы и подсказки! Так выглядит реализация доработанного алгоритма программы: ANDI R16,0x7F MOV R17,R16 ADD R17,R16 EOR R17,R16 ANDI R17,0xAA SUBI R17,0x9A ANDI R17,0x88 SUBI R17,0x88 ANDI R17,0x80 OR R16,R17 По параметрам, он полностью аналогичен предыдущему варианту. Но из него исключена инструкция SWAP, которая имеется не во всех системах команд. В данном алгоритме используются только арифметические и логические команды. P.S. Проверьте. -------------------- P.P.S. Если удалить из программы первую и последнюю строку (даже две последних), то алгоритм будет работать и для полного байта - для всех 8-ми бит. Конечный результат - бит четности - будет в 7-м бите R17. Изменено 4 января, 2023 пользователем quark добавление Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vvppvv 0 9 января, 2023 Опубликовано 9 января, 2023 · Жалоба Добрый день! Проверил. Не знаю как, но тоже работает. )) Компилятор, увидев сложение самое с собой ("ADD R17,R16"), вставил "LSL R16" 🙂 Инструкция SWAP в ассемблерах мне встречалась часто, но вот чтобы её использовать в Си для AVR, приходится подключать и применять intrinsic-функции, что привязано к конкретному железу и компилятору, т.е. неуниверсально. Потому без SWAP, конечно же, будет корректнее, на чистом Си: char cSetParity (char cin) { char ctemp; ctemp = cin; ctemp += cin; ctemp ^= cin; ctemp &= 0xAA; ctemp -= 0x9A; ctemp &= 0x88; ctemp -= 0x88; ctemp &= 0x80; cin |= ctemp; return cin; } Как говорится, "Ну вот, теперь можно в рамочку, и на стену". )) Спасибо! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 9 января, 2023 Опубликовано 9 января, 2023 · Жалоба 15 минут назад, vvppvv сказал: Инструкция SWAP в ассемблерах мне встречалась часто, но вот чтобы её использовать в Си для AVR, приходится подключать и применять intrinsic-функции, У меня конструкция byte = (byte >> 4)|(byte << 4); обычно оптимизировалась в swap. С включенной оптимизацией, разумеется (без оптимизации не компилирую). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
quark 48 9 января, 2023 Опубликовано 9 января, 2023 (изменено) · Жалоба 21 минуту назад, vvppvv сказал: Компилятор, увидев сложение самое с собой ("ADD R17,R16"), вставил "LSL R16" 🙂 Наверное, все-таки, "LSL R17". Но компилятору, конечно, виднее... 🙂 21 минуту назад, vvppvv сказал: Как говорится, "Ну вот, теперь можно в рамочку, и на стену". )) Для варианта на С, чтобы "на стену в рамочке", надо бы заменить: - 0x9A на +0x66, а - 0x88 на +0x78, чтобы совсем было по "фэншую", как в исходном алгоритме. Хотя, разницы нет, конечно. Изменено 9 января, 2023 пользователем quark Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vvppvv 0 9 января, 2023 Опубликовано 9 января, 2023 · Жалоба 3 minutes ago, quark said: Наверное, все-таки, "LSL R17". Но компилятору, конечно, виднее... Конкретно в том месте, компилятор просто решил использовать R16 как ctemp и R17 как cin. )) 7 minutes ago, quark said: Для варианта на С, чтобы "на стену в рамочке", надо бы заменить: - 0x9A на +0x66, а - 0x88 на +0x78, чтобы совсем было по "фэншую", как в исходном алгоритме. Ну, для понятия алгоритма (для, так сказать, визуализации) - да, корректней было бы написать сложение. Переписал. Это у же в кодах, по факту, будет SUBI. )) 398 char cSetParity (char cin) \ cSetParity: 399 { 400 char ctemp; 401 ctemp = cin; \ 00000000 2F10 MOV R17, R16 402 ctemp += cin; \ 00000002 0F10 ADD R17, R16 403 ctemp ^= cin; \ 00000004 2710 EOR R17, R16 404 ctemp &= 0xAA; \ 00000006 7A1A ANDI R17, 0xAA 405 ctemp += 0x66; \ 00000008 591A SUBI R17, 154 406 ctemp &= 0x88; \ 0000000A 7818 ANDI R17, 0x88 407 ctemp += 0x78; \ 0000000C 5818 SUBI R17, 136 408 ctemp &= 0x80; \ 0000000E 7810 ANDI R17, 0x80 409 cin |= ctemp; \ 00000010 2B01 OR R16, R17 410 return cin; \ 00000012 9508 RET 411 } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
quark 48 9 января, 2023 Опубликовано 9 января, 2023 (изменено) · Жалоба 21 минуту назад, vvppvv сказал: Ну, для понятия алгоритма (для, так сказать, визуализации) - да, корректней было бы написать сложение. Переписал. Это у же в кодах, по факту, будет SUBI. )) Первая строчка потерялась в программе: cin &= 0x7F; (ANDI R16,0x7F) Изменено 9 января, 2023 пользователем quark Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vvppvv 0 9 января, 2023 Опубликовано 9 января, 2023 (изменено) · Жалоба 29 minutes ago, quark said: Первая строчка потерялась в программе: cin &= 0x7F; (ANDI R16,0x7F) Да, это была просто перестраховка, в начале опытов. На самом деле входные символы используют только первую половину ASCII-кодов, так что седьмой (старший) бит теоретически на входе должен быть всегда 0. А на выходе должен дополнять байт до чётного количества битов. Алгоритм уже опробован на реальном железе (старые системы ЧПУ типа FANUC-6, FANUC-0mc) и показал полную работоспособность! )) Поэтому я эту команду обнуления убрал, как ненужную. Изменено 9 января, 2023 пользователем vvppvv Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
quark 48 9 января, 2023 Опубликовано 9 января, 2023 · Жалоба 15 минут назад, vvppvv сказал: Да, это была просто перестраховка, в начале опытов. На самом деле входные символы используют только первую половину ASCII-кодов, так что седьмой (старший) бит теоретически на входе должен быть всегда 0. А на выходе должен дополнять байт до чётного количества битов. Алгоритм уже опробован на реальном железе (старые системы ЧПУ типа FANUC-6, FANUC-0mc) и показал полную работоспособность! )) Поэтому я эту команду обнуления убрал, как ненужную. Для варианта "в рамочке на стене", все-таки, приведу полный вариант: char cSetParity (char cin) { char ctemp; cin &= 0x7F; ctemp = cin; ctemp += cin; ctemp ^= cin; ctemp &= 0xAA; ctemp += 0x66; ctemp &= 0x88; ctemp += 0x78; ctemp &= 0x80; cin |= ctemp; return cin; } Теперь совсем "конфетка" получилась - кроссплатформенная. 🙂 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vvppvv 0 9 января, 2023 Опубликовано 9 января, 2023 (изменено) · Жалоба Тогда уж, для универсальности и кросс-платформенности, придётся какие-нибудь ifdef'ы дописать, сколько бит в байте (7 или 8), и куда совать бит четности, на позицию 7-го бита, или в отдельный байт. Чтоб выполнялось: On 1/4/2023 at 10:12 PM, quark said: P.P.S. Если удалить из программы первую и последнюю строку (даже две последних), то алгоритм будет работать и для полного байта - для всех 8-ми бит. Конечный результат - бит четности - будет в 7-м бите R17. Тогда конфетка точно будет. 🙂 Изменено 9 января, 2023 пользователем vvppvv Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться