|
| 1 | +# yaml-language-server: $schema=../../../schemas/inst_schema.json |
| 2 | + |
| 3 | +$schema: "inst_schema.json#" |
| 4 | +kind: instruction |
| 5 | +name: cm.popretz |
| 6 | +long_name: Destroy function call stack frame, move zero to `a0` and return to `ra`. |
| 7 | +description: | |
| 8 | + Destroy stack frame: load `ra` and 0 to 12 saved registers from the stack frame, deallocate the stack frame, move zero to `a0`, return to `ra`. |
| 9 | + This instruction pops (loads) the registers in `reg_list` from stack memory, and then adjusts the stack pointer by `stack_adj`, move zero to `a0` and then return to `ra`. |
| 10 | +
|
| 11 | + Restrictions on stack_adj: |
| 12 | +
|
| 13 | + * it must be enough to store all of the listed registers |
| 14 | + * it must be a multiple of 16 (bytes): |
| 15 | + ** for RV32 the allowed values are: 16, 32, 48, 64, 80, 96, 112 |
| 16 | + ** for RV64 the allowed values are: 16, 32, 48, 64, 80, 96, 112, 128, 144, 160 |
| 17 | +definedBy: |
| 18 | + anyOf: |
| 19 | + - Zcmp |
| 20 | +assembly: reg_list, stack_adj |
| 21 | +encoding: |
| 22 | + match: 10111100------10 |
| 23 | + variables: |
| 24 | + - name: rlist |
| 25 | + location: 7-4 |
| 26 | + not: [0, 1, 2, 3] |
| 27 | + - name: spimm |
| 28 | + location: 3-2 |
| 29 | + left_shift: 4 |
| 30 | +access: |
| 31 | + s: always |
| 32 | + u: always |
| 33 | + vs: always |
| 34 | + vu: always |
| 35 | +operation(): | |
| 36 | + if (implemented?(ExtensionName::Zcmp) && (CSR[misa].C == 1'b0)) { |
| 37 | + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); |
| 38 | + } |
| 39 | +
|
| 40 | + XReg size = xlen(); |
| 41 | + XReg nreg = (rlist == 15) ? 13 : (rlist - 3); |
| 42 | + XReg stack_aligned_adj = (nreg * 4 + 15) & ~0xF; |
| 43 | + XReg virtual_address_sp = X[2]; |
| 44 | + XReg virtual_address_new_sp = virtual_address_sp + stack_aligned_adj + spimm; |
| 45 | + XReg virtual_address_base = virtual_address_new_sp - (nreg * size); |
| 46 | +
|
| 47 | + X[ 1] = read_memory_xlen(virtual_address_base + 0*size, $encoding); |
| 48 | + if (nreg > 1) { |
| 49 | + X[ 8] = read_memory_xlen(virtual_address_base + 1*size, $encoding); |
| 50 | + } |
| 51 | + if (nreg > 2) { |
| 52 | + X[ 9] = read_memory_xlen(virtual_address_base + 2*size, $encoding); |
| 53 | + } |
| 54 | + if (nreg > 3) { |
| 55 | + X[18] = read_memory_xlen(virtual_address_base + 3*size, $encoding); |
| 56 | + } |
| 57 | + if (nreg > 4) { |
| 58 | + X[19] = read_memory_xlen(virtual_address_base + 4*size, $encoding); |
| 59 | + } |
| 60 | + if (nreg > 5) { |
| 61 | + X[20] = read_memory_xlen(virtual_address_base + 5*size, $encoding); |
| 62 | + } |
| 63 | + if (nreg > 6) { |
| 64 | + X[21] = read_memory_xlen(virtual_address_base + 6*size, $encoding); |
| 65 | + } |
| 66 | + if (nreg > 7) { |
| 67 | + X[22] = read_memory_xlen(virtual_address_base + 7*size, $encoding); |
| 68 | + } |
| 69 | + if (nreg > 8) { |
| 70 | + X[23] = read_memory_xlen(virtual_address_base + 8*size, $encoding); |
| 71 | + } |
| 72 | + if (nreg > 9) { |
| 73 | + X[24] = read_memory_xlen(virtual_address_base + 9*size, $encoding); |
| 74 | + } |
| 75 | + if (nreg > 10) { |
| 76 | + X[25] = read_memory_xlen(virtual_address_base + 10*size, $encoding); |
| 77 | + } |
| 78 | + if (nreg > 11) { |
| 79 | + X[26] = read_memory_xlen(virtual_address_base + 11*size, $encoding); |
| 80 | + X[27] = read_memory_xlen(virtual_address_base + 12*size, $encoding); |
| 81 | + } |
| 82 | +
|
| 83 | + X[2] = virtual_address_new_sp; |
| 84 | + X[10] = 0; |
| 85 | + jump(X[1]); |
0 commit comments