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.