mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
actually, get rid of integer pow() because a naive multiplication loop approach is way too slow
This commit is contained in:
parent
b57c02b0ba
commit
905d8a0c06
@ -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
|
||||
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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")
|
||||
}
|
||||
}
|
||||
"&" -> {
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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).
|
||||
|
||||
|
@ -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
|
||||
|
@ -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')
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user