1 #include "stdafx.h"
2 #include "ArmParser.h"
3 #include "Parser/Parser.h"
4 #include "Parser/ExpressionParser.h"
5 #include "Parser/DirectivesParser.h"
6 #include "Util/Util.h"
7 #include "Core/Common.h"
8 #include "Commands/CDirectiveFile.h"
9
10 #define CHECK(exp) if (!(exp)) return false;
11
12 const ArmRegisterDescriptor armRegisters[] = {
13 { L"r0", 0 }, { L"r1", 1 }, { L"r2", 2 }, { L"r3", 3 },
14 { L"r4", 4 }, { L"r5", 5 }, { L"r6", 6 }, { L"r7", 7 },
15 { L"r8", 8 }, { L"r9", 9 }, { L"r10", 10 }, { L"r11", 11 },
16 { L"r12", 12 }, { L"r13", 13 }, { L"sp", 13 }, { L"r14", 14 },
17 { L"lr", 14 }, { L"r15", 15 }, { L"pc", 15 },
18 };
19
20 const ArmRegisterDescriptor armCopRegisters[] = {
21 { L"c0", 0 }, { L"c1", 1 }, { L"c2", 2 }, { L"c3", 3 },
22 { L"c4", 4 }, { L"c5", 5 }, { L"c6", 6 }, { L"c7", 7 },
23 { L"c8", 8 }, { L"c9", 9 }, { L"c10", 10 }, { L"c11", 11 },
24 { L"c12", 12 }, { L"c13", 13 }, { L"c14", 14 }, { L"c15", 15 },
25 };
26
27 const ArmRegisterDescriptor armCopNumbers[] = {
28 { L"p0", 0 }, { L"p1", 1 }, { L"p2", 2 }, { L"p3", 3 },
29 { L"p4", 4 }, { L"p5", 5 }, { L"p6", 6 }, { L"p7", 7 },
30 { L"p8", 8 }, { L"p9", 9 }, { L"p10", 10 }, { L"p11", 11 },
31 { L"p12", 12 }, { L"p13", 13 }, { L"p14", 14 }, { L"p15", 15 },
32 };
33
parseDirectiveThumb(Parser & parser,int flags)34 std::unique_ptr<CAssemblerCommand> parseDirectiveThumb(Parser& parser, int flags)
35 {
36 Arm.SetThumbMode(true);
37 return make_unique<ArmStateCommand>(false);
38 }
39
parseDirectiveArm(Parser & parser,int flags)40 std::unique_ptr<CAssemblerCommand> parseDirectiveArm(Parser& parser, int flags)
41 {
42 Arm.SetThumbMode(false);
43 return make_unique<ArmStateCommand>(true);
44 }
45
parseDirectivePool(Parser & parser,int flags)46 std::unique_ptr<CAssemblerCommand> parseDirectivePool(Parser& parser, int flags)
47 {
48 auto seq = make_unique<CommandSequence>();
49 seq->addCommand(make_unique<CDirectiveAlignFill>(4,CDirectiveAlignFill::Align));
50 seq->addCommand(make_unique<ArmPoolCommand>());
51
52 return std::move(seq);
53 }
54
55 const wchar_t* msgTemplate =
56 L"mov r12,r12\n"
57 L"b %after%\n"
58 L".byte 0x64,0x64,0x00,0x00\n"
59 L".ascii %text%\n"
60 L".align %alignment%\n"
61 L"%after%:"
62 ;
63
parseDirectiveMsg(Parser & parser,int flags)64 std::unique_ptr<CAssemblerCommand> parseDirectiveMsg(Parser& parser, int flags)
65 {
66 Expression text = parser.parseExpression();
67 if (text.isLoaded() == false)
68 return nullptr;
69
70 return parser.parseTemplate(msgTemplate, {
71 { L"%after%", Global.symbolTable.getUniqueLabelName() },
72 { L"%text%", text.toString() },
73 { L"%alignment%", Arm.GetThumbMode() == true ? L"2" : L"4" }
74 });
75 }
76
77 const DirectiveMap armDirectives = {
78 { L".thumb", { &parseDirectiveThumb, 0 } },
79 { L".arm", { &parseDirectiveArm, 0 } },
80 { L".pool", { &parseDirectivePool, 0 } },
81 { L".msg", { &parseDirectiveMsg, 0 } },
82 };
83
parseDirective(Parser & parser)84 std::unique_ptr<CAssemblerCommand> ArmParser::parseDirective(Parser& parser)
85 {
86 return parser.parseDirective(armDirectives);
87 }
88
parseRegisterTable(Parser & parser,ArmRegisterValue & dest,const ArmRegisterDescriptor * table,size_t count)89 bool ArmParser::parseRegisterTable(Parser& parser, ArmRegisterValue& dest, const ArmRegisterDescriptor* table, size_t count)
90 {
91 const Token& token = parser.peekToken();
92 if (token.type != TokenType::Identifier)
93 return false;
94
95 const std::wstring stringValue = token.getStringValue();
96 for (size_t i = 0; i < count; i++)
97 {
98 if (stringValue == table[i].name)
99 {
100 dest.name = stringValue;
101 dest.num = table[i].num;
102 parser.eatToken();
103 return true;
104 }
105 }
106
107 return false;
108 }
109
parseRegister(Parser & parser,ArmRegisterValue & dest,int max)110 bool ArmParser::parseRegister(Parser& parser, ArmRegisterValue& dest, int max)
111 {
112 if (parseRegisterTable(parser,dest,armRegisters,ARRAY_SIZE(armRegisters)) == false)
113 return false;
114
115 return dest.num <= max;
116 }
117
parseCopRegister(Parser & parser,ArmRegisterValue & dest)118 bool ArmParser::parseCopRegister(Parser& parser, ArmRegisterValue& dest)
119 {
120 return parseRegisterTable(parser,dest,armCopRegisters,ARRAY_SIZE(armCopRegisters));
121 }
122
parseCopNumber(Parser & parser,ArmRegisterValue & dest)123 bool ArmParser::parseCopNumber(Parser& parser, ArmRegisterValue& dest)
124 {
125 return parseRegisterTable(parser,dest,armCopNumbers,ARRAY_SIZE(armCopNumbers));
126 }
127
parseRegisterList(Parser & parser,int & dest,int validMask)128 bool ArmParser::parseRegisterList(Parser& parser, int& dest, int validMask)
129 {
130 ArmRegisterValue reg, reg2;
131
132 dest = 0;
133 while (true)
134 {
135 if (parseRegister(parser,reg) == false)
136 return false;
137
138 if (parser.peekToken().type == TokenType::Minus)
139 {
140 parser.eatToken();
141
142 if (parseRegister(parser,reg2) == false || reg2.num < reg.num)
143 return false;
144
145 for (int i = reg.num; i <= reg2.num; i++)
146 {
147 dest |= (1 << i);
148 }
149 } else {
150 dest |= (1 << reg.num);
151 }
152
153 if (parser.peekToken().type != TokenType::Comma)
154 break;
155
156 parser.eatToken();
157 }
158
159 return (validMask & dest) == dest;
160 }
161
parseImmediate(Parser & parser,Expression & dest)162 bool ArmParser::parseImmediate(Parser& parser, Expression& dest)
163 {
164 TokenizerPosition pos = parser.getTokenizer()->getPosition();
165
166 // check if it really is an immediate
167 ArmOpcodeVariables tempVars;
168 if (parsePsrTransfer(parser,tempVars,false))
169 return false;
170
171 parser.getTokenizer()->setPosition(pos);
172 if (parseRegister(parser,tempVars.rd))
173 return false;
174
175 parser.getTokenizer()->setPosition(pos);
176 if (parseCopNumber(parser,tempVars.rd))
177 return false;
178
179 parser.getTokenizer()->setPosition(pos);
180 if (parseCopRegister(parser,tempVars.rd))
181 return false;
182
183 parser.getTokenizer()->setPosition(pos);
184 dest = parser.parseExpression();
185 return dest.isLoaded();
186 }
187
matchSymbol(Parser & parser,wchar_t symbol,bool optional)188 bool ArmParser::matchSymbol(Parser& parser, wchar_t symbol, bool optional)
189 {
190 switch (symbol)
191 {
192 case '[':
193 return parser.matchToken(TokenType::LBrack,optional);
194 case ']':
195 return parser.matchToken(TokenType::RBrack,optional);
196 case ',':
197 return parser.matchToken(TokenType::Comma,optional);
198 case '!':
199 return parser.matchToken(TokenType::Exclamation,optional);
200 case '{':
201 return parser.matchToken(TokenType::LBrace,optional);
202 case '}':
203 return parser.matchToken(TokenType::RBrace,optional);
204 case '#':
205 return parser.matchToken(TokenType::Hash,optional);
206 case '=':
207 return parser.matchToken(TokenType::Assign,optional);
208 case '+':
209 return parser.matchToken(TokenType::Plus,optional);
210 }
211
212 return false;
213 }
214
isNumber(wchar_t value)215 inline bool isNumber(wchar_t value)
216 {
217 return (value >= '0' && value <= '9');
218 }
219
parseShift(Parser & parser,ArmOpcodeVariables & vars,bool immediateOnly)220 bool ArmParser::parseShift(Parser& parser, ArmOpcodeVariables& vars, bool immediateOnly)
221 {
222 // no shift is also valid
223 vars.Shift.UseShift = false;
224 if (parser.peekToken().type != TokenType::Comma)
225 return true;
226
227 parser.eatToken();
228
229 // load shift mode
230 const Token& shiftMode = parser.nextToken();
231 if (shiftMode.type != TokenType::Identifier)
232 return false;
233
234 std::wstring stringValue = shiftMode.getStringValue();
235
236 bool hasNumber = isNumber(stringValue.back());
237 int64_t number;
238
239 // handle modeXX syntax
240 if (hasNumber)
241 {
242 number = 0;
243 int64_t multiplier = 1;
244 while (isNumber(stringValue.back()))
245 {
246 number += multiplier*(stringValue.back() - '0');
247 multiplier *= 10;
248 stringValue.pop_back();
249 }
250 }
251
252 if (stringValue == L"lsl")
253 vars.Shift.Type = 0;
254 else if (stringValue == L"lsr")
255 vars.Shift.Type = 1;
256 else if (stringValue == L"asr")
257 vars.Shift.Type = 2;
258 else if (stringValue == L"ror")
259 vars.Shift.Type = 3;
260 else if (stringValue == L"rrx")
261 vars.Shift.Type = 4;
262 else
263 return false;
264
265 if (hasNumber)
266 {
267 vars.Shift.ShiftExpression = createConstExpression(number);
268 vars.Shift.ShiftByRegister = false;
269 } else if (parseRegister(parser,vars.Shift.reg) == true)
270 {
271 if (immediateOnly)
272 return false;
273
274 vars.Shift.ShiftByRegister = true;
275 } else {
276 if (parser.peekToken().type == TokenType::Hash)
277 parser.eatToken();
278
279 if (parseImmediate(parser,vars.Shift.ShiftExpression) == false)
280 return false;
281
282 vars.Shift.ShiftByRegister = false;
283 }
284
285 vars.Shift.UseShift = true;
286 return true;
287 }
288
parsePseudoShift(Parser & parser,ArmOpcodeVariables & vars,int type)289 bool ArmParser::parsePseudoShift(Parser& parser, ArmOpcodeVariables& vars, int type)
290 {
291 vars.Shift.Type = type;
292
293 if (parseRegister(parser,vars.Shift.reg) == true)
294 {
295 vars.Shift.ShiftByRegister = true;
296 } else {
297 if (parser.peekToken().type == TokenType::Hash)
298 parser.eatToken();
299
300 if (parseImmediate(parser,vars.Shift.ShiftExpression) == false)
301 return false;
302
303 vars.Shift.ShiftByRegister = false;
304 }
305
306 vars.Shift.UseShift = true;
307 return true;
308 }
309
decodeCondition(const std::wstring & text,size_t & pos)310 int ArmParser::decodeCondition(const std::wstring& text, size_t& pos)
311 {
312 if (pos+2 <= text.size())
313 {
314 wchar_t c1 = text[pos+0];
315 wchar_t c2 = text[pos+1];
316 pos += 2;
317
318 if (c1 == 'e' && c2 == 'q') return 0;
319 if (c1 == 'n' && c2 == 'e') return 1;
320 if (c1 == 'c' && c2 == 's') return 2;
321 if (c1 == 'h' && c2 == 's') return 2;
322 if (c1 == 'c' && c2 == 'c') return 3;
323 if (c1 == 'l' && c2 == 'o') return 3;
324 if (c1 == 'm' && c2 == 'i') return 4;
325 if (c1 == 'p' && c2 == 'l') return 5;
326 if (c1 == 'v' && c2 == 's') return 6;
327 if (c1 == 'v' && c2 == 'c') return 7;
328 if (c1 == 'h' && c2 == 'i') return 8;
329 if (c1 == 'l' && c2 == 's') return 9;
330 if (c1 == 'g' && c2 == 'e') return 10;
331 if (c1 == 'l' && c2 == 't') return 11;
332 if (c1 == 'g' && c2 == 't') return 12;
333 if (c1 == 'l' && c2 == 'e') return 13;
334 if (c1 == 'a' && c2 == 'l') return 14;
335
336 pos -= 2;
337 }
338
339 return 14;
340 }
341
decodeAddressingMode(const std::wstring & text,size_t & pos,unsigned char & dest)342 bool ArmParser::decodeAddressingMode(const std::wstring& text, size_t& pos, unsigned char& dest)
343 {
344 if (pos+2 > text.size())
345 return false;
346
347 wchar_t c1 = text[pos+0];
348 wchar_t c2 = text[pos+1];
349
350 if (c1 == 'i' && c2 == 'b') dest = ARM_AMODE_IB;
351 else if (c1 == 'i' && c2 == 'a') dest = ARM_AMODE_IA;
352 else if (c1 == 'd' && c2 == 'b') dest = ARM_AMODE_DB;
353 else if (c1 == 'd' && c2 == 'a') dest = ARM_AMODE_DA;
354 else if (c1 == 'e' && c2 == 'd') dest = ARM_AMODE_ED;
355 else if (c1 == 'f' && c2 == 'd') dest = ARM_AMODE_FD;
356 else if (c1 == 'e' && c2 == 'a') dest = ARM_AMODE_EA;
357 else if (c1 == 'f' && c2 == 'a') dest = ARM_AMODE_FA;
358 else
359 return false;
360
361 pos += 2;
362 return true;
363 }
364
decodeXY(const std::wstring & text,size_t & pos,bool & dest)365 bool ArmParser::decodeXY(const std::wstring& text, size_t& pos, bool& dest)
366 {
367 if (pos >= text.size())
368 return false;
369
370 if (text[pos] == 't')
371 dest = true;
372 else if (text[pos] == 'b')
373 dest = false;
374 else
375 return false;
376
377 pos++;
378 return true;
379 }
380
decodeS(const std::wstring & text,size_t & pos,bool & dest)381 void ArmParser::decodeS(const std::wstring& text, size_t& pos, bool& dest)
382 {
383 dest = pos < text.size() && text[pos] == 's';
384 if (dest)
385 pos++;
386 }
387
decodeArmOpcode(const std::wstring & name,const tArmOpcode & opcode,ArmOpcodeVariables & vars)388 bool ArmParser::decodeArmOpcode(const std::wstring& name, const tArmOpcode& opcode, ArmOpcodeVariables& vars)
389 {
390 vars.Opcode.c = vars.Opcode.a = 0;
391 vars.Opcode.s = false;
392
393 const char* encoding = opcode.name;
394 size_t pos = 0;
395
396 while (*encoding != 0)
397 {
398 switch (*encoding++)
399 {
400 case 'C': // condition
401 vars.Opcode.c = decodeCondition(name,pos);
402 break;
403 case 'S': // set flag
404 decodeS(name,pos,vars.Opcode.s);
405 break;
406 case 'A': // addressing mode
407 CHECK(decodeAddressingMode(name,pos,vars.Opcode.a));
408 break;
409 case 'X': // x flag
410 CHECK(decodeXY(name,pos,vars.Opcode.x));
411 break;
412 case 'Y': // y flag
413 CHECK(decodeXY(name,pos,vars.Opcode.y));
414 break;
415 default:
416 CHECK(pos < name.size());
417 CHECK(*(encoding-1) == name[pos++]);
418 break;
419 }
420 }
421
422 return pos >= name.size();
423 }
424
parseWriteback(Parser & parser,bool & dest)425 void ArmParser::parseWriteback(Parser& parser, bool& dest)
426 {
427 dest = parser.peekToken().type == TokenType::Exclamation;
428 if (dest)
429 parser.eatToken();
430 }
431
parsePsr(Parser & parser,bool & dest)432 void ArmParser::parsePsr(Parser& parser, bool& dest)
433 {
434 dest = parser.peekToken().type == TokenType::Caret;
435 if (dest)
436 parser.eatToken();
437 }
438
parseSign(Parser & parser,bool & dest)439 void ArmParser::parseSign(Parser& parser, bool& dest)
440 {
441 switch (parser.peekToken().type)
442 {
443 case TokenType::Plus:
444 dest = true;
445 parser.eatToken();
446 break;
447 case TokenType::Minus:
448 dest = false;
449 parser.eatToken();
450 break;
451 default:
452 dest = true;
453 break;
454 }
455 }
456
parsePsrTransfer(Parser & parser,ArmOpcodeVariables & vars,bool shortVersion)457 bool ArmParser::parsePsrTransfer(Parser& parser, ArmOpcodeVariables& vars, bool shortVersion)
458 {
459 const Token& token = parser.nextToken();
460 if (token.type != TokenType::Identifier)
461 return false;
462
463 const std::wstring stringValue = token.getStringValue();
464 size_t pos = 0;
465 if (startsWith(stringValue,L"cpsr"))
466 {
467 vars.PsrData.spsr = false;
468 pos = 4;
469 } else if (startsWith(stringValue,L"spsr"))
470 {
471 vars.PsrData.spsr = true;
472 pos = 4;
473 } else {
474 return false;
475 }
476
477 if (shortVersion)
478 return pos == stringValue.size();
479
480 if (pos == stringValue.size())
481 {
482 vars.PsrData.field = 0xF;
483 return true;
484 }
485
486 if (stringValue[pos++] != '_')
487 return false;
488
489 if (startsWith(stringValue,L"ctl",pos))
490 {
491 vars.PsrData.field = 1;
492 return pos+3 == stringValue.size();
493 }
494
495 if (startsWith(stringValue,L"flg",pos))
496 {
497 vars.PsrData.field = 8;
498 return pos+3 == stringValue.size();
499 }
500
501 vars.PsrData.field = 0;
502 for (int i = 0; i < 4; i++)
503 {
504 if (pos == stringValue.size())
505 break;
506
507 switch(stringValue[pos++])
508 {
509 case 'f':
510 if (vars.PsrData.field & 8)
511 return false; // can only appear once
512 vars.PsrData.field |= 8;
513 break;
514 case 's':
515 if (vars.PsrData.field & 4)
516 return false; // can only appear once
517 vars.PsrData.field |= 4;
518 break;
519 case 'x':
520 if (vars.PsrData.field & 2)
521 return false; // can only appear once
522 vars.PsrData.field |= 2;
523 break;
524 case 'c':
525 if (vars.PsrData.field & 1)
526 return false; // can only appear once
527 vars.PsrData.field |= 1;
528 break;
529 default:
530 return false; // has to be one of those
531 }
532 }
533
534 return true;
535 }
536
parseArmParameters(Parser & parser,const tArmOpcode & opcode,ArmOpcodeVariables & vars)537 bool ArmParser::parseArmParameters(Parser& parser, const tArmOpcode& opcode, ArmOpcodeVariables& vars)
538 {
539 const char* encoding = opcode.mask;
540
541 ArmRegisterValue tempRegister;
542
543 vars.Shift.UseShift = false;
544 vars.Shift.UseFinal = false;
545 vars.psr = false;
546 vars.writeback = false;
547 vars.SignPlus = false;
548 vars.Opcode.UseNewEncoding = false;
549 vars.Opcode.UseNewType = false;
550
551 while (*encoding != 0)
552 {
553 bool optional = *encoding == '/';
554 if (optional)
555 encoding++;
556
557 switch (*encoding++)
558 {
559 case 'd': // register
560 CHECK(parseRegister(parser,vars.rd,*encoding++ == '1' ? 14 : 15));
561 break;
562 case 's': // register
563 CHECK(parseRegister(parser,vars.rs,*encoding++ == '1' ? 14 : 15));
564 break;
565 case 'n': // register
566 CHECK(parseRegister(parser,vars.rn,*encoding++ == '1' ? 14 : 15));
567 break;
568 case 'm': // register
569 CHECK(parseRegister(parser,vars.rm,*encoding++ == '1' ? 14 : 15));
570 break;
571 case 'D': // cop register
572 CHECK(parseCopRegister(parser,vars.CopData.cd));
573 break;
574 case 'N': // cop register
575 CHECK(parseCopRegister(parser,vars.CopData.cn));
576 break;
577 case 'M': // cop register
578 CHECK(parseCopRegister(parser,vars.CopData.cm));
579 break;
580 case 'W': // writeback
581 parseWriteback(parser,vars.writeback);
582 break;
583 case 'p': // psr
584 parsePsr(parser,vars.psr);
585 break;
586 case 'P': // msr/mrs psr data
587 CHECK(parsePsrTransfer(parser,vars,*encoding++ == '1'));
588 break;
589 case 'R': // register list
590 CHECK(parseRegisterList(parser,vars.rlist,0xFFFF));
591 break;
592 case 'S': // shift
593 CHECK(parseShift(parser,vars,*encoding++ == '1'));
594 break;
595 case 'I': // immediate
596 case 'i':
597 CHECK(parseImmediate(parser,vars.ImmediateExpression));
598 vars.ImmediateBitLen = 32;
599 break;
600 case 'j': // variable bit immediate
601 CHECK(parseImmediate(parser,vars.ImmediateExpression));
602 vars.ImmediateBitLen = *encoding++;
603 break;
604 case 'X': // cop number
605 CHECK(parseCopNumber(parser,vars.CopData.pn));
606 break;
607 case 'Y': // cop opcode number
608 CHECK(parseImmediate(parser,vars.CopData.CpopExpression));
609 vars.ImmediateBitLen = 4;
610 break;
611 case 'Z': // cop info number
612 CHECK(parseImmediate(parser,vars.CopData.CpinfExpression));
613 vars.ImmediateBitLen = 3;
614 break;
615 case 'z': // shift for pseudo opcodes
616 CHECK(parsePseudoShift(parser,vars,*encoding++));
617 break;
618 case 'v': // sign for register index parameter
619 parseSign(parser,vars.SignPlus);
620 break;
621 default:
622 CHECK(matchSymbol(parser,*(encoding-1),optional));
623 break;
624 }
625 }
626
627 // the next token has to be a separator, else the parameters aren't
628 // completely parsed
629 return parser.nextToken().type == TokenType::Separator;
630 }
631
parseArmOpcode(Parser & parser)632 std::unique_ptr<CArmInstruction> ArmParser::parseArmOpcode(Parser& parser)
633 {
634 if (parser.peekToken().type != TokenType::Identifier)
635 return nullptr;
636
637 const Token &token = parser.nextToken();
638
639 ArmOpcodeVariables vars;
640 bool paramFail = false;
641
642 const std::wstring stringValue = token.getStringValue();
643 for (int z = 0; ArmOpcodes[z].name != nullptr; z++)
644 {
645 if ((ArmOpcodes[z].flags & ARM_ARM9) && Arm.getVersion() == AARCH_GBA)
646 continue;
647
648 if (decodeArmOpcode(stringValue,ArmOpcodes[z],vars) == true)
649 {
650 TokenizerPosition tokenPos = parser.getTokenizer()->getPosition();
651
652 if (parseArmParameters(parser,ArmOpcodes[z],vars) == true)
653 {
654 // success, return opcode
655 return make_unique<CArmInstruction>(ArmOpcodes[z],vars);
656 }
657
658 parser.getTokenizer()->setPosition(tokenPos);
659 paramFail = true;
660 }
661 }
662
663 if (paramFail == true)
664 parser.printError(token,L"ARM parameter failure");
665 else
666 parser.printError(token,L"Invalid ARM opcode");
667
668 return nullptr;
669 }
670
parseThumbParameters(Parser & parser,const tThumbOpcode & opcode,ThumbOpcodeVariables & vars)671 bool ArmParser::parseThumbParameters(Parser& parser, const tThumbOpcode& opcode, ThumbOpcodeVariables& vars)
672 {
673 const char* encoding = opcode.mask;
674
675 ArmRegisterValue tempRegister;
676 int value;
677
678 while (*encoding != 0)
679 {
680 bool optional = *encoding == '/';
681 if (optional)
682 encoding++;
683
684 switch (*encoding++)
685 {
686 case 'd': // register
687 CHECK(parseRegister(parser,vars.rd,7));
688 break;
689 case 's': // register
690 CHECK(parseRegister(parser,vars.rs,7));
691 break;
692 case 'n': // register
693 CHECK(parseRegister(parser,vars.rn,7));
694 break;
695 case 'o': // register
696 CHECK(parseRegister(parser,vars.ro,7));
697 break;
698 case 'D': // register
699 CHECK(parseRegister(parser,vars.rd,15));
700 break;
701 case 'S': // register
702 CHECK(parseRegister(parser,vars.rs,15));
703 break;
704 case 'r': // forced register
705 CHECK(parseRegister(parser,tempRegister,15));
706 CHECK(*encoding++ == tempRegister.num);
707 break;
708 case 'R': // register list
709 value = encoding[0] | (encoding[1] << 8);
710 CHECK(parseRegisterList(parser,vars.rlist,value));
711 encoding += 2;
712 break;
713 case 'I': // immediate
714 case 'i':
715 CHECK(parseImmediate(parser,vars.ImmediateExpression));
716 vars.ImmediateBitLen = *encoding++;
717 break;
718 default:
719 CHECK(matchSymbol(parser,*(encoding-1),optional));
720 break;
721 }
722 }
723
724 // the next token has to be a separator, else the parameters aren't
725 // completely parsed
726 return parser.nextToken().type == TokenType::Separator;
727 }
728
parseThumbOpcode(Parser & parser)729 std::unique_ptr<CThumbInstruction> ArmParser::parseThumbOpcode(Parser& parser)
730 {
731 if (parser.peekToken().type != TokenType::Identifier)
732 return nullptr;
733
734 const Token &token = parser.nextToken();
735
736 ThumbOpcodeVariables vars;
737 bool paramFail = false;
738
739 const std::wstring stringValue = token.getStringValue();
740 for (int z = 0; ThumbOpcodes[z].name != nullptr; z++)
741 {
742 if ((ThumbOpcodes[z].flags & THUMB_ARM9) && Arm.getVersion() == AARCH_GBA)
743 continue;
744
745 // todo: save as wchar
746 std::wstring name = convertUtf8ToWString(ThumbOpcodes[z].name);
747
748 if (stringValue == name)
749 {
750 TokenizerPosition tokenPos = parser.getTokenizer()->getPosition();
751
752 if (parseThumbParameters(parser,ThumbOpcodes[z],vars) == true)
753 {
754 // success, return opcode
755 return make_unique<CThumbInstruction>(ThumbOpcodes[z],vars);
756 }
757
758 parser.getTokenizer()->setPosition(tokenPos);
759 paramFail = true;
760 }
761 }
762
763 if (paramFail == true)
764 parser.printError(token,L"THUMB parameter failure");
765 else
766 parser.printError(token,L"Invalid THUMB opcode");
767
768 return nullptr;
769 }
770