MAKEFLAGS += -R -r

SUBDIRS  := include test roms fatfs/source zlib

CROSS	  = ../tools/gnu/bin/riscv32-unknown-elf-
CC	  = $(CROSS)gcc
LD	  = $(CROSS)ld
OBJCOPY   = $(CROSS)objcopy
AR        = $(CROSS)ar
NM	  = $(CROSS)nm
PERL      = perl
GZIP	  = gzip

INCLUDE   = -I. -I./include -I./zlib -I./fatfs/source
include ../riscv-opts.mk
CPPFLAGS  = $(INCLUDE) $(riscv_flags)
CFLAGS    = $(CPPFLAGS) -W -Wextra
SFLAGS    = $(CPPFLAGS) -D__ASSEMBLY__
LDSCRIPT  = max80.ild
LDFLAGS   = $(CFLAGS) \
	    -Wl,-Map=$*.map \
	    -Wl,--gc-sections \
	    -Wl,--sort-section=alignment \
	    -Wl,-T,$(LDSCRIPT) \
	    -Wl,-z,common-page-size=16 \
	    -Wl,-z,max-page-size=16

gendeps   = -MD -MF $(@D)/.$(@F).d -MT $@

# Delete output files on error
.DELETE_ON_ERROR:

# Don't delete intermediate files
.SECONDARY:

genhdrs = iodevs.h irqtable.h
gensrcs =

all: boot.bin dram.bin.gz dram.hex checksum.h

ROMS    := $(wildcard roms/*.rom)
ROMOBJS  = $(ROMS:.rom=.o)

max80.elf: head.o dummy.o die.o main.o system.o \
	  ioregsa.o irqasm.o irqtable.o spurious_irq.o sbrk.o \
	  console.o rtc.o romcopy.o spiflash.o \
	  sdcard.o diskcache.o \
	  abcmem.o abcio.o abcdisk.o abcrtc.o abcpun80.o \
	  memset.o memcpy.o \
	  runtest.o start_test.o \
	  $(ROMOBJS) \
	  testimg.o \
	  fatfs.a

testimg.elf: head.o dummy.o die.o test/main.o test/system.o \
	  ioregsa.o irqasm.o irqtable.o spurious_irq.o sbrk.o \
	  console.o rtc.o romcopy.o spiflash.o \
	  sdcard.o diskcache.o \
	  abcmem.o abcio.o abcdisk.o abcrtc.o abcpun80.o \
	  memset.o memcpy.o \
	  testdata.o $(ROMOBJS) \
	  fatfs.a

FATFS_C = $(wildcard fatfs/source/*.c)
FATFS_O = $(FATFS_C:.c=.o)
fatfs.a: $(FATFS_O)
	rm -f $@
	$(AR) cq $@ $(FATFS_O)

ZLIB_C = $(wildcard zlib/*.c)
ZLIB_O = $(ZLIB_C:.c=.o)
zlib.a: $(ZLIB_O)
	rm -f $@
	$(AR) cq $@ $(ZLIB_O)

CFLAGS_zlib/inflate.c := -Wno-implicit-fallthrough
CFLAGS_zlib/infback.c := -Wno-implicit-fallthrough

CFLAGS_memset.c := -O2

%.hex: %.elf
	$(OBJCOPY) -O ihex $< $@

%.mem: %.bin
	$(BIN2MEM) $< > $@

boot.bin: max80.elf
	$(OBJCOPY) -O binary -R '.dram*' $< $@

dram.bin: max80.elf
	$(OBJCOPY) -O binary -j '.dram*' $< $@

%.gz: %
	$(GZIP) -9 < $< > $@

checksum.h: dram.bin boot.bin checksum.pl
	$(PERL) checksum.pl -o $@ -p boot.bin \
		-l $$(($$($(NM) -n max80.elf --radix=decimal | \
			grep ' [A-Z] __dram_init_end$$' | \
	                awk '{ print $$1; }') - (1 << 30))) \
		dram.bin

testimg.bin: testimg.elf
	$(OBJCOPY) -O binary $< $@

testimg.o: testimg.S testimg.bin

%.hex: %.bin
	$(OBJCOPY) -I binary -O ihex $< $@

%.elf: $(LDSCRIPT)
	$(CC) $(LDFLAGS) -o $@ $(filter-out $(LDSCRIPT),$^)

%.o: %.c | $(genhdrs)
	$(CC) $(CFLAGS) $(CFLAGS_$<) $(gendeps) -c -o $@ $<

%.s: %.c | $(genhdrs)
	$(CC) $(CFLAGS) $(CFLAGS_$<) $(gendeps) -S -o $@ $<

%.i: %.c | $(genhdrs)
	$(CC) $(CFLAGS) $(CFLAGS_$<) $(gendeps) -E -o $@ $<

%.o: %.S | $(genhdrs)
	$(CC) $(SFLAGS) $(SFLAGS_$<) $(gendeps) -c -o $@ $<

%.s: %.S | $(genhdrs)
	$(CC) $(SFLAGS) $(SFLAGS_$<) $(gendeps) -E -o $@ $<

ioregsa.S: ioregs.h ioregsa.pl | $(genhdrs)
	$(PERL) ioregsa.pl $< $@

roms/%.o: roms/%.rom rom.S
	$(CC) $(SFLAGS) $(SFLAGS_$(F<)) -DNAME='rom_$*' -DFILE='"$<"' \
		-c -o $@ rom.S

%.ild: %.ld | $(genhdrs)
	$(CC) $(CFLAGS) $(CFLAGS_$<) $(gendeps) \
		-x assembler-with-cpp \
		-fdollars-in-identifiers \
		-C -P -E $< | $(PERL) -pe 's:^(#.*)$$:/* $$1 */:' > $@

iodevs.h: ../iodevs.conf ../tools/iodevs.pl
	$(PERL) ../tools/iodevs.pl h $< $@

irqtable.h: ../iodevs.conf ../tools/iodevs.pl
	$(PERL) ../tools/iodevs.pl irqh $< $@

clean:
	for d in . $(SUBDIRS); do \
		rm -f $$d/*.a $$d/*.o $$d/*.i $$d/*.s $$d/*.elf $$d/*.bin \
		$$d/.*.d $$d/*.ild $$d/*.map; \
	done
	rm -f $(genhdrs) $(gensrcs)

spotless: clean
	rm -f *.mem *.hex *.mif checksum.h

-include $(patsubst %,%/.*.d,. $(SUBDIRS))
