PDA

Просмотр полной версии : Баг формата SZX



ZXMAK
11.11.2024, 08:32
Интересно узнать статистику - какие эмуляторы умеют корректно загружать этот SZX снэпшот. :)

Spectramine
11.11.2024, 12:22
А есть такие вообще? Пока что на всех игра сбрасывается, включая Спектакулятор. Штош там за баг-то такой?

ZXMAK
11.11.2024, 14:44
Баг в том, что если выполнение остановлено во время префиксной инструкции, то после сохранения в SZX теряется информация о префиксе, в SZX есть только флаг что была инструкция заблокировавшая прерывания, а какая именно информации нет. Впринципе это восстанавливается если прочитать предыдущую перед PC ячейку, ведь сам флаг что прерывания заблочены инструкцией говорит что процессор находится в состоянии в которое не мог попасть при возврате из подпрограммы или джампом, соответственно можно быть уверенным, что он выполнял предыдущий байт.

Я таким образом и пофиксил загрузку этого снэпшота в ZXMAK2.

Вручную можно пофиксить уменьшив PC на 1, но такой способ собъёт тайминг. Правильнее просто взвести соответствующий флаг префикса.

Spectramine
11.11.2024, 15:20
Баг в том, что если выполнение остановлено во время префиксной инструкции, то после сохранения в SZX теряется информация о префиксе, в SZX есть только флаг что была инструкция заблокировавшая прерывания, а какая именно информации нет. Впринципе это восстанавливается если прочитать предыдущую перед PC ячейку, ведь сам флаг что прерывания заблочены инструкцией говорит что процессор находится в состоянии в которое не мог попасть при возврате из подпрограммы или джампом, соответственно можно быть уверенным, что он выполнял предыдущий байт.

Я таким образом и пофиксил загрузку этого снэпшота в ZXMAK2.

Вручную можно пофиксить уменьшив PC на 1, но такой способ собъёт тайминг. Правильнее просто взвести соответствующий флаг префикса.

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

- - - Добавлено - - -

Вообще цепочки префиксов прерывать конечно можно (и иногда нужно), нельзя прерывать команду после значимого префикса.

ZXMAK
11.11.2024, 15:20
Так это не баг формата. Формат предполагает, что префиксные инструкции нельзя разрывать, они должны быть выполнены до конца перед сохранением снапа. Это баг эмулятора, сохранившего такой снап ;)

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

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

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

Spectramine
11.11.2024, 15:29
Повторюсь - вообще цепочки префиксов прерывать конечно можно (и иногда нужно), нельзя прерывать команду после значимого префикса.

- - - Добавлено - - -

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

- - - Добавлено - - -


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

goodboy
11.11.2024, 15:59
Баг в том, что если выполнение остановлено во время префиксной инструкции, то после сохранения в SZX теряется информация о префиксе
а почему PC устанавливается некорректно ?

Lethargeek
11.11.2024, 16:09
ну почти

- доктор, у меня болит, когда делаю вот так...
- не делайте так!
кстати, sna/z80 еще сохранять нельзя в цепочке ei, пока INTR не закончился; насчёт szx не помню, возможно, тоже

Spectramine
11.11.2024, 16:12
кстати, sna/z80 еще сохранять нельзя в цепочке ei, пока INTR не закончился; насчёт szx не помню, возможно, тоже

В szx есть флаг временного запрещения прерывания, ZXSTZF_EILAST.

Chwe
11.11.2024, 16:14
Мнэээ, а о чём спор? Я, конечно, как Ходжа Насреддин, ничего не понимаю в эмуляторах, но я точно читал документацию для zx-state формат. И там ясно написано, если не читается и в Spectaculator и в FUSE, посмотрите в FUSE как надо записывать.

goodboy
11.11.2024, 16:22
Мнэээ, а о чём спор?
в приведённом примере PC=#F46D INC HL
но в коде выполняется #F46C INC IX

ZXMAK
11.11.2024, 16:25
Снапшот с командой, прерванной после значимого префикса, не сможет корректно прочитать ни один эмулятор, т.к. формат снапшота не предполагает прерывание в середине команды.

что значит ни один, доработанный ZXMAK2 может и корректно читает такие снэпшоты.




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

Как быть если я хочу сохранить текущее состояние процессора, в том виде как есть, а не "после выполнения команд"?

Spectramine
11.11.2024, 16:31
что значит ни один, доработанный ZXMAK2 может и корректно читает такие снэпшоты.

Ну вот только он один и может))


Как быть если я хочу сохранить текущее состояние процессора, в том виде как есть, а не "после выполнения команд"?

Если вы хотите сохранять состояние процессора в середине выполнения команды, можно написать своё расширение формата, ни с чем не совместимое, например.

ZXMAK
11.11.2024, 16:36
а почему PC устанавливается некорректно ?

PC устанавливается корректно, как был до сохранения. Проблема в том, что в SZX только один флаг для указания, что процессор находится в состоянии выполнения префикса из этого флага непонятно какой именно префикс выполняется. Но это можно узнать прочитав ячейку памяти PC-1 - если там #DD, значит взведен префикс IX, если #FD - IY, если чтото другое, значит просто блокировка прерывания инструкцией.

- - - Добавлено - - -


Ну вот только он один и может))
Если вы хотите сохранять состояние процессора в середине выполнения команды, можно написать своё расширение формата, ни с чем не совместимое, например.

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

Spectramine
11.11.2024, 16:43
Проблема в том, что в SZX только один флаг для указания, что процессор находится в состоянии выполнения префикса из этого флага непонятно какой именно префикс выполняется. Но это можно узнать прочитав ячейку памяти PC-1 - если там #DD, значит взведен префикс IX, если #FD - IY, если чтото другое, значит просто блокировка прерывания инструкцией.
В SZX нет флага, что процессор находится в состоянии выполнения префикса, есть флаг временного запрещения прерывания, актуальный после команды EI и некорректных префиксов #DD/#FD, как написано в описании формата. Т.е. для корректных префиксов #DD/#FD этот флаг неактуален.

- - - Добавлено - - -


зачем, если текущий формат вполне позволяет это делать без расширений? Другое дело, что не каждый эмулятор сможет потом прочитать такой снэпшот, тем более не во всех вообще есть возможность остановить процессор во время выполнения префикса.
Сам формат не предполагает прерывание команды после корректного префикса #DD/#FD.

- - - Добавлено - - -

Flag Meaning
ZXSTZF_EILAST The last instruction executed was an EI instruction or an invalid $DD or $FD prefix.

Lethargeek
11.11.2024, 18:02
еще вспомнил, тема поднималась недавно - https://spectrumcomputing.co.uk/forums/viewtopic.php?t=7086
выход retn/reti после корректного NMI (что возможно при модификации пзу) также может прерывание отложить
тогда сразу после будет невозможно понять, выполнялся ли предыдущий байт, если это код префикса или ei

Bedazzle
11.11.2024, 20:13
Интересно узнать статистику - какие эмуляторы умеют корректно загружать этот SZX снэпшот. :)

а какой инструмент охранил такой снапшот?

Spectramine
11.11.2024, 21:04
а какой инструмент охранил такой снапшот?

Сам ZXMAK2 и сохранил, в снапе инфа есть.

ZXMAK
12.11.2024, 04:06
и некорректных префиксов #DD/#FD, как написано в описании формата. Т.е. для корректных префиксов #DD/#FD этот флаг неактуален.

что значит "некорректный префикс"? У Z80 все префиксы корректные.

- - - Добавлено - - -


еще вспомнил, тема поднималась недавно - https://spectrumcomputing.co.uk/forums/viewtopic.php?t=7086
выход retn/reti после корректного NMI (что возможно при модификации пзу) также может прерывание отложить
тогда сразу после будет невозможно понять, выполнялся ли предыдущий байт, если это код префикса или ei

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

Lethargeek
12.11.2024, 04:19
который модифицировал адрес возврата таким образом, чтобы в предыдущем байте был префикс.
необязательно, перед адресом могло быть что-то вроде "cp $DD", или даже "ld ix,$DDFE", или и того хуже

- - - Добавлено - - -

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

Spectramine
12.11.2024, 07:11
что значит "некорректный префикс"? У Z80 все префиксы корректные.
Некорректный - значит цепочечный, который не является корректной частью команды. В цепочке префиксов DD|FD все префиксы некорректные, кроме последнего.

Ещё раз, выдержка из описания формата SZX:
Flag Meaning
ZXSTZF_EILAST The last instruction executed was an EI instruction or an invalid $DD or $FD prefix.

Итого - вы, конечно, можете разрывать команду при записи SZX, записывая его после чтения корректного префикса #DD|#FD, но 1) это не корректно - не соответствует описанию формата, 2) ни один эмулятор, кроме вашего, не будет читать такой SZX, 3) и это не баг формата SZX.

ZXMAK
12.11.2024, 09:54
да, лучше конечно добавить флаги для состояния префиксов в снэпшот. Без этого снэпшоты неполноценные получаются.

А как с автором SZX связаться?

Bedazzle
12.11.2024, 11:10
А как с автором SZX связаться?

Наверное, писать автору спектакулятора. Так понимаю, для телефонов приложуха развивается.

goodboy
12.11.2024, 11:11
специально проверил в нескольких эмуляторах, например
#8000 LD IX,#4000

BreakPoint на #8001 не сработает, также не сработает и условие PC==#8001

получается что в идеале выносить PC `наружу` (для префиксных команд) это неправильно.
.......
call #8001 ; сработает, эмуль понимает что начинает выполняться обычная команда.

ZXMAK
12.11.2024, 12:03
специально проверил в нескольких эмуляторах, например
#8000 LD IX,#4000

BreakPoint на #8001 не сработает, также не сработает и условие PC==#8001


в ZXMAK2 breakpoint сработает.

- - - Добавлено - - -


получается что в идеале выносить PC `наружу` (для префиксных команд) это неправильно.

с чего вдруг неправильно? А если вся память забита скажем #DD, куда эмулятору деваться? :)

Lethargeek
12.11.2024, 12:23
с чего вдруг неправильно? А если вся память забита скажем #DD, куда эмулятору деваться?
на колу мочало... сказано же -

получается что в идеале выносить PC `наружу` (для префиксных КОМАНД) это неправильно.
цепочка незначимых префиксов - НЕ команда (не одна команда, во всяком случае)

ZXMAK
12.11.2024, 12:35
неправильно для чего? Для Z80 это правильно и возможно.

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

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

Пока добавил при загрузке SZX проверку ячейки *(PC-1) если взведен флаг ZXSTZF_EILAST. Это хорошо работает. Но в теории возможна ситуации когда может привести к неправильной интерпретации состояния, как в рассмотреном выше случае с возвратом из NMI по RETI/RETN, в этом случае будет взведен флаг ZXSTZF_EILAST, что приведет к взведению флага IX/IY в загрузчике SZX, если *(PC-1) окажется равным #DD/#FD. Других случаев кроме возврата из NMI когда это может дать ошибочное состояние не вижу.

Если предыдущая инструкция была LD A,#DD, это не приведет к взведению флага IX/IY, т.к. флаг ZXSTZF_EILAST будет сброшен. Он взводится только после выполнения #DD/FD префикса или EI.

Написал Jonathan Needle с просьбой зарезервировать флаги ZXSTZF_IXLAST и ZXSTZF_IYLAST. Если зарезервирует, можно будет их использовать вместо анализа предыдущего байта по ZXSTZF_EILAST.

Bedazzle
12.11.2024, 12:59
при срабатывании точки останова внутри префиксной инструкции процессор останавливается на следующей инструкции вводя пользоваля в замешательство, т.к. на этой интсрукции нет точки останова. Ну и как уже упоминалось выше, если вся память забита префиксом такое завершение инструкции приведет к зависанию эмулятора.

А как отрабатывают цепочку префиксов железные отладчики, например, в Скорпе?

Chwe
12.11.2024, 13:14
А как отрабатывают цепочку префиксов железные отладчики, например, в Скорпе?

Я там выше уже писал, но, видимо, не совсем ясно выразился. Для случая конкретно SZX, а не поведения/эмуляции Z80 «вообще», какая разница? Вроде, конкретно для SZX есть две reference implementations. Ладно, одна без исходников (или нет?), но вторая-то с открытыми исходниками. Если снапшот ни в одной из них не работает, надо просто посмотреть, как сделано в reference implementation и повторить.

Spectramine
12.11.2024, 13:17
Написал Jonathan Needle с просьбой зарезервировать флаги ZXSTZF_IXLAST и ZXSTZF_IYLAST. Если зарезервирует, можно будет их использовать вместо анализа предыдущего байта по ZXSTZF_EILAST.
Это полумеры, для полноты картины ещё можно добавить флаги для информации о текущем машинном цикле, чтобы можно было разрывать команду даже внутри чтения кода операции. Ну и, само собой, после префиксов #CB, #ED, перед чтением операнда и в процессе его чтения.

Titus
12.11.2024, 13:31
А как отрабатывают цепочку префиксов железные отладчики, например, в Скорпе?
Железный отладчик (процессор) не может остановиться в середине цепочки префиксов, т.к. пока не закончится команда, прерывание сработать не может. А даже 100500 префиксов подряд - это для процессора одна команда.

Lethargeek
12.11.2024, 13:47
Железный отладчик (процессор) не может остановиться в середине цепочки префиксов, т.к. пока не закончится команда, прерывание сработать не может. А даже 100500 префиксов подряд - это для процессора одна команда.
он и до конца цепочки ei остановиться не сможет, но это не повод считать всю цепочку одной командой

Titus
12.11.2024, 14:17
он и до конца цепочки ei остановиться не сможет, но это не повод считать всю цепочку одной командой
Это все равно в процессоре по разному реализовано.
Длинный префикс для процессора это все же одна команда.

- - - Добавлено - - -

Кстати, технически для Z80 EI и DI - это одна и та же команда. Просто одна взводит флаг, другая сбрасывает.
И та, и другая блокируют сигнал от триггера IFF1.

- - - Добавлено - - -

https://pic.maxiol.com/images2/1731410212.1595414782.clipboard111220240.png

Lethargeek
12.11.2024, 15:48
Это все равно в процессоре по разному реализовано.
Длинный префикс для процессора это все же одна команда.
с чего бы? префикс тоже всего-навсего "что-то сбрасывает и взводит" - без оглядки на следующий опкод

Titus
12.11.2024, 16:29
с чего бы? префикс тоже всего-навсего "что-то сбрасывает и взводит" - без оглядки на следующий опкод

Да, но технически это реализовано по-разному, и в разных частях процессора.

ZXMAK
12.11.2024, 17:34
Это полумеры, для полноты картины ещё можно добавить флаги для информации о текущем машинном цикле, чтобы можно было разрывать команду даже внутри чтения кода операции. Ну и, само собой, после префиксов #CB, #ED, перед чтением операнда и в процессе его чтения.

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

- - - Добавлено - - -


Это все равно в процессоре по разному реализовано.
Длинный префикс для процессора это все же одна команда.


Почему-же одна. Это много инструкций.

Например: #DD,#FD, #23 - это три инструкции:
1) переключение в режим подмены HL на IX
2) переключение в режим подмены HL на IY
3) INC HL

Titus
12.11.2024, 18:13
Например: #DD,#FD, #23 - это три инструкции:
Это одна команда. Префиксы процессором считаются частью неделимой команды.

ZXMAK
12.11.2024, 18:27
Это одна команда. Префиксы процессором считаются частью неделимой команды.

я так не считаю. И вот почему.
Инструкции у Z80 отделяются по M1 циклу.
Для #DD,#FD, #23 будет отдельный M1 цикл для #DD, отдельный M1 цикл для #FD и отдельный M1 цикл для #23.
Соответственно это три отдельных инструкции.

Spectramine
12.11.2024, 18:31
Я так понимаю, #ED и #CB в вашей картине мира это тоже отдельные инструкции.

Titus
12.11.2024, 18:47
я так не считаю. И вот почему.
Инструкции у Z80 отделяются по M1 циклу.
Для #DD,#FD, #23 будет отдельный M1 цикл для #DD, отдельный M1 цикл для #FD и отдельный M1 цикл для #23.
Соответственно это три отдельных инструкции.
M1 цикл - это машинный цикл в котором выбирается опкод инструкции. Префикс считается частным случаем опкода.
А конец инструкции (или начало следующий) в процессоре совершенно четко обозначен. В моем реверсе это сигнал RES_MCLK (последний машинный цикл инструкции).
M1-циклов может быть много, но RES_MCLK всегда один. По нему процессором и определяется, что инструкция закончилась, можно обработать запрос на прерывание или еще что-то в этом роде.

Lethargeek
12.11.2024, 21:14
M1 цикл - это машинный цикл в котором выбирается опкод инструкции.
СЛЕДУЮЩЕЙ НОВОЙ инструкции :p


Префикс считается частным случаем опкода.
бинго! стало быть, и инструкции :v2_dizzy_roll:


А конец инструкции (или начало следующий) в процессоре совершенно четко обозначен. В моем реверсе это сигнал RES_MCLK (последний машинный цикл инструкции).
КЕМ обозначен, тобой? а с чего ты взял, что авторы именно это в виду имели?


M1-циклов может быть много, но RES_MCLK всегда один. По нему процессором и определяется, что инструкция закончилась, можно обработать запрос на прерывание или еще что-то в этом роде.
я пока что вижу только, что "По нему процессором и определяется, что" + "можно обработать запрос на прерывание или еще что-то в этом роде." - не более

- - - Добавлено - - -

в смысле запрещения прерываний поведение законченной команды ei ну ничем от префиксов не отличается, пусть там даже флаги разные внутри, ну и что?
могли сделать так, могли по-другому (а в каких-нибудь наследниках и клонах, может, и сделали)

Titus
12.11.2024, 21:46
КЕМ обозначен, тобой? а с чего ты взял, что авторы именно это в виду имели?
Мною обозначено его название.
А авторами предусмотрен функционал - как маркер окончания одной команды и начала другой.

Lethargeek
12.11.2024, 23:50
авторами предусмотрен
ты приписываешь авторам свои мысли


функционал - как маркер окончания одной команды и начала другой
никаких полезных функций у такого "маркера" я не вижу

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

Bedazzle
13.11.2024, 00:13
Я чутка потерялся. А что будет происходить, если сделать длинную цепочку префиксов, и во время её отработки наступит момент прерывания. Когда оно отработает? В середине цепочки, или будет пропущено, и цепочка отработает до конца? Если в середине, то процессор будет помнить какой был последний префикс перед прерыванием, или потеряет?

Lethargeek
13.11.2024, 01:25
Я чутка потерялся. А что будет происходить, если сделать длинную цепочку префиксов, и во время её отработки наступит момент прерывания. Когда оно отработает? В середине цепочки, или будет пропущено, и цепочка отработает до конца? Если в середине, то процессор будет помнить какой был последний префикс перед прерыванием, или потеряет?
на реальных Z80 - будет пропущено
насчёт Z?80/eZ80 не помню

Titus
13.11.2024, 01:38
Я чутка потерялся. А что будет происходить, если сделать длинную цепочку префиксов, и во время её отработки наступит момент прерывания. Когда оно отработает? В середине цепочки, или будет пропущено, и цепочка отработает до конца? Если в середине, то процессор будет помнить какой был последний префикс перед прерыванием, или потеряет?

Если прерывание немаскируемое (NMI), то оно не может быть пропущено, т.к. фиксируется специальной схемой, способной уловить даже маленькие иголочки на входе. Любой перепад на входе NMI 0->1->0 будет зафиксирован, как запрос переывания, и после выполнения сверхдлинной команды будет отработан, и только потом снят. Единственное, что может отменить запрос NMI - это только RESET.

Если прерывание маскируемое (INT), то оно может быть пропущено, если сигнал на входе INT пропал до того, как закончилась сверхдлинная команда.
Мало того, запрос INT может быть пропущен, если длина запроса меньше одного такта процессора.

Reobne
13.11.2024, 03:15
Мне кажется, лучше считать, что никакого бага в SZX нет. Что сохранить снапшот можно только в тот момент, с которого легко продолжить выполнение не только в эмуляторе, но и на реале. Для усложнения нужны более веские причины, чем просто "так хочется".

