mirror of
https://github.com/irmen/prog8.git
synced 2024-11-18 04:08:58 +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(
|
||||
// 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),
|
||||
"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),
|
||||
@ -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),
|
||||
)
|
||||
|
||||
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)
|
||||
"ror" -> funcRor(fcall)
|
||||
"ror2" -> funcRor2(fcall)
|
||||
"setlsb" -> funcSetLsbMsb(fcall, false)
|
||||
"setmsb" -> funcSetLsbMsb(fcall, true)
|
||||
"sort" -> funcSort(fcall)
|
||||
"reverse" -> funcReverse(fcall)
|
||||
"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)
|
||||
}
|
||||
|
||||
private fun funcSetLsbMsb(fcall: PtBuiltinFunctionCall, msb: Boolean) {
|
||||
TODO("setlsb/setmsb for $fcall")
|
||||
}
|
||||
|
||||
private fun funcSgn(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?, scope: IPtSubroutine?) {
|
||||
translateArguments(fcall, scope)
|
||||
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)
|
||||
"sort" -> funcSort(call)
|
||||
"reverse" -> funcReverse(call)
|
||||
"setlsb" -> funcSetLsbMsb(call, false)
|
||||
"setmsb" -> funcSetLsbMsb(call, true)
|
||||
"rol" -> funcRolRor(Opcode.ROXL, call)
|
||||
"ror" -> funcRolRor(Opcode.ROXR, 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)
|
||||
}
|
||||
|
||||
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 {
|
||||
val assignment = PtAssignment(target.position)
|
||||
val assignTarget = PtAssignTarget(target.position)
|
||||
|
@ -6,10 +6,10 @@ package prog8.buildversion
|
||||
const val MAVEN_GROUP = "prog8"
|
||||
const val MAVEN_NAME = "compiler"
|
||||
const val VERSION = "9.5-SNAPSHOT"
|
||||
const val GIT_REVISION = 4097
|
||||
const val GIT_SHA = "UNKNOWN"
|
||||
const val GIT_DATE = "2023-09-08T19:29:49Z"
|
||||
const val GIT_REVISION = 4101
|
||||
const val GIT_SHA = "31c132c2ebfef803ae197489fc7eaf56642501ac"
|
||||
const val GIT_DATE = "2023-09-14T21:04:23Z"
|
||||
const val GIT_BRANCH = "master"
|
||||
const val BUILD_DATE = "2023-09-12T19:47:42Z"
|
||||
const val BUILD_UNIX_TIME = 1694548062963L
|
||||
const val BUILD_DATE = "2023-09-14T21:06:25Z"
|
||||
const val BUILD_UNIX_TIME = 1694725585234L
|
||||
const val DIRTY = 1
|
||||
|
@ -1183,8 +1183,13 @@ internal class AstChecker(private val program: Program,
|
||||
|
||||
if(funcName[0] in InplaceModifyingBuiltinFunctions) {
|
||||
// in-place modification, can't be done on literals
|
||||
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)
|
||||
if(funcName[0]=="setlsb" || funcName[0]=="setmsb") {
|
||||
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).
|
||||
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)
|
||||
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.
|
||||
|
@ -1,6 +1,8 @@
|
||||
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 ....
|
||||
- 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!
|
||||
|
@ -3,20 +3,31 @@
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
uword zz = 0
|
||||
uword zz = $ea45
|
||||
txt.print_uwhex(zz, true)
|
||||
txt.nl()
|
||||
|
||||
@(&zz) = 1
|
||||
txt.print_uw(zz)
|
||||
setlsb(zz, $11)
|
||||
txt.print_uwhex(zz, true)
|
||||
txt.nl()
|
||||
@(&zz+1) = 2
|
||||
txt.print_uw(zz)
|
||||
setmsb(zz, $22)
|
||||
txt.print_uwhex(zz, true)
|
||||
txt.nl()
|
||||
ubyte bb
|
||||
bb = @(&zz)
|
||||
txt.print_ub(bb)
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
@ -189,6 +189,7 @@ expression :
|
||||
arrayindexed:
|
||||
scoped_identifier 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" />
|
||||
<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" />
|
||||
<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>
|
||||
<extensionMap>
|
||||
<mapping ext="p8" />
|
||||
|
Loading…
Reference in New Issue
Block a user