arm fix single data transfer imm offset, add mmio/interrupt writes

this hits the fps by ~15 for some reason on tonc's m3_demo...
This commit is contained in:
Matthew Berry 2020-10-07 08:19:14 -07:00
parent 9c166aca90
commit e29bde0bcf
6 changed files with 95 additions and 38 deletions

View file

@ -9,19 +9,19 @@ module ARM
load = bit?(instr, 20)
rn = bits(instr, 16..19)
rd = bits(instr, 12..15)
operand_2 = if imm_flag # Operand 2 is a register (opposite of data procesing for some reason)
rotate_register bits(instr, 0..11), set_conditions: false, allow_register_shifts: false
else # Operand 2 is an immediate offset
immediate_offset bits(instr, 0..11)
end
offset = if imm_flag # Operand 2 is a register (opposite of data processing for some reason)
rotate_register bits(instr, 0..11), set_conditions: false, allow_register_shifts: false
else # Operand 2 is an immediate offset
bits(instr, 0..11)
end
address = @r[rn]
if pre_indexing
if add_offset
address &+= operand_2
address &+= offset
else
address &-= operand_2
address &-= offset
end
end
@ -33,9 +33,9 @@ module ARM
if !pre_indexing
if add_offset
@r[rn] &+= operand_2
@r[rn] &+= offset
else
@r[rn] &-= operand_2
@r[rn] &-= offset
end
elsif write_back
@r[rn] = address

View file

@ -10,13 +10,7 @@ class Bus
case bits(index, 24..27)
when 0x2 then @wram_board[index & 0x3FFFF]
when 0x3 then @wram_chip[index & 0x7FFF]
when 0x4
io_addr = 0x0FFF_u16 & index
if io_addr <= 0x05F
@gba.ppu[index]
else
raise "Unmapped i/o read: #{hex_str index.to_u32}"
end
when 0x4 then @gba.mmio[index]
when 0x5 then @gba.ppu.pram[index]
when 0x6
address = 0x1FFFF_u32 & index
@ -45,13 +39,7 @@ class Bus
case bits(index, 24..27)
when 0x2 then @wram_board[index & 0x3FFFF] = value
when 0x3 then @wram_chip[index & 0x7FFF] = value
when 0x4
io_addr = 0x0FFF_u16 & index
if io_addr <= 0x05F
@gba.ppu[index] = value
else
raise "Unmapped i/o write: #{hex_str index.to_u32}"
end
when 0x4 then @gba.mmio[index] = value
when 0x5 then @gba.ppu.pram[index & 0x3FF] = value
when 0x6
address = 0x1FFFF_u32 & index

View file

@ -1,14 +1,18 @@
require "./types"
require "./util"
require "./cartridge"
require "./mmio"
require "./bus"
require "./interrupts"
require "./cpu"
require "./display"
require "./ppu"
class GBA
getter cartridge : Cartridge
getter mmio : MMIO { MMIO.new self }
getter bus : Bus { Bus.new self }
getter interrupts : Interrupts { Interrupts.new }
getter cpu : CPU { CPU.new self }
getter display : Display { Display.new }
getter ppu : PPU { PPU.new self }

29
src/crab/interrupts.cr Normal file
View file

@ -0,0 +1,29 @@
class Interrupts
getter reg_ie : UInt16 = 0
getter reg_if : UInt16 = 0
getter reg_ime : Bool = false
def read_io(io_addr : Int) : Byte
case io_addr
when 0x200 then (@reg_ie >> 8).to_u8
when 0x201 then @reg_ie.to_u8!
when 0x202 then (@reg_if >> 8).to_u8
when 0x203 then @reg_if.to_u8!
when 0x208 then @reg_ime ? 1_u8 : 0_u8
when 0x209 then @reg_ime ? 1_u8 : 0_u8
else raise "Unimplemented interrupts read ~ addr:#{hex_str io_addr.to_u8}"
end
end
def write_io(io_addr : Int, value : Byte) : Nil
case io_addr
when 0x200 then @reg_ie = (@reg_ie & 0x00FF) | value.to_u16 << 8
when 0x201 then @reg_ie = (@reg_ie & 0xFF00) | value
when 0x202 then @reg_ie = (@reg_if & 0x00FF) | value.to_u16 << 8
when 0x203 then @reg_ie = (@reg_if & 0xFF00) | value
when 0x208 then @reg_ime = bit?(value, 0)
when 0x209 then @reg_ime = bit?(value, 0)
else raise "Unimplemented interrupts write ~ addr:#{hex_str io_addr.to_u8!}, val:#{value}"
end
end
end

