base/regdump-arm64.S, base/regdump.h: Save NZCV and x8--x15 early.
[catacomb] / base / regdump.h
index aae35bc..3a6d59c 100644 (file)
@@ -135,6 +135,7 @@ union gp64 { uint64 u64; int64 i64; PTR64 };
 #define   REGSRC_SIMD  0x04000000      /* SIMD vector register */
 #define   REGSRC_STMMX 0x05000000      /* x86-specific: x87/MMX register */
 #define   REGSRC_SEG   0x06000000      /* x86-specific: segment register */
+#define   REGSRC_NONE  0x0f000000      /* just a message */
 /* Where to find the values. */
 
 #define REGF_WDMASK    0xf0000000
@@ -271,11 +272,11 @@ struct regmap {
        regmap_avx = 2*WORDSZ
        regmap_size = 3*WORDSZ
 
-#define REGDEF_GPX86_COMMON(rn, RN)                                    \
-       regsrc.e##rn = REGSRC_GP | REGIX_##RN;                          \
+#define REGDEF_GPX86_COMMON(rn, ix)                                    \
+       regsrc.e##rn = REGSRC_GP | ix;                                  \
        regty.e##rn = REGF_32;                                          \
        regfmt.e##rn = REGF_HEX;                                        \
-       regsrc.r##rn = REGSRC_GP | REGIX_##RN;                          \
+       regsrc.r##rn = REGSRC_GP | ix;                                  \
        regty.r##rn = REGF_64;                                          \
        regfmt.r##rn = REGF_HEX
 
@@ -289,7 +290,7 @@ struct regmap {
        regsrc.rn##x = REGSRC_GP | REGIX_##RN##X;                       \
        regty.rn##x = REGF_16;                                          \
        regfmt.rn##x = REGF_HEX;                                        \
-       REGDEF_GPX86_COMMON(rn##x, RN##X)
+       REGDEF_GPX86_COMMON(rn##x, REGIX_##RN##X)
 REGDEF_GPX86_ABCD(a, A)
 REGDEF_GPX86_ABCD(b, B)
 REGDEF_GPX86_ABCD(c, C)
@@ -297,12 +298,12 @@ REGDEF_GPX86_ABCD(d, D)
 
        regsrc.eflags = REGSRC_GP | REGIX_FLAGS
        regty.eflags = REGF_32
-       regty.eflags = 0
+       regfmt.eflags = 0
 
 #if CPUFAM_AMD64
        regsrc.rflags = REGSRC_GP | REGIX_FLAGS
        regty.rflags = REGF_64
-       regty.rflags = 0
+       regfmt.rflags = 0
 #endif
 
 #define REGDEF_GPX86_XP(rn, RN)                                                \
@@ -312,7 +313,7 @@ REGDEF_GPX86_ABCD(d, D)
        regsrc.rn = REGSRC_GP | REGIX_##RN;                             \
        regty.rn = REGF_16;                                             \
        regfmt.rn = REGF_HEX;                                           \
-       REGDEF_GPX86_COMMON(rn, RN)
+       REGDEF_GPX86_COMMON(rn, REGIX_##RN)
 REGDEF_GPX86_XP(ip, IP)
 REGDEF_GPX86_XP(si, SI)
 REGDEF_GPX86_XP(di, DI)
@@ -381,32 +382,32 @@ DO8(REGDEF_SIMD)
 
        // Stash r/eax.  This is bletcherous: hope we don't get a signal in
        // the next few instructions.
-       mov     [R_sp(r) - REGDUMP_SPADJ + (REGIX_AX - 1)*WORDSZ], R_a(r)
+       mov     [SP - REGDUMP_SPADJ + (REGIX_AX - 1)*WORDSZ], AX
 
   .ifnes "\addr", "nil"
        // Collect the effective address for the following dump, leaving it
        // in the `addr' slot of the dump.
-       lea     R_a(r), \addr
-       mov     [R_sp(r) - REGDUMP_SPADJ + (REGIX_ADDR - 1)*WORDSZ], R_a(r)
+       lea     AX, \addr
+       mov     [SP - REGDUMP_SPADJ + (REGIX_ADDR - 1)*WORDSZ], AX
   .endif
 
        // Make space for the register save area.  On AMD64 with System/V
        // ABI, also skip the red zone.  Use `lea' here to preserve the
        // flags.
-       lea     R_sp(r), [R_sp(r) - REGDUMP_SPADJ]
+       lea     SP, [SP - REGDUMP_SPADJ]
 
        // Save flags and general-purpose registers.  On 32-bit x86, we save
        // ebx here and establish a GOT pointer here for the benefit of the
        // PLT-indirect calls made later on.
        pushf
 #  if CPUFAM_X86
-       mov     [esp + 4*REGIX_BX], ebx
+       mov     [SP + 4*REGIX_BX], ebx
        ldgot
 #  endif
        callext F(regdump_gpsave)
 
        // Make space for the extended registers.
-       sub     R_sp(r), R_c(r)
+       sub     SP, CX
        callext F(regdump_xtsave)
 
        // Prepare for calling back into C.  On 32-bit x86, leave space for
@@ -414,11 +415,11 @@ DO8(REGDEF_SIMD)
        // the `shadow space' for the called-function's arguments.  Also,
        // forcibly align the stack pointer to a 16-byte boundary.
 #  if CPUFAM_X86
-       sub     esp, 16
+       sub     SP, 16
 #  elif ABI_WIN
-       sub     rsp, 32
+       sub     SP, 32
 #  endif
-       and     R_sp(r), ~15
+       and     SP, ~15
 .endm
 
 .macro _rstrregs
@@ -426,27 +427,38 @@ DO8(REGDEF_SIMD)
 
        // We assume r/ebp still points to the register map.
        callext F(regdump_xtrstr)
-       mov     R_sp(r), R_bp(r)
+       mov     SP, BP
        callext F(regdump_gprstr)
        popf
-       lea     R_sp(r), [R_sp(r) + REGDUMP_SPADJ]
+       lea     SP, [SP + REGDUMP_SPADJ]
+.endm
+
+.macro _nilbase
+#  if CPUFAM_X86
+       xor     eax, eax
+       mov     [SP + 0], eax
+#  elif ABI_SYSV
+       xor     edi, edi
+#  elif ABI_WIN
+       xor     ecx, ecx
+#  endif
 .endm
 
 .macro _regbase
 #  if CPUFAM_X86
-       mov     [esp + 0], ebp
+       mov     [SP + 0], BP
 #  elif ABI_SYSV
-       mov     rdi, rbp
+       mov     rdi, BP
 #  elif ABI_WIN
-       mov     rcx, rbp
+       mov     rcx, BP
 #  endif
 .endm
 
 .macro _membase
-       mov     R_a(r), [R_bp(r) + regmap_gp]
+       mov     AX, [BP + regmap_gp]
 #  if CPUFAM_X86
        mov     eax, [eax + REGIX_ADDR*WORDSZ]
-       mov     [esp + 0], eax
+       mov     [SP + 0], eax
 #  elif ABI_SYSV
        mov     rdi, [rax + REGIX_ADDR*WORDSZ]
 #  elif ABI_WIN
@@ -457,7 +469,7 @@ DO8(REGDEF_SIMD)
 .macro _reglbl msg
   .ifeqs "\msg", ""
 #  if CPUFAM_X86
-       mov     dword ptr [esp + 4], 0
+       mov     dword ptr [SP + 4], 0
 #  elif ABI_SYSV
        xor     esi, esi
 #  elif ABI_WIN
@@ -466,7 +478,7 @@ DO8(REGDEF_SIMD)
   .else
 #  if CPUFAM_X86
        lea     eax, [INTADDR(.L$_reglbl$\@)]
-       mov     [esp + 4], eax
+       mov     [SP + 4], eax
 #  elif ABI_SYSV
        lea     rsi, [INTADDR(.L$_reglbl$\@)]
 #  elif ABI_WIN
@@ -481,7 +493,7 @@ DO8(REGDEF_SIMD)
 
 .macro _regfmt arg
 #  if CPUFAM_X86
-       mov     dword ptr [esp + 8], \arg
+       mov     dword ptr [SP + 8], \arg
 #  elif ABI_SYSV
        mov     edx, \arg
 #  elif ABI_WIN
@@ -600,6 +612,8 @@ DO16(REGDEF_NEONQ)
        sub     r13, r13, #REGDUMP_GPSIZE
 
        // Save flags and general-purpose registers.
+       mrs     r14, cpsr
+       str     r14, [r13, #4*REGIX_CPSR]
        str     r12, [r13, #4*12]
        bl      regdump_gpsave
 
@@ -625,6 +639,10 @@ DO16(REGDEF_NEONQ)
        add     r13, r13, #REGDUMP_GPSIZE
 .endm
 
+.macro _nilbase
+       mov     r0, #0
+.endm
+
 .macro _regbase
        mov     r0, r5
 .endm
@@ -643,8 +661,8 @@ DO16(REGDEF_NEONQ)
 .endm
 
 .macro _regfmt arg
-       movw    r2, #\arg&0xffff
-       movt    r2, #(\arg >> 16)&0xffff
+       movw    r2, #(\arg)&0xffff
+       movt    r2, #((\arg) >> 16)&0xffff
 .endm
 
 #endif
@@ -756,8 +774,15 @@ DO32(REGDEF_FP)
        // Make space for the register save area.
        sub     sp, sp, #REGDUMP_GPSIZE
 
-       // Save flags and general-purpose registers.
-       stp     x16, x17, [sp, #8*16]
+       // Save flags and general-purpose registers.  The PLT linkage code
+       // makes free with x8--x17, so we must save those here.
+       mrs     x30, nzcv
+       str     x30, [sp, #8*REGIX_NZCV]
+       stp     x8, x9, [sp, #64]
+       stp     x10, x11, [sp, #80]
+       stp     x12, x13, [sp, #96]
+       stp     x14, x15, [sp, #112]
+       stp     x16, x17, [sp, #128]
        bl      regdump_gpsave
 
        // Make space for the extended registers.
@@ -776,6 +801,10 @@ DO32(REGDEF_FP)
        add     sp, sp, #REGDUMP_GPSIZE
 .endm
 
+.macro _nilbase
+       mov     x0, #0
+.endm
+
 .macro _regbase
        mov     x0, x21
 .endm
@@ -794,8 +823,8 @@ DO32(REGDEF_FP)
 .endm
 
 .macro _regfmt arg
-       movz    w2, #\arg&0xffff
-       movk    w2, #(\arg >> 16)&0xffff, lsl #16
+       movz    w2, #(\arg)&0xffff
+       movk    w2, #((\arg) >> 16)&0xffff, lsl #16
 .endm
 
 #endif
@@ -889,6 +918,15 @@ extern void regdump_freshline(void);
        _rstrregs
 .endm
 
+.macro msg     lbl
+       _saveregs
+       _nilbase
+       _reglbl "\lbl"
+       _regfmt REGSRC_NONE | (1 << REGF_WDSHIFT)
+       callext F(regdump)
+       _rstrregs
+.endm
+
 .macro reg     lbl, rn, fmt=0
        _saveregs
        _regbase