VirtualBox

Changeset 101304 in vbox for trunk


Ignore:
Timestamp:
Sep 29, 2023 1:02:02 AM (16 months ago)
Author:
vboxsync
Message:

VMM/IEM: Emit native code for pure defer-CImpl instructions. Tested on linux.amd64 only and this doesn't cover cases with zero parameters. bugref:10371

Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/armv8.h

    r101260 r101304  
    22432243 * @returns The encoded instruction.
    22442244 * @param   fLoad       true for ldp, false of stp.
    2245  * @param   iOpc        When @a fSimdFp is @c false:
     2245 * @param   u2Opc       When @a fSimdFp is @c false:
    22462246 *                          - 0 for 32-bit GPRs (Wt).
    22472247 *                          - 1 for encoding stgp or ldpsw.
     
    22622262 *                      stgp/ldpsw instructions.
    22632263 */
    2264 DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrStLdPair(bool fLoad, uint32_t iOpc, ARM64INSTRSTLDPAIRTYPE enmType,
     2264DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrStLdPair(bool fLoad, uint32_t u2Opc, ARM64INSTRSTLDPAIRTYPE enmType,
    22652265                                                    uint32_t iReg1, uint32_t iReg2, uint32_t iBaseReg, int32_t iImm7 = 0,
    22662266                                                    bool fSimdFp = false)
    22672267{
    2268     Assert(iOpc < 3); Assert(iReg1 <= 31); Assert(iReg2 <= 31); Assert(iBaseReg <= 31); Assert(iImm7 < 64 && iImm7 >= -64);
    2269     return (iOpc                               << 30)
    2270          | UINT32_C(0x28000000)
     2268    Assert(u2Opc < 3); Assert(iReg1 <= 31); Assert(iReg2 <= 31); Assert(iBaseReg <= 31); Assert(iImm7 < 64 && iImm7 >= -64);
     2269    return (u2Opc                              << 30)
     2270         | UINT32_C(0x28000000) /* 0b101000000000000000000000000000 */
    22712271         | ((uint32_t)fSimdFp                  << 26) /* VR bit, see "Top-level encodings for A64" */
    22722272         | ((uint32_t)enmType                  << 23)
     
    22762276         | (iBaseReg                           <<  5)
    22772277         | iReg1;
     2278}
     2279
     2280typedef enum                         /* Size VR Opc */
     2281{                                    /*     \ | /   */
     2282    kArmv8A64InstrLdStType_Mask_Size       = 0x300,
     2283    kArmv8A64InstrLdStType_Mask_VR         = 0x010,
     2284    kArmv8A64InstrLdStType_Mask_Opc        = 0x003,
     2285    kArmv8A64InstrLdStType_Shift_Size      =     8,
     2286    kArmv8A64InstrLdStType_Shift_VR        =     4,
     2287    kArmv8A64InstrLdStType_Shift_Opc       =     0,
     2288
     2289    kArmv8A64InstrLdStType_St_Byte         = 0x000,
     2290    kArmv8A64InstrLdStType_Ld_Byte         = 0x001,
     2291    kArmv8A64InstrLdStType_Ld_SignByte64   = 0x002,
     2292    kArmv8A64InstrLdStType_Ld_SignByte32   = 0x003,
     2293
     2294    kArmv8A64InstrLdStType_St_Half         = 0x100, /**< Half = 16-bit */
     2295    kArmv8A64InstrLdStType_Ld_Half         = 0x101, /**< Half = 16-bit */
     2296    kArmv8A64InstrLdStType_Ld_SignHalf64   = 0x102, /**< Half = 16-bit */
     2297    kArmv8A64InstrLdStType_Ld_SignHalf32   = 0x103, /**< Half = 16-bit */
     2298
     2299    kArmv8A64InstrLdStType_St_Word         = 0x200, /**< Word = 32-bit */
     2300    kArmv8A64InstrLdStType_Ld_Word         = 0x201, /**< Word = 32-bit */
     2301    kArmv8A64InstrLdStType_Ld_SignWord64   = 0x202, /**< Word = 32-bit */
     2302
     2303    kArmv8A64InstrLdStType_St_Dword        = 0x300, /**< Dword = 64-bit */
     2304    kArmv8A64InstrLdStType_Ld_Dword        = 0x301, /**< Dword = 64-bit */
     2305
     2306    kArmv8A64InstrLdStType_Prefetch        = 0x302, /**< Not valid in all variations, check docs. */
     2307
     2308    kArmv8A64InstrLdStType_St_Vr_Byte      = 0x010,
     2309    kArmv8A64InstrLdStType_Ld_Vr_Byte      = 0x011,
     2310    kArmv8A64InstrLdStType_St_Vr_128       = 0x012,
     2311    kArmv8A64InstrLdStType_Ld_Vr_128       = 0x013,
     2312
     2313    kArmv8A64InstrLdStType_St_Vr_Half      = 0x110, /**< Half = 16-bit */
     2314    kArmv8A64InstrLdStType_Ld_Vr_Half      = 0x111, /**< Half = 16-bit */
     2315
     2316    kArmv8A64InstrLdStType_St_Vr_Word      = 0x210, /**< Word = 32-bit */
     2317    kArmv8A64InstrLdStType_Ld_Vr_Word      = 0x211, /**< Word = 32-bit */
     2318
     2319    kArmv8A64InstrLdStType_St_Vr_Dword     = 0x310, /**< Dword = 64-bit */
     2320    kArmv8A64InstrLdStType_Ld_Vr_Dword     = 0x311  /**< Dword = 64-bit */
     2321
     2322} ARMV8A64INSTRLDSTTYPE;
     2323
     2324/**
     2325 * A64: Encodes load/store with unscaled 9-bit signed immediate.
     2326 *
     2327 * @returns The encoded instruction.
     2328 * @param   u32Opcode   The base opcode value.
     2329 * @param   enmType     The load/store instruction type. Prefech valid (PRFUM)
     2330 * @param   iReg        The register to load into / store.
     2331 * @param   iBaseReg    The base register to use when addressing. SP is allowed.
     2332 * @param   i9ImmDisp   The 9-bit signed addressing displacement. Unscaled.
     2333 */
     2334DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrStLdImm9Ex(uint32_t u32Opcode, ARMV8A64INSTRLDSTTYPE enmType,
     2335                                                      uint32_t iReg, uint32_t iRegBase, int32_t i9ImmDisp = 0)
     2336{
     2337    Assert(i9ImmDisp >= -256 && i9ImmDisp < 256); Assert(iReg < 32); Assert(iRegBase < 32);
     2338    return u32Opcode
     2339         | (((uint32_t)enmType & (uint32_t)kArmv8A64InstrLdStType_Mask_Size) << (30 - kArmv8A64InstrLdStType_Shift_Size))
     2340         | (((uint32_t)enmType & (uint32_t)kArmv8A64InstrLdStType_Mask_VR)   << (26 - kArmv8A64InstrLdStType_Shift_VR))
     2341         | (((uint32_t)enmType & (uint32_t)kArmv8A64InstrLdStType_Mask_Opc)  << (22 - kArmv8A64InstrLdStType_Shift_Opc))
     2342         | (((uint32_t)i9ImmDisp & UINT32_C(0x1ff)) << 12)
     2343         | (iRegBase                                <<  5)
     2344         | iReg;
     2345}
     2346
     2347
     2348/**
     2349 * A64: Encodes load/store with unscaled 9-bit signed immediate.
     2350 *
     2351 * @returns The encoded instruction.
     2352 * @param   enmType     The load/store instruction type. Prefech valid (PRFUM)
     2353 * @param   iReg        The register to load into / store.
     2354 * @param   iBaseReg    The base register to use when addressing. SP is allowed.
     2355 * @param   i9ImmDisp   The 9-bit signed addressing displacement. Unscaled.
     2356 */
     2357DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrSturLdur(ARMV8A64INSTRLDSTTYPE enmType,
     2358                                                    uint32_t iReg, uint32_t iRegBase, int32_t i9ImmDisp = 0)
     2359{
     2360                                                          /*    3         2         1         0 */
     2361                                                          /*   10987654321098765432109876543210 */
     2362    return Armv8A64MkInstrStLdImm9Ex(UINT32_C(0x38000000) /* 0b00111000000000000000000000000000 */,
     2363                                     enmType, iReg, iRegBase, i9ImmDisp);
     2364}
     2365
     2366/**
     2367 * A64: Encodes load/store with unscaled 9-bit signed immediate, post-indexed.
     2368 *
     2369 * @returns The encoded instruction.
     2370 * @param   enmType     The load/store instruction type. Prefech not valid.
     2371 * @param   iReg        The register to load into / store.
     2372 * @param   iBaseReg    The base register to use when addressing. SP is allowed.
     2373 *                      Written back.
     2374 * @param   i9ImmDisp   The 9-bit signed addressing displacement. Unscaled.
     2375 */
     2376DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrStrLdrPostIndex9(ARMV8A64INSTRLDSTTYPE enmType,
     2377                                                            uint32_t iReg, uint32_t iRegBase, int32_t i9ImmDisp = 0)
     2378{
     2379    Assert(enmType != kArmv8A64InstrLdStType_Prefetch);   /*    3         2         1         0 */
     2380                                                          /*   10987654321098765432109876543210 */
     2381    return Armv8A64MkInstrStLdImm9Ex(UINT32_C(0x38000400) /* 0b00111000000000000000010000000000 */,
     2382                                     enmType, iReg, iRegBase, i9ImmDisp);
     2383}
     2384
     2385/**
     2386 * A64: Encodes load/store with unscaled 9-bit signed immediate, pre-indexed
     2387 *
     2388 * @returns The encoded instruction.
     2389 * @param   enmType     The load/store instruction type. Prefech valid (PRFUM)
     2390 * @param   iReg        The register to load into / store.
     2391 * @param   iBaseReg    The base register to use when addressing. SP is allowed.
     2392 *                      Written back.
     2393 * @param   i9ImmDisp   The 9-bit signed addressing displacement. Unscaled.
     2394 */
     2395DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrStrLdrPreIndex9(ARMV8A64INSTRLDSTTYPE enmType,
     2396                                                           uint32_t iReg, uint32_t iRegBase, int32_t i9ImmDisp = 0)
     2397{
     2398    Assert(enmType != kArmv8A64InstrLdStType_Prefetch);   /*    3         2         1         0 */
     2399                                                          /*   10987654321098765432109876543210 */
     2400    return Armv8A64MkInstrStLdImm9Ex(UINT32_C(0x38000c00) /* 0b00111000000000000000110000000000 */,
     2401                                     enmType, iReg, iRegBase, i9ImmDisp);
     2402}
     2403
     2404/**
     2405 * A64: Encodes unprivileged load/store with unscaled 9-bit signed immediate.
     2406 *
     2407 * @returns The encoded instruction.
     2408 * @param   enmType     The load/store instruction type. Prefech not valid,
     2409 *                      nor any SIMD&FP variants.
     2410 * @param   iReg        The register to load into / store.
     2411 * @param   iBaseReg    The base register to use when addressing. SP is allowed.
     2412 * @param   i9ImmDisp   The 9-bit signed addressing displacement. Unscaled.
     2413 */
     2414DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrSttrLdtr(ARMV8A64INSTRLDSTTYPE enmType,
     2415                                                    uint32_t iReg, uint32_t iRegBase, int32_t i9ImmDisp = 0)
     2416{
     2417    Assert(enmType != kArmv8A64InstrLdStType_Prefetch);
     2418    Assert(!((uint32_t)enmType & (uint32_t)kArmv8A64InstrLdStType_Mask_VR));
     2419                                                          /*    3         2         1         0 */
     2420                                                          /*   10987654321098765432109876543210 */
     2421    return Armv8A64MkInstrStLdImm9Ex(UINT32_C(0x38000800) /* 0b00111000000000000000100000000000 */,
     2422                                     enmType, iReg, iRegBase, i9ImmDisp);
     2423}
     2424
     2425
     2426/**
     2427 * A64: Encodes load/store w/ scaled 12-bit unsigned address displacement.
     2428 *
     2429 * @returns The encoded instruction.
     2430 * @param   enmType     The load/store instruction type. Prefech not valid,
     2431 *                      nor any SIMD&FP variants.
     2432 * @param   iReg        The register to load into / store.
     2433 * @param   iBaseReg    The base register to use when addressing. SP is allowed.
     2434 * @param   u12ImmDisp  Addressing displacement, scaled by size.
     2435 */
     2436DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrStLdRUOff(ARMV8A64INSTRLDSTTYPE enmType,
     2437                                                     uint32_t iReg, uint32_t iRegBase, uint32_t u12ImmDisp)
     2438{
     2439    Assert(u12ImmDisp < 4096U);
     2440    Assert(iReg < 32);          /*    3         2         1         0 */
     2441    Assert(iRegBase < 32);      /*   10987654321098765432109876543210 */
     2442    return UINT32_C(0x39000000) /* 0b00111001000000000000000000000000 */
     2443         | (((uint32_t)enmType & (uint32_t)kArmv8A64InstrLdStType_Mask_Size) << (30 - kArmv8A64InstrLdStType_Shift_Size))
     2444         | (((uint32_t)enmType & (uint32_t)kArmv8A64InstrLdStType_Mask_VR)   << (26 - kArmv8A64InstrLdStType_Shift_VR))
     2445         | (((uint32_t)enmType & (uint32_t)kArmv8A64InstrLdStType_Mask_Opc)  << (22 - kArmv8A64InstrLdStType_Shift_Opc))
     2446         | (u12ImmDisp       << 10)
     2447         | (iRegBase         <<  5)
     2448         | iReg;
     2449}
     2450
     2451typedef enum
     2452{
     2453    kArmv8A64InstrLdStExtend_Uxtw   = 2, /**< Zero-extend (32-bit) word. */
     2454    kArmv8A64InstrLdStExtend_Lsl    = 3, /**< Not valid for bytes. */
     2455    kArmv8A64InstrLdStExtend_Sxtw   = 6, /**< Sign-extend (32-bit) word. */
     2456    kArmv8A64InstrLdStExtend_Sxtx   = 7  /**< Sign-extend (64-bit) dword (to 128-bit SIMD&FP reg, presumably). */
     2457} ARMV8A64INSTRLDSTEXTEND;
     2458
     2459/**
     2460 * A64: Encodes load/store w/ scaled 12-bit unsigned address displacement.
     2461 *
     2462 * @returns The encoded instruction.
     2463 * @param   enmType     The load/store instruction type.
     2464 * @param   iReg        The register to load into / store.
     2465 * @param   iBaseReg    The base register to use when addressing. SP is allowed.
     2466 * @param   iRegIndex   The index register.
     2467 * @param   enmExtend   The extending to apply to @a iRegIndex.
     2468 * @param   fShifted    Whether to shift the index. The shift amount corresponds
     2469 *                      to the access size (thus irrelevant for byte accesses).
     2470 */
     2471DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrStLdRegIdx(ARMV8A64INSTRLDSTTYPE enmType,
     2472                                                      uint32_t iReg, uint32_t iRegBase, uint32_t iRegIndex,
     2473                                                      ARMV8A64INSTRLDSTEXTEND enmExtend = kArmv8A64InstrLdStExtend_Lsl,
     2474                                                      bool fShifted = false)
     2475{
     2476    Assert(iRegIndex < 32);
     2477    Assert(iReg < 32);          /*    3         2         1         0 */
     2478    Assert(iRegBase < 32);      /*   10987654321098765432109876543210 */
     2479    return UINT32_C(0x38200800) /* 0b00111000001000000000100000000000 */
     2480         | (((uint32_t)enmType & (uint32_t)kArmv8A64InstrLdStType_Mask_Size) << (30 - kArmv8A64InstrLdStType_Shift_Size))
     2481         | (((uint32_t)enmType & (uint32_t)kArmv8A64InstrLdStType_Mask_VR)   << (26 - kArmv8A64InstrLdStType_Shift_VR))
     2482         | (((uint32_t)enmType & (uint32_t)kArmv8A64InstrLdStType_Mask_Opc)  << (22 - kArmv8A64InstrLdStType_Shift_Opc))
     2483         | (iRegIndex            << 16)
     2484         | ((uint32_t)enmExtend  << 13)
     2485         | ((uint32_t)fShifted   << 12)
     2486         | (iRegBase             <<  5)
     2487         | iReg;
     2488}
     2489
     2490typedef enum                            /* VR  Opc */
     2491{                                       /*   \ |   */
     2492    kArmv8A64InstrLdrLitteral_Mask_Vr     = 0x10,
     2493    kArmv8A64InstrLdrLitteral_Mask_Opc    = 0x03,
     2494    kArmv8A64InstrLdrLitteral_Shift_Vr    = 4,
     2495    kArmv8A64InstrLdrLitteral_Shift_Opc   = 0,
     2496
     2497    kArmv8A64InstrLdrLitteral_Word        = 0x00,   /**< word = 32-bit */
     2498    kArmv8A64InstrLdrLitteral_Dword       = 0x01,   /**< dword = 64-bit */
     2499    kArmv8A64InstrLdrLitteral_SignWord64  = 0x02,   /**< Loads word, signextending it to 64-bit  */
     2500    kArmv8A64InstrLdrLitteral_Prefetch    = 0x03,   /**< prfm */
     2501
     2502    kArmv8A64InstrLdrLitteral_Vr_Word     = 0x10,   /**< word = 32-bit */
     2503    kArmv8A64InstrLdrLitteral_Vr_Dword    = 0x11,   /**< dword = 64-bit */
     2504    kArmv8A64InstrLdrLitteral_Vr_128      = 0x12
     2505} ARMV8A64INSTRLDRLITTERAL;
     2506
     2507
     2508/**
     2509 * A64: Encodes load w/ a PC relative 19-bit signed immediate.
     2510 *
     2511 * @returns The encoded instruction.
     2512 * @param   enmType     The load instruction type.
     2513 * @param   iReg        The register to load into.
     2514 * @param   i19Imm      The signed immediate value, multiplied by 4 regardless
     2515 *                      of access size.
     2516 */
     2517DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrLdrLitteral(ARMV8A64INSTRLDRLITTERAL enmType, uint32_t iReg, int32_t i19Imm)
     2518{
     2519    Assert(i19Imm >= -262144 && i19Imm < 262144);
     2520    Assert(iReg < 32);          /*    3         2         1         0 */
     2521                                /*   10987654321098765432109876543210 */
     2522    return UINT32_C(0x30000000) /* 0b00110000000000000000000000000000 */
     2523         | (((uint32_t)enmType & (uint32_t)kArmv8A64InstrLdrLitteral_Mask_Vr)  << (26 - kArmv8A64InstrLdrLitteral_Shift_Vr))
     2524         | (((uint32_t)enmType & (uint32_t)kArmv8A64InstrLdrLitteral_Mask_Opc) << (30 - kArmv8A64InstrLdrLitteral_Shift_Opc))
     2525         | (((uint32_t)i19Imm & UINT32_C(0x00ffffe0)) << 5)
     2526         | iReg;
    22782527}
    22792528
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp

    r100787 r101304  
    98899889 *
    98909890 * @param   iStReg              The other stack register.
    9891  * @param   pfnAImpl            The assembly comparison implementation.
     9891 * @param   fUCmp               true for FUCOMI[P], false for FCOMI[P].
    98929892 * @param   uPopAndFpuOpcode    Bits 15-0: The FPU opcode.
    98939893 *                              Bit  31: Whether we should pop the stack when
    98949894 *                              done or not.
    98959895 */
    9896 IEM_CIMPL_DEF_3(iemCImpl_fcomi_fucomi, uint8_t, iStReg, PFNIEMAIMPLFPUR80EFL, pfnAImpl, uint32_t, uPopAndFpuOpcode)
     9896IEM_CIMPL_DEF_3(iemCImpl_fcomi_fucomi, uint8_t, iStReg, bool, fUCmp, uint32_t, uPopAndFpuOpcode)
    98979897{
    98989898    Assert(iStReg < 8);
     
    99189918    if ((pFpuCtx->FTW & (RT_BIT(iReg1) | RT_BIT(iReg2))) == (RT_BIT(iReg1) | RT_BIT(iReg2)))
    99199919    {
    9920         uint32_t u32Eflags = pfnAImpl(pFpuCtx, &u16Fsw, &pFpuCtx->aRegs[0].r80, &pFpuCtx->aRegs[iStReg].r80);
     9920        uint32_t u32Eflags;
     9921        if (!fUCmp)
     9922            u32Eflags = iemAImpl_fcomi_r80_by_r80(pFpuCtx, &u16Fsw, &pFpuCtx->aRegs[0].r80, &pFpuCtx->aRegs[iStReg].r80);
     9923        else
     9924            u32Eflags = iemAImpl_fucomi_r80_by_r80(pFpuCtx, &u16Fsw, &pFpuCtx->aRegs[0].r80, &pFpuCtx->aRegs[iStReg].r80);
    99219925
    99229926        pFpuCtx->FSW &= ~X86_FSW_C1;
  • trunk/src/VBox/VMM/VMMAll/IEMAllInstOneByte.cpp.h

    r100858 r101304  
    1053810538    IEMOP_MNEMONIC(fucomi_st0_stN, "fucomi st0,stN");
    1053910539    IEM_MC_DEFER_TO_CIMPL_3_RET(IEM_CIMPL_F_FPU | IEM_CIMPL_F_STATUS_FLAGS,
    10540                                 iemCImpl_fcomi_fucomi, IEM_GET_MODRM_RM_8(bRm), iemAImpl_fucomi_r80_by_r80,
     10540                                iemCImpl_fcomi_fucomi, IEM_GET_MODRM_RM_8(bRm), true /*fUCmp*/,
    1054110541                                0 /*fPop*/ | pVCpu->iem.s.uFpuOpcode);
    1054210542}
     
    1054810548    IEMOP_MNEMONIC(fcomi_st0_stN, "fcomi st0,stN");
    1054910549    IEM_MC_DEFER_TO_CIMPL_3_RET(IEM_CIMPL_F_FPU | IEM_CIMPL_F_STATUS_FLAGS,
    10550                                 iemCImpl_fcomi_fucomi, IEM_GET_MODRM_RM_8(bRm), iemAImpl_fcomi_r80_by_r80,
     10550                                iemCImpl_fcomi_fucomi, IEM_GET_MODRM_RM_8(bRm), false /*fUCmp*/,
    1055110551                                false /*fPop*/ | pVCpu->iem.s.uFpuOpcode);
    1055210552}
     
    1146711467    IEMOP_MNEMONIC(fucomip_st0_stN, "fucomip st0,stN");
    1146811468    IEM_MC_DEFER_TO_CIMPL_3_RET(IEM_CIMPL_F_FPU | IEM_CIMPL_F_STATUS_FLAGS,
    11469                                 iemCImpl_fcomi_fucomi, IEM_GET_MODRM_RM_8(bRm), iemAImpl_fcomi_r80_by_r80,
     11469                                iemCImpl_fcomi_fucomi, IEM_GET_MODRM_RM_8(bRm), false /*fUCmp*/,
    1147011470                                RT_BIT_32(31) /*fPop*/ | pVCpu->iem.s.uFpuOpcode);
    1147111471}
     
    1147711477    IEMOP_MNEMONIC(fcomip_st0_stN, "fcomip st0,stN");
    1147811478    IEM_MC_DEFER_TO_CIMPL_3_RET(IEM_CIMPL_F_FPU | IEM_CIMPL_F_STATUS_FLAGS,
    11479                                 iemCImpl_fcomi_fucomi, IEM_GET_MODRM_RM_8(bRm), iemAImpl_fcomi_r80_by_r80,
     11479                                iemCImpl_fcomi_fucomi, IEM_GET_MODRM_RM_8(bRm), false /*fUCmp*/,
    1148011480                                RT_BIT_32(31) /*fPop*/ | pVCpu->iem.s.uFpuOpcode);
    1148111481}
  • trunk/src/VBox/VMM/VMMAll/IEMAllN8vePython.py

    r101275 r101304  
    3737__version__ = "$Revision$"
    3838
    39 # Standard python imports.
     39# Standard python imports:
    4040#import sys;
    4141
    42 #import IEMAllInstPython as iai;
     42# Out python imports:
     43import IEMAllInstPython as iai;
    4344
    4445
     
    4748    Class that deals with transforming a threaded function variation into a
    4849    native recompiler function.
     50
     51    This base class doesn't do any transforming and just renders the same
     52    code as for the threaded function.
    4953    """
    5054
     
    5862        (for the selected host architecture).
    5963        """
    60         return False;
     64        return True;
    6165
    6266    def renderCode(self, cchIndent):
     
    6468        Returns the native recompiler function body for this threaded variant.
    6569        """
    66         return ' ' * cchIndent + '    AssertFailed();';
     70        aoStmts = self.oVariation.aoStmtsForThreadedFunction # type: list(McStmt)
     71        return iai.McStmt.renderCodeForList(aoStmts, cchIndent);
    6772
    6873
     
    7883    """
    7984
    80     _ = oVariation;
    81     _ = sHostArch;
     85    #
     86    # Analyze the statements.
     87    #
     88    aoStmts = oVariation.aoStmtsForThreadedFunction # type: list(McStmt)
     89
     90    # The simplest case are the IEM_MC_DEFER_TO_CIMPL_*_RET_THREADED ones, just pass them thru:
     91    if (    len(aoStmts) == 1
     92        and aoStmts[0].sName.startswith('IEM_MC_DEFER_TO_CIMPL_')
     93        and aoStmts[0].sName.endswith('_RET_THREADED')
     94        and sHostArch in ('amd64',)):
     95        return NativeRecompFunctionVariation(oVariation, sHostArch);
    8296
    8397    return None;
  • trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp

    r101275 r101304  
    14051405
    14061406/**
     1407 * Emits a call to a CImpl function or something similar.
     1408 */
     1409static int32_t iemNativeEmitCImplCall(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxInstr,
     1410                                      uintptr_t pfnCImpl, uint8_t cbInstr, uint8_t cAddParams,
     1411                                      uint64_t uParam0, uint64_t uParam1, uint64_t uParam2)
     1412{
     1413#ifdef VBOX_STRICT
     1414    off = iemNativeEmitMarker(pReNative, off);
     1415    AssertReturn(off != UINT32_MAX, UINT32_MAX);
     1416#endif
     1417
     1418    /*
     1419     * Load the parameters.
     1420     */
     1421#if defined(RT_OS_WINDOWS) && defined(VBOXSTRICTRC_STRICT_ENABLED)
     1422    /* Special code the hidden VBOXSTRICTRC pointer. */
     1423    off = iemNativeEmitLoadGprFromGpr(  pReNative, off, IEMNATIVE_CALL_ARG1_GREG, IEMNATIVE_REG_FIXED_PVMCPU);
     1424    off = iemNativeEmitLoadGprImm64(    pReNative, off, IEMNATIVE_CALL_ARG2_GREG, cbInstr); /** @todo 8-bit reg load opt for amd64 */
     1425    if (cAddParams > 0)
     1426        off = iemNativeEmitLoadGprImm64(pReNative, off, IEMNATIVE_CALL_ARG3_GREG, uParam0);
     1427    if (cAddParams > 1)
     1428        off = iemNativeEmitStoreImm64ByBp(pReNative, off, IEMNATIVE_FP_OFF_STACK_ARG0, uParam1);
     1429    if (cAddParams > 2)
     1430        off = iemNativeEmitStoreImm64ByBp(pReNative, off, IEMNATIVE_FP_OFF_STACK_ARG1, uParam2);
     1431    off = iemNativeEmitLeaGrpByBp(pReNative, off, X86_GREG_xCX, IEMNATIVE_FP_OFF_IN_SHADOW_ARG0); /* rcStrict */
     1432
     1433#else
     1434    AssertCompile(IEMNATIVE_CALL_ARG_GREG_COUNT >= 4);
     1435    off = iemNativeEmitLoadGprFromGpr(  pReNative, off, IEMNATIVE_CALL_ARG0_GREG, IEMNATIVE_REG_FIXED_PVMCPU);
     1436    off = iemNativeEmitLoadGprImm64(    pReNative, off, IEMNATIVE_CALL_ARG1_GREG, cbInstr); /** @todo 8-bit reg load opt for amd64 */
     1437    if (cAddParams > 0)
     1438        off = iemNativeEmitLoadGprImm64(pReNative, off, IEMNATIVE_CALL_ARG2_GREG, uParam0);
     1439    if (cAddParams > 1)
     1440        off = iemNativeEmitLoadGprImm64(pReNative, off, IEMNATIVE_CALL_ARG3_GREG, uParam1);
     1441    if (cAddParams > 2)
     1442# if IEMNATIVE_CALL_ARG_GREG_COUNT >= 5
     1443        off = iemNativeEmitLoadGprImm64(pReNative, off, IEMNATIVE_CALL_ARG4_GREG, uParam2);
     1444# else
     1445        off = iemNativeEmitStoreImm64ByBp(pReNative, off, IEMNATIVE_FP_OFF_STACK_ARG0, uParam2);
     1446# endif
     1447#endif
     1448    AssertReturn(off != UINT32_MAX, off);
     1449
     1450    /*
     1451     * Make the call.
     1452     */
     1453#ifdef RT_ARCH_AMD64
     1454    off = iemNativeEmitLoadGprImm64(pReNative, off, X86_GREG_xAX, pfnCImpl);
     1455
     1456    uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 2);
     1457    AssertReturn(pbCodeBuf, UINT32_MAX);
     1458    pbCodeBuf[off++] = 0xff;                    /* call rax */
     1459    pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 2, X86_GREG_xAX);
     1460
     1461# if defined(VBOXSTRICTRC_STRICT_ENABLED) && defined(RT_OS_WINDOWS)
     1462    off = iemNativeEmitLoadGprByBpU32(pReNative, off, X86_GREG_xAX, IEMNATIVE_FP_OFF_IN_SHADOW_ARG0); /* rcStrict (see above) */
     1463# endif
     1464
     1465#elif defined(RT_ARCH_ARM64)
     1466    off = iemNativeEmitLoadGprImm64(pReNative, off, IEMNATIVE_REG_FIXED_TMP0, pfnCImpl);
     1467
     1468    uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
     1469    AssertReturn(pu32CodeBuf, UINT32_MAX);
     1470    pu32CodeBuf[off++] = Armv8A64MkInstrBlr(IEMNATIVE_REG_FIXED_TMP0);
     1471
     1472#else
     1473# error "Port me!"
     1474#endif
     1475
     1476    /*
     1477     * Check the status code.
     1478     */
     1479    return iemNativeEmitCheckCallRetAndPassUp(pReNative, off, idxInstr);
     1480}
     1481
     1482
     1483/**
    14071484 * Emits a call to a threaded worker function.
    14081485 */
     
    15241601
    15251602/**
    1526  * Emits a standard epilog.
     1603 * Emits the RC fiddling code for handling non-zero return code or rcPassUp.
    15271604 */
    15281605static uint32_t iemNativeEmitRcFiddling(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t idxReturnLabel)
     
    18081885
    18091886
     1887DECLINLINE(uint32_t) iemNativeEmitCImplCall1(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxInstr,
     1888                                             uintptr_t pfnCImpl, uint8_t cbInstr, uint64_t uArg0)
     1889{
     1890    return iemNativeEmitCImplCall(pReNative, off, idxInstr, pfnCImpl, cbInstr, 1, uArg0, 0, 0);
     1891}
     1892
     1893
     1894DECLINLINE(uint32_t) iemNativeEmitCImplCall2(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxInstr,
     1895                                             uintptr_t pfnCImpl, uint8_t cbInstr, uint64_t uArg0, uint64_t uArg1)
     1896{
     1897    return iemNativeEmitCImplCall(pReNative, off, idxInstr, pfnCImpl, cbInstr, 2, uArg0, uArg1, 0);
     1898}
     1899
     1900
     1901DECLINLINE(uint32_t) iemNativeEmitCImplCall3(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxInstr,
     1902                                             uintptr_t pfnCImpl, uint8_t cbInstr, uint64_t uArg0, uint64_t uArg1, uint64_t uArg2)
     1903{
     1904    return iemNativeEmitCImplCall(pReNative, off, idxInstr, pfnCImpl, cbInstr, 3, uArg0, uArg1, uArg2);
     1905}
     1906
     1907
     1908/*
     1909 * MC definitions for the native recompiler.
     1910 */
     1911
     1912#define IEM_MC_DEFER_TO_CIMPL_0_RET_THREADED(a_cbInstr, a_fFlags, a_pfnCImpl) \
     1913    return iemNativeEmitCImplCall0(pReNative, off, pCallEntry->idxInstr, (uintptr_t)a_pfnCImpl, a_cbInstr) /** @todo not used ... */
     1914
     1915#define IEM_MC_DEFER_TO_CIMPL_1_RET_THREADED(a_cbInstr, a_fFlags, a_pfnCImpl, a0) \
     1916    return iemNativeEmitCImplCall1(pReNative, off, pCallEntry->idxInstr, (uintptr_t)a_pfnCImpl, a_cbInstr, a0)
     1917
     1918#define IEM_MC_DEFER_TO_CIMPL_2_RET_THREADED(a_cbInstr, a_fFlags, a_pfnCImpl, a0, a1) \
     1919    return iemNativeEmitCImplCall2(pReNative, off, pCallEntry->idxInstr, (uintptr_t)a_pfnCImpl, a_cbInstr, a0, a1)
     1920
     1921#define IEM_MC_DEFER_TO_CIMPL_3_RET_THREADED(a_cbInstr, a_fFlags, a_pfnCImpl, a0, a1, a2) \
     1922    return iemNativeEmitCImplCall3(pReNative, off, pCallEntry->idxInstr, (uintptr_t)a_pfnCImpl, a_cbInstr, a0, a1, a2)
     1923
     1924
     1925
    18101926/*
    18111927 * Include g_apfnIemNativeRecompileFunctions and associated functions.
  • trunk/src/VBox/VMM/include/IEMInternal.h

    r101262 r101304  
    50925092IEM_CIMPL_PROTO_1(iemCImpl_fldcw, uint16_t, u16Fcw);
    50935093IEM_CIMPL_PROTO_2(iemCImpl_fxch_underflow, uint8_t, iStReg, uint16_t, uFpuOpcode);
    5094 IEM_CIMPL_PROTO_3(iemCImpl_fcomi_fucomi, uint8_t, iStReg, PFNIEMAIMPLFPUR80EFL, pfnAImpl, uint32_t, uPopAndFpuOpcode);
     5094IEM_CIMPL_PROTO_3(iemCImpl_fcomi_fucomi, uint8_t, iStReg, bool, fUCmp, uint32_t, uPopAndFpuOpcode);
    50955095/** @} */
    50965096
  • trunk/src/VBox/VMM/include/IEMN8veRecompiler.h

    r101275 r101304  
    114114/** @def IEMNATIVE_REG_FIXED_PVMCPU
    115115 * The register number hold in pVCpu pointer.  */
     116/** @def IEMNATIVE_REG_FIXED_TMP0
     117 * Dedicated temporary register.
     118 * @todo replace this by a register allocator and content tracker.  */
    116119#ifdef RT_ARCH_AMD64
    117120# define IEMNATIVE_REG_FIXED_PVMCPU         X86_GREG_xBX
     121# define IEMNATIVE_REG_FIXED_TMP0           X86_GREG_x11
    118122
    119123#elif defined(RT_ARCH_ARM64)
    120124# define IEMNATIVE_REG_FIXED_PVMCPU         ARMV8_A64_REG_X28
    121 /** Dedicated temporary register.
    122  * @todo replace this by a register allocator and content tracker.  */
    123125# define IEMNATIVE_REG_FIXED_TMP0           ARMV8_A64_REG_X15
    124126
     
    584586    /* mov gprdst, qword [rbp + offDisp]  */
    585587    uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 7);
     588    AssertReturn(pbCodeBuf, UINT32_MAX);
    586589    if (iGprDst < 8)
    587590        pbCodeBuf[off++] = X86_OP_REX_W;
     
    602605    /* mov gprdst, dword [rbp + offDisp]  */
    603606    uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 7);
     607    AssertReturn(pbCodeBuf, UINT32_MAX);
    604608    if (iGprDst >= 8)
    605609        pbCodeBuf[off++] = X86_OP_REX_R;
     
    618622    /* lea gprdst, [rbp + offDisp] */
    619623    uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 7);
     624    AssertReturn(pbCodeBuf, UINT32_MAX);
    620625    if (iGprDst < 8)
    621626        pbCodeBuf[off++] = X86_OP_REX_W;
     
    628633
    629634
    630 #ifdef RT_ARCH_AMD64
    631635/**
    632636 * Emits a 64-bit GPR store with an BP relative destination address.
     637 *
     638 * @note May trash IEMNATIVE_REG_FIXED_TMP0.
    633639 */
    634640DECLINLINE(uint32_t) iemNativeEmitStoreGprByBp(PIEMRECOMPILERSTATE pReNative, uint32_t off, int32_t offDisp, uint8_t iGprSrc)
    635641{
     642#ifdef RT_ARCH_AMD64
    636643    /* mov qword [rbp + offDisp], gprdst */
    637644    uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 7);
     645    AssertReturn(pbCodeBuf, UINT32_MAX);
    638646    if (iGprSrc < 8)
    639647        pbCodeBuf[off++] = X86_OP_REX_W;
     
    642650    pbCodeBuf[off++] = 0x89;
    643651    return iemNativeEmitGprByBpDisp(pbCodeBuf, off, iGprSrc, offDisp);
    644 }
    645 #endif
     652
     653#elif defined(RT_ARCH_ARM64)
     654    if (offDisp >= 0 && offDisp < 4096 * 8 && !((uint32_t)offDisp & 7))
     655    {
     656        /* str w/ unsigned imm12 (scaled) */
     657        uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
     658        AssertReturn(pu32CodeBuf, UINT32_MAX);
     659        pu32CodeBuf[off++] = Armv8A64MkInstrStLdRUOff(kArmv8A64InstrLdStType_St_Dword, iGprSrc,
     660                                                      ARMV8_A64_BP, (uint32_t)offDisp / 8);
     661    }
     662    else if (offDisp >= -256 offDisp <= 256)
     663    {
     664        /* stur w/ signed imm9 (unscaled) */
     665        uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
     666        AssertReturn(pu32CodeBuf, UINT32_MAX);
     667        pu32CodeBuf[off++] = Armv8A64MkInstrSturLdur(kArmv8A64InstrLdStType_St_Dword, iGprSrc, ARMV8_A64_BP, offDisp);
     668    }
     669    else
     670    {
     671        /* Use temporary indexing register. */
     672        off = iemNativeEmitLoadGprImm64(pReNative, off, IEMNATIVE_REG_FIXED_TMP0, (uint32_t)offDisp);
     673        uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
     674        AssertReturn(pu32CodeBuf, UINT32_MAX);
     675        pu32CodeBuf[off++] = Armv8A64MkInstrStLdRegIdx(kArmv8A64InstrLdStType_St_Dword, iGprSrc, ARMV8_A64_BP,
     676                                                       IEMNATIVE_REG_FIXDE_TMP0, kArmv8A64InstrLdStExtend_Sxtw);
     677    }
     678    return off;
     679
     680#else
     681# error "Port me!"
     682#endif
     683}
     684
     685
     686/**
     687 * Emits a 64-bit immediate store with an BP relative destination address.
     688 *
     689 * @note May trash IEMNATIVE_REG_FIXED_TMP0.
     690 */
     691DECLINLINE(uint32_t) iemNativeEmitStoreImm64ByBp(PIEMRECOMPILERSTATE pReNative, uint32_t off, int32_t offDisp, uint64_t uImm64)
     692{
     693#ifdef RT_ARCH_AMD64
     694    if ((int64_t)uImm64 == (int32_t)uImm64)
     695    {
     696        /* mov qword [rbp + offDisp], imm32 - sign extended */
     697        uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 11);
     698        AssertReturn(pbCodeBuf, UINT32_MAX);
     699
     700        pbCodeBuf[off++] = X86_OP_REX_W;
     701        pbCodeBuf[off++] = 0xc7;
     702        if (offDisp < 128 && offDisp >= -128)
     703        {
     704            pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_MEM1, 0, X86_GREG_xBP);
     705            pbCodeBuf[off++] = (uint8_t)offDisp;
     706        }
     707        else
     708        {
     709            pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_MEM4, 0, X86_GREG_xBP);
     710            pbCodeBuf[off++] = RT_BYTE1((uint32_t)offDisp);
     711            pbCodeBuf[off++] = RT_BYTE2((uint32_t)offDisp);
     712            pbCodeBuf[off++] = RT_BYTE3((uint32_t)offDisp);
     713            pbCodeBuf[off++] = RT_BYTE4((uint32_t)offDisp);
     714        }
     715        pbCodeBuf[off++] = RT_BYTE1(uImm64);
     716        pbCodeBuf[off++] = RT_BYTE2(uImm64);
     717        pbCodeBuf[off++] = RT_BYTE3(uImm64);
     718        pbCodeBuf[off++] = RT_BYTE4(uImm64);
     719        return off;
     720    }
     721#endif
     722
     723    /* Load tmp0, imm64; Store tmp to bp+disp. */
     724    off = iemNativeEmitLoadGprImm64(pReNative, off, IEMNATIVE_REG_FIXED_TMP0, uImm64);
     725    return iemNativeEmitStoreGprByBp(pReNative, off, offDisp, IEMNATIVE_REG_FIXED_TMP0);
     726}
    646727
    647728
     
    654735    /* sub gprdst, imm8/imm32 */
    655736    uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 7);
     737    AssertReturn(pbCodeBuf, UINT32_MAX);
    656738    if (iGprDst < 7)
    657739        pbCodeBuf[off++] = X86_OP_REX_W;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette