1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-06-03 07:29:37 +00:00

Merge branch '766-add-huc6280-tst-instruction-addressing-modes' into 'master'

Resolve "Add Huc6280 TST instruction addressing modes"

Closes #766

See merge request camelot/kickc!15
This commit is contained in:
Jesper Balman Gravgaard 2022-02-12 07:22:16 +00:00
commit 49abe6cdb7
56 changed files with 23382 additions and 40 deletions

View File

@ -79,7 +79,7 @@
<dependency>
<groupId>cml.kickass</groupId>
<artifactId>kickassembler</artifactId>
<version>5.24-65ce02.a</version>
<version>5.24-65ce02.c</version>
</dependency>
<dependency>
<groupId>dk.camelot64.kickass.xexplugin</groupId>

View File

@ -0,0 +1 @@
0c00040f87c87fb73965e1f53afe7dcc

View File

@ -0,0 +1 @@
d51578b4523d90c4d5d5e9e3fe2806b42fd4a2ea

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>cml.kickass</groupId>
<artifactId>kickassembler</artifactId>
<version>5.24-65ce02.b</version>
<description>POM was created from install:install-file</description>
</project>

View File

@ -0,0 +1 @@
a4241896151d8ae9bad33889412751d9

View File

@ -0,0 +1 @@
3e36d1dbb157f463b0459185f396ce8da6f93ad9

View File

@ -0,0 +1 @@
befef7068401bafd8562e7ebd311c0e6

View File

@ -0,0 +1 @@
a829567c323ef50c79ed58a81c0e1dfe4902de74

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>cml.kickass</groupId>
<artifactId>kickassembler</artifactId>
<version>5.24-65ce02.c</version>
<description>POM was created from install:install-file</description>
</project>

View File

@ -0,0 +1 @@
b983e5035bd6302ebee3c19ec4c300d2

View File

@ -0,0 +1 @@
490fa2a18814b75785f0cbcd5e586fe80dc70843

View File

@ -3,7 +3,7 @@
<groupId>cml.kickass</groupId>
<artifactId>kickassembler</artifactId>
<versioning>
<release>5.24-65ce02.a</release>
<release>5.24-65ce02.c</release>
<versions>
<version>4.19</version>
<version>5.7</version>
@ -28,7 +28,9 @@
<version>5.22-65ce02.a</version>
<version>5.23-65ce02.a</version>
<version>5.24-65ce02.a</version>
<version>5.24-65ce02.b</version>
<version>5.24-65ce02.c</version>
</versions>
<lastUpdated>20220123234604</lastUpdated>
<lastUpdated>20220212060216</lastUpdated>
</versioning>
</metadata>

View File

@ -1 +1 @@
e21df397cfbdfffab5bdf0710903e415
24290bfa1613ef56b57bc4c4e670423c

View File

@ -1 +1 @@
e1786fe7f339b0358623f3109c1e3aa3306c9011
e3cf25389c4e30b070712f29c599f6e090746e7c

View File

@ -165,7 +165,7 @@ ASM_MNEMONIC:
'tsb' | 'wai' | 'cle' | 'see' | 'tsy' | 'lbpl'| 'inz' | 'tys' | 'lbmi'| 'dez' | 'neg' | 'asr' | 'taz' | 'lbvc'| 'tab' | 'map' | 'rtn' | 'lbsr'| 'tza' |
'lbvs'| 'tba' | 'lbra'| 'lbcc'| 'ldz' | 'lbcs'| 'cpz' | 'dew' | 'asw' | 'lbne'| 'phz' | 'inw' | 'row' | 'lbeq'| 'phw' | 'plz' | 'eom' | 'adcq'| 'andq'|
'aslq'| 'asrq'| 'bitq'| 'cpq' | 'deq' | 'eorq'| 'inq' | 'ldq' | 'lsrq'| 'orq' | 'rolq'| 'rorq'| 'sbcq'| 'stq' | 'sxy' | 'st0' | 'st1' | 'st2' | 'say' |
'tma' | 'bsr' | 'tam' | 'csl' | 'cla' | 'clx' | 'cly' | 'csh' | 'set'
'tma' | 'bsr' | 'tam' | 'csl' | 'cla' | 'clx' | 'cly' | 'csh' | 'set' | 'tst'
;
ASM_IMM : '#' ;

View File

@ -305,6 +305,8 @@ asmParamMode
| ASM_PAR_BEGIN asmExpr ASM_COMMA ASM_NAME ASM_PAR_END #asmModeIdxIndXY
| ASM_PAR_BEGIN asmExpr ASM_PAR_END #asmModeInd
| ASM_PAR_BEGIN ASM_PAR_BEGIN asmExpr ASM_PAR_END ASM_PAR_END #asmModeIndLong
| ASM_IMM asmExpr ASM_COMMA asmExpr #asmModeImmAndAbs
| ASM_IMM asmExpr ASM_COMMA asmExpr ASM_COMMA ASM_NAME #asmModeImmAndAbsX
;
asmExpr

View File

@ -138,13 +138,26 @@ public class Cpu65xx {
if(CpuAddressingMode.IAX.equals(addressingMode) && isOperandZp) {
cpuOpcode = getOpcode(mnemonic, CpuAddressingMode.IZX);
}
if(CpuAddressingMode.IAB.equals(addressingMode) && isOperandZp) {
cpuOpcode = getOpcode(mnemonic, CpuAddressingMode.IZP);
}
if(CpuAddressingMode.IABX.equals(addressingMode) && isOperandZp) {
cpuOpcode = getOpcode(mnemonic, CpuAddressingMode.IZPX);
}
if(cpuOpcode == null) {
// If the ZP-form does not exist use the ABS-variation
cpuOpcode = getOpcode(mnemonic, addressingMode);
}
if(cpuOpcode == null && CpuAddressingMode.IMM.equals(addressingMode)) {
// If the IMM-form does not exist try #imw (immediate word)
cpuOpcode = getOpcode(mnemonic, CpuAddressingMode.IMW);
}
if(cpuOpcode == null && CpuAddressingMode.ABS.equals(addressingMode)) {
// If the ABS-form does not exist try REL
cpuOpcode = getOpcode(mnemonic, CpuAddressingMode.REL);
// If the REL-form does not exist try REW
if(cpuOpcode==null)
cpuOpcode = getOpcode(mnemonic, CpuAddressingMode.REW);
}
return cpuOpcode;
}

View File

@ -19,6 +19,13 @@ public enum CpuAddressingMode {
*/
IMM("#imm", "%i #%p", 1),
/**
* #imw Immediate Word<br>
* IMMEDIATE WORD ADDRESSING In immediate word addressing, the operand is contained in the second and third byte
* of the instruction, with no further memory addressing required.
*/
IMW("#imw", "%i #%p", 2),
/**
* zp Zeropage <br>
* ZERO PAGE ADDRESSING The zero page instructions allow for shorter code and execution times by only fetching the
@ -170,13 +177,46 @@ public enum CpuAddressingMode {
*/
REL("rel", "%i %p", 1),
/**
* Relative Word<br>
* RELATIVE WORD ADDRESSING Relative addressing is used only with branch instructions and establishes a destination for
* the conditional branch. The second byte of-the instruction becomes the operand which is an Offset"" added to the
* contents of the program counter when the counter is set at the next instruction. The range
* of the offset is 32768 to + 32767 bytes from the next instruction."
*/
REW("rew", "%i %p", 2),
/**
* zp,rel Zeropage Test Relative
* ZEROPAGE TEST RELATIVE. It needs two one-byte operands, one for the zero page address that is used for the bit
* test, and one indicating the signed relative PC offset if the branch is taken. This makes BBRi and BBSi the single
* instructions with two explicit operands.
*/
REZ("zp,rel", "%i %p,%q", 2);
REZ("zp,rel", "%i %p,%q", 2),
/**
* #imm,zp Immediate, zeropage <br>
* IMMEDIATE ADDRESSING, ZEROPAGE Two parameters, one immediate the other a zeropage address. Only used by HUC6280 TST.
*/
IZP("#imm,zp", "%i.z #%p,%q", 2),
/**
* #imm,abs Immediate, absolute <br>
* IMMEDIATE ADDRESSING, ABSOLUTE Two parameters, one immediate the other an absolute address. Only used by HUC6280 TST.
*/
IAB("#imm,abs", "%i #%p,%q", 3),
/**
* #imm,zp,x Immediate, zeropage, x <br>
* IMMEDIATE ADDRESSING, ZEROPAGE Two parameters, one immediate the other a zeropage address. Only used by HUC6280 TST.
*/
IZPX("#imm,zp,x", "%i.z #%p,%q,x", 2),
/**
* #imm,abs,x Immediate, absolute,x <br>
* IMMEDIATE ADDRESSING, ABSOLUTE Two parameters, one immediate the other an absolute address. Only used by HUC6280 TST.
*/
IABX("#imm,abs,x", "%i #%p,%q,x", 3);
/** The short name of the addressing mode. */
private String name;

View File

@ -66,18 +66,13 @@ public class CpuOpcode {
return cycles;
}
/** Opcodes that use an extra byte for their operand that the addressing mode reports. This is immediate word and long branches.
* The format of the string is <code>mnemonic + " " + addressingMode</code> */
public static List<String> LONG_MNEMONICS = Arrays.asList("phw #imm", "lbra rel", "lbne rel", "lbeq rel", "lbcc rel", "lbcs rel", "lbmi rel", "lbpl rel", "lbvs rel", "lbvc rel", "lbsr rel" );
/**
* Get the number of bytes the instruction with operands takes up in memory
*
* @return The number of bytes.
*/
public int getBytes() {
final int numBytes = opcode.length + addressingMode.getBytes() + (LONG_MNEMONICS.contains(mnemonic+" "+addressingMode.getName())?1:0);
return numBytes;
return opcode.length + addressingMode.getBytes();
}
/**

View File

@ -32,45 +32,45 @@ public class Cpu65CE02 extends Cpu65xx {
addOpcode(0x3,"see",CpuAddressingMode.NON,2,"e");
addOpcode(0xB,"tsy",CpuAddressingMode.NON,1,"Ynz");
addOpcode(0x12,"ora",CpuAddressingMode.IZZ,5,"Anz");
addOpcode(0x13,"lbpl",CpuAddressingMode.REL,3,"P");
addOpcode(0x13,"lbpl",CpuAddressingMode.REW,3,"P");
addOpcode(0x1B,"inz",CpuAddressingMode.NON,1,"Znz");
addOpcode(0x22,"jsr",CpuAddressingMode.IND,7,"PS");
addOpcode(0x23,"jsr",CpuAddressingMode.IAX,7,"PS");
addOpcode(0x2B,"tys",CpuAddressingMode.NON,1,"S");
addOpcode(0x32,"and",CpuAddressingMode.IZZ,5,"Anz");
addOpcode(0x33,"lbmi",CpuAddressingMode.REL,3,"P");
addOpcode(0x33,"lbmi",CpuAddressingMode.REW,3,"P");
addOpcode(0x3B,"dez",CpuAddressingMode.NON,1,"Znz");
addOpcode(0x42,"neg",CpuAddressingMode.NON,2,"Anz");
addOpcode(0x43,"asr",CpuAddressingMode.NON,2,"Acnz");
addOpcode(0x44,"asr",CpuAddressingMode.ZP,4,"cnz");
addOpcode(0x4B,"taz",CpuAddressingMode.NON,1,"Znz");
addOpcode(0x52,"eor",CpuAddressingMode.IZZ,5,"Anz");
addOpcode(0x53,"lbvc",CpuAddressingMode.REL,3,"P");
addOpcode(0x53,"lbvc",CpuAddressingMode.REW,3,"P");
addOpcode(0x54,"asr",CpuAddressingMode.ZPX,4,"cnz");
addOpcode(0x5B,"tab",CpuAddressingMode.NON,1,"B");
addOpcode(0x5C,"map",CpuAddressingMode.NON,2,"");
addOpcode(0x62,"rtn",CpuAddressingMode.IMM,7,"P");
addOpcode(0x63,"lbsr",CpuAddressingMode.REL,3,"P");
addOpcode(0x63,"lbsr",CpuAddressingMode.REW,3,"P");
addOpcode(0x6B,"tza",CpuAddressingMode.NON,1,"Anz");
addOpcode(0x72,"adc",CpuAddressingMode.IZZ,5,"Acvnz");
addOpcode(0x73,"lbvs",CpuAddressingMode.REL,3,"P");
addOpcode(0x73,"lbvs",CpuAddressingMode.REW,3,"P");
addOpcode(0x7B,"tba",CpuAddressingMode.NON,1,"Anz");
addOpcode(0x82,"sta",CpuAddressingMode.ISY,6,"");
addOpcode(0x83,"lbra",CpuAddressingMode.REL,3,"P");
addOpcode(0x83,"lbra",CpuAddressingMode.REW,3,"P");
addOpcode(0x8B,"sty",CpuAddressingMode.ABX,4,"");
addOpcode(0x92,"sta",CpuAddressingMode.IZZ,5,"");
addOpcode(0x93,"lbcc",CpuAddressingMode.REL,3,"P");
addOpcode(0x93,"lbcc",CpuAddressingMode.REW,3,"P");
addOpcode(0x9B,"stx",CpuAddressingMode.ABY,4,"");
addOpcode(0xA3,"ldz",CpuAddressingMode.IMM,2,"Znz");
addOpcode(0xAB,"ldz",CpuAddressingMode.ABS,4,"Znz");
addOpcode(0xB2,"lda",CpuAddressingMode.IZZ,5,"Anz");
addOpcode(0xB3,"lbcs",CpuAddressingMode.REL,3,"P");
addOpcode(0xB3,"lbcs",CpuAddressingMode.REW,3,"P");
addOpcode(0xBB,"ldz",CpuAddressingMode.ABX,4,"Znz");
addOpcode(0xC2,"cpz",CpuAddressingMode.IMM,2,"cnz");
addOpcode(0xC3,"dew",CpuAddressingMode.ZP,5,"nz");
addOpcode(0xCB,"asw",CpuAddressingMode.ABS,7,"cnz");
addOpcode(0xD2,"cmp",CpuAddressingMode.IZZ,5,"cnz");
addOpcode(0xD3,"lbne",CpuAddressingMode.REL,3,"P");
addOpcode(0xD3,"lbne",CpuAddressingMode.REW,3,"P");
addOpcode(0xD4,"cpz",CpuAddressingMode.ZP,3,"cnz");
addOpcode(0xDB,"phz",CpuAddressingMode.NON,3,"S");
addOpcode(0xDC,"cpz",CpuAddressingMode.ABS,4,"cnz");
@ -78,8 +78,8 @@ public class Cpu65CE02 extends Cpu65xx {
addOpcode(0xE3,"inw",CpuAddressingMode.ZP,5,"nz");
addOpcode(0xEB,"row",CpuAddressingMode.ABS,6,"cnz");
addOpcode(0xF2,"sbc",CpuAddressingMode.IZZ,5,"Acvnz");
addOpcode(0xF3,"lbeq",CpuAddressingMode.REL,3,"P");
addOpcode(0xF4,"phw",CpuAddressingMode.IMM,5,"S");
addOpcode(0xF3,"lbeq",CpuAddressingMode.REW,3,"P");
addOpcode(0xF4,"phw",CpuAddressingMode.IMW,5,"S");
addOpcode(0xFB,"plz",CpuAddressingMode.NON,3,"ZnzS");
addOpcode(0xFC,"phw",CpuAddressingMode.ABS,7,"S");
addOpcode(0xEA,"eom",CpuAddressingMode.NON,1,"");

View File

@ -45,6 +45,10 @@ public class CpuHuc6280 extends Cpu65xx {
addOpcode(0xc2,"cly", CpuAddressingMode.NON,2,"Y");
addOpcode(0xd4,"csh", CpuAddressingMode.NON,2,"");
addOpcode(0xf4,"set", CpuAddressingMode.NON,2,"");
addOpcode(0x83,"tst", CpuAddressingMode.IZP,7,"vnz");
addOpcode(0x93,"tst", CpuAddressingMode.IAB,8,"vnz");
addOpcode(0xA3,"tst", CpuAddressingMode.IZPX,7,"vnz");
addOpcode(0xB3,"tst", CpuAddressingMode.IABX,8,"vnz");
}
}

View File

@ -286,6 +286,16 @@ public class AsmFragmentInstance {
return createAsmInstruction(ctx, ctx.asmExpr(), null, CpuAddressingMode.IMM);
}
@Override
public Object visitAsmModeImmAndAbs(KickCParser.AsmModeImmAndAbsContext ctx) {
return createAsmInstruction(ctx, ctx.asmExpr(0), ctx.asmExpr(1), CpuAddressingMode.IAB);
}
@Override
public Object visitAsmModeImmAndAbsX(KickCParser.AsmModeImmAndAbsXContext ctx) {
return createAsmInstruction(ctx, ctx.asmExpr(0), ctx.asmExpr(1), CpuAddressingMode.IABX);
}
@Override
public Object visitAsmModeAbsXY(KickCParser.AsmModeAbsXYContext ctx) {
final KickCParser.AsmExprContext indexCtx = ctx.asmExpr(1);
@ -370,13 +380,22 @@ public class AsmFragmentInstance {
String mnemonic = instructionCtx.ASM_MNEMONIC().getSymbol().getText();
AsmParameter param1 = operand1Ctx == null ? null : (AsmParameter) this.visit(operand1Ctx);
AsmParameter param2 = operand2Ctx == null ? null : (AsmParameter) this.visit(operand2Ctx);
// Convert to ZP-addressing mode if possible
boolean isZp = param1 != null && param1.isZp();
if(CpuAddressingMode.IAB.equals(addressingMode) || CpuAddressingMode.IABX.equals(addressingMode)) {
// For the HuC6280 CPU TST #imm,abs addressing mode it is param2 that can converted the instruction to ZP
isZp = param2 != null && param2.isZp();
}
CpuOpcode cpuOpcode = this.getAsmProgram().getTargetCpu().getCpu65xx().getOpcode(mnemonic, addressingMode, isZp);
if(!isZp && cpuOpcode==null) {
// Fallback to ZP-addressing
cpuOpcode = this.getAsmProgram().getTargetCpu().getCpu65xx().getOpcode(mnemonic, addressingMode, true);
}
String operand1 = param1 == null ? null : param1.getParam();
String operand2 = param2 == null ? null : param2.getParam();
if(cpuOpcode == null) {

View File

@ -4,7 +4,7 @@
cp ./repo/cml/kickass/kickassembler/maven-metadata.xml ./repo/cml/kickass/kickassembler/maven-metadata-local.xml
# mvn install:install-file -Dmaven.repo.local=./repo/ -Dfile=/Applications/KickAssembler/KickAss.jar -DgroupId=cml.kickass -DartifactId=kickassembler -Dpackaging=jar -DgeneratePom=true -DcreateChecksum=true -Dversion=5.16
mvn install:install-file -Dmaven.repo.local=./repo/ -Dfile=/Users/jespergravgaard/c64/kickassembler65ce02/out/KickAss65CE02.jar -DgroupId=cml.kickass -DartifactId=kickassembler -Dpackaging=jar -DgeneratePom=true -DcreateChecksum=true -Dversion=5.24-65ce02.a
mvn install:install-file -Dmaven.repo.local=./repo/ -Dfile=/Users/jespergravgaard/c64/kickassembler65ce02/out/KickAss65CE02.jar -DgroupId=cml.kickass -DartifactId=kickassembler -Dpackaging=jar -DgeneratePom=true -DcreateChecksum=true -Dversion=5.24-65ce02.c
# Finalize by making the local metadata official
pushd ./repo/cml/kickass/kickassembler

View File

@ -62,7 +62,7 @@ public class TestCpuFamilyKickAssCompatibility {
assertNotNull(kcOpcode.getMnemonic(), "KickAss CPU " + kaCpu.name + " does not know the KickC CPU " + kcCpu.getName() + " mnemonic");
final List<_65xxArgType> kaArgTypes = kaAddressingModeMap.get(kcOpcode.getAddressingMode());
assertNotNull(kaArgTypes, "KickAss addressing mode not found " + kcOpcode.getAddressingMode().getName());
assertNotNull(kaArgTypes, "KickAss addressing mode not found " + kcOpcode.getAddressingMode().getName());
// Try each argtype to find the one that works
boolean found = false;
for(_65xxArgType kaArgType : kaArgTypes) {
@ -121,7 +121,8 @@ public class TestCpuFamilyKickAssCompatibility {
Map<CpuAddressingMode, List<_65xxArgType>> getKAAddressingModeMap() {
final HashMap<CpuAddressingMode, List<_65xxArgType>> map = new HashMap<>();
map.put(CpuAddressingMode.NON, Collections.singletonList(_65xxArgType.noArgument));
map.put(CpuAddressingMode.IMM, Arrays.asList(_65xxArgType.immediate, _65xxArgType.immediateWord));
map.put(CpuAddressingMode.IMM, Collections.singletonList(_65xxArgType.immediate));
map.put(CpuAddressingMode.IMW, Collections.singletonList(_65xxArgType.immediateWord));
map.put(CpuAddressingMode.ZP, Collections.singletonList(_65xxArgType.zeropage));
map.put(CpuAddressingMode.ZPX, Collections.singletonList(_65xxArgType.zeropageX));
map.put(CpuAddressingMode.ZPY, Collections.singletonList(_65xxArgType.zeropageY));
@ -137,12 +138,14 @@ public class TestCpuFamilyKickAssCompatibility {
map.put(CpuAddressingMode.LIN, Collections.singletonList(_65xxArgType.indirect32Zeropage));
map.put(CpuAddressingMode.LIZ, Collections.singletonList(_65xxArgType.indirect32ZeropageZ));
map.put(CpuAddressingMode.ISY, Collections.singletonList(_65xxArgType.indirectStackZeropageY));
map.put(CpuAddressingMode.REL, Arrays.asList(_65xxArgType.relative, _65xxArgType.relativeWord));
map.put(CpuAddressingMode.REL, Collections.singletonList(_65xxArgType.relative));
map.put(CpuAddressingMode.REW, Collections.singletonList(_65xxArgType.relativeWord));
map.put(CpuAddressingMode.REZ, Collections.singletonList(_65xxArgType.zeropageRelative));
map.put(CpuAddressingMode.IZP, Collections.singletonList(_65xxArgType.immediateAndZeropage));
map.put(CpuAddressingMode.IAB, Collections.singletonList(_65xxArgType.immediateAndAbsolute));
map.put(CpuAddressingMode.IZPX, Collections.singletonList(_65xxArgType.immediateAndZeropageX));
map.put(CpuAddressingMode.IABX, Collections.singletonList(_65xxArgType.immediateAndAbsoluteX));
return map;
}
// map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey))
}

View File

@ -9,6 +9,27 @@ import java.io.IOException;
*/
public class TestProgramsFast extends TestPrograms {
@Test
public void testPointerSwap() throws IOException {
compileAndCompare("pointer-swap.c");
}
@Test
public void testDucksTotal() throws IOException {
compileAndCompare("ducks-total.c");
}
@Test
public void testDucksLoop211() throws IOException {
compileAndCompare("ducks-loop211.c");
}
@Test
public void testDucksArray() throws IOException {
compileAndCompare("ducks-array.c");
}
@Test
public void testSepaOptimizeProblem1() throws IOException {
compileAndCompare("sepa-optimize-problem-1.c");
@ -554,6 +575,11 @@ public class TestProgramsFast extends TestPrograms {
// compileAndCompare("library-constructor-0.c");
//}
@Test
public void testCpuHuc6280Tst() throws IOException {
compileAndCompare("cpu-huc6280-tst.c");
}
@Test
public void testCpuHuc6280() throws IOException {
compileAndCompare("cpu-huc6280.c");

View File

@ -0,0 +1,14 @@
// Tests the HUC6280 instructions
#pragma cpu(huc6280)
void main() {
asm {
tst #1+2,$3+4
tst #1+2*3,$7654/2
tst #1+2,$3+4,x
tst #1+2*3,$7654/2,x
!:
rts
}
}

View File

@ -20,6 +20,10 @@ void main() {
cly
csh
set
tst #1+2,$3+4
tst #1+2*3,$7654/2
tst #1+2,$3+4,x
tst #1+2*3,$7654/2,x
!:
rts
}

14
src/test/kc/ducks-array.c Normal file
View File

@ -0,0 +1,14 @@
#include <stdio.h>
unsigned byte points[]={1,2,3,4};
void chrout(volatile char register(A) petscii)
{ asm { jsr $ffd2 }}
void main()
{
chrout(149);
chrout(points[0]);
chrout(points[1]);
chrout(points[2]);
chrout(points[3]);
}

View File

@ -0,0 +1,22 @@
#include <peekpoke.h>
#include <6502.h>
const unsigned byte brick=230;
void chrout(volatile char petscii)
{
asm {
lda petscii
jsr $ffd2
}
}
void main()
{
char k=1;
do {
POKE(211,k*4);
chrout(brick);
++k;
} while (k<5);
}

157
src/test/kc/ducks-total.c Normal file
View File

@ -0,0 +1,157 @@
#include <stdio.h>
#include <peekpoke.h>
#include <stdlib.h>
#include <division.h>
unsigned byte j,k,l,m,n=0; // [0..255] 8-bit
unsigned short tu,duck,peephole,y,z,time,score,hiscore=0; // [0..65536] 16-bit
unsigned byte points[]={0,0,0,0};
unsigned byte buffer[]={0,0,0,0};
const unsigned byte down=17,right=29,lock=8,lower=14;
const unsigned byte home=19,reverse_on=18,brick=230;
const unsigned byte green=30,yellow=158,red=28;
const unsigned short c=30720; // for unexpanded. 37888-4096 color for expanded
const unsigned byte ducknumber[]={68,85,67,75,58}; // DUCK:
const unsigned byte chrono[]={84,77,58,57}; // TM:9
const unsigned byte duck_udg[]={14,27,63,31,15,7,15,31,0,0,0,0,0,192,112,188,31,29,30,15,3,1,1,3,206,30,124,248,224,64,64,224,0,0,0,0,0,0,0,0};
// POKE CODES = 0,1,2,3,4; CHROUT CODES = 64, 65, 66, 67, 68 (with previous reverse_off "chrout(146)")
const unsigned byte intro[]="\n\n\nDIFFICULTY\n----------\n\n\n";
const unsigned byte levels[]="1.EASIEST\n\n3.EASY\n\n5.MEDIUM\n\n7.HARD\n\n9.EXPERT\n\n\n\n\n";
const unsigned byte foot[]="PRESS: 1,3,5,7 or 9\n\n";
const unsigned byte game_over[]="\n\n\n\nGAME OVER";
const unsigned byte play_again[]="\n\n\nPlay Again (Y/N)?";
const unsigned byte your_score[]="\n\n\nYour Score: ";
const unsigned byte high_score[]="\n\nHi-Score: ";
void clear_screen(byte n, byte m)
{ for (z=0; z<506; ++z) { POKE(7680+z+c,m); POKE(7680+z,n); } // From 0-->505 (506 bytes). ClearScreen with byte 'n' with color 'm'
gotoxy(0,0); chrout(home); } // Return to home position
void random(byte k, byte n) // Random { k..n }
{ do { m=PEEK(37140); }
while (m<k || m>n); }
void chrout(volatile char petscii)
{ asm { lda petscii jsr $ffd2 }}
void write_score(void) {
if (score>65000) score=0;
for (m=0;m<4;m++) { points[m]='0'; } // (!!) Needed. Possibly a bug
utoa(score,buffer,10);
if (score>9) { points[2]=buffer[0];points[3]=buffer[1]; }
if (score>99) { points[1]=buffer[0];points[2]=buffer[1];points[3]=buffer[2]; }
chrout(yellow);chrout(home);POKE(211,4);
for (m=0;m<4;m++) { chrout(points[m]); }
}
void wait(byte n)
{ for (m=0;m<n;++m) { for (z=0;z<540;++z) {}; } }
void chrono_restart(void)
{ asm {
lda #0
ldy #0
ldx #0
jsr $ffdb }; }
void read_chrono(void) // time (in seconds)
{ asm {
jsr $ffde
sta l
stx m
};
time=div16u8u((m*256)+l,60);
POKE (7701+c,7); POKE(7701,185);
if (time<10) POKE(7701,185-time); // if chrono<10 write time, otherwise write '9'. it avoids '/' symbol. Yellow
}
void main()
{
POKE(36879,8); // border and black paper
chrout(lock); //Lock UpperCase to Lowercase key
chrout(lower); //Put text in Lowercase set
for (m=0; m<40; m++) POKE(7168+m,duck_udg[m]);  // Load udgs. From 0-->39;
do {
clear_screen(32,0); // Clear Screen with spaces & black ink
textcolor(7); cputs(intro); // Yellow ink
textcolor(1); cputs(levels); // White
textcolor(2); cputs(foot); // Red
do { l=PEEK(197); ++l; } while (l>5); // wait for 1-3-5-7-9 keys only
clear_screen(4,0); // with (4=duser defined). Black ink
POKE(36869,255); // Graphic mode
chrout(reverse_on);chrout(red);chrout(down);
//for (z=1;z<23;z++) { POKE(7680+z*22,230);POKE(c+7680+z*22,2); POKE(7679+z*22,230); POKE(c+7679+z*22,2); } // 23 rows * 22 columns (7680 to 8185). 506 positions.
//k=1; do { chrout(brick); POKE(211,20); chrout(brick); ++k; } while (k<23);
//for (k=1;k<22;k++) { chrout(brick); POKE(211,22); chrout(brick); }; // 23 rows * 22 columns (7680 to 8185). 506 positions.
for (k=1;k<22;k++) { chrout(brick); for(n=2;n<22;++n) { chrout(right); }; chrout(brick); }; // 23 rows * 22 columns (7680 to 8185). 506 positions.
chrout(brick); // first brick from last line (#23)
POKE(8185,brick);POKE(8185+c,2); //last brick from last line (#23) to avoid scrolling
chrout(home); z=1; // First position
if (l>1) {
do { // Write differential random bricks depending on 'l' level choosen
random((7-l),26-(3*l)); // Random number is 'm' (interleaves are level-dependent)
if (z+m>505) break;
for (j=1; j<=m; ++j) chrout(right);
chrout(brick); z=z+m+1; }
while (z<506);
}
peephole=7967; // Initial peephole position
POKE(36878,15); // Volume to max
score=0;
tu=1; // Duck #1
chrout(home);chrout(yellow);chrout(80);chrout(84);chrout(83);chrout(58); // Write 'PTS:', yellow
POKE(211,18); // jump to Column 18
for (j=0; j<4; ++j) { chrout(chrono[j]); }; // Write 'TM:9', yellow
write_score(); // Write Score (yellow)
chrout(home);chrout(green);POKE(211,10); // Jump to column 10
for (j=0; j<5; j++) { chrout(ducknumber[j]); }; // Write 'DUCK', green
do {
chrout(home);chrout(green);chrout(reverse_on);
POKE(211,15); // Jump to column 15
if (tu<10) { chrout(48+tu) }; else { chrout(49);chrout(48); } // Write duck number
do { random(0,255); duck=m; random(0,255); duck=m+7701+duck; } // Choose randon Duck position (in 2 parts random+random)
while ((duck>8163) || PEEK(duck)==brick || PEEK(duck+1)==brick || PEEK(duck+22)==brick || PEEK(duck+23)==brick);
time=0;chrono_restart();
while (time<10) // ...until 10 seconds
{ read_chrono();
// Joystick routine
m=PEEK(37151); POKE(37154,127);
n=PEEK(37152); POKE(37154,255);
if ((16&m)==0) y--; // Left
if ((128&n)==0) y++; // Right
if ((4&m)==0) y=y-22; // Up
if ((8&m)==0) y=y+22; // Down
if ((32&m)==0) // FIRE!!
{ POKE(36877,130);
if (peephole!=duck) { score=score-10; write_score(); wait(10); } // We hit the duck!
else { score=score+(12-time)*10; wait(10);time=10; } // We fail!
POKE(36877,0); // Stop sounds
}
if (PEEK(y)!=brick && PEEK(y+1)!=brick && PEEK(y+22)!=brick && PEEK(y+23)!=brick && y>7702 && y<8163)
{ POKE(peephole+c,0); POKE(peephole+c+1,0); POKE(peephole+c+22,0); POKE(peephole+c+23,0); peephole=y; } // Check if peephole touches some bricks
y=peephole;
POKE(peephole,253);POKE(peephole+c,1);POKE(peephole+1,237);POKE(peephole+1+c,1);
POKE(peephole+22,238);POKE(peephole+22+c,1);POKE(peephole+23,240);POKE(peephole+23+c,1); // Clear peephole if there is not bricks contact
wait(5);
POKE(duck,0);POKE(duck+c,7);POKE(duck+1,1);POKE(duck+1+c,7); // Draw duck (udg)
POKE(duck+22,2);POKE(duck+22+c,7);POKE(duck+23,3);POKE(duck+23+c,7);
wait(5);
}
tu++; // Next duck
score=score-10;write_score(); // Substract 10 points if time finishes
POKE(36877,130);wait(20);POKE(36877,0); // Make some noise
POKE(duck+c,0); POKE(duck+1+c,0); POKE(duck+22+c,0); POKE(duck+23+c,0); // Clear previous duck draw
}
while (tu<11); // 10 ducks
clear_screen(4,0); // Clear screen with user-defined spaces & black ink
POKE(36869,240);chrout(lower); // Return to text mode, lowcase
textcolor(7); cputs(game_over); // Yellow
textcolor(2); cputs(your_score); cputs(buffer); // Red
textcolor(3); cputs(high_score); if (score>hiscore) hiscore=score; utoa(hiscore,buffer,10); cputs(buffer); // Cyan
textcolor(1); cputs(play_again); // white
do { j=PEEK(197); } while (j!= 11 && j!=28 ); // Wait for Y or N
} // Y pressed --> start again
while (j==11); // N pressed. Exit game
asm {jsr $FD22}; // Reset the VIC.
}

View File

@ -0,0 +1,31 @@
byte buffer1[10];
byte buffer2[10];
byte *newbuffer = buffer1;
byte *oldbuffer = buffer2;
byte *tempbuffer;
char* screen = (char*)0x0400;
char hextab[] = "0123456789abcdef"z;
void print() {
screen[0] = hextab[(char)tempbuffer&0x0f];
screen[2] = hextab[(char)newbuffer&0x0f];
screen[4] = hextab[(char)oldbuffer&0x0f];
screen += 40;
}
void swap() {
tempbuffer = newbuffer;
newbuffer = oldbuffer;
oldbuffer = tempbuffer;
print();
}
void main() {
print();
swap();
swap();
swap();
}

View File

@ -0,0 +1,21 @@
// Tests the HUC6280 instructions
.cpu _huc6280
// Commodore 64 PRG executable file
.file [name="cpu-huc6280-tst.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
.segment Code
main: {
// asm
tst.z #1+2,3+4
tst #1+2*3,$7654/2
tst.z #1+2,3+4,x
tst #1+2*3,$7654/2,x
!:
rts
// }
}

View File

@ -0,0 +1,8 @@
void main()
main: scope:[main] from
asm { tst#1+2,$3+4 tst#1+2*3,$7654/2 tst#1+2,$3+4,x tst#1+2*3,$7654/2,x !: rts }
to:main::@return
main::@return: scope:[main] from main
[1] return
to:@return

View File

@ -0,0 +1,138 @@
CONTROL FLOW GRAPH SSA
void main()
main: scope:[main] from __start
asm { tst#1+2,$3+4 tst#1+2*3,$7654/2 tst#1+2,$3+4,x tst#1+2*3,$7654/2,x !: rts }
to:main::@return
main::@return: scope:[main] from main
return
to:@return
void __start()
__start: scope:[__start] from
call main
to:__start::@1
__start::@1: scope:[__start] from __start
to:__start::@return
__start::@return: scope:[__start] from __start::@1
return
to:@return
SYMBOL TABLE SSA
void __start()
void main()
Removing unused procedure __start
Removing unused procedure block __start
Removing unused procedure block __start::@1
Removing unused procedure block __start::@return
Successful SSA optimization PassNEliminateEmptyStart
CALL GRAPH
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
FINAL CONTROL FLOW GRAPH
void main()
main: scope:[main] from
asm { tst#1+2,$3+4 tst#1+2*3,$7654/2 tst#1+2,$3+4,x tst#1+2*3,$7654/2,x !: rts }
to:main::@return
main::@return: scope:[main] from main
[1] return
to:@return
VARIABLE REGISTER WEIGHTS
void main()
Initial phi equivalence classes
Complete equivalence classes
REGISTER UPLIFT POTENTIAL REGISTERS
REGISTER UPLIFT SCOPES
Uplift Scope [main]
Uplift Scope []
Uplifting [main] best 45 combination
Uplifting [] best 45 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Tests the HUC6280 instructions
// Upstart
.cpu _huc6280
// Commodore 64 PRG executable file
.file [name="cpu-huc6280-tst.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.segment Code
// main
main: {
// asm { tst#1+2,$3+4 tst#1+2*3,$7654/2 tst#1+2,$3+4,x tst#1+2*3,$7654/2,x !: rts }
tst.z #1+2,3+4
tst #1+2*3,$7654/2
tst.z #1+2,3+4,x
tst #1+2*3,$7654/2,x
!:
rts
jmp __breturn
// main::@return
__breturn:
// [1] return
rts
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Removing unreachable instruction rts
Succesful ASM optimization Pass5UnreachableCodeElimination
FINAL SYMBOL TABLE
void main()
FINAL ASSEMBLER
Score: 36
// File Comments
// Tests the HUC6280 instructions
// Upstart
.cpu _huc6280
// Commodore 64 PRG executable file
.file [name="cpu-huc6280-tst.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.segment Code
// main
main: {
// asm
// asm { tst#1+2,$3+4 tst#1+2*3,$7654/2 tst#1+2,$3+4,x tst#1+2*3,$7654/2,x !: rts }
tst.z #1+2,3+4
tst #1+2*3,$7654/2
tst.z #1+2,3+4,x
tst #1+2*3,$7654/2,x
!:
rts
// main::@return
// }
// [1] return
}
// File Data

View File

@ -0,0 +1,2 @@
void main()

View File

@ -26,6 +26,10 @@ main: {
cly
csh
set
tst.z #1+2,3+4
tst #1+2*3,$7654/2
tst.z #1+2,3+4,x
tst #1+2*3,$7654/2,x
!:
rts
// }

View File

@ -1,7 +1,7 @@
void main()
main: scope:[main] from
asm { sxy st0#$55 st1#$aa sax st2#$be say tma#2 bsr!+ tam#4 csl cla clx cly csh set !: rts }
asm { sxy st0#$55 st1#$aa sax st2#$be say tma#2 bsr!+ tam#4 csl cla clx cly csh set tst#1+2,$3+4 tst#1+2*3,$7654/2 tst#1+2,$3+4,x tst#1+2*3,$7654/2,x !: rts }
to:main::@return
main::@return: scope:[main] from main
[1] return

View File

@ -3,7 +3,7 @@ CONTROL FLOW GRAPH SSA
void main()
main: scope:[main] from __start
asm { sxy st0#$55 st1#$aa sax st2#$be say tma#2 bsr!+ tam#4 csl cla clx cly csh set !: rts }
asm { sxy st0#$55 st1#$aa sax st2#$be say tma#2 bsr!+ tam#4 csl cla clx cly csh set tst#1+2,$3+4 tst#1+2*3,$7654/2 tst#1+2,$3+4,x tst#1+2*3,$7654/2,x !: rts }
to:main::@return
main::@return: scope:[main] from main
return
@ -37,7 +37,7 @@ FINAL CONTROL FLOW GRAPH
void main()
main: scope:[main] from
asm { sxy st0#$55 st1#$aa sax st2#$be say tma#2 bsr!+ tam#4 csl cla clx cly csh set !: rts }
asm { sxy st0#$55 st1#$aa sax st2#$be say tma#2 bsr!+ tam#4 csl cla clx cly csh set tst#1+2,$3+4 tst#1+2*3,$7654/2 tst#1+2,$3+4,x tst#1+2*3,$7654/2,x !: rts }
to:main::@return
main::@return: scope:[main] from main
[1] return
@ -50,14 +50,14 @@ void main()
Initial phi equivalence classes
Complete equivalence classes
REGISTER UPLIFT POTENTIAL REGISTERS
Statement asm { sxy st0#$55 st1#$aa sax st2#$be say tma#2 bsr!+ tam#4 csl cla clx cly csh set !: rts } always clobbers reg byte a reg byte x reg byte y
Statement asm { sxy st0#$55 st1#$aa sax st2#$be say tma#2 bsr!+ tam#4 csl cla clx cly csh set tst#1+2,$3+4 tst#1+2*3,$7654/2 tst#1+2,$3+4,x tst#1+2*3,$7654/2,x !: rts } always clobbers reg byte a reg byte x reg byte y
REGISTER UPLIFT SCOPES
Uplift Scope [main]
Uplift Scope []
Uplifting [main] best 65 combination
Uplifting [] best 65 combination
Uplifting [main] best 95 combination
Uplifting [] best 95 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
@ -76,7 +76,7 @@ ASSEMBLER BEFORE OPTIMIZATION
.segment Code
// main
main: {
// asm { sxy st0#$55 st1#$aa sax st2#$be say tma#2 bsr!+ tam#4 csl cla clx cly csh set !: rts }
// asm { sxy st0#$55 st1#$aa sax st2#$be say tma#2 bsr!+ tam#4 csl cla clx cly csh set tst#1+2,$3+4 tst#1+2*3,$7654/2 tst#1+2,$3+4,x tst#1+2*3,$7654/2,x !: rts }
sxy
st0 #$55
st1 #$aa
@ -92,6 +92,10 @@ main: {
cly
csh
set
tst.z #1+2,3+4
tst #1+2*3,$7654/2
tst.z #1+2,3+4,x
tst #1+2*3,$7654/2,x
!:
rts
jmp __breturn
@ -116,7 +120,7 @@ void main()
FINAL ASSEMBLER
Score: 56
Score: 86
// File Comments
// Tests the HUC6280 instructions
@ -135,7 +139,7 @@ Score: 56
// main
main: {
// asm
// asm { sxy st0#$55 st1#$aa sax st2#$be say tma#2 bsr!+ tam#4 csl cla clx cly csh set !: rts }
// asm { sxy st0#$55 st1#$aa sax st2#$be say tma#2 bsr!+ tam#4 csl cla clx cly csh set tst#1+2,$3+4 tst#1+2*3,$7654/2 tst#1+2,$3+4,x tst#1+2*3,$7654/2,x !: rts }
sxy
st0 #$55
st1 #$aa
@ -151,6 +155,10 @@ main: {
cly
csh
set
tst.z #1+2,3+4
tst #1+2*3,$7654/2
tst.z #1+2,3+4,x
tst #1+2*3,$7654/2,x
!:
rts
// main::@return

View File

@ -0,0 +1,45 @@
/// @file
/// Functions for performing input and output.
// Commodore 64 PRG executable file
.file [name="ducks-array.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
.segment Code
main: {
// chrout(149)
lda #$95
sta.z chrout.petscii
jsr chrout
// chrout(points[0])
lda points
sta.z chrout.petscii
jsr chrout
// chrout(points[1])
lda points+1
sta.z chrout.petscii
jsr chrout
// chrout(points[2])
lda points+2
sta.z chrout.petscii
jsr chrout
// chrout(points[3])
lda points+3
sta.z chrout.petscii
jsr chrout
// }
rts
}
// void chrout(__zp(2) volatile char petscii)
chrout: {
.label petscii = 2
// asm
jsr $ffd2
// }
rts
}
.segment Data
points: .byte 1, 2, 3, 4

View File

@ -0,0 +1,33 @@
void main()
main: scope:[main] from
[0] chrout::petscii = $95
[1] call chrout
to:main::@1
main::@1: scope:[main] from main
[2] chrout::petscii = *points
[3] call chrout
to:main::@2
main::@2: scope:[main] from main::@1
[4] chrout::petscii = *(points+1)
[5] call chrout
to:main::@3
main::@3: scope:[main] from main::@2
[6] chrout::petscii = *(points+2)
[7] call chrout
to:main::@4
main::@4: scope:[main] from main::@3
[8] chrout::petscii = *(points+3)
[9] call chrout
to:main::@return
main::@return: scope:[main] from main::@4
[10] return
to:@return
void chrout(volatile char petscii)
chrout: scope:[chrout] from main main::@1 main::@2 main::@3 main::@4
asm { jsr$ffd2 }
to:chrout::@return
chrout::@return: scope:[chrout] from chrout
[12] return
to:@return

View File

@ -0,0 +1,521 @@
Fixing struct type size struct printf_buffer_number to 12
Fixing struct type size struct printf_buffer_number to 12
Fixing struct type size struct printf_buffer_number to 12
Fixing struct type SIZE_OF struct printf_buffer_number to 12
Fixing struct type SIZE_OF struct printf_buffer_number to 12
Inlined call vicSelectGfxBank::$0 = call toDd00(vicSelectGfxBank::gfx)
Inlined call call __init
Eliminating unused variable with no statement gotoxy::$4
Eliminating unused variable with no statement printf_buffer
CONTROL FLOW GRAPH SSA
void gotoxy(char x , char y)
gotoxy: scope:[gotoxy] from conio_c64_init::@1
gotoxy::x#3 = phi( conio_c64_init::@1/gotoxy::x#1 )
gotoxy::y#2 = phi( conio_c64_init::@1/gotoxy::y#1 )
gotoxy::$0 = gotoxy::y#2 > $19
gotoxy::$1 = ! gotoxy::$0
if(gotoxy::$1) goto gotoxy::@1
to:gotoxy::@2
gotoxy::@1: scope:[gotoxy] from gotoxy gotoxy::@2
gotoxy::x#2 = phi( gotoxy/gotoxy::x#3, gotoxy::@2/gotoxy::x#4 )
gotoxy::$2 = gotoxy::x#2 >= $28
gotoxy::$3 = ! gotoxy::$2
if(gotoxy::$3) goto gotoxy::@return
to:gotoxy::@3
gotoxy::@2: scope:[gotoxy] from gotoxy
gotoxy::x#4 = phi( gotoxy/gotoxy::x#3 )
gotoxy::y#0 = 0
to:gotoxy::@1
gotoxy::@3: scope:[gotoxy] from gotoxy::@1
gotoxy::x#0 = 0
to:gotoxy::@return
gotoxy::@return: scope:[gotoxy] from gotoxy::@1 gotoxy::@3
return
to:@return
void conio_c64_init()
conio_c64_init: scope:[conio_c64_init] from __start::__init1
conio_c64_init::line#0 = *conio_c64_init::BASIC_CURSOR_LINE
conio_c64_init::$0 = conio_c64_init::line#0 >= $19
conio_c64_init::$1 = ! conio_c64_init::$0
if(conio_c64_init::$1) goto conio_c64_init::@1
to:conio_c64_init::@2
conio_c64_init::@1: scope:[conio_c64_init] from conio_c64_init conio_c64_init::@2
conio_c64_init::line#2 = phi( conio_c64_init/conio_c64_init::line#0, conio_c64_init::@2/conio_c64_init::line#1 )
gotoxy::x#1 = 0
gotoxy::y#1 = conio_c64_init::line#2
call gotoxy
to:conio_c64_init::@3
conio_c64_init::@3: scope:[conio_c64_init] from conio_c64_init::@1
to:conio_c64_init::@return
conio_c64_init::@2: scope:[conio_c64_init] from conio_c64_init
conio_c64_init::line#1 = $19-1
to:conio_c64_init::@1
conio_c64_init::@return: scope:[conio_c64_init] from conio_c64_init::@3
return
to:@return
void chrout(volatile char petscii)
chrout: scope:[chrout] from main main::@1 main::@2 main::@3 main::@4
asm { jsr$ffd2 }
to:chrout::@return
chrout::@return: scope:[chrout] from chrout
return
to:@return
void main()
main: scope:[main] from __start::@1
chrout::petscii = $95
call chrout
to:main::@1
main::@1: scope:[main] from main
chrout::petscii = points[0]
call chrout
to:main::@2
main::@2: scope:[main] from main::@1
chrout::petscii = points[1]
call chrout
to:main::@3
main::@3: scope:[main] from main::@2
chrout::petscii = points[2]
call chrout
to:main::@4
main::@4: scope:[main] from main::@3
chrout::petscii = points[3]
call chrout
to:main::@5
main::@5: scope:[main] from main::@4
to:main::@return
main::@return: scope:[main] from main::@5
return
to:@return
void __start()
__start: scope:[__start] from
to:__start::__init1
__start::__init1: scope:[__start] from __start
call conio_c64_init
to:__start::@2
__start::@2: scope:[__start] from __start::__init1
to:__start::@1
__start::@1: scope:[__start] from __start::@2
call main
to:__start::@3
__start::@3: scope:[__start] from __start::@1
to:__start::@return
__start::@return: scope:[__start] from __start::@3
return
to:@return
SYMBOL TABLE SSA
__constant char RADIX::BINARY = 2
__constant char RADIX::DECIMAL = $a
__constant char RADIX::HEXADECIMAL = $10
__constant char RADIX::OCTAL = 8
void __start()
void chrout(volatile char petscii)
__loadstore volatile char chrout::petscii
void conio_c64_init()
bool conio_c64_init::$0
bool conio_c64_init::$1
__constant char * const conio_c64_init::BASIC_CURSOR_LINE = (char *)$d6
char conio_c64_init::line
char conio_c64_init::line#0
char conio_c64_init::line#1
char conio_c64_init::line#2
void gotoxy(char x , char y)
bool gotoxy::$0
bool gotoxy::$1
bool gotoxy::$2
bool gotoxy::$3
char gotoxy::x
char gotoxy::x#0
char gotoxy::x#1
char gotoxy::x#2
char gotoxy::x#3
char gotoxy::x#4
char gotoxy::y
char gotoxy::y#0
char gotoxy::y#1
char gotoxy::y#2
void main()
__constant char points[] = { 1, 2, 3, 4 }
Adding number conversion cast (unumber) $19 in gotoxy::$0 = gotoxy::y#2 > $19
Adding number conversion cast (unumber) $28 in gotoxy::$2 = gotoxy::x#2 >= $28
Adding number conversion cast (unumber) 0 in gotoxy::y#0 = 0
Adding number conversion cast (unumber) 0 in gotoxy::x#0 = 0
Adding number conversion cast (unumber) $19 in conio_c64_init::$0 = conio_c64_init::line#0 >= $19
Adding number conversion cast (unumber) 0 in gotoxy::x#1 = 0
Adding number conversion cast (unumber) $19-1 in conio_c64_init::line#1 = $19-1
Adding number conversion cast (unumber) $95 in chrout::petscii = $95
Adding number conversion cast (unumber) 0 in chrout::petscii = points[0]
Adding number conversion cast (unumber) 1 in chrout::petscii = points[1]
Adding number conversion cast (unumber) 2 in chrout::petscii = points[2]
Adding number conversion cast (unumber) 3 in chrout::petscii = points[3]
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast gotoxy::y#0 = (unumber)0
Inlining cast gotoxy::x#0 = (unumber)0
Inlining cast gotoxy::x#1 = (unumber)0
Inlining cast conio_c64_init::line#1 = (unumber)$19-1
Inlining cast chrout::petscii = (unumber)$95
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (char *) 214
Simplifying constant integer cast $19
Simplifying constant integer cast $28
Simplifying constant integer cast 0
Simplifying constant integer cast 0
Simplifying constant integer cast $19
Simplifying constant integer cast 0
Simplifying constant integer cast $95
Simplifying constant integer cast 0
Simplifying constant integer cast 1
Simplifying constant integer cast 2
Simplifying constant integer cast 3
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (char) $19
Finalized unsigned number type (char) $28
Finalized unsigned number type (char) 0
Finalized unsigned number type (char) 0
Finalized unsigned number type (char) $19
Finalized unsigned number type (char) 0
Finalized unsigned number type (char) $95
Finalized unsigned number type (char) 0
Finalized unsigned number type (char) 1
Finalized unsigned number type (char) 2
Finalized unsigned number type (char) 3
Successful SSA optimization PassNFinalizeNumberTypeConversions
Inversing boolean not [2] gotoxy::$1 = gotoxy::y#2 <= $19 from [1] gotoxy::$0 = gotoxy::y#2 > $19
Inversing boolean not [6] gotoxy::$3 = gotoxy::x#2 < $28 from [5] gotoxy::$2 = gotoxy::x#2 >= $28
Inversing boolean not [14] conio_c64_init::$1 = conio_c64_init::line#0 < $19 from [13] conio_c64_init::$0 = conio_c64_init::line#0 >= $19
Successful SSA optimization Pass2UnaryNotSimplification
Alias gotoxy::x#3 = gotoxy::x#4
Successful SSA optimization Pass2AliasElimination
Alias gotoxy::x#2 = gotoxy::x#3
Successful SSA optimization Pass2AliasElimination
Identical Phi Values gotoxy::y#2 gotoxy::y#1
Identical Phi Values gotoxy::x#2 gotoxy::x#1
Successful SSA optimization Pass2IdenticalPhiElimination
Simple Condition gotoxy::$1 [2] if(gotoxy::y#1<=$19) goto gotoxy::@1
Simple Condition gotoxy::$3 [4] if(gotoxy::x#1<$28) goto gotoxy::@return
Simple Condition conio_c64_init::$1 [10] if(conio_c64_init::line#0<$19) goto conio_c64_init::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant right-side identified [15] conio_c64_init::line#1 = (unumber)$19-1
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant gotoxy::y#0 = 0
Constant gotoxy::x#0 = 0
Constant gotoxy::x#1 = 0
Constant conio_c64_init::line#1 = (unumber)$19-1
Successful SSA optimization Pass2ConstantIdentification
if() condition always true - replacing block destination [4] if(gotoxy::x#1<$28) goto gotoxy::@return
Successful SSA optimization Pass2ConstantIfs
Rewriting conditional comparison [2] if(gotoxy::y#1<=$19) goto gotoxy::@1
Simplifying expression containing zero points in [21] chrout::petscii = points[0]
Successful SSA optimization PassNSimplifyExpressionWithZero
Removing call to empty/unused procedure [30] call conio_c64_init
Successful SSA optimization PassNEliminateUnusedConstructors
Eliminating variable conio_c64_init::line#0 from unused block conio_c64_init
Eliminating variable conio_c64_init::line#2 from unused block conio_c64_init::@1
Eliminating variable gotoxy::y#1 from unused block conio_c64_init::@1
Removing unused procedure gotoxy
Removing unused procedure block gotoxy
Removing unused procedure block gotoxy::@1
Removing unused procedure block gotoxy::@2
Removing unused procedure block gotoxy::@3
Removing unused procedure block gotoxy::@return
Removing unused procedure conio_c64_init
Removing unused procedure block conio_c64_init
Removing PHI-reference to removed block (conio_c64_init) in block conio_c64_init::@1
Removing unused procedure block conio_c64_init::@1
Removing unused procedure block conio_c64_init::@3
Removing unused procedure block conio_c64_init::@2
Removing unused procedure block conio_c64_init::@return
Successful SSA optimization Pass2EliminateUnusedBlocks
Removing unused procedure __start
Removing unused procedure block __start
Removing unused procedure block __start::__init1
Removing unused procedure block __start::@2
Removing unused procedure block __start::@1
Removing unused procedure block __start::@3
Removing unused procedure block __start::@return
Successful SSA optimization PassNEliminateEmptyStart
Consolidated array index constant in *(points+1)
Consolidated array index constant in *(points+2)
Consolidated array index constant in *(points+3)
Successful SSA optimization Pass2ConstantAdditionElimination
Finalized unsigned number type (char) 2
Finalized unsigned number type (char) 8
Finalized unsigned number type (char) $a
Finalized unsigned number type (char) $10
Finalized unsigned number type (char) $b
Finalized unsigned number type (char) $b
Successful SSA optimization PassNFinalizeNumberTypeConversions
Adding NOP phi() at start of main::@5
CALL GRAPH
Calls in [main] to chrout:1 chrout:3 chrout:5 chrout:7 chrout:9
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Culled Empty Block label main::@5
FINAL CONTROL FLOW GRAPH
void main()
main: scope:[main] from
[0] chrout::petscii = $95
[1] call chrout
to:main::@1
main::@1: scope:[main] from main
[2] chrout::petscii = *points
[3] call chrout
to:main::@2
main::@2: scope:[main] from main::@1
[4] chrout::petscii = *(points+1)
[5] call chrout
to:main::@3
main::@3: scope:[main] from main::@2
[6] chrout::petscii = *(points+2)
[7] call chrout
to:main::@4
main::@4: scope:[main] from main::@3
[8] chrout::petscii = *(points+3)
[9] call chrout
to:main::@return
main::@return: scope:[main] from main::@4
[10] return
to:@return
void chrout(volatile char petscii)
chrout: scope:[chrout] from main main::@1 main::@2 main::@3 main::@4
asm { jsr$ffd2 }
to:chrout::@return
chrout::@return: scope:[chrout] from chrout
[12] return
to:@return
VARIABLE REGISTER WEIGHTS
void chrout(volatile char petscii)
__loadstore volatile char chrout::petscii // 100.0
void main()
Initial phi equivalence classes
Added variable chrout::petscii to live range equivalence class [ chrout::petscii ]
Complete equivalence classes
[ chrout::petscii ]
Allocated zp[1]:2 [ chrout::petscii ]
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] chrout::petscii = $95 [ ] ( [ ] { } ) always clobbers reg byte a
Statement [2] chrout::petscii = *points [ ] ( [ ] { } ) always clobbers reg byte a
Statement [4] chrout::petscii = *(points+1) [ ] ( [ ] { } ) always clobbers reg byte a
Statement [6] chrout::petscii = *(points+2) [ ] ( [ ] { } ) always clobbers reg byte a
Statement [8] chrout::petscii = *(points+3) [ ] ( [ ] { } ) always clobbers reg byte a
Statement asm { jsr$ffd2 } always clobbers reg byte a reg byte x reg byte y
Potential registers zp[1]:2 [ chrout::petscii ] : zp[1]:2 ,
REGISTER UPLIFT SCOPES
Uplift Scope [chrout] 100: zp[1]:2 [ chrout::petscii ]
Uplift Scope [RADIX]
Uplift Scope [MOS6526_CIA]
Uplift Scope [MOS6569_VICII]
Uplift Scope [MOS6581_SID]
Uplift Scope [printf_format_number]
Uplift Scope [printf_buffer_number]
Uplift Scope [printf_format_string]
Uplift Scope [main]
Uplift Scope []
Uplifting [chrout] best 99 combination zp[1]:2 [ chrout::petscii ]
Uplifting [RADIX] best 99 combination
Uplifting [MOS6526_CIA] best 99 combination
Uplifting [MOS6569_VICII] best 99 combination
Uplifting [MOS6581_SID] best 99 combination
Uplifting [printf_format_number] best 99 combination
Uplifting [printf_buffer_number] best 99 combination
Uplifting [printf_format_string] best 99 combination
Uplifting [main] best 99 combination
Uplifting [] best 99 combination
Attempting to uplift remaining variables inzp[1]:2 [ chrout::petscii ]
Uplifting [chrout] best 99 combination zp[1]:2 [ chrout::petscii ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
/// @file
/// Functions for performing input and output.
// Upstart
// Commodore 64 PRG executable file
.file [name="ducks-array.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.segment Code
// main
main: {
// [0] chrout::petscii = $95 -- vbuz1=vbuc1
lda #$95
sta.z chrout.petscii
// [1] call chrout
jsr chrout
jmp __b1
// main::@1
__b1:
// [2] chrout::petscii = *points -- vbuz1=_deref_pbuc1
lda points
sta.z chrout.petscii
// [3] call chrout
jsr chrout
jmp __b2
// main::@2
__b2:
// [4] chrout::petscii = *(points+1) -- vbuz1=_deref_pbuc1
lda points+1
sta.z chrout.petscii
// [5] call chrout
jsr chrout
jmp __b3
// main::@3
__b3:
// [6] chrout::petscii = *(points+2) -- vbuz1=_deref_pbuc1
lda points+2
sta.z chrout.petscii
// [7] call chrout
jsr chrout
jmp __b4
// main::@4
__b4:
// [8] chrout::petscii = *(points+3) -- vbuz1=_deref_pbuc1
lda points+3
sta.z chrout.petscii
// [9] call chrout
jsr chrout
jmp __breturn
// main::@return
__breturn:
// [10] return
rts
}
// chrout
// void chrout(__zp(2) volatile char petscii)
chrout: {
.label petscii = 2
// asm { jsr$ffd2 }
jsr $ffd2
jmp __breturn
// chrout::@return
__breturn:
// [12] return
rts
}
// File Data
.segment Data
points: .byte 1, 2, 3, 4
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __b2
Removing instruction jmp __b3
Removing instruction jmp __b4
Removing instruction jmp __breturn
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction __b1:
Removing instruction __b2:
Removing instruction __b3:
Removing instruction __b4:
Removing instruction __breturn:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
__constant char RADIX::BINARY = 2
__constant char RADIX::DECIMAL = $a
__constant char RADIX::HEXADECIMAL = $10
__constant char RADIX::OCTAL = 8
void chrout(volatile char petscii)
__loadstore volatile char chrout::petscii // zp[1]:2 100.0
void main()
__constant char points[] = { 1, 2, 3, 4 }
zp[1]:2 [ chrout::petscii ]
FINAL ASSEMBLER
Score: 81
// File Comments
/// @file
/// Functions for performing input and output.
// Upstart
// Commodore 64 PRG executable file
.file [name="ducks-array.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.segment Code
// main
main: {
// chrout(149)
// [0] chrout::petscii = $95 -- vbuz1=vbuc1
lda #$95
sta.z chrout.petscii
// [1] call chrout
jsr chrout
// main::@1
// chrout(points[0])
// [2] chrout::petscii = *points -- vbuz1=_deref_pbuc1
lda points
sta.z chrout.petscii
// [3] call chrout
jsr chrout
// main::@2
// chrout(points[1])
// [4] chrout::petscii = *(points+1) -- vbuz1=_deref_pbuc1
lda points+1
sta.z chrout.petscii
// [5] call chrout
jsr chrout
// main::@3
// chrout(points[2])
// [6] chrout::petscii = *(points+2) -- vbuz1=_deref_pbuc1
lda points+2
sta.z chrout.petscii
// [7] call chrout
jsr chrout
// main::@4
// chrout(points[3])
// [8] chrout::petscii = *(points+3) -- vbuz1=_deref_pbuc1
lda points+3
sta.z chrout.petscii
// [9] call chrout
jsr chrout
// main::@return
// }
// [10] return
rts
}
// chrout
// void chrout(__zp(2) volatile char petscii)
chrout: {
.label petscii = 2
// asm
// asm { jsr$ffd2 }
jsr $ffd2
// chrout::@return
// }
// [12] return
rts
}
// File Data
.segment Data
points: .byte 1, 2, 3, 4

View File

@ -0,0 +1,10 @@
__constant char RADIX::BINARY = 2
__constant char RADIX::DECIMAL = $a
__constant char RADIX::HEXADECIMAL = $10
__constant char RADIX::OCTAL = 8
void chrout(volatile char petscii)
__loadstore volatile char chrout::petscii // zp[1]:2 100.0
void main()
__constant char points[] = { 1, 2, 3, 4 }
zp[1]:2 [ chrout::petscii ]

View File

@ -0,0 +1,46 @@
/// @file
/// PEEK and POKE macros for those who want to write BASIC code in C
///
/// Based on https://github.com/cc65/cc65/blob/master/include/peekpoke.h
// Commodore 64 PRG executable file
.file [name="ducks-loop211.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
.const brick = $e6
.segment Code
main: {
.label k = 2
lda #1
sta.z k
__b1:
// POKE
lda.z k
asl
asl
sta.z $d3
// chrout(brick)
lda #brick
sta.z chrout.petscii
jsr chrout
// ++k;
inc.z k
// while (k<5)
lda.z k
cmp #5
bcc __b1
// }
rts
}
// void chrout(__zp(3) volatile char petscii)
chrout: {
.label petscii = 3
// asm
lda petscii
jsr $ffd2
// }
rts
}

View File

@ -0,0 +1,27 @@
void main()
main: scope:[main] from
[0] phi()
to:main::@1
main::@1: scope:[main] from main main::@2
[1] main::k#2 = phi( main/1, main::@2/main::k#1 )
[2] main::$0 = main::k#2 << 2
[3] *((char *) 211) = main::$0
[4] chrout::petscii = brick
[5] call chrout
to:main::@2
main::@2: scope:[main] from main::@1
[6] main::k#1 = ++ main::k#2
[7] if(main::k#1<5) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@2
[8] return
to:@return
void chrout(volatile char petscii)
chrout: scope:[chrout] from main::@1
asm { ldapetscii jsr$ffd2 }
to:chrout::@return
chrout::@return: scope:[chrout] from chrout
[10] return
to:@return

View File

@ -0,0 +1,353 @@
CONTROL FLOW GRAPH SSA
void chrout(volatile char petscii)
chrout: scope:[chrout] from main::@1
asm { ldapetscii jsr$ffd2 }
to:chrout::@return
chrout::@return: scope:[chrout] from chrout
return
to:@return
void main()
main: scope:[main] from __start
main::k#0 = 1
to:main::@1
main::@1: scope:[main] from main main::@2
main::k#2 = phi( main/main::k#0, main::@2/main::k#1 )
main::$0 = main::k#2 * 4
*((char *)$d3) = main::$0
chrout::petscii = brick
call chrout
to:main::@2
main::@2: scope:[main] from main::@1
main::k#3 = phi( main::@1/main::k#2 )
main::k#1 = ++ main::k#3
main::$2 = main::k#1 < 5
if(main::$2) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@2
return
to:@return
void __start()
__start: scope:[__start] from
call main
to:__start::@1
__start::@1: scope:[__start] from __start
to:__start::@return
__start::@return: scope:[__start] from __start::@1
return
to:@return
SYMBOL TABLE SSA
void __start()
__constant const char brick = $e6
void chrout(volatile char petscii)
__loadstore volatile char chrout::petscii
void main()
number main::$0
bool main::$2
char main::k
char main::k#0
char main::k#1
char main::k#2
char main::k#3
Adding number conversion cast (unumber) 4 in main::$0 = main::k#2 * 4
Adding number conversion cast (unumber) main::$0 in main::$0 = main::k#2 * (unumber)4
Adding number conversion cast (unumber) 5 in main::$2 = main::k#1 < 5
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant integer cast 4
Simplifying constant pointer cast (char *) 211
Simplifying constant integer cast 5
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (char) 4
Finalized unsigned number type (char) 5
Successful SSA optimization PassNFinalizeNumberTypeConversions
Inferred type updated to char in main::$0 = main::k#2 * 4
Alias main::k#2 = main::k#3
Successful SSA optimization Pass2AliasElimination
Simple Condition main::$2 [10] if(main::k#1<5) goto main::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant main::k#0 = 1
Successful SSA optimization Pass2ConstantIdentification
Removing unused procedure __start
Removing unused procedure block __start
Removing unused procedure block __start::@1
Removing unused procedure block __start::@return
Successful SSA optimization PassNEliminateEmptyStart
Rewriting multiplication to use shift [3] main::$0 = main::k#2 * 4
Successful SSA optimization Pass2MultiplyToShiftRewriting
Inlining constant with var siblings main::k#0
Constant inlined main::k#0 = 1
Successful SSA optimization Pass2ConstantInlining
Added new block during phi lifting main::@3(between main::@2 and main::@1)
Adding NOP phi() at start of main
CALL GRAPH
Calls in [main] to chrout:5
Created 1 initial phi equivalence classes
Coalesced [9] main::k#4 = main::k#1
Coalesced down to 1 phi equivalence classes
Culled Empty Block label main::@3
Adding NOP phi() at start of main
FINAL CONTROL FLOW GRAPH
void main()
main: scope:[main] from
[0] phi()
to:main::@1
main::@1: scope:[main] from main main::@2
[1] main::k#2 = phi( main/1, main::@2/main::k#1 )
[2] main::$0 = main::k#2 << 2
[3] *((char *) 211) = main::$0
[4] chrout::petscii = brick
[5] call chrout
to:main::@2
main::@2: scope:[main] from main::@1
[6] main::k#1 = ++ main::k#2
[7] if(main::k#1<5) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@2
[8] return
to:@return
void chrout(volatile char petscii)
chrout: scope:[chrout] from main::@1
asm { ldapetscii jsr$ffd2 }
to:chrout::@return
chrout::@return: scope:[chrout] from chrout
[10] return
to:@return
VARIABLE REGISTER WEIGHTS
void chrout(volatile char petscii)
__loadstore volatile char chrout::petscii // 11.0
void main()
char main::$0 // 22.0
char main::k
char main::k#1 // 16.5
char main::k#2 // 6.6000000000000005
Initial phi equivalence classes
[ main::k#2 main::k#1 ]
Added variable main::$0 to live range equivalence class [ main::$0 ]
Added variable chrout::petscii to live range equivalence class [ chrout::petscii ]
Complete equivalence classes
[ main::k#2 main::k#1 ]
[ main::$0 ]
[ chrout::petscii ]
Allocated zp[1]:2 [ main::k#2 main::k#1 ]
Allocated zp[1]:3 [ main::$0 ]
Allocated zp[1]:4 [ chrout::petscii ]
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [2] main::$0 = main::k#2 << 2 [ main::k#2 main::$0 ] ( [ main::k#2 main::$0 ] { } ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::k#2 main::k#1 ]
Statement [4] chrout::petscii = brick [ main::k#2 chrout::petscii ] ( [ main::k#2 chrout::petscii ] { } ) always clobbers reg byte a
Statement asm { ldapetscii jsr$ffd2 } always clobbers reg byte a reg byte x reg byte y
Removing always clobbered register reg byte x as potential for zp[1]:2 [ main::k#2 main::k#1 ]
Removing always clobbered register reg byte y as potential for zp[1]:2 [ main::k#2 main::k#1 ]
Statement [2] main::$0 = main::k#2 << 2 [ main::k#2 main::$0 ] ( [ main::k#2 main::$0 ] { } ) always clobbers reg byte a
Statement [4] chrout::petscii = brick [ main::k#2 chrout::petscii ] ( [ main::k#2 chrout::petscii ] { } ) always clobbers reg byte a
Statement [7] if(main::k#1<5) goto main::@1 [ main::k#1 ] ( [ main::k#1 ] { } ) always clobbers reg byte a
Statement asm { ldapetscii jsr$ffd2 } always clobbers reg byte a reg byte x reg byte y
Potential registers zp[1]:2 [ main::k#2 main::k#1 ] : zp[1]:2 ,
Potential registers zp[1]:3 [ main::$0 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[1]:4 [ chrout::petscii ] : zp[1]:4 ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 23.1: zp[1]:2 [ main::k#2 main::k#1 ] 22: zp[1]:3 [ main::$0 ]
Uplift Scope [chrout] 11: zp[1]:4 [ chrout::petscii ]
Uplift Scope []
Uplifting [main] best 530 combination zp[1]:2 [ main::k#2 main::k#1 ] reg byte a [ main::$0 ]
Uplifting [chrout] best 530 combination zp[1]:4 [ chrout::petscii ]
Uplifting [] best 530 combination
Attempting to uplift remaining variables inzp[1]:2 [ main::k#2 main::k#1 ]
Uplifting [main] best 530 combination zp[1]:2 [ main::k#2 main::k#1 ]
Attempting to uplift remaining variables inzp[1]:4 [ chrout::petscii ]
Uplifting [chrout] best 530 combination zp[1]:4 [ chrout::petscii ]
Allocated (was zp[1]:4) zp[1]:3 [ chrout::petscii ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
/// @file
/// PEEK and POKE macros for those who want to write BASIC code in C
///
/// Based on https://github.com/cc65/cc65/blob/master/include/peekpoke.h
// Upstart
// Commodore 64 PRG executable file
.file [name="ducks-loop211.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.const brick = $e6
.segment Code
// main
main: {
.label k = 2
// [1] phi from main to main::@1 [phi:main->main::@1]
__b1_from_main:
// [1] phi main::k#2 = 1 [phi:main->main::@1#0] -- vbuz1=vbuc1
lda #1
sta.z k
jmp __b1
// [1] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
__b1_from___b2:
// [1] phi main::k#2 = main::k#1 [phi:main::@2->main::@1#0] -- register_copy
jmp __b1
// main::@1
__b1:
// [2] main::$0 = main::k#2 << 2 -- vbuaa=vbuz1_rol_2
lda.z k
asl
asl
// [3] *((char *) 211) = main::$0 -- _deref_pbuc1=vbuaa
sta.z $d3
// [4] chrout::petscii = brick -- vbuz1=vbuc1
lda #brick
sta.z chrout.petscii
// [5] call chrout
jsr chrout
jmp __b2
// main::@2
__b2:
// [6] main::k#1 = ++ main::k#2 -- vbuz1=_inc_vbuz1
inc.z k
// [7] if(main::k#1<5) goto main::@1 -- vbuz1_lt_vbuc1_then_la1
lda.z k
cmp #5
bcc __b1_from___b2
jmp __breturn
// main::@return
__breturn:
// [8] return
rts
}
// chrout
// void chrout(__zp(3) volatile char petscii)
chrout: {
.label petscii = 3
// asm { ldapetscii jsr$ffd2 }
lda petscii
jsr $ffd2
jmp __breturn
// chrout::@return
__breturn:
// [10] return
rts
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __b2
Removing instruction jmp __breturn
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label __b1_from___b2 with __b1
Removing instruction __b1_from___b2:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __b1_from_main:
Removing instruction __b2:
Removing instruction __breturn:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Removing instruction jmp __b1
Succesful ASM optimization Pass5NextJumpElimination
FINAL SYMBOL TABLE
__constant const char brick = $e6
void chrout(volatile char petscii)
__loadstore volatile char chrout::petscii // zp[1]:3 11.0
void main()
char main::$0 // reg byte a 22.0
char main::k
char main::k#1 // k zp[1]:2 16.5
char main::k#2 // k zp[1]:2 6.6000000000000005
zp[1]:2 [ main::k#2 main::k#1 ]
reg byte a [ main::$0 ]
zp[1]:3 [ chrout::petscii ]
FINAL ASSEMBLER
Score: 407
// File Comments
/// @file
/// PEEK and POKE macros for those who want to write BASIC code in C
///
/// Based on https://github.com/cc65/cc65/blob/master/include/peekpoke.h
// Upstart
// Commodore 64 PRG executable file
.file [name="ducks-loop211.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.const brick = $e6
.segment Code
// main
main: {
.label k = 2
// [1] phi from main to main::@1 [phi:main->main::@1]
// [1] phi main::k#2 = 1 [phi:main->main::@1#0] -- vbuz1=vbuc1
lda #1
sta.z k
// [1] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
// [1] phi main::k#2 = main::k#1 [phi:main::@2->main::@1#0] -- register_copy
// main::@1
__b1:
// POKE
// [2] main::$0 = main::k#2 << 2 -- vbuaa=vbuz1_rol_2
lda.z k
asl
asl
// [3] *((char *) 211) = main::$0 -- _deref_pbuc1=vbuaa
sta.z $d3
// chrout(brick)
// [4] chrout::petscii = brick -- vbuz1=vbuc1
lda #brick
sta.z chrout.petscii
// [5] call chrout
jsr chrout
// main::@2
// ++k;
// [6] main::k#1 = ++ main::k#2 -- vbuz1=_inc_vbuz1
inc.z k
// while (k<5)
// [7] if(main::k#1<5) goto main::@1 -- vbuz1_lt_vbuc1_then_la1
lda.z k
cmp #5
bcc __b1
// main::@return
// }
// [8] return
rts
}
// chrout
// void chrout(__zp(3) volatile char petscii)
chrout: {
.label petscii = 3
// asm
// asm { ldapetscii jsr$ffd2 }
lda petscii
jsr $ffd2
// chrout::@return
// }
// [10] return
rts
}
// File Data

View File

@ -0,0 +1,12 @@
__constant const char brick = $e6
void chrout(volatile char petscii)
__loadstore volatile char chrout::petscii // zp[1]:3 11.0
void main()
char main::$0 // reg byte a 22.0
char main::k
char main::k#1 // k zp[1]:2 16.5
char main::k#2 // k zp[1]:2 6.6000000000000005
zp[1]:2 [ main::k#2 main::k#1 ]
reg byte a [ main::$0 ]
zp[1]:3 [ chrout::petscii ]

2126
src/test/ref/ducks-total.asm Normal file

File diff suppressed because it is too large Load Diff

1030
src/test/ref/ducks-total.cfg Normal file

File diff suppressed because it is too large Load Diff

16903
src/test/ref/ducks-total.log Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,440 @@
__constant char * const COLORRAM = (char *) 55296
__constant char * const DEFAULT_SCREEN = (char *) 1024
__constant char DIGITS[] = "0123456789abcdef"z
__constant const char LIGHT_BLUE = $e
__constant char RADIX::BINARY = 2
__constant char RADIX::DECIMAL = $a
__constant char RADIX::HEXADECIMAL = $10
__constant char RADIX::OCTAL = 8
__constant unsigned int RADIX_DECIMAL_VALUES[] = { $2710, $3e8, $64, $a }
void __start()
__constant const char brick = $e6
__constant char buffer[] = { 0, 0, 0, 0 }
__constant const unsigned int c = $7800
__constant const char chrono[] = { $54, $4d, $3a, $39 }
void chrono_restart()
void chrout(volatile char petscii)
__loadstore volatile char chrout::petscii // zp[1]:24 3.0310104636363637E7
void clear_screen(char n , char m)
unsigned int clear_screen::$4 // zp[2]:35 100001.0
unsigned int clear_screen::$5 // zp[2]:9 66667.33333333333
char clear_screen::m
char clear_screen::n
char clear_screen::n#5 // n zp[1]:8 12500.125
void conio_c64_init()
__constant char * const conio_c64_init::BASIC_CURSOR_LINE = (char *) 214
char conio_c64_init::line
char conio_c64_init::line#0 // line zp[1]:76 11.0
char conio_c64_init::line#2 // line zp[1]:76 22.0
__loadstore char conio_cursor_x // zp[1]:39 200133.45333333334
__loadstore char conio_cursor_y // zp[1]:29 3516593.4945054944
__loadstore char *conio_line_color // zp[2]:30 2662771.1807228914
__loadstore char *conio_line_text // zp[2]:32 2600117.7411764706
__loadstore char conio_textcolor // zp[1]:34 1629048.4677419355
void cputc(char c)
char cputc::c
char cputc::c#0 // c zp[1]:2 1050001.5
void cputln()
void cputs(const char *s)
char cputs::c
char cputs::c#1 // c zp[1]:2 100001.0
const char *cputs::s
const char *cputs::s#0 // s zp[2]:5 50000.5
const char *cputs::s#10 // s zp[2]:5 150502.0
const char *cputs::s#11 // s zp[2]:5 1001.0
void cscroll()
unsigned int div16u8u(unsigned int dividend , char divisor)
unsigned int div16u8u::dividend
unsigned int div16u8u::dividend#0 // dividend zp[2]:35 420000.60000000003
char div16u8u::divisor
__constant char div16u8u::divisor#0 = $3c // divisor
unsigned int div16u8u::quotient
char div16u8u::quotient_hi
char div16u8u::quotient_hi#0 // quotient_hi zp[1]:2 333333.6666666667
char div16u8u::quotient_lo
char div16u8u::quotient_lo#0 // quotient_lo zp[1]:16 2000002.0
unsigned int div16u8u::return
unsigned int div16u8u::return#0 // return zp[2]:18 366667.3333333334
unsigned int div16u8u::return#2 // return_1 zp[2]:48 9166.833333333332
char divr8u(char dividend , char divisor , char rem)
char divr8u::$1 // zp[1]:17 2.00000000002E11
char divr8u::dividend
char divr8u::dividend#0 // dividend zp[1]:3 2.500000000025E10
char divr8u::dividend#1 // dividend zp[1]:3 2000002.0
char divr8u::dividend#2 // dividend zp[1]:3 1000001.0
char divr8u::dividend#3 // dividend zp[1]:3 5.0001666667333336E10
char divr8u::dividend#5 // dividend zp[1]:3 1.2000003E7
char divr8u::divisor
char divr8u::i
char divr8u::i#1 // i zp[1]:7 1.500000000015E11
char divr8u::i#2 // i zp[1]:7 1.6666666666833334E10
char divr8u::quotient
char divr8u::quotient#1 // quotient zp[1]:16 1.500000000015E11
char divr8u::quotient#2 // quotient zp[1]:16 1.00000000001E11
char divr8u::quotient#3 // quotient zp[1]:16 2.8571428571714287E10
char divr8u::rem
char divr8u::rem#0 // rem zp[1]:15 1.00000000001E11
char divr8u::rem#1 // rem zp[1]:15 2.00000000002E11
char divr8u::rem#10 // rem zp[1]:15 1.1000002E7
char divr8u::rem#11 // rem zp[1]:15 2.702711801846847E9
char divr8u::rem#2 // rem zp[1]:15 2.00000000002E11
char divr8u::rem#4 // rem zp[1]:15 2000002.0
char divr8u::rem#5 // rem zp[1]:15 2.00010000003E11
char divr8u::rem#6 // rem zp[1]:15 1.00000000001E11
char divr8u::return
char divr8u::return#0 // return zp[1]:16 5.000033333416667E10
char divr8u::return#2 // return zp[1]:16 2000002.0
char divr8u::return#3 // return zp[1]:16 2000002.0
__constant const char down = $11
unsigned int duck
unsigned int duck#0 // duck zp[2]:22 6.6666667333333336E7
unsigned int duck#1 // duck zp[2]:22 4237745.88135593
__constant const char duck_udg[] = { $e, $1b, $3f, $1f, $f, 7, $f, $1f, 0, 0, 0, 0, 0, $c0, $70, $bc, $1f, $1d, $1e, $f, 3, 1, 1, 3, $ce, $1e, $7c, $f8, $e0, $40, $40, $e0, 0, 0, 0, 0, 0, 0, 0, 0 }
__constant const char ducknumber[] = { $44, $55, $43, $4b, $3a }
__constant const char foot[] = "PRESS: 1,3,5,7 or 9
"
__constant const char game_over[] = "
GAME OVER"
void gotoxy(char x , char y)
char *gotoxy::$5 // zp[2]:72 20002.0
char *gotoxy::$6 // zp[2]:44 20002.0
unsigned int gotoxy::$7 // zp[2]:44 15001.5
unsigned int gotoxy::$8 // zp[2]:70 20002.0
unsigned int gotoxy::$9 // zp[2]:44 20002.0
unsigned int gotoxy::line_offset
unsigned int gotoxy::line_offset#0 // line_offset zp[2]:44 10001.0
char gotoxy::x
char gotoxy::y
char gotoxy::y#2 // y zp[1]:76 22.0
char gotoxy::y#4 // y zp[1]:76 6671.0
char gotoxy::y#5 // y zp[1]:76 6667.333333333333
__constant const char green = $1e
__constant const char high_score[] = "
Hi-Score: "
unsigned int hiscore
unsigned int hiscore#110 // hiscore_1 zp[2]:108 1.1744186046511627
unsigned int hiscore#123 // hiscore_1 zp[2]:108 202.0
unsigned int hiscore#124 // hiscore zp[2]:42 202.0
unsigned int hiscore#19 // hiscore zp[2]:42 31.076923076923077
__constant const char home = $13
__constant const char intro[] = "
DIFFICULTY
----------
"
char j
char j#11 // j zp[1]:50 7500.75
char j#13 // j_1 zp[1]:85 1001.0
char j#16 // j_2 zp[1]:86 1001.0
char j#19 // j_3 zp[1]:104 1034.6666666666667
char j#2 // j zp[1]:50 20002.0
char j#3 // j_1 zp[1]:85 2002.0
char j#5 // j_2 zp[1]:86 2002.0
char k
char k#1 // k zp[1]:99 2002.0
char k#101 // k zp[1]:99 273.0
__loadstore volatile char l // zp[1]:107 455.79148936170213
__constant const char levels[] = "1.EASIEST
3.EASY
5.MEDIUM
7.HARD
9.EXPERT
"
__constant const char lock = 8
__constant const char lower = $e
__loadstore volatile char m // zp[1]:4 3.8961039106499544E16
void main()
unsigned int main::$104 // zp[2]:93 2500.25
unsigned int main::$107 // zp[2]:95 2500.25
unsigned int main::$110 // zp[2]:97 2500.25
unsigned int main::$119 // zp[2]:74 6667.333333333333
unsigned int main::$120 // zp[2]:81 10001.0
unsigned int main::$122 // zp[2]:83 10001.0
unsigned int main::$124 // zp[2]:74 10001.0
unsigned int main::$125 // zp[2]:77 10001.0
unsigned int main::$127 // zp[2]:58 10001.0
unsigned int main::$128 // zp[2]:58 10001.0
unsigned int main::$130 // zp[2]:60 10001.0
unsigned int main::$131 // zp[2]:60 10001.0
unsigned int main::$133 // zp[2]:62 10001.0
unsigned int main::$134 // zp[2]:62 10001.0
unsigned int main::$136 // zp[2]:79 10001.0
unsigned int main::$138 // zp[2]:64 10001.0
unsigned int main::$139 // zp[2]:64 10001.0
unsigned int main::$141 // zp[2]:66 10001.0
unsigned int main::$142 // zp[2]:66 10001.0
unsigned int main::$144 // zp[2]:68 10001.0
unsigned int main::$145 // zp[2]:68 10001.0
unsigned int main::$150 // zp[2]:105 1001.0
unsigned int main::$151 // zp[2]:87 2002.0
unsigned int main::$152 // zp[2]:87 1001.0
unsigned int main::$153 // zp[2]:89 2002.0
unsigned int main::$154 // zp[2]:89 1001.0
unsigned int main::$155 // zp[2]:91 2002.0
unsigned int main::$156 // zp[2]:91 1001.0
char main::$177 // zp[1]:8 2002.0
unsigned int main::$179 // zp[2]:56 20002.0
unsigned int main::$180 // zp[2]:46 20002.0
char main::$26 // zp[1]:8 2002.0
unsigned int main::$29 // zp[2]:5 2002.0
unsigned int main::$3 // zp[2]:112 101.0
unsigned int main::$35 // zp[2]:102 2002.0
unsigned int main::$57 // zp[2]:100 2002.0
unsigned int main::$61 // zp[2]:13 2.00000002E8
unsigned int main::$66 // zp[2]:11 2.00000002E7
unsigned int main::$69 // zp[2]:25 2.00000002E7
unsigned int main::$72 // zp[2]:27 2.00000002E7
char main::$78 // zp[1]:16 20002.0
char main::$81 // zp[1]:7 20002.0
char main::$84 // zp[1]:3 20002.0
char main::$88 // zp[1]:54 20002.0
char main::$92 // zp[1]:55 20002.0
unsigned int main::$96 // zp[2]:46 15001.5
unsigned int main::$97 // zp[2]:46 20002.0
void * memcpy(void *destination , void *source , unsigned int num)
void *memcpy::destination
void *memcpy::destination#2 // destination zp[2]:11
char *memcpy::dst
char *memcpy::dst#1 // dst zp[2]:11 1.000000000001E12
char *memcpy::dst#2 // dst zp[2]:11 1.0003333333346667E12
char *memcpy::dst#4 // dst zp[2]:11 2.000000002E9
unsigned int memcpy::num
void *memcpy::return
void *memcpy::source
void *memcpy::source#2 // source zp[2]:13
char *memcpy::src
char *memcpy::src#1 // src zp[2]:13 2.000000000002E12
char *memcpy::src#2 // src zp[2]:13 1.00025000000125E12
char *memcpy::src#4 // src zp[2]:13 1.000000001E9
char *memcpy::src_end
char *memcpy::src_end#0 // src_end zp[2]:9 1.2512500000025E11
void * memset(void *str , char c , unsigned int num)
char memset::c
char memset::c#1 // c zp[1]:16 2.00000002E8
char memset::c#4 // c zp[1]:16 1.4287142857171426E11
char *memset::dst
char *memset::dst#1 // dst zp[2]:11 2.000000000002E12
char *memset::dst#2 // dst zp[2]:11 1.3336666666683335E12
char *memset::dst#4 // dst zp[2]:11 2.000000002E9
char *memset::end
char *memset::end#0 // end zp[2]:18 1.668333333336667E11
unsigned int memset::num
void *memset::return
void *memset::str
void *memset::str#3 // str zp[2]:11
char n
char n#1 // n zp[1]:51 20002.0
char n#101 // n zp[1]:51 4429.142857142857
char n#109 // n zp[1]:51 7.769230769230769
char n#14 // n zp[1]:51 344.8620689655172
char n#20 // n zp[1]:51 220.07272727272726
char n#52 // n zp[1]:51 93.84375
char n#89 // n zp[1]:51 35.644067796610166
unsigned int peephole
unsigned int peephole#12 // peephole zp[2]:52 617.7352941176471
unsigned int peephole#52 // peephole zp[2]:52 62.5625
__constant const char play_again[] = "
Play Again (Y/N)?"
__constant char points[] = { 0, 0, 0, 0 }
void random(char k , char n)
char random::$3 // zp[1]:2 5.5E17
char random::k
char random::k#0 // k zp[1]:3 500.5
char random::k#4 // k zp[1]:3 2.00000000000000192E17
char random::n
char random::n#0 // n zp[1]:8 2002.0
char random::n#4 // n zp[1]:8 2.00000000000002E16
void read_chrono()
unsigned int read_chrono::$0 // zp[2]:35 200002.0
unsigned int read_chrono::$5 // zp[2]:9 200002.0
__constant const char red = $1c
char rem8u
char rem8u#127 // rem8u zp[1]:15 11.6
char rem8u#25 // rem8u zp[1]:15 220.07272727272726
char rem8u#48 // rem8u zp[1]:15 93.84375
__constant const char reverse_on = $12
__constant const char right = $1d
unsigned int score
unsigned int score#13 // score zp[2]:42 70334.66666666666
unsigned int score#19 // score zp[2]:42 1272.9090909090908
unsigned int score#38 // score zp[2]:42 3843.0654205607475
unsigned int score#4 // score zp[2]:42 2002.0
unsigned int score#43 // score zp[2]:42 566.0943396226415
unsigned int score#6 // score zp[2]:42 20002.0
unsigned int score#8 // score zp[2]:42 10001.0
unsigned int score#81 // score zp[2]:42 15001.5
char textcolor(char color)
char textcolor::color
char textcolor::color#7 // color zp[1]:8 1001.0
char textcolor::old
char textcolor::return
unsigned int time
unsigned int time#11 // time zp[2]:48 20002.0
unsigned int time#17 // time zp[2]:48 566.0943396226415
unsigned int time#38 // time zp[2]:48 10001.0
unsigned int tu
unsigned int tu#1 // tu zp[2]:110 166.83333333333334
unsigned int tu#13 // tu zp[2]:110 32.032
void utoa(unsigned int value , char *buffer , char radix)
char utoa::$10 // zp[1]:17 2.0000000002E10
char utoa::$11 // zp[1]:2 2000002.0
char *utoa::buffer
char *utoa::buffer#10 // buffer zp[2]:13 2.857285714714286E9
char *utoa::buffer#15 // buffer zp[2]:13 1.50000000015E10
char *utoa::buffer#3 // buffer zp[2]:13 2000002.0
char *utoa::buffer#4 // buffer zp[2]:13 2.0000000002E10
char utoa::digit
char utoa::digit#1 // digit zp[1]:3 2.0000000002E10
char utoa::digit#2 // digit zp[1]:3 2.857142857428571E9
unsigned int utoa::digit_value
unsigned int utoa::digit_value#0 // digit_value zp[2]:9 6.0000000006E9
unsigned int *utoa::digit_values
char utoa::max_digits
char utoa::radix
char utoa::started
char utoa::started#2 // started zp[1]:16 5.0000000005E9
char utoa::started#4 // started zp[1]:16 1.0000000001E10
unsigned int utoa::value
unsigned int utoa::value#0 // value zp[2]:5 1.0000000001E10
unsigned int utoa::value#1 // value zp[2]:5 200002.0
unsigned int utoa::value#10 // value zp[2]:5 1100103.0
unsigned int utoa::value#2 // value zp[2]:5 202.0
unsigned int utoa::value#3 // value zp[2]:5 5.714428572142858E9
unsigned int utoa::value#7 // value zp[2]:5 1.50000000015E10
unsigned int utoa_append(char *buffer , unsigned int value , unsigned int sub)
char *utoa_append::buffer
char *utoa_append::buffer#0 // buffer zp[2]:13 1.375000000025E10
char utoa_append::digit
char utoa_append::digit#1 // digit zp[1]:7 1.0E16
char utoa_append::digit#2 // digit zp[1]:7 1.000005E16
unsigned int utoa_append::return
unsigned int utoa_append::return#0 // return zp[2]:5 2.0000000002E10
unsigned int utoa_append::sub
unsigned int utoa_append::sub#0 // sub zp[2]:9 3.333335E15
unsigned int utoa_append::value
unsigned int utoa_append::value#0 // value zp[2]:5 3.6666666667333336E10
unsigned int utoa_append::value#1 // value zp[2]:5 2.0E16
unsigned int utoa_append::value#2 // value zp[2]:5 5.000018333333334E15
void wait(char n)
char wait::n
char wait::n#6 // n zp[1]:3 1.25000000125E8
void write_score()
unsigned int y
unsigned int y#0 // y zp[2]:40 20002.0
unsigned int y#1 // y zp[2]:40 20002.0
unsigned int y#10 // y zp[2]:40 13334.666666666666
unsigned int y#11 // y zp[2]:40 13334.666666666666
unsigned int y#114 // y zp[2]:40 11.6
unsigned int y#12 // y zp[2]:40 13334.666666666666
unsigned int y#13 // y zp[2]:40 2285.9428571428575
unsigned int y#130 // y zp[2]:40 20002.0
unsigned int y#141 // y_1 zp[2]:52 20002.0
unsigned int y#18 // y zp[2]:40 509.61904761904765
unsigned int y#2 // y zp[2]:40 20002.0
unsigned int y#3 // y zp[2]:40 20002.0
unsigned int y#35 // y_1 zp[2]:52 2353.1764705882347
unsigned int y#49 // y zp[2]:40 93.84375
__constant const char yellow = $9e
__constant const char your_score[] = "
Your Score: "
unsigned int z
unsigned int z#1 // z zp[2]:37 200002.0
unsigned int z#100 // z_1 zp[2]:20 1050.15
unsigned int z#102 // z_1 zp[2]:20 93.84375
unsigned int z#128 // z_1 zp[2]:20 93.84375
unsigned int z#2 // z zp[2]:37 66667.33333333333
unsigned int z#23 // z_1 zp[2]:20 1.0333333334666666E10
unsigned int z#25 // z_1 zp[2]:20 2.564438476923077E7
unsigned int z#28 // z_1 zp[2]:20 266.93333333333334
unsigned int z#4 // z_1 zp[2]:20 2.0000000002E10
unsigned int z#48 // z_1 zp[2]:20 857.2285714285714
unsigned int z#53 // z_1 zp[2]:20 70503.0
unsigned int z#9 // z_1 zp[2]:20 2002.0
zp[1]:76 [ conio_c64_init::line#2 conio_c64_init::line#0 gotoxy::y#5 gotoxy::y#4 gotoxy::y#2 ]
zp[2]:108 [ hiscore#110 hiscore#123 ]
zp[1]:99 [ k#101 k#1 ]
zp[1]:85 [ j#13 j#3 ]
zp[1]:86 [ j#16 j#5 ]
zp[2]:110 [ tu#13 tu#1 ]
zp[2]:52 [ peephole#52 peephole#12 y#35 y#141 ]
zp[1]:51 [ n#52 n#89 n#109 n#20 n#101 n#14 n#1 ]
zp[2]:48 [ time#11 time#17 time#38 div16u8u::return#2 ]
zp[2]:40 [ y#13 y#12 y#11 y#10 y#0 y#49 y#114 y#18 y#130 y#1 y#2 y#3 ]
zp[2]:42 [ score#81 hiscore#19 hiscore#124 score#19 score#43 score#38 score#8 score#13 score#4 score#6 ]
zp[1]:50 [ j#11 j#2 ]
zp[2]:37 [ z#2 z#1 ]
zp[1]:8 [ random::n#4 random::n#0 main::$26 main::$177 textcolor::color#7 clear_screen::n#5 ]
zp[2]:20 [ z#53 z#48 z#100 z#102 z#128 z#28 z#9 z#25 z#23 z#4 ]
zp[1]:15 [ divr8u::rem#5 divr8u::rem#10 divr8u::rem#4 rem8u#48 rem8u#127 rem8u#25 divr8u::rem#11 divr8u::rem#6 divr8u::rem#0 divr8u::rem#1 divr8u::rem#2 ]
zp[1]:39 [ conio_cursor_x ]
zp[1]:29 [ conio_cursor_y ]
zp[2]:32 [ conio_line_text ]
zp[2]:30 [ conio_line_color ]
zp[1]:34 [ conio_textcolor ]
zp[1]:107 [ l ]
zp[1]:4 [ m ]
zp[1]:24 [ chrout::petscii ]
zp[2]:5 [ main::$29 utoa::value#3 utoa::value#7 utoa::value#10 utoa::value#2 utoa::value#1 utoa::value#0 utoa_append::value#2 utoa_append::value#0 utoa_append::value#1 utoa_append::return#0 cputs::s#10 cputs::s#11 cputs::s#0 ]
zp[2]:22 [ duck#0 duck#1 ]
zp[2]:13 [ main::$61 memcpy::source#2 memcpy::src#2 memcpy::src#4 memcpy::src#1 utoa::buffer#10 utoa::buffer#15 utoa::buffer#4 utoa::buffer#3 utoa_append::buffer#0 ]
zp[2]:11 [ main::$66 memset::str#3 memset::dst#2 memset::dst#4 memset::dst#1 memcpy::destination#2 memcpy::dst#2 memcpy::dst#4 memcpy::dst#1 ]
zp[2]:25 [ main::$69 ]
zp[2]:27 [ main::$72 ]
zp[2]:105 [ main::$150 ]
zp[2]:87 [ main::$151 main::$152 ]
zp[2]:89 [ main::$153 main::$154 ]
zp[2]:91 [ main::$155 main::$156 ]
zp[1]:104 [ j#19 ]
zp[1]:16 [ main::$78 memset::c#4 memset::c#1 divr8u::quotient#3 divr8u::return#0 divr8u::quotient#1 divr8u::quotient#2 divr8u::return#2 divr8u::return#3 div16u8u::quotient_lo#0 utoa::started#2 utoa::started#4 ]
zp[1]:7 [ main::$81 divr8u::i#2 divr8u::i#1 utoa_append::digit#2 utoa_append::digit#1 ]
zp[1]:3 [ main::$84 divr8u::dividend#3 divr8u::dividend#5 divr8u::dividend#1 divr8u::dividend#2 divr8u::dividend#0 utoa::digit#2 utoa::digit#1 wait::n#6 random::k#4 random::k#0 ]
zp[1]:54 [ main::$88 ]
zp[1]:55 [ main::$92 ]
zp[2]:46 [ main::$96 main::$180 main::$97 ]
zp[2]:56 [ main::$179 ]
zp[2]:93 [ main::$104 ]
zp[2]:95 [ main::$107 ]
zp[2]:97 [ main::$110 ]
zp[2]:77 [ main::$125 ]
zp[2]:58 [ main::$127 main::$128 ]
zp[2]:60 [ main::$130 main::$131 ]
zp[2]:62 [ main::$133 main::$134 ]
zp[2]:79 [ main::$136 ]
zp[2]:64 [ main::$138 main::$139 ]
zp[2]:66 [ main::$141 main::$142 ]
zp[2]:68 [ main::$144 main::$145 ]
zp[2]:74 [ main::$119 main::$124 ]
zp[2]:81 [ main::$120 ]
zp[2]:83 [ main::$122 ]
zp[2]:100 [ main::$57 ]
zp[2]:102 [ main::$35 ]
zp[2]:112 [ main::$3 ]
zp[2]:44 [ gotoxy::$7 gotoxy::$9 gotoxy::line_offset#0 gotoxy::$6 ]
zp[2]:70 [ gotoxy::$8 ]
zp[2]:72 [ gotoxy::$5 ]
zp[2]:35 [ read_chrono::$0 div16u8u::dividend#0 clear_screen::$4 ]
zp[1]:2 [ div16u8u::quotient_hi#0 utoa::$11 random::$3 cputs::c#1 cputc::c#0 ]
zp[1]:17 [ divr8u::$1 utoa::$10 ]
zp[2]:9 [ memcpy::src_end#0 read_chrono::$5 utoa::digit_value#0 utoa_append::sub#0 clear_screen::$5 ]
zp[2]:18 [ memset::end#0 div16u8u::return#0 ]

View File

@ -0,0 +1,124 @@
// Commodore 64 PRG executable file
.file [name="pointer-swap.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
.label screen = 2
.label tempbuffer = $c
.label newbuffer = $a
.label tempbuffer_1 = 6
.label newbuffer_1 = 8
.label oldbuffer = 4
.segment Code
main: {
// print()
lda #<buffer2
sta.z oldbuffer
lda #>buffer2
sta.z oldbuffer+1
lda #<buffer1
sta.z newbuffer_1
lda #>buffer1
sta.z newbuffer_1+1
lda #<$400
sta.z screen
lda #>$400
sta.z screen+1
lda #<0
sta.z tempbuffer_1
sta.z tempbuffer_1+1
jsr print
// swap()
lda #<buffer2
sta.z newbuffer
lda #>buffer2
sta.z newbuffer+1
lda #<buffer1
sta.z tempbuffer
lda #>buffer1
sta.z tempbuffer+1
jsr swap
lda.z newbuffer
sta.z tempbuffer
lda.z newbuffer+1
sta.z tempbuffer+1
lda.z tempbuffer
sta.z newbuffer
lda.z tempbuffer+1
sta.z newbuffer+1
// swap()
jsr swap
lda.z newbuffer
sta.z tempbuffer
lda.z newbuffer+1
sta.z tempbuffer+1
lda.z tempbuffer
sta.z newbuffer
lda.z tempbuffer+1
sta.z newbuffer+1
// swap()
jsr swap
// }
rts
}
print: {
// (char)tempbuffer&0x0f
lda.z tempbuffer_1
and #$f
// screen[0] = hextab[(char)tempbuffer&0x0f]
tay
lda hextab,y
ldy #0
sta (screen),y
// (char)newbuffer&0x0f
lda.z newbuffer_1
and #$f
// screen[2] = hextab[(char)newbuffer&0x0f]
tay
lda hextab,y
ldy #2
sta (screen),y
// (char)oldbuffer&0x0f
lda.z oldbuffer
and #$f
// screen[4] = hextab[(char)oldbuffer&0x0f]
tay
lda hextab,y
ldy #4
sta (screen),y
// screen += 40
lda #$28
clc
adc.z screen
sta.z screen
bcc !+
inc.z screen+1
!:
// }
rts
}
swap: {
lda.z tempbuffer
sta.z tempbuffer_1
lda.z tempbuffer+1
sta.z tempbuffer_1+1
lda.z newbuffer
sta.z newbuffer_1
lda.z newbuffer+1
sta.z newbuffer_1+1
lda.z tempbuffer
sta.z oldbuffer
lda.z tempbuffer+1
sta.z oldbuffer+1
// print()
jsr print
// }
rts
}
.segment Data
buffer1: .fill $a, 0
buffer2: .fill $a, 0
hextab: .text "0123456789abcdef"

View File

@ -0,0 +1,57 @@
void main()
main: scope:[main] from
[0] phi()
[1] call print
to:main::@1
main::@1: scope:[main] from main
[2] phi()
[3] call swap
to:main::@2
main::@2: scope:[main] from main::@1
[4] tempbuffer#22 = newbuffer#0
[5] newbuffer#23 = tempbuffer#0
[6] call swap
to:main::@3
main::@3: scope:[main] from main::@2
[7] tempbuffer#23 = newbuffer#0
[8] newbuffer#24 = tempbuffer#0
[9] call swap
to:main::@return
main::@return: scope:[main] from main::@3
[10] return
to:@return
void print()
print: scope:[print] from main swap
[11] oldbuffer#9 = phi( main/buffer2, swap/oldbuffer#22 )
[11] newbuffer#9 = phi( main/buffer1, swap/newbuffer#22 )
[11] screen#12 = phi( main/(char *) 1024, swap/screen#0 )
[11] tempbuffer#9 = phi( main/(char *) 0, swap/tempbuffer#21 )
[12] print::$3 = (char)tempbuffer#9
[13] print::$0 = print::$3 & $f
[14] *screen#12 = hextab[print::$0]
[15] print::$4 = (char)newbuffer#9
[16] print::$1 = print::$4 & $f
[17] screen#12[2] = hextab[print::$1]
[18] print::$5 = (char)oldbuffer#9
[19] print::$2 = print::$5 & $f
[20] screen#12[4] = hextab[print::$2]
[21] screen#0 = screen#12 + $28
to:print::@return
print::@return: scope:[print] from print
[22] return
to:@return
void swap()
swap: scope:[swap] from main::@1 main::@2 main::@3
[23] newbuffer#0 = phi( main::@1/buffer2, main::@2/newbuffer#23, main::@3/newbuffer#24 )
[23] tempbuffer#0 = phi( main::@1/buffer1, main::@2/tempbuffer#22, main::@3/tempbuffer#23 )
[24] tempbuffer#21 = tempbuffer#0
[25] newbuffer#22 = newbuffer#0
[26] oldbuffer#22 = tempbuffer#0
[27] call print
to:swap::@return
swap::@return: scope:[swap] from swap
[28] return
to:@return

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,43 @@
__constant char buffer1[$a] = { fill( $a, 0) }
__constant char buffer2[$a] = { fill( $a, 0) }
__constant char hextab[] = "0123456789abcdef"z
void main()
char *newbuffer
char *newbuffer#0 // newbuffer zp[2]:10 2.375
char *newbuffer#22 // newbuffer_1 zp[2]:8 11.0
char *newbuffer#23 // newbuffer zp[2]:10 4.0
char *newbuffer#24 // newbuffer zp[2]:10 4.0
char *newbuffer#9 // newbuffer_1 zp[2]:8 2.75
char *oldbuffer
char *oldbuffer#22 // oldbuffer zp[2]:4 22.0
char *oldbuffer#9 // oldbuffer zp[2]:4 1.5714285714285714
void print()
char print::$0 // reg byte a 202.0
char print::$1 // reg byte a 202.0
char print::$2 // reg byte a 202.0
char print::$3 // reg byte a 202.0
char print::$4 // reg byte a 202.0
char print::$5 // reg byte a 202.0
char *screen
char *screen#0 // screen zp[2]:2 7.0
char *screen#12 // screen zp[2]:2 41.5
void swap()
char *tempbuffer
char *tempbuffer#0 // tempbuffer zp[2]:12 3.0
char *tempbuffer#21 // tempbuffer_1 zp[2]:6 7.333333333333333
char *tempbuffer#22 // tempbuffer zp[2]:12 2.0
char *tempbuffer#23 // tempbuffer zp[2]:12 2.0
char *tempbuffer#9 // tempbuffer_1 zp[2]:6 11.0
zp[2]:6 [ tempbuffer#9 tempbuffer#21 ]
zp[2]:2 [ screen#12 screen#0 ]
zp[2]:8 [ newbuffer#9 newbuffer#22 ]
zp[2]:4 [ oldbuffer#9 oldbuffer#22 ]
zp[2]:12 [ tempbuffer#0 tempbuffer#22 tempbuffer#23 ]
zp[2]:10 [ newbuffer#0 newbuffer#23 newbuffer#24 ]
reg byte a [ print::$3 ]
reg byte a [ print::$0 ]
reg byte a [ print::$4 ]
reg byte a [ print::$1 ]
reg byte a [ print::$5 ]
reg byte a [ print::$2 ]