1AArch64 Simulator state trace 2============================= 3 4The AArch64 Simulator can be configured to produce traces of instruction 5execution, register contents, and memory accesses. The trace is designed to be 6intuitive for human readers, but this document describes the format of the 7trace, so that post-processing tools can confidently parse the output. 8 9In VIXL's own test runner, the trace is controlled by the `--trace*` options. 10Run `test-runner --help` for details. 11 12Basic structure 13--------------- 14 15Executed instructions show the address, the encoding of the instruction and the 16disassembly (as produced by VIXL's Disassembler). For example: 17 18 0x00007fbe2a6a9044 d299d200 mov x0, #0xce90 19 20The first field is the address of the instruction, with exactly 16 hexadecimal 21characters and a leading 0x, and is followed by two spaces. The second field is 22the instruction encoding, with exactly eight hexadecimal characters (and no 23leading 0x). This is followed by two _tab_ characters, and the instruction 24disassembly. The following regular expression can be used to capture each field: 25 26 (0x[0-9a-f]{16}) ([0-9a-f]{8})\t\t(.*) 27 28Following each instruction are zero or more lines of state update. Most notably, 29these represent the register state updates and memory accesses that occurred 30during simulation of the instruction. All of these lines begin with a '#' 31character, so that they can be easily identified, and filtered if necessary. For 32example: 33 34 0x00007fd2221c907c 8b82200e add x14, x0, x2, asr #8 35 # x14: 0xfffedcba98765432 36 0x00007fd2221c9080 0b81200f add w15, w0, w1, asr #8 37 # w15: 0xff89abcd 38 39Note that the Simulator uses these state update lines to describe its initial 40state. As a result, there will be state trace output before the first simulated 41instruction, and parsers need to be tolerant of this. 42 43Note that padding white space is used liberally to keep values vertically 44aligned throughout the trace (as shown with the write to `w15` in the example 45above). Similarly, some compound values are split into parts using the C++14 46literal separator (`'`) character. Refer to the "Memory accesses" section 47(below) for examples. 48 49Ordering 50-------- 51 52VIXL guarantees that each instruction is printed before its associated state 53trace. 54 55State trace must be interpreted sequentially, line by line. VIXL avoids updating 56the same register more than once (because it makes the trace hard for humans to 57read), but this can occur in some situations, and should be supported by 58parsers. 59 60The state is intended to be consistent with architectural execution at the start 61of each instruction and at the end of the whole trace, but no such guarantees 62are made about the traced state _between_ instructions. VIXL prioritises 63human-readability when choosing the ordering of state updates. 64 65If simulated registers are modified externally, for example using 66`WriteRegister` from C++ code, their state will (by default) be logged 67immediately. In the full trace, it will appear as though the (runtime) call or 68return instruction modified the state. This is consistent with the guarantees 69above, but it can result in single instructions appearing to generate a large 70number of state updates. 71 72There is no upper limit on the number of state update lines that any one 73instruction can generate. 74 75Whole register trace 76-------------------- 77 78The simplest form of state trace has the form "`REG: VALUE`", meaning that 79the register `REG` has the specified value, and any high-order bits in aliased 80registers are set to zero. 81 82 0x00007fd2221c907c 8b82200e add x14, x0, x2, asr #8 83 # x14: 0xfffedcba98765432 84 85Note that to correctly track state, parsers need to be aware of architectural 86register aliasing rules. Also, VIXL uses some standard register aliases, such as 87`lr` (`x30`). To avoid misinterpreting a register alias (and thereby potentially 88missing an aliased register update), some tools may need to treat an 89unrecognised register name as an error. 90 91This trace format attempts to represent _architectural_ register writes. 92However, this is not strictly checked or enforced. 93 94`VALUE` is always shown in hexadecimal (raw bits) form, with a leading `0x` and 95enough digits to exactly fill `REG`. `VALUE` may also include annotations (for 96example to show FP arithmetic values) in parentheses. These annotations are for 97the benefit of human readers, and parsers may ignore them. 98 99Note that SVE registers _always_ use the partial register trace format, 100described below, so a plain `z` or `p` register will never be used in a whole 101register trace. This is true even if the vector length is configured to 16 102bytes. 103 104Partial register trace 105---------------------- 106 107Sometimes, VIXL needs to show _part_ of a register without implying that the 108rest of the register is zeroed. A partial register value is indicated by a bit 109range in angled brackets after the register name: "`REG<MSB:LSB>: VALUE`". 110This format is used for stores, for example. 111 112SVE register updates are split across multiple lines, and therefore always use 113the partial register trace format. For example (with a 384-bit VL): 114 115 0x00007fb1978da044 04214000 index z0.b, #0, #1 116 # z0<383:256>: 0x2f2e2d2c2b2a29282726252423222120 117 # z0<255:128>: 0x1f1e1d1c1b1a19181716151413121110 118 # z0<127:0>: 0x0f0e0d0c0b0a09080706050403020100 119 120Note that VIXL will omit whole lines where they are unnecessary, for example if 121they have no active (predicated) lanes. Parsers should not assume that every 122part of a register will appear in such cases. 123 124The `VALUE` has the same format as in the whole register trace, except in the 125case of SVE `p` registers (as described below). 126 127SVE `p` registers 128----------------- 129 130For `p` registers, we try to keep the lanes vertically aligned with the 131corresponding parts of the `z` registers that they affect. To do this, we use a 132binary format, with a leading `0b`, and spaces between each digit. For example: 133 134 0x00007f66e539b0b8 04f54607 index z7.d, x16, #-11 135 # z7<127:0>: 0x00000000000000150000000000000020 136 0x00007f66e539b0bc 25d8e3a7 ptrue p7.d, all 137 # p7<15:0>: 0b 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 138 139Memory accesses 140--------------- 141 142The pattern for a memory access is "`VALUE OP ADDRESS`", where: 143 144- `VALUE` is a hexadecimal value, with visual separators (') between 145 structure components, 146- `OP` is `"->"` for a store, or `"<-"` for a load, 147- `ADDRESS` is the (hexadecimal) address of the access. 148 149Accesses shown in this style are always contiguous, and with little-endian 150semantics. However, a given instruction might have multiple lines of memory 151access trace, particularly if the instruction performs non-contiguous accesses. 152 153In the case of simple accesses, the `VALUE` is shared with register value trace: 154 155 0x00007f3835372058 e400e401 st1b { z1.b }, p1, [x0] 156 # z1<127:0>: 0xd4d7dadde0e3e6e9eceff2f5f8fbfe01 -> 0x000055d170298e90 157 158Sign-extending loads show the whole resulting register value, with the (smaller) 159access represented on a separate line. This makes the (differing) values in the 160register and in memory unambiguous, without parsers needing to understand the 161instruction set: 162 163 0x00007f47922d0068 79800306 ldrsh x6, [x24] 164 # x6: 0xffffffffffff8080 165 # ╙─ 0x8080 <- 0x00007fffbc197708 166 167Some instructions access several different memory locations. In these cases, 168each access is given its own line, with the highest lane index first so that 169(for contiguous accesses) the lowest address ends up at the bottom: 170 171 0x00007fa6001e9060 e4217c0a st2b { z10.b, z11.b }, p7, [x0, x1] 172 # z10<127:0>: 0x0f0e0d0c0b0a09080706050403020100 173 # z11<127:0>: 0x1f1e1d1c1b1a19181716151413121110 174 # ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ╙─ 0x10'00 -> 0x00007ffe485d2f90 175 # ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ╙─── 0x11'01 -> 0x00007ffe485d2f92 176 # ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ╙───── 0x12'02 -> 0x00007ffe485d2f94 177 # ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ╙─────── 0x13'03 -> 0x00007ffe485d2f96 178 # ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ╙───────── 0x14'04 -> 0x00007ffe485d2f98 179 # ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ╙─────────── 0x15'05 -> 0x00007ffe485d2f9a 180 # ║ ║ ║ ║ ║ ║ ║ ║ ║ ╙───────────── 0x16'06 -> 0x00007ffe485d2f9c 181 # ║ ║ ║ ║ ║ ║ ║ ║ ╙─────────────── 0x17'07 -> 0x00007ffe485d2f9e 182 # ║ ║ ║ ║ ║ ║ ║ ╙───────────────── 0x18'08 -> 0x00007ffe485d2fa0 183 # ║ ║ ║ ║ ║ ║ ╙─────────────────── 0x19'09 -> 0x00007ffe485d2fa2 184 # ║ ║ ║ ║ ║ ╙───────────────────── 0x1a'0a -> 0x00007ffe485d2fa4 185 # ║ ║ ║ ║ ╙─────────────────────── 0x1b'0b -> 0x00007ffe485d2fa6 186 # ║ ║ ║ ╙───────────────────────── 0x1c'0c -> 0x00007ffe485d2fa8 187 # ║ ║ ╙─────────────────────────── 0x1d'0d -> 0x00007ffe485d2faa 188 # ║ ╙───────────────────────────── 0x1e'0e -> 0x00007ffe485d2fac 189 # ╙─────────────────────────────── 0x1f'0f -> 0x00007ffe485d2fae 190 191The line-drawing characters are encoded as UTF-8 (as is this document). There is 192currently no locale handling in VIXL, so this is not configurable. However, 193since these annotations are for the benefit of human readers, parsers can safely 194ignore them, and treat the whole trace as an ASCII byte stream (ignoring 8-bit 195characters). This is useful in situations where UTF-8 handling carries an 196unacceptable performance cost. 197 198In the future, VIXL may offer an option to avoid printing these annotations, so 199that the trace is restricted to single-byte characters. 200 201Floating-point value annotations 202-------------------------------- 203 204Some floating-point operations produce register trace that annotates the raw 205values with the corresponding FP arithmetic values. This is for the benefit of 206human readers (and has limited precision). Such annotations follow the `VALUE` 207in parentheses. 208 209Scalar form: 210 211 # s1: 0x3f800000 (1.000) <- 0x00007ffdc64d2314 212 213Vector form, updating all S lanes using a load: 214 215 # v16: 0x1211100f0e0d0c0b0a09080706050403 (4.577e-28, 1.739e-30, 6.598e-33, 2.502e-35) 216 # ║ ║ ║ ╙─ 0x06050403 <- 0x00007ffe56fd7863 217 # ║ ║ ╙───────── 0x0a090807 <- 0x00007ffe56fd7867 218 # ║ ╙───────────────── 0x0e0d0c0b <- 0x00007ffe56fd786b 219 # ╙───────────────────────── 0x1211100f <- 0x00007ffe56fd786f 220 221Vector form, updating a single S lane using a load: 222 223 # v2: 0x03020100040302017ff0f0027f80f000 (..., 1.540e-36, ...) 224 # ╙───────────────── 0x04030201 <- 0x00007ffc7b2e3ca1 225 226Vector form, replicating a single struct load to all S lanes: 227 228 # v15: 0x100f0e0d100f0e0d100f0e0d100f0e0d (2.821e-29, 2.821e-29, 2.821e-29, 2.821e-29) 229 # v16: 0x14131211141312111413121114131211 (7.425e-27, 7.425e-27, 7.425e-27, 7.425e-27) 230 # v17: 0x18171615181716151817161518171615 (1.953e-24, 1.953e-24, 1.953e-24, 1.953e-24) 231 # ╙───────╨───────╨───────╨─ 0x18171615'14131211'100f0e0d <- 0x00007ffdd64d847d 232