diff --git a/src/crab/arm/arm.cr b/src/crab/arm/arm.cr index 4961474..6d32bcf 100644 --- a/src/crab/arm/arm.cr +++ b/src/crab/arm/arm.cr @@ -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 diff --git a/src/crab/cpu.cr b/src/crab/cpu.cr index 6a6079f..a019369 100644 --- a/src/crab/cpu.cr +++ b/src/crab/cpu.cr @@ -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| diff --git a/src/crab/thumb/conditional_branch.cr b/src/crab/thumb/conditional_branch.cr new file mode 100644 index 0000000..685e449 --- /dev/null +++ b/src/crab/thumb/conditional_branch.cr @@ -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 diff --git a/src/crab/thumb/move_shifted_register.cr b/src/crab/thumb/move_shifted_register.cr index a4e1281..5fec274 100644 --- a/src/crab/thumb/move_shifted_register.cr +++ b/src/crab/thumb/move_shifted_register.cr @@ -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 diff --git a/src/crab/thumb/thumb.cr b/src/crab/thumb/thumb.cr index b0450c1..b7d588c 100644 --- a/src/crab/thumb/thumb.cr +++ b/src/crab/thumb/thumb.cr @@ -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