From 1523742e12723cdae656b104980ec653dfcdc343 Mon Sep 17 00:00:00 2001 From: Matthew Berry Date: Sun, 30 Oct 2022 11:30:36 -0700 Subject: [PATCH] tighten address type restrictions from int to uint32 --- src/crab/gba/apu.cr | 6 +- src/crab/gba/apu/abstract_channels.cr | 4 +- src/crab/gba/apu/channel1.cr | 10 +- src/crab/gba/apu/channel2.cr | 10 +- src/crab/gba/apu/channel3.cr | 14 +- src/crab/gba/apu/channel4.cr | 10 +- src/crab/gba/apu/dma_channels.cr | 8 +- src/crab/gba/arm/arm.cr | 44 +-- src/crab/gba/arm/block_data_transfer.cr | 8 +- src/crab/gba/arm/branch.cr | 2 +- src/crab/gba/arm/branch_exchange.cr | 2 +- src/crab/gba/arm/data_processing.cr | 2 +- .../gba/arm/halfword_data_transfer_imm.cr | 18 +- .../gba/arm/halfword_data_transfer_reg.cr | 18 +- src/crab/gba/arm/multiply.cr | 2 +- src/crab/gba/arm/multiply_long.cr | 2 +- src/crab/gba/arm/psr_transfer.cr | 2 +- src/crab/gba/arm/single_data_swap.cr | 2 +- src/crab/gba/arm/single_data_transfer.cr | 14 +- src/crab/gba/arm/software_interrupt.cr | 2 +- src/crab/gba/bus.cr | 306 +++++++++--------- src/crab/gba/cpu.cr | 42 +-- src/crab/gba/dma.cr | 4 +- src/crab/gba/gba.cr | 1 - src/crab/gba/gpio.cr | 4 +- src/crab/gba/interrupts.cr | 4 +- src/crab/gba/keypad.cr | 4 +- src/crab/gba/mmio.cr | 8 +- src/crab/gba/pipeline.cr | 12 +- src/crab/gba/ppu.cr | 10 +- src/crab/gba/reg.cr | 8 +- src/crab/gba/storage.cr | 16 +- src/crab/gba/storage/eeprom.cr | 4 +- src/crab/gba/storage/flash.cr | 28 +- src/crab/gba/storage/sram.cr | 8 +- .../gba/thumb/add_offset_to_stack_pointer.cr | 2 +- src/crab/gba/thumb/add_subtract.cr | 2 +- src/crab/gba/thumb/alu_operations.cr | 2 +- src/crab/gba/thumb/conditional_branch.cr | 2 +- src/crab/gba/thumb/hi_reg_branch_exchange.cr | 2 +- src/crab/gba/thumb/load_address.cr | 2 +- src/crab/gba/thumb/load_store_halfword.cr | 2 +- .../gba/thumb/load_store_immediate_offset.cr | 2 +- .../gba/thumb/load_store_register_offset.cr | 2 +- .../gba/thumb/load_store_sign_extended.cr | 2 +- src/crab/gba/thumb/long_branch_link.cr | 2 +- .../gba/thumb/move_compare_add_subtract.cr | 2 +- src/crab/gba/thumb/move_shifted_register.cr | 2 +- src/crab/gba/thumb/multiple_load_store.cr | 2 +- src/crab/gba/thumb/pc_relative_load.cr | 2 +- src/crab/gba/thumb/push_pop_registers.cr | 2 +- src/crab/gba/thumb/software_interrupt.cr | 2 +- src/crab/gba/thumb/sp_relative_load_store.cr | 2 +- src/crab/gba/thumb/thumb.cr | 44 +-- src/crab/gba/thumb/unconditional_branch.cr | 2 +- src/crab/gba/timer.cr | 4 +- src/crab/gba/types.cr | 6 - 57 files changed, 362 insertions(+), 369 deletions(-) delete mode 100644 src/crab/gba/types.cr diff --git a/src/crab/gba/apu.cr b/src/crab/gba/apu.cr index 57e4e2d..eff1589 100644 --- a/src/crab/gba/apu.cr +++ b/src/crab/gba/apu.cr @@ -136,7 +136,7 @@ module GBA @dma_channels.timer_overflow timer end - def [](io_addr : Int) : UInt8 + def [](io_addr : UInt32) : UInt8 case io_addr when @channel1 then @channel1[io_addr] when @channel2 then @channel2[io_addr] @@ -161,7 +161,7 @@ module GBA end end - def []=(io_addr : Int, value : UInt8) : Nil + def []=(io_addr : UInt32, value : UInt8) : Nil return unless @sound_enabled || 0x82 <= io_addr <= 0x89 || Channel3::WAVE_RAM_RANGE.includes?(io_addr) case io_addr when @channel1 then @channel1[io_addr] = value @@ -175,7 +175,7 @@ module GBA when 0x83 then @soundcnt_h.value = (@soundcnt_h.value & 0x00FF) | value.to_u16 << 8 when 0x84 if value & 0x80 == 0 && @sound_enabled - (0x60..0x81).each { |addr| self[addr] = 0x00 } + (0x60_u32..0x81_u32).each { |addr| self[addr] = 0x00 } @sound_enabled = false elsif value & 0x80 > 0 && !@sound_enabled @sound_enabled = true diff --git a/src/crab/gba/apu/abstract_channels.cr b/src/crab/gba/apu/abstract_channels.cr index ff96f5b..f3042aa 100644 --- a/src/crab/gba/apu/abstract_channels.cr +++ b/src/crab/gba/apu/abstract_channels.cr @@ -42,8 +42,8 @@ module GBA abstract def get_amplitude : Int16 - abstract def [](index : Int) : UInt8 - abstract def []=(index : Int, value : UInt8) : Nil + abstract def [](address : UInt32) : UInt8 + abstract def []=(address : UInt32, value : UInt8) : Nil end abstract class VolumeEnvelopeChannel < SoundChannel diff --git a/src/crab/gba/apu/channel1.cr b/src/crab/gba/apu/channel1.cr index d731d8a..5ac734d 100644 --- a/src/crab/gba/apu/channel1.cr +++ b/src/crab/gba/apu/channel1.cr @@ -77,8 +77,8 @@ module GBA calculated end - def [](index : Int) : UInt8 - case index + def [](address : UInt32) : UInt8 + case address when 0x60 then @sweep_period << 4 | (@negate ? 0x08 : 0) | @shift when 0x62 then @duty << 6 when 0x63 then read_NRx2 @@ -87,8 +87,8 @@ module GBA end end - def []=(index : Int, value : UInt8) : Nil - case index + def []=(address : UInt32, value : UInt8) : Nil + case address when 0x60 @sweep_period = (value & 0x70) >> 4 @negate = value & 0x08 > 0 @@ -139,7 +139,7 @@ module GBA end when 0x66 # not used when 0x67 # not used - else raise "Writing to invalid Channel1 register: #{hex_str index.to_u16}" + else raise "Writing to invalid Channel1 register: #{hex_str address.to_u16}" end end end diff --git a/src/crab/gba/apu/channel2.cr b/src/crab/gba/apu/channel2.cr index 508512a..3b2aaab 100644 --- a/src/crab/gba/apu/channel2.cr +++ b/src/crab/gba/apu/channel2.cr @@ -43,8 +43,8 @@ module GBA end end - def [](index : Int) : UInt8 - case index + def [](address : UInt32) : UInt8 + case address when 0x68 then @duty << 6 when 0x69 then read_NRx2 when 0x6D then (@length_enable ? 0x40_u8 : 0_u8) @@ -52,8 +52,8 @@ module GBA end end - def []=(index : Int, value : UInt8) : Nil - case index + def []=(address : UInt32, value : UInt8) : Nil + case address when 0x68 @duty = (value & 0xC0) >> 6 @length_load = value & 0x3F @@ -91,7 +91,7 @@ module GBA end when 0x6E # not used when 0x6F # not used - else raise "Writing to invalid Channel2 register: #{hex_str index.to_u16}" + else raise "Writing to invalid Channel2 register: #{hex_str address.to_u16}" end end end diff --git a/src/crab/gba/apu/channel3.cr b/src/crab/gba/apu/channel3.cr index 3ce88e9..057d5d6 100644 --- a/src/crab/gba/apu/channel3.cr +++ b/src/crab/gba/apu/channel3.cr @@ -49,8 +49,8 @@ module GBA end end - def [](index : Int) : UInt8 - case index + def [](address : UInt32) : UInt8 + case address when 0x70 then (@dac_enabled ? 0x80_u8 : 0_u8) | @wave_ram_bank << 6 | (@wave_ram_dimension ? 0x20 : 0) when 0x73 then (@volume_force ? 0x80_u8 : 0_u8) | @volume_code << 5 when 0x75 then (@length_enable ? 0x40_u8 : 0_u8) @@ -58,14 +58,14 @@ module GBA if @enabled @wave_ram[@wave_ram_bank][@wave_ram_position // 2] else - @wave_ram[@wave_ram_bank][index - WAVE_RAM_RANGE.begin] + @wave_ram[@wave_ram_bank][address - WAVE_RAM_RANGE.begin] end else 0_u8 end end - def []=(index : Int, value : UInt8) : Nil - case index + def []=(address : UInt32, value : UInt8) : Nil + case address when 0x70 @dac_enabled = value & 0x80 > 0 @enabled = false if !@dac_enabled @@ -116,9 +116,9 @@ module GBA if @enabled @wave_ram[@wave_ram_bank][@wave_ram_position // 2] = value else - @wave_ram[@wave_ram_bank][index - WAVE_RAM_RANGE.begin] = value + @wave_ram[@wave_ram_bank][address - WAVE_RAM_RANGE.begin] = value end - else raise "Writing to invalid Channel3 register: #{hex_str index.to_u16}" + else raise "Writing to invalid Channel3 register: #{hex_str address.to_u16}" end end end diff --git a/src/crab/gba/apu/channel4.cr b/src/crab/gba/apu/channel4.cr index fde63f5..d4d21ef 100644 --- a/src/crab/gba/apu/channel4.cr +++ b/src/crab/gba/apu/channel4.cr @@ -43,8 +43,8 @@ module GBA end end - def [](index : Int) : UInt8 - case index + def [](address : UInt32) : UInt8 + case address when 0x79 then read_NRx2 when 0x7C then @clock_shift << 4 | @width_mode << 3 | @divisor_code when 0x7D then (@length_enable ? 0x40_u8 : 0_u8) @@ -52,8 +52,8 @@ module GBA end end - def []=(index : Int, value : UInt8) : Nil - case index + def []=(address : UInt32, value : UInt8) : Nil + case address when 0x78 @length_load = value & 0x3F # Internal values @@ -93,7 +93,7 @@ module GBA end when 0x7E # not used when 0x7F # not used - else raise "Writing to invalid Channel4 register: #{hex_str index.to_u16}" + else raise "Writing to invalid Channel4 register: #{hex_str address.to_u16}" end end end diff --git a/src/crab/gba/apu/dma_channels.cr b/src/crab/gba/apu/dma_channels.cr index ff444bf..241f097 100644 --- a/src/crab/gba/apu/dma_channels.cr +++ b/src/crab/gba/apu/dma_channels.cr @@ -19,12 +19,12 @@ module GBA ] end - def [](index : Int) : UInt8 - @gba.bus.read_open_bus_value(index) + def [](address : UInt32) : UInt8 + @gba.bus.read_open_bus_value(address) end - def []=(index : Int, value : Byte) : Nil - channel = bit?(index, 2).to_unsafe + def []=(address : UInt32, value : UInt8) : Nil + channel = bit?(address, 2).to_unsafe if @sizes[channel] < 32 @fifos[channel][(@positions[channel] + @sizes[channel]) % 32] = value.to_i8! @sizes[channel] += 1 diff --git a/src/crab/gba/arm/arm.cr b/src/crab/gba/arm/arm.cr index 04dffa4..9c9010e 100644 --- a/src/crab/gba/arm/arm.cr +++ b/src/crab/gba/arm/arm.cr @@ -5,7 +5,7 @@ module GBA # module. module ARM - def arm_execute(instr : Word) : Nil + def arm_execute(instr : UInt32) : Nil if check_cond bits(instr, 28..31) hash = hash_instr instr lut[hash].call instr @@ -15,15 +15,15 @@ module GBA end end - private def hash_instr(instr : Word) : Word + private def hash_instr(instr : UInt32) : UInt32 (instr >> 16 & 0x0FF0) | (instr >> 4 & 0xF) end - def fill_lut : Slice(Proc(Word, Nil)) - lut = Slice(Proc(Word, Nil)).new 4096, ->arm_unimplemented(Word) + def fill_lut : Slice(Proc(UInt32, Nil)) + lut = Slice(Proc(UInt32, Nil)).new 4096, ->arm_unimplemented(UInt32) 4096.times do |idx| if idx & 0b111100000000 == 0b111100000000 - lut[idx] = ->arm_software_interrupt(Word) + lut[idx] = ->arm_software_interrupt(UInt32) elsif idx & 0b111100000001 == 0b111000000001 # coprocessor register transfer elsif idx & 0b111100000001 == 0b111000000001 @@ -31,45 +31,45 @@ module GBA elsif idx & 0b111000000000 == 0b110000000000 # coprocessor data transfer elsif idx & 0b111000000000 == 0b101000000000 - lut[idx] = ->arm_branch(Word) + lut[idx] = ->arm_branch(UInt32) elsif idx & 0b111000000000 == 0b100000000000 - lut[idx] = ->arm_block_data_transfer(Word) + lut[idx] = ->arm_block_data_transfer(UInt32) elsif idx & 0b111000000001 == 0b011000000001 # undefined elsif idx & 0b110000000000 == 0b010000000000 - lut[idx] = ->arm_single_data_transfer(Word) + lut[idx] = ->arm_single_data_transfer(UInt32) elsif idx & 0b111111111111 == 0b000100100001 - lut[idx] = ->arm_branch_exchange(Word) + lut[idx] = ->arm_branch_exchange(UInt32) elsif idx & 0b111110111111 == 0b000100001001 - lut[idx] = ->arm_single_data_swap(Word) + lut[idx] = ->arm_single_data_swap(UInt32) elsif idx & 0b111110001111 == 0b000010001001 - lut[idx] = ->arm_multiply_long(Word) + lut[idx] = ->arm_multiply_long(UInt32) elsif idx & 0b111111001111 == 0b000000001001 - lut[idx] = ->arm_multiply(Word) + lut[idx] = ->arm_multiply(UInt32) elsif idx & 0b111001001001 == 0b000001001001 - lut[idx] = ->arm_halfword_data_transfer_immediate(Word) + lut[idx] = ->arm_UInt16_data_transfer_immediate(UInt32) elsif idx & 0b111001001001 == 0b000000001001 - lut[idx] = ->arm_halfword_data_transfer_register(Word) + lut[idx] = ->arm_UInt16_data_transfer_register(UInt32) elsif idx & 0b110110010000 == 0b000100000000 - lut[idx] = ->arm_psr_transfer(Word) + lut[idx] = ->arm_psr_transfer(UInt32) elsif idx & 0b110000000000 == 0b000000000000 - lut[idx] = ->arm_data_processing(Word) + lut[idx] = ->arm_data_processing(UInt32) else - lut[idx] = ->arm_unused(Word) + lut[idx] = ->arm_unused(UInt32) end end lut end - def arm_unimplemented(instr : Word) : Nil + def arm_unimplemented(instr : UInt32) : Nil abort "Unimplemented instruction: #{hex_str instr}" end - def arm_unused(instr : Word) : Nil + def arm_unused(instr : UInt32) : Nil puts "Unused instruction: #{hex_str instr}" end - def rotate_register(instr : Word, carry_out : Pointer(Bool), allow_register_shifts : Bool) : Word + def rotate_register(instr : UInt32, carry_out : Pointer(Bool), allow_register_shifts : Bool) : UInt32 reg = bits(instr, 0..3) shift_type = bits(instr, 5..6) immediate = !(allow_register_shifts && bit?(instr, 4)) @@ -89,11 +89,11 @@ module GBA end end - def immediate_offset(instr : Word, carry_out : Pointer(Bool)) : Word + def immediate_offset(instr : UInt32, carry_out : Pointer(Bool)) : UInt32 rotate = bits(instr, 8..11) imm = bits(instr, 0..7) # todo putting "false" here causes the gba-suite tests to pass, but _why_ - ror(imm, 2 * rotate, false, carry_out) + ror(imm, rotate << 1, false, carry_out) end end end diff --git a/src/crab/gba/arm/block_data_transfer.cr b/src/crab/gba/arm/block_data_transfer.cr index 52eac6c..62547e3 100644 --- a/src/crab/gba/arm/block_data_transfer.cr +++ b/src/crab/gba/arm/block_data_transfer.cr @@ -1,7 +1,7 @@ module GBA module ARM - def arm_block_data_transfer(instr : Word) : Nil - pre_index = bit?(instr, 24) + def arm_block_data_transfer(instr : UInt32) : Nil + pre_address = bit?(instr, 24) add = bit?(instr, 23) s_bit = bit?(instr, 22) write_back = bit?(instr, 21) @@ -23,10 +23,10 @@ module GBA end final_addr = address + bits_set * (add ? 4 : -4) if add - address += 4 if pre_index + address += 4 if pre_address else address = final_addr - address += 4 unless pre_index + address += 4 unless pre_address end first_transfer = false 16.times do |idx| # always transfered to/from incrementing addresses diff --git a/src/crab/gba/arm/branch.cr b/src/crab/gba/arm/branch.cr index 6cbcbfb..b636897 100644 --- a/src/crab/gba/arm/branch.cr +++ b/src/crab/gba/arm/branch.cr @@ -1,6 +1,6 @@ module GBA module ARM - def arm_branch(instr : Word) : Nil + def arm_branch(instr : UInt32) : Nil link = bit?(instr, 24) offset = (bits(instr, 0..23) << 8).to_i32! >> 6 set_reg(14, @r[15] - 4) if link diff --git a/src/crab/gba/arm/branch_exchange.cr b/src/crab/gba/arm/branch_exchange.cr index f12ff54..3a62ca1 100644 --- a/src/crab/gba/arm/branch_exchange.cr +++ b/src/crab/gba/arm/branch_exchange.cr @@ -1,6 +1,6 @@ module GBA module ARM - def arm_branch_exchange(instr : Word) : Nil + def arm_branch_exchange(instr : UInt32) : Nil address = @r[bits(instr, 0..3)] @cpsr.thumb = bit?(address, 0) set_reg(15, address) diff --git a/src/crab/gba/arm/data_processing.cr b/src/crab/gba/arm/data_processing.cr index 6530920..0afdec2 100644 --- a/src/crab/gba/arm/data_processing.cr +++ b/src/crab/gba/arm/data_processing.cr @@ -1,6 +1,6 @@ module GBA module ARM - def arm_data_processing(instr : Word) : Nil + def arm_data_processing(instr : UInt32) : Nil imm_flag = bit?(instr, 25) opcode = bits(instr, 21..24) set_conditions = bit?(instr, 20) diff --git a/src/crab/gba/arm/halfword_data_transfer_imm.cr b/src/crab/gba/arm/halfword_data_transfer_imm.cr index bb06634..0891d97 100644 --- a/src/crab/gba/arm/halfword_data_transfer_imm.cr +++ b/src/crab/gba/arm/halfword_data_transfer_imm.cr @@ -1,7 +1,7 @@ module GBA module ARM - def arm_halfword_data_transfer_immediate(instr : Word) : Nil - pre_index = bit?(instr, 24) + def arm_UInt16_data_transfer_immediate(instr : UInt32) : Nil + pre_address = bit?(instr, 24) add = bit?(instr, 23) write_back = bit?(instr, 21) load = bit?(instr, 20) @@ -14,7 +14,7 @@ module GBA address = @r[rn] offset = offset_high << 4 | offset_low - if pre_index + if pre_address if add address &+= offset else @@ -24,7 +24,7 @@ module GBA case sh when 0b00 # swp, no docs on this? - abort "HalfwordDataTransferReg swp #{hex_str instr}" + abort "UInt16DataTransferReg swp #{hex_str instr}" when 0b01 # ldrh/strh if load set_reg(rd, @gba.bus.read_half_rotate address) @@ -38,20 +38,20 @@ module GBA set_reg(rd, @gba.bus[address].to_i8!.to_u32!) when 0b11 # ldrsh set_reg(rd, @gba.bus.read_half_signed(address)) - else raise "Invalid halfword data transfer imm op: #{sh}" + else raise "Invalid UInt16 data transfer imm op: #{sh}" end - unless pre_index + unless pre_address if add address &+= offset else address &-= offset end end - # In the case of post-indexed addressing, the write back bit is redundant and is always set to + # In the case of post-addressed addressing, the write back bit is redundant and is always set to # zero, since the old base value can be retained by setting the offset to zero. Therefore - # post-indexed data transfers always write back the modified base. - set_reg(rn, address) if (write_back || !pre_index) && (rd != rn || !load) + # post-addressed data transfers always write back the modified base. + set_reg(rn, address) if (write_back || !pre_address) && (rd != rn || !load) step_arm unless load && rd == 15 end diff --git a/src/crab/gba/arm/halfword_data_transfer_reg.cr b/src/crab/gba/arm/halfword_data_transfer_reg.cr index e3761cc..a6eb442 100644 --- a/src/crab/gba/arm/halfword_data_transfer_reg.cr +++ b/src/crab/gba/arm/halfword_data_transfer_reg.cr @@ -1,7 +1,7 @@ module GBA module ARM - def arm_halfword_data_transfer_register(instr : Word) : Nil - pre_index = bit?(instr, 24) + def arm_UInt16_data_transfer_register(instr : UInt32) : Nil + pre_address = bit?(instr, 24) add = bit?(instr, 23) write_back = bit?(instr, 21) load = bit?(instr, 20) @@ -13,7 +13,7 @@ module GBA address = @r[rn] offset = @r[rm] - if pre_index + if pre_address if add address &+= offset else @@ -23,7 +23,7 @@ module GBA case sh when 0b00 # swp, no docs on this? - abort "HalfwordDataTransferReg swp #{hex_str instr}" + abort "UInt16DataTransferReg swp #{hex_str instr}" when 0b01 # ldrh/strh if load set_reg(rd, @gba.bus.read_half_rotate address) @@ -37,20 +37,20 @@ module GBA set_reg(rd, @gba.bus[address].to_i8!.to_u32!) when 0b11 # ldrsh set_reg(rd, @gba.bus.read_half_signed(address)) - else raise "Invalid halfword data transfer imm op: #{sh}" + else raise "Invalid UInt16 data transfer imm op: #{sh}" end - unless pre_index + unless pre_address if add address &+= offset else address &-= offset end end - # In the case of post-indexed addressing, the write back bit is redundant and is always set to + # In the case of post-addressed addressing, the write back bit is redundant and is always set to # zero, since the old base value can be retained by setting the offset to zero. Therefore - # post-indexed data transfers always write back the modified base. - set_reg(rn, address) if (write_back || !pre_index) && (rd != rn || !load) + # post-addressed data transfers always write back the modified base. + set_reg(rn, address) if (write_back || !pre_address) && (rd != rn || !load) step_arm unless load && rd == 15 end diff --git a/src/crab/gba/arm/multiply.cr b/src/crab/gba/arm/multiply.cr index 59811e2..fefa606 100644 --- a/src/crab/gba/arm/multiply.cr +++ b/src/crab/gba/arm/multiply.cr @@ -1,6 +1,6 @@ module GBA module ARM - def arm_multiply(instr : Word) : Nil + def arm_multiply(instr : UInt32) : Nil accumulate = bit?(instr, 21) set_conditions = bit?(instr, 20) rd = bits(instr, 16..19) diff --git a/src/crab/gba/arm/multiply_long.cr b/src/crab/gba/arm/multiply_long.cr index ff22996..e37fc7c 100644 --- a/src/crab/gba/arm/multiply_long.cr +++ b/src/crab/gba/arm/multiply_long.cr @@ -1,6 +1,6 @@ module GBA module ARM - def arm_multiply_long(instr : Word) : Nil + def arm_multiply_long(instr : UInt32) : Nil signed = bit?(instr, 22) accumulate = bit?(instr, 21) set_conditions = bit?(instr, 20) diff --git a/src/crab/gba/arm/psr_transfer.cr b/src/crab/gba/arm/psr_transfer.cr index 6ca2548..a827ed3 100644 --- a/src/crab/gba/arm/psr_transfer.cr +++ b/src/crab/gba/arm/psr_transfer.cr @@ -1,6 +1,6 @@ module GBA module ARM - def arm_psr_transfer(instr : Word) : Nil + def arm_psr_transfer(instr : UInt32) : Nil spsr = bit?(instr, 22) mode = CPU::Mode.from_value @cpsr.mode has_spsr = mode != CPU::Mode::USR && mode != CPU::Mode::SYS diff --git a/src/crab/gba/arm/single_data_swap.cr b/src/crab/gba/arm/single_data_swap.cr index 09cb8a8..0a134b7 100644 --- a/src/crab/gba/arm/single_data_swap.cr +++ b/src/crab/gba/arm/single_data_swap.cr @@ -1,6 +1,6 @@ module GBA module ARM - def arm_single_data_swap(instr : Word) : Nil + def arm_single_data_swap(instr : UInt32) : Nil byte_quantity = bit?(instr, 22) rn = bits(instr, 16..19) rd = bits(instr, 12..15) diff --git a/src/crab/gba/arm/single_data_transfer.cr b/src/crab/gba/arm/single_data_transfer.cr index 7880f13..680e850 100644 --- a/src/crab/gba/arm/single_data_transfer.cr +++ b/src/crab/gba/arm/single_data_transfer.cr @@ -1,8 +1,8 @@ module GBA module ARM - def arm_single_data_transfer(instr : Word) : Nil + def arm_single_data_transfer(instr : UInt32) : Nil imm_flag = bit?(instr, 25) - pre_indexing = bit?(instr, 24) + pre_addressing = bit?(instr, 24) add_offset = bit?(instr, 23) byte_quantity = bit?(instr, 22) write_back = bit?(instr, 21) @@ -19,7 +19,7 @@ module GBA address = @r[rn] - if pre_indexing + if pre_addressing if add_offset address &+= offset else @@ -44,17 +44,17 @@ module GBA @gba.bus[address] &+= 4 if rd == 15 end - unless pre_indexing + unless pre_addressing if add_offset address &+= offset else address &-= offset end end - # In the case of post-indexed addressing, the write back bit is redundant and is always set to + # In the case of post-addressed addressing, the write back bit is redundant and is always set to # zero, since the old base value can be retained by setting the offset to zero. Therefore - # post-indexed data transfers always write back the modified base. - set_reg(rn, address) if (write_back || !pre_indexing) && (rd != rn || !load) + # post-addressed data transfers always write back the modified base. + set_reg(rn, address) if (write_back || !pre_addressing) && (rd != rn || !load) step_arm unless load && rd == 15 end diff --git a/src/crab/gba/arm/software_interrupt.cr b/src/crab/gba/arm/software_interrupt.cr index b651153..e232ce7 100644 --- a/src/crab/gba/arm/software_interrupt.cr +++ b/src/crab/gba/arm/software_interrupt.cr @@ -1,6 +1,6 @@ module GBA module ARM - def arm_software_interrupt(instr : Word) : Nil + def arm_software_interrupt(instr : UInt32) : Nil lr = @r[15] - 4 switch_mode CPU::Mode::SVC set_reg(14, lr) diff --git a/src/crab/gba/bus.cr b/src/crab/gba/bus.cr index 116fcd6..aee7860 100644 --- a/src/crab/gba/bus.cr +++ b/src/crab/gba/bus.cr @@ -20,256 +20,256 @@ module GBA @gpio = GPIO.new(@gba) end - def [](index : Int) : Byte - @cycles += ACCESS_TIMING_TABLE[0][page(index)] - read_byte_internal(index) + def [](address : UInt32) : UInt8 + @cycles += ACCESS_TIMING_TABLE[0][page(address)] + read_byte_internal(address) end - def read_half(index : Int) : HalfWord - @cycles += ACCESS_TIMING_TABLE[0][page(index)] - read_half_internal(index) + def read_half(address : UInt32) : UInt16 + @cycles += ACCESS_TIMING_TABLE[0][page(address)] + read_half_internal(address) end - def read_word(index : Int) : Word - @cycles += ACCESS_TIMING_TABLE[1][page(index)] - read_word_internal(index) + def read_word(address : UInt32) : UInt32 + @cycles += ACCESS_TIMING_TABLE[1][page(address)] + read_word_internal(address) end - def []=(index : Int, value : Byte) : Nil - @cycles += ACCESS_TIMING_TABLE[0][page(index)] - write_byte_internal(index, value) + def []=(address : UInt32, value : UInt8) : Nil + @cycles += ACCESS_TIMING_TABLE[0][page(address)] + write_byte_internal(address, value) end - def []=(index : Int, value : HalfWord) : Nil - @cycles += ACCESS_TIMING_TABLE[0][page(index)] - write_half_internal(index, value) + def []=(address : UInt32, value : UInt16) : Nil + @cycles += ACCESS_TIMING_TABLE[0][page(address)] + write_half_internal(address, value) end - def []=(index : Int, value : Word) : Nil - @cycles += ACCESS_TIMING_TABLE[1][page(index)] - write_word_internal(index, value) + def []=(address : UInt32, value : UInt32) : Nil + @cycles += ACCESS_TIMING_TABLE[1][page(address)] + write_word_internal(address, value) end - def read_half_rotate(index : Int) : Word - half = read_half(index).to_u32! - bits = (index & 1) << 3 + def read_half_rotate(address : UInt32) : UInt32 + half = read_half(address).to_u32! + bits = (address & 1) << 3 half >> bits | half << (32 - bits) end # On ARM7 aka ARMv4 aka NDS7/GBA: # LDRH Rd,[odd] --> LDRH Rd,[odd-1] ROR 8 ;read to bit0-7 and bit24-31 # LDRSH Rd,[odd] --> LDRSB Rd,[odd] ;sign-expand BYTE value - def read_half_signed(index : Int) : Word - if bit?(index, 0) - self[index].to_i8!.to_u32! + def read_half_signed(address : UInt32) : UInt32 + if bit?(address, 0) + self[address].to_i8!.to_u32! else - read_half(index).to_i16!.to_u32! + read_half(address).to_i16!.to_u32! end end - def read_word_rotate(index : Int) : Word - word = read_word index - bits = (index & 3) << 3 + def read_word_rotate(address : UInt32) : UInt32 + word = read_word address + bits = (address & 3) << 3 word >> bits | word << (32 - bits) end @[AlwaysInline] - private def page(index : Int) : Int - bits(index, 24..27) + private def page(address : UInt32) : Int + bits(address, 24..27) end @[AlwaysInline] - private def read_byte_internal(index : Int) : Byte - case bits(index, 24..27) - when 0x0 then @bios[index & 0x3FFF] + private def read_byte_internal(address : UInt32) : UInt8 + case bits(address, 24..27) + when 0x0 then @bios[address & 0x3FFF] when 0x1 then 0_u8 # todo: open bus - when 0x2 then @wram_board[index & 0x3FFFF] - when 0x3 then @wram_chip[index & 0x7FFF] - when 0x4 then @gba.mmio[index] - when 0x5 then @gba.ppu.pram[index & 0x3FF] + when 0x2 then @wram_board[address & 0x3FFFF] + when 0x3 then @wram_chip[address & 0x7FFF] + when 0x4 then @gba.mmio[address] + when 0x5 then @gba.ppu.pram[address & 0x3FF] when 0x6 - address = 0x1FFFF_u32 & index + address = 0x1FFFF_u32 & address address -= 0x8000 if address > 0x17FFF @gba.ppu.vram[address] - when 0x7 then @gba.ppu.oam[index & 0x3FF] + when 0x7 then @gba.ppu.oam[address & 0x3FF] when 0x8, 0x9, 0xA, 0xB, 0xC, 0xD - if @gpio.address?(index) && @gpio.allow_reads - @gpio[index] - elsif @gba.storage.eeprom?(index) - @gba.storage[index] + if @gpio.address?(address) && @gpio.allow_reads + @gpio[address] + elsif @gba.storage.eeprom?(address) + @gba.storage[address] else - @gba.cartridge.rom[index & 0x01FFFFFF] + @gba.cartridge.rom[address & 0x01FFFFFF] end - when 0xE, 0xF then @gba.storage[index] - else abort "Unmapped read: #{hex_str index.to_u32}" + when 0xE, 0xF then @gba.storage[address] + else abort "Unmapped read: #{hex_str address.to_u32}" end end @[AlwaysInline] - private def read_half_internal(index : Int) : HalfWord - index &= ~1 - case bits(index, 24..27) - when 0x0 then (@bios.to_unsafe + (index & 0x3FFF)).as(HalfWord*).value + private def read_half_internal(address : UInt32) : UInt16 + address &= ~1 + case bits(address, 24..27) + when 0x0 then (@bios.to_unsafe + (address & 0x3FFF)).as(UInt16*).value when 0x1 then 0_u16 # todo: open bus - when 0x2 then (@wram_board.to_unsafe + (index & 0x3FFFF)).as(HalfWord*).value - when 0x3 then (@wram_chip.to_unsafe + (index & 0x7FFF)).as(HalfWord*).value - when 0x4 then read_half_internal_slow(index) - when 0x5 then (@gba.ppu.pram.to_unsafe + (index & 0x3FF)).as(HalfWord*).value + when 0x2 then (@wram_board.to_unsafe + (address & 0x3FFFF)).as(UInt16*).value + when 0x3 then (@wram_chip.to_unsafe + (address & 0x7FFF)).as(UInt16*).value + when 0x4 then read_half_internal_slow(address) + when 0x5 then (@gba.ppu.pram.to_unsafe + (address & 0x3FF)).as(UInt16*).value when 0x6 - address = 0x1FFFF_u32 & index + address = 0x1FFFF_u32 & address address -= 0x8000 if address > 0x17FFF - (@gba.ppu.vram.to_unsafe + address).as(HalfWord*).value - when 0x7 then (@gba.ppu.oam.to_unsafe + (index & 0x3FF)).as(HalfWord*).value + (@gba.ppu.vram.to_unsafe + address).as(UInt16*).value + when 0x7 then (@gba.ppu.oam.to_unsafe + (address & 0x3FF)).as(UInt16*).value when 0x8, 0x9, 0xA, 0xB, 0xC, 0xD - if @gpio.address?(index) && @gpio.allow_reads - @gpio[index].to_u16! - elsif @gba.storage.eeprom?(index) - @gba.storage[index].to_u16! + if @gpio.address?(address) && @gpio.allow_reads + @gpio[address].to_u16! + elsif @gba.storage.eeprom?(address) + @gba.storage[address].to_u16! else - (@gba.cartridge.rom.to_unsafe + (index & 0x01FFFFFF)).as(HalfWord*).value + (@gba.cartridge.rom.to_unsafe + (address & 0x01FFFFFF)).as(UInt16*).value end - when 0xE, 0xF then @gba.storage.read_half(index) - else abort "Unmapped read: #{hex_str index.to_u32}" + when 0xE, 0xF then @gba.storage.read_half(address) + else abort "Unmapped read: #{hex_str address.to_u32}" end end @[AlwaysInline] - private def read_word_internal(index : Int) : Word - index &= ~3 - case bits(index, 24..27) - when 0x0 then (@bios.to_unsafe + (index & 0x3FFF)).as(Word*).value + private def read_word_internal(address : UInt32) : UInt32 + address &= ~3 + case bits(address, 24..27) + when 0x0 then (@bios.to_unsafe + (address & 0x3FFF)).as(UInt32*).value when 0x1 then 0_u32 # todo: open bus - when 0x2 then (@wram_board.to_unsafe + (index & 0x3FFFF)).as(Word*).value - when 0x3 then (@wram_chip.to_unsafe + (index & 0x7FFF)).as(Word*).value - when 0x4 then read_word_internal_slow(index) - when 0x5 then (@gba.ppu.pram.to_unsafe + (index & 0x3FF)).as(Word*).value + when 0x2 then (@wram_board.to_unsafe + (address & 0x3FFFF)).as(UInt32*).value + when 0x3 then (@wram_chip.to_unsafe + (address & 0x7FFF)).as(UInt32*).value + when 0x4 then read_word_internal_slow(address) + when 0x5 then (@gba.ppu.pram.to_unsafe + (address & 0x3FF)).as(UInt32*).value when 0x6 - address = 0x1FFFF_u32 & index + address = 0x1FFFF_u32 & address address -= 0x8000 if address > 0x17FFF - (@gba.ppu.vram.to_unsafe + address).as(Word*).value - when 0x7 then (@gba.ppu.oam.to_unsafe + (index & 0x3FF)).as(Word*).value + (@gba.ppu.vram.to_unsafe + address).as(UInt32*).value + when 0x7 then (@gba.ppu.oam.to_unsafe + (address & 0x3FF)).as(UInt32*).value when 0x8, 0x9, 0xA, 0xB, 0xC, 0xD - if @gpio.address?(index) && @gpio.allow_reads - @gpio[index].to_u32! - elsif @gba.storage.eeprom?(index) - @gba.storage[index].to_u32! + if @gpio.address?(address) && @gpio.allow_reads + @gpio[address].to_u32! + elsif @gba.storage.eeprom?(address) + @gba.storage[address].to_u32! else - (@gba.cartridge.rom.to_unsafe + (index & 0x01FFFFFF)).as(Word*).value + (@gba.cartridge.rom.to_unsafe + (address & 0x01FFFFFF)).as(UInt32*).value end - when 0xE, 0xF then @gba.storage.read_word(index) - else abort "Unmapped read: #{hex_str index.to_u32}" + when 0xE, 0xF then @gba.storage.read_word(address) + else abort "Unmapped read: #{hex_str address.to_u32}" end end @[AlwaysInline] - private def write_byte_internal(index : Int, value : Byte) : Nil - return if bits(index, 28..31) > 0 - @gba.cpu.fill_pipeline if index <= @gba.cpu.r[15] && index >= @gba.cpu.r[15] &- 4 # detect writes near pc - case bits(index, 24..27) - when 0x2 then @wram_board[index & 0x3FFFF] = value - when 0x3 then @wram_chip[index & 0x7FFF] = value - when 0x4 then @gba.mmio[index] = value - when 0x5 then (@gba.ppu.pram.to_unsafe + (index & 0x3FE)).as(HalfWord*).value = 0x0101_u16 * value + private def write_byte_internal(address : UInt32, value : UInt8) : Nil + return if bits(address, 28..31) > 0 + @gba.cpu.fill_pipeline if address <= @gba.cpu.r[15] && address >= @gba.cpu.r[15] &- 4 # detect writes near pc + case bits(address, 24..27) + when 0x2 then @wram_board[address & 0x3FFFF] = value + when 0x3 then @wram_chip[address & 0x7FFF] = value + when 0x4 then @gba.mmio[address] = value + when 0x5 then (@gba.ppu.pram.to_unsafe + (address & 0x3FE)).as(UInt16*).value = 0x0101_u16 * value when 0x6 limit = @gba.ppu.bitmap? ? 0x13FFF : 0x0FFFF # (u8 write only) upper limit depends on display mode - address = 0x1FFFE_u32 & index # (u8 write only) halfword-aligned + address = 0x1FFFE_u32 & address # (u8 write only) UInt16-aligned address -= 0x8000 if address > 0x17FFF # todo: determine if this happens before or after the limit check - (@gba.ppu.vram.to_unsafe + address).as(HalfWord*).value = 0x0101_u16 * value if address <= limit + (@gba.ppu.vram.to_unsafe + address).as(UInt16*).value = 0x0101_u16 * value if address <= limit when 0x7 # can't write bytes to oam when 0x8, 0xD # all address between aren't writable - if @gpio.address? index - @gpio[index] = value - elsif @gba.storage.eeprom? index - @gba.storage[index] + if @gpio.address? address + @gpio[address] = value + elsif @gba.storage.eeprom? address + @gba.storage[address] end - when 0xE, 0xF then @gba.storage[index] = value - else log "Unmapped write: #{hex_str index.to_u32}" + when 0xE, 0xF then @gba.storage[address] = value + else log "Unmapped write: #{hex_str address.to_u32}" end end @[AlwaysInline] - private def write_half_internal(index : Int, value : HalfWord) : Nil - return if bits(index, 28..31) > 0 - index &= ~1 - @gba.cpu.fill_pipeline if index <= @gba.cpu.r[15] && index >= @gba.cpu.r[15] &- 4 # detect writes near pc - case bits(index, 24..27) - when 0x2 then (@wram_board.to_unsafe + (index & 0x3FFFF)).as(HalfWord*).value = value - when 0x3 then (@wram_chip.to_unsafe + (index & 0x7FFF)).as(HalfWord*).value = value - when 0x4 then write_half_internal_slow(index, value) - when 0x5 then (@gba.ppu.pram.to_unsafe + (index & 0x3FF)).as(HalfWord*).value = value + private def write_half_internal(address : UInt32, value : UInt16) : Nil + return if bits(address, 28..31) > 0 + address &= ~1 + @gba.cpu.fill_pipeline if address <= @gba.cpu.r[15] && address >= @gba.cpu.r[15] &- 4 # detect writes near pc + case bits(address, 24..27) + when 0x2 then (@wram_board.to_unsafe + (address & 0x3FFFF)).as(UInt16*).value = value + when 0x3 then (@wram_chip.to_unsafe + (address & 0x7FFF)).as(UInt16*).value = value + when 0x4 then write_half_internal_slow(address, value) + when 0x5 then (@gba.ppu.pram.to_unsafe + (address & 0x3FF)).as(UInt16*).value = value when 0x6 - address = 0x1FFFF_u32 & index + address = 0x1FFFF_u32 & address address -= 0x8000 if address > 0x17FFF - (@gba.ppu.vram.to_unsafe + address).as(HalfWord*).value = value - when 0x7 then (@gba.ppu.oam.to_unsafe + (index & 0x3FF)).as(HalfWord*).value = value + (@gba.ppu.vram.to_unsafe + address).as(UInt16*).value = value + when 0x7 then (@gba.ppu.oam.to_unsafe + (address & 0x3FF)).as(UInt16*).value = value when 0x8, 0xD # all address between aren't writable - if @gpio.address? index - @gpio[index] = value.to_u8! - elsif @gba.storage.eeprom? index - @gba.storage[index] = value.to_u8! + if @gpio.address? address + @gpio[address] = value.to_u8! + elsif @gba.storage.eeprom? address + @gba.storage[address] = value.to_u8! end - when 0xE, 0xF then write_half_internal_slow(index, value) - else log "Unmapped write: #{hex_str index.to_u32}" + when 0xE, 0xF then write_half_internal_slow(address, value) + else log "Unmapped write: #{hex_str address.to_u32}" end end @[AlwaysInline] - private def write_word_internal(index : Int, value : Word) : Nil - return if bits(index, 28..31) > 0 - index &= ~3 - @gba.cpu.fill_pipeline if index <= @gba.cpu.r[15] && index >= @gba.cpu.r[15] &- 4 # detect writes near pc - case bits(index, 24..27) - when 0x2 then (@wram_board.to_unsafe + (index & 0x3FFFF)).as(Word*).value = value - when 0x3 then (@wram_chip.to_unsafe + (index & 0x7FFF)).as(Word*).value = value - when 0x4 then write_word_internal_slow(index, value) - when 0x5 then (@gba.ppu.pram.to_unsafe + (index & 0x3FF)).as(Word*).value = value + private def write_word_internal(address : UInt32, value : UInt32) : Nil + return if bits(address, 28..31) > 0 + address &= ~3 + @gba.cpu.fill_pipeline if address <= @gba.cpu.r[15] && address >= @gba.cpu.r[15] &- 4 # detect writes near pc + case bits(address, 24..27) + when 0x2 then (@wram_board.to_unsafe + (address & 0x3FFFF)).as(UInt32*).value = value + when 0x3 then (@wram_chip.to_unsafe + (address & 0x7FFF)).as(UInt32*).value = value + when 0x4 then write_word_internal_slow(address, value) + when 0x5 then (@gba.ppu.pram.to_unsafe + (address & 0x3FF)).as(UInt32*).value = value when 0x6 - address = 0x1FFFF_u32 & index + address = 0x1FFFF_u32 & address address -= 0x8000 if address > 0x17FFF - (@gba.ppu.vram.to_unsafe + address).as(Word*).value = value - when 0x7 then (@gba.ppu.oam.to_unsafe + (index & 0x3FF)).as(Word*).value = value + (@gba.ppu.vram.to_unsafe + address).as(UInt32*).value = value + when 0x7 then (@gba.ppu.oam.to_unsafe + (address & 0x3FF)).as(UInt32*).value = value when 0x8, 0xD # all address between aren't writable - if @gpio.address? index - @gpio[index] = value.to_u8! - elsif @gba.storage.eeprom? index - @gba.storage[index] = value.to_u8! + if @gpio.address? address + @gpio[address] = value.to_u8! + elsif @gba.storage.eeprom? address + @gba.storage[address] = value.to_u8! end - when 0xE, 0xF then write_word_internal_slow(index, value) - else log "Unmapped write: #{hex_str index.to_u32}" + when 0xE, 0xF then write_word_internal_slow(address, value) + else log "Unmapped write: #{hex_str address.to_u32}" end end @[AlwaysInline] - private def read_half_internal_slow(index : Int) : HalfWord - read_byte_internal(index).to_u16! | - (read_byte_internal(index + 1).to_u16! << 8) + private def read_half_internal_slow(address : UInt32) : UInt16 + read_byte_internal(address).to_u16! | + (read_byte_internal(address + 1).to_u16! << 8) end @[AlwaysInline] - private def read_word_internal_slow(index : Int) : Word - read_byte_internal(index).to_u32! | - (read_byte_internal(index + 1).to_u32! << 8) | - (read_byte_internal(index + 2).to_u32! << 16) | - (read_byte_internal(index + 3).to_u32! << 24) + private def read_word_internal_slow(address : UInt32) : UInt32 + read_byte_internal(address).to_u32! | + (read_byte_internal(address + 1).to_u32! << 8) | + (read_byte_internal(address + 2).to_u32! << 16) | + (read_byte_internal(address + 3).to_u32! << 24) end @[AlwaysInline] - private def write_half_internal_slow(index : Int, value : HalfWord) : Nil - write_byte_internal(index, value.to_u8!) - write_byte_internal(index + 1, (value >> 8).to_u8!) + private def write_half_internal_slow(address : UInt32, value : UInt16) : Nil + write_byte_internal(address, value.to_u8!) + write_byte_internal(address + 1, (value >> 8).to_u8!) end @[AlwaysInline] - private def write_word_internal_slow(index : Int, value : Word) : Nil - write_byte_internal(index, value.to_u8!) - write_byte_internal(index + 1, (value >> 8).to_u8!) - write_byte_internal(index + 2, (value >> 16).to_u8!) - write_byte_internal(index + 3, (value >> 24).to_u8!) + private def write_word_internal_slow(address : UInt32, value : UInt32) : Nil + write_byte_internal(address, value.to_u8!) + write_byte_internal(address + 1, (value >> 8).to_u8!) + write_byte_internal(address + 2, (value >> 16).to_u8!) + write_byte_internal(address + 3, (value >> 24).to_u8!) end - def read_open_bus_value(index : Int, _file = __FILE__) : Byte - log "Reading open bus at #{hex_str index.to_u32} from #{_file}" - shift = (index & 3) * 8 + def read_open_bus_value(address : UInt32, _file = __FILE__) : UInt8 + log "Reading open bus at #{hex_str address.to_u32} from #{_file}" + shift = (address & 3) * 8 if @gba.cpu.cpsr.thumb # todo: special handling for 16-bit vs 32-bit regions # todo: does this need to have both of the previous opcodes? diff --git a/src/crab/gba/cpu.cr b/src/crab/gba/cpu.cr index a3ce912..b60cad0 100644 --- a/src/crab/gba/cpu.cr +++ b/src/crab/gba/cpu.cr @@ -42,14 +42,14 @@ module GBA bool negative end - getter r = Slice(Word).new 16 + getter r = Slice(UInt32).new 16 getter cpsr : PSR = PSR.new CPU::Mode::SYS.value @spsr : PSR = PSR.new CPU::Mode::SYS.value getter 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(GBA::Word).new 7, 0 } - @spsr_banks = Array(Word).new 6, CPU::Mode::SYS.value # logically independent of typical register banks + getter lut : Slice(Proc(UInt32, Nil)) { fill_lut } + getter thumb_lut : Slice(Proc(UInt32, Nil)) { fill_thumb_lut } + @reg_banks = Array(Array(UInt32)).new 6 { Array(UInt32).new 7, 0 } + @spsr_banks = Array(UInt32).new 6, CPU::Mode::SYS.value # logically independent of typical register banks property halted = false def initialize(@gba : GBA) @@ -118,7 +118,7 @@ module GBA end end - def read_instr : Word + def read_instr : UInt32 if @pipeline.size == 0 if @cpsr.thumb @r[15] &= ~1 @@ -148,7 +148,7 @@ module GBA end end - def check_cond(cond : Word) : Bool + def check_cond(cond : UInt32) : Bool case cond when 0x0 then @cpsr.zero when 0x1 then !@cpsr.zero @@ -178,20 +178,20 @@ module GBA end @[AlwaysInline] - def set_reg(reg : Int, value : Int) : UInt32 - @r[reg] = value.to_u32! + def set_reg(reg : Int, value : UInt32) : UInt32 + @r[reg] = value clear_pipeline if reg == 15 - value.to_u32! + value end @[AlwaysInline] - def set_neg_and_zero_flags(value : Int) : Nil + def set_neg_and_zero_flags(value : UInt32) : Nil @cpsr.negative = bit?(value, 31) @cpsr.zero = value == 0 end # Logical shift left - def lsl(word : Word, bits : Int, carry_out : Pointer(Bool)) : Word + def lsl(word : UInt32, bits : Int::Unsigned, carry_out : Pointer(Bool)) : UInt32 log "lsl - word:#{hex_str word}, bits:#{bits}" return word if bits == 0 carry_out.value = bit?(word, 32 - bits) @@ -199,7 +199,7 @@ module GBA end # Logical shift right - def lsr(word : Word, bits : Int, immediate : Bool, carry_out : Pointer(Bool)) : Word + def lsr(word : UInt32, bits : Int::Unsigned, immediate : Bool, carry_out : Pointer(Bool)) : UInt32 log "lsr - word:#{hex_str word}, bits:#{bits}" if bits == 0 return word unless immediate @@ -210,7 +210,7 @@ module GBA end # Arithmetic shift right - def asr(word : Word, bits : Int, immediate : Bool, carry_out : Pointer(Bool)) : Word + def asr(word : UInt32, bits : Int::Unsigned, immediate : Bool, carry_out : Pointer(Bool)) : UInt32 log "asr - word:#{hex_str word}, bits:#{bits}" if bits == 0 return word unless immediate @@ -227,7 +227,7 @@ module GBA end # Rotate right - def ror(word : Word, bits : Int, immediate : Bool, carry_out : Pointer(Bool)) : Word + def ror(word : UInt32, bits : Int::Unsigned, immediate : Bool, carry_out : Pointer(Bool)) : UInt32 log "ror - word:#{hex_str word}, bits:#{bits}" if bits == 0 # RRX #1 return word unless immediate @@ -243,7 +243,7 @@ module GBA end # Subtract two values - def sub(operand_1 : Word, operand_2 : Word, set_conditions : Bool) : Word + def sub(operand_1 : UInt32, operand_2 : UInt32, set_conditions : Bool) : UInt32 log "sub - operand_1:#{hex_str operand_1}, operand_2:#{hex_str operand_2}" res = operand_1 &- operand_2 if set_conditions @@ -255,7 +255,7 @@ module GBA end # Subtract two values with carry - def sbc(operand_1 : Word, operand_2 : Word, set_conditions : Bool) : Word + def sbc(operand_1 : UInt32, operand_2 : UInt32, set_conditions : Bool) : UInt32 log "sbc - operand_1:#{hex_str operand_1}, operand_2:#{hex_str operand_2}" res = operand_1 &- operand_2 &- 1 &+ @cpsr.carry.to_unsafe if set_conditions @@ -267,7 +267,7 @@ module GBA end # Add two values - def add(operand_1 : Word, operand_2 : Word, set_conditions : Bool) : Word + def add(operand_1 : UInt32, operand_2 : UInt32, set_conditions : Bool) : UInt32 log "add - operand_1:#{hex_str operand_1}, operand_2:#{hex_str operand_2}" res = operand_1 &+ operand_2 if set_conditions @@ -279,7 +279,7 @@ module GBA end # Add two values with carry - def adc(operand_1 : Word, operand_2 : Word, set_conditions : Bool) : Word + def adc(operand_1 : UInt32, operand_2 : UInt32, set_conditions : Bool) : UInt32 log "adc - operand_1:#{hex_str operand_1}, operand_2:#{hex_str operand_2}" res = operand_1 &+ operand_2 &+ @cpsr.carry.to_unsafe if set_conditions @@ -290,8 +290,8 @@ module GBA res end - def print_state(instr : Word? = nil) : Nil - @r.each_with_index do |val, reg| + def print_state(instr : UInt32? = nil) : Nil + @r.each_with_address do |val, reg| print "#{hex_str reg == 15 ? val - (@cpsr.thumb ? 2 : 4) : val, prefix: false} " end instr ||= @pipeline.peek diff --git a/src/crab/gba/dma.cr b/src/crab/gba/dma.cr index f55b819..b72da81 100644 --- a/src/crab/gba/dma.cr +++ b/src/crab/gba/dma.cr @@ -41,7 +41,7 @@ module GBA ->{ @gba.interrupts.reg_if.dma2 = true }, ->{ @gba.interrupts.reg_if.dma3 = true }] end - def [](io_addr : Int) : UInt8 + def [](io_addr : UInt32) : UInt8 channel = (io_addr - 0xB0) // 12 reg = (io_addr - 0xB0) % 12 case reg @@ -54,7 +54,7 @@ module GBA end end - def []=(io_addr : Int, value : UInt8) : Nil + def []=(io_addr : UInt32, value : UInt8) : Nil channel = (io_addr - 0xB0) // 12 reg = (io_addr - 0xB0) % 12 case reg diff --git a/src/crab/gba/gba.cr b/src/crab/gba/gba.cr index f80fb23..fc059d4 100644 --- a/src/crab/gba/gba.cr +++ b/src/crab/gba/gba.cr @@ -1,4 +1,3 @@ -require "./types" require "./reg" require "./cartridge" require "./storage" diff --git a/src/crab/gba/gpio.cr b/src/crab/gba/gpio.cr index 1e6cb4a..0b0da3b 100644 --- a/src/crab/gba/gpio.cr +++ b/src/crab/gba/gpio.cr @@ -10,7 +10,7 @@ module GBA @rtc = RTC.new(@gba) # todo: support other forms of gpio end - def [](io_addr : Int) : Byte + def [](io_addr : UInt32) : UInt8 case io_addr & 0xFF when 0xC4 # IO Port Data if @allow_reads @@ -27,7 +27,7 @@ module GBA end end - def []=(io_addr : Int, value : Byte) : Nil + def []=(io_addr : UInt32, value : UInt8) : Nil case io_addr & 0xFF when 0xC4 # IO Port Data @data &= value & 0xF_u8 diff --git a/src/crab/gba/interrupts.cr b/src/crab/gba/interrupts.cr index 553f06f..44e5ee1 100644 --- a/src/crab/gba/interrupts.cr +++ b/src/crab/gba/interrupts.cr @@ -7,7 +7,7 @@ module GBA def initialize(@gba : GBA) end - def [](io_addr : Int) : Byte + def [](io_addr : UInt32) : UInt8 case io_addr when 0x200 then 0xFF_u8 & @reg_ie.value when 0x201 then 0xFF_u8 & @reg_ie.value >> 8 @@ -19,7 +19,7 @@ module GBA end end - def []=(io_addr : Int, value : Byte) : Nil + def []=(io_addr : UInt32, value : UInt8) : Nil case io_addr when 0x200 then @reg_ie.value = (@reg_ie.value & 0xFF00) | value when 0x201 then @reg_ie.value = (@reg_ie.value & 0x00FF) | value.to_u16 << 8 diff --git a/src/crab/gba/keypad.cr b/src/crab/gba/keypad.cr index cab3285..3e1b18f 100644 --- a/src/crab/gba/keypad.cr +++ b/src/crab/gba/keypad.cr @@ -6,7 +6,7 @@ module GBA def initialize(@gba : GBA) end - def [](io_addr : Int) : Byte + def [](io_addr : UInt32) : UInt8 case io_addr when 0x130..0x131 then @keyinput.read_byte(io_addr & 1) when 0x132..0x133 then @keycnt.read_byte(io_addr & 1) @@ -14,7 +14,7 @@ module GBA end end - def []=(io_addr : Int, value : Byte) : Nil + def []=(io_addr : UInt32, value : UInt8) : Nil # TODO: If stopping is implemented, implement keycnt to exit stop mode end diff --git a/src/crab/gba/mmio.cr b/src/crab/gba/mmio.cr index 2512273..9d773a7 100644 --- a/src/crab/gba/mmio.cr +++ b/src/crab/gba/mmio.cr @@ -5,8 +5,8 @@ module GBA def initialize(@gba : GBA) end - def [](index : Int) : Byte - io_addr = 0xFFFFFF_u32 & index + def [](address : UInt32) : UInt8 + io_addr = 0xFFFFFF_u32 & address case io_addr when 0x000..0x055 then @gba.ppu[io_addr] when 0x060..0x0A7 then @gba.apu[io_addr] @@ -29,8 +29,8 @@ module GBA end end - def []=(index : Int, value : Byte) : Nil - io_addr = 0xFFFFFF_u32 & index + def []=(address : UInt32, value : UInt8) : Nil + io_addr = 0xFFFFFF_u32 & address case io_addr when 0x000..0x055 then @gba.ppu[io_addr] = value when 0x060..0x0A7 then @gba.apu[io_addr] = value diff --git a/src/crab/gba/pipeline.cr b/src/crab/gba/pipeline.cr index 8ae7920..b3884c2 100644 --- a/src/crab/gba/pipeline.cr +++ b/src/crab/gba/pipeline.cr @@ -2,25 +2,25 @@ module GBA # A super minimalistic FIFO queue implementation optimized for # use as an ARM instruction pipeline. class Pipeline - @buffer = Slice(Word).new 2 + @buffer = Slice(UInt32).new 2 @pos = 0 @size = 0 - def push(instr : Word) : Nil + def push(instr : UInt32) : Nil raise "Pushing to full pipeline" if @size == 2 - index = (@pos + @size) & 1 - @buffer[index] = instr + address = (@pos + @size) & 1 + @buffer[address] = instr @size += 1 end - def shift : Word + def shift : UInt32 @size -= 1 val = @buffer[@pos] @pos = (@pos + 1) & 1 val end - def peek : Word + def peek : UInt32 @buffer[@pos] end diff --git a/src/crab/gba/ppu.cr b/src/crab/gba/ppu.cr index 565d4fd..52a332e 100644 --- a/src/crab/gba/ppu.cr +++ b/src/crab/gba/ppu.cr @@ -84,7 +84,7 @@ module GBA # Get the screen entry offset from the tile x, tile y, and background screen-size param using tonc algo @[AlwaysInline] - def se_index(tx : Int, ty : Int, screen_size : Int) : Int + def se_address(tx : Int, ty : Int, screen_size : Int) : Int n = tx + ty * 32 n += 0x03E0 if tx >= 32 n += 0x0400 if ty >= 32 && screen_size == 0b11 @@ -167,7 +167,7 @@ module GBA effective_col = (col + bghofs.offset) & bg_width tile_x = effective_col >> 3 - se_idx = se_index(tile_x, tile_y, bgcnt.screen_size) + se_idx = se_address(tile_x, tile_y, bgcnt.screen_size) screen_entry = @vram[screen_base + se_idx * 2 + 1].to_u16 << 8 | @vram[screen_base + se_idx * 2] tile_id = bits(screen_entry, 0..9) @@ -295,7 +295,7 @@ module GBA tile_id += offset palettes = @vram[base + tile_id * 0x20 + tile_y * 4 + (tile_x >> 1)] pal_idx = ((palettes >> ((tile_x & 1) * 4)) & 0xF) - pal_idx += (sprite.palette_bank << 4) if pal_idx > 0 # convert palette index to absolute value + pal_idx += (sprite.palette_bank << 4) if pal_idx > 0 # convert palette address to absolute value end if sprite.obj_mode == 0b10 # object window @@ -396,7 +396,7 @@ module GBA end end - def [](io_addr : Int) : Byte + def [](io_addr : UInt32) : UInt8 case io_addr when 0x000..0x001 then @dispcnt.read_byte(io_addr & 1) when 0x002..0x003 then 0_u8 # todo green swap @@ -415,7 +415,7 @@ module GBA end end - def []=(io_addr : Int, value : Byte) : Nil + def []=(io_addr : UInt32, value : UInt8) : Nil case io_addr when 0x000..0x001 then @dispcnt.write_byte(io_addr & 1, value) when 0x002..0x003 # undocumented - green swap diff --git a/src/crab/gba/reg.cr b/src/crab/gba/reg.cr index 4caa60b..5d1ff81 100644 --- a/src/crab/gba/reg.cr +++ b/src/crab/gba/reg.cr @@ -1,11 +1,11 @@ module GBA module Reg module Base16 - def read_byte(byte_num : Int) : Byte + def read_byte(byte_num : Int) : UInt8 (value >> (8 * byte_num)).to_u8! end - def write_byte(byte_num : Int, byte : Byte) : Byte + def write_byte(byte_num : Int, byte : UInt8) : UInt8 shift = 8 * byte_num mask = ~(0xFF_u16 << shift) self.value = (@value & mask) | byte.to_u16 << shift @@ -14,11 +14,11 @@ module GBA end module Base32 - def read_byte(byte_num : Int) : Byte + def read_byte(byte_num : Int) : UInt8 (value >> (8 * byte_num)).to_u8! end - def write_byte(byte_num : Int, byte : Byte) : Byte + def write_byte(byte_num : Int, byte : UInt8) : UInt8 shift = 8 * byte_num mask = ~(0xFF_u32 << shift) self.value = (@value & mask) | byte.to_u32 << shift diff --git a/src/crab/gba/storage.cr b/src/crab/gba/storage.cr index a681b4a..1f44de4 100644 --- a/src/crab/gba/storage.cr +++ b/src/crab/gba/storage.cr @@ -49,20 +49,20 @@ module GBA end end - abstract def [](index : Int) : Byte + abstract def [](address : UInt32) : UInt8 - def read_half(index : Int) : HalfWord - 0x0101_u16 * self[index & ~1] + def read_half(address : UInt32) : UInt16 + 0x0101_u16 * self[address & ~1] end - def read_word(index : Int) : Word - 0x01010101_u32 * self[index & ~3] + def read_word(address : UInt32) : UInt32 + 0x01010101_u32 * self[address & ~3] end - abstract def []=(index : Int, value : Byte) : Nil + abstract def []=(address : UInt32, value : UInt8) : Nil - def eeprom?(index : Int) : Bool - self.class == EEPROM && (0x0D000000..0x0DFFFFFF).includes? index + def eeprom?(address : UInt32) : Bool + self.class == EEPROM && (0x0D000000..0x0DFFFFFF).includes?(address) end private def self.find_type(file : File) : Type? diff --git a/src/crab/gba/storage/eeprom.cr b/src/crab/gba/storage/eeprom.cr index bb095a2..20fbc9b 100644 --- a/src/crab/gba/storage/eeprom.cr +++ b/src/crab/gba/storage/eeprom.cr @@ -69,7 +69,7 @@ module GBA end end - def [](index : Int) : Byte + def [](address : UInt32) : UInt8 case @state when .includes? State::READ_IGNORE if (@ignored_reads += 1) == 4 @@ -89,7 +89,7 @@ module GBA 1_u8 end - def []=(index : Int, value : Byte) : Nil + def []=(address : UInt32, value : UInt8) : Nil return if @state == State::READ || @state == State::READ_IGNORE value &= 1 @buffer.push value diff --git a/src/crab/gba/storage/flash.cr b/src/crab/gba/storage/flash.cr index 6b65a98..9255bed 100644 --- a/src/crab/gba/storage/flash.cr +++ b/src/crab/gba/storage/flash.cr @@ -11,7 +11,7 @@ module GBA SET_BANK end - enum Command : Byte + enum Command : UInt8 ENTER_IDENT = 0x90 EXIT_IDENT = 0xF0 PREPARE_ERASE = 0x80 @@ -32,37 +32,37 @@ module GBA end end - def [](index : Int) : Byte - index &= 0xFFFF - if @state.includes?(State::IDENTIFICATION) && 0 <= index <= 1 - (@id >> (8 * index) & 0xFF).to_u8! + def [](address : UInt32) : UInt8 + address &= 0xFFFF + if @state.includes?(State::IDENTIFICATION) && 0 <= address <= 1 + (@id >> (8 * address) & 0xFF).to_u8! else - @memory[0x10000 * @bank + index] + @memory[0x10000 * @bank + address] end end - def []=(index : Int, value : Byte) : Nil - index &= 0xFFFF + def []=(address : UInt32, value : UInt8) : Nil + address &= 0xFFFF case @state when .includes? State::PREPARE_WRITE - @memory[0x10000 * @bank + index] &= value + @memory[0x10000 * @bank + address] &= value @dirty = true @state ^= State::PREPARE_WRITE when .includes? State::SET_BANK @bank = value & 1 @state ^= State::SET_BANK when .includes? State::READY - if index == 0x5555 && value == 0xAA + if address == 0x5555 && value == 0xAA @state ^= State::READY @state |= State::CMD_1 end when .includes? State::CMD_1 - if index == 0x2AAA && value == 0x55 + if address == 0x2AAA && value == 0x55 @state ^= State::CMD_1 @state |= State::CMD_2 end when .includes? State::CMD_2 - if index == 0x5555 + if address == 0x5555 case Command.new(value) when Command::ENTER_IDENT then @state |= State::IDENTIFICATION when Command::EXIT_IDENT then @state ^= State::IDENTIFICATION @@ -77,8 +77,8 @@ module GBA when Command::SET_BANK then @state |= State::SET_BANK if @type == Type::FLASH1M else puts "Unsupported flash command #{hex_str value}" end - elsif @state.includes?(State::PREPARE_ERASE) && index & 0x0FFF == 0 && value == Command::ERASE_CHUNK.value - 0x1000.times { |i| @memory[0x10000 * @bank + index + i] = 0xFF } + elsif @state.includes?(State::PREPARE_ERASE) && address & 0x0FFF == 0 && value == Command::ERASE_CHUNK.value + 0x1000.times { |i| @memory[0x10000 * @bank + address + i] = 0xFF } @dirty = true @state ^= State::PREPARE_ERASE end diff --git a/src/crab/gba/storage/sram.cr b/src/crab/gba/storage/sram.cr index 0c6f3b8..d158cb9 100644 --- a/src/crab/gba/storage/sram.cr +++ b/src/crab/gba/storage/sram.cr @@ -2,12 +2,12 @@ module GBA class SRAM < Storage @memory = Bytes.new(Type::SRAM.bytes, 0xFF) - def [](index : Int) : Byte - @memory[index & 0x7FFF] + def [](address : UInt32) : UInt8 + @memory[address & 0x7FFF] end - def []=(index : Int, value : Byte) : Nil - @memory[index & 0x7FFF] = value + def []=(address : UInt32, value : UInt8) : Nil + @memory[address & 0x7FFF] = value @dirty = true end end diff --git a/src/crab/gba/thumb/add_offset_to_stack_pointer.cr b/src/crab/gba/thumb/add_offset_to_stack_pointer.cr index ae9f315..868a153 100644 --- a/src/crab/gba/thumb/add_offset_to_stack_pointer.cr +++ b/src/crab/gba/thumb/add_offset_to_stack_pointer.cr @@ -1,6 +1,6 @@ module GBA module THUMB - def thumb_add_offset_to_stack_pointer(instr : Word) : Nil + def thumb_add_offset_to_stack_pointer(instr : UInt32) : Nil sign = bit?(instr, 7) offset = bits(instr, 0..6) if sign # negative diff --git a/src/crab/gba/thumb/add_subtract.cr b/src/crab/gba/thumb/add_subtract.cr index d7997f0..0cf571d 100644 --- a/src/crab/gba/thumb/add_subtract.cr +++ b/src/crab/gba/thumb/add_subtract.cr @@ -1,6 +1,6 @@ module GBA module THUMB - def thumb_add_subtract(instr : Word) : Nil + def thumb_add_subtract(instr : UInt32) : Nil imm_flag = bit?(instr, 10) sub = bit?(instr, 9) imm = bits(instr, 6..8) diff --git a/src/crab/gba/thumb/alu_operations.cr b/src/crab/gba/thumb/alu_operations.cr index caed2fe..120990c 100644 --- a/src/crab/gba/thumb/alu_operations.cr +++ b/src/crab/gba/thumb/alu_operations.cr @@ -1,6 +1,6 @@ module GBA module THUMB - def thumb_alu_operations(instr : Word) : Nil + def thumb_alu_operations(instr : UInt32) : Nil op = bits(instr, 6..9) rs = bits(instr, 3..5) rd = bits(instr, 0..2) diff --git a/src/crab/gba/thumb/conditional_branch.cr b/src/crab/gba/thumb/conditional_branch.cr index 1693d93..72c58c7 100644 --- a/src/crab/gba/thumb/conditional_branch.cr +++ b/src/crab/gba/thumb/conditional_branch.cr @@ -1,6 +1,6 @@ module GBA module THUMB - def thumb_conditional_branch(instr : Word) : Nil + def thumb_conditional_branch(instr : UInt32) : Nil cond = bits(instr, 8..11) offset = bits(instr, 0..7).to_i8!.to_i32 if check_cond cond diff --git a/src/crab/gba/thumb/hi_reg_branch_exchange.cr b/src/crab/gba/thumb/hi_reg_branch_exchange.cr index 68c7cff..575ece9 100644 --- a/src/crab/gba/thumb/hi_reg_branch_exchange.cr +++ b/src/crab/gba/thumb/hi_reg_branch_exchange.cr @@ -1,6 +1,6 @@ module GBA module THUMB - def thumb_high_reg_branch_exchange(instr : Word) : Nil + def thumb_high_reg_branch_exchange(instr : UInt32) : Nil op = bits(instr, 8..9) h1 = bit?(instr, 7) h2 = bit?(instr, 6) diff --git a/src/crab/gba/thumb/load_address.cr b/src/crab/gba/thumb/load_address.cr index ff51321..e7a2ecb 100644 --- a/src/crab/gba/thumb/load_address.cr +++ b/src/crab/gba/thumb/load_address.cr @@ -1,6 +1,6 @@ module GBA module THUMB - def thumb_load_address(instr : Word) : Nil + def thumb_load_address(instr : UInt32) : Nil source = bit?(instr, 11) rd = bits(instr, 8..10) word = bits(instr, 0..7) diff --git a/src/crab/gba/thumb/load_store_halfword.cr b/src/crab/gba/thumb/load_store_halfword.cr index 51adaac..7169c29 100644 --- a/src/crab/gba/thumb/load_store_halfword.cr +++ b/src/crab/gba/thumb/load_store_halfword.cr @@ -1,6 +1,6 @@ module GBA module THUMB - def thumb_load_store_halfword(instr : Word) : Nil + def thumb_load_store_UInt16(instr : UInt32) : Nil load = bit?(instr, 11) offset = bits(instr, 6..10) rb = bits(instr, 3..5) diff --git a/src/crab/gba/thumb/load_store_immediate_offset.cr b/src/crab/gba/thumb/load_store_immediate_offset.cr index bec14a7..94b53e2 100644 --- a/src/crab/gba/thumb/load_store_immediate_offset.cr +++ b/src/crab/gba/thumb/load_store_immediate_offset.cr @@ -1,6 +1,6 @@ module GBA module THUMB - def thumb_load_store_immediate_offset(instr : Word) : Nil + def thumb_load_store_immediate_offset(instr : UInt32) : Nil byte_quantity_and_load = bits(instr, 11..12) offset = bits(instr, 6..10) rb = bits(instr, 3..5) diff --git a/src/crab/gba/thumb/load_store_register_offset.cr b/src/crab/gba/thumb/load_store_register_offset.cr index 6329d10..d74f055 100644 --- a/src/crab/gba/thumb/load_store_register_offset.cr +++ b/src/crab/gba/thumb/load_store_register_offset.cr @@ -1,6 +1,6 @@ module GBA module THUMB - def thumb_load_store_register_offset(instr : Word) : Nil + def thumb_load_store_register_offset(instr : UInt32) : Nil load_and_byte_quantity = bits(instr, 10..11) ro = bits(instr, 6..8) rb = bits(instr, 3..5) diff --git a/src/crab/gba/thumb/load_store_sign_extended.cr b/src/crab/gba/thumb/load_store_sign_extended.cr index c30509d..1e4c8df 100644 --- a/src/crab/gba/thumb/load_store_sign_extended.cr +++ b/src/crab/gba/thumb/load_store_sign_extended.cr @@ -1,6 +1,6 @@ module GBA module THUMB - def thumb_load_store_sign_extended(instr : Word) : Nil + def thumb_load_store_sign_extended(instr : UInt32) : Nil hs = bits(instr, 10..11) ro = bits(instr, 6..8) rb = bits(instr, 3..5) diff --git a/src/crab/gba/thumb/long_branch_link.cr b/src/crab/gba/thumb/long_branch_link.cr index 66a9659..7ee0e90 100644 --- a/src/crab/gba/thumb/long_branch_link.cr +++ b/src/crab/gba/thumb/long_branch_link.cr @@ -1,6 +1,6 @@ module GBA module THUMB - def thumb_long_branch_link(instr : Word) : Nil + def thumb_long_branch_link(instr : UInt32) : Nil second_instr = bit?(instr, 11) offset = bits(instr, 0..10) if second_instr diff --git a/src/crab/gba/thumb/move_compare_add_subtract.cr b/src/crab/gba/thumb/move_compare_add_subtract.cr index 6455ee6..6f6d12f 100644 --- a/src/crab/gba/thumb/move_compare_add_subtract.cr +++ b/src/crab/gba/thumb/move_compare_add_subtract.cr @@ -1,6 +1,6 @@ module GBA module THUMB - def thumb_move_compare_add_subtract(instr : Word) : Nil + def thumb_move_compare_add_subtract(instr : UInt32) : Nil op = bits(instr, 11..12) rd = bits(instr, 8..10) offset = bits(instr, 0..7) diff --git a/src/crab/gba/thumb/move_shifted_register.cr b/src/crab/gba/thumb/move_shifted_register.cr index 13637c0..4c28a06 100644 --- a/src/crab/gba/thumb/move_shifted_register.cr +++ b/src/crab/gba/thumb/move_shifted_register.cr @@ -1,6 +1,6 @@ module GBA module THUMB - def thumb_move_shifted_register(instr : Word) : Nil + def thumb_move_shifted_register(instr : UInt32) : Nil op = bits(instr, 11..12) offset = bits(instr, 6..10) rs = bits(instr, 3..5) diff --git a/src/crab/gba/thumb/multiple_load_store.cr b/src/crab/gba/thumb/multiple_load_store.cr index c56dc58..4db0b19 100644 --- a/src/crab/gba/thumb/multiple_load_store.cr +++ b/src/crab/gba/thumb/multiple_load_store.cr @@ -1,6 +1,6 @@ module GBA module THUMB - def thumb_multiple_load_store(instr : Word) : Nil + def thumb_multiple_load_store(instr : UInt32) : Nil load = bit?(instr, 11) rb = bits(instr, 8..10) list = bits(instr, 0..7) diff --git a/src/crab/gba/thumb/pc_relative_load.cr b/src/crab/gba/thumb/pc_relative_load.cr index baeed02..6b5a1d2 100644 --- a/src/crab/gba/thumb/pc_relative_load.cr +++ b/src/crab/gba/thumb/pc_relative_load.cr @@ -1,6 +1,6 @@ module GBA module THUMB - def thumb_pc_relative_load(instr : Word) : Nil + def thumb_pc_relative_load(instr : UInt32) : Nil imm = bits(instr, 0..7) rd = bits(instr, 8..10) set_reg(rd, @gba.bus.read_word((@r[15] & ~2) &+ (imm << 2))) diff --git a/src/crab/gba/thumb/push_pop_registers.cr b/src/crab/gba/thumb/push_pop_registers.cr index 7c5bf47..178ad7b 100644 --- a/src/crab/gba/thumb/push_pop_registers.cr +++ b/src/crab/gba/thumb/push_pop_registers.cr @@ -1,6 +1,6 @@ module GBA module THUMB - def thumb_push_pop_registers(instr : Word) : Nil + def thumb_push_pop_registers(instr : UInt32) : Nil pop = bit?(instr, 11) pclr = bit?(instr, 8) list = bits(instr, 0..7) diff --git a/src/crab/gba/thumb/software_interrupt.cr b/src/crab/gba/thumb/software_interrupt.cr index 7a2252c..3b24045 100644 --- a/src/crab/gba/thumb/software_interrupt.cr +++ b/src/crab/gba/thumb/software_interrupt.cr @@ -1,6 +1,6 @@ module GBA module THUMB - def thumb_software_interrupt(instr : Word) : Nil + def thumb_software_interrupt(instr : UInt32) : Nil lr = @r[15] - 2 switch_mode CPU::Mode::SVC set_reg(14, lr) diff --git a/src/crab/gba/thumb/sp_relative_load_store.cr b/src/crab/gba/thumb/sp_relative_load_store.cr index c3cca2b..0946cb5 100644 --- a/src/crab/gba/thumb/sp_relative_load_store.cr +++ b/src/crab/gba/thumb/sp_relative_load_store.cr @@ -1,6 +1,6 @@ module GBA module THUMB - def thumb_sp_relative_load_store(instr : Word) : Nil + def thumb_sp_relative_load_store(instr : UInt32) : Nil load = bit?(instr, 11) rd = bits(instr, 8..10) word = bits(instr, 0..7) diff --git a/src/crab/gba/thumb/thumb.cr b/src/crab/gba/thumb/thumb.cr index 3f9bbf9..9bbe839 100644 --- a/src/crab/gba/thumb/thumb.cr +++ b/src/crab/gba/thumb/thumb.cr @@ -1,56 +1,56 @@ module GBA module THUMB - def thumb_execute(instr : Word) : Nil + def thumb_execute(instr : UInt32) : Nil thumb_lut[instr >> 8].call instr end def fill_thumb_lut - lut = Slice(Proc(Word, Nil)).new 256, ->thumb_unimplemented(Word) + lut = Slice(Proc(UInt32, Nil)).new 256, ->thumb_unimplemented(UInt32) 256.times do |idx| if idx & 0b11110000 == 0b11110000 - lut[idx] = ->thumb_long_branch_link(Word) + lut[idx] = ->thumb_long_branch_link(UInt32) elsif idx & 0b11111000 == 0b11100000 - lut[idx] = ->thumb_unconditional_branch(Word) + lut[idx] = ->thumb_unconditional_branch(UInt32) elsif idx & 0b11111111 == 0b11011111 - lut[idx] = ->thumb_software_interrupt(Word) + lut[idx] = ->thumb_software_interrupt(UInt32) elsif idx & 0b11110000 == 0b11010000 - lut[idx] = ->thumb_conditional_branch(Word) + lut[idx] = ->thumb_conditional_branch(UInt32) elsif idx & 0b11110000 == 0b11000000 - lut[idx] = ->thumb_multiple_load_store(Word) + lut[idx] = ->thumb_multiple_load_store(UInt32) elsif idx & 0b11110110 == 0b10110100 - lut[idx] = ->thumb_push_pop_registers(Word) + lut[idx] = ->thumb_push_pop_registers(UInt32) elsif idx & 0b11111111 == 0b10110000 - lut[idx] = ->thumb_add_offset_to_stack_pointer(Word) + lut[idx] = ->thumb_add_offset_to_stack_pointer(UInt32) elsif idx & 0b11110000 == 0b10100000 - lut[idx] = ->thumb_load_address(Word) + lut[idx] = ->thumb_load_address(UInt32) elsif idx & 0b11110000 == 0b10010000 - lut[idx] = ->thumb_sp_relative_load_store(Word) + lut[idx] = ->thumb_sp_relative_load_store(UInt32) elsif idx & 0b11110000 == 0b10000000 - lut[idx] = ->thumb_load_store_halfword(Word) + lut[idx] = ->thumb_load_store_UInt16(UInt32) elsif idx & 0b11100000 == 0b01100000 - lut[idx] = ->thumb_load_store_immediate_offset(Word) + lut[idx] = ->thumb_load_store_immediate_offset(UInt32) elsif idx & 0b11110010 == 0b01010010 - lut[idx] = ->thumb_load_store_sign_extended(Word) + lut[idx] = ->thumb_load_store_sign_extended(UInt32) elsif idx & 0b11110010 == 0b01010000 - lut[idx] = ->thumb_load_store_register_offset(Word) + lut[idx] = ->thumb_load_store_register_offset(UInt32) elsif idx & 0b11111000 == 0b01001000 - lut[idx] = ->thumb_pc_relative_load(Word) + lut[idx] = ->thumb_pc_relative_load(UInt32) elsif idx & 0b11111100 == 0b01000100 - lut[idx] = ->thumb_high_reg_branch_exchange(Word) + lut[idx] = ->thumb_high_reg_branch_exchange(UInt32) elsif idx & 0b11111100 == 0b01000000 - lut[idx] = ->thumb_alu_operations(Word) + lut[idx] = ->thumb_alu_operations(UInt32) elsif idx & 0b11100000 == 0b00100000 - lut[idx] = ->thumb_move_compare_add_subtract(Word) + lut[idx] = ->thumb_move_compare_add_subtract(UInt32) elsif idx & 0b11111000 == 0b00011000 - lut[idx] = ->thumb_add_subtract(Word) + lut[idx] = ->thumb_add_subtract(UInt32) elsif idx & 0b11100000 == 0b00000000 - lut[idx] = ->thumb_move_shifted_register(Word) + lut[idx] = ->thumb_move_shifted_register(UInt32) end end lut end - def thumb_unimplemented(instr : Word) : Nil + def thumb_unimplemented(instr : UInt32) : Nil abort "Unimplemented instruction: #{hex_str instr.to_u16}" end end diff --git a/src/crab/gba/thumb/unconditional_branch.cr b/src/crab/gba/thumb/unconditional_branch.cr index eda6c52..914c93b 100644 --- a/src/crab/gba/thumb/unconditional_branch.cr +++ b/src/crab/gba/thumb/unconditional_branch.cr @@ -1,6 +1,6 @@ module GBA module THUMB - def thumb_unconditional_branch(instr : Word) : Nil + def thumb_unconditional_branch(instr : UInt32) : Nil offset = bits(instr, 0..10) offset = (offset << 5).to_i16! >> 4 set_reg(15, @r[15] &+ offset) diff --git a/src/crab/gba/timer.cr b/src/crab/gba/timer.cr index 158338d..0ce3d3e 100644 --- a/src/crab/gba/timer.cr +++ b/src/crab/gba/timer.cr @@ -51,7 +51,7 @@ module GBA @cycle_enabled[num] = @gba.scheduler.cycles end - def [](io_addr : Int) : UInt8 + def [](io_addr : UInt32) : UInt8 num = (io_addr & 0xF) // 4 value = if bit?(io_addr, 1) @tmcnt[num].value @@ -62,7 +62,7 @@ module GBA value.to_u8! end - def []=(io_addr : Int, value : UInt8) : Nil + def []=(io_addr : UInt32, value : UInt8) : Nil num = (io_addr & 0xF) // 4 high = bit?(io_addr, 0) mask = 0xFF00_u16 diff --git a/src/crab/gba/types.cr b/src/crab/gba/types.cr deleted file mode 100644 index 2db8de9..0000000 --- a/src/crab/gba/types.cr +++ /dev/null @@ -1,6 +0,0 @@ -module GBA - alias Byte = UInt8 - alias HalfWord = UInt16 - alias Word = UInt32 - alias Words = Slice(UInt32) -end