1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2023 Oxide Computer Company
  14  */
  15 
  16         .file   "xsave_asm32.s"
  17 
  18 /*
  19  * Test utility routines that we need assembler for. 32-bit addition.
  20  */
  21 
  22 #include <sys/asm_linkage.h>
  23 #include "xsave_util.h"
  24 
  25 #define GET_FPU_XMM(src, i)     \
  26         leal    (i * XSU_ZMM_U32 * 4)(src), %eax; \
  27         movdqu  %xmm##i, (%eax)
  28 
  29 #define GET_FPU_YMM(src, i)     \
  30         leal    (i * XSU_ZMM_U32 * 4)(src), %eax; \
  31         vmovdqu %ymm##i, (%eax)
  32 
  33 #define GET_FPU_ZMM(src, i)     \
  34         leal    (i * XSU_ZMM_U32 * 4)(src), %eax; \
  35         vmovdqu64       %zmm##i, (%eax)
  36 
  37 #define GET_MASK(src, i)        \
  38         leal    (0x800 + i * 8)(src), %eax; \
  39         kmovq   %k##i, (%eax)
  40 
  41         /*
  42          * void xsu_getfpu(xsu_fpu_t *data, uint32_t type)
  43          *
  44          * Our job is to get the entire contents of the FPU and save it into our
  45          * data structure.
  46          */
  47         ENTRY(xsu_getfpu)
  48         movl    8(%esp), %eax
  49         movl    4(%esp), %edx
  50         cmpl    $XSU_XMM, %eax
  51         je      get_xmm
  52         cmpl    $XSU_YMM, %eax
  53         je      get_ymm
  54         cmpl    $XSU_ZMM, %eax
  55         je      get_zmm
  56         call    abort
  57 get_xmm:
  58         GET_FPU_XMM(%edx, 0)
  59         GET_FPU_XMM(%edx, 1)
  60         GET_FPU_XMM(%edx, 2)
  61         GET_FPU_XMM(%edx, 3)
  62         GET_FPU_XMM(%edx, 4)
  63         GET_FPU_XMM(%edx, 5)
  64         GET_FPU_XMM(%edx, 6)
  65         GET_FPU_XMM(%edx, 7)
  66         jmp     get_done
  67 get_ymm:
  68         GET_FPU_YMM(%edx, 0)
  69         GET_FPU_YMM(%edx, 1)
  70         GET_FPU_YMM(%edx, 2)
  71         GET_FPU_YMM(%edx, 3)
  72         GET_FPU_YMM(%edx, 4)
  73         GET_FPU_YMM(%edx, 5)
  74         GET_FPU_YMM(%edx, 6)
  75         GET_FPU_YMM(%edx, 7)
  76         jmp     get_done
  77 get_zmm:
  78         GET_FPU_ZMM(%edx, 0)
  79         GET_FPU_ZMM(%edx, 1)
  80         GET_FPU_ZMM(%edx, 2)
  81         GET_FPU_ZMM(%edx, 3)
  82         GET_FPU_ZMM(%edx, 4)
  83         GET_FPU_ZMM(%edx, 5)
  84         GET_FPU_ZMM(%edx, 6)
  85         GET_FPU_ZMM(%edx, 7)
  86         GET_MASK(%edx, 0)
  87         GET_MASK(%edx, 1)
  88         GET_MASK(%edx, 2)
  89         GET_MASK(%edx, 3)
  90         GET_MASK(%edx, 4)
  91         GET_MASK(%edx, 5)
  92         GET_MASK(%edx, 6)
  93         GET_MASK(%edx, 7)
  94 get_done:
  95         ret
  96         SET_SIZE(xsu_getfpu)
  97 
  98 #define SET_FPU_XMM(src, i)     \
  99         leal    (i * XSU_ZMM_U32 * 4)(src), %eax; \
 100         movdqu  (%eax), %xmm##i
 101 
 102 #define SET_FPU_YMM(src, i)     \
 103         leal    (i * XSU_ZMM_U32 * 4)(src), %eax; \
 104         vmovdqu (%eax), %ymm##i
 105 
 106 #define SET_FPU_ZMM(src, i)     \
 107         leal    (i * XSU_ZMM_U32 * 4)(src), %eax; \
 108         vmovdqu64       (%eax), %zmm##i
 109 
 110 #define SET_MASK(src, i)        \
 111         leal    (0x800 + i * 8)(src), %eax; \
 112         kmovq   (%eax), %k##i
 113 
 114         /*
 115          * void xsu_setfpu(const xsu_fpu_t *data, uint32_t type)
 116          *
 117          * Our job is to override the contents of the FPU with this structure
 118          * that we've been given. The type indicates how much of it to use.
 119          */
 120         ENTRY(xsu_setfpu)
 121         movl    8(%esp), %eax
 122         movl    4(%esp), %edx
 123         cmpl    $XSU_XMM, %eax
 124         je      set_xmm
 125         cmpl    $XSU_YMM, %eax
 126         je      set_ymm
 127         cmpl    $XSU_ZMM, %eax
 128         je      set_zmm
 129         call    abort
 130 set_xmm:
 131         SET_FPU_XMM(%edx, 0)
 132         SET_FPU_XMM(%edx, 1)
 133         SET_FPU_XMM(%edx, 2)
 134         SET_FPU_XMM(%edx, 3)
 135         SET_FPU_XMM(%edx, 4)
 136         SET_FPU_XMM(%edx, 5)
 137         SET_FPU_XMM(%edx, 6)
 138         SET_FPU_XMM(%edx, 7)
 139         jmp     set_done
 140 set_ymm:
 141         SET_FPU_YMM(%edx, 0)
 142         SET_FPU_YMM(%edx, 1)
 143         SET_FPU_YMM(%edx, 2)
 144         SET_FPU_YMM(%edx, 3)
 145         SET_FPU_YMM(%edx, 4)
 146         SET_FPU_YMM(%edx, 5)
 147         SET_FPU_YMM(%edx, 6)
 148         SET_FPU_YMM(%edx, 7)
 149         jmp     set_done
 150 set_zmm:
 151         SET_FPU_ZMM(%edx, 0)
 152         SET_FPU_ZMM(%edx, 1)
 153         SET_FPU_ZMM(%edx, 2)
 154         SET_FPU_ZMM(%edx, 3)
 155         SET_FPU_ZMM(%edx, 4)
 156         SET_FPU_ZMM(%edx, 5)
 157         SET_FPU_ZMM(%edx, 6)
 158         SET_FPU_ZMM(%edx, 7)
 159         SET_MASK(%edx, 0)
 160         SET_MASK(%edx, 1)
 161         SET_MASK(%edx, 2)
 162         SET_MASK(%edx, 3)
 163         SET_MASK(%edx, 4)
 164         SET_MASK(%edx, 5)
 165         SET_MASK(%edx, 6)
 166         SET_MASK(%edx, 7)
 167 set_done:
 168         ret
 169         SET_SIZE(xsu_setfpu)