
OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv", "elf32-littleriscv")
OUTPUT_ARCH(riscv)

ENTRY(_start)


MEMORY {
  rom (RX): ORIGIN = 0x80000000, LENGTH = 256M
  ram (RWX): ORIGIN = 0x02000000, LENGTH = 16K
}

STACK_SIZE = 1024;
HEAP_SIZE = 1024;

CL_SIZE = 16;

SECTIONS {
    .text ORIGIN(rom) : {
        PROVIDE(__TEXT_START__ = .);
        *crt0.S.o(.text .text.*)
        *(.text.smallsysteminit)
        *(.text.SmallSystemInit)
        /*. = ORIGIN(rom) + 0xC0;*/
        /*KEEP(*crt0.S.o(.trap_text))*/

        *(.text)
        *(.text.*)
        *(.rodata)
        *(.rodata.*)      
        . = ALIGN(CL_SIZE);
    } >rom 

	.init_array (READONLY) :
	{
	  PROVIDE_HIDDEN (__init_array_start = .);
	  KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
	  KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
	  PROVIDE_HIDDEN (__init_array_end = .);
	  
	  PROVIDE_HIDDEN (__fini_array_start = .);
	  KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*)))
	  KEEP(*(.fini_array))
	  PROVIDE_HIDDEN (__fini_array_end   = .); 
		
	  PROVIDE(__TEXT_END__ = .);
	} >rom AT>rom 
	
	.data : 
    AT( __TEXT_END__ ) {
        PROVIDE(__DATA_START__ = .);
        _gp = .;
        . = ORIGIN(ram) + 0xC0;
        KEEP(*crt0.S.o(.trap_text))
        *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata*)
        *(.sdata .sdata.* .sdata* .sdata*.* .gnu.linkonce.s.*)
        *(.data .data.*)
        . = ALIGN(CL_SIZE);
        PROVIDE(__DATA_END__ = .);
    } >ram
    
    __DATA_IMAGE_START__ = LOADADDR(.data);
    __DATA_IMAGE_END__ = LOADADDR(.data) + SIZEOF(.data);

    /* thread-local data segment */
    .tdata : {
        PROVIDE(_tls_data = .);
        PROVIDE(_tdata_begin = .);
        *(.tdata .tdata.*)
        PROVIDE(_tdata_end = .);
        . = ALIGN(CL_SIZE);
    } >ram

    .tbss : {
        PROVIDE(__BSS_START__ = .);
        *(.tbss .tbss.*)
        . = ALIGN(CL_SIZE);
        PROVIDE(_tbss_end = .);
    } >ram

    /* bss segment */
    .sbss : {
        *(.sbss .sbss.* .gnu.linkonce.sb.*)
        *(.scommon)
    } >ram

    .bss : {
        *(.bss .bss.*)
        *(COMMON)
        . = ALIGN(CL_SIZE);
        PROVIDE(__BSS_END__ = .);
    } >ram

    /* Code intended to be copied to REGION_RAM before execution */
    .ram_text : 
    AT( ALIGN(__DATA_IMAGE_END__, CL_SIZE) ) {
        PROVIDE(__RAM_TEXT_START__ = .);
        *(.ram_text)
        . = ALIGN(CL_SIZE);
        PROVIDE(__RAM_TEXT_END__ = .);
    } > ram

    __RAM_TEXT_IMAGE_START__ = LOADADDR(.ram_text);
    __RAM_TEXT_IMAGE_END__ = LOADADDR(.ram_text) + SIZEOF(.ram_text);
    ASSERT(__RAM_TEXT_IMAGE_END__ < ORIGIN(rom) + LENGTH(rom), "rom segment overflows")

    ASSERT(__RAM_TEXT_END__ < ORIGIN(ram) + LENGTH(ram) - STACK_SIZE - HEAP_SIZE, "REGION_RAM section overflows")

    .heap : {
        PROVIDE(__heap_start = .);
        . += HEAP_SIZE;
        . = ALIGN(CL_SIZE);
        PROVIDE(__heap_end = .);
    } >ram

    _end = .;
    PROVIDE(__end = .);

    /* End of uninitalized data segement */

    .stack ORIGIN(ram) + LENGTH(ram) - STACK_SIZE : {
        FILL(0);
        PROVIDE(__STACK_START__ = .);
        . += STACK_SIZE;
        PROVIDE(__C_STACK_TOP__ = .);
        PROVIDE(__STACK_END__ = .);
    } >ram

    /DISCARD/ : {
        *(.eh_frame .eh_frame.*)
    }
}
