|
| 1 | +[[sec:zilsd]] |
| 2 | +== "Zilsd", "Zclsd" Extensions for Load/Store pair for RV32, Version 1.0 |
| 3 | + |
| 4 | +The Zilsd & Zclsd extensions provide load/store pair instructions for RV32, reusing the existing RV64 doubleword load/store instruction encodings. |
| 5 | + |
| 6 | +Operands containing `src` for store instructions and `dest` for load instructions are held in aligned `x`-register pairs, i.e., register numbers must be even. Use of misaligned (odd-numbered) registers for these operands is _reserved_. |
| 7 | + |
| 8 | +Regardless of endianness, the lower-numbered register holds the |
| 9 | +low-order bits, and the higher-numbered register holds the high-order |
| 10 | +bits: e.g., bits 31:0 of an operand in Zilsd might be held in register `x14`, with bits 63:32 of that operand held in `x15`. |
| 11 | + |
| 12 | +[[zilsd, Zilsd]] |
| 13 | +=== Load/Store pair instructions (Zilsd) |
| 14 | + |
| 15 | +The Zilsd extension adds the following RV32-only instructions: |
| 16 | + |
| 17 | +[%header,cols="^1,^1,4,8"] |
| 18 | +|=== |
| 19 | +|RV32 |
| 20 | +|RV64 |
| 21 | +|Mnemonic |
| 22 | +|Instruction |
| 23 | + |
| 24 | +|yes |
| 25 | +|no |
| 26 | +|ld rd, offset(rs1) |
| 27 | +|<<#insns-ld>> |
| 28 | + |
| 29 | +|yes |
| 30 | +|no |
| 31 | +|sd rs2, offset(rs1) |
| 32 | +|<<#insns-sd>> |
| 33 | + |
| 34 | +|=== |
| 35 | + |
| 36 | +As the access size is 64-bit, accesses are only considered naturally aligned for effective addresses that are a multiple of 8. |
| 37 | +In this case, these instructions are guaranteed to not raise an address-misaligned exception. |
| 38 | +Even if naturally aligned, the memory access might not be performed atomically. |
| 39 | + |
| 40 | +If the effective address is a multiple of 4, then each word access is required to be performed atomically. |
| 41 | + |
| 42 | +The following table summarizes the required behavior: |
| 43 | + |
| 44 | +[%header] |
| 45 | +|=== |
| 46 | +|Alignment |Word accesses guaranteed atomic? |Can cause misaligned trap? |
| 47 | +|8B |yes |no |
| 48 | +|4B not 8B |yes |yes |
| 49 | +|else |no | yes |
| 50 | +|=== |
| 51 | + |
| 52 | +To ensure resumable trap handling is possible for the load instructions, the base register must have its original value if a trap is taken. The other register in the pair can have been updated. |
| 53 | +This affects x2 for the stack pointer relative instruction and rs1 otherwise. |
| 54 | + |
| 55 | +[NOTE] |
| 56 | +==== |
| 57 | +If an implementation performs a doubleword load access atomically and the register file implements writeback for even/odd register pairs, |
| 58 | +the mentioned atomicity requirements are inherently fulfilled. |
| 59 | +Otherwise, an implementation either needs to delay the writeback until the write can be performed atomically, |
| 60 | +or order sequential writes to the registers to ensure the requirement above is satisfied. |
| 61 | +==== |
| 62 | + |
| 63 | +[[zclsd, Zclsd]] |
| 64 | +=== Compressed Load/Store pair instructions (Zclsd) |
| 65 | + |
| 66 | +Zclsd depends on Zilsd and Zca. It has overlapping encodings with Zcf and is thus incompatible with Zcf. |
| 67 | + |
| 68 | +Zclsd adds the following RV32-only instructions: |
| 69 | + |
| 70 | +[%header,cols="^1,^1,4,8"] |
| 71 | +|=== |
| 72 | +|RV32 |
| 73 | +|RV64 |
| 74 | +|Mnemonic |
| 75 | +|Instruction |
| 76 | + |
| 77 | +|yes |
| 78 | +|no |
| 79 | +|c.ldsp rd, offset(sp) |
| 80 | +|<<#insns-cldsp>> |
| 81 | + |
| 82 | +|yes |
| 83 | +|no |
| 84 | +|c.sdsp rs2, offset(sp) |
| 85 | +|<<#insns-csdsp>> |
| 86 | + |
| 87 | +|yes |
| 88 | +|no |
| 89 | +|c.ld rd', offset(rs1') |
| 90 | +|<<#insns-cld>> |
| 91 | + |
| 92 | +|yes |
| 93 | +|no |
| 94 | +|c.sd rs2', offset(rs1') |
| 95 | +|<<#insns-csd>> |
| 96 | + |
| 97 | +|=== |
| 98 | + |
| 99 | +=== Use of x0 as operand |
| 100 | + |
| 101 | +LD instructions with destination `x0` are processed as any other load, but the result is discarded entirely and x1 is not written. |
| 102 | +For C.LDSP, usage of `x0` as the destination is reserved. |
| 103 | + |
| 104 | +If using `x0` as `src` of SD or C.SDSP, the entire 64-bit operand is zero — i.e., register `x1` is not accessed. |
| 105 | + |
| 106 | +C.LD and C.SD instructions can only use `x8-15`. |
| 107 | + |
| 108 | +=== Exception Handling |
| 109 | + |
| 110 | +For the purposes of RVWMO and exception handling, LD and SD instructions are |
| 111 | +considered to be misaligned loads and stores, with one additional constraint: |
| 112 | +an LD or SD instruction whose effective address is a multiple of 4 gives rise |
| 113 | +to two 4-byte memory operations. |
| 114 | + |
| 115 | +NOTE: This definition permits LD and SD instructions giving rise to exactly one |
| 116 | +memory access, regardless of alignment. |
| 117 | +If instructions with 4-byte-aligned effective address are decomposed |
| 118 | +into two 32b operations, there is no constraint on the order in which the |
| 119 | +operations are performed and each operation is guaranteed to be atomic. |
| 120 | +These decomposed sequences are interruptible. |
| 121 | +Exceptions might occur on subsequent operations, making the effects of previous |
| 122 | +operations within the same instruction visible. |
| 123 | + |
| 124 | +NOTE: Software should make no assumptions about the number or order of |
| 125 | +accesses these instructions might give rise to, beyond the 4-byte constraint |
| 126 | +mentioned above. |
| 127 | +For example, an interrupted store might overwrite the same bytes upon return |
| 128 | +from the interrupt handler. |
| 129 | + |
| 130 | +<<< |
| 131 | + |
| 132 | +=== Instructions |
| 133 | +[#insns-ld,reftext="Load doubleword to register pair, 32-bit encoding"] |
| 134 | +==== ld |
| 135 | + |
| 136 | +Synopsis:: |
| 137 | +Load doubleword to even/odd register pair, 32-bit encoding |
| 138 | + |
| 139 | +Mnemonic:: |
| 140 | +ld rd, offset(rs1) |
| 141 | + |
| 142 | +Encoding (RV32):: |
| 143 | +[wavedrom, ,svg] |
| 144 | +.... |
| 145 | +{reg: [ |
| 146 | + {bits: 7, name: 0x3, attr: ['LOAD'], type: 8}, |
| 147 | + {bits: 5, name: 'rd', attr: ['dest, dest[0]=0'], type: 2}, |
| 148 | + {bits: 3, name: 0x3, attr: ['width=D'], type: 8}, |
| 149 | + {bits: 5, name: 'rs1', attr: ['base'], type: 4}, |
| 150 | + {bits: 12, name: 'imm[11:0]', attr: ['offset[11:0]'], type: 3}, |
| 151 | +]} |
| 152 | +.... |
| 153 | + |
| 154 | +Description:: |
| 155 | +Loads a 64-bit value into registers `rd` and `rd+1`. |
| 156 | +The effective address is obtained by adding register rs1 to the |
| 157 | +sign-extended 12-bit offset. |
| 158 | + |
| 159 | +Included in: <<zilsd>> |
| 160 | + |
| 161 | +<<< |
| 162 | + |
| 163 | +[#insns-sd,reftext="Store doubleword from register pair, 32-bit encoding"] |
| 164 | +==== sd |
| 165 | + |
| 166 | +Synopsis:: |
| 167 | +Store doubleword from even/odd register pair, 32-bit encoding |
| 168 | + |
| 169 | +Mnemonic:: |
| 170 | +sd rs2, offset(rs1) |
| 171 | + |
| 172 | +Encoding (RV32):: |
| 173 | +[wavedrom, ,svg] |
| 174 | +.... |
| 175 | +{reg: [ |
| 176 | + {bits: 7, name: 0x23, attr: ['STORE'], type: 8}, |
| 177 | + {bits: 5, name: 'imm[4:0]', attr: ['offset[4:0]'], type: 3}, |
| 178 | + {bits: 3, name: 0x3, attr: ['width=D'], type: 8}, |
| 179 | + {bits: 5, name: 'rs1', attr: ['base'], type: 4}, |
| 180 | + {bits: 5, name: 'rs2', attr: ['src, src[0]=0'], type: 4}, |
| 181 | + {bits: 7, name: 'imm[11:5]', attr: ['offset[11:5]'], type: 3}, |
| 182 | +]} |
| 183 | +.... |
| 184 | + |
| 185 | +Description:: |
| 186 | +Stores a 64-bit value from registers `rs2` and `rs2+1`. |
| 187 | +The effective address is obtained by adding register rs1 to the |
| 188 | +sign-extended 12-bit offset. |
| 189 | + |
| 190 | +Included in: <<zilsd>> |
| 191 | + |
| 192 | +<<< |
| 193 | + |
| 194 | +[#insns-cldsp,reftext="Stack-pointer based load doubleword to register pair, 16-bit encoding"] |
| 195 | +==== c.ldsp |
| 196 | + |
| 197 | +Synopsis:: |
| 198 | +Stack-pointer based load doubleword to even/odd register pair, 16-bit encoding |
| 199 | + |
| 200 | +Mnemonic:: |
| 201 | +c.ldsp rd, offset(sp) |
| 202 | + |
| 203 | +Encoding (RV32):: |
| 204 | +[wavedrom, ,svg] |
| 205 | +.... |
| 206 | +{reg: [ |
| 207 | + {bits: 2, name: 0x2, type: 8, attr: ['C2']}, |
| 208 | + {bits: 5, name: 'imm', type: 3, attr: ['offset[4:3|8:6]']}, |
| 209 | + {bits: 5, name: 'rd', type: 2, attr: ['dest≠0, dest[0]=0']}, |
| 210 | + {bits: 1, name: 'imm', type: 3, attr: ['offset[5]']}, |
| 211 | + {bits: 3, name: 0x3, type: 8, attr: ['C.LDSP']}, |
| 212 | +], config: {bits: 16}} |
| 213 | +.... |
| 214 | + |
| 215 | +Description:: |
| 216 | +Loads stack-pointer relative 64-bit value into registers `rd'` and `rd'+1`. It computes its effective address by adding the zero-extended offset, scaled by 8, to the stack pointer, `x2`. It expands to `ld rd, offset(x2)`. C.LDSP is only valid when _rd_≠x0; the code points with _rd_=x0 are reserved. |
| 217 | + |
| 218 | +Included in: <<zclsd>> |
| 219 | + |
| 220 | +<<< |
| 221 | + |
| 222 | +[#insns-csdsp,reftext="Stack-pointer based store doubleword from register pair, 16-bit encoding"] |
| 223 | +==== c.sdsp |
| 224 | + |
| 225 | +Synopsis:: |
| 226 | +Stack-pointer based store doubleword from even/odd register pair, 16-bit encoding |
| 227 | + |
| 228 | +Mnemonic:: |
| 229 | +c.sdsp rs2, offset(sp) |
| 230 | + |
| 231 | +Encoding (RV32):: |
| 232 | +[wavedrom, ,svg] |
| 233 | +.... |
| 234 | +{reg: [ |
| 235 | + {bits: 2, name: 0x2, type: 8, attr: ['C2']}, |
| 236 | + {bits: 5, name: 'rs2', type: 4, attr: ['src, src[0]=0']}, |
| 237 | + {bits: 6, name: 'imm', type: 3, attr: ['offset[5:3|8:6]']}, |
| 238 | + {bits: 3, name: 0x7, type: 8, attr: ['C.SDSP']}, |
| 239 | +], config: {bits: 16}} |
| 240 | +.... |
| 241 | + |
| 242 | +Description:: |
| 243 | +Stores a stack-pointer relative 64-bit value from registers `rs2'` and `rs2'+1`. It computes an effective address by adding the _zero_-extended offset, scaled by 8, to the stack pointer, `x2`. It expands to `sd rs2, offset(x2)`. |
| 244 | + |
| 245 | +Included in: <<zclsd>> |
| 246 | + |
| 247 | +<<< |
| 248 | + |
| 249 | +[#insns-cld,reftext="Load doubleword to register pair, 16-bit encoding"] |
| 250 | +==== c.ld |
| 251 | + |
| 252 | +Synopsis:: |
| 253 | +Load doubleword to even/odd register pair, 16-bit encoding |
| 254 | + |
| 255 | +Mnemonic:: |
| 256 | +c.ld rd', offset(rs1') |
| 257 | + |
| 258 | +Encoding (RV32):: |
| 259 | +[wavedrom, ,svg] |
| 260 | +.... |
| 261 | +{reg: [ |
| 262 | + {bits: 2, name: 0x0, type: 8, attr: ['C0']}, |
| 263 | + {bits: 3, name: 'rd`', type: 2, attr: ['dest, dest[0]=0']}, |
| 264 | + {bits: 2, name: 'imm', type: 3, attr: ['offset[7:6]']}, |
| 265 | + {bits: 3, name: 'rs1`', type: 4, attr: ['base']}, |
| 266 | + {bits: 3, name: 'imm', type: 3, attr: ['offset[5:3]']}, |
| 267 | + {bits: 3, name: 0x3, type: 8, attr: ['C.LD']}, |
| 268 | +], config: {bits: 16}} |
| 269 | +.... |
| 270 | + |
| 271 | +Description:: |
| 272 | +Loads a 64-bit value into registers `rd'` and `rd'+1`. |
| 273 | +It computes an effective address by adding the zero-extended offset, scaled by 8, to the base address in register rs1'. |
| 274 | + |
| 275 | +Included in: <<zclsd>> |
| 276 | + |
| 277 | +<<< |
| 278 | + |
| 279 | +[#insns-csd,reftext="Store doubleword from register pair, 16-bit encoding"] |
| 280 | +==== c.sd |
| 281 | + |
| 282 | +Synopsis:: |
| 283 | +Store doubleword from even/odd register pair, 16-bit encoding |
| 284 | + |
| 285 | +Mnemonic:: |
| 286 | +c.sd rs2', offset(rs1') |
| 287 | + |
| 288 | +Encoding (RV32):: |
| 289 | +[wavedrom, ,svg] |
| 290 | +.... |
| 291 | +{reg: [ |
| 292 | + {bits: 2, name: 0x0, type: 8, attr: ['C0']}, |
| 293 | + {bits: 3, name: 'rs2`', type: 4, attr: ['src, src[0]=0']}, |
| 294 | + {bits: 2, name: 'imm', type: 3, attr: ['offset[7:6]']}, |
| 295 | + {bits: 3, name: 'rs1`', type: 4, attr: ['base']}, |
| 296 | + {bits: 3, name: 'imm', type: 3, attr: ['offset[5:3]']}, |
| 297 | + {bits: 3, name: 0x7, type: 8, attr: ['C.SD']}, |
| 298 | +], config: {bits: 16}} |
| 299 | +.... |
| 300 | + |
| 301 | +Description:: |
| 302 | +Stores a 64-bit value from registers `rs2'` and `rs2'+1`. |
| 303 | +It computes an effective address by adding the zero-extended offset, scaled by 8, to the base address in register rs1'. |
| 304 | +It expands to `sd rs2', offset(rs1')`. |
| 305 | + |
| 306 | +Included in: <<zclsd>> |
0 commit comments