ppcreg.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 802 行 · 第 1/2 页
C
802 行
/****************************************************************************
*
* 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: PowerPC machine register description.
*
****************************************************************************/
#include <stddef.h>
#include <string.h>
#include <ctype.h>
#include "ppc.h"
#include "ppctypes.h"
#include "madregs.h"
#define BIT_OFF( who ) (offsetof( mad_registers, ppc.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_MSR,
RS_XER,
RS_PCSCR,
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 IntRegSubData[] = {
{ "b0", 0, PPCT_BYTE },
{ "b1", 8, PPCT_BYTE },
{ "b2", 16, PPCT_BYTE },
{ "b3", 24, PPCT_BYTE },
{ "b4", 32, PPCT_BYTE },
{ "b5", 40, PPCT_BYTE },
{ "b6", 48, PPCT_BYTE },
{ "b7", 56, PPCT_BYTE },
{ "h0", 0, PPCT_HWORD },
{ "h1", 16, PPCT_HWORD },
{ "h2", 32, PPCT_HWORD },
{ "h3", 48, PPCT_HWORD },
{ "w0", 0, PPCT_WORD },
{ "w1", 32, PPCT_WORD },
};
#define sublist( name, type, reg_set, base, start, len ) \
{ { NAME_##name, \
PPCT_##type, \
BIT_OFF( base )+start, \
len, \
1 }, \
reg_set##_REG_SET, RS_NONE },
static const ppc_reg_info *SubList[] =
{
//NYI:
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
};
#define PPCT_U32 PPCT_WORD
#define PPCT_U64 PPCT_DWORD
#define XREG_TYPE( bits ) PPCT_U##bits
#define REG_TYPE( bits ) XREG_TYPE( bits )
#define REG_BITS_WORD 32
#define REG_BITS_DWORD 64
#define REG_BITS_DOUBLE 64
/* to avoid relocations to R/W data segments */
#define regpick( name, type, s ) REG_NAME( name );
#include "ppcregs.h"
#undef regpick
#define regpick( name, type, reg_set ) \
{ { NAME_##name, \
PPCT_##type, \
BIT_OFF( name ), \
REG_BITS_##type, \
1 }, \
reg_set##_REG_SET, RS_##type },
const ppc_reg_info RegList[] = {
#include "ppcregs.h"
};
// For 64-bit registers displayed as 32-bit - 32GPRs + sp, lr, iar, ctr, msr
// NB: Relies on the fact that all the DWORD registers are grouped together
// in a single block.
static ppc_reg_info RegListHalf[32 + 5];
static ppc_reg_info **RegSubList;
static const mad_toggle_strings CPUToggleList[] =
{
{MSTR_MHEX,MSTR_HEX,MSTR_DECIMAL},
{MSTR_MEXTENDED,MSTR_REG_EXTENDED,MSTR_REG_NORMAL},
{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 ppc_mad_registers ) );
}
mad_status DIGENTRY MIRegistersHost( mad_registers *mr )
{
#if !defined( __BIG_ENDIAN__ )
unsigned_32 temp;
int i;
// Currently harcoded for big 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->ppc, i ) );
CONV_BE_32( TRANS_GPREG_HI( mr->ppc, i ) );
temp = TRANS_GPREG_LO( mr->ppc, i );
TRANS_GPREG_LO( mr->ppc, i ) = TRANS_GPREG_HI( mr->ppc, i );
TRANS_GPREG_HI( mr->ppc, i ) = temp;
}
// Convert FPRs
for( i = 0; i < 32; i++ ) {
CONV_BE_32( TRANS_FPREG_LO( mr->ppc, i ) );
CONV_BE_32( TRANS_FPREG_HI( mr->ppc, i ) );
temp = TRANS_FPREG_LO( mr->ppc, i );
TRANS_FPREG_LO( mr->ppc, i ) = TRANS_FPREG_HI( mr->ppc, i );
TRANS_FPREG_HI( mr->ppc, i ) = temp;
}
// Convert special registers
CONV_BE_32( mr->ppc.iar.u._32[I64LO32] );
CONV_BE_32( mr->ppc.iar.u._32[I64HI32] );
temp = mr->ppc.iar.u._32[I64LO32];
mr->ppc.iar.u._32[I64LO32] = mr->ppc.iar.u._32[I64HI32];
mr->ppc.iar.u._32[I64HI32] = temp;
CONV_BE_32( mr->ppc.msr.u._32[I64LO32] );
CONV_BE_32( mr->ppc.msr.u._32[I64HI32] );
temp = mr->ppc.msr.u._32[I64LO32];
mr->ppc.msr.u._32[I64LO32] = mr->ppc.msr.u._32[I64HI32];
mr->ppc.msr.u._32[I64HI32] = temp;
CONV_BE_32( mr->ppc.ctr.u._32[I64LO32] );
CONV_BE_32( mr->ppc.ctr.u._32[I64HI32] );
temp = mr->ppc.ctr.u._32[I64LO32];
mr->ppc.ctr.u._32[I64LO32] = mr->ppc.ctr.u._32[I64HI32];
mr->ppc.ctr.u._32[I64HI32] = temp;
CONV_BE_32( mr->ppc.lr.u._32[I64LO32] );
CONV_BE_32( mr->ppc.lr.u._32[I64HI32] );
temp = mr->ppc.lr.u._32[I64LO32];
mr->ppc.lr.u._32[I64LO32] = mr->ppc.lr.u._32[I64HI32];
mr->ppc.lr.u._32[I64HI32] = temp;
CONV_BE_32( mr->ppc.xer );
CONV_BE_32( mr->ppc.cr );
CONV_BE_32( mr->ppc.fpscr );
#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->ppc, i ) );
CONV_BE_32( TRANS_GPREG_HI( mr->ppc, i ) );
temp = TRANS_GPREG_LO( mr->ppc, i );
TRANS_GPREG_LO( mr->ppc, i ) = TRANS_GPREG_HI( mr->ppc, i );
TRANS_GPREG_HI( mr->ppc, i ) = temp;
}
// Convert FPRs
for( i = 0; i < 32; i++ ) {
CONV_BE_32( TRANS_FPREG_LO( mr->ppc, i ) );
CONV_BE_32( TRANS_FPREG_HI( mr->ppc, i ) );
temp = TRANS_FPREG_LO( mr->ppc, i );
TRANS_FPREG_LO( mr->ppc, i ) = TRANS_FPREG_HI( mr->ppc, i );
TRANS_FPREG_HI( mr->ppc, i ) = temp;
}
// Convert special registers
CONV_BE_32( mr->ppc.iar.u._32[I64LO32] );
CONV_BE_32( mr->ppc.iar.u._32[I64HI32] );
temp = mr->ppc.iar.u._32[I64LO32];
mr->ppc.iar.u._32[I64LO32] = mr->ppc.iar.u._32[I64HI32];
mr->ppc.iar.u._32[I64HI32] = temp;
CONV_BE_32( mr->ppc.msr.u._32[I64LO32] );
CONV_BE_32( mr->ppc.msr.u._32[I64HI32] );
temp = mr->ppc.msr.u._32[I64LO32];
mr->ppc.msr.u._32[I64LO32] = mr->ppc.msr.u._32[I64HI32];
mr->ppc.msr.u._32[I64HI32] = temp;
CONV_BE_32( mr->ppc.ctr.u._32[I64LO32] );
CONV_BE_32( mr->ppc.ctr.u._32[I64HI32] );
temp = mr->ppc.ctr.u._32[I64LO32];
mr->ppc.ctr.u._32[I64LO32] = mr->ppc.ctr.u._32[I64HI32];
mr->ppc.ctr.u._32[I64HI32] = temp;
CONV_BE_32( mr->ppc.lr.u._32[I64LO32] );
CONV_BE_32( mr->ppc.lr.u._32[I64HI32] );
temp = mr->ppc.lr.u._32[I64LO32];
mr->ppc.lr.u._32[I64LO32] = mr->ppc.lr.u._32[I64HI32];
mr->ppc.lr.u._32[I64HI32] = temp;
CONV_BE_32( mr->ppc.xer );
CONV_BE_32( mr->ppc.cr );
CONV_BE_32( mr->ppc.fpscr );
#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 PPC_601:
strcpy( str, "601" );
break;
case PPC_603:
strcpy( str, "603" );
break;
case PPC_604:
strcpy( str, "604" );
break;
case PPC_620:
strcpy( str, "620" );
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;
static const reg_display_entry CPUNumeric[] = {
{ IDX_r0, 32, PPCT_H_DWORD },
{ IDX_lr, 4, PPCT_H_DWORD },
{ IDX_cr, 2, PPCT_H_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( !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 == PPCT_H_DWORD ) {
*disp_type = PPCT_H_WORD;
*reg = &RegListHalf[idx - IDX_r0].info;
}
}
//NYI: if extended & ~ 64 bit mode, downshift to 32-bit display.
// Also, if 64 <=> 32 bit switch, tell client to redraw window
if( !(MADState->reg_state[CPU_REG_SET] & CT_HEX) ) {
switch( *disp_type ) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?