Skip to content

Commit

Permalink
Merge pull request #5205 from Akira1Saitoh/aarch64MemSrc2Instruction
Browse files Browse the repository at this point in the history
AArch64: Add ARM64MemSrc2Instruction
  • Loading branch information
knn-k authored May 19, 2020
2 parents 8967d99 + ebbe6f8 commit 656748a
Show file tree
Hide file tree
Showing 9 changed files with 297 additions and 2 deletions.
20 changes: 20 additions & 0 deletions compiler/aarch64/codegen/ARM64BinaryEncoding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,26 @@ int32_t TR::ARM64MemSrc1Instruction::estimateBinaryLength(int32_t currentEstimat
return(currentEstimate + getEstimatedBinaryLength());
}

uint8_t *TR::ARM64MemSrc2Instruction::generateBinaryEncoding()
{
uint8_t *instructionStart = cg()->getBinaryBufferCursor();
uint8_t *cursor = instructionStart;
cursor = getOpCode().copyBinaryToBuffer(instructionStart);
insertSource1Register(toARM64Cursor(cursor));
insertSource2Register(toARM64Cursor(cursor));
cursor = getMemoryReference()->generateBinaryEncoding(this, cursor, cg());
setBinaryLength(cursor - instructionStart);
setBinaryEncoding(instructionStart);
cg()->addAccumulatedInstructionLengthError(getEstimatedBinaryLength() - getBinaryLength());
return cursor;
}

int32_t TR::ARM64MemSrc2Instruction::estimateBinaryLength(int32_t currentEstimate)
{
setEstimatedBinaryLength(getMemoryReference()->estimateBinaryLength(getOpCodeValue()));
return(currentEstimate + getEstimatedBinaryLength());
}

uint8_t *TR::ARM64Trg1MemSrc1Instruction::generateBinaryEncoding()
{
uint8_t *instructionStart = cg()->getBinaryBufferCursor();
Expand Down
17 changes: 17 additions & 0 deletions compiler/aarch64/codegen/ARM64Debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,9 @@ TR_Debug::print(TR::FILE *pOutFile, TR::Instruction *instr)
case OMR::Instruction::IsMemSrc1:
print(pOutFile, (TR::ARM64MemSrc1Instruction *)instr);
break;
case OMR::Instruction::IsMemSrc2:
print(pOutFile, (TR::ARM64MemSrc2Instruction *)instr);
break;
case OMR::Instruction::IsTrg1MemSrc1:
print(pOutFile, (TR::ARM64Trg1MemSrc1Instruction *)instr);
break;
Expand Down Expand Up @@ -1197,6 +1200,20 @@ TR_Debug::print(TR::FILE *pOutFile, TR::ARM64MemSrc1Instruction *instr)
trfflush(_comp->getOutFile());
}

void
TR_Debug::print(TR::FILE *pOutFile, TR::ARM64MemSrc2Instruction *instr)
{
printPrefix(pOutFile, instr);
trfprintf(pOutFile, "%s \t", getOpCodeName(&instr->getOpCode()));

print(pOutFile, instr->getSource1Register(), TR_WordReg); trfprintf(pOutFile, ", ");
print(pOutFile, instr->getSource2Register(), TR_WordReg); trfprintf(pOutFile, ", ");
print(pOutFile, instr->getMemoryReference());

printMemoryReferenceComment(pOutFile, instr->getMemoryReference());
trfflush(_comp->getOutFile());
}

