diff --git a/ArmPkg/Library/ArmExceptionLib/AArch64/ExceptionSupport.S b/ArmPkg/Library/ArmExceptionLib/AArch64/ExceptionSupport.S
index 0fd304db2dbf..fef7d908c1cc 100644
--- a/ArmPkg/Library/ArmExceptionLib/AArch64/ExceptionSupport.S
+++ b/ArmPkg/Library/ArmExceptionLib/AArch64/ExceptionSupport.S
@@ -107,54 +107,6 @@ GCC_ASM_EXPORT(CommonCExceptionHandler)
 #define FP_CONTEXT_SIZE    (32 * 16)
 #define SYS_CONTEXT_SIZE   ( 6 *  8) // 5 SYS regs + Alignment requirement (ie: the stack must be aligned on 0x10)
 
-// Cannot str x31 directly
-#define ALL_GP_REGS                                     \
-        REG_PAIR (x0,  x1,  0x000, GP_CONTEXT_SIZE);    \
-        REG_PAIR (x2,  x3,  0x010, GP_CONTEXT_SIZE);    \
-        REG_PAIR (x4,  x5,  0x020, GP_CONTEXT_SIZE);    \
-        REG_PAIR (x6,  x7,  0x030, GP_CONTEXT_SIZE);    \
-        REG_PAIR (x8,  x9,  0x040, GP_CONTEXT_SIZE);    \
-        REG_PAIR (x10, x11, 0x050, GP_CONTEXT_SIZE);    \
-        REG_PAIR (x12, x13, 0x060, GP_CONTEXT_SIZE);    \
-        REG_PAIR (x14, x15, 0x070, GP_CONTEXT_SIZE);    \
-        REG_PAIR (x16, x17, 0x080, GP_CONTEXT_SIZE);    \
-        REG_PAIR (x18, x19, 0x090, GP_CONTEXT_SIZE);    \
-        REG_PAIR (x20, x21, 0x0a0, GP_CONTEXT_SIZE);    \
-        REG_PAIR (x22, x23, 0x0b0, GP_CONTEXT_SIZE);    \
-        REG_PAIR (x24, x25, 0x0c0, GP_CONTEXT_SIZE);    \
-        REG_PAIR (x26, x27, 0x0d0, GP_CONTEXT_SIZE);    \
-        REG_PAIR (x28, x29, 0x0e0, GP_CONTEXT_SIZE);    \
-        REG_ONE  (x30,      0x0f0, GP_CONTEXT_SIZE);
-
-// In order to save the SP we need to put it somewhere else first.
-// STR only works with XZR/WZR directly
-#define SAVE_SP \
-        add x1, sp, #(FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE); \
-        REG_ONE (x1,        0x0f8, GP_CONTEXT_SIZE);
-
-#define ALL_FP_REGS                                     \
-        REG_PAIR (q0,  q1,  0x000, FP_CONTEXT_SIZE);    \
-        REG_PAIR (q2,  q3,  0x020, FP_CONTEXT_SIZE);    \
-        REG_PAIR (q4,  q5,  0x040, FP_CONTEXT_SIZE);    \
-        REG_PAIR (q6,  q7,  0x060, FP_CONTEXT_SIZE);    \
-        REG_PAIR (q8,  q9,  0x080, FP_CONTEXT_SIZE);    \
-        REG_PAIR (q10, q11, 0x0a0, FP_CONTEXT_SIZE);    \
-        REG_PAIR (q12, q13, 0x0c0, FP_CONTEXT_SIZE);    \
-        REG_PAIR (q14, q15, 0x0e0, FP_CONTEXT_SIZE);    \
-        REG_PAIR (q16, q17, 0x100, FP_CONTEXT_SIZE);    \
-        REG_PAIR (q18, q19, 0x120, FP_CONTEXT_SIZE);    \
-        REG_PAIR (q20, q21, 0x140, FP_CONTEXT_SIZE);    \
-        REG_PAIR (q22, q23, 0x160, FP_CONTEXT_SIZE);    \
-        REG_PAIR (q24, q25, 0x180, FP_CONTEXT_SIZE);    \
-        REG_PAIR (q26, q27, 0x1a0, FP_CONTEXT_SIZE);    \
-        REG_PAIR (q28, q29, 0x1c0, FP_CONTEXT_SIZE);    \
-        REG_PAIR (q30, q31, 0x1e0, FP_CONTEXT_SIZE);
-
-#define ALL_SYS_REGS                                    \
-        REG_PAIR (x1,  x2,  0x000, SYS_CONTEXT_SIZE);   \
-        REG_PAIR (x3,  x4,  0x010, SYS_CONTEXT_SIZE);   \
-        REG_ONE  (x5,       0x020, SYS_CONTEXT_SIZE);
-
 //
 // There are two methods for installing AArch64 exception vectors:
 //  1. Install a copy of the vectors to a location specified by a PCD
@@ -170,18 +122,35 @@ ASM_PFX(ExceptionHandlersStart):
 VECTOR_BASE(ExceptionHandlersStart)
 #endif
 
-#undef  REG_PAIR
-#undef  REG_ONE
-#define REG_PAIR(REG1, REG2, OFFSET, CONTEXT_SIZE)  stp  REG1, REG2, [sp, #(OFFSET-CONTEXT_SIZE)]
-#define REG_ONE(REG1, OFFSET, CONTEXT_SIZE)         stur REG1, [sp, #(OFFSET-CONTEXT_SIZE)]
-
   .macro  ExceptionEntry, val
   // Move the stackpointer so we can reach our structure with the str instruction.
   sub sp, sp, #(FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE)
 
-  // Save all the General regs before touching x0 and x1.
-  // This does not save r31(SP) as it is special. We do that later.
-  ALL_GP_REGS
+  // Push some GP registers so we can record the exception context
+  stp      x0, x1, [sp, #-GP_CONTEXT_SIZE]!
+  stp      x2, x3, [sp, #0x10]
+  stp      x4, x5, [sp, #0x20]
+  stp      x6, x7, [sp, #0x30]
+
+  EL1_OR_EL2_OR_EL3(x1)
+1:mrs      x2, elr_el1   // Exception Link Register
+  mrs      x3, spsr_el1  // Saved Processor Status Register 32bit
+  mrs      x5, esr_el1   // EL1 Exception syndrome register 32bit
+  mrs      x6, far_el1   // EL1 Fault Address Register
+  b        4f
+
+2:mrs      x2, elr_el2   // Exception Link Register
+  mrs      x3, spsr_el2  // Saved Processor Status Register 32bit
+  mrs      x5, esr_el2   // EL2 Exception syndrome register 32bit
+  mrs      x6, far_el2   // EL2 Fault Address Register
+  b        4f
+
+3:mrs      x2, elr_el3   // Exception Link Register
+  mrs      x3, spsr_el3  // Saved Processor Status Register 32bit
+  mrs      x5, esr_el3   // EL3 Exception syndrome register 32bit
+  mrs      x6, far_el3   // EL3 Fault Address Register
+
+4:mrs      x4, fpsr      // Floating point Status Register  32bit
 
   // Record the type of exception that occurred.
   mov       x0, #\val
@@ -278,49 +247,44 @@ ASM_PFX(ExceptionHandlersEnd):
 
 
 ASM_PFX(CommonExceptionEntry):
-  /* NOTE:
-     We have to break up the save code because the immediate value to be used
-     with the SP is too big to do it all in one step so we need to shuffle the SP
-     along as we go. (we only have 9bits of immediate to work with) */
-
-  // Save the current Stack pointer before we start modifying it.
-  SAVE_SP
-
-  // Preserve the stack pointer we came in with before we modify it
-  EL1_OR_EL2_OR_EL3(x1)
-1:mrs      x1, elr_el1   // Exception Link Register
-  mrs      x2, spsr_el1  // Saved Processor Status Register 32bit
-  mrs      x4, esr_el1   // EL1 Exception syndrome register 32bit
-  mrs      x5, far_el1   // EL1 Fault Address Register
-  b        4f
 
-2:mrs      x1, elr_el2   // Exception Link Register
-  mrs      x2, spsr_el2  // Saved Processor Status Register 32bit
-  mrs      x4, esr_el2   // EL2 Exception syndrome register 32bit
-  mrs      x5, far_el2   // EL2 Fault Address Register
-  b        4f
-
-3:mrs      x1, elr_el3   // Exception Link Register
-  mrs      x2, spsr_el3  // Saved Processor Status Register 32bit
-  mrs      x4, esr_el3   // EL3 Exception syndrome register 32bit
-  mrs      x5, far_el3   // EL3 Fault Address Register
-
-4:mrs      x3, fpsr      // Floating point Status Register  32bit
-
-  // Adjust SP to save next set
-  add      sp, sp, #FP_CONTEXT_SIZE
-
-  // Push FP regs to Stack.
-  ALL_FP_REGS
-
-  // Adjust SP to save next set
-  add      sp, sp, #SYS_CONTEXT_SIZE
+  // Stack the remaining GP registers
+  stp      x8,  x9,  [sp, #0x40]
+  stp      x10, x11, [sp, #0x50]
+  stp      x12, x13, [sp, #0x60]
+  stp      x14, x15, [sp, #0x70]
+  stp      x16, x17, [sp, #0x80]
+  stp      x18, x19, [sp, #0x90]
+  stp      x20, x21, [sp, #0xa0]
+  stp      x22, x23, [sp, #0xb0]
+  stp      x24, x25, [sp, #0xc0]
+  stp      x26, x27, [sp, #0xd0]
+  stp      x28, x29, [sp, #0xe0]
+  add      x28, sp, #GP_CONTEXT_SIZE + FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE
+  stp      x30, x28, [sp, #0xf0]
 
   // Save the SYS regs
-  ALL_SYS_REGS
+  stp      x2,  x3,  [x28, #-SYS_CONTEXT_SIZE]!
+  stp      x4,  x5,  [x28, #0x10]
+  str      x6,  [x28, #0x20]
 
-  // Point to top of struct after all regs saved
-  sub      sp, sp, #(GP_CONTEXT_SIZE + FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE)
+  // Push FP regs to Stack.
+  stp      q0,  q1,  [x28, #-FP_CONTEXT_SIZE]!
+  stp      q2,  q3,  [x28, #0x20]
+  stp      q4,  q5,  [x28, #0x40]
+  stp      q6,  q7,  [x28, #0x60]
+  stp      q8,  q9,  [x28, #0x80]
+  stp      q10, q11, [x28, #0xa0]
+  stp      q12, q13, [x28, #0xc0]
+  stp      q14, q15, [x28, #0xe0]
+  stp      q16, q17, [x28, #0x100]
+  stp      q18, q19, [x28, #0x120]
+  stp      q20, q21, [x28, #0x140]
+  stp      q22, q23, [x28, #0x160]
+  stp      q24, q25, [x28, #0x180]
+  stp      q26, q27, [x28, #0x1a0]
+  stp      q28, q29, [x28, #0x1c0]
+  stp      q30, q31, [x28, #0x1e0]
 
   // x0 still holds the exception type.
   // Set x1 to point to the top of our struct on the Stack
@@ -337,13 +301,44 @@ ASM_PFX(CommonExceptionEntry):
   // We do not try to recover.
   bl       ASM_PFX(CommonCExceptionHandler) // Call exception handler
 
-
-// Defines for popping from stack
-
-#undef REG_PAIR
-#undef REG_ONE
-#define REG_PAIR(REG1, REG2, OFFSET, CONTEXT_SIZE)    ldp  REG1, REG2, [sp, #(OFFSET-CONTEXT_SIZE)]
-#define REG_ONE(REG1, OFFSET, CONTEXT_SIZE)           ldur REG1, [sp, #(OFFSET-CONTEXT_SIZE)]
+  // Pop as many GP regs as we can before entering the critical section below
+  ldp      x2,  x3,  [sp, #0x10]
+  ldp      x4,  x5,  [sp, #0x20]
+  ldp      x6,  x7,  [sp, #0x30]
+  ldp      x8,  x9,  [sp, #0x40]
+  ldp      x10, x11, [sp, #0x50]
+  ldp      x12, x13, [sp, #0x60]
+  ldp      x14, x15, [sp, #0x70]
+  ldp      x16, x17, [sp, #0x80]
+  ldp      x18, x19, [sp, #0x90]
+  ldp      x20, x21, [sp, #0xa0]
+  ldp      x22, x23, [sp, #0xb0]
+  ldp      x24, x25, [sp, #0xc0]
+  ldp      x26, x27, [sp, #0xd0]
+  ldp      x0,  x1,  [sp], #0xe0
+
+  // Pop FP regs from Stack.
+  ldp      q2,  q3,  [x28, #0x20]
+  ldp      q4,  q5,  [x28, #0x40]
+  ldp      q6,  q7,  [x28, #0x60]
+  ldp      q8,  q9,  [x28, #0x80]
+  ldp      q10, q11, [x28, #0xa0]
+  ldp      q12, q13, [x28, #0xc0]
+  ldp      q14, q15, [x28, #0xe0]
+  ldp      q16, q17, [x28, #0x100]
+  ldp      q18, q19, [x28, #0x120]
+  ldp      q20, q21, [x28, #0x140]
+  ldp      q22, q23, [x28, #0x160]
+  ldp      q24, q25, [x28, #0x180]
+  ldp      q26, q27, [x28, #0x1a0]
+  ldp      q28, q29, [x28, #0x1c0]
+  ldp      q30, q31, [x28, #0x1e0]
+  ldp      q0,  q1,  [x28], #FP_CONTEXT_SIZE
+
+  // Pop the SYS regs we need
+  ldp      x29, x30, [x28]
+  ldr      x28, [x28, #0x10]
+  msr      fpsr, x28
 
   //
   // Disable interrupt(IRQ and FIQ) before restoring context,
@@ -353,35 +348,23 @@ ASM_PFX(CommonExceptionEntry):
   msr   daifset, #3
   isb
 
-  // Adjust SP to pop system registers
-  add     sp, sp, #(GP_CONTEXT_SIZE + FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE)
-  ALL_SYS_REGS
-
-  EL1_OR_EL2_OR_EL3(x6)
-1:msr      elr_el1, x1   // Exception Link Register
-  msr      spsr_el1,x2   // Saved Processor Status Register 32bit
+  EL1_OR_EL2_OR_EL3(x28)
+1:msr      elr_el1, x29  // Exception Link Register
+  msr      spsr_el1,x30  // Saved Processor Status Register 32bit
   b        4f
-2:msr      elr_el2, x1   // Exception Link Register
-  msr      spsr_el2,x2   // Saved Processor Status Register 32bit
+2:msr      elr_el2, x29  // Exception Link Register
+  msr      spsr_el2,x30  // Saved Processor Status Register 32bit
   b        4f
-3:msr      elr_el3, x1   // Exception Link Register
-  msr      spsr_el3,x2   // Saved Processor Status Register 32bit
-4:msr      fpsr, x3      // Floating point Status Register  32bit
-
-  // pop all regs and return from exception.
-  sub     sp, sp, #(FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE)
-  ALL_GP_REGS
+3:msr      elr_el3, x29  // Exception Link Register
+  msr      spsr_el3,x30  // Saved Processor Status Register 32bit
+4:
 
-  // Adjust SP to pop next set
-  add      sp, sp, #FP_CONTEXT_SIZE
-  // Pop FP regs to Stack.
-  ALL_FP_REGS
+  // pop remaining GP regs and return from exception.
+  ldr      x30, [sp, #GP_CONTEXT_SIZE - 0xf0]
+  ldp      x28, x29, [sp], #GP_CONTEXT_SIZE - 0xe0
 
   // Adjust SP to be where we started from when we came into the handler.
   // The handler can not change the SP.
-  add      sp, sp, #SYS_CONTEXT_SIZE
+  add      sp, sp, #FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE
 
   eret
-
-#undef REG_PAIR
-#undef REG_ONE
