public Operand(string token) { //TODO: properly handle optional elements {K}{Z} {AES}{ER} string token2 = token. Replace("{K0}", ""). Replace("{K1}", ""). Replace("{K2}", ""). Replace("{K3}", ""). Replace("{K4}", ""). Replace("{K5}", ""). Replace("{K6}", ""). Replace("{K7}", ""). Replace("{Z}", ""). Replace("{ER}", ""). Replace("{SAE}", ""). Replace("{1TO4}", ""). Replace("{1TO8}", ""). Replace("{1TO16}", ""); this._str = token; Tuple <bool, Rn, int> t0 = RegisterTools.toRn(token2); if (t0.Item1) { this._type = Ot.reg; this._rn = t0.Item2; this._nBits = t0.Item3; } else { Tuple <bool, ulong, int> t1 = AsmSourceTools.toConstant(token2); if (t1.Item1) { this._type = Ot.imm; this._imm = t1.Item2; this._nBits = t1.Item3; } else { Tuple <bool, Rn, Rn, int, long, int> t2 = AsmSourceTools.parseMemOperand(token2); if (t2.Item1) { this._type = Ot.mem; this._mem = new Tuple <Rn, Rn, int, long>(t2.Item2, t2.Item3, t2.Item4, t2.Item5); this._nBits = t2.Item6; } else { this._type = Ot.UNKNOWN; this._nBits = -1; } } } }
/// <summary> /// return Offset = Base + (Index * Scale) + Displacement /// </summary> public static Tuple <bool, Rn, Rn, int, long, int> parseMemOperand(string token) { int length = token.Length; if (length < 3) { return(new Tuple <bool, Rn, Rn, int, long, int>(false, Rn.NOREG, Rn.NOREG, 0, 0, 0)); } // 1] select everything between [] int beginPos = length; for (int i = 0; i < length; ++i) { if (token[i] == '[') { beginPos = i + 1; } } int nBits = getNbitsMemOperand(token); int endPos = length; for (int i = beginPos; i < length; ++i) { if (token[i] == ']') { endPos = i; } } token = token.Substring(beginPos, endPos - beginPos).Trim(); length = token.Length; if (length == 0) { return(new Tuple <bool, Rn, Rn, int, long, int>(false, Rn.NOREG, Rn.NOREG, 0, 0, 0)); } // 2] check if the displacement is negative bool negativeDisplacement = token.Contains('-'); if (negativeDisplacement) { token = token.Replace('-', '+'); } // 3] remove superfluous initial + if (token[0] == '+') { token = token.Substring(1, length - 1).Trim(); } // 4] split based on + string[] x = token.Split('+'); Rn baseRn = Rn.NOREG; Rn indexRn = Rn.NOREG; int scale = 0; long displacement = 0; bool foundDisplacement = false; for (int i = 0; i < x.Length; ++i) { string y = x[i].Trim(); var t2 = AsmSourceTools.toConstant(y); if (t2.Item1) { if (foundDisplacement) { // found an second displacement, error return(new Tuple <bool, Rn, Rn, int, long, int>(false, Rn.NOREG, Rn.NOREG, 0, 0, 0)); } else { foundDisplacement = true; displacement = (negativeDisplacement) ? -(long)t2.Item2 : (long)t2.Item2; } } else { Rn t1 = RegisterTools.parseRn(y); if (t1 != Rn.NOREG) { if (baseRn == Rn.NOREG) { baseRn = t1; } else { indexRn = t1; scale = 1; } } if (y.Contains('*')) { string[] z = y.Split('*'); string z0 = z[0].Trim(); string z1 = z[1].Trim(); Rn z0r = RegisterTools.parseRn(z0); if (z0r != Rn.NOREG) { indexRn = z0r; scale = parseScale(z1); } else { Rn z1r = RegisterTools.parseRn(z1); if (z1r != Rn.NOREG) { indexRn = z1r; scale = parseScale(z0); } } } } } if (scale == -1) { return(new Tuple <bool, Rn, Rn, int, long, int>(false, Rn.NOREG, Rn.NOREG, 0, 0, 0)); } if ((baseRn != Rn.NOREG) && (indexRn != Rn.NOREG)) { if (RegisterTools.nBits(baseRn) != RegisterTools.nBits(indexRn)) { return(new Tuple <bool, Rn, Rn, int, long, int>(false, Rn.NOREG, Rn.NOREG, 0, 0, 0)); } } return(new Tuple <bool, Rn, Rn, int, long, int>(true, baseRn, indexRn, scale, displacement, nBits)); }