Last active
August 27, 2021 17:17
-
-
Save heiher/9edc63ffb70c10d2c3f807797c7c15c7 to your computer and use it in GitHub Desktop.
LoongArch64 load immediate test generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* li-test-gen.c | |
* wangrui <wangrui@loongson.cn> | |
* | |
* gcc -o li-test-gen li-test-gen.c | |
* ./li-test-gen | |
* gcc -o li-test li-test.c li-test.S | |
* ./li-test | |
*/ | |
#include <stdio.h> | |
#include <stdint.h> | |
#define nth_bit(n) (((n) >= 64) ? 0 : (1L << (n))) | |
#define right_n_bits(n) (nth_bit (n) - 1) | |
static intptr_t | |
mask_bits (intptr_t x, intptr_t m) | |
{ | |
return x & m; | |
} | |
static intptr_t | |
bitfield (intptr_t x, int start_bit_no, int field_length) | |
{ | |
return mask_bits (x >> start_bit_no, right_n_bits (field_length)); | |
} | |
static int | |
simm12 (int x) | |
{ | |
return (x << 20) >> 20; | |
} | |
static int | |
simm20 (int x) | |
{ | |
return (x << 12) >> 12; | |
} | |
static void | |
li (long value, FILE *fp) | |
{ | |
long hi12 = bitfield (value, 52, 12); | |
long lo52 = bitfield (value, 0, 52); | |
fprintf (fp, "\t.global li%016lx\n", value); | |
fprintf (fp, "li%016lx:\n", value); | |
if (hi12 != 0 && lo52 == 0) { | |
fprintf (fp, "\tlu52i.d $a0, $zero, %d\n", (hi12 << 52) >> 52); | |
} else { | |
long hi20 = bitfield (value, 32, 20); | |
long lo20 = bitfield (value, 12, 20); | |
long lo12 = bitfield (value, 0, 12); | |
if (lo20 == 0) { | |
fprintf (fp, "\tori $a0, $zero, %d\n", lo12); | |
} else if (bitfield (simm12 (lo12), 12, 20) == lo20) { | |
fprintf (fp, "\taddi.w $a0, $zero, %d\n", (lo12 << 52) >> 52); | |
} else { | |
fprintf (fp, "\tlu12i.w $a0, %d\n", (lo20 << 44) >> 44); | |
if (lo12 != 0) | |
fprintf (fp, "\tori $a0, $a0, %d\n", lo12); | |
} | |
if (hi20 != bitfield (simm20 (lo20), 20, 20)) | |
fprintf (fp, "\tlu32i.d $a0, %d\n", (hi20 << 44) >> 44); | |
if (hi12 != bitfield (simm20 (hi20), 20, 12)) | |
fprintf (fp, "\tlu52i.d $a0, $a0, %d\n", (hi12 << 52) >> 52); | |
} | |
fprintf (fp, "\tjirl $zero, $ra, 0\n"); | |
} | |
int | |
main (int argc, char *argv[]) | |
{ | |
unsigned long lo12[] = { | |
0x0000000000000000UL, | |
0x00000000000007ffUL, | |
0x0000000000000800UL, | |
0x0000000000000fffUL, | |
}; | |
unsigned long lo20[] = { | |
0x0000000000000000UL, | |
0x000000007ffff000UL, | |
0x0000000080000000UL, | |
0x00000000fffff000UL, | |
}; | |
unsigned long hi20[] = { | |
0x0000000000000000UL, | |
0x0007ffff00000000UL, | |
0x0008000000000000UL, | |
0x000fffff00000000UL, | |
}; | |
unsigned long hi12[] = { | |
0x0000000000000000UL, | |
0x7ff0000000000000UL, | |
0x8000000000000000UL, | |
0xfff0000000000000UL, | |
}; | |
int a, b, c, d; | |
FILE *fp; | |
fp = fopen ("li-test.S", "w+"); | |
for (a = 0; a < 4; a++) { | |
for (b = 0; b < 4; b++) { | |
for (c = 0; c < 4; c++) { | |
for (d = 0; d < 4; d++) { | |
li (lo12[d] | lo20[c] | hi20[b] | hi12[a], fp); | |
} | |
} | |
} | |
} | |
fclose (fp); | |
fp = fopen ("li-test.c", "w+"); | |
fprintf (fp, "#include <stdio.h>\n"); | |
fprintf (fp, "#include <stdlib.h>\n\n"); | |
for (a = 0; a < 4; a++) { | |
for (b = 0; b < 4; b++) { | |
for (c = 0; c < 4; c++) { | |
for (d = 0; d < 4; d++) { | |
fprintf (fp, "extern unsigned long li%016lx(void);\n", | |
lo12[d] | lo20[c] | hi20[b] | hi12[a]); | |
} | |
} | |
} | |
} | |
fprintf (fp, "\nint\n"); | |
fprintf (fp, "main(int argc, char *argv[])\n"); | |
fprintf (fp, "{\n"); | |
fprintf (fp, "\tunsigned long val;\n"); | |
for (a = 0; a < 4; a++) { | |
for (b = 0; b < 4; b++) { | |
for (c = 0; c < 4; c++) { | |
for (d = 0; d < 4; d++) { | |
fprintf (fp, "\tval = li%016lx();\n", | |
lo12[d] | lo20[c] | hi20[b] | hi12[a]); | |
fprintf (fp, "\tif (val != 0x%016lxUL) {\n", | |
lo12[d] | lo20[c] | hi20[b] | hi12[a]); | |
fprintf ( | |
fp, | |
"\t\tprintf(\"FAIL: %%016lx (line %%d)\\n\", val, __LINE__);\n"); | |
fprintf (fp, "\t\texit(1);\n"); | |
fprintf (fp, "\t}\n"); | |
} | |
} | |
} | |
} | |
fprintf (fp, "\treturn 0;\n"); | |
fprintf (fp, "}\n"); | |
fclose (fp); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment