/**
  * @brief Saves the correct opcode and all operands of the current instruction.
  * @param[in] opcode The binary target specific opcode.
  * @param[in,out] instruction The instruction which shall be saved.
  */
static void saveInstruction(uint32_t opcode, sparc_instruction* instruction) {

	int sim_opcode = getOpcode(opcode);
	int dst_reg;
	int src1_reg;
	int src2_reg;
	int immediate;
	int icc;

	static char errormsg[100]; 

	/* save opcode */
	instruction->opcode = sim_opcode;

	/* save operands */
	switch (sim_opcode) {

		/* calls only have a displacement: */
		case CALL:
		
			immediate = GET_DISP30(opcode);
			/* sign extension of displacement */
			if (immediate & (1<<29)) {
				immediate |= ((1<<30)|(1<<31));
			}
			/* save call displacement as operand */
			instruction->num_operands = 1;
			instruction->operands = malloc(sizeof(sparc_operand));

			/* memory allocation OK? */
			if (!(instruction->operands)) {
				gen_simulator->cleanUp();
				simerror("Could not allocate memory for instruction operands!");
			}

			instruction->operands[0].type = OPERAND_TYPE_LABEL_ADDRESS;
			/* label address is (absolute) instruction number */
			instruction->operands[0].value.labeladdress = (unsigned) ((int) instruction->instr_no + immediate);
			break;
		
		/* handle branch instructions */
		case BRANCH:
			immediate = GET_IMM22(opcode);
			/* sign extension of displacement */ 
			if (immediate & (1<<21)) {
				immediate |= 0xFFC00000; 
			}
			icc = GET_CC(opcode);

			instruction->num_operands = 2;
			instruction->operands = malloc(sizeof(sparc_operand)*2);

			/* memory allocation OK? */
			if (!(instruction->operands)) {
				gen_simulator->cleanUp();
				simerror("Could not allocate memory for instruction operands!");
			}
			
			instruction->operands[0].type = OPERAND_TYPE_LABEL_ADDRESS;
			/* label address is (absolute) instruction number */
			instruction->operands[0].value.labeladdress = (unsigned) ((int) instruction->instr_no + immediate);

			/* save integer condition code */
			instruction->operands[1].type = OPERAND_TYPE_ICC;
			instruction->operands[1].value.icc = icc;

			break;

		/* handle sethi and nop instructions */
		case SETHI:
			immediate = GET_IMM22(opcode);
			dst_reg = GET_RD(opcode);

			/* if destination register and immediate are zero, it's a NOP instruction*/
			if (!dst_reg && !immediate) {

				instruction->num_operands = 0;
				instruction->opcode = NOP;

			} else {

				instruction->num_operands = 2;

				instruction->operands = malloc(sizeof(sparc_operand)*2);

				/* memory allocation OK? */
				if (!(instruction->operands)) {
					gen_simulator->cleanUp();
					simerror("Could not allocate memory for instruction operands!");
				}

				instruction->operands[0].type = OPERAND_TYPE_REGISTER;
				instruction->operands[0].value.reg = dst_reg;

				instruction->operands[1].type = OPERAND_TYPE_IMM22;
				instruction->operands[1].value.imm22 = immediate;

			}
			break;

		case RD:
			dst_reg = GET_RD(opcode);
			src1_reg = GET_RS1(opcode);
			if (src1_reg != Y_REGISTER_NO) {
				gen_simulator->cleanUp();
				simerror("Unknown source register for rd instruction!");
			}

			instruction->num_operands = 2;

			instruction->operands = malloc(sizeof(sparc_operand)*2);

			/* memory allocation OK? */
			if (!(instruction->operands)) {
				gen_simulator->cleanUp();
				simerror("Could not allocate memory for instruction operands!");
			}

			instruction->operands[0].type = OPERAND_TYPE_REGISTER;
			instruction->operands[0].value.reg = dst_reg;

			instruction->operands[1].type = OPERAND_TYPE_REGISTER;
			instruction->operands[1].value.reg = src1_reg;
			break;

		/* nothing to do for sim-cylce instruction */
		case CYCLE_PRINT:
		case CYCLE_CLEAR:
			instruction->num_operands = 0;
			break;

		/* terminate on unkown instruction */
		case UNKNOWN:
			gen_simulator->cleanUp();
			snprintf(errormsg, 100, "Encountered unknown opcode at instruction no %d!", 
				instruction->instr_no);
			simerror(errormsg);
			break;

		/* all other instructions have exactly three operands */
		default:

			dst_reg = GET_RD(opcode);
			src1_reg = GET_RS1(opcode);

			instruction->num_operands = 3;			
			
			instruction->operands = malloc(sizeof(sparc_operand)*3);

			/* memory allocation OK? */
			if (!(instruction->operands)) {
				gen_simulator->cleanUp();
				simerror("Could not allocate memory for instruction operands!");
			}

			instruction->operands[0].type = OPERAND_TYPE_REGISTER;
			instruction->operands[0].value.reg = dst_reg;

			instruction->operands[1].type = OPERAND_TYPE_REGISTER;
			instruction->operands[1].value.reg = src1_reg;

			/* is third operand an immediate? */
			if (GET_I(opcode)) {
				immediate = GET_SIMM13(opcode);
				/* sign extension of immediate */
				if (immediate & (1<<12)) {
					immediate |= 0xFFFFE000;
				}
				instruction->operands[2].type = OPERAND_TYPE_SIMM13;
				instruction->operands[2].value.simm13 = immediate;
			} else {
				src2_reg = GET_RS2(opcode);
				instruction->operands[2].type = OPERAND_TYPE_REGISTER;
				instruction->operands[2].value.reg = src2_reg;
			}
			break;

	}


}
示例#2
0
static void episodic_store_full(
                           noble_being * local,
                           n_byte event,
                           n_int affect,
                           noble_simulation * local_sim,
                           n_byte2 name1, n_byte2 family1,
                           n_byte2 name2, n_byte2 family2,
                           n_byte2 arg,
                           n_byte food)
{
    episodic_memory * local_episodic = GET_EPI(local_sim, local);
    n_int replace;
    n_byte  old_event;
    n_byte2 old_time;
    n_byte2 new_time;

    if (local_episodic == 0L)
    {
        return;
    }

    if (being_awake_local(local_sim, local)==FULLY_ASLEEP) return;

    replace = episodic_memory_replace_index(event,affect,name1,family1,name2,family2,local,local_sim);

    if (replace == -1) return;

    old_event = local_episodic[replace].event;
    old_time = local_episodic[replace].time;
    
    /** insert the current event into the episodic memory */
    local_episodic[replace].event       = event;
    local_episodic[replace].affect      = (n_byte2)(affect+EPISODIC_AFFECT_ZERO);
    local_episodic[replace].location[0] = GET_X(local);
    local_episodic[replace].location[1] = GET_Y(local);
    local_episodic[replace].time        = new_time =local_sim->land->time;
    local_episodic[replace].date[0]     = local_sim->land->date[0];
    local_episodic[replace].date[1]     = local_sim->land->date[1];
    local_episodic[replace].first_name[BEING_MEETER]=name1;
    local_episodic[replace].family_name[BEING_MEETER]=family1;
    local_episodic[replace].first_name[BEING_MET]=name2;
    local_episodic[replace].family_name[BEING_MET]=family2;
    local_episodic[replace].food=food;
    local_episodic[replace].arg=arg;
    
    if ((event == 0) || (event>=EVENTS))
    {
        (void)SHOW_ERROR("Event outside scope");
    }
    
    if (local_logging)
    {
        if ((old_event != event) || ((old_time+10) < (new_time))) /* this may need to be changed */
        {
            n_string_block description;
            n_string_block str;
            n_string_block time;
            n_string_block combination = {0};
            n_int social_event;
            
            being_name((FIND_SEX(GET_I(local)) == SEX_FEMALE), GET_NAME(local_sim, local), GET_FAMILY_FIRST_NAME(local_sim, local), GET_FAMILY_SECOND_NAME(local_sim, local), str);

            social_event = episode_description(local_sim, local, replace, description);
            
            if ((local_social == 1) && (social_event == 0))
            {
                return;
            }
            
            io_time_to_string(time, local_sim->land->time, local_sim->land->date[0], local_sim->land->date[1]);
            
            io_three_string_combination(combination, time, str, description, 35);
                        
            (*local_logging)(combination);
        }
    }
}