1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-09-08 17:54:40 +00:00

Implemented Xmega65 SYSCALLS.

This commit is contained in:
jespergravgaard 2019-08-10 00:22:57 +02:00
parent 4430974f25
commit e53159699b
4 changed files with 57 additions and 83 deletions

View File

@ -1,13 +1,12 @@
// Example showing how to perform linking using a linker-file
// The linker file is created using KickAssembler segments.
// See the KickAssembler manual for description of the format http://theweb.dk/KickAssembler/
// Specifying the linker script file is done using the #pragma link(<file>)
// It can also be specified using kickc command line option -T <file>
// XMega65 Kernal Development Template
// Each function of the kernal is a no-args function
// The functions are placed in the SYSCALLS table surrounded by JMP and NOP
#pragma link("xmega65.ld")
void main() {
char i=0;
// Call functions one at a time
while(true) {
unsigned int fn = CALLS[i*2];
void()* f = (void()*)fn;
@ -33,8 +32,7 @@ const char NOP = 0xea;
char[] SYSCALLS = {
JMP, <&fn1, >&fn1, NOP,
JMP, <&fn2, >&fn2, NOP,
JMP, <&main, >&main, NOP
JMP, <&fn2, >&fn2, NOP
};
const unsigned int* CALLS = (unsigned int*)(SYSCALLS+1);

View File

@ -1,8 +1,6 @@
// Example showing how to perform linking using a linker-file
// The linker file is created using KickAssembler segments.
// See the KickAssembler manual for description of the format http://theweb.dk/KickAssembler/
// Specifying the linker script file is done using the #pragma link(<file>)
// It can also be specified using kickc command line option -T <file>
// XMega65 Kernal Development Template
// Each function of the kernal is a no-args function
// The functions are placed in the SYSCALLS table surrounded by JMP and NOP
.file [name="xmega65.bin", type="bin", segments="XMega65Bin"]
.segmentdef XMega65Bin [segments="Syscall, Code, Data, Stack, Zeropage"]
.segmentdef Syscall [start=$8000, max=$81ff]
@ -20,6 +18,7 @@ main: {
b1:
lda #0
sta.z i
// Call functions one at a time
b2:
lda.z i
asl
@ -49,4 +48,4 @@ fn1: {
rts
}
.segment Syscall
SYSCALLS: .byte JMP, <fn1, >fn1, NOP, JMP, <fn2, >fn2, NOP, JMP, <main, >main, NOP
SYSCALLS: .byte JMP, <fn1, >fn1, NOP, JMP, <fn2, >fn2, NOP

View File

@ -63,14 +63,10 @@ fn2::@return: scope:[fn2] from fn2
(byte~) $5 ← < (void()*~) $4
(void()*~) $6 ← & (void()) fn2()
(byte~) $7 ← > (void()*~) $6
(void()*~) $8 ← & (void()) main()
(byte~) $9 ← < (void()*~) $8
(void()*~) $10 ← & (void()) main()
(byte~) $11 ← > (void()*~) $10
(byte[]) SYSCALLS#0 ← { (byte) JMP#0, (byte~) $1, (byte~) $3, (byte) NOP#0, (byte) JMP#0, (byte~) $5, (byte~) $7, (byte) NOP#0, (byte) JMP#0, (byte~) $9, (byte~) $11, (byte) NOP#0 }
(byte*~) $12 ← (byte[]) SYSCALLS#0 + (number) 1
(word*~) $13 ← ((word*)) (byte*~) $12
(word*) CALLS#0 ← (word*~) $13
(byte[]) SYSCALLS#0 ← { (byte) JMP#0, (byte~) $1, (byte~) $3, (byte) NOP#0, (byte) JMP#0, (byte~) $5, (byte~) $7, (byte) NOP#0 }
(byte*~) $8 ← (byte[]) SYSCALLS#0 + (number) 1
(word*~) $9 ← ((word*)) (byte*~) $8
(word*) CALLS#0 ← (word*~) $9
call main
to:@4
@4: scope:[] from @3
@ -80,18 +76,14 @@ fn2::@return: scope:[fn2] from fn2
SYMBOL TABLE SSA
(void()*~) $0
(byte~) $1
(void()*~) $10
(byte~) $11
(byte*~) $12
(word*~) $13
(void()*~) $2
(byte~) $3
(void()*~) $4
(byte~) $5
(void()*~) $6
(byte~) $7
(void()*~) $8
(byte~) $9
(byte*~) $8
(word*~) $9
(label) @3
(label) @4
(label) @begin
@ -142,7 +134,7 @@ Adding number conversion cast (unumber) 2 in (bool~) main::$3 ← (byte) main::i
Adding number conversion cast (unumber) 0 in (byte) main::i#2 ← (number) 0
Adding number conversion cast (unumber) $4c in (byte) JMP#0 ← (number) $4c
Adding number conversion cast (unumber) $ea in (byte) NOP#0 ← (number) $ea
Adding number conversion cast (unumber) 1 in (byte*~) $12 ← (byte[]) SYSCALLS#0 + (number) 1
Adding number conversion cast (unumber) 1 in (byte*~) $8 ← (byte[]) SYSCALLS#0 + (number) 1
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast (byte) main::i#0 ← (unumber)(number) 0
Inlining cast (void()*~) main::$1 ← (void()*)(word) main::fn#0
@ -151,7 +143,7 @@ Inlining cast (byte*) fn1::BORDERCOL#0 ← (byte*)(number) $d020
Inlining cast (byte*) fn2::BGCOL#0 ← (byte*)(number) $d021
Inlining cast (byte) JMP#0 ← (unumber)(number) $4c
Inlining cast (byte) NOP#0 ← (unumber)(number) $ea
Inlining cast (word*~) $13 ← (word*)(byte*~) $12
Inlining cast (word*~) $9 ← (word*)(byte*~) $8
Successful SSA optimization Pass2InlineCast
Simplifying constant integer cast 0
Simplifying constant integer cast 2
@ -177,17 +169,15 @@ Inversing boolean not [12] (bool~) main::$4 ← (byte) main::i#1 != (byte) 2 fro
Successful SSA optimization Pass2UnaryNotSimplification
Alias (byte) main::i#3 = (byte) main::i#4
Alias (void()*) main::f#0 = (void()*~) main::$1
Alias (word*) CALLS#0 = (word*~) $13
Alias (word*) CALLS#0 = (word*~) $9
Successful SSA optimization Pass2AliasElimination
Identified duplicate assignment right side [26] (void()*~) $2 ← & (void()) fn1()
Identified duplicate assignment right side [30] (void()*~) $6 ← & (void()) fn2()
Identified duplicate assignment right side [34] (void()*~) $10 ← & (void()) main()
Successful SSA optimization Pass2DuplicateRValueIdentification
Simple Condition (bool~) main::$4 [13] if((byte) main::i#1!=(byte) 2) goto main::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant right-side identified [24] (void()*~) $0 ← & (void()) fn1()
Constant right-side identified [28] (void()*~) $4 ← & (void()) fn2()
Constant right-side identified [32] (void()*~) $8 ← & (void()) main()
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte) main::i#0 = 0
Constant (const byte) main::i#2 = 0
@ -197,11 +187,9 @@ Constant (const byte) JMP#0 = $4c
Constant (const byte) NOP#0 = $ea
Constant (const void()*) $0 = &fn1
Constant (const void()*) $4 = &fn2
Constant (const void()*) $8 = &main
Successful SSA optimization Pass2ConstantIdentification
Constant (const void()*) $2 = $0
Constant (const void()*) $6 = $4
Constant (const void()*) $10 = $8
Successful SSA optimization Pass2ConstantIdentification
if() condition always true - replacing block destination [2] if(true) goto main::@2
Successful SSA optimization Pass2ConstantIfs
@ -211,27 +199,23 @@ Constant right-side identified [12] (byte~) $1 ← < (const void()*) $0
Constant right-side identified [13] (byte~) $3 ← > (const void()*) $2
Constant right-side identified [14] (byte~) $5 ← < (const void()*) $4
Constant right-side identified [15] (byte~) $7 ← > (const void()*) $6
Constant right-side identified [16] (byte~) $9 ← < (const void()*) $8
Constant right-side identified [17] (byte~) $11 ← > (const void()*) $10
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte) $1 = <$0
Constant (const byte) $3 = >$2
Constant (const byte) $5 = <$4
Constant (const byte) $7 = >$6
Constant (const byte) $9 = <$8
Constant (const byte) $11 = >$10
Successful SSA optimization Pass2ConstantIdentification
Identified constant from value list (byte[]) { (const byte) JMP#0, (const byte) $1, (const byte) $3, (const byte) NOP#0, (const byte) JMP#0, (const byte) $5, (const byte) $7, (const byte) NOP#0, (const byte) JMP#0, (const byte) $9, (const byte) $11, (const byte) NOP#0 }
Identified constant from value list (byte[]) { (const byte) JMP#0, (const byte) $1, (const byte) $3, (const byte) NOP#0, (const byte) JMP#0, (const byte) $5, (const byte) $7, (const byte) NOP#0 }
Successful SSA optimization Pass2ConstantInitializerValueLists
Constant (const byte[]) SYSCALLS#0 = { JMP#0, $1, $3, NOP#0, JMP#0, $5, $7, NOP#0, JMP#0, $9, $11, NOP#0 }
Constant (const byte[]) SYSCALLS#0 = { JMP#0, $1, $3, NOP#0, JMP#0, $5, $7, NOP#0 }
Successful SSA optimization Pass2ConstantIdentification
Constant right-side identified [12] (byte*~) $12 ← (const byte[]) SYSCALLS#0 + (byte) 1
Constant right-side identified [12] (byte*~) $8 ← (const byte[]) SYSCALLS#0 + (byte) 1
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte*) $12 = SYSCALLS#0+1
Constant (const byte*) $8 = SYSCALLS#0+1
Successful SSA optimization Pass2ConstantIdentification
Constant value identified (word*)$12 in [13] (word*) CALLS#0 ← (word*)(const byte*) $12
Constant value identified (word*)$8 in [13] (word*) CALLS#0 ← (word*)(const byte*) $8
Successful SSA optimization Pass2ConstantValues
Constant (const word*) CALLS#0 = (word*)$12
Constant (const word*) CALLS#0 = (word*)$8
Successful SSA optimization Pass2ConstantIdentification
Inlining Noop Cast [4] (void()*) main::f#0 ← (void()*)(word) main::fn#0 keeping main::fn#0
Successful SSA optimization Pass2NopCastInlining
@ -240,21 +224,17 @@ Rewriting multiplication to use shift [2] (byte~) main::$5 ← (byte~) main::$0
Successful SSA optimization Pass2MultiplyToShiftRewriting
Inlining constant with var siblings (const byte) main::i#0
Inlining constant with var siblings (const byte) main::i#2
Constant inlined $10 = &(void()) main()
Constant inlined $11 = >&(void()) main()
Constant inlined $12 = (const byte[]) SYSCALLS#0+(byte) 1
Constant inlined $0 = &(void()) fn1()
Constant inlined $1 = <&(void()) fn1()
Constant inlined $2 = &(void()) fn1()
Constant inlined $3 = >&(void()) fn1()
Constant inlined $4 = &(void()) fn2()
Constant inlined $5 = <&(void()) fn2()
Constant inlined $6 = &(void()) fn2()
Constant inlined $7 = >&(void()) fn2()
Constant inlined $8 = &(void()) main()
Constant inlined $9 = <&(void()) main()
Constant inlined $8 = (const byte[]) SYSCALLS#0+(byte) 1
Constant inlined main::i#0 = (byte) 0
Constant inlined main::i#2 = (byte) 0
Constant inlined $0 = &(void()) fn1()
Constant inlined $1 = <&(void()) fn1()
Constant inlined $2 = &(void()) fn1()
Constant inlined $3 = >&(void()) fn1()
Successful SSA optimization Pass2ConstantInlining
Eliminating unused constant (const byte) SIZEOF_WORD
Successful SSA optimization PassNEliminateUnusedVars
@ -359,11 +339,9 @@ Allocated zp ZP_WORD:5 [ main::fn#0 ]
INITIAL ASM
Target platform is custom
// File Comments
// Example showing how to perform linking using a linker-file
// The linker file is created using KickAssembler segments.
// See the KickAssembler manual for description of the format http://theweb.dk/KickAssembler/
// Specifying the linker script file is done using the #pragma link(<file>)
// It can also be specified using kickc command line option -T <file>
// XMega65 Kernal Development Template
// Each function of the kernal is a no-args function
// The functions are placed in the SYSCALLS table surrounded by JMP and NOP
// Upstart
.file [name="xmega65.bin", type="bin", segments="XMega65Bin"]
.segmentdef XMega65Bin [segments="Syscall, Code, Data, Stack, Zeropage"]
@ -406,6 +384,7 @@ main: {
lda #0
sta.z i
jmp b1
// Call functions one at a time
// main::@1
b1:
jmp b2
@ -470,22 +449,22 @@ fn1: {
}
// File Data
.segment Syscall
SYSCALLS: .byte JMP, <fn1, >fn1, NOP, JMP, <fn2, >fn2, NOP, JMP, <main, >main, NOP
SYSCALLS: .byte JMP, <fn1, >fn1, NOP, JMP, <fn2, >fn2, NOP
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [6] (byte~) main::$0 ← (byte) main::i#3 << (byte) 1 [ main::i#3 main::$0 ] ( [ main::i#3 main::$0 ] main:2 [ main::i#3 main::$0 ] ) always clobbers reg byte a
Statement [6] (byte~) main::$0 ← (byte) main::i#3 << (byte) 1 [ main::i#3 main::$0 ] ( main:2 [ main::i#3 main::$0 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::i#3 main::i#1 ]
Statement [7] (byte~) main::$5 ← (byte~) main::$0 << (byte) 1 [ main::i#3 main::$5 ] ( [ main::i#3 main::$5 ] main:2 [ main::i#3 main::$5 ] ) always clobbers reg byte a
Statement [8] (word) main::fn#0 ← *((const word*) CALLS#0 + (byte~) main::$5) [ main::i#3 main::fn#0 ] ( [ main::i#3 main::fn#0 ] main:2 [ main::i#3 main::fn#0 ] ) always clobbers reg byte a
Statement [9] call *((void()*)(word) main::fn#0) [ main::i#3 ] ( [ main::i#3 ] main:2 [ main::i#3 ] ) always clobbers reg byte a reg byte x reg byte y
Statement [7] (byte~) main::$5 ← (byte~) main::$0 << (byte) 1 [ main::i#3 main::$5 ] ( main:2 [ main::i#3 main::$5 ] ) always clobbers reg byte a
Statement [8] (word) main::fn#0 ← *((const word*) CALLS#0 + (byte~) main::$5) [ main::i#3 main::fn#0 ] ( main:2 [ main::i#3 main::fn#0 ] ) always clobbers reg byte a
Statement [9] call *((void()*)(word) main::fn#0) [ main::i#3 ] ( main:2 [ main::i#3 ] ) always clobbers reg byte a reg byte x reg byte y
Removing always clobbered register reg byte x as potential for zp ZP_BYTE:2 [ main::i#3 main::i#1 ]
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:2 [ main::i#3 main::i#1 ]
Statement [11] if((byte) main::i#1!=(byte) 2) goto main::@3 [ main::i#1 ] ( [ main::i#1 ] main:2 [ main::i#1 ] ) always clobbers reg byte a
Statement [6] (byte~) main::$0 ← (byte) main::i#3 << (byte) 1 [ main::i#3 main::$0 ] ( [ main::i#3 main::$0 ] main:2 [ main::i#3 main::$0 ] ) always clobbers reg byte a
Statement [7] (byte~) main::$5 ← (byte~) main::$0 << (byte) 1 [ main::i#3 main::$5 ] ( [ main::i#3 main::$5 ] main:2 [ main::i#3 main::$5 ] ) always clobbers reg byte a
Statement [8] (word) main::fn#0 ← *((const word*) CALLS#0 + (byte~) main::$5) [ main::i#3 main::fn#0 ] ( [ main::i#3 main::fn#0 ] main:2 [ main::i#3 main::fn#0 ] ) always clobbers reg byte a
Statement [9] call *((void()*)(word) main::fn#0) [ main::i#3 ] ( [ main::i#3 ] main:2 [ main::i#3 ] ) always clobbers reg byte a reg byte x reg byte y
Statement [11] if((byte) main::i#1!=(byte) 2) goto main::@3 [ main::i#1 ] ( [ main::i#1 ] main:2 [ main::i#1 ] ) always clobbers reg byte a
Statement [11] if((byte) main::i#1!=(byte) 2) goto main::@3 [ main::i#1 ] ( main:2 [ main::i#1 ] ) always clobbers reg byte a
Statement [6] (byte~) main::$0 ← (byte) main::i#3 << (byte) 1 [ main::i#3 main::$0 ] ( main:2 [ main::i#3 main::$0 ] ) always clobbers reg byte a
Statement [7] (byte~) main::$5 ← (byte~) main::$0 << (byte) 1 [ main::i#3 main::$5 ] ( main:2 [ main::i#3 main::$5 ] ) always clobbers reg byte a
Statement [8] (word) main::fn#0 ← *((const word*) CALLS#0 + (byte~) main::$5) [ main::i#3 main::fn#0 ] ( main:2 [ main::i#3 main::fn#0 ] ) always clobbers reg byte a
Statement [9] call *((void()*)(word) main::fn#0) [ main::i#3 ] ( main:2 [ main::i#3 ] ) always clobbers reg byte a reg byte x reg byte y
Statement [11] if((byte) main::i#1!=(byte) 2) goto main::@3 [ main::i#1 ] ( main:2 [ main::i#1 ] ) always clobbers reg byte a
Potential registers zp ZP_BYTE:2 [ main::i#3 main::i#1 ] : zp ZP_BYTE:2 ,
Potential registers zp ZP_BYTE:3 [ main::$0 ] : zp ZP_BYTE:3 , reg byte a , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:4 [ main::$5 ] : zp ZP_BYTE:4 , reg byte a , reg byte x , reg byte y ,
@ -507,11 +486,9 @@ Allocated (was zp ZP_WORD:5) zp ZP_WORD:3 [ main::fn#0 ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Example showing how to perform linking using a linker-file
// The linker file is created using KickAssembler segments.
// See the KickAssembler manual for description of the format http://theweb.dk/KickAssembler/
// Specifying the linker script file is done using the #pragma link(<file>)
// It can also be specified using kickc command line option -T <file>
// XMega65 Kernal Development Template
// Each function of the kernal is a no-args function
// The functions are placed in the SYSCALLS table surrounded by JMP and NOP
// Upstart
.file [name="xmega65.bin", type="bin", segments="XMega65Bin"]
.segmentdef XMega65Bin [segments="Syscall, Code, Data, Stack, Zeropage"]
@ -552,6 +529,7 @@ main: {
lda #0
sta.z i
jmp b1
// Call functions one at a time
// main::@1
b1:
jmp b2
@ -613,7 +591,7 @@ fn1: {
}
// File Data
.segment Syscall
SYSCALLS: .byte JMP, <fn1, >fn1, NOP, JMP, <fn2, >fn2, NOP, JMP, <main, >main, NOP
SYSCALLS: .byte JMP, <fn1, >fn1, NOP, JMP, <fn2, >fn2, NOP
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b1
@ -662,7 +640,7 @@ FINAL SYMBOL TABLE
(byte) NOP
(const byte) NOP#0 NOP = (byte) $ea
(byte[]) SYSCALLS
(const byte[]) SYSCALLS#0 SYSCALLS = { (const byte) JMP#0, <&(void()) fn1(), >&(void()) fn1(), (const byte) NOP#0, (const byte) JMP#0, <&(void()) fn2(), >&(void()) fn2(), (const byte) NOP#0, (const byte) JMP#0, <&(void()) main(), >&(void()) main(), (const byte) NOP#0 }
(const byte[]) SYSCALLS#0 SYSCALLS = { (const byte) JMP#0, <&(void()) fn1(), >&(void()) fn1(), (const byte) NOP#0, (const byte) JMP#0, <&(void()) fn2(), >&(void()) fn2(), (const byte) NOP#0 }
(void()) fn1()
(label) fn1::@return
(byte*) fn1::BORDERCOL
@ -694,11 +672,9 @@ FINAL ASSEMBLER
Score: 5574
// File Comments
// Example showing how to perform linking using a linker-file
// The linker file is created using KickAssembler segments.
// See the KickAssembler manual for description of the format http://theweb.dk/KickAssembler/
// Specifying the linker script file is done using the #pragma link(<file>)
// It can also be specified using kickc command line option -T <file>
// XMega65 Kernal Development Template
// Each function of the kernal is a no-args function
// The functions are placed in the SYSCALLS table surrounded by JMP and NOP
// Upstart
.file [name="xmega65.bin", type="bin", segments="XMega65Bin"]
.segmentdef XMega65Bin [segments="Syscall, Code, Data, Stack, Zeropage"]
@ -728,6 +704,7 @@ main: {
// [5] phi (byte) main::i#3 = (byte) 0 [phi:main/main::@2->main::@1#0] -- vbuz1=vbuc1
lda #0
sta.z i
// Call functions one at a time
// main::@1
// main::@2
b2:
@ -786,5 +763,5 @@ fn1: {
}
// File Data
.segment Syscall
SYSCALLS: .byte JMP, <fn1, >fn1, NOP, JMP, <fn2, >fn2, NOP, JMP, <main, >main, NOP
SYSCALLS: .byte JMP, <fn1, >fn1, NOP, JMP, <fn2, >fn2, NOP

View File

@ -8,7 +8,7 @@
(byte) NOP
(const byte) NOP#0 NOP = (byte) $ea
(byte[]) SYSCALLS
(const byte[]) SYSCALLS#0 SYSCALLS = { (const byte) JMP#0, <&(void()) fn1(), >&(void()) fn1(), (const byte) NOP#0, (const byte) JMP#0, <&(void()) fn2(), >&(void()) fn2(), (const byte) NOP#0, (const byte) JMP#0, <&(void()) main(), >&(void()) main(), (const byte) NOP#0 }
(const byte[]) SYSCALLS#0 SYSCALLS = { (const byte) JMP#0, <&(void()) fn1(), >&(void()) fn1(), (const byte) NOP#0, (const byte) JMP#0, <&(void()) fn2(), >&(void()) fn2(), (const byte) NOP#0 }
(void()) fn1()
(label) fn1::@return
(byte*) fn1::BORDERCOL