0.00
Рейтинг
6.44
Сила
в том, что ты на ровном месте потерял до половины нумерации для инструкций
у тебя сейчас возможно лишь 16 различных instr, а могло быть 32-(x<16)
а я пояснил, что тратить целый бит опкода на то не нужно
во всех случаях «существенного отличия» экономнее использовать другой instr
Заполнение Y реально может быть не просто ненужным, но и времязатратным процессом.
вроде как [DST] читать не нужно только для load, что определяется по опкоду (лучше нулевому) и без TI
и второй раз в операциях типа [DST=SRC],[SRC=DST] — ну так там уже прочитано в первый раз

Я сильно над этим не задумывался еще, но т.к. есть 16 однооперандных инструкций (и они никак не обязаны быть теми же что и 16 двухоперандных), то возможно там будет и dec/inc-1/2/3/4 и возможно что-то еще.
лично я между любым кол-вом дополнительных инкрементов и обменом всегда выберу обмен
уже только ради одного обмена со стековым указателем, даже если больше не понадобится никак 8)
Если TI=1, то общая схема инструкции следующая:
1. SRC загружается в X
2. DST загружается в Y
это можно делать одновременно, и TI не нужен
если не понадобится Y, так не понадобится

Так и есть — это пожалуй единственная «бесполезная» комбинация аргументов которая осталась и действительно сделать её каким то особым случаем выглядит привлекательно.
Но лично мне не нравится, что ломается общая схема работы Simpleton-а.
почему ломается? считай просто, что схема общая у тебя такая:
1) может быть, записать PC в стек
2) DST ?= SRC
и нет проблем :D

Ну зависит от задачи. Например, если первый элемент нам подходит — переходим к его хвосту, а если нет — пропускаем до следующего элемента.
это только если по первому слову ясно (кстати, у тебя какой порядок слов-байтов? little/big endian?)
но если нужно элемент проверить целиком и условно пропустить следующий, то inc1+inc2 ничем не лучше add3
и кстати, на z80 очень огорчает отсутствие операций ex sp,rr
из-за этого двухстековые схемы и шитый код намного реже применимы, чем могло быть
Главное откуда оно возникло — это минимизация и ускорение реализации CALL,
Кстати, лучшим вариантом именно минимизации с ускорением может быть отдать под однокомандный call в принципе небессмысленный, но на практике вряд ли нужный случай «op [PC],src» — то есть dst=PC всегда прямая адресация, а ID=1 в этом случае будет означать «перед выполнением сохранить PC в стек». Подумай, так ли тебе нужно писать что-то в следующий опкод.

помимо этого может быть применён для, допустим, быстрой адресации переменных близких к вершине стека
переменные нормально надо располагать, и не понадобятся лишние инкременты :D
(а еще лучше адресацию [R+imm], но она не лезет в такую схему)

может быть полезен при итерировании по массивам с таким размером ячейки и тому подобное.
ИТЕРИРОВАНИЕ подразумевает использование каждого элемента, то есть последовательный доступ ко всем его частям, то есть одинарный инкремент :P

также не совсем понимаю смысл необходимости флага TI — почему бы всегда не производить копирование в X,Y?
ну, в одном хотя бы смог убедить :) тем не менее…

Не стоит того чтобы из-за этого ломать систему команд.
почему «ломать»? обобщить!

Даже в ЯВУ swap как правило записывается проброской данного через tmp,
что крайне бесит, так же как отсутствие циклических сдвигов

ну пробросим через регистр, несущественно
это инкремент на 2 несущественно, а нерациональный расход регистра — существенно

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

Как и inc1 это экономия на imm в ряде случаев когда это часто нужно.

