Skip to content

Instantly share code, notes, and snippets.

@heiher
Created November 16, 2023 03:50
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/3c7a2a9e7d05354e818b50d69e40b8cb to your computer and use it in GitHub Desktop.
Save heiher/3c7a2a9e7d05354e818b50d69e40b8cb to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
static unsigned long getLoongArchPage(unsigned long p) {
return p & ~0xfffUL;
}
static unsigned int lo12(unsigned int val) { return val & 0xfff; }
static long
delta (long dest, long pc)
{
long result = getLoongArchPage(dest) - getLoongArchPage(pc);
int negativeA = lo12(dest) > 0x7ff;
int negativeB = (result & 0x80000000) != 0;
// A corner case; directly return the expected result.
if (result == 0xfffffffffffff000 && negativeA)
return 0xffffffff00000000;
if (negativeA)
result += 0x1000;
if (negativeA && !negativeB)
result -= 0x100000000;
else if (!negativeA && negativeB)
result += 0x100000000;
return result;
}
int
test (long dest, long pc)
{
long target;
long delta1;
long delta2;
long delta3;
long delta4;
long pcala_hi20;
long pcala_lo12;
long pcala64_lo20;
long pcala64_hi12;
pc = pc & ~3UL;
delta1 = delta (dest, pc);
delta2 = dest;
delta3 = delta (dest, pc + 8);
delta4 = delta (dest, pc + 12);
pcala_hi20 = (delta1 >> 12) & 0xfffffUL;
pcala_lo12 = delta2 & 0xfffUL;
pcala64_lo20 = (delta3 >> 32) & 0xfffffUL;
pcala64_hi12 = (delta4 >> 52) & 0xfffUL;
target = (pc & ~0xfffUL) + ((pcala_hi20 << 44) >> 32) +
((pcala64_hi12 << 52) | (pcala64_lo20 << 32) | (((pcala_lo12 << 52) >> 52) & 0xffffffffUL));
if (target != dest) {
printf ("DEST: 0x%016lx PC: 0x%016lx\n", dest, pc);
printf ("R_LARCH_PCALA_HI20 = 0x%lx\n", pcala_hi20);
printf ("R_LARCH_PCALA_LO12 = 0x%lx\n", pcala_lo12);
printf ("R_LARCH_PCALA64_LO20 = 0x%lx\n", pcala64_lo20);
printf ("R_LARCH_PCALA64_HI12 = 0x%lx\n", pcala64_hi12);
printf ("%0lx != %0lx\n", dest, target);
return -1;
}
return 0;
}
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, e, f, g, h, i;
for (a = 0; a < 4; a++) {
for (b = 0; b < 4; b++) {
for (c = 0; c < 4; c++) {
for (d = 0; d < 4; d++) {
for (e = 0; e < 4; e++) {
for (f = 0; f < 4; f++) {
for (g = 0; g < 4; g++) {
for (h = 0; h < 4; h++) {
int res = test (lo12[d] | lo20[c] | hi20[b] | hi12[a], lo12[h] | lo20[g] | hi20[f] | hi12[e]);
if (res != 0)
return -1;
}
}
}
}
}
}
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment