goetz@6458: /* mdoerr@9603: * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. mdoerr@9603: * Copyright (c) 2012, 2018, SAP SE. All rights reserved. goetz@6458: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. goetz@6458: * goetz@6458: * This code is free software; you can redistribute it and/or modify it goetz@6458: * under the terms of the GNU General Public License version 2 only, as goetz@6458: * published by the Free Software Foundation. goetz@6458: * goetz@6458: * This code is distributed in the hope that it will be useful, but WITHOUT goetz@6458: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or goetz@6458: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License goetz@6458: * version 2 for more details (a copy is included in the LICENSE file that goetz@6458: * accompanied this code). goetz@6458: * goetz@6458: * You should have received a copy of the GNU General Public License version goetz@6458: * 2 along with this work; if not, write to the Free Software Foundation, goetz@6458: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. goetz@6458: * goetz@6458: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA goetz@6458: * or visit www.oracle.com if you need additional information or have any goetz@6458: * questions. goetz@6458: * goetz@6458: */ goetz@6458: goetz@6458: #ifndef CPU_PPC_VM_ASSEMBLER_PPC_HPP goetz@6458: #define CPU_PPC_VM_ASSEMBLER_PPC_HPP goetz@6458: goetz@6458: #include "asm/register.hpp" goetz@6458: goetz@6458: // Address is an abstraction used to represent a memory location goetz@6458: // as used in assembler instructions. goetz@6458: // PPC instructions grok either baseReg + indexReg or baseReg + disp. goetz@6458: // So far we do not use this as simplification by this class is low goetz@6458: // on PPC with its simple addressing mode. Use RegisterOrConstant to goetz@6458: // represent an offset. goetz@6458: class Address VALUE_OBJ_CLASS_SPEC { goetz@6458: }; goetz@6458: goetz@6458: class AddressLiteral VALUE_OBJ_CLASS_SPEC { goetz@6458: private: goetz@6458: address _address; goetz@6458: RelocationHolder _rspec; goetz@6458: goetz@6458: RelocationHolder rspec_from_rtype(relocInfo::relocType rtype, address addr) { goetz@6458: switch (rtype) { goetz@6458: case relocInfo::external_word_type: goetz@6458: return external_word_Relocation::spec(addr); goetz@6458: case relocInfo::internal_word_type: goetz@6458: return internal_word_Relocation::spec(addr); goetz@6458: case relocInfo::opt_virtual_call_type: goetz@6458: return opt_virtual_call_Relocation::spec(); goetz@6458: case relocInfo::static_call_type: goetz@6458: return static_call_Relocation::spec(); goetz@6458: case relocInfo::runtime_call_type: goetz@6458: return runtime_call_Relocation::spec(); goetz@6458: case relocInfo::none: goetz@6458: return RelocationHolder(); goetz@6458: default: goetz@6458: ShouldNotReachHere(); goetz@6458: return RelocationHolder(); goetz@6458: } goetz@6458: } goetz@6458: goetz@6458: protected: goetz@6458: // creation goetz@6458: AddressLiteral() : _address(NULL), _rspec(NULL) {} goetz@6458: goetz@6458: public: goetz@6458: AddressLiteral(address addr, RelocationHolder const& rspec) goetz@6458: : _address(addr), goetz@6458: _rspec(rspec) {} goetz@6458: goetz@6458: AddressLiteral(address addr, relocInfo::relocType rtype = relocInfo::none) goetz@6458: : _address((address) addr), goetz@6458: _rspec(rspec_from_rtype(rtype, (address) addr)) {} goetz@6458: goetz@6458: AddressLiteral(oop* addr, relocInfo::relocType rtype = relocInfo::none) goetz@6458: : _address((address) addr), goetz@6458: _rspec(rspec_from_rtype(rtype, (address) addr)) {} goetz@6458: goetz@6458: intptr_t value() const { return (intptr_t) _address; } goetz@6458: goetz@6458: const RelocationHolder& rspec() const { return _rspec; } goetz@6458: }; goetz@6458: goetz@6458: // Argument is an abstraction used to represent an outgoing goetz@6458: // actual argument or an incoming formal parameter, whether goetz@6458: // it resides in memory or in a register, in a manner consistent goetz@6458: // with the PPC Application Binary Interface, or ABI. This is goetz@6458: // often referred to as the native or C calling convention. goetz@6458: goetz@6458: class Argument VALUE_OBJ_CLASS_SPEC { goetz@6458: private: goetz@6458: int _number; // The number of the argument. goetz@6458: public: goetz@6458: enum { goetz@6458: // Only 8 registers may contain integer parameters. goetz@6458: n_register_parameters = 8, goetz@6458: // Can have up to 8 floating registers. goetz@6495: n_float_register_parameters = 8, goetz@6495: goetz@6495: // PPC C calling conventions. goetz@6495: // The first eight arguments are passed in int regs if they are int. goetz@6495: n_int_register_parameters_c = 8, goetz@6495: // The first thirteen float arguments are passed in float regs. goetz@6495: n_float_register_parameters_c = 13, goetz@6495: // Only the first 8 parameters are not placed on the stack. Aix disassembly goetz@6495: // shows that xlC places all float args after argument 8 on the stack AND goetz@6495: // in a register. This is not documented, but we follow this convention, too. goetz@6495: n_regs_not_on_stack_c = 8, goetz@6458: }; goetz@6458: // creation goetz@6458: Argument(int number) : _number(number) {} goetz@6458: goetz@6458: int number() const { return _number; } goetz@6458: goetz@6458: // Locating register-based arguments: goetz@6458: bool is_register() const { return _number < n_register_parameters; } goetz@6458: goetz@6458: Register as_register() const { goetz@6458: assert(is_register(), "must be a register argument"); goetz@6458: return as_Register(number() + R3_ARG1->encoding()); goetz@6458: } goetz@6458: }; goetz@6458: goetz@6511: #if !defined(ABI_ELFv2) goetz@6458: // A ppc64 function descriptor. goetz@6458: struct FunctionDescriptor VALUE_OBJ_CLASS_SPEC { goetz@6458: private: goetz@6458: address _entry; goetz@6458: address _toc; goetz@6458: address _env; goetz@6458: goetz@6458: public: goetz@6458: inline address entry() const { return _entry; } goetz@6458: inline address toc() const { return _toc; } goetz@6458: inline address env() const { return _env; } goetz@6458: goetz@6458: inline void set_entry(address entry) { _entry = entry; } goetz@6458: inline void set_toc( address toc) { _toc = toc; } goetz@6458: inline void set_env( address env) { _env = env; } goetz@6458: goetz@6458: inline static ByteSize entry_offset() { return byte_offset_of(FunctionDescriptor, _entry); } goetz@6458: inline static ByteSize toc_offset() { return byte_offset_of(FunctionDescriptor, _toc); } goetz@6458: inline static ByteSize env_offset() { return byte_offset_of(FunctionDescriptor, _env); } goetz@6458: goetz@6458: // Friend functions can be called without loading toc and env. goetz@6458: enum { goetz@6458: friend_toc = 0xcafe, goetz@6458: friend_env = 0xc0de goetz@6458: }; goetz@6458: goetz@6458: inline bool is_friend_function() const { goetz@6458: return (toc() == (address) friend_toc) && (env() == (address) friend_env); goetz@6458: } goetz@6458: goetz@6458: // Constructor for stack-allocated instances. goetz@6458: FunctionDescriptor() { goetz@6458: _entry = (address) 0xbad; goetz@6458: _toc = (address) 0xbad; goetz@6458: _env = (address) 0xbad; goetz@6458: } goetz@6458: }; goetz@6511: #endif goetz@6458: goetz@6458: class Assembler : public AbstractAssembler { goetz@6458: protected: goetz@6458: // Displacement routines goetz@6458: static void print_instruction(int inst); goetz@6458: static int patched_branch(int dest_pos, int inst, int inst_pos); goetz@6458: static int branch_destination(int inst, int pos); goetz@6458: goetz@6458: friend class AbstractAssembler; goetz@6458: goetz@6458: // Code patchers need various routines like inv_wdisp() goetz@6458: friend class NativeInstruction; goetz@6458: friend class NativeGeneralJump; goetz@6458: friend class Relocation; goetz@6458: goetz@6458: public: goetz@6458: goetz@6458: enum shifts { goetz@6458: XO_21_29_SHIFT = 2, goetz@6458: XO_21_30_SHIFT = 1, goetz@6458: XO_27_29_SHIFT = 2, goetz@6458: XO_30_31_SHIFT = 0, goetz@6458: SPR_5_9_SHIFT = 11u, // SPR_5_9 field in bits 11 -- 15 goetz@6458: SPR_0_4_SHIFT = 16u, // SPR_0_4 field in bits 16 -- 20 goetz@6458: RS_SHIFT = 21u, // RS field in bits 21 -- 25 goetz@6458: OPCODE_SHIFT = 26u, // opcode in bits 26 -- 31 goetz@6458: }; goetz@6458: goetz@6458: enum opcdxos_masks { goetz@6458: XL_FORM_OPCODE_MASK = (63u << OPCODE_SHIFT) | (1023u << 1), goetz@6458: ADDI_OPCODE_MASK = (63u << OPCODE_SHIFT), goetz@6458: ADDIS_OPCODE_MASK = (63u << OPCODE_SHIFT), goetz@6458: BXX_OPCODE_MASK = (63u << OPCODE_SHIFT), goetz@6458: BCXX_OPCODE_MASK = (63u << OPCODE_SHIFT), goetz@6458: // trap instructions goetz@6458: TDI_OPCODE_MASK = (63u << OPCODE_SHIFT), goetz@6458: TWI_OPCODE_MASK = (63u << OPCODE_SHIFT), goetz@6458: TD_OPCODE_MASK = (63u << OPCODE_SHIFT) | (1023u << 1), goetz@6458: TW_OPCODE_MASK = (63u << OPCODE_SHIFT) | (1023u << 1), goetz@6458: LD_OPCODE_MASK = (63u << OPCODE_SHIFT) | (3u << XO_30_31_SHIFT), // DS-FORM goetz@6458: STD_OPCODE_MASK = LD_OPCODE_MASK, goetz@6458: STDU_OPCODE_MASK = STD_OPCODE_MASK, goetz@6458: STDX_OPCODE_MASK = (63u << OPCODE_SHIFT) | (1023u << 1), goetz@6458: STDUX_OPCODE_MASK = STDX_OPCODE_MASK, goetz@6458: STW_OPCODE_MASK = (63u << OPCODE_SHIFT), goetz@6458: STWU_OPCODE_MASK = STW_OPCODE_MASK, goetz@6458: STWX_OPCODE_MASK = (63u << OPCODE_SHIFT) | (1023u << 1), goetz@6458: STWUX_OPCODE_MASK = STWX_OPCODE_MASK, goetz@6458: MTCTR_OPCODE_MASK = ~(31u << RS_SHIFT), goetz@6458: ORI_OPCODE_MASK = (63u << OPCODE_SHIFT), goetz@6458: ORIS_OPCODE_MASK = (63u << OPCODE_SHIFT), goetz@6458: RLDICR_OPCODE_MASK = (63u << OPCODE_SHIFT) | (7u << XO_27_29_SHIFT) goetz@6458: }; goetz@6458: goetz@6458: enum opcdxos { goetz@6458: ADD_OPCODE = (31u << OPCODE_SHIFT | 266u << 1), goetz@6458: ADDC_OPCODE = (31u << OPCODE_SHIFT | 10u << 1), goetz@6458: ADDI_OPCODE = (14u << OPCODE_SHIFT), goetz@6458: ADDIS_OPCODE = (15u << OPCODE_SHIFT), goetz@6458: ADDIC__OPCODE = (13u << OPCODE_SHIFT), goetz@6458: ADDE_OPCODE = (31u << OPCODE_SHIFT | 138u << 1), goetz@6458: SUBF_OPCODE = (31u << OPCODE_SHIFT | 40u << 1), goetz@6458: SUBFC_OPCODE = (31u << OPCODE_SHIFT | 8u << 1), goetz@6458: SUBFE_OPCODE = (31u << OPCODE_SHIFT | 136u << 1), goetz@6458: SUBFIC_OPCODE = (8u << OPCODE_SHIFT), goetz@6458: SUBFZE_OPCODE = (31u << OPCODE_SHIFT | 200u << 1), goetz@6458: DIVW_OPCODE = (31u << OPCODE_SHIFT | 491u << 1), goetz@6458: MULLW_OPCODE = (31u << OPCODE_SHIFT | 235u << 1), goetz@6458: MULHW_OPCODE = (31u << OPCODE_SHIFT | 75u << 1), goetz@6458: MULHWU_OPCODE = (31u << OPCODE_SHIFT | 11u << 1), goetz@6458: MULLI_OPCODE = (7u << OPCODE_SHIFT), goetz@6458: AND_OPCODE = (31u << OPCODE_SHIFT | 28u << 1), goetz@6458: ANDI_OPCODE = (28u << OPCODE_SHIFT), goetz@6458: ANDIS_OPCODE = (29u << OPCODE_SHIFT), goetz@6458: ANDC_OPCODE = (31u << OPCODE_SHIFT | 60u << 1), goetz@6458: ORC_OPCODE = (31u << OPCODE_SHIFT | 412u << 1), goetz@6458: OR_OPCODE = (31u << OPCODE_SHIFT | 444u << 1), goetz@6458: ORI_OPCODE = (24u << OPCODE_SHIFT), goetz@6458: ORIS_OPCODE = (25u << OPCODE_SHIFT), goetz@6458: XOR_OPCODE = (31u << OPCODE_SHIFT | 316u << 1), goetz@6458: XORI_OPCODE = (26u << OPCODE_SHIFT), goetz@6458: XORIS_OPCODE = (27u << OPCODE_SHIFT), goetz@6458: goetz@6458: NEG_OPCODE = (31u << OPCODE_SHIFT | 104u << 1), goetz@6458: goetz@6458: RLWINM_OPCODE = (21u << OPCODE_SHIFT), goetz@6458: CLRRWI_OPCODE = RLWINM_OPCODE, goetz@6458: CLRLWI_OPCODE = RLWINM_OPCODE, goetz@6458: goetz@6458: RLWIMI_OPCODE = (20u << OPCODE_SHIFT), goetz@6458: goetz@6458: SLW_OPCODE = (31u << OPCODE_SHIFT | 24u << 1), goetz@6458: SLWI_OPCODE = RLWINM_OPCODE, goetz@6458: SRW_OPCODE = (31u << OPCODE_SHIFT | 536u << 1), goetz@6458: SRWI_OPCODE = RLWINM_OPCODE, goetz@6458: SRAW_OPCODE = (31u << OPCODE_SHIFT | 792u << 1), goetz@6458: SRAWI_OPCODE = (31u << OPCODE_SHIFT | 824u << 1), goetz@6458: goetz@6458: CMP_OPCODE = (31u << OPCODE_SHIFT | 0u << 1), goetz@6458: CMPI_OPCODE = (11u << OPCODE_SHIFT), goetz@6458: CMPL_OPCODE = (31u << OPCODE_SHIFT | 32u << 1), goetz@6458: CMPLI_OPCODE = (10u << OPCODE_SHIFT), goetz@6458: goetz@6458: ISEL_OPCODE = (31u << OPCODE_SHIFT | 15u << 1), goetz@6458: goetz@7222: // Special purpose registers goetz@7222: MTSPR_OPCODE = (31u << OPCODE_SHIFT | 467u << 1), goetz@7222: MFSPR_OPCODE = (31u << OPCODE_SHIFT | 339u << 1), goetz@7222: goetz@7222: MTXER_OPCODE = (MTSPR_OPCODE | 1 << SPR_0_4_SHIFT), goetz@7222: MFXER_OPCODE = (MFSPR_OPCODE | 1 << SPR_0_4_SHIFT), goetz@7222: goetz@7222: MTDSCR_OPCODE = (MTSPR_OPCODE | 3 << SPR_0_4_SHIFT), goetz@7222: MFDSCR_OPCODE = (MFSPR_OPCODE | 3 << SPR_0_4_SHIFT), goetz@7222: goetz@7222: MTLR_OPCODE = (MTSPR_OPCODE | 8 << SPR_0_4_SHIFT), goetz@7222: MFLR_OPCODE = (MFSPR_OPCODE | 8 << SPR_0_4_SHIFT), goetz@7222: goetz@7222: MTCTR_OPCODE = (MTSPR_OPCODE | 9 << SPR_0_4_SHIFT), goetz@7222: MFCTR_OPCODE = (MFSPR_OPCODE | 9 << SPR_0_4_SHIFT), goetz@7222: goetz@7222: MTTFHAR_OPCODE = (MTSPR_OPCODE | 128 << SPR_0_4_SHIFT), goetz@7222: MFTFHAR_OPCODE = (MFSPR_OPCODE | 128 << SPR_0_4_SHIFT), goetz@7222: MTTFIAR_OPCODE = (MTSPR_OPCODE | 129 << SPR_0_4_SHIFT), goetz@7222: MFTFIAR_OPCODE = (MFSPR_OPCODE | 129 << SPR_0_4_SHIFT), goetz@7222: MTTEXASR_OPCODE = (MTSPR_OPCODE | 130 << SPR_0_4_SHIFT), goetz@7222: MFTEXASR_OPCODE = (MFSPR_OPCODE | 130 << SPR_0_4_SHIFT), goetz@7222: MTTEXASRU_OPCODE = (MTSPR_OPCODE | 131 << SPR_0_4_SHIFT), goetz@7222: MFTEXASRU_OPCODE = (MFSPR_OPCODE | 131 << SPR_0_4_SHIFT), goetz@7222: goetz@7222: MTVRSAVE_OPCODE = (MTSPR_OPCODE | 256 << SPR_0_4_SHIFT), goetz@7222: MFVRSAVE_OPCODE = (MFSPR_OPCODE | 256 << SPR_0_4_SHIFT), goetz@7222: goetz@7222: MFTB_OPCODE = (MFSPR_OPCODE | 268 << SPR_0_4_SHIFT), goetz@6458: goetz@6458: MTCRF_OPCODE = (31u << OPCODE_SHIFT | 144u << 1), goetz@6458: MFCR_OPCODE = (31u << OPCODE_SHIFT | 19u << 1), goetz@6458: MCRF_OPCODE = (19u << OPCODE_SHIFT | 0u << 1), goetz@6458: goetz@6458: // condition register logic instructions goetz@6458: CRAND_OPCODE = (19u << OPCODE_SHIFT | 257u << 1), goetz@6458: CRNAND_OPCODE = (19u << OPCODE_SHIFT | 225u << 1), goetz@6458: CROR_OPCODE = (19u << OPCODE_SHIFT | 449u << 1), goetz@6458: CRXOR_OPCODE = (19u << OPCODE_SHIFT | 193u << 1), goetz@6458: CRNOR_OPCODE = (19u << OPCODE_SHIFT | 33u << 1), goetz@6458: CREQV_OPCODE = (19u << OPCODE_SHIFT | 289u << 1), goetz@6458: CRANDC_OPCODE = (19u << OPCODE_SHIFT | 129u << 1), goetz@6458: CRORC_OPCODE = (19u << OPCODE_SHIFT | 417u << 1), goetz@6458: goetz@6458: BCLR_OPCODE = (19u << OPCODE_SHIFT | 16u << 1), goetz@6458: BXX_OPCODE = (18u << OPCODE_SHIFT), goetz@6458: BCXX_OPCODE = (16u << OPCODE_SHIFT), goetz@6458: goetz@6458: // CTR-related opcodes goetz@6458: BCCTR_OPCODE = (19u << OPCODE_SHIFT | 528u << 1), goetz@6458: goetz@6458: LWZ_OPCODE = (32u << OPCODE_SHIFT), goetz@6458: LWZX_OPCODE = (31u << OPCODE_SHIFT | 23u << 1), goetz@6458: LWZU_OPCODE = (33u << OPCODE_SHIFT), kvn@7132: LWBRX_OPCODE = (31u << OPCODE_SHIFT | 534 << 1), goetz@6458: goetz@6458: LHA_OPCODE = (42u << OPCODE_SHIFT), goetz@6458: LHAX_OPCODE = (31u << OPCODE_SHIFT | 343u << 1), goetz@6458: LHAU_OPCODE = (43u << OPCODE_SHIFT), goetz@6458: goetz@6458: LHZ_OPCODE = (40u << OPCODE_SHIFT), goetz@6458: LHZX_OPCODE = (31u << OPCODE_SHIFT | 279u << 1), goetz@6458: LHZU_OPCODE = (41u << OPCODE_SHIFT), kvn@7132: LHBRX_OPCODE = (31u << OPCODE_SHIFT | 790 << 1), goetz@6458: goetz@6458: LBZ_OPCODE = (34u << OPCODE_SHIFT), goetz@6458: LBZX_OPCODE = (31u << OPCODE_SHIFT | 87u << 1), goetz@6458: LBZU_OPCODE = (35u << OPCODE_SHIFT), goetz@6458: goetz@6458: STW_OPCODE = (36u << OPCODE_SHIFT), goetz@6458: STWX_OPCODE = (31u << OPCODE_SHIFT | 151u << 1), goetz@6458: STWU_OPCODE = (37u << OPCODE_SHIFT), goetz@6458: STWUX_OPCODE = (31u << OPCODE_SHIFT | 183u << 1), goetz@6458: goetz@6458: STH_OPCODE = (44u << OPCODE_SHIFT), goetz@6458: STHX_OPCODE = (31u << OPCODE_SHIFT | 407u << 1), goetz@6458: STHU_OPCODE = (45u << OPCODE_SHIFT), goetz@6458: goetz@6458: STB_OPCODE = (38u << OPCODE_SHIFT), goetz@6458: STBX_OPCODE = (31u << OPCODE_SHIFT | 215u << 1), goetz@6458: STBU_OPCODE = (39u << OPCODE_SHIFT), goetz@6458: goetz@6458: EXTSB_OPCODE = (31u << OPCODE_SHIFT | 954u << 1), goetz@6458: EXTSH_OPCODE = (31u << OPCODE_SHIFT | 922u << 1), goetz@6458: EXTSW_OPCODE = (31u << OPCODE_SHIFT | 986u << 1), // X-FORM goetz@6458: goetz@6458: // 32 bit opcode encodings goetz@6458: goetz@6458: LWA_OPCODE = (58u << OPCODE_SHIFT | 2u << XO_30_31_SHIFT), // DS-FORM goetz@6458: LWAX_OPCODE = (31u << OPCODE_SHIFT | 341u << XO_21_30_SHIFT), // X-FORM goetz@6458: goetz@6458: CNTLZW_OPCODE = (31u << OPCODE_SHIFT | 26u << XO_21_30_SHIFT), // X-FORM goetz@6458: goetz@6458: // 64 bit opcode encodings goetz@6458: goetz@6458: LD_OPCODE = (58u << OPCODE_SHIFT | 0u << XO_30_31_SHIFT), // DS-FORM goetz@6458: LDU_OPCODE = (58u << OPCODE_SHIFT | 1u << XO_30_31_SHIFT), // DS-FORM goetz@6458: LDX_OPCODE = (31u << OPCODE_SHIFT | 21u << XO_21_30_SHIFT), // X-FORM goetz@6458: goetz@6458: STD_OPCODE = (62u << OPCODE_SHIFT | 0u << XO_30_31_SHIFT), // DS-FORM goetz@6458: STDU_OPCODE = (62u << OPCODE_SHIFT | 1u << XO_30_31_SHIFT), // DS-FORM goetz@6458: STDUX_OPCODE = (31u << OPCODE_SHIFT | 181u << 1), // X-FORM goetz@6458: STDX_OPCODE = (31u << OPCODE_SHIFT | 149u << XO_21_30_SHIFT), // X-FORM goetz@6458: goetz@6458: RLDICR_OPCODE = (30u << OPCODE_SHIFT | 1u << XO_27_29_SHIFT), // MD-FORM goetz@6458: RLDICL_OPCODE = (30u << OPCODE_SHIFT | 0u << XO_27_29_SHIFT), // MD-FORM goetz@6458: RLDIC_OPCODE = (30u << OPCODE_SHIFT | 2u << XO_27_29_SHIFT), // MD-FORM goetz@6458: RLDIMI_OPCODE = (30u << OPCODE_SHIFT | 3u << XO_27_29_SHIFT), // MD-FORM goetz@6458: goetz@6458: SRADI_OPCODE = (31u << OPCODE_SHIFT | 413u << XO_21_29_SHIFT), // XS-FORM goetz@6458: goetz@6458: SLD_OPCODE = (31u << OPCODE_SHIFT | 27u << 1), // X-FORM goetz@6458: SRD_OPCODE = (31u << OPCODE_SHIFT | 539u << 1), // X-FORM goetz@6458: SRAD_OPCODE = (31u << OPCODE_SHIFT | 794u << 1), // X-FORM goetz@6458: goetz@6458: MULLD_OPCODE = (31u << OPCODE_SHIFT | 233u << 1), // XO-FORM goetz@6458: MULHD_OPCODE = (31u << OPCODE_SHIFT | 73u << 1), // XO-FORM goetz@6458: MULHDU_OPCODE = (31u << OPCODE_SHIFT | 9u << 1), // XO-FORM goetz@6458: DIVD_OPCODE = (31u << OPCODE_SHIFT | 489u << 1), // XO-FORM goetz@6458: goetz@6458: CNTLZD_OPCODE = (31u << OPCODE_SHIFT | 58u << XO_21_30_SHIFT), // X-FORM goetz@6458: NAND_OPCODE = (31u << OPCODE_SHIFT | 476u << XO_21_30_SHIFT), // X-FORM goetz@6458: NOR_OPCODE = (31u << OPCODE_SHIFT | 124u << XO_21_30_SHIFT), // X-FORM goetz@6458: goetz@6458: goetz@6458: // opcodes only used for floating arithmetic goetz@6458: FADD_OPCODE = (63u << OPCODE_SHIFT | 21u << 1), goetz@6458: FADDS_OPCODE = (59u << OPCODE_SHIFT | 21u << 1), goetz@6458: FCMPU_OPCODE = (63u << OPCODE_SHIFT | 00u << 1), goetz@6458: FDIV_OPCODE = (63u << OPCODE_SHIFT | 18u << 1), goetz@6458: FDIVS_OPCODE = (59u << OPCODE_SHIFT | 18u << 1), goetz@6458: FMR_OPCODE = (63u << OPCODE_SHIFT | 72u << 1), goetz@6458: // These are special Power6 opcodes, reused for "lfdepx" and "stfdepx" goetz@6458: // on Power7. Do not use. goetz@6458: // MFFGPR_OPCODE = (31u << OPCODE_SHIFT | 607u << 1), goetz@6458: // MFTGPR_OPCODE = (31u << OPCODE_SHIFT | 735u << 1), goetz@6458: CMPB_OPCODE = (31u << OPCODE_SHIFT | 508 << 1), goetz@6458: POPCNTB_OPCODE = (31u << OPCODE_SHIFT | 122 << 1), goetz@6458: POPCNTW_OPCODE = (31u << OPCODE_SHIFT | 378 << 1), goetz@6458: POPCNTD_OPCODE = (31u << OPCODE_SHIFT | 506 << 1), goetz@6458: FABS_OPCODE = (63u << OPCODE_SHIFT | 264u << 1), goetz@6458: FNABS_OPCODE = (63u << OPCODE_SHIFT | 136u << 1), goetz@6458: FMUL_OPCODE = (63u << OPCODE_SHIFT | 25u << 1), goetz@6458: FMULS_OPCODE = (59u << OPCODE_SHIFT | 25u << 1), goetz@6458: FNEG_OPCODE = (63u << OPCODE_SHIFT | 40u << 1), goetz@6458: FSUB_OPCODE = (63u << OPCODE_SHIFT | 20u << 1), goetz@6458: FSUBS_OPCODE = (59u << OPCODE_SHIFT | 20u << 1), goetz@6458: goetz@6458: // PPC64-internal FPU conversion opcodes goetz@6458: FCFID_OPCODE = (63u << OPCODE_SHIFT | 846u << 1), goetz@6458: FCFIDS_OPCODE = (59u << OPCODE_SHIFT | 846u << 1), goetz@6458: FCTID_OPCODE = (63u << OPCODE_SHIFT | 814u << 1), goetz@6458: FCTIDZ_OPCODE = (63u << OPCODE_SHIFT | 815u << 1), goetz@6458: FCTIW_OPCODE = (63u << OPCODE_SHIFT | 14u << 1), goetz@6458: FCTIWZ_OPCODE = (63u << OPCODE_SHIFT | 15u << 1), goetz@6458: FRSP_OPCODE = (63u << OPCODE_SHIFT | 12u << 1), goetz@6458: goetz@6458: // WARNING: using fmadd results in a non-compliant vm. Some floating goetz@6458: // point tck tests will fail. goetz@6458: FMADD_OPCODE = (59u << OPCODE_SHIFT | 29u << 1), goetz@6458: DMADD_OPCODE = (63u << OPCODE_SHIFT | 29u << 1), goetz@6458: FMSUB_OPCODE = (59u << OPCODE_SHIFT | 28u << 1), goetz@6458: DMSUB_OPCODE = (63u << OPCODE_SHIFT | 28u << 1), goetz@6458: FNMADD_OPCODE = (59u << OPCODE_SHIFT | 31u << 1), goetz@6458: DNMADD_OPCODE = (63u << OPCODE_SHIFT | 31u << 1), goetz@6458: FNMSUB_OPCODE = (59u << OPCODE_SHIFT | 30u << 1), goetz@6458: DNMSUB_OPCODE = (63u << OPCODE_SHIFT | 30u << 1), goetz@6458: goetz@6458: LFD_OPCODE = (50u << OPCODE_SHIFT | 00u << 1), goetz@6458: LFDU_OPCODE = (51u << OPCODE_SHIFT | 00u << 1), goetz@6458: LFDX_OPCODE = (31u << OPCODE_SHIFT | 599u << 1), goetz@6458: LFS_OPCODE = (48u << OPCODE_SHIFT | 00u << 1), goetz@6458: LFSU_OPCODE = (49u << OPCODE_SHIFT | 00u << 1), goetz@6458: LFSX_OPCODE = (31u << OPCODE_SHIFT | 535u << 1), goetz@6458: goetz@6458: STFD_OPCODE = (54u << OPCODE_SHIFT | 00u << 1), goetz@6458: STFDU_OPCODE = (55u << OPCODE_SHIFT | 00u << 1), goetz@6458: STFDX_OPCODE = (31u << OPCODE_SHIFT | 727u << 1), goetz@6458: STFS_OPCODE = (52u << OPCODE_SHIFT | 00u << 1), goetz@6458: STFSU_OPCODE = (53u << OPCODE_SHIFT | 00u << 1), goetz@6458: STFSX_OPCODE = (31u << OPCODE_SHIFT | 663u << 1), goetz@6458: goetz@6458: FSQRT_OPCODE = (63u << OPCODE_SHIFT | 22u << 1), // A-FORM goetz@6458: FSQRTS_OPCODE = (59u << OPCODE_SHIFT | 22u << 1), // A-FORM goetz@6458: goetz@6458: // Vector instruction support for >= Power6 goetz@6458: // Vector Storage Access goetz@6458: LVEBX_OPCODE = (31u << OPCODE_SHIFT | 7u << 1), goetz@6458: LVEHX_OPCODE = (31u << OPCODE_SHIFT | 39u << 1), goetz@6458: LVEWX_OPCODE = (31u << OPCODE_SHIFT | 71u << 1), goetz@6458: LVX_OPCODE = (31u << OPCODE_SHIFT | 103u << 1), goetz@6458: LVXL_OPCODE = (31u << OPCODE_SHIFT | 359u << 1), goetz@6458: STVEBX_OPCODE = (31u << OPCODE_SHIFT | 135u << 1), goetz@6458: STVEHX_OPCODE = (31u << OPCODE_SHIFT | 167u << 1), goetz@6458: STVEWX_OPCODE = (31u << OPCODE_SHIFT | 199u << 1), goetz@6458: STVX_OPCODE = (31u << OPCODE_SHIFT | 231u << 1), goetz@6458: STVXL_OPCODE = (31u << OPCODE_SHIFT | 487u << 1), goetz@6458: LVSL_OPCODE = (31u << OPCODE_SHIFT | 6u << 1), goetz@6458: LVSR_OPCODE = (31u << OPCODE_SHIFT | 38u << 1), goetz@6458: mdoerr@9497: // Vector-Scalar (VSX) instruction support. gromero@9662: LXVD2X_OPCODE = (31u << OPCODE_SHIFT | 844u << 1), gromero@9662: STXVD2X_OPCODE = (31u << OPCODE_SHIFT | 972u << 1), mdoerr@9497: MTVSRD_OPCODE = (31u << OPCODE_SHIFT | 179u << 1), gromero@9687: MTVSRWZ_OPCODE = (31u << OPCODE_SHIFT | 243u << 1), mdoerr@9497: MFVSRD_OPCODE = (31u << OPCODE_SHIFT | 51u << 1), gromero@9687: MFVSRWZ_OPCODE = (31u << OPCODE_SHIFT | 115u << 1), gromero@9687: XXPERMDI_OPCODE= (60u << OPCODE_SHIFT | 10u << 3), gromero@9687: XXMRGHW_OPCODE = (60u << OPCODE_SHIFT | 18u << 3), gromero@9687: XXMRGLW_OPCODE = (60u << OPCODE_SHIFT | 50u << 3), mdoerr@9497: goetz@6458: // Vector Permute and Formatting goetz@6458: VPKPX_OPCODE = (4u << OPCODE_SHIFT | 782u ), goetz@6458: VPKSHSS_OPCODE = (4u << OPCODE_SHIFT | 398u ), goetz@6458: VPKSWSS_OPCODE = (4u << OPCODE_SHIFT | 462u ), goetz@6458: VPKSHUS_OPCODE = (4u << OPCODE_SHIFT | 270u ), goetz@6458: VPKSWUS_OPCODE = (4u << OPCODE_SHIFT | 334u ), goetz@6458: VPKUHUM_OPCODE = (4u << OPCODE_SHIFT | 14u ), goetz@6458: VPKUWUM_OPCODE = (4u << OPCODE_SHIFT | 78u ), goetz@6458: VPKUHUS_OPCODE = (4u << OPCODE_SHIFT | 142u ), goetz@6458: VPKUWUS_OPCODE = (4u << OPCODE_SHIFT | 206u ), goetz@6458: VUPKHPX_OPCODE = (4u << OPCODE_SHIFT | 846u ), goetz@6458: VUPKHSB_OPCODE = (4u << OPCODE_SHIFT | 526u ), goetz@6458: VUPKHSH_OPCODE = (4u << OPCODE_SHIFT | 590u ), goetz@6458: VUPKLPX_OPCODE = (4u << OPCODE_SHIFT | 974u ), goetz@6458: VUPKLSB_OPCODE = (4u << OPCODE_SHIFT | 654u ), goetz@6458: VUPKLSH_OPCODE = (4u << OPCODE_SHIFT | 718u ), goetz@6458: goetz@6458: VMRGHB_OPCODE = (4u << OPCODE_SHIFT | 12u ), goetz@6458: VMRGHW_OPCODE = (4u << OPCODE_SHIFT | 140u ), goetz@6458: VMRGHH_OPCODE = (4u << OPCODE_SHIFT | 76u ), goetz@6458: VMRGLB_OPCODE = (4u << OPCODE_SHIFT | 268u ), goetz@6458: VMRGLW_OPCODE = (4u << OPCODE_SHIFT | 396u ), goetz@6458: VMRGLH_OPCODE = (4u << OPCODE_SHIFT | 332u ), goetz@6458: goetz@6458: VSPLT_OPCODE = (4u << OPCODE_SHIFT | 524u ), goetz@6458: VSPLTH_OPCODE = (4u << OPCODE_SHIFT | 588u ), goetz@6458: VSPLTW_OPCODE = (4u << OPCODE_SHIFT | 652u ), goetz@6458: VSPLTISB_OPCODE= (4u << OPCODE_SHIFT | 780u ), goetz@6458: VSPLTISH_OPCODE= (4u << OPCODE_SHIFT | 844u ), goetz@6458: VSPLTISW_OPCODE= (4u << OPCODE_SHIFT | 908u ), goetz@6458: goetz@6458: VPERM_OPCODE = (4u << OPCODE_SHIFT | 43u ), goetz@6458: VSEL_OPCODE = (4u << OPCODE_SHIFT | 42u ), goetz@6458: goetz@6458: VSL_OPCODE = (4u << OPCODE_SHIFT | 452u ), goetz@6458: VSLDOI_OPCODE = (4u << OPCODE_SHIFT | 44u ), goetz@6458: VSLO_OPCODE = (4u << OPCODE_SHIFT | 1036u ), goetz@6458: VSR_OPCODE = (4u << OPCODE_SHIFT | 708u ), goetz@6458: VSRO_OPCODE = (4u << OPCODE_SHIFT | 1100u ), goetz@6458: goetz@6458: // Vector Integer goetz@6458: VADDCUW_OPCODE = (4u << OPCODE_SHIFT | 384u ), goetz@6458: VADDSHS_OPCODE = (4u << OPCODE_SHIFT | 832u ), goetz@6458: VADDSBS_OPCODE = (4u << OPCODE_SHIFT | 768u ), goetz@6458: VADDSWS_OPCODE = (4u << OPCODE_SHIFT | 896u ), goetz@6458: VADDUBM_OPCODE = (4u << OPCODE_SHIFT | 0u ), goetz@6458: VADDUWM_OPCODE = (4u << OPCODE_SHIFT | 128u ), goetz@6458: VADDUHM_OPCODE = (4u << OPCODE_SHIFT | 64u ), gromero@9687: VADDUDM_OPCODE = (4u << OPCODE_SHIFT | 192u ), goetz@6458: VADDUBS_OPCODE = (4u << OPCODE_SHIFT | 512u ), goetz@6458: VADDUWS_OPCODE = (4u << OPCODE_SHIFT | 640u ), goetz@6458: VADDUHS_OPCODE = (4u << OPCODE_SHIFT | 576u ), goetz@6458: VSUBCUW_OPCODE = (4u << OPCODE_SHIFT | 1408u ), goetz@6458: VSUBSHS_OPCODE = (4u << OPCODE_SHIFT | 1856u ), goetz@6458: VSUBSBS_OPCODE = (4u << OPCODE_SHIFT | 1792u ), goetz@6458: VSUBSWS_OPCODE = (4u << OPCODE_SHIFT | 1920u ), goetz@6458: VSUBUBM_OPCODE = (4u << OPCODE_SHIFT | 1024u ), goetz@6458: VSUBUWM_OPCODE = (4u << OPCODE_SHIFT | 1152u ), goetz@6458: VSUBUHM_OPCODE = (4u << OPCODE_SHIFT | 1088u ), goetz@6458: VSUBUBS_OPCODE = (4u << OPCODE_SHIFT | 1536u ), goetz@6458: VSUBUWS_OPCODE = (4u << OPCODE_SHIFT | 1664u ), goetz@6458: VSUBUHS_OPCODE = (4u << OPCODE_SHIFT | 1600u ), goetz@6458: goetz@6458: VMULESB_OPCODE = (4u << OPCODE_SHIFT | 776u ), goetz@6458: VMULEUB_OPCODE = (4u << OPCODE_SHIFT | 520u ), goetz@6458: VMULESH_OPCODE = (4u << OPCODE_SHIFT | 840u ), goetz@6458: VMULEUH_OPCODE = (4u << OPCODE_SHIFT | 584u ), goetz@6458: VMULOSB_OPCODE = (4u << OPCODE_SHIFT | 264u ), goetz@6458: VMULOUB_OPCODE = (4u << OPCODE_SHIFT | 8u ), goetz@6458: VMULOSH_OPCODE = (4u << OPCODE_SHIFT | 328u ), goetz@6458: VMULOUH_OPCODE = (4u << OPCODE_SHIFT | 72u ), goetz@6458: VMHADDSHS_OPCODE=(4u << OPCODE_SHIFT | 32u ), goetz@6458: VMHRADDSHS_OPCODE=(4u << OPCODE_SHIFT | 33u ), goetz@6458: VMLADDUHM_OPCODE=(4u << OPCODE_SHIFT | 34u ), goetz@6458: VMSUBUHM_OPCODE= (4u << OPCODE_SHIFT | 36u ), goetz@6458: VMSUMMBM_OPCODE= (4u << OPCODE_SHIFT | 37u ), goetz@6458: VMSUMSHM_OPCODE= (4u << OPCODE_SHIFT | 40u ), goetz@6458: VMSUMSHS_OPCODE= (4u << OPCODE_SHIFT | 41u ), goetz@6458: VMSUMUHM_OPCODE= (4u << OPCODE_SHIFT | 38u ), goetz@6458: VMSUMUHS_OPCODE= (4u << OPCODE_SHIFT | 39u ), goetz@6458: goetz@6458: VSUMSWS_OPCODE = (4u << OPCODE_SHIFT | 1928u ), goetz@6458: VSUM2SWS_OPCODE= (4u << OPCODE_SHIFT | 1672u ), goetz@6458: VSUM4SBS_OPCODE= (4u << OPCODE_SHIFT | 1800u ), goetz@6458: VSUM4UBS_OPCODE= (4u << OPCODE_SHIFT | 1544u ), goetz@6458: VSUM4SHS_OPCODE= (4u << OPCODE_SHIFT | 1608u ), goetz@6458: goetz@6458: VAVGSB_OPCODE = (4u << OPCODE_SHIFT | 1282u ), goetz@6458: VAVGSW_OPCODE = (4u << OPCODE_SHIFT | 1410u ), goetz@6458: VAVGSH_OPCODE = (4u << OPCODE_SHIFT | 1346u ), goetz@6458: VAVGUB_OPCODE = (4u << OPCODE_SHIFT | 1026u ), goetz@6458: VAVGUW_OPCODE = (4u << OPCODE_SHIFT | 1154u ), goetz@6458: VAVGUH_OPCODE = (4u << OPCODE_SHIFT | 1090u ), goetz@6458: goetz@6458: VMAXSB_OPCODE = (4u << OPCODE_SHIFT | 258u ), goetz@6458: VMAXSW_OPCODE = (4u << OPCODE_SHIFT | 386u ), goetz@6458: VMAXSH_OPCODE = (4u << OPCODE_SHIFT | 322u ), goetz@6458: VMAXUB_OPCODE = (4u << OPCODE_SHIFT | 2u ), goetz@6458: VMAXUW_OPCODE = (4u << OPCODE_SHIFT | 130u ), goetz@6458: VMAXUH_OPCODE = (4u << OPCODE_SHIFT | 66u ), goetz@6458: VMINSB_OPCODE = (4u << OPCODE_SHIFT | 770u ), goetz@6458: VMINSW_OPCODE = (4u << OPCODE_SHIFT | 898u ), goetz@6458: VMINSH_OPCODE = (4u << OPCODE_SHIFT | 834u ), goetz@6458: VMINUB_OPCODE = (4u << OPCODE_SHIFT | 514u ), goetz@6458: VMINUW_OPCODE = (4u << OPCODE_SHIFT | 642u ), goetz@6458: VMINUH_OPCODE = (4u << OPCODE_SHIFT | 578u ), goetz@6458: goetz@6458: VCMPEQUB_OPCODE= (4u << OPCODE_SHIFT | 6u ), goetz@6458: VCMPEQUH_OPCODE= (4u << OPCODE_SHIFT | 70u ), goetz@6458: VCMPEQUW_OPCODE= (4u << OPCODE_SHIFT | 134u ), goetz@6458: VCMPGTSH_OPCODE= (4u << OPCODE_SHIFT | 838u ), goetz@6458: VCMPGTSB_OPCODE= (4u << OPCODE_SHIFT | 774u ), goetz@6458: VCMPGTSW_OPCODE= (4u << OPCODE_SHIFT | 902u ), goetz@6458: VCMPGTUB_OPCODE= (4u << OPCODE_SHIFT | 518u ), goetz@6458: VCMPGTUH_OPCODE= (4u << OPCODE_SHIFT | 582u ), goetz@6458: VCMPGTUW_OPCODE= (4u << OPCODE_SHIFT | 646u ), goetz@6458: goetz@6458: VAND_OPCODE = (4u << OPCODE_SHIFT | 1028u ), goetz@6458: VANDC_OPCODE = (4u << OPCODE_SHIFT | 1092u ), goetz@6458: VNOR_OPCODE = (4u << OPCODE_SHIFT | 1284u ), goetz@6458: VOR_OPCODE = (4u << OPCODE_SHIFT | 1156u ), goetz@6458: VXOR_OPCODE = (4u << OPCODE_SHIFT | 1220u ), simonis@8608: VRLD_OPCODE = (4u << OPCODE_SHIFT | 196u ), goetz@6458: VRLB_OPCODE = (4u << OPCODE_SHIFT | 4u ), goetz@6458: VRLW_OPCODE = (4u << OPCODE_SHIFT | 132u ), goetz@6458: VRLH_OPCODE = (4u << OPCODE_SHIFT | 68u ), goetz@6458: VSLB_OPCODE = (4u << OPCODE_SHIFT | 260u ), goetz@6458: VSKW_OPCODE = (4u << OPCODE_SHIFT | 388u ), goetz@6458: VSLH_OPCODE = (4u << OPCODE_SHIFT | 324u ), goetz@6458: VSRB_OPCODE = (4u << OPCODE_SHIFT | 516u ), goetz@6458: VSRW_OPCODE = (4u << OPCODE_SHIFT | 644u ), goetz@6458: VSRH_OPCODE = (4u << OPCODE_SHIFT | 580u ), goetz@6458: VSRAB_OPCODE = (4u << OPCODE_SHIFT | 772u ), goetz@6458: VSRAW_OPCODE = (4u << OPCODE_SHIFT | 900u ), goetz@6458: VSRAH_OPCODE = (4u << OPCODE_SHIFT | 836u ), goetz@6458: goetz@6458: // Vector Floating-Point goetz@6458: // not implemented yet goetz@6458: goetz@6458: // Vector Status and Control goetz@6458: MTVSCR_OPCODE = (4u << OPCODE_SHIFT | 1604u ), goetz@6458: MFVSCR_OPCODE = (4u << OPCODE_SHIFT | 1540u ), goetz@6458: goetz@7222: // AES (introduced with Power 8) goetz@7222: VCIPHER_OPCODE = (4u << OPCODE_SHIFT | 1288u), goetz@7222: VCIPHERLAST_OPCODE = (4u << OPCODE_SHIFT | 1289u), goetz@7222: VNCIPHER_OPCODE = (4u << OPCODE_SHIFT | 1352u), goetz@7222: VNCIPHERLAST_OPCODE = (4u << OPCODE_SHIFT | 1353u), goetz@7222: VSBOX_OPCODE = (4u << OPCODE_SHIFT | 1480u), goetz@7222: goetz@7222: // SHA (introduced with Power 8) goetz@7222: VSHASIGMAD_OPCODE = (4u << OPCODE_SHIFT | 1730u), goetz@7222: VSHASIGMAW_OPCODE = (4u << OPCODE_SHIFT | 1666u), goetz@7222: goetz@7222: // Vector Binary Polynomial Multiplication (introduced with Power 8) goetz@7222: VPMSUMB_OPCODE = (4u << OPCODE_SHIFT | 1032u), goetz@7222: VPMSUMD_OPCODE = (4u << OPCODE_SHIFT | 1224u), goetz@7222: VPMSUMH_OPCODE = (4u << OPCODE_SHIFT | 1096u), goetz@7222: VPMSUMW_OPCODE = (4u << OPCODE_SHIFT | 1160u), goetz@7222: goetz@7222: // Vector Permute and Xor (introduced with Power 8) goetz@7222: VPERMXOR_OPCODE = (4u << OPCODE_SHIFT | 45u), goetz@7222: goetz@7222: // Transactional Memory instructions (introduced with Power 8) goetz@7222: TBEGIN_OPCODE = (31u << OPCODE_SHIFT | 654u << 1), goetz@7222: TEND_OPCODE = (31u << OPCODE_SHIFT | 686u << 1), goetz@7222: TABORT_OPCODE = (31u << OPCODE_SHIFT | 910u << 1), goetz@7222: TABORTWC_OPCODE = (31u << OPCODE_SHIFT | 782u << 1), goetz@7222: TABORTWCI_OPCODE = (31u << OPCODE_SHIFT | 846u << 1), goetz@7222: TABORTDC_OPCODE = (31u << OPCODE_SHIFT | 814u << 1), goetz@7222: TABORTDCI_OPCODE = (31u << OPCODE_SHIFT | 878u << 1), goetz@7222: TSR_OPCODE = (31u << OPCODE_SHIFT | 750u << 1), goetz@7222: TCHECK_OPCODE = (31u << OPCODE_SHIFT | 718u << 1), goetz@7222: goetz@6458: // Icache and dcache related instructions goetz@6458: DCBA_OPCODE = (31u << OPCODE_SHIFT | 758u << 1), goetz@6458: DCBZ_OPCODE = (31u << OPCODE_SHIFT | 1014u << 1), goetz@6458: DCBST_OPCODE = (31u << OPCODE_SHIFT | 54u << 1), goetz@6458: DCBF_OPCODE = (31u << OPCODE_SHIFT | 86u << 1), goetz@6458: goetz@6458: DCBT_OPCODE = (31u << OPCODE_SHIFT | 278u << 1), goetz@6458: DCBTST_OPCODE = (31u << OPCODE_SHIFT | 246u << 1), goetz@6458: ICBI_OPCODE = (31u << OPCODE_SHIFT | 982u << 1), goetz@6458: goetz@6458: // Instruction synchronization goetz@6458: ISYNC_OPCODE = (19u << OPCODE_SHIFT | 150u << 1), goetz@6458: // Memory barriers goetz@6458: SYNC_OPCODE = (31u << OPCODE_SHIFT | 598u << 1), goetz@6458: EIEIO_OPCODE = (31u << OPCODE_SHIFT | 854u << 1), goetz@6458: goetz@6458: // Trap instructions goetz@6458: TDI_OPCODE = (2u << OPCODE_SHIFT), goetz@6458: TWI_OPCODE = (3u << OPCODE_SHIFT), goetz@6458: TD_OPCODE = (31u << OPCODE_SHIFT | 68u << 1), goetz@6458: TW_OPCODE = (31u << OPCODE_SHIFT | 4u << 1), goetz@6458: goetz@6458: // Atomics. goetz@6458: LWARX_OPCODE = (31u << OPCODE_SHIFT | 20u << 1), goetz@6458: LDARX_OPCODE = (31u << OPCODE_SHIFT | 84u << 1), gromero@9662: LQARX_OPCODE = (31u << OPCODE_SHIFT | 276u << 1), goetz@6458: STWCX_OPCODE = (31u << OPCODE_SHIFT | 150u << 1), gromero@9662: STDCX_OPCODE = (31u << OPCODE_SHIFT | 214u << 1), gromero@9662: STQCX_OPCODE = (31u << OPCODE_SHIFT | 182u << 1) goetz@6458: goetz@6458: }; goetz@6458: goetz@6458: // Trap instructions TO bits goetz@6458: enum trap_to_bits { goetz@6458: // single bits goetz@6458: traptoLessThanSigned = 1 << 4, // 0, left end goetz@6458: traptoGreaterThanSigned = 1 << 3, goetz@6458: traptoEqual = 1 << 2, goetz@6458: traptoLessThanUnsigned = 1 << 1, goetz@6458: traptoGreaterThanUnsigned = 1 << 0, // 4, right end goetz@6458: goetz@6458: // compound ones goetz@6458: traptoUnconditional = (traptoLessThanSigned | goetz@6458: traptoGreaterThanSigned | goetz@6458: traptoEqual | goetz@6458: traptoLessThanUnsigned | goetz@6458: traptoGreaterThanUnsigned) goetz@6458: }; goetz@6458: goetz@6458: // Branch hints BH field goetz@6458: enum branch_hint_bh { goetz@6458: // bclr cases: goetz@6458: bhintbhBCLRisReturn = 0, goetz@6458: bhintbhBCLRisNotReturnButSame = 1, goetz@6458: bhintbhBCLRisNotPredictable = 3, goetz@6458: goetz@6458: // bcctr cases: goetz@6458: bhintbhBCCTRisNotReturnButSame = 0, goetz@6458: bhintbhBCCTRisNotPredictable = 3 goetz@6458: }; goetz@6458: goetz@6458: // Branch prediction hints AT field goetz@6458: enum branch_hint_at { goetz@6458: bhintatNoHint = 0, // at=00 goetz@6458: bhintatIsNotTaken = 2, // at=10 goetz@6458: bhintatIsTaken = 3 // at=11 goetz@6458: }; goetz@6458: goetz@6458: // Branch prediction hints goetz@6458: enum branch_hint_concept { goetz@6458: // Use the same encoding as branch_hint_at to simply code. goetz@6458: bhintNoHint = bhintatNoHint, goetz@6458: bhintIsNotTaken = bhintatIsNotTaken, goetz@6458: bhintIsTaken = bhintatIsTaken goetz@6458: }; goetz@6458: goetz@6458: // Used in BO field of branch instruction. goetz@6458: enum branch_condition { goetz@6458: bcondCRbiIs0 = 4, // bo=001at goetz@6458: bcondCRbiIs1 = 12, // bo=011at goetz@6458: bcondAlways = 20 // bo=10100 goetz@6458: }; goetz@6458: goetz@6458: // Branch condition with combined prediction hints. goetz@6458: enum branch_condition_with_hint { goetz@6458: bcondCRbiIs0_bhintNoHint = bcondCRbiIs0 | bhintatNoHint, goetz@6458: bcondCRbiIs0_bhintIsNotTaken = bcondCRbiIs0 | bhintatIsNotTaken, goetz@6458: bcondCRbiIs0_bhintIsTaken = bcondCRbiIs0 | bhintatIsTaken, goetz@6458: bcondCRbiIs1_bhintNoHint = bcondCRbiIs1 | bhintatNoHint, goetz@6458: bcondCRbiIs1_bhintIsNotTaken = bcondCRbiIs1 | bhintatIsNotTaken, goetz@6458: bcondCRbiIs1_bhintIsTaken = bcondCRbiIs1 | bhintatIsTaken, goetz@6458: }; goetz@6458: goetz@6495: // Elemental Memory Barriers (>=Power 8) goetz@6495: enum Elemental_Membar_mask_bits { goetz@6495: StoreStore = 1 << 0, goetz@6495: StoreLoad = 1 << 1, goetz@6495: LoadStore = 1 << 2, goetz@6495: LoadLoad = 1 << 3 goetz@6495: }; goetz@6495: goetz@6458: // Branch prediction hints. goetz@6458: inline static int add_bhint_to_boint(const int bhint, const int boint) { goetz@6458: switch (boint) { goetz@6458: case bcondCRbiIs0: goetz@6458: case bcondCRbiIs1: goetz@6458: // branch_hint and branch_hint_at have same encodings goetz@6458: assert( (int)bhintNoHint == (int)bhintatNoHint goetz@6458: && (int)bhintIsNotTaken == (int)bhintatIsNotTaken goetz@6458: && (int)bhintIsTaken == (int)bhintatIsTaken, goetz@6458: "wrong encodings"); goetz@6458: assert((bhint & 0x03) == bhint, "wrong encodings"); goetz@6458: return (boint & ~0x03) | bhint; goetz@6458: case bcondAlways: goetz@6458: // no branch_hint goetz@6458: return boint; goetz@6458: default: goetz@6458: ShouldNotReachHere(); goetz@6458: return 0; goetz@6458: } goetz@6458: } goetz@6458: goetz@6458: // Extract bcond from boint. goetz@6458: inline static int inv_boint_bcond(const int boint) { goetz@6458: int r_bcond = boint & ~0x03; goetz@6458: assert(r_bcond == bcondCRbiIs0 || goetz@6458: r_bcond == bcondCRbiIs1 || goetz@6458: r_bcond == bcondAlways, goetz@6458: "bad branch condition"); goetz@6458: return r_bcond; goetz@6458: } goetz@6458: goetz@6458: // Extract bhint from boint. goetz@6458: inline static int inv_boint_bhint(const int boint) { goetz@6458: int r_bhint = boint & 0x03; goetz@6458: assert(r_bhint == bhintatNoHint || goetz@6458: r_bhint == bhintatIsNotTaken || goetz@6458: r_bhint == bhintatIsTaken, goetz@6458: "bad branch hint"); goetz@6458: return r_bhint; goetz@6458: } goetz@6458: goetz@6458: // Calculate opposite of given bcond. goetz@6458: inline static int opposite_bcond(const int bcond) { goetz@6458: switch (bcond) { goetz@6458: case bcondCRbiIs0: goetz@6458: return bcondCRbiIs1; goetz@6458: case bcondCRbiIs1: goetz@6458: return bcondCRbiIs0; goetz@6458: default: goetz@6458: ShouldNotReachHere(); goetz@6458: return 0; goetz@6458: } goetz@6458: } goetz@6458: goetz@6458: // Calculate opposite of given bhint. goetz@6458: inline static int opposite_bhint(const int bhint) { goetz@6458: switch (bhint) { goetz@6458: case bhintatNoHint: goetz@6458: return bhintatNoHint; goetz@6458: case bhintatIsNotTaken: goetz@6458: return bhintatIsTaken; goetz@6458: case bhintatIsTaken: goetz@6458: return bhintatIsNotTaken; goetz@6458: default: goetz@6458: ShouldNotReachHere(); goetz@6458: return 0; goetz@6458: } goetz@6458: } goetz@6458: goetz@6458: // PPC branch instructions goetz@6458: enum ppcops { goetz@6458: b_op = 18, goetz@6458: bc_op = 16, goetz@6458: bcr_op = 19 goetz@6458: }; goetz@6458: goetz@6458: enum Condition { goetz@6458: negative = 0, goetz@6458: less = 0, goetz@6458: positive = 1, goetz@6458: greater = 1, goetz@6458: zero = 2, goetz@6458: equal = 2, goetz@6458: summary_overflow = 3, goetz@6458: }; goetz@6458: goetz@6458: public: goetz@6458: // Helper functions for groups of instructions goetz@6458: goetz@6458: enum Predict { pt = 1, pn = 0 }; // pt = predict taken goetz@6458: goetz@6458: // instruction must start at passed address goetz@6458: static int instr_len(unsigned char *instr) { return BytesPerInstWord; } goetz@6458: goetz@6458: // instruction must be left-justified in argument goetz@6458: static int instr_len(unsigned long instr) { return BytesPerInstWord; } goetz@6458: goetz@6458: // longest instructions goetz@6458: static int instr_maxlen() { return BytesPerInstWord; } goetz@6458: goetz@6458: // Test if x is within signed immediate range for nbits. goetz@6458: static bool is_simm(int x, unsigned int nbits) { goetz@6458: assert(0 < nbits && nbits < 32, "out of bounds"); goetz@6458: const int min = -( ((int)1) << nbits-1 ); goetz@6458: const int maxplus1 = ( ((int)1) << nbits-1 ); goetz@6458: return min <= x && x < maxplus1; goetz@6458: } goetz@6458: goetz@6458: static bool is_simm(jlong x, unsigned int nbits) { goetz@6458: assert(0 < nbits && nbits < 64, "out of bounds"); goetz@6458: const jlong min = -( ((jlong)1) << nbits-1 ); goetz@6458: const jlong maxplus1 = ( ((jlong)1) << nbits-1 ); goetz@6458: return min <= x && x < maxplus1; goetz@6458: } goetz@6458: goetz@6458: // Test if x is within unsigned immediate range for nbits goetz@6458: static bool is_uimm(int x, unsigned int nbits) { goetz@6458: assert(0 < nbits && nbits < 32, "out of bounds"); goetz@6458: const int maxplus1 = ( ((int)1) << nbits ); goetz@6458: return 0 <= x && x < maxplus1; goetz@6458: } goetz@6458: goetz@6458: static bool is_uimm(jlong x, unsigned int nbits) { goetz@6458: assert(0 < nbits && nbits < 64, "out of bounds"); goetz@6458: const jlong maxplus1 = ( ((jlong)1) << nbits ); goetz@6458: return 0 <= x && x < maxplus1; goetz@6458: } goetz@6458: goetz@6458: protected: goetz@6458: // helpers goetz@6458: goetz@6458: // X is supposed to fit in a field "nbits" wide goetz@6458: // and be sign-extended. Check the range. goetz@6458: static void assert_signed_range(intptr_t x, int nbits) { goetz@6458: assert(nbits == 32 || (-(1 << nbits-1) <= x && x < (1 << nbits-1)), goetz@6458: "value out of range"); goetz@6458: } goetz@6458: goetz@6458: static void assert_signed_word_disp_range(intptr_t x, int nbits) { goetz@6458: assert((x & 3) == 0, "not word aligned"); goetz@6458: assert_signed_range(x, nbits + 2); goetz@6458: } goetz@6458: goetz@6458: static void assert_unsigned_const(int x, int nbits) { goetz@6458: assert(juint(x) < juint(1 << nbits), "unsigned constant out of range"); goetz@6458: } goetz@6458: goetz@6458: static int fmask(juint hi_bit, juint lo_bit) { goetz@6458: assert(hi_bit >= lo_bit && hi_bit < 32, "bad bits"); goetz@6458: return (1 << ( hi_bit-lo_bit + 1 )) - 1; goetz@6458: } goetz@6458: goetz@6458: // inverse of u_field goetz@6458: static int inv_u_field(int x, int hi_bit, int lo_bit) { goetz@6458: juint r = juint(x) >> lo_bit; goetz@6458: r &= fmask(hi_bit, lo_bit); goetz@6458: return int(r); goetz@6458: } goetz@6458: goetz@6458: // signed version: extract from field and sign-extend goetz@6458: static int inv_s_field_ppc(int x, int hi_bit, int lo_bit) { goetz@6458: x = x << (31-hi_bit); goetz@6458: x = x >> (31-hi_bit+lo_bit); goetz@6458: return x; goetz@6458: } goetz@6458: goetz@6458: static int u_field(int x, int hi_bit, int lo_bit) { goetz@6458: assert((x & ~fmask(hi_bit, lo_bit)) == 0, "value out of range"); goetz@6458: int r = x << lo_bit; goetz@6458: assert(inv_u_field(r, hi_bit, lo_bit) == x, "just checking"); goetz@6458: return r; goetz@6458: } goetz@6458: goetz@6458: // Same as u_field for signed values goetz@6458: static int s_field(int x, int hi_bit, int lo_bit) { goetz@6458: int nbits = hi_bit - lo_bit + 1; goetz@6458: assert(nbits == 32 || (-(1 << nbits-1) <= x && x < (1 << nbits-1)), goetz@6458: "value out of range"); goetz@6458: x &= fmask(hi_bit, lo_bit); goetz@6458: int r = x << lo_bit; goetz@6458: return r; goetz@6458: } goetz@6458: goetz@6458: // inv_op for ppc instructions goetz@6458: static int inv_op_ppc(int x) { return inv_u_field(x, 31, 26); } goetz@6458: goetz@6458: // Determine target address from li, bd field of branch instruction. goetz@6458: static intptr_t inv_li_field(int x) { goetz@6458: intptr_t r = inv_s_field_ppc(x, 25, 2); goetz@6458: r = (r << 2); goetz@6458: return r; goetz@6458: } goetz@6458: static intptr_t inv_bd_field(int x, intptr_t pos) { goetz@6458: intptr_t r = inv_s_field_ppc(x, 15, 2); goetz@6458: r = (r << 2) + pos; goetz@6458: return r; goetz@6458: } goetz@6458: goetz@6458: #define inv_opp_u_field(x, hi_bit, lo_bit) inv_u_field(x, 31-(lo_bit), 31-(hi_bit)) goetz@6458: #define inv_opp_s_field(x, hi_bit, lo_bit) inv_s_field_ppc(x, 31-(lo_bit), 31-(hi_bit)) goetz@6458: // Extract instruction fields from instruction words. goetz@6458: public: goetz@6495: static int inv_ra_field(int x) { return inv_opp_u_field(x, 15, 11); } goetz@6495: static int inv_rb_field(int x) { return inv_opp_u_field(x, 20, 16); } goetz@6495: static int inv_rt_field(int x) { return inv_opp_u_field(x, 10, 6); } goetz@6495: static int inv_rta_field(int x) { return inv_opp_u_field(x, 15, 11); } goetz@6495: static int inv_rs_field(int x) { return inv_opp_u_field(x, 10, 6); } goetz@6458: // Ds uses opp_s_field(x, 31, 16), but lowest 2 bits must be 0. goetz@6458: // Inv_ds_field uses range (x, 29, 16) but shifts by 2 to ensure that lowest bits are 0. goetz@6495: static int inv_ds_field(int x) { return inv_opp_s_field(x, 29, 16) << 2; } goetz@6495: static int inv_d1_field(int x) { return inv_opp_s_field(x, 31, 16); } goetz@6495: static int inv_si_field(int x) { return inv_opp_s_field(x, 31, 16); } goetz@6495: static int inv_to_field(int x) { return inv_opp_u_field(x, 10, 6); } goetz@6495: static int inv_lk_field(int x) { return inv_opp_u_field(x, 31, 31); } goetz@6495: static int inv_bo_field(int x) { return inv_opp_u_field(x, 10, 6); } goetz@6495: static int inv_bi_field(int x) { return inv_opp_u_field(x, 15, 11); } goetz@6458: goetz@6458: #define opp_u_field(x, hi_bit, lo_bit) u_field(x, 31-(lo_bit), 31-(hi_bit)) goetz@6458: #define opp_s_field(x, hi_bit, lo_bit) s_field(x, 31-(lo_bit), 31-(hi_bit)) goetz@6458: goetz@6458: // instruction fields goetz@6458: static int aa( int x) { return opp_u_field(x, 30, 30); } goetz@6458: static int ba( int x) { return opp_u_field(x, 15, 11); } goetz@6458: static int bb( int x) { return opp_u_field(x, 20, 16); } goetz@6458: static int bc( int x) { return opp_u_field(x, 25, 21); } goetz@6458: static int bd( int x) { return opp_s_field(x, 29, 16); } goetz@6458: static int bf( ConditionRegister cr) { return bf(cr->encoding()); } goetz@6458: static int bf( int x) { return opp_u_field(x, 8, 6); } goetz@6458: static int bfa(ConditionRegister cr) { return bfa(cr->encoding()); } goetz@6458: static int bfa( int x) { return opp_u_field(x, 13, 11); } goetz@6458: static int bh( int x) { return opp_u_field(x, 20, 19); } goetz@6458: static int bi( int x) { return opp_u_field(x, 15, 11); } goetz@6458: static int bi0(ConditionRegister cr, Condition c) { return (cr->encoding() << 2) | c; } goetz@6458: static int bo( int x) { return opp_u_field(x, 10, 6); } goetz@6458: static int bt( int x) { return opp_u_field(x, 10, 6); } goetz@6458: static int d1( int x) { return opp_s_field(x, 31, 16); } goetz@6458: static int ds( int x) { assert((x & 0x3) == 0, "unaligned offset"); return opp_s_field(x, 31, 16); } goetz@6458: static int eh( int x) { return opp_u_field(x, 31, 31); } goetz@6458: static int flm( int x) { return opp_u_field(x, 14, 7); } goetz@6458: static int fra( FloatRegister r) { return fra(r->encoding());} goetz@6458: static int frb( FloatRegister r) { return frb(r->encoding());} goetz@6458: static int frc( FloatRegister r) { return frc(r->encoding());} goetz@6458: static int frs( FloatRegister r) { return frs(r->encoding());} goetz@6458: static int frt( FloatRegister r) { return frt(r->encoding());} goetz@6458: static int fra( int x) { return opp_u_field(x, 15, 11); } goetz@6458: static int frb( int x) { return opp_u_field(x, 20, 16); } goetz@6458: static int frc( int x) { return opp_u_field(x, 25, 21); } goetz@6458: static int frs( int x) { return opp_u_field(x, 10, 6); } goetz@6458: static int frt( int x) { return opp_u_field(x, 10, 6); } goetz@6458: static int fxm( int x) { return opp_u_field(x, 19, 12); } goetz@6458: static int l10( int x) { return opp_u_field(x, 10, 10); } goetz@6458: static int l15( int x) { return opp_u_field(x, 15, 15); } goetz@6458: static int l910( int x) { return opp_u_field(x, 10, 9); } goetz@6495: static int e1215( int x) { return opp_u_field(x, 15, 12); } goetz@6458: static int lev( int x) { return opp_u_field(x, 26, 20); } goetz@6458: static int li( int x) { return opp_s_field(x, 29, 6); } goetz@6458: static int lk( int x) { return opp_u_field(x, 31, 31); } goetz@6458: static int mb2125( int x) { return opp_u_field(x, 25, 21); } goetz@6458: static int me2630( int x) { return opp_u_field(x, 30, 26); } goetz@6458: static int mb2126( int x) { return opp_u_field(((x & 0x1f) << 1) | ((x & 0x20) >> 5), 26, 21); } goetz@6458: static int me2126( int x) { return mb2126(x); } goetz@6458: static int nb( int x) { return opp_u_field(x, 20, 16); } goetz@6458: //static int opcd( int x) { return opp_u_field(x, 5, 0); } // is contained in our opcodes goetz@6458: static int oe( int x) { return opp_u_field(x, 21, 21); } goetz@6458: static int ra( Register r) { return ra(r->encoding()); } goetz@6458: static int ra( int x) { return opp_u_field(x, 15, 11); } goetz@6458: static int rb( Register r) { return rb(r->encoding()); } goetz@6458: static int rb( int x) { return opp_u_field(x, 20, 16); } goetz@6458: static int rc( int x) { return opp_u_field(x, 31, 31); } goetz@6458: static int rs( Register r) { return rs(r->encoding()); } goetz@6458: static int rs( int x) { return opp_u_field(x, 10, 6); } goetz@6458: // we don't want to use R0 in memory accesses, because it has value `0' then goetz@6458: static int ra0mem( Register r) { assert(r != R0, "cannot use register R0 in memory access"); return ra(r); } goetz@6458: static int ra0mem( int x) { assert(x != 0, "cannot use register 0 in memory access"); return ra(x); } goetz@6458: goetz@6458: // register r is target goetz@6458: static int rt( Register r) { return rs(r); } goetz@6458: static int rt( int x) { return rs(x); } goetz@6458: static int rta( Register r) { return ra(r); } goetz@6458: static int rta0mem( Register r) { rta(r); return ra0mem(r); } goetz@6458: goetz@6458: static int sh1620( int x) { return opp_u_field(x, 20, 16); } goetz@6458: static int sh30( int x) { return opp_u_field(x, 30, 30); } goetz@6458: static int sh162030( int x) { return sh1620(x & 0x1f) | sh30((x & 0x20) >> 5); } goetz@6458: static int si( int x) { return opp_s_field(x, 31, 16); } goetz@6458: static int spr( int x) { return opp_u_field(x, 20, 11); } goetz@6458: static int sr( int x) { return opp_u_field(x, 15, 12); } goetz@6458: static int tbr( int x) { return opp_u_field(x, 20, 11); } goetz@6458: static int th( int x) { return opp_u_field(x, 10, 7); } goetz@6495: static int thct( int x) { assert((x&8) == 0, "must be valid cache specification"); return th(x); } goetz@6495: static int thds( int x) { assert((x&8) == 8, "must be valid stream specification"); return th(x); } goetz@6458: static int to( int x) { return opp_u_field(x, 10, 6); } goetz@6458: static int u( int x) { return opp_u_field(x, 19, 16); } goetz@6458: static int ui( int x) { return opp_u_field(x, 31, 16); } goetz@6458: goetz@6495: // Support vector instructions for >= Power6. goetz@6458: static int vra( int x) { return opp_u_field(x, 15, 11); } goetz@6458: static int vrb( int x) { return opp_u_field(x, 20, 16); } goetz@6458: static int vrc( int x) { return opp_u_field(x, 25, 21); } goetz@6458: static int vrs( int x) { return opp_u_field(x, 10, 6); } goetz@6458: static int vrt( int x) { return opp_u_field(x, 10, 6); } goetz@6458: goetz@6458: static int vra( VectorRegister r) { return vra(r->encoding());} goetz@6458: static int vrb( VectorRegister r) { return vrb(r->encoding());} goetz@6458: static int vrc( VectorRegister r) { return vrc(r->encoding());} goetz@6458: static int vrs( VectorRegister r) { return vrs(r->encoding());} goetz@6458: static int vrt( VectorRegister r) { return vrt(r->encoding());} goetz@6458: gromero@9687: // Only used on SHA sigma instructions (VX-form) gromero@9687: static int vst( int x) { return opp_u_field(x, 16, 16); } gromero@9687: static int vsix( int x) { return opp_u_field(x, 20, 17); } gromero@9687: gromero@9662: // Support Vector-Scalar (VSX) instructions. gromero@9687: static int vsra( int x) { return opp_u_field(x & 0x1F, 15, 11) | opp_u_field((x & 0x20) >> 5, 29, 29); } gromero@9687: static int vsrb( int x) { return opp_u_field(x & 0x1F, 20, 16) | opp_u_field((x & 0x20) >> 5, 30, 30); } gromero@9687: static int vsrs( int x) { return opp_u_field(x & 0x1F, 10, 6) | opp_u_field((x & 0x20) >> 5, 31, 31); } gromero@9687: static int vsrt( int x) { return vsrs(x); } gromero@9687: static int vsdm( int x) { return opp_u_field(x, 23, 22); } gromero@9662: gromero@9662: static int vsra( VectorSRegister r) { return vsra(r->encoding());} gromero@9662: static int vsrb( VectorSRegister r) { return vsrb(r->encoding());} gromero@9662: static int vsrs( VectorSRegister r) { return vsrs(r->encoding());} gromero@9662: static int vsrt( VectorSRegister r) { return vsrt(r->encoding());} gromero@9662: goetz@6458: static int vsplt_uim( int x) { return opp_u_field(x, 15, 12); } // for vsplt* instructions goetz@6458: static int vsplti_sim(int x) { return opp_u_field(x, 15, 11); } // for vsplti* instructions goetz@6458: static int vsldoi_shb(int x) { return opp_u_field(x, 25, 22); } // for vsldoi instruction goetz@6458: static int vcmp_rc( int x) { return opp_u_field(x, 21, 21); } // for vcmp* instructions goetz@6458: goetz@6458: //static int xo1( int x) { return opp_u_field(x, 29, 21); }// is contained in our opcodes goetz@6458: //static int xo2( int x) { return opp_u_field(x, 30, 21); }// is contained in our opcodes goetz@6458: //static int xo3( int x) { return opp_u_field(x, 30, 22); }// is contained in our opcodes goetz@6458: //static int xo4( int x) { return opp_u_field(x, 30, 26); }// is contained in our opcodes goetz@6458: //static int xo5( int x) { return opp_u_field(x, 29, 27); }// is contained in our opcodes goetz@6458: //static int xo6( int x) { return opp_u_field(x, 30, 27); }// is contained in our opcodes goetz@6458: //static int xo7( int x) { return opp_u_field(x, 31, 30); }// is contained in our opcodes goetz@6458: goetz@6458: protected: goetz@6458: // Compute relative address for branch. goetz@6458: static intptr_t disp(intptr_t x, intptr_t off) { goetz@6458: int xx = x - off; goetz@6458: xx = xx >> 2; goetz@6458: return xx; goetz@6458: } goetz@6458: goetz@6458: public: goetz@6458: // signed immediate, in low bits, nbits long goetz@6458: static int simm(int x, int nbits) { goetz@6458: assert_signed_range(x, nbits); goetz@6458: return x & ((1 << nbits) - 1); goetz@6458: } goetz@6458: goetz@6458: // unsigned immediate, in low bits, nbits long goetz@6458: static int uimm(int x, int nbits) { goetz@6458: assert_unsigned_const(x, nbits); goetz@6458: return x & ((1 << nbits) - 1); goetz@6458: } goetz@6458: goetz@6458: static void set_imm(int* instr, short s) { kvn@6538: // imm is always in the lower 16 bits of the instruction, kvn@6538: // so this is endian-neutral. Same for the get_imm below. kvn@6538: uint32_t w = *(uint32_t *)instr; kvn@6538: *instr = (int)((w & ~0x0000FFFF) | (s & 0x0000FFFF)); goetz@6458: } goetz@6458: goetz@6458: static int get_imm(address a, int instruction_number) { kvn@6538: return (short)((int *)a)[instruction_number]; goetz@6458: } goetz@6458: goetz@6458: static inline int hi16_signed( int x) { return (int)(int16_t)(x >> 16); } goetz@6458: static inline int lo16_unsigned(int x) { return x & 0xffff; } goetz@6458: goetz@6458: protected: goetz@6458: goetz@6458: // Extract the top 32 bits in a 64 bit word. goetz@6458: static int32_t hi32(int64_t x) { goetz@6458: int32_t r = int32_t((uint64_t)x >> 32); goetz@6458: return r; goetz@6458: } goetz@6458: goetz@6458: public: goetz@6458: goetz@6458: static inline unsigned int align_addr(unsigned int addr, unsigned int a) { goetz@6458: return ((addr + (a - 1)) & ~(a - 1)); goetz@6458: } goetz@6458: goetz@6458: static inline bool is_aligned(unsigned int addr, unsigned int a) { goetz@6458: return (0 == addr % a); goetz@6458: } goetz@6458: goetz@6458: void flush() { goetz@6458: AbstractAssembler::flush(); goetz@6458: } goetz@6458: goetz@6458: inline void emit_int32(int); // shadows AbstractAssembler::emit_int32 goetz@6458: inline void emit_data(int); goetz@6458: inline void emit_data(int, RelocationHolder const&); goetz@6458: inline void emit_data(int, relocInfo::relocType rtype); goetz@6458: goetz@6458: // Emit an address. goetz@6458: inline address emit_addr(const address addr = NULL); goetz@6458: goetz@6511: #if !defined(ABI_ELFv2) goetz@6458: // Emit a function descriptor with the specified entry point, TOC, goetz@6458: // and ENV. If the entry point is NULL, the descriptor will point goetz@6458: // just past the descriptor. goetz@6458: // Use values from friend functions as defaults. goetz@6458: inline address emit_fd(address entry = NULL, goetz@6458: address toc = (address) FunctionDescriptor::friend_toc, goetz@6458: address env = (address) FunctionDescriptor::friend_env); goetz@6511: #endif goetz@6458: goetz@6458: ///////////////////////////////////////////////////////////////////////////////////// goetz@6458: // PPC instructions goetz@6458: ///////////////////////////////////////////////////////////////////////////////////// goetz@6458: goetz@6458: // Memory instructions use r0 as hard coded 0, e.g. to simulate loading goetz@6458: // immediates. The normal instruction encoders enforce that r0 is not goetz@6458: // passed to them. Use either extended mnemonics encoders or the special ra0 goetz@6458: // versions. goetz@6458: goetz@6458: // Issue an illegal instruction. goetz@6458: inline void illtrap(); goetz@6458: static inline bool is_illtrap(int x); goetz@6458: goetz@6458: // PPC 1, section 3.3.8, Fixed-Point Arithmetic Instructions goetz@6458: inline void addi( Register d, Register a, int si16); goetz@6458: inline void addis(Register d, Register a, int si16); goetz@6458: private: goetz@6458: inline void addi_r0ok( Register d, Register a, int si16); goetz@6458: inline void addis_r0ok(Register d, Register a, int si16); goetz@6458: public: goetz@6458: inline void addic_( Register d, Register a, int si16); goetz@6458: inline void subfic( Register d, Register a, int si16); goetz@6458: inline void add( Register d, Register a, Register b); goetz@6458: inline void add_( Register d, Register a, Register b); goetz@6495: inline void subf( Register d, Register a, Register b); // d = b - a "Sub_from", as in ppc spec. goetz@6495: inline void sub( Register d, Register a, Register b); // d = a - b Swap operands of subf for readability. goetz@6458: inline void subf_( Register d, Register a, Register b); goetz@6458: inline void addc( Register d, Register a, Register b); goetz@6458: inline void addc_( Register d, Register a, Register b); goetz@6458: inline void subfc( Register d, Register a, Register b); goetz@6458: inline void subfc_( Register d, Register a, Register b); goetz@6458: inline void adde( Register d, Register a, Register b); goetz@6458: inline void adde_( Register d, Register a, Register b); goetz@6458: inline void subfe( Register d, Register a, Register b); goetz@6458: inline void subfe_( Register d, Register a, Register b); goetz@6458: inline void neg( Register d, Register a); goetz@6458: inline void neg_( Register d, Register a); goetz@6458: inline void mulli( Register d, Register a, int si16); goetz@6458: inline void mulld( Register d, Register a, Register b); goetz@6458: inline void mulld_( Register d, Register a, Register b); goetz@6458: inline void mullw( Register d, Register a, Register b); goetz@6458: inline void mullw_( Register d, Register a, Register b); goetz@6458: inline void mulhw( Register d, Register a, Register b); goetz@6458: inline void mulhw_( Register d, Register a, Register b); mdoerr@8903: inline void mulhwu( Register d, Register a, Register b); mdoerr@8903: inline void mulhwu_(Register d, Register a, Register b); goetz@6458: inline void mulhd( Register d, Register a, Register b); goetz@6458: inline void mulhd_( Register d, Register a, Register b); goetz@6458: inline void mulhdu( Register d, Register a, Register b); goetz@6458: inline void mulhdu_(Register d, Register a, Register b); goetz@6458: inline void divd( Register d, Register a, Register b); goetz@6458: inline void divd_( Register d, Register a, Register b); goetz@6458: inline void divw( Register d, Register a, Register b); goetz@6458: inline void divw_( Register d, Register a, Register b); goetz@6458: goetz@6458: // extended mnemonics goetz@6458: inline void li( Register d, int si16); goetz@6458: inline void lis( Register d, int si16); goetz@6458: inline void addir(Register d, int si16, Register a); goetz@6458: goetz@6458: static bool is_addi(int x) { goetz@6458: return ADDI_OPCODE == (x & ADDI_OPCODE_MASK); goetz@6458: } goetz@6458: static bool is_addis(int x) { goetz@6458: return ADDIS_OPCODE == (x & ADDIS_OPCODE_MASK); goetz@6458: } goetz@6458: static bool is_bxx(int x) { goetz@6458: return BXX_OPCODE == (x & BXX_OPCODE_MASK); goetz@6458: } goetz@6458: static bool is_b(int x) { goetz@6458: return BXX_OPCODE == (x & BXX_OPCODE_MASK) && inv_lk_field(x) == 0; goetz@6458: } goetz@6458: static bool is_bl(int x) { goetz@6458: return BXX_OPCODE == (x & BXX_OPCODE_MASK) && inv_lk_field(x) == 1; goetz@6458: } goetz@6458: static bool is_bcxx(int x) { goetz@6458: return BCXX_OPCODE == (x & BCXX_OPCODE_MASK); goetz@6458: } goetz@6458: static bool is_bxx_or_bcxx(int x) { goetz@6458: return is_bxx(x) || is_bcxx(x); goetz@6458: } goetz@6458: static bool is_bctrl(int x) { goetz@6458: return x == 0x4e800421; goetz@6458: } goetz@6458: static bool is_bctr(int x) { goetz@6458: return x == 0x4e800420; goetz@6458: } goetz@6458: static bool is_bclr(int x) { goetz@6458: return BCLR_OPCODE == (x & XL_FORM_OPCODE_MASK); goetz@6458: } goetz@6458: static bool is_li(int x) { goetz@6458: return is_addi(x) && inv_ra_field(x)==0; goetz@6458: } goetz@6458: static bool is_lis(int x) { goetz@6458: return is_addis(x) && inv_ra_field(x)==0; goetz@6458: } goetz@6458: static bool is_mtctr(int x) { goetz@6458: return MTCTR_OPCODE == (x & MTCTR_OPCODE_MASK); goetz@6458: } goetz@6458: static bool is_ld(int x) { goetz@6458: return LD_OPCODE == (x & LD_OPCODE_MASK); goetz@6458: } goetz@6458: static bool is_std(int x) { goetz@6458: return STD_OPCODE == (x & STD_OPCODE_MASK); goetz@6458: } goetz@6458: static bool is_stdu(int x) { goetz@6458: return STDU_OPCODE == (x & STDU_OPCODE_MASK); goetz@6458: } goetz@6458: static bool is_stdx(int x) { goetz@6458: return STDX_OPCODE == (x & STDX_OPCODE_MASK); goetz@6458: } goetz@6458: static bool is_stdux(int x) { goetz@6458: return STDUX_OPCODE == (x & STDUX_OPCODE_MASK); goetz@6458: } goetz@6458: static bool is_stwx(int x) { goetz@6458: return STWX_OPCODE == (x & STWX_OPCODE_MASK); goetz@6458: } goetz@6458: static bool is_stwux(int x) { goetz@6458: return STWUX_OPCODE == (x & STWUX_OPCODE_MASK); goetz@6458: } goetz@6458: static bool is_stw(int x) { goetz@6458: return STW_OPCODE == (x & STW_OPCODE_MASK); goetz@6458: } goetz@6458: static bool is_stwu(int x) { goetz@6458: return STWU_OPCODE == (x & STWU_OPCODE_MASK); goetz@6458: } goetz@6458: static bool is_ori(int x) { goetz@6458: return ORI_OPCODE == (x & ORI_OPCODE_MASK); goetz@6458: }; goetz@6458: static bool is_oris(int x) { goetz@6458: return ORIS_OPCODE == (x & ORIS_OPCODE_MASK); goetz@6458: }; goetz@6458: static bool is_rldicr(int x) { goetz@6458: return (RLDICR_OPCODE == (x & RLDICR_OPCODE_MASK)); goetz@6458: }; goetz@6458: static bool is_nop(int x) { goetz@6458: return x == 0x60000000; goetz@6458: } goetz@6458: // endgroup opcode for Power6 goetz@6458: static bool is_endgroup(int x) { goetz@6495: return is_ori(x) && inv_ra_field(x) == 1 && inv_rs_field(x) == 1 && inv_d1_field(x) == 0; goetz@6458: } goetz@6458: goetz@6458: goetz@6458: private: goetz@6458: // PPC 1, section 3.3.9, Fixed-Point Compare Instructions goetz@6458: inline void cmpi( ConditionRegister bf, int l, Register a, int si16); goetz@6458: inline void cmp( ConditionRegister bf, int l, Register a, Register b); goetz@6458: inline void cmpli(ConditionRegister bf, int l, Register a, int ui16); goetz@6458: inline void cmpl( ConditionRegister bf, int l, Register a, Register b); goetz@6458: goetz@6458: public: goetz@6458: // extended mnemonics of Compare Instructions goetz@6458: inline void cmpwi( ConditionRegister crx, Register a, int si16); goetz@6458: inline void cmpdi( ConditionRegister crx, Register a, int si16); goetz@6458: inline void cmpw( ConditionRegister crx, Register a, Register b); goetz@6458: inline void cmpd( ConditionRegister crx, Register a, Register b); goetz@6458: inline void cmplwi(ConditionRegister crx, Register a, int ui16); goetz@6458: inline void cmpldi(ConditionRegister crx, Register a, int ui16); goetz@6458: inline void cmplw( ConditionRegister crx, Register a, Register b); goetz@6458: inline void cmpld( ConditionRegister crx, Register a, Register b); goetz@6458: goetz@6458: inline void isel( Register d, Register a, Register b, int bc); goetz@6495: // Convenient version which takes: Condition register, Condition code and invert flag. Omit b to keep old value. goetz@6495: inline void isel( Register d, ConditionRegister cr, Condition cc, bool inv, Register a, Register b = noreg); goetz@6495: // Set d = 0 if (cr.cc) equals 1, otherwise b. goetz@6495: inline void isel_0( Register d, ConditionRegister cr, Condition cc, Register b = noreg); goetz@6458: goetz@6458: // PPC 1, section 3.3.11, Fixed-Point Logical Instructions goetz@6495: void andi( Register a, Register s, int ui16); // optimized version goetz@6458: inline void andi_( Register a, Register s, int ui16); goetz@6458: inline void andis_( Register a, Register s, int ui16); goetz@6458: inline void ori( Register a, Register s, int ui16); goetz@6458: inline void oris( Register a, Register s, int ui16); goetz@6458: inline void xori( Register a, Register s, int ui16); goetz@6458: inline void xoris( Register a, Register s, int ui16); goetz@6458: inline void andr( Register a, Register s, Register b); // suffixed by 'r' as 'and' is C++ keyword goetz@6458: inline void and_( Register a, Register s, Register b); goetz@6458: // Turn or0(rx,rx,rx) into a nop and avoid that we accidently emit a goetz@6458: // SMT-priority change instruction (see SMT instructions below). goetz@6458: inline void or_unchecked(Register a, Register s, Register b); goetz@6458: inline void orr( Register a, Register s, Register b); // suffixed by 'r' as 'or' is C++ keyword goetz@6458: inline void or_( Register a, Register s, Register b); goetz@6458: inline void xorr( Register a, Register s, Register b); // suffixed by 'r' as 'xor' is C++ keyword goetz@6458: inline void xor_( Register a, Register s, Register b); goetz@6458: inline void nand( Register a, Register s, Register b); goetz@6458: inline void nand_( Register a, Register s, Register b); goetz@6458: inline void nor( Register a, Register s, Register b); goetz@6458: inline void nor_( Register a, Register s, Register b); goetz@6458: inline void andc( Register a, Register s, Register b); goetz@6458: inline void andc_( Register a, Register s, Register b); goetz@6458: inline void orc( Register a, Register s, Register b); goetz@6458: inline void orc_( Register a, Register s, Register b); goetz@6458: inline void extsb( Register a, Register s); goetz@6458: inline void extsh( Register a, Register s); goetz@6458: inline void extsw( Register a, Register s); goetz@6458: goetz@6458: // extended mnemonics goetz@6458: inline void nop(); goetz@6458: // NOP for FP and BR units (different versions to allow them to be in one group) goetz@6458: inline void fpnop0(); goetz@6458: inline void fpnop1(); goetz@6458: inline void brnop0(); goetz@6458: inline void brnop1(); goetz@6458: inline void brnop2(); goetz@6458: goetz@6458: inline void mr( Register d, Register s); goetz@6458: inline void ori_opt( Register d, int ui16); goetz@6458: inline void oris_opt(Register d, int ui16); goetz@6458: goetz@6458: // endgroup opcode for Power6 goetz@6458: inline void endgroup(); goetz@6458: goetz@6458: // count instructions goetz@6458: inline void cntlzw( Register a, Register s); goetz@6458: inline void cntlzw_( Register a, Register s); goetz@6458: inline void cntlzd( Register a, Register s); goetz@6458: inline void cntlzd_( Register a, Register s); goetz@6458: goetz@6458: // PPC 1, section 3.3.12, Fixed-Point Rotate and Shift Instructions goetz@6458: inline void sld( Register a, Register s, Register b); goetz@6458: inline void sld_( Register a, Register s, Register b); goetz@6458: inline void slw( Register a, Register s, Register b); goetz@6458: inline void slw_( Register a, Register s, Register b); goetz@6458: inline void srd( Register a, Register s, Register b); goetz@6458: inline void srd_( Register a, Register s, Register b); goetz@6458: inline void srw( Register a, Register s, Register b); goetz@6458: inline void srw_( Register a, Register s, Register b); goetz@6458: inline void srad( Register a, Register s, Register b); goetz@6458: inline void srad_( Register a, Register s, Register b); goetz@6458: inline void sraw( Register a, Register s, Register b); goetz@6458: inline void sraw_( Register a, Register s, Register b); goetz@6458: inline void sradi( Register a, Register s, int sh6); goetz@6458: inline void sradi_( Register a, Register s, int sh6); goetz@6458: inline void srawi( Register a, Register s, int sh5); goetz@6458: inline void srawi_( Register a, Register s, int sh5); goetz@6458: goetz@6458: // extended mnemonics for Shift Instructions goetz@6458: inline void sldi( Register a, Register s, int sh6); goetz@6458: inline void sldi_( Register a, Register s, int sh6); goetz@6458: inline void slwi( Register a, Register s, int sh5); goetz@6458: inline void slwi_( Register a, Register s, int sh5); goetz@6458: inline void srdi( Register a, Register s, int sh6); goetz@6458: inline void srdi_( Register a, Register s, int sh6); goetz@6458: inline void srwi( Register a, Register s, int sh5); goetz@6458: inline void srwi_( Register a, Register s, int sh5); goetz@6458: goetz@6458: inline void clrrdi( Register a, Register s, int ui6); goetz@6458: inline void clrrdi_( Register a, Register s, int ui6); goetz@6458: inline void clrldi( Register a, Register s, int ui6); goetz@6458: inline void clrldi_( Register a, Register s, int ui6); goetz@6458: inline void clrlsldi(Register a, Register s, int clrl6, int shl6); goetz@6458: inline void clrlsldi_(Register a, Register s, int clrl6, int shl6); goetz@6458: inline void extrdi( Register a, Register s, int n, int b); goetz@6458: // testbit with condition register goetz@6458: inline void testbitdi(ConditionRegister cr, Register a, Register s, int ui6); goetz@6458: goetz@6458: // rotate instructions goetz@6458: inline void rotldi( Register a, Register s, int n); goetz@6458: inline void rotrdi( Register a, Register s, int n); goetz@6458: inline void rotlwi( Register a, Register s, int n); goetz@6458: inline void rotrwi( Register a, Register s, int n); goetz@6458: goetz@6458: // Rotate Instructions goetz@6458: inline void rldic( Register a, Register s, int sh6, int mb6); goetz@6458: inline void rldic_( Register a, Register s, int sh6, int mb6); goetz@6458: inline void rldicr( Register a, Register s, int sh6, int mb6); goetz@6458: inline void rldicr_( Register a, Register s, int sh6, int mb6); goetz@6458: inline void rldicl( Register a, Register s, int sh6, int mb6); goetz@6458: inline void rldicl_( Register a, Register s, int sh6, int mb6); goetz@6458: inline void rlwinm( Register a, Register s, int sh5, int mb5, int me5); goetz@6458: inline void rlwinm_( Register a, Register s, int sh5, int mb5, int me5); goetz@6458: inline void rldimi( Register a, Register s, int sh6, int mb6); goetz@6458: inline void rldimi_( Register a, Register s, int sh6, int mb6); goetz@6458: inline void rlwimi( Register a, Register s, int sh5, int mb5, int me5); goetz@6458: inline void insrdi( Register a, Register s, int n, int b); goetz@6458: inline void insrwi( Register a, Register s, int n, int b); goetz@6458: goetz@6458: // PPC 1, section 3.3.2 Fixed-Point Load Instructions goetz@6458: // 4 bytes goetz@6458: inline void lwzx( Register d, Register s1, Register s2); goetz@6458: inline void lwz( Register d, int si16, Register s1); goetz@6458: inline void lwzu( Register d, int si16, Register s1); goetz@6458: goetz@6458: // 4 bytes goetz@6458: inline void lwax( Register d, Register s1, Register s2); goetz@6458: inline void lwa( Register d, int si16, Register s1); goetz@6458: kvn@7132: // 4 bytes reversed kvn@7132: inline void lwbrx( Register d, Register s1, Register s2); kvn@7132: goetz@6458: // 2 bytes goetz@6458: inline void lhzx( Register d, Register s1, Register s2); goetz@6458: inline void lhz( Register d, int si16, Register s1); goetz@6458: inline void lhzu( Register d, int si16, Register s1); goetz@6458: kvn@7132: // 2 bytes reversed kvn@7132: inline void lhbrx( Register d, Register s1, Register s2); kvn@7132: goetz@6458: // 2 bytes goetz@6458: inline void lhax( Register d, Register s1, Register s2); goetz@6458: inline void lha( Register d, int si16, Register s1); goetz@6458: inline void lhau( Register d, int si16, Register s1); goetz@6458: goetz@6458: // 1 byte goetz@6458: inline void lbzx( Register d, Register s1, Register s2); goetz@6458: inline void lbz( Register d, int si16, Register s1); goetz@6458: inline void lbzu( Register d, int si16, Register s1); goetz@6458: goetz@6458: // 8 bytes goetz@6458: inline void ldx( Register d, Register s1, Register s2); goetz@6458: inline void ld( Register d, int si16, Register s1); goetz@6458: inline void ldu( Register d, int si16, Register s1); goetz@6458: goetz@6458: // PPC 1, section 3.3.3 Fixed-Point Store Instructions goetz@6458: inline void stwx( Register d, Register s1, Register s2); goetz@6458: inline void stw( Register d, int si16, Register s1); goetz@6458: inline void stwu( Register d, int si16, Register s1); goetz@6458: goetz@6458: inline void sthx( Register d, Register s1, Register s2); goetz@6458: inline void sth( Register d, int si16, Register s1); goetz@6458: inline void sthu( Register d, int si16, Register s1); goetz@6458: goetz@6458: inline void stbx( Register d, Register s1, Register s2); goetz@6458: inline void stb( Register d, int si16, Register s1); goetz@6458: inline void stbu( Register d, int si16, Register s1); goetz@6458: goetz@6458: inline void stdx( Register d, Register s1, Register s2); goetz@6458: inline void std( Register d, int si16, Register s1); goetz@6458: inline void stdu( Register d, int si16, Register s1); goetz@6458: inline void stdux(Register s, Register a, Register b); goetz@6458: goetz@6458: // PPC 1, section 3.3.13 Move To/From System Register Instructions goetz@6458: inline void mtlr( Register s1); goetz@6458: inline void mflr( Register d); goetz@6458: inline void mtctr(Register s1); goetz@6458: inline void mfctr(Register d); goetz@6458: inline void mtcrf(int fxm, Register s); goetz@6458: inline void mfcr( Register d); goetz@6458: inline void mcrf( ConditionRegister crd, ConditionRegister cra); goetz@6458: inline void mtcr( Register s); goetz@6458: goetz@7222: // Special purpose registers goetz@7222: // Exception Register goetz@7222: inline void mtxer(Register s1); goetz@7222: inline void mfxer(Register d); goetz@7222: // Vector Register Save Register goetz@7222: inline void mtvrsave(Register s1); goetz@7222: inline void mfvrsave(Register d); goetz@7222: // Timebase goetz@7222: inline void mftb(Register d); goetz@7222: // Introduced with Power 8: goetz@7222: // Data Stream Control Register goetz@7222: inline void mtdscr(Register s1); goetz@7222: inline void mfdscr(Register d ); goetz@7222: // Transactional Memory Registers goetz@7222: inline void mftfhar(Register d); goetz@7222: inline void mftfiar(Register d); goetz@7222: inline void mftexasr(Register d); goetz@7222: inline void mftexasru(Register d); goetz@7222: goetz@6458: // PPC 1, section 2.4.1 Branch Instructions goetz@6458: inline void b( address a, relocInfo::relocType rt = relocInfo::none); goetz@6458: inline void b( Label& L); goetz@6458: inline void bl( address a, relocInfo::relocType rt = relocInfo::none); goetz@6458: inline void bl( Label& L); goetz@6458: inline void bc( int boint, int biint, address a, relocInfo::relocType rt = relocInfo::none); goetz@6458: inline void bc( int boint, int biint, Label& L); goetz@6458: inline void bcl(int boint, int biint, address a, relocInfo::relocType rt = relocInfo::none); goetz@6458: inline void bcl(int boint, int biint, Label& L); goetz@6458: goetz@6458: inline void bclr( int boint, int biint, int bhint, relocInfo::relocType rt = relocInfo::none); goetz@6458: inline void bclrl( int boint, int biint, int bhint, relocInfo::relocType rt = relocInfo::none); goetz@6458: inline void bcctr( int boint, int biint, int bhint = bhintbhBCCTRisNotReturnButSame, goetz@6458: relocInfo::relocType rt = relocInfo::none); goetz@6458: inline void bcctrl(int boint, int biint, int bhint = bhintbhBCLRisReturn, goetz@6458: relocInfo::relocType rt = relocInfo::none); goetz@6458: goetz@6458: // helper function for b, bcxx goetz@6458: inline bool is_within_range_of_b(address a, address pc); goetz@6458: inline bool is_within_range_of_bcxx(address a, address pc); goetz@6458: goetz@6458: // get the destination of a bxx branch (b, bl, ba, bla) goetz@6458: static inline address bxx_destination(address baddr); goetz@6458: static inline address bxx_destination(int instr, address pc); goetz@6458: static inline intptr_t bxx_destination_offset(int instr, intptr_t bxx_pos); goetz@6458: goetz@6458: // extended mnemonics for branch instructions goetz@6458: inline void blt(ConditionRegister crx, Label& L); goetz@6458: inline void bgt(ConditionRegister crx, Label& L); goetz@6458: inline void beq(ConditionRegister crx, Label& L); goetz@6458: inline void bso(ConditionRegister crx, Label& L); goetz@6458: inline void bge(ConditionRegister crx, Label& L); goetz@6458: inline void ble(ConditionRegister crx, Label& L); goetz@6458: inline void bne(ConditionRegister crx, Label& L); goetz@6458: inline void bns(ConditionRegister crx, Label& L); goetz@6458: goetz@6458: // Branch instructions with static prediction hints. goetz@6458: inline void blt_predict_taken( ConditionRegister crx, Label& L); goetz@6458: inline void bgt_predict_taken( ConditionRegister crx, Label& L); goetz@6458: inline void beq_predict_taken( ConditionRegister crx, Label& L); goetz@6458: inline void bso_predict_taken( ConditionRegister crx, Label& L); goetz@6458: inline void bge_predict_taken( ConditionRegister crx, Label& L); goetz@6458: inline void ble_predict_taken( ConditionRegister crx, Label& L); goetz@6458: inline void bne_predict_taken( ConditionRegister crx, Label& L); goetz@6458: inline void bns_predict_taken( ConditionRegister crx, Label& L); goetz@6458: inline void blt_predict_not_taken(ConditionRegister crx, Label& L); goetz@6458: inline void bgt_predict_not_taken(ConditionRegister crx, Label& L); goetz@6458: inline void beq_predict_not_taken(ConditionRegister crx, Label& L); goetz@6458: inline void bso_predict_not_taken(ConditionRegister crx, Label& L); goetz@6458: inline void bge_predict_not_taken(ConditionRegister crx, Label& L); goetz@6458: inline void ble_predict_not_taken(ConditionRegister crx, Label& L); goetz@6458: inline void bne_predict_not_taken(ConditionRegister crx, Label& L); goetz@6458: inline void bns_predict_not_taken(ConditionRegister crx, Label& L); goetz@6458: goetz@6458: // for use in conjunction with testbitdi: goetz@6458: inline void btrue( ConditionRegister crx, Label& L); goetz@6458: inline void bfalse(ConditionRegister crx, Label& L); goetz@6458: goetz@6458: inline void bltl(ConditionRegister crx, Label& L); goetz@6458: inline void bgtl(ConditionRegister crx, Label& L); goetz@6458: inline void beql(ConditionRegister crx, Label& L); goetz@6458: inline void bsol(ConditionRegister crx, Label& L); goetz@6458: inline void bgel(ConditionRegister crx, Label& L); goetz@6458: inline void blel(ConditionRegister crx, Label& L); goetz@6458: inline void bnel(ConditionRegister crx, Label& L); goetz@6458: inline void bnsl(ConditionRegister crx, Label& L); goetz@6458: goetz@6458: // extended mnemonics for Branch Instructions via LR goetz@6458: // We use `blr' for returns. goetz@6458: inline void blr(relocInfo::relocType rt = relocInfo::none); goetz@6458: goetz@6458: // extended mnemonics for Branch Instructions with CTR goetz@6458: // bdnz means `decrement CTR and jump to L if CTR is not zero' goetz@6458: inline void bdnz(Label& L); goetz@6458: // Decrement and branch if result is zero. goetz@6458: inline void bdz(Label& L); goetz@6458: // we use `bctr[l]' for jumps/calls in function descriptor glue goetz@6458: // code, e.g. calls to runtime functions goetz@6458: inline void bctr( relocInfo::relocType rt = relocInfo::none); goetz@6458: inline void bctrl(relocInfo::relocType rt = relocInfo::none); goetz@6458: // conditional jumps/branches via CTR goetz@6458: inline void beqctr( ConditionRegister crx, relocInfo::relocType rt = relocInfo::none); goetz@6458: inline void beqctrl(ConditionRegister crx, relocInfo::relocType rt = relocInfo::none); goetz@6458: inline void bnectr( ConditionRegister crx, relocInfo::relocType rt = relocInfo::none); goetz@6458: inline void bnectrl(ConditionRegister crx, relocInfo::relocType rt = relocInfo::none); goetz@6458: goetz@6458: // condition register logic instructions goetz@6458: inline void crand( int d, int s1, int s2); goetz@6458: inline void crnand(int d, int s1, int s2); goetz@6458: inline void cror( int d, int s1, int s2); goetz@6458: inline void crxor( int d, int s1, int s2); goetz@6458: inline void crnor( int d, int s1, int s2); goetz@6458: inline void creqv( int d, int s1, int s2); goetz@6458: inline void crandc(int d, int s1, int s2); goetz@6458: inline void crorc( int d, int s1, int s2); goetz@6458: goetz@6458: // icache and dcache related instructions goetz@6458: inline void icbi( Register s1, Register s2); goetz@6458: //inline void dcba(Register s1, Register s2); // Instruction for embedded processor only. goetz@6458: inline void dcbz( Register s1, Register s2); goetz@6458: inline void dcbst( Register s1, Register s2); goetz@6458: inline void dcbf( Register s1, Register s2); goetz@6458: goetz@6458: enum ct_cache_specification { goetz@6458: ct_primary_cache = 0, goetz@6458: ct_secondary_cache = 2 goetz@6458: }; goetz@6458: // dcache read hint goetz@6458: inline void dcbt( Register s1, Register s2); goetz@6458: inline void dcbtct( Register s1, Register s2, int ct); goetz@6458: inline void dcbtds( Register s1, Register s2, int ds); goetz@6458: // dcache write hint goetz@6458: inline void dcbtst( Register s1, Register s2); goetz@6458: inline void dcbtstct(Register s1, Register s2, int ct); goetz@6458: goetz@6458: // machine barrier instructions: goetz@6458: // goetz@6458: // - sync two-way memory barrier, aka fence goetz@6458: // - lwsync orders Store|Store, goetz@6458: // Load|Store, goetz@6458: // Load|Load, goetz@6458: // but not Store|Load goetz@6458: // - eieio orders memory accesses for device memory (only) goetz@6458: // - isync invalidates speculatively executed instructions goetz@6458: // From the Power ISA 2.06 documentation: goetz@6458: // "[...] an isync instruction prevents the execution of goetz@6458: // instructions following the isync until instructions goetz@6458: // preceding the isync have completed, [...]" goetz@6458: // From IBM's AIX assembler reference: goetz@6458: // "The isync [...] instructions causes the processor to goetz@6458: // refetch any instructions that might have been fetched goetz@6458: // prior to the isync instruction. The instruction isync goetz@6458: // causes the processor to wait for all previous instructions goetz@6458: // to complete. Then any instructions already fetched are goetz@6458: // discarded and instruction processing continues in the goetz@6458: // environment established by the previous instructions." goetz@6458: // goetz@6458: // semantic barrier instructions: goetz@6458: // (as defined in orderAccess.hpp) goetz@6458: // goetz@6458: // - release orders Store|Store, (maps to lwsync) goetz@6458: // Load|Store goetz@6458: // - acquire orders Load|Store, (maps to lwsync) goetz@6458: // Load|Load goetz@6458: // - fence orders Store|Store, (maps to sync) goetz@6458: // Load|Store, goetz@6458: // Load|Load, goetz@6458: // Store|Load goetz@6458: // goetz@6458: private: goetz@6458: inline void sync(int l); goetz@6458: public: goetz@6458: inline void sync(); goetz@6458: inline void lwsync(); goetz@6458: inline void ptesync(); goetz@6458: inline void eieio(); goetz@6458: inline void isync(); goetz@6495: inline void elemental_membar(int e); // Elemental Memory Barriers (>=Power 8) goetz@6458: goetz@6458: // atomics goetz@6458: inline void lwarx_unchecked(Register d, Register a, Register b, int eh1 = 0); goetz@6458: inline void ldarx_unchecked(Register d, Register a, Register b, int eh1 = 0); gromero@9662: inline void lqarx_unchecked(Register d, Register a, Register b, int eh1 = 0); goetz@6458: inline bool lxarx_hint_exclusive_access(); goetz@6458: inline void lwarx( Register d, Register a, Register b, bool hint_exclusive_access = false); goetz@6458: inline void ldarx( Register d, Register a, Register b, bool hint_exclusive_access = false); gromero@9662: inline void lqarx( Register d, Register a, Register b, bool hint_exclusive_access = false); goetz@6458: inline void stwcx_( Register s, Register a, Register b); goetz@6458: inline void stdcx_( Register s, Register a, Register b); gromero@9662: inline void stqcx_( Register s, Register a, Register b); goetz@6458: goetz@6458: // Instructions for adjusting thread priority for simultaneous goetz@6458: // multithreading (SMT) on Power5. goetz@6458: private: goetz@6458: inline void smt_prio_very_low(); goetz@6458: inline void smt_prio_medium_high(); goetz@6458: inline void smt_prio_high(); goetz@6458: goetz@6458: public: goetz@6458: inline void smt_prio_low(); goetz@6458: inline void smt_prio_medium_low(); goetz@6458: inline void smt_prio_medium(); goetz@6458: goetz@6458: // trap instructions goetz@6458: inline void twi_0(Register a); // for load with acquire semantics use load+twi_0+isync (trap can't occur) goetz@6458: // NOT FOR DIRECT USE!! goetz@6458: protected: goetz@6458: inline void tdi_unchecked(int tobits, Register a, int si16); goetz@6458: inline void twi_unchecked(int tobits, Register a, int si16); goetz@6458: inline void tdi( int tobits, Register a, int si16); // asserts UseSIGTRAP goetz@6458: inline void twi( int tobits, Register a, int si16); // asserts UseSIGTRAP goetz@6458: inline void td( int tobits, Register a, Register b); // asserts UseSIGTRAP goetz@6458: inline void tw( int tobits, Register a, Register b); // asserts UseSIGTRAP goetz@6458: goetz@6458: static bool is_tdi(int x, int tobits, int ra, int si16) { goetz@6458: return (TDI_OPCODE == (x & TDI_OPCODE_MASK)) goetz@6458: && (tobits == inv_to_field(x)) goetz@6458: && (ra == -1/*any reg*/ || ra == inv_ra_field(x)) goetz@6458: && (si16 == inv_si_field(x)); goetz@6458: } goetz@6458: goetz@6458: static bool is_twi(int x, int tobits, int ra, int si16) { goetz@6458: return (TWI_OPCODE == (x & TWI_OPCODE_MASK)) goetz@6458: && (tobits == inv_to_field(x)) goetz@6458: && (ra == -1/*any reg*/ || ra == inv_ra_field(x)) goetz@6458: && (si16 == inv_si_field(x)); goetz@6458: } goetz@6458: goetz@6458: static bool is_twi(int x, int tobits, int ra) { goetz@6458: return (TWI_OPCODE == (x & TWI_OPCODE_MASK)) goetz@6458: && (tobits == inv_to_field(x)) goetz@6458: && (ra == -1/*any reg*/ || ra == inv_ra_field(x)); goetz@6458: } goetz@6458: goetz@6458: static bool is_td(int x, int tobits, int ra, int rb) { goetz@6458: return (TD_OPCODE == (x & TD_OPCODE_MASK)) goetz@6458: && (tobits == inv_to_field(x)) goetz@6458: && (ra == -1/*any reg*/ || ra == inv_ra_field(x)) goetz@6458: && (rb == -1/*any reg*/ || rb == inv_rb_field(x)); goetz@6458: } goetz@6458: goetz@6458: static bool is_tw(int x, int tobits, int ra, int rb) { goetz@6458: return (TW_OPCODE == (x & TW_OPCODE_MASK)) goetz@6458: && (tobits == inv_to_field(x)) goetz@6458: && (ra == -1/*any reg*/ || ra == inv_ra_field(x)) goetz@6458: && (rb == -1/*any reg*/ || rb == inv_rb_field(x)); goetz@6458: } goetz@6458: goetz@6458: public: goetz@6458: // PPC floating point instructions goetz@6458: // PPC 1, section 4.6.2 Floating-Point Load Instructions goetz@6458: inline void lfs( FloatRegister d, int si16, Register a); goetz@6458: inline void lfsu( FloatRegister d, int si16, Register a); goetz@6458: inline void lfsx( FloatRegister d, Register a, Register b); goetz@6458: inline void lfd( FloatRegister d, int si16, Register a); goetz@6458: inline void lfdu( FloatRegister d, int si16, Register a); goetz@6458: inline void lfdx( FloatRegister d, Register a, Register b); goetz@6458: goetz@6458: // PPC 1, section 4.6.3 Floating-Point Store Instructions goetz@6458: inline void stfs( FloatRegister s, int si16, Register a); goetz@6458: inline void stfsu( FloatRegister s, int si16, Register a); goetz@6458: inline void stfsx( FloatRegister s, Register a, Register b); goetz@6458: inline void stfd( FloatRegister s, int si16, Register a); goetz@6458: inline void stfdu( FloatRegister s, int si16, Register a); goetz@6458: inline void stfdx( FloatRegister s, Register a, Register b); goetz@6458: goetz@6458: // PPC 1, section 4.6.4 Floating-Point Move Instructions goetz@6458: inline void fmr( FloatRegister d, FloatRegister b); goetz@6458: inline void fmr_( FloatRegister d, FloatRegister b); goetz@6458: goetz@6458: // inline void mffgpr( FloatRegister d, Register b); goetz@6458: // inline void mftgpr( Register d, FloatRegister b); goetz@6458: inline void cmpb( Register a, Register s, Register b); goetz@6458: inline void popcntb(Register a, Register s); goetz@6458: inline void popcntw(Register a, Register s); goetz@6458: inline void popcntd(Register a, Register s); goetz@6458: goetz@6458: inline void fneg( FloatRegister d, FloatRegister b); goetz@6458: inline void fneg_( FloatRegister d, FloatRegister b); goetz@6458: inline void fabs( FloatRegister d, FloatRegister b); goetz@6458: inline void fabs_( FloatRegister d, FloatRegister b); goetz@6458: inline void fnabs( FloatRegister d, FloatRegister b); goetz@6458: inline void fnabs_(FloatRegister d, FloatRegister b); goetz@6458: goetz@6458: // PPC 1, section 4.6.5.1 Floating-Point Elementary Arithmetic Instructions goetz@6458: inline void fadd( FloatRegister d, FloatRegister a, FloatRegister b); goetz@6458: inline void fadd_( FloatRegister d, FloatRegister a, FloatRegister b); goetz@6458: inline void fadds( FloatRegister d, FloatRegister a, FloatRegister b); goetz@6458: inline void fadds_(FloatRegister d, FloatRegister a, FloatRegister b); goetz@6458: inline void fsub( FloatRegister d, FloatRegister a, FloatRegister b); goetz@6458: inline void fsub_( FloatRegister d, FloatRegister a, FloatRegister b); goetz@6458: inline void fsubs( FloatRegister d, FloatRegister a, FloatRegister b); goetz@6458: inline void fsubs_(FloatRegister d, FloatRegister a, FloatRegister b); goetz@6458: inline void fmul( FloatRegister d, FloatRegister a, FloatRegister c); goetz@6458: inline void fmul_( FloatRegister d, FloatRegister a, FloatRegister c); goetz@6458: inline void fmuls( FloatRegister d, FloatRegister a, FloatRegister c); goetz@6458: inline void fmuls_(FloatRegister d, FloatRegister a, FloatRegister c); goetz@6458: inline void fdiv( FloatRegister d, FloatRegister a, FloatRegister b); goetz@6458: inline void fdiv_( FloatRegister d, FloatRegister a, FloatRegister b); goetz@6458: inline void fdivs( FloatRegister d, FloatRegister a, FloatRegister b); goetz@6458: inline void fdivs_(FloatRegister d, FloatRegister a, FloatRegister b); goetz@6458: goetz@6458: // PPC 1, section 4.6.6 Floating-Point Rounding and Conversion Instructions goetz@6458: inline void frsp( FloatRegister d, FloatRegister b); goetz@6458: inline void fctid( FloatRegister d, FloatRegister b); goetz@6458: inline void fctidz(FloatRegister d, FloatRegister b); goetz@6458: inline void fctiw( FloatRegister d, FloatRegister b); goetz@6458: inline void fctiwz(FloatRegister d, FloatRegister b); goetz@6458: inline void fcfid( FloatRegister d, FloatRegister b); goetz@6458: inline void fcfids(FloatRegister d, FloatRegister b); goetz@6458: goetz@6458: // PPC 1, section 4.6.7 Floating-Point Compare Instructions goetz@6458: inline void fcmpu( ConditionRegister crx, FloatRegister a, FloatRegister b); goetz@6458: goetz@6458: inline void fsqrt( FloatRegister d, FloatRegister b); goetz@6458: inline void fsqrts(FloatRegister d, FloatRegister b); goetz@6458: goetz@6458: // Vector instructions for >= Power6. goetz@6458: inline void lvebx( VectorRegister d, Register s1, Register s2); goetz@6458: inline void lvehx( VectorRegister d, Register s1, Register s2); goetz@6458: inline void lvewx( VectorRegister d, Register s1, Register s2); goetz@6458: inline void lvx( VectorRegister d, Register s1, Register s2); goetz@6458: inline void lvxl( VectorRegister d, Register s1, Register s2); goetz@6458: inline void stvebx( VectorRegister d, Register s1, Register s2); goetz@6458: inline void stvehx( VectorRegister d, Register s1, Register s2); goetz@6458: inline void stvewx( VectorRegister d, Register s1, Register s2); goetz@6458: inline void stvx( VectorRegister d, Register s1, Register s2); goetz@6458: inline void stvxl( VectorRegister d, Register s1, Register s2); goetz@6458: inline void lvsl( VectorRegister d, Register s1, Register s2); goetz@6458: inline void lvsr( VectorRegister d, Register s1, Register s2); goetz@6458: inline void vpkpx( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vpkshss( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vpkswss( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vpkshus( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vpkswus( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vpkuhum( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vpkuwum( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vpkuhus( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vpkuwus( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vupkhpx( VectorRegister d, VectorRegister b); goetz@6458: inline void vupkhsb( VectorRegister d, VectorRegister b); goetz@6458: inline void vupkhsh( VectorRegister d, VectorRegister b); goetz@6458: inline void vupklpx( VectorRegister d, VectorRegister b); goetz@6458: inline void vupklsb( VectorRegister d, VectorRegister b); goetz@6458: inline void vupklsh( VectorRegister d, VectorRegister b); goetz@6458: inline void vmrghb( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vmrghw( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vmrghh( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vmrglb( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vmrglw( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vmrglh( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vsplt( VectorRegister d, int ui4, VectorRegister b); goetz@6458: inline void vsplth( VectorRegister d, int ui3, VectorRegister b); goetz@6458: inline void vspltw( VectorRegister d, int ui2, VectorRegister b); goetz@6458: inline void vspltisb( VectorRegister d, int si5); goetz@6458: inline void vspltish( VectorRegister d, int si5); goetz@6458: inline void vspltisw( VectorRegister d, int si5); goetz@6458: inline void vperm( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); goetz@6458: inline void vsel( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); goetz@6458: inline void vsl( VectorRegister d, VectorRegister a, VectorRegister b); mdoerr@9603: inline void vsldoi( VectorRegister d, VectorRegister a, VectorRegister b, int ui4); goetz@6458: inline void vslo( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vsr( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vsro( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vaddcuw( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vaddshs( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vaddsbs( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vaddsws( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vaddubm( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vadduwm( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vadduhm( VectorRegister d, VectorRegister a, VectorRegister b); gromero@9687: inline void vaddudm( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vaddubs( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vadduws( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vadduhs( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vsubcuw( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vsubshs( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vsubsbs( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vsubsws( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vsububm( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vsubuwm( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vsubuhm( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vsububs( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vsubuws( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vsubuhs( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vmulesb( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vmuleub( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vmulesh( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vmuleuh( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vmulosb( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vmuloub( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vmulosh( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vmulouh( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vmhaddshs(VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); goetz@6458: inline void vmhraddshs(VectorRegister d,VectorRegister a, VectorRegister b, VectorRegister c); goetz@6458: inline void vmladduhm(VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); goetz@6458: inline void vmsubuhm( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); goetz@6458: inline void vmsummbm( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); goetz@6458: inline void vmsumshm( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); goetz@6458: inline void vmsumshs( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); goetz@6458: inline void vmsumuhm( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); goetz@6458: inline void vmsumuhs( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); goetz@6458: inline void vsumsws( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vsum2sws( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vsum4sbs( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vsum4ubs( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vsum4shs( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vavgsb( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vavgsw( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vavgsh( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vavgub( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vavguw( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vavguh( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vmaxsb( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vmaxsw( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vmaxsh( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vmaxub( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vmaxuw( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vmaxuh( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vminsb( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vminsw( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vminsh( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vminub( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vminuw( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vminuh( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vcmpequb( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vcmpequh( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vcmpequw( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vcmpgtsh( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vcmpgtsb( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vcmpgtsw( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vcmpgtub( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vcmpgtuh( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vcmpgtuw( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vcmpequb_(VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vcmpequh_(VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vcmpequw_(VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vcmpgtsh_(VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vcmpgtsb_(VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vcmpgtsw_(VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vcmpgtub_(VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vcmpgtuh_(VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vcmpgtuw_(VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vand( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vandc( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vnor( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vor( VectorRegister d, VectorRegister a, VectorRegister b); gromero@9687: inline void vmr( VectorRegister d, VectorRegister a); goetz@6458: inline void vxor( VectorRegister d, VectorRegister a, VectorRegister b); simonis@8608: inline void vrld( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vrlb( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vrlw( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vrlh( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vslb( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vskw( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vslh( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vsrb( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vsrw( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vsrh( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vsrab( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vsraw( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: inline void vsrah( VectorRegister d, VectorRegister a, VectorRegister b); goetz@6458: // Vector Floating-Point not implemented yet goetz@6458: inline void mtvscr( VectorRegister b); goetz@6458: inline void mfvscr( VectorRegister d); goetz@6458: mdoerr@9497: // Vector-Scalar (VSX) instructions. gromero@9684: inline void lxvd2x( VectorSRegister d, Register a); gromero@9662: inline void lxvd2x( VectorSRegister d, Register a, Register b); gromero@9684: inline void stxvd2x( VectorSRegister d, Register a); gromero@9662: inline void stxvd2x( VectorSRegister d, Register a, Register b); gromero@9687: inline void mtvrwz( VectorRegister d, Register a); gromero@9687: inline void mfvrwz( Register a, VectorRegister d); mdoerr@9497: inline void mtvrd( VectorRegister d, Register a); mdoerr@9497: inline void mfvrd( Register a, VectorRegister d); gromero@9687: inline void xxpermdi( VectorSRegister d, VectorSRegister a, VectorSRegister b, int dm); gromero@9687: inline void xxmrghw( VectorSRegister d, VectorSRegister a, VectorSRegister b); gromero@9687: inline void xxmrglw( VectorSRegister d, VectorSRegister a, VectorSRegister b); gromero@9687: gromero@9687: // VSX Extended Mnemonics gromero@9687: inline void xxspltd( VectorSRegister d, VectorSRegister a, int x); gromero@9687: inline void xxmrghd( VectorSRegister d, VectorSRegister a, VectorSRegister b); gromero@9687: inline void xxmrgld( VectorSRegister d, VectorSRegister a, VectorSRegister b); gromero@9687: inline void xxswapd( VectorSRegister d, VectorSRegister a); mdoerr@9497: goetz@7222: // AES (introduced with Power 8) goetz@7222: inline void vcipher( VectorRegister d, VectorRegister a, VectorRegister b); goetz@7222: inline void vcipherlast( VectorRegister d, VectorRegister a, VectorRegister b); goetz@7222: inline void vncipher( VectorRegister d, VectorRegister a, VectorRegister b); goetz@7222: inline void vncipherlast(VectorRegister d, VectorRegister a, VectorRegister b); goetz@7222: inline void vsbox( VectorRegister d, VectorRegister a); goetz@7222: goetz@7222: // SHA (introduced with Power 8) ogatak@9713: inline void vshasigmad(VectorRegister d, VectorRegister a, bool st, int six); ogatak@9713: inline void vshasigmaw(VectorRegister d, VectorRegister a, bool st, int six); goetz@7222: goetz@7222: // Vector Binary Polynomial Multiplication (introduced with Power 8) goetz@7222: inline void vpmsumb( VectorRegister d, VectorRegister a, VectorRegister b); goetz@7222: inline void vpmsumd( VectorRegister d, VectorRegister a, VectorRegister b); goetz@7222: inline void vpmsumh( VectorRegister d, VectorRegister a, VectorRegister b); goetz@7222: inline void vpmsumw( VectorRegister d, VectorRegister a, VectorRegister b); goetz@7222: goetz@7222: // Vector Permute and Xor (introduced with Power 8) goetz@7222: inline void vpermxor( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); goetz@7222: goetz@7222: // Transactional Memory instructions (introduced with Power 8) goetz@7222: inline void tbegin_(); // R=0 goetz@7222: inline void tbeginrot_(); // R=1 Rollback-Only Transaction goetz@7222: inline void tend_(); // A=0 goetz@7222: inline void tendall_(); // A=1 goetz@7222: inline void tabort_(Register a); goetz@7222: inline void tabortwc_(int t, Register a, Register b); goetz@7222: inline void tabortwci_(int t, Register a, int si); goetz@7222: inline void tabortdc_(int t, Register a, Register b); goetz@7222: inline void tabortdci_(int t, Register a, int si); goetz@7222: inline void tsuspend_(); // tsr with L=0 goetz@7222: inline void tresume_(); // tsr with L=1 goetz@7222: inline void tcheck(int f); goetz@7222: goetz@6458: // The following encoders use r0 as second operand. These instructions goetz@6458: // read r0 as '0'. goetz@6458: inline void lwzx( Register d, Register s2); goetz@6458: inline void lwz( Register d, int si16); goetz@6458: inline void lwax( Register d, Register s2); goetz@6458: inline void lwa( Register d, int si16); kvn@7132: inline void lwbrx(Register d, Register s2); goetz@6458: inline void lhzx( Register d, Register s2); goetz@6458: inline void lhz( Register d, int si16); goetz@6458: inline void lhax( Register d, Register s2); goetz@6458: inline void lha( Register d, int si16); kvn@7132: inline void lhbrx(Register d, Register s2); goetz@6458: inline void lbzx( Register d, Register s2); goetz@6458: inline void lbz( Register d, int si16); goetz@6458: inline void ldx( Register d, Register s2); goetz@6458: inline void ld( Register d, int si16); goetz@6458: inline void stwx( Register d, Register s2); goetz@6458: inline void stw( Register d, int si16); goetz@6458: inline void sthx( Register d, Register s2); goetz@6458: inline void sth( Register d, int si16); goetz@6458: inline void stbx( Register d, Register s2); goetz@6458: inline void stb( Register d, int si16); goetz@6458: inline void stdx( Register d, Register s2); goetz@6458: inline void std( Register d, int si16); goetz@6458: goetz@6458: // PPC 2, section 3.2.1 Instruction Cache Instructions goetz@6458: inline void icbi( Register s2); goetz@6458: // PPC 2, section 3.2.2 Data Cache Instructions goetz@6458: //inlinevoid dcba( Register s2); // Instruction for embedded processor only. goetz@6458: inline void dcbz( Register s2); goetz@6458: inline void dcbst( Register s2); goetz@6458: inline void dcbf( Register s2); goetz@6458: // dcache read hint goetz@6458: inline void dcbt( Register s2); goetz@6458: inline void dcbtct( Register s2, int ct); goetz@6458: inline void dcbtds( Register s2, int ds); goetz@6458: // dcache write hint goetz@6458: inline void dcbtst( Register s2); goetz@6458: inline void dcbtstct(Register s2, int ct); goetz@6458: goetz@6458: // Atomics: use ra0mem to disallow R0 as base. goetz@6458: inline void lwarx_unchecked(Register d, Register b, int eh1); goetz@6458: inline void ldarx_unchecked(Register d, Register b, int eh1); gromero@9662: inline void lqarx_unchecked(Register d, Register b, int eh1); goetz@6458: inline void lwarx( Register d, Register b, bool hint_exclusive_access); goetz@6458: inline void ldarx( Register d, Register b, bool hint_exclusive_access); gromero@9662: inline void lqarx( Register d, Register b, bool hint_exclusive_access); goetz@6458: inline void stwcx_(Register s, Register b); goetz@6458: inline void stdcx_(Register s, Register b); gromero@9662: inline void stqcx_(Register s, Register b); goetz@6458: inline void lfs( FloatRegister d, int si16); goetz@6458: inline void lfsx( FloatRegister d, Register b); goetz@6458: inline void lfd( FloatRegister d, int si16); goetz@6458: inline void lfdx( FloatRegister d, Register b); goetz@6458: inline void stfs( FloatRegister s, int si16); goetz@6458: inline void stfsx( FloatRegister s, Register b); goetz@6458: inline void stfd( FloatRegister s, int si16); goetz@6458: inline void stfdx( FloatRegister s, Register b); goetz@6458: inline void lvebx( VectorRegister d, Register s2); goetz@6458: inline void lvehx( VectorRegister d, Register s2); goetz@6458: inline void lvewx( VectorRegister d, Register s2); goetz@6458: inline void lvx( VectorRegister d, Register s2); goetz@6458: inline void lvxl( VectorRegister d, Register s2); goetz@6458: inline void stvebx(VectorRegister d, Register s2); goetz@6458: inline void stvehx(VectorRegister d, Register s2); goetz@6458: inline void stvewx(VectorRegister d, Register s2); goetz@6458: inline void stvx( VectorRegister d, Register s2); goetz@6458: inline void stvxl( VectorRegister d, Register s2); goetz@6458: inline void lvsl( VectorRegister d, Register s2); goetz@6458: inline void lvsr( VectorRegister d, Register s2); goetz@6458: ogatak@9713: // Endianess specific concatenation of 2 loaded vectors. ogatak@9713: inline void load_perm(VectorRegister perm, Register addr); ogatak@9713: inline void vec_perm(VectorRegister first_dest, VectorRegister second, VectorRegister perm); ogatak@9713: goetz@6458: // RegisterOrConstant versions. goetz@6458: // These emitters choose between the versions using two registers and goetz@6458: // those with register and immediate, depending on the content of roc. goetz@6458: // If the constant is not encodable as immediate, instructions to goetz@6458: // load the constant are emitted beforehand. Store instructions need a goetz@6458: // tmp reg if the constant is not encodable as immediate. goetz@6458: // Size unpredictable. goetz@6458: void ld( Register d, RegisterOrConstant roc, Register s1 = noreg); goetz@6458: void lwa( Register d, RegisterOrConstant roc, Register s1 = noreg); goetz@6458: void lwz( Register d, RegisterOrConstant roc, Register s1 = noreg); goetz@6458: void lha( Register d, RegisterOrConstant roc, Register s1 = noreg); goetz@6458: void lhz( Register d, RegisterOrConstant roc, Register s1 = noreg); goetz@6458: void lbz( Register d, RegisterOrConstant roc, Register s1 = noreg); goetz@6458: void std( Register d, RegisterOrConstant roc, Register s1 = noreg, Register tmp = noreg); goetz@6458: void stw( Register d, RegisterOrConstant roc, Register s1 = noreg, Register tmp = noreg); goetz@6458: void sth( Register d, RegisterOrConstant roc, Register s1 = noreg, Register tmp = noreg); goetz@6458: void stb( Register d, RegisterOrConstant roc, Register s1 = noreg, Register tmp = noreg); goetz@6458: void add( Register d, RegisterOrConstant roc, Register s1); goetz@6458: void subf(Register d, RegisterOrConstant roc, Register s1); goetz@6458: void cmpd(ConditionRegister d, RegisterOrConstant roc, Register s1); goetz@6458: goetz@6458: goetz@6458: // Emit several instructions to load a 64 bit constant. This issues a fixed goetz@6458: // instruction pattern so that the constant can be patched later on. goetz@6458: enum { goetz@6458: load_const_size = 5 * BytesPerInstWord goetz@6458: }; goetz@6458: void load_const(Register d, long a, Register tmp = noreg); goetz@6458: inline void load_const(Register d, void* a, Register tmp = noreg); goetz@6458: inline void load_const(Register d, Label& L, Register tmp = noreg); goetz@6458: inline void load_const(Register d, AddressLiteral& a, Register tmp = noreg); goetz@6458: goetz@6458: // Load a 64 bit constant, optimized, not identifyable. goetz@6495: // Tmp can be used to increase ILP. Set return_simm16_rest = true to get a goetz@6458: // 16 bit immediate offset. This is useful if the offset can be encoded in goetz@6458: // a succeeding instruction. goetz@6458: int load_const_optimized(Register d, long a, Register tmp = noreg, bool return_simm16_rest = false); goetz@6458: inline int load_const_optimized(Register d, void* a, Register tmp = noreg, bool return_simm16_rest = false) { goetz@6458: return load_const_optimized(d, (long)(unsigned long)a, tmp, return_simm16_rest); goetz@6458: } goetz@6458: goetz@6458: // Creation goetz@6458: Assembler(CodeBuffer* code) : AbstractAssembler(code) { goetz@6458: #ifdef CHECK_DELAY goetz@6458: delay_state = no_delay; goetz@6458: #endif goetz@6458: } goetz@6458: goetz@6458: // Testing goetz@6458: #ifndef PRODUCT goetz@6458: void test_asm(); goetz@6458: #endif goetz@6458: }; goetz@6458: goetz@6458: goetz@6458: #endif // CPU_PPC_VM_ASSEMBLER_PPC_HPP