VirtualBox

Changeset 101247 in vbox for trunk/src/VBox/VMM/VMMAll


Ignore:
Timestamp:
Sep 22, 2023 11:48:24 PM (18 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
159230
Message:

VMM/IEM: Working on emitting native arm64 instructions... bugref:10370

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp

    r101203 r101247  
    5959#include <iprt/mem.h>
    6060#include <iprt/string.h>
     61#if   defined(RT_ARCH_AMD64)
     62# include <iprt/x86.h>
     63#elif defined(RT_ARCH_ARM64)
     64# include <iprt/armv8.h>
     65#endif
    6166
    6267#ifdef RT_OS_WINDOWS
     
    97102# error The setjmp approach must be enabled for the recompiler.
    98103#endif
    99 
    100 
    101 /*********************************************************************************************************************************
    102 *   Defined Constants And Macros                                                                                                 *
    103 *********************************************************************************************************************************/
    104 /** @name Stack Frame Layout
    105  *
    106  * @{  */
    107 /** The size of the area for stack variables and spills and stuff. */
    108 #define IEMNATIVE_FRAME_VAR_SIZE            0x40
    109 #ifdef RT_ARCH_AMD64
    110 /** Number of stack arguments slots for calls made from the frame. */
    111 # define IEMNATIVE_FRAME_STACK_ARG_COUNT    4
    112 /** An stack alignment adjustment (between non-volatile register pushes and
    113  *  the stack variable area, so the latter better aligned). */
    114 # define IEMNATIVE_FRAME_ALIGN_SIZE         8
    115 /** Number of any shadow arguments (spill area) for calls we make. */
    116 # ifdef RT_OS_WINDOWS
    117 #  define IEMNATIVE_FRAME_SHADOW_ARG_COUNT  4
    118 # else
    119 #  define IEMNATIVE_FRAME_SHADOW_ARG_COUNT  0
    120 # endif
    121 
    122 /** Frame pointer (RBP) relative offset of the last push. */
    123 # ifdef RT_OS_WINDOWS
    124 #  define IEMNATIVE_FP_OFF_LAST_PUSH        (7 * -8)
    125 # else
    126 #  define IEMNATIVE_FP_OFF_LAST_PUSH        (5 * -8)
    127 # endif
    128 /** Frame pointer (RBP) relative offset of the stack variable area (the lowest
    129  * address for it). */
    130 # define IEMNATIVE_FP_OFF_STACK_VARS        (IEMNATIVE_FP_OFF_LAST_PUSH - IEMNATIVE_FRAME_ALIGN_SIZE - IEMNATIVE_FRAME_VAR_SIZE)
    131 /** Frame pointer (RBP) relative offset of the first stack argument for calls. */
    132 # define IEMNATIVE_FP_OFF_STACK_ARG0        (IEMNATIVE_FP_OFF_STACK_VARS - IEMNATIVE_FRAME_STACK_ARG_COUNT * 8)
    133 /** Frame pointer (RBP) relative offset of the second stack argument for calls. */
    134 # define IEMNATIVE_FP_OFF_STACK_ARG1        (IEMNATIVE_FP_OFF_STACK_ARG0 + 8)
    135 /** Frame pointer (RBP) relative offset of the third stack argument for calls. */
    136 # define IEMNATIVE_FP_OFF_STACK_ARG2        (IEMNATIVE_FP_OFF_STACK_ARG0 + 16)
    137 /** Frame pointer (RBP) relative offset of the fourth stack argument for calls. */
    138 # define IEMNATIVE_FP_OFF_STACK_ARG3        (IEMNATIVE_FP_OFF_STACK_ARG0 + 24)
    139 
    140 # ifdef RT_OS_WINDOWS
    141 /** Frame pointer (RBP) relative offset of the first incoming shadow argument. */
    142 #  define IEMNATIVE_FP_OFF_IN_SHADOW_ARG0   (16)
    143 /** Frame pointer (RBP) relative offset of the second incoming shadow argument. */
    144 #  define IEMNATIVE_FP_OFF_IN_SHADOW_ARG1   (24)
    145 /** Frame pointer (RBP) relative offset of the third incoming shadow argument. */
    146 #  define IEMNATIVE_FP_OFF_IN_SHADOW_ARG2   (32)
    147 /** Frame pointer (RBP) relative offset of the fourth incoming shadow argument. */
    148 #  define IEMNATIVE_FP_OFF_IN_SHADOW_ARG3   (40)
    149 # endif
    150 
    151 #elif RT_ARCH_ARM64
    152 
    153 #else
    154 # error "port me"
    155 #endif
    156 /** @} */
    157104
    158105
     
    475422    Ptr = iemDwarfPutLeb128(Ptr, 1);                        /* Code alignment factor (LEB128 = 1). */
    476423    Ptr = iemDwarfPutLeb128(Ptr, -8);                       /* Data alignment factor (LEB128 = -8). */
     424#  ifdef RT_ARCH_AMD64
    477425    Ptr = iemDwarfPutUleb128(Ptr, DWREG_AMD64_RA);          /* Return address column (ULEB128) */
     426#  elif defined(RT_ARCH_ARM64)
     427    Ptr = iemDwarfPutUleb128(Ptr, DWREG_ARM64_PC);          /* Return address column (ULEB128) */
     428#  else
     429#   error "port me"
     430#  endif
    478431    /* Initial instructions: */
     432#  ifdef RT_ARCH_AMD64
    479433    Ptr = iemDwarfPutCfaDefCfa(Ptr, DWREG_AMD64_RBP, 16);   /* CFA     = RBP + 0x10 - first stack parameter */
    480434    Ptr = iemDwarfPutCfaOffset(Ptr, DWREG_AMD64_RA,  1);    /* Ret RIP = [CFA + 1*-8] */
     
    485439    Ptr = iemDwarfPutCfaOffset(Ptr, DWREG_AMD64_R14, 6);    /* R14     = [CFA + 6*-8] */
    486440    Ptr = iemDwarfPutCfaOffset(Ptr, DWREG_AMD64_R15, 7);    /* R15     = [CFA + 7*-8] */
     441#  elif defined(RT_ARCH_ARM64)
     442    Ptr = iemDwarfPutCfaDefCfa(Ptr, DWREG_ARM64_BP,  0);    /* CFA     = BP + 0x00 - first stack parameter */
     443    Ptr = iemDwarfPutCfaOffset(Ptr, DWREG_ARM64_PC,  1);    /* Ret PC  = [CFA + 1*-8] */
     444    Ptr = iemDwarfPutCfaOffset(Ptr, DWREG_ARM64_BP,  2);    /* Ret BP  = [CFA + 2*-8] */
     445#  endif
    487446    while ((Ptr.u - PtrCie.u) & 3)
    488447        *Ptr.pb++ = DW_CFA_nop;
     
    11471106# ifdef RT_OS_WINDOWS
    11481107#  ifndef VBOXSTRICTRC_STRICT_ENABLED
    1149     off = iemNativeEmitLoadGprFromGpr(pReNative, off, X86_GREG_xCX, X86_GREG_xBX);
     1108    off = iemNativeEmitLoadGprFromGpr(pReNative, off, X86_GREG_xCX, IEMNATIVE_REG_FIXED_PVMCPU);
    11501109    AssertReturn(off != UINT32_MAX, UINT32_MAX);
    11511110    if (cParams > 0)
     
    11651124    }
    11661125#  else  /* VBOXSTRICTRC: Returned via hidden parameter. Sigh. */
    1167     off = iemNativeEmitLoadGprFromGpr(pReNative, off, X86_GREG_xDX, X86_GREG_xBX);
     1126    off = iemNativeEmitLoadGprFromGpr(pReNative, off, X86_GREG_xDX, IEMNATIVE_REG_FIXED_PVMCPU);
    11681127    AssertReturn(off != UINT32_MAX, UINT32_MAX);
    11691128    if (cParams > 0)
     
    11881147#  endif /* VBOXSTRICTRC_STRICT_ENABLED */
    11891148# else
    1190     off = iemNativeEmitLoadGprFromGpr(pReNative, off, X86_GREG_xDI, X86_GREG_xBX);
     1149    off = iemNativeEmitLoadGprFromGpr(pReNative, off, X86_GREG_xDI, IEMNATIVE_REG_FIXED_PVMCPU);
    11911150    AssertReturn(off != UINT32_MAX, UINT32_MAX);
    11921151    if (cParams > 0)
     
    12241183
    12251184#elif RT_ARCH_ARM64
    1226     RT_NOREF(pReNative, pCallEntry);
     1185    RT_NOREF(pReNative, pCallEntry, cParams);
    12271186    off = UINT32_MAX;
    12281187
     
    12921251        off = iemNativeEmitLoadGprFromGpr(pReNative, off, X86_GREG_x8,  X86_GREG_xCX); /* cl = instruction number */
    12931252        AssertReturn(off != UINT32_MAX, UINT32_MAX);
    1294         off = iemNativeEmitLoadGprFromGpr(pReNative, off, X86_GREG_xCX, X86_GREG_xBX);
     1253        off = iemNativeEmitLoadGprFromGpr(pReNative, off, X86_GREG_xCX, IEMNATIVE_REG_FIXED_PVMCPU);
    12951254        AssertReturn(off != UINT32_MAX, UINT32_MAX);
    12961255        off = iemNativeEmitLoadGprFromGpr(pReNative, off, X86_GREG_xDX, X86_GREG_xAX);
    12971256        AssertReturn(off != UINT32_MAX, UINT32_MAX);
    12981257# else
    1299         off = iemNativeEmitLoadGprFromGpr(pReNative, off, X86_GREG_xDI, X86_GREG_xBX);
     1258        off = iemNativeEmitLoadGprFromGpr(pReNative, off, X86_GREG_xDI, IEMNATIVE_REG_FIXED_PVMCPU);
    13001259        AssertReturn(off != UINT32_MAX, UINT32_MAX);
    13011260        off = iemNativeEmitLoadGprFromGpr(pReNative, off, X86_GREG_xSI, X86_GREG_xAX);
     
    13431302
    13441303
     1304typedef enum
     1305{
     1306    kArm64InstrStLdPairType_kPostIndex = 1,
     1307    kArm64InstrStLdPairType_kSigned    = 2,
     1308    kArm64InstrStLdPairType_kPreIndex  = 3
     1309} ARM64INSTRSTLDPAIRTYPE;
     1310
     1311DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrStLdPair(bool fLoad, uint32_t iOpc, ARM64INSTRSTLDPAIRTYPE enmType,
     1312                                                    uint32_t iReg1, uint32_t iReg2, uint32_t iBaseReg, int32_t iImm7 = 0)
     1313{
     1314    Assert(iOpc < 3); Assert(iReg1 <= 31); Assert(iReg2 <= 31); Assert(iBaseReg <= 31); Assert(iImm7 < 64 && iImm7 >= -64);
     1315    return (iOpc << 30)
     1316         | UINT32_C(0x28000000)
     1317         | ((uint32_t)enmType << 23)
     1318         | ((uint32_t)fLoad << 22)
     1319         | ((uint32_t)iImm7 << 15)
     1320         | (iReg2 << 10)
     1321         | (iBaseReg << 5)
     1322         | iReg1;
     1323}
     1324
     1325
     1326
    13451327/**
    13461328 * Emits a standard prolog.
     
    13641346    pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, X86_GREG_xBP, X86_GREG_xSP);
    13651347    pbCodeBuf[off++] = 0x50 + X86_GREG_xBX;     /* push rbx */
     1348    AssertCompile(IEMNATIVE_REG_FIXED_PVMCPU == X86_GREG_xBX);
    13661349# ifdef RT_OS_WINDOWS
    13671350    pbCodeBuf[off++] = X86_OP_REX_W;            /* mov rbx, rcx ; RBX = pVCpu */
     
    13951378
    13961379#elif RT_ARCH_ARM64
    1397     RT_NOREF(pReNative);
    1398     off = UINT32_MAX;
     1380    /*
     1381     * We set up a stack frame exactly like on x86, only we have to push the
     1382     * return address our selves here.  We save all non-volatile registers.
     1383     */
     1384    uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 10);
     1385    AssertReturn(pu32CodeBuf, UINT32_MAX);
     1386    /* stp x19, x20, [sp, #-IEMNATIVE_FRAME_SAVE_REG_SIZE] ; Allocate space for saving registers and place x19+x20 at the bottom. */
     1387    AssertCompile(IEMNATIVE_FRAME_SAVE_REG_SIZE < 64*8);
     1388    pu32CodeBuf[off++] = Armv8A64MkInstrStLdPair(false /*fLoad*/, 2 /*64-bit*/, kArm64InstrStLdPairType_kPreIndex,
     1389                                                 ARMV8_A64_REG_X19, ARMV8_A64_REG_X20, ARMV8_A64_REG_SP,
     1390                                                 -IEMNATIVE_FRAME_SAVE_REG_SIZE / 8);
     1391    /* Save x21 thru x28 (SP remains unchanged in the kSigned variant). */
     1392    pu32CodeBuf[off++] = Armv8A64MkInstrStLdPair(false /*fLoad*/, 2 /*64-bit*/, kArm64InstrStLdPairType_kSigned,
     1393                                                 ARMV8_A64_REG_X21, ARMV8_A64_REG_X22, ARMV8_A64_REG_SP, 2);
     1394    pu32CodeBuf[off++] = Armv8A64MkInstrStLdPair(false /*fLoad*/, 2 /*64-bit*/, kArm64InstrStLdPairType_kSigned,
     1395                                                 ARMV8_A64_REG_X23, ARMV8_A64_REG_X24, ARMV8_A64_REG_SP, 4);
     1396    pu32CodeBuf[off++] = Armv8A64MkInstrStLdPair(false /*fLoad*/, 2 /*64-bit*/, kArm64InstrStLdPairType_kSigned,
     1397                                                 ARMV8_A64_REG_X25, ARMV8_A64_REG_X26, ARMV8_A64_REG_SP, 6);
     1398    pu32CodeBuf[off++] = Armv8A64MkInstrStLdPair(false /*fLoad*/, 2 /*64-bit*/, kArm64InstrStLdPairType_kSigned,
     1399                                                 ARMV8_A64_REG_X27, ARMV8_A64_REG_X28, ARMV8_A64_REG_SP, 8);
     1400    /* Save the BP and LR (ret address) registers at the top of the frame. */
     1401    pu32CodeBuf[off++] = Armv8A64MkInstrStLdPair(false /*fLoad*/, 2 /*64-bit*/, kArm64InstrStLdPairType_kSigned,
     1402                                                 ARMV8_A64_REG_BP, ARMV8_A64_REG_LR, ARMV8_A64_REG_SP, 10);
     1403    AssertCompile(IEMNATIVE_FRAME_SAVE_REG_SIZE / 8 == 12);
     1404    /* sub bp, sp, IEMNATIVE_FRAME_SAVE_REG_SIZE - 16 ; Set BP to point to the old BP stack address. */
     1405    AssertCompile(IEMNATIVE_FRAME_SAVE_REG_SIZE - 16 < 4096);
     1406    pu32CodeBuf[off++] = UINT32_C(0xd1000000) | ((IEMNATIVE_FRAME_SAVE_REG_SIZE - 16) << 10) | ARMV8_A64_REG_SP | ARMV8_A64_REG_BP;
     1407
     1408    /* sub sp, sp, IEMNATIVE_FRAME_VAR_SIZE ;  Allocate the variable area from SP. */
     1409    AssertCompile(IEMNATIVE_FRAME_VAR_SIZE < 4096);
     1410    pu32CodeBuf[off++] = UINT32_C(0xd1000000) | (IEMNATIVE_FRAME_VAR_SIZE << 10)             | ARMV8_A64_REG_SP | ARMV8_A64_REG_SP;
    13991411
    14001412#else
Note: See TracChangeset for help on using the changeset viewer.

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