Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  tests.c   Sprache: C

 

#include <inttypes.h>
#include <stdio.h>

#include "tests.h"

#if ARCH_X86

/* Re-use helpers from main checkasm library */
#include "src/cpu.h"

uint64_t selftest_get_cpu_flags_x86(void)
{
    uint64_t       flags = SELFTEST_CPU_FLAG_X86;
    CpuidRegisters r;
    checkasm_cpu_cpuid(&r, 0, 0);
    const uint32_t max_leaf = r.eax;
    if (max_leaf < 1)
        return flags;

    checkasm_cpu_cpuid(&r, 1, 0);
    if (r.edx & 0x00800000) /* MMX */
        flags |= SELFTEST_CPU_FLAG_MMX;
    if (r.edx & 0x02000000) /* SSE2 */
        flags |= SELFTEST_CPU_FLAG_SSE2;
    if (~r.ecx & 0x18000000) /* OSXSAVE/AVX */
        return flags;

    const uint64_t xcr0 = checkasm_cpu_xgetbv(0);
    if (max_leaf < 7 || ~xcr0 & 0x6) /* XMM/YMM */
        return flags;

    checkasm_cpu_cpuid(&r, 7, 0);
    if (r.ebx & 0x00000020) /* AVX2 */
        flags |= SELFTEST_CPU_FLAG_AVX2;

    if (~xcr0 & 0xe0) /* ZMM/OPMASK */
        return flags;

    if (r.ebx & 0x00000020) /* AVX512F */
        flags |= SELFTEST_CPU_FLAG_AVX512;
    return flags;
}

DEF_COPY_FUNC(copy_x86);
DEF_COPY_FUNC(copy_mmx);
DEF_COPY_FUNC(copy_sse2);
DEF_COPY_FUNC(copy_avx2);
DEF_COPY_FUNC(copy_avx512);

DEF_NOOP_FUNC(clobber_r0);
DEF_NOOP_FUNC(clobber_r1);
DEF_NOOP_FUNC(clobber_r2);
DEF_NOOP_FUNC(clobber_r3);
DEF_NOOP_FUNC(clobber_r4);
DEF_NOOP_FUNC(clobber_r5);
DEF_NOOP_FUNC(clobber_r6);
#if ARCH_X86_64
DEF_NOOP_FUNC(clobber_r7);
DEF_NOOP_FUNC(clobber_r8);
DEF_NOOP_FUNC(clobber_r9);
DEF_NOOP_FUNC(clobber_r10);
DEF_NOOP_FUNC(clobber_r11);
DEF_NOOP_FUNC(clobber_r12);
DEF_NOOP_FUNC(clobber_r13);
DEF_NOOP_FUNC(clobber_r14);
#endif

DEF_NOOP_FUNC(sigill_x86);
DEF_NOOP_FUNC(corrupt_stack_x86);

DEF_COPY_FUNC(copy_noemms_mmx);
DEF_COPY_FUNC(copy_novzeroupper_avx2);

static copy_func *get_copy_x86(void)
{
    const uint64_t flags = checkasm_get_cpu_flags();
#if ARCH_X86
    if (flags & SELFTEST_CPU_FLAG_AVX512)
        return selftest_copy_avx512;
    if (flags & SELFTEST_CPU_FLAG_AVX2)
        return selftest_copy_avx2;
    if (flags & SELFTEST_CPU_FLAG_SSE2)
        return selftest_copy_sse2;
    if (flags & SELFTEST_CPU_FLAG_MMX)
        return selftest_copy_mmx;
    if (flags & SELFTEST_CPU_FLAG_X86)
        return selftest_copy_x86;
#endif
    return selftest_copy_c;
}

#if ARCH_X86_64
  #ifdef _WIN32
    #define NUM_SAFE 7
  #else
    #define NUM_SAFE 9
  #endif
  #define NUM_REGS 15
  #define STACK_ALIGN 16
#else
  #define NUM_SAFE 3
  #define NUM_REGS 7
  #define STACK_ALIGN 4
#endif

