1*** Keywords *** 2 3# WriteDoubleWord: reversed bytes 4# Disassembly output: spaces between bytes 5DisasTest BE 6 [Arguments] ${hex_code} ${mnemonic}= ${operands}= ${code_size}=4 ${hex_addr}=0 ${flags}=0 7 8 ${hex_addr}= Convert To Hex ${hex_addr} length=8 base=16 9 10 ${b1}= Get Substring ${hex_code} 0 2 11 ${b2}= Get Substring ${hex_code} 2 4 12 ${b3}= Get Substring ${hex_code} 4 6 13 ${b4}= Get Substring ${hex_code} 6 8 14 15 ${b_write}= Set Variable ${b4}${b3}${b2}${b1} 16 ${b_disas}= Set Variable ${b1}${b2}${b3}${b4} 17 18 IF ${code_size} > 4 19 ${b_disas_4B+}= Write Extra Bytes BE And Return Their Expected Output ${hex_addr} ${hex_code} 20 ELSE 21 ${b_disas_4B+}= Set Variable ${None} 22 END 23 ${b_disas}= Set Variable If ${code_size} > 4 ${b_disas}${b_disas_4B+} ${b_disas} 24 25 DisasTest Core ${hex_addr} ${b_write} ${b_disas} ${mnemonic} ${operands} ${code_size} ${flags} 26 27 28RoundTrip BE 29 [Arguments] ${hex_code} ${mnemonic}= ${operands}= ${code_size}=4 ${hex_addr}=0 ${flags}=0 ${reverse}=True 30 31 IF ${reverse} 32 ${expected}= Reverse Bytes ${{$hex_code[:int($code_size) * 2]}} 33 ELSE 34 ${expected}= Set Variable ${hex_code} 35 END 36 AsTest ${expected} ${mnemonic} ${operands} ${flags} 0x${hex_addr} 37 DisasTest BE ${hex_code} ${mnemonic} ${operands} ${code_size} ${hex_addr} ${flags} 38 39 40Write Extra Bytes BE And Return Their Expected Output 41 [Arguments] ${hex_addr} ${hex_code} 42 43 ${int}= Convert To Integer 0x${hex_addr} 44 ${int}= Evaluate $int + 4 45 ${adjusted_addr}= Convert To Hex ${int} 46 47 ${b5}= Get Substring ${hex_code} 8 10 48 ${b6}= Get Substring ${hex_code} 10 12 49 ${b7}= Get Substring ${hex_code} 12 14 50 ${b8}= Get Substring ${hex_code} 14 16 51 52 Execute Command sysbus WriteDoubleWord 0x${adjusted_addr} 0x${b8}${b7}${b6}${b5} 53 54 Return From Keyword ${b5}${b6}${b7}${b8} 55 56Reverse Bytes 57 [Arguments] ${hex_str} ${group_size}=${2} 58 59 ${len}= Get Length ${hex_str} 60 ${out}= Create List 61 FOR ${i} IN RANGE 0 ${len} ${group_size} 62 ${byte}= Get Substring ${hex_str} ${i} ${{$i+$group_size}} 63 Append To List ${out} ${byte} 64 END 65 Reverse List ${out} 66 67 [Return] ${{"".join($out)}} 68 69# WriteDoubleWord: reversed words 70# Disassembly output: space between words 71DisasTest Thumb 72 [Arguments] ${hex_code} ${mnemonic}= ${operands}= ${code_size}=4 ${hex_addr}=0 73 74 ${hex_addr}= Convert To Hex ${hex_addr} length=8 base=16 75 76 ${w1}= Get Substring ${hex_code} 0 4 77 ${w2}= Get Substring ${hex_code} 4 78 79 ${b_write}= Set Variable ${w2}${w1} 80 ${b_disas}= Set Variable ${w1}${w2} 81 82 DisasTest Core ${hex_addr} ${b_write} ${b_disas} ${mnemonic} ${operands} ${code_size} 83 84 85RoundTrip Thumb 86 [Arguments] ${hex_code} ${mnemonic}= ${operands}= ${code_size}=4 ${hex_addr}=0 87 88 # For Thumb, reverse the bytes in each word 89 ${expected}= Reverse Bytes ${hex_code} 90 ${expected}= Reverse Bytes ${expected} group_size=${4} 91 AsTest ${expected} ${mnemonic} ${operands} address=0x${hex_addr} 92 DisasTest Thumb ${hex_code} ${mnemonic} ${operands} ${code_size} ${hex_addr} 93 94 95DisasTest LE 96 [Arguments] ${hex_code} ${mnemonic}= ${operands}= ${code_size}=4 ${hex_addr}=0 97 98 ${hex_addr}= Convert To Hex ${hex_addr} length=8 base=16 99 100 DisasTest Core ${hex_addr} ${hex_code} ${hex_code} ${mnemonic} ${operands} ${code_size} 101 102 103RoundTrip LE 104 [Arguments] ${hex_code} ${mnemonic}= ${operands}= ${code_size}=4 ${hex_addr}=0 105 106 ${expected}= Reverse Bytes ${{$hex_code[:int($code_size) * 2]}} 107 AsTest ${expected} ${mnemonic} ${operands} address=0x${hex_addr} 108 DisasTest LE ${hex_code} ${mnemonic} ${operands} ${code_size} ${hex_addr} 109 110 111DisasTest Core 112 [Arguments] ${hex_addr} ${code_write} ${code_disas} ${mnemonic} ${operands} ${code_size} ${flags}=0 113 114 Execute Command sysbus WriteDoubleWord 0x${hex_addr} 0x${code_write} 115 ${res}= Execute Command sysbus.cpu DisassembleBlock 0x${hex_addr} ${code_size} ${flags} 116 117 # expect error if "$mnemonic" and "$operands" (without curly brackets!) are empty 118 Run Keyword And Return If $mnemonic == '' and $operands == '' Should Match Regexp ${res} Disassembly error detected 119 120 # compare DisassembleBlock output with the expected one; "(?i)" prefix causes ignoring case difference 121 ${escaped_mnem}= Regexp Escape ${mnemonic} 122 ${escaped_oper}= Regexp Escape ${operands} 123 Should Match Regexp ${res} (?i)^0x${hex_addr}:\\s+${code_disas}\\s+${escaped_mnem}\\s+${escaped_oper}\\n+$ 124 125 126AsTest 127 [Arguments] ${expected} ${mnemonic} ${operands}= ${flags}=0 ${address}=0 128 129 ${len}= Execute Command sysbus.cpu AssembleBlock ${address} "${mnemonic} ${operands}" ${flags} 130 ${bytes}= Execute Command sysbus ReadBytes ${address} ${len} 131 132 # This string is safe to eval because it's formatted as a Python list by PrintActionResult in MonitorCommands.cs 133 ${hex_bytes}= Evaluate "".join("%02x"%b for b in ${bytes}) 134 135 # Reverse the bytes for a big-endian bus because the expected strings in the test cases are formatted 136 # as if they had been read by ReadDoubleWord 137 ${bus_endian}= Execute Command sysbus Endianess 138 ${bus_endian}= Get Line ${bus_endian} 0 139 IF "${bus_endian}" == "BigEndian" 140 ${hex_bytes}= Reverse Bytes ${hex_bytes} 141 END 142 143 Should Be Equal ${hex_bytes} ${expected} 144 145 146Create Machine 147 [Arguments] ${cpu} ${model} 148 149 # "extra" will be appended to the cpu creation string after cpuType (at least it has to close curly brackets opened before cpuType) 150 ${extra}= Set Variable } 151 152 # the last ${extra} field covers the "else" case, keeping the previous value of "extra"; by default, "else" case sets variables to "None" 153 ${extra}= Set Variable If "${cpu}" == "CortexM" ; nvic: nvic }; nvic: IRQControllers.NVIC ${extra} 154 ${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} 155 ${extra}= Set Variable If "${cpu}" == "PowerPc64" ; endianness: Endianess.LittleEndian } ${extra} 156 ${extra}= Set Variable If "${cpu}" == "RiscV32" ; timeProvider: empty } ${extra} 157 ${extra}= Set Variable If "${cpu}" == "RiscV64" ; timeProvider: empty } ${extra} 158 ${extra}= Set Variable If "${cpu}" == "X86" ; lapic: empty } ${extra} 159 ${extra}= Set Variable If "${cpu}" == "X86_64" ; lapic: empty } ${extra} 160 161 162 Execute Command mach create 163 IF any(x in "${cpu}" for x in ("PowerPc", "Sparc")) 164 Execute Command machine LoadPlatformDescriptionFromString "sysbus: { Endianess: Endianess.BigEndian }" 165 END 166 Execute Command machine LoadPlatformDescriptionFromString "cpu: CPU.${cpu} @ sysbus { cpuType: \\"${model}\\" ${extra}" 167 Execute Command machine LoadPlatformDescriptionFromString "mem: Memory.MappedMemory @ sysbus 0x0 { size: 0x50000 }" 168 169Assemble And Disassemble RV32IMA 170 [Arguments] ${compressed}=False 171 172 # Compressed format will be generated by the assembler if the core has the C extension 173 # and is only accepted by the disassembler if the core has the C extension. The disassembler 174 # output doesn't explicitly indicate the compressed instruction (c.sw, c.add) 175 IF ${compressed} 176 RoundTrip LE c84a sw s2, 16(sp) 2 # rv32c 177 RoundTrip LE 95be add a1, a1, a5 2 # rv32c 178 ELSE 179 RoundTrip LE 01212823 sw s2, 16(sp) # rv32i 180 RoundTrip LE 00b785b3 add a1, a5, a1 # rv32i 181 END 182 183 # The uncompressed forms should be accepted by the disassembler even with the C extension 184 DisasTest LE 01212823 sw s2, 16(sp) # rv32i 185 DisasTest LE 00b785b3 add a1, a5, a1 # rv32i 186 187 RoundTrip LE 00008297 auipc t0, 8 # rv32i 188 RoundTrip LE 0000100f fence.i # Zifencei 189 RoundTrip LE 3401f173 csrrci sp, mscratch, 3 # Zicsr 190 RoundTrip LE 02ab5c33 divu s8, s6, a0 # rv32m 191 RoundTrip LE 0805252f amoswap.w a0, zero, (a0) # rv32a 192 193Assemble And Disassemble RV32FD 194 RoundTrip LE 580123d3 fsqrt.s ft7, ft2, rdn # rv32f 195 RoundTrip LE 5a0123d3 fsqrt.d ft7, ft2, rdn # rv32d 196 197Assemble And Disassemble RV32C 198 RoundTrip LE 3fed jal -6 2 # rv32c 199 200Assemble And Disassemble RV64IMAC 201 RoundTrip LE 000a3a83 ld s5, 0(s4) # rv64i 202 RoundTrip LE abcd8a9b addiw s5, s11, -1348 # rv64i 203 RoundTrip LE 02ab7c3b remuw s8, s6, a0 # rv64m 204 RoundTrip LE e705b52f amomaxu.d.aqrl a0, a6, (a1) # rv64a 205 RoundTrip LE eabc sd a5, 80(a3) 2 # rv64c 206 207Assemble And Disassemble RV64FD 208 RoundTrip LE d0312353 fcvt.s.lu ft6, sp, rdn # rv64f 209 RoundTrip LE d2312353 fcvt.d.lu ft6, sp, rdn # rv64d 210 211Assemble And Disassemble RVV 212 RoundTrip LE 00057757 vsetvli a4, a0, e8, m1, tu, mu # rv64v 213 RoundTrip LE 03058407 vle8ff.v v8, (a1) # rv64v 214 RoundTrip LE 4218a757 vfirst.m a4, v1 # rv64v 215 216 217*** Test Cases *** 218 219# Keywords to disassemble single instruction 220# 221# DisasTest (BE|LE|Thumb) HEX_CODE [MNEMONIC] [OPERANDS] [CODE_SIZE=4] [HEX_ADDR=00000000] 222# HEX_CODE the opcode to disassemble; don't prefix with "0x" 223# MNEMONIC, OPERANDS expected disassembly results; expect empty result if both are empty 224# CODE_SIZE in bytes; max 8B instructions are supported 225# HEX_ADDR hex address of the instruction, verified with the disassembler output but not influencing the opcode itself; don't prefix with "0x" 226 227Should Assemble And Disassemble ARM Cortex-A 228 Create Machine ARMv7A arm926 229 230 RoundTrip LE 32855001 addlo r5, r5, \#1 hex_addr=8000 231 RoundTrip LE e1b00a00 lsls r0, r0, \#20 hex_addr=813c 232 RoundTrip LE 1a00000a bne \#40 233 234Should Assemble And Disassemble ARM Cortex-A53 235 Create Machine ARMv8A cortex-a53 236 237 RoundTrip LE 5400f041 b.ne \#7688 238 RoundTrip LE aa0603e1 mov x1, x6 239 RoundTrip LE aa2c1c65 orn x5, x3, x12, lsl \#7 240 241Should Assemble And Disassemble ARM Cortex-M 242 Create Machine CortexM cortex-m4 243 244 RoundTrip Thumb f0230403 bic r4, r3, \#3 hex_addr=2 245 RoundTrip Thumb 58c8 ldr r0, [r1, r3] 2 246 RoundTrip Thumb f44f426d mov.w r2, \#60672 hex_addr=9e8 247 RoundTrip Thumb 10b6 asrs r6, r6, \#2 2 ad88 248 249Should Assemble And Disassemble RISCV32IMA 250 Create Machine RiscV32 rv32ima 251 Assemble And Disassemble RV32IMA 252 253Should Assemble And Disassemble RISCV32IMAC 254 Create Machine RiscV32 rv32imac 255 Assemble And Disassemble RV32IMA compressed=True 256 Assemble And Disassemble RV32C 257 258Should Assemble And Disassemble RISCV32IMAFDC 259 Create Machine RiscV32 rv32imafdc 260 Assemble And Disassemble RV32IMA compressed=True 261 Assemble And Disassemble RV32FD 262 Assemble And Disassemble RV32C 263 264Should Assemble And Disassemble RISCV32GC 265 Create Machine RiscV32 rv32gc 266 Assemble And Disassemble RV32IMA compressed=True 267 Assemble And Disassemble RV32FD 268 Assemble And Disassemble RV32C 269 270Should Assemble And Disassemble RISCV32GV 271 Create Machine RiscV32 rv32gv 272 Assemble And Disassemble RV32IMA 273 Assemble And Disassemble RVV 274 275Should Assemble And Disassemble RISCV64IMAC 276 Create Machine RiscV64 rv64imac 277 Assemble And Disassemble RV32IMA compressed=True 278 Assemble And Disassemble RV64IMAC 279 280Should Assemble And Disassemble RISCV64IMAFDC 281 Create Machine RiscV64 rv64imafdc 282 Assemble And Disassemble RV32IMA compressed=True 283 Assemble And Disassemble RV32FD 284 Assemble And Disassemble RV64IMAC 285 Assemble And Disassemble RV64FD 286 287Should Assemble And Disassemble RISCV64GC 288 Create Machine RiscV64 rv64gc 289 Assemble And Disassemble RV32IMA compressed=True 290 Assemble And Disassemble RV32FD 291 Assemble And Disassemble RV64IMAC 292 Assemble And Disassemble RV64FD 293 294Should Assemble And Disassemble RISCV64GCV 295 Create Machine RiscV64 rv64gcv 296 Assemble And Disassemble RV64IMAC 297 Assemble And Disassemble RVV 298 299Should Assemble And Disassemble PPC 300 Create Machine PowerPc e200z6 301 302 RoundTrip LE 4800007c b .+124 303 RoundTrip LE 7f880040 cmplw 7, 8, 0 hex_addr=123 304 RoundTrip LE 7ce40034 cntlzw 4, 7 305 306Should Assemble And Disassemble PPC64 LE 307 Create Machine PowerPc64 620 308 309 # RoundTrip BE is used because of the output formatting in DisasTest BE 310 # CPU is set as LE in Renode and LLVM's LE version of ppc64 is used 311 RoundTrip BE 18002389 lbz 9, 24(3) 312 RoundTrip BE 40202a7c cmpld 10, 4 313 RoundTrip BE 71790248 bl .+162160 314 315Should Assemble And Disassemble Sparc 316 Create Machine Sparc leon3 317 318 RoundTrip LE 85e8a018 restore %g2, 24, %g2 hex_addr=abc 319 RoundTrip LE 01000000 nop hex_addr=abc 320 RoundTrip LE 10680047 ba %xcc, 71 321 322Should Assemble And Disassemble X86 Using Intel Syntax 323 Create Machine X86 x86 324 325 RoundTrip BE 6b7b0c14 imul edi, dword ptr [ebx + 12], 20 flags=1 reverse=False 326 RoundTrip BE 45 inc ebp 1 flags=1 reverse=False 327 RoundTrip BE 0fb7c0 movzx eax, ax 3 cc flags=1 reverse=False 328 RoundTrip BE 66890cc516a9fd00 mov word ptr [8*eax + 16623894], cx 8 a flags=1 reverse=False 329 RoundTrip BE 0f011d5e00fc00 lidtd [16515166] 7 abd flags=1 reverse=False 330 331Should Assemble And Disassemble X86 Using GAS Syntax 332 Create Machine X86 x86 333 334 RoundTrip BE 6b7b0c14 imull $20, 12(%ebx), %edi reverse=False 335 RoundTrip BE 45 incl %ebp 1 reverse=False 336 RoundTrip BE 0fb7c0 movzwl %ax, %eax 3 cc reverse=False 337 RoundTrip BE 66890cc516a9fd00 movw %cx, 16623894(,%eax,8) 8 a reverse=False 338 RoundTrip BE 0f011d5e00fc00 lidtl 16515166 7 abd reverse=False 339 340Should Assemble And Disassemble X86_64 Using Intel Syntax 341 Create Machine X86_64 x86_64 342 343 RoundTrip BE 676b7b0c14 imul edi, dword ptr [ebx + 12], 20 5 flags=1 reverse=False 344 # Only testing assembly here as the disassembly-testing keywords can handle at most 8 bytes of code. 345 AsTest 48b8f0debc8a67452301 movabs rax, 81985529234382576 flags=1 346 RoundTrip BE 48890cc516a9fd00 mov qword ptr [8*rax + 16623894], rcx 8 flags=1 reverse=False 347 RoundTrip BE 48ffc0 inc rax 3 flags=1 reverse=False 348 RoundTrip BE 65488b06 mov rax, qword ptr gs:[rsi] flags=1 reverse=False 349 350Should Assemble And Disassemble X86_64 Using GAS Syntax 351 Create Machine X86_64 x86_64 352 353 RoundTrip BE 676b7b0c14 imull $20, 12(%ebx), %edi 5 reverse=False 354 AsTest 48b8f0debc8a67452301 movabsq $81985529234382576, %rax 355 RoundTrip BE 48890cc516a9fd00 movq %rcx, 16623894(,%rax,8) 8 reverse=False 356 RoundTrip BE 48ffc0 incq %rax 3 reverse=False 357 RoundTrip BE 65488b06 movq %gs:(%rsi), %rax reverse=False 358 359Should Handle Illegal Instruction When Disassembling 360 Create Machine RiscV64 rv64g 361 362 DisasTest LE 0 363 DisasTest LE 0000 364 365Should Handle Disassembly From Invalid Address 366 Create Machine RiscV64 rv64g 367 368 # test with the valid address 369 DisasTest LE 02051613 slli a2, a0, 32 hex_addr=1234 370 371 # check whether the output contains error if we only change the address to be outside "mem" 372 Run Keyword And Expect Error 'Disassembly error detected* DisasTest LE 02051613 slli a2, a0, 32 hex_addr=02000000 373 374Should Take Base Address Into Account When Assembling 375 Create Machine X86 x86 376 377 AsTest 8d0534120000 a: lea eax, [a] address=0x1234 flags=1 378 AsTest 8d053a120000 lea eax, [a]; a: address=0x1234 flags=1 379 380Should Assemble Multiline Program 381 ${prog}= Catenate SEPARATOR=\n 382 ... nop 383 ... nop 384 385 Create Machine X86 x86 386 387 Execute Command sysbus.cpu AssembleBlock 0 "${prog}" 388 389 ${ins}= Execute Command sysbus ReadWord 0 390 391 Should Be Equal As Numbers ${ins} 0x9090 392 393Should Handle Illegal Instruction When Assembling 394 Create Machine RiscV64 rv64g 395 396 Run Keyword And Expect Error *unrecognized instruction mnemonic* AsTest 00 illegalinstruction123 397 Run Keyword And Expect Error *invalid operand* AsTest 00 sw s123, 0(sp) 398 # The V extension is not in rv64g so this is illegal as well 399 Run Keyword And Expect Error *instruction requires * 'V'* AsTest 00 vsetvli a4, a0, e8, m1, tu, mu 400 401Should Handle Assembler Directives 402 Create Machine X86 x86 403 404 AsTest 909090909090 .rept 6; nop; .endr 405