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
rts
.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 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)
}
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)
}
DataType.FLOAT -> {
pushFloatAddress(arg.first)
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")
}
}
@ -1005,13 +1009,17 @@ private class StatementTranslator(private val prog: IntermediateProgram,
prog.instr(Opcode.POP_REGAY_WORD)
}
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)
}
DataType.FLOAT -> {
pushFloatAddress(arg.first)
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")
}
}
@ -1039,13 +1047,17 @@ private class StatementTranslator(private val prog: IntermediateProgram,
prog.instr(Opcode.POP_REGXY_WORD)
}
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)
}
DataType.FLOAT -> {
pushFloatAddress(arg.first)
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")
}
}
@ -1491,10 +1503,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
private fun pushStringAddress(value: IExpression, removeLastOpcode: Boolean) {
when (value) {
is LiteralValue -> {
if(removeLastOpcode) prog.removeLastInstruction()
prog.instr(Opcode.PUSH_ADDR_STR, Value(value.type, value.heapId!!))
}
is LiteralValue -> throw CompilerException("can only push address of string that is a variable on the heap")
is IdentifierReference -> {
val vardecl = value.targetStatement(namespace) as VarDecl
if(removeLastOpcode) prog.removeLastInstruction()
@ -1506,9 +1515,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
private fun pushFloatAddress(value: IExpression) {
when (value) {
is LiteralValue -> {
prog.instr(Opcode.PUSH_ADDR_FLOAT, Value(value.type, value.floatvalue!!))
}
is LiteralValue -> throw CompilerException("can only push address of float that is a variable on the heap")
is IdentifierReference -> {
val vardecl = value.targetStatement(namespace) as VarDecl
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_REGAY_WORD, // push registers A/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)
// 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 -> {
" 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_REGXY_WORD -> throw AssemblyError("cannot load X register from stack because it's used as the stack pointer itself")
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.SHR_UBYTE -> AsmFragment(" lsr $variable+$index", 8)
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.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.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_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.ROR_BYTE -> AsmFragment(" ror $variable+$index", 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.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.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.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.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.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.INC_INDEXED_VAR_W -> TODO("inc array_w")
Opcode.INC_INDEXED_VAR_UW -> TODO("inc array_uw")
Opcode.INC_INDEXED_VAR_FLOAT -> TODO("inc array_f")
Opcode.DEC_INDEXED_VAR_W -> TODO("dec array_w")
Opcode.DEC_INDEXED_VAR_UW -> TODO("dec array_uw")
Opcode.DEC_INDEXED_VAR_FLOAT -> TODO("dec array_f")
Opcode.INC_INDEXED_VAR_W, Opcode.INC_INDEXED_VAR_UW -> AsmFragment(" inc $variable+${index*2} | bne + | inc $variable+${index*2+1} |+")
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 -> AsmFragment(
"""
lda #<($variable+${index*Mflpt5.MemorySize})
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
}
}
@ -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.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.INC_INDEXED_VAR_W -> TODO("inc array_w")
Opcode.INC_INDEXED_VAR_UW -> AsmFragment("$saveX $loadXWord inc $variable,x | bne + | inc $variable+1,x |+ $restoreX", 10)
Opcode.INC_INDEXED_VAR_FLOAT -> TODO("inc array_f")
Opcode.DEC_INDEXED_VAR_W -> TODO("dec array_w")
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")
Opcode.INC_INDEXED_VAR_W, 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 -> AsmFragment(" lda #<$variable | ldy #>$variable | $saveX $loadX jsr c64flt.inc_indexed_var_f $restoreX")
Opcode.DEC_INDEXED_VAR_FLOAT -> AsmFragment(" lda #<$variable | ldy #>$variable | $saveX $loadX jsr c64flt.dec_indexed_var_f $restoreX")
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 ->
" 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
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 ->
val amount = segment[0].arg!!.integerValue()
if(amount in 1..2) {

View File

@ -1497,17 +1497,6 @@ class StackVm(private var traceOutputFile: String?) {
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)
}
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_W_TO_B -> typecast(DataType.WORD, DataType.BYTE)
Opcode.CAST_UW_TO_B -> typecast(DataType.UWORD, DataType.BYTE)

View File

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