actually, get rid of integer pow() because a naive multiplication loop approach is way too slow

This commit is contained in:
Irmen de Jong 2019-03-31 18:04:19 +02:00
parent b57c02b0ba
commit 905d8a0c06
10 changed files with 41 additions and 105 deletions

View File

@ -58,29 +58,29 @@ multiply_words .proc
stx c64.SCRATCH_ZPREGX
mult16 lda #$00
sta multiply_words_result+2 ; clear upper bits of product
sta multiply_words_result+3
sta result+2 ; clear upper bits of product
sta result+3
ldx #16 ; for all 16 bits...
- lsr c64.SCRATCH_ZPWORD1+1 ; divide multiplier by 2
ror c64.SCRATCH_ZPWORD1
bcc +
lda multiply_words_result+2 ; get upper half of product and add multiplicand
lda result+2 ; get upper half of product and add multiplicand
clc
adc c64.SCRATCH_ZPWORD2
sta multiply_words_result+2
lda multiply_words_result+3
sta result+2
lda result+3
adc c64.SCRATCH_ZPWORD2+1
+ ror a ; rotate partial product
sta multiply_words_result+3
ror multiply_words_result+2
ror multiply_words_result+1
ror multiply_words_result
sta result+3
ror result+2
ror result+1
ror result
dex
bne -
ldx c64.SCRATCH_ZPREGX
rts
multiply_words_result .byte 0,0,0,0
result .byte 0,0,0,0
.pend

View File

@ -105,7 +105,7 @@ not_word .proc
sta c64.ESTACK_HI + 1,x
rts
.pend
bitand_b .proc
; -- bitwise and (of 2 bytes)
lda c64.ESTACK_LO+2,x
@ -114,7 +114,7 @@ bitand_b .proc
sta c64.ESTACK_LO+1,x
rts
.pend
bitor_b .proc
; -- bitwise or (of 2 bytes)
lda c64.ESTACK_LO+2,x
@ -123,7 +123,7 @@ bitor_b .proc
sta c64.ESTACK_LO+1,x
rts
.pend
bitxor_b .proc
; -- bitwise xor (of 2 bytes)
lda c64.ESTACK_LO+2,x
@ -144,7 +144,7 @@ bitand_w .proc
inx
rts
.pend
bitor_w .proc
; -- bitwise or (of 2 words)
lda c64.ESTACK_LO+2,x
@ -156,7 +156,7 @@ bitor_w .proc
inx
rts
.pend
bitxor_w .proc
; -- bitwise xor (of 2 bytes)
lda c64.ESTACK_LO+2,x
@ -168,7 +168,7 @@ bitxor_w .proc
inx
rts
.pend
and_b .proc
; -- logical and (of 2 bytes)
lda c64.ESTACK_LO+2,x
@ -183,7 +183,7 @@ and_b .proc
sta c64.ESTACK_LO+1,x
rts
.pend
or_b .proc
; -- logical or (of 2 bytes)
lda c64.ESTACK_LO+2,x
@ -194,7 +194,7 @@ or_b .proc
sta c64.ESTACK_LO+1,x
rts
.pend
xor_b .proc
; -- logical xor (of 2 bytes)
lda c64.ESTACK_LO+2,x
@ -227,7 +227,7 @@ and_w .proc
sta c64.ESTACK_HI+1,x
rts
.pend
or_w .proc
; -- logical or (word or word -> byte)
lda c64.ESTACK_LO+2,x
@ -241,7 +241,7 @@ or_w .proc
sta c64.ESTACK_HI+1,x
rts
.pend
xor_w .proc
; -- logical xor (word xor word -> byte)
lda c64.ESTACK_LO+2,x
@ -322,9 +322,9 @@ mul_word .proc
stx c64.SCRATCH_ZPREGX
jsr math.multiply_words
ldx c64.SCRATCH_ZPREGX
lda math.multiply_words.multiply_words_result
lda math.multiply_words.result
sta c64.ESTACK_LO+1,x
lda math.multiply_words.multiply_words_result+1
lda math.multiply_words.result+1
sta c64.ESTACK_HI+1,x
rts
.pend
@ -648,8 +648,8 @@ func_read_flags .proc
dex
rts
.pend
func_sqrt16 .proc
lda c64.ESTACK_LO+1,x
sta c64.SCRATCH_ZPWORD2
@ -698,8 +698,8 @@ _skip3
rts
_stab .byte $01,$02,$04,$08,$10,$20,$40,$80
.pend
func_sin8 .proc
ldy c64.ESTACK_LO+1,x
lda _sinecos8,y
@ -1194,7 +1194,7 @@ func_rndw .proc
.pend
func_memcopy .proc
func_memcopy .proc
; note: clobbers A,Y
inx
stx c64.SCRATCH_ZPREGX
@ -1220,7 +1220,7 @@ func_memcopy .proc
rts
.pend
func_memset .proc
func_memset .proc
; note: clobbers A,Y
inx
stx c64.SCRATCH_ZPREGX
@ -1240,7 +1240,7 @@ func_memset .proc
rts
.pend
func_memsetw .proc
func_memsetw .proc
; note: clobbers A,Y
; -- fill memory from (SCRATCH_ZPWORD1) number of words in SCRATCH_ZPWORD2, with word value in AY.

View File

@ -688,15 +688,8 @@ private class AstChecker(private val namespace: INameScope,
}
}
"**" -> {
if(leftDt in IntegerDatatypes) {
val constvalRight = expr.right.constValue(namespace, heap)?.asNumericValue?.toDouble()
if(constvalRight==null) {
if(rightDt==DataType.FLOAT || rightDt==DataType.BYTE || rightDt==DataType.WORD)
checkResult.add(ExpressionError("raising to a signed value requires floating point", expr.position))
} else if(constvalRight<0.0) {
checkResult.add(ExpressionError("raising to negative power requires floating point", expr.position))
}
}
if(leftDt in IntegerDatatypes)
checkResult.add(ExpressionError("power operator requires floating point", expr.position))
}
"and", "or", "xor" -> {
// only integer numeric operands accepted, and if literal constants, only boolean values accepted (0 or 1)

View File

@ -1238,11 +1238,9 @@ internal class Compiler(private val rootModule: Module,
}
"**" -> {
when(dt) {
DataType.UBYTE -> Opcode.POW_UB
DataType.BYTE, DataType.WORD -> throw CompilerException("power operator only available for unsigned integer types and floats")
DataType.UWORD -> Opcode.POW_UW
in IntegerDatatypes -> throw CompilerException("power operator requires floating points")
DataType.FLOAT -> Opcode.POW_F
else -> throw CompilerException("only byte/word/float possible")
else -> throw CompilerException("only numeric datatype possible")
}
}
"&" -> {

View File

@ -58,8 +58,6 @@ enum class Opcode {
DIV_F,
REMAINDER_UB, // signed remainder is undefined/unimplemented
REMAINDER_UW, // signed remainder is undefined/unimplemented
POW_UB,
POW_UW,
POW_F,
NEG_B,
NEG_W,

View File

@ -729,9 +729,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
Opcode.ABS_B -> " jsr prog8_lib.abs_b"
Opcode.ABS_W -> " jsr prog8_lib.abs_w"
Opcode.ABS_F -> " jsr c64flt.abs_f"
Opcode.POW_UB -> " jsr prog8_lib.pow_ub" // @todo implement
Opcode.POW_UW -> " jsr prog8_lib.pow_uw" // @todo implement
Opcode.POW_F -> " jsr c64flt.pow_f" // @todo implement
Opcode.POW_F -> " jsr c64flt.pow_f"
Opcode.INV_BYTE -> {
"""
lda ${(ESTACK_LO + 1).toHex()},x

View File

@ -615,22 +615,6 @@ class StackVm(private var traceOutputFile: String?) {
evalstack.push(value)
setFlags(value)
}
Opcode.POW_UB -> {
val (top, second) = evalstack.pop2()
checkDt(top, DataType.UBYTE)
checkDt(second, DataType.UBYTE)
val value=second.pow(top)
evalstack.push(value)
setFlags(value)
}
Opcode.POW_UW -> {
val (top, second) = evalstack.pop2()
checkDt(top, DataType.UWORD)
checkDt(second, DataType.UWORD)
val value=second.pow(top)
evalstack.push(value)
setFlags(value)
}
Opcode.POW_F -> {
val (top, second) = evalstack.pop2()
checkDt(top, DataType.FLOAT)

View File

@ -372,8 +372,7 @@ Operators
arithmetic: ``+`` ``-`` ``*`` ``/`` ``**`` ``%``
``+``, ``-``, ``*``, ``/`` are the familiar arithmetic operations.
``/`` is division (will result in integer division when using on integer operands, and a floating point division when at least one of the operands is a float)
``**`` is the power operator: ``3 ** 5`` is equal to 3*3*3*3*3 and is 243. (certain restrictions
apply when dealing with signed or negative numbers)
``**`` is the power operator: ``3 ** 5`` is equal to 3*3*3*3*3 and is 243. (it only works on floating point variables)
``%`` 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

@ -86,6 +86,5 @@ of values together (and use it multiple times). Something like::
Misc
^^^^
- code generation for POW instruction
- are there any other missing instructions in the code generator?
- implement %asmbinary

View File

@ -13,53 +13,20 @@
float fl=2.3
float fl2=20
; ub = ub ** 7
; c64scr.print_ub(ub)
; c64.CHROUT('\n')
; uw = uw ** 5
; c64scr.print_uw(uw)
; c64.CHROUT('\n')
fl = (ub as float) ** 4
fl = 2.3
fl = fl ** 20.0
c64flt.print_f(fl)
c64.CHROUT('\n')
; ub=3 ; @todo no instruction?
; ub **=7 ; @todo no instruction?
; c64scr.print_ub(ub)
; c64.CHROUT('\n')
; uw = 9 ; @todo no instruction?
; uw **=5 ; @todo no instruction?
; c64scr.print_uw(uw)
; c64.CHROUT('\n')
fl = 2.3 ; @todo no instruction?
fl **=20.0 ; @todo no instruction?
fl = 2.3
fl = fl ** fl2
c64flt.print_f(fl)
c64.CHROUT('\n')
; ub=3
; ub **= 7
; c64scr.print_ub(ub)
; c64.CHROUT('\n')
; uw = 9
; uw **= 5
; c64scr.print_uw(uw)
; c64.CHROUT('\n')
fl = 2.3
fl **= 20.0
c64flt.print_f(fl)
c64.CHROUT('\n')
; ub=3
; ub **= ub2
; c64scr.print_ub(ub)
; c64.CHROUT('\n')
; uw = 9
; uw **= uw2
; c64scr.print_uw(uw)
; c64.CHROUT('\n')
fl = 2.3
fl **= fl2
fl **=20.0
c64flt.print_f(fl)
c64.CHROUT('\n')