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_asm64.s"
  17 
  18 /*
  19  * Test utility routines that we need assembler for. 64-bit addition.
  20  */
  21 
  22 #include <sys/asm_linkage.h>
  23 #include "xsave_util.h"
  24 
  25 #define GET_FPU_XMM(src, i)     \
  26         leaq    (i * XSU_ZMM_U32 * 4)(src), %rax; \
  27         movdqu  %xmm##i, (%rax)
  28 
  29 #define GET_FPU_YMM(src, i)     \
  30         leaq    (i * XSU_ZMM_U32 * 4)(src), %rax; \
  31         vmovdqu %ymm##i, (%rax)
  32 
  33 #define GET_FPU_ZMM(src, i)     \
  34         leaq    (i * XSU_ZMM_U32 * 4)(src), %rax; \
  35         vmovdqu64       %zmm##i, (%rax)
  36 
  37 #define GET_MASK(src, i)        \
  38         leaq    (0x800 + i * 8)(src), %rax; \
  39         kmovq   %k##i, (%rax)
  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         cmpl    $XSU_XMM, %esi
  49         je      get_xmm
  50         cmpl    $XSU_YMM, %esi
  51         je      get_ymm
  52         cmpl    $XSU_ZMM, %esi
  53         je      get_zmm
  54         call    abort
  55 get_xmm:
  56         GET_FPU_XMM(%rdi, 0)
  57         GET_FPU_XMM(%rdi, 1)
  58         GET_FPU_XMM(%rdi, 2)
  59         GET_FPU_XMM(%rdi, 3)
  60         GET_FPU_XMM(%rdi, 4)
  61         GET_FPU_XMM(%rdi, 5)
  62         GET_FPU_XMM(%rdi, 6)
  63         GET_FPU_XMM(%rdi, 7)
  64         GET_FPU_XMM(%rdi, 8)
  65         GET_FPU_XMM(%rdi, 9)
  66         GET_FPU_XMM(%rdi, 10)
  67         GET_FPU_XMM(%rdi, 11)
  68         GET_FPU_XMM(%rdi, 12)
  69         GET_FPU_XMM(%rdi, 13)
  70         GET_FPU_XMM(%rdi, 14)
  71         GET_FPU_XMM(%rdi, 15)
  72         jmp     get_done
  73 get_ymm:
  74         GET_FPU_YMM(%rdi, 0)
  75         GET_FPU_YMM(%rdi, 1)
  76         GET_FPU_YMM(%rdi, 2)
  77         GET_FPU_YMM(%rdi, 3)
  78         GET_FPU_YMM(%rdi, 4)
  79         GET_FPU_YMM(%rdi, 5)
  80         GET_FPU_YMM(%rdi, 6)
  81         GET_FPU_YMM(%rdi, 7)
  82         GET_FPU_YMM(%rdi, 8)
  83         GET_FPU_YMM(%rdi, 9)
  84         GET_FPU_YMM(%rdi, 10)
  85         GET_FPU_YMM(%rdi, 11)
  86         GET_FPU_YMM(%rdi, 12)
  87         GET_FPU_YMM(%rdi, 13)
  88         GET_FPU_YMM(%rdi, 14)
  89         GET_FPU_YMM(%rdi, 15)
  90         jmp     get_done
  91 get_zmm:
  92         GET_FPU_ZMM(%rdi, 0)
  93         GET_FPU_ZMM(%rdi, 1)
  94         GET_FPU_ZMM(%rdi, 2)
  95         GET_FPU_ZMM(%rdi, 3)
  96         GET_FPU_ZMM(%rdi, 4)
  97         GET_FPU_ZMM(%rdi, 5)
  98         GET_FPU_ZMM(%rdi, 6)
  99         GET_FPU_ZMM(%rdi, 7)
 100         GET_FPU_ZMM(%rdi, 8)
 101         GET_FPU_ZMM(%rdi, 9)
 102         GET_FPU_ZMM(%rdi, 10)
 103         GET_FPU_ZMM(%rdi, 11)
 104         GET_FPU_ZMM(%rdi, 12)
 105         GET_FPU_ZMM(%rdi, 13)
 106         GET_FPU_ZMM(%rdi, 14)
 107         GET_FPU_ZMM(%rdi, 15)
 108         GET_FPU_ZMM(%rdi, 16)
 109         GET_FPU_ZMM(%rdi, 17)
 110         GET_FPU_ZMM(%rdi, 18)
 111         GET_FPU_ZMM(%rdi, 19)
 112         GET_FPU_ZMM(%rdi, 20)
 113         GET_FPU_ZMM(%rdi, 21)
 114         GET_FPU_ZMM(%rdi, 22)
 115         GET_FPU_ZMM(%rdi, 23)
 116         GET_FPU_ZMM(%rdi, 24)
 117         GET_FPU_ZMM(%rdi, 25)
 118         GET_FPU_ZMM(%rdi, 25)
 119         GET_FPU_ZMM(%rdi, 26)
 120         GET_FPU_ZMM(%rdi, 27)
 121         GET_FPU_ZMM(%rdi, 28)
 122         GET_FPU_ZMM(%rdi, 29)
 123         GET_FPU_ZMM(%rdi, 30)
 124         GET_FPU_ZMM(%rdi, 31)
 125         GET_MASK(%rdi, 0)
 126         GET_MASK(%rdi, 1)
 127         GET_MASK(%rdi, 2)
 128         GET_MASK(%rdi, 3)
 129         GET_MASK(%rdi, 4)
 130         GET_MASK(%rdi, 5)
 131         GET_MASK(%rdi, 6)
 132         GET_MASK(%rdi, 7)
 133 get_done:
 134         ret
 135         SET_SIZE(xsu_getfpu)
 136 
 137 #define SET_FPU_XMM(src, i)     \
 138         leaq    (i * XSU_ZMM_U32 * 4)(src), %rax; \
 139         movdqu  (%rax), %xmm##i
 140 
 141 #define SET_FPU_YMM(src, i)     \
 142         leaq    (i * XSU_ZMM_U32 * 4)(src), %rax; \
 143         vmovdqu (%rax), %ymm##i
 144 
 145 #define SET_FPU_ZMM(src, i)     \
 146         leaq    (i * XSU_ZMM_U32 * 4)(src), %rax; \
 147         vmovdqu64       (%rax), %zmm##i
 148 
 149 #define SET_MASK(src, i)        \
 150         leaq    (0x800 + i * 8)(src), %rax; \
 151         kmovq   (%rax), %k##i
 152 
 153         /*
 154          * void xsu_setfpu(const xsu_fpu_t *data, uint32_t type)
 155          *
 156          * Our job is to override the contents of the FPU with this structure
 157          * that we've been given. The type indicates how much of it to use.
 158          */
 159         ENTRY(xsu_setfpu)
 160         cmpl    $XSU_XMM, %esi
 161         je      set_xmm
 162         cmpl    $XSU_YMM, %esi
 163         je      set_ymm
 164         cmpl    $XSU_ZMM, %esi
 165         je      set_zmm
 166         call    abort
 167 set_xmm:
 168         SET_FPU_XMM(%rdi, 0)
 169         SET_FPU_XMM(%rdi, 1)
 170         SET_FPU_XMM(%rdi, 2)
 171         SET_FPU_XMM(%rdi, 3)
 172         SET_FPU_XMM(%rdi, 4)
 173         SET_FPU_XMM(%rdi, 5)
 174         SET_FPU_XMM(%rdi, 6)
 175         SET_FPU_XMM(%rdi, 7)
 176         SET_FPU_XMM(%rdi, 8)
 177         SET_FPU_XMM(%rdi, 9)
 178         SET_FPU_XMM(%rdi, 10)
 179         SET_FPU_XMM(%rdi, 11)
 180         SET_FPU_XMM(%rdi, 12)
 181         SET_FPU_XMM(%rdi, 13)
 182         SET_FPU_XMM(%rdi, 14)
 183         SET_FPU_XMM(%rdi, 15)
 184         jmp     set_done
 185 set_ymm:
 186         SET_FPU_YMM(%rdi, 0)
 187         SET_FPU_YMM(%rdi, 1)
 188         SET_FPU_YMM(%rdi, 2)
 189         SET_FPU_YMM(%rdi, 3)
 190         SET_FPU_YMM(%rdi, 4)
 191         SET_FPU_YMM(%rdi, 5)
 192         SET_FPU_YMM(%rdi, 6)
 193         SET_FPU_YMM(%rdi, 7)
 194         SET_FPU_YMM(%rdi, 8)
 195         SET_FPU_YMM(%rdi, 9)
 196         SET_FPU_YMM(%rdi, 10)
 197         SET_FPU_YMM(%rdi, 11)
 198         SET_FPU_YMM(%rdi, 12)
 199         SET_FPU_YMM(%rdi, 13)
 200         SET_FPU_YMM(%rdi, 14)
 201         SET_FPU_YMM(%rdi, 15)
 202         jmp     set_done
 203 set_zmm:
 204         SET_FPU_ZMM(%rdi, 0)
 205         SET_FPU_ZMM(%rdi, 1)
 206         SET_FPU_ZMM(%rdi, 2)
 207         SET_FPU_ZMM(%rdi, 3)
 208         SET_FPU_ZMM(%rdi, 4)
 209         SET_FPU_ZMM(%rdi, 5)
 210         SET_FPU_ZMM(%rdi, 6)
 211         SET_FPU_ZMM(%rdi, 7)
 212         SET_FPU_ZMM(%rdi, 8)
 213         SET_FPU_ZMM(%rdi, 9)
 214         SET_FPU_ZMM(%rdi, 10)
 215         SET_FPU_ZMM(%rdi, 11)
 216         SET_FPU_ZMM(%rdi, 12)
 217         SET_FPU_ZMM(%rdi, 13)
 218         SET_FPU_ZMM(%rdi, 14)
 219         SET_FPU_ZMM(%rdi, 15)
 220         SET_FPU_ZMM(%rdi, 16)
 221         SET_FPU_ZMM(%rdi, 17)
 222         SET_FPU_ZMM(%rdi, 18)
 223         SET_FPU_ZMM(%rdi, 19)
 224         SET_FPU_ZMM(%rdi, 20)
 225         SET_FPU_ZMM(%rdi, 21)
 226         SET_FPU_ZMM(%rdi, 22)
 227         SET_FPU_ZMM(%rdi, 23)
 228         SET_FPU_ZMM(%rdi, 24)
 229         SET_FPU_ZMM(%rdi, 25)
 230         SET_FPU_ZMM(%rdi, 25)
 231         SET_FPU_ZMM(%rdi, 26)
 232         SET_FPU_ZMM(%rdi, 27)
 233         SET_FPU_ZMM(%rdi, 28)
 234         SET_FPU_ZMM(%rdi, 29)
 235         SET_FPU_ZMM(%rdi, 30)
 236         SET_FPU_ZMM(%rdi, 31)
 237         SET_MASK(%rdi, 0)
 238         SET_MASK(%rdi, 1)
 239         SET_MASK(%rdi, 2)
 240         SET_MASK(%rdi, 3)
 241         SET_MASK(%rdi, 4)
 242         SET_MASK(%rdi, 5)
 243         SET_MASK(%rdi, 6)
 244         SET_MASK(%rdi, 7)
 245 set_done:
 246         ret
 247         SET_SIZE(xsu_setfpu)