added some more missing assignment codegens (word * byte etc)

This commit is contained in:
Irmen de Jong 2020-10-09 23:48:33 +02:00
parent 94c30fc21e
commit 59c0e6ae32
4 changed files with 137 additions and 103 deletions

View File

@ -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")
}
}
}

View File

@ -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")

View File

@ -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")

View File

@ -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")