sine table and bit shifting of signed values fixed

This commit is contained in:
Irmen de Jong 2019-01-05 02:42:58 +01:00
parent 32d82e8e56
commit 39a8508daa
16 changed files with 443 additions and 259 deletions

View File

@ -0,0 +1,93 @@
%import c64utils
%option enable_floats
~ main {
const uword width = 40
const uword height = 25
; 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 ]
; storage for rotated coordinates
float[len(xcoor)] rotatedx=0.0
float[len(ycoor)] rotatedy=0.0
float[len(zcoor)] rotatedz=-1.0
sub start() {
float time=0.0
while(true) {
rotate_vertices(time)
c64.CLEARSCR()
draw_edges()
time+=0.2
}
}
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 {
float xc = xcoor[i]
float yc = ycoor[i]
float zc = zcoor[i]
rotatedx[i] = Axx*xc + Axy*yc + Axz*zc
rotatedy[i] = Ayx*xc + Ayy*yc + Ayz*zc
rotatedz[i] = Azx*xc + Azy*yc + Azz*zc
}
}
sub draw_edges() {
sub toscreenx(float x, float z) -> byte {
return x/(5.0+z) * (height as float) as byte + width // 2
}
sub toscreeny(float y, float z) -> byte {
return y/(5.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 {
float rz = rotatedz[i]
if rz >= 0.1 {
ubyte sx = toscreenx(rotatedx[i], rz) as ubyte
ubyte sy = toscreeny(rotatedy[i], rz) as ubyte
c64scr.setchrclr(sx, sy, 46, i+2)
}
}
for ubyte i in 0 to len(xcoor)-1 {
float rz = rotatedz[i]
if rz < 0.1 {
ubyte sx = toscreenx(rotatedx[i], rz) as ubyte
ubyte sy = toscreeny(rotatedy[i], rz) as ubyte
c64scr.setchrclr(sx, sy, 81, i+2)
}
}
}
}

View File

@ -1,5 +1,5 @@
%import c64utils
%option enable_floats
%option enable_floats ; @todo needed for now to avoid compile error in c64lib
~ main {
@ -7,85 +7,104 @@
const uword height = 25
; 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 ]
byte[8] xcoor = [ -100, -100, -100, -100, 100, 100, 100, 100 ]
byte[8] ycoor = [ -100, -100, 100, 100, -100, -100, 100, 100 ]
byte[8] zcoor = [ -100, 100, -100, 100, -100, 100, -100, 100 ]
; storage for rotated coordinates
float[len(xcoor)] rotatedx=0.0
float[len(ycoor)] rotatedy=0.0
float[len(zcoor)] rotatedz=-1.0
word[len(xcoor)] rotatedx=0
word[len(ycoor)] rotatedy=0
word[len(zcoor)] rotatedz=-32767
sub start() {
float time=0.0
uword anglex
uword angley
uword anglez
while(true) {
rotate_vertices(time)
c64.CLEARSCR()
draw_edges()
time+=0.2
rotate_vertices(anglex, angley, anglez)
; c64.CLEARSCR()
; draw_edges()
anglex+=256
angley+=83
anglez+=201
}
}
sub rotate_vertices(float t) {
sub rotate_vertices(uword ax, uword ay, uword az) {
; 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)
word cosa = cos8(msb(ax)) as word
word sina = sin8(msb(ax)) as word
word cosb = cos8(msb(ay)) as word
word sinb = sin8(msb(ay)) as word
word cosc = cos8(msb(az)) as word
word sinc = sin8(msb(az)) as word
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
word cosa_sinb = msb(cosa*sinb)
word sina_sinb = msb(sina*sinb)
c64.CHROUT('>')
c64scr.print_w(cosa_sinb)
c64.CHROUT(',')
c64scr.print_w(sina_sinb)
c64.CHROUT('\n')
word Axx = msb(cosa*cosb)
word Axy = msb(cosa_sinb*sinc - sina*cosc)
word Axz = msb(cosa_sinb*cosc + sina*sinc)
word Ayx = msb(sina*cosb)
word Ayy = msb(sina_sinb*sinc + cosa*cosc)
word Ayz = msb(sina_sinb*cosc - cosa*sinc)
word Azx = -sinb
word Azy = msb(cosb*sinc)
word Azz = msb(cosb*cosc)
c64.CHROUT('>')
c64scr.print_w(Axx)
c64.CHROUT(',')
c64scr.print_w(Axy)
c64.CHROUT(',')
c64scr.print_w(Axz)
c64.CHROUT('\n')
for ubyte i in 0 to len(xcoor)-1 {
float xc = xcoor[i]
float yc = ycoor[i]
float zc = zcoor[i]
rotatedx[i] = Axx*xc + Axy*yc + Axz*zc
rotatedy[i] = Ayx*xc + Ayy*yc + Ayz*zc
rotatedz[i] = Azx*xc + Azy*yc + Azz*zc
word xc = xcoor[i]
word yc = ycoor[i]
word zc = zcoor[i]
rotatedx[i] = Axx*xc ;+ Axy*yc + Axz*zc ; @todo wrong code generated? crash!
rotatedy[i] = Ayx*xc ;+ Ayy*yc + Ayz*zc ; @todo wrong code generated? crash!
rotatedz[i] = Azx*xc ;+ Azy*yc + Azz*zc ; @todo wrong code generated? crash!
}
}
sub draw_edges() {
sub toscreenx(float x, float z) -> byte {
return x/(5.0+z) * (height as float) as byte + width // 2
sub toscreenx(word x, word z) -> ubyte {
return msb(x) and 31
}
sub toscreeny(float y, float z) -> byte {
return y/(5.0+z) * (height as float) as byte + height // 2
sub toscreeny(word y, word z) -> ubyte {
return msb(y) and 15
}
; 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 {
float rz = rotatedz[i]
if rz >= 0.1 {
ubyte sx = toscreenx(rotatedx[i], rz) as ubyte
ubyte sy = toscreeny(rotatedy[i], rz) as ubyte
word rz = rotatedz[i]
if rz >= 100 {
ubyte sx = toscreenx(rotatedx[i], rz)
ubyte sy = toscreeny(rotatedy[i], rz)
c64scr.setchrclr(sx, sy, 46, i+2)
}
}
for ubyte i in 0 to len(xcoor)-1 {
float rz = rotatedz[i]
if rz < 0.1 {
ubyte sx = toscreenx(rotatedx[i], rz) as ubyte
ubyte sy = toscreeny(rotatedy[i], rz) as ubyte
word rz = rotatedz[i]
if rz < 100 {
ubyte sx = toscreenx(rotatedx[i], rz)
ubyte sy = toscreeny(rotatedy[i], rz)
c64scr.setchrclr(sx, sy, 81, i+2)
}
}

View File

@ -40,7 +40,7 @@
c64.STROUT("balloon sprites!\n")
c64.STROUT("...we are all floating...\n")
const uword sprite_address_ptr = &balloonsprite // 64
const uword sprite_address_ptr = $0a00 // 64
c64.SPRPTR0 = sprite_address_ptr
c64.SPRPTR1 = sprite_address_ptr
c64.SPRPTR2 = sprite_address_ptr

View File

@ -0,0 +1,36 @@
%import c64utils
%option enable_floats
~ main {
const uword width = 40
const uword height = 25
sub start() {
float t
ubyte color
while true {
float x = sin(t)
float y = cos(t*1.1356)
ubyte xx=screenx(x)
ubyte yy=screeny(y)
;c64.COLOR = color
;c64scr.PLOT(xx,yy)
;c64.CHROUT('Q') ; shift-q = filled circle
c64scr.setchrclr(xx, yy, 81, color)
t += 0.08
color++
}
}
sub screenx(float x) -> ubyte {
return (x * width/2.2) + width/2.0 as ubyte
}
sub screeny(float y) -> ubyte {
return (y * height/2.2) + height/2.0 as ubyte
}
}

View File

@ -1,5 +1,5 @@
%import c64utils
%option enable_floats
%option enable_floats ; @todo needed for now to avoid compile error in c64lib
~ main {
@ -8,29 +8,20 @@
sub start() {
float t
uword anglex
uword angley
ubyte color
while true {
float x = sin(t)
float y = cos(t*1.1356)
ubyte xx=screenx(x)
ubyte yy=screeny(y)
;c64.COLOR = color
;c64scr.PLOT(xx,yy)
;c64.CHROUT('Q') ; shift-q = filled circle
word x = sin8(msb(anglex)) as word
word y = cos8(msb(angley)) as word
ubyte xx=msb(x*39) + 20 ; -127..127 -> 0..39
ubyte yy=msb(y*24) + 12 ; -127..127 -> 0..24
c64scr.setchrclr(xx, yy, 81, color)
t += 0.08
anglex+=800
angley+=947
color++
}
}
sub screenx(float x) -> ubyte {
return (x * width/2.2) + width/2.0 as ubyte
}
sub screeny(float y) -> ubyte {
return (y * height/2.2) + height/2.0 as ubyte
}
}

View File

@ -5,148 +5,39 @@
~ main {
sub start() {
ubyte i=0
memory byte b1 = $c000
memory byte b2 = $c001
memory word w1 = $c002
memory word w2 = $c004
vm_write_str("sin 0 ")
i=0
vm_write_num(sin8(0))
vm_write_char(':')
vm_write_num(sin8(i))
vm_write_char('\n')
vm_write_str("sin 50 ")
i=50
vm_write_num(sin8(50))
vm_write_char(':')
vm_write_num(sin8(i))
vm_write_char('\n')
b1=50
b2=-50
w1=100
w2=-100
vm_write_str("sin 128 ")
i=128
vm_write_num(sin8(128))
vm_write_char(':')
vm_write_num(sin8(i))
vm_write_char('\n')
c64scr.print_b(b1)
c64.CHROUT('/')
lsr(b1)
c64scr.print_b(b1)
c64.CHROUT('\n')
c64scr.print_b(b2)
c64.CHROUT('/')
lsr(b2)
c64scr.print_b(b2)
c64.CHROUT('\n')
c64scr.print_w(w1)
c64.CHROUT('/')
lsr(w1)
c64scr.print_w(w1)
c64.CHROUT('\n')
c64scr.print_w(w2)
c64.CHROUT('/')
lsr(w2)
c64scr.print_w(w2)
c64.CHROUT('\n')
vm_write_str("sin 140 ")
i=140
vm_write_num(sin8(140))
vm_write_char(':')
vm_write_num(sin8(i))
vm_write_char('\n')
vm_write_str("sin 250 ")
i=250
vm_write_num(sin8(250))
vm_write_char(':')
vm_write_num(sin8(i))
vm_write_char('\n')
vm_write_str("cos 0 ")
i=0
vm_write_num(cos8(0))
vm_write_char(':')
vm_write_num(cos8(i))
vm_write_char('\n')
vm_write_str("cos 50 ")
i=50
vm_write_num(cos8(50))
vm_write_char(':')
vm_write_num(cos8(i))
vm_write_char('\n')
vm_write_str("cos 128 ")
i=128
vm_write_num(cos8(128))
vm_write_char(':')
vm_write_num(cos8(i))
vm_write_char('\n')
vm_write_str("cos 140 ")
i=140
vm_write_num(cos8(140))
vm_write_char(':')
vm_write_num(cos8(i))
vm_write_char('\n')
vm_write_str("cos 250 ")
i=250
vm_write_num(cos8(250))
vm_write_char(':')
vm_write_num(cos8(i))
vm_write_char('\n')
vm_write_char('\n')
vm_write_str("sin16 0 ")
i=0
vm_write_num(sin16(0))
vm_write_char(':')
vm_write_num(sin16(i))
vm_write_char('\n')
vm_write_str("sin16 50 ")
i=50
vm_write_num(sin16(50))
vm_write_char(':')
vm_write_num(sin16(i))
vm_write_char('\n')
vm_write_str("sin16 128 ")
i=128
vm_write_num(sin16(128))
vm_write_char(':')
vm_write_num(sin16(i))
vm_write_char('\n')
vm_write_str("sin16 140 ")
i=140
vm_write_num(sin16(140))
vm_write_char(':')
vm_write_num(sin16(i))
vm_write_char('\n')
vm_write_str("sin16 250 ")
i=250
vm_write_num(sin16(250))
vm_write_char(':')
vm_write_num(sin16(i))
vm_write_char('\n')
vm_write_str("cos16 0 ")
i=0
vm_write_num(cos16(0))
vm_write_char(':')
vm_write_num(cos16(i))
vm_write_char('\n')
vm_write_str("cos16 50 ")
i=50
vm_write_num(cos16(50))
vm_write_char(':')
vm_write_num(cos16(i))
vm_write_char('\n')
vm_write_str("cos16 128 ")
i=128
vm_write_num(cos16(128))
vm_write_char(':')
vm_write_num(cos16(i))
vm_write_char('\n')
vm_write_str("cos16 140 ")
i=140
vm_write_num(cos16(140))
vm_write_char(':')
vm_write_num(cos16(i))
vm_write_char('\n')
vm_write_str("cos16 250 ")
i=250
vm_write_num(cos16(250))
vm_write_char(':')
vm_write_num(cos16(i))
vm_write_char('\n')
}
}

View File

@ -0,0 +1,79 @@
%import c64utils
%option enable_floats ; @todo needed for now to avoid compile error in c64lib
~ spritedata $0a00 {
; this memory block contains the sprite data
; it must start on an address aligned to 64 bytes.
%option force_output ; make sure the data in this block appears in the resulting program
ubyte[63] balloonsprite = [ %00000000,%01111111,%00000000,
%00000001,%11111111,%11000000,
%00000011,%11111111,%11100000,
%00000011,%11100011,%11100000,
%00000111,%11011100,%11110000,
%00000111,%11011101,%11110000,
%00000111,%11011100,%11110000,
%00000011,%11100011,%11100000,
%00000011,%11111111,%11100000,
%00000011,%11111111,%11100000,
%00000010,%11111111,%10100000,
%00000001,%01111111,%01000000,
%00000001,%00111110,%01000000,
%00000000,%10011100,%10000000,
%00000000,%10011100,%10000000,
%00000000,%01001001,%00000000,
%00000000,%01001001,%00000000,
%00000000,%00111110,%00000000,
%00000000,%00111110,%00000000,
%00000000,%00111110,%00000000,
%00000000,%00011100,%00000000 ]
}
~ main {
sub start() {
const uword sprite_address_ptr = $0a00 // 64
c64.SPRPTR0 = sprite_address_ptr
c64.SPRPTR1 = sprite_address_ptr
c64.SPRPTR2 = sprite_address_ptr
c64.SPRPTR3 = sprite_address_ptr
c64.SPRPTR4 = sprite_address_ptr
c64.SPRPTR5 = sprite_address_ptr
c64.SPRPTR6 = sprite_address_ptr
c64.SPRPTR7 = sprite_address_ptr
c64.SPENA = 255 ; enable all sprites
c64utils.set_rasterirq(240) ; enable animation
}
}
~ irq {
ubyte angle=0
sub irq() {
const uword SP0X = $d000
const uword SP0Y = $d001
c64.EXTCOL--
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)
@(SP0X+i) = lsb(x)
@(SP0Y+i) = y+150 as ubyte
lsr(c64.MSIGX)
if msb(x) c64.MSIGX |= %10000000
}
c64.EXTCOL++
}
}

View File

@ -783,8 +783,8 @@ private class StatementTranslator(private val prog: IntermediateProgram,
val arg = args.single()
val dt = arg.resultingDatatype(namespace, heap)
when (dt) {
DataType.UBYTE -> prog.instr(Opcode.SHL_BYTE)
DataType.UWORD -> prog.instr(Opcode.SHL_WORD)
DataType.UBYTE, DataType.BYTE -> prog.instr(Opcode.SHL_BYTE)
DataType.UWORD, DataType.WORD -> prog.instr(Opcode.SHL_WORD)
else -> throw CompilerException("wrong datatype")
}
// this function doesn't return a value on the stack so we pop it directly into the argument register/variable again
@ -794,8 +794,10 @@ private class StatementTranslator(private val prog: IntermediateProgram,
val arg = args.single()
val dt = arg.resultingDatatype(namespace, heap)
when (dt) {
DataType.UBYTE -> prog.instr(Opcode.SHR_BYTE)
DataType.UWORD -> prog.instr(Opcode.SHR_WORD)
DataType.UBYTE -> prog.instr(Opcode.SHR_UBYTE)
DataType.BYTE -> prog.instr(Opcode.SHR_SBYTE)
DataType.UWORD -> prog.instr(Opcode.SHR_UWORD)
DataType.WORD -> prog.instr(Opcode.SHR_SWORD)
else -> throw CompilerException("wrong datatype")
}
// this function doesn't return a value on the stack so we pop it directly into the argument register/variable again

View File

@ -81,12 +81,18 @@ enum class Opcode {
SHL_MEM_WORD,
SHL_VAR_BYTE,
SHL_VAR_WORD,
SHR_BYTE,
SHR_WORD,
SHR_MEM_BYTE,
SHR_MEM_WORD,
SHR_VAR_BYTE,
SHR_VAR_WORD,
SHR_UBYTE,
SHR_SBYTE,
SHR_UWORD,
SHR_SWORD,
SHR_MEM_UBYTE,
SHR_MEM_SBYTE,
SHR_MEM_UWORD,
SHR_MEM_SWORD,
SHR_VAR_UBYTE,
SHR_VAR_SBYTE,
SHR_VAR_UWORD,
SHR_VAR_SWORD,
ROL_BYTE,
ROL_WORD,
ROL_MEM_BYTE,
@ -259,7 +265,8 @@ enum class Opcode {
val opcodesWithVarArgument = setOf(
Opcode.INC_VAR_B, Opcode.INC_VAR_W, Opcode.DEC_VAR_B, Opcode.DEC_VAR_W,
Opcode.INC_VAR_UB, Opcode.INC_VAR_UW, Opcode.DEC_VAR_UB, Opcode.DEC_VAR_UW,
Opcode.SHR_VAR_BYTE, Opcode.SHR_VAR_WORD, Opcode.SHL_VAR_BYTE, Opcode.SHL_VAR_WORD,
Opcode.SHR_VAR_SBYTE, Opcode.SHR_VAR_UBYTE, Opcode.SHR_VAR_SWORD, Opcode.SHR_VAR_UWORD,
Opcode.SHL_VAR_BYTE, Opcode.SHL_VAR_WORD,
Opcode.ROL_VAR_BYTE, Opcode.ROL_VAR_WORD, Opcode.ROR_VAR_BYTE, Opcode.ROR_VAR_WORD,
Opcode.ROL2_VAR_BYTE, Opcode.ROL2_VAR_WORD, Opcode.ROR2_VAR_BYTE, Opcode.ROR2_VAR_WORD,
Opcode.POP_VAR_BYTE, Opcode.POP_VAR_WORD, Opcode.POP_VAR_FLOAT,

View File

@ -235,11 +235,13 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
fun shr(): Value {
val v = integerValue()
if(type==DataType.UBYTE)
return Value(type, (v ushr 1) and 255)
if(type==DataType.UWORD)
return Value(type, (v ushr 1) and 65535)
throw ValueException("invalid type for shr: $type")
return when(type){
DataType.UBYTE -> Value(type, (v ushr 1) and 255)
DataType.BYTE -> TODO("shr sbyte")
DataType.UWORD -> Value(type, (v ushr 1) and 65535)
DataType.WORD -> TODO("shr sword")
else -> throw ValueException("invalid type for shr: $type")
}
}
fun rol(carry: Boolean): Pair<Value, Boolean> {

View File

@ -922,16 +922,18 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
// an in place operation that consists of a push-value / op / push-index-value / pop-into-indexed-var
return when(ins.opcode) {
Opcode.SHL_BYTE -> AsmFragment(" asl $variable+$index", 8)
Opcode.SHR_BYTE -> AsmFragment(" lsr $variable+$index", 8)
Opcode.SHL_WORD -> AsmFragment(" asl $variable+$index | rol $variable+${index+1}", 8)
Opcode.SHR_WORD -> AsmFragment(" lsr $variable+${index+1},x | ror $variable+$index", 8)
Opcode.SHR_UBYTE -> AsmFragment(" lsr $variable+$index", 8)
Opcode.SHR_SBYTE -> AsmFragment(" lda $variable+$index | asl a | ror $variable+$index")
Opcode.SHL_WORD -> AsmFragment(" asl $variable+${index+1} | rol $variable+$index", 8)
Opcode.SHR_UWORD -> AsmFragment(" lsr $variable+${index+1} | ror $variable+$index", 8)
Opcode.SHR_SWORD -> AsmFragment(" lda $variable+${index+1} | asl a | ror $variable+${index+1} | ror $variable+$index", 8)
Opcode.ROL_BYTE -> AsmFragment(" rol $variable+$index", 8)
Opcode.ROR_BYTE -> AsmFragment(" ror $variable+$index", 8)
Opcode.ROL_WORD -> AsmFragment(" rol $variable+$index | rol $variable+${index+1}", 8)
Opcode.ROL_WORD -> AsmFragment(" rol $variable+${index+1} | rol $variable+$index", 8)
Opcode.ROR_WORD -> AsmFragment(" ror $variable+${index+1} | ror $variable+$index", 8)
Opcode.ROL2_BYTE -> AsmFragment(" lda $variable+$index | cmp #\$80 | rol $variable+$index", 8)
Opcode.ROR2_BYTE -> AsmFragment(" lda $variable+$index | lsr a | bcc + | ora #\$80 |+ | sta $variable+$index", 10)
Opcode.ROL2_WORD -> AsmFragment(" asl $variable+$index | rol $variable+${index+1} | bcc + | inc $variable+$index |+",20)
Opcode.ROL2_WORD -> AsmFragment(" asl $variable+${index+1} | rol $variable+$index | bcc + | inc $variable+$index |+",20) // todo wrong???
Opcode.ROR2_WORD -> AsmFragment(" lsr $variable+${index+1} | ror $variable+$index | bcc + | lda $variable+${index+1} | ora #\$80 | sta $variable+${index+1} |+", 30)
Opcode.INC_INDEXED_VAR_B, Opcode.INC_INDEXED_VAR_UB -> AsmFragment(" inc $variable+$index", 2)
Opcode.DEC_INDEXED_VAR_B, Opcode.DEC_INDEXED_VAR_UB -> AsmFragment(" dec $variable+$index", 5)
@ -974,9 +976,11 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
return when (ins.opcode) {
Opcode.SHL_BYTE -> AsmFragment(" txa | $loadX asl $variable,x | tax", 10)
Opcode.SHR_BYTE -> AsmFragment(" txa | $loadX lsr $variable,x | tax", 10)
Opcode.SHR_UBYTE -> AsmFragment(" txa | $loadX lsr $variable,x | tax", 10)
Opcode.SHR_SBYTE -> AsmFragment("$saveX $loadX lda $variable,x | asl a | ror $variable,x $restoreX", 10)
Opcode.SHL_WORD -> AsmFragment("$saveX $loadXWord asl $variable,x | rol $variable+1,x $restoreX", 10)
Opcode.SHR_WORD -> AsmFragment("$saveX $loadXWord lsr $variable+1,x | ror $variable,x $restoreX", 10)
Opcode.SHR_UWORD -> AsmFragment("$saveX $loadXWord lsr $variable+1,x | ror $variable,x $restoreX", 10)
Opcode.SHR_SWORD -> AsmFragment("$saveX $loadXWord lda $variable+1,x | asl a | ror $variable+1,x | ror $variable,x $restoreX", 10)
Opcode.ROL_BYTE -> AsmFragment(" txa | $loadX rol $variable,x | tax", 10)
Opcode.ROR_BYTE -> AsmFragment(" txa | $loadX ror $variable,x | tax", 10)
Opcode.ROL_WORD -> AsmFragment("$saveX $loadXWord rol $variable,x | rol $variable+1,x $restoreX", 10)
@ -999,14 +1003,16 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
}
private fun sameMemOperation(address: Int, ins: Instruction): AsmFragment? {
// an in place operation that consists of a push-mem / op / pop-mem sequence
// an in place operation that consists of push-mem / op / pop-mem
val addr = address.toHex()
val addrHi = (address+1).toHex()
return when(ins.opcode) {
Opcode.SHL_BYTE -> AsmFragment(" asl $addr", 10)
Opcode.SHR_BYTE -> AsmFragment(" lsr $addr", 10)
Opcode.SHR_UBYTE -> AsmFragment(" lsr $addr", 10)
Opcode.SHR_SBYTE -> AsmFragment(" lda $addr | asl a | ror $addr", 10)
Opcode.SHL_WORD -> AsmFragment(" asl $addr | rol $addrHi", 10)
Opcode.SHR_WORD -> AsmFragment(" lsr $addrHi | ror $addr", 10)
Opcode.SHR_UWORD -> AsmFragment(" lsr $addrHi | ror $addr", 10)
Opcode.SHR_SWORD -> AsmFragment(" lda $addrHi | asl a | ror $addrHi | ror $addr", 10)
Opcode.ROL_BYTE -> AsmFragment(" rol $addr", 10)
Opcode.ROR_BYTE -> AsmFragment(" ror $addr", 10)
Opcode.ROL_WORD -> AsmFragment(" rol $addr | rol $addrHi", 10)
@ -1030,7 +1036,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
else -> AsmFragment(" asl $variable", 10)
}
}
Opcode.SHR_BYTE -> {
Opcode.SHR_UBYTE -> {
when (variable) {
"A" -> AsmFragment(" lsr a", 10)
"X" -> AsmFragment(" txa | lsr a | tax", 10)
@ -1038,12 +1044,25 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
else -> AsmFragment(" lsr $variable", 10)
}
}
Opcode.SHR_SBYTE -> {
// arithmetic shift right (keep sign bit)
when (variable) {
"A" -> AsmFragment(" cmp #$80 | ror a", 10)
"X" -> AsmFragment(" txa | cmp #$80 | ror a | tax", 10)
"Y" -> AsmFragment(" tya | cmp #$80 | ror a | tay", 10)
else -> AsmFragment(" lda $variable | asl a | ror $variable", 10)
}
}
Opcode.SHL_WORD -> {
AsmFragment(" asl $variable | rol $variable+1", 10)
}
Opcode.SHR_WORD -> {
Opcode.SHR_UWORD -> {
AsmFragment(" lsr $variable+1 | ror $variable", 10)
}
Opcode.SHR_SWORD -> {
// arithmetic shift right (keep sign bit)
AsmFragment(" lda $variable+1 | asl a | ror $variable+1 | ror $variable", 10)
}
Opcode.ROL_BYTE -> {
when (variable) {
"A" -> AsmFragment(" rol a", 10)
@ -2880,7 +2899,18 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
listOf(Opcode.PUSH_MEM_UB, Opcode.PUSH_BYTE, Opcode.BITXOR_BYTE)) { segment ->
" lda ${hexVal(segment[0])} | eor #${hexVal(segment[1])} | sta ${ESTACK_LO.toHex()},x | dex "
},
// push var byte | bytevalue
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.BITOR_BYTE)) { segment ->
" lda ${segment[0].callLabel} | ora #${hexVal(segment[1])} | sta ${ESTACK_LO.toHex()},x | dex "
},
// push var byte & bytevalue
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.BITAND_BYTE)) { segment ->
" lda ${segment[0].callLabel} | and #${hexVal(segment[1])} | sta ${ESTACK_LO.toHex()},x | dex "
},
// push var byte ^ bytevalue
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.BITXOR_BYTE)) { segment ->
" lda ${segment[0].callLabel} | eor #${hexVal(segment[1])} | sta ${ESTACK_LO.toHex()},x | dex "
},
// 16 bit addition avoiding excessive stack usage
// @todo optimize this even more with longer asmpatterns (avoid stack use altogether on most common operations)

View File

@ -22,8 +22,8 @@ val BuiltinFunctions = mapOf(
"ror" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null),
"rol2" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null),
"ror2" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null),
"lsl" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null),
"lsr" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null),
"lsl" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", IntegerDatatypes)), null),
"lsr" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", IntegerDatatypes)), null),
// these few have a return value depending on the argument(s):
"max" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.max()!! }}, // type depends on args
"min" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.min()!! }}, // type depends on args
@ -303,7 +303,7 @@ private fun builtinSin8(args: List<IExpression>, position: Position, namespace:I
throw SyntaxError("sin8 requires one argument", position)
val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
val rad = constval.asNumericValue!!.toDouble() /256.0 * 2.0 * PI
return LiteralValue(DataType.BYTE, bytevalue = (32767.5* sin(rad)).toInt().shr(8).toShort(), position = position)
return LiteralValue(DataType.BYTE, bytevalue = (32767.0* sin(rad)).toInt().shr(8).toShort(), position = position)
}
private fun builtinCos8(args: List<IExpression>, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue {
@ -311,7 +311,7 @@ private fun builtinCos8(args: List<IExpression>, position: Position, namespace:I
throw SyntaxError("cos8 requires one argument", position)
val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
val rad = constval.asNumericValue!!.toDouble() /256.0 * 2.0 * PI
return LiteralValue(DataType.BYTE, bytevalue = (32767.5* cos(rad)).toInt().shr(8).toShort(), position = position)
return LiteralValue(DataType.BYTE, bytevalue = (32767.0* cos(rad)).toInt().shr(8).toShort(), position = position)
}
private fun builtinSin16(args: List<IExpression>, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue {
@ -319,7 +319,7 @@ private fun builtinSin16(args: List<IExpression>, position: Position, namespace:
throw SyntaxError("sin16 requires one argument", position)
val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
val rad = constval.asNumericValue!!.toDouble() /256.0 * 2.0 * PI
return LiteralValue(DataType.WORD, wordvalue = (32767.5* sin(rad)).toInt(), position = position)
return LiteralValue(DataType.WORD, wordvalue = (32767.0* sin(rad)).toInt(), position = position)
}
private fun builtinCos16(args: List<IExpression>, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue {
@ -327,7 +327,7 @@ private fun builtinCos16(args: List<IExpression>, position: Position, namespace:
throw SyntaxError("cos16 requires one argument", position)
val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
val rad = constval.asNumericValue!!.toDouble() /256.0 * 2.0 * PI
return LiteralValue(DataType.WORD, wordvalue = (32767.5* cos(rad)).toInt(), position = position)
return LiteralValue(DataType.WORD, wordvalue = (32767.0* cos(rad)).toInt(), position = position)
}
private fun numericLiteral(value: Number, position: Position): LiteralValue {

View File

@ -564,16 +564,26 @@ class StackVm(private var traceOutputFile: String?) {
checkDt(v, DataType.UWORD)
evalstack.push(v.shl())
}
Opcode.SHR_BYTE -> {
Opcode.SHR_UBYTE -> {
val v = evalstack.pop()
checkDt(v, DataType.UBYTE)
evalstack.push(v.shr())
}
Opcode.SHR_WORD -> {
Opcode.SHR_SBYTE -> {
val v = evalstack.pop()
checkDt(v, DataType.BYTE)
evalstack.push(v.shr())
}
Opcode.SHR_UWORD -> {
val v = evalstack.pop()
checkDt(v, DataType.UWORD)
evalstack.push(v.shr())
}
Opcode.SHR_SWORD -> {
val v = evalstack.pop()
checkDt(v, DataType.WORD)
evalstack.push(v.shr())
}
Opcode.ROL_BYTE -> {
val v = evalstack.pop()
checkDt(v, DataType.UBYTE)
@ -691,18 +701,30 @@ class StackVm(private var traceOutputFile: String?) {
val newValue = value.shl()
mem.setUWord(addr, newValue.integerValue())
}
Opcode.SHR_MEM_BYTE -> {
Opcode.SHR_MEM_UBYTE -> {
val addr = ins.arg!!.integerValue()
val value = Value(DataType.UBYTE, mem.getUByte(addr))
val newValue = value.shr()
mem.setUByte(addr, newValue.integerValue().toShort())
}
Opcode.SHR_MEM_WORD -> {
Opcode.SHR_MEM_SBYTE -> {
val addr = ins.arg!!.integerValue()
val value = Value(DataType.BYTE, mem.getSByte(addr))
val newValue = value.shr()
mem.setSByte(addr, newValue.integerValue().toShort())
}
Opcode.SHR_MEM_UWORD -> {
val addr = ins.arg!!.integerValue()
val value = Value(DataType.UWORD, mem.getUWord(addr))
val newValue = value.shr()
mem.setUWord(addr, newValue.integerValue())
}
Opcode.SHR_MEM_SWORD -> {
val addr = ins.arg!!.integerValue()
val value = Value(DataType.WORD, mem.getSWord(addr))
val newValue = value.shr()
mem.setSWord(addr, newValue.integerValue())
}
Opcode.ROL_MEM_BYTE -> {
val addr = ins.arg!!.integerValue()
val value = Value(DataType.UBYTE, mem.getUByte(addr))
@ -867,16 +889,26 @@ class StackVm(private var traceOutputFile: String?) {
checkDt(variable, DataType.UWORD)
variables[ins.callLabel] =variable.shl()
}
Opcode.SHR_VAR_BYTE -> {
Opcode.SHR_VAR_UBYTE -> {
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.UBYTE)
variables[ins.callLabel] =variable.shr()
}
Opcode.SHR_VAR_WORD -> {
Opcode.SHR_VAR_SBYTE -> {
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.BYTE)
variables[ins.callLabel] =variable.shr()
}
Opcode.SHR_VAR_UWORD -> {
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.UWORD)
variables[ins.callLabel] =variable.shr()
}
Opcode.SHR_VAR_SWORD -> {
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.WORD)
variables[ins.callLabel] =variable.shr()
}
Opcode.ROL_VAR_BYTE -> {
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.UBYTE)
@ -1529,19 +1561,19 @@ class StackVm(private var traceOutputFile: String?) {
Syscall.FUNC_COS -> evalstack.push(Value(DataType.FLOAT, cos(evalstack.pop().numericValue().toDouble())))
Syscall.FUNC_SIN8 -> {
val rad = evalstack.pop().numericValue().toDouble() /256.0 * 2.0 * PI
evalstack.push(Value(DataType.BYTE, (32767.5* sin(rad)).toInt().shr(8).toShort()))
evalstack.push(Value(DataType.BYTE, (32767.0* sin(rad)).toInt().shr(8).toShort()))
}
Syscall.FUNC_SIN16 -> {
val rad = evalstack.pop().numericValue().toDouble() /256.0 * 2.0 * PI
evalstack.push(Value(DataType.WORD, (32767.5* sin(rad)).toInt()))
evalstack.push(Value(DataType.WORD, (32767.0* sin(rad)).toInt()))
}
Syscall.FUNC_COS8 -> {
val rad = evalstack.pop().numericValue().toDouble() /256.0 * 2.0 * PI
evalstack.push(Value(DataType.BYTE, (32767.5* cos(rad)).toInt().shr(8).toShort()))
evalstack.push(Value(DataType.BYTE, (32767.0* cos(rad)).toInt().shr(8).toShort()))
}
Syscall.FUNC_COS16 -> {
val rad = evalstack.pop().numericValue().toDouble() /256.0 * 2.0 * PI
evalstack.push(Value(DataType.WORD, (32767.5* cos(rad)).toInt()))
evalstack.push(Value(DataType.WORD, (32767.0* cos(rad)).toInt()))
}
Syscall.FUNC_ROUND -> evalstack.push(Value(DataType.WORD, evalstack.pop().numericValue().toDouble().roundToInt()))
Syscall.FUNC_ABS -> {

View File

@ -923,25 +923,26 @@ class TestStackVmOpcodes {
@Test
fun testSHR() {
// @todo test SHR signed byte + signed word
val ins = mutableListOf(
Instruction(Opcode.PUSH_FLOAT, Value(DataType.FLOAT, 9.99)),
Instruction(Opcode.PUSH_WORD, Value(DataType.UWORD, 3)),
Instruction(Opcode.PUSH_WORD, Value(DataType.UWORD, 61005)),
Instruction(Opcode.PUSH_BYTE, Value(DataType.UBYTE, 3)),
Instruction(Opcode.PUSH_BYTE, Value(DataType.UBYTE, 249)),
Instruction(Opcode.SHR_BYTE), // 124
Instruction(Opcode.SHR_UBYTE), // 124
Instruction(Opcode.DISCARD_BYTE),
Instruction(Opcode.SHR_BYTE), // 1
Instruction(Opcode.SHR_BYTE), // 0
Instruction(Opcode.SHR_BYTE), // 0
Instruction(Opcode.SHR_UBYTE), // 1
Instruction(Opcode.SHR_UBYTE), // 0
Instruction(Opcode.SHR_UBYTE), // 0
Instruction(Opcode.DISCARD_BYTE),
Instruction(Opcode.SHR_WORD), // 30502
Instruction(Opcode.SHR_UWORD), // 30502
Instruction(Opcode.DISCARD_WORD),
Instruction(Opcode.SHR_WORD), // 1
Instruction(Opcode.SHR_WORD), // 0
Instruction(Opcode.SHR_WORD), // 0
Instruction(Opcode.SHR_UWORD), // 1
Instruction(Opcode.SHR_UWORD), // 0
Instruction(Opcode.SHR_UWORD), // 0
Instruction(Opcode.DISCARD_WORD),
Instruction(Opcode.SHR_BYTE) // error on float
Instruction(Opcode.SHR_UBYTE) // error on float
)
vm.load(makeProg(ins), null)
vm.step(6)

View File

@ -531,6 +531,7 @@ _raster_irq_handler
; @todo move to c64fp.p8 and enable float-checkin astchecker.process(decl: VarDecl) again
const float PI = 3.141592653589793
const float TWOPI = 6.283185307179586
asmsub FREADS32 () -> clobbers(A,X,Y) -> () {

View File

@ -936,7 +936,7 @@ func_sin16 .proc
sta ESTACK_HI+1,x
rts
_ := 32767.5 * sin(range(256+64) * rad(360.0/256.0))
_ := 32767 * sin(range(256+64) * rad(360.0/256.0))
sinecos8lo .byte <_
sinecos8hi .byte >_
.pend