mirror of
https://github.com/irmen/prog8.git
synced 2025-11-23 14:17:51 +00:00
implement 6502 codegen for casting long to float
This commit is contained in:
@@ -3077,7 +3077,14 @@ $endLabel""")
|
||||
BaseDataType.BYTE -> asmgen.out(" jsr floats.cast_as_w_into_ay | sta $targetAsmVarName")
|
||||
BaseDataType.UWORD -> asmgen.out(" jsr floats.cast_as_uw_into_ya | sty $targetAsmVarName | sta $targetAsmVarName+1")
|
||||
BaseDataType.WORD -> asmgen.out(" jsr floats.cast_as_w_into_ay | sta $targetAsmVarName | sty $targetAsmVarName+1")
|
||||
BaseDataType.LONG -> TODO("cast float to long")
|
||||
BaseDataType.LONG -> {
|
||||
asmgen.out("""
|
||||
sta cx16.r0L
|
||||
sty cx16.r0H
|
||||
lda #<$targetAsmVarName
|
||||
ldy #>$targetAsmVarName
|
||||
jsr floats.internal_cast_as_long""")
|
||||
}
|
||||
else -> throw AssemblyError("weird type")
|
||||
}
|
||||
}
|
||||
@@ -3087,6 +3094,15 @@ $endLabel""")
|
||||
asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName")
|
||||
} else if(targetDt.isWord || targetDt.isPointer) {
|
||||
asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName | lda $sourceAsmVarName+1 | sta $targetAsmVarName+1")
|
||||
} else if(targetDt.isFloat) {
|
||||
asmgen.out("""
|
||||
lda #<$targetAsmVarName
|
||||
ldy #>$targetAsmVarName
|
||||
sta cx16.r0L
|
||||
sty cx16.r0H
|
||||
lda #<$sourceAsmVarName
|
||||
ldy #>$sourceAsmVarName
|
||||
jsr floats.internal_cast_from_long""")
|
||||
} else
|
||||
throw AssemblyError("weird type")
|
||||
}
|
||||
|
||||
@@ -302,4 +302,58 @@ sub interpolate(float v, float inputMin, float inputMax, float outputMin, float
|
||||
return v * (outputMax - outputMin) + outputMin
|
||||
}
|
||||
|
||||
|
||||
asmsub internal_cast_from_long(^^long lptr_src @AY, ^^float fptr_target @R0) {
|
||||
%asm {{
|
||||
; convert long pointed to by AY into a float pointed to by R0
|
||||
; algorithm: (msw(l) as word) as float * 65536.0 + (lsw(l) as float)
|
||||
; TODO optimize this by manipuliating the float memory bits directly
|
||||
sta P8ZP_SCRATCH_W1
|
||||
sty P8ZP_SCRATCH_W1+1
|
||||
ldy #3
|
||||
lda (P8ZP_SCRATCH_W1),y
|
||||
sta P8ZP_SCRATCH_REG
|
||||
dey
|
||||
lda (P8ZP_SCRATCH_W1),y
|
||||
ldy P8ZP_SCRATCH_REG
|
||||
jsr GIVAYFAY
|
||||
lda #<FL_65536_const
|
||||
ldy #>FL_65536_const
|
||||
jsr CONUPK
|
||||
jsr FMULTT
|
||||
jsr pushFAC1
|
||||
ldy #1
|
||||
lda (P8ZP_SCRATCH_W1),y
|
||||
sta P8ZP_SCRATCH_REG
|
||||
dey
|
||||
lda (P8ZP_SCRATCH_W1),y
|
||||
ldy P8ZP_SCRATCH_REG
|
||||
jsr GIVUAYFAY
|
||||
jsr MOVEF
|
||||
clc
|
||||
jsr popFAC
|
||||
jsr FADDT
|
||||
ldx cx16.r0L
|
||||
ldy cx16.r0H
|
||||
jmp MOVMF
|
||||
|
||||
FL_65536_const .byte $91, $00, $00, $00, $00 ; 65536.0
|
||||
; !notreached!
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub internal_cast_as_long(^^float fptr_src @R0, ^^long lptr_target @AY) {
|
||||
%asm {{
|
||||
; TODO actually implement this
|
||||
sta P8ZP_SCRATCH_W1
|
||||
sty P8ZP_SCRATCH_W1+1
|
||||
lda #0
|
||||
ldy #3
|
||||
- sta (P8ZP_SCRATCH_W1),y
|
||||
dey
|
||||
bpl -
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -497,8 +497,8 @@ internal class AstChecker(private val program: Program,
|
||||
errors.err("parameter '${param.first.name}' should be (u)byte or bool", param.first.position)
|
||||
}
|
||||
else if(param.second.registerOrPair in arrayOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY)) {
|
||||
if (!param.first.type.isWord && !param.first.type.isString && !param.first.type.isArray && param.first.type!=DataType.pointer(BaseDataType.UBYTE)) {
|
||||
err("parameter '${param.first.name}' should be (u)word, str or ^^ubyte")
|
||||
if (!param.first.type.isWord && !param.first.type.isString && !param.first.type.isArray && !param.first.type.isPointer) {
|
||||
err("parameter '${param.first.name}' should be (u)word, str or a pointer")
|
||||
}
|
||||
}
|
||||
else if(param.second.statusflag!=null) {
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
- implement float to long casting and vice versa (6502)
|
||||
- IR BUG: bool negative = sgn(f)<0 register type error
|
||||
- 6502 codegen: lptr_target^^ = -lptr_target^^ then put that into internal_cast_as_long()
|
||||
- before final release: test all examples and programs again with final version of the compiler!
|
||||
|
||||
|
||||
Future Things and Ideas
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
- implement float to long casting and vice versa (6502)
|
||||
- make $8000000 a valid long integer (-2147483648) this is more involved than you think. To make this work: long \|= $80000000
|
||||
- add cx16.r0r1sL, r2r3sL, ... etc to map signed longs on the virtual registers?
|
||||
- implement rest of long comparisons in IfElseAsmGen compareLongValues(): expressions operands that might clobber the R14-R15 registers...
|
||||
- struct/ptr: implement the remaining TODOs in PointerAssignmentsGen.
|
||||
- struct/ptr: optimize deref in PointerAssignmentsGen: optimize 'forceTemporary' to only use a temporary when the offset is >0
|
||||
@@ -117,6 +119,7 @@ Optimizations
|
||||
|
||||
- change float<0, float==0, float>0 to use sgn(float) instead? (also see IR)
|
||||
- optimize inplaceLongShiftRight() for byte aligned cases
|
||||
- optimize floats.internal_cast_from_long and floats.internal_cast_as_long
|
||||
- more optimized operator handling of different types, for example uword a ^ byte b now does a type cast of b to word first
|
||||
- optimize longEqualsValue() for const and variable operands to not assign needlessly to R0-R3.
|
||||
- optimize optimizedBitwiseExpr() for const and variable operands to not assign needlessly to R0-R3.
|
||||
|
||||
176
examples/test.p8
176
examples/test.p8
@@ -1,63 +1,131 @@
|
||||
%import floats
|
||||
%import textio
|
||||
%zeropage basicsafe
|
||||
|
||||
main {
|
||||
|
||||
sub start() {
|
||||
repeat test()
|
||||
manual()
|
||||
casts()
|
||||
}
|
||||
|
||||
sub test() {
|
||||
txt.cls()
|
||||
txt.plot(10, 10)
|
||||
txt.print("enter four digit access code:")
|
||||
txt.plot(20, 12)
|
||||
txt.print("╭──────╮")
|
||||
txt.plot(20, 13)
|
||||
txt.print("│ │")
|
||||
txt.plot(20, 14)
|
||||
txt.print("╰──────╯")
|
||||
|
||||
|
||||
txt.plot(22, 13)
|
||||
cx16.blink_enable(true)
|
||||
str code = "????"
|
||||
|
||||
ubyte numbers = 0
|
||||
repeat {
|
||||
ubyte char = txt.waitkey()
|
||||
when char {
|
||||
'0' to '9' -> {
|
||||
if numbers<4 {
|
||||
cx16.blink_enable(false)
|
||||
txt.chrout(char)
|
||||
cx16.blink_enable(true)
|
||||
code[numbers] = char
|
||||
numbers++
|
||||
}
|
||||
}
|
||||
'\r' -> {
|
||||
if numbers==4 {
|
||||
cx16.blink_enable(false)
|
||||
break
|
||||
}
|
||||
}
|
||||
20, 25 -> {
|
||||
if numbers>0 {
|
||||
cx16.blink_enable(false)
|
||||
txt.chrout(157) ; cursor left
|
||||
txt.spc() ; clear digit
|
||||
txt.chrout(157) ; cursor left
|
||||
cx16.blink_enable(true)
|
||||
numbers--
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
txt.print("\n\n\ncode entered: ")
|
||||
txt.print(code)
|
||||
|
||||
sys.wait(120)
|
||||
sub manual() {
|
||||
txt.print("\nwith conversion function:\n")
|
||||
long lv
|
||||
float f
|
||||
lv = 123456789
|
||||
txt.print_l(lv)
|
||||
txt.spc()
|
||||
floats.internal_cast_from_long(&lv, &f)
|
||||
txt.print_f(f)
|
||||
txt.spc()
|
||||
internal_cast_as_long(&f, &lv)
|
||||
txt.print_l(lv)
|
||||
txt.nl()
|
||||
lv = -987654321
|
||||
txt.print_l(lv)
|
||||
txt.spc()
|
||||
floats.internal_cast_from_long(&lv, &f)
|
||||
txt.print_f(f)
|
||||
txt.spc()
|
||||
internal_cast_as_long(&f, &lv)
|
||||
txt.print_l(lv)
|
||||
txt.nl()
|
||||
lv = -$111101
|
||||
txt.print_l(lv)
|
||||
txt.spc()
|
||||
txt.print_ulhex(lv, true)
|
||||
txt.spc()
|
||||
floats.internal_cast_from_long(&lv, &f)
|
||||
txt.print_f(f)
|
||||
txt.spc()
|
||||
internal_cast_as_long(&f, &lv)
|
||||
txt.print_l(lv)
|
||||
txt.nl()
|
||||
}
|
||||
|
||||
sub casts() {
|
||||
txt.print("\nwith casting:\n")
|
||||
long lv
|
||||
float f
|
||||
lv = 123456789
|
||||
txt.print_l(lv)
|
||||
txt.spc()
|
||||
f = lv as float
|
||||
txt.print_f(f)
|
||||
txt.spc()
|
||||
txt.print_l(f as long)
|
||||
txt.nl()
|
||||
lv = -987654321
|
||||
txt.print_l(lv)
|
||||
txt.spc()
|
||||
f = lv as float
|
||||
txt.print_f(f)
|
||||
txt.spc()
|
||||
txt.print_l(f as long)
|
||||
txt.nl()
|
||||
lv = -$111101
|
||||
txt.print_l(lv)
|
||||
txt.spc()
|
||||
txt.print_ulhex(lv, true)
|
||||
txt.spc()
|
||||
f = lv as float
|
||||
txt.print_f(f)
|
||||
txt.spc()
|
||||
txt.print_l(f as long)
|
||||
txt.nl()
|
||||
}
|
||||
|
||||
|
||||
sub internal_cast_as_long(^^float fptr_src, ^^long lptr_target) {
|
||||
; clobbers R0-R3
|
||||
float @nozp f = fptr_src^^
|
||||
alias sign = cx16.r3sL
|
||||
sign = sgn(f)
|
||||
if sign<0
|
||||
f = abs(f)
|
||||
cx16.r2 = (f / 65536.0) as uword
|
||||
&long result = &cx16.r0
|
||||
result = mklong2(cx16.r2, (f - 65536.0 * (cx16.r2 as float)) as uword)
|
||||
if sign<0
|
||||
result = -result
|
||||
lptr_target^^ = result
|
||||
}
|
||||
|
||||
/*
|
||||
sub start2() {
|
||||
uword uw
|
||||
word sw
|
||||
long lv
|
||||
float fl
|
||||
|
||||
|
||||
uw = 44555
|
||||
fl = uw as float
|
||||
txt.print_f(fl)
|
||||
txt.nl()
|
||||
fl /= 2
|
||||
uw = fl as uword
|
||||
txt.print_uw(uw)
|
||||
txt.nl()
|
||||
|
||||
sw = -8888
|
||||
fl = sw as float
|
||||
txt.print_f(fl)
|
||||
txt.nl()
|
||||
fl /= 2
|
||||
sw = fl as word
|
||||
txt.print_w(sw)
|
||||
txt.nl()
|
||||
|
||||
lv = -99886666
|
||||
fl = lv as float
|
||||
txt.print_f(fl)
|
||||
txt.nl()
|
||||
fl /= 2
|
||||
lv = fl as long
|
||||
txt.print_l(lv)
|
||||
txt.nl()
|
||||
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user