use a different Slice constructor for luts

This commit is contained in:
Matthew Berry 2022-11-18 17:13:03 -08:00
parent 37dcb6fcca
commit 120abb5261
2 changed files with 45 additions and 80 deletions

View file

@ -20,49 +20,32 @@ module GBA
end
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(UInt32)
elsif idx & 0b111100000001 == 0b111000000001
# coprocessor register transfer
elsif idx & 0b111100000001 == 0b111000000001
# coprocessor data operation
elsif idx & 0b111000000000 == 0b110000000000
# coprocessor data transfer
elsif idx & 0b111000000000 == 0b101000000000
lut[idx] = ->arm_branch(UInt32)
elsif idx & 0b111000000000 == 0b100000000000
lut[idx] = ->arm_block_data_transfer(UInt32)
elsif idx & 0b111000000001 == 0b011000000001
# undefined
elsif idx & 0b110000000000 == 0b010000000000
lut[idx] = ->arm_single_data_transfer(UInt32)
elsif idx & 0b111111111111 == 0b000100100001
lut[idx] = ->arm_branch_exchange(UInt32)
elsif idx & 0b111110111111 == 0b000100001001
lut[idx] = ->arm_single_data_swap(UInt32)
elsif idx & 0b111110001111 == 0b000010001001
lut[idx] = ->arm_multiply_long(UInt32)
elsif idx & 0b111111001111 == 0b000000001001
lut[idx] = ->arm_multiply(UInt32)
elsif idx & 0b111001001001 == 0b000001001001
lut[idx] = ->arm_halfword_data_transfer_immediate(UInt32)
elsif idx & 0b111001001001 == 0b000000001001
lut[idx] = ->arm_halfword_data_transfer_register(UInt32)
elsif idx & 0b110110010000 == 0b000100000000
lut[idx] = ->arm_psr_transfer(UInt32)
elsif idx & 0b110000000000 == 0b000000000000
lut[idx] = ->arm_data_processing(UInt32)
else
lut[idx] = ->arm_unused(UInt32)
Slice(Proc(UInt32, Nil)).new(4096) do |idx|
case
when idx & 0b111100000000 == 0b111100000000 then ->arm_software_interrupt(UInt32)
when idx & 0b111100000001 == 0b111000000001 then ->arm_unimplemented(UInt32) # coprocessor register transfer
when idx & 0b111100000001 == 0b111000000001 then ->arm_unimplemented(UInt32) # coprocessor data operation
when idx & 0b111000000000 == 0b110000000000 then ->arm_unimplemented(UInt32) # coprocessor data transfer
when idx & 0b111000000000 == 0b101000000000 then ->arm_branch(UInt32)
when idx & 0b111000000000 == 0b100000000000 then ->arm_block_data_transfer(UInt32)
when idx & 0b111000000001 == 0b011000000001 then ->arm_unimplemented(UInt32) # undefined
when idx & 0b110000000000 == 0b010000000000 then ->arm_single_data_transfer(UInt32)
when idx & 0b111111111111 == 0b000100100001 then ->arm_branch_exchange(UInt32)
when idx & 0b111110111111 == 0b000100001001 then ->arm_single_data_swap(UInt32)
when idx & 0b111110001111 == 0b000010001001 then ->arm_multiply_long(UInt32)
when idx & 0b111111001111 == 0b000000001001 then ->arm_multiply(UInt32)
when idx & 0b111001001001 == 0b000001001001 then ->arm_halfword_data_transfer_immediate(UInt32)
when idx & 0b111001001001 == 0b000000001001 then ->arm_halfword_data_transfer_register(UInt32)
when idx & 0b110110010000 == 0b000100000000 then ->arm_psr_transfer(UInt32)
when idx & 0b110000000000 == 0b000000000000 then ->arm_data_processing(UInt32)
else ->arm_unused(UInt32)
end
end
lut
end
def arm_unimplemented(instr : UInt32) : Nil
abort "Unimplemented instruction: #{hex_str instr}"
# "if true" is a hack until https://github.com/crystal-lang/crystal/issues/12758 is patched
abort "Unimplemented instruction: #{hex_str instr}" if true
end
def arm_unused(instr : UInt32) : Nil

View file

