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