/*
 * Giovanni Agosta, Andrea Di Biagio
 * Politecnico di Milano, 2007
 * 
 * decode.c
 * Formal Languages & Compilers Machine, 2007/2008
 * 
 */
#include <stdlib.h>
#include "decode.h"

/* Nomi dei codici per le stampe di debug  */
char *names[4][16] = { 
	{ "ADD", "SUB", "ANDL", "ORL", "EORL", "ANDB", "ORB", "EORB", "MUL", "DIV", "SHL", "SHR", "ROTL", "ROTR", "NEG", "SPCL" },
	{ "ADDI", "SUBI", "ANDLI", "ORLI", "EORLI", "ANDBI", "ORBI", "EORBI", "MULI", "DIVI", "SHLI", "SHRI", "ROTLI", "ROTRI", "NOTL", "NOTB" },
	{ "NOP", "MOVA", "JSR", "RET", "LOAD", "STORE", "HALT", "SEQ", "SGE", "SGT", "SLE", "SLT", "SNE", "READ", "WRITE", "ILL15" },
	{ "BT", "BF", "BHI", "BLS", "BCC", "BCS", "BNE", "BEQ", "BVC", "BVS", "BPL", "BMI", "BGE", "BLT", "BGT", "BLE" } 
};

decoded_instr *decode(int the_instr) {
		decoded_instr *instr = (decoded_instr *)malloc(sizeof(decoded_instr));
		/* decodifica */
		instr->format = getbits(the_instr,31,30); /* Instruction format (2 bits) */
		instr->opcode = getbits(the_instr,29,26); /* Opcode (4 bits) */
		instr->dest   = getbits(the_instr,25,21); /* Destination register */
		instr->src1   = getbits(the_instr,20,16); /* Source register 1 */
		instr->src2   = getbits(the_instr,15,11); /* Source register 2 */
		instr->imm    = getbits(the_instr,15, 0); /* 16 bits immediate value */
		instr->addr   = getbits(the_instr,19, 0); /* 20 bits immediate address */
		instr->func   = getbits(the_instr,10, 0); /* 11 extra bits, used to encode extra info */
      normalizeValues(instr);
		return instr;
}		

int carry(decoded_instr *instr){
	return instr->func & 1;
}

int sign(decoded_instr *instr){
	return instr->func & 2;
}

int indirect_dest(decoded_instr *instr){
	return instr->func & 4;
}

int indirect_src2(decoded_instr *instr){
	return instr->func & 8;
}

void print(FILE* file, decoded_instr *instr){
		  /* Debug printf, stampa l'istruzione corrente */
      fprintf(file,"%s R%d, R%d, R%d or imm %d\n"
            , names[instr->format][instr->opcode], instr->dest
                  , instr->src1, instr->src2, instr->imm);
}

void normalizeValues(decoded_instr *instr)
{
   instr->imm = (instr->imm << 16);
   instr->imm = (instr->imm >> 16);
   instr->addr = (instr->addr << 12);
   instr->addr = (instr->addr >> 12);
}
