filename | src/sh4/sh4.c |
changeset | 998:1754a8c6a9cf |
prev | 991:60c7fab9c880 |
next | 1065:bc1cc0c54917 |
author | nkeynes |
date | Wed Jun 24 06:06:40 2009 +0000 (14 years ago) |
permissions | -rw-r--r-- |
last change | Support shell substitutions in config paths Keep track of last folder in file dialogs Fix out-of-dateness in GTK path dialog |
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_xlat_init( void );
46 void sh4_poweron_reset( void );
47 void sh4_start( void );
48 void sh4_stop( void );
49 void sh4_save_state( FILE *f );
50 int sh4_load_state( FILE *f );
51 size_t sh4_debug_read_phys( unsigned char *buf, uint32_t addr, size_t length );
52 size_t sh4_debug_write_phys( uint32_t addr, unsigned char *buf, size_t length );
53 size_t sh4_debug_read_vma( unsigned char *buf, uint32_t addr, size_t length );
54 size_t sh4_debug_write_vma( uint32_t addr, unsigned char *buf, size_t length );
56 uint32_t sh4_run_slice( uint32_t );
57 uint32_t sh4_xlat_run_slice( uint32_t );
59 /* Note: this must match GDB's ordering */
60 const struct reg_desc_struct sh4_reg_map[] =
61 { {"R0", REG_INT, &sh4r.r[0]}, {"R1", REG_INT, &sh4r.r[1]},
62 {"R2", REG_INT, &sh4r.r[2]}, {"R3", REG_INT, &sh4r.r[3]},
63 {"R4", REG_INT, &sh4r.r[4]}, {"R5", REG_INT, &sh4r.r[5]},
64 {"R6", REG_INT, &sh4r.r[6]}, {"R7", REG_INT, &sh4r.r[7]},
65 {"R8", REG_INT, &sh4r.r[8]}, {"R9", REG_INT, &sh4r.r[9]},
66 {"R10",REG_INT, &sh4r.r[10]}, {"R11",REG_INT, &sh4r.r[11]},
67 {"R12",REG_INT, &sh4r.r[12]}, {"R13",REG_INT, &sh4r.r[13]},
68 {"R14",REG_INT, &sh4r.r[14]}, {"R15",REG_INT, &sh4r.r[15]},
69 {"PC", REG_INT, &sh4r.pc}, {"PR", REG_INT, &sh4r.pr},
70 {"GBR", REG_INT, &sh4r.gbr}, {"VBR",REG_INT, &sh4r.vbr},
71 {"MACH",REG_INT, ((uint32_t *)&sh4r.mac)+1}, {"MACL",REG_INT, &sh4r.mac},
72 {"SR", REG_INT, &sh4r.sr},
73 {"FPUL", REG_INT, &sh4r.fpul.i}, {"FPSCR", REG_INT, &sh4r.fpscr},
75 {"FR0", REG_FLOAT, &sh4r.fr[0][1] },{"FR1", REG_FLOAT, &sh4r.fr[0][0]},
76 {"FR2", REG_FLOAT, &sh4r.fr[0][3] },{"FR3", REG_FLOAT, &sh4r.fr[0][2]},
77 {"FR4", REG_FLOAT, &sh4r.fr[0][5] },{"FR5", REG_FLOAT, &sh4r.fr[0][4]},
78 {"FR6", REG_FLOAT, &sh4r.fr[0][7] },{"FR7", REG_FLOAT, &sh4r.fr[0][6]},
79 {"FR8", REG_FLOAT, &sh4r.fr[0][9] },{"FR9", REG_FLOAT, &sh4r.fr[0][8]},
80 {"FR10", REG_FLOAT, &sh4r.fr[0][11] },{"FR11", REG_FLOAT, &sh4r.fr[0][10]},
81 {"FR12", REG_FLOAT, &sh4r.fr[0][13] },{"FR13", REG_FLOAT, &sh4r.fr[0][12]},
82 {"FR14", REG_FLOAT, &sh4r.fr[0][15] },{"FR15", REG_FLOAT, &sh4r.fr[0][14]},
84 {"SSR",REG_INT, &sh4r.ssr}, {"SPC", REG_INT, &sh4r.spc},
86 {"R0B0", REG_INT, NULL}, {"R1B0", REG_INT, NULL},
87 {"R2B0", REG_INT, NULL}, {"R3B0", REG_INT, NULL},
88 {"R4B0", REG_INT, NULL}, {"R5B0", REG_INT, NULL},
89 {"R6B0", REG_INT, NULL}, {"R7B0", REG_INT, NULL},
90 {"R0B1", REG_INT, NULL}, {"R1B1", REG_INT, NULL},
91 {"R2B1", REG_INT, NULL}, {"R3B1", REG_INT, NULL},
92 {"R4B1", REG_INT, NULL}, {"R5B1", REG_INT, NULL},
93 {"R6B1", REG_INT, NULL}, {"R7B1", REG_INT, NULL},
95 {"SGR",REG_INT, &sh4r.sgr}, {"DBR", REG_INT, &sh4r.dbr},
97 {"XF0", REG_FLOAT, &sh4r.fr[1][1] },{"XF1", REG_FLOAT, &sh4r.fr[1][0]},
98 {"XF2", REG_FLOAT, &sh4r.fr[1][3] },{"XF3", REG_FLOAT, &sh4r.fr[1][2]},
99 {"XF4", REG_FLOAT, &sh4r.fr[1][5] },{"XF5", REG_FLOAT, &sh4r.fr[1][4]},
100 {"XF6", REG_FLOAT, &sh4r.fr[1][7] },{"XF7", REG_FLOAT, &sh4r.fr[1][6]},
101 {"XF8", REG_FLOAT, &sh4r.fr[1][9] },{"XF9", REG_FLOAT, &sh4r.fr[1][8]},
102 {"XF10", REG_FLOAT, &sh4r.fr[1][11] },{"XF11", REG_FLOAT, &sh4r.fr[1][10]},
103 {"XF12", REG_FLOAT, &sh4r.fr[1][13] },{"XF13", REG_FLOAT, &sh4r.fr[1][12]},
104 {"XF14", REG_FLOAT, &sh4r.fr[1][15] },{"XF15", REG_FLOAT, &sh4r.fr[1][14]},
106 {NULL, 0, NULL} };
108 void *sh4_get_register( int reg )
109 {
110 if( reg < 0 || reg >= 94 ) {
111 return NULL;
112 } else if( reg < 43 ) {
113 return sh4_reg_map[reg].value;
114 } else if( reg < 51 ) {
115 /* r0b0..r7b0 */
116 if( (sh4r.sr & SR_MDRB) == SR_MDRB ) {
117 /* bank 1 is primary */
118 return &sh4r.r_bank[reg-43];
119 } else {
120 return &sh4r.r[reg-43];
121 }
122 } else if( reg < 59 ) {
123 /* r0b1..r7b1 */
124 if( (sh4r.sr & SR_MDRB) == SR_MDRB ) {
125 /* bank 1 is primary */
126 return &sh4r.r[reg-43];
127 } else {
128 return &sh4r.r_bank[reg-43];
129 }
130 } else {
131 return NULL; /* not supported at the moment */
132 }
133 }
136 const struct cpu_desc_struct sh4_cpu_desc =
137 { "SH4", sh4_disasm_instruction, sh4_get_register, sh4_has_page,
138 sh4_debug_read_phys, sh4_debug_write_phys, sh4_debug_read_vma, sh4_debug_write_vma,
139 sh4_execute_instruction,
140 sh4_set_breakpoint, sh4_clear_breakpoint, sh4_get_breakpoint, 2,
141 (char *)&sh4r, sizeof(sh4r), sh4_reg_map, 23, 59,
142 &sh4r.pc };
144 struct dreamcast_module sh4_module = { "SH4", sh4_init, sh4_poweron_reset,
145 sh4_start, sh4_run_slice, sh4_stop,
146 sh4_save_state, sh4_load_state };
148 struct sh4_registers sh4r __attribute__((aligned(16)));
149 struct breakpoint_struct sh4_breakpoints[MAX_BREAKPOINTS];
150 int sh4_breakpoint_count = 0;
152 gboolean sh4_starting = FALSE;
153 static gboolean sh4_use_translator = FALSE;
154 static jmp_buf sh4_exit_jmp_buf;
155 static gboolean sh4_running = FALSE;
156 struct sh4_icache_struct sh4_icache = { NULL, -1, -1, 0 };
158 void sh4_translate_set_enabled( gboolean use )
159 {
160 // No-op if the translator was not built
161 #ifdef SH4_TRANSLATOR
162 if( use ) {
163 sh4_translate_init();
164 }
165 sh4_use_translator = use;
166 #endif
167 }
169 gboolean sh4_translate_is_enabled()
170 {
171 return sh4_use_translator;
172 }
174 void sh4_init(void)
175 {
176 register_io_regions( mmio_list_sh4mmio );
177 MMU_init();
178 TMU_init();
179 xlat_cache_init();
180 sh4_poweron_reset();
181 #ifdef ENABLE_SH4STATS
182 sh4_stats_reset();
183 #endif
184 }
186 void sh4_start(void)
187 {
188 sh4_starting = TRUE;
189 }
191 void sh4_poweron_reset(void)
192 {
193 /* zero everything out, for the sake of having a consistent state. */
194 memset( &sh4r, 0, sizeof(sh4r) );
195 if( sh4_use_translator ) {
196 xlat_flush_cache();
197 }
199 /* Resume running if we were halted */
200 sh4r.sh4_state = SH4_STATE_RUNNING;
202 sh4r.pc = 0xA0000000;
203 sh4r.new_pc= 0xA0000002;
204 sh4r.vbr = 0x00000000;
205 sh4r.fpscr = 0x00040001;
206 sh4_write_sr(0x700000F0);
208 /* Mem reset will do this, but if we want to reset _just_ the SH4... */
209 MMIO_WRITE( MMU, EXPEVT, EXC_POWER_RESET );
211 /* Peripheral modules */
212 CPG_reset();
213 INTC_reset();
214 PMM_reset();
215 TMU_reset();
216 SCIF_reset();
217 CCN_reset();
218 MMU_reset();
219 }
221 void sh4_stop(void)
222 {
223 if( sh4_use_translator ) {
224 /* If we were running with the translator, update new_pc and in_delay_slot */
225 sh4r.new_pc = sh4r.pc+2;
226 sh4r.in_delay_slot = FALSE;
227 }
229 }
231 /**
232 * Execute a timeslice using translated code only (ie translate/execute loop)
233 */
234 uint32_t sh4_run_slice( uint32_t nanosecs )
235 {
236 sh4r.slice_cycle = 0;
238 if( sh4r.sh4_state != SH4_STATE_RUNNING ) {
239 sh4_sleep_run_slice(nanosecs);
240 }
242 /* Setup for sudden vm exits */
243 switch( setjmp(sh4_exit_jmp_buf) ) {
244 case CORE_EXIT_BREAKPOINT:
245 sh4_clear_breakpoint( sh4r.pc, BREAK_ONESHOT );
246 /* fallthrough */
247 case CORE_EXIT_HALT:
248 if( sh4r.sh4_state != SH4_STATE_STANDBY ) {
249 TMU_run_slice( sh4r.slice_cycle );
250 SCIF_run_slice( sh4r.slice_cycle );
251 PMM_run_slice( sh4r.slice_cycle );
252 dreamcast_stop();
253 return sh4r.slice_cycle;
254 }
255 case CORE_EXIT_SYSRESET:
256 dreamcast_reset();
257 break;
258 case CORE_EXIT_SLEEP:
259 sh4_sleep_run_slice(nanosecs);
260 break;
261 case CORE_EXIT_FLUSH_ICACHE:
262 xlat_flush_cache();
263 break;
264 }
266 sh4_running = TRUE;
268 /* Execute the core's real slice */
269 #ifdef SH4_TRANSLATOR
270 if( sh4_use_translator ) {
271 sh4_translate_run_slice(nanosecs);
272 } else {
273 sh4_emulate_run_slice(nanosecs);
274 }
275 #else
276 sh4_emulate_run_slice(nanosecs);
277 #endif
279 /* And finish off the peripherals afterwards */
281 sh4_running = FALSE;
282 sh4_starting = FALSE;
283 sh4r.slice_cycle = nanosecs;
284 if( sh4r.sh4_state != SH4_STATE_STANDBY ) {
285 TMU_run_slice( nanosecs );
286 SCIF_run_slice( nanosecs );
287 PMM_run_slice( sh4r.slice_cycle );
288 }
289 return nanosecs;
290 }
292 void sh4_core_exit( int exit_code )
293 {
294 if( sh4_running ) {
295 #ifdef SH4_TRANSLATOR
296 if( sh4_use_translator ) {
297 if( exit_code == CORE_EXIT_EXCEPTION ) {
298 sh4_translate_exception_exit_recover();
299 } else {
300 sh4_translate_exit_recover();
301 }
302 }
303 #endif
304 if( exit_code != CORE_EXIT_EXCEPTION &&
305 exit_code != CORE_EXIT_BREAKPOINT ) {
306 sh4_finalize_instruction();
307 }
308 // longjmp back into sh4_run_slice
309 sh4_running = FALSE;
310 longjmp(sh4_exit_jmp_buf, exit_code);
311 }
312 }
314 void sh4_save_state( FILE *f )
315 {
316 if( sh4_use_translator ) {
317 /* If we were running with the translator, update new_pc and in_delay_slot */
318 sh4r.new_pc = sh4r.pc+2;
319 sh4r.in_delay_slot = FALSE;
320 }
322 fwrite( &sh4r, offsetof(struct sh4_registers, xlat_sh4_mode), 1, f );
323 MMU_save_state( f );
324 CCN_save_state( f );
325 PMM_save_state( f );
326 INTC_save_state( f );
327 TMU_save_state( f );
328 SCIF_save_state( f );
329 }
331 int sh4_load_state( FILE * f )
332 {
333 if( sh4_use_translator ) {
334 xlat_flush_cache();
335 }
336 fread( &sh4r, offsetof(struct sh4_registers, xlat_sh4_mode), 1, f );
337 sh4r.xlat_sh4_mode = (sh4r.sr & SR_MD) | (sh4r.fpscr & (FPSCR_SZ|FPSCR_PR));
338 MMU_load_state( f );
339 CCN_load_state( f );
340 PMM_load_state( f );
341 INTC_load_state( f );
342 TMU_load_state( f );
343 return SCIF_load_state( f );
344 }
346 void sh4_set_breakpoint( uint32_t pc, breakpoint_type_t type )
347 {
348 sh4_breakpoints[sh4_breakpoint_count].address = pc;
349 sh4_breakpoints[sh4_breakpoint_count].type = type;
350 if( sh4_use_translator ) {
351 xlat_invalidate_word( pc );
352 }
353 sh4_breakpoint_count++;
354 }
356 gboolean sh4_clear_breakpoint( uint32_t pc, breakpoint_type_t type )
357 {
358 int i;
360 for( i=0; i<sh4_breakpoint_count; i++ ) {
361 if( sh4_breakpoints[i].address == pc &&
362 sh4_breakpoints[i].type == type ) {
363 while( ++i < sh4_breakpoint_count ) {
364 sh4_breakpoints[i-1].address = sh4_breakpoints[i].address;
365 sh4_breakpoints[i-1].type = sh4_breakpoints[i].type;
366 }
367 if( sh4_use_translator ) {
368 xlat_invalidate_word( pc );
369 }
370 sh4_breakpoint_count--;
371 return TRUE;
372 }
373 }
374 return FALSE;
375 }
377 int sh4_get_breakpoint( uint32_t pc )
378 {
379 int i;
380 for( i=0; i<sh4_breakpoint_count; i++ ) {
381 if( sh4_breakpoints[i].address == pc )
382 return sh4_breakpoints[i].type;
383 }
384 return 0;
385 }
387 void sh4_set_pc( int pc )
388 {
389 sh4r.pc = pc;
390 sh4r.new_pc = pc+2;
391 }
394 /******************************* Support methods ***************************/
396 static void sh4_switch_banks( )
397 {
398 uint32_t tmp[8];
400 memcpy( tmp, sh4r.r, sizeof(uint32_t)*8 );
401 memcpy( sh4r.r, sh4r.r_bank, sizeof(uint32_t)*8 );
402 memcpy( sh4r.r_bank, tmp, sizeof(uint32_t)*8 );
403 }
405 void FASTCALL sh4_switch_fr_banks()
406 {
407 int i;
408 for( i=0; i<16; i++ ) {
409 float tmp = sh4r.fr[0][i];
410 sh4r.fr[0][i] = sh4r.fr[1][i];
411 sh4r.fr[1][i] = tmp;
412 }
413 }
415 void FASTCALL sh4_write_sr( uint32_t newval )
416 {
417 int oldbank = (sh4r.sr&SR_MDRB) == SR_MDRB;
418 int newbank = (newval&SR_MDRB) == SR_MDRB;
419 if( oldbank != newbank )
420 sh4_switch_banks();
421 sh4r.sr = newval & SR_MASK;
422 sh4r.t = (newval&SR_T) ? 1 : 0;
423 sh4r.s = (newval&SR_S) ? 1 : 0;
424 sh4r.m = (newval&SR_M) ? 1 : 0;
425 sh4r.q = (newval&SR_Q) ? 1 : 0;
426 sh4r.xlat_sh4_mode = (sh4r.sr & SR_MD) | (sh4r.fpscr & (FPSCR_SZ|FPSCR_PR));
427 intc_mask_changed();
428 }
430 void FASTCALL sh4_write_fpscr( uint32_t newval )
431 {
432 if( (sh4r.fpscr ^ newval) & FPSCR_FR ) {
433 sh4_switch_fr_banks();
434 }
435 sh4r.fpscr = newval & FPSCR_MASK;
436 sh4r.xlat_sh4_mode = (sh4r.sr & SR_MD) | (sh4r.fpscr & (FPSCR_SZ|FPSCR_PR));
437 }
439 uint32_t FASTCALL sh4_read_sr( void )
440 {
441 /* synchronize sh4r.sr with the various bitflags */
442 sh4r.sr &= SR_MQSTMASK;
443 if( sh4r.t ) sh4r.sr |= SR_T;
444 if( sh4r.s ) sh4r.sr |= SR_S;
445 if( sh4r.m ) sh4r.sr |= SR_M;
446 if( sh4r.q ) sh4r.sr |= SR_Q;
447 return sh4r.sr;
448 }
450 /**
451 * Raise a CPU reset exception with the specified exception code.
452 */
453 void FASTCALL sh4_raise_reset( int code )
454 {
455 MMIO_WRITE(MMU,EXPEVT,code);
456 sh4r.vbr = 0x00000000;
457 sh4r.pc = 0xA0000000;
458 sh4r.new_pc = sh4r.pc + 2;
459 sh4r.in_delay_slot = 0;
460 sh4_write_sr( (sh4r.sr|SR_MD|SR_BL|SR_RB|SR_IMASK)&(~SR_FD) );
462 /* Peripheral manual reset (FIXME: incomplete) */
463 INTC_reset();
464 SCIF_reset();
465 MMU_reset();
466 }
468 void FASTCALL sh4_raise_tlb_multihit( sh4vma_t vpn )
469 {
470 MMIO_WRITE( MMU, TEA, vpn );
471 MMIO_WRITE( MMU, PTEH, ((MMIO_READ(MMU, PTEH) & 0x000003FF) | (vpn&0xFFFFFC00)) );
472 sh4_raise_reset( EXC_TLB_MULTI_HIT );
473 }
475 /**
476 * Raise a general CPU exception for the specified exception code.
477 * (NOT for TRAPA or TLB exceptions)
478 */
479 void FASTCALL sh4_raise_exception( int code )
480 {
481 if( sh4r.sr & SR_BL ) {
482 sh4_raise_reset( EXC_MANUAL_RESET );
483 } else {
484 sh4r.spc = sh4r.pc;
485 sh4r.ssr = sh4_read_sr();
486 sh4r.sgr = sh4r.r[15];
487 MMIO_WRITE(MMU,EXPEVT, code);
488 sh4r.pc = sh4r.vbr + EXV_EXCEPTION;
489 sh4r.new_pc = sh4r.pc + 2;
490 sh4_write_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB );
491 sh4r.in_delay_slot = 0;
492 }
493 }
495 void FASTCALL sh4_raise_trap( int trap )
496 {
497 MMIO_WRITE( MMU, TRA, trap<<2 );
498 MMIO_WRITE( MMU, EXPEVT, EXC_TRAP );
499 sh4r.spc = sh4r.pc;
500 sh4r.ssr = sh4_read_sr();
501 sh4r.sgr = sh4r.r[15];
502 sh4r.pc = sh4r.vbr + EXV_EXCEPTION;
503 sh4r.new_pc = sh4r.pc + 2;
504 sh4_write_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB );
505 sh4r.in_delay_slot = 0;
506 }
508 void FASTCALL sh4_raise_tlb_exception( int code, sh4vma_t vpn )
509 {
510 MMIO_WRITE( MMU, TEA, vpn );
511 MMIO_WRITE( MMU, PTEH, ((MMIO_READ(MMU, PTEH) & 0x000003FF) | (vpn&0xFFFFFC00)) );
512 MMIO_WRITE( MMU, EXPEVT, code );
513 sh4r.spc = sh4r.pc;
514 sh4r.ssr = sh4_read_sr();
515 sh4r.sgr = sh4r.r[15];
516 sh4r.pc = sh4r.vbr + EXV_TLBMISS;
517 sh4r.new_pc = sh4r.pc + 2;
518 sh4_write_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB );
519 sh4r.in_delay_slot = 0;
520 }
522 void FASTCALL sh4_accept_interrupt( void )
523 {
524 uint32_t code = intc_accept_interrupt();
525 MMIO_WRITE( MMU, INTEVT, code );
526 sh4r.ssr = sh4_read_sr();
527 sh4r.spc = sh4r.pc;
528 sh4r.sgr = sh4r.r[15];
529 sh4_write_sr( sh4r.ssr|SR_BL|SR_MD|SR_RB );
530 sh4r.pc = sh4r.vbr + 0x600;
531 sh4r.new_pc = sh4r.pc + 2;
532 sh4r.in_delay_slot = 0;
533 }
535 void FASTCALL signsat48( void )
536 {
537 if( ((int64_t)sh4r.mac) < (int64_t)0xFFFF800000000000LL )
538 sh4r.mac = 0xFFFF800000000000LL;
539 else if( ((int64_t)sh4r.mac) > (int64_t)0x00007FFFFFFFFFFFLL )
540 sh4r.mac = 0x00007FFFFFFFFFFFLL;
541 }
543 void FASTCALL sh4_fsca( uint32_t anglei, float *fr )
544 {
545 float angle = (((float)(anglei&0xFFFF))/65536.0) * 2 * M_PI;
546 *fr++ = cosf(angle);
547 *fr = sinf(angle);
548 }
550 /**
551 * Enter sleep mode (eg by executing a SLEEP instruction).
552 * Sets sh4_state appropriately and ensures any stopping peripheral modules
553 * are up to date.
554 */
555 void FASTCALL sh4_sleep(void)
556 {
557 if( MMIO_READ( CPG, STBCR ) & 0x80 ) {
558 sh4r.sh4_state = SH4_STATE_STANDBY;
559 /* Bring all running peripheral modules up to date, and then halt them. */
560 TMU_run_slice( sh4r.slice_cycle );
561 SCIF_run_slice( sh4r.slice_cycle );
562 PMM_run_slice( sh4r.slice_cycle );
563 } else {
564 if( MMIO_READ( CPG, STBCR2 ) & 0x80 ) {
565 sh4r.sh4_state = SH4_STATE_DEEP_SLEEP;
566 /* Halt DMAC but other peripherals still running */
568 } else {
569 sh4r.sh4_state = SH4_STATE_SLEEP;
570 }
571 }
572 sh4_core_exit( CORE_EXIT_SLEEP );
573 }
575 /**
576 * Wakeup following sleep mode (IRQ or reset). Sets state back to running,
577 * and restarts any peripheral devices that were stopped.
578 */
579 void sh4_wakeup(void)
580 {
581 switch( sh4r.sh4_state ) {
582 case SH4_STATE_STANDBY:
583 break;
584 case SH4_STATE_DEEP_SLEEP:
585 break;
586 case SH4_STATE_SLEEP:
587 break;
588 }
589 sh4r.sh4_state = SH4_STATE_RUNNING;
590 }
592 /**
593 * Run a time slice (or portion of a timeslice) while the SH4 is sleeping.
594 * Returns when either the SH4 wakes up (interrupt received) or the end of
595 * the slice is reached. Updates sh4.slice_cycle with the exit time and
596 * returns the same value.
597 */
598 uint32_t sh4_sleep_run_slice( uint32_t nanosecs )
599 {
600 int sleep_state = sh4r.sh4_state;
601 assert( sleep_state != SH4_STATE_RUNNING );
603 while( sh4r.event_pending < nanosecs ) {
604 sh4r.slice_cycle = sh4r.event_pending;
605 if( sh4r.event_types & PENDING_EVENT ) {
606 event_execute();
607 }
608 if( sh4r.event_types & PENDING_IRQ ) {
609 sh4_wakeup();
610 return sh4r.slice_cycle;
611 }
612 }
613 sh4r.slice_cycle = nanosecs;
614 return sh4r.slice_cycle;
615 }
618 /**
619 * Compute the matrix tranform of fv given the matrix xf.
620 * Both fv and xf are word-swapped as per the sh4r.fr banks
621 */
622 void FASTCALL sh4_ftrv( float *target )
623 {
624 float fv[4] = { target[1], target[0], target[3], target[2] };
625 target[1] = sh4r.fr[1][1] * fv[0] + sh4r.fr[1][5]*fv[1] +
626 sh4r.fr[1][9]*fv[2] + sh4r.fr[1][13]*fv[3];
627 target[0] = sh4r.fr[1][0] * fv[0] + sh4r.fr[1][4]*fv[1] +
628 sh4r.fr[1][8]*fv[2] + sh4r.fr[1][12]*fv[3];
629 target[3] = sh4r.fr[1][3] * fv[0] + sh4r.fr[1][7]*fv[1] +
630 sh4r.fr[1][11]*fv[2] + sh4r.fr[1][15]*fv[3];
631 target[2] = sh4r.fr[1][2] * fv[0] + sh4r.fr[1][6]*fv[1] +
632 sh4r.fr[1][10]*fv[2] + sh4r.fr[1][14]*fv[3];
633 }
635 gboolean sh4_has_page( sh4vma_t vma )
636 {
637 sh4addr_t addr = mmu_vma_to_phys_disasm(vma);
638 return addr != MMU_VMA_ERROR && mem_has_page(addr);
639 }
641 /**
642 * Go through ext_address_space page by page
643 */
644 size_t sh4_debug_read_phys( unsigned char *buf, uint32_t addr, size_t length )
645 {
646 /* Quick and very dirty */
647 unsigned char *region = mem_get_region(addr);
648 if( region == NULL ) {
649 memset( buf, 0, length );
650 } else {
651 memcpy( buf, region, length );
652 }
653 return length;
654 }
656 size_t sh4_debug_write_phys( uint32_t addr, unsigned char *buf, size_t length )
657 {
658 unsigned char *region = mem_get_region(addr);
659 if( region != NULL ) {
660 memcpy( region, buf, length );
661 }
662 return length;
663 }
665 /**
666 * Read virtual memory - for now just go 1K at a time
667 */
668 size_t sh4_debug_read_vma( unsigned char *buf, uint32_t addr, size_t length )
669 {
670 if( IS_TLB_ENABLED() ) {
671 size_t read_len = 0;
672 while( length > 0 ) {
673 sh4addr_t phys = mmu_vma_to_phys_disasm(addr);
674 if( phys == MMU_VMA_ERROR )
675 break;
676 int next_len = 1024 - (phys&0x000003FF);
677 if( next_len >= length ) {
678 next_len = length;
679 }
680 sh4_debug_read_phys( buf, phys, length );
681 buf += next_len;
682 addr += next_len;
683 read_len += next_len;
684 length -= next_len;
685 }
686 return read_len;
687 } else {
688 return sh4_debug_read_phys( buf, addr, length );
689 }
690 }
692 size_t sh4_debug_write_vma( uint32_t addr, unsigned char *buf, size_t length )
693 {
694 if( IS_TLB_ENABLED() ) {
695 size_t read_len = 0;
696 while( length > 0 ) {
697 sh4addr_t phys = mmu_vma_to_phys_disasm(addr);
698 if( phys == MMU_VMA_ERROR )
699 break;
700 int next_len = 1024 - (phys&0x000003FF);
701 if( next_len >= length ) {
702 next_len = length;
703 }
704 sh4_debug_write_phys( phys, buf, length );
705 buf += next_len;
706 addr += next_len;
707 read_len += next_len;
708 length -= next_len;
709 }
710 } else {
711 return sh4_debug_write_phys( addr, buf, length );
712 }
713 }
.