mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-04-18 21:37:18 +00:00
Added initial support for new CPU's 65C02, 65CE02 and 45GS02.
This commit is contained in:
parent
f62631812e
commit
f221865593
src
main
fragment
cache
wdc65c02-common
java/dk/camelot64/kickc
test
6167
src/main/fragment/cache/fragment-cache-mos6502x.asm
vendored
6167
src/main/fragment/cache/fragment-cache-mos6502x.asm
vendored
File diff suppressed because it is too large
Load Diff
67
src/main/fragment/cache/fragment-cache-wdc65c02.asm
vendored
Normal file
67
src/main/fragment/cache/fragment-cache-wdc65c02.asm
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
//KICKC FRAGMENT CACHE 15c356fca7
|
||||
//FRAGMENT vbuz1=_deref_pbuc1
|
||||
lda {c1}
|
||||
sta {z1}
|
||||
//FRAGMENT vbuz1=vbuz2_plus_1
|
||||
lda {z2}
|
||||
inc
|
||||
sta {z1}
|
||||
//FRAGMENT _deref_pbuc1=vbuz1
|
||||
lda {z1}
|
||||
sta {c1}
|
||||
//FRAGMENT vbuaa=_deref_pbuc1
|
||||
lda {c1}
|
||||
//FRAGMENT vbuxx=_deref_pbuc1
|
||||
ldx {c1}
|
||||
//FRAGMENT vbuz1=vbuaa_plus_1
|
||||
inc
|
||||
sta {z1}
|
||||
//FRAGMENT _deref_pbuc1=vbuaa
|
||||
sta {c1}
|
||||
//FRAGMENT vbuz1=vbuxx_plus_1
|
||||
inx
|
||||
stx {z1}
|
||||
//FRAGMENT vbuyy=_deref_pbuc1
|
||||
ldy {c1}
|
||||
//FRAGMENT vbuz1=vbuyy_plus_1
|
||||
iny
|
||||
sty {z1}
|
||||
//FRAGMENT vbuaa=vbuz1_plus_1
|
||||
lda {z1}
|
||||
inc
|
||||
//FRAGMENT vbuaa=vbuaa_plus_1
|
||||
inc
|
||||
//FRAGMENT vbuaa=vbuxx_plus_1
|
||||
txa
|
||||
inc
|
||||
//FRAGMENT vbuaa=vbuyy_plus_1
|
||||
tya
|
||||
inc
|
||||
//FRAGMENT vbuxx=vbuz1_plus_1
|
||||
ldx {z1}
|
||||
inx
|
||||
//FRAGMENT _deref_pbuc1=vbuxx
|
||||
stx {c1}
|
||||
//FRAGMENT vbuxx=vbuaa_plus_1
|
||||
inc
|
||||
tax
|
||||
//FRAGMENT vbuxx=vbuxx_plus_1
|
||||
inx
|
||||
//FRAGMENT vbuxx=vbuyy_plus_1
|
||||
tya
|
||||
inc
|
||||
tax
|
||||
//FRAGMENT vbuyy=vbuz1_plus_1
|
||||
ldy {z1}
|
||||
iny
|
||||
//FRAGMENT _deref_pbuc1=vbuyy
|
||||
sty {c1}
|
||||
//FRAGMENT vbuyy=vbuaa_plus_1
|
||||
inc
|
||||
tay
|
||||
//FRAGMENT vbuyy=vbuxx_plus_1
|
||||
txa
|
||||
inc
|
||||
tay
|
||||
//FRAGMENT vbuyy=vbuyy_plus_1
|
||||
iny
|
1
src/main/fragment/wdc65c02-common/vbuaa=vbuaa_plus_1.asm
Normal file
1
src/main/fragment/wdc65c02-common/vbuaa=vbuaa_plus_1.asm
Normal file
@ -0,0 +1 @@
|
||||
inc
|
2
src/main/fragment/wdc65c02-common/vbuaa=vbuaa_plus_2.asm
Normal file
2
src/main/fragment/wdc65c02-common/vbuaa=vbuaa_plus_2.asm
Normal file
@ -0,0 +1,2 @@
|
||||
inc
|
||||
inc
|
@ -284,6 +284,11 @@ public class AsmInstructionSet {
|
||||
add(0xfd, "sbc", abx, 4.5);
|
||||
add(0xfe, "inc", abx, 7.0);
|
||||
add(0xff, "isc", abx, 7.0);
|
||||
|
||||
// 65c02 instructions
|
||||
// TODO: create instruction set model that knows the different CPU's
|
||||
add(0x1a, "inc", non, 2.0);
|
||||
|
||||
List<String> jumps = Arrays.asList("jmp", "beq", "bne", "bcc", "bcs", "bvs", "bvc", "bmi", "bpl", "jsr");
|
||||
for(AsmInstructionType instruction : instructions) {
|
||||
if(jumps.contains(instruction.getMnemnonic())) {
|
||||
|
44
src/main/java/dk/camelot64/kickc/asm/AsmSetCpu.java
Normal file
44
src/main/java/dk/camelot64/kickc/asm/AsmSetCpu.java
Normal file
@ -0,0 +1,44 @@
|
||||
package dk.camelot64.kickc.asm;
|
||||
|
||||
import dk.camelot64.kickc.model.TargetCpu;
|
||||
|
||||
/** Set the current CPU */
|
||||
public class AsmSetCpu implements AsmLine {
|
||||
|
||||
private final TargetCpu cpu;
|
||||
private int index;
|
||||
|
||||
public AsmSetCpu(TargetCpu cpu) {
|
||||
this.cpu = cpu;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLineBytes() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getLineCycles() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsm() {
|
||||
final String cpuName = cpu.getAsmName();
|
||||
return ".cpu " + cpuName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIndex(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public TargetCpu getCpu() {
|
||||
return cpu;
|
||||
}
|
||||
}
|
@ -223,10 +223,14 @@ public class AsmFragmentInstance {
|
||||
KickCParser.AsmParamModeContext paramModeCtx = ctx.asmParamMode();
|
||||
AsmInstruction instruction;
|
||||
if(paramModeCtx == null) {
|
||||
final String mnemonic = ctx.ASM_MNEMONIC().getText();
|
||||
AsmInstructionType type = AsmInstructionSet.getInstructionType(
|
||||
ctx.ASM_MNEMONIC().getText(),
|
||||
mnemonic,
|
||||
AsmAddressingMode.NON,
|
||||
false);
|
||||
if(type == null) {
|
||||
throw new InternalError("Error in " + name + ".asm line " + ctx.getStart().getLine() + " - Instruction type unknown " + mnemonic + " " + AsmAddressingMode.NON);
|
||||
}
|
||||
instruction = new AsmInstruction(type, null);
|
||||
} else {
|
||||
instruction = (AsmInstruction) this.visit(paramModeCtx);
|
||||
@ -291,14 +295,14 @@ public class AsmFragmentInstance {
|
||||
KickCParser.AsmExprContext exprCtx,
|
||||
AsmAddressingMode addressingMode) {
|
||||
KickCParser.AsmInstructionContext instructionCtx = (KickCParser.AsmInstructionContext) ctx.getParent();
|
||||
String mnemonic = instructionCtx.ASM_MNEMONIC().getSymbol().getText();
|
||||
AsmParameter parameter = (AsmParameter) this.visit(exprCtx);
|
||||
String mnemonic = instructionCtx.ASM_MNEMONIC().getSymbol().getText();
|
||||
AsmInstructionType type = AsmInstructionSet.getInstructionType(
|
||||
mnemonic,
|
||||
addressingMode,
|
||||
parameter.isZp());
|
||||
if(type == null) {
|
||||
throw new InternalError("Error in " + name + ".asm line " + ctx.getStart().getLine() + " - Instruction type unknown " + mnemonic + " " + addressingMode + " " + parameter);
|
||||
throw new InternalError("Error in " + name + ".asm line " + instructionCtx.getStart().getLine() + " - Instruction type unknown " + mnemonic + " " + addressingMode + " " + parameter);
|
||||
}
|
||||
return new AsmInstruction(type, parameter.getParam());
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
package dk.camelot64.kickc.model;
|
||||
|
||||
import kickass._65xx.cpus.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@ -10,32 +12,42 @@ import java.util.List;
|
||||
* */
|
||||
public enum TargetCpu {
|
||||
/** Vanilla MOS 6502 CPU running in ROM - no illegal opcodes, no self-modifying code. */
|
||||
ROM6502("rom6502", Collections.singletonList(Feature.MOS6502_COMMON)),
|
||||
ROM6502("rom6502", CPU_6502NoIllegals.name, Collections.singletonList(Feature.MOS6502_COMMON)),
|
||||
/** MOS 6502 CPU running in ROM - allows illegal instructions, no self-modifying code. */
|
||||
ROM6502X("rom6502x", Arrays.asList(Feature.MOS6502_COMMON, Feature.MOS6502_UNODC)),
|
||||
ROM6502X("rom6502x", CPU_6502WithIllegals.name, Arrays.asList(Feature.MOS6502_COMMON, Feature.MOS6502_UNODC)),
|
||||
/** Vanilla MOS 6502 CPU - no illegal opcodes, allows self-modifying code. */
|
||||
MOS6502("mos6502", Arrays.asList(Feature.MOS6502_COMMON, Feature.MOS6502_SELFMOD)),
|
||||
MOS6502("mos6502", CPU_6502NoIllegals.name, Arrays.asList(Feature.MOS6502_COMMON, Feature.MOS6502_SELFMOD)),
|
||||
/** MOS 6502 CPU - allows illegal instructions, allows self-modifying code. */
|
||||
MOS6502X("mos6502x", Arrays.asList(Feature.MOS6502_COMMON, Feature.MOS6502_UNODC, Feature.MOS6502_SELFMOD)),
|
||||
///** 65C02 CPU - More addressing modes and instructions, no illegal instructions. http://westerndesigncenter.com/wdc/documentation/w65c02s.pdf */
|
||||
//WDC65C02("65C02"),
|
||||
///** 65CE02 CPU - Even more addressing modes and instructions. http://www.zimmers.net/anonftp/pub/cbm/documents/chipdata/65ce02.txt */
|
||||
//MOS65CE02("65CE02"),
|
||||
MOS6502X("mos6502x", CPU_6502WithIllegals.name, Arrays.asList(Feature.MOS6502_COMMON, Feature.MOS6502_UNODC, Feature.MOS6502_SELFMOD)),
|
||||
/** WDC 65C02 CPU - More addressing modes and instructions, no self-modifying code. http://westerndesigncenter.com/wdc/documentation/w65c02s.pdf */
|
||||
WDC65C02("wdc65c02", CPU_65C02.name, Arrays.asList(Feature.MOS6502_COMMON, Feature.WDC65C02_COMMON, Feature.WDC65C02_SPECIFIC)),
|
||||
/** CSG 65CE02 CPU - Even more addressing modes and instructions, no self-modifying code. http://www.zimmers.net/anonftp/pub/cbm/documents/chipdata/65ce02.txt */
|
||||
CSG65CE02("csg65ce02", CPU_65CE02.name, Arrays.asList(Feature.MOS6502_COMMON, Feature.WDC65C02_COMMON, Feature.CSG65CE02_COMMON)),
|
||||
/** 45GS02 CPU - Even more addressing modes and instructions, no self-modifying code. https://github.com/MEGA65/mega65-user-guide/blob/master/MEGA65-Book_draft.pdf */
|
||||
MEGA45GS02("mega45gs02", CPU_45GS02.name, Arrays.asList(Feature.MOS6502_COMMON, Feature.WDC65C02_COMMON, Feature.CSG65CE02_COMMON, Feature.MEGA45GS02_COMMON)),
|
||||
///** 65C186 CPU - 16-bit instructions, 24-bit addressing modes and more instructions. http://www.westerndesigncenter.com/wdc/documentation/w65c816s.pdf */
|
||||
//WDC65C186("65CE02"),
|
||||
//WDC65C186("65C186"),
|
||||
;
|
||||
|
||||
/** The default target CPU */
|
||||
public static final TargetCpu DEFAULT = MOS6502X;
|
||||
|
||||
/** Feature of a CPU. A feature is represented by a folder containing a number of fragments. */
|
||||
/** A feature set of a CPU. The feature set is effectively a subset of the instruction set. In practice a feature is represented by a folder containing a number of fragments using the instructions. */
|
||||
public enum Feature {
|
||||
/** Official Instruction Set of the MOS6502 CPU. https://www.masswerk.at/6502/6502_instruction_set.html */
|
||||
/** Official Instruction Set of the MOS 6502 CPU, which is also present on descendants. https://www.masswerk.at/6502/6502_instruction_set.html */
|
||||
MOS6502_COMMON("mos6502-common"),
|
||||
/** The Undocumented Opcodes of the MOS6502 CPU. http://www.oxyron.de/html/opcodes02.html */
|
||||
/** The Undocumented Opcodes of the MOS 6502 CPU, not present on descendant CPU's. http://www.oxyron.de/html/opcodes02.html */
|
||||
MOS6502_UNODC("mos6502-undoc"),
|
||||
/** Self-modifying Code using MOS6502 instructions. */
|
||||
/** Self-modifying Code using MOS 6502 instructions, not usable in ROM. */
|
||||
MOS6502_SELFMOD("mos6502-selfmod"),
|
||||
/** Added instructions of the WDC 65C02 CPU that are also present on the descendants 65CE02 and 45GS02. https://eater.net/datasheets/w65c02s.pdf */
|
||||
WDC65C02_COMMON("wdc65c02-common"),
|
||||
/** Instructions and features of the WDC 65C02 CPU that are not present on the descendants 65CE02 and 45GS02 (such as assuming that Z is always zero). https://eater.net/datasheets/w65c02s.pdf */
|
||||
WDC65C02_SPECIFIC("wdc65c02-specific"),
|
||||
/** Added instructions of the CSG 65CE02 CPU that are also present on the descendant 45GS02. http://archive.6502.org/datasheets/mos_65ce02_mpu.pdf */
|
||||
CSG65CE02_COMMON("csg65ce02-common"),
|
||||
/** Added instructions of the MEGA 45GS02 CPU. https://github.com/MEGA65/mega65-user-guide/blob/master/MEGA65-Book_draft.pdf */
|
||||
MEGA45GS02_COMMON("mega45gs02-common"),
|
||||
;
|
||||
|
||||
/** The CPU feature name. */
|
||||
@ -53,11 +65,15 @@ public enum TargetCpu {
|
||||
/** The name of the CPU. */
|
||||
private String name;
|
||||
|
||||
/** The CPU name used by KickAsm */
|
||||
private String asmName;
|
||||
|
||||
/** Features of the CPU */
|
||||
private List<Feature> features;
|
||||
|
||||
TargetCpu(String name, List<Feature> features) {
|
||||
TargetCpu(String name, String asmName, List<Feature> features) {
|
||||
this.name = name;
|
||||
this.asmName = asmName;
|
||||
this.features = features;
|
||||
}
|
||||
|
||||
@ -65,6 +81,14 @@ public enum TargetCpu {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name used by KickAsm
|
||||
* @return The CPU name used by KickAsm
|
||||
*/
|
||||
public String getAsmName() {
|
||||
return asmName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the features of the CPU deciding which fragments is usable
|
||||
* @return The features
|
||||
|
@ -81,6 +81,12 @@ public class Pass4CodeGeneration {
|
||||
generateComments(asm, program.getFileComments());
|
||||
asm.startChunk(currentScope, null, "Upstart");
|
||||
final TargetPlatform targetPlatform = program.getTargetPlatform();
|
||||
|
||||
// Add Target CPU - if it is not the default
|
||||
final TargetCpu targetCpu = program.getTargetCpu();
|
||||
if(!targetCpu.equals(TargetCpu.DEFAULT))
|
||||
asm.addLine(new AsmSetCpu(targetCpu));
|
||||
|
||||
String linkScriptBody = targetPlatform.getLinkScriptBody();
|
||||
String outputFileName = new File(program.getPrimaryFileName()).getName() + "." + program.getTargetPlatform().getOutFileExtension();
|
||||
linkScriptBody = linkScriptBody.replace("%O", outputFileName);
|
||||
|
@ -34,7 +34,7 @@ public class Pass5DoubleJumpElimination extends Pass5AsmOptimization {
|
||||
currentLabel = ((AsmLabel) line).getLabel();
|
||||
} else if(line instanceof AsmComment || line instanceof AsmConstant || line instanceof AsmLabelDecl) {
|
||||
// ignore
|
||||
} else if(line instanceof AsmBasicUpstart || line instanceof AsmDataNumeric || line instanceof AsmDataFill || line instanceof AsmDataString || line instanceof AsmDataAlignment || line instanceof AsmSetPc || line instanceof AsmInlineKickAsm|| line instanceof AsmSetEncoding|| line instanceof AsmDataKickAsm|| line instanceof AsmSegmentDef|| line instanceof AsmSegment|| line instanceof AsmFile) {
|
||||
} else if(line instanceof AsmBasicUpstart || line instanceof AsmDataNumeric || line instanceof AsmDataFill || line instanceof AsmDataString || line instanceof AsmDataAlignment || line instanceof AsmSetPc || line instanceof AsmInlineKickAsm|| line instanceof AsmSetEncoding|| line instanceof AsmSetCpu|| line instanceof AsmDataKickAsm|| line instanceof AsmSegmentDef|| line instanceof AsmSegment|| line instanceof AsmFile) {
|
||||
currentLabel = null;
|
||||
} else if(line instanceof AsmInstruction) {
|
||||
if(currentLabel != null) {
|
||||
|
@ -42,11 +42,6 @@ public class TestPrograms {
|
||||
public TestPrograms() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMega65C65ce02() throws IOException, URISyntaxException {
|
||||
compileAndCompare("mega65-c65ce02.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCastingNegative() throws IOException, URISyntaxException {
|
||||
compileAndCompare("casting-negative.c");
|
||||
@ -949,6 +944,16 @@ public class TestPrograms {
|
||||
}
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testMega65C65ce02() throws IOException, URISyntaxException {
|
||||
compileAndCompare("cpu-45gs02.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCpu65C02() throws IOException, URISyntaxException {
|
||||
compileAndCompare("cpu-65c02.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCpu6502() throws IOException, URISyntaxException {
|
||||
compileAndCompare("cpu-6502.c");
|
||||
|
@ -1,8 +1,9 @@
|
||||
// Tests compiling inline C65CE02 Assembler
|
||||
// Tests compiling inline C65CE02/45GS02 Assembler
|
||||
|
||||
#pragma cpu(MEGA45GS02)
|
||||
|
||||
void main() {
|
||||
kickasm {{
|
||||
.cpu _45gs02
|
||||
ldz #2
|
||||
stz $0800
|
||||
adcq ($2)
|
11
src/test/kc/cpu-65c02.c
Normal file
11
src/test/kc/cpu-65c02.c
Normal file
@ -0,0 +1,11 @@
|
||||
// Test the 65C02 CPU
|
||||
// A program that uses 65C02 instructions
|
||||
|
||||
#pragma cpu(WDC65C02)
|
||||
|
||||
char* const SCREEN = 0x0400;
|
||||
|
||||
void main() {
|
||||
char a = SCREEN[0];
|
||||
SCREEN[1] = a+1;
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
// Tests compiling inline C65CE02 Assembler
|
||||
// Tests compiling inline C65CE02/45GS02 Assembler
|
||||
.cpu _45gs02
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
main: {
|
||||
// kickasm
|
||||
.cpu _45gs02
|
||||
ldz #2
|
||||
ldz #2
|
||||
stz $0800
|
||||
adcq ($2)
|
||||
|
@ -1,8 +1,7 @@
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from
|
||||
kickasm() {{ .cpu _45gs02
|
||||
ldz #2
|
||||
kickasm() {{ ldz #2
|
||||
stz $0800
|
||||
adcq ($2)
|
||||
}}
|
@ -3,8 +3,7 @@ CONTROL FLOW GRAPH SSA
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from __start
|
||||
kickasm() {{ .cpu _45gs02
|
||||
ldz #2
|
||||
kickasm() {{ ldz #2
|
||||
stz $0800
|
||||
adcq ($2)
|
||||
}}
|
||||
@ -44,8 +43,7 @@ FINAL CONTROL FLOW GRAPH
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from
|
||||
kickasm() {{ .cpu _45gs02
|
||||
ldz #2
|
||||
kickasm() {{ ldz #2
|
||||
stz $0800
|
||||
adcq ($2)
|
||||
}}
|
||||
@ -62,19 +60,19 @@ Initial phi equivalence classes
|
||||
Complete equivalence classes
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
Target platform is c64basic / MEGA45GS02
|
||||
// File Comments
|
||||
// Tests compiling inline C65CE02 Assembler
|
||||
// Tests compiling inline C65CE02/45GS02 Assembler
|
||||
// Upstart
|
||||
.cpu _45gs02
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
// main
|
||||
main: {
|
||||
// kickasm() {{ .cpu _45gs02 ldz #2 stz $0800 adcq ($2) }}
|
||||
.cpu _45gs02
|
||||
ldz #2
|
||||
// kickasm() {{ ldz #2 stz $0800 adcq ($2) }}
|
||||
ldz #2
|
||||
stz $0800
|
||||
adcq ($2)
|
||||
|
||||
@ -97,17 +95,17 @@ Uplifting [] best 265 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Tests compiling inline C65CE02 Assembler
|
||||
// Tests compiling inline C65CE02/45GS02 Assembler
|
||||
// Upstart
|
||||
.cpu _45gs02
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
// main
|
||||
main: {
|
||||
// kickasm() {{ .cpu _45gs02 ldz #2 stz $0800 adcq ($2) }}
|
||||
.cpu _45gs02
|
||||
ldz #2
|
||||
// kickasm() {{ ldz #2 stz $0800 adcq ($2) }}
|
||||
ldz #2
|
||||
stz $0800
|
||||
adcq ($2)
|
||||
|
||||
@ -135,8 +133,9 @@ FINAL ASSEMBLER
|
||||
Score: 262
|
||||
|
||||
// File Comments
|
||||
// Tests compiling inline C65CE02 Assembler
|
||||
// Tests compiling inline C65CE02/45GS02 Assembler
|
||||
// Upstart
|
||||
.cpu _45gs02
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
@ -144,9 +143,8 @@ Score: 262
|
||||
// main
|
||||
main: {
|
||||
// kickasm
|
||||
// kickasm() {{ .cpu _45gs02 ldz #2 stz $0800 adcq ($2) }}
|
||||
.cpu _45gs02
|
||||
ldz #2
|
||||
// kickasm() {{ ldz #2 stz $0800 adcq ($2) }}
|
||||
ldz #2
|
||||
stz $0800
|
||||
adcq ($2)
|
||||
|
@ -1,5 +1,6 @@
|
||||
// Test the 6502 CPU without support for illegal opcodes
|
||||
// By a program that normally uses illegal opcodes
|
||||
.cpu _6502NoIllegals
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
|
@ -162,6 +162,7 @@ Target platform is c64basic / MOS6502
|
||||
// Test the 6502 CPU without support for illegal opcodes
|
||||
// By a program that normally uses illegal opcodes
|
||||
// Upstart
|
||||
.cpu _6502NoIllegals
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
@ -249,6 +250,7 @@ ASSEMBLER BEFORE OPTIMIZATION
|
||||
// Test the 6502 CPU without support for illegal opcodes
|
||||
// By a program that normally uses illegal opcodes
|
||||
// Upstart
|
||||
.cpu _6502NoIllegals
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
@ -348,6 +350,7 @@ Score: 356
|
||||
// Test the 6502 CPU without support for illegal opcodes
|
||||
// By a program that normally uses illegal opcodes
|
||||
// Upstart
|
||||
.cpu _6502NoIllegals
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
|
17
src/test/ref/cpu-65c02.asm
Normal file
17
src/test/ref/cpu-65c02.asm
Normal file
@ -0,0 +1,17 @@
|
||||
// Test the 65C02 CPU
|
||||
// A program that uses 65C02 instructions
|
||||
.cpu _65c02
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
main: {
|
||||
// a = SCREEN[0]
|
||||
lda SCREEN
|
||||
// a+1
|
||||
inc
|
||||
// SCREEN[1] = a+1
|
||||
sta SCREEN+1
|
||||
// }
|
||||
rts
|
||||
}
|
10
src/test/ref/cpu-65c02.cfg
Normal file
10
src/test/ref/cpu-65c02.cfg
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from
|
||||
[0] (byte) main::a#0 ← *((const nomodify byte*) SCREEN)
|
||||
[1] (byte~) main::$0 ← (byte) main::a#0 + (byte) 1
|
||||
[2] *((const nomodify byte*) SCREEN+(byte) 1) ← (byte~) main::$0
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[3] return
|
||||
to:@return
|
212
src/test/ref/cpu-65c02.log
Normal file
212
src/test/ref/cpu-65c02.log
Normal file
@ -0,0 +1,212 @@
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from __start
|
||||
(byte) main::a#0 ← *((const nomodify byte*) SCREEN + (number) 0)
|
||||
(number~) main::$0 ← (byte) main::a#0 + (number) 1
|
||||
*((const nomodify byte*) SCREEN + (number) 1) ← (number~) main::$0
|
||||
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
|
||||
(const nomodify byte*) SCREEN = (byte*)(number) $400
|
||||
(void()) __start()
|
||||
(label) __start::@1
|
||||
(label) __start::@return
|
||||
(void()) main()
|
||||
(number~) main::$0
|
||||
(label) main::@return
|
||||
(byte) main::a
|
||||
(byte) main::a#0
|
||||
|
||||
Adding number conversion cast (unumber) 0 in (byte) main::a#0 ← *((const nomodify byte*) SCREEN + (number) 0)
|
||||
Adding number conversion cast (unumber) 1 in (number~) main::$0 ← (byte) main::a#0 + (number) 1
|
||||
Adding number conversion cast (unumber) main::$0 in (number~) main::$0 ← (byte) main::a#0 + (unumber)(number) 1
|
||||
Adding number conversion cast (unumber) 1 in *((const nomodify byte*) SCREEN + (number) 1) ← (unumber~) main::$0
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 1
|
||||
Simplifying constant integer cast 1
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 1
|
||||
Finalized unsigned number type (byte) 1
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Inferred type updated to byte in (unumber~) main::$0 ← (byte) main::a#0 + (byte) 1
|
||||
Simplifying expression containing zero SCREEN in [0] (byte) main::a#0 ← *((const nomodify byte*) SCREEN + (byte) 0)
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
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
|
||||
Consolidated array index constant in *(SCREEN+1)
|
||||
Successful SSA optimization Pass2ConstantAdditionElimination
|
||||
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
|
||||
[0] (byte) main::a#0 ← *((const nomodify byte*) SCREEN)
|
||||
[1] (byte~) main::$0 ← (byte) main::a#0 + (byte) 1
|
||||
[2] *((const nomodify byte*) SCREEN+(byte) 1) ← (byte~) main::$0
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[3] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(void()) main()
|
||||
(byte~) main::$0 4.0
|
||||
(byte) main::a
|
||||
(byte) main::a#0 4.0
|
||||
|
||||
Initial phi equivalence classes
|
||||
Added variable main::a#0 to live range equivalence class [ main::a#0 ]
|
||||
Added variable main::$0 to live range equivalence class [ main::$0 ]
|
||||
Complete equivalence classes
|
||||
[ main::a#0 ]
|
||||
[ main::$0 ]
|
||||
Allocated zp[1]:2 [ main::a#0 ]
|
||||
Allocated zp[1]:3 [ main::$0 ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / WDC65C02
|
||||
// File Comments
|
||||
// Test the 65C02 CPU
|
||||
// A program that uses 65C02 instructions
|
||||
// Upstart
|
||||
.cpu _65c02
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
// main
|
||||
main: {
|
||||
.label __0 = 3
|
||||
.label a = 2
|
||||
// [0] (byte) main::a#0 ← *((const nomodify byte*) SCREEN) -- vbuz1=_deref_pbuc1
|
||||
lda SCREEN
|
||||
sta.z a
|
||||
// [1] (byte~) main::$0 ← (byte) main::a#0 + (byte) 1 -- vbuz1=vbuz2_plus_1
|
||||
lda.z a
|
||||
inc
|
||||
sta.z __0
|
||||
// [2] *((const nomodify byte*) SCREEN+(byte) 1) ← (byte~) main::$0 -- _deref_pbuc1=vbuz1
|
||||
lda.z __0
|
||||
sta SCREEN+1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [3] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Potential registers zp[1]:2 [ main::a#0 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp[1]:3 [ main::$0 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main] 4: zp[1]:2 [ main::a#0 ] 4: zp[1]:3 [ main::$0 ]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 19 combination reg byte a [ main::a#0 ] reg byte a [ main::$0 ]
|
||||
Uplifting [] best 19 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test the 65C02 CPU
|
||||
// A program that uses 65C02 instructions
|
||||
// Upstart
|
||||
.cpu _65c02
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
// main
|
||||
main: {
|
||||
// [0] (byte) main::a#0 ← *((const nomodify byte*) SCREEN) -- vbuaa=_deref_pbuc1
|
||||
lda SCREEN
|
||||
// [1] (byte~) main::$0 ← (byte) main::a#0 + (byte) 1 -- vbuaa=vbuaa_plus_1
|
||||
inc
|
||||
// [2] *((const nomodify byte*) SCREEN+(byte) 1) ← (byte~) main::$0 -- _deref_pbuc1=vbuaa
|
||||
sta SCREEN+1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [3] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction __breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(const nomodify byte*) SCREEN = (byte*) 1024
|
||||
(void()) main()
|
||||
(byte~) main::$0 reg byte a 4.0
|
||||
(label) main::@return
|
||||
(byte) main::a
|
||||
(byte) main::a#0 reg byte a 4.0
|
||||
|
||||
reg byte a [ main::a#0 ]
|
||||
reg byte a [ main::$0 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 16
|
||||
|
||||
// File Comments
|
||||
// Test the 65C02 CPU
|
||||
// A program that uses 65C02 instructions
|
||||
// Upstart
|
||||
.cpu _65c02
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
// main
|
||||
main: {
|
||||
// a = SCREEN[0]
|
||||
// [0] (byte) main::a#0 ← *((const nomodify byte*) SCREEN) -- vbuaa=_deref_pbuc1
|
||||
lda SCREEN
|
||||
// a+1
|
||||
// [1] (byte~) main::$0 ← (byte) main::a#0 + (byte) 1 -- vbuaa=vbuaa_plus_1
|
||||
inc
|
||||
// SCREEN[1] = a+1
|
||||
// [2] *((const nomodify byte*) SCREEN+(byte) 1) ← (byte~) main::$0 -- _deref_pbuc1=vbuaa
|
||||
sta SCREEN+1
|
||||
// main::@return
|
||||
// }
|
||||
// [3] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
9
src/test/ref/cpu-65c02.sym
Normal file
9
src/test/ref/cpu-65c02.sym
Normal file
@ -0,0 +1,9 @@
|
||||
(const nomodify byte*) SCREEN = (byte*) 1024
|
||||
(void()) main()
|
||||
(byte~) main::$0 reg byte a 4.0
|
||||
(label) main::@return
|
||||
(byte) main::a
|
||||
(byte) main::a#0 reg byte a 4.0
|
||||
|
||||
reg byte a [ main::a#0 ]
|
||||
reg byte a [ main::$0 ]
|
Loading…
x
Reference in New Issue
Block a user