mirror of
https://github.com/mattrberry/crab.git
synced 2025-01-19 10:26:44 +01:00
thumb conditional branch, fix reg rotation, thumb/arm abstraction
This commit is contained in:
parent
55589ea0b0
commit
8e6040e4c4
5 changed files with 59 additions and 49 deletions
|
@ -17,27 +17,6 @@ module ARM
|
|||
(instr >> 16 & 0x0FF0) | (instr >> 4 & 0xF)
|
||||
end
|
||||
|
||||
private def check_cond(cond : Word) : Bool
|
||||
case bits cond, 28..31
|
||||
when 0x0 then @cpsr.zero
|
||||
when 0x1 then !@cpsr.zero
|
||||
when 0x2 then @cpsr.carry
|
||||
when 0x3 then !@cpsr.carry
|
||||
when 0x4 then @cpsr.negative
|
||||
when 0x5 then !@cpsr.negative
|
||||
when 0x6 then @cpsr.overflow
|
||||
when 0x7 then !@cpsr.overflow
|
||||
when 0x8 then @cpsr.carry && !@cpsr.zero
|
||||
when 0x9 then !@cpsr.carry || @cpsr.zero
|
||||
when 0xA then @cpsr.negative == @cpsr.overflow
|
||||
when 0xB then @cpsr.negative != @cpsr.overflow
|
||||
when 0xC then !@cpsr.zero && @cpsr.negative == @cpsr.overflow
|
||||
when 0xD then @cpsr.zero || @cpsr.negative != @cpsr.overflow
|
||||
when 0xE then true
|
||||
else raise "Cond 0xF is reserved"
|
||||
end
|
||||
end
|
||||
|
||||
def fill_lut : Slice(Proc(Word, Nil))
|
||||
lut = Slice(Proc(Word, Nil)).new 4096, ->arm_unimplemented(Word)
|
||||
4096.times do |idx|
|
||||
|
@ -89,26 +68,6 @@ module ARM
|
|||
puts "Unused instruction: #{hex_str instr}"
|
||||
end
|
||||
|
||||
# Logical shift left
|
||||
def lsl(word : Word, bits : Int) : Word
|
||||
word << bits
|
||||
end
|
||||
|
||||
# Logical shift right
|
||||
def lsr(word : Word, bits : Int) : Word
|
||||
word >> bits
|
||||
end
|
||||
|
||||
# Arithmetic shift right
|
||||
def asr(word : Word, bits : Int) : Word
|
||||
word // (2 ** bits)
|
||||
end
|
||||
|
||||
# Rotate right
|
||||
def ror(word : Word, bits : Int) : Word
|
||||
word >> bits | word << (32 - bits)
|
||||
end
|
||||
|
||||
def rotate_register(instr : Word, allow_register_shifts = true) : Word
|
||||
reg = bits(instr, 0..3)
|
||||
shift_type = bits(instr, 5..6)
|
||||
|
@ -120,10 +79,10 @@ module ARM
|
|||
bits(instr, 7..11)
|
||||
end
|
||||
case shift_type
|
||||
when 0b00 then lsl(reg, shift_amount)
|
||||
when 0b01 then lsr(reg, shift_amount)
|
||||
when 0b10 then asr(reg, shift_amount)
|
||||
when 0b11 then ror(reg, shift_amount)
|
||||
when 0b00 then lsl(@r[reg], shift_amount)
|
||||
when 0b01 then lsr(@r[reg], shift_amount)
|
||||
when 0b10 then asr(@r[reg], shift_amount)
|
||||
when 0b11 then ror(@r[reg], shift_amount)
|
||||
else raise "Impossible shift type: #{hex_str shift_type}"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -61,6 +61,47 @@ class CPU
|
|||
end
|
||||
end
|
||||
|
||||
def check_cond(cond : Word) : Bool
|
||||
case bits cond, 28..31
|
||||
when 0x0 then @cpsr.zero
|
||||
when 0x1 then !@cpsr.zero
|
||||
when 0x2 then @cpsr.carry
|
||||
when 0x3 then !@cpsr.carry
|
||||
when 0x4 then @cpsr.negative
|
||||
when 0x5 then !@cpsr.negative
|
||||
when 0x6 then @cpsr.overflow
|
||||
when 0x7 then !@cpsr.overflow
|
||||
when 0x8 then @cpsr.carry && !@cpsr.zero
|
||||
when 0x9 then !@cpsr.carry || @cpsr.zero
|
||||
when 0xA then @cpsr.negative == @cpsr.overflow
|
||||
when 0xB then @cpsr.negative != @cpsr.overflow
|
||||
when 0xC then !@cpsr.zero && @cpsr.negative == @cpsr.overflow
|
||||
when 0xD then @cpsr.zero || @cpsr.negative != @cpsr.overflow
|
||||
when 0xE then true
|
||||
else raise "Cond 0xF is reserved"
|
||||
end
|
||||
end
|
||||
|
||||
# Logical shift left
|
||||
def lsl(word : Word, bits : Int) : Word
|
||||
word << bits
|
||||
end
|
||||
|
||||
# Logical shift right
|
||||
def lsr(word : Word, bits : Int) : Word
|
||||
word >> bits
|
||||
end
|
||||
|
||||
# Arithmetic shift right
|
||||
def asr(word : Word, bits : Int) : Word
|
||||
word // (2 ** bits)
|
||||
end
|
||||
|
||||
# Rotate right
|
||||
def ror(word : Word, bits : Int) : Word
|
||||
word >> bits | word << (32 - bits)
|
||||
end
|
||||
|
||||
def print_state(instr : Word) : Nil
|
||||
{% if flag? :trace %}
|
||||
@r.each do |reg|
|
||||
|
|
10
src/crab/thumb/conditional_branch.cr
Normal file
10
src/crab/thumb/conditional_branch.cr
Normal file
|
@ -0,0 +1,10 @@
|
|||
module THUMB
|
||||
def thumb_conditional_branch(instr : Word) : Nil
|
||||
cond = bits(instr, 8..11)
|
||||
offset = bits(instr, 0..8).to_i8!
|
||||
if cond
|
||||
@r[15] &+= (offset * 2)
|
||||
clear_pipeline
|
||||
end
|
||||
end
|
||||
end
|
|
@ -6,9 +6,9 @@ module THUMB
|
|||
rs = bits(instr, 3..5)
|
||||
rd = bits(instr, 0..2)
|
||||
@r[rd] = case op
|
||||
when 0b00 then @r[rs] << offset
|
||||
when 0b01 then @r[rs] >> offset
|
||||
when 0b10 then @r[rs] // (2 ** offset)
|
||||
when 0b00 then lsl(@r[rs], offset)
|
||||
when 0b01 then lsr(@r[rs], offset)
|
||||
when 0b10 then asr(@r[rs], offset)
|
||||
else raise "Invalid shifted register op: #{op}"
|
||||
end
|
||||
@cpsr.zero = @r[rd] == 0
|
||||
|
|
|
@ -13,7 +13,7 @@ module THUMB
|
|||
elsif idx & 0b11111111 == 0b11011111
|
||||
# software interrupt
|
||||
elsif idx & 0b11110000 == 0b11010000
|
||||
# conditional branch
|
||||
lut[idx] = ->thumb_conditional_branch(Word)
|
||||
elsif idx & 0b11110000 == 0b11000000
|
||||
# multiple load/store
|
||||
elsif idx & 0b11110110 == 0b10110100
|
||||
|
|
Loading…
Reference in a new issue