mirror of
https://github.com/irmen/prog8.git
synced 2024-12-22 18:30:01 +00:00
added callfar2() builtin function that allows to set A,X,Y and Carry arguments.
This commit is contained in:
parent
b2bdfe8482
commit
eaa22a9d13
@ -128,6 +128,7 @@ val BuiltinFunctions: Map<String, FSignature> = mapOf(
|
||||
"rrestore" to FSignature(false, emptyList(), null),
|
||||
"memory" to FSignature(true, listOf(FParam("name", arrayOf(DataType.STR)), FParam("size", arrayOf(DataType.UWORD)), FParam("alignment", arrayOf(DataType.UWORD))), DataType.UWORD),
|
||||
"callfar" to FSignature(false, listOf(FParam("bank", arrayOf(DataType.UBYTE)), FParam("address", arrayOf(DataType.UWORD)), FParam("arg", arrayOf(DataType.UWORD))), DataType.UWORD),
|
||||
"callfar2" to FSignature(false, listOf(FParam("bank", arrayOf(DataType.UBYTE)), FParam("address", arrayOf(DataType.UWORD)), FParam("argA", arrayOf(DataType.UBYTE)), FParam("argX", arrayOf(DataType.UBYTE)), FParam("argY", arrayOf(DataType.UBYTE)), FParam("argC", arrayOf(DataType.BOOL))), DataType.UWORD),
|
||||
"call" to FSignature(false, listOf(FParam("address", arrayOf(DataType.UWORD))), DataType.UWORD),
|
||||
)
|
||||
|
||||
|
@ -64,6 +64,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
"rrestore" -> funcRrestore()
|
||||
"cmp" -> funcCmp(fcall)
|
||||
"callfar" -> funcCallFar(fcall, resultRegister)
|
||||
"callfar2" -> funcCallFar2(fcall, resultRegister)
|
||||
"call" -> funcCall(fcall)
|
||||
"prog8_ifelse_bittest_set" -> throw AssemblyError("prog8_ifelse_bittest_set() should have been translated as part of an ifElse statement")
|
||||
"prog8_ifelse_bittest_notset" -> throw AssemblyError("prog8_ifelse_bittest_notset() should have been translated as part of an ifElse statement")
|
||||
@ -298,8 +299,6 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
}
|
||||
|
||||
private fun funcCallFar(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?) {
|
||||
// TODO apply same optimizations here as used on call() codegen above
|
||||
|
||||
if(asmgen.options.compTarget.name != "cx16")
|
||||
throw AssemblyError("callfar only works on cx16 target at this time")
|
||||
|
||||
@ -329,6 +328,55 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
}
|
||||
}
|
||||
|
||||
private fun funcCallFar2(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?) {
|
||||
if(asmgen.options.compTarget.name != "cx16")
|
||||
throw AssemblyError("callfar2 only works on cx16 target at this time")
|
||||
|
||||
fun assignArgs() {
|
||||
fun assign(value: PtExpression, register: Char) {
|
||||
when(value) {
|
||||
is PtBool -> asmgen.out(" ld$register #${value.asInt()}")
|
||||
is PtNumber -> asmgen.out(" ld$register #${value.number.toInt()}")
|
||||
is PtIdentifier -> asmgen.out(" ld$register ${asmgen.asmVariableName(value)}")
|
||||
else -> TODO("callfar2: support non-simple expressions for arguments")
|
||||
}
|
||||
}
|
||||
assign(fcall.args[2], 'a')
|
||||
assign(fcall.args[3], 'x')
|
||||
assign(fcall.args[4], 'y')
|
||||
val carry = fcall.args[5].asConstInteger()
|
||||
if(carry!=null)
|
||||
asmgen.out(if(carry==0) " clc" else " sec")
|
||||
else
|
||||
TODO("callfar2: support non-const argument values")
|
||||
}
|
||||
|
||||
val constBank = fcall.args[0].asConstInteger()
|
||||
val constAddress = fcall.args[1].asConstInteger()
|
||||
if(constBank!=null && constAddress!=null) {
|
||||
assignArgs()
|
||||
asmgen.out("""
|
||||
jsr cx16.JSRFAR
|
||||
.word ${constAddress.toHex()}
|
||||
.byte $constBank""")
|
||||
} else {
|
||||
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.A) // bank
|
||||
asmgen.out(" sta (++)+0")
|
||||
asmgen.assignExpressionToRegister(fcall.args[1], RegisterOrPair.AY) // jump address
|
||||
asmgen.out(" sta (+)+0 | sty (+)+1")
|
||||
assignArgs()
|
||||
asmgen.out("""
|
||||
jsr cx16.JSRFAR
|
||||
+ .word 0
|
||||
+ .byte 0""")
|
||||
}
|
||||
|
||||
// note that by convention the values in A+Y registers are now the return value of the call.
|
||||
if(resultRegister!=null) {
|
||||
assignAsmGen.assignRegisterpairWord(AsmAssignTarget.fromRegisters(resultRegister, false, fcall.position, null, asmgen), RegisterOrPair.AY)
|
||||
}
|
||||
}
|
||||
|
||||
private fun funcCmp(fcall: PtBuiltinFunctionCall) {
|
||||
val arg1 = fcall.args[0]
|
||||
val arg2 = fcall.args[1]
|
||||
|
@ -17,6 +17,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
"divmod__uword" -> funcDivmod(call, IRDataType.WORD)
|
||||
"rsave", "rrestore" -> ExpressionCodeResult.EMPTY // vm doesn't have registers to save/restore
|
||||
"callfar" -> funcCallfar(call)
|
||||
"callfar2" -> funcCallfar2(call)
|
||||
"call" -> funcCall(call)
|
||||
"msb" -> funcMsb(call)
|
||||
"lsb" -> funcLsb(call)
|
||||
@ -149,6 +150,29 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
return ExpressionCodeResult(result, IRDataType.WORD, argumentwordTr.resultReg, -1)
|
||||
}
|
||||
|
||||
private fun funcCallfar2(call: PtBuiltinFunctionCall): ExpressionCodeResult {
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
addInstr(result, IRInstruction(Opcode.PREPARECALL, immediate = 3), null)
|
||||
val bankTr = exprGen.translateExpression(call.args[0])
|
||||
val addressTr = exprGen.translateExpression(call.args[1])
|
||||
val argumentA = exprGen.translateExpression(call.args[2])
|
||||
val argumentX = exprGen.translateExpression(call.args[3])
|
||||
val argumentY = exprGen.translateExpression(call.args[4])
|
||||
val argumentCarry = exprGen.translateExpression(call.args[5])
|
||||
addToResult(result, bankTr, bankTr.resultReg, -1)
|
||||
addToResult(result, addressTr, addressTr.resultReg, -1)
|
||||
addToResult(result, argumentA, argumentA.resultReg, -1)
|
||||
addToResult(result, argumentX, argumentX.resultReg, -1)
|
||||
addToResult(result, argumentY, argumentY.resultReg, -1)
|
||||
addToResult(result, argumentCarry, argumentCarry.resultReg, -1)
|
||||
result += codeGen.makeSyscall(IMSyscall.CALLFAR2, listOf(IRDataType.BYTE to bankTr.resultReg, IRDataType.WORD to addressTr.resultReg,
|
||||
IRDataType.BYTE to argumentA.resultReg,
|
||||
IRDataType.BYTE to argumentX.resultReg,
|
||||
IRDataType.BYTE to argumentY.resultReg,
|
||||
IRDataType.BYTE to argumentCarry.resultReg), IRDataType.WORD to addressTr.resultReg)
|
||||
return ExpressionCodeResult(result, IRDataType.WORD, addressTr.resultReg, -1)
|
||||
}
|
||||
|
||||
private fun funcDivmod(call: PtBuiltinFunctionCall, type: IRDataType): ExpressionCodeResult {
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
val number = call.args[0]
|
||||
|
@ -200,6 +200,10 @@ callfar (bank, address, argumentword) -> uword ; NOTE: specific to cx16 targ
|
||||
NOTE: this routine is very inefficient, so don't use it to call often. Set the bank yourself
|
||||
or even write a custom tailored trampoline routine if you need to. Or use ``call`` if you can.
|
||||
|
||||
callfar2 (bank, address, argA, argX, argY, argCarry) -> uword ; NOTE: specific to cx16 target for now
|
||||
Identical to ``callfar``, except here you can give arguments not only for AY,
|
||||
but for each of the A, X and Y registers (each an ubyte) and the Carry status bit as well (a boolean).
|
||||
|
||||
syscall (callnr), syscall1 (callnr, arg), syscall2 (callnr, arg1, arg2), syscall3 (callnr, arg1, arg2, arg3)
|
||||
Functions for doing a system call on targets that support this. Currently no actual target
|
||||
uses this though except, possibly, the experimental code generation target!
|
||||
|
@ -13,7 +13,6 @@ Future Things and Ideas
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Improve the SublimeText syntax file for prog8, you can also install this for 'bat': https://github.com/sharkdp/bat?tab=readme-ov-file#adding-new-syntaxes--language-definitions
|
||||
- callfar() should allow setting an argument in the X register as well?
|
||||
- Can we support signed % (remainder) somehow?
|
||||
- Don't add "random" rts to %asm blocks but instead give a warning about it? (but this breaks existing behavior that others already depend on... command line switch? block directive?)
|
||||
- IR: implement missing operators in AssignmentGen (array shifts etc)
|
||||
|
@ -1,19 +1,46 @@
|
||||
%import textio
|
||||
%zeropage basicsafe
|
||||
|
||||
main {
|
||||
sub foo() {
|
||||
cx16.r0++
|
||||
}
|
||||
asmsub baz() {
|
||||
%asm{{
|
||||
jsr p8s_foo
|
||||
}}
|
||||
}
|
||||
asmsub bar() {
|
||||
%asm{{
|
||||
inx
|
||||
jmp p8s_foo
|
||||
}}
|
||||
}
|
||||
sub start() {
|
||||
bar()
|
||||
routine(11,22,33)
|
||||
txt.nl()
|
||||
cx16.r0 = callfar2(0, &routine, 11, 22, 33, true)
|
||||
txt.nl()
|
||||
txt.print_uwhex(cx16.r0, true)
|
||||
txt.nl()
|
||||
cx16.r0 = callfar(0, &routine, 11*256 + 22)
|
||||
txt.nl()
|
||||
txt.print_uwhex(cx16.r0, true)
|
||||
txt.nl()
|
||||
}
|
||||
|
||||
asmsub routine(ubyte v1 @A, ubyte v2 @X, ubyte v3 @Y) -> uword @AY {
|
||||
%asm {{
|
||||
sta cx16.r8L
|
||||
stx cx16.r9L
|
||||
sty cx16.r10L
|
||||
lda #0
|
||||
rol a
|
||||
sta cx16.r11L
|
||||
|
||||
lda cx16.r8L
|
||||
jsr txt.print_ub
|
||||
lda #' '
|
||||
jsr txt.chrout
|
||||
lda cx16.r9L
|
||||
jsr txt.print_ub
|
||||
lda #' '
|
||||
jsr txt.chrout
|
||||
lda cx16.r10L
|
||||
jsr txt.print_ub
|
||||
lda #' '
|
||||
jsr txt.chrout
|
||||
lda cx16.r11L
|
||||
jsr txt.print_ub
|
||||
lda #$31
|
||||
ldy #$ea
|
||||
rts
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
@ -16,8 +16,9 @@ enum class IMSyscall(val number: Int) {
|
||||
CLAMP_WORD(0x1015),
|
||||
CLAMP_FLOAT(0x1016),
|
||||
CALLFAR(0x1017),
|
||||
MEMCOPY(0x1018),
|
||||
MEMCOPY_SMALL(0x1019),
|
||||
ARRAYCOPY_SPLITW_TO_NORMAL(0x101a),
|
||||
ARRAYCOPY_NORMAL_TO_SPLITW(0x101b),
|
||||
CALLFAR2(0x1018),
|
||||
MEMCOPY(0x1019),
|
||||
MEMCOPY_SMALL(0x101a),
|
||||
ARRAYCOPY_SPLITW_TO_NORMAL(0x101b),
|
||||
ARRAYCOPY_NORMAL_TO_SPLITW(0x101c),
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
<keywords keywords="&;->;@;and;as;asmsub;break;clobbers;continue;do;downto;else;false;for;goto;if;if_cc;if_cs;if_eq;if_mi;if_ne;if_neg;if_nz;if_pl;if_pos;if_vc;if_vs;if_z;in;inline;not;or;repeat;return;romsub;step;sub;to;true;unroll;until;when;while;xor;~" ignore_case="false" />
|
||||
<keywords2 keywords="%address;%asm;%asmbinary;%asminclude;%breakpoint;%encoding;%import;%ir;%launcher;%option;%output;%zeropage;%zpallowed;%zpreserved;atascii:;cp437:;default:;iso16:;iso5:;iso:;kata:;petscii:;sc:" />
|
||||
<keywords3 keywords="@nozp;@requirezp;@shared;@split;@zp;bool;byte;const;float;str;ubyte;uword;void;word" />
|
||||
<keywords4 keywords="abs;call;callfar;clamp;cmp;divmod;len;lsb;max;memory;min;mkword;msb;peek;peekf;peekw;poke;pokef;pokew;rol;rol2;ror;ror2;rrestore;rrestorex;rsave;rsavex;setlsb;setmsb;sgn;sizeof;sqrt" />
|
||||
<keywords4 keywords="abs;call;callfar;callfar2;clamp;cmp;divmod;len;lsb;max;memory;min;mkword;msb;peek;peekf;peekw;poke;pokef;pokew;rol;rol2;ror;ror2;rrestore;rrestorex;rsave;rsavex;setlsb;setmsb;sgn;sizeof;sqrt" />
|
||||
</highlighting>
|
||||
<extensionMap>
|
||||
<mapping ext="p8" />
|
||||
|
@ -27,7 +27,7 @@
|
||||
<Keywords name="Keywords1">void const
str
byte ubyte bool
word uword
float
zp shared split requirezp nozp</Keywords>
|
||||
<Keywords name="Keywords2">%address
%asm
%ir
%asmbinary
%asminclude
%breakpoint
%encoding
%import
%launcher
%option
%output
%zeropage
%zpreserved
%zpallowed</Keywords>
|
||||
<Keywords name="Keywords3">inline sub asmsub romsub
clobbers
asm
if
when else
if_cc if_cs if_eq if_mi if_neg if_nz if_pl if_pos if_vc if_vs if_z
for in step do while repeat unroll
break continue return goto</Keywords>
|
||||
<Keywords name="Keywords4">abs call callfar clamp cmp divmod len lsb lsl lsr memory mkword min max msb peek peekw peekf poke pokew pokef rsave rsavex rrestore rrestorex rnd rndw rol rol2 ror ror2 setlsb setmsb sgn sizeof sqrtw</Keywords>
|
||||
<Keywords name="Keywords4">abs call callfar callfar2 clamp cmp divmod len lsb lsl lsr memory mkword min max msb peek peekw peekf poke pokew pokef rsave rsavex rrestore rrestorex rnd rndw rol rol2 ror ror2 setlsb setmsb sgn sizeof sqrtw</Keywords>
|
||||
<Keywords name="Keywords5">true false
not and or xor
as to downto |></Keywords>
|
||||
<Keywords name="Keywords6"></Keywords>
|
||||
<Keywords name="Keywords7"></Keywords>
|
||||
|
@ -15,7 +15,7 @@ syn keyword prog8BuiltInFunc len
|
||||
" Miscellaneous functions
|
||||
syn keyword prog8BuiltInFunc cmp divmod lsb msb mkword min max peek peekw peekf poke pokew pokef rsave rsavex rrestore rrestorex
|
||||
syn keyword prog8BuiltInFunc rol rol2 ror ror2 sizeof setlsb setmsb
|
||||
syn keyword prog8BuiltInFunc memory call callfar clamp
|
||||
syn keyword prog8BuiltInFunc memory call callfar callfar2 clamp
|
||||
|
||||
|
||||
" c64/floats.p8
|
||||
|
@ -114,6 +114,7 @@ class VmProgramLoader {
|
||||
IMSyscall.CLAMP_UWORD.number -> Syscall.CLAMP_UWORD
|
||||
IMSyscall.CLAMP_FLOAT.number -> Syscall.CLAMP_FLOAT
|
||||
IMSyscall.CALLFAR.number -> throw IRParseException("vm doesn't support the callfar() syscall")
|
||||
IMSyscall.CALLFAR2.number -> throw IRParseException("vm doesn't support the callfar2() syscall")
|
||||
IMSyscall.MEMCOPY.number -> Syscall.MEMCOPY
|
||||
IMSyscall.MEMCOPY_SMALL.number -> Syscall.MEMCOPY_SMALL
|
||||
IMSyscall.ARRAYCOPY_SPLITW_TO_NORMAL.number -> Syscall.ARRAYCOPY_SPLITW_TO_NORMAL
|
||||
|
Loading…
Reference in New Issue
Block a user