Files
a-machine/rv32ima_tests.s
T

742 lines
13 KiB
ArmAsm
Raw Normal View History

2026-06-18 14:01:36 +03:00
.section .text
.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
# ==========================================
# 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"