more asm output

This commit is contained in:
Irmen de Jong 2018-10-25 01:05:35 +02:00
parent f42a036fc5
commit 595bf7ad4b
3 changed files with 257 additions and 68 deletions

View File

@ -0,0 +1,124 @@
%import c64utils
%option enable_floats
~ irq {
uword global_time
ubyte time_changed
sub irq() {
global_time++
time_changed = 1
}
}
~ main {
const uword width = 320
const uword height = 200
; vertices
float[8] xcoor = [ -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0 ]
float[8] ycoor = [ -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0 ]
float[8] 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[12] 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(1) {
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 {
uword x=i*2+width//2-width//10
;vm_gfx_line(x, 130, i*10.w, 199, 6)
}
rotate_vertices(flt(irq.global_time) / 30.0)
draw_edges()
}
}
}
sub rotate_vertices(t: float) {
; 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 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(x: float, z: float) -> word {
return floor(x/(4.2+z) * flt(height)) + width // 2
}
sub toscreeny(y: float, z: float) -> word {
return floor(y/(4.2+z) * flt(height)) + height // 2
}
; draw all edges of the object
for uword edge in edges {
ubyte e_from = msb(edge)
ubyte e_to = lsb(edge)
word x1 = toscreenx(rotatedx[e_from], rotatedz[e_from])
word y1 = toscreeny(rotatedy[e_from], rotatedz[e_from])
word x2 = toscreenx(rotatedx[e_to], rotatedz[e_to])
word y2 = toscreeny(rotatedy[e_to], rotatedz[e_to])
ubyte color = e_from+e_to
;vm_gfx_line(x1, y1, x2, y2)
}
; 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

@ -8,7 +8,7 @@
sub start() {
ubyte pixely = 255
ubyte derp = 0
ubyte ub = 0
byte b = 99
byte b2 = 100
word w = 999
@ -18,6 +18,22 @@ sub start() {
float fl1 = 1.1
float fl2 = 2.2
byte[5] barr1
byte[5] barr2
ubyte[5] ubarr1
ubyte[5] ubarr2
word[5] warr1
word[5] warr2
uword[5] uwarr1
uword[5] uwarr2
float[5] farr1
float[5] farr2
byte[2,3] bmatrix1
byte[2,3] bmatrix2
ubyte[2,3] ubmatrix1
ubyte[2,3] ubmatrix2
memory byte mbyte = $c000
memory byte mbyte2 = $d000
memory ubyte mubyte = $c001
@ -29,20 +45,59 @@ sub start() {
memory float mfloat = $c006
memory float mfloat2 = $d006
barr1[2]=42
ubarr1[2]=42
warr1[2]=12555
uwarr1[2]=42555
farr1[2]=42.5678
barr1[2] = b
ubarr1[2] = ub
warr1[2] = w
uwarr1[2] = uw
farr1[2] = fl1
barr1[2] = mbyte
ubarr1[2] = mubyte
warr1[2] = mword
uwarr1[2] = muword
farr1[2] = mfloat
b= barr1[2]
ub = ubarr1[2]
w = warr1[2]
uw = uwarr1[2]
fl1 = farr1[2]
mbyte= barr1[2]
mubyte = ubarr1[2]
mword = warr1[2]
muword = uwarr1[2]
mfloat = farr1[2]
barr1[2] = barr2[3]
ubarr1[2] = ubarr2[3]
warr1[2] = warr2[3]
uwarr1[2] = uwarr2[3]
farr1[2] = farr2[3]
; b = 1
; derp = 1
; ub = 1
; w = 1
; uw = 1
; fl1 = 2.345
;
; b = b2
; derp = pixely
; ub = pixely
; w = w2
; uw = uw2
; fl1 = fl2
;
; b = mbyte
; derp = mubyte
; ub = mubyte
; w = mword
; uw = muword
; fl1 = mfloat
@ -53,22 +108,22 @@ sub start() {
; muword = 1
; mfloat = 3.456
%breakpoint
mbyte = b
mubyte = derp
mword = w
muword = uw
mfloat = fl2
%breakpoint
mbyte = mbyte2
mubyte = mubyte2
mword = mword2
muword = muword2
mfloat = mfloat2
; %breakpoint
;
; mbyte = b
; mubyte = ub
; mword = w
; muword = uw
; mfloat = fl2
;
; %breakpoint
;
; mbyte = mbyte2
; mubyte = mubyte2
; mword = mword2
; muword = muword2
; mfloat = mfloat2
;
return
}

View File

@ -8,6 +8,7 @@ import prog8.ast.DataType
import prog8.ast.Register
import prog8.compiler.*
import prog8.compiler.intermediate.*
import prog8.stackvm.Syscall
import prog8.stackvm.syscallsForStackVm
import java.io.File
import java.io.PrintWriter
@ -391,58 +392,58 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
Opcode.SYSCALL -> {
if (ins.arg!!.numericValue() in syscallsForStackVm.map { it.callNr })
throw CompilerException("cannot translate vm syscalls to real assembly calls - use *real* subroutine calls instead. Syscall ${ins.arg.numericValue()}")
TODO("syscall $ins")
val call = Syscall.values().find { it.callNr==ins.arg.numericValue() }
" jsr prog8_lib.${call.toString().toLowerCase()}"
}
Opcode.BREAKPOINT -> {
breakpointCounter++
"_prog8_breakpoint_$breakpointCounter\tnop"
}
// todo weer aanzetten?
// Opcode.PUSH_BYTE -> {
// " lda #${ins.arg!!.integerValue().toHex()} | sta ${ESTACK_LO.toHex()},x | dex"
// }
// Opcode.PUSH_WORD -> {
// val value = ins.arg!!.integerValue().toHex()
// " lda #<$value | sta ${ESTACK_LO.toHex()},x | lda #>$value | sta ${ESTACK_HI.toHex()},x | dex"
// }
// Opcode.PUSH_FLOAT -> {
// val floatConst = getFloatConst(ins.arg)
// " lda #<$floatConst | ldy #>$floatConst | jsr prog8_lib.push_float"
// }
// Opcode.PUSH_VAR_BYTE -> {
// when(ins.callLabel) {
// "X" -> throw CompilerException("makes no sense to push X, it's used as a stack pointer itself")
// "A" -> " sta ${ESTACK_LO.toHex()},x | dex"
// "Y" -> " tya | sta ${ESTACK_LO.toHex()},x | dex"
// else -> " lda ${ins.callLabel} | sta ${ESTACK_LO.toHex()},x | dex"
// }
// }
// Opcode.PUSH_VAR_WORD -> {
// when (ins.callLabel) {
// "AX" -> throw CompilerException("makes no sense to push X, it's used as a stack pointer itself")
// "XY" -> throw CompilerException("makes no sense to push X, it's used as a stack pointer itself")
// "AY" -> " sta ${ESTACK_LO.toHex()},x | pha | tya | sta ${ESTACK_HI.toHex()},x | pla | dex"
// else -> " lda ${ins.callLabel} | ldy ${ins.callLabel}+1 | sta ${ESTACK_LO.toHex()},x | pha | tya | sta ${ESTACK_HI.toHex()},x | pla | dex"
// }
// }
// Opcode.PUSH_VAR_FLOAT -> " lda #<${ins.callLabel} | ldy #>${ins.callLabel}| jsr prog8_lib.push_float"
// Opcode.PUSH_MEM_B, Opcode.PUSH_MEM_UB -> {
// """
// lda ${ins.arg!!.integerValue().toHex()}
// sta ${ESTACK_LO.toHex()},x
// dex
// """
// }
// Opcode.PUSH_MEM_W, Opcode.PUSH_MEM_UW -> {
// """
// lda ${ins.arg!!.integerValue().toHex()}
// sta ${ESTACK_LO.toHex()},x
// lda ${(ins.arg.integerValue()+1).toHex()}
// sta ${ESTACK_HI.toHex()},x
// dex
// """
// }
Opcode.PUSH_BYTE -> {
" lda #${ins.arg!!.integerValue().toHex()} | sta ${ESTACK_LO.toHex()},x | dex"
}
Opcode.PUSH_WORD -> {
val value = ins.arg!!.integerValue().toHex()
" lda #<$value | sta ${ESTACK_LO.toHex()},x | lda #>$value | sta ${ESTACK_HI.toHex()},x | dex"
}
Opcode.PUSH_FLOAT -> {
val floatConst = getFloatConst(ins.arg!!)
" lda #<$floatConst | ldy #>$floatConst | jsr prog8_lib.push_float"
}
Opcode.PUSH_VAR_BYTE -> {
when(ins.callLabel) {
"X" -> throw CompilerException("makes no sense to push X, it's used as a stack pointer itself")
"A" -> " sta ${ESTACK_LO.toHex()},x | dex"
"Y" -> " tya | sta ${ESTACK_LO.toHex()},x | dex"
else -> " lda ${ins.callLabel} | sta ${ESTACK_LO.toHex()},x | dex"
}
}
Opcode.PUSH_VAR_WORD -> {
when (ins.callLabel) {
"AX" -> throw CompilerException("makes no sense to push X, it's used as a stack pointer itself")
"XY" -> throw CompilerException("makes no sense to push X, it's used as a stack pointer itself")
"AY" -> " sta ${ESTACK_LO.toHex()},x | pha | tya | sta ${ESTACK_HI.toHex()},x | pla | dex"
else -> " lda ${ins.callLabel} | ldy ${ins.callLabel}+1 | sta ${ESTACK_LO.toHex()},x | pha | tya | sta ${ESTACK_HI.toHex()},x | pla | dex"
}
}
Opcode.PUSH_VAR_FLOAT -> " lda #<${ins.callLabel} | ldy #>${ins.callLabel}| jsr prog8_lib.push_float"
Opcode.PUSH_MEM_B, Opcode.PUSH_MEM_UB -> {
"""
lda ${ins.arg!!.integerValue().toHex()}
sta ${ESTACK_LO.toHex()},x
dex
"""
}
Opcode.PUSH_MEM_W, Opcode.PUSH_MEM_UW -> {
"""
lda ${ins.arg!!.integerValue().toHex()}
sta ${ESTACK_LO.toHex()},x
lda ${(ins.arg.integerValue()+1).toHex()}
sta ${ESTACK_HI.toHex()},x
dex
"""
}
Opcode.POP_MEM_B, Opcode.POP_MEM_UB -> {
"""
@ -635,6 +636,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
sta ${(ESTACK_LO+1).toHex()},x
"""
}
Opcode.NEG_F -> " jsr prog8_lib.neg_f"
Opcode.INV_BYTE -> {
"""
lda ${(ESTACK_LO + 1).toHex()},x
@ -768,7 +770,8 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
// check for operations that modify a single value, by putting it on the stack (and popping it afterwards)
if((opcodes[0]==Opcode.PUSH_VAR_BYTE && opcodes[2]==Opcode.POP_VAR_BYTE) ||
(opcodes[0]==Opcode.PUSH_VAR_WORD && opcodes[2]==Opcode.POP_VAR_WORD)) {
(opcodes[0]==Opcode.PUSH_VAR_WORD && opcodes[2]==Opcode.POP_VAR_WORD) ||
(opcodes[0]==Opcode.PUSH_VAR_FLOAT && opcodes[2]==Opcode.POP_VAR_FLOAT)) {
if (segment[0].callLabel == segment[2].callLabel) {
val fragment = sameVarOperation(segment[0].callLabel!!, segment[1])
if (fragment != null) {
@ -778,7 +781,10 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
}
}
else if((opcodes[0]==Opcode.PUSH_MEM_UB && opcodes[2]==Opcode.POP_MEM_UB) ||
(opcodes[0]==Opcode.PUSH_MEM_UW && opcodes[2]==Opcode.POP_MEM_UW)) {
(opcodes[0]==Opcode.PUSH_MEM_B && opcodes[2]==Opcode.POP_MEM_B) ||
(opcodes[0]==Opcode.PUSH_MEM_UW && opcodes[2]==Opcode.POP_MEM_UW) ||
(opcodes[0]==Opcode.PUSH_MEM_W && opcodes[2]==Opcode.POP_MEM_W) ||
(opcodes[0]==Opcode.PUSH_MEM_FLOAT && opcodes[2]==Opcode.POP_MEM_FLOAT)) {
if(segment[0].arg==segment[2].arg) {
val fragment = sameMemOperation(segment[0].arg!!.integerValue(), segment[1])
if(fragment!=null) {
@ -1004,6 +1010,9 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
else -> AsmFragment(" lda $variable | sta ${C64Zeropage.SCRATCH_W1} | lda $variable+1 | sta ${C64Zeropage.SCRATCH_W1+1} | jsr prog8_lib.ror2_word | lda ${C64Zeropage.SCRATCH_W1} | sta $variable | lda ${C64Zeropage.SCRATCH_W1+1} | sta $variable+1", 30)
}
}
// Opcode.SYSCALL -> {
// TODO("optimize SYSCALL $ins in-place on variable $variable")
// }
else -> null
}
}
@ -1182,6 +1191,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
},
// @todo add all indexed assignment forms
// assignment: var = bytearray[index]
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.POP_VAR_BYTE)) { segment ->