From: andrewfish Date: Wed, 27 Jan 2010 02:47:47 +0000 (+0000) Subject: Added a library for the default exception handler and started to add a dissasembler... X-Git-Tag: edk2-stable201903~16506 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=6f72e28d04348ad4539679949609675b114896e1 Added a library for the default exception handler and started to add a dissasembler. Cleaned up some issues with BlockIo in BeagleBoard and add some extra info on Ebl devices command to show if a blk device has a file system on it. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9830 6f19259b-4bc3-4df7-8a09-765794883524 --- diff --git a/ArmPkg/ArmPkg.dec b/ArmPkg/ArmPkg.dec index 5509b4e04b..67c729d8e1 100644 --- a/ArmPkg/ArmPkg.dec +++ b/ArmPkg/ArmPkg.dec @@ -35,6 +35,7 @@ ArmLib|Include/Library/ArmLib.h SemihostLib|Include/Library/Semihosting.h UncachedMemoryAllocationLib|Include/Library/UncachedMemoryAllocationLib.h + DefaultExceptioHandlerLib|Include/Library/DefaultExceptioHandlerLib.h [Guids.common] gArmTokenSpaceGuid = { 0xBB11ECFE, 0x820F, 0x4968, { 0xBB, 0xA6, 0xF7, 0x6A, 0xFE, 0x30, 0x25, 0x96 } } diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc index 5925466bcc..f28af29a49 100644 --- a/ArmPkg/ArmPkg.dsc +++ b/ArmPkg/ArmPkg.dsc @@ -48,6 +48,7 @@ SemihostLib|ArmPkg/Library/SemihostLib/SemihostLib.inf UncachedMemoryAllocationLib|ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf + DefaultExceptioHandlerLib|ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf ArmLib|ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLib.inf CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf @@ -83,7 +84,8 @@ ArmPkg/Library/SemihostLib/SemihostLib.inf ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf ArmPkg/Library/DebugUncachedMemoryAllocationLib/DebugUncachedMemoryAllocationLib.inf - ArmPkg/Library/RviPeCoffExtraActionLib/RviPeCoffExtraActionLib.inf + ArmPkg/Library/RvdPeCoffExtraActionLib/RvdPeCoffExtraActionLib.inf + ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf ArmPkg/Drivers/CpuDxe/CpuDxe.inf ArmPkg/Drivers/DebugSupportDxe/DebugSupportDxe.inf diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.c b/ArmPkg/Drivers/CpuDxe/CpuDxe.c index a4ac97c65d..b51867fda3 100644 --- a/ArmPkg/Drivers/CpuDxe/CpuDxe.c +++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.c @@ -53,7 +53,6 @@ CpuFlushCpuDataCache ( IN EFI_CPU_FLUSH_TYPE FlushType ) { - DEBUG ((EFI_D_ERROR, "CpuFlushCpuDataCache (%lx, %lx, %x)\n", Start, Length, FlushType)); switch (FlushType) { case EfiCpuFlushTypeWriteBack: diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.h b/ArmPkg/Drivers/CpuDxe/CpuDxe.h index 8a71075c65..c8cba81621 100644 --- a/ArmPkg/Drivers/CpuDxe/CpuDxe.h +++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.inf b/ArmPkg/Drivers/CpuDxe/CpuDxe.inf index d4b494536b..99d52f96b4 100644 --- a/ArmPkg/Drivers/CpuDxe/CpuDxe.inf +++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.inf @@ -41,6 +41,7 @@ # ExceptionSupport.ARMv6.S | GCC Mmu.c + [Packages] ArmPkg/ArmPkg.dec EmbeddedPkg/EmbeddedPkg.dec @@ -55,6 +56,7 @@ PeCoffGetEntryPointLib UefiLib CpuLib + DefaultExceptioHandlerLib [Protocols] gEfiCpuArchProtocolGuid diff --git a/ArmPkg/Drivers/CpuDxe/Exception.c b/ArmPkg/Drivers/CpuDxe/Exception.c index d46971b33c..e313cf3fe9 100644 --- a/ArmPkg/Drivers/CpuDxe/Exception.c +++ b/ArmPkg/Drivers/CpuDxe/Exception.c @@ -14,7 +14,6 @@ #include "CpuDxe.h" -EFI_DEBUG_IMAGE_INFO_TABLE_HEADER *gDebugImageTableHeader = NULL; VOID ExceptionHandlersStart ( @@ -123,125 +122,6 @@ RegisterDebuggerInterruptHandler ( - -CHAR8 * -GetImageName ( - IN UINT32 FaultAddress, - OUT UINT32 *ImageBase, - OUT UINT32 *PeCoffSizeOfHeaders - ) -{ - EFI_DEBUG_IMAGE_INFO *DebugTable; - UINTN Entry; - CHAR8 *Address; - - - DebugTable = gDebugImageTableHeader->EfiDebugImageInfoTable; - if (DebugTable == NULL) { - return NULL; - } - - Address = (CHAR8 *)(UINTN)FaultAddress; - for (Entry = 0; Entry < gDebugImageTableHeader->TableSize; Entry++, DebugTable++) { - if (DebugTable->NormalImage != NULL) { - if ((DebugTable->NormalImage->ImageInfoType == EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL) && - (DebugTable->NormalImage->LoadedImageProtocolInstance != NULL)) { - if ((Address >= (CHAR8 *)DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase) && - (Address <= ((CHAR8 *)DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase + DebugTable->NormalImage->LoadedImageProtocolInstance->ImageSize))) { - *ImageBase = (UINT32)DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase; - *PeCoffSizeOfHeaders = PeCoffGetSizeOfHeaders ((VOID *)(UINTN)*ImageBase); - return PeCoffLoaderGetPdbPointer (DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase); - } - } - } - } - - return NULL; -} - -typedef struct { - UINT32 Bit; - CHAR8 Char; -} CPSR_CHAR; - - -VOID -CpsrString ( - IN UINT32 Cpsr, - OUT CHAR8 *ReturnStr - ) -{ - UINTN Index; - CHAR8 *Str = ReturnStr; - CHAR8 *ModeStr; - CPSR_CHAR CpsrChar[] = { - { 31, 'n' }, - { 30, 'z' }, - { 29, 'c' }, - { 28, 'v' }, - - { 9, 'e' }, - { 8, 'a' }, - { 7, 'i' }, - { 6, 'f' }, - { 5, 't' }, - { 0, '?' } - }; - - for (Index = 0; CpsrChar[Index].Bit != 0; Index++, Str++) { - *Str = CpsrChar[Index].Char; - if ((Cpsr & (1 << CpsrChar[Index].Bit)) != 0) { - // Concert to upper case if bit is set - *Str &= ~0x20; - } - } - - *Str++ = '_'; - *Str = '\0'; - - switch (Cpsr & 0x1f) { - case 0x17: - ModeStr = "abt"; - break; - case 0x011: - ModeStr = "fiq"; - break; - case 0x12: - ModeStr = "irq"; - break; - case 0x13: - ModeStr = "svc"; - break; - case 0x1f: - ModeStr = "sys"; - break; - case 0x1b: - ModeStr = "und"; - break; - case 0x10: - ModeStr = "usr"; - break; - - default: - ModeStr = "???"; - break; - } - - AsciiStrCat (Str, ModeStr); - return; -} - -CHAR8 *gExceptionTypeString[] = { - "Reset", - "Undefined Instruction", - "SWI", - "Prefetch Abort", - "Data Abort", - "Undefined", - "IRQ", - "FIQ" -}; - VOID EFIAPI CommonCExceptionHandler ( @@ -284,52 +164,7 @@ CommonCExceptionHandler ( return; } - // - // Code after here is the default exception handler... Dump the context - // - DEBUG ((EFI_D_ERROR, "\n%a Exception PC at 0x%08x CPSR 0x%08x ", gExceptionTypeString[ExceptionType], SystemContext.SystemContextArm->PC, SystemContext.SystemContextArm->CPSR)); - DEBUG_CODE_BEGIN (); - CHAR8 *Pdb; - UINT32 ImageBase; - UINT32 PeCoffSizeOfHeader; - UINT32 Offset; - CHAR8 CpsrStr[32]; // char per bit. Lower 5-bits are mode that is a 3 char string - - CpsrString (SystemContext.SystemContextArm->CPSR, CpsrStr); - DEBUG ((EFI_D_ERROR, "%a\n", CpsrStr)); - - Pdb = GetImageName (SystemContext.SystemContextArm->PC, &ImageBase, &PeCoffSizeOfHeader); - Offset = SystemContext.SystemContextArm->PC - ImageBase; - if (Pdb != NULL) { - DEBUG ((EFI_D_ERROR, "%a\n", Pdb)); - - // - // A PE/COFF image loads its headers into memory so the headers are - // included in the linked addressess. ELF and Mach-O images do not - // include the headers so the first byte of the image is usually - // text (code). If you look at link maps from ELF or Mach-O images - // you need to subtact out the size of the PE/COFF header to get - // get the offset that matches the link map. - // - DEBUG ((EFI_D_ERROR, "loaded at 0x%08x (PE/COFF offset) 0x%x (ELF or Mach-O offset) 0x%x", ImageBase, Offset, Offset - PeCoffSizeOfHeader)); - - // If we come from an image it is safe to show the instruction. We know it should not fault - if ((SystemContext.SystemContextArm->CPSR & 0x20) == 0) { - // ARM - DEBUG ((EFI_D_ERROR, "\nFaulting Instruction 0x%08x", *(UINT32 *)(UINTN)SystemContext.SystemContextArm->PC)); - } else { - // Thumb - DEBUG ((EFI_D_ERROR, "\nFaulting Instruction 0x%04x", *(UINT16 *)(UINTN)SystemContext.SystemContextArm->PC)); - } - } - DEBUG_CODE_END (); - DEBUG ((EFI_D_ERROR, "\n R0 0x%08x R1 0x%08x R2 0x%08x R3 0x%08x\n", SystemContext.SystemContextArm->R0, SystemContext.SystemContextArm->R1, SystemContext.SystemContextArm->R2, SystemContext.SystemContextArm->R3)); - DEBUG ((EFI_D_ERROR, " R4 0x%08x R5 0x%08x R6 0x%08x R7 0x%08x\n", SystemContext.SystemContextArm->R4, SystemContext.SystemContextArm->R5, SystemContext.SystemContextArm->R6, SystemContext.SystemContextArm->R7)); - DEBUG ((EFI_D_ERROR, " R8 0x%08x R9 0x%08x R10 0x%08x R11 0x%08x\n", SystemContext.SystemContextArm->R8, SystemContext.SystemContextArm->R9, SystemContext.SystemContextArm->R10, SystemContext.SystemContextArm->R11)); - DEBUG ((EFI_D_ERROR, " R12 0x%08x SP 0x%08x LR 0x%08x PC 0x%08x\n", SystemContext.SystemContextArm->R12, SystemContext.SystemContextArm->SP, SystemContext.SystemContextArm->LR, SystemContext.SystemContextArm->PC)); - DEBUG ((EFI_D_ERROR, "DFSR 0x%08x DFAR 0x%08x IFSR 0x%08x IFAR 0x%08x\n\n", SystemContext.SystemContextArm->DFSR, SystemContext.SystemContextArm->DFAR, SystemContext.SystemContextArm->IFSR, SystemContext.SystemContextArm->IFAR)); - - ASSERT (FALSE); + DefaultExceptionHandler (ExceptionType, SystemContext); } @@ -346,11 +181,6 @@ InitializeExceptions ( BOOLEAN Enabled; EFI_PHYSICAL_ADDRESS Base; - Status = EfiGetSystemConfigurationTable (&gEfiDebugImageInfoTableGuid, (VOID **)&gDebugImageTableHeader); - if (EFI_ERROR (Status)) { - gDebugImageTableHeader = NULL; - } - // // Disable interrupts // diff --git a/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.asm b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.asm index 6162e1ba50..7411762c72 100755 --- a/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.asm +++ b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.asm @@ -101,6 +101,7 @@ ResetEntry bx R1 UndefinedInstructionEntry + sub LR, LR, #4 ; Only -2 for Thumb, adjust in CommonExceptionEntry srsfd #0x13! ; Store return state on SVC stack cps #0x13 ; Switch to SVC for common stack stmfd SP!,{LR} ; Store the link register for the current mode @@ -112,6 +113,7 @@ UndefinedInstructionEntry bx R1 SoftwareInterruptEntry + sub LR, LR, #4 ; Only -2 for Thumb, adjust in CommonExceptionEntry srsfd #0x13! ; Store return state on SVC stack ; We are already in SVC mode stmfd SP!,{LR} ; Store the link register for the current mode @@ -211,15 +213,26 @@ AsmCommonExceptionEntry str R1, [SP, #0x40] ; Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR add R2, SP, #0x38 ; Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR - and R1, R1, #0x1f ; Check CPSR to see if User or System Mode - cmp R1, #0x1f ; if ((CPSR == 0x10) || (CPSR == 0x1df)) - cmpne R1, #0x10 ; + and R3, R1, #0x1f ; Check CPSR to see if User or System Mode + cmp R3, #0x1f ; if ((CPSR == 0x10) || (CPSR == 0x1df)) + cmpne R3, #0x10 ; stmeqed R2, {lr}^ ; save unbanked lr ; else stmneed R2, {lr} ; save SVC lr - ldr R1, [SP, #0x58] ; PC is the LR pushed by srsfd - str R1, [SP, #0x3c] ; Store it in EFI_SYSTEM_CONTEXT_ARM.PC + + ldr R5, [SP, #0x58] ; PC is the LR pushed by srsfd + ; Check to see if we have to adjust for Thumb entry + sub r4, r0, #1 ; if (ExceptionType == 1 || ExceptionType ==2)) { + cmp r4, #1 ; // UND & SVC have differnt LR adjust for Thumb + bhi NoAdjustNeeded + + tst r1, #0x20 ; if ((CPSR & T)) == T) { // Thumb Mode on entry + addne R5, R5, #2 ; PC += 2; + +NoAdjustNeeded + + str R5, [SP, #0x3c] ; Store it in EFI_SYSTEM_CONTEXT_ARM.PC sub R1, SP, #0x60 ; We pused 0x60 bytes on the stack str R1, [SP, #0x34] ; Store it in EFI_SYSTEM_CONTEXT_ARM.SP @@ -228,12 +241,13 @@ AsmCommonExceptionEntry mov R1,SP ; R1 is SystemContext /* -VOID -EFIAPI -CommonCExceptionHandler ( - IN EFI_EXCEPTION_TYPE ExceptionType, R0 - IN OUT EFI_SYSTEM_CONTEXT SystemContext R1 - ) +VOID +EFIAPI +CommonCExceptionHandler ( + IN EFI_EXCEPTION_TYPE ExceptionType, R0 + IN OUT EFI_SYSTEM_CONTEXT SystemContext R1 + ) + */ blx CommonCExceptionHandler ; Call exception handler diff --git a/ArmPkg/Drivers/CpuDxe/Mmu.c b/ArmPkg/Drivers/CpuDxe/Mmu.c index f2669fc32a..e81e58a9b1 100644 --- a/ArmPkg/Drivers/CpuDxe/Mmu.c +++ b/ArmPkg/Drivers/CpuDxe/Mmu.c @@ -848,13 +848,15 @@ CpuConvertPagesToUncachedVirtualAddress ( Status = SetMemoryAttributes (Address | VirtualMask, Length, EFI_MEMORY_UC, VirtualMask); } + DEBUG ((DEBUG_INFO | DEBUG_LOAD, "ConvertPagesToUncachedVirtualAddress()\n Unmapped 0x%08lx Mapped 0x%08lx 0x%x bytes\n", Address, Address | VirtualMask, Length)); + return Status; } EFI_STATUS EFIAPI -CpuReconvertPagesPages ( +CpuReconvertPages ( IN VIRTUAL_UNCACHED_PAGES_PROTOCOL *This, IN EFI_PHYSICAL_ADDRESS Address, IN UINTN Length, @@ -863,9 +865,10 @@ CpuReconvertPagesPages ( ) { EFI_STATUS Status; -DEBUG ((EFI_D_ERROR, "CpuReconvertPagesPages(%lx, %x, %lx, %lx)\n", Address, Length, VirtualMask, Attributes)); -ASSERT (FALSE); -// + + DEBUG ((DEBUG_INFO | DEBUG_LOAD, "CpuReconvertPages(%lx, %x, %lx, %lx)\n", Address, Length, VirtualMask, Attributes)); + + // // Unmap the alaised Address // Status = SetMemoryAttributes (Address | VirtualMask, Length, EFI_MEMORY_WP, 0); @@ -882,7 +885,7 @@ ASSERT (FALSE); VIRTUAL_UNCACHED_PAGES_PROTOCOL gVirtualUncachedPages = { CpuConvertPagesToUncachedVirtualAddress, - CpuReconvertPagesPages + CpuReconvertPages }; diff --git a/ArmPkg/Include/Library/ArmLib.h b/ArmPkg/Include/Library/ArmLib.h index 371075b132..da28c34731 100644 --- a/ArmPkg/Include/Library/ArmLib.h +++ b/ArmPkg/Include/Library/ArmLib.h @@ -248,6 +248,12 @@ ArmInvalidateTlb ( VOID ); +VOID +EFIAPI +ArmUpdateTranslationTableEntry ( + IN UINTN Mva + ); + VOID EFIAPI ArmSetDomainAccessControl ( diff --git a/ArmPkg/Include/Library/DefaultExceptionHandlerLib.h b/ArmPkg/Include/Library/DefaultExceptionHandlerLib.h new file mode 100644 index 0000000000..58c6cfca4e --- /dev/null +++ b/ArmPkg/Include/Library/DefaultExceptionHandlerLib.h @@ -0,0 +1,31 @@ +/** @file + + Copyright (c) 2008-2010 Apple Inc. All rights reserved.
+ + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __DEFAULT_EXCEPTION_HANDLER_LIB_H__ +#define __DEFAULT_EXCEPTION_HANDLER_LIB_H__ + +/** + This is the default action to take on an unexpected exception + + @param ExceptionType Type of the exception + @param SystemContext Register state at the time of the Exception + +**/ +VOID +DefaultExceptionHandler ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ); + +#endif diff --git a/ArmPkg/Library/DefaultExceptionHandlerLib/ArmDisassembler.c b/ArmPkg/Library/DefaultExceptionHandlerLib/ArmDisassembler.c new file mode 100644 index 0000000000..034236b946 --- /dev/null +++ b/ArmPkg/Library/DefaultExceptionHandlerLib/ArmDisassembler.c @@ -0,0 +1,442 @@ +/** @file + Default exception handler + + Copyright (c) 2008-2010, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include + + +CHAR8 *gCondition[] = { + "EQ", + "NE", + "CS", + "CC", + "MI", + "PL", + "VS", + "VC", + "HI", + "LS", + "GE", + "LT", + "GT", + "LE", + "", + "2" +}; + +#define COND(_a) gCondition[(_a) >> 28] + +CHAR8 *gReg[] = { + "r0", + "r1", + "r2", + "r3", + "r4", + "r5", + "r6", + "r7", + "r8", + "r9", + "r10", + "r11", + "r12", + "sp", + "lr", + "pc" +}; + +CHAR8 *gLdmAdr[] = { + "DA", + "IA", + "DB", + "IB" +}; + +CHAR8 *gLdmStack[] = { + "FA", + "FD", + "EA", + "ED" +}; + +#define LDM_EXT(_reg, _off) ((_reg == 13) ? gLdmStack[(_off)] : gLdmAdr[(_off)]) + + +#define SIGN(_U) ((_U) ? "" : "-") +#define WRITE(_W) ((_W) ? "!" : "") +#define BYTE(_B) ((_B) ? "B":"") +#define USER(_B) ((_B) ? "^" : "") + +CHAR8 mMregListStr[4*15 + 1]; + +CHAR8 * +MRegList ( + UINT32 OpCode + ) +{ + UINTN Index, Start, End; + CHAR8 *Str; + BOOLEAN First; + + Str = mMregListStr; + *Str = '\0'; + AsciiStrCat (Str, "{"); + for (Index = 0, First = TRUE; Index <= 15; Index++) { + if ((OpCode & (1 << Index)) != 0) { + Start = End = Index; + for (Index++; ((OpCode & (1 << Index)) != 0) && Index <= 15; Index++) { + End = Index; + } + + if (!First) { + AsciiStrCat (Str, ","); + } else { + First = FALSE; + } + + if (Start == End) { + AsciiStrCat (Str, gReg[Start]); + AsciiStrCat (Str, ", "); + } else { + AsciiStrCat (Str, gReg[Start]); + AsciiStrCat (Str, "-"); + AsciiStrCat (Str, gReg[End]); + } + } + } + if (First) { + AsciiStrCat (Str, "ERROR"); + } + AsciiStrCat (Str, "}"); + + // BugBug: Make caller pass in buffer it is cleaner + return mMregListStr; +} + +CHAR8 * +FieldMask ( + IN UINT32 Mask + ) +{ + return ""; +} + +UINT32 +RotateRight ( + IN UINT32 Op, + IN UINT32 Shift + ) +{ + return (Op >> Shift) | (Op << (32 - Shift)); +} + + +/** + DEBUG print the faulting instruction. We cheat and only decode instructions that access + memory. If the instruction is not found we dump the instruction in hex. + + @param Insturction ARM instruction to disassemble. + +**/ +VOID +DisassembleArmInstruction ( + IN UINT32 *OpCodePtr, + OUT CHAR8 *Buf, + OUT UINTN Size + ) +{ + UINT32 OpCode = *OpCodePtr; + CHAR8 *Type, *Root; + BOOLEAN I, P, U, B, W, L, S, H; + UINT32 Rn, Rd, Rm; + UINT32 imode, offset_8, offset_12; + UINT32 Index; + UINT32 shift_imm, shift; + + I = (OpCode & BIT25) == BIT25; + P = (OpCode & BIT24) == BIT24; + U = (OpCode & BIT23) == BIT23; + B = (OpCode & BIT22) == BIT22; // Also called S + W = (OpCode & BIT21) == BIT21; + L = (OpCode & BIT20) == BIT20; + S = (OpCode & BIT6) == BIT6; + H = (OpCode & BIT5) == BIT5; + Rn = (OpCode >> 16) & 0xf; + Rd = (OpCode >> 12) & 0xf; + Rm = (OpCode & 0xf); + + // LDREX, STREX + if ((OpCode & 0x0fe000f0) == 0x01800090) { + if (L) { + // A4.1.27 LDREX{} , [] + AsciiSPrint (Buf, Size, "LDREX%a %a, [%a]", COND (OpCode), gReg[Rd], gReg[Rn]); + } else { + // A4.1.103 STREX{} , , [] + AsciiSPrint (Buf, Size, "STREX%a %a, %a, [%a]", COND (OpCode), gReg[Rd], gReg[Rn], gReg[Rn]); + } + return; + } + + // LDM/STM + if ((OpCode & 0x0e000000) == 0x08000000) { + if (L) { + // A4.1.20 LDM{} {!}, + // A4.1.21 LDM{} , ^ + // A4.1.22 LDM{} {!}, ^ + AsciiSPrint (Buf, Size, "LDM%a%a, %a%a, %a", COND (OpCode), LDM_EXT (Rn ,(OpCode >> 23) & 3), gReg[Rn], WRITE (W), MRegList (OpCode), USER (B)); + } else { + // A4.1.97 STM{} {!}, + // A4.1.98 STM{} , ^ + AsciiSPrint (Buf, Size, "STM%a%a, %a%a, %a", COND (OpCode), LDM_EXT (Rn ,(OpCode >> 23) & 3), gReg[Rn], WRITE (W), MRegList (OpCode), USER (B)); + } + return; + } + + // LDR/STR Address Mode 2 + if ( ((OpCode & 0x0c000000) == 0x04000000) || ((OpCode & 0xfd70f000 ) == 0xf550f000) ) { + offset_12 = OpCode & 0xfff; + if ((OpCode & 0xfd70f000 ) == 0xf550f000) { + Index = AsciiSPrint (Buf, Size, "PLD"); + } else { + Index = AsciiSPrint (Buf, Size, "%a%a%a%a %a, ", L ? "LDR" : "STR", COND (OpCode), BYTE (B), (!P & W) ? "T":"", gReg[Rd]); + } + if (P) { + if (!I) { + // A5.2.2 [, #+/-] + // A5.2.5 [, #+/-] + AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a0x%x]%a", gReg[Rn], SIGN (U), offset_12, WRITE (W)); + } else if ((OpCode & 0x03000ff0) == 0x03000000) { + // A5.2.3 [, +/-] + // A5.2.6 [, +/-]! + AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a%a]%a", gReg[Rn], SIGN (U), WRITE (W)); + } else { + // A5.2.4 [, +/-, LSL #] + // A5.2.7 [, +/-, LSL #]! + shift_imm = (OpCode >> 7) & 0x1f; + shift = (OpCode >> 5) & 0x3; + if (shift == 0x0) { + Type = "LSL"; + } else if (shift == 0x1) { + Type = "LSR"; + if (shift_imm == 0) { + shift_imm = 32; + } + } else if (shift == 0x12) { + Type = "ASR"; + } else if (shift_imm == 0) { + AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a%a, %a, RRX]%a", gReg[Rn], SIGN (U), gReg[Rm], WRITE (W)); + return; + } else { + Type = "ROR"; + } + + AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a%a, %a, #%d]%a", gReg[Rn], SIGN (U), gReg[Rm], Type, shift_imm, WRITE (W)); + } + } else { // !P + if (!I) { + // A5.2.8 [], #+/- + AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a0x%x", gReg[Rn], SIGN (U), offset_12); + } else if ((OpCode & 0x03000ff0) == 0x03000000) { + // A5.2.9 [], +/- + AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a%a", gReg[Rn], SIGN (U), gReg[Rm]); + } else { + // A5.2.10 [], +/-, LSL # + shift_imm = (OpCode >> 7) & 0x1f; + shift = (OpCode >> 5) & 0x3; + + if (shift == 0x0) { + Type = "LSL"; + } else if (shift == 0x1) { + Type = "LSR"; + if (shift_imm == 0) { + shift_imm = 32; + } + } else if (shift == 0x12) { + Type = "ASR"; + } else if (shift_imm == 0) { + AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a%a, %a, RRX", gReg[Rn], SIGN (U), gReg[Rm]); + // FIx me + return; + } else { + Type = "ROR"; + } + + AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a%a, %a, #%d", gReg[Rn], SIGN (U), gReg[Rm], Type, shift_imm); + } + } + return; + } + + if ((OpCode & 0x0e000000) == 0x00000000) { + // LDR/STR address mode 3 + // LDR|STR{}H|SH|SB|D , + if (L) { + if (!S) { + Root = "LDR%aH %a, "; + } else if (!H) { + Root = "LDR%aSB %a, "; + } else { + Root = "LDR%aSH %a, "; + } + } else { + if (!S) { + Root = "STR%aH %a "; + } else if (!H) { + Root = "LDR%aD %a "; + } else { + Root = "STR%aD %a "; + } + } + + Index = AsciiSPrint (Buf, Size, Root, COND (OpCode), gReg[Rd]); + + S = (OpCode & BIT6) == BIT6; + H = (OpCode & BIT5) == BIT5; + offset_8 = ((OpCode >> 4) | (OpCode * 0xf)) & 0xff; + if (P & !W) { + // Immediate offset/index + if (B) { + // A5.3.2 [, #+/-] + // A5.3.4 [, #+/-]! + AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a%d]%a", gReg[Rn], SIGN (U), offset_8, WRITE (W)); + } else { + // A5.3.3 [, +/-] + // A5.3.5 [, +/-]! + AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a%]a", gReg[Rn], SIGN (U), gReg[Rm], WRITE (W)); + } + } else { + // Register offset/index + if (B) { + // A5.3.6 [], #+/- + AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a%d", gReg[Rn], SIGN (U), offset_8); + } else { + // A5.3.7 [], +/- + AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a%a", gReg[Rn], SIGN (U), gReg[Rm]); + } + } + return; + } + + if ((OpCode & 0x0fb000f0) == 0x01000050) { + // A4.1.108 SWP SWP{}B , , [] + // A4.1.109 SWPB SWP{}B , , [] + AsciiSPrint (Buf, Size, "SWP%a%a %a, %a, [%a]", COND (OpCode), BYTE (B), gReg[Rd], gReg[Rm], gReg[Rn]); + return; + } + + if ((OpCode & 0xfe5f0f00) == 0xf84d0500) { + // A4.1.90 SRS SRS #{!} + AsciiSPrint (Buf, Size, "SRS%a #0x%x%a", gLdmStack[(OpCode >> 23) & 3], OpCode & 0x1f, WRITE (W)); + return; + } + + if ((OpCode & 0xfe500f00) == 0xf8100500) { + // A4.1.59 RFE {!} + AsciiSPrint (Buf, Size, "RFE%a %a", gLdmStack[(OpCode >> 23) & 3], gReg[Rn], WRITE (W)); + return; + } + + if ((OpCode & 0xfff000f0) == 0xe1200070) { + // A4.1.7 BKPT + AsciiSPrint (Buf, Size, "BKPT %x", ((OpCode >> 8) | (OpCode & 0xf)) & 0xffff); + return; + } + + if ((OpCode & 0xfff10020) == 0xf1000000) { + // A4.1.16 CPS {, #} + if (((OpCode >> 6) & 0x7) == 0) { + AsciiSPrint (Buf, Size, "CPS #0x%x", (OpCode & 0x2f)); + } else { + imode = (OpCode >> 18) & 0x3; + Index = AsciiSPrint (Buf, Size, "CPS%a %a%a%a", (imode == 3) ? "ID":"IE", (OpCode & BIT8) ? "A":"", (OpCode & BIT7) ? "I":"", (OpCode & BIT6) ? "F":""); + if ((OpCode & BIT17) != 0) { + AsciiSPrint (&Buf[Index], Size - Index, ", #0x%x", OpCode & 0x1f); + } + } + return; + } + + if ((OpCode & 0x0f000000) == 0x0f000000) { + // A4.1.107 SWI{} + AsciiSPrint (Buf, Size, "SWI%a %x", COND (OpCode), OpCode & 0x00ffffff); + return; + } + + if ((OpCode & 0x0fb00000) == 0x01000000) { + // A4.1.38 MRS{} , CPSR MRS{} , SPSR + AsciiSPrint (Buf, Size, "MRS%a %a, %a", COND (OpCode), gReg[Rd], B ? "SPSR" : "CPSR"); + return; + } + + + if ((OpCode & 0x0db00000) == 0x03200000) { + // A4.1.38 MSR{} CPSR_, # MSR{} CPSR_, + if (I) { + // MSR{} CPSR_, # + AsciiSPrint (Buf, Size, "MRS%a %a_%a, #0x%x", COND (OpCode), B ? "SPSR" : "CPSR", FieldMask ((OpCode >> 16) & 0xf), RotateRight (OpCode & 0xf, ((OpCode >> 8) & 0xf) *2)); + } else { + // MSR{} CPSR_, + AsciiSPrint (Buf, Size, "MRS%a %a_%a, %a", COND (OpCode), B ? "SPSR" : "CPSR", gReg[Rd]); + } + return; + } + + if ((OpCode & 0xff000010) == 0xfe000000) { + // A4.1.13 CDP{} , , , , , + AsciiSPrint (Buf, Size, "CDP%a 0x%x, 0x%x, CR%d, CR%d, CR%d, 0x%x", COND (OpCode), (OpCode >> 8) & 0xf, (OpCode >> 20) & 0xf, Rn, Rd, Rm, (OpCode >> 5) &0x7); + return; + } + + if ((OpCode & 0x0e000000) == 0x0c000000) { + // A4.1.19 LDC and A4.1.96 SDC + if ((OpCode & 0xf0000000) == 0xf0000000) { + Index = AsciiSPrint (Buf, Size, "%a2 0x%x, CR%d, ", L ? "LDC":"SDC", (OpCode >> 8) & 0xf, Rd); + } else { + Index = AsciiSPrint (Buf, Size, "%a%a 0x%x, CR%d, ", L ? "LDC":"SDC", COND (OpCode), (OpCode >> 8) & 0xf, Rd); + } + + if (!P) { + if (!W) { + // A5.5.5.5 [],