/** @file GCC inline implementation of BaseLib processor specific functions. Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.
Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "BaseLibInternals.h" /** Used to serialize load and store operations. All loads and stores that proceed calls to this function are guaranteed to be globally visible when this function returns. **/ VOID EFIAPI MemoryFence ( VOID ) { // This is a little bit of overkill and it is more about the compiler that it is // actually processor synchronization. This is like the _ReadWriteBarrier // Microsoft specific intrinsic __asm__ __volatile__ ("":::"memory"); } /** Requests CPU to pause for a short period of time. Requests CPU to pause for a short period of time. Typically used in MP systems to prevent memory starvation while waiting for a spin lock. **/ VOID EFIAPI CpuPause ( VOID ) { __asm__ __volatile__ ("pause"); } /** Generates a breakpoint on the CPU. Generates a breakpoint on the CPU. The breakpoint must be implemented such that code can resume normal execution after the breakpoint. **/ VOID EFIAPI CpuBreakpoint ( VOID ) { __asm__ __volatile__ ("int $3"); } /** Reads the current value of the EFLAGS register. Reads and returns the current value of the EFLAGS register. This function is only available on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on X64. @return EFLAGS on IA-32 or RFLAGS on X64. **/ UINTN EFIAPI AsmReadEflags ( VOID ) { UINTN Eflags; __asm__ __volatile__ ( "pushfq \n\t" "pop %0 " : "=r" (Eflags) // %0 ); return Eflags; } /** Save the current floating point/SSE/SSE2 context to a buffer. Saves the current floating point/SSE/SSE2 state to the buffer specified by Buffer. Buffer must be aligned on a 16-byte boundary. This function is only available on IA-32 and X64. @param Buffer The pointer to a buffer to save the floating point/SSE/SSE2 context. **/ VOID EFIAPI InternalX86FxSave ( OUT IA32_FX_BUFFER *Buffer ) { __asm__ __volatile__ ( "fxsave %0" : : "m" (*Buffer) // %0 ); } /** Restores the current floating point/SSE/SSE2 context from a buffer. Restores the current floating point/SSE/SSE2 state from the buffer specified by Buffer. Buffer must be aligned on a 16-byte boundary. This function is only available on IA-32 and X64. @param Buffer The pointer to a buffer to save the floating point/SSE/SSE2 context. **/ VOID EFIAPI InternalX86FxRestore ( IN CONST IA32_FX_BUFFER *Buffer ) { __asm__ __volatile__ ( "fxrstor %0" : : "m" (*Buffer) // %0 ); } /** Reads the current value of 64-bit MMX Register #0 (MM0). Reads and returns the current value of MM0. This function is only available on IA-32 and X64. @return The current value of MM0. **/ UINT64 EFIAPI AsmReadMm0 ( VOID ) { UINT64 Data; __asm__ __volatile__ ( "movd %%mm0, %0 \n\t" : "=r" (Data) // %0 ); return Data; } /** Reads the current value of 64-bit MMX Register #1 (MM1). Reads and returns the current value of MM1. This function is only available on IA-32 and X64. @return The current value of MM1. **/ UINT64 EFIAPI AsmReadMm1 ( VOID ) { UINT64 Data; __asm__ __volatile__ ( "movd %%mm1, %0 \n\t" : "=r" (Data) // %0 ); return Data; } /** Reads the current value of 64-bit MMX Register #2 (MM2). Reads and returns the current value of MM2. This function is only available on IA-32 and X64. @return The current value of MM2. **/ UINT64 EFIAPI AsmReadMm2 ( VOID ) { UINT64 Data; __asm__ __volatile__ ( "movd %%mm2, %0 \n\t" : "=r" (Data) // %0 ); return Data; } /** Reads the current value of 64-bit MMX Register #3 (MM3). Reads and returns the current value of MM3. This function is only available on IA-32 and X64. @return The current value of MM3. **/ UINT64 EFIAPI AsmReadMm3 ( VOID ) { UINT64 Data; __asm__ __volatile__ ( "movd %%mm3, %0 \n\t" : "=r" (Data) // %0 ); return Data; } /** Reads the current value of 64-bit MMX Register #4 (MM4). Reads and returns the current value of MM4. This function is only available on IA-32 and X64. @return The current value of MM4. **/ UINT64 EFIAPI AsmReadMm4 ( VOID ) { UINT64 Data; __asm__ __volatile__ ( "movd %%mm4, %0 \n\t" : "=r" (Data) // %0 ); return Data; } /** Reads the current value of 64-bit MMX Register #5 (MM5). Reads and returns the current value of MM5. This function is only available on IA-32 and X64. @return The current value of MM5. **/ UINT64 EFIAPI AsmReadMm5 ( VOID ) { UINT64 Data; __asm__ __volatile__ ( "movd %%mm5, %0 \n\t" : "=r" (Data) // %0 ); return Data; } /** Reads the current value of 64-bit MMX Register #6 (MM6). Reads and returns the current value of MM6. This function is only available on IA-32 and X64. @return The current value of MM6. **/ UINT64 EFIAPI AsmReadMm6 ( VOID ) { UINT64 Data; __asm__ __volatile__ ( "movd %%mm6, %0 \n\t" : "=r" (Data) // %0 ); return Data; } /** Reads the current value of 64-bit MMX Register #7 (MM7). Reads and returns the current value of MM7. This function is only available on IA-32 and X64. @return The current value of MM7. **/ UINT64 EFIAPI AsmReadMm7 ( VOID ) { UINT64 Data; __asm__ __volatile__ ( "movd %%mm7, %0 \n\t" : "=r" (Data) // %0 ); return Data; } /** Writes the current value of 64-bit MMX Register #0 (MM0). Writes the current value of MM0. This function is only available on IA32 and X64. @param Value The 64-bit value to write to MM0. **/ VOID EFIAPI AsmWriteMm0 ( IN UINT64 Value ) { __asm__ __volatile__ ( "movd %0, %%mm0" // %0 : : "m" (Value) ); } /** Writes the current value of 64-bit MMX Register #1 (MM1). Writes the current value of MM1. This function is only available on IA32 and X64. @param Value The 64-bit value to write to MM1. **/ VOID EFIAPI AsmWriteMm1 ( IN UINT64 Value ) { __asm__ __volatile__ ( "movd %0, %%mm1" // %0 : : "m" (Value) ); } /** Writes the current value of 64-bit MMX Register #2 (MM2). Writes the current value of MM2. This function is only available on IA32 and X64. @param Value The 64-bit value to write to MM2. **/ VOID EFIAPI AsmWriteMm2 ( IN UINT64 Value ) { __asm__ __volatile__ ( "movd %0, %%mm2" // %0 : : "m" (Value) ); } /** Writes the current value of 64-bit MMX Register #3 (MM3). Writes the current value of MM3. This function is only available on IA32 and X64. @param Value The 64-bit value to write to MM3. **/ VOID EFIAPI AsmWriteMm3 ( IN UINT64 Value ) { __asm__ __volatile__ ( "movd %0, %%mm3" // %0 : : "m" (Value) ); } /** Writes the current value of 64-bit MMX Register #4 (MM4). Writes the current value of MM4. This function is only available on IA32 and X64. @param Value The 64-bit value to write to MM4. **/ VOID EFIAPI AsmWriteMm4 ( IN UINT64 Value ) { __asm__ __volatile__ ( "movd %0, %%mm4" // %0 : : "m" (Value) ); } /** Writes the current value of 64-bit MMX Register #5 (MM5). Writes the current value of MM5. This function is only available on IA32 and X64. @param Value The 64-bit value to write to MM5. **/ VOID EFIAPI AsmWriteMm5 ( IN UINT64 Value ) { __asm__ __volatile__ ( "movd %0, %%mm5" // %0 : : "m" (Value) ); } /** Writes the current value of 64-bit MMX Register #6 (MM6). Writes the current value of MM6. This function is only available on IA32 and X64. @param Value The 64-bit value to write to MM6. **/ VOID EFIAPI AsmWriteMm6 ( IN UINT64 Value ) { __asm__ __volatile__ ( "movd %0, %%mm6" // %0 : : "m" (Value) ); } /** Writes the current value of 64-bit MMX Register #7 (MM7). Writes the current value of MM7. This function is only available on IA32 and X64. @param Value The 64-bit value to write to MM7. **/ VOID EFIAPI AsmWriteMm7 ( IN UINT64 Value ) { __asm__ __volatile__ ( "movd %0, %%mm7" // %0 : : "m" (Value) ); } /** Reads the current value of Time Stamp Counter (TSC). Reads and returns the current value of TSC. This function is only available on IA-32 and X64. @return The current value of TSC **/ UINT64 EFIAPI AsmReadTsc ( VOID ) { UINT32 LowData; UINT32 HiData; __asm__ __volatile__ ( "rdtsc" : "=a" (LowData), "=d" (HiData) ); return (((UINT64)HiData) << 32) | LowData; }