PROCESSOR GLICK (2/2)
ZXNet echo conference «code.zx»
From Kirill Frolov → To All 27 November 1998
Hi, All!
Continuation of the subject:
===================================================================================
=
7. Final confirmation
──────────────────────────────
Let's check this fact. Let the interrupt handler determine
where the program was interrupted. If it was interrupted
exactly after the command LD A,R, let the curb for a while
will turn yellow:
ORG #6000
LD HL,#8000
LD (HL),#81
LD DE,#8001
LD BC,#100
LDIR
LD A,#80
LD I,A
IM 2
EI
M1 CALL SUBR1
JR M1
SUBR1 LD A,R
BP1 RET PE
LD A,4
OUT(254),A
LD HL,0
LD DE,0
LD BC,#600
LDIR ;WAIT
XOR A
OUT(254),A
RET
ORG #8181
EXX
EX AF,AF'
POP HL
PUSH HL
LD DE,BP1
AND A
SBC HL,DE
JR NZ,NE_BP1
LD A,6
OUT(254),A
LD HL,0
LD DE,0
LD BC,#600
LDIR ;WAIT
NE_BP1 EXX
EX AF,AF'
EI
RET
If the incorrect operation of the LD A,R command is not due to
that during its execution an interrupt pulse arrives, then wewe will see how the upper part of the border will blink in green
that, then yellow. But if the connection between these two events is
exists, then we should see the top of the border blinking
it is yellow, and the lower part is green, and they should
blink perfectly synchronously.
I launch it and see exactly what I expected. Action
Indeed, such a connection exists:
┌─────────────────────────────────┐
│▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓│
│▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓│
│▓▓▓▓ ▓▓▓▓│
│▓▓▓▓ ▓▓▓▓│
│▒▒▒▒ ▒▒▒▒│
│▒▒▒▒ ▒▒▒▒│
│▒▒▒▒ ▒▒▒▒│
│▒▒▒▒ ▒▒▒▒│
│▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒│
│ │
└─────────────────────────────────┘
But how can interruptions and the operation of the LD command be related?
A,R? This command places the contents of the interrupt trigger into the P/V flag.
Vaniya IFF2. When interrupts are enabled, this trigger is 1, and
when the interrupt pulse arrives, it automatically resets
is set to 0 to prevent repeated interrupt processing. But about
interrupt request processing begins during executionthe last clock cycle of the instruction being executed (i.e., the LD A,R instruction). And,
Apparently, the already reset IFF2 trigger is copied to the P/V flag
(indeed, from the point of view of the processor, interrupts at this moment
ment are already prohibited).
All of the above also applies to the LD A,I team. Given information
The formation was tested on the original Z80 processor from ZI-
LOG and on the domestic analogue KP1858VM1.
8. What does this lead to and what to do?
────────────────────────────────────
Using the LD A,R and LD A,I commands to determine the status
The interrupt trigger is, generally speaking, used in many applications.
grams (and even in TR-DOS ROM). Here's an explanation for some
number of strange freezes. It seems as if the probability of their coming
interrupt pulse precisely during the execution of the LD A,R command
great. But, firstly, the probability increases due to the fact that
that this command can be executed more than once in the program (and for
a single incorrect execution is enough to freeze), and,
secondly, if the program previously contained the HALT command,
i.e. synchronization with interrupts, it may happen that
the LD A,R command will be executed each time at the time when the most
more likely another interruption (this was the case in BestView).
So this method is not reliable. But what can we do? It turns out
you can determine the state of the interrupt trigger with 100% accuracyaccording to the following simple rule:
- execute the command LD A,R;
- if the P/V flag = 1, it means that interrupts are indeed
allowed;
- if the flag P/V = 0 - or interrupts are actually disabled,
or they are allowed, but the LD A,R command set it incorrectly
flag. To eliminate the uncertainty, we perform again
command LD A,R. If now the flag P/V = 0, it means
interrupts are disabled (in fact, it cannot be so,
so that during the execution of the second command LD A,R it occurs
interrupt - 1/50 of a second passes between two interrupts,
and between two commands LD A,R - much less time).
If the P/V flag = 1, then interrupts are enabled.
Here is the relevant program fragment:
SUBR1 LD A,R
JP PE,M1
LD A,R
M1 PUSH AF
D.I.
....
POP AF
D.I.
RET PO
EI
RET
9. How can this be used?
──────────────────────────────
Using the LD A,R command it is convenient to test the pro-
processor to recognize that the program is running under the emulator.
The emulator executes Z80 commands sequentially, one after another,
and the LD A,R command will always set the P/V flag correctly.
But in the real Z80 this is not the case.
Here is the simplest procedure for testing a processor that
paradise returns in accumulator 1 if it is running on realZ80, and 0 otherwise. She tries 65536 times to read
register R when interrupts are enabled, and if at least
once the P/V flag is set to 0, it is concluded that the procedure
ra works on a real Z80.
TESTZ80 EI
LD BC,0
M1 LD A,R
JP PO,QUIT
INC B.C.
LD A,B
OR C
JR NZ,M1
RET
QUIT LD A,1
RET
If the emulator is recognized, you can either stop executing
installation of the program (a kind of protection), or disable some
sections of the program that may not work correctly under the emulator
(for example, instead of working directly with VG93, use the entry point
#3D13, etc.).
10. STS 6.2 fix
───────────────────────
In the well-known STS debugger, determining the trigger state
interrupts also occur using the LD A,R instruction. Because of this-
The program may not be traced correctly. When
trace STS runs every command (except send commands
management) with the help of a resident, and after completion of its execution
remembers the contents of processor registers and the state of the trigger
interrupts. This is where mistakes are possible.
Let’s say interrupts are enabled and the following simple
Our program:
#8000 NOP
#8001 JR #8000
By stopping tracing after some time (with theoption Indicate one minute is enough), we will see that
interrupts were disabled. If the real
program, such interrupt disabling could have an impact on
the entire course of its further execution and even lead to a freeze
(if the HALT command were encountered during tracing).
It is clear that corrections need to be made to the STS. Here
how to do this for version 6.2:
First you need to launch STS and load the file "sts6.2
", in which the corrections will be made.
Then you need to find the free 14 bytes - their purpose will be
explained below. You can use the user function buffer (with
addresses #FE37). But in the version of STS that I use, this
the buffer is occupied by the disassembly procedure with assembly marks
ra ZX ASM, so I decided to shorten some text messages
nia:
'Block' -> 'Bl.' (2 bytes saved)
'Save' -> 'S.' (----/----- 2 --/--)
'Load' -> 'L.' (----/----- 2 --/--)
' DEFB' -> ' ' (----/----- 4 --/--)
'FileName' -> 'Name' (----/----- 4 --/--)
To do this, from address #EB24 you need to enter the following sequence:
byte capacity:
#EB24: AE 46 72 6F ED 54 EF 46
#EB2C: 69 6C E5 53 65 63 74 6F
#EB34: F2 53 AE 4C AE 53 74 6F
#EB3C: 70 20 69 E6 42 61 6E EB
#EB44: 51 75 69 F4 54 72 61 63
#EB4C: E5 53 74 61 72 F4 44 69#EB54: 73 61 73 ED A0 46 69 6C
#EB5C: E5 42 41 53 49 C3 20 44
#EB64: 4F D3
At address #E702 we replace the value #0A with #0E to correct
but the file name was printed (because instead of the line FileName there was
just Name).
So, now 14 bytes are free from address #EB66. Let's see where in
STS determines the state of the interrupt trigger:
#DFFE: LD (#5BA1),SP
LD SP,#5BA1
PUSH BC
PUSH AF
LD A,R
D.I.
LD BC,#7FFD
LD A,#1F
OUT(C),A
LD B,#BF
LD A,#00
OUT(C),A
JP#E028
Let's replace the commands LD A,R: DI with NOP, and the command JP #E028 with
JP #EB66. From address #EB66 we will place the following fragment:
#EB66: LD A,R
JP PO,#EB6E ┐
NOP │
┌─ JR #EB70 │
│ LD A,R <───┘
└>DI
JP#E028
Please note - this fragment, in any case, with its
operation increases register R by the same amount (by 7). Case
is that another command LD A,R will be executed next, on
this time it is needed to determine the value of register R, and it will be
The resulting value has been corrected because value re-
gistra R increases with each executed command, but it is necessary tofind its value at the end of the traced execution
teams. This is what it looks like:
#DCA2: LD A,#5A
LD HL,#FEF4
SLA (HL)
R.L.A.
ADD A,(HL)
RRCA
LD(HL),A
RET
Constant #5A at address #DCA3 should be replaced with #53, i.e.
reduce by 7 - after all, an additional one was added to the program
fragment that increases register R by 7, and needs to be compensated
this is a change.
After this, all that remains is to write the modified file to
disk.
* * *
===================================================================================
=
THE END
With best wishes, Kirill Frolov.