Сейчас и на реалах можно делать снапшоты, по немаскируемому прерыванию. Есть, правда, глюки, при некоторых SP. Ну и, получается, если всю помять забить префиксом, то тоже не сработает NMI.

Эмуляторные извращения это весело, можно хоть любой такт сохранять, но во первых: "Зачем?", а во вторых: "Нафига усложнять запуск снапшота на реале?"

ZXMAK
13.11.2024, 04:21
Я так понимаю, #ED и #CB в вашей картине мира это тоже отдельные инструкции.

вполне - инструкции перевода процессора в режим расширенных опкодов.

- - - Добавлено - - -


M1 цикл - это машинный цикл в котором выбирается опкод инструкции. Префикс считается частным случаем опкода.
А конец инструкции (или начало следующий) в процессоре совершенно четко обозначен. В моем реверсе это сигнал RES_MCLK (последний машинный цикл инструкции).
M1-циклов может быть много, но RES_MCLK всегда один. По нему процессором и определяется, что инструкция закончилась, можно обработать запрос на прерывание или еще что-то в этом роде.

Вполне логично, что процессор может вырабатывать дополнительные сигналы блокировки прерывания, чтобы исключить прерывание, когда это нежелательно. Но ведь возможность обработать прерывание не означает что процессор закончил выполнение инструкции, иначе прийдется все что находится между DI и EI или весь обработчик NMI/INT прерывания трактовать как одну большую инструкцию.

- - - Добавлено - - -


Я чутка потерялся. А что будет происходить, если сделать длинную цепочку префиксов, и во время её отработки наступит момент прерывания. Когда оно отработает? В середине цепочки, или будет пропущено, и цепочка отработает до конца? Если в середине, то процессор будет помнить какой был последний префикс перед прерыванием, или потеряет?

выполнение инструкции префикса переводит процессор в префиксный режим, в котором прерывания блокируются пока режим префикса не будет снят. Также как выполнение EI блокирует прерывания на одну следующую инструкцию.

- - - Добавлено - - -


Мне кажется, лучше считать, что никакого бага в SZX нет. Что сохранить снапшот можно только в тот момент, с которого легко продолжить выполнение не только в эмуляторе, но и на реале. Для усложнения нужны более веские причины, чем просто "так хочется".

Дело в том, что если сохранять снэпшот только в тот момент, когда процессор не находится в режиме префикса, то не всегда будет возможность вообще сохранить снэпшот. В случае, когда вся память заполнена префиксом #DD или #FD, процессор перманентно всегда находится в префиксном режиме, не выходя из него. Поэтому это просто приведет к вечному зависанию эмулятора при попытке сохранить снэпшот. Такое поведение неправильное.

- - - Добавлено - - -


Сейчас и на реалах можно делать снапшоты, по немаскируемому прерыванию. Есть, правда, глюки, при некоторых SP. Ну и, получается, если всю помять забить префиксом, то тоже не сработает NMI.

сохранение снэпшотов из обработачика NMI не всегда даёт рабочие снэпшоты, т.к. необратимо портит память и состояние процессора. Методы защиты от снятия снэпшотов с помощью TRDOS MAGIC или другого NMI обработчика на Z80 давно известны и в таких программах после нажатия NMI код программы будет испорчен и программа покажет сообщение о недопустимости выполнения NMI либо просто сбросится или перестанет работать.

Эмулятор-же или железный отладчик (JTAG) должен обеспечивать отладку полностью прозрачно для отлаживаемой программы, никак не влияя на её состояние.

- - - Добавлено - - -


Эмуляторные извращения это весело, можно хоть любой такт сохранять, но во первых: "Зачем?"

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


а во вторых: "Нафига усложнять запуск снапшота на реале?"

а как вы себе представляете корректный запуск SZX снэпштоа на риале, сохраненного после выполнения EI, т.е. с взведенным флагом EILAST?

Reobne
13.11.2024, 05:57
Затем, чтобы во время отладки можно было сохранить текущее состояние программы, пойти погулять, покушать, отдохнуть и на следующий день загрузить его и продолжить отладку с того-же самого состояния.
Ну, то есть, заходим в отладчик, а там PC указывает, допустим, на "LD (IY+0),L" Нажимаем на шаг вперёд и что мы увидим? PC увеличится на байт или на 3?

ZXMAK
13.11.2024, 07:38
Ну, то есть, заходим в отладчик, а там PC указывает, допустим, на "LD (IY+0),L" Нажимаем на шаг вперёд и что мы увидим? PC увеличится на байт или на 3?

В этом случае отладчик установит точку останова на адрес следующий за "LD (IY+0),L" и запустит выполнение.
Далее будет зависеть от того - дойдет ли выполнение до указанной точки останова - тогда отладчик остановится и покажет адрес на котором сработала точка останова.
Если же управление до точки останова не дойдет, процессор так и будет продолжать работать выполняя все инструкции подряд.

Поэтому однозначно сказать нельзя - будет зависеть от результатов выполнения кода. Также как нельзя сказать - вернет ли CALL или RST управление на следующий адрес или на следующий адрес + N или вообще не вернет управление или вообще не выполнится, потому что сработает прерывание.

Однако если вы поставите точку останова на адрес PC, то при шаге/запуске отладчик остановит выполнение на адресе PC+1, т.е. будет показывать "LD (HL),L; NOP" и взведенный флаг префикса IY. Вообще конечно правильнее было-бы доработать отладчик чтобы он дизассемблировал память с учетом текущего состояния процессора и тогда он будет показывать все ту-же инструкцию "LD (IY+0),L"

Dexus
13.11.2024, 08:49
Недоумеваю
1. Геморрой развели из-за синтетической ситуации, когда ВСЯ память забита префиксами. Накой вообще такое сохранять? Оно и осмысленной работы не делает, и не отлаживается.
2. Не припомню эмуляторов с отладчиками (за исключением онлайн игрушки со схемой z80), в которой шаги не по инструкциям, а по байтам. Какая от этого практическая польза?

Бага нет.
Если хочешь чтобы szx сохранял внутреннее состояние z80 с фазами опкодов - просто надо новый блок в формат добавить. Но никто кроме тебя его не будет поддерживать (потому что это не нужно). И да, придется свою имплементацию мутить, а не использовать libspectrum (хотя может libspectrum позволяет кастомные блоки сохранять и хэндлить - тогда вообще проблем нет).

Titus
13.11.2024, 12:53
В случае, когда вся память заполнена префиксом #DD или #FD, процессор перманентно всегда находится в префиксном режиме, не выходя из него. Поэтому это просто приведет к вечному зависанию эмулятора при попытке сохранить снэпшот. Такое поведение неправильное.

1. Нельзя всю память заполнить префиксами. Все равно настанет адрес 0000, где находится ПЗУ, а там уже команда.
2. Если же эмулируется клон, у которого вместо ПЗУ может встать ОЗУ, и тогда действительно можно заполнить всю память префиксами, то... такой снапшот никому не нужен, т.к. он никогда не будет работать на реале) Вся память в префиксах - это вечный зависон и отсутствие программы)

Spectramine
13.11.2024, 17:59
1. Нельзя всю память заполнить префиксами. Все равно настанет адрес 0000, где находится ПЗУ, а там уже команда.
2. Если же эмулируется клон, у которого вместо ПЗУ может встать ОЗУ, и тогда действительно можно заполнить всю память префиксами, то... такой снапшот никому не нужен, т.к. он никогда не будет работать на реале) Вся память в префиксах - это вечный зависон и отсутствие программы)

На +2А/+3 вместо ПЗУ может встать ОЗУ (чисто для информации).

- - - Добавлено - - -

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

ZXMAK
13.11.2024, 19:04
На +2А/+3 вместо ПЗУ может встать ОЗУ (чисто для информации).

- - - Добавлено - - -

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

возникает вопрос, как остановить выполение именно на таком так называемом "корректном" префиксе? Чтобы проверить корректный ли префикс или нет - нужно выполнить цикл, чтобы процессор прочитал ячейку памяти, однако если память заполнена префиксами, то на новом цикле префикс опять взведен и опять нужно проверить "корректный" ли префикс, для чего снова нужно выполнить цикл и так до бесконечности по кругу.

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

Titus
13.11.2024, 19:28
Таким образом проверить "корректный" ли префикс невозможно.
Если это твой эмулятор Z80, то ты можешь проверить все, что угодно.
Сделай проверку, что если после выборки префикса DD/FD идет снова выборка префикса DD/FD, то помечай, что префикс 'некорректный', как ты его называешь.

Bedazzle
13.11.2024, 20:14
Проблема тут заключается в том, что просто прочитать память нельзя, т.к. при доступе к памяти процессора банка может переключиться и прочитается совсем другое значение, чем при чтения до выполнения цикла. Таким образом проверить "корректный" ли префикс невозможно.

я потому и спрашиаал, как работает цепочка префиксов, и может ли между ними придти прерывание :) ну, и непонятно, что значит "нельзя прочитать" :) эмуль же, реализовать можно что угодно, лишь бы корректное поведение реальной машины :) но можно и нереальное - например, Spec256

ZXMAK
13.11.2024, 20:46
Если это твой эмулятор Z80, то ты можешь проверить все, что угодно.
Сделай проверку, что если после выборки префикса DD/FD идет снова выборка префикса DD/FD, то помечай, что префикс 'некорректный', как ты его называешь.

Так в том-то и дело, чтобы сделать проверку - нужно выполнить цикл, а после выполнения цикла нужно проверять уже новое состояние, т.е. нужно опять выполнить цикл и так до бесконечности. :)

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

- - - Добавлено - - -


ну, и непонятно, что значит "нельзя прочитать" :) эмуль же, реализовать можно что угодно, лишь бы корректное поведение реальной машины :) но можно и нереальное - например, Spec256

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

Lethargeek
13.11.2024, 22:19
Так в том-то и дело, чтобы сделать проверку - нужно выполнить цикл, а после выполнения цикла нужно проверять уже новое состояние, т.е. нужно опять выполнить цикл и так до бесконечности.

Просто прочитать память - неправильно, т.к. из памяти может прочитаться одно значение, а при выполнении цикла прочитается другое (например если читается инструкция из TRDOS гейта).
какой цикл, какую память читать... :v2_wacko: ну элементарно же, флажок сделай, что в прошлый M1 был DD/FD
и тогда если в текущий M1 операция от такого префикса не зависит - сохраняться можно в этот момент

- - - Добавлено - - -


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

ZXMAK
14.11.2024, 04:00
и тогда если в текущий M1 операция от такого префикса не зависит - сохраняться можно в этот момент


вот это условие проверить проблематично. Как узнать в новом M1 операция зависит от префикса или нет?
Для этого нужно выполнить цикл, чтобы процессор полноценно сделал выборку опкода, тогда станет понятно зависит или нет.
Но когда новый цикл M1 будет выполнен, то может оказаться что выбран новый опкод #DD/#FD, и требуется еще один цикл М1, чтобы проверить новое состояние. И так до бесконечности.

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

И даже если удалось правильно предсказать, какой прочитается опкод в следующем M1 цикле, пользователь после загрузки снэпшота может поменять память, сделав какой-то poke или загрузив патч для кода и тогда окажется что опкод который прогнозировался до сохранения опкода окажется неправильным и это приведет к неправильной интерпретации "некорретности" префикса.

Titus
14.11.2024, 12:44
вот это условие проверить проблематично. Как узнать в новом M1 операция зависит от префикса или нет?
В смысле зависит от префикса? Зачем что-то предсказывать?
Если ты выбрал любой префикс, то все, что дальше по любому зависит от этого префикса, не важно, сколько раз он повторится, и останавливать выполнение, пока команда не закончится, нельзя.

ZXMAK
14.11.2024, 13:04
В смысле зависит от префикса? Зачем что-то предсказывать?
Если ты выбрал любой префикс, то все, что дальше по любому зависит от этого префикса, не важно, сколько раз он повторится, и останавливать выполнение, пока команда не закончится, нельзя.

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

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

Спектакулятор так не делает, вместо этого он использует костыль с вышеописанным так называемым "инвалидным префиксом" под которым подразумевается, что если если процессор переключился в префиксный режим, но далее следует еще один префикс, то первый префикс можно проигнорировать путём предсказания что после загрузки SZX процессор выполнит еще один префикс и снова перейдет в режим префикса. Но это костыль, такое прогнозирование с потерей информации о префиксе нельзя назвать корректным поведением.

Далеко не факт, что если спектакулятор прочитал из памяти по адресу PC префикс, то после сохранения/загрузки снэпшота, при выполении M1 цикла именно этот префикс по этому адресу и прочитается. Вполне может произойти переключение страниц памяти, например в ПЗУ TRDOS или в гейт другого устройства. И тогда так называемый "инвалидный префикс" внезапно станет далеко не инвалидным, а самым нормальным, но будет уже поздно, т.к. в снэпшоте информация о текущем режиме префикса не сохранена и процессор выполнит некорректную инструкцию, т.к. режим префикса в снэпшоте не был сохранен.

Titus
14.11.2024, 13:11
Если нельзя, тогда эмулятор должен зависать в мёртвом бесконечном цикле, если память заполнена префиксами.
Да не бывает всей памяти заполненной префиксами. Потому что если она заполнена, то такой снапшот сохранять не надо, он не будет работать, и никому не нужен.
А эмулятор может проверить, если друг за другом идет 100500 префиксов, то все, команду можно прерывать, злобный буратино запорол себе программу.

ZXMAK
14.11.2024, 13:21
Да не бывает всей памяти заполненной префиксами. Потому что если она заполнена, то такой снапшот сохранять не надо, он не будет работать, и никому не нужен.

почему-же не бывает, вполне может быть, кстати нужно будет ради интереса посмотреть как эмуляторы ведут себя на такой программе и как SZX сохраняют. :)


А эмулятор может проверить, если друг за другом идет 100500 префиксов, то все, команду можно прерывать, злобный буратино запорол себе программу.

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

jerri
14.11.2024, 13:38
Если нельзя, тогда эмулятор должен зависать в мёртвом бесконечном цикле, если память заполнена префиксами.
Тут одно из двух - либо можно и тогда ничего зависать не будет, либо нельзя и прийдется зависать по дизайну.

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

Спектакулятор так не делает, вместо этого он использует костыль с вышеописанным так называемым "инвалидным префиксом" под которым подразумевается, что если если процессор переключился в префиксный режим, но далее следует еще один префикс, то первый префикс можно проигнорировать путём предсказания что после загрузки SZX процессор выполнит еще один префикс и снова перейдет в режим префикса. Но это костыль, такое прогнозирование с потерей информации о префиксе нельзя назвать корректным поведением.

Далеко не факт, что если спектакулятор прочитал из памяти по адресу PC префикс, то после сохранения/загрузки снэпшота, при выполении M1 цикла именно этот префикс по этому адресу и прочитается. Вполне может произойти переключение страниц памяти, например в ПЗУ TRDOS или в гейт другого устройства. И тогда так называемый "инвалидный префикс" внезапно станет далеко не инвалидным, а самым нормальным, но будет уже поздно, т.к. в снэпшоте информация о текущем режиме префикса не сохранена и процессор выполнит некорректную инструкцию, т.к. режим префикса в снэпшоте не был сохранен.

Короче - проц знает что он выполняет и когда? значит это знание проца надо перенести кудато во флаги. хоть в AF -там есть бит свободный
сам по себе СНАПШОТ является извращением работы системы, значит заботится о правильном выполнении должен автор формата.
Вот и заботься.

Titus
14.11.2024, 13:46
Короче - проц знает что он выполняет и когда? значит это знание проца надо перенести кудато во флаги. хоть в AF -там есть бит свободный
Нельзя переносить в AF, и битов там свободных нет.
Конечно, в снапшоте все можно сохранять и восстанавливать, это не извращение.
Извращение, если при этом портится стек или что-то еще.

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

jerri
14.11.2024, 14:06
Нельзя переносить в AF, и битов там свободных нет.
Конечно, в снапшоте все можно сохранять и восстанавливать, это не извращение.
Извращение, если при этом портится стек или что-то еще.


НУ в данном случае как раз и происходит извращение

inc IX >> inc hl

потому что прерывание приходит между #DD и #23
и эмулятор забывает что работает с префиксом



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

Ну как тут пишет ZXMAK вот оно будущее уже пришло.

Lethargeek
14.11.2024, 15:00
вот это условие проверить проблематично. Как узнать в новом M1 операция зависит от префикса или нет?
да как угодно, хоть через таблицу опкод проверить


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


Но когда новый цикл M1 будет выполнен,
нафига? холостую выборку просто сделай


Грубо говоря проблема в том, что читать память для проверки что будет выполнять процессор в следующем цикле - это ошибочный подход, т.к. предсказать какой опкод будет выбран нереально. Можно только сделать предположение, что опкод прочитается из текущей страницы памяти, но это далеко не факт, т.к. во время выборки опкода какое-то эмулируемое устройсво может переключить страницу памяти или отключить память и само выдать опкод на шину данных во время выборки опкода.
у тебя, блин, ЭМУЛЯТОР! с ним всё предсказуемо и реально


И даже если удалось правильно предсказать, какой прочитается опкод в следующем M1 цикле, пользователь после загрузки снэпшота может поменять память, сделав какой-то poke или загрузив патч для кода и тогда окажется что опкод который прогнозировался до сохранения опкода окажется неправильным и это приведет к неправильной интерпретации "некорретности" префикса.
ну и ССЗБ такой кулхацкер, эмуль-то при чём? шаловливыми ручонками лезть в принципе небезопасно, понимать надо

ZXMAK
14.11.2024, 16:51
Короче - проц знает что он выполняет и когда? значит это знание проца надо перенести кудато во флаги. хоть в AF -там есть бит свободный


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

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



и эмулятор забывает что работает с префиксом


не эмулятор забывает, а снэпшот не сохраняет это состояние. В нем не предусмотрено полей для сохранения этих состояний.


да как угодно, хоть через таблицу опкод проверить


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

- - - Добавлено - - -


нафига? холостую выборку просто сделай

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

Например, ставим PC процессора на адрес перед входом в гейт TRDOS, в отладчике видим что читается один байт, выполняем шаг - прочитался совсем другой байт, т.к. при выполнении цикла M1 подключилась банка ПЗУ TRDOS, в которой байт отличается от того что в банке ПЗУ ROM48.

jerri
14.11.2024, 18:00
процессор-то знает, у него для этого флаги есть. Но в снэпшоте нет полей куда это состояние процессора можно сохранить, поэтому информация о состоянии этих флагов теряется.


вот ты носки жуешь уже 7 страницу.
дополни/сделай версию 2



не эмулятор забывает, а снэпшот не сохраняет это состояние. В нем не предусмотрено полей для сохранения этих состояний.


Новые проблемы требуют современных решений.

Lethargeek
14.11.2024, 18:37
проверить код опкода на префикс не проблема. Проблема спрогнозировать какой опкод прочитается на следующем цикле, не выполняя этот цикл.
:v2_dizzy_facepalm: в каком "следующем"? ты ТЕКУЩИЙ проверяешь ПОСЛЕ префикса!


холостую выборку не сделаешь. Если прочитать память при текущем состоянии результат будет один. А когда начнет выполняться цикл, отработает логика устройств, может подключиться другая банка памяти и результат будет совсем другой.
:v2_dizzy_tired2: значит, делай с "отработкой логики устройств", в чём проблема-то?

- - - Добавлено - - -

понимаю, иногда что-то программировать неприятно, но твоя лень - это всё же не "баг формата"

ZXMAK
14.11.2024, 20:06
:v2_dizzy_facepalm: в каком "следующем"? ты ТЕКУЩИЙ проверяешь ПОСЛЕ префикса!


"текущего" цикла нет. Есть предыдущий, есть следующий. Между ними и происходит сохранение или просмотр состояния в отладчике. Чтобы узнать что DD/FD префикс в предыдущем цикле был "инвалидный" нужно предсказать что прочитается из памяти по адресу PC. Полноценно это можно сделать только выполнив следующий цикл. Предсказать что прочитается и не выполнять следующий цикл по результату предсказания не получится.

- - - Добавлено - - -


:v2_dizzy_tired2: значит, делай с "отработкой логики устройств", в чём проблема-то?

понимаю, иногда что-то программировать неприятно, но твоя лень - это всё же не "баг формата"

это тоже самое, как предсказывать в программе какую следующую кнопку нажмет пользователь, "отрабатывая логику пользователя"... :)

Titus
14.11.2024, 20:11
холостую выборку не сделаешь. Если прочитать память при текущем состоянии результат будет один. А когда начнет выполняться цикл, отработает логика устройств, может подключиться другая банка памяти и результат будет совсем другой.
А как ты вообще решаешь такой вопрос эмуляции Z80, что пока Z80 выполняет одну команду, он уже читает опкод другой команды? )

Bedazzle
14.11.2024, 20:13
Я опять потерялся. Вот мы обсуждаем, в цепочке префиксов может ли придти прерывание, да когда отработает, да что устройство внешнее может банку памяти подменить... А разве в снап пишется инфа о подключенных устройствах?
Тогда ведь это баг формата если пользаватель в эмуле может добавить, или убрать устройство? Может, оно пзу подменило, а пзу в снап не сохранено, и хз, куда улетит эмуляция при загрузке?

ZXMAK
14.11.2024, 20:32
Я опять потерялся. Вот мы обсуждаем, в цепочке префиксов может ли придти прерывание

прерывание между префикса прийти не может, также как и между двумя EI. Но обрабатывается каждый префикс отдельно по одному, а не все разом.


А как ты вообще решаешь такой вопрос эмуляции Z80, что пока Z80 выполняет одну команду, он уже читает опкод другой команды? )

эмулятор что читает то и обрабатывает :)

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

Lethargeek
14.11.2024, 20:35
"текущего" цикла нет. Есть предыдущий, есть следующий.
когда мы с ним уже работаем (вне зависимости от степени отработки) - он текущий


Чтобы узнать что DD/FD префикс в предыдущем цикле был "инвалидный" нужно предсказать что прочитается из памяти по адресу PC. Полноценно это можно сделать только выполнив следующий цикл. Предсказать что прочитается и не выполнять следующий цикл по результату предсказания не получится.
:v2_dizzy_facepalm: :v2_dizzy_facepalm: ё-моё, полноценно можно это сделать через полноценную ТОЛЬКО ВЫБОРКУ!
ВЫПОЛНЯТЬ инструкцию НЕ требуется, приращение pc НЕ требуется
изменение в эмуле аппаратного контекста НЕ требуется


это тоже самое, как предсказывать в программе какую следующую кнопку нажмет пользователь, "отрабатывая логику пользователя"...
https://media.tenor.com/Gopydqo1d94AAAAM/kazakhstan-explaining.gif
не тупи, это ЭМУЛЬ, перед выборкой всё ДЕТЕРМИНИРОВАНО!

goodboy
14.11.2024, 20:50
А разве в снап пишется инфа о подключенных устройствах?
https://www.spectaculator.com/docs/zx-state/intro.shtml

- - - Добавлено - - -


Может, оно пзу подменило, а пзу в снап не сохранено,
я недавно сконвертил игрушку (для запуска из ROM, InterfaceII) - работает.

Titus
14.11.2024, 20:50
У Z80 такой возможности нет.
Z80 тоже имеет конвейер)

Если эмулятор это не отрабатывает, зачем так педантично стремиться другие вещи отследить типа пререключения страниц в момент выборки предсказания префикса)

Bedazzle
14.11.2024, 21:07
https://www.spectaculator.com/docs/zx-state/intro.shtml

Спасибо! Век - живи, век - учись...

ZXMAK
15.11.2024, 10:03
:v2_dizzy_facepalm: :v2_dizzy_facepalm: ё-моё, полноценно можно это сделать через полноценную ТОЛЬКО ВЫБОРКУ!
ВЫПОЛНЯТЬ инструкцию НЕ требуется, приращение pc НЕ требуется
изменение в эмуле аппаратного контекста НЕ требуется

Главная причина, почему выборка опкодов для анализа без выполнения инструкции невозможна, связана с состоянием внешней схемы и стейт-машин, которые реагируют на действия процессора. Для внешней схемы каждая выборка Z80 из памяти - это реальная операция с шиной, которая изменяет её состояние.

Например, при обращении к определённым адресам памяти или при выполнении определённых условий на шине, схема может переключить банку памяти, переместить луч развертки CRT или выполнить другое действие.

Внешняя логика реагирует на сигналы процессора (MREQ, RD, IOREQ, адресная шина, шина данных и т.д.), поэтому даже два одинаковых обращения к одной и той же ячейке памяти происходят в разных состояниях схемы и могут приводить к разным результатам.

Если вы выполняете "имитацию" выборки для анализа, то схема уже перейдёт в изменённое состояние. Когда процессор начнёт реальное выполнение, его взаимодействие с шиной нарушит ожидаемую последовательность действий, что приведёт к сбоям в тайминге и работе внешних устройств.

Чтобы корректно проанализировать цепочку префиксов, потребуется на каждом цикле полностью сохранять состояние всей системы, включая периферию, и затем откатывать это состояние назад при обнаружении двух префиксов #DD/#FD подряд. Однако такой подход крайне сложен и не всегда возможен.



не тупи, это ЭМУЛЬ, перед выборкой всё ДЕТЕРМИНИРОВАНО!

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

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

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

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

- - - Добавлено - - -



Если эмулятор это не отрабатывает, зачем так педантично стремиться другие вещи отследить типа пререключения страниц в момент выборки предсказания префикса)

А зачем эмулировать конвейер, если его наличие или отсутствие никак на эмуляцию не влияет?

С режимом префикса совсем другая ситуация. Если снэпшот сохранён в момент, когда процессор находился в режиме префикса, то отсутствие информации о текущем состоянии префикса в снэпшоте приведёт к его сбросу. Это может нарушить корректное выполнение программы после восстановления, поскольку процессор окажется в неверном состоянии.

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

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

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

Titus
15.11.2024, 11:42
А зачем эмулировать конвейер, если его наличие или отсутствие никак на эмуляцию не влияет?
Как зачем?
Допустим, выполняется RET.
В эмуляторе у тебя прочитается опкод C9, затем процессор перейдет по адресу возврата.
А на реале прочитается и следующий за C9 байт. А там, допустим, уже размещен какой-то порт, спроецированный в память, чтение которого приводит к каким-то действиям.
Понятно, что на оригинальном спектруме такого нет, но мало ли какие клоны бывают. Да и вообще, если эмулируется не спектрум, а другая система на Z80.

- - - Добавлено - - -

Или более реалистичный пример.

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

Lethargeek
15.11.2024, 13:43
Главная причина, почему выборка опкодов для анализа без выполнения инструкции невозможна, связана с состоянием внешней схемы и стейт-машин, которые реагируют на действия процессора. Для внешней схемы каждая выборка Z80 из памяти - это реальная операция с шиной, которая изменяет её состояние.
Еще раз: главная причина МНИМОЙ "невозможности" - твоя ЛЕНЬ. Никакой непреодолимой технической проблемы здесь НЕТ. Если у тебя процедура-монолит производит выполнение вместе с выборкой - РАЗДЕЛИ. Или напиши отдельную для сейва, с КОПИЕЙ ЧАСТИ (связанного только с выборкой, "полностью" НЕ нужно) аппаратного контекста, в конце концов. ВСЁ РЕШАЕМО.


Ваше утверждение о полной детерминированности эмуляции некорректно. Даже в эмуляторе есть недетерминированные факторы, такие как пользовательский ввод, время прихода внешних сигналов (например, от дисплея, звуковой карты, системного таймера), а также поведение схемы при загрузке снэпшота. (...)
Моё утверждение абсолютно корректно. Детерминированность - это когда для одних и тех же исходных данных получаем одинаковый результат. Отличающийся пользовательский ввод (который, кстати, сохраняется в szx, да и в типичном эмуле скорей всего сканируется и фиксируется перед прогонкой кадра) или "малейшие" (на практике многие проходят незамеченными) несовпадения чего-то для rzx, или недостаток апппаратных данных в снапшоте - это нарушение условия по исходным данным. Но мы здесь говорим пока что ТОЛЬКО о ВЫБОРКЕ. Для неё условие одинаковых исходных обеспечить технически возможно и не так уж сложно. Тем более, что возможность форка состояний вообще полезна.


Однако, как рассмотрено выше, предсказать следующий опкод невозможно, что делает такой подход ненадёжным, т.к. при загрузке снэпшота может оказаться, что из памяти читается далеко не префикс, а информация о том что процессор должен быть в префиксном режиме уже потеряна, т.к. снэпшот её не сохранил.
Если в снапе чего-то не хватает, восстановить недостающий контекст - на совести пользователя. Но уж для ДОСТАТОЧНО корректно восстановленного пользователем, будь так добр обеспечить правильные результаты после загрузки. Это на твоей совести. А в идеале - даже для недостаточного восстановления максимально снизить вероятность проблем.

Reobne
16.11.2024, 09:56
Думаю всё же, формат снапшота надо оставить как есть, с сохранением в начале выполнения команды. А если очень хочется, то для потактовой отладки можно завести дополнительный блок, в котором сохранить, сколько тактов выполнялась последняя команда, и список недетёрминированных событий, которые за эти такты случились. Чтобы проги, которые не готовы работать с потактовой информацией, максимально корректно загружали такой снапшот, игнорируя блок с потактовой информацией.

ZXMAK
16.11.2024, 14:24
[QUOTE=Titus;1206650]Как зачем?
Допустим, выполняется RET.
QUOTE]

вопрос довольно простой - можно ли отличить эмулятор эмулирующий конвеер или нет. Для Z80 ответ - нет, никак не отличить. Поэтому и смысла его эмулировать нет - только лишний код.

Titus
16.11.2024, 14:34
вопрос довольно простой - можно ли отличить эмулятор эмулирующий конвеер или нет. Для Z80 ответ - нет, никак не отличить. Поэтому и смысла его эмулировать нет - только лишний код.
Как нельзя? Я только что написал, как отличить. По таймингам.

