float ++/-- and missing asm code handlers added

This commit is contained in:
Irmen de Jong 2019-01-12 14:55:57 +01:00
parent 0b86af0c4e
commit f3c9be4e06
6 changed files with 116 additions and 113 deletions

View File

@ -490,6 +490,43 @@ dec_var_f .proc
ldx c64.SCRATCH_ZPREGX ldx c64.SCRATCH_ZPREGX
rts rts
.pend .pend
inc_indexed_var_f .proc
; -- add 1 to float in array pointed to by A/Y, at index X
pha
txa
sta c64.SCRATCH_ZPB1
asl a
asl a
clc
adc c64.SCRATCH_ZPB1
sta c64.SCRATCH_ZPB1
pla
clc
adc c64.SCRATCH_ZPB1
bcc +
iny
+ jmp inc_var_f
.pend
dec_indexed_var_f .proc
; -- subtract 1 to float in array pointed to by A/Y, at index X
pha
txa
sta c64.SCRATCH_ZPB1
asl a
asl a
clc
adc c64.SCRATCH_ZPB1
sta c64.SCRATCH_ZPB1
pla
clc
adc c64.SCRATCH_ZPB1
bcc +
iny
+ jmp dec_var_f
.pend
pop_2_floats_f2_in_fac1 .proc pop_2_floats_f2_in_fac1 .proc
; -- pop 2 floats from stack, load the second one in FAC1 as well ; -- pop 2 floats from stack, load the second one in FAC1 as well

View File

@ -975,13 +975,17 @@ private class StatementTranslator(private val prog: IntermediateProgram,
prog.instr(Opcode.POP_REGAX_WORD) prog.instr(Opcode.POP_REGAX_WORD)
} }
DataType.STR, DataType.STR_S -> { DataType.STR, DataType.STR_S -> {
pushStringAddress(arg.first, false) // TODO with or without remove last opcode?? pushStringAddress(arg.first, false)
prog.instr(Opcode.POP_REGAX_WORD) prog.instr(Opcode.POP_REGAX_WORD)
} }
DataType.FLOAT -> { DataType.FLOAT -> {
pushFloatAddress(arg.first) pushFloatAddress(arg.first)
prog.instr(Opcode.POP_REGAX_WORD) prog.instr(Opcode.POP_REGAX_WORD)
} }
in ArrayDatatypes -> {
pushStringAddress(arg.first, false)
prog.instr(Opcode.POP_REGAX_WORD)
}
else -> TODO("pass parameter of type $paramDt in registers AX at $callPosition") else -> TODO("pass parameter of type $paramDt in registers AX at $callPosition")
} }
} }
@ -1005,13 +1009,17 @@ private class StatementTranslator(private val prog: IntermediateProgram,
prog.instr(Opcode.POP_REGAY_WORD) prog.instr(Opcode.POP_REGAY_WORD)
} }
DataType.STR, DataType.STR_S -> { DataType.STR, DataType.STR_S -> {
pushStringAddress(arg.first, false) // TODO with or without remove last opcode?? pushStringAddress(arg.first, false)
prog.instr(Opcode.POP_REGAY_WORD) prog.instr(Opcode.POP_REGAY_WORD)
} }
DataType.FLOAT -> { DataType.FLOAT -> {
pushFloatAddress(arg.first) pushFloatAddress(arg.first)
prog.instr(Opcode.POP_REGAY_WORD) prog.instr(Opcode.POP_REGAY_WORD)
} }
in ArrayDatatypes -> {
pushStringAddress(arg.first, false)
prog.instr(Opcode.POP_REGAY_WORD)
}
else -> TODO("pass parameter of type $paramDt in registers AY at $callPosition") else -> TODO("pass parameter of type $paramDt in registers AY at $callPosition")
} }
} }
@ -1039,13 +1047,17 @@ private class StatementTranslator(private val prog: IntermediateProgram,
prog.instr(Opcode.POP_REGXY_WORD) prog.instr(Opcode.POP_REGXY_WORD)
} }
DataType.STR, DataType.STR_S -> { DataType.STR, DataType.STR_S -> {
pushStringAddress(arg.first, false) // TODO with or without remove last opcode?? pushStringAddress(arg.first, false)
prog.instr(Opcode.POP_REGXY_WORD) prog.instr(Opcode.POP_REGXY_WORD)
} }
DataType.FLOAT -> { DataType.FLOAT -> {
pushFloatAddress(arg.first) pushFloatAddress(arg.first)
prog.instr(Opcode.POP_REGXY_WORD) prog.instr(Opcode.POP_REGXY_WORD)
} }
in ArrayDatatypes -> {
pushStringAddress(arg.first, false)
prog.instr(Opcode.POP_REGXY_WORD)
}
else -> TODO("pass parameter of type $paramDt in registers XY at $callPosition") else -> TODO("pass parameter of type $paramDt in registers XY at $callPosition")
} }
} }
@ -1491,10 +1503,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
private fun pushStringAddress(value: IExpression, removeLastOpcode: Boolean) { private fun pushStringAddress(value: IExpression, removeLastOpcode: Boolean) {
when (value) { when (value) {
is LiteralValue -> { is LiteralValue -> throw CompilerException("can only push address of string that is a variable on the heap")
if(removeLastOpcode) prog.removeLastInstruction()
prog.instr(Opcode.PUSH_ADDR_STR, Value(value.type, value.heapId!!))
}
is IdentifierReference -> { is IdentifierReference -> {
val vardecl = value.targetStatement(namespace) as VarDecl val vardecl = value.targetStatement(namespace) as VarDecl
if(removeLastOpcode) prog.removeLastInstruction() if(removeLastOpcode) prog.removeLastInstruction()
@ -1506,9 +1515,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
private fun pushFloatAddress(value: IExpression) { private fun pushFloatAddress(value: IExpression) {
when (value) { when (value) {
is LiteralValue -> { is LiteralValue -> throw CompilerException("can only push address of float that is a variable on the heap")
prog.instr(Opcode.PUSH_ADDR_FLOAT, Value(value.type, value.floatvalue!!))
}
is IdentifierReference -> { is IdentifierReference -> {
val vardecl = value.targetStatement(namespace) as VarDecl val vardecl = value.targetStatement(namespace) as VarDecl
prog.instr(Opcode.PUSH_ADDR_HEAPVAR, callLabel = vardecl.scopedname) prog.instr(Opcode.PUSH_ADDR_HEAPVAR, callLabel = vardecl.scopedname)

View File

@ -18,8 +18,6 @@ enum class Opcode {
PUSH_REGAX_WORD, // push registers A/X as a 16-bit word PUSH_REGAX_WORD, // push registers A/X as a 16-bit word
PUSH_REGAY_WORD, // push registers A/Y as a 16-bit word PUSH_REGAY_WORD, // push registers A/Y as a 16-bit word
PUSH_REGXY_WORD, // push registers X/Y as a 16-bit word PUSH_REGXY_WORD, // push registers X/Y as a 16-bit word
PUSH_ADDR_STR, // push the address of the string value (literal)
PUSH_ADDR_FLOAT, // push the address of the float value (literal)
PUSH_ADDR_HEAPVAR, // push the address of the variable that's on the heap (string or array) PUSH_ADDR_HEAPVAR, // push the address of the variable that's on the heap (string or array)
// popping values off the (evaluation) stack, possibly storing them in another location // popping values off the (evaluation) stack, possibly storing them in another location

View File

@ -580,10 +580,6 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
Opcode.PUSH_ADDR_HEAPVAR -> { Opcode.PUSH_ADDR_HEAPVAR -> {
" lda #<${ins.callLabel} | sta ${ESTACK_LO.toHex()},x | lda #>${ins.callLabel} | sta ${ESTACK_HI.toHex()},x | dex" " lda #<${ins.callLabel} | sta ${ESTACK_LO.toHex()},x | lda #>${ins.callLabel} | sta ${ESTACK_HI.toHex()},x | dex"
} }
Opcode.PUSH_ADDR_FLOAT -> {
val varname = getFloatConst(ins.arg!!)
" lda #<$varname | sta ${ESTACK_LO.toHex()},x | lda #>$varname | sta ${ESTACK_HI.toHex()},x | dex"
}
Opcode.POP_REGAX_WORD -> throw AssemblyError("cannot load X register from stack because it's used as the stack pointer itself") Opcode.POP_REGAX_WORD -> throw AssemblyError("cannot load X register from stack because it's used as the stack pointer itself")
Opcode.POP_REGXY_WORD -> throw AssemblyError("cannot load X register from stack because it's used as the stack pointer itself") Opcode.POP_REGXY_WORD -> throw AssemblyError("cannot load X register from stack because it's used as the stack pointer itself")
Opcode.POP_REGAY_WORD -> { Opcode.POP_REGAY_WORD -> {
@ -1047,25 +1043,34 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
Opcode.SHL_BYTE -> AsmFragment(" asl $variable+$index", 8) Opcode.SHL_BYTE -> AsmFragment(" asl $variable+$index", 8)
Opcode.SHR_UBYTE -> AsmFragment(" lsr $variable+$index", 8) Opcode.SHR_UBYTE -> AsmFragment(" lsr $variable+$index", 8)
Opcode.SHR_SBYTE -> AsmFragment(" lda $variable+$index | asl a | ror $variable+$index") Opcode.SHR_SBYTE -> AsmFragment(" lda $variable+$index | asl a | ror $variable+$index")
Opcode.SHL_WORD -> AsmFragment(" asl $variable+${index*2+1} | rol $variable+$index*2", 8) Opcode.SHL_WORD -> AsmFragment(" asl $variable+${index*2+1} | rol $variable+${index*2}", 8)
Opcode.SHR_UWORD -> AsmFragment(" lsr $variable+${index*2+1} | ror $variable+$index*2", 8) Opcode.SHR_UWORD -> AsmFragment(" lsr $variable+${index*2+1} | ror $variable+${index*2}", 8)
Opcode.SHR_SWORD -> AsmFragment(" lda $variable+${index*2+1} | asl a | ror $variable+${index*2+1} | ror $variable+$index*2", 8) Opcode.SHR_SWORD -> AsmFragment(" lda $variable+${index*2+1} | asl a | ror $variable+${index*2+1} | ror $variable+${index*2}", 8)
Opcode.ROL_BYTE -> AsmFragment(" rol $variable+$index", 8) Opcode.ROL_BYTE -> AsmFragment(" rol $variable+$index", 8)
Opcode.ROR_BYTE -> AsmFragment(" ror $variable+$index", 8) Opcode.ROR_BYTE -> AsmFragment(" ror $variable+$index", 8)
Opcode.ROL_WORD -> AsmFragment(" rol $variable+${index*2+1} | rol $variable+$index*2", 8) Opcode.ROL_WORD -> AsmFragment(" rol $variable+${index*2+1} | rol $variable+${index*2}", 8)
Opcode.ROR_WORD -> AsmFragment(" ror $variable+${index*2+1} | ror $variable+$index*2", 8) Opcode.ROR_WORD -> AsmFragment(" ror $variable+${index*2+1} | ror $variable+${index*2}", 8)
Opcode.ROL2_BYTE -> AsmFragment(" lda $variable+$index | cmp #\$80 | rol $variable+$index", 8) Opcode.ROL2_BYTE -> AsmFragment(" lda $variable+$index | cmp #\$80 | rol $variable+$index", 8)
Opcode.ROR2_BYTE -> AsmFragment(" lda $variable+$index | lsr a | bcc + | ora #\$80 |+ | sta $variable+$index", 10) Opcode.ROR2_BYTE -> AsmFragment(" lda $variable+$index | lsr a | bcc + | ora #\$80 |+ | sta $variable+$index", 10)
Opcode.ROL2_WORD -> AsmFragment(" asl $variable+${index*2+1} | rol $variable+$index*2 | bcc + | inc $variable+$index*2+1 |+",20) Opcode.ROL2_WORD -> AsmFragment(" asl $variable+${index*2+1} | rol $variable+${index*2} | bcc + | inc $variable+${index*2+1} |+",20)
Opcode.ROR2_WORD -> AsmFragment(" lsr $variable+${index*2+1} | ror $variable+$index*2 | bcc + | lda $variable+${index*2+1} | ora #\$80 | sta $variable+${index*2+1} |+", 30) Opcode.ROR2_WORD -> AsmFragment(" lsr $variable+${index*2+1} | ror $variable+${index*2} | bcc + | lda $variable+${index*2+1} | ora #\$80 | sta $variable+${index*2+1} |+", 30)
Opcode.INC_INDEXED_VAR_B, Opcode.INC_INDEXED_VAR_UB -> AsmFragment(" inc $variable+$index", 2) Opcode.INC_INDEXED_VAR_B, Opcode.INC_INDEXED_VAR_UB -> AsmFragment(" inc $variable+$index", 2)
Opcode.DEC_INDEXED_VAR_B, Opcode.DEC_INDEXED_VAR_UB -> AsmFragment(" dec $variable+$index", 5) Opcode.DEC_INDEXED_VAR_B, Opcode.DEC_INDEXED_VAR_UB -> AsmFragment(" dec $variable+$index", 5)
Opcode.INC_INDEXED_VAR_W -> TODO("inc array_w") Opcode.INC_INDEXED_VAR_W, Opcode.INC_INDEXED_VAR_UW -> AsmFragment(" inc $variable+${index*2} | bne + | inc $variable+${index*2+1} |+")
Opcode.INC_INDEXED_VAR_UW -> TODO("inc array_uw") Opcode.DEC_INDEXED_VAR_W, Opcode.DEC_INDEXED_VAR_UW -> AsmFragment(" lda $variable+${index*2} | bne + | dec $variable+${index*2+1} |+ | dec $variable+${index*2}")
Opcode.INC_INDEXED_VAR_FLOAT -> TODO("inc array_f") Opcode.INC_INDEXED_VAR_FLOAT -> AsmFragment(
Opcode.DEC_INDEXED_VAR_W -> TODO("dec array_w") """
Opcode.DEC_INDEXED_VAR_UW -> TODO("dec array_uw") lda #<($variable+${index*Mflpt5.MemorySize})
Opcode.DEC_INDEXED_VAR_FLOAT -> TODO("dec array_f") ldy #>($variable+${index*Mflpt5.MemorySize})
jsr c64flt.inc_var_f
""")
Opcode.DEC_INDEXED_VAR_FLOAT -> AsmFragment(
"""
lda #<($variable+${index*Mflpt5.MemorySize})
ldy #>($variable+${index*Mflpt5.MemorySize})
jsr c64flt.dec_var_f
""")
else -> null else -> null
} }
} }
@ -1114,12 +1119,10 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
Opcode.ROR2_WORD -> AsmFragment("$saveX $loadXWord lsr $variable+1,x | ror $variable,x | bcc + | lda $variable+1,x | ora #\$80 | sta $variable+1,x |+ $restoreX", 30) Opcode.ROR2_WORD -> AsmFragment("$saveX $loadXWord lsr $variable+1,x | ror $variable,x | bcc + | lda $variable+1,x | ora #\$80 | sta $variable+1,x |+ $restoreX", 30)
Opcode.INC_INDEXED_VAR_B, Opcode.INC_INDEXED_VAR_UB -> AsmFragment(" txa | $loadX inc $variable,x | tax", 10) Opcode.INC_INDEXED_VAR_B, Opcode.INC_INDEXED_VAR_UB -> AsmFragment(" txa | $loadX inc $variable,x | tax", 10)
Opcode.DEC_INDEXED_VAR_B, Opcode.DEC_INDEXED_VAR_UB -> AsmFragment(" txa | $loadX dec $variable,x | tax", 10) Opcode.DEC_INDEXED_VAR_B, Opcode.DEC_INDEXED_VAR_UB -> AsmFragment(" txa | $loadX dec $variable,x | tax", 10)
Opcode.INC_INDEXED_VAR_W -> TODO("inc array_w") Opcode.INC_INDEXED_VAR_W, Opcode.INC_INDEXED_VAR_UW -> AsmFragment("$saveX $loadXWord inc $variable,x | bne + | inc $variable+1,x |+ $restoreX", 10)
Opcode.INC_INDEXED_VAR_UW -> AsmFragment("$saveX $loadXWord inc $variable,x | bne + | inc $variable+1,x |+ $restoreX", 10) Opcode.DEC_INDEXED_VAR_W, Opcode.DEC_INDEXED_VAR_UW -> AsmFragment("$saveX $loadXWord lda $variable,x | bne + | dec $variable+1,x |+ | dec $variable,x $restoreX", 10)
Opcode.INC_INDEXED_VAR_FLOAT -> TODO("inc array_f") Opcode.INC_INDEXED_VAR_FLOAT -> AsmFragment(" lda #<$variable | ldy #>$variable | $saveX $loadX jsr c64flt.inc_indexed_var_f $restoreX")
Opcode.DEC_INDEXED_VAR_W -> TODO("dec array_w") Opcode.DEC_INDEXED_VAR_FLOAT -> AsmFragment(" lda #<$variable | ldy #>$variable | $saveX $loadX jsr c64flt.dec_indexed_var_f $restoreX")
Opcode.DEC_INDEXED_VAR_UW -> AsmFragment("$saveX $loadXWord lda $variable,x | bne + | dec $variable+1,x |+ | dec $variable,x $restoreX", 10)
Opcode.DEC_INDEXED_VAR_FLOAT -> TODO("dec array_f")
else -> null else -> null
} }
@ -2995,29 +2998,6 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
AsmPattern(listOf(Opcode.PUSH_ADDR_HEAPVAR, Opcode.POP_REGXY_WORD)) { segment -> AsmPattern(listOf(Opcode.PUSH_ADDR_HEAPVAR, Opcode.POP_REGXY_WORD)) { segment ->
" ldx #<${segment[0].callLabel} | ldy #>${segment[0].callLabel} " " ldx #<${segment[0].callLabel} | ldy #>${segment[0].callLabel} "
}, },
// set a register pair to a certain memory address (of a floating point value)
AsmPattern(listOf(Opcode.PUSH_ADDR_FLOAT, Opcode.POP_REGAX_WORD)) { segment ->
val varname=getFloatConst(segment[0].arg!!)
" lda #<$varname | ldx #>$varname "
},
AsmPattern(listOf(Opcode.PUSH_ADDR_FLOAT, Opcode.POP_REGAY_WORD)) { segment ->
val varname=getFloatConst(segment[0].arg!!)
" lda #<$varname | ldy #>$varname "
},
AsmPattern(listOf(Opcode.PUSH_ADDR_FLOAT, Opcode.POP_REGXY_WORD)) { segment ->
val varname=getFloatConst(segment[0].arg!!)
" ldx #<$varname | ldy #>$varname "
},
// set a register pair to a certain memory address (of a literal string value)
AsmPattern(listOf(Opcode.PUSH_ADDR_STR, Opcode.POP_REGAX_WORD)) { segment ->
TODO("$segment")
},
AsmPattern(listOf(Opcode.PUSH_ADDR_STR, Opcode.POP_REGAY_WORD)) { segment ->
TODO("$segment")
},
AsmPattern(listOf(Opcode.PUSH_ADDR_STR, Opcode.POP_REGXY_WORD)) { segment ->
TODO("$segment")
},
// push memory byte | bytevalue // push memory byte | bytevalue
AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.PUSH_BYTE, Opcode.BITOR_BYTE), AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.PUSH_BYTE, Opcode.BITOR_BYTE),
@ -3183,7 +3163,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
""" """
}, },
// more efficient versions of x+1 and x-1 to avoid pushing the 1 on the stack @todo what about 1+x? reorder? // more efficient versions of x+1 and x-1 to avoid pushing the 1 on the stack
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.ADD_B), listOf(Opcode.PUSH_BYTE, Opcode.ADD_UB)) { segment -> AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.ADD_B), listOf(Opcode.PUSH_BYTE, Opcode.ADD_UB)) { segment ->
val amount = segment[0].arg!!.integerValue() val amount = segment[0].arg!!.integerValue()
if(amount in 1..2) { if(amount in 1..2) {

View File

@ -1497,17 +1497,6 @@ class StackVm(private var traceOutputFile: String?) {
throw VmExecutionException("expected variable on heap") throw VmExecutionException("expected variable on heap")
evalstack.push(Value(DataType.UWORD, heapId)) // push the "address" of the string or array variable (this is taken care of properly in the assembly code generator) evalstack.push(Value(DataType.UWORD, heapId)) // push the "address" of the string or array variable (this is taken care of properly in the assembly code generator)
} }
Opcode.PUSH_ADDR_STR -> {
val heapId = ins.arg!!.heapId
if(heapId<0)
throw VmExecutionException("expected string to be on heap")
evalstack.push(Value(DataType.UWORD, heapId)) // push the "address" of the string (this is taken care of properly in the assembly code generator)
}
Opcode.PUSH_ADDR_FLOAT -> {
val floatvalue = ins.arg!!
checkDt(floatvalue, DataType.FLOAT)
evalstack.push(Value(DataType.UWORD, floatvalue.numericValue().toInt() and 65535)) // push the "address" of the floating point value (this is taken care of properly in the assembly code generator)
}
Opcode.CAST_UB_TO_B -> typecast(DataType.UBYTE, DataType.BYTE) Opcode.CAST_UB_TO_B -> typecast(DataType.UBYTE, DataType.BYTE)
Opcode.CAST_W_TO_B -> typecast(DataType.WORD, DataType.BYTE) Opcode.CAST_W_TO_B -> typecast(DataType.WORD, DataType.BYTE)
Opcode.CAST_UW_TO_B -> typecast(DataType.UWORD, DataType.BYTE) Opcode.CAST_UW_TO_B -> typecast(DataType.UWORD, DataType.BYTE)

View File

@ -1,56 +1,48 @@
%import c64utils %import c64utils
%import c64flt
~ main { ~ main {
sub start() { sub start() {
byte b uword[4] uwa = 5
ubyte ub ubyte[4] uba = 5
memory ubyte mb = $c000 word[4] wa = 5
memory uword muw = $c000 byte[4] ba = 5
word w float[4] fa = 5.123
uword uw str naam = "irmen"
uword[4] uwa float ff = 3.4444
ub=%10001011 uword addr
for ubyte i in 0 to 10 {
c64scr.print_ubbin(1, ub)
rol2(ub)
c64.CHROUT('\n')
}
c64.CHROUT('\n')
uw=%1000101100001110 addr = naam
for ubyte i in 0 to 10 { addr = uwa
c64scr.print_uwbin(1, uw) addr = fa
rol2(uw)
c64.CHROUT('\n')
}
c64.CHROUT('\n')
muw=%1000101100001110 pairAX(naam)
for ubyte i in 0 to 10 { pairAX("hello")
c64scr.print_uwbin(1, muw) pairAX("hello2")
rol2(muw) pairAX("hello2")
c64.CHROUT('\n') pairAX("hello2")
} pairAY("hello2")
c64.CHROUT('\n') pairAY("hello2")
pairXY("hello2")
pairXY("hello2")
pairAX(uwa)
pairAX(fa)
pairAY(naam)
pairAY(uwa)
pairAY(fa)
pairXY(naam)
pairXY(uwa)
pairXY(fa)
ubyte x=2 }
uwa[x]=%1000101100001110
for ubyte i in 0 to 10 {
c64scr.print_uwbin(1, uwa[x])
rol2(uwa[x])
c64.CHROUT('\n')
}
c64.CHROUT('\n')
uwa[2]=%1000101100001110 asmsub pairAX(uword address @ AX) -> clobbers() -> () {
for ubyte i in 0 to 10 { }
c64scr.print_uwbin(1, uwa[2]) asmsub pairAY(uword address @ AY) -> clobbers() -> () {
rol2(uwa[2]) ; @todo wrong }
c64.CHROUT('\n') asmsub pairXY(uword address @ XY) -> clobbers() -> () {
}
c64.CHROUT('\n')
} }
} }