mipsreg.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 828 行 · 第 1/2 页
C
828 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: MIPS machine register description.
*
****************************************************************************/
#include <stddef.h>
#include <string.h>
#include <ctype.h>
#include "mips.h"
#include "mipstypes.h"
#include "madregs.h"
#define BIT_OFF( who ) (offsetof( mad_registers, mips.who ) * BITS_PER_BYTE)
/* Macros to get at GP/FP registers based on their number; useful in loops */
#define TRANS_GPREG_LO( mr, idx ) (*((unsigned_32 *)(&(mr.r0.u._32[I64LO32])) + (2 * idx)))
#define TRANS_GPREG_HI( mr, idx ) (*((unsigned_32 *)(&(mr.r0.u._32[I64HI32])) + (2 * idx)))
#define TRANS_FPREG_LO( mr, idx ) (*((unsigned_32 *)(&(mr.f0.u64.u._32[I64LO32])) + (2 * idx)))
#define TRANS_FPREG_HI( mr, idx ) (*((unsigned_32 *)(&(mr.f0.u64.u._32[I64HI32])) + (2 * idx)))
enum {
RS_NONE,
RS_DWORD,
RS_WORD,
RS_DOUBLE,
RS_FPCSR,
RS_NUM,
};
#define REG_NAME( name ) const char NAME_##name[] = #name
typedef struct {
char name[5];
unsigned_8 start;
mad_type_handle mth;
} sublist_data;
static const sublist_data DwordRegSubData[] = {
{ "b0", 0, MIPST_BYTE },
{ "b1", 8, MIPST_BYTE },
{ "b2", 16, MIPST_BYTE },
{ "b3", 24, MIPST_BYTE },
{ "b4", 32, MIPST_BYTE },
{ "b5", 40, MIPST_BYTE },
{ "b6", 48, MIPST_BYTE },
{ "b7", 56, MIPST_BYTE },
{ "h0", 0, MIPST_HALF },
{ "h1", 16, MIPST_HALF },
{ "h2", 32, MIPST_HALF },
{ "h3", 48, MIPST_HALF },
{ "w0", 0, MIPST_WORD },
{ "w1", 32, MIPST_WORD },
};
#define sublist( name, type, reg_set, base, start, len ) \
{ { NAME_##name, \
MIPST_##type, \
BIT_OFF( base )+start, \
len, \
1 }, \
reg_set##_REG_SET, RS_NONE },
REG_NAME( rm );
REG_NAME( fi );
REG_NAME( fu );
REG_NAME( fo );
REG_NAME( fz );
REG_NAME( fv );
REG_NAME( ei );
REG_NAME( eu );
REG_NAME( eo );
REG_NAME( ez );
REG_NAME( ev );
REG_NAME( ci );
REG_NAME( cu );
REG_NAME( co );
REG_NAME( cz );
REG_NAME( cv );
REG_NAME( cn );
REG_NAME( c );
static const mips_reg_info FPCSRSubList[] = {
sublist( rm, BYTE, FPU, fpcsr, 0, 2 )
sublist( fi, BYTE, FPU, fpcsr, 2, 1 )
sublist( fu, BYTE, FPU, fpcsr, 3, 1 )
sublist( fo, BYTE, FPU, fpcsr, 4, 1 )
sublist( fz, BYTE, FPU, fpcsr, 5, 1 )
sublist( fv, BYTE, FPU, fpcsr, 6, 1 )
sublist( ei, BYTE, FPU, fpcsr, 7, 1 )
sublist( eu, BYTE, FPU, fpcsr, 8, 1 )
sublist( eo, BYTE, FPU, fpcsr, 9, 1 )
sublist( ez, BYTE, FPU, fpcsr, 10, 1 )
sublist( ev, BYTE, FPU, fpcsr, 11, 1 )
sublist( ci, BYTE, FPU, fpcsr, 12, 1 )
sublist( cu, BYTE, FPU, fpcsr, 13, 1 )
sublist( co, BYTE, FPU, fpcsr, 14, 1 )
sublist( cz, BYTE, FPU, fpcsr, 15, 1 )
sublist( cv, BYTE, FPU, fpcsr, 16, 1 )
sublist( cn, BYTE, FPU, fpcsr, 17, 1 )
sublist( c, BYTE, FPU, fpcsr, 23, 1 )
{ NULL }
};
static const mips_reg_info *SubList[] =
{
NULL,
NULL,
NULL,
NULL,
FPCSRSubList,
};
#define MIPST_U32 MIPST_WORD
#define MIPST_U64 MIPST_DWORD
#define XREG_TYPE( bits ) MIPST_U##bits
#define REG_TYPE( bits ) XREG_TYPE( bits )
#define REG_BITS_WORD 32
#define REG_BITS_DWORD 64
#define REG_BITS_DOUBLE 64
#define REG_BITS_FPCSR REG_BITS_WORD
#define RT_DOUBLE MIPST_DOUBLE
#define RT_DWORD MIPST_DWORD
#define RT_WORD REG_TYPE( REG_BITS_WORD )
#define RT_FPCSR RT_WORD
/* to avoid relocations to R/W data segments */
#define regpick( name, type, s ) REG_NAME( name );
#include "mipsregs.h"
#undef regpick
#define regpick( name, type, reg_set ) \
{ { NAME_##name, \
RT_##type, \
BIT_OFF( name ), \
REG_BITS_##type, \
1 }, \
reg_set##_REG_SET, RS_##type },
const mips_reg_info RegList[] = {
#include "mipsregs.h"
};
// For 64-bit registers displayed as 32-bit - 32GPRs + pc
// NB: Relies on the fact that all the 64-bit registers are grouped together
// in a single block.
static mips_reg_info RegListHalf[32 + 32 + 1];
static mips_reg_info **RegSubList;
static const mad_toggle_strings CPUToggleList[] =
{
{ MSTR_MHEX, MSTR_HEX, MSTR_DECIMAL },
{ MSTR_MEXTENDED, MSTR_REG_EXTENDED, MSTR_REG_NORMAL },
{ MSTR_MSYMBOLIC, MSTR_REG_SYMBOLIC, MSTR_REG_NUMERIC },
{ MSTR_NIL, MSTR_NIL, MSTR_NIL }
};
static const mad_toggle_strings FPUToggleList[] =
{
{ MSTR_MHEX, MSTR_HEX, MSTR_DECIMAL},
{ MSTR_NIL, MSTR_NIL, MSTR_NIL}
};
struct mad_reg_set_data {
mad_status (*get_piece)( unsigned piece, char **descript, unsigned *max_descript, const mad_reg_info **reg, mad_type_handle *disp_type, unsigned *max_value );
const mad_toggle_strings *togglelist;
mad_string name;
};
static mad_status CPUGetPiece( unsigned piece,
char **descript,
unsigned *max_descript,
const mad_reg_info **reg,
mad_type_handle *disp_type,
unsigned *max_value );
static mad_status FPUGetPiece( unsigned piece,
char **descript,
unsigned *max_descript,
const mad_reg_info **reg,
mad_type_handle *disp_type,
unsigned *max_value );
static const mad_reg_set_data RegSet[] = {
{ CPUGetPiece, CPUToggleList, MSTR_CPU },
{ FPUGetPiece, FPUToggleList, MSTR_FPU },
};
unsigned DIGENTRY MIRegistersSize( void )
{
return( sizeof( struct mips_mad_registers ) );
}
mad_status DIGENTRY MIRegistersHost( mad_registers *mr )
{
#if defined( __BIG_ENDIAN__ )
unsigned_32 temp;
int i;
// Currently harcoded for little endian targets - should be dynamic
// And we really ought to have a 64-bit byte swap routine...
// Convert GPRs
for( i = 0; i < 32; i++ ) {
CONV_BE_32( TRANS_GPREG_LO( mr->mips, i ) );
CONV_BE_32( TRANS_GPREG_HI( mr->mips, i ) );
temp = TRANS_GPREG_LO( mr->mips, i );
TRANS_GPREG_LO( mr->mips, i ) = TRANS_GPREG_HI( mr->mips, i );
TRANS_GPREG_HI( mr->mips, i ) = temp;
}
// Convert FPRs
for( i = 0; i < 32; i++ ) {
CONV_BE_32( TRANS_FPREG_LO( mr->mips, i ) );
CONV_BE_32( TRANS_FPREG_HI( mr->mips, i ) );
temp = TRANS_FPREG_LO( mr->mips, i );
TRANS_FPREG_LO( mr->mips, i ) = TRANS_FPREG_HI( mr->mips, i );
TRANS_FPREG_HI( mr->mips, i ) = temp;
}
// Convert special registers
CONV_BE_32( mr->mips.pc.u._32[I64LO32] );
CONV_BE_32( mr->mips.pc.u._32[I64HI32] );
temp = mr->mips.pc.u._32[I64LO32];
mr->mips.pc.u._32[I64LO32] = mr->mips.pc.u._32[I64HI32];
mr->mips.pc.u._32[I64HI32] = temp;
CONV_BE_32( mr->mips.lo );
CONV_BE_32( mr->mips.hi );
CONV_BE_32( mr->mips.fpcsr );
CONV_BE_32( mr->mips.fpivr );
#endif
return( MS_OK );
}
mad_status DIGENTRY MIRegistersTarget( mad_registers *mr )
{
#if defined( __BIG_ENDIAN__ )
unsigned_32 temp;
int i;
// Convert GPRs
for( i = 0; i < 32; i++ ) {
CONV_BE_32( TRANS_GPREG_LO( mr->mips, i ) );
CONV_BE_32( TRANS_GPREG_HI( mr->mips, i ) );
temp = TRANS_GPREG_LO( mr->mips, i );
TRANS_GPREG_LO( mr->mips, i ) = TRANS_GPREG_HI( mr->mips, i );
TRANS_GPREG_HI( mr->mips, i ) = temp;
}
// Convert FPRs
for( i = 0; i < 32; i++ ) {
CONV_BE_32( TRANS_FPREG_LO( mr->mips, i ) );
CONV_BE_32( TRANS_FPREG_HI( mr->mips, i ) );
temp = TRANS_FPREG_LO( mr->mips, i );
TRANS_FPREG_LO( mr->mips, i ) = TRANS_FPREG_HI( mr->mips, i );
TRANS_FPREG_HI( mr->mips, i ) = temp;
}
// Convert special registers
CONV_BE_32( mr->mips.pc.u._32[I64LO32] );
CONV_BE_32( mr->mips.pc.u._32[I64HI32] );
temp = mr->mips.pc.u._32[I64LO32];
mr->mips.pc.u._32[I64LO32] = mr->mips.pc.u._32[I64HI32];
mr->mips.pc.u._32[I64HI32] = temp;
CONV_BE_32( mr->mips.lo );
CONV_BE_32( mr->mips.hi );
CONV_BE_32( mr->mips.fpcsr );
CONV_BE_32( mr->mips.fpivr );
#endif
return( MS_OK );
}
walk_result DIGENTRY MIRegSetWalk( mad_type_kind tk, MI_REG_SET_WALKER *wk, void *d )
{
walk_result wr;
if( tk & MTK_INTEGER ) {
wr = wk( &RegSet[CPU_REG_SET], d );
if( wr != WR_CONTINUE ) return( wr );
}
if( tk & MTK_FLOAT ) {
wr = wk( &RegSet[FPU_REG_SET], d );
if( wr != WR_CONTINUE ) return( wr );
}
return( WR_CONTINUE );
}
mad_string DIGENTRY MIRegSetName( const mad_reg_set_data *rsd )
{
return( rsd->name );
}
unsigned DIGENTRY MIRegSetLevel( const mad_reg_set_data *rsd, unsigned max, char *buff )
{
char str[80];
unsigned len;
if( rsd == &RegSet[CPU_REG_SET] ) {
switch( MCSystemConfig()->cpu ) {
case MIPS_R2000:
strcpy( str, "R2000" );
break;
case MIPS_R3000:
strcpy( str, "R3000" );
break;
case MIPS_R4000:
strcpy( str, "R4000" );
break;
case MIPS_R5000:
strcpy( str, "R5000" );
break;
default:
str[0] = '\0';
break;
}
} else {
str[0] = '\0';
}
len = strlen( str );
if( max > 0 ) {
--max;
if( max > len ) max = len;
memcpy( buff, str, max );
buff[max] = '\0';
}
return( len );
}
unsigned DIGENTRY MIRegSetDisplayGrouping( const mad_reg_set_data *rsd )
{
return( 0 );
}
static char DescriptBuff[10];
typedef struct {
unsigned_16 first_reg_idx;
unsigned_8 num_regs;
unsigned_8 disp_type;
} reg_display_entry;
/* Note that $zero isn't displayed - it'd just waste valuable space */
static const reg_display_entry CPUNumeric[] = {
{ IDX_r1, 31, MIPST_DWORD },
{ IDX_pc, 1, MIPST_DWORD },
{ IDX_lo, 2, MIPST_WORD },
{ 0, 0, 0 }
};
static const reg_display_entry CPUSymbolic[] = {
{ IDX_at, 31, MIPST_DWORD },
{ IDX_pc, 1, MIPST_DWORD },
{ IDX_lo, 2, MIPST_WORD },
{ 0, 0, 0 }
};
static int FindEntry( const reg_display_entry *tbl, unsigned piece,
unsigned *idx, mad_type_handle *type )
{
for( ;; ) {
if( tbl->num_regs == 0 ) return( 0 );
if( tbl->num_regs > piece ) break;
piece -= tbl->num_regs;
++tbl;
}
*idx = tbl->first_reg_idx + piece;
*type = tbl->disp_type;
return( 1 );
}
static mad_status CPUGetPiece( unsigned piece,
char **descript,
unsigned *max_descript,
const mad_reg_info **reg,
mad_type_handle *disp_type,
unsigned *max_value )
{
unsigned idx;
if( MADState->reg_state[CPU_REG_SET] & CT_SYMBOLIC_NAMES ) {
if( !FindEntry( CPUSymbolic, piece, &idx, disp_type ) ) return( MS_FAIL );
} else {
if( !FindEntry( CPUNumeric, piece, &idx, disp_type ) ) return( MS_FAIL );
}
*reg = &RegList[idx].info;
if( !(MADState->reg_state[CPU_REG_SET] & CT_EXTENDED) ) {
if( *disp_type == MIPST_DWORD ) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?