Files
a-machine/rv32imac_tests.s
T

972 lines
16 KiB
ArmAsm
Raw Normal View History

2026-06-18 14:01:36 +03:00
.section .text
2026-06-18 19:10:32 +03:00
.option norvc
2026-06-18 14:01:36 +03:00
.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
2026-06-18 19:10:32 +03:00
# ==========================================
# 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
2026-06-18 14:01:36 +03:00
# ==========================================
# 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
2026-06-18 19:34:05 +03:00
# Unreachable: placed to verify standard/compressed ebreak compilation
ebreak
.option rvc
c.ebreak
.option norvc
2026-06-18 14:01:36 +03:00
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"