mirror of
https://github.com/irmen/prog8.git
synced 2025-02-16 22:30:46 +00:00
vm: added math.mul16_last_upper()
This commit is contained in:
parent
9b9e6f4af5
commit
cd40088636
@ -141,8 +141,13 @@ _sinecosR8 .char trunc(127.0 * sin(range(180+45) * rad(360.0/180.0)))
|
||||
}
|
||||
|
||||
asmsub mul16_last_upper() -> uword @AY {
|
||||
; this routine peeks into the internal 32 bits multiplication result buffer of the
|
||||
; This routine peeks into the internal 32 bits multiplication result buffer of the
|
||||
; 16*16 bits multiplication routine, to fetch the upper 16 bits of the last calculation.
|
||||
; Notes:
|
||||
; - to avoid interference it's best to fetch and store this value immediately after the multiplication expression.
|
||||
; for instance, simply printing a number may already result in new multiplication calls being performed
|
||||
; - not all multiplications in the source code result in an actual multiplication call:
|
||||
; some simpler multiplications will be optimized away into faster routines. These will not set the upper 16 bits at all!
|
||||
%asm {{
|
||||
lda multiply_words.result+2
|
||||
ldy multiply_words.result+3
|
||||
|
@ -212,59 +212,72 @@ math {
|
||||
}
|
||||
}
|
||||
|
||||
sub direction(ubyte x1, ubyte y1, ubyte x2, ubyte y2) -> ubyte {
|
||||
; From a pair of positive coordinates, calculate discrete direction between 0 and 23 into A.
|
||||
; This adjusts the atan() result so that the direction N is centered on the angle=N instead of having it as a boundary
|
||||
ubyte angle = atan2(x1, y1, x2, y2) - 256/48
|
||||
return 23-lsb(mkword(angle,0) / 2730)
|
||||
}
|
||||
|
||||
sub direction_sc(byte x1, byte y1, byte x2, byte y2) -> ubyte {
|
||||
; From a pair of signed coordinates around the origin, calculate discrete direction between 0 and 23 into A.
|
||||
; shift the points into the positive quadrant
|
||||
ubyte px1
|
||||
ubyte py1
|
||||
ubyte px2
|
||||
ubyte py2
|
||||
if x1<0 or x2<0 {
|
||||
px1 = x1 as ubyte + 128
|
||||
px2 = x2 as ubyte + 128
|
||||
} else {
|
||||
px1 = x1 as ubyte
|
||||
px2 = x2 as ubyte
|
||||
}
|
||||
if y1<0 or y2<0 {
|
||||
py1 = y1 as ubyte + 128
|
||||
py2 = y2 as ubyte + 128
|
||||
} else {
|
||||
py1 = y1 as ubyte
|
||||
py2 = y2 as ubyte
|
||||
sub direction(ubyte x1, ubyte y1, ubyte x2, ubyte y2) -> ubyte {
|
||||
; From a pair of positive coordinates, calculate discrete direction between 0 and 23 into A.
|
||||
; This adjusts the atan() result so that the direction N is centered on the angle=N instead of having it as a boundary
|
||||
ubyte angle = atan2(x1, y1, x2, y2) - 256/48
|
||||
return 23-lsb(mkword(angle,0) / 2730)
|
||||
}
|
||||
|
||||
return direction(px1, py1, px2, py2)
|
||||
}
|
||||
sub direction_sc(byte x1, byte y1, byte x2, byte y2) -> ubyte {
|
||||
; From a pair of signed coordinates around the origin, calculate discrete direction between 0 and 23 into A.
|
||||
; shift the points into the positive quadrant
|
||||
ubyte px1
|
||||
ubyte py1
|
||||
ubyte px2
|
||||
ubyte py2
|
||||
if x1<0 or x2<0 {
|
||||
px1 = x1 as ubyte + 128
|
||||
px2 = x2 as ubyte + 128
|
||||
} else {
|
||||
px1 = x1 as ubyte
|
||||
px2 = x2 as ubyte
|
||||
}
|
||||
if y1<0 or y2<0 {
|
||||
py1 = y1 as ubyte + 128
|
||||
py2 = y2 as ubyte + 128
|
||||
} else {
|
||||
py1 = y1 as ubyte
|
||||
py2 = y2 as ubyte
|
||||
}
|
||||
|
||||
sub direction_qd(ubyte quadrant, ubyte xdelta, ubyte ydelta) -> ubyte {
|
||||
; From a pair of X/Y deltas (both >=0), and quadrant 0-3, calculate discrete direction between 0 and 23.
|
||||
when quadrant {
|
||||
3 -> return direction(0, 0, xdelta, ydelta)
|
||||
2 -> return direction(xdelta, 0, 0, ydelta)
|
||||
1 -> return direction(0, ydelta, xdelta, 0)
|
||||
else -> return direction(xdelta, ydelta, 0, 0)
|
||||
return direction(px1, py1, px2, py2)
|
||||
}
|
||||
|
||||
sub direction_qd(ubyte quadrant, ubyte xdelta, ubyte ydelta) -> ubyte {
|
||||
; From a pair of X/Y deltas (both >=0), and quadrant 0-3, calculate discrete direction between 0 and 23.
|
||||
when quadrant {
|
||||
3 -> return direction(0, 0, xdelta, ydelta)
|
||||
2 -> return direction(xdelta, 0, 0, ydelta)
|
||||
1 -> return direction(0, ydelta, xdelta, 0)
|
||||
else -> return direction(xdelta, ydelta, 0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
sub atan2(ubyte x1, ubyte y1, ubyte x2, ubyte y2) -> ubyte {
|
||||
;; Calculate the angle, in a 256-degree circle, between two points into A.
|
||||
;; The points (x1, y1) and (x2, y2) have to use *unsigned coordinates only* from the positive quadrant in the carthesian plane!
|
||||
%ir {{
|
||||
loadm.b r65532,math.atan2.x1
|
||||
loadm.b r65533,math.atan2.y1
|
||||
loadm.b r65534,math.atan2.x2
|
||||
loadm.b r65535,math.atan2.y2
|
||||
syscall 44 (r65532.b, r65533.b, r65534.b, r65535.b): r0.b
|
||||
returnr.b r0
|
||||
}}
|
||||
}
|
||||
|
||||
sub mul16_last_upper() -> uword {
|
||||
; This routine peeks into the internal 32 bits multiplication result buffer of the
|
||||
; 16*16 bits multiplication routine, to fetch the upper 16 bits of the last calculation.
|
||||
; Notes:
|
||||
; - to avoid interference it's best to fetch and store this value immediately after the multiplication expression.
|
||||
; for instance, simply printing a number may already result in new multiplication calls being performed
|
||||
; - not all multiplications in the source code result in an actual multiplication call:
|
||||
; some simpler multiplications will be optimized away into faster routines. These will not set the upper 16 bits at all!
|
||||
%ir {{
|
||||
syscall 46 (): r0.w
|
||||
returnr.w r0
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
sub atan2(ubyte x1, ubyte y1, ubyte x2, ubyte y2) -> ubyte {
|
||||
;; Calculate the angle, in a 256-degree circle, between two points into A.
|
||||
;; The points (x1, y1) and (x2, y2) have to use *unsigned coordinates only* from the positive quadrant in the carthesian plane!
|
||||
%ir {{
|
||||
loadm.b r65532,math.atan2.x1
|
||||
loadm.b r65533,math.atan2.y1
|
||||
loadm.b r65534,math.atan2.x2
|
||||
loadm.b r65535,math.atan2.y2
|
||||
syscall 44 (r65532.b, r65533.b, r65534.b, r65535.b): r0.b
|
||||
returnr.b r0
|
||||
}}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
- VM: make matn.mul16_last_upper()
|
||||
- clean up the active file channel assumptions in diskio (basically do chkin every time and not in f_open?)
|
||||
- return the file channel number from f_open and f_open_w instead of just true (so user can change it and set it back if they want instead of relying on the magic numbers 12 and 13)
|
||||
OR just add routines to set it back to 12/13 so no tracking has to occur by the user at all
|
||||
|
@ -1,4 +1,5 @@
|
||||
%import textio
|
||||
%import math
|
||||
;%import verafx
|
||||
%zeropage basicsafe
|
||||
%option no_sysinit
|
||||
@ -12,9 +13,10 @@ main {
|
||||
uword value1=5678
|
||||
uword value2=9999
|
||||
uword result = value1*value2
|
||||
uword upper16 = math.mul16_last_upper()
|
||||
txt.print_uw(result)
|
||||
txt.spc()
|
||||
txt.print_uw(math.mul16_last_upper())
|
||||
txt.print_uw(upper16)
|
||||
txt.nl()
|
||||
|
||||
|
||||
|
@ -53,6 +53,7 @@ SYSCALLS:
|
||||
43 = CLAMP_FLOAT
|
||||
44 = ATAN
|
||||
45 = STR_TO_FLOAT
|
||||
46 = MUL16_LAST_UPPER
|
||||
*/
|
||||
|
||||
enum class Syscall {
|
||||
@ -101,7 +102,8 @@ enum class Syscall {
|
||||
CLAMP_UWORD,
|
||||
CLAMP_FLOAT,
|
||||
ATAN,
|
||||
STR_TO_FLOAT
|
||||
STR_TO_FLOAT,
|
||||
MUL16_LAST_UPPER
|
||||
;
|
||||
|
||||
companion object {
|
||||
@ -490,6 +492,9 @@ object SysCalls {
|
||||
val result = floor(radians/2.0/PI*256.0)
|
||||
returnValue(callspec.returns!!, result, vm)
|
||||
}
|
||||
Syscall.MUL16_LAST_UPPER -> {
|
||||
returnValue(callspec.returns!!, vm.mul16_last_upper, vm)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
var statusNegative = false
|
||||
internal var randomGenerator = Random(0xa55a7653)
|
||||
internal var randomGeneratorFloats = Random(0xc0d3dbad)
|
||||
internal var mul16_last_upper = 0u
|
||||
val cx16virtualregsBaseAddress: Int
|
||||
|
||||
init {
|
||||
@ -1447,10 +1448,14 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
private fun plusMinusMultAnyWord(operator: String, reg1: Int, reg2: Int) {
|
||||
val left = registers.getUW(reg1)
|
||||
val right = registers.getUW(reg2)
|
||||
val result = when(operator) {
|
||||
"+" -> left + right
|
||||
"-" -> left - right
|
||||
"*" -> left * right
|
||||
val result: UInt
|
||||
when(operator) {
|
||||
"+" -> result = left + right
|
||||
"-" -> result = left - right
|
||||
"*" -> {
|
||||
result = left.toUInt() * right
|
||||
mul16_last_upper = result shr 16
|
||||
}
|
||||
else -> throw IllegalArgumentException("operator word $operator")
|
||||
}
|
||||
registers.setUW(reg1, result.toUShort())
|
||||
@ -1458,10 +1463,14 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
|
||||
private fun plusMinusMultConstWord(operator: String, reg1: Int, value: UShort) {
|
||||
val left = registers.getUW(reg1)
|
||||
val result = when(operator) {
|
||||
"+" -> left + value
|
||||
"-" -> left - value
|
||||
"*" -> left * value
|
||||
val result: UInt
|
||||
when(operator) {
|
||||
"+" -> result = left + value
|
||||
"-" -> result = left - value
|
||||
"*" -> {
|
||||
result = left.toUInt() * value
|
||||
mul16_last_upper = result shr 16
|
||||
}
|
||||
else -> throw IllegalArgumentException("operator word $operator")
|
||||
}
|
||||
registers.setUW(reg1, result.toUShort())
|
||||
@ -1470,10 +1479,14 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
private fun plusMinusMultAnyWordInplace(operator: String, reg1: Int, address: Int) {
|
||||
val memvalue = memory.getUW(address)
|
||||
val operand = registers.getUW(reg1)
|
||||
val result = when(operator) {
|
||||
"+" -> memvalue + operand
|
||||
"-" -> memvalue - operand
|
||||
"*" -> memvalue * operand
|
||||
val result: UInt
|
||||
when(operator) {
|
||||
"+" -> result = memvalue + operand
|
||||
"-" -> result = memvalue - operand
|
||||
"*" -> {
|
||||
result = memvalue.toUInt() * operand
|
||||
mul16_last_upper = result shr 16
|
||||
}
|
||||
else -> throw IllegalArgumentException("operator word $operator")
|
||||
}
|
||||
memory.setUW(address, result.toUShort())
|
||||
|
Loading…
x
Reference in New Issue
Block a user