Changeset 101248 in vbox for trunk/include
- Timestamp:
- Sep 24, 2023 2:48:56 AM (17 months ago)
- svn:sync-xref-src-repo-rev:
- 159231
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/armv8.h
r101246 r101248 2202 2202 /** @} */ 2203 2203 2204 2205 #if (!defined(VBOX_FOR_DTRACE_LIB) && defined(__cplusplus) && !defined(ARMV8_WITHOUT_MK_INSTR)) || defined(DOXYGEN_RUNNING) 2206 /** @def grp_rt_armv8_mkinstr Instruction Encoding Helpers 2207 * 2208 * A few inlined functions and macros for assiting in encoding common ARMv8 2209 * instructions. 2210 * 2211 * @{ */ 2212 2213 /** A64: Return instruction. */ 2214 #define ARMV8_A64_INSTR_RET UINT32_C(0xd65f03c0) 2215 2216 2217 typedef enum 2218 { 2219 /** Add @a iImm7*sizeof(reg) to @a iBaseReg after the store/load, 2220 * and update the register. */ 2221 kArm64InstrStLdPairType_kPostIndex = 1, 2222 /** Add @a iImm7*sizeof(reg) to @a iBaseReg before the store/load, 2223 * but don't update the register. */ 2224 kArm64InstrStLdPairType_kSigned = 2, 2225 /** Add @a iImm7*sizeof(reg) to @a iBaseReg before the store/load, 2226 * and update the register. */ 2227 kArm64InstrStLdPairType_kPreIndex = 3 2228 } ARM64INSTRSTLDPAIRTYPE; 2229 2230 /** 2231 * A64: Encodes either stp (store register pair) or ldp (load register pair). 2232 * 2233 * @returns The encoded instruction. 2234 * @param fLoad true for ldp, false of stp. 2235 * @param iOpc When @a fSimdFp is @c false: 2236 * - 0 for 32-bit GPRs (Wt). 2237 * - 1 for encoding stgp or ldpsw. 2238 * - 2 for 64-bit GRPs (Xt). 2239 * - 3 illegal. 2240 * When @a fSimdFp is @c true: 2241 * - 0 for 32-bit SIMD&FP registers (St). 2242 * - 1 for 64-bit SIMD&FP registers (Dt). 2243 * - 2 for 128-bit SIMD&FP regsiters (Qt). 2244 * @param enmType The instruction variant wrt addressing and updating of the 2245 * addressing register. 2246 * @param iReg1 The first register to store/load. 2247 * @param iReg2 The second register to store/load. 2248 * @param iBaseReg The base register to use when addressing. SP is allowed. 2249 * @param iImm7 Signed addressing immediate value scaled, range -64..63, 2250 * will be multiplied by the register size. 2251 * @param fSimdFp true for SIMD&FP registers, false for GPRs and 2252 * stgp/ldpsw instructions. 2253 */ 2254 DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrStLdPair(bool fLoad, uint32_t iOpc, ARM64INSTRSTLDPAIRTYPE enmType, 2255 uint32_t iReg1, uint32_t iReg2, uint32_t iBaseReg, int32_t iImm7 = 0, 2256 bool fSimdFp = false) 2257 { 2258 Assert(iOpc < 3); Assert(iReg1 <= 31); Assert(iReg2 <= 31); Assert(iBaseReg <= 31); Assert(iImm7 < 64 && iImm7 >= -64); 2259 return (iOpc << 30) 2260 | UINT32_C(0x28000000) 2261 | ((uint32_t)fSimdFp << 26) /* VR bit, see "Top-level encodings for A64" */ 2262 | ((uint32_t)enmType << 23) 2263 | ((uint32_t)fLoad << 22) 2264 | (((uint32_t)iImm7 & UINT32_C(0x7f)) << 15) 2265 | (iReg2 << 10) 2266 | (iBaseReg << 5) 2267 | iReg1; 2268 } 2269 2270 2271 typedef enum 2272 { 2273 kArmv8A64InstrShift_kLsl = 0, 2274 kArmv8A64InstrShift_kLsr, 2275 kArmv8A64InstrShift_kAsr, 2276 kArmv8A64InstrShift_kRor 2277 } ARMV8A64INSTRSHIFT; 2278 2279 2280 /** 2281 * A64: Encodes a logical instruction with a shifted 2nd register operand. 2282 * 2283 * @returns The encoded instruction. 2284 * @param u2Opc The logical operation to perform. 2285 * @param fNot Whether to complement the 2nd operand. 2286 * @param iRegResult The output register. 2287 * @param iReg1 The 1st register operand. 2288 * @param iReg2Shifted The 2nd register operand, to which the optional 2289 * shifting is applied. 2290 * @param f64Bit true for 64-bit GPRs (default), @c false for 32-bit 2291 * GPRs. 2292 * @param offShift6 The shift amount (default: none). 2293 * @param enmShift The shift operation (default: LSL). 2294 */ 2295 DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrLogicalShiftedReg(uint32_t u2Opc, bool fNot, 2296 uint32_t iRegResult, uint32_t iReg1, uint32_t iReg2Shifted, 2297 bool f64Bit, uint32_t offShift6, ARMV8A64INSTRSHIFT enmShift) 2298 { 2299 Assert(u2Opc < 4); Assert(offShift6 < (f64Bit ? 64 : 32)); 2300 Assert(iRegResult < 32); Assert(iReg1 < 32); Assert(iReg2Shifted < 32); 2301 return ((uint32_t)f64Bit << 31) 2302 | (u2Opc << 29) 2303 | UINT32_C(0x0a000000) 2304 | ((uint32_t)enmShift << 22) 2305 | ((uint32_t)fNot << 21) 2306 | (iReg2Shifted << 16) 2307 | (offShift6 << 10) 2308 | (iReg1 << 5) 2309 | iRegResult; 2310 } 2311 2312 2313 /** A64: Encodes an AND instruction. 2314 * @see Armv8A64MkInstrLogicalShiftedReg for parameter details. */ 2315 DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrAnd(uint32_t iRegResult, uint32_t iReg1, uint32_t iReg2Shifted, bool f64Bit = true, 2316 uint32_t offShift6 = 0, ARMV8A64INSTRSHIFT enmShift = kArmv8A64InstrShift_kLsl) 2317 { 2318 return Armv8A64MkInstrLogicalShiftedReg(0, false /*fNot*/, iRegResult, iReg1, iReg2Shifted, f64Bit, offShift6, enmShift); 2319 } 2320 2321 2322 /** A64: Encodes an BIC instruction. 2323 * @see Armv8A64MkInstrLogicalShiftedReg for parameter details. */ 2324 DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrBic(uint32_t iRegResult, uint32_t iReg1, uint32_t iReg2Shifted, bool f64Bit = true, 2325 uint32_t offShift6 = 0, ARMV8A64INSTRSHIFT enmShift = kArmv8A64InstrShift_kLsl) 2326 { 2327 return Armv8A64MkInstrLogicalShiftedReg(0, true /*fNot*/, iRegResult, iReg1, iReg2Shifted, f64Bit, offShift6, enmShift); 2328 } 2329 2330 2331 /** A64: Encodes an ORR instruction. 2332 * @see Armv8A64MkInstrLogicalShiftedReg for parameter details. */ 2333 DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrOrr(uint32_t iRegResult, uint32_t iReg1, uint32_t iReg2Shifted, bool f64Bit = true, 2334 uint32_t offShift6 = 0, ARMV8A64INSTRSHIFT enmShift = kArmv8A64InstrShift_kLsl) 2335 { 2336 return Armv8A64MkInstrLogicalShiftedReg(1, false /*fNot*/, iRegResult, iReg1, iReg2Shifted, f64Bit, offShift6, enmShift); 2337 } 2338 2339 2340 /** A64: Encodes an ORN instruction. 2341 * @see Armv8A64MkInstrLogicalShiftedReg for parameter details. */ 2342 DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrOrn(uint32_t iRegResult, uint32_t iReg1, uint32_t iReg2Shifted, bool f64Bit = true, 2343 uint32_t offShift6 = 0, ARMV8A64INSTRSHIFT enmShift = kArmv8A64InstrShift_kLsl) 2344 { 2345 return Armv8A64MkInstrLogicalShiftedReg(1, true /*fNot*/, iRegResult, iReg1, iReg2Shifted, f64Bit, offShift6, enmShift); 2346 } 2347 2348 2349 /** A64: Encodes an EOR instruction. 2350 * @see Armv8A64MkInstrLogicalShiftedReg for parameter details. */ 2351 DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrEor(uint32_t iRegResult, uint32_t iReg1, uint32_t iReg2Shifted, bool f64Bit = true, 2352 uint32_t offShift6 = 0, ARMV8A64INSTRSHIFT enmShift = kArmv8A64InstrShift_kLsl) 2353 { 2354 return Armv8A64MkInstrLogicalShiftedReg(2, false /*fNot*/, iRegResult, iReg1, iReg2Shifted, f64Bit, offShift6, enmShift); 2355 } 2356 2357 2358 /** A64: Encodes an EON instruction. 2359 * @see Armv8A64MkInstrLogicalShiftedReg for parameter details. */ 2360 DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrEon(uint32_t iRegResult, uint32_t iReg1, uint32_t iReg2Shifted, bool f64Bit = true, 2361 uint32_t offShift6 = 0, ARMV8A64INSTRSHIFT enmShift = kArmv8A64InstrShift_kLsl) 2362 { 2363 return Armv8A64MkInstrLogicalShiftedReg(2, true /*fNot*/, iRegResult, iReg1, iReg2Shifted, f64Bit, offShift6, enmShift); 2364 } 2365 2366 2367 /** A64: Encodes an ANDS instruction. 2368 * @see Armv8A64MkInstrLogicalShiftedReg for parameter details. */ 2369 DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrAnds(uint32_t iRegResult, uint32_t iReg1, uint32_t iReg2Shifted, bool f64Bit = true, 2370 uint32_t offShift6 = 0, ARMV8A64INSTRSHIFT enmShift = kArmv8A64InstrShift_kLsl) 2371 { 2372 return Armv8A64MkInstrLogicalShiftedReg(3, false /*fNot*/, iRegResult, iReg1, iReg2Shifted, f64Bit, offShift6, enmShift); 2373 } 2374 2375 2376 /** A64: Encodes an BICS instruction. 2377 * @see Armv8A64MkInstrLogicalShiftedReg for parameter details. */ 2378 DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrBics(uint32_t iRegResult, uint32_t iReg1, uint32_t iReg2Shifted, bool f64Bit = true, 2379 uint32_t offShift6 = 0, ARMV8A64INSTRSHIFT enmShift = kArmv8A64InstrShift_kLsl) 2380 { 2381 return Armv8A64MkInstrLogicalShiftedReg(3, true /*fNot*/, iRegResult, iReg1, iReg2Shifted, f64Bit, offShift6, enmShift); 2382 } 2383 2384 2385 /** 2386 * A64: Encodes either add, adds, sub or subs. 2387 * 2388 * @returns The encoded instruction. 2389 * @param fSub true for sub and subs, false for add and 2390 * adds. 2391 * @param iRegResult The register to store the result in. 2392 * SP is valid when @a fSetFlags = false, 2393 * and ZR is valid otherwise. 2394 * @param iRegSrc The register containing the augend (@a fSub 2395 * = false) or minuend (@a fSub = true). SP is 2396 * a valid registers for all variations. 2397 * @param uImm12AddendSubtrahend The addended (@a fSub = false) or subtrahend 2398 * (@a fSub = true). 2399 * @param f64Bit true for 64-bit GRPs (default), false for 2400 * 32-bit GPRs. 2401 * @param fSetFlags Whether to set flags (adds / subs) or not 2402 * (add / sub - default). 2403 * @param fShift12 Whether to shift uImm12AddendSubtrahend 12 2404 * bits to the left, or not (default). 2405 */ 2406 DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrAddSub(bool fSub, uint32_t iRegResult, uint32_t iRegSrc, 2407 uint32_t uImm12AddendSubtrahend, bool f64Bit = true, bool fSetFlags = false, 2408 bool fShift12 = false) 2409 { 2410 Assert(uImm12AddendSubtrahend < 4096); Assert(iRegSrc < 32); Assert(iRegResult < 32); 2411 return ((uint32_t)f64Bit << 31) 2412 | ((uint32_t)fSub << 30) 2413 | ((uint32_t)fSetFlags << 29) 2414 | UINT32_C(0x11000000) 2415 | ((uint32_t)fShift12 << 22) 2416 | (uImm12AddendSubtrahend << 10) 2417 | (iRegSrc << 5) 2418 | iRegResult; 2419 } 2420 2421 2422 /** 2423 * A64: Encodes a B (unconditional branch w/ imm) instruction. 2424 * 2425 * @returns The encoded instruction. 2426 * @param iImm26 Signed number of instruction to jump (i.e. *4). 2427 */ 2428 DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrB(int32_t iImm26) 2429 { 2430 Assert(iImm26 >= -67108864 && iImm26 < 67108864); 2431 return UINT32_C(0x14000000) | ((uint32_t)iImm26 & UINT32_C(0x3ffffff)); 2432 } 2433 2434 2435 /** 2436 * A64: Encodes a BL (unconditional call w/ imm) instruction. 2437 * 2438 * @returns The encoded instruction. 2439 * @param iImm26 Signed number of instruction to jump (i.e. *4). 2440 */ 2441 DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrBl(int32_t iImm26) 2442 { 2443 return Armv8A64MkInstrB(iImm26) | RT_BIT_32(31); 2444 } 2445 2446 2447 /** 2448 * A64: Encodes a BR (unconditional branch w/ register) instruction. 2449 * 2450 * @returns The encoded instruction. 2451 * @param iReg The register containing the target address. 2452 */ 2453 DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrBr(uint32_t iReg) 2454 { 2455 Assert(iReg < 32); 2456 return UINT32_C(0xd61f0000) | (iReg << 5); 2457 } 2458 2459 2460 /** 2461 * A64: Encodes a BLR instruction. 2462 * 2463 * @returns The encoded instruction. 2464 * @param iReg The register containing the target address. 2465 */ 2466 DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrBlr(uint32_t iReg) 2467 { 2468 return Armv8A64MkInstrBr(iReg) | RT_BIT_32(21); 2469 } 2470 2471 2472 /** 2473 * A64: Encodes CBZ and CBNZ (conditional branch w/ immediate) instructions. 2474 * 2475 * @returns The encoded instruction. 2476 * @param fJmpIfNotZero false to jump if register is zero, true to jump if 2477 * its not zero. 2478 * @param iImm19 Signed number of instruction to jump (i.e. *4). 2479 * @param iReg The GPR to check for zero / non-zero value. 2480 * @param f64Bit true for 64-bit register, false for 32-bit. 2481 */ 2482 DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrCbzCbnz(bool fJmpIfNotZero, int32_t iImm19, uint32_t iReg, bool f64Bit = true) 2483 { 2484 Assert(iReg < 32); Assert(iImm19 >= -262144 && iImm19 < 262144); 2485 return ((uint32_t)f64Bit << 31) 2486 | UINT32_C(0x34000000) 2487 | ((uint32_t)fJmpIfNotZero << 24) 2488 | (((uint32_t)iImm19 & 0x7ffff) << 5) 2489 | iReg; 2490 } 2491 2492 2493 /** @} */ 2494 2495 #endif /* !dtrace && __cplusplus */ 2496 2204 2497 /** @} */ 2205 2498
Note:
See TracChangeset
for help on using the changeset viewer.