mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
subroutines are now wrapped in .proc/.pend for 64tass
This commit is contained in:
parent
f803b4edc1
commit
775cdd451c
@ -1,52 +1,150 @@
|
||||
%import c64utils
|
||||
%import c64flt
|
||||
|
||||
~ main {
|
||||
|
||||
const uword width = 40
|
||||
const uword height = 25
|
||||
|
||||
; vertices
|
||||
byte[8] xcoor = [ -50, -50, -50, -50, 50, 50, 50, 50 ]
|
||||
byte[8] ycoor = [ -50, -50, 50, 50, -50, -50, 50, 50 ]
|
||||
byte[8] zcoor = [ -50, 50, -50, 50, -50, 50, -50, 50 ]
|
||||
|
||||
; storage for rotated coordinates
|
||||
word[len(xcoor)] rotatedx=0
|
||||
word[len(ycoor)] rotatedy=0
|
||||
word[len(zcoor)] rotatedz=-1
|
||||
|
||||
sub start() {
|
||||
|
||||
ubyte a=200
|
||||
ubyte b=33
|
||||
ubyte c
|
||||
|
||||
byte ab=100
|
||||
byte bb=-6
|
||||
byte cb
|
||||
|
||||
uword wa=50000
|
||||
uword wb=999
|
||||
uword wc
|
||||
word wab=30000
|
||||
word wbb=-99
|
||||
word wcb
|
||||
|
||||
c=a//b
|
||||
c64scr.print_ub(c)
|
||||
c64.CHROUT('\n')
|
||||
a=155
|
||||
b=11
|
||||
c=a//b
|
||||
c64scr.print_ub(c)
|
||||
c64.CHROUT('\n')
|
||||
cb=ab//bb
|
||||
c64scr.print_b(cb)
|
||||
c64.CHROUT('\n')
|
||||
ab=-100
|
||||
bb=6
|
||||
cb=ab//bb
|
||||
c64scr.print_b(cb)
|
||||
c64.CHROUT('\n')
|
||||
ab=-100
|
||||
bb=-6
|
||||
cb=ab//bb
|
||||
c64scr.print_b(cb)
|
||||
c64.CHROUT('\n')
|
||||
ab=100
|
||||
bb=6
|
||||
cb=ab//bb
|
||||
c64scr.print_b(cb)
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print_ub(X)
|
||||
c64.CHROUT('\n')
|
||||
uword anglex
|
||||
uword angley
|
||||
uword anglez
|
||||
while(true) {
|
||||
rotate_vertices(msb(anglex), msb(angley), msb(anglez))
|
||||
c64.CLEARSCR()
|
||||
draw_edges()
|
||||
anglex+=1000
|
||||
angley+=333
|
||||
anglez+=807
|
||||
}
|
||||
}
|
||||
|
||||
sub rotate_vertices(ubyte ax, ubyte ay, ubyte az) {
|
||||
; rotate around origin (0,0,0)
|
||||
|
||||
; set up the 3d rotation matrix values
|
||||
word wcosa = cos8(ax) as word
|
||||
word wsina = sin8(ax) as word
|
||||
word wcosb = cos8(ay) as word
|
||||
word wsinb = sin8(ay) as word
|
||||
word wcosc = cos8(az) as word
|
||||
word wsinc = sin8(az) as word
|
||||
|
||||
word wcosa_sinb = wcosa*wsinb
|
||||
lsr(wcosa_sinb)
|
||||
lsr(wcosa_sinb)
|
||||
lsr(wcosa_sinb)
|
||||
lsr(wcosa_sinb)
|
||||
lsr(wcosa_sinb)
|
||||
lsr(wcosa_sinb)
|
||||
lsr(wcosa_sinb) ; / 128
|
||||
word wsina_sinb = wsina*wsinb
|
||||
lsr(wsina_sinb)
|
||||
lsr(wsina_sinb)
|
||||
lsr(wsina_sinb)
|
||||
lsr(wsina_sinb)
|
||||
lsr(wsina_sinb)
|
||||
lsr(wsina_sinb)
|
||||
lsr(wsina_sinb) ; / 128
|
||||
|
||||
float cosa_sinb = wcosa_sinb as float / 128.0
|
||||
float sina_sinb = wsina_sinb as float / 128.0
|
||||
float Axx = wcosa*wcosb as float / 16384.0
|
||||
float Axy = cosa_sinb*(wsinc as float / 128.0) - (wsina*wcosc as float / 16384.0)
|
||||
float Axz = cosa_sinb*(wcosc as float / 128.0) + (wsina*wsinc as float / 16384.0)
|
||||
float Ayx = wsina*wcosb as float / 16384.0
|
||||
float Ayy = sina_sinb*(wsinc as float / 128.0) + (wcosa*wcosc as float / 16384.0)
|
||||
float Ayz = sina_sinb*(wcosc as float / 128.0) - (wcosa*wsinc as float / 16384.0)
|
||||
float Azx = -wsinb as float / 128.0
|
||||
float Azy = wcosb*wsinc as float / 16384.0
|
||||
float Azz = wcosb*wcosc as float / 16384.0
|
||||
|
||||
word wAxx = Axx * 128.0 as word
|
||||
word wAxy = Axy * 128.0 as word
|
||||
word wAxz = Axz * 128.0 as word
|
||||
word wAyx = Ayx * 128.0 as word
|
||||
word wAyy = Ayy * 128.0 as word
|
||||
word wAyz = Ayz * 128.0 as word
|
||||
word wAzx = Azx * 128.0 as word
|
||||
word wAzy = Azy * 128.0 as word
|
||||
word wAzz = Azz * 128.0 as word
|
||||
|
||||
for ubyte i in 0 to len(xcoor)-1 {
|
||||
word xc = xcoor[i] as word
|
||||
word yc = ycoor[i] as word
|
||||
word zc = zcoor[i] as word
|
||||
word zz = wAxx*xc + wAxy*yc + wAxz*zc
|
||||
lsr(zz)
|
||||
lsr(zz)
|
||||
lsr(zz)
|
||||
lsr(zz)
|
||||
lsr(zz)
|
||||
lsr(zz)
|
||||
lsr(zz) ; /128
|
||||
rotatedx[i] = zz
|
||||
zz=wAyx*xc + wAyy*yc + wAyz*zc
|
||||
lsr(zz)
|
||||
lsr(zz)
|
||||
lsr(zz)
|
||||
lsr(zz)
|
||||
lsr(zz)
|
||||
lsr(zz)
|
||||
lsr(zz) ; /128
|
||||
rotatedy[i] = zz
|
||||
zz = wAzx*xc + wAzy*yc + wAzz*zc
|
||||
lsr(zz)
|
||||
lsr(zz)
|
||||
lsr(zz)
|
||||
lsr(zz)
|
||||
lsr(zz)
|
||||
lsr(zz)
|
||||
lsr(zz) ; /128
|
||||
rotatedz[i] = zz
|
||||
}
|
||||
}
|
||||
|
||||
sub draw_edges() {
|
||||
|
||||
sub toscreenx(float x, float z) -> byte {
|
||||
return x/(250.0+z) * (height as float) as byte + width // 2
|
||||
}
|
||||
|
||||
sub toscreeny(float y, float z) -> byte {
|
||||
return y/(250.0+z) * (height as float) as byte + height // 2
|
||||
}
|
||||
|
||||
; plot the points of the 3d cube
|
||||
; first the points on the back, then the points on the front (painter algorithm)
|
||||
|
||||
for ubyte i in 0 to len(xcoor)-1 {
|
||||
word rz = rotatedz[i]
|
||||
if rz >= 10 {
|
||||
ubyte sx = toscreenx(rotatedx[i] as float, rz as float) as ubyte ; @todo crash when not using 'as float' for the param!
|
||||
ubyte sy = toscreeny(rotatedy[i] as float, rz as float) as ubyte ; @todo crash when not using 'as float' for the param!
|
||||
c64scr.setchrclr(sx, sy, 46, i+2)
|
||||
}
|
||||
}
|
||||
|
||||
; @todo integer / integer should usually result in a FLOAT, not INT. the // operator is for integer division!
|
||||
|
||||
for ubyte i in 0 to len(xcoor)-1 {
|
||||
word rz = rotatedz[i]
|
||||
if rz < 10 {
|
||||
ubyte sx = toscreenx(rotatedx[i] as float, rz as float) as ubyte ; @todo crash when not using 'as float' for the param!
|
||||
ubyte sy = toscreeny(rotatedy[i] as float, rz as float) as ubyte ; @todo crash when not using 'as float' for the param!
|
||||
c64scr.setchrclr(sx, sy, 81, i+2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -62,9 +62,8 @@ sub irq() {
|
||||
angle++
|
||||
c64.MSIGX=0
|
||||
for ubyte i in 0 to 14 step 2 {
|
||||
word x = (sin8(angle*2-i*8) as word)+190
|
||||
byte y = cos8(angle*3-i*8)
|
||||
lsr(y)
|
||||
word x = (sin8(angle*2-i*8) as word)+190 ; @todo will/should be using shifts for faster multiplication
|
||||
byte y = cos8(angle*3-i*8) // 2 ; @todo will/should be using shifts for faster multiplication
|
||||
@(SP0X+i) = lsb(x)
|
||||
@(SP0Y+i) = y+150 as ubyte
|
||||
|
||||
|
@ -153,10 +153,11 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
override fun process(block: Block): IStatement {
|
||||
prog.newBlock(block.scopedname, block.name, block.address, block.options())
|
||||
processVariables(block) // @todo optimize initializations with same value: load the value only once (sort on initalization value, datatype ?)
|
||||
prog.label("block."+block.scopedname)
|
||||
prog.label("block."+block.scopedname, false)
|
||||
prog.line(block.position)
|
||||
translate(block.statements)
|
||||
return super.process(block)
|
||||
val r = super.process(block)
|
||||
return r
|
||||
}
|
||||
|
||||
private fun processVariables(scope: INameScope) {
|
||||
@ -168,18 +169,22 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
|
||||
override fun process(subroutine: Subroutine): IStatement {
|
||||
if(subroutine.asmAddress==null) {
|
||||
prog.label(subroutine.scopedname)
|
||||
prog.label(subroutine.scopedname, true)
|
||||
prog.instr(Opcode.START_PROCDEF)
|
||||
prog.line(subroutine.position)
|
||||
// note: the caller has already written the arguments into the subroutine's parameter variables.
|
||||
translate(subroutine.statements)
|
||||
val r= super.process(subroutine)
|
||||
prog.instr(Opcode.END_PROCDEF)
|
||||
return r
|
||||
} else {
|
||||
// asmsub
|
||||
if(subroutine.isNotEmpty())
|
||||
throw CompilerException("kernel subroutines (with memory address) can't have a body: $subroutine")
|
||||
|
||||
prog.memoryPointer(subroutine.scopedname, subroutine.asmAddress, DataType.UBYTE) // the datatype is a bit of a dummy in this case
|
||||
return super.process(subroutine)
|
||||
}
|
||||
return super.process(subroutine)
|
||||
}
|
||||
|
||||
private fun translate(statements: List<IStatement>) {
|
||||
@ -1809,6 +1814,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
}
|
||||
|
||||
// TODO: optimize edge cases if last value = 255 or 0 (for bytes) etc. to avoid PUSH_BYTE / SUB opcodes and make use of the wrapping around of the value.
|
||||
// TODO: ubyte/uword can't count down to 0 with negative step because test value will be <0 which causes "value out of range" crash
|
||||
prog.instr(opcodePush(varDt), Value(varDt, range.last + range.step))
|
||||
prog.instr(opcodePushvar(varDt), callLabel = varname)
|
||||
prog.instr(opcodeSub(varDt))
|
||||
|
@ -34,7 +34,7 @@ open class Instruction(val opcode: Opcode,
|
||||
}
|
||||
}
|
||||
|
||||
class LabelInstr(val name: String) : Instruction(Opcode.NOP, null, null) {
|
||||
class LabelInstr(val name: String, val asmProc: Boolean) : Instruction(Opcode.NOP, null, null) {
|
||||
override fun toString(): String {
|
||||
return "\n$name:"
|
||||
}
|
||||
|
@ -358,8 +358,8 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
|
||||
currentBlock.instructions.add(Instruction(opcode, arg, callLabel = callLabel))
|
||||
}
|
||||
|
||||
fun label(labelname: String) {
|
||||
val instr = LabelInstr(labelname)
|
||||
fun label(labelname: String, asmProc: Boolean=false) {
|
||||
val instr = LabelInstr(labelname, asmProc)
|
||||
currentBlock.instructions.add(instr)
|
||||
currentBlock.labels[labelname] = instr
|
||||
}
|
||||
|
@ -239,10 +239,12 @@ enum class Opcode {
|
||||
JNZW, // branch if value is not zero (word)
|
||||
|
||||
|
||||
// subroutine calling
|
||||
// subroutines
|
||||
CALL,
|
||||
RETURN,
|
||||
SYSCALL,
|
||||
START_PROCDEF,
|
||||
END_PROCDEF,
|
||||
|
||||
// misc
|
||||
SEC, // set carry status flag NOTE: is mostly fake, carry flag is not affected by any numeric operations
|
||||
|
@ -33,7 +33,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
val newlabels = block.labels.map { symname(it.key, block) to it.value}.toMap().toMutableMap()
|
||||
val newinstructions = block.instructions.asSequence().map {
|
||||
when {
|
||||
it is LabelInstr -> LabelInstr(symname(it.name, block))
|
||||
it is LabelInstr -> LabelInstr(symname(it.name, block), it.asmProc)
|
||||
it.opcode == Opcode.INLINE_ASSEMBLY -> it
|
||||
else ->
|
||||
Instruction(it.opcode, it.arg, it.arg2,
|
||||
@ -394,16 +394,21 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
if(ins is LabelInstr) {
|
||||
if(ins.name.startsWith("block."))
|
||||
return ""
|
||||
return if(ins.name.startsWith("${block.shortname}."))
|
||||
ins.name.substring(block.shortname.length+1)
|
||||
else
|
||||
ins.name
|
||||
|
||||
val labelresult =
|
||||
if(ins.name.startsWith("${block.shortname}."))
|
||||
ins.name.substring(block.shortname.length+1)
|
||||
else
|
||||
ins.name
|
||||
return if(ins.asmProc) labelresult+"\t\t.proc" else labelresult
|
||||
}
|
||||
|
||||
// simple opcodes that are translated directly into one or a few asm instructions
|
||||
return when(ins.opcode) {
|
||||
Opcode.LINE -> " ;\tsrc line: ${ins.callLabel}"
|
||||
Opcode.NOP -> " nop" // shouldn't be present anymore though
|
||||
Opcode.START_PROCDEF -> "" // is done as part of a label
|
||||
Opcode.END_PROCDEF -> " .pend"
|
||||
Opcode.TERMINATE -> " brk"
|
||||
Opcode.SEC -> " sec"
|
||||
Opcode.CLC -> " clc"
|
||||
|
@ -19,7 +19,7 @@ class Program (val name: String,
|
||||
{
|
||||
init {
|
||||
// add end of program marker and some sentinel instructions, to correctly connect all others
|
||||
program.add(LabelInstr("____program_end"))
|
||||
program.add(LabelInstr("____program_end", false))
|
||||
program.add(Instruction(Opcode.TERMINATE))
|
||||
program.add(Instruction(Opcode.NOP))
|
||||
connect()
|
||||
|
@ -254,6 +254,7 @@ class StackVm(private var traceOutputFile: String?) {
|
||||
traceOutput?.println("\n$ins")
|
||||
when (ins.opcode) {
|
||||
Opcode.NOP -> {}
|
||||
Opcode.START_PROCDEF, Opcode.END_PROCDEF -> {}
|
||||
Opcode.PUSH_BYTE -> {
|
||||
checkDt(ins.arg, DataType.UBYTE, DataType.BYTE)
|
||||
evalstack.push(ins.arg)
|
||||
|
@ -156,9 +156,9 @@ mul_word .proc
|
||||
stx c64.SCRATCH_ZPREGX
|
||||
jsr math.multiply_words
|
||||
ldx c64.SCRATCH_ZPREGX
|
||||
lda math.multiply_words_result
|
||||
lda math.multiply_words.multiply_words_result
|
||||
sta c64.ESTACK_LO+1,x
|
||||
lda math.multiply_words_result+1
|
||||
lda math.multiply_words.multiply_words_result+1
|
||||
sta c64.ESTACK_HI+1,x
|
||||
rts
|
||||
.pend
|
||||
|
Loading…
x
Reference in New Issue
Block a user