filename | src/sh4/sh4.c |
changeset | 1112:4cac5e474d4c |
prev | 1091:186558374345 |
next | 1125:9dd5dee45db9 |
author | nkeynes |
date | Fri Sep 10 08:50:55 2010 +1000 (13 years ago) |
permissions | -rw-r--r-- |
last change | Add missing sh4_translate_breakpoint_hit to the symbol table Change asm() to __asm__() as it's more likely to work |
view | annotate | diff | log | raw |
1 /**
2 * $Id$
3 *
4 * SH4 parent module for all CPU modes and SH4 peripheral
5 * modules.
6 *
7 * Copyright (c) 2005 Nathan Keynes.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
20 #define MODULE sh4_module
21 #include <math.h>
22 #include <setjmp.h>
23 #include <assert.h>
24 #include "lxdream.h"
25 #include "dreamcast.h"
26 #include "cpu.h"
27 #include "mem.h"
28 #include "clock.h"
29 #include "eventq.h"
30 #include "syscall.h"
31 #include "sh4/intc.h"
32 #include "sh4/mmu.h"
33 #include "sh4/sh4core.h"
34 #include "sh4/sh4dasm.h"
35 #include "sh4/sh4mmio.h"
36 #include "sh4/sh4stat.h"
37 #include "sh4/sh4trans.h"
38 #include "xlat/xltcache.h"
40 #ifndef M_PI
41 #define M_PI 3.14159265358979323846264338327950288
42 #endif
44 void sh4_init( void );
45 void sh4_poweron_reset( void );
46 void sh4_start( void );
47 void sh4_stop( void );
48 void sh4_save_state( FILE *f );
49 int sh4_load_state( FILE *f );
50 size_t sh4_debug_read_phys( unsigned char *buf, uint32_t addr, size_t length );
51 size_t sh4_debug_write_phys( uint32_t addr, unsigned char *buf, size_t length );
52 size_t sh4_debug_read_vma( unsigned char *buf, uint32_t addr, size_t length );
53 size_t sh4_debug_write_vma( uint32_t addr, unsigned char *buf, size_t length );
55 uint32_t sh4_run_slice( uint32_t );
57 /* Note: this must match GDB's ordering */
58 const struct reg_desc_struct sh4_reg_map[] =
59 { {"R0", REG_TYPE_INT, &sh4r.r[0]}, {"R1", REG_TYPE_INT, &sh4r.r[1]},
60 {"R2", REG_TYPE_INT, &sh4r.r[2]}, {"R3", REG_TYPE_INT, &sh4r.r[3]},
61 {"R4", REG_TYPE_INT, &sh4r.r[4]}, {"R5", REG_TYPE_INT, &sh4r.r[5]},
62 {"R6", REG_TYPE_INT, &sh4r.r[6]}, {"R7", REG_TYPE_INT, &sh4r.r[7]},
63 {"R8", REG_TYPE_INT, &sh4r.r[8]}, {"R9", REG_TYPE_INT, &sh4r.r[9]},
64 {"R10",REG_TYPE_INT, &sh4r.r[10]}, {"R11",REG_TYPE_INT, &sh4r.r[11]},
65 {"R12",REG_TYPE_INT, &sh4r.r[12]}, {"R13",REG_TYPE_INT, &sh4r.r[13]},
66 {"R14",REG_TYPE_INT, &sh4r.r[14]}, {"R15",REG_TYPE_INT, &sh4r.r[15]},
67 {"PC", REG_TYPE_INT, &sh4r.pc}, {"PR", REG_TYPE_INT, &sh4r.pr},
68 {"GBR", REG_TYPE_INT, &sh4r.gbr}, {"VBR",REG_TYPE_INT, &sh4r.vbr},
69 {"MACH",REG_TYPE_INT, ((uint32_t *)&sh4r.mac)+1}, {"MACL",REG_TYPE_INT, &sh4r.mac},
70 {"SR", REG_TYPE_INT, &sh4r.sr},
71 {"FPUL", REG_TYPE_INT, &sh4r.fpul.i}, {"FPSCR", REG_TYPE_INT, &sh4r.fpscr},
73 {"FR0", REG_TYPE_FLOAT, &sh4r.fr[0][1] },{"FR1", REG_TYPE_FLOAT, &sh4r.fr[0][0]},
74 {"FR2", REG_TYPE_FLOAT, &sh4r.fr[0][3] },{"FR3", REG_TYPE_FLOAT, &sh4r.fr[0][2]},
75 {"FR4", REG_TYPE_FLOAT, &sh4r.fr[0][5] },{"FR5", REG_TYPE_FLOAT, &sh4r.fr[0][4]},
76 {"FR6", REG_TYPE_FLOAT, &sh4r.fr[0][7] },{"FR7", REG_TYPE_FLOAT, &sh4r.fr[0][6]},
77 {"FR8", REG_TYPE_FLOAT, &sh4r.fr[0][9] },{"FR9", REG_TYPE_FLOAT, &sh4r.fr[0][8]},
78 {"FR10", REG_TYPE_FLOAT, &sh4r.fr[0][11] },{"FR11", REG_TYPE_FLOAT, &sh4r.fr[0][10]},
79 {"FR12", REG_TYPE_FLOAT, &sh4r.fr[0][13] },{"FR13", REG_TYPE_FLOAT, &sh4r.fr[0][12]},
80 {"FR14", REG_TYPE_FLOAT, &sh4r.fr[0][15] },{"FR15", REG_TYPE_FLOAT, &sh4r.fr[0][14]},
82 {"SSR",REG_TYPE_INT, &sh4r.ssr}, {"SPC", REG_TYPE_INT, &sh4r.spc},
84 {"R0B0", REG_TYPE_INT, NULL}, {"R1B0", REG_TYPE_INT, NULL},
85 {"R2B0", REG_TYPE_INT, NULL}, {"R3B0", REG_TYPE_INT, NULL},
86 {"R4B0", REG_TYPE_INT, NULL}, {"R5B0", REG_TYPE_INT, NULL},
87 {"R6B0", REG_TYPE_INT, NULL}, {"R7B0", REG_TYPE_INT, NULL},
88 {"R0B1", REG_TYPE_INT, NULL}, {"R1B1", REG_TYPE_INT, NULL},
89 {"R2B1", REG_TYPE_INT, NULL}, {"R3B1", REG_TYPE_INT, NULL},
90 {"R4B1", REG_TYPE_INT, NULL}, {"R5B1", REG_TYPE_INT, NULL},
91 {"R6B1", REG_TYPE_INT, NULL}, {"R7B1", REG_TYPE_INT, NULL},
93 {"SGR",REG_TYPE_INT, &sh4r.sgr}, {"DBR", REG_TYPE_INT, &sh4r.dbr},
95 {"XF0", REG_TYPE_FLOAT, &sh4r.fr[1][1] },{"XF1", REG_TYPE_FLOAT, &sh4r.fr[1][0]},
96 {"XF2", REG_TYPE_FLOAT, &sh4r.fr[1][3] },{"XF3", REG_TYPE_FLOAT, &sh4r.fr[1][2]},
97 {"XF4", REG_TYPE_FLOAT, &sh4r.fr[1][5] },{"XF5", REG_TYPE_FLOAT, &sh4r.fr[1][4]},
98 {"XF6", REG_TYPE_FLOAT, &sh4r.fr[1][7] },{"XF7", REG_TYPE_FLOAT, &sh4r.fr[1][6]},
99 {"XF8", REG_TYPE_FLOAT, &sh4r.fr[1][9] },{"XF9", REG_TYPE_FLOAT, &sh4r.fr[1][8]},
100 {"XF10", REG_TYPE_FLOAT, &sh4r.fr[1][11] },{"XF11", REG_TYPE_FLOAT, &sh4r.fr[1][10]},
101 {"XF12", REG_TYPE_FLOAT, &sh4r.fr[1][13] },{"XF13", REG_TYPE_FLOAT, &sh4r.fr[1][12]},
102 {"XF14", REG_TYPE_FLOAT, &sh4r.fr[1][15] },{"XF15", REG_TYPE_FLOAT, &sh4r.fr[1][14]},
104 {NULL, 0, NULL} };
106 void *sh4_get_register( int reg )
107 {
108 if( reg < 0 || reg >= 94 ) {
109 return NULL;
110 } else if( reg < 43 ) {
111 return sh4_reg_map[reg].value;
112 } else if( reg < 51 ) {
113 /* r0b0..r7b0 */
114 if( (sh4r.sr & SR_MDRB) == SR_MDRB ) {
115 /* bank 1 is primary */
116 return &sh4r.r_bank[reg-43];
117 } else {
118 return &sh4r.r[reg-43];
119 }
120 } else if( reg < 59 ) {
121 /* r0b1..r7b1 */
122 if( (sh4r.sr & SR_MDRB) == SR_MDRB ) {
123 /* bank 1 is primary */
124 return &sh4r.r[reg-43];
125 } else {
126 return &sh4r.r_bank[reg-43];
127 }
128 } else {
129 return NULL; /* not supported at the moment */
130 }
131 }
134 const struct cpu_desc_struct sh4_cpu_desc =
135 { "SH4", sh4_disasm_instruction, sh4_get_register, sh4_has_page,
136 sh4_debug_read_phys, sh4_debug_write_phys, sh4_debug_read_vma, sh4_debug_write_vma,
137 sh4_execute_instruction,
138 sh4_set_breakpoint, sh4_clear_breakpoint, sh4_get_breakpoint, 2,
139 (char *)&sh4r, sizeof(sh4r), sh4_reg_map, 23, 59,
140 &sh4r.pc };
142 struct dreamcast_module sh4_module = { "SH4", sh4_init, sh4_poweron_reset,
143 sh4_start, sh4_run_slice, sh4_stop,
144 sh4_save_state, sh4_load_state };
146 struct sh4_registers sh4r __attribute__((aligned(16)));
147 struct breakpoint_struct sh4_breakpoints[MAX_BREAKPOINTS];
148 int sh4_breakpoint_count = 0;
150 gboolean sh4_starting = FALSE;
151 static gboolean sh4_use_translator = FALSE;
152 static jmp_buf sh4_exit_jmp_buf;
153 static gboolean sh4_running = FALSE;
154 struct sh4_icache_struct sh4_icache = { NULL, -1, -1, 0 };
156 /* At the moment this is a dummy event to mark the end of the
157 * timeslice
158 */
159 void sh4_dummy_event(int eventid)
160 {
161 }
163 void sh4_translate_set_enabled( gboolean use )
164 {
165 // No-op if the translator was not built
166 #ifdef SH4_TRANSLATOR
167 if( use ) {
168 sh4_translate_init();
169 }
170 sh4_use_translator = use;
171 #endif
172 }
174 gboolean sh4_translate_is_enabled()
175 {
176 return sh4_use_translator;
177 }
179 void sh4_init(void)
180 {
181 register_io_regions( mmio_list_sh4mmio );
182 register_event_callback( EVENT_ENDTIMESLICE, sh4_dummy_event );
183 MMU_init();
184 TMU_init();
185 xlat_cache_init();
186 sh4_poweron_reset();
187 #ifdef ENABLE_SH4STATS
188 sh4_stats_reset();
189 #endif
190 }
192 void sh4_start(void)
193 {
194 sh4_starting = TRUE;
195 }
197 void sh4_poweron_reset(void)
198 {
199 /* zero everything out, for the sake of having a consistent state. */
200 memset( &sh4r, 0, sizeof(sh4r) );
201 if( sh4_use_translator ) {
202 xlat_flush_cache();
203 }
205 /* Resume running if we were halted */
206 sh4r.sh4_state = SH4_STATE_RUNNING;
208 sh4r.pc = 0xA0000000;
209 sh4r.new_pc= 0xA0000002;
210 sh4r.vbr = 0x00000000;
211 sh4r.fpscr = 0x00040001;
212 sh4_write_sr(0x700000F0);
214 /* Mem reset will do this, but if we want to reset _just_ the SH4... */
215 MMIO_WRITE( MMU, EXPEVT, EXC_POWER_RESET );
217 /* Peripheral modules */
218 CPG_reset();
219 INTC_reset();
220 PMM_reset();
221 TMU_reset();
222 SCIF_reset();
223 CCN_reset();
224 MMU_reset();
225 }
227 void sh4_stop(void)
228 {
229 if( sh4_use_translator ) {
230 /* If we were running with the translator, update new_pc and in_delay_slot */
231 sh4r.new_pc = sh4r.pc+2;
232 sh4r.in_delay_slot = FALSE;
233 }
235 }
237 /**
238 * Execute a timeslice using translated code only (ie translate/execute loop)
239 */
240 uint32_t sh4_run_slice( uint32_t nanosecs )
241 {
242 sh4r.slice_cycle = 0;
244 if( sh4r.sh4_state != SH4_STATE_RUNNING ) {
245 sh4_sleep_run_slice(nanosecs);
246 }
248 /* Setup for sudden vm exits */
249 switch( setjmp(sh4_exit_jmp_buf) ) {
250 case CORE_EXIT_BREAKPOINT:
251 sh4_clear_breakpoint( sh4r.pc, BREAK_ONESHOT );
252 /* fallthrough */
253 case CORE_EXIT_HALT:
254 if( sh4r.sh4_state != SH4_STATE_STANDBY ) {
255 TMU_run_slice( sh4r.slice_cycle );
256 SCIF_run_slice( sh4r.slice_cycle );
257 PMM_run_slice( sh4r.slice_cycle );
258 dreamcast_stop();
259 return sh4r.slice_cycle;
260 }
261 case CORE_EXIT_SYSRESET:
262 dreamcast_reset();
263 break;
264 case CORE_EXIT_SLEEP:
265 sh4_sleep_run_slice(nanosecs);
266 break;
267 case CORE_EXIT_FLUSH_ICACHE:
268 xlat_flush_cache();
269 break;
270 }
272 sh4_running = TRUE;
274 /* Execute the core's real slice */
275 #ifdef SH4_TRANSLATOR
276 if( sh4_use_translator ) {
277 sh4_translate_run_slice(nanosecs);
278 } else {
279 sh4_emulate_run_slice(nanosecs);
280 }
281 #else
282 sh4_emulate_run_slice(nanosecs);
283 #endif
285 /* And finish off the peripherals afterwards */
287 sh4_running = FALSE;
288 sh4_starting = FALSE;
289 sh4r.slice_cycle = nanosecs;
290 if( sh4r.sh4_state != SH4_STATE_STANDBY ) {
291 TMU_run_slice( nanosecs );
292 SCIF_run_slice( nanosecs );
293 PMM_run_slice( sh4r.slice_cycle );
294 }
295 return nanosecs;
296 }
298 void sh4_core_exit( int exit_code )
299 {
300 if( sh4_running ) {
301 #ifdef SH4_TRANSLATOR
302 if( sh4_use_translator ) {
303 if( exit_code == CORE_EXIT_EXCEPTION ) {
304 sh4_translate_exception_exit_recover();
305 } else {
306 sh4_translate_exit_recover();
307 }
308 }
309 #endif
310 if( exit_code != CORE_EXIT_EXCEPTION &&
311 exit_code != CORE_EXIT_BREAKPOINT ) {
312 sh4_finalize_instruction();
313 }
314 // longjmp back into sh4_run_slice
315 sh4_running = FALSE;
316 longjmp(sh4_exit_jmp_buf, exit_code);
317 }
318 }
320 void sh4_save_state( FILE *f )
321 {
322 if( sh4_use_translator ) {
323 /* If we were running with the translator, update new_pc and in_delay_slot */
324 sh4r.new_pc = sh4r.pc+2;
325 sh4r.in_delay_slot = FALSE;
326 }
328 fwrite( &sh4r, offsetof(struct sh4_registers, xlat_sh4_mode), 1, f );
329 MMU_save_state( f );
330 CCN_save_state( f );
331 PMM_save_state( f );
332 INTC_save_state( f );
333 TMU_save_state( f );
334 SCIF_save_state( f );
335 }
337 int sh4_load_state( FILE * f )
338 {
339 if( sh4_use_translator ) {
340 xlat_flush_cache();
341 }
342 fread( &sh4r, offsetof(struct sh4_registers, xlat_sh4_mode), 1, f );
343 sh4r.xlat_sh4_mode = (sh4r.sr & SR_MD) | (sh4r.fpscr & (FPSCR_SZ|FPSCR_PR));
344 MMU_load_state( f );
345 CCN_load_state( f );
346 PMM_load_state( f );
347 INTC_load_state( f );
348 TMU_load_state( f );
349 return SCIF_load_state( f );
350 }
352 void sh4_set_breakpoint( uint32_t pc, breakpoint_type_t type )
353 {
354 sh4_breakpoints[sh4_breakpoint_count].address = pc;
355 sh4_breakpoints[sh4_breakpoint_count].type = type;
356 if( sh4_use_translator ) {
357 xlat_invalidate_word( pc );
358 }
359 sh4_breakpoint_count++;
360 }
362 gboolean sh4_clear_breakpoint( uint32_t pc, breakpoint_type_t type )
363 {
364 int i;
366 for( i=0; i<sh4_breakpoint_count; i++ ) {
367 if( sh4_breakpoints[i].address == pc &&
368 sh4_breakpoints[i].type == type ) {
369 while( ++i < sh4_breakpoint_count ) {
370 sh4_breakpoints[i-1].address = sh4_breakpoints[i].address;
371 sh4_breakpoints[i-1].type = sh4_breakpoints[i].type;
372 }
373 if( sh4_use_translator ) {
374 xlat_invalidate_word( pc );
375 }
376 sh4_breakpoint_count--;
377 return TRUE;
378 }
379 }
380 return FALSE;
381 }
383 int sh4_get_breakpoint( uint32_t pc )
384 {
385 int i;
386 for( i=0; i<sh4_breakpoint_count; i++ ) {
387 if( sh4_breakpoints[i].address == pc )
388 return sh4_breakpoints[i].type;
389 }
390 return 0;
391 }
393 void sh4_set_pc( int pc )
394 {
395 sh4r.pc = pc;
396 sh4r.new_pc = pc+2;
397 }
399 /**
400 * Dump all SH4 core information for crash-dump purposes
401 */
402 void sh4_crashdump()
403 {
404 cpu_print_registers( stderr, &sh4_cpu_desc );
405 #ifdef SH4_TRANSLATOR
406 if( sh4_use_translator ) {
407 sh4_translate_crashdump();
408 } /* Nothing really to print for emu core */
409 #endif
410 }
413 /******************************* Support methods ***************************/
415 static void sh4_switch_banks( )
416 {
417 uint32_t tmp[8];
419 memcpy( tmp, sh4r.r, sizeof(uint32_t)*8 );
420 memcpy( sh4r.r, sh4r.r_bank, sizeof(uint32_t)*8 );
421 memcpy( sh4r.r_bank, tmp, sizeof(uint32_t)*8 );
422 }
424 void FASTCALL sh4_switch_fr_banks()
425 {
426 int i;
427 for( i=0; i<16; i++ ) {
428 float tmp = sh4r.fr[0][i];
429 sh4r.fr[0][i] = sh4r.fr[1][i];
430 sh4r.fr[1][i] = tmp;
431 }
432 }
434 void FASTCALL sh4_write_sr( uint32_t newval )
435 {
436 int oldbank = (sh4r.sr&SR_MDRB) == SR_MDRB;
437 int newbank = (newval&SR_MDRB) == SR_MDRB;
438 if( oldbank != newbank )
439 sh4_switch_banks();
440 sh4r.sr = newval & SR_MASK;
441 sh4r.t = (newval&SR_T) ? 1 : 0;
442 sh4r.s = (newval&SR_S) ? 1 : 0;
443 sh4r.m = (newval&SR_M) ? 1 : 0;
444 sh4r.q = (newval&SR_Q) ? 1 : 0;
445 sh4r.xlat_sh4_mode = (sh4r.sr & SR_MD) | (sh4r.fpscr & (FPSCR_SZ|FPSCR_PR));
446 intc_mask_changed();
447 }
449 void FASTCALL sh4_write_fpscr( uint32_t newval )
450 {
451 if( (sh4r.fpscr ^ newval) & FPSCR_FR ) {
452 sh4_switch_fr_banks();
453 }
454 sh4r.fpscr = newval & FPSCR_MASK;
455 sh4r.xlat_sh4_mode = (sh4r.sr & SR_MD) | (sh4r.fpscr & (FPSCR_SZ|FPSCR_PR));
456 }
458 uint32_t FASTCALL sh4_read_sr( void )
459 {
460 /* synchronize sh4r.sr with the various bitflags */
461 sh4r.sr &= SR_MQSTMASK;
462 if( sh4r.t ) sh4r.sr |= SR_T;
463 if( sh4r.s ) sh4r.sr |= SR_S;
464 if( sh4r.m ) sh4r.sr |= SR_M;
465 if( sh4r.q ) sh4r.sr |= SR_Q;
466 return sh4r.sr;
467 }
469 /**
470 * Raise a CPU reset exception with the specified exception code.
471 */
472 void FASTCALL sh4_raise_reset( int code )
473 {
474 MMIO_WRITE(MMU,EXPEVT,code);
475 sh4r.vbr = 0x00000000;
476 sh4r.pc = 0xA0000000;
477 sh4r.new_pc = sh4r.pc + 2;
478 sh4r.in_delay_slot = 0;
479 sh4_write_sr( (sh4r.sr|SR_MD|SR_BL|SR_RB|SR_IMASK)&(~SR_FD) );
481 /* Peripheral manual reset (FIXME: incomplete) */
482 INTC_reset();
483 SCIF_reset();
484 MMU_reset();
485 }
487 void FASTCALL sh4_raise_tlb_multihit( sh4vma_t vpn )
488 {
489 MMIO_WRITE( MMU, TEA, vpn );
490 MMIO_WRITE( MMU, PTEH, ((MMIO_READ(MMU, PTEH) & 0x000003FF) | (vpn&0xFFFFFC00)) );
491 sh4_raise_reset( EXC_TLB_MULTI_HIT );
492 }
494 /**
495 * Raise a general CPU exception for the specified exception code.
496 * (NOT for TRAPA or TLB exceptions)
497 */
498 void FASTCALL sh4_raise_exception( int code )
499 {
500 if( sh4r.sr & SR_BL ) {
501 sh4_raise_reset( EXC_MANUAL_RESET );
502 } else {
503 sh4r.spc = sh4r.pc;
504 sh4r.ssr = sh4_read_sr();
505 sh4r.sgr = sh4r.r[15];
506 MMIO_WRITE(MMU,EXPEVT, code);
507 sh4r.pc = sh4r.vbr + EXV_EXCEPTION;
508 sh4r.new_pc = sh4r.pc + 2;
509 sh4_write_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB );
510 sh4r.in_delay_slot = 0;
511 }
512 }
514 void FASTCALL sh4_raise_trap( int trap )
515 {
516 MMIO_WRITE( MMU, TRA, trap<<2 );
517 MMIO_WRITE( MMU, EXPEVT, EXC_TRAP );
518 sh4r.spc = sh4r.pc;
519 sh4r.ssr = sh4_read_sr();
520 sh4r.sgr = sh4r.r[15];
521 sh4r.pc = sh4r.vbr + EXV_EXCEPTION;
522 sh4r.new_pc = sh4r.pc + 2;
523 sh4_write_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB );
524 sh4r.in_delay_slot = 0;
525 }
527 void FASTCALL sh4_raise_tlb_exception( int code, sh4vma_t vpn )
528 {
529 MMIO_WRITE( MMU, TEA, vpn );
530 MMIO_WRITE( MMU, PTEH, ((MMIO_READ(MMU, PTEH) & 0x000003FF) | (vpn&0xFFFFFC00)) );
531 MMIO_WRITE( MMU, EXPEVT, code );
532 sh4r.spc = sh4r.pc;
533 sh4r.ssr = sh4_read_sr();
534 sh4r.sgr = sh4r.r[15];
535 sh4r.pc = sh4r.vbr + EXV_TLBMISS;
536 sh4r.new_pc = sh4r.pc + 2;
537 sh4_write_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB );
538 sh4r.in_delay_slot = 0;
539 }
541 void FASTCALL sh4_accept_interrupt( void )
542 {
543 uint32_t code = intc_accept_interrupt();
544 MMIO_WRITE( MMU, INTEVT, code );
545 sh4r.ssr = sh4_read_sr();
546 sh4r.spc = sh4r.pc;
547 sh4r.sgr = sh4r.r[15];
548 sh4_write_sr( sh4r.ssr|SR_BL|SR_MD|SR_RB );
549 sh4r.pc = sh4r.vbr + 0x600;
550 sh4r.new_pc = sh4r.pc + 2;
551 sh4r.in_delay_slot = 0;
552 }
554 void FASTCALL signsat48( void )
555 {
556 if( ((int64_t)sh4r.mac) < (int64_t)0xFFFF800000000000LL )
557 sh4r.mac = 0xFFFF800000000000LL;
558 else if( ((int64_t)sh4r.mac) > (int64_t)0x00007FFFFFFFFFFFLL )
559 sh4r.mac = 0x00007FFFFFFFFFFFLL;
560 }
562 void FASTCALL sh4_fsca( uint32_t anglei, float *fr )
563 {
564 float angle = (((float)(anglei&0xFFFF))/65536.0) * 2 * M_PI;
565 *fr++ = cosf(angle);
566 *fr = sinf(angle);
567 }
569 /**
570 * Enter sleep mode (eg by executing a SLEEP instruction).
571 * Sets sh4_state appropriately and ensures any stopping peripheral modules
572 * are up to date.
573 */
574 void FASTCALL sh4_sleep(void)
575 {
576 if( MMIO_READ( CPG, STBCR ) & 0x80 ) {
577 sh4r.sh4_state = SH4_STATE_STANDBY;
578 /* Bring all running peripheral modules up to date, and then halt them. */
579 TMU_run_slice( sh4r.slice_cycle );
580 SCIF_run_slice( sh4r.slice_cycle );
581 PMM_run_slice( sh4r.slice_cycle );
582 } else {
583 if( MMIO_READ( CPG, STBCR2 ) & 0x80 ) {
584 sh4r.sh4_state = SH4_STATE_DEEP_SLEEP;
585 /* Halt DMAC but other peripherals still running */
587 } else {
588 sh4r.sh4_state = SH4_STATE_SLEEP;
589 }
590 }
591 sh4_core_exit( CORE_EXIT_SLEEP );
592 }
594 /**
595 * Wakeup following sleep mode (IRQ or reset). Sets state back to running,
596 * and restarts any peripheral devices that were stopped.
597 */
598 void sh4_wakeup(void)
599 {
600 switch( sh4r.sh4_state ) {
601 case SH4_STATE_STANDBY:
602 break;
603 case SH4_STATE_DEEP_SLEEP:
604 break;
605 case SH4_STATE_SLEEP:
606 break;
607 }
608 sh4r.sh4_state = SH4_STATE_RUNNING;
609 }
611 /**
612 * Run a time slice (or portion of a timeslice) while the SH4 is sleeping.
613 * Returns when either the SH4 wakes up (interrupt received) or the end of
614 * the slice is reached. Updates sh4.slice_cycle with the exit time and
615 * returns the same value.
616 */
617 uint32_t sh4_sleep_run_slice( uint32_t nanosecs )
618 {
619 int sleep_state = sh4r.sh4_state;
620 assert( sleep_state != SH4_STATE_RUNNING );
622 while( sh4r.event_pending < nanosecs ) {
623 sh4r.slice_cycle = sh4r.event_pending;
624 if( sh4r.event_types & PENDING_EVENT ) {
625 event_execute();
626 }
627 if( sh4r.event_types & PENDING_IRQ ) {
628 sh4_wakeup();
629 return sh4r.slice_cycle;
630 }
631 }
632 sh4r.slice_cycle = nanosecs;
633 return sh4r.slice_cycle;
634 }
637 /**
638 * Compute the matrix tranform of fv given the matrix xf.
639 * Both fv and xf are word-swapped as per the sh4r.fr banks
640 */
641 void FASTCALL sh4_ftrv( float *target )
642 {
643 float fv[4] = { target[1], target[0], target[3], target[2] };
644 target[1] = sh4r.fr[1][1] * fv[0] + sh4r.fr[1][5]*fv[1] +
645 sh4r.fr[1][9]*fv[2] + sh4r.fr[1][13]*fv[3];
646 target[0] = sh4r.fr[1][0] * fv[0] + sh4r.fr[1][4]*fv[1] +
647 sh4r.fr[1][8]*fv[2] + sh4r.fr[1][12]*fv[3];
648 target[3] = sh4r.fr[1][3] * fv[0] + sh4r.fr[1][7]*fv[1] +
649 sh4r.fr[1][11]*fv[2] + sh4r.fr[1][15]*fv[3];
650 target[2] = sh4r.fr[1][2] * fv[0] + sh4r.fr[1][6]*fv[1] +
651 sh4r.fr[1][10]*fv[2] + sh4r.fr[1][14]*fv[3];
652 }
654 gboolean sh4_has_page( sh4vma_t vma )
655 {
656 sh4addr_t addr = mmu_vma_to_phys_disasm(vma);
657 return addr != MMU_VMA_ERROR && mem_has_page(addr);
658 }
660 /**
661 * Go through ext_address_space page by page
662 */
663 size_t sh4_debug_read_phys( unsigned char *buf, uint32_t addr, size_t length )
664 {
665 /* Quick and very dirty */
666 unsigned char *region = mem_get_region(addr);
667 if( region == NULL ) {
668 memset( buf, 0, length );
669 } else {
670 memcpy( buf, region, length );
671 }
672 return length;
673 }
675 size_t sh4_debug_write_phys( uint32_t addr, unsigned char *buf, size_t length )
676 {
677 unsigned char *region = mem_get_region(addr);
678 if( region != NULL ) {
679 memcpy( region, buf, length );
680 }
681 return length;
682 }
684 /**
685 * Read virtual memory - for now just go 1K at a time
686 */
687 size_t sh4_debug_read_vma( unsigned char *buf, uint32_t addr, size_t length )
688 {
689 if( IS_TLB_ENABLED() ) {
690 size_t read_len = 0;
691 while( length > 0 ) {
692 sh4addr_t phys = mmu_vma_to_phys_disasm(addr);
693 if( phys == MMU_VMA_ERROR )
694 break;
695 int next_len = 1024 - (phys&0x000003FF);
696 if( next_len >= length ) {
697 next_len = length;
698 }
699 sh4_debug_read_phys( buf, phys, length );
700 buf += next_len;
701 addr += next_len;
702 read_len += next_len;
703 length -= next_len;
704 }
705 return read_len;
706 } else {
707 return sh4_debug_read_phys( buf, addr, length );
708 }
709 }
711 size_t sh4_debug_write_vma( uint32_t addr, unsigned char *buf, size_t length )
712 {
713 if( IS_TLB_ENABLED() ) {
714 size_t read_len = 0;
715 while( length > 0 ) {
716 sh4addr_t phys = mmu_vma_to_phys_disasm(addr);
717 if( phys == MMU_VMA_ERROR )
718 break;
719 int next_len = 1024 - (phys&0x000003FF);
720 if( next_len >= length ) {
721 next_len = length;
722 }
723 sh4_debug_write_phys( phys, buf, length );
724 buf += next_len;
725 addr += next_len;
726 read_len += next_len;
727 length -= next_len;
728 }
729 return read_len;
730 } else {
731 return sh4_debug_write_phys( addr, buf, length );
732 }
733 }
.