Войти
ФлеймФорумЖелезо

Блеск и нищета 8/16-битных консолей и ПК (21 стр)

Страницы: 120 21 22 2346 Следующая »
#300
22:37, 2 июня 2018

=A=L=X=
> Scorpion ZX 256 - прям в точку на эту тему.
У нас копировали все, кто пытался хоть что-то ваять сам. У меня на Балтике было. Причём озу было 512к


#301
(Правка: 5:14) 5:13, 3 июня 2018

Вообще несколько обидно от того какой разброд пошёл после архитектуры ZX Spectrum 128, которая управляется портом $77FD
Официальный ZX Spectrum +3 умудрился дойти до такого, что через его порт $1FFD управление дополнительными банками ПЗУ требовало обязательно записи в него для переключения между банками ПЗУ Basic 128 и Basic 48 - этим чудакам даже пришлось переписать процедуру переключения банков по адресу $5B00, ибо иначе никак. То есть ломалась совместимость как будто намеренно, вместо расширения порт 1FFD вёл себя как обязалово.
У тех же пентагонов и скорпионов тоже радикально отличаются подходы к менеджменту дополнительных банков памяти свыше 128Кб.
В общем когда пытаешься выйти за рамки ZX Spectrum 128, то уже приходится выбирать конкретную архитектуру под что пишешь без совместимостей с остальным зоопарком.

#302
(Правка: 23 июня 2018, 7:06) 12:36, 6 июня 2018

Почитав поподробнее про первую популярную портативную консоль от Nintendo - Game Boy я с удивлением обнаружил, что процессором в нём служил не клон Zilog Z80 (полностью совместимый с Intel 8080) и даже не "совместимый с Z80" чип, как иногда можно прочитать в разных местах (и как я сам иногда писал), а довольно таки своеобразный зверёк - Sharp LR35902. В английской вики можно найти утверждения, что он является смесью Intel 8080 и Z80, но это тоже правда лишь отчасти. Судя по всему Sharp LR35902 был продуктом вдумчивой переработки микросхемы Z80 с участием инженеров как Nintendo так и Sharp, чтобы получить 8-битный процессор идеальный в их представлении для портативной консоли. Явно преследовались цели простоты и энергоэффективности - вещи критически важные для машины, работающей от батареек. Основная часть произведенных над Sharp LR35902 работ являлась отрезанием сложного и ненужного, но так же взамен были предложены некоторые простые, но эффективные вещи.

Итак, по системе команд LR35902 старается как можно больше унаследовать от Intel 8080 и Z80, но в процессе упрощения были ликвидированы флаг P (parity/чётность или overflow/переполнение), флаг S (sign/знак) и, поэтому, половина команд условного выполнения (условия P, M, PO и PE). В результате в системе команд остались только условия Z, NZ, C, NC, то есть условные вещи (а в i8080 это JP, CALL и RET) стали возможны только по флагу нуля и переноса. Кроме того под нож из i8080 пошли порты ввода-вывода.
В результате в LR35902 освободилось много кодов инструкций из которых следующие так и остались незанятыми (все мнемоники здесь и далее берутся как в Z80):

D3  out (*), a
DB  in a, (*)
E3  ex (sp), hl
EB  ex de, hl
E4  call po, **
EC  call pe, **
F4  call p, **
FC  call m, **
То есть эти инструкции из i8080 в Sharp LR35902 отсутствуют.
От Z80 осталось еще меньше - команды относительного перехода JR, да перфикс битовых операций CB (о нём ниже). Ни регистры IX, IY, ни дополнительные команды наподобие LDIR и расширенной 16-битной арифметики в LR35902 не попали.
Так что по сравнению с Z80 и не используются еще коды DD, ED и FD.
Более того, некоторые из команд Z80 введённых в нём по сравнению с i8080 некоторые поменяли своё назначение:
Код     Было            Стало
------------------------------------
08      ex af, af'      ld (a16), sp
10      djnz *          stop 0
D9      exx             reti
RETI - это RET + EI, то есть возврат из процедуры с одновременным разрешением маскируемых прерываний.
STOP вероятно стопорит как то иначе нежели HALT.
Но кроме вышеперечисленных кодов осталось еще немало других с зарезанными флагами, их в результате начали использовать по другому (то есть это переиначенные коды команд еще из i8080):
Код     Было            Стало
------------------------------------
E0      ret po          ldh (a8), a
F0      ret p           ldh a, (a8)
E2      jp po, **       ld (c), a
F2      jp p, **        ld a, (c)
E8      ret pe          add sp, r8
F8      ret m           ld hl, sp+r8
EA      jp pe, **       ld (a16), a
FA      jp m, **        ld a, (a16)
И вот эти новые команды и интересны. Еще в Famicom/Денди (а скорее всего и ранее) Nintendo маппило порты ввода-вывода в память, поэтому и избавилось от специализированных команд ввода-вывода. Но вместо них были добавлены новые - работающие с основной памятью особым образом. Команды LDH можно еще записать иначе, чтобы понять лучше их сущность:
LDH (A8), A = LD ($FF00+A8), A
LD (C), A = LD ($FF00+C), A
То есть эти команды записывают (или считывают) аккумулятор в верхние 256 байт памяти 64Кб-ого адресного пространства ЦП по непосредственному смещению или косвенно по регистру C. Забавно, но это очень похоже на zero-page из семейства процессоров MOS 6502, клоны которых и стояли в Famicom, но только со спецификой 8080 - теперь это можно назвать FF-page, так как в нулевая страница у 8080 занята под точки входа в прерывания.
И действительно у Game Boy верхние 256 байт памяти поделены на две почти равных зоны по 128 байт между портами ввода-вывода и служебным ОЗУ, которое может быть использовано таким образом для хранения быстрых переменных.
Следующие две инструкции - ADD SP, R8 и LD HL, SP+R8 позволяют прибавить к SP байт со знаком или загрузить в HL сумму SP с байтом со знаком - это явно инструкции для поддержки локальных переменных на стеке. Без индексных регистров IX и IY от Z80 адресовать стек в стиле ЯВУ стало трудно, но эти две команды помогают это сделать - выправлять кадр стека с помощью первой и помещать в HL адрес переменной рядом с вершиной стека, а косвенные загрузки по HL в 8080 уже есть.

Любопытны так же две последние инструкции из таблицы выше - дело в том, что они уже были в i8080, но с другими кодами. Оказался переделан еще один кусок кодов i8080:

Код     Было            Стало
------------------------------------
22      ld (**), hl     ld (hl+), a
2A      ld hl, (**)     ld a, (hl+)
32      ld (**), a      ld (hl-), a
3A      ld a, (**)      ld a, (hl-)
То есть инструкции 32 и 3A переехали жить в EA и FA, а вместо них и загрузки HL из адреса стали жить загрузки/сохранения аккумулятора по адресу HL с постинкрементами и постдекрементами. Видимо это упрощало декодер.
От Z80 выжил полностью доп-код CB - большое множество битовых операций над всеми 8-битными регистрами процессора.
Однако он не только выжил, но и слегка обогатился - в оригинале коды в диапазоне CB30-CB37 были недокументированными, в Sharp LR35902 же в этих кодах разместили инструкцию SWAP r, которая обменивает у указанного 8-битного регистра верхнюю и нижнюю квадру бит.

Вот такой мутантик получился из Z80 и i8080 в руках Nintendo.
Полностью таблицу его оп-кодов любопытствующим можно посмотреть здесь: http://www.pastraiser.com/cpu/gameboy/gameboy_opcodes.html
А чтобы было с чем сравнивать - вот таблицы оп-кодов Z80: http://clrhome.org/table/

#303
12:54, 6 июня 2018

=A=L=X=
> Это был процессор  Sharp LR35902, который являлся дикой смесью из Intel 8080 и
> Z80 с собственными блекджеками.
> Во первых - он был почти совместим по системе команд с Intel 8080. Однако
> некоторые вещи даже из i8080 пошли под нож.

Интересно, это они из любви к прекрасному или просто пытались удешевить чип ?

#304
12:59, 6 июня 2018

0iStalker
> Интересно, это они из любви к прекрасному или просто пытались удешевить чип ?

Game Boy должен был как можно дольше работать от батареи, поэтому наверное тут больше попытка сделать всё сердито для энергоэффективности.

#305
(Правка: 6:35) 6:33, 19 июня 2018

В процессе пописывания данных статей немного познакомился с энтузиастом, который пишет на TS Config.
TS Config - это конфигурация для компьютера-конструктора ZX Evolution, разработанная TS-Labs.
В базисе совместима с Pentagon 512, но еще куча фарша добавлено.

