PDA

Просмотр полной версии : Языки программирования



BlackWolf
11.11.2006, 16:32
А какие языки программирования были реализованы на спеке?
Насколько я помню несколько басиков, си, паскаль... что ещё?

boo_boo
11.11.2006, 16:55
А какие языки программирования были реализованы на спеке?
Насколько я помню несколько басиков, си, паскаль... что ещё?
кучка васиков
паскаль
си
лого
пролог
форт

больше вроде не было ничего

caro
11.11.2006, 16:58
А какие языки программирования были реализованы на спеке?
Насколько я помню несколько басиков, си, паскаль... что ещё?Есть несколько версий Forth, в том числе и дисковая, TAP версия Prolog, TAP версия Lisp.

BlackWolf
11.11.2006, 21:08
А какие были вариации на тему бейсика?

Shaos
11.11.2006, 21:51
А какие были вариации на тему бейсика?

мегабейсик, бетабейсик, лазербейсик, ну и компиляторы со стандартного бейсика типа бласта

а пролог на самом деле был микропрологом с другим синтаксисом и сильно примитивнее

TomCaT
12.11.2006, 11:24
Хотя серьезно подходить к программированию все равно можно только на машкодах без макросов и процедур. :)

Ну, а серьезно -- хотя бы асм без макросов.

Vitamin
12.11.2006, 14:10
Хотя серьезно подходить к программированию все равно можно только на машкодах без макросов и процедур.

Типа "суровые сибирские мужыки пишут только на машинных кодах сразу в шестнадцатеричном дампе"? Обоснуй плз свое заявление, потому что я на своем личном опыте убедился, что наиболее эффективное программирование именно на С (для встроенных систем).



Ну, а серьезно -- хотя бы асм без макросов
Имхо наоборот- макросы позволяют хоть как-то приблизить асм к уровню ЯВУ. Как говорится, на безрыбье...

TomCaT
13.11.2006, 22:08
И замедлить прогу

Изучая сейчас цэ после паскаля соглашусь, что он совсем не плох. Но никакие доводы не отберут пальму с кокосами у асма. Уж извините, можно и с ирландцем по-английски говорить, но как правило ирландский ему попонятней...

BlackWolf
13.11.2006, 22:53
Все зависит от поставленной задачи, если надо костьми лечь но обеспечить быстродействие тогда тока "в машинных кодах сразу в шестнадцатеричном дампе" если задача за разумные сроки сделать приложение отвечающие по скорости и трудозатратам изначальным условиям почему бы не использовать отвечающие заданным критериям доступные инструменты : макросы, яву и т.д.?
Сколько проектов заморожено-развалилось из-за сложностей реализации в разрезе трудозатрат? Почему бы их не уменьшить (трудозатраты) если это можно сделать? :mad:

BlackWolf
13.11.2006, 23:02
И замедлить прогу

Изучая сейчас цэ после паскаля соглашусь, что он совсем не плох.

О сколько нам открытий чудных....


Но никакие доводы не отберут пальму с кокосами у асма.
А как быть с доводами скорости и удобства разработки? Так что насчет "никаких доводов" будем считать что ты погорячился.


Уж извините, можно и с ирландцем по-английски говорить, но как правило ирландский ему попонятней...

Не надо аналогий. Они никогда полностью не отражают обсуждаемую ситуацию.

Vitamin
14.11.2006, 00:03
И замедлить прогу
Расскажи пожалста, каким это образом макросы могут замедлить прогу? Или злобный ассемблер при развороте макроса после каждой команды halt вставляет? :)


Изучая сейчас цэ после паскаля соглашусь, что он совсем не плох. Но никакие доводы не отберут пальму с кокосами у асма. Уж извините, можно и с ирландцем по-английски говорить, но как правило ирландский ему попонятней...
Я тоже когда-то бегал и махал флагом "асм рулит, С для ленивых". Но после того как пришлось сначала разбираться, а потом переделывать чужую программу на асме (микроконтроллер 8051, довольно примитивно), я слегка поменял свое мнение. Плюс к тому, С обеспечивает кроссплатформенность- пара моих библиотек без проблем была опробована на трех разных процессорах (8051, TMS430, TMS470). Сколько бы я писал их вручную?
Так что для промышленного программирования лучше С пока ничего не придумали. И если очень уж требуется быстродействие, ассемблерные вставки никто не отменял.
(для справки- изучаю асм спека уже 7 лет, С/С++ уже 5 лет, плюс еще парочка асмов, полузабытый паскаль/делфи и т.д.)
ЗЫ. Все-таки на спеке не хватает С с приличной средой разработки...

Robus
14.11.2006, 09:03
Но после того как пришлось сначала разбираться, а потом переделывать чужую программу на асме
На любом языке можно написать гадость, но на С не возможно написать оттактированую во времянках програму. Хотя можно пойти корявым способом и навесить всё на таймера, ну тогда програмирование будет ограниченным.


Плюс к тому, С обеспечивает кроссплатформенность- пара моих библиотек без проблем была опробована на трех разных процессорах (8051, TMS430, TMS470). Сколько бы я писал их вручную?
Наверное это что-то очень простое. Практически всё время нужно писать под процессор новые процедуры. Особенно если у тебя всего 128 байт памяти из которых для исполнения задачи нужно 128. Я хочу посмотреть как на СИ будет рашаться эта проблема ? Сколько я не видел фирмв с инициативами писать для МК на СИ, они постоянно занимаются поиском дорогих МК для решения серьёзных задач. Типичная гигантомания в стиле виндовсовских программ, года "весь пар уходит на гудок" ... =)

Vitamin
14.11.2006, 09:54
На любом языке можно написать гадость, но на С не возможно написать оттактированую во времянках програму. Хотя можно пойти корявым способом и навесить всё на таймера, ну тогда програмирование будет ограниченным.
Все зависит от дискретизации тактирования. Для периодов в миллисекунды и выше таймер как раз то самое средство. А если надо меньше- то тут, конечно, ассемблер.


Наверное это что-то очень простое.
Графическая библиотека для монохромных жк-дисплеев- всякие линии, точки, пропорциональная печать со стилями, работа с изображениями, буферизация, аппаратная независимость от реализации (работало даже на подключаемом через последовательный канал дисплее). Вторая библиотека- пользовательский интерфейс в стиле меню для бытовой техники, основан на графической библиотеке. Не бог весть что, но не ОЧЕНЬ простое.


Особенно если у тебя всего 128 байт памяти из которых для исполнения задачи нужно 128. Я хочу посмотреть как на СИ будет рашаться эта проблема ?
А если у тебя куча устройств, множество источников прерывания, дофига разных таймеров. Я хочу посмотреть как на ассемблере будет решаться эта проблема, и, самое главное, сколько времени будет писаться эта программа.


Сколько я не видел фирмв с инициативами писать для МК на СИ, они постоянно занимаются поиском дорогих МК для решения серьёзных задач.
Скажу по секрету, мощный буржуйский микропроцессор стоит дешевле наших слабеньких монстров (зато с 5 приемкой....), при этом ему не требуется большей части обвязки, да и по настройке и надержности он гораздо легче. А дорого-дешево- это все относительно, сэкономишь на процике- потеряешь на написании программы.


Типичная гигантомания в стиле виндовсовских программ, года "весь пар уходит на гудок"
Бывает, соглашусь. Когда вместо PIC ставят навороченный процик "чтоб было" :)

andrews
14.11.2006, 10:17
Но никакие доводы не отберут пальму с кокосами у асма. еще есть довод - "переносимость" или "портирование"...доводку на асме, если использовался качественный компилятор, тоже никто не запрещает...

andrews
14.11.2006, 10:21
Бывает, соглашусь. Когда вместо PIC ставят навороченный процик "чтоб было" :)
у нас в фирме ставят из-за того, что у заказчиков софт под QNX...а наши делают для них железо, драйверы и тесты...на PIC же QNX пока вроде не портировано...хотя и pic PICу рознь...последние пики очень так навороченные :)

elf/2
14.11.2006, 12:15
Изучая сейчас цэ после паскаля соглашусь, что он совсем не плох. Но никакие доводы не отберут пальму с кокосами у асма.
если брать современное железо, то хороший оптимизирующий компилятор c/c++ делает код быстрее чем средний программер на асме.

Vitamin
14.11.2006, 13:00
у нас в фирме ставят из-за того, что у заказчиков софт под QNX...а наши делают для них железо, драйверы и тесты...на PIC же QNX пока вроде не портировано...хотя и pic PICу рознь...последние пики очень так навороченные
не, я не про такую ситуацию, а именно про "шоб было" %)


если брать современное железо, то хороший оптимизирующий компилятор c/c++ делает код быстрее чем средний программер на асме
ага. а еще б я настоятельно посоветовал пописать на асме под АРМ :)))

andrews
14.11.2006, 13:16
ЗЫ. Все-таки на спеке не хватает С с приличной средой разработки...
+1
зато на GB есть...через 5 минут как я энтот компилятор себе поставил уже гонял какую-то демку на эмуле...как приятно все ж найти заброшенный, но пользованный миллионами юсерами предмет который безукоризненно работает :)

boo_boo
14.11.2006, 15:01
+1
зато на GB есть...через 5 минут как я энтот компилятор себе поставил уже гонял какую-то демку на эмуле...как приятно все ж найти заброшенный, но пользованный миллионами юсерами предмет который безукоризненно работает :)
для GameBoy? так это ж кросскомпилятор, работающий на "больших" машинах, такого и для спектрума понаписано достаточно (z88dk, SDCC)
а еще, к слову, есть ACK -- кросскомпилятор с C,pascal,fortran,modula,occam и васика.

но вот на zx -- только hisoft C :(

andrews
14.11.2006, 15:22
Напишите...пока такого вроде нет с нормальными графическими и звуковыми библиотеками и поддержкой железа.

TomCaT
14.11.2006, 20:12
Хорошо. Беру слова назад. С + ассемблер, но по крайней мере до 20-30 МГц -- с уклоном в сторону последнего, т.е. после переноса и до окончательной сборки, конечно.

Vitamin
14.11.2006, 21:46
С + ассемблер, но по крайней мере до 20-30 МГц -- с уклоном в сторону последнего, т.е. после переноса и до окончательной сборки, конечно.
8051@1Мгц вполне терпимо исполняет код, собранный из С. И это с учетом одного-единственного 16-разрядного регистра. Для спека должно быть получше...

Кто-нибудь находил версию GCC для зетника? А то перерыл дофига ссылок- одни огрызки информации, ни сорцов ни бинарника. А то была б маза собрать его же исходники для спека :) Ибо писать с нуля- весьма ресурсозатратно...

maximk
14.11.2006, 22:04
Кто-нибудь находил версию GCC для зетника? А то перерыл дофига ссылок- одни огрызки информации, ни сорцов ни бинарника.

Та же фигня. Но есть открытый компилятор из ACK, причем его можно оптимизировать. Имхо, эта задача на порядок проще, чем писать back-end к gcc.

Vitamin
14.11.2006, 22:11
Но есть открытый компилятор из ACK, причем его можно оптимизировать.
Подробнее можно? Не слышал о таком чтото...


Имхо, эта задача на порядок проще, чем писать back-end к gcc.
Гм... Иногда проще написать заново, нежели переделывать уже написанно :)

maximk
14.11.2006, 22:22
Подробнее можно? Не слышал о таком чтото...
ACK = Amsterdam Compiler Kit.

http://tack.sourceforge.net/

Целый пакет из средств разработки. Компилятор C, как и другие (еще поддерживаются несколько языков) производит промежуточный код, а back-end'ы из него создают код для целевой платформы. Причем, как транслировать промежуточный байт-код в реальный описывается на специальном языке. И соответствующее описание для генерации кода z80 уже есть! Но, как и сказано в доке, оно не оптимально, ибо за основу был взят вариант от i8080.

Vitamin
14.11.2006, 22:58
ACK = Amsterdam Compiler Kit.
Почитал, завтра скачаю и попробую под никсами собрать и попрогонять. Хочется посмотреть асм на выходе. Ибо все существующие кросс-компилеры такую хрень городят... Разве что IAR по слухам весьма достойно себя ведет (надо достать попробовать).

Robus
15.11.2006, 00:16
Графическая библиотека для монохромных жк-дисплеев- всякие линии, точки, пропорциональная печать со стилями, работа с изображениями, буферизация, аппаратная независимость от реализации (работало даже на подключаемом через последовательный канал дисплее). Вторая библиотека- пользовательский интерфейс в стиле меню для бытовой техники, основан на графической библиотеке. Не бог весть что, но не ОЧЕНЬ простое.

Практически каждый раз пишу под каждый LCD процедуры вывода, поскольку каждый LCD очень отличается от предыдущего. Практически везде использую поддержку окон, она, конечно, стандартная и написана только на assemblere. Последние попытки использовать предлагаемые библиотеки закончились тем, что вывод символов, конечно же разной ширины, выглядил как прин на "васике", хоте нет наш "васик" примерно в 10-ть раз быстрее. Короче скорость просто ужасная и подходит для отображения каких-нибудь крайне статических изображений. Мало того, я постоянно занимаюсь тем, что подрабатываю на фирмах где меня просят ускорить вывод информации на LCD'шки. Вот на следующей неделе еду делать работу для компании Квазар-Микро, которая выставляется на выставке на стендах. Их программисты не могут на 25 мипсовм "интеле51" сделать нормальную анимацию. Я же программирую только на асме, скорорсть разработки, конечно не лучшая, примерно неделя для любой задачи с переферией(а значит и LCD), а остальное это уже мелочи, которые долизываются по ходу дела. В последний раз делал прибор месяц тому назад с LCD 240х128 (epson), за день был написан полностью модул графики со всеми окошками, шрифтиками и другой мелочью. Поэтому не вижу смысла писать на Си, только тратить время на поиск, - "а почему же это всё так тормозит..." ...

Vitamin
15.11.2006, 00:36
Немного оффтопа, но с рациональным зерном


Практически каждый раз пишу под каждый LCD процедуры вывода, поскольку каждый LCD очень отличается от предыдущего.
Я для себя выбрал другой подход. Библиотека заточена под работу с дисплеями 128х64 (8 строк по 128 байт, пиксели вертикально). Но благодаря буферу позволяет работать с дисплеями с любой(!) организацией растра (успешно работал на многстраничном дисплее с "растровой" организацией). Естественно, тормознее (перекидывание буфера целиком на экран), но зато "все внутри".
Ну и библиотека пользовательского интерфейса. К ней в комплекте программа-конструктор и конвертер в С.


Практически везде использую поддержку окон, она, конечно, стандартная и написана только на assemblere.
И путем каких манипуляций ты ее портируешь на другие процессоры? Переписывание?


Последние попытки использовать предлагаемые библиотеки закончились тем, что вывод символов, конечно же разной ширины, выглядил как прин на "васике", хоте нет наш "васик" примерно в 10-ть раз быстрее.
Вышеупомянутый 8051 на 1мгц запечатывает весь экран (с прямой отрисовкой в дисплей) примерно за 0.4с. Это с пропорциональной печатью с обработкой (особенно трудно реализовывать наклонный шрифт в силу структуры).


Их программисты не могут на 25 мипсовм "интеле51" сделать нормальную анимацию.
Мдя :) Помнится ради хохмы написал прогу под 470 (48 мипс вроде, но не уверен), которая по последовательному каналу принимала кадры изображения, распаковывала их в реалтайме на экран. А другая прога на компе из авишника конвертила и слала. До 25фпс выдавало при размере кадра в 1к, сжатие в 1.5...3 раза получалось. Все ограничивалось скоростью порта- до 200кбит только выжимал (далее конвертер не позволял). Надо будет ради прикола попробовать эту же фишку на 8051...


Я же программирую только на асме, скорорсть разработки, конечно не лучшая, примерно неделя для любой задачи с переферией(а значит и LCD), а остальное это уже мелочи, которые долизываются по ходу дела.
У меня в боекомплекте периферия- 6 счетных каналов (16-разрядные счетчики импульсов), жк-дисплей (символьный, с тупой организацией), лсд-матрица (примитив...), последовательный порт, плюс внутри математика. И все это на одном 8051 и на С. Прога писалась очень долго, ассемблерный вариант уже почти неуправляем (постоянные доделки-переделки), сейчас переписываю на С.
Второй вариант отличается графическим ЖК, 8 счетными каналами, 2 последовательными портами. Проц тот же самый, прога изначально писалась на С, благодаря чему доработка относительно проста.


Поэтому не вижу смысла писать на Си, только тратить время на поиск, - "а почему же это всё так тормозит..."
А что тратить время? Надо включать логику! :) В основном цикле программы разные не критичные ко времени процессы (пользовательский интерфейс, пост-обработка данных, печать в буферы и т.п.), а прием данных и предварительная обработка на прерываниях. Ставишь контроль-точки установки/сброса уровней между блоками подпрограммы-обработчика и смотришь на осциллографе кто и сколько чего жрет. А потом уже переписываешь критичные участки на асме. Ну и плюс чисто алгоритмическая оптимизация.

SfS
15.11.2006, 07:56
А что тратить время? Надо включать логику! :) В основном цикле программы разные не критичные ко времени процессы (пользовательский интерфейс, пост-обработка данных, печать в буферы и т.п.), а прием данных и предварительная обработка на прерываниях. Ставишь контроль-точки установки/сброса уровней между блоками подпрограммы-обработчика и смотришь на осциллографе кто и сколько чего жрет. А потом уже переписываешь критичные участки на асме. Ну и плюс чисто алгоритмическая оптимизация.

Целиком и полностью согласен. Это некий "юношеский комплекс" - писать все на АСМе... Причем нисколько не обоснованный. Как показала практика и опыт - продумывание алгоритма и распределение по приоритетам задач - гораздо более эффективный способ сделать, "чтобы не тормозило", чем переписывание всего на АСМе. Куски на асме - другое дело (например в обработчиках очень критичных ко времени прерываний). Но все на асме - изврат :)

maximk
15.11.2006, 09:02
Хочется посмотреть асм на выходе.
Я смотрел. Фигня. Но дело в другом. Чем с нуля писать кодогенератор под монстрообразный gcc можно попробовать (если конечно есть желание, а ведь именно об этом шла речь :) ) _оптимизировать_ уже существующий back-end из ACK.

Vitamin
15.11.2006, 10:20
Как показала практика и опыт - продумывание алгоритма и распределение по приоритетам задач - гораздо более эффективный способ сделать, "чтобы не тормозило", чем переписывание всего на АСМе. Куски на асме - другое дело (например в обработчиках очень критичных ко времени прерываний). Но все на асме - изврат
Медленно но верно, я тоже пришел к такому выводу :) Особенно если приходится переделывать чей-то код- на сях бывает достаточно отформатировать исходник чтобы понять что к чему. А вот на асме обычно надо глубоко разбираться...


Я смотрел. Фигня. Но дело в другом. Чем с нуля писать кодогенератор под монстрообразный gcc можно попробовать (если конечно есть желание, а ведь именно об этом шла речь ) _оптимизировать_ уже существующий back-end из ACK.
Я просто видел одну реализацию компилятора на С. Сделано все влоб, продвинутые грамматические разборы не применяются (подозреваю что и стандарт не полностью соблюдается и оптимизация слабоватая), но зато все относительно ясно и понятно.

NovaStorm
15.11.2006, 14:07
А весёленькие эти "The Ten Commandments for C Programmers" у АСК'ного lint =)
А эффективный С для спеки скорее всего будет далёк отстандарта,тк наверняка придётся много делать руками: и типы вызовов прописывать и со стеком извращаться и код ORG'ами рассовывать...
++
"ACK has received minimalmaintenance for the best part of a decade. During that time, the Unix world has moved on", "the ACK is not C99 compatible" ещё бы, 10 лет ему... стоит ли вообще возиться?
++
Жгут: "User options - How to make lint shut up".
У АСК походу дела внутрях стековая машина ЕМ, будет ли это хорошо для Z80?

maximk
15.11.2006, 15:00
стоит ли вообще возиться?

Альтернатив не видно. Если кому-то хочется сделать лучше, чем в z88dk или sdcc, то, имхо, лучше всего начать с ACK. Что проще: ковырять исходники всего компилятора (как вариант - писать вообще с нуля :) ) или написать нормальный конвертер из EM в код Z80, пусть даже для этого придется выкинуть штатный кодогенератор.

10 лет это пустяки :) Сколько там некоторым местам кода ядер BSD или древних гнушных утилит? :)

C99 для спека и нафик не нужен. Имхо, если бы даже был Small C (подмножество т.е.) , но генерил мега-код - это был бы реальный рулез. Что с того, что sdcc ANSI-compliant?

И еще: лично мне больше всего понравился LCC. Хоть он и написан для RISC-машин, но я думаю, можно было бы приспобосить и для z80. Но там с доками глухо... Исходники есть, но не с самодокументированным кодом :)

NovaStorm
15.11.2006, 15:39
Писать back-end для EM почти бесперспективно. Может лучше в сторону www.cminusminus.org податься, там хотя бы серьёзные дядьки работают, работы конечно там будет скорее всего больше, но и результат себя должен будет оправдать.
++
блин, этих С--, как собак... но смысл я думаю понятен - попытаться попользовать более поддерживаемый кодогенератор.
++
Можно небольшое how-to по ACK? скомпилил, проверил... Вроде что-то делает, но на z80 код это ну совсем не похоже =)

captain cobalt
15.11.2006, 16:40
Если говорить о z80 вообще, то под CP/M есть много всяких языков - покопайтесь на файловых хранилищах.

Документация на один из компиляторов Modula-2 (freeware c 2002 года):
http://www.hartetechnologies.com/manuals/Modula2/

Error404
15.11.2006, 18:03
Альтернатив не видно. Если кому-то хочется сделать лучше, чем в z88dk или sdcc, то, имхо, лучше всего начать с ACK.
...
10 лет это пустяки :) Сколько там некоторым местам кода ядер BSD или древних гнушных утилит? :)


Хехе. Я тут недавно сравнивал: распоследний SDCC генерит с одного и того же исходника вдвое более объемный код, чем CP/M Hitec C однатысячадевятьсотмохнатого года



C99 для спека и нафик не нужен. Имхо, если бы даже был Small C (подмножество т.е.) , но генерил мега-код - это был бы реальный рулез. Что с того, что sdcc ANSI-compliant?


Да вообще нужно хотябы один более-менее похожий на C язык с изначальной поддержкой нормальных типов данных (32bit integer, float)
Но их нет! Все недоделанные, либо генерят монструозный код, либо ни с чем не совместимы кроме как сами с собой.

captain cobalt
15.11.2006, 21:32
Вот ещё нагуглилось:
http://www.softools.com/scz180.htm
http://www.ticalc.org/pub/text/z80/

NovaStorm
16.11.2006, 08:54
Да уж, под CP/M есть вот например что http://www.bdsoft.com/resources/bdsc.html, но исходник на асме 8080 =(
А Small C кто-нибудь собирал?
++
Ага! Ситуация проясняется... Z88DK это потомок от Small C.
Гляжу теперь AnyC.
Надо бы FAQ сделать прилепленный, чтоб не лазить толпой...

maximk
16.11.2006, 09:26
bdsc генерит код для i8080. Код относительно нормальный, но с hisoft уже не сравнить, а то, что он не для z80 делает его малопригодным...

andrews
16.11.2006, 09:27
А Small C кто-нибудь собирал?
я собирал...это самое простое, но нужны хорошие графические и прочие библиотеки( в частности работающие со специфическим железом спектрумов)

NovaStorm
16.11.2006, 09:49
AnyC скорее мёртв.
А вот библиотеки... Я думаю что у каждого будут свои, ибо пока нет нормальной ОСи, для которой их следовало бы делать.

boo_boo
16.11.2006, 09:52
я собирал...это самое простое, но нужны хорошие графические и прочие библиотеки( в частности работающие со специфическим железом спектрумов)
тоже еще проблемы %))
был бы нормальный компилятор, за библиотеками дело не станет, готов лично поучаствовать :rolleyes:
это если разговор о нативном C для zx.

а если кросскомпилер, то чем z88dk не устраивает? с splib можно вполне сносные игрульки писать (спрайты, тайлы, прерывания, опрос клавы/джойстиков/мыши, работа с памятью... phantomas infinity на нем написан)... остальное прикручивается из asm-сорцов за 5 минут.
а сделан z88dk, кстати, на основе small C

maximk
16.11.2006, 10:25
Имхо, из открытых проектов z88dk по отношению качество кода/фичастость рулит на данный момент, но все понимают, особенно оглядываясь на hitech, что это не идеал :)

NovaStorm
16.11.2006, 12:16
Идеал/не идеал... Где бенчмарки? =) Надо бы для такого тестирования сделать тест пакет.

maximk
16.11.2006, 12:51
Ну это, есть же Dhrystone, хотя им и процессоры тестят, но у нас получится на одном процессоре будут теститься компиляторы.

caro
16.11.2006, 13:55
под CP/M есть вот например что http://www.bdsoft.com/resources/bdsc.html, но исходник на асме 8080 =(Без проблем конвертится в исходник с мнемоникой Z80.
Я его кстати выкладывал на форуме в составе ZXCPM, перекомпилировав для работы с адреса 6100h.


А Small C кто-нибудь собирал?Собирал, но он очень громозкий и требует для работы даже в CP/M не менее 50 КБайт TPA.

captain cobalt
16.11.2006, 14:04
32bit integer Это ещё зачем?
Как это будет работать на z80?

NovaStorm
16.11.2006, 14:33
Боюсь от реалий спеки от оторван напрочь =) особенно по памяти.

Vitamin
16.11.2006, 14:41
Это ещё зачем?
Как это будет работать на z80?
Почемуто по поводу нужности float вопросов не возникало, хотя очень много вычислений можно проводит с фиксированной, а не плавающей запятой (что несравненно быстрее и проще). Вот для этих целей 32разрядное целое и нужно. Прекрасно хранится в паре регистров (равно как и float)

Error404
16.11.2006, 15:21
Цитата:
Сообщение от Error404
32bit integer

Это ещё зачем?
Как это будет работать на z80?

Нормально будет работать. А нужно это затем, чтобы не изобретать велосипеды, а брать готовый код с любых платформ. Есть готовые реализации, к примеру, TCP/IP или FAT32 на С, причем в минималистской форме (специально для 8-биток). Да и вообще, я часто натыкался на необходимость в 32 bit int, а перелопачивать и отлаживать код из-за того, что компилер не может - это сильно на любителя. Из CP/M-овских нативных С-компиляторов мне пока известны (пробовал) только 2 компилятора из всего множества, изначально (а не через дурацкие char-конверсии) поддерживающие приемлимый набор типов - это
Hitec C и Mix C. Но и тут ложка дегтя: оба хранят либы в уникальных форматах, тогда как удобнее если бы это был rel/irl.
Bdsc, SmallC, C80, MsxC тоже пробовал - не понравились из-за их предельного аскетизма поддерживаемых типов.

maximk
16.11.2006, 15:22
Без проблем конвертится в исходник с мнемоникой Z80.
Я его кстати выкладывал на форуме в составе ZXCPM, перекомпилировав для работы с адреса 6100h.

Это все да, но код-то он продолжает генерить для i8080 и поддержка возможностей z80 не появится :) Кроме того, кажется bdsc сразу компилит в бинарный код, без ассемблерного текста, что не есть хорошо.

SfS
17.11.2006, 07:42
Нормально будет работать. А нужно это затем, чтобы не изобретать велосипеды, а брать готовый код с любых платформ. Есть готовые реализации, к примеру, TCP/IP или FAT32 на С, причем в минималистской форме (специально для 8-биток). Да и вообще, я часто натыкался на необходимость в 32 bit int, а перелопачивать и отлаживать код из-за того, что компилер не может - это сильно на любителя.

Вообще-то int в С для всех 8 и 16битных процов, какие я знаю - 16 бит, а не 32 (AVR, PIC, I196 и т.п.). Так зачем это менять ? Пользуйся 32х битным long int или 64битным long long int. Причем, только там, где это надо. Это оптимальнее.

maximk
17.11.2006, 09:44
Так зачем это менять ?
Я так понял, что никто и не предлагал менять, проблема в том, что в некоторых недокомпиляторах C тип long int отсутствует как класс или равен тоже 2-м байтам :)
Про long long я вообще молчу :)

Sonic
17.11.2006, 10:17
Кто-нибудь находил версию GCC для зетника? А то перерыл дофига ссылок- одни огрызки информации, ни сорцов ни бинарника. А то была б маза собрать его же исходники для спека :) Ибо писать с нуля- весьма ресурсозатратно...

AFAIK хрена с два ты его найдешь. Насколько я понимаю, оного существовать не может, по крайней мере для классического z80. Может для eZ80 разве что... У gcc тоже есть свои ограничения - он ориентирован на 32-бит/64-бит архитектуры и Flat memory Model. На ZX нет ни того ни другого.

Есть другие открытые компиляторы, в том числе и z80-targetted.
К тому же C для ZX был бы действительно интересен, если бы еще и работал на самом ZX (я сторонник нативных систем). А даже если и представить себе, что gcc неким образом существует на Спеке, то Hello world он компилировал бы несколько суток. gcc - слишком сложная система с использованием нескольких промежуточных представлений.

Error404
17.11.2006, 15:37
Вообще-то int в С для всех 8 и 16битных процов, какие я знаю - 16 бит, а не 32 (AVR, PIC, I196 и т.п.). Так зачем это менять ? Пользуйся 32х битным long int или 64битным long long int. Причем, только там, где это надо. Это оптимальнее.

Шутите? :v2_biggr:
Оффтоп: Встречает "новый русский" (HP) "старого русского" (СР):
НР: - Кака дела?
СР: - Да вот, не ел три дня...
НР: Ну, братан, надо же себя как-то заставлять....
:smile:

А если серьезно: рад бы воспользоваться, да не могу: не знает тип long (32bit) большинство 8080/Z80 С-компиляторов (по крайней мере нативных, не писюковых) . Естественно я имел ввиду long... Т.е. принципиальную возможность использовать нативный целочисленный тип 32bit.

Vitamin
17.11.2006, 18:42
Т.е. принципиальную возможность использовать нативный целочисленный тип 32bit.
нативного типа такого нет. а для нативных типов int(16) и char(8) определены только операции + и -. Все остальное (*/%) пишется ручками. Равно как и весь перечень операций для long(32) и float(32). Будет поддержка- будет и тип.

Error404
17.11.2006, 20:12
нативного типа такого нет. а для нативных типов int(16) и char(8) определены только операции + и -. Все остальное (*/%) пишется ручками. Равно как и весь перечень операций для long(32) и float(32). Будет поддержка- будет и тип.

Пишется все что угодно и без привязки к процессору. Причем тут аппаратная поддержка? Любая арифметика делается. Только заниматься этим должно ядро компилятора (это я имел ввиду под определением "нативные типы" - с терминологией беда :smile: ). Чтобы не изобретать в дополнительных библиотеках порнографию вида:

typedef LONG char*
void plus32(LONG op1, op2, result)
{}
...
char[4] a,b,c;
...
plus32(a,b,c); /* c=a+b */

А этим занимаются почти все компиляторы для 8080/Z80 - сделают 3 типа, а остальное - "сделай сам". Понятно, что при таком подходе никакие сторонние исходники не используешь (везде принято писать c=a+b , а не plus32(a,b,c) ), да и тормозит такая "прикрученная сбоку" арифметика жутко.
У авторов Hitec C в CP/M-версии компилятора, к примеру, хватило ресурсов реализовать все наиболее часто требуемые типы на все том же z80. Пока это лучшеее, что я видел из бесплатного (считая и PC-версии) и, похоже, единственное более-менее пригодное к употреблению.

Vitamin
17.11.2006, 21:57
А этим занимаются почти все компиляторы для 8080/Z80 - сделают 3 типа, а остальное - "сделай сам".
Насколько С++ шаг вперед по отношению к С (class::operator ...), настолько и эти компилеры шаг назад от того же С...
В нормальных компилерах есть runtime-библиотека, где определены функции типа __inttofloat __add32 etc, и компилятор занимается их вызовом. Т.е. обеспечиваются все нативные (для языка) типы, причем глубоко пофиг какой разрядности целевая машина.
Грустно, что такого не сделали...

fk0
18.11.2006, 18:06
Расскажи пожалста, каким это образом макросы могут замедлить прогу?


"Комментарии в теле цикла замедляют его работу".
А ты не знал? Низачот.



Я тоже когда-то бегал и махал флагом "асм рулит, С для ленивых". Но


Я в принципе и сейчас бы помахал. В асме реализуются зачастую концепции недоступные в недоязычках вроде паскаля. Или C. Хотя в последнем не всё так уж и плохо, по сравнению с некоторыми... Тоже прикручиваются внешние макропроцессоры. Или можно потихоньку мигрировать в сторону C-два-креста.



Так что для промышленного программирования лучше С пока ничего не придумали.


Java. Там этих страшных указателей нет. И выделение памяти абсолютно-безопасносное (пока OOM killer не отстрелит).
Да нет, самое главное конечно не это. Самое главное -- что
Java обучаются даже бабуины. Вся суть в этом.



ЗЫ. Все-таки на спеке не хватает С с приличной средой разработки...

www.htsoft.com? Никто не отменял. Только Z80 супротив современных RISC цпу, даже самых мелких мелкоконтроллеров,
сильно проигрывает. В том смысле, на него C с его парадигмой распределения памяти хреновенько ложится.

fk0
18.11.2006, 18:15
8051@1Мгц вполне терпимо исполняет код, собранный из С. И это с учетом одного-единственного 16-разрядного регистра.

Ага, DPTR. Мне уже второй год страшно в листинги из-за этого заглядывать. Вот я и не заглядываю. В small model оно, к слову, гораздо веселее.



Кто-нибудь находил версию GCC для зетника? А то перерыл дофига ссылок- одни огрызки информации, ни сорцов ни бинарника. А то была


Несколько лет назад в инете искалось и у меня сохранился патч на GCC старой (2.x, вроде 2.95 примерно) версии GCC. Другое дело, что тут очень много зависит от:

1) кодогенерирующего backend'а. А он явно плох.

2) стиля кодирования. Он от писишного должен отличаться.

Я бы сказал, на 50% возможность использования компилятора определяется программистом. И на 50% компилятором. Компилятор -- повторяюсь -- hitech. Лучше для Z80 (и PIC) нет.



маза собрать его же исходники для спека :) Ибо писать с нуля- весьма ресурсозатратно...

small C compiler.

fk0
18.11.2006, 18:30
Писать back-end для EM почти бесперспективно. Может лучше в сторону www.cminusminus.org податься, там
хотя бы серьёзные дядьки работают, работы конечно там будет скорее


Если они такие серьёзные, то чего ж они изобретательством велосипедов занимаются. Этот велосипед называется PL/M и известен уже лет чуть ли не 30 как. Для Z80, кстати, должен быть и должен пускаться с лёгкостью в CP/M. Т.е. на пентагоне/скорпионе вполне реально. И документация, всё есть.

Error404
18.11.2006, 18:31
"Комментарии в теле цикла замедляют его работу".
А ты не знал? Низачот.


Почемуто всегда считал, что макрос и inline-процедуры работают быcтрее обычного вида подпрограмм, т.к. как раз не являются подпрограммами и не требуют вызова и сопутствующих манипуляций со стеком.
Впрочем, утверждать не берусь.




Я в принципе и сейчас бы помахал. В асме реализуются зачастую концепции недоступные в недоязычках вроде паскаля. Или C.


Вообще-то, когда нужен 100% результат, концепции реализуются на языке блок-схем. И язык реализации в большинстве случаев принципиального значения не имеет - это лишь вопрос технологии и деталей реализации. Соответственно, в правильно спроектированных системах не возникает необходимости в спецсредствах типа ASM (ну кроме считанных time-critical мест или в случае программирования каких-то уж очень чудных микроконтроллеров).
Про С в последних сообщениях этого треда говорилось с точки зрения переносимости кода с платформы на платформу. С этой точки зрения юзабельность АСМ стремится к нулю.



Java. Там этих страшных указателей нет. И выделение памяти абсолютно-безопасносное (пока OOM killer не отстрелит).
Да нет, самое главное конечно не это. Самое главное -- что
Java обучаются даже бабуины. Вся суть в этом.


Ну да. А десят лет назад то же говорили про Basic. А еще раньше про Фортран. А еще через 20 лет будут говорить про что-то другое. Кстати, а есть ли Java-машины для Z80? Было бы интересно взглянуть...



Только Z80 супротив современных RISC цпу, даже самых мелких мелкоконтроллеров, сильно проигрывает. В том смысле, на него C с его парадигмой распределения памяти хреновенько ложится.

А что такого особенного в распределении памяти в C?

Vitamin
18.11.2006, 19:48
"Комментарии в теле цикла замедляют его работу".
А ты не знал? Низачот.
Посыпаю голову пеплом от сожженых исходников и ухожу в монастырь. Женский :))))


В асме реализуются зачастую концепции недоступные в недоязычках вроде паскаля.
Я б сказал так- в асме реализуется все, ибо это праматерия. Другое дело что вместе с полной свободой действий мы получаем полуметровый геморрой с разработкой, рефакторингом, реверс инженирингом и отладкой...


Java. Там этих страшных указателей нет. И выделение памяти абсолютно-безопасносное (пока OOM killer не отстрелит).
Это если имеется компилятор явы (или поддержка на аппаратном уровне)


www.htsoft.com? Никто не отменял. Только Z80 супротив современных RISC цпу, даже самых мелких мелкоконтроллеров,
сильно проигрывает. В том смысле, на него C с его парадигмой распределения памяти хреновенько ложится.
Ну дык, сравнил зетник и арм... Я, если честно, при написании под контроллер вообще не пользуюсь функциями выделения памяти, только статически все. Если надо- беру свой минималистический менеджер памяти и не мучаюсь.


Ага, DPTR. Мне уже второй год страшно в листинги из-за этого заглядывать. Вот я и не заглядываю. В small model оно, к слову, гораздо веселее.
не, проект только под huge тянется...


2) стиля кодирования. Он от писишного должен отличаться
ясен хрен... неоднократно с этим сталкивался:
xdata unsigned char* ext_dev _at_ 0xff00;
гораздо хуже чем
#define (*(xdata unsigned char*)0xff00) ext_dev
хотя по логике одно и то же...


Компилятор -- повторяюсь -- hitech. Лучше для Z80 (и PIC) нет.
приятное открытие- он берет 8051 и msp430. надо будет погонять как время будет....
ЗЫ. А бесплатная версия имееццо? А то на сайте грят "только по талонам"...

James DiGreze
19.11.2006, 08:54
Вах-вах! HI-TECH C Z80/Z180 = $950 - приятная цена! :)

Error404
19.11.2006, 11:03
Вах-вах! HI-TECH C Z80/Z180 = $950 - приятная цена! :)

последняя из CP/M-версий - бесплатно

Aprisobal
19.11.2006, 13:02
А версия компилятора Hi-tech, которую выкладывал 53431 не подходит?

caro
19.11.2006, 13:34
А версия компилятора Hi-tech, которую выкладывал 53431 не подходит?Все попытки скачать файл с RapidShare лично для меня не увенчались успехом :)
Выдает:

You have requested the file Embedded_Systems_-_Avocet_WideUI_V3.28_ANSI-C_Compiler_for_Z80.rar (3749 KB).
This file has been downloaded 1 times already.

ERROR: Please enable JavaScript.

PS. Java у меня включена.

Vitamin
19.11.2006, 14:07
А версия компилятора Hi-tech, которую выкладывал http://zx.pk.ru/showthread.php?p=53431 не подходит?
Скачал, проверяю пока первый.
Тестовый код (взято с codenet.ru):



/* ---------------------------------------------------------- *
| |
| Серия тестов PC Tech Journal |
| Тест оптимизации кода Си |
| |
| Copyright (c) 1988 Ziff-Devis Publishing Company |
| |
| Эта программа-тест была разработана для проверки |
| методов оптимизации кода, применяемых компилятором |
| Си. Она не вырабатывает разумные результаты и не |
| представляет хороший стиль программирования. |
| |
* ---------------------------------------------------------- */


//#include
//#include
#define max_vector 2
#define constant5 5

typedef unsigned char uchar;

int i, j, k, l, m;
int i2, j2, k2;
int g3, h3, i3, k3, m3;
int i4, j4;
int i5, j5, k5;

double flt_1, flt_2, flt_3, flt_4, flt_5, flt_6;

int ivector[ 3 ];
uchar ivector2[ 3 ];
short ivector4[ 6 ];
int ivector5[ 100 ];

#ifndef NO_PROTOTYPES
void dead_code( int, char * );
void unnecessary_loop( void );
void loop_jamming( int );
void loop_unrolling( int );
int jump_compression( int, int, int, int, int );
#else
void dead_code();
void unnecessary_loop();
void loop_jamming();
void loop_unrolling();
int jump_compression();
#endif

int main( argc, argv ) /* optbench */
int argc;
char **argv;
{

/* ---------------------------- *
| Размножение констант и копий |
*------------------------------*/

j4 = 2;
if( i2 < j4 && i4 < j4 )
i2 = 2;

j4 = k5;
if( i2 < j4 && i4 < j4 )
i5 = 3;

/* ------------------------------------------ *
| Свертка констант, арифметические тождества |
| и излишние операции загрузки/сохранения |
* ------------------------------------------ */

i3 = 1 + 2;
flt_1 = 2.4 + 6.3;
i2 = 5;
j2 = i + 0;
k2 = i / 1;
i4 = i * 1;
i5 = i * 0;

#ifndef NO_ZERO_DIVIDE
/*
* Некоторые компиляторы распознают ошибку
* деления на нуль и не генерируют объектный код
*/
i2 = i / 0;
flt_2 = flt_1 / 0.0;
#else
printf( "This compiler handles divide-by-zero as \
an error\n");
#endif
flt_3 = 2.4 / 1.0;
flt_4 = 1.0 + 0.0000001;
flt_5 = flt_6 * 0.0;
flt_6 = flt_2 * flt_3;

/* -------------------- *
| Лишнее присваивание |
* -------------------- */

k3 = 1;
k3 = 1;

/* ------------------ *
| Снижение мощности |
* ------------------ */

k2 = 4 * j5;
for( i = 0; i <= 5; i++ )
ivector4[ i ] = i * 2;

/* ------------- *
| Простой цикл |
* ------------- */

j5 = 0;
k5 = 10000;
do {
k5 = k5 - 1;
j5 = j5 + 1;
i5 = (k5 * 3) / (j5 * constant5);
} while ( k5 > 0 );

/* -------------------------------------- *
| Управление переменной индукции цикла |
* -------------------------------------- */
for( i = 0; i < 100; i++ )
ivector5[ i * 2 + 3 ] = 5;

/* ----------------------- *
| Глубокие подвыражения |
* ----------------------- */

if( i < 10 )
j5 = i5 + i2;
else
k5 = i5 + i2;

/* ------------------------------------------------ *
| Проверка того, как компилятор генерирует адрес |
| переменной с константным индексом, размножает |
| копии и регистры |
* ------------------------------------------------ */

ivector[ 0 ] = 1; /* генерация константного адреса */
ivector[ i2 ] = 2; /* значение i2 должно быть скопировано*/
ivector[ i2 ] = 2; /* копирование регистров */
ivector[ 2 ] = 3; /* генарация константного адреса */


/* ----------------------------- *
| Удаление общих подвыражений |
* ----------------------------- */

if(( h3 + k3 ) < 0 || ( h3 + k3 ) > 5 )
printf("Common subexpression elimination\n");
else {
m3 = ( h3 + k3 ) / i3;
g3 = i3 + (h3 + k3);
}

/* -------------------------------------- *
| Вынесение инвариантного кода |
| (j * k) может быть вынесено из цикла |
* -------------------------------------- */

for( i4 = 0; i4 <= max_vector; i4++)
ivector2[ i4 ] = j * k;

/* ----------------------------- *
| Вызов функции с аргументами |
* ----------------------------- */

dead_code( 1, "This line should not be printed" );

/* ------------------------------ *
| Вызов функции без аргументов |
* ------------------------------ */

unnecessary_loop();

} /* Конец функции main */


/* ------------------------------------------------------ *
| Функция: dead_code |
| Проверка недостижимого кода и лишних |
| присваиваний. Не должен генерироваться код. |
* ------------------------------------------------------ */

void dead_code( a, b )
int a;
char *b;
{
int idead_store;

idead_store = a;
if( 0 )
printf( "%s\n", b );
} /* Конец dead_code */


/* ---------------------------------------------------- *
| Функция: unnecessary_loop |
| Цикл в следующей функции ненужен, так как |
| значение присваивания постоянно. В идеале |
| цикл должен быть удален. |
* ---------------------------------------------------- */

void unnecessary_loop()
{
int x;

x = 0;
for( i = 0; i < 5; i++ ) /* Цикл не должен
генерироваться*/
k5 = x + j5;
} /* Конец unnecessary_loop */

/* ---------------------------------------------------- *
| Функция: loop_jamming |
| Два цикла в этой функции имеют одинаковые |
| заголовки и могут быть слиты в один. |
* ---------------------------------------------------- */


void loop_jamming( x )
int x;
{
for( i = 0; i < 5; i++ )
k5 = x + j5 * i;
for( i = 0; i < 5; i++ )
i5 = x * k5 * i;
} /* Конец loop_jamming */

/* ------------------------------------------------------ *
| Функция: loop_unrolling |
| Цикл в этой функции должен быть заменен |
| тремя присваиваниями с использованием |
| константной индексации массива или машинно- |
| зависимыми командами для инициализации |
| блока памяти. |
* ------------------------------------------------------ */

void loop_unrolling( x )
int x;
{
for( i = 0; i < 6; i++ )
ivector4[ i ] = 0;
} /* Конец loop_unrolling */

/* ----------------------------------------------------- *
| Функция: jump_compression |
| Эта программа полезна для демонстрации |
| сжатия цепочки переходов. goto end_1 может |
| быть заменен на прямой переход на beg_1. |
* ----------------------------------------------------- */

int jump_compression( i, j, k, l, m )
int i, j, k, l, m;
{
beg_1:
if( i < j )
if( j < k )
if( k < l )
if( l < m )
l += m;
else
goto end_1;
else
k += l;
else {
j += k;
end_1:
goto beg_1;
}
else
i += j;
return( i + j + k + l + m );
} /* Конец jump_compression */

Vitamin
19.11.2006, 15:11
Ну что, прогнал HitechC по тесту, осталось весьма приятное впечатление. Некоторые вещи, конечно, хотелось бы улучшить, но все же.
Итак, что он, собственно накрутил. Испытания проводились с учетом максимального уровня оптимизации

0. Пролог. Весьма короткий:


_main:
push ix
ld ix,0
add ix,sp

дальше идет непосредственно код

1. Тест на размножение констант и копий.


;TEST.C: 62: j4 = 2;
ld hl,02h
ld (_j4),hl
;TEST.C: 63: if( i2 < j4 && i4 < j4 )
;лишняя загрузка из j4 - следствие того, что для
;сравнения используется функция с фиксированными
;позициями для параметра, но все равно- мог бы
;использовать de для инициализации или сделать
;ld d,h:ld e,l
ld de,(_j4)
ld hl,(_i2)
call wrelop
;также использование jp не есть хорошо. сокращенные
;вычисления используются в соответствии со стандартом
jp p,l4
ld de,(_j4)
ld hl,(_i4)
call wrelop
jp p,l4
;TEST.C: 64: i2 = 2;
ld hl,02h
ld (_i2),hl
l4:
;TEST.C: 66: j4 = k5;
ld hl,(_k5)
ld (_j4),hl
;TEST.C: 67: if( i2 < j4 && i4 < j4 )
;картина полностью аналогичная
ld de,(_j4)
ld hl,(_i2)
call wrelop
jp p,l5
ld de,(_j4)
ld hl,(_i4)
call wrelop
;TEST.C: 68: i5 = 3;
ld hl,03h
jp p,L2

ld (_i5),hl
l5:


2.Свертка констант


;TEST.C: 75: i3 = 1 + 2;
;успешно
ld hl,03h
L2:
ld (_i3),hl
;TEST.C: 76: flt_1 = 2.4 + 6.3;
;аналогично
ld de,(e1)
ld hl,(e1+02h)
ld (_flt_1),de
ld (_flt_1+02h),hl
;TEST.C: 77: i2 = 5;
ld hl,05h
ld (_i2),hl
;TEST.C: 78: j2 = i + 0;
;ничего прибавлять не стал, молодец :)
ld hl,(_i)
ld (_j2),hl
;TEST.C: 79: k2 = i / 1;
;равно как не стал и делить, плюс не стал лишний раз
;делать загрузку!
ld (_k2),hl
;TEST.C: 80: i4 = i * 1;
;аналогично
ld (_i4),hl
;TEST.C: 81: i5 = i * 0;
;ну и умножение на ноль тоже распознал
ld hl,0
ld (_i5),hl




;TEST.C: 94: flt_3 = 2.4 / 1.0;
;свернул деление
ld de,(e2)
ld hl,(e2+02h)
ld (_flt_3),de
ld (_flt_3+02h),hl
;TEST.C: 95: flt_4 = 1.0 + 0.0000001;
;свернул сложение
ld de,(e3)
ld hl,(e3+02h)
ld (_flt_4),de
ld (_flt_4+02h),hl
;TEST.C: 96: flt_5 = flt_6 * 0.0;
;а вот здесь прокосячил- наверное нет проверки на 0
;для констант с плавающей запятой
ld hl,(e4+02h)
push hl
ld hl,(e4)
push hl
ld de,(_flt_6)
ld hl,(_flt_6+02h)
call flmul
ld (_flt_5),de
ld (_flt_5+02h),hl
;TEST.C: 97: flt_6 = flt_2 * flt_3;
;ничего интересного
ld hl,(_flt_3+02h)
push hl
ld hl,(_flt_3)
push hl
ld de,(_flt_2)
ld hl,(_flt_2+02h)
call flmul
ld (_flt_6),de
ld (_flt_6+02h),hl


2.1.Ошибка деления на ноль была успешно распознана и компилятор ничего не собирал до тех пор, пока не определил NO_ZERO_DIVIDE

3.Лишнее присваивание


;TEST.C: 103: k3 = 1;
ld hl,01h
ld (_k3),hl
;TEST.C: 104: k3 = 1;
;сэкономил загрузку, но выполнил лишнее присваивание
;в силу того, что компилятор для встроенных систем на
;базе микроконтроллеров, повторное присваивание (а
;также чтение) имеют свой смысл. Так что это не ошибка
ld (_k3),hl


4.Снижение мощности


;TEST.C: 110: k2 = 4 * j5;
;вполне логично свернул умножение на 4
ld hl,(_j5)
add hl,hl
add hl,hl
ld (_k2),hl
;TEST.C: 111: for( i = 0; i <= 5; i++ )
;но просто отвратительно сделал цикл с изначально
;известными условиями- по шаблону
ld hl,0
ld (_i),hl
ld de,06h
ld hl,(_i)
call wrelop
jp p,l7
l6:
;TEST.C: 112: ivector4[ i ] = i * 2;
;чуда не произошло- снижения мощности нет
;в принципе, для такого шаблона без регистровых
;переменных это и логично...
ld de,_ivector4
ld hl,(_i)
add hl,hl
add hl,de
ex de,hl
ld hl,(_i)
add hl,hl
ld a,l
ld (de),a
inc de
ld a,h
ld (de),a
ld hl,(_i)
inc hl
ld (_i),hl
ld de,06h
call wrelop
jp m,l6
l7:


5.Простой цикл


;TEST.C: 118: j5 = 0;
ld hl,0
ld (_j5),hl
;TEST.C: 119: k5 = 10000;
ld hl,02710h
ld (_k5),hl
l11:
;TEST.C: 120: do {
;TEST.C: 121: k5 = k5 - 1;
;недостатки отсутствия регистровых переменных во
;всей красе...
ld hl,(_k5)
dec hl
ld (_k5),hl
;TEST.C: 122: j5 = j5 + 1;
ld hl,(_j5)
inc hl
ld (_j5),hl
;TEST.C: 123: i5 = (k5 * 3) / (j5 * 5);
;хотя тут их отсутствие вполне закономерно- иначе
;пришлось бы мучаться со стеком
;достойная свертка констант умножения
ld b,h
ld c,l
add hl,hl
add hl,hl
add hl,bc
ex de,hl
ld hl,(_k5)
ld b,h
ld c,l
add hl,hl
add hl,bc
call adiv
ld (_i5),hl
;TEST.C: 124: } while ( k5 > 0 );
;глупое сравнение на >=1...
ld de,01h
ld hl,(_k5)
call wrelop
jp p,l11


6.Управление переменной индукции цикла


;TEST.C: 129: for( i = 0; i < 100; i++ )
;та же лажа с циклом
ld hl,0
ld (_i),hl
ld de,064h
call wrelop
jp p,l13
l12:
;TEST.C: 130: ivector5[ i * 2 + 3 ] = 5;
;переменной индукции нет (не регистровая)
;но смещение индекса преобразовано в смещение базы
;массива
ld hl,(_i)
add hl,hl
add hl,hl
ld de,_ivector5+06h
add hl,de
ld (hl),05h
inc hl
ld (hl),0
ld hl,(_i)
inc hl
ld (_i),hl
ld de,064h
call wrelop
jp m,l12
l13:


7.Глубокие подвыражения


;TEST.C: 136: if( i < 10 )
ld de,0Ah
ld hl,(_i)
call wrelop
;TEST.C: 137: j5 = i5 + i2;
;весьма хитро- загрузку параметров вынесли перед
;переходом, а сложение после, чтобы не портить флаг
ld hl,(_i5)
ld de,(_i2)
jp p,L1

add hl,de
ld (_j5),hl
;TEST.C: 138: else
jp l16
;TEST.C: 139: k5 = i5 + i2;
L1:
add hl,de
ld (_k5),hl
l16:


8.Генерация адреса переменной с константным индексом, размножение копий и регистров


;TEST.C: 147: ivector[ 0 ] = 1;
;логично
ld hl,01h
ld (_ivector),hl
;TEST.C: 148: ivector[ i2 ] = 2;
ld hl,(_i2)
add hl,hl
ld de,_ivector
add hl,de
ld (hl),02h
inc hl
ld (hl),0
;TEST.C: 149: ivector[ i2 ] = 2;
;повтор вычислений, но запоминание смещения-
;недостаток модели распределения регистров
ld hl,(_i2)
add hl,hl
add hl,de
ld (hl),02h
inc hl
ld (hl),0
;TEST.C: 150: ivector[ 2 ] = 3;
;тоже логично :)
ld hl,03h
ld (_ivector+04h),hl


9.Удаление общих подвыражений


;TEST.C: 157: if(( h3 + k3 ) < 0 || ( h3 + k3 ) > 5 )
ld hl,(_h3)
ld de,(_k3)
add hl,de
;наконец-то вспомнили о битовых операциях...
bit 07h,h
jp nz,u90
;а тут косяк- нахрена подобные вычисления?
;переменные ведь не volatile...
ld de,06h
ld hl,(_h3)
ld bc,(_k3)
add hl,bc
call wrelop
jp m,u91
u90:
;TEST.C: 158: printf("Common subexpression elimination\n");
ld hl,u29
push hl
call _printf
pop bc
;TEST.C: 159: else {
jp l18
u91:
;TEST.C: 160: m3 = ( h3 + k3 ) / i3;
;опять вычисления с нуля
ld de,(_i3)
ld hl,(_h3)
ld bc,(_k3)
add hl,bc
call adiv
ld (_m3),hl
;TEST.C: 161: g3 = i3 + (h3 + k3);
;фиаско! никаких промежуточных сохранений результатов
ld hl,(_i3)
ld de,(_h3)
add hl,de
ld de,(_k3)
add hl,de
ld (_g3),hl
l18:
;TEST.C: 162: }


10.Вынесение инвариантного кода


;TEST.C: 168: for( i4 = 0; i4 <= 2; i4++)
;все тот же бешеный цикл...
ld hl,0
ld (_i4),hl
ld de,03h
ld hl,(_i4)
call wrelop
jp p,l20
l19:
;TEST.C: 169: ivector2[ i4 ] = j * k;
;полная Ж... вычисление j * k в каждой итерации цикла
ld a,(_k)
ld e,a
ld d,0
ld a,(_j)
ld l,a
ld h,d
call lmul
ld a,l
ld hl,(_i4)
ld de,_ivector2
add hl,de
ld (hl),a
ld hl,(_i4)
inc hl
ld (_i4),hl
ld de,03h
call wrelop
jp m,l19
l20:

Vitamin
19.11.2006, 15:11
11.Вызов функции с аргументами. Определение недостижимого кода


;TEST.C: 175: dead_code( 1, "This line should not be printed" );
;вызов типа fastcall- все что можно, через регистры
ld bc,u39
ld de,01h
call _dead_code




;TEST.C: 192: void dead_code( a, b )
;TEST.C: 193: int a;
;TEST.C: 194: char *b;
;TEST.C: 195: {
_dead_code:
;TEST.C: 196: int idead_store;
;TEST.C: 198: idead_store = a;
;о! первое использование регистровых
;переменных
; _idead_store allocated to hl
ld l,e
ld h,d
;TEST.C: 199: if( 0 )
;пустышка благополучно свернута. честь и хвала!
ret
;TEST.C: 201: }


12.Вызов функции без аргументов. Исключение циклов


;TEST.C: 181: unnecessary_loop();
;простенько и со вкусом :)
call _unnecessary_loop




;TEST.C: 211: void unnecessary_loop()
;TEST.C: 212: {
_unnecessary_loop:
;TEST.C: 213: int x;
;TEST.C: 215: x = 0;
;еще одна регистровая переменная
; _x allocated to bc
ld bc,0
;TEST.C: 216: for( i = 0; i < 5; i++ )
;более глубокий анализ убрал бы этот цикл нафиг...
;но см. примечание про повторную загрузку
ld l,c
ld h,b
ld (_i),hl
ld de,05h
call wrelop
ret p
l25:
;TEST.C: 218: k5 = x + j5;
;не свернул х=0... никому не нужное сложение
ld hl,(_j5)
add hl,bc
ld (_k5),hl
ld hl,(_i)
inc hl
ld (_i),hl
ld de,05h
call wrelop
jp m,l25
;TEST.C: 219: }
ret


13. Слияние заголовков циклов


;TEST.C: 228: void loop_jamming( x )
;TEST.C: 229: int x;
;TEST.C: 230: {
_loop_jamming:
;пролог функции- выделение стека под локальные
;переменные и параметр
push ix
ld ix,0
add ix,sp
push bc
;_x stored from de
ld (ix+-2),e
ld (ix+-1),d
;TEST.C: 231: for( i = 0; i < 5; i++ )
ld hl,0
ld (_i),hl
ld de,05h
ld hl,(_i)
call wrelop
jp p,l30
l29:
;TEST.C: 232: k5 = x + j5 * i;
ld de,(_i)
ld hl,(_j5)
call amul
ld e,(ix+-2)
ld d,(ix+-1)
add hl,de
ld (_k5),hl
ld hl,(_i)
inc hl
ld (_i),hl
ld de,05h
call wrelop
jp m,l29
l30:
;TEST.C: 233: for( i = 0; i < 5; i++ )
;чуда нет- слияния заголовков циклов тоже
ld hl,0
ld (_i),hl
ld de,05h
ld hl,(_i)
call wrelop
jp p,l28
l32:
;TEST.C: 234: i5 = x * k5 * i;
ld de,(_k5)
ld l,(ix+-2)
ld h,(ix+-1)
call amul
ld de,(_i)
call amul
ld (_i5),hl
ld hl,(_i)
inc hl
ld (_i),hl
ld de,05h
call wrelop
jp m,l32
;TEST.C: 235: }
l28:


14.Разворачивание циклов


;TEST.C: 246: void loop_unrolling( x )
;TEST.C: 247: int x;
;TEST.C: 248: {
_loop_unrolling:
;TEST.C: 249: for( i = 0; i < 6; i++ )
;тоже без чуда- возможно, число итераций цикла
;слишком велико для разворота, но опций не нашел
ld hl,0
ld (_i),hl
ld de,06h
ld hl,(_i)
call wrelop
ret p
l36:
;TEST.C: 250: ivector4[ i ] = 0;
ld hl,(_i)
add hl,hl
ld de,_ivector4
add hl,de
ld (hl),0
inc hl
ld (hl),0
ld hl,(_i)
inc hl
ld (_i),hl
ld de,06h
call wrelop
jp m,l36
;TEST.C: 251: }
ret


15.Сжатие цепочки переходов


;TEST.C: 260: int jump_compression( i, j, k, l, m )
;TEST.C: 261: int i, j, k, l, m;
;TEST.C: 262: {
_jump_compression:
;монструозный пролог- много переменных на входе
;все равно не оптимально...
push ix
ld ix,0
add ix,sp
push bc
push bc
;_j stored from bc
ld (ix+-4),c
ld (ix+-3),b
;_i stored from de
ld (ix+-2),e
ld (ix+-1),d
l40:
; _l loaded to bc
ld c,(ix+6)
ld b,(ix+7)
;TEST.C: 263: beg_1:
;TEST.C: 264: if( i < j )
ld e,(ix+-4)
ld d,(ix+-3)
ld l,(ix+-2)
ld h,(ix+-1)
call wrelop
jp p,l41
;TEST.C: 265: if( j < k )
ld e,(ix+4)
ld d,(ix+5)
ld l,(ix+-4)
ld h,(ix+-3)
call wrelop
jp p,l42
;TEST.C: 266: if( k < l )
ld e,c
ld d,b
ld l,(ix+4)
ld h,(ix+5)
call wrelop
jp p,l43
;TEST.C: 267: if( l < m )
ld e,(ix+8)
ld d,(ix+9)
ld l,c
ld h,b
call wrelop
;сжатия нет- помешало невесть откуда взявшееся
;сохранение l (bc), хотя к данному моменту оно не менялось
jp p,l46
;TEST.C: 268: l += m;
ld l,(ix+8)
ld h,(ix+9)
add hl,bc
push hl
pop bc
;TEST.C: 269: else
jp l49
;TEST.C: 271: else
l43:
;TEST.C: 272: k += l;
ld l,(ix+4)
ld h,(ix+5)
add hl,bc
ld (ix+4),l
ld (ix+5),h
;TEST.C: 273: else {
jp l49
l42:
;TEST.C: 274: j += k;
ld e,(ix+4)
ld d,(ix+5)
ld l,(ix+-4)
ld h,(ix+-3)
add hl,de
ld (ix+-4),l
ld (ix+-3),h
l46:
;TEST.C: 275: end_1:
;_l stored from bc
ld (ix+6),c
ld (ix+7),b
;TEST.C: 276: goto beg_1;
jp l40
;TEST.C: 277: }
;TEST.C: 278: else
l41:
;TEST.C: 279: i += j;
ld e,(ix+-4)
ld d,(ix+-3)
ld l,(ix+-2)
ld h,(ix+-1)
add hl,de
ld (ix+-2),l
ld (ix+-1),h
l49:
;TEST.C: 280: return( i + j + k + l + m );
ld e,(ix+8)
ld d,(ix+9)
ld l,(ix+-4)
ld h,(ix+-3)
add hl,de
ld e,(ix+4)
ld d,(ix+5)
add hl,de
ld e,c
ld d,b
add hl,de
ld e,(ix+-2)
ld d,(ix+-1)
add hl,de
;TEST.C: 281: }
;эпилог- очистка стека, не рационально...
ld sp,ix
pop ix
pop bc
pop af
pop af
pop af
push bc
ret



Фух! Вроде все сделал.
Итоговая оценка (субъективно)- 8/10. Годится для быстрой проверки идей, для создания готовых программ следует подходить с осторожностью.

Камрады, протестите плз другие компилеры и подобным образом откомментируйте их код :)

Vitamin
19.11.2006, 16:37
Снял слепки с Avoset, sdcc, z88dk. В ближайшее время попробую проанализировать и их код. У кого еще какие компилеры завалялись?

fk0
19.11.2006, 17:50
Вах-вах! HI-TECH C Z80/Z180 = $950 - приятная цена! :)

Что заметно дешевле KEIL. Так что как сказать...

fk0
19.11.2006, 17:53
Все попытки скачать файл с RapidShare лично для меня не увенчались успехом :)

Hitech могу дать.

Vitamin
19.11.2006, 18:40
Итак, препарируемый- Avocet. Этот компилятор не понял старого синтаксиса теста (см. заголовки функций), поэтому пришлось слегка его подработать напильником.
Вот что он нагенерил (лишние директивы вырезаны).

0.Пролог


;не суть важно, все равно один раз делается...
push ix
push de
push hl
ld ix,-?TSC0
add ix,sp
push af


1.Размножение констант и копий


ld hl,2
ld (_j4),hl
;лишняя операция
ld de,(_j4)
ld hl,(_i2)
and a
;использование нативных операций- плюс в копилку
sbc hl,de
;хитровымудренная система переходов- жирный минус
jp p,$+8
jp pe,?BOL0
jr +3
jp po,?BOL0
?ACC0: .equal $
ld de,(_j4)
ld hl,(_i4)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL0
jr +3
jp po,?BOL0
?PLC0: .equal $
ld hl,2
ld (_i2),hl
?BOL0: .equal $
;короче, никаких размножений констант не применяется
;и этот кусок- практически полная копия предыдущего
ld hl,(_k5)
ld (_j4),hl
ld e,l
ld d,h
ld hl,(_i2)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL1
jr +3
jp po,?BOL1
?ACC1: .equal $
ld de,(_j4)
ld hl,(_i4)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL1
jr +3
jp po,?BOL1
?PLC1: .equal $
ld hl,3
ld (_i5),hl
?BOL1: .equal $


2.Свертка констант


;благополучно свернул целочисленные константы
ld hl,3
ld (_i3),hl

.const_data
?CGL0: .double 8.69999999999999930000
.program
;также свернул дробную
ld de,?CGL0
ld hl,_flt_1
call __store_double
;просто константа
ld hl,5
ld (_i2),hl
;а это убожество...
ld de,0
ld hl,(_i)
add hl,de
ld (_j2),hl
;здесь не сообразил что на 1 делить не надо...
ld de,1
ld hl,(_i)
call __div_int
ld (_k2),hl
;да и умножать тоже...
ld de,1
ld hl,(_i)
call __mult_int
ld (_i4),hl
;а это вообще хохма
ld de,0
ld hl,(_i)
call __mult_int
ld (_i5),hl
;и на 0 мы делить тоже умеем! :)
;как целочисленно...
ld de,0
ld hl,(_i)
call __div_int
ld (_i2),hl

.const_data
?CGL1: .double 0.0
.program
;...так и с плавающей запятой
ld de,?CGL1
ld hl,_flt_1
call __div_double
ex de,hl
ld hl,_flt_2
call __store_double

.const_data
?CGL2: .double 2.39999999999999990000
.program
;вот деление константы на константу он свернул
ld de,?CGL2
ld hl,_flt_3
call __store_double

.const_data
?CGL3: .double 1.00000010000000010000
.program
;сложение тоже
ld de,?CGL3
ld hl,_flt_4
call __store_double

.const_data
?CGL4: .double 0.0
.program
;но вот умножение на 0 не догадался облагородить
ld de,?CGL4
ld hl,_flt_6
call __mult_double
ex de,hl
ld hl,_flt_5
call __store_double
;ничего интересного
ld de,_flt_3
ld hl,_flt_2
call __mult_double
ex de,hl
ld hl,_flt_6
call __store_double


3.Лишнее присваивание


;за такое надо руки отрывать...
ld hl,1
ld (_k3),hl
ld hl,1
ld (_k3),hl


4.Снижение мощности


;никакой фантазии...
ld de,(_j5)
ld hl,4
call __mult_int
ld (_k2),hl
ld hl,0
ld (_i),hl
?FLC2: .equal $
ld de,5
ld hl,(_i)
and a
sbc hl,de
;опять сложная система переходов
jr z,+11
jp p,$+8
jp pe,?BOL2
jr +3
jp po,?BOL2
jp ?FLB2
?FLA2: .equal $
;регистровые переменные не поддерживаются,
;по крайней мере здесь
ld hl,(_i)
inc hl
ld (_i),hl
jp ?FLC2
?FLB2: .equal $
;это просто мрак...
ld de,2
ld hl,(_i)
call __mult_int
ld (ix+0),l
ld (ix+0+1),h
ld hl,(_i)
add hl,hl
ld bc,_ivector4
add hl,bc
ld e,l
ld d,h
;люди, не смотрите на это :)
ld l,(ix+0)
ld h,(ix+0+1)
push de
pop iy
ld (iy+0),l
ld (iy+1),h
jp ?FLA2
?BOL2: .equal $


5.Простой цикл


ld hl,0
ld (_j5),hl
ld hl,10000
ld (_k5),hl
?TOL3: .equal $
;просто ни ума, ни фантазии...
ld de,1
ld hl,(_k5)
and a
sbc hl,de
ld (_k5),hl
ld de,1
ld hl,(_j5)
add hl,de
ld (_j5),hl

ld de,3
ld hl,(_k5)
call __mult_int
ld (ix+0),l
ld (ix+0+1),h
ld de,5
ld hl,(_j5)
call __mult_int
ld e,l
ld d,h
ld l,(ix+0)
ld h,(ix+0+1)
call __div_int
ld (_i5),hl
?DCL3: .equal $
;просто верх кодерского разума- сравнение на 0...
ld de,0
ld hl,(_k5)
and a
sbc hl,de
jp z,?BOL3
jp p,$+8
jp po,?BOL3
jr +3
jp pe,?BOL3
?PLC2: .equal $
jp ?TOL3
?BOL3: .equal $


6.Управление переменной индукции цикла


;достаточно приличный заголовок цикла
ld hl,0
ld (_i),hl
?FLC4: .equal $
ld de,100
ld hl,(_i)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL4
jr +3
jp po,?BOL4
jp ?FLB4
?FLA4: .equal $
ld hl,(_i)
inc hl
ld (_i),hl
jp ?FLC4
?FLB4: .equal $
;а здесь начинаются страшные вычисления без каких
;бы то ни было следов оптимизации
ld de,2
ld hl,(_i)
call __mult_int
ld e,l
ld d,h
ld hl,3
add hl,de
add hl,hl
ld bc,_ivector5
add hl,bc
ld e,l
ld d,h
ld hl,5
push de
pop iy
ld (iy+0),l
ld (iy+1),h
jp ?FLA4
?BOL4: .equal $


7. Глубокие подвыражения


;без слов. все и так видно...
ld de,10
ld hl,(_i)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL5
jr +3
jp po,?BOL5
?PLC3: .equal $
ld de,(_i2)
ld hl,(_i5)
add hl,de
ld (_j5),hl
jp ?EOI5
?BOL5: .equal $
ld de,(_i2)
ld hl,(_i5)
add hl,de
ld (_k5),hl
?EOI5: .equal $


8.Генерация адреса переменной с константным индексом, размножение копий и регистров


ld hl,_ivector+0
ld e,l
ld d,h
ld hl,1
;ребята наверное не знают про команду ld (hl),..
push de
pop iy
ld (iy+0),l
ld (iy+1),h
ld hl,(_i2)
add hl,hl
ld bc,_ivector
add hl,bc
ld e,l
ld d,h
ld hl,2
push de
pop iy
ld (iy+0),l
ld (iy+1),h
ld hl,(_i2)
add hl,hl
ld bc,_ivector
add hl,bc
ld e,l
ld d,h
ld hl,2
push de
pop iy
ld (iy+0),l
ld (iy+1),h
ld hl,_ivector+4
ld e,l
ld d,h
ld hl,3
push de
pop iy
ld (iy+0),l
ld (iy+1),h


9.Удаление общих подвыражений


ld de,(_k3)
ld hl,(_h3)
add hl,de
ld de,0
and a
sbc hl,de
jp p,$+8
jp po,?PLC4
jr +3
jp pe,?PLC4
?OCC2: .equal $
ld de,(_k3)
ld hl,(_h3)
add hl,de
ld de,5
and a
sbc hl,de
jp z,?BOL6
jp p,$+8
jp po,?BOL6
jr +3
jp pe,?BOL6
?PLC4: .equal $
.const_data
?PLC5: .byte "Common subexpression elimination",0ah,0
.program
ld hl,?PLC5
call _printf
jp ?EOI6
?BOL6: .equal $
;иными словами, никаких выделений не производится
ld de,(_k3)
ld hl,(_h3)
add hl,de
ld de,(_i3)
call __div_int
ld (_m3),hl
ld de,(_k3)
ld hl,(_h3)
add hl,de
ld e,l
ld d,h
ld hl,(_i3)
add hl,de
ld (_g3),hl
?EOI6: .equal $


10.Вынесение инвариантного кода


;приемлимое начало цикла
ld hl,0
ld (_i4),hl
?FLC7: .equal $
ld de,2
ld hl,(_i4)
and a
sbc hl,de
jr z,+11
;но его структура в коде просто ужасна!
jp p,$+8
jp pe,?BOL7
jr +3
jp po,?BOL7
jp ?FLB7
?FLA7: .equal $
ld hl,(_i4)
inc hl
ld (_i4),hl
jp ?FLC7
?FLB7: .equal $
;никакого вынесения нет- вычисления на каждой итерации
ld de,(_k)
ld hl,(_j)
call __mult_int
ld (ix+0),l
ld (ix+0+1),h
ld hl,(_i4)
ld bc,_ivector2
add hl,bc
ld e,l
ld d,h
ld l,(ix+0)
ld h,(ix+0+1)
ld a,l
ld (de),a
jp ?FLA7

Vitamin
19.11.2006, 18:41
11.Вызов функции с аргументами. Определение недостижимого кода


.const_data
?PLC6: .byte "This line should not be printed",0
.program
;хоть тут никаких изысков, параметры в регистрах
ld de,?PLC6
ld hl,1
call _dead_code




_dead_code: .equal $
;страшный пролог!
push ix
push de
push hl
ld ix,-?TSC1
add ix,sp
push af

ld l,(ix+0+?TSC1)
ld h,(ix+0+?TSC1+1)
ld (ix-2),l
ld (ix-2+1),h
;страх и ужас!
ld a,0
cp a,0
jp z,?BOL8
?PLC7: .equal $
.const_data
?PLC8: .byte "%s",0ah,0
.program
ld e,(ix+2+?TSC1)
ld d,(ix+2+?TSC1+1)
ld hl,?PLC8
call _printf
?BOL8: .equal $
?BOF1: .equal $
;и не менее страшный эпилог
pop bc
pop bc
pop bc
pop ix
ret


12.Вызов функции без аргументов. Исключение циклов


;как обычно, ничего никуда не передаем
call _unnecessary_loop




_unnecessary_loop: .equal $
push ix
ld ix,-?TSC2
add ix,sp
push af
;все тот же кошмарный пролог...
ld hl,0
ld (ix-2),l
ld (ix-2+1),h
ld hl,0
ld (_i),hl
?FLC9: .equal $
ld de,5
ld hl,(_i)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL9
jr +3
jp po,?BOL9
jp ?FLB9
?FLA9: .equal $
ld hl,(_i)
inc hl
ld (_i),hl
jp ?FLC9
?FLB9: .equal $
;постоянные вычисления, тут даже пресловутое
;примечание опускает руки :)
ld de,(_j5)
ld l,(ix-2)
ld h,(ix-2+1)
add hl,de
ld (_k5),hl
jp ?FLA9
?BOL9: .equal $
?BOF2: .equal $
pop bc
pop ix
ret


13. Слияние заголовков циклов


_loop_jamming: .equal $
push ix
push hl
ld ix,-?TSC3
add ix,sp
ld hl,0
ld (_i),hl
?FLC10: .equal $
ld de,5
ld hl,(_i)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL10
jr +3
jp po,?BOL10
jp ?FLB10
?FLA10: .equal $
ld hl,(_i)
inc hl
ld (_i),hl
jp ?FLC10
?FLB10: .equal $
ld de,(_i)
ld hl,(_j5)
call __mult_int
ld e,l
ld d,h
ld l,(ix+0+?TSC3)
ld h,(ix+0+?TSC3+1)
add hl,de
ld (_k5),hl
jp ?FLA10
?BOL10: .equal $
;никакого слияния плюс страшные вычисления
ld hl,0
ld (_i),hl
?FLC11: .equal $
ld de,5
ld hl,(_i)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL11
jr +3
jp po,?BOL11
jp ?FLB11
?FLA11: .equal $
ld hl,(_i)
inc hl
ld (_i),hl
jp ?FLC11
?FLB11: .equal $
ld de,(_k5)
ld l,(ix+0+?TSC3)
ld h,(ix+0+?TSC3+1)
call __mult_int
ld e,l
ld d,h
ld hl,(_i)
call __mult_int
ld (_i5),hl
jp ?FLA11
?BOL11: .equal $
?BOF3: .equal $
pop bc
pop ix
ret


14.Разворачивание циклов


_loop_unrolling: .equal $
push ix
push hl
ld ix,-?TSC4
add ix,sp
ld hl,0
ld (_i),hl
?FLC12: .equal $
;разворота нет
ld de,6
ld hl,(_i)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL12
jr +3
jp po,?BOL12
jp ?FLB12
?FLA12: .equal $
ld hl,(_i)
inc hl
ld (_i),hl
jp ?FLC12
?FLB12: .equal $
;да еще и вычисления страшные
ld hl,(_i)
;хоть не догадался умножать на 2 процедурой...
add hl,hl
ld bc,_ivector4
add hl,bc
ld e,l
ld d,h
ld hl,0
push de
pop iy
ld (iy+0),l
ld (iy+1),h
jp ?FLA12
?BOL12: .equal $
?BOF4: .equal $
pop bc
pop ix
ret


15.Сжатие цепочки переходов


_jump_compression: .equal $
push ix
push de
push hl
ld ix,-?TSC5
add ix,sp
.c_start 0ba1h,260
?beg_1: .equal $
ld e,(ix+2+?TSC5)
ld d,(ix+2+?TSC5+1)
ld l,(ix+0+?TSC5)
ld h,(ix+0+?TSC5+1)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL13
jr +3
jp po,?BOL13
?PLC9: .equal $
ld e,(ix+8+?TSC5)
ld d,(ix+8+?TSC5+1)
ld l,(ix+2+?TSC5)
ld h,(ix+2+?TSC5+1)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL14
jr +3
jp po,?BOL14
?PLC10: .equal $
ld e,(ix+10+?TSC5)
ld d,(ix+10+?TSC5+1)
ld l,(ix+8+?TSC5)
ld h,(ix+8+?TSC5+1)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL15
jr +3
jp po,?BOL15
?PLC11: .equal $
ld e,(ix+12+?TSC5)
ld d,(ix+12+?TSC5+1)
ld l,(ix+10+?TSC5)
ld h,(ix+10+?TSC5+1)
and a
sbc hl,de
jp p,$+8
jp pe,?BOL16
jr +3
jp po,?BOL16
?PLC12: .equal $
ld e,(ix+12+?TSC5)
ld d,(ix+12+?TSC5+1)
ld l,(ix+10+?TSC5)
ld h,(ix+10+?TSC5+1)
add hl,de
ld (ix+10+?TSC5),l
ld (ix+10+?TSC5+1),h
jp ?EOI16
?BOL16: .equal $
;нет оптимизации
jp ?end_1
?EOI16: .equal $
jp ?EOI15
?BOL15: .equal $
ld e,(ix+10+?TSC5)
ld d,(ix+10+?TSC5+1)
ld l,(ix+8+?TSC5)
ld h,(ix+8+?TSC5+1)
add hl,de
ld (ix+8+?TSC5),l
ld (ix+8+?TSC5+1),h
?EOI15: .equal $
jp ?EOI14
?BOL14: .equal $
ld e,(ix+8+?TSC5)
ld d,(ix+8+?TSC5+1)
ld l,(ix+2+?TSC5)
ld h,(ix+2+?TSC5+1)
add hl,de
ld (ix+2+?TSC5),l
ld (ix+2+?TSC5+1),h
?end_1: .equal $
jp ?beg_1
?EOI14: .equal $
jp ?EOI13
?BOL13: .equal $
ld e,(ix+2+?T
;а дальше текст почемуто потерян...


Итоговая оценка- 4/10. Поставил бы 3/10, да понравился достаточно легкий заголовок цикла.
Плюс данный компилятор распространяетя со средой разработки и отладки под винду. Опций настройки я не нашел- они задавались в настройках проекта, но в хелпе я нашел не все указанные опции. Про оптимизацию там не было сказано ни слова. Итого- это просто транслятор с примитивной сверткой констант (и только!). Выходной ассемблерный файл без указания строк исходного файла, весьма неудобно по нему лазить.
Короче, использовать не рекомендуется :)

Vitamin
19.11.2006, 19:23
Следующий кандидат- Small Device C Compiler
Испытания проводились с оптимизацией по размеру и по скорости- результат одинаковый.

0. Пролог.


;классика жанра для переменных в стеке
_main:
push ix
ld ix,#0
add ix,sp


1. Тест на размножение констант и копий.


;жирный-жирный минус- использование тяжелой
;артиллерии в виде индексных регистров
;test.c:59: j4 = 2;
ld iy,#_j4
ld 0(iy),#0x02
ld 1(iy),#0x00
;test.c:60: if( i2 < j4 && i4 < j4 )
;вот оно- распространение констант в действии!!!
ld iy,#_i2
;вместо вычитания j4 используется вычитание константы
ld a,0(iy)
sub a,#0x02
ld a,1(iy)
sbc a,#0x00
jp p,00102$
;аналогично вторая половина
ld iy,#_i4
ld a,0(iy)
sub a,#0x02
ld a,1(iy)
sbc a,#0x00
jp p,00102$
;test.c:61: i2 = 2;
;опять IY...
ld iy,#_i2
ld 0(iy),#0x02
ld 1(iy),#0x00
00102$:
;test.c:63: j4 = k5;
;ну почему загрузка сделана нормально, но сохранение
;так лажово?
ld hl,(_k5)
ld iy,#_j4
ld 0(iy),l
ld 1(iy),h
;test.c:64: if( i2 < j4 && i4 < j4 )
;просто страшная перезагрузка!!! нет использования
;предыдущего операнда в hl!!!
ld iy,#_i2
ld a,0(iy)
ld iy,#_j4
sub a,0(iy)
ld iy,#_i2
ld a,1(iy)
ld iy,#_j4
sbc a,1(iy)
jp p,00105$
;то же самое...
ld iy,#_i4
ld a,0(iy)
ld iy,#_j4
sub a,0(iy)
ld iy,#_i4
ld a,1(iy)
ld iy,#_j4
sbc a,1(iy)
jp p,00105$
;test.c:65: i5 = 3;
ld iy,#_i5
ld 0(iy),#0x03
ld 1(iy),#0x00
00105$:


2.Свертка констант


;test.c:72: i3 = 1 + 2;
;свернул
ld iy,#_i3
ld 0(iy),#0x03
ld 1(iy),#0x00
;test.c:73: flt_1 = 2.4 + 6.3;
;вот здесь использование индексных регистров можно
;оправдать, да и то с натяжкой...
ld iy,#_flt_1
ld 0(iy),#0x33
ld 1(iy),#0x33
ld 2(iy),#0x0B
ld 3(iy),#0x41
;test.c:74: i2 = 5;
ld iy,#_i2
ld 0(iy),#0x05
ld 1(iy),#0x00
;test.c:75: j2 = i + 0;
;0 не стал добавлять, просто копирование
ld hl,(_i)
ld iy,#_j2
ld 0(iy),l
ld 1(iy),h
;test.c:76: k2 = i / 1;
;и на 1 делить не стал
ld hl,(_i)
ld iy,#_k2
ld 0(iy),l
ld 1(iy),h
;test.c:77: i4 = i * 1;
;да и умножать тоже
ld hl,(_i)
ld iy,#_i4
ld 0(iy),l
ld 1(iy),h
;test.c:78: i5 = i * 0;
;сообразительный малый :)
ld iy,#_i5
ld 0(iy),#0x00
ld 1(iy),#0x00
;test.c:88: printf( "This compiler handles divide-by-zero as
;деление на 0 не словил на этапе комппиляции, пытается
;печатать
;передача параметров через стек- не очень хорошо...
ld hl,#__str_0
push hl
call _printf
;и очистка вызывающей функцией- классическая
;парадигма _cdecl
pop af
;test.c:91: flt_3 = 2.4 / 1.0;
;с плавающей запятой константы тоже сворачивает
ld iy,#_flt_3
ld 0(iy),#0x9A
ld 1(iy),#0x99
ld 2(iy),#0x19
ld 3(iy),#0x40
;test.c:92: flt_4 = 1.0 + 0.0000001;
ld iy,#_flt_4
ld 0(iy),#0x01
ld 1(iy),#0x00
ld 2(iy),#0x80
ld 3(iy),#0x3F
;test.c:93: flt_5 = flt_6 * 0.0;
;молодец :)
ld iy,#_flt_5
ld 0(iy),#0x00
ld 1(iy),#0x00
ld 2(iy),#0x00
ld 3(iy),#0x00
;test.c:94: flt_6 = flt_2 * flt_3;
;распространение константы flt_3 = 2.4
ld hl,#0x4019
push hl
ld hl,#0x999A
push hl
ld hl,(_flt_2 + 2)
push hl
ld hl,(_flt_2)
push hl
call ___fsmul
;заволновался по поводу hl...
ld b,h
ld c,l
;освобождение стека- 8 байт
pop af
pop af
pop af
pop af
ld iy,#_flt_6
ld 0(iy),c
ld 1(iy),b
ld 2(iy),e
ld 3(iy),d


3.Лишнее присваивание


;test.c:101: k3 = 1;
;было благополучно удалено!
ld iy,#_k3
ld 0(iy),#0x01
ld 1(iy),#0x00


4.Снижение мощности


;test.c:107: k2 = 4 * j5;
;это просто "шедевр"! это надо видеть!!!
ld iy,#_j5
ld a,0(iy)
ld iy,#_k2
ld 0(iy),a
ld iy,#_j5
ld a,1(iy)
ld iy,#_k2
ld 1(iy),a
;впервые на манеже ТАКИЕ извращения при попытке
;заменить умножение сдвигами :)
ld a,#0x02+1
jp 00146$
00145$:
ld iy,#_k2
sla 0(iy)
rl 1(iy)
00146$:
dec a
jp nz,00145$

;test.c:108: for( i = 0; i <= 5; i++ )
;переменная цикла тоже в индексном... грустно...
ld iy,#_i
ld 0(iy),#0x00
ld 1(iy),#0x00
00117$:
ld a,#0x05
ld iy,#_i
sub a,0(iy)
ld a,#0x00
sbc a,1(iy)
jp m,00120$
;test.c:109: ivector4[ i ] = i * 2;
;мрачно...
ld c,0(iy)
ld b,1(iy)
sla c
rl b

ld hl,#_ivector4
add hl,bc
;так и не понял, для чего эти две команды...
ld e,l
ld d,h
ld (hl),c
inc hl
ld (hl),b
;test.c:108: for( i = 0; i <= 5; i++ )
;а вот это небольшой финт- полупересчетка
ld iy,#_i
inc 0(iy)
jp nz,00149$
inc 1(iy)
00149$:
jp 00117$
00120$:


5.Простой цикл


;test.c:115: j5 = 0;
ld iy,#_j5
ld 0(iy),#0x00
ld 1(iy),#0x00
;test.c:116: k5 = 10000;
ld iy,#_k5
ld 0(iy),#0x10
ld 1(iy),#0x27
;test.c:117: do {
00107$:
;test.c:118: k5 = k5 - 1;
;ну достаточно логичная конструкция- почему в остальных
;местах IY????
ld hl,(_k5)
dec hl
ld (_k5),hl
;test.c:119: j5 = j5 + 1;
;например, здесь????
ld iy,#_j5
inc 0(iy)
jp nz,00150$
inc 1(iy)
00150$:
;test.c:120: i5 = (k5 * 3) / (j5 * constant5);
;ну просто конфетка! :)
ld de,(_k5)
ld l,e
ld h,d
add hl,hl
add hl,de
ld c,l
ld b,h
;он даже константу развернул!!!
ld de,(_j5)
ld l,e
ld h,d
add hl,hl
add hl,hl
add hl,de
ld e,l
ld d,h
;параметры через стек
push de
push bc
call __divsint_rrx_s
;непонятного назначения конструкция...
ld b,h
ld c,l
pop af
pop af
ld iy,#_i5
ld 0(iy),c
ld 1(iy),b
;test.c:121: } while ( k5 > 0 );
;страшная конструкция...
ld a,#0x00
ld iy,#_k5
sub a,0(iy)
ld a,#0x00
sbc a,1(iy)
jp m,00107$


6.Управление переменной индукции цикла


;test.c:126: for( i = 0; i < 100; i++ )
;стандартный заголовок цикла
ld iy,#_i
ld 0(iy),#0x00
ld 1(iy),#0x00
00121$:
ld iy,#_i
ld a,0(iy)
sub a,#0x64
ld a,1(iy)
sbc a,#0x00
jp p,00124$
;test.c:127: ivector5[ i * 2 + 3 ] = 5;
;выделение индукции нет, но интересно- сообразил, что
; переменная цикла помещается в один байт
ld c,0(iy)
ld a,c
add a,a
ld c,a
;эх, не догадался базу массива сместить :)
inc c
inc c
inc c
;не забываем про размер
ld a,c
add a,a
ld c,a
;вот это интересно- использование полуслов адреса
ld a,#<_ivector5
add a,c
ld c,a
ld a,#>_ivector5
adc a,#0x00
ld b,a
;бережет он HL непонятно с какими целями...
ld l,c
ld h,b
ld (hl),#0x05
inc hl
ld (hl),#0x00
;test.c:126: for( i = 0; i < 100; i++ )
;стандарный инкремент
inc 0(iy)
jp nz,00151$
inc 1(iy)
00151$:
jp 00121$
00124$:


7.Глубокие подвыражения


;test.c:133: if( i < 10 )
ld iy,#_i
ld a,0(iy)
sub a,#0x0A
ld a,1(iy)
sbc a,#0x00
jp p,00111$
;test.c:134: j5 = i5 + i2;
;страхолюдная конструкция...
ld hl,#_i2
push de
ld iy,#_j5
push iy
pop de
ld iy,#_i5
ld a,0(iy)
add a,(hl)
ld (de),a
ld a,1(iy)
inc hl
adc a,(hl)
inc de
ld (de),a
pop de
jp 00112$
00111$:
;test.c:136: k5 = i5 + i2;
;иными словами- никакого выделения общего подвыражения нет
ld hl,#_i2
push de
ld iy,#_k5
push iy
pop de
ld iy,#_i5
ld a,0(iy)
add a,(hl)
ld (de),a
ld a,1(iy)
inc hl
adc a,(hl)
inc de
ld (de),a
pop de
00112$:


8.Генерация адреса переменной с константным индексом, размножение копий и регистров


;test.c:144: ivector[ 0 ] = 1;
;ну почему в обычном варианте этого нет???
ld hl,#_ivector
ld (hl),#0x01
inc hl
ld (hl),#0x00
;test.c:145: ivector[ i2 ] = 2;
;страсти-то какие...
ld iy,#_i2
ld c,0(iy)
ld b,1(iy)
sla c
rl b
dec hl
add hl,bc
ld c,l
ld b,h
ld (hl),#0x02
inc hl
ld (hl),#0x00
;test.c:146: ivector[ i2 ] = 2;
;эти две команды лишние, но в целом используется
;результат предыдущих вычислений
ld l,c
ld h,b
ld (hl),#0x02
inc hl
ld (hl),#0x00
;test.c:147: ivector[ 2 ] = 3;
;почему так странно?
ld bc,#_ivector + 4
ld l,c
ld h,b
ld (hl),#0x03
inc hl
ld (hl),#0x00


9.Удаление общих подвыражений


;test.c:154: if(( h3 + k3 ) < 0 || ( h3 + k3 ) > 5 )
;советую присмотреться внимательно- компилятор
;запомнил, что k3 не менялся и равен 1- размножение
;константы плюс сокращенные вычисления плюс сразу
;два сравнения
;ЗЫ. закрывайте глаза на реализацию идеи :)
ld iy,#_h3
ld c,0(iy)
ld b,1(iy)
;вот это мы добавляем к3
inc bc
;проверка на <0 - проще простого
ld a,b
bit 7,a
jp nz,00113$
;а также на >5
ld a,#0x05
sub a,c
ld a,#0x00
sbc a,b
jp p,00114$
00113$:
;test.c:155: printf("Common subexpression elimination\n");
;параметры через стек
ld hl,#__str_1
push hl
call _printf
pop af
jp 00115$
00114$:
;test.c:157: m3 = ( h3 + k3 ) / i3;
;выделение общих подвыражений действует!- выражение
;в скобках не вычисляется повторно, а хранится в bc
push bc
ld hl,(_i3)
push hl
push bc
call __divsint_rrx_s
ld d,h
ld e,l
pop af
pop af
pop bc
ld iy,#_m3
ld 0(iy),e
ld 1(iy),d
;test.c:158: g3 = i3 + (h3 + k3);
;аналогично и здесь
ld hl,#_g3
ld iy,#_i3
ld a,0(iy)
add a,c
ld (hl),a
ld a,1(iy)
adc a,b
inc hl
ld (hl),a
00115$:


10.Вынесение инвариантного кода


;test.c:166: for( i4 = 0; i4 <= max_vector; i4++)
ld iy,#_i4
ld 0(iy),#0x00
ld 1(iy),#0x00
00125$:
ld a,#0x02
ld iy,#_i4
sub a,0(iy)
ld a,#0x00
sbc a,1(iy)
jp m,00128$
;test.c:167: ivector2[ i4 ] = j * k;
;весьма оригинальное разыменование указателя
ld hl,#_i4
ld a,#<_ivector2
add a,(hl)
ld c,a
ld a,#>_ivector2
inc hl
adc a,(hl)
ld b,a
;но вынесения инвариантной части нет- каждый цикл
;выполняются вычисления
ld iy,#_j
ld e,0(iy)
ld iy,#_k
ld d,0(iy)
push bc
push de
inc sp
ld a,e
push af
inc sp
call __mulschar_rrx_s
ld e,l
pop af
pop bc
ld a,e
ld (bc),a
;test.c:166: for( i4 = 0; i4 <= max_vector; i4++)
ld iy,#_i4
inc 0(iy)
jp nz,00154$
inc 1(iy)
00154$:
jp 00125$
00128$:

Vitamin
19.11.2006, 19:47
11.Вызов функции с аргументами. Определение недостижимого кода


;test.c:173: dead_code( 1, "This line should not be printed" );
;обычная передача параметров через стек и очистка
ld hl,#__str_2
push hl
ld hl,#0x0001
push hl
call _dead_code
pop af
pop af




_dead_code:
;лишнее выделение стекового места, но полная оптимизация
;внутренностей функции
push ix
ld ix,#0
add ix,sp
;test.c:196: printf( "%s\n", b );
00103$:
pop ix
ret


12.Вызов функции без аргументов. Исключение циклов


;test.c:179: unnecessary_loop();
call _unnecessary_loop
00129$:




_unnecessary_loop:
;test.c:212: for( i = 0; i < 5; i++ )
ld iy,#_i
;обратите внимание- компилятор перевернул цикл!
ld 0(iy),#0x05
ld 1(iy),#0x00
00103$:
;test.c:214: k5 = x + j5;
;размножение константы х = 0
;но повторная загрузка имеется, простительно
ld hl,(_j5)
ld iy,#_k5
ld 0(iy),l
ld 1(iy),h
ld hl,(_i)
dec hl
ld (_i),hl
;test.c:212: for( i = 0; i < 5; i++ )
;оригинальная концовка!
ld iy,#_i
ld a,0(iy)
or a,1(iy)
jp nz,00103$
;а этот код потому что i является глобально переменной
ld 0(iy),#0x05
ld 1(iy),#0x00
00104$:
ret


13. Слияние заголовков циклов


_loop_jamming:
push ix
ld ix,#0
add ix,sp
;test.c:226: for( i = 0; i < 5; i++ )
ld iy,#_i
ld 0(iy),#0x00
ld 1(iy),#0x00
00101$:
ld iy,#_i
ld a,0(iy)
sub a,#0x05
ld a,1(iy)
sbc a,#0x00
jp p,00104$
;test.c:227: k5 = x + j5 * i;
ld hl,(_i)
push hl
ld hl,(_j5)
push hl
call __mulint_rrx_s
ld b,h
ld c,l
pop af
pop af
;переменная x хранится в стеке
ld hl,#_k5
ld a,4(ix)
add a,c
ld (hl),a
ld a,5(ix)
adc a,b
inc hl
ld (hl),a
;test.c:226: for( i = 0; i < 5; i++ )
ld iy,#_i
inc 0(iy)
jp nz,00115$
inc 1(iy)
00115$:
jp 00101$
00104$:
;test.c:228: for( i = 0; i < 5; i++ )
;слияния заголовков нет
ld iy,#_i
ld 0(iy),#0x00
ld 1(iy),#0x00
00105$:
ld iy,#_i
ld a,0(iy)
sub a,#0x05
ld a,1(iy)
sbc a,#0x00
jp p,00109$
;test.c:229: i5 = x * k5 * i;
ld hl,(_k5)
push hl
ld l,4(ix)
ld h,5(ix)
push hl
call __mulint_rrx_s
ld b,h
ld c,l
pop af
pop af
ld hl,(_i)
push hl
push bc
call __mulint_rrx_s
ld b,h
ld c,l
pop af
pop af
ld iy,#_i5
ld 0(iy),c
ld 1(iy),b
;test.c:228: for( i = 0; i < 5; i++ )
ld iy,#_i
inc 0(iy)
jp nz,00116$
inc 1(iy)
00116$:
jp 00105$
00109$:
pop ix
ret


14.Разворачивание циклов


_loop_unrolling:
push ix
ld ix,#0
add ix,sp
;test.c:243: for( i = 0; i < 6; i++ )
;разворота нет
ld iy,#_i
ld 0(iy),#0x00
ld 1(iy),#0x00
00101$:
ld iy,#_i
ld a,0(iy)
sub a,#0x06
ld a,1(iy)
sbc a,#0x00
jp p,00105$
;test.c:244: ivector4[ i ] = 0;
;экзотическая загрузка :)
ld c,0(iy)
ld b,1(iy)
sla c
rl b
ld hl,#_ivector4
add hl,bc
ld c,l
ld b,h
ld (hl),#0x00
inc hl
ld (hl),#0x00
;test.c:243: for( i = 0; i < 6; i++ )
ld iy,#_i
inc 0(iy)
jp nz,00111$
inc 1(iy)
00111$:
jp 00101$
00105$:
pop ix
ret


15.Сжатие цепочки переходов


_jump_compression:
push ix
ld ix,#0
add ix,sp
;test.c:256: beg_1:
ld a,8(ix)
sub a,10(ix)
ld a,9(ix)
sbc a,11(ix)
;интересный финт- в С результат сравнения k и l
rlca
and a,#0x01
ld c,a
ld a,10(ix)
sub a,12(ix)
ld a,11(ix)
sbc a,13(ix)
;а в А результат сравнения l и m
rlca
and a,#0x01
;только он почему-то не используется, а теряется...
00101$:
;test.c:257: if( i < j )
ld a,4(ix)
sub a,6(ix)
ld a,5(ix)
sbc a,7(ix)
jp p,00113$
;test.c:259: if( j < k )
ld a,6(ix)
sub a,8(ix)
ld a,7(ix)
sbc a,9(ix)
jp p,00110$
;test.c:261: if( k < l )
;использование предыдущего результата
xor a,a
or a,c
jp z,00106$
;test.c:263: if( l < m )
;очень странный код... не понимаю как работает....
or a,a
;есть свертка перехода!
jp z,00101$
;test.c:264: l += m;
ld a,10(ix)
add a,12(ix)
ld 10(ix),a
ld a,11(ix)
adc a,13(ix)
ld 11(ix),a
jp 00114$
;test.c:266: goto end_1;
; genLabel
00106$:
;test.c:269: k += l;
ld a,8(ix)
add a,10(ix)
ld 8(ix),a
ld a,9(ix)
adc a,11(ix)
ld 9(ix),a
jp 00114$
00110$:
;test.c:273: j += k;
ld a,6(ix)
add a,8(ix)
ld 6(ix),a
ld a,7(ix)
adc a,9(ix)
ld 7(ix),a
;test.c:275: goto beg_1;
jp 00101$
00113$:
;test.c:279: i += j;
ld a,4(ix)
add a,6(ix)
ld 4(ix),a
ld a,5(ix)
adc a,7(ix)
ld 5(ix),a
00114$:
;test.c:280: return( i + j + k + l + m );
ld a,4(ix)
add a,6(ix)
ld c,a
ld a,5(ix)
adc a,7(ix)
ld b,a
ld a,c
add a,8(ix)
ld c,a
ld a,b
adc a,9(ix)
ld b,a
ld a,c
add a,10(ix)
ld c,a
ld a,b
adc a,11(ix)
ld b,a
ld l,12(ix)
ld h,13(ix)
add hl,bc
00115$:
pop ix
ret


Итоговая оценка- 7/10. Умное распространение констант, сжатие переходов, приемлимый заголовок цикла, различная оптимизация, но повсеместное использование индексного регистра для хранения глобальных переменных все портит. Надо будет проверить как он себя ведет на статических переменных и возможно ли убрать работу с индексными регистрами. Если получится, то данный компилятор можно рекомендовать к применению! :)

Vitamin
19.11.2006, 20:13
Последний из имеющихся пациент- z88dk. Порядком помучался пока заставил его генерить исходник ассемблера. Если попросить, вставляет в исходный текст строки на С, но честно предупреждает, что в таком случае некоторая оптимизация не получится. Я буду уточнять, в каких местах возникла разница.
Использовался уровень оптимизации 2

0.Пролог
Его просто нет. Сразу идет код main.

1. Тест на размножение констант и копий.


;j4 = 2;
ld hl,2 ;const
ld (_j4),hl
;if( i2 < j4 && i4 < j4 )
;нет размножения констант плюс функции для сравнения
ld de,(_i2)
ld hl,(_j4)
call l_lt
jp nc,i_4
ld de,(_i4)
ld hl,(_j4)
call l_lt
;обратите внимание- использование коротких команд
;перехода
;но в то же время систему переходов можно (и нужно)
;было бы оптимизировать
jr c,i_5_i_4
.i_4
jp i_3
.i_5_i_4
;i2 = 2;
ld hl,2 ;const
ld (_i2),hl
;j4 = k5;
.i_3
;та же картина
ld hl,(_k5)
ld (_j4),hl
;if( i2 < j4 && i4 < j4 )
ld de,(_i2)
ld hl,(_j4)
call l_lt
jp nc,i_7
ld de,(_i4)
ld hl,(_j4)
call l_lt
jr c,i_8_i_7
.i_7
jp i_6
.i_8_i_7
;i5 = 3;
ld hl,3 ;const
ld (_i5),hl
.i_6


2.Свертка констант


;i3 = 1 + 2;
;свернул
ld hl,3 ;const
ld (_i3),hl
;flt_1 = 2.4 + 6.3;
;оп-па! не свернул!
ld hl,i_2+0
call dldpsh
ld hl,i_2+6
call dload
call dadd
ld hl,_flt_1
call dstore
;i2 = 5;
;загрузка константы
ld hl,5 ;const
ld (_i2),hl
;j2 = i + 0;
;0 не стал прибавлять
ld hl,(_i)
ld (_j2),hl
;k2 = i / 1;
;а вот на 1 поделить не побрезговал....
ld hl,(_i)
ld de,1 ;const
ex de,hl
call l_div
ld (_k2),hl
;i4 = i * 1;
;и умножить тоже
ld hl,(_i)
ld de,1
call l_mult
ld (_i4),hl
;i5 = i * 0;
;и на ноль тоже...
ld hl,(_i)
ld de,0
call l_mult
ld (_i5),hl
;printf( "This compiler handles divide-by-zero as an error\n");
;да, он прохавал деление на нулевую константу
;параметры через стек
ld hl,i_1+0
push hl
call _printf
pop bc
;flt_3 = 2.4 / 1.0;
;мрак... на 1 тоже делит, да еще и в реальном времени...
ld hl,i_2+0
call dldpsh
ld hl,i_2+12
call dload
call ddiv
ld hl,_flt_3
call dstore
;flt_4 = 1.0 + 0.0000001;
;без слов...
ld hl,i_2+12
call dldpsh
ld hl,i_2+18
call dload
call dadd
ld hl,_flt_4
call dstore
;flt_5 = flt_6 * 0.0;
;...одни эмоции
ld hl,_flt_6
call dldpsh
ld hl,i_2+24
call dload
call dmul
ld hl,_flt_5
call dstore
;flt_6 = flt_2 * flt_3;
;ну тут по другому никак
ld hl,_flt_2
call dldpsh
ld hl,_flt_3
call dload
call dmul
ld hl,_flt_6
call dstore


3.Лишнее присваивание


;k3 = 1;
ld hl,1 ;const
ld (_k3),hl
;k3 = 1;
;в худших традициях...
ld hl,1 ;const
ld (_k3),hl


4.Снижение мощности


;k2 = 4 * j5;
;не заметил возможности умножения "малой кровью"
ld hl,(_j5)
ld de,4
call l_mult
ld (_k2),hl
;for( i = 0; i <= 5; i++ )
;реализация цикла for в лучших традициях!
ld hl,0 ;const
ld (_i),hl
jp i_11
.i_9
;ivector4[ i ] = i * 2;
;хорошо что хоть догадался сдвигами умножать на размер
;типа, а не функциями, но лишние операции со стеком
ld hl,_ivector4
push hl
ld hl,(_i)
add hl,hl
pop de
add hl,de
push hl
ld hl,(_i)
add hl,hl
pop de
call l_pint
;классика!
ld hl,(_i)
inc hl
ld (_i),hl
dec hl
.i_11
;мрак...
ld hl,(_i)
ld de,5 ;const
ex de,hl
call l_le
jp c,i_9
.i_10


5.Простой цикл


;j5 = 0;
ld hl,0 ;const
ld (_j5),hl
;k5 = 10000;
ld hl,10000 ;const
ld (_k5),hl
;do {
.i_14
;k5 = k5 - 1;
;распознал вычитание единицы!
ld hl,(_k5)
dec hl
ld (_k5),hl
;j5 = j5 + 1;
;и ее прибавление
ld hl,(_j5)
inc hl
ld (_j5),hl
;i5 = (k5 * 3) / (j5 * 5);
;ну ведь можешь же умножать когда хочешь!
ld hl,(_k5)
ld b,h
ld c,l
add hl,bc
add hl,bc
push hl
ld hl,(_j5)
ld b,h
ld c,l
add hl,hl
add hl,hl
add hl,bc
pop de
call l_div
ld (_i5),hl
;} while ( k5 > 0 );
.i_12
;оригинальная проверка на конец цикла
ld hl,(_k5)
xor a
or h
jp m,i_13
or l
jp nz,i_14
.i_13


6.Управление переменной индукции цикла


;for( i = 0; i < 100; i++ )
ld hl,0 ;const
ld (_i),hl
jp i_17
.i_15
;ivector5[ i * 2 + 3 ] = 5;
;специфично, но в целом терпимо
ld hl,_ivector5
push hl
ld hl,(_i)
add hl,hl
inc hl
inc hl
inc hl
add hl,hl
pop de
add hl,de
ld (hl),#(5 % 256)
inc hl
ld (hl),#(5 / 256)
ld hl,(_i)
inc hl
ld (_i),hl
;а это зачем???
dec hl
.i_17
;оптимизацию for не доделали...
ld hl,(_i)
ld de,100 ;const
ex de,hl
call l_lt
jp c,i_15
.i_16


7.Глубокие подвыражения


;if( i < 10 )
;хреново сравнивает!
ld hl,(_i)
ld de,10 ;const
ex de,hl
call l_lt
jp nc,i_18
;j5 = i5 + i2;
;зато хоть складывает нормально
ld de,(_i5)
ld hl,(_i2)
add hl,de
ld (_j5),hl
;else
jp i_19
.i_18
;k5 = i5 + i2;
;выделения подвыражений нет
ld de,(_i5)
ld hl,(_i2)
add hl,de
ld (_k5),hl
.i_19


8.Генерация адреса переменной с константным индексом, размножение копий и регистров


;ivector[ 0 ] = 1;
;правильно
ld hl,1 ;const
ld (_ivector),hl
;ivector[ i2 ] = 2;
;лишние операции со стеком, простая перестановка дала
;бы прирост эффективности
ld hl,_ivector
push hl
ld hl,(_i2)
add hl,hl
pop de
add hl,de
ld de,2 ;const
ex de,hl
;да что за мрак!
call l_pint
;ivector[ i2 ] = 2;
;не воспользовался результатом предыдущей операции
ld hl,_ivector
push hl
ld hl,(_i2)
add hl,hl
pop de
add hl,de
ld de,2 ;const
ex de,hl
call l_pint
;ivector[ 2 ] = 3;
;тут все правильно
ld hl,3 ;const
ld (_ivector+4),hl


9.Удаление общих подвыражений


;if(( h3 + k3 ) < 0 || ( h3 + k3 ) > 5 )
;хорошее начало, но дальше не очень
ld de,(_h3)
ld hl,(_k3)
add hl,de
ld de,0 ;const
ex de,hl
call l_lt
jp c,i_21
;не используются результаты...
ld de,(_h3)
ld hl,(_k3)
add hl,de
ld de,5 ;const
ex de,hl
call l_gt
jp nc,i_20
.i_21
;printf("Common subexpression elimination\n");
;параметры через стек
ld hl,i_1+63
push hl
call _printf
pop bc
;else {
jp i_23
.i_20
;m3 = ( h3 + k3 ) / i3;
;совсем не используются...
ld de,(_h3)
ld hl,(_k3)
add hl,de
ex de,hl
ld hl,(_i3)
call l_div
ld (_m3),hl
;g3 = i3 + (h3 + k3);
ld hl,(_i3)
push hl
ld de,(_h3)
ld hl,(_k3)
add hl,de
pop de
add hl,de
ld (_g3),hl
;}
.i_23


10.Вынесение инвариантного кода


;for( i4 = 0; i4 <= 2; i4++)
ld hl,0 ;const
ld (_i4),hl
jp i_26
.i_24
;ivector2[ i4 ] = j * k;
;обычная обработка индекса массива
ld de,_ivector2
ld hl,(_i4)
add hl,de
push hl
;но вынесения кода нет
ld de,(_j)
ld hl,(_k)
call l_mult
pop de
ld a,l
ld (de),a
ld hl,(_i4)
inc hl
ld (_i4),hl
dec hl
.i_26
ld hl,(_i4)
ld de,2 ;const
ex de,hl
call l_le
jp c,i_24
.i_25

Vitamin
19.11.2006, 20:25
11.Вызов функции с аргументами. Определение недостижимого кода


;dead_code( 1, "This line should not be printed" );
;параметры через стек, слева направо (хотя должно быть наоборот...)
ld hl,1 ;const
push hl
ld hl,i_1+97
push hl
call _dead_code
pop bc
pop bc




;void dead_code( a, b )
;int a;
;char *b;

._dead_code
;{
;int idead_store;
;idead_store = a;
ld hl,6-2 ;const
add hl,sp
call l_gint ;
push hl
;if( 0 )
;переход выполняет
jp i_27
;printf( "%s\n", b );
;но код для пустышки генерит!
ld hl,i_1+129
push hl
ld hl,6 ;const
add hl,sp
call l_gint ;
push hl
call _printf
pop bc
pop bc
;}
.i_27
pop bc
ret


12.Вызов функции без аргументов. Исключение циклов


call _unnecessary_loop




;void unnecessary_loop()
;{
._unnecessary_loop
;int x;
;x = 0;
;регистровая переменная- хорошо
ld hl,0 ;const
;но в стеке- плохо
push hl
;for( i = 0; i < 5; i++ )
ld hl,0 ;const
ld (_i),hl
jp i_30
.i_28
;k5 = x + j5;
;прикольно :)
pop de
push de
ld hl,(_j5)
add hl,de
ld (_k5),hl
ld hl,(_i)
inc hl
ld (_i),hl
dec hl
.i_30
ld hl,(_i)
ld de,5 ;const
ex de,hl
call l_lt
jp c,i_28
.i_29
;}
pop bc
ret


13. Слияние заголовков циклов


;void loop_jamming( x )
;int x;
._loop_jamming
;{
;for( i = 0; i < 5; i++ )
ld hl,0 ;const
ld (_i),hl
jp i_33
.i_31
;k5 = x + j5 * i;
;наверное ошибка- на стеке на один параметр меньше
pop bc
pop hl
push hl
push bc
push hl
ld de,(_j5)
ld hl,(_i)
call l_mult
pop de
add hl,de
ld (_k5),hl
ld hl,(_i)
inc hl
ld (_i),hl
dec hl
.i_33
ld hl,(_i)
ld de,5 ;const
ex de,hl
call l_lt
jp c,i_31
.i_32
;for( i = 0; i < 5; i++ )
;второй цикл точная копия первого
ld hl,0 ;const
ld (_i),hl
jp i_36
.i_34
;i5 = x * k5 * i;
pop bc
pop hl
push hl
push bc
ex de,hl
ld hl,(_k5)
call l_mult
ex de,hl
ld hl,(_i)
call l_mult
ld (_i5),hl
ld hl,(_i)
inc hl
ld (_i),hl
dec hl
.i_36
ld hl,(_i)
ld de,5 ;const
ex de,hl
call l_lt
jp c,i_34
.i_35
;}
ret


14.Разворачивание циклов


;void loop_unrolling( x )
;int x;
._loop_unrolling
;{
;for( i = 0; i < 6; i++ )
ld hl,0 ;const
ld (_i),hl
jp i_39
.i_37
;ivector4[ i ] = 0;
;нет разворота, да и загрузка достаточно тяжела
ld hl,_ivector4
push hl
ld hl,(_i)
add hl,hl
pop de
add hl,de
ld (hl),#(0 % 256)
inc hl
ld (hl),#(0 / 256)
ld hl,(_i)
inc hl
ld (_i),hl
dec hl
.i_39
ld hl,(_i)
ld de,6 ;const
ex de,hl
call l_lt
jp c,i_37
.i_38
;}
ret


15.Сжатие цепочки переходов


;int jump_compression( i, j, k, l, m )
;int i, j, k, l, m;
._jump_compression
;{
;beg_1:
.i_40
;if( i < j )
;вот тут бы не помешали индексные регистры, да не
;используются совсем...
ld hl,10 ;const
add hl,sp
ld e,(hl)
inc hl
ld d,(hl)
push de
ld hl,10 ;const
add hl,sp
call l_gint ;
pop de
call l_lt
jp nc,i_41
;{
;if( j < k )
ld hl,8 ;const
add hl,sp
ld e,(hl)
inc hl
ld d,(hl)
push de
ld hl,8 ;const
add hl,sp
call l_gint ;
pop de
call l_lt
jp nc,i_42
;{
;if( k < l )
ld hl,6 ;const
add hl,sp
ld e,(hl)
inc hl
ld d,(hl)
push de
ld hl,6 ;const
add hl,sp
call l_gint ;
pop de
call l_lt
jp nc,i_43
;{
;if( l < m )
ld hl,4 ;const
add hl,sp
ld e,(hl)
inc hl
ld d,(hl)
push de
ld hl,4 ;const
add hl,sp
call l_gint ;
pop de
call l_lt
jp nc,i_44
;l += m;
ld hl,4 ;const
add hl,sp
push hl
ld e,(hl)
inc hl
ld d,(hl)
push de
ld hl,6 ;const
add hl,sp
call l_gint ;
pop de
add hl,de
pop de
call l_pint
;else
jp i_45
.i_44
;goto end_1;
;нет оптимизации переходов
jp i_46
.i_45
;}
;else
jp i_47
.i_43
;k += l;
ld hl,6 ;const
add hl,sp
push hl
ld e,(hl)
inc hl
ld d,(hl)
push de
ld hl,8 ;const
add hl,sp
call l_gint ;
pop de
add hl,de
pop de
call l_pint
.i_47
;}
;else
jp i_48
.i_42
;{
;j += k;
ld hl,8 ;const
add hl,sp
push hl
ld e,(hl)
inc hl
ld d,(hl)
push de
ld hl,10 ;const
add hl,sp
call l_gint ;
pop de
add hl,de
pop de
call l_pint
;end_1:
.i_46
.i_49
;goto beg_1;
jp i_40
;}
.i_48
;}
;else
jp i_50
.i_41
;i += j;
ld hl,10 ;const
add hl,sp
push hl
ld e,(hl)
inc hl
ld d,(hl)
push de
ld hl,12 ;const
add hl,sp
call l_gint ;
pop de
add hl,de
pop de
call l_pint
.i_50
;return( i + j + k + l + m );
ld hl,10 ;const
add hl,sp
ld e,(hl)
inc hl
ld d,(hl)
push de
ld hl,10 ;const
add hl,sp
call l_gint ;
pop de
add hl,de
ex de,hl
ld hl,8-2 ;const
add hl,sp
call l_gint ;
add hl,de
ex de,hl
ld hl,6-2 ;const
add hl,sp
call l_gint ;
add hl,de
ex de,hl
ld hl,4-2 ;const
add hl,sp
call l_gint ;
add hl,de
ret
;}


Итоговая оценка- 5/10. Туповатый компилятор, на который изредка находит озарение и он генерит неплохой код. К применению не рекомендуется...

NovaStorm
20.11.2006, 14:25
Спасибо, интересное исследование. Значит sdcc... Но вот меня смущает, что на sdcc.sf.net постоянно упоминается "freeware", несмотря на его GPL'ность.
А по поводу переменных, наверное в реальных проектах будет много глобальных статических, чтобы компилятор их просто клал в память, не извращаясь со стеком или IX/IY.

Vitamin
20.11.2006, 15:17
Спасибо, интересное исследование. Значит sdcc... Но вот меня смущает, что на sdcc.sf.net постоянно упоминается "freeware", несмотря на его GPL'ность.
А по поводу переменных, наверное в реальных проектах будет много глобальных статических, чтобы компилятор их просто клал в память, не извращаясь со стеком или IX/IY.
Фриварный он и есть- сорцы в комплекте, доки тоже.
Проверил статические переменные- те же яйца, только в профиль.
Частично решить проблему получается с использованием встроенного peephole-оптимизатора. Пишется файл автозамен и код весьма и весьма легчает, но это не панацея, ибо оптимизация использования регистров (в частности, IY) бывает приводит к ошибкам постоптимизации.
Так что надо ковыряться в части кодогенератора- он в сорцах отдельно лежит, я правда не разобрался еще в нем.
А вообще- приятное впечатление произвел, весьма.

maximk
20.11.2006, 15:52
Все-таки мне кажется, что тест несколько синтетический.

Например, умножение на 1, деление на нее же - в чем смысл? Разве кто-то напишет так в программе? Ну, хорошо, а если константное выражение? Ну, это дело поправимое. Да, читаемость снизиться, но до асма будет далеко.

Или, например, цикл который можно убрать. Ну дык пусть программер и уберет. Не всегда видно? Дык, хороший стиль программирования предполагает, что все видно. В конечном счете при кривых исходниках самому же будет хуже.

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

NovaStorm
20.11.2006, 16:38
Vitamin, разницу free/freeware думаю тебе объяснять не надо. Но он GPL и ладно.
Dynamic C http://www.rabbitsemiconductor.com/products/dc/ Z80 поддерживает, никто не в курсе?
++
"Andrew S. Tanenbaum created MINIX at Vrije Universiteit in Amsterdam" и компилилась она их же ACK. Кстати MINIX3 до сих пор им собирается.

Vitamin
20.11.2006, 16:50
Все-таки мне кажется, что тест несколько синтетический.
Предложи свой. Который будет естественным, в котором не будет "синтетических" циклов, "синтетических" присваиваний, "синтетических" разыменований указателей и т.п.


Например, умножение на 1, деление на нее же - в чем смысл? Разве кто-то напишет так в программе? Ну, хорошо, а если константное выражение? Ну, это дело поправимое. Да, читаемость снизиться, но до асма будет далеко.
Ну вот тебе две строчки исходников:
const float var = (100.0 + 13.0) / 100.0; //(base + addition) / percents
и
const float var = 1.13; //(base + addition) / percents

как ты по второй строке (не глядя на первую) скажешь что чему ты принимаешь? никак- разворачиваем выражения для своей пользы. И просто очень приятно, когда тупой компилятор не догадывается свернуть это безобразие...
А насчет умножения на 1. Тоже имеем код
#define COEFF 4
...
int t = var * COEFF;

Хорошо, если компилятор свернет умножение на константу. А то есть такие индивиды, что и не сворачивают, даже если COEFF=1


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


Или, например, цикл который можно убрать. Ну дык пусть программер и уберет. Не всегда видно? Дык, хороший стиль программирования предполагает, что все видно. В конечном счете при кривых исходниках самому же будет хуже.
Компилятор должен брать на себя упрощение рудиментов, возможно оставшихся с прошлых версий. Реализация в коде скрыта от программиста и может быть какой угодно сложной, лишь бы эффективно работало. А вот исходный текст на С должен быть понятен программисту. Это же относится и к развороту циклов.

Vitamin
20.11.2006, 16:51
Vitamin, разницу free/freeware думаю тебе объяснять не надо. Но он GPL и ладно.
Dynamic C http://www.rabbitsemiconductor.com/products/dc/ Z80 gподдерживает, никто не в курсе?
Если честно, не силен в этих терминологиях :) Кряков и денег не требует, доки и сорцы в комплекте- что еще надо? :)
А про тот компилер ничего не знаю- попробуй достань, пощщупай :)

maximk
20.11.2006, 17:17
Но это не выход.
На самом деле ты прав, но есть одно но. Мы имеем дело с процессором, который поддерживается постольку-поскольку. То, что под популярный gcc так и не написали backend для z80 показательно. Оно никому не надо. И поэтому то, что есть - ценно.

Проги для спектрума пишут в основном на асме. А это значит, что они в 10 раз менее читаемы, чем несколько кривая прога на С, которую пришлось подтачивать под недо-компилер. И тем не менее, если приложив какие-то свои усилия удасться получить приемлемый результат, написав прогу на С, а не на ASM - это будет прорыв.

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

И второй момент. Логично желание иметь хороший компилятор под Z80 на самом спектруме. Но ресурсы машины таковы, что супер-мега компилятор на ней просто не сделать, и тогда такие вещи, как умножение на 1 - это мелочи, это не суть важно. Да, хотелось бы, но не так чтобы очень.

А мы, как часто бывает на форуме (и как было с динамическим компоновщиком) быстро скатываемся в область сферических коней в вакууме, типа, да ну нет, это отстой, вот надо делать вот как!

Vitamin
20.11.2006, 17:24
На самом деле ты прав, но есть одно но. Мы имеем дело с процессором, который поддерживается постольку-поскольку. То, что под популярный gcc так и не написали backend для z80 показательно. Оно никому не надо. И поэтому то, что есть - ценно.
Ну это как призрак коммунизьма- он гдето есть, но сырцов никто не видел. Я одно время изрядно пошарился по разным форумам и прочая, но так ничего и не нашел


Проги для спектрума пишут в основном на асме. А это значит, что они в 10 раз менее читаемы, чем несколько кривая прога на С, которую пришлось подтачивать под недо-компилер. И тем не менее, если приложив какие-то свои усилия удасться получить приемлемый результат, написав прогу на С, а не на ASM - это будет прорыв.
Я не питаю иллюзий по поводу того, что С будет использоваться для написания прог. Но что оттачивать идеи на ЯВУ гораздо удобнее, чем на асме (особенно имя готовы библиотеки для работы с плавающими числами или ввода-вывода) это факт.


И второй момент. Логично желание иметь хороший компилятор под Z80 на самом спектруме. Но ресурсы машины таковы, что супер-мега компилятор на ней просто не сделать, и тогда такие вещи, как умножение на 1 - это мелочи, это не суть важно. Да, хотелось бы, но не так чтобы очень.
Не соглашусь- сворачивание констант на этапе компиляции не такая уж и затратная операция по сравнению с потерями на фактическое вычисление их во время работы. А по поводу скорости- протести плз нативный компилер HiTech на спеке. Подозреваю, что результаты будут такие же, как и у его кросс-варианта.


А мы, как часто бывает на форуме (и как было с динамическим компоновщиком) быстро скатываемся в область сферических коней в вакууме, типа, да ну нет, это отстой, вот надо делать вот как!
В отличие от "динамического компоновщика" здесь есть конкретные продукты (а не исследовательский макет), причем не в единичном экземпляре.

caro
20.11.2006, 17:26
Проги для спектрума пишут в основном на асме. А это значит, что они в 10 раз менее читаемы, чем несколько кривая прога на С, которую пришлось подтачивать под недо-компилер. И тем не менее, если приложив какие-то свои усилия удасться получить приемлемый результат, написав прогу на С, а не на ASM - это будет прорыв.

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

И второй момент. Логично желание иметь хороший компилятор под Z80 на самом спектруме. Но ресурсы машины таковы, что супер-мега компилятор на ней просто не сделать, и тогда такие вещи, как умножение на 1 - это мелочи, это не суть важно. Да, хотелось бы, но не так чтобы очень.

А мы, как часто бывает на форуме (и как было с динамическим компоновщиком) быстро скатываемся в область сферических коней в вакууме, типа, да ну нет, это отстой, вот надо делать вот как!Золотые слова.
По этой причине я и убрал с форума последнюю версию C Warp,
поняв что кроме охаивания ничего хорошего не услышу :)
Мне он нравится уже потому, что работает на моем любимом Спекке,
хоть и генерит страшно "монструозный" код :)

psndcj
21.11.2006, 07:11
Я не питаю иллюзий по поводу того, что С будет использоваться для написания прог.
если появится кросс-компилятор, генерящий боле-менее адекватный код, то лично я бы начал его использовать в наших следующих демах. Несмотря на всеобщее мнение, что демо выжимают из машины невозможное, критическогл по времени кода не так уж и много - процентов 20-40, все остальное занимает управление и менеджеры данных и событий - их выполнение на асме занимает ничтожное время (до 10-15% прерывания), а написание их на pure asm занимает до 80% времени!!! Конечно я говорю по своему опыту, у кого-то все совсем наоборот - но логику на асме писать очень напряжно, в отличие от раскрытого и линейного демо-кода...

NovaStorm
21.11.2006, 08:58
Увы =( "Dynamic C runs on a PC and connects to the processor though a serial connection to the Rabbit Microprocessor core module."
Только для кроликов. А там система команд отличается.

Vitamin
21.11.2006, 12:03
По этой причине я и убрал с форума последнюю версию C Warp,
поняв что кроме охаивания ничего хорошего не услышу
Мне он нравится уже потому, что работает на моем любимом Спекке,
хоть и генерит страшно "монструозный" код
Можешь прогнать его на тесте и выложить обзор результата? С максимальной оптимизацией конечно, если таковая имеется.


если появится кросс-компилятор, генерящий боле-менее адекватный код, то лично я бы начал его использовать в наших следующих демах.
HiTechC или SDCC+Peephole. На выбор.

andrews
21.11.2006, 13:47
SDCC+Peephole
...можно ли взглянуть на пример маленького проекта под ZX Spectrum на нем. А то я пока думал по старинке, на Мазницинском C-- (pc110)

Vitamin
21.11.2006, 14:20
...можно ли взглянуть на пример маленького проекта под ZX Spectrum на нем. А то я пока думал по старинке, на Мазницинском C-- (pc110)
Смотря что понимается под "маленьким проектом"... Можно скачать компилятор из инета (в свободном доступе) и проверить. Примеры кода есть выше (тяжеловат он). Файл оптимизации можно за полчаса написать ручками по анализу полученного кода.

andrews
21.11.2006, 15:38
Смотря что понимается под "маленьким проектом"... что-нибудь со спрайтами...у Мазницы библиотеки от Laser Basica прикручены...в качестве демки игра Кладова...компилится все o'k.

Vitamin
22.11.2006, 19:03
что-нибудь со спрайтами...у Мазницы библиотеки от Laser Basica прикручены...в качестве демки игра Кладова...компилится все o'k.
Надо посмотреть какие там библиотеки в комплекте. В принципе, написать свои процедуры вывода (даже на асме) труда большого не составляет. А вот насчет лазербейсика тут думаю сложнее...
ЗЫ. С-- чем отличается от полноценного С?

Sinus
22.11.2006, 20:47
Vitamin
всем ;) это совершенно другой язык программинга. (только синтаксис чуть чуть на C похож)
а что, есть уже C-- генерящий код для z80 ?

Vitamin
22.11.2006, 21:04
всем это совершенно другой язык программинга. (только синтаксис чуть чуть на C похож)
Я просто слышал про этот язык. Его, кажется, для какойто ОС разработали?


а что, есть уже C-- генерящий код для z80 ?
Судя по всему, да. За подробностями- к andrews :)

Lethargeek
23.11.2006, 07:25
если появится кросс-компилятор, генерящий боле-менее адекватный код, то лично я бы начал его использовать в наших следующих демах. Несмотря на всеобщее мнение, что демо выжимают из машины невозможное, критическогл по времени кода не так уж и много - процентов 20-40, все остальное занимает управление и менеджеры данных и событий - их выполнение на асме занимает ничтожное время (до 10-15% прерывания), а написание их на pure asm занимает до 80% времени!!! Конечно я говорю по своему опыту, у кого-то все совсем наоборот - но логику на асме писать очень напряжно, в отличие от раскрытого и линейного демо-кода...
Логику на "мелких" компах лучше на Forth писать. Правда, спековские версии не ахти... проще версию "под себя" один раз с нуля написать и дальше проблем не иметь.

caro
23.11.2006, 09:30
Логику на "мелких" компах лучше на Forth писать.Forth конечно хорош, но "лучше" - спорное утверждение,
тем более что ни одного примера реализации логики на нем для Спектрума
я во всяком случае не видел.

Правда, спековские версии не ахти... И это не совсем верно.
Реализации Forth для Спектрума основаны на стандартах Forth79 и Fig-Forth и практически
идентичны их CP/M и ранним PC вариантам.

Да и программирование на Forth требует несколько "другого" мышления чем на традиционных ЯВУ.

caro
23.11.2006, 10:24
С-- чем отличается от полноценного С?

Вот выдержки из описания:

0 Introduction
^^^^^^^^^^^^^^^

0.1 C--, what can it do?

C-- was designed to build small and fast programs. It is most suitable for
memory resident programs (TSRs), programs requiring interrupt handling or
programs that have limited resources.

C-- supports, among other things, inline assembly and recursion. Also the
internal C-- library of functions and macros, contains code support for
files, sound, graphics and access to extended memory by the use of the XMS
standard 2.0.

-----------------------------------------------------------------------------

0.2 C--, what is it like?

Nothing you have experienced before. :-)
Seriously, its sort of like C and kinda like assembly.

================================================== ===========================

1 THE C-- LANGUAGE
^^^^^^^^^^^^^^^^^^^

1.0 SECTION INTRODUCTION

After pondering for quite some time over what the best method to explain C--
to a new user, I came to the conclusion of describing some of its syntax and
usage as a contrast to C. This does limit the explanation's usefulness to
only C programmers, but since anyone who is anyone knows C, I don't see it a
problem. :-)

-----------------------------------------------------------------------------
Действительно генерит очень компактный код, но только под DOS :)
Сам пакет вместе с множеством примеров весит порядка
260 кб в RARе.
Кому интересно могу выслать, обращайтесь на k2k()list.ru

BlackWolf
23.11.2006, 20:10
Забавно. Редкое совпадение. Только сегодня на работе обсуждали с коллегами журнал RSDN и один сотрудник выдвинул тезис что этот журнал только для "Сишников", тут же возник вопрос а для какого С или С++, кто-то пошутил С--
Оказывается не такая уж это и шутка :rolleyes:

Southern Bear
23.11.2006, 21:34
Действительно генерит очень компактный код, но только под DOS
Да и под MD довольно компактный генерит. Года 4 назад кейген писал на нём под WinTarif и программатор KX-TA616. Под консоль винды 2,5 кило, под гуй 3 кило (да и то только из за иконки).

Lethargeek
24.11.2006, 07:53
Forth конечно хорош, но "лучше" - спорное утверждение,
тем более что ни одного примера реализации логики на нем для Спектрума я во всяком случае не видел.
И я не видел почему-то. :v2_conf3: Хотя на других восьмибитках - нередко.
Насчет "лучше" - так речь пойдет скорее всего об экономии памяти и скорости отладки, а здесь вряд ли найдется что-то значительно "лучше".


И это не совсем верно.
Реализации Forth для Спектрума основаны на стандартах Forth79 и Fig-Forth и практически идентичны их CP/M и ранним PC вариантам.
Вот это-то и плохо по нынешним временам. Редактор морально устарел, кое-чего не хватает... Сейчас вообще выгоднее отлаживать в кроссплатформенном варианте, а в готовый продукт вставлять сильно урезанное ядро. В котором от Forth может остаться только сам принцип.


Да и программирование на Forth требует несколько "другого" мышления чем на традиционных ЯВУ.
Что да, то да. Тут главное втянуться... :)

sinn_dtr
27.11.2006, 21:23
Почитал, завтра скачаю и попробую под никсами собрать и попрогонять. Хочется посмотреть асм на выходе. Ибо все существующие кросс-компилеры такую хрень городят... Разве что IAR по слухам весьма достойно себя ведет (надо достать попробовать).
Пробовал я его. Говно редкостное. Особенно если смотреть асмовский код, который он генерит. И вообще для спекка только Асм. Остальное фуфел и не спортивно :p

sinn_dtr
27.11.2006, 21:23
Забавно. Редкое совпадение. Только сегодня на работе обсуждали с коллегами журнал RSDN и один сотрудник выдвинул тезис что этот журнал только для "Сишников", тут же возник вопрос а для какого С или С++, кто-то пошутил С--
Оказывается не такая уж это и шутка :rolleyes:
Этот журнал в основном для вендузятников.

Vitamin
27.11.2006, 23:27
Пробовал я его. Говно редкостное. Особенно если смотреть асмовский код, который он генерит.
Можно листинг с анализом?


И вообще для спекка только Асм. Остальное фуфел и не спортивно
Кесарю-кесарево. Сложную математику (в пределах предоставляемой мощности конечно) и алгоритмику на асме порой только чуть не свихнув мозги получается делать...

ЗЫ. У меня тут возникла идея сделать набросок "идеального" компилятора, а точнее результата его работы над вышеуказанным тестом. Надо будет подумать...


Этот журнал в основном для вендузятников.
При желании программист даже под линух на С++ может найти много чего полезного в статье про делфи... А журнал неплохой, много чего интересного там есть.

sinn_dtr
28.11.2006, 14:36
Можно листинг с анализом?

Я его ковырял года 3 назад. Листинги не сохранились :)



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

Ну, мы ведь говорим о спектруме? Здесь другого не дано, кроме как асм.
Всякие Ц годятся толь-ко для программ уровня "Hello world".



При желании программист даже под линух на С++ может найти много чего полезного в статье про делфи... А журнал неплохой, много чего интересного там есть.

Но мне больше форум RSDN нравится, чем журнал.

Vitamin
28.11.2006, 15:06
Всякие Ц годятся толь-ко для программ уровня "Hello world".
Поздравляю. Тебя сплошь окружают программы уровня Hello world ;) Ибо С находит свое применение во встроенных системах и в операционных системах (наравне с С++).


Но мне больше форум RSDN нравится, чем журнал.
Это да. Хотя бы потому что это форум и там поиск есть :)

sinn_dtr
28.11.2006, 15:42
Поздравляю. Тебя сплошь окружают программы уровня Hello world ;) Ибо С находит свое применение во встроенных системах и в операционных системах (наравне с С++).


Это да. Хотя бы потому что это форум и там поиск есть :)

Ты выкинул из контекста:
"Ну, мы ведь говорим о спектруме? Здесь другого не дано, кроме как асм."
Так можно любой пост до абсурда довести.

caro
28.11.2006, 16:31
"Ну, мы ведь говорим о спектруме? Здесь другого не дано, кроме как асм."С какой стати?
Здесь дано все, что позволяет Спектруму называться компьютером.

Vitamin
28.11.2006, 16:32
Ты выкинул из контекста:
"Ну, мы ведь говорим о спектруме? Здесь другого не дано, кроме как асм."
А чем спек хуже какого-нибудь встроенного микроконтроллера? Наоборот, мощнее даже. А С даже на них есть...

