From 120abb5261ece742a8e39ccaf43ce8e7b5eac093 Mon Sep 17 00:00:00 2001 From: Matthew Berry Date: Fri, 18 Nov 2022 17:13:03 -0800 Subject: [PATCH] use a different Slice constructor for luts --- src/crab/gba/arm/arm.cr | 59 ++++++++++++--------------------- src/crab/gba/thumb/thumb.cr | 66 ++++++++++++++----------------------- 2 files changed, 45 insertions(+), 80 deletions(-) diff --git a/src/crab/gba/arm/arm.cr b/src/crab/gba/arm/arm.cr index f263d79..2f1a946 100644 --- a/src/crab/gba/arm/arm.cr +++ b/src/crab/gba/arm/arm.cr @@ -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 diff --git a/src/crab/gba/thumb/thumb.cr b/src/crab/gba/thumb/thumb.cr index 603cc25..87cfabc 100644 --- a/src/crab/gba/thumb/thumb.cr +++ b/src/crab/gba/thumb/thumb.cr @@ -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