Search
lxdream.org :: lxdream/src/sh4/sh4.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4.c
changeset 998:1754a8c6a9cf
prev991:60c7fab9c880
next1065:bc1cc0c54917
author nkeynes
date Tue Mar 24 11:15:57 2009 +0000 (13 years ago)
permissions -rw-r--r--
last change Add preliminary implementation of the GDB remote debugging server - attaches to
either or both the SH4 and ARM
file annotate diff log raw
1.1 --- a/src/sh4/sh4.c Wed Mar 04 23:12:21 2009 +0000
1.2 +++ b/src/sh4/sh4.c Tue Mar 24 11:15:57 2009 +0000
1.3 @@ -23,6 +23,7 @@
1.4 #include <assert.h>
1.5 #include "lxdream.h"
1.6 #include "dreamcast.h"
1.7 +#include "cpu.h"
1.8 #include "mem.h"
1.9 #include "clock.h"
1.10 #include "eventq.h"
1.11 @@ -30,6 +31,7 @@
1.12 #include "sh4/intc.h"
1.13 #include "sh4/mmu.h"
1.14 #include "sh4/sh4core.h"
1.15 +#include "sh4/sh4dasm.h"
1.16 #include "sh4/sh4mmio.h"
1.17 #include "sh4/sh4stat.h"
1.18 #include "sh4/sh4trans.h"
1.19 @@ -46,10 +48,99 @@
1.20 void sh4_stop( void );
1.21 void sh4_save_state( FILE *f );
1.22 int sh4_load_state( FILE *f );
1.23 +size_t sh4_debug_read_phys( unsigned char *buf, uint32_t addr, size_t length );
1.24 +size_t sh4_debug_write_phys( uint32_t addr, unsigned char *buf, size_t length );
1.25 +size_t sh4_debug_read_vma( unsigned char *buf, uint32_t addr, size_t length );
1.26 +size_t sh4_debug_write_vma( uint32_t addr, unsigned char *buf, size_t length );
1.27
1.28 uint32_t sh4_run_slice( uint32_t );
1.29 uint32_t sh4_xlat_run_slice( uint32_t );
1.30
1.31 +/* Note: this must match GDB's ordering */
1.32 +const struct reg_desc_struct sh4_reg_map[] =
1.33 + { {"R0", REG_INT, &sh4r.r[0]}, {"R1", REG_INT, &sh4r.r[1]},
1.34 + {"R2", REG_INT, &sh4r.r[2]}, {"R3", REG_INT, &sh4r.r[3]},
1.35 + {"R4", REG_INT, &sh4r.r[4]}, {"R5", REG_INT, &sh4r.r[5]},
1.36 + {"R6", REG_INT, &sh4r.r[6]}, {"R7", REG_INT, &sh4r.r[7]},
1.37 + {"R8", REG_INT, &sh4r.r[8]}, {"R9", REG_INT, &sh4r.r[9]},
1.38 + {"R10",REG_INT, &sh4r.r[10]}, {"R11",REG_INT, &sh4r.r[11]},
1.39 + {"R12",REG_INT, &sh4r.r[12]}, {"R13",REG_INT, &sh4r.r[13]},
1.40 + {"R14",REG_INT, &sh4r.r[14]}, {"R15",REG_INT, &sh4r.r[15]},
1.41 + {"PC", REG_INT, &sh4r.pc}, {"PR", REG_INT, &sh4r.pr},
1.42 + {"GBR", REG_INT, &sh4r.gbr}, {"VBR",REG_INT, &sh4r.vbr},
1.43 + {"MACH",REG_INT, ((uint32_t *)&sh4r.mac)+1}, {"MACL",REG_INT, &sh4r.mac},
1.44 + {"SR", REG_INT, &sh4r.sr},
1.45 + {"FPUL", REG_INT, &sh4r.fpul.i}, {"FPSCR", REG_INT, &sh4r.fpscr},
1.46 +
1.47 + {"FR0", REG_FLOAT, &sh4r.fr[0][1] },{"FR1", REG_FLOAT, &sh4r.fr[0][0]},
1.48 + {"FR2", REG_FLOAT, &sh4r.fr[0][3] },{"FR3", REG_FLOAT, &sh4r.fr[0][2]},
1.49 + {"FR4", REG_FLOAT, &sh4r.fr[0][5] },{"FR5", REG_FLOAT, &sh4r.fr[0][4]},
1.50 + {"FR6", REG_FLOAT, &sh4r.fr[0][7] },{"FR7", REG_FLOAT, &sh4r.fr[0][6]},
1.51 + {"FR8", REG_FLOAT, &sh4r.fr[0][9] },{"FR9", REG_FLOAT, &sh4r.fr[0][8]},
1.52 + {"FR10", REG_FLOAT, &sh4r.fr[0][11] },{"FR11", REG_FLOAT, &sh4r.fr[0][10]},
1.53 + {"FR12", REG_FLOAT, &sh4r.fr[0][13] },{"FR13", REG_FLOAT, &sh4r.fr[0][12]},
1.54 + {"FR14", REG_FLOAT, &sh4r.fr[0][15] },{"FR15", REG_FLOAT, &sh4r.fr[0][14]},
1.55 +
1.56 + {"SSR",REG_INT, &sh4r.ssr}, {"SPC", REG_INT, &sh4r.spc},
1.57 +
1.58 + {"R0B0", REG_INT, NULL}, {"R1B0", REG_INT, NULL},
1.59 + {"R2B0", REG_INT, NULL}, {"R3B0", REG_INT, NULL},
1.60 + {"R4B0", REG_INT, NULL}, {"R5B0", REG_INT, NULL},
1.61 + {"R6B0", REG_INT, NULL}, {"R7B0", REG_INT, NULL},
1.62 + {"R0B1", REG_INT, NULL}, {"R1B1", REG_INT, NULL},
1.63 + {"R2B1", REG_INT, NULL}, {"R3B1", REG_INT, NULL},
1.64 + {"R4B1", REG_INT, NULL}, {"R5B1", REG_INT, NULL},
1.65 + {"R6B1", REG_INT, NULL}, {"R7B1", REG_INT, NULL},
1.66 +
1.67 + {"SGR",REG_INT, &sh4r.sgr}, {"DBR", REG_INT, &sh4r.dbr},
1.68 +
1.69 + {"XF0", REG_FLOAT, &sh4r.fr[1][1] },{"XF1", REG_FLOAT, &sh4r.fr[1][0]},
1.70 + {"XF2", REG_FLOAT, &sh4r.fr[1][3] },{"XF3", REG_FLOAT, &sh4r.fr[1][2]},
1.71 + {"XF4", REG_FLOAT, &sh4r.fr[1][5] },{"XF5", REG_FLOAT, &sh4r.fr[1][4]},
1.72 + {"XF6", REG_FLOAT, &sh4r.fr[1][7] },{"XF7", REG_FLOAT, &sh4r.fr[1][6]},
1.73 + {"XF8", REG_FLOAT, &sh4r.fr[1][9] },{"XF9", REG_FLOAT, &sh4r.fr[1][8]},
1.74 + {"XF10", REG_FLOAT, &sh4r.fr[1][11] },{"XF11", REG_FLOAT, &sh4r.fr[1][10]},
1.75 + {"XF12", REG_FLOAT, &sh4r.fr[1][13] },{"XF13", REG_FLOAT, &sh4r.fr[1][12]},
1.76 + {"XF14", REG_FLOAT, &sh4r.fr[1][15] },{"XF15", REG_FLOAT, &sh4r.fr[1][14]},
1.77 +
1.78 + {NULL, 0, NULL} };
1.79 +
1.80 +void *sh4_get_register( int reg )
1.81 +{
1.82 + if( reg < 0 || reg >= 94 ) {
1.83 + return NULL;
1.84 + } else if( reg < 43 ) {
1.85 + return sh4_reg_map[reg].value;
1.86 + } else if( reg < 51 ) {
1.87 + /* r0b0..r7b0 */
1.88 + if( (sh4r.sr & SR_MDRB) == SR_MDRB ) {
1.89 + /* bank 1 is primary */
1.90 + return &sh4r.r_bank[reg-43];
1.91 + } else {
1.92 + return &sh4r.r[reg-43];
1.93 + }
1.94 + } else if( reg < 59 ) {
1.95 + /* r0b1..r7b1 */
1.96 + if( (sh4r.sr & SR_MDRB) == SR_MDRB ) {
1.97 + /* bank 1 is primary */
1.98 + return &sh4r.r[reg-43];
1.99 + } else {
1.100 + return &sh4r.r_bank[reg-43];
1.101 + }
1.102 + } else {
1.103 + return NULL; /* not supported at the moment */
1.104 + }
1.105 +}
1.106 +
1.107 +
1.108 +const struct cpu_desc_struct sh4_cpu_desc =
1.109 + { "SH4", sh4_disasm_instruction, sh4_get_register, sh4_has_page,
1.110 + sh4_debug_read_phys, sh4_debug_write_phys, sh4_debug_read_vma, sh4_debug_write_vma,
1.111 + sh4_execute_instruction,
1.112 + sh4_set_breakpoint, sh4_clear_breakpoint, sh4_get_breakpoint, 2,
1.113 + (char *)&sh4r, sizeof(sh4r), sh4_reg_map, 23, 59,
1.114 + &sh4r.pc };
1.115 +
1.116 struct dreamcast_module sh4_module = { "SH4", sh4_init, sh4_poweron_reset,
1.117 sh4_start, sh4_run_slice, sh4_stop,
1.118 sh4_save_state, sh4_load_state };
1.119 @@ -546,3 +637,77 @@
1.120 sh4addr_t addr = mmu_vma_to_phys_disasm(vma);
1.121 return addr != MMU_VMA_ERROR && mem_has_page(addr);
1.122 }
1.123 +
1.124 +/**
1.125 + * Go through ext_address_space page by page
1.126 + */
1.127 +size_t sh4_debug_read_phys( unsigned char *buf, uint32_t addr, size_t length )
1.128 +{
1.129 + /* Quick and very dirty */
1.130 + unsigned char *region = mem_get_region(addr);
1.131 + if( region == NULL ) {
1.132 + memset( buf, 0, length );
1.133 + } else {
1.134 + memcpy( buf, region, length );
1.135 + }
1.136 + return length;
1.137 +}
1.138 +
1.139 +size_t sh4_debug_write_phys( uint32_t addr, unsigned char *buf, size_t length )
1.140 +{
1.141 + unsigned char *region = mem_get_region(addr);
1.142 + if( region != NULL ) {
1.143 + memcpy( region, buf, length );
1.144 + }
1.145 + return length;
1.146 +}
1.147 +
1.148 +/**
1.149 + * Read virtual memory - for now just go 1K at a time
1.150 + */
1.151 +size_t sh4_debug_read_vma( unsigned char *buf, uint32_t addr, size_t length )
1.152 +{
1.153 + if( IS_TLB_ENABLED() ) {
1.154 + size_t read_len = 0;
1.155 + while( length > 0 ) {
1.156 + sh4addr_t phys = mmu_vma_to_phys_disasm(addr);
1.157 + if( phys == MMU_VMA_ERROR )
1.158 + break;
1.159 + int next_len = 1024 - (phys&0x000003FF);
1.160 + if( next_len >= length ) {
1.161 + next_len = length;
1.162 + }
1.163 + sh4_debug_read_phys( buf, phys, length );
1.164 + buf += next_len;
1.165 + addr += next_len;
1.166 + read_len += next_len;
1.167 + length -= next_len;
1.168 + }
1.169 + return read_len;
1.170 + } else {
1.171 + return sh4_debug_read_phys( buf, addr, length );
1.172 + }
1.173 +}
1.174 +
1.175 +size_t sh4_debug_write_vma( uint32_t addr, unsigned char *buf, size_t length )
1.176 +{
1.177 + if( IS_TLB_ENABLED() ) {
1.178 + size_t read_len = 0;
1.179 + while( length > 0 ) {
1.180 + sh4addr_t phys = mmu_vma_to_phys_disasm(addr);
1.181 + if( phys == MMU_VMA_ERROR )
1.182 + break;
1.183 + int next_len = 1024 - (phys&0x000003FF);
1.184 + if( next_len >= length ) {
1.185 + next_len = length;
1.186 + }
1.187 + sh4_debug_write_phys( phys, buf, length );
1.188 + buf += next_len;
1.189 + addr += next_len;
1.190 + read_len += next_len;
1.191 + length -= next_len;
1.192 + }
1.193 + } else {
1.194 + return sh4_debug_write_phys( addr, buf, length );
1.195 + }
1.196 +}
.