gint/src/std/memory.c
Lephe 7d63a1b536
r61524 render-cg: support Prizm and fx-CG Manager
This change adds a new HWCALC model, HWCALC_FXCG_MANAGER, which
identifies Casio's official fx-CG Manager software. Both the Prizm and,
to my surprise, the fx-CG Manager use the old RAM address of 88000000
(P1) and a8000000 (P2) instead of the new fx-CG 50 address of 8c000000
(P1) and ac000000 (P2).

The VRAM is hence adjusted at startup to move hardcoded pointers into
the proper space. Added to the kernel moving the VBR space dynamically
on the Prizm, this allows gint to be fully compatible with these
platforms.

The fx-CG Manager is detected by its product ID made of 0xff.

Also adds a proper interface to the R61524 driver, even though it's not
any more complete than previously, and fixes an oversight where the
HWURAM entry of the kernel data array was no longer computed since the
TLB management change.

As of now, the fx-CG Manager still has a bug regarding return-to-menu
since returning from the main menu doesn't work very well and often
loops. This has been seen occasionally on some Graph 90+E so it's
unlikely to be a platform-specific problem.
2020-07-02 15:48:19 +02:00

118 lines
2.2 KiB
C

#include <gint/defs/attributes.h>
#include <gint/hardware.h>
#include <stddef.h>
#include <stdint.h>
static void memcpy4(uint32_t * restrict d, const void * restrict src, size_t n)
{
int modulo = (uintptr_t)src & 3;
/* Best case: perform 32-bit accesses only */
if(!modulo)
{
const uint32_t *s = src;
for(; n; n-=4) *d++ = *s++;
}
#if 0
/* Here's where SH-3 and SH-4A start working differently. SH-4A has a
2-cycle 'movua' instruction to perform unaligned reads */
else if(isSH4())
{
uint32_t longword;
const uint32_t *s = src;
while(n--)
{
__asm__(
"movua.l %1, %0"
: "=z"(longword)
: "m>"(*s)
);
s++;
*d++ = longword;
}
}
#endif
/* On SH-3, we can only hope that there is 2-alignment */
else if(!(modulo & 1))
{
const uint16_t *s = src;
uint16_t * restrict dst = (void *)d;
for(; n; n-=2)
{
*dst++ = *s++;
*dst++ = *s++;
}
}
/* Or just perform the raw copy */
else
{
const uint8_t *s = src;
uint8_t * restrict dst = (void *)d;
while(n--) *dst++ = *s++;
}
}
void *memcpy(void * restrict dst, const void * restrict src, size_t n)
{
uint8_t *d = dst;
const uint8_t *s = src;
/* Small areas: don't bother with complex methods */
if(n < 32)
{
while(n--) *d++ = *s++;
return dst;
}
/* Find a longword offset to perform word or longword operations */
while((uintptr_t)d & 3) *d++ = *s++, n--;
/* Perform the big, efficient copy */
memcpy4((void *)d, s, n & ~3);
size_t m = n & 3;
d += (n - m);
s += (n - m);
n = m;
/* Copy around the last bytes */
while(n--) *d++ = *s++;
return dst;
}
void *_memmove(GUNUSED void *dst, GUNUSED const void *src, GUNUSED size_t n)
{
// (same as memcpy, but heed for direction if areas overlap)
// copy by increasing addresses if dst < src
// copy by decreasing addresses if dst > src
return dst;
}
int memcmp(GUNUSED const void *s1, GUNUSED const void *s2, GUNUSED size_t n)
{
uint8_t const *p1 = s1;
uint8_t const *p2 = s2;
for(size_t i = 0; i < n; i++)
{
if(p1[i] != p2[i]) return (p1[i] - p2[i]);
}
return 0;
}
void *memset(void *s, int byte, size_t n)
{
/* TODO: Do it efficiently */
char *dst = s;
while(n--) *dst++ = byte;
return s;
}