normal division is always float, implemented (u)byte integer division

This commit is contained in:
Irmen de Jong 2019-01-06 01:43:47 +01:00
parent cca94d41bc
commit d203bfaf25
11 changed files with 161 additions and 316 deletions

View File

@ -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)

View File

@ -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)
}
}
}
}

View File

@ -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")
}
}

View File

@ -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")
}

View File

@ -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,

View File

@ -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")

View File

@ -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 -> {
"""

View File

@ -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)

View File

@ -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))
}
}

View File

@ -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).

View File

@ -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
}}
}