forked from mirror/qemu
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
191 lines
5.4 KiB
C
191 lines
5.4 KiB
C
/*
|
|
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
int err;
|
|
|
|
#define NBITS 8
|
|
#define SIZE (1 << NBITS)
|
|
|
|
long long dbuf[SIZE] __attribute__((aligned(1 << 16))) = {0};
|
|
int wbuf[SIZE] __attribute__((aligned(1 << 16))) = {0};
|
|
short hbuf[SIZE] __attribute__((aligned(1 << 16))) = {0};
|
|
unsigned char bbuf[SIZE] __attribute__((aligned(1 << 16))) = {0};
|
|
|
|
/*
|
|
* We use the C preporcessor to deal with the combinations of types
|
|
*/
|
|
|
|
#define BREV_LOAD(SZ, RES, ADDR, INC) \
|
|
__asm__( \
|
|
"m0 = %2\n\t" \
|
|
"%0 = mem" #SZ "(%1++m0:brev)\n\t" \
|
|
: "=r"(RES), "+r"(ADDR) \
|
|
: "r"(INC) \
|
|
: "m0")
|
|
|
|
#define BREV_LOAD_b(RES, ADDR, INC) \
|
|
BREV_LOAD(b, RES, ADDR, INC)
|
|
#define BREV_LOAD_ub(RES, ADDR, INC) \
|
|
BREV_LOAD(ub, RES, ADDR, INC)
|
|
#define BREV_LOAD_h(RES, ADDR, INC) \
|
|
BREV_LOAD(h, RES, ADDR, INC)
|
|
#define BREV_LOAD_uh(RES, ADDR, INC) \
|
|
BREV_LOAD(uh, RES, ADDR, INC)
|
|
#define BREV_LOAD_w(RES, ADDR, INC) \
|
|
BREV_LOAD(w, RES, ADDR, INC)
|
|
#define BREV_LOAD_d(RES, ADDR, INC) \
|
|
BREV_LOAD(d, RES, ADDR, INC)
|
|
|
|
#define BREV_STORE(SZ, PART, ADDR, VAL, INC) \
|
|
__asm__( \
|
|
"m0 = %2\n\t" \
|
|
"mem" #SZ "(%0++m0:brev) = %1" PART "\n\t" \
|
|
: "+r"(ADDR) \
|
|
: "r"(VAL), "r"(INC) \
|
|
: "m0", "memory")
|
|
|
|
#define BREV_STORE_b(ADDR, VAL, INC) \
|
|
BREV_STORE(b, "", ADDR, VAL, INC)
|
|
#define BREV_STORE_h(ADDR, VAL, INC) \
|
|
BREV_STORE(h, "", ADDR, VAL, INC)
|
|
#define BREV_STORE_f(ADDR, VAL, INC) \
|
|
BREV_STORE(h, ".H", ADDR, VAL, INC)
|
|
#define BREV_STORE_w(ADDR, VAL, INC) \
|
|
BREV_STORE(w, "", ADDR, VAL, INC)
|
|
#define BREV_STORE_d(ADDR, VAL, INC) \
|
|
BREV_STORE(d, "", ADDR, VAL, INC)
|
|
|
|
#define BREV_STORE_NEW(SZ, ADDR, VAL, INC) \
|
|
__asm__( \
|
|
"m0 = %2\n\t" \
|
|
"{\n\t" \
|
|
" r5 = %1\n\t" \
|
|
" mem" #SZ "(%0++m0:brev) = r5.new\n\t" \
|
|
"}\n\t" \
|
|
: "+r"(ADDR) \
|
|
: "r"(VAL), "r"(INC) \
|
|
: "r5", "m0", "memory")
|
|
|
|
#define BREV_STORE_bnew(ADDR, VAL, INC) \
|
|
BREV_STORE_NEW(b, ADDR, VAL, INC)
|
|
#define BREV_STORE_hnew(ADDR, VAL, INC) \
|
|
BREV_STORE_NEW(h, ADDR, VAL, INC)
|
|
#define BREV_STORE_wnew(ADDR, VAL, INC) \
|
|
BREV_STORE_NEW(w, ADDR, VAL, INC)
|
|
|
|
int bitreverse(int x)
|
|
{
|
|
int result = 0;
|
|
int i;
|
|
for (i = 0; i < NBITS; i++) {
|
|
result <<= 1;
|
|
result |= x & 1;
|
|
x >>= 1;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int sext8(int x)
|
|
{
|
|
return (x << 24) >> 24;
|
|
}
|
|
|
|
void check(int i, long long result, long long expect)
|
|
{
|
|
if (result != expect) {
|
|
printf("ERROR(%d): 0x%04llx != 0x%04llx\n", i, result, expect);
|
|
err++;
|
|
}
|
|
}
|
|
|
|
#define TEST_BREV_LOAD(SZ, TYPE, BUF, SHIFT, EXP) \
|
|
do { \
|
|
p = BUF; \
|
|
for (i = 0; i < SIZE; i++) { \
|
|
TYPE result; \
|
|
BREV_LOAD_##SZ(result, p, 1 << (SHIFT - NBITS)); \
|
|
check(i, result, EXP); \
|
|
} \
|
|
} while (0)
|
|
|
|
#define TEST_BREV_STORE(SZ, TYPE, BUF, VAL, SHIFT) \
|
|
do { \
|
|
p = BUF; \
|
|
memset(BUF, 0xff, sizeof(BUF)); \
|
|
for (i = 0; i < SIZE; i++) { \
|
|
BREV_STORE_##SZ(p, (TYPE)(VAL), 1 << (SHIFT - NBITS)); \
|
|
} \
|
|
for (i = 0; i < SIZE; i++) { \
|
|
check(i, BUF[i], bitreverse(i)); \
|
|
} \
|
|
} while (0)
|
|
|
|
#define TEST_BREV_STORE_NEW(SZ, BUF, SHIFT) \
|
|
do { \
|
|
p = BUF; \
|
|
memset(BUF, 0xff, sizeof(BUF)); \
|
|
for (i = 0; i < SIZE; i++) { \
|
|
BREV_STORE_##SZ(p, i, 1 << (SHIFT - NBITS)); \
|
|
} \
|
|
for (i = 0; i < SIZE; i++) { \
|
|
check(i, BUF[i], bitreverse(i)); \
|
|
} \
|
|
} while (0)
|
|
|
|
/*
|
|
* We'll set high_half[i] = i << 16 for use in the .H form of store
|
|
* which stores from the high half of the word.
|
|
*/
|
|
int high_half[SIZE];
|
|
|
|
int main()
|
|
{
|
|
void *p;
|
|
int i;
|
|
|
|
for (i = 0; i < SIZE; i++) {
|
|
bbuf[i] = bitreverse(i);
|
|
hbuf[i] = bitreverse(i);
|
|
wbuf[i] = bitreverse(i);
|
|
dbuf[i] = bitreverse(i);
|
|
high_half[i] = i << 16;
|
|
}
|
|
|
|
TEST_BREV_LOAD(b, int, bbuf, 16, sext8(i));
|
|
TEST_BREV_LOAD(ub, int, bbuf, 16, i);
|
|
TEST_BREV_LOAD(h, int, hbuf, 15, i);
|
|
TEST_BREV_LOAD(uh, int, hbuf, 15, i);
|
|
TEST_BREV_LOAD(w, int, wbuf, 14, i);
|
|
TEST_BREV_LOAD(d, long long, dbuf, 13, i);
|
|
|
|
TEST_BREV_STORE(b, int, bbuf, i, 16);
|
|
TEST_BREV_STORE(h, int, hbuf, i, 15);
|
|
TEST_BREV_STORE(f, int, hbuf, high_half[i], 15);
|
|
TEST_BREV_STORE(w, int, wbuf, i, 14);
|
|
TEST_BREV_STORE(d, long long, dbuf, i, 13);
|
|
|
|
TEST_BREV_STORE_NEW(bnew, bbuf, 16);
|
|
TEST_BREV_STORE_NEW(hnew, hbuf, 15);
|
|
TEST_BREV_STORE_NEW(wnew, wbuf, 14);
|
|
|
|
puts(err ? "FAIL" : "PASS");
|
|
return err ? 1 : 0;
|
|
}
|