sinn_dtr
28.11.2006, 16:36
А чем спек хуже какого-нибудь встроенного микроконтроллера? Наоборот, мощнее даже. А С даже на них есть...
Я не говорю, что Ц не имеет права существования.
Мое ИМХО, что большие проги писать на Ц не получится.

caro
28.11.2006, 16:45
Я не говорю, что Ц не имеет права существования.
Мое ИМХО, что большие проги писать на Ц не получится.Значит ты не видел пакет ZED от Rick Murray.
Это почтовый редактор-эхопроцессор для ZX Spectrum.
Он написан в основном на HiSoft С, причем именно на Спектруме.

sinn_dtr
28.11.2006, 16:54
Значит ты не видел пакет ZED от Rick Murray.
Это почтовый редактор-эхопроцессор для ZX Spectrum.
Он написан в основном на HiSoft С, причем именно на Спектруме.
Ты скорость его работы видел?
Вот есть редактор-эхопроцессор от KVA (не помню название). Я думаю что ты бы выбрал последний, т.к. скорость уж сильно отличалась. Не говоря уже о качестве продукта.

caro
28.11.2006, 17:39
Ты скорость его работы видел?Меня устраивала.

Вот есть редактор-эхопроцессор от KVA (не помню название). Я думаю что ты бы выбрал последний, т.к. скорость уж сильно отличалась.Не знаю, не видел.

Не говоря уже о качестве продукта.Качество отменное, мне нравится. Особенно когда посмотрел исходники.

fk0
28.11.2006, 17:48
Значит ты не видел пакет ZED от Rick Murray.
Это почтовый редактор-эхопроцессор для ZX Spectrum.
Он написан в основном на HiSoft С, причем именно на Спектруме.

Зато я видел. Пока к нему не прикрутили кеш дисковый на 512к памяти -- работать было невозможно. А потом появился Lara Croft и ZED был быстро заброшен.

Vitamin
28.11.2006, 18:10
Не говоря уже о качестве продукта.
Качество продукта крайне косвенно зависит от языка написания. На асме тоже немало хреновых поделок сделано и что? Это ж не повод заявлять, что "асм- не для спека"

sinn_dtr
28.11.2006, 18:48
Качество продукта крайне косвенно зависит от языка написания. На асме тоже немало хреновых поделок сделано и что? Это ж не повод заявлять, что "асм- не для спека"
Пора равязывать пустой треп.
Мое мнение таково, что на спектруме асм - это наше фсе.
Я не вижу и НЕ увижу ни одной качественной программы на сях.
Ваше мнение другое.
Спор бесмысленен.

captain cobalt
28.11.2006, 20:06
На эхотаге основные тормоза от вывода на экран.
Прикрутят тридевятый чип - можно будет использовать Паскаль.

Vitamin
28.11.2006, 22:43
Я не вижу и НЕ увижу ни одной качественной программы на сях.
Чтоб поставить "трепу" какие-то рамки, определи показатели качества программы (без привязки к языку).


Прикрутят тридевятый чип - можно будет использовать Паскаль.
Только не паскаль! %)

andrews
29.11.2006, 09:16
А чем спек хуже какого-нибудь встроенного микроконтроллера? Наоборот, мощнее даже.
он, как я с удивлением для себя вчера выяснил мощнее даже GB, GBC, поскольку там недоZ80...относительно же топика замечу, что та прога на асме рулезней, которую пишет продвинутый программер...не столь важно качество кода ( если речь идет о 20-40% перерасхода памяти и недоиспользования cpu)...сколько продуманность всего проекта, структура кода, его стиль и документированность...
Мне приходилось сопровождать чужой проект на MASM-е объемом более 100 тыс. строк...под самопальной СРВ...интенсивно работающий с железом цифровой АТС...с тех пор у меня устойчивая аллергия к серьезным проектам реализованным на ассемблере. Хотя в смысле защиты интеллектуальной собственности и неПортируемости они идеальны :)

andrews
29.11.2006, 09:19
Недостаток же C применительно конкретно к z80 тот, что это отнюдь не стековый проц в том смысле, что у него богатый набор регистров и операций с ними, которые известные реализации C явно недоиспользуют... и оттого проигрыш сишных прог становится ощутимее.

andrews
29.11.2006, 09:23
Только не паскаль!
был еще PL/Z...словом нужен ЯВУ с классами, но хорошо учитывающий особенности z80

Vitamin
29.11.2006, 09:32
не столь важно качество кода ( если речь идет о 20-40% перерасхода памяти и недоиспользования cpu)...сколько продуманность всего проекта, структура кода, его стиль и документированность...
Ну перерасход памяти обычно ограничен сверху. А насчет продуманности проекта и структуры кода- согласен. Иногда обычный пересмотр исходников, легкое изменение концепции позволяют добиться значительных результатов.


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


Недостаток же C применительно конкретно к z80 тот, что это отнюдь не стековый проц в том смысле, что у него богатый набор регистров и операций с ними, которые известные реализации C явно недоиспользуют...
Это да. Или на постой используют стек, либо кучу левых вызовов впендюривают.


был еще PL/Z...
PL/2

caro
29.11.2006, 09:46
PL/2
PL/M (англ. Programming Language for Microcomputers) -
процедурный язык программирования, разработанный в 1972
фирмой Digital Research для микропроцессоров Intel.

Язык заимствовал идеи из PL/I, ALGOL, XPL и имел
интегрированный макропроцессор. Язык использовался в
реализации операционной системы CP/M.
Компиляторы PL/M существовали для ранних моделей
процессоров Intel: Intel 4004, 8008, 8080, 8051, 8086, 286, и 386.

andrews
29.11.2006, 10:22
Я не ошибся, PL/Z это реализация PL/M под U880A(DDR-овский z80a)...входил в ПО не помню какого комплекса Robotron...впервые прочитал о нем в какой-то переводной книжке про микропроцессоры в начале 80-х. В руках правда подержать не довелось. Исходники PL/M, которые общедоступны в сети, к сожалению, на Фортране, и посему повторить подвиг немецких камрадов хоть и очень хотелось, но :(
А конвертнуть на С...конвертнул, но вышло для разбора не проще. Есть еще PL/M на основе yacc+lex, но это тоже большой труд.

Vitamin
29.11.2006, 10:24
PL/M (англ. Programming Language for Microcomputers)
Точно. Хотя помнится был и язык с "дробь два", только не помню что там...

boo_boo
29.11.2006, 10:28
был еще PL/Z...словом нужен ЯВУ с классами, но хорошо учитывающий особенности z80
ООП-подход оправдан только в случае грамотно построенной иерархии классов, с использованием полиморфизма и инкапсуляции. но в случае ZX это будет слишком ресурсоемко.

и вообще, все только говорят про ООП, а на деле 9 из 10и программистов практически не используют наследование, полиморфизм и инкапсуляцию, т.е. их программы по сути структурные, и классы в них можно спокойно заменить на ф-ии, в которые передается указатель на данные обьекта.

andrews
29.11.2006, 10:33
PL/2 стоял на майнфреймах IBM/360 начала 70-х...когда наши их передрали ( серия ЕС) то в наших вычцентрах тоже был...и посему было много пакетов прикладного ПО и книжек про этот язык. PL/M ( я на нем писал проги в начале 80-х для встроенных систем МСУВТ В7 на 8080) стоял на отладочных комплексах КРАМ( советский клон Intellec MDS series II) под интеловской операционкой ISIS-II и еще на комплексах СМ1800.

ng_dead
29.11.2006, 10:33
и вообще, все только говорят про ООП, а на деле 9 из 10и программистов практически не используют наследование, полиморфизм и инкапсуляцию, т.е. их программы по сути структурные, и классы в них можно спокойно заменить на ф-ии, в которые передается указатель на данные обьекта.
сказывается многолетний опыт кодинга в процедурных языках. по себе знаю:)

andrews
29.11.2006, 10:47
Для интересующихся родословной языков программирования вот весьма любопытная ссылка
http://hopl.murdoch.edu.au/findlanguages.prx?year=1972&which=byyear

andrews
29.11.2006, 11:00
Ага! А вот и более точные сведения об этом языке...правильное название PLZ на этом же сайте ( прошу прощения что несколькими минутами раньше высказывал мое давнее заблуждение...многолетний туман загадочности рассеялся для меня только сейчас :) )
Итак, знакомьтесь PLZ!
http://hopl.murdoch.edu.au/showlanguage.prx?exp=865&language=PLZ

captain cobalt
29.11.2006, 13:33
Вот нашлась такая вещь:
http://archive.computerhistory.org/resources/text/Zilog/

Это сканированные рекламные брошюры 70-х годов.
Цитата из самой последней:

PLZ

PLZ is Zilog's own family of system implementation languages. Designed specifically with the system programmer in mind, PLZ provides an extremely sophisticated structured programming environment. Implemented at two separate language levels and distinct translator packages, PLZ offers a complete solution to microcomputer system programming problems.

In its highest level, PLZ is a fully block structured language with an IF-THEN-ELSE clause, a case selector (actually implemented in the syntax of the IF statement), block REPEAT and EXIT statements, procedure references and, of course, RETURN's. Data types include BYTE, WORD, INTEGER, SHORT INTEGER and POINTER as well as ARRAYS of any type and RECORD's composed of groupings of the various basic types, arrays, or even other records.

At this language level, both an Interpreter and a Compiler are available. The interpreter provides a fast and convenient means of program development and debugging, while the highly efficient Compiler generates Z80 Object code.

For applications requiring total control of hardware resources, a second level of PLZ provides all the block structuring and control conventions of the full compiler, but uses assembly language statements rather than compiler level expressions and assignments. Thus, it acts as PLZ compatible structured assembler and produces code which can be linked directly to modules translated by the compiler.

Regardless of the scope or complexity of a system programming problem, PLZ will provide a simple, elegant, and complete environment for its solution.

andrews
29.11.2006, 14:23
Комиксы это конечно здорово, но похоже это как раз пример того, что когда был сам язык, не было еще инета, а теперь нет уже языка :( Правда остался патент и к нему описание, но доступ туда только тем, кто является членом, т.е. платит бабки. Так что конкурс на лучшего языкаВУ-кандидата для z80 остается пока что без претендентов.

maximk
29.11.2006, 21:32
Решил протестить компиляторы z80 на dhryston'е.

Вот такие результаты на 10000 запусков:
z88dk - 3852 ticks ~ 130 dps (c register тоже самое)
sdcc - 2613 ticks ~ 191 dps (с register тоже самое)
hitech - 2621 ticks ~ 191 dps
hitech register - 2607 ticks ~ 192 dps

Почему hitech без register оказался хуже sdcc я пока не понял.

Дополнительные замечания. Тестирование проводилось под эмулятором unreal, в исходный текст dhrystone 2.1 были внесены изменения для подстройки под компилятор, так как некоторые фишки не поддерживаются.

Время измерялось чтением переменной SOS FRAMES.
Из библиотечных функций внутри теста вызываются только strcpy и strcmp. Оные использованы из собственных библиотек компилятора. Написаны они по-разному, но все на асме, так что тут вроде условия более менее равные.

Комментарии по возможностям компиляторов:

hitech откомпилил все с минимальными изменениями.

sdcc умеет почти все, но не умеет присваивать структуры по значению. Написал для него memcpy на асме через LDIR (hitech LDIR встраивает в сам код).

z88dk не умеет ряд очень важных вещей, а именно:
* не поддерживает многомерные массивы. Работу с многомерными массивам в тексте заменил на работу с одномерным через arr[y*width+x]
* какие-то косяки с typedef. Массивы определять не умеет, тип typedef, являющийся указателем на структуру тоже, не поддерживает.
* не поддерживает(!) указатели на функции. Это я уже узнал потом, а в тесте эта фича не заюзана, хотя ой как нужна!

sdcc и z88dk никак не прореагировали на register. Видимо они и так работают на пределе своих сил. А вот для hitech register не пустой звук.

Исходя также из анализа проведенного Vitamin'ом могу сказать, что Hitech, конечно, лучший. Но вот sdcc отстает от него совсем чуть-чуть. Видимо Hitech просто лучше справляется с подковырками из теста на compiler features, но в реальных программах такое не так уж и требуется.

Что такое Dhrystone и почему стоит обратить на него внимание:
http://en.wikipedia.org/wiki/Dhrystone

Vitamin
29.11.2006, 22:47
sdcc - 2613 ticks ~ 191 dps (с register тоже самое)
гм. я ожидал худшего результата в связи с любовью этого компилятора к индексному регистру.
Попробуй скомпилять тест с вот этим вот файлом peephole-оптимизатора (как подключать написано в хелпе компилера)



replace restart {
ld iy,%1
ld 0(iy),#0x%2
ld 1(iy),#0x%3
ld 2(iy),#0x%4
ld 3(iy),#0x%5
} by {
ld de,#0x%3%2
ld (%1),de
ld de,#0x%5%4
ld (%1+2),de
}
replace restart {
ld iy,%1
ld 0(iy),#0x%2
ld 1(iy),#0x%3
} by {
ld de,#0x%3%2
ld (%1),de
}
replace restart {
ld iy,%1
ld 0(iy),l
ld 1(iy),h
} by {
ld (%1),hl
}
replace {
ld iy,%1
ld 0(iy),c
ld 1(iy),b
ld 2(iy),e
ld 3(iy),d
} by {
ld (%1),bc
ld (%1+2),de
}

replace {
ld iy,%1
ld 0(iy),c
ld 1(iy),b
} by {
ld (%1),bc
}

replace {
jp %5
} by {
ret
} if labelIsReturnOnly

replace {
jp %1,%5
} by {
ret %1
} if labelIsReturnOnly

replace {
jp %5
} by {
jr %5
} if labelInRange

replace {
jp z,%5
} by {
jr z,%5
} if labelInRange

replace {
jp nz,%5
} by {
jr nz,%5
} if labelInRange

replace {
jp c,%5
} by {
jr c,%5
} if labelInRange

replace {
jp nc,%5
} by {
jr nc,%5
} if labelInRange

replace {
ld iy,%1
ld a,0(iy)
ld iy,%2
sub a,0(iy)
ld iy,%1
ld a,1(iy)
ld iy,%2
sbc a,1(iy)
} by {
and a,a
ld hl,(%1)
ld de,(%2)
sbc hl,de
}

replace {
ld iy,%1
ld a,0(iy)
sub a,#0x%2
ld a,1(iy)
sbc a,#0x%3
} by {
ld hl,(%1)
ld de,#0x%3%2
and a,a
sbc hl,de
}

maximk
29.11.2006, 22:54
Попробуй скомпилять тест с вот этим вот файлом peephole-оптимизатора (как подключать написано в хелпе компилера)

Ну, получилось как у Hitech с register - 2607 ticks. :))

Vitamin
30.11.2006, 00:04
Ну, получилось как у Hitech с register - 2607 ticks. )
Итого два лидера в команде

Посмотри полученный код и попробуй подправить файл оптимизатора. Я его писал в расчете на свой тест, у тебя могли другие конструкции использоваться.

SfS
30.11.2006, 06:32
А есть у кого исходники-патчи для гнутых утилит под z80 ? gcc и binutils, которые ?
Если есть - киньте ссылку, хочу глянуть, что это такое.

NovaStorm
30.11.2006, 08:27
GCC для Z80 - миф =)
Довольно много людей пробовало сделать порт.
http://gcc.gnu.org/ml/gcc-patches/2001-06/msg01546.html тут даже патч есть.
http://gcc.gnu.org/ml/gcc/2003-05/msg02369.html а вот тут даже московский телефон.
http://gcc.gnu.org/ml/gcc/2003-03/msg01402.html почему gcc плох/хорош для разных процов.

Vitamin
30.11.2006, 09:43
http://gcc.gnu.org/ml/gcc/2003-03/msg01402.html почему gcc плох/хорош для разных процов.
Интересный обзор. Только непонятно, как же тогда gcc работает на x86 ? Архитектура не ортогональная, РОНов не так много, физический адрес зависит от сегментных регистров.
Да и вообще, z80 суть есть предок x86....

NovaStorm
30.11.2006, 11:05
Дык это 2003 год. А работа gcc обусловлена скорее всего тем, что под х86 он и точится. Если вести речь про i386 и AMD64 то там не все так плохо, как в 8086. и режимов адресации хватает, и регистры во многих случаях равноправны, 32-48 бит адресация... Но этот монстуозный велосипед тоже конечно не фонтан =)

Vitamin
30.11.2006, 11:59
А работа gcc обусловлена скорее всего тем, что под х86 он и точится.
Судя по требованиям, точился он под ARM- там тебе и ортогональная структура и дохрена РОНов и еще куча разных вкусностей (не говорю про ложку дегтя в виде ограничений на прямую загрузку констант)

fk0
30.11.2006, 12:21
Решил протестить компиляторы z80 на dhryston'е.

Вот такие результаты на 10000 запусков:
z88dk - 3852 ticks ~ 130 dps (c register тоже самое)
sdcc - 2613 ticks ~ 191 dps (с register тоже самое)
hitech - 2621 ticks ~ 191 dps
hitech register - 2607 ticks ~ 192 dps

Почему hitech без register оказался хуже sdcc я пока не понял.


Я не понял, почему он не выигрывает у z88dk даже в 2 раза. В то, что sdcc таки допинали до рабочего состояния верится с трудом. В чём же тогда дело?

Хотелось бы увидеть:

1) какие версии компиляторов использовались во всех случаях;

2) какие командные строки использовались для сборки теста.

Может, у hitech попросту не была включена оптимизация?



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


Несколько лет назад hitech середины-конца 90-х годов (версия для DOS) выигрывал просто по размеру листинга в строках, у SDCC, В РАЗЫ. :-/

yoko_ono
30.11.2006, 12:37
Судя по требованиям, точился он под ARM- там тебе и ортогональная структура и дохрена РОНов и еще куча разных вкусностей (не говорю про ложку дегтя в виде ограничений на прямую загрузку констант)

Скажите, а Вы себе кроме АРМ не представляете больше никаких RISC-процессоров с 'дохрена РОНов', трёхадресными командами и 'ортогональной структурой'? Если не представляете, то печально...

SfS
30.11.2006, 13:12
GCC для Z80 - миф =)

Странно, почему миф ? Под AVR gcc есть, развивается и вдобавок генерит очень неплохой код... Почему для Z80 нет этого ?

fk0
30.11.2006, 13:59
Комиксы это конечно здорово, но похоже это как раз пример того, что когда был сам язык, не было еще инета, а теперь нет уже языка :( Правда остался патент и к нему описание, но доступ туда только тем, кто является членом, т.е. платит бабки. Так что конкурс на лучшего языкаВУ-кандидата для z80 остается пока что без претендентов.

Что? Номер патента в студию.

NovaStorm
30.11.2006, 14:10
Скажите, а Вы себе кроме АРМ не представляете больше никаких RISC-процессоров с 'дохрена РОНов', трёхадресными командами и 'ортогональной структурой'? Если не представляете, то печально...
Ммм... спек на FPGA перепрограммируем на хороший ортогональный(кому оно вообще надо? load-store "хватит всем"), "с 'дохрена РОНов'" (128 GPR) OpenSPARC и понеслась... =)

yoko_ono
30.11.2006, 14:20
Странно, почему миф ? Под AVR gcc есть, развивается и вдобавок генерит очень неплохой код... Почему для Z80 нет этого ?

Видимо потому, что в авр 32 равноправных (ну, или почти) регистра. 8-битных, правда, но тем не менее.

Vitamin
30.11.2006, 14:23
Скажите, а Вы себе кроме АРМ не представляете больше никаких RISC-процессоров с 'дохрена РОНов', трёхадресными командами и 'ортогональной структурой'? Если не представляете, то печально...
Я говорю про АРМ потому что достаточно тесно с ним работаю. И если этот простой факт не пришел в вашу светлую голову, то печально.

ЗЫ. За вами должок! ;)

SfS
01.12.2006, 06:00
Видимо потому, что в авр 32 равноправных (ну, или почти) регистра. 8-битных, правда, но тем не менее.

Ну только не поэтому... Для х86х gcc тоже код генерит, хотя там такой же разнобой с регистрами, что на Z80...
Да и в AVRке регистры r0, r1-r15, r16-r25 и r26-r31 далеко не равноправны...

yoko_ono
04.12.2006, 15:05
Я говорю про АРМ потому что достаточно тесно с ним работаю. И если этот простой факт не пришел в вашу светлую голову, то печально.

Вы работаете с армом и поэтому решили, что gcc точился под арм? Браво, вашей логике позавидуют даже блондинки...



ЗЫ. За вами должок! ;)
Да что вы.

yoko_ono
04.12.2006, 15:09
Ну только не поэтому... Для х86х gcc тоже код генерит, хотя там такой же разнобой с регистрами, что на Z80...

По крайней мере в ia32 можно говорить, что имеющиеся 7 регистров более-менее равноправны, за редкими исключениями вроде 8-битных загрузок и умножений-делений.



Да и в AVRке регистры r0, r1-r15, r16-r25 и r26-r31 далеко не равноправны...

И что? Их же 32, и со всеми (абсолютно со всеми) возможны 2-адресные логические и арифметические операции. Неравноправность только в операциях с константами и 16-битными указателями в память.

Vitamin
04.12.2006, 15:38
Вы работаете с армом и поэтому решили, что gcc точился под арм?
Почемуто вы опустили предыдущую фразу тов. NovaStorm, где он сказал, что gcc заточен под х86. Почему-то она вопросов не вызвала. А вот мое возражение, в котором в качестве аргумента я привел АРМ, сразу "обидело державу". Вы кроме х86 больше ни на чем не работали?


Браво, вашей логике позавидуют даже блондинки...
Официально разрешаю завидовать даже вам.


Да что вы.
Да. Вы меня обвинили в недостаточном знании возможностей ALASM'а (с чем, собственно согласен), но никак не доказали свою состоятельность в этом вопросе. Вместо этого довольно топорно увильнули от беседы. Так что...

Raydac
21.12.2006, 13:37
а мой транслятор PC110 Си->Z80 Asm у когонить сохранился? а то че то меня ностальжи мучать начала, не моглиб прислать на rrg<собака>forth.org.ru

deathsoft
31.12.2006, 14:26
Почему для Z80 нет этого ?
Потому, что это никому не нужно. В новых разработках Z80 никто не использует, поэтому и порт для gcc не делают. gcc например поддерживает 68hc11, 68hc12 и т.п., хотя поддержка этих контроллеров сложнее чем поддержка Z80.

Lethargeek
01.01.2007, 05:54
Недостаток же C применительно конкретно к z80 тот, что это отнюдь не стековый проц в том смысле, что у него богатый набор регистров и операций с ними, которые известные реализации C явно недоиспользуют... и оттого проигрыш сишных прог становится ощутимее.
(оффтоп) А у хваленого недориск-проца 6502 ваще полный мрак с ЯВУ, особенно компиляторами :p (/оффтоп)

Vitamin
14.03.2007, 00:51
Скачал компилятор IAR и решил протестить. Весьма серьезная штука. Имеется довольно развитая среда разработки, куча библиотек.

Компилятор был протестирован в двух режимах работы- с максимальной оптимизацией по скорости и по размеру.
Из влияющих на кодогенерацию настроек:
Large model, enable undocumented instructions, use alternate register set, use rst-functions, static allocation of 'autos', language extensions, 'char' is 'signed char'.

Для начала быстрая версия кода:
0. Пролог. Ничего особого


PUSH BC
PUSH DE


1. Размножение констант и копий


;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:


2. Свертка констант


;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

Деление на 0 было определено на этапе компиляции. Пришлось объявить NO_ZERO_DIVIDE


;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


3. Лишнее присваивание


;k3 = 1;
;k3 = 1;
;в Багдаде все спокойно...
LD HL,1
LD (k3),HL


4. Снижение мощности


;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:


5. Простой цикл


;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:


6. Управление переменной индукции цикла


;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:


7. Глубокие подвыражения


;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:


8. Генерация адреса переменной с константным индексом


;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


9. Удаление общих подвыражений


;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:
;}

Vitamin
14.03.2007, 00:52
10. Вынесение инвариантного кода


;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:


11. Вызов функции с аргументами


;dead_code( 1, "This line should not be printed" );
;все чин-чином: справа налево, в регистрах
LD BC,?0043
LD DE,1
CALL dead_code


12. Вызов функции без аргументов, эпилог


;unnecessary_loop();
;ничего особого. в конце очистка стека и возврат по дну(!)
CALL unnecessary_loop
POP HL
POP HL
RET


13. Проверка недостижимого кода и лишних присваиваний


;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


14.Ненужный цикл


;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


15. Слияние циклов


;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


16. Разворот циклов


;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


17. Сжатие цепочки переходов


;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


Версия с оптимизацией по размеру отличается в основном операциями сравнения, кой-какой оптимизацией загрузки регистров а также вызовом рестартов в прологах (rst 8) и эпилогах (rst 20h) функций, принимающих параметры (кроме jump_compression)

Резюме: 9/10. Компилятор оставил крайне приятное впечатление практически полным отсутствием неоправданных наворотов (иногда даже в ущерб...) и грамотным использованием регистров.
Для практического применения следует выработать ряд рекомендаций, направленных на улучшение качества кода (что, впрочем, является обычным явлением для всех ЯВУ для встроенных систем).

ЗЫ. Если все переменные, где не нужна знаковость, принудительно объявить как unsigned, а также снять опцию "static allocation of 'autos'" (в данном случае), то можно получить достаточно весомый выигрыш по оптимизации! В частности, первая рекомендация весьма и весьма упрощает операции сравнения, а вторая облегчает функции с маленьким числом локальных переменных и оптимизирует использование регистров как переменных

NovaStorm
14.03.2007, 09:02
Кажется в IAR можно управлять вычислением указателей, не сталкивался? А то вот интересно, можно ли это применить для того, чтобы дать проге побольше памяти как при стандарном 7FFD, так и при более навороченном (4x16k)MMU? Сорцы uzi(x) как глотает? А то, я так понял, оно довольно старомодно писано...

Vitamin
14.03.2007, 09:55
NovaStorm,
Вроде бы можно. При использовании банкируемой модели все вызовы стандартных функций оборачиваются в прокси, указатели на дальнюю память, думаю, тоже.
На досуге поближе познакомлюсь с этим компилером, заинтересовал :)
Он еще под msp430 генерил более компактный код, нежели gcc. Правда имеющаяся среда разработки кривоватая...

valker
14.03.2007, 10:43
Кажется в IAR можно управлять вычислением указателей, не сталкивался? А то вот интересно, можно ли это применить для того, чтобы дать проге побольше памяти как при стандарном 7FFD, так и при более навороченном (4x16k)MMU? Сорцы uzi(x) как глотает? А то, я так понял, оно довольно старомодно писано...

Что значит "управлять вычислением указателей"?
В IAR модель памяти "banked" поддерживает размещение констант и кода в расширенной памяти (насчёт переменных - не уверен).
Написав функции вызова дальней процедуры и возврата оттуда можно дать проге до 64К*256 = 16М памяти (по максимуму). При размере страницы 16к -> 16К*256 = 4М.
Существуют модели с таким объемом ОЗУ?

valker
14.03.2007, 11:21
Я тут состряпал примерчик, как на IAR под ZX-Spectrum 128 проектики собирать. Надеюсь, будет полезным.

http://zx.pk.ru/attachment.php?attachmentid=4808&stc=1&d=1173860306

Error404
14.03.2007, 12:40
Я тут состряпал примерчик, как на IAR под ZX-Spectrum 128 проектики собирать. Надеюсь, будет полезным.

http://zx.pk.ru/attachment.php?attachmentid=4808&stc=1&d=1173860306

Какой пароль в твоем iar*.rar 9M ?

valker
14.03.2007, 12:43
Какой пароль в твоем iar*.rar 9M ?

пароль speccy.wikispaces.com
здесь всё написано: http://speccy.wikispaces.com/iar_cross

Vitamin
15.03.2007, 10:54
Я тут состряпал примерчик, как на IAR под ZX-Spectrum 128 проектики собирать. Надеюсь, будет полезным.
Имхо надо бы переписать файлик L08.s01- дюже монстроидальные процедурки. А поддержку многопамятности (разные расширения по памяти) обернуть в условную компиляцию.
Компилятор интересный (а в этой ветке его ктото конкретно обкакал- типа код лажовый генерится, видать про -s9/-z9 и слыхом не слыхивал...), в ближайшее время думаю погонять его на своих разных тестах чтоб посмотреть как он генерит разные конструкции. По поводу передачи параметров в доке исчерпывающе написано, а вот про структуру- ничего нет.
Пока на глаз прикинул следующие рекомендации по написанию кода (часть из них нашла подтверждение в мануале):
-где возможно использовать беззнаковые операнды (в частности там, где имеются сравнения). При этом читать предупреждения компилятора, он ловит бессмысленные сравнения.
-где возможно использовать операнды меньшей разрядности (если счетчик от 0 до 100, то 1 байта ему будет с головой)
-использовать общие переменные только если это действительно надо (в моем вышеприведенном тесте имеются общие переменные типа i,j,k...), для временных переменных использовать локальные. Это позволит компилятору хранить их в регистрах.

Остальные рекомендации допишу когда детально все пощщупаю :)

valker
15.03.2007, 11:15
Имхо надо бы переписать файлик L08.s01- дюже монстроидальные процедурки. А поддержку многопамятности (разные расширения по памяти) обернуть в условную компиляцию.
Естественно. Всё делалось в режиме эксперимента - заработает/не заработает. Как минимум, табличку можно по круглому адресу положить.


Компилятор интересный (а в этой ветке его ктото конкретно обкакал- типа код лажовый генерится, видать про -s9/-z9 и слыхом не слыхивал...), в ближайшее время думаю погонять его на своих разных тестах чтоб посмотреть как он генерит разные конструкции. По поводу передачи параметров в доке исчерпывающе написано, а вот про структуру- ничего нет.
Я заметил, что иногда этот компилятор генерит лишние команды пересылки между регистрами. А про какую "структуру" ничего нет?


Пока на глаз прикинул следующие рекомендации по написанию кода (часть из них нашла подтверждение в мануале):
Ещё: часто вызываемые процедуры размещать в нижней памяти (модификатор non_banked) - это позволит сократить время вызова/возврата.

В контексте использования С-компилятор + эмулятор хорошо бы какой-нибудь профайлер придумать, чтобы узкие места обнаруживать и на ассемблере переписывать.

Vitamin
15.03.2007, 11:46
заметил, что иногда этот компилятор генерит лишние команды пересылки между регистрами. А про какую "структуру" ничего нет?
Ну это следствие недостаточно гибкой модели распределения ролей регистров имхо.

Про структуру- надо глянуть как он генерит switch/case конструкции при разном количестве ветвей (проверки или таблица и где порог принятия решения) и как склеивает ветки если надо, какие конструкции лучше использовать.
Например в вышеуказанном примере var = var + 1; дало далеко не оптимальный код. Вот надо глянуть, что будет при var += 1; и var++/++var. Плюс как он делает постфиксный/префиксный инкремент если нужен результат (ну префиксный это понятно...).
Может ли сам делать подстановку тела процедуры в код вместо вызова (например для memcpy). Как выворачивает целочисленное умножение (что сдвигами, а что вызовом) или деление (не уверен что его вообще сдвигами делает). Как делается вызов функции по указателю.



В контексте использования С-компилятор + эмулятор хорошо бы какой-нибудь профайлер придумать, чтобы узкие места обнаруживать и на ассемблере переписывать.
По поводу эмулятора- легко можно написать программку конверсии итогового хекс-дампа в снапшот. Формат там такой
[Sn][Len][00][data][crc]

Sn- неизвестно... наверное описание области прошивки(?)
Len- количество следующих за ним байт (включая 00 и crc)
crc- подбирается таким образом, что сумма всех полей, начиная с len и до конца заканчивается на 255.
Для строк типа S2 первые 2 байта data содержат адрес в big endian формате

Ты C-spy щупал? он только с железяками дружит или к нему можно прикрутить программный эмуль?

valker
15.03.2007, 11:59
По поводу эмулятора- легко можно написать программку конверсии итогового хекс-дампа в снапшот. Формат там такой
[Sn][Len][00][data][crc]

Sn- неизвестно... наверное описание области прошивки(?)
Len- количество следующих за ним байт (включая 00 и crc)
crc- подбирается таким образом, что сумма всех полей, начиная с len и до конца заканчивается на 255.
Для строк типа S2 первые 2 байта data содержат адрес в big endian формате
Формат называется motorola srec. Вот тут описалово: http://www.amelek.gda.pl/avr/uisp/srecord.htm. Для нас актуальны записи типа: 0,1,2,9. Я написал конвертер в sna-формат. Но не выкладывал (сырой он, плюс требует .NET2.0). Ежели нужно, могу выложить.

Ты C-spy щупал? он только с железяками дружит или к нему можно прикрутить программный эмуль?Не щупал. Я пока в unreal отлаживаюсь. Конечно, не хватает отладки по исходникам, но это не самое страшное.

Vitamin
15.03.2007, 15:09
Я написал конвертер в sna-формат. Но не выкладывал (сырой он, плюс требует .NET2.0). Ежели нужно, могу выложить.
Дотнету- нет! :)

Вот сырец моего конвертора (тока шо написал, еще не проверял).
Не берет пока 128к режим (ибо не знаю пока как раскиданы адреса по страничкам). Компиляется под gnu-gcc, но должен собраться и под виндой и под досом (ничего специфичного).
Имя выходного файла можно задать, иначе оно берется либо из секции 0 или имени входного файла.


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef unsigned char BYTE;
typedef unsigned short WORD;

#pragma pack(push, 1)
struct SNA48
{
BYTE i;
WORD hl_;
WORD de_;
WORD bc_;
WORD af_;
WORD hl;
WORD de;
WORD bc;
WORD iy;
WORD ix;
BYTE intstat;
BYTE r;
WORD af;
WORD sp;
BYTE intmode;
BYTE border;
BYTE memory[49152];
};

struct SNA128
{
SNA48 hdr1;
WORD pc;
BYTE port7ffd;
BYTE trdosrom;
BYTE himemory[5 * 16384];
};
#pragma pack(pop)

class FdEnv
{
FdEnv(const FdEnv&);
FdEnv& operator = (const FdEnv&);
public:
FdEnv(FILE* fil) {if (! (file_ = fil)) throw "Cannot open file";}
~FdEnv() {fclose(file_);}
operator FILE* () {return file_;}
private:
FILE* file_;
};

// usage: makesna -o output.sna -v -b0 -r24576 input.s01
int main(int argc, char** argv)
{
SNA128 snapshot;
unsigned verbose = 0;
unsigned getname = 1;
int result = 0;
unsigned use128k = 0;
unsigned startaddr =0;

char* infile = NULL;
const char* outfile = NULL;

memset(&snapshot, 0, sizeof(snapshot));
try
{
if (argc < 2)
{
printf( "Convert .a01 -> sna\n"
"Usage:\n"
"%s [options] inputfile\n\n"
"Options:\n"
"-o <filename> -- specify output file name (else it will be taken from dump or input filename)\n"
"-v -- be verbose\n"
"-bN -- set border to N\n"
"-rN -- set run address to N\n"
, *argv);
throw 1;
}
int argind = 1;
for (;;)
{
if (argind == argc)
throw "Wrong parameters";
if (argind == argc - 1)
{
infile = argv[argind];
break;
}
if (! strcmp(argv[argind], "-v"))
{
verbose = 1;
argind++;
} else
if (! strcmp(argv[argind], "-o"))
{
outfile = argv[argind + 1];
argind += 2;
} else
if (! strncmp(argv[argind], "-b", 2))
{
snapshot.hdr1.border = atoi(argv[argind++] + 2) & 7;
} else
if (! strncmp(argv[argind], "-r", 2))
{
startaddr = atoi(argv[argind++] + 2);
}
}

char outname[256] = {0};
{
FdEnv file(fopen(infile, "rt"));
char instr[520];
BYTE dump[256];
//prepare filename
if (outfile)
strncpy(outname, outfile, 256);
else
strncpy(outname, infile, 256);

while (fgets(instr, 520, file))
{
unsigned mode = 0;
unsigned count = 0;
if (sscanf(instr, "S%1i%02x", &mode, &count) != 2) throw "Wrong file!";
infile = instr + 4;
BYTE* out = dump;
unsigned crc = count;
unsigned cnt = 0;
while (sscanf(infile, "%02x", dump + cnt) && cnt != count)
{
crc += dump[cnt++];
infile += 2;
}
if (count != cnt) throw "Error in file!";
if (0xff != (crc & 0xff)) throw "Wrong crc!";
unsigned addr = (dump[0] << 24) | (dump[1] << 16) | (dump[2] << 8) | dump[3];
out = dump + 4;
switch (mode)
{
case 0:
if (! outfile)
{
memcpy(outname, dump + 2, cnt - 3);
outname[cnt - 3] = 0;
}
break;
case 1:
out--;
addr >>= 8;
case 2:
out--;
addr >>= 8;
case 3:
if (addr & 0xffff0000) throw ">16 bit addresses are not supported";
while (out != dump + cnt - 1)
{
if (addr >= 0x4000 && addr < 0xffff)
snapshot.hdr1.memory[addr - 0x4000] = *out;
out++;
addr++;
}
break;
case 5:
break;
case 9:
out--;
addr >>= 8;
case 8:
out--;
addr >>= 8;
case 7:
if (!startaddr) startaddr = addr;
break;
default:
throw "Unknown field type!";
}
}
if (startaddr & 0xffff0000) throw "> 16 bit start address is not supported";
if (verbose)
{
printf("Created %s\nPC=%#x\n", outname, startaddr);
}
if (use128k)
snapshot.pc = startaddr;
else
{
snapshot.hdr1.sp = 0x4000;
snapshot.hdr1.memory[0] = startaddr & 0xff;
snapshot.hdr1.memory[1] = startaddr >> 8;
}
}
infile = strrchr(outname, '.');
if (! infile) infile = strrchr(outname, 0);
strcpy(infile, ".sna");
FdEnv file(fopen(outname, "wb"));
fwrite(&snapshot, use128k ? sizeof(SNA128) : sizeof(SNA48), 1, file);
}
catch (const char* msg)
{
puts(msg);
result = 1;
}
catch (int val)
{
result = val;
}
catch (...)
{
puts("Unknown exception");
result = 1;
}
return result;
}

deathsoft
16.03.2007, 00:36
а поискать влом было?
http://www.s-record.com/
конвертеров из srec в bin полным полно, аналогично и из ihex в bin.
если уж не нашли, могли бы objcopy из пакета binutils использовать (входит в cygwin и mingw)

Более того в IAR должна быть опция линкера генерировать на выходе bin файл для прошивки ПЗУ.

Vitamin
16.03.2007, 09:19
а поискать влом было?
http://www.s-record.com/
конвертеров из srec в bin полным полно, аналогично и из ihex в bin.
если уж не нашли, могли бы objcopy из пакета binutils использовать (входит в cygwin и mingw)

Более того в IAR должна быть опция линкера генерировать на выходе bin файл для прошивки ПЗУ
А подумать влом было?
Что делать с этим бинарником на выходе? В качестве пзухи в эмулятор подключать?

maximk
16.03.2007, 09:31
А подумать влом было?
Что делать с этим бинарником на выходе? В качестве пзухи в эмулятор подключать?

Заюзать потом, например, это
http://zx.pk.ru/showthread.php?t=93

Vitamin
16.03.2007, 09:44
Заюзать потом, например, это
http://zx.pk.ru/showthread.php?t=93
Тоже вариант. Попробуй использовать этот конвертер и ту утилитку с вышеуказанного сайта.

Я тебе сразу скажу на чем споткнешься- на определении стартового адреса

deathsoft
16.03.2007, 11:07
А подумать влом было?
Что делать с этим бинарником на выходе? В качестве пзухи в эмулятор подключать?
Присабачить бейсик загрузчик и радоваться, загрузчик можно в asm файле через db вбить. А можно и просто на асме написать, а потом совместно слинковать. И даже заголовок хобетты можно присобачить, в результате получится .$B файл, в котором будет загрузчик (под REM) а дальше запускаемый блок кода.

Загрузчик такого плана:
10 REM тут идет асмовый код
20 randomize usr то что после REM

Vitamin
16.03.2007, 11:22
Присабачить бейсик загрузчик и радоваться, загрузчик можно в asm файле через db вбить.
Если цель стоит создать конечное приложение, то такой вариант пойдет (с ограничениями правда). А для отладки только снапшоты.
Тем более, вопрос определения стартового адреса из этого бинарника остается открытым

deathsoft
16.03.2007, 11:25
Таким же образом и sna файл делается. Все формирует линкер, в массиве из db делаются выражения куда подставляются стартовый адрес длина и другие параметры, линкер при линковке их заполняет.

Добавлено через 1 минуту

А для отладки только снапшоты.
Для отладки я вообще bin файл в эмулятор загружаю по нужному адресу, и коректирую PC в отладчике.

Vitamin
16.03.2007, 11:39
А я предпочитаю один раз потратить 10 минут на написание удобного инструмента под свои цели, нежели целый день искать что подходящее, потом еще день прикручивать к имеющемуся или 100 раз в день долбаться по 1 минуте...

deathsoft
16.03.2007, 11:40
Тем более, вопрос определения стартового адреса из этого бинарника остается открытым
Что значит вопрос определения стартового адреса? Под какой адрес слинковал, под такой загрузит и запустит. Например под 0x8000 или под 0xC000, что в линкере укажешь, то и будет, и загрузчик линкер автоматом на этот адрес настроит. Для этого linker/locater и сделан.

Vitamin
16.03.2007, 12:00
В общем случае адрес запуска программы не совпадает со стартовым адресом расположения кодового блока...

deathsoft
16.03.2007, 12:01
А я предпочитаю один раз потратить 10 минут на написание удобного инструмента под свои цели, нежели целый день искать что подходящее
Искать ничего и не надо, objcopy входит в сотсав gcc, которым ты пользуешься.

Vitamin
16.03.2007, 12:06
Искать ничего и не надо, objcopy входит в сотсав gcc, которым ты пользуешься.
gcc я пользуюсь на работе, дома у меня винда стоит. Так что пока остаюсь при своем мнении насчет инструмента (который кстати без проблем собирается и под виндой, сейчас доработал его как раз до 128к)

deathsoft
16.03.2007, 12:26
В общем случае адрес запуска программы не совпадает со стартовым адресом расположения кодового блока...
Что такое LMA и VMA в линкере знаешь?

Добавлено через 52 секунды

gcc я пользуюсь на работе, дома у меня винда стоит.
gcc и под винду есть, cygwin и mingw, к томуже бинутилсы есть нативные под винду.

Vitamin
16.03.2007, 12:58
Что такое LMA и VMA в линкере знаешь?
В описалове не нашел, но подозреваю что Local/Virtual Memory Address. Так?
Можно заставить линкер насильно делать стартовую точку в начале кодового блока?
Если нет, то как ты узнаешь из простого бинарника этот адрес?


gcc и под винду есть, cygwin и mingw, к томуже бинутилсы есть нативные под винду.
cygwin у меня есть, но все равно это не совсем то. Как среда для выполнения шелл-скриптов (ибо командные файлы это редкостный дуст) еще пойдет. Чтото серьезное- не очень...
Елки! Я ж ленивый человек, мне проще сделать свое, нежели искать что там есть подобного в мире...

deathsoft
16.03.2007, 13:06
В описалове не нашел, но подозреваю что Local/Virtual Memory Address. Так?
Можно заставить линкер насильно делать стартовую точку в начале кодового блока?
Если нет, то как ты узнаешь из простого бинарника этот адрес?
Линкер можно заставить сделать что угодно (особенно если это линкер ld).
LMA - адрес где лежит код
VMA - адрес с которого он исполняется
линкером ld можно вообще сформировать обычный .sna файл, а не plane binary. А можно и в plane binary сделать так:
dw entry
а дальше этот entry в линк скрипте объявить как хочешь, хоть выражением высчитать.

В ИАРовском линкере все примерно также, токо там скрипты победнее чем в ld

Vitamin
16.03.2007, 14:30
Линкер можно заставить сделать что угодно (особенно если это линкер ld).

В ИАРовском линкере все примерно также, токо там скрипты победнее чем в ld
Ну значит как будет время поковыряюсь. Спасибо за совет!

deathsoft
18.03.2007, 14:49
Программа закрашивает прямоугольную область экрана пикселями в шахматном порядке.

Для компиляции программы необходим IAR C, программа использует свой нестандартный startup, поэтому из стандартной библиотеки IAR необходимо удалить модуль startup (модифицированная библиотека есть в архиве).

Выходом компиляции является файл test.sna (причем этот файл в формате intel-hex формируется самим компилятором).

Для преобразования hex->bin служит всего одна внешняя утилита objcopy из пакета binutils (для windows входит в cygwin и mingw).

Аналогичным образом делаются программы с бейсик загрузчиком.

Более того IAR C позволяет генерировать программы с автоматическим переключением банков памяти (например для ZX128 и выше), при этом необходимо написать всего лишь одну дополнительную функцию (которая включает нужный банк памяти) на ассемблере.

Error404
21.03.2007, 13:24
по MIX C есть у кого-нибудь документация?

Valen
26.04.2009, 13:34
IAR C безусловно крут.

SDCC рулит для разработки открытых проектов, где важно наличие открытых средств разработки (и такое бывает :))
Можно посмотреть таблицу сравнения компилеров.
(http://sourceforge.net/apps/trac/sdcc/wiki/Philipp%27s%20TODO%20list)