Skip to content

Commit

Permalink
Implemented plus, minus and times operation in emitImm for ARM64.
Browse files Browse the repository at this point in the history
The plusOp, minusOp and timesOp cases for emitImm are implemented with
this commit. This also introduces three new methods in the codegen file:
* generateAddSubShifted - ADD/SUB (shifted variant)
* generateAddSubImmediate - ADD/SUB (immediate variant)
* generateMul - MUL
  • Loading branch information
ssunny7 committed Apr 3, 2017
1 parent b6608b6 commit 99fd772
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 33 deletions.
3 changes: 3 additions & 0 deletions common/src/arch-aarch64.h
Expand Up @@ -64,6 +64,9 @@ namespace NS_aarch64 {

#define ADDShiftOp 0x0B
#define ADDImmOp 0x11
#define SUBShiftOp 0x4B
#define SUBImmOp 0x51
#define MULOp 0xD8

#define STRImmOp 0x1C0
#define LDRImmOp 0x1C2
Expand Down
29 changes: 25 additions & 4 deletions dyninstAPI/src/codegen-aarch64.C
Expand Up @@ -185,15 +185,15 @@ void insnCodeGen::generateBranchViaTrap(codeGen &gen, Address from, Address to,
}
}

void insnCodeGen::generateAddShifted(codeGen &gen, int shift, int imm6, Register rm, Register rn, Register rd, bool is64bit) {
void insnCodeGen::generateAddSubShifted(codeGen &gen, insnCodeGen::AddSubOp op, int shift, int imm6, Register rm, Register rn, Register rd, bool is64bit) {
instruction insn;
insn.clear();

//Set bit 31 to 1 if using 64-bit registers
if(is64bit)
INSN_SET(insn, 31, 31, 1);
//Set opcode
INSN_SET(insn, 24, 30, ADDShiftOp);
INSN_SET(insn, 24, 30, op == Add ? ADDShiftOp : SUBShiftOp);

//Set shift field
assert(shift >= 0 && shift <= 3);
Expand All @@ -211,15 +211,15 @@ void insnCodeGen::generateAddShifted(codeGen &gen, int shift, int imm6, Register
insnCodeGen::generate(gen, insn);
}

void insnCodeGen::generateAddImmediate(codeGen &gen, int shift, int imm12, Register rn, Register rd, bool is64bit) {
void insnCodeGen::generateAddSubImmediate(codeGen &gen, insnCodeGen::AddSubOp op, int shift, int imm12, Register rn, Register rd, bool is64bit) {
instruction insn;
insn.clear();

//Set bit 31 to 1 if using 64-bit registers
if(is64bit)
INSN_SET(insn, 31, 31, 1);
//Set opcode
INSN_SET(insn, 24, 30, ADDImmOp);
INSN_SET(insn, 24, 30, op == Add ? ADDImmOp : SUBShiftOp);

//Set shift field
assert(shift >= 0 && shift <= 3);
Expand All @@ -235,6 +235,27 @@ void insnCodeGen::generateAddImmediate(codeGen &gen, int shift, int imm12, Regis
insnCodeGen::generate(gen, insn);
}

void insnCodeGen::generateMul(codeGen &gen, Register rm, Register rn, Register rd, bool is64bit) {
instruction insn;
insn.clear();

//Set bit 31 to 1 if using 64-bit registers
if(is64bit)
INSN_SET(insn, 31, 31, 1);
//Set opcode
INSN_SET(insn, 21, 28, MULOp);

//Bits 10 to 14 are 1 for MUL
INSN_SET(insn, 10, 14, 0x1F);

//Set registers
INSN_SET(insn, 16, 20, rm);
INSN_SET(insn, 5, 9, rn);
INSN_SET(insn, 0, 4, rd);

insnCodeGen::generate(gen, insn);
}

void insnCodeGen::generateLoadReg(codeGen &gen, Register rt,
Register ra, Register rb)
{
Expand Down
11 changes: 9 additions & 2 deletions dyninstAPI/src/codegen-aarch64.h
Expand Up @@ -49,6 +49,11 @@ class insnCodeGen {
Store
};

enum AddSubOp {
Add,
Sub
};

static instructUnion *insnPtr(codeGen &gen);
//static instructUnion *ptrAndInc(codeGen &gen);

Expand Down Expand Up @@ -140,9 +145,11 @@ class insnCodeGen {

/** *** **/

static void generateAddShifted(codeGen &gen, int shift, int imm6, Register rm, Register rn, Register rd, bool is64bit);
static void generateAddSubShifted(codeGen &gen, AddSubOp op, int shift, int imm6, Register rm, Register rn, Register rd, bool is64bit);

static void generateAddSubImmediate(codeGen &gen, AddSubOp op, int shift, int imm12, Register rn, Register rd, bool is64bit);

static void generateAddImmediate(codeGen &gen, int shift, int imm12, Register rn, Register rd, bool is64bit);
static void generateMul(codeGen &gen, Register rm, Register rn, Register rd, bool is64bit);

static void generateMove(codeGen &gen, int imm16, int shift, Register rd, MoveOp movOp);

Expand Down
71 changes: 44 additions & 27 deletions dyninstAPI/src/inst-aarch64.C
Expand Up @@ -430,10 +430,50 @@ bool baseTramp::generateRestores(codeGen &gen,

/***********************************************************************************************/
/***********************************************************************************************/
Register moveValueToReg(codeGen &gen, RegValue val) {
Register scratchReg = gen.rs()->getScratchRegister(gen, true);

void emitImm(opCode op, Register src1, RegValue src2imm, Register dest,
codeGen &gen, bool noCost, registerSpace * /* rs */) {
assert(0); //Not implemented
if (scratchReg == REG_NULL) {
fprintf(stderr, " %s[%d] No scratch register available to generate add instruction!", FILE__, __LINE__);
assert(0);
}

insnCodeGen::generateMove(gen, (val & 0xFFFF), 0, scratchReg, insnCodeGen::MovOp_MOVZ);
if (val >= MIN_IMM32 && val < MAX_IMM32)
insnCodeGen::generateMove(gen, ((val >> 16) & 0xFFFF), 0x1, scratchReg, insnCodeGen::MovOp_MOVK);
if (val < MIN_IMM32 || val > MAX_IMM32) {
insnCodeGen::generateMove(gen, ((val >> 32) & 0xFFFF), 0x2, scratchReg, insnCodeGen::MovOp_MOVK);
insnCodeGen::generateMove(gen, ((val >> 48) & 0xFFFF), 0x3, scratchReg, insnCodeGen::MovOp_MOVK);
}

return scratchReg;
}

//TODO: 32-/64-bit regs?
void emitImm(opCode op, Register src1, RegValue src2imm, Register dest, codeGen &gen, bool noCost, registerSpace * /* rs */) {
switch(op) {
case plusOp:
case minusOp: {
if(src2imm >= -(1 << 11) && src2imm < (long int)((1 << 11) - 1))
insnCodeGen::generateAddSubImmediate(gen, op == plusOp ? insnCodeGen::Add : insnCodeGen::Sub, 0, src2imm, src1, dest, false);
else if(src2imm >= MIN_IMM16 && src2imm < MAX_IMM16) {
Register rm = moveValueToReg(gen, src2imm);
insnCodeGen::generateAddSubShifted(gen, op == plusOp ? insnCodeGen::Add : insnCodeGen::Sub, 0, 0, rm, src1, dest, true);
}
}
break;
case timesOp: {
Register rm = moveValueToReg(src2imm);
insnCodeGen::generateMul(gen, rm, src1, dest, true);
}
break;
case divOp:
break;
case orOp:
break;
case andOp:
break;
}
}

void cleanUpAndExit(int status);
Expand Down Expand Up @@ -472,28 +512,6 @@ bool EmitterAARCH64::clobberAllFuncCall(registerSpace *rs,
return false;
}


//
// Author: Jeff Hollingsworth (3/26/96)
//
// Emit a function call.
// It saves registers as needed.
// copy the passed arguments into the canonical argument registers (r3-r10)
// 64-bit ELF Linux ONLY:
// Locate the TOC entry of the callee module and copy it into R2
// generate a branch and link the destination
// 64-bit ELF Linux ONLY:
// Restore the original TOC into R2
// restore the saved registers.
//
// Parameters:
// op - unused parameter (to be compatible with sparc)
// srcs - vector of ints indicating the registers that contain the parameters
// dest - the destination address (should be Address not reg).
// insn - pointer to the code we are generating
// based - offset into the code generated.
//

Register emitFuncCall(opCode, codeGen &, pdvector <AstNodePtr> &, bool, Address) {
assert(0);
return 0;
Expand All @@ -503,8 +521,7 @@ Register emitFuncCall(opCode op,
codeGen &gen,
pdvector <AstNodePtr> &operands, bool noCost,
func_instance *callee) {
assert(0); //Not implemented
return 0;
return gen.emitter()->emitCall(op, gen, operands, noCost, callee);
}

Register EmitterAARCH64::emitCallReplacement(opCode ocode,
Expand Down

0 comments on commit 99fd772

Please sign in to comment.