Модификация операндов машинной команды при линковке

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
ptr128
Вымогатель припоя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Модификация операндов машинной команды при линковке

Сообщение ptr128 »

Может я туплю, но длительные размышления и гугл пока не помогли. А суть проблемы в следующем.
Пусть у нас есть код. Не важно для какого МК. Важно то, что подавлющее большинство МК не позволяют использовать номер бита или номер порта в команде из регистра. Извольте непосредственно указать номер бита 0..7. Или извольте непосредственно указать номер порта 0..1F (для примера).
Иными словами, если на момент написания кода, номер бита или номер порта не известен, то вместо одной машинной команды "установить бит X в порту Y" нам нужно запрещать прерывания, читать весь порт в регистр, устанавливать в нем бит, записывать весь порт обратно и разрешать прерывания. Уродство (
Если речь идет о небольшой программке, которую мы все равно будем компилить со всеми файлами целиком, то вопрос решается средствами препроцессора.
А вот если хочется иметь статическую библиотеку, подключая ее LD, то для того, чтобы поменять в ней потом этот номер бита в команде приходится писать совершенно непотребный скрипт для LD. Настолько непотребный, что понимаешь, что не только чайнику теперь ты эту библиотеку не даш, но даже на гитхаб выложить постесняешься.

Отсюда вопрос:
Как понятно для того, кто будет использовать твою библиотеку, подменять, например, номера битов операнда в конкретных машинных командах, в зависимости от желаний пользователя?
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Реклама
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Модификация операндов машинной команды при линковке

Сообщение Аlex »

Как вариант - таблица с масками + лог. операции.
Но, в любом случае, если работа с битом выполняется через RMW, то будьте любезны организовать атомарный доступ. И не важно, через запрет/разрешение прерывания это будет, или каким-либо иным способом.
Реклама
Аватара пользователя
ptr128
Вымогатель припоя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Re: Модификация операндов машинной команды при линковке

Сообщение ptr128 »

Аlex писал(а):Как вариант - таблица с масками + лог. операции.
Про маски и логические операции я, естествнно, знаю.
Проблема не в том, как это сделать. Проблема в том, как это сделать быстро, когда высчитываешь каждый такт, чтобы вписаться во время какого-то цикла. Например, когда на AVR передаешь или принимаешь данные по SPI с нулевым делителем (FCLK/2). И надо вписаться в 16 тактов процессора между приемом или передачей байта.

Если на том же Z80 данную проблему я обходил модифицируя свой код при инициализации, то для гарвардской архитектуры такой вариант не приемлем (

Опишу проблему подробней. Имеем ST7735 и AVR. В AVR трансмиттер SPI без буферизации. Но есть буферизация в трансмиттере USART в MSPIM. Сам протокол обмена с ST7735 не совсем SPI. Он требует выставления D/C в низкий уровень для команд и в высокий для данных до передачи последнего бита. Сейчас есть код, который позволяет передавать в фреймбуфер ST7735 без пауз в CLK. Но если в этом коде модифицировать контроль за D/C так, чтобы для D/C можно было использовать любой пин (порт и бит), то паузы сразу возникают.

Вот функция, для понимания:

Код: Выделить всё

uint8_t st7735_spi_send_byte(uint8_t data, uint8_t status)
{
  asm volatile ( ";                             \n   \
WAIT_UDREn_ON_START%=:                          \n\t \
  lds   __tmp_reg__, %[UCSRnA_addr]   ;2        \n\t \
  sbrs  __tmp_reg__, %[UDREn_bit]     ;1/2      \n\t \
  rjmp  WAIT_UDREn_ON_START%=         ;2        \n\t \
  cli                                 ;1        \n\t \
  sts   %[UDRn_addr], %[data]         ;2   (7)  \n\t \
  sbrc  %[status], 1                  ;1/2      \n\t \
  rjmp  EXIT_ASM%=                    ;2   (10) \n\t \
  sbrc  %[status], 0                  ;1/2      \n\t \
  rjmp  SET_DC_FOR_DATA%=             ;2   (12) \n   \
; Set DC for command                            \n\t \
  sbis  %[port],%[pin]                ;1/2      \n\t \
  rjmp  EXIT_ASM%=                    ;2   (14) \n   \
WAIT_UDREn_FOR_COMMAND%=:                       \n\t \
  lds   __tmp_reg__, %[UCSRnA_addr]   ;2        \n\t \
  sbrs  __tmp_reg__, %[UDREn_bit]     ;1/2      \n\t \
  rjmp  WAIT_UDREn_FOR_COMMAND%=      ;2        \n\t \
  cbi   %[port],%[pin]                ;2        \n\t \
  rjmp  EXIT_ASM%=                    ;2   (21) \n   \
SET_DC_FOR_DATA%=:                              \n\t \
  sbic  %[port],%[pin]                ;1/2      \n\t \
  rjmp  SET_DC_STATUS%=               ;2   (15) \n   \
WAIT_UDREn_FOR_DATA%=:                          \n\t \
  lds   __tmp_reg__, %[UCSRnA_addr]   ;2        \n\t \
  sbrs  __tmp_reg__, %[UDREn_bit]     ;1/2      \n\t \
  rjmp  WAIT_UDREn_FOR_DATA%=         ;2        \n\t \
  sbi   %[port],%[pin]                ;2   (20) \n   \
SET_DC_STATUS%=:                                \n\t \
  sbr   %[status], 1                  ;1        \n\t \
EXIT_ASM%=:                                     \n\t \
  sei                                 ;1        \n\t \
  "
  : [status] "+r" (status)
  : [data] "r" (data),
    [UCSRnA_addr] "M" (_ST7735_SPI_UCSRnA_ADDRESS_),
    [UDREn_bit] "I" (UDRE0),
    [UDRn_addr] "M" (_ST7735_SPI_UDRn_ADDRESS_),
    [port] "I" (PIN_TO_PORTn_OFFSET(ST7735_SPI_DC_PIN_NO)),
    [pin] "I" (PIN_TO_PINn_BIT(ST7735_SPI_DC_PIN_NO))
  : "cc" );
  return(status);
}
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15575
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: Модификация операндов машинной команды при линковке

Сообщение BOB51 »

Для программ написанных под ассемблером такое не вызывает абсолютно никаких затруднений.
Причем для любого из компиляторов семейств mcs51, pic10/12/16/18, AVRmega/tiny.
Для этого используется или встроенный в текст библиотеки или автономный (на все файлы программы) участок текста с "определением имен" (xxxdef.inc или еще как назвать - в правилах применимых к конкретному компилятору).
Достаточно изменить значения в данном участке текста.
:beer:
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
ptr128
Вымогатель припоя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Re: Модификация операндов машинной команды при линковке

Сообщение ptr128 »

BOB51 писал(а): Достаточно изменить значения в данном участке текста.
:beer:
Вы не внимательно читали. Я же писал выше:
"Если речь идет о небольшой программке, которую мы все равно будем компилить со всеми файлами целиком, то вопрос решается средствами препроцессора.
А вот если хочется иметь статическую библиотеку, подключая ее LD, то для того, чтобы поменять в ней потом этот номер бита в команде приходится писать совершенно непотребный скрипт для LD. Настолько непотребный, что понимаешь, что не только чайнику теперь ты эту библиотеку не даш, но даже на гитхаб выложить постесняешься."

В приведенном примере кода и так пин определяется через препроцессор и макросами препроцессора вычисляется по нему порт и бит. Но изменить их после компиляции можно только совершенно неочевидным скриптом для LD, что мне и не нравится.
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Реклама
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15575
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: Модификация операндов машинной команды при линковке

Сообщение BOB51 »

Тоесть желанно изменение значений методом подстановки?
Тогда или работа через константу в памяти (ОЗУ, ЕЕПРОМ)/"скользящую маску"
или использование режима самопрограммирования (там, где оное имеется) для
модификации участка кода.
(Исключение mcs51с внешней памятью программ/данных).
Есть правда более экзотические "надстройки" вида имитации команд, считываемых из внешнего ПЗУ.
Но то режим симуляции встроенной ОС.
Как вариант весьма "близкого приближения" можно рассматривать систему команд и ядро STM8 и ARM.
Там возможно исполнение программы из области ОЗУ.
:beer:
Помимо прочего возможно и условное исполнение заранее заготовленных блоков кода в
зависимости от "кода конфигурации" (а сами блоки размещать с учетом возможности
оперативной замены методикой самопрограммирования, предусмотренной в данном типе МК).
8)
Реклама
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Модификация операндов машинной команды при линковке

Сообщение Аlex »

Про маски и логические операции я, естествнно, знаю.
Проблема не в том, как это сделать. Проблема в том, как это сделать быстро, когда высчитываешь каждый такт, чтобы вписаться во время какого-то цикла.
Значит плохо знаете. Если нужно быстро - лучше таблицы ничего не придумаешь.
С портами - через косвенную.
Аватара пользователя
ptr128
Вымогатель припоя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Re: Модификация операндов машинной команды при линковке

Сообщение ptr128 »

Аlex писал(а):Значит плохо знаете. Если нужно быстро - лучше таблицы ничего не придумаешь.
Не понял. Код я привел. В нем на установку/сброс/тестирование бита в порте уходит по 2 такта. По коду видно, что запас у меня всего 2 такта (14 из 16 уже использованы).
Просьба привести код, например, как за 4 такта можно установить или сбросить бит в порту, не указывая номер бита и оперируя только маской. У меня меньше 5 тактов никак не получается:

Код: Выделить всё

  ld  some_reg, X            ; 2
  ori some_reg, some_mask    ; 1
  st  X, some_reg            ; 2
Система команд, если еще не поняли, AVR8

Или честно признайте, что Вы плохо знаете, а не я )
Последний раз редактировалось ptr128 Пт окт 07, 2016 11:00:39, всего редактировалось 1 раз.
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15575
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: Модификация операндов машинной команды при линковке

