mirror of
https://github.com/irmen/prog8.git
synced 2024-12-01 15:52:54 +00:00
tweak IR
This commit is contained in:
parent
7c1d5cadd7
commit
b55be093be
@ -383,10 +383,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
var resultFpReg = -1
|
var resultFpReg = -1
|
||||||
if(fcall.type==DataType.FLOAT) {
|
if(fcall.type==DataType.FLOAT) {
|
||||||
resultFpReg = codeGen.registers.nextFreeFloat()
|
resultFpReg = codeGen.registers.nextFreeFloat()
|
||||||
addInstr(result, IRInstruction(Opcode.CALLRVAL, IRDataType.FLOAT, fpReg1=resultFpReg, labelSymbol=fcall.name), null)
|
addInstr(result, IRInstruction(Opcode.CALLR, IRDataType.FLOAT, fpReg1=resultFpReg, labelSymbol=fcall.name), null)
|
||||||
} else {
|
} else {
|
||||||
resultReg = codeGen.registers.nextFree()
|
resultReg = codeGen.registers.nextFree()
|
||||||
addInstr(result, IRInstruction(Opcode.CALLRVAL, codeGen.irType(fcall.type), reg1=resultReg, labelSymbol=fcall.name), null)
|
addInstr(result, IRInstruction(Opcode.CALLR, codeGen.irType(fcall.type), reg1=resultReg, labelSymbol=fcall.name), null)
|
||||||
}
|
}
|
||||||
ExpressionCodeResult(result, codeGen.irType(fcall.type), resultReg, resultFpReg)
|
ExpressionCodeResult(result, codeGen.irType(fcall.type), resultReg, resultFpReg)
|
||||||
}
|
}
|
||||||
|
@ -1458,12 +1458,12 @@ class IRCodeGen(
|
|||||||
if(value.type==DataType.FLOAT) {
|
if(value.type==DataType.FLOAT) {
|
||||||
val tr = expressionEval.translateExpression(value)
|
val tr = expressionEval.translateExpression(value)
|
||||||
addToResult(result, tr, -1, tr.resultFpReg)
|
addToResult(result, tr, -1, tr.resultFpReg)
|
||||||
addInstr(result, IRInstruction(Opcode.RETURNREG, IRDataType.FLOAT, fpReg1 = tr.resultFpReg), null)
|
addInstr(result, IRInstruction(Opcode.RETURNR, IRDataType.FLOAT, fpReg1 = tr.resultFpReg), null)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val tr = expressionEval.translateExpression(value)
|
val tr = expressionEval.translateExpression(value)
|
||||||
addToResult(result, tr, tr.resultReg, -1)
|
addToResult(result, tr, tr.resultReg, -1)
|
||||||
addInstr(result, IRInstruction(Opcode.RETURNREG, irType(value.type) , reg1=tr.resultReg), null)
|
addInstr(result, IRInstruction(Opcode.RETURNR, irType(value.type) , reg1=tr.resultReg), null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
@ -184,7 +184,7 @@ internal class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// remove useless RETURN
|
// remove useless RETURN
|
||||||
if(idx>0 && (ins.opcode == Opcode.RETURN || ins.opcode==Opcode.RETURNREG)) {
|
if(idx>0 && (ins.opcode == Opcode.RETURN || ins.opcode==Opcode.RETURNR)) {
|
||||||
val previous = chunk.instructions[idx-1]
|
val previous = chunk.instructions[idx-1]
|
||||||
if(previous.opcode in OpcodesThatJump) {
|
if(previous.opcode in OpcodesThatJump) {
|
||||||
chunk.instructions.removeAt(idx)
|
chunk.instructions.removeAt(idx)
|
||||||
@ -204,7 +204,7 @@ internal class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
|||||||
// replace call + return --> jump
|
// replace call + return --> jump
|
||||||
if(idx>0 && ins.opcode==Opcode.RETURN) {
|
if(idx>0 && ins.opcode==Opcode.RETURN) {
|
||||||
val previous = chunk.instructions[idx-1]
|
val previous = chunk.instructions[idx-1]
|
||||||
if(previous.opcode==Opcode.CALL || previous.opcode==Opcode.CALLRVAL) {
|
if(previous.opcode==Opcode.CALL || previous.opcode==Opcode.CALLR) {
|
||||||
chunk.instructions[idx-1] = IRInstruction(Opcode.JUMP, address = previous.address, labelSymbol = previous.labelSymbol, branchTarget = previous.branchTarget)
|
chunk.instructions[idx-1] = IRInstruction(Opcode.JUMP, address = previous.address, labelSymbol = previous.labelSymbol, branchTarget = previous.branchTarget)
|
||||||
chunk.instructions.removeAt(idx)
|
chunk.instructions.removeAt(idx)
|
||||||
changed = true
|
changed = true
|
||||||
|
@ -200,7 +200,7 @@ sub str2uword(str string) -> uword {
|
|||||||
push.w r65535
|
push.w r65535
|
||||||
syscall 11
|
syscall 11
|
||||||
pop.w r0
|
pop.w r0
|
||||||
returnreg.w r0
|
returnr.w r0
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,7 +213,7 @@ sub str2word(str string) -> word {
|
|||||||
push.w r65535
|
push.w r65535
|
||||||
syscall 12
|
syscall 12
|
||||||
pop.w r0
|
pop.w r0
|
||||||
returnreg.w r0
|
returnr.w r0
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ sub pow(float value, float power) -> float {
|
|||||||
loadm.f fr0,floats.pow.value
|
loadm.f fr0,floats.pow.value
|
||||||
loadm.f fr1,floats.pow.power
|
loadm.f fr1,floats.pow.power
|
||||||
fpow.f fr0,fr1
|
fpow.f fr0,fr1
|
||||||
returnreg.f fr0
|
returnr.f fr0
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ sub fabs(float value) -> float {
|
|||||||
%ir {{
|
%ir {{
|
||||||
loadm.f fr0,floats.fabs.value
|
loadm.f fr0,floats.fabs.value
|
||||||
fabs.f fr0,fr0
|
fabs.f fr0,fr0
|
||||||
returnreg.f fr0
|
returnr.f fr0
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ sub sin(float angle) -> float {
|
|||||||
%ir {{
|
%ir {{
|
||||||
loadm.f fr0,floats.sin.angle
|
loadm.f fr0,floats.sin.angle
|
||||||
fsin.f fr0,fr0
|
fsin.f fr0,fr0
|
||||||
returnreg.f fr0
|
returnr.f fr0
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ sub cos(float angle) -> float {
|
|||||||
%ir {{
|
%ir {{
|
||||||
loadm.f fr0,floats.cos.angle
|
loadm.f fr0,floats.cos.angle
|
||||||
fcos.f fr0,fr0
|
fcos.f fr0,fr0
|
||||||
returnreg.f fr0
|
returnr.f fr0
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ sub tan(float value) -> float {
|
|||||||
%ir {{
|
%ir {{
|
||||||
loadm.f fr0,floats.tan.value
|
loadm.f fr0,floats.tan.value
|
||||||
ftan.f fr0,fr0
|
ftan.f fr0,fr0
|
||||||
returnreg.f fr0
|
returnr.f fr0
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ sub atan(float value) -> float {
|
|||||||
%ir {{
|
%ir {{
|
||||||
loadm.f fr0,floats.atan.value
|
loadm.f fr0,floats.atan.value
|
||||||
fatan.f fr0,fr0
|
fatan.f fr0,fr0
|
||||||
returnreg.f fr0
|
returnr.f fr0
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +70,7 @@ sub ln(float value) -> float {
|
|||||||
%ir {{
|
%ir {{
|
||||||
loadm.f fr0,floats.ln.value
|
loadm.f fr0,floats.ln.value
|
||||||
fln.f fr0,fr0
|
fln.f fr0,fr0
|
||||||
returnreg.f fr0
|
returnr.f fr0
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ sub log2(float value) -> float {
|
|||||||
%ir {{
|
%ir {{
|
||||||
loadm.f fr0,floats.log2.value
|
loadm.f fr0,floats.log2.value
|
||||||
flog.f fr0,fr0
|
flog.f fr0,fr0
|
||||||
returnreg.f fr0
|
returnr.f fr0
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ sub sqrt(float value) -> float {
|
|||||||
%ir {{
|
%ir {{
|
||||||
loadm.f fr0,floats.sqrt.value
|
loadm.f fr0,floats.sqrt.value
|
||||||
sqrt.f fr0,fr0
|
sqrt.f fr0,fr0
|
||||||
returnreg.f fr0
|
returnr.f fr0
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ sub round(float value) -> float {
|
|||||||
%ir {{
|
%ir {{
|
||||||
loadm.f fr0,floats.round.value
|
loadm.f fr0,floats.round.value
|
||||||
fround.f fr0,fr0
|
fround.f fr0,fr0
|
||||||
returnreg.f fr0
|
returnr.f fr0
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ sub floor(float value) -> float {
|
|||||||
%ir {{
|
%ir {{
|
||||||
loadm.f fr0,floats.floor.value
|
loadm.f fr0,floats.floor.value
|
||||||
ffloor.f fr0,fr0
|
ffloor.f fr0,fr0
|
||||||
returnreg.f fr0
|
returnr.f fr0
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +121,7 @@ sub ceil(float value) -> float {
|
|||||||
%ir {{
|
%ir {{
|
||||||
loadm.f fr0,floats.ceil.value
|
loadm.f fr0,floats.ceil.value
|
||||||
fceil.f fr0,fr0
|
fceil.f fr0,fr0
|
||||||
returnreg.f fr0
|
returnr.f fr0
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,7 +129,7 @@ sub rndf() -> float {
|
|||||||
%ir {{
|
%ir {{
|
||||||
syscall 35
|
syscall 35
|
||||||
pop.f fr0
|
pop.f fr0
|
||||||
returnreg.f fr0
|
returnr.f fr0
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ math {
|
|||||||
%ir {{
|
%ir {{
|
||||||
syscall 33
|
syscall 33
|
||||||
pop.b r0
|
pop.b r0
|
||||||
returnreg.b r0
|
returnr.b r0
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,7 +171,7 @@ math {
|
|||||||
%ir {{
|
%ir {{
|
||||||
syscall 34
|
syscall 34
|
||||||
pop.w r0
|
pop.w r0
|
||||||
returnreg.w r0
|
returnr.w r0
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ string {
|
|||||||
push.w r65535
|
push.w r65535
|
||||||
syscall 29
|
syscall 29
|
||||||
pop.b r0
|
pop.b r0
|
||||||
returnreg.b r0
|
returnr.b r0
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ sys {
|
|||||||
push.w r65535
|
push.w r65535
|
||||||
syscall 30
|
syscall 30
|
||||||
pop.b r0
|
pop.b r0
|
||||||
returnreg.b r0
|
returnr.b r0
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ sub input_chars (uword buffer) -> ubyte {
|
|||||||
push.b r65535
|
push.b r65535
|
||||||
syscall 6
|
syscall 6
|
||||||
pop.b r0
|
pop.b r0
|
||||||
returnreg.b r0
|
returnr.b r0
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,11 +3,15 @@ TODO
|
|||||||
|
|
||||||
For next minor release
|
For next minor release
|
||||||
^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
- try to optimize newexpr a bit more
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
For 9.0 major changes
|
For 9.0 major changes
|
||||||
^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
- try to reintroduce builtin functions max/maxw/min/minw that take 2 args and return the largest/smallest of them.
|
||||||
|
This is a major change because it will likely break existing code that is now using min and max as variable names.
|
||||||
- get rid of the disknumber parameter everywhere in diskio, make it a configurable variable that defaults to 8.
|
- get rid of the disknumber parameter everywhere in diskio, make it a configurable variable that defaults to 8.
|
||||||
the large majority of users will only deal with a single disk drive so why not make it easier for them.
|
the large majority of users will only deal with a single disk drive so why not make it easier for them.
|
||||||
- duplicate diskio for cx16 (get rid of cx16diskio, just copy diskio and tweak everything) + documentation
|
- duplicate diskio for cx16 (get rid of cx16diskio, just copy diskio and tweak everything) + documentation
|
||||||
@ -33,9 +37,9 @@ Future Things and Ideas
|
|||||||
^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
Compiler:
|
Compiler:
|
||||||
|
|
||||||
- ir: investigate passing parameters to function calls using fixed set of regs r60000,r60001, etc.
|
- ir: idea? (but LLVM IR simply keeps the variables, so not a good idea then?...): replace all scalar variables by an allocated register. Keep a table of the variable to register mapping (including the datatype)
|
||||||
these have to be offset somehow by the subroutine number (?) somehow to have a unique list of them per subroutine.
|
global initialization values are simply a list of LOAD instructions.
|
||||||
also only if we can optimize the subroutine to replace the parameter variables to those registers.
|
Variables replaced include all subroutine parameters! So the only variables that remain as variables are arrays and strings.
|
||||||
- ir: can we determine for the loop variable in forloops if it could be kept in a (virtual) register instead of a real variable? Need to be able to check if the variable is used by another statement beside just the for loop.
|
- ir: can we determine for the loop variable in forloops if it could be kept in a (virtual) register instead of a real variable? Need to be able to check if the variable is used by another statement beside just the for loop.
|
||||||
- ir: mechanism to determine for chunks which registers are getting input values from "outside"
|
- ir: mechanism to determine for chunks which registers are getting input values from "outside"
|
||||||
- ir: mechanism to determine for chunks which registers are passing values out? (i.e. are used again in another chunk)
|
- ir: mechanism to determine for chunks which registers are passing values out? (i.e. are used again in another chunk)
|
||||||
|
@ -17,8 +17,11 @@ Status flags: Carry, Zero, Negative. NOTE: status flags are only affected by t
|
|||||||
logical or arithmetic operations DO NOT AFFECT THE STATUS FLAGS UNLESS EXPLICITLY NOTED!
|
logical or arithmetic operations DO NOT AFFECT THE STATUS FLAGS UNLESS EXPLICITLY NOTED!
|
||||||
|
|
||||||
Instruction set is mostly a load/store architecture, there are few instructions operating on memory directly.
|
Instruction set is mostly a load/store architecture, there are few instructions operating on memory directly.
|
||||||
Most instructions have an associated data type 'b','w','f'. (omitting it defaults to 'b' - byte).
|
|
||||||
Currently NO support for 24 or 32 bits integers.
|
Value types: integers (.b=byte=8 bits, .w=word=16 bits) and float (.f=32 bits). Omitting it defaults to b.
|
||||||
|
Currently ther is NO support for 24 or 32 bits integers.
|
||||||
|
There is no distinction between signed and unsigned integers.
|
||||||
|
Instead, a different instruction is used if a distinction should be made (for example div and divs).
|
||||||
Floating point operations are just 'f' typed regular instructions, however there are a few unique fp conversion instructions.
|
Floating point operations are just 'f' typed regular instructions, however there are a few unique fp conversion instructions.
|
||||||
Instructions taking more than 1 register cannot take the same register multiple times! (to avoid confusing different datatypes)
|
Instructions taking more than 1 register cannot take the same register multiple times! (to avoid confusing different datatypes)
|
||||||
|
|
||||||
@ -50,11 +53,11 @@ CONTROL FLOW
|
|||||||
------------
|
------------
|
||||||
jump location - continue running at instruction number given by location
|
jump location - continue running at instruction number given by location
|
||||||
jumpa address - continue running at memory address (note: only used to encode a physical cpu jump to fixed address instruction)
|
jumpa address - continue running at memory address (note: only used to encode a physical cpu jump to fixed address instruction)
|
||||||
call location - save current instruction location+1, continue execution at instruction nr given by location. Expect no return value.
|
call location - save current instruction location+1, continue execution at instruction nr given by location. No return value is expected.
|
||||||
callrval reg1, location - like call but expects a return value from a returnreg instruction, and puts that in reg1
|
callr reg1, location - like call but expects the routine to return a value with a returnr instruction, it then puts that in reg1
|
||||||
syscall value - do a systemcall identified by call number, result value(s) are pushed on value stack so need to be POPped off (depends on syscall)
|
syscall value - do a systemcall identified by call number, result value(s) are pushed on value stack so need to be POPped off (depends on syscall)
|
||||||
return - restore last saved instruction location and continue at that instruction. No return value.
|
return - restore last saved instruction location and continue at that instruction. No return value.
|
||||||
returnreg reg1 - like return, but also returns a value to the caller via reg1
|
returnr reg1 - like return, but also returns the value in reg1 to the caller
|
||||||
|
|
||||||
|
|
||||||
BRANCHING and CONDITIONALS
|
BRANCHING and CONDITIONALS
|
||||||
@ -112,12 +115,12 @@ dec reg1 - reg1 = reg1-1
|
|||||||
decm address - memory at address -= 1
|
decm address - memory at address -= 1
|
||||||
neg reg1 - reg1 = sign negation of reg1
|
neg reg1 - reg1 = sign negation of reg1
|
||||||
negm address - sign negate memory at address
|
negm address - sign negate memory at address
|
||||||
addr reg1, reg2 - reg1 += reg2 (unsigned + signed)
|
addr reg1, reg2 - reg1 += reg2
|
||||||
add reg1, value - reg1 += value (unsigned + signed)
|
add reg1, value - reg1 += value
|
||||||
addm reg1, address - memory at address += reg1 (unsigned + signed)
|
addm reg1, address - memory at address += reg1
|
||||||
subr reg1, reg2 - reg1 -= reg2 (unsigned + signed)
|
subr reg1, reg2 - reg1 -= reg2
|
||||||
sub reg1, value - reg1 -= value (unsigned + signed)
|
sub reg1, value - reg1 -= value
|
||||||
subm reg1, address - memory at address -= reg1 (unsigned + signed)
|
subm reg1, address - memory at address -= reg1
|
||||||
mulr reg1, reg2 - unsigned multiply reg1 *= reg2 note: byte*byte->byte, no type extension to word!
|
mulr reg1, reg2 - unsigned multiply reg1 *= reg2 note: byte*byte->byte, no type extension to word!
|
||||||
mul reg1, value - unsigned multiply reg1 *= value note: byte*byte->byte, no type extension to word!
|
mul reg1, value - unsigned multiply reg1 *= value note: byte*byte->byte, no type extension to word!
|
||||||
mulm reg1, address - memory at address *= reg2 note: byte*byte->byte, no type extension to word!
|
mulm reg1, address - memory at address *= reg2 note: byte*byte->byte, no type extension to word!
|
||||||
@ -235,10 +238,10 @@ enum class Opcode {
|
|||||||
JUMP,
|
JUMP,
|
||||||
JUMPA,
|
JUMPA,
|
||||||
CALL,
|
CALL,
|
||||||
CALLRVAL,
|
CALLR,
|
||||||
SYSCALL,
|
SYSCALL,
|
||||||
RETURN,
|
RETURN,
|
||||||
RETURNREG,
|
RETURNR,
|
||||||
|
|
||||||
BSTCC,
|
BSTCC,
|
||||||
BSTCS,
|
BSTCS,
|
||||||
@ -375,16 +378,16 @@ val OpcodesThatJump = setOf(
|
|||||||
Opcode.JUMP,
|
Opcode.JUMP,
|
||||||
Opcode.JUMPA,
|
Opcode.JUMPA,
|
||||||
Opcode.RETURN,
|
Opcode.RETURN,
|
||||||
Opcode.RETURNREG
|
Opcode.RETURNR
|
||||||
)
|
)
|
||||||
|
|
||||||
val OpcodesThatBranch = setOf(
|
val OpcodesThatBranch = setOf(
|
||||||
Opcode.JUMP,
|
Opcode.JUMP,
|
||||||
Opcode.JUMPA,
|
Opcode.JUMPA,
|
||||||
Opcode.RETURN,
|
Opcode.RETURN,
|
||||||
Opcode.RETURNREG,
|
Opcode.RETURNR,
|
||||||
Opcode.CALL,
|
Opcode.CALL,
|
||||||
Opcode.CALLRVAL,
|
Opcode.CALLR,
|
||||||
Opcode.SYSCALL,
|
Opcode.SYSCALL,
|
||||||
Opcode.BSTCC,
|
Opcode.BSTCC,
|
||||||
Opcode.BSTCS,
|
Opcode.BSTCS,
|
||||||
@ -515,10 +518,10 @@ val instructionFormats = mutableMapOf(
|
|||||||
Opcode.JUMP to InstructionFormat.from("N,<a"),
|
Opcode.JUMP to InstructionFormat.from("N,<a"),
|
||||||
Opcode.JUMPA to InstructionFormat.from("N,<a"),
|
Opcode.JUMPA to InstructionFormat.from("N,<a"),
|
||||||
Opcode.CALL to InstructionFormat.from("N,<a"),
|
Opcode.CALL to InstructionFormat.from("N,<a"),
|
||||||
Opcode.CALLRVAL to InstructionFormat.from("BW,>r1,<a | F,>fr1,<a"),
|
Opcode.CALLR to InstructionFormat.from("BW,>r1,<a | F,>fr1,<a"),
|
||||||
Opcode.SYSCALL to InstructionFormat.from("N,<i"),
|
Opcode.SYSCALL to InstructionFormat.from("N,<i"),
|
||||||
Opcode.RETURN to InstructionFormat.from("N"),
|
Opcode.RETURN to InstructionFormat.from("N"),
|
||||||
Opcode.RETURNREG to InstructionFormat.from("BW,>r1 | F,>fr1"),
|
Opcode.RETURNR to InstructionFormat.from("BW,>r1 | F,>fr1"),
|
||||||
Opcode.BSTCC to InstructionFormat.from("N,<a"),
|
Opcode.BSTCC to InstructionFormat.from("N,<a"),
|
||||||
Opcode.BSTCS to InstructionFormat.from("N,<a"),
|
Opcode.BSTCS to InstructionFormat.from("N,<a"),
|
||||||
Opcode.BSTEQ to InstructionFormat.from("N,<a"),
|
Opcode.BSTEQ to InstructionFormat.from("N,<a"),
|
||||||
|
@ -134,7 +134,7 @@ class IRProgram(val name: String,
|
|||||||
|
|
||||||
// link all jump and branching instructions to their target
|
// link all jump and branching instructions to their target
|
||||||
chunk.instructions.forEach {
|
chunk.instructions.forEach {
|
||||||
if(it.opcode in OpcodesThatBranch && it.opcode!=Opcode.RETURN && it.opcode!=Opcode.RETURNREG && it.labelSymbol!=null)
|
if(it.opcode in OpcodesThatBranch && it.opcode!=Opcode.RETURN && it.opcode!=Opcode.RETURNR && it.labelSymbol!=null)
|
||||||
it.branchTarget = labeledChunks.getValue(it.labelSymbol)
|
it.branchTarget = labeledChunks.getValue(it.labelSymbol)
|
||||||
// note: branches with an address value cannot be linked to something...
|
// note: branches with an address value cannot be linked to something...
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ internal class BitmapScreenPanel(private val drawImage: BufferedImage, val pixel
|
|||||||
|
|
||||||
override fun paint(graphics: Graphics) {
|
override fun paint(graphics: Graphics) {
|
||||||
val g2d = graphics as Graphics2D
|
val g2d = graphics as Graphics2D
|
||||||
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR)
|
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR)
|
||||||
g2d.drawImage(drawImage, 0, 0, size.width, size.height, null)
|
g2d.drawImage(drawImage, 0, 0, size.width, size.height, null)
|
||||||
Toolkit.getDefaultToolkit().sync()
|
Toolkit.getDefaultToolkit().sync()
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ Virtual machine specs:
|
|||||||
Program to execute is not stored in the system memory, it's just a separate list of instructions.
|
Program to execute is not stored in the system memory, it's just a separate list of instructions.
|
||||||
65536 virtual registers, 16 bits wide, can also be used as 8 bits. r0-r65535
|
65536 virtual registers, 16 bits wide, can also be used as 8 bits. r0-r65535
|
||||||
65536 virtual floating point registers (32 bits single precision floats) fr0-fr65535
|
65536 virtual floating point registers (32 bits single precision floats) fr0-fr65535
|
||||||
65536 bytes of memory. Thus memory pointers (addresses) are limited to 16 bits.
|
65536 bytes of memory, thus memory pointers (addresses) are limited to 16 bits.
|
||||||
Value stack, max 128 entries of 1 byte each.
|
Value stack, max 128 entries of 1 byte each.
|
||||||
Status flags: Carry, Zero, Negative. NOTE: status flags are only affected by the CMP instruction or explicit CLC/SEC!!!
|
Status flags: Carry, Zero, Negative. NOTE: status flags are only affected by the CMP instruction or explicit CLC/SEC!!!
|
||||||
logical or arithmetic operations DO NOT AFFECT THE STATUS FLAGS UNLESS EXPLICITLY NOTED!
|
logical or arithmetic operations DO NOT AFFECT THE STATUS FLAGS UNLESS EXPLICITLY NOTED!
|
||||||
@ -176,11 +176,10 @@ class VirtualMachine(irProgram: IRProgram) {
|
|||||||
Opcode.STOREZI -> InsSTOREZI(ins)
|
Opcode.STOREZI -> InsSTOREZI(ins)
|
||||||
Opcode.JUMP -> InsJUMP(ins)
|
Opcode.JUMP -> InsJUMP(ins)
|
||||||
Opcode.JUMPA -> throw IllegalArgumentException("vm program can't jump to system memory address (JUMPA)")
|
Opcode.JUMPA -> throw IllegalArgumentException("vm program can't jump to system memory address (JUMPA)")
|
||||||
Opcode.CALL -> InsCALL(ins)
|
Opcode.CALL, Opcode.CALLR -> InsCALL(ins)
|
||||||
Opcode.CALLRVAL -> InsCALLRVAL(ins)
|
|
||||||
Opcode.SYSCALL -> InsSYSCALL(ins)
|
Opcode.SYSCALL -> InsSYSCALL(ins)
|
||||||
Opcode.RETURN -> InsRETURN()
|
Opcode.RETURN -> InsRETURN()
|
||||||
Opcode.RETURNREG -> InsRETURNREG(ins)
|
Opcode.RETURNR -> InsRETURNR(ins)
|
||||||
Opcode.BSTCC -> InsBSTCC(ins)
|
Opcode.BSTCC -> InsBSTCC(ins)
|
||||||
Opcode.BSTCS -> InsBSTCS(ins)
|
Opcode.BSTCS -> InsBSTCS(ins)
|
||||||
Opcode.BSTEQ -> InsBSTEQ(ins)
|
Opcode.BSTEQ -> InsBSTEQ(ins)
|
||||||
@ -591,11 +590,6 @@ class VirtualMachine(irProgram: IRProgram) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun InsCALL(i: IRInstruction) {
|
private fun InsCALL(i: IRInstruction) {
|
||||||
callStack.push(CallSiteContext(pcChunk, pcIndex+1, null, null))
|
|
||||||
branchTo(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun InsCALLRVAL(i: IRInstruction) {
|
|
||||||
callStack.push(CallSiteContext(pcChunk, pcIndex+1, i.reg1, i.fpReg1))
|
callStack.push(CallSiteContext(pcChunk, pcIndex+1, i.reg1, i.fpReg1))
|
||||||
branchTo(i)
|
branchTo(i)
|
||||||
}
|
}
|
||||||
@ -611,7 +605,7 @@ class VirtualMachine(irProgram: IRProgram) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun InsRETURNREG(i: IRInstruction) {
|
private fun InsRETURNR(i: IRInstruction) {
|
||||||
if(callStack.isEmpty())
|
if(callStack.isEmpty())
|
||||||
exit(0)
|
exit(0)
|
||||||
else {
|
else {
|
||||||
@ -2293,11 +2287,11 @@ class VirtualMachine(irProgram: IRProgram) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun gfx_getpixel() {
|
fun gfx_getpixel() {
|
||||||
if(window==null)
|
|
||||||
registers.setUB(0, 0u)
|
|
||||||
else {
|
|
||||||
val y = valueStack.popw()
|
val y = valueStack.popw()
|
||||||
val x = valueStack.popw()
|
val x = valueStack.popw()
|
||||||
|
if(window==null)
|
||||||
|
valueStack.push(0u)
|
||||||
|
else {
|
||||||
val color = Color(window!!.getpixel(x.toInt(), y.toInt()))
|
val color = Color(window!!.getpixel(x.toInt(), y.toInt()))
|
||||||
valueStack.push(color.green.toUByte()) // gets called from a syscall, return value via stack.
|
valueStack.push(color.green.toUByte()) // gets called from a syscall, return value via stack.
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user