1 // 2 // Copyright (c) 2010-2024 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 8 using Antmicro.Renode.Core; 9 using Antmicro.Renode.Core.Structure.Registers; 10 using Antmicro.Renode.Peripherals.Bus; 11 12 namespace Antmicro.Renode.Peripherals.Miscellaneous 13 { 14 public class MSP430F2XXX_MPY : BasicWordPeripheral, IBytePeripheral 15 { MSP430F2XXX_MPY(IMachine machine)16 public MSP430F2XXX_MPY(IMachine machine) : base(machine) 17 { 18 DefineRegisters(); 19 } 20 WriteByte(long offset, byte value)21 public void WriteByte(long offset, byte value) 22 { 23 if(offset == (long)Registers.MultiplySignedOperand1 || offset == (long)Registers.MultiplySignedAccumulateOperand1) 24 { 25 ushort extendedValue = value; 26 extendedValue |= (value & 0x80) > 0 ? (ushort)0xFF00 : (ushort)0; 27 WriteWord(offset, extendedValue); 28 return; 29 } 30 31 WriteWord(offset, value); 32 } 33 ReadByte(long offset)34 public byte ReadByte(long offset) 35 { 36 return (byte)ReadWord(offset); 37 } 38 SetModeAndOperand(ulong value, Mode mode)39 private void SetModeAndOperand(ulong value, Mode mode) 40 { 41 operand1 = (uint)value; 42 currentMode = mode; 43 } 44 StoreResult(ulong result)45 private void StoreResult(ulong result) 46 { 47 resultLow.Value = (ushort)result; 48 resultHigh.Value = (ushort)(result >> 16); 49 } 50 PerformCalculation(ulong operand2)51 private void PerformCalculation(ulong operand2) 52 { 53 switch(currentMode) 54 { 55 case Mode.Unsigned: 56 { 57 var result = operand1 * operand2; 58 59 StoreResult(result); 60 sumExtend.Value = 0; 61 break; 62 } 63 64 case Mode.Signed: 65 { 66 var result = (short)operand1 * (short)operand2; 67 StoreResult((ulong)result); 68 sumExtend.Value = result < 0 ? 0xFFFFU : 0U; 69 break; 70 } 71 72 case Mode.UnsignedAccumulate: 73 { 74 var result = LastResult + (int)(operand1 * operand2); 75 StoreResult((ulong)result); 76 sumExtend.Value = result > ushort.MaxValue ? 1U : 0U; 77 break; 78 } 79 80 case Mode.SignedAccumulate: 81 { 82 var result = LastResult + (short)operand1 * (short)operand2; 83 StoreResult((ulong)result); 84 sumExtend.Value = result < 0 ? 0xFFFFU : 0U; 85 break; 86 } 87 } 88 } 89 DefineRegisters()90 private void DefineRegisters() 91 { 92 Registers.MultiplyUnsignedOperand1.Define(this) 93 .WithValueField(0, 16, name: "MPY", 94 writeCallback: (_, value) => SetModeAndOperand(value, Mode.Unsigned)) 95 ; 96 97 Registers.MultiplySignedOperand1.Define(this) 98 .WithValueField(0, 16, name: "MPYS", 99 writeCallback: (_, value) => SetModeAndOperand(value, Mode.Signed)) 100 ; 101 102 Registers.MultiplyAccumulateOperand1.Define(this) 103 .WithValueField(0, 16, name: "MAC", 104 writeCallback: (_, value) => SetModeAndOperand(value, Mode.UnsignedAccumulate)) 105 ; 106 107 Registers.MultiplySignedAccumulateOperand1.Define(this) 108 .WithValueField(0, 16, name: "MACS", 109 writeCallback: (_, value) => SetModeAndOperand(value, Mode.SignedAccumulate)) 110 ; 111 112 Registers.SecondOperand.Define(this) 113 .WithValueField(0, 16, name: "OP2", 114 writeCallback: (_, value) => PerformCalculation(value)) 115 ; 116 117 Registers.ResultLow.Define(this) 118 .WithValueField(0, 16, out resultLow, name: "RESLO") 119 ; 120 121 Registers.ResultHigh.Define(this) 122 .WithValueField(0, 16, out resultHigh, name: "RESHI") 123 ; 124 125 Registers.SumExtend.Define(this) 126 .WithValueField(0, 16, out sumExtend, FieldMode.Read, name: "SUMEXT") 127 ; 128 } 129 130 private int LastResult => (int)resultLow.Value | ((int)resultHigh.Value << 16); 131 132 private Mode currentMode; 133 private uint operand1; 134 135 private IValueRegisterField resultLow; 136 private IValueRegisterField resultHigh; 137 private IValueRegisterField sumExtend; 138 139 private enum Mode 140 { 141 Unsigned, 142 Signed, 143 UnsignedAccumulate, 144 SignedAccumulate, 145 } 146 147 private enum Registers 148 { 149 MultiplyUnsignedOperand1 = 0x00, 150 MultiplySignedOperand1 = 0x02, 151 MultiplyAccumulateOperand1 = 0x04, 152 MultiplySignedAccumulateOperand1 = 0x06, 153 SecondOperand = 0x8, 154 ResultLow = 0xA, 155 ResultHigh = 0xC, 156 SumExtend = 0xE, 157 } 158 } 159 } 160