// // execute.C // // Description: // Implements execute stage of the AD-MIPS pipeline. // // Version: // $Id$ // // Revision: // $Log$ // // Author: // Brian J. Alliet // Jonathon W. Donaldson // #include "includes.h" void execute() { StorageObject& pc = imem.MAR(); StorageObject& ex_mem_aluout = dmem.MAR(); StorageObject *rs = forward(RS(id_ex_ir),&id_ex_rs,1/*MEM*/); StorageObject *rt = forward(RT(id_ex_ir),&id_ex_rt,1/*MEM*/); // case for OP1 for *most* instrux (may be changed below) alu.OP1().pullFrom(*rs); // FEATURE: copyVia.... // copy IR to next stage ex_ir_bus.IN().pullFrom(id_ex_ir); ex_mem_ir.latchFrom(ex_ir_bus.OUT()); // copy rt to nexxt stage ex_rt_bus.IN().pullFrom(*rt); ex_mem_rt.latchFrom(ex_rt_bus.OUT()); // copy ALU result to EX/MEM pipeline register ex_mem_aluout.latchFrom(alu.OUT()); switch(OP(id_ex_ir)) { case R_: { unsigned long func = FUNC(id_ex_ir); alu.OP2().pullFrom(*rt); switch(func) { case R_F_SLL: case R_F_SRA: case R_F_SRL: // NOTE: These override what we set above because shifts are fucked up alu.OP1().pullFrom(*rt); alu.OP2().pullFrom(id_ex_shamt); // perform ALU operation based on function code alu.perform(func == R_F_SLL ? BusALU::op_lshift : func == R_F_SRA ? BusALU::op_rashift : func == R_F_SRL ? BusALU::op_rshift : BusALU::op_zero); break; case R_F_SLLV: alu.OP1().pullFrom(*rt); alu.OP2().pullFrom(*rs); alu.perform(BusALU::op_lshift); break; case R_F_SRLV: alu.OP1().pullFrom(*rt); alu.OP2().pullFrom(*rs); alu.perform(BusALU::op_rshift); break; case R_F_JR: alu.perform(BusALU::op_zero); break; case R_F_JALR: alu.OP1().pullFrom(id_ex_onpc); alu.OP2().pullFrom(ex_4); alu.perform(BusALU::op_add); break; case R_F_SYSCALL: { // syscalls are what allow us to communicate with the kernel. // This case allows us to pretend to be the kernel // for any syscall instrux to override the real kernel. long nr = forward(V0,regs[V0],1/*MEM*/)->value(); long a0 = forward(A0,regs[A0],1/*MEM*/)->value(); long a1 = forward(A1,regs[A1],1/*MEM*/)->value(); long a2 = forward(A2,regs[A2],1/*MEM*/)->value(); syscall_ret.m_val = mips_syscall(nr,a0,a1,a2); ex_mem_aluout.latchFrom(syscall_ret.OUT()); break; } case R_F_ADDU: alu.perform(BusALU::op_add); break; case R_F_SUBU: alu.perform(BusALU::op_sub); break; case R_F_AND: alu.perform(BusALU::op_and); break; case R_F_OR: alu.perform(BusALU::op_or); break; case R_F_NOR: alu.perform(BusALU::op_nor); break; case R_F_SLT: alu.perform(BusALU::op_slt); break; case R_F_SLTU: alu.perform(BusALU::op_sltu); break; default: fprintf(stderr,"Unknown function for opcode 0x00: 0x%02lx at 0x%08lx\n",id_ex_ir(5,0),pc.uvalue()-8); exit(EXIT_FAILURE); break; } break; } case I_O_COM_BRA: { switch(RT(id_ex_ir)) { case I_F_BLTZ: case I_F_BGEZ: alu.perform(BusALU::op_zero); break; case I_F_BGEZAL: alu.OP1().pullFrom(id_ex_onpc); alu.OP2().pullFrom(ex_4); alu.perform(BusALU::op_add); break; default: fprintf(stderr,"Unknown rt for opcode 0x01: 0x%02lx at 0x%08lx\n",RT(id_ex_ir),pc.uvalue()-8); exit(EXIT_FAILURE); break; } break; } case J_O_JAL: alu.OP1().pullFrom(id_ex_onpc); alu.OP2().pullFrom(ex_4); alu.perform(BusALU::op_add); break; case J_O_J: case I_O_BEQ: case I_O_BNE: case I_O_BLEZ: case I_O_BGTZ: alu.perform(BusALU::op_zero); break; case I_O_ADDIU: alu.OP2().pullFrom(id_ex_imm); alu.perform(BusALU::op_add); break; case I_O_SLTI: alu.OP2().pullFrom(id_ex_imm); alu.perform(BusALU::op_slt); break; case I_O_SLTIU: alu.OP2().pullFrom(id_ex_imm); alu.perform(BusALU::op_sltu); break; case I_O_ANDI: alu.OP2().pullFrom(id_ex_uimm); alu.perform(BusALU::op_and); break; case I_O_ORI: alu.OP2().pullFrom(id_ex_uimm); alu.perform(BusALU::op_or); break; case I_O_XORI: alu.OP2().pullFrom(id_ex_uimm); alu.perform(BusALU::op_xor); break; case I_O_LUI: alu.OP1().pullFrom(id_ex_imm); alu.OP2().pullFrom(ex_16); alu.perform(BusALU::op_lshift); break; case I_O_LB: case I_O_LH: case I_O_SB: case I_O_SH: case I_O_SW: case I_O_LW: case I_O_LBU: case I_O_LHU: //case I_O_LWC0: //case I_O_SWC0: case I_O_LWC1: case I_O_SWC1: alu.OP2().pullFrom(id_ex_imm); alu.perform(BusALU::op_add); break; default: fprintf(stderr,"Unknown opcode: 0x%02lx at 0x%08lx\n",id_ex_ir(31,26),pc.uvalue()-8); exit(EXIT_FAILURE); break; } }