Skip to content

Commit

Permalink
Fixing MOV instruction generation.
Browse files Browse the repository at this point in the history
Implementing store and restore register functions.
Fixed bug of stack pointer alignment.
emitCall - getting into shape.
emitR - first steps.
Some hard-coded values to be fixed, debug code and printing to be removed later.
  • Loading branch information
Sasha Nicolas (arm1) committed May 19, 2018
1 parent 9384918 commit 0f9e277
Show file tree
Hide file tree
Showing 13 changed files with 280 additions and 76 deletions.
2 changes: 1 addition & 1 deletion dyninstAPI/src/addressSpace.C
Expand Up @@ -1778,7 +1778,7 @@ bool AddressSpace::relocateInt(FuncSet::const_iterator begin, FuncSet::const_ite
(cm->ptr(),cm->size(),getArch());
Instruction::Ptr insn = deco.decode();
while(insn) {
#if defined(aarch64)
#if defined(arch_aarch64)
std::stringstream rawInsn;
unsigned idx = insn->size();
while(idx--) rawInsn << hex << setfill('0') << setw(2) << (unsigned int) insn->rawByte(idx);
Expand Down
9 changes: 6 additions & 3 deletions dyninstAPI/src/ast.C
Expand Up @@ -1930,15 +1930,17 @@ bool AstOperandNode::generateCode_phase2(codeGen &gen, bool noCost,
case FrameAddr:
addr = (Address) oValue;
temp = gen.rs()->allocateRegister(gen, noCost);
emitVload(loadFrameRelativeOp, addr, temp, retReg, gen, noCost, gen.rs(), size, gen.point(), gen.addrSpace());
emitVload(loadFrameRelativeOp, addr, temp, retReg, gen, noCost, gen.rs(),
size, gen.point(), gen.addrSpace());
gen.rs()->freeRegister(temp);
break;
case RegOffset:
// Prepare offset from value in any general register (not just fp).
// This AstNode holds the register number, and loperand holds offset.
assert(operand_);
addr = (Address) operand_->getOValue();
emitVload(loadRegRelativeOp, addr, (long)oValue, retReg, gen, noCost, gen.rs(), size, gen.point(), gen.addrSpace());
emitVload(loadRegRelativeOp, addr, (long)oValue, retReg, gen, noCost,
gen.rs(), size, gen.point(), gen.addrSpace());
break;
case ConstantString:
// XXX This is for the std::string type. If/when we fix the std::string type
Expand All @@ -1954,7 +1956,8 @@ bool AstOperandNode::generateCode_phase2(codeGen &gen, bool noCost,

if(!gen.addrSpace()->needsPIC())
{
emitVload(loadConstOp, addr, retReg, retReg, gen, noCost, gen.rs(), size, gen.point(), gen.addrSpace());
emitVload(loadConstOp, addr, retReg, retReg, gen, noCost, gen.rs(),
size, gen.point(), gen.addrSpace());
}
else
{
Expand Down
35 changes: 25 additions & 10 deletions dyninstAPI/src/codegen-aarch64.C
Expand Up @@ -61,7 +61,7 @@ codeBuf_t *insnCodeGen::ptrAndInc(codeGen &gen) {
}
#endif

void insnCodeGen::generate(codeGen &gen, instruction&insn) {
void insnCodeGen::generate(codeGen &gen, instruction &insn) {
#if defined(endian_mismatch)
// Writing an instruction. Convert byte order if necessary.
unsigned raw = swapBytesIfNeeded(insn.asInt());
Expand Down Expand Up @@ -125,15 +125,16 @@ void insnCodeGen::generateLongBranch(codeGen &gen,
Address to,
bool isCall)
{
Register scratch = 0;
Register scratch = REG_NULL;

instPoint *point = gen.point();
if(!point)
{
if(!isCall)
{
//scratch = 12; //#sasha test for springboard
scratch = gen.rs()->getScratchRegister(gen);
scratch = 14; //#sasha hard coding register for springboard
//scratch = gen.rs()->getScratchRegister(gen);
//assert(gen.rs());
}
else
{
Expand Down Expand Up @@ -471,7 +472,8 @@ Register insnCodeGen::moveValueToReg(codeGen &gen, long int val, pdvector<Regist
}

/* Currently, I'm only considering generation of only STR/LDR and their register/immediate variants.*/
void insnCodeGen::generateMemAccess32or64(codeGen &gen, LoadStore accType, Register r1, Register r2, int immd, bool is64bit)
void insnCodeGen::generateMemAccess32or64(codeGen &gen, LoadStore accType,
Register r1, Register r2, int immd, bool is64bit)
{
instruction insn;
insn.clear();
Expand Down Expand Up @@ -585,14 +587,27 @@ void insnCodeGen::loadImmIntoReg(codeGen &gen, Register rt, T value)
assert(value >= 0);

insnCodeGen::generateMove(gen, (value & 0xFFFF), 0, rt, MovOp_MOVZ);
if(value > MAX_IMM16)
if(value > 0xFFFF)
insnCodeGen::generateMove(gen, ((value >> 16) & 0xFFFF), 0x1, rt, MovOp_MOVK);
if(value > MAX_IMM32) {
if(value > 0xFFFFFFFF)
insnCodeGen::generateMove(gen, ((value >> 32) & 0xFFFF), 0x2, rt, MovOp_MOVK);
if(value > 0xFFFFFFFFFFFF)
insnCodeGen::generateMove(gen, ((value >> 48) & 0xFFFF), 0x3, rt, MovOp_MOVK);
}
}


void insnCodeGen::saveRegister(codeGen &gen, Register r)
{
generateMemAccess32or64(gen, insnCodeGen::Store, r, REG_SP, -2*GPRSIZE_64, true);
}


void insnCodeGen::restoreRegister(codeGen &gen, Register r)
{
generateMemAccess32or64(gen, insnCodeGen::Load, r, REG_SP, 2*GPRSIZE_64, true);
}


// Helper method. Fills register with partial value to be completed
// by an operation with a 16-bit signed immediate. Such as loads and
// stores.
Expand All @@ -618,8 +633,8 @@ bool insnCodeGen::generate(codeGen &gen,
AddressSpace * /*proc*/,
Address /*origAddr*/,
Address /*relocAddr*/,
patchTarget */*fallthroughOverride*/,
patchTarget */*targetOverride*/) {
patchTarget * /*fallthroughOverride*/,
patchTarget * /*targetOverride*/) {
assert(0 && "Deprecated!");
return false;
}
Expand Down
16 changes: 11 additions & 5 deletions dyninstAPI/src/codegen-aarch64.h
Expand Up @@ -98,11 +98,16 @@ class insnCodeGen {
static void generateMemAccess32or64(codeGen &gen, LoadStore accType,
Register r1, Register r2, int immd, bool is64bit);

static void generateMemAccessFP(codeGen &gen, LoadStore accType, Register rt, Register rn, int immd, int size, bool is128bit);
static void generateMemAccessFP(codeGen &gen, LoadStore accType, Register rt,
Register rn, int immd, int size, bool is128bit);

template<typename T>
static void loadImmIntoReg(codeGen &gen, Register rt, T value);

static void saveRegister(codeGen &gen, Register r);

static void restoreRegister(codeGen &gen, Register r);

/** TODO **/
static void generateLoadReg(codeGen &gen, Register rt,
Register ra, Register rb);
Expand Down Expand Up @@ -164,9 +169,10 @@ class insnCodeGen {

static void generateDiv(codeGen &gen, Register rm, Register rn, Register rd, bool is64bit);

static void generateBitwiseOpShifted(codeGen &gen, BitwiseOp op, int shift, Register rm, int imm6, Register rn, Register rd, bool is64bit);
static void generateBitwiseOpShifted(codeGen &gen, BitwiseOp op, int shift,
Register rm, int imm6, Register rn, Register rd, bool is64bit);

// This is for MOVK, MOVN, and MOVZ. For MOV use generateMoveToReg()
// This is for MOVK, MOVN, and MOVZ. For MOV use the other generateMove()
static void generateMove(codeGen &gen, int imm16, int shift, Register rd, MoveOp movOp);

// This is for MOV, which is an alias for ORR. See ARMv8 Documentation.
Expand All @@ -190,8 +196,8 @@ class insnCodeGen {

//TODO
// Routines to create/remove a new stack frame for getting scratch registers
static int
createStackFrame(codeGen &gen, int numRegs, pdvector <Register> &freeReg, pdvector <Register> &excludeReg);
static int createStackFrame(codeGen &gen, int numRegs, pdvector <Register> &freeReg,
pdvector <Register> &excludeReg);

//TODO
static void removeStackFrame(codeGen &gen);
Expand Down
36 changes: 29 additions & 7 deletions dyninstAPI/src/dynProcess.C
Expand Up @@ -1646,25 +1646,28 @@ Address PCProcess::inferiorMalloc(unsigned size, inferiorHeapType type,
for (ntry = 0; freeIndex == -1; ntry++) {
switch(ntry) {
case AsIs:
infmalloc_printf("%s[%d]: (1) AsIs\n", FILE__, __LINE__);
break;
//#if defined(cap_dynamic_heap)
case DeferredFree:
infmalloc_printf("%s[%d]: garbage collecting and compacting\n",
infmalloc_printf("%s[%d]: (2) garbage collecting and compacting\n",
FILE__, __LINE__);
inferiorFreeCompact();
break;
case NewSegment1MBConstrained:
infmalloc_printf("%s[%d]: inferiorMallocDynamic for %d (0x%x) bytes between 0x%lx - 0x%lx\n",
FILE__, __LINE__, HEAP_DYN_BUF_SIZE, HEAP_DYN_BUF_SIZE, lo, hi);
infmalloc_printf("%s[%d]: (3) inferiorMallocDynamic "
"for %d (0x%x) bytes between 0x%lx - 0x%lx\n", FILE__, __LINE__,
HEAP_DYN_BUF_SIZE, HEAP_DYN_BUF_SIZE, lo, hi);
inferiorMallocDynamic(HEAP_DYN_BUF_SIZE, lo, hi);
break;
case NewSegmentSizedConstrained:
infmalloc_printf("%s[%d]: inferiorMallocDynamic for %d (0x%x) bytes between 0x%lx - 0x%lx\n",
infmalloc_printf("%s[%d]: (4) inferiorMallocDynamic "
"for %d (0x%x) bytes between 0x%lx - 0x%lx\n",
FILE__, __LINE__, size, size, lo, hi);
inferiorMallocDynamic(size, lo, hi);
break;
case RemoveRangeConstraints:
infmalloc_printf("%s[%d]: inferiorMalloc: removing range constraints\n",
infmalloc_printf("%s[%d]: (5) inferiorMalloc: removing range constraints\n",
FILE__, __LINE__);
lo = ADDRESS_LO;
hi = ADDRESS_HI;
Expand All @@ -1674,12 +1677,12 @@ Address PCProcess::inferiorMalloc(unsigned size, inferiorHeapType type,
}
break;
case NewSegment1MBUnconstrained:
infmalloc_printf("%s[%d]: inferiorMallocDynamic for %d (0x%x) bytes between 0x%lx - 0x%lx\n",
infmalloc_printf("%s[%d]: (6) inferiorMallocDynamic for %d (0x%x) bytes between 0x%lx - 0x%lx\n",
FILE__, __LINE__, HEAP_DYN_BUF_SIZE, HEAP_DYN_BUF_SIZE, lo, hi);
inferiorMallocDynamic(HEAP_DYN_BUF_SIZE, lo, hi);
break;
case NewSegmentSizedUnconstrained:
infmalloc_printf("%s[%d]: inferiorMallocDynamic for %d (0x%x) bytes between 0x%lx - 0x%lx\n",
infmalloc_printf("%s[%d]: (7) inferiorMallocDynamic for %d (0x%x) bytes between 0x%lx - 0x%lx\n",
FILE__, __LINE__, size, size, lo, hi);
inferiorMallocDynamic(size, lo, hi);
break;
Expand Down Expand Up @@ -1970,6 +1973,25 @@ bool PCProcess::postIRPC(AstNodePtr action, void *userData,

irpcBuf.endTrackRegDefs();

//#sasha printing code patch for DYNINSTos_malloc
#if defined(arch_aarch64)
#include "InstructionDecoder.h"
using namespace Dyninst::InstructionAPI;
Address base = 0;
InstructionDecoder deco(irpcBuf.start_ptr(),irpcBuf.size(),getArch());
Instruction::Ptr insn = deco.decode();
while(base<300) {
std::stringstream rawInsn;
unsigned idx = insn->size();
while(idx--) rawInsn << hex << setfill('0') << setw(2) << (unsigned int) insn->rawByte(idx);

cerr << "\t" << hex << base << ": " << rawInsn.str() << " "
<< insn->format(base) << dec << endl;
base += insn->size();
insn = deco.decode();
}
#endif

return postIRPC_internal(irpcBuf.start_ptr(),
irpcBuf.used(),
breakOffset,
Expand Down
52 changes: 50 additions & 2 deletions dyninstAPI/src/emit-aarch64.C
Expand Up @@ -59,6 +59,25 @@
#include "dyninstAPI/src/emit-aarch64.h"
#include "dyninstAPI/src/registerSpace.h"

codeBufIndex_t EmitterAARCH64::emitIf(
Register expr_reg, Register target, RegControl /*rc*/, codeGen &gen)
{
instruction insn;
insn.clear();

// compare to 0 and branch
// register number, its value is compared to 0.
INSN_SET(insn, 0, 4, expr_reg);
INSN_SET(insn, 5, 23, (target+4)/4);
INSN_SET(insn, 25, 30, 0x1a); // CBZ
INSN_SET(insn, 31, 31, 1);

insnCodeGen::generate(gen,insn);

// Retval: where the jump is in this sequence
codeBufIndex_t retval = gen.getIndex();
return retval;
}

void EmitterAARCH64::emitLoadConst(Register dest, Address imm, codeGen &gen)
{
Expand All @@ -71,7 +90,7 @@ void EmitterAARCH64::emitLoad(Register dest, Address addr, int size, codeGen &ge
Register scratch = gen.rs()->getScratchRegister(gen);

insnCodeGen::loadImmIntoReg<Address>(gen, scratch, addr);
insnCodeGen::generateMemAccess32or64(gen, insnCodeGen::Load, dest, scratch, 0, false);
insnCodeGen::generateMemAccess32or64(gen, insnCodeGen::Load, dest, scratch, 0, true);

gen.rs()->freeRegister(scratch);
gen.markRegDefined(dest);
Expand All @@ -83,7 +102,7 @@ void EmitterAARCH64::emitStore(Address addr, Register src, int size, codeGen &ge
Register scratch = gen.rs()->getScratchRegister(gen);

insnCodeGen::loadImmIntoReg<Address>(gen, scratch, addr);
insnCodeGen::generateMemAccess32or64(gen, insnCodeGen::Store, src, scratch, 0, false);
insnCodeGen::generateMemAccess32or64(gen, insnCodeGen::Store, src, scratch, 0, true);

gen.rs()->freeRegister(scratch);
gen.markRegDefined(src);
Expand Down Expand Up @@ -141,6 +160,35 @@ void EmitterAARCH64::emitRelOp(
}


void EmitterAARCH64::emitGetParam(
Register dest, Register param_num,
instPoint::Type pt_type, opCode op,
bool addr_of, codeGen &gen)
{
registerSlot *regSlot = NULL;
switch (op) {
case getParamOp:
if(param_num <= 3) {
// param_num is 0..8 - it's a parameter number, not a register
regSlot = (*(gen.rs()))[registerSpace::r0 + param_num];
break;

} else {
assert(0);
}
break;
default:
assert(0);
break;
} // end of swich(op)

assert(regSlot);
Register reg = regSlot->number;

//return reg;
}





Expand Down
2 changes: 1 addition & 1 deletion dyninstAPI/src/emit-aarch64.h
Expand Up @@ -123,7 +123,7 @@ class EmitterAARCH64 : public Emitter {

virtual void emitGetRetAddr(Register, codeGen &) { assert(0); }

virtual void emitGetParam(Register, Register, instPoint::Type, opCode, bool, codeGen &) { assert(0); }
virtual void emitGetParam(Register, Register, instPoint::Type, opCode, bool, codeGen &);

virtual void emitASload(int, int, int, long, Register, int, codeGen &) { assert(0); }

Expand Down

0 comments on commit 0f9e277

Please sign in to comment.