# Compiler and assembler CROSS=riscv64-linux-gnu CC = ${CROSS}-gcc AS = ${CROSS}-as LD = ${CROSS}-ld OBJDUMP = ${CROSS}-objdump SIZE = ${CROSS}-size # Specify the target binary (call it whatever) TARGET = bin.elf # QEMU command and flags # QEMU = qemu-riscv64-static QEMU = qemu-system-riscv64 QEMU_FLAGS += --machine virt# # Use the virt machine QEMU_FLAGS += --nographic# # No graphical output # Flags for compiler and assembler CFLAGS += -static# # Use static linking CFLAGS += -nostartfiles# # Do not use standard startup files CFLAGS += -nostdlib# # Do not use standard libraries CFLAGS += -fno-builtin# # Do not use built-in functions CFLAGS += -fno-common# # Do not use common sections CFLAGS += -march=rv64i # Use RV64I ISA, i.e., integer only CFLAGS += -mabi=lp64 # Use LP64 ABI, i.e., 64-bit longs and pointers, 32-bit ints CFLAGS += -Os# # Optimize for size LDFLAGS += -T link.ld # Use the linker script LDFLAGS += --no-dynamic-linker LDFLAGS += -m elf64lriscv LDFLAGS += -static LDFLAGS += -nostdlib LDFLAGS += -s # Use GC=0 to disable garbage collection ifneq ($(GC), 0) CFLAGS += -ffreestanding CFLAGS += -ffunction-sections -fdata-sections CFLAGS += -Wl,--gc-sections endif # Debugging flags, passed as 'make DEBUG=1 ' ifeq ($(DEBUG), 1) CFLAGS += -g -O0 endif # Assembly source files AS_SRCS := $(wildcard *.s) # Object files OBJS := $(AS_SRCS:.s=.o) # Default target all: $(OBJS) @$(LD) $(LDFLAGS) -o $(TARGET) $(OBJS) @echo "LD $(OBJS)" # Compile assembly sources %.o: %.s @$(CC) $(CFLAGS) -c -o $@ $< @echo "CC $<" # Run the binary in QEMU run: all @echo "To exit: Ctrl+A, X" @$(QEMU) $(QEMU_FLAGS) -bios $(TARGET) # View the text section of the binary inspect: all $(OBJDUMP) -d $(TARGET) # View the disassembly raw: all $(OBJDUMP) -D $(TARGET) # View the data section data: all $(OBJDUMP) -s $(TARGET) --section=.data # Check the size of the compiled binary size: all $(SIZE) $(TARGET) # Clean up clean: rm -f $(TARGET) $(OBJS)