void opc_cmp_handler(char *opd1,char *opd2,char *offset,char *immi){ int ans; int dec_opd2=bintodec(opd2); if(immi[1]=='0'){ if(immi[0]=='0'){ int dec_opd1=bintodec(opd1); int val_opd2=get_reg_val(dec_opd2); ans=val_opd2-get_reg_val(dec_opd1); } else{ int dec_im_opd1=bintodec(opd1); ans=get_reg_val(dec_opd2)-dec_im_opd1; } } else{ int dec_off=bintodec(offset); if(immi[0]=='0'){ int dec_opd1=bintodec(opd1); ans=get_mem_val(dec_opd2+dec_off)-get_reg_val(dec_opd1); } else{ int dec_im_opd1=bintodec(opd1); ans=get_mem_val(dec_opd2+dec_off)-dec_im_opd1; } } if(ans==0){ set_reg_val(regfile+R_FLAGS,0); } else if(ans>0){ set_reg_val(regfile+R_FLAGS,1); } else{ set_reg_val(regfile+R_FLAGS,2); } }
void init_regs(int k){ if(k==0){ int i; for(i=0;i<32;i++){ set_reg_val(regfile+i,0); } set_reg_val(regfile+8,100); } }
/* May need to disable updating of memory & condition codes */ static void update_state(bool_t update_mem, bool_t update_cc) { /* Writeback(s): If either register is REG_NONE, write will have no effect . Order of two writes determines semantics of popl %esp. According to ISA, %esp will get popped value */ if (wb_destE != REG_NONE) { sim_log("Writeback: Wrote 0x%x to register %s\n", wb_valE, reg_name(wb_destE)); set_reg_val(reg, wb_destE, wb_valE); } if (wb_destM != REG_NONE) { sim_log("Writeback: Wrote 0x%x to register %s\n", wb_valM, reg_name(wb_destM)); set_reg_val(reg, wb_destM, wb_valM); } /* Memory write */ if (mem_write && !update_mem) { sim_log("Disabled write of 0x%x to address 0x%x\n", mem_data, mem_addr); } if (update_mem && mem_write) { if (!set_word_val(mem, mem_addr, mem_data)) { sim_log("Couldn't write to address 0x%x\n", mem_addr); } else { sim_log("Wrote 0x%x to address 0x%x\n", mem_data, mem_addr); #ifdef HAS_GUI if (gui_mode) { if (mem_addr % 4 != 0) { /* Just did a misaligned write. Need to display both words */ word_t align_addr = mem_addr & ~0x3; word_t val; get_word_val(mem, align_addr, &val); set_memory(align_addr, val); align_addr+=4; get_word_val(mem, align_addr, &val); set_memory(align_addr, val); } else { set_memory(mem_addr, mem_data); } } #endif } } if (update_cc) cc = cc_in; }
/* May need to disable updating of memory & condition codes */ static void update_state(bool_t update_mem, bool_t update_cc) { /* Writeback(s): If either register is REG_NONE, write will have no effect . Order of two writes determines semantics of popl %esp. According to ISA, %esp will get popped value */ if (wb_destE != REG_NONE) { sim_log("\tWriteback: Wrote 0x%x to register %s\n", wb_valE, reg_name(wb_destE)); set_reg_val(reg, wb_destE, wb_valE); //printf("set_reg_valE %d %d %d\n", PSIM_ID, wb_destE, wb_valE); //fflush(stdout); } if (wb_destM != REG_NONE && wb_testM == REG_NONE) { sim_log("\tWriteback: Wrote 0x%x to register %s\n", wb_valM, reg_name(wb_destM)); set_reg_val(reg, wb_destM, wb_valM); //printf("set_reg_valM %d %d %d\n", PSIM_ID, wb_destM, wb_valM); //fflush(stdout); } /* Memory write */ if(wb_testM != REG_NONE){ set_reg_val(reg, wb_testM, wb_valM); printf("PSIM_ID %d test_result: %d on %d\n", PSIM_ID, wb_valM, mem_test_address); //fflush(stdout); } if (mem_write && !update_mem) { sim_log("\tDisabled write of 0x%x to address 0x%x\n", mem_data, mem_addr); } if (update_mem && mem_write) { // printf("WRITE: %d %d\n", mem_addr, mem_data); if (!set_word_val(mem, mem_addr, mem_data)) { sim_log("\tCouldn't write to address 0x%x\n", mem_addr); } else { sim_log("\tWrote 0x%x to address 0x%x\n", mem_data, mem_addr); } /* int ans; printf("%d %d\n",mem_addr, mem_data); int b = get_word_val(mem, mem_addr, &ans); printf("%d\n", ans); */ } if (update_cc) cc = cc_in; }
void execute(_decoder_output *decoded_instr){ instr_handlers[0]=opc_add_handler; instr_handlers[1]=opc_sub_handler; instr_handlers[2]=opc_mov_handler; instr_handlers[3]=opc_and_handler; instr_handlers[4]=opc_xor_handler; instr_handlers[5]=opc_or_handler; instr_handlers[6]=opc_cmp_handler; instr_handlers[8]=opc_xchange_handler; instr_handlers[9]=opc_push_handler; instr_handlers[10]=opc_pop_handler; instr_handlers[11]=opc_mul_handler; instr_handlers[12]=opc_mul_handler; instr_handlers[13]=opc_div_handler; instr_handlers[14]=opc_div_handler; instr_handlers[15]=opc_jmp_handler; instr_handlers[16]=opc_je_handler; instr_handlers[17]=opc_jne_handler; instr_handlers[18]=opc_jg_handler; instr_handlers[19]=opc_jge_handler; instr_handlers[20]=opc_jl_handler; instr_handlers[21]=opc_jle_handler; instr_handlers[22]=opc_jmp_handler; if(clock>2){ int dec_opc=bintodec(decoded_instr->opc); if(dec_opc==63){ printf("\n\npc is %d\n",get_reg_val(15)); printf("\n\nregister file is\n"); print(regfile); printf("\n\nmemory is\n"); print(mem); printf("exiting"); exit(0); } instr_handlers[dec_opc](decoded_instr->opd1,decoded_instr->opd2,decoded_instr->offset,decoded_instr->immi); } switch(pending_bds){ case 2: set_reg_val(regfile+REG_PC,get_reg_val(REG_PC)+1); pending_bds--; break; case 1: set_reg_val(regfile+REG_PC,get_reg_val(REG_NEXTPC)-2); pending_bds--; break; case 0: set_reg_val(regfile+REG_PC,get_reg_val(REG_PC)+1); break; } }
/* Update the processor state */ static exc_t update_state() { exc_t status = EXC_NONE; if (plusmode) { prev_icode = prev_icode_in; prev_ifun = prev_ifun_in; prev_valc = prev_valc_in; prev_valm = prev_valm_in; prev_valp = prev_valp_in; prev_bcond = prev_bcond_in; } else { pc = pc_in; } cc = cc_in; /* Writeback */ if (destE != REG_NONE) set_reg_val(reg, destE, vale); if (destM != REG_NONE) set_reg_val(reg, destM, valm); if (mem_write) { if (!set_word_val(mem, mem_addr, mem_data)) { sim_log("Couldn't write to address 0x%x\n", mem_addr); status = EXC_ADDR; } else { sim_log("Wrote 0x%x to address 0x%x\n", mem_data, mem_addr); #ifdef HAS_GUI if (gui_mode) { if (mem_addr % 4 != 0) { /* Just did a misaligned write. Need to display both words */ word_t align_addr = mem_addr & ~0x3; word_t val; get_word_val(mem, align_addr, &val); set_memory(align_addr, val); align_addr+=4; get_word_val(mem, align_addr, &val); set_memory(align_addr, val); } else { set_memory(mem_addr, mem_data); } } #endif// HAS_GUI } } return status; }
void opc_pop_handler(char *opd1,char *opd2,char *offset,char *immi){ int ans; int dec_opd2=bintodec(opd2); int val_esp=get_reg_val(8); if(immi[1]=='0'){ if(immi[0]=='0'){ int dec_opd1=bintodec(opd1); int val_mem=get_mem_val(mem+val_esp); ans=val_mem; set_reg_val(regfile+dec_opd1,ans); } } int new_esp=get_reg_val(8)+1; set_reg_val(regfile+8,new_esp); }
int execute_command(PVRDMADev *dev) { int err = 0xFFFF; DSRInfo *dsr_info; dsr_info = &dev->dsr_info; pr_dbg("cmd=%d\n", dsr_info->req->hdr.cmd); if (dsr_info->req->hdr.cmd >= sizeof(cmd_handlers) / sizeof(struct cmd_handler)) { pr_dbg("Unsupported command\n"); goto out; } if (!cmd_handlers[dsr_info->req->hdr.cmd].exec) { pr_dbg("Unsupported command (not implemented yet)\n"); goto out; } err = cmd_handlers[dsr_info->req->hdr.cmd].exec(dev, dsr_info->req, dsr_info->rsp); out: set_reg_val(dev, PVRDMA_REG_ERR, err); post_interrupt(dev, INTR_VEC_CMD_RING); return (err == 0) ? 0 : -EINVAL; }
int load_program(char *fname){ FILE *ifp; char ch; int i=0,j=0; ifp= fopen(fname,"r"); while((ch=fgetc(ifp))!=EOF){ if(ch=='\n' && j==0) continue; if(ch=='\n'){ j++; ch='\0'; mem[i].data[j]=ch; i++; j=0; } else{ mem[i].data[j]=ch; j++; } } if(j!=0){ mem[i].data[j]='\0'; } set_reg_val(mem+i,0); fclose(ifp); return 0; }
void init_memory(int k){ if(k==0){ int i; for(i=0;i<216;i++){ set_reg_val(mem+i,0); } } }
void opc_jmp_handler(char *opd1,char *opd2,char *offset,char *immi){ int ans; int dec_opd2=bintodec(opd2); if(immi[1]=='0'){ if(immi[0]=='0'){ int dec_opd1=bintodec(opd1); ans=get_reg_val(dec_opd1)-1; set_reg_val(regfile+16,ans); } else{ int dec_im_opd1=bintodec(opd1); ans=dec_im_opd1-1; set_reg_val(regfile+16,ans); } } pending_bds=2; }
void opc_div_handler(char *opd1,char *opd2,char *offset,char *immi){ int ans; int dec_opd2=bintodec(opd2); if(immi[1]=='0'){ if(immi[0]=='0'){ int dec_opd1=bintodec(opd1); int val_eax=get_reg_val(0); ans=val_eax/get_reg_val(dec_opd1); set_reg_val(regfile+0,ans); } else{ int dec_im_opd1=bintodec(opd1); ans=get_reg_val(0)/dec_im_opd1; set_reg_val(regfile+0,ans); } } }
void start_cpu(void){ int RESET_VEC_ADDR=0; set_reg_val(regfile+16,RESET_VEC_ADDR); //NEXT_PC set_reg_val(regfile+15,get_reg_val(REG_NEXTPC)-2); //PC pending_bds =0 ; while(1){ if(no_of_ins-1>stop_ins){ printf("\n\npc is %d\n",get_reg_val(15)); printf("\n\nregister file is\n"); print(regfile); printf("\n\nmemory is\n"); print(mem); exit(0); } start_new_cycle(); exec_pipeline_stages(); } }
void opc_push_handler(char *opd1,char *opd2,char *offset,char *immi){ int ans; int dec_opd2=bintodec(opd2); int val_esp=get_reg_val(8); if(immi[1]=='0'){ if(immi[0]=='0'){ int dec_opd1=bintodec(opd1); ans=get_reg_val(dec_opd1); set_reg_val(mem+val_esp,ans); } else{ int dec_im_opd1=bintodec(opd1); ans=dec_im_opd1; set_reg_val(mem+val_esp,ans); } } int new_esp=get_reg_val(8)-1; set_reg_val(regfile+8,new_esp); }
void decode( char *instr, _decoder_output *out){ if(instr){ get_opcode(instr,out); get_operands(instr,out); } else{ out->opc[0] = '\0'; } set_reg_val(regfile+REG_NEXTPC,get_reg_val(REG_NEXTPC)+1); }
int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) { int r = 0; union kvmppc_one_reg val; int size; size = one_reg_size(reg->id); if (size > sizeof(val)) return -EINVAL; r = kvmppc_get_one_reg(vcpu, reg->id, &val); if (r == -EINVAL) { r = 0; switch (reg->id) { #ifdef CONFIG_ALTIVEC case KVM_REG_PPC_VR0 ... KVM_REG_PPC_VR31: if (!cpu_has_feature(CPU_FTR_ALTIVEC)) { r = -ENXIO; break; } vcpu->arch.vr.vr[reg->id - KVM_REG_PPC_VR0] = val.vval; break; case KVM_REG_PPC_VSCR: if (!cpu_has_feature(CPU_FTR_ALTIVEC)) { r = -ENXIO; break; } vcpu->arch.vr.vscr.u[3] = set_reg_val(reg->id, val); break; case KVM_REG_PPC_VRSAVE: if (!cpu_has_feature(CPU_FTR_ALTIVEC)) { r = -ENXIO; break; } vcpu->arch.vrsave = set_reg_val(reg->id, val); break; #endif /* CONFIG_ALTIVEC */ default: r = -EINVAL; break; } }
/* Update the processor state */ static void update_state() { if (plusmode) { prev_icode = prev_icode_in; prev_ifun = prev_ifun_in; prev_valc = prev_valc_in; prev_valm = prev_valm_in; prev_valp = prev_valp_in; prev_bcond = prev_bcond_in; } else { pc = pc_in; } cc = cc_in; /* Writeback */ if (destE != REG_NONE) set_reg_val(reg, destE, vale); if (destM != REG_NONE) set_reg_val(reg, destM, valm); if (mem_write) { /* Should have already tested this address */ set_word_val(mem, mem_addr, mem_data); sim_log("Wrote 0x%x to address 0x%x\n", mem_data, mem_addr); #ifdef HAS_GUI if (gui_mode) { if (mem_addr % 4 != 0) { /* Just did a misaligned write. Need to display both words */ word_t align_addr = mem_addr & ~0x3; word_t val; get_word_val(mem, align_addr, &val); set_memory(align_addr, val); align_addr+=4; get_word_val(mem, align_addr, &val); set_memory(align_addr, val); } else { set_memory(mem_addr, mem_data); } } #endif /* HAS_GUI */ } }
void main(void) { unsigned hder = 0, new_hder = 0; unsigned crt_address; BIOS_VAR _far *bios_var_ptr; unsigned i = 0; // Получаем указатель на область переменных видеофункций BIOS bios_var_ptr = (BIOS_VAR _far *) FP_MAKE(0x0000, 0x0410); // Определяем адрес порта индексного регистра контроллера ЭЛТ crt_address = bios_var_ptr->crt_address; disable_protection_mode(crt_address); // Читаем значение HDER hder = get_reg_val(crt_address, HDER); // Очищаем экран clrscr(); printf("\nТекущее значение HDER регистра %d\n", hder); for (i = 0; i < hder; i++) { printf("*"); } printf("\nВведите длину отображаемой части горизонтальной развертки:"); scanf("%d", &new_hder); // Устанавливаем новое значение set_reg_val(crt_address, HDER, new_hder); printf("\nДля завершения программы нажмите любую клавишу"); getch(); // Восстанавливаем значение по умолчанию set_reg_val(crt_address, HDER, hder); }
void opc_xchange_handler(char *opd1,char *opd2,char *offset,char *immi){ int ans1,ans2; int dec_opd2=bintodec(opd2); if(immi[1]=='0'){ if(immi[0]=='0'){ int dec_opd1=bintodec(opd1); int val_opd2=get_reg_val(dec_opd2); ans1=get_reg_val(dec_opd1); set_reg_val(regfile+dec_opd2,ans1); ans2=get_reg_val(dec_opd2); set_reg_val(regfile+dec_opd1,ans2); } } else{ int dec_off=bintodec(offset); if(immi[0]=='0'){ int dec_opd1=bintodec(opd1); ans1=get_mem_val(dec_opd2+dec_off)+get_reg_val(dec_opd1); set_reg_val(mem+dec_opd2+dec_off,ans1); ans2=get_mem_val(dec_opd2+dec_off); set_reg_val(regfile+dec_opd1,ans2); } } }
/* Execute single instruction. Return exception condition. */ exc_t step_state(state_ptr s, FILE *error_file) { word_t argA, argB; byte_t byte0 = 0; byte_t byte1 = 0; itype_t hi0; alu_t lo0; reg_id_t hi1 = REG_NONE; reg_id_t lo1 = REG_NONE; bool_t ok1 = TRUE; word_t cval; word_t okc = TRUE; word_t val, dval; bool_t need_regids; bool_t need_imm; word_t ftpc = s->pc; if (!get_byte_val(s->m, ftpc, &byte0)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return EXC_ADDR; } ftpc++; hi0 = HI4(byte0); lo0 = LO4(byte0); need_regids = (hi0 == I_RRMOVL || hi0 == I_ALU || hi0 == I_PUSHL || hi0 == I_POPL || hi0 == I_IRMOVL || hi0 == I_RMMOVL || hi0 == I_MRMOVL || hi0 == I_ALUI); if (need_regids) { ok1 = get_byte_val(s->m, ftpc, &byte1); ftpc++; hi1 = HI4(byte1); lo1 = LO4(byte1); } need_imm = (hi0 == I_IRMOVL || hi0 == I_RMMOVL || hi0 == I_MRMOVL || hi0 == I_JXX || hi0 == I_CALL || hi0 == I_ALUI); if (need_imm) { okc = get_word_val(s->m, ftpc, &cval); ftpc += 4; } switch (hi0) { case I_NOP: s->pc = ftpc; break; case I_HALT: s->pc = ftpc; return EXC_HALT; break; case I_RRMOVL: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return EXC_ADDR; } if (hi1 >= 8) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, hi1); return EXC_INSTR; } if (lo1 >= 8) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, lo1); return EXC_INSTR; } val = get_reg_val(s->r, hi1); set_reg_val(s->r, lo1, val); s->pc = ftpc; break; #if 0 case I_IRMOVL: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return EXC_ADDR; } if (!okc) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address", s->pc); return EXC_INSTR; } if (lo1 >= 8) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, lo1); return EXC_INSTR; } set_reg_val(s->r, lo1, cval); s->pc = ftpc; break; #endif case I_RMMOVL: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return EXC_ADDR; } if (!okc) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return EXC_INSTR; } if (hi1 >= 8) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, hi1); return EXC_INSTR; } if (lo1 < 8) cval += get_reg_val(s->r, lo1); val = get_reg_val(s->r, hi1); if (!set_word_val(s->m, cval, val)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid data address 0x%x\n", s->pc, cval); return EXC_ADDR; } s->pc = ftpc; break; case I_MRMOVL: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return EXC_ADDR; } if (!okc) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction addres\n", s->pc); return EXC_INSTR; } if (hi1 >= 8) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, hi1); return EXC_INSTR; } if (lo1 < 8) cval += get_reg_val(s->r, lo1); if (!get_word_val(s->m, cval, &val)) return EXC_ADDR; set_reg_val(s->r, hi1, val); s->pc = ftpc; break; case I_ALU: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return EXC_ADDR; } argA = get_reg_val(s->r, hi1); argB = get_reg_val(s->r, lo1); val = compute_alu(lo0, argA, argB); set_reg_val(s->r, lo1, val); s->cc = compute_cc(lo0, argA, argB); s->pc = ftpc; break; case I_JXX: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return EXC_ADDR; } if (!okc) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return EXC_ADDR; } if (take_branch(s->cc, lo0)) s->pc = cval; else s->pc = ftpc; break; #if 0 case I_CALL: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return EXC_ADDR; } if (!okc) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return EXC_ADDR; } val = get_reg_val(s->r, REG_ESP) - 4; set_reg_val(s->r, REG_ESP, val); if (!set_word_val(s->m, val, ftpc)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid stack address 0x%x\n", s->pc, val); return EXC_ADDR; } s->pc = cval; break; case I_RET: /* Return Instruction. Pop address from stack */ dval = get_reg_val(s->r, REG_ESP); if (!get_word_val(s->m, dval, &val)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid stack address 0x%x\n", s->pc, dval); return EXC_ADDR; } set_reg_val(s->r, REG_ESP, dval + 4); s->pc = val; break; #endif case I_PUSHL: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return EXC_ADDR; } if (hi1 >= 8) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, hi1); return EXC_INSTR; } val = get_reg_val(s->r, hi1); dval = get_reg_val(s->r, REG_ESP) - 4; set_reg_val(s->r, REG_ESP, dval); if (!set_word_val(s->m, dval, val)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid stack address 0x%x\n", s->pc, dval); return EXC_ADDR; } s->pc = ftpc; break; case I_POPL: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return EXC_ADDR; } if (hi1 >= 8) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, hi1); return EXC_INSTR; } dval = get_reg_val(s->r, REG_ESP); set_reg_val(s->r, REG_ESP, dval+4); if (!get_word_val(s->m, dval, &val)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid stack address 0x%x\n", s->pc, dval); return EXC_ADDR; } set_reg_val(s->r, hi1, val); s->pc = ftpc; break; case I_LEAVE: dval = get_reg_val(s->r, REG_EBP); set_reg_val(s->r, REG_ESP, dval+4); if (!get_word_val(s->m, dval, &val)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid stack address 0x%x\n", s->pc, dval); return EXC_ADDR; } set_reg_val(s->r, REG_EBP, val); s->pc = ftpc; break; #if 0 case I_ALUI: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return EXC_ADDR; } if (!okc) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address", s->pc); return EXC_INSTR; } if (lo1 >= 8) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, lo1); return EXC_INSTR; } argB = get_reg_val(s->r, lo1); val = argB + cval; set_reg_val(s->r, lo1, val); s->cc = compute_cc(A_ADD, cval, argB); s->pc = ftpc; break; #endif default: if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction %.2x\n", s->pc, byte0); return EXC_INSTR; } return EXC_NONE; }
inline bool set_reg_val(const char *regname, ulonglong ival) { regval_t regval; regval.ival = ival; return set_reg_val(regname, ®val); }
/* * nexti: execute single instruction and return status. * args * sim: the y86 image with PC, register and memory * * return * STAT_AOK: continue * STAT_HLT: halt * STAT_ADR: invalid instruction address * STAT_INS: invalid instruction, register id, data address, stack address, ... */ stat_t nexti(y86sim_t *sim) { byte_t codefun = 0; itype_t icode; alu_t ifun; long_t next_pc = sim->pc; regid_t rA = REG_NONE; regid_t rB = REG_NONE; long_t im_value = 0; /* get code and function (1 byte) */ if (!get_byte_val(sim->m, next_pc, &codefun)) { err_print("PC = 0x%x, Invalid instruction address", sim->pc); return STAT_ADR; } icode = GET_ICODE(codefun); ifun = GET_FUN(codefun); next_pc++; /* get registers if needed (1 byte) */ byte_t reg = 0; switch (icode) { case I_RRMOVL: case I_IRMOVL: case I_RMMOVL: case I_MRMOVL: case I_ALU: case I_PUSHL: case I_POPL: if(!get_byte_val(sim->m, next_pc, ®)) { err_print("PC = 0x%x, Invalid instruction address", sim->pc); return STAT_ADR; } rA = GET_REGA(reg); rB = GET_REGB(reg); next_pc++; case I_HALT:case I_NOP:case I_JMP:case I_CALL:case I_RET:default: break; } /* get immediate if needed (4 bytes) */ switch(icode) { case I_IRMOVL: case I_RMMOVL: case I_MRMOVL: case I_JMP: case I_CALL: if(!get_long_val(sim->m, next_pc, &im_value)) { err_print("PC = 0x%x, Invalid instruction address", sim->pc); return STAT_ADR; } next_pc += 4; case I_HALT:case I_NOP:case I_RRMOVL:case I_ALU: case I_RET:case I_PUSHL:case I_POPL:default: break; } /* execute the instruction */ switch (icode) { case I_HALT: /* 0:0 */ return STAT_HLT; break; case I_NOP: /* 1:0 */ sim->pc = next_pc; break; case I_RRMOVL:/* 2:x regA:regB */ { long_t rr_temp = get_reg_val(sim->r, rA); if (cond_doit(sim->cc, ifun)) set_reg_val(sim->r, rB, rr_temp); sim->pc = next_pc; break; } case I_IRMOVL: /* 3:0 F:regB imm */ { set_reg_val(sim->r, rB, im_value); sim->pc = next_pc; break; } case I_RMMOVL: /* 4:0 regA:regB imm */ { long_t rm_temp_rA = get_reg_val(sim->r, rA); long_t rm_temp_rB = get_reg_val(sim->r, rB); set_long_val(sim->m, im_value+rm_temp_rB, rm_temp_rA); sim->pc = next_pc; break; } case I_MRMOVL: /* 5:0 regB:regA imm */ { long_t mr_temp_rB = get_reg_val(sim->r, rB); long_t temp_val = 0; if(!get_long_val(sim->m, im_value+mr_temp_rB, &temp_val)) { err_print("PC = 0x%x, Invalid data address 0x%x", sim->pc, im_value+mr_temp_rB); return STAT_ADR; } set_reg_val(sim->r, rA, temp_val); sim->pc = next_pc; break; } case I_ALU: /* 6:x regA:regB */ { long_t rA_val = get_reg_val(sim->r, rA); long_t rB_val = get_reg_val(sim->r, rB); long_t alu_result = 0; switch (ifun) { case A_ADD:case A_SUB:case A_AND:case A_XOR: alu_result = compute_alu(ifun, rA_val, rB_val); set_reg_val(sim->r, rB, alu_result); break; case A_NONE:default: return STAT_INS; } sim->cc = compute_cc(ifun, rA_val, rB_val, alu_result); sim->pc = next_pc; break; } case I_JMP: /* 7:x imm */ { if (cond_doit(sim->cc, ifun)) sim->pc = im_value; else sim->pc=next_pc; break; } case I_CALL: /* 8:x imm */ { long_t esp = get_reg_val(sim->r, REG_ESP); esp -= 4; set_reg_val(sim->r, REG_ESP, esp); if (esp < 0) { err_print("PC = 0x%x, Invalid stack address 0x%x", sim->pc, esp); return STAT_ADR; } set_long_val(sim->m, esp, next_pc); sim->pc = im_value; break; } case I_RET: /* 9:0 */ { long_t esp = get_reg_val(sim->r, REG_ESP); long_t return_value = 0; if(!get_long_val(sim->m, esp, &return_value)) { err_print("PC = 0x%x, Invalid data address 0x%x", sim->pc, esp); return STAT_ADR; } esp += 4; set_reg_val(sim->r, REG_ESP, esp); if (esp < 0) { err_print("PC = 0x%x, Invalid stack address 0x%x", sim->pc, esp); return STAT_ADR; } sim->pc = return_value; break; } case I_PUSHL: /* A:0 regA:F */ { long_t esp = get_reg_val(sim->r, REG_ESP); long_t rA_value = get_reg_val(sim->r, rA); esp -= 4; set_reg_val(sim->r, REG_ESP, esp); if (esp < 0) { err_print("PC = 0x%x, Invalid stack address 0x%x", sim->pc, esp); return STAT_ADR; } set_long_val(sim->m, esp, rA_value); sim->pc = next_pc; break; } case I_POPL: /* B:0 regA:F */ { long_t esp = get_reg_val(sim->r, REG_ESP); long_t temp_value = 0; if(!get_long_val(sim->m, esp, &temp_value)) { err_print("PC = 0x%x, Invalid instruction address", esp); return STAT_ADR; } esp += 4; set_reg_val(sim->r, REG_ESP, esp); if (esp < 0) { err_print("PC = 0x%x, Invalid stack address 0x%x", sim->pc, esp); return STAT_ADR; } set_reg_val(sim->r, rA, temp_value); sim->pc = next_pc; break; } return STAT_INS; /* unsupported now, replace it with your implementation */ break; default: err_print("PC = 0x%x, Invalid instruction %.2x", sim->pc, codefun); return STAT_INS; } return STAT_AOK; }
/* Execute single instruction. Return status. */ stat_t step_state(state_ptr s, FILE *error_file) { word_t argA, argB; byte_t byte0 = 0; byte_t byte1 = 0; itype_t hi0; alu_t lo0; reg_id_t hi1 = REG_NONE; reg_id_t lo1 = REG_NONE; bool_t ok1 = TRUE; word_t cval = 0; word_t okc = TRUE; word_t val, dval; bool_t need_regids; bool_t need_imm; word_t ftpc = s->pc; /* Fall-through PC */ if (!get_byte_val(s->m, ftpc, &byte0)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_ADR; } ftpc++; hi0 = HI4(byte0); lo0 = LO4(byte0); need_regids = (hi0 == I_RRMOVL || hi0 == I_ALU || hi0 == I_PUSHL || hi0 == I_POPL || hi0 == I_IRMOVL || hi0 == I_RMMOVL || hi0 == I_MRMOVL || hi0 == I_IADDL || hi0 == I_ISUBL); if (need_regids) { ok1 = get_byte_val(s->m, ftpc, &byte1); ftpc++; hi1 = HI4(byte1); lo1 = LO4(byte1); } need_imm = (hi0 == I_IRMOVL || hi0 == I_RMMOVL || hi0 == I_MRMOVL || hi0 == I_JMP || hi0 == I_CALL || hi0 == I_IADDL || hi0 == I_ISUBL); if (need_imm) { okc = get_word_val(s->m, ftpc, &cval); ftpc += 4; } switch (hi0) { case I_NOP: s->pc = ftpc; break; case I_HALT: return STAT_HLT; break; case I_RRMOVL: /* Both unconditional and conditional moves */ if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_ADR; } if (!reg_valid(hi1)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, hi1); return STAT_INS; } if (!reg_valid(lo1)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, lo1); return STAT_INS; } val = get_reg_val(s->r, hi1); if (cond_holds(s->cc, lo0)) set_reg_val(s->r, lo1, val); s->pc = ftpc; break; case I_IRMOVL: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_ADR; } if (!okc) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address", s->pc); return STAT_INS; } if (!reg_valid(lo1)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, lo1); return STAT_INS; } set_reg_val(s->r, lo1, cval); s->pc = ftpc; break; case I_RMMOVL: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_ADR; } if (!okc) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_INS; } if (!reg_valid(hi1)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, hi1); return STAT_INS; } if (reg_valid(lo1)) cval += get_reg_val(s->r, lo1); val = get_reg_val(s->r, hi1); if (!set_word_val(s->m, cval, val)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid data address 0x%x\n", s->pc, cval); return STAT_ADR; } s->pc = ftpc; break; case I_MRMOVL: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_ADR; } if (!okc) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction addres\n", s->pc); return STAT_INS; } if (!reg_valid(hi1)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, hi1); return STAT_INS; } if (reg_valid(lo1)) cval += get_reg_val(s->r, lo1); if (!get_word_val(s->m, cval, &val)) return STAT_ADR; set_reg_val(s->r, hi1, val); s->pc = ftpc; break; case I_ALU: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_ADR; } argA = get_reg_val(s->r, hi1); argB = get_reg_val(s->r, lo1); val = compute_alu(lo0, argA, argB); set_reg_val(s->r, lo1, val); s->cc = compute_cc(lo0, argA, argB); s->pc = ftpc; break; case I_JMP: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_ADR; } if (!okc) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_ADR; } if (cond_holds(s->cc, lo0)) s->pc = cval; else s->pc = ftpc; break; case I_CALL: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_ADR; } if (!okc) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_ADR; } val = get_reg_val(s->r, REG_ESP) - 4; set_reg_val(s->r, REG_ESP, val); if (!set_word_val(s->m, val, ftpc)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid stack address 0x%x\n", s->pc, val); return STAT_ADR; } s->pc = cval; break; case I_RET: /* Return Instruction. Pop address from stack */ dval = get_reg_val(s->r, REG_ESP); if (!get_word_val(s->m, dval, &val)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid stack address 0x%x\n", s->pc, dval); return STAT_ADR; } set_reg_val(s->r, REG_ESP, dval + 4); s->pc = val; break; case I_PUSHL: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_ADR; } if (!reg_valid(hi1)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, hi1); return STAT_INS; } val = get_reg_val(s->r, hi1); dval = get_reg_val(s->r, REG_ESP) - 4; set_reg_val(s->r, REG_ESP, dval); if (!set_word_val(s->m, dval, val)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid stack address 0x%x\n", s->pc, dval); return STAT_ADR; } s->pc = ftpc; break; case I_POPL: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_ADR; } if (!reg_valid(hi1)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, hi1); return STAT_INS; } dval = get_reg_val(s->r, REG_ESP); set_reg_val(s->r, REG_ESP, dval+4); if (!get_word_val(s->m, dval, &val)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid stack address 0x%x\n", s->pc, dval); return STAT_ADR; } set_reg_val(s->r, hi1, val); s->pc = ftpc; break; case I_LEAVE: dval = get_reg_val(s->r, REG_EBP); set_reg_val(s->r, REG_ESP, dval+4); if (!get_word_val(s->m, dval, &val)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid stack address 0x%x\n", s->pc, dval); return STAT_ADR; } set_reg_val(s->r, REG_EBP, val); s->pc = ftpc; break; case I_IADDL: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_ADR; } if (!okc) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address", s->pc); return STAT_INS; } if (!reg_valid(lo1)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, lo1); return STAT_INS; } argB = get_reg_val(s->r, lo1); val = argB + cval; set_reg_val(s->r, lo1, val); s->cc = compute_cc(A_ADD, cval, argB); s->pc = ftpc; break; case I_ISUBL: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_ADR; } if (!okc) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address", s->pc); return STAT_INS; } if (!reg_valid(lo1)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, lo1); return STAT_INS; } argB = get_reg_val(s->r, lo1); val = argB - cval; set_reg_val(s->r, lo1, val); s->cc = compute_cc(A_SUB, cval, argB); s->pc = ftpc; break; default: if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction %.2x\n", s->pc, byte0); return STAT_INS; } return STAT_AOK; }
void execute_program(UM_state um) { int ra =0; int rb =0; int rc =0; //uint32_t val= 0; bool proceed = true; int num_instructions = get_words_in_seg(um->memory, 0); int i = um->instr_ctr; while (i < num_instructions && proceed) { uint32_t word = get_word(um->memory, 0, i); uint32_t op_code = get_op_code(word); /*if (op_code == 13) { int ra = get_reg_num(word, LOAD_RA_LSB); proceed &= valid_reg(ra); uint32_t val = get_val(word); (void) val; } else {*/ ra = get_reg_num(word, RA_LSB); rb = get_reg_num(word, RB_LSB); rc = get_reg_num(word, RC_LSB); proceed &= valid_reg(ra); proceed &= valid_reg(rb); proceed &= valid_reg(rc); //} if (!proceed) { break; } if (op_code == 0) { /* Conditional move - op code 0 */ if (val_in_reg(um, rc) != 0) { uint32_t val = val_in_reg(um, rb); set_reg_val(um, ra, val); } } else if (op_code == 1) { /* Segmented load - op code 1 */ uint32_t val = get_word(um->memory, val_in_reg(um, rb), val_in_reg(um, rc)); set_reg_val(um, ra, val); } else if (op_code == 2) { /* Segmented store - op code 2 */ uint32_t ID = val_in_reg(um, ra); uint32_t offset = val_in_reg(um, rb); uint32_t val = val_in_reg(um, rc); put_word(um->memory, ID, offset, val); } else if (op_code == 3) { /* Add - op code 3 */ uint32_t val = (val_in_reg(um, rb) + val_in_reg(um, rc)) % UINT_MAX; set_reg_val(um, ra, val); } else if (op_code == 4) { /* Multiply - op code 4 */ uint32_t val = (val_in_reg(um, rb) * val_in_reg(um, rc)) % UINT_MAX; set_reg_val(um, ra, val); } else if (op_code == 5) { /* Divide - op code 5 */ uint32_t val = val_in_reg(um, rb) / val_in_reg(um, rc); set_reg_val(um, ra, val); } else if (op_code == 6) { /* Bitwise NAND - op code 6 */ uint32_t val = ~(val_in_reg(um, rb) & val_in_reg(um, rc)); set_reg_val(um, ra, val); } else if (op_code == 7) { /* Halt */ proceed = false; } else if (op_code == 8) { /* Map segment - op code 8 */ if (Stack_empty(um->unmapped_IDs)) { uint32_t num_words = val_in_reg(um, rc); proceed &= create_segment(um->memory, num_words); set_reg_val(um, rb, (get_num_segs(um->memory) - 1)); } else { uint32_t ID = get_unmapped_ID(um); uint32_t num_words = val_in_reg(um, rc); proceed &= resize(um->memory, ID, num_words); set_reg_val(um, rb, ID); } } else if (op_code == 9) { /* Unmap segment - op code 9 */ uint32_t ID = val_in_reg(um, rc); proceed &= clear_seg(um->memory, ID); proceed &= add_unmapped_ID(um, ID); } else if (op_code == 10) { /* Output - op code 10 */ uint32_t val = val_in_reg(um, rc); if (val < 256) { fprintf(stdout, "%c", (char) val); } else { proceed &= false; } } else if (op_code == 11) { /* Input - op code 11 */ uint32_t val = getc(stdin); if ((int) val == EOF) { val = ~0; } else if (val > 255) { proceed &= false; } set_reg_val(um, rc, val); } else if (op_code == 12) { /* Load program - op code 12 */ uint32_t ID = val_in_reg(um, rb); if (ID != 0) { proceed &= clear_seg(um->memory, 0); int num_words = get_words_in_seg(um->memory, ID); resize(um->memory, 0, num_words); for (int i = 0; i < num_words; i++) { proceed &= put_word(um->memory, 0, i, get_word(um->memory, ID, i)); } } um->instr_ctr = val_in_reg(um, rc); num_instructions = get_words_in_seg(um->memory, 0); i = um->instr_ctr; } else if (op_code == 13) { /* Load value - op code 13 */ ra = get_reg_num(word, LOAD_RA_LSB); proceed &= valid_reg(ra); uint32_t val = get_val(word); set_reg_val(um, ra, val); } else { fprintf(stderr, "op code doesn't exist\n"); proceed = false; } if (op_code != 12) { i++; } } return; }
/* * nexti: execute single instruction and return status. * args * sim: the y86 image with PC, register and memory * * return * STAT_AOK: continue * STAT_HLT: halt * STAT_ADR: invalid instruction address, data address, stack address, ... * STAT_INS: invalid instruction, register id, ... */ stat_t nexti(y86sim_t *sim) { byte_t codefun = 0; itype_t icode; alu_t ifun; long_t valP = sim->pc; /* get code and function (1 byte) */ if (!get_byte_val(sim->m, valP, &codefun)) { err_print("PC = 0x%x, Invalid instruction address", sim->pc); return STAT_ADR; } icode = GET_ICODE(codefun); ifun = GET_FUN(codefun); valP++; /* get registers if needed (1 byte) */ byte_t byte; long_t valA, valB, valC, val; regid_t regA, regB; if ((icode>1 && icode<7) || icode==I_PUSHL || icode==I_POPL) { if (!get_byte_val(sim->m, valP, &byte)) { err_print("PC = 0x%x, Invalid data address 0x%x", sim->pc, valC); return STAT_ADR; } valP++; regA = HIGH(byte); regB = LOW(byte); } /* get immediate if needed (4 bytes) */ if (icode>=3 && icode<=8 && icode!=I_ALU) { if (!get_long_val(sim->m, valP, &valC)) { err_print("PC = 0x%x, Invalid data address 0x%x", sim->pc, valC); return STAT_ADR; } valP+=4; } /* execute the instruction */ switch (icode) { case I_HALT: /* 0:0 */ return STAT_HLT; break; case I_NOP: /* 1:0 */ sim->pc = valP; break; case I_RRMOVL: sim->pc = valP; if (!cond_doit(sim->cc,ifun)) break; val = get_reg_val(sim->r, regA); set_reg_val(sim->r, regB, val); break; /* 2:x regA:regB */ case I_IRMOVL: set_reg_val(sim->r, regB, valC); sim->pc = valP; break; /* 3:0 F:regB imm */ case I_RMMOVL: valC += get_reg_val(sim->r, regB); val = get_reg_val(sim->r, regA); set_long_val(sim->m, valC, val); sim->pc = valP; break; /* 4:0 regA:regB imm */ case I_MRMOVL: valC += get_reg_val(sim->r, regB); if (!get_long_val(sim->m, valC, &val)) { err_print("PC = 0x%x, Invalid data address 0x%x", sim->pc, valC); return STAT_ADR; } set_reg_val(sim->r, regA, val); sim->pc = valP; break; /* 5:0 regB:regA imm */ case I_ALU: valA = get_reg_val(sim->r,regA); valB = get_reg_val(sim->r,regB); val = compute_alu(ifun, valA, valB); set_reg_val(sim->r, regB, val); sim->cc = compute_cc(ifun, valA, valB, val); sim->pc = valP; break; /* 6:x regA:regB */ case I_JMP: sim->pc = (cond_doit(sim->cc,ifun))?valC:valP; break; /* 7:x imm */ case I_CALL: val = get_reg_val(sim->r, REG_ESP) - 4; set_reg_val(sim->r, REG_ESP, val); if (!set_long_val(sim->m, val, valP)) { err_print("PC = 0x%x, Invalid stack address 0x%x", sim->pc, val); return STAT_ADR; } sim->pc = valC; break; /* 8:x imm */ case I_RET: valA = get_reg_val(sim->r, REG_ESP); if (!get_long_val(sim->m, valA, &valB)) { err_print("PC = 0x%x, Invalid stack address 0x%x", sim->pc, valA); return STAT_ADR; } set_reg_val(sim->r, REG_ESP, valA+4); sim->pc = valB; break; /* 9:0 */ case I_PUSHL: valA = get_reg_val(sim->r, regA); val = get_reg_val(sim->r, REG_ESP) - 4; set_reg_val(sim->r, REG_ESP, val); if (!set_long_val(sim->m, val, valA)) { err_print("PC = 0x%x, Invalid stack address 0x%x", sim->pc, val); return STAT_ADR; } sim->pc = valP; break; /* A:0 regA:F */ case I_POPL: valA = get_reg_val(sim->r, REG_ESP); set_reg_val(sim->r, REG_ESP, valA+4); if (!get_long_val(sim->m, valA, &valB)) { err_print("PC = 0x%x, Invalid stack address 0x%x", sim->pc, valA); return STAT_ADR; } set_reg_val(sim->r, regA, valB); sim->pc = valP; break; /* B:0 regA:F */ default: err_print("PC = 0x%x, Invalid instruction %.2x", sim->pc, codefun); return STAT_INS; } return STAT_AOK; }
/* * nexti: execute single instruction and return status. * args * sim: the y64 image with PC, register and memory * * return * STAT_AOK: continue * STAT_HLT: halt * STAT_ADR: invalid instruction address * STAT_INS: invalid instruction, register id, data address, stack address, ... */ stat_t nexti(y64sim_t *sim) { byte_t codefun = 0; /* 1 byte */ itype_t icode; alu_t ifun; long_t next_pc = sim->pc; /* get code and function (1 byte) */ if (!get_byte_val(sim->m, next_pc, &codefun)) { err_print("PC = 0x%lx, Invalid instruction address", sim->pc); return STAT_ADR; } icode = GET_ICODE(codefun); ifun = GET_FUN(codefun); next_pc++; /* get registers if needed (1 byte) */ byte_t rArB = 0; regid_t rA = REG_ERR, rB = REG_ERR; if((icode == I_RRMOVQ) || (icode == I_ALU) || (icode == I_RMMOVQ) || (icode == I_PUSHQ) || (icode == I_POPQ) || (icode == I_IRMOVQ) || (icode == I_MRMOVQ) ){ get_byte_val(sim->m, next_pc, &rArB); rA = GET_REGA(rArB); rB = GET_REGB(rArB); next_pc++; } /* get immediate if needed (8 bytes) */ long_t valC; if(icode == I_IRMOVQ || icode == I_RMMOVQ ||icode == I_MRMOVQ || icode == I_JMP || icode == I_CALL){ get_long_val(sim->m,next_pc,&valC); next_pc += 8; } /* execute the instruction*/ long_t valA,valB,valE,valM; switch (icode) { case I_HALT: /* 0:0 */ return STAT_HLT; break; case I_NOP: /* 1:0 */ sim->pc = next_pc; break; case I_RRMOVQ: /* 2:x regA:regB */ if(!NORM_REG(rA) || !NORM_REG(rB)){ err_print("PC = 0x%lx, Invalid register id %.2x", sim->pc, rArB); return STAT_INS; } valA = get_reg_val(sim->r,rA); valE = valA + 0; if(cond_doit(sim->cc, ifun)) set_reg_val(sim->r, rB, valE); sim->pc = next_pc; break; case I_IRMOVQ: /* 3:0 F:regB imm */ if(!NORM_REG(rB) || !NONE_REG(rA)){ err_print("PC = 0x%lx, Invalid register id %.2x", sim->pc, rArB); return STAT_INS; } valA = get_reg_val(sim->r, rA); valB = get_reg_val(sim->r, rB); valE = 0 + valC; set_reg_val(sim->r, rB, valE); sim->pc = next_pc; break; case I_RMMOVQ: /* 4:0 regA:regB imm */ if(!NORM_REG(rA) || !NORM_REG(rB)){ err_print("PC = 0x%lx, Invalid register id %.2x", sim->pc, rArB); return STAT_INS; } valA = get_reg_val(sim->r, rA); valB = get_reg_val(sim->r, rB); valE = valB + valC; if(!set_long_val(sim->m, valE, valA)){ err_print("PC = 0x%lx, Invalid data address 0x%.8lx", sim->pc, valE); return STAT_ADR; } sim->pc = next_pc; break; case I_MRMOVQ: /* 5:0 regB:regA imm */ if(!NORM_REG(rA) || !NORM_REG(rB)){ err_print("PC = 0x%lx, Invalid register id %.2x", sim->pc, rArB); return STAT_INS; } valA = get_reg_val(sim->r, rA); valB = get_reg_val(sim->r, rB); valE = valB + valC; if(!get_long_val(sim->m, valE, &valM)){ err_print("PC = 0x%lx, Invalid data address 0x%.8lx", sim->pc, valE); return STAT_ADR; } set_reg_val(sim->r, rA, valM); sim->pc = next_pc; break; case I_ALU: /* 6:x regA:regB */ if(!NORM_REG(rA) || !NORM_REG(rB)){ err_print("PC = 0x%lx, Invalid register id %.2x", sim->pc, rArB); return STAT_INS; } valA = get_reg_val(sim->r, rA); valB = get_reg_val(sim->r, rB); valE = compute_alu(ifun, valA, valB); sim->cc = compute_cc(ifun, valA, valB, valE); set_reg_val(sim->r, rB, valE); sim->pc = next_pc; break; case I_JMP: /* 7:x imm */ if(ifun > 6){ err_print("PC = 0x%lx, Invalid instruction %.2x", sim->pc, codefun); return STAT_INS; } sim->pc = cond_doit(sim->cc,ifun)? valC : next_pc; break; case I_CALL: /* 8:x imm */ valB = get_reg_val(sim->r, REG_RSP); valE = valB + (-8); set_reg_val(sim->r, REG_RSP, valE); if(!set_long_val(sim->m, valE, next_pc)){ err_print("PC = 0x%lx, Invalid stack address 0x%.8lx", sim->pc, valE); return STAT_ADR; } sim->pc = valC; break; case I_RET: /* 9:0 */ valA = get_reg_val(sim->r, REG_RSP); valB = valA; valE = valB + 8; get_long_val(sim->m, valA, &valM); set_reg_val(sim->r, REG_RSP, valE); sim->pc = valM; break; case I_PUSHQ: /* A:0 regA:F */ if(!NORM_REG(rA)){ err_print("PC = 0x%lx, Invalid register id %.2x", sim->pc, rArB); return STAT_INS; } valA = get_reg_val(sim->r, rA); valB = get_reg_val(sim->r, REG_RSP); valE = valB + (-8); set_reg_val(sim->r, REG_RSP, valE); if(!set_long_val(sim->m, valE, valA)){ err_print("PC = 0x%lx, Invalid stack address 0x%.8lx", sim->pc, valE); return STAT_ADR; } sim->pc = next_pc; break; case I_POPQ: /* B:0 regA:F */ if(!NORM_REG(rA)){ err_print("PC = 0x%lx, Invalid register id %.2x", sim->pc, rArB); return STAT_INS; } valA = get_reg_val(sim->r, REG_RSP); valB = valA; valE = valB + 8; get_long_val(sim->m, valA, &valM); set_reg_val(sim->r, REG_RSP, valE); set_reg_val(sim->r, rA, valM); sim->pc = next_pc; break; // return STAT_INS; /* unsupported now, replace it with your implementation */ default: err_print("PC = 0x%lx, Invalid instruction %.2x", sim->pc, codefun); return STAT_INS; } return STAT_AOK; }