From 27dca7419e3b5f8df2fdb9aae45481aea6754bc7 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Thu, 14 Jul 2022 02:21:54 -0700 Subject: [PATCH] add jit_test for testing icbi and isync TODO: integrate into unit test framework --- .gitignore | 2 ++ jit_test.cpp | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++ jit_test.sh | 14 +++++++++++ 3 files changed, 85 insertions(+) create mode 100644 jit_test.cpp create mode 100755 jit_test.sh diff --git a/.gitignore b/.gitignore index 9b0bf1dd..40029618 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ dist *.vcd *.gtkw *.egg-info +/jit_test +/jit_test.o diff --git a/jit_test.cpp b/jit_test.cpp new file mode 100644 index 00000000..78d3b5ab --- /dev/null +++ b/jit_test.cpp @@ -0,0 +1,69 @@ +typedef __UINT8_TYPE__ uint8_t; +typedef __UINT16_TYPE__ uint16_t; +typedef __UINT32_TYPE__ uint32_t; +typedef __UINT64_TYPE__ uint64_t; +typedef __INT8_TYPE__ int8_t; +typedef __INT16_TYPE__ int16_t; +typedef __INT32_TYPE__ int32_t; +typedef __INT64_TYPE__ int64_t; + +/// returns `v + inc` by jitting an addi instruction and executing it +/// requires .wtext section to be writable +extern "C" uint64_t jit_test(uint64_t v, int16_t inc) __attribute__((noinline, section(".wtext"))); +extern "C" uint64_t jit_test(uint64_t v, int16_t inc) { + register uint64_t r3 asm("r3"); + r3 = v; + uint32_t instr = 0x38630000 | (uint16_t)inc; // addi 3, 3, inc + asm("mflr 5\n\t" + "bl 0f\n\t" + "0: mflr 4\n\t" + "addi 4, 4, 1f - 0b\n\t" + "stw %1, 0(4)\n\t" + "dcbf 0, 4\n\t" + "sync\n\t" + "icbi 0, 4\n\t" + "isync\n\t" + "1: addi 3, 3, 0x1234\n\t" + "mtlr 5" + : "+b"(r3) : "b"(instr) : "r4", "r5"); + return r3; +} + +extern "C" uint64_t parse_hex(const char *s) __attribute__((noinline)); +extern "C" uint64_t parse_hex(const char *s) { + uint64_t retval = 0; + bool negate = *s == '-'; + if(*s == '-' || *s == '+') + s++; + if(*s == '0' && (s[1] == 'x' || s[1] == 'X')) + s += 2; + if(!*s) + return -1; + for(; *s; s++) { + uint64_t digit; + if(*s >= '0' && *s <= '9') + digit = *s - '0'; + else if(*s >= 'a' && *s <= 'f') + digit = *s - 'a' + 0xA; + else if(*s >= 'A' && *s <= 'F') + digit = *s - 'A' + 0xA; + else + return -1; + if(retval >= 1ULL << 60) + return -1; + retval <<= 4; + retval += digit; + } + return retval; +} + +extern "C" int main(int argc, char **argv) { + uint64_t a = 1, b = 2; + if(argc > 1) + a = parse_hex(argv[1]); + if(argc > 2) + b = parse_hex(argv[2]); + register long r3 asm("r3") = jit_test(a, b); + register long r0 asm("r0") = 1; // exit + asm volatile("sc" : : "r"(r0), "b"(r3)); +} diff --git a/jit_test.sh b/jit_test.sh new file mode 100755 index 00000000..c32ce1cb --- /dev/null +++ b/jit_test.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -xe +clang --target=powerpc64le-linux-gnu -Og -g -c -o jit_test.o jit_test.cpp +powerpc64le-linux-gnu-objcopy --set-section-flags .wtext=CONTENTS,ALLOC,LOAD,CODE jit_test.o +powerpc64le-linux-gnu-gcc -static -o jit_test jit_test.o +set +e +for i in {-3..3}; do + printf -v ih "%#x" "$i" + for j in {-3..3}; do + printf -v jh "%#x" "$j" + ./jit_test "$ih" "$jh" + echo "return value $? -- should be $(((i + j) & 0xFF))" + done +done -- 2.30.2