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) } }