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 loadOpCode, Register* destinationReg, MachineCode& machineCode, Instruction* inst);
12 public abstract void GenerateLoadAddress(Register* destinationReg, MachineCode& machineCode, Instruction* inst);
13 public abstract void GenerateStore(int storeOpCode, Register* valueReg, MachineCode& machineCode, Instruction* 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 loadOpCode, Register* destinationReg, MachineCode& machineCode, Instruction* inst)
94 {
95 MachineInstruction* loadInstruction = machineCode.GetInstruction(loadOpCode, inst);
96 loadInstruction->AddOperand(destinationReg);
97 loadInstruction->AddOperand(baseReg);
98 loadInstruction->AddOperand(machineCode.context.GetLiteralOperand(offset));
99 }
100 public override void GenerateLoadAddress(Register* destinationReg, MachineCode& machineCode, Instruction* inst)
101 {
102 MachineInstruction* loadAddressInstruction = machineCode.GetInstruction(cmsx.assembly.LDA, inst);
103 loadAddressInstruction->AddOperand(destinationReg);
104 loadAddressInstruction->AddOperand(baseReg);
105 loadAddressInstruction->AddOperand(machineCode.context.GetLiteralOperand(offset));
106 }
107 public override void GenerateStore(int storeOpCode, Register* valueReg, MachineCode& machineCode, Instruction* inst)
108 {
109 MachineInstruction* storeInstruction = machineCode.GetInstruction(storeOpCode, inst);
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 loadOpCode, Register* destinationReg, MachineCode& machineCode, Instruction* inst)
128 {
129 MachineInstruction* setIxInstruction = machineCode.GetInstruction(cmsx.assembly.SET, inst);
130 setIxInstruction->AddOperand(ixReg);
131 setIxInstruction->AddOperand(machineCode.context.GetLiteralOperand(offset));
132 MachineInstruction* loadInstruction = machineCode.GetInstruction(loadOpCode, inst);
133 loadInstruction->AddOperand(destinationReg);
134 loadInstruction->AddOperand(baseReg);
135 loadInstruction->AddOperand(ixReg);
136 }
137 public override void GenerateLoadAddress(Register* destinationReg, MachineCode& machineCode, Instruction* inst)
138 {
139 MachineInstruction* setIxInstruction = machineCode.GetInstruction(cmsx.assembly.SET, inst);
140 setIxInstruction->AddOperand(ixReg);
141 setIxInstruction->AddOperand(machineCode.context.GetLiteralOperand(offset));
142 MachineInstruction* loadAddressInstruction = machineCode.GetInstruction(cmsx.assembly.LDA, inst);
143 loadAddressInstruction->AddOperand(destinationReg);
144 loadAddressInstruction->AddOperand(baseReg);
145 loadAddressInstruction->AddOperand(ixReg);
146 }
147 public override void GenerateStore(int storeOpCode, Register* valueReg, MachineCode& machineCode, Instruction* inst)
148 {
149 MachineInstruction* setIxInstruction = machineCode.GetInstruction(cmsx.assembly.SET, inst);
150 setIxInstruction->AddOperand(ixReg);
151 setIxInstruction->AddOperand(machineCode.context.GetLiteralOperand(offset));
152 MachineInstruction* storeInstruction = machineCode.GetInstruction(storeOpCode, inst);
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 loadOpCode, Register* destinationReg, MachineCode& machineCode, Instruction* inst)
172 {
173 MachineInstruction* setIxInstruction = machineCode.GetInstruction(cmsx.assembly.SET, inst);
174 setIxInstruction->AddOperand(ixReg);
175 setIxInstruction->AddOperand(machineCode.context.GetLiteralOperand(offset & MaxValue<ushort>()));
176 MachineInstruction* orMlInstruction = machineCode.GetInstruction(cmsx.machine.ORML, inst);
177 orMlInstruction->AddOperand(ixReg);
178 orMlInstruction->AddOperand(machineCode.context.GetLiteralOperand((offset >> 16u)));
179 MachineInstruction* loadInstruction = machineCode.GetInstruction(loadOpCode, inst);
180 loadInstruction->AddOperand(destinationReg);
181 loadInstruction->AddOperand(baseReg);
182 loadInstruction->AddOperand(ixReg);
183 }
184 public override void GenerateLoadAddress(Register* destinationReg, MachineCode& machineCode, Instruction* inst)
185 {
186 MachineInstruction* setIxInstruction = machineCode.GetInstruction(cmsx.assembly.SET, inst);
187 setIxInstruction->AddOperand(ixReg);
188 setIxInstruction->AddOperand(machineCode.context.GetLiteralOperand(offset & MaxValue<ushort>()));
189 MachineInstruction* orMlInstruction = machineCode.GetInstruction(cmsx.machine.ORML, inst);
190 orMlInstruction->AddOperand(ixReg);
191 orMlInstruction->AddOperand(machineCode.context.GetLiteralOperand((offset >> 16u)));
192 MachineInstruction* loadAddressInstruction = machineCode.GetInstruction(cmsx.assembly.LDA, inst);
193 loadAddressInstruction->AddOperand(destinationReg);
194 loadAddressInstruction->AddOperand(baseReg);
195 loadAddressInstruction->AddOperand(ixReg);
196 }
197 public override void GenerateStore(int storeOpCode, Register* valueReg, MachineCode& machineCode, Instruction* inst)
198 {
199 MachineInstruction* setIxInstruction = machineCode.GetInstruction(cmsx.assembly.SET, inst);
200 setIxInstruction->AddOperand(ixReg);
201 setIxInstruction->AddOperand(machineCode.context.GetLiteralOperand(offset & MaxValue<ushort>()));
202 MachineInstruction* orMlInstruction = machineCode.GetInstruction(cmsx.machine.ORML, inst);
203 orMlInstruction->AddOperand(ixReg);
204 orMlInstruction->AddOperand(machineCode.context.GetLiteralOperand((offset >> 16u)));
205 MachineInstruction* storeInstruction = machineCode.GetInstruction(storeOpCode, inst);
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 loadOpCode, Register* destinationReg, MachineCode& machineCode, Instruction* inst)
225 {
226 Register* ptrReg = machineCode.context.regs.GetIx();
227 MachineInstruction* loadAddressInstruction = machineCode.GetInstruction(cmsx.machine.LDOU, inst);
228 loadAddressInstruction->AddOperand(ptrReg);
229 loadAddressInstruction->AddOperand(symbolOperand);
230 MachineInstruction* loadInstruction = machineCode.GetInstruction(loadOpCode, null);
231 loadInstruction->AddOperand(destinationReg);
232 loadInstruction->AddOperand(ptrReg);
233 loadInstruction->AddOperand(machineCode.context.GetLiteralOperand(0u));
234 }
235 public override void GenerateLoadAddress(Register* destinationReg, MachineCode& machineCode, Instruction* inst)
236 {
237 MachineInstruction* loadAddressInstruction = machineCode.GetInstruction(cmsx.machine.LDOU, inst);
238 loadAddressInstruction->AddOperand(destinationReg);
239 loadAddressInstruction->AddOperand(symbolOperand);
240 }
241 public override void GenerateStore(int storeOpCode, Register* valueReg, MachineCode& machineCode, Instruction* inst)
242 {
243 Register* ptrReg = machineCode.context.regs.GetIx();
244 MachineInstruction* loadAddressInstruction = machineCode.GetInstruction(cmsx.machine.LDOU, inst);
245 loadAddressInstruction->AddOperand(ptrReg);
246 loadAddressInstruction->AddOperand(symbolOperand);
247 MachineInstruction* storeInstruction = machineCode.GetInstruction(storeOpCode, null);
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 }