1
/*********************************************************
2
* Copyright (C) 1998-2004 VMware, Inc. All rights reserved.
4
* This program is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU General Public License as published by the
6
* Free Software Foundation version 2 and no later version.
8
* This program is distributed in the hope that it will be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13
* You should have received a copy of the GNU General Public License along
14
* with this program; if not, write to the Free Software Foundation, Inc.,
15
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
*********************************************************/
20
* vm_basic_asm_x86_64.h
22
* Basic x86_64 asm macros.
25
#ifndef _VM_BASIC_ASM_X86_64_H_
26
#define _VM_BASIC_ASM_X86_64_H_
28
#define INCLUDE_ALLOW_USERLEVEL
29
#define INCLUDE_ALLOW_VMMEXT
30
#define INCLUDE_ALLOW_MODULE
31
#define INCLUDE_ALLOW_VMMON
32
#define INCLUDE_ALLOW_VMK_MODULE
33
#define INCLUDE_ALLOW_VMKERNEL
34
#define INCLUDE_ALLOW_DISTRIBUTE
35
#define INCLUDE_ALLOW_VMCORE
36
#define INCLUDE_ALLOW_VMNIXMOD
37
#include "includeCheck.h"
40
#error "This file is x86-64 only!"
48
uint64 _umul128(uint64 multiplier, uint64 multiplicand,
50
int64 _mul128(int64 multiplier, int64 multiplicand,
52
uint64 __shiftright128(uint64 lowPart, uint64 highPart, uint8 shift);
57
#pragma intrinsic(_umul128, _mul128, __shiftright128)
63
* save/restore SIMD/MMX fpu state
65
* The pointer passed in must be 16-byte aligned.
67
* Intel and AMD processors behave differently w.r.t. fxsave/fxrstor. Intel
68
* processors unconditionally save the exception pointer state (instruction
69
* ptr., data ptr., and error instruction opcode). FXSAVE_ES1 and FXRSTOR_ES1
70
* work correctly for Intel processors.
72
* AMD processors only save the exception pointer state if ES=1. This leads to a
73
* security hole whereby one process/VM can inspect the state of another process
74
* VM. The AMD recommended workaround involves clobbering the exception pointer
75
* state unconditionally, and this is implemented in FXRSTOR_AMD_ES0. Note that
76
* FXSAVE_ES1 will only save the exception pointer state for AMD processors if
79
* The workaround (FXRSTOR_AMD_ES0) only costs 1 cycle more than just doing an
80
* fxrstor, on both AMD Opteron and Intel Core CPUs.
85
FXSAVE_ES1(uint8 *save)
87
__asm__ __volatile__ ("fxsaveq %0 \n" : "=m" (*save) : : "memory");
91
FXSAVE_COMPAT_ES1(uint8 *save)
93
__asm__ __volatile__ ("fxsave %0 \n" : "=m" (*save) : : "memory");
97
FXRSTOR_ES1(const uint8 *load)
99
__asm__ __volatile__ ("fxrstorq %0 \n" : : "m" (*load) : "memory");
103
FXRSTOR_COMPAT_ES1(const uint8 *load)
105
__asm__ __volatile__ ("fxrstor %0 \n" : : "m" (*load) : "memory");
109
FXRSTOR_AMD_ES0(const uint8 *load)
114
("fnstsw %%ax \n" // Grab x87 ES bit
115
"bt $7,%%ax \n" // Test ES bit
116
"jnc 1f \n" // Jump if ES=0
117
"fnclex \n" // ES=1. Clear it so fild doesn't trap
119
"ffree %%st(7) \n" // Clear tag bit - avoid poss. stack overflow
120
"fildl %0 \n" // Dummy Load from "safe address" changes all
121
// x87 exception pointers.
124
: "m" (dummy), "m" (*load)
128
#endif /* __GNUC__ */
132
*-----------------------------------------------------------------------------
136
* Unsigned integer by fixed point multiplication:
137
* result = multiplicand * multiplier >> shift
139
* Unsigned 64-bit integer multiplicand.
140
* Unsigned 32-bit fixed point multiplier, represented as
141
* multiplier >> shift, where shift < 64.
142
* Unsigned 64-bit integer product.
145
* Multiply 64x64 bits to yield a full 128-bit product.
146
* Shift result in RDX:RAX right by "shift".
147
* Return the low-order 64 bits of the above.
152
*-----------------------------------------------------------------------------
155
#if defined(__GNUC__)
158
Mul64x3264(uint64 multiplicand,
162
uint64 result, dummy;
163
const uint64 multiplier64 = multiplier;
165
__asm__("mulq %3 \n\t"
169
: "0" (multiplier64),
176
#elif defined(_MSC_VER)
179
Mul64x3264(uint64 multiplicand, uint32 multiplier, uint32 shift)
182
tmplo = _umul128(multiplicand, multiplier, &tmphi);
183
return __shiftright128(tmplo, tmphi, (uint8) shift);
189
*-----------------------------------------------------------------------------
193
* Signed integer by fixed point multiplication:
194
* result = multiplicand * multiplier >> shift
196
* Signed 64-bit integer multiplicand.
197
* Unsigned 32-bit fixed point multiplier, represented as
198
* multiplier >> shift, where shift < 64.
199
* Signed 64-bit integer product.
202
* Multiply 64x64 bits to yield a full 128-bit product.
203
* Shift result in RDX:RAX right by "shift".
204
* Return the low-order 64 bits of the above.
206
* Note: using an unsigned shift instruction is correct because
207
* shift < 64 and we return only the low 64 bits of the shifted
213
*-----------------------------------------------------------------------------
216
#if defined(__GNUC__)
219
Muls64x32s64(int64 multiplicand, uint32 multiplier, uint32 shift)
222
const int64 multiplier64 = multiplier;
224
__asm__("imulq %3 \n\t"
228
: "0" (multiplier64),
235
#elif defined(_MSC_VER)
238
Muls64x32s64(int64 multiplicand, uint32 multiplier, uint32 shift)
241
tmplo = _mul128(multiplicand, multiplier, &tmphi);
242
return __shiftright128(tmplo, tmphi, (uint8) shift);
248
#if defined(__GNUC__)
251
uint64set(void *dst, uint64 val, uint64 count)
255
__asm__ __volatile__("\t"
258
: "=c" (dummy0), "=D" (dummy1)
259
: "0" (count), "1" (dst), "a" (val)
267
*-----------------------------------------------------------------------------
271
* Unsigned integer division:
272
* The dividend is 64-bit wide
273
* The divisor is 32-bit wide
274
* The quotient is 32-bit wide
276
* Use this function if you are certain that the quotient will fit in 32 bits,
277
* If that is not the case, a #DE exception was generated in 32-bit version,
278
* but not in this 64-bit version. So please be careful.
281
* Quotient and remainder
286
*-----------------------------------------------------------------------------
289
#if defined(__GNUC__) || defined(_MSC_VER)
292
Div643232(uint64 dividend, // IN
293
uint32 divisor, // IN
294
uint32 *quotient, // OUT
295
uint32 *remainder) // OUT
297
*quotient = (uint32)(dividend / divisor);
298
*remainder = (uint32)(dividend % divisor);
304
*-----------------------------------------------------------------------------
308
* Unsigned integer division:
309
* The dividend is 64-bit wide
310
* The divisor is 32-bit wide
311
* The quotient is 64-bit wide
314
* Quotient and remainder
319
*-----------------------------------------------------------------------------
322
#if defined(__GNUC__)
325
Div643264(uint64 dividend, // IN
326
uint32 divisor, // IN
327
uint64 *quotient, // OUT
328
uint32 *remainder) // OUT
330
*quotient = dividend / divisor;
331
*remainder = dividend % divisor;
336
#endif // _VM_BASIC_ASM_X86_64_H_