📄 cpu.c
字号:
/************************************************************************ * find_reg ************************************************************************/static UINT32find_reg( char *reg_name ){ UINT32 i; for( i=0; (strcasecmp(reg_name, regs[i].name) != 0) && (i < REG_COUNT); i++ ); return i;}/************************************************************************ * * print_reg * Description : * ------------- * * Print CP0 register while handling indentation so that print of * additional registers is lined up nicely. * ************************************************************************/static boolprint_reg( bool multi, bool silent, bool width32, bool even, char *s, UINT64 value, bool shell ){ char msg[80]; UINT32 len; UINT32 i; UINT32 maxlen_left; len = strlen( s ); if( silent ) { if( even ) maxlen_name_left = MAX(maxlen_name_left, len); else maxlen_name_right = MAX(maxlen_name_right, len); if( !width32 ) val64_left = TRUE; return OK; } else maxlen_left = maxlen_name_left + (val64_left ? 23 : 15); strcpy( msg, s ); i = len; if( multi ) { for( ; i<(even ? maxlen_name_left : maxlen_name_right); i++ ) msg[i] = ' '; } if( width32 ) sprintf( &msg[i], " = 0x%08x", (UINT32)value ); else sprintf( &msg[i], " = 0x%08x%08x", HI32(value), LO32(value) ); if( even && multi ) { len = strlen( msg ); for( i=len; i<maxlen_left; i++ ) msg[i] = ' '; msg[i] = '\0'; } else strcat( msg, "\n" ); if( shell ) return SHELL_PUTS( msg ); else { printf( "%s", msg ); return FALSE; }}/************************************************************************ * * print_regs * Description : * ------------- * * Print one or all CP0 registers that are available for CPU. * ************************************************************************/static UINT32print_regs( bool all, bool silent, UINT32 index_single, t_gdb_regs *context ){ UINT32 i; UINT32 rc; char *name; UINT8 width; UINT32 syscon_id; UINT32 gdb_offset; bool even = TRUE; UINT32 value32; UINT64 value64; if( silent ) { maxlen_name_left = 0; maxlen_name_right = 0; val64_left = FALSE; } for(i=(all ? 0 : index_single); i<=(all ? REG_COUNT-1 : index_single); i++ ) { name = regs[i].name; width = sys_64bit ? regs[i].width : 32; if( silent ) { syscon_id = regs[i].syscon_id; gdb_offset = regs[i].gdb_offset; rc = (width == 64) ? SYSCON_read( syscon_id, &value64, sizeof(UINT64) ) : SYSCON_read( syscon_id, &value32, sizeof(UINT32) ); if( (rc == OK) && context ) { if( EXCEP_nmi && ((gdb_offset == GDB_FR_CAUSE) || (gdb_offset == GDB_FR_CP0_WATCHLO) || (gdb_offset == GDB_FR_CP0_WATCHHI)) ) { /* Cause, WatchLo, WatchHi don't make sense for NMI, * since they are modified by the reset code, * which is excecuted upon an NMI. * Status is also modified somewhat (IE,KSU fields * are cleared), but we display it anyway. */ rc = NOT_OK; } else if( gdb_offset != -1 ) { if(width == 64) value64 = *GDB_REG64(context, gdb_offset); else value32 = *GDB_REG32(context, gdb_offset); } else { rc = NOT_OK; } } regs[i].rc = rc; if(width == 32) regs[i].val.value32 = value32; else regs[i].val.value64 = value64; } else { rc = regs[i].rc; if(width == 32) value32 = regs[i].val.value32; else value64 = regs[i].val.value64; } if( (rc != OK) && !all ) return SHELL_ERROR_UNKNOWN_CP0_REG; if( rc == OK ) { if( print_reg( all, silent, ((width == 64) ? W64 : W32), even, name, ((width == 64) ? value64 : (UINT64)value32), context ? FALSE : TRUE ) ) { return SHELL_ERROR_CONTROL_C_DETECTED; } else even = !even; } } if( !context ) { if( all && !even && !silent ) return SHELL_PUTS( "\n" ) ? SHELL_ERROR_CONTROL_C_DETECTED : OK; } else { if( sys_fpu && (UINT32)context->cp0_status & M_StatusCU1 ) { print_reg( all, silent, W32, even, "FCSR", (UINT32)context->cp1_fsr, FALSE ); even = !even; } print_reg( all, silent, (sys_64bit ? W64 : W32), even, "Hi", context->hi, FALSE ); print_reg( all, silent, (sys_64bit ? W64 : W32), !even, "Lo", context->lo, FALSE ); if( !even && !silent ) printf( "\n" ); } return OK;}/************************************************************************ * sys_uncached ************************************************************************/static boolsys_uncached( void ){ UINT32 config; SYSCON_read( SYSCON_CPU_CP0_CONFIG_ID, &config, sizeof(UINT32) ); return ((config & M_ConfigK0) >> S_ConfigK0) == K_CacheAttrU ? TRUE : FALSE;}/************************************************************************ * sys_l2_flush_all ************************************************************************/static voidsys_l2_flush_all( void ){ UINT32 line; UINT32 addr; for( line = 0, addr = KSEG0(0); line < sys_l2cache_lines; line++, addr += sys_l2cache_linesize ) { sys_scache_flush_index( addr ); }}/************************************************************************ * * sys_cp0_printreg_all * Description : * ------------- * * Print CP0 registers. * ************************************************************************/UINT32sys_cp0_printreg_all( t_gdb_regs *context ) // If not NULL, this holds the context to be dumped. // If NULL, print current values of all CP0 regs.{ static bool init = TRUE; /* Note : This function is self-initialising. The first * call causes the cp0 table to be sorted. */ if( init ) { init = FALSE; /* Sort the table */ qsort( (char *)regs, (int)REG_COUNT, (int)sizeof(t_cp0_reg), compare ); } /* Pass 1 : Get availability and values of registers and determine indentations */ print_regs( TRUE, TRUE, 0, context ); /* Pass 2 : Print values */ return print_regs( TRUE, FALSE, 0, context );}/************************************************************************ * * sys_cp0_printreg * Description : * ------------- * * Print value of CP0 register specified by name. * ************************************************************************/UINT32sys_cp0_printreg( char *reg_name ) // Name of register.{ /* Register selected by name */ UINT32 i = find_reg( reg_name ); /* Pass 1 (get availability and value of register */ print_regs( FALSE, TRUE, i, NULL ); return ( i == REG_COUNT ) ? SHELL_ERROR_UNKNOWN_CP0_REG : print_regs( FALSE, FALSE, i, NULL ); /* Pass 2 : Print value */}/************************************************************************ * * sys_cp0_writereg * Description : * ------------- * * Write to CP0 register specified by name. * ************************************************************************/UINT32sys_cp0_writereg( char *reg_name, // Name of register. UINT64 value ) // Value to be written.{ /* Register selected by name */ UINT32 width; UINT32 rc; UINT32 i; UINT32 value32 = (UINT32)value; i = find_reg( reg_name ); if( i == REG_COUNT ) return SHELL_ERROR_UNKNOWN_CP0_REG; width = sys_64bit ? regs[i].width : 32; rc = (width == 64) ? SYSCON_write( regs[i].syscon_id, &value, sizeof(UINT64) ) : SYSCON_write( regs[i].syscon_id, &value32, sizeof(UINT32) ); if( rc != OK ) return SHELL_ERROR_RO_CP0_REG; else return OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -