blob: b656fed9c566a15ebad36f594f503f670a45bf11 [file] [log] [blame]
*** Keywords ***
# WriteDoubleWord: reversed bytes
# Disassembly output: spaces between bytes
DisasTest BE
[Arguments] ${hex_code} ${mnemonic}= ${operands}= ${code_size}=4 ${hex_addr}=0 ${flags}=0
${hex_addr}= Convert To Hex ${hex_addr} length=8 base=16
${b1}= Get Substring ${hex_code} 0 2
${b2}= Get Substring ${hex_code} 2 4
${b3}= Get Substring ${hex_code} 4 6
${b4}= Get Substring ${hex_code} 6 8
${b_write}= Set Variable ${b4}${b3}${b2}${b1}
${b_disas}= Set Variable ${b1}${b2}${b3}${b4}
IF ${code_size} > 4
${b_disas_4B+}= Write Extra Bytes BE And Return Their Expected Output ${hex_addr} ${hex_code}
ELSE
${b_disas_4B+}= Set Variable ${None}
END
${b_disas}= Set Variable If ${code_size} > 4 ${b_disas}${b_disas_4B+} ${b_disas}
DisasTest Core ${hex_addr} ${b_write} ${b_disas} ${mnemonic} ${operands} ${code_size} ${flags}
RoundTrip BE
[Arguments] ${hex_code} ${mnemonic}= ${operands}= ${code_size}=4 ${hex_addr}=0 ${flags}=0 ${reverse}=True
IF ${reverse}
${expected}= Reverse Bytes ${{$hex_code[:int($code_size) * 2]}}
ELSE
${expected}= Set Variable ${hex_code}
END
AsTest ${expected} ${mnemonic} ${operands} ${flags} 0x${hex_addr}
DisasTest BE ${hex_code} ${mnemonic} ${operands} ${code_size} ${hex_addr} ${flags}
Write Extra Bytes BE And Return Their Expected Output
[Arguments] ${hex_addr} ${hex_code}
${int}= Convert To Integer 0x${hex_addr}
${int}= Evaluate $int + 4
${adjusted_addr}= Convert To Hex ${int}
${b5}= Get Substring ${hex_code} 8 10
${b6}= Get Substring ${hex_code} 10 12
${b7}= Get Substring ${hex_code} 12 14
${b8}= Get Substring ${hex_code} 14 16
Execute Command sysbus WriteDoubleWord 0x${adjusted_addr} 0x${b8}${b7}${b6}${b5}
Return From Keyword ${b5}${b6}${b7}${b8}
Reverse Bytes
[Arguments] ${hex_str} ${group_size}=${2}
${len}= Get Length ${hex_str}
${out}= Create List
FOR ${i} IN RANGE 0 ${len} ${group_size}
${byte}= Get Substring ${hex_str} ${i} ${{$i+$group_size}}
Append To List ${out} ${byte}
END
Reverse List ${out}
[Return] ${{"".join($out)}}
# WriteDoubleWord: reversed words
# Disassembly output: space between words
DisasTest Thumb
[Arguments] ${hex_code} ${mnemonic}= ${operands}= ${code_size}=4 ${hex_addr}=0
${hex_addr}= Convert To Hex ${hex_addr} length=8 base=16
${w1}= Get Substring ${hex_code} 0 4
${w2}= Get Substring ${hex_code} 4
${b_write}= Set Variable ${w2}${w1}
${b_disas}= Set Variable ${w1}${w2}
DisasTest Core ${hex_addr} ${b_write} ${b_disas} ${mnemonic} ${operands} ${code_size}
RoundTrip Thumb
[Arguments] ${hex_code} ${mnemonic}= ${operands}= ${code_size}=4 ${hex_addr}=0
# For Thumb, reverse the bytes in each word
${expected}= Reverse Bytes ${hex_code}
${expected}= Reverse Bytes ${expected} group_size=${4}
AsTest ${expected} ${mnemonic} ${operands} address=0x${hex_addr}
DisasTest Thumb ${hex_code} ${mnemonic} ${operands} ${code_size} ${hex_addr}
DisasTest LE
[Arguments] ${hex_code} ${mnemonic}= ${operands}= ${code_size}=4 ${hex_addr}=0
${hex_addr}= Convert To Hex ${hex_addr} length=8 base=16
DisasTest Core ${hex_addr} ${hex_code} ${hex_code} ${mnemonic} ${operands} ${code_size}
RoundTrip LE
[Arguments] ${hex_code} ${mnemonic}= ${operands}= ${code_size}=4 ${hex_addr}=0
${expected}= Reverse Bytes ${{$hex_code[:int($code_size) * 2]}}
AsTest ${expected} ${mnemonic} ${operands} address=0x${hex_addr}
DisasTest LE ${hex_code} ${mnemonic} ${operands} ${code_size} ${hex_addr}
DisasTest Core
[Arguments] ${hex_addr} ${code_write} ${code_disas} ${mnemonic} ${operands} ${code_size} ${flags}=0
Execute Command sysbus WriteDoubleWord 0x${hex_addr} 0x${code_write}
${res}= Execute Command sysbus.cpu DisassembleBlock 0x${hex_addr} ${code_size} ${flags}
# expect error if "$mnemonic" and "$operands" (without curly brackets!) are empty
Run Keyword And Return If $mnemonic == '' and $operands == '' Should Match Regexp ${res} Disassembly error detected
# compare DisassembleBlock output with the expected one; "(?i)" prefix causes ignoring case difference
${escaped_mnem}= Regexp Escape ${mnemonic}
${escaped_oper}= Regexp Escape ${operands}
Should Match Regexp ${res} (?i)^0x${hex_addr}:\\s+${code_disas}\\s+${escaped_mnem}\\s+${escaped_oper}\\n+$
AsTest
[Arguments] ${expected} ${mnemonic} ${operands}= ${flags}=0 ${address}=0
${len}= Execute Command sysbus.cpu AssembleBlock ${address} "${mnemonic} ${operands}" ${flags}
${bytes}= Execute Command sysbus ReadBytes ${address} ${len}
# This string is safe to eval because it's formatted as a Python list by PrintActionResult in MonitorCommands.cs
${hex_bytes}= Evaluate "".join("%02x"%b for b in ${bytes})
# Reverse the bytes for a big-endian bus because the expected strings in the test cases are formatted
# as if they had been read by ReadDoubleWord
${bus_endian}= Execute Command sysbus Endianess
${bus_endian}= Get Line ${bus_endian} 0
IF "${bus_endian}" == "BigEndian"
${hex_bytes}= Reverse Bytes ${hex_bytes}
END
Should Be Equal ${hex_bytes} ${expected}
Create Machine
[Arguments] ${cpu} ${model}
# "extra" will be appended to the cpu creation string after cpuType (at least it has to close curly brackets opened before cpuType)
${extra}= Set Variable }
# the last ${extra} field covers the "else" case, keeping the previous value of "extra"; by default, "else" case sets variables to "None"
${extra}= Set Variable If "${cpu}" == "CortexM" ; nvic: nvic }; nvic: IRQControllers.NVIC ${extra}
${extra}= Set Variable If "${cpu}" == "ARMv8A" ; genericInterruptController: gic }; gic: IRQControllers.ARM_GenericInterruptController @ { sysbus new Bus.BusMultiRegistration { address: 0x8000000; size: 0x010000; region: \\"distributor\\" }; sysbus new IRQControllers.ArmGicRedistributorRegistration { attachedCPU: cpu; address: 0x80a0000 } } { [0-1] -> cpu@[0-1]; architectureVersion: IRQControllers.ARM_GenericInterruptControllerVersion.GICv3; supportsTwoSecurityStates: true } ${extra}
${extra}= Set Variable If "${cpu}" == "PowerPc64" ; endianness: Endianess.LittleEndian } ${extra}
${extra}= Set Variable If "${cpu}" == "RiscV32" ; timeProvider: empty } ${extra}
${extra}= Set Variable If "${cpu}" == "RiscV64" ; timeProvider: empty } ${extra}
${extra}= Set Variable If "${cpu}" == "X86" ; lapic: empty } ${extra}
${extra}= Set Variable If "${cpu}" == "X86_64" ; lapic: empty } ${extra}
Execute Command mach create
IF any(x in "${cpu}" for x in ("PowerPc", "Sparc"))
Execute Command machine LoadPlatformDescriptionFromString "sysbus: { Endianess: Endianess.BigEndian }"
END
Execute Command machine LoadPlatformDescriptionFromString "cpu: CPU.${cpu} @ sysbus { cpuType: \\"${model}\\" ${extra}"
Execute Command machine LoadPlatformDescriptionFromString "mem: Memory.MappedMemory @ sysbus 0x0 { size: 0x50000 }"
Assemble And Disassemble RV32IMA
[Arguments] ${compressed}=False
# Compressed format will be generated by the assembler if the core has the C extension
# and is only accepted by the disassembler if the core has the C extension. The disassembler
# output doesn't explicitly indicate the compressed instruction (c.sw, c.add)
IF ${compressed}
RoundTrip LE c84a sw s2, 16(sp) 2 # rv32c
RoundTrip LE 95be add a1, a1, a5 2 # rv32c
ELSE
RoundTrip LE 01212823 sw s2, 16(sp) # rv32i
RoundTrip LE 00b785b3 add a1, a5, a1 # rv32i
END
# The uncompressed forms should be accepted by the disassembler even with the C extension
DisasTest LE 01212823 sw s2, 16(sp) # rv32i
DisasTest LE 00b785b3 add a1, a5, a1 # rv32i
RoundTrip LE 00008297 auipc t0, 8 # rv32i
RoundTrip LE 0000100f fence.i # Zifencei
RoundTrip LE 3401f173 csrrci sp, mscratch, 3 # Zicsr
RoundTrip LE 02ab5c33 divu s8, s6, a0 # rv32m
RoundTrip LE 0805252f amoswap.w a0, zero, (a0) # rv32a
Assemble And Disassemble RV32FD
RoundTrip LE 580123d3 fsqrt.s ft7, ft2, rdn # rv32f
RoundTrip LE 5a0123d3 fsqrt.d ft7, ft2, rdn # rv32d
Assemble And Disassemble RV32C
RoundTrip LE 3fed jal -6 2 # rv32c
Assemble And Disassemble RV64IMAC
RoundTrip LE 000a3a83 ld s5, 0(s4) # rv64i
RoundTrip LE abcd8a9b addiw s5, s11, -1348 # rv64i
RoundTrip LE 02ab7c3b remuw s8, s6, a0 # rv64m
RoundTrip LE e705b52f amomaxu.d.aqrl a0, a6, (a1) # rv64a
RoundTrip LE eabc sd a5, 80(a3) 2 # rv64c
Assemble And Disassemble RV64FD
RoundTrip LE d0312353 fcvt.s.lu ft6, sp, rdn # rv64f
RoundTrip LE d2312353 fcvt.d.lu ft6, sp, rdn # rv64d
Assemble And Disassemble RVV
RoundTrip LE 00057757 vsetvli a4, a0, e8, m1, tu, mu # rv64v
RoundTrip LE 03058407 vle8ff.v v8, (a1) # rv64v
RoundTrip LE 4218a757 vfirst.m a4, v1 # rv64v
*** Test Cases ***
# Keywords to disassemble single instruction
#
# DisasTest (BE|LE|Thumb) HEX_CODE [MNEMONIC] [OPERANDS] [CODE_SIZE=4] [HEX_ADDR=00000000]
# HEX_CODE the opcode to disassemble; don't prefix with "0x"
# MNEMONIC, OPERANDS expected disassembly results; expect empty result if both are empty
# CODE_SIZE in bytes; max 8B instructions are supported
# HEX_ADDR hex address of the instruction, verified with the disassembler output but not influencing the opcode itself; don't prefix with "0x"
Should Assemble And Disassemble ARM Cortex-A
Create Machine ARMv7A arm926
RoundTrip LE 32855001 addlo r5, r5, \#1 hex_addr=8000
RoundTrip LE e1b00a00 lsls r0, r0, \#20 hex_addr=813c
RoundTrip LE 1a00000a bne \#40
Should Assemble And Disassemble ARM Cortex-A53
Create Machine ARMv8A cortex-a53
RoundTrip LE 5400f041 b.ne \#7688
RoundTrip LE aa0603e1 mov x1, x6
RoundTrip LE aa2c1c65 orn x5, x3, x12, lsl \#7
Should Assemble And Disassemble ARM Cortex-M
Create Machine CortexM cortex-m4
RoundTrip Thumb f0230403 bic r4, r3, \#3 hex_addr=2
RoundTrip Thumb 58c8 ldr r0, [r1, r3] 2
RoundTrip Thumb f44f426d mov.w r2, \#60672 hex_addr=9e8
RoundTrip Thumb 10b6 asrs r6, r6, \#2 2 ad88
Should Assemble And Disassemble RISCV32IMA
Create Machine RiscV32 rv32ima
Assemble And Disassemble RV32IMA
Should Assemble And Disassemble RISCV32IMAC
Create Machine RiscV32 rv32imac
Assemble And Disassemble RV32IMA compressed=True
Assemble And Disassemble RV32C
Should Assemble And Disassemble RISCV32IMAFDC
Create Machine RiscV32 rv32imafdc
Assemble And Disassemble RV32IMA compressed=True
Assemble And Disassemble RV32FD
Assemble And Disassemble RV32C
Should Assemble And Disassemble RISCV32GC
Create Machine RiscV32 rv32gc
Assemble And Disassemble RV32IMA compressed=True
Assemble And Disassemble RV32FD
Assemble And Disassemble RV32C
Should Assemble And Disassemble RISCV32GV
Create Machine RiscV32 rv32gv
Assemble And Disassemble RV32IMA
Assemble And Disassemble RVV
Should Assemble And Disassemble RISCV64IMAC
Create Machine RiscV64 rv64imac
Assemble And Disassemble RV32IMA compressed=True
Assemble And Disassemble RV64IMAC
Should Assemble And Disassemble RISCV64IMAFDC
Create Machine RiscV64 rv64imafdc
Assemble And Disassemble RV32IMA compressed=True
Assemble And Disassemble RV32FD
Assemble And Disassemble RV64IMAC
Assemble And Disassemble RV64FD
Should Assemble And Disassemble RISCV64GC
Create Machine RiscV64 rv64gc
Assemble And Disassemble RV32IMA compressed=True
Assemble And Disassemble RV32FD
Assemble And Disassemble RV64IMAC
Assemble And Disassemble RV64FD
Should Assemble And Disassemble RISCV64GCV
Create Machine RiscV64 rv64gcv
Assemble And Disassemble RV64IMAC
Assemble And Disassemble RVV
Should Assemble And Disassemble PPC
Create Machine PowerPc e200z6
RoundTrip LE 4800007c b .+124
RoundTrip LE 7f880040 cmplw 7, 8, 0 hex_addr=123
RoundTrip LE 7ce40034 cntlzw 4, 7
Should Assemble And Disassemble PPC64 LE
Create Machine PowerPc64 620
# RoundTrip BE is used because of the output formatting in DisasTest BE
# CPU is set as LE in Renode and LLVM's LE version of ppc64 is used
RoundTrip BE 18002389 lbz 9, 24(3)
RoundTrip BE 40202a7c cmpld 10, 4
RoundTrip BE 71790248 bl .+162160
Should Assemble And Disassemble Sparc
Create Machine Sparc leon3
RoundTrip LE 85e8a018 restore %g2, 24, %g2 hex_addr=abc
RoundTrip LE 01000000 nop hex_addr=abc
RoundTrip LE 10680047 ba %xcc, 71
Should Assemble And Disassemble X86 Using Intel Syntax
Create Machine X86 x86
RoundTrip BE 6b7b0c14 imul edi, dword ptr [ebx + 12], 20 flags=1 reverse=False
RoundTrip BE 45 inc ebp 1 flags=1 reverse=False
RoundTrip BE 0fb7c0 movzx eax, ax 3 cc flags=1 reverse=False
RoundTrip BE 66890cc516a9fd00 mov word ptr [8*eax + 16623894], cx 8 a flags=1 reverse=False
RoundTrip BE 0f011d5e00fc00 lidtd [16515166] 7 abd flags=1 reverse=False
Should Assemble And Disassemble X86 Using GAS Syntax
Create Machine X86 x86
RoundTrip BE 6b7b0c14 imull $20, 12(%ebx), %edi reverse=False
RoundTrip BE 45 incl %ebp 1 reverse=False
RoundTrip BE 0fb7c0 movzwl %ax, %eax 3 cc reverse=False
RoundTrip BE 66890cc516a9fd00 movw %cx, 16623894(,%eax,8) 8 a reverse=False
RoundTrip BE 0f011d5e00fc00 lidtl 16515166 7 abd reverse=False
Should Assemble And Disassemble X86_64 Using Intel Syntax
Create Machine X86_64 x86_64
RoundTrip BE 676b7b0c14 imul edi, dword ptr [ebx + 12], 20 5 flags=1 reverse=False
# Only testing assembly here as the disassembly-testing keywords can handle at most 8 bytes of code.
AsTest 48b8f0debc8a67452301 movabs rax, 81985529234382576 flags=1
RoundTrip BE 48890cc516a9fd00 mov qword ptr [8*rax + 16623894], rcx 8 flags=1 reverse=False
RoundTrip BE 48ffc0 inc rax 3 flags=1 reverse=False
RoundTrip BE 65488b06 mov rax, qword ptr gs:[rsi] flags=1 reverse=False
Should Assemble And Disassemble X86_64 Using GAS Syntax
Create Machine X86_64 x86_64
RoundTrip BE 676b7b0c14 imull $20, 12(%ebx), %edi 5 reverse=False
AsTest 48b8f0debc8a67452301 movabsq $81985529234382576, %rax
RoundTrip BE 48890cc516a9fd00 movq %rcx, 16623894(,%rax,8) 8 reverse=False
RoundTrip BE 48ffc0 incq %rax 3 reverse=False
RoundTrip BE 65488b06 movq %gs:(%rsi), %rax reverse=False
Should Handle Illegal Instruction When Disassembling
Create Machine RiscV64 rv64g
DisasTest LE 0
DisasTest LE 0000
Should Handle Disassembly From Invalid Address
Create Machine RiscV64 rv64g
# test with the valid address
DisasTest LE 02051613 slli a2, a0, 32 hex_addr=1234
# check whether the output contains error if we only change the address to be outside "mem"
Run Keyword And Expect Error 'Disassembly error detected* DisasTest LE 02051613 slli a2, a0, 32 hex_addr=02000000
Should Take Base Address Into Account When Assembling
Create Machine X86 x86
AsTest 8d0534120000 a: lea eax, [a] address=0x1234 flags=1
AsTest 8d053a120000 lea eax, [a]; a: address=0x1234 flags=1
Should Assemble Multiline Program
${prog}= Catenate SEPARATOR=\n
... nop
... nop
Create Machine X86 x86
Execute Command sysbus.cpu AssembleBlock 0 "${prog}"
${ins}= Execute Command sysbus ReadWord 0
Should Be Equal As Numbers ${ins} 0x9090
Should Handle Illegal Instruction When Assembling
Create Machine RiscV64 rv64g
Run Keyword And Expect Error *unrecognized instruction mnemonic* AsTest 00 illegalinstruction123
Run Keyword And Expect Error *invalid operand* AsTest 00 sw s123, 0(sp)
# The V extension is not in rv64g so this is illegal as well
Run Keyword And Expect Error *instruction requires * 'V'* AsTest 00 vsetvli a4, a0, e8, m1, tu, mu
Should Handle Assembler Directives
Create Machine X86 x86
AsTest 909090909090 .rept 6; nop; .endr