@ -5,53 +5,35 @@ module GBA
end
def fill_thumb_lut
lut = Slice(Proc(UInt32, Nil)).new 256, ->thumb_unimplemented(UInt32)
256.times do |idx|
if idx & 0b11110000 == 0b11110000
lut[idx] = ->thumb_long_branch_link(UInt32)
elsif idx & 0b11111000 == 0b11100000
lut[idx] = ->thumb_unconditional_branch(UInt32)
elsif idx & 0b11111111 == 0b11011111
lut[idx] = ->thumb_software_interrupt(UInt32)
elsif idx & 0b11110000 == 0b11010000
lut[idx] = ->thumb_conditional_branch(UInt32)
elsif idx & 0b11110000 == 0b11000000
lut[idx] = ->thumb_multiple_load_store(UInt32)
elsif idx & 0b11110110 == 0b10110100
lut[idx] = ->thumb_push_pop_registers(UInt32)
elsif idx & 0b11111111 == 0b10110000
lut[idx] = ->thumb_add_offset_to_stack_pointer(UInt32)
elsif idx & 0b11110000 == 0b10100000
lut[idx] = ->thumb_load_address(UInt32)
elsif idx & 0b11110000 == 0b10010000
lut[idx] = ->thumb_sp_relative_load_store(UInt32)
elsif idx & 0b11110000 == 0b10000000
lut[idx] = ->thumb_load_store_halfword(UInt32)
elsif idx & 0b11100000 == 0b01100000
lut[idx] = ->thumb_load_store_immediate_offset(UInt32)
elsif idx & 0b11110010 == 0b01010010
lut[idx] = ->thumb_load_store_sign_extended(UInt32)
elsif idx & 0b11110010 == 0b01010000
lut[idx] = ->thumb_load_store_register_offset(UInt32)
elsif idx & 0b11111000 == 0b01001000
lut[idx] = ->thumb_pc_relative_load(UInt32)
elsif idx & 0b11111100 == 0b01000100
lut[idx] = ->thumb_high_reg_branch_exchange(UInt32)
elsif idx & 0b11111100 == 0b01000000
lut[idx] = ->thumb_alu_operations(UInt32)
elsif idx & 0b11100000 == 0b00100000
lut[idx] = ->thumb_move_compare_add_subtract(UInt32)
elsif idx & 0b11111000 == 0b00011000
lut[idx] = ->thumb_add_subtract(UInt32)
elsif idx & 0b11100000 == 0b00000000
lut[idx] = ->thumb_move_shifted_register(UInt32)
Slice(Proc(UInt32, Nil)).new(256) do |idx|
case
when idx & 0b11110000 == 0b11110000 then ->thumb_long_branch_link(UInt32)
when idx & 0b11111000 == 0b11100000 then ->thumb_unconditional_branch(UInt32)
when idx & 0b11111111 == 0b11011111 then ->thumb_software_interrupt(UInt32)
when idx & 0b11110000 == 0b11010000 then ->thumb_conditional_branch(UInt32)
when idx & 0b11110000 == 0b11000000 then ->thumb_multiple_load_store(UInt32)
when idx & 0b11110110 == 0b10110100 then ->thumb_push_pop_registers(UInt32)
when idx & 0b11111111 == 0b10110000 then ->thumb_add_offset_to_stack_pointer(UInt32)
when idx & 0b11110000 == 0b10100000 then ->thumb_load_address(UInt32)
when idx & 0b11110000 == 0b10010000 then ->thumb_sp_relative_load_store(UInt32)
when idx & 0b11110000 == 0b10000000 then ->thumb_load_store_halfword(UInt32)
when idx & 0b11100000 == 0b01100000 then ->thumb_load_store_immediate_offset(UInt32)
when idx & 0b11110010 == 0b01010010 then ->thumb_load_store_sign_extended(UInt32)
when idx & 0b11110010 == 0b01010000 then ->thumb_load_store_register_offset(UInt32)
when idx & 0b11111000 == 0b01001000 then ->thumb_pc_relative_load(UInt32)
when idx & 0b11111100 == 0b01000100 then ->thumb_high_reg_branch_exchange(UInt32)
when idx & 0b11111100 == 0b01000000 then ->thumb_alu_operations(UInt32)
when idx & 0b11100000 == 0b00100000 then ->thumb_move_compare_add_subtract(UInt32)
when idx & 0b11111000 == 0b00011000 then ->thumb_add_subtract(UInt32)
when idx & 0b11100000 == 0b00000000 then ->thumb_move_shifted_register(UInt32)
else ->thumb_unimplemented(UInt32)
end
end
lut
end
def thumb_unimplemented(instr : UInt32) : Nil
abort "Unimplemented instruction: #{hex_str instr.to_u16}"
# "if true" is a hack until https://github.com/crystal-lang/crystal/issues/12758 is patched
abort "Unimplemented instruction: #{hex_str instr.to_u16}" if true
end
end
end