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!