966 lines
16 KiB
ArmAsm
966 lines
16 KiB
ArmAsm
.section .text
|
|
.option norvc
|
|
.global _start
|
|
|
|
.macro INC_TESTS
|
|
la s10, test_count
|
|
lw s11, 0(s10)
|
|
addi s11, s11, 1
|
|
sw s11, 0(s10)
|
|
.endm
|
|
|
|
.macro ASSERT_EQ reg, expected, msg
|
|
li s10, \expected
|
|
mv s11, \reg
|
|
beq s10, s11, .L_success_\@
|
|
# Failure
|
|
la a0, .L_msg_\@
|
|
mv a1, s11
|
|
li a2, \expected
|
|
jal report_failure
|
|
j .L_end_\@
|
|
.L_success_\@:
|
|
# Success
|
|
la s10, success_count
|
|
lw s11, 0(s10)
|
|
addi s11, s11, 1
|
|
sw s11, 0(s10)
|
|
.L_end_\@:
|
|
.section .rodata
|
|
.L_msg_\@: .string "\msg"
|
|
.section .text
|
|
.endm
|
|
|
|
.macro ASSERT_EQ_REG reg, expected_reg, msg
|
|
mv s10, \expected_reg
|
|
mv s11, \reg
|
|
beq s10, s11, .L_success_reg_\@
|
|
# Failure
|
|
la a0, .L_msg_reg_\@
|
|
mv a1, s11
|
|
mv a2, s10
|
|
jal report_failure
|
|
j .L_end_reg_\@
|
|
.L_success_reg_\@:
|
|
# Success
|
|
la s10, success_count
|
|
lw s11, 0(s10)
|
|
addi s11, s11, 1
|
|
sw s11, 0(s10)
|
|
.L_end_reg_\@:
|
|
.section .rodata
|
|
.L_msg_reg_\@: .string "\msg"
|
|
.section .text
|
|
.endm
|
|
|
|
.macro TEST_VAL_RI inst, val1, imm, expected, name
|
|
INC_TESTS
|
|
li t1, \val1
|
|
\inst t0, t1, \imm
|
|
ASSERT_EQ t0, \expected, \name
|
|
.endm
|
|
|
|
.macro TEST_VAL_RR inst, val1, val2, expected, name
|
|
INC_TESTS
|
|
li t1, \val1
|
|
li t2, \val2
|
|
\inst t0, t1, t2
|
|
ASSERT_EQ t0, \expected, \name
|
|
.endm
|
|
|
|
_start:
|
|
# ==========================================
|
|
# RV32I Immediate Arithmetic
|
|
# ==========================================
|
|
TEST_VAL_RI addi, 10, 20, 30, addi_pos
|
|
TEST_VAL_RI addi, 10, -20, -10, addi_neg
|
|
TEST_VAL_RI addi, 0x7fffffff, 1, 0x80000000, addi_overflow
|
|
|
|
TEST_VAL_RI slti, 10, 20, 1, slti_lt
|
|
TEST_VAL_RI slti, 20, 10, 0, slti_gt
|
|
TEST_VAL_RI slti, -10, 10, 1, slti_neg_lt
|
|
|
|
TEST_VAL_RI sltiu, 10, 20, 1, sltiu_lt
|
|
TEST_VAL_RI sltiu, -10, 10, 0, sltiu_neg_gt
|
|
|
|
TEST_VAL_RI xori, 0xf0f0f0f0, 0x0ff, 0xf0f0f00f, xori_val
|
|
TEST_VAL_RI ori, 0xf0f0f0f0, 0x0ff, 0xf0f0f0ff, ori_val
|
|
TEST_VAL_RI andi, 0xf0f0f0f0, 0x0ff, 0x000000f0, andi_val
|
|
|
|
TEST_VAL_RI slli, 1, 5, 32, slli_val
|
|
TEST_VAL_RI slli, 0x80000000, 1, 0, slli_overflow
|
|
|
|
TEST_VAL_RI srli, 32, 5, 1, srli_val
|
|
TEST_VAL_RI srli, 0x80000000, 1, 0x40000000, srli_sign
|
|
|
|
TEST_VAL_RI srai, 32, 5, 1, srai_pos
|
|
TEST_VAL_RI srai, 0x80000000, 1, 0xc0000000, srai_neg
|
|
|
|
# ==========================================
|
|
# RV32I Register-Register Arithmetic
|
|
# ==========================================
|
|
TEST_VAL_RR add, 10, 20, 30, add_pos
|
|
TEST_VAL_RR add, 0x7fffffff, 1, 0x80000000, add_overflow
|
|
|
|
TEST_VAL_RR sub, 20, 10, 10, sub_pos
|
|
TEST_VAL_RR sub, 10, 20, -10, sub_neg
|
|
|
|
TEST_VAL_RR sll, 1, 5, 32, sll_val
|
|
TEST_VAL_RR sll, 1, 37, 32, sll_wrap
|
|
|
|
TEST_VAL_RR slt, 10, 20, 1, slt_lt
|
|
TEST_VAL_RR slt, -10, 10, 1, slt_neg
|
|
|
|
TEST_VAL_RR sltu, 10, 20, 1, sltu_lt
|
|
TEST_VAL_RR sltu, -10, 10, 0, sltu_neg
|
|
|
|
TEST_VAL_RR xor, 0xf0f0f0f0, 0x0f0f0f0f, 0xffffffff, xor_val
|
|
|
|
TEST_VAL_RR srl, 32, 5, 1, srl_val
|
|
TEST_VAL_RR srl, 32, 37, 1, srl_wrap
|
|
|
|
TEST_VAL_RR sra, 0x80000000, 1, 0xc0000000, sra_neg
|
|
TEST_VAL_RR sra, 0x80000000, 33, 0xc0000000, sra_wrap
|
|
|
|
TEST_VAL_RR or, 0xf0f0f0f0, 0x0f0f0f0f, 0xffffffff, or_val
|
|
TEST_VAL_RR and, 0xf0f0f0f0, 0x0f0f0f0f, 0, and_val
|
|
|
|
# ==========================================
|
|
# RV32I LUI and AUIPC
|
|
# ==========================================
|
|
INC_TESTS
|
|
lui t0, 0x12345
|
|
ASSERT_EQ t0, 0x12345000, lui_val
|
|
|
|
INC_TESTS
|
|
1: auipc t0, 0x10
|
|
la t1, 1b
|
|
sub t0, t0, t1
|
|
ASSERT_EQ t0, 0x10000, auipc_val
|
|
|
|
# ==========================================
|
|
# RV32I Jumps
|
|
# ==========================================
|
|
INC_TESTS
|
|
jal t0, 2f
|
|
li t1, 0
|
|
j 3f
|
|
2:
|
|
li t1, 1
|
|
3:
|
|
ASSERT_EQ t1, 1, jal_branch
|
|
INC_TESTS
|
|
la t2, 2b - 8
|
|
ASSERT_EQ_REG t0, t2, jal_link
|
|
|
|
INC_TESTS
|
|
la t1, 4f
|
|
jalr t0, t1, 0
|
|
li t2, 0
|
|
j 5f
|
|
4:
|
|
li t2, 1
|
|
5:
|
|
ASSERT_EQ t2, 1, jalr_branch
|
|
INC_TESTS
|
|
la t3, 4b - 8
|
|
ASSERT_EQ_REG t0, t3, jalr_link
|
|
|
|
INC_TESTS
|
|
la t1, 6f - 4
|
|
jalr t0, t1, 4
|
|
li t2, 0
|
|
j 7f
|
|
6:
|
|
li t2, 1
|
|
7:
|
|
ASSERT_EQ t2, 1, jalr_offset
|
|
|
|
# ==========================================
|
|
# RV32I Branches
|
|
# ==========================================
|
|
# BEQ
|
|
INC_TESTS
|
|
li t1, 10
|
|
li t2, 10
|
|
beq t1, t2, 1f
|
|
li t0, 0
|
|
j 2f
|
|
1:
|
|
li t0, 1
|
|
2:
|
|
ASSERT_EQ t0, 1, beq_taken
|
|
|
|
INC_TESTS
|
|
li t1, 10
|
|
li t2, 20
|
|
beq t1, t2, 1f
|
|
li t0, 1
|
|
j 2f
|
|
1:
|
|
li t0, 0
|
|
2:
|
|
ASSERT_EQ t0, 1, beq_not_taken
|
|
|
|
# BNE
|
|
INC_TESTS
|
|
li t1, 10
|
|
li t2, 20
|
|
bne t1, t2, 1f
|
|
li t0, 0
|
|
j 2f
|
|
1:
|
|
li t0, 1
|
|
2:
|
|
ASSERT_EQ t0, 1, bne_taken
|
|
|
|
INC_TESTS
|
|
li t1, 10
|
|
li t2, 10
|
|
bne t1, t2, 1f
|
|
li t0, 1
|
|
j 2f
|
|
1:
|
|
li t0, 0
|
|
2:
|
|
ASSERT_EQ t0, 1, bne_not_taken
|
|
|
|
# BLT
|
|
INC_TESTS
|
|
li t1, -10
|
|
li t2, 10
|
|
blt t1, t2, 1f
|
|
li t0, 0
|
|
j 2f
|
|
1:
|
|
li t0, 1
|
|
2:
|
|
ASSERT_EQ t0, 1, blt_taken
|
|
|
|
INC_TESTS
|
|
li t1, 10
|
|
li t2, -10
|
|
blt t1, t2, 1f
|
|
li t0, 1
|
|
j 2f
|
|
1:
|
|
li t0, 0
|
|
2:
|
|
ASSERT_EQ t0, 1, blt_not_taken
|
|
|
|
# BGE
|
|
INC_TESTS
|
|
li t1, 10
|
|
li t2, -10
|
|
bge t1, t2, 1f
|
|
li t0, 0
|
|
j 2f
|
|
1:
|
|
li t0, 1
|
|
2:
|
|
ASSERT_EQ t0, 1, bge_taken
|
|
|
|
INC_TESTS
|
|
li t1, -10
|
|
li t2, 10
|
|
bge t1, t2, 1f
|
|
li t0, 1
|
|
j 2f
|
|
1:
|
|
li t0, 0
|
|
2:
|
|
ASSERT_EQ t0, 1, bge_not_taken
|
|
|
|
# BLTU
|
|
INC_TESTS
|
|
li t1, 10
|
|
li t2, -10
|
|
bltu t1, t2, 1f
|
|
li t0, 0
|
|
j 2f
|
|
1:
|
|
li t0, 1
|
|
2:
|
|
ASSERT_EQ t0, 1, bltu_taken
|
|
|
|
INC_TESTS
|
|
li t1, -10
|
|
li t2, 10
|
|
bltu t1, t2, 1f
|
|
li t0, 1
|
|
j 2f
|
|
1:
|
|
li t0, 0
|
|
2:
|
|
ASSERT_EQ t0, 1, bltu_not_taken
|
|
|
|
# BGEU
|
|
INC_TESTS
|
|
li t1, -10
|
|
li t2, 10
|
|
bgeu t1, t2, 1f
|
|
li t0, 0
|
|
j 2f
|
|
1:
|
|
li t0, 1
|
|
2:
|
|
ASSERT_EQ t0, 1, bgeu_taken
|
|
|
|
INC_TESTS
|
|
li t1, 10
|
|
li t2, -10
|
|
bgeu t1, t2, 1f
|
|
li t0, 1
|
|
j 2f
|
|
1:
|
|
li t0, 0
|
|
2:
|
|
ASSERT_EQ t0, 1, bgeu_not_taken
|
|
|
|
# ==========================================
|
|
# RV32I Loads and Stores
|
|
# ==========================================
|
|
# Store word and load word/half/byte
|
|
la t1, data_buffer
|
|
li t2, 0x12345678
|
|
sw t2, 0(t1)
|
|
|
|
INC_TESTS
|
|
lw t0, 0(t1)
|
|
ASSERT_EQ t0, 0x12345678, load_word
|
|
|
|
INC_TESTS
|
|
lh t0, 0(t1)
|
|
ASSERT_EQ t0, 0x5678, load_half
|
|
|
|
INC_TESTS
|
|
lhu t0, 0(t1)
|
|
ASSERT_EQ t0, 0x5678, load_half_u
|
|
|
|
INC_TESTS
|
|
lb t0, 0(t1)
|
|
ASSERT_EQ t0, 0x78, load_byte
|
|
|
|
INC_TESTS
|
|
lbu t0, 0(t1)
|
|
ASSERT_EQ t0, 0x78, load_byte_u
|
|
|
|
# Store half and byte with sign extension verification
|
|
li t2, 0x8000
|
|
sh t2, 0(t1)
|
|
INC_TESTS
|
|
lh t0, 0(t1)
|
|
ASSERT_EQ t0, -32768, load_half_neg
|
|
|
|
INC_TESTS
|
|
lhu t0, 0(t1)
|
|
ASSERT_EQ t0, 32768, load_half_neg_u
|
|
|
|
li t2, 0x80
|
|
sb t2, 0(t1)
|
|
INC_TESTS
|
|
lb t0, 0(t1)
|
|
ASSERT_EQ t0, -128, load_byte_neg
|
|
|
|
INC_TESTS
|
|
lbu t0, 0(t1)
|
|
ASSERT_EQ t0, 128, load_byte_neg_u
|
|
|
|
# ==========================================
|
|
# RV32M Extensions
|
|
# ==========================================
|
|
TEST_VAL_RR mul, 10, 20, 200, mul_pos
|
|
TEST_VAL_RR mul, -10, 20, -200, mul_neg
|
|
TEST_VAL_RR mul, 0x10000, 0x10000, 0, mul_overflow
|
|
|
|
TEST_VAL_RR mulh, 0x10000, 0x10000, 1, mulh_pos
|
|
TEST_VAL_RR mulh, -10, 20, -1, mulh_neg
|
|
|
|
TEST_VAL_RR mulhsu, -10, 20, -1, mulhsu_neg
|
|
TEST_VAL_RR mulhu, 0x80000000, 2, 1, mulhu_val
|
|
|
|
TEST_VAL_RR div, 20, 6, 3, div_pos
|
|
TEST_VAL_RR div, -20, 6, -3, div_neg
|
|
TEST_VAL_RR div, 20, 0, -1, div_by_zero
|
|
TEST_VAL_RR div, -2147483648, -1, -2147483648, div_overflow
|
|
|
|
TEST_VAL_RR divu, 20, 6, 3, divu_pos
|
|
TEST_VAL_RR divu, -20, 6, 715827879, divu_neg
|
|
TEST_VAL_RR divu, 20, 0, 4294967295, divu_by_zero
|
|
|
|
TEST_VAL_RR rem, 20, 6, 2, rem_pos
|
|
TEST_VAL_RR rem, -20, 6, -2, rem_neg
|
|
TEST_VAL_RR rem, 20, 0, 20, rem_by_zero
|
|
TEST_VAL_RR rem, -2147483648, -1, 0, rem_overflow
|
|
|
|
TEST_VAL_RR remu, 20, 6, 2, remu_pos
|
|
TEST_VAL_RR remu, -20, 6, 2, remu_neg
|
|
TEST_VAL_RR remu, 20, 0, 20, remu_by_zero
|
|
|
|
# ==========================================
|
|
# RV32A Extensions
|
|
# ==========================================
|
|
# Load-Reserved / Store-Conditional
|
|
la t1, atomic_var
|
|
li t2, 42
|
|
lr.w t0, (t1)
|
|
sc.w t3, t2, (t1)
|
|
INC_TESTS
|
|
ASSERT_EQ t3, 0, sc_success
|
|
INC_TESTS
|
|
lw t4, 0(t1)
|
|
ASSERT_EQ t4, 42, sc_val
|
|
|
|
# SC without LR (should fail)
|
|
li t2, 99
|
|
sc.w t3, t2, (t1)
|
|
INC_TESTS
|
|
ASSERT_EQ t3, 1, sc_fail_no_lr
|
|
|
|
# AMOSWAP.W
|
|
li t2, 10
|
|
sw t2, 0(t1)
|
|
li t3, 20
|
|
amoswap.w t0, t3, (t1)
|
|
INC_TESTS
|
|
ASSERT_EQ t0, 10, amoswap_old
|
|
INC_TESTS
|
|
lw t4, 0(t1)
|
|
ASSERT_EQ t4, 20, amoswap_new
|
|
|
|
# AMOADD.W
|
|
li t2, 10
|
|
sw t2, 0(t1)
|
|
li t3, 20
|
|
amoadd.w t0, t3, (t1)
|
|
INC_TESTS
|
|
ASSERT_EQ t0, 10, amoadd_old
|
|
INC_TESTS
|
|
lw t4, 0(t1)
|
|
ASSERT_EQ t4, 30, amoadd_new
|
|
|
|
# AMOXOR.W
|
|
li t2, 0x12345678
|
|
sw t2, 0(t1)
|
|
li t3, 0x0f0f0f0f
|
|
amoxor.w t0, t3, (t1)
|
|
INC_TESTS
|
|
ASSERT_EQ t0, 0x12345678, amoxor_old
|
|
INC_TESTS
|
|
lw t4, 0(t1)
|
|
ASSERT_EQ t4, 0x1d3b5977, amoxor_new
|
|
|
|
# AMOAND.W
|
|
li t2, 0x12345678
|
|
sw t2, 0(t1)
|
|
li t3, 0x0f0f0f0f
|
|
amoand.w t0, t3, (t1)
|
|
INC_TESTS
|
|
ASSERT_EQ t0, 0x12345678, amoand_old
|
|
INC_TESTS
|
|
lw t4, 0(t1)
|
|
ASSERT_EQ t4, 0x02040608, amoand_new
|
|
|
|
# AMOOR.W
|
|
li t2, 0x12345678
|
|
sw t2, 0(t1)
|
|
li t3, 0x0f0f0f0f
|
|
amoor.w t0, t3, (t1)
|
|
INC_TESTS
|
|
ASSERT_EQ t0, 0x12345678, amoor_old
|
|
INC_TESTS
|
|
lw t4, 0(t1)
|
|
ASSERT_EQ t4, 0x1f3f5f7f, amoor_new
|
|
|
|
# AMOMIN.W
|
|
li t2, -10
|
|
sw t2, 0(t1)
|
|
li t3, 10
|
|
amomin.w t0, t3, (t1)
|
|
INC_TESTS
|
|
ASSERT_EQ t0, -10, amomin_old1
|
|
INC_TESTS
|
|
lw t4, 0(t1)
|
|
ASSERT_EQ t4, -10, amomin_new1
|
|
|
|
li t2, 10
|
|
sw t2, 0(t1)
|
|
li t3, -10
|
|
amomin.w t0, t3, (t1)
|
|
INC_TESTS
|
|
ASSERT_EQ t0, 10, amomin_old2
|
|
INC_TESTS
|
|
lw t4, 0(t1)
|
|
ASSERT_EQ t4, -10, amomin_new2
|
|
|
|
# AMOMAX.W
|
|
li t2, -10
|
|
sw t2, 0(t1)
|
|
li t3, 10
|
|
amomax.w t0, t3, (t1)
|
|
INC_TESTS
|
|
ASSERT_EQ t0, -10, amomax_old
|
|
INC_TESTS
|
|
lw t4, 0(t1)
|
|
ASSERT_EQ t4, 10, amomax_new
|
|
|
|
# AMOMINU.W
|
|
li t2, -10 # 0xfffffff6
|
|
sw t2, 0(t1)
|
|
li t3, 10
|
|
amominu.w t0, t3, (t1)
|
|
INC_TESTS
|
|
ASSERT_EQ t0, -10, amominu_old
|
|
INC_TESTS
|
|
lw t4, 0(t1)
|
|
ASSERT_EQ t4, 10, amominu_new
|
|
|
|
# AMOMAXU.W
|
|
li t2, -10 # 0xfffffff6
|
|
sw t2, 0(t1)
|
|
li t3, 10
|
|
amomaxu.w t0, t3, (t1)
|
|
INC_TESTS
|
|
ASSERT_EQ t0, -10, amomaxu_old
|
|
INC_TESTS
|
|
lw t4, 0(t1)
|
|
ASSERT_EQ t4, -10, amomaxu_new
|
|
|
|
# ==========================================
|
|
# RV32I 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
|
|
# ==========================================
|
|
# Print Summary
|
|
la a0, str_summary_prefix
|
|
jal print_string
|
|
|
|
# Print total test count
|
|
la t0, test_count
|
|
lw a0, 0(t0)
|
|
jal print_decimal
|
|
|
|
la a0, str_summary_tests
|
|
jal print_string
|
|
|
|
# Print passed count
|
|
la t0, success_count
|
|
lw a0, 0(t0)
|
|
jal print_decimal
|
|
|
|
la a0, str_summary_passed
|
|
jal print_string
|
|
|
|
# Print failed count
|
|
la t0, failure_count
|
|
lw a0, 0(t0)
|
|
jal print_decimal
|
|
|
|
la a0, str_summary_failed
|
|
jal print_string
|
|
|
|
la t0, failure_count
|
|
lw t1, 0(t0)
|
|
bnez t1, report_error
|
|
|
|
la a0, str_all_passed
|
|
jal print_string
|
|
li a0, 0
|
|
li a7, 93
|
|
ecall
|
|
|
|
report_error:
|
|
la a0, str_some_failed
|
|
jal print_string
|
|
li a0, 1
|
|
li a7, 93
|
|
ecall
|
|
|
|
report_failure:
|
|
addi sp, sp, -32
|
|
sw ra, 28(sp)
|
|
sw s0, 24(sp)
|
|
sw s1, 20(sp)
|
|
sw s2, 16(sp)
|
|
|
|
mv s0, a0
|
|
mv s1, a1
|
|
mv s2, a2
|
|
|
|
la a0, str_fail_prefix
|
|
jal print_string
|
|
|
|
mv a0, s0
|
|
jal print_string
|
|
|
|
la a0, str_expected
|
|
jal print_string
|
|
|
|
mv a0, s2
|
|
jal print_hex
|
|
|
|
la a0, str_got
|
|
jal print_string
|
|
|
|
mv a0, s1
|
|
jal print_hex
|
|
|
|
li a0, 10
|
|
jal print_char
|
|
|
|
la t0, failure_count
|
|
lw t1, 0(t0)
|
|
addi t1, t1, 1
|
|
sw t1, 0(t0)
|
|
|
|
lw ra, 28(sp)
|
|
lw s0, 24(sp)
|
|
lw s1, 20(sp)
|
|
lw s2, 16(sp)
|
|
addi sp, sp, 32
|
|
ret
|
|
|
|
print_string:
|
|
addi sp, sp, -16
|
|
sw ra, 12(sp)
|
|
sw s0, 8(sp)
|
|
mv s0, a0
|
|
print_string_loop:
|
|
lbu a0, 0(s0)
|
|
beqz a0, print_string_done
|
|
jal print_char
|
|
addi s0, s0, 1
|
|
j print_string_loop
|
|
print_string_done:
|
|
lw ra, 12(sp)
|
|
lw s0, 8(sp)
|
|
addi sp, sp, 16
|
|
ret
|
|
|
|
print_char:
|
|
addi sp, sp, -16
|
|
sb a0, 0(sp)
|
|
li a7, 64
|
|
li a0, 1
|
|
mv a1, sp
|
|
li a2, 1
|
|
ecall
|
|
addi sp, sp, 16
|
|
ret
|
|
|
|
print_hex:
|
|
addi sp, sp, -32
|
|
sw ra, 28(sp)
|
|
sw s0, 24(sp)
|
|
sw s1, 20(sp)
|
|
sw s2, 16(sp)
|
|
|
|
mv s0, a0
|
|
li s1, 8
|
|
la s2, hex_chars
|
|
|
|
print_hex_loop:
|
|
srli t0, s0, 28
|
|
andi t0, t0, 0xF
|
|
add t1, s2, t0
|
|
lbu a0, 0(t1)
|
|
jal print_char
|
|
slli s0, s0, 4
|
|
addi s1, s1, -1
|
|
bnez s1, print_hex_loop
|
|
|
|
lw ra, 28(sp)
|
|
lw s0, 24(sp)
|
|
lw s1, 20(sp)
|
|
lw s2, 16(sp)
|
|
addi sp, sp, 32
|
|
ret
|
|
|
|
print_decimal:
|
|
addi sp, sp, -32
|
|
sw ra, 28(sp)
|
|
sw s0, 24(sp)
|
|
sw s1, 20(sp)
|
|
|
|
mv s0, a0
|
|
|
|
# Handle 0 case
|
|
bnez s0, 1f
|
|
li a0, 48 # '0'
|
|
jal print_char
|
|
j print_decimal_done
|
|
1:
|
|
addi s1, sp, 8
|
|
li t2, 10
|
|
2:
|
|
divu t0, s0, t2
|
|
remu t1, s0, t2
|
|
addi t1, t1, 48 # convert to ASCII
|
|
sb t1, 0(s1)
|
|
addi s1, s1, 1
|
|
mv s0, t0
|
|
bnez s0, 2b
|
|
|
|
# Now print digits in reverse order
|
|
3:
|
|
addi s1, s1, -1
|
|
lbu a0, 0(s1)
|
|
jal print_char
|
|
addi t0, sp, 8
|
|
bne s1, t0, 3b
|
|
|
|
print_decimal_done:
|
|
lw ra, 28(sp)
|
|
lw s0, 24(sp)
|
|
lw s1, 20(sp)
|
|
addi sp, sp, 32
|
|
ret
|
|
|
|
.section .data
|
|
.align 2
|
|
test_count: .word 0
|
|
success_count: .word 0
|
|
failure_count: .word 0
|
|
|
|
.align 4
|
|
data_buffer: .zero 16
|
|
atomic_var: .word 0
|
|
|
|
.section .rodata
|
|
hex_chars: .string "0123456789abcdef"
|
|
str_fail_prefix: .string " FAIL: "
|
|
str_expected: .string ", expected 0x"
|
|
str_got: .string ", got 0x"
|
|
str_summary_prefix: .string "Executed "
|
|
str_summary_tests: .string " tests: "
|
|
str_summary_passed: .string " passed, "
|
|
str_summary_failed: .string " failed.\n"
|
|
str_all_passed: .string "All tests PASSED!\n"
|
|
str_some_failed: .string "Some tests FAILED.\n"
|