mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-04-07 06:37:31 +00:00
Fixed relative labels in KickAss 5.9 #272
ASM now uses literal encoded chars for better readability #245
This commit is contained in:
parent
21e4638857
commit
19c0637f1e
@ -7,9 +7,10 @@ import dk.camelot64.kickc.model.symbols.ConstantVar;
|
||||
import dk.camelot64.kickc.model.symbols.Procedure;
|
||||
import dk.camelot64.kickc.model.symbols.Symbol;
|
||||
import dk.camelot64.kickc.model.symbols.Variable;
|
||||
import dk.camelot64.kickc.model.types.*;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeInference;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
||||
import dk.camelot64.kickc.model.values.*;
|
||||
import kickass.nonasm.c64.CharToPetsciiConverter;
|
||||
|
||||
/** Formatting of numbers, constants, names and more for KickAssembler */
|
||||
public class AsmFormat {
|
||||
@ -32,29 +33,14 @@ public class AsmFormat {
|
||||
} else if(value instanceof ConstantBool) {
|
||||
return getAsmBool(((ConstantBool) value).getBool());
|
||||
} else if(value instanceof ConstantChar) {
|
||||
ConstantChar constantChar = (ConstantChar) value;
|
||||
if(!ConstantString.Encoding.SCREENCODE_MIXED.equals(constantChar.getEncoding())) {
|
||||
// Current KickAsm does not support encoded literal chars
|
||||
// Manually convert literal chars in non-standard encodings
|
||||
CharToPetsciiConverter.setCurrentEncoding(constantChar.getEncoding().name);
|
||||
byte converted = CharToPetsciiConverter.convertOrChar(constantChar.getChar(), true);
|
||||
return getAsmNumber(new Long(converted));
|
||||
} else {
|
||||
String escapedChar = ConstantChar.asciiToCharEscape(((ConstantChar) value).getChar());
|
||||
if(escapedChar.length()>1) {
|
||||
// Currently KickAss does not support escaped characters - so instead we must output the number value instead
|
||||
CharToPetsciiConverter.setCurrentEncoding(constantChar.getEncoding().name);
|
||||
byte converted = CharToPetsciiConverter.convertOrChar(constantChar.getChar(), true);
|
||||
return getAsmNumber(new Long(converted));
|
||||
} else {
|
||||
return "'" + escapedChar + "'";
|
||||
}
|
||||
}
|
||||
ConstantChar constantChar = (ConstantChar) value;
|
||||
String escapedChar = ConstantChar.asciiToCharEscape(constantChar.getChar());
|
||||
return "'" + escapedChar + "'";
|
||||
} else if(value instanceof ConstantString) {
|
||||
String stringValue = ((ConstantString) value).getValue();
|
||||
String escapedString = ConstantString.asciiToStringEscape(stringValue);
|
||||
boolean hasEscape = !stringValue.equals(escapedString);
|
||||
return (hasEscape?"@":"")+"\"" + escapedString + "\"";
|
||||
return (hasEscape ? "@" : "") + "\"" + escapedString + "\"";
|
||||
} else if(value instanceof ConstantUnary) {
|
||||
ConstantUnary unary = (ConstantUnary) value;
|
||||
Operator operator = unary.getOperator();
|
||||
@ -151,15 +137,15 @@ public class AsmFormat {
|
||||
return getAsmConstant(program, operand, outerPrecedence, codeScope);
|
||||
}
|
||||
ConstantLiteral constantLiteral = operand.calculateLiteral(program.getScope());
|
||||
if(constantLiteral instanceof ConstantInteger && Operators.CAST_WORD.equals(operator)&& SymbolType.WORD.contains(((ConstantInteger) constantLiteral).getValue())) {
|
||||
if(constantLiteral instanceof ConstantInteger && Operators.CAST_WORD.equals(operator) && SymbolType.WORD.contains(((ConstantInteger) constantLiteral).getValue())) {
|
||||
// No cast needed
|
||||
return getAsmConstant(program, operand, outerPrecedence, codeScope);
|
||||
}
|
||||
if(constantLiteral instanceof ConstantInteger && Operators.CAST_SWORD.equals(operator)&& SymbolType.SWORD.contains(((ConstantInteger) constantLiteral).getValue())) {
|
||||
if(constantLiteral instanceof ConstantInteger && Operators.CAST_SWORD.equals(operator) && SymbolType.SWORD.contains(((ConstantInteger) constantLiteral).getValue())) {
|
||||
// No cast needed
|
||||
return getAsmConstant(program, operand, outerPrecedence, codeScope);
|
||||
}
|
||||
if(constantLiteral instanceof ConstantInteger && (operator instanceof OperatorCastPtr) && SymbolType.WORD.contains(((ConstantInteger) constantLiteral).getValue())) {
|
||||
if(constantLiteral instanceof ConstantInteger && (operator instanceof OperatorCastPtr) && SymbolType.WORD.contains(((ConstantInteger) constantLiteral).getValue())) {
|
||||
// No cast needed
|
||||
return getAsmConstant(program, operand, outerPrecedence, codeScope);
|
||||
}
|
||||
@ -172,11 +158,11 @@ public class AsmFormat {
|
||||
return getAsmConstant(program, operand, outerPrecedence, codeScope);
|
||||
}
|
||||
ConstantLiteral constantLiteral = operand.calculateLiteral(program.getScope());
|
||||
if(constantLiteral instanceof ConstantInteger && Operators.CAST_DWORD.equals(operator)&& SymbolType.DWORD.contains(((ConstantInteger) constantLiteral).getValue())) {
|
||||
if(constantLiteral instanceof ConstantInteger && Operators.CAST_DWORD.equals(operator) && SymbolType.DWORD.contains(((ConstantInteger) constantLiteral).getValue())) {
|
||||
// No cast needed
|
||||
return getAsmConstant(program, operand, outerPrecedence, codeScope);
|
||||
}
|
||||
if(constantLiteral instanceof ConstantInteger && Operators.CAST_SDWORD.equals(operator)&& SymbolType.SDWORD.contains(((ConstantInteger) constantLiteral).getValue())) {
|
||||
if(constantLiteral instanceof ConstantInteger && Operators.CAST_SDWORD.equals(operator) && SymbolType.SDWORD.contains(((ConstantInteger) constantLiteral).getValue())) {
|
||||
// No cast needed
|
||||
return getAsmConstant(program, operand, outerPrecedence, codeScope);
|
||||
}
|
||||
@ -251,8 +237,8 @@ public class AsmFormat {
|
||||
if(number.longValue() >= 0L && number.longValue() <= 255L) {
|
||||
return SHORT_ASM_NUMBERS[number.intValue()];
|
||||
} else {
|
||||
if(number.longValue()<0) {
|
||||
return "-"+getAsmNumber(-number.longValue());
|
||||
if(number.longValue() < 0) {
|
||||
return "-" + getAsmNumber(-number.longValue());
|
||||
} else {
|
||||
return String.format("$%x", number.longValue());
|
||||
}
|
||||
|
@ -273,9 +273,16 @@ public class AsmFragmentInstance {
|
||||
public AsmParameter visitAsmExprBinary(KickCParser.AsmExprBinaryContext ctx) {
|
||||
AsmParameter left = (AsmParameter) this.visit(ctx.asmExpr(0));
|
||||
AsmParameter right = (AsmParameter) this.visit(ctx.asmExpr(1));
|
||||
String param = "" + left.getParam() + ctx.getChild(1).getText() + right.getParam();
|
||||
StringBuilder param = new StringBuilder();
|
||||
param.append(left.getParam());
|
||||
if(ctx.asmExpr(0) instanceof KickCParser.AsmExprLabelRelContext) {
|
||||
// Add an extra space if we are doing a binary expression with a relative label as the left part
|
||||
param.append(" ");
|
||||
}
|
||||
param.append(ctx.getChild(1).getText());
|
||||
param.append(right.getParam());
|
||||
boolean zp = left.isZp() && right.isZp();
|
||||
return new AsmParameter(param, zp);
|
||||
return new AsmParameter(param.toString(), zp);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -242,6 +242,7 @@ public class ProgramValueIterator {
|
||||
value instanceof ConstantLiteral ||
|
||||
value instanceof ConstantRef ||
|
||||
value instanceof StructZero ||
|
||||
value instanceof Label ||
|
||||
value instanceof LabelRef
|
||||
) {
|
||||
// No sub values
|
||||
|
@ -672,6 +672,7 @@ public class Pass4CodeGeneration {
|
||||
}
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
AsmFragmentInstanceSpecFactory asmFragmentInstanceSpecFactory = new AsmFragmentInstanceSpecFactory(assignment, assignmentAlu, program);
|
||||
ensureEncoding(asm, asmFragmentInstanceSpecFactory);
|
||||
generateAsm(asm, asmFragmentInstanceSpecFactory);
|
||||
aluState.clear();
|
||||
return;
|
||||
@ -703,6 +704,7 @@ public class Pass4CodeGeneration {
|
||||
}
|
||||
} else if(statement instanceof StatementConditionalJump) {
|
||||
AsmFragmentInstanceSpecFactory asmFragmentInstanceSpecFactory = new AsmFragmentInstanceSpecFactory((StatementConditionalJump) statement, block, program, getGraph());
|
||||
ensureEncoding(asm, asmFragmentInstanceSpecFactory);
|
||||
generateAsm(asm, asmFragmentInstanceSpecFactory);
|
||||
} else if(statement instanceof StatementCall) {
|
||||
StatementCall call = (StatementCall) statement;
|
||||
@ -981,6 +983,7 @@ public class Pass4CodeGeneration {
|
||||
asm.getCurrentChunk().setFragment("register_copy");
|
||||
} else {
|
||||
AsmFragmentInstanceSpecFactory asmFragmentInstanceSpecFactory = new AsmFragmentInstanceSpecFactory(lValue, rValue, program, scope);
|
||||
ensureEncoding(asm, asmFragmentInstanceSpecFactory);
|
||||
generateAsm(asm, asmFragmentInstanceSpecFactory);
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,11 @@ public class TestPrograms {
|
||||
assertError("string-escapes-err-0", "Unfinished string escape sequence at end of string");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringEscapes3() throws IOException, URISyntaxException {
|
||||
compileAndCompare("string-escapes-3");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringEscapes2() throws IOException, URISyntaxException {
|
||||
compileAndCompare("string-escapes-2");
|
||||
|
26
src/test/kc/string-escapes-3.kc
Normal file
26
src/test/kc/string-escapes-3.kc
Normal file
@ -0,0 +1,26 @@
|
||||
// Test using some simple supported string escape \n in both string and char
|
||||
// Uses encoding PETSCII mixed
|
||||
|
||||
#pragma encoding(petscii_mixed)
|
||||
|
||||
char[] MESSAGE = "hello\nworld";
|
||||
char* SCREEN = 0x0400;
|
||||
|
||||
void main() {
|
||||
byte* line = 0x0400;
|
||||
byte* cursor = line;
|
||||
byte* msg = MESSAGE;
|
||||
|
||||
while(*msg) {
|
||||
switch(*msg) {
|
||||
case '\n':
|
||||
line += 0x28;
|
||||
cursor = line;
|
||||
break;
|
||||
default:
|
||||
*cursor++ = *msg & 0x3f;
|
||||
}
|
||||
msg++;
|
||||
}
|
||||
|
||||
}
|
@ -1032,10 +1032,10 @@ processChars: {
|
||||
ldx #' '
|
||||
ldy #OFFSET_STRUCT_PROCESSINGSPRITE_SCREENPTR
|
||||
lda (processing),y
|
||||
sta !++1
|
||||
sta !+ +1
|
||||
iny
|
||||
lda (processing),y
|
||||
sta !++2
|
||||
sta !+ +2
|
||||
txa
|
||||
!:
|
||||
sta $ffff
|
||||
|
@ -7168,10 +7168,10 @@ processChars: {
|
||||
ldx #' '
|
||||
ldy #OFFSET_STRUCT_PROCESSINGSPRITE_SCREENPTR
|
||||
lda (processing),y
|
||||
sta !++1
|
||||
sta !+ +1
|
||||
iny
|
||||
lda (processing),y
|
||||
sta !++2
|
||||
sta !+ +2
|
||||
txa
|
||||
!:
|
||||
sta $ffff
|
||||
@ -10002,10 +10002,10 @@ processChars: {
|
||||
ldx #' '
|
||||
ldy #OFFSET_STRUCT_PROCESSINGSPRITE_SCREENPTR
|
||||
lda (processing),y
|
||||
sta !++1
|
||||
sta !+ +1
|
||||
iny
|
||||
lda (processing),y
|
||||
sta !++2
|
||||
sta !+ +2
|
||||
txa
|
||||
!:
|
||||
sta $ffff
|
||||
@ -12867,10 +12867,10 @@ processChars: {
|
||||
ldx #' '
|
||||
ldy #OFFSET_STRUCT_PROCESSINGSPRITE_SCREENPTR
|
||||
lda (processing),y
|
||||
sta !++1
|
||||
sta !+ +1
|
||||
iny
|
||||
lda (processing),y
|
||||
sta !++2
|
||||
sta !+ +2
|
||||
txa
|
||||
!:
|
||||
sta $ffff
|
||||
|
@ -3,13 +3,13 @@
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.encoding "petscii_mixed"
|
||||
.const cpm = -$3f
|
||||
.const cpm = 'A'
|
||||
.encoding "petscii_upper"
|
||||
.const cpu = $41
|
||||
.const cpu = 'A'
|
||||
.encoding "screencode_mixed"
|
||||
.const csm = 'A'
|
||||
.encoding "screencode_upper"
|
||||
.const csu = 1
|
||||
.const csu = 'A'
|
||||
.label screen = $400
|
||||
main: {
|
||||
lda #cpm
|
||||
|
@ -253,13 +253,13 @@ Target platform is c64basic
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.encoding "petscii_mixed"
|
||||
.const cpm = -$3f
|
||||
.const cpm = 'A'
|
||||
.encoding "petscii_upper"
|
||||
.const cpu = $41
|
||||
.const cpu = 'A'
|
||||
.encoding "screencode_mixed"
|
||||
.const csm = 'A'
|
||||
.encoding "screencode_upper"
|
||||
.const csu = 1
|
||||
.const csu = 'A'
|
||||
.label screen = $400
|
||||
// @begin
|
||||
bbegin:
|
||||
@ -347,13 +347,13 @@ ASSEMBLER BEFORE OPTIMIZATION
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.encoding "petscii_mixed"
|
||||
.const cpm = -$3f
|
||||
.const cpm = 'A'
|
||||
.encoding "petscii_upper"
|
||||
.const cpu = $41
|
||||
.const cpu = 'A'
|
||||
.encoding "screencode_mixed"
|
||||
.const csm = 'A'
|
||||
.encoding "screencode_upper"
|
||||
.const csu = 1
|
||||
.const csu = 'A'
|
||||
.label screen = $400
|
||||
// @begin
|
||||
bbegin:
|
||||
@ -472,13 +472,13 @@ Score: 62
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.encoding "petscii_mixed"
|
||||
.const cpm = -$3f
|
||||
.const cpm = 'A'
|
||||
.encoding "petscii_upper"
|
||||
.const cpu = $41
|
||||
.const cpu = 'A'
|
||||
.encoding "screencode_mixed"
|
||||
.const csm = 'A'
|
||||
.encoding "screencode_upper"
|
||||
.const csu = 1
|
||||
.const csu = 'A'
|
||||
.label screen = $400
|
||||
// @begin
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
|
@ -3,7 +3,7 @@
|
||||
.pc = $80d "Program"
|
||||
main: {
|
||||
.encoding "petscii_mixed"
|
||||
lda #$45
|
||||
lda #'e'
|
||||
sta strTemp+2
|
||||
lda #0
|
||||
sta strTemp+3
|
||||
|
@ -141,7 +141,7 @@ bend:
|
||||
main: {
|
||||
// [4] *((const byte[]) strTemp#0+(byte) 2) ← (byte) 'e'pm -- _deref_pbuc1=vbuc2
|
||||
.encoding "petscii_mixed"
|
||||
lda #$45
|
||||
lda #'e'
|
||||
sta strTemp+2
|
||||
// [5] *((const byte[]) strTemp#0+(byte) 3) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
@ -202,7 +202,7 @@ bend:
|
||||
main: {
|
||||
// [4] *((const byte[]) strTemp#0+(byte) 2) ← (byte) 'e'pm -- _deref_pbuc1=vbuc2
|
||||
.encoding "petscii_mixed"
|
||||
lda #$45
|
||||
lda #'e'
|
||||
sta strTemp+2
|
||||
// [5] *((const byte[]) strTemp#0+(byte) 3) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
@ -277,7 +277,7 @@ main: {
|
||||
// strTemp[2] = 'e'
|
||||
// [4] *((const byte[]) strTemp#0+(byte) 2) ← (byte) 'e'pm -- _deref_pbuc1=vbuc2
|
||||
.encoding "petscii_mixed"
|
||||
lda #$45
|
||||
lda #'e'
|
||||
sta strTemp+2
|
||||
// strTemp[3] = 0
|
||||
// [5] *((const byte[]) strTemp#0+(byte) 3) ← (byte) 0 -- _deref_pbuc1=vbuc2
|
||||
|
@ -25,7 +25,7 @@ main: {
|
||||
bne b2
|
||||
rts
|
||||
b2:
|
||||
lda #-$33
|
||||
lda #'\n'
|
||||
ldy #0
|
||||
cmp (msg),y
|
||||
beq b3
|
||||
|
@ -293,7 +293,7 @@ main: {
|
||||
// main::@2
|
||||
b2:
|
||||
// [8] if(*((byte*) main::msg#2)==(byte) ' ') goto main::@3 -- _deref_pbuz1_eq_vbuc1_then_la1
|
||||
lda #-$33
|
||||
lda #'\n'
|
||||
ldy #0
|
||||
cmp (msg),y
|
||||
beq b3
|
||||
@ -430,7 +430,7 @@ main: {
|
||||
// main::@2
|
||||
b2:
|
||||
// [8] if(*((byte*) main::msg#2)==(byte) ' ') goto main::@3 -- _deref_pbuz1_eq_vbuc1_then_la1
|
||||
lda #-$33
|
||||
lda #'\n'
|
||||
ldy #0
|
||||
cmp (msg),y
|
||||
beq b3
|
||||
@ -608,7 +608,7 @@ main: {
|
||||
// cursor = line;
|
||||
// break;
|
||||
// [8] if(*((byte*) main::msg#2)==(byte) ' ') goto main::@3 -- _deref_pbuz1_eq_vbuc1_then_la1
|
||||
lda #-$33
|
||||
lda #'\n'
|
||||
ldy #0
|
||||
cmp (msg),y
|
||||
beq b3
|
||||
|
62
src/test/ref/string-escapes-3.asm
Normal file
62
src/test/ref/string-escapes-3.asm
Normal file
@ -0,0 +1,62 @@
|
||||
// Test using some simple supported string escape \n in both string and char
|
||||
// Uses encoding PETSCII mixed
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
main: {
|
||||
.label cursor = 6
|
||||
.label msg = 2
|
||||
.label line = 4
|
||||
lda #<$400
|
||||
sta.z cursor
|
||||
lda #>$400
|
||||
sta.z cursor+1
|
||||
lda #<$400
|
||||
sta.z line
|
||||
lda #>$400
|
||||
sta.z line+1
|
||||
lda #<MESSAGE
|
||||
sta.z msg
|
||||
lda #>MESSAGE
|
||||
sta.z msg+1
|
||||
b1:
|
||||
ldy #0
|
||||
lda (msg),y
|
||||
cmp #0
|
||||
bne b2
|
||||
rts
|
||||
b2:
|
||||
.encoding "petscii_mixed"
|
||||
lda #'\n'
|
||||
ldy #0
|
||||
cmp (msg),y
|
||||
beq b3
|
||||
lda #$3f
|
||||
and (msg),y
|
||||
sta (cursor),y
|
||||
inc.z cursor
|
||||
bne !+
|
||||
inc.z cursor+1
|
||||
!:
|
||||
b5:
|
||||
inc.z msg
|
||||
bne !+
|
||||
inc.z msg+1
|
||||
!:
|
||||
jmp b1
|
||||
b3:
|
||||
lda #$28
|
||||
clc
|
||||
adc.z line
|
||||
sta.z cursor
|
||||
lda #0
|
||||
adc.z line+1
|
||||
sta.z cursor+1
|
||||
lda.z cursor
|
||||
sta.z line
|
||||
lda.z cursor+1
|
||||
sta.z line+1
|
||||
jmp b5
|
||||
}
|
||||
MESSAGE: .text @"hello\nworld"
|
||||
.byte 0
|
39
src/test/ref/string-escapes-3.cfg
Normal file
39
src/test/ref/string-escapes-3.cfg
Normal file
@ -0,0 +1,39 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
main: scope:[main] from @1
|
||||
[4] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@5
|
||||
[5] (byte*) main::cursor#3 ← phi( main/(byte*) 1024 main::@5/(byte*) main::cursor#6 )
|
||||
[5] (byte*) main::line#2 ← phi( main/(byte*) 1024 main::@5/(byte*) main::line#5 )
|
||||
[5] (byte*) main::msg#2 ← phi( main/(const byte[]) MESSAGE#0 main::@5/(byte*) main::msg#1 )
|
||||
[6] if((byte) 0!=*((byte*) main::msg#2)) goto main::@2
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[7] return
|
||||
to:@return
|
||||
main::@2: scope:[main] from main::@1
|
||||
[8] if(*((byte*) main::msg#2)==(byte) '
|
||||
'pm) goto main::@3
|
||||
to:main::@4
|
||||
main::@4: scope:[main] from main::@2
|
||||
[9] (byte~) main::$0 ← *((byte*) main::msg#2) & (byte) $3f
|
||||
[10] *((byte*) main::cursor#3) ← (byte~) main::$0
|
||||
[11] (byte*) main::cursor#2 ← ++ (byte*) main::cursor#3
|
||||
to:main::@5
|
||||
main::@5: scope:[main] from main::@3 main::@4
|
||||
[12] (byte*) main::cursor#6 ← phi( main::@3/(byte*) main::cursor#1 main::@4/(byte*) main::cursor#2 )
|
||||
[12] (byte*) main::line#5 ← phi( main::@3/(byte*~) main::line#8 main::@4/(byte*) main::line#2 )
|
||||
[13] (byte*) main::msg#1 ← ++ (byte*) main::msg#2
|
||||
to:main::@1
|
||||
main::@3: scope:[main] from main::@2
|
||||
[14] (byte*) main::cursor#1 ← (byte*) main::line#2 + (byte) $28
|
||||
[15] (byte*~) main::line#8 ← (byte*) main::cursor#1
|
||||
to:main::@5
|
695
src/test/ref/string-escapes-3.log
Normal file
695
src/test/ref/string-escapes-3.log
Normal file
@ -0,0 +1,695 @@
|
||||
Warning! Adding boolean cast to non-boolean condition *((byte*) main::msg)
|
||||
Identified constant variable (byte*) SCREEN
|
||||
Culled Empty Block (label) main::@9
|
||||
Culled Empty Block (label) main::@3
|
||||
Culled Empty Block (label) main::@10
|
||||
Culled Empty Block (label) main::@11
|
||||
Culled Empty Block (label) main::@12
|
||||
Culled Empty Block (label) main::@7
|
||||
Culled Empty Block (label) main::@8
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
(byte[]) MESSAGE#0 ← (const string) $0
|
||||
to:@1
|
||||
main: scope:[main] from @1
|
||||
(byte*) main::line#0 ← ((byte*)) (number) $400
|
||||
(byte*) main::cursor#0 ← (byte*) main::line#0
|
||||
(byte*) main::msg#0 ← (byte[]) MESSAGE#0
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@6
|
||||
(byte*) main::cursor#5 ← phi( main/(byte*) main::cursor#0 main::@6/(byte*) main::cursor#6 )
|
||||
(byte*) main::line#4 ← phi( main/(byte*) main::line#0 main::@6/(byte*) main::line#5 )
|
||||
(byte*) main::msg#2 ← phi( main/(byte*) main::msg#0 main::@6/(byte*) main::msg#1 )
|
||||
(bool~) main::$1 ← (number) 0 != *((byte*) main::msg#2)
|
||||
if((bool~) main::$1) goto main::@2
|
||||
to:main::@return
|
||||
main::@2: scope:[main] from main::@1
|
||||
(byte*) main::cursor#4 ← phi( main::@1/(byte*) main::cursor#5 )
|
||||
(byte*) main::line#3 ← phi( main::@1/(byte*) main::line#4 )
|
||||
(byte*) main::msg#3 ← phi( main::@1/(byte*) main::msg#2 )
|
||||
if(*((byte*) main::msg#3)==(byte) '
|
||||
'pm) goto main::@4
|
||||
to:main::@5
|
||||
main::@4: scope:[main] from main::@2
|
||||
(byte*) main::msg#6 ← phi( main::@2/(byte*) main::msg#3 )
|
||||
(byte*) main::line#2 ← phi( main::@2/(byte*) main::line#3 )
|
||||
(byte*) main::line#1 ← (byte*) main::line#2 + (number) $28
|
||||
(byte*) main::cursor#1 ← (byte*) main::line#1
|
||||
to:main::@6
|
||||
main::@5: scope:[main] from main::@2
|
||||
(byte*) main::line#6 ← phi( main::@2/(byte*) main::line#3 )
|
||||
(byte*) main::cursor#3 ← phi( main::@2/(byte*) main::cursor#4 )
|
||||
(byte*) main::msg#4 ← phi( main::@2/(byte*) main::msg#3 )
|
||||
(number~) main::$0 ← *((byte*) main::msg#4) & (number) $3f
|
||||
*((byte*) main::cursor#3) ← (number~) main::$0
|
||||
(byte*) main::cursor#2 ← ++ (byte*) main::cursor#3
|
||||
to:main::@6
|
||||
main::@6: scope:[main] from main::@4 main::@5
|
||||
(byte*) main::cursor#6 ← phi( main::@4/(byte*) main::cursor#1 main::@5/(byte*) main::cursor#2 )
|
||||
(byte*) main::line#5 ← phi( main::@4/(byte*) main::line#1 main::@5/(byte*) main::line#6 )
|
||||
(byte*) main::msg#5 ← phi( main::@4/(byte*) main::msg#6 main::@5/(byte*) main::msg#4 )
|
||||
(byte*) main::msg#1 ← ++ (byte*) main::msg#5
|
||||
to:main::@1
|
||||
main::@return: scope:[main] from main::@1
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
call main
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(const string) $0 = (string) "hello
|
||||
world"pm
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte[]) MESSAGE
|
||||
(byte[]) MESSAGE#0
|
||||
(void()) main()
|
||||
(number~) main::$0
|
||||
(bool~) main::$1
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@4
|
||||
(label) main::@5
|
||||
(label) main::@6
|
||||
(label) main::@return
|
||||
(byte*) main::cursor
|
||||
(byte*) main::cursor#0
|
||||
(byte*) main::cursor#1
|
||||
(byte*) main::cursor#2
|
||||
(byte*) main::cursor#3
|
||||
(byte*) main::cursor#4
|
||||
(byte*) main::cursor#5
|
||||
(byte*) main::cursor#6
|
||||
(byte*) main::line
|
||||
(byte*) main::line#0
|
||||
(byte*) main::line#1
|
||||
(byte*) main::line#2
|
||||
(byte*) main::line#3
|
||||
(byte*) main::line#4
|
||||
(byte*) main::line#5
|
||||
(byte*) main::line#6
|
||||
(byte*) main::msg
|
||||
(byte*) main::msg#0
|
||||
(byte*) main::msg#1
|
||||
(byte*) main::msg#2
|
||||
(byte*) main::msg#3
|
||||
(byte*) main::msg#4
|
||||
(byte*) main::msg#5
|
||||
(byte*) main::msg#6
|
||||
|
||||
Adding number conversion cast (unumber) 0 in (bool~) main::$1 ← (number) 0 != *((byte*) main::msg#2)
|
||||
Adding number conversion cast (unumber) $28 in (byte*) main::line#1 ← (byte*) main::line#2 + (number) $28
|
||||
Adding number conversion cast (unumber) $3f in (number~) main::$0 ← *((byte*) main::msg#4) & (number) $3f
|
||||
Adding number conversion cast (unumber) main::$0 in (number~) main::$0 ← *((byte*) main::msg#4) & (unumber)(number) $3f
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast (byte*) main::line#0 ← (byte*)(number) $400
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast $28
|
||||
Simplifying constant integer cast $3f
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) $28
|
||||
Finalized unsigned number type (byte) $3f
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Inferred type updated to byte in (unumber~) main::$0 ← *((byte*) main::msg#4) & (byte) $3f
|
||||
Alias (byte*) main::cursor#0 = (byte*) main::line#0
|
||||
Alias (byte*) main::msg#2 = (byte*) main::msg#3 (byte*) main::msg#6 (byte*) main::msg#4
|
||||
Alias (byte*) main::line#2 = (byte*) main::line#3 (byte*) main::line#4 (byte*) main::line#6
|
||||
Alias (byte*) main::cursor#3 = (byte*) main::cursor#4 (byte*) main::cursor#5
|
||||
Alias (byte*) main::cursor#1 = (byte*) main::line#1
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Alias (byte*) main::msg#2 = (byte*) main::msg#5
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Simple Condition (bool~) main::$1 [6] if((byte) 0!=*((byte*) main::msg#2)) goto main::@2
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Constant (const byte[]) MESSAGE#0 = $0
|
||||
Constant (const byte*) main::cursor#0 = (byte*) 1024
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant (const byte*) main::msg#0 = MESSAGE#0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Inlining constant with var siblings (const byte*) main::cursor#0
|
||||
Inlining constant with var siblings (const byte*) main::msg#0
|
||||
Constant inlined $0 = (const byte[]) MESSAGE#0
|
||||
Constant inlined main::cursor#0 = (byte*) 1024
|
||||
Constant inlined main::msg#0 = (const byte[]) MESSAGE#0
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
CALL GRAPH
|
||||
Calls in [] to main:2
|
||||
|
||||
Created 5 initial phi equivalence classes
|
||||
Coalesced [13] main::line#9 ← main::line#2
|
||||
Coalesced [14] main::cursor#9 ← main::cursor#2
|
||||
Coalesced [17] main::msg#7 ← main::msg#1
|
||||
Coalesced (already) [18] main::line#7 ← main::line#5
|
||||
Coalesced [19] main::cursor#7 ← main::cursor#6
|
||||
Not coalescing [21] main::line#8 ← main::cursor#1
|
||||
Coalesced [22] main::cursor#8 ← main::cursor#1
|
||||
Coalesced down to 3 phi equivalence classes
|
||||
Culled Empty Block (label) @2
|
||||
Renumbering block main::@4 to main::@3
|
||||
Renumbering block main::@5 to main::@4
|
||||
Renumbering block main::@6 to main::@5
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
main: scope:[main] from @1
|
||||
[4] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@5
|
||||
[5] (byte*) main::cursor#3 ← phi( main/(byte*) 1024 main::@5/(byte*) main::cursor#6 )
|
||||
[5] (byte*) main::line#2 ← phi( main/(byte*) 1024 main::@5/(byte*) main::line#5 )
|
||||
[5] (byte*) main::msg#2 ← phi( main/(const byte[]) MESSAGE#0 main::@5/(byte*) main::msg#1 )
|
||||
[6] if((byte) 0!=*((byte*) main::msg#2)) goto main::@2
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[7] return
|
||||
to:@return
|
||||
main::@2: scope:[main] from main::@1
|
||||
[8] if(*((byte*) main::msg#2)==(byte) '
|
||||
'pm) goto main::@3
|
||||
to:main::@4
|
||||
main::@4: scope:[main] from main::@2
|
||||
[9] (byte~) main::$0 ← *((byte*) main::msg#2) & (byte) $3f
|
||||
[10] *((byte*) main::cursor#3) ← (byte~) main::$0
|
||||
[11] (byte*) main::cursor#2 ← ++ (byte*) main::cursor#3
|
||||
to:main::@5
|
||||
main::@5: scope:[main] from main::@3 main::@4
|
||||
[12] (byte*) main::cursor#6 ← phi( main::@3/(byte*) main::cursor#1 main::@4/(byte*) main::cursor#2 )
|
||||
[12] (byte*) main::line#5 ← phi( main::@3/(byte*~) main::line#8 main::@4/(byte*) main::line#2 )
|
||||
[13] (byte*) main::msg#1 ← ++ (byte*) main::msg#2
|
||||
to:main::@1
|
||||
main::@3: scope:[main] from main::@2
|
||||
[14] (byte*) main::cursor#1 ← (byte*) main::line#2 + (byte) $28
|
||||
[15] (byte*~) main::line#8 ← (byte*) main::cursor#1
|
||||
to:main::@5
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte[]) MESSAGE
|
||||
(void()) main()
|
||||
(byte~) main::$0 22.0
|
||||
(byte*) main::cursor
|
||||
(byte*) main::cursor#1 16.5
|
||||
(byte*) main::cursor#2 22.0
|
||||
(byte*) main::cursor#3 6.6000000000000005
|
||||
(byte*) main::cursor#6 16.5
|
||||
(byte*) main::line
|
||||
(byte*) main::line#2 5.5
|
||||
(byte*) main::line#5 16.5
|
||||
(byte*~) main::line#8 22.0
|
||||
(byte*) main::msg
|
||||
(byte*) main::msg#1 22.0
|
||||
(byte*) main::msg#2 6.111111111111112
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ main::msg#2 main::msg#1 ]
|
||||
[ main::line#2 main::line#5 main::line#8 ]
|
||||
[ main::cursor#3 main::cursor#6 main::cursor#1 main::cursor#2 ]
|
||||
Added variable main::$0 to zero page equivalence class [ main::$0 ]
|
||||
Complete equivalence classes
|
||||
[ main::msg#2 main::msg#1 ]
|
||||
[ main::line#2 main::line#5 main::line#8 ]
|
||||
[ main::cursor#3 main::cursor#6 main::cursor#1 main::cursor#2 ]
|
||||
[ main::$0 ]
|
||||
Allocated zp ZP_WORD:2 [ main::msg#2 main::msg#1 ]
|
||||
Allocated zp ZP_WORD:4 [ main::line#2 main::line#5 main::line#8 ]
|
||||
Allocated zp ZP_WORD:6 [ main::cursor#3 main::cursor#6 main::cursor#1 main::cursor#2 ]
|
||||
Allocated zp ZP_BYTE:8 [ main::$0 ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic
|
||||
// File Comments
|
||||
// Test using some simple supported string escape \n in both string and char
|
||||
// Uses encoding PETSCII mixed
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
// @begin
|
||||
bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
// @1
|
||||
b1:
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
main_from_b1:
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
// @end
|
||||
bend:
|
||||
// main
|
||||
main: {
|
||||
.label _0 = 8
|
||||
.label cursor = 6
|
||||
.label msg = 2
|
||||
.label line = 4
|
||||
// [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
// [5] phi (byte*) main::cursor#3 = (byte*) 1024 [phi:main->main::@1#0] -- pbuz1=pbuc1
|
||||
lda #<$400
|
||||
sta.z cursor
|
||||
lda #>$400
|
||||
sta.z cursor+1
|
||||
// [5] phi (byte*) main::line#2 = (byte*) 1024 [phi:main->main::@1#1] -- pbuz1=pbuc1
|
||||
lda #<$400
|
||||
sta.z line
|
||||
lda #>$400
|
||||
sta.z line+1
|
||||
// [5] phi (byte*) main::msg#2 = (const byte[]) MESSAGE#0 [phi:main->main::@1#2] -- pbuz1=pbuc1
|
||||
lda #<MESSAGE
|
||||
sta.z msg
|
||||
lda #>MESSAGE
|
||||
sta.z msg+1
|
||||
jmp b1
|
||||
// main::@1
|
||||
b1:
|
||||
// [6] if((byte) 0!=*((byte*) main::msg#2)) goto main::@2 -- vbuc1_neq__deref_pbuz1_then_la1
|
||||
ldy #0
|
||||
lda (msg),y
|
||||
cmp #0
|
||||
bne b2
|
||||
jmp breturn
|
||||
// main::@return
|
||||
breturn:
|
||||
// [7] return
|
||||
rts
|
||||
// main::@2
|
||||
b2:
|
||||
// [8] if(*((byte*) main::msg#2)==(byte) ' 'pm) goto main::@3 -- _deref_pbuz1_eq_vbuc1_then_la1
|
||||
.encoding "petscii_mixed"
|
||||
lda #'\n'
|
||||
ldy #0
|
||||
cmp (msg),y
|
||||
beq b3
|
||||
jmp b4
|
||||
// main::@4
|
||||
b4:
|
||||
// [9] (byte~) main::$0 ← *((byte*) main::msg#2) & (byte) $3f -- vbuz1=_deref_pbuz2_band_vbuc1
|
||||
lda #$3f
|
||||
ldy #0
|
||||
and (msg),y
|
||||
sta.z _0
|
||||
// [10] *((byte*) main::cursor#3) ← (byte~) main::$0 -- _deref_pbuz1=vbuz2
|
||||
lda.z _0
|
||||
ldy #0
|
||||
sta (cursor),y
|
||||
// [11] (byte*) main::cursor#2 ← ++ (byte*) main::cursor#3 -- pbuz1=_inc_pbuz1
|
||||
inc.z cursor
|
||||
bne !+
|
||||
inc.z cursor+1
|
||||
!:
|
||||
// [12] phi from main::@3 main::@4 to main::@5 [phi:main::@3/main::@4->main::@5]
|
||||
b5_from_b3:
|
||||
b5_from_b4:
|
||||
// [12] phi (byte*) main::cursor#6 = (byte*) main::cursor#1 [phi:main::@3/main::@4->main::@5#0] -- register_copy
|
||||
// [12] phi (byte*) main::line#5 = (byte*~) main::line#8 [phi:main::@3/main::@4->main::@5#1] -- register_copy
|
||||
jmp b5
|
||||
// main::@5
|
||||
b5:
|
||||
// [13] (byte*) main::msg#1 ← ++ (byte*) main::msg#2 -- pbuz1=_inc_pbuz1
|
||||
inc.z msg
|
||||
bne !+
|
||||
inc.z msg+1
|
||||
!:
|
||||
// [5] phi from main::@5 to main::@1 [phi:main::@5->main::@1]
|
||||
b1_from_b5:
|
||||
// [5] phi (byte*) main::cursor#3 = (byte*) main::cursor#6 [phi:main::@5->main::@1#0] -- register_copy
|
||||
// [5] phi (byte*) main::line#2 = (byte*) main::line#5 [phi:main::@5->main::@1#1] -- register_copy
|
||||
// [5] phi (byte*) main::msg#2 = (byte*) main::msg#1 [phi:main::@5->main::@1#2] -- register_copy
|
||||
jmp b1
|
||||
// main::@3
|
||||
b3:
|
||||
// [14] (byte*) main::cursor#1 ← (byte*) main::line#2 + (byte) $28 -- pbuz1=pbuz2_plus_vbuc1
|
||||
lda #$28
|
||||
clc
|
||||
adc.z line
|
||||
sta.z cursor
|
||||
lda #0
|
||||
adc.z line+1
|
||||
sta.z cursor+1
|
||||
// [15] (byte*~) main::line#8 ← (byte*) main::cursor#1 -- pbuz1=pbuz2
|
||||
lda.z cursor
|
||||
sta.z line
|
||||
lda.z cursor+1
|
||||
sta.z line+1
|
||||
jmp b5_from_b3
|
||||
}
|
||||
// File Data
|
||||
MESSAGE: .text @"hello\nworld"
|
||||
.byte 0
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [6] if((byte) 0!=*((byte*) main::msg#2)) goto main::@2 [ main::msg#2 main::line#2 main::cursor#3 ] ( main:2 [ main::msg#2 main::line#2 main::cursor#3 ] ) always clobbers reg byte a reg byte y
|
||||
Statement [8] if(*((byte*) main::msg#2)==(byte) '
|
||||
'pm) goto main::@3 [ main::msg#2 main::line#2 main::cursor#3 ] ( main:2 [ main::msg#2 main::line#2 main::cursor#3 ] ) always clobbers reg byte a reg byte y
|
||||
Statement [9] (byte~) main::$0 ← *((byte*) main::msg#2) & (byte) $3f [ main::msg#2 main::line#2 main::cursor#3 main::$0 ] ( main:2 [ main::msg#2 main::line#2 main::cursor#3 main::$0 ] ) always clobbers reg byte a reg byte y
|
||||
Statement [10] *((byte*) main::cursor#3) ← (byte~) main::$0 [ main::msg#2 main::line#2 main::cursor#3 ] ( main:2 [ main::msg#2 main::line#2 main::cursor#3 ] ) always clobbers reg byte y
|
||||
Statement [14] (byte*) main::cursor#1 ← (byte*) main::line#2 + (byte) $28 [ main::msg#2 main::cursor#1 ] ( main:2 [ main::msg#2 main::cursor#1 ] ) always clobbers reg byte a
|
||||
Statement [15] (byte*~) main::line#8 ← (byte*) main::cursor#1 [ main::msg#2 main::line#8 main::cursor#1 ] ( main:2 [ main::msg#2 main::line#8 main::cursor#1 ] ) always clobbers reg byte a
|
||||
Potential registers zp ZP_WORD:2 [ main::msg#2 main::msg#1 ] : zp ZP_WORD:2 ,
|
||||
Potential registers zp ZP_WORD:4 [ main::line#2 main::line#5 main::line#8 ] : zp ZP_WORD:4 ,
|
||||
Potential registers zp ZP_WORD:6 [ main::cursor#3 main::cursor#6 main::cursor#1 main::cursor#2 ] : zp ZP_WORD:6 ,
|
||||
Potential registers zp ZP_BYTE:8 [ main::$0 ] : zp ZP_BYTE:8 , reg byte a , reg byte x , reg byte y ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main] 61.6: zp ZP_WORD:6 [ main::cursor#3 main::cursor#6 main::cursor#1 main::cursor#2 ] 44: zp ZP_WORD:4 [ main::line#2 main::line#5 main::line#8 ] 28.11: zp ZP_WORD:2 [ main::msg#2 main::msg#1 ] 22: zp ZP_BYTE:8 [ main::$0 ]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 1463 combination zp ZP_WORD:6 [ main::cursor#3 main::cursor#6 main::cursor#1 main::cursor#2 ] zp ZP_WORD:4 [ main::line#2 main::line#5 main::line#8 ] zp ZP_WORD:2 [ main::msg#2 main::msg#1 ] reg byte a [ main::$0 ]
|
||||
Uplifting [] best 1463 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test using some simple supported string escape \n in both string and char
|
||||
// Uses encoding PETSCII mixed
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
// @begin
|
||||
bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
// @1
|
||||
b1:
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
main_from_b1:
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
// @end
|
||||
bend:
|
||||
// main
|
||||
main: {
|
||||
.label cursor = 6
|
||||
.label msg = 2
|
||||
.label line = 4
|
||||
// [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
// [5] phi (byte*) main::cursor#3 = (byte*) 1024 [phi:main->main::@1#0] -- pbuz1=pbuc1
|
||||
lda #<$400
|
||||
sta.z cursor
|
||||
lda #>$400
|
||||
sta.z cursor+1
|
||||
// [5] phi (byte*) main::line#2 = (byte*) 1024 [phi:main->main::@1#1] -- pbuz1=pbuc1
|
||||
lda #<$400
|
||||
sta.z line
|
||||
lda #>$400
|
||||
sta.z line+1
|
||||
// [5] phi (byte*) main::msg#2 = (const byte[]) MESSAGE#0 [phi:main->main::@1#2] -- pbuz1=pbuc1
|
||||
lda #<MESSAGE
|
||||
sta.z msg
|
||||
lda #>MESSAGE
|
||||
sta.z msg+1
|
||||
jmp b1
|
||||
// main::@1
|
||||
b1:
|
||||
// [6] if((byte) 0!=*((byte*) main::msg#2)) goto main::@2 -- vbuc1_neq__deref_pbuz1_then_la1
|
||||
ldy #0
|
||||
lda (msg),y
|
||||
cmp #0
|
||||
bne b2
|
||||
jmp breturn
|
||||
// main::@return
|
||||
breturn:
|
||||
// [7] return
|
||||
rts
|
||||
// main::@2
|
||||
b2:
|
||||
// [8] if(*((byte*) main::msg#2)==(byte) ' 'pm) goto main::@3 -- _deref_pbuz1_eq_vbuc1_then_la1
|
||||
.encoding "petscii_mixed"
|
||||
lda #'\n'
|
||||
ldy #0
|
||||
cmp (msg),y
|
||||
beq b3
|
||||
jmp b4
|
||||
// main::@4
|
||||
b4:
|
||||
// [9] (byte~) main::$0 ← *((byte*) main::msg#2) & (byte) $3f -- vbuaa=_deref_pbuz1_band_vbuc1
|
||||
lda #$3f
|
||||
ldy #0
|
||||
and (msg),y
|
||||
// [10] *((byte*) main::cursor#3) ← (byte~) main::$0 -- _deref_pbuz1=vbuaa
|
||||
ldy #0
|
||||
sta (cursor),y
|
||||
// [11] (byte*) main::cursor#2 ← ++ (byte*) main::cursor#3 -- pbuz1=_inc_pbuz1
|
||||
inc.z cursor
|
||||
bne !+
|
||||
inc.z cursor+1
|
||||
!:
|
||||
// [12] phi from main::@3 main::@4 to main::@5 [phi:main::@3/main::@4->main::@5]
|
||||
b5_from_b3:
|
||||
b5_from_b4:
|
||||
// [12] phi (byte*) main::cursor#6 = (byte*) main::cursor#1 [phi:main::@3/main::@4->main::@5#0] -- register_copy
|
||||
// [12] phi (byte*) main::line#5 = (byte*~) main::line#8 [phi:main::@3/main::@4->main::@5#1] -- register_copy
|
||||
jmp b5
|
||||
// main::@5
|
||||
b5:
|
||||
// [13] (byte*) main::msg#1 ← ++ (byte*) main::msg#2 -- pbuz1=_inc_pbuz1
|
||||
inc.z msg
|
||||
bne !+
|
||||
inc.z msg+1
|
||||
!:
|
||||
// [5] phi from main::@5 to main::@1 [phi:main::@5->main::@1]
|
||||
b1_from_b5:
|
||||
// [5] phi (byte*) main::cursor#3 = (byte*) main::cursor#6 [phi:main::@5->main::@1#0] -- register_copy
|
||||
// [5] phi (byte*) main::line#2 = (byte*) main::line#5 [phi:main::@5->main::@1#1] -- register_copy
|
||||
// [5] phi (byte*) main::msg#2 = (byte*) main::msg#1 [phi:main::@5->main::@1#2] -- register_copy
|
||||
jmp b1
|
||||
// main::@3
|
||||
b3:
|
||||
// [14] (byte*) main::cursor#1 ← (byte*) main::line#2 + (byte) $28 -- pbuz1=pbuz2_plus_vbuc1
|
||||
lda #$28
|
||||
clc
|
||||
adc.z line
|
||||
sta.z cursor
|
||||
lda #0
|
||||
adc.z line+1
|
||||
sta.z cursor+1
|
||||
// [15] (byte*~) main::line#8 ← (byte*) main::cursor#1 -- pbuz1=pbuz2
|
||||
lda.z cursor
|
||||
sta.z line
|
||||
lda.z cursor+1
|
||||
sta.z line+1
|
||||
jmp b5_from_b3
|
||||
}
|
||||
// File Data
|
||||
MESSAGE: .text @"hello\nworld"
|
||||
.byte 0
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp bend
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp breturn
|
||||
Removing instruction jmp b4
|
||||
Removing instruction jmp b5
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction ldy #0
|
||||
Succesful ASM optimization Pass5UnnecesaryLoadElimination
|
||||
Replacing label b5_from_b3 with b5
|
||||
Removing instruction b1_from_bbegin:
|
||||
Removing instruction b1:
|
||||
Removing instruction main_from_b1:
|
||||
Removing instruction bend_from_b1:
|
||||
Removing instruction b5_from_b3:
|
||||
Removing instruction b5_from_b4:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction bend:
|
||||
Removing instruction b1_from_main:
|
||||
Removing instruction breturn:
|
||||
Removing instruction b4:
|
||||
Removing instruction b1_from_b5:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Updating BasicUpstart to call main directly
|
||||
Removing instruction jsr main
|
||||
Succesful ASM optimization Pass5SkipBegin
|
||||
Removing instruction ldy #0
|
||||
Succesful ASM optimization Pass5UnnecesaryLoadElimination
|
||||
Removing instruction bbegin:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte[]) MESSAGE
|
||||
(const byte[]) MESSAGE#0 MESSAGE = (string) "hello
|
||||
world"pm
|
||||
(void()) main()
|
||||
(byte~) main::$0 reg byte a 22.0
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(label) main::@4
|
||||
(label) main::@5
|
||||
(label) main::@return
|
||||
(byte*) main::cursor
|
||||
(byte*) main::cursor#1 cursor zp ZP_WORD:6 16.5
|
||||
(byte*) main::cursor#2 cursor zp ZP_WORD:6 22.0
|
||||
(byte*) main::cursor#3 cursor zp ZP_WORD:6 6.6000000000000005
|
||||
(byte*) main::cursor#6 cursor zp ZP_WORD:6 16.5
|
||||
(byte*) main::line
|
||||
(byte*) main::line#2 line zp ZP_WORD:4 5.5
|
||||
(byte*) main::line#5 line zp ZP_WORD:4 16.5
|
||||
(byte*~) main::line#8 line zp ZP_WORD:4 22.0
|
||||
(byte*) main::msg
|
||||
(byte*) main::msg#1 msg zp ZP_WORD:2 22.0
|
||||
(byte*) main::msg#2 msg zp ZP_WORD:2 6.111111111111112
|
||||
|
||||
zp ZP_WORD:2 [ main::msg#2 main::msg#1 ]
|
||||
zp ZP_WORD:4 [ main::line#2 main::line#5 main::line#8 ]
|
||||
zp ZP_WORD:6 [ main::cursor#3 main::cursor#6 main::cursor#1 main::cursor#2 ]
|
||||
reg byte a [ main::$0 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 1291
|
||||
|
||||
// File Comments
|
||||
// Test using some simple supported string escape \n in both string and char
|
||||
// Uses encoding PETSCII mixed
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
// @begin
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
.label cursor = 6
|
||||
.label msg = 2
|
||||
.label line = 4
|
||||
// [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [5] phi (byte*) main::cursor#3 = (byte*) 1024 [phi:main->main::@1#0] -- pbuz1=pbuc1
|
||||
lda #<$400
|
||||
sta.z cursor
|
||||
lda #>$400
|
||||
sta.z cursor+1
|
||||
// [5] phi (byte*) main::line#2 = (byte*) 1024 [phi:main->main::@1#1] -- pbuz1=pbuc1
|
||||
lda #<$400
|
||||
sta.z line
|
||||
lda #>$400
|
||||
sta.z line+1
|
||||
// [5] phi (byte*) main::msg#2 = (const byte[]) MESSAGE#0 [phi:main->main::@1#2] -- pbuz1=pbuc1
|
||||
lda #<MESSAGE
|
||||
sta.z msg
|
||||
lda #>MESSAGE
|
||||
sta.z msg+1
|
||||
// main::@1
|
||||
b1:
|
||||
// while(*msg)
|
||||
// [6] if((byte) 0!=*((byte*) main::msg#2)) goto main::@2 -- vbuc1_neq__deref_pbuz1_then_la1
|
||||
ldy #0
|
||||
lda (msg),y
|
||||
cmp #0
|
||||
bne b2
|
||||
// main::@return
|
||||
// }
|
||||
// [7] return
|
||||
rts
|
||||
// main::@2
|
||||
b2:
|
||||
// case '\n':
|
||||
// line += 0x28;
|
||||
// cursor = line;
|
||||
// break;
|
||||
// [8] if(*((byte*) main::msg#2)==(byte) ' 'pm) goto main::@3 -- _deref_pbuz1_eq_vbuc1_then_la1
|
||||
.encoding "petscii_mixed"
|
||||
lda #'\n'
|
||||
ldy #0
|
||||
cmp (msg),y
|
||||
beq b3
|
||||
// main::@4
|
||||
// *msg & 0x3f
|
||||
// [9] (byte~) main::$0 ← *((byte*) main::msg#2) & (byte) $3f -- vbuaa=_deref_pbuz1_band_vbuc1
|
||||
lda #$3f
|
||||
and (msg),y
|
||||
// *cursor++ = *msg & 0x3f
|
||||
// [10] *((byte*) main::cursor#3) ← (byte~) main::$0 -- _deref_pbuz1=vbuaa
|
||||
sta (cursor),y
|
||||
// *cursor++ = *msg & 0x3f;
|
||||
// [11] (byte*) main::cursor#2 ← ++ (byte*) main::cursor#3 -- pbuz1=_inc_pbuz1
|
||||
inc.z cursor
|
||||
bne !+
|
||||
inc.z cursor+1
|
||||
!:
|
||||
// [12] phi from main::@3 main::@4 to main::@5 [phi:main::@3/main::@4->main::@5]
|
||||
// [12] phi (byte*) main::cursor#6 = (byte*) main::cursor#1 [phi:main::@3/main::@4->main::@5#0] -- register_copy
|
||||
// [12] phi (byte*) main::line#5 = (byte*~) main::line#8 [phi:main::@3/main::@4->main::@5#1] -- register_copy
|
||||
// main::@5
|
||||
b5:
|
||||
// msg++;
|
||||
// [13] (byte*) main::msg#1 ← ++ (byte*) main::msg#2 -- pbuz1=_inc_pbuz1
|
||||
inc.z msg
|
||||
bne !+
|
||||
inc.z msg+1
|
||||
!:
|
||||
// [5] phi from main::@5 to main::@1 [phi:main::@5->main::@1]
|
||||
// [5] phi (byte*) main::cursor#3 = (byte*) main::cursor#6 [phi:main::@5->main::@1#0] -- register_copy
|
||||
// [5] phi (byte*) main::line#2 = (byte*) main::line#5 [phi:main::@5->main::@1#1] -- register_copy
|
||||
// [5] phi (byte*) main::msg#2 = (byte*) main::msg#1 [phi:main::@5->main::@1#2] -- register_copy
|
||||
jmp b1
|
||||
// main::@3
|
||||
b3:
|
||||
// line += 0x28
|
||||
// [14] (byte*) main::cursor#1 ← (byte*) main::line#2 + (byte) $28 -- pbuz1=pbuz2_plus_vbuc1
|
||||
lda #$28
|
||||
clc
|
||||
adc.z line
|
||||
sta.z cursor
|
||||
lda #0
|
||||
adc.z line+1
|
||||
sta.z cursor+1
|
||||
// [15] (byte*~) main::line#8 ← (byte*) main::cursor#1 -- pbuz1=pbuz2
|
||||
lda.z cursor
|
||||
sta.z line
|
||||
lda.z cursor+1
|
||||
sta.z line+1
|
||||
jmp b5
|
||||
}
|
||||
// File Data
|
||||
MESSAGE: .text @"hello\nworld"
|
||||
.byte 0
|
||||
|
31
src/test/ref/string-escapes-3.sym
Normal file
31
src/test/ref/string-escapes-3.sym
Normal file
@ -0,0 +1,31 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte[]) MESSAGE
|
||||
(const byte[]) MESSAGE#0 MESSAGE = (string) "hello
|
||||
world"pm
|
||||
(void()) main()
|
||||
(byte~) main::$0 reg byte a 22.0
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(label) main::@4
|
||||
(label) main::@5
|
||||
(label) main::@return
|
||||
(byte*) main::cursor
|
||||
(byte*) main::cursor#1 cursor zp ZP_WORD:6 16.5
|
||||
(byte*) main::cursor#2 cursor zp ZP_WORD:6 22.0
|
||||
(byte*) main::cursor#3 cursor zp ZP_WORD:6 6.6000000000000005
|
||||
(byte*) main::cursor#6 cursor zp ZP_WORD:6 16.5
|
||||
(byte*) main::line
|
||||
(byte*) main::line#2 line zp ZP_WORD:4 5.5
|
||||
(byte*) main::line#5 line zp ZP_WORD:4 16.5
|
||||
(byte*~) main::line#8 line zp ZP_WORD:4 22.0
|
||||
(byte*) main::msg
|
||||
(byte*) main::msg#1 msg zp ZP_WORD:2 22.0
|
||||
(byte*) main::msg#2 msg zp ZP_WORD:2 6.111111111111112
|
||||
|
||||
zp ZP_WORD:2 [ main::msg#2 main::msg#1 ]
|
||||
zp ZP_WORD:4 [ main::line#2 main::line#5 main::line#8 ]
|
||||
zp ZP_WORD:6 [ main::cursor#3 main::cursor#6 main::cursor#1 main::cursor#2 ]
|
||||
reg byte a [ main::$0 ]
|
Loading…
x
Reference in New Issue
Block a user