mirror of
https://github.com/irmen/prog8.git
synced 2024-11-25 04:31:20 +00:00
IR: add SEC,CLC,SEI,CLI instructions for the sys function calls.
This commit is contained in:
parent
69f953fd9b
commit
d5adb85e5b
@ -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 -> {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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") {
|
||||
|
@ -85,6 +85,18 @@ sys {
|
||||
}}
|
||||
}
|
||||
|
||||
sub set_irqd() {
|
||||
%ir {{
|
||||
sei
|
||||
}}
|
||||
}
|
||||
|
||||
sub clear_irqd() {
|
||||
%ir {{
|
||||
cli
|
||||
}}
|
||||
}
|
||||
|
||||
sub disable_caseswitch() {
|
||||
; no-op
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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"),
|
||||
)
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user