1 #include <stdint.h>
2 #include <stdbool.h>
3
4 #include "pxa260/pxa260.h"
5 #include "pxa260/pxa260_DMA.h"
6 #include "pxa260/pxa260_DSP.h"
7 #include "pxa260/pxa260_GPIO.h"
8 #include "pxa260/pxa260_IC.h"
9 #include "pxa260/pxa260_LCD.h"
10 #include "pxa260/pxa260_PwrClk.h"
11 #include "pxa260/pxa260_RTC.h"
12 #include "pxa260/pxa260_TIMR.h"
13 #include "pxa260/pxa260_UART.h"
14 #include "pxa260/pxa260I2c.h"
15 #include "pxa260/pxa260Memctrl.h"
16 #include "pxa260/pxa260Ssp.h"
17 #include "pxa260/pxa260Udc.h"
18 #include "pxa260/pxa260Timing.h"
19 #if !defined(EMU_NO_SAFETY)
20 #include "armv5te/uArm/CPU_2.h"
21 #include "armv5te/uArm/uArmGlue.h"
22 #endif
23 #include "armv5te/cpu.h"
24 #include "armv5te/emu.h"
25 #include "armv5te/mem.h"
26 #include "armv5te/mmu.h"
27 #include "armv5te/os/os.h"
28 #include "armv5te/translate.h"
29 #include "tungstenT3Bus.h"
30 #include "tsc2101.h"
31 #include "tps65010.h"
32 #include "emulator.h"
33
34
35 #define PXA260_IO_BASE 0x40000000
36 #define PXA260_MEMCTRL_BASE 0x48000000
37
38 #define PXA260_TIMER_TICKS_PER_FRAME (TUNGSTEN_T3_CPU_CRYSTAL_FREQUENCY / EMU_FPS)
39
40 #if !defined(EMU_NO_SAFETY)
41 ArmCpu pxa260CpuState;
42 #endif
43 uint16_t* pxa260Framebuffer;
44 Pxa260pwrClk pxa260PwrClk;
45 Pxa260ic pxa260Ic;
46 Pxa260gpio pxa260Gpio;
47 Pxa260timr pxa260Timer;
48
49 static Pxa260lcd pxa260Lcd;
50
51
52 #include "pxa260/pxa260Accessors.c.h"
53
pxa260Init(uint8_t ** returnRom,uint8_t ** returnRam)54 bool pxa260Init(uint8_t** returnRom, uint8_t** returnRam){
55 uint32_t mem_offset = 0;
56 uint8_t i;
57
58 //set timing callback pointers
59 pxa260TimingInit();
60
61 //enable dynarec if available
62 do_translate = true;
63
64 mem_and_flags = os_reserve(MEM_MAXSIZE * 2);
65 if(!mem_and_flags)
66 return false;
67
68 addr_cache_init();
69 memset(mem_areas, 0x00, sizeof(mem_areas));
70
71 //regions
72 //ROM
73 mem_areas[0].base = PXA260_ROM_START_ADDRESS;
74 mem_areas[0].size = TUNGSTEN_T3_ROM_SIZE;
75 mem_areas[0].ptr = mem_and_flags + mem_offset;
76 mem_offset += TUNGSTEN_T3_ROM_SIZE;
77
78 //RAM
79 mem_areas[1].base = PXA260_RAM_START_ADDRESS;
80 mem_areas[1].size = TUNGSTEN_T3_RAM_SIZE;
81 mem_areas[1].ptr = mem_and_flags + mem_offset;
82 mem_offset += TUNGSTEN_T3_RAM_SIZE;
83
84 //memory regions that are not directly mapped to a buffer are not added to mem_areas
85 //adding them causes SIGSEGVs
86
87 //accessors
88 //default
89 for(i = 0; i < PXA260_TOTAL_MEMORY_BANKS; i++){
90 // will fallback to bad_* on non-memory addresses
91 read_byte_map[i] = memory_read_byte;
92 read_half_map[i] = memory_read_half;
93 read_word_map[i] = memory_read_word;
94 write_byte_map[i] = memory_write_byte;
95 write_half_map[i] = memory_write_half;
96 write_word_map[i] = memory_write_word;
97 }
98
99 //PCMCIA0
100 for(i = PXA260_START_BANK(PXA260_PCMCIA0_START_ADDRESS); i <= PXA260_END_BANK(PXA260_PCMCIA0_START_ADDRESS, PXA260_PCMCIA0_SIZE); i++){
101 read_byte_map[i] = pxa260_pcmcia0_read_byte;
102 read_half_map[i] = pxa260_pcmcia0_read_half;
103 read_word_map[i] = pxa260_pcmcia0_read_word;
104 write_byte_map[i] = pxa260_pcmcia0_write_byte;
105 write_half_map[i] = pxa260_pcmcia0_write_half;
106 write_word_map[i] = pxa260_pcmcia0_write_word;
107 }
108
109 //PCMCIA1
110 for(i = PXA260_START_BANK(PXA260_PCMCIA1_START_ADDRESS); i <= PXA260_END_BANK(PXA260_PCMCIA1_START_ADDRESS, PXA260_PCMCIA1_SIZE); i++){
111 read_byte_map[i] = pxa260_pcmcia1_read_byte;
112 read_half_map[i] = pxa260_pcmcia1_read_half;
113 read_word_map[i] = pxa260_pcmcia1_read_word;
114 write_byte_map[i] = pxa260_pcmcia1_write_byte;
115 write_half_map[i] = pxa260_pcmcia1_write_half;
116 write_word_map[i] = pxa260_pcmcia1_write_word;
117 }
118
119 //IO
120 read_byte_map[PXA260_START_BANK(PXA260_IO_BASE)] = pxa260_io_read_byte;
121 read_half_map[PXA260_START_BANK(PXA260_IO_BASE)] = pxa260_io_read_half;
122 read_word_map[PXA260_START_BANK(PXA260_IO_BASE)] = pxa260_io_read_word;
123 write_byte_map[PXA260_START_BANK(PXA260_IO_BASE)] = pxa260_io_write_byte;
124 write_half_map[PXA260_START_BANK(PXA260_IO_BASE)] = pxa260_io_write_half;
125 write_word_map[PXA260_START_BANK(PXA260_IO_BASE)] = pxa260_io_write_word;
126
127 //LCD
128 read_byte_map[PXA260_START_BANK(PXA260_LCD_BASE)] = bad_read_byte;
129 read_half_map[PXA260_START_BANK(PXA260_LCD_BASE)] = bad_read_half;
130 read_word_map[PXA260_START_BANK(PXA260_LCD_BASE)] = pxa260_lcd_read_word;
131 write_byte_map[PXA260_START_BANK(PXA260_LCD_BASE)] = bad_write_byte;
132 write_half_map[PXA260_START_BANK(PXA260_LCD_BASE)] = bad_write_half;
133 write_word_map[PXA260_START_BANK(PXA260_LCD_BASE)] = pxa260_lcd_write_word;
134
135 //MEMCTRL
136 read_byte_map[PXA260_START_BANK(PXA260_MEMCTRL_BASE)] = bad_read_byte;
137 read_half_map[PXA260_START_BANK(PXA260_MEMCTRL_BASE)] = bad_read_half;
138 read_word_map[PXA260_START_BANK(PXA260_MEMCTRL_BASE)] = pxa260MemctrlReadWord;
139 write_byte_map[PXA260_START_BANK(PXA260_MEMCTRL_BASE)] = bad_write_byte;
140 write_half_map[PXA260_START_BANK(PXA260_MEMCTRL_BASE)] = bad_write_half;
141 write_word_map[PXA260_START_BANK(PXA260_MEMCTRL_BASE)] = pxa260MemctrlWriteWord;
142
143 //W86L488
144 read_byte_map[PXA260_START_BANK(TUNGSTEN_T3_W86L488_START_ADDRESS)] = bad_read_byte;
145 read_half_map[PXA260_START_BANK(TUNGSTEN_T3_W86L488_START_ADDRESS)] = pxa260_static_chip_select_2_read_half;
146 read_word_map[PXA260_START_BANK(TUNGSTEN_T3_W86L488_START_ADDRESS)] = bad_read_word;
147 write_byte_map[PXA260_START_BANK(TUNGSTEN_T3_W86L488_START_ADDRESS)] = bad_write_byte;
148 write_half_map[PXA260_START_BANK(TUNGSTEN_T3_W86L488_START_ADDRESS)] = pxa260_static_chip_select_2_write_half;
149 write_word_map[PXA260_START_BANK(TUNGSTEN_T3_W86L488_START_ADDRESS)] = bad_write_word;
150
151 *returnRom = mem_areas[0].ptr;
152 *returnRam = mem_areas[1].ptr;
153
154 return true;
155 }
156
pxa260Deinit(void)157 void pxa260Deinit(void){
158 if(mem_and_flags){
159 // translation_table uses absolute addresses
160 flush_translations();
161 memset(mem_areas, 0, sizeof(mem_areas));
162 os_free(mem_and_flags, MEM_MAXSIZE * 2);
163 mem_and_flags = NULL;
164 }
165
166 addr_cache_deinit();
167 }
168
pxa260Reset(void)169 void pxa260Reset(void){
170 /*
171 static void emu_reset()
172 {
173 memset(mem_areas[1].ptr, 0, mem_areas[1].size);
174
175 memset(&arm, 0, sizeof arm);
176 arm.control = 0x00050078;
177 arm.cpsr_low28 = MODE_SVC | 0xC0;
178 cpu_events &= EVENT_DEBUG_STEP;
179
180 sched_reset();
181 sched.items[SCHED_THROTTLE].clock = CLOCK_27M;
182 sched.items[SCHED_THROTTLE].proc = throttle_interval_event;
183
184 memory_reset();
185 }
186 */
187
188 //set up extra CPU hardware
189 pxa260icInit(&pxa260Ic);
190 pxa260pwrClkInit(&pxa260PwrClk);
191 pxa260lcdInit(&pxa260Lcd, &pxa260Ic);
192 pxa260timrInit(&pxa260Timer, &pxa260Ic);
193 pxa260gpioInit(&pxa260Gpio, &pxa260Ic);
194 pxa260I2cReset();
195 pxa260MemctrlReset();
196 pxa260SspReset();
197 pxa260UdcReset();
198 pxa260TimingReset();
199
200 //set first timer event
201 pxa260TimingTriggerEvent(PXA260_TIMING_CALLBACK_TICK_CPU_TIMER, TUNGSTEN_T3_CPU_PLL_FREQUENCY / TUNGSTEN_T3_CPU_CRYSTAL_FREQUENCY);
202
203 #if !defined(EMU_NO_SAFETY)
204 debugLog("Using uARM CPU core!\n");
205 cpuInit(&pxa260CpuState, 0x00000000, uArmMemAccess, uArmEmulErr, uArmHypercall, uArmSetFaultAddr);
206 uArmInitCpXX(&pxa260CpuState);
207 #else
208 memset(&arm, 0, sizeof arm);
209 arm.control = 0x00050078;
210 arm.cpsr_low28 = MODE_SVC | 0xC0;
211 cycle_count_delta = 0;
212 cpu_events = 0;
213 //cpu_events &= EVENT_DEBUG_STEP;
214 #endif
215
216 addr_cache_flush();//SIGSEGVs on reset without this because the MMU needs to be turned off
217
218 //PC starts at 0x00000000, the first opcode for Palm OS 5 is a jump
219 }
220
pxa260SetRtc(uint16_t days,uint8_t hours,uint8_t minutes,uint8_t seconds)221 void pxa260SetRtc(uint16_t days, uint8_t hours, uint8_t minutes, uint8_t seconds){
222 //TODO: make this do something
223 }
224
pxa260StateSize(void)225 uint32_t pxa260StateSize(void){
226 uint32_t size = 0;
227
228 return size;
229 }
230
pxa260SaveState(uint8_t * data)231 void pxa260SaveState(uint8_t* data){
232 uint32_t offset = 0;
233
234 }
235
pxa260LoadState(uint8_t * data)236 void pxa260LoadState(uint8_t* data){
237 uint32_t offset = 0;
238
239 }
240
pxa260Execute(bool wantVideo)241 void pxa260Execute(bool wantVideo){
242 tsc2101UpdateInterrupt();
243 tps65010UpdateInterrupt();
244 pxa260gpioUpdateKeyMatrix(&pxa260Gpio);
245
246 pxa260TimingRun(TUNGSTEN_T3_CPU_PLL_FREQUENCY / EMU_FPS);
247
248 //render
249 if(likely(wantVideo))
250 pxa260lcdFrame(&pxa260Lcd);
251 }
252
pxa260GetRegister(uint8_t reg)253 uint32_t pxa260GetRegister(uint8_t reg){
254 #if !defined(EMU_NO_SAFETY)
255 return cpuGetRegExternal(&pxa260CpuState, reg);
256 #else
257 return reg_pc_mem(reg);
258 #endif
259 }
260
pxa260GetCpsr(void)261 uint32_t pxa260GetCpsr(void){
262 #if !defined(EMU_NO_SAFETY)
263 return cpuGetRegExternal(&pxa260CpuState, ARM_REG_NUM_CPSR);
264 #else
265 return get_cpsr();
266 #endif
267 }
268
pxa260GetSpsr(void)269 uint32_t pxa260GetSpsr(void){
270 #if !defined(EMU_NO_SAFETY)
271 return cpuGetRegExternal(&pxa260CpuState, ARM_REG_NUM_SPSR);
272 #else
273 return get_spsr();
274 #endif
275 }
276
pxa260ReadArbitraryMemory(uint32_t address,uint8_t size)277 uint64_t pxa260ReadArbitraryMemory(uint32_t address, uint8_t size){
278 uint64_t data = UINT64_MAX;//invalid access
279
280 address = mmu_translate(address, false, NULL, NULL);
281
282 switch(size){
283 case 8:
284 if(read_byte_map[address >> 26] != bad_read_byte){
285 data = read_byte_map[address >> 26](address);
286 }
287 break;
288
289 case 16:
290 if(read_half_map[address >> 26] != bad_read_half){
291 data = read_half_map[address >> 26](address);
292 }
293 break;
294
295 case 32:
296 if(read_word_map[address >> 26] != bad_read_word){
297 data = read_word_map[address >> 26](address);
298 }
299 break;
300 }
301
302 return data;
303 }
304