s390x: use constraints for call arguments and return values (#5092)
Use the regalloc constraint-based CallArgList / CallRetList mechanism instead of directly using physregs in instructions.
This commit is contained in:
@@ -2900,11 +2900,8 @@
|
|||||||
(rule 1 (emit_memcpy dst src (len_minus_one len))
|
(rule 1 (emit_memcpy dst src (len_minus_one len))
|
||||||
(emit_side_effect (mvc (memarg_pair dst) (memarg_pair src) len)))
|
(emit_side_effect (mvc (memarg_pair dst) (memarg_pair src) len)))
|
||||||
(rule (emit_memcpy dst src len)
|
(rule (emit_memcpy dst src len)
|
||||||
(let ((libcall LibCallInfo (lib_call_info_memcpy))
|
(let ((libcall LibCallInfo (lib_call_info_memcpy (load_addr dst) (load_addr src) (imm $I64 len)))
|
||||||
(_ Unit (lib_accumulate_outgoing_args_size libcall))
|
(_ Unit (lib_accumulate_outgoing_args_size libcall)))
|
||||||
(_ Unit (emit_mov $I64 (writable_gpr 2) (load_addr dst)))
|
|
||||||
(_ Unit (emit_mov $I64 (writable_gpr 3) (load_addr src)))
|
|
||||||
(_ Unit (emit_imm $I64 (writable_gpr 4) len)))
|
|
||||||
(emit_side_effect (lib_call libcall))))
|
(emit_side_effect (lib_call libcall))))
|
||||||
|
|
||||||
;; Prepare a stack copy of a single (oversized) argument.
|
;; Prepare a stack copy of a single (oversized) argument.
|
||||||
@@ -2923,49 +2920,53 @@
|
|||||||
|
|
||||||
;; Copy a single argument/return value to its slots.
|
;; Copy a single argument/return value to its slots.
|
||||||
;; For oversized arguments, set the slot to the buffer address.
|
;; For oversized arguments, set the slot to the buffer address.
|
||||||
(decl copy_to_arg (LaneOrder i64 ABIArg Value) Unit)
|
(decl copy_to_arg (CallArgListBuilder LaneOrder i64 ABIArg Value) Unit)
|
||||||
(rule 2 (copy_to_arg lo base (abi_arg_only_slot slot) val)
|
(rule 2 (copy_to_arg uses lo base (abi_arg_only_slot slot) val)
|
||||||
(copy_val_to_arg_slot lo base slot val))
|
(copy_reg_to_arg_slot uses lo base slot (prepare_arg_val slot val)))
|
||||||
(rule 1 (copy_to_arg _ base (abi_arg_struct_pointer slot offset _) _)
|
(rule 1 (copy_to_arg uses lo base (abi_arg_struct_pointer slot offset _) _)
|
||||||
(let ((ptr Reg (load_addr (memarg_stack_off base offset))))
|
(let ((ptr Reg (load_addr (memarg_stack_off base offset))))
|
||||||
(copy_reg_to_arg_slot base slot ptr)))
|
(copy_reg_to_arg_slot uses lo base slot ptr)))
|
||||||
(rule 0 (copy_to_arg _ base (abi_arg_implicit_pointer slot offset _) _)
|
(rule 0 (copy_to_arg uses lo base (abi_arg_implicit_pointer slot offset _) _)
|
||||||
(let ((ptr Reg (load_addr (memarg_stack_off base offset))))
|
(let ((ptr Reg (load_addr (memarg_stack_off base offset))))
|
||||||
(copy_reg_to_arg_slot base slot ptr)))
|
(copy_reg_to_arg_slot uses lo base slot ptr)))
|
||||||
|
|
||||||
;; Copy a single argument/return value from its slots.
|
;; Copy a single argument/return value from its slots.
|
||||||
(decl copy_from_arg (LaneOrder i64 ABIArg) ValueRegs)
|
(decl copy_from_arg (CallRetList LaneOrder i64 ABIArg) ValueRegs)
|
||||||
(rule (copy_from_arg lo base (abi_arg_only_slot slot))
|
(rule (copy_from_arg defs lo base (abi_arg_only_slot slot))
|
||||||
(value_reg (copy_reg_from_arg_slot lo base slot)))
|
(value_reg (copy_reg_from_arg_slot defs lo base slot)))
|
||||||
|
|
||||||
;; Copy one component of an argument/return value to its slot.
|
;; Place one component of an argument/return value into a register.
|
||||||
(decl copy_val_to_arg_slot (LaneOrder i64 ABIArgSlot Value) Unit)
|
;; Copy reference values into registers of integer type.
|
||||||
(rule (copy_val_to_arg_slot lo _ (ABIArgSlot.Reg reg ty (ArgumentExtension.None)) val)
|
;; Zero- or sign-extend as required by the ABI.
|
||||||
(emit_mov ty (real_reg_to_writable_reg reg) (abi_vec_elt_rev lo ty val)))
|
(decl prepare_arg_val (ABIArgSlot Value) Reg)
|
||||||
(rule (copy_val_to_arg_slot _ _ (ABIArgSlot.Reg reg _ (ArgumentExtension.Uext)) val)
|
(rule 1 (prepare_arg_val (ABIArgSlot.Reg _ $R64 (ArgumentExtension.None)) val)
|
||||||
(emit_put_in_reg_zext64 (real_reg_to_writable_reg reg) val))
|
(copy_reg $I64 val))
|
||||||
(rule (copy_val_to_arg_slot _ _ (ABIArgSlot.Reg reg _ (ArgumentExtension.Sext)) val)
|
(rule (prepare_arg_val (ABIArgSlot.Reg _ _ (ArgumentExtension.None)) val)
|
||||||
(emit_put_in_reg_sext64 (real_reg_to_writable_reg reg) val))
|
val)
|
||||||
(rule (copy_val_to_arg_slot _ base (ABIArgSlot.Stack offset ty (ArgumentExtension.None)) val)
|
(rule (prepare_arg_val (ABIArgSlot.Reg _ _ (ArgumentExtension.Uext)) val)
|
||||||
(emit_arg_store ty val (memarg_stack_off base offset)))
|
(put_in_reg_zext64 val))
|
||||||
(rule (copy_val_to_arg_slot _ base (ABIArgSlot.Stack offset _ (ArgumentExtension.Uext)) val)
|
(rule (prepare_arg_val (ABIArgSlot.Reg _ _ (ArgumentExtension.Sext)) val)
|
||||||
(emit_arg_store $I64 (put_in_reg_zext64 val) (memarg_stack_off base offset)))
|
(put_in_reg_sext64 val))
|
||||||
(rule (copy_val_to_arg_slot _ base (ABIArgSlot.Stack offset _ (ArgumentExtension.Sext)) val)
|
(rule (prepare_arg_val (ABIArgSlot.Stack _ _ (ArgumentExtension.None)) val)
|
||||||
(emit_arg_store $I64 (put_in_reg_sext64 val) (memarg_stack_off base offset)))
|
val)
|
||||||
|
(rule (prepare_arg_val (ABIArgSlot.Stack _ _ (ArgumentExtension.Uext)) val)
|
||||||
|
(put_in_reg_zext64 val))
|
||||||
|
(rule (prepare_arg_val (ABIArgSlot.Stack _ _ (ArgumentExtension.Sext)) val)
|
||||||
|
(put_in_reg_sext64 val))
|
||||||
|
|
||||||
;; Copy one component of an argument/return value to its slot, where the
|
;; Copy one component of an argument/return value to its slot, where the
|
||||||
;; value is already extended and present in a register.
|
;; value is already extended and present in a register.
|
||||||
(decl copy_reg_to_arg_slot (i64 ABIArgSlot Reg) Unit)
|
(decl copy_reg_to_arg_slot (CallArgListBuilder LaneOrder i64 ABIArgSlot Reg) Unit)
|
||||||
(rule (copy_reg_to_arg_slot _ (ABIArgSlot.Reg reg ty ext) src)
|
(rule (copy_reg_to_arg_slot uses lo _ (ABIArgSlot.Reg reg ty ext) src)
|
||||||
(emit_mov (abi_ext_ty ext ty) (real_reg_to_writable_reg reg) src))
|
(args_builder_push uses (abi_vec_elt_rev lo ty src) reg))
|
||||||
(rule (copy_reg_to_arg_slot base (ABIArgSlot.Stack offset ty ext) src)
|
(rule (copy_reg_to_arg_slot _ _ base (ABIArgSlot.Stack offset ty ext) src)
|
||||||
(emit_arg_store (abi_ext_ty ext ty) src (memarg_stack_off base offset)))
|
(emit_arg_store (abi_ext_ty ext ty) src (memarg_stack_off base offset)))
|
||||||
|
|
||||||
;; Copy one component of an argument/return value from its slot.
|
;; Copy one component of an argument/return value from its slot.
|
||||||
(decl copy_reg_from_arg_slot (LaneOrder i64 ABIArgSlot) Reg)
|
(decl copy_reg_from_arg_slot (CallRetList LaneOrder i64 ABIArgSlot) Reg)
|
||||||
(rule (copy_reg_from_arg_slot lo _ (ABIArgSlot.Reg reg ty ext))
|
(rule (copy_reg_from_arg_slot defs lo _ (ABIArgSlot.Reg reg ty ext))
|
||||||
(abi_vec_elt_rev lo ty (copy_reg (abi_ext_ty ext ty) (real_reg_to_reg reg))))
|
(abi_vec_elt_rev lo ty (defs_lookup defs reg)))
|
||||||
(rule (copy_reg_from_arg_slot _ base (ABIArgSlot.Stack offset ty ext))
|
(rule (copy_reg_from_arg_slot _ _ base (ABIArgSlot.Stack offset ty ext))
|
||||||
(emit_arg_load (abi_ext_ty ext ty) (memarg_stack_off base offset)))
|
(emit_arg_load (abi_ext_ty ext ty) (memarg_stack_off base offset)))
|
||||||
|
|
||||||
;; Helper to compute the type of an implicitly extended argument/return value.
|
;; Helper to compute the type of an implicitly extended argument/return value.
|
||||||
@@ -3574,25 +3575,54 @@
|
|||||||
|
|
||||||
;; Helpers for generating `call` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;; Helpers for generating `call` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
;; List of argument registers for a call instruction.
|
||||||
|
(type CallArgList extern (enum))
|
||||||
|
|
||||||
|
;; Partial (mutable) argument list in the process of being created.
|
||||||
|
(type CallArgListBuilder extern (enum))
|
||||||
|
|
||||||
|
;; Create a new empty instruction sequence builder.
|
||||||
|
(decl args_builder_new () CallArgListBuilder)
|
||||||
|
(extern constructor args_builder_new args_builder_new)
|
||||||
|
|
||||||
|
;; Push an instruction to a sequence under construction.
|
||||||
|
(decl args_builder_push (CallArgListBuilder Reg RealReg) Unit)
|
||||||
|
(extern constructor args_builder_push args_builder_push)
|
||||||
|
|
||||||
|
;; Complete the sequence under construction.
|
||||||
|
(decl args_builder_finish (CallArgListBuilder) CallArgList)
|
||||||
|
(extern constructor args_builder_finish args_builder_finish)
|
||||||
|
|
||||||
|
;; List of return registers for a call instnuction.
|
||||||
|
(type CallRetList extern (enum))
|
||||||
|
|
||||||
|
;; Initialize return register list.
|
||||||
|
(decl defs_init (Sig) CallRetList)
|
||||||
|
(extern constructor defs_init defs_init)
|
||||||
|
|
||||||
|
;; Look up return register in list.
|
||||||
|
(decl defs_lookup (CallRetList RealReg) Reg)
|
||||||
|
(extern constructor defs_lookup defs_lookup)
|
||||||
|
|
||||||
(decl abi_sig (SigRef) Sig)
|
(decl abi_sig (SigRef) Sig)
|
||||||
(extern constructor abi_sig abi_sig)
|
(extern constructor abi_sig abi_sig)
|
||||||
|
|
||||||
(decl abi_call_info (Sig ExternalName Opcode) BoxCallInfo)
|
(decl abi_call_info (Sig ExternalName CallArgList CallRetList Opcode) BoxCallInfo)
|
||||||
(extern constructor abi_call_info abi_call_info)
|
(extern constructor abi_call_info abi_call_info)
|
||||||
|
|
||||||
(decl abi_call_ind_info (Sig Reg Opcode) BoxCallIndInfo)
|
(decl abi_call_ind_info (Sig Reg CallArgList CallRetList Opcode) BoxCallIndInfo)
|
||||||
(extern constructor abi_call_ind_info abi_call_ind_info)
|
(extern constructor abi_call_ind_info abi_call_ind_info)
|
||||||
|
|
||||||
(decl writable_link_reg () WritableReg)
|
(decl writable_link_reg () WritableReg)
|
||||||
(rule (writable_link_reg) (writable_gpr 14))
|
(rule (writable_link_reg) (writable_gpr 14))
|
||||||
|
|
||||||
(decl abi_call (Sig ExternalName Opcode) SideEffectNoResult)
|
(decl abi_call (Sig ExternalName CallArgList CallRetList Opcode) SideEffectNoResult)
|
||||||
(rule (abi_call abi name opcode)
|
(rule (abi_call abi name uses defs opcode)
|
||||||
(call_impl (writable_link_reg) (abi_call_info abi name opcode)))
|
(call_impl (writable_link_reg) (abi_call_info abi name uses defs opcode)))
|
||||||
|
|
||||||
(decl abi_call_ind (Sig Reg Opcode) SideEffectNoResult)
|
(decl abi_call_ind (Sig Reg CallArgList CallRetList Opcode) SideEffectNoResult)
|
||||||
(rule (abi_call_ind abi target opcode)
|
(rule (abi_call_ind abi target uses defs opcode)
|
||||||
(call_ind_impl (writable_link_reg) (abi_call_ind_info abi target opcode)))
|
(call_ind_impl (writable_link_reg) (abi_call_ind_info abi target uses defs opcode)))
|
||||||
|
|
||||||
(decl abi_accumulate_outgoing_args_size (Sig) Unit)
|
(decl abi_accumulate_outgoing_args_size (Sig) Unit)
|
||||||
(extern constructor abi_accumulate_outgoing_args_size abi_accumulate_outgoing_args_size)
|
(extern constructor abi_accumulate_outgoing_args_size abi_accumulate_outgoing_args_size)
|
||||||
@@ -3605,10 +3635,10 @@
|
|||||||
|
|
||||||
(type LibCallInfo extern (enum))
|
(type LibCallInfo extern (enum))
|
||||||
|
|
||||||
(decl lib_call_info_memcpy () LibCallInfo)
|
(decl lib_call_info_memcpy (Reg Reg Reg) LibCallInfo)
|
||||||
(extern constructor lib_call_info_memcpy lib_call_info_memcpy)
|
(extern constructor lib_call_info_memcpy lib_call_info_memcpy)
|
||||||
|
|
||||||
(decl lib_call_info_tls_get_offset (SymbolReloc) LibCallInfo)
|
(decl lib_call_info_tls_get_offset (WritableReg Reg Reg SymbolReloc) LibCallInfo)
|
||||||
(extern constructor lib_call_info_tls_get_offset lib_call_info_tls_get_offset)
|
(extern constructor lib_call_info_tls_get_offset lib_call_info_tls_get_offset)
|
||||||
|
|
||||||
(decl lib_call_info (LibCallInfo) BoxCallInfo)
|
(decl lib_call_info (LibCallInfo) BoxCallInfo)
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ pub use crate::isa::s390x::lower::isle::generated_code::{
|
|||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct CallInfo {
|
pub struct CallInfo {
|
||||||
pub dest: ExternalName,
|
pub dest: ExternalName,
|
||||||
pub uses: SmallVec<[Reg; 8]>,
|
pub uses: CallArgList,
|
||||||
pub defs: SmallVec<[Writable<Reg>; 8]>,
|
pub defs: CallRetList,
|
||||||
pub clobbers: PRegSet,
|
pub clobbers: PRegSet,
|
||||||
pub opcode: Opcode,
|
pub opcode: Opcode,
|
||||||
pub caller_callconv: CallConv,
|
pub caller_callconv: CallConv,
|
||||||
@@ -53,8 +53,8 @@ pub struct CallInfo {
|
|||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct CallIndInfo {
|
pub struct CallIndInfo {
|
||||||
pub rn: Reg,
|
pub rn: Reg,
|
||||||
pub uses: SmallVec<[Reg; 8]>,
|
pub uses: CallArgList,
|
||||||
pub defs: SmallVec<[Writable<Reg>; 8]>,
|
pub defs: CallRetList,
|
||||||
pub clobbers: PRegSet,
|
pub clobbers: PRegSet,
|
||||||
pub opcode: Opcode,
|
pub opcode: Opcode,
|
||||||
pub caller_callconv: CallConv,
|
pub caller_callconv: CallConv,
|
||||||
@@ -1004,15 +1004,23 @@ fn s390x_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandC
|
|||||||
}
|
}
|
||||||
&Inst::Call { link, ref info } => {
|
&Inst::Call { link, ref info } => {
|
||||||
collector.reg_def(link);
|
collector.reg_def(link);
|
||||||
collector.reg_uses(&*info.uses);
|
for u in &info.uses {
|
||||||
collector.reg_defs(&*info.defs);
|
collector.reg_fixed_use(u.vreg, u.preg);
|
||||||
|
}
|
||||||
|
for d in &info.defs {
|
||||||
|
collector.reg_fixed_def(d.vreg, d.preg);
|
||||||
|
}
|
||||||
collector.reg_clobbers(info.clobbers);
|
collector.reg_clobbers(info.clobbers);
|
||||||
}
|
}
|
||||||
&Inst::CallInd { link, ref info } => {
|
&Inst::CallInd { link, ref info } => {
|
||||||
collector.reg_def(link);
|
collector.reg_def(link);
|
||||||
collector.reg_use(info.rn);
|
collector.reg_use(info.rn);
|
||||||
collector.reg_uses(&*info.uses);
|
for u in &info.uses {
|
||||||
collector.reg_defs(&*info.defs);
|
collector.reg_fixed_use(u.vreg, u.preg);
|
||||||
|
}
|
||||||
|
for d in &info.defs {
|
||||||
|
collector.reg_fixed_def(d.vreg, d.preg);
|
||||||
|
}
|
||||||
collector.reg_clobbers(info.clobbers);
|
collector.reg_clobbers(info.clobbers);
|
||||||
}
|
}
|
||||||
&Inst::Args { ref args } => {
|
&Inst::Args { ref args } => {
|
||||||
|
|||||||
@@ -2283,12 +2283,11 @@
|
|||||||
;; Helper to perform a call to the __tls_get_offset library routine.
|
;; Helper to perform a call to the __tls_get_offset library routine.
|
||||||
(decl lib_call_tls_get_offset (Reg Reg SymbolReloc) Reg)
|
(decl lib_call_tls_get_offset (Reg Reg SymbolReloc) Reg)
|
||||||
(rule (lib_call_tls_get_offset got got_offset symbol)
|
(rule (lib_call_tls_get_offset got got_offset symbol)
|
||||||
(let ((libcall LibCallInfo (lib_call_info_tls_get_offset symbol))
|
(let ((tls_offset WritableReg (temp_writable_reg $I64))
|
||||||
|
(libcall LibCallInfo (lib_call_info_tls_get_offset tls_offset got got_offset symbol))
|
||||||
(_ Unit (lib_accumulate_outgoing_args_size libcall))
|
(_ Unit (lib_accumulate_outgoing_args_size libcall))
|
||||||
(_ Unit (emit_mov $I64 (writable_gpr 12) got))
|
|
||||||
(_ Unit (emit_mov $I64 (writable_gpr 2) got_offset))
|
|
||||||
(_ Unit (emit_side_effect (lib_call libcall))))
|
(_ Unit (emit_side_effect (lib_call libcall))))
|
||||||
(copy_reg $I64 (writable_gpr 2))))
|
tls_offset))
|
||||||
|
|
||||||
;; Helper to extract the current thread pointer from %a0/%a1.
|
;; Helper to extract the current thread pointer from %a0/%a1.
|
||||||
(decl thread_pointer () Reg)
|
(decl thread_pointer () Reg)
|
||||||
@@ -3905,34 +3904,39 @@
|
|||||||
(rule 1 (lower (call (func_ref_data sig_ref name (reloc_distance_near)) args))
|
(rule 1 (lower (call (func_ref_data sig_ref name (reloc_distance_near)) args))
|
||||||
(let ((abi Sig (abi_sig sig_ref))
|
(let ((abi Sig (abi_sig sig_ref))
|
||||||
(_ Unit (abi_accumulate_outgoing_args_size abi))
|
(_ Unit (abi_accumulate_outgoing_args_size abi))
|
||||||
(_ InstOutput (lower_call_args abi (range 0 (abi_num_args abi)) args))
|
(uses CallArgList (lower_call_args abi (range 0 (abi_num_args abi)) args))
|
||||||
(_ InstOutput (side_effect (abi_call abi name (Opcode.Call)))))
|
(defs CallRetList (defs_init abi))
|
||||||
(lower_call_rets abi (range 0 (abi_num_rets abi)) (output_builder_new))))
|
(_ InstOutput (side_effect (abi_call abi name uses defs (Opcode.Call)))))
|
||||||
|
(lower_call_rets abi defs (range 0 (abi_num_rets abi)) (output_builder_new))))
|
||||||
|
|
||||||
;; Direct call to an out-of-range function (implicitly via pointer).
|
;; Direct call to an out-of-range function (implicitly via pointer).
|
||||||
(rule (lower (call (func_ref_data sig_ref name _) args))
|
(rule (lower (call (func_ref_data sig_ref name _) args))
|
||||||
(let ((abi Sig (abi_sig sig_ref))
|
(let ((abi Sig (abi_sig sig_ref))
|
||||||
(_ Unit (abi_accumulate_outgoing_args_size abi))
|
(_ Unit (abi_accumulate_outgoing_args_size abi))
|
||||||
(_ InstOutput (lower_call_args abi (range 0 (abi_num_args abi)) args))
|
(uses CallArgList (lower_call_args abi (range 0 (abi_num_args abi)) args))
|
||||||
|
(defs CallRetList (defs_init abi))
|
||||||
(target Reg (load_symbol_reloc (SymbolReloc.Absolute name 0)))
|
(target Reg (load_symbol_reloc (SymbolReloc.Absolute name 0)))
|
||||||
(_ InstOutput (side_effect (abi_call_ind abi target (Opcode.Call)))))
|
(_ InstOutput (side_effect (abi_call_ind abi target uses defs (Opcode.Call)))))
|
||||||
(lower_call_rets abi (range 0 (abi_num_rets abi)) (output_builder_new))))
|
(lower_call_rets abi defs (range 0 (abi_num_rets abi)) (output_builder_new))))
|
||||||
|
|
||||||
;; Indirect call.
|
;; Indirect call.
|
||||||
(rule (lower (call_indirect sig_ref ptr args))
|
(rule (lower (call_indirect sig_ref ptr args))
|
||||||
(let ((abi Sig (abi_sig sig_ref))
|
(let ((abi Sig (abi_sig sig_ref))
|
||||||
(target Reg (put_in_reg ptr))
|
(target Reg (put_in_reg ptr))
|
||||||
(_ Unit (abi_accumulate_outgoing_args_size abi))
|
(_ Unit (abi_accumulate_outgoing_args_size abi))
|
||||||
(_ InstOutput (lower_call_args abi (range 0 (abi_num_args abi)) args))
|
(uses CallArgList (lower_call_args abi (range 0 (abi_num_args abi)) args))
|
||||||
(_ InstOutput (side_effect (abi_call_ind abi target (Opcode.CallIndirect)))))
|
(defs CallRetList (defs_init abi))
|
||||||
(lower_call_rets abi (range 0 (abi_num_rets abi)) (output_builder_new))))
|
(_ InstOutput (side_effect (abi_call_ind abi target uses defs (Opcode.CallIndirect)))))
|
||||||
|
(lower_call_rets abi defs (range 0 (abi_num_rets abi)) (output_builder_new))))
|
||||||
|
|
||||||
;; Lower function arguments.
|
;; Lower function arguments.
|
||||||
(decl lower_call_args (Sig Range ValueSlice) InstOutput)
|
(decl lower_call_args (Sig Range ValueSlice) CallArgList)
|
||||||
(rule (lower_call_args abi range args)
|
(rule (lower_call_args abi range args)
|
||||||
(let ((_ InstOutput (lower_call_args_buffer abi range args))
|
(let ((uses CallArgListBuilder (args_builder_new))
|
||||||
(_ InstOutput (lower_call_args_slots abi range args)))
|
(_ InstOutput (lower_call_args_buffer abi range args))
|
||||||
(lower_call_ret_arg abi)))
|
(_ InstOutput (lower_call_args_slots abi uses range args))
|
||||||
|
(_ InstOutput (lower_call_ret_arg abi uses)))
|
||||||
|
(args_builder_finish uses)))
|
||||||
|
|
||||||
;; Lower function arguments (part 1): prepare buffer copies.
|
;; Lower function arguments (part 1): prepare buffer copies.
|
||||||
(decl lower_call_args_buffer (Sig Range ValueSlice) InstOutput)
|
(decl lower_call_args_buffer (Sig Range ValueSlice) InstOutput)
|
||||||
@@ -3943,31 +3947,31 @@
|
|||||||
(lower_call_args_buffer abi tail args)))
|
(lower_call_args_buffer abi tail args)))
|
||||||
|
|
||||||
;; Lower function arguments (part 2): set up registers / stack slots.
|
;; Lower function arguments (part 2): set up registers / stack slots.
|
||||||
(decl lower_call_args_slots (Sig Range ValueSlice) InstOutput)
|
(decl lower_call_args_slots (Sig CallArgListBuilder Range ValueSlice) InstOutput)
|
||||||
(rule (lower_call_args_slots abi (range_empty) _) (output_none))
|
(rule (lower_call_args_slots abi _ (range_empty) _) (output_none))
|
||||||
(rule (lower_call_args_slots abi (range_unwrap head tail) args)
|
(rule (lower_call_args_slots abi uses (range_unwrap head tail) args)
|
||||||
(let ((_ Unit (copy_to_arg (abi_lane_order abi)
|
(let ((_ Unit (copy_to_arg uses (abi_lane_order abi)
|
||||||
0 (abi_get_arg abi head)
|
0 (abi_get_arg abi head)
|
||||||
(value_slice_get args head))))
|
(value_slice_get args head))))
|
||||||
(lower_call_args_slots abi tail args)))
|
(lower_call_args_slots abi uses tail args)))
|
||||||
|
|
||||||
;; Lower function arguments (part 3): implicit return-area pointer.
|
;; Lower function arguments (part 3): implicit return-area pointer.
|
||||||
(decl lower_call_ret_arg (Sig) InstOutput)
|
(decl lower_call_ret_arg (Sig CallArgListBuilder) InstOutput)
|
||||||
(rule (lower_call_ret_arg (abi_no_ret_arg)) (output_none))
|
(rule (lower_call_ret_arg (abi_no_ret_arg) _) (output_none))
|
||||||
(rule 1 (lower_call_ret_arg abi @ (abi_ret_arg (abi_arg_only_slot slot)))
|
(rule 1 (lower_call_ret_arg abi @ (abi_ret_arg (abi_arg_only_slot slot)) uses)
|
||||||
(let ((ret_arg Reg (load_addr (memarg_stack_off (abi_sized_stack_arg_space abi) 0)))
|
(let ((ret_arg Reg (load_addr (memarg_stack_off (abi_sized_stack_arg_space abi) 0)))
|
||||||
(_ Unit (copy_reg_to_arg_slot 0 slot ret_arg)))
|
(_ Unit (copy_reg_to_arg_slot uses (abi_lane_order abi) 0 slot ret_arg)))
|
||||||
(output_none)))
|
(output_none)))
|
||||||
|
|
||||||
;; Lower function return values by collecting them from registers / stack slots.
|
;; Lower function return values by collecting them from registers / stack slots.
|
||||||
(decl lower_call_rets (Sig Range InstOutputBuilder) InstOutput)
|
(decl lower_call_rets (Sig CallRetList Range InstOutputBuilder) InstOutput)
|
||||||
(rule (lower_call_rets abi (range_empty) builder) (output_builder_finish builder))
|
(rule (lower_call_rets abi _ (range_empty) builder) (output_builder_finish builder))
|
||||||
(rule (lower_call_rets abi (range_unwrap head tail) builder)
|
(rule (lower_call_rets abi defs (range_unwrap head tail) builder)
|
||||||
(let ((ret ValueRegs (copy_from_arg (abi_lane_order abi)
|
(let ((ret ValueRegs (copy_from_arg defs (abi_lane_order abi)
|
||||||
(abi_sized_stack_arg_space abi)
|
(abi_sized_stack_arg_space abi)
|
||||||
(abi_get_ret abi head)))
|
(abi_get_ret abi head)))
|
||||||
(_ Unit (output_builder_push builder ret)))
|
(_ Unit (output_builder_push builder ret)))
|
||||||
(lower_call_rets abi tail builder)))
|
(lower_call_rets abi defs tail builder)))
|
||||||
|
|
||||||
;;;; Rules for `get_{frame,stack}_pointer` and `get_return_address` ;;;;;;;;;;;;
|
;;;; Rules for `get_{frame,stack}_pointer` and `get_return_address` ;;;;;;;;;;;;
|
||||||
|
|
||||||
|
|||||||
@@ -17,17 +17,20 @@ use crate::machinst::{MachLabel, Reg};
|
|||||||
use crate::settings::Flags;
|
use crate::settings::Flags;
|
||||||
use crate::{
|
use crate::{
|
||||||
ir::{
|
ir::{
|
||||||
condcodes::*, immediates::*, types::*, AtomicRmwOp, Endianness, Inst, InstructionData,
|
condcodes::*, immediates::*, types::*, ArgumentPurpose, AtomicRmwOp, Endianness, Inst,
|
||||||
KnownSymbol, LibCall, MemFlags, Opcode, TrapCode, Value, ValueList,
|
InstructionData, KnownSymbol, LibCall, MemFlags, Opcode, TrapCode, Value, ValueList,
|
||||||
},
|
},
|
||||||
isa::unwind::UnwindInst,
|
isa::unwind::UnwindInst,
|
||||||
isa::CallConv,
|
isa::CallConv,
|
||||||
machinst::abi::ABIMachineSpec,
|
machinst::abi::ABIMachineSpec,
|
||||||
machinst::{ArgPair, InsnOutput, Lower, MachInst, VCodeConstant, VCodeConstantData},
|
machinst::{
|
||||||
|
ArgPair, CallArgList, CallArgPair, CallRetList, CallRetPair, InsnOutput, Lower, MachInst,
|
||||||
|
VCodeConstant, VCodeConstantData,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use crate::{isle_common_prelude_methods, isle_lower_prelude_methods};
|
use crate::{isle_common_prelude_methods, isle_lower_prelude_methods};
|
||||||
use regalloc2::PReg;
|
use regalloc2::PReg;
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::smallvec;
|
||||||
use std::boxed::Box;
|
use std::boxed::Box;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
@@ -37,6 +40,8 @@ use target_lexicon::Triple;
|
|||||||
/// Information describing a library call to be emitted.
|
/// Information describing a library call to be emitted.
|
||||||
pub struct LibCallInfo {
|
pub struct LibCallInfo {
|
||||||
libcall: LibCall,
|
libcall: LibCall,
|
||||||
|
uses: CallArgList,
|
||||||
|
defs: CallRetList,
|
||||||
tls_symbol: Option<SymbolReloc>,
|
tls_symbol: Option<SymbolReloc>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,6 +53,7 @@ type BoxSymbolReloc = Box<SymbolReloc>;
|
|||||||
type VecMInst = Vec<MInst>;
|
type VecMInst = Vec<MInst>;
|
||||||
type VecMInstBuilder = Cell<Vec<MInst>>;
|
type VecMInstBuilder = Cell<Vec<MInst>>;
|
||||||
type VecArgPair = Vec<ArgPair>;
|
type VecArgPair = Vec<ArgPair>;
|
||||||
|
type CallArgListBuilder = Cell<CallArgList>;
|
||||||
|
|
||||||
/// The main entry point for lowering with ISLE.
|
/// The main entry point for lowering with ISLE.
|
||||||
pub(crate) fn lower(
|
pub(crate) fn lower(
|
||||||
@@ -92,6 +98,69 @@ pub(crate) fn lower_branch(
|
|||||||
impl generated_code::Context for IsleContext<'_, '_, MInst, Flags, IsaFlags, 6> {
|
impl generated_code::Context for IsleContext<'_, '_, MInst, Flags, IsaFlags, 6> {
|
||||||
isle_lower_prelude_methods!();
|
isle_lower_prelude_methods!();
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn args_builder_new(&mut self) -> CallArgListBuilder {
|
||||||
|
Cell::new(CallArgList::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn args_builder_push(
|
||||||
|
&mut self,
|
||||||
|
builder: &CallArgListBuilder,
|
||||||
|
vreg: Reg,
|
||||||
|
preg: RealReg,
|
||||||
|
) -> Unit {
|
||||||
|
let mut args = builder.take();
|
||||||
|
args.push(CallArgPair {
|
||||||
|
vreg,
|
||||||
|
preg: preg.into(),
|
||||||
|
});
|
||||||
|
builder.set(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn args_builder_finish(&mut self, builder: &CallArgListBuilder) -> CallArgList {
|
||||||
|
builder.take()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn defs_init(&mut self, abi: &Sig) -> CallRetList {
|
||||||
|
// Allocate writable registers for all retval regs, except for StructRet args.
|
||||||
|
let mut defs = smallvec![];
|
||||||
|
for i in 0..self.lower_ctx.sigs()[*abi].num_rets() {
|
||||||
|
if let &ABIArg::Slots {
|
||||||
|
ref slots, purpose, ..
|
||||||
|
} = &self.lower_ctx.sigs()[*abi].get_ret(i)
|
||||||
|
{
|
||||||
|
if purpose == ArgumentPurpose::StructReturn {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for slot in slots {
|
||||||
|
match slot {
|
||||||
|
&ABIArgSlot::Reg { reg, ty, .. } => {
|
||||||
|
let value_regs = self.lower_ctx.alloc_tmp(ty);
|
||||||
|
defs.push(CallRetPair {
|
||||||
|
vreg: value_regs.only_reg().unwrap(),
|
||||||
|
preg: reg.into(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defs
|
||||||
|
}
|
||||||
|
|
||||||
|
fn defs_lookup(&mut self, defs: &CallRetList, reg: RealReg) -> Reg {
|
||||||
|
let reg = Reg::from(reg);
|
||||||
|
for def in defs {
|
||||||
|
if def.preg == reg {
|
||||||
|
return def.vreg.to_reg();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
fn abi_sig(&mut self, sig_ref: SigRef) -> Sig {
|
fn abi_sig(&mut self, sig_ref: SigRef) -> Sig {
|
||||||
self.lower_ctx.sigs().abi_sig_for_sig_ref(sig_ref)
|
self.lower_ctx.sigs().abi_sig_for_sig_ref(sig_ref)
|
||||||
}
|
}
|
||||||
@@ -108,13 +177,19 @@ impl generated_code::Context for IsleContext<'_, '_, MInst, Flags, IsaFlags, 6>
|
|||||||
.accumulate_outgoing_args_size(off as u32);
|
.accumulate_outgoing_args_size(off as u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn abi_call_info(&mut self, abi: &Sig, name: ExternalName, opcode: &Opcode) -> BoxCallInfo {
|
fn abi_call_info(
|
||||||
let (uses, defs, clobbers) =
|
&mut self,
|
||||||
self.lower_ctx.sigs()[*abi].call_uses_defs_clobbers::<S390xMachineDeps>();
|
abi: &Sig,
|
||||||
|
name: ExternalName,
|
||||||
|
uses: &CallArgList,
|
||||||
|
defs: &CallRetList,
|
||||||
|
opcode: &Opcode,
|
||||||
|
) -> BoxCallInfo {
|
||||||
|
let clobbers = self.lower_ctx.sigs()[*abi].call_clobbers::<S390xMachineDeps>();
|
||||||
Box::new(CallInfo {
|
Box::new(CallInfo {
|
||||||
dest: name.clone(),
|
dest: name.clone(),
|
||||||
uses,
|
uses: uses.clone(),
|
||||||
defs,
|
defs: defs.clone(),
|
||||||
clobbers,
|
clobbers,
|
||||||
opcode: *opcode,
|
opcode: *opcode,
|
||||||
caller_callconv: self.lower_ctx.abi().call_conv(self.lower_ctx.sigs()),
|
caller_callconv: self.lower_ctx.abi().call_conv(self.lower_ctx.sigs()),
|
||||||
@@ -123,13 +198,19 @@ impl generated_code::Context for IsleContext<'_, '_, MInst, Flags, IsaFlags, 6>
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn abi_call_ind_info(&mut self, abi: &Sig, target: Reg, opcode: &Opcode) -> BoxCallIndInfo {
|
fn abi_call_ind_info(
|
||||||
let (uses, defs, clobbers) =
|
&mut self,
|
||||||
self.lower_ctx.sigs()[*abi].call_uses_defs_clobbers::<S390xMachineDeps>();
|
abi: &Sig,
|
||||||
|
target: Reg,
|
||||||
|
uses: &CallArgList,
|
||||||
|
defs: &CallRetList,
|
||||||
|
opcode: &Opcode,
|
||||||
|
) -> BoxCallIndInfo {
|
||||||
|
let clobbers = self.lower_ctx.sigs()[*abi].call_clobbers::<S390xMachineDeps>();
|
||||||
Box::new(CallIndInfo {
|
Box::new(CallIndInfo {
|
||||||
rn: target,
|
rn: target,
|
||||||
uses,
|
uses: uses.clone(),
|
||||||
defs,
|
defs: defs.clone(),
|
||||||
clobbers,
|
clobbers,
|
||||||
opcode: *opcode,
|
opcode: *opcode,
|
||||||
caller_callconv: self.lower_ctx.abi().call_conv(self.lower_ctx.sigs()),
|
caller_callconv: self.lower_ctx.abi().call_conv(self.lower_ctx.sigs()),
|
||||||
@@ -137,16 +218,51 @@ impl generated_code::Context for IsleContext<'_, '_, MInst, Flags, IsaFlags, 6>
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lib_call_info_memcpy(&mut self) -> LibCallInfo {
|
fn lib_call_info_memcpy(&mut self, dst: Reg, src: Reg, len: Reg) -> LibCallInfo {
|
||||||
LibCallInfo {
|
LibCallInfo {
|
||||||
libcall: LibCall::Memcpy,
|
libcall: LibCall::Memcpy,
|
||||||
|
uses: smallvec![
|
||||||
|
CallArgPair {
|
||||||
|
vreg: dst,
|
||||||
|
preg: gpr(2),
|
||||||
|
},
|
||||||
|
CallArgPair {
|
||||||
|
vreg: src,
|
||||||
|
preg: gpr(3),
|
||||||
|
},
|
||||||
|
CallArgPair {
|
||||||
|
vreg: len,
|
||||||
|
preg: gpr(4),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
defs: smallvec![],
|
||||||
tls_symbol: None,
|
tls_symbol: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lib_call_info_tls_get_offset(&mut self, tls_symbol: &SymbolReloc) -> LibCallInfo {
|
fn lib_call_info_tls_get_offset(
|
||||||
|
&mut self,
|
||||||
|
tls_offset: WritableReg,
|
||||||
|
got: Reg,
|
||||||
|
got_offset: Reg,
|
||||||
|
tls_symbol: &SymbolReloc,
|
||||||
|
) -> LibCallInfo {
|
||||||
LibCallInfo {
|
LibCallInfo {
|
||||||
libcall: LibCall::ElfTlsGetOffset,
|
libcall: LibCall::ElfTlsGetOffset,
|
||||||
|
uses: smallvec![
|
||||||
|
CallArgPair {
|
||||||
|
vreg: got,
|
||||||
|
preg: gpr(12),
|
||||||
|
},
|
||||||
|
CallArgPair {
|
||||||
|
vreg: got_offset,
|
||||||
|
preg: gpr(2),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
defs: smallvec![CallRetPair {
|
||||||
|
vreg: tls_offset,
|
||||||
|
preg: gpr(2),
|
||||||
|
},],
|
||||||
tls_symbol: Some(tls_symbol.clone()),
|
tls_symbol: Some(tls_symbol.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -162,26 +278,16 @@ impl generated_code::Context for IsleContext<'_, '_, MInst, Flags, IsaFlags, 6>
|
|||||||
let caller_callconv = self.lower_ctx.abi().call_conv(self.lower_ctx.sigs());
|
let caller_callconv = self.lower_ctx.abi().call_conv(self.lower_ctx.sigs());
|
||||||
let callee_callconv = CallConv::for_libcall(&self.flags, caller_callconv);
|
let callee_callconv = CallConv::for_libcall(&self.flags, caller_callconv);
|
||||||
|
|
||||||
// Uses and defs are defined by the particular libcall.
|
// Clobbers are defined by the calling convention. Remove defs from clobbers.
|
||||||
let (uses, defs): (SmallVec<[Reg; 8]>, SmallVec<[WritableReg; 8]>) = match info.libcall {
|
|
||||||
LibCall::Memcpy => (
|
|
||||||
smallvec![gpr(2), gpr(3), gpr(4)],
|
|
||||||
smallvec![writable_gpr(2)],
|
|
||||||
),
|
|
||||||
LibCall::ElfTlsGetOffset => (smallvec![gpr(2), gpr(12)], smallvec![writable_gpr(2)]),
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Clobbers are defined by the calling convention. Remove deps from clobbers.
|
|
||||||
let mut clobbers = S390xMachineDeps::get_regs_clobbered_by_call(callee_callconv);
|
let mut clobbers = S390xMachineDeps::get_regs_clobbered_by_call(callee_callconv);
|
||||||
for reg in &defs {
|
for reg in &info.defs {
|
||||||
clobbers.remove(PReg::from(reg.to_reg().to_real_reg().unwrap()));
|
clobbers.remove(PReg::from(reg.preg.to_real_reg().unwrap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Box::new(CallInfo {
|
Box::new(CallInfo {
|
||||||
dest: ExternalName::LibCall(info.libcall),
|
dest: ExternalName::LibCall(info.libcall),
|
||||||
uses,
|
uses: info.uses.clone(),
|
||||||
defs,
|
defs: info.defs.clone(),
|
||||||
clobbers,
|
clobbers,
|
||||||
opcode: Opcode::Call,
|
opcode: Opcode::Call,
|
||||||
caller_callconv,
|
caller_callconv,
|
||||||
|
|||||||
@@ -624,77 +624,6 @@ impl SigData {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return all uses (i.e, function args), defs (i.e., return values
|
|
||||||
/// and caller-saved registers), and clobbers for the callsite.
|
|
||||||
///
|
|
||||||
/// FIXME: used only by s390x; remove once that backend moves to
|
|
||||||
/// `call_clobbers` and constraint-based calls.
|
|
||||||
pub fn call_uses_defs_clobbers<M: ABIMachineSpec>(
|
|
||||||
&self,
|
|
||||||
) -> (SmallVec<[Reg; 8]>, SmallVec<[Writable<Reg>; 8]>, PRegSet) {
|
|
||||||
// Compute uses: all arg regs.
|
|
||||||
let mut uses = smallvec![];
|
|
||||||
for arg in &self.args {
|
|
||||||
match arg {
|
|
||||||
&ABIArg::Slots { ref slots, .. } => {
|
|
||||||
for slot in slots {
|
|
||||||
match slot {
|
|
||||||
&ABIArgSlot::Reg { reg, .. } => {
|
|
||||||
uses.push(Reg::from(reg));
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&ABIArg::StructArg { ref pointer, .. } => {
|
|
||||||
if let Some(slot) = pointer {
|
|
||||||
match slot {
|
|
||||||
&ABIArgSlot::Reg { reg, .. } => {
|
|
||||||
uses.push(Reg::from(reg));
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&ABIArg::ImplicitPtrArg { ref pointer, .. } => match pointer {
|
|
||||||
&ABIArgSlot::Reg { reg, .. } => {
|
|
||||||
uses.push(Reg::from(reg));
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get clobbers: all caller-saves. These may include return value
|
|
||||||
// regs, which we will remove from the clobber set below.
|
|
||||||
let mut clobbers = M::get_regs_clobbered_by_call(self.call_conv);
|
|
||||||
|
|
||||||
// Compute defs: all retval regs, and all caller-save
|
|
||||||
// (clobbered) regs, except for StructRet args.
|
|
||||||
let mut defs = smallvec![];
|
|
||||||
for ret in &self.rets {
|
|
||||||
if let &ABIArg::Slots {
|
|
||||||
ref slots, purpose, ..
|
|
||||||
} = ret
|
|
||||||
{
|
|
||||||
if purpose == ir::ArgumentPurpose::StructReturn {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for slot in slots {
|
|
||||||
match slot {
|
|
||||||
&ABIArgSlot::Reg { reg, .. } => {
|
|
||||||
defs.push(Writable::from_reg(Reg::from(reg)));
|
|
||||||
clobbers.remove(PReg::from(reg));
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(uses, defs, clobbers)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return all clobbers for the callsite.
|
/// Return all clobbers for the callsite.
|
||||||
pub fn call_clobbers<M: ABIMachineSpec>(&self) -> PRegSet {
|
pub fn call_clobbers<M: ABIMachineSpec>(&self) -> PRegSet {
|
||||||
// Get clobbers: all caller-saves. These may include return value
|
// Get clobbers: all caller-saves. These may include return value
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ block0(v0: i32):
|
|||||||
; virtual_sp_offset_adjust 160
|
; virtual_sp_offset_adjust 160
|
||||||
; block0:
|
; block0:
|
||||||
; llgfr %r2, %r2
|
; llgfr %r2, %r2
|
||||||
; bras %r1, 12 ; data %g + 0 ; lg %r3, 0(%r1)
|
; bras %r1, 12 ; data %g + 0 ; lg %r4, 0(%r1)
|
||||||
; basr %r14, %r3
|
; basr %r14, %r4
|
||||||
; lmg %r14, %r15, 272(%r15)
|
; lmg %r14, %r15, 272(%r15)
|
||||||
; br %r14
|
; br %r14
|
||||||
|
|
||||||
@@ -63,8 +63,8 @@ block0(v0: i32):
|
|||||||
; virtual_sp_offset_adjust 160
|
; virtual_sp_offset_adjust 160
|
||||||
; block0:
|
; block0:
|
||||||
; lgfr %r2, %r2
|
; lgfr %r2, %r2
|
||||||
; bras %r1, 12 ; data %g + 0 ; lg %r3, 0(%r1)
|
; bras %r1, 12 ; data %g + 0 ; lg %r4, 0(%r1)
|
||||||
; basr %r14, %r3
|
; basr %r14, %r4
|
||||||
; lmg %r14, %r15, 272(%r15)
|
; lmg %r14, %r15, 272(%r15)
|
||||||
; br %r14
|
; br %r14
|
||||||
|
|
||||||
@@ -107,8 +107,8 @@ block0(v0: i32):
|
|||||||
; virtual_sp_offset_adjust 160
|
; virtual_sp_offset_adjust 160
|
||||||
; block0:
|
; block0:
|
||||||
; llgfr %r2, %r2
|
; llgfr %r2, %r2
|
||||||
; bras %r1, 12 ; data %g + 0 ; lg %r3, 0(%r1)
|
; bras %r1, 12 ; data %g + 0 ; lg %r4, 0(%r1)
|
||||||
; basr %r14, %r3
|
; basr %r14, %r4
|
||||||
; lmg %r14, %r15, 272(%r15)
|
; lmg %r14, %r15, 272(%r15)
|
||||||
; br %r14
|
; br %r14
|
||||||
|
|
||||||
|
|||||||
@@ -69,15 +69,15 @@ block3(v7: r64, v8: r64):
|
|||||||
; aghi %r15, -184
|
; aghi %r15, -184
|
||||||
; virtual_sp_offset_adjust 160
|
; virtual_sp_offset_adjust 160
|
||||||
; block0:
|
; block0:
|
||||||
; stg %r3, 176(%r15)
|
|
||||||
; stg %r2, 168(%r15)
|
; stg %r2, 168(%r15)
|
||||||
; bras %r1, 12 ; data %f + 0 ; lg %r3, 0(%r1)
|
; stg %r3, 176(%r15)
|
||||||
; basr %r14, %r3
|
; bras %r1, 12 ; data %f + 0 ; lg %r5, 0(%r1)
|
||||||
; la %r5, 160(%r15)
|
; basr %r14, %r5
|
||||||
|
; la %r4, 160(%r15)
|
||||||
; lg %r3, 168(%r15)
|
; lg %r3, 168(%r15)
|
||||||
; stg %r3, 0(%r5)
|
; stg %r3, 0(%r4)
|
||||||
; lbr %r2, %r2
|
; lbr %r5, %r2
|
||||||
; chi %r2, 0
|
; chi %r5, 0
|
||||||
; jgnlh label1 ; jg label3
|
; jgnlh label1 ; jg label3
|
||||||
; block1:
|
; block1:
|
||||||
; jg label2
|
; jg label2
|
||||||
|
|||||||
@@ -103,22 +103,22 @@ block0(v0: i64, v1: i64, v2: i64):
|
|||||||
return v3
|
return v3
|
||||||
}
|
}
|
||||||
|
|
||||||
; stmg %r7, %r15, 56(%r15)
|
; stmg %r8, %r15, 64(%r15)
|
||||||
; aghi %r15, -1248
|
; aghi %r15, -1248
|
||||||
; virtual_sp_offset_adjust 1248
|
; virtual_sp_offset_adjust 1248
|
||||||
; block0:
|
; block0:
|
||||||
; lgr %r7, %r2
|
; lgr %r8, %r2
|
||||||
; lgr %r9, %r4
|
; lgr %r10, %r4
|
||||||
; la %r2, 160(%r15)
|
; la %r2, 160(%r15)
|
||||||
; la %r3, 0(%r3)
|
; la %r3, 0(%r3)
|
||||||
; lghi %r4, 1024
|
; lghi %r4, 1024
|
||||||
; brasl %r14, %Memcpy
|
; brasl %r14, %Memcpy
|
||||||
; lgr %r4, %r9
|
; lgr %r4, %r10
|
||||||
; mvc 1184(63,%r15), 0(%r4)
|
; mvc 1184(63,%r15), 0(%r4)
|
||||||
; lgr %r2, %r7
|
|
||||||
; la %r3, 160(%r15)
|
; la %r3, 160(%r15)
|
||||||
; la %r4, 1184(%r15)
|
; la %r4, 1184(%r15)
|
||||||
|
; lgr %r2, %r8
|
||||||
; brasl %r14, userextname0
|
; brasl %r14, userextname0
|
||||||
; lmg %r7, %r15, 1304(%r15)
|
; lmg %r8, %r15, 1312(%r15)
|
||||||
; br %r14
|
; br %r14
|
||||||
|
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ block0(v0: i32):
|
|||||||
; bras %r1, 12 ; data userextname0@tlsgd ; lg %r2, 0(%r1)
|
; bras %r1, 12 ; data userextname0@tlsgd ; lg %r2, 0(%r1)
|
||||||
; brasl %r14, %ElfTlsGetOffset:tls_gdcall:userextname0
|
; brasl %r14, %ElfTlsGetOffset:tls_gdcall:userextname0
|
||||||
; ear %r3, %a0
|
; ear %r3, %a0
|
||||||
; sllg %r5, %r3, 32
|
; sllg %r3, %r3, 32
|
||||||
; ear %r5, %a1
|
; ear %r3, %a1
|
||||||
; agr %r2, %r5
|
; agr %r2, %r3
|
||||||
; lmg %r12, %r15, 256(%r15)
|
; lmg %r12, %r15, 256(%r15)
|
||||||
; br %r14
|
; br %r14
|
||||||
|
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ block0(v0: i64x2, v1: i32x4, v2: i16x8, v3: i8x16):
|
|||||||
; aghi %r15, -160
|
; aghi %r15, -160
|
||||||
; virtual_sp_offset_adjust 160
|
; virtual_sp_offset_adjust 160
|
||||||
; block0:
|
; block0:
|
||||||
; bras %r1, 12 ; data %callee_be + 0 ; lg %r4, 0(%r1)
|
; bras %r1, 12 ; data %callee_be + 0 ; lg %r5, 0(%r1)
|
||||||
; basr %r14, %r4
|
; basr %r14, %r5
|
||||||
; lmg %r14, %r15, 272(%r15)
|
; lmg %r14, %r15, 272(%r15)
|
||||||
; br %r14
|
; br %r14
|
||||||
|
|
||||||
@@ -39,19 +39,19 @@ block0(v0: i64x2, v1: i32x4, v2: i16x8, v3: i8x16):
|
|||||||
; std %f15, 216(%r15)
|
; std %f15, 216(%r15)
|
||||||
; block0:
|
; block0:
|
||||||
; vpdi %v24, %v24, %v24, 4
|
; vpdi %v24, %v24, %v24, 4
|
||||||
; vpdi %v17, %v25, %v25, 4
|
; vpdi %v16, %v25, %v25, 4
|
||||||
; verllg %v25, %v17, 32
|
; verllg %v25, %v16, 32
|
||||||
; vpdi %v22, %v26, %v26, 4
|
; vpdi %v20, %v26, %v26, 4
|
||||||
; verllg %v26, %v22, 32
|
; verllg %v22, %v20, 32
|
||||||
; verllf %v26, %v26, 16
|
; verllf %v26, %v22, 16
|
||||||
; vpdi %v29, %v27, %v27, 4
|
; vpdi %v27, %v27, %v27, 4
|
||||||
; verllg %v31, %v29, 32
|
; verllg %v28, %v27, 32
|
||||||
; verllf %v1, %v31, 16
|
; verllf %v30, %v28, 16
|
||||||
; verllh %v27, %v1, 8
|
; verllh %v27, %v30, 8
|
||||||
; bras %r1, 12 ; data %callee_le + 0 ; lg %r4, 0(%r1)
|
; bras %r1, 12 ; data %callee_le + 0 ; lg %r5, 0(%r1)
|
||||||
; basr %r14, %r4
|
; basr %r14, %r5
|
||||||
; vpdi %v19, %v24, %v24, 4
|
; vpdi %v6, %v24, %v24, 4
|
||||||
; verllg %v24, %v19, 32
|
; verllg %v24, %v6, 32
|
||||||
; ld %f8, 160(%r15)
|
; ld %f8, 160(%r15)
|
||||||
; ld %f9, 168(%r15)
|
; ld %f9, 168(%r15)
|
||||||
; ld %f10, 176(%r15)
|
; ld %f10, 176(%r15)
|
||||||
@@ -84,19 +84,19 @@ block0(v0: i64x2, v1: i32x4, v2: i16x8, v3: i8x16):
|
|||||||
; std %f15, 216(%r15)
|
; std %f15, 216(%r15)
|
||||||
; block0:
|
; block0:
|
||||||
; vpdi %v24, %v24, %v24, 4
|
; vpdi %v24, %v24, %v24, 4
|
||||||
; vpdi %v17, %v25, %v25, 4
|
; vpdi %v16, %v25, %v25, 4
|
||||||
; verllg %v25, %v17, 32
|
; verllg %v25, %v16, 32
|
||||||
; vpdi %v22, %v26, %v26, 4
|
; vpdi %v20, %v26, %v26, 4
|
||||||
; verllg %v26, %v22, 32
|
; verllg %v22, %v20, 32
|
||||||
; verllf %v26, %v26, 16
|
; verllf %v26, %v22, 16
|
||||||
; vpdi %v29, %v27, %v27, 4
|
; vpdi %v27, %v27, %v27, 4
|
||||||
; verllg %v31, %v29, 32
|
; verllg %v28, %v27, 32
|
||||||
; verllf %v1, %v31, 16
|
; verllf %v30, %v28, 16
|
||||||
; verllh %v27, %v1, 8
|
; verllh %v27, %v30, 8
|
||||||
; bras %r1, 12 ; data %callee_be + 0 ; lg %r4, 0(%r1)
|
; bras %r1, 12 ; data %callee_be + 0 ; lg %r5, 0(%r1)
|
||||||
; basr %r14, %r4
|
; basr %r14, %r5
|
||||||
; vpdi %v19, %v24, %v24, 4
|
; vpdi %v6, %v24, %v24, 4
|
||||||
; verllg %v24, %v19, 32
|
; verllg %v24, %v6, 32
|
||||||
; ld %f8, 160(%r15)
|
; ld %f8, 160(%r15)
|
||||||
; ld %f9, 168(%r15)
|
; ld %f9, 168(%r15)
|
||||||
; ld %f10, 176(%r15)
|
; ld %f10, 176(%r15)
|
||||||
@@ -120,8 +120,8 @@ block0(v0: i64x2, v1: i32x4, v2: i16x8, v3: i8x16):
|
|||||||
; aghi %r15, -160
|
; aghi %r15, -160
|
||||||
; virtual_sp_offset_adjust 160
|
; virtual_sp_offset_adjust 160
|
||||||
; block0:
|
; block0:
|
||||||
; bras %r1, 12 ; data %callee_le + 0 ; lg %r4, 0(%r1)
|
; bras %r1, 12 ; data %callee_le + 0 ; lg %r5, 0(%r1)
|
||||||
; basr %r14, %r4
|
; basr %r14, %r5
|
||||||
; lmg %r14, %r15, 272(%r15)
|
; lmg %r14, %r15, 272(%r15)
|
||||||
; br %r14
|
; br %r14
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user