2
#include "DirectivesParser.h"
3
#include "Core/Common.h"
4
#include "Commands/CDirectiveFile.h"
5
#include "Commands/CDirectiveData.h"
6
#include "Commands/CDirectiveConditional.h"
7
#include "Commands/CDirectiveMessage.h"
8
#include "Commands/CDirectiveArea.h"
9
#include "Commands/CAssemblerLabel.h"
10
#include "Commands/CommandSequence.h"
11
#include "Archs/MIPS/Mips.h"
12
#include "Archs/ARM/Arm.h"
13
#include "Core/Expression.h"
14
#include "Util/Util.h"
16
#include "Tokenizer.h"
17
#include "ExpressionParser.h"
18
#include <initializer_list>
22
CAssemblerCommand* parseDirectiveOpen(Parser& parser, int flags)
24
std::vector<Expression> list;
25
if (parser.parseExpressionList(list,2,3) == false)
29
std::wstring inputName, outputName;
31
if (list[0].evaluateString(inputName,false) == false)
34
if (list.back().evaluateInteger(memoryAddress) == false)
39
if (list[1].evaluateString(outputName,false) == false)
42
CDirectiveFile* file = new CDirectiveFile();
43
file->initCopy(inputName,outputName,memoryAddress);
46
CDirectiveFile* file = new CDirectiveFile();
47
file->initOpen(inputName,memoryAddress);
52
CAssemblerCommand* parseDirectiveCreate(Parser& parser, int flags)
54
std::vector<Expression> list;
55
if (parser.parseExpressionList(list,2,2) == false)
59
std::wstring inputName, outputName;
61
if (list[0].evaluateString(inputName,false) == false)
64
if (list.back().evaluateInteger(memoryAddress) == false)
67
CDirectiveFile* file = new CDirectiveFile();
68
file->initCreate(inputName,memoryAddress);
72
CAssemblerCommand* parseDirectiveClose(Parser& parser, int flags)
74
CDirectiveFile* file = new CDirectiveFile();
79
CAssemblerCommand* parseDirectiveIncbin(Parser& parser, int flags)
81
std::vector<Expression> list;
82
if (parser.parseExpressionList(list,1,3) == false)
85
std::wstring fileName;
86
if (list[0].evaluateString(fileName,false) == false)
89
CDirectiveIncbin* incbin = new CDirectiveIncbin(fileName);
91
incbin->setStart(list[1]);
94
incbin->setSize(list[2]);
99
CAssemblerCommand* parseDirectivePosition(Parser& parser, int flags)
101
const Token& start = parser.peekToken();
103
std::vector<Expression> list;
104
if (parser.parseExpressionList(list,1,1) == false)
108
if (list[0].evaluateInteger(position) == false)
110
parser.printError(start,L"Invalid ram address");
114
switch (flags & DIRECTIVE_USERMASK)
116
case DIRECTIVE_POS_PHYSICAL:
117
return new CDirectivePosition(CDirectivePosition::Physical,position);
118
case DIRECTIVE_POS_VIRTUAL:
119
return new CDirectivePosition(CDirectivePosition::Virtual,position);
125
CAssemblerCommand* parseDirectiveAlignFill(Parser& parser, int flags)
127
std::vector<Expression> list;
128
if (parser.parseExpressionList(list,1,2) == false)
131
CDirectiveAlignFill::Mode mode;
132
switch (flags & DIRECTIVE_USERMASK)
134
case DIRECTIVE_FILE_ALIGN:
135
mode = CDirectiveAlignFill::Align;
137
case DIRECTIVE_FILE_FILL:
138
mode = CDirectiveAlignFill::Fill;
144
if (list.size() == 2)
145
return new CDirectiveAlignFill(list[0],list[1],mode);
147
return new CDirectiveAlignFill(list[0],mode);
150
CAssemblerCommand* parseDirectiveHeaderSize(Parser& parser, int flags)
152
const Token& start = parser.peekToken();
154
std::vector<Expression> list;
155
if (parser.parseExpressionList(list,1,1) == false)
159
if (list[0].evaluateInteger(size) == false)
161
parser.printError(start,L"Invalid header size");
165
return new CDirectiveHeaderSize(size);
168
CAssemblerCommand* parseDirectiveObjImport(Parser& parser, int flags)
170
std::vector<Expression> list;
171
if (parser.parseExpressionList(list,1,2) == false)
174
std::wstring fileName;
175
if (list[0].evaluateString(fileName,true) == false)
178
if (list.size() == 2)
180
std::wstring ctorName;
181
if (list[1].evaluateIdentifier(ctorName) == false)
184
return new DirectiveObjImport(fileName,ctorName);
187
return new DirectiveObjImport(fileName);
190
CAssemblerCommand* parseDirectiveConditional(Parser& parser, int flags)
196
const Token& start = parser.peekToken();
197
ConditionalResult condResult = ConditionalResult::Unknown;
200
case DIRECTIVE_COND_IF:
201
type = ConditionType::IF;
202
exp = parser.parseExpression();
203
if (exp.isLoaded() == false)
205
parser.printError(start,L"Invalid condition");
206
return new DummyCommand();
209
if (exp.isConstExpression())
211
ExpressionValue result = exp.evaluate();
213
condResult = result.intValue != 0 ? ConditionalResult::True : ConditionalResult::False;
216
case DIRECTIVE_COND_IFDEF:
217
type = ConditionType::IFDEF;
218
if (parser.parseIdentifier(name) == false)
221
case DIRECTIVE_COND_IFNDEF:
222
type = ConditionType::IFNDEF;
223
if (parser.parseIdentifier(name) == false)
228
parser.pushConditionalResult(condResult);
229
CAssemblerCommand* ifBlock = parser.parseCommandSequence(L'.', {L".else", L".elseif", L".elseifdef", L".elseifndef", L".endif"});
230
parser.popConditionalResult();
232
// update the file info so that else commands get the right line number
233
parser.updateFileInfo();
235
CAssemblerCommand* elseBlock = nullptr;
236
const Token &next = parser.nextToken();
237
const std::wstring stringValue = next.getStringValue();
239
if (stringValue == L".else")
241
ConditionalResult elseResult = condResult;
244
case ConditionalResult::True:
245
elseResult = ConditionalResult::False;
247
case ConditionalResult::False:
248
elseResult = ConditionalResult::True;
252
parser.pushConditionalResult(elseResult);
253
elseBlock = parser.parseCommandSequence(L'.', {L".endif"});
254
parser.popConditionalResult();
256
parser.eatToken(); // eat .endif
257
} else if (stringValue == L".elseif")
259
elseBlock = parseDirectiveConditional(parser,DIRECTIVE_COND_IF);
260
} else if (stringValue == L".elseifdef")
262
elseBlock = parseDirectiveConditional(parser,DIRECTIVE_COND_IFDEF);
263
} else if (stringValue == L".elseifndef")
265
elseBlock = parseDirectiveConditional(parser,DIRECTIVE_COND_IFNDEF);
266
} else if (stringValue != L".endif")
271
// for true or false blocks, there's no need to create a conditional command
272
if (condResult == ConditionalResult::True)
278
if (condResult == ConditionalResult::False)
281
if (elseBlock != nullptr)
284
return new DummyCommand();
287
CDirectiveConditional* cond;
289
cond = new CDirectiveConditional(type,exp);
290
else if (name.size() != 0)
291
cond = new CDirectiveConditional(type,name);
293
cond = new CDirectiveConditional(type);
295
cond->setContent(ifBlock,elseBlock);
299
CAssemblerCommand* parseDirectiveTable(Parser& parser, int flags)
301
const Token& start = parser.peekToken();
303
std::vector<Expression> list;
304
if (parser.parseExpressionList(list,1,2) == false)
307
std::wstring fileName;
308
if (list[0].evaluateString(fileName,true) == false)
310
parser.printError(start,L"Invalid file name");
314
TextFile::Encoding encoding = TextFile::GUESS;
315
if (list.size() == 2)
317
std::wstring encodingName;
318
if (list[1].evaluateString(encodingName,true) == false)
320
parser.printError(start,L"Invalid encoding name");
324
encoding = getEncodingFromString(encodingName);
327
return new TableCommand(fileName,encoding);
330
CAssemblerCommand* parseDirectiveData(Parser& parser, int flags)
332
bool terminate = false;
333
if (flags & DIRECTIVE_DATA_TERMINATION)
336
flags &= ~DIRECTIVE_DATA_TERMINATION;
339
std::vector<Expression> list;
340
if (parser.parseExpressionList(list,1,-1) == false)
343
CDirectiveData* data = new CDirectiveData();
344
switch (flags & DIRECTIVE_USERMASK)
346
case DIRECTIVE_DATA_8:
347
data->setNormal(list,1,false);
349
case DIRECTIVE_DATA_16:
350
data->setNormal(list,2,false);
352
case DIRECTIVE_DATA_32:
353
data->setNormal(list,4,false);
355
case DIRECTIVE_DATA_ASCII:
356
data->setNormal(list,1,true);
358
case DIRECTIVE_DATA_SJIS:
359
data->setSjis(list,terminate);
361
case DIRECTIVE_DATA_CUSTOM:
362
data->setCustom(list,terminate);
369
CAssemblerCommand* parseDirectivePsx(Parser& parser, int flags)
372
Mips.SetLoadDelay(false,0);
373
Mips.SetVersion(MARCH_PSX);
374
return new ArchitectureCommand(L".psx",L"");
377
CAssemblerCommand* parseDirectivePs2(Parser& parser, int flags)
380
Mips.SetLoadDelay(false,0);
381
Mips.SetVersion(MARCH_PS2);
382
return new ArchitectureCommand(L".ps2",L"");
385
CAssemblerCommand* parseDirectivePsp(Parser& parser, int flags)
388
Mips.SetLoadDelay(false,0);
389
Mips.SetVersion(MARCH_PSP);
390
return new ArchitectureCommand(L".psp",L"");
393
CAssemblerCommand* parseDirectiveN64(Parser& parser, int flags)
396
Mips.SetLoadDelay(false, 0);
397
Mips.SetVersion(MARCH_N64);
398
return new ArchitectureCommand(L".n64", L"");
401
CAssemblerCommand* parseDirectiveArmArch(Parser& parser, int flags)
407
case DIRECTIVE_ARM_GBA:
408
Arm.SetThumbMode(true);
409
Arm.setVersion(AARCH_GBA);
410
return new ArchitectureCommand(L".gba\n.thumb", L".thumb");
411
case DIRECTIVE_ARM_NDS:
412
Arm.SetThumbMode(false);
413
Arm.setVersion(AARCH_NDS);
414
return new ArchitectureCommand(L".nds\n.arm", L".arm");
415
case DIRECTIVE_ARM_3DS:
416
Arm.SetThumbMode(false);
417
Arm.setVersion(AARCH_3DS);
418
return new ArchitectureCommand(L".3ds\n.arm", L".arm");
419
case DIRECTIVE_ARM_BIG:
420
Arm.SetThumbMode(false);
421
Arm.setVersion(AARCH_BIG);
422
return new ArchitectureCommand(L".arm.big\n.arm", L".arm");
423
case DIRECTIVE_ARM_LITTLE:
424
Arm.SetThumbMode(false);
425
Arm.setVersion(AARCH_LITTLE);
426
return new ArchitectureCommand(L".arm.little\n.arm", L".arm");
432
CAssemblerCommand* parseDirectiveArea(Parser& parser, int flags)
434
std::vector<Expression> parameters;
435
if (parser.parseExpressionList(parameters,1,2) == false)
438
CDirectiveArea* area = new CDirectiveArea(parameters[0]);
439
if (parameters.size() == 2)
440
area->setFillExpression(parameters[1]);
442
CAssemblerCommand* content = parser.parseCommandSequence(L'.', {L".endarea"});
445
area->setContent(content);
449
CAssemblerCommand* parseDirectiveErrorWarning(Parser& parser, int flags)
451
const Token &tok = parser.nextToken();
453
if (tok.type != TokenType::Identifier && tok.type != TokenType::String)
456
std::wstring stringValue = tok.getStringValue();
457
std::transform(stringValue.begin(),stringValue.end(),stringValue.begin(),::towlower);
459
if (stringValue == L"on")
461
Logger::setErrorOnWarning(true);
462
return new DummyCommand();
463
} else if (stringValue == L"off")
465
Logger::setErrorOnWarning(false);
466
return new DummyCommand();
472
CAssemblerCommand* parseDirectiveRelativeInclude(Parser& parser, int flags)
474
const Token &tok = parser.nextToken();
476
if (tok.type != TokenType::Identifier && tok.type != TokenType::String)
479
std::wstring stringValue = tok.getStringValue();
480
std::transform(stringValue.begin(),stringValue.end(),stringValue.begin(),::towlower);
482
if (stringValue == L"on")
484
Global.relativeInclude = true;
485
return new DummyCommand();
486
} else if (stringValue == L"off")
488
Global.relativeInclude = false;
489
return new DummyCommand();
495
CAssemblerCommand* parseDirectiveNocash(Parser& parser, int flags)
497
const Token &tok = parser.nextToken();
499
if (tok.type != TokenType::Identifier && tok.type != TokenType::String)
502
std::wstring stringValue = tok.getStringValue();
503
std::transform(stringValue.begin(),stringValue.end(),stringValue.begin(),::towlower);
505
if (stringValue == L"on")
507
Global.nocash = true;
508
return new DummyCommand();
509
} else if (stringValue == L"off")
511
Global.nocash = false;
512
return new DummyCommand();
518
CAssemblerCommand* parseDirectiveSym(Parser& parser, int flags)
520
const Token &tok = parser.nextToken();
522
if (tok.type != TokenType::Identifier && tok.type != TokenType::String)
525
std::wstring stringValue = tok.getStringValue();
526
std::transform(stringValue.begin(),stringValue.end(),stringValue.begin(),::towlower);
528
if (stringValue == L"on")
529
return new CDirectiveSym(true);
530
else if (stringValue == L"off")
531
return new CDirectiveSym(false);
536
CAssemblerCommand* parseDirectiveDefineLabel(Parser& parser, int flags)
538
const Token& tok = parser.nextToken();
539
if (tok.type != TokenType::Identifier)
542
if (parser.nextToken().type != TokenType::Comma)
545
Expression value = parser.parseExpression();
546
if (value.isLoaded() == false)
549
const std::wstring stringValue = tok.getStringValue();
550
if (Global.symbolTable.isValidSymbolName(stringValue) == false)
552
parser.printError(tok,L"Invalid label name \"%s\"",stringValue);
556
return new CAssemblerLabel(stringValue,value);
559
CAssemblerCommand* parseDirectiveFunction(Parser& parser, int flags)
561
std::vector<Expression> parameters;
562
if (parser.parseExpressionList(parameters,1,1) == false)
566
if (parameters[0].evaluateIdentifier(name) == false)
569
CDirectiveFunction* func = new CDirectiveFunction(name);
570
CAssemblerCommand* seq = parser.parseCommandSequence(L'.', {L".endfunc",L".endfunction",L".func",L".function"});
572
const std::wstring stringValue = parser.peekToken().getStringValue();
573
if (stringValue == L".endfunc" ||
574
stringValue == L".endfunction")
579
func->setContent(seq);
583
CAssemblerCommand* parseDirectiveMessage(Parser& parser, int flags)
585
Expression exp = parser.parseExpression();
589
case DIRECTIVE_MSG_WARNING:
590
return new CDirectiveMessage(CDirectiveMessage::Type::Warning,exp);
591
case DIRECTIVE_MSG_ERROR:
592
return new CDirectiveMessage(CDirectiveMessage::Type::Error,exp);
593
case DIRECTIVE_MSG_NOTICE:
594
return new CDirectiveMessage(CDirectiveMessage::Type::Notice,exp);
600
CAssemblerCommand* parseDirectiveInclude(Parser& parser, int flags)
602
const Token& start = parser.peekToken();
604
std::vector<Expression> parameters;
605
if (parser.parseExpressionList(parameters,1,2) == false)
608
std::wstring fileName;
609
if (parameters[0].evaluateString(fileName,true) == false)
612
fileName = getFullPathName(fileName);
614
TextFile::Encoding encoding = TextFile::GUESS;
615
if (parameters.size() == 2)
617
std::wstring encodingName;
618
if (parameters[1].evaluateString(encodingName,true) == false
619
&& parameters[1].evaluateIdentifier(encodingName) == false)
622
encoding = getEncodingFromString(encodingName);
625
// don't include the file if it's inside a false block
626
if (parser.isInsideTrueBlock() == false)
627
return new DummyCommand();
629
if (fileExists(fileName) == false)
631
parser.printError(start,L"Included file \"%s\" does not exist",fileName);
636
if (f.open(fileName,TextFile::Read,encoding) == false)
638
parser.printError(start,L"Could not open included file \"%s\"",fileName);
642
return parser.parseFile(f);
645
const DirectiveMap directives = {
646
{ L".open", { &parseDirectiveOpen, DIRECTIVE_NOTINMEMORY } },
647
{ L".openfile", { &parseDirectiveOpen, DIRECTIVE_NOTINMEMORY } },
648
{ L".create", { &parseDirectiveCreate, DIRECTIVE_NOTINMEMORY } },
649
{ L".createfile", { &parseDirectiveCreate, DIRECTIVE_NOTINMEMORY } },
650
{ L".close", { &parseDirectiveClose, DIRECTIVE_NOTINMEMORY } },
651
{ L".closefile", { &parseDirectiveClose, DIRECTIVE_NOTINMEMORY } },
652
{ L".incbin", { &parseDirectiveIncbin, 0 } },
653
{ L".import", { &parseDirectiveIncbin, 0 } },
654
{ L".org", { &parseDirectivePosition, DIRECTIVE_POS_VIRTUAL } },
655
{ L"org", { &parseDirectivePosition, DIRECTIVE_POS_VIRTUAL } },
656
{ L".orga", { &parseDirectivePosition, DIRECTIVE_POS_PHYSICAL } },
657
{ L"orga", { &parseDirectivePosition, DIRECTIVE_POS_PHYSICAL } },
658
{ L".align", { &parseDirectiveAlignFill, DIRECTIVE_FILE_ALIGN } },
659
{ L".fill", { &parseDirectiveAlignFill, DIRECTIVE_FILE_FILL } },
660
{ L"defs", { &parseDirectiveAlignFill, DIRECTIVE_FILE_FILL } },
661
{ L".headersize", { &parseDirectiveHeaderSize, 0 } },
663
{ L".if", { &parseDirectiveConditional, DIRECTIVE_COND_IF } },
664
{ L".ifdef", { &parseDirectiveConditional, DIRECTIVE_COND_IFDEF } },
665
{ L".ifndef", { &parseDirectiveConditional, DIRECTIVE_COND_IFNDEF } },
667
{ L".loadtable", { &parseDirectiveTable, 0 } },
668
{ L".table", { &parseDirectiveTable, 0 } },
669
{ L".byte", { &parseDirectiveData, DIRECTIVE_DATA_8 } },
670
{ L".halfword", { &parseDirectiveData, DIRECTIVE_DATA_16 } },
671
{ L".word", { &parseDirectiveData, DIRECTIVE_DATA_32 } },
672
{ L".db", { &parseDirectiveData, DIRECTIVE_DATA_8 } },
673
{ L".dh", { &parseDirectiveData, DIRECTIVE_DATA_16|DIRECTIVE_NOCASHOFF } },
674
{ L".dw", { &parseDirectiveData, DIRECTIVE_DATA_32|DIRECTIVE_NOCASHOFF } },
675
{ L".dw", { &parseDirectiveData, DIRECTIVE_DATA_16|DIRECTIVE_NOCASHON } },
676
{ L".dd", { &parseDirectiveData, DIRECTIVE_DATA_32|DIRECTIVE_NOCASHON } },
677
{ L".dcb", { &parseDirectiveData, DIRECTIVE_DATA_8 } },
678
{ L".dcw", { &parseDirectiveData, DIRECTIVE_DATA_16 } },
679
{ L".dcd", { &parseDirectiveData, DIRECTIVE_DATA_32 } },
680
{ L"db", { &parseDirectiveData, DIRECTIVE_DATA_8 } },
681
{ L"dh", { &parseDirectiveData, DIRECTIVE_DATA_16|DIRECTIVE_NOCASHOFF } },
682
{ L"dw", { &parseDirectiveData, DIRECTIVE_DATA_32|DIRECTIVE_NOCASHOFF } },
683
{ L"dw", { &parseDirectiveData, DIRECTIVE_DATA_16|DIRECTIVE_NOCASHON } },
684
{ L"dd", { &parseDirectiveData, DIRECTIVE_DATA_32|DIRECTIVE_NOCASHON } },
685
{ L"dcb", { &parseDirectiveData, DIRECTIVE_DATA_8 } },
686
{ L"dcw", { &parseDirectiveData, DIRECTIVE_DATA_16 } },
687
{ L"dcd", { &parseDirectiveData, DIRECTIVE_DATA_32 } },
688
{ L".ascii", { &parseDirectiveData, DIRECTIVE_DATA_ASCII } },
689
{ L".string", { &parseDirectiveData, DIRECTIVE_DATA_CUSTOM|DIRECTIVE_DATA_TERMINATION } },
690
{ L".str", { &parseDirectiveData, DIRECTIVE_DATA_CUSTOM|DIRECTIVE_DATA_TERMINATION } },
691
{ L".stringn", { &parseDirectiveData, DIRECTIVE_DATA_CUSTOM } },
692
{ L".strn", { &parseDirectiveData, DIRECTIVE_DATA_CUSTOM } },
693
{ L".sjis", { &parseDirectiveData, DIRECTIVE_DATA_SJIS|DIRECTIVE_DATA_TERMINATION } },
694
{ L".sjisn", { &parseDirectiveData, DIRECTIVE_DATA_SJIS } },
696
{ L".psx", { &parseDirectivePsx, 0 } },
697
{ L".ps2", { &parseDirectivePs2, 0 } },
698
{ L".psp", { &parseDirectivePsp, 0 } },
699
{ L".n64", { &parseDirectiveN64, 0 } },
701
{ L".gba", { &parseDirectiveArmArch, DIRECTIVE_ARM_GBA } },
702
{ L".nds", { &parseDirectiveArmArch, DIRECTIVE_ARM_NDS } },
703
{ L".3ds", { &parseDirectiveArmArch, DIRECTIVE_ARM_3DS } },
704
{ L".arm.big", { &parseDirectiveArmArch, DIRECTIVE_ARM_BIG } },
705
{ L".arm.little", { &parseDirectiveArmArch, DIRECTIVE_ARM_LITTLE } },
707
{ L".area", { &parseDirectiveArea, 0 } },
709
{ L".importobj", { &parseDirectiveObjImport, 0 } },
710
{ L".importlib", { &parseDirectiveObjImport, 0 } },
712
{ L".erroronwarning", { &parseDirectiveErrorWarning, 0 } },
713
{ L".relativeinclude", { &parseDirectiveRelativeInclude, 0 } },
714
{ L".nocash", { &parseDirectiveNocash, 0 } },
715
{ L".sym", { &parseDirectiveSym, 0 } },
717
{ L".definelabel", { &parseDirectiveDefineLabel, 0 } },
718
{ L".function", { &parseDirectiveFunction, 0 } },
719
{ L".func", { &parseDirectiveFunction, 0 } },
721
{ L".warning", { &parseDirectiveMessage, DIRECTIVE_MSG_WARNING } },
722
{ L".error", { &parseDirectiveMessage, DIRECTIVE_MSG_ERROR } },
723
{ L".notice", { &parseDirectiveMessage, DIRECTIVE_MSG_NOTICE } },
725
{ L".include", { &parseDirectiveInclude, 0 } },