mirror of
https://github.com/irmen/prog8.git
synced 2024-08-15 03:29:16 +00:00
multiplications
This commit is contained in:
parent
9ffc68acab
commit
ee893e5a2c
@ -1,6 +1,6 @@
|
||||
set PROG8_LIBDIR=../prog8lib
|
||||
set PROG8CLASSPATH=out/production/compiler/
|
||||
set KOTLINPATH=%USERPROFILE%/.IdeaIC2018.3/config/plugins/Kotlin
|
||||
set LIBJARS=%KOTLINPATH%/lib/kotlin-stdlib.jar;%KOTLINPATH%/lib/kotlin-reflect.jar;antlr/lib/antlr-runtime-4.7.1.jar
|
||||
set LIBJARS=%KOTLINPATH%/lib/kotlin-stdlib.jar;%KOTLINPATH%/lib/kotlin-reflect.jar;antlr/lib/antlr-runtime-4.7.2.jar
|
||||
|
||||
java -Dprog8.libdir=%PROG8_LIBDIR% -cp %PROG8CLASSPATH%;%LIBJARS% prog8.CompilerMainKt %*
|
||||
|
@ -3,6 +3,6 @@
|
||||
PROG8_LIBDIR=../prog8lib
|
||||
PROG8CLASSPATH=out/production/compiler
|
||||
KOTLINPATH=${HOME}/.IntelliJIdea2018.3/config/plugins/Kotlin
|
||||
LIBJARS=${KOTLINPATH}/lib/kotlin-stdlib.jar:${KOTLINPATH}/lib/kotlin-reflect.jar:antlr/lib/antlr-runtime-4.7.1.jar
|
||||
LIBJARS=${KOTLINPATH}/lib/kotlin-stdlib.jar:${KOTLINPATH}/lib/kotlin-reflect.jar:antlr/lib/antlr-runtime-4.7.2.jar
|
||||
|
||||
java -Dprog8.libdir=${PROG8_LIBDIR} -cp ${PROG8CLASSPATH}:${LIBJARS} prog8.CompilerMainKt $*
|
||||
|
@ -6,23 +6,127 @@
|
||||
|
||||
;c64scr.PLOT(screenx(x), screeny(y)) ; @todo fix argument calculation???!!!
|
||||
|
||||
; @todo unify the type cast functions... "wrd(5)" -> "5 as word"
|
||||
|
||||
; @todo docs: "integer / int will not result in float but is integer floor division." verify this!
|
||||
|
||||
sub toscreenx(float x, float z) -> word {
|
||||
return 42.w as word
|
||||
}
|
||||
|
||||
asmsub blerp(ubyte x @ A, uword ding @ XY) -> clobbers() -> () {
|
||||
word qq = A as word
|
||||
}
|
||||
|
||||
sub start() {
|
||||
|
||||
word x = toscreenx(1.22, 3.22)
|
||||
blerp(4, 555)
|
||||
ubyte ub1
|
||||
ubyte ub2
|
||||
ubyte ub3
|
||||
byte b1
|
||||
byte b2
|
||||
byte b3
|
||||
uword uw1
|
||||
uword uw2
|
||||
uword uw3
|
||||
word w1
|
||||
word w2
|
||||
word w3
|
||||
float f1
|
||||
float f2
|
||||
float f3
|
||||
|
||||
c64scr.print(" X=")
|
||||
c64scr.print_ub(X)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
ub1=20
|
||||
ub2=6
|
||||
ub3=ub1*ub2
|
||||
c64scr.print_ub(ub3) ; 120
|
||||
c64.CHROUT('\n')
|
||||
uw1=900
|
||||
uw2=66
|
||||
uw3=uw1*uw2
|
||||
c64scr.print_uw(uw3) ; 59400
|
||||
c64.CHROUT('\n')
|
||||
|
||||
b1=20
|
||||
b2=6
|
||||
b3=b1*b2
|
||||
c64scr.print_b(b3) ; 120
|
||||
c64.CHROUT('\n')
|
||||
w1=500
|
||||
w2=44
|
||||
w3=w1*w2
|
||||
c64scr.print_w(w3) ; 22000
|
||||
c64.CHROUT('\n')
|
||||
b1=20
|
||||
b2=-6
|
||||
b3=b1*b2
|
||||
c64scr.print_b(b3) ; -120
|
||||
c64.CHROUT('\n')
|
||||
w1=500
|
||||
w2=-44
|
||||
w3=w1*w2
|
||||
c64scr.print_w(w3) ; -22000
|
||||
c64.CHROUT('\n')
|
||||
b1=-20
|
||||
b2=-6
|
||||
b3=b1*b2
|
||||
c64scr.print_b(b3) ; 120
|
||||
c64.CHROUT('\n')
|
||||
w1=-500
|
||||
w2=-44
|
||||
w3=w1*w2
|
||||
c64scr.print_w(w3) ; 22000
|
||||
c64.CHROUT('\n')
|
||||
f1=-500.11
|
||||
f2=44.4
|
||||
f3=f1*f2
|
||||
c64flt.print_f(f3)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
|
||||
; ub3 = 200/67 as ubyte
|
||||
; ub3 = 200//67
|
||||
; c64scr.print_ub(ub3)
|
||||
; c64.CHROUT('\n')
|
||||
; ub3 = ub1/ub2
|
||||
; c64scr.print_ub(ub3)
|
||||
; c64.CHROUT('\n')
|
||||
; ub3 = ub1//ub2
|
||||
; c64scr.print_ub(ub3)
|
||||
; c64.CHROUT('\n')
|
||||
;
|
||||
; uw3 = 2000/67 as uword
|
||||
; c64scr.print_uw(uw3)
|
||||
; c64.CHROUT('\n')
|
||||
; uw3 = 2000//67
|
||||
; c64scr.print_uw(uw3)
|
||||
; c64.CHROUT('\n')
|
||||
; uw3 = uw1/uw2
|
||||
; c64scr.print_uw(uw3)
|
||||
; c64.CHROUT('\n')
|
||||
; uw3 = uw1//uw2
|
||||
; c64scr.print_uw(uw3)
|
||||
; c64.CHROUT('\n')
|
||||
;
|
||||
; f3 = 999/44
|
||||
; c64flt.print_f(f3)
|
||||
; c64.CHROUT('\n')
|
||||
; f3 = 999//44
|
||||
; c64flt.print_f(f3)
|
||||
; c64.CHROUT('\n')
|
||||
; f3 = f1/f2
|
||||
; c64flt.print_f(f3)
|
||||
; c64.CHROUT('\n')
|
||||
; f3 = f1//f2
|
||||
; c64flt.print_f(f3)
|
||||
; c64.CHROUT('\n')
|
||||
; f3 = ub1/ub2
|
||||
; c64flt.print_f(f3)
|
||||
; c64.CHROUT('\n')
|
||||
; f3 = ub1//ub2
|
||||
; c64flt.print_f(f3)
|
||||
; c64.CHROUT('\n')
|
||||
; f3 = uw1/uw2
|
||||
; c64flt.print_f(f3)
|
||||
; c64.CHROUT('\n')
|
||||
; f3 = uw1//uw2
|
||||
; c64flt.print_f(f3)
|
||||
; c64.CHROUT('\n')
|
||||
c64scr.print(" X=")
|
||||
c64scr.print_ub(X)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
; const byte width=20
|
||||
; word w1
|
||||
@ -36,10 +140,10 @@
|
||||
; c64scr.print_byte(b1)
|
||||
; c64.CHROUT('\n')
|
||||
; ub1 = b2ub(fintb(x * flt(width)/4.2) + width//2)
|
||||
; c64scr.print_ubyte(ub1)
|
||||
; c64scr.print_ub(ub1)
|
||||
; c64.CHROUT('\n')
|
||||
; ub1 = b2ub(fintb(x/4.2 * flt(width)) + width//2)
|
||||
; c64scr.print_ubyte(ub1)
|
||||
; c64scr.print_ub(ub1)
|
||||
; c64.CHROUT('\n')
|
||||
; w1 = fintw(x * flt(width)/4.2) + width//2
|
||||
; c64scr.print_word(w1)
|
||||
|
@ -895,7 +895,7 @@ class BinaryExpression(var left: IExpression, var operator: String, var right: I
|
||||
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
|
||||
}
|
||||
DataType.FLOAT -> when(rightDt) {
|
||||
in NumericDatatypes -> DataType.WORD
|
||||
in NumericDatatypes -> DataType.FLOAT
|
||||
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
|
||||
}
|
||||
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
|
||||
|
@ -55,7 +55,7 @@ enum class Opcode {
|
||||
DIV_UW,
|
||||
DIV_W,
|
||||
DIV_F,
|
||||
FLOORDIV,
|
||||
FLOORDIV, // integer division but on floatint point argument(s)
|
||||
REMAINDER_UB,
|
||||
REMAINDER_B,
|
||||
REMAINDER_UW,
|
||||
|
@ -410,7 +410,7 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
|
||||
DataType.UWORD -> Value(DataType.UWORD, numericValue())
|
||||
DataType.WORD -> Value(DataType.WORD, numericValue())
|
||||
DataType.FLOAT -> Value(DataType.FLOAT, numericValue())
|
||||
else -> throw ValueException("invalid type cast from $type to $targetType")
|
||||
else -> throw ValueException("invalid type cast from $type to $targetType") // @todo ast-check for this
|
||||
}
|
||||
}
|
||||
DataType.BYTE -> {
|
||||
@ -420,7 +420,7 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
|
||||
DataType.UWORD -> Value(DataType.UWORD, integerValue() and 65535)
|
||||
DataType.WORD -> Value(DataType.WORD, integerValue())
|
||||
DataType.FLOAT -> Value(DataType.FLOAT, numericValue())
|
||||
else -> throw ValueException("invalid type cast from $type to $targetType")
|
||||
else -> throw ValueException("invalid type cast from $type to $targetType") // @todo ast-check for this
|
||||
}
|
||||
}
|
||||
DataType.UWORD -> {
|
||||
@ -434,7 +434,7 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
|
||||
Value(DataType.WORD, -(65536-integerValue()))
|
||||
}
|
||||
DataType.FLOAT -> Value(DataType.FLOAT, numericValue())
|
||||
else -> throw ValueException("invalid type cast from $type to $targetType")
|
||||
else -> throw ValueException("invalid type cast from $type to $targetType") // @todo ast-check for this
|
||||
}
|
||||
}
|
||||
DataType.WORD -> {
|
||||
@ -443,7 +443,7 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
|
||||
DataType.UWORD -> Value(DataType.UWORD, integerValue() and 65535)
|
||||
DataType.WORD -> this
|
||||
DataType.FLOAT -> Value(DataType.FLOAT, numericValue())
|
||||
else -> throw ValueException("invalid type cast from $type to $targetType")
|
||||
else -> throw ValueException("invalid type cast from $type to $targetType") // @todo ast-check for this
|
||||
}
|
||||
}
|
||||
DataType.FLOAT -> {
|
||||
@ -453,7 +453,7 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
|
||||
if(integer in -128..127)
|
||||
Value(DataType.BYTE, integer)
|
||||
else
|
||||
throw AstException("overflow when casting float to byte: $this")
|
||||
throw AstException("overflow when casting float to byte: $this") // @todo ast-check for this
|
||||
}
|
||||
DataType.UBYTE -> Value(DataType.UBYTE, numericValue().toInt() and 255)
|
||||
DataType.UWORD -> Value(DataType.UWORD, numericValue().toInt() and 65535)
|
||||
@ -462,13 +462,13 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
|
||||
if(integer in -32768..32767)
|
||||
Value(DataType.WORD, integer)
|
||||
else
|
||||
throw AstException("overflow when casting float to word: $this")
|
||||
throw AstException("overflow when casting float to word: $this") // @todo ast-check for this
|
||||
}
|
||||
DataType.FLOAT -> this
|
||||
else -> throw ValueException("invalid type cast from $type to $targetType")
|
||||
else -> throw ValueException("invalid type cast from $type to $targetType") // @todo ast-check for this
|
||||
}
|
||||
}
|
||||
else -> throw ValueException("invalid type cast from $type to $targetType")
|
||||
else -> throw ValueException("invalid type cast from $type to $targetType") // @todo ast-check for this
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -690,11 +690,6 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
Opcode.CAST_B_TO_UW, Opcode.CAST_B_TO_W -> " ${signExtendA("${ESTACK_HI+1},x")}" // sign extend the lsb @todo missing an lda???
|
||||
Opcode.MSB -> " lda ${(ESTACK_HI+1).toHex()},x | sta ${(ESTACK_LO+1).toHex()},x"
|
||||
|
||||
Opcode.DIV_UB -> " jsr prog8_lib.div_ub"
|
||||
Opcode.DIV_B -> " jsr prog8_lib.div_b"
|
||||
Opcode.DIV_F -> " jsr prog8_lib.div_f"
|
||||
Opcode.DIV_W -> " jsr prog8_lib.div_w"
|
||||
Opcode.DIV_UW -> " jsr prog8_lib.div_uw"
|
||||
Opcode.ADD_UB, Opcode.ADD_B -> {
|
||||
"""
|
||||
lda ${(ESTACK_LO + 2).toHex()},x
|
||||
@ -713,15 +708,19 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
sta ${(ESTACK_LO + 1).toHex()},x
|
||||
"""
|
||||
}
|
||||
Opcode.ADD_W, Opcode.ADD_UW -> " jsr prog8_lib.add_w"
|
||||
Opcode.ADD_W, Opcode.ADD_UW -> " jsr prog8_lib.add_word"
|
||||
Opcode.SUB_W, Opcode.SUB_UW -> " jsr prog8_lib.sub_word"
|
||||
Opcode.MUL_B, Opcode.MUL_UB -> " jsr prog8_lib.mul_byte"
|
||||
Opcode.MUL_W, Opcode.MUL_UW -> " jsr prog8_lib.mul_word"
|
||||
Opcode.ADD_F -> " jsr prog8_lib.add_f"
|
||||
Opcode.SUB_W, Opcode.SUB_UW -> " jsr prog8_lib.sub_w"
|
||||
Opcode.SUB_F -> " jsr prog8_lib.sub_f"
|
||||
Opcode.MUL_B -> " jsr prog8_lib.mul_b"
|
||||
Opcode.MUL_UB -> " jsr prog8_lib.mul_ub"
|
||||
Opcode.MUL_W -> " jsr prog8_lib.mul_w"
|
||||
Opcode.MUL_UW -> " jsr prog8_lib.mul_uw"
|
||||
Opcode.MUL_F -> " jsr prog8_lib.mul_f"
|
||||
Opcode.DIV_UB -> " jsr prog8_lib.div_ub"
|
||||
Opcode.DIV_B -> " jsr prog8_lib.div_b"
|
||||
Opcode.DIV_F -> " jsr prog8_lib.div_f"
|
||||
Opcode.DIV_W -> " jsr prog8_lib.div_w"
|
||||
Opcode.DIV_UW -> " jsr prog8_lib.div_uw"
|
||||
Opcode.FLOORDIV -> " jsr prog8_lib.floordiv_f"
|
||||
|
||||
Opcode.AND_BYTE -> {
|
||||
"""
|
||||
|
@ -432,11 +432,13 @@ You can also reference idendifiers defined elsewhere in your code.
|
||||
will be automatically converted into floats in this case. The compiler will issue a warning though when this happens, because floating
|
||||
point calculations are very slow and possibly unintended!
|
||||
|
||||
Calculations with integers will not result in floating point values;
|
||||
if you divide two integer values (say: ``32500 / 99``) the result will be the integer floor
|
||||
Calculations with integer variables will not result in floating point values.
|
||||
if you divide two integer variables say 32500 and 99 the result will be the integer floor
|
||||
division (328) rather than the floating point result (328.2828282828283). If you need the full precision,
|
||||
you'll have to make sure at least the first operand is a floating point. So write ``32500.0 / 99.0``,
|
||||
or use the type cast ``value as float``.
|
||||
you'll have to make sure at least the first operand is a floating point. You can do this by
|
||||
using a floating point value or variable, or use a type cast.
|
||||
When the compiler can calculate the result during compile-time, it will try to avoid loss
|
||||
of precision though and gives an error if you may be losing a floating point result.
|
||||
|
||||
|
||||
|
||||
|
@ -280,7 +280,7 @@ asmsub GETADRAY () -> clobbers(X) -> (uword @ AY) {
|
||||
}}
|
||||
}
|
||||
|
||||
sub print_float (float value) {
|
||||
sub print_f (float value) {
|
||||
; ---- prints the floating point value (without a newline) using basic rom routines.
|
||||
; clobbers no registers.
|
||||
; @todo version that takes A/Y pointer to float instead
|
||||
@ -290,8 +290,8 @@ sub print_float (float value) {
|
||||
pha
|
||||
txa
|
||||
pha
|
||||
lda #<print_float_value
|
||||
ldy #>print_float_value
|
||||
lda #<print_f_value
|
||||
ldy #>print_f_value
|
||||
jsr c64.MOVFM ; load float into fac1
|
||||
jsr c64.FOUT ; fac1 to string in A/Y
|
||||
jsr c64.STROUT ; print string in A/Y
|
||||
@ -304,7 +304,7 @@ sub print_float (float value) {
|
||||
}}
|
||||
}
|
||||
|
||||
sub print_float_ln (float value) {
|
||||
sub print_fln (float value) {
|
||||
; ---- prints the floating point value (with a newline at the end) using basic rom routines
|
||||
; clobbers no registers.
|
||||
; @todo version that takes A/Y pointer to float instead
|
||||
@ -314,8 +314,8 @@ sub print_float_ln (float value) {
|
||||
pha
|
||||
txa
|
||||
pha
|
||||
lda #<print_float_ln_value
|
||||
ldy #>print_float_ln_value
|
||||
lda #<print_fln_value
|
||||
ldy #>print_fln_value
|
||||
jsr c64.MOVFM ; load float into fac1
|
||||
jsr c64.FPRINTLN ; print fac1 with newline
|
||||
pla
|
||||
@ -579,7 +579,7 @@ _scroll_screen ; scroll the screen memory
|
||||
|
||||
|
||||
|
||||
asmsub print_string (str text @ AY) -> clobbers(A,Y) -> () {
|
||||
asmsub print (str text @ AY) -> clobbers(A,Y) -> () {
|
||||
; ---- print null terminated string from A/Y
|
||||
; note: the compiler contains an optimization that will replace
|
||||
; a call to this subroutine with a string argument of just one char,
|
||||
@ -598,7 +598,7 @@ asmsub print_string (str text @ AY) -> clobbers(A,Y) -> () {
|
||||
}
|
||||
|
||||
|
||||
asmsub print_pstring (str_p text @ AY) -> clobbers(A,X) -> (ubyte @ Y) {
|
||||
asmsub print_p (str_p text @ AY) -> clobbers(A,X) -> (ubyte @ Y) {
|
||||
; ---- print pstring (length as first byte) from A/Y, returns str len in Y
|
||||
%asm {{
|
||||
sta c64.SCRATCH_ZPB1
|
||||
@ -617,7 +617,7 @@ asmsub print_pstring (str_p text @ AY) -> clobbers(A,X) -> (ubyte @ Y) {
|
||||
}
|
||||
|
||||
|
||||
asmsub print_ubyte0 (ubyte value @ A) -> clobbers(A,X,Y) -> () {
|
||||
asmsub print_ub0 (ubyte value @ A) -> clobbers(A,X,Y) -> () {
|
||||
; ---- print the ubyte in A in decimal form, with left padding 0s (3 positions total)
|
||||
%asm {{
|
||||
jsr c64utils.ubyte2decimal
|
||||
@ -632,7 +632,7 @@ asmsub print_ubyte0 (ubyte value @ A) -> clobbers(A,X,Y) -> () {
|
||||
}
|
||||
|
||||
|
||||
asmsub print_ubyte (ubyte value @ A) -> clobbers(A,X,Y) -> () {
|
||||
asmsub print_ub (ubyte value @ A) -> clobbers(A,X,Y) -> () {
|
||||
; ---- print the ubyte in A in decimal form, without left padding 0s
|
||||
%asm {{
|
||||
jsr c64utils.ubyte2decimal
|
||||
@ -653,7 +653,7 @@ _print_tens txa
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub print_byte (byte value @ A) -> clobbers(A,X,Y) -> () {
|
||||
asmsub print_b (byte value @ A) -> clobbers(A,X,Y) -> () {
|
||||
; ---- print the byte in A in decimal form, without left padding 0s
|
||||
%asm {{
|
||||
pha
|
||||
@ -663,12 +663,12 @@ asmsub print_byte (byte value @ A) -> clobbers(A,X,Y) -> () {
|
||||
jsr c64.CHROUT
|
||||
+ pla
|
||||
jsr c64utils.byte2decimal
|
||||
jmp print_ubyte._print_byte_digits
|
||||
jmp print_ub._print_byte_digits
|
||||
}}
|
||||
}
|
||||
|
||||
|
||||
asmsub print_ubyte_hex (ubyte prefix @ Pc, ubyte value @ A) -> clobbers(A,X,Y) -> () {
|
||||
asmsub print_ubhex (ubyte prefix @ Pc, ubyte value @ A) -> clobbers(A,X,Y) -> () {
|
||||
; ---- print the ubyte in A in hex form (if Carry is set, a radix prefix '$' is printed as well)
|
||||
%asm {{
|
||||
bcc +
|
||||
@ -684,21 +684,21 @@ asmsub print_ubyte_hex (ubyte prefix @ Pc, ubyte value @ A) -> clobbers(A,X,Y)
|
||||
}
|
||||
|
||||
|
||||
asmsub print_uword_hex (ubyte prefix @ Pc, uword value @ AY) -> clobbers(A,X,Y) -> () {
|
||||
asmsub print_uwhex (ubyte prefix @ Pc, uword value @ AY) -> clobbers(A,X,Y) -> () {
|
||||
; ---- print the uword in A/Y in hexadecimal form (4 digits)
|
||||
; (if Carry is set, a radix prefix '$' is printed as well)
|
||||
%asm {{
|
||||
pha
|
||||
tya
|
||||
jsr print_ubyte_hex
|
||||
jsr print_ubhex
|
||||
pla
|
||||
clc
|
||||
jmp print_ubyte_hex
|
||||
jmp print_ubhex
|
||||
}}
|
||||
}
|
||||
|
||||
|
||||
asmsub print_uword0 (uword value @ AY) -> clobbers(A,X,Y) -> () {
|
||||
asmsub print_uw0 (uword value @ AY) -> clobbers(A,X,Y) -> () {
|
||||
; ---- print the uword in A/Y in decimal form, with left padding 0s (5 positions total)
|
||||
; @todo shorter in loop form?
|
||||
%asm {{
|
||||
@ -717,7 +717,7 @@ asmsub print_uword0 (uword value @ AY) -> clobbers(A,X,Y) -> () {
|
||||
}
|
||||
|
||||
|
||||
asmsub print_uword (uword value @ AY) -> clobbers(A,X,Y) -> () {
|
||||
asmsub print_uw (uword value @ AY) -> clobbers(A,X,Y) -> () {
|
||||
; ---- print the uword in A/Y in decimal form, without left padding 0s
|
||||
%asm {{
|
||||
jsr c64utils.uword2decimal
|
||||
@ -749,7 +749,7 @@ _pr_decimal
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub print_word (word value @ AY) -> clobbers(A,X,Y) -> () {
|
||||
asmsub print_w (word value @ AY) -> clobbers(A,X,Y) -> () {
|
||||
; ---- print the (signed) word in A/Y in decimal form, without left padding 0s
|
||||
%asm {{
|
||||
cpy #0
|
||||
@ -766,7 +766,7 @@ asmsub print_word (word value @ AY) -> clobbers(A,X,Y) -> () {
|
||||
adc #1
|
||||
bcc +
|
||||
iny
|
||||
+ jmp print_uword
|
||||
+ jmp print_uw
|
||||
}}
|
||||
}
|
||||
|
||||
|
@ -19,19 +19,19 @@
|
||||
|
||||
|
||||
|
||||
asmsub multiply_bytes (ubyte byte1 @ A, ubyte byte2 @ Y) -> clobbers(X) -> (ubyte @ A) {
|
||||
asmsub multiply_bytes (ubyte byte1 @ A, ubyte byte2 @ Y) -> clobbers() -> (ubyte @ A) {
|
||||
; ---- multiply 2 bytes, result as byte in A (signed or unsigned)
|
||||
%asm {{
|
||||
sta SCRATCH_ZPB1
|
||||
sty SCRATCH_ZPREG
|
||||
ldx #8
|
||||
- asl a
|
||||
asl SCRATCH_ZPB1
|
||||
bcc +
|
||||
clc
|
||||
adc SCRATCH_ZPREG
|
||||
+ dex
|
||||
bne -
|
||||
sta SCRATCH_ZPB1 ; num1
|
||||
sty SCRATCH_ZPREG ; num2
|
||||
lda #0
|
||||
beq _enterloop
|
||||
_doAdd clc
|
||||
adc SCRATCH_ZPB1
|
||||
_loop asl SCRATCH_ZPB1
|
||||
_enterloop lsr SCRATCH_ZPREG
|
||||
bcs _doAdd
|
||||
bne _loop
|
||||
rts
|
||||
}}
|
||||
}
|
||||
@ -58,41 +58,42 @@ asmsub multiply_bytes_16 (ubyte byte1 @ A, ubyte byte2 @ Y) -> clobbers(X) ->
|
||||
}}
|
||||
}
|
||||
|
||||
word[2] multiply_words_product = 0
|
||||
asmsub multiply_words (uword number @ AY) -> clobbers(A,X) -> () {
|
||||
; ---- multiply two 16-bit words into a 32-bit result
|
||||
; ---- multiply two 16-bit words into a 32-bit result (signed and unsigned)
|
||||
; input: A/Y = first 16-bit number, SCRATCH_ZPWORD1 in ZP = second 16-bit number
|
||||
; output: multiply_words_product 32-bits product, LSB order (low-to-high)
|
||||
; output: multiply_words.result 4-bytes/32-bits product, LSB order (low-to-high)
|
||||
|
||||
%asm {{
|
||||
sta SCRATCH_ZPWORD2
|
||||
sty SCRATCH_ZPWORD2+1
|
||||
|
||||
mult16 lda #$00
|
||||
sta multiply_words_product+2 ; clear upper bits of product
|
||||
sta multiply_words_product+3
|
||||
sta multiply_words_result+2 ; clear upper bits of product
|
||||
sta multiply_words_result+3
|
||||
ldx #16 ; for all 16 bits...
|
||||
- lsr SCRATCH_ZPWORD1+1 ; divide multiplier by 2
|
||||
ror SCRATCH_ZPWORD1
|
||||
bcc +
|
||||
lda multiply_words_product+2 ; get upper half of product and add multiplicand
|
||||
lda multiply_words_result+2 ; get upper half of product and add multiplicand
|
||||
clc
|
||||
adc SCRATCH_ZPWORD2
|
||||
sta multiply_words_product+2
|
||||
lda multiply_words_product+3
|
||||
sta multiply_words_result+2
|
||||
lda multiply_words_result+3
|
||||
adc SCRATCH_ZPWORD2+1
|
||||
+ ror a ; rotate partial product
|
||||
sta multiply_words_product+3
|
||||
ror multiply_words_product+2
|
||||
ror multiply_words_product+1
|
||||
ror multiply_words_product
|
||||
sta multiply_words_result+3
|
||||
ror multiply_words_result+2
|
||||
ror multiply_words_result+1
|
||||
ror multiply_words_result
|
||||
dex
|
||||
bne -
|
||||
rts
|
||||
|
||||
multiply_words_result .fill 4
|
||||
|
||||
}}
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
; division by zero will result in quotient = 255 and remainder = original number
|
||||
|
@ -316,7 +316,18 @@ push_fac1_as_result .proc
|
||||
jmp push_float
|
||||
.pend
|
||||
|
||||
|
||||
|
||||
floordiv_f .proc
|
||||
; -- push f1//f2 on stack
|
||||
jsr pop_2_floats_f2_in_fac1
|
||||
stx SCRATCH_ZPREGX
|
||||
lda #<fmath_float1
|
||||
ldy #>fmath_float1
|
||||
jsr c64.FDIV
|
||||
jsr c64.INT
|
||||
jmp push_fac1_as_result
|
||||
.pend
|
||||
|
||||
div_f .proc
|
||||
; -- push f1/f2 on stack
|
||||
jsr pop_2_floats_f2_in_fac1
|
||||
@ -465,47 +476,80 @@ sub_w .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
mul_b .proc
|
||||
mul_byte .proc
|
||||
; -- b*b->b (signed and unsigned)
|
||||
inx
|
||||
lda ESTACK_LO,x
|
||||
ldy ESTACK_LO+1,x
|
||||
jsr math.multiply_bytes
|
||||
sta ESTACK_LO+1,x
|
||||
rts
|
||||
.warn "mul_b not implemented"
|
||||
.pend
|
||||
|
||||
mul_ub .proc
|
||||
mul_word .proc
|
||||
inx
|
||||
lda ESTACK_LO,x
|
||||
sta SCRATCH_ZPWORD1
|
||||
lda ESTACK_HI,x
|
||||
sta SCRATCH_ZPWORD1+1
|
||||
lda ESTACK_LO+1,x
|
||||
ldy ESTACK_HI+1,x
|
||||
stx SCRATCH_ZPREGX
|
||||
jsr math.multiply_words
|
||||
ldx SCRATCH_ZPREGX
|
||||
lda math.multiply_words_result
|
||||
sta ESTACK_LO+1,x
|
||||
lda math.multiply_words_result+1
|
||||
sta ESTACK_HI+1,x
|
||||
rts
|
||||
.warn "mul_ub not implemented"
|
||||
.pend
|
||||
|
||||
mul_w .proc
|
||||
rts
|
||||
.warn "mul_w not implemented"
|
||||
.pend
|
||||
|
||||
mul_uw .proc
|
||||
rts
|
||||
.warn "mul_uw not implemented"
|
||||
.pend
|
||||
|
||||
div_b .proc
|
||||
inx
|
||||
lda #42
|
||||
sta ESTACK_LO+1,x
|
||||
lda #0
|
||||
sta ESTACK_HI+1,x
|
||||
rts
|
||||
.warn "div_b not implemented"
|
||||
.pend
|
||||
|
||||
div_ub .proc
|
||||
inx
|
||||
lda #42
|
||||
sta ESTACK_LO+1,x
|
||||
lda #0
|
||||
sta ESTACK_HI+1,x
|
||||
rts
|
||||
.warn "div_ub not implemented"
|
||||
.pend
|
||||
|
||||
div_w .proc
|
||||
inx
|
||||
lda #42
|
||||
sta ESTACK_LO+1,x
|
||||
lda #0
|
||||
sta ESTACK_HI+1,x
|
||||
rts
|
||||
.warn "div_w not implemented"
|
||||
.pend
|
||||
|
||||
div_uw .proc
|
||||
inx
|
||||
lda #42
|
||||
sta ESTACK_LO+1,x
|
||||
lda #0
|
||||
sta ESTACK_HI+1,x
|
||||
rts
|
||||
.warn "div_uw not implemented"
|
||||
.pend
|
||||
|
||||
remainder_b .proc
|
||||
inx
|
||||
lda #42
|
||||
sta ESTACK_LO+1,x
|
||||
lda #0
|
||||
sta ESTACK_HI+1,x
|
||||
rts
|
||||
.warn "remainder_b via div_b?"
|
||||
.pend
|
||||
@ -524,18 +568,27 @@ remainder_ub .proc
|
||||
.pend
|
||||
|
||||
remainder_w .proc
|
||||
inx
|
||||
lda #42
|
||||
sta ESTACK_LO+1,x
|
||||
lda #0
|
||||
sta ESTACK_HI+1,x
|
||||
rts
|
||||
.warn "remainder_w not implemented - via div_w"
|
||||
.pend
|
||||
|
||||
remainder_uw .proc
|
||||
inx
|
||||
lda #42
|
||||
sta ESTACK_LO+1,x
|
||||
lda #0
|
||||
sta ESTACK_HI+1,x
|
||||
rts
|
||||
.warn "remainder_uw not implemented - via div_uw"
|
||||
.pend
|
||||
|
||||
equal_w .proc
|
||||
; -- are the two words on the stack identical?
|
||||
; @todo optimize according to http://www.6502.org/tutorials/compare_beyond.html
|
||||
lda ESTACK_LO+1,x
|
||||
cmp ESTACK_LO+2,x
|
||||
bne equal_b._equal_b_false
|
||||
|
Loading…
Reference in New Issue
Block a user