📄 mipsuwnd.c
字号:
Op->Rd = NOREG;
Op++;
} else {
// Look for a previous definition using SP
if (NotFirst
&& ((Op-1)->Opcode == OP_ADD || (Op-1)->Opcode == OP_ADDI)
&& (Op-1)->Rd == Op->Rs
&& ((Op-1)->Rs == SP || (Op-1)->Rt == SP)) {
Op->Rd = NOREG;
Op++;
}
}
break;
case ADDIU_OP:
case DADDIU_OP:
Op->Rd = Op->Rt;
if (Op->Rs == Op->Rt || Op->Rs == SP) {
Op->Opcode = OP_ADDI;
Op++;
} else if (Op->Rs == ZERO) {
Op->Opcode = OP_IMM;
Op++;
}
break;
case ORI_OP:
Op->Opcode = OP_IMM;
Op->Imm &= 0xffff;
Op->Rd = Op->Rt;
if (Op->Rs == Op->Rt) {
// Look for matching LUI
if (NotFirst && (Op-1)->Opcode == OP_IMM && (Op-1)->Rd == Op->Rd) {
(Op-1)->Imm |= Op->Imm;
} else {
Op++;
}
} else if (Op->Rs == ZERO) {
Op++;
}
break;
case SPEC_OP:
switch (I32.r_format.Function) {
case OR_OP:
Op->Opcode = OP_OR;
goto spec;
case ADDU_OP:
Op->Opcode = OP_ADD;
spec:
if (Op->Rs == ZERO) {
Op->Opcode = OP_MOVE;
Op->Rs = Op->Rt;
Op++;
} else if (Op->Rt == ZERO) {
Op->Opcode = OP_MOVE;
Op++;
} else if (Op->Rs == Op->Rd) {
Op++;
} else if (Op->Rt == Op->Rd) {
Op->Rt = Op->Rs;
Op->Rs = Op->Rd;
Op++;
} else if (Op->Rs == SP || Op->Rt == SP) {
Op++;
}
break;
case SUBU_OP:
case DSUBU_OP:
if (Op->Rs == Op->Rd) {
Op->Opcode = OP_SUB;
Op++;
}
break;
}
break;
case LUI_OP:
Op->Opcode = OP_IMM;
Op->Imm <<= 16;
Op->Rd = Op->Rt;
Op++;
break;
}
return Op;
}
static INT
BuildOps (
IN OUT POPERATION Operations,
IN INT Max,
IN ULONG Address,
IN ULONG EndAddress,
IN ULONG pcOfst)
/*++
Routine Description
This function constructs an interpreter operation list based upon the machine
instructions found between a start and end address.
The code is smart enough to handle a single level of calls, this is required
if prolog helpers are being used.
Arguments
Operations - A pointer to an interpreter operation array to receive the translated
instructions.
Max - Size of the operation array.
Address - The address of the first instruction.
EndAddress - The address of the last instruction.
Return Value:
The number of operations generated.
--*/
{
MIPS16_INSTRUCTION I16;
MIPS_INSTRUCTION I32;
ULONG RetAddress = (ULONG) -1;
ULONG Extend = (ULONG) -1;
ULONG PCAddress = Address;
POPERATION Op = Operations;
POPERATION LastOp = Operations + Max;
while (Address != EndAddress && Op < LastOp) {
if (Address & 1) {
// Get MIPS16 instruction
I16.Short = *((PUSHORT) (Address - 1));
// Replace any break instruction introduced in the prolog
// by the debugger with its original instruction
if (I16.rr_format.Function == BREAK_OP16 &&
I16.rr_format.Opcode == RR_OP16) {
(*KDSanitize)((BYTE *)&I16.Short, (void *)(Address - 1),
sizeof(I16.Short), FALSE);
}
switch (I16.i_format.Opcode) {
case EXTEND_OP16:
Extend = (I16.ei_format.Simmediate11 << 11) | (I16.ei_format.Immediate5 << 5);
PCAddress = Address;
Address += 2;
break;
case B_OP16:
if (Extend == (ULONG) -1) {
Address += (I16.b_format.Simmediate << 1) + 2;
} else {
Address += (I16.rri_format.Immediate | Extend) + 4;
}
PCAddress = Address;
Extend = (ULONG) -1;
break;
case JALX_OP16:
Op = BuildSimpleOp16 (Op, Address + 3, Address, (ULONG) -1);
RetAddress = Address + 6;
Address = (I16.j_format.Target16 << 18) | (I16.j_format.Target21 << 23) | (*(PUSHORT) (Address+1) << 2) | ((Address-pcOfst+3) & 0xf0000000);
Address += pcOfst;
Address |= (I16.j_format.Ext == 0);
PCAddress = Address;
Extend = (ULONG) -1;
break;
case RR_OP16:
switch (I16.rr_format.Function) {
case JR_OP16:
if (I16.rr_format.Ry == 1 && I16.rr_format.Rx == 0) {
// If this is a "JR RA" and we've nested then decode from return address
if (RetAddress != (ULONG) -1) {
Op = BuildSimpleOp16 (Op, Address + 1, PCAddress, (ULONG) -1);
PCAddress = Address = RetAddress;
RetAddress = (ULONG) -1;
Extend = (ULONG) -1;
continue;
}
}
// Anything other than JR RA is not acceptable in helper functions
return -1;
}
Address += 2;
PCAddress = Address;
Extend = (ULONG) -1;
break;
default:
Op = BuildSimpleOp16 (Op, Address - 1, PCAddress, Extend);
Address += 2;
PCAddress = Address;
Extend = (ULONG) -1;
break;
}
} else {
// Get MIPS32 instruction
I32.Long = *(PULONG) Address;
// Replace any break instruction introduced in the prolog
// by the debugger with its original instruction
if (I32.r_format.Function == BREAK_OP &&
I32.r_format.Opcode == SPEC_OP) {
(*KDSanitize)((BYTE *)&I32.Long, (void *)Address,
sizeof(I32.Long), FALSE);
}
switch (I32.i_format.Opcode) {
case JAL_OP:
Op = BuildSimpleOp32 (Op, Address + 4, (BOOLEAN)(Op != Operations));
RetAddress = Address + 8;
Address = ((I32.j_format.Target << 2) | ((Address - pcOfst + 4) & 0xf0000000)) + pcOfst;
if (I32.j_format.Target >> 26) Address |= 1;
PCAddress = Address;
break;
case SPEC_OP:
if (I32.Long == JUMP_RA && RetAddress != (ULONG) -1) {
Op = BuildSimpleOp32 (Op, Address + 4, (BOOLEAN)(Op != Operations));
Address = PCAddress = RetAddress;
RetAddress = (ULONG) -1;
continue;
}
// Note fallthrough
default:
Op = BuildSimpleOp32 (Op, Address, (BOOLEAN)(Op != Operations));
Address += 4;
break;
}
}
}
if (Address != EndAddress) {
return -1;
}
return Op - Operations;
}
static void
FindValue (
IN POPERATION Ops,
IN DWORD NumOps,
IN DWORD RegNum,
IN OUT REG_TYPE *Regs)
/*++
Routine Description
This function searches backwards through the Op array trying to deduce
the value of an expression targeting a register. Here, instructions
must be executed forwards.
Arguments
Ops - A pointer to an interpreter operation array.
NumOps - Number of operations in the array.
RegNum - Register to search for.
Regs - Register value array to update.
--*/
{
if (!IsScratchReg(RegNum)) return;
while (NumOps-- > 0) {
if (Ops->Rd == RegNum) {
switch (Ops->Opcode) {
case OP_IMM:
Regs [RegNum] = Ops->Imm;
break;
case OP_ADD:
case OP_SUB:
FindValue (Ops - 1, NumOps, Ops->Rs, Regs);
FindValue (Ops - 1, NumOps, Ops->Rt, Regs);
Regs [RegNum] = (Ops->Opcode == OP_ADD) ?
Regs [Ops->Rs] + Regs [Ops->Rt] :
Regs [Ops->Rs] - Regs [Ops->Rt];
break;
case OP_ADDI:
FindValue (Ops - 1, NumOps, Ops->Rs, Regs);
Regs [RegNum] = Regs [Ops->Rs] + Ops->Imm;
break;
case OP_MOVE:
FindValue (Ops - 1, NumOps, Ops->Rs, Regs);
Regs [RegNum] = Regs [Ops->Rs];
break;
}
// stop once we've found the definition of our register
return;
}
Ops--;
}
}
ULONG
Reverse (
IN POPERATION Op,
IN DWORD NumOps,
IN OUT PCONTEXT Context)
/*++
Routine Description
Arguments
--*/
{
REG_TYPE * IntRegs = &Context->IntZero;
FREG_TYPE * FpRegs = &Context->FltF0;
ULONG NextPc;
BOOL RestoredRa = FALSE;
Op += NumOps - 1;
while (NumOps-- > 0) {
switch (Op->Opcode) {
case OP_ADD:
if (Op->Rd == Op->Rs) {
FindValue (Op-1, NumOps, Op->Rt, IntRegs);
IntRegs [Op->Rd] -= IntRegs [Op->Rt];
}
break;
case OP_SUB:
if (Op->Rd == Op->Rs) {
FindValue (Op-1, NumOps, Op->Rt, IntRegs);
IntRegs [Op->Rd] += IntRegs [Op->Rt];
}
break;
case OP_ADDI:
if (Op->Rd == Op->Rs) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -