Как включить инструкцию DIV в выводе ASM компилятора C

Я использую компилятор vbcc для перевода моего кода C в Motorola 68000 ASM.

По какой-то причине каждый раз, когда я использую в коде деление (просто целое, а не с плавающей запятой), компилятор вставляет в вывод ASM только следующую заглушку (которая генерируется при каждой перекомпиляции):

public  __ldivs
jsr __ldivs

Я явно искал все варианты DIVS/DIVU, но каждый раз находил только эту заглушку выше. Сам код работает (я отлаживал его на целевом устройстве), поэтому в окончательном коде есть инструкция DIV, а не промежуточный вывод.

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

Однако я не могу этого сделать, если не вижу результирующий код ASM. Любые идеи, как включить его? В руководстве по компилятору ничего подобного не указано, поэтому явно должен быть какой-то другой - возможно, общий - высший принцип в игре?


person 3D Coder    schedule 29.09.2015    source источник
comment
Эта заглушка на самом деле является вызовом функции __ldivs. Скорее всего, это часть вашей библиотеки времени выполнения C. Возможно, вы захотите разобрать функцию __ldivs, чтобы посмотреть, как она выполняет вычисления.   -  person Michael Petch    schedule 29.09.2015
comment
Какие типы имеют openers и result? 68000 не имеет полного 32-битного деления. Покажите минимально воспроизводимый пример   -  person too honest for this site    schedule 29.09.2015
comment
@MichaelPetch Ну, проблема с библиотекой времени выполнения C в том, что у меня ее нет - например. У меня нет доступа к куче/поплавкам/memcpy или чему-то подобному — только базовый набор языков. Возможно, платформа имеет минимальное время выполнения. Позвольте мне проверить библиотеки, с которыми он связан. Я просмотрел 300 тысяч строк вывода ASM и убедился, что __ldivs там нет.   -  person 3D Coder    schedule 29.09.2015
comment
Вероятно, вы ссылаетесь на какую-то математическую библиотеку.   -  person Michael Petch    schedule 29.09.2015
comment
@Olaf: Типы короткие int (например, 16 бит на платформе) — все связанные инструкции имеют модификатор .W. Хотя иногда компилятор вставляет .L, к моему огромному разочарованию, так как 68000 всего лишь 16-битный. Хотя не по теме - есть идеи, почему это происходит?   -  person 3D Coder    schedule 29.09.2015
comment
Нет простите. Как я уже писал, размещайте всю актуальную информацию, а не только описание. Я не программировал 68000 на C, только на ассемблере и избегал DIV из соображений производительности, черт возьми. Проверьте параметры; возможно, это какой-то общий код 680x0 (у 68020+ был полный набор целочисленного деления, IIRC, так что это может просто связать соответствующую библиотеку)   -  person too honest for this site    schedule 29.09.2015
comment
@MichaelPetch: Хотя я не вижу какой-либо конкретной библиотеки в разделе компоновщика make-файла, это хороший совет, поскольку я проверял документы только по компилятору (а не по компоновщику, который сам по себе является отдельным двоичным файлом, и может быть больше подсказки по библиотеке времени выполнения). Что касается математической библиотеки, то для получения чисел с плавающей запятой мне приходилось связываться с mieee.lib, что приводило к проблемам, поэтому я переработал алгоритмы, чтобы использовать только целые числа.   -  person 3D Coder    schedule 29.09.2015
comment
Можете ли вы добавить пример кода C, который компилятор компилирует в вызов __ldivs вместо использования инструкции DIV, как вы ожидаете? Однако пытались ли вы привести операнд к uint16_t или int16_t, а также привести результат деления, чтобы «помочь» компилятору выбрать инструкцию DIV?   -  person Laurent H.    schedule 29.09.2015
comment
Опубликуйте параметры, которые вы передаете gcc для компиляции.   -  person too honest for this site    schedule 29.09.2015
comment
@MichaelPetch: Итак, есть библиотека времени выполнения в формате *.A. у него 8 КБ, и я вижу __ldivs в разделе заголовка текста. Теперь мне просто нужен дизассемблер 68k. Пойду погуглю, но если у вас есть предложения, я открыт :-)   -  person 3D Coder    schedule 29.09.2015
comment
@ Олаф Это не gcc. Это vbcc, но есть варианты: -k -c99 -O2 -c -o   -  person 3D Coder    schedule 29.09.2015
comment
@Laurent Этот компилятор не очень хорошо справляется с приведением типов - если вы это сделаете, он генерирует ужасное количество 68k инструкций. Я обнаружил, что быстрее всего просто убедиться, что вы не смешиваете и не сопоставляете различные типы, особенно опаленные и неподписанные вместе (если возможно, конечно = иногда вам нужны отрицательные числа).   -  person 3D Coder    schedule 29.09.2015
comment
В любом случае вам все еще не хватает минимально воспроизводимого примера.   -  person too honest for this site    schedule 30.09.2015
comment
@Olaf Ну, на данный момент мы уже знаем, что компилятор/компоновщик обрабатывает деление через библиотеку C времени выполнения (странно, поскольку инструкции по умножению прекрасно вставляются в ASM), поэтому примеры кода на самом деле не нужны, так как это не мой код это что-то делает. Я только что загрузил документацию по компоновщику и просматриваю ее, чтобы увидеть, возможно ли вообще настроить компоновщик, чтобы избежать больших затрат времени выполнения jsr/rts, которые в основном бросают каждое отдельное деление через барьер в 200 циклов - достаточно медленно, чтобы рассмотреть огромный LUT ...   -  person 3D Coder    schedule 30.09.2015
comment
Утверждения, содержащие что-то вроде того, что мы уже знаем, в большинстве случаев не соответствуют действительности. Мы нет; знаете, это только вы предполагаете. Но поскольку вы отказываетесь публиковать всю информацию, мне интересно, почему вы вообще спросили, поскольку вы, очевидно, уже знали ответ. Спасибо, что потратили наше время.   -  person too honest for this site    schedule 30.09.2015
comment
@Olaf Вау, помедленнее, турбо :-) Довольно много предположений, которые у тебя есть! Я понятия не имел, почему компилятор вставил вызов библиотеки C для чего-то, что должно быть 1 инструкцией DIV. Из вашего первоначального описания казалось, что вам нужно 3 отдельных примера кода, но теперь, когда я читаю ссылку, которую вы разместили, похоже, что одного достаточно. Если бы я знал это раньше, я бы тоже разместил код C - это в основном 1 строка: Slope1 = AbsX / Pairs;   -  person 3D Coder    schedule 30.09.2015
comment
@ 3DCoder vbcc не поддерживает встроенную сборку? Если это такой критический путь кода, то похоже, что это книжный сценарий для его использования (наряду с условной компиляцией, если вам нужно поддерживать разные архитектуры с одним и тем же кодом).   -  person Eli Algranti    schedule 30.09.2015
comment
l в __ldivs, кажется, означает long, s вместо signed. Каким-то образом компилятор убежден, что 16-битной версии недостаточно. Одна из возможностей состоит в том, что -32768/-1 переполняет divs, но стандарт C требует вернуть 32768, поэтому компилятор решает отказаться от divs.   -  person user3528438    schedule 30.09.2015
comment
@EliAlgranti Я еще не пробовал встроенный ассемблер под vbcc, но из документов кажется (конечно, я могу ошибаться), что он должен работать только с целыми методами. Сейчас я на 4-й рефакторинговой версии (изменение алгоритмов, подходов). Только самый быстрый из них будет написан на оптимизированном вручную ASM, поэтому пока необходимо использовать C — я думаю, вы согласитесь, что для быстрого высокоуровневого кодирования C действительно превосходит ASM.   -  person 3D Coder    schedule 30.09.2015
comment
@user3528438 user3528438 Верно. Вчера вечером, когда я просматривал шестнадцатеричный список C lib, я заметил несколько вариантов (со знаком/без знака), так что, несмотря на то, что я нигде не использую 32-бита в этом методе, и хотя приведение типов в vbcc очень медленно, я попытаюсь разыграть его, чтобы увидеть, если это что-то изменит. Обратите внимание, что это не просто одно деление в этом методе. Каждый отдельный раздел во всей программе (в других модулях) скомпилирован таким образом (всего их около 17).   -  person 3D Coder    schedule 30.09.2015
comment
Я создал 6 разных версий (со знаком/без знака char/short int/int) следующего тестового метода, и все они вызывают библиотечную функцию (jsr __ldivs): 'void tmpdiv1 () { unsigned short int a,b,c ; а = 100; б = 10; с = а/б; }' Интересно, что только версия без знака int называется __ldivu, остальные версии без знака (char, short int) по-прежнему называются __ldivs.   -  person 3D Coder    schedule 30.09.2015
comment
@3DCoder Независимо от того, какой тип вы используете, operator/ расширяет оба операнда как минимум до int/unsigned int, как того требует стандарт C. Так что похоже, что VBCC не удалось оптимизировать его до более узких типов.   -  person user3528438    schedule 01.10.2015