ZXMAK
16.11.2024, 14:56
Еще раз: главная причина МНИМОЙ "невозможности" - твоя ЛЕНЬ. Никакой непреодолимой технической проблемы здесь НЕТ. Если у тебя процедура-монолит производит выполнение вместе с выборкой - РАЗДЕЛИ. Или напиши отдельную для сейва, с КОПИЕЙ ЧАСТИ (связанного только с выборкой, "полностью" НЕ нужно) аппаратного контекста, в конце концов. ВСЁ РЕШАЕМО.

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

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

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



Моё утверждение абсолютно корректно. Детерминированность - это когда для одних и тех же исходных данных получаем одинаковый результат

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

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

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

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


Если в снапе чего-то не хватает, восстановить недостающий контекст - на совести пользователя. Но уж для ДОСТАТОЧНО корректно восстановленного пользователем, будь так добр обеспечить правильные результаты после загрузки. Это на твоей совести. А в идеале - даже для недостаточного восстановления максимально снизить вероятность проблем.

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

Подобно тому как в SNA невозможно восстановить текущий такт кадра, в SZX также не предусмотрено сохранение состояния префиксов, что делает их восстановление невозможным. В случае, если программа не предъявляет строгих требований к точности состояния, она может продолжить работу без проблем. Однако если для корректной работы критично, на каком такте выполняется каждая инструкция, и необходимо точное восстановление состояния процессора, то после загрузки такого снапшота программа, скорее всего, не будет работать корректно.

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

- - - Добавлено - - -


Как нельзя? Я только что написал, как отличить. По таймингам.

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

Titus
16.11.2024, 15:25
и как по таймингам отличить. Вот синхронизировали эмулятор с конвеером и без конвеера по событию чтения инструкции из памяти, условно приняли это за нулевую точку отсчета - нулевой такт. Разве будет отличие в таймингах следующей выборки и т.д.? Нет, они покажут абсолютно одинаковые тайминги. Отличие будет только в том, как они внутри реализованы. Но на таймингах это не сказывается.

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

- - - Добавлено - - -

Возможно, в случае с RET вопрос спорный, я еще не рассматривал, как она взаимодействует с конвейером.
Но это именно для примера, что эмуляция настоящего поактового Z80 где-то может и отличиться по таймингам.

ZXMAK
16.11.2024, 17:57
Если у тебя крутится цикл, каждая итерация которого заканчивается RET (для примера), и этот RET находится в последнем байте медленной памяти, а следующий байт будет уже быстрая память. Или наоборот.
То такой цикл будет давать другие тайминги на честном Z80 с конвейером, т.к. после RET всегда будет читаться байт из памяти с другими таймингами.


нет, оба эмулятора будут давать идентичные тайминги. Отличие будет условным - в названии. :)
У обоих эмуляторов число тактов между выборками будет одинаковым. Просто в том что без конвеера все такты будут условно сдвинуты на фиксированную величину. Но выборки из памяти будут одинаково работать и все тайминги будут идентичными.

Titus
16.11.2024, 18:07
нет, оба эмулятора будут давать идентичные тайминги. Отличие будет условным - в названии.
Мне кажется, кто-то из нас кого-то не понимает)

ZXMAK
16.11.2024, 20:02
Мне кажется, кто-то из нас кого-то не понимает)

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

Lethargeek
25.11.2024, 03:27
Подобно тому как невозможно предсказать, выпадет ли орел или решка при подбрасывании монеты, так и в эмуляторе невозможно точно предсказать, когда пользователь нажмет кнопку, когда произойдёт событие обратного хода луча на дисплее, когда будет обработан сигнал от звуковой карты или другие подобные события, зависящие от взаимодействия с внешней средой.
:v2_dizzy_facepalm: да блин горелый же, все эти "предсказания" НЕ НУЖНЫ! ну какая тебе разница, что за кнопка будет нажата юзверем ЗА ПЕРВЫЕ ДВА ТАКТА любой инструкции?


Поэтому, несмотря на то что для теоретически детерминированных систем можно ожидать одинаковый результат при одинаковых входных данных, для эмулятора, работающего в условиях неопределенности, это условие не выполняется.
ПРИМЕР в студию! ну хотя бы чисто теоретический, что такого ужасного и вселомающего может произойти конкретно ЗА ВРЕМЯ ВЫБОРКИ?


Подобно тому как в SNA невозможно восстановить текущий такт кадра, в SZX также не предусмотрено сохранение состояния префиксов, что делает их восстановление невозможным.
:v2_dizzy_tired2: еще раз: значит, сохраняй в тот момент, КОГДА состояние префиксов НЕВАЖНО (это даже и для примитивного sna несложно)

jerri
25.11.2024, 08:13
:v2_dizzy_tired2: еще раз: значит, сохраняй в тот момент, КОГДА состояние префиксов НЕВАЖНО (это даже и для примитивного sna несложно)

А вот это кстати самый правильный вариант

ZXMAK
25.11.2024, 22:53
ПРИМЕР в студию! ну хотя бы чисто теоретический, что такого ужасного и вселомающего может произойти конкретно ЗА ВРЕМЯ ВЫБОРКИ?

именно с этого примера и началась эта тема, см. первый пост.



еще раз: значит, сохраняй в тот момент, КОГДА состояние префиксов НЕВАЖНО (это даже и для примитивного sna несложно)

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

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

Lethargeek
25.11.2024, 23:29
именно с этого примера и началась эта тема, см. первый пост.
не подходит, не выполняется условие по исходным (а также не является примером "бага формата", а является примером ССЗБ)


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

Можно конечно просто запретить пользователю останавливать выполнение на длинных инструкциях, например занимающих 30 кБ памяти на одну инструкцию, чтобы у него просто не было возможности установить точку останова и остановить процессор в нужный момент. Но это не совсем правильно.
:v2_dizzy_wall: ЕЩЕ РАЗ:

значит, сохраняй в тот момент, КОГДА состояние префиксов НЕВАЖНО (это даже и для примитивного sna несложно)

- - - Добавлено - - -

и да, что эта тема вообще делает в разделе "ZX Spectrum Software"? даже тут неверно определил :D

ZXMAK
25.11.2024, 23:37
ЕЩЕ РАЗ: значит, сохраняй в тот момент, КОГДА состояние префиксов НЕВАЖНО (это даже и для примитивного sna несложно)

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

Проблема выше уже описывалась, возможно я недостаточно ясно её раскрыл. Попробую объяснить более понятным языком.

Для случаев с длинными префиксами в SZX предлагается трактовать их как "invalid", и такое префиксное состояние помечать флагом ZXSTZF_EILAST, при этом предполагается, что процессор всегда останавливается на "valid" префиксе.

Проблема возникает, когда эмулятор сохраняет снэпшот для такого "invalid" префикса, предполагая что после загрузки снэпшота выполнится префикс из текущей ячейки памяти и префикс восстановится. Для блокировки прерываний при этом взводится ZXSTZF_EILAST. Казалось бы всё хорошо. Но нет... После загрузки снэпшота и выборке следующей инструкции она может оказаться далеко не префиксом. Например если выборка приводит к триггеру переключающему память, как это происходит в адресном гейте TRDOS.

И баг формата SZX заключается в том, что "invalid" префикс который эмулятор видел на этапе сохранения, оказался вовсе не "invalid" префиксом, а очень даже "valid" префиксом. Однако информация о префиксном состоянии от предыдущего префикса после восстановления снэпшота потеряна, т.к. состояние префиксов в SZX не сохраняется. Поэтому после загрузки снэпшота процессор выполнит не префиксную команду, а команду без префикса, т.е. выполнит некорректный код.

Titus
26.11.2024, 00:17
Можно конечно просто запретить пользователю останавливать выполнение на длинных инструкциях, например занимающих 30 кБ памяти на одну инструкцию, чтобы у него просто не было возможности установить точку останова и остановить процессор в нужный момент. Но это не совсем правильно.
Это и есть совсем правильно)
Процессор не может остановиться посередине, а значит это самое правильное)
Кроме того, сколько тебе встречалось на практике программ, где 30 кб префиксов, и кто-то захотел это отладить? Причем так отладить, что шагать пошагово все эти 30Кб) Думаю, что ни разу)

ZXMAK
26.11.2024, 02:20
Это и есть совсем правильно)
Процессор не может остановиться посередине, а значит это самое правильное)

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

Процессору ничего не мешает остановиться после выполнения инструкции префикса, но до начала выполнения префиксной инструкции. Прерывание - да, в таком состоянии процессор не примет, также как и после выполнения EI.

Не зря же в SZX предусмотрен флаг для состояния после выполнения EI и "invalid" (или если более корректно выражаться - многократного префикса). Но, как описано выше, этот флаг не дает возможность всегда корректно сохранить снэпшот, т.к. подразумеват что при наличии многократного префикса состоянием префикса можно пренебречь, что на практике не всегда так...


Кроме того, сколько тебе встречалось на практике программ, где 30 кб префиксов, и кто-то захотел это отладить? Причем так отладить, что шагать пошагово все эти 30Кб) Думаю, что ни разу)

когда отлаживал multicolor не так уж и редко, может не 30 кБ, но помню были случаи где-то 10-20 кБ, а может и больше 30 кБ. К сожалению уже не помню название демки.

Titus
26.11.2024, 03:10
в таком случае если память забита префиксом снэпшот вообще невозможно сохранить - эмулятор будет просто зависать. Это уже серьезный баг.
Мы опять переходим к обсуждению, которое было выше)
1. Такой снапшот практически невозможен, только на клонах с ОЗУ вместо ПЗУ.
2. Такой снапшот никому не нужен, т.к. он полностью нерабочий. Это просто повисший компьютер с вечно зацикленным префиксом в памяти.

- - - Добавлено - - -


Процессору ничего не мешает остановиться после выполнения инструкции префикса, но до начала выполнения префиксной инструкции.
В смысле остановиться? Процессор неостановим в середине команды. Его можно остановить только ресетом или остановкой тактирования. Как и в середине любой другой команды.
Реакция на любые внешние раздражители в процессе выполнения команды (в том числе и сверхдлинной) у процессора отсутствуют.

- - - Добавлено - - -


