X-Git-Url: http://git.joshuawise.com/firearm.git/blobdiff_plain/778ef14fd7c4dadb9923bb9b8628843587a43e1c..a9f76b88574c4e20ed91ab6704f3f74852584825:/Decode.v diff --git a/Decode.v b/Decode.v index 495942b..a989f42 100644 --- a/Decode.v +++ b/Decode.v @@ -2,28 +2,30 @@ module Decode( input clk, - input [31:0] insn, - input [31:0] inpc, - input [31:0] incpsr, - input [31:0] inspsr, - output reg [31:0] op0, - output reg [31:0] op1, - output reg [31:0] op2, - output reg carry, - output reg [31:0] outspsr, + input stall, + input [31:0] insn_1a, + input [31:0] pc_1a, + input [31:0] cpsr_1a, + input [31:0] spsr_1a, + output reg [31:0] op0_2a, + output reg [31:0] op1_2a, + output reg [31:0] op2_2a, + output reg carry_2a, + output reg [31:0] cpsr_2a, + output reg [31:0] spsr_2a, - output reg [3:0] read_0, - output reg [3:0] read_1, - output reg [3:0] read_2, - input [31:0] rdata_0, - input [31:0] rdata_1, - input [31:0] rdata_2 + output reg [3:0] rf__read_0_1a, + output reg [3:0] rf__read_1_1a, + output reg [3:0] rf__read_2_1a, + input [31:0] rf__rdata_0_1a, + input [31:0] rf__rdata_1_1a, + input [31:0] rf__rdata_2_1a ); wire [31:0] regs0, regs1, regs2; reg [31:0] rpc; - reg [31:0] op0_out, op1_out, op2_out; - reg carry_out; + reg [31:0] op0_1a, op1_1a, op2_1a; + reg carry_1a; /* shifter stuff */ wire [31:0] shift_oper; @@ -31,23 +33,23 @@ module Decode( wire shift_cflag_out; wire [31:0] rotate_res; - assign regs0 = (read_0 == 4'b1111) ? rpc : rdata_0; - assign regs1 = (read_1 == 4'b1111) ? rpc : rdata_1; - assign regs2 = rdata_2; /* use regs2 for things that cannot be r15 */ + assign regs0 = (rf__read_0_1a == 4'b1111) ? rpc : rf__rdata_0_1a; + assign regs1 = (rf__read_1_1a == 4'b1111) ? rpc : rf__rdata_1_1a; + assign regs2 = rf__rdata_2_1a; /* use regs2 for things that cannot be r15 */ - IREALLYHATEARMSHIFT shift(.insn(insn), + IREALLYHATEARMSHIFT shift(.insn(insn_1a), .operand(regs1), .reg_amt(regs2), - .cflag_in(incpsr[`CPSR_C]), + .cflag_in(cpsr_1a[`CPSR_C]), .res(shift_res), .cflag_out(shift_cflag_out)); - SuckLessRotator whirr(.oper({24'b0, insn[7:0]}), - .amt(insn[11:8]), + SuckLessRotator whirr(.oper({24'b0, insn_1a[7:0]}), + .amt(insn_1a[11:8]), .res(rotate_res)); always @(*) - casez (insn) + casez (insn_1a) `DECODE_ALU_MULT, /* Multiply -- must come before ALU, because it pattern matches a specific case of ALU */ // `DECODE_ALU_MUL_LONG, /* Multiply long */ `DECODE_ALU_MRS, /* MRS (Transfer PSR to register) */ @@ -64,172 +66,178 @@ module Decode( `DECODE_LDCSTC, /* Coprocessor data transfer */ `DECODE_CDP, /* Coprocessor data op */ `DECODE_SWI: /* SWI */ - rpc = inpc + 8; + rpc = pc_1a + 8; `DECODE_MRCMCR: /* Coprocessor register transfer */ - rpc = inpc + 12; + rpc = pc_1a + 12; `DECODE_ALU: /* ALU */ - rpc = inpc + (insn[25] ? 8 : (insn[4] ? 12 : 8)); + rpc = pc_1a + (insn_1a[25] ? 8 : (insn_1a[4] ? 12 : 8)); default: /* X everything else out */ rpc = 32'hxxxxxxxx; endcase always @(*) begin - read_0 = 4'hx; - read_1 = 4'hx; - read_2 = 4'hx; - - op0_out = 32'hxxxxxxxx; - op1_out = 32'hxxxxxxxx; - op2_out = 32'hxxxxxxxx; - carry_out = 1'bx; + rf__read_0_1a = 4'hx; + rf__read_1_1a = 4'hx; + rf__read_2_1a = 4'hx; - casez (insn) + casez (insn_1a) `DECODE_ALU_MULT: /* Multiply -- must come before ALU, because it pattern matches a specific case of ALU */ begin - read_0 = insn[15:12]; /* Rn */ - read_1 = insn[3:0]; /* Rm */ - read_2 = insn[11:8]; /* Rs */ - - op0_out = regs0; - op1_out = regs1; - op2_out = regs2; + rf__read_0_1a = insn_1a[15:12]; /* Rn */ + rf__read_1_1a = insn_1a[3:0]; /* Rm */ + rf__read_2_1a = insn_1a[11:8]; /* Rs */ end -// `DECODE_ALU_MUL_LONG: /* Multiply long */ -// begin -// read_0 = insn[11:8]; /* Rn */ -// read_1 = insn[3:0]; /* Rm */ -// read_2 = 4'b0; /* anyus */ -// -// op1_res = regs1; -// end `DECODE_ALU_MRS: /* MRS (Transfer PSR to register) */ begin end `DECODE_ALU_MSR: /* MSR (Transfer register to PSR) */ + rf__read_0_1a = insn_1a[3:0]; /* Rm */ + `DECODE_ALU_MSR_FLAGS: /* MSR (Transfer register or immediate to PSR, flag bits only) */ + rf__read_0_1a = insn_1a[3:0]; /* Rm */ + `DECODE_ALU_SWP: /* Atomic swap */ begin - read_0 = insn[3:0]; /* Rm */ - - op0_out = regs0; + rf__read_0_1a = insn_1a[19:16]; /* Rn */ + rf__read_1_1a = insn_1a[3:0]; /* Rm */ end - `DECODE_ALU_MSR_FLAGS: /* MSR (Transfer register or immediate to PSR, flag bits only) */ + `DECODE_ALU_BX: /* Branch and exchange */ + rf__read_0_1a = insn_1a[3:0]; /* Rn */ + `DECODE_ALU_HDATA_REG: /* Halfword transfer - register offset */ + begin + rf__read_0_1a = insn_1a[19:16]; + rf__read_1_1a = insn_1a[3:0]; + rf__read_2_1a = insn_1a[15:12]; + end + `DECODE_ALU_HDATA_IMM: /* Halfword transfer - immediate offset */ + begin + rf__read_0_1a = insn_1a[19:16]; + rf__read_1_1a = insn_1a[15:12]; + end + `DECODE_ALU: /* ALU */ + begin + rf__read_0_1a = insn_1a[19:16]; /* Rn */ + rf__read_1_1a = insn_1a[3:0]; /* Rm */ + rf__read_2_1a = insn_1a[11:8]; /* Rs for shift */ + end + `DECODE_LDRSTR_UNDEFINED: /* Undefined. I hate ARM */ + begin end + `DECODE_LDRSTR: /* Single data transfer */ + begin + rf__read_0_1a = insn_1a[19:16]; /* Rn */ + rf__read_1_1a = insn_1a[3:0]; /* Rm */ + rf__read_2_1a = insn_1a[15:12]; + end + `DECODE_LDMSTM: /* Block data transfer */ + rf__read_0_1a = insn_1a[19:16]; + `DECODE_BRANCH: /* Branch */ + begin end + `DECODE_LDCSTC: /* Coprocessor data transfer */ + rf__read_0_1a = insn_1a[19:16]; + `DECODE_CDP: /* Coprocessor data op */ + begin end + `DECODE_MRCMCR: /* Coprocessor register transfer */ + rf__read_0_1a = insn_1a[15:12]; + `DECODE_SWI: /* SWI */ + begin end + default: + $display("Undecoded instruction"); + endcase + end + + always @(*) begin + op0_1a = 32'hxxxxxxxx; + op1_1a = 32'hxxxxxxxx; + op2_1a = 32'hxxxxxxxx; + carry_1a = 1'bx; + + casez (insn_1a) + `DECODE_ALU_MULT: /* Multiply -- must come before ALU, because it pattern matches a specific case of ALU */ begin - read_0 = insn[3:0]; /* Rm */ - - if(insn[25]) begin /* the constant case */ - op0_out = rotate_res; + op0_1a = regs0; + op1_1a = regs1; + op2_1a = regs2; + end + `DECODE_ALU_MRS: /* MRS (Transfer PSR to register) */ + begin end + `DECODE_ALU_MSR: /* MSR (Transfer register to PSR) */ + op0_1a = regs0; + `DECODE_ALU_MSR_FLAGS: /* MSR (Transfer register or immediate to PSR, flag bits only) */ + if(insn_1a[25]) begin /* the constant case */ + op0_1a = rotate_res; end else begin - op0_out = regs0; + op0_1a = regs0; end - end `DECODE_ALU_SWP: /* Atomic swap */ begin - read_0 = insn[19:16]; /* Rn */ - read_1 = insn[3:0]; /* Rm */ - - op0_out = regs0; - op1_out = regs1; + op0_1a = regs0; + op1_1a = regs1; end `DECODE_ALU_BX: /* Branch and exchange */ - begin - read_0 = insn[3:0]; /* Rn */ - - op0_out = regs0; - end + op0_1a = regs0; `DECODE_ALU_HDATA_REG: /* Halfword transfer - register offset */ begin - read_0 = insn[19:16]; - read_1 = insn[3:0]; - read_2 = insn[15:12]; - - op0_out = regs0; - op1_out = regs1; - op2_out = regs2; + op0_1a = regs0; + op1_1a = regs1; + op2_1a = regs2; end `DECODE_ALU_HDATA_IMM: /* Halfword transfer - immediate offset */ begin - read_0 = insn[19:16]; - read_1 = insn[15:12]; - - op0_out = regs0; - op1_out = {24'b0, insn[11:8], insn[3:0]}; - op2_out = regs1; + op0_1a = regs0; + op1_1a = {24'b0, insn_1a[11:8], insn_1a[3:0]}; + op2_1a = regs1; end `DECODE_ALU: /* ALU */ begin - read_0 = insn[19:16]; /* Rn */ - read_1 = insn[3:0]; /* Rm */ - read_2 = insn[11:8]; /* Rs for shift */ - - op0_out = regs0; - if(insn[25]) begin /* the constant case */ - carry_out = incpsr[`CPSR_C]; - op1_out = rotate_res; + op0_1a = regs0; + if(insn_1a[25]) begin /* the constant case */ + carry_1a = cpsr_1a[`CPSR_C]; + op1_1a = rotate_res; end else begin - carry_out = shift_cflag_out; - op1_out = shift_res; + carry_1a = shift_cflag_out; + op1_1a = shift_res; end end - `DECODE_LDRSTR_UNDEFINED: /* Undefined. I hate ARM */ - begin - /* eat shit */ - end `DECODE_LDRSTR: /* Single data transfer */ begin - read_0 = insn[19:16]; /* Rn */ - read_1 = insn[3:0]; /* Rm */ - read_2 = insn[15:12]; - - op0_out = regs0; - if(insn[25]) begin - op1_out = {20'b0, insn[11:0]}; - carry_out = incpsr[`CPSR_C]; + op0_1a = regs0; + if(!insn_1a[25] /* immediate */) begin + op1_1a = {20'b0, insn_1a[11:0]}; + carry_1a = cpsr_1a[`CPSR_C]; end else begin - op1_out = shift_res; - carry_out = shift_cflag_out; + op1_1a = shift_res; + carry_1a = shift_cflag_out; end - op2_out = regs2; + op2_1a = regs2; end `DECODE_LDMSTM: /* Block data transfer */ begin - read_0 = insn[19:16]; - - op0_out = regs0; - op1_out = {16'b0, insn[15:0]}; + op0_1a = regs0; + op1_1a = {16'b0, insn_1a[15:0]}; end `DECODE_BRANCH: /* Branch */ - begin - op0_out = {{6{insn[23]}}, insn[23:0], 2'b0}; - end + op0_1a = {{6{insn_1a[23]}}, insn_1a[23:0], 2'b0}; `DECODE_LDCSTC: /* Coprocessor data transfer */ begin - read_0 = insn[19:16]; - - op0_out = regs0; - op1_out = {24'b0, insn[7:0]}; + op0_1a = regs0; + op1_1a = {24'b0, insn_1a[7:0]}; end `DECODE_CDP: /* Coprocessor data op */ - begin - end + begin end `DECODE_MRCMCR: /* Coprocessor register transfer */ - begin - read_0 = insn[15:12]; - - op0_out = regs0; - end + op0_1a = regs0; `DECODE_SWI: /* SWI */ - begin - end - default: - $display("Undecoded instruction"); + begin end endcase end - always @ (posedge clk) begin - op0 <= op0_out; /* Rn - always */ - op1 <= op1_out; /* 'operand 2' - Rm */ - op2 <= op2_out; /* thirdedge - Rs */ - carry <= carry_out; - outspsr <= inspsr; + if (!stall) + begin + op0_2a <= op0_1a; /* Rn - always */ + op1_2a <= op1_1a; /* 'operand 2' - Rm */ + op2_2a <= op2_1a; /* thirdedge - Rs */ + carry_2a <= carry_1a; + cpsr_2a <= cpsr_1a; + spsr_2a <= spsr_1a; + end end endmodule