RAM_BASE = 0x80000000;
RAM_SIZE = 2M;
BIOS_SIZE = 64K;
HEADER_SIZE = 2K;
LOAD_OFFSET = 0;
LOAD_ADDR = RAM_BASE + BIOS_SIZE + LOAD_OFFSET;
STACK_INIT = RAM_BASE + 0x001FFF00;
MEMORY {
HEADER : ORIGIN = LOAD_ADDR - HEADER_SIZE, LENGTH = HEADER_SIZE
RAM (rwx) : ORIGIN = LOAD_ADDR, LENGTH = RAM_SIZE - (LOAD_ADDR - RAM_BASE)
}
ENTRY(__start)
SECTIONS {
.psx_exe_header : {
/* ASCII ID "PS-X EXE" */
BYTE(0x50); BYTE(0x53); BYTE(0x2d); BYTE(0x58);
BYTE(0x20); BYTE(0x45); BYTE(0x58); BYTE(0x45);
/* Unused */
QUAD(0);
/* Initial PC */
LONG(ABSOLUTE(__start));
/* Initial GP/R28 */
LONG(_gp);
/* Load address */
LONG(LOAD_ADDR);
/* File size excluding the 2K header */
LONG(__bss_start - __text_start);
/* Unused */
QUAD(0); QUAD(0);
/* Initial SP/R29 and FP/R30 base */
LONG(STACK_INIT);
/* Initial SP/R29 and FP/R30 offset */
LONG(0);
/* Unused */
QUAD(0); QUAD(0); LONG(0);
/* ASCII region marker */
KEEP(*(.region));
. = ALIGN(HEADER_SIZE);
} > HEADER
.text : {
__text_start = .;
__ctors_start = .;
*(.ctors*)
__ctors_end = .;
ASSERT((__ctors_end - __ctors_start) % 4 == 0, "Invalid .ctors section");
__dtors_start = .;
*(.dtors*)
__dtors_end = .;
ASSERT((__dtors_end - __dtors_start) % 4 == 0, "Invalid .dtors section");
*(.text*)
__text_end = .;
} > RAM
/* The PSX doesn't have an MMU so we don't really care about RO vs RW */
.data : {
__data_start = .;
*(.data*)
*(.rodata*)
*(.got)
/* Padding to a multiple of 2K is required for loading from ISO */
. = ALIGN(2048);
__data_end = .;
} > RAM
.bss (NOLOAD) : {
__bss_start = .;
*(.bss*)
*(COMMON)
__bss_end = .;
} > RAM
/* Make the heap word-aligned */
. = ALIGN(4);
__heap_start = .;
/DISCARD/ : {
*(.MIPS.abiflags)
*(.reginfo)
*(.eh_frame_hdr)
*(.eh_frame)
}
}