Browse Source

abcmem: implement XM# handling and ABC800MAC+"ROM hack" map switching

Add XM# handling to the ABC memory map.

Change the granularity of the ABC memory map to 1K and move the flags
to the bottom of the CPU-visible register.

Add support for the ABC800MAC and "ROM hack" (some SmartAid variant?)
map switching schemes. These are done in "hardware" (in the FPGA) as
they need to be able to take effect immediately.
H. Peter Anvin 1 year ago
parent
commit
0ccc916f7e
6 changed files with 223 additions and 94 deletions
  1. 156 41
      fpga/abcbus.sv
  2. 1 1
      fpga/max80.sv
  3. 32 22
      rv32/abcmem.c
  4. 15 15
      rv32/ioregs.h
  5. 18 15
      rv32/rom.S
  6. 1 0
      rv32/sections.h

+ 156 - 41
fpga/abcbus.sv

@@ -61,9 +61,15 @@ module abcbus (
 	       output reg	 sdram_wstrb
 	       );
 
+   // SDRAM base address, used for reading back the map registers
+   parameter [31:0]		 sdram_base_addr;
+
    // Set if MOSFETs Q1-Q6 are installed rather than the corresponding
    // resistors. BOTH CANNOT BE INSTALLED AT THE SAME TIME.
    parameter [6:1] mosfet_installed = 6'b111_111;
+
+   // Are the auxiliary extension header bits reversed (this may be
+   // programmable in the future depending on orientation of the header)?
    parameter [0:0] exth_reversed = 1'b0;
 
    // Synchronizer for ABC-bus input signals; also changes
@@ -103,26 +109,45 @@ module abcbus (
    wire      abc80  = abc_xinpstb_s & abc_xoutpstb_s;
    wire      abc800 = ~abc80;
 
+   wire	     xinpstb_s  = (abc800 & abc_xinpstb_s) | (|abc_inp_s);
+   wire	     xoutpstb_s = (abc800 & abc_xinpstb_s) | (|abc_out_s);
    // Memory and I/O read/write strobes for ABC-bus
    reg	     abc_xmemrd;
    reg       abc_xmemwr;
+   reg	     abc_xinpstb;
+   reg	     abc_xoutpstb;
    reg [1:0] abc_inp;
    reg [4:0] abc_out;
    reg	     abc_rst;
    reg	     abc_cs;
    reg [3:1] abc_stb;		// Delayed strobes
 
-   always @(posedge sdram_clk)
+   always @(negedge rst_n or posedge sdram_clk)
+     if (~rst_n)
+       begin
+	  abc_xmemrd   <= 1'b0;
+	  abc_xmemwr   <= 1'b0;
+	  abc_inp      <= 2'b0;
+	  abc_out      <= 5'b0;
+	  abc_xinpstb  <= 1'b0;
+	  abc_xoutpstb <= 1'b0;
+	  abc_rst      <= 1'b0;
+	  abc_cs       <= 1'b0;
+	  abc_stb      <= 'b0;
+       end
+   else
      begin
 	abc_xmemrd <= abc_clk_active & abc_xmemfl_s;
 	abc_xmemwr <= abc_clk_active &
 	(abc800 ? abc_xmemw800_s : abc_xmemw80_s);
 	abc_inp <= abc_inp_s & {2{abc_clk_active}};
 	abc_out <= abc_out_s & {5{abc_clk_active}};
+	abc_xinpstb  <= xinpstb_s  & abc_clk_active;
+	abc_xoutpstb <= xoutpstb_s & abc_clk_active;
 	abc_rst <= abc_rst_s & abc_clk_active;
 	abc_cs  <= abc_cs_s  & abc_clk_active;
-	abc_stb <= { abc_stb, |{abc_inp, abc_out, abc_rst,
-				abc_cs, abc_xmemrd, abc_xmemwr} };
+	abc_stb <= { abc_stb,
+		     abc_xinpstb|abc_xoutpstb|abc_xmemrd|abc_xmemwr };
      end
 
    reg  [7:0] abc_do;
@@ -245,41 +270,47 @@ module abcbus (
    // ABC SDRAM interface
    //
    // Memory map for ABC-bus memory references.
-   // 512 byte granularity for memory (registers 0-127),
-   // one input and one output queue per select code for I/O (128-255).
+   // 1024 byte granularity in two maps for memory (registers 0-127).
    //
-   // bit [15:0]  = SDRAM address [24:9] ( bits 24:9 from CPU )
-   // bit [16]    = write enable ( bit 30 from CPU )
-   // bit [17]    = read enable  ( bit 31 from CPU )
+   // For simplicity, the data bits from the CPU are reorganized
+   // so the SDRAM address is the same as the CPU uses.
    //
-   // Accesses from the internal CPU supports 32-bit accesses only!
+   // bit [14:0]  = SDRAM address [24:10] ( bits 24:10 from RV32 )
+   // bit [15]    = write enable ( bit 0 from RV32 )
+   // bit [16]    = read enable  ( bit 1 from RV32 )
+   // bit [17]    = assert XM#   ( bit 2 from RV32 )
    //
-   wire [17:0] rdata_abcmemmap;
-   wire [17:0] abc_memmap_rd;
-
-   abcmapram abcmapram (
-			.aclr      ( ~rst_n ),
+   // Accesses from RV32 supports 32-bit accesses only!
+   //
+   logic       abc_a_map;
+   wire [17:0] rdata_abcmemmap;		// RV32 access port
+   wire [17:0] abc_memmap_rd;		// ABC-bus access port
 
-			.clock     ( sdram_clk ),
+   abcmapram
+   (
+    .aclr      ( ~rst_n ),
 
-			.address_a ( abc_a_s[15:9] ),
-			.data_a    ( 18'bx ),
-			.wren_a    ( 1'b0 ),
-			.q_a       ( abc_memmap_rd ),
+    .clock     ( sdram_clk ),
 
-			.address_b ( cpu_addr[8:2] ),
-			.data_b    ( { cpu_wdata[31:30], cpu_wdata[24:9] } ),
-			.wren_b    ( map_valid & cpu_wstrb[0] ),
+    .address_a ( { abc_a_map, abc_a_s[15:10] } ),
+    .data_a    ( 18'bx ),
+    .wren_a    ( 1'b0 ),
+    .q_a       ( abc_memmap_rd ),
 
-			.q_b       ( rdata_abcmemmap )
-			);
+    .address_b ( cpu_addr[8:2] ),
+    .data_b    ( { cpu_wdata[2:0], cpu_wdata[24:10] } ),
+    .wren_b    ( map_valid & cpu_wstrb[0] ),
 
-   assign cpu_rdata_map =  { rdata_abcmemmap[17:16], 5'b0,
-			     rdata_abcmemmap[15:0], 9'b0 };
+    .q_b       ( rdata_abcmemmap )
+    );
 
-   wire        abc_rden    = abc_memmap_rd[17];
-   wire        abc_wren    = abc_memmap_rd[16];
-   wire [24:0] abc_memaddr = { abc_memmap_rd[15:0], abc_a_s[8:0] };
+   assign cpu_rdata_map =  sdram_base_addr |		     // Fixed bits
+			   { 7'b0, rdata_abcmemmap[14:0],    // Address
+			     7'b0, rdata_abcmemmap[17:15] }; // Flags
+   wire	       abc_xmen    = abc_memmap_rd[17];
+   wire        abc_rden    = abc_memmap_rd[16];
+   wire        abc_wren    = abc_memmap_rd[15];
+   wire [24:0] abc_memaddr = { abc_memmap_rd[14:0], abc_a_s[9:0] };
 
    reg	      abc_memrd_en;
    reg	      abc_memwr_en;
@@ -295,6 +326,7 @@ module abcbus (
 	  abc_do_memwr   <= 1'b0;
 	  sdram_valid    <= 1'b0;
 	  sdram_wstrb    <= 1'b0;
+	  abc_xm         <= 1'b0;
        end
      else
        begin
@@ -309,12 +341,15 @@ module abcbus (
 
 	  sdram_valid   <= abc_do_memrd | abc_do_memwr;
 	  sdram_wstrb   <= abc_do_memwr;
+
+	  abc_xm        <= abc_xmen;
        end // else: !if(~rst_n)
 
    assign sdram_addr = abc_memaddr;
    assign sdram_wd   = abc_di;
 
-   // I/O data registers; RST# is considered OUT 7 even through
+   //
+   // 4680 data registers; RST# is considered OUT 7 even through
    // it is an IN from the ABC point of view.
    //
    // OUT register, written from ABC: <addr 2:0>   <data 7:0>
@@ -365,7 +400,7 @@ module abcbus (
      abc_wait <= abc_wait_force | (rst_n & |set_busy & is_busy);
 
    //
-   // I/O data registers
+   // 4680 bus data registers
    //
    reg [2:0]  reg_out_addr;
    reg [7:0]  reg_out_data;
@@ -391,6 +426,46 @@ module abcbus (
 	  end // if (|busy_io[7:0])
      end // always @ (posedge sdram_clk)
 
+   //
+   // ABC800 non-4680 I/O ports
+   //
+   reg        abc800mac_en     =  1'b0;
+   reg [7:1]  abc800mac_iobase =  7'b0;
+   reg [15:0] abc800mac_xmmask = 16'b0;
+   wire	      abc800mac_avalid =
+	      abc800mac_en && abc_a_s[7:1] == abc800mac_iobase;
+   wire	      cpu_xmmask = rst_n && abc_valid && cpu_addr[6:2] == 5'b01001;
+
+   // XMMASK logic (abc800mac_en is handled with other CPU registers)
+   always @(posedge sdram_clk)
+     begin
+	if (abc_xoutpstb & abc800mac_avalid & !abc_a_s[0])
+	  abc800mac_xmmask[7:0]  <= abc_di;
+	else if (cpu_xmmask & cpu_wstrb[0])
+	  abc800mac_xmmask[7:0]  <= cpu_wdata[7:0];
+
+	if (abc_xoutpstb & abc800mac_avalid & abc_a_s[1])
+	  abc800mac_xmmask[15:8] <= abc_di;
+	else if (cpu_xmmask & cpu_wstrb[1])
+	  abc800mac_xmmask[15:8] <= cpu_wdata[15:8];
+     end // always @ (posedge sdram_clk)
+
+   //
+   // "ROM hack" map control logic
+   //
+   reg	     romhack_en    = 1'b0;     // Enable
+   reg [5:0] romhack_addr  = 6'b0;     // Address mask (1K granular)
+   reg	     romhack_map   = 1'b0;     // Current map
+   wire	     cpu_romhackmap = rst_n && abc_valid && cpu_addr[6:2] == 5'b01011;
+
+   always @(posedge sdram_clk)
+     begin
+	if (abc_xmemwr & romhack_en & (abc_a_s[15:10] == romhack_addr))
+	  romhack_map <= abc_a_s[0];
+	else if (cpu_romhackmap & cpu_wstrb[0])
+	  romhack_map <= cpu_wdata[0];
+     end
+
    //
    // ABC data out (= ABC host read) logic
    //
@@ -424,8 +499,28 @@ module abcbus (
 	       abc_d_oe <= 1'b1;
 	       abc_do   <= reg_inp_data[1];
 	    end
+	  else if (abc_xinpstb & abc800mac_avalid)
+	    begin
+	       abc_d_oe <= 1'b1;
+	       case (abc_a_s[0])
+		 1'b0: abc_do <= abc800mac_xmmask[7:0];
+		 1'b1: abc_do <= abc800mac_xmmask[15:8];
+	       endcase // case (abc_a_s[0])
+	    end
        end // else: !if(~rst_n)
 
+   //
+   // Memory map control logic
+   //
+   always_comb
+     begin
+	abc_a_map = 1'b0;
+	if (abc800mac_en)
+	  abc_a_map |= abc800mac_xmmask[abc_a_s[15:12]];
+	if (romhack_en)
+	  abc_a_map |= romhack_map;
+     end
+
    // Memory read latency counter
    reg [7:0] memrd_latency_ctr = 'b0;
    reg [7:0] memrd_latency_max = 'b0;
@@ -477,6 +572,8 @@ module abcbus (
 	  inp_en            <= 2'b00;
 	  bus_change_status <= 4'b0;
 	  bus_change_mask   <= 4'b0;
+	  abc800mac_en      <= 1'b0;
+	  romhack_en        <= 1'b0;
 
 	  // abc_resin, nmi, int and force_wait are deliberately not affected
 	  // by an internal CPU reset. They are, however, inherently asserted
@@ -490,8 +587,8 @@ module abcbus (
 
 	  if (abc_valid)
 	    begin
-	       casez (cpu_addr[5:2] )
-		 5'b??010: begin
+	       casez (cpu_addr[6:2] )
+		 5'b00010: begin
 		   if (cpu_wstrb[0])
 		     busy_status[7:0] <= set_busy[7:0] | (busy_status[7:0] & ~cpu_wdata[7:0]);
 		    if (cpu_wstrb[1])
@@ -507,7 +604,7 @@ module abcbus (
 			 bus_change_mask <= cpu_wdata[31:28] & bus_change_valid;
 		      end
 		 end
-		 5'b??011: begin
+		 5'b00011: begin
 		    if (cpu_wstrb[0])
 		      begin
 			 abc_resin      <= cpu_wdata[3];
@@ -516,17 +613,31 @@ module abcbus (
 			 abc_wait_force <= cpu_wdata[0];
 		      end
 		 end
-		 5'b??101: begin
+		 5'b00101: begin
 		    if (cpu_wstrb[0])
 		      reg_inp_data[0] <= cpu_wdata[7:0];
+		     if (cpu_wstrb[1])
+		       reg_inp_data[1] <= cpu_wdata[15:8];
+		     if (cpu_wstrb[2])
+		       inp_en <= cpu_wdata[17:16];
+		   end
+		 5'b01000: begin
+		    if (cpu_wstrb[0])
+		      abc800mac_iobase <= cpu_wdata[7:1];
+		    if (cpu_wstrb[3])
+		      abc800mac_en <= cpu_wdata[31];
+		   end
+		   // 5'b01001: abc800mac_xmdata - handled elsewhere
+		 5'b01010: begin
 		    if (cpu_wstrb[1])
-		      reg_inp_data[1] <= cpu_wdata[15:8];
-		    if (cpu_wstrb[2])
-		      inp_en <= cpu_wdata[17:16];
-		 end
+		      romhack_addr <= cpu_wdata[15:10];
+		    if (cpu_wstrb[3])
+		      romhack_en <= cpu_wdata[31];
+		   end
+		   // 5'b01011: romhack_map - handled elsewhere
 		 default:
 		   /* do nothing */ ;
-	       endcase // casez (cpu_addr[5:2])
+	       endcase // casez (cpu_addr[6:2])
 	    end // if (abc_valid & cpu_wstrb[0])
        end
 
@@ -545,7 +656,11 @@ module abcbus (
        5'b00100: cpu_rdata = { 21'b0, reg_out_addr, reg_out_data };
        5'b00101: cpu_rdata = { 14'b0, inp_en, reg_inp_data[1], reg_inp_data[0] };
        5'b00111: cpu_rdata = { 23'b0, memrd_latency_err, memrd_latency_max };
+       5'b01000: cpu_rdata = { abc800mac_en, 23'b0, abc800mac_iobase, 1'b0 };
+       5'b01001: cpu_rdata = { 16'b0, abc800mac_xmmask };
+       5'b01010: cpu_rdata = { romhack_en, 15'b0, romhack_addr, 10'b0 };
+       5'b01011: cpu_rdata = { 31'b0, romhack_map };
        default:  cpu_rdata = 32'bx;
-     endcase // casez (cpu_addr[5:2])
+     endcase // casez (cpu_addr[6:2])
 
 endmodule // abcbus

+ 1 - 1
fpga/max80.sv

@@ -425,7 +425,7 @@ module max80
    //
    wire        abc_clk_s;	// abc_clk synchronous to sys_clk
 
-   abcbus #(.mosfet_installed(x_mosfet))
+   abcbus #(.mosfet_installed(x_mosfet), .sdram_base_addr(SDRAM_ADDR))
    abcbus (
 	   .rst_n ( rst_n ),
 	   .sys_clk ( sys_clk ),

+ 32 - 22
rv32/abcmem.c

@@ -18,8 +18,17 @@ struct abc_mem_init {
     enum sysvar_enum enable;
     struct rom r;
 };
-#define RD ABCMEMMAP_RD
-#define WR ABCMEMMAP_WR
+
+/* Convenience aliases */
+#define MAPS		ABCMEMMAP_MAPS
+#define PAGE_SHIFT	ABCMEMMAP_PAGE_SHIFT
+#define PAGE_SIZE	ABCMEMMAP_PAGE_SIZE
+#define PAGE_MASK	ABCMEMMAP_PAGE_MASK
+#define PAGE_COUNT	ABCMEMMAP_PAGE_COUNT
+#define PERMAP		(PAGE_COUNT / MAPS)
+#define RD		ABCMEMMAP_RD
+#define WR		ABCMEMMAP_WR
+#define XM		ABCMEMMAP_XM
 
 #define K 1024
 #define R(x)	{ (x), sizeof(x), #x }
@@ -28,10 +37,10 @@ struct abc_mem_init {
 /* ---- ABC80 memory configurations ---- */
 
 /* Not really NV, but matches NVRAM in some expansions */
-static char __dram_bss __aligned(512) abc80_nvram[2][2*K];
+static char __dram_bss __aligned(PAGE_SIZE) abc80_nvram[2][2*K];
 
 /* 16K external memory to expand to 512K */
-static char __dram_bss __aligned(512) abc80_extmem[16*K];
+static char __dram_bss __aligned(PAGE_SIZE) abc80_extmem[16*K];
 
 static const struct abc_mem_init mem_init_abc80[] = {
     /* Put these here in case someone wants to enable both */
@@ -74,11 +83,6 @@ static const struct abc_mem_init mem_init_abc800[] = {
     END
 };
 
-#define ABC_PAGE_SHIFT	9
-#define ABC_PAGE_SIZE	(1U << ABC_PAGE_SHIFT)
-#define ABC_PAGE_MASK	(0xffff & ~(ABC_PAGE_SIZE-1))
-#define ABC_PAGE_COUNT	(0x10000 >> ABC_PAGE_SHIFT)
-
 static void abc_map_list(uint32_t *memmap, const struct abc_mem_init *mem)
 {
     while (mem->addr >= 0) {
@@ -90,9 +94,9 @@ static void abc_map_list(uint32_t *memmap, const struct abc_mem_init *mem)
 	    continue;		/* Empty range, skip */
 
 	uint32_t addr = mem->addr;
-	bool bad = ((addr | len) & ~ABC_PAGE_MASK) ||
+	bool bad = ((addr | len) & ~PAGE_MASK) ||
 	    (len > 0x10000 - addr) ||
-	    ((size_t)data & (ABC_PAGE_SIZE-1));
+	    ((size_t)data & (PAGE_SIZE-1));
 
 	con_printf("abcmem: %s %s @ 0x%04x len 0x%04x\n",
 		   mem->r.name ? mem->r.name : "(none)",
@@ -102,16 +106,17 @@ static void abc_map_list(uint32_t *memmap, const struct abc_mem_init *mem)
 		   addr, len);
 
 	if (enabled) {
-	    uint32_t *pg = &memmap[addr >> ABC_PAGE_SHIFT];
+	    uint32_t *pg = &memmap[addr >> PAGE_SHIFT];
 	    uint32_t flags = mem->flags;
 
 	    if (data) {
 		/* Mapped range */
-		for (uint32_t bytes = 0; bytes < len; bytes += ABC_PAGE_SIZE)
-		    *pg++ = ((size_t)(data + bytes) & SDRAM_MASK) | flags;
+		size_t pgv = (size_t)data | flags;
+		for (uint32_t bytes = 0; bytes < len; bytes += PAGE_SIZE)
+		    *pg++ = pgv + bytes;
 	    } else {
 		/* Unmapped range - set to 0 for clarity */
-		memset(pg, 0, len >> (ABC_PAGE_SHIFT-2));
+		memset(pg, 0, len >> (PAGE_SHIFT-2));
 	    }
 	}
 	mem++;
@@ -120,25 +125,30 @@ static void abc_map_list(uint32_t *memmap, const struct abc_mem_init *mem)
 
 void __cold abc_init_memmap(void)
 {
-    static uint32_t memmap[ABC_PAGE_COUNT];
+    static uint32_t memmap[MAPS][PERMAP]; /* Too big to fit on stack */
     const struct abc_mem_init *mem;
 
     memset(memmap, 0, sizeof memmap);
 
+    /*
+     * Currently the only map that gets populated is map 0; the
+     * remaining map(s) get cleared by the memset() above.
+     */
+
     if (is_abc800()) {
-	abc_map_list(memmap, mem_init_abc800);
+	abc_map_list(memmap[0], mem_init_abc800);
     } else {
 	/* Put 22K first so UFD-DOS/PUN80 memory always is put at the end */
 	if (getvar_bool(config_abc_mem_abc80_nvram_22k))
-	    abc_map_list(memmap, mem_init_abc80_nvram_22k);
+	    abc_map_list(memmap[0], mem_init_abc80_nvram_22k);
 	else if (getvar_bool(config_abc_mem_abc80_nvram_20k))
-	    abc_map_list(memmap, mem_init_abc80_nvram_20k);
+	    abc_map_list(memmap[0], mem_init_abc80_nvram_20k);
 	else
-	    abc_map_list(memmap, mem_init_abc80_no_nvram);
+	    abc_map_list(memmap[0], mem_init_abc80_no_nvram);
 
-	abc_map_list(memmap, mem_init_abc80);
+	abc_map_list(memmap[0], mem_init_abc80);
     }
 
     /* Install memory map into hardware registers */
-    memcpy(&ABCMEMMAP_PAGE(0), memmap, sizeof memmap);
+    memcpy((void *)&ABCMEMMAP_PAGE(0), memmap, sizeof memmap);
 }

+ 15 - 15
rv32/ioregs.h

@@ -1,7 +1,6 @@
 #ifndef IODEV_H
 #define IODEV_H
 
-#include "compiler.h"
 #include "iodevs.h"
 #include "iodeva.h"
 
@@ -131,23 +130,24 @@
 #define ABC_LATENCY		IODEVRL(ABC,7)
 #define ABC_LATENCY_CTR		IODEVRB0(ABC,7)
 #define ABC_LATENCY_ERR		IODEVRB1(ABC,7)
+#define ABC_MAP_MAC800_CFG	IODEVL(ABC,8)
+#define ABC_MAP_MAC800_MAPS	IODEVL(ABC,9)
+#define ABC_MAP_ROMHACK_CFG	IODEVL(ABC,10)
+#define ABC_MAP_ROMHACK_MAP	IODEVL(ABC,11)
 
-/* n = 0 ... 511 */
+/* n = 0 ... 127 for one of two 64x1K maps */
 #define ABCMEMMAP_PAGE(n)	IODEVL(ABCMEMMAP,n)
 
-/* n = 0 ... 255 */
-#define ABCMEMMAP_WRPORT(n)	IODEVL(ABCMEMMAP,128+((n) << 1))
-#define ABCMEMMAP_RDPORT(n)	IODEVL(ABCMEMMAP,129+((n) << 1))
-#define ABCMEMMAP_WRCOUNT(n)	IODEVL(ABCMEMMAP,384+((n) << 1))
-#define ABCMEMMAP_RDCOUNT(n)	IODEVL(ABCMEMMAP,385+((n) << 1))
-#define ABCMEMMAP_WR		(1 << 30)
-#define ABCMEMMAP_RD		(1 << 31)
-
-#define ABCMEMMAP_STATUS(n)	IODEVL(ABCMEMMAP,512+(n))
-#define ABCMEMMAP_CLR7DMA	0x800
-#define ABCMEMMAP_CLR1WEMP	0x400
-#define ABCMEMMAP_CLR0WEMP	0x200
-#define ABCMEMMAP_CLR0REMP	0x100
+#define ABCMEMMAP_MAPS		2
+#define ABCMEMMAP_PAGE_SHIFT	10
+#define ABCMEMMAP_PAGE_SIZE	(1 << ABCMEMMAP_PAGE_SHIFT)
+#define ABCMEMMAP_PAGE_MASK	(0xffff & ~(ABCMEMMAP_PAGE_SIZE-1))
+#define ABCMEMMAP_PAGE_COUNT	((0x10000 >> ABCMEMMAP_PAGE_SHIFT) \
+				 * ABCMEMMAP_MAPS)
+
+#define ABCMEMMAP_WR		1
+#define ABCMEMMAP_RD		2
+#define ABCMEMMAP_XM		4
 
 #define RANDOM_DATA		IODEVRL(RANDOM,0)
 

+ 18 - 15
rv32/rom.S

@@ -2,23 +2,26 @@
  * ROM wrapper
  */
 
-.macro __rom name
-	.globl \name
-	.section ".dram.abcrom","a"
-	.balign 512, 0xff		/* Required MMU granulatity */
-\name :
-	.incbin FILE
+#include "sections.h"
+#include "ioregs.h"
+
+#define _paste(x,y) x ## y
 
-	.balign 512, 0xff
+	.globl NAME
+	__dram_rom
+	.balign ABCMEMMAP_PAGE_SIZE, 0xff	/* Required MMU granulatity */
+NAME :
+	.incbin FILE
 
-	.type \name, @object
-	.size \name, . - \name
+	.balign ABCMEMMAP_PAGE_SIZE, 0xff
 
-	.globl \name\()_size
-	\name\()_size = . - \name
+	.type NAME, @object
 
-	.globl \name\()_end
-	\name\()_end = .
-.endm
+#define SIZE _paste(NAME, _size)
+	.globl SIZE
+	SIZE = . - NAME
+	.size NAME , SIZE
 
-	__rom name=NAME
+#define END  _paste(NAME, _end)
+	.globl END
+	END = .

+ 1 - 0
rv32/sections.h

@@ -13,6 +13,7 @@
 #define __bss_hot	___section(".bss.hot","aw",@nobits)
 #define __esplink_head	___section(".dram.esplink.head","aw",@nobits)
 #define __esplink	___section(".dram.bss.esplink","aw",@nobits)
+#define __dram_rom	___section(".dram.abcrom","a")
 #define __dram_text	___section(".dram.text","ax")
 #define __dram_rodata	___section(".dram.rodata","a")
 #define __dram_string	___section(".dram.rodata.str","aMS")