From 62b03bcefb62e3631b3f5fe1a9734590f5350913 Mon Sep 17 00:00:00 2001 From: Jesper Gravgaard Date: Wed, 7 Aug 2019 14:58:57 +0200 Subject: [PATCH] Fixed encoding for literal chars through work-around. Closes #245 --- .../camelot64/kickc/fragment/AsmFormat.java | 11 +- .../dk/camelot64/kickc/test/TestPrograms.java | 5 + src/test/kc/encoding-literal-char.kc | 31 + src/test/ref/encoding-literal-char.asm | 40 ++ src/test/ref/encoding-literal-char.cfg | 22 + src/test/ref/encoding-literal-char.log | 529 ++++++++++++++++++ src/test/ref/encoding-literal-char.sym | 25 + src/test/ref/kc-ka-string-encoding.asm | 2 +- src/test/ref/kc-ka-string-encoding.log | 6 +- 9 files changed, 666 insertions(+), 5 deletions(-) create mode 100644 src/test/kc/encoding-literal-char.kc create mode 100644 src/test/ref/encoding-literal-char.asm create mode 100644 src/test/ref/encoding-literal-char.cfg create mode 100644 src/test/ref/encoding-literal-char.log create mode 100644 src/test/ref/encoding-literal-char.sym diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java index edd3e0899..98d82d1a6 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java @@ -9,6 +9,7 @@ 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.values.*; +import kickass.nonasm.c64.CharToPetsciiConverter; /** Formatting of numbers, constants, names and more for KickAssembler */ public class AsmFormat { @@ -31,7 +32,15 @@ public class AsmFormat { } else if(value instanceof ConstantBool) { return getAsmBool(((ConstantBool) value).getBool()); } else if(value instanceof ConstantChar) { - return "'" + ((ConstantChar) value).getValue() + "'"; + ConstantChar constantChar = (ConstantChar) value; + if(!ConstantString.Encoding.SCREENCODE_MIXED.equals(constantChar.getEncoding())) { + // 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 { + return "'" + constantChar.getValue() + "'"; + } } else if(value instanceof ConstantString) { return "\"" + ((ConstantString) value).getValue() + "\""; } else if(value instanceof ConstantUnary) { diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 42f57bb90..5b0f01f87 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -36,6 +36,11 @@ public class TestPrograms { public TestPrograms() { } + @Test + public void testEncodingLiteralChar() throws IOException, URISyntaxException { + compileAndCompare("encoding-literal-char"); + } + @Test public void testKcKaStringEncoding() throws IOException, URISyntaxException { compileAndCompare("kc-ka-string-encoding"); diff --git a/src/test/kc/encoding-literal-char.kc b/src/test/kc/encoding-literal-char.kc new file mode 100644 index 000000000..fc43f7fa6 --- /dev/null +++ b/src/test/kc/encoding-literal-char.kc @@ -0,0 +1,31 @@ +// Tests encoding of literal chars + +#encoding(petscii_mixed) +const char cpm = 'A'; +const char[] spm = "A"; +#encoding(petscii_upper) +const char cpu = 'A'; +const char[] spu = "A"; +#encoding(screencode_mixed) +const char csm = 'A'; +const char[] ssm = "A"; +#encoding(screencode_upper) +const char csu = 'A'; +const char[] ssu = "A"; + +const char* screen = 0x0400; +void main() { + char idx = 0; + screen[idx++] = cpm; + screen[idx++] = cpu; + screen[idx++] = csm; + screen[idx++] = csu; + idx = 0x28; + screen[idx++] = spm[0]; + screen[idx++] = spu[0]; + screen[idx++] = ssm[0]; + screen[idx++] = ssu[0]; + +} + + diff --git a/src/test/ref/encoding-literal-char.asm b/src/test/ref/encoding-literal-char.asm new file mode 100644 index 000000000..8f4130cd1 --- /dev/null +++ b/src/test/ref/encoding-literal-char.asm @@ -0,0 +1,40 @@ +// Tests encoding of literal chars +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +.encoding "petscii_mixed" + .const cpm = -$3f +.encoding "petscii_upper" + .const cpu = $41 +.encoding "screencode_mixed" + .const csm = 'A' +.encoding "screencode_upper" + .const csu = 1 + .label screen = $400 +main: { + lda #cpm + sta screen + lda #cpu + sta screen+1 + lda #csm + sta screen+2 + lda #csu + sta screen+3 + lda spm + sta screen+$28 + lda spu + sta screen+$29 + lda ssm + sta screen+$2a + lda ssu + sta screen+$2b + rts +} +.encoding "petscii_mixed" + spm: .text "A@" +.encoding "petscii_upper" + spu: .text "A@" +.encoding "screencode_mixed" + ssm: .text "A@" +.encoding "screencode_upper" + ssu: .text "A@" diff --git a/src/test/ref/encoding-literal-char.cfg b/src/test/ref/encoding-literal-char.cfg new file mode 100644 index 000000000..dc819fada --- /dev/null +++ b/src/test/ref/encoding-literal-char.cfg @@ -0,0 +1,22 @@ +@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] *((const byte*) screen#0) ← (const byte) cpm#0 + [5] *((const byte*) screen#0+(byte) 1) ← (const byte) cpu#0 + [6] *((const byte*) screen#0+(byte) 2) ← (const byte) csm#0 + [7] *((const byte*) screen#0+(byte) 3) ← (const byte) csu#0 + [8] *((const byte*) screen#0+(byte) $28) ← *((const byte[]) spm#0) + [9] *((const byte*) screen#0+(byte) $29) ← *((const byte[]) spu#0) + [10] *((const byte*) screen#0+(byte) $2a) ← *((const byte[]) ssm#0) + [11] *((const byte*) screen#0+(byte) $2b) ← *((const byte[]) ssu#0) + to:main::@return +main::@return: scope:[main] from main + [12] return + to:@return diff --git a/src/test/ref/encoding-literal-char.log b/src/test/ref/encoding-literal-char.log new file mode 100644 index 000000000..07fccabfb --- /dev/null +++ b/src/test/ref/encoding-literal-char.log @@ -0,0 +1,529 @@ + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + (byte) cpm#0 ← (byte) 'A'pm + (byte[]) spm#0 ← (const string) $0 + (byte) cpu#0 ← (byte) 'A'pu + (byte[]) spu#0 ← (const string) $1 + (byte) csm#0 ← (byte) 'A' + (byte[]) ssm#0 ← (const string) $2 + (byte) csu#0 ← (byte) 'A'su + (byte[]) ssu#0 ← (const string) $3 + (byte*) screen#0 ← ((byte*)) (number) $400 + to:@1 +main: scope:[main] from @1 + (byte) main::idx#0 ← (number) 0 + *((byte*) screen#0 + (byte) main::idx#0) ← (byte) cpm#0 + (byte) main::idx#1 ← ++ (byte) main::idx#0 + *((byte*) screen#0 + (byte) main::idx#1) ← (byte) cpu#0 + (byte) main::idx#2 ← ++ (byte) main::idx#1 + *((byte*) screen#0 + (byte) main::idx#2) ← (byte) csm#0 + (byte) main::idx#3 ← ++ (byte) main::idx#2 + *((byte*) screen#0 + (byte) main::idx#3) ← (byte) csu#0 + (byte) main::idx#4 ← ++ (byte) main::idx#3 + (byte) main::idx#5 ← (number) $28 + *((byte*) screen#0 + (byte) main::idx#5) ← *((byte[]) spm#0 + (number) 0) + (byte) main::idx#6 ← ++ (byte) main::idx#5 + *((byte*) screen#0 + (byte) main::idx#6) ← *((byte[]) spu#0 + (number) 0) + (byte) main::idx#7 ← ++ (byte) main::idx#6 + *((byte*) screen#0 + (byte) main::idx#7) ← *((byte[]) ssm#0 + (number) 0) + (byte) main::idx#8 ← ++ (byte) main::idx#7 + *((byte*) screen#0 + (byte) main::idx#8) ← *((byte[]) ssu#0 + (number) 0) + (byte) main::idx#9 ← ++ (byte) main::idx#8 + to:main::@return +main::@return: scope:[main] from main + 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) "A@"pm +(const string) $1 = (string) "A@"pu +(const string) $2 = (string) "A@" +(const string) $3 = (string) "A@"su +(label) @1 +(label) @2 +(label) @begin +(label) @end +(byte) cpm +(byte) cpm#0 +(byte) cpu +(byte) cpu#0 +(byte) csm +(byte) csm#0 +(byte) csu +(byte) csu#0 +(void()) main() +(label) main::@return +(byte) main::idx +(byte) main::idx#0 +(byte) main::idx#1 +(byte) main::idx#2 +(byte) main::idx#3 +(byte) main::idx#4 +(byte) main::idx#5 +(byte) main::idx#6 +(byte) main::idx#7 +(byte) main::idx#8 +(byte) main::idx#9 +(byte*) screen +(byte*) screen#0 +(byte[]) spm +(byte[]) spm#0 +(byte[]) spu +(byte[]) spu#0 +(byte[]) ssm +(byte[]) ssm#0 +(byte[]) ssu +(byte[]) ssu#0 + +Adding number conversion cast (unumber) 0 in (byte) main::idx#0 ← (number) 0 +Adding number conversion cast (unumber) $28 in (byte) main::idx#5 ← (number) $28 +Adding number conversion cast (unumber) 0 in *((byte*) screen#0 + (byte) main::idx#5) ← *((byte[]) spm#0 + (number) 0) +Adding number conversion cast (unumber) 0 in *((byte*) screen#0 + (byte) main::idx#6) ← *((byte[]) spu#0 + (number) 0) +Adding number conversion cast (unumber) 0 in *((byte*) screen#0 + (byte) main::idx#7) ← *((byte[]) ssm#0 + (number) 0) +Adding number conversion cast (unumber) 0 in *((byte*) screen#0 + (byte) main::idx#8) ← *((byte[]) ssu#0 + (number) 0) +Successful SSA optimization PassNAddNumberTypeConversions +Inlining cast (byte*) screen#0 ← (byte*)(number) $400 +Inlining cast (byte) main::idx#0 ← (unumber)(number) 0 +Inlining cast (byte) main::idx#5 ← (unumber)(number) $28 +Successful SSA optimization Pass2InlineCast +Simplifying constant pointer cast (byte*) 1024 +Simplifying constant integer cast 0 +Simplifying constant integer cast $28 +Simplifying constant integer cast 0 +Simplifying constant integer cast 0 +Simplifying constant integer cast 0 +Simplifying constant integer cast 0 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) $28 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) 0 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Constant (const byte) cpm#0 = 'A'pm +Constant (const byte[]) spm#0 = $0 +Constant (const byte) cpu#0 = 'A'pu +Constant (const byte[]) spu#0 = $1 +Constant (const byte) csm#0 = 'A' +Constant (const byte[]) ssm#0 = $2 +Constant (const byte) csu#0 = 'A'su +Constant (const byte[]) ssu#0 = $3 +Constant (const byte*) screen#0 = (byte*) 1024 +Constant (const byte) main::idx#0 = 0 +Constant (const byte) main::idx#5 = $28 +Successful SSA optimization Pass2ConstantIdentification +Simplifying expression containing zero screen#0 in [10] *((const byte*) screen#0 + (const byte) main::idx#0) ← (const byte) cpm#0 +Simplifying expression containing zero spm#0 in [19] *((const byte*) screen#0 + (const byte) main::idx#5) ← *((const byte[]) spm#0 + (byte) 0) +Simplifying expression containing zero spu#0 in [21] *((const byte*) screen#0 + (byte) main::idx#6) ← *((const byte[]) spu#0 + (byte) 0) +Simplifying expression containing zero ssm#0 in [23] *((const byte*) screen#0 + (byte) main::idx#7) ← *((const byte[]) ssm#0 + (byte) 0) +Simplifying expression containing zero ssu#0 in [25] *((const byte*) screen#0 + (byte) main::idx#8) ← *((const byte[]) ssu#0 + (byte) 0) +Successful SSA optimization PassNSimplifyExpressionWithZero +Eliminating unused variable (byte) main::idx#4 and assignment [7] (byte) main::idx#4 ← ++ (byte) main::idx#3 +Eliminating unused variable (byte) main::idx#9 and assignment [15] (byte) main::idx#9 ← ++ (byte) main::idx#8 +Successful SSA optimization PassNEliminateUnusedVars +Constant right-side identified [1] (byte) main::idx#1 ← ++ (const byte) main::idx#0 +Constant right-side identified [8] (byte) main::idx#6 ← ++ (const byte) main::idx#5 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#1 = ++main::idx#0 +Constant (const byte) main::idx#6 = ++main::idx#5 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [2] (byte) main::idx#2 ← ++ (const byte) main::idx#1 +Constant right-side identified [8] (byte) main::idx#7 ← ++ (const byte) main::idx#6 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#2 = ++main::idx#1 +Constant (const byte) main::idx#7 = ++main::idx#6 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [3] (byte) main::idx#3 ← ++ (const byte) main::idx#2 +Constant right-side identified [8] (byte) main::idx#8 ← ++ (const byte) main::idx#7 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#3 = ++main::idx#2 +Constant (const byte) main::idx#8 = ++main::idx#7 +Successful SSA optimization Pass2ConstantIdentification +Inlining constant with different constant siblings (const byte) main::idx#0 +Inlining constant with different constant siblings (const byte) main::idx#5 +Inlining constant with different constant siblings (const byte) main::idx#1 +Inlining constant with different constant siblings (const byte) main::idx#6 +Inlining constant with different constant siblings (const byte) main::idx#2 +Inlining constant with different constant siblings (const byte) main::idx#7 +Inlining constant with different constant siblings (const byte) main::idx#3 +Inlining constant with different constant siblings (const byte) main::idx#8 +Constant inlined main::idx#0 = (byte) 0 +Constant inlined main::idx#1 = ++(byte) 0 +Constant inlined main::idx#2 = ++++(byte) 0 +Constant inlined main::idx#3 = ++++++(byte) 0 +Constant inlined main::idx#5 = (byte) $28 +Constant inlined main::idx#6 = ++(byte) $28 +Constant inlined main::idx#7 = ++++(byte) $28 +Constant inlined main::idx#8 = ++++++(byte) $28 +Constant inlined $0 = (const byte[]) spm#0 +Constant inlined $1 = (const byte[]) spu#0 +Constant inlined $2 = (const byte[]) ssm#0 +Constant inlined $3 = (const byte[]) ssu#0 +Successful SSA optimization Pass2ConstantInlining +Consolidated array index constant in *(screen#0+++0) +Consolidated array index constant in *(screen#0+++++0) +Consolidated array index constant in *(screen#0+++++++0) +Consolidated array index constant in *(screen#0+$28) +Consolidated array index constant in *(screen#0+++$28) +Consolidated array index constant in *(screen#0+++++$28) +Consolidated array index constant in *(screen#0+++++++$28) +Successful SSA optimization Pass2ConstantAdditionElimination +Simplifying constant integer increment ++0 +Simplifying constant integer increment ++0 +Simplifying constant integer increment ++1 +Simplifying constant integer increment ++$28 +Simplifying constant integer increment ++$28 +Simplifying constant integer increment ++$29 +Successful SSA optimization Pass2ConstantSimplification +Simplifying constant integer increment ++1 +Simplifying constant integer increment ++2 +Simplifying constant integer increment ++$29 +Simplifying constant integer increment ++$2a +Successful SSA optimization Pass2ConstantSimplification +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 +CALL GRAPH +Calls in [] to main:2 + +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes +Culled Empty Block (label) @2 +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @end + +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] *((const byte*) screen#0) ← (const byte) cpm#0 + [5] *((const byte*) screen#0+(byte) 1) ← (const byte) cpu#0 + [6] *((const byte*) screen#0+(byte) 2) ← (const byte) csm#0 + [7] *((const byte*) screen#0+(byte) 3) ← (const byte) csu#0 + [8] *((const byte*) screen#0+(byte) $28) ← *((const byte[]) spm#0) + [9] *((const byte*) screen#0+(byte) $29) ← *((const byte[]) spu#0) + [10] *((const byte*) screen#0+(byte) $2a) ← *((const byte[]) ssm#0) + [11] *((const byte*) screen#0+(byte) $2b) ← *((const byte[]) ssu#0) + to:main::@return +main::@return: scope:[main] from main + [12] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(byte) cpm +(byte) cpu +(byte) csm +(byte) csu +(void()) main() +(byte) main::idx +(byte*) screen +(byte[]) spm +(byte[]) spu +(byte[]) ssm +(byte[]) ssu + +Initial phi equivalence classes +Complete equivalence classes + +INITIAL ASM +Target platform is c64basic + // File Comments +// Tests encoding of literal chars + // Upstart +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" + // Global Constants & labels +.encoding "petscii_mixed" + .const cpm = -$3f +.encoding "petscii_upper" + .const cpu = $41 +.encoding "screencode_mixed" + .const csm = 'A' +.encoding "screencode_upper" + .const csu = 1 + .label screen = $400 + // @begin +bbegin: + // [1] phi from @begin to @1 [phi:@begin->@1] +b1_from_bbegin: + jmp b1 + // @1 +b1: + // [2] call main + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend + // @end +bend: + // main +main: { + // [4] *((const byte*) screen#0) ← (const byte) cpm#0 -- _deref_pbuc1=vbuc2 + lda #cpm + sta screen + // [5] *((const byte*) screen#0+(byte) 1) ← (const byte) cpu#0 -- _deref_pbuc1=vbuc2 + lda #cpu + sta screen+1 + // [6] *((const byte*) screen#0+(byte) 2) ← (const byte) csm#0 -- _deref_pbuc1=vbuc2 + lda #csm + sta screen+2 + // [7] *((const byte*) screen#0+(byte) 3) ← (const byte) csu#0 -- _deref_pbuc1=vbuc2 + lda #csu + sta screen+3 + // [8] *((const byte*) screen#0+(byte) $28) ← *((const byte[]) spm#0) -- _deref_pbuc1=_deref_pbuc2 + lda spm + sta screen+$28 + // [9] *((const byte*) screen#0+(byte) $29) ← *((const byte[]) spu#0) -- _deref_pbuc1=_deref_pbuc2 + lda spu + sta screen+$29 + // [10] *((const byte*) screen#0+(byte) $2a) ← *((const byte[]) ssm#0) -- _deref_pbuc1=_deref_pbuc2 + lda ssm + sta screen+$2a + // [11] *((const byte*) screen#0+(byte) $2b) ← *((const byte[]) ssu#0) -- _deref_pbuc1=_deref_pbuc2 + lda ssu + sta screen+$2b + jmp breturn + // main::@return + breturn: + // [12] return + rts +} + // File Data +.encoding "petscii_mixed" + spm: .text "A@" +.encoding "petscii_upper" + spu: .text "A@" +.encoding "screencode_mixed" + ssm: .text "A@" +.encoding "screencode_upper" + ssu: .text "A@" + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [4] *((const byte*) screen#0) ← (const byte) cpm#0 [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [5] *((const byte*) screen#0+(byte) 1) ← (const byte) cpu#0 [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [6] *((const byte*) screen#0+(byte) 2) ← (const byte) csm#0 [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [7] *((const byte*) screen#0+(byte) 3) ← (const byte) csu#0 [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [8] *((const byte*) screen#0+(byte) $28) ← *((const byte[]) spm#0) [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [9] *((const byte*) screen#0+(byte) $29) ← *((const byte[]) spu#0) [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [10] *((const byte*) screen#0+(byte) $2a) ← *((const byte[]) ssm#0) [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [11] *((const byte*) screen#0+(byte) $2b) ← *((const byte[]) ssu#0) [ ] ( main:2 [ ] ) always clobbers reg byte a + +REGISTER UPLIFT SCOPES +Uplift Scope [main] +Uplift Scope [] + +Uplifting [main] best 77 combination +Uplifting [] best 77 combination + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Tests encoding of literal chars + // Upstart +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" + // Global Constants & labels +.encoding "petscii_mixed" + .const cpm = -$3f +.encoding "petscii_upper" + .const cpu = $41 +.encoding "screencode_mixed" + .const csm = 'A' +.encoding "screencode_upper" + .const csu = 1 + .label screen = $400 + // @begin +bbegin: + // [1] phi from @begin to @1 [phi:@begin->@1] +b1_from_bbegin: + jmp b1 + // @1 +b1: + // [2] call main + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend + // @end +bend: + // main +main: { + // [4] *((const byte*) screen#0) ← (const byte) cpm#0 -- _deref_pbuc1=vbuc2 + lda #cpm + sta screen + // [5] *((const byte*) screen#0+(byte) 1) ← (const byte) cpu#0 -- _deref_pbuc1=vbuc2 + lda #cpu + sta screen+1 + // [6] *((const byte*) screen#0+(byte) 2) ← (const byte) csm#0 -- _deref_pbuc1=vbuc2 + lda #csm + sta screen+2 + // [7] *((const byte*) screen#0+(byte) 3) ← (const byte) csu#0 -- _deref_pbuc1=vbuc2 + lda #csu + sta screen+3 + // [8] *((const byte*) screen#0+(byte) $28) ← *((const byte[]) spm#0) -- _deref_pbuc1=_deref_pbuc2 + lda spm + sta screen+$28 + // [9] *((const byte*) screen#0+(byte) $29) ← *((const byte[]) spu#0) -- _deref_pbuc1=_deref_pbuc2 + lda spu + sta screen+$29 + // [10] *((const byte*) screen#0+(byte) $2a) ← *((const byte[]) ssm#0) -- _deref_pbuc1=_deref_pbuc2 + lda ssm + sta screen+$2a + // [11] *((const byte*) screen#0+(byte) $2b) ← *((const byte[]) ssu#0) -- _deref_pbuc1=_deref_pbuc2 + lda ssu + sta screen+$2b + jmp breturn + // main::@return + breturn: + // [12] return + rts +} + // File Data +.encoding "petscii_mixed" + spm: .text "A@" +.encoding "petscii_upper" + spu: .text "A@" +.encoding "screencode_mixed" + ssm: .text "A@" +.encoding "screencode_upper" + ssu: .text "A@" + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp b1 +Removing instruction jmp bend +Removing instruction jmp breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction b1_from_bbegin: +Removing instruction b1: +Removing instruction bend_from_b1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction bend: +Removing instruction breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Updating BasicUpstart to call main directly +Removing instruction jsr main +Succesful ASM optimization Pass5SkipBegin +Removing instruction bbegin: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(byte) cpm +(const byte) cpm#0 cpm = (byte) 'A'pm +(byte) cpu +(const byte) cpu#0 cpu = (byte) 'A'pu +(byte) csm +(const byte) csm#0 csm = (byte) 'A' +(byte) csu +(const byte) csu#0 csu = (byte) 'A'su +(void()) main() +(label) main::@return +(byte) main::idx +(byte*) screen +(const byte*) screen#0 screen = (byte*) 1024 +(byte[]) spm +(const byte[]) spm#0 spm = (string) "A@"pm +(byte[]) spu +(const byte[]) spu#0 spu = (string) "A@"pu +(byte[]) ssm +(const byte[]) ssm#0 ssm = (string) "A@" +(byte[]) ssu +(const byte[]) ssu#0 ssu = (string) "A@"su + + + +FINAL ASSEMBLER +Score: 62 + + // File Comments +// Tests encoding of literal chars + // Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + // Global Constants & labels +.encoding "petscii_mixed" + .const cpm = -$3f +.encoding "petscii_upper" + .const cpu = $41 +.encoding "screencode_mixed" + .const csm = 'A' +.encoding "screencode_upper" + .const csu = 1 + .label screen = $400 + // @begin + // [1] phi from @begin to @1 [phi:@begin->@1] + // @1 + // [2] call main + // [3] phi from @1 to @end [phi:@1->@end] + // @end + // main +main: { + // screen[idx++] = cpm + // [4] *((const byte*) screen#0) ← (const byte) cpm#0 -- _deref_pbuc1=vbuc2 + lda #cpm + sta screen + // screen[idx++] = cpu + // [5] *((const byte*) screen#0+(byte) 1) ← (const byte) cpu#0 -- _deref_pbuc1=vbuc2 + lda #cpu + sta screen+1 + // screen[idx++] = csm + // [6] *((const byte*) screen#0+(byte) 2) ← (const byte) csm#0 -- _deref_pbuc1=vbuc2 + lda #csm + sta screen+2 + // screen[idx++] = csu + // [7] *((const byte*) screen#0+(byte) 3) ← (const byte) csu#0 -- _deref_pbuc1=vbuc2 + lda #csu + sta screen+3 + // screen[idx++] = spm[0] + // [8] *((const byte*) screen#0+(byte) $28) ← *((const byte[]) spm#0) -- _deref_pbuc1=_deref_pbuc2 + lda spm + sta screen+$28 + // screen[idx++] = spu[0] + // [9] *((const byte*) screen#0+(byte) $29) ← *((const byte[]) spu#0) -- _deref_pbuc1=_deref_pbuc2 + lda spu + sta screen+$29 + // screen[idx++] = ssm[0] + // [10] *((const byte*) screen#0+(byte) $2a) ← *((const byte[]) ssm#0) -- _deref_pbuc1=_deref_pbuc2 + lda ssm + sta screen+$2a + // screen[idx++] = ssu[0] + // [11] *((const byte*) screen#0+(byte) $2b) ← *((const byte[]) ssu#0) -- _deref_pbuc1=_deref_pbuc2 + lda ssu + sta screen+$2b + // main::@return + // } + // [12] return + rts +} + // File Data +.encoding "petscii_mixed" + spm: .text "A@" +.encoding "petscii_upper" + spu: .text "A@" +.encoding "screencode_mixed" + ssm: .text "A@" +.encoding "screencode_upper" + ssu: .text "A@" + diff --git a/src/test/ref/encoding-literal-char.sym b/src/test/ref/encoding-literal-char.sym new file mode 100644 index 000000000..b48474fd2 --- /dev/null +++ b/src/test/ref/encoding-literal-char.sym @@ -0,0 +1,25 @@ +(label) @1 +(label) @begin +(label) @end +(byte) cpm +(const byte) cpm#0 cpm = (byte) 'A'pm +(byte) cpu +(const byte) cpu#0 cpu = (byte) 'A'pu +(byte) csm +(const byte) csm#0 csm = (byte) 'A' +(byte) csu +(const byte) csu#0 csu = (byte) 'A'su +(void()) main() +(label) main::@return +(byte) main::idx +(byte*) screen +(const byte*) screen#0 screen = (byte*) 1024 +(byte[]) spm +(const byte[]) spm#0 spm = (string) "A@"pm +(byte[]) spu +(const byte[]) spu#0 spu = (string) "A@"pu +(byte[]) ssm +(const byte[]) ssm#0 ssm = (string) "A@" +(byte[]) ssu +(const byte[]) ssu#0 ssu = (string) "A@"su + diff --git a/src/test/ref/kc-ka-string-encoding.asm b/src/test/ref/kc-ka-string-encoding.asm index 039ab8bf8..855713017 100644 --- a/src/test/ref/kc-ka-string-encoding.asm +++ b/src/test/ref/kc-ka-string-encoding.asm @@ -3,7 +3,7 @@ .pc = $80d "Program" main: { .encoding "petscii_mixed" - lda #'e' + lda #$45 sta strTemp+2 lda #0 sta strTemp+3 diff --git a/src/test/ref/kc-ka-string-encoding.log b/src/test/ref/kc-ka-string-encoding.log index 1c78682d3..b63167ab9 100644 --- a/src/test/ref/kc-ka-string-encoding.log +++ b/src/test/ref/kc-ka-string-encoding.log @@ -141,7 +141,7 @@ bend: main: { // [4] *((const byte[]) strTemp#0+(byte) 2) ← (byte) 'e'pm -- _deref_pbuc1=vbuc2 .encoding "petscii_mixed" - lda #'e' + lda #$45 sta strTemp+2 // [5] *((const byte[]) strTemp#0+(byte) 3) ← (byte) 0 -- _deref_pbuc1=vbuc2 lda #0 @@ -201,7 +201,7 @@ bend: main: { // [4] *((const byte[]) strTemp#0+(byte) 2) ← (byte) 'e'pm -- _deref_pbuc1=vbuc2 .encoding "petscii_mixed" - lda #'e' + lda #$45 sta strTemp+2 // [5] *((const byte[]) strTemp#0+(byte) 3) ← (byte) 0 -- _deref_pbuc1=vbuc2 lda #0 @@ -275,7 +275,7 @@ main: { // strTemp[2] = 'e' // [4] *((const byte[]) strTemp#0+(byte) 2) ← (byte) 'e'pm -- _deref_pbuc1=vbuc2 .encoding "petscii_mixed" - lda #'e' + lda #$45 sta strTemp+2 // strTemp[3] = 0 // [5] *((const byte[]) strTemp#0+(byte) 3) ← (byte) 0 -- _deref_pbuc1=vbuc2