reg [3:0] next_write_num;
reg [31:0] next_write_data;
- reg [1:0] lsr_state = 2'b01, next_lsr_state;
+ reg [2:0] lsr_state = 3'b001, next_lsr_state;
reg [31:0] align_s1, align_s2, align_rddata;
- reg [1:0] lsrh_state = 2'b01, next_lsrh_state;
+ reg [2:0] lsrh_state = 3'b001, next_lsrh_state;
reg [31:0] lsrh_rddata;
reg [15:0] lsrh_rddata_s1;
reg [7:0] lsrh_rddata_s2;
reg [15:0] regs, next_regs;
- reg [2:0] lsm_state = 3'b001, next_lsm_state;
+ reg [3:0] lsm_state = 4'b0001, next_lsm_state;
reg [5:0] offset, prev_offset, offset_sel;
reg [31:0] swp_oldval, next_swp_oldval;
cp_rnw = 1'bx;
cp_write = 32'hxxxxxxxx;
offset = prev_offset;
- next_outcpsr = lsm_state == 3'b010 ? outcpsr : cpsr;
+ next_outcpsr = lsm_state == 4'b0010 ? outcpsr : cpsr;
lsrh_rddata = 32'hxxxxxxxx;
lsrh_rddata_s1 = 16'hxxxx;
lsrh_rddata_s2 = 8'hxx;
next_swp_state = 2'b10;
next_swp_oldval = rd_data;
end
+ $display("SWP: read stage");
end
2'b10: begin
wr_req = 1'b1;
next_write_data = insn[22] ? {24'b0, swp_oldval[7:0]} : swp_oldval;
if(!rw_wait)
next_swp_state = 2'b01;
+ $display("SWP: write stage");
end
default: begin end
endcase
end
+ `DECODE_ALU_MULT: begin end
`DECODE_ALU_HDATA_REG,
`DECODE_ALU_HDATA_IMM: if(!inbubble) begin
next_outbubble = rw_wait;
endcase
case(lsrh_state)
- 2'b01: begin
+ 3'b001: begin
rd_req = insn[20];
wr_req = ~insn[20];
next_write_num = insn[15:12];
if(insn[21] | !insn[24]) begin
outstall = 1'b1;
if(!rw_wait)
- next_lsrh_state = 2'b10;
+ next_lsrh_state = 3'b010;
end
+ $display("ALU_LDRSTRH: rd_req %d, wr_req %d", rd_req, wr_req);
end
- 2'b10: begin
+ 3'b010: begin
+ next_outbubble = 1'b0;
next_write_reg = 1'b1;
next_write_num = insn[19:16];
next_write_data = addr;
- next_lsrh_state = 2'b10;
+ next_lsrh_state = 3'b100;
+ end
+ 3'b100: begin
+ outstall = 0;
+ next_lsrh_state = 3'b001;
end
default: begin end
endcase
+
+ if ((lsrh_state == 3'b001) && flush) begin /* Reject it. */
+ outstall = 1'b0;
+ next_lsrh_state = 3'b001;
+ end
end
`DECODE_LDRSTR_UNDEFINED: begin end
`DECODE_LDRSTR: if(!inbubble) begin
wr_data = insn[22] ? {4{op2[7:0]}} : op2; /* XXX need to actually store just a byte */
data_size = insn[22] ? 3'b001 : 3'b100;
case(lsr_state)
- 2'b01: begin
- rd_req = insn[20];
- wr_req = ~insn[20];
- next_write_reg = 1'b1;
+ 3'b001: begin
+ rd_req = insn[20] /* L */;
+ wr_req = ~insn[20] /* L */;
+ next_write_reg = insn[20] /* L */;
next_write_num = insn[15:12];
- if(insn[20]) begin
+ if(insn[20] /* L */) begin
next_write_data = align_rddata;
end
- if(insn[21] | !insn[24]) begin
+ if(insn[21] /* W */ | !insn[24] /* P */) begin
outstall = 1'b1;
if(!rw_wait)
- next_lsr_state = 2'b10;
+ next_lsr_state = 3'b010;
end
$display("LDRSTR: rd_req %d, wr_req %d, raddr %08x, wait %d", rd_req, wr_req, raddr, rw_wait);
end
- 2'b10: begin
+ 3'b010: begin
+ outstall = 1;
+ next_outbubble = 0;
next_write_reg = 1'b1;
next_write_num = insn[19:16];
next_write_data = addr;
- next_lsr_state = 2'b01;
+ next_lsr_state = 3'b100;
+ end
+ 3'b100: begin
+ outstall = 0;
+ next_lsr_state = 3'b001;
end
default: begin end
endcase
+
+ if ((lsr_state == 3'b001) && flush) begin /* Reject it. */
+ outstall = 1'b0;
+ next_lsr_state = 3'b001;
+ end
end
/* XXX ldm/stm incorrect in that stupid case where one of the listed regs is the base reg */
`DECODE_LDMSTM: if(!inbubble) begin
next_outbubble = rw_wait;
data_size = 3'b100;
case(lsm_state)
- 3'b001: begin
+ 4'b0001: begin
// next_regs = insn[23] ? op1[15:0] : op1[0:15];
/** verilator can suck my dick */
$display("LDMSTM: Round 1: base register: %08x, reg list %b", op0, op1[15:0]);
op1[8], op1[9], op1[10], op1[11], op1[12], op1[13], op1[14], op1[15]};
offset = 6'b0;
outstall = 1'b1;
- next_lsm_state = 3'b010;
+ next_lsm_state = 4'b0010;
end
- 3'b010: begin
+ 4'b0010: begin
rd_req = insn[20];
wr_req = ~insn[20];
casez(regs)
outstall = 1'b1;
if(next_regs == 16'b0) begin
- next_lsm_state = 3'b100;
+ next_lsm_state = 4'b0100;
end
end
- 3'b100: begin
+ 4'b0100: begin
+ outstall = 1;
+ next_outbubble = 0;
next_write_reg = insn[21] /* writeback */;
next_write_num = insn[19:16];
next_write_data = insn[23] ? op0 + {26'b0, prev_offset} : op0 - {26'b0, prev_offset};
- next_lsm_state = 3'b001;
+ next_lsm_state = 4'b1000;
$display("LDMSTM: Stage 3: Writing back");
end
+ 4'b1000: begin
+ outstall = 0;
+ next_lsm_state = 4'b0001;
+ end
default: $stop;
endcase
+ if ((lsm_state == 4'b0001) && flush) begin /* Reject it. */
+ outstall = 1'b0;
+ next_lsm_state = 4'b0001;
+ end
$display("LDMSTM: Decoded, bubble %d, insn %08x, lsm state %b -> %b, stall %d", inbubble, insn, lsm_state, next_lsm_state, outstall);
end
`DECODE_LDCSTC: if(!inbubble) begin