diff --git a/Makefile b/Makefile index c616a84..139c53e 100644 --- a/Makefile +++ b/Makefile @@ -96,12 +96,6 @@ LDFLAGS += -z noexecstack ### Paste in arch-specific configurations (e.g., from `scripts/x86_64-qemu.mk`) -include $(AM_HOME)/scripts/$(ARCH).mk -### Fall back to native gcc/binutils if there is no cross compiler -ifeq ($(wildcard $(shell which $(CC))),) - $(info # $(CC) not found; fall back to default gcc and binutils) - CROSS_COMPILE := -endif - ## 5. Compilation Rules ### Rule (compile): a single `.c` -> `.o` (gcc) diff --git a/scripts/riscv32mini-nemu.mk b/scripts/riscv32mini-nemu.mk new file mode 100644 index 0000000..5d29012 --- /dev/null +++ b/scripts/riscv32mini-nemu.mk @@ -0,0 +1,24 @@ +include $(AM_HOME)/scripts/isa/riscv.mk +include $(AM_HOME)/scripts/platform/nemu.mk + +export PATH := $(PATH):$(abspath $(AM_HOME)/tools/rvmini) +CC = rvmini-gcc +AS = rvmini-gcc +CXX = rvmini-g++ + +CFLAGS += -DISA_H=\"riscv/riscv.h\" +COMMON_CFLAGS += -march=rv32i_zicsr -mabi=ilp32 # overwrite +LDFLAGS += -melf32lriscv # overwrite + +AM_SRCS += riscv/nemu/start.S \ + riscv/nemu/cte.c \ + riscv/nemu/trap.S \ + riscv/nemu/vme.c + +AM_SRCS += riscv/npc/libgcc/div.S \ + riscv/npc/libgcc/muldi3.S \ + riscv/npc/libgcc/multi3.c \ + riscv/npc/libgcc/ashldi3.c \ + riscv/npc/libgcc/unused.c + +INC_PATH += $(AM_HOME)/am/src/riscv/npc/libgcc diff --git a/tools/rvmini/gen-lut.c b/tools/rvmini/gen-lut.c new file mode 100644 index 0000000..60700a4 --- /dev/null +++ b/tools/rvmini/gen-lut.c @@ -0,0 +1,29 @@ +#include +#include + +#define LUT_BIN "lut.bin" + +int main() { + FILE *fp = fopen(LUT_BIN, "w"); + assert(fp != NULL); + +#define gen_table(name, row, col, entry_size, expr) do { \ + for (int j = 0; j < row; j ++) { \ + for (int i = 0; i < col; i ++) { \ + unsigned res = (expr); \ + fwrite(&res, entry_size, 1, fp); \ + } \ + } \ +} while (0) + + gen_table(_and8_table, 256, 256, 1, j & i); + gen_table(_or8_table, 256, 256, 1, j | i); + gen_table(_xor8_table, 256, 256, 1, j ^ i); + gen_table(_sll8_table, 32, 256, 4, (unsigned)i << j); + gen_table(_srl8_table, 32, 256, 4, ((unsigned)i << 24) >> j); + gen_table(_sra8_table, 32, 256, 4, (int)((unsigned)i << 24) >> j); + + fclose(fp); + + return 0; +} diff --git a/tools/rvmini/inst-replace.h b/tools/rvmini/inst-replace.h new file mode 100644 index 0000000..2808f4b --- /dev/null +++ b/tools/rvmini/inst-replace.h @@ -0,0 +1,730 @@ +#if 0 +Base instructions: +* add, addi, lui, lw, lbu, sw, sb, jalr + +Assumption: +* compiler do not use tp and gp +* stack below sp is not used yet + +Calling convention: +* tp - temporary register +* gp - saved register, but temporary for the most outer functions + +Limitation: +* We can not break sw into sb, since this process depends on shift operations. + But shift operationss also depend on sw. +* It is difficult to break lw into lbu, since it requires at least two temporary + registers. This makes it difficult to implement other instructions with lw, + due to the small numbers of avaliable registers. +* We can not use lw/sw io impement lbu/sb, since this process requires detecting + misaligned memory accessing. +* We can not break lui into addi + slli, since the linker can not provide + symbol[31:20] and symbol[19:12]. The linker can only provide %hi(symbol) + and %lo(symbol), which are symbol[31:12] and symbol[11:0] respectively. +#endif + +#define _concat(x, y) x ## y +#define concat(x, y) _concat(x, y) +#define SET_DEBUG_LABEL(name) concat(name, _\@): + +#define SP_VAR_BYTE(n, boffset) (-(n) * 4 + (boffset))(sp) +#define SP_VAR(n) SP_VAR_BYTE(n, 0) +#define VAR_A 4 +#define VAR_B 5 +#define VAR_C 6 +#define VAR_D 7 +#define PUSH(r, n) sw r, SP_VAR(n) +#define POP(r, n) lw r, SP_VAR(n) + +.section .rodata +.align 8 +.weak _check_same_array +_check_same_array: .fill 256, 1, 0 +.weak _same_result_table +_same_result_table: .byte 1, 0, 0, 0, 0, 0, 0, 0 + +.weak _check_8bit_0_table +_check_8bit_0_table: +.byte 0 +.fill 255, 1, 1 + +# slt = OF ^ SF = ((sign(A) ^ sign(B)) & (sign(A) ^ sign(R))) ^ sign(R) +# sltu = slt ^ sign(A) ^ sign(B) +# A B R OF slt sltu (sltu = slt ^ A ^ B) +# 0 0 0 0 0 0 +# 0 0 1 0 1 1 +# 0 1 0 0 0 1 +# 0 1 1 1 0 1 +# 1 0 0 1 1 0 +# 1 0 1 0 1 0 +# 1 1 0 0 0 0 +# 1 1 1 0 1 1 +.weak _slt1_table +_slt1_table: .byte 0, 1, 0, 0, 1, 1, 0, 1 +.weak _sltu1_table +_sltu1_table: .byte 0, 1, 1, 1, 0, 0, 0, 1 + +.weak _or1_table +_or1_table: .byte 0, 1, 1, 1 + +.weak _logic_shift_table +.align 8 +_logic_shift_table: +.incbin _LUT_BIN_PATH # defined in command line flags + +#define _and8_table _logic_shift_table +#define _or8_table (_and8_table + 256 * 256) +#define _xor8_table (_or8_table + 256 * 256) +#define _sll8_table (_xor8_table + 256 * 256) +#define _srl8_table (_sll8_table + 32 * 256 * 4) +#define _sra8_table (_srl8_table + 32 * 256 * 4) + +#define def_itype(name, rtype_name) \ + .macro name rd, rs1, imm ;\ + SET_DEBUG_LABEL(name); \ + li tp, \imm; \ + rtype_name \rd, \rs1, tp; \ + .endm + + +.macro call_template r, addr + la \r, \addr + jalr \r, \r +.endm + +.macro jal rd, addr + SET_DEBUG_LABEL(jal) + .if \rd == zero + j \addr + .else + .if \rd == x0 + j \addr + .else + call_template \rd, \addr + .endif + .endif +.endm + +.macro sub rd, rs1, rs2 + SET_DEBUG_LABEL(sub) + not tp, \rs2 + add \rd, \rs1, tp + addi \rd, \rd, 1 +.endm + +.macro getbyte rd, rs1, byte + sw \rs1, SP_VAR(VAR_C) + lbu \rd, SP_VAR_BYTE(VAR_C, \byte) +.endm + +.macro msb rd, rs1 + getbyte \rd, \rs1, 3 + slli \rd, \rd, 1 + getbyte \rd, \rd, 1 +.endm + +.macro slt_template lut, rd, rs1, rs2 + PUSH(s0, 1) + PUSH(s1, 2) + sw \rs2, SP_VAR(VAR_A) + mv s0, \rs1 + lw s1, SP_VAR(VAR_A) + + msb gp, s0 + slli gp, gp, 1 + + msb tp, s1 + add gp, gp, tp + slli gp, gp, 1 + + sub tp, s0, s1 # sub uses tp + msb tp, tp + add gp, gp, tp + + la tp, \lut + add tp, tp, gp + + POP(s1, 2) + POP(s0, 1) + + lbu \rd, (tp) +.endm + +.macro slt rd, rs1, rs2 + SET_DEBUG_LABEL(slt) + slt_template _slt1_table, \rd, \rs1, \rs2 +.endm + +.macro sltu rd, rs1, rs2 + SET_DEBUG_LABEL(slt) + slt_template _sltu1_table, \rd, \rs1, \rs2 +.endm + +.macro logic8_byte_internal lut_reg, boffset + lbu tp, SP_VAR_BYTE(VAR_A, \boffset) + sb tp, SP_VAR_BYTE(VAR_D, 1) + lbu tp, SP_VAR_BYTE(VAR_B, \boffset) + sb tp, SP_VAR_BYTE(VAR_D, 0) + lw tp, SP_VAR(VAR_D) + add tp, \lut_reg, tp + lbu tp, (tp) + sb tp, SP_VAR_BYTE(VAR_C, \boffset) +.endm + +.macro logic lut, rd, rs1, rs2 + .if \rd == x0 + .exitm + .endif + .if \rd == sp || \rs1 == sp || \rs2 == sp + .abort + .endif + .if \rd == gp || \rs1 == gp || \rs2 == gp + .abort + .endif + .if \rd == tp || \rs1 == tp + .abort + .endif + sw \rs1, SP_VAR(VAR_A) + sw \rs2, SP_VAR(VAR_B) + la \rd, \lut + sw x0, SP_VAR(VAR_D) + + logic8_byte_internal \rd, 3 + logic8_byte_internal \rd, 2 + logic8_byte_internal \rd, 1 + logic8_byte_internal \rd, 0 + + lw \rd, SP_VAR(VAR_C) +.endm + +#define def_logic(name) \ + .macro name rd, rs1, rs2 ;\ + SET_DEBUG_LABEL(name); \ + logic concat(_, concat(name, 8_table)), \rd, \rs1, \rs2; \ + .endm + +def_logic(and) +def_logic(or) +def_logic(xor) + + +.macro check_8bit_same table, rd, boffset # rd == 0 if same + lbu \rd, SP_VAR_BYTE(VAR_A, \boffset) + add tp, \table, \rd + addi \rd, x0, 1 + sb \rd, (tp) + + lbu \rd, SP_VAR_BYTE(VAR_B, \boffset) + add \rd, \table, \rd + sb x0, (\rd) + + lbu \rd, (tp) +.endm + +.macro seq rd, rs1, rs2 # set equal + sw \rs1, SP_VAR(VAR_A) + sw \rs2, SP_VAR(VAR_B) + PUSH(s0, 1) + PUSH(s1, 2) + + la s0, _check_same_array + check_8bit_same s0, gp, 0 + check_8bit_same s0, s1, 1 + add gp, gp, s1 + check_8bit_same s0, s1, 2 + add gp, gp, s1 + check_8bit_same s0, s1, 3 + add gp, gp, s1 + + la tp, _same_result_table + add tp, tp, gp + lbu \rd, (tp) + + POP(s1, 2) + POP(s0, 1) +.endm + +.macro check_8bit_0 table, rd, boffset # rd = (source is 0 ? 0 : 1) + lbu \rd, SP_VAR_BYTE(VAR_A, \boffset) + add \rd, \table, \rd + lbu \rd, (\rd) +.endm + +.macro seqz rd, rs1 # set if 0 + sw \rs1, SP_VAR(VAR_A) + PUSH(s0, 1) + + la s0, _check_8bit_0_table + check_8bit_0 s0, gp, 0 + check_8bit_0 s0, tp, 1 + add gp, gp, tp + check_8bit_0 s0, tp, 2 + add gp, gp, tp + check_8bit_0 s0, tp, 3 + add gp, gp, tp + + la tp, _same_result_table + add tp, tp, gp + lbu \rd, (tp) + + POP(s0, 1) +.endm + +#define SET_BRANCH_LABEL(name) concat(name, _\@\target): + +.macro branch_resolve target, is_tp_high_sel_target, label +#define LABEL_NAME non_taken_\label\target + slli tp, tp, 2 # tp = tp * 4 + add tp, sp, tp + .if \is_tp_high_sel_target == 1 + la gp, \target + sw gp, SP_VAR(VAR_A) # higher address + la gp, LABEL_NAME + sw gp, SP_VAR(VAR_B) # lower address + .else + la gp, LABEL_NAME + sw gp, SP_VAR(VAR_A) # higher address + la gp, \target + sw gp, SP_VAR(VAR_B) # lower address + .endif + lw tp, (-VAR_B * 4)(tp) + jr tp + +LABEL_NAME: +.endm + + +.macro beq rs1, rs2, target + SET_BRANCH_LABEL(beq) + .if \rs2 == zero || \rs2 == x0 + seqz tp, \rs1 + .else + .if \rs1 == zero || \rs1 == x0 + beq \rs2, \rs1, \target + .exitm + .else + seq tp, \rs1, \rs2 + .endif + .endif + branch_resolve \target, 1, \@ +.endm + +.macro bne rs1, rs2, target + SET_BRANCH_LABEL(bne) + .if \rs2 == zero || \rs2 == x0 + seqz tp, \rs1 + .else + .if \rs1 == zero || \rs1 == x0 + bne \rs2, \rs1, \target + .exitm + .else + seq tp, \rs1, \rs2 + .endif + .endif + branch_resolve \target, 0, \@ +.endm + +.macro blt rs1, rs2, target + SET_BRANCH_LABEL(blt) + .if \rs2 == zero || \rs2 == x0 + msb tp, \rs1 + branch_resolve \target, 1, \@ + .else + .if \rs1 == zero || \rs1 == x0 + # check rs2 > 0 ? + # msb(rs2) == 0 && msb(rs2 - 1) == 0 + msb gp, \rs2 + addi tp, \rs2, -1 + msb tp, tp + add gp, gp, tp + la tp, _or1_table + add tp, gp, tp + lbu tp, (tp) # tp == 1 -> not taken + branch_resolve \target, 0, \@ + .else + slt tp, \rs1, \rs2 + branch_resolve \target, 1, \@ + .endif + .endif +.endm + +.macro bltu rs1, rs2, target + SET_BRANCH_LABEL(bltu) + sltu tp, \rs1, \rs2 + branch_resolve \target, 1, \@ +.endm + +.macro bge rs1, rs2, target + SET_BRANCH_LABEL(bge) + .if \rs1 == zero || \rs1 == x0 + # check rs2 <= 0 ? + # msb(rs2) == 1 || msb(rs2 - 1) == 1 + msb gp, \rs2 + addi tp, \rs2, -1 + msb tp, tp + add gp, gp, tp + la tp, _or1_table + add tp, gp, tp + lbu tp, (tp) + branch_resolve \target, 1, \@ + .else + slt tp, \rs1, \rs2 + branch_resolve \target, 0, \@ + .endif +.endm + +.macro bgeu rs1, rs2, target + SET_BRANCH_LABEL(bgeu) + sltu tp, \rs1, \rs2 + branch_resolve \target, 0, \@ +.endm + +.macro getshamt rd, rs1 + sb \rs1, SP_VAR_BYTE(VAR_B, 0) + lbu \rd, SP_VAR_BYTE(VAR_B, 0) + la tp, (_and8_table + (0x1f << 8)) + add \rd, \rd, tp + lbu \rd, (\rd) +.endm + +.macro get_shift_byte_in_tp base, boffset + lbu tp, SP_VAR_BYTE(VAR_A, \boffset) + slli tp, tp, 2 # word per entry + add tp, \base, tp + lw tp, (tp) +.endm + +.macro sll rd, rs1, rs2 + SET_DEBUG_LABEL(sll) + PUSH(s0, 1) + + sw \rs1, SP_VAR(VAR_A) + getshamt s0, \rs2 + sw x0, SP_VAR(VAR_B) + sb s0, SP_VAR_BYTE(VAR_B, 1) + lw s0, SP_VAR(VAR_B) # s0 = s0 << 8 + slli s0, s0, 2 # word per entry + la tp, _sll8_table + add s0, s0, tp + + sw x0, SP_VAR(VAR_B) + get_shift_byte_in_tp s0, 3 + sb tp, SP_VAR_BYTE(VAR_B, 3) + lw gp, SP_VAR(VAR_B) # gp = tp << 24 + + get_shift_byte_in_tp s0, 2 + sh tp, SP_VAR_BYTE(VAR_B, 2) + lw tp, SP_VAR(VAR_B) # tp = tp << 16 + add gp, gp, tp + + get_shift_byte_in_tp s0, 1 + slli tp, tp, 8 + add gp, gp, tp + + get_shift_byte_in_tp s0, 0 + + POP(s0, 1) + add \rd, gp, tp +.endm + +.macro shift_right_template rd, rs1, rs2, is_arith, is_rs2_imm + .if \is_rs2_imm == 1 && \rs2 == 24 # fast path + .if \is_arith == 1 + sw \rs1, SP_VAR(VAR_A) + la tp, (_sra8_table + (\rs2 << 10)) + lbu \rd, SP_VAR_BYTE(VAR_A, 3) + slli \rd, \rd, 2 # word per entry + add tp, tp, \rd + lw \rd, (tp) + .else + getbyte \rd, \rs1, 3 + .endif + .exitm + .endif + + + PUSH(s0, 1) + + sw \rs1, SP_VAR(VAR_A) + .if \is_rs2_imm == 0 + getshamt s0, \rs2 + sw x0, SP_VAR(VAR_B) + sb s0, SP_VAR_BYTE(VAR_B, 1) + lw s0, SP_VAR(VAR_B) # s0 = s0 << 8 + slli s0, s0, 2 # word per entry + la tp, _srl8_table + add s0, s0, tp + .else + la s0, (_srl8_table + (\rs2 << 10)) + .endif + + # result = ((x3 << 24) | (x2 << 16) | (x1 << 8) | x0) >> a + # let y be the values fetched from the table, then + # y3 = (x3 << 24 >> a) + # y2 = (x2 << 24 >> a) + # y1 = (x1 << 24 >> a) + # y0 = (x0 << 24 >> a) + # result = y3 | (y2 >> 8) | (y1 >> 16) | (y0 >> 24) + # = { y33, y32, y31, y30 } | + # { y23, y22, y21 } | + # { y13, y12 } | + # { y03 } + + get_shift_byte_in_tp s0, 2 + sw tp, SP_VAR(VAR_B) + get_shift_byte_in_tp s0, 1 + sw tp, SP_VAR(VAR_C) + get_shift_byte_in_tp s0, 0 + sw tp, SP_VAR(VAR_D) + + # y3 is added in the end + # compute byte 0 + lbu gp, SP_VAR_BYTE(VAR_B, 1) + lbu tp, SP_VAR_BYTE(VAR_C, 2) + add gp, gp, tp + lbu tp, SP_VAR_BYTE(VAR_D, 3) + add gp, gp, tp + sw gp, SP_VAR(VAR_D) # no carry during addition + + # compute byte 1 + lbu gp, SP_VAR_BYTE(VAR_B, 2) + lbu tp, SP_VAR_BYTE(VAR_C, 3) + add gp, gp, tp + sb gp, SP_VAR_BYTE(VAR_D, 1) # no carry during addition + + # compute byte 2 + lbu gp, SP_VAR_BYTE(VAR_B, 3) + sb gp, SP_VAR_BYTE(VAR_D, 2) + + # combine byte 2~0 + lw gp, SP_VAR(VAR_D) + + .if \is_arith == 1 + la tp, (_sra8_table - _srl8_table) + add s0, s0, tp + .endif + + get_shift_byte_in_tp s0, 3 + + POP(s0, 1) + add \rd, gp, tp +.endm + +.macro srl rd, rs1, rs2 + SET_DEBUG_LABEL(srl) + shift_right_template \rd, \rs1, \rs2, 0, 0 +.endm + +.macro sra rd, rs1, rs2 + SET_DEBUG_LABEL(sra) + shift_right_template \rd, \rs1, \rs2, 1, 0 +.endm + + +.macro slli rd, rs1, imm + .if \imm == 0 + .if \rd != \rs1 + mv \rd, \rs1 + .endif + .exitm + .endif + .if \imm >= 24 + sw x0, SP_VAR(VAR_A) + sb \rs1, SP_VAR_BYTE(VAR_A, 3) + lw \rd, SP_VAR(VAR_A) + slli \rd, \rd, (\imm - 24) + .exitm + .endif + .if \imm >= 16 + sw x0, SP_VAR(VAR_A) + sh \rs1, SP_VAR_BYTE(VAR_A, 2) + lw \rd, SP_VAR(VAR_A) + slli \rd, \rd, (\imm - 16) + .exitm + .endif + SET_DEBUG_LABEL(slli) + add \rd, \rs1, \rs1 + .rept (\imm - 1) + add \rd, \rd, \rd + .endr +.endm + +.macro srli rd, rs1, imm + SET_DEBUG_LABEL(srli) + shift_right_template \rd, \rs1, \imm, 0, 1 +.endm + +.macro srai rd, rs1, imm + SET_DEBUG_LABEL(srai) + shift_right_template \rd, \rs1, \imm, 1, 1 +.endm + +def_itype(slti, slt) +def_itype(sltiu, sltu) +def_itype(andi, and) +def_itype(ori, or) +def_itype(xori, xor) + +.macro lb rd, addr + sw x0, SP_VAR(VAR_A) + lbu \rd, \addr + sb \rd, SP_VAR_BYTE(VAR_A, 3) + lw \rd, SP_VAR(VAR_A) + srai \rd, \rd, 24 +.endm + +.macro lhu rd, addr + sw x0, SP_VAR(VAR_A) + lbu tp, 1 + \addr + sb tp, SP_VAR_BYTE(VAR_A, 1) + lw tp, SP_VAR(VAR_A) + lbu \rd, 0 + \addr + add \rd, \rd, tp +.endm + +.macro lh rd, addr + sw x0, SP_VAR(VAR_A) + lbu gp, 1 + \addr + sb gp, SP_VAR_BYTE(VAR_A, 3) + lw gp, SP_VAR(VAR_A) + srai gp, gp, 16 + lbu \rd, 0 + \addr + add \rd, \rd, gp +.endm + +.macro sh rs, addr + sb \rs, 0 + \addr + getbyte tp, \rs, 1 + sb tp, 1 + \addr +.endm + +# RISC-V pseudo-instruction + +.macro la r, addr + lui \r, %hi(\addr) + addi \r, \r, %lo(\addr) +.endm + +.macro lla r, addr + la \r, \addr +.endm + +.macro call addr + call_template ra, \addr +.endm + +.macro tail addr + la tp, \addr + jr tp + call_template ra, \addr +.endm + +.macro j addr + call_template tp, \addr +.endm + +.macro not rd, rs1 + PUSH(gp, 3) + sw \rs1, SP_VAR(VAR_C) + la tp, (_xor8_table + (0xff << 8)) + + lbu gp, SP_VAR_BYTE(VAR_C, 3) + add gp, gp, tp + lbu gp, (gp) + sb gp, SP_VAR_BYTE(VAR_D, 3) + + lbu gp, SP_VAR_BYTE(VAR_C, 2) + add gp, gp, tp + lbu gp, (gp) + sb gp, SP_VAR_BYTE(VAR_D, 2) + + lbu gp, SP_VAR_BYTE(VAR_C, 1) + add gp, gp, tp + lbu gp, (gp) + sb gp, SP_VAR_BYTE(VAR_D, 1) + + lbu gp, SP_VAR_BYTE(VAR_C, 0) + add gp, gp, tp + lbu gp, (gp) + sb gp, SP_VAR_BYTE(VAR_D, 0) + + POP(gp, 3) + + lw \rd, SP_VAR(VAR_D) +.endm + +.macro neg rd, rs + sub \rd, x0, \rs +.endm + +.macro snez rd, rs + sltu \rd, x0, \rs +.endm + +.macro sltz rd, rs + msb \rd, \rs +.endm + +.macro sgt rd, rs1, rs2 + slt \rd, \rs2, \rs1 +.endm + +.macro sgtu rd, rs1, rs2 + sltu \rd, \rs2, \rs1 +.endm + +.macro sgtz rd, rs + slt \rd, x0, \rs +.endm + +#if 0 +# already defined above +.macro seqz rd, rs + sltiu \rd, \rs, 1 +.endm +#endif + +.macro beqz rs, offset + beq \rs, x0, \offset +.endm + +.macro bnez rs, offset + bne \rs, x0, \offset +.endm + +.macro blez rs, offset + bge x0, \rs, \offset +.endm + +.macro bgez rs, offset + bge \rs, x0, \offset +.endm + +.macro bltz rs, offset + blt \rs, x0, \offset +.endm + +.macro bgtz rs, offset + blt x0, \rs, \offset +.endm + +.macro bgt rs, rt, offset + blt \rt, \rs, \offset +.endm + +.macro ble rs, rt, offset + bge \rt, \rs, \offset +.endm + +.macro bgtu rs, rt, offset + bltu \rt, \rs, \offset +.endm + +.macro bleu rs, rt, offset + bgeu \rt, \rs, \offset +.endm + +#undef _concat +#undef concat +#undef PUSH +#undef POP diff --git a/tools/rvmini/rvmini-common.sh b/tools/rvmini/rvmini-common.sh new file mode 100644 index 0000000..823c3dc --- /dev/null +++ b/tools/rvmini/rvmini-common.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +src=${*: -1} +dst=${*: -2:1} +cc=$1 +flags=${*: 2:$#-4} + +dst_S=${dst%.o}.S +if [[ "$src" == *.S ]] then + cp $src $dst_S +else + riscv64-linux-gnu-$cc $flags -S -o $dst_S $src +fi + +# replace pseudo instructions for load/store +sp="[[:space:]]*" +reg="[[:alnum:]]+" +comma="$sp,$sp" +symbol="[[:alnum:]_]+" +sed -E -i -e "s/(l[bhw]u?)${sp}(${reg})${comma}(${symbol})(${sp}[-+]${sp}${symbol})?${sp}\$/la \2, \3\4; \1 \2, 0(\2);/" \ + -e "s/(s[bhw])${sp}(${reg})${comma}(${symbol})(${sp}[-+]${sp}${symbol})?${comma}(${reg})${sp}\$/la \5, \3\4; \1 \2, 0(\5);/" $dst_S + +# insert inst-replace.h to each .h files +rvmini_path=$AM_HOME/tools/rvmini +lut_bin_path=$rvmini_path/lut.bin +sed -i "1i#include \"$rvmini_path/inst-replace.h\"" $dst_S +flock $rvmini_path/.lock -c "test -e $lut_bin_path || (cd $rvmini_path && gcc gen-lut.c && ./a.out && rm a.out)" + +riscv64-linux-gnu-gcc $flags -D_LUT_BIN_PATH=\"$lut_bin_path\" -Wno-trigraphs -c -o $dst $dst_S diff --git a/tools/rvmini/rvmini-g++ b/tools/rvmini/rvmini-g++ new file mode 100755 index 0000000..8f7e823 --- /dev/null +++ b/tools/rvmini/rvmini-g++ @@ -0,0 +1,3 @@ +#!/bin/bash + +bash rvmini-common.sh g++ $@ diff --git a/tools/rvmini/rvmini-gcc b/tools/rvmini/rvmini-gcc new file mode 100755 index 0000000..b591d81 --- /dev/null +++ b/tools/rvmini/rvmini-gcc @@ -0,0 +1,3 @@ +#!/bin/bash + +bash rvmini-common.sh gcc $@