LINUX.ORG.RU

Генерация кода на препроцессоре C


0

1

Ситуация такая - между отправлением байт по последовательному порту нужно очень четко выдержать время. Все происходит на микроконтроллере, все таймеры уже заняты, остаются только нопы, благо времена не большие. Проблема в том, что возможно придется изменить битрейт и паузу между байтами, поэтому не хочется хардкодить. Хочу сделать макрос который в нужном месте сгенерит нужное количество нопов, но не могу додуматься как такое сделать и можно ли вообще? В идеале должно получиться что-то такое #define NOPS(x) ... и чтоб оно генерило x нопов. Нид хелп.


CPP такого не умеет.

Попробуй генерацию кода без препроцессора.

schizoid ★★★
()


#define NOPS(x) \
__asm(\
".rept " #x «\n» \
«nop\n» \
".endr\n" \
)

test()
{
NOPS(20);
}

$ gcc -S testik.c
$ as -alm testik.s
GAS LISTING testik.s page 1


1 .file «testik.c»
2 .text
3 .globl test
4 .type test, @function
5 test:
6 0000 55 pushl %ebp
7 0001 89E5 movl %esp, %ebp
8 #APP
9 # 10 «testik.c» 1
1 #define NOPS(x) \
2 __asm(\
3 ".rept " #x «\n» \
4 «nop\n» \
5 ".endr\n" \
6 )
7
8 test()
9 {
10 NOPS(20);
10 0003 90 > nop
10 >
10 0004 90 > nop
10 >
10 0005 90 > nop
....
10 0014 90 > nop
10 >
10 0015 90 > nop
10 >

GAS LISTING testik.s page 2


10 0016 90 > nop
11 }
12
13 ...
10 .rept 20
11 nop
12 .endr
13
14 # 0 «» 2
15 #NO_APP
16 0017 5D popl %ebp
17 0018 C3 ret
18 .size test, .-test
19 .ident «GCC: (GNU) 4.4.5 20101112 (Red Hat 4.4.5-2)»
20 .section .note.GNU-stack,"",@progbits

io ★★
()

Если известен какой-то лимит на количество nop, то можно на чистом cpp, но более гумозно чем с rept-ом.

io ★★
()
Ответ на: комментарий от io

Спасибо, но .rept не катит, тк компилятор не gcc.

Если известен какой-то лимит на количество nop, то можно на чистом cpp, но более гумозно чем с rept-ом.

Какой? Я кое что придумал, но препроцессор не переваривает строки больше 5к символов.

CFA
() автор топика
Ответ на: комментарий от CFA

Если у препроцессора сильные ограничения по длине строки, то в этой ситуации его лучше не использовать.

Хотя можно иметь пачку, например, nop1, nop2 ... nop63 которые будут порождать нужное число nop-ов (ассемблерные вставки-то хоть какие-нибудь есть?). Ничто не мешает им использовать друг друга и даже вызывать их из общего NOPS макро. 5k скорее всего для тупого решения хватит.

Можно, также иметь nop1, nop2, nop4, nop8 .... nop64 макро и пользоваться ими в стиле (x == 64 ? (NOP64, 0) : 0) - ожидается более сложная конструкция с массой if. Реализуемость зависит от возможностей вставки ассемблера.

Есть и более забавные варианты.

rept это возможность не gcc, а ассемблера! Вставка ассемблера работает? В большинстве ассемблеров имеется возможность дублирования набора строк нужное число раз. Как альтернатива масса ассемблеров в зависимости от секции при изменении позиции генерирует либо набор нулей (секция данных), либо набор nop-ов. Но это уже зависит от ассемблера. М.б. что-то типа .=.+20 , указание org и т.п.

io ★★
()
Ответ на: комментарий от io

Тогда можно просто брать двоичное разложение желаемого числа нопов и вставлять соответствующую комбинацию: 5 = 1 + 4 => вместо nop5() пишем { nop1(); nop4(); }.

dave ★★★★★
()
Ответ на: комментарий от dave

