bigbiff | 673c7ae | 2020-12-02 19:44:56 -0500 | [diff] [blame] | 1 | /* libs/pixelflinger/codeflinger/ARMAssemblerInterface.h |
| 2 | ** |
| 3 | ** Copyright 2006, The Android Open Source Project |
| 4 | ** |
| 5 | ** Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | ** you may not use this file except in compliance with the License. |
| 7 | ** You may obtain a copy of the License at |
| 8 | ** |
| 9 | ** http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | ** |
| 11 | ** Unless required by applicable law or agreed to in writing, software |
| 12 | ** distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | ** See the License for the specific language governing permissions and |
| 15 | ** limitations under the License. |
| 16 | */ |
| 17 | |
| 18 | |
| 19 | #ifndef ANDROID_ARMASSEMBLER_INTERFACE_H |
| 20 | #define ANDROID_ARMASSEMBLER_INTERFACE_H |
| 21 | |
| 22 | #include <stdint.h> |
| 23 | #include <sys/types.h> |
| 24 | |
| 25 | namespace android { |
| 26 | |
| 27 | // ---------------------------------------------------------------------------- |
| 28 | |
| 29 | class ARMAssemblerInterface |
| 30 | { |
| 31 | public: |
| 32 | virtual ~ARMAssemblerInterface(); |
| 33 | |
| 34 | enum { |
| 35 | EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV, |
| 36 | HS = CS, |
| 37 | LO = CC |
| 38 | }; |
| 39 | enum { |
| 40 | S = 1 |
| 41 | }; |
| 42 | enum { |
| 43 | LSL, LSR, ASR, ROR |
| 44 | }; |
| 45 | enum { |
| 46 | ED, FD, EA, FA, |
| 47 | IB, IA, DB, DA |
| 48 | }; |
| 49 | enum { |
| 50 | R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, |
| 51 | SP = R13, |
| 52 | LR = R14, |
| 53 | PC = R15 |
| 54 | }; |
| 55 | enum { |
| 56 | #define LIST(rr) L##rr=1<<rr |
| 57 | LIST(R0), LIST(R1), LIST(R2), LIST(R3), LIST(R4), LIST(R5), LIST(R6), |
| 58 | LIST(R7), LIST(R8), LIST(R9), LIST(R10), LIST(R11), LIST(R12), |
| 59 | LIST(R13), LIST(R14), LIST(R15), |
| 60 | LIST(SP), LIST(LR), LIST(PC), |
| 61 | #undef LIST |
| 62 | LSAVED = LR4|LR5|LR6|LR7|LR8|LR9|LR10|LR11 | LLR |
| 63 | }; |
| 64 | |
| 65 | enum { |
| 66 | CODEGEN_ARCH_ARM = 1, CODEGEN_ARCH_MIPS, CODEGEN_ARCH_ARM64, CODEGEN_ARCH_MIPS64 |
| 67 | }; |
| 68 | |
| 69 | // ----------------------------------------------------------------------- |
| 70 | // shifters and addressing modes |
| 71 | // ----------------------------------------------------------------------- |
| 72 | |
| 73 | // these static versions are used for initializers on LDxx/STxx below |
| 74 | static uint32_t __immed12_pre(int32_t immed12, int W=0); |
| 75 | static uint32_t __immed8_pre(int32_t immed12, int W=0); |
| 76 | |
| 77 | virtual bool isValidImmediate(uint32_t immed) = 0; |
| 78 | virtual int buildImmediate(uint32_t i, uint32_t& rot, uint32_t& imm) = 0; |
| 79 | |
| 80 | virtual uint32_t imm(uint32_t immediate) = 0; |
| 81 | virtual uint32_t reg_imm(int Rm, int type, uint32_t shift) = 0; |
| 82 | virtual uint32_t reg_rrx(int Rm) = 0; |
| 83 | virtual uint32_t reg_reg(int Rm, int type, int Rs) = 0; |
| 84 | |
| 85 | // addressing modes... |
| 86 | // LDR(B)/STR(B)/PLD |
| 87 | // (immediate and Rm can be negative, which indicates U=0) |
| 88 | virtual uint32_t immed12_pre(int32_t immed12, int W=0) = 0; |
| 89 | virtual uint32_t immed12_post(int32_t immed12) = 0; |
| 90 | virtual uint32_t reg_scale_pre(int Rm, int type=0, uint32_t shift=0, int W=0) = 0; |
| 91 | virtual uint32_t reg_scale_post(int Rm, int type=0, uint32_t shift=0) = 0; |
| 92 | |
| 93 | // LDRH/LDRSB/LDRSH/STRH |
| 94 | // (immediate and Rm can be negative, which indicates U=0) |
| 95 | virtual uint32_t immed8_pre(int32_t immed8, int W=0) = 0; |
| 96 | virtual uint32_t immed8_post(int32_t immed8) = 0; |
| 97 | virtual uint32_t reg_pre(int Rm, int W=0) = 0; |
| 98 | virtual uint32_t reg_post(int Rm) = 0; |
| 99 | |
| 100 | // ----------------------------------------------------------------------- |
| 101 | // basic instructions & code generation |
| 102 | // ----------------------------------------------------------------------- |
| 103 | |
| 104 | // generate the code |
| 105 | virtual void reset() = 0; |
| 106 | virtual int generate(const char* name) = 0; |
| 107 | virtual void disassemble(const char* name) = 0; |
| 108 | virtual int getCodegenArch() = 0; |
| 109 | |
| 110 | // construct prolog and epilog |
| 111 | virtual void prolog() = 0; |
| 112 | virtual void epilog(uint32_t touched) = 0; |
| 113 | virtual void comment(const char* string) = 0; |
| 114 | |
| 115 | // data processing... |
| 116 | enum { |
| 117 | opAND, opEOR, opSUB, opRSB, opADD, opADC, opSBC, opRSC, |
| 118 | opTST, opTEQ, opCMP, opCMN, opORR, opMOV, opBIC, opMVN, |
| 119 | opADD64, opSUB64 |
| 120 | }; |
| 121 | |
| 122 | virtual void |
| 123 | dataProcessing( int opcode, int cc, int s, |
| 124 | int Rd, int Rn, |
| 125 | uint32_t Op2) = 0; |
| 126 | |
| 127 | // multiply... |
| 128 | virtual void MLA(int cc, int s, |
| 129 | int Rd, int Rm, int Rs, int Rn) = 0; |
| 130 | virtual void MUL(int cc, int s, |
| 131 | int Rd, int Rm, int Rs) = 0; |
| 132 | virtual void UMULL(int cc, int s, |
| 133 | int RdLo, int RdHi, int Rm, int Rs) = 0; |
| 134 | virtual void UMUAL(int cc, int s, |
| 135 | int RdLo, int RdHi, int Rm, int Rs) = 0; |
| 136 | virtual void SMULL(int cc, int s, |
| 137 | int RdLo, int RdHi, int Rm, int Rs) = 0; |
| 138 | virtual void SMUAL(int cc, int s, |
| 139 | int RdLo, int RdHi, int Rm, int Rs) = 0; |
| 140 | |
| 141 | // branches... |
| 142 | virtual void B(int cc, uint32_t* pc) = 0; |
| 143 | virtual void BL(int cc, uint32_t* pc) = 0; |
| 144 | virtual void BX(int cc, int Rn) = 0; |
| 145 | |
| 146 | virtual void label(const char* theLabel) = 0; |
| 147 | virtual void B(int cc, const char* label) = 0; |
| 148 | virtual void BL(int cc, const char* label) = 0; |
| 149 | |
| 150 | // valid only after generate() has been called |
| 151 | virtual uint32_t* pcForLabel(const char* label) = 0; |
| 152 | |
| 153 | // data transfer... |
| 154 | virtual void LDR (int cc, int Rd, |
| 155 | int Rn, uint32_t offset = __immed12_pre(0)) = 0; |
| 156 | virtual void LDRB(int cc, int Rd, |
| 157 | int Rn, uint32_t offset = __immed12_pre(0)) = 0; |
| 158 | virtual void STR (int cc, int Rd, |
| 159 | int Rn, uint32_t offset = __immed12_pre(0)) = 0; |
| 160 | virtual void STRB(int cc, int Rd, |
| 161 | int Rn, uint32_t offset = __immed12_pre(0)) = 0; |
| 162 | |
| 163 | virtual void LDRH (int cc, int Rd, |
| 164 | int Rn, uint32_t offset = __immed8_pre(0)) = 0; |
| 165 | virtual void LDRSB(int cc, int Rd, |
| 166 | int Rn, uint32_t offset = __immed8_pre(0)) = 0; |
| 167 | virtual void LDRSH(int cc, int Rd, |
| 168 | int Rn, uint32_t offset = __immed8_pre(0)) = 0; |
| 169 | virtual void STRH (int cc, int Rd, |
| 170 | int Rn, uint32_t offset = __immed8_pre(0)) = 0; |
| 171 | |
| 172 | // block data transfer... |
| 173 | virtual void LDM(int cc, int dir, |
| 174 | int Rn, int W, uint32_t reg_list) = 0; |
| 175 | virtual void STM(int cc, int dir, |
| 176 | int Rn, int W, uint32_t reg_list) = 0; |
| 177 | |
| 178 | // special... |
| 179 | virtual void SWP(int cc, int Rn, int Rd, int Rm) = 0; |
| 180 | virtual void SWPB(int cc, int Rn, int Rd, int Rm) = 0; |
| 181 | virtual void SWI(int cc, uint32_t comment) = 0; |
| 182 | |
| 183 | // DSP instructions... |
| 184 | enum { |
| 185 | // B=0, T=1 |
| 186 | // yx |
| 187 | xyBB = 0, // 0000, |
| 188 | xyTB = 2, // 0010, |
| 189 | xyBT = 4, // 0100, |
| 190 | xyTT = 6, // 0110, |
| 191 | yB = 0, // 0000, |
| 192 | yT = 4, // 0100 |
| 193 | }; |
| 194 | |
| 195 | virtual void PLD(int Rn, uint32_t offset) = 0; |
| 196 | |
| 197 | virtual void CLZ(int cc, int Rd, int Rm) = 0; |
| 198 | |
| 199 | virtual void QADD(int cc, int Rd, int Rm, int Rn) = 0; |
| 200 | virtual void QDADD(int cc, int Rd, int Rm, int Rn) = 0; |
| 201 | virtual void QSUB(int cc, int Rd, int Rm, int Rn) = 0; |
| 202 | virtual void QDSUB(int cc, int Rd, int Rm, int Rn) = 0; |
| 203 | |
| 204 | virtual void SMUL(int cc, int xy, |
| 205 | int Rd, int Rm, int Rs) = 0; |
| 206 | virtual void SMULW(int cc, int y, |
| 207 | int Rd, int Rm, int Rs) = 0; |
| 208 | virtual void SMLA(int cc, int xy, |
| 209 | int Rd, int Rm, int Rs, int Rn) = 0; |
| 210 | virtual void SMLAL(int cc, int xy, |
| 211 | int RdHi, int RdLo, int Rs, int Rm) = 0; |
| 212 | virtual void SMLAW(int cc, int y, |
| 213 | int Rd, int Rm, int Rs, int Rn) = 0; |
| 214 | |
| 215 | // byte/half word extract... |
| 216 | virtual void UXTB16(int cc, int Rd, int Rm, int rotate) = 0; |
| 217 | |
| 218 | // bit manipulation... |
| 219 | virtual void UBFX(int cc, int Rd, int Rn, int lsb, int width) = 0; |
| 220 | |
| 221 | // ----------------------------------------------------------------------- |
| 222 | // convenience... |
| 223 | // ----------------------------------------------------------------------- |
| 224 | inline void |
| 225 | ADC(int cc, int s, int Rd, int Rn, uint32_t Op2) { |
| 226 | dataProcessing(opADC, cc, s, Rd, Rn, Op2); |
| 227 | } |
| 228 | inline void |
| 229 | ADD(int cc, int s, int Rd, int Rn, uint32_t Op2) { |
| 230 | dataProcessing(opADD, cc, s, Rd, Rn, Op2); |
| 231 | } |
| 232 | inline void |
| 233 | AND(int cc, int s, int Rd, int Rn, uint32_t Op2) { |
| 234 | dataProcessing(opAND, cc, s, Rd, Rn, Op2); |
| 235 | } |
| 236 | inline void |
| 237 | BIC(int cc, int s, int Rd, int Rn, uint32_t Op2) { |
| 238 | dataProcessing(opBIC, cc, s, Rd, Rn, Op2); |
| 239 | } |
| 240 | inline void |
| 241 | EOR(int cc, int s, int Rd, int Rn, uint32_t Op2) { |
| 242 | dataProcessing(opEOR, cc, s, Rd, Rn, Op2); |
| 243 | } |
| 244 | inline void |
| 245 | MOV(int cc, int s, int Rd, uint32_t Op2) { |
| 246 | dataProcessing(opMOV, cc, s, Rd, 0, Op2); |
| 247 | } |
| 248 | inline void |
| 249 | MVN(int cc, int s, int Rd, uint32_t Op2) { |
| 250 | dataProcessing(opMVN, cc, s, Rd, 0, Op2); |
| 251 | } |
| 252 | inline void |
| 253 | ORR(int cc, int s, int Rd, int Rn, uint32_t Op2) { |
| 254 | dataProcessing(opORR, cc, s, Rd, Rn, Op2); |
| 255 | } |
| 256 | inline void |
| 257 | RSB(int cc, int s, int Rd, int Rn, uint32_t Op2) { |
| 258 | dataProcessing(opRSB, cc, s, Rd, Rn, Op2); |
| 259 | } |
| 260 | inline void |
| 261 | RSC(int cc, int s, int Rd, int Rn, uint32_t Op2) { |
| 262 | dataProcessing(opRSC, cc, s, Rd, Rn, Op2); |
| 263 | } |
| 264 | inline void |
| 265 | SBC(int cc, int s, int Rd, int Rn, uint32_t Op2) { |
| 266 | dataProcessing(opSBC, cc, s, Rd, Rn, Op2); |
| 267 | } |
| 268 | inline void |
| 269 | SUB(int cc, int s, int Rd, int Rn, uint32_t Op2) { |
| 270 | dataProcessing(opSUB, cc, s, Rd, Rn, Op2); |
| 271 | } |
| 272 | inline void |
| 273 | TEQ(int cc, int Rn, uint32_t Op2) { |
| 274 | dataProcessing(opTEQ, cc, 1, 0, Rn, Op2); |
| 275 | } |
| 276 | inline void |
| 277 | TST(int cc, int Rn, uint32_t Op2) { |
| 278 | dataProcessing(opTST, cc, 1, 0, Rn, Op2); |
| 279 | } |
| 280 | inline void |
| 281 | CMP(int cc, int Rn, uint32_t Op2) { |
| 282 | dataProcessing(opCMP, cc, 1, 0, Rn, Op2); |
| 283 | } |
| 284 | inline void |
| 285 | CMN(int cc, int Rn, uint32_t Op2) { |
| 286 | dataProcessing(opCMN, cc, 1, 0, Rn, Op2); |
| 287 | } |
| 288 | |
| 289 | inline void SMULBB(int cc, int Rd, int Rm, int Rs) { |
| 290 | SMUL(cc, xyBB, Rd, Rm, Rs); } |
| 291 | inline void SMULTB(int cc, int Rd, int Rm, int Rs) { |
| 292 | SMUL(cc, xyTB, Rd, Rm, Rs); } |
| 293 | inline void SMULBT(int cc, int Rd, int Rm, int Rs) { |
| 294 | SMUL(cc, xyBT, Rd, Rm, Rs); } |
| 295 | inline void SMULTT(int cc, int Rd, int Rm, int Rs) { |
| 296 | SMUL(cc, xyTT, Rd, Rm, Rs); } |
| 297 | |
| 298 | inline void SMULWB(int cc, int Rd, int Rm, int Rs) { |
| 299 | SMULW(cc, yB, Rd, Rm, Rs); } |
| 300 | inline void SMULWT(int cc, int Rd, int Rm, int Rs) { |
| 301 | SMULW(cc, yT, Rd, Rm, Rs); } |
| 302 | |
| 303 | inline void |
| 304 | SMLABB(int cc, int Rd, int Rm, int Rs, int Rn) { |
| 305 | SMLA(cc, xyBB, Rd, Rm, Rs, Rn); } |
| 306 | inline void |
| 307 | SMLATB(int cc, int Rd, int Rm, int Rs, int Rn) { |
| 308 | SMLA(cc, xyTB, Rd, Rm, Rs, Rn); } |
| 309 | inline void |
| 310 | SMLABT(int cc, int Rd, int Rm, int Rs, int Rn) { |
| 311 | SMLA(cc, xyBT, Rd, Rm, Rs, Rn); } |
| 312 | inline void |
| 313 | SMLATT(int cc, int Rd, int Rm, int Rs, int Rn) { |
| 314 | SMLA(cc, xyTT, Rd, Rm, Rs, Rn); } |
| 315 | |
| 316 | inline void |
| 317 | SMLALBB(int cc, int RdHi, int RdLo, int Rs, int Rm) { |
| 318 | SMLAL(cc, xyBB, RdHi, RdLo, Rs, Rm); } |
| 319 | inline void |
| 320 | SMLALTB(int cc, int RdHi, int RdLo, int Rs, int Rm) { |
| 321 | SMLAL(cc, xyTB, RdHi, RdLo, Rs, Rm); } |
| 322 | inline void |
| 323 | SMLALBT(int cc, int RdHi, int RdLo, int Rs, int Rm) { |
| 324 | SMLAL(cc, xyBT, RdHi, RdLo, Rs, Rm); } |
| 325 | inline void |
| 326 | SMLALTT(int cc, int RdHi, int RdLo, int Rs, int Rm) { |
| 327 | SMLAL(cc, xyTT, RdHi, RdLo, Rs, Rm); } |
| 328 | |
| 329 | inline void |
| 330 | SMLAWB(int cc, int Rd, int Rm, int Rs, int Rn) { |
| 331 | SMLAW(cc, yB, Rd, Rm, Rs, Rn); } |
| 332 | inline void |
| 333 | SMLAWT(int cc, int Rd, int Rm, int Rs, int Rn) { |
| 334 | SMLAW(cc, yT, Rd, Rm, Rs, Rn); } |
| 335 | |
| 336 | // Address loading/storing/manipulation |
| 337 | virtual void ADDR_LDR(int cc, int Rd, |
| 338 | int Rn, uint32_t offset = __immed12_pre(0)); |
| 339 | virtual void ADDR_STR (int cc, int Rd, |
| 340 | int Rn, uint32_t offset = __immed12_pre(0)); |
| 341 | virtual void ADDR_ADD(int cc, int s, int Rd, |
| 342 | int Rn, uint32_t Op2); |
| 343 | virtual void ADDR_SUB(int cc, int s, int Rd, |
| 344 | int Rn, uint32_t Op2); |
| 345 | }; |
| 346 | |
| 347 | }; // namespace android |
| 348 | |
| 349 | #endif //ANDROID_ARMASSEMBLER_INTERFACE_H |