Сообщение BOB51 »

Скорее тут "инерция восприятия" после опыта работ с i8080/86 и/или Z80,
где программа размещается в области ОЗУ.
У МК изменить содержимое ячейки ПЗУ весьма муторное занятие (если вообще возможное
для большинства "простых малолапых").
Посему и приемы программирования/алгоритмы строятся несколько иначе.
Относительно высчитывания каждого такта по недостатку быстродействия - также весьма спорный момент
ибо большинство современных МК имеют весьма высокое быстродействие с обязательным конвеером предвыборки команд.
В тех же случаях, когда надо "лаподрыг по максимуму" для МК действует правило применения готовых функциональных аппаратных блоков - просто нужно подбирать соответствующее семейство и/или модель МК в пределах текущего выбранного семейства.
Может просто "умение правильно приготовить" пока еще не преодолело стереотип?
:dont_know:
Кистати...
а 8МГц типовой тактовой (0,000000125 секунды на такт/операцию) неуж-то мало?
не говоря уже о 16МГц (или 63МГц при ПЛЛ для периферии)...
:wink:
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Модификация операндов машинной команды при линковке

Сообщение Аlex »

как за 4 такта можно установить или сбросить бит в порту, не указывая номер бита и оперируя только маской.
Никак. Вы хотите и рыбку съесть, и ....... .
Вообще, речи о 4 тактах не было. Было о
ptr128 писал(а):И надо вписаться в 16 тактов процессора
Так что, ставьте правильно задачу, чтобы Вас понимали и не разводили лишних демагогий.
Или честно признайте, что Вы плохо знаете, а не я )
Признаюсь. Вы удовлетворены ?
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18629
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Модификация операндов машинной команды при линковке

