mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 01:29:28 +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
|
||||
|
||||
; 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 ]
|
||||
byte[8] xcoor = [ -40, -40, -40, -40, 40, 40, 40, 40 ]
|
||||
byte[8] ycoor = [ -40, -40, 40, 40, -40, -40, 40, 40 ]
|
||||
byte[8] zcoor = [ -40, 40, -40, 40, -40, 40, -40, 40 ]
|
||||
|
||||
; storage for rotated coordinates
|
||||
word[len(xcoor)] rotatedx=0
|
||||
word[len(ycoor)] rotatedy=0
|
||||
word[len(zcoor)] rotatedz=-1
|
||||
word[len(xcoor)] rotatedx
|
||||
word[len(ycoor)] rotatedy
|
||||
word[len(zcoor)] rotatedz
|
||||
|
||||
sub start() {
|
||||
uword anglex
|
||||
@ -23,11 +23,11 @@
|
||||
uword anglez
|
||||
while(true) {
|
||||
rotate_vertices(msb(anglex), msb(angley), msb(anglez))
|
||||
c64.CLEARSCR()
|
||||
c64scr.clear_screen(32,1)
|
||||
draw_edges()
|
||||
anglex+=1000
|
||||
angley+=333
|
||||
anglez+=807
|
||||
angley+=433
|
||||
anglez+=907
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,33 +59,21 @@
|
||||
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
|
||||
word Axx = (wcosa*wcosb as float / 128.0) as word
|
||||
word Axy = ((wcosa_sinb*wsinc - wsina*wcosc) as float / 128.0) as word
|
||||
word Axz = ((wcosa_sinb*wcosc + wsina*wsinc) as float / 128.0) as word
|
||||
word Ayx = (wsina*wcosb as float / 128.0) as word
|
||||
word Ayy = ((wsina_sinb*wsinc + wcosa*wcosc) as float / 128.0) as word
|
||||
word Ayz = ((wsina_sinb*wcosc - wcosa*wsinc) as float / 128.0) as word
|
||||
word Azx = -wsinb
|
||||
word Azy = (wcosb*wsinc as float / 128.0) as word
|
||||
word Azz = (wcosb*wcosc as float / 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
|
||||
word zz = Axx*xc + Axy*yc + Axz*zc
|
||||
lsr(zz)
|
||||
lsr(zz)
|
||||
lsr(zz)
|
||||
@ -94,7 +82,7 @@
|
||||
lsr(zz)
|
||||
lsr(zz) ; /128
|
||||
rotatedx[i] = zz
|
||||
zz=wAyx*xc + wAyy*yc + wAyz*zc
|
||||
zz=Ayx*xc + Ayy*yc + Ayz*zc
|
||||
lsr(zz)
|
||||
lsr(zz)
|
||||
lsr(zz)
|
||||
@ -103,7 +91,7 @@
|
||||
lsr(zz)
|
||||
lsr(zz) ; /128
|
||||
rotatedy[i] = zz
|
||||
zz = wAzx*xc + wAzy*yc + wAzz*zc
|
||||
zz = Azx*xc + Azy*yc + Azz*zc
|
||||
lsr(zz)
|
||||
lsr(zz)
|
||||
lsr(zz)
|
||||
@ -123,7 +111,7 @@
|
||||
for ubyte i in 0 to len(xcoor)-1 {
|
||||
word rz = rotatedz[i]
|
||||
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 sy = rotatedy[i] as float / persp as byte + height//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 {
|
||||
word rz = rotatedz[i]
|
||||
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 sy = rotatedy[i] as float / persp as byte + height//2
|
||||
c64scr.setchrclr(sx as ubyte, sy as ubyte, 81, i+2)
|
||||
|
@ -1,148 +1,52 @@
|
||||
%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() {
|
||||
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
|
||||
}
|
||||
|
||||
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')
|
||||
}
|
||||
|
||||
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
|
||||
"/" -> {
|
||||
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)
|
||||
}
|
||||
"/" -> DataType.FLOAT // use integer division '//' if you don't want floats
|
||||
else -> throw FatalAstException("resulting datatype check for invalid operator $operator")
|
||||
}
|
||||
}
|
||||
|
@ -552,7 +552,11 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
is BinaryExpression -> {
|
||||
val leftDt = expr.left.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)
|
||||
if(leftDt!=commonDt)
|
||||
convertType(leftDt, commonDt)
|
||||
@ -1039,21 +1043,15 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
}
|
||||
}
|
||||
"/" -> {
|
||||
when(dt) {
|
||||
DataType.UBYTE -> Opcode.DIV_UB
|
||||
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")
|
||||
}
|
||||
if(dt!=DataType.FLOAT) throw CompilerException("normal division only possible between floats")
|
||||
else Opcode.DIV_F
|
||||
}
|
||||
"//" -> {
|
||||
when(dt) {
|
||||
DataType.UBYTE -> Opcode.DIV_UB
|
||||
DataType.BYTE -> Opcode.DIV_B
|
||||
DataType.UWORD -> Opcode.DIV_UW
|
||||
DataType.WORD -> Opcode.DIV_W
|
||||
DataType.UBYTE -> Opcode.IDIV_UB
|
||||
DataType.BYTE -> Opcode.IDIV_B
|
||||
DataType.UWORD -> Opcode.IDIV_UW
|
||||
DataType.WORD -> Opcode.IDIV_W
|
||||
DataType.FLOAT -> Opcode.FLOORDIV
|
||||
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")
|
||||
}
|
||||
}
|
||||
"/=" -> {
|
||||
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")
|
||||
}
|
||||
}
|
||||
"/=" -> TODO("/=")
|
||||
"//=" -> {
|
||||
when (valueDt) {
|
||||
DataType.UBYTE -> Opcode.DIV_UB
|
||||
DataType.UWORD -> Opcode.DIV_UW
|
||||
DataType.UBYTE -> Opcode.IDIV_UB
|
||||
DataType.BYTE -> Opcode.IDIV_B
|
||||
DataType.UWORD -> Opcode.IDIV_UW
|
||||
DataType.WORD -> Opcode.IDIV_W
|
||||
DataType.FLOAT -> Opcode.FLOORDIV
|
||||
else -> throw CompilerException("only byte/word/lfoat possible")
|
||||
}
|
||||
|
@ -52,10 +52,10 @@ enum class Opcode {
|
||||
MUL_UW,
|
||||
MUL_W,
|
||||
MUL_F,
|
||||
DIV_UB,
|
||||
DIV_B,
|
||||
DIV_UW,
|
||||
DIV_W,
|
||||
IDIV_UB,
|
||||
IDIV_B,
|
||||
IDIV_UW,
|
||||
IDIV_W,
|
||||
DIV_F,
|
||||
FLOORDIV, // integer division but on floatint point argument(s)
|
||||
REMAINDER_UB,
|
||||
|
@ -180,16 +180,20 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
|
||||
val v1 = numericValue()
|
||||
val v2 = other.numericValue()
|
||||
if(v2.toDouble()==0.0) {
|
||||
if (type == DataType.UBYTE)
|
||||
return Value(DataType.UBYTE, 255)
|
||||
else if(type == DataType.UWORD)
|
||||
return Value(DataType.UWORD, 65535)
|
||||
when (type) {
|
||||
DataType.UBYTE -> return Value(DataType.UBYTE, 255)
|
||||
DataType.BYTE -> return Value(DataType.BYTE, 127)
|
||||
DataType.UWORD -> return Value(DataType.UWORD, 65535)
|
||||
DataType.WORD -> return Value(DataType.WORD, 32767)
|
||||
}
|
||||
}
|
||||
val result = v1.toDouble() / v2.toDouble()
|
||||
// NOTE: integer division returns integer result!
|
||||
return when(type) {
|
||||
DataType.UBYTE -> Value(DataType.UBYTE, result)
|
||||
DataType.BYTE -> Value(DataType.BYTE, result)
|
||||
DataType.UWORD -> Value(DataType.UWORD, result)
|
||||
DataType.WORD -> Value(DataType.WORD, result)
|
||||
DataType.FLOAT -> Value(DataType.FLOAT, result)
|
||||
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())
|
||||
// NOTE: integer division returns integer result!
|
||||
return when(type) {
|
||||
DataType.BYTE -> Value(DataType.BYTE, result)
|
||||
DataType.UBYTE -> Value(DataType.UBYTE, result)
|
||||
DataType.WORD -> Value(DataType.WORD, result)
|
||||
DataType.UWORD -> Value(DataType.UWORD, result)
|
||||
DataType.FLOAT -> Value(DataType.FLOAT, result)
|
||||
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_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_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.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.DIV_F -> " jsr c64flt.div_f"
|
||||
Opcode.FLOORDIV -> " jsr c64flt.floordiv_f"
|
||||
Opcode.DIV_UB -> " jsr prog8_lib.div_ub"
|
||||
Opcode.DIV_B -> " jsr prog8_lib.div_b"
|
||||
Opcode.DIV_W -> " jsr prog8_lib.div_w"
|
||||
Opcode.DIV_UW -> " jsr prog8_lib.div_uw"
|
||||
Opcode.IDIV_UB -> " jsr prog8_lib.idiv_ub"
|
||||
Opcode.IDIV_B -> " jsr prog8_lib.idiv_b"
|
||||
Opcode.IDIV_W -> " jsr prog8_lib.idiv_w"
|
||||
Opcode.IDIV_UW -> " jsr prog8_lib.idiv_uw"
|
||||
|
||||
Opcode.AND_BYTE -> {
|
||||
"""
|
||||
|
@ -434,25 +434,25 @@ class StackVm(private var traceOutputFile: String?) {
|
||||
checkDt(second, DataType.FLOAT)
|
||||
evalstack.push(second.mul(top))
|
||||
}
|
||||
Opcode.DIV_UB -> {
|
||||
Opcode.IDIV_UB -> {
|
||||
val (top, second) = evalstack.pop2()
|
||||
checkDt(top, DataType.UBYTE)
|
||||
checkDt(second, DataType.UBYTE)
|
||||
evalstack.push(second.div(top))
|
||||
}
|
||||
Opcode.DIV_UW -> {
|
||||
Opcode.IDIV_UW -> {
|
||||
val (top, second) = evalstack.pop2()
|
||||
checkDt(top, DataType.UWORD)
|
||||
checkDt(second, DataType.UWORD)
|
||||
evalstack.push(second.div(top))
|
||||
}
|
||||
Opcode.DIV_B -> {
|
||||
Opcode.IDIV_B -> {
|
||||
val (top, second) = evalstack.pop2()
|
||||
checkDt(top, DataType.BYTE)
|
||||
checkDt(second, DataType.BYTE)
|
||||
evalstack.push(second.div(top))
|
||||
}
|
||||
Opcode.DIV_W -> {
|
||||
Opcode.IDIV_W -> {
|
||||
val (top, second) = evalstack.pop2()
|
||||
checkDt(top, DataType.WORD)
|
||||
checkDt(second, DataType.WORD)
|
||||
|
@ -315,11 +315,13 @@ class TestStackVmOpcodes {
|
||||
|
||||
@Test
|
||||
fun testDiv() {
|
||||
testBinaryOperator(Value(DataType.UBYTE, 250), Opcode.DIV_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.UBYTE, 250), Opcode.IDIV_UB, Value(DataType.UBYTE, 12), Value(DataType.UBYTE, 20))
|
||||
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))
|
||||
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: ``+`` ``-`` ``*`` ``/`` ``//`` ``**`` ``%``
|
||||
``+``, ``-``, ``*``, ``/`` 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 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).
|
||||
|
@ -163,54 +163,58 @@ mul_word .proc
|
||||
rts
|
||||
.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
|
||||
lda #42
|
||||
sta c64.ESTACK_LO+1,x
|
||||
lda #0
|
||||
sta c64.ESTACK_HI+1,x
|
||||
lda c64.ESTACK_LO,x
|
||||
bpl +
|
||||
eor #$ff
|
||||
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
|
||||
.warn "div_b not implemented"
|
||||
.pend
|
||||
|
||||
div_ub .proc
|
||||
idiv_ub .proc
|
||||
inx
|
||||
lda #42
|
||||
sta c64.ESTACK_LO+1,x
|
||||
lda #0
|
||||
sta c64.ESTACK_HI+1,x
|
||||
ldy c64.ESTACK_LO,x
|
||||
inx
|
||||
lda c64.ESTACK_LO,x
|
||||
jsr math.divmod_ubytes
|
||||
tya
|
||||
sta c64.ESTACK_LO,x
|
||||
dex
|
||||
rts
|
||||
.warn "div_ub not implemented"
|
||||
.pend
|
||||
|
||||
div_w .proc
|
||||
inx
|
||||
lda #42
|
||||
sta c64.ESTACK_LO+1,x
|
||||
lda #0
|
||||
sta c64.ESTACK_HI+1,x
|
||||
rts
|
||||
.warn "div_w not implemented"
|
||||
idiv_w .proc
|
||||
.error "idiv_w not yet implemented"
|
||||
.pend
|
||||
|
||||
div_uw .proc
|
||||
inx
|
||||
lda #42
|
||||
sta c64.ESTACK_LO+1,x
|
||||
lda #0
|
||||
sta c64.ESTACK_HI+1,x
|
||||
rts
|
||||
.warn "div_uw not implemented"
|
||||
idiv_uw .proc
|
||||
.error "idiv_uw not implemented"
|
||||
.pend
|
||||
|
||||
remainder_b .proc
|
||||
inx
|
||||
lda #42
|
||||
sta c64.ESTACK_LO+1,x
|
||||
lda #0
|
||||
sta c64.ESTACK_HI+1,x
|
||||
rts
|
||||
.warn "remainder_b via div_b?"
|
||||
.error "remainder_b not yet implemented, via div_b?"
|
||||
.pend
|
||||
|
||||
remainder_ub .proc
|
||||
@ -227,23 +231,11 @@ remainder_ub .proc
|
||||
.pend
|
||||
|
||||
remainder_w .proc
|
||||
inx
|
||||
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"
|
||||
.error "remainder_w not implemented - via div_w"
|
||||
.pend
|
||||
|
||||
remainder_uw .proc
|
||||
inx
|
||||
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"
|
||||
.error "remainder_uw not implemented - via div_uw"
|
||||
.pend
|
||||
|
||||
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) {
|
||||
; ---- divide X by Y, result quotient in X, remainder in A (unsigned)
|
||||
asmsub divmod_ubytes (ubyte number @ A, ubyte divisor @ Y) -> clobbers() -> (ubyte @ Y, ubyte @ A) {
|
||||
; ---- divide A by Y, result quotient in Y, remainder in A (unsigned)
|
||||
; division by zero will result in quotient = 255 and remainder = original number
|
||||
%asm {{
|
||||
stx c64.SCRATCH_ZPB1
|
||||
sty c64.SCRATCH_ZPREG
|
||||
sta c64.SCRATCH_ZPB1
|
||||
stx c64.SCRATCH_ZPREGX
|
||||
|
||||
lda #0
|
||||
ldx #8
|
||||
@ -1047,7 +1040,8 @@ asmsub divmod_bytes (ubyte number @ X, ubyte divisor @ Y) -> clobbers() -> (ub
|
||||
dex
|
||||
bne -
|
||||
|
||||
ldx c64.SCRATCH_ZPB1
|
||||
ldy c64.SCRATCH_ZPB1
|
||||
ldx c64.SCRATCH_ZPREGX
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user