void
TR_Debug::print(TR::FILE *pOutFile, TR::ARM64Trg1MemSrc1Instruction *instr)
{
Expand Down
56 changes: 55 additions & 1 deletion compiler/aarch64/codegen/ARM64Instruction.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2018, 2019 IBM Corp. and others
* Copyright (c) 2018, 2020 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
Expand Down Expand Up @@ -285,6 +285,60 @@ void TR::ARM64MemSrc1Instruction::assignRegisters(TR_RegisterKinds kindToBeAssig
getDependencyConditions()->assignPreConditionRegisters(this->getPrev(), kindToBeAssigned, cg());
}

// TR::ARM64MemSrc2Instruction:: member functions

bool TR::ARM64MemSrc2Instruction::refsRegister(TR::Register *reg)
{
return (reg == getSource2Register()) || TR::ARM64MemSrc1Instruction::refsRegister(reg);
}

bool TR::ARM64MemSrc2Instruction::usesRegister(TR::Register *reg)
{
return (reg == getSource2Register()) || TR::ARM64MemSrc1Instruction::usesRegister(reg);
}

bool TR::ARM64MemSrc2Instruction::defsRegister(TR::Register *reg)
{
return false;
}

bool TR::ARM64MemSrc2Instruction::defsRealRegister(TR::Register *reg)
{
return false;
}

void TR::ARM64MemSrc2Instruction::assignRegisters(TR_RegisterKinds kindToBeAssigned)
{
TR::Machine *machine = cg()->machine();
TR::MemoryReference *mref = getMemoryReference();
TR::Register *source1Virtual = getSource1Register();
TR::Register *source2Virtual = getSource2Register();

if (getDependencyConditions())
getDependencyConditions()->assignPostConditionRegisters(this, kindToBeAssigned, cg());

mref->blockRegisters();
source2Virtual->block();
setSource1Register(machine->assignOneRegister(this, source1Virtual));
source2Virtual->unblock();
mref->unblockRegisters();

mref->blockRegisters();
source1Virtual->block();
setSource2Register(machine->assignOneRegister(this, source2Virtual));
source1Virtual->unblock();
mref->unblockRegisters();

source1Virtual->block();
source2Virtual->block();
mref->assignRegisters(this, cg());
source2Virtual->unblock();
source1Virtual->unblock();

if (getDependencyConditions())
getDependencyConditions()->assignPreConditionRegisters(this->getPrev(), kindToBeAssigned, cg());
}

// TR::ARM64Trg1MemInstruction:: member functions

bool TR::ARM64Trg1MemInstruction::refsRegister(TR::Register *reg)
Expand Down
132 changes: 132 additions & 0 deletions compiler/aarch64/codegen/ARM64Instruction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ namespace TR { class SymbolReference; }

#define ARM64_INSTRUCTION_LENGTH 4

/*
* @brief Answers if the signed integer value can be placed in 7-bit field
* @param[in] intValue : signed integer value
* @return true if the value can be placed in 7-bit field, false otherwise
*/
inline bool constantIsImm7(int32_t intValue)
{
return (-64 <= intValue && intValue < 64);
}

/*
* @brief Answers if the signed integer value can be placed in 9-bit field
* @param[in] intValue : signed integer value
Expand Down Expand Up @@ -2567,6 +2577,128 @@ class ARM64MemSrc1Instruction : public ARM64MemInstruction
virtual int32_t estimateBinaryLength(int32_t currentEstimate);
};

class ARM64MemSrc2Instruction : public ARM64MemSrc1Instruction
{
TR::Register *_source2Register;

public:

/*
* @brief Constructor
* @param[in] op : instruction opcode
* @param[in] node : node
* @param[in] mr : memory reference
* @param[in] s1reg : source register 1
* @param[in] s2reg : source register 2
* @param[in] cg : CodeGenerator
*/
ARM64MemSrc2Instruction(TR::InstOpCode::Mnemonic op,
TR::Node *node,
TR::MemoryReference *mr,
TR::Register *s1reg,
TR::Register *s2reg,
TR::CodeGenerator *cg)
: ARM64MemSrc1Instruction(op, node, mr, s1reg, cg), _source2Register(s2reg)
{
useRegister(s2reg);
}

/*
* @brief Constructor
* @param[in] op : instruction opcode
* @param[in] node : node
* @param[in] mr : memory reference
* @param[in] s1reg : source register 1
* @param[in] s2reg : source register 2
* @param[in] precedingInstruction : preceding instruction
* @param[in] cg : CodeGenerator
*/
ARM64MemSrc2Instruction(TR::InstOpCode::Mnemonic op,
TR::Node *node,
TR::MemoryReference *mr,
TR::Register *s1reg,
TR::Register *s2reg,
TR::Instruction *precedingInstruction, TR::CodeGenerator *cg)
: ARM64MemSrc1Instruction(op, node, mr, s1reg, precedingInstruction, cg), _source2Register(s2reg)
{
useRegister(s2reg);
}

/**
* @brief Gets instruction kind
* @return instruction kind
*/
virtual Kind getKind() { return IsMemSrc2; }

/**
* @brief Gets source register 2
* @return source register 2
*/
TR::Register *getSource2Register() {return _source2Register;}

/**
* @brief Sets source register 2
* @param[in] sr : source register 2
* @return source register 2
*/
TR::Register *setSource2Register(TR::Register *sr) {return (_source2Register = sr);}

virtual TR::Snippet *getSnippetForGC() {return getMemoryReference()->getUnresolvedSnippet();}

/**
* @brief Sets source register 2 in binary encoding
* @param[in] instruction : instruction cursor
*/
void insertSource2Register(uint32_t *instruction)
{
TR::RealRegister *source2 = toRealRegister(_source2Register);
source2->setRegisterFieldRT2(instruction);
}

/**
* @brief Answers whether this instruction references the given virtual register
* @param[in] reg : virtual register
* @return true when the instruction references the virtual register
*/
virtual bool refsRegister(TR::Register *reg);
/**
* @brief Answers whether this instruction uses the given virtual register
* @param[in] reg : virtual register
* @return true when the instruction uses the virtual register
*/
virtual bool usesRegister(TR::Register *reg);
/**
* @brief Answers whether this instruction defines the given virtual register
* @param[in] reg : virtual register
* @return true when the instruction defines the virtual register
*/
virtual bool defsRegister(TR::Register *reg);
/**
* @brief Answers whether this instruction defines the given real register
* @param[in] reg : real register
* @return true when the instruction defines the real register
*/
virtual bool defsRealRegister(TR::Register *reg);
/**
* @brief Assigns registers
* @param[in] kindToBeAssigned : register kind
*/
virtual void assignRegisters(TR_RegisterKinds kindToBeAssigned);

/**
* @brief Generates binary encoding of the instruction
* @return instruction cursor
*/
virtual uint8_t *generateBinaryEncoding();

/**
* @brief Estimates binary length
* @param[in] currentEstimate : current estimated length
* @return estimated binary length
*/
virtual int32_t estimateBinaryLength(int32_t currentEstimate);
};

// for "store exclusive" instructions such as stxrx/stxrw
class ARM64Trg1MemSrc1Instruction : public ARM64Trg1MemInstruction
{
Expand Down
8 changes: 8 additions & 0 deletions compiler/aarch64/codegen/GenerateInstructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,14 @@ TR::Instruction *generateMemSrc1Instruction(TR::CodeGenerator *cg, TR::InstOpCod
return new (cg->trHeapMemory()) TR::ARM64MemSrc1Instruction(op, node, mr, sreg, cg);
}

TR::Instruction *generateMemSrc2Instruction(TR::CodeGenerator *cg, TR::InstOpCode::Mnemonic op, TR::Node *node,
TR::MemoryReference *mr, TR::Register *s1reg, TR::Register *s2reg, TR::Instruction *preced)
{
if (preced)
return new (cg->trHeapMemory()) TR::ARM64MemSrc2Instruction(op, node, mr, s1reg, s2reg, preced, cg);
return new (cg->trHeapMemory()) TR::ARM64MemSrc2Instruction(op, node, mr, s1reg, s2reg, cg);
}

TR::Instruction *generateTrg1MemSrc1Instruction(TR::CodeGenerator *cg, TR::InstOpCode::Mnemonic op, TR::Node *node,
TR::Register *treg, TR::MemoryReference *mr, TR::Register *sreg, TR::Instruction *preced)
{
Expand Down
20 changes: 20 additions & 0 deletions compiler/aarch64/codegen/GenerateInstructions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,26 @@ TR::Instruction *generateMemSrc1Instruction(
TR::Register *sreg,
TR::Instruction *preced = NULL);

/*
* @brief Generates src2-to-mem instruction
* @param[in] cg : CodeGenerator
* @param[in] op : instruction opcode
* @param[in] node : node
* @param[in] mr : memory reference
* @param[in] s1reg : source register 1
* @param[in] s2reg : source register 2
* @param[in] preced : preceding instruction
* @return generated instruction
*/
TR::Instruction *generateMemSrc2Instruction(
TR::CodeGenerator *cg,
TR::InstOpCode::Mnemonic op,
TR::Node *node,
TR::MemoryReference *mr,
TR::Register *s1reg,
TR::Register *s2reg,
TR::Instruction *preced = NULL);

/*
* @brief Generates "store exclusive" instruction
* @param[in] cg : CodeGenerator
Expand Down
3 changes: 2 additions & 1 deletion compiler/aarch64/codegen/OMRInstructionKindEnum.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2018, 2019 IBM Corp. and others
* Copyright (c) 2018, 2020 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
Expand Down Expand Up @@ -50,5 +50,6 @@
IsTrg1MemSrc1,
IsMem,
IsMemSrc1,
IsMemSrc2,
IsSrc1,
IsSrc2,
41 changes: 41 additions & 0 deletions compiler/aarch64/codegen/OMRMemoryReference.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,12 @@ static bool isImm12OffsetInstruction(uint32_t enc)
return ((enc & 0x3b200000) == 0x39000000);
}

/* stp/ldp GPR */
static bool isImm7OffsetGPRInstruction(uint32_t enc)
{
return ((enc & 0x3e000000) == 0x28000000);
}

/* load/store exclusive */
static bool isExclusiveMemAccessInstruction(TR::InstOpCode::Mnemonic op)
{
Expand Down Expand Up @@ -852,6 +858,24 @@ uint8_t *OMR::ARM64::MemoryReference::generateBinaryEncoding(TR::Instruction *cu
}
}
}
else if (isImm7OffsetGPRInstruction(enc))
{
uint32_t opc = ((enc >> 30) & 3); /* 32bit: 00, 64bit: 10 */
uint32_t size = ((opc >> 1) + 2);
uint32_t shifted = displacement >> size;

TR_ASSERT((displacement & ((1 << size) - 1)) == 0, "displacement must be 4/8-byte alligned");

if (constantIsImm7(shifted))
{
*wcursor |= (shifted & 0x7f) << 15; /* imm7 */
cursor += ARM64_INSTRUCTION_LENGTH;
}
else
{
TR_ASSERT_FATAL(false, "Offset is too large for specified instruction.");
}
}
else if (isExclusiveMemAccessInstruction(op.getMnemonic()))
{
TR_ASSERT(displacement == 0, "Offset must be zero for specified instruction.");
Expand Down Expand Up @@ -995,6 +1019,23 @@ uint32_t OMR::ARM64::MemoryReference::estimateBinaryLength(TR::InstOpCode op)
}
}
}
else if (isImm7OffsetGPRInstruction(enc))
{
uint32_t opc = ((enc >> 30) & 3); /* 32bit: 00, 64bit: 10 */
uint32_t size = ((opc >> 1) + 2);
uint32_t shifted = displacement >> size;

TR_ASSERT((displacement & ((1 << size) - 1)) == 0, "displacement must be 4/8-byte alligned");

if (constantIsImm7(shifted))
{
return ARM64_INSTRUCTION_LENGTH;
}
else
{
TR_ASSERT_FATAL(false, "Offset is too large for specified instruction.");
}
}
else if (isExclusiveMemAccessInstruction(op.getMnemonic()))
{
return ARM64_INSTRUCTION_LENGTH;
Expand Down
Loading

0 comments on commit 656748a

Please sign in to comment.