From e8d15a489fa76612707ff9e99feb0fb36acc9f14 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 7 May 2021 16:11:18 -0700 Subject: machine: correct some additional cases of UB (#246) Use of asm aliased register variables in local scope can only be used for extended assembly parameters. This changes the few instances of this in the floating point emulation to use the GNU extended assembly syntax to access the `tp` register. This ensures that we do not rely on undefined behaviour. This was uncovered when building the Proxy kernel with clang and LLVM. --- machine/fp_emulation.h | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/machine/fp_emulation.h b/machine/fp_emulation.h index 1352ca3..eeafafb 100644 --- a/machine/fp_emulation.h +++ b/machine/fp_emulation.h @@ -47,14 +47,22 @@ else tp = GET_RM(insn); \ asm volatile ("":"+r"(tp)); }) # define softfloat_raiseFlags(which) set_csr(fflags, which) -# define softfloat_roundingMode ({ register int tp asm("tp"); tp; }) +# define softfloat_roundingMode ({ \ + uintptr_t __tp; \ + __asm__("mv %0, tp" : "=r"(__tp)); \ + __tp; \ +}) # define SET_FS_DIRTY() ((void) 0) #else # define GET_F64_REG(insn, pos, regs) (*(int64_t*)((void*)((regs) + 32) + (SHIFT_RIGHT(insn, (pos)-3) & 0xf8))) # define SET_F64_REG(insn, pos, regs, val) (GET_F64_REG(insn, pos, regs) = (val)) # define GET_F32_REG(insn, pos, regs) (*(int32_t*)&GET_F64_REG(insn, pos, regs)) # define SET_F32_REG(insn, pos, regs, val) (GET_F32_REG(insn, pos, regs) = (val)) -# define GET_FCSR() ({ register int tp asm("tp"); tp & 0xFF; }) +# define GET_FCSR() ({ \ + uintptr_t __tp; \ + __asm__("mv %0, tp" : "=r"(__tp)); \ + __tp & 0xff; \ +}) # define SET_FCSR(value) ({ asm volatile("add tp, x0, %0" :: "rI"((value) & 0xFF)); SET_FS_DIRTY(); }) # define GET_FRM() (GET_FCSR() >> 5) # define SET_FRM(value) SET_FCSR(GET_FFLAGS() | ((value) << 5)) @@ -62,13 +70,19 @@ # define SET_FFLAGS(value) SET_FCSR((GET_FRM() << 5) | ((value) & 0x1F)) # define SETUP_STATIC_ROUNDING(insn) ({ \ - register int tp asm("tp"); tp &= 0xFF; \ + register uintptr_t tp asm("tp"); \ + __asm__("mv %0, tp" : "=r"(tp)); \ + tp &= 0xff; \ if (likely(((insn) & MASK_FUNCT3) == MASK_FUNCT3)) tp |= tp << 8; \ else if (GET_RM(insn) > 4) return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); \ else tp |= GET_RM(insn) << 13; \ asm volatile ("":"+r"(tp)); }) # define softfloat_raiseFlags(which) ({ asm volatile ("or tp, tp, %0" :: "rI"(which)); }) -# define softfloat_roundingMode ({ register int tp asm("tp"); tp >> 13; }) +# define softfloat_roundingMode ({ \ + uintptr_t __tp; \ + __asm__("mv %0, tp" : "=r"(__tp)); \ + __tp >> 13; \ +}) # define SET_FS_DIRTY() set_csr(mstatus, MSTATUS_FS) #endif -- cgit v1.1