mirror of
https://github.com/memtest86plus/memtest86plus.git
synced 2025-02-25 18:55:23 -06:00
Use atomic memory read/write functions in tests.
This ensures compiler optimisations won't interfere with the tests.
This commit is contained in:
parent
eb58a63ad4
commit
11c0c6c2f5
60
system/memrw64.h
Normal file
60
system/memrw64.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
#ifndef MEMRW64_H
|
||||||
|
#define MEMRW64_H
|
||||||
|
/*
|
||||||
|
* Provides some 64-bit memory access functions. These stop the compiler
|
||||||
|
* optimizing accesses which need to be ordered and atomic. Mostly used
|
||||||
|
* for accessing memory-mapped hardware registers.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Martin Whitaker.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reads and returns the value stored in the 64-bit memory location pointed
|
||||||
|
* to by ptr.
|
||||||
|
*/
|
||||||
|
static inline uint64_t read64(const volatile uint64_t *ptr)
|
||||||
|
{
|
||||||
|
uint64_t val;
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"movq %1, %0"
|
||||||
|
: "=r" (val)
|
||||||
|
: "m" (*ptr)
|
||||||
|
: "memory"
|
||||||
|
);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Writes val to the 64-bit memory location pointed to by ptr.
|
||||||
|
*/
|
||||||
|
static inline void write64(const volatile uint64_t *ptr, uint64_t val)
|
||||||
|
{
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"movq %1, %0"
|
||||||
|
:
|
||||||
|
: "m" (*ptr),
|
||||||
|
"r" (val)
|
||||||
|
: "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Writes val to the 64-bit memory location pointed to by ptr. Reads it
|
||||||
|
* back (and discards it) to ensure the write is complete.
|
||||||
|
*/
|
||||||
|
static inline void flush64(const volatile uint64_t *ptr, uint64_t val)
|
||||||
|
{
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"movl %1, %0\n"
|
||||||
|
"movl %0, %1"
|
||||||
|
:
|
||||||
|
: "m" (*ptr),
|
||||||
|
"r" (val)
|
||||||
|
: "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MEMRW64_H
|
@ -1,5 +1,5 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
// Copyright (C) 2020 Martin Whitaker.
|
// Copyright (C) 2020-2021 Martin Whitaker.
|
||||||
//
|
//
|
||||||
// Derived from an extract of memtest86+ test.c:
|
// Derived from an extract of memtest86+ test.c:
|
||||||
//
|
//
|
||||||
@ -56,7 +56,7 @@ int test_addr_walk1(int my_vcpu)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
testword_t expect = invert ^ (testword_t)p1;
|
testword_t expect = invert ^ (testword_t)p1;
|
||||||
*p1 = expect;
|
write_word(p1, expect);
|
||||||
|
|
||||||
// Walking one on our second address.
|
// Walking one on our second address.
|
||||||
uintptr_t mask2 = sizeof(testword_t);
|
uintptr_t mask2 = sizeof(testword_t);
|
||||||
@ -69,12 +69,12 @@ int test_addr_walk1(int my_vcpu)
|
|||||||
if (p2 > (testword_t *)pe) {
|
if (p2 > (testword_t *)pe) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
*p2 = ~invert ^ (testword_t)p2;
|
write_word(p2, ~invert ^ (testword_t)p2);
|
||||||
|
|
||||||
testword_t actual = *p1;
|
testword_t actual = read_word(p1);
|
||||||
if (unlikely(actual != expect)) {
|
if (unlikely(actual != expect)) {
|
||||||
addr_error(p1, p2, expect, actual);
|
addr_error(p1, p2, expect, actual);
|
||||||
*p1 = expect; // recover from error
|
write_word(p1, expect); // recover from error
|
||||||
}
|
}
|
||||||
} while (mask2);
|
} while (mask2);
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
// Copyright (C) 2020 Martin Whitaker.
|
// Copyright (C) 2020-2021 Martin Whitaker.
|
||||||
//
|
//
|
||||||
// Derived from an extract of memtest86+ test.c:
|
// Derived from an extract of memtest86+ test.c:
|
||||||
//
|
//
|
||||||
@ -59,7 +59,7 @@ static int pattern_fill(int my_vcpu, testword_t pattern)
|
|||||||
}
|
}
|
||||||
test_addr[my_vcpu] = (uintptr_t)p;
|
test_addr[my_vcpu] = (uintptr_t)p;
|
||||||
do {
|
do {
|
||||||
*p = pattern;
|
write_word(p, pattern);
|
||||||
} while (p++ < pe); // test before increment in case pointer overflows
|
} while (p++ < pe); // test before increment in case pointer overflows
|
||||||
do_tick(my_vcpu);
|
do_tick(my_vcpu);
|
||||||
BAILOUT;
|
BAILOUT;
|
||||||
@ -95,7 +95,7 @@ static int pattern_check(int my_vcpu, testword_t pattern)
|
|||||||
}
|
}
|
||||||
test_addr[my_vcpu] = (uintptr_t)p;
|
test_addr[my_vcpu] = (uintptr_t)p;
|
||||||
do {
|
do {
|
||||||
testword_t actual = *p;
|
testword_t actual = read_word(p);
|
||||||
if (unlikely(actual != pattern)) {
|
if (unlikely(actual != pattern)) {
|
||||||
data_error(p, pattern, actual, true);
|
data_error(p, pattern, actual, true);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
// Copyright (C) 2020 Martin Whitaker.
|
// Copyright (C) 2020-2021 Martin Whitaker.
|
||||||
//
|
//
|
||||||
// Derived from an extract of memtest86+ test.c:
|
// Derived from an extract of memtest86+ test.c:
|
||||||
//
|
//
|
||||||
@ -60,22 +60,22 @@ int test_block_move(int my_vcpu, int iterations)
|
|||||||
testword_t pattern1 = 1;
|
testword_t pattern1 = 1;
|
||||||
do {
|
do {
|
||||||
testword_t pattern2 = ~pattern1;
|
testword_t pattern2 = ~pattern1;
|
||||||
p[ 0] = pattern1;
|
write_word(p + 0, pattern1);
|
||||||
p[ 1] = pattern1;
|
write_word(p + 1, pattern1);
|
||||||
p[ 2] = pattern1;
|
write_word(p + 2, pattern1);
|
||||||
p[ 3] = pattern1;
|
write_word(p + 3, pattern1);
|
||||||
p[ 4] = pattern2;
|
write_word(p + 4, pattern2);
|
||||||
p[ 5] = pattern2;
|
write_word(p + 5, pattern2);
|
||||||
p[ 6] = pattern1;
|
write_word(p + 6, pattern1);
|
||||||
p[ 7] = pattern1;
|
write_word(p + 7, pattern1);
|
||||||
p[ 8] = pattern1;
|
write_word(p + 8, pattern1);
|
||||||
p[ 9] = pattern1;
|
write_word(p + 9, pattern1);
|
||||||
p[10] = pattern2;
|
write_word(p + 10, pattern2);
|
||||||
p[11] = pattern2;
|
write_word(p + 11, pattern2);
|
||||||
p[12] = pattern1;
|
write_word(p + 12, pattern1);
|
||||||
p[13] = pattern1;
|
write_word(p + 13, pattern1);
|
||||||
p[14] = pattern2;
|
write_word(p + 14, pattern2);
|
||||||
p[15] = pattern2;
|
write_word(p + 15, pattern2);
|
||||||
pattern1 = pattern1 << 1 | pattern1 >> (TESTWORD_WIDTH - 1); // rotate left
|
pattern1 = pattern1 << 1 | pattern1 >> (TESTWORD_WIDTH - 1); // rotate left
|
||||||
} while (p <= (pe - 16) && (p += 16)); // test before increment in case pointer overflows
|
} while (p <= (pe - 16) && (p += 16)); // test before increment in case pointer overflows
|
||||||
do_tick(my_vcpu);
|
do_tick(my_vcpu);
|
||||||
@ -219,8 +219,10 @@ int test_block_move(int my_vcpu, int iterations)
|
|||||||
}
|
}
|
||||||
test_addr[my_vcpu] = (uintptr_t)p;
|
test_addr[my_vcpu] = (uintptr_t)p;
|
||||||
do {
|
do {
|
||||||
if (unlikely(p[0] != p[1])) {
|
testword_t p0 = read_word(p + 0);
|
||||||
data_error(p, p[0], p[1], false);
|
testword_t p1 = read_word(p + 1);
|
||||||
|
if (unlikely(p0 != p1)) {
|
||||||
|
data_error(p, p0, p1, false);
|
||||||
}
|
}
|
||||||
} while (p <= (pe - 2) && (p += 2)); // test before increment in case pointer overflows
|
} while (p <= (pe - 2) && (p += 2)); // test before increment in case pointer overflows
|
||||||
do_tick(my_vcpu);
|
do_tick(my_vcpu);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
// Copyright (C) 2020 Martin Whitaker.
|
// Copyright (C) 2020-2021 Martin Whitaker.
|
||||||
//
|
//
|
||||||
// Derived from an extract of memtest86+ test.c:
|
// Derived from an extract of memtest86+ test.c:
|
||||||
//
|
//
|
||||||
@ -59,7 +59,7 @@ int test_modulo_n(int my_vcpu, int iterations, testword_t pattern1, testword_t p
|
|||||||
}
|
}
|
||||||
test_addr[my_vcpu] = (uintptr_t)p;
|
test_addr[my_vcpu] = (uintptr_t)p;
|
||||||
do {
|
do {
|
||||||
*p = pattern1;
|
write_word(p, pattern1);
|
||||||
} while (p <= (pe - n) && (p += n)); // test before increment in case pointer overflows
|
} while (p <= (pe - n) && (p += n)); // test before increment in case pointer overflows
|
||||||
do_tick(my_vcpu);
|
do_tick(my_vcpu);
|
||||||
BAILOUT;
|
BAILOUT;
|
||||||
@ -92,7 +92,7 @@ int test_modulo_n(int my_vcpu, int iterations, testword_t pattern1, testword_t p
|
|||||||
test_addr[my_vcpu] = (uintptr_t)p;
|
test_addr[my_vcpu] = (uintptr_t)p;
|
||||||
do {
|
do {
|
||||||
if (k != offset) {
|
if (k != offset) {
|
||||||
*p = pattern2;
|
write_word(p, pattern2);
|
||||||
}
|
}
|
||||||
k++;
|
k++;
|
||||||
if (k == n) {
|
if (k == n) {
|
||||||
@ -129,7 +129,7 @@ int test_modulo_n(int my_vcpu, int iterations, testword_t pattern1, testword_t p
|
|||||||
}
|
}
|
||||||
test_addr[my_vcpu] = (uintptr_t)p;
|
test_addr[my_vcpu] = (uintptr_t)p;
|
||||||
do {
|
do {
|
||||||
testword_t actual = *p;
|
testword_t actual = read_word(p);
|
||||||
if (unlikely(actual != pattern1)) {
|
if (unlikely(actual != pattern1)) {
|
||||||
data_error(p, pattern1, actual, true);
|
data_error(p, pattern1, actual, true);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
// Copyright (C) 2020 Martin Whitaker.
|
// Copyright (C) 2020-2021 Martin Whitaker.
|
||||||
//
|
//
|
||||||
// Derived from an extract of memtest86+ test.c:
|
// Derived from an extract of memtest86+ test.c:
|
||||||
//
|
//
|
||||||
@ -83,7 +83,7 @@ int test_mov_inv_fixed(int my_vcpu, int iterations, testword_t pattern1, testwor
|
|||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
do {
|
do {
|
||||||
*p = pattern1;
|
write_word(p, pattern1);
|
||||||
} while (p++ < pe); // test before increment in case pointer overflows
|
} while (p++ < pe); // test before increment in case pointer overflows
|
||||||
#endif
|
#endif
|
||||||
do_tick(my_vcpu);
|
do_tick(my_vcpu);
|
||||||
@ -116,11 +116,11 @@ int test_mov_inv_fixed(int my_vcpu, int iterations, testword_t pattern1, testwor
|
|||||||
}
|
}
|
||||||
test_addr[my_vcpu] = (uintptr_t)p;
|
test_addr[my_vcpu] = (uintptr_t)p;
|
||||||
do {
|
do {
|
||||||
testword_t actual = *p;
|
testword_t actual = read_word(p);
|
||||||
if (unlikely(actual != pattern1)) {
|
if (unlikely(actual != pattern1)) {
|
||||||
data_error(p, pattern1, actual, true);
|
data_error(p, pattern1, actual, true);
|
||||||
}
|
}
|
||||||
*p = pattern2;
|
write_word(p, pattern2);
|
||||||
} while (p++ < pe); // test before increment in case pointer overflows
|
} while (p++ < pe); // test before increment in case pointer overflows
|
||||||
do_tick(my_vcpu);
|
do_tick(my_vcpu);
|
||||||
BAILOUT;
|
BAILOUT;
|
||||||
@ -149,11 +149,11 @@ int test_mov_inv_fixed(int my_vcpu, int iterations, testword_t pattern1, testwor
|
|||||||
}
|
}
|
||||||
test_addr[my_vcpu] = (uintptr_t)p;
|
test_addr[my_vcpu] = (uintptr_t)p;
|
||||||
do {
|
do {
|
||||||
testword_t actual = *p;
|
testword_t actual = read_word(p);
|
||||||
if (unlikely(actual != pattern2)) {
|
if (unlikely(actual != pattern2)) {
|
||||||
data_error(p, pattern2, actual, true);
|
data_error(p, pattern2, actual, true);
|
||||||
}
|
}
|
||||||
*p = pattern1;
|
write_word(p, pattern1);
|
||||||
} while (p-- > ps); // test before decrement in case pointer overflows
|
} while (p-- > ps); // test before decrement in case pointer overflows
|
||||||
do_tick(my_vcpu);
|
do_tick(my_vcpu);
|
||||||
BAILOUT;
|
BAILOUT;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
// Copyright (C) 2020 Martin Whitaker.
|
// Copyright (C) 2020-2021 Martin Whitaker.
|
||||||
//
|
//
|
||||||
// Derived from an extract of memtest86+ test.c:
|
// Derived from an extract of memtest86+ test.c:
|
||||||
//
|
//
|
||||||
@ -69,7 +69,7 @@ int test_mov_inv_random(int my_vcpu)
|
|||||||
}
|
}
|
||||||
test_addr[my_vcpu] = (uintptr_t)p;
|
test_addr[my_vcpu] = (uintptr_t)p;
|
||||||
do {
|
do {
|
||||||
*p = random(my_vcpu);
|
write_word(p, random(my_vcpu));
|
||||||
} while (p++ < pe); // test before increment in case pointer overflows
|
} while (p++ < pe); // test before increment in case pointer overflows
|
||||||
do_tick(my_vcpu);
|
do_tick(my_vcpu);
|
||||||
BAILOUT;
|
BAILOUT;
|
||||||
@ -104,11 +104,11 @@ int test_mov_inv_random(int my_vcpu)
|
|||||||
test_addr[my_vcpu] = (uintptr_t)p;
|
test_addr[my_vcpu] = (uintptr_t)p;
|
||||||
do {
|
do {
|
||||||
testword_t expect = random(my_vcpu) ^ invert;
|
testword_t expect = random(my_vcpu) ^ invert;
|
||||||
testword_t actual = *p;
|
testword_t actual = read_word(p);
|
||||||
if (unlikely(actual != expect)) {
|
if (unlikely(actual != expect)) {
|
||||||
data_error(p, expect, actual, true);
|
data_error(p, expect, actual, true);
|
||||||
}
|
}
|
||||||
*p = ~expect;
|
write_word(p, ~expect);
|
||||||
} while (p++ < pe); // test before increment in case pointer overflows
|
} while (p++ < pe); // test before increment in case pointer overflows
|
||||||
do_tick(my_vcpu);
|
do_tick(my_vcpu);
|
||||||
BAILOUT;
|
BAILOUT;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
// Copyright (C) 2020 Martin Whitaker.
|
// Copyright (C) 2020-2021 Martin Whitaker.
|
||||||
//
|
//
|
||||||
// Derived from an extract of memtest86+ test.c:
|
// Derived from an extract of memtest86+ test.c:
|
||||||
//
|
//
|
||||||
@ -60,7 +60,7 @@ int test_mov_inv_walk1(int my_vcpu, int iterations, int offset, bool inverse)
|
|||||||
}
|
}
|
||||||
test_addr[my_vcpu] = (uintptr_t)p;
|
test_addr[my_vcpu] = (uintptr_t)p;
|
||||||
do {
|
do {
|
||||||
*p = inverse ? ~pattern : pattern;
|
write_word(p, inverse ? ~pattern : pattern);
|
||||||
pattern = pattern << 1 | pattern >> (TESTWORD_WIDTH - 1); // rotate left
|
pattern = pattern << 1 | pattern >> (TESTWORD_WIDTH - 1); // rotate left
|
||||||
} while (p++ < pe); // test before increment in case pointer overflows
|
} while (p++ < pe); // test before increment in case pointer overflows
|
||||||
do_tick(my_vcpu);
|
do_tick(my_vcpu);
|
||||||
@ -96,11 +96,11 @@ int test_mov_inv_walk1(int my_vcpu, int iterations, int offset, bool inverse)
|
|||||||
test_addr[my_vcpu] = (uintptr_t)p;
|
test_addr[my_vcpu] = (uintptr_t)p;
|
||||||
do {
|
do {
|
||||||
testword_t expect = inverse ? ~pattern : pattern;
|
testword_t expect = inverse ? ~pattern : pattern;
|
||||||
testword_t actual = *p;
|
testword_t actual = read_word(p);
|
||||||
if (unlikely(actual != expect)) {
|
if (unlikely(actual != expect)) {
|
||||||
data_error(p, expect, actual, true);
|
data_error(p, expect, actual, true);
|
||||||
}
|
}
|
||||||
*p = ~expect;
|
write_word(p, ~expect);
|
||||||
pattern = pattern << 1 | pattern >> (TESTWORD_WIDTH - 1); // rotate left
|
pattern = pattern << 1 | pattern >> (TESTWORD_WIDTH - 1); // rotate left
|
||||||
} while (p++ < pe); // test before increment in case pointer overflows
|
} while (p++ < pe); // test before increment in case pointer overflows
|
||||||
do_tick(my_vcpu);
|
do_tick(my_vcpu);
|
||||||
@ -132,11 +132,11 @@ int test_mov_inv_walk1(int my_vcpu, int iterations, int offset, bool inverse)
|
|||||||
do {
|
do {
|
||||||
pattern = pattern >> 1 | pattern << (TESTWORD_WIDTH - 1); // rotate right
|
pattern = pattern >> 1 | pattern << (TESTWORD_WIDTH - 1); // rotate right
|
||||||
testword_t expect = inverse ? pattern : ~pattern;
|
testword_t expect = inverse ? pattern : ~pattern;
|
||||||
testword_t actual = *p;
|
testword_t actual = read_word(p);
|
||||||
if (unlikely(actual != expect)) {
|
if (unlikely(actual != expect)) {
|
||||||
data_error(p, expect, actual, true);
|
data_error(p, expect, actual, true);
|
||||||
}
|
}
|
||||||
*p = ~expect;
|
write_word(p, ~expect);
|
||||||
} while (p-- > ps); // test before decrement in case pointer overflows
|
} while (p-- > ps); // test before decrement in case pointer overflows
|
||||||
do_tick(my_vcpu);
|
do_tick(my_vcpu);
|
||||||
BAILOUT;
|
BAILOUT;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
// Copyright (C) 2020 Martin Whitaker.
|
// Copyright (C) 2020-2021 Martin Whitaker.
|
||||||
//
|
//
|
||||||
// Derived from an extract of memtest86+ test.c:
|
// Derived from an extract of memtest86+ test.c:
|
||||||
//
|
//
|
||||||
@ -58,7 +58,7 @@ static int pattern_fill(int my_vcpu, testword_t offset)
|
|||||||
}
|
}
|
||||||
test_addr[my_vcpu] = (uintptr_t)p;
|
test_addr[my_vcpu] = (uintptr_t)p;
|
||||||
do {
|
do {
|
||||||
*p = (testword_t)p + offset;
|
write_word(p, (testword_t)p + offset);
|
||||||
} while (p++ < pe); // test before increment in case pointer overflows
|
} while (p++ < pe); // test before increment in case pointer overflows
|
||||||
do_tick(my_vcpu);
|
do_tick(my_vcpu);
|
||||||
BAILOUT;
|
BAILOUT;
|
||||||
@ -96,7 +96,7 @@ static int pattern_check(int my_vcpu, testword_t offset)
|
|||||||
test_addr[my_vcpu] = (uintptr_t)p;
|
test_addr[my_vcpu] = (uintptr_t)p;
|
||||||
do {
|
do {
|
||||||
testword_t expect = (testword_t)p + offset;
|
testword_t expect = (testword_t)p + offset;
|
||||||
testword_t actual = *p;
|
testword_t actual = read_word(p);
|
||||||
if (unlikely(actual != expect)) {
|
if (unlikely(actual != expect)) {
|
||||||
data_error(p, expect, actual, true);
|
data_error(p, expect, actual, true);
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
* Provides some common definitions and helper functions for the memory
|
* Provides some common definitions and helper functions for the memory
|
||||||
* tests.
|
* tests.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2020 Martin Whitaker.
|
* Copyright (C) 2020-2021 Martin Whitaker.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
@ -13,6 +13,19 @@
|
|||||||
|
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test word atomic read and write functions.
|
||||||
|
*/
|
||||||
|
#ifdef __x86_64__
|
||||||
|
#include "memrw64.h"
|
||||||
|
#define read_word read64
|
||||||
|
#define write_word write64
|
||||||
|
#else
|
||||||
|
#include "memrw32.h"
|
||||||
|
#define read_word read32
|
||||||
|
#define write_word write32
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A wrapper for guiding branch prediction.
|
* A wrapper for guiding branch prediction.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user