Tue, 18 Jun 2019 09:33:34 -0400
8185979: PPC64: Implement SHA2 intrinsic
Reviewed-by: mdoerr, goetz
Contributed-by: Bruno Rosa <bruno.rosa@eldorado.org.br>, Gustavo Serra Scalet <gustavo.scalet@eldorado.org.br>, Igor Nunes <igor.nunes@eldorado.org.br>, Martin Doerr <martin.doerr@sap.com>
goetz@6458 | 1 | /* |
mdoerr@9603 | 2 | * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. |
mdoerr@9603 | 3 | * Copyright (c) 2012, 2018, SAP SE. All rights reserved. |
goetz@6458 | 4 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
goetz@6458 | 5 | * |
goetz@6458 | 6 | * This code is free software; you can redistribute it and/or modify it |
goetz@6458 | 7 | * under the terms of the GNU General Public License version 2 only, as |
goetz@6458 | 8 | * published by the Free Software Foundation. |
goetz@6458 | 9 | * |
goetz@6458 | 10 | * This code is distributed in the hope that it will be useful, but WITHOUT |
goetz@6458 | 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
goetz@6458 | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
goetz@6458 | 13 | * version 2 for more details (a copy is included in the LICENSE file that |
goetz@6458 | 14 | * accompanied this code). |
goetz@6458 | 15 | * |
goetz@6458 | 16 | * You should have received a copy of the GNU General Public License version |
goetz@6458 | 17 | * 2 along with this work; if not, write to the Free Software Foundation, |
goetz@6458 | 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
goetz@6458 | 19 | * |
goetz@6458 | 20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
goetz@6458 | 21 | * or visit www.oracle.com if you need additional information or have any |
goetz@6458 | 22 | * questions. |
goetz@6458 | 23 | * |
goetz@6458 | 24 | */ |
goetz@6458 | 25 | |
goetz@6458 | 26 | #ifndef CPU_PPC_VM_ASSEMBLER_PPC_HPP |
goetz@6458 | 27 | #define CPU_PPC_VM_ASSEMBLER_PPC_HPP |
goetz@6458 | 28 | |
goetz@6458 | 29 | #include "asm/register.hpp" |
goetz@6458 | 30 | |
goetz@6458 | 31 | // Address is an abstraction used to represent a memory location |
goetz@6458 | 32 | // as used in assembler instructions. |
goetz@6458 | 33 | // PPC instructions grok either baseReg + indexReg or baseReg + disp. |
goetz@6458 | 34 | // So far we do not use this as simplification by this class is low |
goetz@6458 | 35 | // on PPC with its simple addressing mode. Use RegisterOrConstant to |
goetz@6458 | 36 | // represent an offset. |
goetz@6458 | 37 | class Address VALUE_OBJ_CLASS_SPEC { |
goetz@6458 | 38 | }; |
goetz@6458 | 39 | |
goetz@6458 | 40 | class AddressLiteral VALUE_OBJ_CLASS_SPEC { |
goetz@6458 | 41 | private: |
goetz@6458 | 42 | address _address; |
goetz@6458 | 43 | RelocationHolder _rspec; |
goetz@6458 | 44 | |
goetz@6458 | 45 | RelocationHolder rspec_from_rtype(relocInfo::relocType rtype, address addr) { |
goetz@6458 | 46 | switch (rtype) { |
goetz@6458 | 47 | case relocInfo::external_word_type: |
goetz@6458 | 48 | return external_word_Relocation::spec(addr); |
goetz@6458 | 49 | case relocInfo::internal_word_type: |
goetz@6458 | 50 | return internal_word_Relocation::spec(addr); |
goetz@6458 | 51 | case relocInfo::opt_virtual_call_type: |
goetz@6458 | 52 | return opt_virtual_call_Relocation::spec(); |
goetz@6458 | 53 | case relocInfo::static_call_type: |
goetz@6458 | 54 | return static_call_Relocation::spec(); |
goetz@6458 | 55 | case relocInfo::runtime_call_type: |
goetz@6458 | 56 | return runtime_call_Relocation::spec(); |
goetz@6458 | 57 | case relocInfo::none: |
goetz@6458 | 58 | return RelocationHolder(); |
goetz@6458 | 59 | default: |
goetz@6458 | 60 | ShouldNotReachHere(); |
goetz@6458 | 61 | return RelocationHolder(); |
goetz@6458 | 62 | } |
goetz@6458 | 63 | } |
goetz@6458 | 64 | |
goetz@6458 | 65 | protected: |
goetz@6458 | 66 | // creation |
goetz@6458 | 67 | AddressLiteral() : _address(NULL), _rspec(NULL) {} |
goetz@6458 | 68 | |
goetz@6458 | 69 | public: |
goetz@6458 | 70 | AddressLiteral(address addr, RelocationHolder const& rspec) |
goetz@6458 | 71 | : _address(addr), |
goetz@6458 | 72 | _rspec(rspec) {} |
goetz@6458 | 73 | |
goetz@6458 | 74 | AddressLiteral(address addr, relocInfo::relocType rtype = relocInfo::none) |
goetz@6458 | 75 | : _address((address) addr), |
goetz@6458 | 76 | _rspec(rspec_from_rtype(rtype, (address) addr)) {} |
goetz@6458 | 77 | |
goetz@6458 | 78 | AddressLiteral(oop* addr, relocInfo::relocType rtype = relocInfo::none) |
goetz@6458 | 79 | : _address((address) addr), |
goetz@6458 | 80 | _rspec(rspec_from_rtype(rtype, (address) addr)) {} |
goetz@6458 | 81 | |
goetz@6458 | 82 | intptr_t value() const { return (intptr_t) _address; } |
goetz@6458 | 83 | |
goetz@6458 | 84 | const RelocationHolder& rspec() const { return _rspec; } |
goetz@6458 | 85 | }; |
goetz@6458 | 86 | |
goetz@6458 | 87 | // Argument is an abstraction used to represent an outgoing |
goetz@6458 | 88 | // actual argument or an incoming formal parameter, whether |
goetz@6458 | 89 | // it resides in memory or in a register, in a manner consistent |
goetz@6458 | 90 | // with the PPC Application Binary Interface, or ABI. This is |
goetz@6458 | 91 | // often referred to as the native or C calling convention. |
goetz@6458 | 92 | |
goetz@6458 | 93 | class Argument VALUE_OBJ_CLASS_SPEC { |
goetz@6458 | 94 | private: |
goetz@6458 | 95 | int _number; // The number of the argument. |
goetz@6458 | 96 | public: |
goetz@6458 | 97 | enum { |
goetz@6458 | 98 | // Only 8 registers may contain integer parameters. |
goetz@6458 | 99 | n_register_parameters = 8, |
goetz@6458 | 100 | // Can have up to 8 floating registers. |
goetz@6495 | 101 | n_float_register_parameters = 8, |
goetz@6495 | 102 | |
goetz@6495 | 103 | // PPC C calling conventions. |
goetz@6495 | 104 | // The first eight arguments are passed in int regs if they are int. |
goetz@6495 | 105 | n_int_register_parameters_c = 8, |
goetz@6495 | 106 | // The first thirteen float arguments are passed in float regs. |
goetz@6495 | 107 | n_float_register_parameters_c = 13, |
goetz@6495 | 108 | // Only the first 8 parameters are not placed on the stack. Aix disassembly |
goetz@6495 | 109 | // shows that xlC places all float args after argument 8 on the stack AND |
goetz@6495 | 110 | // in a register. This is not documented, but we follow this convention, too. |
goetz@6495 | 111 | n_regs_not_on_stack_c = 8, |
goetz@6458 | 112 | }; |
goetz@6458 | 113 | // creation |
goetz@6458 | 114 | Argument(int number) : _number(number) {} |
goetz@6458 | 115 | |
goetz@6458 | 116 | int number() const { return _number; } |
goetz@6458 | 117 | |
goetz@6458 | 118 | // Locating register-based arguments: |
goetz@6458 | 119 | bool is_register() const { return _number < n_register_parameters; } |
goetz@6458 | 120 | |
goetz@6458 | 121 | Register as_register() const { |
goetz@6458 | 122 | assert(is_register(), "must be a register argument"); |
goetz@6458 | 123 | return as_Register(number() + R3_ARG1->encoding()); |
goetz@6458 | 124 | } |
goetz@6458 | 125 | }; |
goetz@6458 | 126 | |
goetz@6511 | 127 | #if !defined(ABI_ELFv2) |
goetz@6458 | 128 | // A ppc64 function descriptor. |
goetz@6458 | 129 | struct FunctionDescriptor VALUE_OBJ_CLASS_SPEC { |
goetz@6458 | 130 | private: |
goetz@6458 | 131 | address _entry; |
goetz@6458 | 132 | address _toc; |
goetz@6458 | 133 | address _env; |
goetz@6458 | 134 | |
goetz@6458 | 135 | public: |
goetz@6458 | 136 | inline address entry() const { return _entry; } |
goetz@6458 | 137 | inline address toc() const { return _toc; } |
goetz@6458 | 138 | inline address env() const { return _env; } |
goetz@6458 | 139 | |
goetz@6458 | 140 | inline void set_entry(address entry) { _entry = entry; } |
goetz@6458 | 141 | inline void set_toc( address toc) { _toc = toc; } |
goetz@6458 | 142 | inline void set_env( address env) { _env = env; } |
goetz@6458 | 143 | |
goetz@6458 | 144 | inline static ByteSize entry_offset() { return byte_offset_of(FunctionDescriptor, _entry); } |
goetz@6458 | 145 | inline static ByteSize toc_offset() { return byte_offset_of(FunctionDescriptor, _toc); } |
goetz@6458 | 146 | inline static ByteSize env_offset() { return byte_offset_of(FunctionDescriptor, _env); } |
goetz@6458 | 147 | |
goetz@6458 | 148 | // Friend functions can be called without loading toc and env. |
goetz@6458 | 149 | enum { |
goetz@6458 | 150 | friend_toc = 0xcafe, |
goetz@6458 | 151 | friend_env = 0xc0de |
goetz@6458 | 152 | }; |
goetz@6458 | 153 | |
goetz@6458 | 154 | inline bool is_friend_function() const { |
goetz@6458 | 155 | return (toc() == (address) friend_toc) && (env() == (address) friend_env); |
goetz@6458 | 156 | } |
goetz@6458 | 157 | |
goetz@6458 | 158 | // Constructor for stack-allocated instances. |
goetz@6458 | 159 | FunctionDescriptor() { |
goetz@6458 | 160 | _entry = (address) 0xbad; |
goetz@6458 | 161 | _toc = (address) 0xbad; |
goetz@6458 | 162 | _env = (address) 0xbad; |
goetz@6458 | 163 | } |
goetz@6458 | 164 | }; |
goetz@6511 | 165 | #endif |
goetz@6458 | 166 | |
goetz@6458 | 167 | class Assembler : public AbstractAssembler { |
goetz@6458 | 168 | protected: |
goetz@6458 | 169 | // Displacement routines |
goetz@6458 | 170 | static void print_instruction(int inst); |
goetz@6458 | 171 | static int patched_branch(int dest_pos, int inst, int inst_pos); |
goetz@6458 | 172 | static int branch_destination(int inst, int pos); |
goetz@6458 | 173 | |
goetz@6458 | 174 | friend class AbstractAssembler; |
goetz@6458 | 175 | |
goetz@6458 | 176 | // Code patchers need various routines like inv_wdisp() |
goetz@6458 | 177 | friend class NativeInstruction; |
goetz@6458 | 178 | friend class NativeGeneralJump; |
goetz@6458 | 179 | friend class Relocation; |
goetz@6458 | 180 | |
goetz@6458 | 181 | public: |
goetz@6458 | 182 | |
goetz@6458 | 183 | enum shifts { |
goetz@6458 | 184 | XO_21_29_SHIFT = 2, |
goetz@6458 | 185 | XO_21_30_SHIFT = 1, |
goetz@6458 | 186 | XO_27_29_SHIFT = 2, |
goetz@6458 | 187 | XO_30_31_SHIFT = 0, |
goetz@6458 | 188 | SPR_5_9_SHIFT = 11u, // SPR_5_9 field in bits 11 -- 15 |
goetz@6458 | 189 | SPR_0_4_SHIFT = 16u, // SPR_0_4 field in bits 16 -- 20 |
goetz@6458 | 190 | RS_SHIFT = 21u, // RS field in bits 21 -- 25 |
goetz@6458 | 191 | OPCODE_SHIFT = 26u, // opcode in bits 26 -- 31 |
goetz@6458 | 192 | }; |
goetz@6458 | 193 | |
goetz@6458 | 194 | enum opcdxos_masks { |
goetz@6458 | 195 | XL_FORM_OPCODE_MASK = (63u << OPCODE_SHIFT) | (1023u << 1), |
goetz@6458 | 196 | ADDI_OPCODE_MASK = (63u << OPCODE_SHIFT), |
goetz@6458 | 197 | ADDIS_OPCODE_MASK = (63u << OPCODE_SHIFT), |
goetz@6458 | 198 | BXX_OPCODE_MASK = (63u << OPCODE_SHIFT), |
goetz@6458 | 199 | BCXX_OPCODE_MASK = (63u << OPCODE_SHIFT), |
goetz@6458 | 200 | // trap instructions |
goetz@6458 | 201 | TDI_OPCODE_MASK = (63u << OPCODE_SHIFT), |
goetz@6458 | 202 | TWI_OPCODE_MASK = (63u << OPCODE_SHIFT), |
goetz@6458 | 203 | TD_OPCODE_MASK = (63u << OPCODE_SHIFT) | (1023u << 1), |
goetz@6458 | 204 | TW_OPCODE_MASK = (63u << OPCODE_SHIFT) | (1023u << 1), |
goetz@6458 | 205 | LD_OPCODE_MASK = (63u << OPCODE_SHIFT) | (3u << XO_30_31_SHIFT), // DS-FORM |
goetz@6458 | 206 | STD_OPCODE_MASK = LD_OPCODE_MASK, |
goetz@6458 | 207 | STDU_OPCODE_MASK = STD_OPCODE_MASK, |
goetz@6458 | 208 | STDX_OPCODE_MASK = (63u << OPCODE_SHIFT) | (1023u << 1), |
goetz@6458 | 209 | STDUX_OPCODE_MASK = STDX_OPCODE_MASK, |
goetz@6458 | 210 | STW_OPCODE_MASK = (63u << OPCODE_SHIFT), |
goetz@6458 | 211 | STWU_OPCODE_MASK = STW_OPCODE_MASK, |
goetz@6458 | 212 | STWX_OPCODE_MASK = (63u << OPCODE_SHIFT) | (1023u << 1), |
goetz@6458 | 213 | STWUX_OPCODE_MASK = STWX_OPCODE_MASK, |
goetz@6458 | 214 | MTCTR_OPCODE_MASK = ~(31u << RS_SHIFT), |
goetz@6458 | 215 | ORI_OPCODE_MASK = (63u << OPCODE_SHIFT), |
goetz@6458 | 216 | ORIS_OPCODE_MASK = (63u << OPCODE_SHIFT), |
goetz@6458 | 217 | RLDICR_OPCODE_MASK = (63u << OPCODE_SHIFT) | (7u << XO_27_29_SHIFT) |
goetz@6458 | 218 | }; |
goetz@6458 | 219 | |
goetz@6458 | 220 | enum opcdxos { |
goetz@6458 | 221 | ADD_OPCODE = (31u << OPCODE_SHIFT | 266u << 1), |
goetz@6458 | 222 | ADDC_OPCODE = (31u << OPCODE_SHIFT | 10u << 1), |
goetz@6458 | 223 | ADDI_OPCODE = (14u << OPCODE_SHIFT), |
goetz@6458 | 224 | ADDIS_OPCODE = (15u << OPCODE_SHIFT), |
goetz@6458 | 225 | ADDIC__OPCODE = (13u << OPCODE_SHIFT), |
goetz@6458 | 226 | ADDE_OPCODE = (31u << OPCODE_SHIFT | 138u << 1), |
goetz@6458 | 227 | SUBF_OPCODE = (31u << OPCODE_SHIFT | 40u << 1), |
goetz@6458 | 228 | SUBFC_OPCODE = (31u << OPCODE_SHIFT | 8u << 1), |
goetz@6458 | 229 | SUBFE_OPCODE = (31u << OPCODE_SHIFT | 136u << 1), |
goetz@6458 | 230 | SUBFIC_OPCODE = (8u << OPCODE_SHIFT), |
goetz@6458 | 231 | SUBFZE_OPCODE = (31u << OPCODE_SHIFT | 200u << 1), |
goetz@6458 | 232 | DIVW_OPCODE = (31u << OPCODE_SHIFT | 491u << 1), |
goetz@6458 | 233 | MULLW_OPCODE = (31u << OPCODE_SHIFT | 235u << 1), |
goetz@6458 | 234 | MULHW_OPCODE = (31u << OPCODE_SHIFT | 75u << 1), |
goetz@6458 | 235 | MULHWU_OPCODE = (31u << OPCODE_SHIFT | 11u << 1), |
goetz@6458 | 236 | MULLI_OPCODE = (7u << OPCODE_SHIFT), |
goetz@6458 | 237 | AND_OPCODE = (31u << OPCODE_SHIFT | 28u << 1), |
goetz@6458 | 238 | ANDI_OPCODE = (28u << OPCODE_SHIFT), |
goetz@6458 | 239 | ANDIS_OPCODE = (29u << OPCODE_SHIFT), |
goetz@6458 | 240 | ANDC_OPCODE = (31u << OPCODE_SHIFT | 60u << 1), |
goetz@6458 | 241 | ORC_OPCODE = (31u << OPCODE_SHIFT | 412u << 1), |
goetz@6458 | 242 | OR_OPCODE = (31u << OPCODE_SHIFT | 444u << 1), |
goetz@6458 | 243 | ORI_OPCODE = (24u << OPCODE_SHIFT), |
goetz@6458 | 244 | ORIS_OPCODE = (25u << OPCODE_SHIFT), |
goetz@6458 | 245 | XOR_OPCODE = (31u << OPCODE_SHIFT | 316u << 1), |
goetz@6458 | 246 | XORI_OPCODE = (26u << OPCODE_SHIFT), |
goetz@6458 | 247 | XORIS_OPCODE = (27u << OPCODE_SHIFT), |
goetz@6458 | 248 | |
goetz@6458 | 249 | NEG_OPCODE = (31u << OPCODE_SHIFT | 104u << 1), |
goetz@6458 | 250 | |
goetz@6458 | 251 | RLWINM_OPCODE = (21u << OPCODE_SHIFT), |
goetz@6458 | 252 | CLRRWI_OPCODE = RLWINM_OPCODE, |
goetz@6458 | 253 | CLRLWI_OPCODE = RLWINM_OPCODE, |
goetz@6458 | 254 | |
goetz@6458 | 255 | RLWIMI_OPCODE = (20u << OPCODE_SHIFT), |
goetz@6458 | 256 | |
goetz@6458 | 257 | SLW_OPCODE = (31u << OPCODE_SHIFT | 24u << 1), |
goetz@6458 | 258 | SLWI_OPCODE = RLWINM_OPCODE, |
goetz@6458 | 259 | SRW_OPCODE = (31u << OPCODE_SHIFT | 536u << 1), |
goetz@6458 | 260 | SRWI_OPCODE = RLWINM_OPCODE, |
goetz@6458 | 261 | SRAW_OPCODE = (31u << OPCODE_SHIFT | 792u << 1), |
goetz@6458 | 262 | SRAWI_OPCODE = (31u << OPCODE_SHIFT | 824u << 1), |
goetz@6458 | 263 | |
goetz@6458 | 264 | CMP_OPCODE = (31u << OPCODE_SHIFT | 0u << 1), |
goetz@6458 | 265 | CMPI_OPCODE = (11u << OPCODE_SHIFT), |
goetz@6458 | 266 | CMPL_OPCODE = (31u << OPCODE_SHIFT | 32u << 1), |
goetz@6458 | 267 | CMPLI_OPCODE = (10u << OPCODE_SHIFT), |
goetz@6458 | 268 | |
goetz@6458 | 269 | ISEL_OPCODE = (31u << OPCODE_SHIFT | 15u << 1), |
goetz@6458 | 270 | |
goetz@7222 | 271 | // Special purpose registers |
goetz@7222 | 272 | MTSPR_OPCODE = (31u << OPCODE_SHIFT | 467u << 1), |
goetz@7222 | 273 | MFSPR_OPCODE = (31u << OPCODE_SHIFT | 339u << 1), |
goetz@7222 | 274 | |
goetz@7222 | 275 | MTXER_OPCODE = (MTSPR_OPCODE | 1 << SPR_0_4_SHIFT), |
goetz@7222 | 276 | MFXER_OPCODE = (MFSPR_OPCODE | 1 << SPR_0_4_SHIFT), |
goetz@7222 | 277 | |
goetz@7222 | 278 | MTDSCR_OPCODE = (MTSPR_OPCODE | 3 << SPR_0_4_SHIFT), |
goetz@7222 | 279 | MFDSCR_OPCODE = (MFSPR_OPCODE | 3 << SPR_0_4_SHIFT), |
goetz@7222 | 280 | |
goetz@7222 | 281 | MTLR_OPCODE = (MTSPR_OPCODE | 8 << SPR_0_4_SHIFT), |
goetz@7222 | 282 | MFLR_OPCODE = (MFSPR_OPCODE | 8 << SPR_0_4_SHIFT), |
goetz@7222 | 283 | |
goetz@7222 | 284 | MTCTR_OPCODE = (MTSPR_OPCODE | 9 << SPR_0_4_SHIFT), |
goetz@7222 | 285 | MFCTR_OPCODE = (MFSPR_OPCODE | 9 << SPR_0_4_SHIFT), |
goetz@7222 | 286 | |
goetz@7222 | 287 | MTTFHAR_OPCODE = (MTSPR_OPCODE | 128 << SPR_0_4_SHIFT), |
goetz@7222 | 288 | MFTFHAR_OPCODE = (MFSPR_OPCODE | 128 << SPR_0_4_SHIFT), |
goetz@7222 | 289 | MTTFIAR_OPCODE = (MTSPR_OPCODE | 129 << SPR_0_4_SHIFT), |
goetz@7222 | 290 | MFTFIAR_OPCODE = (MFSPR_OPCODE | 129 << SPR_0_4_SHIFT), |
goetz@7222 | 291 | MTTEXASR_OPCODE = (MTSPR_OPCODE | 130 << SPR_0_4_SHIFT), |
goetz@7222 | 292 | MFTEXASR_OPCODE = (MFSPR_OPCODE | 130 << SPR_0_4_SHIFT), |
goetz@7222 | 293 | MTTEXASRU_OPCODE = (MTSPR_OPCODE | 131 << SPR_0_4_SHIFT), |
goetz@7222 | 294 | MFTEXASRU_OPCODE = (MFSPR_OPCODE | 131 << SPR_0_4_SHIFT), |
goetz@7222 | 295 | |
goetz@7222 | 296 | MTVRSAVE_OPCODE = (MTSPR_OPCODE | 256 << SPR_0_4_SHIFT), |
goetz@7222 | 297 | MFVRSAVE_OPCODE = (MFSPR_OPCODE | 256 << SPR_0_4_SHIFT), |
goetz@7222 | 298 | |
goetz@7222 | 299 | MFTB_OPCODE = (MFSPR_OPCODE | 268 << SPR_0_4_SHIFT), |
goetz@6458 | 300 | |
goetz@6458 | 301 | MTCRF_OPCODE = (31u << OPCODE_SHIFT | 144u << 1), |
goetz@6458 | 302 | MFCR_OPCODE = (31u << OPCODE_SHIFT | 19u << 1), |
goetz@6458 | 303 | MCRF_OPCODE = (19u << OPCODE_SHIFT | 0u << 1), |
goetz@6458 | 304 | |
goetz@6458 | 305 | // condition register logic instructions |
goetz@6458 | 306 | CRAND_OPCODE = (19u << OPCODE_SHIFT | 257u << 1), |
goetz@6458 | 307 | CRNAND_OPCODE = (19u << OPCODE_SHIFT | 225u << 1), |
goetz@6458 | 308 | CROR_OPCODE = (19u << OPCODE_SHIFT | 449u << 1), |
goetz@6458 | 309 | CRXOR_OPCODE = (19u << OPCODE_SHIFT | 193u << 1), |
goetz@6458 | 310 | CRNOR_OPCODE = (19u << OPCODE_SHIFT | 33u << 1), |
goetz@6458 | 311 | CREQV_OPCODE = (19u << OPCODE_SHIFT | 289u << 1), |
goetz@6458 | 312 | CRANDC_OPCODE = (19u << OPCODE_SHIFT | 129u << 1), |
goetz@6458 | 313 | CRORC_OPCODE = (19u << OPCODE_SHIFT | 417u << 1), |
goetz@6458 | 314 | |
goetz@6458 | 315 | BCLR_OPCODE = (19u << OPCODE_SHIFT | 16u << 1), |
goetz@6458 | 316 | BXX_OPCODE = (18u << OPCODE_SHIFT), |
goetz@6458 | 317 | BCXX_OPCODE = (16u << OPCODE_SHIFT), |
goetz@6458 | 318 | |
goetz@6458 | 319 | // CTR-related opcodes |
goetz@6458 | 320 | BCCTR_OPCODE = (19u << OPCODE_SHIFT | 528u << 1), |
goetz@6458 | 321 | |
goetz@6458 | 322 | LWZ_OPCODE = (32u << OPCODE_SHIFT), |
goetz@6458 | 323 | LWZX_OPCODE = (31u << OPCODE_SHIFT | 23u << 1), |
goetz@6458 | 324 | LWZU_OPCODE = (33u << OPCODE_SHIFT), |
kvn@7132 | 325 | LWBRX_OPCODE = (31u << OPCODE_SHIFT | 534 << 1), |
goetz@6458 | 326 | |
goetz@6458 | 327 | LHA_OPCODE = (42u << OPCODE_SHIFT), |
goetz@6458 | 328 | LHAX_OPCODE = (31u << OPCODE_SHIFT | 343u << 1), |
goetz@6458 | 329 | LHAU_OPCODE = (43u << OPCODE_SHIFT), |
goetz@6458 | 330 | |
goetz@6458 | 331 | LHZ_OPCODE = (40u << OPCODE_SHIFT), |
goetz@6458 | 332 | LHZX_OPCODE = (31u << OPCODE_SHIFT | 279u << 1), |
goetz@6458 | 333 | LHZU_OPCODE = (41u << OPCODE_SHIFT), |
kvn@7132 | 334 | LHBRX_OPCODE = (31u << OPCODE_SHIFT | 790 << 1), |
goetz@6458 | 335 | |
goetz@6458 | 336 | LBZ_OPCODE = (34u << OPCODE_SHIFT), |
goetz@6458 | 337 | LBZX_OPCODE = (31u << OPCODE_SHIFT | 87u << 1), |
goetz@6458 | 338 | LBZU_OPCODE = (35u << OPCODE_SHIFT), |
goetz@6458 | 339 | |
goetz@6458 | 340 | STW_OPCODE = (36u << OPCODE_SHIFT), |
goetz@6458 | 341 | STWX_OPCODE = (31u << OPCODE_SHIFT | 151u << 1), |
goetz@6458 | 342 | STWU_OPCODE = (37u << OPCODE_SHIFT), |
goetz@6458 | 343 | STWUX_OPCODE = (31u << OPCODE_SHIFT | 183u << 1), |
goetz@6458 | 344 | |
goetz@6458 | 345 | STH_OPCODE = (44u << OPCODE_SHIFT), |
goetz@6458 | 346 | STHX_OPCODE = (31u << OPCODE_SHIFT | 407u << 1), |
goetz@6458 | 347 | STHU_OPCODE = (45u << OPCODE_SHIFT), |
goetz@6458 | 348 | |
goetz@6458 | 349 | STB_OPCODE = (38u << OPCODE_SHIFT), |
goetz@6458 | 350 | STBX_OPCODE = (31u << OPCODE_SHIFT | 215u << 1), |
goetz@6458 | 351 | STBU_OPCODE = (39u << OPCODE_SHIFT), |
goetz@6458 | 352 | |
goetz@6458 | 353 | EXTSB_OPCODE = (31u << OPCODE_SHIFT | 954u << 1), |
goetz@6458 | 354 | EXTSH_OPCODE = (31u << OPCODE_SHIFT | 922u << 1), |
goetz@6458 | 355 | EXTSW_OPCODE = (31u << OPCODE_SHIFT | 986u << 1), // X-FORM |
goetz@6458 | 356 | |
goetz@6458 | 357 | // 32 bit opcode encodings |
goetz@6458 | 358 | |
goetz@6458 | 359 | LWA_OPCODE = (58u << OPCODE_SHIFT | 2u << XO_30_31_SHIFT), // DS-FORM |
goetz@6458 | 360 | LWAX_OPCODE = (31u << OPCODE_SHIFT | 341u << XO_21_30_SHIFT), // X-FORM |
goetz@6458 | 361 | |
goetz@6458 | 362 | CNTLZW_OPCODE = (31u << OPCODE_SHIFT | 26u << XO_21_30_SHIFT), // X-FORM |
goetz@6458 | 363 | |
goetz@6458 | 364 | // 64 bit opcode encodings |
goetz@6458 | 365 | |
goetz@6458 | 366 | LD_OPCODE = (58u << OPCODE_SHIFT | 0u << XO_30_31_SHIFT), // DS-FORM |
goetz@6458 | 367 | LDU_OPCODE = (58u << OPCODE_SHIFT | 1u << XO_30_31_SHIFT), // DS-FORM |
goetz@6458 | 368 | LDX_OPCODE = (31u << OPCODE_SHIFT | 21u << XO_21_30_SHIFT), // X-FORM |
goetz@6458 | 369 | |
goetz@6458 | 370 | STD_OPCODE = (62u << OPCODE_SHIFT | 0u << XO_30_31_SHIFT), // DS-FORM |
goetz@6458 | 371 | STDU_OPCODE = (62u << OPCODE_SHIFT | 1u << XO_30_31_SHIFT), // DS-FORM |
goetz@6458 | 372 | STDUX_OPCODE = (31u << OPCODE_SHIFT | 181u << 1), // X-FORM |
goetz@6458 | 373 | STDX_OPCODE = (31u << OPCODE_SHIFT | 149u << XO_21_30_SHIFT), // X-FORM |
goetz@6458 | 374 | |
goetz@6458 | 375 | RLDICR_OPCODE = (30u << OPCODE_SHIFT | 1u << XO_27_29_SHIFT), // MD-FORM |
goetz@6458 | 376 | RLDICL_OPCODE = (30u << OPCODE_SHIFT | 0u << XO_27_29_SHIFT), // MD-FORM |
goetz@6458 | 377 | RLDIC_OPCODE = (30u << OPCODE_SHIFT | 2u << XO_27_29_SHIFT), // MD-FORM |
goetz@6458 | 378 | RLDIMI_OPCODE = (30u << OPCODE_SHIFT | 3u << XO_27_29_SHIFT), // MD-FORM |
goetz@6458 | 379 | |
goetz@6458 | 380 | SRADI_OPCODE = (31u << OPCODE_SHIFT | 413u << XO_21_29_SHIFT), // XS-FORM |
goetz@6458 | 381 | |
goetz@6458 | 382 | SLD_OPCODE = (31u << OPCODE_SHIFT | 27u << 1), // X-FORM |
goetz@6458 | 383 | SRD_OPCODE = (31u << OPCODE_SHIFT | 539u << 1), // X-FORM |
goetz@6458 | 384 | SRAD_OPCODE = (31u << OPCODE_SHIFT | 794u << 1), // X-FORM |
goetz@6458 | 385 | |
goetz@6458 | 386 | MULLD_OPCODE = (31u << OPCODE_SHIFT | 233u << 1), // XO-FORM |
goetz@6458 | 387 | MULHD_OPCODE = (31u << OPCODE_SHIFT | 73u << 1), // XO-FORM |
goetz@6458 | 388 | MULHDU_OPCODE = (31u << OPCODE_SHIFT | 9u << 1), // XO-FORM |
goetz@6458 | 389 | DIVD_OPCODE = (31u << OPCODE_SHIFT | 489u << 1), // XO-FORM |
goetz@6458 | 390 | |
goetz@6458 | 391 | CNTLZD_OPCODE = (31u << OPCODE_SHIFT | 58u << XO_21_30_SHIFT), // X-FORM |
goetz@6458 | 392 | NAND_OPCODE = (31u << OPCODE_SHIFT | 476u << XO_21_30_SHIFT), // X-FORM |
goetz@6458 | 393 | NOR_OPCODE = (31u << OPCODE_SHIFT | 124u << XO_21_30_SHIFT), // X-FORM |
goetz@6458 | 394 | |
goetz@6458 | 395 | |
goetz@6458 | 396 | // opcodes only used for floating arithmetic |
goetz@6458 | 397 | FADD_OPCODE = (63u << OPCODE_SHIFT | 21u << 1), |
goetz@6458 | 398 | FADDS_OPCODE = (59u << OPCODE_SHIFT | 21u << 1), |
goetz@6458 | 399 | FCMPU_OPCODE = (63u << OPCODE_SHIFT | 00u << 1), |
goetz@6458 | 400 | FDIV_OPCODE = (63u << OPCODE_SHIFT | 18u << 1), |
goetz@6458 | 401 | FDIVS_OPCODE = (59u << OPCODE_SHIFT | 18u << 1), |
goetz@6458 | 402 | FMR_OPCODE = (63u << OPCODE_SHIFT | 72u << 1), |
goetz@6458 | 403 | // These are special Power6 opcodes, reused for "lfdepx" and "stfdepx" |
goetz@6458 | 404 | // on Power7. Do not use. |
goetz@6458 | 405 | // MFFGPR_OPCODE = (31u << OPCODE_SHIFT | 607u << 1), |
goetz@6458 | 406 | // MFTGPR_OPCODE = (31u << OPCODE_SHIFT | 735u << 1), |
goetz@6458 | 407 | CMPB_OPCODE = (31u << OPCODE_SHIFT | 508 << 1), |
goetz@6458 | 408 | POPCNTB_OPCODE = (31u << OPCODE_SHIFT | 122 << 1), |
goetz@6458 | 409 | POPCNTW_OPCODE = (31u << OPCODE_SHIFT | 378 << 1), |
goetz@6458 | 410 | POPCNTD_OPCODE = (31u << OPCODE_SHIFT | 506 << 1), |
goetz@6458 | 411 | FABS_OPCODE = (63u << OPCODE_SHIFT | 264u << 1), |
goetz@6458 | 412 | FNABS_OPCODE = (63u << OPCODE_SHIFT | 136u << 1), |
goetz@6458 | 413 | FMUL_OPCODE = (63u << OPCODE_SHIFT | 25u << 1), |
goetz@6458 | 414 | FMULS_OPCODE = (59u << OPCODE_SHIFT | 25u << 1), |
goetz@6458 | 415 | FNEG_OPCODE = (63u << OPCODE_SHIFT | 40u << 1), |
goetz@6458 | 416 | FSUB_OPCODE = (63u << OPCODE_SHIFT | 20u << 1), |
goetz@6458 | 417 | FSUBS_OPCODE = (59u << OPCODE_SHIFT | 20u << 1), |
goetz@6458 | 418 | |
goetz@6458 | 419 | // PPC64-internal FPU conversion opcodes |
goetz@6458 | 420 | FCFID_OPCODE = (63u << OPCODE_SHIFT | 846u << 1), |
goetz@6458 | 421 | FCFIDS_OPCODE = (59u << OPCODE_SHIFT | 846u << 1), |
goetz@6458 | 422 | FCTID_OPCODE = (63u << OPCODE_SHIFT | 814u << 1), |
goetz@6458 | 423 | FCTIDZ_OPCODE = (63u << OPCODE_SHIFT | 815u << 1), |
goetz@6458 | 424 | FCTIW_OPCODE = (63u << OPCODE_SHIFT | 14u << 1), |
goetz@6458 | 425 | FCTIWZ_OPCODE = (63u << OPCODE_SHIFT | 15u << 1), |
goetz@6458 | 426 | FRSP_OPCODE = (63u << OPCODE_SHIFT | 12u << 1), |
goetz@6458 | 427 | |
goetz@6458 | 428 | // WARNING: using fmadd results in a non-compliant vm. Some floating |
goetz@6458 | 429 | // point tck tests will fail. |
goetz@6458 | 430 | FMADD_OPCODE = (59u << OPCODE_SHIFT | 29u << 1), |
goetz@6458 | 431 | DMADD_OPCODE = (63u << OPCODE_SHIFT | 29u << 1), |
goetz@6458 | 432 | FMSUB_OPCODE = (59u << OPCODE_SHIFT | 28u << 1), |
goetz@6458 | 433 | DMSUB_OPCODE = (63u << OPCODE_SHIFT | 28u << 1), |
goetz@6458 | 434 | FNMADD_OPCODE = (59u << OPCODE_SHIFT | 31u << 1), |
goetz@6458 | 435 | DNMADD_OPCODE = (63u << OPCODE_SHIFT | 31u << 1), |
goetz@6458 | 436 | FNMSUB_OPCODE = (59u << OPCODE_SHIFT | 30u << 1), |
goetz@6458 | 437 | DNMSUB_OPCODE = (63u << OPCODE_SHIFT | 30u << 1), |
goetz@6458 | 438 | |
goetz@6458 | 439 | LFD_OPCODE = (50u << OPCODE_SHIFT | 00u << 1), |
goetz@6458 | 440 | LFDU_OPCODE = (51u << OPCODE_SHIFT | 00u << 1), |
goetz@6458 | 441 | LFDX_OPCODE = (31u << OPCODE_SHIFT | 599u << 1), |
goetz@6458 | 442 | LFS_OPCODE = (48u << OPCODE_SHIFT | 00u << 1), |
goetz@6458 | 443 | LFSU_OPCODE = (49u << OPCODE_SHIFT | 00u << 1), |
goetz@6458 | 444 | LFSX_OPCODE = (31u << OPCODE_SHIFT | 535u << 1), |
goetz@6458 | 445 | |
goetz@6458 | 446 | STFD_OPCODE = (54u << OPCODE_SHIFT | 00u << 1), |
goetz@6458 | 447 | STFDU_OPCODE = (55u << OPCODE_SHIFT | 00u << 1), |
goetz@6458 | 448 | STFDX_OPCODE = (31u << OPCODE_SHIFT | 727u << 1), |
goetz@6458 | 449 | STFS_OPCODE = (52u << OPCODE_SHIFT | 00u << 1), |
goetz@6458 | 450 | STFSU_OPCODE = (53u << OPCODE_SHIFT | 00u << 1), |
goetz@6458 | 451 | STFSX_OPCODE = (31u << OPCODE_SHIFT | 663u << 1), |
goetz@6458 | 452 | |
goetz@6458 | 453 | FSQRT_OPCODE = (63u << OPCODE_SHIFT | 22u << 1), // A-FORM |
goetz@6458 | 454 | FSQRTS_OPCODE = (59u << OPCODE_SHIFT | 22u << 1), // A-FORM |
goetz@6458 | 455 | |
goetz@6458 | 456 | // Vector instruction support for >= Power6 |
goetz@6458 | 457 | // Vector Storage Access |
goetz@6458 | 458 | LVEBX_OPCODE = (31u << OPCODE_SHIFT | 7u << 1), |
goetz@6458 | 459 | LVEHX_OPCODE = (31u << OPCODE_SHIFT | 39u << 1), |
goetz@6458 | 460 | LVEWX_OPCODE = (31u << OPCODE_SHIFT | 71u << 1), |
goetz@6458 | 461 | LVX_OPCODE = (31u << OPCODE_SHIFT | 103u << 1), |
goetz@6458 | 462 | LVXL_OPCODE = (31u << OPCODE_SHIFT | 359u << 1), |
goetz@6458 | 463 | STVEBX_OPCODE = (31u << OPCODE_SHIFT | 135u << 1), |
goetz@6458 | 464 | STVEHX_OPCODE = (31u << OPCODE_SHIFT | 167u << 1), |
goetz@6458 | 465 | STVEWX_OPCODE = (31u << OPCODE_SHIFT | 199u << 1), |
goetz@6458 | 466 | STVX_OPCODE = (31u << OPCODE_SHIFT | 231u << 1), |
goetz@6458 | 467 | STVXL_OPCODE = (31u << OPCODE_SHIFT | 487u << 1), |
goetz@6458 | 468 | LVSL_OPCODE = (31u << OPCODE_SHIFT | 6u << 1), |
goetz@6458 | 469 | LVSR_OPCODE = (31u << OPCODE_SHIFT | 38u << 1), |
goetz@6458 | 470 | |
mdoerr@9497 | 471 | // Vector-Scalar (VSX) instruction support. |
gromero@9662 | 472 | LXVD2X_OPCODE = (31u << OPCODE_SHIFT | 844u << 1), |
gromero@9662 | 473 | STXVD2X_OPCODE = (31u << OPCODE_SHIFT | 972u << 1), |
mdoerr@9497 | 474 | MTVSRD_OPCODE = (31u << OPCODE_SHIFT | 179u << 1), |
gromero@9687 | 475 | MTVSRWZ_OPCODE = (31u << OPCODE_SHIFT | 243u << 1), |
mdoerr@9497 | 476 | MFVSRD_OPCODE = (31u << OPCODE_SHIFT | 51u << 1), |
gromero@9687 | 477 | MFVSRWZ_OPCODE = (31u << OPCODE_SHIFT | 115u << 1), |
gromero@9687 | 478 | XXPERMDI_OPCODE= (60u << OPCODE_SHIFT | 10u << 3), |
gromero@9687 | 479 | XXMRGHW_OPCODE = (60u << OPCODE_SHIFT | 18u << 3), |
gromero@9687 | 480 | XXMRGLW_OPCODE = (60u << OPCODE_SHIFT | 50u << 3), |
mdoerr@9497 | 481 | |
goetz@6458 | 482 | // Vector Permute and Formatting |
goetz@6458 | 483 | VPKPX_OPCODE = (4u << OPCODE_SHIFT | 782u ), |
goetz@6458 | 484 | VPKSHSS_OPCODE = (4u << OPCODE_SHIFT | 398u ), |
goetz@6458 | 485 | VPKSWSS_OPCODE = (4u << OPCODE_SHIFT | 462u ), |
goetz@6458 | 486 | VPKSHUS_OPCODE = (4u << OPCODE_SHIFT | 270u ), |
goetz@6458 | 487 | VPKSWUS_OPCODE = (4u << OPCODE_SHIFT | 334u ), |
goetz@6458 | 488 | VPKUHUM_OPCODE = (4u << OPCODE_SHIFT | 14u ), |
goetz@6458 | 489 | VPKUWUM_OPCODE = (4u << OPCODE_SHIFT | 78u ), |
goetz@6458 | 490 | VPKUHUS_OPCODE = (4u << OPCODE_SHIFT | 142u ), |
goetz@6458 | 491 | VPKUWUS_OPCODE = (4u << OPCODE_SHIFT | 206u ), |
goetz@6458 | 492 | VUPKHPX_OPCODE = (4u << OPCODE_SHIFT | 846u ), |
goetz@6458 | 493 | VUPKHSB_OPCODE = (4u << OPCODE_SHIFT | 526u ), |
goetz@6458 | 494 | VUPKHSH_OPCODE = (4u << OPCODE_SHIFT | 590u ), |
goetz@6458 | 495 | VUPKLPX_OPCODE = (4u << OPCODE_SHIFT | 974u ), |
goetz@6458 | 496 | VUPKLSB_OPCODE = (4u << OPCODE_SHIFT | 654u ), |
goetz@6458 | 497 | VUPKLSH_OPCODE = (4u << OPCODE_SHIFT | 718u ), |
goetz@6458 | 498 | |
goetz@6458 | 499 | VMRGHB_OPCODE = (4u << OPCODE_SHIFT | 12u ), |
goetz@6458 | 500 | VMRGHW_OPCODE = (4u << OPCODE_SHIFT | 140u ), |
goetz@6458 | 501 | VMRGHH_OPCODE = (4u << OPCODE_SHIFT | 76u ), |
goetz@6458 | 502 | VMRGLB_OPCODE = (4u << OPCODE_SHIFT | 268u ), |
goetz@6458 | 503 | VMRGLW_OPCODE = (4u << OPCODE_SHIFT | 396u ), |
goetz@6458 | 504 | VMRGLH_OPCODE = (4u << OPCODE_SHIFT | 332u ), |
goetz@6458 | 505 | |
goetz@6458 | 506 | VSPLT_OPCODE = (4u << OPCODE_SHIFT | 524u ), |
goetz@6458 | 507 | VSPLTH_OPCODE = (4u << OPCODE_SHIFT | 588u ), |
goetz@6458 | 508 | VSPLTW_OPCODE = (4u << OPCODE_SHIFT | 652u ), |
goetz@6458 | 509 | VSPLTISB_OPCODE= (4u << OPCODE_SHIFT | 780u ), |
goetz@6458 | 510 | VSPLTISH_OPCODE= (4u << OPCODE_SHIFT | 844u ), |
goetz@6458 | 511 | VSPLTISW_OPCODE= (4u << OPCODE_SHIFT | 908u ), |
goetz@6458 | 512 | |
goetz@6458 | 513 | VPERM_OPCODE = (4u << OPCODE_SHIFT | 43u ), |
goetz@6458 | 514 | VSEL_OPCODE = (4u << OPCODE_SHIFT | 42u ), |
goetz@6458 | 515 | |
goetz@6458 | 516 | VSL_OPCODE = (4u << OPCODE_SHIFT | 452u ), |
goetz@6458 | 517 | VSLDOI_OPCODE = (4u << OPCODE_SHIFT | 44u ), |
goetz@6458 | 518 | VSLO_OPCODE = (4u << OPCODE_SHIFT | 1036u ), |
goetz@6458 | 519 | VSR_OPCODE = (4u << OPCODE_SHIFT | 708u ), |
goetz@6458 | 520 | VSRO_OPCODE = (4u << OPCODE_SHIFT | 1100u ), |
goetz@6458 | 521 | |
goetz@6458 | 522 | // Vector Integer |
goetz@6458 | 523 | VADDCUW_OPCODE = (4u << OPCODE_SHIFT | 384u ), |
goetz@6458 | 524 | VADDSHS_OPCODE = (4u << OPCODE_SHIFT | 832u ), |
goetz@6458 | 525 | VADDSBS_OPCODE = (4u << OPCODE_SHIFT | 768u ), |
goetz@6458 | 526 | VADDSWS_OPCODE = (4u << OPCODE_SHIFT | 896u ), |
goetz@6458 | 527 | VADDUBM_OPCODE = (4u << OPCODE_SHIFT | 0u ), |
goetz@6458 | 528 | VADDUWM_OPCODE = (4u << OPCODE_SHIFT | 128u ), |
goetz@6458 | 529 | VADDUHM_OPCODE = (4u << OPCODE_SHIFT | 64u ), |
gromero@9687 | 530 | VADDUDM_OPCODE = (4u << OPCODE_SHIFT | 192u ), |
goetz@6458 | 531 | VADDUBS_OPCODE = (4u << OPCODE_SHIFT | 512u ), |
goetz@6458 | 532 | VADDUWS_OPCODE = (4u << OPCODE_SHIFT | 640u ), |
goetz@6458 | 533 | VADDUHS_OPCODE = (4u << OPCODE_SHIFT | 576u ), |
goetz@6458 | 534 | VSUBCUW_OPCODE = (4u << OPCODE_SHIFT | 1408u ), |
goetz@6458 | 535 | VSUBSHS_OPCODE = (4u << OPCODE_SHIFT | 1856u ), |
goetz@6458 | 536 | VSUBSBS_OPCODE = (4u << OPCODE_SHIFT | 1792u ), |
goetz@6458 | 537 | VSUBSWS_OPCODE = (4u << OPCODE_SHIFT | 1920u ), |
goetz@6458 | 538 | VSUBUBM_OPCODE = (4u << OPCODE_SHIFT | 1024u ), |
goetz@6458 | 539 | VSUBUWM_OPCODE = (4u << OPCODE_SHIFT | 1152u ), |
goetz@6458 | 540 | VSUBUHM_OPCODE = (4u << OPCODE_SHIFT | 1088u ), |
goetz@6458 | 541 | VSUBUBS_OPCODE = (4u << OPCODE_SHIFT | 1536u ), |
goetz@6458 | 542 | VSUBUWS_OPCODE = (4u << OPCODE_SHIFT | 1664u ), |
goetz@6458 | 543 | VSUBUHS_OPCODE = (4u << OPCODE_SHIFT | 1600u ), |
goetz@6458 | 544 | |
goetz@6458 | 545 | VMULESB_OPCODE = (4u << OPCODE_SHIFT | 776u ), |
goetz@6458 | 546 | VMULEUB_OPCODE = (4u << OPCODE_SHIFT | 520u ), |
goetz@6458 | 547 | VMULESH_OPCODE = (4u << OPCODE_SHIFT | 840u ), |
goetz@6458 | 548 | VMULEUH_OPCODE = (4u << OPCODE_SHIFT | 584u ), |
goetz@6458 | 549 | VMULOSB_OPCODE = (4u << OPCODE_SHIFT | 264u ), |
goetz@6458 | 550 | VMULOUB_OPCODE = (4u << OPCODE_SHIFT | 8u ), |
goetz@6458 | 551 | VMULOSH_OPCODE = (4u << OPCODE_SHIFT | 328u ), |
goetz@6458 | 552 | VMULOUH_OPCODE = (4u << OPCODE_SHIFT | 72u ), |
goetz@6458 | 553 | VMHADDSHS_OPCODE=(4u << OPCODE_SHIFT | 32u ), |
goetz@6458 | 554 | VMHRADDSHS_OPCODE=(4u << OPCODE_SHIFT | 33u ), |
goetz@6458 | 555 | VMLADDUHM_OPCODE=(4u << OPCODE_SHIFT | 34u ), |
goetz@6458 | 556 | VMSUBUHM_OPCODE= (4u << OPCODE_SHIFT | 36u ), |
goetz@6458 | 557 | VMSUMMBM_OPCODE= (4u << OPCODE_SHIFT | 37u ), |
goetz@6458 | 558 | VMSUMSHM_OPCODE= (4u << OPCODE_SHIFT | 40u ), |
goetz@6458 | 559 | VMSUMSHS_OPCODE= (4u << OPCODE_SHIFT | 41u ), |
goetz@6458 | 560 | VMSUMUHM_OPCODE= (4u << OPCODE_SHIFT | 38u ), |
goetz@6458 | 561 | VMSUMUHS_OPCODE= (4u << OPCODE_SHIFT | 39u ), |
goetz@6458 | 562 | |
goetz@6458 | 563 | VSUMSWS_OPCODE = (4u << OPCODE_SHIFT | 1928u ), |
goetz@6458 | 564 | VSUM2SWS_OPCODE= (4u << OPCODE_SHIFT | 1672u ), |
goetz@6458 | 565 | VSUM4SBS_OPCODE= (4u << OPCODE_SHIFT | 1800u ), |
goetz@6458 | 566 | VSUM4UBS_OPCODE= (4u << OPCODE_SHIFT | 1544u ), |
goetz@6458 | 567 | VSUM4SHS_OPCODE= (4u << OPCODE_SHIFT | 1608u ), |
goetz@6458 | 568 | |
goetz@6458 | 569 | VAVGSB_OPCODE = (4u << OPCODE_SHIFT | 1282u ), |
goetz@6458 | 570 | VAVGSW_OPCODE = (4u << OPCODE_SHIFT | 1410u ), |
goetz@6458 | 571 | VAVGSH_OPCODE = (4u << OPCODE_SHIFT | 1346u ), |
goetz@6458 | 572 | VAVGUB_OPCODE = (4u << OPCODE_SHIFT | 1026u ), |
goetz@6458 | 573 | VAVGUW_OPCODE = (4u << OPCODE_SHIFT | 1154u ), |
goetz@6458 | 574 | VAVGUH_OPCODE = (4u << OPCODE_SHIFT | 1090u ), |
goetz@6458 | 575 | |
goetz@6458 | 576 | VMAXSB_OPCODE = (4u << OPCODE_SHIFT | 258u ), |
goetz@6458 | 577 | VMAXSW_OPCODE = (4u << OPCODE_SHIFT | 386u ), |
goetz@6458 | 578 | VMAXSH_OPCODE = (4u << OPCODE_SHIFT | 322u ), |
goetz@6458 | 579 | VMAXUB_OPCODE = (4u << OPCODE_SHIFT | 2u ), |
goetz@6458 | 580 | VMAXUW_OPCODE = (4u << OPCODE_SHIFT | 130u ), |
goetz@6458 | 581 | VMAXUH_OPCODE = (4u << OPCODE_SHIFT | 66u ), |
goetz@6458 | 582 | VMINSB_OPCODE = (4u << OPCODE_SHIFT | 770u ), |
goetz@6458 | 583 | VMINSW_OPCODE = (4u << OPCODE_SHIFT | 898u ), |
goetz@6458 | 584 | VMINSH_OPCODE = (4u << OPCODE_SHIFT | 834u ), |
goetz@6458 | 585 | VMINUB_OPCODE = (4u << OPCODE_SHIFT | 514u ), |
goetz@6458 | 586 | VMINUW_OPCODE = (4u << OPCODE_SHIFT | 642u ), |
goetz@6458 | 587 | VMINUH_OPCODE = (4u << OPCODE_SHIFT | 578u ), |
goetz@6458 | 588 | |
goetz@6458 | 589 | VCMPEQUB_OPCODE= (4u << OPCODE_SHIFT | 6u ), |
goetz@6458 | 590 | VCMPEQUH_OPCODE= (4u << OPCODE_SHIFT | 70u ), |
goetz@6458 | 591 | VCMPEQUW_OPCODE= (4u << OPCODE_SHIFT | 134u ), |
goetz@6458 | 592 | VCMPGTSH_OPCODE= (4u << OPCODE_SHIFT | 838u ), |
goetz@6458 | 593 | VCMPGTSB_OPCODE= (4u << OPCODE_SHIFT | 774u ), |
goetz@6458 | 594 | VCMPGTSW_OPCODE= (4u << OPCODE_SHIFT | 902u ), |
goetz@6458 | 595 | VCMPGTUB_OPCODE= (4u << OPCODE_SHIFT | 518u ), |
goetz@6458 | 596 | VCMPGTUH_OPCODE= (4u << OPCODE_SHIFT | 582u ), |
goetz@6458 | 597 | VCMPGTUW_OPCODE= (4u << OPCODE_SHIFT | 646u ), |
goetz@6458 | 598 | |
goetz@6458 | 599 | VAND_OPCODE = (4u << OPCODE_SHIFT | 1028u ), |
goetz@6458 | 600 | VANDC_OPCODE = (4u << OPCODE_SHIFT | 1092u ), |
goetz@6458 | 601 | VNOR_OPCODE = (4u << OPCODE_SHIFT | 1284u ), |
goetz@6458 | 602 | VOR_OPCODE = (4u << OPCODE_SHIFT | 1156u ), |
goetz@6458 | 603 | VXOR_OPCODE = (4u << OPCODE_SHIFT | 1220u ), |
simonis@8608 | 604 | VRLD_OPCODE = (4u << OPCODE_SHIFT | 196u ), |
goetz@6458 | 605 | VRLB_OPCODE = (4u << OPCODE_SHIFT | 4u ), |
goetz@6458 | 606 | VRLW_OPCODE = (4u << OPCODE_SHIFT | 132u ), |
goetz@6458 | 607 | VRLH_OPCODE = (4u << OPCODE_SHIFT | 68u ), |
goetz@6458 | 608 | VSLB_OPCODE = (4u << OPCODE_SHIFT | 260u ), |
goetz@6458 | 609 | VSKW_OPCODE = (4u << OPCODE_SHIFT | 388u ), |
goetz@6458 | 610 | VSLH_OPCODE = (4u << OPCODE_SHIFT | 324u ), |
goetz@6458 | 611 | VSRB_OPCODE = (4u << OPCODE_SHIFT | 516u ), |
goetz@6458 | 612 | VSRW_OPCODE = (4u << OPCODE_SHIFT | 644u ), |
goetz@6458 | 613 | VSRH_OPCODE = (4u << OPCODE_SHIFT | 580u ), |
goetz@6458 | 614 | VSRAB_OPCODE = (4u << OPCODE_SHIFT | 772u ), |
goetz@6458 | 615 | VSRAW_OPCODE = (4u << OPCODE_SHIFT | 900u ), |
goetz@6458 | 616 | VSRAH_OPCODE = (4u << OPCODE_SHIFT | 836u ), |
goetz@6458 | 617 | |
goetz@6458 | 618 | // Vector Floating-Point |
goetz@6458 | 619 | // not implemented yet |
goetz@6458 | 620 | |
goetz@6458 | 621 | // Vector Status and Control |
goetz@6458 | 622 | MTVSCR_OPCODE = (4u << OPCODE_SHIFT | 1604u ), |
goetz@6458 | 623 | MFVSCR_OPCODE = (4u << OPCODE_SHIFT | 1540u ), |
goetz@6458 | 624 | |
goetz@7222 | 625 | // AES (introduced with Power 8) |
goetz@7222 | 626 | VCIPHER_OPCODE = (4u << OPCODE_SHIFT | 1288u), |
goetz@7222 | 627 | VCIPHERLAST_OPCODE = (4u << OPCODE_SHIFT | 1289u), |
goetz@7222 | 628 | VNCIPHER_OPCODE = (4u << OPCODE_SHIFT | 1352u), |
goetz@7222 | 629 | VNCIPHERLAST_OPCODE = (4u << OPCODE_SHIFT | 1353u), |
goetz@7222 | 630 | VSBOX_OPCODE = (4u << OPCODE_SHIFT | 1480u), |
goetz@7222 | 631 | |
goetz@7222 | 632 | // SHA (introduced with Power 8) |
goetz@7222 | 633 | VSHASIGMAD_OPCODE = (4u << OPCODE_SHIFT | 1730u), |
goetz@7222 | 634 | VSHASIGMAW_OPCODE = (4u << OPCODE_SHIFT | 1666u), |
goetz@7222 | 635 | |
goetz@7222 | 636 | // Vector Binary Polynomial Multiplication (introduced with Power 8) |
goetz@7222 | 637 | VPMSUMB_OPCODE = (4u << OPCODE_SHIFT | 1032u), |
goetz@7222 | 638 | VPMSUMD_OPCODE = (4u << OPCODE_SHIFT | 1224u), |
goetz@7222 | 639 | VPMSUMH_OPCODE = (4u << OPCODE_SHIFT | 1096u), |
goetz@7222 | 640 | VPMSUMW_OPCODE = (4u << OPCODE_SHIFT | 1160u), |
goetz@7222 | 641 | |
goetz@7222 | 642 | // Vector Permute and Xor (introduced with Power 8) |
goetz@7222 | 643 | VPERMXOR_OPCODE = (4u << OPCODE_SHIFT | 45u), |
goetz@7222 | 644 | |
goetz@7222 | 645 | // Transactional Memory instructions (introduced with Power 8) |
goetz@7222 | 646 | TBEGIN_OPCODE = (31u << OPCODE_SHIFT | 654u << 1), |
goetz@7222 | 647 | TEND_OPCODE = (31u << OPCODE_SHIFT | 686u << 1), |
goetz@7222 | 648 | TABORT_OPCODE = (31u << OPCODE_SHIFT | 910u << 1), |
goetz@7222 | 649 | TABORTWC_OPCODE = (31u << OPCODE_SHIFT | 782u << 1), |
goetz@7222 | 650 | TABORTWCI_OPCODE = (31u << OPCODE_SHIFT | 846u << 1), |
goetz@7222 | 651 | TABORTDC_OPCODE = (31u << OPCODE_SHIFT | 814u << 1), |
goetz@7222 | 652 | TABORTDCI_OPCODE = (31u << OPCODE_SHIFT | 878u << 1), |
goetz@7222 | 653 | TSR_OPCODE = (31u << OPCODE_SHIFT | 750u << 1), |
goetz@7222 | 654 | TCHECK_OPCODE = (31u << OPCODE_SHIFT | 718u << 1), |
goetz@7222 | 655 | |
goetz@6458 | 656 | // Icache and dcache related instructions |
goetz@6458 | 657 | DCBA_OPCODE = (31u << OPCODE_SHIFT | 758u << 1), |
goetz@6458 | 658 | DCBZ_OPCODE = (31u << OPCODE_SHIFT | 1014u << 1), |
goetz@6458 | 659 | DCBST_OPCODE = (31u << OPCODE_SHIFT | 54u << 1), |
goetz@6458 | 660 | DCBF_OPCODE = (31u << OPCODE_SHIFT | 86u << 1), |
goetz@6458 | 661 | |
goetz@6458 | 662 | DCBT_OPCODE = (31u << OPCODE_SHIFT | 278u << 1), |
goetz@6458 | 663 | DCBTST_OPCODE = (31u << OPCODE_SHIFT | 246u << 1), |
goetz@6458 | 664 | ICBI_OPCODE = (31u << OPCODE_SHIFT | 982u << 1), |
goetz@6458 | 665 | |
goetz@6458 | 666 | // Instruction synchronization |
goetz@6458 | 667 | ISYNC_OPCODE = (19u << OPCODE_SHIFT | 150u << 1), |
goetz@6458 | 668 | // Memory barriers |
goetz@6458 | 669 | SYNC_OPCODE = (31u << OPCODE_SHIFT | 598u << 1), |
goetz@6458 | 670 | EIEIO_OPCODE = (31u << OPCODE_SHIFT | 854u << 1), |
goetz@6458 | 671 | |
goetz@6458 | 672 | // Trap instructions |
goetz@6458 | 673 | TDI_OPCODE = (2u << OPCODE_SHIFT), |
goetz@6458 | 674 | TWI_OPCODE = (3u << OPCODE_SHIFT), |
goetz@6458 | 675 | TD_OPCODE = (31u << OPCODE_SHIFT | 68u << 1), |
goetz@6458 | 676 | TW_OPCODE = (31u << OPCODE_SHIFT | 4u << 1), |
goetz@6458 | 677 | |
goetz@6458 | 678 | // Atomics. |
goetz@6458 | 679 | LWARX_OPCODE = (31u << OPCODE_SHIFT | 20u << 1), |
goetz@6458 | 680 | LDARX_OPCODE = (31u << OPCODE_SHIFT | 84u << 1), |
gromero@9662 | 681 | LQARX_OPCODE = (31u << OPCODE_SHIFT | 276u << 1), |
goetz@6458 | 682 | STWCX_OPCODE = (31u << OPCODE_SHIFT | 150u << 1), |
gromero@9662 | 683 | STDCX_OPCODE = (31u << OPCODE_SHIFT | 214u << 1), |
gromero@9662 | 684 | STQCX_OPCODE = (31u << OPCODE_SHIFT | 182u << 1) |
goetz@6458 | 685 | |
goetz@6458 | 686 | }; |
goetz@6458 | 687 | |
goetz@6458 | 688 | // Trap instructions TO bits |
goetz@6458 | 689 | enum trap_to_bits { |
goetz@6458 | 690 | // single bits |
goetz@6458 | 691 | traptoLessThanSigned = 1 << 4, // 0, left end |
goetz@6458 | 692 | traptoGreaterThanSigned = 1 << 3, |
goetz@6458 | 693 | traptoEqual = 1 << 2, |
goetz@6458 | 694 | traptoLessThanUnsigned = 1 << 1, |
goetz@6458 | 695 | traptoGreaterThanUnsigned = 1 << 0, // 4, right end |
goetz@6458 | 696 | |
goetz@6458 | 697 | // compound ones |
goetz@6458 | 698 | traptoUnconditional = (traptoLessThanSigned | |
goetz@6458 | 699 | traptoGreaterThanSigned | |
goetz@6458 | 700 | traptoEqual | |
goetz@6458 | 701 | traptoLessThanUnsigned | |
goetz@6458 | 702 | traptoGreaterThanUnsigned) |
goetz@6458 | 703 | }; |
goetz@6458 | 704 | |
goetz@6458 | 705 | // Branch hints BH field |
goetz@6458 | 706 | enum branch_hint_bh { |
goetz@6458 | 707 | // bclr cases: |
goetz@6458 | 708 | bhintbhBCLRisReturn = 0, |
goetz@6458 | 709 | bhintbhBCLRisNotReturnButSame = 1, |
goetz@6458 | 710 | bhintbhBCLRisNotPredictable = 3, |
goetz@6458 | 711 | |
goetz@6458 | 712 | // bcctr cases: |
goetz@6458 | 713 | bhintbhBCCTRisNotReturnButSame = 0, |
goetz@6458 | 714 | bhintbhBCCTRisNotPredictable = 3 |
goetz@6458 | 715 | }; |
goetz@6458 | 716 | |
goetz@6458 | 717 | // Branch prediction hints AT field |
goetz@6458 | 718 | enum branch_hint_at { |
goetz@6458 | 719 | bhintatNoHint = 0, // at=00 |
goetz@6458 | 720 | bhintatIsNotTaken = 2, // at=10 |
goetz@6458 | 721 | bhintatIsTaken = 3 // at=11 |
goetz@6458 | 722 | }; |
goetz@6458 | 723 | |
goetz@6458 | 724 | // Branch prediction hints |
goetz@6458 | 725 | enum branch_hint_concept { |
goetz@6458 | 726 | // Use the same encoding as branch_hint_at to simply code. |
goetz@6458 | 727 | bhintNoHint = bhintatNoHint, |
goetz@6458 | 728 | bhintIsNotTaken = bhintatIsNotTaken, |
goetz@6458 | 729 | bhintIsTaken = bhintatIsTaken |
goetz@6458 | 730 | }; |
goetz@6458 | 731 | |
goetz@6458 | 732 | // Used in BO field of branch instruction. |
goetz@6458 | 733 | enum branch_condition { |
goetz@6458 | 734 | bcondCRbiIs0 = 4, // bo=001at |
goetz@6458 | 735 | bcondCRbiIs1 = 12, // bo=011at |
goetz@6458 | 736 | bcondAlways = 20 // bo=10100 |
goetz@6458 | 737 | }; |
goetz@6458 | 738 | |
goetz@6458 | 739 | // Branch condition with combined prediction hints. |
goetz@6458 | 740 | enum branch_condition_with_hint { |
goetz@6458 | 741 | bcondCRbiIs0_bhintNoHint = bcondCRbiIs0 | bhintatNoHint, |
goetz@6458 | 742 | bcondCRbiIs0_bhintIsNotTaken = bcondCRbiIs0 | bhintatIsNotTaken, |
goetz@6458 | 743 | bcondCRbiIs0_bhintIsTaken = bcondCRbiIs0 | bhintatIsTaken, |
goetz@6458 | 744 | bcondCRbiIs1_bhintNoHint = bcondCRbiIs1 | bhintatNoHint, |
goetz@6458 | 745 | bcondCRbiIs1_bhintIsNotTaken = bcondCRbiIs1 | bhintatIsNotTaken, |
goetz@6458 | 746 | bcondCRbiIs1_bhintIsTaken = bcondCRbiIs1 | bhintatIsTaken, |
goetz@6458 | 747 | }; |
goetz@6458 | 748 | |
goetz@6495 | 749 | // Elemental Memory Barriers (>=Power 8) |
goetz@6495 | 750 | enum Elemental_Membar_mask_bits { |
goetz@6495 | 751 | StoreStore = 1 << 0, |
goetz@6495 | 752 | StoreLoad = 1 << 1, |
goetz@6495 | 753 | LoadStore = 1 << 2, |
goetz@6495 | 754 | LoadLoad = 1 << 3 |
goetz@6495 | 755 | }; |
goetz@6495 | 756 | |
goetz@6458 | 757 | // Branch prediction hints. |
goetz@6458 | 758 | inline static int add_bhint_to_boint(const int bhint, const int boint) { |
goetz@6458 | 759 | switch (boint) { |
goetz@6458 | 760 | case bcondCRbiIs0: |
goetz@6458 | 761 | case bcondCRbiIs1: |
goetz@6458 | 762 | // branch_hint and branch_hint_at have same encodings |
goetz@6458 | 763 | assert( (int)bhintNoHint == (int)bhintatNoHint |
goetz@6458 | 764 | && (int)bhintIsNotTaken == (int)bhintatIsNotTaken |
goetz@6458 | 765 | && (int)bhintIsTaken == (int)bhintatIsTaken, |
goetz@6458 | 766 | "wrong encodings"); |
goetz@6458 | 767 | assert((bhint & 0x03) == bhint, "wrong encodings"); |
goetz@6458 | 768 | return (boint & ~0x03) | bhint; |
goetz@6458 | 769 | case bcondAlways: |
goetz@6458 | 770 | // no branch_hint |
goetz@6458 | 771 | return boint; |
goetz@6458 | 772 | default: |
goetz@6458 | 773 | ShouldNotReachHere(); |
goetz@6458 | 774 | return 0; |
goetz@6458 | 775 | } |
goetz@6458 | 776 | } |
goetz@6458 | 777 | |
goetz@6458 | 778 | // Extract bcond from boint. |
goetz@6458 | 779 | inline static int inv_boint_bcond(const int boint) { |
goetz@6458 | 780 | int r_bcond = boint & ~0x03; |
goetz@6458 | 781 | assert(r_bcond == bcondCRbiIs0 || |
goetz@6458 | 782 | r_bcond == bcondCRbiIs1 || |
goetz@6458 | 783 | r_bcond == bcondAlways, |
goetz@6458 | 784 | "bad branch condition"); |
goetz@6458 | 785 | return r_bcond; |
goetz@6458 | 786 | } |
goetz@6458 | 787 | |
goetz@6458 | 788 | // Extract bhint from boint. |
goetz@6458 | 789 | inline static int inv_boint_bhint(const int boint) { |
goetz@6458 | 790 | int r_bhint = boint & 0x03; |
goetz@6458 | 791 | assert(r_bhint == bhintatNoHint || |
goetz@6458 | 792 | r_bhint == bhintatIsNotTaken || |
goetz@6458 | 793 | r_bhint == bhintatIsTaken, |
goetz@6458 | 794 | "bad branch hint"); |
goetz@6458 | 795 | return r_bhint; |
goetz@6458 | 796 | } |
goetz@6458 | 797 | |
goetz@6458 | 798 | // Calculate opposite of given bcond. |
goetz@6458 | 799 | inline static int opposite_bcond(const int bcond) { |
goetz@6458 | 800 | switch (bcond) { |
goetz@6458 | 801 | case bcondCRbiIs0: |
goetz@6458 | 802 | return bcondCRbiIs1; |
goetz@6458 | 803 | case bcondCRbiIs1: |
goetz@6458 | 804 | return bcondCRbiIs0; |
goetz@6458 | 805 | default: |
goetz@6458 | 806 | ShouldNotReachHere(); |
goetz@6458 | 807 | return 0; |
goetz@6458 | 808 | } |
goetz@6458 | 809 | } |
goetz@6458 | 810 | |
goetz@6458 | 811 | // Calculate opposite of given bhint. |
goetz@6458 | 812 | inline static int opposite_bhint(const int bhint) { |
goetz@6458 | 813 | switch (bhint) { |
goetz@6458 | 814 | case bhintatNoHint: |
goetz@6458 | 815 | return bhintatNoHint; |
goetz@6458 | 816 | case bhintatIsNotTaken: |
goetz@6458 | 817 | return bhintatIsTaken; |
goetz@6458 | 818 | case bhintatIsTaken: |
goetz@6458 | 819 | return bhintatIsNotTaken; |
goetz@6458 | 820 | default: |
goetz@6458 | 821 | ShouldNotReachHere(); |
goetz@6458 | 822 | return 0; |
goetz@6458 | 823 | } |
goetz@6458 | 824 | } |
goetz@6458 | 825 | |
goetz@6458 | 826 | // PPC branch instructions |
goetz@6458 | 827 | enum ppcops { |
goetz@6458 | 828 | b_op = 18, |
goetz@6458 | 829 | bc_op = 16, |
goetz@6458 | 830 | bcr_op = 19 |
goetz@6458 | 831 | }; |
goetz@6458 | 832 | |
goetz@6458 | 833 | enum Condition { |
goetz@6458 | 834 | negative = 0, |
goetz@6458 | 835 | less = 0, |
goetz@6458 | 836 | positive = 1, |
goetz@6458 | 837 | greater = 1, |
goetz@6458 | 838 | zero = 2, |
goetz@6458 | 839 | equal = 2, |
goetz@6458 | 840 | summary_overflow = 3, |
goetz@6458 | 841 | }; |
goetz@6458 | 842 | |
goetz@6458 | 843 | public: |
goetz@6458 | 844 | // Helper functions for groups of instructions |
goetz@6458 | 845 | |
goetz@6458 | 846 | enum Predict { pt = 1, pn = 0 }; // pt = predict taken |
goetz@6458 | 847 | |
goetz@6458 | 848 | // instruction must start at passed address |
goetz@6458 | 849 | static int instr_len(unsigned char *instr) { return BytesPerInstWord; } |
goetz@6458 | 850 | |
goetz@6458 | 851 | // instruction must be left-justified in argument |
goetz@6458 | 852 | static int instr_len(unsigned long instr) { return BytesPerInstWord; } |
goetz@6458 | 853 | |
goetz@6458 | 854 | // longest instructions |
goetz@6458 | 855 | static int instr_maxlen() { return BytesPerInstWord; } |
goetz@6458 | 856 | |
goetz@6458 | 857 | // Test if x is within signed immediate range for nbits. |
goetz@6458 | 858 | static bool is_simm(int x, unsigned int nbits) { |
goetz@6458 | 859 | assert(0 < nbits && nbits < 32, "out of bounds"); |
goetz@6458 | 860 | const int min = -( ((int)1) << nbits-1 ); |
goetz@6458 | 861 | const int maxplus1 = ( ((int)1) << nbits-1 ); |
goetz@6458 | 862 | return min <= x && x < maxplus1; |
goetz@6458 | 863 | } |
goetz@6458 | 864 | |
goetz@6458 | 865 | static bool is_simm(jlong x, unsigned int nbits) { |
goetz@6458 | 866 | assert(0 < nbits && nbits < 64, "out of bounds"); |
goetz@6458 | 867 | const jlong min = -( ((jlong)1) << nbits-1 ); |
goetz@6458 | 868 | const jlong maxplus1 = ( ((jlong)1) << nbits-1 ); |
goetz@6458 | 869 | return min <= x && x < maxplus1; |
goetz@6458 | 870 | } |
goetz@6458 | 871 | |
goetz@6458 | 872 | // Test if x is within unsigned immediate range for nbits |
goetz@6458 | 873 | static bool is_uimm(int x, unsigned int nbits) { |
goetz@6458 | 874 | assert(0 < nbits && nbits < 32, "out of bounds"); |
goetz@6458 | 875 | const int maxplus1 = ( ((int)1) << nbits ); |
goetz@6458 | 876 | return 0 <= x && x < maxplus1; |
goetz@6458 | 877 | } |
goetz@6458 | 878 | |
goetz@6458 | 879 | static bool is_uimm(jlong x, unsigned int nbits) { |
goetz@6458 | 880 | assert(0 < nbits && nbits < 64, "out of bounds"); |
goetz@6458 | 881 | const jlong maxplus1 = ( ((jlong)1) << nbits ); |
goetz@6458 | 882 | return 0 <= x && x < maxplus1; |
goetz@6458 | 883 | } |
goetz@6458 | 884 | |
goetz@6458 | 885 | protected: |
goetz@6458 | 886 | // helpers |
goetz@6458 | 887 | |
goetz@6458 | 888 | // X is supposed to fit in a field "nbits" wide |
goetz@6458 | 889 | // and be sign-extended. Check the range. |
goetz@6458 | 890 | static void assert_signed_range(intptr_t x, int nbits) { |
goetz@6458 | 891 | assert(nbits == 32 || (-(1 << nbits-1) <= x && x < (1 << nbits-1)), |
goetz@6458 | 892 | "value out of range"); |
goetz@6458 | 893 | } |
goetz@6458 | 894 | |
goetz@6458 | 895 | static void assert_signed_word_disp_range(intptr_t x, int nbits) { |
goetz@6458 | 896 | assert((x & 3) == 0, "not word aligned"); |
goetz@6458 | 897 | assert_signed_range(x, nbits + 2); |
goetz@6458 | 898 | } |
goetz@6458 | 899 | |
goetz@6458 | 900 | static void assert_unsigned_const(int x, int nbits) { |
goetz@6458 | 901 | assert(juint(x) < juint(1 << nbits), "unsigned constant out of range"); |
goetz@6458 | 902 | } |
goetz@6458 | 903 | |
goetz@6458 | 904 | static int fmask(juint hi_bit, juint lo_bit) { |
goetz@6458 | 905 | assert(hi_bit >= lo_bit && hi_bit < 32, "bad bits"); |
goetz@6458 | 906 | return (1 << ( hi_bit-lo_bit + 1 )) - 1; |
goetz@6458 | 907 | } |
goetz@6458 | 908 | |
goetz@6458 | 909 | // inverse of u_field |
goetz@6458 | 910 | static int inv_u_field(int x, int hi_bit, int lo_bit) { |
goetz@6458 | 911 | juint r = juint(x) >> lo_bit; |
goetz@6458 | 912 | r &= fmask(hi_bit, lo_bit); |
goetz@6458 | 913 | return int(r); |
goetz@6458 | 914 | } |
goetz@6458 | 915 | |
goetz@6458 | 916 | // signed version: extract from field and sign-extend |
goetz@6458 | 917 | static int inv_s_field_ppc(int x, int hi_bit, int lo_bit) { |
goetz@6458 | 918 | x = x << (31-hi_bit); |
goetz@6458 | 919 | x = x >> (31-hi_bit+lo_bit); |
goetz@6458 | 920 | return x; |
goetz@6458 | 921 | } |
goetz@6458 | 922 | |
goetz@6458 | 923 | static int u_field(int x, int hi_bit, int lo_bit) { |
goetz@6458 | 924 | assert((x & ~fmask(hi_bit, lo_bit)) == 0, "value out of range"); |
goetz@6458 | 925 | int r = x << lo_bit; |
goetz@6458 | 926 | assert(inv_u_field(r, hi_bit, lo_bit) == x, "just checking"); |
goetz@6458 | 927 | return r; |
goetz@6458 | 928 | } |
goetz@6458 | 929 | |
goetz@6458 | 930 | // Same as u_field for signed values |
goetz@6458 | 931 | static int s_field(int x, int hi_bit, int lo_bit) { |
goetz@6458 | 932 | int nbits = hi_bit - lo_bit + 1; |
goetz@6458 | 933 | assert(nbits == 32 || (-(1 << nbits-1) <= x && x < (1 << nbits-1)), |
goetz@6458 | 934 | "value out of range"); |
goetz@6458 | 935 | x &= fmask(hi_bit, lo_bit); |
goetz@6458 | 936 | int r = x << lo_bit; |
goetz@6458 | 937 | return r; |
goetz@6458 | 938 | } |
goetz@6458 | 939 | |
goetz@6458 | 940 | // inv_op for ppc instructions |
goetz@6458 | 941 | static int inv_op_ppc(int x) { return inv_u_field(x, 31, 26); } |
goetz@6458 | 942 | |
goetz@6458 | 943 | // Determine target address from li, bd field of branch instruction. |
goetz@6458 | 944 | static intptr_t inv_li_field(int x) { |
goetz@6458 | 945 | intptr_t r = inv_s_field_ppc(x, 25, 2); |
goetz@6458 | 946 | r = (r << 2); |
goetz@6458 | 947 | return r; |
goetz@6458 | 948 | } |
goetz@6458 | 949 | static intptr_t inv_bd_field(int x, intptr_t pos) { |
goetz@6458 | 950 | intptr_t r = inv_s_field_ppc(x, 15, 2); |
goetz@6458 | 951 | r = (r << 2) + pos; |
goetz@6458 | 952 | return r; |
goetz@6458 | 953 | } |
goetz@6458 | 954 | |
goetz@6458 | 955 | #define inv_opp_u_field(x, hi_bit, lo_bit) inv_u_field(x, 31-(lo_bit), 31-(hi_bit)) |
goetz@6458 | 956 | #define inv_opp_s_field(x, hi_bit, lo_bit) inv_s_field_ppc(x, 31-(lo_bit), 31-(hi_bit)) |
goetz@6458 | 957 | // Extract instruction fields from instruction words. |
goetz@6458 | 958 | public: |
goetz@6495 | 959 | static int inv_ra_field(int x) { return inv_opp_u_field(x, 15, 11); } |
goetz@6495 | 960 | static int inv_rb_field(int x) { return inv_opp_u_field(x, 20, 16); } |
goetz@6495 | 961 | static int inv_rt_field(int x) { return inv_opp_u_field(x, 10, 6); } |
goetz@6495 | 962 | static int inv_rta_field(int x) { return inv_opp_u_field(x, 15, 11); } |
goetz@6495 | 963 | static int inv_rs_field(int x) { return inv_opp_u_field(x, 10, 6); } |
goetz@6458 | 964 | // Ds uses opp_s_field(x, 31, 16), but lowest 2 bits must be 0. |
goetz@6458 | 965 | // Inv_ds_field uses range (x, 29, 16) but shifts by 2 to ensure that lowest bits are 0. |
goetz@6495 | 966 | static int inv_ds_field(int x) { return inv_opp_s_field(x, 29, 16) << 2; } |
goetz@6495 | 967 | static int inv_d1_field(int x) { return inv_opp_s_field(x, 31, 16); } |
goetz@6495 | 968 | static int inv_si_field(int x) { return inv_opp_s_field(x, 31, 16); } |
goetz@6495 | 969 | static int inv_to_field(int x) { return inv_opp_u_field(x, 10, 6); } |
goetz@6495 | 970 | static int inv_lk_field(int x) { return inv_opp_u_field(x, 31, 31); } |
goetz@6495 | 971 | static int inv_bo_field(int x) { return inv_opp_u_field(x, 10, 6); } |
goetz@6495 | 972 | static int inv_bi_field(int x) { return inv_opp_u_field(x, 15, 11); } |
goetz@6458 | 973 | |
goetz@6458 | 974 | #define opp_u_field(x, hi_bit, lo_bit) u_field(x, 31-(lo_bit), 31-(hi_bit)) |
goetz@6458 | 975 | #define opp_s_field(x, hi_bit, lo_bit) s_field(x, 31-(lo_bit), 31-(hi_bit)) |
goetz@6458 | 976 | |
goetz@6458 | 977 | // instruction fields |
goetz@6458 | 978 | static int aa( int x) { return opp_u_field(x, 30, 30); } |
goetz@6458 | 979 | static int ba( int x) { return opp_u_field(x, 15, 11); } |
goetz@6458 | 980 | static int bb( int x) { return opp_u_field(x, 20, 16); } |
goetz@6458 | 981 | static int bc( int x) { return opp_u_field(x, 25, 21); } |
goetz@6458 | 982 | static int bd( int x) { return opp_s_field(x, 29, 16); } |
goetz@6458 | 983 | static int bf( ConditionRegister cr) { return bf(cr->encoding()); } |
goetz@6458 | 984 | static int bf( int x) { return opp_u_field(x, 8, 6); } |
goetz@6458 | 985 | static int bfa(ConditionRegister cr) { return bfa(cr->encoding()); } |
goetz@6458 | 986 | static int bfa( int x) { return opp_u_field(x, 13, 11); } |
goetz@6458 | 987 | static int bh( int x) { return opp_u_field(x, 20, 19); } |
goetz@6458 | 988 | static int bi( int x) { return opp_u_field(x, 15, 11); } |
goetz@6458 | 989 | static int bi0(ConditionRegister cr, Condition c) { return (cr->encoding() << 2) | c; } |
goetz@6458 | 990 | static int bo( int x) { return opp_u_field(x, 10, 6); } |
goetz@6458 | 991 | static int bt( int x) { return opp_u_field(x, 10, 6); } |
goetz@6458 | 992 | static int d1( int x) { return opp_s_field(x, 31, 16); } |
goetz@6458 | 993 | static int ds( int x) { assert((x & 0x3) == 0, "unaligned offset"); return opp_s_field(x, 31, 16); } |
goetz@6458 | 994 | static int eh( int x) { return opp_u_field(x, 31, 31); } |
goetz@6458 | 995 | static int flm( int x) { return opp_u_field(x, 14, 7); } |
goetz@6458 | 996 | static int fra( FloatRegister r) { return fra(r->encoding());} |
goetz@6458 | 997 | static int frb( FloatRegister r) { return frb(r->encoding());} |
goetz@6458 | 998 | static int frc( FloatRegister r) { return frc(r->encoding());} |
goetz@6458 | 999 | static int frs( FloatRegister r) { return frs(r->encoding());} |
goetz@6458 | 1000 | static int frt( FloatRegister r) { return frt(r->encoding());} |
goetz@6458 | 1001 | static int fra( int x) { return opp_u_field(x, 15, 11); } |
goetz@6458 | 1002 | static int frb( int x) { return opp_u_field(x, 20, 16); } |
goetz@6458 | 1003 | static int frc( int x) { return opp_u_field(x, 25, 21); } |
goetz@6458 | 1004 | static int frs( int x) { return opp_u_field(x, 10, 6); } |
goetz@6458 | 1005 | static int frt( int x) { return opp_u_field(x, 10, 6); } |
goetz@6458 | 1006 | static int fxm( int x) { return opp_u_field(x, 19, 12); } |
goetz@6458 | 1007 | static int l10( int x) { return opp_u_field(x, 10, 10); } |
goetz@6458 | 1008 | static int l15( int x) { return opp_u_field(x, 15, 15); } |
goetz@6458 | 1009 | static int l910( int x) { return opp_u_field(x, 10, 9); } |
goetz@6495 | 1010 | static int e1215( int x) { return opp_u_field(x, 15, 12); } |
goetz@6458 | 1011 | static int lev( int x) { return opp_u_field(x, 26, 20); } |
goetz@6458 | 1012 | static int li( int x) { return opp_s_field(x, 29, 6); } |
goetz@6458 | 1013 | static int lk( int x) { return opp_u_field(x, 31, 31); } |
goetz@6458 | 1014 | static int mb2125( int x) { return opp_u_field(x, 25, 21); } |
goetz@6458 | 1015 | static int me2630( int x) { return opp_u_field(x, 30, 26); } |
goetz@6458 | 1016 | static int mb2126( int x) { return opp_u_field(((x & 0x1f) << 1) | ((x & 0x20) >> 5), 26, 21); } |
goetz@6458 | 1017 | static int me2126( int x) { return mb2126(x); } |
goetz@6458 | 1018 | static int nb( int x) { return opp_u_field(x, 20, 16); } |
goetz@6458 | 1019 | //static int opcd( int x) { return opp_u_field(x, 5, 0); } // is contained in our opcodes |
goetz@6458 | 1020 | static int oe( int x) { return opp_u_field(x, 21, 21); } |
goetz@6458 | 1021 | static int ra( Register r) { return ra(r->encoding()); } |
goetz@6458 | 1022 | static int ra( int x) { return opp_u_field(x, 15, 11); } |
goetz@6458 | 1023 | static int rb( Register r) { return rb(r->encoding()); } |
goetz@6458 | 1024 | static int rb( int x) { return opp_u_field(x, 20, 16); } |
goetz@6458 | 1025 | static int rc( int x) { return opp_u_field(x, 31, 31); } |
goetz@6458 | 1026 | static int rs( Register r) { return rs(r->encoding()); } |
goetz@6458 | 1027 | static int rs( int x) { return opp_u_field(x, 10, 6); } |
goetz@6458 | 1028 | // we don't want to use R0 in memory accesses, because it has value `0' then |
goetz@6458 | 1029 | static int ra0mem( Register r) { assert(r != R0, "cannot use register R0 in memory access"); return ra(r); } |
goetz@6458 | 1030 | static int ra0mem( int x) { assert(x != 0, "cannot use register 0 in memory access"); return ra(x); } |
goetz@6458 | 1031 | |
goetz@6458 | 1032 | // register r is target |
goetz@6458 | 1033 | static int rt( Register r) { return rs(r); } |
goetz@6458 | 1034 | static int rt( int x) { return rs(x); } |
goetz@6458 | 1035 | static int rta( Register r) { return ra(r); } |
goetz@6458 | 1036 | static int rta0mem( Register r) { rta(r); return ra0mem(r); } |
goetz@6458 | 1037 | |
goetz@6458 | 1038 | static int sh1620( int x) { return opp_u_field(x, 20, 16); } |
goetz@6458 | 1039 | static int sh30( int x) { return opp_u_field(x, 30, 30); } |
goetz@6458 | 1040 | static int sh162030( int x) { return sh1620(x & 0x1f) | sh30((x & 0x20) >> 5); } |
goetz@6458 | 1041 | static int si( int x) { return opp_s_field(x, 31, 16); } |
goetz@6458 | 1042 | static int spr( int x) { return opp_u_field(x, 20, 11); } |
goetz@6458 | 1043 | static int sr( int x) { return opp_u_field(x, 15, 12); } |
goetz@6458 | 1044 | static int tbr( int x) { return opp_u_field(x, 20, 11); } |
goetz@6458 | 1045 | static int th( int x) { return opp_u_field(x, 10, 7); } |
goetz@6495 | 1046 | static int thct( int x) { assert((x&8) == 0, "must be valid cache specification"); return th(x); } |
goetz@6495 | 1047 | static int thds( int x) { assert((x&8) == 8, "must be valid stream specification"); return th(x); } |
goetz@6458 | 1048 | static int to( int x) { return opp_u_field(x, 10, 6); } |
goetz@6458 | 1049 | static int u( int x) { return opp_u_field(x, 19, 16); } |
goetz@6458 | 1050 | static int ui( int x) { return opp_u_field(x, 31, 16); } |
goetz@6458 | 1051 | |
goetz@6495 | 1052 | // Support vector instructions for >= Power6. |
goetz@6458 | 1053 | static int vra( int x) { return opp_u_field(x, 15, 11); } |
goetz@6458 | 1054 | static int vrb( int x) { return opp_u_field(x, 20, 16); } |
goetz@6458 | 1055 | static int vrc( int x) { return opp_u_field(x, 25, 21); } |
goetz@6458 | 1056 | static int vrs( int x) { return opp_u_field(x, 10, 6); } |
goetz@6458 | 1057 | static int vrt( int x) { return opp_u_field(x, 10, 6); } |
goetz@6458 | 1058 | |
goetz@6458 | 1059 | static int vra( VectorRegister r) { return vra(r->encoding());} |
goetz@6458 | 1060 | static int vrb( VectorRegister r) { return vrb(r->encoding());} |
goetz@6458 | 1061 | static int vrc( VectorRegister r) { return vrc(r->encoding());} |
goetz@6458 | 1062 | static int vrs( VectorRegister r) { return vrs(r->encoding());} |
goetz@6458 | 1063 | static int vrt( VectorRegister r) { return vrt(r->encoding());} |
goetz@6458 | 1064 | |
gromero@9687 | 1065 | // Only used on SHA sigma instructions (VX-form) |
gromero@9687 | 1066 | static int vst( int x) { return opp_u_field(x, 16, 16); } |
gromero@9687 | 1067 | static int vsix( int x) { return opp_u_field(x, 20, 17); } |
gromero@9687 | 1068 | |
gromero@9662 | 1069 | // Support Vector-Scalar (VSX) instructions. |
gromero@9687 | 1070 | static int vsra( int x) { return opp_u_field(x & 0x1F, 15, 11) | opp_u_field((x & 0x20) >> 5, 29, 29); } |
gromero@9687 | 1071 | static int vsrb( int x) { return opp_u_field(x & 0x1F, 20, 16) | opp_u_field((x & 0x20) >> 5, 30, 30); } |
gromero@9687 | 1072 | static int vsrs( int x) { return opp_u_field(x & 0x1F, 10, 6) | opp_u_field((x & 0x20) >> 5, 31, 31); } |
gromero@9687 | 1073 | static int vsrt( int x) { return vsrs(x); } |
gromero@9687 | 1074 | static int vsdm( int x) { return opp_u_field(x, 23, 22); } |
gromero@9662 | 1075 | |
gromero@9662 | 1076 | static int vsra( VectorSRegister r) { return vsra(r->encoding());} |
gromero@9662 | 1077 | static int vsrb( VectorSRegister r) { return vsrb(r->encoding());} |
gromero@9662 | 1078 | static int vsrs( VectorSRegister r) { return vsrs(r->encoding());} |
gromero@9662 | 1079 | static int vsrt( VectorSRegister r) { return vsrt(r->encoding());} |
gromero@9662 | 1080 | |
goetz@6458 | 1081 | static int vsplt_uim( int x) { return opp_u_field(x, 15, 12); } // for vsplt* instructions |
goetz@6458 | 1082 | static int vsplti_sim(int x) { return opp_u_field(x, 15, 11); } // for vsplti* instructions |
goetz@6458 | 1083 | static int vsldoi_shb(int x) { return opp_u_field(x, 25, 22); } // for vsldoi instruction |
goetz@6458 | 1084 | static int vcmp_rc( int x) { return opp_u_field(x, 21, 21); } // for vcmp* instructions |
goetz@6458 | 1085 | |
goetz@6458 | 1086 | //static int xo1( int x) { return opp_u_field(x, 29, 21); }// is contained in our opcodes |
goetz@6458 | 1087 | //static int xo2( int x) { return opp_u_field(x, 30, 21); }// is contained in our opcodes |
goetz@6458 | 1088 | //static int xo3( int x) { return opp_u_field(x, 30, 22); }// is contained in our opcodes |
goetz@6458 | 1089 | //static int xo4( int x) { return opp_u_field(x, 30, 26); }// is contained in our opcodes |
goetz@6458 | 1090 | //static int xo5( int x) { return opp_u_field(x, 29, 27); }// is contained in our opcodes |
goetz@6458 | 1091 | //static int xo6( int x) { return opp_u_field(x, 30, 27); }// is contained in our opcodes |
goetz@6458 | 1092 | //static int xo7( int x) { return opp_u_field(x, 31, 30); }// is contained in our opcodes |
goetz@6458 | 1093 | |
goetz@6458 | 1094 | protected: |
goetz@6458 | 1095 | // Compute relative address for branch. |
goetz@6458 | 1096 | static intptr_t disp(intptr_t x, intptr_t off) { |
goetz@6458 | 1097 | int xx = x - off; |
goetz@6458 | 1098 | xx = xx >> 2; |
goetz@6458 | 1099 | return xx; |
goetz@6458 | 1100 | } |
goetz@6458 | 1101 | |
goetz@6458 | 1102 | public: |
goetz@6458 | 1103 | // signed immediate, in low bits, nbits long |
goetz@6458 | 1104 | static int simm(int x, int nbits) { |
goetz@6458 | 1105 | assert_signed_range(x, nbits); |
goetz@6458 | 1106 | return x & ((1 << nbits) - 1); |
goetz@6458 | 1107 | } |
goetz@6458 | 1108 | |
goetz@6458 | 1109 | // unsigned immediate, in low bits, nbits long |
goetz@6458 | 1110 | static int uimm(int x, int nbits) { |
goetz@6458 | 1111 | assert_unsigned_const(x, nbits); |
goetz@6458 | 1112 | return x & ((1 << nbits) - 1); |
goetz@6458 | 1113 | } |
goetz@6458 | 1114 | |
goetz@6458 | 1115 | static void set_imm(int* instr, short s) { |
kvn@6538 | 1116 | // imm is always in the lower 16 bits of the instruction, |
kvn@6538 | 1117 | // so this is endian-neutral. Same for the get_imm below. |
kvn@6538 | 1118 | uint32_t w = *(uint32_t *)instr; |
kvn@6538 | 1119 | *instr = (int)((w & ~0x0000FFFF) | (s & 0x0000FFFF)); |
goetz@6458 | 1120 | } |
goetz@6458 | 1121 | |
goetz@6458 | 1122 | static int get_imm(address a, int instruction_number) { |
kvn@6538 | 1123 | return (short)((int *)a)[instruction_number]; |
goetz@6458 | 1124 | } |
goetz@6458 | 1125 | |
goetz@6458 | 1126 | static inline int hi16_signed( int x) { return (int)(int16_t)(x >> 16); } |
goetz@6458 | 1127 | static inline int lo16_unsigned(int x) { return x & 0xffff; } |
goetz@6458 | 1128 | |
goetz@6458 | 1129 | protected: |
goetz@6458 | 1130 | |
goetz@6458 | 1131 | // Extract the top 32 bits in a 64 bit word. |
goetz@6458 | 1132 | static int32_t hi32(int64_t x) { |
goetz@6458 | 1133 | int32_t r = int32_t((uint64_t)x >> 32); |
goetz@6458 | 1134 | return r; |
goetz@6458 | 1135 | } |
goetz@6458 | 1136 | |
goetz@6458 | 1137 | public: |
goetz@6458 | 1138 | |
goetz@6458 | 1139 | static inline unsigned int align_addr(unsigned int addr, unsigned int a) { |
goetz@6458 | 1140 | return ((addr + (a - 1)) & ~(a - 1)); |
goetz@6458 | 1141 | } |
goetz@6458 | 1142 | |
goetz@6458 | 1143 | static inline bool is_aligned(unsigned int addr, unsigned int a) { |
goetz@6458 | 1144 | return (0 == addr % a); |
goetz@6458 | 1145 | } |
goetz@6458 | 1146 | |
goetz@6458 | 1147 | void flush() { |
goetz@6458 | 1148 | AbstractAssembler::flush(); |
goetz@6458 | 1149 | } |
goetz@6458 | 1150 | |
goetz@6458 | 1151 | inline void emit_int32(int); // shadows AbstractAssembler::emit_int32 |
goetz@6458 | 1152 | inline void emit_data(int); |
goetz@6458 | 1153 | inline void emit_data(int, RelocationHolder const&); |
goetz@6458 | 1154 | inline void emit_data(int, relocInfo::relocType rtype); |
goetz@6458 | 1155 | |
goetz@6458 | 1156 | // Emit an address. |
goetz@6458 | 1157 | inline address emit_addr(const address addr = NULL); |
goetz@6458 | 1158 | |
goetz@6511 | 1159 | #if !defined(ABI_ELFv2) |
goetz@6458 | 1160 | // Emit a function descriptor with the specified entry point, TOC, |
goetz@6458 | 1161 | // and ENV. If the entry point is NULL, the descriptor will point |
goetz@6458 | 1162 | // just past the descriptor. |
goetz@6458 | 1163 | // Use values from friend functions as defaults. |
goetz@6458 | 1164 | inline address emit_fd(address entry = NULL, |
goetz@6458 | 1165 | address toc = (address) FunctionDescriptor::friend_toc, |
goetz@6458 | 1166 | address env = (address) FunctionDescriptor::friend_env); |
goetz@6511 | 1167 | #endif |
goetz@6458 | 1168 | |
goetz@6458 | 1169 | ///////////////////////////////////////////////////////////////////////////////////// |
goetz@6458 | 1170 | // PPC instructions |
goetz@6458 | 1171 | ///////////////////////////////////////////////////////////////////////////////////// |
goetz@6458 | 1172 | |
goetz@6458 | 1173 | // Memory instructions use r0 as hard coded 0, e.g. to simulate loading |
goetz@6458 | 1174 | // immediates. The normal instruction encoders enforce that r0 is not |
goetz@6458 | 1175 | // passed to them. Use either extended mnemonics encoders or the special ra0 |
goetz@6458 | 1176 | // versions. |
goetz@6458 | 1177 | |
goetz@6458 | 1178 | // Issue an illegal instruction. |
goetz@6458 | 1179 | inline void illtrap(); |
goetz@6458 | 1180 | static inline bool is_illtrap(int x); |
goetz@6458 | 1181 | |
goetz@6458 | 1182 | // PPC 1, section 3.3.8, Fixed-Point Arithmetic Instructions |
goetz@6458 | 1183 | inline void addi( Register d, Register a, int si16); |
goetz@6458 | 1184 | inline void addis(Register d, Register a, int si16); |
goetz@6458 | 1185 | private: |
goetz@6458 | 1186 | inline void addi_r0ok( Register d, Register a, int si16); |
goetz@6458 | 1187 | inline void addis_r0ok(Register d, Register a, int si16); |
goetz@6458 | 1188 | public: |
goetz@6458 | 1189 | inline void addic_( Register d, Register a, int si16); |
goetz@6458 | 1190 | inline void subfic( Register d, Register a, int si16); |
goetz@6458 | 1191 | inline void add( Register d, Register a, Register b); |
goetz@6458 | 1192 | inline void add_( Register d, Register a, Register b); |
goetz@6495 | 1193 | inline void subf( Register d, Register a, Register b); // d = b - a "Sub_from", as in ppc spec. |
goetz@6495 | 1194 | inline void sub( Register d, Register a, Register b); // d = a - b Swap operands of subf for readability. |
goetz@6458 | 1195 | inline void subf_( Register d, Register a, Register b); |
goetz@6458 | 1196 | inline void addc( Register d, Register a, Register b); |
goetz@6458 | 1197 | inline void addc_( Register d, Register a, Register b); |
goetz@6458 | 1198 | inline void subfc( Register d, Register a, Register b); |
goetz@6458 | 1199 | inline void subfc_( Register d, Register a, Register b); |
goetz@6458 | 1200 | inline void adde( Register d, Register a, Register b); |
goetz@6458 | 1201 | inline void adde_( Register d, Register a, Register b); |
goetz@6458 | 1202 | inline void subfe( Register d, Register a, Register b); |
goetz@6458 | 1203 | inline void subfe_( Register d, Register a, Register b); |
goetz@6458 | 1204 | inline void neg( Register d, Register a); |
goetz@6458 | 1205 | inline void neg_( Register d, Register a); |
goetz@6458 | 1206 | inline void mulli( Register d, Register a, int si16); |
goetz@6458 | 1207 | inline void mulld( Register d, Register a, Register b); |
goetz@6458 | 1208 | inline void mulld_( Register d, Register a, Register b); |
goetz@6458 | 1209 | inline void mullw( Register d, Register a, Register b); |
goetz@6458 | 1210 | inline void mullw_( Register d, Register a, Register b); |
goetz@6458 | 1211 | inline void mulhw( Register d, Register a, Register b); |
goetz@6458 | 1212 | inline void mulhw_( Register d, Register a, Register b); |
mdoerr@8903 | 1213 | inline void mulhwu( Register d, Register a, Register b); |
mdoerr@8903 | 1214 | inline void mulhwu_(Register d, Register a, Register b); |
goetz@6458 | 1215 | inline void mulhd( Register d, Register a, Register b); |
goetz@6458 | 1216 | inline void mulhd_( Register d, Register a, Register b); |
goetz@6458 | 1217 | inline void mulhdu( Register d, Register a, Register b); |
goetz@6458 | 1218 | inline void mulhdu_(Register d, Register a, Register b); |
goetz@6458 | 1219 | inline void divd( Register d, Register a, Register b); |
goetz@6458 | 1220 | inline void divd_( Register d, Register a, Register b); |
goetz@6458 | 1221 | inline void divw( Register d, Register a, Register b); |
goetz@6458 | 1222 | inline void divw_( Register d, Register a, Register b); |
goetz@6458 | 1223 | |
goetz@6458 | 1224 | // extended mnemonics |
goetz@6458 | 1225 | inline void li( Register d, int si16); |
goetz@6458 | 1226 | inline void lis( Register d, int si16); |
goetz@6458 | 1227 | inline void addir(Register d, int si16, Register a); |
goetz@6458 | 1228 | |
goetz@6458 | 1229 | static bool is_addi(int x) { |
goetz@6458 | 1230 | return ADDI_OPCODE == (x & ADDI_OPCODE_MASK); |
goetz@6458 | 1231 | } |
goetz@6458 | 1232 | static bool is_addis(int x) { |
goetz@6458 | 1233 | return ADDIS_OPCODE == (x & ADDIS_OPCODE_MASK); |
goetz@6458 | 1234 | } |
goetz@6458 | 1235 | static bool is_bxx(int x) { |
goetz@6458 | 1236 | return BXX_OPCODE == (x & BXX_OPCODE_MASK); |
goetz@6458 | 1237 | } |
goetz@6458 | 1238 | static bool is_b(int x) { |
goetz@6458 | 1239 | return BXX_OPCODE == (x & BXX_OPCODE_MASK) && inv_lk_field(x) == 0; |
goetz@6458 | 1240 | } |
goetz@6458 | 1241 | static bool is_bl(int x) { |
goetz@6458 | 1242 | return BXX_OPCODE == (x & BXX_OPCODE_MASK) && inv_lk_field(x) == 1; |
goetz@6458 | 1243 | } |
goetz@6458 | 1244 | static bool is_bcxx(int x) { |
goetz@6458 | 1245 | return BCXX_OPCODE == (x & BCXX_OPCODE_MASK); |
goetz@6458 | 1246 | } |
goetz@6458 | 1247 | static bool is_bxx_or_bcxx(int x) { |
goetz@6458 | 1248 | return is_bxx(x) || is_bcxx(x); |
goetz@6458 | 1249 | } |
goetz@6458 | 1250 | static bool is_bctrl(int x) { |
goetz@6458 | 1251 | return x == 0x4e800421; |
goetz@6458 | 1252 | } |
goetz@6458 | 1253 | static bool is_bctr(int x) { |
goetz@6458 | 1254 | return x == 0x4e800420; |
goetz@6458 | 1255 | } |
goetz@6458 | 1256 | static bool is_bclr(int x) { |
goetz@6458 | 1257 | return BCLR_OPCODE == (x & XL_FORM_OPCODE_MASK); |
goetz@6458 | 1258 | } |
goetz@6458 | 1259 | static bool is_li(int x) { |
goetz@6458 | 1260 | return is_addi(x) && inv_ra_field(x)==0; |
goetz@6458 | 1261 | } |
goetz@6458 | 1262 | static bool is_lis(int x) { |
goetz@6458 | 1263 | return is_addis(x) && inv_ra_field(x)==0; |
goetz@6458 | 1264 | } |
goetz@6458 | 1265 | static bool is_mtctr(int x) { |
goetz@6458 | 1266 | return MTCTR_OPCODE == (x & MTCTR_OPCODE_MASK); |
goetz@6458 | 1267 | } |
goetz@6458 | 1268 | static bool is_ld(int x) { |
goetz@6458 | 1269 | return LD_OPCODE == (x & LD_OPCODE_MASK); |
goetz@6458 | 1270 | } |
goetz@6458 | 1271 | static bool is_std(int x) { |
goetz@6458 | 1272 | return STD_OPCODE == (x & STD_OPCODE_MASK); |
goetz@6458 | 1273 | } |
goetz@6458 | 1274 | static bool is_stdu(int x) { |
goetz@6458 | 1275 | return STDU_OPCODE == (x & STDU_OPCODE_MASK); |
goetz@6458 | 1276 | } |
goetz@6458 | 1277 | static bool is_stdx(int x) { |
goetz@6458 | 1278 | return STDX_OPCODE == (x & STDX_OPCODE_MASK); |
goetz@6458 | 1279 | } |
goetz@6458 | 1280 | static bool is_stdux(int x) { |
goetz@6458 | 1281 | return STDUX_OPCODE == (x & STDUX_OPCODE_MASK); |
goetz@6458 | 1282 | } |
goetz@6458 | 1283 | static bool is_stwx(int x) { |
goetz@6458 | 1284 | return STWX_OPCODE == (x & STWX_OPCODE_MASK); |
goetz@6458 | 1285 | } |
goetz@6458 | 1286 | static bool is_stwux(int x) { |
goetz@6458 | 1287 | return STWUX_OPCODE == (x & STWUX_OPCODE_MASK); |
goetz@6458 | 1288 | } |
goetz@6458 | 1289 | static bool is_stw(int x) { |
goetz@6458 | 1290 | return STW_OPCODE == (x & STW_OPCODE_MASK); |
goetz@6458 | 1291 | } |
goetz@6458 | 1292 | static bool is_stwu(int x) { |
goetz@6458 | 1293 | return STWU_OPCODE == (x & STWU_OPCODE_MASK); |
goetz@6458 | 1294 | } |
goetz@6458 | 1295 | static bool is_ori(int x) { |
goetz@6458 | 1296 | return ORI_OPCODE == (x & ORI_OPCODE_MASK); |
goetz@6458 | 1297 | }; |
goetz@6458 | 1298 | static bool is_oris(int x) { |
goetz@6458 | 1299 | return ORIS_OPCODE == (x & ORIS_OPCODE_MASK); |
goetz@6458 | 1300 | }; |
goetz@6458 | 1301 | static bool is_rldicr(int x) { |
goetz@6458 | 1302 | return (RLDICR_OPCODE == (x & RLDICR_OPCODE_MASK)); |
goetz@6458 | 1303 | }; |
goetz@6458 | 1304 | static bool is_nop(int x) { |
goetz@6458 | 1305 | return x == 0x60000000; |
goetz@6458 | 1306 | } |
goetz@6458 | 1307 | // endgroup opcode for Power6 |
goetz@6458 | 1308 | static bool is_endgroup(int x) { |
goetz@6495 | 1309 | return is_ori(x) && inv_ra_field(x) == 1 && inv_rs_field(x) == 1 && inv_d1_field(x) == 0; |
goetz@6458 | 1310 | } |
goetz@6458 | 1311 | |
goetz@6458 | 1312 | |
goetz@6458 | 1313 | private: |
goetz@6458 | 1314 | // PPC 1, section 3.3.9, Fixed-Point Compare Instructions |
goetz@6458 | 1315 | inline void cmpi( ConditionRegister bf, int l, Register a, int si16); |
goetz@6458 | 1316 | inline void cmp( ConditionRegister bf, int l, Register a, Register b); |
goetz@6458 | 1317 | inline void cmpli(ConditionRegister bf, int l, Register a, int ui16); |
goetz@6458 | 1318 | inline void cmpl( ConditionRegister bf, int l, Register a, Register b); |
goetz@6458 | 1319 | |
goetz@6458 | 1320 | public: |
goetz@6458 | 1321 | // extended mnemonics of Compare Instructions |
goetz@6458 | 1322 | inline void cmpwi( ConditionRegister crx, Register a, int si16); |
goetz@6458 | 1323 | inline void cmpdi( ConditionRegister crx, Register a, int si16); |
goetz@6458 | 1324 | inline void cmpw( ConditionRegister crx, Register a, Register b); |
goetz@6458 | 1325 | inline void cmpd( ConditionRegister crx, Register a, Register b); |
goetz@6458 | 1326 | inline void cmplwi(ConditionRegister crx, Register a, int ui16); |
goetz@6458 | 1327 | inline void cmpldi(ConditionRegister crx, Register a, int ui16); |
goetz@6458 | 1328 | inline void cmplw( ConditionRegister crx, Register a, Register b); |
goetz@6458 | 1329 | inline void cmpld( ConditionRegister crx, Register a, Register b); |
goetz@6458 | 1330 | |
goetz@6458 | 1331 | inline void isel( Register d, Register a, Register b, int bc); |
goetz@6495 | 1332 | // Convenient version which takes: Condition register, Condition code and invert flag. Omit b to keep old value. |
goetz@6495 | 1333 | inline void isel( Register d, ConditionRegister cr, Condition cc, bool inv, Register a, Register b = noreg); |
goetz@6495 | 1334 | // Set d = 0 if (cr.cc) equals 1, otherwise b. |
goetz@6495 | 1335 | inline void isel_0( Register d, ConditionRegister cr, Condition cc, Register b = noreg); |
goetz@6458 | 1336 | |
goetz@6458 | 1337 | // PPC 1, section 3.3.11, Fixed-Point Logical Instructions |
goetz@6495 | 1338 | void andi( Register a, Register s, int ui16); // optimized version |
goetz@6458 | 1339 | inline void andi_( Register a, Register s, int ui16); |
goetz@6458 | 1340 | inline void andis_( Register a, Register s, int ui16); |
goetz@6458 | 1341 | inline void ori( Register a, Register s, int ui16); |
goetz@6458 | 1342 | inline void oris( Register a, Register s, int ui16); |
goetz@6458 | 1343 | inline void xori( Register a, Register s, int ui16); |
goetz@6458 | 1344 | inline void xoris( Register a, Register s, int ui16); |
goetz@6458 | 1345 | inline void andr( Register a, Register s, Register b); // suffixed by 'r' as 'and' is C++ keyword |
goetz@6458 | 1346 | inline void and_( Register a, Register s, Register b); |
goetz@6458 | 1347 | // Turn or0(rx,rx,rx) into a nop and avoid that we accidently emit a |
goetz@6458 | 1348 | // SMT-priority change instruction (see SMT instructions below). |
goetz@6458 | 1349 | inline void or_unchecked(Register a, Register s, Register b); |
goetz@6458 | 1350 | inline void orr( Register a, Register s, Register b); // suffixed by 'r' as 'or' is C++ keyword |
goetz@6458 | 1351 | inline void or_( Register a, Register s, Register b); |
goetz@6458 | 1352 | inline void xorr( Register a, Register s, Register b); // suffixed by 'r' as 'xor' is C++ keyword |
goetz@6458 | 1353 | inline void xor_( Register a, Register s, Register b); |
goetz@6458 | 1354 | inline void nand( Register a, Register s, Register b); |
goetz@6458 | 1355 | inline void nand_( Register a, Register s, Register b); |
goetz@6458 | 1356 | inline void nor( Register a, Register s, Register b); |
goetz@6458 | 1357 | inline void nor_( Register a, Register s, Register b); |
goetz@6458 | 1358 | inline void andc( Register a, Register s, Register b); |
goetz@6458 | 1359 | inline void andc_( Register a, Register s, Register b); |
goetz@6458 | 1360 | inline void orc( Register a, Register s, Register b); |
goetz@6458 | 1361 | inline void orc_( Register a, Register s, Register b); |
goetz@6458 | 1362 | inline void extsb( Register a, Register s); |
goetz@6458 | 1363 | inline void extsh( Register a, Register s); |
goetz@6458 | 1364 | inline void extsw( Register a, Register s); |
goetz@6458 | 1365 | |
goetz@6458 | 1366 | // extended mnemonics |
goetz@6458 | 1367 | inline void nop(); |
goetz@6458 | 1368 | // NOP for FP and BR units (different versions to allow them to be in one group) |
goetz@6458 | 1369 | inline void fpnop0(); |
goetz@6458 | 1370 | inline void fpnop1(); |
goetz@6458 | 1371 | inline void brnop0(); |
goetz@6458 | 1372 | inline void brnop1(); |
goetz@6458 | 1373 | inline void brnop2(); |
goetz@6458 | 1374 | |
goetz@6458 | 1375 | inline void mr( Register d, Register s); |
goetz@6458 | 1376 | inline void ori_opt( Register d, int ui16); |
goetz@6458 | 1377 | inline void oris_opt(Register d, int ui16); |
goetz@6458 | 1378 | |
goetz@6458 | 1379 | // endgroup opcode for Power6 |
goetz@6458 | 1380 | inline void endgroup(); |
goetz@6458 | 1381 | |
goetz@6458 | 1382 | // count instructions |
goetz@6458 | 1383 | inline void cntlzw( Register a, Register s); |
goetz@6458 | 1384 | inline void cntlzw_( Register a, Register s); |
goetz@6458 | 1385 | inline void cntlzd( Register a, Register s); |
goetz@6458 | 1386 | inline void cntlzd_( Register a, Register s); |
goetz@6458 | 1387 | |
goetz@6458 | 1388 | // PPC 1, section 3.3.12, Fixed-Point Rotate and Shift Instructions |
goetz@6458 | 1389 | inline void sld( Register a, Register s, Register b); |
goetz@6458 | 1390 | inline void sld_( Register a, Register s, Register b); |
goetz@6458 | 1391 | inline void slw( Register a, Register s, Register b); |
goetz@6458 | 1392 | inline void slw_( Register a, Register s, Register b); |
goetz@6458 | 1393 | inline void srd( Register a, Register s, Register b); |
goetz@6458 | 1394 | inline void srd_( Register a, Register s, Register b); |
goetz@6458 | 1395 | inline void srw( Register a, Register s, Register b); |
goetz@6458 | 1396 | inline void srw_( Register a, Register s, Register b); |
goetz@6458 | 1397 | inline void srad( Register a, Register s, Register b); |
goetz@6458 | 1398 | inline void srad_( Register a, Register s, Register b); |
goetz@6458 | 1399 | inline void sraw( Register a, Register s, Register b); |
goetz@6458 | 1400 | inline void sraw_( Register a, Register s, Register b); |
goetz@6458 | 1401 | inline void sradi( Register a, Register s, int sh6); |
goetz@6458 | 1402 | inline void sradi_( Register a, Register s, int sh6); |
goetz@6458 | 1403 | inline void srawi( Register a, Register s, int sh5); |
goetz@6458 | 1404 | inline void srawi_( Register a, Register s, int sh5); |
goetz@6458 | 1405 | |
goetz@6458 | 1406 | // extended mnemonics for Shift Instructions |
goetz@6458 | 1407 | inline void sldi( Register a, Register s, int sh6); |
goetz@6458 | 1408 | inline void sldi_( Register a, Register s, int sh6); |
goetz@6458 | 1409 | inline void slwi( Register a, Register s, int sh5); |
goetz@6458 | 1410 | inline void slwi_( Register a, Register s, int sh5); |
goetz@6458 | 1411 | inline void srdi( Register a, Register s, int sh6); |
goetz@6458 | 1412 | inline void srdi_( Register a, Register s, int sh6); |
goetz@6458 | 1413 | inline void srwi( Register a, Register s, int sh5); |
goetz@6458 | 1414 | inline void srwi_( Register a, Register s, int sh5); |
goetz@6458 | 1415 | |
goetz@6458 | 1416 | inline void clrrdi( Register a, Register s, int ui6); |
goetz@6458 | 1417 | inline void clrrdi_( Register a, Register s, int ui6); |
goetz@6458 | 1418 | inline void clrldi( Register a, Register s, int ui6); |
goetz@6458 | 1419 | inline void clrldi_( Register a, Register s, int ui6); |
goetz@6458 | 1420 | inline void clrlsldi(Register a, Register s, int clrl6, int shl6); |
goetz@6458 | 1421 | inline void clrlsldi_(Register a, Register s, int clrl6, int shl6); |
goetz@6458 | 1422 | inline void extrdi( Register a, Register s, int n, int b); |
goetz@6458 | 1423 | // testbit with condition register |
goetz@6458 | 1424 | inline void testbitdi(ConditionRegister cr, Register a, Register s, int ui6); |
goetz@6458 | 1425 | |
goetz@6458 | 1426 | // rotate instructions |
goetz@6458 | 1427 | inline void rotldi( Register a, Register s, int n); |
goetz@6458 | 1428 | inline void rotrdi( Register a, Register s, int n); |
goetz@6458 | 1429 | inline void rotlwi( Register a, Register s, int n); |
goetz@6458 | 1430 | inline void rotrwi( Register a, Register s, int n); |
goetz@6458 | 1431 | |
goetz@6458 | 1432 | // Rotate Instructions |
goetz@6458 | 1433 | inline void rldic( Register a, Register s, int sh6, int mb6); |
goetz@6458 | 1434 | inline void rldic_( Register a, Register s, int sh6, int mb6); |
goetz@6458 | 1435 | inline void rldicr( Register a, Register s, int sh6, int mb6); |
goetz@6458 | 1436 | inline void rldicr_( Register a, Register s, int sh6, int mb6); |
goetz@6458 | 1437 | inline void rldicl( Register a, Register s, int sh6, int mb6); |
goetz@6458 | 1438 | inline void rldicl_( Register a, Register s, int sh6, int mb6); |
goetz@6458 | 1439 | inline void rlwinm( Register a, Register s, int sh5, int mb5, int me5); |
goetz@6458 | 1440 | inline void rlwinm_( Register a, Register s, int sh5, int mb5, int me5); |
goetz@6458 | 1441 | inline void rldimi( Register a, Register s, int sh6, int mb6); |
goetz@6458 | 1442 | inline void rldimi_( Register a, Register s, int sh6, int mb6); |
goetz@6458 | 1443 | inline void rlwimi( Register a, Register s, int sh5, int mb5, int me5); |
goetz@6458 | 1444 | inline void insrdi( Register a, Register s, int n, int b); |
goetz@6458 | 1445 | inline void insrwi( Register a, Register s, int n, int b); |
goetz@6458 | 1446 | |
goetz@6458 | 1447 | // PPC 1, section 3.3.2 Fixed-Point Load Instructions |
goetz@6458 | 1448 | // 4 bytes |
goetz@6458 | 1449 | inline void lwzx( Register d, Register s1, Register s2); |
goetz@6458 | 1450 | inline void lwz( Register d, int si16, Register s1); |
goetz@6458 | 1451 | inline void lwzu( Register d, int si16, Register s1); |
goetz@6458 | 1452 | |
goetz@6458 | 1453 | // 4 bytes |
goetz@6458 | 1454 | inline void lwax( Register d, Register s1, Register s2); |
goetz@6458 | 1455 | inline void lwa( Register d, int si16, Register s1); |
goetz@6458 | 1456 | |
kvn@7132 | 1457 | // 4 bytes reversed |
kvn@7132 | 1458 | inline void lwbrx( Register d, Register s1, Register s2); |
kvn@7132 | 1459 | |
goetz@6458 | 1460 | // 2 bytes |
goetz@6458 | 1461 | inline void lhzx( Register d, Register s1, Register s2); |
goetz@6458 | 1462 | inline void lhz( Register d, int si16, Register s1); |
goetz@6458 | 1463 | inline void lhzu( Register d, int si16, Register s1); |
goetz@6458 | 1464 | |
kvn@7132 | 1465 | // 2 bytes reversed |
kvn@7132 | 1466 | inline void lhbrx( Register d, Register s1, Register s2); |
kvn@7132 | 1467 | |
goetz@6458 | 1468 | // 2 bytes |
goetz@6458 | 1469 | inline void lhax( Register d, Register s1, Register s2); |
goetz@6458 | 1470 | inline void lha( Register d, int si16, Register s1); |
goetz@6458 | 1471 | inline void lhau( Register d, int si16, Register s1); |
goetz@6458 | 1472 | |
goetz@6458 | 1473 | // 1 byte |
goetz@6458 | 1474 | inline void lbzx( Register d, Register s1, Register s2); |
goetz@6458 | 1475 | inline void lbz( Register d, int si16, Register s1); |
goetz@6458 | 1476 | inline void lbzu( Register d, int si16, Register s1); |
goetz@6458 | 1477 | |
goetz@6458 | 1478 | // 8 bytes |
goetz@6458 | 1479 | inline void ldx( Register d, Register s1, Register s2); |
goetz@6458 | 1480 | inline void ld( Register d, int si16, Register s1); |
goetz@6458 | 1481 | inline void ldu( Register d, int si16, Register s1); |
goetz@6458 | 1482 | |
goetz@6458 | 1483 | // PPC 1, section 3.3.3 Fixed-Point Store Instructions |
goetz@6458 | 1484 | inline void stwx( Register d, Register s1, Register s2); |
goetz@6458 | 1485 | inline void stw( Register d, int si16, Register s1); |
goetz@6458 | 1486 | inline void stwu( Register d, int si16, Register s1); |
goetz@6458 | 1487 | |
goetz@6458 | 1488 | inline void sthx( Register d, Register s1, Register s2); |
goetz@6458 | 1489 | inline void sth( Register d, int si16, Register s1); |
goetz@6458 | 1490 | inline void sthu( Register d, int si16, Register s1); |
goetz@6458 | 1491 | |
goetz@6458 | 1492 | inline void stbx( Register d, Register s1, Register s2); |
goetz@6458 | 1493 | inline void stb( Register d, int si16, Register s1); |
goetz@6458 | 1494 | inline void stbu( Register d, int si16, Register s1); |
goetz@6458 | 1495 | |
goetz@6458 | 1496 | inline void stdx( Register d, Register s1, Register s2); |
goetz@6458 | 1497 | inline void std( Register d, int si16, Register s1); |
goetz@6458 | 1498 | inline void stdu( Register d, int si16, Register s1); |
goetz@6458 | 1499 | inline void stdux(Register s, Register a, Register b); |
goetz@6458 | 1500 | |
goetz@6458 | 1501 | // PPC 1, section 3.3.13 Move To/From System Register Instructions |
goetz@6458 | 1502 | inline void mtlr( Register s1); |
goetz@6458 | 1503 | inline void mflr( Register d); |
goetz@6458 | 1504 | inline void mtctr(Register s1); |
goetz@6458 | 1505 | inline void mfctr(Register d); |
goetz@6458 | 1506 | inline void mtcrf(int fxm, Register s); |
goetz@6458 | 1507 | inline void mfcr( Register d); |
goetz@6458 | 1508 | inline void mcrf( ConditionRegister crd, ConditionRegister cra); |
goetz@6458 | 1509 | inline void mtcr( Register s); |
goetz@6458 | 1510 | |
goetz@7222 | 1511 | // Special purpose registers |
goetz@7222 | 1512 | // Exception Register |
goetz@7222 | 1513 | inline void mtxer(Register s1); |
goetz@7222 | 1514 | inline void mfxer(Register d); |
goetz@7222 | 1515 | // Vector Register Save Register |
goetz@7222 | 1516 | inline void mtvrsave(Register s1); |
goetz@7222 | 1517 | inline void mfvrsave(Register d); |
goetz@7222 | 1518 | // Timebase |
goetz@7222 | 1519 | inline void mftb(Register d); |
goetz@7222 | 1520 | // Introduced with Power 8: |
goetz@7222 | 1521 | // Data Stream Control Register |
goetz@7222 | 1522 | inline void mtdscr(Register s1); |
goetz@7222 | 1523 | inline void mfdscr(Register d ); |
goetz@7222 | 1524 | // Transactional Memory Registers |
goetz@7222 | 1525 | inline void mftfhar(Register d); |
goetz@7222 | 1526 | inline void mftfiar(Register d); |
goetz@7222 | 1527 | inline void mftexasr(Register d); |
goetz@7222 | 1528 | inline void mftexasru(Register d); |
goetz@7222 | 1529 | |
goetz@6458 | 1530 | // PPC 1, section 2.4.1 Branch Instructions |
goetz@6458 | 1531 | inline void b( address a, relocInfo::relocType rt = relocInfo::none); |
goetz@6458 | 1532 | inline void b( Label& L); |
goetz@6458 | 1533 | inline void bl( address a, relocInfo::relocType rt = relocInfo::none); |
goetz@6458 | 1534 | inline void bl( Label& L); |
goetz@6458 | 1535 | inline void bc( int boint, int biint, address a, relocInfo::relocType rt = relocInfo::none); |
goetz@6458 | 1536 | inline void bc( int boint, int biint, Label& L); |
goetz@6458 | 1537 | inline void bcl(int boint, int biint, address a, relocInfo::relocType rt = relocInfo::none); |
goetz@6458 | 1538 | inline void bcl(int boint, int biint, Label& L); |
goetz@6458 | 1539 | |
goetz@6458 | 1540 | inline void bclr( int boint, int biint, int bhint, relocInfo::relocType rt = relocInfo::none); |
goetz@6458 | 1541 | inline void bclrl( int boint, int biint, int bhint, relocInfo::relocType rt = relocInfo::none); |
goetz@6458 | 1542 | inline void bcctr( int boint, int biint, int bhint = bhintbhBCCTRisNotReturnButSame, |
goetz@6458 | 1543 | relocInfo::relocType rt = relocInfo::none); |
goetz@6458 | 1544 | inline void bcctrl(int boint, int biint, int bhint = bhintbhBCLRisReturn, |
goetz@6458 | 1545 | relocInfo::relocType rt = relocInfo::none); |
goetz@6458 | 1546 | |
goetz@6458 | 1547 | // helper function for b, bcxx |
goetz@6458 | 1548 | inline bool is_within_range_of_b(address a, address pc); |
goetz@6458 | 1549 | inline bool is_within_range_of_bcxx(address a, address pc); |
goetz@6458 | 1550 | |
goetz@6458 | 1551 | // get the destination of a bxx branch (b, bl, ba, bla) |
goetz@6458 | 1552 | static inline address bxx_destination(address baddr); |
goetz@6458 | 1553 | static inline address bxx_destination(int instr, address pc); |
goetz@6458 | 1554 | static inline intptr_t bxx_destination_offset(int instr, intptr_t bxx_pos); |
goetz@6458 | 1555 | |
goetz@6458 | 1556 | // extended mnemonics for branch instructions |
goetz@6458 | 1557 | inline void blt(ConditionRegister crx, Label& L); |
goetz@6458 | 1558 | inline void bgt(ConditionRegister crx, Label& L); |
goetz@6458 | 1559 | inline void beq(ConditionRegister crx, Label& L); |
goetz@6458 | 1560 | inline void bso(ConditionRegister crx, Label& L); |
goetz@6458 | 1561 | inline void bge(ConditionRegister crx, Label& L); |
goetz@6458 | 1562 | inline void ble(ConditionRegister crx, Label& L); |
goetz@6458 | 1563 | inline void bne(ConditionRegister crx, Label& L); |
goetz@6458 | 1564 | inline void bns(ConditionRegister crx, Label& L); |
goetz@6458 | 1565 | |
goetz@6458 | 1566 | // Branch instructions with static prediction hints. |
goetz@6458 | 1567 | inline void blt_predict_taken( ConditionRegister crx, Label& L); |
goetz@6458 | 1568 | inline void bgt_predict_taken( ConditionRegister crx, Label& L); |
goetz@6458 | 1569 | inline void beq_predict_taken( ConditionRegister crx, Label& L); |
goetz@6458 | 1570 | inline void bso_predict_taken( ConditionRegister crx, Label& L); |
goetz@6458 | 1571 | inline void bge_predict_taken( ConditionRegister crx, Label& L); |
goetz@6458 | 1572 | inline void ble_predict_taken( ConditionRegister crx, Label& L); |
goetz@6458 | 1573 | inline void bne_predict_taken( ConditionRegister crx, Label& L); |
goetz@6458 | 1574 | inline void bns_predict_taken( ConditionRegister crx, Label& L); |
goetz@6458 | 1575 | inline void blt_predict_not_taken(ConditionRegister crx, Label& L); |
goetz@6458 | 1576 | inline void bgt_predict_not_taken(ConditionRegister crx, Label& L); |
goetz@6458 | 1577 | inline void beq_predict_not_taken(ConditionRegister crx, Label& L); |
goetz@6458 | 1578 | inline void bso_predict_not_taken(ConditionRegister crx, Label& L); |
goetz@6458 | 1579 | inline void bge_predict_not_taken(ConditionRegister crx, Label& L); |
goetz@6458 | 1580 | inline void ble_predict_not_taken(ConditionRegister crx, Label& L); |
goetz@6458 | 1581 | inline void bne_predict_not_taken(ConditionRegister crx, Label& L); |
goetz@6458 | 1582 | inline void bns_predict_not_taken(ConditionRegister crx, Label& L); |
goetz@6458 | 1583 | |
goetz@6458 | 1584 | // for use in conjunction with testbitdi: |
goetz@6458 | 1585 | inline void btrue( ConditionRegister crx, Label& L); |
goetz@6458 | 1586 | inline void bfalse(ConditionRegister crx, Label& L); |
goetz@6458 | 1587 | |
goetz@6458 | 1588 | inline void bltl(ConditionRegister crx, Label& L); |
goetz@6458 | 1589 | inline void bgtl(ConditionRegister crx, Label& L); |
goetz@6458 | 1590 | inline void beql(ConditionRegister crx, Label& L); |
goetz@6458 | 1591 | inline void bsol(ConditionRegister crx, Label& L); |
goetz@6458 | 1592 | inline void bgel(ConditionRegister crx, Label& L); |
goetz@6458 | 1593 | inline void blel(ConditionRegister crx, Label& L); |
goetz@6458 | 1594 | inline void bnel(ConditionRegister crx, Label& L); |
goetz@6458 | 1595 | inline void bnsl(ConditionRegister crx, Label& L); |
goetz@6458 | 1596 | |
goetz@6458 | 1597 | // extended mnemonics for Branch Instructions via LR |
goetz@6458 | 1598 | // We use `blr' for returns. |
goetz@6458 | 1599 | inline void blr(relocInfo::relocType rt = relocInfo::none); |
goetz@6458 | 1600 | |
goetz@6458 | 1601 | // extended mnemonics for Branch Instructions with CTR |
goetz@6458 | 1602 | // bdnz means `decrement CTR and jump to L if CTR is not zero' |
goetz@6458 | 1603 | inline void bdnz(Label& L); |
goetz@6458 | 1604 | // Decrement and branch if result is zero. |
goetz@6458 | 1605 | inline void bdz(Label& L); |
goetz@6458 | 1606 | // we use `bctr[l]' for jumps/calls in function descriptor glue |
goetz@6458 | 1607 | // code, e.g. calls to runtime functions |
goetz@6458 | 1608 | inline void bctr( relocInfo::relocType rt = relocInfo::none); |
goetz@6458 | 1609 | inline void bctrl(relocInfo::relocType rt = relocInfo::none); |
goetz@6458 | 1610 | // conditional jumps/branches via CTR |
goetz@6458 | 1611 | inline void beqctr( ConditionRegister crx, relocInfo::relocType rt = relocInfo::none); |
goetz@6458 | 1612 | inline void beqctrl(ConditionRegister crx, relocInfo::relocType rt = relocInfo::none); |
goetz@6458 | 1613 | inline void bnectr( ConditionRegister crx, relocInfo::relocType rt = relocInfo::none); |
goetz@6458 | 1614 | inline void bnectrl(ConditionRegister crx, relocInfo::relocType rt = relocInfo::none); |
goetz@6458 | 1615 | |
goetz@6458 | 1616 | // condition register logic instructions |
goetz@6458 | 1617 | inline void crand( int d, int s1, int s2); |
goetz@6458 | 1618 | inline void crnand(int d, int s1, int s2); |
goetz@6458 | 1619 | inline void cror( int d, int s1, int s2); |
goetz@6458 | 1620 | inline void crxor( int d, int s1, int s2); |
goetz@6458 | 1621 | inline void crnor( int d, int s1, int s2); |
goetz@6458 | 1622 | inline void creqv( int d, int s1, int s2); |
goetz@6458 | 1623 | inline void crandc(int d, int s1, int s2); |
goetz@6458 | 1624 | inline void crorc( int d, int s1, int s2); |
goetz@6458 | 1625 | |
goetz@6458 | 1626 | // icache and dcache related instructions |
goetz@6458 | 1627 | inline void icbi( Register s1, Register s2); |
goetz@6458 | 1628 | //inline void dcba(Register s1, Register s2); // Instruction for embedded processor only. |
goetz@6458 | 1629 | inline void dcbz( Register s1, Register s2); |
goetz@6458 | 1630 | inline void dcbst( Register s1, Register s2); |
goetz@6458 | 1631 | inline void dcbf( Register s1, Register s2); |
goetz@6458 | 1632 | |
goetz@6458 | 1633 | enum ct_cache_specification { |
goetz@6458 | 1634 | ct_primary_cache = 0, |
goetz@6458 | 1635 | ct_secondary_cache = 2 |
goetz@6458 | 1636 | }; |
goetz@6458 | 1637 | // dcache read hint |
goetz@6458 | 1638 | inline void dcbt( Register s1, Register s2); |
goetz@6458 | 1639 | inline void dcbtct( Register s1, Register s2, int ct); |
goetz@6458 | 1640 | inline void dcbtds( Register s1, Register s2, int ds); |
goetz@6458 | 1641 | // dcache write hint |
goetz@6458 | 1642 | inline void dcbtst( Register s1, Register s2); |
goetz@6458 | 1643 | inline void dcbtstct(Register s1, Register s2, int ct); |
goetz@6458 | 1644 | |
goetz@6458 | 1645 | // machine barrier instructions: |
goetz@6458 | 1646 | // |
goetz@6458 | 1647 | // - sync two-way memory barrier, aka fence |
goetz@6458 | 1648 | // - lwsync orders Store|Store, |
goetz@6458 | 1649 | // Load|Store, |
goetz@6458 | 1650 | // Load|Load, |
goetz@6458 | 1651 | // but not Store|Load |
goetz@6458 | 1652 | // - eieio orders memory accesses for device memory (only) |
goetz@6458 | 1653 | // - isync invalidates speculatively executed instructions |
goetz@6458 | 1654 | // From the Power ISA 2.06 documentation: |
goetz@6458 | 1655 | // "[...] an isync instruction prevents the execution of |
goetz@6458 | 1656 | // instructions following the isync until instructions |
goetz@6458 | 1657 | // preceding the isync have completed, [...]" |
goetz@6458 | 1658 | // From IBM's AIX assembler reference: |
goetz@6458 | 1659 | // "The isync [...] instructions causes the processor to |
goetz@6458 | 1660 | // refetch any instructions that might have been fetched |
goetz@6458 | 1661 | // prior to the isync instruction. The instruction isync |
goetz@6458 | 1662 | // causes the processor to wait for all previous instructions |
goetz@6458 | 1663 | // to complete. Then any instructions already fetched are |
goetz@6458 | 1664 | // discarded and instruction processing continues in the |
goetz@6458 | 1665 | // environment established by the previous instructions." |
goetz@6458 | 1666 | // |
goetz@6458 | 1667 | // semantic barrier instructions: |
goetz@6458 | 1668 | // (as defined in orderAccess.hpp) |
goetz@6458 | 1669 | // |
goetz@6458 | 1670 | // - release orders Store|Store, (maps to lwsync) |
goetz@6458 | 1671 | // Load|Store |
goetz@6458 | 1672 | // - acquire orders Load|Store, (maps to lwsync) |
goetz@6458 | 1673 | // Load|Load |
goetz@6458 | 1674 | // - fence orders Store|Store, (maps to sync) |
goetz@6458 | 1675 | // Load|Store, |
goetz@6458 | 1676 | // Load|Load, |
goetz@6458 | 1677 | // Store|Load |
goetz@6458 | 1678 | // |
goetz@6458 | 1679 | private: |
goetz@6458 | 1680 | inline void sync(int l); |
goetz@6458 | 1681 | public: |
goetz@6458 | 1682 | inline void sync(); |
goetz@6458 | 1683 | inline void lwsync(); |
goetz@6458 | 1684 | inline void ptesync(); |
goetz@6458 | 1685 | inline void eieio(); |
goetz@6458 | 1686 | inline void isync(); |
goetz@6495 | 1687 | inline void elemental_membar(int e); // Elemental Memory Barriers (>=Power 8) |
goetz@6458 | 1688 | |
goetz@6458 | 1689 | // atomics |
goetz@6458 | 1690 | inline void lwarx_unchecked(Register d, Register a, Register b, int eh1 = 0); |
goetz@6458 | 1691 | inline void ldarx_unchecked(Register d, Register a, Register b, int eh1 = 0); |
gromero@9662 | 1692 | inline void lqarx_unchecked(Register d, Register a, Register b, int eh1 = 0); |
goetz@6458 | 1693 | inline bool lxarx_hint_exclusive_access(); |
goetz@6458 | 1694 | inline void lwarx( Register d, Register a, Register b, bool hint_exclusive_access = false); |
goetz@6458 | 1695 | inline void ldarx( Register d, Register a, Register b, bool hint_exclusive_access = false); |
gromero@9662 | 1696 | inline void lqarx( Register d, Register a, Register b, bool hint_exclusive_access = false); |
goetz@6458 | 1697 | inline void stwcx_( Register s, Register a, Register b); |
goetz@6458 | 1698 | inline void stdcx_( Register s, Register a, Register b); |
gromero@9662 | 1699 | inline void stqcx_( Register s, Register a, Register b); |
goetz@6458 | 1700 | |
goetz@6458 | 1701 | // Instructions for adjusting thread priority for simultaneous |
goetz@6458 | 1702 | // multithreading (SMT) on Power5. |
goetz@6458 | 1703 | private: |
goetz@6458 | 1704 | inline void smt_prio_very_low(); |
goetz@6458 | 1705 | inline void smt_prio_medium_high(); |
goetz@6458 | 1706 | inline void smt_prio_high(); |
goetz@6458 | 1707 | |
goetz@6458 | 1708 | public: |
goetz@6458 | 1709 | inline void smt_prio_low(); |
goetz@6458 | 1710 | inline void smt_prio_medium_low(); |
goetz@6458 | 1711 | inline void smt_prio_medium(); |
goetz@6458 | 1712 | |
goetz@6458 | 1713 | // trap instructions |
goetz@6458 | 1714 | inline void twi_0(Register a); // for load with acquire semantics use load+twi_0+isync (trap can't occur) |
goetz@6458 | 1715 | // NOT FOR DIRECT USE!! |
goetz@6458 | 1716 | protected: |
goetz@6458 | 1717 | inline void tdi_unchecked(int tobits, Register a, int si16); |
goetz@6458 | 1718 | inline void twi_unchecked(int tobits, Register a, int si16); |
goetz@6458 | 1719 | inline void tdi( int tobits, Register a, int si16); // asserts UseSIGTRAP |
goetz@6458 | 1720 | inline void twi( int tobits, Register a, int si16); // asserts UseSIGTRAP |
goetz@6458 | 1721 | inline void td( int tobits, Register a, Register b); // asserts UseSIGTRAP |
goetz@6458 | 1722 | inline void tw( int tobits, Register a, Register b); // asserts UseSIGTRAP |
goetz@6458 | 1723 | |
goetz@6458 | 1724 | static bool is_tdi(int x, int tobits, int ra, int si16) { |
goetz@6458 | 1725 | return (TDI_OPCODE == (x & TDI_OPCODE_MASK)) |
goetz@6458 | 1726 | && (tobits == inv_to_field(x)) |
goetz@6458 | 1727 | && (ra == -1/*any reg*/ || ra == inv_ra_field(x)) |
goetz@6458 | 1728 | && (si16 == inv_si_field(x)); |
goetz@6458 | 1729 | } |
goetz@6458 | 1730 | |
goetz@6458 | 1731 | static bool is_twi(int x, int tobits, int ra, int si16) { |
goetz@6458 | 1732 | return (TWI_OPCODE == (x & TWI_OPCODE_MASK)) |
goetz@6458 | 1733 | && (tobits == inv_to_field(x)) |
goetz@6458 | 1734 | && (ra == -1/*any reg*/ || ra == inv_ra_field(x)) |
goetz@6458 | 1735 | && (si16 == inv_si_field(x)); |
goetz@6458 | 1736 | } |
goetz@6458 | 1737 | |
goetz@6458 | 1738 | static bool is_twi(int x, int tobits, int ra) { |
goetz@6458 | 1739 | return (TWI_OPCODE == (x & TWI_OPCODE_MASK)) |
goetz@6458 | 1740 | && (tobits == inv_to_field(x)) |
goetz@6458 | 1741 | && (ra == -1/*any reg*/ || ra == inv_ra_field(x)); |
goetz@6458 | 1742 | } |
goetz@6458 | 1743 | |
goetz@6458 | 1744 | static bool is_td(int x, int tobits, int ra, int rb) { |
goetz@6458 | 1745 | return (TD_OPCODE == (x & TD_OPCODE_MASK)) |
goetz@6458 | 1746 | && (tobits == inv_to_field(x)) |
goetz@6458 | 1747 | && (ra == -1/*any reg*/ || ra == inv_ra_field(x)) |
goetz@6458 | 1748 | && (rb == -1/*any reg*/ || rb == inv_rb_field(x)); |
goetz@6458 | 1749 | } |
goetz@6458 | 1750 | |
goetz@6458 | 1751 | static bool is_tw(int x, int tobits, int ra, int rb) { |
goetz@6458 | 1752 | return (TW_OPCODE == (x & TW_OPCODE_MASK)) |
goetz@6458 | 1753 | && (tobits == inv_to_field(x)) |
goetz@6458 | 1754 | && (ra == -1/*any reg*/ || ra == inv_ra_field(x)) |
goetz@6458 | 1755 | && (rb == -1/*any reg*/ || rb == inv_rb_field(x)); |
goetz@6458 | 1756 | } |
goetz@6458 | 1757 | |
goetz@6458 | 1758 | public: |
goetz@6458 | 1759 | // PPC floating point instructions |
goetz@6458 | 1760 | // PPC 1, section 4.6.2 Floating-Point Load Instructions |
goetz@6458 | 1761 | inline void lfs( FloatRegister d, int si16, Register a); |
goetz@6458 | 1762 | inline void lfsu( FloatRegister d, int si16, Register a); |
goetz@6458 | 1763 | inline void lfsx( FloatRegister d, Register a, Register b); |
goetz@6458 | 1764 | inline void lfd( FloatRegister d, int si16, Register a); |
goetz@6458 | 1765 | inline void lfdu( FloatRegister d, int si16, Register a); |
goetz@6458 | 1766 | inline void lfdx( FloatRegister d, Register a, Register b); |
goetz@6458 | 1767 | |
goetz@6458 | 1768 | // PPC 1, section 4.6.3 Floating-Point Store Instructions |
goetz@6458 | 1769 | inline void stfs( FloatRegister s, int si16, Register a); |
goetz@6458 | 1770 | inline void stfsu( FloatRegister s, int si16, Register a); |
goetz@6458 | 1771 | inline void stfsx( FloatRegister s, Register a, Register b); |
goetz@6458 | 1772 | inline void stfd( FloatRegister s, int si16, Register a); |
goetz@6458 | 1773 | inline void stfdu( FloatRegister s, int si16, Register a); |
goetz@6458 | 1774 | inline void stfdx( FloatRegister s, Register a, Register b); |
goetz@6458 | 1775 | |
goetz@6458 | 1776 | // PPC 1, section 4.6.4 Floating-Point Move Instructions |
goetz@6458 | 1777 | inline void fmr( FloatRegister d, FloatRegister b); |
goetz@6458 | 1778 | inline void fmr_( FloatRegister d, FloatRegister b); |
goetz@6458 | 1779 | |
goetz@6458 | 1780 | // inline void mffgpr( FloatRegister d, Register b); |
goetz@6458 | 1781 | // inline void mftgpr( Register d, FloatRegister b); |
goetz@6458 | 1782 | inline void cmpb( Register a, Register s, Register b); |
goetz@6458 | 1783 | inline void popcntb(Register a, Register s); |
goetz@6458 | 1784 | inline void popcntw(Register a, Register s); |
goetz@6458 | 1785 | inline void popcntd(Register a, Register s); |
goetz@6458 | 1786 | |
goetz@6458 | 1787 | inline void fneg( FloatRegister d, FloatRegister b); |
goetz@6458 | 1788 | inline void fneg_( FloatRegister d, FloatRegister b); |
goetz@6458 | 1789 | inline void fabs( FloatRegister d, FloatRegister b); |
goetz@6458 | 1790 | inline void fabs_( FloatRegister d, FloatRegister b); |
goetz@6458 | 1791 | inline void fnabs( FloatRegister d, FloatRegister b); |
goetz@6458 | 1792 | inline void fnabs_(FloatRegister d, FloatRegister b); |
goetz@6458 | 1793 | |
goetz@6458 | 1794 | // PPC 1, section 4.6.5.1 Floating-Point Elementary Arithmetic Instructions |
goetz@6458 | 1795 | inline void fadd( FloatRegister d, FloatRegister a, FloatRegister b); |
goetz@6458 | 1796 | inline void fadd_( FloatRegister d, FloatRegister a, FloatRegister b); |
goetz@6458 | 1797 | inline void fadds( FloatRegister d, FloatRegister a, FloatRegister b); |
goetz@6458 | 1798 | inline void fadds_(FloatRegister d, FloatRegister a, FloatRegister b); |
goetz@6458 | 1799 | inline void fsub( FloatRegister d, FloatRegister a, FloatRegister b); |
goetz@6458 | 1800 | inline void fsub_( FloatRegister d, FloatRegister a, FloatRegister b); |
goetz@6458 | 1801 | inline void fsubs( FloatRegister d, FloatRegister a, FloatRegister b); |
goetz@6458 | 1802 | inline void fsubs_(FloatRegister d, FloatRegister a, FloatRegister b); |
goetz@6458 | 1803 | inline void fmul( FloatRegister d, FloatRegister a, FloatRegister c); |
goetz@6458 | 1804 | inline void fmul_( FloatRegister d, FloatRegister a, FloatRegister c); |
goetz@6458 | 1805 | inline void fmuls( FloatRegister d, FloatRegister a, FloatRegister c); |
goetz@6458 | 1806 | inline void fmuls_(FloatRegister d, FloatRegister a, FloatRegister c); |
goetz@6458 | 1807 | inline void fdiv( FloatRegister d, FloatRegister a, FloatRegister b); |
goetz@6458 | 1808 | inline void fdiv_( FloatRegister d, FloatRegister a, FloatRegister b); |
goetz@6458 | 1809 | inline void fdivs( FloatRegister d, FloatRegister a, FloatRegister b); |
goetz@6458 | 1810 | inline void fdivs_(FloatRegister d, FloatRegister a, FloatRegister b); |
goetz@6458 | 1811 | |
goetz@6458 | 1812 | // PPC 1, section 4.6.6 Floating-Point Rounding and Conversion Instructions |
goetz@6458 | 1813 | inline void frsp( FloatRegister d, FloatRegister b); |
goetz@6458 | 1814 | inline void fctid( FloatRegister d, FloatRegister b); |
goetz@6458 | 1815 | inline void fctidz(FloatRegister d, FloatRegister b); |
goetz@6458 | 1816 | inline void fctiw( FloatRegister d, FloatRegister b); |
goetz@6458 | 1817 | inline void fctiwz(FloatRegister d, FloatRegister b); |
goetz@6458 | 1818 | inline void fcfid( FloatRegister d, FloatRegister b); |
goetz@6458 | 1819 | inline void fcfids(FloatRegister d, FloatRegister b); |
goetz@6458 | 1820 | |
goetz@6458 | 1821 | // PPC 1, section 4.6.7 Floating-Point Compare Instructions |
goetz@6458 | 1822 | inline void fcmpu( ConditionRegister crx, FloatRegister a, FloatRegister b); |
goetz@6458 | 1823 | |
goetz@6458 | 1824 | inline void fsqrt( FloatRegister d, FloatRegister b); |
goetz@6458 | 1825 | inline void fsqrts(FloatRegister d, FloatRegister b); |
goetz@6458 | 1826 | |
goetz@6458 | 1827 | // Vector instructions for >= Power6. |
goetz@6458 | 1828 | inline void lvebx( VectorRegister d, Register s1, Register s2); |
goetz@6458 | 1829 | inline void lvehx( VectorRegister d, Register s1, Register s2); |
goetz@6458 | 1830 | inline void lvewx( VectorRegister d, Register s1, Register s2); |
goetz@6458 | 1831 | inline void lvx( VectorRegister d, Register s1, Register s2); |
goetz@6458 | 1832 | inline void lvxl( VectorRegister d, Register s1, Register s2); |
goetz@6458 | 1833 | inline void stvebx( VectorRegister d, Register s1, Register s2); |
goetz@6458 | 1834 | inline void stvehx( VectorRegister d, Register s1, Register s2); |
goetz@6458 | 1835 | inline void stvewx( VectorRegister d, Register s1, Register s2); |
goetz@6458 | 1836 | inline void stvx( VectorRegister d, Register s1, Register s2); |
goetz@6458 | 1837 | inline void stvxl( VectorRegister d, Register s1, Register s2); |
goetz@6458 | 1838 | inline void lvsl( VectorRegister d, Register s1, Register s2); |
goetz@6458 | 1839 | inline void lvsr( VectorRegister d, Register s1, Register s2); |
goetz@6458 | 1840 | inline void vpkpx( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1841 | inline void vpkshss( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1842 | inline void vpkswss( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1843 | inline void vpkshus( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1844 | inline void vpkswus( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1845 | inline void vpkuhum( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1846 | inline void vpkuwum( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1847 | inline void vpkuhus( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1848 | inline void vpkuwus( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1849 | inline void vupkhpx( VectorRegister d, VectorRegister b); |
goetz@6458 | 1850 | inline void vupkhsb( VectorRegister d, VectorRegister b); |
goetz@6458 | 1851 | inline void vupkhsh( VectorRegister d, VectorRegister b); |
goetz@6458 | 1852 | inline void vupklpx( VectorRegister d, VectorRegister b); |
goetz@6458 | 1853 | inline void vupklsb( VectorRegister d, VectorRegister b); |
goetz@6458 | 1854 | inline void vupklsh( VectorRegister d, VectorRegister b); |
goetz@6458 | 1855 | inline void vmrghb( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1856 | inline void vmrghw( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1857 | inline void vmrghh( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1858 | inline void vmrglb( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1859 | inline void vmrglw( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1860 | inline void vmrglh( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1861 | inline void vsplt( VectorRegister d, int ui4, VectorRegister b); |
goetz@6458 | 1862 | inline void vsplth( VectorRegister d, int ui3, VectorRegister b); |
goetz@6458 | 1863 | inline void vspltw( VectorRegister d, int ui2, VectorRegister b); |
goetz@6458 | 1864 | inline void vspltisb( VectorRegister d, int si5); |
goetz@6458 | 1865 | inline void vspltish( VectorRegister d, int si5); |
goetz@6458 | 1866 | inline void vspltisw( VectorRegister d, int si5); |
goetz@6458 | 1867 | inline void vperm( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); |
goetz@6458 | 1868 | inline void vsel( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); |
goetz@6458 | 1869 | inline void vsl( VectorRegister d, VectorRegister a, VectorRegister b); |
mdoerr@9603 | 1870 | inline void vsldoi( VectorRegister d, VectorRegister a, VectorRegister b, int ui4); |
goetz@6458 | 1871 | inline void vslo( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1872 | inline void vsr( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1873 | inline void vsro( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1874 | inline void vaddcuw( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1875 | inline void vaddshs( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1876 | inline void vaddsbs( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1877 | inline void vaddsws( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1878 | inline void vaddubm( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1879 | inline void vadduwm( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1880 | inline void vadduhm( VectorRegister d, VectorRegister a, VectorRegister b); |
gromero@9687 | 1881 | inline void vaddudm( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1882 | inline void vaddubs( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1883 | inline void vadduws( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1884 | inline void vadduhs( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1885 | inline void vsubcuw( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1886 | inline void vsubshs( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1887 | inline void vsubsbs( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1888 | inline void vsubsws( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1889 | inline void vsububm( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1890 | inline void vsubuwm( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1891 | inline void vsubuhm( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1892 | inline void vsububs( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1893 | inline void vsubuws( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1894 | inline void vsubuhs( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1895 | inline void vmulesb( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1896 | inline void vmuleub( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1897 | inline void vmulesh( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1898 | inline void vmuleuh( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1899 | inline void vmulosb( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1900 | inline void vmuloub( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1901 | inline void vmulosh( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1902 | inline void vmulouh( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1903 | inline void vmhaddshs(VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); |
goetz@6458 | 1904 | inline void vmhraddshs(VectorRegister d,VectorRegister a, VectorRegister b, VectorRegister c); |
goetz@6458 | 1905 | inline void vmladduhm(VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); |
goetz@6458 | 1906 | inline void vmsubuhm( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); |
goetz@6458 | 1907 | inline void vmsummbm( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); |
goetz@6458 | 1908 | inline void vmsumshm( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); |
goetz@6458 | 1909 | inline void vmsumshs( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); |
goetz@6458 | 1910 | inline void vmsumuhm( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); |
goetz@6458 | 1911 | inline void vmsumuhs( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); |
goetz@6458 | 1912 | inline void vsumsws( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1913 | inline void vsum2sws( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1914 | inline void vsum4sbs( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1915 | inline void vsum4ubs( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1916 | inline void vsum4shs( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1917 | inline void vavgsb( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1918 | inline void vavgsw( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1919 | inline void vavgsh( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1920 | inline void vavgub( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1921 | inline void vavguw( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1922 | inline void vavguh( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1923 | inline void vmaxsb( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1924 | inline void vmaxsw( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1925 | inline void vmaxsh( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1926 | inline void vmaxub( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1927 | inline void vmaxuw( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1928 | inline void vmaxuh( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1929 | inline void vminsb( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1930 | inline void vminsw( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1931 | inline void vminsh( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1932 | inline void vminub( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1933 | inline void vminuw( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1934 | inline void vminuh( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1935 | inline void vcmpequb( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1936 | inline void vcmpequh( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1937 | inline void vcmpequw( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1938 | inline void vcmpgtsh( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1939 | inline void vcmpgtsb( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1940 | inline void vcmpgtsw( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1941 | inline void vcmpgtub( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1942 | inline void vcmpgtuh( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1943 | inline void vcmpgtuw( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1944 | inline void vcmpequb_(VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1945 | inline void vcmpequh_(VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1946 | inline void vcmpequw_(VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1947 | inline void vcmpgtsh_(VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1948 | inline void vcmpgtsb_(VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1949 | inline void vcmpgtsw_(VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1950 | inline void vcmpgtub_(VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1951 | inline void vcmpgtuh_(VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1952 | inline void vcmpgtuw_(VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1953 | inline void vand( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1954 | inline void vandc( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1955 | inline void vnor( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1956 | inline void vor( VectorRegister d, VectorRegister a, VectorRegister b); |
gromero@9687 | 1957 | inline void vmr( VectorRegister d, VectorRegister a); |
goetz@6458 | 1958 | inline void vxor( VectorRegister d, VectorRegister a, VectorRegister b); |
simonis@8608 | 1959 | inline void vrld( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1960 | inline void vrlb( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1961 | inline void vrlw( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1962 | inline void vrlh( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1963 | inline void vslb( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1964 | inline void vskw( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1965 | inline void vslh( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1966 | inline void vsrb( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1967 | inline void vsrw( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1968 | inline void vsrh( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1969 | inline void vsrab( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1970 | inline void vsraw( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1971 | inline void vsrah( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@6458 | 1972 | // Vector Floating-Point not implemented yet |
goetz@6458 | 1973 | inline void mtvscr( VectorRegister b); |
goetz@6458 | 1974 | inline void mfvscr( VectorRegister d); |
goetz@6458 | 1975 | |
mdoerr@9497 | 1976 | // Vector-Scalar (VSX) instructions. |
gromero@9684 | 1977 | inline void lxvd2x( VectorSRegister d, Register a); |
gromero@9662 | 1978 | inline void lxvd2x( VectorSRegister d, Register a, Register b); |
gromero@9684 | 1979 | inline void stxvd2x( VectorSRegister d, Register a); |
gromero@9662 | 1980 | inline void stxvd2x( VectorSRegister d, Register a, Register b); |
gromero@9687 | 1981 | inline void mtvrwz( VectorRegister d, Register a); |
gromero@9687 | 1982 | inline void mfvrwz( Register a, VectorRegister d); |
mdoerr@9497 | 1983 | inline void mtvrd( VectorRegister d, Register a); |
mdoerr@9497 | 1984 | inline void mfvrd( Register a, VectorRegister d); |
gromero@9687 | 1985 | inline void xxpermdi( VectorSRegister d, VectorSRegister a, VectorSRegister b, int dm); |
gromero@9687 | 1986 | inline void xxmrghw( VectorSRegister d, VectorSRegister a, VectorSRegister b); |
gromero@9687 | 1987 | inline void xxmrglw( VectorSRegister d, VectorSRegister a, VectorSRegister b); |
gromero@9687 | 1988 | |
gromero@9687 | 1989 | // VSX Extended Mnemonics |
gromero@9687 | 1990 | inline void xxspltd( VectorSRegister d, VectorSRegister a, int x); |
gromero@9687 | 1991 | inline void xxmrghd( VectorSRegister d, VectorSRegister a, VectorSRegister b); |
gromero@9687 | 1992 | inline void xxmrgld( VectorSRegister d, VectorSRegister a, VectorSRegister b); |
gromero@9687 | 1993 | inline void xxswapd( VectorSRegister d, VectorSRegister a); |
mdoerr@9497 | 1994 | |
goetz@7222 | 1995 | // AES (introduced with Power 8) |
goetz@7222 | 1996 | inline void vcipher( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@7222 | 1997 | inline void vcipherlast( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@7222 | 1998 | inline void vncipher( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@7222 | 1999 | inline void vncipherlast(VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@7222 | 2000 | inline void vsbox( VectorRegister d, VectorRegister a); |
goetz@7222 | 2001 | |
goetz@7222 | 2002 | // SHA (introduced with Power 8) |
ogatak@9713 | 2003 | inline void vshasigmad(VectorRegister d, VectorRegister a, bool st, int six); |
ogatak@9713 | 2004 | inline void vshasigmaw(VectorRegister d, VectorRegister a, bool st, int six); |
goetz@7222 | 2005 | |
goetz@7222 | 2006 | // Vector Binary Polynomial Multiplication (introduced with Power 8) |
goetz@7222 | 2007 | inline void vpmsumb( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@7222 | 2008 | inline void vpmsumd( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@7222 | 2009 | inline void vpmsumh( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@7222 | 2010 | inline void vpmsumw( VectorRegister d, VectorRegister a, VectorRegister b); |
goetz@7222 | 2011 | |
goetz@7222 | 2012 | // Vector Permute and Xor (introduced with Power 8) |
goetz@7222 | 2013 | inline void vpermxor( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); |
goetz@7222 | 2014 | |
goetz@7222 | 2015 | // Transactional Memory instructions (introduced with Power 8) |
goetz@7222 | 2016 | inline void tbegin_(); // R=0 |
goetz@7222 | 2017 | inline void tbeginrot_(); // R=1 Rollback-Only Transaction |
goetz@7222 | 2018 | inline void tend_(); // A=0 |
goetz@7222 | 2019 | inline void tendall_(); // A=1 |
goetz@7222 | 2020 | inline void tabort_(Register a); |
goetz@7222 | 2021 | inline void tabortwc_(int t, Register a, Register b); |
goetz@7222 | 2022 | inline void tabortwci_(int t, Register a, int si); |
goetz@7222 | 2023 | inline void tabortdc_(int t, Register a, Register b); |
goetz@7222 | 2024 | inline void tabortdci_(int t, Register a, int si); |
goetz@7222 | 2025 | inline void tsuspend_(); // tsr with L=0 |
goetz@7222 | 2026 | inline void tresume_(); // tsr with L=1 |
goetz@7222 | 2027 | inline void tcheck(int f); |
goetz@7222 | 2028 | |
goetz@6458 | 2029 | // The following encoders use r0 as second operand. These instructions |
goetz@6458 | 2030 | // read r0 as '0'. |
goetz@6458 | 2031 | inline void lwzx( Register d, Register s2); |
goetz@6458 | 2032 | inline void lwz( Register d, int si16); |
goetz@6458 | 2033 | inline void lwax( Register d, Register s2); |
goetz@6458 | 2034 | inline void lwa( Register d, int si16); |
kvn@7132 | 2035 | inline void lwbrx(Register d, Register s2); |
goetz@6458 | 2036 | inline void lhzx( Register d, Register s2); |
goetz@6458 | 2037 | inline void lhz( Register d, int si16); |
goetz@6458 | 2038 | inline void lhax( Register d, Register s2); |
goetz@6458 | 2039 | inline void lha( Register d, int si16); |
kvn@7132 | 2040 | inline void lhbrx(Register d, Register s2); |
goetz@6458 | 2041 | inline void lbzx( Register d, Register s2); |
goetz@6458 | 2042 | inline void lbz( Register d, int si16); |
goetz@6458 | 2043 | inline void ldx( Register d, Register s2); |
goetz@6458 | 2044 | inline void ld( Register d, int si16); |
goetz@6458 | 2045 | inline void stwx( Register d, Register s2); |
goetz@6458 | 2046 | inline void stw( Register d, int si16); |
goetz@6458 | 2047 | inline void sthx( Register d, Register s2); |
goetz@6458 | 2048 | inline void sth( Register d, int si16); |
goetz@6458 | 2049 | inline void stbx( Register d, Register s2); |
goetz@6458 | 2050 | inline void stb( Register d, int si16); |
goetz@6458 | 2051 | inline void stdx( Register d, Register s2); |
goetz@6458 | 2052 | inline void std( Register d, int si16); |
goetz@6458 | 2053 | |
goetz@6458 | 2054 | // PPC 2, section 3.2.1 Instruction Cache Instructions |
goetz@6458 | 2055 | inline void icbi( Register s2); |
goetz@6458 | 2056 | // PPC 2, section 3.2.2 Data Cache Instructions |
goetz@6458 | 2057 | //inlinevoid dcba( Register s2); // Instruction for embedded processor only. |
goetz@6458 | 2058 | inline void dcbz( Register s2); |
goetz@6458 | 2059 | inline void dcbst( Register s2); |
goetz@6458 | 2060 | inline void dcbf( Register s2); |
goetz@6458 | 2061 | // dcache read hint |
goetz@6458 | 2062 | inline void dcbt( Register s2); |
goetz@6458 | 2063 | inline void dcbtct( Register s2, int ct); |
goetz@6458 | 2064 | inline void dcbtds( Register s2, int ds); |
goetz@6458 | 2065 | // dcache write hint |
goetz@6458 | 2066 | inline void dcbtst( Register s2); |
goetz@6458 | 2067 | inline void dcbtstct(Register s2, int ct); |
goetz@6458 | 2068 | |
goetz@6458 | 2069 | // Atomics: use ra0mem to disallow R0 as base. |
goetz@6458 | 2070 | inline void lwarx_unchecked(Register d, Register b, int eh1); |
goetz@6458 | 2071 | inline void ldarx_unchecked(Register d, Register b, int eh1); |
gromero@9662 | 2072 | inline void lqarx_unchecked(Register d, Register b, int eh1); |
goetz@6458 | 2073 | inline void lwarx( Register d, Register b, bool hint_exclusive_access); |
goetz@6458 | 2074 | inline void ldarx( Register d, Register b, bool hint_exclusive_access); |
gromero@9662 | 2075 | inline void lqarx( Register d, Register b, bool hint_exclusive_access); |
goetz@6458 | 2076 | inline void stwcx_(Register s, Register b); |
goetz@6458 | 2077 | inline void stdcx_(Register s, Register b); |
gromero@9662 | 2078 | inline void stqcx_(Register s, Register b); |
goetz@6458 | 2079 | inline void lfs( FloatRegister d, int si16); |
goetz@6458 | 2080 | inline void lfsx( FloatRegister d, Register b); |
goetz@6458 | 2081 | inline void lfd( FloatRegister d, int si16); |
goetz@6458 | 2082 | inline void lfdx( FloatRegister d, Register b); |
goetz@6458 | 2083 | inline void stfs( FloatRegister s, int si16); |
goetz@6458 | 2084 | inline void stfsx( FloatRegister s, Register b); |
goetz@6458 | 2085 | inline void stfd( FloatRegister s, int si16); |
goetz@6458 | 2086 | inline void stfdx( FloatRegister s, Register b); |
goetz@6458 | 2087 | inline void lvebx( VectorRegister d, Register s2); |
goetz@6458 | 2088 | inline void lvehx( VectorRegister d, Register s2); |
goetz@6458 | 2089 | inline void lvewx( VectorRegister d, Register s2); |
goetz@6458 | 2090 | inline void lvx( VectorRegister d, Register s2); |
goetz@6458 | 2091 | inline void lvxl( VectorRegister d, Register s2); |
goetz@6458 | 2092 | inline void stvebx(VectorRegister d, Register s2); |
goetz@6458 | 2093 | inline void stvehx(VectorRegister d, Register s2); |
goetz@6458 | 2094 | inline void stvewx(VectorRegister d, Register s2); |
goetz@6458 | 2095 | inline void stvx( VectorRegister d, Register s2); |
goetz@6458 | 2096 | inline void stvxl( VectorRegister d, Register s2); |
goetz@6458 | 2097 | inline void lvsl( VectorRegister d, Register s2); |
goetz@6458 | 2098 | inline void lvsr( VectorRegister d, Register s2); |
goetz@6458 | 2099 | |
ogatak@9713 | 2100 | // Endianess specific concatenation of 2 loaded vectors. |
ogatak@9713 | 2101 | inline void load_perm(VectorRegister perm, Register addr); |
ogatak@9713 | 2102 | inline void vec_perm(VectorRegister first_dest, VectorRegister second, VectorRegister perm); |
ogatak@9713 | 2103 | |
goetz@6458 | 2104 | // RegisterOrConstant versions. |
goetz@6458 | 2105 | // These emitters choose between the versions using two registers and |
goetz@6458 | 2106 | // those with register and immediate, depending on the content of roc. |
goetz@6458 | 2107 | // If the constant is not encodable as immediate, instructions to |
goetz@6458 | 2108 | // load the constant are emitted beforehand. Store instructions need a |
goetz@6458 | 2109 | // tmp reg if the constant is not encodable as immediate. |
goetz@6458 | 2110 | // Size unpredictable. |
goetz@6458 | 2111 | void ld( Register d, RegisterOrConstant roc, Register s1 = noreg); |
goetz@6458 | 2112 | void lwa( Register d, RegisterOrConstant roc, Register s1 = noreg); |
goetz@6458 | 2113 | void lwz( Register d, RegisterOrConstant roc, Register s1 = noreg); |
goetz@6458 | 2114 | void lha( Register d, RegisterOrConstant roc, Register s1 = noreg); |
goetz@6458 | 2115 | void lhz( Register d, RegisterOrConstant roc, Register s1 = noreg); |
goetz@6458 | 2116 | void lbz( Register d, RegisterOrConstant roc, Register s1 = noreg); |
goetz@6458 | 2117 | void std( Register d, RegisterOrConstant roc, Register s1 = noreg, Register tmp = noreg); |
goetz@6458 | 2118 | void stw( Register d, RegisterOrConstant roc, Register s1 = noreg, Register tmp = noreg); |
goetz@6458 | 2119 | void sth( Register d, RegisterOrConstant roc, Register s1 = noreg, Register tmp = noreg); |
goetz@6458 | 2120 | void stb( Register d, RegisterOrConstant roc, Register s1 = noreg, Register tmp = noreg); |
goetz@6458 | 2121 | void add( Register d, RegisterOrConstant roc, Register s1); |
goetz@6458 | 2122 | void subf(Register d, RegisterOrConstant roc, Register s1); |
goetz@6458 | 2123 | void cmpd(ConditionRegister d, RegisterOrConstant roc, Register s1); |
goetz@6458 | 2124 | |
goetz@6458 | 2125 | |
goetz@6458 | 2126 | // Emit several instructions to load a 64 bit constant. This issues a fixed |
goetz@6458 | 2127 | // instruction pattern so that the constant can be patched later on. |
goetz@6458 | 2128 | enum { |
goetz@6458 | 2129 | load_const_size = 5 * BytesPerInstWord |
goetz@6458 | 2130 | }; |
goetz@6458 | 2131 | void load_const(Register d, long a, Register tmp = noreg); |
goetz@6458 | 2132 | inline void load_const(Register d, void* a, Register tmp = noreg); |
goetz@6458 | 2133 | inline void load_const(Register d, Label& L, Register tmp = noreg); |
goetz@6458 | 2134 | inline void load_const(Register d, AddressLiteral& a, Register tmp = noreg); |
goetz@6458 | 2135 | |
goetz@6458 | 2136 | // Load a 64 bit constant, optimized, not identifyable. |
goetz@6495 | 2137 | // Tmp can be used to increase ILP. Set return_simm16_rest = true to get a |
goetz@6458 | 2138 | // 16 bit immediate offset. This is useful if the offset can be encoded in |
goetz@6458 | 2139 | // a succeeding instruction. |
goetz@6458 | 2140 | int load_const_optimized(Register d, long a, Register tmp = noreg, bool return_simm16_rest = false); |
goetz@6458 | 2141 | inline int load_const_optimized(Register d, void* a, Register tmp = noreg, bool return_simm16_rest = false) { |
goetz@6458 | 2142 | return load_const_optimized(d, (long)(unsigned long)a, tmp, return_simm16_rest); |
goetz@6458 | 2143 | } |
goetz@6458 | 2144 | |
goetz@6458 | 2145 | // Creation |
goetz@6458 | 2146 | Assembler(CodeBuffer* code) : AbstractAssembler(code) { |
goetz@6458 | 2147 | #ifdef CHECK_DELAY |
goetz@6458 | 2148 | delay_state = no_delay; |
goetz@6458 | 2149 | #endif |
goetz@6458 | 2150 | } |
goetz@6458 | 2151 | |
goetz@6458 | 2152 | // Testing |
goetz@6458 | 2153 | #ifndef PRODUCT |
goetz@6458 | 2154 | void test_asm(); |
goetz@6458 | 2155 | #endif |
goetz@6458 | 2156 | }; |
goetz@6458 | 2157 | |
goetz@6458 | 2158 | |
goetz@6458 | 2159 | #endif // CPU_PPC_VM_ASSEMBLER_PPC_HPP |