diff --git a/compiler/aarch64/codegen/ARM64BinaryEncoding.cpp b/compiler/aarch64/codegen/ARM64BinaryEncoding.cpp index 495185be5bd..0621022a791 100644 --- a/compiler/aarch64/codegen/ARM64BinaryEncoding.cpp +++ b/compiler/aarch64/codegen/ARM64BinaryEncoding.cpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018, 2020 IBM Corp. and others + * Copyright (c) 2018, 2021 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -654,6 +654,19 @@ int32_t TR::ARM64MemInstruction::estimateBinaryLength(int32_t currentEstimate) return(currentEstimate + getEstimatedBinaryLength()); } +uint8_t *TR::ARM64MemImmInstruction::generateBinaryEncoding() + { + uint8_t *instructionStart = cg()->getBinaryBufferCursor(); + uint8_t *cursor = instructionStart; + cursor = getOpCode().copyBinaryToBuffer(instructionStart); + insertImmediateField(toARM64Cursor(cursor)); + cursor = getMemoryReference()->generateBinaryEncoding(this, cursor, cg()); + setBinaryLength(cursor - instructionStart); + setBinaryEncoding(instructionStart); + cg()->addAccumulatedInstructionLengthError(getEstimatedBinaryLength() - getBinaryLength()); + return cursor; + } + uint8_t *TR::ARM64MemSrc1Instruction::generateBinaryEncoding() { uint8_t *instructionStart = cg()->getBinaryBufferCursor(); diff --git a/compiler/aarch64/codegen/ARM64Debug.cpp b/compiler/aarch64/codegen/ARM64Debug.cpp index 624ca18663e..c5a6ce265a4 100644 --- a/compiler/aarch64/codegen/ARM64Debug.cpp +++ b/compiler/aarch64/codegen/ARM64Debug.cpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018, 2020 IBM Corp. and others + * Copyright (c) 2018, 2021 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -618,6 +618,9 @@ TR_Debug::print(TR::FILE *pOutFile, TR::Instruction *instr) case OMR::Instruction::IsMem: print(pOutFile, (TR::ARM64MemInstruction *)instr); break; + case OMR::Instruction::IsMemImm: + print(pOutFile, (TR::ARM64MemImmInstruction *)instr); + break; case OMR::Instruction::IsMemSrc1: print(pOutFile, (TR::ARM64MemSrc1Instruction *)instr); break; @@ -1436,6 +1439,41 @@ TR_Debug::print(TR::FILE *pOutFile, TR::ARM64MemInstruction *instr) trfflush(_comp->getOutFile()); } +void +TR_Debug::print(TR::FILE *pOutFile, TR::ARM64MemImmInstruction *instr) + { + TR::InstOpCode::Mnemonic op = instr->getOpCodeValue(); + printPrefix(pOutFile, instr); + trfprintf(pOutFile, "%s \t", getOpCodeName(&instr->getOpCode())); + if ((op == TR::InstOpCode::prfmoff || op == TR::InstOpCode::prfmimm)) + { + uint32_t immediate = instr->getImmediate(); + uint32_t typeValue = (immediate >> 3) & 0x3; + uint32_t targetValue = (immediate >> 1) & 0x3; + if ((typeValue != 3) && (targetValue != 3)) + { + ARM64PrefetchType type = static_cast(typeValue); + ARM64PrefetchTarget target = static_cast(targetValue); + ARM64PrefetchPolicy policy = static_cast(immediate & 0x1); + trfprintf(pOutFile, "%s%s%s, ", (type == ARM64PrefetchType::LOAD) ? "pld" : ((type == ARM64PrefetchType::INSTRUCTION) ? "pli" : "pst"), + (target == ARM64PrefetchTarget::L1) ? "l1" : ((target == ARM64PrefetchTarget::L2) ? "l2" : "l3"), + (policy == ARM64PrefetchPolicy::KEEP) ? "keep" : "strm"); + } + else + { + trfprintf(pOutFile, "#%d, ", instr->getImmediate()); + } + } + else + { + trfprintf(pOutFile, "#%d, ", instr->getImmediate()); + } + print(pOutFile, instr->getMemoryReference()); + printMemoryReferenceComment(pOutFile, instr->getMemoryReference()); + printInstructionComment(pOutFile, 1, instr); + trfflush(_comp->getOutFile()); + } + void TR_Debug::print(TR::FILE *pOutFile, TR::ARM64MemSrc1Instruction *instr) { diff --git a/compiler/aarch64/codegen/ARM64Instruction.hpp b/compiler/aarch64/codegen/ARM64Instruction.hpp index 83ca5f5713a..419daf20424 100644 --- a/compiler/aarch64/codegen/ARM64Instruction.hpp +++ b/compiler/aarch64/codegen/ARM64Instruction.hpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018, 2020 IBM Corp. and others + * Copyright (c) 2018, 2021 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -40,6 +40,47 @@ namespace TR { class SymbolReference; } #define ARM64_INSTRUCTION_LENGTH 4 +/* + * Prefetch type used in PRFM instructions + */ +enum class ARM64PrefetchType + { + LOAD = 0, + INSTRUCTION = 1, + STORE = 2 + }; + +/* + * Prefetch target used in PRFM instructions + */ +enum class ARM64PrefetchTarget + { + L1 = 0, + L2 = 1, + L3 = 2 + }; + +/* + * Prefetch policy used in PRFM instructions + */ +enum class ARM64PrefetchPolicy + { + KEEP = 0, + STRM = 1 + }; + +/* + * @brief returns Prefetch operation from specified type, target, and policy. + * @param[in] type : prefetch type + * @param[in] target : prefetch target + * @param[in] policy : prefetch policy + * @return prefetch operation + */ +inline uint32_t toPrefetchOp(ARM64PrefetchType type, ARM64PrefetchTarget target, ARM64PrefetchPolicy policy) + { + return (static_cast(type) << 3) | (static_cast(target) << 1) | static_cast(policy); + } + /* * @brief Answers if the signed integer value can be placed in 7-bit field * @param[in] intValue : signed integer value @@ -3355,6 +3396,80 @@ class ARM64Trg1MemSrc1Instruction : public ARM64Trg1MemInstruction virtual int32_t estimateBinaryLength(int32_t currentEstimate); }; +class ARM64MemImmInstruction : public ARM64MemInstruction + { + uint32_t _immediate; // Imm5 + + public: + /* + * @brief Constructor + * @param[in] op : instruction opcode + * @param[in] node : node + * @param[in] mr : memory reference + * @param[in] immediate : 5bit immediate + * @param[in] cg : CodeGenerator + */ + ARM64MemImmInstruction(TR::InstOpCode::Mnemonic op, + TR::Node *node, + TR::MemoryReference *mr, + uint32_t immediate, + TR::CodeGenerator *cg) + : ARM64MemInstruction(op, node, mr, cg), _immediate(immediate) + { + } + + /* + * @brief Constructor + * @param[in] op : instruction opcode + * @param[in] node : node + * @param[in] mr : memory reference + * @param[in] precedingInstruction : preceding instruction + * @param[in] immediate : 5bit immediate + * @param[in] cg : CodeGenerator + */ + ARM64MemImmInstruction(TR::InstOpCode::Mnemonic op, + TR::Node *node, + TR::MemoryReference *mr, + uint32_t immediate, + TR::Instruction *precedingInstruction, TR::CodeGenerator *cg) + : ARM64MemInstruction(op, node, mr, precedingInstruction, cg), _immediate(immediate) + { + } + + /** + * @brief Gets instruction kind + * @return instruction kind + */ + virtual Kind getKind() { return IsMemImm; } + + /** + * @brief Gets immediate + * @return immediate + */ + uint32_t getImmediate() {return _immediate;} + /** + * @brief Sets immediate + * @param[in] immediate : immediate value + * @return immediate + */ + uint32_t setImmediate(uint32_t immediate) {return (_immediate = immediate);} + + /** + * @brief Sets immediate field in binary encoding + * @param[in] instruction : instruction cursor + */ + void insertImmediateField(uint32_t *instruction) + { + *instruction |= (_immediate & 0x1f); /* imm5 */ + } + + /** + * @brief Generates binary encoding of the instruction + * @return instruction cursor + */ + virtual uint8_t *generateBinaryEncoding(); + }; + class ARM64Src1Instruction : public TR::Instruction { TR::Register *_source1Register; diff --git a/compiler/aarch64/codegen/GenerateInstructions.cpp b/compiler/aarch64/codegen/GenerateInstructions.cpp index b37d7a38a2e..5578f7caf82 100644 --- a/compiler/aarch64/codegen/GenerateInstructions.cpp +++ b/compiler/aarch64/codegen/GenerateInstructions.cpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018, 2020 IBM Corp. and others + * Copyright (c) 2018, 2021 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -280,6 +280,14 @@ TR::Instruction *generateTrg1MemInstruction(TR::CodeGenerator *cg, TR::InstOpCod return new (cg->trHeapMemory()) TR::ARM64Trg1MemInstruction(op, node, treg, mr, cg); } +TR::Instruction *generateMemImmInstruction(TR::CodeGenerator *cg, TR::InstOpCode::Mnemonic op, TR::Node *node, + TR::MemoryReference *mr, uint32_t imm, TR::Instruction *preced) + { + if (preced) + return new (cg->trHeapMemory()) TR::ARM64MemImmInstruction(op, node, mr, imm, preced, cg); + return new (cg->trHeapMemory()) TR::ARM64MemImmInstruction(op, node, mr, imm, cg); + } + TR::Instruction *generateMemSrc1Instruction(TR::CodeGenerator *cg, TR::InstOpCode::Mnemonic op, TR::Node *node, TR::MemoryReference *mr, TR::Register *sreg, TR::Instruction *preced) { diff --git a/compiler/aarch64/codegen/GenerateInstructions.hpp b/compiler/aarch64/codegen/GenerateInstructions.hpp index 473e4a5c612..61f2ae99bf9 100644 --- a/compiler/aarch64/codegen/GenerateInstructions.hpp +++ b/compiler/aarch64/codegen/GenerateInstructions.hpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018, 2020 IBM Corp. and others + * Copyright (c) 2018, 2021 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -622,6 +622,24 @@ TR::Instruction *generateTrg1MemInstruction( TR::MemoryReference *mr, TR::Instruction *preced = NULL); +/* + * @brief Generates mem-imm instruction + * @param[in] cg : CodeGenerator + * @param[in] op : instruction opcode + * @param[in] node : node + * @param[in] mr : memory reference + * @param[in] imm : immediate + * @param[in] preced : preceding instruction + * @return generated instruction + */ +TR::Instruction *generateMemImmInstruction( + TR::CodeGenerator *cg, + TR::InstOpCode::Mnemonic op, + TR::Node *node, + TR::MemoryReference *mr, + uint32_t imm, + TR::Instruction *preced = NULL); + /* * @brief Generates src-to-mem instruction * @param[in] cg : CodeGenerator diff --git a/compiler/aarch64/codegen/OMRInstructionKindEnum.hpp b/compiler/aarch64/codegen/OMRInstructionKindEnum.hpp index b29e9f9c8e5..da488e0323f 100644 --- a/compiler/aarch64/codegen/OMRInstructionKindEnum.hpp +++ b/compiler/aarch64/codegen/OMRInstructionKindEnum.hpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018, 2020 IBM Corp. and others + * Copyright (c) 2018, 2021 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -55,6 +55,7 @@ IsMem, IsMemSrc1, IsMemSrc2, + IsMemImm, IsSrc1, IsZeroSrc1Imm, IsSrc2, diff --git a/compiler/ras/Debug.hpp b/compiler/ras/Debug.hpp index 630f5b5c2e6..00b916fce48 100644 --- a/compiler/ras/Debug.hpp +++ b/compiler/ras/Debug.hpp @@ -358,6 +358,7 @@ namespace TR { class ARM64Trg1Src2ZeroInstruction; } namespace TR { class ARM64Trg1Src3Instruction; } namespace TR { class ARM64Trg1MemInstruction; } namespace TR { class ARM64MemInstruction; } +namespace TR { class ARM64MemImmInstruction; } namespace TR { class ARM64MemSrc1Instruction; } namespace TR { class ARM64MemSrc2Instruction; } namespace TR { class ARM64Trg1MemSrc1Instruction; } @@ -1135,6 +1136,7 @@ class TR_Debug void print(TR::FILE *, TR::ARM64Trg1Src3Instruction *); void print(TR::FILE *, TR::ARM64Trg1MemInstruction *); void print(TR::FILE *, TR::ARM64MemInstruction *); + void print(TR::FILE *, TR::ARM64MemImmInstruction *); void print(TR::FILE *, TR::ARM64MemSrc1Instruction *); void print(TR::FILE *, TR::ARM64MemSrc2Instruction *); void print(TR::FILE *, TR::ARM64Trg1MemSrc1Instruction *);