Сообщение ARV »

ptr128 писал(а):У меня меньше 5 тактов никак не получается
тут может быть несколлько вариантов:
1. хранить маску в регистре, чтобы не загружать ее каждый раз
2. использовать "хаки" архитектуры, например, для многих AVR8 переключение (т.е. смена состояния на противоположное) битов PORTx происходит при записи лог.1 в PINx
3. проблема зарыта "в верхнем уровне": от изначально неоправданных надежд на архитектуру до некорректного или не оптимального алгоритма. т.е. проблема 16 тактов, возможно, на самом деле может быть обойдена, если изменить весь алгоритм.

что конкретно вам посоветовать, я не знаю. но мне кажется, кроме перечисленных вариантов, ничего не придумать. попытка ковыряться в бинарном коде - это с моей т.з. вообще не вариант (см. п.3).
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
ptr128
Вымогатель припоя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Re: Модификация операндов машинной команды при линковке

Сообщение ptr128 »

BOB51 писал(а):Скорее тут "инерция восприятия" после опыта работ с i8080/86 и/или Z80,
где программа размещается в области ОЗУ.
Не спорю, что с гарвардской архитектурой мало дела имел и не долюбливаю ее.
У МК изменить содержимое ячейки ПЗУ весьма муторное занятие (если вообще возможное
для большинства "простых малолапых").
Возможно, но блоками. Я уже рассматривал этот вариант, но отложил пока, как запасной.
Относительно высчитывания каждого такта по недостатку быстродействия - также весьма спорный момент
А что тут спорить? Я же реальный пример привел при частоте SPI FCLK/2. То есть, между байтами есть по 16 тактов. Вне зависимости от тактовой частоты МК.
МК в пределах текущего выбранного семейства.
В рамках семейства AVR они все такие. Тут только на 32-х битный, разве что переходить. Но на данный момент, я задачу решаю именно для восьмибитной ATMega

