//Register with 6-bit immediate subtracted from PC private static bool ru6_m_pc(uint uInstr, XCore200Disassembler dasm) { var iReg = (uInstr >> 6) & 0xF; var imm = uInstr & 0x3F; if ((imm & 1) != 0) { return(false); // Illegal address. } var addr = dasm.addr - imm; dasm.ops.Add(new RegisterOperand(Registers.GpRegs[iReg])); dasm.ops.Add(AddressOperand.Create(addr)); return(true); }
private static bool disp32(uint uInstr, V850Disassembler dasm) { if (!dasm.rdr.TryReadUInt16(out ushort dispLo)) { return(false); } if (!dasm.rdr.TryReadUInt16(out ushort dispHi)) { return(false); } var disp = (uint)(dispHi << 16) | dispLo; dasm.ops.Add(AddressOperand.Create(dasm.addr + (int)disp)); return(true); }
private void RewritePush() { if (instrCur.Operands[0] is RegisterOperand reg && reg.Register == Registers.cs) { // Is it a 'push cs;call near XXXX' sequence that simulates a far call? if (dasm.Peek(1).Mnemonic == Mnemonic.call && dasm.Peek(1).Operands[0].Width.BitSize == 16) { dasm.MoveNext(); MachineOperand targetOperand = dasm.Current.Operands[0]; if (targetOperand is ImmediateOperand immOperand) { targetOperand = AddressOperand.Create(orw.ImmediateAsAddress(instrCur.Address, immOperand)); } else { m.Assign(StackPointer(), m.ISubS(StackPointer(), reg.Register.DataType.Size)); } RewriteCall(targetOperand, targetOperand.Width); this.len = (byte)(this.len + dasm.Current.Length); return; } if ( dasm.Peek(1).Mnemonic == Mnemonic.push && (dasm.Peek(1).Operands[0] is ImmediateOperand) && dasm.Peek(2).Mnemonic == Mnemonic.push && (dasm.Peek(2).Operands[0] is ImmediateOperand) && dasm.Peek(3).Mnemonic == Mnemonic.jmp && (dasm.Peek(3).Operands[0] is AddressOperand)) { // That's actually a far call, but the callee thinks its a near call. RewriteCall(dasm.Peek(3).Operands[0], instrCur.Operands[0].Width); dasm.MoveNext(); dasm.MoveNext(); dasm.MoveNext(); return; } } var value = SrcOp(0, instrCur.dataWidth); Debug.Assert( value.DataType.BitSize == 16 || value.DataType.BitSize == 32 || value.DataType.BitSize == 64, $"Unexpected size {dasm.Current.dataWidth}"); RewritePush(PrimitiveType.CreateWord(value.DataType.BitSize), value); }
public override AArch32Instruction Decode(uint wInstr, T32Disassembler dasm) { var s = SBitfield(wInstr, 10 + 16, 1); var i1 = 1 & ~(SBitfield(wInstr, 13, 1) ^ s); var i2 = 1 & ~(SBitfield(wInstr, 11, 1) ^ s); var off = (int)Bits.SignExtend((uint)s, 1); off = (off << 2) | (i1 << 1) | i2; off = (off << 10) | SBitfield(wInstr, 16, 10); off = (off << 11) | SBitfield(wInstr, 0, 11); off <<= 1; return(new T32Instruction { Mnemonic = Mnemonic.bl, Operands = new MachineOperand[] { AddressOperand.Create(dasm.addr + (off + 4)) } }); }
private static Mutator <C166Disassembler> QQrrqFn() { var qqField = new Bitfield(8, 8); var qField = new Bitfield(28, 4); var rrField = new Bitfield(16, 8); return((u, d) => { if (!d.rdr.TryReadLeUInt16(out ushort hiword)) { return false; } u |= ((uint)hiword) << 16; var qq = Decode8bitReg(PrimitiveType.Word16, Registers.GpRegs, (int)qqField.Read(u)); var q = (int)qField.Read(u); d.ops.Add(new BitOfOperand(q, qq)); var offset = rrField.ReadSigned(u) << 1; var addr = d.rdr.Address + offset; d.ops.Add(AddressOperand.Create(addr)); return true; }); }
public AvrInstruction Decode(ushort wInstr, Opcode opcode, InstrClass iclass, string fmt) { var ops = new List <MachineOperand>(); int offset; ushort w2; for (int i = 0; i < fmt.Length; ++i) { MachineOperand op; switch (fmt[i++]) { case ',': continue; case '+': op = IncDec(true, fmt[i++]); break; case '-': op = IncDec(false, fmt[i++]); break; case 'A': // I/O location op = ImmediateOperand.Byte((byte)(((wInstr >> 5) & 0x30) | (wInstr & 0xF))); break; case 'B': // 8-bit immediate at bits 8..11 and 0..3 op = ImmediateOperand.Byte((byte)(((wInstr >> 4) & 0xF0) | (wInstr & 0x0F))); break; case 'g': // 4-bit field in sgis op = ImmediateOperand.Byte((byte)((wInstr >> 3) & 0x0F)); break; case 'h': // 3-bit field in sgis, indicating bit nr. op = ImmediateOperand.Byte((byte)(wInstr & 7)); break; case 'I': // 4-bit immediate at bit 0 op = ImmediateOperand.Byte((byte)(wInstr & 0x0F)); break; case 'i': // 4-bit immediate at bit 4 op = ImmediateOperand.Byte((byte)((wInstr >> 4) & 0x0F)); break; case 'J': // Relative jump offset = (short)((wInstr & 0xFFF) << 4); offset = offset >> 3; op = AddressOperand.Create(this.addr + 2 + offset); break; case 'D': // Destination register op = Register((wInstr >> 4) & 0x1F); break; case 'd': // Destination register (r16-r31) op = Register(0x10 | (wInstr >> 4) & 0x0F); break; case 'R': // source register (5 bits) op = Register((wInstr >> 5) & 0x10 | (wInstr) & 0x0F); break; case 'r': if (i < fmt.Length && fmt[i] == '4') { ++i; // source register (r16-r31) op = Register(0x10 | wInstr & 0x0F); } else { // source register (5 bits) op = Register((wInstr >> 4) & 0x10 | (wInstr >> 4) & 0x0F); } break; case 'K': op = ImmediateOperand.Byte((byte)(((wInstr >> 4) & 0xF0) | (wInstr & 0xF))); break; case 'P': // register pair source op = Register((wInstr << 1) & ~1); break; case 'p': // register pair destination op = Register((wInstr >> 3) & ~1); break; case 'Q': // absolute address used by jump and call. if (!rdr.TryReadLeUInt16(out w2)) { return(null); } op = AddressOperand.Ptr32( (uint)(((wInstr >> 4) & 0x1F) << 18) | (uint)((wInstr & 1) << 17) | (uint)(w2 << 1)); break; case 'q': // register pair used by adiw op = Register(24 + ((wInstr >> 3) & 6)); break; case 's': // immediate used by adiw/sbiw op = ImmediateOperand.Byte((byte)(((wInstr >> 2) & 0x30) | (wInstr & 0xF))); break; case 'w': // Trailing 16-bit absolute address if (!rdr.TryReadLeUInt16(out w2)) { return(null); } op = AddressOperand.Ptr16(w2); break; case 'o': // Branch offset offset = (short)wInstr; offset = (short)(offset << 6); offset = (short)(offset >> 8); offset = (short)(offset & ~1); op = AddressOperand.Create(this.addr + offset + 2); break; case 'X': op = MemD(arch.x, 0); break; case 'Y': op = MemD(arch.y, 0); break; case 'y': op = MemD(arch.y, Displacement(wInstr)); break; case 'Z': op = MemD(arch.z, 0); break; case 'z': op = MemD(arch.z, Displacement(wInstr)); break; default: throw new NotImplementedException(string.Format("Unimplemented AVR8 format symbol '{0}'.'", fmt[i - 1])); } ops.Add(op); } return(new AvrInstruction { opcode = opcode, iclass = iclass, operands = ops.ToArray(), }); }
private static bool j(uint uInstr, SuperHDisassembler dasm) { dasm.state.ops.Add(AddressOperand.Create(dasm.rdr.Address + (2 + 2 * (sbyte)uInstr))); return(true); }
private Tms7000Instruction Decode(Opcode opcode, string format) { int iOp = 0; var instr = new Tms7000Instruction { Opcode = opcode, }; for (int i = 0; i < format.Length; ++i) { MachineOperand op; byte b; ushort w; switch (format[i]) { case ',': continue; case 'A': op = new RegisterOperand(arch.a); break; case 'B': op = new RegisterOperand(arch.b); break; case 'R': if (!rdr.TryReadByte(out b)) { return(Invalid()); } op = new RegisterOperand(arch.GpRegs[b]); break; case 'P': if (!rdr.TryReadByte(out b)) { return(Invalid()); } op = new RegisterOperand(arch.Ports[b]); break; case 'S': ; op = new RegisterOperand(arch.st); break; case 'i': if (!rdr.TryReadByte(out b)) { return(Invalid()); } op = ImmediateOperand.Byte(b); break; case 'I': if (!rdr.TryReadBeUInt16(out w)) { return(Invalid()); } op = ImmediateOperand.Word16(w); break; case 'j': // short PC-relative jump if (!rdr.TryReadByte(out b)) { return(Invalid()); } op = AddressOperand.Create(rdr.Address + (sbyte)b); break; case 'D': // direct, absolute address if (!rdr.TryReadBeUInt16(out w)) { return(Invalid()); } if (i < format.Length - 1 && format[i + 1] == 'B') { ++i; op = MemoryOperand.Indexed(Address.Ptr16(w), arch.b); } else { op = MemoryOperand.Direct(Address.Ptr16(w)); } break; case '*': // indirect if (!rdr.TryReadByte(out b)) { return(Invalid()); } op = MemoryOperand.Indirect(arch.GpRegs[b]); break; default: throw new NotImplementedException($"Addressing mode {format[i]}"); } switch (iOp++) { case 0: instr.op1 = op; break; case 1: instr.op2 = op; break; case 2: instr.op3 = op; break; } } return(instr); }
private SuperHInstruction Decode(ushort uInstr, Opcode opcode, string format) { var ops = new MachineOperand[2]; int iop = 0; RegisterStorage reg; PrimitiveType width; for (int i = 0; i < format.Length; ++i) { switch (format[i]) { case ',': continue; case '-': // predecrement reg = Register(format[++i], uInstr); ops[iop] = MemoryOperand.IndirectPreDecr(GetWidth(format[++i]), reg); break; case '+': // postdecrement reg = Register(format[++i], uInstr); ops[iop] = MemoryOperand.IndirectPostIncr(GetWidth(format[++i]), reg); break; case 'd': ops[iop] = DfpRegister(format[++i], uInstr); break; case 'f': ops[iop] = FpRegister(format[++i], uInstr); break; case 'r': ops[iop] = new RegisterOperand(Register(format[++i], uInstr)); break; case 'v': ops[iop] = VfpRegister(format[++i], uInstr); break; case 'I': ops[iop] = ImmediateOperand.Byte((byte)uInstr); break; case 'F': if (format[++i] == 'U') { ops[iop] = new RegisterOperand(Registers.fpul); break; } goto default; case 'G': ops[iop] = MemoryOperand.GbrIndexedIndirect(GetWidth(format[++i])); break; case '@': reg = Register(format[++i], uInstr); ops[iop] = MemoryOperand.Indirect(GetWidth(format[++i]), reg); break; case 'D': // indirect with displacement reg = Register(format[++i], uInstr); width = GetWidth(format[++i]); ops[iop] = MemoryOperand.IndirectDisplacement(width, reg, (uInstr & 0xF) * width.Size); break; case 'X': // indirect indexed reg = Register(format[++i], uInstr); ops[iop] = MemoryOperand.IndexedIndirect(GetWidth(format[++i]), reg); break; case 'P': // PC-relative with displacement width = GetWidth(format[++i]); ops[iop] = MemoryOperand.PcRelativeDisplacement(width, width.Size * (byte)uInstr); break; case 'R': ++i; if (format[i] == 'P') ops[iop] = new RegisterOperand(Registers.pr); else ops[iop] = new RegisterOperand(Registers.gpregs[HexDigit(format[i]).Value]); break; case 'j': ops[iop] = AddressOperand.Create(rdr.Address + (2 + 2 * (sbyte)uInstr)); break; case 'J': int offset = ((int)uInstr << 20) >> 19; ops[iop] = AddressOperand.Create(rdr.Address + (2 + offset)); break; case 'm': // Macl. if (i < format.Length-1) { ++i; if (format[i] == 'l') { ops[iop] = new RegisterOperand(Registers.macl); } else if (format[i] == 'h') { ops[iop] = new RegisterOperand(Registers.mach); } else { throw new NotImplementedException(string.Format("m{0}", format[i])); } } else { throw new NotImplementedException(string.Format("m{0}", format[i])); } break; default: throw new NotImplementedException(string.Format("SuperHDisassembler.Decode({0})", format[i])); } ++iop; } return new SuperHInstruction { Opcode = opcode, op1 = ops[0], op2 = ops[1], }; }
private i8051Instruction Decode(Mnemonic opcode, byte uInstr, string fmt) { byte b; var ops = new List <MachineOperand>(); foreach (var ch in fmt) { switch (ch) { case ',': continue; case 'j': // An 11-bit address destination. This argument is used by ACALL and AJMP instructions. The target of the CALL or JMP must lie within the same 2K page as the first byte of the following instruction. if (!rdr.TryReadByte(out b)) { return(null); } ops.Add(AddressOperand.Ptr16( (ushort)( (rdr.Address.ToLinear() & ~0x7Ful) | (uInstr & 0xE0u) << 3 | b))); break; case 'J': // A 16-bit address destination. This argument is used by LCALL and LJMP instructions. if (!rdr.TryReadBeUInt16(out var uAddr)) // Yes, big endian! { return(null); } ops.Add(AddressOperand.Ptr16(uAddr)); break; case 'o': // A signed (two's complement) 8-bit offset (-128 to 127) relative to the first byte of the following instruction. if (!rdr.TryReadByte(out b)) { return(null); } ops.Add(AddressOperand.Create(rdr.Address + (sbyte)b)); break; case 'A': // The accumulator. ops.Add(new RegisterOperand(Registers.A)); break; case 'd': // An internal data RAM location (0-127) or SFR (128-255). if (!rdr.TryReadByte(out b)) { return(null); } ops.Add(MemoryOperand.Direct(Address.Ptr16(b))); break; case 'r': // Register r0-r7 ops.Add(Reg(uInstr & 7)); break; case 'b': // A direct addressed bit in internal data RAM or SFR memory. if (!rdr.TryReadByte(out b)) { return(null); } ops.Add(BitReg(b, false)); break; case 'B': // A direct addressed bit in internal data RAM or SFR memory. if (!rdr.TryReadByte(out b)) { return(null); } ops.Add(BitReg(b, true)); break; case 'C': // C flag of PSW ops.Add(new FlagGroupOperand(arch.GetFlagGroup(Registers.PSW, (uint)FlagM.C))); break; case 'D': // @DPTR ops.Add(MemoryOperand.Indirect(Registers.DPTR)); break; case 'p': // DPTR register pair ops.Add(new SequenceOperand(Registers.DPTR)); break; case 'i': // A constant included in the instruction encoding. if (!rdr.TryReadByte(out b)) { return(null); } ops.Add(ImmediateOperand.Byte(b)); break; case 'I': // A constant included in the instruction encoding. if (!rdr.TryReadUInt16(out var w)) { return(null); } ops.Add(ImmediateOperand.Word16(w)); break; case '@': // @Ri An internal data RAM location (0-255) addressed indirectly through R0 or R1. ops.Add(MemoryOperand.Indirect(Registers.GetRegister(uInstr & 1))); break; case '+': // @A + DPTR: ops.Add(MemoryOperand.Indexed(Registers.DPTR, Registers.A)); break; case 'P': // @A + PC: ops.Add(MemoryOperand.Indexed(Registers.PC, Registers.A)); break; case '*': // AB register pair ops.Add(new SequenceOperand(Registers.AB)); break; default: EmitUnitTest(opcode, uInstr); break; } } return(new i8051Instruction { Mnemonic = opcode, Address = this.addr, Length = (int)(rdr.Address - this.addr), Operands = ops.ToArray() }); }
private Tlcs90Instruction DecodeOperands(byte b, Opcode opcode, string format) { int op = 0; var ops = new MachineOperand[2]; Constant c; PrimitiveType size; for (int i = 0; i < format.Length; ++i) { switch (format[i]) { case ',': continue; case 'a': this.dataWidth = PrimitiveType.Byte; ops[op] = new RegisterOperand(Registers.a); break; case '@': this.dataWidth = PrimitiveType.Word16; ops[op] = new RegisterOperand(Registers.af_); break; case 'A': this.dataWidth = PrimitiveType.Word16; ops[op] = new RegisterOperand(Registers.af); break; case 'B': this.dataWidth = PrimitiveType.Word16; ops[op] = new RegisterOperand(Registers.bc); break; case 'c': ops[op] = new ConditionOperand((CondCode)(b & 0xF)); break; case 'D': this.dataWidth = PrimitiveType.Word16; ops[op] = new RegisterOperand(Registers.de); break; case 'I': // Immediate value this.dataWidth = GetSize(format[++i]); if (!rdr.TryReadLe(this.dataWidth, out c)) { return(null); } ops[op] = new ImmediateOperand(c); break; case 'i': // immediate value from opcode bits ops[op] = ImmediateOperand.Byte((byte)(b & 0x7)); break; case 'g': Debug.Assert(byteReg != null); ops[op] = this.byteReg; break; case 'G': Debug.Assert(wordReg != null); ops[op] = this.wordReg; break; case 'H': ops[op] = new RegisterOperand(Registers.hl); break; case 'J': // Absolute jump. size = GetSize(format[++i]); if (!rdr.TryReadLe(size, out c)) { return(null); } ops[op] = AddressOperand.Ptr16(c.ToUInt16()); break; case 'j': // relative jump size = GetSize(format[++i]); Address dest; if (size.Size == 1) { if (!rdr.TryReadByte(out b)) { return(null); } dest = rdr.Address + (sbyte)b; } else { if (!rdr.TryReadLeInt16(out short off)) { return(null); } dest = rdr.Address + off; } ops[op] = AddressOperand.Create(dest); break; case 'M': this.dataWidth = GetSize(format[++i]); ushort absAddr; if (!rdr.TryReadLeUInt16(out absAddr)) { return(null); } ops[op] = MemoryOperand.Absolute(this.dataWidth, absAddr); break; case 'm': size = GetSize(format[++i]); byte pageAddr; if (!rdr.TryReadByte(out pageAddr)) { return(null); } ops[op] = MemoryOperand.Absolute(size, (ushort)(0xFF00 | pageAddr)); break; case 'S': this.dataWidth = PrimitiveType.Word16; ops[op] = new RegisterOperand(Registers.sp); break; case 'X': this.dataWidth = PrimitiveType.Word16; ops[op] = new RegisterOperand(Registers.ix); break; case 'Y': this.dataWidth = PrimitiveType.Word16; ops[op] = new RegisterOperand(Registers.iy); break; case 'r': // Register encoded in low 3 bits of b. ops[op] = new RegisterOperand(Registers.byteRegs[b & 7]); dataWidth = PrimitiveType.Byte; break; case 'x': this.backPatchOp = op; break; default: throw new NotImplementedException(string.Format("Encoding '{0}' not implemented yet.", format[i])); } ++op; } return(new Tlcs90Instruction { Opcode = opcode, op1 = op > 0 ? ops[0] : null, op2 = op > 1 ? ops[1] : null, }); }
private Tlcs900Instruction Decode(byte b, Opcode opcode, string fmt) { var instr = new Tlcs900Instruction { Opcode = opcode, Address = this.addr, }; var ops = new List <MachineOperand>(); MachineOperand op = null; for (int i = 0; i < fmt.Length; ++i) { switch (fmt[i++]) { case ',': continue; case 'C': // condition code var cc = (CondCode)(b & 0xF); if (cc == CondCode.T) { continue; } op = new ConditionOperand(cc); break; case 'A': op = new RegisterOperand(Tlcs900Registers.a); break; case '3': // Immediate encoded in low 3 bits var c = Constant.Create(Size(fmt[1]), imm3Const[b & 7]); SetSize(fmt[1]); op = new ImmediateOperand(c); break; case 'I': // immediate op = Immediate(fmt[i++]); break; case 'j': // Relative jump switch (fmt[i++]) { case 'b': byte o8; if (!rdr.TryReadByte(out o8)) { op = null; } else { op = AddressOperand.Create(rdr.Address + (sbyte)o8); } break; case 'w': short o16; if (!rdr.TryReadLeInt16(out o16)) { op = null; } else { op = AddressOperand.Create(rdr.Address + o16); } break; } break; case 'J': // Absolute jump switch (fmt[i++]) { case 'w': op = AbsoluteDestination(2); break; case 'l': op = AbsoluteDestination(3); break; default: op = null; break; } break; case 'R': // 16 bit register encoded in lsb op = new RegisterOperand(Reg(fmt[i++], b & 0x7)); break; case 'S': // status/flag register op = StatusRegister(fmt[i++]); break; } if (op == null) { return(Decode(b, Opcode.invalid, "")); } ops.Add(op); } if (ops.Count > 0) { instr.op1 = ops[0]; if (ops.Count > 1) { instr.op2 = ops[1]; if (ops.Count > 2) { instr.op3 = ops[2]; } } } return(instr); }
private MachineOperand DecodeOperand(byte b, string fmt) { MachineOperand op; byte r; Constant c; byte o8; int incCode; switch (fmt[0]) { case '+': // Predecrement if (!rdr.TryReadByte(out r)) { return(null); } incCode = r & 3; if (incCode >= incDecSize.Length) { return(null); } op = MemoryOperand.PostIncrement(Size(fmt[1]), incDecSize[r & 3], Reg('x', (r >> 2) & 0x3F)); SetSize(fmt[1]); return(op); case '-': if (!rdr.TryReadByte(out r)) { return(null); } incCode = r & 3; if (incCode >= incDecSize.Length) { return(null); } op = MemoryOperand.PreDecrement(Size(fmt[1]), incDecSize[r & 3], Reg('x', (r >> 2) & 0x3F)); SetSize(fmt[1]); return(op); case '3': // Immediate encoded in low 3 bits c = Constant.Create(Size(fmt[1]), b & 7); SetSize(fmt[1]); return(new ImmediateOperand(c)); case '#': // Immediate encoded in low 3 bits, with 8 encoded as 0 c = Constant.Create(Size(fmt[1]), imm3Const[b & 7]); SetSize(fmt[1]); return(new ImmediateOperand(c)); case 'A': // A register op = new RegisterOperand(Tlcs900Registers.a); return(op); case 'C': // condition code op = new ConditionOperand((CondCode)(b & 0xF)); return(op); case 'I': // immediate op = Immediate(fmt[1]); return(op); case 'j': // Relative jump switch (fmt[1]) { case 'b': if (!rdr.TryReadByte(out o8)) { return(null); } else { return(AddressOperand.Create(rdr.Address + (sbyte)o8)); } case 'w': short o16; if (!rdr.TryReadLeInt16(out o16)) { return(null); } else { return(AddressOperand.Create(rdr.Address + o16)); } } return(null); case 'r': // Register case 'R': //$TODO: 'r' may encode other registers. manual is dense op = new RegisterOperand(Reg(fmt[1], b & 0x7)); SetSize(fmt[1]); return(op); case 'M': // Register indirect op = MemoryOperand.Indirect(Size(fmt[1]), Reg('x', b & 7)); SetSize(fmt[1]); return(op); case 'N': // indexed (8-bit offset) if (!rdr.TryReadByte(out o8)) { return(null); } op = MemoryOperand.Indexed8(Size(fmt[1]), Reg('x', b & 7), (sbyte)o8); SetSize(fmt[1]); return(op); case 'm': // various mem formats byte m; if (!rdr.TryReadByte(out m)) { return(null); } switch (m & 3) { case 0: // Register indirect op = MemoryOperand.Indirect(Size(fmt[1]), Reg('x', (m >> 2) & 0x3F)); break; case 1: // indexed (16-bit offset) short o16; if (!rdr.TryReadLeInt16(out o16)) { return(null); } op = MemoryOperand.Indexed16(Size(fmt[1]), Reg('x', (m >> 2) & 0x3F), o16); SetSize(fmt[1]); return(op); case 3: if (m != 3 && m != 7) { return(null); } byte rBase; if (!rdr.TryReadByte(out rBase)) { return(null); } byte rIdx; if (!rdr.TryReadByte(out rIdx)) { return(null); } var regBase = Reg('x', rBase); var regIdx = Reg(m == 3 ? 'b' : 'w', rIdx); op = MemoryOperand.RegisterIndexed(Size(fmt[1]), regBase, regIdx); SetSize(fmt[1]); return(op); default: throw new FormatException(string.Format( "Unknown format {0} decoding bytes {1:X2}{2:X2}.", fmt[0], (int)b, (int)m)); } SetSize(fmt[1]); return(op); case 'O': return(Absolute(1, fmt[1])); case 'P': return(Absolute(2, fmt[1])); case 'Q': return(Absolute(3, fmt[1])); default: throw new FormatException( string.Format( "Unknown format {0} decoding byte {1:X2}.", fmt[0], (int)b)); } }
public static bool RILc(ulong uInstr, zSeriesDisassembler dasm) { var offset = 2 * (int)Bits.SignExtend(uInstr, 32); dasm.ops.Add(AddressOperand.Create(dasm.addr + offset)); return true; }
public static bool RIc(ulong uInstr, zSeriesDisassembler dasm) { var addr = dasm.addr + 2*(int)Bits.SignExtend(uInstr, 16); dasm.ops.Add(AddressOperand.Create(addr)); return true; }
private Msp430Instruction Decode(ushort uInstr, Opcode opcode, string fmt) { PrimitiveType dataWidth = null; int i = 0; if (i < fmt.Length) { switch (fmt[i++]) { case 'w': // use width bit dataWidth = (uInstr & 0x40) != 0 ? PrimitiveType.Byte : PrimitiveType.Word16; break; case 'a': // a/w bit 4. dataWidth = (uInstr & 0x04) != 0 ? PrimitiveType.Word16 : Msp430Architecture.Word20; break; case 'x': dataWidth = (uExtension != 0) && (uExtension & 0x40) == 0 ? Msp430Architecture.Word20 : PrimitiveType.Word16; break; case 'p': dataWidth = Msp430Architecture.Word20; break; case 'W': // b/w/a combined from the op and the extension var w = ((this.uExtension & 0x40) >> 5) | (uInstr & 0x040) >> 6; switch (w) { case 0: return(Invalid()); case 1: dataWidth = Msp430Architecture.Word20; break; case 2: dataWidth = PrimitiveType.Word16; break; case 3: dataWidth = PrimitiveType.Byte; break; } break; default: --i; break; } } MachineOperand op1 = null; MachineOperand op2 = null; int aS; int iReg; if (i < fmt.Length) { switch (fmt[i++]) { case 'J': int offset = (short)(uInstr << 6) >> 5; op1 = AddressOperand.Create(rdr.Address + offset); break; case 'r': op1 = SourceOperand(0, uInstr & 0x0F, dataWidth); break; case 'S': aS = (uInstr >> 4) & 0x03; iReg = (uInstr >> 8) & 0x0F; op1 = SourceOperand(aS, iReg, dataWidth); if (op1 == null) { return(null); } break; case 's': aS = (uInstr >> 4) & 0x03; iReg = uInstr & 0x0F; op1 = SourceOperand(aS, iReg, dataWidth); if (op1 == null) { return(null); } break; case 'n': int n = 1 + ((uInstr >> 4) & 0x0F); op1 = ImmediateOperand.Byte((byte)n); break; case 'N': n = 1 + ((uInstr >> 10) & 3); op1 = ImmediateOperand.Byte((byte)n); break; case '@': iReg = (uInstr >> 8) & 0x0F; var reg = Registers.GpRegisters[iReg]; op1 = new MemoryOperand(Msp430Architecture.Word20) { Base = reg, }; break; case '+': iReg = (uInstr >> 8) & 0x0F; reg = Registers.GpRegisters[iReg]; op1 = PostInc(reg, Msp430Architecture.Word20); break; case '&': if (!rdr.TryReadLeUInt16(out var lo16)) { return(Invalid()); } var hi4 = (uint)(uInstr >> 8) & 0x0F; //$TODO: 20-bit address? op1 = AddressOperand.Ptr32((hi4 << 16) | lo16); break; case 'x': if (!rdr.TryReadLeInt16(out var idxOffset)) { return(Invalid()); } iReg = (uInstr >> 8) & 0x0F; reg = Registers.GpRegisters[iReg]; op1 = new MemoryOperand(Msp430Architecture.Word20) { Base = reg, Offset = idxOffset }; break; default: --i; break; } } if (i < fmt.Length) { switch (fmt[i]) { case 'D': var aD = (uInstr >> 7) & 0x01; iReg = uInstr & 0x0F; if (iReg == 3) { return(Invalid()); } var reg = Registers.GpRegisters[iReg]; if (aD == 0) { if (iReg == 3) { return(Invalid()); } op2 = new RegisterOperand(reg); } else { op2 = Indexed(reg, dataWidth); if (op2 == null) { return(null); } } break; case 'r': op2 = SourceOperand(0, uInstr & 0x0F, dataWidth); break; } } int rep = (uExtension & 0x0F); var instr = new Msp430Instruction { opcode = opcode, dataWidth = dataWidth, op1 = op1, op2 = op2, repeatImm = (uExtension & 0x80) != 0 ? 0 : rep + 1, repeatReg = (uExtension & 0x80) != 0 ? Registers.GpRegisters[rep] : null, }; instr = SpecialCase(instr); return(instr); }