blob: 798056fc06c9816666c28e983d7852593d7996ef [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Intel, Konstantin M. Anisimov, Igor V. Chebykin
*
*/
#ifndef IPFENCODER_H_
#define IPFENCODER_H_
#include <vector>
#include <bitset>
#include "Type.h"
#include "IpfType.h"
using namespace std;
namespace Jitrino {
namespace IPF {
#define IPF_BUNDLE_SIZE 16 // 16 bytes
//============================================================================//
// This file is based on following docs:
// Intel Itanium Architecture
// Software Developers Manual
// Volume 1: Application Architecture
// Volume 2: System Architecture
// Volume 3: Instruction Set Reference
// Revision 2.1
// October 2002
//============================================================================//
// Type of instruction, Description Execution Unit Type
// IT_I...IT_X are used in bundle mask and occupies 1 byte
enum InstructionType {
IT_I = 0x01, // Non-ALU integer, I-unit slot type
IT_M = 0x02, // Memory, M-unit slot type
IT_A = IT_I | IT_M, // Integer ALU, I/M-unit slot type
IT_F = 0x04, // Floating-point, F-unit slot type
IT_B = 0x08, // Branch, B-unit slot type
IT_L = 0x10, // Extended, occupies 2 slots: 2nd ant 3d
// L+X Major Opcodes 0 - 7 execute on an I-unit.
// L+X Major Opcodes 8 - F execute on a B-unit.
IT_X = 0x20, // Continue of IT_L
IT_ANY = 0xFF, // ANY type above
// pseudo-op
IT_PSEUDO_OP = 0x100,
IT_IGNORE_OP = 0x200, // the inst is ignored in all passes (stopping, bundling, etc.)
// pseudo-op special: explicit set of unit, something else for chk.s
IT_EXPLICIT_IMBFX = 0x1000, // explicitly set compliter (I,M,B,F,X) due to slot type
IT_EXPLICIT_IM = 0x2000, // explicitly set compliter (I,M) due to slot type
// positon in instruction group
IT_GF = 0x10000, // first in group
IT_GL = 0x20000 // last in group
};
// List of instructions
// - prefixed with INST_
// - dots in names are replaced by underscores
// - there is a difference from "Volume 3: Instruction Set Reference":
// few instructions have variable operands count, but we havn't
// so there are additional instructions for those cases
enum InstCode {
INST_INVALID = -1,
INST_FIRST = 0, // MUST BE 0
INST_ADD = INST_FIRST,
INST_ADDS, // imm-14
INST_ADDL, // imm-22
INST_ADDP4,
INST_ALLOC,
INST_AND,
INST_ANDCM,
INST_BR_FIRST, // start of continuous group of branch instructions
INST_BR=INST_BR_FIRST,
INST_BRL,
INST_BRP, // ip_relative_form, indirect_form
INST_BRP_RET, // return_form, indirect_form
INST_BR_LAST=INST_BRP_RET, // end of continuous group of branch instructions
INST_BREAK,
INST_BSW_0,
INST_BSW_1,
INST_CHK_S,
INST_CHK_S_I,
INST_CHK_S_M,
INST_CHK_A,
INST_CLRRRB,
INST_CLRRRB_PR,
INST_CMP,
INST_CMP4,
INST_CMPXCHG,
INST_CMP8XCHG16,
INST_COVER,
INST_CZX1_L, // one_byte_form, left_form
INST_CZX1_R, // one_byte_form, right_form
INST_CZX2_L, // two_byte_form, left_form
INST_CZX2_R, // two_byte_form, right_form
INST_DEP,
INST_DEP_Z,
INST_EPC,
INST_EXTR,
INST_EXTR_U,
INST_FABS,
INST_FADD,
INST_FAMAX,
INST_FAMIN,
INST_FAND,
INST_FANDCM,
INST_FC, // invalidate_line_form
INST_FC_I, // instruction_cache_coherent_form
INST_FCHKF,
INST_FCLASS,
INST_FCLRF,
INST_FCMP,
INST_FCVT_FX, // signed_form
INST_FCVT_FX_TRUNC, // signed_form, trunc_form
INST_FCVT_FXU, // unsigned_form
INST_FCVT_FXU_TRUNC, // unsigned_form, trunc_form
INST_FCVT_XF,
INST_FCVT_XUF,
INST_FETCHADD4, // four_byte_form
INST_FETCHADD8, // eight_byte_form
INST_FLUSHRS,
INST_FMA,
INST_FMAX,
INST_FMERGE_NS, // Floating-point Merge Negative Sign
INST_FMERGE_S, // Floating-point Merge Sign Operation
INST_FMERGE_SE, // Floating-point Merge Sign and Exponent
INST_FMIN,
INST_FMIX_L, // Floating-point Mix Left
INST_FMIX_R, // Floating-point Mix Right
INST_FMIX_LR, // Floating-point Mix Left-Right
INST_FMPY,
INST_FMS,
INST_FNEG,
INST_FNEGABS,
INST_FNMA,
INST_FNMPY,
INST_FNORM,
INST_FOR,
INST_FPABS,
INST_FPACK,
INST_FPAMAX,
INST_FPAMIN,
INST_FPCMP,
INST_FPCVT_FX,
INST_FPCVT_FX_TRUNC,
INST_FPCVT_FXU,
INST_FPCVT_FXU_TRUNC,
INST_FPMA,
INST_FPMAX,
INST_FPMERGE_NS, // Floating-point Parallel Merge Negative Sign
INST_FPMERGE_S, // Floating-point Parallel Merge Sign
INST_FPMERGE_SE, // Floating-point Parallel Merge Sign and Exponent Operation
INST_FPMIN,
INST_FPMPY,
INST_FPMS,
INST_FPNEG,
INST_FPNEGABS,
INST_FPNMA,
INST_FPNMPY,
INST_FPRCPA,
INST_FPRSQRTA,
INST_FRCPA,
INST_FRSQRTA,
INST_FSELECT,
INST_FSETC,
INST_FSUB,
INST_FSWAP, // Floating-point Swap
INST_FSWAP_NL, // Floating-point Swap Negate Left
INST_FSWAP_NR, // Floating-point Swap Negate Right
INST_FSXT_L, // Floating-point Sign Extend Left
INST_FSXT_R, // Floating-point Sign Extend Right
INST_FWB,
INST_FXOR,
INST_GETF_S,
INST_GETF_D,
INST_GETF_EXP,
INST_GETF_SIG,
INST_HINT,
INST_INVALA, // All entries in ALAT are invalidated
INST_INVALA_E, // One entry in ALAT is invalidated
INST_ITC_I, // itc.i instruction_form
INST_ITC_D, // itc.d data_form
INST_ITR_I, // instruction_form
INST_ITR_D, // data_form
INST_LD_FIRST,
INST_LD = INST_LD_FIRST,
INST_LD16,
INST_LD16_ACQ,
INST_LD8_FILL,
INST_LDF, // 4,8,10 bytes Single precision
INST_LDF8, // integer form
INST_LDF_FILL, // fill form
INST_LDFPS,
INST_LDFPD,
INST_LDFP8,
INST_LD_LAST = INST_LDFP8,
INST_LFETCH,
INST_LFETCH_EXCL,
INST_LOADRS,
INST_MF,
INST_MF_A,
INST_MIX1_L, // one_byte_form, left_form
INST_MIX2_L, // two_byte_form, left_form
INST_MIX4_L, // four_byte_form, left_form
INST_MIX1_R, // one_byte_form, right_form
INST_MIX2_R, // two_byte_form, right_form
INST_MIX4_R, // four_byte_form, right_form
INST_MOV, // there are many incarnations of mov,
// so parse it like pseudo-op
INST_MOV_I,
INST_MOV_M,
INST_MOV_RET,
INST_MOVL,
INST_MUX1,
INST_MUX2,
INST_NOP,
INST_OR,
INST_PACK2_SSS,
INST_PACK2_USS,
INST_PACK4_SSS,
INST_PADD1,
INST_PADD1_SSS,
INST_PADD1_UUS,
INST_PADD1_UUU,
INST_PADD2,
INST_PADD2_SSS,
INST_PADD2_UUS,
INST_PADD2_UUU,
INST_PADD4,
INST_PAVG1,
INST_PAVG1_RAZ,
INST_PAVG2,
INST_PAVG2_RAZ,
INST_PAVGSUB1,
INST_PAVGSUB2,
INST_PCMP1,
INST_PCMP2,
INST_PCMP4,
INST_PMAX1_U,
INST_PMAX2,
INST_PMIN1_U,
INST_PMIN2,
INST_PMPY2_R,
INST_PMPY2_L,
INST_PMPYSHR2,
INST_PMPYSHR2_U,
INST_POPCNT,
INST_PROBE_R,
INST_PROBE_W,
INST_PROBE_R_FAULT,
INST_PROBE_W_FAULT,
INST_PROBE_RW_FAULT,
INST_PSAD1,
INST_PSHL2,
INST_PSHL4,
INST_PSHLADD2,
INST_PSHR2,
INST_PSHR2_U,
INST_PSHR4,
INST_PSHR4_U,
INST_PSHRADD2,
INST_PSUB1,
INST_PSUB1_SSS,
INST_PSUB1_UUS,
INST_PSUB1_UUU,
INST_PSUB2,
INST_PSUB2_SSS,
INST_PSUB2_UUS,
INST_PSUB2_UUU,
INST_PSUB4,
INST_PTC_E,
INST_PTC_G,
INST_PTC_GA,
INST_PTC_L,
INST_PTR_D,
INST_PTR_I,
INST_RFI,
INST_RSM,
INST_RUM,
INST_SETF_S,
INST_SETF_D,
INST_SETF_EXP,
INST_SETF_SIG,
INST_SHL,
INST_SHLADD,
INST_SHLADDP4,
INST_SHR,
INST_SHR_U,
INST_SHRP,
INST_SRLZ_I,
INST_SRLZ_D,
INST_SSM,
INST_ST_FIRST, // start of continuous group of store instructions
INST_ST = INST_ST_FIRST,
INST_ST16,
INST_ST8_SPILL,
INST_STF,
INST_STF8,
INST_STF_SPILL,
INST_ST_LAST = INST_STF_SPILL, // end of continuous group of store instructions
INST_SUB,
INST_SUM,
INST_SXT,
INST_SYNC_I,
INST_TAK,
INST_TBIT,
INST_THASH,
INST_TNAT,
INST_TPA,
INST_TTAG,
INST_UNPACK1_H,
INST_UNPACK2_H,
INST_UNPACK4_H,
INST_UNPACK1_L,
INST_UNPACK2_L,
INST_UNPACK4_L,
INST_XCHG,
INST_XMA_L,
INST_XMA_LU,
INST_XMA_H,
INST_XMA_HU,
INST_XMPY_L,
INST_XMPY_LU,
INST_XMPY_H,
INST_XMPY_HU,
INST_XOR,
INST_ZXT,
INST_LAST = INST_ZXT,
// following are pseudo-op
INST_SWITCH, // switch, ignored
INST_BREAKPOINT,
INST_USE,
INST_DEF,
INST_BRL13,
INST_BR13
};
enum Completer {
CMPLT_INVALID = -1,
CMPLT_FIRST = 0, // MUST BE 0
//----------------------------
// Branch_Types (br)
CMPLT_BTYPE_COND = CMPLT_FIRST, // br, brl
CMPLT_BTYPE_IA,
CMPLT_BTYPE_WEXIT,
CMPLT_BTYPE_WTOP,
CMPLT_BTYPE_RET,
CMPLT_BTYPE_CLOOP,
CMPLT_BTYPE_CEXIT,
CMPLT_BTYPE_CTOP,
CMPLT_BTYPE_CALL, // br, brl
//----------------------------
// Branch_Whether_Hint, NOT for all branch instructions!
CMPLT_WH_IGNORE, // Ignore all hints.
CMPLT_WH_SPTK, // Presaged branch should be predicted Static Taken
CMPLT_WH_SPNT,
CMPLT_WH_LOOP, // Presaged branch will be br.cloop, br.ctop, or br.wtop
CMPLT_WH_EXIT, // Presaged branch will be br.cexit or br.wexit
CMPLT_WH_DPTK, // Presaged branch should be predicted Dynamically
CMPLT_WH_DPNT,
//----------------------------
// Branch_Sequential_Prefetch_Hint (br, brl)
CMPLT_PH_FEW,
CMPLT_PH_MANY,
//----------------------------
// Branch_Cache_Deallocation_Hint (br, brl)
CMPLT_DH_NOT_CLR,
CMPLT_DH_CLR,
//----------------------------
// Branch_Predict_Importance_Hint (brp)
CMPLT_IH_NOT_IMP,
CMPLT_IH_IMP,
//----------------------------
// Speculation_Check_ALAT_Clear_Completer (chk.s, chk.a)
CMPLT_CHK_A_CLR, // Invalidate matching ALAT entry
CMPLT_CHK_A_NC, // Dont invalidate
//----------------------------
// Comparison_Types ( both int and float! )
CMPLT_CMP_CTYPE_NONE,
CMPLT_CMP_CTYPE_NORMAL = CMPLT_CMP_CTYPE_NONE,
CMPLT_CMP_CTYPE_UNC,
CMPLT_CMP_CTYPE_OR,
CMPLT_CMP_CTYPE_AND,
CMPLT_CMP_CTYPE_OR_ANDCM,
//----------------------------
// Comparison_Relations
CMPLT_CMP_CREL_EQ,
CMPLT_CMP_CREL_NE,
CMPLT_CMP_CREL_LT,
CMPLT_CMP_CREL_LE,
CMPLT_CMP_CREL_GT,
CMPLT_CMP_CREL_GE,
CMPLT_CMP_CREL_LTU, // unsigned
CMPLT_CMP_CREL_LEU, // unsigned
CMPLT_CMP_CREL_GTU, // unsigned
CMPLT_CMP_CREL_GEU, // unsigned
// Floating_Point_Comparison_Relations
CMPLT_FCMP_FREL_UNORD, // unordered f2 ? f3
CMPLT_FCMP_FREL_NLT, // not less than !(f2 < f3)
CMPLT_FCMP_FREL_NLE, // not less than or equal !(f2 <= f3)
CMPLT_FCMP_FREL_NGT, // not greater than !(f2 > f3)
CMPLT_FCMP_FREL_NGE, // not greater than or equal !(f2 >= f3)
CMPLT_FCMP_FREL_ORD, // ordered !(f2 ? f3)
//----------------------------
// Semaphore_Types
CMPLT_SEM_ACQ, // Acquire The memory read/write is made
// visible prior to all subsequent data
// memory accesses.
CMPLT_SEM_REL, // Release The memory read/write is made
// visible after all previous data memory
// accesses.
//----------------------------
// Floating_Point_pc_Mnemonic_Values
CMPLT_PC_SINGLE,
CMPLT_PC_DOUBLE,
CMPLT_PC_DYNAMIC,
//----------------------------
// Floating_Point_sf_Mnemonic_Values
CMPLT_SF0,
CMPLT_SF1,
CMPLT_SF2,
CMPLT_SF3,
//----------------------------
// Floating_Point_Class_Relations
CMPLT_FCREL_M, // FR f2 agrees with the pattern specified
// by fclass9 (is a member)
CMPLT_FCREL_NM, // FR f2 does not agree with the pattern
// specified by fclass9 (is not a member)
//----------------------------
// Floating_Point_Classes
CMPLT_FCLASS_NAT, // NaTVal
CMPLT_FCLASS_QNAN, // Quiet NaN
CMPLT_FCLASS_SNAN, // Signaling NaN
CMPLT_FCLASS_POS, // Positive
CMPLT_FCLASS_NEG, // Negative
CMPLT_FCLASS_ZERO, // Zero
CMPLT_FCLASS_UNORM, // Unnormalized
CMPLT_FCLASS_NORM, // Normalized
CMPLT_FCLASS_INF, // Infinity
//----------------------------
// fsz completer for ldf instruction
CMPLT_FSZ_S,
CMPLT_FSZ_D,
CMPLT_FSZ_E,
//----------------------------
// sz completer for ld, st, cmpxchg, ...
CMPLT_SZ_1,
CMPLT_SZ_2,
CMPLT_SZ_4,
CMPLT_SZ_8,
//----------------------------
// Load_Types
CMPLT_LDTYPE_NORMAL, // Normal load
CMPLT_LDTYPE_S, // Speculative load
CMPLT_LDTYPE_A, // Advanced load
CMPLT_LDTYPE_SA, // Speculative Advanced load
CMPLT_LDTYPE_C_NC, // Check load - no clear
CMPLT_LDTYPE_C_CLR, // Check load - clear
CMPLT_LDTYPE_C_CLR_ACQ, // Ordered check load clear
CMPLT_LDTYPE_ACQ, // Ordered load
CMPLT_LDTYPE_BIAS, // Biased load
//----------------------------
// Line_Prefetch_Hints
// Some of Line_Prefetch_Hints are valid for lfetch, store, etc.
CMPLT_HINT_NONE, // Temporal locality, level 1
CMPLT_HINT_NT1, // No temporal locality, level 1
CMPLT_HINT_NT2, // No temporal locality, level 2
CMPLT_HINT_NTA, // No temporal locality, all levels
//----------------------------
// Saturation
CMPLT_SAT_NONE, // modulo_form
CMPLT_SAT_SSS,
CMPLT_SAT_USS,
CMPLT_SAT_UUS,
CMPLT_SAT_UUU,
//----------------------------
// Store_Types
CMPLT_ST_TYPE_NORMAL,
CMPLT_ST_TYPE_REL,
//----------------------------
CMPLT_FP_S, // single_form, M18/M19
CMPLT_FP_D, // double_form, M18/M19
CMPLT_FP_EXP, // exponent_form, M18/M19
CMPLT_FP_SIG, // significand_form, M18/M19
//----------------------------
CMPLT_IREG_FIRST,
CMPLT_IREG_CPUID = CMPLT_IREG_FIRST, // Processor Identification Register
CMPLT_IREG_DBR, // Data Breakpoint Register
CMPLT_IREG_IBR, // Instruction Breakpoint Register
CMPLT_IREG_PKR, // Protection Key Register
CMPLT_IREG_PMC, // Performance Monitor Configuration Register
CMPLT_IREG_PMD, // Performance Monitor Data Register
CMPLT_IREG_RR, // Region Register
CMPLT_IREG_LAST = CMPLT_IREG_RR,
//==================================================
CMPLT_LAST = CMPLT_FP_SIG,
//----------------------------
// xsz completer for sxt/zxt instructions
CMPLT_XSZ_1 = CMPLT_SZ_1,
CMPLT_XSZ_2 = CMPLT_SZ_2,
CMPLT_XSZ_4 = CMPLT_SZ_4,
//----------------------------
// Floating_Point_Comparison_Types
CMPLT_FCMP_FCTYPE_NORMAL = CMPLT_CMP_CTYPE_NORMAL,
CMPLT_FCMP_FCTYPE_NONE = CMPLT_FCMP_FCTYPE_NORMAL,
CMPLT_FCMP_FCTYPE_UNC = CMPLT_CMP_CTYPE_UNC,
// Floating_Point_Comparison_Relations
CMPLT_FCMP_FREL_EQ = CMPLT_CMP_CREL_EQ, // equal f2 == f3
CMPLT_FCMP_FREL_NEQ = CMPLT_CMP_CREL_NE, // not equal !(f2 == f3)
CMPLT_FCMP_FREL_LT = CMPLT_CMP_CREL_LT, // less than f2 < f3
CMPLT_FCMP_FREL_LE = CMPLT_CMP_CREL_LE, // less than or equal f2 <= f3
CMPLT_FCMP_FREL_GT = CMPLT_CMP_CREL_GT, // greater than f2 > f3
CMPLT_FCMP_FREL_GE = CMPLT_CMP_CREL_GE // greater than or equal f2 >= f3
};
// ========================================================================================//
// Instruction Description
// ========================================================================================//
struct InstDescription {
char * mnemonic;
InstCode inst;
uint16 numDst;
uint16 numOpnd;
int instType;
};
//============================================================================//
// Compliter Description
//============================================================================//
struct CmpltDescription {
char *mnemonic;
Completer cmplt;
};
//============================================================================//
#define INST_BREAKPOINT_IMM_VALUE ((uint64)0x4cafe)
#define CAFE ((uint64)0x4cafe)
//============================================================================//
// Encoder
//============================================================================//
// forward declaration of Inst class, declared in some other file
//class Inst;
//class Opnd;
//class Cfg;
//typedef vector<Opnd*> OpndVector;
//typedef vector<Inst*> InstVector;
typedef StlVector<Completer> CompVector;
class Encoder {
public:
static bool patchCallAddr(char * callAddr, char * methodAddr);
static void readBundle(uint64 *code, uint64 * tmplt, uint64 * slots);
static char * getMnemonic(InstCode opcode) { return instDesc[opcode].mnemonic; };
static uint16 getNumDst(InstCode opcode) { return instDesc[opcode].numDst; };
static uint16 getNumOpnd(InstCode opcode) { return instDesc[opcode].numOpnd; };
static int getInstType(InstCode opcode) { return instDesc[opcode].instType; };
static int getInstType(Inst *inst);
static char * getMnemonic(Completer cmplt) { return cmpltDesc[cmplt].mnemonic; };
static bool isBranchInst(Inst *);
static bool isBranchCallInst(Inst *);
static bool isIgnoreInst(Inst *);
static bool isPseudoInst(Inst *);
static Inst * resolvePseudo(Cfg &, Inst *);
static uint64 getNopBits(InstructionType, unsigned, uint64);
static uint64 getHintBits(InstructionType, unsigned, uint64);
static uint64 getBreakBits(InstructionType, unsigned, uint64);
static uint64 getInstBits(InstructionType, Inst *);
static uint64 getInstBitsBranch(InstructionType, Inst *, int);
static uint64 * getInstBitsExtended(Inst *, uint64 *, void *);
static uint64 ldfx(InstCode icode, Inst * inst, CompVector & cmpls, OpndVector & opnds, uint64 qp);
static uint64 fcmp(InstCode icode, Inst * inst, CompVector & cmpls, OpndVector & opnds, uint64 qp);
static uint64 cmp_cmp4(InstCode icode, Inst * inst, CompVector & cmpls, OpndVector & opnds, uint64 qp);
static uint64 mov(InstructionType unit, InstCode icode, Inst * inst, CompVector & cmpls, OpndVector & opnds, uint64 qp);
//----------------------------------------------------------------------------//
static uint64 A1(uint64 x4, uint64 ct2d, int64 r3, int64 r2, int64 r1, uint64 qp) {
return ((uint64)8 << 37) | ((x4 & 0xF) << 29) | (ct2d << 27)
| (r3 << 20) | (r2 << 13) | (r1 << 6) | qp;
}
static uint64 A2(uint64 x4, int64 count2, int64 r3, int64 r2, int64 r1, uint64 qp) {
// count2 = ct2d + 1
return ((uint64)8 << 37) | ((x4 & 0xF) << 29) | (((count2-1) & 0x3) << 27)
| (r3 << 20) | (r2 << 13) | (r1 << 6) | qp;
}
static uint64 A3(uint64 x4, uint64 x2b, int64 r3, int64 imm8, int64 r1, uint64 qp) {
return ((uint64)8 << 37) | (x4 << 29) | (x2b << 27)
| (r3 << 20) | ( imm8<0 ? (uint64)1<<36 : 0 ) | ((0x7F & imm8) << 13)
| (r1 << 6) | qp;
}
static uint64 A4(uint64 x2a, int64 r3, int64 imm14, int64 r1, uint64 qp) {
// imm14 = sign_ext(s << 13 | imm6d << 7 | imm7b, 14)
return ((uint64)8 << 37) | (x2a << 34)
| (r3 << 20) | (r1 << 6) | qp
| (imm14<0 ? (uint64)1<<36 : 0)
| ((imm14 & 0x1F80) << 20) | ((imm14 & 0x7F) << 13);
}
static uint64 A5(int64 r3, int64 imm22, int64 r1, uint64 qp) {
// imm22 = sign_ext(s << 21 | imm5c << 16 | imm9d << 7 | imm7b, 22)
return ((uint64)9 << 37)
| ((r3 & 0x3) << 20) | (r1 << 6) | qp
| (imm22<0 ? (uint64)1<<36 : 0)
| ((imm22 & 0xFF80) << 20) | ((imm22 & 0x1F0000) << 6) | ((imm22 & 0x7F) << 13);
}
static uint64 A6(uint64 opcode, uint64 x2, uint64 ta, uint64 c, int64 p1, int64 p2, int64 r2, int64 r3, uint64 qp) {
return (opcode << 37) | (x2 << 34)
| (ta << 33) | (p2 << 27) | (r3 << 20)
| (r2 << 13) | (c << 12) | (p1 << 6) | qp;
}
static uint64 A7(uint64 opcode, uint64 x2, uint64 ta, uint64 c, int64 p1, int64 p2, int64 r3, uint64 qp) {
return (opcode << 37) | ((uint64)1 << 36) | (x2 << 34)
| (ta << 33) | (p2 << 27) | (r3 << 20)
| (c << 12) | (p1 << 6) | qp;
}
static uint64 A8(uint64 opcode, uint64 x2, uint64 ta, uint64 c, int64 p1, int64 p2, int64 imm8, int64 r3, uint64 qp) {
return (opcode << 37) | (x2 << 34) | (ta << 33) | (c << 12)
| (p1 << 6) | (p2 << 27) | (r3 << 20)
| (imm8<0 ? (uint64)1<<36 : 0) | ((imm8 & 0x7F) << 13) | qp;
}
static uint64 A9(uint64 za, uint64 zb, uint64 x4, uint64 x2b, uint64 r3, uint64 r2, uint64 r1, uint64 qp) {
return ((uint64)0x8 << 37) | (za << 36) | ((uint64)0x1 << 34)
| (zb << 33) | (x4 << 29) | (x2b << 27)
| (r3 << 20) | (r2 << 13) | (r1 << 6) | qp;
}
static uint64 A10(uint64 x4, uint64 ct2d, uint64 r3, uint64 r2, uint64 r1, uint64 qp) {
return ((uint64)0x8 << 37) | ((uint64)0x1 << 34)
| ((uint64)0x1 << 33) | (x4 << 29) | (ct2d << 27)
| (r3 << 20) | (r2 << 13) | (r1 << 6) | qp;
}
static uint64 I1(uint64 ct2d, uint64 x2b, uint64 r3, uint64 r2, uint64 r1, uint64 qp) {
// count2 = (ct2d == 0) ? 0 : (ct2d == 1) ? 7 : (ct2d == 2) ? 15 : 16
return ((uint64)7 << 37) | ((uint64)1 << 33) | ((0x3 & ct2d) << 30)
| ((0x3 & x2b) << 28) | (r3 << 20) | (r2 << 13) | (r1 << 6) | qp;
}
static uint64 I2(uint64 za, uint64 zb, uint64 x2c, uint64 x2b, uint64 r3, uint64 r2, uint64 r1, uint64 qp) {
return ((uint64)7 << 37) | ((uint64)2 << 34) | ((0x1 & za) << 36)
| ((0x1 & zb) << 33) | ((0x3 & x2c) << 30) | ((0x3 & x2b) << 28)
| (r3 << 20) | (r2 << 13) | (r1 << 6) | qp;
}
static uint64 I3(uint64 mbt4c, uint64 r2, uint64 r1, uint64 qp) {
return ((uint64)7 << 37) | ((uint64)3 << 34) | ((uint64)2 << 28)
| ((uint64)2 << 30)
| ((0xf & mbt4c) << 20) | (r2 << 13) | (r1 << 6) | qp;
}
static uint64 I4(uint64 mht8c, uint64 r2, uint64 r1, uint64 qp) {
return ((uint64)7 << 37) | ((uint64)3 << 34) | ((uint64)2 << 28)
| ((uint64)2 << 30) | ((uint64)1 << 33)
| ((0xFF & mht8c) << 20) | (r2 << 13) | (r1 << 6) | qp;
}
static uint64 I5(uint64 za, uint64 zb, uint64 x2b, uint64 r3, uint64 r2, uint64 r1, uint64 qp) {
return ((uint64)7 << 37)
| ((0x1 & za) << 36) | ((0x1 & zb) << 33) | ((0x3 & x2b) << 28)
| (r3 << 20) | (r2 << 13) | (r1 << 6) | qp;
}
static uint64 I6(uint64 za, uint64 zb, uint64 x2b, uint64 r3, uint64 count5b, uint64 r1, uint64 qp) {
return ((uint64)7 << 37) | ((uint64)1 << 34)
| ((0x1 & za) << 36) | ((0x1 & zb) << 33) | ((0x3 & x2b) << 28)
| (r3 << 20) | ((0x1F & count5b) << 14) | (r1 << 6) | qp;
}
static uint64 I7(uint64 za, uint64 zb, uint64 r3, uint64 r2, uint64 r1, uint64 qp) {
return ((uint64)7 << 37) | ((uint64)1 << 30)
| ((0x1 & za) << 36) | ((0x1 & zb) << 33)
| (r3 << 20) | (r2 << 13) | (r1 << 6) | qp;
}
static uint64 I8(uint64 za, uint64 zb, uint64 count5c, uint64 r2, uint64 r1, uint64 qp) {
return ((uint64)7 << 37) | ((uint64)3 << 34) | ((uint64)1 << 28) | ((uint64)1 << 30)
| ((0x1 & za) << 36) | ((0x1 & zb) << 33)
| (count5c << 20) | (r2 << 13) | (r1 << 6) | qp;
}
static uint64 I9(uint64 r3, uint64 r1, uint64 qp) {
return ((uint64)7 << 37) | ((uint64)1 << 33) | ((uint64)1 << 34)
| ((uint64)1 << 28) | ((uint64)2 << 30)
| (r3 << 20) | (r1 << 6) | qp;
}
static uint64 I10(uint64 count6d, uint64 r3, uint64 r2, uint64 r1, uint64 qp) {
return ((uint64)5 << 37) | ((uint64)3 << 34)
| (count6d << 27) | (r3 << 20) | (r2 << 13) | (r1 << 6) | qp;
}
static uint64 I11(uint64 len6d, uint64 r3, uint64 pos6b, uint64 y, uint64 r1, uint64 qp) {
return ((uint64)5 << 37) | ((uint64)1 << 34)
| (len6d << 27) | (r3 << 20) | (pos6b << 14) | (y << 13) | (r1 << 6) | qp;
}
static uint64 I12(uint64 len6d, uint64 cpos6c, uint64 r2, uint64 r1, uint64 qp) {
return ((uint64)5 << 37) | ((uint64)1 << 34) | ((uint64)1 << 33)
| ((0x3F & len6d) << 27) | ((0x3F & cpos6c) << 20)
| (r2 << 13) | (r1 << 6) | qp;
}
static uint64 I13(uint64 len6d, uint64 cpos6c, int64 imm8, uint64 r1, uint64 qp) {
return ((uint64)5 << 37) | ((uint64)1 << 34) | ((uint64)1 << 33) | ((uint64)1 << 26)
| ((uint64)(imm8<0?1:0) << 36) | ((0x7F & imm8) << 13)
| (len6d << 27) | (cpos6c << 20) | (r1 << 6) | qp;
}
static uint64 I14(int64 imm1, uint64 len6d, uint64 r3, uint64 cpos6b, uint64 r1, uint64 qp) {
return ((uint64)5 << 37) | ((uint64)3 << 34) | ((uint64)1 << 33)
| ((0x1 & imm1) << 36) | (len6d << 27) | (r3 << 20) | (cpos6b << 14) | (r1 << 6) | qp;
}
static uint64 I15(uint64 cpos6d, uint64 len4d, uint64 r3, uint64 r2, uint64 r1, uint64 qp) {
return ((uint64)4 << 37)
| (cpos6d << 36) | (len4d << 27) | (r3 << 20) | (r2 << 13) | (r1 << 6) | qp;
}
static uint64 I20(int64 imm21, uint64 r2, uint64 qp) {
return ((uint64)(imm21<0?1:0) << 36) | ((uint64)1 << 33)
| ((0xFFF80 & imm21) << 20) | (r2 << 13) | ((0x7F & imm21) << 6) | qp;
}
static uint64 I21(uint64 timm9c, uint64 ih, uint64 x, uint64 wh, uint64 r2, uint64 b1, uint64 qp) {
return ((uint64)0x7 << 33) | (timm9c << 24)
| (ih << 23) | (x << 22) | (wh << 20) | (r2 << 13) | (b1 << 6) | qp;
}
static uint64 I22(uint64 b2, uint64 r1, uint64 qp) {
return ((uint64)0x31 << 27)
| (b2 << 13) | (r1 << 6) | qp;
}
static uint64 I23(uint64 mask16, uint64 r2, uint64 qp) {
return ((uint64)0x3 << 33)
| ((uint64)(mask16&0x8000 ? 1 : 0) << 36) | (((mask16 >> 7) & 0xFF) << 24)
| ((mask16 & 0x7F) << 6) | (r2 << 13) | qp;
}
static uint64 I24(int64 imm28, uint64 qp) {
return ((uint64)0x2 << 33)
| ((uint64)(imm28<0 ? 1 : 0) << 36) | ((imm28 & 0x7FFFFFF) << 6) | qp;
}
static uint64 I25(uint64 x6, uint64 r1, uint64 qp) {
return (x6 << 27) | (r1 << 6) | qp;
}
static uint64 I26(uint64 ar3, uint64 r2, uint64 qp) {
return ((uint64)0x2A << 27) | (ar3 << 20) | (r2 << 13) | qp;
}
static uint64 I27(uint64 ar3, int64 imm8, uint64 qp) {
return ((uint64)0x0A << 27) | (ar3 << 20)
| ((uint64)(imm8 < 0?1:0) << 36) | ((0x7F & imm8) << 13) | qp;
}
static uint64 I28(uint64 ar3, uint64 r1, uint64 qp) {
return ((uint64)0x32 << 27) | (ar3 << 20) | (r1 << 6) | qp;
}
static uint64 I29(uint64 x6, uint64 r3, uint64 r1, uint64 qp) {
return ((x6 & 0x3f) << 27) | ((r3 & 0x7f) << 20) | ((r1 & 0x7f) << 6) | qp;
}
static uint64 M1(uint64 x6, uint64 hint, uint64 x, int64 r3, int64 r1, uint64 qp) {
return ((uint64)4 << 37) | (x6 << 30) | (hint << 28) | (x << 27)
| (r3 << 20) | (r1 << 6) | qp;
}
static uint64 M2(uint64 x6, uint64 hint, int64 r3, int64 r2, int64 r1, uint64 qp) {
return ((uint64)4 << 37) | ((uint64)1 << 36) | (x6 << 30) | (hint << 28)
| (r3 << 20) | (r2 << 13) | (r1 << 6) | qp;
}
static uint64 M3(uint64 x6, uint64 hint, int64 r3, int64 imm9, int64 r1, uint64 qp) {
return ((uint64)5 << 37) | (x6 << 30) | (hint << 28)
| (r3 << 20) | ((uint64)(imm9<0?1:0) << 36)
| (((imm9 >> 7) & 0x1) << 27) | ((imm9 & 0x7F) <<13)
| (r1 << 6) | qp;
}
static uint64 M4(uint64 x6, uint64 hint, uint64 x, int64 r3, int64 r2, uint64 qp) {
return ((uint64)4 << 37) | (x6 << 30) | (hint << 28) |(x << 27)
| (r3 << 20) | (r2 << 13) | qp;
}
static uint64 M5(uint64 x6, uint64 hint, int64 r3, int64 r2, int64 imm9, uint64 qp) {
// imm9 = sign_ext(s << 8 | i << 7 | imm7a, 9)
return ((uint64)5 << 37) | (x6 << 30) | (hint << 28)
| (r3 << 20) | (r2 << 13)
| (imm9<0 ? (uint64)1<<36 : 0)
| ((imm9 & 0x80) << 20) | ((imm9 & 0x7F) << 6) | qp;
}
static uint64 M6(uint64 x6, uint64 hint, int64 r3, int64 f1, uint64 qp) {
return ((uint64)6 << 37) | (x6 << 30) | (hint << 28)
| (r3 << 20) | (f1 << 6) | qp;
}
static uint64 M7(uint64 x6, uint64 hint, int64 r3, int64 r2, int64 f1, uint64 qp) {
return ((uint64)6 << 37) | ((uint64)1 << 36) | (x6 << 30) | (hint << 28)
| (r3 << 20) | (r2 << 13) | (f1 << 6) | qp;
}
static uint64 M8(uint64 x6, uint64 hint, int64 r3, int64 imm9, int64 f1, uint64 qp) {
return ((uint64)7 << 37) | (x6 << 30) | (hint << 28)
| ((uint64)(imm9<0?1:0) << 36) | (((imm9 >> 7) & 0x1) << 27)
| ((imm9 & 0x7F) << 13) | (r3 << 20) | (f1 << 6) | qp;
}
static uint64 M9(uint64 x6, uint64 hint, int64 r3, int64 f2, uint64 qp) {
// 6 m x6 hint x r3 f2 qp
return ((uint64)6 << 37) | (x6 << 30) | (hint << 28)
| (r3 << 20) | (f2 << 13) | qp;
}
static uint64 M10(uint64 x6, uint64 hint, int64 r3, int64 f2, int64 imm9, uint64 qp) {
// imm9 = sign_ext(s << 8 | i << 7 | imm7a, 9)
return ((uint64)7 << 37) | (x6 << 30) | (hint << 28)
| (r3 << 20) | (f2 << 13) | ((uint64)(imm9<0?1:0) << 36)
| ((uint64)(imm9 & 0x80) << 20) | ((uint64)(imm9 & 0x7F) << 6) | qp;
}
static uint64 M18(uint64 x6, int64 r2, int64 f1, int64 qp) {
return ((uint64)6 << 37) | (x6 << 30) | ((uint64)1 << 27)
| (r2 << 13) | (f1 << 6) | qp;
}
static uint64 M19(uint64 x6, int64 f2, int64 r1, int64 qp) {
return ((uint64)4 << 37) | (x6 << 30) | ((uint64)1 << 27)
| (f2 << 13) | (r1 << 6) | qp;
}
static uint64 M28(uint64 x, int64 r3, int64 qp) {
return ((uint64)1 << 37) | ((uint64)0x30 << 27)
| (x << 36) | (r3 << 20) | qp;
}
static uint64 M29(uint64 ar3, int64 r2, int64 qp) {
return ((uint64)1 << 37) | ((uint64)0x2A << 27)
| (ar3 << 20) | (r2 << 13) | qp;
}
static uint64 M30(uint64 ar3, int64 imm8, int64 qp) {
return ((uint64)0 << 37) | ((uint64)0x2 << 31) | ((uint64)0x8 << 27)
| (ar3 << 20) | ((uint64)(imm8<0?1:0) << 36) | ((0x7F & imm8) << 13)
| qp;
}
static uint64 M31(uint64 ar3, int64 r1, int64 qp) {
return ((uint64)1 << 37) | ((uint64)0x22 << 27)
| (ar3 << 20) | (r1 << 6) | qp;
}
static uint64 M34(uint64 sor, uint64 sol, uint64 sof, int64 r1, int64 qp) {
return ((uint64)1 << 37) | ((uint64)0x6 << 33)
| (sor << 27) | (sol << 20) | (sof << 13) | (r1 << 6) | qp;
}
static uint64 B1_B2(uint64 dh, uint64 bwh, uint64 ph, uint64 btype, int64 imm21, uint64 qp) {
return ((uint64)4 << 37)
| (dh << 35) | (bwh << 33) | (ph << 12) | (btype << 6) | qp
| (imm21<0 ? (uint64)1<<36 : 0)
| ((imm21 & 0xFFFFF) << 13);
}
static uint64 B3(uint64 p, uint64 wh, uint64 d, int64 imm21, uint64 b1, uint64 qp) {
// target25 = IP + (sign_ext(s << 20 | imm20b, 21) << 4)
return ((uint64)5 << 37)
| (d << 35) | (wh << 32) | (p << 12)
| ((uint64)(imm21<0?1:0) << 36) | ((imm21 & 0xFFFFF) << 13) | (b1 << 6) | qp;
}
static uint64 B4(uint64 dh, uint64 bwh, uint64 x6, uint64 b2, uint64 ph, uint64 btype, uint64 qp) {
return ((uint64)0 << 37)
| (dh << 35) | (bwh << 33) | (x6 << 27) | (ph << 12) | (btype << 6) | qp
| (b2 << 13);
}
static uint64 B5(uint64 p, uint64 wh, uint64 d, uint64 b2, uint64 b1, uint64 qp) {
return ((uint64)1 << 37)
| (d << 35) | (wh << 32) | (p << 12) | (b2 << 13) | (b1 << 6) | qp;
}
static uint64 F1(uint64 opcode, uint64 x, uint64 sf, int64 f4, int64 f3, int64 f2, int64 f1, uint64 qp) {
return (opcode << 37) | (x << 36) | (sf << 34)
| (f4 << 27) | (f3 << 20) | (f2 << 13) | (f1 << 6) | qp;
}
static uint64 F2(uint64 x2, int64 f4, int64 f3, int64 f2, int64 f1, uint64 qp) {
return ((uint64)0xE << 37) | ((uint64)1 << 36) | ((x2 & 0x3)<< 34)
| (f4 << 27) | (f3 << 20) | (f2 << 13) | (f1 << 6) | qp;
}
static uint64 F4(uint64 rb, uint64 sf, uint64 ra, int64 p2, int64 f3, int64 f2, uint64 ta, int64 p1, uint64 qp) {
return ((uint64)0x4 << 37) | (rb << 36) | (sf << 34) | (ra << 33)
| (p2 << 27) | (f3 << 20) | (f2 << 13) | (ta << 12) | ( p1 << 6) | qp;
}
static uint64 F5(uint64 fclass9, uint64 p2, uint64 f2, int64 ta, uint64 p1, uint64 qp) {
return ((uint64)0x5 << 37) | ((fclass9 >> 7) << 33) | ((fclass9 & 0x7F) << 20)
| (p2 << 27) | (f2 << 13) | (ta << 12) | ( p1 << 6) | qp;
}
static uint64 F6(uint64 opcode, uint64 sf, int64 p2, int64 f3, int64 f2, uint64 f1, uint64 qp) {
return (opcode << 37) | (sf << 34) | ((uint64)1 << 33)
| (p2 << 27) | (f3 << 20) | (f2 << 13) | (f1 << 6) | qp;
}
static uint64 F8(uint64 opcode, uint64 sf, uint64 x6, int64 f3, int64 f2, uint64 f1, uint64 qp) {
return (opcode << 37) | (sf <<34) | (x6 << 27) | (f3 << 20) | (f2 << 13) | (f1 << 6) | qp;
}
static uint64 F9(uint64 opcode, uint64 x6, int64 f3, int64 f2, uint64 f1, uint64 qp) {
return (opcode << 37) | (x6 << 27) | (f3 << 20) | (f2 << 13) | (f1 << 6) | qp;
}
static uint64 F10(uint64 opcode, uint64 sf, uint64 x6, int64 f2, uint64 f1, uint64 qp) {
return (opcode << 37) | (sf << 34) | (x6 << 27) | (f2 << 13) | (f1 << 6) | qp;
}
static uint64 F11(int64 f2, int64 f1, int64 qp) {
return ((uint64)0x1C << 27)
| (f2 << 13) | (f1 << 6) | qp;
}
static uint64 * X2(int vc, uint64 r1, int64 imm64, uint64 qp, uint64 * slots12) {
// imm64 = i << 63 | imm41 << 22 | ic << 21 | imm5c << 16 | imm9d << 7 | imm7b
// slot1: 6 i imm9d imm5c ic vc imm7b r1 qp; slot2: imm41
slots12[1] = ((uint64)6 << 37);
slots12[1] |= r1 << 6
| qp | ((vc & 0x01) << 20)
| ((int64)imm64<0 ? (uint64)1<<36 : 0)
| ((imm64 & 0x7F) << 13)
| ((imm64 & (0x1FF<<7)) << 20)
| ((imm64 & (0x1F<<16)) << 6)
| (imm64 & (0x01<<21)) ;
slots12[0] = (imm64 & (0x1FFFFFFFFFF<<22)) >> 22;
return slots12;
}
static uint64 * X3(uint64 imm60, uint64 d, uint64 wh, uint64 p, uint64 qp, uint64 * slots12) {
// (qp) brl.btype.bwh.ph.dh b1 = target64
// target64 = IP + ((i << 59 | imm39 << 20 | imm20b) << 4)
slots12[1] = ((uint64)0xC << 37) | ((imm60 >> 59) << 36) | (d << 35)
| (wh << 33) | (p << 12) | qp
| ((imm60 & 0xFFFFF) << 13);
slots12[0] = (imm60 & (0x7FFFFFFFFF<<20)) >> 18;
return slots12;
}
static uint64 * X4(uint64 imm60, uint64 d, uint64 wh, uint64 p, uint64 b1, uint64 qp, uint64 * slots12) {
// (qp) brl.btype.bwh.ph.dh b1 = target64
// target64 = IP + ((i << 59 | imm39 << 20 | imm20b) << 4)
slots12[1] = ((uint64)0xD << 37) | ((imm60 >> 59) << 36) | (d << 35)
| (wh << 33) | (p << 12) | (b1 << 6) | qp
| ((imm60 & 0xFFFFF) << 13);
slots12[0] = (imm60 & (0x7FFFFFFFFF<<20)) >> 18;
return slots12;
}
static uint64 * X5(uint64 y, int64 imm62, uint64 qp, uint64 * slots12) {
// imm62 = imm41 << 21 | i << 20 | imm20a
slots12[1] = ((y & 0x01) << 26) | qp
| ((imm62 & 0xFFFFF) << 6)
| ((imm62 & 0x100000) << 16);
slots12[0] = (imm62 & (0x1FFFFFFFFFF<<21)) >> 21;
return slots12;
}
protected:
static const InstDescription instDesc[];
static const CmpltDescription cmpltDesc[];
};
} // IPF
} // Jitrino
#endif /*IPFENCODER_H_*/