2013-09-12 4 views
8

В попытке сделать GCC не генерированием операцию загрузки-изменение-магазин каждый раз, когда я делаю |= или &=, я определил следующие макросы:Получение GCC оптимизировать сборку руки

#define bset(base, offset, mask) bmanip(set, base, offset, mask) 

#define bclr(base, offset, mask) bmanip(clr, base, offset, mask) 

#define bmanip(op, base, offset, mask) \ 
asm("pshx");\ 
asm("ldx " #base);\ 
asm("b" #op " " #offset ",x " #mask);\ 
asm("pulx") 

И они прекрасно работают ; дизассемблированная бинарность идеальна.

Проблема возникает, когда я использую более одного в последовательности:

inline void spi_init() 
{ 
    bset(_io_ports, M6811_DDRD, 0x38); 
    bset(_io_ports, M6811_PORTD, 0x20); 
    bset(_io_ports, M6811_SPCR, (M6811_SPE | M6811_DWOM | M6811_MSTR)); 
} 

Это приводит к:

00002227 <spi_init>: 
    2227:  3c    pshx 
    2228:  fe 10 00  ldx  0x1000 <_io_ports> 
    222b:  1c 09 38  bset 0x9,x, #0x38 
    222e:  38    pulx 
    222f:  3c    pshx 
    2230:  fe 10 00  ldx  0x1000 <_io_ports> 
    2233:  1c 08 20  bset 0x8,x, #0x20 
    2236:  38    pulx 
    2237:  3c    pshx 
    2238:  fe 10 00  ldx  0x1000 <_io_ports> 
    223b:  1c 28 70  bset 0x28,x, #0x70 
    223e:  38    pulx 
    223f:  39    rts 

Есть ли способ, чтобы получить GCC (3.3.6-m68hc1x-20060122) автоматически оптимизировать избыточные операции стека?

ответ

9

gcc всегда выдаст инструкции по сборке, которые вы говорите, чтобы испустить. Поэтому вместо того, чтобы явно писать код для загрузки регистров со значением, которое вы хотите манипулировать, вместо этого вы хотите сказать gcc, чтобы сделать это от вашего имени. Вы можете сделать это с ограничениями регистра.

К сожалению, генератор кода 6811, похоже, не является стандартной частью gcc --- Я не рассматриваю документацию в руководстве. Поэтому я не могу указать вам на конкретный бит документа. Но общий бит вам нужно прочитать здесь: http://gcc.gnu.org/onlinedocs/gcc-4.8.1/gcc/Extended-Asm.html#Extended-Asm

Синтаксис является причудливым, но краткое изложение:

asm("instructions" : outputs : inputs); 

... где inputs и outputs списки ограничений, которые говорят НКУ, какое значение поставить куда. Классическим примером является:

asm("fsinx %1,%0" : "=f" (result) : "f" (angle)); 

f указывает, что названное значение должно перейти в точку регистра плавающей; = указывает, что это выход; то имена регистров заменяются в инструкции.

Таким образом, вы, вероятно, хотите что-то вроде этого:

asm("b" #op " " #offset ",%0 " #mask : "=Z" (i) : "0" (i)); 

... где i это переменная, содержащая значение, которое вы хотите изменить. Z вам нужно искать в документах 6811 gcc --- это ограничение, которое представляет собой регистр, который действителен для команды asm, которая генерируется. 0 указывает, что входные данные разделяют регистр с выходом 0 и используются для значений чтения/записи.

Поскольку вы сказали gcc, какой регистр вы хотите, i, он может интегрировать эти знания в свой распределитель регистров и найти наименьший из возможных способов получить i, где вам это нужно с наименьшим количеством кода. (Иногда нет дополнительного кода.)

Сборник gcc inline глубоко искажен и странный, но довольно мощный. Стоит потратить некоторое время, чтобы полностью понять систему ограничений, чтобы наилучшим образом использовать ее.

(Кстати, я не знаю кода 6811, но вы забыли поставить результат операции где-нибудь? Я бы ожидал увидеть stx в соответствии с ldx.)

Обновление: О, я вижу, что делает bset --- он записывает результат обратно в ячейку памяти, не так ли? Это все еще выполнимо, но это немного больнее. Вам нужно сообщить gcc, что вы изменяете эту ячейку памяти, чтобы она не полагалась на какое-либо кешированное значение. Вам нужно будет иметь выходной параметр с ограничением m, который представляет это местоположение. Проверьте документы.

+0

Не удивительно, что вы его не нашли; Поддержка m68hc11 была устарела в 4.6 и удалена в 4.7. Мне не нужна ценность 'X' после того, как я закончу; 'bset' (бит SET) и' bclr' (бит CLeaR) имеют только нулевые страницы и индексированные режимы адресации, поэтому сохраняются, загружаются и восстанавливаются индексный регистр. Я проверю документы, спасибо. –

+0

После нескольких экспериментов я теперь убежден, что это правильное решение. У меня проблемы с индексированной адресацией, но я отправлю это как отдельный вопрос. –