mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
normal division is always float, implemented (u)byte integer division
This commit is contained in:
parent
cca94d41bc
commit
d203bfaf25
@ -8,14 +8,14 @@
|
|||||||
const float height_f = height
|
const float height_f = height
|
||||||
|
|
||||||
; vertices
|
; vertices
|
||||||
byte[8] xcoor = [ -50, -50, -50, -50, 50, 50, 50, 50 ]
|
byte[8] xcoor = [ -40, -40, -40, -40, 40, 40, 40, 40 ]
|
||||||
byte[8] ycoor = [ -50, -50, 50, 50, -50, -50, 50, 50 ]
|
byte[8] ycoor = [ -40, -40, 40, 40, -40, -40, 40, 40 ]
|
||||||
byte[8] zcoor = [ -50, 50, -50, 50, -50, 50, -50, 50 ]
|
byte[8] zcoor = [ -40, 40, -40, 40, -40, 40, -40, 40 ]
|
||||||
|
|
||||||
; storage for rotated coordinates
|
; storage for rotated coordinates
|
||||||
word[len(xcoor)] rotatedx=0
|
word[len(xcoor)] rotatedx
|
||||||
word[len(ycoor)] rotatedy=0
|
word[len(ycoor)] rotatedy
|
||||||
word[len(zcoor)] rotatedz=-1
|
word[len(zcoor)] rotatedz
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
uword anglex
|
uword anglex
|
||||||
@ -23,11 +23,11 @@
|
|||||||
uword anglez
|
uword anglez
|
||||||
while(true) {
|
while(true) {
|
||||||
rotate_vertices(msb(anglex), msb(angley), msb(anglez))
|
rotate_vertices(msb(anglex), msb(angley), msb(anglez))
|
||||||
c64.CLEARSCR()
|
c64scr.clear_screen(32,1)
|
||||||
draw_edges()
|
draw_edges()
|
||||||
anglex+=1000
|
anglex+=1000
|
||||||
angley+=333
|
angley+=433
|
||||||
anglez+=807
|
anglez+=907
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,33 +59,21 @@
|
|||||||
lsr(wsina_sinb)
|
lsr(wsina_sinb)
|
||||||
lsr(wsina_sinb) ; / 128
|
lsr(wsina_sinb) ; / 128
|
||||||
|
|
||||||
float cosa_sinb = wcosa_sinb as float / 128.0
|
word Axx = (wcosa*wcosb as float / 128.0) as word
|
||||||
float sina_sinb = wsina_sinb as float / 128.0
|
word Axy = ((wcosa_sinb*wsinc - wsina*wcosc) as float / 128.0) as word
|
||||||
float Axx = wcosa*wcosb as float / 16384.0
|
word Axz = ((wcosa_sinb*wcosc + wsina*wsinc) as float / 128.0) as word
|
||||||
float Axy = cosa_sinb*(wsinc as float / 128.0) - (wsina*wcosc as float / 16384.0)
|
word Ayx = (wsina*wcosb as float / 128.0) as word
|
||||||
float Axz = cosa_sinb*(wcosc as float / 128.0) + (wsina*wsinc as float / 16384.0)
|
word Ayy = ((wsina_sinb*wsinc + wcosa*wcosc) as float / 128.0) as word
|
||||||
float Ayx = wsina*wcosb as float / 16384.0
|
word Ayz = ((wsina_sinb*wcosc - wcosa*wsinc) as float / 128.0) as word
|
||||||
float Ayy = sina_sinb*(wsinc as float / 128.0) + (wcosa*wcosc as float / 16384.0)
|
word Azx = -wsinb
|
||||||
float Ayz = sina_sinb*(wcosc as float / 128.0) - (wcosa*wsinc as float / 16384.0)
|
word Azy = (wcosb*wsinc as float / 128.0) as word
|
||||||
float Azx = -wsinb as float / 128.0
|
word Azz = (wcosb*wcosc as float / 128.0) as word
|
||||||
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 {
|
for ubyte i in 0 to len(xcoor)-1 {
|
||||||
word xc = xcoor[i] as word
|
word xc = xcoor[i] as word
|
||||||
word yc = ycoor[i] as word
|
word yc = ycoor[i] as word
|
||||||
word zc = zcoor[i] as word
|
word zc = zcoor[i] as word
|
||||||
word zz = wAxx*xc + wAxy*yc + wAxz*zc
|
word zz = Axx*xc + Axy*yc + Axz*zc
|
||||||
lsr(zz)
|
lsr(zz)
|
||||||
lsr(zz)
|
lsr(zz)
|
||||||
lsr(zz)
|
lsr(zz)
|
||||||
@ -94,7 +82,7 @@
|
|||||||
lsr(zz)
|
lsr(zz)
|
||||||
lsr(zz) ; /128
|
lsr(zz) ; /128
|
||||||
rotatedx[i] = zz
|
rotatedx[i] = zz
|
||||||
zz=wAyx*xc + wAyy*yc + wAyz*zc
|
zz=Ayx*xc + Ayy*yc + Ayz*zc
|
||||||
lsr(zz)
|
lsr(zz)
|
||||||
lsr(zz)
|
lsr(zz)
|
||||||
lsr(zz)
|
lsr(zz)
|
||||||
@ -103,7 +91,7 @@
|
|||||||
lsr(zz)
|
lsr(zz)
|
||||||
lsr(zz) ; /128
|
lsr(zz) ; /128
|
||||||
rotatedy[i] = zz
|
rotatedy[i] = zz
|
||||||
zz = wAzx*xc + wAzy*yc + wAzz*zc
|
zz = Azx*xc + Azy*yc + Azz*zc
|
||||||
lsr(zz)
|
lsr(zz)
|
||||||
lsr(zz)
|
lsr(zz)
|
||||||
lsr(zz)
|
lsr(zz)
|
||||||
@ -123,7 +111,7 @@
|
|||||||
for ubyte i in 0 to len(xcoor)-1 {
|
for ubyte i in 0 to len(xcoor)-1 {
|
||||||
word rz = rotatedz[i]
|
word rz = rotatedz[i]
|
||||||
if rz >= 10 {
|
if rz >= 10 {
|
||||||
float persp = (rz as float + 250.0)/height_f
|
float persp = (rz as float + 180.0)/height_f
|
||||||
byte sx = rotatedx[i] as float / persp as byte + width//2
|
byte sx = rotatedx[i] as float / persp as byte + width//2
|
||||||
byte sy = rotatedy[i] as float / persp as byte + height//2
|
byte sy = rotatedy[i] as float / persp as byte + height//2
|
||||||
c64scr.setchrclr(sx as ubyte, sy as ubyte, 46, i+2)
|
c64scr.setchrclr(sx as ubyte, sy as ubyte, 46, i+2)
|
||||||
@ -133,7 +121,7 @@
|
|||||||
for ubyte i in 0 to len(xcoor)-1 {
|
for ubyte i in 0 to len(xcoor)-1 {
|
||||||
word rz = rotatedz[i]
|
word rz = rotatedz[i]
|
||||||
if rz < 10 {
|
if rz < 10 {
|
||||||
float persp = (rz as float + 250.0)/height_f
|
float persp = (rz as float + 180.0)/height_f
|
||||||
byte sx = rotatedx[i] as float / persp as byte + width//2
|
byte sx = rotatedx[i] as float / persp as byte + width//2
|
||||||
byte sy = rotatedy[i] as float / persp as byte + height//2
|
byte sy = rotatedy[i] as float / persp as byte + height//2
|
||||||
c64scr.setchrclr(sx as ubyte, sy as ubyte, 81, i+2)
|
c64scr.setchrclr(sx as ubyte, sy as ubyte, 81, i+2)
|
||||||
|
@ -1,148 +1,52 @@
|
|||||||
%import c64utils
|
%import c64utils
|
||||||
%import c64flt
|
|
||||||
|
|
||||||
~ main {
|
~ 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() {
|
sub start() {
|
||||||
uword anglex
|
|
||||||
uword angley
|
ubyte a=200
|
||||||
uword anglez
|
ubyte b=33
|
||||||
while(true) {
|
ubyte c
|
||||||
rotate_vertices(msb(anglex), msb(angley), msb(anglez))
|
|
||||||
c64.CLEARSCR()
|
byte ab=100
|
||||||
draw_edges()
|
byte bb=-6
|
||||||
anglex+=1000
|
byte cb
|
||||||
angley+=333
|
|
||||||
anglez+=807
|
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')
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -868,50 +868,7 @@ class BinaryExpression(var left: IExpression, var operator: String, var right: I
|
|||||||
"<", ">",
|
"<", ">",
|
||||||
"<=", ">=",
|
"<=", ">=",
|
||||||
"==", "!=" -> DataType.UBYTE
|
"==", "!=" -> DataType.UBYTE
|
||||||
"/" -> {
|
"/" -> DataType.FLOAT // use integer division '//' if you don't want floats
|
||||||
val rightNum = right.constValue(namespace, heap)?.asNumericValue?.toDouble()
|
|
||||||
if(rightNum!=null) {
|
|
||||||
when(leftDt) {
|
|
||||||
DataType.UBYTE ->
|
|
||||||
when(rightDt) {
|
|
||||||
DataType.UBYTE -> DataType.UBYTE
|
|
||||||
DataType.BYTE -> DataType.BYTE
|
|
||||||
DataType.UWORD -> if(rightNum >= 256) DataType.UBYTE else DataType.UWORD
|
|
||||||
DataType.WORD -> {
|
|
||||||
if(rightNum < 0)
|
|
||||||
if(rightNum<-256) DataType.UBYTE else DataType.WORD
|
|
||||||
else
|
|
||||||
if(rightNum>256) DataType.UBYTE else DataType.UWORD
|
|
||||||
}
|
|
||||||
DataType.FLOAT -> if(rightNum <= -256 || rightNum >= 256) DataType.UBYTE else DataType.FLOAT
|
|
||||||
else -> throw FatalAstException("invalid rightDt $rightDt")
|
|
||||||
}
|
|
||||||
DataType.BYTE ->
|
|
||||||
when(rightDt) {
|
|
||||||
DataType.UBYTE, DataType.BYTE -> DataType.BYTE
|
|
||||||
DataType.UWORD, DataType.WORD -> if(rightNum <= -256 || rightNum >= 256) DataType.BYTE else DataType.WORD
|
|
||||||
DataType.FLOAT -> if(rightNum <= -256 || rightNum >= 256) DataType.BYTE else DataType.FLOAT
|
|
||||||
else -> throw FatalAstException("invalid rightDt $rightDt")
|
|
||||||
}
|
|
||||||
DataType.UWORD ->
|
|
||||||
when(rightDt) {
|
|
||||||
DataType.UBYTE, DataType.UWORD -> DataType.UWORD
|
|
||||||
DataType.BYTE, DataType.WORD -> DataType.WORD
|
|
||||||
DataType.FLOAT -> if(rightNum <= -65536 || rightNum >= 65536) DataType.UWORD else DataType.FLOAT
|
|
||||||
else -> throw FatalAstException("invalid rightDt $rightDt")
|
|
||||||
}
|
|
||||||
DataType.WORD ->
|
|
||||||
when(rightDt) {
|
|
||||||
DataType.UBYTE, DataType.UWORD, DataType.BYTE, DataType.WORD -> DataType.WORD
|
|
||||||
DataType.FLOAT -> if(rightNum <= -65536 || rightNum >= 65536) DataType.WORD else DataType.FLOAT
|
|
||||||
else -> throw FatalAstException("invalid rightDt $rightDt")
|
|
||||||
}
|
|
||||||
DataType.FLOAT -> DataType.FLOAT
|
|
||||||
null -> DataType.FLOAT
|
|
||||||
else -> throw FatalAstException("invalid leftDt $leftDt")
|
|
||||||
}
|
|
||||||
} else if(leftDt==null || rightDt==null) null else arithmeticOpDt(leftDt, rightDt)
|
|
||||||
}
|
|
||||||
else -> throw FatalAstException("resulting datatype check for invalid operator $operator")
|
else -> throw FatalAstException("resulting datatype check for invalid operator $operator")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -552,7 +552,11 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
|||||||
is BinaryExpression -> {
|
is BinaryExpression -> {
|
||||||
val leftDt = expr.left.resultingDatatype(namespace, heap)!!
|
val leftDt = expr.left.resultingDatatype(namespace, heap)!!
|
||||||
val rightDt = expr.right.resultingDatatype(namespace, heap)!!
|
val rightDt = expr.right.resultingDatatype(namespace, heap)!!
|
||||||
val commonDt = commonDatatype(leftDt, rightDt, expr.left.position, expr.right.position)
|
val commonDt =
|
||||||
|
if(expr.operator=="/")
|
||||||
|
DataType.FLOAT // result of division is always float
|
||||||
|
else
|
||||||
|
commonDatatype(leftDt, rightDt, expr.left.position, expr.right.position)
|
||||||
translate(expr.left)
|
translate(expr.left)
|
||||||
if(leftDt!=commonDt)
|
if(leftDt!=commonDt)
|
||||||
convertType(leftDt, commonDt)
|
convertType(leftDt, commonDt)
|
||||||
@ -1039,21 +1043,15 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"/" -> {
|
"/" -> {
|
||||||
when(dt) {
|
if(dt!=DataType.FLOAT) throw CompilerException("normal division only possible between floats")
|
||||||
DataType.UBYTE -> Opcode.DIV_UB
|
else Opcode.DIV_F
|
||||||
DataType.BYTE -> Opcode.DIV_B
|
|
||||||
DataType.UWORD -> Opcode.DIV_UW
|
|
||||||
DataType.WORD -> Opcode.DIV_W
|
|
||||||
DataType.FLOAT -> Opcode.DIV_F
|
|
||||||
else -> throw CompilerException("only byte/word/float possible")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
"//" -> {
|
"//" -> {
|
||||||
when(dt) {
|
when(dt) {
|
||||||
DataType.UBYTE -> Opcode.DIV_UB
|
DataType.UBYTE -> Opcode.IDIV_UB
|
||||||
DataType.BYTE -> Opcode.DIV_B
|
DataType.BYTE -> Opcode.IDIV_B
|
||||||
DataType.UWORD -> Opcode.DIV_UW
|
DataType.UWORD -> Opcode.IDIV_UW
|
||||||
DataType.WORD -> Opcode.DIV_W
|
DataType.WORD -> Opcode.IDIV_W
|
||||||
DataType.FLOAT -> Opcode.FLOORDIV
|
DataType.FLOAT -> Opcode.FLOORDIV
|
||||||
else -> throw CompilerException("only byte/word/float possible")
|
else -> throw CompilerException("only byte/word/float possible")
|
||||||
}
|
}
|
||||||
@ -1538,18 +1536,13 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
|||||||
else -> throw CompilerException("only byte/word/lfoat possible")
|
else -> throw CompilerException("only byte/word/lfoat possible")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"/=" -> {
|
"/=" -> TODO("/=")
|
||||||
when (valueDt) {
|
|
||||||
DataType.UBYTE -> Opcode.DIV_UB
|
|
||||||
DataType.UWORD -> Opcode.DIV_UW
|
|
||||||
DataType.FLOAT -> Opcode.DIV_F
|
|
||||||
else -> throw CompilerException("only byte/word/lfoat possible")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"//=" -> {
|
"//=" -> {
|
||||||
when (valueDt) {
|
when (valueDt) {
|
||||||
DataType.UBYTE -> Opcode.DIV_UB
|
DataType.UBYTE -> Opcode.IDIV_UB
|
||||||
DataType.UWORD -> Opcode.DIV_UW
|
DataType.BYTE -> Opcode.IDIV_B
|
||||||
|
DataType.UWORD -> Opcode.IDIV_UW
|
||||||
|
DataType.WORD -> Opcode.IDIV_W
|
||||||
DataType.FLOAT -> Opcode.FLOORDIV
|
DataType.FLOAT -> Opcode.FLOORDIV
|
||||||
else -> throw CompilerException("only byte/word/lfoat possible")
|
else -> throw CompilerException("only byte/word/lfoat possible")
|
||||||
}
|
}
|
||||||
|
@ -52,10 +52,10 @@ enum class Opcode {
|
|||||||
MUL_UW,
|
MUL_UW,
|
||||||
MUL_W,
|
MUL_W,
|
||||||
MUL_F,
|
MUL_F,
|
||||||
DIV_UB,
|
IDIV_UB,
|
||||||
DIV_B,
|
IDIV_B,
|
||||||
DIV_UW,
|
IDIV_UW,
|
||||||
DIV_W,
|
IDIV_W,
|
||||||
DIV_F,
|
DIV_F,
|
||||||
FLOORDIV, // integer division but on floatint point argument(s)
|
FLOORDIV, // integer division but on floatint point argument(s)
|
||||||
REMAINDER_UB,
|
REMAINDER_UB,
|
||||||
|
@ -180,16 +180,20 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
|
|||||||
val v1 = numericValue()
|
val v1 = numericValue()
|
||||||
val v2 = other.numericValue()
|
val v2 = other.numericValue()
|
||||||
if(v2.toDouble()==0.0) {
|
if(v2.toDouble()==0.0) {
|
||||||
if (type == DataType.UBYTE)
|
when (type) {
|
||||||
return Value(DataType.UBYTE, 255)
|
DataType.UBYTE -> return Value(DataType.UBYTE, 255)
|
||||||
else if(type == DataType.UWORD)
|
DataType.BYTE -> return Value(DataType.BYTE, 127)
|
||||||
return Value(DataType.UWORD, 65535)
|
DataType.UWORD -> return Value(DataType.UWORD, 65535)
|
||||||
|
DataType.WORD -> return Value(DataType.WORD, 32767)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val result = v1.toDouble() / v2.toDouble()
|
val result = v1.toDouble() / v2.toDouble()
|
||||||
// NOTE: integer division returns integer result!
|
// NOTE: integer division returns integer result!
|
||||||
return when(type) {
|
return when(type) {
|
||||||
DataType.UBYTE -> Value(DataType.UBYTE, result)
|
DataType.UBYTE -> Value(DataType.UBYTE, result)
|
||||||
|
DataType.BYTE -> Value(DataType.BYTE, result)
|
||||||
DataType.UWORD -> Value(DataType.UWORD, result)
|
DataType.UWORD -> Value(DataType.UWORD, result)
|
||||||
|
DataType.WORD -> Value(DataType.WORD, result)
|
||||||
DataType.FLOAT -> Value(DataType.FLOAT, result)
|
DataType.FLOAT -> Value(DataType.FLOAT, result)
|
||||||
else -> throw ValueException("div on non-numeric type")
|
else -> throw ValueException("div on non-numeric type")
|
||||||
}
|
}
|
||||||
@ -203,7 +207,9 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
|
|||||||
val result = floor(v1.toDouble() / v2.toDouble())
|
val result = floor(v1.toDouble() / v2.toDouble())
|
||||||
// NOTE: integer division returns integer result!
|
// NOTE: integer division returns integer result!
|
||||||
return when(type) {
|
return when(type) {
|
||||||
|
DataType.BYTE -> Value(DataType.BYTE, result)
|
||||||
DataType.UBYTE -> Value(DataType.UBYTE, result)
|
DataType.UBYTE -> Value(DataType.UBYTE, result)
|
||||||
|
DataType.WORD -> Value(DataType.WORD, result)
|
||||||
DataType.UWORD -> Value(DataType.UWORD, result)
|
DataType.UWORD -> Value(DataType.UWORD, result)
|
||||||
DataType.FLOAT -> Value(DataType.FLOAT, result)
|
DataType.FLOAT -> Value(DataType.FLOAT, result)
|
||||||
else -> throw ValueException("div on non-numeric type")
|
else -> throw ValueException("div on non-numeric type")
|
||||||
|
@ -758,7 +758,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
|||||||
Opcode.CAST_F_TO_UW -> " jsr c64flt.stack_float2uw"
|
Opcode.CAST_F_TO_UW -> " jsr c64flt.stack_float2uw"
|
||||||
Opcode.CAST_F_TO_W -> " jsr c64flt.stack_float2w"
|
Opcode.CAST_F_TO_W -> " jsr c64flt.stack_float2w"
|
||||||
Opcode.CAST_UB_TO_UW, Opcode.CAST_UB_TO_W -> " lda #0 | sta ${(ESTACK_HI+1).toHex()},x" // clear the msb
|
Opcode.CAST_UB_TO_UW, Opcode.CAST_UB_TO_W -> " lda #0 | sta ${(ESTACK_HI+1).toHex()},x" // clear the msb
|
||||||
Opcode.CAST_B_TO_UW, Opcode.CAST_B_TO_W -> " lda ${(ESTACK_LO+1)},x | ${signExtendA("${(ESTACK_HI+1).toHex()},x")}" // sign extend the lsb
|
Opcode.CAST_B_TO_UW, Opcode.CAST_B_TO_W -> " lda ${(ESTACK_LO+1).toHex()},x | ${signExtendA("${(ESTACK_HI+1).toHex()},x")}" // sign extend the lsb
|
||||||
Opcode.MSB -> " lda ${(ESTACK_HI+1).toHex()},x | sta ${(ESTACK_LO+1).toHex()},x"
|
Opcode.MSB -> " lda ${(ESTACK_HI+1).toHex()},x | sta ${(ESTACK_LO+1).toHex()},x"
|
||||||
|
|
||||||
Opcode.ADD_UB, Opcode.ADD_B -> { // TODO inline better?
|
Opcode.ADD_UB, Opcode.ADD_B -> { // TODO inline better?
|
||||||
@ -788,10 +788,10 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
|||||||
Opcode.MUL_F -> " jsr c64flt.mul_f"
|
Opcode.MUL_F -> " jsr c64flt.mul_f"
|
||||||
Opcode.DIV_F -> " jsr c64flt.div_f"
|
Opcode.DIV_F -> " jsr c64flt.div_f"
|
||||||
Opcode.FLOORDIV -> " jsr c64flt.floordiv_f"
|
Opcode.FLOORDIV -> " jsr c64flt.floordiv_f"
|
||||||
Opcode.DIV_UB -> " jsr prog8_lib.div_ub"
|
Opcode.IDIV_UB -> " jsr prog8_lib.idiv_ub"
|
||||||
Opcode.DIV_B -> " jsr prog8_lib.div_b"
|
Opcode.IDIV_B -> " jsr prog8_lib.idiv_b"
|
||||||
Opcode.DIV_W -> " jsr prog8_lib.div_w"
|
Opcode.IDIV_W -> " jsr prog8_lib.idiv_w"
|
||||||
Opcode.DIV_UW -> " jsr prog8_lib.div_uw"
|
Opcode.IDIV_UW -> " jsr prog8_lib.idiv_uw"
|
||||||
|
|
||||||
Opcode.AND_BYTE -> {
|
Opcode.AND_BYTE -> {
|
||||||
"""
|
"""
|
||||||
|
@ -434,25 +434,25 @@ class StackVm(private var traceOutputFile: String?) {
|
|||||||
checkDt(second, DataType.FLOAT)
|
checkDt(second, DataType.FLOAT)
|
||||||
evalstack.push(second.mul(top))
|
evalstack.push(second.mul(top))
|
||||||
}
|
}
|
||||||
Opcode.DIV_UB -> {
|
Opcode.IDIV_UB -> {
|
||||||
val (top, second) = evalstack.pop2()
|
val (top, second) = evalstack.pop2()
|
||||||
checkDt(top, DataType.UBYTE)
|
checkDt(top, DataType.UBYTE)
|
||||||
checkDt(second, DataType.UBYTE)
|
checkDt(second, DataType.UBYTE)
|
||||||
evalstack.push(second.div(top))
|
evalstack.push(second.div(top))
|
||||||
}
|
}
|
||||||
Opcode.DIV_UW -> {
|
Opcode.IDIV_UW -> {
|
||||||
val (top, second) = evalstack.pop2()
|
val (top, second) = evalstack.pop2()
|
||||||
checkDt(top, DataType.UWORD)
|
checkDt(top, DataType.UWORD)
|
||||||
checkDt(second, DataType.UWORD)
|
checkDt(second, DataType.UWORD)
|
||||||
evalstack.push(second.div(top))
|
evalstack.push(second.div(top))
|
||||||
}
|
}
|
||||||
Opcode.DIV_B -> {
|
Opcode.IDIV_B -> {
|
||||||
val (top, second) = evalstack.pop2()
|
val (top, second) = evalstack.pop2()
|
||||||
checkDt(top, DataType.BYTE)
|
checkDt(top, DataType.BYTE)
|
||||||
checkDt(second, DataType.BYTE)
|
checkDt(second, DataType.BYTE)
|
||||||
evalstack.push(second.div(top))
|
evalstack.push(second.div(top))
|
||||||
}
|
}
|
||||||
Opcode.DIV_W -> {
|
Opcode.IDIV_W -> {
|
||||||
val (top, second) = evalstack.pop2()
|
val (top, second) = evalstack.pop2()
|
||||||
checkDt(top, DataType.WORD)
|
checkDt(top, DataType.WORD)
|
||||||
checkDt(second, DataType.WORD)
|
checkDt(second, DataType.WORD)
|
||||||
|
@ -315,11 +315,13 @@ class TestStackVmOpcodes {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDiv() {
|
fun testDiv() {
|
||||||
testBinaryOperator(Value(DataType.UBYTE, 250), Opcode.DIV_UB, Value(DataType.UBYTE, 12), Value(DataType.UBYTE, 20))
|
testBinaryOperator(Value(DataType.UBYTE, 250), Opcode.IDIV_UB, Value(DataType.UBYTE, 12), Value(DataType.UBYTE, 20))
|
||||||
testBinaryOperator(Value(DataType.UWORD, 3999), Opcode.DIV_UW, Value(DataType.UWORD, 40), Value(DataType.UWORD, 99))
|
testBinaryOperator(Value(DataType.BYTE, 120), Opcode.IDIV_B, Value(DataType.BYTE, -9), Value(DataType.BYTE, -13))
|
||||||
|
testBinaryOperator(Value(DataType.UWORD, 3999), Opcode.IDIV_UW, Value(DataType.UWORD, 40), Value(DataType.UWORD, 99))
|
||||||
|
testBinaryOperator(Value(DataType.WORD, 3999), Opcode.IDIV_W, Value(DataType.WORD, -40), Value(DataType.WORD, -99))
|
||||||
testBinaryOperator(Value(DataType.FLOAT, 42.25), Opcode.DIV_F, Value(DataType.FLOAT, 99.0), Value(DataType.FLOAT, 42.25 / 99.0))
|
testBinaryOperator(Value(DataType.FLOAT, 42.25), Opcode.DIV_F, Value(DataType.FLOAT, 99.0), Value(DataType.FLOAT, 42.25 / 99.0))
|
||||||
assertFailsWith<VmExecutionException> {
|
assertFailsWith<VmExecutionException> {
|
||||||
testBinaryOperator(Value(DataType.UWORD, 3333), Opcode.DIV_UW, Value(DataType.FLOAT, 2.22), Value(DataType.FLOAT, 3333 / 2.22))
|
testBinaryOperator(Value(DataType.UWORD, 3333), Opcode.IDIV_UW, Value(DataType.FLOAT, 2.22), Value(DataType.FLOAT, 3333 / 2.22))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,7 +362,8 @@ Operators
|
|||||||
|
|
||||||
arithmetic: ``+`` ``-`` ``*`` ``/`` ``//`` ``**`` ``%``
|
arithmetic: ``+`` ``-`` ``*`` ``/`` ``//`` ``**`` ``%``
|
||||||
``+``, ``-``, ``*``, ``/`` are the familiar arithmetic operations.
|
``+``, ``-``, ``*``, ``/`` are the familiar arithmetic operations.
|
||||||
``//`` is the floor-divide, the division resulting in a whole number rounded towards minus infinity.
|
``/`` is floating-point division (will always result in a floating point result)
|
||||||
|
``//`` is the integer divison (can divide integers into integer result of the same type), or floor-division on floating points (the division resulting in a whole number rounded towards minus infinity).
|
||||||
``**`` is the power operator: ``3 ** 5`` is equal to 3*3*3*3*3 and is 243.
|
``**`` is the power operator: ``3 ** 5`` is equal to 3*3*3*3*3 and is 243.
|
||||||
``%`` is the remainder operator: ``25 % 7`` is 4. Be careful: without a space, %10 will be parsed as the binary number 2
|
``%`` is the remainder operator: ``25 % 7`` is 4. Be careful: without a space, %10 will be parsed as the binary number 2
|
||||||
Remainder is only supported on integer operands (not floats).
|
Remainder is only supported on integer operands (not floats).
|
||||||
|
@ -163,54 +163,58 @@ mul_word .proc
|
|||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
div_b .proc
|
idiv_b .proc
|
||||||
|
; signed division: use unsigned division and fix sign of result afterwards
|
||||||
|
lda c64.ESTACK_LO+1,x
|
||||||
|
eor c64.ESTACK_LO+2,x
|
||||||
|
php ; save sign of result
|
||||||
inx
|
inx
|
||||||
lda #42
|
lda c64.ESTACK_LO,x
|
||||||
sta c64.ESTACK_LO+1,x
|
bpl +
|
||||||
lda #0
|
eor #$ff
|
||||||
sta c64.ESTACK_HI+1,x
|
sec
|
||||||
|
adc #0 ; make num1 positive
|
||||||
|
+ tay
|
||||||
|
inx
|
||||||
|
lda c64.ESTACK_LO,x
|
||||||
|
bpl +
|
||||||
|
eor #$ff
|
||||||
|
sec
|
||||||
|
adc #0 ; make num2 positive
|
||||||
|
+ jsr math.divmod_ubytes
|
||||||
|
tya
|
||||||
|
plp ; get sign of result
|
||||||
|
bpl +
|
||||||
|
eor #$ff
|
||||||
|
sec
|
||||||
|
adc #0 ; negate result
|
||||||
|
+ sta c64.ESTACK_LO,x
|
||||||
|
dex
|
||||||
rts
|
rts
|
||||||
.warn "div_b not implemented"
|
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
div_ub .proc
|
idiv_ub .proc
|
||||||
inx
|
inx
|
||||||
lda #42
|
ldy c64.ESTACK_LO,x
|
||||||
sta c64.ESTACK_LO+1,x
|
inx
|
||||||
lda #0
|
lda c64.ESTACK_LO,x
|
||||||
sta c64.ESTACK_HI+1,x
|
jsr math.divmod_ubytes
|
||||||
|
tya
|
||||||
|
sta c64.ESTACK_LO,x
|
||||||
|
dex
|
||||||
rts
|
rts
|
||||||
.warn "div_ub not implemented"
|
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
div_w .proc
|
idiv_w .proc
|
||||||
inx
|
.error "idiv_w not yet implemented"
|
||||||
lda #42
|
|
||||||
sta c64.ESTACK_LO+1,x
|
|
||||||
lda #0
|
|
||||||
sta c64.ESTACK_HI+1,x
|
|
||||||
rts
|
|
||||||
.warn "div_w not implemented"
|
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
div_uw .proc
|
idiv_uw .proc
|
||||||
inx
|
.error "idiv_uw not implemented"
|
||||||
lda #42
|
|
||||||
sta c64.ESTACK_LO+1,x
|
|
||||||
lda #0
|
|
||||||
sta c64.ESTACK_HI+1,x
|
|
||||||
rts
|
|
||||||
.warn "div_uw not implemented"
|
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
remainder_b .proc
|
remainder_b .proc
|
||||||
inx
|
.error "remainder_b not yet implemented, via div_b?"
|
||||||
lda #42
|
|
||||||
sta c64.ESTACK_LO+1,x
|
|
||||||
lda #0
|
|
||||||
sta c64.ESTACK_HI+1,x
|
|
||||||
rts
|
|
||||||
.warn "remainder_b via div_b?"
|
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
remainder_ub .proc
|
remainder_ub .proc
|
||||||
@ -227,23 +231,11 @@ remainder_ub .proc
|
|||||||
.pend
|
.pend
|
||||||
|
|
||||||
remainder_w .proc
|
remainder_w .proc
|
||||||
inx
|
.error "remainder_w not implemented - via div_w"
|
||||||
lda #42
|
|
||||||
sta c64.ESTACK_LO+1,x
|
|
||||||
lda #0
|
|
||||||
sta c64.ESTACK_HI+1,x
|
|
||||||
rts
|
|
||||||
.warn "remainder_w not implemented - via div_w"
|
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
remainder_uw .proc
|
remainder_uw .proc
|
||||||
inx
|
.error "remainder_uw not implemented - via div_uw"
|
||||||
lda #42
|
|
||||||
sta c64.ESTACK_LO+1,x
|
|
||||||
lda #0
|
|
||||||
sta c64.ESTACK_HI+1,x
|
|
||||||
rts
|
|
||||||
.warn "remainder_uw not implemented - via div_uw"
|
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
equal_w .proc
|
equal_w .proc
|
||||||
@ -1029,12 +1021,13 @@ multiply_words_result .byte 0,0,0,0
|
|||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
asmsub divmod_bytes (ubyte number @ X, ubyte divisor @ Y) -> clobbers() -> (ubyte @ X, ubyte @ A) {
|
asmsub divmod_ubytes (ubyte number @ A, ubyte divisor @ Y) -> clobbers() -> (ubyte @ Y, ubyte @ A) {
|
||||||
; ---- divide X by Y, result quotient in X, remainder in A (unsigned)
|
; ---- divide A by Y, result quotient in Y, remainder in A (unsigned)
|
||||||
; division by zero will result in quotient = 255 and remainder = original number
|
; division by zero will result in quotient = 255 and remainder = original number
|
||||||
%asm {{
|
%asm {{
|
||||||
stx c64.SCRATCH_ZPB1
|
|
||||||
sty c64.SCRATCH_ZPREG
|
sty c64.SCRATCH_ZPREG
|
||||||
|
sta c64.SCRATCH_ZPB1
|
||||||
|
stx c64.SCRATCH_ZPREGX
|
||||||
|
|
||||||
lda #0
|
lda #0
|
||||||
ldx #8
|
ldx #8
|
||||||
@ -1047,7 +1040,8 @@ asmsub divmod_bytes (ubyte number @ X, ubyte divisor @ Y) -> clobbers() -> (ub
|
|||||||
dex
|
dex
|
||||||
bne -
|
bne -
|
||||||
|
|
||||||
ldx c64.SCRATCH_ZPB1
|
ldy c64.SCRATCH_ZPB1
|
||||||
|
ldx c64.SCRATCH_ZPREGX
|
||||||
rts
|
rts
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user