diff --git a/src/parser.c b/src/parser.c index 97eef8d..594d477 100644 --- a/src/parser.c +++ b/src/parser.c @@ -174,8 +174,475 @@ void classifyOpcode(char* opcode, a64inst_instruction *instr, char *operandList[ } else { if(classifyDPInst(operandList)){ instr->type = a64inst_DPREGISTER; + a64inst_DPRegisterData data = instr->data.DPRegisterData; + char t = operandList[0][0]; + if (t == 'w') { + data.regType=0; + } + else { + data.regType=1; + } + data.dest = getOperandNumber(operandList[0]); + data.src1 = getOperandNumber(operandList[1]); + // multiply + // mul, mneg, madd, msub + if (opcode[0] == 'm') { + data.DPROpType = 1; + data.src2 = getOperandNumber(operandList[2]); + switch (opcode[1]) { + // madd + case 'a': + data.processOpData.multiplydata.summand = getOperandNumber(operandList[3]); + data.processOpData.multiplydata.negProd = false; + break; + // mneg + case 'n': + data.processOpData.multiplydata.summand = ZERO_REGISTER; + data.processOpData.multiplydata.negProd = true; + break; + // msub + case 's': + data.processOpData.multiplydata.summand = getOperandNumber(operandList[3]); + data.processOpData.multiplydata.negProd = true; + break; + // mul + default: + data.processOpData.multiplydata.summand = ZERO_REGISTER; + data.processOpData.multiplydata.negProd = false; + break; + } + } + // arithmlogic + else { + data.DPROpType = 0; + // overridden when neccesary + data.processOpData.arithmLogicData.negShiftedSrc2 = 0; + // arithmetic + // add, adds + if (opcode[1] == 'd') { + data.processOpData.arithmLogicData.type = 1; + data.src2 = getOperandNumber(operandList[2]); + if (strlen(opcode) == 4) { + data.processOp = 1; + } + else { + data.processOp = 0; + } + // handles shifts + if (strlen(operandList) == 4) { + char *split[] = strtok(operandList[3], ' '); + switch (split[1][0]) { + case 'L': + // LSR + if (split[1][2] == 'R') { + data.processOpData.arithmLogicData.shiftType = 1; + } + // LSL + else { + data.processOpData.arithmLogicData.shiftType = 0; + } + break; + // ROR + case 'R': + data.processOpData.arithmLogicData.shiftType = 3; + break; + // ASR + default: + data.processOpData.arithmLogicData.shiftType = 2; + break; + } + } + } + // cmn + else if (opcode == 'cmn') { + data.dest = ZERO_REGISTER; + data.src1 = getOperandNumber(operandList[0]); + data.src2 = getOperandNumber(operandList[1]); + data.processOpData.arithmLogicData.type = 1; + data.processOp = 1; + // handles shifts + if (strlen(operandList) == 3) { + char *split[] = strtok(operandList[2], ' '); + switch (split[1][0]) { + case 'L': + // LSR + if (split[1][2] == 'R') { + data.processOpData.arithmLogicData.shiftType = 1; + } + // LSL + else { + data.processOpData.arithmLogicData.shiftType = 0; + } + break; + // ROR + case 'R': + data.processOpData.arithmLogicData.shiftType = 3; + break; + // ASR + default: + data.processOpData.arithmLogicData.shiftType = 2; + break; + } + } + } + // sub, subs + else if (opcode[2] == 'b') { + data.src2 = getOperandNumber(operandList[2]); + data.processOpData.arithmLogicData.type = 1; + if (strlen(opcode) == 4) { + data.processOp = 3; + } + else { + data.processOp = 2; + } + // handles shifts + if (strlen(operandList) == 4) { + char *split[] = strtok(operandList[3], ' '); + switch (split[1][0]) { + case 'L': + // LSR + if (split[1][2] == 'R') { + data.processOpData.arithmLogicData.shiftType = 1; + } + // LSL + else { + data.processOpData.arithmLogicData.shiftType = 0; + } + break; + // ROR + case 'R': + data.processOpData.arithmLogicData.shiftType = 3; + break; + // ASR + default: + data.processOpData.arithmLogicData.shiftType = 2; + break; + } + } + } + // cmp + else if (opcode == 'cmp') { + data.dest = ZERO_REGISTER; + data.src1 = getOperandNumber(operandList[0]); + data.src2 = getOperandNumber(operandList[1]); + data.processOpData.arithmLogicData.type = 1; + data.processOp = 3; + // handles shifts + if (strlen(operandList) == 3) { + char *split[] = strtok(operandList[2], ' '); + switch (split[1][0]) { + case 'L': + // LSR + if (split[1][2] == 'R') { + data.processOpData.arithmLogicData.shiftType = 1; + } + // LSL + else { + data.processOpData.arithmLogicData.shiftType = 0; + } + break; + // ROR + case 'R': + data.processOpData.arithmLogicData.shiftType = 3; + break; + // ASR + default: + data.processOpData.arithmLogicData.shiftType = 2; + break; + } + } + } + // neg, negs + else if (opcode[0] == 'n') { + data.src1 = ZERO_REGISTER; + data.src2 = getOperandNumber(operandList[1]); + data.processOpData.arithmLogicData.type = 1; + if (strlen(opcode) == 4) { + data.processOp = 3; + } + else { + data.processOp = 2; + } + // handles shifts + if (strlen(operandList) == 3) { + char *split[] = strtok(operandList[2], ' '); + switch (split[1][0]) { + case 'L': + // LSR + if (split[1][2] == 'R') { + data.processOpData.arithmLogicData.shiftType = 1; + } + // LSL + else { + data.processOpData.arithmLogicData.shiftType = 0; + } + break; + // ROR + case 'R': + data.processOpData.arithmLogicData.shiftType = 3; + break; + // ASR + default: + data.processOpData.arithmLogicData.shiftType = 2; + break; + } + } + } + else { + // logical + data.processOpData.arithmLogicData.type = 0; + // three special cases + if (opcode == 'tst') { + data.dest = ZERO_REGISTER; + data.src1 = getOperandNumber(operandList[0]); + data.src2 = getOperandNumber(operandList[1]); + data.processOp = 3; + if (strlen(operandList) == 3) { + char *split[] = strtok(operandList[2], ' '); + switch (split[1][0]) { + case 'L': + // LSR + if (split[1][2] == 'R') { + data.processOpData.arithmLogicData.shiftType = 1; + } + // LSL + else { + data.processOpData.arithmLogicData.shiftType = 0; + } + break; + // ROR + case 'R': + data.processOpData.arithmLogicData.shiftType = 3; + break; + // ASR + default: + data.processOpData.arithmLogicData.shiftType = 2; + break; + } + } + } + else if (opcode == 'mvn') { + data.dest = getOperandNumber(operandList[0]); + data.src1 = ZERO_REGISTER; + data.src2 = getOperandNumber(operandList[1]); + data.processOp = 1; + data.processOpData.arithmLogicData.negShiftedSrc2 = 1; + if (strlen(operandList) == 3) { + char *split[] = strtok(operandList[2], ' '); + switch (split[1][0]) { + case 'L': + // LSR + if (split[1][2] == 'R') { + data.processOpData.arithmLogicData.shiftType = 1; + } + // LSL + else { + data.processOpData.arithmLogicData.shiftType = 0; + } + break; + // ROR + case 'R': + data.processOpData.arithmLogicData.shiftType = 3; + break; + // ASR + default: + data.processOpData.arithmLogicData.shiftType = 2; + break; + } + } + } + else if (opcode == 'mov') { + data.dest = getOperandNumber(operandList[0]); + data.src1 = ZERO_REGISTER; + data.src2 = getOperandNumber(operandList[1]); + data.processOp = 1; + } + else { + data.src2 = getOperandNumber(operandList[2]); + // handles shifts + if (strlen(operandList) == 4) { + char *split[] = strtok(operandList[3], ' '); + switch (split[1][0]) { + case 'L': + // LSR + if (split[1][2] == 'R') { + data.processOpData.arithmLogicData.shiftType = 1; + } + // LSL + else { + data.processOpData.arithmLogicData.shiftType = 0; + } + break; + // ROR + case 'R': + data.processOpData.arithmLogicData.shiftType = 3; + break; + // ASR + default: + data.processOpData.arithmLogicData.shiftType = 2; + break; + } + } + switch (opcode[0]) { + // and, ands + case 'a': + // ands + if (strlen(opcode) == 4) { + data.processOp = 3; + } + // and + else { + data.processOp = 0; + } + break; + // bic, bics + case 'b': + data.processOpData.arithmLogicData.negShiftedSrc2 = 1; + // bics + if (strlen(opcode) == 4) { + data.processOp = 3; + } + // bic + else { + data.processOp = 0; + } + break; + // orr, orn + case 'o': + data.processOp = 1; + // orn + if (opcode[2] == 'n') { + data.processOpData.arithmLogicData.negShiftedSrc2 = 1; + } + break; + // eor, eon + default: + data.processOp = 2; + // eon + if (opcode[2] == 'n') { + data.processOpData.arithmLogicData.negShiftedSrc2 = 1; + } + break; + } + } + } + } } else { instr->type = a64inst_DPIMMEDIATE; + a64inst_DPImmediateData data = instr->data.DPImmediateData; + char t = operandList[0][0]; + if (t == 'w') { + data.regType=0; + } + else { + data.regType=1; + } + // arithmetic + // can be overwritten later + data.processOpData.arithmData.shiftImmediate = false; + // add, adds + if (opcode[1] == 'd') { + data.DPIOpType = 0; + data.dest = getOperandNumber(operandList[0]); + data.processOpData.arithmData.src = getOperandNumber(operandList[1]); + data.processOpData.arithmData.immediate = getOperandNumber(operandList[2]); + if (strlen(operandList) == 4) { + if (strlen(operandList[3]) == 8) { + data.processOpData.arithmData.shiftImmediate = true; + } + } + if (strlen(opcode) == 4) { + data.processOp = 1; + } + else { + data.processOp = 0; + } + } + // cmn + else if (opcode == "cmn") { + data.DPIOpType = 0; + data.dest = ZERO_REGISTER; + data.processOpData.arithmData.src = getOperandNumber(operandList[0]); + data.processOpData.arithmData.immediate = getOperandNumber(operandList[1]); + data.processOp = 1; + if (strlen(operandList) == 3) { + if (strlen(operandList[2]) == 8) { + data.processOpData.arithmData.shiftImmediate = true; + } + } + } + // sub, subs + else if (opcode[0] == 's') { + data.DPIOpType = 0; + data.dest = getOperandNumber(operandList[0]); + data.processOpData.arithmData.src = getOperandNumber(operandList[1]); + data.processOpData.arithmData.immediate = getOperandNumber(operandList[2]); + if (strlen(operandList) == 4) { + if (strlen(operandList[3]) == 8) { + data.processOpData.arithmData.shiftImmediate = true; + } + } + if (opcode[-1] == 's') { + data.processOp = 3; + } + else { + data.processOp = 2; + } + } + // cmp + else if (opcode == 'cmp') { + data.DPIOpType = 0; + data.dest = ZERO_REGISTER; + data.processOpData.arithmData.src = getOperandNumber(operandList[0]); + data.processOpData.arithmData.immediate = getOperandNumber(operandList[1]); + data.processOp = 3; + if (strlen(operandList) == 3) { + if (strlen(operandList[2]) == 8) { + data.processOpData.arithmData.shiftImmediate = true; + } + } + } + // neg, negs + else if (opcode[0] == 'n') { + data.DPIOpType = 0; + data.dest = getOperandNumber(operandList[1]); + data.processOpData.arithmData.src = ZERO_REGISTER; + data.processOpData.arithmData.immediate = getOperandNumber(operandList[2]); + if (strlen(operandList) == 3) { + if (strlen(operandList[2]) == 8) { + data.processOpData.arithmData.shiftImmediate = true; + } + } + if (opcode[-1] == 's') { + data.processOp = 3; + } + else { + data.processOp = 2; + } + } + // wide move + else { + data.DPIOpType = 1; + data.dest = getOperandNumber(operandList[0]); + switch (opcode[3]) { + case 'k': + data.processOp = 3; + break; + case 'n': + data.processOp = 0; + break; + case 'z': + data.processOp = 2; + break; + default: + data.processOp = 1; + break; + } + data.processOpData.wideMovData.immediate = getOperandNumber(operandList[1]); + if (numOperands == 3){ + data.processOpData.wideMovData.shiftScalar = getOperandNumber(strtok(operandList[2], ' ')[1]); + } + } } }