From 59c0e6ae3243aa305192b92fbdad7a5d28c9a19e Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 9 Oct 2020 23:48:33 +0200 Subject: [PATCH] added some more missing assignment codegens (word * byte etc) --- .../compiler/target/c64/codegen/AsmGen.kt | 18 +++ .../target/c64/codegen/ExpressionsAsmGen.kt | 10 +- .../assignment/AugmentableAssignmentAsmGen.kt | 142 ++++++++++-------- examples/textelite.p8 | 70 +++++---- 4 files changed, 137 insertions(+), 103 deletions(-) diff --git a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt index e622c6410..bb7c0adc5 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt @@ -1197,4 +1197,22 @@ $counterVar .byte 0""") val assembly = asm.assembly.trimEnd().trimStart('\n') assemblyLines.add(assembly) } + + internal fun signExtendStackByte(valueDt: DataType) { + // sign extend signed byte on stack to signed word + when(valueDt) { + DataType.UBYTE -> { + out(" lda #0 | sta P8ESTACK_HI+1,x") + } + DataType.BYTE -> { + out(""" + lda P8ESTACK_LO+1,x + ora #$7f + bmi + + lda #0 ++ sta P8ESTACK_HI+1,x""") + } + else -> throw AssemblyError("need byte type") + } + } } diff --git a/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt index 35557b8ed..3a7b20a8d 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt @@ -1013,15 +1013,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge DataType.BYTE -> { when(typecast.type) { DataType.UBYTE, DataType.BYTE -> {} - DataType.UWORD, DataType.WORD -> { - // sign extend - asmgen.out(""" - lda P8ESTACK_LO+1,x - ora #$7f - bmi + - lda #0 -+ sta P8ESTACK_HI+1,x""") - } + DataType.UWORD, DataType.WORD -> asmgen.signExtendStackByte(DataType.BYTE) DataType.FLOAT -> asmgen.out(" jsr floats.stack_b2float") in PassByReferenceDatatypes -> throw AssemblyError("cannot cast to a pass-by-reference datatype") else -> throw AssemblyError("weird type") diff --git a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt index 0f6b09acb..448f95db5 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt @@ -1031,6 +1031,68 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, asmgen.translateExpression(value) val valueDt = value.inferType(program).typeOrElse(DataType.STRUCT) + fun multiplyWord() { + asmgen.out(""" + lda P8ESTACK_LO+1,x + ldy P8ESTACK_HI+1,x + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 + lda $name + ldy $name+1 + jsr math.multiply_words + lda math.multiply_words.result + sta $name + lda math.multiply_words.result+1 + sta $name+1 + """) + } + + fun divideWord() { + if (dt == DataType.WORD) { + asmgen.out(""" + lda $name + ldy $name+1 + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 + lda P8ESTACK_LO+1,x + ldy P8ESTACK_HI+1,x + jsr math.divmod_w_asm + sta $name + sty $name+1 + """) + } else { + asmgen.out(""" + lda $name + ldy $name+1 + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 + lda P8ESTACK_LO+1,x + ldy P8ESTACK_HI+1,x + jsr math.divmod_uw_asm + sta $name + sty $name+1 + """) + } + } + + fun remainderWord() { + if(dt==DataType.WORD) + throw AssemblyError("remainder of signed integers is not properly defined/implemented, use unsigned instead") + asmgen.out(""" + lda $name + ldy $name+1 + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 + lda P8ESTACK_LO+1,x + ldy P8ESTACK_HI+1,x + jsr math.divmod_uw_asm + lda P8ZP_SCRATCH_W2 + sta $name + lda P8ZP_SCRATCH_W2+1 + sta $name+1 + """) + } + when(valueDt) { in ByteDatatypes -> { // the other variable is a BYTE type so optimize for that @@ -1084,9 +1146,21 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, sbc P8ZP_SCRATCH_B1 sta $name+1""") } - "*" -> TODO("mul (u)word (u)byte") - "/" -> TODO("div (u)word (u)byte") - "%" -> TODO("(u)word remainder (u)byte") + "*" -> { + // stack contains (u) byte value, sign extend that and proceed with regular 16 bit operation + asmgen.signExtendStackByte(valueDt) + multiplyWord() + } + "/" -> { + // stack contains (u) byte value, sign extend that and proceed with regular 16 bit operation + asmgen.signExtendStackByte(valueDt) + divideWord() + } + "%" -> { + // stack contains (u) byte value, sign extend that and proceed with regular 16 bit operation + asmgen.signExtendStackByte(valueDt) + remainderWord() + } "<<" -> { asmgen.translateExpression(value) asmgen.out(""" @@ -1137,65 +1211,9 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, // note: ** (power) operator requires floats. "+" -> asmgen.out(" lda $name | clc | adc P8ESTACK_LO+1,x | sta $name | lda $name+1 | adc P8ESTACK_HI+1,x | sta $name+1") "-" -> asmgen.out(" lda $name | sec | sbc P8ESTACK_LO+1,x | sta $name | lda $name+1 | sbc P8ESTACK_HI+1,x | sta $name+1") - "*" -> { - asmgen.out(""" - lda P8ESTACK_LO+1,x - ldy P8ESTACK_HI+1,x - sta P8ZP_SCRATCH_W1 - sty P8ZP_SCRATCH_W1+1 - lda $name - ldy $name+1 - jsr math.multiply_words - lda math.multiply_words.result - sta $name - lda math.multiply_words.result+1 - sta $name+1 - """) - } - "/" -> { - if (dt == DataType.WORD) { - asmgen.out(""" - lda $name - ldy $name+1 - sta P8ZP_SCRATCH_W1 - sty P8ZP_SCRATCH_W1+1 - lda P8ESTACK_LO+1,x - ldy P8ESTACK_HI+1,x - jsr math.divmod_w_asm - sta $name - sty $name+1 - """) - } else { - asmgen.out(""" - lda $name - ldy $name+1 - sta P8ZP_SCRATCH_W1 - sty P8ZP_SCRATCH_W1+1 - lda P8ESTACK_LO+1,x - ldy P8ESTACK_HI+1,x - jsr math.divmod_uw_asm - sta $name - sty $name+1 - """) - } - } - "%" -> { - if(dt==DataType.WORD) - throw AssemblyError("remainder of signed integers is not properly defined/implemented, use unsigned instead") - asmgen.out(""" - lda $name - ldy $name+1 - sta P8ZP_SCRATCH_W1 - sty P8ZP_SCRATCH_W1+1 - lda P8ESTACK_LO+1,x - ldy P8ESTACK_HI+1,x - jsr math.divmod_uw_asm - lda P8ZP_SCRATCH_W2 - sta $name - lda P8ZP_SCRATCH_W2+1 - sta $name+1 - """) - } + "*" -> multiplyWord() + "/" -> divideWord() + "%" -> remainderWord() "<<", ">>" -> throw AssemblyError("shift by a word value not supported, max is a byte") "&" -> asmgen.out(" lda $name | and P8ESTACK_LO+1,x | sta $name | lda $name+1 | and P8ESTACK_HI+1,x | sta $name+1") "^" -> asmgen.out(" lda $name | eor P8ESTACK_LO+1,x | sta $name | lda $name+1 | eor P8ESTACK_HI+1,x | sta $name+1") diff --git a/examples/textelite.p8 b/examples/textelite.p8 index 5ca70b27f..5df9cf177 100644 --- a/examples/textelite.p8 +++ b/examples/textelite.p8 @@ -1,6 +1,4 @@ %import textio -%zeropage basicsafe -%option no_sysinit main { sub start() { @@ -9,18 +7,11 @@ main { txt.print("\n--> TextElite conversion to Prog8 <--\n\n") galaxy.init(1) - txt.print("\nstart!!!!") - galaxy.debug_seed() - galaxy.generate_planet(galaxy.numforLave) planet.display(false) -; repeat 5 { -; planet.set_seed(rndw(), rndw()) -; planet.name = planet.random_name() -; planet.display(false) -; txt.chrout('\n') -; } + txt.print("\nEnter to exit: ") + void c64.CHRIN() } asmsub testX() { @@ -42,11 +33,10 @@ _saveX .byte 0 galaxy { const uword GALSIZE = 256 - ; seed for first galaxy: - const uword base0 = $5A4A + const uword base0 = $5A4A ; seeds for the first galaxy const uword base1 = $0248 const uword base2 = $B753 - const ubyte numforLave = 7 ; Lave is 7th generated planet in galaxy one + const ubyte numforLave = 7 ; Lave is 7th generated planet in galaxy one const ubyte numforZaonce = 129 const ubyte numforDiso = 147 const ubyte numforRied = 46 @@ -98,12 +88,39 @@ galaxy { txt.chrout('\n') } + sub generate_planet_properties() { + ; create the planet's characteristics + planet.x = msb(seed[1]) + planet.y = msb(seed[0]) + planet.govtype = lsb(seed[1]) >> 3 & 7 ; bits 3,4 &5 of w1 + planet.economy = msb(seed[0]) & 7 ; bits 8,9 &A of w0 + if planet.govtype <= 1 + planet.economy = (planet.economy | 2) + planet.techlevel = (msb(seed[1]) & 3) + (planet.economy ^ 7) + planet.techlevel += planet.govtype >> 1 + if planet.govtype & 1 + planet.techlevel++ + planet.population = 4 * planet.techlevel + planet.economy + planet.population += planet.govtype + 1 + planet.productivity = ((planet.economy ^ 7) + 3) * (planet.govtype + 4) + planet.productivity *= planet.population * 8 + planet.radius = mkword((msb(seed[2]) & 15) + 11, planet.x) + ;planet.radius = 256 * (((seed[2] >> 8) & 15) + 11) + planet.x ; TODO why not the same answer?? + ; TODO make this work: planet.goatsoup_seed = [seed[1] & $FF, seed[1] >> 8, seed[2] & $FF, seed[2] >> 8] + planet.goatsoup_seed[0] = lsb(seed[1]) + planet.goatsoup_seed[1] = msb(seed[1]) + planet.goatsoup_seed[2] = lsb(seed[2]) + planet.goatsoup_seed[3] = msb(seed[2]) + } + sub generate_planet(ubyte planetnum) { ubyte pair1 ubyte pair2 ubyte pair3 ubyte pair4 repeat planetnum+1 { + generate_planet_properties() + ; Always four iterations of random number pair1 = (msb(seed[2]) & 31) * 2 tweakseed() @@ -115,20 +132,9 @@ galaxy { tweakseed() } - debug_seed() - - txt.print("generating planet #") - txt.print_ub(planetnum) - txt.print("\npairs:") - txt.print_ub(pair1) - txt.chrout(',') - txt.print_ub(pair2) - txt.chrout(',') - txt.print_ub(pair3) - txt.chrout(',') - txt.print_ub(pair4) - txt.chrout('\n') + ; debug_seed() + ; create the planet's name ubyte ni = 0 if pairs[pair1] != '.' { planet.name[ni] = pairs[pair1] @@ -241,8 +247,8 @@ planet { ubyte govtype ubyte techlevel ubyte population - ubyte productivity - ubyte radius + uword productivity + uword radius ; todo: species sub set_seed(uword s1, uword s2) { @@ -404,9 +410,9 @@ planet { txt.print("\nTech Level: ") txt.print_ub(techlevel+1) txt.print("\nTurnover: ") - txt.print_ub(productivity) - txt.print("\nRadius:") - txt.print_ub(radius) + txt.print_uw(productivity) + txt.print("\nRadius: ") + txt.print_uw(radius) txt.print("\nPopulation: ") txt.print_ub(population >> 3) txt.print(" Billion\n")