Merge branch 'master' of nyus.joshuawise.com:/git/firearm
[firearm.git] / Decode.v
CommitLineData
bae77231
CL
1module Decode(
2 input clk,
3 input [31:0] ansn,
4 input [31:0] inpc,
5 input [31:0] cps_in,
6 output reg [31:0] op0,
7 output reg [31:0] op1,
8 output reg [31:0] op2,
9 output reg [31:0] cps_out,
10
11 output [3:0] regsel0,
12 output [3:0] regsel1,
13 output [3:0] regsel2,
14 input [31:0] iregs0,
15 input [31:0] iregs1,
16 input [31:0] iregs2
17 );
18
19 wire [31:0] regs0, regs1, regs2, rpc;
20 wire [31:0] op1_res, new_cps;
21
22 /* shifter stuff */
23 wire [31:0] shift_oper;
24 wire [31:0] shift_res;
25 wire shift_cflag_out;
26
27 assign regs0 = (regsel0 == 4'b1111) ? rpc : iregs0;
28 assign regs1 = (regsel1 == 4'b1111) ? rpc : iregs1;
29 assign regs2 = iregs2; /* use regs2 for things that cannot be r15 */
30
31 IHATEARMSHIFT(.insn(ansn),
32 .operand(regs1),
33 .reg_amt(regs2),
34 .cflag_in(cps_in[`COND_CBIT]),
35 .res(shift_res),
36 .cflag_out(shift_cflag));
37
38 always @ (*) begin
39 casez (ansn)
40 32'b????000000??????????????1001????: begin /* Multiply */
41 rpc = inpc - 8;
42 regsel0 = ansn[15:12]; /* Rn */
43 regsel1 = ansn[3:0]; /* Rm */
44 regsel2 = ansn[11:8]; /* Rs */
45 op1_res = regs1;
46 new_cps = cps_in;
47 end
48/*
49 32'b????00001???????????????1001????: begin * Multiply long *
50 regsel0 = ansn[11:8]; * Rn *
51 regsel1 = ansn[3:0]; * Rm *
52 regsel2 = 4'b0; * anyus *
53 op1_res = regs1;
54 end
55*/
56 32'b????00010?001111????000000000000: begin /* MRS (Transfer PSR to register) */
57 rpc = inpc - 8;
58 new_cps = cps_in;
59 end
60 32'b????00010?101001111100000000????: begin /* MSR (Transfer register to PSR) */
61 rpc = inpc - 8;
62 new_cps = cps_in;
63 end
64 32'b????00?10?1010001111????????????: begin /* MSR (Transfer register or immediate to PSR, flag bits onry) */
65 rpc = inpc - 8;
66 new_cps = cps_in;
67 end
68 32'b????00??????????????????????????: begin /* ALU */
69 rpc = inpc - (ansn[25] ? 8 : (ansn[4] ? 12 : 8));
70 regsel0 = ansn[19:16]; /* Rn */
71 regsel1 = ansn[3:0]; /* Rm */
72 regsel2 = ansn[11:8]; /* Rs for shift */
73 if(ansn[25]) begin /* the constant case */
74 new_cps = cps_in;
75 op1_res = ({24'b0, ansn[7:0]} >> {ansn[11:8], 1'b0}) | ({24'b0, ansn[7:0]} << (5'b0 - {ansn[11:8], 1'b0}));
76 end else begin
77 new_cps = {shift_cflag_out, cps_in[30:0]};
78 op1_res = shift_res;
79 end
80 end
81 32'b????00010?00????????00001001????: begin /* Atomic swap */
82 rpc = inpc - 8;
83 regsel0 = ansn[19:16]; /* Rn */
84 regsel1 = ansn[3:0]; /* Rm */
85 regsel2 = 4'b0; /* anyus */
86 op1_res = regs1;
87 end
88 32'b????000100101111111111110001????: begin /* Branch and exchange */
89 rpc = inpc - 8;
90 regsel0 = ansn[3:0]; /* Rn */
91 new_cps = cps_in;
92 end
93 32'b????000??0??????????00001??1????: begin /* Halfword transfer - register offset */
94 rpc = inpc - 8;
95 regsel0 = ansn[19:16];
96 regsel1 = ansn[3:0];
97 regsel2 = 4'b0;
98 op1_res = regs1;
99 new_cps = cps_in;
100 end
101 32'b????000??1??????????00001??1????: begin /* Halfword transfer - immediate offset */
102 rpc = inpc - 8;
103 regsel0 = ansn[19:16];
104 regsel1 = ansn[3:0];
105 op1_res = {24'b0, ansn[11:8], ansn[3:0]};
106 new_cps = cps_in;
107 end
108 32'b????011????????????????????1????: begin /* Undefined. I hate ARM */
109 /* eat shit */
110 end
111 32'b????01??????????????????????????: begin /* Single data transfer */
112 rpc = inpc - 8;
113 regsel0 = ansn[19:16]; /* Rn */
114 regsel1 = ansn[3:0]; /* Rm */
115 if(ansn[25]) begin
116 op1_res = {20'b0, ansn[11:0]};
117 new_cps = cps_in;
118 end else begin
119 op1_res = shift_res;
120 new_cps = shift_cflag_out;
121 end
122 end
123 32'b????100?????????????????????????: begin /* Block data transfer */
124 rpc = inpc - 8;
125 regsel0 = ansn[19:16];
126 op1_res = {16'b0, ansn[15:0]};
127 new_cps = cps_in;
128 end
129 32'b????101?????????????????????????: begin /* Branch */
130 rpc = inpc - 8;
131 op1_res = {6{ansn[23]}, ansn[23:0], 2'b0};
132 new_cps = cps_in;
133 end
134 32'b????110?????????????????????????: begin /* Coprocessor data transfer */
135 rpc = inpc - 8;
136 regsel0 = ansn[19:16];
137 op1_res = {24'b0, ansn[7:0]};
138 new_cps = cps_in;
139 end
140 32'b????1110???????????????????0????: begin /* Coprocessor data op */
141 rpc = inpc - 8;
142 new_cps = cps_in;
143 end
144 32'b????1110???????????????????1????: begin /* Coprocessor register transfer */
145 rpc = inpc - 8;
146 new_cps = cps_in;
147 end
148 32'b????1111????????????????????????: begin /* SWI */
149 rpc = inpc - 8;
150 new_cps = cps_in;
151 end
152 default:
153 endcase
154 end
155
156 always @ (posedge clk) begin
157 op0 <= regs0; /* Rn - always */
158 op1 <= op1_res; /* 'operand 2' - Rm */
159 op2 <= regs2; /* thirdedge - Rs */
160 cps_out <= new_cps;
161 end
162
163endmodule
164
165module IHATEARMSHIFT(
166 input [31:0] insn,
167 input [31:0] operand,
168 input [31:0] reg_amt,
169 input cflag_in,
170 output [31:0] res,
171 output cflag_out
172);
173 wire [1:0] shift_type;
174 wire [5:0] shift_amt;
175 wire elanus;
176
177 shift_type = insn[6:5];
178 if(insn[4]) begin
179 shift_amt = {|reg_amt[7:5], reg_amt[4:0]};
180 elanus = 1'b1;
181 end else begin
182 shift_amt = {insn[11:7] == 5'b0, insn[11:7]};
183 elanus = 1'b0;
184 end
185
186 /* might want to write our own damn shifter that does arithmetic/logical efficiently and stuff */
187 always @ (*) begin
188 case (shift_type)
189 `SHIFT_LSL: begin
190 {cflag_out, res} = {cflag_in, operand} << {elanus & shift_amt[5], shift_amt[4:0]};
191 end
192 `SHIFT_LSR: begin
193 {res, cflag_out} = {operand, cflag_in} >> shift_amt;
194 end
195 `SHIFT_ASR: begin
196 {res, cflag_out} = {operand, cflag_in} >> shift_amt | (operand[31] ? ~(33'h1FFFFFFFF >> shift_amt) : 33'b0);
197 end
198 `SHIFT_ROR: begin
199 if(!elanus && shift_amt[4:0] == 5'b0) begin /* RRX x.x */
200 res = {cflag_in, operand[31:1]};
201 cflag_out = operand[0];
202 end else if(!shift_amt) begin
203 res = operand;
204 cflag_out = cflag_in;
205 end else begin
206 res = operand >> shift_amt[4:0] | operand << (5'b0 - shift_amt[4:0]);
207 cflag_out = operand[shift_amt[4:0] - 5'b1];
208 end
209 end
210 end
211endmodule
This page took 0.036055 seconds and 4 git commands to generate.