mirror of
https://github.com/irmen/prog8.git
synced 2024-11-26 11:49:22 +00:00
float ++/-- and missing asm code handlers added
This commit is contained in:
parent
0b86af0c4e
commit
f3c9be4e06
@ -491,6 +491,43 @@ dec_var_f .proc
|
||||
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
|
||||
lda #<fmath_float2
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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() -> () {
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user