add riscv32mini-nemu
This commit is contained in:
parent
e76ca7406a
commit
56d4ae7165
7 changed files with 818 additions and 6 deletions
6
Makefile
6
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)
|
||||
|
|
24
scripts/riscv32mini-nemu.mk
Normal file
24
scripts/riscv32mini-nemu.mk
Normal file
|
@ -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
|
29
tools/rvmini/gen-lut.c
Normal file
29
tools/rvmini/gen-lut.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#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;
|
||||
}
|
730
tools/rvmini/inst-replace.h
Normal file
730
tools/rvmini/inst-replace.h
Normal file
|
@ -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
|
29
tools/rvmini/rvmini-common.sh
Normal file
29
tools/rvmini/rvmini-common.sh
Normal file
|
@ -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
|
3
tools/rvmini/rvmini-g++
Executable file
3
tools/rvmini/rvmini-g++
Executable file
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
bash rvmini-common.sh g++ $@
|
3
tools/rvmini/rvmini-gcc
Executable file
3
tools/rvmini/rvmini-gcc
Executable file
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
bash rvmini-common.sh gcc $@
|
Loading…
Add table
Reference in a new issue