~ubuntu-branches/ubuntu/quantal/open-vm-tools/quantal-201210021442

« back to all changes in this revision

Viewing changes to lib/include/vm_basic_asm.h

  • Committer: Package Import Robot
  • Author(s): Nate Muench
  • Date: 2012-06-20 15:59:51 UTC
  • mfrom: (1.4.8)
  • Revision ID: package-import@ubuntu.com-20120620155951-6rupmpb0f70b52zr
Tags: 2012.05.21-724730-0ubuntu1
* Merging upstream version 2012.05.21-724730.
  - Fixes building against the current Quantal kernel. (LP: #1000344)
  - Fixes Quantal installation issues. (LP: #1019031)

* Sync with Debian
  - Updating to debhelper version 9.
  - Updating to standards version 3.9.3.
  - Updating copyright file machine-readable format version 1.0.
  - Building without multiarch paths for now

Show diffs side-by-side

added added

removed removed

Lines of Context:
130
130
unsigned char  _BitScanReverse(unsigned long *, unsigned long);
131
131
#pragma intrinsic(_BitScanForward, _BitScanReverse)
132
132
 
 
133
unsigned char  _bittest(const long *, long);
133
134
unsigned char  _bittestandset(long *, long);
134
135
unsigned char  _bittestandreset(long *, long);
135
 
#pragma intrinsic(_bittestandset, _bittestandreset)
 
136
unsigned char  _bittestandcomplement(long *, long);
 
137
#pragma intrinsic(_bittest, _bittestandset, _bittestandreset, _bittestandcomplement)
136
138
#ifdef VM_X86_64
137
139
unsigned char  _bittestandset64(__int64 *, __int64);
138
140
unsigned char  _bittestandreset64(__int64 *, __int64);
799
801
 
800
802
 
801
803
/*
 
804
 *----------------------------------------------------------------------
 
805
 *
 
806
 * COMPILER_FORCED_LOAD_AND_MEM_BARRIER --
 
807
 *
 
808
 *        This macro prevents the compiler from re-ordering memory references
 
809
 *        across the barrier. In addition it emits a forced load from the given
 
810
 *        memory reference. The memory reference has to be either 1, 2, 4 or 8
 
811
 *        bytes wide.
 
812
 *        The forced load of a memory reference can be used exploit details of a
 
813
 *        given CPUs memory model. For example x86 CPUs won't reorder stores to
 
814
 *        a memory location x with loads from a memory location x.
 
815
 *        NOTE: It does not generate any fencing instruction, so the CPU is free
 
816
 *              to reorder instructions according to its memory model.
 
817
 *
 
818
 * Results:
 
819
 *        None
 
820
 *
 
821
 * Side Effects:
 
822
 *        None.
 
823
 *
 
824
 *----------------------------------------------------------------------
 
825
 */
 
826
 
 
827
#ifdef VM_X86_64
 
828
#ifdef __GNUC__
 
829
 
 
830
#define COMPILER_FORCED_LOAD_AND_MEM_BARRIER(_memory_reference)               \
 
831
   do {                                                                       \
 
832
      typeof(_memory_reference) _dummy;                                       \
 
833
                                                                              \
 
834
      asm volatile("mov %1, %0\n\t"                                           \
 
835
                   : "=r" (_dummy) /* Let compiler choose reg for _dummy */   \
 
836
                   : "m" (_memory_reference)                                  \
 
837
                   : "memory");                                               \
 
838
   } while(0)
 
839
 
 
840
#endif /* __GNUC__ */
 
841
#endif /* VM_X86_64 */
 
842
 
 
843
 
 
844
/*
802
845
 * PAUSE is a P4 instruction that improves spinlock power+performance;
803
846
 * on non-P4 IA32 systems, the encoding is interpreted as a REPZ-NOP.
804
847
 * Use volatile to avoid NOP removal.
945
988
 *-----------------------------------------------------------------------------
946
989
 */
947
990
 
 
991
#ifdef __arm__
 
992
#define DEBUGBREAK() __asm__("bkpt")
 
993
#else
948
994
#ifdef _MSC_VER
949
 
#define DEBUGBREAK()   __debugbreak()
 
995
#define DEBUGBREAK() __debugbreak()
950
996
#else
951
 
#define DEBUGBREAK()   __asm__ (" int $3 ")
 
997
#define DEBUGBREAK() __asm__("int $3")
952
998
#endif
 
999
#endif // __arm__
953
1000
#endif // defined(__i386__) || defined(__x86_64__) || defined(__arm__)
954
1001
 
955
1002
 
956
1003
/*
957
1004
 *-----------------------------------------------------------------------------
958
1005
 *
959
 
 * {Clear,Set}Bit{32,64} --
 
1006
 * {Clear,Set,Test}Bit{32,64} --
960
1007
 *
961
1008
 *    Sets or clears a specified single bit in the provided variable.  
962
1009
 *    The index input value specifies which bit to modify and is 0-based. 
1069
1116
 
1070
1117
/*
1071
1118
 *-----------------------------------------------------------------------------
 
1119
 *
 
1120
 * {Clear,Set,Complement,Test}BitVector --
 
1121
 *
 
1122
 *    Sets, clears, complements, or tests a specified single bit in the
 
1123
 *    provided array.  The index input value specifies which bit to modify
 
1124
 *    and is 0-based.  Bit number can be +-2Gb (+-128MB) relative from 'var'
 
1125
 *    variable.
 
1126
 *
 
1127
 *    All functions return value of the bit before modification was performed.
 
1128
 *
 
1129
 *-----------------------------------------------------------------------------
 
1130
 */
 
1131
 
 
1132
static INLINE Bool
 
1133
SetBitVector(void *var, int32 index)
 
1134
{
 
1135
#ifdef __GNUC__
 
1136
   Bool bit;
 
1137
   __asm__ (
 
1138
      "bts %2, %1;"
 
1139
      "setc %0"
 
1140
      : "=rm" (bit), "+m" (*(volatile uint32 *)var)
 
1141
      : "rI" (index)
 
1142
      : "memory"
 
1143
   );
 
1144
   return bit;
 
1145
#elif defined(_MSC_VER)
 
1146
   return _bittestandset((long *)var, index) != 0;
 
1147
#else
 
1148
#error No compiler defined for SetBitVector
 
1149
#endif
 
1150
}
 
1151
 
 
1152
static INLINE Bool
 
1153
ClearBitVector(void *var, int32 index)
 
1154
{
 
1155
#ifdef __GNUC__
 
1156
   Bool bit;
 
1157
   __asm__ (
 
1158
      "btr %2, %1;"
 
1159
      "setc %0"
 
1160
      : "=rm" (bit), "+m" (*(volatile uint32 *)var)
 
1161
      : "rI" (index)
 
1162
      : "cc"
 
1163
   );
 
1164
   return bit;
 
1165
#elif defined(_MSC_VER)
 
1166
   return _bittestandreset((long *)var, index) != 0;
 
1167
#else
 
1168
#error No compiler defined for ClearBitVector
 
1169
#endif
 
1170
}
 
1171
 
 
1172
static INLINE Bool
 
1173
ComplementBitVector(void *var, int32 index)
 
1174
{
 
1175
#ifdef __GNUC__
 
1176
   Bool bit;
 
1177
   __asm__ (
 
1178
      "btc %2, %1;"
 
1179
      "setc %0"
 
1180
      : "=rm" (bit), "+m" (*(volatile uint32 *)var)
 
1181
      : "rI" (index)
 
1182
      : "cc"
 
1183
   );
 
1184
   return bit;
 
1185
#elif defined(_MSC_VER)
 
1186
   return _bittestandcomplement((long *)var, index) != 0;
 
1187
#else
 
1188
#error No compiler defined for ComplementBitVector
 
1189
#endif
 
1190
}
 
1191
 
 
1192
static INLINE Bool
 
1193
TestBitVector(const void *var, int32 index)
 
1194
{
 
1195
#ifdef __GNUC__
 
1196
   Bool bit;
 
1197
   __asm__ (
 
1198
      "bt %2, %1;"
 
1199
      "setc %0"
 
1200
      : "=rm" (bit)
 
1201
      : "m" (*(const uint32 *)var), "rI" (index)
 
1202
      : "cc"
 
1203
   );
 
1204
   return bit;
 
1205
#elif defined _MSC_VER
 
1206
   return _bittest((long *)var, index) != 0;
 
1207
#else
 
1208
#error No compiler defined for TestBitVector
 
1209
#endif
 
1210
}
 
1211
 
 
1212
/*
 
1213
 *-----------------------------------------------------------------------------
1072
1214
 * RoundUpPow2_{64,32} --
1073
1215
 *
1074
1216
 *   Rounds a value up to the next higher power of 2.  Returns the original 
1135
1277
static INLINE uint32
1136
1278
RoundUpPow2Asm32(uint32 value)
1137
1279
{
 
1280
#ifdef __arm__
 
1281
   uint32 out = 1;
 
1282
   // Note: None Thumb only!
 
1283
   //       The value of the argument "value"
 
1284
   //       will be affected!
 
1285
   __asm__("sub %[in], %[in], #1;"         // r1 = value - 1 . if value == 0 then r1 = 0xFFFFFFFF
 
1286
           "clz %[in], %[in];"             // r1 = log2(value - 1) if value != 1
 
1287
                                           // if value == 0 then r1 = 0
 
1288
                                           // if value == 1 then r1 = 32
 
1289
           "mov %[out], %[out], ror %[in]" // out = 2^(32 - r1)
 
1290
                                           // if out == 2^32 then out = 1 as it is right rotate
 
1291
       : [in]"+r"(value),[out]"+r"(out));
 
1292
#else
1138
1293
   uint32 out = 2;
 
1294
 
1139
1295
   __asm__("lea -1(%[in]), %%ecx;"      // ecx = value - 1.  Preserve original.
1140
1296
           "bsr %%ecx, %%ecx;"          // ecx = log2(value - 1) if value != 1
1141
1297
                                        // if value == 0, then ecx = 31
1146
1302
                                        // zf is always unmodified
1147
1303
           "cmovz %[in], %[out]"        // if value == 1 (zf == 1), write 1 to out.
1148
1304
       : [out]"+r"(out) : [in]"r"(value) : "%ecx", "cc");
 
1305
#endif
1149
1306
   return out;
1150
1307
}
1151
1308
#endif // __GNUC__