inc2 лично мне приятно, экономит код, данные и скорость в массе случаев
в какой массе? перечисли несколько хотя бы разумных случаев? вот как раз на 8-битках иногда могло еще быть полезно, потому что основные типы данных разных размеров, но здесь-то одинаковые они! притом польза, даже если где-то она и будет, не «в два раза», а всего-то навсего в (N+1)/N от всех циклов доступа в итерации
Когда load [PC] (на одном операнде X рассмотрим) отрабатывает он сперва в X грузит PC, а уже потом из-за бита indirect замещает X на [X]. Это совсем не то же самое что сперва загрузить в X [PC++], а потом заменить X на [X].
что совсем не повод так бездарно тратить номер регистра
load imm = load [pc++]
load [imm] = load [[pc++]]
второй случай можно закодировать через номер регистра флагов
(потому что, ну кому и зачем мб нужен косвенный доступ через флаги))

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

Регистров на самом деле хватает чтобы сделать memmove/memcopy полностью на регистрах, а это я считаю эталонным кодом для проверки на нехватку регистров.
а я считаю это разновидностью подхода «и так сойдёт» :P

Такую оптимизацию можно проделать в существующей системе команд и без swap:
; вызов процедуры
R3 =+2 PC; адрес возврата (inc2) (команда без immediate)
PC = proc_addr; вызов процедуры
; возврат из процедуры
PC = R3
нет! это совершенно не то же самое! например:
load R3,adr1
(вычисления)
(условный переход)
load R3,adr2
(вычисления)
swap PC,R3

Чем же он уродлив?
тем, что повторяет функцию универсального сложения с любой константой
собс-но, даже инкремент на 1 — пережиток неортогональных восьмибитных процов
(но он хотя бы нужен бывает часто, и его наличие мб оправданным)
у обмена же гораздо шире функционал

В эти годы уже просто для поддержки CP/M могли целый процессор Z80 засадить в какой нибудь Commodore XXL (не помню точно модели) — какая уж тут гонка за примитивизмом?
засадить могли, а в нормальную производительность z80 не шмогли
и это тормозное в cp/m режиме угрёбище справедливо было непопулярно
тем более, что и стоило вдвое дороже c64 того же года

Я уже говорил — команда типа SWAP BYTES внутри регистра (опять таки с логикой Y = swap bytes of X) делает такой сценарий маловероятным. Ну и вообще соединять комп с устройством которое плюётся данными быстрее чем или даже соизмеримо чем скорость с которой процессор отрабатывает memfill — это сомнительно и вряд ли такое вообще есть/было на практике.
на практике поддерживали 8 и 16 бит девайсы одновременно очень недешёвые песюки
причём в них не было полного отказа от 8 бит
Immediate сам может быть тоже indirect и таким образом операции можно проводить непосредственно над памятью не загрязняя регистры. С чтением через PC так уже не получится
это почему еще? сам же пишешь:
значение в X замещается значением ячейки памяти по адресу X
то есть load [PC],[PC] это X=[PC++]; Y=[PC++]; X=[X]; [Y]=X
что эквивалентно load [imm1],[imm2]
Т.к. регистров действительно немного,
вооот, в том числе еще поэтому нужен swap, а у тебя и регистров меньше, и свопа нет
а в самом обобщённом случае Link Register таки нужно пихать в стек,
только частных случаев очень много и эффект заметный от ускорения
плюс содержимое линк-регистра может служить указателем на данные процедуры
(после обработки данных с инкрементом получается корректный адрес возврата)
то делать так всегда имхо проще для системы команд
а для «компа мечты» должно быть эффективней и удобнее, а не «проще»
В ней есть только одна операция X ?= Y с лёгкими вариациями. Swap уже не пролазит и не знаю как его протащить без вреда для внутренней красоты.
ну, уродливый inc2 протащил же :)
Только до тех лет когда начали делать 128Кб-ные машины.
с чего такой вывод? это просто посадить на ту же шину больше микросхем
а не разрабатывать весь микропроцессорный комплект, а не только проц
Да ну, не вижу ни трудностей ни тем более невозможностей.
например, девайс подкидывает байты высоким темпом, нужно успевать выгребать и складывать их, а складывать ты можешь только словами; будешь выделять блок вдвое больше, а потом корячиться с утаптыванием? + удорожание в любом случае
Вот можно было бы и послушать, если есть конкретные образы и идеи. :)
пока некогда :)
Зря лишил себя одного регистра из-за непосредственного операнда, всё равно его читаешь через PC, вот и кодируй (с индиректом) тоже через PC. И зачем адрес возврата обязательно пихать в память? В рисках, например, он пишется в (обычно специально выделенный) регистр, это дело вызываемой процедуры, сохранять в памяти его или нет. Можно сделать и через РОН, тут тебе пригодилась бы команда обмена, то есть вызов процедуры выглядит так load R,adr + swap PC,R и возврат load/swap PC,R (если обошёлся без стека).

Отказ полный от 8 бит может выглядеть восхитительно удачным только сегодня. Для 80-х все шины ширины 16 (и все вспомогательные микрухи!) в домашней машине дороговато, плюс доступную восьмибитную периферию трудно или невозможно использовать. И по мне, тогда уж лучше Форт-процессор на них сажать. Это уже был бы компик моей мечты))
Для образовательных целей объективно лучше подходил Лого, который, собственно, и был для этого разработан. Но почему-то воспринимался как игрушка для самых маленьких, хотя на деле был куда удобнее, выразительнее, мощнее и ближе к нормальному языку, чем любой бейсик. Вот такая несправедливость.
Тащемта все бейсики тех времён разной степени паршивости ерундень. Теоретически можно было упихать в 16k нормальный структурный интерпретатор, без номеров строк, с независимыми процедурами, локальными переменными итд. Но инерция и цейтнот у наёмных разработчиков не позволили.
win10home и смотрю, в разных браузерах по-разному
где-то ничего (ни промежутка даже) на месте прямоугольников
вероятно, так бы выглядеть и должно, но откуда взялся мусор невидимый
а что за такая кодировка у вас на сайте? тут и там пустые прямоугольники неотображаемых символов
в 2 раза не выйдет, и не мечтай)) даже в самом удобном буфере, без учёта времени переброски, без ограничений на размер кода, с рисованием set и одновременно с двух концов, с экономией проверки после ступеньки, без учёта дополнительных расходов на цикл и хвост — теоретический предел 23+ такта на пиксель (для вертикалей)
если так, то у меня сейчас (лучший случай/худший случай/среднее)
467/610/538; 774/1013/893; 1221/1609/1415
но средневзвешенное дб поменьше среднего, особенно для линий короче 9 точек
так как самый худший случай (и близкие) статистически довольно редки

также думаю поменять местами ветки на входе
не ускорит, так хоть сузит разброс немного
протестирую и выложу исходники после этого
И еще. Как уже говорил на форуме, если сцена сложная, из большого кол-ва коротких линий, и в 25-50 fps заведомо не уложится, может оказаться выгоднее рисовать в буфере с удобной раскладкой и стеком перебрасывать на экран, что в итоге может получиться быстрее и по памяти примерно столько же вместе с буфером (и даже меньше, если вычесть второй экран)
Ну хз-хз, может быть, такой задачи там и не ставили, но в двух других примерах от call до постановки первой точки проходит ~400 и ~490 тактов, у меня в среднем ~330 (и это не старался еще особенно). Сам алон упоминал как рекорд около 270 емнип, но там, вероятно, цикл намного проще и медленней.
Где ты там увидел 16k?? Чуть больше восьми, если точно — 8635 байт на саму процедуру линии (и даже вместе с демо-кодом нет и 9k). Из них вход 169 байт и 2k заняли таблицы, которые все можно сократить на четверть за счёт небольшого замедления входа, а на освободившееся место распихать рисующие куски. То есть можно в 8k утоптать вполне. И нет, размер не мог удвоиться хотя бы потому, что ветка без ступенек короче, а еще для хвоста часть кода можно объединить.
нет, ldi-ldi-ldi