diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index 2a6afc840..ff2002bb5 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -1144,22 +1144,21 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, val dt = fcall.args.single().inferType(program).getOr(DataType.UNDEFINED) if(resultToStack) { when (dt) { - in ByteDatatypes -> asmgen.out(" jsr prog8_lib.abs_b_stack") - in WordDatatypes -> asmgen.out(" jsr prog8_lib.abs_w_stack") + DataType.UBYTE -> asmgen.out(" ldy #0") + DataType.BYTE -> asmgen.out(" jsr prog8_lib.abs_b_stack") + DataType.UWORD -> {} + DataType.WORD -> asmgen.out(" jsr prog8_lib.abs_w_stack") else -> throw AssemblyError("weird type") } } else { when (dt) { - in ByteDatatypes -> { - asmgen.out(" jsr prog8_lib.abs_b_into_A") - assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, scope, program, asmgen), CpuRegister.A) - } - in WordDatatypes -> { - asmgen.out(" jsr prog8_lib.abs_w_into_AY") - assignAsmGen.assignRegisterpairWord(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, false, scope, program, asmgen), RegisterOrPair.AY) - } + DataType.UBYTE -> asmgen.out(" ldy #0") + DataType.BYTE -> asmgen.out(" jsr prog8_lib.abs_b_into_AY") + DataType.UWORD -> {} + DataType.WORD -> asmgen.out(" jsr prog8_lib.abs_w_into_AY") else -> throw AssemblyError("weird type") } + assignAsmGen.assignRegisterpairWord(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, false, scope, program, asmgen), RegisterOrPair.AY) } } diff --git a/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt index da04ecd4a..1199137f1 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt @@ -15,7 +15,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen: return when(call.name) { "any" -> funcAny(call, resultRegister) "all" -> funcAll(call, resultRegister) - "abs" -> TODO("abs once we can compare plus minus") + "abs" -> funcAbs(call, resultRegister) "cmp" -> funcCmp(call) "sgn" -> funcSgn(call, resultRegister) "sin" -> TODO("floats not yet implemented") @@ -122,6 +122,40 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen: return code } + private fun funcAbs(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk { + val code = VmCodeChunk() + val sourceDt = call.args.single().type + if(sourceDt!=DataType.UWORD) { + code += exprGen.translateExpression(call.args[0], resultRegister) + when (sourceDt) { + DataType.UBYTE -> { + code += VmCodeInstruction(Opcode.EXT, VmDataType.BYTE, reg1=resultRegister) + } + DataType.BYTE -> { + val andReg = codeGen.vmRegisters.nextFree() + val notNegativeLabel = codeGen.createLabelName() + code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=andReg, value=0x80) + code += VmCodeInstruction(Opcode.AND, VmDataType.BYTE, reg1=andReg, reg2=resultRegister, reg3=andReg) + code += VmCodeInstruction(Opcode.BZ, VmDataType.BYTE, reg1=andReg, symbol = notNegativeLabel) + code += VmCodeInstruction(Opcode.NEG, VmDataType.BYTE, reg1=resultRegister) + code += VmCodeInstruction(Opcode.EXT, VmDataType.BYTE, reg1=resultRegister) + code += VmCodeLabel(notNegativeLabel) + } + DataType.WORD -> { + val andReg = codeGen.vmRegisters.nextFree() + val notNegativeLabel = codeGen.createLabelName() + code += VmCodeInstruction(Opcode.LOAD, VmDataType.WORD, reg1=andReg, value=0x8000) + code += VmCodeInstruction(Opcode.AND, VmDataType.WORD, reg1=andReg, reg2=resultRegister, reg3=andReg) + code += VmCodeInstruction(Opcode.BZ, VmDataType.WORD, reg1=andReg, symbol = notNegativeLabel) + code += VmCodeInstruction(Opcode.NEG, VmDataType.WORD, reg1=resultRegister) + code += VmCodeLabel(notNegativeLabel) + } + else -> throw AssemblyError("weird type") + } + } + return code + } + private fun funcSgn(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk { val code = VmCodeChunk() code += exprGen.translateExpression(call.args.single(), 0) diff --git a/compiler/res/prog8lib/prog8_funcs.asm b/compiler/res/prog8lib/prog8_funcs.asm index 8b132f7ce..8173a376f 100644 --- a/compiler/res/prog8lib/prog8_funcs.asm +++ b/compiler/res/prog8lib/prog8_funcs.asm @@ -85,15 +85,17 @@ func_all_w_stack .proc .pend abs_b_stack .proc - ; -- push abs(A) on stack (as byte) + ; -- push abs(A) on stack (as unsigned word) jsr abs_b_into_A sta P8ESTACK_LO,x + stz p8ESTACK_HI,x dex rts .pend -abs_b_into_A .proc - ; -- A = abs(A) +abs_b_into_AY .proc + ; -- AY = abs(A) (abs always returns unsigned word) + ldy #0 cmp #0 bmi + rts diff --git a/docs/source/todo.rst b/docs/source/todo.rst index a5ab5cd85..9d0bf5a5c 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,6 @@ TODO For next release ^^^^^^^^^^^^^^^^ -- vm: add abs(). - pipe operator: allow non-unary function calls in the pipe that specify the other argument(s) in the calls. - createAssemblyAndAssemble(): make it possible to actually get rid of the VarDecl nodes by fixing the rest of the code mentioned there. - allow "xxx" * constexpr (where constexpr is not a number literal), now gives expression error not same type diff --git a/examples/test.p8 b/examples/test.p8 index faaf0e444..93de363d5 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -7,24 +7,40 @@ main { sub start() { + ubyte ub = 234 byte v1 = -10 byte v2 = 20 + uword w3 - cmp(v1,v2) - ;sys.clear_carry() - if_cc - txt.print("cc\n") - if_cs - txt.print("cs\n") + byte v3 = abs(v1) as byte + txt.print_b(v3) + txt.spc() + v3 = abs(v2) as byte + txt.print_b(v3) + txt.spc() + w3 = abs(v1) + txt.print_uw(w3) + txt.spc() + w3 = abs(v2) + txt.print_uw(w3) + txt.spc() + w3 = abs(ub) + txt.print_uw(w3) + txt.nl() -; uword ww = 100 -; uword vv -; vv = ww+1 -; txt.print_uw(vv) -; txt.nl() -; vv = ww * 8 -; txt.print_uw(vv) -; txt.nl() + txt.print_uw(abs(v1)) + txt.spc() + txt.print_uw(abs(v2)) + txt.spc() + txt.print_uw(abs(ub)) + txt.nl() + + word sw1 = -12345 + w3 = abs(sw1) + txt.print_uw(w3) + txt.spc() + txt.print_uw(abs(sw1)) + txt.nl() ; ; a "pixelshader": ; void syscall1(8, 0) ; enable lo res creen