SuperCPU rayed - Episode 7

IRQ programming with the SuperCPU
Where is the vector? We are reminded of a very early course section: it was about Native and emulation mode. The Native mode is not about how could initially , for the new commands needed - namely the work also in the emulation mode (this is also the reason why illegal Opcodes do not work). However, in order to be able use 16 Bit-Akku and index register , you will have to turn on every case in the native mode. Here the developers have of the 65816 new vectors for the interrupts. The most important thing, the for the IRQ is located in the Native mode no longer at $FFFE/ $FFFF, but at $FFEE/ $FFEF. But what is all this? Apparently it has the development thought in advance (well, it's a pity that something like that is seldom the case today only): in Native Mode the battery you can at any time as well as the X- and Y-registers between 8 and 16 bit mode. An interrupt routine must be able deal with registers in both conditions - finally they must be saved, if the IRQ-routine be used! There is therefore a different IRQ for the Native Mode vector, so that one can switch between the two modes, if you accordingly, depending on the respective mode a concerted IRQ-routine ready. Let us recall a very early part of the course: It was about Native and Emulation mode. The native mode is not about how to initially assume could, required for new commands - the work namely in Emulation mode (which is not the reason why illegal opcodes can work). However, by 16 bit accumulator and index register to use can, you have to switch to native mode in any case. Here, the Developers of 65816 provided new vectors for the interrupts. The most important, which is not in native mode for the IRQ at $ FFFE / $ FFFF, but at $ FFEE / $ FFEF. But what's all this? Obviously it has in itself made in advance of the development of thought (shame that something today only rarely the case): In native mode, you can always switch the accumulator as well the X-and Y-registers between 8 and 16 bit. Here an Interrupt routine must be able to cope with registers in both states - after all these must be saved if they used in the IRQ routine! Therefore, there is for the Native fashion a own IRQ vector, so you can, if you between the two modes switches, each one according to instructions depending on the mode IRQ routine ready. Yes, but ...? But for crying out loud what is with the good old vector at $ 0314/ $0315, but otherwise the man always for IRQ-programming has used? The one could forget. In truth namely the 6510 jumps to the address in a IRQ always , in $FFFE/ $FFFF is saved. And the shows to the Rome - this is where the tabs are saved, and only then is about $ 0314/ $0315 jump. You surely remember: before each switch in the Native mode so far, we have always carried out, and the CLI was a first came back again, if the processor was in emulation mode. However, these were not as solid in native mode, because no interrupts are possible, but for a different reason : as already described, the IRQ-vector in Native Mode with $FFEE/ $FFEF. The ROM is usually displayed, and - you sense it probably already - what is in $FFEE/ $FFEF in Rome? The address $E505, an operand to a JMP-command, a Betriebssystemroutine to Screen-Spalten - and Zeilenermittlung starts. In short: determines any IRQ -routine - even as it? Commodore 1982 could still know nothing of 65816 (the was released), but it was not until 1985 that this processor time thing that bothered ancestors in a unit called SuperCPU to your original C64 would be used. We must therefore either the IRQ lock in Native Mode, or the ROM with LDA # $35 STA $01 hide and an IRQ-routine letter. Where this is located, we then write to $FFEE/ $FFEF. But what the hell is with the good old vector at $ 0314 / $ 0315, which one but otherwise always for IRQ programming has used? That can safely forgotten. In truth, namely the 6510 jumps at a IRQ always adhere to the Address $ FFFE is stored in / $ FFFF. And the shows into ROM - there the registers are saved and only then is about $ 0314 / $ 0315 jumped. Surely you remember: Before changing the native mode we have have always executed a SEI and CLI only came back when the Processor in emulation was fashionable again. But this is not as pulled through, because in native mode interrupts are not possible, but from another reason: As already described is the IRQ vector in Native Fashion at $ FFEE / $ FFEF. The usual approach, the ROM is visible, and - you guessed it probably - what is at $ FFEE / $ FFEF in the ROM? The address $ E505, an operand to a JMP instruction, the to an operating system routine Screen column and row identification starts. In short: Definitely no IRQ routine - how could they? Commodore was in 1982 but still nothing from 65816 know (which was only released in 1985) suspecting, let alone that this Processor time in a device called SuperCPU used at their original C64 would be. Thus we must in native mode either the IRQ lock, or but the ROM with LDA # $ 35 STA $ 01 Hide and an IRQ routine . Write Where this is, we then write down $ FFEE / $ FFEF. Here we go The main problem with IRQ routines in native mode is the fact that the Interrupt at any time to interrupt the main program, regardless of whether this currently working with 8 or 16 bits. The IRQ routine saves the registers - the Push commands work always the same, whether you 8 or 16 bits wide Register pushes, or those stores with STA somewhere. But then you want to of course also perform some operations, and since it bothers but then, not knowing whether the accumulator and / or the index register just 8 or 16 bit are - after all, would a LDX # $ 00, executed at slaked X flag (Index registers are 16 bits) lead to chaos, since the command byte after would the $ 00 yet with added taken to form the 16-bit value. Then there will be a more or less fatal crash. But it is nothing easier than the registers to shift the way they have wants - after all, there are the commands REP and SEP which is the 16 Bit flags and delete can put. So far, so good - the IRQ routine is processed and you can switch between modes kicking back and forth. Slow approaches the interrupt routine to an end and we a problem. Because the Registers must be restored, either as 8 - or as 16 bit registers! Bypass? Of course, there's an easy possibility to circumvent the whole problem - just for demos or intros, this is certainly an acceptable way: One omitted simply on a main program and laesstt everything is interrupt. After the initialization part followed only a JMP to itself - who does not need register, so we must not save them in the IRQ, let alone us at 8 or 16 bit modes worry. The direct solution But suppose we do not leave anything in the main program frame-oriented calculate or whatever, so that we solve the problem solve instead want to avoid. As we can now command the register is 100% again produce? In order modes recovery but we do not need to us take care, because the flags are indeed at an IRQ automatically on the stack saved and the interrupt end (RTI instruction) back retrieved. For us but unfortunately too late, because we would have previously been very interested to see what State of the M and X flags (for accumulator and index register) had. And here is the key to a solution: At the beginning of the IRQ routine after the register are already on the stack (according to their modes also correct), we save us just continue the status register with all EMTeachline Flags - command PHP. At the end of the IRQ routine now before the registers with Pull restore commands again, we take this saved status with PLP again from the stack - and M-and X-Flag are back in the State that they had at the time the IRQ trigger. So we can safely be that the subsequent pull-instructions exactly the right number of bytes get for the corresponding register from the stack! Yes, and that's about it - The problem is solved. Now you can in the main program anywhere between 8 and 16-bit switch, without being forced to worry that after an IRQ maybe some high bytes are lost of 16 bit registers. Raster interrupt For habitually will be the IRQ, as suggested by the operating system, about a CIA-timer can be triggered, but instead by the VIC - at a certain raster line. When CIA you have to confirm with a LDA $ DC0D that the IRQ was received and processed - that's what makes the Kernal at $ EA7E. In VIC it works differently: You have to interrupt with LDA $ D019 STA $ D019 confirm. Confirmed to an interrupt - whether CIA or VIC - not, immediately after the IRQ routines-end immediately in the Jumped IRQ routine, because the C64 thinks the interrupt would have to still are processed. Instead of LDA $ D019 STA $ D019 using many Coder However, a DEC $ D019, $ D019 ASL or LSR $ D019 - do the same thing, only it is shorter. In native mode of the 65816, however, reveals a Curiosity, for which we also could not find any explanation: The DEC, ASL or LSR variant shows to $ D019 no effect - you have already LDA STA take. Hair Exactly the same routine that still worked in emulation mode goes, when the native mode and IRQ vector at $ FFEE / $ FFEF no more. The "cleaner" LDA $ D019 STA $ D019 is the one worry though again going on. Please wait Many interrupt routines to a specific operation on a specific Raster line Run. Let us take the simple example of a Rasterbar. Here we wait for a raster line, timen with a short loop until we are exactly at the end, and then quickly Change $ D020 and $ D021, thus, when the VIC begins to draw the nearest grid line, that in a other color appears. Then we wait again until shortly before the end of the line and amend again, according to a color table, frame and Background color. As a special uebel the Charline (Badline) has proved thereby, since the VIC reads data from the screen and color RAM, but some time needs and we therefore somewhat less than usual on hold must hang until the next raster line is reached. Almost every Assembler entrants are these raster beam an abomination, because until you has understood why when you have to wait much, sometimes takes some Time. Time also goes by the way, when we service the C64 until the Raster line is over. About Taking the entire screen with Grid bar, no longer even large jumps remains much screen time, to make - and on hold while the beam structure is in each case short that only real professional coders in there still accommodate routines. More than 20 times faster? With the SuperCPU one could now of course, the 20-fold amount of Schleifendurchlaeufen wait, and would have also Gorgeous grid beams. But There is another possibility, and we even get a very large portion of the computing time, which is otherwise maintained, free for the Main program! The SuperCPU is namely so fast that they at the beginning of Raster line can alter the colors in time. One must not, as is usual, already at the end of the previous grid line with its LDA from the Color table to start, so you have time for the start of the new Wrote raster line the value after $ D020/21. We leave the interrupt just come on the line, where we want the first color, and Write this in the VIC registers. After that we very, very much Calculation time for the next raster line is reached and the next color must be set. So we tell the VIC simply that he next in the Raster line us again to say about it (an IRQ Release) so that we then can put the next color. We provide the Registrar restores and leave with RTI interrupt routine! Now available to the main program Tons of clock cycles at disposal, for the calculations or similar can be used. Meanwhile draws the VIC at rest the raster line. Starts the next, the IRQ routine is called again, we Change quickly the color and give control back immediately return to's Main program. The wait for the next raster line is completely eliminated, Thus, computation time is free. Waerde you Saemtliche existing raster lines of the C64 pull over with scanning beams, so would not have time at 1 MHz uebrigsein to do anything else because of poor computer mostly on the next raster line waiting. With the SuperCPU but we have the same Case for about 80% of computing time or more left (only one rating)! The sample program In Listing 7.1 Your whatâ everything explained here again see. First of is turned the native mode and initialize the IRQ. Then, in a Endless loop as the main program constantly 8-16 bit back and hergeschaltet. To check is in 8-bit mode, the address $ D800, which is the color of the sign above the left increases. Because this is done in 8-bit mode, likely never be $ D801 affected, but this would be the case in 16 bit mode. On these we then switch to namely and increase $ 0400 - is this Address to $ FF is automatically incremented $ 0401. The IRQ can therefore at any time be triggered - in 8 - or 16-bit mode. In the IRQ we save Then, the register, using the routine itself, as well as the status to later the registers according to regulations to be restored again. Then we turn the index register to 8, the accumulator pack to 16 bit. Retrieve from a color table we deal with a LDA at a stroke two values ??we after $ D020 (and of course write down $ D021). Reminder: A LDA # $ 0102 STA $ D020 causes the $ 02 will be written by $ D020, while the $ 01 lands logically in $ D021. Then we raise $ D012, which is the Grid line where the next IRQ will be triggered. Of course, we turn before the accumulator again increased to 8 bits, otherwise would also $ D013, which we certainly not necessarily want. The mixture is then queried whether we end up our Rasterbar have arrived - if so, we let the next interrupt again until the beginning of the Rasterbar auslaesen (for the next frame). For Conclusion is communicated with LDA $ D019 STA $ D019 the VIC that we its IRQ have received and processed - why, for example ASL $ D019 does not work remains unexplained. By the way: If you in the main program frequently with 16 bit works, kaennte the IRQ come too late a little, since the 16 bit instructions (although they make the double work) usually one clock cycle need more. But through clever programming of the IRQ routine lets itself the offset - our example is by no means represents the ultimate solution

(w) Malte Mundt
©1999 Go64 Redax! & Count Zero/SCS*TRC for all HTML Stuff

[ Zum 6. Teil ][ Zum Index ][ Zum 8. Teil ]