diff --git a/dyninstAPI/src/codegen-aarch64.C b/dyninstAPI/src/codegen-aarch64.C index c1aff0b69a..6f4f8c745b 100644 --- a/dyninstAPI/src/codegen-aarch64.C +++ b/dyninstAPI/src/codegen-aarch64.C @@ -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(); @@ -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: @@ -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(); @@ -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); diff --git a/dyninstAPI/src/codegen-aarch64.h b/dyninstAPI/src/codegen-aarch64.h index 275929fb7b..76725d548c 100644 --- a/dyninstAPI/src/codegen-aarch64.h +++ b/dyninstAPI/src/codegen-aarch64.h @@ -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); @@ -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); diff --git a/dyninstAPI/src/emit-aarch64.C b/dyninstAPI/src/emit-aarch64.C index 7925aa8d35..04b6ef0798 100644 --- a/dyninstAPI/src/emit-aarch64.C +++ b/dyninstAPI/src/emit-aarch64.C @@ -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); @@ -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 @@ -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
(gen, dest, 0x0); @@ -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); @@ -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
(gen, dest, 0x0); diff --git a/dyninstAPI/src/emit-aarch64.h b/dyninstAPI/src/emit-aarch64.h index 1ed50f2914..2eeae304a2 100644 --- a/dyninstAPI/src/emit-aarch64.h +++ b/dyninstAPI/src/emit-aarch64.h @@ -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 &); diff --git a/dyninstAPI/src/inst-aarch64.C b/dyninstAPI/src/inst-aarch64.C index 4f31a76da7..8ae39c0218 100644 --- a/dyninstAPI/src/inst-aarch64.C +++ b/dyninstAPI/src/inst-aarch64.C @@ -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: @@ -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; @@ -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 @@ -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;