ebcexecute.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,978 行 · 第 1/5 页
C
2,978 行
VmPtr->Ip += Immed64 + Size;
} else {
VmPtr->Ip = (VMIP) (UINTN) Immed64;
}
} else {
//
// Native call. Relative or absolute?
//
if (Operands & OPERAND_M_RELATIVE_ADDR) {
EbcLLCALLEX (VmPtr, (UINTN) (Immed64 + VmPtr->Ip + Size), (UINTN) VmPtr->R[0], FramePtr, Size);
} else {
if (VmPtr->StopFlags & STOPFLAG_BREAK_ON_CALLEX) {
EFI_BREAKPOINT ();
}
EbcLLCALLEX (VmPtr, (UINTN) Immed64, (UINTN) VmPtr->R[0], FramePtr, Size);
}
}
}
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
ExecuteRET (
IN VM_CONTEXT *VmPtr
)
/*++
Routine Description:
Execute the EBC RET instruction
Arguments:
VmPtr - pointer to a VM context
Returns:
Standard EFI_STATUS
Instruction syntax:
RET
--*/
{
//
// If we're at the top of the stack, then simply set the done
// flag and return
//
if (VmPtr->StackRetAddr == (UINT64) VmPtr->R[0]) {
VmPtr->StopFlags |= STOPFLAG_APP_DONE;
} else {
//
// Pull the return address off the VM app's stack and set the IP
// to it
//
if (!IS_ALIGNED ((UINTN) VmPtr->R[0], sizeof (UINT16))) {
EbcDebugSignalException (
EXCEPT_EBC_ALIGNMENT_CHECK,
EXCEPTION_FLAG_FATAL,
VmPtr
);
}
//
// Restore the IP and frame pointer from the stack
//
VmPtr->Ip = (VMIP) (UINTN) VmReadMem64 (VmPtr, (UINTN) VmPtr->R[0]);
VmPtr->R[0] += 8;
VmPtr->FramePtr = (VOID *) VmReadMemN (VmPtr, (UINTN) VmPtr->R[0]);
VmPtr->R[0] += 8;
}
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
ExecuteCMP (
IN VM_CONTEXT *VmPtr
)
/*++
Routine Description:
Execute the EBC CMP instruction
Arguments:
VmPtr - pointer to a VM context
Returns:
Standard EFI_STATUS
Instruction syntax:
CMP[32|64][eq|lte|gte|ulte|ugte] R1, {@}R2 {Index16|Immed16}
--*/
{
UINT8 Opcode;
UINT8 Operands;
UINT8 Size;
INT16 Index16;
UINT32 Flag;
INT64 Op2;
INT64 Op1;
//
// Get opcode and operands
//
Opcode = GETOPCODE (VmPtr);
Operands = GETOPERANDS (VmPtr);
//
// Get the register data we're going to compare to
//
Op1 = VmPtr->R[OPERAND1_REGNUM (Operands)];
//
// Get immediate data
//
if (Opcode & OPCODE_M_IMMDATA) {
if (OPERAND2_INDIRECT (Operands)) {
Index16 = VmReadIndex16 (VmPtr, 2);
} else {
Index16 = VmReadImmed16 (VmPtr, 2);
}
Size = 4;
} else {
Index16 = 0;
Size = 2;
}
//
// Now get Op2
//
if (OPERAND2_INDIRECT (Operands)) {
if (Opcode & OPCODE_M_64BIT) {
Op2 = (INT64) VmReadMem64 (VmPtr, (UINTN) (VmPtr->R[OPERAND2_REGNUM (Operands)] + Index16));
} else {
//
// 32-bit operations. 0-extend the values for all cases.
//
Op2 = (INT64) (UINT64) ((UINT32) VmReadMem32 (VmPtr, (UINTN) (VmPtr->R[OPERAND2_REGNUM (Operands)] + Index16)));
}
} else {
Op2 = VmPtr->R[OPERAND2_REGNUM (Operands)] + Index16;
}
//
// Now do the compare
//
Flag = 0;
if (Opcode & OPCODE_M_64BIT) {
//
// 64-bit compares
//
switch (Opcode & OPCODE_M_OPCODE) {
case OPCODE_CMPEQ:
if (Op1 == Op2) {
Flag = 1;
}
break;
case OPCODE_CMPLTE:
if (Op1 <= Op2) {
Flag = 1;
}
break;
case OPCODE_CMPGTE:
if (Op1 >= Op2) {
Flag = 1;
}
break;
case OPCODE_CMPULTE:
if ((UINT64) Op1 <= (UINT64) Op2) {
Flag = 1;
}
break;
case OPCODE_CMPUGTE:
if ((UINT64) Op1 >= (UINT64) Op2) {
Flag = 1;
}
break;
default:
ASSERT (0);
}
} else {
//
// 32-bit compares
//
switch (Opcode & OPCODE_M_OPCODE) {
case OPCODE_CMPEQ:
if ((INT32) Op1 == (INT32) Op2) {
Flag = 1;
}
break;
case OPCODE_CMPLTE:
if ((INT32) Op1 <= (INT32) Op2) {
Flag = 1;
}
break;
case OPCODE_CMPGTE:
if ((INT32) Op1 >= (INT32) Op2) {
Flag = 1;
}
break;
case OPCODE_CMPULTE:
if ((UINT32) Op1 <= (UINT32) Op2) {
Flag = 1;
}
break;
case OPCODE_CMPUGTE:
if ((UINT32) Op1 >= (UINT32) Op2) {
Flag = 1;
}
break;
default:
ASSERT (0);
}
}
//
// Now set the flag accordingly for the comparison
//
if (Flag) {
VMFLAG_SET (VmPtr, VMFLAGS_CC);
} else {
VMFLAG_CLEAR (VmPtr, VMFLAGS_CC);
}
//
// Advance the IP
//
VmPtr->Ip += Size;
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
ExecuteCMPI (
IN VM_CONTEXT *VmPtr
)
/*++
Routine Description:
Execute the EBC CMPI instruction
Arguments:
VmPtr - pointer to a VM context
Returns:
Standard EFI_STATUS
Instruction syntax:
CMPI[32|64]{w|d}[eq|lte|gte|ulte|ugte] {@}Rx {Index16}, Immed16|Immed32
--*/
{
UINT8 Opcode;
UINT8 Operands;
UINT8 Size;
INT64 Op1;
INT64 Op2;
INT16 Index16;
UINT32 Flag;
//
// Get opcode and operands
//
Opcode = GETOPCODE (VmPtr);
Operands = GETOPERANDS (VmPtr);
//
// Get operand1 index if present
//
Size = 2;
if (Operands & OPERAND_M_CMPI_INDEX) {
Index16 = VmReadIndex16 (VmPtr, 2);
Size += 2;
} else {
Index16 = 0;
}
//
// Get operand1 data we're going to compare to
//
Op1 = (INT64) VmPtr->R[OPERAND1_REGNUM (Operands)];
if (OPERAND1_INDIRECT (Operands)) {
//
// Indirect operand1. Fetch 32 or 64-bit value based on compare size.
//
if (Opcode & OPCODE_M_CMPI64) {
Op1 = (INT64) VmReadMem64 (VmPtr, (UINTN) Op1 + Index16);
} else {
Op1 = (INT64) VmReadMem32 (VmPtr, (UINTN) Op1 + Index16);
}
} else {
//
// Better not have been an index with direct. That is, CMPI R1 Index,...
// is illegal.
//
if (Operands & OPERAND_M_CMPI_INDEX) {
EbcDebugSignalException (
EXCEPT_EBC_INSTRUCTION_ENCODING,
EXCEPTION_FLAG_ERROR,
VmPtr
);
VmPtr->Ip += Size;
return EFI_UNSUPPORTED;
}
}
//
// Get immediate data -- 16- or 32-bit sign extended
//
if (Opcode & OPCODE_M_CMPI32_DATA) {
Op2 = (INT64) VmReadImmed32 (VmPtr, Size);
Size += 4;
} else {
//
// 16-bit immediate data. Sign extend always.
//
Op2 = (INT64) ((INT16) VmReadImmed16 (VmPtr, Size));
Size += 2;
}
//
// Now do the compare
//
Flag = 0;
if (Opcode & OPCODE_M_CMPI64) {
//
// 64 bit comparison
//
switch (Opcode & OPCODE_M_OPCODE) {
case OPCODE_CMPIEQ:
if (Op1 == (INT64) Op2) {
Flag = 1;
}
break;
case OPCODE_CMPILTE:
if (Op1 <= (INT64) Op2) {
Flag = 1;
}
break;
case OPCODE_CMPIGTE:
if (Op1 >= (INT64) Op2) {
Flag = 1;
}
break;
case OPCODE_CMPIULTE:
if ((UINT64) Op1 <= (UINT64) ((UINT32) Op2)) {
Flag = 1;
}
break;
case OPCODE_CMPIUGTE:
if ((UINT64) Op1 >= (UINT64) ((UINT32) Op2)) {
Flag = 1;
}
break;
default:
ASSERT (0);
}
} else {
//
// 32-bit comparisons
//
switch (Opcode & OPCODE_M_OPCODE) {
case OPCODE_CMPIEQ:
if ((INT32) Op1 == Op2) {
Flag = 1;
}
break;
case OPCODE_CMPILTE:
if ((INT32) Op1 <= Op2) {
Flag = 1;
}
break;
case OPCODE_CMPIGTE:
if ((INT32) Op1 >= Op2) {
Flag = 1;
}
break;
case OPCODE_CMPIULTE:
if ((UINT32) Op1 <= (UINT32) Op2) {
Flag = 1;
}
break;
case OPCODE_CMPIUGTE:
if ((UINT32) Op1 >= (UINT32) Op2) {
Flag = 1;
}
break;
default:
ASSERT (0);
}
}
//
// Now set the flag accordingly for the comparison
//
if (Flag) {
VMFLAG_SET (VmPtr, VMFLAGS_CC);
} else {
VMFLAG_CLEAR (VmPtr, VMFLAGS_CC);
}
//
// Advance the IP
//
VmPtr->Ip += Size;
return EFI_SUCCESS;
}
STATIC
UINT64
ExecuteNOT (
IN VM_CONTEXT *VmPtr,
IN UINT64 Op1,
IN UINT64 Op2
)
/*++
Routine Description:
Execute the EBC NOT instruction
Arguments:
VmPtr - pointer to a VM context
Op1 - Operand 1 from the instruction
Op2 - Operand 2 from the instruction
Returns:
~Op2
Instruction syntax:
NOT[32|64] {@}R1, {@}R2 {Index16|Immed16}
--*/
{
return ~Op2;
}
STATIC
UINT64
ExecuteNEG (
IN VM_CONTEXT *VmPtr,
IN UINT64 Op1,
IN UINT64 Op2
)
/*++
Routine Description:
Execute the EBC NEG instruction
Arguments:
VmPtr - pointer to a VM context
Op1 - Operand 1 from the instruction
Op2 - Operand 2 from the instruction
Returns:
Op2 * -1
Instruction syntax:
NEG[32|64] {@}R1, {@}R2 {Index16|Immed16}
--*/
{
return ~Op2 + 1;
}
STATIC
UINT64
ExecuteADD (
IN VM_CONTEXT *VmPtr,
IN UINT64 Op1,
IN UINT64 Op2
)
/*++
Routine Description:
Execute the EBC ADD instruction
Arguments:
VmPtr - pointer to a VM context
Op1 - Operand 1 from the instruction
Op2 - Operand 2 from the instruction
Returns:
Op1 + Op2
Instruction syntax:
ADD[32|64] {@}R1, {@}R2 {Index16}
--*/
{
return Op1 + Op2;
}
STATIC
UINT64
ExecuteSUB (
IN VM_CONTEXT *VmPtr,
IN UINT64 Op1,
IN UINT64 Op2
)
/*++
Routine Description:
Execute the EBC SUB instruction
Arguments:
VmPtr - pointer to a VM context
Op1 - Operand 1 from the instruction
Op2 - Operand 2 from the instruction
Returns:
Op1 - Op2
Standard EFI_STATUS
Instruction syntax:
SUB[32|64] {@}R1, {@}R2 {Index16|Immed16}
--*/
{
if (*VmPtr->Ip & DATAMANIP_M_64) {
return (UINT64) ((INT64) ((INT64) Op1 - (INT64) Op2));
} else {
return (UINT64) ((INT64) ((INT32) Op1 - (INT32) Op2));
}
}
STATIC
UINT64
ExecuteMUL (
IN VM_CONTEXT *VmPtr,
IN UINT64 Op1,
IN UINT64 Op2
)
/*++
Routine Description:
Execute the EBC MUL instruction
Arguments:
VmPtr - pointer to a VM context
Op1 - Operand 1 from the instruction
Op2 - Operand 2 from the instruction
Returns:
Op1 * Op2
Instruction syntax:
MUL[32|64] {@}R1, {@}R2 {Index16|Immed16}
--*/
{
INT64 ResultHigh;
if (*VmPtr->Ip & DATAMANIP_M_64) {
return MulS64x64 (Op1, Op2, &ResultHigh);
} else {
return (UINT64) ((INT64) ((INT32) Op1 * (INT32) Op2));
}
}
STATIC
UINT64
ExecuteMULU (
IN VM_CONTEXT *VmPtr,
IN UINT64 Op1,
IN UINT64 Op2
)
/*++
Routine Description:
Execute the EBC MULU instruction
Arguments:
VmPtr - pointer to a VM context
Op1 - Operand 1 from the instruction
Op2 - Operand 2 from the instruction
Returns:
(unsigned)Op1 * (unsigned)Op2
Instruction
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?