mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-12-28 16:31:36 +00:00
Fixed problem with volatile booleans being allocated to registers. Closes #153
This commit is contained in:
parent
c696d9610e
commit
c81147f60f
@ -54,7 +54,7 @@ public class Pass4RegisterUpliftPotentialInitialize extends Pass2Base {
|
||||
potentials.add(Registers.getRegisterX());
|
||||
potentials.add(Registers.getRegisterY());
|
||||
}
|
||||
if(registerType.equals(Registers.RegisterType.ZP_BOOL) && !varRefExtracted(equivalenceClass)) {
|
||||
if(registerType.equals(Registers.RegisterType.ZP_BOOL) && !varRefExtracted(equivalenceClass) &&!varVolatile(equivalenceClass)) {
|
||||
potentials.add(Registers.getRegisterA());
|
||||
}
|
||||
registerPotentials.setPotentialRegisters(equivalenceClass, potentials);
|
||||
|
@ -32,6 +32,15 @@ public class TestPrograms {
|
||||
public TestPrograms() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiplexerIrq() throws IOException, URISyntaxException {
|
||||
compileAndCompare("multiplexer-irq/simple-multiplexer-irq", 10);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIrqVolatileProblem() throws IOException, URISyntaxException {
|
||||
compileAndCompare("irq-volatile-bool-problem");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMusicIrq() throws IOException, URISyntaxException {
|
||||
|
43
src/test/kc/irq-volatile-bool-problem.kc
Normal file
43
src/test/kc/irq-volatile-bool-problem.kc
Normal file
@ -0,0 +1,43 @@
|
||||
// Illustrates a problem where a volatile bool modified at the end of an IRQ is not stored properly
|
||||
// because it is assigned to the A register
|
||||
|
||||
const void()** KERNEL_IRQ = $0314;
|
||||
const byte* RASTER = $d012;
|
||||
const byte* VIC_CONTROL = $d011;
|
||||
const byte* IRQ_STATUS = $d019;
|
||||
const byte* IRQ_ENABLE = $d01a;
|
||||
const byte IRQ_RASTER = %00000001;
|
||||
const byte* BGCOL = $d020;
|
||||
|
||||
const byte* CIA1_INTERRUPT = $dc0d;
|
||||
const byte CIA_INTERRUPT_CLEAR = $7f;
|
||||
|
||||
|
||||
void main() {
|
||||
asm { sei }
|
||||
// Disable CIA 1 Timer IRQ
|
||||
*CIA1_INTERRUPT = CIA_INTERRUPT_CLEAR;
|
||||
// Set raster line to $0fd
|
||||
*VIC_CONTROL &=$7f;
|
||||
*RASTER = $fd;
|
||||
// Enable Raster Interrupt
|
||||
*IRQ_ENABLE = IRQ_RASTER;
|
||||
// Set the IRQ routine
|
||||
*KERNEL_IRQ = &irq;
|
||||
asm { cli }
|
||||
while(true) {
|
||||
if(*RASTER<20)
|
||||
framedone = true;
|
||||
}
|
||||
}
|
||||
|
||||
volatile bool framedone = false;
|
||||
|
||||
interrupt(kernel_min) void irq() {
|
||||
(*BGCOL)++;
|
||||
*IRQ_STATUS = IRQ_RASTER;
|
||||
if (*RASTER>50) {
|
||||
framedone = false;
|
||||
}
|
||||
(*BGCOL)--;
|
||||
}
|
BIN
src/test/kc/multiplexer-irq/balloon.png
Normal file
BIN
src/test/kc/multiplexer-irq/balloon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
BIN
src/test/kc/multiplexer-irq/balloon.pxi
Normal file
BIN
src/test/kc/multiplexer-irq/balloon.pxi
Normal file
Binary file not shown.
140
src/test/kc/multiplexer-irq/multiplexer-irq.kc
Normal file
140
src/test/kc/multiplexer-irq/multiplexer-irq.kc
Normal file
@ -0,0 +1,140 @@
|
||||
// A flexible sprite multiplexer routine for 32 sprites.
|
||||
// Usage:
|
||||
// - Once:
|
||||
// - plexInit(screen): Initialize the data structures and set the screen address
|
||||
// Each frame:
|
||||
// - Set x-pos, y-pos and pointer in PLEX_XPOS[id], PLEX_YPOS[id], PLEX_PTR[id]
|
||||
// - plexSort() Sorts the sprites according to y-positions and prepares for showing them. This uses an insertion sort that is quite fast when the relative order of the sprites does not change very much.
|
||||
// - plexShowSprite() Shows the next sprite by copying values from PLEX_XXX[] to an actual sprite. Actual sprites are used round-robin. This should be called once for each of the 24 virtual sprites.
|
||||
// - plexFreeNextYpos() Returns the Y-position where the next sprite is available to be shown (ie. the next pos where the next sprite is no longer in use showing something else).
|
||||
// - plexShowNextYpos() Returns the Y-position of the next sprite to show.
|
||||
//
|
||||
// In practice a good method is to wait until the raster is beyond plexFreeNextYpos() and then call plexShowSprite(). Repeat until all 32 sprites have been shown.
|
||||
// TODO: Let the caller specify the number of sprites to use (or add PLEX_ENABLE[PLEX_COUNT])
|
||||
|
||||
import "c64"
|
||||
|
||||
// The number of sprites in the multiplexer
|
||||
const byte PLEX_COUNT = 32;
|
||||
|
||||
// The x-positions of the multiplexer sprites ($000-$1ff)
|
||||
word[PLEX_COUNT] PLEX_XPOS;
|
||||
|
||||
// The y-positions of the multiplexer sprites.
|
||||
byte[PLEX_COUNT] PLEX_YPOS;
|
||||
|
||||
// The sprite pointers for the multiplexed sprites
|
||||
byte[PLEX_COUNT] PLEX_PTR;
|
||||
|
||||
// The address of the sprite pointers on the current screen (screen+$3f8).
|
||||
byte* PLEX_SCREEN_PTR = $400+$3f8;
|
||||
|
||||
// Indexes of the plex-sprites sorted by sprite y-position. Each call to plexSort() will fix the sorting if changes to the Y-positions have ruined it.
|
||||
byte[PLEX_COUNT] PLEX_SORTED_IDX;
|
||||
|
||||
// Variables controlling the showing of sprites
|
||||
|
||||
// The index in the PLEX tables of the next sprite to show
|
||||
volatile byte plex_show_idx=0;
|
||||
// The index the next sprite to use for showing (sprites are used round-robin)
|
||||
volatile byte plex_sprite_idx=0;
|
||||
// The MSB bit of the next sprite to use for showing
|
||||
volatile byte plex_sprite_msb=1;
|
||||
|
||||
// Initialize the multiplexer data structures
|
||||
void plexInit(byte* screen) {
|
||||
plexSetScreen(screen);
|
||||
for(byte i: 0..PLEX_COUNT-1) {
|
||||
PLEX_SORTED_IDX[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the address of the current screen used for setting sprite pointers (at screen+$3f8)
|
||||
inline void plexSetScreen(byte* screen) {
|
||||
PLEX_SCREEN_PTR = screen+$3f8;
|
||||
}
|
||||
|
||||
// Ensure that the indices in PLEX_SORTED_IDX is sorted based on the y-positions in PLEX_YPOS
|
||||
// Assumes that the positions are nearly sorted already (as each sprite just moves a bit)
|
||||
// Uses an insertion sort:
|
||||
// 1. Moves a marker (m) from the start to end of the array. Every time the marker moves forward all elements before the marker are sorted correctly.
|
||||
// 2a. If the next element after the marker is larger that the current element
|
||||
// the marker can be moved forwards (as the sorting is correct).
|
||||
// 2b. If the next element after the marker is smaller than the current element:
|
||||
// elements before the marker are shifted right one at a time until encountering one smaller than the current one.
|
||||
// It is then inserted at the spot. Now the marker can move forward.
|
||||
void plexSort() {
|
||||
for(byte m: 0..PLEX_COUNT-2) {
|
||||
byte nxt_idx = PLEX_SORTED_IDX[m+1];
|
||||
byte nxt_y = PLEX_YPOS[nxt_idx];
|
||||
if(nxt_y<PLEX_YPOS[PLEX_SORTED_IDX[m]]) {
|
||||
// Shift values until we encounter a value smaller than nxt_y
|
||||
byte s = m;
|
||||
do {
|
||||
PLEX_SORTED_IDX[s+1] = PLEX_SORTED_IDX[s];
|
||||
s--;
|
||||
} while((s!=$ff) && (nxt_y<PLEX_YPOS[PLEX_SORTED_IDX[s]]));
|
||||
// store the mark at the found position
|
||||
s++;
|
||||
PLEX_SORTED_IDX[s] = nxt_idx;
|
||||
}
|
||||
}
|
||||
// Prepare for showing the sprites
|
||||
plex_show_idx = 0;
|
||||
plex_sprite_idx = 0;
|
||||
plex_sprite_msb = 1;
|
||||
plexFreePrepare();
|
||||
}
|
||||
|
||||
// Show the next sprite.
|
||||
// plexSort() prepares showing the sprites
|
||||
void plexShowSprite() {
|
||||
byte plex_sprite_idx2 = plex_sprite_idx<<1;
|
||||
byte ypos = PLEX_YPOS[PLEX_SORTED_IDX[plex_show_idx]];
|
||||
SPRITES_YPOS[plex_sprite_idx2] = ypos;
|
||||
plexFreeAdd(ypos);
|
||||
PLEX_SCREEN_PTR[plex_sprite_idx] = PLEX_PTR[PLEX_SORTED_IDX[plex_show_idx]];
|
||||
byte xpos_idx = PLEX_SORTED_IDX[plex_show_idx]<<1;
|
||||
SPRITES_XPOS[plex_sprite_idx2] = <PLEX_XPOS[xpos_idx];
|
||||
if(>PLEX_XPOS[xpos_idx]!=0) {
|
||||
*SPRITES_XMSB |= plex_sprite_msb;
|
||||
} else {
|
||||
*SPRITES_XMSB &= ($ff^plex_sprite_msb);
|
||||
}
|
||||
plex_sprite_idx = (plex_sprite_idx+1)&7;
|
||||
plex_show_idx++;
|
||||
plex_sprite_msb <<=1;
|
||||
if(plex_sprite_msb==0) {
|
||||
plex_sprite_msb = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the y-position of the next sprite to show
|
||||
inline byte plexShowNextYpos() {
|
||||
return PLEX_YPOS[PLEX_SORTED_IDX[plex_show_idx]];
|
||||
}
|
||||
|
||||
// Contains the Y-position where each sprite is free again. PLEX_FREE_YPOS[s] holds the Y-position where sprite s is free to use again.
|
||||
byte[8] PLEX_FREE_YPOS;
|
||||
|
||||
// The index of the sprite that is free next. Since sprites are used round-robin this moves forward each time a sprite is shown.
|
||||
volatile byte plex_free_next = 0;
|
||||
|
||||
// Prepare for a new frame. Initialize free to zero for all sprites.
|
||||
inline void plexFreePrepare() {
|
||||
for( byte s: 0..7) {
|
||||
PLEX_FREE_YPOS[s] = 0;
|
||||
}
|
||||
plex_free_next = 0;
|
||||
}
|
||||
|
||||
// Get the Y-position where the next sprite to be shown is free to use.
|
||||
inline byte plexFreeNextYpos() {
|
||||
return PLEX_FREE_YPOS[plex_free_next];
|
||||
}
|
||||
|
||||
// Update the data structure to reflect that a sprite has been shown. This sprite will be free again after 21 lines.
|
||||
inline void plexFreeAdd(byte ypos) {
|
||||
PLEX_FREE_YPOS[plex_free_next] = ypos+21;
|
||||
plex_free_next = (plex_free_next+1)&7;
|
||||
}
|
96
src/test/kc/multiplexer-irq/simple-multiplexer-irq.kc
Normal file
96
src/test/kc/multiplexer-irq/simple-multiplexer-irq.kc
Normal file
@ -0,0 +1,96 @@
|
||||
// A simple usage of the flexible sprite multiplexer routine
|
||||
import "c64"
|
||||
import "multiplexer-irq"
|
||||
// Location of screen & sprites
|
||||
byte* SCREEN = $400;
|
||||
byte* SPRITE = $2000;
|
||||
byte* YSIN = $2100;
|
||||
|
||||
kickasm(pc YSIN) {{
|
||||
.var min = 50
|
||||
.var max = 250-21
|
||||
.var ampl = max-min;
|
||||
.for(var i=0;i<256;i++)
|
||||
.byte round(min+(ampl/2)+(ampl/2)*sin(toRadians(360*i/256)))
|
||||
}}
|
||||
|
||||
kickasm(pc SPRITE, resource "balloon.png") {{
|
||||
.var pic = LoadPicture("balloon.png", List().add($000000, $ffffff))
|
||||
.for (var y=0; y<21; y++)
|
||||
.for (var x=0;x<3; x++)
|
||||
.byte pic.getSinglecolorByte(x,y)
|
||||
}}
|
||||
|
||||
void main() {
|
||||
asm { sei }
|
||||
init();
|
||||
loop();
|
||||
}
|
||||
|
||||
// Initialize the program
|
||||
void init() {
|
||||
*D011 = VIC_DEN | VIC_RSEL | 3;
|
||||
// Initialize the multiplexer
|
||||
plexInit(SCREEN);
|
||||
// Set the x-positions & pointers
|
||||
word xp = 32;
|
||||
for(byte sx: 0..PLEX_COUNT-1) {
|
||||
PLEX_PTR[sx] = (byte)(SPRITE/$40);
|
||||
PLEX_XPOS[sx<<1] = xp;
|
||||
xp += 9;
|
||||
}
|
||||
// Enable & initialize sprites
|
||||
*SPRITES_ENABLE = $ff;
|
||||
for(byte ss: 0..7) {
|
||||
SPRITES_COLS[ss] = GREEN;
|
||||
}
|
||||
// enable the interrupt
|
||||
asm { sei }
|
||||
*CIA1_INTERRUPT = CIA_INTERRUPT_CLEAR;
|
||||
*IRQ_ENABLE = IRQ_RASTER;
|
||||
*IRQ_STATUS = IRQ_RASTER;
|
||||
*KERNEL_IRQ = &plex_irq;
|
||||
asm { cli }
|
||||
}
|
||||
|
||||
volatile bool framedone = true;
|
||||
|
||||
interrupt(kernel_min) void plex_irq() {
|
||||
byte rasterY;
|
||||
*BORDERCOL = WHITE;
|
||||
do {
|
||||
plexShowSprite();
|
||||
rasterY = plexFreeNextYpos();
|
||||
} while (plex_show_idx < PLEX_COUNT && rasterY < *RASTER+2);
|
||||
*IRQ_STATUS = IRQ_RASTER;
|
||||
if (plex_show_idx<PLEX_COUNT) {
|
||||
*RASTER = rasterY;
|
||||
} else {
|
||||
framedone = true;
|
||||
}
|
||||
*BORDERCOL = 0;
|
||||
}
|
||||
|
||||
// The raster loop
|
||||
void loop() {
|
||||
// The current index into the y-sinus
|
||||
volatile byte sin_idx = 0; // without volatile gives wrong asm
|
||||
while(true) {
|
||||
while(!framedone) { }
|
||||
*BORDERCOL = RED;
|
||||
// Assign sinus positions
|
||||
volatile byte y_idx = sin_idx; // without volatile gives wrong asm
|
||||
for(byte sy: 0..PLEX_COUNT-1) {
|
||||
PLEX_YPOS[sy] = YSIN[y_idx];
|
||||
y_idx += 8;
|
||||
}
|
||||
sin_idx +=1;
|
||||
// Sort the sprites by y-position
|
||||
(*BORDERCOL)++;
|
||||
plexSort();
|
||||
*BORDERCOL = GREEN;
|
||||
framedone = false;
|
||||
*VIC_CONTROL &=$7f;
|
||||
*RASTER = $0;
|
||||
}
|
||||
}
|
61
src/test/ref/irq-volatile-bool-problem.asm
Normal file
61
src/test/ref/irq-volatile-bool-problem.asm
Normal file
@ -0,0 +1,61 @@
|
||||
// Illustrates a problem where a volatile bool modified at the end of an IRQ is not stored properly
|
||||
// because it is assigned to the A register
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
.label KERNEL_IRQ = $314
|
||||
.label RASTER = $d012
|
||||
.label VIC_CONTROL = $d011
|
||||
.label IRQ_STATUS = $d019
|
||||
.label IRQ_ENABLE = $d01a
|
||||
.const IRQ_RASTER = 1
|
||||
.label BGCOL = $d020
|
||||
.label CIA1_INTERRUPT = $dc0d
|
||||
.const CIA_INTERRUPT_CLEAR = $7f
|
||||
.label framedone = 2
|
||||
bbegin:
|
||||
lda #0
|
||||
sta framedone
|
||||
jsr main
|
||||
main: {
|
||||
sei
|
||||
// Disable CIA 1 Timer IRQ
|
||||
lda #CIA_INTERRUPT_CLEAR
|
||||
sta CIA1_INTERRUPT
|
||||
// Set raster line to $0fd
|
||||
lda #$7f
|
||||
and VIC_CONTROL
|
||||
sta VIC_CONTROL
|
||||
lda #$fd
|
||||
sta RASTER
|
||||
// Enable Raster Interrupt
|
||||
lda #IRQ_RASTER
|
||||
sta IRQ_ENABLE
|
||||
// Set the IRQ routine
|
||||
lda #<irq
|
||||
sta KERNEL_IRQ
|
||||
lda #>irq
|
||||
sta KERNEL_IRQ+1
|
||||
cli
|
||||
b2:
|
||||
lda RASTER
|
||||
cmp #$14
|
||||
bcs b2
|
||||
lda #1
|
||||
sta framedone
|
||||
jmp b2
|
||||
}
|
||||
irq: {
|
||||
inc BGCOL
|
||||
lda #IRQ_RASTER
|
||||
sta IRQ_STATUS
|
||||
lda RASTER
|
||||
cmp #$32
|
||||
bcc b1
|
||||
beq b1
|
||||
lda #0
|
||||
sta framedone
|
||||
b1:
|
||||
dec BGCOL
|
||||
jmp $ea81
|
||||
}
|
41
src/test/ref/irq-volatile-bool-problem.cfg
Normal file
41
src/test/ref/irq-volatile-bool-problem.cfg
Normal file
@ -0,0 +1,41 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] (bool) framedone#11 ← false
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
[2] phi()
|
||||
[3] call main
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
[4] phi()
|
||||
main: scope:[main] from @2
|
||||
asm { sei }
|
||||
[6] *((const byte*) CIA1_INTERRUPT#0) ← (const byte) CIA_INTERRUPT_CLEAR#0
|
||||
[7] *((const byte*) VIC_CONTROL#0) ← *((const byte*) VIC_CONTROL#0) & (byte/signed byte/word/signed word/dword/signed dword) $7f
|
||||
[8] *((const byte*) RASTER#0) ← (byte/word/signed word/dword/signed dword) $fd
|
||||
[9] *((const byte*) IRQ_ENABLE#0) ← (const byte) IRQ_RASTER#0
|
||||
[10] *((const void()**) KERNEL_IRQ#0) ← &interrupt(KERNEL_MIN)(void()) irq()
|
||||
asm { cli }
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main main::@2 main::@7
|
||||
[12] if(*((const byte*) RASTER#0)>=(byte/signed byte/word/signed word/dword/signed dword) $14) goto main::@2
|
||||
to:main::@7
|
||||
main::@7: scope:[main] from main::@2
|
||||
[13] (bool) framedone#0 ← true
|
||||
to:main::@2
|
||||
irq: scope:[irq] from
|
||||
[14] *((const byte*) BGCOL#0) ← ++ *((const byte*) BGCOL#0)
|
||||
[15] *((const byte*) IRQ_STATUS#0) ← (const byte) IRQ_RASTER#0
|
||||
[16] if(*((const byte*) RASTER#0)<=(byte/signed byte/word/signed word/dword/signed dword) $32) goto irq::@1
|
||||
to:irq::@2
|
||||
irq::@2: scope:[irq] from irq
|
||||
[17] (bool) framedone#3 ← false
|
||||
to:irq::@1
|
||||
irq::@1: scope:[irq] from irq irq::@2
|
||||
[18] *((const byte*) BGCOL#0) ← -- *((const byte*) BGCOL#0)
|
||||
to:irq::@return
|
||||
irq::@return: scope:[irq] from irq::@1
|
||||
[19] return
|
||||
to:@return
|
675
src/test/ref/irq-volatile-bool-problem.log
Normal file
675
src/test/ref/irq-volatile-bool-problem.log
Normal file
@ -0,0 +1,675 @@
|
||||
Resolved forward reference irq to interrupt(KERNEL_MIN)(void()) irq()
|
||||
Resolved forward reference framedone to (bool) framedone
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
(void()**) KERNEL_IRQ#0 ← ((void()**)) (word/signed word/dword/signed dword) $314
|
||||
(byte*) RASTER#0 ← ((byte*)) (word/dword/signed dword) $d012
|
||||
(byte*) VIC_CONTROL#0 ← ((byte*)) (word/dword/signed dword) $d011
|
||||
(byte*) IRQ_STATUS#0 ← ((byte*)) (word/dword/signed dword) $d019
|
||||
(byte*) IRQ_ENABLE#0 ← ((byte*)) (word/dword/signed dword) $d01a
|
||||
(byte) IRQ_RASTER#0 ← (byte/signed byte/word/signed word/dword/signed dword) 1
|
||||
(byte*) BGCOL#0 ← ((byte*)) (word/dword/signed dword) $d020
|
||||
(byte*) CIA1_INTERRUPT#0 ← ((byte*)) (word/dword/signed dword) $dc0d
|
||||
(byte) CIA_INTERRUPT_CLEAR#0 ← (byte/signed byte/word/signed word/dword/signed dword) $7f
|
||||
to:@1
|
||||
main: scope:[main] from @2
|
||||
(bool) framedone#12 ← phi( @2/(bool) framedone#11 )
|
||||
asm { sei }
|
||||
*((byte*) CIA1_INTERRUPT#0) ← (byte) CIA_INTERRUPT_CLEAR#0
|
||||
*((byte*) VIC_CONTROL#0) ← *((byte*) VIC_CONTROL#0) & (byte/signed byte/word/signed word/dword/signed dword) $7f
|
||||
*((byte*) RASTER#0) ← (byte/word/signed word/dword/signed dword) $fd
|
||||
*((byte*) IRQ_ENABLE#0) ← (byte) IRQ_RASTER#0
|
||||
(void()*~) main::$0 ← & interrupt(KERNEL_MIN)(void()) irq()
|
||||
*((void()**) KERNEL_IRQ#0) ← (void()*~) main::$0
|
||||
asm { cli }
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@4 main::@7
|
||||
(bool) framedone#9 ← phi( main/(bool) framedone#12 main::@4/(bool) framedone#13 main::@7/(bool) framedone#0 )
|
||||
if(true) goto main::@2
|
||||
to:main::@return
|
||||
main::@2: scope:[main] from main::@1
|
||||
(bool) framedone#15 ← phi( main::@1/(bool) framedone#9 )
|
||||
(bool~) main::$1 ← *((byte*) RASTER#0) < (byte/signed byte/word/signed word/dword/signed dword) $14
|
||||
(bool~) main::$2 ← ! (bool~) main::$1
|
||||
if((bool~) main::$2) goto main::@4
|
||||
to:main::@7
|
||||
main::@4: scope:[main] from main::@2
|
||||
(bool) framedone#13 ← phi( main::@2/(bool) framedone#15 )
|
||||
to:main::@1
|
||||
main::@7: scope:[main] from main::@2
|
||||
(bool) framedone#0 ← true
|
||||
to:main::@1
|
||||
main::@return: scope:[main] from main::@1
|
||||
(bool) framedone#6 ← phi( main::@1/(bool) framedone#9 )
|
||||
(bool) framedone#1 ← (bool) framedone#6
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
(bool) framedone#2 ← false
|
||||
to:@2
|
||||
irq: scope:[irq] from
|
||||
(bool) framedone#14 ← phi( @2/(bool) framedone#11 )
|
||||
*((byte*) BGCOL#0) ← ++ *((byte*) BGCOL#0)
|
||||
*((byte*) IRQ_STATUS#0) ← (byte) IRQ_RASTER#0
|
||||
(bool~) irq::$0 ← *((byte*) RASTER#0) > (byte/signed byte/word/signed word/dword/signed dword) $32
|
||||
(bool~) irq::$1 ← ! (bool~) irq::$0
|
||||
if((bool~) irq::$1) goto irq::@1
|
||||
to:irq::@2
|
||||
irq::@1: scope:[irq] from irq irq::@2
|
||||
(bool) framedone#10 ← phi( irq/(bool) framedone#14 irq::@2/(bool) framedone#3 )
|
||||
*((byte*) BGCOL#0) ← -- *((byte*) BGCOL#0)
|
||||
to:irq::@return
|
||||
irq::@2: scope:[irq] from irq
|
||||
(bool) framedone#3 ← false
|
||||
to:irq::@1
|
||||
irq::@return: scope:[irq] from irq::@1
|
||||
(bool) framedone#7 ← phi( irq::@1/(bool) framedone#10 )
|
||||
(bool) framedone#4 ← (bool) framedone#7
|
||||
return
|
||||
to:@return
|
||||
@2: scope:[] from @1
|
||||
(bool) framedone#11 ← phi( @1/(bool) framedone#2 )
|
||||
call main
|
||||
to:@3
|
||||
@3: scope:[] from @2
|
||||
(bool) framedone#8 ← phi( @2/(bool) framedone#1 )
|
||||
(bool) framedone#5 ← (bool) framedone#8
|
||||
to:@end
|
||||
@end: scope:[] from @3
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @3
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte*) BGCOL
|
||||
(byte*) BGCOL#0
|
||||
(byte*) CIA1_INTERRUPT
|
||||
(byte*) CIA1_INTERRUPT#0
|
||||
(byte) CIA_INTERRUPT_CLEAR
|
||||
(byte) CIA_INTERRUPT_CLEAR#0
|
||||
(byte*) IRQ_ENABLE
|
||||
(byte*) IRQ_ENABLE#0
|
||||
(byte) IRQ_RASTER
|
||||
(byte) IRQ_RASTER#0
|
||||
(byte*) IRQ_STATUS
|
||||
(byte*) IRQ_STATUS#0
|
||||
(void()**) KERNEL_IRQ
|
||||
(void()**) KERNEL_IRQ#0
|
||||
(byte*) RASTER
|
||||
(byte*) RASTER#0
|
||||
(byte*) VIC_CONTROL
|
||||
(byte*) VIC_CONTROL#0
|
||||
(bool) framedone
|
||||
(bool) framedone#0
|
||||
(bool) framedone#1
|
||||
(bool) framedone#10
|
||||
(bool) framedone#11
|
||||
(bool) framedone#12
|
||||
(bool) framedone#13
|
||||
(bool) framedone#14
|
||||
(bool) framedone#15
|
||||
(bool) framedone#2
|
||||
(bool) framedone#3
|
||||
(bool) framedone#4
|
||||
(bool) framedone#5
|
||||
(bool) framedone#6
|
||||
(bool) framedone#7
|
||||
(bool) framedone#8
|
||||
(bool) framedone#9
|
||||
interrupt(KERNEL_MIN)(void()) irq()
|
||||
(bool~) irq::$0
|
||||
(bool~) irq::$1
|
||||
(label) irq::@1
|
||||
(label) irq::@2
|
||||
(label) irq::@return
|
||||
(void()) main()
|
||||
(void()*~) main::$0
|
||||
(bool~) main::$1
|
||||
(bool~) main::$2
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@4
|
||||
(label) main::@7
|
||||
(label) main::@return
|
||||
|
||||
Inversing boolean not [22] (bool~) main::$2 ← *((byte*) RASTER#0) >= (byte/signed byte/word/signed word/dword/signed dword) $14 from [21] (bool~) main::$1 ← *((byte*) RASTER#0) < (byte/signed byte/word/signed word/dword/signed dword) $14
|
||||
Inversing boolean not [34] (bool~) irq::$1 ← *((byte*) RASTER#0) <= (byte/signed byte/word/signed word/dword/signed dword) $32 from [33] (bool~) irq::$0 ← *((byte*) RASTER#0) > (byte/signed byte/word/signed word/dword/signed dword) $32
|
||||
Successful SSA optimization Pass2UnaryNotSimplification
|
||||
Alias (bool) framedone#1 = (bool) framedone#15 (bool) framedone#9 (bool) framedone#13 (bool) framedone#6
|
||||
Alias (bool) framedone#10 = (bool) framedone#7 (bool) framedone#4
|
||||
Alias (bool) framedone#11 = (bool) framedone#2
|
||||
Alias (bool) framedone#5 = (bool) framedone#8
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Self Phi Eliminated (bool) framedone#1
|
||||
Successful SSA optimization Pass2SelfPhiElimination
|
||||
Redundant Phi (bool) framedone#12 (bool) framedone#11
|
||||
Redundant Phi (bool) framedone#14 (bool) framedone#11
|
||||
Redundant Phi (bool) framedone#5 (bool) framedone#1
|
||||
Successful SSA optimization Pass2RedundantPhiElimination
|
||||
Simple Condition (bool~) main::$2 [23] if(*((byte*) RASTER#0)>=(byte/signed byte/word/signed word/dword/signed dword) $14) goto main::@4
|
||||
Simple Condition (bool~) irq::$1 [35] if(*((byte*) RASTER#0)<=(byte/signed byte/word/signed word/dword/signed dword) $32) goto irq::@1
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Constant (const void()**) KERNEL_IRQ#0 = ((void()**))$314
|
||||
Constant (const byte*) RASTER#0 = ((byte*))$d012
|
||||
Constant (const byte*) VIC_CONTROL#0 = ((byte*))$d011
|
||||
Constant (const byte*) IRQ_STATUS#0 = ((byte*))$d019
|
||||
Constant (const byte*) IRQ_ENABLE#0 = ((byte*))$d01a
|
||||
Constant (const byte) IRQ_RASTER#0 = 1
|
||||
Constant (const byte*) BGCOL#0 = ((byte*))$d020
|
||||
Constant (const byte*) CIA1_INTERRUPT#0 = ((byte*))$dc0d
|
||||
Constant (const byte) CIA_INTERRUPT_CLEAR#0 = $7f
|
||||
Constant (const void()*) main::$0 = &irq
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
if() condition always true - replacing block destination [8] if(true) goto main::@2
|
||||
Successful SSA optimization Pass2ConstantIfs
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Removing unused block main::@return
|
||||
Successful SSA optimization Pass2EliminateUnusedBlocks
|
||||
Culled Empty Block (label) main::@4
|
||||
Culled Empty Block (label) @3
|
||||
Successful SSA optimization Pass2CullEmptyBlocks
|
||||
Culled Empty Block (label) main::@1
|
||||
Successful SSA optimization Pass2CullEmptyBlocks
|
||||
Constant inlined main::$0 = &interrupt(KERNEL_MIN)(void()) irq()
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @end
|
||||
CALL GRAPH
|
||||
Calls in [] to main:3
|
||||
|
||||
Created 0 initial phi equivalence classes
|
||||
Coalesced down to 0 phi equivalence classes
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @end
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] (bool) framedone#11 ← false
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
[2] phi()
|
||||
[3] call main
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
[4] phi()
|
||||
main: scope:[main] from @2
|
||||
asm { sei }
|
||||
[6] *((const byte*) CIA1_INTERRUPT#0) ← (const byte) CIA_INTERRUPT_CLEAR#0
|
||||
[7] *((const byte*) VIC_CONTROL#0) ← *((const byte*) VIC_CONTROL#0) & (byte/signed byte/word/signed word/dword/signed dword) $7f
|
||||
[8] *((const byte*) RASTER#0) ← (byte/word/signed word/dword/signed dword) $fd
|
||||
[9] *((const byte*) IRQ_ENABLE#0) ← (const byte) IRQ_RASTER#0
|
||||
[10] *((const void()**) KERNEL_IRQ#0) ← &interrupt(KERNEL_MIN)(void()) irq()
|
||||
asm { cli }
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main main::@2 main::@7
|
||||
[12] if(*((const byte*) RASTER#0)>=(byte/signed byte/word/signed word/dword/signed dword) $14) goto main::@2
|
||||
to:main::@7
|
||||
main::@7: scope:[main] from main::@2
|
||||
[13] (bool) framedone#0 ← true
|
||||
to:main::@2
|
||||
irq: scope:[irq] from
|
||||
[14] *((const byte*) BGCOL#0) ← ++ *((const byte*) BGCOL#0)
|
||||
[15] *((const byte*) IRQ_STATUS#0) ← (const byte) IRQ_RASTER#0
|
||||
[16] if(*((const byte*) RASTER#0)<=(byte/signed byte/word/signed word/dword/signed dword) $32) goto irq::@1
|
||||
to:irq::@2
|
||||
irq::@2: scope:[irq] from irq
|
||||
[17] (bool) framedone#3 ← false
|
||||
to:irq::@1
|
||||
irq::@1: scope:[irq] from irq irq::@2
|
||||
[18] *((const byte*) BGCOL#0) ← -- *((const byte*) BGCOL#0)
|
||||
to:irq::@return
|
||||
irq::@return: scope:[irq] from irq::@1
|
||||
[19] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte*) BGCOL
|
||||
(byte*) CIA1_INTERRUPT
|
||||
(byte) CIA_INTERRUPT_CLEAR
|
||||
(byte*) IRQ_ENABLE
|
||||
(byte) IRQ_RASTER
|
||||
(byte*) IRQ_STATUS
|
||||
(void()**) KERNEL_IRQ
|
||||
(byte*) RASTER
|
||||
(byte*) VIC_CONTROL
|
||||
(bool) framedone
|
||||
(bool) framedone#0 110.0
|
||||
(bool) framedone#11 20.0
|
||||
(bool) framedone#3 20.0
|
||||
interrupt(KERNEL_MIN)(void()) irq()
|
||||
(void()) main()
|
||||
|
||||
Initial phi equivalence classes
|
||||
Added variable framedone#11 to zero page equivalence class [ framedone#11 ]
|
||||
Added variable framedone#0 to zero page equivalence class [ framedone#0 ]
|
||||
Added variable framedone#3 to zero page equivalence class [ framedone#3 ]
|
||||
Complete equivalence classes
|
||||
[ framedone#11 ]
|
||||
[ framedone#0 ]
|
||||
[ framedone#3 ]
|
||||
Allocated zp ZP_BOOL:2 [ framedone#11 ]
|
||||
Allocated zp ZP_BOOL:3 [ framedone#0 ]
|
||||
Allocated zp ZP_BOOL:4 [ framedone#3 ]
|
||||
|
||||
INITIAL ASM
|
||||
//SEG0 File Comments
|
||||
// Illustrates a problem where a volatile bool modified at the end of an IRQ is not stored properly
|
||||
// because it is assigned to the A register
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
.label KERNEL_IRQ = $314
|
||||
.label RASTER = $d012
|
||||
.label VIC_CONTROL = $d011
|
||||
.label IRQ_STATUS = $d019
|
||||
.label IRQ_ENABLE = $d01a
|
||||
.const IRQ_RASTER = 1
|
||||
.label BGCOL = $d020
|
||||
.label CIA1_INTERRUPT = $dc0d
|
||||
.const CIA_INTERRUPT_CLEAR = $7f
|
||||
.label framedone = 3
|
||||
.label framedone_3 = 4
|
||||
.label framedone_11 = 2
|
||||
//SEG3 @begin
|
||||
bbegin:
|
||||
jmp b1
|
||||
//SEG4 @1
|
||||
b1:
|
||||
//SEG5 [1] (bool) framedone#11 ← false -- vboz1=vboc1
|
||||
lda #0
|
||||
sta framedone_11
|
||||
//SEG6 [2] phi from @1 to @2 [phi:@1->@2]
|
||||
b2_from_b1:
|
||||
jmp b2
|
||||
//SEG7 @2
|
||||
b2:
|
||||
//SEG8 [3] call main
|
||||
jsr main
|
||||
//SEG9 [4] phi from @2 to @end [phi:@2->@end]
|
||||
bend_from_b2:
|
||||
jmp bend
|
||||
//SEG10 @end
|
||||
bend:
|
||||
//SEG11 main
|
||||
main: {
|
||||
//SEG12 asm { sei }
|
||||
sei
|
||||
//SEG13 [6] *((const byte*) CIA1_INTERRUPT#0) ← (const byte) CIA_INTERRUPT_CLEAR#0 -- _deref_pbuc1=vbuc2
|
||||
// Disable CIA 1 Timer IRQ
|
||||
lda #CIA_INTERRUPT_CLEAR
|
||||
sta CIA1_INTERRUPT
|
||||
//SEG14 [7] *((const byte*) VIC_CONTROL#0) ← *((const byte*) VIC_CONTROL#0) & (byte/signed byte/word/signed word/dword/signed dword) $7f -- _deref_pbuc1=_deref_pbuc1_band_vbuc2
|
||||
// Set raster line to $0fd
|
||||
lda #$7f
|
||||
and VIC_CONTROL
|
||||
sta VIC_CONTROL
|
||||
//SEG15 [8] *((const byte*) RASTER#0) ← (byte/word/signed word/dword/signed dword) $fd -- _deref_pbuc1=vbuc2
|
||||
lda #$fd
|
||||
sta RASTER
|
||||
//SEG16 [9] *((const byte*) IRQ_ENABLE#0) ← (const byte) IRQ_RASTER#0 -- _deref_pbuc1=vbuc2
|
||||
// Enable Raster Interrupt
|
||||
lda #IRQ_RASTER
|
||||
sta IRQ_ENABLE
|
||||
//SEG17 [10] *((const void()**) KERNEL_IRQ#0) ← &interrupt(KERNEL_MIN)(void()) irq() -- _deref_pptc1=pprc2
|
||||
// Set the IRQ routine
|
||||
lda #<irq
|
||||
sta KERNEL_IRQ
|
||||
lda #>irq
|
||||
sta KERNEL_IRQ+1
|
||||
//SEG18 asm { cli }
|
||||
cli
|
||||
jmp b2
|
||||
//SEG19 main::@2
|
||||
b2:
|
||||
//SEG20 [12] if(*((const byte*) RASTER#0)>=(byte/signed byte/word/signed word/dword/signed dword) $14) goto main::@2 -- _deref_pbuc1_ge_vbuc2_then_la1
|
||||
lda RASTER
|
||||
cmp #$14
|
||||
bcs b2
|
||||
jmp b7
|
||||
//SEG21 main::@7
|
||||
b7:
|
||||
//SEG22 [13] (bool) framedone#0 ← true -- vboz1=vboc1
|
||||
lda #1
|
||||
sta framedone
|
||||
jmp b2
|
||||
}
|
||||
//SEG23 irq
|
||||
irq: {
|
||||
//SEG24 entry interrupt(KERNEL_MIN)
|
||||
//SEG25 [14] *((const byte*) BGCOL#0) ← ++ *((const byte*) BGCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc BGCOL
|
||||
//SEG26 [15] *((const byte*) IRQ_STATUS#0) ← (const byte) IRQ_RASTER#0 -- _deref_pbuc1=vbuc2
|
||||
lda #IRQ_RASTER
|
||||
sta IRQ_STATUS
|
||||
//SEG27 [16] if(*((const byte*) RASTER#0)<=(byte/signed byte/word/signed word/dword/signed dword) $32) goto irq::@1 -- _deref_pbuc1_le_vbuc2_then_la1
|
||||
lda RASTER
|
||||
cmp #$32
|
||||
bcc b1
|
||||
beq b1
|
||||
jmp b2
|
||||
//SEG28 irq::@2
|
||||
b2:
|
||||
//SEG29 [17] (bool) framedone#3 ← false -- vboz1=vboc1
|
||||
lda #0
|
||||
sta framedone_3
|
||||
jmp b1
|
||||
//SEG30 irq::@1
|
||||
b1:
|
||||
//SEG31 [18] *((const byte*) BGCOL#0) ← -- *((const byte*) BGCOL#0) -- _deref_pbuc1=_dec__deref_pbuc1
|
||||
dec BGCOL
|
||||
jmp breturn
|
||||
//SEG32 irq::@return
|
||||
breturn:
|
||||
//SEG33 [19] return - exit interrupt(KERNEL_MIN)
|
||||
jmp $ea81
|
||||
}
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [1] (bool) framedone#11 ← false [ ] ( ) always clobbers reg byte a
|
||||
Statement [6] *((const byte*) CIA1_INTERRUPT#0) ← (const byte) CIA_INTERRUPT_CLEAR#0 [ ] ( main:3 [ ] ) always clobbers reg byte a
|
||||
Statement [7] *((const byte*) VIC_CONTROL#0) ← *((const byte*) VIC_CONTROL#0) & (byte/signed byte/word/signed word/dword/signed dword) $7f [ ] ( main:3 [ ] ) always clobbers reg byte a
|
||||
Statement [8] *((const byte*) RASTER#0) ← (byte/word/signed word/dword/signed dword) $fd [ ] ( main:3 [ ] ) always clobbers reg byte a
|
||||
Statement [9] *((const byte*) IRQ_ENABLE#0) ← (const byte) IRQ_RASTER#0 [ ] ( main:3 [ ] ) always clobbers reg byte a
|
||||
Statement [10] *((const void()**) KERNEL_IRQ#0) ← &interrupt(KERNEL_MIN)(void()) irq() [ ] ( main:3 [ ] ) always clobbers reg byte a
|
||||
Statement [12] if(*((const byte*) RASTER#0)>=(byte/signed byte/word/signed word/dword/signed dword) $14) goto main::@2 [ ] ( main:3 [ ] ) always clobbers reg byte a
|
||||
Statement [13] (bool) framedone#0 ← true [ ] ( main:3 [ ] ) always clobbers reg byte a
|
||||
Statement [15] *((const byte*) IRQ_STATUS#0) ← (const byte) IRQ_RASTER#0 [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [16] if(*((const byte*) RASTER#0)<=(byte/signed byte/word/signed word/dword/signed dword) $32) goto irq::@1 [ ] ( [ ] ) always clobbers reg byte a
|
||||
Statement [17] (bool) framedone#3 ← false [ ] ( [ ] ) always clobbers reg byte a
|
||||
Potential registers zp ZP_BOOL:2 [ framedone#11 ] : zp ZP_BOOL:2 ,
|
||||
Potential registers zp ZP_BOOL:3 [ framedone#0 ] : zp ZP_BOOL:3 ,
|
||||
Potential registers zp ZP_BOOL:4 [ framedone#3 ] : zp ZP_BOOL:4 ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [] 110: zp ZP_BOOL:3 [ framedone#0 ] 20: zp ZP_BOOL:2 [ framedone#11 ] 20: zp ZP_BOOL:4 [ framedone#3 ]
|
||||
Uplift Scope [main]
|
||||
Uplift Scope [irq]
|
||||
|
||||
Uplifting [] best 1370 combination zp ZP_BOOL:3 [ framedone#0 ] zp ZP_BOOL:2 [ framedone#11 ] zp ZP_BOOL:4 [ framedone#3 ]
|
||||
Uplifting [main] best 1370 combination
|
||||
Uplifting [irq] best 1370 combination
|
||||
Coalescing zero page register [ zp ZP_BOOL:2 [ framedone#11 ] ] with [ zp ZP_BOOL:3 [ framedone#0 ] ]
|
||||
Coalescing zero page register [ zp ZP_BOOL:2 [ framedone#11 framedone#0 ] ] with [ zp ZP_BOOL:4 [ framedone#3 ] ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
//SEG0 File Comments
|
||||
// Illustrates a problem where a volatile bool modified at the end of an IRQ is not stored properly
|
||||
// because it is assigned to the A register
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
.label KERNEL_IRQ = $314
|
||||
.label RASTER = $d012
|
||||
.label VIC_CONTROL = $d011
|
||||
.label IRQ_STATUS = $d019
|
||||
.label IRQ_ENABLE = $d01a
|
||||
.const IRQ_RASTER = 1
|
||||
.label BGCOL = $d020
|
||||
.label CIA1_INTERRUPT = $dc0d
|
||||
.const CIA_INTERRUPT_CLEAR = $7f
|
||||
.label framedone = 2
|
||||
//SEG3 @begin
|
||||
bbegin:
|
||||
jmp b1
|
||||
//SEG4 @1
|
||||
b1:
|
||||
//SEG5 [1] (bool) framedone#11 ← false -- vboz1=vboc1
|
||||
lda #0
|
||||
sta framedone
|
||||
//SEG6 [2] phi from @1 to @2 [phi:@1->@2]
|
||||
b2_from_b1:
|
||||
jmp b2
|
||||
//SEG7 @2
|
||||
b2:
|
||||
//SEG8 [3] call main
|
||||
jsr main
|
||||
//SEG9 [4] phi from @2 to @end [phi:@2->@end]
|
||||
bend_from_b2:
|
||||
jmp bend
|
||||
//SEG10 @end
|
||||
bend:
|
||||
//SEG11 main
|
||||
main: {
|
||||
//SEG12 asm { sei }
|
||||
sei
|
||||
//SEG13 [6] *((const byte*) CIA1_INTERRUPT#0) ← (const byte) CIA_INTERRUPT_CLEAR#0 -- _deref_pbuc1=vbuc2
|
||||
// Disable CIA 1 Timer IRQ
|
||||
lda #CIA_INTERRUPT_CLEAR
|
||||
sta CIA1_INTERRUPT
|
||||
//SEG14 [7] *((const byte*) VIC_CONTROL#0) ← *((const byte*) VIC_CONTROL#0) & (byte/signed byte/word/signed word/dword/signed dword) $7f -- _deref_pbuc1=_deref_pbuc1_band_vbuc2
|
||||
// Set raster line to $0fd
|
||||
lda #$7f
|
||||
and VIC_CONTROL
|
||||
sta VIC_CONTROL
|
||||
//SEG15 [8] *((const byte*) RASTER#0) ← (byte/word/signed word/dword/signed dword) $fd -- _deref_pbuc1=vbuc2
|
||||
lda #$fd
|
||||
sta RASTER
|
||||
//SEG16 [9] *((const byte*) IRQ_ENABLE#0) ← (const byte) IRQ_RASTER#0 -- _deref_pbuc1=vbuc2
|
||||
// Enable Raster Interrupt
|
||||
lda #IRQ_RASTER
|
||||
sta IRQ_ENABLE
|
||||
//SEG17 [10] *((const void()**) KERNEL_IRQ#0) ← &interrupt(KERNEL_MIN)(void()) irq() -- _deref_pptc1=pprc2
|
||||
// Set the IRQ routine
|
||||
lda #<irq
|
||||
sta KERNEL_IRQ
|
||||
lda #>irq
|
||||
sta KERNEL_IRQ+1
|
||||
//SEG18 asm { cli }
|
||||
cli
|
||||
jmp b2
|
||||
//SEG19 main::@2
|
||||
b2:
|
||||
//SEG20 [12] if(*((const byte*) RASTER#0)>=(byte/signed byte/word/signed word/dword/signed dword) $14) goto main::@2 -- _deref_pbuc1_ge_vbuc2_then_la1
|
||||
lda RASTER
|
||||
cmp #$14
|
||||
bcs b2
|
||||
jmp b7
|
||||
//SEG21 main::@7
|
||||
b7:
|
||||
//SEG22 [13] (bool) framedone#0 ← true -- vboz1=vboc1
|
||||
lda #1
|
||||
sta framedone
|
||||
jmp b2
|
||||
}
|
||||
//SEG23 irq
|
||||
irq: {
|
||||
//SEG24 entry interrupt(KERNEL_MIN)
|
||||
//SEG25 [14] *((const byte*) BGCOL#0) ← ++ *((const byte*) BGCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc BGCOL
|
||||
//SEG26 [15] *((const byte*) IRQ_STATUS#0) ← (const byte) IRQ_RASTER#0 -- _deref_pbuc1=vbuc2
|
||||
lda #IRQ_RASTER
|
||||
sta IRQ_STATUS
|
||||
//SEG27 [16] if(*((const byte*) RASTER#0)<=(byte/signed byte/word/signed word/dword/signed dword) $32) goto irq::@1 -- _deref_pbuc1_le_vbuc2_then_la1
|
||||
lda RASTER
|
||||
cmp #$32
|
||||
bcc b1
|
||||
beq b1
|
||||
jmp b2
|
||||
//SEG28 irq::@2
|
||||
b2:
|
||||
//SEG29 [17] (bool) framedone#3 ← false -- vboz1=vboc1
|
||||
lda #0
|
||||
sta framedone
|
||||
jmp b1
|
||||
//SEG30 irq::@1
|
||||
b1:
|
||||
//SEG31 [18] *((const byte*) BGCOL#0) ← -- *((const byte*) BGCOL#0) -- _deref_pbuc1=_dec__deref_pbuc1
|
||||
dec BGCOL
|
||||
jmp breturn
|
||||
//SEG32 irq::@return
|
||||
breturn:
|
||||
//SEG33 [19] return - exit interrupt(KERNEL_MIN)
|
||||
jmp $ea81
|
||||
}
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp b2
|
||||
Removing instruction jmp bend
|
||||
Removing instruction jmp b2
|
||||
Removing instruction jmp b7
|
||||
Removing instruction jmp b2
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction b1:
|
||||
Removing instruction b2_from_b1:
|
||||
Removing instruction bend_from_b2:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction b2:
|
||||
Removing instruction bend:
|
||||
Removing instruction b7:
|
||||
Removing instruction b2:
|
||||
Removing instruction breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte*) BGCOL
|
||||
(const byte*) BGCOL#0 BGCOL = ((byte*))(word/dword/signed dword) $d020
|
||||
(byte*) CIA1_INTERRUPT
|
||||
(const byte*) CIA1_INTERRUPT#0 CIA1_INTERRUPT = ((byte*))(word/dword/signed dword) $dc0d
|
||||
(byte) CIA_INTERRUPT_CLEAR
|
||||
(const byte) CIA_INTERRUPT_CLEAR#0 CIA_INTERRUPT_CLEAR = (byte/signed byte/word/signed word/dword/signed dword) $7f
|
||||
(byte*) IRQ_ENABLE
|
||||
(const byte*) IRQ_ENABLE#0 IRQ_ENABLE = ((byte*))(word/dword/signed dword) $d01a
|
||||
(byte) IRQ_RASTER
|
||||
(const byte) IRQ_RASTER#0 IRQ_RASTER = (byte/signed byte/word/signed word/dword/signed dword) 1
|
||||
(byte*) IRQ_STATUS
|
||||
(const byte*) IRQ_STATUS#0 IRQ_STATUS = ((byte*))(word/dword/signed dword) $d019
|
||||
(void()**) KERNEL_IRQ
|
||||
(const void()**) KERNEL_IRQ#0 KERNEL_IRQ = ((void()**))(word/signed word/dword/signed dword) $314
|
||||
(byte*) RASTER
|
||||
(const byte*) RASTER#0 RASTER = ((byte*))(word/dword/signed dword) $d012
|
||||
(byte*) VIC_CONTROL
|
||||
(const byte*) VIC_CONTROL#0 VIC_CONTROL = ((byte*))(word/dword/signed dword) $d011
|
||||
(bool) framedone
|
||||
(bool) framedone#0 framedone zp ZP_BOOL:2 110.0
|
||||
(bool) framedone#11 framedone zp ZP_BOOL:2 20.0
|
||||
(bool) framedone#3 framedone zp ZP_BOOL:2 20.0
|
||||
interrupt(KERNEL_MIN)(void()) irq()
|
||||
(label) irq::@1
|
||||
(label) irq::@2
|
||||
(label) irq::@return
|
||||
(void()) main()
|
||||
(label) main::@2
|
||||
(label) main::@7
|
||||
|
||||
zp ZP_BOOL:2 [ framedone#11 framedone#0 framedone#3 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 1022
|
||||
|
||||
//SEG0 File Comments
|
||||
// Illustrates a problem where a volatile bool modified at the end of an IRQ is not stored properly
|
||||
// because it is assigned to the A register
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
.label KERNEL_IRQ = $314
|
||||
.label RASTER = $d012
|
||||
.label VIC_CONTROL = $d011
|
||||
.label IRQ_STATUS = $d019
|
||||
.label IRQ_ENABLE = $d01a
|
||||
.const IRQ_RASTER = 1
|
||||
.label BGCOL = $d020
|
||||
.label CIA1_INTERRUPT = $dc0d
|
||||
.const CIA_INTERRUPT_CLEAR = $7f
|
||||
.label framedone = 2
|
||||
//SEG3 @begin
|
||||
bbegin:
|
||||
//SEG4 @1
|
||||
//SEG5 [1] (bool) framedone#11 ← false -- vboz1=vboc1
|
||||
lda #0
|
||||
sta framedone
|
||||
//SEG6 [2] phi from @1 to @2 [phi:@1->@2]
|
||||
//SEG7 @2
|
||||
//SEG8 [3] call main
|
||||
jsr main
|
||||
//SEG9 [4] phi from @2 to @end [phi:@2->@end]
|
||||
//SEG10 @end
|
||||
//SEG11 main
|
||||
main: {
|
||||
//SEG12 asm { sei }
|
||||
sei
|
||||
//SEG13 [6] *((const byte*) CIA1_INTERRUPT#0) ← (const byte) CIA_INTERRUPT_CLEAR#0 -- _deref_pbuc1=vbuc2
|
||||
// Disable CIA 1 Timer IRQ
|
||||
lda #CIA_INTERRUPT_CLEAR
|
||||
sta CIA1_INTERRUPT
|
||||
//SEG14 [7] *((const byte*) VIC_CONTROL#0) ← *((const byte*) VIC_CONTROL#0) & (byte/signed byte/word/signed word/dword/signed dword) $7f -- _deref_pbuc1=_deref_pbuc1_band_vbuc2
|
||||
// Set raster line to $0fd
|
||||
lda #$7f
|
||||
and VIC_CONTROL
|
||||
sta VIC_CONTROL
|
||||
//SEG15 [8] *((const byte*) RASTER#0) ← (byte/word/signed word/dword/signed dword) $fd -- _deref_pbuc1=vbuc2
|
||||
lda #$fd
|
||||
sta RASTER
|
||||
//SEG16 [9] *((const byte*) IRQ_ENABLE#0) ← (const byte) IRQ_RASTER#0 -- _deref_pbuc1=vbuc2
|
||||
// Enable Raster Interrupt
|
||||
lda #IRQ_RASTER
|
||||
sta IRQ_ENABLE
|
||||
//SEG17 [10] *((const void()**) KERNEL_IRQ#0) ← &interrupt(KERNEL_MIN)(void()) irq() -- _deref_pptc1=pprc2
|
||||
// Set the IRQ routine
|
||||
lda #<irq
|
||||
sta KERNEL_IRQ
|
||||
lda #>irq
|
||||
sta KERNEL_IRQ+1
|
||||
//SEG18 asm { cli }
|
||||
cli
|
||||
//SEG19 main::@2
|
||||
b2:
|
||||
//SEG20 [12] if(*((const byte*) RASTER#0)>=(byte/signed byte/word/signed word/dword/signed dword) $14) goto main::@2 -- _deref_pbuc1_ge_vbuc2_then_la1
|
||||
lda RASTER
|
||||
cmp #$14
|
||||
bcs b2
|
||||
//SEG21 main::@7
|
||||
//SEG22 [13] (bool) framedone#0 ← true -- vboz1=vboc1
|
||||
lda #1
|
||||
sta framedone
|
||||
jmp b2
|
||||
}
|
||||
//SEG23 irq
|
||||
irq: {
|
||||
//SEG24 entry interrupt(KERNEL_MIN)
|
||||
//SEG25 [14] *((const byte*) BGCOL#0) ← ++ *((const byte*) BGCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc BGCOL
|
||||
//SEG26 [15] *((const byte*) IRQ_STATUS#0) ← (const byte) IRQ_RASTER#0 -- _deref_pbuc1=vbuc2
|
||||
lda #IRQ_RASTER
|
||||
sta IRQ_STATUS
|
||||
//SEG27 [16] if(*((const byte*) RASTER#0)<=(byte/signed byte/word/signed word/dword/signed dword) $32) goto irq::@1 -- _deref_pbuc1_le_vbuc2_then_la1
|
||||
lda RASTER
|
||||
cmp #$32
|
||||
bcc b1
|
||||
beq b1
|
||||
//SEG28 irq::@2
|
||||
//SEG29 [17] (bool) framedone#3 ← false -- vboz1=vboc1
|
||||
lda #0
|
||||
sta framedone
|
||||
//SEG30 irq::@1
|
||||
b1:
|
||||
//SEG31 [18] *((const byte*) BGCOL#0) ← -- *((const byte*) BGCOL#0) -- _deref_pbuc1=_dec__deref_pbuc1
|
||||
dec BGCOL
|
||||
//SEG32 irq::@return
|
||||
//SEG33 [19] return - exit interrupt(KERNEL_MIN)
|
||||
jmp $ea81
|
||||
}
|
||||
|
35
src/test/ref/irq-volatile-bool-problem.sym
Normal file
35
src/test/ref/irq-volatile-bool-problem.sym
Normal file
@ -0,0 +1,35 @@
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte*) BGCOL
|
||||
(const byte*) BGCOL#0 BGCOL = ((byte*))(word/dword/signed dword) $d020
|
||||
(byte*) CIA1_INTERRUPT
|
||||
(const byte*) CIA1_INTERRUPT#0 CIA1_INTERRUPT = ((byte*))(word/dword/signed dword) $dc0d
|
||||
(byte) CIA_INTERRUPT_CLEAR
|
||||
(const byte) CIA_INTERRUPT_CLEAR#0 CIA_INTERRUPT_CLEAR = (byte/signed byte/word/signed word/dword/signed dword) $7f
|
||||
(byte*) IRQ_ENABLE
|
||||
(const byte*) IRQ_ENABLE#0 IRQ_ENABLE = ((byte*))(word/dword/signed dword) $d01a
|
||||
(byte) IRQ_RASTER
|
||||
(const byte) IRQ_RASTER#0 IRQ_RASTER = (byte/signed byte/word/signed word/dword/signed dword) 1
|
||||
(byte*) IRQ_STATUS
|
||||
(const byte*) IRQ_STATUS#0 IRQ_STATUS = ((byte*))(word/dword/signed dword) $d019
|
||||
(void()**) KERNEL_IRQ
|
||||
(const void()**) KERNEL_IRQ#0 KERNEL_IRQ = ((void()**))(word/signed word/dword/signed dword) $314
|
||||
(byte*) RASTER
|
||||
(const byte*) RASTER#0 RASTER = ((byte*))(word/dword/signed dword) $d012
|
||||
(byte*) VIC_CONTROL
|
||||
(const byte*) VIC_CONTROL#0 VIC_CONTROL = ((byte*))(word/dword/signed dword) $d011
|
||||
(bool) framedone
|
||||
(bool) framedone#0 framedone zp ZP_BOOL:2 110.0
|
||||
(bool) framedone#11 framedone zp ZP_BOOL:2 20.0
|
||||
(bool) framedone#3 framedone zp ZP_BOOL:2 20.0
|
||||
interrupt(KERNEL_MIN)(void()) irq()
|
||||
(label) irq::@1
|
||||
(label) irq::@2
|
||||
(label) irq::@return
|
||||
(void()) main()
|
||||
(label) main::@2
|
||||
(label) main::@7
|
||||
|
||||
zp ZP_BOOL:2 [ framedone#11 framedone#0 framedone#3 ]
|
359
src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm
Normal file
359
src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm
Normal file
@ -0,0 +1,359 @@
|
||||
// A simple usage of the flexible sprite multiplexer routine
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
.label SPRITES_XPOS = $d000
|
||||
.label SPRITES_YPOS = $d001
|
||||
.label SPRITES_XMSB = $d010
|
||||
.label RASTER = $d012
|
||||
.label SPRITES_ENABLE = $d015
|
||||
.label BORDERCOL = $d020
|
||||
.label SPRITES_COLS = $d027
|
||||
.label VIC_CONTROL = $d011
|
||||
.label D011 = $d011
|
||||
.const VIC_DEN = $10
|
||||
.const VIC_RSEL = 8
|
||||
// VIC II IRQ Status Register
|
||||
.label IRQ_STATUS = $d019
|
||||
// VIC II IRQ Enable Register
|
||||
.label IRQ_ENABLE = $d01a
|
||||
// Bits for the IRQ Status/Enable Registers
|
||||
.const IRQ_RASTER = 1
|
||||
// CIA#1 Interrupt Status & Control Register
|
||||
.label CIA1_INTERRUPT = $dc0d
|
||||
// Value that disables all CIA interrupts when stored to the CIA Interrupt registers
|
||||
.const CIA_INTERRUPT_CLEAR = $7f
|
||||
// The vector used when the KERNAL serves IRQ interrupts
|
||||
.label KERNEL_IRQ = $314
|
||||
.const WHITE = 1
|
||||
.const RED = 2
|
||||
.const GREEN = 5
|
||||
// The number of sprites in the multiplexer
|
||||
.const PLEX_COUNT = $20
|
||||
.label SPRITE = $2000
|
||||
.label YSIN = $2100
|
||||
// The address of the sprite pointers on the current screen (screen+$3f8).
|
||||
.label PLEX_SCREEN_PTR = $400+$3f8
|
||||
.label plex_show_idx = 9
|
||||
.label plex_sprite_idx = 8
|
||||
.label plex_sprite_msb = $b
|
||||
.label plex_sprite_idx_1 = $e
|
||||
.label plex_free_next = $f
|
||||
.label framedone = 2
|
||||
.label plex_free_next_27 = $a
|
||||
.label plex_free_next_31 = $a
|
||||
bbegin:
|
||||
// The index in the PLEX tables of the next sprite to show
|
||||
lda #0
|
||||
sta plex_show_idx
|
||||
// The index the next sprite to use for showing (sprites are used round-robin)
|
||||
sta plex_sprite_idx
|
||||
// The MSB bit of the next sprite to use for showing
|
||||
lda #1
|
||||
sta plex_sprite_msb
|
||||
// The index of the sprite that is free next. Since sprites are used round-robin this moves forward each time a sprite is shown.
|
||||
lda #0
|
||||
sta plex_free_next_31
|
||||
lda #1
|
||||
sta framedone
|
||||
jsr main
|
||||
main: {
|
||||
sei
|
||||
jsr init
|
||||
jsr loop
|
||||
rts
|
||||
}
|
||||
// The raster loop
|
||||
loop: {
|
||||
.label sin_idx = 3
|
||||
.label y_idx = 4
|
||||
// The current index into the y-sinus
|
||||
lda #0
|
||||
sta sin_idx
|
||||
b1:
|
||||
// without volatile gives wrong asm
|
||||
b4:
|
||||
lda framedone
|
||||
cmp #0
|
||||
bne b6
|
||||
jmp b4
|
||||
b6:
|
||||
lda #RED
|
||||
sta BORDERCOL
|
||||
// Assign sinus positions
|
||||
lda sin_idx
|
||||
sta y_idx
|
||||
ldy #0
|
||||
// without volatile gives wrong asm
|
||||
b7:
|
||||
ldx y_idx
|
||||
lda YSIN,x
|
||||
sta PLEX_YPOS,y
|
||||
lax y_idx
|
||||
axs #-[8]
|
||||
stx y_idx
|
||||
iny
|
||||
cpy #PLEX_COUNT-1+1
|
||||
bne b7
|
||||
inc sin_idx
|
||||
inc BORDERCOL
|
||||
jsr plexSort
|
||||
lda #GREEN
|
||||
sta BORDERCOL
|
||||
lda #0
|
||||
sta framedone
|
||||
lda #$7f
|
||||
and VIC_CONTROL
|
||||
sta VIC_CONTROL
|
||||
lda #0
|
||||
sta RASTER
|
||||
jmp b1
|
||||
}
|
||||
// Ensure that the indices in PLEX_SORTED_IDX is sorted based on the y-positions in PLEX_YPOS
|
||||
// Assumes that the positions are nearly sorted already (as each sprite just moves a bit)
|
||||
// Uses an insertion sort:
|
||||
// 1. Moves a marker (m) from the start to end of the array. Every time the marker moves forward all elements before the marker are sorted correctly.
|
||||
// 2a. If the next element after the marker is larger that the current element
|
||||
// the marker can be moved forwards (as the sorting is correct).
|
||||
// 2b. If the next element after the marker is smaller than the current element:
|
||||
// elements before the marker are shifted right one at a time until encountering one smaller than the current one.
|
||||
// It is then inserted at the spot. Now the marker can move forward.
|
||||
plexSort: {
|
||||
.label nxt_idx = $c
|
||||
.label nxt_y = $d
|
||||
.label m = 5
|
||||
lda #0
|
||||
sta m
|
||||
b1:
|
||||
ldy m
|
||||
lda PLEX_SORTED_IDX+1,y
|
||||
sta nxt_idx
|
||||
tay
|
||||
lda PLEX_YPOS,y
|
||||
sta nxt_y
|
||||
ldx m
|
||||
ldy PLEX_SORTED_IDX,x
|
||||
cmp PLEX_YPOS,y
|
||||
bcs b2
|
||||
b3:
|
||||
lda PLEX_SORTED_IDX,x
|
||||
sta PLEX_SORTED_IDX+1,x
|
||||
dex
|
||||
cpx #$ff
|
||||
bne b8
|
||||
b5:
|
||||
inx
|
||||
lda nxt_idx
|
||||
sta PLEX_SORTED_IDX,x
|
||||
b2:
|
||||
inc m
|
||||
lda #PLEX_COUNT-2+1
|
||||
cmp m
|
||||
bne b1
|
||||
// Prepare for showing the sprites
|
||||
lda #0
|
||||
sta plex_show_idx
|
||||
sta plex_sprite_idx_1
|
||||
lda #1
|
||||
sta plex_sprite_msb
|
||||
ldx #0
|
||||
plexFreePrepare1_b1:
|
||||
lda #0
|
||||
sta PLEX_FREE_YPOS,x
|
||||
inx
|
||||
cpx #8
|
||||
bne plexFreePrepare1_b1
|
||||
sta plex_free_next
|
||||
rts
|
||||
b8:
|
||||
lda nxt_y
|
||||
ldy PLEX_SORTED_IDX,x
|
||||
cmp PLEX_YPOS,y
|
||||
bcc b3
|
||||
jmp b5
|
||||
}
|
||||
// Initialize the program
|
||||
init: {
|
||||
.label xp = 6
|
||||
lda #VIC_DEN|VIC_RSEL|3
|
||||
sta D011
|
||||
jsr plexInit
|
||||
lda #$20
|
||||
sta xp
|
||||
lda #0
|
||||
sta xp+1
|
||||
tax
|
||||
b1:
|
||||
lda #$ff&SPRITE/$40
|
||||
sta PLEX_PTR,x
|
||||
txa
|
||||
asl
|
||||
tay
|
||||
lda xp
|
||||
sta PLEX_XPOS,y
|
||||
lda xp+1
|
||||
sta PLEX_XPOS+1,y
|
||||
lda #9
|
||||
clc
|
||||
adc xp
|
||||
sta xp
|
||||
bcc !+
|
||||
inc xp+1
|
||||
!:
|
||||
inx
|
||||
cpx #PLEX_COUNT-1+1
|
||||
bne b1
|
||||
// Enable & initialize sprites
|
||||
lda #$ff
|
||||
sta SPRITES_ENABLE
|
||||
ldx #0
|
||||
b2:
|
||||
lda #GREEN
|
||||
sta SPRITES_COLS,x
|
||||
inx
|
||||
cpx #8
|
||||
bne b2
|
||||
// enable the interrupt
|
||||
sei
|
||||
lda #CIA_INTERRUPT_CLEAR
|
||||
sta CIA1_INTERRUPT
|
||||
lda #IRQ_RASTER
|
||||
sta IRQ_ENABLE
|
||||
sta IRQ_STATUS
|
||||
lda #<plex_irq
|
||||
sta KERNEL_IRQ
|
||||
lda #>plex_irq
|
||||
sta KERNEL_IRQ+1
|
||||
cli
|
||||
rts
|
||||
}
|
||||
// Initialize the multiplexer data structures
|
||||
plexInit: {
|
||||
ldx #0
|
||||
b1:
|
||||
txa
|
||||
sta PLEX_SORTED_IDX,x
|
||||
inx
|
||||
cpx #PLEX_COUNT-1+1
|
||||
bne b1
|
||||
rts
|
||||
}
|
||||
plex_irq: {
|
||||
.label _3 = 5
|
||||
lda #WHITE
|
||||
sta BORDERCOL
|
||||
b1:
|
||||
jsr plexShowSprite
|
||||
ldy plexShowSprite.plexFreeAdd1__2
|
||||
ldx PLEX_FREE_YPOS,y
|
||||
lda RASTER
|
||||
clc
|
||||
adc #2
|
||||
sta _3
|
||||
lda plex_show_idx
|
||||
cmp #PLEX_COUNT
|
||||
bcc b9
|
||||
b4:
|
||||
lda #IRQ_RASTER
|
||||
sta IRQ_STATUS
|
||||
lda plex_show_idx
|
||||
cmp #PLEX_COUNT
|
||||
bcc b2
|
||||
lda #1
|
||||
sta framedone
|
||||
b3:
|
||||
lda #0
|
||||
sta BORDERCOL
|
||||
jmp $ea81
|
||||
b2:
|
||||
stx RASTER
|
||||
jmp b3
|
||||
b9:
|
||||
cpx _3
|
||||
bcc b1
|
||||
jmp b4
|
||||
}
|
||||
// Show the next sprite.
|
||||
// plexSort() prepares showing the sprites
|
||||
plexShowSprite: {
|
||||
.label _8 = 8
|
||||
.label plex_sprite_idx2 = 5
|
||||
.label plexFreeAdd1__2 = $a
|
||||
lda plex_sprite_idx
|
||||
asl
|
||||
sta plex_sprite_idx2
|
||||
ldx plex_show_idx
|
||||
ldy PLEX_SORTED_IDX,x
|
||||
lda PLEX_YPOS,y
|
||||
ldy plex_sprite_idx2
|
||||
sta SPRITES_YPOS,y
|
||||
clc
|
||||
adc #$15
|
||||
ldy plex_free_next_27
|
||||
sta PLEX_FREE_YPOS,y
|
||||
ldx plex_free_next_27
|
||||
inx
|
||||
lda #7
|
||||
sax plexFreeAdd1__2
|
||||
ldx plex_show_idx
|
||||
ldy PLEX_SORTED_IDX,x
|
||||
lda PLEX_PTR,y
|
||||
ldx plex_sprite_idx
|
||||
sta PLEX_SCREEN_PTR,x
|
||||
ldx plex_show_idx
|
||||
lda PLEX_SORTED_IDX,x
|
||||
asl
|
||||
tax
|
||||
lda PLEX_XPOS,x
|
||||
ldy plex_sprite_idx2
|
||||
sta SPRITES_XPOS,y
|
||||
lda PLEX_XPOS+1,x
|
||||
cmp #0
|
||||
bne b1
|
||||
lda plex_sprite_msb
|
||||
eor #$ff
|
||||
and SPRITES_XMSB
|
||||
sta SPRITES_XMSB
|
||||
b2:
|
||||
ldx plex_sprite_idx
|
||||
inx
|
||||
lda #7
|
||||
sax _8
|
||||
inc plex_show_idx
|
||||
asl plex_sprite_msb
|
||||
lda plex_sprite_msb
|
||||
cmp #0
|
||||
bne breturn
|
||||
lda #1
|
||||
sta plex_sprite_msb
|
||||
breturn:
|
||||
rts
|
||||
b1:
|
||||
lda SPRITES_XMSB
|
||||
ora plex_sprite_msb
|
||||
sta SPRITES_XMSB
|
||||
jmp b2
|
||||
}
|
||||
// Contains the Y-position where each sprite is free again. PLEX_FREE_YPOS[s] holds the Y-position where sprite s is free to use again.
|
||||
PLEX_FREE_YPOS: .fill 8, 0
|
||||
// The x-positions of the multiplexer sprites ($000-$1ff)
|
||||
PLEX_XPOS: .fill 2*PLEX_COUNT, 0
|
||||
// The y-positions of the multiplexer sprites.
|
||||
PLEX_YPOS: .fill PLEX_COUNT, 0
|
||||
// The sprite pointers for the multiplexed sprites
|
||||
PLEX_PTR: .fill PLEX_COUNT, 0
|
||||
// Indexes of the plex-sprites sorted by sprite y-position. Each call to plexSort() will fix the sorting if changes to the Y-positions have ruined it.
|
||||
PLEX_SORTED_IDX: .fill PLEX_COUNT, 0
|
||||
.pc = YSIN "YSIN"
|
||||
.var min = 50
|
||||
.var max = 250-21
|
||||
.var ampl = max-min;
|
||||
.for(var i=0;i<256;i++)
|
||||
.byte round(min+(ampl/2)+(ampl/2)*sin(toRadians(360*i/256)))
|
||||
|
||||
.pc = SPRITE "SPRITE"
|
||||
.var pic = LoadPicture("balloon.png", List().add($000000, $ffffff))
|
||||
.for (var y=0; y<21; y++)
|
||||
.for (var x=0;x<3; x++)
|
||||
.byte pic.getSinglecolorByte(x,y)
|
||||
|
251
src/test/ref/multiplexer-irq/simple-multiplexer-irq.cfg
Normal file
251
src/test/ref/multiplexer-irq/simple-multiplexer-irq.cfg
Normal file
@ -0,0 +1,251 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@4
|
||||
@4: scope:[] from @begin
|
||||
[1] (byte) plex_show_idx#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
[2] (byte) plex_sprite_idx#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
[3] (byte) plex_sprite_msb#0 ← (byte/signed byte/word/signed word/dword/signed dword) 1
|
||||
to:@9
|
||||
@9: scope:[] from @4
|
||||
[4] (byte) plex_free_next#31 ← (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
to:@12
|
||||
@12: scope:[] from @9
|
||||
kickasm(location (const byte*) YSIN#0) {{ .var min = 50
|
||||
.var max = 250-21
|
||||
.var ampl = max-min;
|
||||
.for(var i=0;i<256;i++)
|
||||
.byte round(min+(ampl/2)+(ampl/2)*sin(toRadians(360*i/256)))
|
||||
}}
|
||||
kickasm(location (const byte*) SPRITE#0) {{ .var pic = LoadPicture("balloon.png", List().add($000000, $ffffff))
|
||||
.for (var y=0; y<21; y++)
|
||||
.for (var x=0;x<3; x++)
|
||||
.byte pic.getSinglecolorByte(x,y)
|
||||
}}
|
||||
to:@14
|
||||
@14: scope:[] from @12
|
||||
[7] (bool) framedone#19 ← true
|
||||
to:@16
|
||||
@16: scope:[] from @14
|
||||
[8] phi()
|
||||
[9] call main
|
||||
to:@end
|
||||
@end: scope:[] from @16
|
||||
[10] phi()
|
||||
main: scope:[main] from @16
|
||||
asm { sei }
|
||||
[12] call init
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[13] phi()
|
||||
[14] call loop
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[15] return
|
||||
to:@return
|
||||
loop: scope:[loop] from main::@1
|
||||
[16] (byte) loop::sin_idx#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
to:loop::@1
|
||||
loop::@1: scope:[loop] from loop loop::@15
|
||||
[17] (byte) loop::sin_idx#6 ← phi( loop/(byte) loop::sin_idx#0 loop::@15/(byte) loop::sin_idx#1 )
|
||||
[17] (bool) framedone#12 ← phi( loop/(bool) framedone#19 loop::@15/(bool) framedone#5 )
|
||||
to:loop::@4
|
||||
loop::@4: scope:[loop] from loop::@1 loop::@4
|
||||
[18] if((bool) framedone#12) goto loop::@6
|
||||
to:loop::@4
|
||||
loop::@6: scope:[loop] from loop::@4
|
||||
[19] *((const byte*) BORDERCOL#0) ← (const byte) RED#0
|
||||
[20] (byte) loop::y_idx#0 ← (byte) loop::sin_idx#6
|
||||
to:loop::@7
|
||||
loop::@7: scope:[loop] from loop::@6 loop::@7
|
||||
[21] (byte) loop::sy#2 ← phi( loop::@6/(byte/signed byte/word/signed word/dword/signed dword) 0 loop::@7/(byte) loop::sy#1 )
|
||||
[21] (byte) loop::y_idx#2 ← phi( loop::@6/(byte) loop::y_idx#0 loop::@7/(byte) loop::y_idx#1 )
|
||||
[22] *((const byte[PLEX_COUNT#0]) PLEX_YPOS#0 + (byte) loop::sy#2) ← *((const byte*) YSIN#0 + (byte) loop::y_idx#2)
|
||||
[23] (byte) loop::y_idx#1 ← (byte) loop::y_idx#2 + (byte/signed byte/word/signed word/dword/signed dword) 8
|
||||
[24] (byte) loop::sy#1 ← ++ (byte) loop::sy#2
|
||||
[25] if((byte) loop::sy#1!=(const byte) PLEX_COUNT#0-(byte/signed byte/word/signed word/dword/signed dword) 1+(byte/signed byte/word/signed word/dword/signed dword) 1) goto loop::@7
|
||||
to:loop::@13
|
||||
loop::@13: scope:[loop] from loop::@7
|
||||
[26] (byte) loop::sin_idx#1 ← (byte) loop::sin_idx#6 + (byte/signed byte/word/signed word/dword/signed dword) 1
|
||||
[27] *((const byte*) BORDERCOL#0) ← ++ *((const byte*) BORDERCOL#0)
|
||||
[28] call plexSort
|
||||
to:loop::@15
|
||||
loop::@15: scope:[loop] from loop::@13
|
||||
[29] *((const byte*) BORDERCOL#0) ← (const byte) GREEN#0
|
||||
[30] (bool) framedone#5 ← false
|
||||
[31] *((const byte*) VIC_CONTROL#0) ← *((const byte*) VIC_CONTROL#0) & (byte/signed byte/word/signed word/dword/signed dword) $7f
|
||||
[32] *((const byte*) RASTER#0) ← (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
to:loop::@1
|
||||
plexSort: scope:[plexSort] from loop::@13
|
||||
[33] phi()
|
||||
to:plexSort::@1
|
||||
plexSort::@1: scope:[plexSort] from plexSort plexSort::@2
|
||||
[34] (byte) plexSort::m#2 ← phi( plexSort/(byte/signed byte/word/signed word/dword/signed dword) 0 plexSort::@2/(byte) plexSort::m#1 )
|
||||
[35] (byte) plexSort::nxt_idx#0 ← *((const byte[PLEX_COUNT#0]) PLEX_SORTED_IDX#0+(byte/signed byte/word/signed word/dword/signed dword) 1 + (byte) plexSort::m#2)
|
||||
[36] (byte) plexSort::nxt_y#0 ← *((const byte[PLEX_COUNT#0]) PLEX_YPOS#0 + (byte) plexSort::nxt_idx#0)
|
||||
[37] if((byte) plexSort::nxt_y#0>=*((const byte[PLEX_COUNT#0]) PLEX_YPOS#0 + *((const byte[PLEX_COUNT#0]) PLEX_SORTED_IDX#0 + (byte) plexSort::m#2))) goto plexSort::@2
|
||||
to:plexSort::@11
|
||||
plexSort::@11: scope:[plexSort] from plexSort::@1
|
||||
[38] (byte~) plexSort::s#6 ← (byte) plexSort::m#2
|
||||
to:plexSort::@3
|
||||
plexSort::@3: scope:[plexSort] from plexSort::@11 plexSort::@8
|
||||
[39] (byte) plexSort::s#3 ← phi( plexSort::@8/(byte) plexSort::s#1 plexSort::@11/(byte~) plexSort::s#6 )
|
||||
[40] *((const byte[PLEX_COUNT#0]) PLEX_SORTED_IDX#0+(byte/signed byte/word/signed word/dword/signed dword) 1 + (byte) plexSort::s#3) ← *((const byte[PLEX_COUNT#0]) PLEX_SORTED_IDX#0 + (byte) plexSort::s#3)
|
||||
[41] (byte) plexSort::s#1 ← -- (byte) plexSort::s#3
|
||||
[42] if((byte) plexSort::s#1!=(byte/word/signed word/dword/signed dword) $ff) goto plexSort::@8
|
||||
to:plexSort::@5
|
||||
plexSort::@5: scope:[plexSort] from plexSort::@3 plexSort::@8
|
||||
[43] (byte) plexSort::s#2 ← ++ (byte) plexSort::s#1
|
||||
[44] *((const byte[PLEX_COUNT#0]) PLEX_SORTED_IDX#0 + (byte) plexSort::s#2) ← (byte) plexSort::nxt_idx#0
|
||||
to:plexSort::@2
|
||||
plexSort::@2: scope:[plexSort] from plexSort::@1 plexSort::@5
|
||||
[45] (byte) plexSort::m#1 ← ++ (byte) plexSort::m#2
|
||||
[46] if((byte) plexSort::m#1!=(const byte) PLEX_COUNT#0-(byte/signed byte/word/signed word/dword/signed dword) 2+(byte/signed byte/word/signed word/dword/signed dword) 1) goto plexSort::@1
|
||||
to:plexSort::@6
|
||||
plexSort::@6: scope:[plexSort] from plexSort::@2
|
||||
[47] (byte) plex_show_idx#1 ← (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
[48] (byte) plex_sprite_idx#1 ← (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
[49] (byte) plex_sprite_msb#1 ← (byte/signed byte/word/signed word/dword/signed dword) 1
|
||||
to:plexSort::plexFreePrepare1
|
||||
plexSort::plexFreePrepare1: scope:[plexSort] from plexSort::@6
|
||||
[50] phi()
|
||||
to:plexSort::plexFreePrepare1_@1
|
||||
plexSort::plexFreePrepare1_@1: scope:[plexSort] from plexSort::plexFreePrepare1 plexSort::plexFreePrepare1_@1
|
||||
[51] (byte) plexSort::plexFreePrepare1_s#2 ← phi( plexSort::plexFreePrepare1/(byte/signed byte/word/signed word/dword/signed dword) 0 plexSort::plexFreePrepare1_@1/(byte) plexSort::plexFreePrepare1_s#1 )
|
||||
[52] *((const byte[8]) PLEX_FREE_YPOS#0 + (byte) plexSort::plexFreePrepare1_s#2) ← (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
[53] (byte) plexSort::plexFreePrepare1_s#1 ← ++ (byte) plexSort::plexFreePrepare1_s#2
|
||||
[54] if((byte) plexSort::plexFreePrepare1_s#1!=(byte/signed byte/word/signed word/dword/signed dword) 8) goto plexSort::plexFreePrepare1_@1
|
||||
to:plexSort::plexFreePrepare1_@2
|
||||
plexSort::plexFreePrepare1_@2: scope:[plexSort] from plexSort::plexFreePrepare1_@1
|
||||
[55] (byte) plex_free_next#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
to:plexSort::@return
|
||||
plexSort::@return: scope:[plexSort] from plexSort::plexFreePrepare1_@2
|
||||
[56] return
|
||||
to:@return
|
||||
plexSort::@8: scope:[plexSort] from plexSort::@3
|
||||
[57] if((byte) plexSort::nxt_y#0<*((const byte[PLEX_COUNT#0]) PLEX_YPOS#0 + *((const byte[PLEX_COUNT#0]) PLEX_SORTED_IDX#0 + (byte) plexSort::s#1))) goto plexSort::@3
|
||||
to:plexSort::@5
|
||||
init: scope:[init] from main
|
||||
[58] *((const byte*) D011#0) ← (const byte) VIC_DEN#0|(const byte) VIC_RSEL#0|(byte/signed byte/word/signed word/dword/signed dword) 3
|
||||
[59] call plexInit
|
||||
to:init::@1
|
||||
init::@1: scope:[init] from init init::@1
|
||||
[60] (word) init::xp#2 ← phi( init::@1/(word) init::xp#1 init/(byte/signed byte/word/signed word/dword/signed dword) $20 )
|
||||
[60] (byte) init::sx#2 ← phi( init::@1/(byte) init::sx#1 init/(byte/signed byte/word/signed word/dword/signed dword) 0 )
|
||||
[61] *((const byte[PLEX_COUNT#0]) PLEX_PTR#0 + (byte) init::sx#2) ← ((byte))(const byte*) SPRITE#0/(byte/signed byte/word/signed word/dword/signed dword) $40
|
||||
[62] (byte~) init::$6 ← (byte) init::sx#2 << (byte/signed byte/word/signed word/dword/signed dword) 1
|
||||
[63] *((const word[PLEX_COUNT#0]) PLEX_XPOS#0 + (byte~) init::$6) ← (word) init::xp#2
|
||||
[64] (word) init::xp#1 ← (word) init::xp#2 + (byte/signed byte/word/signed word/dword/signed dword) 9
|
||||
[65] (byte) init::sx#1 ← ++ (byte) init::sx#2
|
||||
[66] if((byte) init::sx#1!=(const byte) PLEX_COUNT#0-(byte/signed byte/word/signed word/dword/signed dword) 1+(byte/signed byte/word/signed word/dword/signed dword) 1) goto init::@1
|
||||
to:init::@3
|
||||
init::@3: scope:[init] from init::@1
|
||||
[67] *((const byte*) SPRITES_ENABLE#0) ← (byte/word/signed word/dword/signed dword) $ff
|
||||
to:init::@2
|
||||
init::@2: scope:[init] from init::@2 init::@3
|
||||
[68] (byte) init::ss#2 ← phi( init::@2/(byte) init::ss#1 init::@3/(byte/signed byte/word/signed word/dword/signed dword) 0 )
|
||||
[69] *((const byte*) SPRITES_COLS#0 + (byte) init::ss#2) ← (const byte) GREEN#0
|
||||
[70] (byte) init::ss#1 ← ++ (byte) init::ss#2
|
||||
[71] if((byte) init::ss#1!=(byte/signed byte/word/signed word/dword/signed dword) 8) goto init::@2
|
||||
to:init::@4
|
||||
init::@4: scope:[init] from init::@2
|
||||
asm { sei }
|
||||
[73] *((const byte*) CIA1_INTERRUPT#0) ← (const byte) CIA_INTERRUPT_CLEAR#0
|
||||
[74] *((const byte*) IRQ_ENABLE#0) ← (const byte) IRQ_RASTER#0
|
||||
[75] *((const byte*) IRQ_STATUS#0) ← (const byte) IRQ_RASTER#0
|
||||
[76] *((const void()**) KERNEL_IRQ#0) ← &interrupt(KERNEL_MIN)(void()) plex_irq()
|
||||
asm { cli }
|
||||
to:init::@return
|
||||
init::@return: scope:[init] from init::@4
|
||||
[78] return
|
||||
to:@return
|
||||
plexInit: scope:[plexInit] from init
|
||||
[79] phi()
|
||||
to:plexInit::plexSetScreen1
|
||||
plexInit::plexSetScreen1: scope:[plexInit] from plexInit
|
||||
[80] phi()
|
||||
to:plexInit::@1
|
||||
plexInit::@1: scope:[plexInit] from plexInit::@1 plexInit::plexSetScreen1
|
||||
[81] (byte) plexInit::i#2 ← phi( plexInit::@1/(byte) plexInit::i#1 plexInit::plexSetScreen1/(byte/signed byte/word/signed word/dword/signed dword) 0 )
|
||||
[82] *((const byte[PLEX_COUNT#0]) PLEX_SORTED_IDX#0 + (byte) plexInit::i#2) ← (byte) plexInit::i#2
|
||||
[83] (byte) plexInit::i#1 ← ++ (byte) plexInit::i#2
|
||||
[84] if((byte) plexInit::i#1!=(const byte) PLEX_COUNT#0-(byte/signed byte/word/signed word/dword/signed dword) 1+(byte/signed byte/word/signed word/dword/signed dword) 1) goto plexInit::@1
|
||||
to:plexInit::@return
|
||||
plexInit::@return: scope:[plexInit] from plexInit::@1
|
||||
[85] return
|
||||
to:@return
|
||||
plex_irq: scope:[plex_irq] from
|
||||
[86] *((const byte*) BORDERCOL#0) ← (const byte) WHITE#0
|
||||
to:plex_irq::@1
|
||||
plex_irq::@1: scope:[plex_irq] from plex_irq plex_irq::@9
|
||||
[87] (byte) plex_sprite_msb#29 ← phi( plex_irq/(byte) plex_sprite_msb#0 plex_irq::@9/(byte) plex_sprite_msb#17 )
|
||||
[87] (byte) plex_free_next#27 ← phi( plex_irq/(byte) plex_free_next#31 plex_irq::@9/(byte/word/dword) plexShowSprite::plexFreeAdd1_$2#0 )
|
||||
[87] (byte) plex_show_idx#27 ← phi( plex_irq/(byte) plex_show_idx#0 plex_irq::@9/(byte) plex_show_idx#16 )
|
||||
[87] (byte) plex_sprite_idx#25 ← phi( plex_irq/(byte) plex_sprite_idx#0 plex_irq::@9/(byte/word/dword~) plexShowSprite::$8 )
|
||||
[88] call plexShowSprite
|
||||
to:plex_irq::plexFreeNextYpos1
|
||||
plex_irq::plexFreeNextYpos1: scope:[plex_irq] from plex_irq::@1
|
||||
[89] (byte) plex_irq::plexFreeNextYpos1_return#0 ← *((const byte[8]) PLEX_FREE_YPOS#0 + (byte/word/dword) plexShowSprite::plexFreeAdd1_$2#0)
|
||||
to:plex_irq::@7
|
||||
plex_irq::@7: scope:[plex_irq] from plex_irq::plexFreeNextYpos1
|
||||
[90] (byte/signed word/word/dword/signed dword~) plex_irq::$3 ← *((const byte*) RASTER#0) + (byte/signed byte/word/signed word/dword/signed dword) 2
|
||||
[91] if((byte) plex_show_idx#16<(const byte) PLEX_COUNT#0) goto plex_irq::@9
|
||||
to:plex_irq::@4
|
||||
plex_irq::@4: scope:[plex_irq] from plex_irq::@7 plex_irq::@9
|
||||
[92] *((const byte*) IRQ_STATUS#0) ← (const byte) IRQ_RASTER#0
|
||||
[93] if((byte) plex_show_idx#16<(const byte) PLEX_COUNT#0) goto plex_irq::@2
|
||||
to:plex_irq::@5
|
||||
plex_irq::@5: scope:[plex_irq] from plex_irq::@4
|
||||
[94] (bool) framedone#3 ← true
|
||||
to:plex_irq::@3
|
||||
plex_irq::@3: scope:[plex_irq] from plex_irq::@2 plex_irq::@5
|
||||
[95] *((const byte*) BORDERCOL#0) ← (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
to:plex_irq::@return
|
||||
plex_irq::@return: scope:[plex_irq] from plex_irq::@3
|
||||
[96] return
|
||||
to:@return
|
||||
plex_irq::@2: scope:[plex_irq] from plex_irq::@4
|
||||
[97] *((const byte*) RASTER#0) ← (byte) plex_irq::plexFreeNextYpos1_return#0
|
||||
to:plex_irq::@3
|
||||
plex_irq::@9: scope:[plex_irq] from plex_irq::@7
|
||||
[98] if((byte) plex_irq::plexFreeNextYpos1_return#0<(byte/signed word/word/dword/signed dword~) plex_irq::$3) goto plex_irq::@1
|
||||
to:plex_irq::@4
|
||||
plexShowSprite: scope:[plexShowSprite] from plex_irq::@1
|
||||
[99] (byte) plexShowSprite::plex_sprite_idx2#0 ← (byte) plex_sprite_idx#25 << (byte/signed byte/word/signed word/dword/signed dword) 1
|
||||
[100] (byte) plexShowSprite::plexFreeAdd1_ypos#0 ← *((const byte[PLEX_COUNT#0]) PLEX_YPOS#0 + *((const byte[PLEX_COUNT#0]) PLEX_SORTED_IDX#0 + (byte) plex_show_idx#27))
|
||||
[101] *((const byte*) SPRITES_YPOS#0 + (byte) plexShowSprite::plex_sprite_idx2#0) ← (byte) plexShowSprite::plexFreeAdd1_ypos#0
|
||||
to:plexShowSprite::plexFreeAdd1
|
||||
plexShowSprite::plexFreeAdd1: scope:[plexShowSprite] from plexShowSprite
|
||||
[102] (byte/signed word/word/dword/signed dword) plexShowSprite::plexFreeAdd1_$0#0 ← (byte) plexShowSprite::plexFreeAdd1_ypos#0 + (byte/signed byte/word/signed word/dword/signed dword) $15
|
||||
[103] *((const byte[8]) PLEX_FREE_YPOS#0 + (byte) plex_free_next#27) ← (byte/signed word/word/dword/signed dword) plexShowSprite::plexFreeAdd1_$0#0
|
||||
[104] (byte/signed word/word/dword/signed dword) plexShowSprite::plexFreeAdd1_$1#0 ← (byte) plex_free_next#27 + (byte/signed byte/word/signed word/dword/signed dword) 1
|
||||
[105] (byte/word/dword) plexShowSprite::plexFreeAdd1_$2#0 ← (byte/signed word/word/dword/signed dword) plexShowSprite::plexFreeAdd1_$1#0 & (byte/signed byte/word/signed word/dword/signed dword) 7
|
||||
to:plexShowSprite::@7
|
||||
plexShowSprite::@7: scope:[plexShowSprite] from plexShowSprite::plexFreeAdd1
|
||||
[106] *((const byte*) PLEX_SCREEN_PTR#0 + (byte) plex_sprite_idx#25) ← *((const byte[PLEX_COUNT#0]) PLEX_PTR#0 + *((const byte[PLEX_COUNT#0]) PLEX_SORTED_IDX#0 + (byte) plex_show_idx#27))
|
||||
[107] (byte) plexShowSprite::xpos_idx#0 ← *((const byte[PLEX_COUNT#0]) PLEX_SORTED_IDX#0 + (byte) plex_show_idx#27) << (byte/signed byte/word/signed word/dword/signed dword) 1
|
||||
[108] (byte~) plexShowSprite::$3 ← < *((const word[PLEX_COUNT#0]) PLEX_XPOS#0 + (byte) plexShowSprite::xpos_idx#0)
|
||||
[109] *((const byte*) SPRITES_XPOS#0 + (byte) plexShowSprite::plex_sprite_idx2#0) ← (byte~) plexShowSprite::$3
|
||||
[110] (byte~) plexShowSprite::$4 ← > *((const word[PLEX_COUNT#0]) PLEX_XPOS#0 + (byte) plexShowSprite::xpos_idx#0)
|
||||
[111] if((byte~) plexShowSprite::$4!=(byte/signed byte/word/signed word/dword/signed dword) 0) goto plexShowSprite::@1
|
||||
to:plexShowSprite::@4
|
||||
plexShowSprite::@4: scope:[plexShowSprite] from plexShowSprite::@7
|
||||
[112] (byte/word/dword~) plexShowSprite::$6 ← (byte/word/signed word/dword/signed dword) $ff ^ (byte) plex_sprite_msb#29
|
||||
[113] *((const byte*) SPRITES_XMSB#0) ← *((const byte*) SPRITES_XMSB#0) & (byte/word/dword~) plexShowSprite::$6
|
||||
to:plexShowSprite::@2
|
||||
plexShowSprite::@2: scope:[plexShowSprite] from plexShowSprite::@1 plexShowSprite::@4
|
||||
[114] (byte/signed word/word/dword/signed dword~) plexShowSprite::$7 ← (byte) plex_sprite_idx#25 + (byte/signed byte/word/signed word/dword/signed dword) 1
|
||||
[115] (byte/word/dword~) plexShowSprite::$8 ← (byte/signed word/word/dword/signed dword~) plexShowSprite::$7 & (byte/signed byte/word/signed word/dword/signed dword) 7
|
||||
[116] (byte) plex_show_idx#16 ← ++ (byte) plex_show_idx#27
|
||||
[117] (byte) plex_sprite_msb#27 ← (byte) plex_sprite_msb#29 << (byte/signed byte/word/signed word/dword/signed dword) 1
|
||||
[118] if((byte) plex_sprite_msb#27!=(byte/signed byte/word/signed word/dword/signed dword) 0) goto plexShowSprite::@return
|
||||
to:plexShowSprite::@6
|
||||
plexShowSprite::@6: scope:[plexShowSprite] from plexShowSprite::@2
|
||||
[119] (byte) plex_sprite_msb#4 ← (byte/signed byte/word/signed word/dword/signed dword) 1
|
||||
to:plexShowSprite::@return
|
||||
plexShowSprite::@return: scope:[plexShowSprite] from plexShowSprite::@2 plexShowSprite::@6
|
||||
[120] (byte) plex_sprite_msb#17 ← phi( plexShowSprite::@2/(byte) plex_sprite_msb#27 plexShowSprite::@6/(byte) plex_sprite_msb#4 )
|
||||
[121] return
|
||||
to:@return
|
||||
plexShowSprite::@1: scope:[plexShowSprite] from plexShowSprite::@7
|
||||
[122] *((const byte*) SPRITES_XMSB#0) ← *((const byte*) SPRITES_XMSB#0) | (byte) plex_sprite_msb#29
|
||||
to:plexShowSprite::@2
|
5160
src/test/ref/multiplexer-irq/simple-multiplexer-irq.log
Normal file
5160
src/test/ref/multiplexer-irq/simple-multiplexer-irq.log
Normal file
File diff suppressed because it is too large
Load Diff
296
src/test/ref/multiplexer-irq/simple-multiplexer-irq.sym
Normal file
296
src/test/ref/multiplexer-irq/simple-multiplexer-irq.sym
Normal file
@ -0,0 +1,296 @@
|
||||
(label) @12
|
||||
(label) @14
|
||||
(label) @16
|
||||
(label) @4
|
||||
(label) @9
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte*) BGCOL
|
||||
(byte*) BGCOL1
|
||||
(byte*) BGCOL2
|
||||
(byte*) BGCOL3
|
||||
(byte*) BGCOL4
|
||||
(byte) BLACK
|
||||
(byte) BLUE
|
||||
(byte*) BORDERCOL
|
||||
(const byte*) BORDERCOL#0 BORDERCOL = ((byte*))(word/dword/signed dword) $d020
|
||||
(byte) BROWN
|
||||
(byte*) CHARGEN
|
||||
(byte*) CIA1_INTERRUPT
|
||||
(const byte*) CIA1_INTERRUPT#0 CIA1_INTERRUPT = ((byte*))(word/dword/signed dword) $dc0d
|
||||
(byte*) CIA1_PORT_A
|
||||
(byte*) CIA1_PORT_A_DDR
|
||||
(byte*) CIA1_PORT_B
|
||||
(byte*) CIA1_PORT_B_DDR
|
||||
(byte*) CIA2_INTERRUPT
|
||||
(byte*) CIA2_PORT_A
|
||||
(byte*) CIA2_PORT_A_DDR
|
||||
(byte*) CIA2_PORT_B
|
||||
(byte*) CIA2_PORT_B_DDR
|
||||
(byte) CIA_INTERRUPT_CLEAR
|
||||
(const byte) CIA_INTERRUPT_CLEAR#0 CIA_INTERRUPT_CLEAR = (byte/signed byte/word/signed word/dword/signed dword) $7f
|
||||
(byte*) COLS
|
||||
(byte) CYAN
|
||||
(byte*) D011
|
||||
(const byte*) D011#0 D011 = ((byte*))(word/dword/signed dword) $d011
|
||||
(byte*) D016
|
||||
(byte*) D018
|
||||
(byte) DARK_GREY
|
||||
(byte) GREEN
|
||||
(const byte) GREEN#0 GREEN = (byte/signed byte/word/signed word/dword/signed dword) 5
|
||||
(byte) GREY
|
||||
(void()**) HARDWARE_IRQ
|
||||
(byte) IRQ_COLLISION_BG
|
||||
(byte) IRQ_COLLISION_SPRITE
|
||||
(byte*) IRQ_ENABLE
|
||||
(const byte*) IRQ_ENABLE#0 IRQ_ENABLE = ((byte*))(word/dword/signed dword) $d01a
|
||||
(byte) IRQ_LIGHTPEN
|
||||
(byte) IRQ_RASTER
|
||||
(const byte) IRQ_RASTER#0 IRQ_RASTER = (byte/signed byte/word/signed word/dword/signed dword) 1
|
||||
(byte*) IRQ_STATUS
|
||||
(const byte*) IRQ_STATUS#0 IRQ_STATUS = ((byte*))(word/dword/signed dword) $d019
|
||||
(void()**) KERNEL_IRQ
|
||||
(const void()**) KERNEL_IRQ#0 KERNEL_IRQ = ((void()**))(word/signed word/dword/signed dword) $314
|
||||
(byte*) LIGHTPEN_X
|
||||
(byte*) LIGHTPEN_Y
|
||||
(byte) LIGHT_BLUE
|
||||
(byte) LIGHT_GREEN
|
||||
(byte) LIGHT_GREY
|
||||
(byte) ORANGE
|
||||
(byte) PINK
|
||||
(byte) PLEX_COUNT
|
||||
(const byte) PLEX_COUNT#0 PLEX_COUNT = (byte/signed byte/word/signed word/dword/signed dword) $20
|
||||
(byte[8]) PLEX_FREE_YPOS
|
||||
(const byte[8]) PLEX_FREE_YPOS#0 PLEX_FREE_YPOS = { fill( 8, 0) }
|
||||
(byte[PLEX_COUNT#0]) PLEX_PTR
|
||||
(const byte[PLEX_COUNT#0]) PLEX_PTR#0 PLEX_PTR = { fill( PLEX_COUNT#0, 0) }
|
||||
(byte*) PLEX_SCREEN_PTR
|
||||
(const byte*) PLEX_SCREEN_PTR#0 PLEX_SCREEN_PTR = ((byte*))(word/signed word/dword/signed dword) $400+(word/signed word/dword/signed dword) $3f8
|
||||
(byte[PLEX_COUNT#0]) PLEX_SORTED_IDX
|
||||
(const byte[PLEX_COUNT#0]) PLEX_SORTED_IDX#0 PLEX_SORTED_IDX = { fill( PLEX_COUNT#0, 0) }
|
||||
(word[PLEX_COUNT#0]) PLEX_XPOS
|
||||
(const word[PLEX_COUNT#0]) PLEX_XPOS#0 PLEX_XPOS = { fill( PLEX_COUNT#0, 0) }
|
||||
(byte[PLEX_COUNT#0]) PLEX_YPOS
|
||||
(const byte[PLEX_COUNT#0]) PLEX_YPOS#0 PLEX_YPOS = { fill( PLEX_COUNT#0, 0) }
|
||||
(byte*) PROCPORT
|
||||
(byte) PROCPORT_BASIC_KERNEL_IO
|
||||
(byte*) PROCPORT_DDR
|
||||
(byte) PROCPORT_DDR_MEMORY_MASK
|
||||
(byte) PROCPORT_KERNEL_IO
|
||||
(byte) PROCPORT_RAM_ALL
|
||||
(byte) PROCPORT_RAM_CHARROM
|
||||
(byte) PROCPORT_RAM_IO
|
||||
(byte) PURPLE
|
||||
(byte*) RASTER
|
||||
(const byte*) RASTER#0 RASTER = ((byte*))(word/dword/signed dword) $d012
|
||||
(byte) RED
|
||||
(const byte) RED#0 RED = (byte/signed byte/word/signed word/dword/signed dword) 2
|
||||
(byte*) SCREEN
|
||||
(byte*) SPRITE
|
||||
(const byte*) SPRITE#0 SPRITE = ((byte*))(word/signed word/dword/signed dword) $2000
|
||||
(byte*) SPRITES_COLS
|
||||
(const byte*) SPRITES_COLS#0 SPRITES_COLS = ((byte*))(word/dword/signed dword) $d027
|
||||
(byte*) SPRITES_ENABLE
|
||||
(const byte*) SPRITES_ENABLE#0 SPRITES_ENABLE = ((byte*))(word/dword/signed dword) $d015
|
||||
(byte*) SPRITES_EXPAND_X
|
||||
(byte*) SPRITES_EXPAND_Y
|
||||
(byte*) SPRITES_MC
|
||||
(byte*) SPRITES_MC1
|
||||
(byte*) SPRITES_MC2
|
||||
(byte*) SPRITES_PRIORITY
|
||||
(byte*) SPRITES_XMSB
|
||||
(const byte*) SPRITES_XMSB#0 SPRITES_XMSB = ((byte*))(word/dword/signed dword) $d010
|
||||
(byte*) SPRITES_XPOS
|
||||
(const byte*) SPRITES_XPOS#0 SPRITES_XPOS = ((byte*))(word/dword/signed dword) $d000
|
||||
(byte*) SPRITES_YPOS
|
||||
(const byte*) SPRITES_YPOS#0 SPRITES_YPOS = ((byte*))(word/dword/signed dword) $d001
|
||||
(word) SPRITE_PTRS
|
||||
(byte) VIC_BMM
|
||||
(byte*) VIC_CONTROL
|
||||
(const byte*) VIC_CONTROL#0 VIC_CONTROL = ((byte*))(word/dword/signed dword) $d011
|
||||
(byte*) VIC_CONTROL2
|
||||
(byte) VIC_CSEL
|
||||
(byte) VIC_DEN
|
||||
(const byte) VIC_DEN#0 VIC_DEN = (byte/signed byte/word/signed word/dword/signed dword) $10
|
||||
(byte) VIC_ECM
|
||||
(byte) VIC_MCM
|
||||
(byte*) VIC_MEMORY
|
||||
(byte) VIC_RSEL
|
||||
(const byte) VIC_RSEL#0 VIC_RSEL = (byte/signed byte/word/signed word/dword/signed dword) 8
|
||||
(byte) VIC_RST8
|
||||
(byte) WHITE
|
||||
(const byte) WHITE#0 WHITE = (byte/signed byte/word/signed word/dword/signed dword) 1
|
||||
(byte) YELLOW
|
||||
(byte*) YSIN
|
||||
(const byte*) YSIN#0 YSIN = ((byte*))(word/signed word/dword/signed dword) $2100
|
||||
(bool) framedone
|
||||
(bool) framedone#12 framedone zp ZP_BOOL:2 57.0
|
||||
(bool) framedone#19 framedone zp ZP_BOOL:2 0.6666666666666666
|
||||
(bool) framedone#3 framedone zp ZP_BOOL:2 20.0
|
||||
(bool) framedone#5 framedone zp ZP_BOOL:2 7.333333333333333
|
||||
(void()) init()
|
||||
(byte~) init::$6 reg byte a 22.0
|
||||
(label) init::@1
|
||||
(label) init::@2
|
||||
(label) init::@3
|
||||
(label) init::@4
|
||||
(label) init::@return
|
||||
(byte) init::ss
|
||||
(byte) init::ss#1 reg byte x 16.5
|
||||
(byte) init::ss#2 reg byte x 16.5
|
||||
(byte) init::sx
|
||||
(byte) init::sx#1 reg byte x 16.5
|
||||
(byte) init::sx#2 reg byte x 8.8
|
||||
(word) init::xp
|
||||
(word) init::xp#1 xp zp ZP_WORD:6 7.333333333333333
|
||||
(word) init::xp#2 xp zp ZP_WORD:6 8.25
|
||||
(void()) loop()
|
||||
(label) loop::@1
|
||||
(label) loop::@13
|
||||
(label) loop::@15
|
||||
(label) loop::@4
|
||||
(label) loop::@6
|
||||
(label) loop::@7
|
||||
(byte) loop::sin_idx
|
||||
(byte) loop::sin_idx#0 sin_idx zp ZP_BYTE:3 4.0
|
||||
(byte) loop::sin_idx#1 sin_idx zp ZP_BYTE:3 3.142857142857143
|
||||
(byte) loop::sin_idx#6 sin_idx zp ZP_BYTE:3 3.8888888888888893
|
||||
(byte) loop::sy
|
||||
(byte) loop::sy#1 reg byte y 151.5
|
||||
(byte) loop::sy#2 reg byte y 101.0
|
||||
(byte) loop::y_idx
|
||||
(byte) loop::y_idx#0 y_idx zp ZP_BYTE:4 22.0
|
||||
(byte) loop::y_idx#1 y_idx zp ZP_BYTE:4 67.33333333333333
|
||||
(byte) loop::y_idx#2 y_idx zp ZP_BYTE:4 157.0
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(void()) plexInit((byte*) plexInit::screen)
|
||||
(label) plexInit::@1
|
||||
(label) plexInit::@return
|
||||
(byte) plexInit::i
|
||||
(byte) plexInit::i#1 reg byte x 16.5
|
||||
(byte) plexInit::i#2 reg byte x 22.0
|
||||
(label) plexInit::plexSetScreen1
|
||||
(byte*~) plexInit::plexSetScreen1_$0
|
||||
(byte*) plexInit::plexSetScreen1_screen
|
||||
(byte*) plexInit::screen
|
||||
(void()) plexShowSprite()
|
||||
(byte~) plexShowSprite::$3 reg byte a 4.0
|
||||
(byte~) plexShowSprite::$4 reg byte a 4.0
|
||||
(byte/word/dword~) plexShowSprite::$6 reg byte a 4.0
|
||||
(byte/signed word/word/dword/signed dword~) plexShowSprite::$7 reg byte x 4.0
|
||||
(byte/word/dword~) plexShowSprite::$8 $8 zp ZP_BYTE:8 1.0833333333333333
|
||||
(label) plexShowSprite::@1
|
||||
(label) plexShowSprite::@2
|
||||
(label) plexShowSprite::@4
|
||||
(label) plexShowSprite::@6
|
||||
(label) plexShowSprite::@7
|
||||
(label) plexShowSprite::@return
|
||||
(label) plexShowSprite::plexFreeAdd1
|
||||
(byte/signed word/word/dword/signed dword~) plexShowSprite::plexFreeAdd1_$0
|
||||
(byte/signed word/word/dword/signed dword) plexShowSprite::plexFreeAdd1_$0#0 reg byte a 4.0
|
||||
(byte/signed word/word/dword/signed dword~) plexShowSprite::plexFreeAdd1_$1
|
||||
(byte/signed word/word/dword/signed dword) plexShowSprite::plexFreeAdd1_$1#0 reg byte x 4.0
|
||||
(byte/word/dword~) plexShowSprite::plexFreeAdd1_$2
|
||||
(byte/word/dword) plexShowSprite::plexFreeAdd1_$2#0 plexFreeAdd1_$2 zp ZP_BYTE:10 1.0434782608695652
|
||||
(byte) plexShowSprite::plexFreeAdd1_ypos
|
||||
(byte) plexShowSprite::plexFreeAdd1_ypos#0 reg byte a 3.0
|
||||
(byte) plexShowSprite::plex_sprite_idx2
|
||||
(byte) plexShowSprite::plex_sprite_idx2#0 plex_sprite_idx2 zp ZP_BYTE:5 0.6000000000000001
|
||||
(byte) plexShowSprite::xpos_idx
|
||||
(byte) plexShowSprite::xpos_idx#0 reg byte x 2.0
|
||||
(byte) plexShowSprite::ypos
|
||||
(void()) plexSort()
|
||||
(label) plexSort::@1
|
||||
(label) plexSort::@11
|
||||
(label) plexSort::@2
|
||||
(label) plexSort::@3
|
||||
(label) plexSort::@5
|
||||
(label) plexSort::@6
|
||||
(label) plexSort::@8
|
||||
(label) plexSort::@return
|
||||
(byte) plexSort::m
|
||||
(byte) plexSort::m#1 m zp ZP_BYTE:5 151.5
|
||||
(byte) plexSort::m#2 m zp ZP_BYTE:5 42.08333333333333
|
||||
(byte) plexSort::nxt_idx
|
||||
(byte) plexSort::nxt_idx#0 nxt_idx zp ZP_BYTE:12 30.299999999999997
|
||||
(byte) plexSort::nxt_y
|
||||
(byte) plexSort::nxt_y#0 nxt_y zp ZP_BYTE:13 150.375
|
||||
(label) plexSort::plexFreePrepare1
|
||||
(bool~) plexSort::plexFreePrepare1_$0
|
||||
(label) plexSort::plexFreePrepare1_@1
|
||||
(label) plexSort::plexFreePrepare1_@2
|
||||
(byte) plexSort::plexFreePrepare1_s
|
||||
(byte) plexSort::plexFreePrepare1_s#1 reg byte x 151.5
|
||||
(byte) plexSort::plexFreePrepare1_s#2 reg byte x 151.5
|
||||
(byte) plexSort::s
|
||||
(byte) plexSort::s#1 reg byte x 1368.3333333333335
|
||||
(byte) plexSort::s#2 reg byte x 202.0
|
||||
(byte) plexSort::s#3 reg byte x 2052.5
|
||||
(byte~) plexSort::s#6 reg byte x 202.0
|
||||
(byte) plex_free_next
|
||||
(byte) plex_free_next#0 plex_free_next zp ZP_BYTE:15 20.0
|
||||
(byte) plex_free_next#27 plex_free_next#27 zp ZP_BYTE:10 2.8333333333333335
|
||||
(byte) plex_free_next#31 plex_free_next#31 zp ZP_BYTE:10 4.0
|
||||
interrupt(KERNEL_MIN)(void()) plex_irq()
|
||||
(byte/signed word/word/dword/signed dword~) plex_irq::$3 $3 zp ZP_BYTE:5 11.0
|
||||
(label) plex_irq::@1
|
||||
(label) plex_irq::@2
|
||||
(label) plex_irq::@3
|
||||
(label) plex_irq::@4
|
||||
(label) plex_irq::@5
|
||||
(label) plex_irq::@7
|
||||
(label) plex_irq::@9
|
||||
(label) plex_irq::@return
|
||||
(label) plex_irq::plexFreeNextYpos1
|
||||
(byte) plex_irq::plexFreeNextYpos1_return
|
||||
(byte) plex_irq::plexFreeNextYpos1_return#0 reg byte x 4.0
|
||||
(byte) plex_irq::rasterY
|
||||
(byte) plex_show_idx
|
||||
(byte) plex_show_idx#0 plex_show_idx zp ZP_BYTE:9 4.0
|
||||
(byte) plex_show_idx#1 plex_show_idx zp ZP_BYTE:9 20.0
|
||||
(byte) plex_show_idx#16 plex_show_idx zp ZP_BYTE:9 2.1666666666666665
|
||||
(byte) plex_show_idx#27 plex_show_idx zp ZP_BYTE:9 1.1052631578947367
|
||||
(byte) plex_sprite_idx
|
||||
(byte) plex_sprite_idx#0 plex_sprite_idx zp ZP_BYTE:8 4.0
|
||||
(byte) plex_sprite_idx#1 plex_sprite_idx#1 zp ZP_BYTE:14 20.0
|
||||
(byte) plex_sprite_idx#25 plex_sprite_idx zp ZP_BYTE:8 1.1176470588235294
|
||||
(byte) plex_sprite_msb
|
||||
(byte) plex_sprite_msb#0 plex_sprite_msb zp ZP_BYTE:11 4.0
|
||||
(byte) plex_sprite_msb#1 plex_sprite_msb zp ZP_BYTE:11 20.0
|
||||
(byte) plex_sprite_msb#17 plex_sprite_msb zp ZP_BYTE:11 2.142857142857143
|
||||
(byte) plex_sprite_msb#27 plex_sprite_msb zp ZP_BYTE:11 3.0
|
||||
(byte) plex_sprite_msb#29 plex_sprite_msb zp ZP_BYTE:11 0.95
|
||||
(byte) plex_sprite_msb#4 plex_sprite_msb zp ZP_BYTE:11 4.0
|
||||
|
||||
zp ZP_BOOL:2 [ framedone#12 framedone#19 framedone#5 framedone#3 ]
|
||||
zp ZP_BYTE:3 [ loop::sin_idx#6 loop::sin_idx#0 loop::sin_idx#1 ]
|
||||
zp ZP_BYTE:4 [ loop::y_idx#2 loop::y_idx#0 loop::y_idx#1 ]
|
||||
reg byte y [ loop::sy#2 loop::sy#1 ]
|
||||
zp ZP_BYTE:5 [ plexSort::m#2 plexSort::m#1 plex_irq::$3 plexShowSprite::plex_sprite_idx2#0 ]
|
||||
reg byte x [ plexSort::s#3 plexSort::s#1 plexSort::s#6 ]
|
||||
reg byte x [ plexSort::plexFreePrepare1_s#2 plexSort::plexFreePrepare1_s#1 ]
|
||||
reg byte x [ init::sx#2 init::sx#1 ]
|
||||
zp ZP_WORD:6 [ init::xp#2 init::xp#1 ]
|
||||
reg byte x [ init::ss#2 init::ss#1 ]
|
||||
reg byte x [ plexInit::i#2 plexInit::i#1 ]
|
||||
zp ZP_BYTE:8 [ plex_sprite_idx#25 plex_sprite_idx#0 plexShowSprite::$8 ]
|
||||
zp ZP_BYTE:9 [ plex_show_idx#27 plex_show_idx#0 plex_show_idx#16 plex_show_idx#1 ]
|
||||
zp ZP_BYTE:10 [ plex_free_next#27 plex_free_next#31 plexShowSprite::plexFreeAdd1_$2#0 ]
|
||||
zp ZP_BYTE:11 [ plex_sprite_msb#29 plex_sprite_msb#0 plex_sprite_msb#17 plex_sprite_msb#27 plex_sprite_msb#4 plex_sprite_msb#1 ]
|
||||
zp ZP_BYTE:12 [ plexSort::nxt_idx#0 ]
|
||||
zp ZP_BYTE:13 [ plexSort::nxt_y#0 ]
|
||||
reg byte x [ plexSort::s#2 ]
|
||||
zp ZP_BYTE:14 [ plex_sprite_idx#1 ]
|
||||
zp ZP_BYTE:15 [ plex_free_next#0 ]
|
||||
reg byte a [ init::$6 ]
|
||||
reg byte x [ plex_irq::plexFreeNextYpos1_return#0 ]
|
||||
reg byte a [ plexShowSprite::plexFreeAdd1_ypos#0 ]
|
||||
reg byte a [ plexShowSprite::plexFreeAdd1_$0#0 ]
|
||||
reg byte x [ plexShowSprite::plexFreeAdd1_$1#0 ]
|
||||
reg byte x [ plexShowSprite::xpos_idx#0 ]
|
||||
reg byte a [ plexShowSprite::$3 ]
|
||||
reg byte a [ plexShowSprite::$4 ]
|
||||
reg byte a [ plexShowSprite::$6 ]
|
||||
reg byte x [ plexShowSprite::$7 ]
|
Loading…
Reference in New Issue
Block a user