gintctl/src/gint/ram.c

337 lines
7.2 KiB
C
Raw Permalink Normal View History

2020-02-17 18:06:38 +01:00
#include <gint/display.h>
#include <gint/keyboard.h>
#include <gintctl/util.h>
#include <gintctl/gint.h>
2021-08-11 01:35:34 +02:00
#include <gintctl/assets.h>
2020-02-17 18:06:38 +01:00
#include <stdio.h>
#include <stdbool.h>
/* Byte-based memory detection functions */
2020-02-17 18:06:38 +01:00
static int writable(uint8_t volatile *mem)
{
int save = *mem;
*mem = save ^ 0xff;
/* Read the written value and restore the pointed byte */
int measured = *mem;
*mem = save;
/* The address is writable iff we succeeded in storing ~save */
return (measured == (save ^ 0xff));
}
static int same_location(uint8_t volatile *m1, uint8_t volatile *m2)
{
uint8_t s1=*m1, s2=*m2;
*m1 = s1 ^ 0xf0;
int equal1 = (*m2 == *m1);
*m1 = s1 ^ 0x0f;
int equal2 = (*m2 == *m1);
*m1 = s1 ^ 0xff;
int equal3 = (*m2 == *m1);
*m1 = s1;
*m2 = s2;
return equal1 && equal2 && equal3;
}
/* Longword-based memory detection functions */
static int writable_lword(uint8_t volatile *mem_8)
{
uint32_t volatile *mem = (void *)mem_8;
uint32_t save = *mem;
*mem = save ^ 0xffffff00;
uint32_t measured = *mem;
*mem = save;
return (measured == (save ^ 0xffffff00));
}
static int same_location_lword(uint8_t volatile *m1_8, uint8_t volatile *m2_8)
{
uint32_t volatile *m1 = (void *)m1_8, *m2 = (void *)m2_8;
uint32_t s1=*m1, s2=*m2;
*m1 = s1 ^ 0xffff0000;
int equal1 = (*m2 == *m1);
*m1 = s1 ^ 0x0000ff00;
int equal2 = (*m2 == *m1);
*m1 = s1 ^ 0xffffff00;
int equal3 = (*m2 == *m1);
*m1 = s1;
*m2 = s2;
return equal1 && equal2 && equal3;
}
/* Region size detection */
struct region {
/* Region name (for display) [input] */
char const *name;
/* Region address [input] */
uint32_t mem;
/* Whether region supports only 32-bit access [input] */
bool use_lword;
2021-09-18 16:04:57 +02:00
/* How often to probe memory (1 in step_size bytes will be tested) */
int step_size;
/* Size of region [output] */
uint32_t size;
/* Reason why region is not larger [output] */
int reason;
};
static void explore_region(struct region *r)
2020-02-17 18:06:38 +01:00
{
uint8_t volatile *mem = (void *)r->mem;
r->size = 0;
2020-02-17 18:06:38 +01:00
2021-09-18 16:04:57 +02:00
while(r->size < (16 << 20))
2020-02-17 18:06:38 +01:00
{
int x = r->use_lword
? writable_lword(mem + r->size)
: writable(mem + r->size);
r->reason = 1;
if(!x) return;
if(r->size > 0)
2020-02-17 18:06:38 +01:00
{
int y = r->use_lword
? same_location_lword(mem, mem+r->size)
: same_location(mem, mem+r->size);
r->reason = 2;
if(y) return;
2020-02-17 18:06:38 +01:00
}
2021-09-18 16:04:57 +02:00
r->size += r->step_size;
2020-02-17 18:06:38 +01:00
}
r->reason = 3;
2020-02-17 18:06:38 +01:00
}
/* Detailed 0xe50[01]xxxx search
On the SH-4A this region contains the OLRAM. On the SH4AL-DSP it is supposed
to contain nothing, but on the calculator the XRAM and YRAM (normally in P1)
use part of the SH-4A OLRAM region. How exactly they wrap around is
uncertain, so this analysis finds independent pages accurately. */
static void e500_search(int e500_pages[32])
{
for(int i = 0; i < 32; i++) {
uint8_t volatile *p1 = (void *)0xe5000000 + (i << 12);
for(int j = 0; j < 32; j++) {
uint8_t volatile *p2 = (void *)0xe5000000 + (j << 12);
if(same_location(p1, p2)) {
e500_pages[i] = j;
break;
}
}
}
}
#ifdef FX9860G
static void show_region(int row, struct region *r)
{
/* Out-of-bounds rows */
if(row < 1 || row > 9 || (row == 1 && r)) return;
extern font_t font_mini;
font_t const *old_font = dfont(&font_mini);
int y = (row - 1) * 6 + 2 * (row > 1);
if(!r)
{
dprint( 1, y, C_BLACK, "Area");
dprint(26, y, C_BLACK, "Address");
dprint(62, y, C_BLACK, "Size");
dprint(82, y, C_BLACK, "At end");
dfont(old_font);
return;
}
char const *reasons[] = { "Not tested", "Read-only", "Loops", "" };
dprint( 1, y, C_BLACK, "%s", r->name);
dprint(26, y, C_BLACK, "%08X", r->mem);
if(r->reason != 0)
dprint(62, y, C_BLACK, "%dk", r->size >> 10);
else
dprint(62, y, C_BLACK, "-");
dprint(82, y, C_BLACK, "%s", reasons[r->reason]);
dfont(old_font);
}
#endif
#ifdef FXCG50
static void show_region(int y, struct region *r)
{
char const *reasons[] = {
"Not tested",
"Not writable",
"Wraps around",
"Maybe larger!",
};
if(!r)
{
row_print(y, 2, "Area");
row_print(y, 9, "Address");
row_print(y, 18, "AS");
row_print(y, 22, "Size");
row_print(y, 35, "At end");
return;
}
row_print(y, 2, "%s", r->name);
row_print(y, 9, "%08X", r->mem);
row_print(y, 18, "%d", r->use_lword ? 32 : 8);
2021-09-18 16:04:57 +02:00
row_print(y, 22, "%d %s", r->size, r->size >= (1000000) ? "B" : "bytes");
row_print(y, 35, reasons[r->reason]);
}
#endif
2020-02-17 18:06:38 +01:00
/* gintctl_gint_ram(): Determine the size of some memory areas */
void gintctl_gint_ram(void)
{
struct region r[] = {
2021-09-18 16:04:57 +02:00
{ "ILRAM", 0xe5200000, false, 4, /**/ 0, 0 },
{ "XRAM", 0xe5007000, false, 4, /**/ 0, 0 },
{ "YRAM", 0xe5017000, false, 4, /**/ 0, 0 },
{ "PRAM0", 0xfe200000, true, 32, /**/ 0, 0 },
{ "XRAM0", 0xfe240000, true, 32, /**/ 0, 0 },
{ "YRAM0", 0xfe280000, true, 32, /**/ 0, 0 },
{ "PRAM1", 0xfe300000, true, 32, /**/ 0, 0 },
{ "XRAM1", 0xfe340000, true, 32, /**/ 0, 0 },
{ "YRAM1", 0xfe380000, true, 32, /**/ 0, 0 },
{ "X_P2", 0xa5007000, false, 4, /**/ 0, 0 },
{ "URAM", 0xa55f0000, false, 4, /**/ 0, 0 },
{ "RAM", 0xac000000, false, 1024, /**/ 0, 0 },
{ NULL },
};
2021-01-31 17:08:28 +01:00
/* Region count (for the scrolling list on fx-9860G) */
GUNUSED int region_count = 9;
/* List scroll no fx-9860G */
GUNUSED int scroll = spu_zero();
2020-02-17 18:06:38 +01:00
/* 0: Standard regions, 1: Detailed e500 search */
int tab = 0;
/* Detailed 16-page e500 search */
int e500_pages[32];
e500_search(e500_pages);
key_event_t ev;
2020-02-17 18:06:38 +01:00
int key = 0;
while(key != KEY_EXIT)
{
dclear(C_WHITE);
#ifdef FX9860G
if(tab == 0) {
show_region(1, NULL);
dhline(6, C_BLACK);
for(int i = 0; i < region_count; i++)
show_region(i+2-scroll, &r[i]);
scrollbar_px(/* view */ 8, 54, /* range */ 0, region_count,
/* visible */ scroll, 8);
dimage(0, 56, &img_opt_gint_ram);
}
else if(tab == 1) {
// TODO
}
2020-02-17 18:06:38 +01:00
#endif
#ifdef FXCG50
row_title("On-chip memory discovery");
if(tab == 0) {
show_region(1, NULL);
for(int i = 0; r[i].name; i++)
show_region(i+2, &r[i]);
fkey_button(1, "ILRAM");
fkey_button(2, "XYRAM");
fkey_button(3, "DSP0");
fkey_button(4, "DSP1");
fkey_action(6, "E500");
}
else if(tab == 1) {
for(int i = 0; i < 32; i++) {
row_print(2 + i / 4, 2 + 12 * (i % 4), "%08X:%d",
0xe5000000 + (i << 12), e500_pages[i]);
}
}
2020-02-17 18:06:38 +01:00
#endif
dupdate();
ev = getkey();
key = ev.key;
if(tab == 0 && key == KEY_F1)
{
explore_region(&r[0]);
}
if(tab == 0 && key == KEY_F2)
{
explore_region(&r[1]);
explore_region(&r[2]);
}
if(tab == 0 && key == KEY_F3)
{
explore_region(&r[3]);
explore_region(&r[4]);
explore_region(&r[5]);
}
if(tab == 0 && key == KEY_F4)
{
explore_region(&r[6]);
explore_region(&r[7]);
explore_region(&r[8]);
}
if(tab == 0 && key == KEY_F5)
{
explore_region(&r[9]);
explore_region(&r[10]);
2021-09-18 16:04:57 +02:00
explore_region(&r[11]);
}
#ifdef FX9860G
int scroll_max = region_count - 8;
if(tab == 0 && key == KEY_UP)
{
if(ev.shift || keydown(KEY_SHIFT)) scroll=0;
else if(scroll > 0) scroll--;
}
if(tab == 0 && key == KEY_DOWN)
{
if(ev.shift || keydown(KEY_SHIFT)) scroll=scroll_max;
else if(scroll < scroll_max) scroll++;
}
#endif
if(tab == 0 && key == KEY_F6)
tab = 1;
if(tab == 1 && key == KEY_EXIT) {
tab = 0;
key = 0;
}
2020-02-17 18:06:38 +01:00
}
}