Так вот, он совсем недавно портировал Соника Супер-Ёжика с 8-битной Sega Master System на этот самый TS Config, подробнее о приключениях в процессе можно почитать тут: http://hype.retroscene.org/blog/822.html
P.S.
А вот здесь сам бинарь и ссылка на эмулятор: http://hype.retroscene.org/blog/games/821.html#cut

#306
(Правка: 26 июня 2018, 8:02) 13:46, 25 июня 2018

Немного обновил и переупорядочил выше текст про Sharp LR35902 и задумался - вот выкинули из него (по сравнению с i8080 и Z80) флаги S (знака) и P (чётности/знакового переполнения) - а насколько эти флаги были востребованы?
Оказалось, что в общем то действительно не особо.
Во первых - все условные переходы в Z80 работали исключительно по содержимому одного только флага. Если с Z/NZ и C/NC всё довольно логично, нужно и уместно, то для сравнения чисел со знаком этого уже сильно не хватает. Ну во первых знак, то есть самый верхний бит, можно протестировать двухбайтовой командой BIT 7, A, где установится флаг Z, а можно и однобайтовой RLCA с разрушением правда аккумулятора, но 7-ой бит ляжет во флаг C. Так или иначе для проверки чисел со знаком на больше-меньше нужно тестировать сразу и бит знака и бит знакового переполнения.
Например, в 8086 условный переход JGE (Greater or equal) осуществляется когда SF = OF, а условный переход JL (Less) когда SF <> OF, где SF и OF это флаги знака и знакового переполнения.
В Z80 таких "комбинированных" команд сравнивающих флаги просто не было - флаги тестировались по одному и надо было выстраивать цепочки переходов, чтобы отсекать нужные условия. В общем сравнения чисел со знаком становились геморроем - и это действительно в одном кросс-компиляторе Си под Z80 упоминается в заметках про оптимизацию.
Кроме учета знакового переполнения в арифметических команда флаг P в Z80 в логических командах выступал как флаг чётности (parity) - хранил чётное или нечетное в результате было число единичных бит.
Вот это применение флага еще более интересно.
В 8086 этот флаг даже не пытались совмещать, а сделали прямо отдельным флагом PF, который до сих пор, даже в AMD64 хранит чётное или нечётное число единичных бит содержится в самом нижнем байте результата. Заметьте, что учитывается только нижний байт, даже если регистр 64-битный.
На деле этот флаг уже давным давно потерял какую либо актуальность. Тестирование байта на чётность количества единичных бит было крайне распространённой техникой детектирования ошибок в телекоммуникационных линиях когда то. Да и сейчас встречается. Но когда то ради удешевления периферии дошли до того, что этот контроль чётности снимали с самих коммуникационных портов и возлагали на центральный процессор. Операция несложно реализовывалась на транзисторах, но имитация её другими командами процессора вовлекала длинные циклы и создатели процессоров сознательно шли на включение такого флага в систему команд ради гипотетического быстрого контроля некой коммуникационной линии. Z80 поступил еще довольно разумно совместив этого флаг и флаг знакового переполнения в одном, но в 8086 сия древность занимает свой личный бит в регистре флагов с самого начала и видимо навсегда.
Забавно, что некий программист всяких сетевых штук Wolfgang Kern пишет, что пользовался переходом по флагу PF на i386 всего два раза за всю жизнь - как раз в драйвере COM-порта и в каком то очень старом 8-битном вычислении. При этом он утверждает, что кодобаза по которой он вёл поиск занимает ажно 14 Гб. пруф

#307
20:09, 25 июня 2018

=A=L=X=
P вообще самый бесполезный флаг был. Через него детектился режим IFF2. Но я честно говоря не сталкивался с необходимостью это как-то делать. Это скорее востребовано в коде обслуживания Magic button.

#308
(Правка: 8:04) 3:51, 26 июня 2018

Dexus

В Z80 флаг P был вообще многофункциональным. При арифметических командах он выступал в роли знакового переполнения (oVerflow), при логических - в роли собственно чётности (Parity), но так же еще строковые команды типа CPI и LDI заполняют его чтобы сигнализировать об обнулении счётчика BC, что может быть полезно тоже. Про детекцию режима IFF2 даже не знаю.
Поэтому в принципе в Z80 он мог быть полезен и кроме функционала проверки чётности единичных бит. Однако пока я писал текст выше я сам забыл об истории вопроса. А ведь 8080 являлся идеологическим потомком 8008, а 8008 проектировался для того чтобы стать микропроцессором в терминале Datapoint 2200, а терминалы по природе своей обязаны решать задачу пересылки данных по линии связи с сервером. Поэтому parity-бит и был внедрён прямо в архитектуру процессора, а далее понятно, что Intel протащило его через 8080, 8086 и вплоть до современных процессоров. Если взять лагерь конкурентов - семейство Motorola/MOS, то там никакого parity отродясь не было.
А если взять ARM, то там флагов вообще ровно четыре - Z (ноль), C (перенос), V (overflow) и S (sign) - компактная четвёрка, решающая сейчас все адекватные задачи на проверки переполнений и сравнений как знаковых так и беззнаковых.

#309
(Правка: 3:35) 3:35, 27 июня 2018

Как то так получилось, что я никогда не видел алгоритм целочисленного деления (на асме, разумеется, ибо на ЯВУ он и не нужен).
Вот умножение - и сам делал и другие реализации видел, а деление всегда оставалось за кадром. И в связи с тезисами, что оно в железе заметно тормознее умножения я так же думал, что алгоритм должен быть зубодробительным. Это убеждение подпитывалось даже гуглом, в котором если искать вещи типа "быстрое деление на Z80", то начинает вываливаться какая то неточная аппроксимация, отсылки к томику Кнута с какими то оценочными аналитиками, проблемы непростого масштабирования на произвольное число разрядов и т.п.
Вчера же случайно наткнулся на набор математических функций для Z80 и смотрю - вот оно, целочисленное деление байт. Ассемблер может выглядеть довольно cryptic, особенно когда результат прямо в аргументе прокруткой формируют, но смотрю и точно понимаю, что алгоритм должен легко масштабироваться и он совсем небольшой - не больше умножения. Начинаю всматриваться дальше и понимаю, что это банальное деление столбиком, причем как и умножение оно в двоичной системе сильно упрощается по природе своей. Хахаха, а вся сложность по сравнению с умножением заключается в невозможности распараллелить на независимые шаги со слиянием результата. Как грица myth busted.

#310
6:22, 27 июня 2018

Dexus
> P вообще самый бесполезный флаг был.
Стoп! Так-с…
Зря я этот флаг, значит, у себя в x80 поддерживаю?
Хотя без него «SKIP/LOOP/WAIT»-режимы не реализуешь…
(Не выделять же под них отдельный регистр!)

P.S.: Никогда не задумывался «о рудиментарности» флага паритета…
Да и в политике «паритет» частенько звучит…

#311
(Правка: 6:37) 6:36, 27 июня 2018

=A=L=X=
> Как грица myth busted.
Поразрядные алгоритмы (их, кстати, дохрена: деление, корень, логарифм, тригонометрия)  — это вариант исключительно для ущербных микроконтоллеров.
Они имеют смысл исключительно при отсутствии хардварного умножения. С умножением полиномиальные аппроксимации и итерационные методы заруливают все.

#312
(Правка: 7:07) 6:50, 27 июня 2018

}:+()___ [Smile]
У тебя есть некий полиномиальный алгоритм бинарного умножения, с количесивом итераций меньше количества бит операндов?? Что-то ты сформулировал свой тезис как-то невнятно, насчёт ущербности.

#313
7:12, 27 июня 2018

Alikberov
> Зря я этот флаг, значит, у себя в x80 поддерживаю?

Если стояла цель совместимости с 8086 то не зря конечно.

#314
(Правка: 8:12) 8:10, 27 июня 2018

}:+()___ [Smile]
> Они имеют смысл исключительно при отсутствии хардварного умножения.

Лет 10 уже назад читал и тестировал (оказалось правдой), что на FPU x86 эпохи всяких пентиумов 2 или 3 деление работало почти так же быстро как умножение, потому что работает оно там через reciprocal+mul (то есть быстрая полиноминальная 1/x + умножение на результат y). Но при этом целочисленное умножение этому трюку не поддавалось и работало медленнее всех арифметических операций, включая вещественные.
P.S.
Хотя это не исключает, что целочисленное деление всё равно как то наскипидарено, но забавно как раз в том, что его целочисленность путалась под ногами даже тогда.

Страницы: 120 21 22 2346 Следующая »
ФлеймФорумЖелезо