когда отлаживал multicolor не так уж и редко, может не 30 кБ, но помню были случаи где-то 10-20 кБ, а может и больше 30 кБ. К сожалению уже не помню название демки.
Допустим, в мультиколоре у тебя стоит 20кб префиксов. Ну шагнул ты сразу в конец 20кб команды, и что такого? Это единая команда, в процессе нее не может произойти перерывания, нет смысла останавливаться.
Смысла не больше, чем остановиться внутри любой команды типа LD HL,nnnn. Давай и в ней останавливаться после опкода $21.

ZXMAK
26.11.2024, 06:03
Мы опять переходим к обсуждению, которое было выше)
В смысле остановиться? Процессор неостановим в середине команды. Его можно остановить только ресетом или остановкой тактирования. Как и в середине любой другой команды.
Реакция на любые внешние раздражители в процессе выполнения команды (в том числе и сверхдлинной) у процессора отсутствуют.


для эмулятора, где остановка не предусмотрена может и так. Я-же смотрю на это со стороны железа, которое при нажатии кнопки "цикл" запускает серию клоков до появления комбинации сигналов M1 & RD & MREQ. Другого варианта задетектить в железе начало цикла выборки инструкции вроде как нет. А для такой комбинации что префикс #DD, что #00 - одна инструкция.




Допустим, в мультиколоре у тебя стоит 20кб префиксов. Ну шагнул ты сразу в конец 20кб команды, и что такого? Это единая команда, в процессе нее не может произойти перерывания, нет смысла останавливаться.
Смысла не больше, чем остановиться внутри любой команды типа LD HL,nnnn. Давай и в ней останавливаться после опкода $21.

в одной из демок которую помню была длинная серия префиксов, потом nop и опять префиксы, прерывание срабатывало только если nop приходился на момент прерывания. ну и в таком роде, зачем там были длинные последовательности префиксов я не разбирался, меня интересовало чтобы прерывание приходило на нужном такте.

goodboy
26.11.2024, 11:42
юзер отлаживает код и вдруг решил пойти на обед,
позволь нам самим решать что делать.
каждый выбирает эмулятор под свои потребности.

Lethargeek
26.11.2024, 12:14
повторюсь, это невозможно,
:v2_dizzy_facepalm::v2_dizzy_facepalm::v2_dizzy_fa cepalm: ты вообще читаешь, что тебе пишут? и даже повторяют неоднократно! ЕЩЕ РАЗ, до полного просветления:

сохраняй в тот момент, КОГДА состояние префиксов НЕВАЖНО
почему вот у меня в эмуле (в котором тоже шаг отладчика - M1 любой, в том числе префиксы) и возможно, и (даже для sna) прекрасно работает?


Проблема возникает, когда эмулятор сохраняет снэпшот для такого "invalid" префикса,
а теперь, внимание, вопрос: а ЗАЧЕМ твой "эмулятор сохраняет снэпшот для такого "invalid" префикса"?
выдумал сам себе проблему на ровном месте, кто ТЕБЕ в таком случае мешает НЕ сохранять?

а в дебагере, допустим, пометить символом или цветом выделить ЗНАЧИМЫЙ префикс в такие моменты
сразу видно - сохранение заблокировано, для разблокировки нужно сделать шаг (одного достаточно)


И баг формата SZX заключается в том, что "invalid" префикс который эмулятор видел на этапе сохранения, оказался вовсе не "invalid" префиксом, а очень даже "valid" префиксом. Однако информация о префиксном состоянии от предыдущего префикса после восстановления снэпшота потеряна, т.к. состояние префиксов в SZX не сохраняется. Поэтому после загрузки снэпшота процессор выполнит не префиксную команду, а команду без префикса, т.е. выполнит некорректный код.
еще раз: НЕТУ никакого "бага формата", есть нарушение ТБ и простреленная нога :D

goodboy
26.11.2024, 12:19
есть нарушение ТБ и простреленная нога
и побличная демонстрация геморроя (который при правильном образе жизни не возникает)

Titus
26.11.2024, 13:47
для эмулятора, где остановка не предусмотрена может и так. Я-же смотрю на это со стороны железа, которое при нажатии кнопки "цикл" запускает серию клоков до появления комбинации сигналов M1 & RD & MREQ. Другого варианта задетектить в железе начало цикла выборки инструкции вроде как нет. А для такой комбинации что префикс #DD, что #00 - одна инструкция.

Исходя из твоей логики любая команда с префиксом - это несколько команд.
Например, $FD $CB xx. Тут аж три команды, и надо шагать это в три шага и уметь сохраняться после каждого префикса.

ZXMAK
26.11.2024, 17:29
Исходя из твоей логики любая команда с префиксом - это несколько команд.
Например, $FD $CB xx. Тут аж три команды, и надо шагать это в три шага и уметь сохраняться после каждого префикса.

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

- - - Добавлено - - -


а теперь, внимание, вопрос: а ЗАЧЕМ твой "эмулятор сохраняет снэпшот для такого "invalid" префикса"?
выдумал сам себе проблему на ровном месте, кто ТЕБЕ в таком случае мешает НЕ сохранять?


из практического использования - при отладке до тактов часто требуется сохранить программу в каком-то определенном состоянии. Например после выполнения первого 10-ка префиксов #DD из серии в 100 префиксов. И потом загружать этот снэпшот и отлаживать разные варианты кода, начиная выполнение с определенного состояния процессора и схемы в которой он используется. Другой вариант, я например хочу посмотреть счетчик тактов ULA когда процессор будет выполнять длинный префикс, но мне нужно видеть счетчик когда процессор будет выполнять префикс по определенному адресу, а не когда он закончит выполнять всю цепочку префиксов, которая может занять тысячи тактов...

- - - Добавлено - - -



а в дебагере, допустим, пометить символом или цветом выделить ЗНАЧИМЫЙ префикс в такие моменты
сразу видно - сохранение заблокировано, для разблокировки нужно сделать шаг (одного достаточно)


проблема в том, что "invalid" префикс который по документации SZX помечается флагом ZXSTZF_EILAST, после загрузки снэпшота и выполнения следующего шага очень даже может оказаться валидным и тогда снэпшот окажется битым, т.к. информация о префиксе сохранена не была.

Чтобы проверить тот ли это случай - нужно выполнить следующую инструкцию и если там еще один префикс, то следующую и так до бесконечности. Хотя пользователь не просил выполнять циклы, он просил сохранить снэпшот в том состоянии как процессор находится в отладчике в остановленном состоянии.

И если эмулятор не может сохранить текущее состояние вообще - это вообще плохо.

Lethargeek
26.11.2024, 20:53
Например после выполнения первого 10-ка префиксов #DD из серии в 100 префиксов.

проблема в том, что "invalid" префикс который по документации SZX помечается флагом ZXSTZF_EILAST,

Чтобы проверить тот ли это случай - нужно выполнить
ляяяяяяяя... походу этой ветке суждено стать рекордсменом по кол-ву постов с ":v2_dizzy_facepalm:"

я вот даже комментировать не буду всю эту ересь, пока ты чётко не ответишь мне (а главное - себе) на три довольно простых вопроса:

1) что такое, по-твоему "ЗНАЧИМЫЙ префикс"?
2) что такое, по-твоему, "НЕзначимый префикс"?
3) насколько безопасно сохранять снап после команды NOP?

ZXMAK
26.11.2024, 21:09
1) что такое, по-твоему "ЗНАЧИМЫЙ префикс"?

в контексте SZX - это последний префикс в серии префиксов.



2) что такое, по-твоему, "НЕзначимый префикс"?


в контексте SZX - это НЕ последний префикс в серии префиксов.



3) насколько безопасно сохранять снап после команды NOP?

вполне безопасно даже в контексте рассматриваемого вопроса, т.к. NOP не переводит процессор в префиксный режим. Т.е. нет риска потерять информацию о префиксном режиме.

Lethargeek
27.11.2024, 02:24
в контексте SZX - это последний префикс в серии префиксов.

в контексте SZX - это НЕ последний префикс в серии префиксов.
оба ответа неверные
во-первых "контекст szx" приплетать не надо, он ни при чём
во-вторых, незначимым может оказаться и последний префикс в серии
например: DD FD FD FD DD FD DD DD DD FD 53
и оказаться ровно по той же причине, что и предпоследний, и остальные
а теперь попытайся верно сформулировать - по какой именно?


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

Lethargeek
27.11.2024, 12:32
для предваряемой команды (и всей программы) вообще ничем от нопа не отличается
точней, для программы - может отличаться (во время INTR); но на то как раз и существует ZXSTZF_EILAST

- - - Добавлено - - -


Например, $FD $CB xx. Тут аж три команды, и надо шагать это в три шага
"FD CB +d xx" - и тут только два M1 (вот бы, кстати, разобрался, почему так)

Titus
27.11.2024, 12:34
(вот бы, кстати, разобрался, почему так)
В каком смысле почему?

Lethargeek
27.11.2024, 12:55
В каком смысле почему?
почему фактический опкод вместо M1 читается в обычном MR-цикле (хотя, может, и не совсем обычном)

Titus
27.11.2024, 13:24
почему фактический опкод вместо M1 читается в обычном MR-цикле (хотя, может, и не совсем обычном)

Опкоды читаются в цикле M1. Он только для этого и предназначен.
А байт смещения читается всегда в цикле M2, и опкодом не является, разумеется.
Причем, механизм его работы одинаков, что при индексной адресации (IX+nn), что при коротком переходе типа JR nn.

Lethargeek
27.11.2024, 13:48
Опкоды читаются в цикле M1. Он только для этого и предназначен.
а в M4 для "DD CB +d xx" тогда что читается, и почему точно такое же для "CB xx" читается в M1?

Titus
27.11.2024, 14:13
а в M4 для "DD CB +d xx" тогда что читается, и почему точно такое же для "CB xx" читается в M1?

Не понял твой вопрос)

DD и CB, и любые префексы и опкоды читаются в M1
M2 - это чтение смещения
M3 - это вычисление смещения
M4 - это чтение непосредственных данных

- - - Добавлено - - -

Циклы конечно многофункциональны, но в общих чертах так

ZXMAK
27.11.2024, 14:23
оба ответа неверные
ответ верный только частично - дело вовсе не в "префиксном режиме"


Не совсем ясно, почему вы берёте на себя роль судьи, оценивая, что "верно", а что "неверно". Думаю, было бы более корректно выразить своё несогласие, аргументировав его, например: "Я с вами не согласен, потому что...".

Во-первых, ваше заявление о "неверности" ответа в данном случае ошибочно. То, что вы упоминаете, не противоречит сказанному, а лишь дополняет его.

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

Lethargeek
27.11.2024, 14:31
Не понял твой вопрос)

DD и CB, и любые префексы и опкоды читаются в M1
M2 - это чтение смещения
M3 - это вычисление смещения
M4 - это чтение непосредственных данных
ладно, зайдём с другой стороны

каждый M1 увеличивает значение в R на единицу, так?
один префикс - это один цикл M1, так?

теперь два вопроса:
1) на сколько увеличится R после выполнения "CB xx"?
2) на сколько увеличится R после выполнения "DD CB +d xx"?

Titus
27.11.2024, 14:37
каждый M1 увеличивает значение в R на единицу, так?
один префикс - это один цикл M1, так?

теперь два вопроса:
1) на сколько увеличится R после выполнения "CB xx"?
2) на сколько увеличится R после выполнения "FD CB +d xx"?

Так.

R увеличивается только в цикле M1.

Ты сам себе ответил в вопросе) Сколько префиксов или опкодов на столько и увеличится)

- - - Добавлено - - -

Мне кажется, мы куда-то в сторону ушли)

- - - Добавлено - - -

Да, есть исключение именно в FD CB.
Тут код команды читается не в цикле M1, а в цикле M3.
Так что ты прав, это особый случай.

- - - Добавлено - - -

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

Lethargeek
27.11.2024, 14:57
Тут код команды читается не в цикле M1, а в цикле M3.
в M4 (в M3 адрес операнда вычисляется)


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

- - - Добавлено - - -

подозреваю, там вообще другая схема работает по сравнению с "нормальным" CB префиксом
но хотелось бы чётких подтверждений/опровержений и грязных подробностей от тебя))

Titus
27.11.2024, 15:05
в M4 (в M3 адрес операнда вычисляется)

Инициируется M3, заканчивается в M4.

https://pic.maxiol.com/images2/1732708854.1595414782.clipboard112720240.jpg

- - - Добавлено - - -


вподозреваю, там вообще другая схема работает по сравнению с "нормальным" CB префиксом
но хотелось бы чётких подтверждений/опровержений и грязных подробностей от тебя))
Да, там другая схема.
И на реверсе все это видно)

- - - Добавлено - - -


M4 - тоже четырёхтактовый, так что не поэтому
Дело не в четырехтактовости.
А в том, что в М1 много делается разного лишнего для регенерации памяти. В том числе блокируется использование блока 16-битного автоинкремента/копирования для основного набора регистров.
Т.е. в M1 этим блоком пользуются только PC и IR.
А тут нужна переброска WZ (со сформировавшимся адресом данных).
Думаю, что именно для этого и сделан такой дополнительный костыль.

ZXMAK
27.11.2024, 15:11
а в M4 для "DD CB +d xx" тогда что читается, и почему точно такое же для "CB xx" читается в M1?

в префиксном режиме CB уже не префикс, а инструкция, хоть и сложная :)

Lethargeek
27.11.2024, 15:15
Не совсем ясно, почему вы берёте на себя роль судьи, оценивая, что "верно", а что "неверно". Думаю, было бы более корректно выразить своё несогласие, аргументировав его, например: "Я с вами не согласен, потому что...
я всего лишь хочу устранить неоднозначности в определении ЗНАЧИМОСТИ префикса
для меня вот "значимый" - это который что-то ЗНАЧИТ для выполнения фрагмента
то есть от его присутствия или отсутствия (замены на ноп, например) может измениться результат
если результат в принципе НЕ может измениться - префикс НЕзначимый
(для упрощения пока считаем, что прерываний не случится за это время)


Во-первых, ваше заявление о "неверности" ответа в данном случае ошибочно. То, что вы упоминаете, не противоречит сказанному, а лишь дополняет его.
именно противоречит! было заявлено:

в контексте SZX (ЗНАЧИМЫЙ префикс) - это последний префикс в серии префиксов.
заявленный признак не является, ни необходимым, ни достаточным, так как найдутся контрпримеры в любую сторону
если префикс последний, он необязательно значимый; если значимый, то необязательно последний (...DD CB) :p

в контексте SZX (НЕзначимый префикс) - это НЕ последний префикс в серии префиксов.
то же самое


Во-вторых, ваш аргумент относительно второго пункта не точен. Инструкция NOP не переводит процессор в состояние, которое не может быть сохранено в формате SZX. Префиксы, напротив, действительно могут перевести процессор в такое состояние, так как SZX не сохраняет информацию о текущих префиксных режимах. Именно в этом состоит принципиальная разница между инструкцией NOP и префиксами в данном контексте.
еще раз: а для предваряемой команды - какая разница?
и зачем нужно сохранять состояние, которое далее заведомо не используется?

- - - Добавлено - - -


в префиксном режиме CB уже не префикс, а инструкция, хоть и сложна
любой префикс был и остаётся инструкцией :p

ZXMAK
27.12.2024, 19:03
еще раз: а для предваряемой команды - какая разница?
и зачем нужно сохранять состояние, которое далее заведомо не используется?

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

Обдумав варианты, решил остановиться на компромисном варианте. При остановке эмулятор пытается завершить префиксную инструкцию, если это не получается в течении большого количества тактов, то останавливает как есть. Таким образом минимизируется вероятность префиксного состояния, которое невозможно корректно сохранить SZX, в то-же время во время загрузки при наличии взведенного флага LAST_EI (который по документации взводится также и для префиксов), производится проверка предыдущего опкода в памяти, если это префикс, то восстанавливается префиксное состояние. Таким образом эмулятор по возможности сохраняет снэпшоты, которые однозначно будут загружены другими эмуляторами, но также при необходимости позволяет сохранить/восстановить и префиксное состояние. Правда такие снэпшоты не будут корректно работать на эмуляторах которые не поддерживают остановку в префиксном состоянии.

Хотя может кому-то ситуация со всей памятью забитой префиксом покажется нереальной, но вот например тест, который переводит ZX Spectrum +2/3 в такой режим:

Lethargeek
27.12.2024, 20:29
При остановке эмулятор пытается завершить префиксную инструкцию, если это не получается в течении большого количества тактов,
и как же это может не получиться, когда в одной инструкции в принципе больше двух неразрывных префиксов быть не может

ZXMAK
27.12.2024, 21:06
и как же это может не получиться, когда в одной инструкции в принципе больше двух неразрывных префиксов быть не может

например в тесте выше, который заполняет всю память префиксом. Вариант с предварительной проверкой префиксов наперед чреват тем, что память может внезапно измениться, например при попадании в окно TRDOS.

Например имеем последовательность DD DD 00. Прцессор выполнил первый префикс DD, затем эмулятор остановили и сохранили снэпшот, затем при загрузке при чтении следующего DD сработал гейт и вместо DD прочиталось 21. Однако состояние предыдущего префикса потеряно при сохранении в SZX.

Lethargeek
27.12.2024, 21:19
Например имеем последовательность DD DD 00. Прцессор выполнил первый префикс DD, затем эмулятор остановили и сохранили снэпшот, затем при загрузке при чтении следующего DD сработал гейт
1) с чего бы ему сработать после загрузки, но не сработать после сохранения точно так же?
2) ну, считай, что не выполнял первый тот DD, всё равно он равносилен нопу, откатить можно

ZXMAK
27.12.2024, 21:38
1) с чего бы ему сработать после загрузки, но не сработать после сохранения точно так же?

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


2) ну, считай, что не выполнял первый тот DD, всё равно он равносилен нопу, откатить можно

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

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

Lethargeek
27.12.2024, 21:55
до сохранения процессор с взведенным флагом префикса. После загрузки это состояние не сохраняется и процессор будет выполнять инструкцию как обычную не префиксную.
ну при чём тут ФЛАГ, да еще такой, которого внешние устройства не видят?
я спросил, с чего бы ГЕЙТУ сработать в одном случае и не сработать в другом?
при совершенно одинаковых вводных-то


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

- - - Добавлено - - -

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

- - - Добавлено - - -

иными словами, функция выборки должна быть повторяема любое кол-во раз для данного состояния и не изменять само состояние

ZXMAK
27.12.2024, 21:59
ну при чём тут ФЛАГ, да еще такой, которого внешние устройства не видят?
я спросил, с чего бы ГЕЙТУ сработать в одном случае и не сработать в другом?
при совершенно одинаковых вводных-то

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

- - - Добавлено - - -



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

иными словами, функция выборки должна быть повторяема любое кол-во раз для данного состояния и не изменять само состояние

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

Lethargeek
27.12.2024, 22:10
у меня две функции выборки - одна для полноценного выполнения с учетом всех переключений и задержек, вторая - просто читает память при текущем состоянии,
для предсказания значимости префикса задержки тебе не нужны, а переключения - предсказуемы (ДОЛЖНЫ быть, если нет - время задуматься о перепроектировании модели)

ZXMAK
27.12.2024, 22:27
для предсказания значимости префикса задержки тебе не нужны, а переключения - предсказуемы (ДОЛЖНЫ быть, если нет - время задуматься о перепроектировании модели)

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

Lethargeek
28.12.2024, 11:06
для этого прийдется связать код логики процессора и конкретных устройств,
не надо ничего связывать, наоборот, надо модули перепроектировать так, чтобы хотя бы некоторые действия отвязать от изменения состояния

ZXMAK
28.12.2024, 17:47
чтобы хотя бы некоторые действия отвязать от изменения состояния

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

Lethargeek
29.12.2024, 12:29
они и не связаны. Есть два метода для чтения памяти
именно, что "чтения", а НЕ выборки! еще раз:

у меня две функции выборки - одна для полноценного выполнения с учетом всех переключений и задержек, вторая - просто читает память при текущем состоянии, ничего не меняя - она используется в отладчике.
у тебя ОДНА функция ВЫБОРКИ, которая и ДОЛЖНА быть "с учётом всех переключений и задержек"
вот ЕЁ тебе и нужно доработать и разделить - чтение "с учётом" отдельно, изменение состояния - отдельно
а вторая, которая "просто читает память" - это НЕ выборка, и вообще даже не часть эмуляции