diff --git a/src/parser.c b/src/parser.c index 92afb0a..e8bc85f 100644 --- a/src/parser.c +++ b/src/parser.c @@ -25,7 +25,8 @@ static const char *ARITHMETIC_OPCODES[] = {"add", "adds", "sub", "subs"}; static const char *MULTIPLY_OPCODES[] = {"mul", "madd", "msub", "mneg"}; static const char *SHIFT_TYPE_OPCODES[] = {"lsl", "lsr", "asr", "ror"}; static const char *LOGIC_OPCODES[] = {"and", "ands", "bic", "bics", "eor", "eon", "orr", "orn"}; -//static const char *ALIASES[] = {"cmp", "cmn", "neg", "negs", "tst", "mvn", "mov", "mul", "mneg"}; +static const char *ALIAS_OPCODES[] = {"cmp", "cmn", "neg", "negs", "tst", "mvn", "mov"}; +static char *ALIAS_TARGET_OPCODES[] = {"subs", "adds", "sub", "subs", "ands", "orn", "orr"}; a64inst_instruction *parse(char **asmLines, int lineCount) { a64inst_instruction *instructions = malloc(sizeof(a64inst_instruction) * lineCount); @@ -64,6 +65,25 @@ static int indexStringIn(char *str, const char *arr[], int arrSize) { return -1; } +typedef struct { + int type; + int immediate; +} ShiftData; + +static ShiftData *parseShift(char *shift) { + char buffer[100]; + strcpy(buffer, shift); + char *shiftType = strtok(buffer, " "); + char *shiftAmount = strtok(NULL, " "); + ShiftData *data = malloc(sizeof(ShiftData)); + data->type = indexStringIn(shiftType, SHIFT_TYPE_OPCODES, 4); + while (*shiftAmount == ' ' || *shiftAmount == '#') { + shiftAmount++; + } + data->immediate = atoi(shiftAmount); + return data; +} + int isOperandRegister(char regStartChar) { return((regStartChar == 'x') || (regStartChar == 'w')); } @@ -74,7 +94,52 @@ int classifyDPInst(char *operandList[]){ isOperandRegister(operandList[3][0])); } -void classifyOpcode(char* opcode, a64inst_instruction *instr, char *tokens[], int tokensCount){ +void classifyAlias(char *opcode, a64inst_instruction *instr, char *tokens[], int *tokensCount) { + + int aliasIndex = indexStringIn(opcode, ALIAS_OPCODES, 9); + if (aliasIndex != -1) { + // The instruction is one of the aliases, convert into the target. + char *opcode = ALIAS_TARGET_OPCODES[aliasIndex]; + + // To correctly encode the zero register, which is either w31 or x31. + char *zeroReg = malloc(5 * sizeof(char)); + *zeroReg = *tokens[1]; + strcat(zeroReg, "31"); + + switch(aliasIndex) { + case 0: // cmp -> subs rzr, rn, + case 1: // cmn -> adds rzr, rn, + case 4: // tst -> ands rzr, rn, + // Convert from [instr] REG, to [instr] RZR, REG, + tokens[0] = opcode; + tokens[4] = tokens[3]; + tokens[3] = tokens[2]; + tokens[2] = tokens[1]; + tokens[1] = zeroReg; + (*tokensCount)++; + break; + + case 2: // neg -> subs rd, rzr, + case 3: // negs -> subs rd, rzr, + case 5: // mvn -> orn rd, rzr, + case 6: // mov -> orr rd, rzr, rm + tokens[0] = opcode; + tokens[4] = tokens[3]; + tokens[3] = tokens[2]; + tokens[2] = zeroReg; + (*tokensCount)++; + break; + + default: + break; + } + + } +} + +void classifyOpcode(char* opcode, a64inst_instruction *instr, char *tokens[], int *tokensCount){ + + classifyAlias(opcode, instr, tokens, tokensCount); if (isStringIn(opcode, BRANCH_OPCODES, 9)) { instr->type = a64inst_BRANCH; @@ -132,7 +197,7 @@ void parse_instruction(char asmLine[], a64inst_instruction *instr) { } else { // Instruction - classifyOpcode(opcode, instr, tokens, tokensCount); + classifyOpcode(opcode, instr, tokens, &tokensCount); switch(instr->type){ case a64inst_BRANCH: @@ -296,12 +361,8 @@ void parseDPImmediate(a64inst_instruction *inst, char *tokens[], int tokensCount data->processOp = indexStringIn(tokens[0], WIDE_MOV_OPCODES, 4); data->processOpData.wideMovData.immediate = getOperandNumber(tokens[2]); if (tokensCount >= 4) { - int numTokens = 0; - char **shiftOperands = tokenise(tokens[3], &numTokens); - int shiftAmount = getOperandNumber(shiftOperands[1]); - if (shiftAmount > 0) { - data->processOpData.wideMovData.shiftScalar = 12; - } + ShiftData shData = *parseShift(tokens[3]); + data->processOpData.wideMovData.shiftScalar = shData.immediate; } } else { @@ -311,10 +372,8 @@ void parseDPImmediate(a64inst_instruction *inst, char *tokens[], int tokensCount data->processOpData.arithmData.immediate = getOperandNumber(tokens[3]); if (tokensCount >= 5) { - int numTokens = 0; - char **shiftOperands = tokenise(tokens[4], &numTokens); - int shiftAmount = getOperandNumber(shiftOperands[1]); - if (shiftAmount > 0) { + ShiftData shData = *parseShift(tokens[4]); + if (shData.immediate > 0) { data->processOpData.arithmData.shiftImmediate = true; } } @@ -340,6 +399,7 @@ void parseDPRegister(a64inst_instruction *inst, char *tokens[], int tokensCount) data->processOpData.multiplydata.summand = ZERO_REGISTER; data->processOpData.multiplydata.negProd = strcmp(tokens[0], "mneg") == 0; } + } else { // Arithmetic/Logic data->DPROpType = a64inst_DPR_ARITHMLOGIC;