IR: add SEC,CLC,SEI,CLI instructions for the sys function calls.

This commit is contained in:
Irmen de Jong 2024-07-14 21:01:19 +02:00
parent 69f953fd9b
commit d5adb85e5b
7 changed files with 95 additions and 7 deletions

View File

@ -458,6 +458,28 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
// special case, these should be inlined, or even use specialized instructions. Instead of doing a normal subroutine call.
return translateStackFunctions(fcall, callTarget)
}
when(callTarget.scopedName) {
"sys.clear_carry" -> {
val chunk = mutableListOf<IRCodeChunkBase>()
addInstr(chunk, IRInstruction(Opcode.CLC), null)
return ExpressionCodeResult(chunk, IRDataType.BYTE, -1, -1)
}
"sys.set_carry" -> {
val chunk = mutableListOf<IRCodeChunkBase>()
addInstr(chunk, IRInstruction(Opcode.SEC), null)
return ExpressionCodeResult(chunk, IRDataType.BYTE, -1, -1)
}
"sys.clear_irqd" -> {
val chunk = mutableListOf<IRCodeChunkBase>()
addInstr(chunk, IRInstruction(Opcode.CLI), null)
return ExpressionCodeResult(chunk, IRDataType.BYTE, -1, -1)
}
"sys.set_irqd" -> {
val chunk = mutableListOf<IRCodeChunkBase>()
addInstr(chunk, IRInstruction(Opcode.SEI), null)
return ExpressionCodeResult(chunk, IRDataType.BYTE, -1, -1)
}
}
when (callTarget) {
is StSub -> {

View File

@ -263,6 +263,24 @@ class IRPeepholeOptimizer(private val irprog: IRProgram) {
}
}
}
if(ins.opcode== Opcode.SEI || ins.opcode== Opcode.CLI) {
if(idx < chunk.instructions.size-1) {
val insAfter = chunk.instructions[idx+1]
if(insAfter.opcode == ins.opcode) {
chunk.instructions.removeAt(idx)
changed = true
}
else if(ins.opcode== Opcode.SEI && insAfter.opcode== Opcode.CLI) {
chunk.instructions.removeAt(idx)
changed = true
}
else if(ins.opcode== Opcode.CLI && insAfter.opcode== Opcode.SEI) {
chunk.instructions.removeAt(idx)
changed = true
}
}
}
}
return changed
}

View File

@ -80,21 +80,52 @@ class TestIRPeepholeOpt: FunSpec({
instr[1].opcode shouldBe Opcode.INC
}
test("remove double sec/clc") {
test("remove double sec/clc/sei/cli") {
val irProg = makeIRProgram(listOf(
IRInstruction(Opcode.SEC),
IRInstruction(Opcode.SEC),
IRInstruction(Opcode.SEC),
IRInstruction(Opcode.CLC),
IRInstruction(Opcode.CLC),
IRInstruction(Opcode.CLC)
IRInstruction(Opcode.CLC),
IRInstruction(Opcode.SEI),
IRInstruction(Opcode.SEI),
IRInstruction(Opcode.SEI),
IRInstruction(Opcode.CLI),
IRInstruction(Opcode.CLI),
IRInstruction(Opcode.CLI),
))
irProg.chunks().single().instructions.size shouldBe 6
irProg.chunks().single().instructions.size shouldBe 12
val opt = IRPeepholeOptimizer(irProg)
opt.optimize(true, ErrorReporterForTests())
val instr = irProg.chunks().single().instructions
instr.size shouldBe 1
instr.size shouldBe 2
instr[0].opcode shouldBe Opcode.CLC
instr[1].opcode shouldBe Opcode.CLI
}
test("remove double sec/clc/sei/cli reversed") {
val irProg = makeIRProgram(listOf(
IRInstruction(Opcode.CLC),
IRInstruction(Opcode.CLC),
IRInstruction(Opcode.CLC),
IRInstruction(Opcode.SEC),
IRInstruction(Opcode.SEC),
IRInstruction(Opcode.SEC),
IRInstruction(Opcode.CLI),
IRInstruction(Opcode.CLI),
IRInstruction(Opcode.CLI),
IRInstruction(Opcode.SEI),
IRInstruction(Opcode.SEI),
IRInstruction(Opcode.SEI),
))
irProg.chunks().single().instructions.size shouldBe 12
val opt = IRPeepholeOptimizer(irProg)
opt.optimize(true, ErrorReporterForTests())
val instr = irProg.chunks().single().instructions
instr.size shouldBe 2
instr[0].opcode shouldBe Opcode.SEC
instr[1].opcode shouldBe Opcode.SEI
}
test("push followed by pop") {

View File

@ -85,6 +85,18 @@ sys {
}}
}
sub set_irqd() {
%ir {{
sei
}}
}
sub clear_irqd() {
%ir {{
cli
}}
}
sub disable_caseswitch() {
; no-op
}

View File

@ -3,9 +3,7 @@ TODO
See open issues on github.
Re-generate the skeleons doc files.
IR: add SEC and CLC instructions in place of call to sys.set_carry() and sys.clear_carry(). (check more inline sub calls that should be a single instruction?)
Re-generate the skeletons doc files.
optimize signed byte/word division by powers of 2 (and shift right?), it's now using divmod routine. (also % ?)
see inplacemodificationByteVariableWithLiteralval() and inplacemodificationSomeWordWithLiteralval()

View File

@ -241,6 +241,8 @@ MISC
clc - clear Carry status bit
sec - set Carry status bit
cli - clear interrupt disable flag
sei - set interrupt disable flag
nop - do nothing
breakpoint - trigger a breakpoint
msig [b, w] reg1, reg2 - reg1 becomes the most significant byte (or word) of the word (or int) in reg2 (.w not yet implemented; requires 32 bits regs)
@ -411,6 +413,8 @@ enum class Opcode {
CLC,
SEC,
CLI,
SEI,
PUSH,
POP,
PUSHST,
@ -771,6 +775,8 @@ val instructionFormats = mutableMapOf(
Opcode.CONCAT to InstructionFormat.from("BW,<>r1,<r2,<r3"),
Opcode.CLC to InstructionFormat.from("N"),
Opcode.SEC to InstructionFormat.from("N"),
Opcode.CLI to InstructionFormat.from("N"),
Opcode.SEI to InstructionFormat.from("N"),
Opcode.BREAKPOINT to InstructionFormat.from("N"),
)

View File

@ -310,6 +310,7 @@ class VirtualMachine(irProgram: IRProgram) {
Opcode.BREAKPOINT -> InsBREAKPOINT()
Opcode.CLC -> { statusCarry = false; nextPc() }
Opcode.SEC -> { statusCarry = true; nextPc() }
Opcode.CLI, Opcode.SEI -> throw IllegalArgumentException("VM doesn't support interrupt status bit")
Opcode.FFROMUB -> InsFFROMUB(ins)
Opcode.FFROMSB -> InsFFROMSB(ins)