Пока получилось, что хотел, но с фиксацией всех пинов на этапе компиляции: https://goo.gl/photos/BFXcPbRXhXge5J9V7
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15575
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: Модификация операндов машинной команды при линковке

Сообщение BOB51 »

ptr128 писал(а):...
Относительно высчитывания каждого такта по недостатку быстродействия - также весьма спорный момент
А что тут спорить? Я же реальный пример привел при частоте SPI FCLK/2. То есть, между байтами есть по 16 тактов. Вне зависимости от тактовой частоты МК....
А неужели сама FCLK не может быть "выставлена повыше" ?
Ведь тогда при соответствующем сохранении скорости SPI количество команд на заданный интервал времени возрастает.
:wink:
Аватара пользователя
ptr128
Вымогатель припоя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Re: Модификация операндов машинной команды при линковке

Сообщение ptr128 »

Аlex писал(а):
как за 4 такта можно установить или сбросить бит в порту, не указывая номер бита и оперируя только маской.
Никак. Вы хотите и рыбку съесть, и ....... .
Вообще, речи о 4 тактах не было. Было о
ptr128 писал(а):И надо вписаться в 16 тактов процессора
Так что, ставьте правильно задачу, чтобы Вас понимали и не разводили лишних демагогий.
Я же код привел, в котором явно видно, что осталось только 2 такта из 16-ти!

И вообще задача изначально ставилась совсем не так. Вопрос был:
"Как понятно для того, кто будет использовать твою библиотеку, подменять, например, номера битов операнда в конкретных машинных командах, в зависимости от желаний пользователя?"
А лишняя демагогия возникла как раз когда Вы написали "Как вариант - таблица с масками + лог. операции.", хотя я спрашивал не о том, как работать с битами, а как сохранить работу с битами командами AVR cbi/sbi/sbic/sbis

Добавлено after 2 minutes 30 seconds:
BOB51 писал(а):
ptr128 писал(а):...
при частоте SPI FCLK/2
А неужели сама FCLK не может быть "выставлена повыше" ?
Ведь тогда при соответствующем сохранении скорости SPI количество команд на заданный интервал времени возрастает.
:wink:
Нет. Когда SPI_CLK=FCLK/2, то на передачу одного бита по SPI будет уходить всегда два такта процессора при любой частоте FCLK
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15575
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: Модификация операндов машинной команды при линковке

Сообщение BOB51 »

От уж...
итак имеем две варьируемые величины - скорость обмена на аппаратном модуле SPI и собственно скорость исполнения команд (частота системного тактового генератора плюс предделитель).
Итог - кручу каждую из них (в разумных пределах) как вверх, так и вниз.
8)
имеем стабильное значение для SPI
подняв частоту системного тактирования автоматически для сохранения того же исходного значения для модуля SPI необходимо также изменить его коэффициент.
Или у Вас программный SPI с частотой в 8МГЦ применяется?
:tea:
Последний раз редактировалось BOB51 Пт окт 07, 2016 11:25:30, всего редактировалось 1 раз.
Аватара пользователя
ptr128
Вымогатель припоя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Re: Модификация операндов машинной команды при линковке

