edea

A ps1 emulator in harelang
Log | Files | Refs

interconnect.ha (6656B)


      1 use bios;
      2 use fmt;
      3 use util;
      4 use ram;
      5 
      6 export type Interconnect = struct {
      7 	bios: bios::BIOS,
      8 	ram: ram::ram,
      9 };
     10 
     11 export fn new(bios: bios::BIOS, ram: ram::ram) Interconnect = {
     12 	return Interconnect {
     13 		bios = bios,
     14 		ram = ram
     15 	};
     16 };
     17 
     18 export fn store32(inter: Interconnect, addr: u32, val: u32) void = {
     19 
     20 	if (addr % 4 != 0)
     21 		fmt::fatalf("Unaligned load32 address: {:.08X}", addr);
     22 
     23 	let abs_addr = util::mask_region(addr);
     24 
     25 	match(util::contains(util::MEMCONTROL_START: u32, util::MEMCONTROL_SIZE: u32, abs_addr)) {
     26 	case let off: u32 =>
     27 		switch (off) {
     28 		case 0 =>
     29 			if (val != 0x1f000000)
     30 				fmt::fatalf("Bad expansion 1 base address: {:.08X}", val);
     31 		case 4 =>
     32 			if (val != 0x1f802000)
     33 				fmt::fatalf("Bad expansion 2 base address: {:.08X}", val);
     34 		case =>
     35 			fmt::println("Unhandled write to MEMCONTROL Register")!;
     36 
     37 		};
     38 		return;
     39 	case void => yield;
     40 	};
     41 
     42 	match(util::contains(util::RAM_SIZE_START: u32, util::RAM_SIZE_SIZE: u32, abs_addr)) {
     43 	case let off: u32 => fmt::println("Unhandled write to RAM SIZE register")!; return;
     44 	case void => yield;
     45 	};
     46 
     47 	match(util::contains(util::CACHE_CONTROL_START: u32, util::CACHE_CONTROL_SIZE: u32, abs_addr)) {
     48 	case let off: u32 => fmt::println("Unhandled write to CACHE CONTROL register")!; return;
     49 	case void => yield;
     50 	};
     51 
     52 	match(util::contains(util::RAM_START: u32, util::RAM_SIZE: u32, abs_addr)) {
     53 	case let off: u32 => ram::store32(inter.ram, off, val); return;
     54 	case void => yield;
     55 	};
     56 
     57 	match(util::contains(util::IRQ_CONTROL_START: u32, util::IRQ_CONTROL_SIZE: u32, abs_addr)) {
     58 	case let off: u32 => fmt::printfln("IRQ control: {:.08X} <- {:X}", off, val)!; return;
     59 	case void => yield;
     60 	};
     61 
     62 	match(util::contains(util::DMA_START: u32, util::DMA_SIZE: u32, abs_addr)) {
     63 	case let off: u32 => fmt::printfln("DMA write: {:.08X} <- {:X}", abs_addr, val)!; return;
     64 	case void => yield;
     65 	};
     66 
     67 	match(util::contains(util::GPU_START: u32, util::GPU_SIZE: u32, abs_addr)) {
     68 	case let off: u32 => fmt::printfln("GPU write: {:.08X} <- {:X}", off, val)!; return;
     69 	case void => yield;
     70 	};
     71 
     72 	match(util::contains(util::TIMERS_START: u32, util::TIMERS_SIZE: u32, abs_addr)) {
     73 	case let off: u32 => fmt::printfln("Timer register write: {:.08X} <- {:X}", off, val)!; return;
     74 	case void => yield;
     75 	};
     76 
     77 	fmt::fatalf("Unhandled store32 into address {:.08X}", abs_addr);
     78 };
     79 
     80 export fn store16(inter: Interconnect, addr: u32, val: u16) void = {
     81 
     82 	if (addr % 2 != 0)
     83 		fmt::fatalf("Unaligned store16 address: {:.08X}", addr);
     84 
     85 	let abs_addr = util::mask_region(addr);
     86 
     87 	match(util::contains(util::SPU_START: u32, util::SPU_SIZE: u32, abs_addr)) {
     88 	case let off: u32 =>
     89 		if (util::DEBUG) fmt::printfln("Unhandled write to SPU register {:X}", off)!; return;
     90 	case void => yield;
     91 	};
     92 
     93 	match(util::contains(util::TIMERS_START: u32, util::TIMERS_SIZE: u32, abs_addr)) {
     94 	case let off: u32 =>
     95 		if (util::DEBUG) fmt::printfln("Unhandled write to Timer register {:X}", off)!; return;
     96 	case void => yield;
     97 	};
     98 
     99 	match(util::contains(util::RAM_START: u32, util::RAM_SIZE: u32, abs_addr)) {
    100 	case let off: u32 => ram::store16(inter.ram, off, val); return;
    101 	case void => yield;
    102 	};
    103 
    104 	match(util::contains(util::IRQ_CONTROL_START: u32, util::IRQ_CONTROL_SIZE: u32, abs_addr)) {
    105 	case let off: u32 =>
    106 		if (util::DEBUG) fmt::printfln("IRQ control write: {:X} <- {:.04X}", off, val)!; 
    107 		return;
    108 	case void => yield;
    109 	};
    110 
    111 	fmt::fatalf("Unhandled store16 into address {:.08X}", abs_addr);
    112 };
    113 
    114 export fn store8(inter: Interconnect, addr: u32, val: u8) void = {
    115 
    116 	let abs_addr = util::mask_region(addr);
    117 
    118 	match(util::contains(util::EXPANSION_2_START: u32, util::EXPANSION_2_SIZE: u32, abs_addr)) {
    119 	case let off: u32 =>
    120 		fmt::printfln("Unhandled write to Expansion 2 register {:X}", off)!; return;
    121 	case void => yield;
    122 	};
    123 
    124 	match(util::contains(util::RAM_START: u32, util::RAM_SIZE: u32, abs_addr)) {
    125 	case let off: u32 =>
    126 		return ram::store8(inter.ram, off, val);
    127 	case void => yield;
    128 	};
    129 
    130 	fmt::fatalf("Unhandled store8 into address {:.08X}", addr);
    131 };
    132 
    133 export fn load32(inter: Interconnect, addr: u32) u32 = {
    134 	if (addr % 4 != 0)
    135 		fmt::fatalf("Unaligned store32 into address {:.08X}", addr);
    136 
    137 	let abs_addr = util::mask_region(addr);
    138 
    139 	match(util::contains(util::BIOS_START: u32, util::BIOS_SIZE: u32, abs_addr)) {
    140 	case let off: u32 =>
    141 		return bios::load32(inter.bios, off);
    142 	case void =>
    143 		yield;
    144 	};
    145 
    146 	match(util::contains(util::RAM_START: u32, util::RAM_SIZE: u32, abs_addr)) {
    147 	case let off: u32 =>
    148 		return ram::load32(inter.ram, off);
    149 	case void =>
    150 		yield;
    151 	};
    152 
    153 	match(util::contains(util::IRQ_CONTROL_START: u32, util::IRQ_CONTROL_SIZE: u32, abs_addr)) {
    154 	case let off: u32 =>
    155 		fmt::printfln("IRQ control read {:X}", off)!; return 0;
    156 	case void =>
    157 		yield;
    158 	};
    159 
    160 	match(util::contains(util::DMA_START: u32, util::DMA_SIZE: u32, abs_addr)) {
    161 	case let off: u32 =>
    162 		fmt::printfln("DMA read {:X}", abs_addr)!; return 0;
    163 	case void =>
    164 		yield;
    165 	};
    166 
    167 	match(util::contains(util::GPU_START: u32, util::GPU_SIZE: u32, abs_addr)) {
    168 	case let off: u32 =>
    169 		fmt::printfln("GPU read {:X}", off)!; 
    170 		let bit: u32 = switch(off) {
    171 		case 4 => yield 0x10000000;
    172 		case => yield 0;
    173 		};
    174 
    175 		return bit;
    176 	case void =>
    177 		yield;
    178 	};
    179 
    180 	fmt::fatalf("Unhandled fetch32 at address {:.08X}", abs_addr);
    181 };
    182 
    183 export fn load16(inter: Interconnect, addr: u32) u16 = {
    184 	let abs_addr = util::mask_region(addr);
    185 
    186 	match(util::contains(util::SPU_START: u32, util::SPU_SIZE: u32, abs_addr)) {
    187 	case let off: u32 =>
    188 		if (util::DEBUG) fmt::printfln("Unhandled read from SPU register: {:.08X}", abs_addr)!; return 0;
    189 	case void =>
    190 		yield;
    191 	};
    192 
    193 	match(util::contains(util::RAM_START: u32, util::RAM_SIZE: u32, abs_addr)) {
    194 	case let off: u32 =>
    195 		return ram::load16(inter.ram, off);
    196 	case void =>
    197 		yield;
    198 	};
    199 
    200 	match(util::contains(util::IRQ_CONTROL_START: u32, util::IRQ_CONTROL_SIZE: u32, abs_addr)) {
    201 	case let off: u32 =>
    202 		fmt::printfln("IRQ control read: {:.08X}", off)!; return 0;
    203 	case void =>
    204 		yield;
    205 	};
    206 
    207 	fmt::fatalf("Unhandled fetch16 at address {:.08X}", abs_addr);
    208 };
    209 
    210 export fn load8(inter: Interconnect, addr: u32) u8 = {
    211 	let abs_addr = util::mask_region(addr);
    212 
    213 	match(util::contains(util::BIOS_START: u32, util::BIOS_SIZE: u32, abs_addr)) {
    214 	case let off: u32 =>
    215 		return bios::load8(inter.bios, off);
    216 	case void =>
    217 		yield;
    218 	};
    219 
    220 	match(util::contains(util::RAM_START: u32, util::RAM_SIZE: u32, abs_addr)) {
    221 	case let off: u32 =>
    222 		return ram::load8(inter.ram, off);
    223 	case void =>
    224 		yield;
    225 	};
    226 
    227 	match(util::contains(util::EXPANSION_1_START: u32, util::EXPANSION_1_SIZE: u32, abs_addr)) {
    228 	case let off: u32 =>
    229 		return 0xff;
    230 	case void =>
    231 		yield;
    232 	};
    233 
    234 	fmt::fatalf("Unhandled fetch8 at address {:.08X}", abs_addr);
    235 };