FromNet: NET_Moscow_Russia_(245_02/09/2005) (commserv.rpb.ru)

Здравствуй(-те), All...!

=== Cut ===
boo_boo

письмо пришло от Мартина Корта, автора nocash-евской доки и
эмуляторов, кроме спасибов и прочего, с указаниями на пару
неточностей/неясностей в тексте. посему -- пофикшенная версия.
=== Cut ===


=== Cut ===
MEMPTR, эзотерический регистр ZiLOG Z80.

Как известно, после выполнения инструкции BIT n,(HL) в 3 и 5 битах флагового регистра оказывается некое нечто, о котором в фирменных руководствах не сказано ни слова. Hа самом деле это -- 11й и 13й биты внутренней регистровой пары Z80, которая используется для операций с 16и-битными значениями, чаще всего -- адресами (обычная практика для процессоров с 8и-битной шиной данных, оперирующих 16и-битными данными). Как и зачем два бита этого регистра оказались во флагах, неясно, однако же, оказались. Упоминания об этом явлении можно встретить в "z80 undocumented documented" Шона Янга (http://www.myquest.nl/z80undocumented/), и, в несколько большем объеме, в описании Z80 из проекта "nocash" (http://www.work.de/nocash/zxdocs.htm), где эта регистровая пара и названа MEMPTR. К сожалению, до недавнего времени, попытки по состоянию двух бит разобраться, какие конкретные значения выставляются в MEMPTR некоторыми инструкциями процессора, были не слишком успешны.
Hо свершилось чудо. В результате множества экспериментов (основанных на предпосылке, что инструкции с индексной адресацией инициализируют MEMPTR соотвутствующим адресом), а также глубоких медитаций над результатами, нам удалось выяснить, что инструкция CPI увеличивает текущее значение MEMPTR на 1, а CPD текущее значение на 1 уменьшает. Таким образом, циклически декрементируя MEMPTR, и отслеживая заём из старших разрядов по двум известным битам, можно однозначно определить 14 младших бит MEMPTR, а имея их на руках -- сказать наверняка, по какому принципу выставляются значения. Далее -- список операций, влияющих на MEMPTR, с формулами для его содержимого. Здесь rp обозначает регистровую пару (16 бит), а INDEX - регистровые пары IX или IY. Операции, в этом списке отсутствующие, на MEMPTR, насколько известно, не влияют. Все процессора, на которых проводились испытания, дали одинаковые разультаты, за исключением КР1858ВМ1 и Т34ВМ1, которые будем обозначать "*BM1".

================================================== =============================
MEMPTR = addr + 1

MEMPTR_low = (addr + 1) & #FF, MEMPTR_hi = A
для *BM1: MEMPTR_low = (addr + 1) & #FF, MEMPTR_hi = 0

MEMPTR = rp + 1

MEMPTR_low = (rp + 1) & #FF, MEMPTR_hi = A
для *BM1: MEMPTR_low = (rp + 1) & #FF, MEMPTR_hi = 0

MEMPTR = addr + 1

MEMPTR = значение rp после операции

ADD/ADC/SBC rp1,rp2
MEMPTR = rp1_до_операции + 1

RLD/RRD
MEMPTR = HL + 1

JR/DJNZ/RET/RETI/RETN/RST (только при переходе по addr. то есть, в случае условных JR/RET при невыполненном условии, или DJNZ когда B_после_декремента == 0, MEMPTR не меняется)
MEMPTR = addr

JP(кроме JP rp)/CALL addr (в случае условного перехода -- независимо от удовлетворения условию)
MEMPTR = addr

MEMPTR = (A_до_операции '' 8) + port + 1

MEMPTR = BC + 1

MEMPTR_low = (port + 1) & #FF, MEMPTR_hi = A
для *BM1: MEMPTR_low = (port + 1) & #FF, MEMPTR_hi = 0

MEMPTR = BC + 1

LDIR/LDDR
при BC '' 1: MEMPTR = адрес_инструкции + 1
при BC = 1 не влияет

CPI
MEMPTR = MEMPTR + 1

CPD
MEMPTR = MEMPTR - 1

CPIR
при BC=1 или A=(HL): как CPI
в остальных случаях на каждом шаге MEMPTR = адрес_инструкции + 1
* поскольку на последнем шаге BC=1 или A=(HL), в итоге MEMPTR = адрес_инструкции + 1 + 1
(если перед этим не было прерывания)

CPDR
при BC=1 или A=(HL): как CPD
в остальных случаях на каждом шаге MEMPTR = адрес_инструкции + 1
* поскольку на последнем шаге BC=1 или A=(HL), в итоге MEMPTR = адрес_инструкции + 1 - 1
(если перед этим не было прерывания)

INI
MEMPTR = BC_до_декремента_B + 1

IND
MEMPTR = BC_до_декремента_B - 1

INIR
как INI на каждом шаге. то есть, в итоге MEMPTR = ((1 '' 8) + C) + 1

INDR
как IND на каждом шаге. то есть, в итоге MEMPTR = ((1 '' 8) + C) - 1

OUTI
MEMPTR = BC_после_декремента_B + 1

OUTD
MEMPTR = BC_после_декремента_B - 1

OTIR
как OUTI на каждом шаге. то есть, в итоге MEMPTR = C + 1

OTDR
как OUTD на каждом шаге. то есть, в итоге MEMPTR = C - 1

любая инструкция с (INDEX+d):
MEMPTR = INDEX+d

переход по прерыванию на addr:
как при обычном CALL. то есть, MEMPTR = addr

================================================== =============================
Какая же польза нам от этого Тайного Знания? Hу, во-первых, теперь возможно написание эмуляторов Z80, поддерживающих _все_ недокументированные особенности cpu. Во-вторых, то, что на некоторых клонах Z80 MEMPTR ведет себя слегка иначе, добавляет еще один метод в копилку способов автоопределения модели процессора. По-моему, уже немало! :)

(c)2006, zx.pk.ru
теоретическая часть: boo_boo, Vladimir Kladov
натурные испытания: Wlodek, CHRV, icebear, molodcov_alex, goodboy

=== Cut ===

С наилучшими - Wlodek # wlblack()newmail.ru # http://wlodeks.narod.ru
[ZX] [500:95/462@ZXNet] [2:5016 Forever] [Golyanovo] [Старые русские]