«Ничто не мешает им использовать друг друга» - я рад что пример так быстро возникает :-)

io ★★
()
Ответ на: комментарий от CFA
#define NOP0(x)
#define NOP1(x) __asm("nop;\n");
#define NOP2(x) NOP1(x);__asm("nop;\n");
#define NOP3(x) NOP2(x);__asm("nop;\n");
#define NOP4(x) NOP3(x);__asm("nop;\n");
#define NOP5(x) NOP4(x);__asm("nop;\n");
#define NOP6(x) NOP5(x);__asm("nop;\n");
#define NOP7(x) NOP6(x);__asm("nop;\n");
#define NOP8(x) NOP7(x);__asm("nop;\n");
#define NOP9(x) NOP8(x);__asm("nop;\n");
#define NOP10(x) NOP9(x);__asm("nop;\n");
#define NOP20(x) NOP10(x);NOP10(x);
#define NOP30(x) NOP20(x);NOP10(x);
#define NOP40(x) NOP30(x);NOP10(x);
#define NOP50(x) NOP40(x);NOP10(x);
#define NOP60(x) NOP50(x);NOP10(x);
#define NOP70(x) NOP60(x);NOP10(x);
#define NOP80(x) NOP70(x);NOP10(x);
#define NOP90(x) NOP80(x);NOP10(x);

#define NOP(ten,one) NOP##ten##0();NOP##one();

// Usage : NOP(2,3);

MKuznetsov ★★★★★
()
Ответ на: комментарий от staseg

При этом сами макры надо генерировать. Вот такой особенный генератор кода :)

staseg ★★★★★
()
Ответ на: комментарий от io

ассемблерные вставки-то хоть какие-нибудь есть?

В большинстве ассемблеров имеется возможность дублирования набора строк нужное число раз.

Спасибо! В ассемблере нашлось, что надо.

CFA
() автор топика
Ответ на: комментарий от MKuznetsov

while(something_not_ready)
NOP(1,0); - не аккуратно будет

io ★★
()

Убогих костылей тред.

buddhist ★★★★★
()

> все таймеры уже заняты, остаются только нопы

а с циклами что случилось? тоже все заняты?

arsi ★★★★★
()

тут есть один нюанс. Таймер генерит прерывания через равные промежутки времени. А твои нопы генерят промежутки времени между их вызовами. Т.е. ты не учитываешь время потраченное на работу с портом.

Криво всё это. Может написать шедулер? Тогда хватит одного таймера. И, я уверен, уже кто-то такое написал, просто надо поискать.

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

А твои нопы генерят промежутки времени между их вызовами.

Какие еще вызовы нопов? nop это инструкция процессора, которая в течении (обычно) одного цикла ничего не делает. Мне надо между отправками байт выдержать паузу в 80 тактов, и я хочу во время компиляции сгенерить портянку этих нопов в количестве 78 штук (-2 такта на команду записи байта в порт). Никто не мешает, тк прерывания в этот момент закрыты.

Может написать шедулер? Тогда хватит одного таймера. И, я уверен, уже кто-то такое написал, просто надо поискать.

Не тот это микроконтроллер чтоб писать шедулеры - 224 байта оперативной памяти и производительность меньше 1кк инструкций в секунду.

а с циклами что случилось? тоже все заняты?

Циклом трудно будет четко выдержать нужное количество тактов. Точнее не трудно, но если это число придется изменить, то опять надо будет высчитывать нужное количество итераций.

CFA
() автор топика
Ответ на: комментарий от CFA

> но если это число придется изменить, то опять надо будет высчитывать нужное количество итераций.

что там высчитывать… замерь, сколько проц выдает богомипсов и используй их в расчётах количества итераций, хоть в рантайме, хоть на этапе компиляции.

arsi ★★★★★
()
Ответ на: комментарий от CFA

Не тот это микроконтроллер чтоб писать шедулеры - 224 байта оперативной памяти

ой ё...

true_admin ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

контроллер ADuC831, компилятор кейл

CFA
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.