📄 mpc.c
字号:
/*
* File: mpc.c
* Purpose: PowerPC assembly and disassembly.
*
* Notes:
*
*/
#include "src/include/dbug.h"
#include "src/uif/cpu.h"
#include "src/uif/sym.h"
/********************************************************************/
#define SYMBOL_TABLE
#define REG_INT (1)
#define REG_FLOAT (2)
#define EA_OFFSET (30) /* offset before appending EA */
static const char
COMMA[] = ",";
typedef struct
{
uint32 keepers;
uint32 match;
char *instruction;
void (*dishandler)(unsigned int);
int (*asmhandler)(void);
} INSTRENTRY;
extern const
INSTRENTRY isa[];
/********************************************************************/
static char
dstr[80];
static ADDRESS
disasm_pc;
static int
valid_instruction;
static INSTRUCTION
asm_insn;
static ADDRESS
asm_pc;
/********************************************************************/
#define append_string(a,b) strcat(a,b)
/********************************************************************/
static uint32
get_gpr(int gpr)
{
extern REGISTERS context;
switch (gpr)
{
case 0: return context.r0; break;
case 1: return context.r1; break;
case 2: return context.r2; break;
case 3: return context.r3; break;
case 4: return context.r4; break;
case 5: return context.r5; break;
case 6: return context.r6; break;
case 7: return context.r7; break;
case 8: return context.r8; break;
case 9: return context.r9; break;
case 10: return context.r10; break;
case 11: return context.r11; break;
case 12: return context.r12; break;
case 13: return context.r13; break;
case 14: return context.r14; break;
case 15: return context.r15; break;
case 16: return context.r16; break;
case 17: return context.r17; break;
case 18: return context.r18; break;
case 19: return context.r19; break;
case 20: return context.r20; break;
case 21: return context.r21; break;
case 22: return context.r22; break;
case 23: return context.r23; break;
case 24: return context.r24; break;
case 25: return context.r25; break;
case 26: return context.r26; break;
case 27: return context.r27; break;
case 28: return context.r28; break;
case 29: return context.r29; break;
case 30: return context.r30; break;
case 31: return context.r31; break;
default:
return 0; break;
}
}
/********************************************************************/
static void
append_eastr (char *buf, uint32 ea)
{
char eastr[20];
int index;
/* Pad out to EA_OFFSET */
for (index = strlen(buf); index < EA_OFFSET; ++index)
append_string(buf," ");
sprintf(eastr,"(EA: %08X)", ea);
append_string(buf,eastr);
}
/********************************************************************/
static void
append_ea_rA_0_d (char *buf, int d, int rA)
{
/*
* EA = (rA|0) + d
*/
uint32 ea;
if (rA == 0)
ea = 0;
else
ea = get_gpr(rA);
if (d < 0)
ea -= (~d+1);
else
ea += d;
append_eastr(buf,ea);
}
/********************************************************************/
static void
append_ea_rA_d (char *buf, int d, int rA)
{
/*
* EA = (rA) + d
*/
uint32 ea;
ea = get_gpr(rA);
if (d < 0)
ea -= (~d+1);
else
ea += d;
append_eastr(buf,ea);
}
/********************************************************************/
static void
append_ea_rA_0_rB (char *buf, int rA, int rB)
{
/*
* EA = (rA|0) + (rB)
*/
uint32 ea;
if (rA == 0)
ea = 0;
else
ea = get_gpr(rA);
ea += get_gpr(rB);
append_eastr(buf,ea);
}
/********************************************************************/
static void
append_ea_rA_rB (char *buf, int rA, int rB)
{
/*
* EA = (rA) + (rB)
*/
uint32 ea;
ea = get_gpr(rA) + get_gpr(rB);
append_eastr(buf,ea);
}
/********************************************************************/
static void
append_instruction (char *buf, char *instruction)
{
sprintf(buf,"%-10s",instruction);
}
/********************************************************************/
static void
append_Xbit_number (char *buf, int opword, int bits, int offset)
{
/*
* This field accepts `opword' and then determines according
* to the offsets what size 'bit' number is.
* The number is then concatenated to the end of the
* disasm_stmt.
*
* The `offset' is given by the bit number as listed in the
* PowerPC Microprocessor Family: Programming Environments, Ch. 8
* (Bit 0 is on the left, bit 31/63 is on the right)
*/
unsigned int i, mask;
char regnum[15];
/*
* Determine register number. The offset is the bit number of the
* left-most bit of the X-bit register field.
*/
mask = 0x80000000;
for (i = 0; i < bits; i++)
{
mask = (mask >> 1) | 0x80000000;
}
for (i = 0; i < offset; i++)
{
mask = mask >> 1;
}
i = (opword & mask) >> (31-(offset+bits-1));
sprintf(regnum,"%d",i);
strcat(buf,regnum);
}
/********************************************************************/
static int
append_register (char *buf, int opword, int reg, int offset)
{
/*
* This field accepts `opword' and then determines according
* to the offsets which register (r0 .. r31) is specified.
* The register name is then concatenated to the end of the
* disasm_stmt.
*
* The `offset' is given by the bit number as listed in the
* PowerPC Microprocessor Family: Programming Environments, Ch. 8
* (Bit 0 is on the left, bit 31/63 is on the right)
*
* This routine also returns the register number.
*/
unsigned int i, mask;
char regnum[5];
/*
* Determine register number. The offset is the bit number of the
* left-most bit of the 5-bit register field.
*/
#if 0
mask = 0xF8000000; /* 5 bits */
for (i = 0; i < offset; i++)
{
mask = mask >> 1;
}
#else
mask = (0xF8000000 >> offset);
#endif
i = (opword & mask) >> (31-(offset+5-1));
if (buf != NULL)
{
switch (reg)
{
case REG_FLOAT:
sprintf(regnum,"f%d",i);
break;
case REG_INT:
default:
sprintf(regnum,"r%d",i);
break;
}
strcat(buf,regnum);
}
return i;
}
/********************************************************************/
static void
append_value (char *buf, unsigned int value, int size)
{
char vbuf[10];
switch (size)
{
case 16:
sprintf(vbuf,"0x%04X",value & 0x0000FFFF);
break;
case 32:
default:
sprintf(vbuf,"0x%08X",value);
break;
}
append_string(buf,vbuf);
}
/********************************************************************/
static void
func (unsigned int opword)
{
/* The instruction name has already been printed. */
(void)opword;
}
/********************************************************************/
static void
func1 (unsigned int opword)
{
append_register(dstr,opword,REG_INT,6);
append_string(dstr,COMMA);
append_register(dstr,opword,REG_INT,11);
append_string(dstr,COMMA);
append_register(dstr,opword,REG_INT,16);
}
/********************************************************************/
static void
func2 (unsigned int opword)
{
append_register(dstr,opword,REG_INT,6);
append_string(dstr,COMMA);
append_register(dstr,opword,REG_INT,11);
append_string(dstr,COMMA);
append_value(dstr,opword & 0x0000FFFF,16);
}
/********************************************************************/
static void
func3 (unsigned int opword)
{
append_register(dstr,opword,REG_INT,6);
append_string(dstr,COMMA);
append_register(dstr,opword,REG_INT,11);
}
/********************************************************************/
static void
func4 (unsigned int opword)
{
append_register(dstr,opword,REG_INT,11);
append_string(dstr,COMMA);
append_register(dstr,opword,REG_INT,6);
append_string(dstr,COMMA);
append_register(dstr,opword,REG_INT,16);
}
/********************************************************************/
static void
func5 (unsigned int opword)
{
append_register(dstr,opword,REG_INT,11);
append_string(dstr,COMMA);
append_register(dstr,opword,REG_INT,6);
append_string(dstr,COMMA);
append_value(dstr,opword & 0x0000FFFF,16);
}
/********************************************************************/
static void
func6 (unsigned int opword)
{
uint32 li;
uint32 target;
char sstr[40];
li = opword & 0x03FFFFFC;
if (li & 0x02000000)
{
/* sign extend */
li = li | 0xFC000000;
}
if (0x00000002 & opword)
{
/* AA = 1 */
target = li;
}
else
{
/* AA = 0 */
target = (uint32)disasm_pc + li;
}
#ifdef SYMBOL_TABLE
if (symtab_convert_address(target,sstr))
{
append_string(dstr,sstr);
}
else
{
append_value(dstr,target,32);
}
#else
append_value(dstr,target,32);
#endif
}
/********************************************************************/
static void
func7 (unsigned int opword)
{
int bd;
unsigned int target;
append_Xbit_number(dstr,opword,5,6);
append_string(dstr,COMMA);
append_Xbit_number(dstr,opword,5,11);
append_string(dstr,COMMA);
bd = opword & 0x0000FFFC;
if (bd & 0x00008000)
{
/* sign extend */
bd = bd | 0xFFFF0000;
}
if (0x00000002 & opword)
{
/* AA = 1 */
target = (unsigned int)bd;
}
else
{
/* AA = 0 */
target = (unsigned int)((int)disasm_pc + (int)bd);
}
append_value(dstr,target,32);
}
/********************************************************************/
static void
func8 (unsigned int opword)
{
append_Xbit_number(dstr,opword,5,6);
append_string(dstr,COMMA);
append_Xbit_number(dstr,opword,5,11);
}
/********************************************************************/
static void
func9 (unsigned int opword)
{
append_Xbit_number(dstr,opword,3,6);
append_string(dstr,COMMA);
if (opword & 0x00200000)
{
append_string(dstr,"1");
}
else
{
append_string(dstr,"0");
}
append_string(dstr,COMMA);
append_register(dstr,opword,REG_INT,11);
append_string(dstr,COMMA);
append_register(dstr,opword,REG_INT,16);
}
/********************************************************************/
static void
func10 (unsigned int opword)
{
append_Xbit_number(dstr,opword,3,6);
append_string(dstr,COMMA);
if (opword & 0x00200000)
{
append_string(dstr,"1");
}
else
{
append_string(dstr,"0");
}
append_string(dstr,COMMA);
append_register(dstr,opword,REG_INT,11);
append_string(dstr,COMMA);
append_value(dstr,opword & 0x0000FFFF,16);
}
/********************************************************************/
static void
func11 (unsigned int opword)
{
append_register(dstr,opword,REG_INT,11);
append_string(dstr,COMMA);
append_register(dstr,opword,REG_INT,6);
}
/********************************************************************/
static void
func12 (unsigned int opword)
{
append_Xbit_number(dstr,opword,5,6);
append_string(dstr,COMMA);
append_Xbit_number(dstr,opword,5,11);
append_string(dstr,COMMA);
append_Xbit_number(dstr,opword,5,16);
}
/********************************************************************/
static void
func13 (unsigned int opword)
{
int rA, rB;
rA = append_register(dstr,opword,REG_INT,11);
append_string(dstr,COMMA);
rB = append_register(dstr,opword,REG_INT,16);
append_ea_rA_rB(dstr, rA, rB);
}
/********************************************************************/
static void
func14 (unsigned int opword)
{
append_register(dstr,opword,REG_FLOAT,6);
append_string(dstr,COMMA);
append_register(dstr,opword,REG_FLOAT,16);
}
/********************************************************************/
static void
func15 (unsigned int opword)
{
append_register(dstr,opword,REG_FLOAT,6);
append_string(dstr,COMMA);
append_register(dstr,opword,REG_FLOAT,11);
append_string(dstr,COMMA);
append_register(dstr,opword,REG_FLOAT,16);
}
/********************************************************************/
static void
func16 (unsigned int opword)
{
append_Xbit_number(dstr,opword,3,6);
append_string(dstr,COMMA);
append_register(dstr,opword,REG_FLOAT,11);
append_string(dstr,COMMA);
append_register(dstr,opword,REG_FLOAT,16);
}
/********************************************************************/
static void
func17 (unsigned int opword)
{
append_register(dstr,opword,REG_FLOAT,6);
append_string(dstr,COMMA);
append_register(dstr,opword,REG_FLOAT,16);
}
/********************************************************************/
static void
func18 (unsigned int opword)
{
append_register(dstr,opword,REG_FLOAT,6);
append_string(dstr,COMMA);
append_register(dstr,opword,REG_FLOAT,11);
append_string(dstr,COMMA);
append_register(dstr,opword,REG_FLOAT,21);
append_string(dstr,COMMA);
append_register(dstr,opword,REG_FLOAT,16);
}
/********************************************************************/
static void
func19 (unsigned int opword)
{
append_register(dstr,opword,REG_FLOAT,6);
append_string(dstr,COMMA);
append_register(dstr,opword,REG_FLOAT,11);
append_string(dstr,COMMA);
append_register(dstr,opword,REG_FLOAT,21);
}
/********************************************************************/
static void
insn_rD_d_rA (unsigned int opword, int *d, int *rA)
{
/*
* Ex: lbz rD,d(rA)
*/
char valstr[10];
int disp;
disp = opword & 0x0000FFFF;
if (disp & 0x00008000)
{
disp = disp | 0xFFFF0000;
}
sprintf(valstr,"%d",disp);
*d = disp;
append_register(dstr,opword,REG_INT,6);
append_string(dstr,COMMA);
append_string(dstr,valstr);
append_string(dstr,"(");
*rA = append_register(dstr,opword,REG_INT,11);
append_string(dstr,")");
}
/********************************************************************/
static void
insn_rD_rA_rB (unsigned int opword, int *rA, int *rB)
{
/*
* Ex: lbzx rD,rA,rB
*/
append_register(dstr,opword,REG_INT,6);
append_string(dstr,COMMA);
*rA = append_register(dstr,opword,REG_INT,11);
append_string(dstr,COMMA);
*rB = append_register(dstr,opword,REG_INT,16);
}
/********************************************************************/
static void
func20a (unsigned int opword)
{
/*
* Ex: lbz rD,d(rA), where EA = (rA|0) + d
*/
int d, rA;
insn_rD_d_rA(opword, &d, &rA);
append_ea_rA_0_d(dstr, d, rA);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -