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