Сообщение ptr128 »

ARV писал(а):
ptr128 писал(а): 3. проблема зарыта "в верхнем уровне": от изначально неоправданных надежд на архитектуру до некорректного или не оптимального алгоритма. т.е. проблема 16 тактов, возможно, на самом деле может быть обойдена, если изменить весь алгоритм.
Проблема 16 тактов как раз решена. И обмен по SPI у меня сейчас происходит с необходимой скоростью. И, в результате, получается не только писать в фреймбуфер ST7735, но и читать из него, что, по утверждению Adafruit невозможно. У меня получилось.
Проблема в том, как сделать этот результат конфигурируемым на уровне библиотеки.

Добавлено after 2 minutes 24 seconds:
BOB51 писал(а): предделитель
Предделитель 0. На 16 МГц. 1 можно поставить для сохранения той же скорости обмена при тактовой 32МГц, которая для ATMega не доступна.

Господа (и дамы если есть)! Убедительная просьба, давайте не обсуждать, как можно сделать иначе но медленней.
Вопрос то был совсем о другом. Можно ли обойтись без повторной компиляции исходников при смене пина или нет?
Вариант со скриптом LD мне не понравился тем, что его писать нужно отдельно и править отдельно.
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15575
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: Модификация операндов машинной команды при линковке

Сообщение BOB51 »

Библиотека всегда генерирует фиксированный код согласно исходного текста.
Для его изменений используется препроцессор и дефайны.
Касательно "игры с подстановкой кодов согласно смены условий работы программы" при исполнении программы в самом кристалле естественно прийдется использовать особенности архитектуры МК.
Для АВР тини/мега их системы команд для типовой области применений вполне достаточно.
:beer:

"Можно ли обойтись без повторной компиляции исходников при смене пина или нет?"

можно
использовать надлежащим образом измененный алгоритм
использовать аппаратный модуль SPI
8)
Последний раз редактировалось BOB51 Пт окт 07, 2016 11:36:53, всего редактировалось 1 раз.
Аватара пользователя
ptr128
Вымогатель припоя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Re: Модификация операндов машинной команды при линковке

Сообщение ptr128 »

BOB51 писал(а): ARM.
Там возможно исполнение программы из области ОЗУ.
Как? Я не в курсе

Добавлено after 3 minutes 27 seconds:
BOB51 писал(а):Библиотека всегда генерирует фиксированный код согласно исходного текста.
Для его изменений используется препроцессор и дефайны.
Ложное утверждение. Операнды команд могут быть изменены LD при компоновке. Точнее даже добиться, чтобы они не были нигде не изменены LD чрезвычайно сложно )
И я могу дать инструкции LD в его скрипте, как изменить операнды команд работы с битами. Я не могу добиться, чтобы такие инструкции пришли к LD от компилятора.
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15575
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: Модификация операндов машинной команды при линковке

Сообщение BOB51 »

Линкер у ассемблера АВР?
:))
это для ПИК, MCS51 (только не в варианте атмелевского c51asm!!!) линкер отдельной единицей и с некоторым описанием имеется.
В типовой авр-студии сей компонент иначе как "по умолчанию" не используется.
8)
Может там чего в вариациях с СИ - эта область мне неведома.
:sleep:
Аватара пользователя
ptr128
Вымогатель припоя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Re: Модификация операндов машинной команды при линковке

Сообщение ptr128 »

BOB51 писал(а): "Можно ли обойтись без повторной компиляции исходников при смене пина или нет?"

можно
использовать надлежащим образом измененный алгоритм
использовать аппаратный модуль SPI
8)
Догма? Или где код?
И не позорьтесь публично. Код ведь приведен. И даже чайнику должно быть понятно, что программным SPI тут и не пахнет )
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Ответить

Вернуться в «Разные вопросы по МК»