mirror of
https://github.com/irmen/prog8.git
synced 2025-11-23 14:17:51 +00:00
IR: added float<>long casts, cx16: blink_cursor extapi tested in test.p8
This commit is contained in:
@@ -2003,9 +2003,9 @@ $repeatLabel""")
|
||||
lda #<$leftName
|
||||
ldy #>$leftName""")
|
||||
if(lessOrEquals)
|
||||
out("jsr floats.vars_lesseq_f")
|
||||
out(" jsr floats.vars_lesseq_f")
|
||||
else
|
||||
out("jsr floats.vars_less_f")
|
||||
out(" jsr floats.vars_less_f")
|
||||
}
|
||||
fun lessf(expr: PtExpression, rightName: String) {
|
||||
assignExpressionToRegister(expr, RegisterOrPair.FAC1, true)
|
||||
|
||||
@@ -1325,8 +1325,8 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
|
||||
|
||||
fun divide(signed: Boolean) {
|
||||
// on entry here: number placed in P8ZP_SCRATCH_PTR, divisor placed in AY
|
||||
if(signed) asmgen.out("jsr prog8_math.divmod_w_asm")
|
||||
else asmgen.out("jsr prog8_math.divmod_uw_asm")
|
||||
if(signed) asmgen.out(" jsr prog8_math.divmod_w_asm")
|
||||
else asmgen.out(" jsr prog8_math.divmod_uw_asm")
|
||||
asmgen.out("""
|
||||
tax
|
||||
tya
|
||||
|
||||
@@ -819,6 +819,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
actualResultReg2 = codeGen.registers.next(IRDataType.LONG)
|
||||
addInstr(result, IRInstruction(Opcode.EXTS, type = IRDataType.WORD, reg1 = actualResultReg2, reg2=tr.resultReg), null)
|
||||
}
|
||||
BaseDataType.FLOAT -> {
|
||||
actualResultReg2 = codeGen.registers.next(IRDataType.LONG)
|
||||
addInstr(result, IRInstruction(Opcode.FTOSL, IRDataType.FLOAT, reg1=actualResultReg2, fpReg1 = tr.resultFpReg), null)
|
||||
}
|
||||
else -> throw AssemblyError("weird cast $valueDt to long ${cast.position}")
|
||||
}
|
||||
}
|
||||
@@ -837,6 +841,9 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
BaseDataType.WORD -> {
|
||||
addInstr(result, IRInstruction(Opcode.FFROMSW, IRDataType.FLOAT, reg1=tr.resultReg, fpReg1 = actualResultFpReg2), null)
|
||||
}
|
||||
BaseDataType.LONG -> {
|
||||
addInstr(result, IRInstruction(Opcode.FFROMSL, IRDataType.FLOAT, reg1=tr.resultReg, fpReg1 = actualResultFpReg2), null)
|
||||
}
|
||||
else -> throw AssemblyError("weird cast value type ${cast.position}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -459,17 +459,19 @@ jump p8_label_gen_2
|
||||
return null
|
||||
}
|
||||
|
||||
val immediate1 = getImmediateLoad(ins.reg1!!)
|
||||
if(immediate1!=null) {
|
||||
chunk.instructions[idx] = IRInstruction(replacementOpcode, ins.type, reg1 = ins.reg2, immediate = immediate1.second)
|
||||
chunk.instructions.removeAt(immediate1.first)
|
||||
changed=true
|
||||
} else {
|
||||
val immediate2 = getImmediateLoad(ins.reg2!!)
|
||||
if (immediate2 != null) {
|
||||
chunk.instructions[idx] = IRInstruction(replacementOpcode, ins.type, reg1 = ins.reg1, immediate = immediate2.second)
|
||||
chunk.instructions.removeAt(immediate2.first)
|
||||
if(ins.reg1!=null) {
|
||||
val immediate1 = getImmediateLoad(ins.reg1!!)
|
||||
if(immediate1!=null) {
|
||||
chunk.instructions[idx] = IRInstruction(replacementOpcode, ins.type, reg1 = ins.reg2, immediate = immediate1.second)
|
||||
chunk.instructions.removeAt(immediate1.first)
|
||||
changed=true
|
||||
} else {
|
||||
val immediate2 = getImmediateLoad(ins.reg2!!)
|
||||
if (immediate2 != null) {
|
||||
chunk.instructions[idx] = IRInstruction(replacementOpcode, ins.type, reg1 = ins.reg1, immediate = immediate2.second)
|
||||
chunk.instructions.removeAt(immediate2.first)
|
||||
changed=true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -814,6 +814,7 @@ asmsub blink_enable(bool enable @X) clobbers(A,X) {
|
||||
; requires rom v49+
|
||||
%asm {{
|
||||
txa
|
||||
and #1
|
||||
eor #1
|
||||
tax
|
||||
lda #EXTAPI_blink_enable
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
- IR BUG: bool negative = sgn(f)<0 register type error
|
||||
- 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
|
||||
- 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.
|
||||
@@ -58,6 +60,7 @@ Future Things and Ideas
|
||||
|
||||
IR/VM
|
||||
-----
|
||||
- make SGN set the N,Z flags and then optimize float<0 float==0 float>0 to use SGN instruction. Check what code is generated for other data types.
|
||||
- getting it in shape for code generation: the IR file should be able to encode every detail about a prog8 program (the VM doesn't have to actually be able to run all of it though!)
|
||||
- fix call() return value handling (... what's wrong with it again?)
|
||||
- proper code gen for the CALLI instruction and that it (optionally) returns a word value that needs to be assigned to a reg
|
||||
@@ -112,6 +115,7 @@ Libraries
|
||||
Optimizations
|
||||
-------------
|
||||
|
||||
- change float<0, float==0, float>0 to use sgn(float) instead? (also see IR)
|
||||
- optimize inplaceLongShiftRight() for byte aligned cases
|
||||
- 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.
|
||||
|
||||
@@ -1,39 +1,63 @@
|
||||
%import diskio
|
||||
%import textio
|
||||
%zeropage basicsafe
|
||||
|
||||
main {
|
||||
|
||||
sub start() {
|
||||
void diskio.f_open("t8s.wav")
|
||||
long size, pos
|
||||
repeat test()
|
||||
}
|
||||
|
||||
pos, size = diskio.f_tell()
|
||||
txt.print_l(pos)
|
||||
txt.spc()
|
||||
txt.print_l(size)
|
||||
txt.nl()
|
||||
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("╰──────╯")
|
||||
|
||||
diskio.f_seek(999999)
|
||||
pos, size = diskio.f_tell()
|
||||
txt.print_l(pos)
|
||||
txt.spc()
|
||||
txt.print_l(size)
|
||||
txt.nl()
|
||||
|
||||
long lba, cluster
|
||||
lba, cluster = diskio.f_fatlba()
|
||||
txt.print_l(lba)
|
||||
txt.spc()
|
||||
txt.print_l(cluster)
|
||||
txt.nl()
|
||||
diskio.f_seek(0)
|
||||
lba, cluster = diskio.f_fatlba()
|
||||
txt.print_l(lba)
|
||||
txt.spc()
|
||||
txt.print_l(cluster)
|
||||
txt.nl()
|
||||
txt.plot(22, 13)
|
||||
cx16.blink_enable(true)
|
||||
str code = "????"
|
||||
|
||||
diskio.f_close()
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,10 +220,12 @@ ffromub fpreg1, reg1 - fpreg1 = reg1 from usigned byte
|
||||
ffromsb fpreg1, reg1 - fpreg1 = reg1 from signed byte
|
||||
ffromuw fpreg1, reg1 - fpreg1 = reg1 from unsigned word
|
||||
ffromsw fpreg1, reg1 - fpreg1 = reg1 from signed word
|
||||
ffromsl fpreg1, reg1 - fpreg1 = reg1 from signed long
|
||||
ftoub reg1, fpreg1 - reg1 = fpreg1 as unsigned byte
|
||||
ftosb reg1, fpreg1 - reg1 = fpreg1 as signed byte
|
||||
ftouw reg1, fpreg1 - reg1 = fpreg1 as unsigned word
|
||||
ftosw reg1, fpreg1 - reg1 = fpreg1 as signed word
|
||||
ftosl reg1, fpreg1 - reg1 = fpreg1 as signed long
|
||||
fpow fpreg1, fpreg2 - fpreg1 = fpreg1 to the power of fpreg2
|
||||
fabs fpreg1, fpreg2 - fpreg1 = abs(fpreg2)
|
||||
fcomp reg1, fpreg1, fpreg2 - reg1 = result of comparison of fpreg1 and fpreg2: 0.b=equal, 1.b=fpreg1 is greater, -1.b=fpreg1 is smaller
|
||||
@@ -398,10 +400,12 @@ enum class Opcode {
|
||||
FFROMSB,
|
||||
FFROMUW,
|
||||
FFROMSW,
|
||||
FFROMSL,
|
||||
FTOUB,
|
||||
FTOSB,
|
||||
FTOUW,
|
||||
FTOSW,
|
||||
FTOSL,
|
||||
FPOW,
|
||||
FABS,
|
||||
FSIN,
|
||||
@@ -787,10 +791,12 @@ val instructionFormats = mutableMapOf(
|
||||
Opcode.FFROMSB to InstructionFormat.from("F,>fr1,<r1"),
|
||||
Opcode.FFROMUW to InstructionFormat.from("F,>fr1,<r1"),
|
||||
Opcode.FFROMSW to InstructionFormat.from("F,>fr1,<r1"),
|
||||
Opcode.FFROMSL to InstructionFormat.from("F,>fr1,<r1"),
|
||||
Opcode.FTOUB to InstructionFormat.from("F,>r1,<fr1"),
|
||||
Opcode.FTOSB to InstructionFormat.from("F,>r1,<fr1"),
|
||||
Opcode.FTOUW to InstructionFormat.from("F,>r1,<fr1"),
|
||||
Opcode.FTOSW to InstructionFormat.from("F,>r1,<fr1"),
|
||||
Opcode.FTOSL to InstructionFormat.from("F,>r1,<fr1"),
|
||||
Opcode.FPOW to InstructionFormat.from("F,<>fr1,<fr2"),
|
||||
Opcode.FABS to InstructionFormat.from("F,>fr1,<fr2"),
|
||||
Opcode.FCOMP to InstructionFormat.from("F,>r1,<fr1,<fr2"),
|
||||
@@ -1086,10 +1092,20 @@ data class IRInstruction(
|
||||
private fun determineReg1Type(): IRDataType? {
|
||||
if(type==IRDataType.FLOAT) {
|
||||
// some float instructions have an integer (byte or word) register as well in reg1
|
||||
return if(opcode in arrayOf(Opcode.FFROMUB, Opcode.FFROMSB, Opcode.FTOUB, Opcode.FTOSB, Opcode.FCOMP, Opcode.LOADIX, Opcode.LOADX, Opcode.STOREX, Opcode.STOREIX, Opcode.STOREZX))
|
||||
IRDataType.BYTE
|
||||
else
|
||||
IRDataType.WORD
|
||||
return when (opcode) {
|
||||
Opcode.FFROMUB,
|
||||
Opcode.FFROMSB,
|
||||
Opcode.FTOUB,
|
||||
Opcode.FTOSB,
|
||||
Opcode.FCOMP,
|
||||
Opcode.LOADIX,
|
||||
Opcode.LOADX,
|
||||
Opcode.STOREX,
|
||||
Opcode.STOREIX,
|
||||
Opcode.STOREZX -> IRDataType.BYTE
|
||||
Opcode.FFROMSL, Opcode.FTOSL -> IRDataType.LONG
|
||||
else -> IRDataType.WORD
|
||||
}
|
||||
}
|
||||
if(type==IRDataType.WORD) {
|
||||
// some word instructions have byte reg1
|
||||
|
||||
@@ -330,10 +330,12 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
Opcode.FFROMSB -> InsFFROMSB(ins)
|
||||
Opcode.FFROMUW -> InsFFROMUW(ins)
|
||||
Opcode.FFROMSW -> InsFFROMSW(ins)
|
||||
Opcode.FFROMSL -> InsFFROMSL(ins)
|
||||
Opcode.FTOUB -> InsFTOUB(ins)
|
||||
Opcode.FTOSB -> InsFTOSB(ins)
|
||||
Opcode.FTOUW -> InsFTOUW(ins)
|
||||
Opcode.FTOSW -> InsFTOSW(ins)
|
||||
Opcode.FTOSL -> InsFTOSL(ins)
|
||||
Opcode.FPOW -> InsFPOW(ins)
|
||||
Opcode.FABS -> InsFABS(ins)
|
||||
Opcode.FSIN -> InsFSIN(ins)
|
||||
@@ -2686,6 +2688,11 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsFFROMSL(i: IRInstruction) {
|
||||
registers.setFloat(i.fpReg1!!, registers.getSL(i.reg1!!).toDouble())
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsFTOUB(i: IRInstruction) {
|
||||
registers.setUB(i.reg1!!, registers.getFloat(i.fpReg1!!).toInt().toUByte())
|
||||
nextPc()
|
||||
@@ -2706,6 +2713,11 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsFTOSL(i: IRInstruction) {
|
||||
registers.setSL(i.reg1!!, registers.getFloat(i.fpReg1!!).toInt())
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsFPOW(i: IRInstruction) {
|
||||
val value = registers.getFloat(i.fpReg1!!)
|
||||
val exponent = registers.getFloat(i.fpReg2!!)
|
||||
|
||||
Reference in New Issue
Block a user