38
src/crab/mmio.cr Normal file
View file

@ -0,0 +1,38 @@
class MMIO
def initialize(@gba : GBA)
end
def [](index : Int) : Byte
io_addr = 0x0FFF_u16 & index
if io_addr <= 0x05F
@gba.ppu.read_io io_addr
elsif (io_addr >= 0x200 & io_addr <= 0x203) || (io_addr >= 0x208 && io_addr <= 0x209)
@gba.interrupts.read_io io_addr
elsif not_used? io_addr
0xFF_u8 # todo what is returned here?
else
raise "Unmapped MMIO read: #{hex_str index.to_u32}"
end
end
def []=(index : Int, value : Byte) : Nil
io_addr = 0x0FFF_u16 & index
if io_addr <= 0x05F
@gba.ppu.write_io io_addr, value
elsif (io_addr >= 0x200 && io_addr <= 0x203) || (io_addr >= 0x208 && io_addr <= 0x209)
@gba.interrupts.write_io io_addr, value
elsif not_used? io_addr
else
raise "Unmapped MMIO write: #{hex_str index.to_u32}"
end
end
def not_used?(io_addr : Int) : Bool
(0x0E0..0x0FE).includes?(io_addr) || (0x110..0x11E).includes?(io_addr) ||
(0x12C..0x12E).includes?(io_addr) || (0x138..0x13E).includes?(io_addr) ||
(0x142..0x14E).includes?(io_addr) || (0x15A..0x1FE).includes?(io_addr) ||
0x206 == io_addr || (0x20A..0x2FF).includes?(io_addr) ||
(0x302..0x40F).includes?(io_addr) || (0x441..0x7FF).includes?(io_addr) ||
(0x804..0xFFFF).includes?(io_addr)
end
end

View file

@ -28,7 +28,7 @@ class PPU
getter pram = Bytes.new 0x400
getter vram = Bytes.new 0x18000
@dispcnt : DISPCNT = DISPCNT.new 0
getter dispcnt : DISPCNT = DISPCNT.new 0
@cycles = 0
@ -43,23 +43,21 @@ class PPU
end
end
def [](index : Int) : Byte
case index
when 0x04000000 then (@dispcnt.value >> 8).to_u8
when 0x04000001 then @dispcnt.value.to_u8!
when 0x04000002 then 0_u8
when 0x04000003 then 0_u8
else raise "Unimplemented PPU read ~ addr:#{hex_str index.to_u32}"
def read_io(io_addr : Int) : Byte
case io_addr
when 0x000 then (@dispcnt.value >> 8).to_u8
when 0x001 then @dispcnt.value.to_u8!
else raise "Unimplemented PPU read ~ addr:#{hex_str io_addr.to_u8}"
end
end
def []=(index : Int, value : Byte) : Nil
case index
when 0x04000000 then @dispcnt.value = (@dispcnt.value & 0x00FF) | value.to_u16 << 8
when 0x04000001 then @dispcnt.value = (@dispcnt.value & 0xFF00) | value
when 0x04000002
when 0x04000003
else raise "Unimplemented PPU write ~ addr:#{hex_str index.to_u32}, val:#{value}"
def write_io(io_addr : Int, value : Byte) : Nil
case io_addr
when 0x000 then @dispcnt.value = (@dispcnt.value & 0x00FF) | value.to_u16 << 8
when 0x001 then @dispcnt.value = (@dispcnt.value & 0xFF00) | value
when 0x002 # undocumented - green swap
when 0x003 # undocumented - green swap
else raise "Unimplemented PPU write ~ addr:#{hex_str io_addr.to_u8}, val:#{value}"
end
end
end