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);
364
case DIRECTIVE_DATA_FLOAT:
365
data->setFloat(list);
372
CAssemblerCommand* parseDirectivePsx(Parser& parser, int flags)
375
Mips.SetLoadDelay(false,0);
376
Mips.SetVersion(MARCH_PSX);
377
return new ArchitectureCommand(L".psx",L"");
380
CAssemblerCommand* parseDirectivePs2(Parser& parser, int flags)
383
Mips.SetLoadDelay(false,0);
384
Mips.SetVersion(MARCH_PS2);
385
return new ArchitectureCommand(L".ps2",L"");
388
CAssemblerCommand* parseDirectivePsp(Parser& parser, int flags)
391
Mips.SetLoadDelay(false,0);
392
Mips.SetVersion(MARCH_PSP);
393
return new ArchitectureCommand(L".psp",L"");
396
CAssemblerCommand* parseDirectiveN64(Parser& parser, int flags)
399
Mips.SetLoadDelay(false, 0);
400
Mips.SetVersion(MARCH_N64);
401
return new ArchitectureCommand(L".n64", L"");
404
CAssemblerCommand* parseDirectiveArmArch(Parser& parser, int flags)
410
case DIRECTIVE_ARM_GBA:
411
Arm.SetThumbMode(true);
412
Arm.setVersion(AARCH_GBA);
413
return new ArchitectureCommand(L".gba\n.thumb", L".thumb");
414
case DIRECTIVE_ARM_NDS:
415
Arm.SetThumbMode(false);
416
Arm.setVersion(AARCH_NDS);
417
return new ArchitectureCommand(L".nds\n.arm", L".arm");
418
case DIRECTIVE_ARM_3DS:
419
Arm.SetThumbMode(false);
420
Arm.setVersion(AARCH_3DS);
421
return new ArchitectureCommand(L".3ds\n.arm", L".arm");
422
case DIRECTIVE_ARM_BIG:
423
Arm.SetThumbMode(false);
424
Arm.setVersion(AARCH_BIG);
425
return new ArchitectureCommand(L".arm.big\n.arm", L".arm");
426
case DIRECTIVE_ARM_LITTLE:
427
Arm.SetThumbMode(false);
428
Arm.setVersion(AARCH_LITTLE);
429
return new ArchitectureCommand(L".arm.little\n.arm", L".arm");
435
CAssemblerCommand* parseDirectiveArea(Parser& parser, int flags)
437
std::vector<Expression> parameters;
438
if (parser.parseExpressionList(parameters,1,2) == false)
441
CDirectiveArea* area = new CDirectiveArea(parameters[0]);
442
if (parameters.size() == 2)
443
area->setFillExpression(parameters[1]);
445
CAssemblerCommand* content = parser.parseCommandSequence(L'.', {L".endarea"});
448
area->setContent(content);
452
CAssemblerCommand* parseDirectiveErrorWarning(Parser& parser, int flags)
454
const Token &tok = parser.nextToken();
456
if (tok.type != TokenType::Identifier && tok.type != TokenType::String)
459
std::wstring stringValue = tok.getStringValue();
460
std::transform(stringValue.begin(),stringValue.end(),stringValue.begin(),::towlower);
462
if (stringValue == L"on")
464
Logger::setErrorOnWarning(true);
465
return new DummyCommand();
466
} else if (stringValue == L"off")
468
Logger::setErrorOnWarning(false);
469
return new DummyCommand();
475
CAssemblerCommand* parseDirectiveRelativeInclude(Parser& parser, int flags)
477
const Token &tok = parser.nextToken();
479
if (tok.type != TokenType::Identifier && tok.type != TokenType::String)
482
std::wstring stringValue = tok.getStringValue();
483
std::transform(stringValue.begin(),stringValue.end(),stringValue.begin(),::towlower);
485
if (stringValue == L"on")
487
Global.relativeInclude = true;
488
return new DummyCommand();
489
} else if (stringValue == L"off")
491
Global.relativeInclude = false;
492
return new DummyCommand();
498
CAssemblerCommand* parseDirectiveNocash(Parser& parser, int flags)
500
const Token &tok = parser.nextToken();
502
if (tok.type != TokenType::Identifier && tok.type != TokenType::String)
505
std::wstring stringValue = tok.getStringValue();
506
std::transform(stringValue.begin(),stringValue.end(),stringValue.begin(),::towlower);
508
if (stringValue == L"on")
510
Global.nocash = true;
511
return new DummyCommand();
512
} else if (stringValue == L"off")
514
Global.nocash = false;
515
return new DummyCommand();
521
CAssemblerCommand* parseDirectiveSym(Parser& parser, int flags)
523
const Token &tok = parser.nextToken();
525
if (tok.type != TokenType::Identifier && tok.type != TokenType::String)
528
std::wstring stringValue = tok.getStringValue();
529
std::transform(stringValue.begin(),stringValue.end(),stringValue.begin(),::towlower);
531
if (stringValue == L"on")
532
return new CDirectiveSym(true);
533
else if (stringValue == L"off")
534
return new CDirectiveSym(false);
539
CAssemblerCommand* parseDirectiveDefineLabel(Parser& parser, int flags)
541
const Token& tok = parser.nextToken();
542
if (tok.type != TokenType::Identifier)
545
if (parser.nextToken().type != TokenType::Comma)
548
Expression value = parser.parseExpression();
549
if (value.isLoaded() == false)
552
const std::wstring stringValue = tok.getStringValue();
553
if (Global.symbolTable.isValidSymbolName(stringValue) == false)
555
parser.printError(tok,L"Invalid label name \"%s\"",stringValue);
559
return new CAssemblerLabel(stringValue,tok.getOriginalText(),value);
562
CAssemblerCommand* parseDirectiveFunction(Parser& parser, int flags)
564
const Token& tok = parser.nextToken();
565
if (tok.type != TokenType::Identifier)
568
if (parser.peekToken().type == TokenType::Comma)
571
CDirectiveFunction* func = new CDirectiveFunction(tok.getStringValue(),tok.getOriginalText());
572
CAssemblerCommand* seq = parser.parseCommandSequence(L'.', {L".endfunc",L".endfunction",L".func",L".function"});
574
const std::wstring stringValue = parser.peekToken().getStringValue();
575
if (stringValue == L".endfunc" ||
576
stringValue == L".endfunction")
581
func->setContent(seq);
585
CAssemblerCommand* parseDirectiveMessage(Parser& parser, int flags)
587
Expression exp = parser.parseExpression();
591
case DIRECTIVE_MSG_WARNING:
592
return new CDirectiveMessage(CDirectiveMessage::Type::Warning,exp);
593
case DIRECTIVE_MSG_ERROR:
594
return new CDirectiveMessage(CDirectiveMessage::Type::Error,exp);
595
case DIRECTIVE_MSG_NOTICE:
596
return new CDirectiveMessage(CDirectiveMessage::Type::Notice,exp);
602
CAssemblerCommand* parseDirectiveInclude(Parser& parser, int flags)
604
const Token& start = parser.peekToken();
606
std::vector<Expression> parameters;
607
if (parser.parseExpressionList(parameters,1,2) == false)
610
std::wstring fileName;
611
if (parameters[0].evaluateString(fileName,true) == false)
614
fileName = getFullPathName(fileName);
616
TextFile::Encoding encoding = TextFile::GUESS;
617
if (parameters.size() == 2)
619
std::wstring encodingName;
620
if (parameters[1].evaluateString(encodingName,true) == false
621
&& parameters[1].evaluateIdentifier(encodingName) == false)
624
encoding = getEncodingFromString(encodingName);
627
// don't include the file if it's inside a false block
628
if (parser.isInsideTrueBlock() == false)
629
return new DummyCommand();
631
if (fileExists(fileName) == false)
633
parser.printError(start,L"Included file \"%s\" does not exist",fileName);
638
if (f.open(fileName,TextFile::Read,encoding) == false)
640
parser.printError(start,L"Could not open included file \"%s\"",fileName);
644
return parser.parseFile(f);
647
const DirectiveMap directives = {
648
{ L".open", { &parseDirectiveOpen, DIRECTIVE_NOTINMEMORY } },
649
{ L".openfile", { &parseDirectiveOpen, DIRECTIVE_NOTINMEMORY } },
650
{ L".create", { &parseDirectiveCreate, DIRECTIVE_NOTINMEMORY } },
651
{ L".createfile", { &parseDirectiveCreate, DIRECTIVE_NOTINMEMORY } },
652
{ L".close", { &parseDirectiveClose, DIRECTIVE_NOTINMEMORY } },
653
{ L".closefile", { &parseDirectiveClose, DIRECTIVE_NOTINMEMORY } },
654
{ L".incbin", { &parseDirectiveIncbin, 0 } },
655
{ L".import", { &parseDirectiveIncbin, 0 } },
656
{ L".org", { &parseDirectivePosition, DIRECTIVE_POS_VIRTUAL } },
657
{ L"org", { &parseDirectivePosition, DIRECTIVE_POS_VIRTUAL } },
658
{ L".orga", { &parseDirectivePosition, DIRECTIVE_POS_PHYSICAL } },
659
{ L"orga", { &parseDirectivePosition, DIRECTIVE_POS_PHYSICAL } },
660
{ L".align", { &parseDirectiveAlignFill, DIRECTIVE_FILE_ALIGN } },
661
{ L".fill", { &parseDirectiveAlignFill, DIRECTIVE_FILE_FILL } },
662
{ L"defs", { &parseDirectiveAlignFill, DIRECTIVE_FILE_FILL } },
663
{ L".headersize", { &parseDirectiveHeaderSize, 0 } },
665
{ L".if", { &parseDirectiveConditional, DIRECTIVE_COND_IF } },
666
{ L".ifdef", { &parseDirectiveConditional, DIRECTIVE_COND_IFDEF } },
667
{ L".ifndef", { &parseDirectiveConditional, DIRECTIVE_COND_IFNDEF } },
669
{ L".loadtable", { &parseDirectiveTable, 0 } },
670
{ L".table", { &parseDirectiveTable, 0 } },
671
{ L".byte", { &parseDirectiveData, DIRECTIVE_DATA_8 } },
672
{ L".halfword", { &parseDirectiveData, DIRECTIVE_DATA_16 } },
673
{ L".word", { &parseDirectiveData, DIRECTIVE_DATA_32 } },
674
{ L".db", { &parseDirectiveData, DIRECTIVE_DATA_8 } },
675
{ L".dh", { &parseDirectiveData, DIRECTIVE_DATA_16|DIRECTIVE_NOCASHOFF } },
676
{ L".dw", { &parseDirectiveData, DIRECTIVE_DATA_32|DIRECTIVE_NOCASHOFF } },
677
{ L".dw", { &parseDirectiveData, DIRECTIVE_DATA_16|DIRECTIVE_NOCASHON } },
678
{ L".dd", { &parseDirectiveData, DIRECTIVE_DATA_32|DIRECTIVE_NOCASHON } },
679
{ L".dcb", { &parseDirectiveData, DIRECTIVE_DATA_8 } },
680
{ L".dcw", { &parseDirectiveData, DIRECTIVE_DATA_16 } },
681
{ L".dcd", { &parseDirectiveData, DIRECTIVE_DATA_32 } },
682
{ L"db", { &parseDirectiveData, DIRECTIVE_DATA_8 } },
683
{ L"dh", { &parseDirectiveData, DIRECTIVE_DATA_16|DIRECTIVE_NOCASHOFF } },
684
{ L"dw", { &parseDirectiveData, DIRECTIVE_DATA_32|DIRECTIVE_NOCASHOFF } },
685
{ L"dw", { &parseDirectiveData, DIRECTIVE_DATA_16|DIRECTIVE_NOCASHON } },
686
{ L"dd", { &parseDirectiveData, DIRECTIVE_DATA_32|DIRECTIVE_NOCASHON } },
687
{ L"dcb", { &parseDirectiveData, DIRECTIVE_DATA_8 } },
688
{ L"dcw", { &parseDirectiveData, DIRECTIVE_DATA_16 } },
689
{ L"dcd", { &parseDirectiveData, DIRECTIVE_DATA_32 } },
690
{ L".ascii", { &parseDirectiveData, DIRECTIVE_DATA_ASCII } },
691
{ L".string", { &parseDirectiveData, DIRECTIVE_DATA_CUSTOM|DIRECTIVE_DATA_TERMINATION } },
692
{ L".str", { &parseDirectiveData, DIRECTIVE_DATA_CUSTOM|DIRECTIVE_DATA_TERMINATION } },
693
{ L".stringn", { &parseDirectiveData, DIRECTIVE_DATA_CUSTOM } },
694
{ L".strn", { &parseDirectiveData, DIRECTIVE_DATA_CUSTOM } },
695
{ L".sjis", { &parseDirectiveData, DIRECTIVE_DATA_SJIS|DIRECTIVE_DATA_TERMINATION } },
696
{ L".sjisn", { &parseDirectiveData, DIRECTIVE_DATA_SJIS } },
697
{ L".float", { &parseDirectiveData, DIRECTIVE_DATA_FLOAT } },
699
{ L".psx", { &parseDirectivePsx, 0 } },
700
{ L".ps2", { &parseDirectivePs2, 0 } },
701
{ L".psp", { &parseDirectivePsp, 0 } },
702
{ L".n64", { &parseDirectiveN64, 0 } },
704
{ L".gba", { &parseDirectiveArmArch, DIRECTIVE_ARM_GBA } },
705
{ L".nds", { &parseDirectiveArmArch, DIRECTIVE_ARM_NDS } },
706
{ L".3ds", { &parseDirectiveArmArch, DIRECTIVE_ARM_3DS } },
707
{ L".arm.big", { &parseDirectiveArmArch, DIRECTIVE_ARM_BIG } },
708
{ L".arm.little", { &parseDirectiveArmArch, DIRECTIVE_ARM_LITTLE } },
710
{ L".area", { &parseDirectiveArea, 0 } },
712
{ L".importobj", { &parseDirectiveObjImport, 0 } },
713
{ L".importlib", { &parseDirectiveObjImport, 0 } },
715
{ L".erroronwarning", { &parseDirectiveErrorWarning, 0 } },
716
{ L".relativeinclude", { &parseDirectiveRelativeInclude, 0 } },
717
{ L".nocash", { &parseDirectiveNocash, 0 } },
718
{ L".sym", { &parseDirectiveSym, 0 } },
720
{ L".definelabel", { &parseDirectiveDefineLabel, 0 } },
721
{ L".function", { &parseDirectiveFunction, 0 } },
722
{ L".func", { &parseDirectiveFunction, 0 } },
724
{ L".warning", { &parseDirectiveMessage, DIRECTIVE_MSG_WARNING } },
725
{ L".error", { &parseDirectiveMessage, DIRECTIVE_MSG_ERROR } },
726
{ L".notice", { &parseDirectiveMessage, DIRECTIVE_MSG_NOTICE } },
728
{ L".include", { &parseDirectiveInclude, 0 } },