diff options
-rw-r--r-- | hdl/core/reg.py | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/hdl/core/reg.py b/hdl/core/reg.py index 8dc1281..df7e948 100644 --- a/hdl/core/reg.py +++ b/hdl/core/reg.py @@ -90,19 +90,24 @@ class Reg(Elaboratable): m.d.comb += self._inc_ip.eq(1) with m.If(self.int_sig): - m.d.comb += self._inc_ip.eq(0) - m.d.sync += self.ip.eq(self.rd) + m.d.comb += self._inc_ip.eq(0) # do not increment instruction pointer on interrupt + + m.d.sync += self.ip.eq(self.rd) # swap ip and cs0 m.d.sync += self.cs0.eq(self.ip) - m.d.sync += self.cs1.eq(self.sp) - m.d.sync += self.cs2.eq(self.flg) + + m.d.sync += self.cs1.eq(self.sp) # swap sp and cs1 + m.d.sync += self.sp.eq(self.cs1) + + m.d.sync += self.cs2.eq(self.flg) # save old flags to cs2 m.d.sync += self.flg.user_mode.eq(0) # set to system mode or iret cannot be used m.d.sync += self.flg.int.eq(0) # clear int flag, essential because another interrupt can be triggered without this - with m.Elif(self.iret): + with m.Elif(self.iret & ~self.flg.user_mode): # don't allow iret in user mode, that would be uhhh.... BAD m.d.comb += self._inc_ip.eq(0) - m.d.sync += self.ip.eq(self.cs0) + m.d.sync += self.ip.eq(self.cs0) #swap back ip and cs0 m.d.sync += self.sp.eq(self.cs1) - m.d.sync += self.flg.eq(self.cs2) + m.d.sync += self.cs1.eq(self.sp) #swap back sp and cs1 + m.d.sync += self.flg.eq(self.cs2) #restore flags from cs2 with m.Elif(self.call): m.d.comb += self._inc_ip.eq(0) @@ -121,6 +126,10 @@ class Reg(Elaboratable): with m.Case(self.ip.idx): #do not directly write to ip register pass + with m.Case(self.pda.idx): # do not write to pda register in user mode + with m.If(~self.flg.user_mode): + m.d.sync += self.pda.eq(self.rd) + with m.Case(self.flg.idx): # mask top half of register to prevent writing to flags in user mode with m.If(~self.flg.user_mode): |