示例#1
0
/* Disassembles an assembled instruction, including its operands. */
int disassembleInstruction(disassembledInstruction *dInstruction, const assembledInstruction *aInstruction, int instructionSetIndex) {
	int instructionIndex, i;

	if (dInstruction == NULL)
		return ERROR_INVALID_ARGUMENTS;

	if (instructionSetIndex != PIC_BASELINE &&
	    instructionSetIndex != PIC_MIDRANGE &&
	    instructionSetIndex != PIC_MIDRANGE_ENHANCED)
		return ERROR_INVALID_ARGUMENTS;

	/* Look up the instruction */
	instructionIndex = lookupInstruction(aInstruction->opcode, 0, instructionSetIndex);

	/* Copy over the address, and reference to the instruction, set
	 * the equivilant-encoded but different instruction to NULL for now. */
	dInstruction->address = aInstruction->address;
	dInstruction->instruction = &(allInstructionSets[instructionSetIndex].instructionSet[instructionIndex]);
	dInstruction->alternateInstruction = NULL;

	/* Copy out each operand, extracting the operand data from the original
	 * opcode using the operand mask. */
	for (i = 0; i < allInstructionSets[instructionSetIndex].instructionSet[instructionIndex].numOperands; i++)
		dInstruction->operands[i] = extractDataFromMask(aInstruction->opcode, dInstruction->instruction->operandMasks[i]);

	/* Disassemble operands */
	if (disassembleOperands(dInstruction) < 0)
		return ERROR_INVALID_ARGUMENTS; /* Only possible error for disassembleOperands() */

	return 0;
}
示例#2
0
/* Look up an instruction by it's opcode in the instructionSet,
 * starting from index offset. Always returns a valid instruction
 * index because the last instruction in the instruction set database
 * is set to be a generic data word (.DW). */
static int lookupInstruction(uint16_t opcode, int offset) {
	uint16_t opcodeSearch, operandTemp;
	int insidx, ghostRegisterConfirmed, i, j;
	
	for (insidx = offset; insidx < AVR_TOTAL_INSTRUCTIONS; insidx++) {
		opcodeSearch = opcode;
		/* If we have a ghost register operand (OPERAND_REGISTER_GHOST),
		 * we need to confirm that all of the other register operands are the same */
		ghostRegisterConfirmed = 1;
		/* We want to mask out all of the operands. We don't count up to
		 * instructionSet[insidx].numOperands because some instructions,
		 * such as clr R16, are actually encoded with two operands (so as eor R16,R16),
		 * and we want to screen out both operands to get the most simplest form of 
		 * the instruction. */ 
		for (i = 0; i < AVR_MAX_NUM_OPERANDS; i++) {
			if (instructionSet[insidx].operandTypes[i] == OPERAND_REGISTER_GHOST) {
				/* Grab the first operand */
				operandTemp = extractDataFromMask(opcode, instructionSet[insidx].operandMasks[0]);
				/* Compare the remaining operands to the first */
				for (j = 1; j < AVR_MAX_NUM_OPERANDS; j++) {
					if (extractDataFromMask(opcode, instructionSet[insidx].operandMasks[i]) !=
							operandTemp)
						ghostRegisterConfirmed = 0;
				}
			} 
			opcodeSearch &= ~(instructionSet[insidx].operandMasks[i]);
		}
		/* If we encountered a ghost register and were unable confirm that
		 * all register operands were equal (in this case ghostRegisterConfirmed
		 * would have changed), then move the match-search onto the next instruction. */
		if (ghostRegisterConfirmed == 0)
			continue;

		if (opcodeSearch == instructionSet[insidx].opcodeMask) 
			break;
	}
	/* It's impossible not to find an instruction, because the last instruction ".DW",
	 * specifies a word of data at the addresses, instead of an instruction. 
	 * Its operand 2 mask, 0x0000, will set opcode search to 0x0000, and this will always
	 * match with the opcodeMask of 0x0000. */
	return insidx;
}
示例#3
0
/* Disassembles an assembled instruction, including its operands. */
int disassembleInstruction(disassembledInstruction *dInstruction, const assembledInstruction aInstruction) {
	int insidx, i;
	
	if (dInstruction == NULL)
		return ERROR_INVALID_ARGUMENTS;
	
	
	/* Look up the instruction */
	insidx = lookupInstruction(aInstruction.opcode, 0);
	if (insidx == AVR_TOTAL_INSTRUCTIONS) {
		// invalid instruction
		return 0;
	}

	/*** AVR SPECIFIC */
	/* If a long instruction was found in the last instruction disassembly,
	 * extract the rest of the address, and indicate that it is to be printed */
	if (AVR_Long_Instruction == AVR_LONG_INSTRUCTION_FOUND) {
		AVR_Long_Instruction = AVR_LONG_INSTRUCTION_PRINT;
		AVR_Long_Address |= aInstruction.opcode;
		/* We must multiply by two, because every instruction is 2 bytes,
		 * so in order to jump/call to the right address (which increments by
		 * two for every instruction), we must multiply this distance by two. */
		//printf ("ii=%d\n", insidx);
		if (insidx==86)
			AVR_Long_Address *= 2;
		*dInstruction = longInstruction;
		return 0;
	/* If a long instruction was printed in the last instruction disassembly,
	 * reset the AVR_Call_Instruction variable back to zero. */
	} else if (AVR_Long_Instruction == AVR_LONG_INSTRUCTION_PRINT) {
		AVR_Long_Instruction = 0;
	}

	/* Copy over the address, and reference to the instruction, set
	 * the equivilant-encoded but different instruction to NULL for now. */
	dInstruction->address = aInstruction.address;
	dInstruction->instruction = &instructionSet[insidx];
	dInstruction->alternateInstruction = NULL;
	
	/* Copy out each operand, extracting the operand data from the original
	 * opcode using the operand mask. */
	for (i = 0; i < instructionSet[insidx].numOperands; i++) {
		dInstruction->operands[i] = extractDataFromMask(aInstruction.opcode, dInstruction->instruction->operandMasks[i]);
		/*** AVR SPECIFIC */
		/* If this is an instruction with a long absolute operand, indicate that a long instruction has been found,
		 * and extract the first part of the long address. */
		if (dInstruction->instruction->operandTypes[i] == OPERAND_LONG_ABSOLUTE_ADDRESS) {
			AVR_Long_Instruction = AVR_LONG_INSTRUCTION_FOUND;
			AVR_Long_Address = dInstruction->operands[i] << 16;
			longInstruction = *dInstruction;
		}
	}
	
	/* Disassemble operands */
	if (disassembleOperands(dInstruction) < 0)
		return ERROR_INVALID_ARGUMENTS; /* Only possible error for disassembleOperands() */

	if (AVR_Long_Instruction == AVR_LONG_INSTRUCTION_FOUND) {
		/* If we found a long instruction (32-bit one),
		 * Copy this instruction over to our special longInstruction variable, that
		 * will exist even after we move onto the next 16-bits */
		longInstruction = *dInstruction;
	}

	return 0;
}