Last active
January 18, 2024 18:33
-
-
Save shlomopongratz/f82466b6044f3a1653890b43b046c443 to your computer and use it in GitHub Desktop.
Viewport calculation.
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
#include <stdio.h> | |
#include <stdint.h> | |
#include <assert.h> | |
typedef union { | |
uint64_t ll; | |
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ | |
struct { | |
uint32_t lo; | |
uint32_t hi; | |
}; | |
#else | |
struct { | |
uint32_t hi; | |
uint32_t lo; | |
}; | |
#endif | |
} u_t; | |
// From include/qemu/bitops.h | |
static inline uint64_t deposit64(uint64_t value, int start, int length, | |
uint64_t fieldval) | |
{ | |
uint64_t mask; | |
assert(start >= 0 && length > 0 && length <= 64 - start); | |
mask = (~0ULL >> (64 - length)) << start; | |
return (value & ~mask) | ((fieldval << start) & mask); | |
} | |
static inline uint64_t extract64(uint64_t value, int start, int length) | |
{ | |
assert(start >= 0 && length > 0 && length <= 64 - start); | |
return (value >> start) & (~0ULL >> (64 - length)); | |
} | |
void original(uint64_t base, uint32_t limit, uint64_t truelimit) | |
{ | |
uint64_t tlimit; | |
uint64_t size; | |
printf("Original\n"); | |
size = (uint64_t)limit - base + 1; | |
tlimit = base + size - 1; | |
printf("Base 0x%lx inferd limit 0x%lx size 0x%lx %s\n", | |
base, tlimit, size, | |
tlimit == truelimit ? "Good" : "Bad"); | |
} | |
void truncated(uint64_t base, uint32_t limit, uint64_t truelimit) | |
{ | |
uint32_t tbase; | |
uint32_t tsize; | |
uint64_t size; | |
uint64_t tlimit; | |
printf("Trucated\n"); | |
// Use 32 bit calculation | |
tbase = base; // Truncate | |
tsize = limit - tbase; | |
// Return to 64 bit | |
size = tsize; | |
size++; | |
tlimit = base + size - 1; | |
printf("Base 0x%lx inferd limit 0x%lx size 0x%lx %s\n", | |
base, tlimit, size, | |
tlimit == truelimit ? "Good" : "Bad"); | |
} | |
void peters(uint64_t base, uint32_t limit, uint64_t truelimit) | |
{ | |
uint64_t size; | |
uint64_t tlimit; | |
printf("Peter's\n"); | |
tlimit = deposit64(limit, 32, 32, extract64(base, 32, 32)); | |
size = tlimit - base + 1; | |
tlimit = base + size - 1; | |
printf("Base 0x%lx inferd limit 0x%lx size 0x%lx %s\n", | |
base, tlimit, size, | |
tlimit == truelimit ? "Good" : "Bad"); | |
} | |
void my_patch(uint64_t base, uint32_t limit, uint64_t truelimit) | |
{ | |
uint64_t tbase; | |
uint64_t tlimit; | |
uint64_t size; | |
printf("My patch\n"); | |
tbase = base & 0xffffffff; | |
tlimit = 0x100000000 + (uint64_t)limit; | |
size = ((tlimit - tbase) & 0xffffffff) + 1; | |
tlimit = base + size - 1; | |
printf("Base 0x%lx inferd limit 0x%lx size 0x%lx %s\n", | |
base, tlimit, size, | |
tlimit == truelimit ? "Good" : "Bad"); | |
} | |
void do_math(uint64_t base, uint32_t limit, uint64_t truelimit) | |
{ | |
uint64_t tlimit; | |
uint64_t size; | |
uint32_t tsize; | |
uint32_t tbase; | |
original(base, limit, truelimit); | |
printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); | |
truncated(base, limit, truelimit); | |
printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); | |
peters(base, limit, truelimit); | |
printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); | |
my_patch(base, limit, truelimit); | |
} | |
void nxp_example_init(u_t *base, u_t *limit) | |
{ | |
base->lo = 0xd0000000; | |
base->hi = 0x80000000; | |
limit->lo = 0xd000ffff; | |
limit->hi = 0x80000000; | |
} | |
void peter_example_init(u_t *base, u_t *limit) | |
{ | |
base->lo = 0xd0000000; | |
base->hi = 0x80000000; | |
limit->lo = 0xffffffff; | |
limit->hi = 0x80000000; | |
} | |
int main(int arc, char *argv[]) | |
{ | |
u_t base; | |
u_t limit; | |
printf("=======================================================\n"); | |
nxp_example_init(&base, &limit); | |
printf("-> NXP example: Base 0x%lx Limit 0x%lx\n", base.ll, limit.ll); | |
do_math(base.ll, limit.lo, limit.ll); | |
printf("-------------------------------------------------------\n"); | |
nxp_example_init(&base, &limit); | |
base.ll += 0x200000000; | |
limit.ll += 0x200000000; | |
printf("-> NXP example shifted by 0x200000000 Base 0x%lx Limit 0x%lx\n", base.ll, limit.ll); | |
do_math(base.ll, limit.lo, limit.ll); | |
printf("-------------------------------------------------------\n"); | |
nxp_example_init(&base, &limit); | |
base.ll += 0x2ffff000; | |
limit.ll += 0x2ffff000; | |
printf("-> NXP example shifted by 0x2ffff000 Base 0x%lx Limit 0x%lx\n", base.ll, limit.ll); | |
do_math(base.ll, limit.lo, limit.ll); | |
printf("=======================================================\n"); | |
peter_example_init(&base, &limit); | |
printf("Peter's: Base 0x%lx Limit 0x%lx\n", base.ll, limit.ll); | |
do_math(base.ll, limit.lo, limit.ll); | |
printf("-------------------------------------------------------\n"); | |
peter_example_init(&base, &limit); | |
base.ll += 0x200000000; | |
limit.ll += 0x200000000; | |
printf("-> Peter's shifted by 0x200000000 Base 0x%lx Limit 0x%lx\n", base.ll, limit.ll); | |
do_math(base.ll, limit.lo, limit.ll); | |
printf("-------------------------------------------------------\n"); | |
peter_example_init(&base, &limit); | |
base.ll += 0x2ffff000; | |
limit.ll += 0x2ffff000; | |
printf("-> Peter's shifted by 0x2ffff000 Base 0x%lx Limit 0x%lx\n", base.ll, limit.ll); | |
do_math(base.ll, limit.lo, limit.ll); | |
printf("=======================================================\n"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment