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