static noop_func *get_clobber(int reg)
{
    if (!(checkasm_get_cpu_flags() & SELFTEST_CPU_FLAG_X86))
        return NULL;

    switch (reg) {
    case 0: return selftest_clobber_r0;
    case 1: return selftest_clobber_r1;
    case 2: return selftest_clobber_r2;
    case 3: return selftest_clobber_r3;
    case 4: return selftest_clobber_r4;
    case 5: return selftest_clobber_r5;
    case 6: return selftest_clobber_r6;
#if ARCH_X86_64
    case 7:  return selftest_clobber_r7;
    case 8:  return selftest_clobber_r8;
    case 9:  return selftest_clobber_r9;
    case 10: return selftest_clobber_r10;
    case 11: return selftest_clobber_r11;
    case 12: return selftest_clobber_r12;
    case 13: return selftest_clobber_r13;
    case 14: return selftest_clobber_r14;
#endif
    /* can't clobber rsp without completely crashing the program */
    default: return NULL;
    }
}

DEF_NOOP_GETTER(SELFTEST_CPU_FLAG_X86, sigill_x86)
DEF_NOOP_GETTER(SELFTEST_CPU_FLAG_X86, corrupt_stack_x86)
DEF_COPY_GETTER(SELFTEST_CPU_FLAG_MMX, copy_noemms_mmx)
DEF_COPY_GETTER(SELFTEST_CPU_FLAG_AVX2, copy_novzeroupper_avx2)

uintptr_t selftest_get_stack_pointer_x86(int unused);

static void check_stack_alignment(void)
{
    checkasm_declare(uintptr_t, int);

    if (checkasm_check_func(selftest_get_stack_pointer_x86, "stack_alignment")) {
        uintptr_t sp = checkasm_call_new(0);

        /* Subtract return address */
        sp -= sizeof(sp);
        if (sp & (STACK_ALIGN - 1)) {
            if (checkasm_fail()) {
                fprintf(stderr, "stack pointer not %d-byte aligned: 0x%" PRIxPTR "\n",
                        STACK_ALIGN, sp);
            }
        }
    }
}

static void check_clobber(int from, int to)
{
    checkasm_declare(void, int);

    for (int reg = from; reg < to; reg++) {
        noop_func *clobber = get_clobber(reg);
        if (!clobber)
            break;

        if (checkasm_check_func(clobber, "clobber_r%d", reg)) {
            checkasm_call_new(0);
        }
    }

    checkasm_report("clobber");
}

static void test_copy_emms(copy_func fun, const char *name)
{
    CHECKASM_ALIGN(uint8_t c_dst[256]);
    CHECKASM_ALIGN(uint8_t a_dst[256]);
    CHECKASM_ALIGN(uint8_t src[256]);
    INITIALIZE_BUF(src);

    checkasm_declare_emms(SELFTEST_CPU_FLAG_MMX, void, uint8_t *dest,
                          const uint8_t *src, size_t n);

    for (size_t w = 8; w <= 256; w *= 2) {
        if (checkasm_check_func(fun, "%s_%zu", name, w)) {
            CLEAR_BUF(c_dst);
            CLEAR_BUF(a_dst);

            checkasm_call_ref(c_dst, src, w);
            checkasm_call_new(a_dst, src, w);
            checkasm_check(uint8_t, c_dst, 0, a_dst, 0, 256, 1, "dst data");
            checkasm_bench_new(a_dst, src, w);
        }
    }

    checkasm_report("%s", name);
}

void selftest_check_x86(void)
{
    selftest_test_copy(get_copy_x86(), "copy", 1);
    test_copy_emms(get_copy_noemms_mmx(), "copy_noemms");
    check_stack_alignment();
    check_clobber(0, NUM_SAFE);

    if (!checkasm_should_fail(SELFTEST_CPU_FLAG_X86))
        return;

    selftest_test_noop(get_sigill_x86(), "sigill");
    selftest_test_noop(get_corrupt_stack_x86(), "corrupt_stack");
    selftest_test_copy(get_copy_noemms_mmx(), "noemms", 8);
    check_clobber(NUM_SAFE, NUM_REGS);

    if (checkasm_get_check_vzeroupper())
        selftest_test_copy(get_copy_novzeroupper_avx2(), "novzeroupper", 32);
}

#endif

Messung
CHZG
83988688

¤ Dauer der Verarbeitung: 0.2 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=1104857
#Domains=418089