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. // special case, these should be inlined, or even use specialized instructions. Instead of doing a normal subroutine call.
return translateStackFunctions(fcall, callTarget) 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) { when (callTarget) {
is StSub -> { 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 return changed
} }

View File

@ -80,21 +80,52 @@ class TestIRPeepholeOpt: FunSpec({
instr[1].opcode shouldBe Opcode.INC instr[1].opcode shouldBe Opcode.INC
} }
test("remove double sec/clc") { test("remove double sec/clc/sei/cli") {
val irProg = makeIRProgram(listOf( val irProg = makeIRProgram(listOf(
IRInstruction(Opcode.SEC), IRInstruction(Opcode.SEC),
IRInstruction(Opcode.SEC), IRInstruction(Opcode.SEC),
IRInstruction(Opcode.SEC), IRInstruction(Opcode.SEC),
IRInstruction(Opcode.CLC), IRInstruction(Opcode.CLC),
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) val opt = IRPeepholeOptimizer(irProg)
opt.optimize(true, ErrorReporterForTests()) opt.optimize(true, ErrorReporterForTests())
val instr = irProg.chunks().single().instructions val instr = irProg.chunks().single().instructions
instr.size shouldBe 1 instr.size shouldBe 2
instr[0].opcode shouldBe Opcode.CLC 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") { 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() { sub disable_caseswitch() {
; no-op ; no-op
} }

View File

@ -3,9 +3,7 @@ TODO
See open issues on github. See open issues on github.
Re-generate the skeleons doc files. Re-generate the skeletons 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?)
optimize signed byte/word division by powers of 2 (and shift right?), it's now using divmod routine. (also % ?) optimize signed byte/word division by powers of 2 (and shift right?), it's now using divmod routine. (also % ?)
see inplacemodificationByteVariableWithLiteralval() and inplacemodificationSomeWordWithLiteralval() see inplacemodificationByteVariableWithLiteralval() and inplacemodificationSomeWordWithLiteralval()

View File

@ -241,6 +241,8 @@ MISC
clc - clear Carry status bit clc - clear Carry status bit
sec - set Carry status bit sec - set Carry status bit
cli - clear interrupt disable flag
sei - set interrupt disable flag
nop - do nothing nop - do nothing
breakpoint - trigger a breakpoint 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) 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, CLC,
SEC, SEC,
CLI,
SEI,
PUSH, PUSH,
POP, POP,
PUSHST, PUSHST,
@ -771,6 +775,8 @@ val instructionFormats = mutableMapOf(
Opcode.CONCAT to InstructionFormat.from("BW,<>r1,<r2,<r3"), Opcode.CONCAT to InstructionFormat.from("BW,<>r1,<r2,<r3"),
Opcode.CLC to InstructionFormat.from("N"), Opcode.CLC to InstructionFormat.from("N"),
Opcode.SEC 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"), Opcode.BREAKPOINT to InstructionFormat.from("N"),
) )

View File

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