mirror of
https://github.com/mattrberry/crab.git
synced 2025-01-15 03:40:56 +01:00
arm / thumb software interrupts, register banking
This commit is contained in:
parent
49f6d39e84
commit
b401524ea5
5 changed files with 66 additions and 2 deletions
|
@ -21,7 +21,7 @@ module ARM
|
|||
lut = Slice(Proc(Word, Nil)).new 4096, ->arm_unimplemented(Word)
|
||||
4096.times do |idx|
|
||||
if idx & 0b111100000000 == 0b111100000000
|
||||
# software interrupt
|
||||
lut[idx] = ->arm_software_interrupt(Word)
|
||||
elsif idx & 0b111100000001 == 0b111000000001
|
||||
# coprocessor register transfer
|
||||
elsif idx & 0b111100000001 == 0b111000000001
|
||||
|
|
10
src/crab/arm/software_interrupt.cr
Normal file
10
src/crab/arm/software_interrupt.cr
Normal file
|
@ -0,0 +1,10 @@
|
|||
module ARM
|
||||
def arm_software_interrupt(instr : Word) : Nil
|
||||
lr = @r[15] - 4
|
||||
switch_mode CPU::Mode::SVC
|
||||
@r[14] = lr
|
||||
@cpsr.irq_disable = true
|
||||
@r[15] = 0x08
|
||||
clear_pipeline
|
||||
end
|
||||
end
|
|
@ -6,6 +6,27 @@ class CPU
|
|||
include ARM
|
||||
include THUMB
|
||||
|
||||
enum Mode
|
||||
USR = 0b10000
|
||||
FIQ = 0b10001
|
||||
IRQ = 0b10010
|
||||
SVC = 0b10011
|
||||
ABT = 0b10111
|
||||
UND = 0b11011
|
||||
SYS = 0b11111
|
||||
|
||||
def bank : Int
|
||||
case self
|
||||
in Mode::USR, Mode::SYS then 0 # todo maybe some cpsr bits can't be changed in user mode?
|
||||
in Mode::FIQ then 1
|
||||
in Mode::IRQ then 2
|
||||
in Mode::SVC then 3
|
||||
in Mode::ABT then 4
|
||||
in Mode::UND then 5
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class PSR < BitField(UInt32)
|
||||
bool negative
|
||||
bool zero
|
||||
|
@ -23,6 +44,7 @@ class CPU
|
|||
@pipeline = Pipeline.new
|
||||
getter lut : Slice(Proc(Word, Nil)) { fill_lut }
|
||||
getter thumb_lut : Slice(Proc(Word, Nil)) { fill_thumb_lut }
|
||||
@reg_banks = Array(Array(Word)).new 6 { Array(Word).new 8, 0 }
|
||||
|
||||
def initialize(@gba : GBA)
|
||||
@r[0] = 0x08000000
|
||||
|
@ -32,6 +54,27 @@ class CPU
|
|||
@cpsr = PSR.new 0x6000001F
|
||||
end
|
||||
|
||||
def switch_mode(new_mode : Mode) : Nil
|
||||
old_mode = Mode.from_value @cpsr.mode
|
||||
return if new_mode == old_mode
|
||||
new_bank = new_mode.bank
|
||||
old_bank = old_mode.bank
|
||||
if new_mode == Mode::FIQ || old_mode == Mode::FIQ
|
||||
5.times do |idx|
|
||||
@reg_banks[old_bank][idx] = @r[8 + idx]
|
||||
@r[8 + idx] = @reg_banks[new_bank][idx]
|
||||
end
|
||||
end
|
||||
# store old regs
|
||||
@reg_banks[old_bank][5] = @r[13]
|
||||
@reg_banks[old_bank][6] = @r[14]
|
||||
@reg_banks[old_bank][7] = @cpsr.value
|
||||
# load new regs
|
||||
@r[13] = @reg_banks[new_bank][5]
|
||||
@r[14] = @reg_banks[new_bank][6]
|
||||
@cpsr.value = @reg_banks[new_bank][7]
|
||||
end
|
||||
|
||||
def fill_pipeline : Nil
|
||||
while @pipeline.size < 2
|
||||
if @cpsr.thumb
|
||||
|
|
11
src/crab/thumb/software_interrupt.cr
Normal file
11
src/crab/thumb/software_interrupt.cr
Normal file
|
@ -0,0 +1,11 @@
|
|||
module THUMB
|
||||
def thumb_software_interrupt(instr : Word) : Nil
|
||||
lr = @r[15] - 4
|
||||
switch_mode CPU::Mode::SVC
|
||||
@r[14] = lr
|
||||
@cpsr.irq_disable = true
|
||||
@cpsr.thumb = false
|
||||
@r[15] = 0x08
|
||||
clear_pipeline
|
||||
end
|
||||
end
|
|
@ -11,7 +11,7 @@ module THUMB
|
|||
elsif idx & 0b11111000 == 0b11100000
|
||||
lut[idx] = ->thumb_unconditional_branch(Word)
|
||||
elsif idx & 0b11111111 == 0b11011111
|
||||
# software interrupt
|
||||
lut[idx] = ->thumb_software_interrupt(Word)
|
||||
elsif idx & 0b11110000 == 0b11010000
|
||||
lut[idx] = ->thumb_conditional_branch(Word)
|
||||
elsif idx & 0b11110000 == 0b11000000
|
||||
|
|
Loading…
Reference in a new issue