public override Tlcs90Instruction Decode(uint bPrev, Tlcs90Disassembler dasm) { Tlcs90Instruction instr; Constant offset = null; RegisterStorage baseReg = null; RegisterStorage idxReg = null; switch (format[0]) { case 'E': switch (format[1]) { case 'S': baseReg = Registers.sp; break; case 'X': baseReg = Registers.ix; break; case 'Y': baseReg = Registers.iy; break; case 'H': baseReg = Registers.hl; idxReg = Registers.a; break; default: throw new NotImplementedException(string.Format("Tlcs-90: src {0}", format)); } ; if (idxReg == null) { if (!dasm.rdr.TryReadByte(out byte bOff)) { return(null); } offset = Constant.SByte((sbyte)bOff); } break; case 'B': baseReg = Registers.bc; break; case 'D': baseReg = Registers.de; break; case 'H': baseReg = Registers.hl; break; case 'S': baseReg = Registers.sp; break; case 'X': baseReg = Registers.ix; break; case 'Y': baseReg = Registers.iy; break; case 'M': ushort us; if (!dasm.rdr.TryReadLeUInt16(out us)) { return(null); } offset = Constant.UInt16(us); break; case 'm': byte pageAddr; if (!dasm.rdr.TryReadByte(out pageAddr)) { return(null); } offset = Constant.UInt16((ushort)(0xFF00 | pageAddr)); break; default: throw new NotImplementedException(string.Format("Tlcs-90: src {0}", format)); } if (!dasm.rdr.TryReadByte(out byte b)) { return(null); } instr = srcEncodings[b].Decode(b, dasm); if (instr == null) { return(null); } var operand = new MemoryOperand(dasm.dataWidth) { Base = baseReg, Index = idxReg, Offset = offset }; if (dasm.backPatchOp == 0) { if (instr.Operands.Length == 1) { instr.Operands = new MachineOperand[] { operand, instr.Operands[0] }; } else { instr.Operands = new MachineOperand[] { operand }; } if (instr.Operands.Length >= 2) { operand.Width = instr.Operands[1].Width; } } else if (dasm.backPatchOp == 1) { if (operand != null) { instr.Operands = new MachineOperand[] { instr.Operands[0], operand }; } operand.Width = instr.Operands[0].Width; } else { return(null); } return(instr); }
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, }); }
public override Tlcs90Instruction Decode(uint bPrev, Tlcs90Disassembler dasm) { RegisterStorage baseReg = null; RegisterStorage idxReg = null; ushort? absAddr = null; Constant offset = null; switch (format[0]) { case 'M': ushort a; if (!dasm.rdr.TryReadLeUInt16(out a)) { return(null); } absAddr = a; break; case 'm': byte bb; if (!dasm.rdr.TryReadByte(out bb)) { return(null); } absAddr = (ushort)(0xFF00 | bb); break; case 'B': baseReg = Registers.bc; break; case 'D': baseReg = Registers.de; break; case 'H': baseReg = Registers.hl; break; case 'X': baseReg = Registers.ix; break; case 'Y': baseReg = Registers.iy; break; case 'S': baseReg = Registers.sp; break; case 'E': switch (format[1]) { case 'S': baseReg = Registers.sp; break; case 'X': baseReg = Registers.ix; break; case 'Y': baseReg = Registers.ix; break; case 'H': baseReg = Registers.hl; idxReg = Registers.a; break; default: throw new NotImplementedException(string.Format("Tlcs-90: dst {0}", format)); } if (idxReg == null) { if (!dasm.rdr.TryReadByte(out byte bOff)) { return(null); } offset = Constant.SByte((sbyte)bOff); } break; default: throw new NotImplementedException(string.Format("Tlcs-90: dst {0}", format)); } if (!dasm.rdr.TryReadByte(out byte b)) { return(null); } var instr = dstEncodings[b].Decode(b, dasm); if (instr == null) { return(null); } var operand = new MemoryOperand(dasm.dataWidth) { Base = baseReg, Offset = absAddr.HasValue ? Constant.UInt16(absAddr.Value) : offset, }; if (dasm.backPatchOp == 0) { if (instr.Operands.Length == 0) { instr.Operands = new MachineOperand[] { operand }; } else { instr.Operands = new MachineOperand[] { operand, instr.Operands[0] }; } if (instr.Operands.Length == 2) { instr.Operands[0].Width = instr.Operands[1].Width; } } else if (dasm.backPatchOp == 1) { if ((instr.Mnemonic == Mnemonic.jp || instr.Mnemonic == Mnemonic.call) && operand.Base == null && operand.Index == null && operand.Offset != null) { // JP cc,(XXXX) should be JP cc,XXXX var op = AddressOperand.Ptr16(operand.Offset.ToUInt16()); op.Width = PrimitiveType.Ptr16; instr.Operands = new MachineOperand[] { instr.Operands[0], op }; } else { instr.Operands = new MachineOperand[] { instr.Operands[0], operand }; instr.Operands[1].Width = instr.Operands[0].Width; } } else { return(null); } return(instr); }
public override Tlcs90Instruction Decode(byte b, Tlcs90Disassembler dasm) { RegisterStorage baseReg = null; RegisterStorage idxReg = null; ushort? absAddr = null; Constant offset = null; switch (format[0]) { case 'M': ushort a; if (!dasm.rdr.TryReadLeUInt16(out a)) { return(null); } absAddr = a; break; case 'm': byte bb; if (!dasm.rdr.TryReadByte(out bb)) { return(null); } absAddr = (ushort)(0xFF00 | bb); break; case 'B': baseReg = Registers.bc; break; case 'D': baseReg = Registers.de; break; case 'H': baseReg = Registers.hl; break; case 'X': baseReg = Registers.ix; break; case 'Y': baseReg = Registers.iy; break; case 'S': baseReg = Registers.sp; break; case 'E': switch (format[1]) { case 'S': baseReg = Registers.sp; break; case 'X': baseReg = Registers.ix; break; case 'Y': baseReg = Registers.ix; break; case 'H': baseReg = Registers.hl; idxReg = Registers.a; break; default: throw new NotImplementedException(string.Format("Tlcs-90: dst {0}", format)); } if (idxReg == null) { if (!dasm.rdr.TryReadByte(out b)) { return(null); } offset = Constant.SByte((sbyte)b); } break; default: throw new NotImplementedException(string.Format("Tlcs-90: dst {0}", format)); } if (!dasm.rdr.TryReadByte(out b)) { return(null); } var instr = dstEncodings[b].Decode(b, dasm); if (instr == null) { return(null); } var operand = new MemoryOperand(dasm.dataWidth) { Base = baseReg, Offset = absAddr.HasValue ? Constant.UInt16(absAddr.Value) : offset, }; if (dasm.backPatchOp == 0) { instr.op1 = operand; if (instr.op2 != null) { instr.op1.Width = instr.op2.Width; } } else if (dasm.backPatchOp == 1) { instr.op2 = operand; instr.op2.Width = instr.op1.Width; } else { return(null); } return(instr); }