mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-07 14:33:15 +00:00
move more pseudo instructions out to X86InstrCompiler.td
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@115598 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d071b83b5d
commit
8af88ef157
@ -100,23 +100,6 @@ def extloadi64i32 : PatFrag<(ops node:$ptr), (i64 (extloadi32 node:$ptr))>;
|
||||
// Instruction list...
|
||||
//
|
||||
|
||||
// ADJCALLSTACKDOWN/UP implicitly use/def RSP because they may be expanded into
|
||||
// a stack adjustment and the codegen must know that they may modify the stack
|
||||
// pointer before prolog-epilog rewriting occurs.
|
||||
// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become
|
||||
// sub / add which can clobber EFLAGS.
|
||||
let Defs = [RSP, EFLAGS], Uses = [RSP] in {
|
||||
def ADJCALLSTACKDOWN64 : I<0, Pseudo, (outs), (ins i32imm:$amt),
|
||||
"#ADJCALLSTACKDOWN",
|
||||
[(X86callseq_start timm:$amt)]>,
|
||||
Requires<[In64BitMode]>;
|
||||
def ADJCALLSTACKUP64 : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2),
|
||||
"#ADJCALLSTACKUP",
|
||||
[(X86callseq_end timm:$amt1, timm:$amt2)]>,
|
||||
Requires<[In64BitMode]>;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Miscellaneous Instructions...
|
||||
@ -1435,40 +1418,6 @@ let AddedComplexity = 1, isReMaterializable = 1, isAsCheapAsAMove = 1 in
|
||||
def MOV64ri64i32 : Ii32<0xB8, AddRegFrm, (outs GR64:$dst), (ins i64i32imm:$src),
|
||||
"", [(set GR64:$dst, i64immZExt32:$src)]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Thread Local Storage Instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// ELF TLS Support
|
||||
// All calls clobber the non-callee saved registers. RSP is marked as
|
||||
// a use to prevent stack-pointer assignments that appear immediately
|
||||
// before calls from potentially appearing dead.
|
||||
let Defs = [RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11,
|
||||
FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0, ST1,
|
||||
MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7,
|
||||
XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
|
||||
XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS],
|
||||
Uses = [RSP] in
|
||||
def TLS_addr64 : I<0, Pseudo, (outs), (ins i64mem:$sym),
|
||||
".byte\t0x66; "
|
||||
"leaq\t$sym(%rip), %rdi; "
|
||||
".word\t0x6666; "
|
||||
"rex64; "
|
||||
"call\t__tls_get_addr@PLT",
|
||||
[(X86tlsaddr tls64addr:$sym)]>,
|
||||
Requires<[In64BitMode]>;
|
||||
|
||||
// Darwin TLS Support
|
||||
// For x86_64, the address of the thunk is passed in %rdi, on return
|
||||
// the address of the variable is in %rax. All other registers are preserved.
|
||||
let Defs = [RAX],
|
||||
Uses = [RDI],
|
||||
usesCustomInserter = 1 in
|
||||
def TLSCall_64 : I<0, Pseudo, (outs), (ins i64mem:$sym),
|
||||
"# TLSCall_64",
|
||||
[(X86TLSCall addr:$sym)]>,
|
||||
Requires<[In64BitMode]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Atomic Instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -12,6 +12,75 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// PIC base construction. This expands to code that looks like this:
|
||||
// call $next_inst
|
||||
// popl %destreg"
|
||||
let neverHasSideEffects = 1, isNotDuplicable = 1, Uses = [ESP] in
|
||||
def MOVPC32r : Ii32<0xE8, Pseudo, (outs GR32:$reg), (ins i32imm:$label),
|
||||
"", []>;
|
||||
|
||||
|
||||
// ADJCALLSTACKDOWN/UP implicitly use/def ESP because they may be expanded into
|
||||
// a stack adjustment and the codegen must know that they may modify the stack
|
||||
// pointer before prolog-epilog rewriting occurs.
|
||||
// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become
|
||||
// sub / add which can clobber EFLAGS.
|
||||
let Defs = [ESP, EFLAGS], Uses = [ESP] in {
|
||||
def ADJCALLSTACKDOWN32 : I<0, Pseudo, (outs), (ins i32imm:$amt),
|
||||
"#ADJCALLSTACKDOWN",
|
||||
[(X86callseq_start timm:$amt)]>,
|
||||
Requires<[In32BitMode]>;
|
||||
def ADJCALLSTACKUP32 : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2),
|
||||
"#ADJCALLSTACKUP",
|
||||
[(X86callseq_end timm:$amt1, timm:$amt2)]>,
|
||||
Requires<[In32BitMode]>;
|
||||
}
|
||||
|
||||
// ADJCALLSTACKDOWN/UP implicitly use/def RSP because they may be expanded into
|
||||
// a stack adjustment and the codegen must know that they may modify the stack
|
||||
// pointer before prolog-epilog rewriting occurs.
|
||||
// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become
|
||||
// sub / add which can clobber EFLAGS.
|
||||
let Defs = [RSP, EFLAGS], Uses = [RSP] in {
|
||||
def ADJCALLSTACKDOWN64 : I<0, Pseudo, (outs), (ins i32imm:$amt),
|
||||
"#ADJCALLSTACKDOWN",
|
||||
[(X86callseq_start timm:$amt)]>,
|
||||
Requires<[In64BitMode]>;
|
||||
def ADJCALLSTACKUP64 : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2),
|
||||
"#ADJCALLSTACKUP",
|
||||
[(X86callseq_end timm:$amt1, timm:$amt2)]>,
|
||||
Requires<[In64BitMode]>;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// x86-64 va_start lowering magic.
|
||||
let usesCustomInserter = 1 in {
|
||||
def VASTART_SAVE_XMM_REGS : I<0, Pseudo,
|
||||
(outs),
|
||||
(ins GR8:$al,
|
||||
i64imm:$regsavefi, i64imm:$offset,
|
||||
variable_ops),
|
||||
"#VASTART_SAVE_XMM_REGS $al, $regsavefi, $offset",
|
||||
[(X86vastart_save_xmm_regs GR8:$al,
|
||||
imm:$regsavefi,
|
||||
imm:$offset)]>;
|
||||
|
||||
// Dynamic stack allocation yields _alloca call for Cygwin/Mingw targets. Calls
|
||||
// to _alloca is needed to probe the stack when allocating more than 4k bytes in
|
||||
// one go. Touching the stack at 4K increments is necessary to ensure that the
|
||||
// guard pages used by the OS virtual memory manager are allocated in correct
|
||||
// sequence.
|
||||
// The main point of having separate instruction are extra unmodelled effects
|
||||
// (compared to ordinary calls) like stack pointer change.
|
||||
|
||||
let Defs = [EAX, ESP, EFLAGS], Uses = [ESP] in
|
||||
def MINGW_ALLOCA : I<0, Pseudo, (outs), (ins),
|
||||
"# dynamic stack allocation",
|
||||
[(X86MingwAlloca)]>;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// EH Pseudo Instructions
|
||||
@ -32,6 +101,90 @@ def EH_RETURN64 : I<0xC3, RawFrm, (outs), (ins GR64:$addr),
|
||||
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Alias Instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Alias instructions that map movr0 to xor.
|
||||
// FIXME: remove when we can teach regalloc that xor reg, reg is ok.
|
||||
// FIXME: Set encoding to pseudo.
|
||||
let Defs = [EFLAGS], isReMaterializable = 1, isAsCheapAsAMove = 1,
|
||||
isCodeGenOnly = 1 in {
|
||||
def MOV8r0 : I<0x30, MRMInitReg, (outs GR8 :$dst), (ins), "",
|
||||
[(set GR8:$dst, 0)]>;
|
||||
|
||||
// We want to rewrite MOV16r0 in terms of MOV32r0, because it's a smaller
|
||||
// encoding and avoids a partial-register update sometimes, but doing so
|
||||
// at isel time interferes with rematerialization in the current register
|
||||
// allocator. For now, this is rewritten when the instruction is lowered
|
||||
// to an MCInst.
|
||||
def MOV16r0 : I<0x31, MRMInitReg, (outs GR16:$dst), (ins),
|
||||
"",
|
||||
[(set GR16:$dst, 0)]>, OpSize;
|
||||
|
||||
// FIXME: Set encoding to pseudo.
|
||||
def MOV32r0 : I<0x31, MRMInitReg, (outs GR32:$dst), (ins), "",
|
||||
[(set GR32:$dst, 0)]>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Thread Local Storage Instructions
|
||||
//
|
||||
|
||||
// ELF TLS Support
|
||||
// All calls clobber the non-callee saved registers. ESP is marked as
|
||||
// a use to prevent stack-pointer assignments that appear immediately
|
||||
// before calls from potentially appearing dead.
|
||||
let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0,
|
||||
MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7,
|
||||
XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
|
||||
XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS],
|
||||
Uses = [ESP] in
|
||||
def TLS_addr32 : I<0, Pseudo, (outs), (ins i32mem:$sym),
|
||||
"leal\t$sym, %eax; "
|
||||
"call\t___tls_get_addr@PLT",
|
||||
[(X86tlsaddr tls32addr:$sym)]>,
|
||||
Requires<[In32BitMode]>;
|
||||
|
||||
// All calls clobber the non-callee saved registers. RSP is marked as
|
||||
// a use to prevent stack-pointer assignments that appear immediately
|
||||
// before calls from potentially appearing dead.
|
||||
let Defs = [RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11,
|
||||
FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0, ST1,
|
||||
MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7,
|
||||
XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
|
||||
XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS],
|
||||
Uses = [RSP] in
|
||||
def TLS_addr64 : I<0, Pseudo, (outs), (ins i64mem:$sym),
|
||||
".byte\t0x66; "
|
||||
"leaq\t$sym(%rip), %rdi; "
|
||||
".word\t0x6666; "
|
||||
"rex64; "
|
||||
"call\t__tls_get_addr@PLT",
|
||||
[(X86tlsaddr tls64addr:$sym)]>,
|
||||
Requires<[In64BitMode]>;
|
||||
|
||||
// Darwin TLS Support
|
||||
// For i386, the address of the thunk is passed on the stack, on return the
|
||||
// address of the variable is in %eax. %ecx is trashed during the function
|
||||
// call. All other registers are preserved.
|
||||
let Defs = [EAX, ECX],
|
||||
Uses = [ESP],
|
||||
usesCustomInserter = 1 in
|
||||
def TLSCall_32 : I<0, Pseudo, (outs), (ins i32mem:$sym),
|
||||
"# TLSCall_32",
|
||||
[(X86TLSCall addr:$sym)]>,
|
||||
Requires<[In32BitMode]>;
|
||||
|
||||
// For x86_64, the address of the thunk is passed in %rdi, on return
|
||||
// the address of the variable is in %rax. All other registers are preserved.
|
||||
let Defs = [RAX],
|
||||
Uses = [RDI],
|
||||
usesCustomInserter = 1 in
|
||||
def TLSCall_64 : I<0, Pseudo, (outs), (ins i64mem:$sym),
|
||||
"# TLSCall_64",
|
||||
[(X86TLSCall addr:$sym)]>,
|
||||
Requires<[In64BitMode]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Non-Instruction Patterns
|
||||
|
@ -504,48 +504,6 @@ def or_is_add : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{
|
||||
// Instruction list.
|
||||
//
|
||||
|
||||
// ADJCALLSTACKDOWN/UP implicitly use/def ESP because they may be expanded into
|
||||
// a stack adjustment and the codegen must know that they may modify the stack
|
||||
// pointer before prolog-epilog rewriting occurs.
|
||||
// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become
|
||||
// sub / add which can clobber EFLAGS.
|
||||
let Defs = [ESP, EFLAGS], Uses = [ESP] in {
|
||||
def ADJCALLSTACKDOWN32 : I<0, Pseudo, (outs), (ins i32imm:$amt),
|
||||
"#ADJCALLSTACKDOWN",
|
||||
[(X86callseq_start timm:$amt)]>,
|
||||
Requires<[In32BitMode]>;
|
||||
def ADJCALLSTACKUP32 : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2),
|
||||
"#ADJCALLSTACKUP",
|
||||
[(X86callseq_end timm:$amt1, timm:$amt2)]>,
|
||||
Requires<[In32BitMode]>;
|
||||
}
|
||||
|
||||
// x86-64 va_start lowering magic.
|
||||
let usesCustomInserter = 1 in {
|
||||
def VASTART_SAVE_XMM_REGS : I<0, Pseudo,
|
||||
(outs),
|
||||
(ins GR8:$al,
|
||||
i64imm:$regsavefi, i64imm:$offset,
|
||||
variable_ops),
|
||||
"#VASTART_SAVE_XMM_REGS $al, $regsavefi, $offset",
|
||||
[(X86vastart_save_xmm_regs GR8:$al,
|
||||
imm:$regsavefi,
|
||||
imm:$offset)]>;
|
||||
|
||||
// Dynamic stack allocation yields _alloca call for Cygwin/Mingw targets. Calls
|
||||
// to _alloca is needed to probe the stack when allocating more than 4k bytes in
|
||||
// one go. Touching the stack at 4K increments is necessary to ensure that the
|
||||
// guard pages used by the OS virtual memory manager are allocated in correct
|
||||
// sequence.
|
||||
// The main point of having separate instruction are extra unmodelled effects
|
||||
// (compared to ordinary calls) like stack pointer change.
|
||||
|
||||
let Defs = [EAX, ESP, EFLAGS], Uses = [ESP] in
|
||||
def MINGW_ALLOCA : I<0, Pseudo, (outs), (ins),
|
||||
"# dynamic stack allocation",
|
||||
[(X86MingwAlloca)]>;
|
||||
}
|
||||
|
||||
// Nop
|
||||
let neverHasSideEffects = 1 in {
|
||||
def NOOP : I<0x90, RawFrm, (outs), (ins), "nop", []>;
|
||||
@ -555,13 +513,6 @@ let neverHasSideEffects = 1 in {
|
||||
"nop{l}\t$zero", []>, TB;
|
||||
}
|
||||
|
||||
// PIC base construction. This expands to code that looks like this:
|
||||
// call $next_inst
|
||||
// popl %destreg"
|
||||
let neverHasSideEffects = 1, isNotDuplicable = 1, Uses = [ESP] in
|
||||
def MOVPC32r : Ii32<0xE8, Pseudo, (outs GR32:$reg), (ins i32imm:$label),
|
||||
"", []>;
|
||||
|
||||
|
||||
// Constructing a stack frame.
|
||||
def ENTER : Ii16<0xC8, RawFrmImm8, (outs), (ins i16imm:$len, i8imm:$lvl),
|
||||
@ -3538,63 +3489,7 @@ let neverHasSideEffects = 1 in {
|
||||
"{cltd|cdq}", []>; // EDX:EAX = signext(EAX)
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Alias Instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Alias instructions that map movr0 to xor.
|
||||
// FIXME: remove when we can teach regalloc that xor reg, reg is ok.
|
||||
// FIXME: Set encoding to pseudo.
|
||||
let Defs = [EFLAGS], isReMaterializable = 1, isAsCheapAsAMove = 1,
|
||||
isCodeGenOnly = 1 in {
|
||||
def MOV8r0 : I<0x30, MRMInitReg, (outs GR8 :$dst), (ins), "",
|
||||
[(set GR8:$dst, 0)]>;
|
||||
|
||||
// We want to rewrite MOV16r0 in terms of MOV32r0, because it's a smaller
|
||||
// encoding and avoids a partial-register update sometimes, but doing so
|
||||
// at isel time interferes with rematerialization in the current register
|
||||
// allocator. For now, this is rewritten when the instruction is lowered
|
||||
// to an MCInst.
|
||||
def MOV16r0 : I<0x31, MRMInitReg, (outs GR16:$dst), (ins),
|
||||
"",
|
||||
[(set GR16:$dst, 0)]>, OpSize;
|
||||
|
||||
// FIXME: Set encoding to pseudo.
|
||||
def MOV32r0 : I<0x31, MRMInitReg, (outs GR32:$dst), (ins), "",
|
||||
[(set GR32:$dst, 0)]>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Thread Local Storage Instructions
|
||||
//
|
||||
|
||||
// ELF TLS Support
|
||||
// All calls clobber the non-callee saved registers. ESP is marked as
|
||||
// a use to prevent stack-pointer assignments that appear immediately
|
||||
// before calls from potentially appearing dead.
|
||||
let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0,
|
||||
MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7,
|
||||
XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
|
||||
XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS],
|
||||
Uses = [ESP] in
|
||||
def TLS_addr32 : I<0, Pseudo, (outs), (ins i32mem:$sym),
|
||||
"leal\t$sym, %eax; "
|
||||
"call\t___tls_get_addr@PLT",
|
||||
[(X86tlsaddr tls32addr:$sym)]>,
|
||||
Requires<[In32BitMode]>;
|
||||
|
||||
// Darwin TLS Support
|
||||
// For i386, the address of the thunk is passed on the stack, on return the
|
||||
// address of the variable is in %eax. %ecx is trashed during the function
|
||||
// call. All other registers are preserved.
|
||||
let Defs = [EAX, ECX],
|
||||
Uses = [ESP],
|
||||
usesCustomInserter = 1 in
|
||||
def TLSCall_32 : I<0, Pseudo, (outs), (ins i32mem:$sym),
|
||||
"# TLSCall_32",
|
||||
[(X86TLSCall addr:$sym)]>,
|
||||
Requires<[In32BitMode]>;
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Atomic support
|
||||
|
Loading…
x
Reference in New Issue
Block a user