mirror of
https://github.com/irmen/prog8.git
synced 2024-06-26 07:29:32 +00:00
abs()
This commit is contained in:
parent
bcfb390077
commit
4be6a2eeef
|
@ -10,7 +10,7 @@
|
|||
byte v1
|
||||
byte v2
|
||||
|
||||
c64scr.print_byte_decimal(X)
|
||||
c64scr.print_byte(X)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
v1 = 100
|
||||
|
@ -110,7 +110,7 @@
|
|||
else
|
||||
c64.STROUT("error in 22>=22!\n")
|
||||
|
||||
c64scr.print_byte_decimal(X)
|
||||
c64scr.print_byte(X)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
float v1
|
||||
float v2
|
||||
|
||||
c64scr.print_byte_decimal(X)
|
||||
c64scr.print_byte(X)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
v1 = 1.11
|
||||
|
@ -110,7 +110,7 @@
|
|||
else
|
||||
c64.STROUT("error in -22.2>=-22.2!\n")
|
||||
|
||||
c64scr.print_byte_decimal(X)
|
||||
c64scr.print_byte(X)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
uword v1
|
||||
uword v2
|
||||
|
||||
c64scr.print_byte_decimal(X)
|
||||
c64scr.print_byte(X)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
v1 = 100
|
||||
|
@ -110,7 +110,7 @@
|
|||
else
|
||||
c64.STROUT("error in 322>=322!\n")
|
||||
|
||||
c64scr.print_byte_decimal(X)
|
||||
c64scr.print_byte(X)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
; check stack usage:
|
||||
c64.STROUT("signed byte ")
|
||||
c64scr.print_byte_decimal(X)
|
||||
c64scr.print_byte(X)
|
||||
c64.CHROUT(' ')
|
||||
|
||||
cr=v1==v2
|
||||
|
@ -39,7 +39,7 @@
|
|||
cr=v1>=v2
|
||||
cr=v1>=v2
|
||||
|
||||
c64scr.print_byte_decimal(X)
|
||||
c64scr.print_byte(X)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
; comparisons:
|
||||
|
@ -58,7 +58,7 @@
|
|||
c64.STROUT("v1=20, v2=-111\n")
|
||||
compare()
|
||||
|
||||
c64scr.print_byte_decimal(X)
|
||||
c64scr.print_byte(X)
|
||||
c64.CHROUT('\n')
|
||||
return
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
; check stack usage:
|
||||
c64.STROUT("floating point ")
|
||||
c64scr.print_byte_decimal(X)
|
||||
c64scr.print_byte(X)
|
||||
c64.CHROUT(' ')
|
||||
|
||||
cr=v1==v2
|
||||
|
@ -41,7 +41,7 @@
|
|||
cr=v1>=v2
|
||||
cr=v1>=v2
|
||||
|
||||
c64scr.print_byte_decimal(X)
|
||||
c64scr.print_byte(X)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
; comparisons:
|
||||
|
@ -75,7 +75,7 @@
|
|||
c64.STROUT("v1 = v2 = 0\n")
|
||||
compare()
|
||||
|
||||
c64scr.print_byte_decimal(X)
|
||||
c64scr.print_byte(X)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
return
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
; check stack usage:
|
||||
c64.STROUT("unsigned byte ")
|
||||
c64scr.print_byte_decimal(X)
|
||||
c64scr.print_byte(X)
|
||||
c64.CHROUT(' ')
|
||||
|
||||
cr=v1==v2
|
||||
|
@ -39,7 +39,7 @@
|
|||
cr=v1>=v2
|
||||
cr=v1>=v2
|
||||
|
||||
c64scr.print_byte_decimal(X)
|
||||
c64scr.print_byte(X)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
; comparisons:
|
||||
|
@ -58,7 +58,7 @@
|
|||
c64.STROUT("v1=220, v2=10\n")
|
||||
compare()
|
||||
|
||||
c64scr.print_byte_decimal(X)
|
||||
c64scr.print_byte(X)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
return
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
; check stack usage:
|
||||
c64.STROUT("unsigned word ")
|
||||
c64scr.print_byte_decimal(X)
|
||||
c64scr.print_byte(X)
|
||||
c64.CHROUT(' ')
|
||||
|
||||
cr=v1==v2
|
||||
|
@ -39,7 +39,7 @@
|
|||
cr=v1>=v2
|
||||
cr=v1>=v2
|
||||
|
||||
c64scr.print_byte_decimal(X)
|
||||
c64scr.print_byte(X)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
; comparisons:
|
||||
|
@ -88,7 +88,7 @@
|
|||
c64.STROUT("v1 = v2 = aa\n")
|
||||
compare()
|
||||
|
||||
c64scr.print_byte_decimal(X)
|
||||
c64scr.print_byte(X)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
return
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
; check stack usage:
|
||||
c64.STROUT("signed word ")
|
||||
c64scr.print_byte_decimal(X)
|
||||
c64scr.print_byte(X)
|
||||
c64.CHROUT(' ')
|
||||
|
||||
cr=v1==v2
|
||||
|
@ -40,7 +40,7 @@
|
|||
cr=v1>=v2
|
||||
cr=v1>=v2
|
||||
|
||||
c64scr.print_byte_decimal(X)
|
||||
c64scr.print_byte(X)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
; comparisons:
|
||||
|
@ -125,7 +125,7 @@
|
|||
c64.STROUT("v1 = v2 = aa\n")
|
||||
compare()
|
||||
|
||||
c64scr.print_byte_decimal(X)
|
||||
c64scr.print_byte(X)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
return
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
ubyte v1
|
||||
ubyte v2
|
||||
|
||||
c64scr.print_byte_decimal(X)
|
||||
c64scr.print_byte(X)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
v1 = 100
|
||||
|
@ -110,7 +110,7 @@
|
|||
else
|
||||
c64.STROUT("error in 22>=22!\n")
|
||||
|
||||
c64scr.print_byte_decimal(X)
|
||||
c64scr.print_byte(X)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
word v1
|
||||
word v2
|
||||
|
||||
c64scr.print_byte_decimal(X)
|
||||
c64scr.print_byte(X)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
v1 = 100
|
||||
|
@ -110,7 +110,7 @@
|
|||
else
|
||||
c64.STROUT("error in -222>=-222!\n")
|
||||
|
||||
c64scr.print_byte_decimal(X)
|
||||
c64scr.print_byte(X)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
ask_guess:
|
||||
c64.STROUT("\nYou have ")
|
||||
c64scr.print_ubyte_decimal(attempts_left)
|
||||
c64scr.print_ubyte(attempts_left)
|
||||
c64.STROUT(" guess")
|
||||
if(attempts_left>1)
|
||||
c64.STROUT("es")
|
||||
|
@ -66,7 +66,7 @@ ask_guess:
|
|||
|
||||
; game over.
|
||||
c64.STROUT("\nToo bad! It was: ")
|
||||
c64scr.print_ubyte_decimal(secretnumber)
|
||||
c64scr.print_ubyte(secretnumber)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
goodbye:
|
||||
|
|
|
@ -22,11 +22,11 @@
|
|||
for ubyte attempts_left in 10 to 1 step -1 {
|
||||
|
||||
; stackptr debugging
|
||||
; c64scr.print_byte_decimal(X)
|
||||
; c64scr.print_byte(X)
|
||||
; c64.CHROUT('\n')
|
||||
|
||||
c64scr.print_string("\nYou have ")
|
||||
c64scr.print_ubyte_decimal(attempts_left)
|
||||
c64scr.print_ubyte(attempts_left)
|
||||
c64scr.print_string(" guess")
|
||||
if attempts_left>1
|
||||
c64scr.print_string("es")
|
||||
|
@ -36,15 +36,15 @@
|
|||
|
||||
; debug info
|
||||
; c64scr.print_string(" > attempts left=")
|
||||
; c64scr.print_byte_decimal(attempts_left)
|
||||
; c64scr.print_byte(attempts_left)
|
||||
; c64scr.print_string("\n > secretnumber=")
|
||||
; c64scr.print_byte_decimal(secretnumber)
|
||||
; c64scr.print_byte(secretnumber)
|
||||
; c64scr.print_string("\n > input=")
|
||||
; c64scr.print_string(input)
|
||||
; c64scr.print_string("\n > guess=")
|
||||
; c64scr.print_byte_decimal(guess)
|
||||
; c64scr.print_byte(guess)
|
||||
; c64.CHROUT('\n')
|
||||
; c64scr.print_byte_decimal(X) ; stackptr debugging
|
||||
; c64scr.print_byte(X) ; stackptr debugging
|
||||
; c64.CHROUT('\n')
|
||||
|
||||
if guess==secretnumber {
|
||||
|
@ -66,7 +66,7 @@
|
|||
c64scr.print_string("\n\nYou guessed it, impressive!\n")
|
||||
else {
|
||||
c64scr.print_string("\nToo bad! My number was: ")
|
||||
c64scr.print_ubyte_decimal(secretnumber)
|
||||
c64scr.print_ubyte(secretnumber)
|
||||
c64scr.print_string(".\n")
|
||||
}
|
||||
c64scr.print_string("Thanks for playing, ")
|
||||
|
|
|
@ -3,24 +3,69 @@
|
|||
|
||||
~ main {
|
||||
|
||||
memory ubyte[40] screen = $0400
|
||||
|
||||
poke()
|
||||
sub start() {
|
||||
float t = 0.0
|
||||
while(true) {
|
||||
ubyte x = lsb(round(sin(t)*15.0))+20
|
||||
ubyte y = lsb(round(cos(t)*10.0))+12
|
||||
|
||||
; vm_gfx_text(x, y, 1, "*")
|
||||
;vm_gfx_pixel(x,y,1)
|
||||
; c64scr.print_ubyte_decimal(x)
|
||||
; c64.CHROUT(',')
|
||||
; c64scr.print_ubyte_decimal(y)
|
||||
; c64.CHROUT('\n')
|
||||
screen[x] = '*'
|
||||
t+=0.1
|
||||
}
|
||||
uword uw1
|
||||
uword uw2
|
||||
word w1
|
||||
word w2
|
||||
ubyte ub1
|
||||
ubyte ub2
|
||||
byte b1
|
||||
byte b2
|
||||
float f1
|
||||
float f2
|
||||
|
||||
ub1 = 200
|
||||
c64scr.print_ubyte(abs(ub1)) ; ok
|
||||
c64.CHROUT('\n')
|
||||
b1 = 100
|
||||
c64scr.print_byte(abs(b1)) ; ok
|
||||
c64.CHROUT('\n')
|
||||
b1 = 0
|
||||
c64scr.print_byte(abs(b1)) ;ok
|
||||
c64.CHROUT('\n')
|
||||
b1 = -100
|
||||
c64scr.print_byte(abs(b1)) ;ok
|
||||
c64.CHROUT('\n')
|
||||
|
||||
uw1 = 1000
|
||||
c64scr.print_uword(abs(uw1)) ;ok
|
||||
c64.CHROUT('\n')
|
||||
w1 = 0
|
||||
c64scr.print_word(abs(w1)) ;ok
|
||||
c64.CHROUT('\n')
|
||||
w1 = -1000
|
||||
c64scr.print_word(abs(w1)) ;ok
|
||||
c64.CHROUT('\n')
|
||||
|
||||
f1 = 11.22
|
||||
c64flt.print_float(abs(f1)) ;ok
|
||||
c64.CHROUT('\n')
|
||||
f1 = 0
|
||||
c64flt.print_float(abs(f1)) ;ok
|
||||
c64.CHROUT('\n')
|
||||
f1 = -22.33
|
||||
c64flt.print_float(abs(f1)) ;@todo FAIL
|
||||
c64.CHROUT('\n')
|
||||
|
||||
; float t = 0.0
|
||||
; ubyte color=0
|
||||
; while(true) {
|
||||
; ubyte x = lsb(round(sin(t)*17.0))+20
|
||||
; ubyte y = lsb(round(cos(t*1.3634567)*10.0))+12
|
||||
;
|
||||
; c64scr.setchrclr(x,y,color,color)
|
||||
; color++
|
||||
;; vm_gfx_text(x, y, 1, "*")
|
||||
; ;vm_gfx_pixel(x,y,1)
|
||||
;; c64scr.print_ubyte(x)
|
||||
;; c64.CHROUT(',')
|
||||
;; c64scr.print_ubyte(y)
|
||||
;; c64.CHROUT('\n')
|
||||
; ;screen[x] = '*'
|
||||
; t+=0.1
|
||||
; }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -711,6 +711,17 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
|||
}
|
||||
|
||||
}
|
||||
"abs" -> {
|
||||
// 1 argument, type determines the exact opcode to use
|
||||
val arg = args.single()
|
||||
when (arg.resultingDatatype(namespace, heap)) {
|
||||
DataType.UBYTE, DataType.UWORD -> {}
|
||||
DataType.BYTE -> prog.instr(Opcode.ABS_B)
|
||||
DataType.WORD -> prog.instr(Opcode.ABS_W)
|
||||
DataType.FLOAT -> prog.instr(Opcode.ABS_F)
|
||||
else -> throw CompilerException("wrong datatype for $funcname()")
|
||||
}
|
||||
}
|
||||
"flt" -> {
|
||||
// 1 argument, type determines the exact opcode to use
|
||||
val arg = args.single()
|
||||
|
|
|
@ -72,6 +72,9 @@ enum class Opcode {
|
|||
NEG_B,
|
||||
NEG_W,
|
||||
NEG_F,
|
||||
ABS_B,
|
||||
ABS_W,
|
||||
ABS_F,
|
||||
|
||||
// bit shifts and bitwise arithmetic
|
||||
SHL_BYTE,
|
||||
|
|
|
@ -325,6 +325,15 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) {
|
|||
}
|
||||
}
|
||||
|
||||
fun abs(): Value {
|
||||
return when(type) {
|
||||
DataType.BYTE -> Value(DataType.BYTE, abs(byteval!!.toInt()))
|
||||
DataType.WORD -> Value(DataType.WORD, abs(wordval!!))
|
||||
DataType.FLOAT -> Value(DataType.FLOAT, abs(floatval!!))
|
||||
else -> throw VmExecutionException("abs can only work on byte/word/float")
|
||||
}
|
||||
}
|
||||
|
||||
fun bitand(other: Value): Value {
|
||||
val v1 = integerValue()
|
||||
val v2 = other.integerValue()
|
||||
|
|
|
@ -409,16 +409,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
|||
Opcode.RSAVE -> {
|
||||
// save cpu status flag and all registers A, X, Y.
|
||||
// see http://6502.org/tutorials/register_preservation.html
|
||||
"""
|
||||
php
|
||||
sta ${C64Zeropage.SCRATCH_REG}
|
||||
pha
|
||||
txa
|
||||
pha
|
||||
tya
|
||||
pha
|
||||
lda ${C64Zeropage.SCRATCH_REG}
|
||||
"""
|
||||
" php | sta ${C64Zeropage.SCRATCH_REG} | pha | txa | pha | tya | pha | lda ${C64Zeropage.SCRATCH_REG}"
|
||||
}
|
||||
Opcode.RRESTORE -> {
|
||||
// restore all registers and cpu status flag
|
||||
|
@ -623,16 +614,12 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
|||
jsr prog8_lib.dec_var_f
|
||||
"""
|
||||
}
|
||||
Opcode.NEG_B -> {
|
||||
"""
|
||||
lda ${(ESTACK_LO+1).toHex()},x
|
||||
eor #255
|
||||
sec
|
||||
adc #0
|
||||
sta ${(ESTACK_LO+1).toHex()},x
|
||||
"""
|
||||
}
|
||||
Opcode.NEG_B -> " jsr prog8_lib.neg_b"
|
||||
Opcode.NEG_W -> " jsr prog8_lib.neg_w"
|
||||
Opcode.NEG_F -> " jsr prog8_lib.neg_f"
|
||||
Opcode.ABS_B -> " jsr prog8_lib.abs_b"
|
||||
Opcode.ABS_W -> " jsr prog8_lib.abs_w"
|
||||
Opcode.ABS_F -> " jsr prog8_lib.abs_f"
|
||||
Opcode.INV_BYTE -> {
|
||||
"""
|
||||
lda ${(ESTACK_LO + 1).toHex()},x
|
||||
|
@ -640,38 +627,9 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
|||
sta ${(ESTACK_LO + 1).toHex()},x
|
||||
"""
|
||||
}
|
||||
Opcode.INV_WORD -> {
|
||||
"""
|
||||
lda ${(ESTACK_LO+1).toHex()},x
|
||||
eor #255
|
||||
sta ${(ESTACK_LO+1).toHex()},x
|
||||
lda ${(ESTACK_HI+1).toHex()},x
|
||||
eor #255
|
||||
sta ${(ESTACK_HI+1).toHex()},x
|
||||
"""
|
||||
}
|
||||
Opcode.NOT_BYTE -> {
|
||||
"""
|
||||
lda ${(ESTACK_LO+1).toHex()},x
|
||||
beq +
|
||||
lda #0
|
||||
beq ++
|
||||
+ lda #1
|
||||
+ sta ${(ESTACK_LO+1).toHex()},x
|
||||
"""
|
||||
}
|
||||
Opcode.NOT_WORD -> {
|
||||
"""
|
||||
lda ${(ESTACK_LO + 1).toHex()},x
|
||||
ora ${(ESTACK_HI + 1).toHex()},x
|
||||
beq +
|
||||
lda #0
|
||||
beq ++
|
||||
+ lda #1
|
||||
+ sta ${(ESTACK_LO + 1).toHex()},x | sta ${(ESTACK_HI + 1).toHex()},x
|
||||
"""
|
||||
}
|
||||
|
||||
Opcode.INV_WORD -> " jsr prog8_lib.inv_word"
|
||||
Opcode.NOT_BYTE -> " jsr prog8_lib.not_byte"
|
||||
Opcode.NOT_WORD -> " jsr prog8_lib.not_word"
|
||||
Opcode.BCS -> " bcs ${ins.callLabel}"
|
||||
Opcode.BCC -> " bcc ${ins.callLabel}"
|
||||
Opcode.BNEG -> " bmi ${ins.callLabel}"
|
||||
|
@ -744,11 +702,9 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
|||
sta ${(ESTACK_LO + 1).toHex()},x
|
||||
"""
|
||||
}
|
||||
Opcode.ADD_W -> " jsr prog8_lib.add_w" // todo inline?
|
||||
Opcode.ADD_UW -> " jsr prog8_lib.add_uw" // todo inline?
|
||||
Opcode.ADD_W, Opcode.ADD_UW -> " jsr prog8_lib.add_w"
|
||||
Opcode.ADD_F -> " jsr prog8_lib.add_f"
|
||||
Opcode.SUB_W -> " jsr prog8_lib.sub_w" // todo inline?
|
||||
Opcode.SUB_UW -> " jsr prog8_lib.sub_uw" // todo inline?
|
||||
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"
|
||||
|
|
|
@ -22,10 +22,11 @@ val BuiltinFunctions = mapOf(
|
|||
"ror2" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null),
|
||||
"lsl" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null),
|
||||
"lsr" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null),
|
||||
// these few have a return value depending on the argument list:
|
||||
// these few have a return value depending on the argument(s):
|
||||
"max" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.max()!! }}, // type depends on args
|
||||
"min" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.min()!! }}, // type depends on args
|
||||
"sum" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.sum() }}, // type depends on args
|
||||
"abs" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", NumericDatatypes)), null, ::builtinAbs), // type depends on argument
|
||||
// normal functions follow:
|
||||
"sin" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::sin) },
|
||||
"cos" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::cos) },
|
||||
|
@ -38,7 +39,6 @@ val BuiltinFunctions = mapOf(
|
|||
"rad" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::toRadians) },
|
||||
"deg" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::toDegrees) },
|
||||
"avg" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), DataType.FLOAT, ::builtinAvg),
|
||||
"abs" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT, ::builtinAbs),
|
||||
"round" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.WORD) { a, p, n, h -> oneDoubleArgOutputWord(a, p, n, h, Math::round) },
|
||||
"floor" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.WORD) { a, p, n, h -> oneDoubleArgOutputWord(a, p, n, h, Math::floor) },
|
||||
"ceil" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.WORD) { a, p, n, h -> oneDoubleArgOutputWord(a, p, n, h, Math::ceil) },
|
||||
|
@ -128,7 +128,7 @@ fun builtinFunctionReturnType(function: String, args: List<IExpression>, namespa
|
|||
// function has return values, but the return type depends on the arguments
|
||||
|
||||
return when (function) {
|
||||
"max", "min" -> {
|
||||
"max", "min", "abs" -> {
|
||||
val dt = datatypeFromListArg(args.single())
|
||||
when(dt) {
|
||||
DataType.UBYTE, DataType.BYTE, DataType.UWORD, DataType.WORD, DataType.FLOAT -> dt
|
||||
|
|
|
@ -542,6 +542,21 @@ class StackVm(private var traceOutputFile: String?) {
|
|||
checkDt(v, DataType.FLOAT)
|
||||
evalstack.push(v.neg())
|
||||
}
|
||||
Opcode.ABS_B -> {
|
||||
val v = evalstack.pop()
|
||||
checkDt(v, DataType.BYTE)
|
||||
evalstack.push(v.abs())
|
||||
}
|
||||
Opcode.ABS_W -> {
|
||||
val v = evalstack.pop()
|
||||
checkDt(v, DataType.WORD)
|
||||
evalstack.push(v.abs())
|
||||
}
|
||||
Opcode.ABS_F -> {
|
||||
val v = evalstack.pop()
|
||||
checkDt(v, DataType.FLOAT)
|
||||
evalstack.push(v.abs())
|
||||
}
|
||||
Opcode.SHL_BYTE -> {
|
||||
val v = evalstack.pop()
|
||||
checkDt(v, DataType.UBYTE)
|
||||
|
|
|
@ -11,6 +11,10 @@
|
|||
|
||||
~ c64utils {
|
||||
|
||||
const uword ESTACK_LO = $ce00
|
||||
const uword ESTACK_HI = $cf00
|
||||
|
||||
|
||||
; ----- utility functions ----
|
||||
|
||||
asmsub init_system () -> clobbers(A,X,Y) -> () {
|
||||
|
@ -613,7 +617,7 @@ asmsub print_pstring (text: str_p @ AY) -> clobbers(A,X) -> (ubyte @ Y) {
|
|||
}
|
||||
|
||||
|
||||
asmsub print_ubyte_decimal0 (value: ubyte @ A) -> clobbers(A,X,Y) -> () {
|
||||
asmsub print_ubyte0 (value: ubyte @ A) -> clobbers(A,X,Y) -> () {
|
||||
; ---- print the ubyte in A in decimal form, with left padding 0s (3 positions total)
|
||||
%asm {{
|
||||
jsr c64utils.ubyte2decimal
|
||||
|
@ -628,7 +632,7 @@ asmsub print_ubyte_decimal0 (value: ubyte @ A) -> clobbers(A,X,Y) -> () {
|
|||
}
|
||||
|
||||
|
||||
asmsub print_ubyte_decimal (value: ubyte @ A) -> clobbers(A,X,Y) -> () {
|
||||
asmsub print_ubyte (value: ubyte @ A) -> clobbers(A,X,Y) -> () {
|
||||
; ---- print the ubyte in A in decimal form, without left padding 0s
|
||||
%asm {{
|
||||
jsr c64utils.ubyte2decimal
|
||||
|
@ -649,7 +653,7 @@ _print_tens txa
|
|||
}}
|
||||
}
|
||||
|
||||
asmsub print_byte_decimal (value: byte @ A) -> clobbers(A,X,Y) -> () {
|
||||
asmsub print_byte (value: byte @ A) -> clobbers(A,X,Y) -> () {
|
||||
; ---- print the byte in A in decimal form, without left padding 0s
|
||||
%asm {{
|
||||
pha
|
||||
|
@ -659,7 +663,7 @@ asmsub print_byte_decimal (value: byte @ A) -> clobbers(A,X,Y) -> () {
|
|||
jsr c64.CHROUT
|
||||
+ pla
|
||||
jsr c64utils.byte2decimal
|
||||
jmp print_ubyte_decimal._print_byte_digits
|
||||
jmp print_ubyte._print_byte_digits
|
||||
}}
|
||||
}
|
||||
|
||||
|
@ -694,7 +698,7 @@ asmsub print_uword_hex (prefix: ubyte @ Pc, value: uword @ AY) -> clobbers(A,X,
|
|||
}
|
||||
|
||||
|
||||
asmsub print_uword_decimal0 (value: uword @ AY) -> clobbers(A,X,Y) -> () {
|
||||
asmsub print_uword0 (value: uword @ 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 {{
|
||||
|
@ -713,7 +717,7 @@ asmsub print_uword_decimal0 (value: uword @ AY) -> clobbers(A,X,Y) -> () {
|
|||
}
|
||||
|
||||
|
||||
asmsub print_uword_decimal (value: uword @ AY) -> clobbers(A,X,Y) -> () {
|
||||
asmsub print_uword (value: uword @ AY) -> clobbers(A,X,Y) -> () {
|
||||
; ---- print the uword in A/Y in decimal form, without left padding 0s
|
||||
%asm {{
|
||||
jsr c64utils.uword2decimal
|
||||
|
@ -745,7 +749,7 @@ _pr_decimal
|
|||
}}
|
||||
}
|
||||
|
||||
asmsub print_word_decimal (value: word @ AY) -> clobbers(A,X,Y) -> () {
|
||||
asmsub print_word (value: word @ AY) -> clobbers(A,X,Y) -> () {
|
||||
; ---- print the (signed) word in A/Y in decimal form, without left padding 0s
|
||||
%asm {{
|
||||
cpy #0
|
||||
|
@ -762,7 +766,7 @@ asmsub print_word_decimal (value: word @ AY) -> clobbers(A,X,Y) -> () {
|
|||
adc #1
|
||||
bcc +
|
||||
iny
|
||||
+ jmp print_uword_decimal
|
||||
+ jmp print_uword
|
||||
}}
|
||||
}
|
||||
|
||||
|
@ -787,4 +791,80 @@ asmsub input_chars (buffer: uword @ AY) -> clobbers(A, X) -> (ubyte @ Y) {
|
|||
}}
|
||||
}
|
||||
|
||||
asmsub setchr (col: ubyte @Y, row: ubyte @A) -> clobbers(A) -> () {
|
||||
; ---- set the character in SCRATCH_ZPB1 on the screen matrix at the given position
|
||||
%asm {{
|
||||
sty c64.SCRATCH_ZPREG
|
||||
asl a
|
||||
tay
|
||||
lda _screenrows+1,y
|
||||
sta _mod+2
|
||||
lda _screenrows,y
|
||||
clc
|
||||
adc c64.SCRATCH_ZPREG
|
||||
sta _mod+1
|
||||
bcc +
|
||||
inc _mod+2
|
||||
+ lda c64.SCRATCH_ZPB1
|
||||
_mod sta $ffff ; modified
|
||||
rts
|
||||
|
||||
_screenrows .word $0400 + range(0, 1000, 40)
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub setclr (col: ubyte @Y, row: ubyte @A) -> clobbers(A) -> () {
|
||||
; ---- set the color in SCRATCH_ZPB1 on the screen matrix at the given position
|
||||
%asm {{
|
||||
sty c64.SCRATCH_ZPREG
|
||||
asl a
|
||||
tay
|
||||
lda _colorrows+1,y
|
||||
sta _mod+2
|
||||
lda _colorrows,y
|
||||
clc
|
||||
adc c64.SCRATCH_ZPREG
|
||||
sta _mod+1
|
||||
bcc +
|
||||
inc _mod+2
|
||||
+ lda c64.SCRATCH_ZPB1
|
||||
_mod sta $ffff ; modified
|
||||
rts
|
||||
|
||||
_colorrows .word $d800 + range(0, 1000, 40)
|
||||
}}
|
||||
}
|
||||
|
||||
|
||||
sub setchrclr (column: ubyte, row: ubyte, char: ubyte, color: ubyte) {
|
||||
; ---- set char+color at the given position on the screen
|
||||
%asm {{
|
||||
lda setchrclr_row
|
||||
asl a
|
||||
tay
|
||||
lda setchr._screenrows+1,y
|
||||
sta _charmod+2
|
||||
adc #$d4
|
||||
sta _colormod+2
|
||||
lda setchr._screenrows,y
|
||||
clc
|
||||
adc setchrclr_column
|
||||
sta _charmod+1
|
||||
sta _colormod+1
|
||||
bcc +
|
||||
inc _charmod+2
|
||||
inc _colormod+2
|
||||
+ lda setchrclr_char
|
||||
_charmod sta $ffff ; modified
|
||||
lda setchrclr_color
|
||||
_colormod sta $ffff ; modified
|
||||
inx
|
||||
inx
|
||||
inx
|
||||
inx
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
|
||||
} ; ---- end block c64scr
|
||||
|
|
|
@ -357,6 +357,26 @@ mul_f .proc
|
|||
jmp push_fac1_as_result
|
||||
.pend
|
||||
|
||||
neg_b .proc
|
||||
lda ESTACK_LO+1,x
|
||||
eor #255
|
||||
clc
|
||||
adc #1
|
||||
sta ESTACK_LO+1,x
|
||||
rts
|
||||
.pend
|
||||
|
||||
neg_w .proc
|
||||
sec
|
||||
lda #0
|
||||
sbc ESTACK_LO+1,x
|
||||
sta ESTACK_LO+1,x
|
||||
lda #0
|
||||
sbc ESTACK_HI+1,x
|
||||
sta ESTACK_HI+1,x
|
||||
rts
|
||||
.pend
|
||||
|
||||
neg_f .proc
|
||||
; -- push -flt back on stack
|
||||
jsr pop_float_fac1
|
||||
|
@ -364,24 +384,63 @@ neg_f .proc
|
|||
jsr c64.NEGOP
|
||||
jmp push_fac1_as_result
|
||||
.pend
|
||||
|
||||
|
||||
add_w .proc
|
||||
; -- push word+word
|
||||
.warn "addw check correctness"
|
||||
inx
|
||||
clc
|
||||
lda ESTACK_LO,x
|
||||
adc ESTACK_LO+1,x
|
||||
inv_word .proc
|
||||
lda ESTACK_LO+1,x
|
||||
eor #255
|
||||
sta ESTACK_LO+1,x
|
||||
lda ESTACK_HI,x
|
||||
adc ESTACK_HI+1,x
|
||||
lda ESTACK_HI+1,x
|
||||
eor #255
|
||||
sta ESTACK_HI+1,x
|
||||
rts
|
||||
.pend
|
||||
|
||||
not_byte .proc
|
||||
lda ESTACK_LO+1,x
|
||||
beq +
|
||||
lda #0
|
||||
beq ++
|
||||
+ lda #1
|
||||
+ sta ESTACK_LO+1,x
|
||||
rts
|
||||
.pend
|
||||
|
||||
add_uw .proc
|
||||
.warn "add_uw check correctness"
|
||||
not_word .proc
|
||||
lda ESTACK_LO + 1,x
|
||||
ora ESTACK_HI + 1,x
|
||||
beq +
|
||||
lda #0
|
||||
beq ++
|
||||
+ lda #1
|
||||
+ sta ESTACK_LO + 1,x
|
||||
sta ESTACK_HI + 1,x
|
||||
rts
|
||||
.pend
|
||||
|
||||
abs_b .proc
|
||||
; -- push abs(byte) on stack (as byte)
|
||||
lda ESTACK_LO+1,x
|
||||
bmi neg_b
|
||||
rts
|
||||
.pend
|
||||
|
||||
abs_w .proc
|
||||
; -- push abs(word) on stack (as word)
|
||||
lda ESTACK_HI+1,x
|
||||
bmi neg_w
|
||||
rts
|
||||
.pend
|
||||
|
||||
abs_f .proc
|
||||
; -- push abs(float) on stack (as float)
|
||||
jsr pop_float_fac1
|
||||
stx SCRATCH_ZPREGX
|
||||
jsr c64.ABS
|
||||
jmp push_fac1_as_result
|
||||
.pend
|
||||
|
||||
add_w .proc
|
||||
; -- push word+word / uword+uword
|
||||
inx
|
||||
clc
|
||||
lda ESTACK_LO,x
|
||||
|
@ -394,13 +453,16 @@ add_uw .proc
|
|||
.pend
|
||||
|
||||
sub_w .proc
|
||||
rts ; @todo inline?
|
||||
.warn "sub_w not implemented"
|
||||
.pend
|
||||
|
||||
sub_uw .proc
|
||||
rts ; @todo inline?
|
||||
.warn "sub_uw not implemented"
|
||||
; -- push word-word
|
||||
inx
|
||||
sec
|
||||
lda ESTACK_LO+1,x
|
||||
sbc ESTACK_LO,x
|
||||
sta ESTACK_LO+1,x
|
||||
lda ESTACK_HI+1,x
|
||||
sbc ESTACK_HI,x
|
||||
sta ESTACK_HI+1,x
|
||||
rts
|
||||
.pend
|
||||
|
||||
mul_b .proc
|
||||
|
@ -445,7 +507,7 @@ div_uw .proc
|
|||
|
||||
remainder_b .proc
|
||||
rts
|
||||
.warn "remainder_b not implemented"
|
||||
.warn "remainder_b via div_b?"
|
||||
.pend
|
||||
|
||||
remainder_ub .proc
|
||||
|
@ -463,12 +525,12 @@ remainder_ub .proc
|
|||
|
||||
remainder_w .proc
|
||||
rts
|
||||
.warn "remainder_w not implemented"
|
||||
.warn "remainder_w not implemented - via div_w"
|
||||
.pend
|
||||
|
||||
remainder_uw .proc
|
||||
rts
|
||||
.warn "remainder_uw not implemented"
|
||||
.warn "remainder_uw not implemented - via div_uw"
|
||||
.pend
|
||||
|
||||
equal_w .proc
|
||||
|
@ -790,11 +852,6 @@ func_cos .proc
|
|||
jmp push_fac1_as_result
|
||||
.pend
|
||||
|
||||
func_abs .proc
|
||||
rts
|
||||
.warn "abs not implemented"
|
||||
.pend
|
||||
|
||||
func_tan .proc
|
||||
; -- push tan(f) back onto stack
|
||||
jsr pop_float_fac1
|
||||
|
|
Loading…
Reference in New Issue
Block a user