mirror of
https://github.com/irmen/prog8.git
synced 2024-11-28 10:51:14 +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.
|
// 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 -> {
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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") {
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
|
@ -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"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user