- Timestamp:
- Apr 6, 2023 7:28:23 PM (18 months ago)
- Location:
- trunk
- Files:
-
- 2 added
- 7 edited
-
include/VBox/dis-armv8.h (modified) (2 diffs)
-
include/VBox/dis.h (modified) (1 diff)
-
include/VBox/disopcode-armv8.h (modified) (1 diff)
-
src/VBox/Disassembler/Disasm.cpp (modified) (1 diff)
-
src/VBox/Disassembler/DisasmCore-armv8.cpp (modified) (4 diffs)
-
src/VBox/Disassembler/DisasmFormatArmV8.cpp (added)
-
src/VBox/Disassembler/DisasmInternal-armv8.h (modified) (1 diff)
-
src/VBox/Disassembler/DisasmTables-armv8.cpp (added)
-
src/VBox/Disassembler/Makefile.kmk (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/dis-armv8.h
r99241 r99319 55 55 typedef struct DISOPPARAMARMV8 56 56 { 57 /** The register operand. */ 58 union 59 { 60 /** General register index (DISGREG_XXX), applicable if DISUSE_REG_GEN32 61 * or DISUSE_REG_GEN64 is set in fUse. */ 62 uint8_t idxGenReg; 63 } Reg; 64 /** Scale factor. */ 57 65 uint8_t uScale; 58 66 /** Parameter size. */ … … 67 75 /** Pointer to opcode parameter. */ 68 76 typedef const DISOPPARAMARMV8 *PCDISOPPARAMARMV8; 69 70 71 /** Parser callback.72 * @remark no DECLCALLBACK() here because it's considered to be internal and73 * there is no point in enforcing CDECL. */74 typedef size_t FNDISPARSEARMV8(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam, uint8_t cBitStart, uint8_t cBits);75 /** Pointer to a disassembler parser function. */76 typedef FNDISPARSEARMV8 *PFNDISPARSEARMV8;77 77 78 78 -
trunk/include/VBox/dis.h
r99241 r99319 552 552 DISDECL(size_t) DISFormatGasEx( PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser); 553 553 554 DISDECL(size_t) DISFormatArmV8( PCDISSTATE pDis, char *pszBuf, size_t cchBuf); 555 DISDECL(size_t) DISFormatArmV8Ex(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser); 556 554 557 /** @todo DISAnnotate(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, register 555 558 * reader, memory reader); */ -
trunk/include/VBox/disopcode-armv8.h
r99243 r99319 520 520 }; 521 521 522 523 /** @defgroup grp_dis_opparam Opcode parameters (DISOPCODE::fParam1, 524 * DISOPCODE::fParam2, DISOPCODE::fParam3) 525 * @ingroup grp_dis 526 * @{ 527 */ 528 529 enum OP_ARMV8_PARM 530 { 531 OP_ARMV8_PARM_NONE, 532 }; 533 534 535 /** Immediate (the instruction class gives the range of the immediate). */ 536 #define OP_ARMV8_PARM_Imm 1 537 522 538 /** @} */ 523 539 -
trunk/src/VBox/Disassembler/Disasm.cpp
r99241 r99319 586 586 if (RT_SUCCESS(rc) && pszOutput && cbOutput) 587 587 { 588 size_t cch = DISFormatYasmEx(pDis, pszOutput, cbOutput, 589 DIS_FMT_FLAGS_BYTES_LEFT | DIS_FMT_FLAGS_BYTES_BRACKETS | DIS_FMT_FLAGS_BYTES_SPACED 590 | DIS_FMT_FLAGS_RELATIVE_BRANCH | DIS_FMT_FLAGS_ADDR_LEFT, 591 NULL /*pfnGetSymbol*/, NULL /*pvUser*/); 588 size_t cch = 0; 589 590 switch (enmCpuMode) 591 { 592 case DISCPUMODE_16BIT: 593 case DISCPUMODE_32BIT: 594 case DISCPUMODE_64BIT: 595 #if defined(VBOX_DIS_WITH_X86_AMD64) 596 cch = DISFormatYasmEx(pDis, pszOutput, cbOutput, 597 DIS_FMT_FLAGS_BYTES_LEFT | DIS_FMT_FLAGS_BYTES_BRACKETS | DIS_FMT_FLAGS_BYTES_SPACED 598 | DIS_FMT_FLAGS_RELATIVE_BRANCH | DIS_FMT_FLAGS_ADDR_LEFT, 599 NULL /*pfnGetSymbol*/, NULL /*pvUser*/); 600 #else 601 AssertReleaseFailed(); /* Shouldn't ever get here (DISInstrEx() returning VERR_NOT_SUPPORTED). */ 602 #endif 603 break; 604 case DISCPUMODE_ARMV8_A64: 605 case DISCPUMODE_ARMV8_A32: 606 case DISCPUMODE_ARMV8_T32: 607 #if defined(VBOX_DIS_WITH_ARMV8) 608 cch = DISFormatArmV8Ex(pDis, pszOutput, cbOutput, 609 DIS_FMT_FLAGS_BYTES_LEFT | DIS_FMT_FLAGS_BYTES_BRACKETS | DIS_FMT_FLAGS_BYTES_SPACED 610 | DIS_FMT_FLAGS_RELATIVE_BRANCH | DIS_FMT_FLAGS_ADDR_LEFT, 611 NULL /*pfnGetSymbol*/, NULL /*pvUser*/); 612 #else 613 AssertReleaseFailed(); /* Shouldn't ever get here (DISInstrEx() returning VERR_NOT_SUPPORTED). */ 614 #endif 615 break; 616 default: 617 break; 618 } 619 592 620 if (cch + 2 <= cbOutput) 593 621 { -
trunk/src/VBox/Disassembler/DisasmCore-armv8.cpp
r99242 r99319 42 42 43 43 /********************************************************************************************************************************* 44 * Structures and Typedefs * 45 *********************************************************************************************************************************/ 46 47 /** Parser callback. 48 * @remark no DECLCALLBACK() here because it's considered to be internal and 49 * there is no point in enforcing CDECL. */ 50 typedef int FNDISPARSEARMV8(PDISSTATE pDis, uint32_t u32Insn, PCDISARMV8INSNCLASS pInsnClass, PDISOPPARAM pParam, PCDISARMV8INSNPARAM pInsnParm, bool f64Bit); 51 /** Pointer to a disassembler parser function. */ 52 typedef FNDISPARSEARMV8 *PFNDISPARSEARMV8; 53 54 55 /** Opcode decoder callback. 56 * @remark no DECLCALLBACK() here because it's considered to be internal and 57 * there is no point in enforcing CDECL. */ 58 typedef uint32_t FNDISDECODEARMV8(PDISSTATE pDis, uint32_t u32Insn, PCDISARMV8INSNCLASS pInsnClass); 59 /** Pointer to a disassembler parser function. */ 60 typedef FNDISDECODEARMV8 *PFNDISDECODEARMV8; 61 62 63 /********************************************************************************************************************************* 44 64 * Defined Constants And Macros * 45 65 *********************************************************************************************************************************/ … … 52 72 * @{ */ 53 73 static FNDISPARSEARMV8 disArmV8ParseIllegal; 74 static FNDISPARSEARMV8 disArmV8ParseImm; 75 static FNDISPARSEARMV8 disArmV8ParseImmRel; 76 static FNDISPARSEARMV8 disArmV8ParseImmAdr; 77 static FNDISPARSEARMV8 disArmV8ParseReg; 78 static FNDISPARSEARMV8 disArmV8ParseImmsImmrN; 79 static FNDISPARSEARMV8 disArmV8ParseHw; 80 static FNDISPARSEARMV8 disArmV8ParseCond; 54 81 /** @} */ 82 83 84 /** @name Decoders 85 * @{ */ 86 static FNDISDECODEARMV8 disArmV8DecodeIllegal; 87 /** @} */ 55 88 56 89 … … 59 92 *********************************************************************************************************************************/ 60 93 /** Parser opcode table for full disassembly. */ 61 static PFNDISPARSEARMV8 const g_apfnDisasm[ IDX_ParseMax] =94 static PFNDISPARSEARMV8 const g_apfnDisasm[kDisParmParseMax] = 62 95 { 63 96 disArmV8ParseIllegal, 97 disArmV8ParseImm, 98 disArmV8ParseImmRel, 99 disArmV8ParseImmAdr, 100 disArmV8ParseReg, 101 disArmV8ParseImmsImmrN, 102 disArmV8ParseHw, 103 disArmV8ParseCond 64 104 }; 65 105 66 static size_t disArmV8ParseIllegal(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam, uint8_t cBitStart, uint8_t cBits) 67 { 68 RT_NOREF_PV(pOp); RT_NOREF_PV(pParam); RT_NOREF_PV(pDis); 106 107 /** Opcode decoder table. */ 108 static PFNDISDECODEARMV8 const g_apfnOpcDecode[kDisArmV8OpcDecodeMax] = 109 { 110 disArmV8DecodeIllegal, 111 }; 112 113 114 DECLINLINE(uint32_t) disArmV8ExtractBitVecFromInsn(uint32_t u32Insn, uint8_t idxBitStart, uint8_t cBits) 115 { 116 uint32_t fMask = RT_BIT_32(idxBitStart + cBits) - 1; 117 return (u32Insn & fMask) >> idxBitStart; 118 } 119 120 121 DECLINLINE(int32_t) disArmV8ExtractBitVecFromInsnSignExtend(uint32_t u32Insn, uint8_t idxBitStart, uint8_t cBits) 122 { 123 uint32_t fMask = RT_BIT_32(idxBitStart + cBits) - 1; 124 uint32_t fSign = ~(UINT32_MAX & (RT_BIT_32(cBits - 1) - 1)); 125 uint32_t fValue = (u32Insn & fMask) >> idxBitStart; 126 if (fValue & fSign) 127 return (int32_t)(fValue | fSign); 128 129 return (int32_t)fValue; 130 } 131 132 133 static int disArmV8ParseIllegal(PDISSTATE pDis, uint32_t u32Insn, PCDISARMV8INSNCLASS pInsnClass, PDISOPPARAM pParam, PCDISARMV8INSNPARAM pInsnParm, bool f64Bit) 134 { 135 RT_NOREF(pDis, u32Insn, pInsnClass, pParam, pInsnParm, f64Bit); 69 136 AssertFailed(); 70 return offInstr; 137 return VERR_INTERNAL_ERROR; 138 } 139 140 141 static int disArmV8ParseImm(PDISSTATE pDis, uint32_t u32Insn, PCDISARMV8INSNCLASS pInsnClass, PDISOPPARAM pParam, PCDISARMV8INSNPARAM pInsnParm, bool f64Bit) 142 { 143 RT_NOREF(pDis, pInsnClass, f64Bit); 144 145 AssertReturn(pInsnParm->idxBitStart + pInsnParm->cBits < 32, VERR_INTERNAL_ERROR_2); 146 147 pParam->uValue = disArmV8ExtractBitVecFromInsn(u32Insn, pInsnParm->idxBitStart, pInsnParm->cBits); 148 if (pInsnParm->cBits <= 8) 149 { 150 pParam->arch.armv8.cb = sizeof(uint8_t); 151 pParam->fUse |= DISUSE_IMMEDIATE8; 152 } 153 else if (pInsnParm->cBits <= 16) 154 { 155 pParam->arch.armv8.cb = sizeof(uint16_t); 156 pParam->fUse |= DISUSE_IMMEDIATE16; 157 } 158 else if (pInsnParm->cBits <= 32) 159 { 160 pParam->arch.armv8.cb = sizeof(uint32_t); 161 pParam->fUse |= DISUSE_IMMEDIATE32; 162 } 163 else 164 AssertReleaseFailed(); 165 166 return VINF_SUCCESS; 167 } 168 169 170 static int disArmV8ParseImmRel(PDISSTATE pDis, uint32_t u32Insn, PCDISARMV8INSNCLASS pInsnClass, PDISOPPARAM pParam, PCDISARMV8INSNPARAM pInsnParm, bool f64Bit) 171 { 172 RT_NOREF(pDis, pInsnClass, f64Bit); 173 174 AssertReturn(pInsnParm->idxBitStart + pInsnParm->cBits < 32, VERR_INTERNAL_ERROR_2); 175 176 pParam->uValue = (int64_t)disArmV8ExtractBitVecFromInsnSignExtend(u32Insn, pInsnParm->idxBitStart, pInsnParm->cBits); 177 if (pInsnParm->cBits <= 8) 178 { 179 pParam->arch.armv8.cb = sizeof(int8_t); 180 pParam->fUse |= DISUSE_IMMEDIATE8_REL; 181 } 182 else if (pInsnParm->cBits <= 16) 183 { 184 pParam->arch.armv8.cb = sizeof(int16_t); 185 pParam->fUse |= DISUSE_IMMEDIATE16_REL; 186 } 187 else if (pInsnParm->cBits <= 32) 188 { 189 pParam->arch.armv8.cb = sizeof(int32_t); 190 pParam->fUse |= DISUSE_IMMEDIATE32_REL; 191 } 192 else 193 AssertReleaseFailed(); 194 195 return VINF_SUCCESS; 196 } 197 198 199 static int disArmV8ParseImmAdr(PDISSTATE pDis, uint32_t u32Insn, PCDISARMV8INSNCLASS pInsnClass, PDISOPPARAM pParam, PCDISARMV8INSNPARAM pInsnParm, bool f64Bit) 200 { 201 RT_NOREF(pDis, pInsnClass, f64Bit, pInsnParm); 202 203 pParam->uValue = disArmV8ExtractBitVecFromInsn(u32Insn, 5, 19); 204 pParam->uValue |= disArmV8ExtractBitVecFromInsn(u32Insn, 29, 2) << 29; 205 pParam->fUse |= DISUSE_IMMEDIATE32; 206 return VINF_SUCCESS; 207 } 208 209 210 static int disArmV8ParseReg(PDISSTATE pDis, uint32_t u32Insn, PCDISARMV8INSNCLASS pInsnClass, PDISOPPARAM pParam, PCDISARMV8INSNPARAM pInsnParm, bool f64Bit) 211 { 212 RT_NOREF(pDis, pInsnClass); 213 pParam->arch.armv8.Reg.idxGenReg = disArmV8ExtractBitVecFromInsn(u32Insn, pInsnParm->idxBitStart, pInsnParm->cBits); 214 pParam->arch.armv8.cb = f64Bit ? sizeof(uint64_t) : sizeof(uint32_t); 215 pParam->fUse |= f64Bit ? DISUSE_REG_GEN64 : DISUSE_REG_GEN32; 216 return VINF_SUCCESS; 217 } 218 219 220 static int disArmV8ParseImmsImmrN(PDISSTATE pDis, uint32_t u32Insn, PCDISARMV8INSNCLASS pInsnClass, PDISOPPARAM pParam, PCDISARMV8INSNPARAM pInsnParm, bool f64Bit) 221 { 222 RT_NOREF(pDis); 223 AssertReturn(pInsnParm->cBits == 13, VERR_INTERNAL_ERROR_2); 224 225 uint32_t u32ImmRaw = disArmV8ExtractBitVecFromInsn(u32Insn, pInsnParm->idxBitStart, pInsnParm->cBits); 226 /* N bit must be 0 if 32-bit variant is used. */ 227 if ( ( (u32ImmRaw & RT_BIT_32(12)) 228 && !f64Bit) 229 || ( !(u32ImmRaw & RT_BIT_32(12)) 230 && f64Bit 231 && (pInsnClass->fClass & DISARMV8INSNCLASS_F_N_FORCED_1_ON_64BIT))) 232 return VERR_DIS_INVALID_OPCODE; 233 234 /** @todo Decode according to spec. */ 235 pParam->uValue = u32ImmRaw; 236 pParam->arch.armv8.cb = sizeof(uint32_t); 237 pParam->fUse |= DISUSE_IMMEDIATE32; 238 return VINF_SUCCESS; 239 } 240 241 242 static int disArmV8ParseHw(PDISSTATE pDis, uint32_t u32Insn, PCDISARMV8INSNCLASS pInsnClass, PDISOPPARAM pParam, PCDISARMV8INSNPARAM pInsnParm, bool f64Bit) 243 { 244 RT_NOREF(pDis, u32Insn, pInsnClass, pParam, pInsnParm, f64Bit); 245 AssertFailed(); 246 /** @todo */ 247 return VINF_SUCCESS; 248 } 249 250 251 static int disArmV8ParseCond(PDISSTATE pDis, uint32_t u32Insn, PCDISARMV8INSNCLASS pInsnClass, PDISOPPARAM pParam, PCDISARMV8INSNPARAM pInsnParm, bool f64Bit) 252 { 253 RT_NOREF(pDis, u32Insn, pInsnClass, pParam, pInsnParm, f64Bit); 254 //AssertFailed(); 255 /** @todo */ 256 return VINF_SUCCESS; 257 } 258 259 260 static uint32_t disArmV8DecodeIllegal(PDISSTATE pDis, uint32_t u32Insn, PCDISARMV8INSNCLASS pInsnClass) 261 { 262 RT_NOREF(pDis, u32Insn, pInsnClass); 263 AssertFailed(); 264 return UINT32_MAX; 265 } 266 267 268 static int disArmV8A64ParseInstruction(PDISSTATE pDis, uint32_t u32Insn, PCDISOPCODE pOp, PCDISARMV8INSNCLASS pInsnClass) 269 { 270 AssertPtr(pOp); 271 AssertPtr(pDis); 272 273 /* Should contain the parameter type on input. */ 274 pDis->Param1.arch.armv8.fParam = pOp->fParam1; 275 pDis->Param2.arch.armv8.fParam = pOp->fParam2; 276 pDis->Param3.arch.armv8.fParam = pOp->fParam3; 277 pDis->Param4.arch.armv8.fParam = pOp->fParam4; 278 279 pDis->pCurInstr = pOp; 280 Assert(pOp != &g_ArmV8A64InvalidOpcode[0]); 281 282 bool f64Bit = false; 283 284 if (pInsnClass->fClass & DISARMV8INSNCLASS_F_SF) 285 f64Bit = RT_BOOL(u32Insn & RT_BIT_32(31)); 286 else if (pInsnClass->fClass & DISARMV8INSNCLASS_F_FORCED_64BIT) 287 f64Bit = true; 288 289 int rc = VINF_SUCCESS; 290 if (pInsnClass->aParms[0].idxParse != kDisParmParseNop) 291 rc = g_apfnDisasm[pInsnClass->aParms[0].idxParse](pDis, u32Insn, pInsnClass, &pDis->Param1, &pInsnClass->aParms[0], f64Bit); 292 293 if ( pInsnClass->aParms[1].idxParse != kDisParmParseNop 294 && RT_SUCCESS(rc)) 295 rc = g_apfnDisasm[pInsnClass->aParms[1].idxParse](pDis, u32Insn, pInsnClass, &pDis->Param2, &pInsnClass->aParms[1], f64Bit); 296 297 if ( pInsnClass->aParms[2].idxParse != kDisParmParseNop 298 && RT_SUCCESS(rc)) 299 rc = g_apfnDisasm[pInsnClass->aParms[2].idxParse](pDis, u32Insn, pInsnClass, &pDis->Param3, &pInsnClass->aParms[2], f64Bit); 300 301 if ( pInsnClass->aParms[3].idxParse != kDisParmParseNop 302 && RT_SUCCESS(rc)) 303 rc = g_apfnDisasm[pInsnClass->aParms[3].idxParse](pDis, u32Insn, pInsnClass, &pDis->Param4, &pInsnClass->aParms[3], f64Bit); 304 305 /* If parameter parsing returned an invalid opcode error the encoding is invalid. */ 306 if (rc == VERR_DIS_INVALID_OPCODE) 307 { 308 pDis->pCurInstr = &g_ArmV8A64InvalidOpcode[0]; 309 310 pDis->Param1.arch.armv8.fParam = g_ArmV8A64InvalidOpcode[0].fParam1; 311 pDis->Param2.arch.armv8.fParam = g_ArmV8A64InvalidOpcode[0].fParam2; 312 pDis->Param3.arch.armv8.fParam = g_ArmV8A64InvalidOpcode[0].fParam3; 313 pDis->Param4.arch.armv8.fParam = g_ArmV8A64InvalidOpcode[0].fParam4; 314 } 315 pDis->rc = rc; 316 return rc; 317 } 318 319 320 static int disArmV8A64ParseInvOpcode(PDISSTATE pDis) 321 { 322 pDis->pCurInstr = &g_ArmV8A64InvalidOpcode[0]; 323 pDis->rc = VERR_DIS_INVALID_OPCODE; 324 return VERR_DIS_INVALID_OPCODE; 325 } 326 327 328 static int disInstrArmV8DecodeWorker(PDISSTATE pDis, uint32_t u32Insn, PCDISARMV8DECODEHDR pHdr) 329 { 330 while ( pHdr 331 && pHdr->enmDecodeType != kDisArmV8DecodeType_InsnClass) 332 { 333 if (pHdr->enmDecodeType == kDisArmV8DecodeType_Map) 334 { 335 PCDISARMV8DECODEMAP pMap = (PCDISARMV8DECODEMAP)pHdr; 336 337 uint32_t idxNext = (u32Insn & pMap->fMask) >> pMap->cShift; 338 if (RT_LIKELY(idxNext < pMap->Hdr.cDecode)) 339 pHdr = pMap->papNext[idxNext]; 340 else 341 { 342 pHdr = NULL; 343 break; 344 } 345 } 346 else 347 { 348 Assert(pHdr->enmDecodeType == kDisArmV8DecodeType_Table); 349 PCDISARMV8DECODETBL pTbl = (PCDISARMV8DECODETBL)pHdr; 350 351 /* Walk all entries in the table and select the best match. */ 352 pHdr = NULL; 353 for (uint32_t i = 0; i < pTbl->Hdr.cDecode; i++) 354 { 355 PCDISARMV8DECODETBLENTRY pEntry = &pTbl->paEntries[i]; 356 if ((u32Insn & pEntry->fMask) == pEntry->fValue) 357 { 358 pHdr = pEntry->pHdrNext; 359 break; 360 } 361 } 362 } 363 } 364 365 if (pHdr) 366 { 367 Assert(pHdr->enmDecodeType == kDisArmV8DecodeType_InsnClass); 368 PCDISARMV8INSNCLASS pInsnClass = (PCDISARMV8INSNCLASS)pHdr; 369 370 /* Decode the opcode from the instruction class. */ 371 uint32_t uOpcRaw = (u32Insn & pInsnClass->fMask) >> pInsnClass->cShift; 372 if (pInsnClass->enmOpcDecode != kDisArmV8OpcDecodeNop) 373 uOpcRaw = g_apfnOpcDecode[pInsnClass->enmOpcDecode](pDis, u32Insn, pInsnClass); 374 375 if (uOpcRaw < pInsnClass->Hdr.cDecode) 376 { 377 PCDISOPCODE pOp = &pInsnClass->paOpcodes[uOpcRaw]; 378 return disArmV8A64ParseInstruction(pDis, u32Insn, pOp, pInsnClass); 379 } 380 } 381 382 return disArmV8A64ParseInvOpcode(pDis); 71 383 } 72 384 … … 82 394 DECLHIDDEN(int) disInstrWorkerArmV8(PDISSTATE pDis, PCDISOPCODE paOneByteMap, uint32_t *pcbInstr) 83 395 { 84 RT_NOREF(pDis, paOneByteMap, pcbInstr); 396 RT_NOREF(paOneByteMap); 397 398 if (pDis->uCpuMode == DISCPUMODE_ARMV8_A64) 399 { 400 *pcbInstr = sizeof(uint32_t); 401 402 /* Instructions are always little endian and 4 bytes. */ 403 uint32_t u32Insn = disReadDWord(pDis, 0 /*offInstr*/); 404 if (RT_FAILURE(pDis->rc)) 405 return pDis->rc; 406 407 pDis->u.u32 = RT_LE2H_U32(u32Insn); 408 pDis->cbInstr = sizeof(u32Insn); 409 410 return disInstrArmV8DecodeWorker(pDis, u32Insn, &g_ArmV8A64DecodeL0.Hdr); 411 } 412 413 AssertReleaseFailed(); 85 414 return VERR_NOT_IMPLEMENTED; 86 415 } -
trunk/src/VBox/Disassembler/DisasmInternal-armv8.h
r99241 r99319 48 48 /** @name Index into g_apfnFullDisasm. 49 49 * @{ */ 50 enum IDX_Parse 51 { 52 IDX_ParseNop = 0, 53 IDX_ParseMax 54 }; 55 AssertCompile(IDX_ParseMax < 64 /* Packed DISOPCODE assumption. */); 50 typedef enum DISPARMPARSEIDX 51 { 52 kDisParmParseNop = 0, 53 kDisParmParseImm, 54 kDisParmParseImmRel, 55 kDisParmParseImmAdr, 56 kDisParmParseReg, 57 kDisParmParseImmsImmrN, 58 kDisParmParseHw, 59 kDisParmParseCond, 60 kDisParmParseMax 61 } DISPARMPARSEIDX; 56 62 /** @} */ 63 64 65 typedef struct DISARMV8INSNPARAM 66 { 67 /** The parser to use for the parameter. */ 68 DISPARMPARSEIDX idxParse; 69 /** Bit index at which the field starts. */ 70 uint8_t idxBitStart; 71 /** Size of the bit field. */ 72 uint8_t cBits; 73 } DISARMV8INSNPARAM; 74 typedef DISARMV8INSNPARAM *PDISARMV8INSNPARAM; 75 typedef const DISARMV8INSNPARAM *PCDISARMV8INSNPARAM; 76 77 #define DIS_ARMV8_INSN_PARAM_NONE { kDisParmParseNop, 0, 0 } 78 #define DIS_ARMV8_INSN_PARAM_CREATE(a_idxParse, a_idxBitStart, a_cBits) \ 79 { a_idxParse, a_idxBitStart, a_cBits } 80 81 82 /** 83 * Opcode decode index. 84 */ 85 typedef enum DISARMV8OPCDECODE 86 { 87 kDisArmV8OpcDecodeNop = 0, 88 kDisArmV8OpcDecodeMax 89 } DISARMV8OPCDECODE; 90 91 92 /** 93 * Decoder stage type. 94 */ 95 typedef enum kDisArmV8DecodeType 96 { 97 kDisArmV8DecodeType_Invalid = 0, 98 kDisArmV8DecodeType_Map, 99 kDisArmV8DecodeType_Table, 100 kDisArmV8DecodeType_InsnClass, 101 kDisArmV8DecodeType_32Bit_Hack = 0x7fffffff 102 } kDisArmV8DecodeType; 103 104 105 /** 106 * Decode header. 107 */ 108 typedef struct DISARMV8DECODEHDR 109 { 110 /** Next stage decoding type. */ 111 kDisArmV8DecodeType enmDecodeType; 112 /** Number of entries in the next decoder stage or 113 * opcodes in the instruction class. */ 114 uint32_t cDecode; 115 } DISARMV8DECODEHDR; 116 /** Pointer to a decode header. */ 117 typedef DISARMV8DECODEHDR *PDISARMV8DECODEHDR; 118 /** Pointer to a const decode header. */ 119 typedef const DISARMV8DECODEHDR *PCDISARMV8DECODEHDR; 120 typedef const PCDISARMV8DECODEHDR *PPCDISARMV8DECODEHDR; 121 122 123 /** 124 * Instruction class descriptor. 125 */ 126 typedef struct DISARMV8INSNCLASS 127 { 128 /** Decoder header. */ 129 DISARMV8DECODEHDR Hdr; 130 /** Pointer to the arry of opcodes. */ 131 PCDISOPCODE paOpcodes; 132 /** Some flags for this instruction class. */ 133 uint32_t fClass; 134 /** Opcode decoder function. */ 135 DISARMV8OPCDECODE enmOpcDecode; 136 /** The mask of the bits relevant for decoding. */ 137 uint32_t fMask; 138 /** Number of bits to shift to get an index. */ 139 uint32_t cShift; 140 /** The parameters. */ 141 DISARMV8INSNPARAM aParms[4]; 142 } DISARMV8INSNCLASS; 143 /** Pointer to a constant instruction class descriptor. */ 144 typedef const DISARMV8INSNCLASS *PCDISARMV8INSNCLASS; 145 146 /** The instruction class distinguishes between a 32-bit and 64-bit variant using the sf bit (bit 31). */ 147 #define DISARMV8INSNCLASS_F_SF RT_BIT_32(0) 148 /** The N bit in an N:ImmR:ImmS bit vector must be 1 for 64-bit instruction variants. */ 149 #define DISARMV8INSNCLASS_F_N_FORCED_1_ON_64BIT RT_BIT_32(1) 150 /** The instruction class is using the 64-bit register encoding only. */ 151 #define DISARMV8INSNCLASS_F_FORCED_64BIT RT_BIT_32(2) 152 153 154 #define DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(a_Name) \ 155 static const DISOPCODE a_Name ## Opcodes[] = { 156 #define DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_PARAMS(a_Name, a_fClass, a_enmOpcDecode, a_fMask, a_cShift) \ 157 }; \ 158 static const DISARMV8INSNCLASS a_Name = { { kDisArmV8DecodeType_InsnClass, RT_ELEMENTS(a_Name ## Opcodes) }, &a_Name ## Opcodes[0],\ 159 a_fClass, a_enmOpcDecode, a_fMask, a_cShift, { 160 #define DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END } } 161 162 /** 163 * Decoder lookup table entry. 164 */ 165 typedef struct DISARMV8DECODETBLENTRY 166 { 167 /** The mask to apply to the instruction. */ 168 uint32_t fMask; 169 /** The value the masked instruction must match for the entry to match. */ 170 uint32_t fValue; 171 /** The next stage followed when there is a match. */ 172 PCDISARMV8DECODEHDR pHdrNext; 173 } DISARMV8DECODETBLENTRY; 174 typedef struct DISARMV8DECODETBLENTRY *PDISARMV8DECODETBLENTRY; 175 typedef const DISARMV8DECODETBLENTRY *PCDISARMV8DECODETBLENTRY; 176 177 178 #define DIS_ARMV8_DECODE_TBL_ENTRY_INIT(a_fMask, a_fValue, a_pNext) \ 179 { a_fMask, a_fValue, &a_pNext.Hdr } 180 181 182 /** 183 * Decoder lookup table using masks and values. 184 */ 185 typedef struct DISARMV8DECODETBL 186 { 187 /** The header for the decoder lookup table. */ 188 DISARMV8DECODEHDR Hdr; 189 /** Pointer to the individual entries. */ 190 PCDISARMV8DECODETBLENTRY paEntries; 191 } DISARMV8DECODETBL; 192 /** Pointer to a const decode table. */ 193 typedef const struct DISARMV8DECODETBL *PCDISARMV8DECODETBL; 194 195 196 #define DIS_ARMV8_DECODE_TBL_DEFINE_BEGIN(a_Name) \ 197 static const DISARMV8DECODETBLENTRY a_Name ## TblEnt[] = { 198 199 #define DIS_ARMV8_DECODE_TBL_DEFINE_END(a_Name) \ 200 }; \ 201 static const DISARMV8DECODETBL a_Name = { { kDisArmV8DecodeType_Table, RT_ELEMENTS(a_Name ## TblEnt) }, &a_Name ## TblEnt[0] } 202 203 204 /** 205 * Decoder map when direct indexing is possible. 206 */ 207 typedef struct DISARMV8DECODEMAP 208 { 209 /** The header for the decoder map. */ 210 DISARMV8DECODEHDR Hdr; 211 /** The bitmask used to decide where to go next. */ 212 uint32_t fMask; 213 /** Amount to shift to get at the index. */ 214 uint32_t cShift; 215 /** Pointer to the array of pointers to the next stage to index into. */ 216 PPCDISARMV8DECODEHDR papNext; 217 } DISARMV8DECODEMAP; 218 /** Pointer to a const decode map. */ 219 typedef const struct DISARMV8DECODEMAP *PCDISARMV8DECODEMAP; 220 221 #define DIS_ARMV8_DECODE_MAP_DEFINE_BEGIN(a_Name) \ 222 static const PCDISARMV8DECODEHDR a_Name ## MapHdrs[] = { 223 224 #define DIS_ARMV8_DECODE_MAP_DEFINE_END(a_Name, a_fMask, a_cShift) \ 225 }; \ 226 static const DISARMV8DECODEMAP a_Name = { { kDisArmV8DecodeType_Map, RT_ELEMENTS(a_Name ## MapHdrs) }, a_fMask, a_cShift, &a_Name ## MapHdrs[0] } 227 228 #define DIS_ARMV8_DECODE_MAP_DEFINE_END_NON_STATIC(a_Name, a_fMask, a_cShift) \ 229 }; \ 230 DECL_HIDDEN_CONST(DISARMV8DECODEMAP) a_Name = { { kDisArmV8DecodeType_Map, RT_ELEMENTS(a_Name ## MapHdrs) }, a_fMask, a_cShift, &a_Name ## MapHdrs[0] } 231 232 #define DIS_ARMV8_DECODE_MAP_INVALID_ENTRY NULL 233 #define DIS_ARMV8_DECODE_MAP_ENTRY(a_Next) &a_Next.Hdr 234 235 236 /** @name Decoder maps. 237 * @{ */ 238 extern DECL_HIDDEN_DATA(DISOPCODE) g_ArmV8A64InvalidOpcode[1]; 239 240 extern DECL_HIDDEN_DATA(DISARMV8DECODEMAP) g_ArmV8A64DecodeL0; 241 /** @} */ 242 57 243 58 244 /** @} */ -
trunk/src/VBox/Disassembler/Makefile.kmk
r99241 r99319 58 58 Disasm.cpp \ 59 59 DisasmCore-armv8.cpp \ 60 DisasmFormatBytes.cpp 60 DisasmTables-armv8.cpp \ 61 DisasmFormatBytes.cpp \ 62 DisasmFormatArmV8.cpp 61 63 endif 62 64
Note:
See TracChangeset
for help on using the changeset viewer.

