Ну только не поэтому... Для х86х gcc тоже код генерит, хотя там такой же разнобой с регистрами, что на Z80...Сообщение от yoko_ono
Да и в AVRке регистры r0, r1-r15, r16-r25 и r26-r31 далеко не равноправны...
Ну только не поэтому... Для х86х gcc тоже код генерит, хотя там такой же разнобой с регистрами, что на Z80...Сообщение от yoko_ono
Да и в AVRке регистры r0, r1-r15, r16-r25 и r26-r31 далеко не равноправны...
С любовью к вам, Yandex.Direct
Размещение рекламы на форуме способствует его дальнейшему развитию
Вы работаете с армом и поэтому решили, что gcc точился под арм? Браво, вашей логике позавидуют даже блондинки...Сообщение от Vitamin
Да что вы.ЗЫ. За вами должок!![]()
По крайней мере в ia32 можно говорить, что имеющиеся 7 регистров более-менее равноправны, за редкими исключениями вроде 8-битных загрузок и умножений-делений.Сообщение от SfS
И что? Их же 32, и со всеми (абсолютно со всеми) возможны 2-адресные логические и арифметические операции. Неравноправность только в операциях с константами и 16-битными указателями в память.Да и в AVRке регистры r0, r1-r15, r16-r25 и r26-r31 далеко не равноправны...
Почемуто вы опустили предыдущую фразу тов. NovaStorm, где он сказал, что gcc заточен под х86. Почему-то она вопросов не вызвала. А вот мое возражение, в котором в качестве аргумента я привел АРМ, сразу "обидело державу". Вы кроме х86 больше ни на чем не работали?Сообщение от yoko_ono
Официально разрешаю завидовать даже вам.Сообщение от yoko_ono
Да. Вы меня обвинили в недостаточном знании возможностей ALASM'а (с чем, собственно согласен), но никак не доказали свою состоятельность в этом вопросе. Вместо этого довольно топорно увильнули от беседы. Так что...Сообщение от yoko_ono
а мой транслятор PC110 Си->Z80 Asm у когонить сохранился? а то че то меня ностальжи мучать начала, не моглиб прислать на rrg<собака>forth.org.ru
Потому, что это никому не нужно. В новых разработках Z80 никто не использует, поэтому и порт для gcc не делают. gcc например поддерживает 68hc11, 68hc12 и т.п., хотя поддержка этих контроллеров сложнее чем поддержка Z80.Сообщение от SfS
(оффтоп) А у хваленого недориск-проца 6502 ваще полный мрак с ЯВУ, особенно компиляторамиСообщение от andrews
(/оффтоп)
Скачал компилятор IAR и решил протестить. Весьма серьезная штука. Имеется довольно развитая среда разработки, куча библиотек.
Компилятор был протестирован в двух режимах работы- с максимальной оптимизацией по скорости и по размеру.
Из влияющих на кодогенерацию настроек:
Large model, enable undocumented instructions, use alternate register set, use rst-functions, static allocation of 'autos', language extensions, 'char' is 'signed char'.
Для начала быстрая версия кода:
0. Пролог. Ничего особого
1. Размножение констант и копийКод:PUSH BC PUSH DE
2. Свертка константКод:;j4 = 2; LD HL,2 LD (j4),HL ;if( i2 < j4 && i4 < j4 ) ; i2 = 2; ;Весьма и весьма странная конструкция! ;Для правильного знакового сравнения кажется ;Размножение константы только на первом сравнении LD BC,32770 LD HL,(i2) LD A,B XOR H LD H,A SBC HL,BC JR NC,?0011 LD BC,(j4) LD HL,(i4) ;почему не AND A?.. OR 128 SBC HL,BC JP PO,?0088 XOR H ?0088: JP P,?0011 ?0013: ?0012: ?0010: LD HL,2 LD (i2),HL ?0011: ;j4 = k5; ;if( i2 < j4 && i4 < j4 ) ; i5 = 3; ;а здесь имеет просто достаточно качественные регистровые переменные LD HL,(k5) LD (j4),HL LD C,L LD B,H LD HL,(i2) OR 128 SBC HL,BC JP PO,?0089 XOR H ?0089: JP P,?0015 LD HL,(i4) OR 128 SBC HL,BC JP PO,?0090 XOR H ?0090: JP P,?0015 ?0017: ?0016: ?0014: LD HL,3 LD (i5),HL ?0015:
Деление на 0 было определено на этапе компиляции. Пришлось объявить NO_ZERO_DIVIDEКод:;i3 = 1 + 2; LD HL,3 LD (i3),HL ;flt_1 = 2.4 + 6.3; LD BC,16651 LD HL,13107 LD (flt_1),HL LD (flt_1+2),BC ;i2 = 5; LD HL,5 LD (i2),HL ;j2 = i + 0; ;k2 = i / 1; ;i4 = i * 1; ;Красавец! LD HL,(i) LD (j2),HL LD (k2),HL LD (i4),HL ;i5 = i * 0; LD HL,0 LD (i5),HL
3. Лишнее присваиваниеКод:;flt_3 = 2.4 / 1.0; LD BC,16409 LD HL,39322 LD (flt_3),HL LD (flt_3+2),BC ;flt_4 = 1.0 + 0.0000001; LD BC,16256 LD HL,1 LD (flt_4),HL LD (flt_4+2),BC ;flt_5 = flt_6 * 0.0; ;умножение на 0 он благополучно распознал ;но как выкрутился с загрузкой!!! LD C,H LD B,H DEC HL LD (flt_5),HL LD (flt_5+2),BC ;flt_6 = flt_2 * flt_3; ;4 байта через стек, 4 в регистрах иначе никак... LD HL,16409 PUSH HL LD HL,39322 PUSH HL LD BC,(flt_2+2) LD HL,(flt_2) CALL ?F_MUL_L04 LD (flt_6),HL LD (flt_6+2),BC
4. Снижение мощностиКод:;k3 = 1; ;k3 = 1; ;в Багдаде все спокойно... LD HL,1 LD (k3),HL
5. Простой циклКод:;k2 = 4 * j5; ;нормально... LD HL,(j5) ADD HL,HL ADD HL,HL LD (k2),HL ;for( i = 0; i <= 5; i++ ) ; ivector4[ i ] = i * 2; LD HL,0 ?0095: LD (i),HL ?0020: ;опять эти интересные сравнения... ;судя по всему, там где не требуются знаковые вычисления, ;лучше честно писать unsigned вместо int LD C,L LD B,H LD HL,5 OR 128 SBC HL,BC JP PO,?0091 XOR H ?0091: JP M,?0019 ?0021: LD L,C LD H,B ADD HL,HL ;снижения мощности нет, но цикл в целом весьма достойный LD BC,ivector4 ADD HL,BC PUSH HL LD HL,(i) ADD HL,HL LD C,L LD B,H POP HL LD (HL),C INC HL LD (HL),B LD HL,(i) INC HL JR ?0095 ?0019:
6. Управление переменной индукции циклаКод:;j5 = 0; LD HL,0 LD (j5),HL ;k5 = 10000; LD HL,10000 LD (k5),HL ;do { ; k5 = k5 - 1; ;много лишнего... подозреваю что дело опять в знаковости ?0025: LD HL,65535 LD BC,(k5) ADD HL,BC LD (k5),HL ; j5 = j5 + 1; LD HL,1 LD BC,(j5) ADD HL,BC LD (j5),HL ; i5 = (k5 * 3) / (j5 * constant5); ;на 3 умножил достойно LD HL,(k5) LD C,L LD B,H ADD HL,HL ADD HL,BC EX DE,HL ;и на 5 тоже LD HL,(j5) LD C,L LD B,H ADD HL,HL ADD HL,HL ADD HL,BC LD C,L LD B,H CALL ?SS_DIV_L02 LD (i5),DE ;} while ( k5 > 0 ); ;опять эти интересные игры с флагами.... LD BC,(k5) LD HL,0 OR 128 SBC HL,BC JP PO,?0092 XOR H ?0092: JP M,?0025 ?0023:
7. Глубокие подвыраженияКод:;for( i = 0; i < 100; i++ ) ; ivector5[ i * 2 + 3 ] = 5; ; хороший добротный пролог цикла ?0023: LD HL,0 ?0096: LD (i),HL ?0027: LD BC,32868 LD A,B XOR H LD H,A SBC HL,BC JR NC,?0026 ?0028: ;ну просто замечательно сделано!!! лучше не придумаешь LD HL,(i) ADD HL,HL ADD HL,HL LD BC,ivector5+6 ADD HL,BC LD (HL),5 INC HL LD (HL),0 LD HL,(i) INC HL JR ?0096 ?0026:
8. Генерация адреса переменной с константным индексомКод:;if( i < 10 ) ; j5 = i5 + i2; ;else ; k5 = i5 + i2; ;не совсем, но имеется- загрузка вынесена за скобки LD BC,32778 LD HL,(i) LD A,B XOR H LD H,A SBC HL,BC LD HL,(i2) LD BC,(i5) JR NC,?0031 ?0030: ADD HL,BC LD (j5),HL JR ?0032 ?0031: ADD HL,BC LD (k5),HL ?0032:
9. Удаление общих подвыраженийКод:;ivector[ 0 ] = 1; /* генерация константного адреса */ LD HL,1 LD (ivector),HL ;ivector[ i2 ] = 2; /* значение i2 должно быть скопировано*/ LD HL,(i2) ADD HL,HL LD BC,ivector ADD HL,BC LD (HL),2 INC HL LD (HL),0 ;ivector[ i2 ] = 2; /* копирование регистров */ ;нет копирования... только база остается LD HL,(i2) ADD HL,HL ADD HL,BC LD (HL),2 INC HL LD (HL),0 ;ivector[ 2 ] = 3; /* генарация константного адреса */ LD HL,3 LD (ivector+4),HL
Код:;if(( h3 + k3 ) < 0 || ( h3 + k3 ) > 5 ) ;нет выделения. зато одна переменная прописалась в регистрах LD HL,(k3) LD BC,(h3) AND A ADC HL,BC BIT 7,H JR NZ,?0035 LD HL,(k3) ADD HL,BC LD C,L LD B,H LD HL,5 OR 128 SBC HL,BC JP PO,?0093 XOR H ?0093: JP P,?0034 ; printf("Common subexpression elimination\n"); ;gcc например, printf без параметров сокращает до puts. но пойдет и так ?0033: LD HL,?0037 PUSH HL CALL printf POP AF JR ?0038 ;else { ; m3 = ( h3 + k3 ) / i3; ;нет выделения... ?0034: LD HL,(k3) LD BC,(h3) ADD HL,BC EX DE,HL LD BC,(i3) CALL ?SS_DIV_L02 LD (m3),DE ; g3 = i3 + (h3 + k3); LD HL,(k3) LD DE,(h3) ADD HL,DE ADD HL,BC LD (g3),HL ?0038: ;}
10. Вынесение инвариантного кода
11. Вызов функции с аргументамиКод:;for( i4 = 0; i4 <= max_vector; i4++) ; ivector2[ i4 ] = j * k; LD HL,0 ?0097: LD (i4),HL ?0040: LD C,L LD B,H LD HL,2 OR 128 SBC HL,BC JP PO,?0094 XOR H ?0094: JP M,?0039 ?0041: ;нет вынесения, умножение на каждом цикле LD HL,ivector2 ADD HL,BC LD A,(j) PUSH AF LD A,(k) LD B,A POP AF CALL ?C_MUL_L01 LD (HL),A LD HL,(i4) INC HL JR ?0097 ?0039:
12. Вызов функции без аргументов, эпилогКод:;dead_code( 1, "This line should not be printed" ); ;все чин-чином: справа налево, в регистрах LD BC,?0043 LD DE,1 CALL dead_code
13. Проверка недостижимого кода и лишних присваиванийКод:;unnecessary_loop(); ;ничего особого. в конце очистка стека и возврат по дну(!) CALL unnecessary_loop POP HL POP HL RET
14.Ненужный циклКод:;void dead_code(int a, char *b ) ;{ ;int idead_store; ;idead_store = a; dead_code: PUSH BC PUSH DE LD HL,0 ADD HL,SP LD D,E INC HL LD H,(HL) LD L,D LD (?0044),HL ;if( 0 ) ; printf( "%s\n", b ); ;нет проверки.... XOR A JR Z,?0046 ?0045: PUSH BC LD HL,?0047 PUSH HL CALL printf POP AF POP AF ?0046: ;} /* Конец dead_code */ POP HL POP HL RET
15. Слияние цикловКод:;void unnecessary_loop() ;{ ;int x; ;x = 0; PUSH BC LD HL,0 LD (?0044+2),HL ;for( i = 0; i < 5; i++ ) ?0098: LD (i),HL ?0049: LD BC,32773 LD A,B XOR H LD H,A SBC HL,BC JR NC,?0048 ?0050: ; k5 = x + j5; ;нет проверки... вычисления каждую итерацию LD HL,(j5) LD BC,(?0044+2) ADD HL,BC LD (k5),HL LD HL,(i) INC HL JR ?0098 ?0048: ;} /* Конец unnecessary_loop */ ?0048: POP BC RET
16. Разворот цикловКод:;void loop_jamming(int x ) ;{ ;интересный пролог... ;x=IX, другого регистра чтоли не нашли... PUSH BC PUSH IX PUSH DE POP IX ;for( i = 0; i < 5; i++ ) LD HL,0 ?0101: LD (i),HL ?0053: LD BC,32773 LD A,B XOR H LD H,A SBC HL,BC JR NC,?0052 ?0054: ; k5 = x + j5 * i; LD BC,(i) LD DE,(j5) CALL ?S_MUL_L02 PUSH IX POP HL ADD HL,DE LD (k5),HL LD L,C LD H,B INC HL JR ?0101 ?0052: ;for( i = 0; i < 5; i++ ) ;нет слияния- видать слишком сложно было бы, будь такая возможность LD HL,0 ?0102: LD (i),HL ?0057: LD BC,32773 LD A,B XOR H LD H,A SBC HL,BC JR NC,?0056 ?0058: ; i5 = x * k5 * i; LD BC,(k5) PUSH IX POP DE CALL ?S_MUL_L02 LD BC,(i) CALL ?S_MUL_L02 LD (i5),DE LD L,C LD H,B INC HL JR ?0102 ;} /* Конец loop_jamming */ POP IX POP BC RET
17. Сжатие цепочки переходовКод:;void loop_unrolling(int x ) ;{ ;нет сжатия, просто обычный цикл PUSH BC PUSH DE ;for( i = 0; i < 6; i++ ) LD HL,0 ?0104: LD (i),HL ?0061: LD BC,32774 LD A,B XOR H LD H,A SBC HL,BC JR NC,?0060 ?0062: ; ivector4[ i ] = 0; LD HL,(i) ADD HL,HL LD BC,ivector4 ADD HL,BC XOR A LD (HL),A INC HL LD (HL),A LD HL,(i) INC HL JR ?0104 ?0060: ;} /* Конец loop_unrolling */ POP HL POP BC RET
Версия с оптимизацией по размеру отличается в основном операциями сравнения, кой-какой оптимизацией загрузки регистров а также вызовом рестартов в прологах (rst 8) и эпилогах (rst 20h) функций, принимающих параметры (кроме jump_compression)Код:;int jump_compression(int i,int j,int k,int l,int m ) ;{ ;просто страшный пролог, уж проще было через индексные регистры... PUSH IY PUSH IX EXX PUSH BC PUSH DE EXX PUSH BC POP IX PUSH DE EXX POP BC EXX LD HL,12 ADD HL,SP LD A,(HL) LD IYL,A INC HL LD A,(HL) LD IYH,A DEC HL DEC HL DEC HL PUSH HL EXX POP HL LD E,(HL) INC HL LD D,(HL) EXX ?0105: ;beg_1: ; if( i < j ) ;далее можно заплутать в регистрах и проверках... PUSH IX POP BC EXX PUSH BC EXX POP HL OR 128 SBC HL,BC JP PO,?0111 XOR H ?0111: JP P,?0066 ?0065: ; if( j < k ) EXX PUSH DE EXX POP BC PUSH IX POP HL OR 128 SBC HL,BC JP PO,?0112 XOR H ?0112: JP P,?0068 ?0067: ; if( k < l ) PUSH IY POP BC EXX PUSH DE EXX POP HL OR 128 SBC HL,BC JP PO,?0113 XOR H ?0113: JP P,?0070 ?0069: ; if( l < m ) LD HL,14 ADD HL,SP LD C,(HL) INC HL LD B,(HL) PUSH IY POP HL OR 128 SBC HL,BC JP PO,?0114 XOR H ?0114: ;есть сжатие! иначе был бы переход на ?0074 JP P,?0105 ?0071: ; l += m; ADD IY,BC JR ?0077 ?0072: ; else ; goto end_1; ; else ; k += l; ?0073: ?0070: PUSH IY EXX POP HL ADD HL,DE EX DE,HL JR ?0115 ?0075: ; else { ; j += k; ;end_1: ; goto beg_1; ; } ; else ; i += j; ?0068: ADD IX,BC ?0074: JR ?0105 ?0076: ; return( i + j + k + l + m ); ?0066: PUSH IX EXX POP HL ADD HL,BC LD C,L LD B,H ?0115: EXX ?0077: PUSH IX POP HL EXX PUSH BC EXX POP BC ADD HL,BC EXX PUSH DE EXX POP BC ADD HL,BC PUSH IY POP BC ADD HL,BC PUSH HL LD HL,16 ADD HL,SP LD C,(HL) INC HL LD B,(HL) POP HL ADD HL,BC ;} /* Конец jump_compression */ EXX POP DE POP BC EXX POP IX POP IY RET
Резюме: 9/10. Компилятор оставил крайне приятное впечатление практически полным отсутствием неоправданных наворотов (иногда даже в ущерб...) и грамотным использованием регистров.
Для практического применения следует выработать ряд рекомендаций, направленных на улучшение качества кода (что, впрочем, является обычным явлением для всех ЯВУ для встроенных систем).
ЗЫ. Если все переменные, где не нужна знаковость, принудительно объявить как unsigned, а также снять опцию "static allocation of 'autos'" (в данном случае), то можно получить достаточно весомый выигрыш по оптимизации! В частности, первая рекомендация весьма и весьма упрощает операции сравнения, а вторая облегчает функции с маленьким числом локальных переменных и оптимизирует использование регистров как переменных
Последний раз редактировалось Vitamin; 14.03.2007 в 01:14.
Кажется в IAR можно управлять вычислением указателей, не сталкивался? А то вот интересно, можно ли это применить для того, чтобы дать проге побольше памяти как при стандарном 7FFD, так и при более навороченном (4x16k)MMU? Сорцы uzi(x) как глотает? А то, я так понял, оно довольно старомодно писано...
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)