Ответы (2)


Из системы компиляции vbcc руководства Фолькера Бартельманна:

4.1 Дополнительные опции

This backend provides the following additional options:
  • -cpu=n Сгенерировать код для процессора (например, -cpu=68020), по умолчанию: 68000.
...

4.5 ЦП

The values of -cpu=n have those e ffects:
...
n>=68020
  • 32-битное умножение/деление/по модулю выполняется с помощью инструкций mul?.l, div?.l и div?l.l.

Исходный ЦП 68000 не поддерживал 32-битное деление, а только 16-битное деление, поэтому по умолчанию vbcc не генерирует 32-битные инструкции деления.

person Ross Ridge    schedule 29.09.2015
comment
Но оп обновил в комментарии, что он использует 16-битные входы. Однако при целочисленном продвижении все еще зависит от разумности/агрессивности оптимизации компилятора, используется ли 32-битная версия или 16-битная версия. ОП также упомянул в комментариях, что этот компилятор плохо справляется с кастингом, поэтому я подозреваю, что целочисленное продвижение заставляет компилятор использовать 32-битную версию в библиотеке времени выполнения. - person user3528438; 30.09.2015
comment
@user3528438 user3528438 Если int имеет ширину 32 бита, а не 16, то компилятор не может использовать 16-битную инструкцию деления из-за того, как 68k обрабатывает переполнение. Если результат слишком велик, чтобы уместиться в 16 бит, то инструкция деления оставляет операнд назначения неизменным. Если приведения используются для принудительного 16-битного деления, стандарт C по-прежнему требует, чтобы результат вычислялся так, как если бы использовалось 32-битное деление, а затем результат усекался до 16 бит. - person Ross Ridge; 30.09.2015
comment
Это правда. Однако, если и делимое, и делитель являются 16-битными или приводятся к ним, то любой приличный компилятор может определить диапазон и вместо этого использовать 16-битную версию. Однако один пограничный случай, -32768/-1, может быть трудно обработать. - person user3528438; 30.09.2015
comment
Я почти никогда не использую int, везде только short int (за исключением случаев, когда компилятор генерирует более быстрый код для 32-битных int (странно, но факт) — в чем легко убедиться, так как я постоянно запускаю тест — сборка/ Цикл развертывания/тестирования занимает менее минуты, поэтому я могу оценить каждое небольшое изменение). Как я упоминал выше, я закодировал 6 версий простой тестовой подпрограммы (с 6 различными типами, так что компилятор не вызывает двусмысленности), и все они используют библиотечный вызов __ldivs, что навело меня на мысль, что в этом компиляторе это невозможно. чтобы избежать 32-битного деления. - person 3D Coder; 30.09.2015
comment
@3DCoder Невозможно избежать этого, используя __ldivs. - person Ross Ridge; 30.09.2015
comment
@RossRidge Есть идеи, как заставить его использовать 16-битное деление для 16-битного делителя / делителя? Уровень оптимизации (L0 против L2) не имеет значения. Однако у меня есть еще один новый след. Я удалил библиотеку C из аргументов компоновщика, и единственной ошибкой компоновщика, о которой сообщалось, была, как вы, наверное, правильно догадались, '__ldivs'. Таким образом, компилятор заставляет это, а не компоновщик (который просто предоставляет код для __ldivs). - person 3D Coder; 30.09.2015
comment
@3DCoder Очевидно, что компилятор, а не компоновщик, выбирает, использовать ли вместо этого данную инструкцию ЦП или вызов библиотеки. Я не думал, что это вопрос. Если вы хотите, чтобы компилятор vbcc генерировал 16-битные инструкции деления, похоже, вам придется изменить исходный код компилятора самостоятельно: sun.hasenbraten.de/vasm/release/vasm.tar.gz - person Ross Ridge; 30.09.2015
comment
Это не тот ответ, на который я надеялся, но, по крайней мере, я знаю, что это невозможно, потому что я не считаю «вариант» переписывания компилятора фактическим вариантом в качестве альтернативы. Но очень важно понимать, что я достиг пределов компилятора vbcc (итак, пришло время попытаться настроить формат объекта gcc с помощью компоновщика платформы), и это не просто вопрос его настройки, поэтому я собираюсь принять это как ответ. Большое спасибо за ваш вклад. - person 3D Coder; 04.10.2015

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

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

