*** 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