From 5749cd3a2497443d520ff91f38ec699c87c21e5a Mon Sep 17 00:00:00 2001 From: Matthew Berry Date: Sat, 24 Oct 2020 16:00:12 -0700 Subject: [PATCH] abstract register writing (always align and clear pipeline on pc writes) --- src/crab/arm/block_data_transfer.cr | 8 ++---- src/crab/arm/branch.cr | 5 ++-- src/crab/arm/branch_exchange.cr | 5 ++-- src/crab/arm/data_processing.cr | 25 +++++++++--------- src/crab/arm/halfword_data_transfer_imm.cr | 12 ++++----- src/crab/arm/halfword_data_transfer_reg.cr | 12 ++++----- src/crab/arm/multiply.cr | 4 +-- src/crab/arm/multiply_long.cr | 4 +-- src/crab/arm/psr_transfer.cr | 4 +-- src/crab/arm/single_data_swap.cr | 4 +-- src/crab/arm/single_data_transfer.cr | 10 +++---- src/crab/arm/software_interrupt.cr | 5 ++-- src/crab/cpu.cr | 15 +++++++++++ src/crab/display.cr | 1 + src/crab/thumb/add_offset_to_stack_pointer.cr | 4 +-- src/crab/thumb/add_subtract.cr | 4 +-- src/crab/thumb/alu_operations.cr | 26 +++++++++---------- src/crab/thumb/conditional_branch.cr | 3 +-- src/crab/thumb/hi_reg_branch_exchange.cr | 10 +++---- src/crab/thumb/load_address.cr | 2 +- src/crab/thumb/load_store_halfword.cr | 2 +- src/crab/thumb/load_store_immediate_offset.cr | 8 ++---- src/crab/thumb/load_store_register_offset.cr | 8 ++---- src/crab/thumb/load_store_sign_extended.cr | 8 +++--- src/crab/thumb/long_branch_link.cr | 7 +++-- src/crab/thumb/move_compare_add_subtract.cr | 6 ++--- src/crab/thumb/move_shifted_register.cr | 12 ++++----- src/crab/thumb/multiple_load_store.cr | 4 +-- src/crab/thumb/pc_relative_load.cr | 2 +- src/crab/thumb/push_pop_registers.cr | 7 +++-- src/crab/thumb/software_interrupt.cr | 5 ++-- src/crab/thumb/sp_relative_load_store.cr | 2 +- src/crab/thumb/thumb.cr | 2 +- src/crab/thumb/unconditional_branch.cr | 3 +-- 34 files changed, 116 insertions(+), 123 deletions(-) diff --git a/src/crab/arm/block_data_transfer.cr b/src/crab/arm/block_data_transfer.cr index f1b2e36..71cb007 100644 --- a/src/crab/arm/block_data_transfer.cr +++ b/src/crab/arm/block_data_transfer.cr @@ -14,8 +14,7 @@ module ARM 16.times do |idx| if bit?(list, idx) address &+= add ? 4 : -4 if pre_index - @r[idx] = @gba.bus.read_word(address) - clear_pipeline if idx == 15 + set_reg(idx, @gba.bus.read_word(address)) address &+= add ? 4 : -4 unless pre_index end end @@ -29,9 +28,6 @@ module ARM end end - if write_back - @r[rn] = address - clear_pipeline if rn == 15 # do this for all other instrs that write to r15 - end + set_reg(rn, address) if write_back end end diff --git a/src/crab/arm/branch.cr b/src/crab/arm/branch.cr index bf26d15..02d733e 100644 --- a/src/crab/arm/branch.cr +++ b/src/crab/arm/branch.cr @@ -3,8 +3,7 @@ module ARM link = bit?(instr, 24) offset = instr & 0xFFFFFF offset = (offset << 8).to_i32! >> 6 - @r[14] = @r[15] - 4 if link - @r[15] &+= offset - clear_pipeline + set_reg(14, @r[15] - 4) if link + set_reg(15, @r[15] &+ offset) end end diff --git a/src/crab/arm/branch_exchange.cr b/src/crab/arm/branch_exchange.cr index 1555078..6587fe6 100644 --- a/src/crab/arm/branch_exchange.cr +++ b/src/crab/arm/branch_exchange.cr @@ -3,10 +3,9 @@ module ARM rn = bits(instr, 0..3) if bit?(@r[rn], 0) @cpsr.thumb = true - @r[15] = @r[rn] & ~1 + set_reg(15, @r[rn]) else - @r[15] = @r[rn] & ~3 + set_reg(15, @r[rn]) end - clear_pipeline end end diff --git a/src/crab/arm/data_processing.cr b/src/crab/arm/data_processing.cr index 2e7b7ca..87a026d 100644 --- a/src/crab/arm/data_processing.cr +++ b/src/crab/arm/data_processing.cr @@ -12,28 +12,27 @@ module ARM end # todo handle carry flag on all ops case opcode - when 0x0 then res = @r[rd] = @r[rn] & operand_2 - when 0x1 then res = @r[rd] = @r[rn] ^ operand_2 - when 0x2 then res = @r[rd] = sub(@r[rn], operand_2, set_conditions) - when 0x3 then res = @r[rd] = sub(operand_2, @r[rn], set_conditions) - when 0x4 then res = @r[rd] = add(@r[rn], operand_2, set_conditions) - when 0x5 then res = @r[rd] = adc(@r[rn], operand_2, set_conditions) - when 0x6 then res = @r[rd] = sbc(@r[rn], operand_2, set_conditions) - when 0x7 then res = @r[rd] = sbc(operand_2, @r[rn], set_conditions) + when 0x0 then res = set_reg(rd, @r[rn] & operand_2) + when 0x1 then res = set_reg(rd, @r[rn] ^ operand_2) + when 0x2 then res = set_reg(rd, sub(@r[rn], operand_2, set_conditions)) + when 0x3 then res = set_reg(rd, sub(operand_2, @r[rn], set_conditions)) + when 0x4 then res = set_reg(rd, add(@r[rn], operand_2, set_conditions)) + when 0x5 then res = set_reg(rd, adc(@r[rn], operand_2, set_conditions)) + when 0x6 then res = set_reg(rd, sbc(@r[rn], operand_2, set_conditions)) + when 0x7 then res = set_reg(rd, sbc(operand_2, @r[rn], set_conditions)) when 0x8 then res = @r[rn] & operand_2 when 0x9 then res = @r[rn] ^ operand_2 when 0xA then res = sub(@r[rn], operand_2, set_conditions) when 0xB then res = add(@r[rn], operand_2, set_conditions) - when 0xC then res = @r[rd] = @r[rn] | operand_2 - when 0xD then res = @r[rd] = operand_2 - when 0xE then res = @r[rd] = @r[rn] & ~operand_2 - when 0xF then res = @r[rd] = ~operand_2 + when 0xC then res = set_reg(rd, @r[rn] | operand_2) + when 0xD then res = set_reg(rd, operand_2) + when 0xE then res = set_reg(rd, @r[rn] & ~operand_2) + when 0xF then res = set_reg(rd, ~operand_2) else raise "Unimplemented execution of data processing opcode: #{hex_str opcode}" end if set_conditions # todo this only works for logical ops, not arithmetic @cpsr.zero = res == 0 @cpsr.negative = bit?(res, 31) end - clear_pipeline if rd == 15 # todo only do this when needed (not 0xA or 0xB) end end diff --git a/src/crab/arm/halfword_data_transfer_imm.cr b/src/crab/arm/halfword_data_transfer_imm.cr index d94dead..b092f53 100644 --- a/src/crab/arm/halfword_data_transfer_imm.cr +++ b/src/crab/arm/halfword_data_transfer_imm.cr @@ -25,25 +25,25 @@ module ARM when 0b00 # swp, no docs on this? when 0b01 # ldrh/strh if load - @r[rd] = @gba.bus.read_half address + set_reg(rd, @gba.bus.read_half address) else @gba.bus[address] = 0xFFFF_u16 & @r[rd] end when 0b10 # ldrsb - @r[rd] = @gba.bus[address].to_i8!.to_u32 + set_reg(rd, @gba.bus[address].to_i8!.to_u32) when 0b11 # ldrsh - @r[rd] = @gba.bus.read_half(address).to_i16!.to_u32 + set_reg(rd, @gba.bus.read_half(address).to_i16!.to_u32) else raise "Invalid halfword data transfer imm op: #{sh}" end if !pre_index if add - @r[rn] &+= offset + set_reg(rn, @r[rn] &+ offset) else - @r[rn] &-= offset + set_reg(rn, @r[rn] &- offset) end elsif write_back - @r[rn] = address + set_reg(rn, address) end end end diff --git a/src/crab/arm/halfword_data_transfer_reg.cr b/src/crab/arm/halfword_data_transfer_reg.cr index ce39d8b..9bd1cb8 100644 --- a/src/crab/arm/halfword_data_transfer_reg.cr +++ b/src/crab/arm/halfword_data_transfer_reg.cr @@ -24,25 +24,25 @@ module ARM when 0b00 # swp, no docs on this? when 0b01 # ldrh/strh if load - @r[rd] = @gba.bus.read_half address + set_reg(rd, @gba.bus.read_half address) else @gba.bus[address] = 0xFFFF_u16 & @r[rd] end when 0b10 # ldrsb - @r[rd] = @gba.bus[address].to_i8!.to_u32 + set_reg(rd, @gba.bus[address].to_i8!.to_u32) when 0b11 # ldrsh - @r[rd] = @gba.bus.read_half(address).to_i16!.to_u32 + set_reg(rd, @gba.bus.read_half(address).to_i16!.to_u32) else raise "Invalid halfword data transfer imm op: #{sh}" end if !pre_index if add - @r[rn] &+= offset + set_reg(rn, @r[rn] &+ offset) else - @r[rn] &-= offset + set_reg(rn, @r[rn] &- offset) end elsif write_back - @r[rn] = address + set_reg(rn, address) end end end diff --git a/src/crab/arm/multiply.cr b/src/crab/arm/multiply.cr index bb05179..91eef3b 100644 --- a/src/crab/arm/multiply.cr +++ b/src/crab/arm/multiply.cr @@ -7,8 +7,8 @@ module ARM rs = bits(instr, 8..11) rm = bits(instr, 0..3) - @r[rd] = @r[rm] &* @r[rs] - @r[rd] &+= @r[rn] if accumulate + set_reg(rd, @r[rm] &* @r[rs]) + set_reg(rd, @r[rd] &+ @r[rn]) if accumulate if set_conditions @cpsr.zero = @r[rd] == 0 @cpsr.negative = bit?(@r[rd], 31) diff --git a/src/crab/arm/multiply_long.cr b/src/crab/arm/multiply_long.cr index c6173e9..6a63c94 100644 --- a/src/crab/arm/multiply_long.cr +++ b/src/crab/arm/multiply_long.cr @@ -14,8 +14,8 @@ module ARM @r[rm].to_u64 &* @r[rs] end res &+= @r[rdhi].to_u64 << 32 | @r[rdlo] if accumulate - @r[rdhi] = (res >> 32).to_u32! - @r[rdlo] = res.to_u32! + set_reg(rdhi, (res >> 32).to_u32!) + set_reg(rdlo, res.to_u32!) if set_conditions @cpsr.zero = res == 0 @cpsr.negative = bit?(@r[rdhi], 31) diff --git a/src/crab/arm/psr_transfer.cr b/src/crab/arm/psr_transfer.cr index 2d874c0..e7b8179 100644 --- a/src/crab/arm/psr_transfer.cr +++ b/src/crab/arm/psr_transfer.cr @@ -27,9 +27,9 @@ module ARM else rd = bits(instr, 12..15) if spsr - @r[rd] = @spsr.value + set_reg(rd, @spsr.value) else - @r[rd] = @cpsr.value + set_reg(rd, @cpsr.value) end end end diff --git a/src/crab/arm/single_data_swap.cr b/src/crab/arm/single_data_swap.cr index 92e1654..9563708 100644 --- a/src/crab/arm/single_data_swap.cr +++ b/src/crab/arm/single_data_swap.cr @@ -7,11 +7,11 @@ module ARM if byte_quantity tmp = @gba.bus[@r[rn]] @gba.bus[@r[rn]] = @r[rm].to_u8! - @r[rd] = tmp.to_u32 + set_reg(rd, tmp.to_u32) else tmp = @gba.bus.read_word @r[rn] @gba.bus[@r[rn]] = @r[rm] - @r[rd] = tmp + set_reg(rd, tmp) end end end diff --git a/src/crab/arm/single_data_transfer.cr b/src/crab/arm/single_data_transfer.cr index 77796f8..1fc5fc3 100644 --- a/src/crab/arm/single_data_transfer.cr +++ b/src/crab/arm/single_data_transfer.cr @@ -27,9 +27,9 @@ module ARM if load if byte_quantity - @r[rd] = 0xFF_u32 & @gba.bus[address] + set_reg(rd, 0xFF_u32 & @gba.bus[address]) else - @r[rd] = @gba.bus.read_word address + set_reg(rd, @gba.bus.read_word address) end else if byte_quantity @@ -41,12 +41,12 @@ module ARM if !pre_indexing if add_offset - @r[rn] &+= offset + set_reg(rn, @r[rn] &+ offset) else - @r[rn] &-= offset + set_reg(rn, @r[rn] &- offset) end elsif write_back - @r[rn] = address + set_reg(rn, address) end end end diff --git a/src/crab/arm/software_interrupt.cr b/src/crab/arm/software_interrupt.cr index f95bebf..3179210 100644 --- a/src/crab/arm/software_interrupt.cr +++ b/src/crab/arm/software_interrupt.cr @@ -2,9 +2,8 @@ module ARM def arm_software_interrupt(instr : Word) : Nil lr = @r[15] - 4 switch_mode CPU::Mode::SVC - @r[14] = lr + set_reg(14, lr) @cpsr.irq_disable = true - @r[15] = 0x08 - clear_pipeline + set_reg(15, 0x08) end end diff --git a/src/crab/cpu.cr b/src/crab/cpu.cr index 6630495..c6eb90e 100644 --- a/src/crab/cpu.cr +++ b/src/crab/cpu.cr @@ -134,6 +134,21 @@ class CPU end end + @[AlwaysInline] + def set_reg(reg : Int, value : UInt32) : UInt32 + case reg + when 15 + if @cpsr.thumb + @r[reg] = value & ~1 + else + @r[reg] = value & ~3 + end + clear_pipeline + else @r[reg] = value + end + value + end + # Logical shift left def lsl(word : Word, bits : Int, set_conditions : Bool) : Word log "lsl - word:#{hex_str word}, bits:#{bits}" diff --git a/src/crab/display.cr b/src/crab/display.cr index ff50f83..8b58f92 100644 --- a/src/crab/display.cr +++ b/src/crab/display.cr @@ -20,6 +20,7 @@ class Display @fps = 30 @seconds : Int32 = Time.utc.second + def draw(framebuffer : Bytes) : Nil LibSDL.update_texture @texture, nil, framebuffer, WIDTH * 2 @renderer.clear diff --git a/src/crab/thumb/add_offset_to_stack_pointer.cr b/src/crab/thumb/add_offset_to_stack_pointer.cr index a5a8b72..28e39bc 100644 --- a/src/crab/thumb/add_offset_to_stack_pointer.cr +++ b/src/crab/thumb/add_offset_to_stack_pointer.cr @@ -3,9 +3,9 @@ module THUMB sign = bit?(instr, 7) offset = bits(instr, 0..6) if sign # negative - @r[13] &-= (offset << 2) + set_reg(13, @r[13] &- (offset << 2)) else # positive - @r[13] &+= (offset << 2) + set_reg(13, @r[13] &+ (offset << 2)) end end end diff --git a/src/crab/thumb/add_subtract.cr b/src/crab/thumb/add_subtract.cr index 2a14fab..1b01cf7 100644 --- a/src/crab/thumb/add_subtract.cr +++ b/src/crab/thumb/add_subtract.cr @@ -11,9 +11,9 @@ module THUMB @r[imm] end if sub - @r[rd] = sub(@r[rs], operand, true) + set_reg(rd, sub(@r[rs], operand, true)) else - @r[rd] = add(@r[rs], operand, true) + set_reg(rd, add(@r[rs], operand, true)) end # todo handle carry flag on all ops @cpsr.zero = @r[rd] == 0 diff --git a/src/crab/thumb/alu_operations.cr b/src/crab/thumb/alu_operations.cr index 1c9c842..0da2356 100644 --- a/src/crab/thumb/alu_operations.cr +++ b/src/crab/thumb/alu_operations.cr @@ -5,22 +5,22 @@ module THUMB rd = bits(instr, 0..2) # todo handle flags for all ops case op - when 0b0000 then res = @r[rd] = @r[rd] & @r[rs] - when 0b0001 then res = @r[rd] = @r[rd] ^ @r[rs] - when 0b0010 then res = @r[rd] = lsl(@r[rd], @r[rs], true) - when 0b0011 then res = @r[rd] = lsr(@r[rd], @r[rs], true) - when 0b0100 then res = @r[rd] = asr(@r[rd], @r[rs], true) - when 0b0101 then res = @r[rd] = adc(@r[rd], @r[rs], true) - when 0b0110 then res = @r[rd] = sbc(@r[rd], @r[rs], true) - when 0b0111 then res = @r[rd] = ror(@r[rd], @r[rs], true) + when 0b0000 then res = set_reg(rd, @r[rd] & @r[rs]) + when 0b0001 then res = set_reg(rd, @r[rd] ^ @r[rs]) + when 0b0010 then res = set_reg(rd, lsl(@r[rd], @r[rs], true)) + when 0b0011 then res = set_reg(rd, lsr(@r[rd], @r[rs], true)) + when 0b0100 then res = set_reg(rd, asr(@r[rd], @r[rs], true)) + when 0b0101 then res = set_reg(rd, adc(@r[rd], @r[rs], true)) + when 0b0110 then res = set_reg(rd, sbc(@r[rd], @r[rs], true)) + when 0b0111 then res = set_reg(rd, ror(@r[rd], @r[rs], true)) when 0b1000 then res = @r[rd] & @r[rs] - when 0b1001 then res = @r[rd] = (-@r[rs].to_i32!).to_u32! + when 0b1001 then res = set_reg(rd, (-@r[rs].to_i32!).to_u32!) when 0b1010 then res = sub(@r[rd], @r[rs], true) when 0b1011 then res = add(@r[rd], @r[rs], true) - when 0b1100 then res = @r[rd] = @r[rd] | @r[rs] - when 0b1101 then res = @r[rd] = @r[rs] &* @r[rd] - when 0b1110 then res = @r[rd] = @r[rd] & ~@r[rs] - when 0b1111 then res = @r[rd] = ~@r[rs] + when 0b1100 then res = set_reg(rd, @r[rd] | @r[rs]) + when 0b1101 then res = set_reg(rd, @r[rs] &* @r[rd]) + when 0b1110 then res = set_reg(rd, @r[rd] & ~@r[rs]) + when 0b1111 then res = set_reg(rd, ~@r[rs]) else raise "Invalid alu op: #{op}" end @cpsr.zero = res == 0 diff --git a/src/crab/thumb/conditional_branch.cr b/src/crab/thumb/conditional_branch.cr index 3477790..bc1dd8b 100644 --- a/src/crab/thumb/conditional_branch.cr +++ b/src/crab/thumb/conditional_branch.cr @@ -3,8 +3,7 @@ module THUMB cond = bits(instr, 8..11) offset = bits(instr, 0..7).to_i8!.to_i32 if check_cond cond - @r[15] &+= (offset * 2) - clear_pipeline + set_reg(15, @r[15] &+ (offset * 2)) end end end diff --git a/src/crab/thumb/hi_reg_branch_exchange.cr b/src/crab/thumb/hi_reg_branch_exchange.cr index 13df881..0c40249 100644 --- a/src/crab/thumb/hi_reg_branch_exchange.cr +++ b/src/crab/thumb/hi_reg_branch_exchange.cr @@ -10,18 +10,16 @@ module THUMB rs += 8 if h2 case op - when 0b00 then @r[rd] = add(@r[rd], @r[rs], true) + when 0b00 then set_reg(rd, add(@r[rd], @r[rs], true)) when 0b01 then sub(@r[rd], @r[rs], true) - when 0b10 then @r[rd] = @r[rs] + when 0b10 then set_reg(rd, @r[rs]) when 0b11 if bit?(@r[rs], 0) - @r[15] = @r[rs] & ~1 + set_reg(15, @r[rs]) else @cpsr.thumb = false - @r[15] = @r[rs] & ~3 + set_reg(15, @r[rs]) end - clear_pipeline end - clear_pipeline if rd == 15 end end diff --git a/src/crab/thumb/load_address.cr b/src/crab/thumb/load_address.cr index dbb6ca1..33514eb 100644 --- a/src/crab/thumb/load_address.cr +++ b/src/crab/thumb/load_address.cr @@ -4,6 +4,6 @@ module THUMB rd = bits(instr, 8..10) word = bits(instr, 0..8) imm = word << 2 - @r[rd] = (source ? @r[13] : @r[15]) &+ imm + set_reg(rd, (source ? @r[13] : @r[15]) &+ imm) end end diff --git a/src/crab/thumb/load_store_halfword.cr b/src/crab/thumb/load_store_halfword.cr index ed7ef45..8664512 100644 --- a/src/crab/thumb/load_store_halfword.cr +++ b/src/crab/thumb/load_store_halfword.cr @@ -6,7 +6,7 @@ module THUMB rd = bits(instr, 0..2) address = @r[rb] + (offset << 1) if load - @r[rd] = @gba.bus.read_half(address) + set_reg(rd, @gba.bus.read_half(address)) else @gba.bus[address] = @r[rd].to_u16! end diff --git a/src/crab/thumb/load_store_immediate_offset.cr b/src/crab/thumb/load_store_immediate_offset.cr index 9541933..7004808 100644 --- a/src/crab/thumb/load_store_immediate_offset.cr +++ b/src/crab/thumb/load_store_immediate_offset.cr @@ -8,13 +8,9 @@ module THUMB address = @r[rb] &+ (offset << 2) case byte_quantity_and_load when 0b00 then @gba.bus[address] = @r[rd] - when 0b01 - @r[rd] = @gba.bus.read_word(address) - clear_pipeline if rd == 15 + when 0b01 then set_reg(rd, @gba.bus.read_word(address)) when 0b10 then @gba.bus[address] = 0xFF_u8 & @r[rd] - when 0b11 - @r[rd] = 0xFFFFFFFF_u32 & @gba.bus[address] - clear_pipeline if rd == 15 + when 0b11 then set_reg(rd, 0xFFFFFFFF_u32 & @gba.bus[address]) end end end diff --git a/src/crab/thumb/load_store_register_offset.cr b/src/crab/thumb/load_store_register_offset.cr index 36ce091..0d335f7 100644 --- a/src/crab/thumb/load_store_register_offset.cr +++ b/src/crab/thumb/load_store_register_offset.cr @@ -8,12 +8,8 @@ module THUMB case load_and_byte_quantity when 0b00 then @gba.bus[address] = @r[rd] when 0b01 then @gba.bus[address] = 0xFF_u8 & @r[rd] - when 0b10 - @r[rd] = @gba.bus.read_word address - clear_pipeline if rd == 15 - when 0b11 - @r[rd] = 0xFFFFFFFF_u32 & @gba.bus[address] - clear_pipeline if rd == 15 + when 0b10 then set_reg(rd, @gba.bus.read_word address) + when 0b11 then set_reg(rd, 0xFFFFFFFF_u32 & @gba.bus[address]) end end end diff --git a/src/crab/thumb/load_store_sign_extended.cr b/src/crab/thumb/load_store_sign_extended.cr index 1db299b..e835a57 100644 --- a/src/crab/thumb/load_store_sign_extended.cr +++ b/src/crab/thumb/load_store_sign_extended.cr @@ -6,10 +6,10 @@ module THUMB rd = bits(instr, 0..2) address = @r[rb] &+ @r[ro] case hs - when 0b00 then @gba.bus[address] = @r[rd].to_u16! # strh - when 0b01 then @r[rd] = @gba.bus[address].to_i8!.to_u32 # ldsb - when 0b10 then @r[rd] = @gba.bus.read_half(address) # ldrh - when 0b11 then @r[rd] = @gba.bus.read_half(address).to_i16!.to_u32 # ldsh + when 0b00 then @gba.bus[address] = @r[rd].to_u16! # strh + when 0b01 then set_reg(rd, @gba.bus[address].to_i8!.to_u32) # ldsb + when 0b10 then set_reg(rd, @gba.bus.read_half(address)) # ldrh + when 0b11 then set_reg(rd, @gba.bus.read_half(address).to_i16!.to_u32) # ldsh else raise "Invalid load/store signed extended: #{hs}" end end diff --git a/src/crab/thumb/long_branch_link.cr b/src/crab/thumb/long_branch_link.cr index 03a7857..9337d8b 100644 --- a/src/crab/thumb/long_branch_link.cr +++ b/src/crab/thumb/long_branch_link.cr @@ -4,12 +4,11 @@ module THUMB offset = bits(instr, 0..10) if second_instr temp = @r[15] &- 2 - @r[15] = @r[14] &+ (offset << 1) - @r[14] = temp | 1 - clear_pipeline + set_reg(15, @r[14] &+ (offset << 1)) + set_reg(14, temp | 1) else offset = (offset << 5).to_i16! >> 5 - @r[14] = @r[15] &+ (offset.to_u32 << 12) + set_reg(14, @r[15] &+ (offset.to_u32 << 12)) end end end diff --git a/src/crab/thumb/move_compare_add_subtract.cr b/src/crab/thumb/move_compare_add_subtract.cr index e943d60..afb8c38 100644 --- a/src/crab/thumb/move_compare_add_subtract.cr +++ b/src/crab/thumb/move_compare_add_subtract.cr @@ -5,10 +5,10 @@ module THUMB offset = bits(instr, 0..7) # todo handle carry flag on all ops case op - when 0b00 then res = @r[rd] = offset + when 0b00 then res = set_reg(rd, offset) when 0b01 then res = sub(@r[rd], offset, true) - when 0b10 then res = @r[rd] = add(@r[rd], offset, true) - when 0b11 then res = @r[rd] = sub(@r[rd], offset, true) + when 0b10 then res = set_reg(rd, add(@r[rd], offset, true)) + when 0b11 then res = set_reg(rd, sub(@r[rd], offset, true)) else raise "Invalid move/compare/add/subtract op: #{op}" end @cpsr.zero = res == 0 diff --git a/src/crab/thumb/move_shifted_register.cr b/src/crab/thumb/move_shifted_register.cr index fde88a9..572fd97 100644 --- a/src/crab/thumb/move_shifted_register.cr +++ b/src/crab/thumb/move_shifted_register.cr @@ -4,12 +4,12 @@ module THUMB offset = bits(instr, 6..10) rs = bits(instr, 3..5) rd = bits(instr, 0..2) - @r[rd] = case op - when 0b00 then lsl(@r[rs], offset, true) - when 0b01 then lsr(@r[rs], offset, true) - when 0b10 then asr(@r[rs], offset, true) - else raise "Invalid shifted register op: #{op}" - end + case op + when 0b00 then set_reg(rd, lsl(@r[rs], offset, true)) + when 0b01 then set_reg(rd, lsr(@r[rs], offset, true)) + when 0b10 then set_reg(rd, asr(@r[rs], offset, true)) + else raise "Invalid shifted register op: #{op}" + end @cpsr.zero = @r[rd] == 0 @cpsr.negative = bit?(@r[rd], 31) end diff --git a/src/crab/thumb/multiple_load_store.cr b/src/crab/thumb/multiple_load_store.cr index d347429..8762751 100644 --- a/src/crab/thumb/multiple_load_store.cr +++ b/src/crab/thumb/multiple_load_store.cr @@ -7,7 +7,7 @@ module THUMB if load # ldmia 8.times do |idx| if bit?(list, idx) - @r[idx] = @gba.bus.read_word(address) + set_reg(idx, @gba.bus.read_word(address)) address &+= 4 end end @@ -19,6 +19,6 @@ module THUMB end end end - @r[rb] = address + set_reg(rb, address) end end diff --git a/src/crab/thumb/pc_relative_load.cr b/src/crab/thumb/pc_relative_load.cr index 24b318f..75a7d03 100644 --- a/src/crab/thumb/pc_relative_load.cr +++ b/src/crab/thumb/pc_relative_load.cr @@ -2,6 +2,6 @@ module THUMB def thumb_pc_relative_load(instr : Word) : Nil imm = bits(instr, 0..7) rd = bits(instr, 8..10) - @r[rd] = @gba.bus.read_word((@r[15] & ~2) &+ (imm << 2)) + set_reg(rd, @gba.bus.read_word((@r[15] & ~2) &+ (imm << 2))) end end diff --git a/src/crab/thumb/push_pop_registers.cr b/src/crab/thumb/push_pop_registers.cr index 17b730b..d3ba4ae 100644 --- a/src/crab/thumb/push_pop_registers.cr +++ b/src/crab/thumb/push_pop_registers.cr @@ -7,14 +7,13 @@ module THUMB if pop 8.times do |idx| if bit?(list, idx) - @r[idx] = @gba.bus.read_word(address) + set_reg(idx, @gba.bus.read_word(address)) address &+= 4 end end if pclr - @r[15] = @gba.bus.read_word(address) + set_reg(15, @gba.bus.read_word(address)) address &+= 4 - clear_pipeline end else if pclr @@ -28,6 +27,6 @@ module THUMB end end end - @r[13] = address + set_reg(13, address) end end diff --git a/src/crab/thumb/software_interrupt.cr b/src/crab/thumb/software_interrupt.cr index a4d612a..4699de7 100644 --- a/src/crab/thumb/software_interrupt.cr +++ b/src/crab/thumb/software_interrupt.cr @@ -2,10 +2,9 @@ module THUMB def thumb_software_interrupt(instr : Word) : Nil lr = @r[15] - 4 switch_mode CPU::Mode::SVC - @r[14] = lr + set_reg(14, lr) @cpsr.irq_disable = true @cpsr.thumb = false - @r[15] = 0x08 - clear_pipeline + set_reg(15, 0x08) end end diff --git a/src/crab/thumb/sp_relative_load_store.cr b/src/crab/thumb/sp_relative_load_store.cr index 5722470..a944195 100644 --- a/src/crab/thumb/sp_relative_load_store.cr +++ b/src/crab/thumb/sp_relative_load_store.cr @@ -5,7 +5,7 @@ module THUMB word = bits(instr, 0..7) address = @r[13] &+ (word << 2) if load - @r[rd] = @gba.bus.read_word(address) + set_reg(rd, @gba.bus.read_word(address)) else @gba.bus[address] = @r[rd] end diff --git a/src/crab/thumb/thumb.cr b/src/crab/thumb/thumb.cr index dd1561f..b812016 100644 --- a/src/crab/thumb/thumb.cr +++ b/src/crab/thumb/thumb.cr @@ -25,7 +25,7 @@ module THUMB elsif idx & 0b11110000 == 0b10010000 lut[idx] = ->thumb_sp_relative_load_store(Word) elsif idx & 0b11110000 == 0b10000000 - lut[idx] = -> thumb_load_store_halfword(Word) + lut[idx] = ->thumb_load_store_halfword(Word) elsif idx & 0b11100000 == 0b01100000 lut[idx] = ->thumb_load_store_immediate_offset(Word) elsif idx & 0b11110010 == 0b01010010 diff --git a/src/crab/thumb/unconditional_branch.cr b/src/crab/thumb/unconditional_branch.cr index 62f8f71..7cbde8c 100644 --- a/src/crab/thumb/unconditional_branch.cr +++ b/src/crab/thumb/unconditional_branch.cr @@ -2,7 +2,6 @@ module THUMB def thumb_unconditional_branch(instr : Word) : Nil offset = bits(instr, 0..10) offset = (offset << 5).to_i16! >> 4 - @r[15] &+= offset - clear_pipeline + set_reg(15, @r[15] &+ offset) end end