x86
Version:
Generates x86_64 native code from assembly instructions
128 lines (127 loc) • 5.26 kB
JavaScript
;
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var code = require('./code');
var o = require('./operand');
var def_1 = require('./def');
var i = require('./instruction');
var p = require('./parts');
var util_1 = require('./util');
var x64;
(function (x64) {
var defDefaults = {
size: 32,
addrSize: 64,
};
function insdef(defs) {
return new def_1.Definition(util_1.extend({}, defDefaults, defs));
}
var INC = insdef({ op: 0xFF, opreg: 0 });
var DEC = insdef({ op: 0xFF, opreg: 1 });
var Instruction = (function (_super) {
__extends(Instruction, _super);
function Instruction() {
_super.apply(this, arguments);
this.prefixRex = null;
}
Instruction.prototype.writePrefixes = function (arr) {
_super.prototype.writePrefixes.call(this, arr);
if (this.prefixRex)
this.prefixRex.write(arr);
};
Instruction.prototype.needsOperandSizeChange = function () {
return (this.def.size == 32 /* DOUBLE */) && this.hasRegisterOfSize(64 /* QUAD */);
};
Instruction.prototype.createPrefixes = function () {
_super.prototype.createPrefixes.call(this);
if (this.def.mandatoryRex || this.needsOperandSizeChange() || this.hasExtendedRegister())
this.prefixRex = this.createRex();
};
Instruction.prototype.createRex = function () {
var W = 0, R = 0, X = 0, B = 0;
if (this.needsOperandSizeChange())
W = 1;
var _a = this.op, dst = _a.dst, src = _a.src;
if (dst && dst.reg() && dst.reg().isExtended())
R = 1;
if (src && src.reg() && src.reg().isExtended())
B = 1;
var mem = this.getMemoryOperand();
if (mem) {
if (mem.base && mem.base.isExtended())
B = 1;
if (mem.index && mem.index.isExtended())
X = 1;
}
// if(!this.regToRegDirectionRegIsDst) [R, B] = [B, R];
return new p.PrefixRex(W, R, X, B);
};
return Instruction;
}(i.Instruction));
x64.Instruction = Instruction;
var Code = (function (_super) {
__extends(Code, _super);
function Code() {
_super.apply(this, arguments);
this.ClassInstruction = Instruction;
this.mode = code.MODE.LONG;
}
Code.prototype.incq = function (operand) {
return this.insert(INC, this.createOperands(operand));
};
Code.prototype.decq = function (operand) {
return this.insert(DEC, this.createOperands(operand));
};
return Code;
}(code.Code));
x64.Code = Code;
// Generates logically equivalent code to `Instruction` but the actual
// bytes of the machine code will likely differ, because `FuzzyInstruction`
// picks at random one of the possible instructions when multiple instructions
// can perform the same operation. Here are some examples:
//
// - Bits in `REX` prefix are ignored if they don't have an effect on the instruction.
// - Register-to-register `MOV` instruction can be encoded in two different ways.
// - Up to four prefixes may be added to instruction, if they are not used, they are ignored.
// - There can be many different *no-op* instruction that are used to fill in padding, for example:
//
// mov %rax, %rax
// add $0, %rax
var FuzzyInstruction = (function (_super) {
__extends(FuzzyInstruction, _super);
function FuzzyInstruction() {
_super.apply(this, arguments);
this.regToRegDirectionRegIsDst = !(Math.random() > 0.5);
}
FuzzyInstruction.prototype.oneOrZero = function () {
return Math.random() > 0.5 ? 1 : 0;
};
// Randomize unused bits in REX byte.
FuzzyInstruction.prototype.createRex = function (dstreg, dstmem, srcreg, srcmem) {
var rex = _super.prototype.createRex.call(this, dstreg, dstmem, srcreg, srcmem);
if (!dstmem && !srcmem) {
rex.X = this.oneOrZero();
if (!srcreg)
rex.B = this.oneOrZero();
}
return rex;
};
return FuzzyInstruction;
}(Instruction));
x64.FuzzyInstruction = FuzzyInstruction;
var FuzzyCode = (function (_super) {
__extends(FuzzyCode, _super);
function FuzzyCode() {
_super.apply(this, arguments);
this.ClassInstruction = FuzzyInstruction;
}
FuzzyCode.prototype.nop = function (size) {
if (size === void 0) { size = 1; }
};
return FuzzyCode;
}(Code));
x64.FuzzyCode = FuzzyCode;
})(x64 = exports.x64 || (exports.x64 = {}));