fixed some array codegen issues

This commit is contained in:
Irmen de Jong 2019-08-10 11:28:38 +02:00
parent fd84152a2b
commit a6bba824d3
5 changed files with 64 additions and 273 deletions

View File

@ -517,18 +517,13 @@ internal class AsmGen2(val program: Program,
private fun readAndPushArrayvalueWithIndexA(arrayDt: DataType, variable: IdentifierReference) {
val variablename = asmIdentifierName(variable)
when (ArrayElementTypes.getValue(arrayDt).memorySize()) {
1 -> {}
2 -> out(" asl a")
5 -> out(" sta ${C64Zeropage.SCRATCH_REG} | asl a | asl a | clc | adc ${C64Zeropage.SCRATCH_REG}")
else -> throw AssemblyError("invalid memory size")
}
when (arrayDt) {
DataType.STR, DataType.STR_S, DataType.ARRAY_UB, DataType.ARRAY_B ->
out(" tay | lda $variablename,y | sta $ESTACK_LO_HEX,x | dex")
DataType.ARRAY_UW, DataType.ARRAY_W ->
out(" tay | lda $variablename,y | sta $ESTACK_LO_HEX,x | lda $variablename+1,y | sta $ESTACK_HI_HEX,x | dex")
out(" asl a | tay | lda $variablename,y | sta $ESTACK_LO_HEX,x | lda $variablename+1,y | sta $ESTACK_HI_HEX,x | dex")
DataType.ARRAY_F ->
// index * 5 is done in the subroutine that's called
out("""
sta $ESTACK_LO_HEX,x
dex
@ -541,6 +536,26 @@ internal class AsmGen2(val program: Program,
}
}
private fun popAndWriteArrayvalueWithIndexA(arrayDt: DataType, variablename: String) {
when (arrayDt) {
DataType.STR, DataType.STR_S, DataType.ARRAY_UB, DataType.ARRAY_B ->
out(" tay | inx | lda $ESTACK_LO_HEX,x | sta $variablename,y")
DataType.ARRAY_UW, DataType.ARRAY_W ->
out(" asl a | tay | inx | lda $ESTACK_LO_HEX,x | sta $variablename,y | lda $ESTACK_HI_HEX,x | sta $variablename+1,y")
DataType.ARRAY_F ->
// index * 5 is done in the subroutine that's called
out("""
sta $ESTACK_LO_HEX,x
dex
lda #<$variablename
ldy #>$variablename
jsr c64flt.pop_float_to_indexed_var
""")
else ->
throw AssemblyError("weird array type")
}
}
private fun saveRegister(register: Register) {
when(register) {
Register.A -> out(" pha")
@ -1087,8 +1102,8 @@ $endLabel""")
TODO("non-const forloop with step -1")
}
else -> when (iterableDt) {
DataType.ARRAY_UB, DataType.ARRAY_B -> TODO()
DataType.ARRAY_UW, DataType.ARRAY_W -> TODO()
DataType.ARRAY_UB, DataType.ARRAY_B -> TODO("non-const forloop bytes")
DataType.ARRAY_UW, DataType.ARRAY_W -> TODO("non-const forloop words")
else -> throw AssemblyError("range expression can only be byte or word")
}
}
@ -2080,13 +2095,10 @@ $endLabel""")
}
}
// TODO: use optimized routines such as mul_10
private fun translateBinaryOperatorBytes(operator: String, types: DataType) {
when(operator) {
"**" -> throw AssemblyError("** operator requires floats")
"*" -> out(" jsr prog8_lib.mul_byte")
"*" -> out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
"/" -> out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
"%" -> {
if(types==DataType.BYTE)
@ -2278,7 +2290,11 @@ $endLabel""")
targetArrayIdx!=null -> {
val index = targetArrayIdx.arrayspec.index
val targetName = asmIdentifierName(targetArrayIdx.identifier)
TODO("assign wordvar $sourceName to array $targetName [ $index ]")
val arrayDt = targetArrayIdx.identifier.inferType(program)!!
out(" lda $sourceName | sta $ESTACK_LO_HEX,x | lda $sourceName+1 | sta $ESTACK_HI_HEX,x | dex")
translateExpression(index)
out(" inx | lda $ESTACK_LO_HEX,x")
popAndWriteArrayvalueWithIndexA(arrayDt, targetName)
}
else -> TODO("assign wordvar to $target")
}
@ -2307,7 +2323,9 @@ $endLabel""")
targetArrayIdx!=null -> {
val index = targetArrayIdx.arrayspec.index
val targetName = asmIdentifierName(targetArrayIdx.identifier)
TODO("assign floatvar $sourceName to array $targetName [ $index ]")
out(" lda #<$sourceName | ldy #>$sourceName | jsr c64flt.push_float")
translateExpression(index)
out(" lda #<$targetName | ldy #>$targetName | jsr c64flt.pop_float_to_indexed_var")
}
else -> TODO("assign floatvar to $target")
}
@ -2331,7 +2349,11 @@ $endLabel""")
targetArrayIdx!=null -> {
val index = targetArrayIdx.arrayspec.index
val targetName = asmIdentifierName(targetArrayIdx.identifier)
TODO("assign bytevar to array $targetName [ $index ] ")
val arrayDt = targetArrayIdx.identifier.inferType(program)!!
out(" lda $sourceName | sta $ESTACK_LO_HEX,x | dex")
translateExpression(index)
out(" inx | lda $ESTACK_LO_HEX,x")
popAndWriteArrayvalueWithIndexA(arrayDt, targetName)
}
target.memoryAddress != null -> {
val addressExpr = target.memoryAddress.addressExpression
@ -2518,7 +2540,9 @@ $endLabel""")
translateExpression(index)
out("""
inx
ldy $ESTACK_LO_HEX,x
lda $ESTACK_LO_HEX,x
asl a
tay
lda #<${word.toHex()}
sta $targetName,y
lda #>${word.toHex()}
@ -2674,31 +2698,6 @@ $endLabel""")
}
}
private fun popAndWriteArrayvalueWithIndexA(arrayDt: DataType, variablename: String) {
when (ArrayElementTypes.getValue(arrayDt).memorySize()) {
1 -> {}
2 -> out(" asl a")
5 -> out(" sta ${C64Zeropage.SCRATCH_REG} | asl a | asl a | clc | adc ${C64Zeropage.SCRATCH_REG}")
else -> throw AssemblyError("invalid memory size")
}
when (arrayDt) {
DataType.STR, DataType.STR_S, DataType.ARRAY_UB, DataType.ARRAY_B ->
out(" tay | inx | lda $ESTACK_LO_HEX,x | sta $variablename,y")
DataType.ARRAY_UW, DataType.ARRAY_W ->
out(" tay | inx | lda $ESTACK_LO_HEX,x | sta $variablename,y | lda $ESTACK_HI_HEX,x | sta $variablename+1,y")
DataType.ARRAY_F ->
out("""
sta $ESTACK_LO_HEX,x
dex
lda #<$variablename
ldy #>$variablename
jsr c64flt.pop_float_to_indexed_var
""")
else ->
throw AssemblyError("weird array type")
}
}
private fun assignFromMemoryByte(target: AssignTarget, address: Int?, identifier: IdentifierReference?) {
val targetIdent = target.identifier
val targetArrayIdx = target.arrayindexed

View File

@ -1,122 +0,0 @@
%output raw
%launcher none
%import c64flt
irq {
uword global_time
ubyte time_changed
sub irq() {
; activated automatically if run in StackVm
global_time++
time_changed = 1
}
}
main {
const uword width = 320
const uword height = 200
; vertices
float[] xcoor = [ -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0 ]
float[] ycoor = [ -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0 ]
float[] zcoor = [ -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 ]
; edges (msb=from vertex, lsb=to vertex)
uword[] edges = [$0001, $0103, $0302, $0200, $0405, $0507, $0706, $0604, $0004, $0105, $0206, $0307]
; storage for rotated coordinates
float[len(xcoor)] rotatedx
float[len(ycoor)] rotatedy
float[len(zcoor)] rotatedz
sub start() {
while true {
if irq.time_changed {
irq.time_changed = 0
vm_gfx_clearscr(0)
vm_gfx_text(8, 6, 1, "Spin")
vm_gfx_text(29, 11, 1, "to Win !")
for uword i in 0 to width/10 {
vm_gfx_line(i*2+width/2-width/10, 130, i*10.w, 199, 6)
}
rotate_vertices(irq.global_time as float / 30.0)
draw_edges()
}
}
}
sub rotate_vertices(float t) {
; rotate around origin (0,0,0)
; set up the 3d rotation matrix values
float cosa = cos(t)
float sina = sin(t)
float cosb = cos(t*0.33)
float sinb = sin(t*0.33)
float cosc = cos(t*0.78)
float sinc = sin(t*0.78)
float cosa_sinb = cosa*sinb
float sina_sinb = sina*sinb
float Axx = cosa*cosb
float Axy = cosa_sinb*sinc - sina*cosc
float Axz = cosa_sinb*cosc + sina*sinc
float Ayx = sina*cosb
float Ayy = sina_sinb*sinc + cosa*cosc
float Ayz = sina_sinb*cosc - cosa*sinc
float Azx = -sinb
float Azy = cosb*sinc
float Azz = cosb*cosc
for ubyte i in 0 to len(xcoor)-1 {
rotatedx[i] = Axx*xcoor[i] + Axy*ycoor[i] + Axz*zcoor[i]
rotatedy[i] = Ayx*xcoor[i] + Ayy*ycoor[i] + Ayz*zcoor[i]
rotatedz[i] = Azx*xcoor[i] + Azy*ycoor[i] + Azz*zcoor[i]
}
}
sub draw_edges() {
sub toscreenx(float x, float z) -> word {
return x/(4.2+z) * (height as float) as word + width / 2
}
sub toscreeny(float y, float z) -> word {
return y/(4.2+z) * (height as float) as word + height / 2
}
; draw all edges of the object
for uword edge in edges {
ubyte e_from = msb(edge)
ubyte e_to = lsb(edge)
vm_gfx_line(toscreenx(rotatedx[e_from], rotatedz[e_from]), toscreeny(rotatedy[e_from], rotatedz[e_from]),
toscreenx(rotatedx[e_to], rotatedz[e_to]), toscreeny(rotatedy[e_to], rotatedz[e_to]), e_from+e_to)
}
; accentuate the vertices a bit with small boxes
for ubyte i in 0 to len(xcoor)-1 {
word sx = toscreenx(rotatedx[i], rotatedz[i])
word sy = toscreeny(rotatedy[i], rotatedz[i])
ubyte color=i+2
vm_gfx_pixel(sx-1, sy-1, color)
vm_gfx_pixel(sx, sy-1, color)
vm_gfx_pixel(sx+1, sy-1, color)
vm_gfx_pixel(sx-1, sy, color)
vm_gfx_pixel(sx, sy, color)
vm_gfx_pixel(sx+1, sy, color)
vm_gfx_pixel(sx-1, sy+1, color)
vm_gfx_pixel(sx, sy+1, color)
vm_gfx_pixel(sx+1, sy+1, color)
vm_gfx_pixel(sx, sy-2, color)
vm_gfx_pixel(sx+2, sy, color)
vm_gfx_pixel(sx, sy+2, color)
vm_gfx_pixel(sx-2, sy, color)
}
}
}

View File

@ -1,40 +0,0 @@
%output raw
%launcher none
%import c64flt
main {
const uword width = 320 / 2
const uword height = 256 / 2
const uword xoffset = 40
const uword yoffset = 30
sub start() {
vm_gfx_clearscr(11)
vm_gfx_text(2, 1, 1, "Calculating Mandelbrot Fractal...")
for ubyte pixely in yoffset to yoffset+height-1 {
float yy = (pixely-yoffset as float)/3.6/height+0.4
for uword pixelx in xoffset to xoffset+width-1 {
float xx = (pixelx-xoffset as float)/3.0/width+0.2
float xsquared = 0.0
float ysquared = 0.0
float x = 0.0
float y = 0.0
ubyte iter = 0
while (iter<32 and xsquared+ysquared<4.0) {
y = x*y*2.0 + yy
x = xsquared - ysquared + xx
xsquared = x*x
ysquared = y*y
iter++
}
vm_gfx_pixel(pixelx, pixely, iter)
}
}
vm_gfx_text(11, 21, 1, "Finished!")
}
}

View File

@ -1,32 +0,0 @@
%output raw
%launcher none
%import c64flt
main {
const uword width = 320
const uword height = 200
sub start() {
vm_gfx_clearscr(0)
float t
ubyte color
while true {
float x = sin(t*1.01) + cos(t*1.1234)
float y = cos(t) + sin(t*0.03456)
vm_gfx_pixel(screenx(x), screeny(y), color/16)
t += 0.01
color++
}
}
sub screenx(float x) -> word {
return (x*width/4.1) + width / 2.0 as word
}
sub screeny(float y) -> word {
return (y*height/4.1) + height / 2.0 as word
}
}

View File

@ -8,50 +8,36 @@ main {
sub start() {
ubyte ub1 = 123
ubyte ub2 = 222
uword uw = 1111
uword uw2 = 2222
word[] warr = [1111, 2222]
float[] farr = [1.111, 2.222]
word[] warr = [1111, 2222, 3333, 4444]
byte[] barr = [11, 22, 33, 44]
c64scr.print_ub(ub1)
c64.CHROUT(',')
c64scr.print_ub(ub2)
c64.CHROUT('\n')
c64scr.print_uw(uw)
c64.CHROUT(',')
c64scr.print_uw(uw2)
c64.CHROUT('\n')
c64scr.print_w(warr[0])
c64.CHROUT(',')
c64scr.print_w(warr[1])
c64.CHROUT('\n')
c64flt.print_f(farr[0])
c64.CHROUT(',')
c64flt.print_f(farr[1])
word ww = 9999
byte bb = 99
c64scr.print_b(barr[2])
c64.CHROUT('\n')
swap(ub1, ub2)
swap(uw,uw2)
swap(warr[0], warr[1])
swap(farr[0], farr[1]) ; TODO CRASHES
barr[2] = 55
c64scr.print_b(barr[2])
c64.CHROUT('\n')
c64scr.print_ub(ub1)
c64.CHROUT(',')
c64scr.print_ub(ub2)
barr[2] = bb
c64scr.print_b(barr[2])
c64.CHROUT('\n')
c64scr.print_uw(uw)
c64.CHROUT(',')
c64scr.print_uw(uw2)
@($0400+72) = X
c64scr.print_w(warr[2])
c64.CHROUT('\n')
c64scr.print_w(warr[0])
c64.CHROUT(',')
c64scr.print_w(warr[1])
warr[2] = 5555
c64scr.print_w(warr[2])
c64.CHROUT('\n')
c64flt.print_f(farr[0])
c64.CHROUT(',')
c64flt.print_f(farr[1])
warr[2] = ww
c64scr.print_w(warr[2])
c64.CHROUT('\n')
@($0400+73) = X
}
}