added C-extension support
This commit is contained in:
@@ -2,21 +2,21 @@ CC = riscv64-linux-gnu-gcc
|
|||||||
OBJCOPY = riscv64-linux-gnu-objcopy
|
OBJCOPY = riscv64-linux-gnu-objcopy
|
||||||
EMULATOR = ./amach
|
EMULATOR = ./amach
|
||||||
|
|
||||||
ASFLAGS = -march=rv32ima -mabi=ilp32 -nostdlib -s -static -fno-pic -fno-pie -mno-relax
|
ASFLAGS = -march=rv32imac -mabi=ilp32 -nostdlib -s -static -fno-pic -fno-pie -mno-relax
|
||||||
LDFLAGS = -Wl,-Ttext=0x100b0 -Wl,--build-id=none
|
LDFLAGS = -Wl,-Ttext=0x100b0 -Wl,--build-id=none
|
||||||
|
|
||||||
all: rv32ima_tests.bin
|
all: rv32imac_tests.bin
|
||||||
|
|
||||||
rv32ima_tests.elf: rv32ima_tests.s
|
rv32imac_tests.elf: rv32imac_tests.s
|
||||||
$(CC) $(ASFLAGS) $(LDFLAGS) rv32ima_tests.s -o rv32ima_tests.elf
|
$(CC) $(ASFLAGS) $(LDFLAGS) rv32imac_tests.s -o rv32imac_tests.elf
|
||||||
|
|
||||||
rv32ima_tests.bin: rv32ima_tests.elf
|
rv32imac_tests.bin: rv32imac_tests.elf
|
||||||
$(OBJCOPY) -O binary rv32ima_tests.elf rv32ima_tests.bin
|
$(OBJCOPY) -O binary rv32imac_tests.elf rv32imac_tests.bin
|
||||||
|
|
||||||
run: rv32ima_tests.bin
|
run: rv32imac_tests.bin
|
||||||
$(EMULATOR) rv32ima_tests.bin
|
$(EMULATOR) rv32imac_tests.bin
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f rv32ima_tests.elf rv32ima_tests.bin
|
rm -f rv32imac_tests.elf rv32imac_tests.bin
|
||||||
|
|
||||||
.PHONY: all run clean
|
.PHONY: all run clean
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
# A-machine: a minimal RISC-V (RV32IMA) emulator in POSIX AWK
|
# A-machine: a minimal RISC-V (RV32IMAC) emulator in POSIX AWK
|
||||||
|
|
||||||
## About
|
## About
|
||||||
|
|
||||||
A-machine is a simple and straightforward implementation of the RV32I specification with M (multiplication/division) and A (atomic operations) extenstions. It consists of two files:
|
A-machine is a simple and straightforward implementation of the RV32I specification with M (multiplication/division), A (atomic operations), and C (compressed instructions) extensions. It consists of two files:
|
||||||
|
|
||||||
- [amach.awk](amach.awk), the emulator core itself that supports .dec files,
|
- [amach.awk](amach.awk), the emulator core itself that supports .dec files,
|
||||||
- and [amach](amach) shell script which is a two-liner that uses POSIX `od` to convert .bin files into .dec files on the fly and then passes them to the emulator core.
|
- and [amach](amach) shell script which is a two-liner that uses POSIX `od` to convert .bin files into .dec files on the fly and then passes them to the emulator core.
|
||||||
|
|
||||||
Additionally, A-machine is shipped with a reference test suite that assumes that you have a full RISC-V toolchain installed under the `riscv64-linux-gnu-` prefix (adjustable in the `Makefile`). Just run `make run` to build and run all tests. In case you don't have any toolchain available, a file called `rv32ima_tests.bin` is also included into the repo.
|
Additionally, A-machine is shipped with a reference test suite that assumes that you have a full RISC-V toolchain installed under the `riscv64-linux-gnu-` prefix (adjustable in the `Makefile`). Just run `make run` to build and run all tests. In case you don't have any toolchain available, a file called `rv32imac_tests.bin` is also included into the repo.
|
||||||
|
|
||||||
The project is to be considered highly experimental and not production-ready in any way.
|
The project is to be considered highly experimental and not production-ready in any way.
|
||||||
|
|
||||||
@@ -32,11 +32,10 @@ POSIXLY_CORRECT=1 awk -f amach.awk [-v LVA=...] -- path/to/program.dec
|
|||||||
|
|
||||||
## Support
|
## Support
|
||||||
|
|
||||||
Currently, A-machine only supports the **unprivileged** RV32IMA instruction set with a few additional `ecall` syscalls: 63 (sys_read, for fd 0 only), 64 (sys_write, for fd 1 and 2 only) and 93 (sys_exit). For completeness, `fence` instruction is also supported but yields a no-op.
|
Currently, A-machine only supports the **unprivileged** RV32IMAC instruction set with a few additional `ecall` syscalls: 63 (sys_read, for fd 0 only), 64 (sys_write, for fd 1 and 2 only) and 93 (sys_exit). For completeness, `fence` instruction is also supported but yields a no-op.
|
||||||
|
|
||||||
## Plans (from higher to lower priority)
|
## Plans (from higher to lower priority)
|
||||||
|
|
||||||
- Implement the C-extension (compressed instruction set).
|
|
||||||
- Implement a simple RV32IMAC disassembler in POSIX AWK.
|
- Implement a simple RV32IMAC disassembler in POSIX AWK.
|
||||||
- Introduce more popular Linux-compatible syscalls (that make sense to implement in AWK but don't increase the overall project complexity).
|
- Introduce more popular Linux-compatible syscalls (that make sense to implement in AWK but don't increase the overall project complexity).
|
||||||
- Test for RV32EMC compatibility (that the code built for the "embedded" variant runs here).
|
- Test for RV32EMC compatibility (that the code built for the "embedded" variant runs here).
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env awk -f
|
#!/usr/bin/env awk -f
|
||||||
# A-Machine: an experimental RISC-V (RV32IMA) emulator in POSIX AWK
|
# A-Machine: an experimental RISC-V (RV32IMAC) emulator in POSIX AWK
|
||||||
# with a very small subset of supported ECALLs
|
# with a very small subset of supported ECALLs
|
||||||
# Accepts a headerless binary previously converted to .dec format
|
# Accepts a headerless binary previously converted to .dec format
|
||||||
# e.g. with POSIX od: od -An -v -tu1 program.bin > program.dec
|
# e.g. with POSIX od: od -An -v -tu1 program.bin > program.dec
|
||||||
@@ -275,8 +275,148 @@ function amach_atomic(f3, f5, aq, rl, rd, rs1, rs2, r1, r2, val, uval, ur2) {
|
|||||||
} else trapout(sprintf("Illegal atomic instruction at 0x%X", pc-4))
|
} else trapout(sprintf("Illegal atomic instruction at 0x%X", pc-4))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# C-extension (compressed instructions) handler
|
||||||
|
function amach_comp(instr, op, f3, b12, r11_7, r9_7, r6_2, r4_2, shamt, imm, base, val) {
|
||||||
|
op = instr % 4
|
||||||
|
f3 = int(instr / 8192) % 8
|
||||||
|
b12 = int(instr / 4096) % 2
|
||||||
|
r11_7 = int(instr / 128) % 32
|
||||||
|
r9_7 = (int(instr / 128) % 8) + 8
|
||||||
|
r6_2 = int(instr / 4) % 32
|
||||||
|
r4_2 = (int(instr / 4) % 8) + 8
|
||||||
|
shamt = r6_2 + b12 * 32
|
||||||
|
|
||||||
|
if (op == 0) {
|
||||||
|
if (f3 == 0) { # C.ADDI4SPN
|
||||||
|
imm = (int(instr / 128) % 16) * 64 + (int(instr / 2048) % 4) * 16 + (int(instr / 32) % 2) * 8 + (int(instr / 64) % 2) * 4
|
||||||
|
if (imm == 0) trapout(sprintf("Illegal instruction C.ADDI4SPN at 0x%X", pc-2))
|
||||||
|
setreg(r4_2, getreg(2) + imm)
|
||||||
|
} else if (f3 == 2) { # C.LW
|
||||||
|
imm = (int(instr / 32) % 2) * 64 + (int(instr / 1024) % 8) * 8 + (int(instr / 64) % 2) * 4
|
||||||
|
base = (getreg(r9_7) + imm) % 4294967296
|
||||||
|
if (base < 0) base += 4294967296
|
||||||
|
val = MEM[base] + MEM[(base+1)%4294967296]*256 + MEM[(base+2)%4294967296]*65536 + MEM[(base+3)%4294967296]*16777216
|
||||||
|
setreg(r4_2, val)
|
||||||
|
} else if (f3 == 6) { # C.SW
|
||||||
|
imm = (int(instr / 32) % 2) * 64 + (int(instr / 1024) % 8) * 8 + (int(instr / 64) % 2) * 4
|
||||||
|
base = (getreg(r9_7) + imm) % 4294967296
|
||||||
|
if (base < 0) base += 4294967296
|
||||||
|
val = getreg(r4_2)
|
||||||
|
if (val < 0) val += 4294967296
|
||||||
|
MEM[base] = val % 256
|
||||||
|
MEM[(base+1)%4294967296] = int(val/256) % 256
|
||||||
|
MEM[(base+2)%4294967296] = int(val/65536) % 256
|
||||||
|
MEM[(base+3)%4294967296] = int(val/16777216) % 256
|
||||||
|
} else trapout(sprintf("Illegal instruction at 0x%X", pc-2))
|
||||||
|
} else if (op == 1) {
|
||||||
|
if (f3 == 0) { # C.NOP / C.ADDI
|
||||||
|
imm = r6_2 + b12 * 32
|
||||||
|
if (imm >= 32) imm -= 64
|
||||||
|
setreg(r11_7, getreg(r11_7) + imm)
|
||||||
|
} else if (f3 == 1 || f3 == 5) { # C.JAL / C.J
|
||||||
|
imm = b12 * 2048 + (int(instr / 256) % 2) * 1024 + (int(instr / 512) % 4) * 256 + (int(instr / 64) % 2) * 128 + (int(instr / 128) % 2) * 64 + (int(instr / 4) % 2) * 32 + (int(instr / 2048) % 2) * 16 + (int(instr / 8) % 8) * 2
|
||||||
|
if (imm >= 2048) imm -= 4096
|
||||||
|
if (f3 == 1) setreg(1, pc)
|
||||||
|
pc = (pc - 2) + imm
|
||||||
|
} else if (f3 == 2) { # C.LI
|
||||||
|
imm = r6_2 + b12 * 32
|
||||||
|
if (imm >= 32) imm -= 64
|
||||||
|
setreg(r11_7, imm)
|
||||||
|
} else if (f3 == 3) { # C.ADDI16SP / C.LUI
|
||||||
|
if (r11_7 == 2) { # C.ADDI16SP
|
||||||
|
imm = b12 * 512 + (int(instr / 8) % 4) * 128 + (int(instr / 32) % 2) * 64 + (int(instr / 4) % 2) * 32 + (int(instr / 64) % 2) * 16
|
||||||
|
if (imm >= 512) imm -= 1024
|
||||||
|
if (imm == 0) trapout(sprintf("Illegal instruction C.ADDI16SP at 0x%X", pc-2))
|
||||||
|
setreg(2, getreg(2) + imm)
|
||||||
|
} else if (r11_7 != 0) { # C.LUI
|
||||||
|
imm = r6_2 + b12 * 32
|
||||||
|
if (imm >= 32) imm -= 64
|
||||||
|
imm = imm * 4096
|
||||||
|
if (imm == 0) trapout(sprintf("Illegal instruction C.LUI at 0x%X", pc-2))
|
||||||
|
setreg(r11_7, imm)
|
||||||
|
}
|
||||||
|
} else if (f3 == 4) {
|
||||||
|
val = int(instr / 1024) % 4
|
||||||
|
if (val == 0) { # C.SRLI
|
||||||
|
if (shamt >= 32) trapout(sprintf("Illegal shift amount %d at 0x%X", shamt, pc-2))
|
||||||
|
imm = getreg(r9_7)
|
||||||
|
if (imm < 0) imm += 4294967296
|
||||||
|
setreg(r9_7, int(imm / (2^shamt)))
|
||||||
|
} else if (val == 1) { # C.SRAI
|
||||||
|
if (shamt >= 32) trapout(sprintf("Illegal shift amount %d at 0x%X", shamt, pc-2))
|
||||||
|
setreg(r9_7, floor(getreg(r9_7) / (2^shamt)))
|
||||||
|
} else if (val == 2) { # C.ANDI
|
||||||
|
imm = r6_2 + b12 * 32
|
||||||
|
if (imm >= 32) imm -= 64
|
||||||
|
setreg(r9_7, bw_and(getreg(r9_7), imm))
|
||||||
|
} else if (val == 3) { # C.SUB, C.XOR, C.OR, C.AND
|
||||||
|
imm = int(instr / 32) % 4
|
||||||
|
if (b12 != 0) trapout(sprintf("Illegal register-register instruction at 0x%X", pc-2))
|
||||||
|
if (imm == 0) setreg(r9_7, getreg(r9_7) - getreg(r4_2))
|
||||||
|
else if (imm == 1) setreg(r9_7, bw_xor(getreg(r9_7), getreg(r4_2)))
|
||||||
|
else if (imm == 2) setreg(r9_7, bw_or(getreg(r9_7), getreg(r4_2)))
|
||||||
|
else if (imm == 3) setreg(r9_7, bw_and(getreg(r9_7), getreg(r4_2)))
|
||||||
|
}
|
||||||
|
} else if (f3 == 6 || f3 == 7) { # C.BEQZ / C.BNEZ
|
||||||
|
imm = b12 * 256 + (int(instr / 32) % 4) * 64 + (int(instr / 4) % 2) * 32 + (int(instr / 1024) % 4) * 8 + (int(instr / 8) % 4) * 2
|
||||||
|
if (imm >= 256) imm -= 512
|
||||||
|
val = (f3 == 6) ? (getreg(r9_7) == 0) : (getreg(r9_7) != 0)
|
||||||
|
pc = val ? (pc - 2) + imm : pc
|
||||||
|
}
|
||||||
|
} else if (op == 2) {
|
||||||
|
if (f3 == 0) { # C.SLLI
|
||||||
|
if (shamt >= 32) trapout(sprintf("Illegal shift amount %d at 0x%X", shamt, pc-2))
|
||||||
|
if (r11_7 != 0) {
|
||||||
|
setreg(r11_7, (getreg(r11_7) * (2^shamt)) % 4294967296)
|
||||||
|
}
|
||||||
|
} else if (f3 == 2) { # C.LWSP
|
||||||
|
if (r11_7 == 0) trapout(sprintf("Illegal instruction C.LWSP with rd=0 at 0x%X", pc-2))
|
||||||
|
imm = (int(instr / 4) % 4) * 64 + b12 * 32 + (int(instr / 16) % 8) * 4
|
||||||
|
base = (getreg(2) + imm) % 4294967296
|
||||||
|
if (base < 0) base += 4294967296
|
||||||
|
val = MEM[base] + MEM[(base+1)%4294967296]*256 + MEM[(base+2)%4294967296]*65536 + MEM[(base+3)%4294967296]*16777216
|
||||||
|
setreg(r11_7, val)
|
||||||
|
} else if (f3 == 4) { # C.JR, C.MV, C.JALR, C.ADD
|
||||||
|
if (b12 == 0) {
|
||||||
|
if (r6_2 == 0) { # C.JR
|
||||||
|
if (r11_7 == 0) trapout(sprintf("Illegal instruction C.JR with rs1=0 at 0x%X", pc-2))
|
||||||
|
pc = getreg(r11_7)
|
||||||
|
} else { # C.MV
|
||||||
|
setreg(r11_7, getreg(r6_2))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (r6_2 == 0) {
|
||||||
|
if (r11_7 == 0) { # C.EBREAK
|
||||||
|
trapout(sprintf("EBREAK at 0x%X", pc-2))
|
||||||
|
} else { # C.JALR
|
||||||
|
imm = getreg(r11_7)
|
||||||
|
setreg(1, pc)
|
||||||
|
pc = imm
|
||||||
|
}
|
||||||
|
} else { # C.ADD
|
||||||
|
setreg(r11_7, getreg(r11_7) + getreg(r6_2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (f3 == 6) { # C.SWSP
|
||||||
|
imm = (int(instr / 128) % 4) * 64 + (int(instr / 512) % 16) * 4
|
||||||
|
base = (getreg(2) + imm) % 4294967296
|
||||||
|
if (base < 0) base += 4294967296
|
||||||
|
val = getreg(r6_2)
|
||||||
|
if (val < 0) val += 4294967296
|
||||||
|
MEM[base] = val % 256
|
||||||
|
MEM[(base+1)%4294967296] = int(val/256) % 256
|
||||||
|
MEM[(base+2)%4294967296] = int(val/65536) % 256
|
||||||
|
MEM[(base+3)%4294967296] = int(val/16777216) % 256
|
||||||
|
} else trapout(sprintf("Illegal instruction at 0x%X", pc-2))
|
||||||
|
} else trapout(sprintf("Illegal instruction at 0x%X", pc-2))
|
||||||
|
}
|
||||||
|
|
||||||
# main instruction decoding and execution routine
|
# main instruction decoding and execution routine
|
||||||
function amach_exec(instr, opcode, rd, rs1, rs2, imm, funct3, funct7) {
|
function amach_exec(instr, opcode, rd, rs1, rs2, imm, funct3, funct7) {
|
||||||
|
if ((instr % 4) != 3) {
|
||||||
|
amach_comp(instr)
|
||||||
|
return
|
||||||
|
}
|
||||||
opcode = instr % 128
|
opcode = instr % 128
|
||||||
instr = int(instr / 128)
|
instr = int(instr / 128)
|
||||||
rd = instr % 32
|
rd = instr % 32
|
||||||
|
|||||||
Binary file not shown.
Executable
BIN
Binary file not shown.
@@ -1,4 +1,5 @@
|
|||||||
.section .text
|
.section .text
|
||||||
|
.option norvc
|
||||||
.global _start
|
.global _start
|
||||||
|
|
||||||
.macro INC_TESTS
|
.macro INC_TESTS
|
||||||
@@ -530,6 +531,229 @@ _start:
|
|||||||
# ==========================================
|
# ==========================================
|
||||||
fence
|
fence
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# RV32C Compressed Instruction Tests
|
||||||
|
# ==========================================
|
||||||
|
.option rvc
|
||||||
|
|
||||||
|
# 1. c.addi4spn
|
||||||
|
INC_TESTS
|
||||||
|
mv s0, sp
|
||||||
|
c.addi4spn a0, sp, 40
|
||||||
|
sub a0, a0, s0
|
||||||
|
ASSERT_EQ a0, 40, c_addi4spn_val
|
||||||
|
|
||||||
|
# 2. c.lw and c.sw
|
||||||
|
INC_TESTS
|
||||||
|
la a1, data_buffer
|
||||||
|
li a0, 0x76543210
|
||||||
|
sw a0, 4(a1)
|
||||||
|
c.lw a2, 4(a1)
|
||||||
|
ASSERT_EQ a2, 0x76543210, c_lw_val
|
||||||
|
|
||||||
|
INC_TESTS
|
||||||
|
li a0, 0x11223344
|
||||||
|
c.sw a0, 8(a1)
|
||||||
|
lw a2, 8(a1)
|
||||||
|
ASSERT_EQ a2, 0x11223344, c_sw_val
|
||||||
|
|
||||||
|
# 3. c.nop
|
||||||
|
INC_TESTS
|
||||||
|
c.nop
|
||||||
|
li a0, 1
|
||||||
|
ASSERT_EQ a0, 1, c_nop_val
|
||||||
|
|
||||||
|
# 4. c.addi
|
||||||
|
INC_TESTS
|
||||||
|
li a0, 10
|
||||||
|
c.addi a0, -3
|
||||||
|
ASSERT_EQ a0, 7, c_addi_val
|
||||||
|
|
||||||
|
# 5. c.jal
|
||||||
|
INC_TESTS
|
||||||
|
3:
|
||||||
|
c.jal 1f
|
||||||
|
li a0, 0
|
||||||
|
j 2f
|
||||||
|
1:
|
||||||
|
li a0, 1
|
||||||
|
2:
|
||||||
|
ASSERT_EQ a0, 1, c_jal_val
|
||||||
|
|
||||||
|
INC_TESTS
|
||||||
|
la a1, 3b + 2
|
||||||
|
ASSERT_EQ_REG ra, a1, c_jal_link
|
||||||
|
|
||||||
|
# 6. c.li
|
||||||
|
INC_TESTS
|
||||||
|
c.li a0, -15
|
||||||
|
ASSERT_EQ a0, -15, c_li_val
|
||||||
|
|
||||||
|
# 7. c.addi16sp
|
||||||
|
INC_TESTS
|
||||||
|
mv s0, sp
|
||||||
|
c.addi16sp sp, -32
|
||||||
|
sub a0, s0, sp
|
||||||
|
ASSERT_EQ a0, 32, c_addi16sp_val
|
||||||
|
mv sp, s0
|
||||||
|
|
||||||
|
# 8. c.lui
|
||||||
|
INC_TESTS
|
||||||
|
c.lui a0, 15
|
||||||
|
ASSERT_EQ a0, 0xf000, c_lui_val
|
||||||
|
|
||||||
|
# 9. c.srli, c.srai, c.andi
|
||||||
|
INC_TESTS
|
||||||
|
li a0, 0x80
|
||||||
|
c.srli a0, 3
|
||||||
|
ASSERT_EQ a0, 0x10, c_srli_val
|
||||||
|
|
||||||
|
INC_TESTS
|
||||||
|
li a0, -16
|
||||||
|
c.srai a0, 2
|
||||||
|
ASSERT_EQ a0, -4, c_srai_val
|
||||||
|
|
||||||
|
INC_TESTS
|
||||||
|
li a0, 15
|
||||||
|
c.andi a0, 9
|
||||||
|
ASSERT_EQ a0, 9, c_andi_val
|
||||||
|
|
||||||
|
# 10. c.sub, c.xor, c.or, c.and
|
||||||
|
INC_TESTS
|
||||||
|
li a0, 15
|
||||||
|
li a1, 5
|
||||||
|
c.sub a0, a1
|
||||||
|
ASSERT_EQ a0, 10, c_sub_val
|
||||||
|
|
||||||
|
INC_TESTS
|
||||||
|
li a0, 5
|
||||||
|
li a1, 3
|
||||||
|
c.xor a0, a1
|
||||||
|
ASSERT_EQ a0, 6, c_xor_val
|
||||||
|
|
||||||
|
INC_TESTS
|
||||||
|
li a0, 5
|
||||||
|
li a1, 3
|
||||||
|
c.or a0, a1
|
||||||
|
ASSERT_EQ a0, 7, c_or_val
|
||||||
|
|
||||||
|
INC_TESTS
|
||||||
|
li a0, 5
|
||||||
|
li a1, 3
|
||||||
|
c.and a0, a1
|
||||||
|
ASSERT_EQ a0, 1, c_and_val
|
||||||
|
|
||||||
|
# 11. c.j
|
||||||
|
INC_TESTS
|
||||||
|
c.j 1f
|
||||||
|
li a0, 0
|
||||||
|
j 2f
|
||||||
|
1:
|
||||||
|
li a0, 1
|
||||||
|
2:
|
||||||
|
ASSERT_EQ a0, 1, c_j_val
|
||||||
|
|
||||||
|
# 12. c.beqz, c.bnez
|
||||||
|
INC_TESTS
|
||||||
|
li a0, 0
|
||||||
|
c.beqz a0, 1f
|
||||||
|
li a1, 0
|
||||||
|
j 2f
|
||||||
|
1:
|
||||||
|
li a1, 1
|
||||||
|
2:
|
||||||
|
ASSERT_EQ a1, 1, c_beqz_taken
|
||||||
|
|
||||||
|
INC_TESTS
|
||||||
|
li a0, 1
|
||||||
|
c.beqz a0, 1f
|
||||||
|
li a1, 0
|
||||||
|
j 2f
|
||||||
|
1:
|
||||||
|
li a1, 1
|
||||||
|
2:
|
||||||
|
ASSERT_EQ a1, 0, c_beqz_not_taken
|
||||||
|
|
||||||
|
INC_TESTS
|
||||||
|
li a0, 1
|
||||||
|
c.bnez a0, 1f
|
||||||
|
li a1, 0
|
||||||
|
j 2f
|
||||||
|
1:
|
||||||
|
li a1, 1
|
||||||
|
2:
|
||||||
|
ASSERT_EQ a1, 1, c_bnez_taken
|
||||||
|
|
||||||
|
INC_TESTS
|
||||||
|
li a0, 0
|
||||||
|
c.bnez a0, 1f
|
||||||
|
li a1, 0
|
||||||
|
j 2f
|
||||||
|
1:
|
||||||
|
li a1, 1
|
||||||
|
2:
|
||||||
|
ASSERT_EQ a1, 0, c_bnez_not_taken
|
||||||
|
|
||||||
|
# 13. c.slli
|
||||||
|
INC_TESTS
|
||||||
|
li a0, 5
|
||||||
|
c.slli a0, 2
|
||||||
|
ASSERT_EQ a0, 20, c_slli_val
|
||||||
|
|
||||||
|
# 14. c.lwsp, c.swsp
|
||||||
|
INC_TESTS
|
||||||
|
mv s0, sp
|
||||||
|
c.addi16sp sp, -32
|
||||||
|
li a0, 0x11223344
|
||||||
|
sw a0, 16(sp)
|
||||||
|
c.lwsp a1, 16(sp)
|
||||||
|
ASSERT_EQ a1, 0x11223344, c_lwsp_val
|
||||||
|
|
||||||
|
INC_TESTS
|
||||||
|
li a0, 0x55667788
|
||||||
|
c.swsp a0, 20(sp)
|
||||||
|
lw a1, 20(sp)
|
||||||
|
ASSERT_EQ a1, 0x55667788, c_swsp_val
|
||||||
|
mv sp, s0
|
||||||
|
|
||||||
|
# 15. c.jr, c.mv, c.jalr, c.add
|
||||||
|
INC_TESTS
|
||||||
|
la a0, 1f
|
||||||
|
c.jr a0
|
||||||
|
li a1, 0
|
||||||
|
j 2f
|
||||||
|
1:
|
||||||
|
li a1, 1
|
||||||
|
2:
|
||||||
|
ASSERT_EQ a1, 1, c_jr_val
|
||||||
|
|
||||||
|
INC_TESTS
|
||||||
|
li a1, 42
|
||||||
|
c.mv a0, a1
|
||||||
|
ASSERT_EQ a0, 42, c_mv_val
|
||||||
|
|
||||||
|
INC_TESTS
|
||||||
|
la a0, 1f
|
||||||
|
3:
|
||||||
|
c.jalr a0
|
||||||
|
li a1, 0
|
||||||
|
j 2f
|
||||||
|
1:
|
||||||
|
li a1, 1
|
||||||
|
2:
|
||||||
|
ASSERT_EQ a1, 1, c_jalr_val
|
||||||
|
INC_TESTS
|
||||||
|
la a2, 3b + 2
|
||||||
|
ASSERT_EQ_REG ra, a2, c_jalr_link
|
||||||
|
|
||||||
|
INC_TESTS
|
||||||
|
li a0, 10
|
||||||
|
li a1, 20
|
||||||
|
c.add a0, a1
|
||||||
|
ASSERT_EQ a0, 30, c_add_val
|
||||||
|
|
||||||
|
.option norvc
|
||||||
|
|
||||||
# ==========================================
|
# ==========================================
|
||||||
# Report Results
|
# Report Results
|
||||||
# ==========================================
|
# ==========================================
|
||||||
Reference in New Issue
Block a user