thumb conditional branch, fix reg rotation, thumb/arm abstraction

This commit is contained in:
Matthew Berry 2020-09-27 17:51:17 -07:00
parent 55589ea0b0
commit 8e6040e4c4
5 changed files with 59 additions and 49 deletions

View file

@ -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

View file

@ -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|

View 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

View file

@ -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

View file

@ -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