1 using System;
2 using System.Collections;
3 using Span = System.Lex.Span;
4 using cmsx.object;
5
6 namespace cmsx.assembly
7 {
8 public enum Stage : byte
9 {
10 resolve = 0u, assemble = 1u, is_ = 2u, setExternal = 3u, setLinkOnce = 4u, bytes = 5u, wydes = 6u, tetras = 7u, octas = 8u, clsid = 9u, spec = 10u, funcInfo = 11u, fileInfo = 12u, lineInfo = 13u,
11 exceptionInfo = 14u
12 }
13
14 private AssemblyLexer* currentAssemblyLexer = null;
15
16 public class ScopedAssemblyLexerPtr
17 {
18 public nothrow ScopedAssemblyLexerPtr(AssemblyLexer* lexer)
19 {
20 currentAssemblyLexer = lexer;
21 }
22 public ~ScopedAssemblyLexerPtr()
23 {
24 currentAssemblyLexer = null;
25 }
26 }
27
28 public void Error(const string& message, const Span& span)
29 {
30 if (currentAssemblyLexer != null)
31 {
32 throw Exception(message + ":\n" + ToUtf8(currentAssemblyLexer->ErrorLines(span)));
33 }
34 else
35 {
36 throw Exception(message);
37 }
38 }
39
40 public class Assembler : Visitor
41 {
42 public Assembler(const string& objectFileName) :
43 objectFile(objectFileName, true), stage(Stage.resolve), currentSegment(Segment.text), currentSection(objectFile.codeSection), currentInstruction(null), currentSymbol(null), currentValue(),
44 currentFunctionSymbol(null), currentStructureSymbol(null), externalLinkCommandOffset(0)
45 {
46 }
47 public void Assemble(List<UniquePtr<Instruction>>& instructions)
48 {
49 currentSegment = Segment.text;
50 currentSection = objectFile.codeSection;
51 stage = Stage.resolve;
52 long n = instructions.Count();
53 for (long i = 0; i < n; ++i;)
54 {
55 Instruction* inst = instructions[i].Get();
56 inst->Accept(*this);
57 }
58 currentSegment = Segment.text;
59 currentSection = objectFile.codeSection;
60 stage = Stage.assemble;
61 for (long i = 0; i < n; ++i;)
62 {
63 Instruction* inst = instructions[i].Get();
64 inst->Accept(*this);
65 }
66 }
67 public void WriteObjectFile()
68 {
69 objectFile.Write();
70 }
71 public Value Evaluate(Node* node)
72 {
73 currentValue = Value();
74 currentSymbol = null;
75 node->Accept(*this);
76 Value value = currentValue;
77 currentValue = Value();
78 return value;
79 }
80 public void EmitOpCode(byte opCode)
81 {
82 if (currentSegment != Segment.text)
83 {
84 Error(currentInstruction->opCode->name + " instruction can appear only in .CODE section", currentInstruction->opCode->span);
85 }
86 currentSection->EmitByte(opCode);
87 }
88 public void EmitRegisterValue(const string& paramName, const Value& v)
89 {
90 if (v.flags == Value.Flag.register)
91 {
92 if (v.value < 256u)
93 {
94 currentSection->EmitByte(cast<byte>(v.value));
95 }
96 else
97 {
98 Error("invalid " + currentInstruction->opCode->name + " " + paramName + " register operand", currentInstruction->span);
99 }
100 }
101 else
102 {
103 Error(currentInstruction->opCode->name + " instruction " + paramName + " operand must be a register", currentInstruction->span);
104 }
105 }
106 public void EmitPureByteValue(const string& paramName, const Value& v)
107 {
108 if (v.GetFlag(Value.Flag.pure))
109 {
110 if (v.value < 256u)
111 {
112 currentSection->EmitByte(cast<byte>(v.value));
113 }
114 else
115 {
116 Error("invalid " + currentInstruction->opCode->name + " " + paramName + " byte operand", currentInstruction->span);
117 }
118 }
119 else
120 {
121 Error(currentInstruction->opCode->name + " instruction " + paramName + " operand must be pure byte value", currentInstruction->span);
122 }
123 }
124 public void EmitSetReg255Value(ulong value)
125 {
126 if (value <= MaxValue<ushort>())
127 {
128 byte b0 = cast<byte>(value);
129 value = value >> 8u;
130 byte b1 = cast<byte>(value);
131 value = value >> 8u;
132 EmitOpCode(cmsx.machine.SETL);
133 currentSection->EmitByte(255u);
134 currentSection->EmitByte(b1);
135 currentSection->EmitByte(b0);
136 }
137 else if (value <= MaxValue<uint>())
138 {
139 byte b0 = cast<byte>(value);
140 value = value >> 8u;
141 byte b1 = cast<byte>(value);
142 value = value >> 8u;
143 byte b2 = cast<byte>(value);
144 value = value >> 8u;
145 byte b3 = cast<byte>(value);
146 value = value >> 8u;
147 EmitOpCode(cmsx.machine.SETML);
148 currentSection->EmitByte(255u);
149 currentSection->EmitByte(b3);
150 currentSection->EmitByte(b2);
151 EmitOpCode(cmsx.machine.ORL);
152 currentSection->EmitByte(255u);
153 currentSection->EmitByte(b1);
154 currentSection->EmitByte(b0);
155 }
156 else
157 {
158 byte b0 = cast<byte>(value);
159 value = value >> 8u;
160 byte b1 = cast<byte>(value);
161 value = value >> 8u;
162 byte b2 = cast<byte>(value);
163 value = value >> 8u;
164 byte b3 = cast<byte>(value);
165 value = value >> 8u;
166 byte b4 = cast<byte>(value);
167 value = value >> 8u;
168 byte b5 = cast<byte>(value);
169 value = value >> 8u;
170 byte b6 = cast<byte>(value);
171 value = value >> 8u;
172 byte b7 = cast<byte>(value);
173 value = value >> 8u;
174 EmitOpCode(cmsx.machine.SETH);
175 currentSection->EmitByte(255u);
176 currentSection->EmitByte(b7);
177 currentSection->EmitByte(b6);
178 EmitOpCode(cmsx.machine.ORMH);
179 currentSection->EmitByte(255u);
180 currentSection->EmitByte(b5);
181 currentSection->EmitByte(b4);
182 EmitOpCode(cmsx.machine.ORML);
183 currentSection->EmitByte(255u);
184 currentSection->EmitByte(b3);
185 currentSection->EmitByte(b2);
186 EmitOpCode(cmsx.machine.ORL);
187 currentSection->EmitByte(255u);
188 currentSection->EmitByte(b1);
189 currentSection->EmitByte(b0);
190 }
191 }
192 public void EmitAbsoluteRegisterValue(const Value& registerNumber, const string& paramName, Symbol* symbol)
193 {
194 #assert(symbol->index != -1);
195 byte reg = 0u;
196 if (registerNumber.flags == Value.Flag.register)
197 {
198 if (registerNumber.value < 256u)
199 {
200 reg = cast<byte>(registerNumber.value);
201 }
202 else
203 {
204 Error("invalid " + currentInstruction->opCode->name + " " + paramName + " register operand", currentInstruction->span);
205 }
206 }
207 else
208 {
209 Error(currentInstruction->opCode->name + " instruction " + paramName + " operand must be a register", currentInstruction->span);
210 }
211 if (currentSegment != Segment.text)
212 {
213 Error(currentInstruction->opCode->name + " instruction can appear only in .CODE section", currentInstruction->opCode->span);
214 }
215 objectFile.linkSection->EmitByte(LinkCode.absoluteAddrValue);
216 objectFile.linkSection->EmitUInt(cast<uint>(symbol->index));
217 objectFile.linkSection->EmitULong(objectFile.codeSection->Address());
218 externalLinkCommandOffset = externalLinkCommandOffset + cast<int>(sizeof(byte) + sizeof(uint) + sizeof(ulong));
219 objectFile.codeSection->EmitByte(cmsx.machine.SETH);
220 objectFile.codeSection->EmitByte(reg);
221 objectFile.codeSection->EmitShortOffset(cast<ushort>(-1));
222 objectFile.codeSection->EmitByte(cmsx.machine.ORMH);
223 objectFile.codeSection->EmitByte(reg);
224 objectFile.codeSection->EmitShortOffset(cast<ushort>(-1));
225 objectFile.codeSection->EmitByte(cmsx.machine.ORML);
226 objectFile.codeSection->EmitByte(reg);
227 objectFile.codeSection->EmitShortOffset(cast<ushort>(-1));
228 objectFile.codeSection->EmitByte(cmsx.machine.ORL);
229 objectFile.codeSection->EmitByte(reg);
230 objectFile.codeSection->EmitShortOffset(cast<ushort>(-1));
231 }
232 public void EmitForwardLongJump(Symbol* symbol)
233 {
234 #assert(symbol->index != -1);
235 if (currentSegment != Segment.text)
236 {
237 Error(currentInstruction->opCode->name + " instruction can appear only in .CODE section", currentInstruction->opCode->span);
238 }
239 objectFile.linkSection->EmitByte(LinkCode.forwardLongJump);
240 objectFile.linkSection->EmitUInt(cast<uint>(symbol->index));
241 objectFile.linkSection->EmitULong(objectFile.codeSection->Address());
242 objectFile.codeSection->EmitByte(cmsx.machine.JMP);
243 objectFile.codeSection->EmitLongOffset(cast<uint>(-1));
244 }
245 public void EmitForwardShortJump(const string& paramName, byte opCode, const Value& registerNumber, Symbol* symbol)
246 {
247 byte reg = 0u;
248 if (registerNumber.flags == Value.Flag.register)
249 {
250 if (registerNumber.value < 256u)
251 {
252 reg = cast<byte>(registerNumber.value);
253 }
254 else
255 {
256 Error("invalid " + currentInstruction->opCode->name + " " + paramName + " register operand", currentInstruction->span);
257 }
258 }
259 else
260 {
261 Error(currentInstruction->opCode->name + " instruction " + paramName + " operand must be a register", currentInstruction->span);
262 }
263 #assert(symbol->index != -1);
264 if (currentSegment != Segment.text)
265 {
266 Error(currentInstruction->opCode->name + " instruction can appear only in .CODE section", currentInstruction->opCode->span);
267 }
268 objectFile.linkSection->EmitByte(LinkCode.forwardShortJump);
269 objectFile.linkSection->EmitUInt(cast<uint>(symbol->index));
270 objectFile.linkSection->EmitULong(objectFile.codeSection->Address());
271 objectFile.codeSection->EmitByte(opCode);
272 objectFile.codeSection->EmitByte(reg);
273 objectFile.codeSection->EmitShortOffset(cast<ushort>(-1));
274 }
275 public void EmitLinkClsIdCommand(const Uuid& typeId)
276 {
277 objectFile.linkSection->EmitByte(LinkCode.clsid);
278 objectFile.linkSection->EmitULong(objectFile.dataSection->Address());
279 objectFile.linkSection->EmitULong(typeId.LeftHalf());
280 objectFile.linkSection->EmitULong(typeId.RightHalf());
281 externalLinkCommandOffset = externalLinkCommandOffset + cast<int>(sizeof(byte) + sizeof(ulong) + sizeof(ulong) + sizeof(ulong));
282 objectFile.dataSection->EmitULong(cast<ulong>(-1));
283 }
284 public void EmitLongOffset(uint offset)
285 {
286 currentSection->EmitLongOffset(offset);
287 }
288 public void EmitShortOffset(ushort offset)
289 {
290 currentSection->EmitShortOffset(offset);
291 }
292 public override void Visit(Instruction& inst)
293 {
294 currentInstruction = &inst;
295 if (stage == Stage.resolve)
296 {
297 inst.opCode->Accept(*this);
298 if (currentInstruction->opCode->value == CODE)
299 {
300 currentSegment = Segment.text;
301 currentSection = objectFile.codeSection;
302 return;
303 }
304 else if (currentInstruction->opCode->value == DATA)
305 {
306 currentSegment = Segment.data;
307 currentSection = objectFile.dataSection;
308 return;
309 }
310 else if (currentInstruction->opCode->value == DEBUG)
311 {
312 currentSegment = Segment.data;
313 currentSection = objectFile.debugSection;
314 return;
315 }
316 if (!inst.label.IsNull())
317 {
318 int opc = currentInstruction->opCode->value;
319 if (opc == EXTERN || opc == LINKONCE)
320 {
321 Error("no label field allowed for EXTERN or LINKONCE instruction", inst.label->span);
322 }
323 else if (opc != IS)
324 {
325 inst.label->Accept(*this);
326 }
327 }
328 }
329 else if (stage == Stage.assemble)
330 {
331 int opc = currentInstruction->opCode->value;
332 if (opc == CODE)
333 {
334 currentSegment = Segment.text;
335 currentSection = objectFile.codeSection;
336 return;
337 }
338 else if (opc == DATA)
339 {
340 currentSegment = Segment.data;
341 currentSection = objectFile.dataSection;
342 return;
343 }
344 else if (opc == DEBUG)
345 {
346 currentSegment = Segment.data;
347 currentSection = objectFile.debugSection;
348 return;
349 }
350 currentSymbol = null;
351 currentAlignment = 1u;
352 if (currentSection != objectFile.debugSection && !inSpec)
353 {
354 AlignAt();
355 }
356 if (!inst.label.IsNull())
357 {
358 if (opc == EXTERN || opc == LINKONCE)
359 {
360 Error("no label field allowed for EXTERN or LINKONCE instruction", inst.label->span);
361 }
362 else if (opc != IS)
363 {
364 currentInstruction->label->Accept(*this);
365 if (currentSymbol != null)
366 {
367 if (opc == FUNC)
368 {
369 currentSymbol->value = Value(cast<Value.Flag>(Value.Flag.definition | Value.Flag.pure | Value.Flag.address | Value.Flag.function), currentSection->Address(), currentSymbol);
370 currentFunctionSymbol = currentSymbol;
371 currentSymbol->start = currentSection->BaseAddress() + currentSection->Address();
372 parentSymbolIndex = currentSymbol->index;
373 currentSymbol->linkStart = externalLinkCommandOffset;
374 currentSymbol->alignment = 4u;
375 if (objectFile.debugSection is DebugSection*)
376 {
377 DebugSection* debugSection = cast<DebugSection*>(objectFile.debugSection);
378 debugSection->EmitStartFunc(cast<uint>(currentSymbol->index));
379 }
380 else
381 {
382 throw Exception("debug section expected");
383 }
384 }
385 else if (opc == STRUCT)
386 {
387 currentSection->Align(8u);
388 currentSymbol->value = Value(cast<Value.Flag>(Value.Flag.definition | Value.Flag.pure | Value.Flag.address | Value.Flag.structure), currentSection->Address(), currentSymbol);
389 currentStructureSymbol = currentSymbol;
390 currentSymbol->start = currentSection->BaseAddress() + currentSection->Address();
391 parentSymbolIndex = currentSymbol->index;
392 currentSymbol->linkStart = externalLinkCommandOffset;
393 currentSymbol->alignment = 8u;
394 }
395 else if (opc == ENDF)
396 {
397 currentSymbol->length = currentSection->BaseAddress() + currentSection->Address() - currentSymbol->start;
398 parentSymbolIndex = -1;
399 currentSymbol->linkEnd = externalLinkCommandOffset;
400 if (objectFile.debugSection is DebugSection*)
401 {
402 DebugSection* debugSection = cast<DebugSection*>(objectFile.debugSection);
403 debugSection->EmitEndFunc(cast<uint>(currentSymbol->index));
404 }
405 else
406 {
407 throw Exception("debug section expected");
408 }
409 }
410 else if (opc == ENDS)
411 {
412 currentSymbol->length = cast<ulong>(Align(cast<long>(currentSection->BaseAddress() + currentSection->Address() - currentSymbol->start), currentSymbol->alignment));
413 currentSection->Align(currentSymbol->alignment);
414 parentSymbolIndex = -1;
415 currentSymbol->linkEnd = externalLinkCommandOffset;
416 }
417 else
418 {
419 currentSymbol->value = Value(cast<Value.Flag>(Value.Flag.pure | Value.Flag.address), currentSection->Address(), currentSymbol);
420 currentSymbol->start = currentSection->BaseAddress() + currentSection->Address();
421 currentSymbol->alignment = currentAlignment;
422 if (parentSymbolIndex != -1)
423 {
424 currentSymbol->parentIndex = parentSymbolIndex;
425 }
426 }
427 objectFile.GetSymbolTable().AddSymbolToAddressMap(currentSymbol);
428 }
429 else
430 {
431 Error("label not found", currentInstruction->label->span);
432 }
433 }
434 }
435 if (opc != FUNC && opc != ENDF && opc != STRUCT && opc != ENDS)
436 {
437 AssemblyInstruction* assemblyInstruction = AssemblyInstructionMap.Instance().GetAssemblyInstruction(opc, currentInstruction->span);
438 assemblyInstruction->Assemble(*this, currentInstruction);
439 }
440 }
441 }
442 public override void Visit(ClsIdConstant& clsIdConstant)
443 {
444 Uuid typeId = ParseUuid(clsIdConstant.typeId);
445 EmitLinkClsIdCommand(typeId);
446 }
447 public override void Visit(OpCode& opCode)
448 {
449 const string& opCodeName = opCode.name;
450 opCode.value = cmsx.machine.GetOpCode(opCodeName);
451 if (opCode.value == -1)
452 {
453 opCode.value = PseudoOpMap.Instance().GetCode(opCodeName);
454 }
455 if (opCode.value == -1)
456 {
457 Error("unknown opcode '" + opCodeName + "'", opCode.span);
458 }
459 }
460 public override void Visit(SymbolNode& node)
461 {
462 int opc = currentInstruction->opCode->value;
463 if (stage == Stage.resolve)
464 {
465 Symbol* symbol = objectFile.GetSymbolTable().GetSymbol(node.name);
466 if (symbol != null)
467 {
468 if (opc == ENDF)
469 {
470 currentFunctionSymbol = null;
471 }
472 else if (opc == ENDS)
473 {
474 currentStructureSymbol = null;
475 }
476 else
477 {
478 Error("symbol '" + node.name + "' already defined", node.span);
479 }
480 }
481 else
482 {
483 if (opc == ENDF)
484 {
485 Error("no corresponding FUNC '" + node.name + "' seen", node.span);
486 }
487 else if (opc == ENDS)
488 {
489 Error("no corresponding STRUCT '" + node.name + "' seen", node.span);
490 }
491 symbol = new Symbol();
492 if (node.local)
493 {
494 if (currentFunctionSymbol != null)
495 {
496 symbol->name = currentFunctionSymbol->name + node.name;
497 symbol->localName = node.name;
498 }
499 else
500 {
501 Error("local symbols can be used only inside FUNC", node.span);
502 }
503 }
504 else
505 {
506 symbol->name = node.name;
507 }
508 symbol->segment = currentSegment;
509 symbol->linkage = Linkage.internal_;
510 symbol->value = Value(Value.Flag.undefined, undefinedValue, symbol);
511 if (opc == FUNC)
512 {
513 currentFunctionSymbol = symbol;
514 }
515 else if (opc == STRUCT)
516 {
517 currentStructureSymbol = symbol;
518 }
519 symbol->start = 0u;
520 symbol->length = 0u;
521 symbol->section = currentSection;
522 objectFile.GetSymbolTable().AddSymbol(symbol);
523 if (currentSegment == Segment.data)
524 {
525 currentSection->AddSymbol(symbol);
526 }
527 }
528 }
529 else if (stage == Stage.assemble)
530 {
531 if (opc == ENDF)
532 {
533 currentFunctionSymbol = null;
534 }
535 if (opc == ENDS)
536 {
537 currentStructureSymbol = null;
538 }
539 if (node.local)
540 {
541 if (currentFunctionSymbol != null)
542 {
543 currentSymbol = objectFile.GetSymbolTable().GetSymbol(currentFunctionSymbol->name + node.name);
544 }
545 else
546 {
547 Error("local symbols can be used only inside FUNC", node.span);
548 }
549 }
550 else
551 {
552 currentSymbol = objectFile.GetSymbolTable().GetSymbol(node.name);
553 }
554 if (currentSymbol == null)
555 {
556 currentSymbol = new Symbol();
557 currentSymbol->name = node.name;
558 currentSymbol->linkage = Linkage.undefined;
559 currentSymbol->value = Value(Value.Flag.undefined, undefinedValue, currentSymbol);
560 currentSymbol->start = 0u;
561 currentSymbol->length = 0u;
562 currentSymbol->section = currentSection;
563 objectFile.GetSymbolTable().AddSymbol(currentSymbol);
564 }
565 currentValue = currentSymbol->value;
566 }
567 else if (stage == Stage.is_)
568 {
569 currentSymbol = objectFile.GetSymbolTable().GetSymbol(node.name);
570 if (currentSymbol != null)
571 {
572 Error("symbol '" + node.name + "' already defined", node.span);
573 }
574 else
575 {
576 currentSymbol = new Symbol();
577 currentSymbol->name = node.name;
578 currentSymbol->segment = Segment.unknown;
579 currentSymbol->linkage = Linkage.internal_;
580 currentSymbol->value = Value(Value.Flag.undefined, undefinedValue, currentSymbol);
581 currentSymbol->start = 0u;
582 currentSymbol->length = 0u;
583 currentSymbol->section = currentSection;
584 objectFile.GetSymbolTable().AddSymbol(currentSymbol);
585 }
586 }
587 else if (stage == Stage.setExternal)
588 {
589 currentSymbol = objectFile.GetSymbolTable().GetSymbol(node.name);
590 if (currentSymbol != null)
591 {
592 currentSymbol->linkage = Linkage.external;
593 }
594 else
595 {
596 Error("symbol '" + node.name + " not found", node.span);
597 }
598 }
599 else if (stage == Stage.setLinkOnce)
600 {
601 currentSymbol = objectFile.GetSymbolTable().GetSymbol(node.name);
602 if (currentSymbol != null)
603 {
604 currentSymbol->linkage = Linkage.once;
605 }
606 else
607 {
608 Error("symbol '" + node.name + " not found", node.span);
609 }
610 }
611 else if (stage == Stage.octas)
612 {
613 if (currentSegment != Segment.data)
614 {
615 Error("OCTA allowed only in .DATA section", node.span);
616 }
617 currentSymbol = objectFile.GetSymbolTable().GetSymbol(node.name);
618 if (currentSymbol == null)
619 {
620 currentSymbol = new Symbol();
621 currentSymbol->name = node.name;
622 currentSymbol->segment = Segment.unknown;
623 currentSymbol->linkage = Linkage.undefined;
624 currentSymbol->value = Value(Value.Flag.undefined, undefinedValue, currentSymbol);
625 currentSymbol->section = currentSection;
626 objectFile.GetSymbolTable().AddSymbol(currentSymbol);
627 }
628 objectFile.linkSection->EmitByte(LinkCode.farOcta);
629 objectFile.linkSection->EmitUInt(cast<uint>(currentSymbol->index));
630 objectFile.linkSection->EmitULong(objectFile.dataSection->Address());
631 externalLinkCommandOffset = externalLinkCommandOffset + cast<int>(sizeof(byte) + sizeof(uint) + sizeof(ulong));
632 objectFile.dataSection->EmitULong(cast<ulong>(-1));
633 }
634 else if (stage == Stage.clsid)
635 {
636 currentSymbol = objectFile.GetSymbolTable().GetSymbol(node.name);
637 if (currentSymbol == null)
638 {
639 Error("symbol '" + node.name + " not found", node.span);
640 }
641 }
642 else if (stage == Stage.funcInfo)
643 {
644 currentSymbol = objectFile.GetSymbolTable().GetSymbol(node.name);
645 if (currentSymbol == null)
646 {
647 Error("symbol '" + node.name + " not found", node.span);
648 }
649 else
650 {
651 currentValue = Value(Value.Flag.function, undefinedValue, currentSymbol);
652 }
653 }
654 else
655 {
656 Error("undefined symbol '" + node.name + "' and not in OCTA mode", node.span);
657 }
658 }
659 private void ProcessValue(ulong value, const Span& span)
660 {
661 currentValue = Value(Value.Flag.pure, value, null);
662 if (stage == Stage.bytes)
663 {
664 if (value > 255u)
665 {
666 Error("invalid BYTE operand", span);
667 }
668 else
669 {
670 currentSection->EmitByte(cast<byte>(currentValue.value));
671 }
672 }
673 else if (stage == Stage.wydes)
674 {
675 if (value > 65535u)
676 {
677 Error("invalid WYDE operand", span);
678 }
679 else
680 {
681 byte b0 = cast<byte>(value);
682 value = value >> 8u;
683 byte b1 = cast<byte>(value);
684 value = value >> 8u;
685 currentSection->EmitByte(b1);
686 currentSection->EmitByte(b0);
687 }
688 }
689 else if (stage == Stage.tetras)
690 {
691 if (value > 0xFFFFFFFFu)
692 {
693 Error("invalid TETRA operand", span);
694 }
695 else
696 {
697 byte b0 = cast<byte>(value);
698 value = value >> 8u;
699 byte b1 = cast<byte>(value);
700 value = value >> 8u;
701 byte b2 = cast<byte>(value);
702 value = value >> 8u;
703 byte b3 = cast<byte>(value);
704 value = value >> 8u;
705 currentSection->EmitByte(b3);
706 currentSection->EmitByte(b2);
707 currentSection->EmitByte(b1);
708 currentSection->EmitByte(b0);
709 }
710 }
711 else if (stage == Stage.octas)
712 {
713 byte b0 = cast<byte>(value);
714 value = value >> 8u;
715 byte b1 = cast<byte>(value);
716 value = value >> 8u;
717 byte b2 = cast<byte>(value);
718 value = value >> 8u;
719 byte b3 = cast<byte>(value);
720 value = value >> 8u;
721 byte b4 = cast<byte>(value);
722 value = value >> 8u;
723 byte b5 = cast<byte>(value);
724 value = value >> 8u;
725 byte b6 = cast<byte>(value);
726 value = value >> 8u;
727 byte b7 = cast<byte>(value);
728 value = value >> 8u;
729 currentSection->EmitByte(b7);
730 currentSection->EmitByte(b6);
731 currentSection->EmitByte(b5);
732 currentSection->EmitByte(b4);
733 currentSection->EmitByte(b3);
734 currentSection->EmitByte(b2);
735 currentSection->EmitByte(b1);
736 currentSection->EmitByte(b0);
737 }
738 }
739 public override void Visit(DecimalConstant& dc)
740 {
741 ProcessValue(dc.value, dc.span);
742 }
743 public override void Visit(HexConstant& hc)
744 {
745 ProcessValue(hc.value, hc.span);
746 }
747 public override void Visit(CharacterConstant& cc)
748 {
749 currentValue = Value(Value.Flag.pure, cast<ulong>(cc.value), null);
750 if (stage == Stage.bytes)
751 {
752 string s = ToString(cc.value);
753 for (char c : s)
754 {
755 currentSection->EmitByte(cast<byte>(c));
756 }
757 }
758 else if (stage == Stage.wydes)
759 {
760 uint value = cast<uint>(cc.value);
761 if (value > 65535u)
762 {
763 Error("invalid WYDE operand", cc.span);
764 }
765 byte b1 = cast<byte>(value);
766 value = value >> 8u;
767 byte b0 = cast<byte>(value);
768 value = value >> 8u;
769 currentSection->EmitByte(b1);
770 currentSection->EmitByte(b0);
771 }
772 else if (stage == Stage.tetras)
773 {
774 uint value = cast<uint>(cc.value);
775 byte b3 = cast<byte>(value);
776 value = value >> 8u;
777 byte b2 = cast<byte>(value);
778 value = value >> 8u;
779 byte b1 = cast<byte>(value);
780 value = value >> 8u;
781 byte b0 = cast<byte>(value);
782 value = value >> 8u;
783 currentSection->EmitByte(b3);
784 currentSection->EmitByte(b2);
785 currentSection->EmitByte(b1);
786 currentSection->EmitByte(b0);
787 }
788 else if (stage == Stage.octas)
789 {
790 uint value = cast<uint>(cc.value);
791 byte b3 = cast<byte>(value);
792 value = value >> 8u;
793 byte b2 = cast<byte>(value);
794 value = value >> 8u;
795 byte b1 = cast<byte>(value);
796 value = value >> 8u;
797 byte b0 = cast<byte>(value);
798 value = value >> 8u;
799 currentSection->EmitByte(0u);
800 currentSection->EmitByte(0u);
801 currentSection->EmitByte(0u);
802 currentSection->EmitByte(0u);
803 currentSection->EmitByte(b3);
804 currentSection->EmitByte(b2);
805 currentSection->EmitByte(b1);
806 currentSection->EmitByte(b0);
807 }
808 }
809 public override void Visit(At&)
810 {
811 currentValue = Value(cast<Value.Flag>(Value.Flag.pure | Value.Flag.address), currentSection->Address(), null);
812 }
813 public override void Visit(StringConstant& sc)
814 {
815 if (stage == Stage.bytes)
816 {
817 string s = ToUtf8(sc.value);
818 for (char c : s)
819 {
820 currentSection->EmitByte(cast<byte>(c));
821 }
822 }
823 else if (stage == Stage.funcInfo || stage == Stage.fileInfo)
824 {
825 str = ToUtf8(sc.value);
826 }
827 else
828 {
829 Error("string constant can appear only inside a BYTE instruction", sc.span);
830 }
831 }
832 public override void Visit(OperandList& operandList)
833 {
834 for (const UniquePtr<Node>& node : operandList.operands)
835 {
836 currentValue = Value();
837 node->Accept(*this);
838 }
839 }
840 public override void Visit(UnaryExpression& expr)
841 {
842 currentValue = Value();
843 expr.subject->Accept(*this);
844 if (currentValue.flags == Value.Flag.undefined)
845 {
846 Error("operand is undefined", expr.subject->span);
847 }
848 switch (expr.op)
849 {
850 case Operator.unaryPlus:
851 {
852 break;
853 }
854 case Operator.unaryMinus:
855 {
856 if (currentValue.GetFlag(Value.Flag.pure))
857 {
858 currentValue.value = cast<ulong>(-currentValue.value);
859 }
860 else
861 {
862 Error("unary minus needs pure operand", expr.span);
863 }
864 break;
865 }
866 case Operator.complement:
867 {
868 if (currentValue.GetFlag(Value.Flag.pure))
869 {
870 currentValue.value = ~currentValue.value;
871 }
872 else
873 {
874 Error("complement needs pure operand", expr.span);
875 }
876 break;
877 }
878 case Operator.register:
879 {
880 if (currentValue.value >= 0u && currentValue.value <= 255u && currentValue.GetFlag(Value.Flag.pure))
881 {
882 currentValue.SetRegister();
883 }
884 else
885 {
886 Error("invalid registerize operand", expr.span);
887 }
888 break;
889 }
890 case Operator.serial:
891 {
892 Error("serial not implemented", expr.span);
893 break;
894 }
895 }
896 }
897 public override void Visit(BinaryExpression& expr)
898 {
899 currentValue = Value();
900 expr.left->Accept(*this);
901 if (currentValue.flags == Value.Flag.undefined)
902 {
903 Error("left operand is undefined", expr.left->span);
904 }
905 Value leftValue = currentValue;
906 currentValue = Value();
907 expr.right->Accept(*this);
908 if (currentValue.flags == Value.Flag.undefined)
909 {
910 Error("right operand is undefined", expr.right->span);
911 }
912 Value rightValue = currentValue;
913 currentValue = Value();
914 switch (expr.op)
915 {
916 case Operator.multiply:
917 {
918 if (leftValue.GetFlag(Value.Flag.pure) && rightValue.GetFlag(Value.Flag.pure))
919 {
920 currentValue = Value(Value.Flag.pure, leftValue.value * rightValue.value, null);
921 if (leftValue.GetFlag(Value.Flag.address) || rightValue.GetFlag(Value.Flag.address))
922 {
923 currentValue.SetAddress();
924 }
925 }
926 else
927 {
928 Error("multiplication needs pure operands", expr.span);
929 }
930 break;
931 }
932 case Operator.divide:
933 {
934 if (leftValue.GetFlag(Value.Flag.pure) && rightValue.GetFlag(Value.Flag.pure))
935 {
936 currentValue = Value(Value.Flag.pure, leftValue.value / rightValue.value, null);
937 if (leftValue.GetFlag(Value.Flag.address) || rightValue.GetFlag(Value.Flag.address))
938 {
939 currentValue.SetAddress();
940 }
941 }
942 else
943 {
944 Error("division needs pure operands", expr.span);
945 }
946 break;
947 }
948 case Operator.modulus:
949 {
950 if (leftValue.GetFlag(Value.Flag.pure) && rightValue.GetFlag(Value.Flag.pure))
951 {
952 currentValue = Value(Value.Flag.pure, leftValue.value % rightValue.value, null);
953 if (leftValue.GetFlag(Value.Flag.address) || rightValue.GetFlag(Value.Flag.address))
954 {
955 currentValue.SetAddress();
956 }
957 }
958 else
959 {
960 Error("modulus needs pure operands", expr.span);
961 }
962 break;
963 }
964 case Operator.shiftLeft:
965 {
966 if (leftValue.GetFlag(Value.Flag.pure) && rightValue.GetFlag(Value.Flag.pure))
967 {
968 currentValue = Value(Value.Flag.pure, leftValue.value << rightValue.value, null);
969 if (leftValue.GetFlag(Value.Flag.address) || rightValue.GetFlag(Value.Flag.address))
970 {
971 currentValue.SetAddress();
972 }
973 }
974 else
975 {
976 Error("shift left needs pure operands", expr.span);
977 }
978 break;
979 }
980 case Operator.shiftRight:
981 {
982 if (leftValue.GetFlag(Value.Flag.pure) && rightValue.GetFlag(Value.Flag.pure))
983 {
984 currentValue = Value(Value.Flag.pure, leftValue.value >> rightValue.value, null);
985 if (leftValue.GetFlag(Value.Flag.address) || rightValue.GetFlag(Value.Flag.address))
986 {
987 currentValue.SetAddress();
988 }
989 }
990 else
991 {
992 Error("shift right needs pure operands", expr.span);
993 }
994 break;
995 }
996 case Operator.bitwiseAnd:
997 {
998 if (leftValue.GetFlag(Value.Flag.pure) && rightValue.GetFlag(Value.Flag.pure))
999 {
1000 currentValue = Value(Value.Flag.pure, leftValue.value & rightValue.value, null);
1001 if (leftValue.GetFlag(Value.Flag.address) || rightValue.GetFlag(Value.Flag.address))
1002 {
1003 currentValue.SetAddress();
1004 }
1005 }
1006 else
1007 {
1008 Error("bitwise AND needs pure operands", expr.span);
1009 }
1010 break;
1011 }
1012 case Operator.bitwiseOr:
1013 {
1014 if (leftValue.GetFlag(Value.Flag.pure) && rightValue.GetFlag(Value.Flag.pure))
1015 {
1016 currentValue = Value(Value.Flag.pure, leftValue.value | rightValue.value, null);
1017 if (leftValue.GetFlag(Value.Flag.address) || rightValue.GetFlag(Value.Flag.address))
1018 {
1019 currentValue.SetAddress();
1020 }
1021 }
1022 else
1023 {
1024 Error("bitwise OR needs pure operands", expr.span);
1025 }
1026 break;
1027 }
1028 case Operator.bitwiseXor:
1029 {
1030 if (leftValue.GetFlag(Value.Flag.pure) && rightValue.GetFlag(Value.Flag.pure))
1031 {
1032 currentValue = Value(Value.Flag.pure, leftValue.value ^ rightValue.value, null);
1033 if (leftValue.GetFlag(Value.Flag.address) || rightValue.GetFlag(Value.Flag.address))
1034 {
1035 currentValue.SetAddress();
1036 }
1037 }
1038 else
1039 {
1040 Error("bitwise XOR needs pure operands", expr.span);
1041 }
1042 break;
1043 }
1044 case Operator.add:
1045 {
1046 if (leftValue.GetFlag(Value.Flag.pure) && rightValue.GetFlag(Value.Flag.pure))
1047 {
1048 currentValue = Value(Value.Flag.pure, leftValue.value + rightValue.value, null);
1049 if (leftValue.GetFlag(Value.Flag.address) || rightValue.GetFlag(Value.Flag.address))
1050 {
1051 currentValue.SetAddress();
1052 }
1053 }
1054 else if (leftValue.flags == Value.Flag.register && rightValue.GetFlag(Value.Flag.pure))
1055 {
1056 currentValue = Value(Value.Flag.register, leftValue.value + rightValue.value, null);
1057 }
1058 else if (rightValue.flags == Value.Flag.register && leftValue.GetFlag(Value.Flag.pure))
1059 {
1060 currentValue = Value(Value.Flag.register, leftValue.value + rightValue.value, null);
1061 }
1062 else
1063 {
1064 Error("add operands must both be pure or either can be a register number", expr.span);
1065 }
1066 break;
1067 }
1068 case Operator.subtract:
1069 {
1070 if (leftValue.GetFlag(Value.Flag.pure) && rightValue.GetFlag(Value.Flag.pure))
1071 {
1072 currentValue = Value(Value.Flag.pure, leftValue.value - rightValue.value, null);
1073 if (leftValue.GetFlag(Value.Flag.address) || rightValue.GetFlag(Value.Flag.address))
1074 {
1075 currentValue.SetAddress();
1076 }
1077 }
1078 else if (leftValue.flags == Value.Flag.register)
1079 {
1080 if (rightValue.GetFlag(Value.Flag.pure))
1081 {
1082 currentValue = Value(Value.Flag.register, leftValue.value - rightValue.value, null);
1083 }
1084 else if (rightValue.flags == Value.Flag.register)
1085 {
1086 currentValue = Value(Value.Flag.pure, leftValue.value - rightValue.value, null);
1087 }
1088 else
1089 {
1090 Error("subtract operands must both be pure or register numbers, or left can be a register number and right can be pure", expr.span);
1091 }
1092 }
1093 else
1094 {
1095 Error("add operands must both be pure or either can be a register number", expr.span);
1096 }
1097 break;
1098 }
1099 default:
1100 {
1101 currentValue = Value();
1102 break;
1103 }
1104 }
1105 if (currentValue.flags == Value.Flag.undefined)
1106 {
1107 Error("invalid binary expression", expr.span);
1108 }
1109 else if (currentValue.flags == Value.Flag.register)
1110 {
1111 if (!(currentValue.value >= 0u && currentValue.value <= 255u))
1112 {
1113 Error("invalid binary expression register result", expr.span);
1114 }
1115 }
1116 }
1117 public override void Visit(ParenthesizedExpression& expr)
1118 {
1119 currentValue = Value();
1120 expr.subject->Accept(*this);
1121 if (currentValue.flags == Value.Flag.undefined)
1122 {
1123 Error("invalid parenthesized expression", expr.span);
1124 }
1125 }
1126 private void AlignAt()
1127 {
1128 ulong alignment = 1u;
1129 if (currentInstruction->opCode->value == WYDE)
1130 {
1131 alignment = 2u;
1132 currentAlignment = 2u;
1133 }
1134 else if (currentInstruction->opCode->value == TETRA || currentInstruction->opCode->value < 256)
1135 {
1136 alignment = 4u;
1137 currentAlignment = 4u;
1138 }
1139 else if (currentInstruction->opCode->value == OCTA || currentInstruction->opCode->value == STRUCT)
1140 {
1141 alignment = 8u;
1142 currentAlignment = 8u;
1143 }
1144 ulong at = currentSection->Address();
1145 ulong a = at & (alignment - 1u);
1146 if (a != 0u)
1147 {
1148 ulong offset = alignment - a;
1149 for (ulong i = 0u; i < offset; ++i;)
1150 {
1151 currentSection->EmitByte(0u);
1152 }
1153 }
1154 }
1155 public Stage stage;
1156 public Value currentValue;
1157 public ObjectFile objectFile;
1158 public Section* currentSection;
1159 public Symbol* currentSymbol;
1160 public Segment currentSegment;
1161 public string str;
1162 public bool inSpec;
1163 public Stack<bool> specStack;
1164 public Symbol* currentFunctionSymbol;
1165 public Symbol* currentStructureSymbol;
1166 private Instruction* currentInstruction;
1167 private int parentSymbolIndex;
1168 private int externalLinkCommandOffset;
1169 private byte currentAlignment;
1170 }
1171 }