mirror of
https://github.com/irmen/prog8.git
synced 2024-11-26 11:49:22 +00:00
adding setlsb() and setmsb() builtin functions
This commit is contained in:
parent
31c132c2eb
commit
95e4490a8a
@ -70,6 +70,8 @@ class FSignature(val pure: Boolean, // does it have side effects?
|
|||||||
|
|
||||||
val BuiltinFunctions: Map<String, FSignature> = mapOf(
|
val BuiltinFunctions: Map<String, FSignature> = mapOf(
|
||||||
// this set of function have no return value and operate in-place:
|
// this set of function have no return value and operate in-place:
|
||||||
|
"setlsb" to FSignature(false, listOf(FParam("variable", arrayOf(DataType.WORD, DataType.UWORD)), FParam("value", arrayOf(DataType.BYTE, DataType.UBYTE))), null),
|
||||||
|
"setmsb" to FSignature(false, listOf(FParam("variable", arrayOf(DataType.WORD, DataType.UWORD)), FParam("value", arrayOf(DataType.BYTE, DataType.UBYTE))), null),
|
||||||
"rol" to FSignature(false, listOf(FParam("item", arrayOf(DataType.UBYTE, DataType.UWORD))), null),
|
"rol" to FSignature(false, listOf(FParam("item", arrayOf(DataType.UBYTE, DataType.UWORD))), null),
|
||||||
"ror" to FSignature(false, listOf(FParam("item", arrayOf(DataType.UBYTE, DataType.UWORD))), null),
|
"ror" to FSignature(false, listOf(FParam("item", arrayOf(DataType.UBYTE, DataType.UWORD))), null),
|
||||||
"rol2" to FSignature(false, listOf(FParam("item", arrayOf(DataType.UBYTE, DataType.UWORD))), null),
|
"rol2" to FSignature(false, listOf(FParam("item", arrayOf(DataType.UBYTE, DataType.UWORD))), null),
|
||||||
@ -131,4 +133,4 @@ val BuiltinFunctions: Map<String, FSignature> = mapOf(
|
|||||||
"callfar" to FSignature(false, listOf(FParam("bank", arrayOf(DataType.UBYTE)), FParam("address", arrayOf(DataType.UWORD)), FParam("arg", 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),
|
||||||
)
|
)
|
||||||
|
|
||||||
val InplaceModifyingBuiltinFunctions = setOf("rol", "ror", "rol2", "ror2", "sort", "reverse")
|
val InplaceModifyingBuiltinFunctions = setOf("setlsb", "setmsb", "rol", "ror", "rol2", "ror2", "sort", "reverse")
|
||||||
|
@ -41,6 +41,8 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
|||||||
"rol2" -> funcRol2(fcall)
|
"rol2" -> funcRol2(fcall)
|
||||||
"ror" -> funcRor(fcall)
|
"ror" -> funcRor(fcall)
|
||||||
"ror2" -> funcRor2(fcall)
|
"ror2" -> funcRor2(fcall)
|
||||||
|
"setlsb" -> funcSetLsbMsb(fcall, false)
|
||||||
|
"setmsb" -> funcSetLsbMsb(fcall, true)
|
||||||
"sort" -> funcSort(fcall)
|
"sort" -> funcSort(fcall)
|
||||||
"reverse" -> funcReverse(fcall)
|
"reverse" -> funcReverse(fcall)
|
||||||
"memory" -> funcMemory(fcall, discardResult, resultRegister)
|
"memory" -> funcMemory(fcall, discardResult, resultRegister)
|
||||||
@ -609,6 +611,10 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
|||||||
asmgen.assignExpressionToVariable(indexer.index, "prog8_lib.${operation}_array_u${dt}._arg_index", DataType.UBYTE)
|
asmgen.assignExpressionToVariable(indexer.index, "prog8_lib.${operation}_array_u${dt}._arg_index", DataType.UBYTE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun funcSetLsbMsb(fcall: PtBuiltinFunctionCall, msb: Boolean) {
|
||||||
|
TODO("setlsb/setmsb for $fcall")
|
||||||
|
}
|
||||||
|
|
||||||
private fun funcSgn(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?, scope: IPtSubroutine?) {
|
private fun funcSgn(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?, scope: IPtSubroutine?) {
|
||||||
translateArguments(fcall, scope)
|
translateArguments(fcall, scope)
|
||||||
val dt = fcall.args.single().type
|
val dt = fcall.args.single().type
|
||||||
|
@ -40,6 +40,8 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
|||||||
"max__byte", "max__ubyte", "max__word", "max__uword" -> funcMax(call)
|
"max__byte", "max__ubyte", "max__word", "max__uword" -> funcMax(call)
|
||||||
"sort" -> funcSort(call)
|
"sort" -> funcSort(call)
|
||||||
"reverse" -> funcReverse(call)
|
"reverse" -> funcReverse(call)
|
||||||
|
"setlsb" -> funcSetLsbMsb(call, false)
|
||||||
|
"setmsb" -> funcSetLsbMsb(call, true)
|
||||||
"rol" -> funcRolRor(Opcode.ROXL, call)
|
"rol" -> funcRolRor(Opcode.ROXL, call)
|
||||||
"ror" -> funcRolRor(Opcode.ROXR, call)
|
"ror" -> funcRolRor(Opcode.ROXR, call)
|
||||||
"rol2" -> funcRolRor(Opcode.ROL, call)
|
"rol2" -> funcRolRor(Opcode.ROL, call)
|
||||||
@ -576,6 +578,78 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
|||||||
return ExpressionCodeResult(result, vmDt, -1, -1)
|
return ExpressionCodeResult(result, vmDt, -1, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun funcSetLsbMsb(call: PtBuiltinFunctionCall, msb: Boolean): ExpressionCodeResult {
|
||||||
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
|
val target = call.args[0]
|
||||||
|
when(target) {
|
||||||
|
is PtIdentifier -> {
|
||||||
|
val valueTr = exprGen.translateExpression(call.args[1])
|
||||||
|
addToResult(result, valueTr, valueTr.resultReg, -1)
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
val pointerReg = codeGen.registers.nextFree()
|
||||||
|
it += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=pointerReg, labelSymbol = target.name)
|
||||||
|
if(msb)
|
||||||
|
it += IRInstruction(Opcode.INC, IRDataType.WORD, reg1=pointerReg)
|
||||||
|
it += IRInstruction(Opcode.STOREI, IRDataType.BYTE, reg1=valueTr.resultReg, reg2=pointerReg)
|
||||||
|
// TODO use STOREZI if the value is zero
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is PtArrayIndexer -> {
|
||||||
|
require(!target.usesPointerVariable)
|
||||||
|
if(target.splitWords) {
|
||||||
|
val varName = target.variable.name + if(msb) "_msb" else "_lsb"
|
||||||
|
val valueTr = exprGen.translateExpression(call.args[1])
|
||||||
|
addToResult(result, valueTr, valueTr.resultReg, -1)
|
||||||
|
val constIndex = target.index.asConstInteger()
|
||||||
|
if(constIndex!=null) {
|
||||||
|
val offsetReg = codeGen.registers.nextFree()
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=offsetReg, immediate = constIndex)
|
||||||
|
it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1=valueTr.resultReg, reg2=offsetReg, labelSymbol = varName)
|
||||||
|
// TODO: use STOREZX if the value is zero
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val indexTr = exprGen.translateExpression(target.index)
|
||||||
|
addToResult(result, indexTr, indexTr.resultReg, -1)
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1=valueTr.resultReg, reg2=indexTr.resultReg, labelSymbol = varName)
|
||||||
|
// TODO: use STOREZX if the value is zero
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val valueTr = exprGen.translateExpression(call.args[1])
|
||||||
|
addToResult(result, valueTr, valueTr.resultReg, -1)
|
||||||
|
val eltSize = codeGen.program.memsizer.memorySize(target.type)
|
||||||
|
val constIndex = target.index.asConstInteger()
|
||||||
|
if(constIndex!=null) {
|
||||||
|
val offsetReg = codeGen.registers.nextFree()
|
||||||
|
val offset = eltSize*constIndex + if(msb) 1 else 0
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=offsetReg, immediate = offset)
|
||||||
|
it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1=valueTr.resultReg, reg2=offsetReg, labelSymbol = target.variable.name)
|
||||||
|
// TODO: use STOREZX if the value is zero
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val indexTr = exprGen.translateExpression(target.index)
|
||||||
|
addToResult(result, indexTr, indexTr.resultReg, -1)
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
if(eltSize>1)
|
||||||
|
it += codeGen.multiplyByConst(IRDataType.BYTE, indexTr.resultReg, eltSize)
|
||||||
|
if(msb)
|
||||||
|
it += IRInstruction(Opcode.INC, IRDataType.BYTE, reg1=indexTr.resultReg)
|
||||||
|
it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1=valueTr.resultReg, reg2=indexTr.resultReg, labelSymbol = target.variable.name)
|
||||||
|
// TODO: use STOREZX if the value is zero
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> throw AssemblyError("weird target for setlsb/setmsb: $target")
|
||||||
|
}
|
||||||
|
return ExpressionCodeResult(result, IRDataType.WORD, -1, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun assignRegisterTo(target: PtExpression, register: Int): IRCodeChunks {
|
private fun assignRegisterTo(target: PtExpression, register: Int): IRCodeChunks {
|
||||||
val assignment = PtAssignment(target.position)
|
val assignment = PtAssignment(target.position)
|
||||||
val assignTarget = PtAssignTarget(target.position)
|
val assignTarget = PtAssignTarget(target.position)
|
||||||
|
@ -6,10 +6,10 @@ package prog8.buildversion
|
|||||||
const val MAVEN_GROUP = "prog8"
|
const val MAVEN_GROUP = "prog8"
|
||||||
const val MAVEN_NAME = "compiler"
|
const val MAVEN_NAME = "compiler"
|
||||||
const val VERSION = "9.5-SNAPSHOT"
|
const val VERSION = "9.5-SNAPSHOT"
|
||||||
const val GIT_REVISION = 4097
|
const val GIT_REVISION = 4101
|
||||||
const val GIT_SHA = "UNKNOWN"
|
const val GIT_SHA = "31c132c2ebfef803ae197489fc7eaf56642501ac"
|
||||||
const val GIT_DATE = "2023-09-08T19:29:49Z"
|
const val GIT_DATE = "2023-09-14T21:04:23Z"
|
||||||
const val GIT_BRANCH = "master"
|
const val GIT_BRANCH = "master"
|
||||||
const val BUILD_DATE = "2023-09-12T19:47:42Z"
|
const val BUILD_DATE = "2023-09-14T21:06:25Z"
|
||||||
const val BUILD_UNIX_TIME = 1694548062963L
|
const val BUILD_UNIX_TIME = 1694725585234L
|
||||||
const val DIRTY = 1
|
const val DIRTY = 1
|
||||||
|
@ -1183,8 +1183,13 @@ internal class AstChecker(private val program: Program,
|
|||||||
|
|
||||||
if(funcName[0] in InplaceModifyingBuiltinFunctions) {
|
if(funcName[0] in InplaceModifyingBuiltinFunctions) {
|
||||||
// in-place modification, can't be done on literals
|
// in-place modification, can't be done on literals
|
||||||
if(functionCallStatement.args.any { it !is IdentifierReference && it !is ArrayIndexedExpression && it !is DirectMemoryRead }) {
|
if(funcName[0]=="setlsb" || funcName[0]=="setmsb") {
|
||||||
errors.err("invalid argument to a in-place modifying function", functionCallStatement.args.first().position)
|
val firstArg = functionCallStatement.args[0]
|
||||||
|
if(firstArg !is IdentifierReference && firstArg !is ArrayIndexedExpression)
|
||||||
|
errors.err("invalid argument to a in-place modifying function", functionCallStatement.args.first().position)
|
||||||
|
} else {
|
||||||
|
if(functionCallStatement.args.any { it !is IdentifierReference && it !is ArrayIndexedExpression && it !is DirectMemoryRead })
|
||||||
|
errors.err("invalid argument to a in-place modifying function", functionCallStatement.args.first().position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -909,6 +909,12 @@ ror2 (x)
|
|||||||
Modifies in-place, doesn't return a value (so can't be used in an expression).
|
Modifies in-place, doesn't return a value (so can't be used in an expression).
|
||||||
You can ror a memory location directly by using the direct memory access syntax, so like ``ror2(@($5000))``
|
You can ror a memory location directly by using the direct memory access syntax, so like ``ror2(@($5000))``
|
||||||
|
|
||||||
|
setlsb (x, value)
|
||||||
|
Sets the least significant byte of word variable x to a new value. Leaves the MSB untouched.
|
||||||
|
|
||||||
|
setmsb (x, value)
|
||||||
|
Sets the most significant byte of word variable x to a new value. Leaves the LSB untouched.
|
||||||
|
|
||||||
sizeof (name)
|
sizeof (name)
|
||||||
Number of bytes that the object 'name' occupies in memory. This is a constant determined by the data type of
|
Number of bytes that the object 'name' occupies in memory. This is a constant determined by the data type of
|
||||||
the object. For instance, for a variable of type uword, the sizeof is 2.
|
the object. For instance, for a variable of type uword, the sizeof is 2.
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
|
- allow taking address of array variable (now gives parser error)
|
||||||
|
|
||||||
- [on branch: shortcircuit] investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 ....
|
- [on branch: shortcircuit] investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 ....
|
||||||
- IR: reduce the number of branch instructions such as BEQ, BEQR, etc (gradually), replace with CMP(I) + status branch instruction
|
- IR: reduce the number of branch instructions such as BEQ, BEQR, etc (gradually), replace with CMP(I) + status branch instruction
|
||||||
- IR: reduce amount of CMP/CMPI after instructions that set the status bits correctly (LOADs? INC? etc), but only after setting the status bits is verified!
|
- IR: reduce amount of CMP/CMPI after instructions that set the status bits correctly (LOADs? INC? etc), but only after setting the status bits is verified!
|
||||||
|
@ -3,20 +3,31 @@
|
|||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
uword zz = 0
|
uword zz = $ea45
|
||||||
|
txt.print_uwhex(zz, true)
|
||||||
|
txt.nl()
|
||||||
|
|
||||||
@(&zz) = 1
|
setlsb(zz, $11)
|
||||||
txt.print_uw(zz)
|
txt.print_uwhex(zz, true)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
@(&zz+1) = 2
|
setmsb(zz, $22)
|
||||||
txt.print_uw(zz)
|
txt.print_uwhex(zz, true)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
ubyte bb
|
|
||||||
bb = @(&zz)
|
|
||||||
txt.print_ub(bb)
|
|
||||||
txt.nl()
|
txt.nl()
|
||||||
bb = @(&zz+1)
|
|
||||||
txt.print_ub(bb)
|
uword[] array = [$1234,$5678,$abcd] ; TODO also with @split
|
||||||
|
|
||||||
|
ubyte one = 1
|
||||||
|
ubyte two = 2
|
||||||
|
txt.print_uwhex(array[1], true)
|
||||||
|
txt.nl()
|
||||||
|
txt.print_uwhex(array[2], true)
|
||||||
|
txt.nl()
|
||||||
|
setlsb(array[one],$ff)
|
||||||
|
setmsb(array[two],$00)
|
||||||
|
txt.print_uwhex(array[1], true)
|
||||||
|
txt.nl()
|
||||||
|
txt.print_uwhex(array[2], true)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,6 +189,7 @@ expression :
|
|||||||
arrayindexed:
|
arrayindexed:
|
||||||
scoped_identifier arrayindex
|
scoped_identifier arrayindex
|
||||||
// TODO to allow chained array indexing: | arrayindexed arrayindex
|
// TODO to allow chained array indexing: | arrayindexed arrayindex
|
||||||
|
// TODO or even to allow array indexing on any uword address value: | expression arrayindex
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
<keywords keywords="&;->;@;and;as;asmsub;break;clobbers;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" />
|
<keywords keywords="&;->;@;and;as;asmsub;break;clobbers;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;%import;%ir;%launcher;%option;%output;%zeropage;%zpreserved;iso:;petscii:;sc:" />
|
<keywords2 keywords="%address;%asm;%asmbinary;%asminclude;%breakpoint;%import;%ir;%launcher;%option;%output;%zeropage;%zpreserved;iso:;petscii:;sc:" />
|
||||||
<keywords3 keywords="@requirezp;@shared;@split;@zp;bool;byte;const;float;str;ubyte;uword;void;word" />
|
<keywords3 keywords="@requirezp;@shared;@split;@zp;bool;byte;const;float;str;ubyte;uword;void;word" />
|
||||||
<keywords4 keywords="abs;all;any;callfar;callram;callrom;clamp;cmp;divmod;len;lsb;max;memory;min;mkword;msb;peek;peekw;poke;pokew;pop;popw;push;pushw;reverse;rol;rol2;ror;ror2;rrestore;rrestorex;rsave;rsavex;sgn;sizeof;sort;sqrt;swap;|>" />
|
<keywords4 keywords="abs;all;any;callfar;callram;callrom;clamp;cmp;divmod;len;lsb;max;memory;min;mkword;msb;peek;peekw;poke;pokew;pop;popw;push;pushw;reverse;rol;rol2;ror;ror2;rrestore;rrestorex;rsave;rsavex;setlsb;setmsb;sgn;sizeof;sort;sqrt;swap;|>" />
|
||||||
</highlighting>
|
</highlighting>
|
||||||
<extensionMap>
|
<extensionMap>
|
||||||
<mapping ext="p8" />
|
<mapping ext="p8" />
|
||||||
|
Loading…
Reference in New Issue
Block a user