Тогда вы уже воюете с ветряными мельницами. Выбор малоизвестного компилятора C и в то же время стремление к максимальной производительности — противоречивые цели.

Если вам действительно нужна совместимость с кодом MC68000, выбор C сомнителен. Поскольку у 68000 нет кэша, оргии хранения/загрузки, которые простые компиляторы C обычно производят в массовом порядке, оказывают огромное влияние на производительность. Он значительно уменьшается для более высоких членов и может стать невидимым для суперскалярных конвейерных (эмм, один; 68060).

Переключитесь на модель кода 68020, если позволяет целевая платформа, и переключите компилятор, если вас не устраивает текущий.

person Durandal    schedule 01.10.2015
comment
Компилятор я точно не выбирал, просто он был предустановлен во всей платформе. В прошлом я пытался заставить gcc работать, и пока у меня работала часть компиляции, я столкнулся с проблемами компоновщика (отсутствуют библиотеки платформы в формате, совместимом с gcc). Но, похоже, мне скоро придется сменить компилятор. Можете ли вы порекомендовать какой-нибудь проверенный, хороший компилятор 68000 C? - person 3D Coder; 01.10.2015
comment
Что касается платформы, то 68000 фиксированная, так как у HW именно такая. Так что о 68020, к сожалению, не может быть и речи. - person 3D Coder; 01.10.2015
comment
Что касается противоречивых целей, то в этом собственно и весь смысл — со временем этот C-код будет портирован на ASM, но разработка на C запросто на порядок продуктивнее (для отладки), чем чистый ASM. - person 3D Coder; 01.10.2015
comment
@ 3DCoder Если вы создаете прототип для последующей ручной оптимизации, то зачем вообще беспокоиться об отсутствии оптимизации у компиляторов? Любые усилия, затраченные на производительность C сейчас, в любом случае пойдут впустую? Я не в курсе, какие компиляторы «хорошие», прошло почти два десятилетия с тех пор, как умерла моя последняя 68-тысячная машина. - person Durandal; 02.10.2015
comment
Это потому, что оптимизированный вручную ASM будет написан не на 68k, а на другом ASM. Платформа HW имеет дополнительные фишки. Это в основном эксперимент, как далеко вы можете зайти с C на 68k. Созданная демонстрация будет служить эталоном того, что возможно с использованием C на данной платформе, поэтому производительность очень важна. Я прошел несколько сеансов рефакторинга, чтобы достичь 60 кадров в секунду, и эта конкретная область с разделением замедляет работу. Я компенсировал это оптимизацией в разных компонентах, но все же предпочел бы иметь возможность использовать только div. По крайней мере, я знаю, что происходит, - person 3D Coder; 02.10.2015