New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

ass-js

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ass-js - npm Package Compare versions

Comparing version 1.0.2 to 1.0.3

abi.js

228

code.js

@@ -7,26 +7,2 @@ "use strict";

var util_1 = require('./util');
var Symbol = (function () {
function Symbol() {
}
return Symbol;
}());
exports.Symbol = Symbol;
var Block = (function () {
function Block() {
}
return Block;
}());
exports.Block = Block;
var Section = (function () {
function Section() {
}
return Section;
}());
exports.Section = Section;
var Assembler = (function () {
function Assembler() {
}
return Assembler;
}());
exports.Assembler = Assembler;
var Code = (function () {

@@ -39,11 +15,133 @@ function Code(start) {

this.ClassInstruction = i.Instruction;
this.ClassInstructionSet = i.InstructionSet;
this.ClassOperands = o.Operands;
this.AlignExpression = i.Align;
this.littleEndian = true;
this.methods = {};
this.label(start);
}
Code.prototype.addMethods = function () {
util_1.extend(this, this.methods);
Code.prototype.matchDefinitions = function (mnemonic, ops, opts) {
var matches = this.table.matchDefinitions(mnemonic, ops, opts);
if (!matches.list.length)
throw Error("Could not match operands to instruction definition " + mnemonic + ".");
return matches;
};
Code.prototype._ = function (mnemonic, operands, options) {
if (operands === void 0) { operands = []; }
if (options === void 0) { options = { size: o.SIZE.ANY }; }
if (typeof mnemonic !== 'string')
throw TypeError('`mnemonic` argument must be a string.');
var opts;
if (typeof options === 'number') {
opts = { size: options };
}
else if (typeof options === 'object') {
opts = options;
}
else
throw TypeError("options must be a number or object.");
if (typeof opts.size === 'undefined')
opts.size = o.SIZE.ANY;
if (!(operands instanceof Array))
operands = [operands];
var ops = new this.ClassOperands(operands, opts.size);
ops.normalizeExpressionToRelative();
var matches = this.matchDefinitions(mnemonic, ops, opts);
var iset = new this.ClassInstructionSet(ops, matches, opts);
this.insert(iset);
var insn = iset.pickShortestInstruction();
if (insn) {
this.replace(insn, iset.index);
return insn;
}
else
return iset;
};
Code.prototype._8 = function (mnemonic) {
var operands = [];
for (var _i = 1; _i < arguments.length; _i++) {
operands[_i - 1] = arguments[_i];
}
return this._(mnemonic, operands, 8);
};
Code.prototype._16 = function (mnemonic) {
var operands = [];
for (var _i = 1; _i < arguments.length; _i++) {
operands[_i - 1] = arguments[_i];
}
return this._(mnemonic, operands, 16);
};
Code.prototype._32 = function (mnemonic) {
var operands = [];
for (var _i = 1; _i < arguments.length; _i++) {
operands[_i - 1] = arguments[_i];
}
return this._(mnemonic, operands, 32);
};
Code.prototype._64 = function (mnemonic) {
var operands = [];
for (var _i = 1; _i < arguments.length; _i++) {
operands[_i - 1] = arguments[_i];
}
return this._(mnemonic, operands, 64);
};
Code.prototype._128 = function (mnemonic) {
var operands = [];
for (var _i = 1; _i < arguments.length; _i++) {
operands[_i - 1] = arguments[_i];
}
return this._(mnemonic, operands, 128);
};
Code.prototype._256 = function (mnemonic) {
var operands = [];
for (var _i = 1; _i < arguments.length; _i++) {
operands[_i - 1] = arguments[_i];
}
return this._(mnemonic, operands, 256);
};
Code.prototype._512 = function (mnemonic) {
var operands = [];
for (var _i = 1; _i < arguments.length; _i++) {
operands[_i - 1] = arguments[_i];
}
return this._(mnemonic, operands, 512);
};
Code.prototype.exportMethods = function (useNumbers, sizes, obj) {
var _this = this;
if (useNumbers === void 0) { useNumbers = false; }
if (sizes === void 0) { sizes = [o.SIZE.B, o.SIZE.W, o.SIZE.D, o.SIZE.Q]; }
if (obj === void 0) { obj = {}; }
var _loop_1 = function(mnemonic) {
obj[mnemonic] = function () {
var operands = [];
for (var _i = 0; _i < arguments.length; _i++) {
operands[_i - 0] = arguments[_i];
}
return _this._(mnemonic, operands);
};
var _loop_2 = function(size) {
var method = useNumbers ? mnemonic + size : mnemonic + o.SIZE[size].toLowerCase();
obj[method] = function () {
var operands = [];
for (var _i = 0; _i < arguments.length; _i++) {
operands[_i - 0] = arguments[_i];
}
return _this._(mnemonic, operands, size);
};
};
for (var _i = 0, sizes_1 = sizes; _i < sizes_1.length; _i++) {
var size = sizes_1[_i];
_loop_2(size);
}
};
for (var mnemonic in this.table.table) {
_loop_1(mnemonic);
}
return obj;
};
Code.prototype.addMethods = function (useNumbers, sizes, obj) {
if (useNumbers === void 0) { useNumbers = false; }
if (sizes === void 0) { sizes = [o.SIZE.B, o.SIZE.W, o.SIZE.D, o.SIZE.Q]; }
if (obj === void 0) { obj = this.exportMethods(useNumbers, sizes); }
util_1.extend(this, obj);
};
Code.prototype.getStartLabel = function () {

@@ -65,35 +163,2 @@ return this.expr[0];

};
Code.prototype.compile = function () {
this.do2ndPass();
return this.do3rdPass();
};
Code.prototype.do2ndPass = function () {
var last = this.expr[this.expr.length - 1];
var all_offsets_known = last.offset >= 0;
var all_sizes_known = last.bytes() >= 0;
if (all_offsets_known && all_sizes_known)
return;
var prev = this.expr[0];
prev.offset = 0;
for (var j = 1; j < this.expr.length; j++) {
var ins = this.expr[j];
if (ins instanceof i.ExpressionVolatile) {
var fixed = ins.getFixedSizeExpression();
this.replace(fixed, ins.index);
ins = fixed;
}
ins.calcOffset();
prev = ins;
}
};
Code.prototype.do3rdPass = function () {
var code = [];
for (var _i = 0, _a = this.expr; _i < _a.length; _i++) {
var ins = _a[_i];
if (ins instanceof i.ExpressionVariable)
ins.evaluate();
code = ins.write(code);
}
return code;
};
Code.prototype.lbl = function (name) {

@@ -207,4 +272,17 @@ return new instruction_1.Label(name);

if (littleEndian === void 0) { littleEndian = this.littleEndian; }
return this.db(instruction_1.Data.quadsToOctets(quads, littleEndian));
var tnums;
if (typeof quads === 'number')
tnums = [quads];
else
tnums = quads;
for (var j = 0; j < tnums.length; j++) {
var num = tnums[j];
if (typeof num === 'number')
tnums[j] = [util_1.UInt64.lo(num), util_1.UInt64.hi(num)];
}
return this.db(instruction_1.Data.quadsToOctets(tnums, littleEndian));
};
Code.prototype.tpl = function (Clazz, args) {
return this.insert(new Clazz(args));
};
Code.prototype.resb = function (length) {

@@ -270,2 +348,30 @@ var data = new instruction_1.DataUninitialized(length);

};
Code.prototype.compile = function () {
this.do2ndPass();
return this.do3rdPass();
};
Code.prototype.do2ndPass = function () {
var prev = this.expr[0];
prev.offset = 0;
for (var j = 1; j < this.expr.length; j++) {
var ins = this.expr[j];
if (ins instanceof i.ExpressionVolatile) {
var fixed = ins.getFixedSizeExpression();
this.replace(fixed, ins.index);
ins = fixed;
}
ins.calcOffset();
prev = ins;
}
};
Code.prototype.do3rdPass = function () {
var code = [];
for (var _i = 0, _a = this.expr; _i < _a.length; _i++) {
var ins = _a[_i];
if (ins instanceof i.ExpressionVariable)
ins.evaluate();
code = ins.write(code);
}
return code;
};
Code.prototype.toString = function (lineNumbers, hex) {

@@ -272,0 +378,0 @@ if (lineNumbers === void 0) { lineNumbers = true; }

@@ -9,14 +9,7 @@ import {SIZE, number64, Tnumber, Operands} from './operand';

export class Symbol {}
export class Block {}
export class Section {}
export class Assembler {}
export interface IInstructionOptions {
size: o.SIZE;
}
// Expressions are compiled in 3 passes:
//
// - *1st pass* -- maximum offset `maxOffset` for each expression is computed, some expression might not know
// their size jet, not all expressions are known, future references. First pass is when user performs insertion of commands.
// - *2nd pass* -- all expressions known now, each expression should pick its right size, exact `offset` is computed for each expression.
// - *3rd pass* -- now we know exact `offset` of each expression, so in this pass we fill in the addresses.
export class Code {

@@ -29,2 +22,3 @@ expr: Expression[] = [];

ClassInstruction = i.Instruction;
ClassInstructionSet = i.InstructionSet;
ClassOperands = o.Operands;

@@ -35,6 +29,3 @@ AlignExpression = i.Align;

// Collection of all assembly instructions: mov, push, ret, retq, etc...
// When needed `addMethods()` adds these funcitons to the `Code` object,
// some segments, for example, data segment may not need these methods.
methods: any = {};
table: d.DefTable;

@@ -45,85 +36,103 @@ constructor(start: string = 'start') {

addMethods() {
extend(this, this.methods);
protected matchDefinitions(mnemonic: string, ops: o.Operands, opts: IInstructionOptions): d.DefMatchList {
var matches = this.table.matchDefinitions(mnemonic, ops, opts);
if(!matches.list.length)
throw Error(`Could not match operands to instruction definition ${mnemonic}.`);
return matches;
}
getStartLabel(): Label {
return this.expr[0] as Label;
_(mnemonic: string, operands: o.TUiOperand|o.TUiOperand[] = [], options: o.SIZE|IInstructionOptions|any = {size: o.SIZE.ANY}): i.Instruction|i.InstructionSet {
if(typeof mnemonic !== 'string') throw TypeError('`mnemonic` argument must be a string.');
var opts: IInstructionOptions;
if(typeof options === 'number') {
opts = {size: options as number};
} else if(typeof options === 'object') {
opts = options;
} else
throw TypeError(`options must be a number or object.`);
if(typeof opts.size === 'undefined') opts.size = o.SIZE.ANY;
if(!(operands instanceof Array)) operands = [operands] as o.TUiOperand[];
var ops = new this.ClassOperands(operands as o.TUiOperand[], opts.size);
ops.normalizeExpressionToRelative();
var matches = this.matchDefinitions(mnemonic, ops, opts);
var iset = new this.ClassInstructionSet(ops, matches, opts);
this.insert(iset);
var insn = iset.pickShortestInstruction();
if(insn) {
this.replace(insn, iset.index);
return insn;
} else
return iset;
}
insert(expr: Expression): Expression {
this.replace(expr, this.expr.length);
expr.build();
return expr;
// expr.index = index;
// expr.bind(this);
// this.expr[index] = expr;
// expr.calcOffsetMaxAndOffset(); // 1st pass
// expr.build();
// return expr;
_8(mnemonic: string, ...operands: o.TUiOperand[]) {
return this._(mnemonic, operands, 8);
}
replace(expr: Expression, index = this.expr.length): Expression {
expr.index = index;
expr.bind(this);
this.expr[index] = expr;
expr.calcOffsetMaxAndOffset(); // 1st pass
return expr;
_16(mnemonic: string, ...operands: o.TUiOperand[]) {
return this._(mnemonic, operands, 16);
}
compile(): number[] {
// 1st pass is performed as instructions are `insert`ed, `.offsetMax` is calculated, and possibly `.offset`.
_32(mnemonic: string, ...operands: o.TUiOperand[]) {
return this._(mnemonic, operands, 32);
}
// Instructions without size can now determine their size based on `.offsetMax` and
// calculate their real `.offset`.
this.do2ndPass();
_64(mnemonic: string, ...operands: o.TUiOperand[]) {
return this._(mnemonic, operands, 64);
}
// Offsets are now know, here we evaluate references.
return this.do3rdPass();
_128(mnemonic: string, ...operands: o.TUiOperand[]) {
return this._(mnemonic, operands, 128);
}
do2ndPass() {
var last = this.expr[this.expr.length - 1];
var all_offsets_known = last.offset >= 0;
_256(mnemonic: string, ...operands: o.TUiOperand[]) {
return this._(mnemonic, operands, 256);
}
// Edge case when only the last Expression has variable size.
var all_sizes_known = last.bytes() >= 0;
_512(mnemonic: string, ...operands: o.TUiOperand[]) {
return this._(mnemonic, operands, 512);
}
if(all_offsets_known && all_sizes_known) return; // Skip 2nd pass.
var prev = this.expr[0];
prev.offset = 0;
for(var j = 1; j < this.expr.length; j++) {
var ins = this.expr[j];
if(ins instanceof i.ExpressionVolatile) {
var fixed = (ins as i.ExpressionVolatile).getFixedSizeExpression();
this.replace(fixed, ins.index);
ins = fixed;
// (ins as i.ExpressionVolatile).determineSize();
exportMethods(useNumbers = false, sizes = [o.SIZE.B, o.SIZE.W, o.SIZE.D, o.SIZE.Q], obj: any = {}) {
for(let mnemonic in this.table.table) {
obj[mnemonic] = (...operands: o.TUiOperand[]) => {
return this._(mnemonic, operands);
};
for(let size of sizes) {
let method = useNumbers ? mnemonic + size : mnemonic + o.SIZE[size].toLowerCase();
obj[method] = (...operands: o.TUiOperand[]) => {
return this._(mnemonic, operands, size);
};
}
}
return obj;
}
// var bytes = prev.bytes();
// if(bytes === i.SIZE_UNKNOWN)
// throw Error(`Instruction [${j}] does not have size.`);
// ins.offset = prev.offset + bytes;
// Need to call method, as `InstructionSet` contains multiple `Instruction`s,
// that all need offset updated of picked instruction.
ins.calcOffset();
addMethods(useNumbers = false, sizes = [o.SIZE.B, o.SIZE.W, o.SIZE.D, o.SIZE.Q], obj = this.exportMethods(useNumbers, sizes)) {
extend(this, obj);
}
prev = ins;
}
getStartLabel(): Label {
return this.expr[0] as Label;
}
do3rdPass() {
var code: number[] = [];
for(var ins of this.expr) {
if(ins instanceof i.ExpressionVariable)
(ins as i.ExpressionVariable).evaluate();
code = ins.write(code); // 3rd pass
}
return code;
insert(expr: Expression): Expression {
this.replace(expr, this.expr.length);
expr.build();
return expr;
}
replace(expr: Expression, index = this.expr.length): Expression {
expr.index = index;
expr.bind(this);
this.expr[index] = expr;
expr.calcOffsetMaxAndOffset(); // 1st pass
return expr;
}
lbl(name: string): Label {

@@ -154,3 +163,3 @@ return new Label(name);

// DB volatile
// DB variable
dbv(ops: o.Operands, littleEndian: boolean): i.DataVariable;

@@ -188,3 +197,3 @@ dbv(expr: i.Expression, size: number, littleEndian: boolean): i.DataVariable;

db(num: number, times: number): Data;
db(num: number, times?: number): Data;
db(str: string, encoding?: string): Data;

@@ -234,6 +243,19 @@ db(octets: number[]): Data;

dq(quads: Tnumber[], littleEndian = this.littleEndian): Data {
return this.db(Data.quadsToOctets(quads, littleEndian));
dq(quads: Tnumber|Tnumber[], littleEndian = this.littleEndian): Data {
var tnums: Tnumber[];
if(typeof quads === 'number') tnums = [quads];
else tnums = quads as Tnumber[];
for(var j = 0; j < tnums.length; j++) {
var num = tnums[j];
if(typeof num === 'number') tnums[j] = [UInt64.lo(num), UInt64.hi(num)];
}
return this.db(Data.quadsToOctets(tnums, littleEndian));
}
tpl(Clazz: typeof i.Template, args?: any[]): i.Expression {
return this.insert(new Clazz(args));
}
resb(length: number): DataUninitialized {

@@ -310,2 +332,65 @@ var data = new DataUninitialized(length);

// Expressions are compiled in 3 passes:
//
// - *1st pass* -- maximum offset `maxOffset` for each expression is computed, some expression might not know
// their size jet, not all expressions are known, future references. First pass is when user performs insertion of commands.
// - *2nd pass* -- all expressions known now, each expression should pick its right size, exact `offset` is computed for each expression.
// - *3rd pass* -- now we know exact `offset` of each expression, so in this pass we fill in the addresses.
compile(): number[] {
// 1st pass is performed as instructions are `insert`ed, `.offsetMax` is calculated, and possibly `.offset`.
// Instructions without size can now determine their size based on `.offsetMax` and
// calculate their real `.offset`.
this.do2ndPass();
// Offsets are now know, here we evaluate references.
return this.do3rdPass();
}
do2ndPass() {
// We probably cannot skip this 2nd pass, as instructions might change their sizes after inserted,
// for example, when `.lock()` prefix is added.
// var last = this.expr[this.expr.length - 1];
// var all_offsets_known = last.offset >= 0;
//
// Edge case when only the last Expression has variable size.
// var all_sizes_known = last.bytes() >= 0;
//
// if(all_offsets_known && all_sizes_known) return; // Skip 2nd pass.
var prev = this.expr[0];
prev.offset = 0;
for(var j = 1; j < this.expr.length; j++) {
var ins = this.expr[j];
if(ins instanceof i.ExpressionVolatile) {
var fixed = (ins as i.ExpressionVolatile).getFixedSizeExpression();
this.replace(fixed, ins.index);
ins = fixed;
// (ins as i.ExpressionVolatile).determineSize();
}
// var bytes = prev.bytes();
// if(bytes === i.SIZE_UNKNOWN)
// throw Error(`Instruction [${j}] does not have size.`);
// ins.offset = prev.offset + bytes;
// Need to call method, as `InstructionSet` contains multiple `Instruction`s,
// that all need offset updated of picked instruction.
ins.calcOffset();
prev = ins;
}
}
do3rdPass() {
var code: number[] = [];
for(var ins of this.expr) {
if(ins instanceof i.ExpressionVariable)
(ins as i.ExpressionVariable).evaluate();
code = ins.write(code); // 3rd pass
}
return code;
}
toString(lineNumbers = true, hex = true) {

@@ -312,0 +397,0 @@ var lines = [];

@@ -111,2 +111,6 @@ "use strict";

Def.prototype.toStringOperand = function (operand) {
if (typeof operand === 'number')
return operand;
if (typeof operand === 'string')
return operand;
if (operand instanceof o.Operand)

@@ -137,2 +141,30 @@ return operand.toString();

};
Def.prototype.toJsonOperands = function () {
var ops = [];
for (var _i = 0, _a = this.operands; _i < _a.length; _i++) {
var op_tpl = _a[_i];
var op_out = [];
for (var _b = 0, op_tpl_1 = op_tpl; _b < op_tpl_1.length; _b++) {
var op = op_tpl_1[_b];
op_out.push(this.toStringOperand(op));
}
if (op_out.length > 1)
ops.push(op_out);
else
ops.push(op_out[0]);
}
return ops;
};
Def.prototype.toJson = function () {
var json = {
opcode: this.opcode,
opcodeHex: this.opcode.toString(16),
};
if (this.operandSize)
json.operandSize = this.operandSize;
var ops = this.toJsonOperands();
if (ops.length)
json.operands = ops;
return json;
};
Def.prototype.toString = function () {

@@ -153,3 +185,6 @@ var opcode = ' ' + (new o.Constant(this.opcode, false)).toString();

operandsstr = ' ' + operands.join(',');
return this.getMnemonic() + opcode + operandsstr;
var size = '';
if (this.operandSize > 0)
size = ' ' + this.operandSize + '-bit';
return this.mnemonic + size + opcode + operandsstr;
};

@@ -190,2 +225,13 @@ return Def;

};
DefGroup.prototype.toJson = function () {
var instructions = [];
for (var _i = 0, _a = this.defs; _i < _a.length; _i++) {
var def = _a[_i];
instructions.push(def.toJson());
}
return {
mnemonic: this.mnemonic,
definitions: instructions,
};
};
DefGroup.prototype.toString = function () {

@@ -203,14 +249,42 @@ var defs = [];

var DefTable = (function () {
function DefTable() {
function DefTable(table, defaults) {
this.DefGroupClass = DefGroup;
this.groups = {};
this.table = table;
this.defaults = defaults;
}
DefTable.prototype.create = function (table, defaults) {
for (var mnemonic in table) {
var group = new this.DefGroupClass(this, mnemonic);
group.createDefinitions(table[mnemonic], defaults);
this.groups[mnemonic] = group;
DefTable.prototype.getGroup = function (mnemonic) {
if (!this.groups[mnemonic]) {
this.createGroup(mnemonic);
}
return this;
return this.groups[mnemonic];
};
DefTable.prototype.createGroup = function (mnemonic) {
var group = new this.DefGroupClass(this, mnemonic);
var definitions = this.table[mnemonic];
if ((definitions.length === 1) && (typeof definitions[0] === 'string'))
definitions = this.table[definitions[0]];
group.createDefinitions(definitions, this.defaults);
this.groups[mnemonic] = group;
};
DefTable.prototype.createAll = function () {
for (var mnemonic in this.table) {
this.getGroup(mnemonic);
}
};
DefTable.prototype.matchDefinitions = function (mnemonic, ops, opts) {
var group = this.getGroup(mnemonic);
if (!group)
throw Error("No such mnemonic \"" + mnemonic + "\".");
var matches = new DefMatchList;
matches.matchAll(group.defs, ops, opts);
return matches;
};
DefTable.prototype.toJson = function () {
var json = {};
for (var group_name in this.groups) {
json[group_name] = this.groups[group_name].toJson();
}
return json;
};
DefTable.prototype.toString = function () {

@@ -238,5 +312,11 @@ var groups = [];

}
DefMatchList.prototype.match = function (def, ops) {
DefMatchList.prototype.match = function (def, ops, opts) {
if (opts.size !== o.SIZE.ANY) {
if (opts.size !== def.operandSize)
return;
}
var tpl = def.matchOperands(ops);
if (tpl) {
if (def.vex && ops.has5bitRegister())
return;
var match = new DefMatch;

@@ -248,6 +328,6 @@ match.def = def;

};
DefMatchList.prototype.matchAll = function (defs, ops) {
DefMatchList.prototype.matchAll = function (defs, ops, opts) {
for (var _i = 0, defs_1 = defs; _i < defs_1.length; _i++) {
var def = defs_1[_i];
this.match(def, ops);
this.match(def, ops, opts);
}

@@ -254,0 +334,0 @@ };

import * as o from './operand';
import * as t from './table';
import {extend} from './util';
import * as c from './code';
type TInstructionOptions = c.IInstructionOptions;
export class Def {

@@ -108,2 +111,4 @@ group: DefGroup = null;

toStringOperand(operand) {
if(typeof operand === 'number') return operand;
if(typeof operand === 'string') return operand;
if(operand instanceof o.Operand) return operand.toString();

@@ -126,2 +131,30 @@ else if(typeof operand === 'function') {

toJsonOperands() {
var ops = [];
for(var op_tpl of this.operands) {
var op_out = [];
for(var op of op_tpl) {
op_out.push(this.toStringOperand(op));
}
if(op_out.length > 1) ops.push(op_out);
else ops.push(op_out[0]);
}
return ops;
}
toJson() {
var json: any = {
opcode: this.opcode,
opcodeHex: this.opcode.toString(16),
// mnemonic: this.mnemonic,
};
if(this.operandSize) json.operandSize = this.operandSize;
var ops = this.toJsonOperands();
if(ops.length) json.operands = ops;
return json;
}
toString() {

@@ -141,3 +174,6 @@ var opcode = ' ' + (new o.Constant(this.opcode, false)).toString();

return this.getMnemonic() + opcode + operandsstr;
var size = '';
if(this.operandSize > 0) size = ' ' + this.operandSize + '-bit';
return this.mnemonic + size + opcode + operandsstr;
}

@@ -186,2 +222,13 @@ }

toJson(): any {
var instructions = [];
for(var def of this.defs) {
instructions.push(def.toJson());
}
return {
mnemonic: this.mnemonic,
definitions: instructions,
};
}
toString() {

@@ -203,11 +250,62 @@ var defs = [];

create(table: t.TableDefinition, defaults: t.Definition): this {
for(var mnemonic in table) {
var group = new this.DefGroupClass(this, mnemonic);
group.createDefinitions(table[mnemonic], defaults);
this.groups[mnemonic] = group;
table: t.TableDefinition;
defaults: t.Definition;
constructor(table: t.TableDefinition, defaults: t.Definition) {
this.table = table;
this.defaults = defaults;
}
getGroup(mnemonic: string): DefGroup {
if(!this.groups[mnemonic]) {
this.createGroup(mnemonic);
}
return this;
return this.groups[mnemonic];
}
protected createGroup(mnemonic: string) {
var group = new this.DefGroupClass(this, mnemonic);
var definitions = this.table[mnemonic];
if((definitions.length === 1) && (typeof definitions[0] === 'string'))
definitions = this.table[definitions[0]];
group.createDefinitions(definitions, this.defaults);
this.groups[mnemonic] = group;
}
createAll() {
for(var mnemonic in this.table) {
this.getGroup(mnemonic);
}
}
matchDefinitions(mnemonic: string, ops: o.Operands, opts: TInstructionOptions): DefMatchList {
var group = this.getGroup(mnemonic);
if(!group)
throw Error(`No such mnemonic "${mnemonic}".`);
var matches = new DefMatchList;
matches.matchAll(group.defs, ops, opts);
return matches;
}
// create(table: t.TableDefinition, defaults: t.Definition): this {
// for(var mnemonic in table) {
// var group = new this.DefGroupClass(this, mnemonic);
// group.createDefinitions(table[mnemonic], defaults);
// this.groups[mnemonic] = group;
// }
// return this;
// }
toJson() {
var json: any = {};
for(var group_name in this.groups) {
json[group_name] = this.groups[group_name].toJson();
}
return json;
}
toString() {

@@ -232,5 +330,13 @@ var groups = [];

match(def: Def, ops: o.Operands) {
match(def: Def, ops: o.Operands, opts: TInstructionOptions) {
if(opts.size !== o.SIZE.ANY) {
if(opts.size !== def.operandSize) return;
}
var tpl = def.matchOperands(ops);
if(tpl) {
// If registers are 5-bit wide, we can encode them only with EVEX, not VEX.
if((def as any).vex && ops.has5bitRegister()) return;
var match = new DefMatch;

@@ -243,5 +349,5 @@ match.def = def;

matchAll(defs: Def[], ops: o.Operands) {
for(var def of defs) this.match(def, ops);
matchAll(defs: Def[], ops: o.Operands, opts: TInstructionOptions) {
for(var def of defs) this.match(def, ops, opts);
}
}

@@ -276,2 +276,23 @@ "use strict";

exports.Data = Data;
var Template = (function (_super) {
__extends(Template, _super);
function Template(args) {
if (args === void 0) { args = []; }
_super.call(this);
this.name = 'template';
this.args = args;
}
Template.prototype.toString = function (margin, comment) {
if (margin === void 0) { margin = ' '; }
if (comment === void 0) { comment = true; }
var expression = this.name + this.args.join(', ');
var cmt = '';
if (comment) {
cmt = this.bytes() + " bytes";
}
return this.formatToString(margin, expression, cmt);
};
return Template;
}(Data));
exports.Template = Template;
var ExpressionVariable = (function (_super) {

@@ -446,2 +467,3 @@ __extends(ExpressionVariable, _super);

this.def = null;
this.opts = null;
}

@@ -455,8 +477,3 @@ Instruction.prototype.build = function () {

};
Instruction.prototype.getFixedSizeExpression = function () {
return this;
};
Instruction.prototype.toString = function (margin, comment) {
if (margin === void 0) { margin = ' '; }
if (comment === void 0) { comment = true; }
Instruction.prototype.toStringExpression = function () {
var parts = [];

@@ -468,12 +485,16 @@ parts.push(this.def.getMnemonic());

parts.push(this.ops.toString());
var expression = margin + parts.join(' ');
return parts.join(' ');
};
Instruction.prototype.toString = function (margin, comment) {
if (margin === void 0) { margin = ' '; }
if (comment === void 0) { comment = true; }
var expression = margin + this.toStringExpression();
var cmt = '';
if (comment) {
var spaces = (new Array(1 + Math.max(0, Expression.commentColls - expression.length))).join(' ');
var octets = this.write([]).map(function (byte) {
return byte <= 0xF ? '0' + byte.toString(16).toUpperCase() : byte.toString(16).toUpperCase();
});
cmt = spaces + ("; " + this.formatOffset() + " 0x") + octets.join(', 0x');
cmt = "0x" + octets.join(', 0x') + (" " + this.bytes() + " bytes");
}
return expression + cmt;
return this.formatToString(margin, expression, cmt);
};

@@ -485,3 +506,3 @@ return Instruction;

__extends(InstructionSet, _super);
function InstructionSet(ops, matches) {
function InstructionSet(ops, matches, opts) {
_super.call(this, ops);

@@ -491,3 +512,5 @@ this.matches = null;

this.picked = -1;
this.opts = null;
this.matches = matches;
this.opts = opts;
}

@@ -637,2 +660,3 @@ InstructionSet.prototype.write = function (arr) {

insn.def = match.def;
insn.opts = this.opts;
var ops = this.createInstructionOperands(insn, match.opTpl);

@@ -639,0 +663,0 @@ ops.validateSize();

@@ -307,3 +307,23 @@ import {Def, DefMatchList} from './def';

// A pre-filled template with some binary data.
export class Template extends Data {
name = 'template';
args: any[];
constructor(args = []) {
super();
this.args = args;
}
toString(margin = ' ', comment = true) {
var expression = this.name + this.args.join(', ');
var cmt = '';
if(comment) {
cmt = `${this.bytes()} bytes`;
}
return this.formatToString(margin, expression, cmt);
}
}
// Expressions that have operands, operands might reference (in case of `Relative`) other expressions, which

@@ -432,3 +452,3 @@ // have not been insert into code yet, so we might not know the how those operands evaluate on first two passes.

// If `Expression` can generate different size machine code this method forces it to pick one.
getFixedSizeExpression() {
getFixedSizeExpression(): Expression {
return this;

@@ -512,2 +532,3 @@ }

def: Def = null; // Definition on how to construct this instruction.
opts: c.IInstructionOptions = null; // Instruction options provided by user.

@@ -523,8 +544,3 @@ build(): this {

getFixedSizeExpression() {
return this;
}
toString(margin = ' ', comment = true) {
protected toStringExpression() {
var parts = [];

@@ -534,14 +550,16 @@ parts.push(this.def.getMnemonic());

if(this.ops.list.length) parts.push(this.ops.toString());
var expression = margin + parts.join(' ');
return parts.join(' ');
}
toString(margin = ' ', comment = true) {
var expression = margin + this.toStringExpression();
var cmt = '';
if(comment) {
var spaces = (new Array(1 + Math.max(0, Expression.commentColls - expression.length))).join(' ');
var octets = this.write([]).map(function(byte) {
return byte <= 0xF ? '0' + byte.toString(16).toUpperCase() : byte.toString(16).toUpperCase();
});
cmt = spaces + `; ${this.formatOffset()} 0x` + octets.join(', 0x');// + ' / ' + this.def.toString();
cmt = `0x` + octets.join(', 0x') + ` ${this.bytes()} bytes`;// + ' / ' + this.def.toString();
}
return expression + cmt;
return this.formatToString(margin, expression, cmt);
}

@@ -557,6 +575,8 @@ }

picked: number = -1; // Index of instruction that was eventually chosen.
opts: c.IInstructionOptions = null; // Instruction options provided by user.
constructor(ops: o.Operands, matches: DefMatchList) {
constructor(ops: o.Operands, matches: DefMatchList, opts: c.IInstructionOptions) {
super(ops);
this.matches = matches;
this.opts = opts;
}

@@ -715,2 +735,3 @@

insn.def = match.def;
insn.opts = this.opts;

@@ -720,2 +741,3 @@ var ops = this.createInstructionOperands(insn, match.opTpl);

insn.ops = ops;
insn.bind(this.code);

@@ -722,0 +744,0 @@ insn.build();

@@ -20,2 +20,6 @@ "use strict";

SIZE[SIZE["I"] = 512] = "I";
SIZE[SIZE["X"] = 128] = "X";
SIZE[SIZE["Y"] = 256] = "Y";
SIZE[SIZE["Z"] = 256] = "Z";
SIZE[SIZE["A"] = 1024] = "A";
})(exports.SIZE || (exports.SIZE = {}));

@@ -57,10 +61,2 @@ var SIZE = exports.SIZE;

}
function isNumber256(num) { return isNumberOfDoubles(8, num); }
exports.isNumber256 = isNumber256;
function isNumber512(num) { return isNumberOfDoubles(16, num); }
exports.isNumber512 = isNumber512;
function isNumber1024(num) { return isNumberOfDoubles(32, num); }
exports.isNumber1024 = isNumber1024;
function isNumber2048(num) { return isNumberOfDoubles(64, num); }
exports.isNumber2048 = isNumber2048;
function isTnumber(num) {

@@ -71,12 +67,4 @@ if (typeof num === 'number')

return true;
else if (isNumber128(num))
return true;
else if (isNumber256(num))
return true;
else if (isNumber512(num))
return true;
else if (isNumber1024(num))
return true;
else
return isNumber2048(num);
return isNumber128(num);
}

@@ -402,2 +390,17 @@ exports.isTnumber = isTnumber;

};
Register.prototype.idSize = function () {
if (this.id < 8)
return 3;
if (this.id < 16)
return 4;
if (this.id < 32)
return 5;
throw Error('Register ID too big.');
};
Register.prototype.get3bitId = function () {
return this.id & 7;
};
Register.prototype.get4bitId = function () {
return this.id & 15;
};
Register.prototype.toNumber = function () {

@@ -639,2 +642,9 @@ return this.id;

};
Operands.prototype.getAtIndexOfClass = function (index, Clazz) {
var op = this.list[index];
if (op instanceof Clazz)
return op;
else
return null;
};
Operands.prototype.getFirstOfClass = function (Clazz, skip) {

@@ -711,2 +721,14 @@ if (skip === void 0) { skip = 0; }

};
Operands.prototype.has5bitRegister = function () {
for (var j = 0; j < 4; j++) {
var op = this.list[j];
if (!op)
break;
if (op instanceof Register) {
if (op.idSize() > 4)
return true;
}
}
return false;
};
Operands.prototype.toString = function () {

@@ -713,0 +735,0 @@ return this.list.map(function (op) { return op.toString(); }).join(', ');

@@ -7,12 +7,16 @@ import {UInt64} from './util';

export enum SIZE {
ANY = -1, // Any size.
NONE = 0, // Either unknown or not specified yet.
B = 8, // byte
W = 16, // word
D = 32, // double word = 2x word
Q = 64, // quad word = 4x word
T = 80, // ten = 10 bytes
O = 128, // octa word = 8x word
H = 256, // hexadeca word = 16x word
I = 512, // dItriaconta word = 32x word
ANY = -1, // Any size.
NONE = 0, // Either unknown or not specified yet.
B = 8, // byte
W = 16, // word
D = 32, // double word = 2x word
Q = 64, // quad word = 4x word
T = 80, // ten = 10 bytes
O = 128, // octa word = 8x word
H = 256, // hexadeca word = 16x word
I = 512, // dItriaconta word = 32x word
X = SIZE.O, // xmm register
Y = SIZE.H, // ymm register
Z = SIZE.Y, // zmm register
A = 1024, // amm register
}

@@ -55,26 +59,28 @@

// 256-bit numbers
export type number256 = [number, number, number, number, number, number, number, number];
export function isNumber256(num) { return isNumberOfDoubles(8, num); }
// export type number256 = [number, number, number, number, number, number, number, number];
// export function isNumber256(num) { return isNumberOfDoubles(8, num); }
// 512-bit numbers
export type number512 = [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number];
export function isNumber512(num) { return isNumberOfDoubles(16, num); }
// export type number512 = [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number];
// export function isNumber512(num) { return isNumberOfDoubles(16, num); }
// AVX-512 extension says registers will be "at least" 512 bits, so can be 1024 bits and maybe even 2048 bits.
export type number1024 = [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number];
export type number2048 = [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number];
export function isNumber1024(num) { return isNumberOfDoubles(32, num); }
export function isNumber2048(num) { return isNumberOfDoubles(64, num); }
// export type number1024 = [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number];
// export type number2048 = [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number];
// export function isNumber1024(num) { return isNumberOfDoubles(32, num); }
// export function isNumber2048(num) { return isNumberOfDoubles(64, num); }
// Combined type of all basic "numbers".
export type Tnumber = number|number64|number128|number256|number512|number1024|number2048;
export type Tnumber = number|number64|number128;
// export type Tnumber = number|number64|number128|number256|number512|number1024|number2048;
export function isTnumber(num) {
if(typeof num === 'number') return true;
else if(isNumber64(num)) return true;
else if(isNumber128(num)) return true;
else if(isNumber256(num)) return true;
else if(isNumber512(num)) return true;
else if(isNumber1024(num)) return true;
else return isNumber2048(num);
// else if(isNumber128(num)) return true;
// else if(isNumber256(num)) return true;
// else if(isNumber512(num)) return true;
// else if(isNumber1024(num)) return true;
// else return isNumber2048(num);
else return isNumber128(num);
}

@@ -386,2 +392,17 @@

idSize() { // In bits
if(this.id < 0b1000) return 3;
if(this.id < 0b10000) return 4;
if(this.id < 0b100000) return 5;
throw Error('Register ID too big.');
}
get3bitId() {
return this.id & 0b111;
}
get4bitId() {
return this.id & 0b1111;
}
toNumber() {

@@ -642,2 +663,8 @@ return this.id;

getAtIndexOfClass(index, Clazz) {
var op = this.list[index];
if(op instanceof Clazz) return op;
else return null;
}
getFirstOfClass(Clazz, skip = 0) {

@@ -712,2 +739,15 @@ for(var op of this.list) {

// EVEX may encode up to 4 operands, 32 registers, so register can be up to 5-bits wide,
// we need to check for that because in that case we cannot use VEX.
has5bitRegister() {
for(var j = 0; j < 4; j++) {
var op = this.list[j];
if(!op) break;
if(op instanceof Register) {
if((op as Register).idSize() > 4) return true;
}
}
return false;
}
toString() {

@@ -714,0 +754,0 @@ return this.list.map((op) => { return op.toString(); }).join(', ');

{
"name": "ass-js",
"description": "Assembler.js",
"version": "1.0.2",
"version": "1.0.3",
"keywords": [

@@ -6,0 +6,0 @@ "x86",

@@ -5,7 +5,9 @@ # Assembler.js

> THIS PACKAGE IS IN DEVELOPMENT, THERE ARE BUGS, SOME INSTRUCTIONS ARE MISSING.
```js
import * as ass from 'ass-js';
var {rax, rbx} = ass.x86;
import {rax, rbx} from 'ass-js/x86/operand'; // x86 registers that we will use.
import {Code} from 'ass-js/x86/x64/code'; // Code object that will `.compile()` our code.
var _ = ass.x86.x64.Code.create();
var _ = Code.create();
_.mov(rax, rbx);

@@ -19,5 +21,12 @@ console.log(_.compile());

```js
console.log(ass.x86.x64.Code.table.toString());
_.table.createAll();
console.log(_.table.toString());
console.log(_.table.toJson());
```
Goals:
1. Create a generic assembler, first with `x86` support and then add `ARM` support.
2. Full support for all `x86` instructions, including: *AVX*, *AVX-2* and *AVX-3* instructions.
## Examples

@@ -47,3 +56,3 @@

```js
var _ = Code.create('hello_world_app');
var _ = new Code('hello_world_app');
```

@@ -55,8 +64,8 @@

_.db('Hello World!\n');
_.movq(rax, 1);
_.movq(rdi, 1);
_.lea(rsi, rip.disp(-34));
_.movq(rdx, 13);
_.syscall();
_.ret();
_._('mov', [rax, 1]);
_._('mov', [rdi, 1]);
_._('lea', [rsi, rip.disp(-34)]);
_._('mov', [rdx, 13]);
_._('syscall');
_._('ret');
```

@@ -67,12 +76,12 @@

- `_.db('Hello World!\n');` -- simply adds `"Hello World!\n"` string to our code.
- `_.movq(rax, 1);` -- stores `1` in `rax` register, which will tell Linux kernel to execute syscall No. 1, which is
- `_._('mov', [rax, 1]);` -- stores `1` in `rax` register, which will tell Linux kernel to execute syscall No. 1, which is
`write` syscall, that writes some data to some file descriptor.
- `_.movq(rdi, 1);` -- stores `1` in `rdi` register, which represents a file descriptor to which Linux kernel will
- `_._('mov', [rdi, 1]);` -- stores `1` in `rdi` register, which represents a file descriptor to which Linux kernel will
write the data, `1` stands for `STDOUT` which will be the console in our case.
- `_.lea(rsi, rip.disp(-34));` -- this expression stores the address of the beginning of our `"Hello World!\n"` string
- `_._('lea', [rsi, rip.disp(-34)]);` -- this expression stores the address of the beginning of our `"Hello World!\n"` string
into the `rsi` register, here we use *"RIP-relative addressing"*, where we basically say that our string actually started
`34` bytes before the end of this instruction.
- `_.movq(rdx, 13);` -- stores `13` in `rdx` register which tells the kernel the length of our string we want to print.
- `_.syscall();` -- this command tells the Linux kernel to execute our system call with the arguments we just provided.
- `_.ret();` -- this command is required by `StaticBuffer` that we will use to execute this code, it will basically stop
- `_._('mov', [rdx, 13]);` -- stores `13` in `rdx` register which tells the kernel the length of our string we want to print.
- `_._('syscall');` -- this command tells the Linux kernel to execute our system call with the arguments we just provided.
- `_._('ret');` -- this command is required by `StaticBuffer` that we will use to execute this code, it will basically stop
executing any further machine instructions and `return` to `JavaScript`.

@@ -114,8 +123,8 @@

_.db(str);
_.movq(rax, SYS_write);
_.movq(rdi, STDOUT);
_.lea(rsi, rip.disp(-34));
_.movq(rdx, 13);
_.syscall();
_.ret();
_._('mov', [rax, SYS_write]);
_._('mov', [rdi, STDOUT]);
_._('lea', [rsi, rip.disp(-34)]);
_._('mov', [rdx, 13]);
_._('syscall');
_._('ret');
```

@@ -134,8 +143,8 @@

var db = _.db(str);
_.movq(rax, SYS_write);
_.movq(rdi, STDOUT);
_.lea(rsi, rip.disp(db));
_.movq(rdx, str.length);
_.syscall();
_.ret();
_._('mov', [rax, SYS_write]);
_._('mov', [rdi, STDOUT]);
_._('lea', [rsi, rip.disp(db)]);
_._('mov', [rdx, str.length]);
_._('syscall');
_._('ret');
```

@@ -169,8 +178,8 @@

_.movq(rax, SYS_write);
_.movq(rdi, STDOUT);
_.lea(rsi, rip.disp(str_lbl));
_.movq(rdx, str.length);
_.syscall();
_.ret();
_._('mov', [rax, SYS_write]);
_._('mov', [rdi, STDOUT]);
_._('lea', [rsi, rip.disp(str_lbl)]);
_._('mov', [rdx, str.length]);
_._('syscall');
_._('ret');
```

@@ -192,8 +201,8 @@

_.movq(rax, SYS_write);
_.movq(rdi, STDOUT);
_.lea(rsi, rip.disp(str_lbl));
_.movq(rdx, str.length);
_.syscall();
_.ret();
_._('mov', [rax, SYS_write]);
_._('mov', [rdi, STDOUT]);
_._('lea', [rsi, rip.disp(str_lbl)]);
_._('mov', [rdx, str.length]);
_._('syscall');
_._('ret');

@@ -200,0 +209,0 @@ _.insert(str_lbl);

@@ -27,3 +27,3 @@ import {SIZE, Register, Memory, Relative, Relative8, Relative16, Relative32,

export type TOperandTemplate = Register | typeof Register | typeof Memory |
export type TOperandTemplate = number | Register | typeof Register | typeof Memory |
typeof Relative | typeof Relative8 | typeof Relative16 | typeof Relative32 |

@@ -41,5 +41,5 @@ typeof Immediate | typeof Immediate8 | typeof Immediate16 | typeof Immediate32 | typeof Immediate64 |

ops?: (any|TOperandTemplate|TOperandTemplate[])[]; // Operands this instruction accepts.
mns?: string[]; // Other mnemonics for exactly the same instruction, basically proxies.
}
export type GroupDefinition = Definition[];
export type Tproxy = [string]; // Proxy to some other mnemonic, which have exactly the same definition.
export type GroupDefinition = (Definition|Tproxy)[];
export type TableDefinition = {[s: string]: GroupDefinition};

@@ -46,0 +46,0 @@

@@ -25,4 +25,2 @@ "use strict";

hi /= 4294967296;
if ((hi < 0) || (hi >= 1048576))
throw Error("Not an int52: " + a);
return hi;

@@ -41,4 +39,18 @@ };

};
UInt64.toNumber = function (num64) {
var lo = num64[0], hi = num64[1];
if (lo < 0)
lo += 4294967296;
return hi * 4294967296 + lo;
};
UInt64.toNumber64 = function (num) {
var lo = num | 0;
if (lo < 0)
lo += 4294967296;
var hi = num - lo;
hi /= 4294967296;
return [lo, hi];
};
return UInt64;
}());
exports.UInt64 = UInt64;

@@ -18,3 +18,2 @@

hi /= 4294967296;
if ((hi < 0) || (hi >= 1048576)) throw Error (`Not an int52: ${a}`);
return hi;

@@ -36,2 +35,18 @@ }

}
static toNumber(num64: [number, number]): number {
var [lo, hi] = num64;
if (lo < 0) lo += 4294967296;
return hi * 4294967296 + lo;
}
static toNumber64(num: number): [number, number] {
var lo = num | 0;
if (lo < 0) lo += 4294967296;
var hi = num - lo;
hi /= 4294967296;
return [lo, hi];
}
}

@@ -19,2 +19,3 @@ "use strict";

this.ClassInstruction = i.Instruction;
this.ClassInstructionSet = i.InstructionSet;
this.AlignExpression = i.Align;

@@ -89,2 +90,19 @@ this.ClassOperands = o.Operands;

};
Code.prototype.matchDefinitions = function (mnemonic, ops, opts) {
var matches = _super.prototype.matchDefinitions.call(this, mnemonic, ops, opts);
for (var j = matches.list.length - 1; j >= 0; j--) {
var def = matches.list[j].def;
if (!(this.mode & def.mode)) {
matches.list.splice(j, 1);
continue;
}
var needs_evex = opts.mask || (typeof opts.z !== 'undefined');
if (needs_evex) {
if (!def.evex)
matches.list.splice(j, 1);
continue;
}
}
return matches;
};
Code.prototype.mem = function (disp) {

@@ -103,6 +121,12 @@ if (typeof disp === 'number')

if (signed === void 0) { signed = true; }
return signed ? new o.Immediate(value) : new o.ImmediateUnsigned(value);
return signed ? new oo.Immediate(value) : new oo.ImmediateUnsigned(value);
};
Code.prototype.lock = function () {
return this.tpl(i.TemplateLock);
};
Code.prototype.rex = function (args) {
return this.tpl(i.TemplateRex, args);
};
return Code;
}(code_1.Code));
exports.Code = Code;
import * as oo from '../operand';
import * as o from './operand';
import * as c from '../code';
import {Code as CodeBase} from '../code';

@@ -11,2 +12,8 @@ import * as t from './table';

export interface IInstructionOptions extends c.IInstructionOptions {
mask?: o.RegisterK;
z: number|boolean;
}
export class Code extends CodeBase {

@@ -54,3 +61,4 @@

ClassInstruction: typeof i.Instruction = i.Instruction;
ClassInstruction: any = i.Instruction;
ClassInstructionSet = i.InstructionSet;
AlignExpression = i.Align;

@@ -81,2 +89,26 @@ ClassOperands = o.Operands;

protected matchDefinitions(mnemonic: string, ops: o.Operands, opts: IInstructionOptions): d.DefMatchList {
var matches = super.matchDefinitions(mnemonic, ops, opts);
for(var j = matches.list.length - 1; j >= 0; j--) {
var def = matches.list[j].def as d.Def;
// Check mode of CPU.
if(!(this.mode & def.mode)) {
matches.list.splice(j, 1);
continue;
}
// If EVEX-specific options provided by user,
// remove instruction definition matches that don't have EVEX prefix.
var needs_evex = opts.mask || (typeof opts.z !== 'undefined');
if(needs_evex) {
if(!def.evex) matches.list.splice(j, 1);
continue;
}
}
return matches;
}
// Displacement is up to 4 bytes in size, and 8 bytes for some specific MOV instructions, AMD64 Vol.2 p.24:

@@ -103,4 +135,17 @@ //

imm(value: Tnumber, signed = true) {
return signed ? new o.Immediate(value) : new o.ImmediateUnsigned(value);
return signed ? new oo.Immediate(value) : new oo.ImmediateUnsigned(value);
}
lock() {
return this.tpl(i.TemplateLock);
}
rex(args: number[]) {
return this.tpl(i.TemplateRex, args);
}
}
export interface Code {
_(mnemonic: string, operands?: oo.TUiOperand|oo.TUiOperand[], options?: oo.SIZE|IInstructionOptions|any): i.Instruction;
}

@@ -8,5 +8,7 @@ "use strict";

var d = require('../def');
var t = require('./table');
var operand_1 = require("../operand");
var oo = require('../operand');
var o = require('./operand');
var util_1 = require('../util');
var Def = (function (_super) {

@@ -21,3 +23,3 @@ __extends(Def, _super);

this.opcodeDirectionBit = def.dbit;
this.mandatoryRex = def.rex;
this.rex = def.rex;
this.useModrm = def.mr;

@@ -27,3 +29,54 @@ this.rep = def.rep;

this.prefixes = def.pfx;
this.opEncoding = def.en;
this.mode = def.mod;
this.extensions = def.ext;
if (typeof def.vex === 'string')
this.vex = Def.parseVexString(def.vex);
else
this.vex = def.vex;
if (typeof def.evex === 'string')
this.evex = Def.parseEvexString(def.evex);
else
this.evex = def.evex;
}
Def.parseVexString = function (vstr) {
var vdef = {
vvvv: '',
L: 0,
pp: 0,
mmmmm: 1,
W: 1,
WIG: false,
};
if (vstr.indexOf('NDS') > -1)
vdef.vvvv = 'NDS';
else if (vstr.indexOf('NDD') > -1)
vdef.vvvv = 'NDD';
else if (vstr.indexOf('DDS') > -1)
vdef.vvvv = 'DDS';
if (vstr.indexOf('256') > -1)
vdef.L = 1;
else if (vstr.indexOf('512') > -1)
vdef.L = 2;
if (vstr.indexOf('.66.') > -1)
vdef.pp = 1;
else if (vstr.indexOf('.F2.') > -1)
vdef.pp = 3;
else if (vstr.indexOf('.F3.') > -1)
vdef.pp = 2;
if (vstr.indexOf('0F38') > -1)
vdef.mmmmm = 2;
else if (vstr.indexOf('0F3A') > -1)
vdef.mmmmm = 3;
else if (vstr.indexOf('0F') > -1)
vdef.mmmmm = 1;
if (vstr.indexOf('W0') > -1)
vdef.W = 0;
if (vstr.indexOf('WIG') > -1)
vdef.WIG = true;
return vdef;
};
Def.parseEvexString = function (estr) {
return Def.parseVexString(estr);
};
Def.prototype.matchOperandTemplate = function (tpl, operand) {

@@ -80,2 +133,12 @@ var OperandClass = tpl;

return 'r64';
if (operand === o.RegisterSegment)
return 'sreg';
if (operand === o.RegisterMmx)
return 'mmx';
if (operand === o.RegisterXmm)
return 'xmm';
if (operand === o.RegisterYmm)
return 'ymm';
if (operand === o.RegisterZmm)
return 'zmm';
if (operand === o.Memory)

@@ -103,2 +166,43 @@ return 'm';

};
Def.prototype.toJson = function () {
var json = _super.prototype.toJson.call(this);
if (this.opreg > 0)
json.opcodeExtensionInModrm = this.opreg;
if (this.regInOp)
json.registerInOpcode = true;
json.operandEncoding = this.opEncoding;
if (this.lock)
json.lock = true;
if (this.opcodeDirectionBit)
json.setOpcodeDirectionBit = true;
if (this.vex)
json.vex = this.vex;
if (this.evex)
json.evex = this.evex;
if (this.prefixes)
json.extraPrefixes = this.prefixes;
if (this.rep)
json.prefixRep = true;
if (this.repne)
json.prefixRepne = true;
if (this.rex)
json.rex = this.rex;
if (!this.useModrm)
json.skipMorm = true;
if (this.mode) {
json.mode = [];
if (this.mode & t.MODE.X32)
json.mode.push('x32');
if (this.mode & t.MODE.X64)
json.mode.push('x64');
}
if (this.extensions) {
json.extensions = [];
for (var _i = 0, _a = this.extensions; _i < _a.length; _i++) {
var ext = _a[_i];
json.extensions.push(t.EXT[ext]);
}
}
return json;
};
Def.prototype.toString = function () {

@@ -109,7 +213,9 @@ var opregstr = '';

var lock = this.lock ? ' LOCK' : '';
var rex = this.mandatoryRex ? ' REX' : '';
var rex = this.rex ? ' REX ' + this.rex : '';
var vex = this.vex ? ' VEX ' + JSON.stringify(this.vex) : '';
var evex = this.evex ? ' EVEX ' + JSON.stringify(this.evex) : '';
var dbit = '';
if (this.opcodeDirectionBit)
dbit = ' d-bit';
return _super.prototype.toString.call(this) + opregstr + lock + rex + dbit;
return _super.prototype.toString.call(this) + opregstr + lock + rex + vex + evex + dbit;
};

@@ -125,2 +231,13 @@ return Def;

}
DefGroup.prototype.createDefinitions = function (defs, defaults) {
_super.prototype.createDefinitions.call(this, defs, defaults);
var group_defaults = defs[0];
group_defaults = util_1.extend({}, defaults, group_defaults);
this.defaultOperandSize = group_defaults.ds;
};
DefGroup.prototype.toJson = function () {
var json = _super.prototype.toJson.call(this);
json.defaultOperandSize = this.defaultOperandSize;
return json;
};
return DefGroup;

@@ -127,0 +244,0 @@ }(d.DefGroup));

@@ -7,5 +7,54 @@ import * as d from '../def';

import * as o from './operand';
import {extend} from '../util';
import {IVexDefinition} from "./table";
export type IVexDefinition = t.IVexDefinition;
export type IEvexDefinition = t.IEvexDefinition;
export class Def extends d.Def {
// 256.66.0F3A.W0 => {L: 1, pp: 1, mmmmm: 1, W: 0}
static parseVexString(vstr: string): IVexDefinition {
var vdef: t.IVexDefinition = {
vvvv: '',
L: 0b0,
pp: 0b00,
mmmmm: 0b00001, // 00000B is reserved, will #UD
W: 0b1, // Inverted, 1 means 2-byte VEX, or ignored.
WIG: false,
};
// vvvv: NDS, NDD, DDS
if(vstr.indexOf('NDS') > -1) vdef.vvvv = 'NDS';
else if(vstr.indexOf('NDD') > -1) vdef.vvvv = 'NDD';
else if(vstr.indexOf('DDS') > -1) vdef.vvvv = 'DDS';
// L: 128, 256, LIG, LZ
if(vstr.indexOf('256') > -1) vdef.L = 0b1;
else if(vstr.indexOf('512') > -1) vdef.L = 0b10; // EVEX
// pp: 66, F2, F3
if(vstr.indexOf('.66.') > -1) vdef.pp = 0b01;
else if(vstr.indexOf('.F2.') > -1) vdef.pp = 0b11;
else if(vstr.indexOf('.F3.') > -1) vdef.pp = 0b10;
// mmmmm: 0F, 0F3A, 0F38
if(vstr.indexOf('0F38') > -1) vdef.mmmmm = 0b00010;
else if(vstr.indexOf('0F3A') > -1) vdef.mmmmm = 0b00011;
else if(vstr.indexOf('0F') > -1) vdef.mmmmm = 0b00001; // Could still be 2-byte VEX prefix
// W: W0, W1
if(vstr.indexOf('W0') > -1) vdef.W = 0b0;
// WIG
if(vstr.indexOf('WIG') > -1) vdef.WIG = true;
return vdef;
}
static parseEvexString(estr: string): t.IEvexDefinition {
return Def.parseVexString(estr) as t.IEvexDefinition;
}
opreg: number;

@@ -17,3 +66,2 @@ operands: (t.TOperandTemplate[])[];

opcodeDirectionBit: boolean;
mandatoryRex: boolean;
useModrm: boolean;

@@ -23,2 +71,8 @@ rep: boolean;

prefixes: number[];
opEncoding: string;
rex: t.TRexDefinition;
vex: t.IVexDefinition;
evex: t.IEvexDefinition;
mode: t.MODE;
extensions: t.EXT[];

@@ -34,3 +88,3 @@

this.opcodeDirectionBit = def.dbit;
this.mandatoryRex = def.rex;
this.rex = def.rex;
this.useModrm = def.mr;

@@ -40,2 +94,11 @@ this.rep = def.rep;

this.prefixes = def.pfx;
this.opEncoding = def.en;
this.mode = def.mod;
this.extensions = def.ext;
if(typeof def.vex === 'string') this.vex = Def.parseVexString(def.vex as string);
else this.vex = def.vex as t.IVexDefinition;
if(typeof def.evex === 'string') this.evex = Def.parseEvexString(def.evex as string);
else this.evex = def.evex as t.IEvexDefinition;
}

@@ -61,12 +124,12 @@

else if(typeof operand === 'function') {
if(operand === oo.Immediate) return 'imm';
if(operand === oo.Immediate8) return 'imm8';
if(operand === oo.Immediate16) return 'imm16';
if(operand === oo.Immediate32) return 'imm32';
if(operand === oo.Immediate64) return 'imm64';
if(operand === oo.ImmediateUnsigned) return 'immu';
if(operand === oo.ImmediateUnsigned8) return 'immu8';
if(operand === oo.ImmediateUnsigned16) return 'immu16';
if(operand === oo.ImmediateUnsigned32) return 'immu32';
if(operand === oo.ImmediateUnsigned64) return 'immu64';
if(operand === oo.Immediate) return 'imm';
if(operand === oo.Immediate8) return 'imm8';
if(operand === oo.Immediate16) return 'imm16';
if(operand === oo.Immediate32) return 'imm32';
if(operand === oo.Immediate64) return 'imm64';
if(operand === oo.ImmediateUnsigned) return 'immu';
if(operand === oo.ImmediateUnsigned8) return 'immu8';
if(operand === oo.ImmediateUnsigned16) return 'immu16';
if(operand === oo.ImmediateUnsigned32) return 'immu32';
if(operand === oo.ImmediateUnsigned64) return 'immu64';
if(operand === o.Register) return 'r';

@@ -77,2 +140,7 @@ if(operand === o.Register8) return 'r8';

if(operand === o.Register64) return 'r64';
if(operand === o.RegisterSegment) return 'sreg';
if(operand === o.RegisterMmx) return 'mmx';
if(operand === o.RegisterXmm) return 'xmm';
if(operand === o.RegisterYmm) return 'ymm';
if(operand === o.RegisterZmm) return 'zmm';
if(operand === o.Memory) return 'm';

@@ -90,2 +158,36 @@ if(operand === o.Memory8) return 'm8';

toJson() {
var json = super.toJson();
if(this.opreg > 0) json.opcodeExtensionInModrm = this.opreg;
if(this.regInOp) json.registerInOpcode = true;
json.operandEncoding = this.opEncoding;
if(this.lock) json.lock = true;
if(this.opcodeDirectionBit) json.setOpcodeDirectionBit = true;
if(this.vex) json.vex = this.vex;
if(this.evex) json.evex = this.evex;
if(this.prefixes) json.extraPrefixes = this.prefixes;
if(this.rep) json.prefixRep = true;
if(this.repne) json.prefixRepne = true;
if(this.rex) json.rex = this.rex;
if(!this.useModrm) json.skipMorm = true;
if(this.mode) {
json.mode = [];
if(this.mode & t.MODE.X32) json.mode.push('x32');
if(this.mode & t.MODE.X64) json.mode.push('x64');
}
if(this.extensions) {
json.extensions = [];
for(var ext of this.extensions) json.extensions.push(t.EXT[ext]);
}
return json;
}
toString() {

@@ -96,3 +198,5 @@ var opregstr = '';

var lock = this.lock ? ' LOCK' : '';
var rex = this.mandatoryRex ? ' REX' : '';
var rex = this.rex ? ' REX ' + this.rex : '';
var vex = this.vex ? ' VEX ' + JSON.stringify(this.vex) : '';
var evex = this.evex ? ' EVEX ' + JSON.stringify(this.evex) : '';

@@ -102,3 +206,3 @@ var dbit = '';

return super.toString() + opregstr + lock + rex + dbit;
return super.toString() + opregstr + lock + rex + vex + evex + dbit;
}

@@ -110,2 +214,17 @@ }

DefClass = Def;
defaultOperandSize: number;
createDefinitions(defs: t.Definition[], defaults: t.Definition) {
super.createDefinitions(defs, defaults);
var [group_defaults, ] = defs;
group_defaults = extend({}, defaults, group_defaults);
this.defaultOperandSize = group_defaults.ds;
}
toJson() {
var json = super.toJson();
json.defaultOperandSize = this.defaultOperandSize;
return json;
}
}

@@ -112,0 +231,0 @@

@@ -21,2 +21,25 @@ "use strict";

exports.Expression = Expression;
var TemplateLock = (function (_super) {
__extends(TemplateLock, _super);
function TemplateLock() {
_super.apply(this, arguments);
this.name = 'lock';
this.octets = [p.PREFIX.LOCK];
}
return TemplateLock;
}(i.Template));
exports.TemplateLock = TemplateLock;
var TemplateRex = (function (_super) {
__extends(TemplateRex, _super);
function TemplateRex(args) {
_super.call(this, args);
this.name = 'rex';
this.args = [0, 0, 0, 0];
var _a = this.args, W = _a[0], R = _a[1], X = _a[2], B = _a[3];
var rex = new p.PrefixRex(W, R, X, B);
rex.write(this.octets);
}
return TemplateRex;
}(i.Template));
exports.TemplateRex = TemplateRex;
var Align = (function (_super) {

@@ -53,2 +76,3 @@ __extends(Align, _super);

this.prefixes = [];
this.pfxEx = null;
this.opcode = new p.Opcode;

@@ -70,2 +94,3 @@ this.modrm = null;

this.prefixes = [];
this.pfxEx = null;
this.opcode = new p.Opcode;

@@ -103,2 +128,4 @@ this.modrm = null;

}
if (this.pfxEx)
this.pfxEx.write(arr);
};

@@ -163,2 +190,4 @@ Instruction.prototype.write = function (arr) {

this.pfxLock = new p.PrefixLock;
this.length++;
this.lengthMax++;
return this;

@@ -220,12 +249,13 @@ };

};
Instruction.prototype.toString = function (margin, hex) {
if (margin === void 0) { margin = ' '; }
if (hex === void 0) { hex = true; }
var parts = [];
Instruction.prototype.toStringExpression = function () {
var expression = _super.prototype.toStringExpression.call(this);
if (this.pfxLock)
parts.push(this.pfxLock.toString());
expression += " {" + this.pfxLock.toString() + "}";
if (this.pfxSegment)
parts.push(this.pfxSegment.toString());
parts.push(_super.prototype.toString.call(this, margin, hex));
return parts.join(' ');
expression += " {" + this.pfxSegment.toString() + "}";
if (this.opts.mask)
expression += " {" + this.opts.mask.toString() + "}";
if (this.opts.z)
expression += " {z}";
return expression;
};

@@ -259,2 +289,6 @@ Instruction.prototype.needsOperandSizeOverride = function () {

}
if (this.def.vex)
this.createVexPrefix();
else if (this.def.evex)
this.createEvexPrefix();
if (this.def.prefixes) {

@@ -269,2 +303,106 @@ for (var _i = 0, _a = this.def.prefixes; _i < _a.length; _i++) {

};
Instruction.prototype.createVexPrefix = function () {
var R = 1, X = 1, B = 1, vvvv = 15;
var pos = this.def.opEncoding.indexOf('v');
if (pos > -1) {
var reg = this.ops.getAtIndexOfClass(pos, o.Register);
if (!reg)
throw Error("Could not find Register operand at position " + pos + " to encode VEX.vvvv");
vvvv = (~reg.get4bitId()) & 15;
}
pos = this.def.opEncoding.indexOf('r');
if (pos > -1) {
var reg = this.ops.getAtIndexOfClass(pos, o.Register);
if (!reg)
throw Error("Could not find Register operand at position " + pos + " to encode VEX.R");
if (reg.idSize() > 3)
R = 0;
}
pos = this.def.opEncoding.indexOf('m');
if (pos > -1) {
var reg = this.ops.getAtIndexOfClass(pos, o.Register);
if (reg && (reg.idSize() > 3))
B = 0;
}
var mem = this.ops.getMemoryOperand();
if (mem) {
if (mem.base && (mem.base.idSize() > 3))
B = 0;
if (mem.index && (mem.index.idSize() > 3))
X = 0;
}
this.pfxEx = new p.PrefixVex(this.def.vex, R, X, B, vvvv);
this.length += this.pfxEx.bytes;
this.lengthMax += this.pfxEx.bytes;
};
Instruction.prototype.createEvexPrefix = function () {
var evex = this.pfxEx = new p.PrefixEvex(this.def.evex);
this.length += 3;
this.lengthMax += 3;
var pos = this.def.opEncoding.indexOf('v');
if (pos > -1) {
var reg = this.ops.getAtIndexOfClass(pos, o.Register);
if (!reg)
throw Error("Could not find Register operand at position " + pos + " to encode EVEX.vvvv");
evex.vvvv = (~reg.get4bitId()) & 15;
evex.Vp = reg.id & 16 ? 0 : 1;
}
pos = this.def.opEncoding.indexOf('r');
if (pos > -1) {
var reg = this.ops.getAtIndexOfClass(pos, o.Register);
if (!reg)
throw Error("Could not find Register operand at position " + pos + " to encode VEX.R");
var id_size = reg.idSize();
if (id_size > 3)
evex.R = 0;
if (id_size > 4) {
evex.Rp = 0;
if (reg.id & 8)
evex.R = 0;
else
evex.R = 1;
}
}
pos = this.def.opEncoding.indexOf('m');
if (pos > -1) {
var reg = this.ops.getAtIndexOfClass(pos, o.Register);
if (reg) {
if (reg.idSize() > 3)
evex.B = 0;
if (reg.idSize() > 4) {
evex.X = 0;
if (reg.id & 8)
evex.B = 0;
else
evex.B = 1;
}
}
}
var mem = this.ops.getMemoryOperand();
if (mem) {
if (mem.base && (mem.base.idSize() > 3))
evex.B = 0;
if (mem.index && (mem.index.idSize() > 3))
evex.X = 0;
}
if (this.opts.mask)
this.mask(this.opts.mask);
if (typeof this.opts.z !== 'undefined')
this.z(this.opts.z);
};
Instruction.prototype.mask = function (k) {
if (!(this.pfxEx instanceof p.PrefixEvex))
throw Error('Cannot set mask on non-EVEX instruction.');
if (k.id === 0)
throw TypeError('Mask register 000 cannot be used as mask.');
this.pfxEx.aaa = k.get3bitId();
return this;
};
Instruction.prototype.z = function (value) {
if (value === void 0) { value = 1; }
if (!(this.pfxEx instanceof p.PrefixEvex))
throw Error('Cannot set z-bit on non-EVEX instruction.');
this.pfxEx.z = value ? 1 : 0;
return this;
};
Instruction.prototype.createOpcode = function () {

@@ -276,4 +414,4 @@ var def = this.def;

if (def.regInOp) {
if (!dst || !dst.isRegister())
throw TypeError("Operation needs destination register.");
if (!dst || (!dst.isRegister()))
throw TypeError("Operation needs destination Register.");
opcode.op = (opcode.op & p.Opcode.MASK_OP) | dst.get3bitId();

@@ -305,2 +443,4 @@ }

return;
var encoding = this.def.opEncoding;
var mod = 0, reg = 0, rm = 0;
var _a = this.ops.list, dst = _a[0], src = _a[1];

@@ -310,4 +450,3 @@ var has_opreg = (this.def.opreg > -1);

if (has_opreg || dst_in_modrm) {
var mod = 0, reg = 0, rm = 0;
var reg_is_dst = !!(this.opcode.op & p.Opcode.DIRECTION.REG_IS_DST);
var reg_is_dst = this.def.opEncoding[0] !== 'm' ? true : false;
if (has_opreg) {

@@ -326,9 +465,41 @@ reg = this.def.opreg;

else {
var r = this.ops.getRegisterOperand(reg_is_dst);
if (r) {
if ((encoding.length === 2) && (dst instanceof o.Register) && (src instanceof o.Register)) {
mod = p.Modrm.MOD.REG_TO_REG;
reg = r.get3bitId();
var regreg = (reg_is_dst ? dst : src);
var rmreg = (reg_is_dst ? src : dst);
reg = regreg.get3bitId();
rm = rmreg.get3bitId();
this.modrm = new p.Modrm(mod, reg, rm);
this.length++;
this.lengthMax++;
return;
}
var rpos = encoding.indexOf('r');
var rreg;
if ((rpos > -1) && (rreg = this.ops.getAtIndexOfClass(rpos, o.Register))) {
reg = rreg.get3bitId();
}
else {
var r = this.ops.getRegisterOperand(this.regToRegDirectionRegIsDst ? 0 : 1);
if (!r)
r = this.ops.getRegisterOperand();
if (r) {
mod = p.Modrm.MOD.REG_TO_REG;
reg = r.get3bitId();
}
}
}
if (!dst) {
var mpos = encoding.indexOf('m');
if (mpos > -1) {
var mreg = this.ops.getAtIndexOfClass(mpos, o.Register);
if (mreg) {
mod = p.Modrm.MOD.REG_TO_REG;
rm = mreg.get3bitId();
this.modrm = new p.Modrm(mod, reg, rm);
this.length++;
this.lengthMax++;
return;
}
}
else {
this.modrm = new p.Modrm(mod, reg, rm);

@@ -339,6 +510,3 @@ this.length++;

}
if ((dst instanceof o.Register) && (src instanceof o.Register)) {
mod = p.Modrm.MOD.REG_TO_REG;
var rmreg = (reg_is_dst ? src : dst);
rm = rmreg.get3bitId();
if (!dst) {
this.modrm = new p.Modrm(mod, reg, rm);

@@ -345,0 +513,0 @@ this.length++;

@@ -8,2 +8,3 @@ import {SIZE} from '../operand';

import * as d from './def';
import * as c from './code';

@@ -16,2 +17,20 @@

export class TemplateLock extends i.Template {
name = 'lock';
octets = [p.PREFIX.LOCK];
}
export class TemplateRex extends i.Template {
name = 'rex';
args = [0, 0, 0, 0];
constructor(args) {
super(args);
var [W, R, X, B] = this.args;
var rex = new p.PrefixRex(W, R, X, B);
rex.write(this.octets);
}
}
export class Align extends i.Align {

@@ -61,2 +80,3 @@

ops: o.Operands;
opts: c.IInstructionOptions;

@@ -71,2 +91,3 @@ // Instruction parts.

prefixes: p.PrefixStatic[] = [];
pfxEx: p.PrefixRex|p.PrefixVex|p.PrefixEvex = null; // One of REX, VEX, EVEX prefixes, only one allowed.
opcode: p.Opcode = new p.Opcode; // required

@@ -93,2 +114,3 @@ modrm: p.Modrm = null;

this.prefixes = [];
this.pfxEx = null;
this.opcode = new p.Opcode; // required

@@ -113,9 +135,10 @@ this.modrm = null;

protected writePrefixes(arr: number[]) {
if(this.pfxLock) this.pfxLock.write(arr);
if(this.pfxRep) this.pfxRep.write(arr);
if(this.pfxRepne) this.pfxRepne.write(arr);
if(this.pfxAddrSize) this.pfxAddrSize.write(arr);
if(this.pfxSegment) this.pfxSegment.write(arr);
if(this.pfxOpSize) this.pfxOpSize.write(arr);
if(this.pfxLock) this.pfxLock.write(arr);
if(this.pfxRep) this.pfxRep.write(arr);
if(this.pfxRepne) this.pfxRepne.write(arr);
if(this.pfxAddrSize) this.pfxAddrSize.write(arr);
if(this.pfxSegment) this.pfxSegment.write(arr);
if(this.pfxOpSize) this.pfxOpSize.write(arr);
for(var pfx of this.prefixes) pfx.write(arr);
if(this.pfxEx) this.pfxEx.write(arr);
}

@@ -181,2 +204,4 @@

this.pfxLock = new p.PrefixLock;
this.length++;
this.lengthMax++;
return this;

@@ -252,8 +277,9 @@ }

toString(margin = ' ', hex = true) {
var parts = [];
if(this.pfxLock) parts.push(this.pfxLock.toString());
if(this.pfxSegment) parts.push(this.pfxSegment.toString());
parts.push(super.toString(margin, hex));
return parts.join(' ');
protected toStringExpression() {
var expression = super.toStringExpression();
if(this.pfxLock) expression += ` {${this.pfxLock.toString()}}`;
if(this.pfxSegment) expression += ` {${this.pfxSegment.toString()}}`;
if(this.opts.mask) expression += ` {${this.opts.mask.toString()}}`;
if(this.opts.z) expression += ` {z}`;
return expression;
}

@@ -288,2 +314,6 @@

if(this.def.vex) this.createVexPrefix();
else if(this.def.evex) this.createEvexPrefix();
// Mandatory prefixes required by op-code.

@@ -299,2 +329,104 @@ if(this.def.prefixes) {

protected createVexPrefix() {
// These bits in VEX are inverted, so they actually all mean "0" zeros.
var R = 1, X = 1, B = 1, vvvv = 0b1111;
var pos = this.def.opEncoding.indexOf('v');
if(pos > -1) {
var reg = this.ops.getAtIndexOfClass(pos, o.Register) as o.Register;
if(!reg) throw Error(`Could not find Register operand at position ${pos} to encode VEX.vvvv`);
vvvv = (~reg.get4bitId()) & 0b1111; // Inverted
}
pos = this.def.opEncoding.indexOf('r');
if(pos > -1) {
var reg = this.ops.getAtIndexOfClass(pos, o.Register) as o.Register;
if(!reg) throw Error(`Could not find Register operand at position ${pos} to encode VEX.R`);
if(reg.idSize() > 3) R = 0; // Inverted
}
pos = this.def.opEncoding.indexOf('m');
if(pos > -1) {
var reg = this.ops.getAtIndexOfClass(pos, o.Register) as o.Register;
if(reg && (reg.idSize() > 3)) B = 0; // Inverted
}
var mem = this.ops.getMemoryOperand() as o.Memory;
if(mem) {
if (mem.base && (mem.base.idSize() > 3)) B = 0;
if (mem.index && (mem.index.idSize() > 3)) X = 0;
}
this.pfxEx = new p.PrefixVex(this.def.vex, R, X, B, vvvv);
this.length += (this.pfxEx as p.PrefixVex).bytes;
this.lengthMax += (this.pfxEx as p.PrefixVex).bytes;
}
protected createEvexPrefix() {
var evex = this.pfxEx = new p.PrefixEvex(this.def.evex);
this.length += 3;
this.lengthMax += 3;
var pos = this.def.opEncoding.indexOf('v');
if(pos > -1) {
var reg = this.ops.getAtIndexOfClass(pos, o.Register) as o.Register;
if(!reg) throw Error(`Could not find Register operand at position ${pos} to encode EVEX.vvvv`);
evex.vvvv = (~reg.get4bitId()) & 0b1111; // Inverted
evex.Vp = reg.id & 0b10000 ? 0 : 1; // Inverted
}
pos = this.def.opEncoding.indexOf('r');
if(pos > -1) {
var reg = this.ops.getAtIndexOfClass(pos, o.Register) as o.Register;
if(!reg) throw Error(`Could not find Register operand at position ${pos} to encode VEX.R`);
var id_size = reg.idSize();
if(id_size > 3) evex.R = 0; // Inverted
if(id_size > 4) {
evex.Rp = 0; // Inverted
if(reg.id & 0b1000) evex.R = 0;
else evex.R = 1;
}
}
pos = this.def.opEncoding.indexOf('m');
if(pos > -1) {
var reg = this.ops.getAtIndexOfClass(pos, o.Register) as o.Register;
if(reg) {
if (reg.idSize() > 3) evex.B = 0; // Inverted
if (reg.idSize() > 4) {
evex.X = 0; // Inverted
if(reg.id & 0b1000) evex.B = 0;
else evex.B = 1;
}
}
}
var mem = this.ops.getMemoryOperand() as o.Memory;
if(mem) {
if (mem.base && (mem.base.idSize() > 3)) evex.B = 0; // Inverted
if (mem.index && (mem.index.idSize() > 3)) evex.X = 0; // Inverted
}
if(this.opts.mask) this.mask(this.opts.mask);
if(typeof this.opts.z !== 'undefined') this.z(this.opts.z);
}
// Set mask register for `EVEX` instructions.
mask(k: o.RegisterK): this {
if(!(this.pfxEx instanceof p.PrefixEvex))
throw Error('Cannot set mask on non-EVEX instruction.');
if(k.id === 0)
throw TypeError('Mask register 000 cannot be used as mask.');
(this.pfxEx as p.PrefixEvex).aaa = k.get3bitId();
return this;
}
// Set `z` bit for `EVEX` instructions.
z(value: number|boolean = 1): this {
if(!(this.pfxEx instanceof p.PrefixEvex))
throw Error('Cannot set z-bit on non-EVEX instruction.');
(this.pfxEx as p.PrefixEvex).z = value ? 1 : 0;
return this;
}
protected createOpcode() {

@@ -309,4 +441,4 @@ var def = this.def;

// We have register encoded in op-code here.
if(!dst || !(dst as oo.Operand).isRegister())
throw TypeError(`Operation needs destination register.`);
if(!dst || (!(dst as oo.Operand).isRegister()))
throw TypeError(`Operation needs destination Register.`);
opcode.op = (opcode.op & p.Opcode.MASK_OP) | (dst as o.Register).get3bitId();

@@ -347,2 +479,5 @@ } else {

var encoding = this.def.opEncoding;
var mod = 0, reg = 0, rm = 0;
var [dst, src] = this.ops.list;

@@ -352,5 +487,5 @@ var has_opreg = (this.def.opreg > -1);

if(has_opreg || dst_in_modrm) {
var mod = 0, reg = 0, rm = 0;
var reg_is_dst = !!(this.opcode.op & p.Opcode.DIRECTION.REG_IS_DST);
// var reg_is_dst = !!(this.opcode.op & p.Opcode.DIRECTION.REG_IS_DST);
var reg_is_dst = this.def.opEncoding[0] !== 'm' ? true : false;

@@ -360,3 +495,3 @@ if(has_opreg) {

reg = this.def.opreg;
var r: o.Register = this.ops.getRegisterOperand();
var r: o.Register = this.ops.getRegisterOperand() as o.Register;
if (r) {

@@ -371,11 +506,43 @@ mod = p.Modrm.MOD.REG_TO_REG;

} else {
// var r: o.Register = this.op.getRegisterOperand(this.regToRegDirectionRegIsDst);
var r: o.Register = this.ops.getRegisterOperand(reg_is_dst) as o.Register;
if (r) {
// Reg-to-reg instruction;
if((encoding.length === 2) && (dst instanceof o.Register) && (src instanceof o.Register)) {
mod = p.Modrm.MOD.REG_TO_REG;
reg = r.get3bitId();
var regreg: o.Register = (reg_is_dst ? dst : src) as o.Register;
var rmreg: o.Register = (reg_is_dst ? src : dst) as o.Register;
reg = regreg.get3bitId();
rm = rmreg.get3bitId();
this.modrm = new p.Modrm(mod, reg, rm);
this.length++;
this.lengthMax++;
return;
}
var rpos = encoding.indexOf('r');
var rreg;
if((rpos > -1) && (rreg = this.ops.getAtIndexOfClass(rpos, o.Register) as o.Register)) {
reg = rreg.get3bitId();
} else {
// var r: o.Register = this.op.getRegisterOperand(this.regToRegDirectionRegIsDst);
var r: o.Register = this.ops.getRegisterOperand(this.regToRegDirectionRegIsDst ? 0 : 1) as o.Register;
if(!r) r = this.ops.getRegisterOperand() as o.Register;
if(r) {
mod = p.Modrm.MOD.REG_TO_REG;
reg = r.get3bitId();
}
}
}
if(!dst) { // No destination operand, just opreg.
var mpos = encoding.indexOf('m');
if(mpos > -1) {
var mreg = this.ops.getAtIndexOfClass(mpos, o.Register) as o.Register;
if(mreg) {
mod = p.Modrm.MOD.REG_TO_REG;
rm = (mreg as o.Register).get3bitId();
this.modrm = new p.Modrm(mod, reg, rm);
this.length++;
this.lengthMax++;
return;
}
} else {
this.modrm = new p.Modrm(mod, reg, rm);

@@ -387,8 +554,3 @@ this.length++;

// Reg-to-reg instruction;
if((dst instanceof o.Register) && (src instanceof o.Register)) {
mod = p.Modrm.MOD.REG_TO_REG;
// var rmreg: o.Register = (this.regToRegDirectionRegIsDst ? src : dst) as o.Register;
var rmreg: o.Register = (reg_is_dst ? src : dst) as o.Register;
rm = rmreg.get3bitId();
if(!dst) { // No destination operand, just opreg.
this.modrm = new p.Modrm(mod, reg, rm);

@@ -402,5 +564,7 @@ this.length++;

// that EBP always has displacement value even if 0x00.
// Memory operand can be encoded in only one way (Modrm.rm + SIB) so we
// ignore here `def.opEncoding` field.
var m: o.Memory = this.ops.getMemoryOperand() as o.Memory;
if(!m) {
// throw Error('No Memory reference for Modrm byte.');
this.modrm = new p.Modrm(mod, reg, rm);

@@ -646,4 +810,1 @@ this.length++;

export interface InstructionSet {
pickShortestInstruction(): Instruction;
}

@@ -79,8 +79,13 @@ "use strict";

};
Register.prototype.get3bitId = function () {
return this.id & 7;
};
return Register;
}(operand_1.Register));
exports.Register = Register;
var RegisterGP = (function (_super) {
__extends(RegisterGP, _super);
function RegisterGP() {
_super.apply(this, arguments);
}
return RegisterGP;
}(Register));
exports.RegisterGP = RegisterGP;
var Register8 = (function (_super) {

@@ -92,3 +97,3 @@ __extends(Register8, _super);

return Register8;
}(Register));
}(RegisterGP));
exports.Register8 = Register8;

@@ -117,3 +122,3 @@ var Register8High = (function (_super) {

return Register32;
}(Register));
}(RegisterGP));
exports.Register32 = Register32;

@@ -126,3 +131,3 @@ var Register64 = (function (_super) {

return Register64;
}(Register));
}(RegisterGP));
exports.Register64 = Register64;

@@ -135,3 +140,3 @@ var Register128 = (function (_super) {

return Register128;
}(Register));
}(RegisterGP));
exports.Register128 = Register128;

@@ -144,3 +149,3 @@ var Register256 = (function (_super) {

return Register256;
}(Register));
}(RegisterGP));
exports.Register256 = Register256;

@@ -153,3 +158,3 @@ var Register512 = (function (_super) {

return Register512;
}(Register));
}(RegisterGP));
exports.Register512 = Register512;

@@ -159,33 +164,66 @@ var RegisterRip = (function (_super) {

function RegisterRip() {
_super.call(this, 0);
_super.call(this, 0, operand_1.SIZE.Q);
this.name = 'rip';
}
return RegisterRip;
}(Register64));
}(Register));
exports.RegisterRip = RegisterRip;
var RegisterSegment = (function (_super) {
__extends(RegisterSegment, _super);
function RegisterSegment() {
_super.apply(this, arguments);
function RegisterSegment(id) {
_super.call(this, id, operand_1.SIZE.W);
}
return RegisterSegment;
}(Register16));
}(Register));
exports.RegisterSegment = RegisterSegment;
var RegisterMmx = (function (_super) {
__extends(RegisterMmx, _super);
function RegisterMmx(id) {
_super.call(this, id);
this.name = 'mmx' + id;
var RegisterBounds = (function (_super) {
__extends(RegisterBounds, _super);
function RegisterBounds(id) {
_super.call(this, id, operand_1.SIZE.O);
}
return RegisterMmx;
}(Register128));
exports.RegisterMmx = RegisterMmx;
return RegisterBounds;
}(Register));
exports.RegisterBounds = RegisterBounds;
var RegisterFloatingPoint = (function (_super) {
__extends(RegisterFloatingPoint, _super);
function RegisterFloatingPoint() {
_super.apply(this, arguments);
}
return RegisterFloatingPoint;
}(Register));
exports.RegisterFloatingPoint = RegisterFloatingPoint;
var RegisterMm = (function (_super) {
__extends(RegisterMm, _super);
function RegisterMm(id) {
_super.call(this, id, operand_1.SIZE.O);
this.name = 'mm' + id;
}
return RegisterMm;
}(RegisterFloatingPoint));
exports.RegisterMm = RegisterMm;
var RegisterSt = (function (_super) {
__extends(RegisterSt, _super);
function RegisterSt(id) {
_super.call(this, id, operand_1.SIZE.T);
this.name = 'st' + id;
}
return RegisterSt;
}(RegisterFloatingPoint));
exports.RegisterSt = RegisterSt;
var RegisterVector = (function (_super) {
__extends(RegisterVector, _super);
function RegisterVector() {
_super.apply(this, arguments);
}
return RegisterVector;
}(Register));
exports.RegisterVector = RegisterVector;
var RegisterXmm = (function (_super) {
__extends(RegisterXmm, _super);
function RegisterXmm(id) {
_super.call(this, id);
_super.call(this, id, operand_1.SIZE.O);
this.name = 'xmm' + id;
}
return RegisterXmm;
}(Register128));
}(RegisterVector));
exports.RegisterXmm = RegisterXmm;

@@ -195,7 +233,7 @@ var RegisterYmm = (function (_super) {

function RegisterYmm(id) {
_super.call(this, id);
_super.call(this, id, operand_1.SIZE.H);
this.name = 'ymm' + id;
}
return RegisterYmm;
}(Register256));
}(RegisterVector));
exports.RegisterYmm = RegisterYmm;

@@ -205,114 +243,35 @@ var RegisterZmm = (function (_super) {

function RegisterZmm(id) {
_super.call(this, id);
_super.call(this, id, operand_1.SIZE.I);
this.name = 'zmm' + id;
}
return RegisterZmm;
}(Register512));
}(RegisterVector));
exports.RegisterZmm = RegisterZmm;
function validateRegId(id, min, max, Clazz) {
if (typeof id !== 'number')
throw TypeError(Clazz.name + ' register ID must be a number.');
if (id < min)
throw TypeError(Clazz.name + " register ID must be at least " + min + ".");
if (id > max)
throw TypeError(Clazz.name + " register ID must be at most " + max + ".");
}
function createRegisterGenerator(Clazz, min_id, max_id) {
if (min_id === void 0) { min_id = 0; }
if (max_id === void 0) { max_id = 15; }
var cache;
return function (id) {
validateRegId(id, min_id, max_id, Clazz);
if (!cache)
cache = new Array(max_id + 1);
if (!cache[id])
cache[id] = new Clazz(id);
return cache[id];
};
}
exports.rb = createRegisterGenerator(Register8, 0, 15);
exports.rw = createRegisterGenerator(Register16, 0, 15);
exports.rd = createRegisterGenerator(Register32, 0, 15);
exports.rq = createRegisterGenerator(Register64, 0, 15);
exports.r = exports.rq;
exports.rs = createRegisterGenerator(RegisterSegment, 0, 15);
exports.mmx = createRegisterGenerator(RegisterMmx, 0, 15);
exports.xmm = createRegisterGenerator(RegisterXmm, 0, 31);
exports.ymm = createRegisterGenerator(RegisterYmm, 0, 31);
exports.zmm = createRegisterGenerator(RegisterZmm, 0, 31);
exports.al = exports.rb(regfile_1.R8.AL);
exports.bl = exports.rb(regfile_1.R8.BL);
exports.cl = exports.rb(regfile_1.R8.CL);
exports.dl = exports.rb(regfile_1.R8.DL);
exports.sil = exports.rb(regfile_1.R8.SIL);
exports.dil = exports.rb(regfile_1.R8.DIL);
exports.bpl = exports.rb(regfile_1.R8.BPL);
exports.spl = exports.rb(regfile_1.R8.SPL);
exports.r8b = exports.rb(regfile_1.R8.R8B);
exports.r9b = exports.rb(regfile_1.R8.R9B);
exports.r10b = exports.rb(regfile_1.R8.R10B);
exports.r11b = exports.rb(regfile_1.R8.R11B);
exports.r12b = exports.rb(regfile_1.R8.R12B);
exports.r13b = exports.rb(regfile_1.R8.R13B);
exports.r14b = exports.rb(regfile_1.R8.R14B);
exports.r15b = exports.rb(regfile_1.R8.R15B);
exports.ah = new Register8High(regfile_1.R8H.AH);
exports.bh = new Register8High(regfile_1.R8H.BH);
exports.ch = new Register8High(regfile_1.R8H.CH);
exports.dh = new Register8High(regfile_1.R8H.DH);
exports.ax = exports.rw(regfile_1.R16.AX);
exports.bx = exports.rw(regfile_1.R16.BX);
exports.cx = exports.rw(regfile_1.R16.CX);
exports.dx = exports.rw(regfile_1.R16.DX);
exports.si = exports.rw(regfile_1.R16.SI);
exports.di = exports.rw(regfile_1.R16.DI);
exports.bp = exports.rw(regfile_1.R16.BP);
exports.sp = exports.rw(regfile_1.R16.SP);
exports.r8w = exports.rw(regfile_1.R16.R8W);
exports.r9w = exports.rw(regfile_1.R16.R9W);
exports.r10w = exports.rw(regfile_1.R16.R10W);
exports.r11w = exports.rw(regfile_1.R16.R11W);
exports.r12w = exports.rw(regfile_1.R16.R12W);
exports.r13w = exports.rw(regfile_1.R16.R13W);
exports.r14w = exports.rw(regfile_1.R16.R14W);
exports.r15w = exports.rw(regfile_1.R16.R15W);
exports.eax = exports.rd(regfile_1.R32.EAX);
exports.ebx = exports.rd(regfile_1.R32.EBX);
exports.ecx = exports.rd(regfile_1.R32.ECX);
exports.edx = exports.rd(regfile_1.R32.EDX);
exports.esi = exports.rd(regfile_1.R32.ESI);
exports.edi = exports.rd(regfile_1.R32.EDI);
exports.ebp = exports.rd(regfile_1.R32.EBP);
exports.esp = exports.rd(regfile_1.R32.ESP);
exports.r8d = exports.rd(regfile_1.R32.R8D);
exports.r9d = exports.rd(regfile_1.R32.R9D);
exports.r10d = exports.rd(regfile_1.R32.R10D);
exports.r11d = exports.rd(regfile_1.R32.R11D);
exports.r12d = exports.rd(regfile_1.R32.R12D);
exports.r13d = exports.rd(regfile_1.R32.R13D);
exports.r14d = exports.rd(regfile_1.R32.R14D);
exports.r15d = exports.rd(regfile_1.R32.R15D);
exports.rax = exports.rq(regfile_1.R64.RAX);
exports.rcx = exports.rq(regfile_1.R64.RCX);
exports.rdx = exports.rq(regfile_1.R64.RDX);
exports.rbx = exports.rq(regfile_1.R64.RBX);
exports.rsp = exports.rq(regfile_1.R64.RSP);
exports.rbp = exports.rq(regfile_1.R64.RBP);
exports.rsi = exports.rq(regfile_1.R64.RSI);
exports.rdi = exports.rq(regfile_1.R64.RDI);
exports.r8 = exports.rq(regfile_1.R64.R8);
exports.r9 = exports.rq(regfile_1.R64.R9);
exports.r10 = exports.rq(regfile_1.R64.R10);
exports.r11 = exports.rq(regfile_1.R64.R11);
exports.r12 = exports.rq(regfile_1.R64.R12);
exports.r13 = exports.rq(regfile_1.R64.R13);
exports.r14 = exports.rq(regfile_1.R64.R14);
exports.r15 = exports.rq(regfile_1.R64.R15);
exports.rip = new RegisterRip;
exports.es = exports.rs(regfile_1.SEG.ES);
exports.cs = exports.rs(regfile_1.SEG.CS);
exports.ss = exports.rs(regfile_1.SEG.SS);
exports.ds = exports.rs(regfile_1.SEG.DS);
exports.fs = exports.rs(regfile_1.SEG.FS);
exports.gs = exports.rs(regfile_1.SEG.GS);
var RegisterK = (function (_super) {
__extends(RegisterK, _super);
function RegisterK(id) {
_super.call(this, id, operand_1.SIZE.Q);
this.name = 'k' + id;
}
return RegisterK;
}(Register));
exports.RegisterK = RegisterK;
var RegisterCr = (function (_super) {
__extends(RegisterCr, _super);
function RegisterCr(id) {
_super.call(this, id, operand_1.SIZE.Q);
this.name = 'cr' + id;
}
return RegisterCr;
}(Register));
exports.RegisterCr = RegisterCr;
var RegisterDr = (function (_super) {
__extends(RegisterDr, _super);
function RegisterDr(id) {
_super.call(this, id, operand_1.SIZE.Q);
this.name = 'dr' + id;
}
return RegisterDr;
}(Register));
exports.RegisterDr = RegisterDr;
var Scale = (function (_super) {

@@ -453,2 +412,29 @@ __extends(Scale, _super);

exports.Memory64 = Memory64;
var Memory128 = (function (_super) {
__extends(Memory128, _super);
function Memory128() {
_super.apply(this, arguments);
this.size = operand_1.SIZE.O;
}
return Memory128;
}(Memory));
exports.Memory128 = Memory128;
var Memory256 = (function (_super) {
__extends(Memory256, _super);
function Memory256() {
_super.apply(this, arguments);
this.size = operand_1.SIZE.H;
}
return Memory256;
}(Memory));
exports.Memory256 = Memory256;
var Memory512 = (function (_super) {
__extends(Memory512, _super);
function Memory512() {
_super.apply(this, arguments);
this.size = operand_1.SIZE.I;
}
return Memory512;
}(Memory));
exports.Memory512 = Memory512;
var Operands = (function (_super) {

@@ -467,20 +453,2 @@ __extends(Operands, _super);

};
Operands.prototype.getRegisterOperand = function (dst_first) {
if (dst_first === void 0) { dst_first = true; }
var _a = this.list, dst = _a[0], src = _a[1];
var first, second;
if (dst_first) {
first = dst;
second = src;
}
else {
first = src;
second = dst;
}
if (first instanceof Register)
return first;
if (second instanceof Register)
return second;
return null;
};
Operands.prototype.hasImmediate = function () {

@@ -490,7 +458,16 @@ return !!this.getImmediate();

Operands.prototype.hasExtendedRegister = function () {
var _a = this.list, dst = _a[0], src = _a[1];
if (dst && dst.reg() && dst.reg().isExtended())
return true;
if (src && src.reg() && src.reg().isExtended())
return true;
for (var _i = 0, _a = this.list; _i < _a.length; _i++) {
var op = _a[_i];
if (op instanceof o.Register) {
if (op.idSize() > 3)
return true;
}
else if (op instanceof o.Memory) {
var mem = op;
if (mem.base && (mem.base.idSize() > 3))
return true;
if (mem.index && (mem.index.idSize() > 3))
return true;
}
}
return false;

@@ -501,1 +478,112 @@ };

exports.Operands = Operands;
function validateRegId(id, min, max, Clazz) {
if (typeof id !== 'number')
throw TypeError(Clazz.name + ' register ID must be a number.');
if (id < min)
throw TypeError(Clazz.name + " register ID must be at least " + min + ".");
if (id > max)
throw TypeError(Clazz.name + " register ID must be at most " + max + ".");
}
function createRegisterGenerator(Clazz, min_id, max_id) {
if (min_id === void 0) { min_id = 0; }
if (max_id === void 0) { max_id = 15; }
var cache;
return function (id) {
validateRegId(id, min_id, max_id, Clazz);
if (!cache)
cache = new Array(max_id + 1);
if (!cache[id])
cache[id] = new Clazz(id);
return cache[id];
};
}
exports.rb = createRegisterGenerator(Register8, 0, 15);
exports.rw = createRegisterGenerator(Register16, 0, 15);
exports.rd = createRegisterGenerator(Register32, 0, 15);
exports.rq = createRegisterGenerator(Register64, 0, 15);
exports.r = exports.rq;
exports.seg = createRegisterGenerator(RegisterSegment, 0, 15);
exports.mm = createRegisterGenerator(RegisterMm, 0, 15);
exports.st = createRegisterGenerator(RegisterSt, 0, 7);
exports.xmm = createRegisterGenerator(RegisterXmm, 0, 31);
exports.ymm = createRegisterGenerator(RegisterYmm, 0, 31);
exports.zmm = createRegisterGenerator(RegisterZmm, 0, 31);
exports.k = createRegisterGenerator(RegisterK, 0, 7);
exports.bnd = createRegisterGenerator(RegisterBounds, 0, 3);
exports.cr = createRegisterGenerator(RegisterCr, 0, 15);
exports.dr = createRegisterGenerator(RegisterDr, 0, 15);
exports.al = exports.rb(regfile_1.R8.AL);
exports.bl = exports.rb(regfile_1.R8.BL);
exports.cl = exports.rb(regfile_1.R8.CL);
exports.dl = exports.rb(regfile_1.R8.DL);
exports.sil = exports.rb(regfile_1.R8.SIL);
exports.dil = exports.rb(regfile_1.R8.DIL);
exports.bpl = exports.rb(regfile_1.R8.BPL);
exports.spl = exports.rb(regfile_1.R8.SPL);
exports.r8b = exports.rb(regfile_1.R8.R8B);
exports.r9b = exports.rb(regfile_1.R8.R9B);
exports.r10b = exports.rb(regfile_1.R8.R10B);
exports.r11b = exports.rb(regfile_1.R8.R11B);
exports.r12b = exports.rb(regfile_1.R8.R12B);
exports.r13b = exports.rb(regfile_1.R8.R13B);
exports.r14b = exports.rb(regfile_1.R8.R14B);
exports.r15b = exports.rb(regfile_1.R8.R15B);
exports.ah = new Register8High(regfile_1.R8H.AH);
exports.bh = new Register8High(regfile_1.R8H.BH);
exports.ch = new Register8High(regfile_1.R8H.CH);
exports.dh = new Register8High(regfile_1.R8H.DH);
exports.ax = exports.rw(regfile_1.R16.AX);
exports.bx = exports.rw(regfile_1.R16.BX);
exports.cx = exports.rw(regfile_1.R16.CX);
exports.dx = exports.rw(regfile_1.R16.DX);
exports.si = exports.rw(regfile_1.R16.SI);
exports.di = exports.rw(regfile_1.R16.DI);
exports.bp = exports.rw(regfile_1.R16.BP);
exports.sp = exports.rw(regfile_1.R16.SP);
exports.r8w = exports.rw(regfile_1.R16.R8W);
exports.r9w = exports.rw(regfile_1.R16.R9W);
exports.r10w = exports.rw(regfile_1.R16.R10W);
exports.r11w = exports.rw(regfile_1.R16.R11W);
exports.r12w = exports.rw(regfile_1.R16.R12W);
exports.r13w = exports.rw(regfile_1.R16.R13W);
exports.r14w = exports.rw(regfile_1.R16.R14W);
exports.r15w = exports.rw(regfile_1.R16.R15W);
exports.eax = exports.rd(regfile_1.R32.EAX);
exports.ebx = exports.rd(regfile_1.R32.EBX);
exports.ecx = exports.rd(regfile_1.R32.ECX);
exports.edx = exports.rd(regfile_1.R32.EDX);
exports.esi = exports.rd(regfile_1.R32.ESI);
exports.edi = exports.rd(regfile_1.R32.EDI);
exports.ebp = exports.rd(regfile_1.R32.EBP);
exports.esp = exports.rd(regfile_1.R32.ESP);
exports.r8d = exports.rd(regfile_1.R32.R8D);
exports.r9d = exports.rd(regfile_1.R32.R9D);
exports.r10d = exports.rd(regfile_1.R32.R10D);
exports.r11d = exports.rd(regfile_1.R32.R11D);
exports.r12d = exports.rd(regfile_1.R32.R12D);
exports.r13d = exports.rd(regfile_1.R32.R13D);
exports.r14d = exports.rd(regfile_1.R32.R14D);
exports.r15d = exports.rd(regfile_1.R32.R15D);
exports.rax = exports.rq(regfile_1.R64.RAX);
exports.rcx = exports.rq(regfile_1.R64.RCX);
exports.rdx = exports.rq(regfile_1.R64.RDX);
exports.rbx = exports.rq(regfile_1.R64.RBX);
exports.rsp = exports.rq(regfile_1.R64.RSP);
exports.rbp = exports.rq(regfile_1.R64.RBP);
exports.rsi = exports.rq(regfile_1.R64.RSI);
exports.rdi = exports.rq(regfile_1.R64.RDI);
exports.r8 = exports.rq(regfile_1.R64.R8);
exports.r9 = exports.rq(regfile_1.R64.R9);
exports.r10 = exports.rq(regfile_1.R64.R10);
exports.r11 = exports.rq(regfile_1.R64.R11);
exports.r12 = exports.rq(regfile_1.R64.R12);
exports.r13 = exports.rq(regfile_1.R64.R13);
exports.r14 = exports.rq(regfile_1.R64.R14);
exports.r15 = exports.rq(regfile_1.R64.R15);
exports.rip = new RegisterRip;
exports.es = exports.seg(regfile_1.SEG.ES);
exports.cs = exports.seg(regfile_1.SEG.CS);
exports.ss = exports.seg(regfile_1.SEG.SS);
exports.ds = exports.seg(regfile_1.SEG.DS);
exports.fs = exports.seg(regfile_1.SEG.FS);
exports.gs = exports.seg(regfile_1.SEG.GS);

@@ -83,3 +83,3 @@ import {R64, R32, R16, R8, R8H, SEG, X87, XMM, YMM, ZMM} from './regfile';

disp(value: o.Tvariable): Memory {
disp(value: o.Tvariable|ii.Expression): Memory {
return (new Memory).ref(this).disp(value);

@@ -92,9 +92,7 @@ }

}
get3bitId() {
return this.id & 0b111;
}
}
export class Register8 extends Register {
export class RegisterGP extends Register {}
export class Register8 extends RegisterGP {
constructor(id: number) {

@@ -113,3 +111,3 @@ super(id, SIZE.B);

export class Register32 extends Register {
export class Register32 extends RegisterGP {
constructor(id: number) {

@@ -120,3 +118,3 @@ super(id, SIZE.D);

export class Register64 extends Register {
export class Register64 extends RegisterGP {
constructor(id: number) {

@@ -127,3 +125,3 @@ super(id, SIZE.Q);

export class Register128 extends Register {
export class Register128 extends RegisterGP {
constructor(id: number) {

@@ -134,3 +132,3 @@ super(id, SIZE.O);

export class Register256 extends Register {
export class Register256 extends RegisterGP {
constructor(id: number) {

@@ -141,3 +139,3 @@ super(id, SIZE.H);

export class Register512 extends Register {
export class Register512 extends RegisterGP {
constructor(id: number) {

@@ -148,23 +146,48 @@ super(id, SIZE.I);

export class RegisterRip extends Register64 {
export class RegisterRip extends Register {
name = 'rip';
constructor() {
super(0);
super(0, SIZE.Q);
}
}
export class RegisterSegment extends Register16 {
export class RegisterSegment extends Register {
constructor(id) {
super(id, SIZE.W);
}
}
export class RegisterBounds extends Register {
constructor(id) {
super(id, SIZE.O);
}
}
export class RegisterMmx extends Register128 {
export class RegisterFloatingPoint extends Register {
}
export class RegisterMm extends RegisterFloatingPoint {
constructor(id: number) {
super(id);
this.name = 'mmx' + id;
super(id, SIZE.O);
this.name = 'mm' + id;
}
}
export class RegisterXmm extends Register128 {
export class RegisterSt extends RegisterFloatingPoint {
constructor(id: number) {
super(id);
super(id, SIZE.T);
this.name = 'st' + id;
}
}
export class RegisterVector extends Register {
}
export class RegisterXmm extends RegisterVector {
constructor(id: number) {
super(id, SIZE.O);
this.name = 'xmm' + id;

@@ -174,5 +197,5 @@ }

export class RegisterYmm extends Register256 {
export class RegisterYmm extends RegisterVector {
constructor(id: number) {
super(id);
super(id, SIZE.H);
this.name = 'ymm' + id;

@@ -182,5 +205,5 @@ }

export class RegisterZmm extends Register512 {
export class RegisterZmm extends RegisterVector {
constructor(id: number) {
super(id);
super(id, SIZE.I);
this.name = 'zmm' + id;

@@ -190,121 +213,24 @@ }

export class RegisterK extends Register {
constructor(id: number) {
super(id, SIZE.Q);
this.name = 'k' + id;
}
}
function validateRegId(id: number, min, max, Clazz) {
if(typeof id !== 'number') throw TypeError(Clazz.name + ' register ID must be a number.');
if(id < min) throw TypeError(`${Clazz.name} register ID must be at least ${min}.`);
if(id > max) throw TypeError(`${Clazz.name} register ID must be at most ${max}.`);
export class RegisterCr extends Register { // Control registers.
constructor(id: number) {
super(id, SIZE.Q);
this.name = 'cr' + id;
}
}
function createRegisterGenerator<T>(Clazz, min_id = 0, max_id = 15) {
var cache: T[];
return function(id: number): T {
validateRegId(id, min_id, max_id, Clazz);
if(!cache) cache = new Array(max_id + 1);
if(!cache[id]) cache[id] = new Clazz(id);
return cache[id];
};
export class RegisterDr extends Register { // Debug registers.
constructor(id: number) {
super(id, SIZE.Q);
this.name = 'dr' + id;
}
}
export var rb = createRegisterGenerator<Register8>(Register8, 0, 15);
export var rw = createRegisterGenerator<Register16>(Register16, 0, 15);
export var rd = createRegisterGenerator<Register32>(Register32, 0, 15);
export var rq = createRegisterGenerator<Register64>(Register64, 0, 15);
export var r = rq;
export var rs = createRegisterGenerator<RegisterSegment>(RegisterSegment, 0, 15);
// SSE registers are lazy-created when used using function: `xmm(3)`; instead of pre-generated objects: xmm3.
export var mmx = createRegisterGenerator<RegisterMmx>(RegisterMmx, 0, 15);
export var xmm = createRegisterGenerator<RegisterXmm>(RegisterXmm, 0, 31);
export var ymm = createRegisterGenerator<RegisterYmm>(RegisterYmm, 0, 31);
export var zmm = createRegisterGenerator<RegisterZmm>(RegisterZmm, 0, 31);
export var al = rb(R8.AL);
export var bl = rb(R8.BL);
export var cl = rb(R8.CL);
export var dl = rb(R8.DL);
export var sil = rb(R8.SIL);
export var dil = rb(R8.DIL);
export var bpl = rb(R8.BPL);
export var spl = rb(R8.SPL);
export var r8b = rb(R8.R8B);
export var r9b = rb(R8.R9B);
export var r10b = rb(R8.R10B);
export var r11b = rb(R8.R11B);
export var r12b = rb(R8.R12B);
export var r13b = rb(R8.R13B);
export var r14b = rb(R8.R14B);
export var r15b = rb(R8.R15B);
export var ah = new Register8High(R8H.AH);
export var bh = new Register8High(R8H.BH);
export var ch = new Register8High(R8H.CH);
export var dh = new Register8High(R8H.DH);
export var ax = rw(R16.AX);
export var bx = rw(R16.BX);
export var cx = rw(R16.CX);
export var dx = rw(R16.DX);
export var si = rw(R16.SI);
export var di = rw(R16.DI);
export var bp = rw(R16.BP);
export var sp = rw(R16.SP);
export var r8w = rw(R16.R8W);
export var r9w = rw(R16.R9W);
export var r10w = rw(R16.R10W);
export var r11w = rw(R16.R11W);
export var r12w = rw(R16.R12W);
export var r13w = rw(R16.R13W);
export var r14w = rw(R16.R14W);
export var r15w = rw(R16.R15W);
export var eax = rd(R32.EAX);
export var ebx = rd(R32.EBX);
export var ecx = rd(R32.ECX);
export var edx = rd(R32.EDX);
export var esi = rd(R32.ESI);
export var edi = rd(R32.EDI);
export var ebp = rd(R32.EBP);
export var esp = rd(R32.ESP);
export var r8d = rd(R32.R8D);
export var r9d = rd(R32.R9D);
export var r10d = rd(R32.R10D);
export var r11d = rd(R32.R11D);
export var r12d = rd(R32.R12D);
export var r13d = rd(R32.R13D);
export var r14d = rd(R32.R14D);
export var r15d = rd(R32.R15D);
export var rax = rq(R64.RAX);
export var rcx = rq(R64.RCX);
export var rdx = rq(R64.RDX);
export var rbx = rq(R64.RBX);
export var rsp = rq(R64.RSP);
export var rbp = rq(R64.RBP);
export var rsi = rq(R64.RSI);
export var rdi = rq(R64.RDI);
export var r8 = rq(R64.R8);
export var r9 = rq(R64.R9);
export var r10 = rq(R64.R10);
export var r11 = rq(R64.R11);
export var r12 = rq(R64.R12);
export var r13 = rq(R64.R13);
export var r14 = rq(R64.R14);
export var r15 = rq(R64.R15);
export var rip = new RegisterRip;
export var es = rs(SEG.ES);
export var cs = rs(SEG.CS);
export var ss = rs(SEG.SS);
export var ds = rs(SEG.DS);
export var fs = rs(SEG.FS);
export var gs = rs(SEG.GS);
// # Scale

@@ -440,2 +366,14 @@ //

export class Memory128 extends Memory {
size = SIZE.O;
}
export class Memory256 extends Memory {
size = SIZE.H;
}
export class Memory512 extends Memory {
size = SIZE.I;
}
export type TInstructionOperand = Register|Memory|o.Immediate|Relative; // `Tnumber` gets converted to `Immediate` or `Relative` to current instruction. `Relative` is converted to `Immediate`.

@@ -453,16 +391,16 @@

getRegisterOperand(dst_first = true): Register {
var [dst, src] = this.list;
var first, second;
if(dst_first) {
first = dst;
second = src;
} else {
first = src;
second = dst;
}
if(first instanceof Register) return first as Register;
if(second instanceof Register) return second as Register;
return null;
}
// getRegisterOperand(dst_first = true): Register {
// var [dst, src] = this.list;
// var first, second;
// if(dst_first) {
// first = dst;
// second = src;
// } else {
// first = src;
// second = dst;
// }
// if(first instanceof Register) return first as Register;
// if(second instanceof Register) return second as Register;
// return null;
// }

@@ -474,7 +412,138 @@ hasImmediate(): boolean {

hasExtendedRegister(): boolean {
var [dst, src] = this.list;
if(dst && dst.reg() && (dst.reg() as Register).isExtended()) return true;
if(src && src.reg() && (src.reg() as Register).isExtended()) return true;
for(var op of this.list) {
if(op instanceof o.Register) {
if((op as o.Register).idSize() > 3) return true;
} else if(op instanceof o.Memory) {
var mem = op as Memory;
if(mem.base && (mem.base.idSize() > 3)) return true;
if(mem.index && (mem.index.idSize() > 3)) return true;
}
}
return false;
}
}
// ## Export Registers
function validateRegId(id: number, min, max, Clazz) {
if(typeof id !== 'number') throw TypeError(Clazz.name + ' register ID must be a number.');
if(id < min) throw TypeError(`${Clazz.name} register ID must be at least ${min}.`);
if(id > max) throw TypeError(`${Clazz.name} register ID must be at most ${max}.`);
}
function createRegisterGenerator<T>(Clazz, min_id = 0, max_id = 15) {
var cache: T[];
return function(id: number): T {
validateRegId(id, min_id, max_id, Clazz);
if(!cache) cache = new Array(max_id + 1);
if(!cache[id]) cache[id] = new Clazz(id);
return cache[id];
};
}
export var rb = createRegisterGenerator<Register8>(Register8, 0, 15);
export var rw = createRegisterGenerator<Register16>(Register16, 0, 15);
export var rd = createRegisterGenerator<Register32>(Register32, 0, 15);
export var rq = createRegisterGenerator<Register64>(Register64, 0, 15);
export var r = rq;
export var seg = createRegisterGenerator<RegisterSegment>(RegisterSegment, 0, 15);
export var mm = createRegisterGenerator<RegisterMm>(RegisterMm, 0, 15);
export var st = createRegisterGenerator<RegisterSt>(RegisterSt, 0, 7);
export var xmm = createRegisterGenerator<RegisterXmm>(RegisterXmm, 0, 31);
export var ymm = createRegisterGenerator<RegisterYmm>(RegisterYmm, 0, 31);
export var zmm = createRegisterGenerator<RegisterZmm>(RegisterZmm, 0, 31);
export var k = createRegisterGenerator<RegisterK>(RegisterK, 0, 7);
export var bnd = createRegisterGenerator<RegisterBounds>(RegisterBounds, 0, 3);
export var cr = createRegisterGenerator<RegisterCr>(RegisterCr, 0, 15);
export var dr = createRegisterGenerator<RegisterDr>(RegisterDr, 0, 15);
export var al = rb(R8.AL);
export var bl = rb(R8.BL);
export var cl = rb(R8.CL);
export var dl = rb(R8.DL);
export var sil = rb(R8.SIL);
export var dil = rb(R8.DIL);
export var bpl = rb(R8.BPL);
export var spl = rb(R8.SPL);
export var r8b = rb(R8.R8B);
export var r9b = rb(R8.R9B);
export var r10b = rb(R8.R10B);
export var r11b = rb(R8.R11B);
export var r12b = rb(R8.R12B);
export var r13b = rb(R8.R13B);
export var r14b = rb(R8.R14B);
export var r15b = rb(R8.R15B);
export var ah = new Register8High(R8H.AH);
export var bh = new Register8High(R8H.BH);
export var ch = new Register8High(R8H.CH);
export var dh = new Register8High(R8H.DH);
export var ax = rw(R16.AX);
export var bx = rw(R16.BX);
export var cx = rw(R16.CX);
export var dx = rw(R16.DX);
export var si = rw(R16.SI);
export var di = rw(R16.DI);
export var bp = rw(R16.BP);
export var sp = rw(R16.SP);
export var r8w = rw(R16.R8W);
export var r9w = rw(R16.R9W);
export var r10w = rw(R16.R10W);
export var r11w = rw(R16.R11W);
export var r12w = rw(R16.R12W);
export var r13w = rw(R16.R13W);
export var r14w = rw(R16.R14W);
export var r15w = rw(R16.R15W);
export var eax = rd(R32.EAX);
export var ebx = rd(R32.EBX);
export var ecx = rd(R32.ECX);
export var edx = rd(R32.EDX);
export var esi = rd(R32.ESI);
export var edi = rd(R32.EDI);
export var ebp = rd(R32.EBP);
export var esp = rd(R32.ESP);
export var r8d = rd(R32.R8D);
export var r9d = rd(R32.R9D);
export var r10d = rd(R32.R10D);
export var r11d = rd(R32.R11D);
export var r12d = rd(R32.R12D);
export var r13d = rd(R32.R13D);
export var r14d = rd(R32.R14D);
export var r15d = rd(R32.R15D);
export var rax = rq(R64.RAX);
export var rcx = rq(R64.RCX);
export var rdx = rq(R64.RDX);
export var rbx = rq(R64.RBX);
export var rsp = rq(R64.RSP);
export var rbp = rq(R64.RBP);
export var rsi = rq(R64.RSI);
export var rdi = rq(R64.RDI);
export var r8 = rq(R64.R8);
export var r9 = rq(R64.R9);
export var r10 = rq(R64.R10);
export var r11 = rq(R64.R11);
export var r12 = rq(R64.R12);
export var r13 = rq(R64.R13);
export var r14 = rq(R64.R14);
export var r15 = rq(R64.R15);
export var rip = new RegisterRip;
export var es = seg(SEG.ES);
export var cs = seg(SEG.CS);
export var ss = seg(SEG.SS);
export var ds = seg(SEG.DS);
export var fs = seg(SEG.FS);
export var gs = seg(SEG.GS);

@@ -126,2 +126,94 @@ "use strict";

exports.PrefixRex = PrefixRex;
var PrefixVex = (function (_super) {
__extends(PrefixVex, _super);
function PrefixVex(vexdef, R, X, B, vvvv) {
if (R === void 0) { R = 1; }
if (X === void 0) { X = 1; }
if (B === void 0) { B = 1; }
if (vvvv === void 0) { vvvv = 15; }
_super.call(this);
this.bytes = 2;
this.R = 1;
this.X = 1;
this.B = 1;
this.W = 1;
this.vvvv = 15;
this.mmmmm = 0;
this.L = 0;
this.pp = 0;
this.L = vexdef.L;
this.mmmmm = vexdef.mmmmm;
this.pp = vexdef.pp;
this.W = vexdef.W;
if (vexdef.WIG)
this.W = 0;
this.R = R;
this.X = X;
this.B = B;
this.vvvv = vvvv;
if ((this.X === 0) || (this.B === 0) ||
((this.W === 0) && !vexdef.WIG) ||
(this.mmmmm === PrefixVex.MMMMM.x0F3A) || (this.mmmmm === PrefixVex.MMMMM.x0F38))
this.promoteTo3bytes();
}
PrefixVex.prototype.promoteTo3bytes = function () {
this.bytes = 3;
};
PrefixVex.prototype.write = function (arr) {
if (this.bytes === 2) {
arr.push(197);
arr.push((this.R << 7) | (this.vvvv << 3) | (this.L << 2) | this.pp);
}
else {
arr.push(196);
arr.push((this.R << 7) | (this.X << 6) | (this.B << 5) | this.mmmmm);
arr.push((this.W << 7) | (this.vvvv << 3) | (this.L << 2) | this.pp);
}
return arr;
};
PrefixVex.PP = {
x66: 1,
xF2: 3,
xF3: 2,
};
PrefixVex.MMMMM = {
x0F38: 2,
x0F3A: 3,
x0F: 1,
};
return PrefixVex;
}(Prefix));
exports.PrefixVex = PrefixVex;
var PrefixEvex = (function (_super) {
__extends(PrefixEvex, _super);
function PrefixEvex(evexdef) {
_super.call(this);
this.R = 1;
this.X = 1;
this.B = 1;
this.W = 1;
this.vvvv = 15;
this.pp = 0;
this.mm = 0;
this.Rp = 1;
this.z = 0;
this.LL = 0;
this.b = 0;
this.Vp = 1;
this.aaa = 0;
this.LL = evexdef.L;
this.mm = evexdef.mmmmm & 3;
this.pp = evexdef.pp;
this.W = evexdef.W;
}
PrefixEvex.prototype.write = function (arr) {
arr.push(0x62);
arr.push((this.R << 7) | (this.X << 6) | (this.B << 5) | (this.Rp << 4) | this.mm);
arr.push((this.W << 7) | (this.vvvv << 3) | 4 | this.pp);
arr.push((this.z << 7) | (this.LL << 5) | (this.b << 4) | (this.Vp << 3) | this.aaa);
return arr;
};
return PrefixEvex;
}(Prefix));
exports.PrefixEvex = PrefixEvex;
var Opcode = (function (_super) {

@@ -128,0 +220,0 @@ __extends(Opcode, _super);

import {R64, R32, R16, R8} from './regfile';
import * as oo from '../operand';
import * as o from './operand';
import * as d from './def';

@@ -149,3 +150,152 @@

// ### 2-byte VEX:
// 76543210
// 11000100
//
// 76543210
// ||||||pp ---> pp
// |||||L -----> L
// |vvvv ------> vvvv
// R ----------> R
//
// ### 3-byte VEX:
// 76543210
// 11000101
//
// 76543210
// |||mmmmm ---> mmmmm
// ||B --------> B
// |X ---------> X
// R ----------> R
//
// 76543210
// ||||||pp ---> pp
// |||||L -----> L
// |vvvv ------> vvvv
// W ----------> W
export class PrefixVex extends Prefix {
static PP = {
x66: 0b01,
xF2: 0b11,
xF3: 0b10,
};
static MMMMM = {
x0F38: 0b00010,
x0F3A: 0b00011,
x0F: 0b00001,
};
bytes = 2; // VEX can be either 2 or 3 bytes.
// R, X, B, W and vvvv are inverted.
R = 1; // Must be 1, if not used, otherwise wrong instruction.
X = 1; // Must be 1, if not used, otherwise wrong instruction.
B = 1;
W = 1;
vvvv = 0b1111; // must be 0b1111, if not used, otherwise CPU will #UD
mmmmm = 0;
L = 0;
pp = 0;
constructor(vexdef: d.IVexDefinition, R = 1, X = 1, B = 1, vvvv = 0b1111) {
super();
this.L = vexdef.L;
this.mmmmm = vexdef.mmmmm;
this.pp = vexdef.pp;
this.W = vexdef.W;
if(vexdef.WIG) this.W = 0b0; // When WIG "W ignored", set to "0" to make compatible with GAS.
this.R = R;
this.X = X;
this.B = B;
this.vvvv = vvvv;
if((this.X === 0) || (this.B === 0) ||
((this.W === 0) && !vexdef.WIG) ||
(this.mmmmm === PrefixVex.MMMMM.x0F3A) || (this.mmmmm === PrefixVex.MMMMM.x0F38))
this.promoteTo3bytes();
}
promoteTo3bytes() {
this.bytes = 3;
}
write(arr: number[]): number[] {
if(this.bytes === 2) { // 2-byte VEX
arr.push(0b11000101); // 0xC5
arr.push((this.R << 7) | (this.vvvv << 3) | (this.L << 2) | this.pp);
} else { // 3-byte VEX
arr.push(0b11000100); // 0xC4
arr.push((this.R << 7) | (this.X << 6) | (this.B << 5) | this.mmmmm);
arr.push((this.W << 7) | (this.vvvv << 3) | (this.L << 2) | this.pp);
}
return arr;
}
}
// EVEX is 4 bytes:
// 62H
//
// 76543210
// ||||||mm ---> mm
// ||||00 -----> always 00
// |||~ -------> R-prime = Rp
// ||B --------> B
// |X ---------> X
// R ----------> R
//
// 76543210
// ||||||pp ---> pp
// |||||1 -----> always 1
// |vvvv-------> vvvv
// W ----------> W
//
// 76543210
// |||||aaa ---> aaa
// ||||~ ------> V-prime = Vp
// |||b -------> b
// |LL --------> LL
// z ----------> z
export class PrefixEvex extends Prefix {
// VEX includes
R = 0b1; // VEX.R - Inverted
X = 0b1; // VEX.X - Inverted
B = 0b1; // VEX.B - Inverted
W = 0b1; // VEX.W - Inverted
vvvv = 0b1111; // VEX.vvvv - Inverted
pp = 0b00; // VEX.pp
mm = 0b00; // Low 2 bits of VEX.mmmmm
// New in EVEX
Rp = 0b1; // REX.R extension - Inverted
z = 0b0; // Zeroing/merging
LL = 0b00; // Like VEX.L but extended to 2 bits.
b = 0b0; // Broadcast/RC/SAE context
Vp = 0b1; // VEX.vvvv exntension - Inverted
aaa = 0b000; // Opmask register ID
constructor(evexdef: d.IEvexDefinition) {
super();
this.LL = evexdef.L;
this.mm = evexdef.mmmmm & 0b11;
this.pp = evexdef.pp;
this.W = evexdef.W;
}
write(arr: number[]): number[] {
arr.push(0x62);
arr.push((this.R << 7) | (this.X << 6) | (this.B << 5) | (this.Rp << 4) | this.mm);
arr.push((this.W << 7) | (this.vvvv << 3) | 0b00000100 | this.pp);
arr.push((this.z << 7) | (this.LL << 5) | (this.b << 4) | (this.Vp << 3) | this.aaa);
return arr;
}
}
// ## Op-code

@@ -152,0 +302,0 @@ //

@@ -7,7 +7,64 @@ "use strict";

(function (MODE) {
MODE[MODE["REAL"] = 0] = "REAL";
MODE[MODE["COMPAT"] = 1] = "COMPAT";
MODE[MODE["X64"] = 2] = "X64";
MODE[MODE["REAL"] = 1] = "REAL";
MODE[MODE["PROT"] = 2] = "PROT";
MODE[MODE["COMP"] = 4] = "COMP";
MODE[MODE["LEG"] = 8] = "LEG";
MODE[MODE["OLD"] = 12] = "OLD";
MODE[MODE["X32"] = 16] = "X32";
MODE[MODE["X64"] = 32] = "X64";
MODE[MODE["X32_64"] = 48] = "X32_64";
MODE[MODE["ALL"] = 63] = "ALL";
})(exports.MODE || (exports.MODE = {}));
var MODE = exports.MODE;
(function (INS) {
INS[INS["NONE"] = 0] = "NONE";
INS[INS["MMX"] = 1] = "MMX";
INS[INS["AES_NI"] = 2] = "AES_NI";
INS[INS["CLMUL"] = 4] = "CLMUL";
INS[INS["FMA3"] = 8] = "FMA3";
})(exports.INS || (exports.INS = {}));
var INS = exports.INS;
(function (EXT) {
EXT[EXT["NONE"] = 0] = "NONE";
EXT[EXT["x86_64"] = 1] = "x86_64";
EXT[EXT["Intel_64"] = 2] = "Intel_64";
EXT[EXT["MPX"] = 3] = "MPX";
EXT[EXT["TXT"] = 4] = "TXT";
EXT[EXT["TSX"] = 5] = "TSX";
EXT[EXT["SGX"] = 6] = "SGX";
EXT[EXT["VT_x"] = 7] = "VT_x";
EXT[EXT["VT_d"] = 8] = "VT_d";
EXT[EXT["BMI1"] = 9] = "BMI1";
EXT[EXT["BMI2"] = 10] = "BMI2";
EXT[EXT["SHA"] = 11] = "SHA";
EXT[EXT["AES"] = 12] = "AES";
EXT[EXT["INVPCID"] = 13] = "INVPCID";
EXT[EXT["LZCNT"] = 14] = "LZCNT";
EXT[EXT["MMX"] = 15] = "MMX";
EXT[EXT["SSE"] = 16] = "SSE";
EXT[EXT["SSE2"] = 17] = "SSE2";
EXT[EXT["SSE3"] = 18] = "SSE3";
EXT[EXT["SSSE3"] = 19] = "SSSE3";
EXT[EXT["SSE4"] = 20] = "SSE4";
EXT[EXT["SSE4_1"] = 21] = "SSE4_1";
EXT[EXT["SSE4_2"] = 22] = "SSE4_2";
EXT[EXT["ADX"] = 23] = "ADX";
EXT[EXT["AVX"] = 24] = "AVX";
EXT[EXT["AVX2"] = 25] = "AVX2";
EXT[EXT["AVX3"] = 26] = "AVX3";
EXT[EXT["AVX512F"] = 26] = "AVX512F";
EXT[EXT["AVX512CDI"] = 27] = "AVX512CDI";
EXT[EXT["AVX512PFI"] = 28] = "AVX512PFI";
EXT[EXT["AVX512ERI"] = 29] = "AVX512ERI";
EXT[EXT["AVX512VL"] = 30] = "AVX512VL";
EXT[EXT["AVX512VLI"] = 31] = "AVX512VLI";
EXT[EXT["AVX512BW"] = 32] = "AVX512BW";
EXT[EXT["AVX512DQ"] = 33] = "AVX512DQ";
EXT[EXT["AVX512IFMA52"] = 34] = "AVX512IFMA52";
EXT[EXT["AVX512VBMI"] = 35] = "AVX512VBMI";
EXT[EXT["FMA3"] = 36] = "FMA3";
EXT[EXT["FMA4"] = 37] = "FMA4";
EXT[EXT["CDI"] = 38] = "CDI";
})(exports.EXT || (exports.EXT = {}));
var EXT = exports.EXT;
exports.M = MODE;

@@ -20,2 +77,10 @@ exports.r = operand_1.Register;

exports.sreg = operand_1.RegisterSegment;
exports.mm = operand_1.RegisterMm;
exports.st = operand_1.RegisterSt;
exports.xmm = operand_1.RegisterXmm;
exports.ymm = operand_1.RegisterYmm;
exports.zmm = operand_1.RegisterZmm;
exports.bnd = operand_1.RegisterBounds;
exports.cr = operand_1.RegisterCr;
exports.dr = operand_1.RegisterDr;
exports.m = operand_1.Memory;

@@ -26,7 +91,20 @@ exports.m8 = operand_1.Memory8;

exports.m64 = operand_1.Memory64;
exports.rm8 = [operand_1.Register8, operand_1.Memory];
exports.rm16 = [operand_1.Register16, operand_1.Memory];
exports.rm32 = [operand_1.Register32, operand_1.Memory];
exports.rm64 = [operand_1.Register64, operand_1.Memory];
exports.defaults = util_1.extend({}, t.defaults, { ds: table_1.S.D, lock: false, or: -1, r: false, dbit: false, rex: false, mr: true, rep: false, repne: false, pfx: null });
exports.m128 = operand_1.Memory128;
exports.m256 = operand_1.Memory256;
exports.m512 = operand_1.Memory512;
exports.rm8 = [exports.r8, exports.m];
exports.rm16 = [exports.r16, exports.m];
exports.rm32 = [exports.r32, exports.m];
exports.rm64 = [exports.r64, exports.m];
exports.xmmm = [exports.xmm, exports.m];
exports.xmm_xmmm = [exports.xmm, exports.xmmm];
exports.xmm_xmm_xmmm = [exports.xmm, exports.xmm, exports.xmmm];
exports.ymmm = [exports.ymm, exports.m];
exports.ymm_ymmm = [exports.ymm, exports.ymmm];
exports.ymm_ymm_ymmm = [exports.ymm, exports.ymm, exports.ymmm];
exports.zmmm = [exports.zmm, exports.m];
exports.zmm_zmmm = [exports.zmm, exports.zmmm];
exports.zmm_zmm_zmmm = [exports.zmm, exports.zmm, exports.zmmm];
exports.defaults = util_1.extend({}, t.defaults, { ds: table_1.S.D, lock: false, or: -1, i: null, r: false, dbit: false, rex: null, mr: true, rep: false, repne: false,
pfx: null, vex: null, evex: null, en: 'rm', mod: exports.M.ALL, ext: null });
exports.table = {

@@ -33,0 +111,0 @@ cpuid: [{ o: 0x0FA2 }],

import {extend} from '../util';
import {S, rel, rel8, rel16, rel32, imm, imm8, imm16, imm32, imm64, immu, immu8, immu16, immu32, immu64} from '../table';
import * as t from '../table';
import {Register, Register8, Register16, Register32, Register64, RegisterSegment,
Memory, Memory8, Memory16, Memory32, Memory64} from './operand';
import {
Register, Register8, Register16, Register32, Register64,
RegisterMm, RegisterSt, RegisterXmm, RegisterYmm, RegisterZmm,
RegisterSegment, RegisterCr, RegisterDr, RegisterBounds,
Memory, Memory8, Memory16, Memory32, Memory64, Memory128, Memory256, Memory512
} from './operand';
export enum MODE {
REAL,
COMPAT,
X64,
REAL = 0b1,
PROT = 0b10,
COMP = 0b100,
LEG = 0b1000,
OLD = MODE.COMP | MODE.LEG,
X32 = 0b10000,
X64 = 0b100000,
X32_64 = MODE.X32 | MODE.X64,
ALL = MODE.REAL | MODE.PROT | MODE.COMP | MODE.LEG | MODE.X32 | MODE.X64,
}
// Instructins
export enum INS {
NONE = 0b0,
MMX = 0b1,
AES_NI = 0b10,
CLMUL = 0b100,
FMA3 = 0b1000,
}
// Extensions
export enum EXT {
NONE,
x86_64,
Intel_64,
MPX,
TXT,
TSX,
SGX,
VT_x,
VT_d,
BMI1,
BMI2,
SHA,
AES,
INVPCID,
LZCNT,
MMX,
SSE,
SSE2,
SSE3,
SSSE3,
SSE4,
SSE4_1,
SSE4_2,
ADX,
AVX,
AVX2,
AVX3, // AVX-512
AVX512F = EXT.AVX3, // Foundation
AVX512CDI,
AVX512PFI,
AVX512ERI,
AVX512VL,
AVX512VLI,
AVX512BW,
AVX512DQ,
AVX512IFMA52,
AVX512VBMI,
FMA3,
FMA4,
CDI,
}
export var M = MODE;

@@ -23,2 +87,10 @@

export var sreg = RegisterSegment;
export var mm = RegisterMm;
export var st = RegisterSt;
export var xmm = RegisterXmm;
export var ymm = RegisterYmm;
export var zmm = RegisterZmm;
export var bnd = RegisterBounds;
export var cr = RegisterCr;
export var dr = RegisterDr;
export var m = Memory;

@@ -29,6 +101,18 @@ export var m8 = Memory8;

export var m64 = Memory64;
export var rm8 = [Register8, Memory];
export var rm16 = [Register16, Memory];
export var rm32 = [Register32, Memory];
export var rm64 = [Register64, Memory];
export var m128 = Memory128;
export var m256 = Memory256;
export var m512 = Memory512;
export var rm8 = [r8, m];
export var rm16 = [r16, m];
export var rm32 = [r32, m];
export var rm64 = [r64, m];
export var xmmm = [xmm, m];
export var xmm_xmmm = [xmm, xmmm];
export var xmm_xmm_xmmm = [xmm, xmm, xmmm];
export var ymmm = [ymm, m];
export var ymm_ymmm = [ymm, ymmm];
export var ymm_ymm_ymmm = [ymm, ymm, ymmm];
export var zmmm = [zmm, m];
export var zmm_zmmm = [zmm, zmmm];
export var zmm_zmm_zmmm = [zmm, zmm, zmmm];

@@ -38,5 +122,23 @@

typeof Register8 | typeof Register16 | typeof Register32 | typeof Register64 |
typeof RegisterMm | typeof RegisterSt |
typeof RegisterXmm | typeof RegisterYmm | typeof RegisterZmm |
typeof RegisterSegment | typeof RegisterCr | typeof RegisterDr |
typeof Memory8 | typeof Memory16 | typeof Memory32 | typeof Memory64;
export type TRexDefinition = [number, number, number, number];
// "VEX.DDS.LIG.66.0F38.W1" => {vvvv: 'DDS', L: 0, pp: 1, mmmmm: 2, W: 1}
export interface IVexDefinition {
L: number;
vvvv: string;
pp: number;
mmmmm: number;
W: number;
WIG: boolean;
}
export interface IEvexDefinition extends IVexDefinition {}
export interface Definition extends t.Definition {

@@ -47,5 +149,5 @@ ds?: number; // Default size, usually 32 bits on x64, some instructions default to 64 bits.

or?: number; // Opreg - 3bit opcode part in modrm.reg field, -1 if none.
i?: number; // Hex octet, when +i provided in x87 floating point operations.
r?: boolean; // 3bit register encoded in lowest opcode bits.
dbit?: boolean; // Whether it is allowed to change `d` bit in opcode.
rex?: boolean; // Whether REX prefix is mandatory for this instruction.
dbit?: boolean; // Whether it is allowed to change `d` bit in opcode. `en` encoding field is ignored then.
mr?: boolean; // Whether to include Mod-REG-R/M byte if deemed necessary.

@@ -55,2 +157,8 @@ rep?: boolean; // REP and REPE/REPZ prefix allowed.

pfx?: number[]; // List of mandatory prefixes.
en?: string; // Operand encoding, e.g. "rvmr" -> (1) modmr.reg; (2) VEX.vvv; (3) modrm.rm; (4) imm8
mod?: MODE; // CPU mode
rex?: TRexDefinition|boolean; // Whether REX prefix is mandatory for this instruction. Holds array of [W, R, X, B].
vex?: string|IVexDefinition; // VEX prefix definitions string as it appears in manual, e.g. "256.66.0F3A.W0"
evex?: string|IEvexDefinition; // VEX prefix definitions string as it appears in manual, e.g. "256.66.0F3A.W0"
ext?: EXT[]; // CPUID extensions required to run this instruction.
}

@@ -63,3 +171,4 @@ export type GroupDefinition = Definition[];

export var defaults: Definition = extend<Definition>({}, t.defaults,
{ds: S.D, lock: false, or: -1, r: false, dbit: false, rex: false, mr: true, rep: false, repne: false, pfx: null});
{ds: S.D, lock: false, or: -1, i: null, r: false, dbit: false, rex: null, mr: true, rep: false, repne: false,
pfx: null, vex: null, evex: null, en: 'rm', mod: M.ALL, ext: null});

@@ -66,0 +175,0 @@

@@ -12,5 +12,2 @@ "use strict";

var t = require('./table');
var util_1 = require('../../util');
exports.table = (new d.DefTable).create(t.table, t.defaults);
var methods = code.Code.attachMethods({}, exports.table);
var Code = (function (_super) {

@@ -20,3 +17,3 @@ __extends(Code, _super);

_super.apply(this, arguments);
this.methods = methods;
this.table = Code.table;
this.ClassInstruction = instruction_1.Instruction;

@@ -28,10 +25,7 @@ this.operandSize = operand_1.SIZE.D;

if (name === void 0) { name = 'start'; }
if (!Code._methodsAdded) {
util_1.extend(Code.prototype, methods);
Code._methodsAdded = true;
}
var newcode = new Code(name);
newcode.addMethods();
return newcode;
};
Code.table = exports.table;
Code.table = new d.DefTable(t.table, t.defaults);
Code._methodsAdded = false;

@@ -38,0 +32,0 @@ return Code;

@@ -9,9 +9,5 @@ import {SIZE, TUiOperand} from '../../operand';

export const table = (new d.DefTable).create(t.table, t.defaults);
const methods = code.Code.attachMethods({} as any, table);
export class Code extends code.Code {
static table = table;
static table = new d.DefTable(t.table, t.defaults);

@@ -21,13 +17,8 @@ private static _methodsAdded = false;

static create(name: string = 'start') {
if(!Code._methodsAdded) {
extend(Code.prototype, methods);
Code._methodsAdded = true;
}
var newcode = new Code(name);
// newcode.addMethods();
newcode.addMethods();
return newcode;
}
methods = methods;
table = Code.table;

@@ -39,128 +30,1 @@ ClassInstruction = Instruction;

}
export interface Code {
jmp(dst: TUiOperand): Instruction;
jmpq(dst: TUiOperand): Instruction;
ljmp(dst: TUiOperand): Instruction;
ljmpq(dst: TUiOperand): Instruction;
jecxz(rel: TUiOperand): Instruction;
jrcxz(rel: TUiOperand): Instruction;
ja(rel: TUiOperand): Instruction;
jae(rel: TUiOperand): Instruction;
jb(rel: TUiOperand): Instruction;
jbe(rel: TUiOperand): Instruction;
jc(rel: TUiOperand): Instruction;
je(rel: TUiOperand): Instruction;
jg(rel: TUiOperand): Instruction;
jge(rel: TUiOperand): Instruction;
jl(rel: TUiOperand): Instruction;
jle(rel: TUiOperand): Instruction;
jna(rel: TUiOperand): Instruction;
jnae(rel: TUiOperand): Instruction;
jnb(rel: TUiOperand): Instruction;
jnbe(rel: TUiOperand): Instruction;
jnc(rel: TUiOperand): Instruction;
jne(rel: TUiOperand): Instruction;
jng(rel: TUiOperand): Instruction;
jnge(rel: TUiOperand): Instruction;
jnl(rel: TUiOperand): Instruction;
jnle(rel: TUiOperand): Instruction;
jno(rel: TUiOperand): Instruction;
jnp(rel: TUiOperand): Instruction;
jns(rel: TUiOperand): Instruction;
jnz(rel: TUiOperand): Instruction;
jo(rel: TUiOperand): Instruction;
jp(rel: TUiOperand): Instruction;
jpe(rel: TUiOperand): Instruction;
jpo(rel: TUiOperand): Instruction;
js(rel: TUiOperand): Instruction;
jz(rel: TUiOperand): Instruction;
loop(rel: TUiOperand): Instruction;
loope(rel: TUiOperand): Instruction;
loopz(rel: TUiOperand): Instruction;
loopne(rel: TUiOperand): Instruction;
loopnz(rel: TUiOperand): Instruction;
enter(imm16: number, imm8: number): Instruction;
'in'(dst: TUiOperand, src: TUiOperand): Instruction;
inb(dst: TUiOperand, src: TUiOperand): Instruction;
inw(dst: TUiOperand, src: TUiOperand): Instruction;
ind(dst: TUiOperand, src: TUiOperand): Instruction;
out(dst: TUiOperand, src: TUiOperand): Instruction;
outb(dst: TUiOperand, src: TUiOperand): Instruction;
outw(dst: TUiOperand, src: TUiOperand): Instruction;
outd(dst: TUiOperand, src: TUiOperand): Instruction;
insb(): Instruction;
insw(): Instruction;
insd(): Instruction;
outsb(): Instruction;
outsw(): Instruction;
outsd(): Instruction;
// Flag Control
stc(): Instruction;
clc(): Instruction;
cmc(): Instruction;
cld(): Instruction;
std(): Instruction;
pushf(): Instruction;
popf(): Instruction;
sti(): Instruction;
cli(): Instruction;
// Random Number
rdrand(dst: TUiOperand): Instruction;
rdseed(src: TUiOperand): Instruction;
adcx(dst: TUiOperand, src: TUiOperand): Instruction;
adox(dst: TUiOperand, src: TUiOperand): Instruction;
add(dst: TUiOperand, src: TUiOperand): Instruction;
adc(dst: TUiOperand, src: TUiOperand): Instruction;
adcb(dst: TUiOperand, src: TUiOperand): Instruction;
adcw(dst: TUiOperand, src: TUiOperand): Instruction;
adcd(dst: TUiOperand, src: TUiOperand): Instruction;
adcq(dst: TUiOperand, src: TUiOperand): Instruction;
sub(dst: TUiOperand, src: TUiOperand): Instruction;
subb(dst: TUiOperand, src: TUiOperand): Instruction;
subw(dst: TUiOperand, src: TUiOperand): Instruction;
subd(dst: TUiOperand, src: TUiOperand): Instruction;
subq(dst: TUiOperand, src: TUiOperand): Instruction;
sbb(dst: TUiOperand, src: TUiOperand): Instruction;
sbbb(dst: TUiOperand, src: TUiOperand): Instruction;
sbbw(dst: TUiOperand, src: TUiOperand): Instruction;
sbbd(dst: TUiOperand, src: TUiOperand): Instruction;
sbbq(dst: TUiOperand, src: TUiOperand): Instruction;
mul(src: TUiOperand): Instruction;
mulb(src: TUiOperand): Instruction;
mulw(src: TUiOperand): Instruction;
muld(src: TUiOperand): Instruction;
mulq(src: TUiOperand): Instruction;
div(src: TUiOperand): Instruction;
divb(src: TUiOperand): Instruction;
divw(src: TUiOperand): Instruction;
divd(src: TUiOperand): Instruction;
divq(src: TUiOperand): Instruction;
neg(dst: TUiOperand): Instruction;
cmp(dst: TUiOperand, src: TUiOperand): Instruction;
addq(dst: TUiOperand, src: TUiOperand): Instruction;
mov(dst: TUiOperand, src: TUiOperand): Instruction;
movq(dst: TUiOperand, src: TUiOperand): Instruction;
movd(dst: TUiOperand, src: TUiOperand): Instruction;
push(): Instruction;
pushq(): Instruction;
pushd(): Instruction;
pushw(): Instruction;
inc(dst: TUiOperand): Instruction;
incq(dst: TUiOperand): Instruction;
dec(dst: TUiOperand): Instruction;
decq(dst: TUiOperand): Instruction;
lea(dst: TUiOperand, src: TUiOperand): Instruction;
ret(): Instruction;
syscall(): Instruction;
sysenter(): Instruction;
sysexit(): Instruction;
int(value: number): Instruction;
}

@@ -15,9 +15,3 @@ "use strict";

_super.apply(this, arguments);
this.pfxRex = null;
}
Instruction.prototype.writePrefixes = function (arr) {
_super.prototype.writePrefixes.call(this, arr);
if (this.pfxRex)
this.pfxRex.write(arr);
};
Instruction.prototype.needs32To64OperandSizeChange = function () {

@@ -27,3 +21,5 @@ return this.def.operandSize === operand_1.SIZE.Q;

Instruction.prototype.needsRexPrefix = function () {
if (this.def.mandatoryRex)
if (this.pfxEx)
return false;
if (this.def.rex)
return true;

@@ -56,2 +52,12 @@ if (!this.ops.list.length)

W = 1;
var pos = this.def.opEncoding.indexOf('m');
if (pos > -1) {
var m = this.ops.getMemoryOperand();
if (m) {
if (m.base && (m.base.idSize() > 3))
B = 1;
if (m.index && (m.index.idSize() > 3))
X = 1;
}
}
if ((dst instanceof o.Register) && (src instanceof o.Register)) {

@@ -67,3 +73,3 @@ if (dst.isExtended())

if (r) {
if (r.isExtended())
if (r.idSize() > 3)
if (mem)

@@ -74,10 +80,4 @@ R = 1;

}
if (mem) {
if (mem.base && mem.base.isExtended())
B = 1;
if (mem.index && mem.index.isExtended())
X = 1;
}
}
this.pfxRex = new p.PrefixRex(W, R, X, B);
this.pfxEx = new p.PrefixRex(W, R, X, B);
this.length++;

@@ -84,0 +84,0 @@ this.lengthMax++;

@@ -9,9 +9,2 @@ import {SIZE} from '../../operand';

pfxRex: p.PrefixRex = null;
protected writePrefixes(arr: number[]) {
super.writePrefixes(arr);
if(this.pfxRex) this.pfxRex.write(arr); // REX prefix must precede immediate op-code byte.
}
protected needs32To64OperandSizeChange() {

@@ -23,5 +16,7 @@ // Default operand size in x64 mode is 32 bits.

protected needsRexPrefix() {
if(this.def.mandatoryRex) return true;
if(this.pfxEx) return false; // VEX or EVEX already set
if(this.def.rex) return true;
if(!this.ops.list.length) return false;
// if(!this.ops.hasRegisterOrMemory()) return false;
if(this.ops.hasExtendedRegister()) return true;

@@ -55,2 +50,11 @@

var pos = this.def.opEncoding.indexOf('m');
if(pos > -1) {
var m = this.ops.getMemoryOperand() as o.Memory; // Memory operand is only one.
if(m) {
if(m.base && (m.base.idSize() > 3)) B = 1;
if(m.index && (m.index.idSize() > 3)) X = 1;
}
}
if((dst instanceof o.Register) && (src instanceof o.Register)) {

@@ -61,18 +65,13 @@ if((dst as o.Register).isExtended()) R = 1;

var r: o.Register = this.ops.getRegisterOperand();
var mem: o.Memory = this.ops.getMemoryOperand();
var r = this.ops.getRegisterOperand();
var mem: o.Memory = this.ops.getMemoryOperand() as o.Memory;
if(r) {
if(r.isExtended())
if(r.idSize() > 3)
if(mem) R = 1;
else B = 1;
}
if(mem) {
if(mem.base && mem.base.isExtended()) B = 1;
if(mem.index && mem.index.isExtended()) X = 1;
}
}
this.pfxRex = new p.PrefixRex(W, R, X, B);
this.pfxEx = new p.PrefixRex(W, R, X, B);
this.length++;

@@ -90,3 +89,3 @@ this.lengthMax++;

protected createModrm() {
var mem: o.Memory = this.ops.getMemoryOperand();
var mem: o.Memory = this.ops.getMemoryOperand() as o.Memory;
if(mem && mem.base && (mem.base instanceof o.RegisterRip)) {

@@ -101,4 +100,4 @@ if(mem.index || mem.scale)

} else {
var r: o.Register = this.ops.getRegisterOperand();
if (r) reg = r.get3bitId();
var r = this.ops.getRegisterOperand();
if(r) reg = r.get3bitId();
}

@@ -122,3 +121,3 @@

protected createDisplacement() {
var mem = this.ops.getMemoryOperand();
var mem = this.ops.getMemoryOperand() as o.Memory;
if(mem && (typeof mem == 'object') && (mem.base instanceof o.RegisterRip)) {

@@ -125,0 +124,0 @@ // RIP-relative addressing has always 4-byte displacement.

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc