bool CThumbInstruction::LoadEncoding(const tThumbOpcode& SourceOpcode, char* Line) { char ImmediateBuffer[512]; int p,RetLen; CStringList List; bool Immediate = false; char* SourceEncoding = SourceOpcode.mask; char* OriginalLine = Line; while (*Line == ' ' || *Line == '\t') Line++; tArmRegisterInfo* Info; if (!(*SourceEncoding == 0 && *Line == 0)) { while (*SourceEncoding != NULL) { while (*Line == ' ' || *Line == '\t') Line++; // if (*Line == 0) return false; switch (*SourceEncoding) { case 'd': case 's': case 'n': case 'o': case 'D': case 'S': // registers for (int i = 0; ; i++) { if (RegisterLookup[i].Character == *SourceEncoding) { Info = (tArmRegisterInfo*)((int) (&Vars) + RegisterLookup[i].StructOffset); if (ArmGetRegister(Line,RetLen,*Info) == false) return false; if (Info->Number > RegisterLookup[i].MaxNum) return false; Line += RetLen; SourceEncoding++; break; } } break; /* case 'd': // low reg if (ArmGetRegister(Line,RetLen,Vars.rd) == false) return false; if (Vars.rd.Number > 7) return false; Line += RetLen; SourceEncoding++; break; case 's': // low reg if (ArmGetRegister(Line,RetLen,Vars.rs) == false) return false; if (Vars.rs.Number > 7) return false; Line += RetLen; SourceEncoding++; break; case 'n': // low reg if (ArmGetRegister(Line,RetLen,Vars.rn) == false) return false; if (Vars.rn.Number > 7) return false; Line += RetLen; SourceEncoding++; break; case 'o': // low reg if (ArmGetRegister(Line,RetLen,Vars.ro) == false) return false; if (Vars.ro.Number > 7) return false; Line += RetLen; SourceEncoding++; break; case 'D': // high reg if (ArmGetRegister(Line,RetLen,Vars.rd) == false) return false; Line += RetLen; SourceEncoding++; break; case 'S': // high reg if (ArmGetRegister(Line,RetLen,Vars.rs) == false) return false; Line += RetLen; SourceEncoding++; break;*/ case 'I': // immediate case 'i': if (ArmCheckImmediate(Line,ImmediateBuffer,RetLen,List) == false) return false; Vars.ImmediateBitLen = *(SourceEncoding+1); Line += RetLen; SourceEncoding += 2; break; case 'r': // forced register if (ArmGetRegister(Line,RetLen) != *(SourceEncoding+1)) return false; Line += RetLen; SourceEncoding += 2; break; case 'R': // rlist memcpy(&p,&SourceEncoding[1],2); if (ArmGetRlist(Line,RetLen,p,Vars.rlist) == false) return false; memcpy(Vars.RlistStr,Line,RetLen); Vars.RlistStr[RetLen] = 0; Line += RetLen; SourceEncoding += 3; break; case '/': // optional characters if (*Line == *(SourceEncoding+1)) Line++; SourceEncoding += 2; break; default: // everything else if (*SourceEncoding++ != *Line++) return false; break; } } } while (*Line == ' ' || *Line == '\t') Line++; if (*Line != 0) return false; // there's something else, bad // opcode is ok - now set all flags Opcode = SourceOpcode; if (Opcode.flags & THUMB_IMMEDIATE) { if (CheckPostfix(List,true) == false) { Logger::printError(Logger::Error,L"Invalid expression \"%S\"",ImmediateBuffer); NoCheckError = true; return false; } Vars.ImmediateExpression.Load(List); } OpcodeSize = Opcode.flags & THUMB_LONG ? 4 : 2; return true; }
/* case 'M': // cop register m if (ArmGetCopRegister(Line,RetLen,Vars.CopData.cm) == false) return false; Line += RetLen; SourceEncoding++;*/ bool CArmInstruction::LoadEncoding(const tArmOpcode& SourceOpcode, char* Line) { int RetLen; bool Immediate = false; Vars.psr= false; Vars.writeback = false; Vars.SignPlus = false; Vars.Opcode.UseNewEncoding = false; Vars.Opcode.UseNewType = false; char* SourceEncoding = (char*)(SourceOpcode.mask); char* OriginalLine = Line; while (*Line == ' ' || *Line == '\t') Line++; tArmRegisterInfo* Info; if (!(*SourceEncoding == 0 && *Line == 0)) { while (*SourceEncoding != 0) { while (*Line == ' ' || *Line == '\t') Line++; // if (*Line == 0) return false; switch (*SourceEncoding) { case 'd': case 's': case 'n': case 'm': case 'D': case 'N': case 'M': // all of them are registers for (int i = 0; ; i++) { if (RegisterLookup[i].Character == *SourceEncoding) { Info = (tArmRegisterInfo*)((uintptr_t) (&Vars) + RegisterLookup[i].StructOffset); if (RegisterLookup[i].type == ARMREG_NORMAL) { if (ArmGetRegister(Line,RetLen,*Info) == false) return false; if (*(SourceEncoding+1) == '1' && Info->Number == 15) return false; Line += RetLen; SourceEncoding += 2; } else { if (ArmGetCopRegister(Line,RetLen,*Info) == false) return false; Line += RetLen; SourceEncoding++; } break; } } break; /* case 'd': // reg if (ArmGetRegister(Line,RetLen,Vars.rd) == false) return false; if (*(SourceEncoding+1) == '1' && Vars.rd.Number == 15) return false; Line += RetLen; SourceEncoding += 2; break; case 's': // reg if (ArmGetRegister(Line,RetLen,Vars.rs) == false) return false; if (*(SourceEncoding+1) == '1' && Vars.rs.Number == 15) return false; Line += RetLen; SourceEncoding += 2; break; case 'n': // reg if (ArmGetRegister(Line,RetLen,Vars.rn) == false) return false; if (*(SourceEncoding+1) == '1' && Vars.rn.Number == 15) return false; Line += RetLen; SourceEncoding += 2; break; case 'm': // reg if (ArmGetRegister(Line,RetLen,Vars.rm) == false) return false; if (*(SourceEncoding+1) == '1' && Vars.rm.Number == 15) return false; Line += RetLen; SourceEncoding += 2; break;*/ case 'W': // writeback if (*Line == '!') { Vars.writeback = true; Line++; } SourceEncoding++; break; case 'p': // psr if (*Line == '^') { Vars.psr = true; Line++; } SourceEncoding++; break; case 'P': // msr/mrs psr data if (strncmp(Line,"cpsr",4) == 0) // is cpsr { Vars.PsrData.spsr = false; Line += 4; } else if (strncmp(Line,"spsr",4) == 0) // is spsr { Vars.PsrData.spsr = true; Line += 4; } else return false; // otherwise it's neither if (SourceEncoding[1] != '1') { if (*Line != '_') // no underscore = short version { Vars.PsrData.field = 0xF; } else { Line++; if (memcmp(Line,"ctl",3) == 0) { Vars.PsrData.field = 1; Line += 3; } else if (memcmp(Line,"flg",3) == 0) { Vars.PsrData.field = 8; Line += 3; } else { Vars.PsrData.field = 0; for (int i = 0; i < 4; i++) { if (*Line == ',') break; if (*Line == 'f') { if (Vars.PsrData.field & 8) return false; // can only appear once Vars.PsrData.field |= 8; } else if (*Line == 's') { if (Vars.PsrData.field & 4) return false; // can only appear once Vars.PsrData.field |= 4; } else if (*Line == 'x') { if (Vars.PsrData.field & 2) return false; // can only appear once Vars.PsrData.field |= 2; } else if (*Line == 'c') { if (Vars.PsrData.field & 1) return false; // can only appear once Vars.PsrData.field |= 1; } else return false; // has to be one of those Line++; } } } } SourceEncoding+=2; break; case 'R': // rlist if (ArmGetRlist(Line,RetLen,0xFFFF,Vars.rlist) == false) return false; memcpy(Vars.RlistStr,Line,RetLen); Vars.RlistStr[RetLen] = 0; Line += RetLen; SourceEncoding++; break; case 'S': if (ParseShift(Line,SourceEncoding[1]) == false) return false; SourceEncoding += 2; break; case 'I': // immediate case 'i': if (ArmParseImmediate(Line,Vars.ImmediateExpression,RetLen) == false) return false; Line += RetLen; Vars.ImmediateBitLen = 32; SourceEncoding++; break; case 'j': // variable bit immediate if (ArmParseImmediate(Line,Vars.ImmediateExpression,RetLen) == false) return false; Line += RetLen; Vars.ImmediateBitLen = *(SourceEncoding+1); SourceEncoding+=2; break; case '/': // optional character if (*Line == *(SourceEncoding+1)) Line++; SourceEncoding += 2; break; /* case 'D': // cop register d if (ArmGetCopRegister(Line,RetLen,Vars.CopData.cd) == false) return false; Line += RetLen; SourceEncoding++; break; case 'N': // cop register n if (ArmGetCopRegister(Line,RetLen,Vars.CopData.cn) == false) return false; Line += RetLen; SourceEncoding++; break; case 'M': // cop register m if (ArmGetCopRegister(Line,RetLen,Vars.CopData.cm) == false) return false; Line += RetLen; SourceEncoding++; break;*/ case 'X': // cop number if (ArmGetCopNumber(Line,RetLen,Vars.CopData.pn) == false) return false; Line += RetLen; SourceEncoding++; break; case 'Y': // cop opcode number if (ArmParseImmediate(Line,Vars.CopData.CpopExpression,RetLen) == false) { Logger::printError(Logger::Error,L"Invalid expression"); NoCheckError = true; return false; } Vars.ImmediateBitLen = 4; Line += RetLen; SourceEncoding++; break; case 'Z': // cop info number if (ArmParseImmediate(Line,Vars.CopData.CpinfExpression,RetLen) == false) { Logger::printError(Logger::Error,L"Invalid expression"); NoCheckError = true; return false; } Vars.ImmediateBitLen = 3; Line += RetLen; SourceEncoding++; break; case 'z': // shift for pseudo opcodes Vars.Shift.Type = SourceEncoding[1]; if (ArmGetRegister(Line,RetLen,Vars.Shift.reg) == true) // shift by register { Vars.Shift.ShiftByRegister = true; } else { // shift by immediate Vars.Shift.ShiftByRegister = false; if (ArmParseImmediate(Line,Vars.Shift.ShiftExpression,RetLen) == false) { Logger::printError(Logger::Error,L"Invalid shift expression"); NoCheckError = true; return false; } } Line += RetLen; Vars.Shift.UseShift = true; SourceEncoding += 2; break; case 'v': // sign for register index parameter if (*Line == '-') { Vars.SignPlus = false; Line++; } else if (*Line == '+') { Vars.SignPlus = true; Line++; } else { Vars.SignPlus = true; } SourceEncoding++; break; default: // everything else if (*SourceEncoding++ != *Line++) return false; break; } } } while (*Line == ' ' || *Line == '\t') Line++; if (*Line != 0) return false; // there's something left, bad // opcode is fine - now set all flags Opcode = SourceOpcode; return true; }