TianoCore EDK2 master
Loading...
Searching...
No Matches
EbcExecute.c
Go to the documentation of this file.
1
9#include "EbcInt.h"
10#include "EbcExecute.h"
11#include "EbcDebuggerHook.h"
12
13//
14// Define some useful data size constants to allow switch statements based on
15// size of operands or data.
16//
17#define DATA_SIZE_INVALID 0
18#define DATA_SIZE_8 1
19#define DATA_SIZE_16 2
20#define DATA_SIZE_32 4
21#define DATA_SIZE_64 8
22#define DATA_SIZE_N 48 // 4 or 8
23//
24// Structure we'll use to dispatch opcodes to execute functions.
25//
26typedef struct {
27 EFI_STATUS (*ExecuteFunction)(
28 IN VM_CONTEXT *VmPtr
29 );
31
32typedef
33UINT64
34(*DATA_MANIP_EXEC_FUNCTION) (
35 IN VM_CONTEXT *VmPtr,
36 IN UINT64 Op1,
37 IN UINT64 Op2
38 );
39
62INT16
64 IN VM_CONTEXT *VmPtr,
65 IN UINT32 CodeOffset
66 );
67
78INT32
80 IN VM_CONTEXT *VmPtr,
81 IN UINT32 CodeOffset
82 );
83
94INT64
96 IN VM_CONTEXT *VmPtr,
97 IN UINT32 CodeOffset
98 );
99
109UINT8
111 IN VM_CONTEXT *VmPtr,
112 IN UINTN Addr
113 );
114
124UINT16
126 IN VM_CONTEXT *VmPtr,
127 IN UINTN Addr
128 );
129
139UINT32
141 IN VM_CONTEXT *VmPtr,
142 IN UINTN Addr
143 );
144
154UINT64
156 IN VM_CONTEXT *VmPtr,
157 IN UINTN Addr
158 );
159
169UINTN
171 IN VM_CONTEXT *VmPtr,
172 IN UINTN Addr
173 );
174
200 IN VM_CONTEXT *VmPtr,
201 IN UINTN Addr,
202 IN UINT8 Data
203 );
204
230 IN VM_CONTEXT *VmPtr,
231 IN UINTN Addr,
232 IN UINT16 Data
233 );
234
260 IN VM_CONTEXT *VmPtr,
261 IN UINTN Addr,
262 IN UINT32 Data
263 );
264
277UINT16
279 IN VM_CONTEXT *VmPtr,
280 IN UINT32 Offset
281 );
282
295UINT32
297 IN VM_CONTEXT *VmPtr,
298 IN UINT32 Offset
299 );
300
313UINT64
315 IN VM_CONTEXT *VmPtr,
316 IN UINT32 Offset
317 );
318
333INT8
335 IN VM_CONTEXT *VmPtr,
336 IN UINT32 Offset
337 );
338
353INT16
355 IN VM_CONTEXT *VmPtr,
356 IN UINT32 Offset
357 );
358
373INT32
375 IN VM_CONTEXT *VmPtr,
376 IN UINT32 Offset
377 );
378
393INT64
395 IN VM_CONTEXT *VmPtr,
396 IN UINT32 Offset
397 );
398
418UINTN
420 IN VM_CONTEXT *VmPtr,
421 IN UINTN Addr
422 );
423
444 IN VM_CONTEXT *VmPtr,
445 IN BOOLEAN IsSignedOp
446 );
447
448//
449// Functions that execute VM opcodes
450//
451
462 IN VM_CONTEXT *VmPtr
463 );
464
492 IN VM_CONTEXT *VmPtr
493 );
494
508 IN VM_CONTEXT *VmPtr
509 );
510
529 IN VM_CONTEXT *VmPtr
530 );
531
545 IN VM_CONTEXT *VmPtr
546 );
547
562 IN VM_CONTEXT *VmPtr
563 );
564
579 IN VM_CONTEXT *VmPtr
580 );
581
605 IN VM_CONTEXT *VmPtr
606 );
607
631 IN VM_CONTEXT *VmPtr
632 );
633
650 IN VM_CONTEXT *VmPtr
651 );
652
669 IN VM_CONTEXT *VmPtr
670 );
671
685 IN VM_CONTEXT *VmPtr
686 );
687
701 IN VM_CONTEXT *VmPtr
702 );
703
717 IN VM_CONTEXT *VmPtr
718 );
719
733 IN VM_CONTEXT *VmPtr
734 );
735
755 IN VM_CONTEXT *VmPtr
756 );
757
777 IN VM_CONTEXT *VmPtr
778 );
779
794 IN VM_CONTEXT *VmPtr
795 );
796
811 IN VM_CONTEXT *VmPtr
812 );
813
835 IN VM_CONTEXT *VmPtr
836 );
837
859 IN VM_CONTEXT *VmPtr
860 );
861
862//
863// Data manipulation subfunctions
864//
865
879UINT64
881 IN VM_CONTEXT *VmPtr,
882 IN UINT64 Op1,
883 IN UINT64 Op2
884 );
885
899UINT64
901 IN VM_CONTEXT *VmPtr,
902 IN UINT64 Op1,
903 IN UINT64 Op2
904 );
905
919UINT64
921 IN VM_CONTEXT *VmPtr,
922 IN UINT64 Op1,
923 IN UINT64 Op2
924 );
925
939UINT64
941 IN VM_CONTEXT *VmPtr,
942 IN UINT64 Op1,
943 IN UINT64 Op2
944 );
945
959UINT64
961 IN VM_CONTEXT *VmPtr,
962 IN UINT64 Op1,
963 IN UINT64 Op2
964 );
965
979UINT64
981 IN VM_CONTEXT *VmPtr,
982 IN UINT64 Op1,
983 IN UINT64 Op2
984 );
985
999UINT64
1000ExecuteDIV (
1001 IN VM_CONTEXT *VmPtr,
1002 IN UINT64 Op1,
1003 IN UINT64 Op2
1004 );
1005
1019UINT64
1021 IN VM_CONTEXT *VmPtr,
1022 IN UINT64 Op1,
1023 IN UINT64 Op2
1024 );
1025
1039UINT64
1040ExecuteMOD (
1041 IN VM_CONTEXT *VmPtr,
1042 IN UINT64 Op1,
1043 IN UINT64 Op2
1044 );
1045
1059UINT64
1061 IN VM_CONTEXT *VmPtr,
1062 IN UINT64 Op1,
1063 IN UINT64 Op2
1064 );
1065
1079UINT64
1080ExecuteAND (
1081 IN VM_CONTEXT *VmPtr,
1082 IN UINT64 Op1,
1083 IN UINT64 Op2
1084 );
1085
1099UINT64
1100ExecuteOR (
1101 IN VM_CONTEXT *VmPtr,
1102 IN UINT64 Op1,
1103 IN UINT64 Op2
1104 );
1105
1119UINT64
1120ExecuteXOR (
1121 IN VM_CONTEXT *VmPtr,
1122 IN UINT64 Op1,
1123 IN UINT64 Op2
1124 );
1125
1139UINT64
1140ExecuteSHL (
1141 IN VM_CONTEXT *VmPtr,
1142 IN UINT64 Op1,
1143 IN UINT64 Op2
1144 );
1145
1159UINT64
1160ExecuteSHR (
1161 IN VM_CONTEXT *VmPtr,
1162 IN UINT64 Op1,
1163 IN UINT64 Op2
1164 );
1165
1179UINT64
1181 IN VM_CONTEXT *VmPtr,
1182 IN UINT64 Op1,
1183 IN UINT64 Op2
1184 );
1185
1199UINT64
1201 IN VM_CONTEXT *VmPtr,
1202 IN UINT64 Op1,
1203 IN UINT64 Op2
1204 );
1205
1219UINT64
1221 IN VM_CONTEXT *VmPtr,
1222 IN UINT64 Op1,
1223 IN UINT64 Op2
1224 );
1225
1239UINT64
1241 IN VM_CONTEXT *VmPtr,
1242 IN UINT64 Op1,
1243 IN UINT64 Op2
1244 );
1245
1246//
1247// Once we retrieve the operands for the data manipulation instructions,
1248// call these functions to perform the operation.
1249//
1250CONST DATA_MANIP_EXEC_FUNCTION mDataManipDispatchTable[] = {
1251 ExecuteNOT,
1252 ExecuteNEG,
1253 ExecuteADD,
1254 ExecuteSUB,
1255 ExecuteMUL,
1257 ExecuteDIV,
1259 ExecuteMOD,
1261 ExecuteAND,
1262 ExecuteOR,
1263 ExecuteXOR,
1264 ExecuteSHL,
1265 ExecuteSHR,
1270};
1271
1272CONST VM_TABLE_ENTRY mVmOpcodeTable[] = {
1273 { ExecuteBREAK }, // opcode 0x00
1274 { ExecuteJMP }, // opcode 0x01
1275 { ExecuteJMP8 }, // opcode 0x02
1276 { ExecuteCALL }, // opcode 0x03
1277 { ExecuteRET }, // opcode 0x04
1278 { ExecuteCMP }, // opcode 0x05 CMPeq
1279 { ExecuteCMP }, // opcode 0x06 CMPlte
1280 { ExecuteCMP }, // opcode 0x07 CMPgte
1281 { ExecuteCMP }, // opcode 0x08 CMPulte
1282 { ExecuteCMP }, // opcode 0x09 CMPugte
1283 { ExecuteUnsignedDataManip }, // opcode 0x0A NOT
1284 { ExecuteSignedDataManip }, // opcode 0x0B NEG
1285 { ExecuteSignedDataManip }, // opcode 0x0C ADD
1286 { ExecuteSignedDataManip }, // opcode 0x0D SUB
1287 { ExecuteSignedDataManip }, // opcode 0x0E MUL
1288 { ExecuteUnsignedDataManip }, // opcode 0x0F MULU
1289 { ExecuteSignedDataManip }, // opcode 0x10 DIV
1290 { ExecuteUnsignedDataManip }, // opcode 0x11 DIVU
1291 { ExecuteSignedDataManip }, // opcode 0x12 MOD
1292 { ExecuteUnsignedDataManip }, // opcode 0x13 MODU
1293 { ExecuteUnsignedDataManip }, // opcode 0x14 AND
1294 { ExecuteUnsignedDataManip }, // opcode 0x15 OR
1295 { ExecuteUnsignedDataManip }, // opcode 0x16 XOR
1296 { ExecuteUnsignedDataManip }, // opcode 0x17 SHL
1297 { ExecuteUnsignedDataManip }, // opcode 0x18 SHR
1298 { ExecuteSignedDataManip }, // opcode 0x19 ASHR
1299 { ExecuteUnsignedDataManip }, // opcode 0x1A EXTNDB
1300 { ExecuteUnsignedDataManip }, // opcode 0x1B EXTNDW
1301 { ExecuteUnsignedDataManip }, // opcode 0x1C EXTNDD
1302 { ExecuteMOVxx }, // opcode 0x1D MOVBW
1303 { ExecuteMOVxx }, // opcode 0x1E MOVWW
1304 { ExecuteMOVxx }, // opcode 0x1F MOVDW
1305 { ExecuteMOVxx }, // opcode 0x20 MOVQW
1306 { ExecuteMOVxx }, // opcode 0x21 MOVBD
1307 { ExecuteMOVxx }, // opcode 0x22 MOVWD
1308 { ExecuteMOVxx }, // opcode 0x23 MOVDD
1309 { ExecuteMOVxx }, // opcode 0x24 MOVQD
1310 { ExecuteMOVsnw }, // opcode 0x25 MOVsnw
1311 { ExecuteMOVsnd }, // opcode 0x26 MOVsnd
1312 { NULL }, // opcode 0x27
1313 { ExecuteMOVxx }, // opcode 0x28 MOVqq
1314 { ExecuteLOADSP }, // opcode 0x29 LOADSP SP1, R2
1315 { ExecuteSTORESP }, // opcode 0x2A STORESP R1, SP2
1316 { ExecutePUSH }, // opcode 0x2B PUSH {@}R1 [imm16]
1317 { ExecutePOP }, // opcode 0x2C POP {@}R1 [imm16]
1318 { ExecuteCMPI }, // opcode 0x2D CMPIEQ
1319 { ExecuteCMPI }, // opcode 0x2E CMPILTE
1320 { ExecuteCMPI }, // opcode 0x2F CMPIGTE
1321 { ExecuteCMPI }, // opcode 0x30 CMPIULTE
1322 { ExecuteCMPI }, // opcode 0x31 CMPIUGTE
1323 { ExecuteMOVxx }, // opcode 0x32 MOVN
1324 { ExecuteMOVxx }, // opcode 0x33 MOVND
1325 { NULL }, // opcode 0x34
1326 { ExecutePUSHn }, // opcode 0x35
1327 { ExecutePOPn }, // opcode 0x36
1328 { ExecuteMOVI }, // opcode 0x37 - mov immediate data
1329 { ExecuteMOVIn }, // opcode 0x38 - mov immediate natural
1330 { ExecuteMOVREL }, // opcode 0x39 - move data relative to PC
1331 { NULL }, // opcode 0x3a
1332 { NULL }, // opcode 0x3b
1333 { NULL }, // opcode 0x3c
1334 { NULL }, // opcode 0x3d
1335 { NULL }, // opcode 0x3e
1336 { NULL } // opcode 0x3f
1337};
1338
1339//
1340// Length of JMP instructions, depending on upper two bits of opcode.
1341//
1342CONST UINT8 mJMPLen[] = { 2, 2, 6, 10 };
1343
1359EFIAPI
1362 IN VM_CONTEXT *VmPtr,
1363 IN OUT UINTN *InstructionCount
1364 )
1365{
1366 UINTN ExecFunc;
1367 EFI_STATUS Status;
1368 UINTN InstructionsLeft;
1369 UINTN SavedInstructionCount;
1370
1371 Status = EFI_SUCCESS;
1372
1373 if (*InstructionCount == 0) {
1374 InstructionsLeft = 1;
1375 } else {
1376 InstructionsLeft = *InstructionCount;
1377 }
1378
1379 SavedInstructionCount = *InstructionCount;
1380 *InstructionCount = 0;
1381
1382 //
1383 // Index into the opcode table using the opcode byte for this instruction.
1384 // This gives you the execute function, which we first test for null, then
1385 // call it if it's not null.
1386 //
1387 while (InstructionsLeft != 0) {
1388 ExecFunc = (UINTN)mVmOpcodeTable[(*VmPtr->Ip & OPCODE_M_OPCODE)].ExecuteFunction;
1389 if (ExecFunc == (UINTN)NULL) {
1390 EbcDebugSignalException (EXCEPT_EBC_INVALID_OPCODE, EXCEPTION_FLAG_FATAL, VmPtr);
1391 return EFI_UNSUPPORTED;
1392 } else {
1393 mVmOpcodeTable[(*VmPtr->Ip & OPCODE_M_OPCODE)].ExecuteFunction (VmPtr);
1394 *InstructionCount = *InstructionCount + 1;
1395 }
1396
1397 //
1398 // Decrement counter if applicable
1399 //
1400 if (SavedInstructionCount != 0) {
1401 InstructionsLeft--;
1402 }
1403 }
1404
1405 return Status;
1406}
1407
1419 IN VM_CONTEXT *VmPtr
1420 )
1421{
1422 UINTN ExecFunc;
1423 UINT8 StackCorrupted;
1424 EFI_STATUS Status;
1425 EFI_EBC_SIMPLE_DEBUGGER_PROTOCOL *EbcSimpleDebugger;
1426
1427 mVmPtr = VmPtr;
1428 EbcSimpleDebugger = NULL;
1429 Status = EFI_SUCCESS;
1430 StackCorrupted = 0;
1431
1432 //
1433 // Make sure the magic value has been put on the stack before we got here.
1434 //
1435 if (*VmPtr->StackMagicPtr != (UINTN)VM_STACK_KEY_VALUE) {
1436 StackCorrupted = 1;
1437 }
1438
1439 VmPtr->FramePtr = (VOID *)((UINT8 *)(UINTN)VmPtr->Gpr[0] + 8);
1440
1441 //
1442 // Try to get the debug support for EBC
1443 //
1445 Status = gBS->LocateProtocol (
1446 &gEfiEbcSimpleDebuggerProtocolGuid,
1447 NULL,
1448 (VOID **)&EbcSimpleDebugger
1449 );
1450 if (EFI_ERROR (Status)) {
1451 EbcSimpleDebugger = NULL;
1452 }
1453
1454 DEBUG_CODE_END ();
1455
1456 //
1457 // Save the start IP for debug. For example, if we take an exception we
1458 // can print out the location of the exception relative to the entry point,
1459 // which could then be used in a disassembly listing to find the problem.
1460 //
1461 VmPtr->EntryPoint = (VOID *)VmPtr->Ip;
1462
1463 //
1464 // We'll wait for this flag to know when we're done. The RET
1465 // instruction sets it if it runs out of stack.
1466 //
1467 VmPtr->StopFlags = 0;
1468 while ((VmPtr->StopFlags & STOPFLAG_APP_DONE) == 0) {
1469 //
1470 // If we've found a simple debugger protocol, call it
1471 //
1473 if (EbcSimpleDebugger != NULL) {
1474 EbcSimpleDebugger->Debugger (EbcSimpleDebugger, VmPtr);
1475 }
1476
1477 DEBUG_CODE_END ();
1478
1479 //
1480 // Use the opcode bits to index into the opcode dispatch table. If the
1481 // function pointer is null then generate an exception.
1482 //
1483 ExecFunc = (UINTN)mVmOpcodeTable[(*VmPtr->Ip & OPCODE_M_OPCODE)].ExecuteFunction;
1484 if (ExecFunc == (UINTN)NULL) {
1485 EbcDebugSignalException (EXCEPT_EBC_INVALID_OPCODE, EXCEPTION_FLAG_FATAL, VmPtr);
1486 Status = EFI_UNSUPPORTED;
1487 goto Done;
1488 }
1489
1491
1492 //
1493 // The EBC VM is a strongly ordered processor, so perform a fence operation before
1494 // and after each instruction is executed.
1495 //
1496 MemoryFence ();
1497
1498 mVmOpcodeTable[(*VmPtr->Ip & OPCODE_M_OPCODE)].ExecuteFunction (VmPtr);
1499
1500 MemoryFence ();
1501
1503
1504 //
1505 // If the step flag is set, signal an exception and continue. We don't
1506 // clear it here. Assuming the debugger is responsible for clearing it.
1507 //
1508 if (VMFLAG_ISSET (VmPtr, VMFLAGS_STEP)) {
1509 EbcDebugSignalException (EXCEPT_EBC_STEP, EXCEPTION_FLAG_NONE, VmPtr);
1510 }
1511
1512 //
1513 // Make sure stack has not been corrupted. Only report it once though.
1514 //
1515 if ((StackCorrupted == 0) && (*VmPtr->StackMagicPtr != (UINTN)VM_STACK_KEY_VALUE)) {
1516 EbcDebugSignalException (EXCEPT_EBC_STACK_FAULT, EXCEPTION_FLAG_FATAL, VmPtr);
1517 StackCorrupted = 1;
1518 }
1519
1520 if ((StackCorrupted == 0) && ((UINT64)VmPtr->Gpr[0] <= (UINT64)(UINTN)VmPtr->StackTop)) {
1521 EbcDebugSignalException (EXCEPT_EBC_STACK_FAULT, EXCEPTION_FLAG_FATAL, VmPtr);
1522 StackCorrupted = 1;
1523 }
1524 }
1525
1526Done:
1527 mVmPtr = NULL;
1528
1529 return Status;
1530}
1531
1555 IN VM_CONTEXT *VmPtr
1556 )
1557{
1558 UINT8 Opcode;
1559 UINT8 OpcMasked;
1560 UINT8 Operands;
1561 UINT8 Size;
1562 UINT8 MoveSize;
1563 INT16 Index16;
1564 INT32 Index32;
1565 INT64 Index64Op1;
1566 INT64 Index64Op2;
1567 UINT64 Data64;
1568 UINT64 DataMask;
1569 UINTN Source;
1570
1571 Opcode = GETOPCODE (VmPtr);
1572 OpcMasked = (UINT8)(Opcode & OPCODE_M_OPCODE);
1573
1574 //
1575 // Get the operands byte so we can get R1 and R2
1576 //
1577 Operands = GETOPERANDS (VmPtr);
1578
1579 //
1580 // Assume no indexes
1581 //
1582 Index64Op1 = 0;
1583 Index64Op2 = 0;
1584 Data64 = 0;
1585
1586 //
1587 // Determine if we have an index/immediate data. Base instruction size
1588 // is 2 (opcode + operands). Add to this size each index specified.
1589 //
1590 Size = 2;
1591 if ((Opcode & (OPCODE_M_IMMED_OP1 | OPCODE_M_IMMED_OP2)) != 0) {
1592 //
1593 // Determine size of the index from the opcode. Then get it.
1594 //
1595 if ((OpcMasked <= OPCODE_MOVQW) || (OpcMasked == OPCODE_MOVNW)) {
1596 //
1597 // MOVBW, MOVWW, MOVDW, MOVQW, and MOVNW have 16-bit immediate index.
1598 // Get one or both index values.
1599 //
1600 if ((Opcode & OPCODE_M_IMMED_OP1) != 0) {
1601 Index16 = VmReadIndex16 (VmPtr, 2);
1602 Index64Op1 = (INT64)Index16;
1603 Size += sizeof (UINT16);
1604 }
1605
1606 if ((Opcode & OPCODE_M_IMMED_OP2) != 0) {
1607 Index16 = VmReadIndex16 (VmPtr, Size);
1608 Index64Op2 = (INT64)Index16;
1609 Size += sizeof (UINT16);
1610 }
1611 } else if ((OpcMasked <= OPCODE_MOVQD) || (OpcMasked == OPCODE_MOVND)) {
1612 //
1613 // MOVBD, MOVWD, MOVDD, MOVQD, and MOVND have 32-bit immediate index
1614 //
1615 if ((Opcode & OPCODE_M_IMMED_OP1) != 0) {
1616 Index32 = VmReadIndex32 (VmPtr, 2);
1617 Index64Op1 = (INT64)Index32;
1618 Size += sizeof (UINT32);
1619 }
1620
1621 if ((Opcode & OPCODE_M_IMMED_OP2) != 0) {
1622 Index32 = VmReadIndex32 (VmPtr, Size);
1623 Index64Op2 = (INT64)Index32;
1624 Size += sizeof (UINT32);
1625 }
1626 } else if (OpcMasked == OPCODE_MOVQQ) {
1627 //
1628 // MOVqq -- only form with a 64-bit index
1629 //
1630 if ((Opcode & OPCODE_M_IMMED_OP1) != 0) {
1631 Index64Op1 = VmReadIndex64 (VmPtr, 2);
1632 Size += sizeof (UINT64);
1633 }
1634
1635 if ((Opcode & OPCODE_M_IMMED_OP2) != 0) {
1636 Index64Op2 = VmReadIndex64 (VmPtr, Size);
1637 Size += sizeof (UINT64);
1638 }
1639 } else {
1640 //
1641 // Obsolete MOVBQ, MOVWQ, MOVDQ, and MOVNQ have 64-bit immediate index
1642 //
1645 EXCEPTION_FLAG_FATAL,
1646 VmPtr
1647 );
1648 return EFI_UNSUPPORTED;
1649 }
1650 }
1651
1652 //
1653 // Determine the size of the move, and create a mask for it so we can
1654 // clear unused bits.
1655 //
1656 if ((OpcMasked == OPCODE_MOVBW) || (OpcMasked == OPCODE_MOVBD)) {
1657 MoveSize = DATA_SIZE_8;
1658 DataMask = 0xFF;
1659 } else if ((OpcMasked == OPCODE_MOVWW) || (OpcMasked == OPCODE_MOVWD)) {
1660 MoveSize = DATA_SIZE_16;
1661 DataMask = 0xFFFF;
1662 } else if ((OpcMasked == OPCODE_MOVDW) || (OpcMasked == OPCODE_MOVDD)) {
1663 MoveSize = DATA_SIZE_32;
1664 DataMask = 0xFFFFFFFF;
1665 } else if ((OpcMasked == OPCODE_MOVQW) || (OpcMasked == OPCODE_MOVQD) || (OpcMasked == OPCODE_MOVQQ)) {
1666 MoveSize = DATA_SIZE_64;
1667 DataMask = (UINT64) ~0;
1668 } else if ((OpcMasked == OPCODE_MOVNW) || (OpcMasked == OPCODE_MOVND)) {
1669 MoveSize = DATA_SIZE_N;
1670 DataMask = (UINT64) ~0 >> (64 - 8 * sizeof (UINTN));
1671 } else {
1672 //
1673 // We were dispatched to this function and we don't recognize the opcode
1674 //
1675 EbcDebugSignalException (EXCEPT_EBC_UNDEFINED, EXCEPTION_FLAG_FATAL, VmPtr);
1676 return EFI_UNSUPPORTED;
1677 }
1678
1679 //
1680 // Now get the source address
1681 //
1682 if (OPERAND2_INDIRECT (Operands)) {
1683 //
1684 // Indirect form @R2. Compute address of operand2
1685 //
1686 Source = (UINTN)(VmPtr->Gpr[OPERAND2_REGNUM (Operands)] + Index64Op2);
1687 //
1688 // Now get the data from the source. Always 0-extend and let the compiler
1689 // sign-extend where required.
1690 //
1691 switch (MoveSize) {
1692 case DATA_SIZE_8:
1693 Data64 = (UINT64)(UINT8)VmReadMem8 (VmPtr, Source);
1694 break;
1695
1696 case DATA_SIZE_16:
1697 Data64 = (UINT64)(UINT16)VmReadMem16 (VmPtr, Source);
1698 break;
1699
1700 case DATA_SIZE_32:
1701 Data64 = (UINT64)(UINT32)VmReadMem32 (VmPtr, Source);
1702 break;
1703
1704 case DATA_SIZE_64:
1705 Data64 = (UINT64)VmReadMem64 (VmPtr, Source);
1706 break;
1707
1708 case DATA_SIZE_N:
1709 Data64 = (UINT64)(UINTN)VmReadMemN (VmPtr, Source);
1710 break;
1711
1712 default:
1713 //
1714 // not reached
1715 //
1716 break;
1717 }
1718 } else {
1719 //
1720 // Not indirect source: MOVxx {@}Rx, Ry [Index]
1721 //
1722 Data64 = (UINT64)(VmPtr->Gpr[OPERAND2_REGNUM (Operands)] + Index64Op2);
1723 //
1724 // Did Operand2 have an index? If so, treat as two signed values since
1725 // indexes are signed values.
1726 //
1727 if ((Opcode & OPCODE_M_IMMED_OP2) != 0) {
1728 //
1729 // NOTE: need to find a way to fix this, most likely by changing the VM
1730 // implementation to remove the stack gap. To do that, we'd need to
1731 // allocate stack space for the VM and actually set the system
1732 // stack pointer to the allocated buffer when the VM starts.
1733 //
1734 // Special case -- if someone took the address of a function parameter
1735 // then we need to make sure it's not in the stack gap. We can identify
1736 // this situation if (Operand2 register == 0) && (Operand2 is direct)
1737 // && (Index applies to Operand2) && (Index > 0) && (Operand1 register != 0)
1738 // Situations that to be aware of:
1739 // * stack adjustments at beginning and end of functions R0 = R0 += stacksize
1740 //
1741 if ((OPERAND2_REGNUM (Operands) == 0) &&
1742 (!OPERAND2_INDIRECT (Operands)) &&
1743 (Index64Op2 > 0) &&
1744 (OPERAND1_REGNUM (Operands) == 0) &&
1745 (OPERAND1_INDIRECT (Operands))
1746 )
1747 {
1748 Data64 = (UINT64)ConvertStackAddr (VmPtr, (UINTN)(INT64)Data64);
1749 }
1750 }
1751 }
1752
1753 //
1754 // Now write it back
1755 //
1756 if (OPERAND1_INDIRECT (Operands)) {
1757 //
1758 // Reuse the Source variable to now be dest.
1759 //
1760 Source = (UINTN)(VmPtr->Gpr[OPERAND1_REGNUM (Operands)] + Index64Op1);
1761 //
1762 // Do the write based on the size
1763 //
1764 switch (MoveSize) {
1765 case DATA_SIZE_8:
1766 VmWriteMem8 (VmPtr, Source, (UINT8)Data64);
1767 break;
1768
1769 case DATA_SIZE_16:
1770 VmWriteMem16 (VmPtr, Source, (UINT16)Data64);
1771 break;
1772
1773 case DATA_SIZE_32:
1774 VmWriteMem32 (VmPtr, Source, (UINT32)Data64);
1775 break;
1776
1777 case DATA_SIZE_64:
1778 VmWriteMem64 (VmPtr, Source, Data64);
1779 break;
1780
1781 case DATA_SIZE_N:
1782 VmWriteMemN (VmPtr, Source, (UINTN)Data64);
1783 break;
1784
1785 default:
1786 //
1787 // not reached
1788 //
1789 break;
1790 }
1791 } else {
1792 //
1793 // Operand1 direct.
1794 // Make sure we didn't have an index on operand1.
1795 //
1796 if ((Opcode & OPCODE_M_IMMED_OP1) != 0) {
1799 EXCEPTION_FLAG_FATAL,
1800 VmPtr
1801 );
1802 return EFI_UNSUPPORTED;
1803 }
1804
1805 //
1806 // Direct storage in register. Clear unused bits and store back to
1807 // register.
1808 //
1809 VmPtr->Gpr[OPERAND1_REGNUM (Operands)] = Data64 & DataMask;
1810 }
1811
1812 //
1813 // Advance the instruction pointer
1814 //
1815 VmPtr->Ip += Size;
1816 return EFI_SUCCESS;
1817}
1818
1829 IN VM_CONTEXT *VmPtr
1830 )
1831{
1832 EFI_STATUS Status;
1833 UINT8 Operands;
1834 VOID *EbcEntryPoint;
1835 VOID *Thunk;
1836 UINT64 U64EbcEntryPoint;
1837 INT32 Offset;
1838
1839 Thunk = NULL;
1840 Operands = GETOPERANDS (VmPtr);
1841 switch (Operands) {
1842 //
1843 // Runaway program break. Generate an exception and terminate
1844 //
1845 case 0:
1846 EbcDebugSignalException (EXCEPT_EBC_BAD_BREAK, EXCEPTION_FLAG_FATAL, VmPtr);
1847 break;
1848
1849 //
1850 // Get VM version -- return VM revision number in R7
1851 //
1852 case 1:
1853 //
1854 // Bits:
1855 // 63-17 = 0
1856 // 16-8 = Major version
1857 // 7-0 = Minor version
1858 //
1859 VmPtr->Gpr[7] = GetVmVersion ();
1860 break;
1861
1862 //
1863 // Debugger breakpoint
1864 //
1865 case 3:
1866 VmPtr->StopFlags |= STOPFLAG_BREAKPOINT;
1867 //
1868 // See if someone has registered a handler
1869 //
1871 EXCEPT_EBC_BREAKPOINT,
1872 EXCEPTION_FLAG_NONE,
1873 VmPtr
1874 );
1875 break;
1876
1877 //
1878 // System call, which there are none, so NOP it.
1879 //
1880 case 4:
1881 break;
1882
1883 //
1884 // Create a thunk for EBC code. R7 points to a 32-bit (in a 64-bit slot)
1885 // "offset from self" pointer to the EBC entry point.
1886 // After we're done, *(UINT64 *)R7 will be the address of the new thunk.
1887 //
1888 case 5:
1889 Offset = (INT32)VmReadMem32 (VmPtr, (UINTN)VmPtr->Gpr[7]);
1890 U64EbcEntryPoint = (UINT64)(VmPtr->Gpr[7] + Offset + 4);
1891 EbcEntryPoint = (VOID *)(UINTN)U64EbcEntryPoint;
1892
1893 //
1894 // Now create a new thunk
1895 //
1896 Status = EbcCreateThunks (VmPtr->ImageHandle, EbcEntryPoint, &Thunk, 0);
1897 if (EFI_ERROR (Status)) {
1898 return Status;
1899 }
1900
1901 //
1902 // Finally replace the EBC entry point memory with the thunk address
1903 //
1904 VmWriteMem64 (VmPtr, (UINTN)VmPtr->Gpr[7], (UINT64)(UINTN)Thunk);
1905 break;
1906
1907 //
1908 // Compiler setting version per value in R7
1909 //
1910 case 6:
1911 VmPtr->CompilerVersion = (UINT32)VmPtr->Gpr[7];
1912 //
1913 // Check compiler version against VM version?
1914 //
1915 break;
1916
1917 //
1918 // Unhandled break code. Signal exception.
1919 //
1920 default:
1921 EbcDebugSignalException (EXCEPT_EBC_BAD_BREAK, EXCEPTION_FLAG_FATAL, VmPtr);
1922 break;
1923 }
1924
1925 //
1926 // Advance IP
1927 //
1928 VmPtr->Ip += 2;
1929 return EFI_SUCCESS;
1930}
1931
1959 IN VM_CONTEXT *VmPtr
1960 )
1961{
1962 UINT8 Opcode;
1963 UINT8 CompareSet;
1964 UINT8 ConditionFlag;
1965 UINT8 Size;
1966 UINT8 Operand;
1967 UINT64 Data64;
1968 INT32 Index32;
1969 UINTN Addr;
1970
1971 Operand = GETOPERANDS (VmPtr);
1972 Opcode = GETOPCODE (VmPtr);
1973
1974 //
1975 // Get instruction length from the opcode. The upper two bits are used here
1976 // to index into the length array.
1977 //
1978 Size = mJMPLen[(Opcode >> 6) & 0x03];
1979
1980 //
1981 // Decode instruction conditions
1982 // If we haven't met the condition, then simply advance the IP and return.
1983 //
1984 CompareSet = (UINT8)(((Operand & JMP_M_CS) != 0) ? 1 : 0);
1985 ConditionFlag = (UINT8)VMFLAG_ISSET (VmPtr, VMFLAGS_CC);
1986 if ((Operand & CONDITION_M_CONDITIONAL) != 0) {
1987 if (CompareSet != ConditionFlag) {
1989 VmPtr->Ip += Size;
1990 EbcDebuggerHookJMPEnd (VmPtr);
1991 return EFI_SUCCESS;
1992 }
1993 }
1994
1995 //
1996 // Check for 64-bit form and do it right away since it's the most
1997 // straight-forward form.
1998 //
1999 if ((Opcode & OPCODE_M_IMMDATA64) != 0) {
2000 //
2001 // Double check for immediate-data, which is required. If not there,
2002 // then signal an exception
2003 //
2004 if ((Opcode & OPCODE_M_IMMDATA) == 0) {
2007 EXCEPTION_FLAG_ERROR,
2008 VmPtr
2009 );
2010 return EFI_UNSUPPORTED;
2011 }
2012
2013 //
2014 // 64-bit immediate data is full address. Read the immediate data,
2015 // check for alignment, and jump absolute.
2016 //
2017 Data64 = (UINT64)VmReadImmed64 (VmPtr, 2);
2018 if (!ADDRESS_IS_ALIGNED ((UINTN)Data64, sizeof (UINT16))) {
2020 EXCEPT_EBC_ALIGNMENT_CHECK,
2021 EXCEPTION_FLAG_FATAL,
2022 VmPtr
2023 );
2024
2025 return EFI_UNSUPPORTED;
2026 }
2027
2028 //
2029 // Take jump -- relative or absolute
2030 //
2032 if ((Operand & JMP_M_RELATIVE) != 0) {
2033 VmPtr->Ip += (UINTN)Data64 + Size;
2034 } else {
2035 VmPtr->Ip = (VMIP)(UINTN)Data64;
2036 }
2037
2038 EbcDebuggerHookJMPEnd (VmPtr);
2039
2040 return EFI_SUCCESS;
2041 }
2042
2043 //
2044 // 32-bit forms:
2045 // Get the index if there is one. May be either an index, or an immediate
2046 // offset depending on indirect operand.
2047 // JMP32 @R1 Index32 -- immediate data is an index
2048 // JMP32 R1 Immed32 -- immedate data is an offset
2049 //
2050 if ((Opcode & OPCODE_M_IMMDATA) != 0) {
2051 if (OPERAND1_INDIRECT (Operand)) {
2052 Index32 = VmReadIndex32 (VmPtr, 2);
2053 } else {
2054 Index32 = VmReadImmed32 (VmPtr, 2);
2055 }
2056 } else {
2057 Index32 = 0;
2058 }
2059
2060 //
2061 // Get the register data. If R == 0, then special case where it's ignored.
2062 //
2063 if (OPERAND1_REGNUM (Operand) == 0) {
2064 Data64 = 0;
2065 } else {
2066 Data64 = (UINT64)OPERAND1_REGDATA (VmPtr, Operand);
2067 }
2068
2069 //
2070 // Decode the forms
2071 //
2072 if (OPERAND1_INDIRECT (Operand)) {
2073 //
2074 // Form: JMP32 @Rx {Index32}
2075 //
2076 Addr = VmReadMemN (VmPtr, (UINTN)Data64 + Index32);
2077 if (!ADDRESS_IS_ALIGNED ((UINTN)Addr, sizeof (UINT16))) {
2079 EXCEPT_EBC_ALIGNMENT_CHECK,
2080 EXCEPTION_FLAG_FATAL,
2081 VmPtr
2082 );
2083
2084 return EFI_UNSUPPORTED;
2085 }
2086
2088 if ((Operand & JMP_M_RELATIVE) != 0) {
2089 VmPtr->Ip += (UINTN)Addr + Size;
2090 } else {
2091 VmPtr->Ip = (VMIP)Addr;
2092 }
2093
2094 EbcDebuggerHookJMPEnd (VmPtr);
2095 } else {
2096 //
2097 // Form: JMP32 Rx {Immed32}
2098 //
2099 Addr = (UINTN)(Data64 + Index32);
2100 if (!ADDRESS_IS_ALIGNED ((UINTN)Addr, sizeof (UINT16))) {
2102 EXCEPT_EBC_ALIGNMENT_CHECK,
2103 EXCEPTION_FLAG_FATAL,
2104 VmPtr
2105 );
2106
2107 return EFI_UNSUPPORTED;
2108 }
2109
2111 if ((Operand & JMP_M_RELATIVE) != 0) {
2112 VmPtr->Ip += (UINTN)Addr + Size;
2113 } else {
2114 VmPtr->Ip = (VMIP)Addr;
2115 }
2116
2117 EbcDebuggerHookJMPEnd (VmPtr);
2118 }
2119
2120 return EFI_SUCCESS;
2121}
2122
2136 IN VM_CONTEXT *VmPtr
2137 )
2138{
2139 UINT8 Opcode;
2140 UINT8 ConditionFlag;
2141 UINT8 CompareSet;
2142 INT8 Offset;
2143
2144 //
2145 // Decode instruction.
2146 //
2147 Opcode = GETOPCODE (VmPtr);
2148 CompareSet = (UINT8)(((Opcode & JMP_M_CS) != 0) ? 1 : 0);
2149 ConditionFlag = (UINT8)VMFLAG_ISSET (VmPtr, VMFLAGS_CC);
2150
2151 //
2152 // If we haven't met the condition, then simply advance the IP and return
2153 //
2154 if ((Opcode & CONDITION_M_CONDITIONAL) != 0) {
2155 if (CompareSet != ConditionFlag) {
2157 VmPtr->Ip += 2;
2158 EbcDebuggerHookJMP8End (VmPtr);
2159 return EFI_SUCCESS;
2160 }
2161 }
2162
2163 //
2164 // Get the offset from the instruction stream. It's relative to the
2165 // following instruction, and divided by 2.
2166 //
2167 Offset = VmReadImmed8 (VmPtr, 1);
2168 //
2169 // Want to check for offset == -2 and then raise an exception?
2170 //
2172 VmPtr->Ip += (Offset * 2) + 2;
2173 EbcDebuggerHookJMP8End (VmPtr);
2174 return EFI_SUCCESS;
2175}
2176
2200 IN VM_CONTEXT *VmPtr
2201 )
2202{
2203 UINT8 Opcode;
2204 UINT8 Operands;
2205 UINT8 Size;
2206 INT16 Index16;
2207 INT64 ImmData64;
2208 UINT64 Op1;
2209 UINT64 Mask64;
2210
2211 //
2212 // Get the opcode and operands byte so we can get R1 and R2
2213 //
2214 Opcode = GETOPCODE (VmPtr);
2215 Operands = GETOPERANDS (VmPtr);
2216
2217 //
2218 // Get the index (16-bit) if present
2219 //
2220 if ((Operands & MOVI_M_IMMDATA) != 0) {
2221 Index16 = VmReadIndex16 (VmPtr, 2);
2222 Size = 4;
2223 } else {
2224 Index16 = 0;
2225 Size = 2;
2226 }
2227
2228 //
2229 // Extract the immediate data. Sign-extend always.
2230 //
2231 if ((Opcode & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH16) {
2232 ImmData64 = (INT64)(INT16)VmReadImmed16 (VmPtr, Size);
2233 Size += 2;
2234 } else if ((Opcode & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH32) {
2235 ImmData64 = (INT64)(INT32)VmReadImmed32 (VmPtr, Size);
2236 Size += 4;
2237 } else if ((Opcode & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH64) {
2238 ImmData64 = (INT64)VmReadImmed64 (VmPtr, Size);
2239 Size += 8;
2240 } else {
2241 //
2242 // Invalid encoding
2243 //
2246 EXCEPTION_FLAG_FATAL,
2247 VmPtr
2248 );
2249 return EFI_UNSUPPORTED;
2250 }
2251
2252 //
2253 // Now write back the result
2254 //
2255 if (!OPERAND1_INDIRECT (Operands)) {
2256 //
2257 // Operand1 direct. Make sure it didn't have an index.
2258 //
2259 if ((Operands & MOVI_M_IMMDATA) != 0) {
2262 EXCEPTION_FLAG_FATAL,
2263 VmPtr
2264 );
2265 return EFI_UNSUPPORTED;
2266 }
2267
2268 //
2269 // Writing directly to a register. Clear unused bits.
2270 //
2271 if ((Operands & MOVI_M_MOVEWIDTH) == MOVI_MOVEWIDTH8) {
2272 Mask64 = 0x000000FF;
2273 } else if ((Operands & MOVI_M_MOVEWIDTH) == MOVI_MOVEWIDTH16) {
2274 Mask64 = 0x0000FFFF;
2275 } else if ((Operands & MOVI_M_MOVEWIDTH) == MOVI_MOVEWIDTH32) {
2276 Mask64 = 0x00000000FFFFFFFF;
2277 } else {
2278 Mask64 = (UINT64) ~0;
2279 }
2280
2281 VmPtr->Gpr[OPERAND1_REGNUM (Operands)] = ImmData64 & Mask64;
2282 } else {
2283 //
2284 // Get the address then write back based on size of the move
2285 //
2286 Op1 = (UINT64)VmPtr->Gpr[OPERAND1_REGNUM (Operands)] + Index16;
2287 if ((Operands & MOVI_M_MOVEWIDTH) == MOVI_MOVEWIDTH8) {
2288 VmWriteMem8 (VmPtr, (UINTN)Op1, (UINT8)ImmData64);
2289 } else if ((Operands & MOVI_M_MOVEWIDTH) == MOVI_MOVEWIDTH16) {
2290 VmWriteMem16 (VmPtr, (UINTN)Op1, (UINT16)ImmData64);
2291 } else if ((Operands & MOVI_M_MOVEWIDTH) == MOVI_MOVEWIDTH32) {
2292 VmWriteMem32 (VmPtr, (UINTN)Op1, (UINT32)ImmData64);
2293 } else {
2294 VmWriteMem64 (VmPtr, (UINTN)Op1, (UINT64)ImmData64);
2295 }
2296 }
2297
2298 //
2299 // Advance the instruction pointer
2300 //
2301 VmPtr->Ip += Size;
2302 return EFI_SUCCESS;
2303}
2304
2321 IN VM_CONTEXT *VmPtr
2322 )
2323{
2324 UINT8 Opcode;
2325 UINT8 Operands;
2326 UINT8 Size;
2327 INT16 Index16;
2328 INT16 ImmedIndex16;
2329 INT32 ImmedIndex32;
2330 INT64 ImmedIndex64;
2331 UINT64 Op1;
2332
2333 //
2334 // Get the opcode and operands byte so we can get R1 and R2
2335 //
2336 Opcode = GETOPCODE (VmPtr);
2337 Operands = GETOPERANDS (VmPtr);
2338
2339 //
2340 // Get the operand1 index (16-bit) if present
2341 //
2342 if ((Operands & MOVI_M_IMMDATA) != 0) {
2343 Index16 = VmReadIndex16 (VmPtr, 2);
2344 Size = 4;
2345 } else {
2346 Index16 = 0;
2347 Size = 2;
2348 }
2349
2350 //
2351 // Extract the immediate data and convert to a 64-bit index.
2352 //
2353 if ((Opcode & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH16) {
2354 ImmedIndex16 = VmReadIndex16 (VmPtr, Size);
2355 ImmedIndex64 = (INT64)ImmedIndex16;
2356 Size += 2;
2357 } else if ((Opcode & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH32) {
2358 ImmedIndex32 = VmReadIndex32 (VmPtr, Size);
2359 ImmedIndex64 = (INT64)ImmedIndex32;
2360 Size += 4;
2361 } else if ((Opcode & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH64) {
2362 ImmedIndex64 = VmReadIndex64 (VmPtr, Size);
2363 Size += 8;
2364 } else {
2365 //
2366 // Invalid encoding
2367 //
2370 EXCEPTION_FLAG_FATAL,
2371 VmPtr
2372 );
2373 return EFI_UNSUPPORTED;
2374 }
2375
2376 //
2377 // Now write back the result
2378 //
2379 if (!OPERAND1_INDIRECT (Operands)) {
2380 //
2381 // Check for MOVIn R1 Index16, Immed (not indirect, with index), which
2382 // is illegal
2383 //
2384 if ((Operands & MOVI_M_IMMDATA) != 0) {
2387 EXCEPTION_FLAG_FATAL,
2388 VmPtr
2389 );
2390 return EFI_UNSUPPORTED;
2391 }
2392
2393 VmPtr->Gpr[OPERAND1_REGNUM (Operands)] = ImmedIndex64;
2394 } else {
2395 //
2396 // Get the address
2397 //
2398 Op1 = (UINT64)VmPtr->Gpr[OPERAND1_REGNUM (Operands)] + Index16;
2399 VmWriteMemN (VmPtr, (UINTN)Op1, (UINTN)(INTN)ImmedIndex64);
2400 }
2401
2402 //
2403 // Advance the instruction pointer
2404 //
2405 VmPtr->Ip += Size;
2406 return EFI_SUCCESS;
2407}
2408
2425 IN VM_CONTEXT *VmPtr
2426 )
2427{
2428 UINT8 Opcode;
2429 UINT8 Operands;
2430 UINT8 Size;
2431 INT16 Index16;
2432 INT64 ImmData64;
2433 UINT64 Op1;
2434 UINT64 Op2;
2435
2436 //
2437 // Get the opcode and operands byte so we can get R1 and R2
2438 //
2439 Opcode = GETOPCODE (VmPtr);
2440 Operands = GETOPERANDS (VmPtr);
2441
2442 //
2443 // Get the Operand 1 index (16-bit) if present
2444 //
2445 if ((Operands & MOVI_M_IMMDATA) != 0) {
2446 Index16 = VmReadIndex16 (VmPtr, 2);
2447 Size = 4;
2448 } else {
2449 Index16 = 0;
2450 Size = 2;
2451 }
2452
2453 //
2454 // Get the immediate data.
2455 //
2456 if ((Opcode & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH16) {
2457 ImmData64 = (INT64)VmReadImmed16 (VmPtr, Size);
2458 Size += 2;
2459 } else if ((Opcode & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH32) {
2460 ImmData64 = (INT64)VmReadImmed32 (VmPtr, Size);
2461 Size += 4;
2462 } else if ((Opcode & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH64) {
2463 ImmData64 = VmReadImmed64 (VmPtr, Size);
2464 Size += 8;
2465 } else {
2466 //
2467 // Invalid encoding
2468 //
2471 EXCEPTION_FLAG_FATAL,
2472 VmPtr
2473 );
2474 return EFI_UNSUPPORTED;
2475 }
2476
2477 //
2478 // Compute the value and write back the result
2479 //
2480 Op2 = (UINT64)((INT64)((UINT64)(UINTN)VmPtr->Ip) + (INT64)ImmData64 + Size);
2481 if (!OPERAND1_INDIRECT (Operands)) {
2482 //
2483 // Check for illegal combination of operand1 direct with immediate data
2484 //
2485 if ((Operands & MOVI_M_IMMDATA) != 0) {
2488 EXCEPTION_FLAG_FATAL,
2489 VmPtr
2490 );
2491 return EFI_UNSUPPORTED;
2492 }
2493
2494 VmPtr->Gpr[OPERAND1_REGNUM (Operands)] = (VM_REGISTER)Op2;
2495 } else {
2496 //
2497 // Get the address = [Rx] + Index16
2498 // Write back the result. Always a natural size write, since
2499 // we're talking addresses here.
2500 //
2501 Op1 = (UINT64)VmPtr->Gpr[OPERAND1_REGNUM (Operands)] + Index16;
2502 VmWriteMemN (VmPtr, (UINTN)Op1, (UINTN)Op2);
2503 }
2504
2505 //
2506 // Advance the instruction pointer
2507 //
2508 VmPtr->Ip += Size;
2509 return EFI_SUCCESS;
2510}
2511
2533 IN VM_CONTEXT *VmPtr
2534 )
2535{
2536 UINT8 Opcode;
2537 UINT8 Operands;
2538 UINT8 Size;
2539 INT16 Op1Index;
2540 INT16 Op2Index;
2541 UINT64 Op2;
2542
2543 //
2544 // Get the opcode and operand bytes
2545 //
2546 Opcode = GETOPCODE (VmPtr);
2547 Operands = GETOPERANDS (VmPtr);
2548
2549 Op1Index = Op2Index = 0;
2550
2551 //
2552 // Get the indexes if present.
2553 //
2554 Size = 2;
2555 if ((Opcode & OPCODE_M_IMMED_OP1) != 0) {
2556 if (OPERAND1_INDIRECT (Operands)) {
2557 Op1Index = VmReadIndex16 (VmPtr, 2);
2558 } else {
2559 //
2560 // Illegal form operand1 direct with index: MOVsnw R1 Index16, {@}R2
2561 //
2564 EXCEPTION_FLAG_FATAL,
2565 VmPtr
2566 );
2567 return EFI_UNSUPPORTED;
2568 }
2569
2570 Size += sizeof (UINT16);
2571 }
2572
2573 if ((Opcode & OPCODE_M_IMMED_OP2) != 0) {
2574 if (OPERAND2_INDIRECT (Operands)) {
2575 Op2Index = VmReadIndex16 (VmPtr, Size);
2576 } else {
2577 Op2Index = VmReadImmed16 (VmPtr, Size);
2578 }
2579
2580 Size += sizeof (UINT16);
2581 }
2582
2583 //
2584 // Get the data from the source.
2585 //
2586 Op2 = (UINT64)(INT64)(INTN)(VmPtr->Gpr[OPERAND2_REGNUM (Operands)] + Op2Index);
2587 if (OPERAND2_INDIRECT (Operands)) {
2588 Op2 = (UINT64)(INT64)(INTN)VmReadMemN (VmPtr, (UINTN)Op2);
2589 }
2590
2591 //
2592 // Now write back the result.
2593 //
2594 if (!OPERAND1_INDIRECT (Operands)) {
2595 VmPtr->Gpr[OPERAND1_REGNUM (Operands)] = Op2;
2596 } else {
2597 VmWriteMemN (VmPtr, (UINTN)(VmPtr->Gpr[OPERAND1_REGNUM (Operands)] + Op1Index), (UINTN)Op2);
2598 }
2599
2600 //
2601 // Advance the instruction pointer
2602 //
2603 VmPtr->Ip += Size;
2604 return EFI_SUCCESS;
2605}
2606
2628 IN VM_CONTEXT *VmPtr
2629 )
2630{
2631 UINT8 Opcode;
2632 UINT8 Operands;
2633 UINT8 Size;
2634 INT32 Op1Index;
2635 INT32 Op2Index;
2636 UINT64 Op2;
2637
2638 //
2639 // Get the opcode and operand bytes
2640 //
2641 Opcode = GETOPCODE (VmPtr);
2642 Operands = GETOPERANDS (VmPtr);
2643
2644 Op1Index = Op2Index = 0;
2645
2646 //
2647 // Get the indexes if present.
2648 //
2649 Size = 2;
2650 if ((Opcode & OPCODE_M_IMMED_OP1) != 0) {
2651 if (OPERAND1_INDIRECT (Operands)) {
2652 Op1Index = VmReadIndex32 (VmPtr, 2);
2653 } else {
2654 //
2655 // Illegal form operand1 direct with index: MOVsnd R1 Index16,..
2656 //
2659 EXCEPTION_FLAG_FATAL,
2660 VmPtr
2661 );
2662 return EFI_UNSUPPORTED;
2663 }
2664
2665 Size += sizeof (UINT32);
2666 }
2667
2668 if ((Opcode & OPCODE_M_IMMED_OP2) != 0) {
2669 if (OPERAND2_INDIRECT (Operands)) {
2670 Op2Index = VmReadIndex32 (VmPtr, Size);
2671 } else {
2672 Op2Index = VmReadImmed32 (VmPtr, Size);
2673 }
2674
2675 Size += sizeof (UINT32);
2676 }
2677
2678 //
2679 // Get the data from the source.
2680 //
2681 Op2 = (UINT64)(INT64)(INTN)(INT64)(VmPtr->Gpr[OPERAND2_REGNUM (Operands)] + Op2Index);
2682 if (OPERAND2_INDIRECT (Operands)) {
2683 Op2 = (UINT64)(INT64)(INTN)(INT64)VmReadMemN (VmPtr, (UINTN)Op2);
2684 }
2685
2686 //
2687 // Now write back the result.
2688 //
2689 if (!OPERAND1_INDIRECT (Operands)) {
2690 VmPtr->Gpr[OPERAND1_REGNUM (Operands)] = Op2;
2691 } else {
2692 VmWriteMemN (VmPtr, (UINTN)(VmPtr->Gpr[OPERAND1_REGNUM (Operands)] + Op1Index), (UINTN)Op2);
2693 }
2694
2695 //
2696 // Advance the instruction pointer
2697 //
2698 VmPtr->Ip += Size;
2699 return EFI_SUCCESS;
2700}
2701
2715 IN VM_CONTEXT *VmPtr
2716 )
2717{
2718 UINT8 Opcode;
2719 UINT8 Operands;
2720 INT16 Index16;
2721 UINTN DataN;
2722
2723 //
2724 // Get opcode and operands
2725 //
2726 Opcode = GETOPCODE (VmPtr);
2727 Operands = GETOPERANDS (VmPtr);
2728
2729 //
2730 // Get index if present
2731 //
2732 if ((Opcode & PUSHPOP_M_IMMDATA) != 0) {
2733 if (OPERAND1_INDIRECT (Operands)) {
2734 Index16 = VmReadIndex16 (VmPtr, 2);
2735 } else {
2736 Index16 = VmReadImmed16 (VmPtr, 2);
2737 }
2738
2739 VmPtr->Ip += 4;
2740 } else {
2741 Index16 = 0;
2742 VmPtr->Ip += 2;
2743 }
2744
2745 //
2746 // Get the data to push
2747 //
2748 if (OPERAND1_INDIRECT (Operands)) {
2749 DataN = VmReadMemN (VmPtr, (UINTN)(VmPtr->Gpr[OPERAND1_REGNUM (Operands)] + Index16));
2750 } else {
2751 DataN = (UINTN)(VmPtr->Gpr[OPERAND1_REGNUM (Operands)] + Index16);
2752 }
2753
2754 //
2755 // Adjust the stack down.
2756 //
2757 VmPtr->Gpr[0] -= sizeof (UINTN);
2758 VmWriteMemN (VmPtr, (UINTN)VmPtr->Gpr[0], DataN);
2759 return EFI_SUCCESS;
2760}
2761
2775 IN VM_CONTEXT *VmPtr
2776 )
2777{
2778 UINT8 Opcode;
2779 UINT8 Operands;
2780 UINT32 Data32;
2781 UINT64 Data64;
2782 INT16 Index16;
2783
2784 //
2785 // Get opcode and operands
2786 //
2787 Opcode = GETOPCODE (VmPtr);
2788 Operands = GETOPERANDS (VmPtr);
2789 //
2790 // Get immediate index if present, then advance the IP.
2791 //
2792 if ((Opcode & PUSHPOP_M_IMMDATA) != 0) {
2793 if (OPERAND1_INDIRECT (Operands)) {
2794 Index16 = VmReadIndex16 (VmPtr, 2);
2795 } else {
2796 Index16 = VmReadImmed16 (VmPtr, 2);
2797 }
2798
2799 VmPtr->Ip += 4;
2800 } else {
2801 Index16 = 0;
2802 VmPtr->Ip += 2;
2803 }
2804
2805 //
2806 // Get the data to push
2807 //
2808 if ((Opcode & PUSHPOP_M_64) != 0) {
2809 if (OPERAND1_INDIRECT (Operands)) {
2810 Data64 = VmReadMem64 (VmPtr, (UINTN)(VmPtr->Gpr[OPERAND1_REGNUM (Operands)] + Index16));
2811 } else {
2812 Data64 = (UINT64)VmPtr->Gpr[OPERAND1_REGNUM (Operands)] + Index16;
2813 }
2814
2815 //
2816 // Adjust the stack down, then write back the data
2817 //
2818 VmPtr->Gpr[0] -= sizeof (UINT64);
2819 VmWriteMem64 (VmPtr, (UINTN)VmPtr->Gpr[0], Data64);
2820 } else {
2821 //
2822 // 32-bit data
2823 //
2824 if (OPERAND1_INDIRECT (Operands)) {
2825 Data32 = VmReadMem32 (VmPtr, (UINTN)(VmPtr->Gpr[OPERAND1_REGNUM (Operands)] + Index16));
2826 } else {
2827 Data32 = (UINT32)VmPtr->Gpr[OPERAND1_REGNUM (Operands)] + Index16;
2828 }
2829
2830 //
2831 // Adjust the stack down and write the data
2832 //
2833 VmPtr->Gpr[0] -= sizeof (UINT32);
2834 VmWriteMem32 (VmPtr, (UINTN)VmPtr->Gpr[0], Data32);
2835 }
2836
2837 return EFI_SUCCESS;
2838}
2839
2853 IN VM_CONTEXT *VmPtr
2854 )
2855{
2856 UINT8 Opcode;
2857 UINT8 Operands;
2858 INT16 Index16;
2859 UINTN DataN;
2860
2861 //
2862 // Get opcode and operands
2863 //
2864 Opcode = GETOPCODE (VmPtr);
2865 Operands = GETOPERANDS (VmPtr);
2866 //
2867 // Get immediate data if present, and advance the IP
2868 //
2869 if ((Opcode & PUSHPOP_M_IMMDATA) != 0) {
2870 if (OPERAND1_INDIRECT (Operands)) {
2871 Index16 = VmReadIndex16 (VmPtr, 2);
2872 } else {
2873 Index16 = VmReadImmed16 (VmPtr, 2);
2874 }
2875
2876 VmPtr->Ip += 4;
2877 } else {
2878 Index16 = 0;
2879 VmPtr->Ip += 2;
2880 }
2881
2882 //
2883 // Read the data off the stack, then adjust the stack pointer
2884 //
2885 DataN = VmReadMemN (VmPtr, (UINTN)VmPtr->Gpr[0]);
2886 VmPtr->Gpr[0] += sizeof (UINTN);
2887 //
2888 // Do the write-back
2889 //
2890 if (OPERAND1_INDIRECT (Operands)) {
2891 VmWriteMemN (VmPtr, (UINTN)(VmPtr->Gpr[OPERAND1_REGNUM (Operands)] + Index16), DataN);
2892 } else {
2893 VmPtr->Gpr[OPERAND1_REGNUM (Operands)] = (INT64)(UINT64)(UINTN)(DataN + Index16);
2894 }
2895
2896 return EFI_SUCCESS;
2897}
2898
2912 IN VM_CONTEXT *VmPtr
2913 )
2914{
2915 UINT8 Opcode;
2916 UINT8 Operands;
2917 INT16 Index16;
2918 INT32 Data32;
2919 UINT64 Data64;
2920
2921 //
2922 // Get opcode and operands
2923 //
2924 Opcode = GETOPCODE (VmPtr);
2925 Operands = GETOPERANDS (VmPtr);
2926 //
2927 // Get immediate data if present, and advance the IP.
2928 //
2929 if ((Opcode & PUSHPOP_M_IMMDATA) != 0) {
2930 if (OPERAND1_INDIRECT (Operands)) {
2931 Index16 = VmReadIndex16 (VmPtr, 2);
2932 } else {
2933 Index16 = VmReadImmed16 (VmPtr, 2);
2934 }
2935
2936 VmPtr->Ip += 4;
2937 } else {
2938 Index16 = 0;
2939 VmPtr->Ip += 2;
2940 }
2941
2942 //
2943 // Get the data off the stack, then write it to the appropriate location
2944 //
2945 if ((Opcode & PUSHPOP_M_64) != 0) {
2946 //
2947 // Read the data off the stack, then adjust the stack pointer
2948 //
2949 Data64 = VmReadMem64 (VmPtr, (UINTN)VmPtr->Gpr[0]);
2950 VmPtr->Gpr[0] += sizeof (UINT64);
2951 //
2952 // Do the write-back
2953 //
2954 if (OPERAND1_INDIRECT (Operands)) {
2955 VmWriteMem64 (VmPtr, (UINTN)(VmPtr->Gpr[OPERAND1_REGNUM (Operands)] + Index16), Data64);
2956 } else {
2957 VmPtr->Gpr[OPERAND1_REGNUM (Operands)] = Data64 + Index16;
2958 }
2959 } else {
2960 //
2961 // 32-bit pop. Read it off the stack and adjust the stack pointer
2962 //
2963 Data32 = (INT32)VmReadMem32 (VmPtr, (UINTN)VmPtr->Gpr[0]);
2964 VmPtr->Gpr[0] += sizeof (UINT32);
2965 //
2966 // Do the write-back
2967 //
2968 if (OPERAND1_INDIRECT (Operands)) {
2969 VmWriteMem32 (VmPtr, (UINTN)(VmPtr->Gpr[OPERAND1_REGNUM (Operands)] + Index16), Data32);
2970 } else {
2971 VmPtr->Gpr[OPERAND1_REGNUM (Operands)] = (INT64)Data32 + Index16;
2972 }
2973 }
2974
2975 return EFI_SUCCESS;
2976}
2977
2996 IN VM_CONTEXT *VmPtr
2997 )
2998{
2999 UINT8 Opcode;
3000 UINT8 Operands;
3001 INT32 Immed32;
3002 UINT8 Size;
3003 INT64 Immed64;
3004 VOID *FramePtr;
3005
3006 //
3007 // Get opcode and operands
3008 //
3009 Opcode = GETOPCODE (VmPtr);
3010 Operands = GETOPERANDS (VmPtr);
3011
3012 if ((Operands & OPERAND_M_NATIVE_CALL) != 0) {
3014 } else {
3016 }
3017
3018 //
3019 // Assign these as well to avoid compiler warnings
3020 //
3021 Immed64 = 0;
3022 Immed32 = 0;
3023
3024 FramePtr = VmPtr->FramePtr;
3025 //
3026 // Determine the instruction size, and get immediate data if present
3027 //
3028 if ((Opcode & OPCODE_M_IMMDATA) != 0) {
3029 if ((Opcode & OPCODE_M_IMMDATA64) != 0) {
3030 Immed64 = VmReadImmed64 (VmPtr, 2);
3031 Size = 10;
3032 } else {
3033 //
3034 // If register operand is indirect, then the immediate data is an index
3035 //
3036 if (OPERAND1_INDIRECT (Operands)) {
3037 Immed32 = VmReadIndex32 (VmPtr, 2);
3038 } else {
3039 Immed32 = VmReadImmed32 (VmPtr, 2);
3040 }
3041
3042 Size = 6;
3043 }
3044 } else {
3045 Size = 2;
3046 }
3047
3048 //
3049 // If it's a call to EBC, adjust the stack pointer down 16 bytes and
3050 // put our return address and frame pointer on the VM stack.
3051 //
3052 if ((Operands & OPERAND_M_NATIVE_CALL) == 0) {
3053 VmPtr->Gpr[0] -= 8;
3054 VmWriteMemN (VmPtr, (UINTN)VmPtr->Gpr[0], (UINTN)FramePtr);
3055 VmPtr->FramePtr = (VOID *)(UINTN)VmPtr->Gpr[0];
3056 VmPtr->Gpr[0] -= 8;
3057 VmWriteMem64 (VmPtr, (UINTN)VmPtr->Gpr[0], (UINT64)(UINTN)(VmPtr->Ip + Size));
3058 }
3059
3060 //
3061 // If 64-bit data, then absolute jump only
3062 //
3063 if ((Opcode & OPCODE_M_IMMDATA64) != 0) {
3064 //
3065 // Native or EBC call?
3066 //
3067 if ((Operands & OPERAND_M_NATIVE_CALL) == 0) {
3068 VmPtr->Ip = (VMIP)(UINTN)Immed64;
3069 } else {
3070 //
3071 // Call external function, get the return value, and advance the IP
3072 //
3073 EbcLLCALLEX (VmPtr, (UINTN)Immed64, (UINTN)VmPtr->Gpr[0], FramePtr, Size);
3074 }
3075 } else {
3076 //
3077 // Get the register data. If operand1 == 0, then ignore register and
3078 // take immediate data as relative or absolute address.
3079 // Compiler should take care of upper bits if 32-bit machine.
3080 //
3081 if (OPERAND1_REGNUM (Operands) != 0) {
3082 Immed64 = (UINT64)(UINTN)VmPtr->Gpr[OPERAND1_REGNUM (Operands)];
3083 }
3084
3085 //
3086 // Get final address
3087 //
3088 if (OPERAND1_INDIRECT (Operands)) {
3089 Immed64 = (INT64)(UINT64)(UINTN)VmReadMemN (VmPtr, (UINTN)(Immed64 + Immed32));
3090 } else {
3091 Immed64 += Immed32;
3092 }
3093
3094 //
3095 // Now determine if external call, and then if relative or absolute
3096 //
3097 if ((Operands & OPERAND_M_NATIVE_CALL) == 0) {
3098 //
3099 // EBC call. Relative or absolute? If relative, then it's relative to the
3100 // start of the next instruction.
3101 //
3102 if ((Operands & OPERAND_M_RELATIVE_ADDR) != 0) {
3103 VmPtr->Ip += Immed64 + Size;
3104 } else {
3105 VmPtr->Ip = (VMIP)(UINTN)Immed64;
3106 }
3107 } else {
3108 //
3109 // Native call. Relative or absolute?
3110 //
3111 if ((Operands & OPERAND_M_RELATIVE_ADDR) != 0) {
3112 EbcLLCALLEX (VmPtr, (UINTN)(Immed64 + VmPtr->Ip + Size), (UINTN)VmPtr->Gpr[0], FramePtr, Size);
3113 } else {
3114 if ((VmPtr->StopFlags & STOPFLAG_BREAK_ON_CALLEX) != 0) {
3115 CpuBreakpoint ();
3116 }
3117
3118 EbcLLCALLEX (VmPtr, (UINTN)Immed64, (UINTN)VmPtr->Gpr[0], FramePtr, Size);
3119 }
3120 }
3121 }
3122
3123 if ((Operands & OPERAND_M_NATIVE_CALL) != 0) {
3125 } else {
3126 EbcDebuggerHookCALLEnd (VmPtr);
3127 }
3128
3129 return EFI_SUCCESS;
3130}
3131
3145 IN VM_CONTEXT *VmPtr
3146 )
3147{
3149
3150 //
3151 // If we're at the top of the stack, then simply set the done
3152 // flag and return
3153 //
3154 if (VmPtr->StackRetAddr == (UINT64)VmPtr->Gpr[0]) {
3155 VmPtr->StopFlags |= STOPFLAG_APP_DONE;
3156 } else {
3157 //
3158 // Pull the return address off the VM app's stack and set the IP
3159 // to it
3160 //
3161 if (!ADDRESS_IS_ALIGNED ((UINTN)VmPtr->Gpr[0], sizeof (UINT16))) {
3163 EXCEPT_EBC_ALIGNMENT_CHECK,
3164 EXCEPTION_FLAG_FATAL,
3165 VmPtr
3166 );
3167 }
3168
3169 //
3170 // Restore the IP and frame pointer from the stack
3171 //
3172 VmPtr->Ip = (VMIP)(UINTN)VmReadMem64 (VmPtr, (UINTN)VmPtr->Gpr[0]);
3173 VmPtr->Gpr[0] += 8;
3174 VmPtr->FramePtr = (VOID *)VmReadMemN (VmPtr, (UINTN)VmPtr->Gpr[0]);
3175 VmPtr->Gpr[0] += 8;
3176 }
3177
3178 EbcDebuggerHookRETEnd (VmPtr);
3179
3180 return EFI_SUCCESS;
3181}
3182
3197 IN VM_CONTEXT *VmPtr
3198 )
3199{
3200 UINT8 Opcode;
3201 UINT8 Operands;
3202 UINT8 Size;
3203 INT16 Index16;
3204 UINT32 Flag;
3205 INT64 Op2;
3206 INT64 Op1;
3207
3208 //
3209 // Get opcode and operands
3210 //
3211 Opcode = GETOPCODE (VmPtr);
3212 Operands = GETOPERANDS (VmPtr);
3213 //
3214 // Get the register data we're going to compare to
3215 //
3216 Op1 = VmPtr->Gpr[OPERAND1_REGNUM (Operands)];
3217 //
3218 // Get immediate data
3219 //
3220 if ((Opcode & OPCODE_M_IMMDATA) != 0) {
3221 if (OPERAND2_INDIRECT (Operands)) {
3222 Index16 = VmReadIndex16 (VmPtr, 2);
3223 } else {
3224 Index16 = VmReadImmed16 (VmPtr, 2);
3225 }
3226
3227 Size = 4;
3228 } else {
3229 Index16 = 0;
3230 Size = 2;
3231 }
3232
3233 //
3234 // Now get Op2
3235 //
3236 if (OPERAND2_INDIRECT (Operands)) {
3237 if ((Opcode & OPCODE_M_64BIT) != 0) {
3238 Op2 = (INT64)VmReadMem64 (VmPtr, (UINTN)(VmPtr->Gpr[OPERAND2_REGNUM (Operands)] + Index16));
3239 } else {
3240 //
3241 // 32-bit operations. 0-extend the values for all cases.
3242 //
3243 Op2 = (INT64)(UINT64)((UINT32)VmReadMem32 (VmPtr, (UINTN)(VmPtr->Gpr[OPERAND2_REGNUM (Operands)] + Index16)));
3244 }
3245 } else {
3246 Op2 = VmPtr->Gpr[OPERAND2_REGNUM (Operands)] + Index16;
3247 }
3248
3249 //
3250 // Now do the compare
3251 //
3252 Flag = 0;
3253 if ((Opcode & OPCODE_M_64BIT) != 0) {
3254 //
3255 // 64-bit compares
3256 //
3257 switch (Opcode & OPCODE_M_OPCODE) {
3258 case OPCODE_CMPEQ:
3259 if (Op1 == Op2) {
3260 Flag = 1;
3261 }
3262
3263 break;
3264
3265 case OPCODE_CMPLTE:
3266 if (Op1 <= Op2) {
3267 Flag = 1;
3268 }
3269
3270 break;
3271
3272 case OPCODE_CMPGTE:
3273 if (Op1 >= Op2) {
3274 Flag = 1;
3275 }
3276
3277 break;
3278
3279 case OPCODE_CMPULTE:
3280 if ((UINT64)Op1 <= (UINT64)Op2) {
3281 Flag = 1;
3282 }
3283
3284 break;
3285
3286 case OPCODE_CMPUGTE:
3287 if ((UINT64)Op1 >= (UINT64)Op2) {
3288 Flag = 1;
3289 }
3290
3291 break;
3292
3293 default:
3294 ASSERT (0);
3295 }
3296 } else {
3297 //
3298 // 32-bit compares
3299 //
3300 switch (Opcode & OPCODE_M_OPCODE) {
3301 case OPCODE_CMPEQ:
3302 if ((INT32)Op1 == (INT32)Op2) {
3303 Flag = 1;
3304 }
3305
3306 break;
3307
3308 case OPCODE_CMPLTE:
3309 if ((INT32)Op1 <= (INT32)Op2) {
3310 Flag = 1;
3311 }
3312
3313 break;
3314
3315 case OPCODE_CMPGTE:
3316 if ((INT32)Op1 >= (INT32)Op2) {
3317 Flag = 1;
3318 }
3319
3320 break;
3321
3322 case OPCODE_CMPULTE:
3323 if ((UINT32)Op1 <= (UINT32)Op2) {
3324 Flag = 1;
3325 }
3326
3327 break;
3328
3329 case OPCODE_CMPUGTE:
3330 if ((UINT32)Op1 >= (UINT32)Op2) {
3331 Flag = 1;
3332 }
3333
3334 break;
3335
3336 default:
3337 ASSERT (0);
3338 }
3339 }
3340
3341 //
3342 // Now set the flag accordingly for the comparison
3343 //
3344 if (Flag != 0) {
3345 VMFLAG_SET (VmPtr, VMFLAGS_CC);
3346 } else {
3347 VMFLAG_CLEAR (VmPtr, (UINT64)VMFLAGS_CC);
3348 }
3349
3350 //
3351 // Advance the IP
3352 //
3353 VmPtr->Ip += Size;
3354 return EFI_SUCCESS;
3355}
3356
3371 IN VM_CONTEXT *VmPtr
3372 )
3373{
3374 UINT8 Opcode;
3375 UINT8 Operands;
3376 UINT8 Size;
3377 INT64 Op1;
3378 INT64 Op2;
3379 INT16 Index16;
3380 UINT32 Flag;
3381
3382 //
3383 // Get opcode and operands
3384 //
3385 Opcode = GETOPCODE (VmPtr);
3386 Operands = GETOPERANDS (VmPtr);
3387
3388 //
3389 // Get operand1 index if present
3390 //
3391 Size = 2;
3392 if ((Operands & OPERAND_M_CMPI_INDEX) != 0) {
3393 Index16 = VmReadIndex16 (VmPtr, 2);
3394 Size += 2;
3395 } else {
3396 Index16 = 0;
3397 }
3398
3399 //
3400 // Get operand1 data we're going to compare to
3401 //
3402 Op1 = (INT64)VmPtr->Gpr[OPERAND1_REGNUM (Operands)];
3403 if (OPERAND1_INDIRECT (Operands)) {
3404 //
3405 // Indirect operand1. Fetch 32 or 64-bit value based on compare size.
3406 //
3407 if ((Opcode & OPCODE_M_CMPI64) != 0) {
3408 Op1 = (INT64)VmReadMem64 (VmPtr, (UINTN)Op1 + Index16);
3409 } else {
3410 Op1 = (INT64)VmReadMem32 (VmPtr, (UINTN)Op1 + Index16);
3411 }
3412 } else {
3413 //
3414 // Better not have been an index with direct. That is, CMPI R1 Index,...
3415 // is illegal.
3416 //
3417 if ((Operands & OPERAND_M_CMPI_INDEX) != 0) {
3420 EXCEPTION_FLAG_ERROR,
3421 VmPtr
3422 );
3423 VmPtr->Ip += Size;
3424 return EFI_UNSUPPORTED;
3425 }
3426 }
3427
3428 //
3429 // Get immediate data -- 16- or 32-bit sign extended
3430 //
3431 if ((Opcode & OPCODE_M_CMPI32_DATA) != 0) {
3432 Op2 = (INT64)VmReadImmed32 (VmPtr, Size);
3433 Size += 4;
3434 } else {
3435 //
3436 // 16-bit immediate data. Sign extend always.
3437 //
3438 Op2 = (INT64)((INT16)VmReadImmed16 (VmPtr, Size));
3439 Size += 2;
3440 }
3441
3442 //
3443 // Now do the compare
3444 //
3445 Flag = 0;
3446 if ((Opcode & OPCODE_M_CMPI64) != 0) {
3447 //
3448 // 64 bit comparison
3449 //
3450 switch (Opcode & OPCODE_M_OPCODE) {
3451 case OPCODE_CMPIEQ:
3452 if (Op1 == (INT64)Op2) {
3453 Flag = 1;
3454 }
3455
3456 break;
3457
3458 case OPCODE_CMPILTE:
3459 if (Op1 <= (INT64)Op2) {
3460 Flag = 1;
3461 }
3462
3463 break;
3464
3465 case OPCODE_CMPIGTE:
3466 if (Op1 >= (INT64)Op2) {
3467 Flag = 1;
3468 }
3469
3470 break;
3471
3472 case OPCODE_CMPIULTE:
3473 if ((UINT64)Op1 <= (UINT64)((UINT32)Op2)) {
3474 Flag = 1;
3475 }
3476
3477 break;
3478
3479 case OPCODE_CMPIUGTE:
3480 if ((UINT64)Op1 >= (UINT64)((UINT32)Op2)) {
3481 Flag = 1;
3482 }
3483
3484 break;
3485
3486 default:
3487 ASSERT (0);
3488 }
3489 } else {
3490 //
3491 // 32-bit comparisons
3492 //
3493 switch (Opcode & OPCODE_M_OPCODE) {
3494 case OPCODE_CMPIEQ:
3495 if ((INT32)Op1 == Op2) {
3496 Flag = 1;
3497 }
3498
3499 break;
3500
3501 case OPCODE_CMPILTE:
3502 if ((INT32)Op1 <= Op2) {
3503 Flag = 1;
3504 }
3505
3506 break;
3507
3508 case OPCODE_CMPIGTE:
3509 if ((INT32)Op1 >= Op2) {
3510 Flag = 1;
3511 }
3512
3513 break;
3514
3515 case OPCODE_CMPIULTE:
3516 if ((UINT32)Op1 <= (UINT32)Op2) {
3517 Flag = 1;
3518 }
3519
3520 break;
3521
3522 case OPCODE_CMPIUGTE:
3523 if ((UINT32)Op1 >= (UINT32)Op2) {
3524 Flag = 1;
3525 }
3526
3527 break;
3528
3529 default:
3530 ASSERT (0);
3531 }
3532 }
3533
3534 //
3535 // Now set the flag accordingly for the comparison
3536 //
3537 if (Flag != 0) {
3538 VMFLAG_SET (VmPtr, VMFLAGS_CC);
3539 } else {
3540 VMFLAG_CLEAR (VmPtr, (UINT64)VMFLAGS_CC);
3541 }
3542
3543 //
3544 // Advance the IP
3545 //
3546 VmPtr->Ip += Size;
3547 return EFI_SUCCESS;
3548}
3549
3563UINT64
3565 IN VM_CONTEXT *VmPtr,
3566 IN UINT64 Op1,
3567 IN UINT64 Op2
3568 )
3569{
3570 return ~Op2;
3571}
3572
3586UINT64
3588 IN VM_CONTEXT *VmPtr,
3589 IN UINT64 Op1,
3590 IN UINT64 Op2
3591 )
3592{
3593 return ~Op2 + 1;
3594}
3595
3609UINT64
3611 IN VM_CONTEXT *VmPtr,
3612 IN UINT64 Op1,
3613 IN UINT64 Op2
3614 )
3615{
3616 return Op1 + Op2;
3617}
3618
3632UINT64
3634 IN VM_CONTEXT *VmPtr,
3635 IN UINT64 Op1,
3636 IN UINT64 Op2
3637 )
3638{
3639 if ((*VmPtr->Ip & DATAMANIP_M_64) != 0) {
3640 return (UINT64)((INT64)((INT64)Op1 - (INT64)Op2));
3641 } else {
3642 return (UINT64)((INT64)((INT32)((INT32)Op1 - (INT32)Op2)));
3643 }
3644}
3645
3659UINT64
3661 IN VM_CONTEXT *VmPtr,
3662 IN UINT64 Op1,
3663 IN UINT64 Op2
3664 )
3665{
3666 if ((*VmPtr->Ip & DATAMANIP_M_64) != 0) {
3667 return MultS64x64 ((INT64)Op1, (INT64)Op2);
3668 } else {
3669 return (UINT64)((INT64)((INT32)((INT32)Op1 * (INT32)Op2)));
3670 }
3671}
3672
3686UINT64
3688 IN VM_CONTEXT *VmPtr,
3689 IN UINT64 Op1,
3690 IN UINT64 Op2
3691 )
3692{
3693 if ((*VmPtr->Ip & DATAMANIP_M_64) != 0) {
3694 return MultU64x64 (Op1, Op2);
3695 } else {
3696 return (UINT64)((UINT32)((UINT32)Op1 * (UINT32)Op2));
3697 }
3698}
3699
3713UINT64
3715 IN VM_CONTEXT *VmPtr,
3716 IN UINT64 Op1,
3717 IN UINT64 Op2
3718 )
3719{
3720 INT64 Remainder;
3721
3722 //
3723 // Check for divide-by-0
3724 //
3725 if (Op2 == 0) {
3727 EXCEPT_EBC_DIVIDE_ERROR,
3728 EXCEPTION_FLAG_FATAL,
3729 VmPtr
3730 );
3731
3732 return 0;
3733 } else {
3734 if ((*VmPtr->Ip & DATAMANIP_M_64) != 0) {
3735 return (UINT64)(DivS64x64Remainder (Op1, Op2, &Remainder));
3736 } else {
3737 return (UINT64)((INT64)((INT32)Op1 / (INT32)Op2));
3738 }
3739 }
3740}
3741
3755UINT64
3757 IN VM_CONTEXT *VmPtr,
3758 IN UINT64 Op1,
3759 IN UINT64 Op2
3760 )
3761{
3762 UINT64 Remainder;
3763
3764 //
3765 // Check for divide-by-0
3766 //
3767 if (Op2 == 0) {
3769 EXCEPT_EBC_DIVIDE_ERROR,
3770 EXCEPTION_FLAG_FATAL,
3771 VmPtr
3772 );
3773 return 0;
3774 } else {
3775 //
3776 // Get the destination register
3777 //
3778 if ((*VmPtr->Ip & DATAMANIP_M_64) != 0) {
3779 return (UINT64)(DivU64x64Remainder (Op1, Op2, &Remainder));
3780 } else {
3781 return (UINT64)((UINT32)Op1 / (UINT32)Op2);
3782 }
3783 }
3784}
3785
3799UINT64
3801 IN VM_CONTEXT *VmPtr,
3802 IN UINT64 Op1,
3803 IN UINT64 Op2
3804 )
3805{
3806 INT64 Remainder;
3807
3808 //
3809 // Check for divide-by-0
3810 //
3811 if (Op2 == 0) {
3813 EXCEPT_EBC_DIVIDE_ERROR,
3814 EXCEPTION_FLAG_FATAL,
3815 VmPtr
3816 );
3817 return 0;
3818 } else {
3819 DivS64x64Remainder ((INT64)Op1, (INT64)Op2, &Remainder);
3820 return Remainder;
3821 }
3822}
3823
3837UINT64
3839 IN VM_CONTEXT *VmPtr,
3840 IN UINT64 Op1,
3841 IN UINT64 Op2
3842 )
3843{
3844 UINT64 Remainder;
3845
3846 //
3847 // Check for divide-by-0
3848 //
3849 if (Op2 == 0) {
3851 EXCEPT_EBC_DIVIDE_ERROR,
3852 EXCEPTION_FLAG_FATAL,
3853 VmPtr
3854 );
3855 return 0;
3856 } else {
3857 DivU64x64Remainder (Op1, Op2, &Remainder);
3858 return Remainder;
3859 }
3860}
3861
3875UINT64
3877 IN VM_CONTEXT *VmPtr,
3878 IN UINT64 Op1,
3879 IN UINT64 Op2
3880 )
3881{
3882 return Op1 & Op2;
3883}
3884
3898UINT64
3900 IN VM_CONTEXT *VmPtr,
3901 IN UINT64 Op1,
3902 IN UINT64 Op2
3903 )
3904{
3905 return Op1 | Op2;
3906}
3907
3921UINT64
3923 IN VM_CONTEXT *VmPtr,
3924 IN UINT64 Op1,
3925 IN UINT64 Op2
3926 )
3927{
3928 return Op1 ^ Op2;
3929}
3930
3944UINT64
3946 IN VM_CONTEXT *VmPtr,
3947 IN UINT64 Op1,
3948 IN UINT64 Op2
3949 )
3950{
3951 if ((*VmPtr->Ip & DATAMANIP_M_64) != 0) {
3952 return LShiftU64 (Op1, (UINTN)Op2);
3953 } else {
3954 return (UINT64)((UINT32)((UINT32)Op1 << (UINT32)Op2));
3955 }
3956}
3957
3971UINT64
3973 IN VM_CONTEXT *VmPtr,
3974 IN UINT64 Op1,
3975 IN UINT64 Op2
3976 )
3977{
3978 if ((*VmPtr->Ip & DATAMANIP_M_64) != 0) {
3979 return RShiftU64 (Op1, (UINTN)Op2);
3980 } else {
3981 return (UINT64)((UINT32)Op1 >> (UINT32)Op2);
3982 }
3983}
3984
3998UINT64
4000 IN VM_CONTEXT *VmPtr,
4001 IN UINT64 Op1,
4002 IN UINT64 Op2
4003 )
4004{
4005 if ((*VmPtr->Ip & DATAMANIP_M_64) != 0) {
4006 return ARShiftU64 (Op1, (UINTN)Op2);
4007 } else {
4008 return (UINT64)((INT64)((INT32)Op1 >> (UINT32)Op2));
4009 }
4010}
4011
4025UINT64
4027 IN VM_CONTEXT *VmPtr,
4028 IN UINT64 Op1,
4029 IN UINT64 Op2
4030 )
4031{
4032 INT8 Data8;
4033 INT64 Data64;
4034
4035 //
4036 // Convert to byte, then return as 64-bit signed value to let compiler
4037 // sign-extend the value
4038 //
4039 Data8 = (INT8)Op2;
4040 Data64 = (INT64)Data8;
4041
4042 return (UINT64)Data64;
4043}
4044
4058UINT64
4060 IN VM_CONTEXT *VmPtr,
4061 IN UINT64 Op1,
4062 IN UINT64 Op2
4063 )
4064{
4065 INT16 Data16;
4066 INT64 Data64;
4067
4068 //
4069 // Convert to word, then return as 64-bit signed value to let compiler
4070 // sign-extend the value
4071 //
4072 Data16 = (INT16)Op2;
4073 Data64 = (INT64)Data16;
4074
4075 return (UINT64)Data64;
4076}
4077
4078//
4079// Execute the EBC EXTNDD instruction.
4080//
4081// Format: EXTNDD {@}Rx, {@}Ry [Index16|Immed16]
4082// EXTNDD Dest, Source
4083//
4084// Operation: Dest <- SignExtended((DWORD)Source))
4085//
4086
4100UINT64
4102 IN VM_CONTEXT *VmPtr,
4103 IN UINT64 Op1,
4104 IN UINT64 Op2
4105 )
4106{
4107 INT32 Data32;
4108 INT64 Data64;
4109
4110 //
4111 // Convert to 32-bit value, then return as 64-bit signed value to let compiler
4112 // sign-extend the value
4113 //
4114 Data32 = (INT32)Op2;
4115 Data64 = (INT64)Data32;
4116
4117 return (UINT64)Data64;
4118}
4119
4139 IN VM_CONTEXT *VmPtr
4140 )
4141{
4142 //
4143 // Just call the data manipulation function with a flag indicating this
4144 // is a signed operation.
4145 //
4146 return ExecuteDataManip (VmPtr, TRUE);
4147}
4148
4168 IN VM_CONTEXT *VmPtr
4169 )
4170{
4171 //
4172 // Just call the data manipulation function with a flag indicating this
4173 // is not a signed operation.
4174 //
4175 return ExecuteDataManip (VmPtr, FALSE);
4176}
4177
4198 IN VM_CONTEXT *VmPtr,
4199 IN BOOLEAN IsSignedOp
4200 )
4201{
4202 UINT8 Opcode;
4203 INT16 Index16;
4204 UINT8 Operands;
4205 UINT8 Size;
4206 UINT64 Op1;
4207 UINT64 Op2;
4208 INTN DataManipDispatchTableIndex;
4209
4210 //
4211 // Get opcode and operands
4212 //
4213 Opcode = GETOPCODE (VmPtr);
4214 Operands = GETOPERANDS (VmPtr);
4215
4216 //
4217 // Determine if we have immediate data by the opcode
4218 //
4219 if ((Opcode & DATAMANIP_M_IMMDATA) != 0) {
4220 //
4221 // Index16 if Ry is indirect, or Immed16 if Ry direct.
4222 //
4223 if (OPERAND2_INDIRECT (Operands)) {
4224 Index16 = VmReadIndex16 (VmPtr, 2);
4225 } else {
4226 Index16 = VmReadImmed16 (VmPtr, 2);
4227 }
4228
4229 Size = 4;
4230 } else {
4231 Index16 = 0;
4232 Size = 2;
4233 }
4234
4235 //
4236 // Now get operand2 (source). It's of format {@}R2 {Index16|Immed16}
4237 //
4238 Op2 = (UINT64)VmPtr->Gpr[OPERAND2_REGNUM (Operands)] + Index16;
4239 if (OPERAND2_INDIRECT (Operands)) {
4240 //
4241 // Indirect form: @R2 Index16. Fetch as 32- or 64-bit data
4242 //
4243 if ((Opcode & DATAMANIP_M_64) != 0) {
4244 Op2 = VmReadMem64 (VmPtr, (UINTN)Op2);
4245 } else {
4246 //
4247 // Read as signed value where appropriate.
4248 //
4249 if (IsSignedOp) {
4250 Op2 = (UINT64)(INT64)((INT32)VmReadMem32 (VmPtr, (UINTN)Op2));
4251 } else {
4252 Op2 = (UINT64)VmReadMem32 (VmPtr, (UINTN)Op2);
4253 }
4254 }
4255 } else {
4256 if ((Opcode & DATAMANIP_M_64) == 0) {
4257 if (IsSignedOp) {
4258 Op2 = (UINT64)(INT64)((INT32)Op2);
4259 } else {
4260 Op2 = (UINT64)((UINT32)Op2);
4261 }
4262 }
4263 }
4264
4265 //
4266 // Get operand1 (destination and sometimes also an actual operand)
4267 // of form {@}R1
4268 //
4269 Op1 = (UINT64)VmPtr->Gpr[OPERAND1_REGNUM (Operands)];
4270 if (OPERAND1_INDIRECT (Operands)) {
4271 if ((Opcode & DATAMANIP_M_64) != 0) {
4272 Op1 = VmReadMem64 (VmPtr, (UINTN)Op1);
4273 } else {
4274 if (IsSignedOp) {
4275 Op1 = (UINT64)(INT64)((INT32)VmReadMem32 (VmPtr, (UINTN)Op1));
4276 } else {
4277 Op1 = (UINT64)VmReadMem32 (VmPtr, (UINTN)Op1);
4278 }
4279 }
4280 } else {
4281 if ((Opcode & DATAMANIP_M_64) == 0) {
4282 if (IsSignedOp) {
4283 Op1 = (UINT64)(INT64)((INT32)Op1);
4284 } else {
4285 Op1 = (UINT64)((UINT32)Op1);
4286 }
4287 }
4288 }
4289
4290 //
4291 // Dispatch to the computation function
4292 //
4293 DataManipDispatchTableIndex = (Opcode & OPCODE_M_OPCODE) - OPCODE_NOT;
4294 if ((DataManipDispatchTableIndex < 0) ||
4295 (DataManipDispatchTableIndex >= ARRAY_SIZE (mDataManipDispatchTable)))
4296 {
4299 EXCEPTION_FLAG_ERROR,
4300 VmPtr
4301 );
4302 //
4303 // Advance and return
4304 //
4305 VmPtr->Ip += Size;
4306 return EFI_UNSUPPORTED;
4307 } else {
4308 Op2 = mDataManipDispatchTable[DataManipDispatchTableIndex](VmPtr, Op1, Op2);
4309 }
4310
4311 //
4312 // Write back the result.
4313 //
4314 if (OPERAND1_INDIRECT (Operands)) {
4315 Op1 = (UINT64)VmPtr->Gpr[OPERAND1_REGNUM (Operands)];
4316 if ((Opcode & DATAMANIP_M_64) != 0) {
4317 VmWriteMem64 (VmPtr, (UINTN)Op1, Op2);
4318 } else {
4319 VmWriteMem32 (VmPtr, (UINTN)Op1, (UINT32)Op2);
4320 }
4321 } else {
4322 //
4323 // Storage back to a register. Write back, clearing upper bits (as per
4324 // the specification) if 32-bit operation.
4325 //
4326 VmPtr->Gpr[OPERAND1_REGNUM (Operands)] = Op2;
4327 if ((Opcode & DATAMANIP_M_64) == 0) {
4328 VmPtr->Gpr[OPERAND1_REGNUM (Operands)] &= 0xFFFFFFFF;
4329 }
4330 }
4331
4332 //
4333 // Advance the instruction pointer
4334 //
4335 VmPtr->Ip += Size;
4336 return EFI_SUCCESS;
4337}
4338
4353 IN VM_CONTEXT *VmPtr
4354 )
4355{
4356 UINT8 Operands;
4357
4358 //
4359 // Get the operands
4360 //
4361 Operands = GETOPERANDS (VmPtr);
4362
4363 //
4364 // Do the operation
4365 //
4366 switch (OPERAND1_REGNUM (Operands)) {
4367 //
4368 // Set flags
4369 //
4370 case 0:
4371 //
4372 // Spec states that this instruction will not modify reserved bits in
4373 // the flags register.
4374 //
4375 VmPtr->Flags = (VmPtr->Flags &~VMFLAGS_ALL_VALID) | (VmPtr->Gpr[OPERAND2_REGNUM (Operands)] & VMFLAGS_ALL_VALID);
4376 break;
4377
4378 default:
4381 EXCEPTION_FLAG_WARNING,
4382 VmPtr
4383 );
4384 VmPtr->Ip += 2;
4385 return EFI_UNSUPPORTED;
4386 }
4387
4388 VmPtr->Ip += 2;
4389 return EFI_SUCCESS;
4390}
4391
4406 IN VM_CONTEXT *VmPtr
4407 )
4408{
4409 UINT8 Operands;
4410
4411 //
4412 // Get the operands
4413 //
4414 Operands = GETOPERANDS (VmPtr);
4415
4416 //
4417 // Do the operation
4418 //
4419 switch (OPERAND2_REGNUM (Operands)) {
4420 //
4421 // Get flags
4422 //
4423 case 0:
4424 //
4425 // Retrieve the value in the flags register, then clear reserved bits
4426 //
4427 VmPtr->Gpr[OPERAND1_REGNUM (Operands)] = (UINT64)(VmPtr->Flags & VMFLAGS_ALL_VALID);
4428 break;
4429
4430 //
4431 // Get IP -- address of following instruction
4432 //
4433 case 1:
4434 VmPtr->Gpr[OPERAND1_REGNUM (Operands)] = (UINT64)(UINTN)VmPtr->Ip + 2;
4435 break;
4436
4437 default:
4440 EXCEPTION_FLAG_WARNING,
4441 VmPtr
4442 );
4443 VmPtr->Ip += 2;
4444 return EFI_UNSUPPORTED;
4445 break;
4446 }
4447
4448 VmPtr->Ip += 2;
4449 return EFI_SUCCESS;
4450}
4451
4474INT16
4476 IN VM_CONTEXT *VmPtr,
4477 IN UINT32 CodeOffset
4478 )
4479{
4480 UINT16 Index;
4481 INT16 Offset;
4482 INT16 ConstUnits;
4483 INT16 NaturalUnits;
4484 INT16 NBits;
4485 INT16 Mask;
4486
4487 //
4488 // First read the index from the code stream
4489 //
4490 Index = VmReadCode16 (VmPtr, CodeOffset);
4491
4492 //
4493 // Get the mask for NaturalUnits. First get the number of bits from the index.
4494 //
4495 NBits = (INT16)((Index & 0x7000) >> 12);
4496
4497 //
4498 // Scale it for 16-bit indexes
4499 //
4500 NBits *= 2;
4501
4502 //
4503 // Now using the number of bits, create a mask.
4504 //
4505 Mask = (INT16)((INT16) ~0 << NBits);
4506
4507 //
4508 // Now using the mask, extract NaturalUnits from the lower bits of the index.
4509 //
4510 NaturalUnits = (INT16)(Index &~Mask);
4511
4512 //
4513 // Now compute ConstUnits
4514 //
4515 ConstUnits = (INT16)(((Index &~0xF000) & Mask) >> NBits);
4516
4517 Offset = (INT16)(NaturalUnits * sizeof (UINTN) + ConstUnits);
4518
4519 //
4520 // Now set the sign
4521 //
4522 if ((Index & 0x8000) != 0) {
4523 //
4524 // Do it the hard way to work around a bogus compiler warning
4525 //
4526 // Offset = -1 * Offset;
4527 //
4528 Offset = (INT16)((INT32)Offset * -1);
4529 }
4530
4531 return Offset;
4532}
4533
4544INT32
4546 IN VM_CONTEXT *VmPtr,
4547 IN UINT32 CodeOffset
4548 )
4549{
4550 UINT32 Index;
4551 INT32 Offset;
4552 INT32 ConstUnits;
4553 INT32 NaturalUnits;
4554 INT32 NBits;
4555 INT32 Mask;
4556
4557 Index = VmReadImmed32 (VmPtr, CodeOffset);
4558
4559 //
4560 // Get the mask for NaturalUnits. First get the number of bits from the index.
4561 //
4562 NBits = (Index & 0x70000000) >> 28;
4563
4564 //
4565 // Scale it for 32-bit indexes
4566 //
4567 NBits *= 4;
4568
4569 //
4570 // Now using the number of bits, create a mask.
4571 //
4572 Mask = (INT32) ~0 << NBits;
4573
4574 //
4575 // Now using the mask, extract NaturalUnits from the lower bits of the index.
4576 //
4577 NaturalUnits = Index &~Mask;
4578
4579 //
4580 // Now compute ConstUnits
4581 //
4582 ConstUnits = ((Index &~0xF0000000) & Mask) >> NBits;
4583
4584 Offset = NaturalUnits * sizeof (UINTN) + ConstUnits;
4585
4586 //
4587 // Now set the sign
4588 //
4589 if ((Index & 0x80000000) != 0) {
4590 Offset = Offset * -1;
4591 }
4592
4593 return Offset;
4594}
4595
4606INT64
4608 IN VM_CONTEXT *VmPtr,
4609 IN UINT32 CodeOffset
4610 )
4611{
4612 UINT64 Index;
4613 INT64 Offset;
4614 INT64 ConstUnits;
4615 INT64 NaturalUnits;
4616 INT64 NBits;
4617 INT64 Mask;
4618
4619 Index = VmReadCode64 (VmPtr, CodeOffset);
4620
4621 //
4622 // Get the mask for NaturalUnits. First get the number of bits from the index.
4623 //
4624 NBits = RShiftU64 ((Index & 0x7000000000000000ULL), 60);
4625
4626 //
4627 // Scale it for 64-bit indexes (multiply by 8 by shifting left 3)
4628 //
4629 NBits = LShiftU64 ((UINT64)NBits, 3);
4630
4631 //
4632 // Now using the number of bits, create a mask.
4633 //
4634 Mask = (LShiftU64 ((UINT64) ~0, (UINTN)NBits));
4635
4636 //
4637 // Now using the mask, extract NaturalUnits from the lower bits of the index.
4638 //
4639 NaturalUnits = Index &~Mask;
4640
4641 //
4642 // Now compute ConstUnits
4643 //
4644 ConstUnits = ARShiftU64 (((Index &~0xF000000000000000ULL) & Mask), (UINTN)NBits);
4645
4646 Offset = MultU64x64 ((UINT64)NaturalUnits, sizeof (UINTN)) + ConstUnits;
4647
4648 //
4649 // Now set the sign
4650 //
4651 if ((Index & 0x8000000000000000ULL) != 0) {
4652 Offset = MultS64x64 (Offset, -1);
4653 }
4654
4655 return Offset;
4656}
4657
4683 IN VM_CONTEXT *VmPtr,
4684 IN UINTN Addr,
4685 IN UINT8 Data
4686 )
4687{
4688 //
4689 // Convert the address if it's in the stack gap
4690 //
4691 Addr = ConvertStackAddr (VmPtr, Addr);
4692 *(UINT8 *)Addr = Data;
4693 return EFI_SUCCESS;
4694}
4695
4721 IN VM_CONTEXT *VmPtr,
4722 IN UINTN Addr,
4723 IN UINT16 Data
4724 )
4725{
4726 EFI_STATUS Status;
4727
4728 //
4729 // Convert the address if it's in the stack gap
4730 //
4731 Addr = ConvertStackAddr (VmPtr, Addr);
4732
4733 //
4734 // Do a simple write if aligned
4735 //
4736 if (ADDRESS_IS_ALIGNED (Addr, sizeof (UINT16))) {
4737 *(UINT16 *)Addr = Data;
4738 } else {
4739 //
4740 // Write as two bytes
4741 //
4742 MemoryFence ();
4743 if ((Status = VmWriteMem8 (VmPtr, Addr, (UINT8)Data)) != EFI_SUCCESS) {
4744 return Status;
4745 }
4746
4747 MemoryFence ();
4748 if ((Status = VmWriteMem8 (VmPtr, Addr + 1, (UINT8)(Data >> 8))) != EFI_SUCCESS) {
4749 return Status;
4750 }
4751
4752 MemoryFence ();
4753 }
4754
4755 return EFI_SUCCESS;
4756}
4757
4783 IN VM_CONTEXT *VmPtr,
4784 IN UINTN Addr,
4785 IN UINT32 Data
4786 )
4787{
4788 EFI_STATUS Status;
4789
4790 //
4791 // Convert the address if it's in the stack gap
4792 //
4793 Addr = ConvertStackAddr (VmPtr, Addr);
4794
4795 //
4796 // Do a simple write if aligned
4797 //
4798 if (ADDRESS_IS_ALIGNED (Addr, sizeof (UINT32))) {
4799 *(UINT32 *)Addr = Data;
4800 } else {
4801 //
4802 // Write as two words
4803 //
4804 MemoryFence ();
4805 if ((Status = VmWriteMem16 (VmPtr, Addr, (UINT16)Data)) != EFI_SUCCESS) {
4806 return Status;
4807 }
4808
4809 MemoryFence ();
4810 if ((Status = VmWriteMem16 (VmPtr, Addr + sizeof (UINT16), (UINT16)(Data >> 16))) != EFI_SUCCESS) {
4811 return Status;
4812 }
4813
4814 MemoryFence ();
4815 }
4816
4817 return EFI_SUCCESS;
4818}
4819
4845 IN VM_CONTEXT *VmPtr,
4846 IN UINTN Addr,
4847 IN UINT64 Data
4848 )
4849{
4850 EFI_STATUS Status;
4851
4852 //
4853 // Convert the address if it's in the stack gap
4854 //
4855 Addr = ConvertStackAddr (VmPtr, Addr);
4856
4857 //
4858 // Do a simple write if aligned
4859 //
4860 if (ADDRESS_IS_ALIGNED (Addr, sizeof (UINT64))) {
4861 *(UINT64 *)Addr = Data;
4862 } else {
4863 //
4864 // Write as two 32-bit words
4865 //
4866 MemoryFence ();
4867 if ((Status = VmWriteMem32 (VmPtr, Addr, (UINT32)Data)) != EFI_SUCCESS) {
4868 return Status;
4869 }
4870
4871 MemoryFence ();
4872 if ((Status = VmWriteMem32 (VmPtr, Addr + sizeof (UINT32), (UINT32)RShiftU64 (Data, 32))) != EFI_SUCCESS) {
4873 return Status;
4874 }
4875
4876 MemoryFence ();
4877 }
4878
4879 return EFI_SUCCESS;
4880}
4881
4907 IN VM_CONTEXT *VmPtr,
4908 IN UINTN Addr,
4909 IN UINTN Data
4910 )
4911{
4912 EFI_STATUS Status;
4913 UINTN Index;
4914
4915 Status = EFI_SUCCESS;
4916
4917 //
4918 // Convert the address if it's in the stack gap
4919 //
4920 Addr = ConvertStackAddr (VmPtr, Addr);
4921
4922 //
4923 // Do a simple write if aligned
4924 //
4925 if (ADDRESS_IS_ALIGNED (Addr, sizeof (UINTN))) {
4926 *(UINTN *)Addr = Data;
4927 } else {
4928 for (Index = 0; Index < sizeof (UINTN) / sizeof (UINT32); Index++) {
4929 MemoryFence ();
4930 Status = VmWriteMem32 (VmPtr, Addr + Index * sizeof (UINT32), (UINT32)Data);
4931 MemoryFence ();
4932 Data = (UINTN)RShiftU64 ((UINT64)Data, 32);
4933 }
4934 }
4935
4936 return Status;
4937}
4938
4953INT8
4955 IN VM_CONTEXT *VmPtr,
4956 IN UINT32 Offset
4957 )
4958{
4959 //
4960 // Simply return the data in flat memory space
4961 //
4962 return *(INT8 *)(VmPtr->Ip + Offset);
4963}
4964
4979INT16
4981 IN VM_CONTEXT *VmPtr,
4982 IN UINT32 Offset
4983 )
4984{
4985 //
4986 // Read direct if aligned
4987 //
4988 if (ADDRESS_IS_ALIGNED ((UINTN)VmPtr->Ip + Offset, sizeof (INT16))) {
4989 return *(INT16 *)(VmPtr->Ip + Offset);
4990 } else {
4991 //
4992 // All code word reads should be aligned
4993 //
4995 EXCEPT_EBC_ALIGNMENT_CHECK,
4996 EXCEPTION_FLAG_WARNING,
4997 VmPtr
4998 );
4999 }
5000
5001 //
5002 // Return unaligned data
5003 //
5004 return (INT16)(*(UINT8 *)(VmPtr->Ip + Offset) + (*(UINT8 *)(VmPtr->Ip + Offset + 1) << 8));
5005}
5006
5021INT32
5023 IN VM_CONTEXT *VmPtr,
5024 IN UINT32 Offset
5025 )
5026{
5027 UINT32 Data;
5028
5029 //
5030 // Read direct if aligned
5031 //
5032 if (ADDRESS_IS_ALIGNED ((UINTN)VmPtr->Ip + Offset, sizeof (UINT32))) {
5033 return *(INT32 *)(VmPtr->Ip + Offset);
5034 }
5035
5036 //
5037 // Return unaligned data
5038 //
5039 Data = (UINT32)VmReadCode16 (VmPtr, Offset);
5040 Data |= (UINT32)(VmReadCode16 (VmPtr, Offset + 2) << 16);
5041 return Data;
5042}
5043
5058INT64
5060 IN VM_CONTEXT *VmPtr,
5061 IN UINT32 Offset
5062 )
5063{
5064 UINT64 Data64;
5065 UINT32 Data32;
5066 UINT8 *Ptr;
5067
5068 //
5069 // Read direct if aligned
5070 //
5071 if (ADDRESS_IS_ALIGNED ((UINTN)VmPtr->Ip + Offset, sizeof (UINT64))) {
5072 return *(UINT64 *)(VmPtr->Ip + Offset);
5073 }
5074
5075 //
5076 // Return unaligned data.
5077 //
5078 Ptr = (UINT8 *)&Data64;
5079 Data32 = VmReadCode32 (VmPtr, Offset);
5080 *(UINT32 *)Ptr = Data32;
5081 Ptr += sizeof (Data32);
5082 Data32 = VmReadCode32 (VmPtr, Offset + sizeof (UINT32));
5083 *(UINT32 *)Ptr = Data32;
5084 return Data64;
5085}
5086
5099UINT16
5101 IN VM_CONTEXT *VmPtr,
5102 IN UINT32 Offset
5103 )
5104{
5105 //
5106 // Read direct if aligned
5107 //
5108 if (ADDRESS_IS_ALIGNED ((UINTN)VmPtr->Ip + Offset, sizeof (UINT16))) {
5109 return *(UINT16 *)(VmPtr->Ip + Offset);
5110 } else {
5111 //
5112 // All code word reads should be aligned
5113 //
5115 EXCEPT_EBC_ALIGNMENT_CHECK,
5116 EXCEPTION_FLAG_WARNING,
5117 VmPtr
5118 );
5119 }
5120
5121 //
5122 // Return unaligned data
5123 //
5124 return (UINT16)(*(UINT8 *)(VmPtr->Ip + Offset) + (*(UINT8 *)(VmPtr->Ip + Offset + 1) << 8));
5125}
5126
5139UINT32
5141 IN VM_CONTEXT *VmPtr,
5142 IN UINT32 Offset
5143 )
5144{
5145 UINT32 Data;
5146
5147 //
5148 // Read direct if aligned
5149 //
5150 if (ADDRESS_IS_ALIGNED ((UINTN)VmPtr->Ip + Offset, sizeof (UINT32))) {
5151 return *(UINT32 *)(VmPtr->Ip + Offset);
5152 }
5153
5154 //
5155 // Return unaligned data
5156 //
5157 Data = (UINT32)VmReadCode16 (VmPtr, Offset);
5158 Data |= (VmReadCode16 (VmPtr, Offset + 2) << 16);
5159 return Data;
5160}
5161
5174UINT64
5176 IN VM_CONTEXT *VmPtr,
5177 IN UINT32 Offset
5178 )
5179{
5180 UINT64 Data64;
5181 UINT32 Data32;
5182 UINT8 *Ptr;
5183
5184 //
5185 // Read direct if aligned
5186 //
5187 if (ADDRESS_IS_ALIGNED ((UINTN)VmPtr->Ip + Offset, sizeof (UINT64))) {
5188 return *(UINT64 *)(VmPtr->Ip + Offset);
5189 }
5190
5191 //
5192 // Return unaligned data.
5193 //
5194 Ptr = (UINT8 *)&Data64;
5195 Data32 = VmReadCode32 (VmPtr, Offset);
5196 *(UINT32 *)Ptr = Data32;
5197 Ptr += sizeof (Data32);
5198 Data32 = VmReadCode32 (VmPtr, Offset + sizeof (UINT32));
5199 *(UINT32 *)Ptr = Data32;
5200 return Data64;
5201}
5202
5212UINT8
5214 IN VM_CONTEXT *VmPtr,
5215 IN UINTN Addr
5216 )
5217{
5218 //
5219 // Convert the address if it's in the stack gap
5220 //
5221 Addr = ConvertStackAddr (VmPtr, Addr);
5222 //
5223 // Simply return the data in flat memory space
5224 //
5225 return *(UINT8 *)Addr;
5226}
5227
5237UINT16
5239 IN VM_CONTEXT *VmPtr,
5240 IN UINTN Addr
5241 )
5242{
5243 //
5244 // Convert the address if it's in the stack gap
5245 //
5246 Addr = ConvertStackAddr (VmPtr, Addr);
5247 //
5248 // Read direct if aligned
5249 //
5250 if (ADDRESS_IS_ALIGNED (Addr, sizeof (UINT16))) {
5251 return *(UINT16 *)Addr;
5252 }
5253
5254 //
5255 // Return unaligned data
5256 //
5257 return (UINT16)(*(UINT8 *)Addr + (*(UINT8 *)(Addr + 1) << 8));
5258}
5259
5269UINT32
5271 IN VM_CONTEXT *VmPtr,
5272 IN UINTN Addr
5273 )
5274{
5275 UINT32 Data;
5276
5277 //
5278 // Convert the address if it's in the stack gap
5279 //
5280 Addr = ConvertStackAddr (VmPtr, Addr);
5281 //
5282 // Read direct if aligned
5283 //
5284 if (ADDRESS_IS_ALIGNED (Addr, sizeof (UINT32))) {
5285 return *(UINT32 *)Addr;
5286 }
5287
5288 //
5289 // Return unaligned data
5290 //
5291 Data = (UINT32)VmReadMem16 (VmPtr, Addr);
5292 Data |= (VmReadMem16 (VmPtr, Addr + 2) << 16);
5293 return Data;
5294}
5295
5305UINT64
5307 IN VM_CONTEXT *VmPtr,
5308 IN UINTN Addr
5309 )
5310{
5311 UINT64 Data;
5312 UINT32 Data32;
5313
5314 //
5315 // Convert the address if it's in the stack gap
5316 //
5317 Addr = ConvertStackAddr (VmPtr, Addr);
5318
5319 //
5320 // Read direct if aligned
5321 //
5322 if (ADDRESS_IS_ALIGNED (Addr, sizeof (UINT64))) {
5323 return *(UINT64 *)Addr;
5324 }
5325
5326 //
5327 // Return unaligned data. Assume little endian.
5328 //
5329 Data32 = VmReadMem32 (VmPtr, Addr);
5330 Data = (UINT64)VmReadMem32 (VmPtr, Addr + sizeof (UINT32));
5331 Data = LShiftU64 (Data, 32) | Data32;
5332 return Data;
5333}
5334
5354UINTN
5356 IN VM_CONTEXT *VmPtr,
5357 IN UINTN Addr
5358 )
5359{
5360 ASSERT (((Addr < VmPtr->LowStackTop) || (Addr > VmPtr->HighStackBottom)));
5361 return Addr;
5362}
5363
5373UINTN
5375 IN VM_CONTEXT *VmPtr,
5376 IN UINTN Addr
5377 )
5378{
5379 UINTN Data;
5380 volatile UINT32 Size;
5381 UINT8 *FromPtr;
5382 UINT8 *ToPtr;
5383
5384 //
5385 // Convert the address if it's in the stack gap
5386 //
5387 Addr = ConvertStackAddr (VmPtr, Addr);
5388 //
5389 // Read direct if aligned
5390 //
5391 if (ADDRESS_IS_ALIGNED (Addr, sizeof (UINTN))) {
5392 return *(UINTN *)Addr;
5393 }
5394
5395 //
5396 // Return unaligned data
5397 //
5398 Data = 0;
5399 FromPtr = (UINT8 *)Addr;
5400 ToPtr = (UINT8 *)&Data;
5401
5402 for (Size = 0; Size < sizeof (Data); Size++) {
5403 *ToPtr = *FromPtr;
5404 ToPtr++;
5405 FromPtr++;
5406 }
5407
5408 return Data;
5409}
5410
5417UINT64
5419 VOID
5420 )
5421{
5422 return (UINT64)(((VM_MAJOR_VERSION & 0xFFFF) << 16) | ((VM_MINOR_VERSION & 0xFFFF)));
5423}
VOID EbcLLCALLEX(IN VM_CONTEXT *VmPtr, IN UINTN FuncAddr, IN UINTN NewStackPointer, IN VOID *FramePtr, IN UINT8 Size)
Definition: EbcSupport.c:436
EFI_STATUS EbcCreateThunks(IN EFI_HANDLE ImageHandle, IN VOID *EbcEntryPoint, OUT VOID **Thunk, IN UINT32 Flags)
Definition: EbcSupport.c:362
UINT64 UINTN
INT64 INTN
UINT64 EFIAPI MultU64x64(IN UINT64 Multiplicand, IN UINT64 Multiplier)
Definition: MultU64x64.c:27
INT64 EFIAPI DivS64x64Remainder(IN INT64 Dividend, IN INT64 Divisor, OUT INT64 *Remainder OPTIONAL)
VOID EFIAPI MemoryFence(VOID)
Definition: CpuBreakpoint.c:42
UINT64 EFIAPI RShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: RShiftU64.c:28
UINT64 EFIAPI ARShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: ARShiftU64.c:28
UINT64 EFIAPI DivU64x64Remainder(IN UINT64 Dividend, IN UINT64 Divisor, OUT UINT64 *Remainder OPTIONAL)
INT64 EFIAPI MultS64x64(IN INT64 Multiplicand, IN INT64 Multiplier)
Definition: MultS64x64.c:27
VOID EFIAPI CpuBreakpoint(VOID)
Definition: CpuBreakpoint.c:26
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: LShiftU64.c:28
EFI_STATUS EbcDebugSignalException(IN EFI_EXCEPTION_TYPE ExceptionType, IN EXCEPTION_FLAGS ExceptionFlags, IN VM_CONTEXT *VmPtr)
Definition: EbcInt.c:860
EFI_STATUS ExecutePOPn(IN VM_CONTEXT *VmPtr)
Definition: EbcExecute.c:2852
UINT64 ExecuteDIV(IN VM_CONTEXT *VmPtr, IN UINT64 Op1, IN UINT64 Op2)
Definition: EbcExecute.c:3714
UINT64 ExecuteMULU(IN VM_CONTEXT *VmPtr, IN UINT64 Op1, IN UINT64 Op2)
Definition: EbcExecute.c:3687
EFI_STATUS ExecuteMOVIn(IN VM_CONTEXT *VmPtr)
Definition: EbcExecute.c:2320
EFI_STATUS ExecuteJMP8(IN VM_CONTEXT *VmPtr)
Definition: EbcExecute.c:2135
UINT64 ExecuteMODU(IN VM_CONTEXT *VmPtr, IN UINT64 Op1, IN UINT64 Op2)
Definition: EbcExecute.c:3838
UINT64 VmReadCode64(IN VM_CONTEXT *VmPtr, IN UINT32 Offset)
Definition: EbcExecute.c:5175
INT32 VmReadIndex32(IN VM_CONTEXT *VmPtr, IN UINT32 CodeOffset)
Definition: EbcExecute.c:4545
UINT64 ExecuteEXTNDD(IN VM_CONTEXT *VmPtr, IN UINT64 Op1, IN UINT64 Op2)
Definition: EbcExecute.c:4101
UINT16 VmReadMem16(IN VM_CONTEXT *VmPtr, IN UINTN Addr)
Definition: EbcExecute.c:5238
UINT64 ExecuteSHR(IN VM_CONTEXT *VmPtr, IN UINT64 Op1, IN UINT64 Op2)
Definition: EbcExecute.c:3972
UINT64 ExecuteXOR(IN VM_CONTEXT *VmPtr, IN UINT64 Op1, IN UINT64 Op2)
Definition: EbcExecute.c:3922
INT64 VmReadIndex64(IN VM_CONTEXT *VmPtr, IN UINT32 CodeOffset)
Definition: EbcExecute.c:4607
EFI_STATUS ExecuteCMP(IN VM_CONTEXT *VmPtr)
Definition: EbcExecute.c:3196
UINT64 ExecuteADD(IN VM_CONTEXT *VmPtr, IN UINT64 Op1, IN UINT64 Op2)
Definition: EbcExecute.c:3610
UINT64 VmReadMem64(IN VM_CONTEXT *VmPtr, IN UINTN Addr)
Definition: EbcExecute.c:5306
INT8 VmReadImmed8(IN VM_CONTEXT *VmPtr, IN UINT32 Offset)
Definition: EbcExecute.c:4954
UINT64 ExecuteDIVU(IN VM_CONTEXT *VmPtr, IN UINT64 Op1, IN UINT64 Op2)
Definition: EbcExecute.c:3756
EFI_STATUS ExecuteMOVsnw(IN VM_CONTEXT *VmPtr)
Definition: EbcExecute.c:2532
INT32 VmReadImmed32(IN VM_CONTEXT *VmPtr, IN UINT32 Offset)
Definition: EbcExecute.c:5022
EFI_STATUS ExecuteMOVsnd(IN VM_CONTEXT *VmPtr)
Definition: EbcExecute.c:2627
UINT16 VmReadCode16(IN VM_CONTEXT *VmPtr, IN UINT32 Offset)
Definition: EbcExecute.c:5100
EFI_STATUS ExecutePOP(IN VM_CONTEXT *VmPtr)
Definition: EbcExecute.c:2911
EFI_STATUS ExecuteCMPI(IN VM_CONTEXT *VmPtr)
Definition: EbcExecute.c:3370
EFI_STATUS ExecuteDataManip(IN VM_CONTEXT *VmPtr, IN BOOLEAN IsSignedOp)
Definition: EbcExecute.c:4197
EFI_STATUS VmWriteMem32(IN VM_CONTEXT *VmPtr, IN UINTN Addr, IN UINT32 Data)
Definition: EbcExecute.c:4782
EFI_STATUS EbcExecute(IN VM_CONTEXT *VmPtr)
Definition: EbcExecute.c:1418
EFI_STATUS ExecuteCALL(IN VM_CONTEXT *VmPtr)
Definition: EbcExecute.c:2995
UINT64 ExecuteSUB(IN VM_CONTEXT *VmPtr, IN UINT64 Op1, IN UINT64 Op2)
Definition: EbcExecute.c:3633
UINT32 VmReadCode32(IN VM_CONTEXT *VmPtr, IN UINT32 Offset)
Definition: EbcExecute.c:5140
EFI_STATUS ExecutePUSHn(IN VM_CONTEXT *VmPtr)
Definition: EbcExecute.c:2714
UINT64 ExecuteOR(IN VM_CONTEXT *VmPtr, IN UINT64 Op1, IN UINT64 Op2)
Definition: EbcExecute.c:3899
UINT64 ExecuteASHR(IN VM_CONTEXT *VmPtr, IN UINT64 Op1, IN UINT64 Op2)
Definition: EbcExecute.c:3999
UINT64 ExecuteEXTNDB(IN VM_CONTEXT *VmPtr, IN UINT64 Op1, IN UINT64 Op2)
Definition: EbcExecute.c:4026
EFI_STATUS ExecuteMOVI(IN VM_CONTEXT *VmPtr)
Definition: EbcExecute.c:2199
UINT64 ExecuteMUL(IN VM_CONTEXT *VmPtr, IN UINT64 Op1, IN UINT64 Op2)
Definition: EbcExecute.c:3660
EFI_STATUS ExecuteSTORESP(IN VM_CONTEXT *VmPtr)
Definition: EbcExecute.c:4405
EFI_STATUS VmWriteMem16(IN VM_CONTEXT *VmPtr, IN UINTN Addr, IN UINT16 Data)
Definition: EbcExecute.c:4720
EFI_STATUS ExecuteRET(IN VM_CONTEXT *VmPtr)
Definition: EbcExecute.c:3144
INT16 VmReadIndex16(IN VM_CONTEXT *VmPtr, IN UINT32 CodeOffset)
Definition: EbcExecute.c:4475
INT16 VmReadImmed16(IN VM_CONTEXT *VmPtr, IN UINT32 Offset)
Definition: EbcExecute.c:4980
UINT64 ExecuteAND(IN VM_CONTEXT *VmPtr, IN UINT64 Op1, IN UINT64 Op2)
Definition: EbcExecute.c:3876
UINT64 ExecuteMOD(IN VM_CONTEXT *VmPtr, IN UINT64 Op1, IN UINT64 Op2)
Definition: EbcExecute.c:3800
UINTN ConvertStackAddr(IN VM_CONTEXT *VmPtr, IN UINTN Addr)
Definition: EbcExecute.c:5355
UINT64 ExecuteNOT(IN VM_CONTEXT *VmPtr, IN UINT64 Op1, IN UINT64 Op2)
Definition: EbcExecute.c:3564
UINT64 GetVmVersion(VOID)
Definition: EbcExecute.c:5418
INT64 VmReadImmed64(IN VM_CONTEXT *VmPtr, IN UINT32 Offset)
Definition: EbcExecute.c:5059
UINTN VmReadMemN(IN VM_CONTEXT *VmPtr, IN UINTN Addr)
Definition: EbcExecute.c:5374
UINT64 ExecuteSHL(IN VM_CONTEXT *VmPtr, IN UINT64 Op1, IN UINT64 Op2)
Definition: EbcExecute.c:3945
EFI_STATUS VmWriteMemN(IN VM_CONTEXT *VmPtr, IN UINTN Addr, IN UINTN Data)
Definition: EbcExecute.c:4906
EFI_STATUS ExecuteBREAK(IN VM_CONTEXT *VmPtr)
Definition: EbcExecute.c:1828
EFI_STATUS ExecutePUSH(IN VM_CONTEXT *VmPtr)
Definition: EbcExecute.c:2774
EFI_STATUS ExecuteSignedDataManip(IN VM_CONTEXT *VmPtr)
Definition: EbcExecute.c:4138
UINT64 ExecuteEXTNDW(IN VM_CONTEXT *VmPtr, IN UINT64 Op1, IN UINT64 Op2)
Definition: EbcExecute.c:4059
EFI_STATUS ExecuteMOVREL(IN VM_CONTEXT *VmPtr)
Definition: EbcExecute.c:2424
EFI_STATUS ExecuteMOVxx(IN VM_CONTEXT *VmPtr)
Definition: EbcExecute.c:1554
EFI_STATUS ExecuteJMP(IN VM_CONTEXT *VmPtr)
Definition: EbcExecute.c:1958
UINT32 VmReadMem32(IN VM_CONTEXT *VmPtr, IN UINTN Addr)
Definition: EbcExecute.c:5270
EFI_STATUS EFIAPI EbcExecuteInstructions(IN EFI_EBC_VM_TEST_PROTOCOL *This, IN VM_CONTEXT *VmPtr, IN OUT UINTN *InstructionCount)
Definition: EbcExecute.c:1360
EFI_STATUS ExecuteUnsignedDataManip(IN VM_CONTEXT *VmPtr)
Definition: EbcExecute.c:4167
UINT8 VmReadMem8(IN VM_CONTEXT *VmPtr, IN UINTN Addr)
Definition: EbcExecute.c:5213
EFI_STATUS VmWriteMem8(IN VM_CONTEXT *VmPtr, IN UINTN Addr, IN UINT8 Data)
Definition: EbcExecute.c:4682
UINT64 ExecuteNEG(IN VM_CONTEXT *VmPtr, IN UINT64 Op1, IN UINT64 Op2)
Definition: EbcExecute.c:3587
EFI_STATUS VmWriteMem64(IN VM_CONTEXT *VmPtr, IN UINTN Addr, IN UINT64 Data)
Definition: EbcExecute.c:4844
EFI_STATUS ExecuteLOADSP(IN VM_CONTEXT *VmPtr)
Definition: EbcExecute.c:4352
UINT8 * VMIP
Definition: EbcVmTest.h:78
VOID EbcDebuggerHookJMPStart(IN VM_CONTEXT *VmPtr)
Definition: EdbHook.c:795
VOID EbcDebuggerHookExecuteStart(IN VM_CONTEXT *VmPtr)
Definition: EdbHook.c:549
VOID EbcDebuggerHookCALLEnd(IN VM_CONTEXT *VmPtr)
Definition: EdbHook.c:679
VOID EbcDebuggerHookCALLStart(IN VM_CONTEXT *VmPtr)
Definition: EdbHook.c:658
VOID EbcDebuggerHookCALLEXStart(IN VM_CONTEXT *VmPtr)
Definition: EdbHook.c:720
VOID EbcDebuggerHookRETEnd(IN VM_CONTEXT *VmPtr)
Definition: EdbHook.c:778
VOID EbcDebuggerHookCALLEXEnd(IN VM_CONTEXT *VmPtr)
Definition: EdbHook.c:740
VOID EbcDebuggerHookJMPEnd(IN VM_CONTEXT *VmPtr)
Definition: EdbHook.c:812
VOID EbcDebuggerHookJMP8Start(IN VM_CONTEXT *VmPtr)
Definition: EdbHook.c:829
VOID EbcDebuggerHookExecuteEnd(IN VM_CONTEXT *VmPtr)
Definition: EdbHook.c:633
VOID EbcDebuggerHookRETStart(IN VM_CONTEXT *VmPtr)
Definition: EdbHook.c:759
VOID EbcDebuggerHookJMP8End(IN VM_CONTEXT *VmPtr)
Definition: EdbHook.c:846
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define ADDRESS_IS_ALIGNED(Address, Alignment)
Definition: Base.h:923
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define ARRAY_SIZE(Array)
Definition: Base.h:1393
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG_CODE_BEGIN()
Definition: DebugLib.h:564
#define DEBUG_CODE_END()
Definition: DebugLib.h:578
#define EXCEPT_EBC_UNDEFINED
Definition: DebugSupport.h:437
#define EXCEPT_EBC_BAD_BREAK
BREAK 0 or undefined BREAK.
Definition: DebugSupport.h:446
#define EXCEPT_EBC_INVALID_OPCODE
Opcode out of range.
Definition: DebugSupport.h:442
#define EXCEPT_EBC_STEP
Definition: DebugSupport.h:447
#define EXCEPT_EBC_INSTRUCTION_ENCODING
Malformed instruction.
Definition: DebugSupport.h:445
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS