forked from sysprog21/rv32emu
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathMakefile
268 lines (227 loc) · 6.81 KB
/
Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
include mk/common.mk
include mk/toolchain.mk
OUT ?= build
BIN := $(OUT)/rv32emu
CONFIG_FILE := $(OUT)/.config
-include $(CONFIG_FILE)
CFLAGS = -std=gnu99 -O2 -Wall -Wextra
CFLAGS += -Wno-unused-label
CFLAGS += -include src/common.h
# Set the default stack pointer
CFLAGS += -D DEFAULT_STACK_ADDR=0xFFFFE000
# Set the default args starting address
CFLAGS += -D DEFAULT_ARGS_ADDR=0xFFFFF000
# Enable link-time optimization (LTO)
ENABLE_LTO ?= 1
ifeq ($(call has, LTO), 1)
ifeq ("$(CC_IS_CLANG)$(CC_IS_GCC)$(CC_IS_EMCC)",)
$(warning LTO is only supported in clang, gcc and emcc.)
override ENABLE_LTO := 0
endif
endif
$(call set-feature, LTO)
ifeq ($(call has, LTO), 1)
ifeq ("$(CC_IS_GCC)$(CC_IS_EMCC)", "1")
CFLAGS += -flto
endif
ifeq ("$(CC_IS_CLANG)", "1")
CFLAGS += -flto=thin -fsplit-lto-unit
LDFLAGS += -flto=thin
endif
endif
# Disable Intel's Control-flow Enforcement Technology (CET)
CFLAGS += $(CFLAGS_NO_CET)
OBJS_EXT :=
# Control and Status Register (CSR)
ENABLE_Zicsr ?= 1
$(call set-feature, Zicsr)
# Instruction-Fetch Fence
ENABLE_Zifencei ?= 1
$(call set-feature, Zifencei)
# Integer Multiplication and Division instructions
ENABLE_EXT_M ?= 1
$(call set-feature, EXT_M)
# Atomic Instructions
ENABLE_EXT_A ?= 1
$(call set-feature, EXT_A)
# Compressed extension instructions
ENABLE_EXT_C ?= 1
$(call set-feature, EXT_C)
# Single-precision floating point instructions
ENABLE_EXT_F ?= 1
$(call set-feature, EXT_F)
ifeq ($(call has, EXT_F), 1)
AR := ar
ifeq ("$(CC_IS_EMCC)", "1")
AR = emar
endif
SOFTFLOAT_OUT = $(abspath $(OUT)/softfloat)
src/softfloat/build/Linux-RISCV-GCC/Makefile:
git submodule update --init src/softfloat/
SOFTFLOAT_LIB := $(SOFTFLOAT_OUT)/softfloat.a
$(SOFTFLOAT_LIB): src/softfloat/build/Linux-RISCV-GCC/Makefile
$(MAKE) -C $(dir $<) BUILD_DIR=$(SOFTFLOAT_OUT) CC=$(CC) AR=$(AR)
$(OUT)/decode.o $(OUT)/riscv.o: $(SOFTFLOAT_LIB)
LDFLAGS += $(SOFTFLOAT_LIB)
LDFLAGS += -lm
endif
# Experimental SDL oriented system calls
ENABLE_SDL ?= 1
ifeq ($(call has, SDL), 1)
ifeq (, $(shell which sdl2-config))
$(warning No sdl2-config in $$PATH. Check SDL2 installation in advance)
override ENABLE_SDL := 0
endif
ifeq (1, $(shell pkg-config --exists SDL2_mixer; echo $$?))
$(warning No SDL2_mixer lib installed. Check SDL2_mixer installation in advance)
override ENABLE_SDL := 0
endif
endif
$(call set-feature, SDL)
ifeq ($(call has, SDL), 1)
OBJS_EXT += syscall_sdl.o
$(OUT)/syscall_sdl.o: CFLAGS += $(shell sdl2-config --cflags)
LDFLAGS += $(shell sdl2-config --libs) -pthread
LDFLAGS += $(shell pkg-config --libs SDL2_mixer)
endif
ENABLE_GDBSTUB ?= 0
$(call set-feature, GDBSTUB)
ifeq ($(call has, GDBSTUB), 1)
GDBSTUB_OUT = $(abspath $(OUT)/mini-gdbstub)
GDBSTUB_COMM = 127.0.0.1:1234
src/mini-gdbstub/Makefile:
git submodule update --init $(dir $@)
GDBSTUB_LIB := $(GDBSTUB_OUT)/libgdbstub.a
$(GDBSTUB_LIB): src/mini-gdbstub/Makefile
$(MAKE) -C $(dir $<) O=$(dir $@)
# FIXME: track gdbstub dependency properly
$(OUT)/decode.o: $(GDBSTUB_LIB)
OBJS_EXT += gdbstub.o breakpoint.o
CFLAGS += -D'GDBSTUB_COMM="$(GDBSTUB_COMM)"'
LDFLAGS += $(GDBSTUB_LIB) -pthread
gdbstub-test: $(BIN)
$(Q).ci/gdbstub-test.sh && $(call notice, [OK])
endif
ENABLE_JIT ?= 0
$(call set-feature, JIT)
ifeq ($(call has, JIT), 1)
OBJS_EXT += jit_x64.o
ifneq ($(processor), x86_64)
$(error JIT mode only supports for x64 target currently.)
endif
src/rv32_jit_template.c:
$(Q)tools/gen-jit-template.py $(CFLAGS) > $@
$(OUT)/jit_x64.o: src/jit_x64.c src/rv32_jit_template.c
$(VECHO) " CC\t$@\n"
$(Q)$(CC) -o $@ $(CFLAGS) -c -MMD -MF [email protected] $<
endif
# For tail-call elimination, we need a specific set of build flags applied.
# FIXME: On macOS + Apple Silicon, -fno-stack-protector might have a negative impact.
# Enable tail-call for emcc
ifeq ("$(CC_IS_EMCC)", "1")
CFLAGS += -mtail-call
endif
$(OUT)/emulate.o: CFLAGS += -foptimize-sibling-calls -fomit-frame-pointer -fno-stack-check -fno-stack-protector
# Clear the .DEFAULT_GOAL special variable, so that the following turns
# to the first target after .DEFAULT_GOAL is not set.
.DEFAULT_GOAL :=
EXPORTED_FUNCS :=
ifeq ("$(CC_IS_EMCC)", "1")
BIN := $(BIN).js
endif
all: config $(BIN)
OBJS := \
map.o \
utils.o \
decode.o \
io.o \
syscall.o \
emulate.o \
riscv.o \
elf.o \
cache.o \
mpool.o \
$(OBJS_EXT) \
main.o
OBJS := $(addprefix $(OUT)/, $(OBJS))
deps := $(OBJS:%.o=%.o.d)
EMCC_CFLAGS :=
ifeq ("$(CC_IS_EMCC)", "1")
EXPORTED_FUNCS += _malloc,_free, \
_elf_new,_elf_delete,_elf_open,_elf_get_symbol,_elf_load, \
_state_new,_state_delete,_rv_create,_rv_delete,_rv_has_halted,_rv_step,_run
EMCC_CFLAGS += -sINITIAL_MEMORY=2GB --embed-file build --pre-js pre.js \
-s"EXPORTED_FUNCTIONS=$(EXPORTED_FUNCS)" \
-sEXPORTED_RUNTIME_METHODS=getValue,setValue,stringToNewUTF8,addFunction \
-sALLOW_TABLE_GROWTH
endif
$(OUT)/%.o: src/%.c
$(VECHO) " CC\t$@\n"
$(Q)$(CC) -o $@ $(CFLAGS) -c -MMD -MF [email protected] $<
$(BIN): $(OBJS)
$(VECHO) " LD\t$@\n"
$(Q)$(CC) -o $@ $(EMCC_CFLAGS) $^ $(LDFLAGS)
mv build/rv32emu.wasm docs
mv build/rv32emu.js docs
config: $(CONFIG_FILE)
$(CONFIG_FILE):
$(Q)echo "$(CFLAGS)" | xargs -n1 | sort | sed -n 's/^RV32_FEATURE/ENABLE/p' > $@
$(VECHO) "Check the file $(OUT)/.config for configured items.\n"
# Tools
include mk/tools.mk
tool: $(TOOLS_BIN)
# RISC-V Architecture Tests
include mk/riscv-arch-test.mk
include mk/tests.mk
CHECK_ELF_FILES := \
hello \
puzzle \
fcalc
ifeq ($(call has, EXT_M), 1)
CHECK_ELF_FILES += \
pi
endif
serve-wasm:
python3 -m http.server 8000 --directory docs
EXPECTED_hello = Hello World!
EXPECTED_puzzle = success in 2005 trials
EXPECTED_fcalc = Performed 12 tests, 0 failures, 100% success rate.
EXPECTED_pi = 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086
check: $(BIN)
$(Q)$(foreach e,$(CHECK_ELF_FILES),\
$(PRINTF) "Running $(e).elf ... "; \
if [ "$(shell $(BIN) $(OUT)/$(e).elf | uniq)" = "$(strip $(EXPECTED_$(e))) inferior exit code 0" ]; then \
$(call notice, [OK]); \
else \
$(PRINTF) "Failed.\n"; \
exit 1; \
fi; \
)
EXPECTED_aes_sha1 = 1242a6757c8aef23e50b5264f5941a2f4b4a347e -
misalign: $(BIN)
$(Q)$(PRINTF) "Running aes.elf ... ";
$(Q)if [ "$(shell $(BIN) -m $(OUT)/aes.elf | $(SHA1SUM))" = "$(EXPECTED_aes_sha1)" ]; then \
$(call notice, [OK]); \
else \
$(PRINTF) "Failed.\n"; \
fi
include mk/external.mk
# Non-trivial demonstration programs
ifeq ($(call has, SDL), 1)
doom: $(BIN) $(DOOM_DATA)
(cd $(OUT); ../$(BIN) doom.elf)
ifeq ($(call has, EXT_F), 1)
quake: $(BIN) $(QUAKE_DATA)
(cd $(OUT); ../$(BIN) quake.elf)
endif
endif
clean:
$(RM) $(BIN) $(OBJS) $(HIST_BIN) $(HIST_OBJS) $(deps) $(CACHE_OUT) src/rv32_jit_template.c build/rv32emu.js build/rv32emu.wasm
distclean: clean
-$(RM) $(DOOM_DATA) $(QUAKE_DATA)
$(RM) -r $(OUT)/id1
$(RM) *.zip
$(RM) -r $(OUT)/mini-gdbstub
-$(RM) $(OUT)/.config
-$(RM) -r $(OUT)/softfloat
-include $(deps)