Treatise on Emulators (2 from 3)
ZXNet echo conference «hardware.zx»
From Kirill Frolov → To All 25 March 2000
================================================================================
* Forwarded by Kirill Frolov (2:5030/946.25)
* Area : RU.PHREAKS (Unknown area)
* From : Ivanov Arthur - lead.engineer, 2:5020/400 (24 Mar 00 20:55)
* To : All
* Subj : Treatise on Emulators (2 from 3)
================================================================================
From: "Ivanov Arthur - lead.engineer"
Sending the following bit to the output:
a.) Immutable data from ROM
inc r0 - increase by one address counter
mov a,r0
movp3 a,@a - read byte from built-in ROM
outl p1,a - the desired data bit at output p1.0
the remaining bits of port p1 are not connected anywhere
let them change as they please
b.) Changeable data from RAM
inc r0 - increase by one address counter
mov a,@r0 - read a byte from the built-in RAM
outl p1,a - the desired data bit at output p1.0
Now the algorithm needs to somehow determine which byte to read from RAM and
which ROM? In each byte we have 7 orphan bits left. Let
one of them /for example the first one/ determines the status of the data - if it
reset, then the data must be looked for in RAM, and if set, in ROM:
inc r0 - increase by one address counter
mov a,r0
movp3 a,@a - read byte from built-in ROM
jb1 ROMRAM: mov a,@r0 - read a byte from the built-in RAM
ROM: outl p1,a - the desired data bit at output p1.0
The Write operation is very simple:
anl p1,#0feh - reset the Out line to zero
inc @r0 - since the bit was deliberately set before Write,
then after inc it will obviously be reset.
The WriteCarry operation also looks like nothing for the 10 ms allotted
for her. Since eight bits were known to be zero before WriteCarry,
eight incs will make them obviously single -
mov a,r0 - current address counter
anl a,#0f8h
add a,#8 - the beginning of the eight bits /tray of the 8-point abacus/ is calculated
mov r1,a
inc @r1
inc r1
inc @r1
inc r1
inc @r1
inc r1
inc @r1
inc r1
inc @r1
inc r1
inc @r1
inc r1
inc @r1
inc r1
inc @r1
In short, you will see the source text of what happened in the tail
this document. The program produced features by itself, significantly
necessary for the emulator, for example, the presence of a 512-bit data ring.
A real card has a 9-bit address counter and it easily overflows.
True, we ended up with a 256-bit ring. But since there is 256-bit, then
and 512-bit is also available.
The resulting program has quite good timing
characteristics. Upon arrival of Clk, the output data appears later
9-13 processor cycles. For 11 MHz quartz this is after 12-18 µsafter the front Clk. Quite a decent result for such a wretched
architecture. This is only 2-3 times worse than what you can get on
PIK-e. However, for some types of payphones this is quite enough.
By the way, the i8049 processor has 128 bytes of built-in RAM, as opposed to 64
byte for i8048. Therefore, when initializing the program, you can move
ALL data is in RAM. As a result, the performance of the read operation can be
win 2 more beats. Switch reading data from ROM to RAM and back
will no longer be necessary.
Read: mov a,r0 - current address counter
inc a - its increase
anl a,#7fh - the ring should now be 128-bit
mov r0,a
mov a,@r0 - reading from RAM
outl p1,a - data bit to output
But, out of principle, I wrote code that would work on any processor
MCS-48 family.
And now a couple of non-trivial tips for programming single-crystal chips.
Completely forget how you were taught to program. The program is needed
write in such a way that Dijkstra /founder of structured programming/,
Having read it, I would have fainted. And season it with a generous portion
crazy. There is a sign that programs for this kind of thing, written without
bits of crazy don't really work. On some architectures, especially
Intel's, without perversions - no way.
For example, in our program the part of the data corresponding to the card creditcopied to RAM. Moreover, these data completely cover the area
stack. But, since I do not call subroutines and interrupts anywhere
I'm banned, so what's wrong?
The card dump in the program is not in order, but wrapped in a ring,
using the fact that the address counter r0 overflows
/more precisely lies half wrapped in a ring, or
wrapped in a half ring, as you prefer.
As a result, it is possible with only two teams
mov a,r0
jb7 Failure
distinguish between an attempt to write to the units area and an attempt to write to
Manufacturer Area. The payphone does this as a counteraction
emulators.
This highlight with the ring requires, willy-nilly, to organize another -
addresses 0 and 1 are used simultaneously and as working registers r0 and r1,
and as cells for storing two bits of credit card. The trick is that
card dump bits assigned to these cells /two most significant bits of credit/
must always be zero, since there are no cards with more credit
than 7*4096-1=28671 units. And whenever r0 and r1 are addressed as
keepers of melon cards, they end up with the least significant bit zero!
How does this happen?
Register r0 is used as an address counter /pointer/. When should he
happens to point to itself, it will naturally be equal to zero, and
This means that its least significant bit will be zero.Register r1 is always, after use, -
anl a,#0f8h ; a.0 <-- 0
add a,#8 ; a.0 = 0
mov r1,a
8 times inc r1
has the least significant bit zero. Q.E.D.
My advice is to never comment on such places in the algorithm. From them
a special transcendental energy emanates, which is favorable
affects payphones. The comments completely neutralize this
beneficial effect, leading to the dissipation of the aura surrounding the emulator.
It has been repeatedly noted that this aura, in addition, has a strong
impact on the analytical abilities of some "correct"
programmers who find themselves powerless to understand the source code from
about a dozen lines, because the transcendental force is blocking them
brain when they reach the key points of the algorithm. This protective
strength, helps to preserve the meaning of your programs from prying eyes.
Apply all known techniques to optimize programs. Expand
cycles completely or partially. Anyway, the firmware will only take a short time
part of the microprocessor's internal ROM. There is enough space, and the expanded cycle
will be completed much faster, because it will not be spent
precious time to check the conditions and transfer. Consider that in
The processor command system lacks the djnz command. Her place is in yours
The assembler directive REPT should be in the arsenal.If you still feel the urge to use djnz, then remember Stalin’s order
"Not a step back!" djnz should point FORWARD and ONLY FORWARD!!!
Otherwise, if you had your way, you would spin the cycle back and stop asking
signal lines until it ended.
Everything in the program must be done AT THE SAME TIME!
Here is an example of "Transparent" loop execution:
mov r7,#0
ProgramMainLoop:
line polling and reaction to events
if you need to start a cycle, then mov r7,#number_repetitions
inc r7
djnz r7,Loop - forward loop
jmp AvoidLoop
Loop: loop body
dec r7
AvoidLoop:
polling other lines and reacting to other events
jmp ProgramMainLoop
The response to events is carried out promptly.
The Loop cycle is executed HIDDENLY.
The main loop of the program rotates CONTINUOUSLY.
In general, the algorithm is like a hose buried in the ground.
When writing a program, you should always carefully study the state of
the processor is located after startup. And make the most of it
default state. In this case, however, it is only used
the fact that at startup register bank 0 and interrupts are selected
prohibited. But, in more sophisticated controllers there are a lot of flags,
governing its regimes. There is no need to waste time initializing them,
if the processor reset mechanism did it for you. For example, in PIK-e,
at startup, the OPTION register is equal to FF. Make sure this is exactly whatneeded for the emulator :)
As an example, I will give this algorithm. Let's assume you need
make not a battery card, but one powered by a payphone. Then the cycle
transferring data from ROM to RAM at the beginning of the program becomes a problem for you
throat. It significantly increases the start time of the emulator. But copy that
necessary. Conclusion - it is necessary to organize “transparent” copying. To the bits
copied from ROM to RAM as data was read by the payphone. And when
the last bit needed will be copied, some flag should
latch and the program should take data from RAM. Let's use that
the fact that flag f0 in the processor status word turns out to be
reset after power is applied. We organize the data like this - 0 and 1 bits
exactly the same as they were / information bit and its status
respectively/, bits 2-4 and 6.7 are zero. And bit 5 will be in all bytes
zero, except for one /the last one of which must be copied/.
org 300h
db 0,0,0,0,0,0,0,0 ;*4096 U a in
db 0,0,0,0,0,0,0,0 ;*512 n r this
db 0,0,0,0,0,0,0,1 ;*64 i e case
db 0,0,0,0,1,1,1,1 ;*8 t a 100
db 0,0,0,0,1,1,1,21h ;*1 s units
db 3,3,3,3,3,3,3,3 ;FF Unused FF
db 2,2,2,3,3,3,3,3 ;1F Certi-
db 2,2,2,3,2,2,2,2 ;10 ficate
etc.
During the first reading of the card by a payphone, the program will copybytes not only in RAM, but also in the processor status word. At the same time,
We won’t do anything military with PSW. Well, let's move the stack pointer,
well, to hell with it. Resetting bits 2-4 and 5.6 pws to zero also benefits us. But,
when the last byte needed is copied, its fifth bit is set
will fit right into the f0 flag. And this checkbox will click.
org 0
Start: ;f0 = psw.5 is cleared after microprocessor startup
Reset: orl p1,#1
mov r0,#0c0h
jt1$
MainLoop: jt1 RstHigh
jnt0 MainLoop
Read: inc r0 ;increment address counter
mov a,r0
movp3 a,@a ;read from ROM
jb1 StaticData
jf0 DataInRAMAlready
mov @r0,a ;write to RAM
mov psw,a ;and also in the processor status word
DataInRAMAlready: mov a,@r0 ;read from RAM
StaticData: outl p1,a ;send bit to Out line
etc.
The "transparent" copying turned out to be very elegant.
Please note - as a result, there is NO SECTION LEFT in the program AT ALL
INITIALIZATIONS! The code that performs the operation begins with the Reset label
Reset /reset the address counter/card. That is, the program
starts with code that will be constantly used during work
emulator. Optimization of the initialization section ended with the achievement
absolute. The limiting case, so to speak. The fee for it is somefour extra processor cycles to process Clk when reading the card for the first time
and only two measures in subsequent ones.
This topic can go on and on.
But, for starters, I think that's enough.
Now, I hope, there will be fewer idiotic questions “How to make an emulator”.
T V O R I T E! ! !
-+- ifmail v.2.15dev4
+ Origin: UNKNOWN (2:5020/400)
================================================================================
Press RESET immediately, All!