ARM64: Enable Long Address
authorKyungwoo Lee <kyulee@microsoft.com>
Fri, 6 May 2016 15:11:08 +0000 (08:11 -0700)
committerKyungwoo Lee <kyulee@microsoft.com>
Thu, 12 May 2016 04:09:57 +0000 (21:09 -0700)
commit9e202d4e48212e7e18cd51fbae38244660ad9733
treead0fca82b5d778f27559044a89205242f5f9aea8
parent3c13acca371e5e18559fc6a030c1c0de333c1584
ARM64: Enable Long Address

Fixes https://github.com/dotnet/coreclr/issues/3668
Currently ARM64 codegen can have reference within +/-1 MB due to encoding
restriction in `b<cond>/adr/ldr` instructions. This is normally okay
assuming each function is reasonably small, but certainly not working for large method which also
can be formed with an aggressive inlining probably like crossgen/corert scenarios.
In addition, for hot/cold code separation long address is a prerequisite
since reference can be across different regions which are arbitrary.
In fact, we need additional relocations which are not in this change yet.

In details, this supports long address for conditional jump/address loading/constant
loading operations by default while they can be shortened later by
`emitJumpDistBind()` if they can fit into the smaller encoding. Logically
those operations now can reach within +/-4GB address range.
Note I haven't extended unconditional jump in this change for simplicity
so it can reach within +/-128MB same as before.
`emitOutputLJ` is extended to finally encode these operations.

There are 3 pseudo instructions introduced. These can be expanded either
short/long form.

1. Conditional jump. See `emitIns_J()`
   a. Short form(`IF_BI_0B`): `b<cond> rel_addr`
   b. Long form(`IF_LARGEJMP`):
   ```
     b<rev cond> $LABEL
     b rel_addr (unconditional jump)
   $LABEL:
   ```

2. Load label(address computation). See `emitIns_R_L()`
   a. Short form(`IF_DI_1E`): `adr x, [rel_addr]`
   b. Long form(`IF_LARGEADR`):
   ```
      adrp x, [rel_page_addr]
      add x, x, page_offs
   ```

3. Load constant (from JIT data). See `emitIns_R_C()`
   a. Short form(`IF_LS_1A`): `ldr x, [rel_addr]`
   b. Long form(`IF_LARGLDC`):
   ```
      adrp x, [rel_page_addr]
      ldr x, [x, page_offs]
     (fmov v, x in case loading vector constant)
   ```

In addition, JIT data is aligned on 8 byte to be accessible from large
load. Replaced JitLargeBranches by JitLongAddress to test stress on these
operations.

Commit migrated from https://github.com/dotnet/coreclr/commit/61fe4641665e84089dcceeabbea3e5faa0f693ce
14 files changed:
src/coreclr/src/jit/codegenarm64.cpp
src/coreclr/src/jit/compiler.cpp
src/coreclr/src/jit/compiler.h
src/coreclr/src/jit/emit.cpp
src/coreclr/src/jit/emit.h
src/coreclr/src/jit/emitarm.cpp
src/coreclr/src/jit/emitarm64.cpp
src/coreclr/src/jit/emitarm64.h
src/coreclr/src/jit/emitfmtsarm64.h
src/coreclr/src/jit/flowgraph.cpp
src/coreclr/src/jit/jitconfigvalues.h
src/coreclr/src/jit/lowerarm64.cpp
src/coreclr/src/jit/target.h
src/coreclr/tests/arm64/Tests.lst