1 using System;
  2 using System.IO;
  3 using System.Collections;
  4 using CodeFormatter = System.Text.CodeFormatter;
  5 
  6 namespace cmsx.intermediate
  7 {
  8     public abstract class Location : Operand
  9     {
 10         public abstract void DebugPrint(CodeFormatter& formatter);
 11         public abstract void GenerateLoad(int loadOpCodeRegister* destinationRegMachineCode& machineCodeInstruction* inst);
 12         public abstract void GenerateLoadAddress(Register* destinationRegMachineCode& machineCodeInstruction* inst);
 13         public abstract void GenerateStore(int storeOpCodeRegister* valueRegMachineCode& machineCodeInstruction* inst);
 14     }
 15 
 16     public class FrameLocations
 17     {
 18         public FrameLocations(Registers& regs_) : regs(regs_)paramOffset(8)argOffset(8)
 19         {
 20         }
 21         public FrameLocation* GetFrameLocation(long size)
 22         {
 23             FrameLocation* location = null;
 24             if (paramOffset < MaxValue<byte>())
 25             {
 26                 location = new NearFrameLocation(cast<byte>(paramOffset)regs.GetFP());
 27             }
 28             else if (paramOffset < MaxValue<ushort>())
 29             {
 30                 location = new MediumFrameLocation(cast<ushort>(paramOffset)regs.GetFP()regs.GetIx());
 31             }
 32             else if (paramOffset < MaxValue<uint>())
 33             {
 34                 location = new FarFrameLocation(cast<uint>(paramOffset)regs.GetFP()regs.GetIx());
 35             }
 36             else
 37             {
 38                 throw Exception("frame too big");
 39             }
 40             paramOffset = paramOffset + size;
 41             paramOffset = 8 * ((paramOffset - 1) / 8 + 1);
 42             paramLocations.Add(UniquePtr<Location>(location));
 43             return location;
 44         }
 45         public FrameLocation* GetArgLocation()
 46         {
 47             FrameLocation* location = null;
 48             if (argOffset < MaxValue<byte>())
 49             {
 50                 location = new NearFrameLocation(cast<byte>(argOffset)regs.GetSP());
 51             }
 52             else if (argOffset < MaxValue<ushort>())
 53             {
 54                 location = new MediumFrameLocation(cast<ushort>(argOffset)regs.GetSP()regs.GetIx());
 55             }
 56             else if (argOffset < MaxValue<uint>())
 57             {
 58                 location = new FarFrameLocation(cast<uint>(argOffset)regs.GetSP()regs.GetIx());
 59             }
 60             argOffset = argOffset + 8;
 61             argLocations.Add(UniquePtr<Location>(location));
 62             return location;
 63         }
 64         public nothrow void ResetArgLocations()
 65         {
 66             argLocations.Clear();
 67             argOffset = 8;
 68         }
 69         public long paramOffset;
 70         public long argOffset;
 71         private List<UniquePtr<Location>> paramLocations;
 72         private List<UniquePtr<Location>> argLocations;
 73         private Registers& regs;
 74     }
 75 
 76     public abstract class MemoryLocation : Location
 77     {
 78     }
 79 
 80     public abstract class FrameLocation : MemoryLocation
 81     {
 82     }
 83 
 84     public class NearFrameLocation : FrameLocation
 85     {
 86         public nothrow NearFrameLocation(byte offset_Register* baseReg_) : offset(offset_)baseReg(baseReg_)
 87         {
 88         }
 89         public override void DebugPrint(CodeFormatter& formatter)
 90         {
 91             formatter << "frame.near(" << offset << ")";
 92         }
 93         public override void GenerateLoad(int loadOpCodeRegister* destinationRegMachineCode& machineCodeInstruction* inst)
 94         {
 95             MachineInstruction* loadInstruction = machineCode.GetInstruction(loadOpCodeinst);
 96             loadInstruction->AddOperand(destinationReg);
 97             loadInstruction->AddOperand(baseReg);
 98             loadInstruction->AddOperand(machineCode.context.GetLiteralOperand(offset));
 99         }
100         public override void GenerateLoadAddress(Register* destinationRegMachineCode& machineCodeInstruction* inst)
101         {
102             MachineInstruction* loadAddressInstruction = machineCode.GetInstruction(cmsx.assembly.LDAinst);
103             loadAddressInstruction->AddOperand(destinationReg);
104             loadAddressInstruction->AddOperand(baseReg);
105             loadAddressInstruction->AddOperand(machineCode.context.GetLiteralOperand(offset));
106         }
107         public override void GenerateStore(int storeOpCodeRegister* valueRegMachineCode& machineCodeInstruction* inst)
108         {
109             MachineInstruction* storeInstruction = machineCode.GetInstruction(storeOpCodeinst);
110             storeInstruction->AddOperand(valueReg);
111             storeInstruction->AddOperand(baseReg);
112             storeInstruction->AddOperand(machineCode.context.GetLiteralOperand(offset));
113         }
114         public byte offset;
115         public Register* baseReg;
116     }
117 
118     public class MediumFrameLocation : FrameLocation
119     {
120         public nothrow MediumFrameLocation(ushort offset_Register* baseReg_Register* ixReg_) : offset(offset_)baseReg(baseReg_)ixReg(ixReg_)
121         {
122         }
123         public override void DebugPrint(CodeFormatter& formatter)
124         {
125             formatter << "frame.medium(" << baseReg->name + ":" << offset << ")";
126         }
127         public override void GenerateLoad(int loadOpCodeRegister* destinationRegMachineCode& machineCodeInstruction* inst)
128         {
129             MachineInstruction* setIxInstruction = machineCode.GetInstruction(cmsx.assembly.SETinst);
130             setIxInstruction->AddOperand(ixReg);
131             setIxInstruction->AddOperand(machineCode.context.GetLiteralOperand(offset));
132             MachineInstruction* loadInstruction = machineCode.GetInstruction(loadOpCodeinst);
133             loadInstruction->AddOperand(destinationReg);
134             loadInstruction->AddOperand(baseReg);
135             loadInstruction->AddOperand(ixReg);
136         }
137         public override void GenerateLoadAddress(Register* destinationRegMachineCode& machineCodeInstruction* inst)
138         {
139             MachineInstruction* setIxInstruction = machineCode.GetInstruction(cmsx.assembly.SETinst);
140             setIxInstruction->AddOperand(ixReg);
141             setIxInstruction->AddOperand(machineCode.context.GetLiteralOperand(offset));
142             MachineInstruction* loadAddressInstruction = machineCode.GetInstruction(cmsx.assembly.LDAinst);
143             loadAddressInstruction->AddOperand(destinationReg);
144             loadAddressInstruction->AddOperand(baseReg);
145             loadAddressInstruction->AddOperand(ixReg);
146         }
147         public override void GenerateStore(int storeOpCodeRegister* valueRegMachineCode& machineCodeInstruction* inst)
148         {
149             MachineInstruction* setIxInstruction = machineCode.GetInstruction(cmsx.assembly.SETinst);
150             setIxInstruction->AddOperand(ixReg);
151             setIxInstruction->AddOperand(machineCode.context.GetLiteralOperand(offset));
152             MachineInstruction* storeInstruction = machineCode.GetInstruction(storeOpCodeinst);
153             storeInstruction->AddOperand(valueReg);
154             storeInstruction->AddOperand(baseReg);
155             storeInstruction->AddOperand(ixReg);
156         }
157         public ushort offset;
158         public Register* baseReg;
159         public Register* ixReg;
160     }
161 
162     public class FarFrameLocation : FrameLocation
163     {
164         public nothrow FarFrameLocation(uint offset_Register* baseReg_Register* ixReg_) : offset(offset_)baseReg(baseReg_)ixReg(ixReg_)
165         {
166         }
167         public override void DebugPrint(CodeFormatter& formatter)
168         {
169             formatter << "frame.far(" << baseReg->name + ":" << offset << ")";
170         }
171         public override void GenerateLoad(int loadOpCodeRegister* destinationRegMachineCode& machineCodeInstruction* inst)
172         {
173             MachineInstruction* setIxInstruction = machineCode.GetInstruction(cmsx.assembly.SETinst);
174             setIxInstruction->AddOperand(ixReg);
175             setIxInstruction->AddOperand(machineCode.context.GetLiteralOperand(offset & MaxValue<ushort>()));
176             MachineInstruction* orMlInstruction = machineCode.GetInstruction(cmsx.machine.ORMLinst);
177             orMlInstruction->AddOperand(ixReg);
178             orMlInstruction->AddOperand(machineCode.context.GetLiteralOperand((offset >> 16u)));
179             MachineInstruction* loadInstruction = machineCode.GetInstruction(loadOpCodeinst);
180             loadInstruction->AddOperand(destinationReg);
181             loadInstruction->AddOperand(baseReg);
182             loadInstruction->AddOperand(ixReg);
183         }
184         public override void GenerateLoadAddress(Register* destinationRegMachineCode& machineCodeInstruction* inst)
185         {
186             MachineInstruction* setIxInstruction = machineCode.GetInstruction(cmsx.assembly.SETinst);
187             setIxInstruction->AddOperand(ixReg);
188             setIxInstruction->AddOperand(machineCode.context.GetLiteralOperand(offset & MaxValue<ushort>()));
189             MachineInstruction* orMlInstruction = machineCode.GetInstruction(cmsx.machine.ORMLinst);
190             orMlInstruction->AddOperand(ixReg);
191             orMlInstruction->AddOperand(machineCode.context.GetLiteralOperand((offset >> 16u)));
192             MachineInstruction* loadAddressInstruction = machineCode.GetInstruction(cmsx.assembly.LDAinst);
193             loadAddressInstruction->AddOperand(destinationReg);
194             loadAddressInstruction->AddOperand(baseReg);
195             loadAddressInstruction->AddOperand(ixReg);
196         }
197         public override void GenerateStore(int storeOpCodeRegister* valueRegMachineCode& machineCodeInstruction* inst)
198         {
199             MachineInstruction* setIxInstruction = machineCode.GetInstruction(cmsx.assembly.SETinst);
200             setIxInstruction->AddOperand(ixReg);
201             setIxInstruction->AddOperand(machineCode.context.GetLiteralOperand(offset & MaxValue<ushort>()));
202             MachineInstruction* orMlInstruction = machineCode.GetInstruction(cmsx.machine.ORMLinst);
203             orMlInstruction->AddOperand(ixReg);
204             orMlInstruction->AddOperand(machineCode.context.GetLiteralOperand((offset >> 16u)));
205             MachineInstruction* storeInstruction = machineCode.GetInstruction(storeOpCodeinst);
206             storeInstruction->AddOperand(valueReg);
207             storeInstruction->AddOperand(baseReg);
208             storeInstruction->AddOperand(ixReg);
209         }
210         public uint offset;
211         public Register* baseReg;
212         public Register* ixReg;
213     }
214 
215     public class DataLocation : MemoryLocation
216     {
217         public nothrow DataLocation(SymbolOperand* symbolOperand_) : symbolOperand(symbolOperand_)
218         {
219         }
220         public override void DebugPrint(CodeFormatter& formatter)
221         {
222             formatter << "data(" << symbolOperand->value << ")";
223         }
224         public override void GenerateLoad(int loadOpCodeRegister* destinationRegMachineCode& machineCodeInstruction* inst)
225         {
226             Register* ptrReg = machineCode.context.regs.GetIx();
227             MachineInstruction* loadAddressInstruction = machineCode.GetInstruction(cmsx.machine.LDOUinst);
228             loadAddressInstruction->AddOperand(ptrReg);
229             loadAddressInstruction->AddOperand(symbolOperand);
230             MachineInstruction* loadInstruction = machineCode.GetInstruction(loadOpCodenull);
231             loadInstruction->AddOperand(destinationReg);
232             loadInstruction->AddOperand(ptrReg);
233             loadInstruction->AddOperand(machineCode.context.GetLiteralOperand(0u));
234         }
235         public override void GenerateLoadAddress(Register* destinationRegMachineCode& machineCodeInstruction* inst)
236         {
237             MachineInstruction* loadAddressInstruction = machineCode.GetInstruction(cmsx.machine.LDOUinst);
238             loadAddressInstruction->AddOperand(destinationReg);
239             loadAddressInstruction->AddOperand(symbolOperand);
240         }
241         public override void GenerateStore(int storeOpCodeRegister* valueRegMachineCode& machineCodeInstruction* inst)
242         {
243             Register* ptrReg = machineCode.context.regs.GetIx();
244             MachineInstruction* loadAddressInstruction = machineCode.GetInstruction(cmsx.machine.LDOUinst);
245             loadAddressInstruction->AddOperand(ptrReg);
246             loadAddressInstruction->AddOperand(symbolOperand);
247             MachineInstruction* storeInstruction = machineCode.GetInstruction(storeOpCodenull);
248             storeInstruction->AddOperand(valueReg);
249             storeInstruction->AddOperand(ptrReg);
250             storeInstruction->AddOperand(machineCode.context.GetLiteralOperand(0u));
251         }
252         private SymbolOperand* symbolOperand;
253     }
254 
255     public class DataLocations
256     {
257         public nothrow DataLocations()
258         {
259         }
260         public DataLocation* GetDataLocation(SymbolOperand* symbolOperand)
261         {
262             DataLocation* dataLocation = new DataLocation(symbolOperand);
263             locations.Add(UniquePtr<Location>(dataLocation));
264             return dataLocation;
265         }
266         private List<UniquePtr<Location>> locations;
267 
268     }
269 }