Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/cpu.h"
      6 #include "build/build_config.h"
      7 
      8 #include "testing/gtest/include/gtest/gtest.h"
      9 
     10 // Tests whether we can run extended instructions represented by the CPU
     11 // information. This test actually executes some extended instructions (such as
     12 // MMX, SSE, etc.) supported by the CPU and sees we can run them without
     13 // "undefined instruction" exceptions. That is, this test succeeds when this
     14 // test finishes without a crash.
     15 TEST(CPU, RunExtendedInstructions) {
     16 #if defined(ARCH_CPU_X86_FAMILY)
     17   // Retrieve the CPU information.
     18   base::CPU cpu;
     19 
     20 // TODO(jschuh): crbug.com/168866 Find a way to enable this on Win64.
     21 #if defined(OS_WIN) && !defined(_M_X64)
     22   ASSERT_TRUE(cpu.has_mmx());
     23 
     24   // Execute an MMX instruction.
     25   __asm emms;
     26 
     27   if (cpu.has_sse()) {
     28     // Execute an SSE instruction.
     29     __asm xorps xmm0, xmm0;
     30   }
     31 
     32   if (cpu.has_sse2()) {
     33     // Execute an SSE 2 instruction.
     34     __asm psrldq xmm0, 0;
     35   }
     36 
     37   if (cpu.has_sse3()) {
     38     // Execute an SSE 3 instruction.
     39     __asm addsubpd xmm0, xmm0;
     40   }
     41 
     42   if (cpu.has_ssse3()) {
     43     // Execute a Supplimental SSE 3 instruction.
     44     __asm psignb xmm0, xmm0;
     45   }
     46 
     47   if (cpu.has_sse41()) {
     48     // Execute an SSE 4.1 instruction.
     49     __asm pmuldq xmm0, xmm0;
     50   }
     51 
     52   if (cpu.has_sse42()) {
     53     // Execute an SSE 4.2 instruction.
     54     __asm crc32 eax, eax;
     55   }
     56 #elif defined(OS_POSIX) && defined(__x86_64__)
     57   ASSERT_TRUE(cpu.has_mmx());
     58 
     59   // Execute an MMX instruction.
     60   __asm__ __volatile__("emms\n" : : : "mm0");
     61 
     62   if (cpu.has_sse()) {
     63     // Execute an SSE instruction.
     64     __asm__ __volatile__("xorps %%xmm0, %%xmm0\n" : : : "xmm0");
     65   }
     66 
     67   if (cpu.has_sse2()) {
     68     // Execute an SSE 2 instruction.
     69     __asm__ __volatile__("psrldq $0, %%xmm0\n" : : : "xmm0");
     70   }
     71 
     72   if (cpu.has_sse3()) {
     73     // Execute an SSE 3 instruction.
     74     __asm__ __volatile__("addsubpd %%xmm0, %%xmm0\n" : : : "xmm0");
     75   }
     76 
     77   if (cpu.has_ssse3()) {
     78     // Execute a Supplimental SSE 3 instruction.
     79     __asm__ __volatile__("psignb %%xmm0, %%xmm0\n" : : : "xmm0");
     80   }
     81 
     82   if (cpu.has_sse41()) {
     83     // Execute an SSE 4.1 instruction.
     84     __asm__ __volatile__("pmuldq %%xmm0, %%xmm0\n" : : : "xmm0");
     85   }
     86 
     87   if (cpu.has_sse42()) {
     88     // Execute an SSE 4.2 instruction.
     89     __asm__ __volatile__("crc32 %%eax, %%eax\n" : : : "eax");
     90   }
     91 #endif
     92 #endif
     93 }
     94