Skip to content

Instantly share code, notes, and snippets.

@heiher
Last active August 27, 2021 17:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save heiher/9edc63ffb70c10d2c3f807797c7c15c7 to your computer and use it in GitHub Desktop.
Save heiher/9edc63ffb70c10d2c3f807797c7c15c7 to your computer and use it in GitHub Desktop.
LoongArch64 load immediate test generator
/*
* 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