Skip to content

Commit

Permalink
Fix 64-bit sign/unsigned comparison, multi, and division on ARM
Browse files Browse the repository at this point in the history
  • Loading branch information
mxz297 committed Dec 7, 2018
1 parent ca0e8f3 commit 1708493
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 31 deletions.
24 changes: 16 additions & 8 deletions dyninstAPI/src/codegen-aarch64.C
Expand Up @@ -218,7 +218,7 @@ void insnCodeGen::generateBranchViaTrap(codeGen &gen, Address from, Address to,
}
}

void insnCodeGen::generateConditionalBranch(codeGen& gen, Address to, unsigned opcode)
void insnCodeGen::generateConditionalBranch(codeGen& gen, Address to, unsigned opcode, bool s)
{
instruction insn;
insn.clear();
Expand All @@ -229,13 +229,17 @@ void insnCodeGen::generateConditionalBranch(codeGen& gen, Address to, unsigned o
//Set imm19 field
INSN_SET(insn, 5, 23, to >> 2);

auto getConditionCode = [&opcode]() -> unsigned
auto getConditionCode = [&opcode, &s]() -> unsigned
{
switch(opcode){
case lessOp: return 0xB;
case leOp: return 0xD;
case greaterOp: return 0xC;
case geOp: return 0xA;
case lessOp:
if (s) return 0xB; else return 0x3;
case leOp:
if (s) return 0xD; else return 0x9;
case greaterOp:
if (s) return 0xC; else return 0x8;
case geOp:
if (s) return 0xA; else return 0x2;
case eqOp: return 0x0;
case neOp: return 0x1;
default:
Expand Down Expand Up @@ -329,7 +333,7 @@ void insnCodeGen::generateMul(codeGen &gen, Register rm, Register rn, Register r

//#sasha is rm or rn the denominator?
void insnCodeGen::generateDiv(
codeGen &gen, Register rm, Register rn, Register rd, bool is64bit)
codeGen &gen, Register rm, Register rn, Register rd, bool is64bit, bool s)
{
instruction insn;
insn.clear();
Expand All @@ -342,7 +346,11 @@ void insnCodeGen::generateDiv(
INSN_SET(insn, 21, 30, SDIVOp);

INSN_SET(insn, 11, 15, 0x1);
INSN_SET(insn, 10, 10, 0x0); // signed: SDIV
if (s) {
INSN_SET(insn, 10, 10, 0x1); // signed: SDIV
} else {
INSN_SET(insn, 10, 10, 0x0); // unsigned: UDIV
}

//Set registers
INSN_SET(insn, 16, 20, rm);
Expand Down
4 changes: 2 additions & 2 deletions dyninstAPI/src/codegen-aarch64.h
Expand Up @@ -99,7 +99,7 @@ class insnCodeGen {
bool isCall);

// Generate conditional branch
static void generateConditionalBranch(codeGen& gen, Address to, unsigned opcode);
static void generateConditionalBranch(codeGen& gen, Address to, unsigned opcode, bool s);

static void generateMemAccess32or64(codeGen &gen, LoadStore accType, Register r1,
Register r2, int immd, bool is64bit, IndexMode im=Post);
Expand Down Expand Up @@ -173,7 +173,7 @@ class insnCodeGen {

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

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

static void generateBitwiseOpShifted(codeGen &gen, BitwiseOp op, int shift,
Register rm, int imm6, Register rn, Register rd, bool is64bit);
Expand Down
14 changes: 4 additions & 10 deletions dyninstAPI/src/emit-aarch64.C
Expand Up @@ -124,12 +124,6 @@ void EmitterAARCH64::emitOp(
else if( opcode == minusOp )
insnCodeGen::generateAddSubShifted(gen, insnCodeGen::Sub, 0, 0, src2, src1, dest, true);

// dest = src1 / src2
else if( opcode == divOp ){
insnCodeGen::generateDiv(gen, src2, src1, dest, true);
//insnCodeGen::generateTrap(gen);
}

// dest = src1 * src2
else if( opcode == timesOp )
insnCodeGen::generateMul(gen, src1, src2, dest, true);
Expand All @@ -151,7 +145,7 @@ void EmitterAARCH64::emitOp(


void EmitterAARCH64::emitRelOp(
unsigned opcode, Register dest, Register src1, Register src2, codeGen &gen)
unsigned opcode, Register dest, Register src1, Register src2, codeGen &gen, bool s)
{
// CMP is an alias to SUBS;
// dest here has src1-src2, which it's not important because the flags are
Expand All @@ -165,7 +159,7 @@ void EmitterAARCH64::emitRelOp(

// insert conditional jump to skip dest=0 in case the comparison resulted true
// therefore keeping dest=1
insnCodeGen::generateConditionalBranch(gen, 8, opcode);
insnCodeGen::generateConditionalBranch(gen, 8, opcode, s);

// make dest = 0, in case it fails the branch
insnCodeGen::loadImmIntoReg<Address>(gen, dest, 0x0);
Expand Down Expand Up @@ -203,7 +197,7 @@ void EmitterAARCH64::emitGetParam(


void EmitterAARCH64::emitRelOpImm(
unsigned opcode, Register dest, Register src1, RegValue src2imm, codeGen &gen)
unsigned opcode, Register dest, Register src1, RegValue src2imm, codeGen &gen, bool s)
{
//Register src2 = gen.rs()->allocateRegister(gen, true);
Register src2 = gen.rs()->getScratchRegister(gen);
Expand All @@ -221,7 +215,7 @@ void EmitterAARCH64::emitRelOpImm(

// insert conditional jump to skip dest=0 in case the comparison resulted true
// therefore keeping dest=1
insnCodeGen::generateConditionalBranch(gen, 8, opcode);
insnCodeGen::generateConditionalBranch(gen, 8, opcode, s);

// make dest = 0, in case it fails the branch
insnCodeGen::loadImmIntoReg<Address>(gen, dest, 0x0);
Expand Down
10 changes: 5 additions & 5 deletions dyninstAPI/src/emit-aarch64.h
Expand Up @@ -59,15 +59,15 @@ class EmitterAARCH64 : public Emitter {
virtual void emitOpImm(unsigned, unsigned, Register, Register, RegValue,
codeGen &) { assert(0); }

virtual void emitRelOp(unsigned, Register, Register, Register, codeGen &);
virtual void emitRelOp(unsigned, Register, Register, Register, codeGen &, bool);

virtual void emitRelOpImm(unsigned, Register, Register, RegValue, codeGen &);
virtual void emitRelOpImm(unsigned, Register, Register, RegValue, codeGen &, bool);

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

virtual void emitTimesImm(Register, Register, RegValue, codeGen &) { assert(0); }
virtual void emitTimesImm(Register, Register, RegValue, codeGen &, bool) { assert(0); }

virtual void emitDivImm(Register, Register, RegValue, codeGen &) { assert(0); }
virtual void emitDivImm(Register, Register, RegValue, codeGen &, bool) { assert(0); }

virtual void emitLoad(Register, Address, int, codeGen &);

Expand Down
14 changes: 8 additions & 6 deletions dyninstAPI/src/inst-aarch64.C
Expand Up @@ -458,7 +458,7 @@ bool baseTramp::generateRestores(codeGen &gen, registerSpace *)

//TODO: 32-/64-bit regs?
void emitImm(opCode op, Register src1, RegValue src2imm, Register dest,
codeGen &gen, bool /*noCost*/, registerSpace * /* rs */)
codeGen &gen, bool /*noCost*/, registerSpace * /* rs */, bool s)
{
switch(op) {
case plusOp:
Expand All @@ -480,7 +480,7 @@ void emitImm(opCode op, Register src1, RegValue src2imm, Register dest,
case divOp:
{
Register rm = insnCodeGen::moveValueToReg(gen, src2imm);
insnCodeGen::generateDiv(gen, rm, src1, dest, true);
insnCodeGen::generateDiv(gen, rm, src1, dest, true, s);
//insnCodeGen::generateTrap(gen);
}
break;
Expand Down Expand Up @@ -516,7 +516,7 @@ void emitImm(opCode op, Register src1, RegValue src2imm, Register dest,
case geOp:
// note that eqOp could be grouped here too.
// There's two ways to implement this.
gen.codeEmitter()->emitRelOpImm(op, dest, src1, src2imm, gen);
gen.codeEmitter()->emitRelOpImm(op, dest, src1, src2imm, gen, s);
return;
default:
assert(0); // not implemented or not valid
Expand Down Expand Up @@ -871,25 +871,27 @@ void emitVstore(opCode op, Register src1, Register /*src2*/, Address dest,
void emitV(opCode op, Register src1, Register src2, Register dest,
codeGen &gen, bool /*noCost*/,
registerSpace * /*rs*/, int size,
const instPoint * /* location */, AddressSpace *proc)
const instPoint * /* location */, AddressSpace *proc, bool s)
{
switch(op){
case plusOp:
case minusOp:
case divOp:
case timesOp:
case orOp:
case andOp:
case xorOp:
gen.codeEmitter()->emitOp(op, dest, src1, src2, gen);
break;
case divOp:
insnCodeGen::generateDiv(gen, src2, src1, dest, true, s);
break;
case lessOp:
case leOp:
case greaterOp:
case geOp:
case eqOp:
case neOp:
gen.codeEmitter()->emitRelOp(op, dest, src1, src2, gen);
gen.codeEmitter()->emitRelOp(op, dest, src1, src2, gen, s);
break;
case loadIndirOp:
size = !size ? proc->getAddressWidth() : size;
Expand Down

0 comments on commit 1708493

Please sign in to comment.