mirror of
https://github.com/irmen/prog8.git
synced 2025-01-12 19:29:50 +00:00
improved subroutine param ast checks, added asm for Carry parameter
This commit is contained in:
parent
b0dda08e74
commit
8e8c112ff0
@ -202,12 +202,12 @@ asmsub CINT () clobbers(A,X,Y) = $FF81 ; (alias: SCINIT) initialize scree
|
||||
asmsub IOINIT () clobbers(A, X) = $FF84 ; initialize I/O devices (CIA, SID, IRQ)
|
||||
asmsub RAMTAS () clobbers(A,X,Y) = $FF87 ; initialize RAM, tape buffer, screen
|
||||
asmsub RESTOR () clobbers(A,X,Y) = $FF8A ; restore default I/O vectors
|
||||
asmsub VECTOR (ubyte dir @ Pc, uword userptr @ XY) clobbers(A,Y) = $FF8D ; read/set I/O vector table
|
||||
asmsub VECTOR (uword userptr @ XY, ubyte dir @ Pc) clobbers(A,Y) = $FF8D ; read/set I/O vector table
|
||||
asmsub SETMSG (ubyte value @ A) = $FF90 ; set Kernal message control flag
|
||||
asmsub SECOND (ubyte address @ A) clobbers(A) = $FF93 ; (alias: LSTNSA) send secondary address after LISTEN
|
||||
asmsub TKSA (ubyte address @ A) clobbers(A) = $FF96 ; (alias: TALKSA) send secondary address after TALK
|
||||
asmsub MEMTOP (ubyte dir @ Pc, uword address @ XY) -> uword @ XY = $FF99 ; read/set top of memory pointer
|
||||
asmsub MEMBOT (ubyte dir @ Pc, uword address @ XY) -> uword @ XY = $FF9C ; read/set bottom of memory pointer
|
||||
asmsub MEMTOP (uword address @ XY, ubyte dir @ Pc) -> uword @ XY = $FF99 ; read/set top of memory pointer
|
||||
asmsub MEMBOT (uword address @ XY, ubyte dir @ Pc) -> uword @ XY = $FF9C ; read/set bottom of memory pointer
|
||||
asmsub SCNKEY () clobbers(A,X,Y) = $FF9F ; scan the keyboard
|
||||
asmsub SETTMO (ubyte timeout @ A) = $FFA2 ; set time-out flag for IEEE bus
|
||||
asmsub ACPTR () -> ubyte @ A = $FFA5 ; (alias: IECIN) input byte from serial bus
|
||||
@ -235,7 +235,7 @@ asmsub GETIN () clobbers(X,Y) -> ubyte @ A = $FFE4 ; (via 810 ($32A)) get a
|
||||
asmsub CLALL () clobbers(A,X) = $FFE7 ; (via 812 ($32C)) close all files
|
||||
asmsub UDTIM () clobbers(A,X) = $FFEA ; update the software clock
|
||||
asmsub SCREEN () -> ubyte @ X, ubyte @ Y = $FFED ; read number of screen rows and columns
|
||||
asmsub PLOT (ubyte dir @ Pc, ubyte col @ Y, ubyte row @ X) -> ubyte @ X, ubyte @ Y = $FFF0 ; read/set position of cursor on screen. Use c64scr.plot for a 'safe' wrapper that preserves X.
|
||||
asmsub PLOT (ubyte col @ Y, ubyte row @ X, ubyte dir @ Pc) -> ubyte @ X, ubyte @ Y = $FFF0 ; read/set position of cursor on screen. Use c64scr.plot for a 'safe' wrapper that preserves X.
|
||||
asmsub IOBASE () -> uword @ XY = $FFF3 ; read base address of I/O devices
|
||||
|
||||
; ---- end of C64 kernal routines ----
|
||||
|
@ -821,7 +821,7 @@ asmsub print_b (byte value @ A) clobbers(A,Y) {
|
||||
}
|
||||
|
||||
|
||||
asmsub print_ubhex (ubyte prefix @ Pc, ubyte value @ A) clobbers(A,Y) {
|
||||
asmsub print_ubhex (ubyte value @ A, ubyte prefix @ Pc) clobbers(A,Y) {
|
||||
; ---- print the ubyte in A in hex form (if Carry is set, a radix prefix '$' is printed as well)
|
||||
%asm {{
|
||||
stx c64.SCRATCH_ZPREGX
|
||||
@ -840,7 +840,7 @@ asmsub print_ubhex (ubyte prefix @ Pc, ubyte value @ A) clobbers(A,Y) {
|
||||
}
|
||||
|
||||
|
||||
asmsub print_ubbin (ubyte prefix @ Pc, ubyte value @ A) clobbers(A,Y) {
|
||||
asmsub print_ubbin (ubyte value @ A, ubyte prefix @ Pc) clobbers(A,Y) {
|
||||
; ---- print the ubyte in A in binary form (if Carry is set, a radix prefix '%' is printed as well)
|
||||
%asm {{
|
||||
stx c64.SCRATCH_ZPREGX
|
||||
@ -862,7 +862,7 @@ asmsub print_ubbin (ubyte prefix @ Pc, ubyte value @ A) clobbers(A,Y) {
|
||||
}
|
||||
|
||||
|
||||
asmsub print_uwbin (ubyte prefix @ Pc, uword value @ AY) clobbers(A,Y) {
|
||||
asmsub print_uwbin (uword value @ AY, ubyte prefix @ Pc) clobbers(A,Y) {
|
||||
; ---- print the uword in A/Y in binary form (if Carry is set, a radix prefix '%' is printed as well)
|
||||
%asm {{
|
||||
pha
|
||||
@ -875,7 +875,7 @@ asmsub print_uwbin (ubyte prefix @ Pc, uword value @ AY) clobbers(A,Y) {
|
||||
}
|
||||
|
||||
|
||||
asmsub print_uwhex (ubyte prefix @ Pc, uword value @ AY) clobbers(A,Y) {
|
||||
asmsub print_uwhex (uword value @ AY, ubyte prefix @ Pc) clobbers(A,Y) {
|
||||
; ---- print the uword in A/Y in hexadecimal form (4 digits)
|
||||
; (if Carry is set, a radix prefix '$' is printed as well)
|
||||
%asm {{
|
||||
|
@ -303,6 +303,18 @@ internal class AstChecker(private val program: Program,
|
||||
|
||||
if(subroutine.asmClobbers.intersect(regCounts.keys).isNotEmpty())
|
||||
err("a return register is also in the clobber list")
|
||||
|
||||
if(subroutine.statements.any{it !is InlineAssembly})
|
||||
err("asmsub can only contain inline assembly (%asm)")
|
||||
|
||||
val statusFlagsNoCarry = subroutine.asmParameterRegisters.mapNotNull { it.statusflag }.toSet() - Statusflag.Pc
|
||||
if(statusFlagsNoCarry.isNotEmpty())
|
||||
err("can only use Carry as status flag parameter")
|
||||
|
||||
val carryParameter = subroutine.asmParameterRegisters.singleOrNull { it.statusflag==Statusflag.Pc }
|
||||
if(carryParameter!=null && carryParameter !== subroutine.asmParameterRegisters.last())
|
||||
err("carry parameter has to come last")
|
||||
|
||||
} else {
|
||||
// TODO: non-asm subroutines can only take numeric arguments for now. (not strings and arrays) Maybe this can be improved now that we have '&' ?
|
||||
// the way string params are treated is almost okay (their address is passed) but the receiving subroutine treats it as an integer rather than referring back to the original string.
|
||||
|
@ -11,7 +11,7 @@ class AssemblyProgram(val name: String) {
|
||||
|
||||
companion object {
|
||||
// reserved by the 64tass assembler (on top of prog8"s own reserved names)
|
||||
val reservedNames = setOf("bit", "bits", "bool", "bytes", "code", "dict", "gap", "int", "list", "tuple", "type",
|
||||
val reservedNames = setOf("bits", "bool", "bytes", "code", "dict", "gap", "int", "list", "tuple", "type",
|
||||
"trunc", " frac", "cbrt", "log10", "log", "exp", "pow", "asin", "sinh", "acos", "cosh", "tanh", "hypot",
|
||||
"atan2", "sign", "binary", "format", "random", "range", "repr", "size", "sort")
|
||||
|
||||
|
@ -698,18 +698,62 @@ internal class AsmGen2(val program: Program,
|
||||
when {
|
||||
stack==true -> TODO("param on stack")
|
||||
statusflag!=null -> {
|
||||
if (statusflag == Statusflag.Pc) TODO("carry flag param")
|
||||
if (statusflag == Statusflag.Pc) {
|
||||
// TODO this param needs to be set last right before the jsr
|
||||
when(value) {
|
||||
is NumericLiteralValue -> {
|
||||
val carrySet = value.number.toInt() != 0
|
||||
out(if(carrySet) " sec" else " clc")
|
||||
}
|
||||
is IdentifierReference -> {
|
||||
val sourceName = asmIdentifierName(value)
|
||||
out("""
|
||||
lda $sourceName
|
||||
beq +
|
||||
sec
|
||||
bcs ++
|
||||
+ clc
|
||||
+
|
||||
""")
|
||||
}
|
||||
is RegisterExpr -> {
|
||||
when(value.register) {
|
||||
Register.A -> out(" cmp #0")
|
||||
Register.X -> out(" txa")
|
||||
Register.Y -> out(" tya")
|
||||
}
|
||||
out("""
|
||||
beq +
|
||||
sec
|
||||
bcs ++
|
||||
+ clc
|
||||
+
|
||||
""")
|
||||
}
|
||||
else -> {
|
||||
translateExpression(value)
|
||||
out("""
|
||||
inx
|
||||
lda $ESTACK_LO_HEX,x
|
||||
beq +
|
||||
sec
|
||||
bcs ++
|
||||
+ clc
|
||||
+
|
||||
""")
|
||||
}
|
||||
}
|
||||
}
|
||||
else throw AssemblyError("can only use Carry as status flag parameter")
|
||||
}
|
||||
register!=null && register.name.length==1 -> {
|
||||
val literal = value as? NumericLiteralValue
|
||||
when {
|
||||
literal!=null -> {
|
||||
when (value) {
|
||||
is NumericLiteralValue -> {
|
||||
val target = AssignTarget(Register.valueOf(register.name), null, null, null, sub.position)
|
||||
target.linkParents(value.parent)
|
||||
assignFromByteConstant(target, literal.number.toShort())
|
||||
assignFromByteConstant(target, value.number.toShort())
|
||||
}
|
||||
value is IdentifierReference -> {
|
||||
is IdentifierReference -> {
|
||||
val target = AssignTarget(Register.valueOf(register.name), null, null, null, sub.position)
|
||||
target.linkParents(value.parent)
|
||||
assignFromByteVariable(target, value)
|
||||
@ -727,30 +771,34 @@ internal class AsmGen2(val program: Program,
|
||||
}
|
||||
register!=null && register.name.length==2 -> {
|
||||
// register pair as a 16-bit value (only possible for subroutine parameters)
|
||||
val literal = value as? NumericLiteralValue
|
||||
if(literal!=null) {
|
||||
// optimize when the argument is a constant literal
|
||||
val hex = literal.number.toHex()
|
||||
if (register == RegisterOrPair.AX) out(" lda #<$hex | ldx #>$hex")
|
||||
else if (register == RegisterOrPair.AY) out(" lda #<$hex | ldy #>$hex")
|
||||
else if (register == RegisterOrPair.XY) out(" ldx #<$hex | ldy #>$hex")
|
||||
} else if(value is AddressOf) {
|
||||
// optimize when the argument is an address of something
|
||||
val sourceName = asmIdentifierName(value.identifier)
|
||||
if (register == RegisterOrPair.AX) out(" lda #<$sourceName | ldx #>$sourceName")
|
||||
else if (register == RegisterOrPair.AY) out(" lda #<$sourceName | ldy #>$sourceName")
|
||||
else if (register == RegisterOrPair.XY) out(" ldx #<$sourceName | ldy #>$sourceName")
|
||||
} else if(value is IdentifierReference) {
|
||||
val sourceName = asmIdentifierName(value)
|
||||
if (register == RegisterOrPair.AX) out(" lda #<$sourceName | ldx #>$sourceName")
|
||||
else if (register == RegisterOrPair.AY) out(" lda #<$sourceName | ldy #>$sourceName")
|
||||
else if (register == RegisterOrPair.XY) out(" ldx #<$sourceName | ldy #>$sourceName")
|
||||
} else {
|
||||
translateExpression(value)
|
||||
if (register == RegisterOrPair.AX || register == RegisterOrPair.XY)
|
||||
throw AssemblyError("can't use X register here - use a variable")
|
||||
else if (register == RegisterOrPair.AY)
|
||||
out(" inx | lda $ESTACK_LO_HEX,x | ldy $ESTACK_HI_HEX,x")
|
||||
when (value) {
|
||||
is NumericLiteralValue -> {
|
||||
// optimize when the argument is a constant literal
|
||||
val hex = value.number.toHex()
|
||||
if (register == RegisterOrPair.AX) out(" lda #<$hex | ldx #>$hex")
|
||||
else if (register == RegisterOrPair.AY) out(" lda #<$hex | ldy #>$hex")
|
||||
else if (register == RegisterOrPair.XY) out(" ldx #<$hex | ldy #>$hex")
|
||||
}
|
||||
is AddressOf -> {
|
||||
// optimize when the argument is an address of something
|
||||
val sourceName = asmIdentifierName(value.identifier)
|
||||
if (register == RegisterOrPair.AX) out(" lda #<$sourceName | ldx #>$sourceName")
|
||||
else if (register == RegisterOrPair.AY) out(" lda #<$sourceName | ldy #>$sourceName")
|
||||
else if (register == RegisterOrPair.XY) out(" ldx #<$sourceName | ldy #>$sourceName")
|
||||
}
|
||||
is IdentifierReference -> {
|
||||
val sourceName = asmIdentifierName(value)
|
||||
if (register == RegisterOrPair.AX) out(" lda #<$sourceName | ldx #>$sourceName")
|
||||
else if (register == RegisterOrPair.AY) out(" lda #<$sourceName | ldy #>$sourceName")
|
||||
else if (register == RegisterOrPair.XY) out(" ldx #<$sourceName | ldy #>$sourceName")
|
||||
}
|
||||
else -> {
|
||||
translateExpression(value)
|
||||
if (register == RegisterOrPair.AX || register == RegisterOrPair.XY)
|
||||
throw AssemblyError("can't use X register here - use a variable")
|
||||
else if (register == RegisterOrPair.AY)
|
||||
out(" inx | lda $ESTACK_LO_HEX,x | ldy $ESTACK_HI_HEX,x")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,30 @@
|
||||
~ main {
|
||||
|
||||
sub start() {
|
||||
ubyte zz
|
||||
|
||||
carry(0, 0)
|
||||
carry(1, 1)
|
||||
|
||||
A=0
|
||||
carry(2, A)
|
||||
A=1
|
||||
carry(3, A)
|
||||
|
||||
zz=0
|
||||
carry(4, zz)
|
||||
zz=122
|
||||
carry(5, zz)
|
||||
|
||||
carry(6, zz-122)
|
||||
carry(7, zz+34)
|
||||
|
||||
ubyte endX = X
|
||||
if endX == 255
|
||||
c64scr.print("\n\nstack x ok!\n")
|
||||
else
|
||||
c64scr.print("\n\nerror: stack x != 255 !\n")
|
||||
|
||||
carry(1)
|
||||
carry(0)
|
||||
; ubyte bb = @($d020)+4
|
||||
; ubyte bb2 = @($d020+A)+4
|
||||
;
|
||||
@ -18,12 +39,17 @@
|
||||
; subje(bb+43)
|
||||
}
|
||||
|
||||
sub carry(ubyte cc) {
|
||||
A=cc
|
||||
if A!=0
|
||||
c64scr.print("carry set\n")
|
||||
else
|
||||
c64scr.print("carry clear\n")
|
||||
asmsub carry(byte offset @Y, ubyte cc @Pc) {
|
||||
%asm {{
|
||||
bcc +
|
||||
lda #1
|
||||
sta $0400,y
|
||||
rts
|
||||
+
|
||||
lda #0
|
||||
sta $0400,y
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
sub subje(ubyte arg) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user