URL
https://opencores.org/ocsvn/thor/thor/trunk
Subversion Repositories thor
Compare Revisions
- This comparison shows the changes necessary to convert path
/thor/trunk
- from Rev 54 to Rev 55
- ↔ Reverse comparison
Rev 54 → Rev 55
/FT64v5/rtl/common/FT64_alu.v
1114,9 → 1114,9
`LUI: |
begin |
if (instr[7:6]==2'b01) |
o[63:0] = {instr[47:13],30'd0}; |
o = {instr[47:13],30'd0}; |
else |
o[63:0] = {{15{instr[31]}},instr[31:13],30'd0}; |
o = {{15{instr[31]}},instr[31:13],30'd0}; |
end |
`ADDI: o[63:0] = a + b; |
`SLTI: o[63:0] = $signed(a) < $signed(b); |
1143,17 → 1143,18
end |
`LWR,`SWC,`CAS: |
begin |
o[63:0] = a + b; |
o = a + b; |
end |
`LV,`SV: begin |
o[63:0] = a + b + {ven,3'b0}; |
o = a + b + {ven,3'b0}; |
end |
`CSRRW: case(instr[27:18]) |
10'h044: o[63:0] = BIG ? csr | {thrd,24'h0} : 64'hDDDDDDDDDDDDDDDD; |
default: o[63:0] = BIG ? csr : 64'hDDDDDDDDDDDDDDDD; |
`CSRRW: |
case(instr[27:18]) |
10'h044: o = BIG ? (csr | {39'd0,thrd,24'h0}) : 64'hDDDDDDDDDDDDDDDD; |
default: o = BIG ? csr : 64'hDDDDDDDDDDDDDDDD; |
endcase |
`BITFIELD: o[63:0] = BIG ? bfout : 64'hCCCCCCCCCCCCCCCC; |
default: o[63:0] = 64'hDEADDEADDEADDEAD; |
`BITFIELD: o = BIG ? bfout : 64'hCCCCCCCCCCCCCCCC; |
default: o = 64'hDEADDEADDEADDEAD; |
endcase |
end |
|
/FT64v5/rtl/common/FT64_config.vh
24,6 → 24,7
// |
`define SIM 1'b1 |
//`define SUPPORT_SMT 1'b1 |
`define SUPPORT_VECTOR 1'b1 |
//`define DEBUG_LOGIC 1'b1 |
|
`define AMSB 31 |
/FT64v5/rtl/common/FT64_defines.vh
221,6 → 221,7
`define JAL 6'h18 |
`define CALL 6'h19 |
`define INC 6'h1A |
`define LFx 6'h1B |
`define SGTUI 6'h1C |
`define LWR 6'h1D |
`define CACHE 6'h1E |
237,7 → 238,9
`define LUI 6'h27 |
`define JMP 6'h28 |
`define RET 6'h29 |
`define SFx 6'h2B |
`define SGTI 6'h2C |
`define CMPRSSD 6'h2D |
`define MODI 6'h2E |
`define AMO 6'h2F |
`define AMO_SWAP 6'h00 |
/FT64v5/rtl/common/FT64_idecoder.v
737,6 → 737,7
`CAS: IsRFW = TRUE; |
`AMO: IsRFW = TRUE; |
`CSRRW: IsRFW = TRUE; |
`LUI: IsRFW = TRUE; |
default: IsRFW = FALSE; |
endcase |
endfunction |
940,11 → 941,14
bus <= 144'h0; |
bus[`IB_CONST] <= instr[6]==1'b1 ? {{34{instr[47]}},instr[47:18]} : |
{{50{instr[31]}},instr[31:18]}; |
case(instr[7:6]) |
2'b00: bus[`IB_LN] <= 3'd4; |
2'b01: bus[`IB_LN] <= 3'd6; |
default: bus[`IB_LN] <= 3'd2; |
endcase |
if (instr[`INSTRUCTION_OP]==`CMPRSSD) |
bus[`IB_LN] <= 3'd2; |
else |
case(instr[7:6]) |
2'b00: bus[`IB_LN] <= 3'd4; |
2'b01: bus[`IB_LN] <= 3'd6; |
default: bus[`IB_LN] <= 3'd2; |
endcase |
// bus[`IB_RT] <= fnRt(instr,ven,vl,thrd) | {thrd,7'b0}; |
// bus[`IB_RC] <= fnRc(instr,ven,thrd) | {thrd,7'b0}; |
// bus[`IB_RA] <= fnRa(instr,ven,vl,thrd) | {thrd,7'b0}; |
/FT64v5/rtl/common/FT64_mpu.v
40,7 → 40,7
input pit_clk2; |
input pit_gate2; |
output pit_out2; |
output [2:0] irq_o; |
output [3:0] irq_o; |
input i1; |
input i2; |
input i3; |
100,7 → 100,7
wire crd_ack; |
wire [63:0] crd_dato; |
wire ack; |
wire [2:0] ol; |
wire [1:0] ol; |
wire [31:0] pcr; |
wire [63:0] pcr2; |
wire icl; // instruction cache load |
/FT64v5/rtl/twoway/FT64.v
37,8 → 37,7
// You should have received a copy of the GNU General Public License |
// along with this program. If not, see <http://www.gnu.org/licenses/>. |
// |
// Approx. 100,000 LUTs. 160,000 LC's. |
// 38,000LUTs??? |
// Approx 41,000 LUTs. 66,000 LC's. |
// ============================================================================ |
// |
`include "FT64_config.vh" |
92,7 → 91,7
parameter NMAP = QENTRIES; |
parameter BRANCH_PRED = 1'b0; |
parameter SUP_TXE = 1'b0; |
parameter SUP_VECTOR = 1; |
parameter SUP_VECTOR = `SUPPORT_VECTOR; |
parameter DBW = 64; |
parameter ABW = 32; |
parameter AMSB = ABW-1; |
389,7 → 388,6
reg [47:0] insn0, insn1, insn2; |
wire [47:0] insn0a, insn1b, insn2b; |
reg [47:0] insn1a, insn2a; |
reg tgtq; |
// Only need enough bits in the seqnence number to cover the instructions in |
// the queue plus an extra count for skipping on branch misses. In this case |
// that would be four bits minimum (count 0 to 8). |
922,14 → 920,16
assign rfoc0 = Rc0[11:6]==6'h3F ? vm[Rc0[2:0]] : rfoc0a; |
assign rfoc1 = Rc1[11:6]==6'h3F ? vm[Rc1[2:0]] : rfoc1a; |
|
function [2:0] fnInsLength; |
function [3:0] fnInsLength; |
input [47:0] ins; |
case(ins[7:6]) |
2'b00: fnInsLength = 3'd4; |
2'b01: fnInsLength = 3'd6; |
2'b10: fnInsLength = 3'd2; |
2'b11: fnInsLength = 3'd2; |
endcase |
if (ins[`INSTRUCTION_OP]==`CMPRSSD) |
fnInsLength = 4'd2; |
else |
case(ins[7:6]) |
2'd0: fnInsLength = 4'd4; |
2'd1: fnInsLength = 4'd6; |
default: fnInsLength = 4'd2; |
endcase |
endfunction |
|
wire [`ABITS] pc0plus6 = pc0 + 32'd6; |
1727,6 → 1727,7
`RET: fnRt = {rgs[thrd],1'b0,isn[`INSTRUCTION_RA]}; |
`LV: fnRt = {vqei,1'b1,isn[`INSTRUCTION_RB]}; |
`AMO: fnRt = isn[31] ? {rgs[thrd],1'b0,isn[`INSTRUCTION_RB]} : {rgs[thrd],1'b0,isn[`INSTRUCTION_RC]}; |
`LUI: fnRt = {rgs[thrd],1'b0,isn[`INSTRUCTION_RA]}; |
default: fnRt = {rgs[thrd],1'b0,isn[`INSTRUCTION_RB]}; |
endcase |
endfunction |
1950,6 → 1951,7
`RET: fnRt = {rgs,1'b0,isn[`INSTRUCTION_RA]}; |
`LV: fnRt = {vqei,1'b1,isn[`INSTRUCTION_RB]}; |
`AMO: fnRt = isn[31] ? {rgs,1'b0,isn[`INSTRUCTION_RB]} : {rgs,1'b0,isn[`INSTRUCTION_RC]}; |
`LUI: fnRt = {rgs,1'b0,isn[`INSTRUCTION_RA]}; |
default: fnRt = {rgs,1'b0,isn[`INSTRUCTION_RB]}; |
endcase |
endfunction |
2617,6 → 2619,7
`CAS: IsRFW = TRUE; |
`AMO: IsRFW = TRUE; |
`CSRRW: IsRFW = TRUE; |
`LUI: IsRFW = TRUE; |
default: IsRFW = FALSE; |
endcase |
endfunction |
3027,6 → 3030,7
.we_i(we_o), |
.adr_i(adr_o[15:0]), |
.dat_i(dat_o[31:0]), |
.cmpgrp(cr0[10:8]), |
.freezePC(freezePC), |
.regLR(regLR), |
.thread_en(thread_en), |
5161,6 → 5165,15
|| (branchmiss && branchmiss_thrd == iqentry_thrd[commit0_id[`QBITS]] && iqentry_source[ commit1_id[`QBITS] ])); |
end |
regIsValid[0] = `VAL; |
regIsValid[32] = `VAL; |
regIsValid[64] = `VAL; |
regIsValid[128] = `VAL; |
`ifdef SMT |
regIsValid[144] = `VAL; |
regIsValid[160] = `VAL; |
regIsValid[192] = `VAL; |
regIsValid[224] = `VAL; |
`endif |
end |
|
// Wait until the cycle after Ra becomes valid to give time to read |
5369,10 → 5382,10
always @(posedge clk) |
if (rst) begin |
`ifdef SUPPORT_SMT |
mstatus[0] <= 64'h0007; // select register set #0 for thread 0 |
mstatus[1] <= 64'h8007; // select register set #2 for thread 1 |
mstatus[0] <= 64'h000F; // select register set #0 for thread 0 |
mstatus[1] <= 64'h800F; // select register set #2 for thread 1 |
`else |
mstatus <= 64'h0007; // select register set #0 for thread 0 |
mstatus <= 64'h000F; // select register set #0 for thread 0 |
`endif |
for (n = 0; n < QENTRIES; n = n + 1) begin |
iqentry_v[n] <= `INV; |
5515,7 → 5528,7
adr_o <= RSTPC; |
icl_o <= `LOW; // instruction cache load |
cr0 <= 64'd0; |
cr0[13:8] <= 6'd0; // select register set #0 |
cr0[13:8] <= 6'd0; // select compressed instruction group #0 |
cr0[30] <= TRUE; // enable data caching |
cr0[32] <= TRUE; // enable branch predictor |
cr0[16] <= 1'b0; // disable SMT |
5525,7 → 5538,6
pcr2 <= 64'd0; |
for (n = 0; n < PREGS; n = n + 1) |
rf_v[n] <= `VAL; |
tgtq <= FALSE; |
fp_rm <= 3'd0; // round nearest even - default rounding mode |
fpu_csr[37:32] <= 5'd31; // register set #31 |
waitctr <= 64'd0; |
5721,7 → 5733,6
seq_num1 <= seq_num1 + 5'd1; |
else |
seq_num <= seq_num + 5'd1; |
tgtq <= FALSE; |
if (fetchbuf1_rfw) begin |
rf_source[ Rt1s ] <= { 1'b0, fetchbuf1_memld, tail0 }; // top bit indicates ALU/MEM bus |
rf_v [Rt1s] <= `INV; |
5739,7 → 5750,6
seq_num1 <= seq_num1 + 5'd2; |
else |
seq_num <= seq_num + 5'd2; |
tgtq <= FALSE; |
if (fetchbuf1_rfw) begin |
rf_source[ Rt1s ] <= { 1'b0, fetchbuf1_memld, tail1 }; // top bit indicates ALU/MEM bus |
rf_v [Rt1s] <= `INV; |
5752,7 → 5762,6
seq_num1 <= seq_num1 + 5'd1; |
else |
seq_num <= seq_num + 5'd1; |
tgtq <= FALSE; |
if (fetchbuf1_rfw) begin |
rf_source[ Rt1s ] <= { 1'b0, fetchbuf1_memld, tail0 }; // top bit indicates ALU/MEM bus |
rf_v [Rt1s] <= `INV; |
5762,68 → 5771,7
|
2'b10: |
if (canq1) begin |
// $display("queued1: %d", queued1); |
// if (!IsBranch(fetchbuf0_instr)) panic <= `PANIC_FETCHBUFBEQ; |
// if (!predict_taken0) panic <= `PANIC_FETCHBUFBEQ; |
// |
// this should only happen when the first instruction is a BEQ-backwards and the IQ |
// happened to be full on the previous cycle (thus we deleted fetchbuf1 but did not |
// enqueue fetchbuf0) ... probably no need to check for LW -- sanity check, just in case |
// |
if (IsVector(fetchbuf0_instr) && SUP_VECTOR) begin |
vqe0 <= vqe0 + 4'd1; |
if (IsVCmprss(fetchbuf0_instr)) begin |
if (vm[fetchbuf0_instr[25:23]][vqe0]) |
vqet0 <= vqet0 + 4'd1; |
end |
else |
vqet0 <= vqet0 + 4'd1; |
if (vqe0 >= vl-2) |
nop_fetchbuf <= fetchbuf ? 4'b1000 : 4'b0010; |
enque0(tail0, fetchbuf0_thrd ? seq_num1 : seq_num, vqe0); |
if (fetchbuf0_thrd) |
seq_num1 <= seq_num1 + 5'd1; |
else |
seq_num <= seq_num + 5'd1; |
tgtq <= FALSE; |
if (fetchbuf0_rfw) begin |
rf_source[ Rt0s ] <= { 1'b0, fetchbuf0_memld, tail0 }; // top bit indicates ALU/MEM bus |
rf_v[Rt0s] <= `INV; |
end |
if (canq2) begin |
if (vqe0 < vl-2) begin |
vqe0 <= vqe0 + 4'd2; |
if (IsVCmprss(fetchbuf0_instr)) begin |
if (vm[fetchbuf0_instr[25:23]][vqe0+6'd1]) |
vqet0 <= vqet0 + 4'd2; |
end |
else |
vqet0 <= vqet0 + 4'd2; |
enque0(tail1, fetchbuf0_thrd ? seq_num1 + 5'd1 : seq_num+5'd1, vqe0 + 6'd1); |
if (fetchbuf0_thrd) |
seq_num1 <= seq_num1 + 5'd2; |
else |
seq_num <= seq_num + 5'd2; |
tgtq <= FALSE; |
if (fetchbuf0_rfw) begin |
rf_source[ Rt0s ] <= { 1'b0, fetchbuf0_memld, tail1 }; // top bit indicates ALU/MEM bus |
rf_v[Rt0s] <= `INV; |
end |
end |
end |
end |
else begin |
enque0(tail0, fetchbuf0_thrd ? seq_num1 : seq_num, 6'd0); |
if (fetchbuf0_thrd) |
seq_num1 <= seq_num1 + 5'd1; |
else |
seq_num <= seq_num + 5'd1; |
tgtq <= FALSE; |
if (fetchbuf0_rfw) begin |
rf_source[ Rt0s ] <= { 1'b0, fetchbuf0_memld, tail0 }; // top bit indicates ALU/MEM bus |
rf_v[Rt0s] <= `INV; |
end |
end |
enque0x(); |
end |
|
2'b11: |
5833,16 → 5781,7
// but only if the following instruction is in the same thread. Otherwise we want to queue two. |
// |
if (take_branch0 && fetchbuf1_thrd==fetchbuf0_thrd) begin |
tgtq <= FALSE; |
enque0(tail0,fetchbuf0_thrd ? seq_num1 : seq_num,6'd0); |
if (fetchbuf0_thrd) |
seq_num1 <= seq_num1 + 5'd1; |
else |
seq_num <= seq_num + 5'd1; |
if (fetchbuf0_rfw) begin |
rf_source[ Rt0s ] <= {1'b0,fetchbuf0_memld, tail0}; |
rf_v [ Rt0s ] <= `INV; |
end |
enque0x(); |
end |
|
else begin // fetchbuf0 doesn't contain a predicted branch |
5866,7 → 5805,6
if (vqe0 >= vl-2) |
nop_fetchbuf <= fetchbuf ? 4'b1000 : 4'b0010; |
end |
tgtq <= FALSE; |
if (vqe0 < vl || !IsVector(fetchbuf0_instr)) begin |
enque0(tail0, fetchbuf0_thrd ? seq_num1 : seq_num, vqe0); |
if (fetchbuf0_thrd) |
5914,58 → 5852,13
end |
|
// SOURCE 1 ... |
// if previous instruction writes nothing to RF, then get info from rf_v and rf_source |
if (~fetchbuf0_rfw) begin |
iqentry_a1_v [tail1] <= regIsValid[Ra1s]; |
iqentry_a1_s [tail1] <= rf_source [Ra1s]; |
end |
// otherwise, previous instruction does write to RF ... see if overlap |
else if (Ra1 == Rt0) begin |
// if the previous instruction is a LW, then grab result from memq, not the iq |
iqentry_a1_v [tail1] <= `INV; |
iqentry_a1_s [tail1] <= { 1'b0, fetchbuf0_mem &IsLoad(fetchbuf0_instr), tail0 }; |
end |
// if no overlap, get info from rf_v and rf_source |
else begin |
iqentry_a1_v [tail1] <= regIsValid[Ra1s]; |
iqentry_a1_s [tail1] <= rf_source [Ra1s]; |
end |
a1_vs(); |
|
// SOURCE 2 ... |
// if previous instruction writes nothing to RF, then get info from rf_v and rf_source |
if (~fetchbuf0_rfw) begin |
iqentry_a2_v [tail1] <= regIsValid[Rb1s]; |
iqentry_a2_s [tail1] <= rf_source[ Rb1s ]; |
end |
// otherwise, previous instruction does write to RF ... see if overlap |
else if (Rb1s == Rt0s) begin |
// if the previous instruction is a LW, then grab result from memq, not the iq |
iqentry_a2_v [tail1] <= `INV; |
iqentry_a2_s [tail1] <= { 1'b0, fetchbuf0_mem &IsLoad(fetchbuf0_instr), tail0 }; |
end |
// if no overlap, get info from rf_v and rf_source |
else begin |
iqentry_a2_v [tail1] <= regIsValid[Rb1s]; |
iqentry_a2_s [tail1] <= rf_source[ Rb1s ]; |
end |
a2_vs(); |
|
// SOURCE 3 ... |
// if previous instruction writes nothing to RF, then get info from rf_v and rf_source |
if (~fetchbuf0_rfw) begin |
iqentry_a3_v [tail1] <= regIsValid[Rc1s]; |
iqentry_a3_s [tail1] <= rf_source[ Rc1s ]; |
end |
// otherwise, previous instruction does write to RF ... see if overlap |
else if (Rc1 == Rt0) begin |
// if the previous instruction is a LW, then grab result from memq, not the iq |
iqentry_a3_v [tail1] <= `INV; |
iqentry_a3_s [tail1] <= { 1'b0, fetchbuf0_mem &IsLoad(fetchbuf0_instr), tail0 }; |
end |
// if no overlap, get info from rf_v and rf_source |
else begin |
iqentry_a3_v [tail1] <= regIsValid[Rc1s]; |
iqentry_a3_s [tail1] <= rf_source[ Rc1s ]; |
end |
a3_vs(); |
|
// if the two instructions enqueued target the same register, |
// make sure only the second writes to rf_v and rf_source. |
6054,58 → 5947,13
end |
|
// SOURCE 1 ... |
// if previous instruction writes nothing to RF, then get info from rf_v and rf_source |
if (~fetchbuf0_rfw) begin |
iqentry_a1_v [tail1] <= regIsValid[Ra1s]; |
iqentry_a1_s [tail1] <= rf_source [Ra1s]; |
end |
// otherwise, previous instruction does write to RF ... see if overlap |
else if (Ra1 == Rt0) begin |
// if the previous instruction is a LW, then grab result from memq, not the iq |
iqentry_a1_v [tail1] <= `INV; |
iqentry_a1_s [tail1] <= { 1'b0, fetchbuf0_mem &IsLoad(fetchbuf0_instr), tail0 }; |
end |
// if no overlap, get info from rf_v and rf_source |
else begin |
iqentry_a1_v [tail1] <= regIsValid[Ra1s]; |
iqentry_a1_s [tail1] <= rf_source [Ra1s]; |
end |
a1_vs(); |
|
// SOURCE 2 ... |
// if previous instruction writes nothing to RF, then get info from rf_v and rf_source |
if (~fetchbuf0_rfw) begin |
iqentry_a2_v [tail1] <= regIsValid[Rb1s]; |
iqentry_a2_s [tail1] <= rf_source[ Rb1s ]; |
end |
// otherwise, previous instruction does write to RF ... see if overlap |
else if (Rb1s == Rt0s) begin |
// if the previous instruction is a LW, then grab result from memq, not the iq |
iqentry_a2_v [tail1] <= `INV; |
iqentry_a2_s [tail1] <= { 1'b0, fetchbuf0_mem &IsLoad(fetchbuf0_instr), tail0 }; |
end |
// if no overlap, get info from rf_v and rf_source |
else begin |
iqentry_a2_v [tail1] <= regIsValid[Rb1s]; |
iqentry_a2_s [tail1] <= rf_source[ Rb1s ]; |
end |
// SOURCE 2 .. |
a2_vs(); |
|
// SOURCE 3 ... |
// if previous instruction writes nothing to RF, then get info from rf_v and rf_source |
if (~fetchbuf0_rfw) begin |
iqentry_a3_v [tail1] <= regIsValid[Rc1s]; |
iqentry_a3_s [tail1] <= rf_source[ Rc1s ]; |
end |
// otherwise, previous instruction does write to RF ... see if overlap |
else if (Rc1 == Rt0) begin |
// if the previous instruction is a LW, then grab result from memq, not the iq |
iqentry_a3_v [tail1] <= `INV; |
iqentry_a3_s [tail1] <= { 1'b0, fetchbuf0_mem &IsLoad(fetchbuf0_instr), tail0 }; |
end |
// if no overlap, get info from rf_v and rf_source |
else begin |
iqentry_a3_v [tail1] <= regIsValid[Rc1s]; |
iqentry_a3_s [tail1] <= rf_source[ Rc1s ]; |
end |
a3_vs(); |
|
// if the two instructions enqueued target the same register, |
// make sure only the second writes to rf_v and rf_source. |
6139,62 → 5987,13
end |
|
// SOURCE 1 ... |
// if previous instruction writes nothing to RF, then get info from rf_v and rf_source |
if (~fetchbuf0_rfw) begin |
iqentry_a1_v [tail1] <= regIsValid[Ra1s]; |
iqentry_a1_s [tail1] <= rf_source [Ra1s]; |
end |
// otherwise, previous instruction does write to RF ... see if overlap |
else if (Ra1s == Rt0s) begin |
iqentry_a1_v [tail1] <= `INV; |
iqentry_a1_s [tail1] <= { 1'b0, fetchbuf0_memld, tail0 }; |
end |
// if no overlap, get info from regIsValid and rf_source |
else begin |
iqentry_a1_v [tail1] <= regIsValid[Ra1s]; |
iqentry_a1_s [tail1] <= rf_source [Ra1s]; |
end |
a1_vs(); |
|
// SOURCE 2 ... |
// if the argument is an immediate or not needed, we're done |
$display("Rb1s=%h, Rt0s=%h", Rb1s, Rt0s); |
$display("instr=%h", fetchbuf1_instr); |
// if previous instruction writes nothing to RF, then get info from regIsValid and rf_source |
if (~fetchbuf0_rfw) begin |
$display("fetchbuf0_rfw=0"); |
iqentry_a2_v [tail1] <= regIsValid[Rb1s]; |
iqentry_a2_s [tail1] <= rf_source[ Rb1s ]; |
end |
// otherwise, previous instruction does write to RF ... see if overlap |
else if (Rb1s == Rt0s) begin |
// if the previous instruction is a LW, then grab result from memq, not the iq |
iqentry_a2_v [tail1] <= `INV; |
iqentry_a2_s [tail1] <= { 1'b0, fetchbuf0_memld, tail0 }; |
end |
// if no overlap, get info from regIsValid and rf_source |
else begin |
$display("No overlap"); |
iqentry_a2_v [tail1] <= regIsValid[Rb1s]; |
iqentry_a2_s [tail1] <= rf_source[ Rb1s ]; |
end |
a2_vs(); |
|
// SOURCE 3 ... |
// if previous instruction writes nothing to RF, then get info from regIsValid and rf_source |
if (~fetchbuf0_rfw) begin |
iqentry_a3_v [tail1] <= regIsValid[Rc1s]; |
iqentry_a3_s [tail1] <= rf_source[ Rc1s ]; |
end |
// otherwise, previous instruction does write to RF ... see if overlap |
else if (Rc1s == Rt0s) begin |
// if the previous instruction is a LW, then grab result from memq, not the iq |
iqentry_a3_v [tail1] <= `INV; |
iqentry_a3_s [tail1] <= { 1'b0, fetchbuf0_memld, tail0 }; |
end |
// if no overlap, get info from regIsValid and rf_source |
else begin |
iqentry_a3_v [tail1] <= regIsValid[Rc1s]; |
iqentry_a3_s [tail1] <= rf_source[ Rc1s ]; |
end |
a3_vs(); |
|
// if the two instructions enqueued target the same register, |
// make sure only the second writes to regIsValid and rf_source. |
6315,7 → 6114,7
end |
// Only safe place to propagate the miss pc is a0. |
iqentry_a0[ fcu_id[`QBITS] ] <= fcu_misspc; |
// Update branch taken indicator. |
// Update branch target update indicator. |
if (fcu_jal || fcu_ret || fcu_brk || fcu_rti) begin |
iqentry_bt[ fcu_id[`QBITS] ] <= `VAL; |
end |
7085,12 → 6884,13
endcase |
|
|
rf_source[0] <= 0; |
L1_wr0 <= FALSE; |
L1_wr1 <= FALSE; |
L1_invline <= FALSE; |
icnxt <= FALSE; |
L2_nxt <= FALSE; |
rf_source[0] <= 0; |
L1_wr0 <= FALSE; |
L1_wr1 <= FALSE; |
L1_wr2 <= FALSE; |
L1_invline <= FALSE; |
icnxt <= FALSE; |
L2_nxt <= FALSE; |
// Instruction cache state machine. |
// On a miss first see if the instruction is in the L2 cache. No need to go to |
// the BIU on an L1 miss. |
7098,7 → 6898,7
|
// Capture the previous ic state, used to determine how long to wait in |
// icstate #4. |
picstate <= icstate; |
picstate <= icstate; |
case(icstate) |
IDLE: |
// If the bus unit is busy doing an update involving L1_adr or L2_adr |
7105,8 → 6905,8
// we have to wait. |
if (bstate != B7 && bstate != B9) begin |
if (!ihit0) begin |
L1_adr <= {pcr[5:0],pc0[31:3],3'h0}; |
L2_adr <= {pcr[5:0],pc0[31:3],3'h0}; |
L1_adr <= {pcr[5:0],pc0[31:5],5'h0}; |
L2_adr <= {pcr[5:0],pc0[31:5],5'h0}; |
L1_invline <= TRUE; |
icwhich <= 2'b00; |
iccnt <= 3'b00; |
7113,13 → 6913,14
icstate <= IC2; |
end |
else if (!ihit1 && `WAYS > 1) begin |
`ifdef SUPPORT_SMT |
L1_adr <= {pcr[5:0],pc1[31:3],3'h0}; |
L2_adr <= {pcr[5:0],pc1[31:3],3'h0}; |
`else |
L1_adr <= {pcr[5:0],pc0plus6[31:3],3'h0}; |
L2_adr <= {pcr[5:0],pc0plus6[31:3],3'h0}; |
`endif |
if (thread_en) begin |
L1_adr <= {pcr[5:0],pc1[31:5],5'h0}; |
L2_adr <= {pcr[5:0],pc1[31:5],5'h0}; |
end |
else begin |
L1_adr <= {pcr[5:0],pc0plus6[31:5],5'h0}; |
L2_adr <= {pcr[5:0],pc0plus6[31:5],5'h0}; |
end |
L1_invline <= TRUE; |
icwhich <= 2'b01; |
iccnt <= 3'b00; |
7126,13 → 6927,14
icstate <= IC2; |
end |
else if (!ihit2 && `WAYS > 2) begin |
`ifdef SUPPORT_SMT |
L1_adr <= {pcr[5:0],pc2[31:3],3'h0}; |
L2_adr <= {pcr[5:0],pc2[31:3],3'h0}; |
`else |
L1_adr <= {pcr[5:0],pc0plus12[31:3],3'h0}; |
L2_adr <= {pcr[5:0],pc0plus12[31:3],3'h0}; |
`endif |
if (thread_en) begin |
L1_adr <= {pcr[5:0],pc2[31:5],5'h0}; |
L2_adr <= {pcr[5:0],pc2[31:5],5'h0}; |
end |
else begin |
L1_adr <= {pcr[5:0],pc0plus12[31:5],5'h0}; |
L2_adr <= {pcr[5:0],pc0plus12[31:5],5'h0}; |
end |
L1_invline <= TRUE; |
icwhich <= 2'b10; |
iccnt <= 3'b00; |
8464,7 → 8266,7
// iqentry_Ra [nn] <= bus[`IB_RA]; |
iqentry_a0 [nn] <= bus[`IB_CONST]; |
iqentry_imm [nn] <= bus[`IB_IMM]; |
iqentry_insln[nn] <= bus[`IB_LN]; |
// iqentry_insln[nn] <= bus[`IB_LN]; |
iqentry_jal [nn] <= bus[`IB_JAL]; |
iqentry_ret [nn] <= bus[`IB_RET]; |
iqentry_irq [nn] <= bus[`IB_IRQ]; |
8501,6 → 8303,104
end |
endtask |
|
task a1_vs; |
begin |
// if there is not an overlapping write to the register file. |
if (Ra1s != Rt0s || !fetchbuf0_rfw) begin |
iqentry_a1_v [tail1] <= regIsValid[Ra1s]; |
iqentry_a1_s [tail1] <= rf_source [Ra1s]; |
end |
else begin |
iqentry_a1_v [tail1] <= `INV; |
iqentry_a1_s [tail1] <= { 1'b0, fetchbuf0_memld, tail0 }; |
end |
end |
endtask |
|
task a2_vs; |
begin |
// if there is not an overlapping write to the register file. |
if (Rb1s != Rt0s || !fetchbuf0_rfw) begin |
iqentry_a2_v [tail1] <= regIsValid[Rb1s]; |
iqentry_a2_s [tail1] <= rf_source [Rb1s]; |
end |
else begin |
iqentry_a2_v [tail1] <= `INV; |
iqentry_a2_s [tail1] <= { 1'b0, fetchbuf0_memld, tail0 }; |
end |
end |
endtask |
|
task a3_vs; |
begin |
// if there is not an overlapping write to the register file. |
if (Rc1s != Rt0s || !fetchbuf0_rfw) begin |
iqentry_a3_v [tail1] <= regIsValid[Rc1s]; |
iqentry_a3_s [tail1] <= rf_source [Rc1s]; |
end |
else begin |
iqentry_a3_v [tail1] <= `INV; |
iqentry_a3_s [tail1] <= { 1'b0, fetchbuf0_memld, tail0 }; |
end |
end |
endtask |
|
task enque0x; |
begin |
if (IsVector(fetchbuf0_instr) && SUP_VECTOR) begin |
vqe0 <= vqe0 + 4'd1; |
if (IsVCmprss(fetchbuf0_instr)) begin |
if (vm[fetchbuf0_instr[25:23]][vqe0]) |
vqet0 <= vqet0 + 4'd1; |
end |
else |
vqet0 <= vqet0 + 4'd1; |
if (vqe0 >= vl-2) |
nop_fetchbuf <= fetchbuf ? 4'b1000 : 4'b0010; |
enque0(tail0, fetchbuf0_thrd ? seq_num1 : seq_num, vqe0); |
if (fetchbuf0_thrd) |
seq_num1 <= seq_num1 + 5'd1; |
else |
seq_num <= seq_num + 5'd1; |
if (fetchbuf0_rfw) begin |
rf_source[ Rt0s ] <= { 1'b0, fetchbuf0_memld, tail0 }; // top bit indicates ALU/MEM bus |
rf_v[Rt0s] <= `INV; |
end |
if (canq2) begin |
if (vqe0 < vl-2) begin |
vqe0 <= vqe0 + 4'd2; |
if (IsVCmprss(fetchbuf0_instr)) begin |
if (vm[fetchbuf0_instr[25:23]][vqe0+6'd1]) |
vqet0 <= vqet0 + 4'd2; |
end |
else |
vqet0 <= vqet0 + 4'd2; |
enque0(tail1, fetchbuf0_thrd ? seq_num1 + 5'd1 : seq_num+5'd1, vqe0 + 6'd1); |
if (fetchbuf0_thrd) |
seq_num1 <= seq_num1 + 5'd2; |
else |
seq_num <= seq_num + 5'd2; |
if (fetchbuf0_rfw) begin |
rf_source[ Rt0s ] <= { 1'b0, fetchbuf0_memld, tail1 }; // top bit indicates ALU/MEM bus |
rf_v[Rt0s] <= `INV; |
end |
end |
end |
end |
else begin |
enque0(tail0, fetchbuf0_thrd ? seq_num1 : seq_num, 6'd0); |
if (fetchbuf0_thrd) |
seq_num1 <= seq_num1 + 5'd1; |
else |
seq_num <= seq_num + 5'd1; |
if (fetchbuf0_rfw) begin |
rf_source[ Rt0s ] <= { 1'b0, fetchbuf0_memld, tail0 }; // top bit indicates ALU/MEM bus |
rf_v[Rt0s] <= `INV; |
end |
end |
end |
endtask |
|
// Enqueue fetchbuf0 onto the tail of the instruction queue |
task enque0; |
input [`QBITS] tail; |
8524,6 → 8424,7
iqentry_out [tail] <= `INV; |
iqentry_res [tail] <= `ZERO; |
iqentry_instr[tail] <= IsVLS(fetchbuf0_instr) ? (vm[fnM2(fetchbuf0_instr)] ? fetchbuf0_instr : `NOP_INSN) : fetchbuf0_instr; |
iqentry_insln[tail] <= fetchbuf0_insln; |
iqentry_pt [tail] <= predict_taken0; |
iqentry_agen [tail] <= `INV; |
iqentry_state[tail] <= IQS_IDLE; |
8578,6 → 8479,7
iqentry_out [tail] <= `INV; |
iqentry_res [tail] <= `ZERO; |
iqentry_instr[tail] <= IsVLS(fetchbuf1_instr) ? (vm[fnM2(fetchbuf1_instr)] ? fetchbuf1_instr : `NOP_INSN) : fetchbuf1_instr; |
iqentry_insln[tail] <= fetchbuf1_insln; |
iqentry_pt [tail] <= predict_taken1; |
iqentry_agen [tail] <= `INV; |
iqentry_state[tail] <= IQS_IDLE; |
/FT64v5/rtl/twoway/FT64_fetchbuf.v
34,6 → 34,7
// |
module FT64_fetchbuf(rst, clk4x, clk, fcu_clk, |
cs_i, cyc_i, stb_i, ack_o, we_i, adr_i, dat_i, |
cmpgrp, |
freezePC, thread_en, |
regLR, |
insn0, insn1, phit, |
72,6 → 73,7
input we_i; |
input [15:0] adr_i; |
input [31:0] dat_i; |
input [2:0] cmpgrp; |
input freezePC; |
input thread_en; |
input [4:0] regLR; |
164,11 → 166,14
|
function [3:0] fnInsLength; |
input [47:0] ins; |
case(ins[7:6]) |
2'd0: fnInsLength = 4'd4; |
2'd1: fnInsLength = 4'd6; |
default: fnInsLength = 4'd2; |
endcase |
if (ins[`INSTRUCTION_OP]==`CMPRSSD) |
fnInsLength = 4'd2; |
else |
case(ins[7:6]) |
2'd0: fnInsLength = 4'd4; |
2'd1: fnInsLength = 4'd6; |
default: fnInsLength = 4'd2; |
endcase |
endfunction |
|
|
191,12 → 196,12
// Table of decompressed instructions. |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
assign ack_o = cs_i & cyc_i & stb_i; |
reg [47:0] DecompressTable [0:1023]; |
reg [47:0] DecompressTable [0:2047]; |
always @(posedge clk) |
if (cs_i & cyc_i & stb_i & we_i) |
DecompressTable[adr_i[11:2]] <= dat_i; |
wire [47:0] expand0 = DecompressTable[insn0[15:6]]; |
wire [47:0] expand1 = DecompressTable[insn1[15:6]]; |
DecompressTable[adr_i[12:3]] <= dat_i; |
wire [47:0] expand0 = DecompressTable[{cmpgrp,insn0[15:8]}]; |
wire [47:0] expand1 = DecompressTable[{cmpgrp,insn1[15:8]}]; |
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
798,7 → 803,9
|
always @* |
begin |
if (insn0[7:6]==2'b00 && insn0[`INSTRUCTION_OP]==`EXEC) |
if (insn0[5:0]==`CMPRSSD) |
fetchbuf0_insln <= 4'd2; |
else if (insn0[7:6]==2'b00 && insn0[`INSTRUCTION_OP]==`EXEC) |
fetchbuf0_insln <= fnInsLength(codebuf0); |
else |
fetchbuf0_insln <= fnInsLength(insn0); |
806,7 → 813,9
|
always @* |
begin |
if (insn1[7:6]==2'b00 && insn1[`INSTRUCTION_OP]==`EXEC) |
if (insn1[5:0]==`CMPRSSD) |
fetchbuf1_insln <= 4'd2; |
else if (insn1[7:6]==2'b00 && insn1[`INSTRUCTION_OP]==`EXEC) |
fetchbuf1_insln <= fnInsLength(codebuf1); |
else |
fetchbuf1_insln <= fnInsLength(insn1); |
816,7 → 825,9
|
always @* |
begin |
if (insn0[7:6]==2'b00 && insn0[`INSTRUCTION_OP]==`EXEC) |
if (insn0[5:0]==`CMPRSSD) |
cinsn0 <= expand0; |
else if (insn0[7:6]==2'b00 && insn0[`INSTRUCTION_OP]==`EXEC) |
cinsn0 <= codebuf0; |
else if (insn0[7]) |
cinsn0 <= xinsn0; |
826,7 → 837,9
|
always @* |
begin |
if (insn1[7:6]==2'b00 && insn1[`INSTRUCTION_OP]==`EXEC) |
if (insn1[5:0]==`CMPRSSD) |
cinsn1 <= expand1; |
else if (insn1[7:6]==2'b00 && insn1[`INSTRUCTION_OP]==`EXEC) |
cinsn1 <= codebuf1; |
else if (insn1[7]) |
cinsn1 <= xinsn1; |
/FT64v5/software/AS64/source/FT64.cpp
33,8 → 33,6
extern int first_rodata; |
extern int first_data; |
extern int first_bss; |
extern int htable[100000]; |
extern int htblcnt[100000]; |
extern int htblmax; |
extern int pass; |
extern int num_cinsns; |
1055,89 → 1053,70
|
static void emit_insn(int64_t oc, int can_compress, int sz) |
{ |
int ndx; |
int ndx; |
|
if (pass==3 && can_compress && gCanCompress) { |
for (ndx = 0; ndx < htblmax; ndx++) { |
if ((int)oc == hTable[ndx].opcode) { |
hTable[ndx].count++; |
return; |
} |
} |
if (htblmax < 100000) { |
hTable[htblmax].opcode = (int)oc; |
hTable[htblmax].count = 1; |
htblmax++; |
return; |
} |
error("Too many instructions"); |
return; |
} |
if (pass > 3) { |
if (can_compress && gCanCompress) { |
for (ndx = 0; ndx < min(128,htblmax); ndx++) { |
if ((int)oc == hTable[ndx].opcode) { |
emitCode(((ndx << 6)|0x3F) & 0xff); |
emitCode(((ndx << 6)|0x3F) >> 8); |
num_bytes += 2; |
num_insns += 1; |
return; |
} |
} |
} |
if (sz==2) { |
emitCode(oc & 255); |
emitCode((oc >> 8) & 255); |
num_bytes += 2; |
num_insns += 1; |
num_cinsns += 1; |
return; |
} |
if (sz == 4) { |
emitCode(oc & 255); |
emitCode((oc >> 8) & 255); |
emitCode((oc >> 16) & 255); |
emitCode((oc >> 24) & 255); |
num_bytes += 4; |
num_insns += 1; |
return; |
} |
emitCode(oc & 255); |
emitCode((oc >> 8) & 255); |
emitCode((oc >> 16) & 255); |
emitCode((oc >> 24) & 255); |
emitCode((oc >> 32LL) & 255); |
emitCode((oc >> 40LL) & 255); |
num_bytes += 6; |
//if (sz==3) { |
// emitCode((int)(oc >> 16)); |
// num_bytes += 2; |
// emitCode(oc >> 32); |
// num_bytes += 2; |
//} |
num_insns += 1; |
/* |
if (processOpt==2) { |
for (ndx = 0; ndx < htblmax; ndx++) { |
if (oc == hTable[ndx].opcode) { |
printf("found opcode\n"); |
emitAlignedCode(((ndx & 8) << 4)|0x50|(ndx & 0x7)); |
emitCode(ndx >> 4); |
return; |
} |
} |
emitAlignedCode(oc & 255); |
emitCode((oc >> 8) & 255); |
emitCode((oc >> 16) & 255); |
emitCode((oc >> 24) & 255); |
} |
else { |
emitAlignedCode(oc & 255); |
emitCode((oc >> 8) & 255); |
emitCode((oc >> 16) & 255); |
emitCode((oc >> 24) & 255); |
*/ |
} |
switch (sz) { |
case 6: oc = oc & 0xffffffffffffLL; break;// 48-bits max |
case 4: oc = oc & 0xffffffffLL; break; |
default: oc = oc & 0xffffLL; break; |
} |
if (sz > 2) { |
if (pass == 3 && can_compress && gCanCompress) { |
for (ndx = 0; ndx < htblmax; ndx++) { |
if (oc == hTable[ndx].opcode) { |
hTable[ndx].count++; |
return; |
} |
} |
if (htblmax < 100000) { |
hTable[htblmax].opcode = oc; |
hTable[htblmax].count = 1; |
htblmax++; |
return; |
} |
error("Too many instructions"); |
return; |
} |
} |
if (pass > 3) { |
if (can_compress && gCanCompress && sz > 2) { |
for (ndx = 0; ndx < min(256, htblmax); ndx++) { |
if (oc == hTable[ndx].opcode) { |
emitCode(0x2D); |
emitCode(ndx); |
num_bytes += 2; |
num_insns += 1; |
num_cinsns += 1; |
return; |
} |
} |
} |
if (sz==2) { |
emitCode(oc & 255); |
emitCode((oc >> 8) & 255); |
num_bytes += 2; |
num_insns += 1; |
num_cinsns += 1; |
return; |
} |
if (sz == 4) { |
emitCode(oc & 255); |
emitCode((oc >> 8) & 255); |
emitCode((oc >> 16) & 255); |
emitCode((oc >> 24) & 255); |
num_bytes += 4; |
num_insns += 1; |
return; |
} |
emitCode(oc & 255); |
emitCode((oc >> 8) & 255); |
emitCode((oc >> 16) & 255); |
emitCode((oc >> 24) & 255); |
emitCode((oc >> 32LL) & 255); |
emitCode((oc >> 40LL) & 255); |
num_bytes += 6; |
num_insns += 1; |
} |
} |
|
void LoadConstant(int64_t val, int rg) |
1159,13 → 1138,14
} |
if (IsNBit(val, 49)) { |
emit_insn( |
((val >> 30) << 13LL) | |
((val >> 30LL) << 13LL) | |
(rg << 8) | |
0x27, !expand_flag, 4); // LUI |
if (((val >> 20) & 0xfffffLL) != 0) |
if (((val >> 20LL) & 0xfffffLL) != 0) |
emit_insn( |
(val << 18LL) | |
(rg << 13) | |
(rg << 8) | |
(1 << 6) | |
0x09, !expand_flag, 6); |
return; |
1179,6 → 1159,7
emit_insn( |
(val << 18LL) | |
(rg << 13) | |
(rg << 8) | |
(1 << 6) | |
0x09, !expand_flag, 6); // ORI |
return; |
3015,10 → 2996,10
|
static void process_store(int64_t opcode6, int sz) |
{ |
int Ra,Rb; |
int Rs; |
int Ra,Rb; |
int Rs; |
int Sc; |
int64_t disp,val; |
int64_t disp,val; |
int64_t aq = 0, rl = 0; |
int ar; |
|
3025,14 → 3006,14
GetArBits(&aq, &rl); |
ar = (int)((aq << 1LL) | rl); |
Rs = getRegisterX(); |
if (Rs < 0) { |
printf("Expecting a source register (%d).\r\n", lineno); |
printf("Line:%.60s\r\n",inptr); |
ScanToEOL(); |
return; |
} |
expect(','); |
mem_operand(&disp, &Ra, &Rb, &Sc); |
if (Rs < 0) { |
printf("Expecting a source register (%d).\r\n", lineno); |
printf("Line:%.60s\r\n",inptr); |
ScanToEOL(); |
return; |
} |
expect(','); |
mem_operand(&disp, &Ra, &Rb, &Sc); |
if (Ra > 0 && Rb > 0) { |
switch (sz) { |
case 1: opcode6 = 0x24; break; // SCX |
3049,8 → 3030,8
0x16,!expand_flag,4); |
return; |
} |
if (Ra < 0) Ra = 0; |
val = disp; |
if (Ra < 0) Ra = 0; |
val = disp; |
if (Ra == 55) |
val -= program_address; |
if (sz == 4 && Ra == regSP) { |
3098,7 → 3079,7
(Rs << 18) | |
(23 << 13) | |
(Ra << 8) | |
0x02,!expand_flag,4); |
0x16,!expand_flag,4); |
ScanToEOL(); |
return; |
} |
3316,15 → 3297,15
|
static void process_load(int64_t opcode6, int sz) |
{ |
int Ra,Rb; |
int Rt; |
int Ra,Rb; |
int Rt; |
int Sc; |
char *p; |
int64_t disp; |
int64_t val; |
char *p; |
int64_t disp; |
int64_t val; |
int64_t aq = 0, rl = 0; |
int ar; |
int fixup = 5; |
int fixup = 5; |
|
GetArBits(&aq, &rl); |
ar = (int)((aq << 1LL) | rl); |
3333,15 → 3314,15
Rt = getVecRegister(); |
else |
Rt = getRegisterX(); |
if (Rt < 0) { |
printf("Expecting a target register (%d).\r\n", lineno); |
printf("Line:%.60s\r\n",p); |
ScanToEOL(); |
inptr-=2; |
return; |
} |
expect(','); |
mem_operand(&disp, &Ra, &Rb, &Sc); |
if (Rt < 0) { |
printf("Expecting a target register (%d).\r\n", lineno); |
printf("Line:%.60s\r\n",p); |
ScanToEOL(); |
inptr-=2; |
return; |
} |
expect(','); |
mem_operand(&disp, &Ra, &Rb, &Sc); |
if (Ra > 0 && Rb > 0) { |
// Trap LEA, convert to LEAX opcode |
if (opcode6==0x04) // ADD is really LEA |
3364,7 → 3345,7
0x16,!expand_flag,4); |
return; |
} |
if (Ra < 0) Ra = 0; |
if (Ra < 0) Ra = 0; |
val = disp; |
if (Ra == 55) |
val -= program_address; |
3414,7 → 3395,7
(Rt << 18) | |
(23 << 13) | |
(Ra << 8) | |
0x02,!expand_flag,4); |
0x16,!expand_flag,4); |
ScanToEOL(); |
return; |
} |
3438,19 → 3419,19
|
static void process_cache(int opcode6) |
{ |
int Ra,Rb; |
int Ra,Rb; |
int Sc; |
char *p; |
int64_t disp; |
int64_t val; |
int fixup = 5; |
char *p; |
int64_t disp; |
int64_t val; |
int fixup = 5; |
int cmd; |
|
p = inptr; |
p = inptr; |
NextToken(); |
cmd = (int)expr() & 0x1f; |
expect(','); |
mem_operand(&disp, &Ra, &Rb, &Sc); |
expect(','); |
mem_operand(&disp, &Ra, &Rb, &Sc); |
if (Ra > 0 && Rb > 0) { |
emit_insn( |
(opcode6 << 26) | |
4451,7 → 4432,7
first_data = 1; |
first_bss = 1; |
expandedBlock = 0; |
if (pass<3) { |
if (pass==3) { |
htblmax = 0; |
for (nn = 0; nn < 100000; nn++) { |
hTable[nn].count = 0; |
4525,7 → 4506,7
break; |
case tk_cache: process_cache(0x1E); break; |
case tk_call: process_call(0x19); break; |
case tk_cli: emit_insn(0xC0000002,0,4); break; |
case tk_cli: emit_insn(0xC0000002,!expand_flag,4); break; |
case tk_chk: process_chk(0x34); break; |
case tk_cmovenz: process_cmove(0x29); break; |
//case tk_cmp: process_rrop(0x06); break; |
4619,8 → 4600,8
case tk_lw: process_load(0x20,4); break; |
case tk_lwr: process_load(0x1D,0); break; |
case tk_macro: process_macro(); break; |
case tk_memdb: emit_insn(0x04400002,0,4); break; |
case tk_memsb: emit_insn(0x04440002,0,4); break; |
case tk_memdb: emit_insn(0x04400002,!expand_flag,4); break; |
case tk_memsb: emit_insn(0x04440002,!expand_flag,4); break; |
case tk_message: process_message(); break; |
case tk_mod: process_rrop(0x16,0x2E); break; |
case tk_modu: process_rrop(0x14,-1); break; |
4630,13 → 4611,13
case tk_mulu: process_rrop(0x38,0x38); break; |
//case tk_muluh: process_rrop(0x24, 0x38); break; |
case tk_neg: process_neg(); break; |
case tk_nop: emit_insn(0x1C,0,4); break; |
case tk_nop: emit_insn(0x1C,!expand_flag,4); break; |
case tk_not: process_rop(0x05); break; |
// case tk_not: process_rop(0x07); break; |
case tk_or: process_rrop(0x09,0x09); break; |
case tk_ori: process_riop(0x09); break; |
case tk_org: process_org(); break; |
case tk_plus: expand_flag = 1; break; |
case tk_plus: compress_flag = 0; expand_flag = 1; break; |
case tk_public: process_public(); break; |
case tk_rodata: |
if (first_rodata) { |
4695,7 → 4676,7
case tk_sxb: process_rop(0x1A); break; |
case tk_sxc: process_rop(0x19); break; |
case tk_sxh: process_rop(0x18); break; |
case tk_sync: emit_insn(0x04480002,0,4); break; |
case tk_sync: emit_insn(0x04480002,!expand_flag,4); break; |
//case tk_unlink: emit_insn((0x1B << 26) | (0x1F << 16) | (30 << 11) | (0x1F << 6) | 0x02,0,4); break; |
case tk_vadd: process_vrrop(0x04); break; |
case tk_vadds: process_vsrrop(0x14); break; |
/FT64v5/software/AS64/source/a64.h
115,12 → 115,6
extern clsElf64Section sections[12]; |
extern SYM *lastsym; |
|
typedef struct _tagHBLE |
{ |
int count; |
int opcode; |
} HTBLE; |
|
extern HTBLE hTable[100000]; |
extern int processOpt; |
extern int expandedBlock; |
/FT64v5/software/AS64/source/main.cpp
160,13 → 160,13
|
// Sort the table (already sorted) |
// qsort(pt, htblmax, sizeof(HTBLE), hcmp); |
|
|
if (gCpu=='F') { |
fprintf(ofp, "%d compressable instructions\n", htblmax); |
fprintf(ofp, "The top 256 are:\n", htblmax); |
fprintf(ofp, "Comp Opcode Count\n"); |
for (nn = 0; nn < htblmax && nn < 256; nn++) { |
fprintf(ofp, " %03X %08X %d\n", nn, hTable[nn].opcode, hTable[nn].count); |
fprintf(ofp, " %03X %012I64X %d\n", nn, hTable[nn].opcode, hTable[nn].count); |
} |
return; |
} |
863,9 → 863,9
int nn; |
|
if (gCpu=='F') { |
emitHalf(htblmax > 1024 ? 1024 : htblmax); |
emitWord(htblmax > 1024 ? 1024 : htblmax); |
for (nn = 0; nn < htblmax && nn < 1024; nn++) { |
emitHalf(hTable[nn].opcode); |
emitWord(hTable[nn].opcode); |
} |
return; |
} |
/FT64v5/software/AS64/source/types.h
1,6 → 1,14
#ifndef _TYPES_H |
#define _TYPES_H |
|
// Compressed instructions table entry |
|
typedef struct _tagHBLE |
{ |
int count; |
int64_t opcode; |
} HTBLE; |
|
class Arg |
{ |
public: |