OpCode32SimdMemMult.cs 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. namespace ARMeilleure.Decoders
  2. {
  3. class OpCode32SimdMemMult : OpCode32
  4. {
  5. public int Rn { get; }
  6. public int Vd { get; }
  7. public int RegisterRange { get; }
  8. public int Offset { get; }
  9. public int PostOffset { get; }
  10. public bool IsLoad { get; }
  11. public bool DoubleWidth { get; }
  12. public bool Add { get; }
  13. public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemMult(inst, address, opCode);
  14. public OpCode32SimdMemMult(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
  15. {
  16. Rn = (opCode >> 16) & 0xf;
  17. bool isLoad = (opCode & (1 << 20)) != 0;
  18. bool w = (opCode & (1 << 21)) != 0;
  19. bool u = (opCode & (1 << 23)) != 0;
  20. bool p = (opCode & (1 << 24)) != 0;
  21. if (p == u && w)
  22. {
  23. Instruction = InstDescriptor.Undefined;
  24. return;
  25. }
  26. DoubleWidth = (opCode & (1 << 8)) != 0;
  27. if (!DoubleWidth)
  28. {
  29. Vd = ((opCode >> 22) & 0x1) | ((opCode >> 11) & 0x1e);
  30. }
  31. else
  32. {
  33. Vd = ((opCode >> 18) & 0x10) | ((opCode >> 12) & 0xf);
  34. }
  35. Add = u;
  36. RegisterRange = opCode & 0xff;
  37. int regsSize = RegisterRange * 4; // Double mode is still measured in single register size.
  38. if (!u)
  39. {
  40. Offset -= regsSize;
  41. }
  42. if (w)
  43. {
  44. PostOffset = u ? regsSize : -regsSize;
  45. }
  46. else
  47. {
  48. PostOffset = 0;
  49. }
  50. IsLoad = isLoad;
  51. int regs = DoubleWidth ? RegisterRange / 2 : RegisterRange;
  52. if (RegisterRange == 0 || RegisterRange > 32 || Vd + regs > 32)
  53. {
  54. Instruction = InstDescriptor.Undefined;
  55. }
  56. }
  57. }
  58. }