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