|
| 1 | + ========================== |
| 2 | + KERNEL ABIS FOR METAG ARCH |
| 3 | + ========================== |
| 4 | + |
| 5 | +This document describes the Linux ABIs for the metag architecture, and has the |
| 6 | +following sections: |
| 7 | + |
| 8 | + (*) Outline of registers |
| 9 | + (*) Userland registers |
| 10 | + (*) Kernel registers |
| 11 | + (*) System call ABI |
| 12 | + (*) Calling conventions |
| 13 | + |
| 14 | + |
| 15 | +==================== |
| 16 | +OUTLINE OF REGISTERS |
| 17 | +==================== |
| 18 | + |
| 19 | +The main Meta core registers are arranged in units: |
| 20 | + |
| 21 | + UNIT Type DESCRIPTION GP EXT PRIV GLOBAL |
| 22 | + ======= ======= =============== ======= ======= ======= ======= |
| 23 | + CT Special Control unit |
| 24 | + D0 General Data unit 0 0-7 8-15 16-31 16-31 |
| 25 | + D1 General Data unit 1 0-7 8-15 16-31 16-31 |
| 26 | + A0 General Address unit 0 0-3 4-7 8-15 8-15 |
| 27 | + A1 General Address unit 1 0-3 4-7 8-15 8-15 |
| 28 | + PC Special PC unit 0 1 |
| 29 | + PORT Special Ports |
| 30 | + TR Special Trigger unit 0-7 |
| 31 | + TT Special Trace unit 0-5 |
| 32 | + FX General FP unit 0-15 |
| 33 | + |
| 34 | +GP registers form part of the main context. |
| 35 | + |
| 36 | +Extended context registers (EXT) may not be present on all hardware threads and |
| 37 | +can be context switched if support is enabled and the appropriate bits are set |
| 38 | +in e.g. the D0.8 register to indicate what extended state to preserve. |
| 39 | + |
| 40 | +Global registers are shared between threads and are privilege protected. |
| 41 | + |
| 42 | +See arch/metag/include/asm/metag_regs.h for definitions relating to core |
| 43 | +registers and the fields and bits they contain. See the TRMs for further details |
| 44 | +about special registers. |
| 45 | + |
| 46 | +Several special registers are preserved in the main context, these are the |
| 47 | +interesting ones: |
| 48 | + |
| 49 | + REG (ALIAS) PURPOSE |
| 50 | + ======================= =============================================== |
| 51 | + CT.1 (TXMODE) Processor mode bits (particularly for DSP) |
| 52 | + CT.2 (TXSTATUS) Condition flags and LSM_STEP (MGET/MSET step) |
| 53 | + CT.3 (TXRPT) Branch repeat counter |
| 54 | + PC.0 (PC) Program counter |
| 55 | + |
| 56 | +Some of the general registers have special purposes in the ABI and therefore |
| 57 | +have aliases: |
| 58 | + |
| 59 | + D0 REG (ALIAS) PURPOSE D1 REG (ALIAS) PURPOSE |
| 60 | + =============== =============== =============== ======================= |
| 61 | + D0.0 (D0Re0) 32bit result D1.0 (D1Re0) Top half of 64bit result |
| 62 | + D0.1 (D0Ar6) Argument 6 D1.1 (D1Ar5) Argument 5 |
| 63 | + D0.2 (D0Ar4) Argument 4 D1.2 (D1Ar3) Argument 3 |
| 64 | + D0.3 (D0Ar2) Argument 2 D1.3 (D1Ar1) Argument 1 |
| 65 | + D0.4 (D0FrT) Frame temp D1.4 (D1RtP) Return pointer |
| 66 | + D0.5 Call preserved D1.5 Call preserved |
| 67 | + D0.6 Call preserved D1.6 Call preserved |
| 68 | + D0.7 Call preserved D1.7 Call preserved |
| 69 | + |
| 70 | + A0 REG (ALIAS) PURPOSE A1 REG (ALIAS) PURPOSE |
| 71 | + =============== =============== =============== ======================= |
| 72 | + A0.0 (A0StP) Stack pointer A1.0 (A1GbP) Global base pointer |
| 73 | + A0.1 (A0FrP) Frame pointer A1.1 (A1LbP) Local base pointer |
| 74 | + A0.2 A1.2 |
| 75 | + A0.3 A1.3 |
| 76 | + |
| 77 | + |
| 78 | +================== |
| 79 | +USERLAND REGISTERS |
| 80 | +================== |
| 81 | + |
| 82 | +All the general purpose D0, D1, A0, A1 registers are preserved when entering the |
| 83 | +kernel (including asynchronous events such as interrupts and timer ticks) except |
| 84 | +the following which have special purposes in the ABI: |
| 85 | + |
| 86 | + REGISTERS WHEN STATUS PURPOSE |
| 87 | + =============== ======= =============== =============================== |
| 88 | + D0.8 DSP Preserved ECH, determines what extended |
| 89 | + DSP state to preserve. |
| 90 | + A0.0 (A0StP) ALWAYS Preserved Stack >= A0StP may be clobbered |
| 91 | + at any time by the creation of a |
| 92 | + signal frame. |
| 93 | + A1.0 (A1GbP) SMP Clobbered Used as temporary for loading |
| 94 | + kernel stack pointer and saving |
| 95 | + core context. |
| 96 | + A0.15 !SMP Protected Stores kernel stack pointer. |
| 97 | + A1.15 ALWAYS Protected Stores kernel base pointer. |
| 98 | + |
| 99 | +On UP A0.15 is used to store the kernel stack pointer for storing the userland |
| 100 | +context. A0.15 is global between hardware threads though which means it cannot |
| 101 | +be used on SMP for this purpose. Since no protected local registers are |
| 102 | +available A1GbP is reserved for use as a temporary to allow a percpu stack |
| 103 | +pointer to be loaded for storing the rest of the context. |
| 104 | + |
| 105 | + |
| 106 | +================ |
| 107 | +KERNEL REGISTERS |
| 108 | +================ |
| 109 | + |
| 110 | +When in the kernel the following registers have special purposes in the ABI: |
| 111 | + |
| 112 | + REGISTERS WHEN STATUS PURPOSE |
| 113 | + =============== ======= =============== =============================== |
| 114 | + A0.0 (A0StP) ALWAYS Preserved Stack >= A0StP may be clobbered |
| 115 | + at any time by the creation of |
| 116 | + an irq signal frame. |
| 117 | + A1.0 (A1GbP) ALWAYS Preserved Reserved (kernel base pointer). |
| 118 | + |
| 119 | + |
| 120 | +=============== |
| 121 | +SYSTEM CALL ABI |
| 122 | +=============== |
| 123 | + |
| 124 | +When a system call is made, the following registers are effective: |
| 125 | + |
| 126 | + REGISTERS CALL RETURN |
| 127 | + =============== ======================= =============================== |
| 128 | + D0.0 (D0Re0) Return value (or -errno) |
| 129 | + D1.0 (D1Re0) System call number Clobbered |
| 130 | + D0.1 (D0Ar6) Syscall arg #6 Preserved |
| 131 | + D1.1 (D1Ar5) Syscall arg #5 Preserved |
| 132 | + D0.2 (D0Ar4) Syscall arg #4 Preserved |
| 133 | + D1.2 (D1Ar3) Syscall arg #3 Preserved |
| 134 | + D0.3 (D0Ar2) Syscall arg #2 Preserved |
| 135 | + D1.3 (D1Ar1) Syscall arg #1 Preserved |
| 136 | + |
| 137 | +Due to the limited number of argument registers and some system calls with badly |
| 138 | +aligned 64-bit arguments, 64-bit values are always packed in consecutive |
| 139 | +arguments, even if this is contrary to the normal calling conventions (where the |
| 140 | +two halves would go in a matching pair of data registers). |
| 141 | + |
| 142 | +For example fadvise64_64 usually has the signature: |
| 143 | + |
| 144 | + long sys_fadvise64_64(i32 fd, i64 offs, i64 len, i32 advice); |
| 145 | + |
| 146 | +But for metag fadvise64_64 is wrapped so that the 64-bit arguments are packed: |
| 147 | + |
| 148 | + long sys_fadvise64_64_metag(i32 fd, i32 offs_lo, |
| 149 | + i32 offs_hi, i32 len_lo, |
| 150 | + i32 len_hi, i32 advice) |
| 151 | + |
| 152 | +So the arguments are packed in the registers like this: |
| 153 | + |
| 154 | + D0 REG (ALIAS) VALUE D1 REG (ALIAS) VALUE |
| 155 | + =============== =============== =============== ======================= |
| 156 | + D0.1 (D0Ar6) advice D1.1 (D1Ar5) hi(len) |
| 157 | + D0.2 (D0Ar4) lo(len) D1.2 (D1Ar3) hi(offs) |
| 158 | + D0.3 (D0Ar2) lo(offs) D1.3 (D1Ar1) fd |
| 159 | + |
| 160 | + |
| 161 | +=================== |
| 162 | +CALLING CONVENTIONS |
| 163 | +=================== |
| 164 | + |
| 165 | +These calling conventions apply to both user and kernel code. The stack grows |
| 166 | +from low addresses to high addresses in the metag ABI. The stack pointer (A0StP) |
| 167 | +should always point to the next free address on the stack and should at all |
| 168 | +times be 64-bit aligned. The following registers are effective at the point of a |
| 169 | +call: |
| 170 | + |
| 171 | + REGISTERS CALL RETURN |
| 172 | + =============== ======================= =============================== |
| 173 | + D0.0 (D0Re0) 32bit return value |
| 174 | + D1.0 (D1Re0) Upper half of 64bit return value |
| 175 | + D0.1 (D0Ar6) 32bit argument #6 Clobbered |
| 176 | + D1.1 (D1Ar5) 32bit argument #5 Clobbered |
| 177 | + D0.2 (D0Ar4) 32bit argument #4 Clobbered |
| 178 | + D1.2 (D1Ar3) 32bit argument #3 Clobbered |
| 179 | + D0.3 (D0Ar2) 32bit argument #2 Clobbered |
| 180 | + D1.3 (D1Ar1) 32bit argument #1 Clobbered |
| 181 | + D0.4 (D0FrT) Clobbered |
| 182 | + D1.4 (D1RtP) Return pointer Clobbered |
| 183 | + D{0-1}.{5-7} Preserved |
| 184 | + A0.0 (A0StP) Stack pointer Preserved |
| 185 | + A1.0 (A0GbP) Preserved |
| 186 | + A0.1 (A0FrP) Frame pointer Preserved |
| 187 | + A1.1 (A0LbP) Preserved |
| 188 | + A{0-1},{2-3} Clobbered |
| 189 | + |
| 190 | +64-bit arguments are placed in matching pairs of registers (i.e. the same |
| 191 | +register number in both D0 and D1 units), with the least significant half in D0 |
| 192 | +and the most significant half in D1, leaving a gap where necessary. Futher |
| 193 | +arguments are stored on the stack in reverse order (earlier arguments at higher |
| 194 | +addresses): |
| 195 | + |
| 196 | + ADDRESS 0 1 2 3 4 5 6 7 |
| 197 | + =============== ===== ===== ===== ===== ===== ===== ===== ===== |
| 198 | + A0StP --> |
| 199 | + A0StP-0x08 32bit argument #8 32bit argument #7 |
| 200 | + A0StP-0x10 32bit argument #10 32bit argument #9 |
| 201 | + |
| 202 | +Function prologues tend to look a bit like this: |
| 203 | + |
| 204 | + /* If frame pointer in use, move it to frame temp register so it can be |
| 205 | + easily pushed onto stack */ |
| 206 | + MOV D0FrT,A0FrP |
| 207 | + |
| 208 | + /* If frame pointer in use, set it to stack pointer */ |
| 209 | + ADD A0FrP,A0StP,#0 |
| 210 | + |
| 211 | + /* Preserve D0FrT, D1RtP, D{0-1}.{5-7} on stack, incrementing A0StP */ |
| 212 | + MSETL [A0StP++],D0FrT,D0.5,D0.6,D0.7 |
| 213 | + |
| 214 | + /* Allocate some stack space for local variables */ |
| 215 | + ADD A0StP,A0StP,#0x10 |
| 216 | + |
| 217 | +At this point the stack would look like this: |
| 218 | + |
| 219 | + ADDRESS 0 1 2 3 4 5 6 7 |
| 220 | + =============== ===== ===== ===== ===== ===== ===== ===== ===== |
| 221 | + A0StP --> |
| 222 | + A0StP-0x08 |
| 223 | + A0StP-0x10 |
| 224 | + A0StP-0x18 Old D0.7 Old D1.7 |
| 225 | + A0StP-0x20 Old D0.6 Old D1.6 |
| 226 | + A0StP-0x28 Old D0.5 Old D1.5 |
| 227 | + A0FrP --> Old A0FrP (frame ptr) Old D1RtP (return ptr) |
| 228 | + A0FrP-0x08 32bit argument #8 32bit argument #7 |
| 229 | + A0FrP-0x10 32bit argument #10 32bit argument #9 |
| 230 | + |
| 231 | +Function epilogues tend to differ depending on the use of a frame pointer. An |
| 232 | +example of a frame pointer epilogue: |
| 233 | + |
| 234 | + /* Restore D0FrT, D1RtP, D{0-1}.{5-7} from stack, incrementing A0FrP */ |
| 235 | + MGETL D0FrT,D0.5,D0.6,D0.7,[A0FrP++] |
| 236 | + /* Restore stack pointer to where frame pointer was before increment */ |
| 237 | + SUB A0StP,A0FrP,#0x20 |
| 238 | + /* Restore frame pointer from frame temp */ |
| 239 | + MOV A0FrP,D0FrT |
| 240 | + /* Return to caller via restored return pointer */ |
| 241 | + MOV PC,D1RtP |
| 242 | + |
| 243 | +If the function hasn't touched the frame pointer, MGETL cannot be safely used |
| 244 | +with A0StP as it always increments and that would expose the stack to clobbering |
| 245 | +by interrupts (kernel) or signals (user). Therefore it's common to see the MGETL |
| 246 | +split into separate GETL instructions: |
| 247 | + |
| 248 | + /* Restore D0FrT, D1RtP, D{0-1}.{5-7} from stack */ |
| 249 | + GETL D0FrT,D1RtP,[A0StP+#-0x30] |
| 250 | + GETL D0.5,D1.5,[A0StP+#-0x28] |
| 251 | + GETL D0.6,D1.6,[A0StP+#-0x20] |
| 252 | + GETL D0.7,D1.7,[A0StP+#-0x18] |
| 253 | + /* Restore stack pointer */ |
| 254 | + SUB A0StP,A0StP,#0x30 |
| 255 | + /* Return to caller via restored return pointer */ |
| 256 | + MOV PC,D1RtP |
0 commit comments