c51e1318ba0ee63d474a5c6799895234c3cb03a8
[calu.git] / cpu / src / decoder_b.vhd
1 library IEEE;
2 use IEEE.std_logic_1164.all;
3 use IEEE.numeric_std.all;
4
5 use work.mem_pkg.all;
6 use work.core_pkg.all;
7 use work.common_pkg.all;
8
9
10 architecture behav_d of decoder is
11
12 begin
13
14 split_instr: process(instruction)
15
16 variable instr_s : instruction_rec;
17
18 begin
19
20         instr_s.predicates := instruction(31 downto 28);
21         instr_s.opcode := instruction(27 downto 27-OPCODE_WIDTH+1);
22
23         instr_s.reg_dest_addr := (others => '0');
24         instr_s.reg_src1_addr := (others => '0');
25         instr_s.reg_src2_addr := (others => '0');
26
27         instr_s.immediate := (others => '0');
28         instr_s.jmptype := (others => '0');
29         instr_s.high_low := '0';
30         instr_s.fill := '0';
31         instr_s.signext := '0';
32         instr_s.bp := '0';
33         instr_s.op_detail := (others => '0');
34         instr_s.displacement := (others => '0');
35         instr_s.int := '0';
36
37         instr_s.op_group := ADDSUB_OP;
38
39 --      type op_info_t is (ADDSUB_OP,AND_OP,OR_OP, XOR_OP,SHIFT_OP);
40
41 --  special function register operations missing
42
43 --      case opcode is
44 --=================================================================
45         if (instr_s.opcode = "00000" or instr_s.opcode = "00001" or instr_s.opcode = "00100" or instr_s.opcode = "00110" or instr_s.opcode = "01000") then
46 --      when "00000" =>         --add
47                 instr_s.reg_dest_addr := instruction(22 downto 19);
48                 instr_s.reg_src1_addr := instruction(18 downto 15);
49                 instr_s.reg_src2_addr := instruction(14 downto 11);
50
51                 instr_s.op_detail(NO_PSW_OPT) := instruction(0); --instr_s.sreg_update;
52                 
53                 instr_s.op_group := ADDSUB_OP;
54
55                 if (instr_s.opcode = "00000") then              
56                         instr_s.op_detail(CARRY_OPT) := instruction(1); --instr_s.carry;
57                 end if;
58
59                 if (instr_s.opcode = "00001") then
60                         instr_s.op_detail(SUB_OPT) := '1';
61                         instr_s.op_detail(CARRY_OPT) := instruction(1); --instr_s.carry;
62                 end if;
63
64                 if (instr_s.opcode = "00100") then
65                         instr_s.op_group := AND_OP;
66                 end if;
67                 
68                 if (instr_s.opcode = "00110") then
69                         instr_s.op_group := OR_OP;
70                 end if;
71                 
72                 if (instr_s.opcode = "01000") then
73                         instr_s.op_group := XOR_OP;
74                 end if;
75
76         end if;
77 --      when "00001" =>         --sub
78 --              instr_s.reg_dest_addr := instruction(22 downto 19);
79 --              instr_s.reg_src1_addr := instruction(18 downto 15);
80 --              instr_s.reg_src2_addr := instruction(14 downto 11);
81 --              instr_s.carry := instruction(1);
82 --              instr_s.sreg_update := instruction(0);
83
84
85 --      when "00100" =>         --and
86 --              instr_s.reg_dest_addr := instruction(22 downto 19);
87 --              instr_s.reg_src1_addr := instruction(18 downto 15);
88 --              instr_s.reg_src2_addr := instruction(14 downto 11);
89 --              instr_s.carry := instruction(1);                        --negligible
90 --              instr_s.sreg_update := instruction(0);
91
92 --      when "00110" =>         --or
93 --              instr_s.reg_dest_addr := instruction(22 downto 19);
94 --              instr_s.reg_src1_addr := instruction(18 downto 15);
95 --              instr_s.reg_src2_addr := instruction(14 downto 11);
96 --              instr_s.carry := instruction(1);                        --negligible
97 --              instr_s.sreg_update := instruction(0);
98
99 --      when "01000" =>         --xor
100 --              instr_s.reg_dest_addr := instruction(22 downto 19);
101 --              instr_s.reg_src1_addr := instruction(18 downto 15);
102 --              instr_s.reg_src2_addr := instruction(14 downto 11);
103 --              instr_s.carry := instruction(1);                        --negligible
104 --              instr_s.sreg_update := instruction(0);
105
106 --=================================================================
107         if (instr_s.opcode = "00010" or instr_s.opcode = "00011") then
108
109 --      when "00010" =>         --addi
110                 instr_s.reg_dest_addr := instruction(22 downto 19);
111                 instr_s.reg_src1_addr := instruction(18 downto 15);
112                 instr_s.immediate(11 downto 0) := instruction(14 downto 3);
113                 instr_s.signext := instruction(2);              
114
115                 if (instr_s.signext = '1' and instr_s.immediate(11) = '1') then
116                         instr_s.immediate(31 downto 12) := (others => '1');
117                 end if;
118
119                 instr_s.op_detail(IMM_OPT) := '1';
120                 instr_s.op_detail(CARRY_OPT) := instruction(1);
121                 instr_s.op_detail(NO_PSW_OPT) := instruction(0);
122
123                 instr_s.op_group := ADDSUB_OP;
124
125                 if (instr_s.opcode = "00011") then
126                         instr_s.op_detail(SUB_OPT) := '1';
127                 end if;
128         end if;
129
130 --      when "00011" =>         --subi
131 --              instr_s.reg_dest_addr := instruction(22 downto 19);
132 --              instr_s.reg_src1_addr := instruction(18 downto 15);
133 --              instr_s.immediate(11 downto 0) := instruction(14 downto 3);
134 --              instr_s.signext := instruction(2);              
135 --              instr_s.carry := instruction(1);
136 --              instr_s.sreg_update := instruction(0);
137
138
139
140
141 --=================================================================
142         if (instr_s.opcode = "00101" or instr_s.opcode = "00111" or instr_s.opcode = "01001") then
143
144 --      when "00101" =>         --andx
145                 instr_s.reg_dest_addr := instruction(22 downto 19);
146                 instr_s.reg_src1_addr := instruction(22 downto 19);
147                 instr_s.immediate(15 downto 0) := instruction(18 downto 3);
148                 instr_s.high_low := instruction(2);             
149                 instr_s.fill := instruction(1);
150
151                 if (instr_s.fill = '1') then
152                         instr_s.immediate(31 downto 16) := (others => '1');
153                 end if;
154
155                 instr_s.op_detail(IMM_OPT) := '1';
156                 instr_s.op_detail(NO_PSW_OPT) := instruction(0);
157
158                 if (instr_s.opcode = "00101") then
159                         instr_s.op_group := AND_OP;
160                 end if;
161
162                 if (instr_s.opcode = "00111") then
163                         instr_s.op_group := OR_OP;
164                 end if;
165
166                 if (instr_s.opcode = "01001") then
167                         instr_s.op_group := XOR_OP;
168                 end if;
169         end if;
170
171 --      when "00111" =>         --orx
172 --              instr_s.reg_dest_addr := instruction(22 downto 19);
173 --              instr_s.reg_src1_addr := instruction(22 downto 19);
174 --              instr_s.immediate(15 downto 0) := instruction(18 downto 3);
175 --              instr_s.high_low := instruction(2);             
176 --              instr_s.fill := instruction(1);
177 --              instr_s.sreg_update := instruction(0);
178 --
179 --      when "01001" =>         --xorx
180 --              instr_s.reg_dest_addr := instruction(22 downto 19);
181 --              instr_s.reg_src1_addr := instruction(22 downto 19);
182 --              instr_s.immediate(15 downto 0) := instruction(18 downto 3);
183 --              instr_s.high_low := instruction(2);             
184 --              instr_s.fill := instruction(1);
185 --              instr_s.sreg_update := instruction(0);
186 --
187 --=================================================================
188         if (instr_s.opcode = "01010") then
189
190 --      when "01010" =>         --shift
191                 instr_s.reg_dest_addr := instruction(22 downto 19);
192                 instr_s.reg_src1_addr := instruction(18 downto 15);
193                 instr_s.immediate(4 downto 0) := instruction(14 downto 10);
194
195                 instr_s.op_detail(RIGHT_OPT) := instruction(3);
196                 instr_s.op_detail(NO_PSW_OPT) := instruction(0);
197                 instr_s.op_detail(CARRY_OPT) := instruction(1);
198                 instr_s.op_detail(ARITH_OPT) := instruction(2);
199                 instr_s.op_detail(IMM_OPT) := '1';
200
201                 instr_s.op_group := SHIFT_OP;
202         end if;
203
204 --      when "01011" =>         --stackop
205 --              instr_s.reg_dest_addr := instruction(22 downto 19);
206 --              instr_s.reg_src1_addr := instruction(22 downto 19);
207 --              instr_s.immediate(1 downto 0) := instruction(18 downto 17);
208 --              instr_s.left_right := instruction(3);           
209 --              instr_s.arith := instruction(2);                
210 --              instr_s.carry := instruction(1);
211 --              instr_s.sreg_update := instruction(0);
212
213 --=================================================================
214         if (instr_s.opcode = "01110" or instr_s.opcode = "10000" or instr_s.opcode = "10010" or instr_s.opcode = "11010") then
215
216 --      when "01110" =>         --ldw
217                 instr_s.reg_dest_addr := instruction(22 downto 19);
218                 instr_s.reg_src1_addr := instruction(18 downto 15);
219                 instr_s.signext := instruction(2);
220                 instr_s.high_low := instruction(1);
221                 instr_s.displacement(14 downto 0) := instruction(14 downto 0);
222
223                 instr_s.op_group := LDST_OP;
224                 instr_s.op_detail(NO_PSW_OPT) := '1';
225
226                 if (instr_s.displacement(14) = '1') then
227                         instr_s.displacement(31 downto 15) := (others => '1');
228                 end if;
229
230                 if (instr_s.opcode = "11010") then              --ldi
231                         instr_s.reg_src1_addr := instr_s.reg_dest_addr;
232                         instr_s.op_detail(LOW_HIGH_OPT) := instr_s.high_low;
233                         instr_s.op_detail(LDI_REPLACE_OPT) := instr_s.signext;
234                         
235                         if (instr_s.high_low = '1') then
236                                 instr_s.immediate(31 downto 16) := instruction(18 downto 3);
237                                 instr_s.immediate(15 downto 0) := (others => '0');
238                         else
239                                 instr_s.immediate(15 downto 0) := instruction(18 downto 3);
240                                 instr_s.immediate(31 downto 16) := (others => '0');
241                         end if;                 
242
243                         if (instr_s.signext = '1' and instr_s.immediate(11) = '1') then
244                                 instr_s.immediate(31 downto 16) := (others => '1');
245                         end if;
246
247                         instr_s.op_detail(IMM_OPT) := '1';
248                 end if;
249                 
250                 if (instr_s.opcode = "10000") then
251                         instr_s.op_detail(HWORD_OPT) := '1';
252                 end if;
253                 
254                 if (instr_s.opcode = "10010") then
255                         instr_s.op_detail(BYTE_OPT) := '1';
256                 end if;
257         end if;
258
259 --      when "10000" =>         --ldh
260 --              instr_s.reg_dest_addr := instruction(22 downto 19);
261 --              instr_s.reg_src1_addr := instruction(18 downto 15);
262 --              instr_s.displacement(14 downto 0) := instruction(14 downto 0);
263 --              instr_s.immediate(15 downto 0) := instruction(18 downto 3);
264 --              instr_s.signext := instruction(2);
265 --              instr_s.high_low := instruction(1);
266
267 --      when "10010" =>         --ldb
268 --              instr_s.reg_dest_addr := instruction(22 downto 19);
269 --              instr_s.reg_src1_addr := instruction(18 downto 15);
270 --              instr_s.displacement(14 downto 0) := instruction(14 downto 0);
271 --              instr_s.immediate(15 downto 0) := instruction(18 downto 3);
272 --              instr_s.signext := instruction(2);
273 --              instr_s.high_low := instruction(1);
274
275 --      when "11010" =>         --ldi
276 --              instr_s.reg_dest_addr := instruction(22 downto 19);
277 --              instr_s.reg_src1_addr := instruction(18 downto 15);
278 --              instr_s.displacement(14 downto 0) := instruction(14 downto 0);
279 --              instr_s.immediate(15 downto 0) := instruction(18 downto 3);
280 --              instr_s.signext := instruction(2);
281 --              instr_s.high_low := instruction(1);
282
283 --=================================================================
284         if (instr_s.opcode = "01111" or instr_s.opcode = "10001" or instr_s.opcode = "10011" or instr_s.opcode = "10101") then
285
286         --when "01111" =>               --stw
287                 instr_s.reg_src2_addr := instruction(22 downto 19);     -- register value
288                 instr_s.reg_src1_addr := instruction(18 downto 15);     -- mem addr
289                 instr_s.displacement(14 downto 0) := instruction(14 downto 0);
290                 instr_s.op_detail(NO_PSW_OPT) := '1';
291                 instr_s.op_detail(ST_OPT) := '1';
292                 instr_s.op_group := LDST_OP;
293
294                 if (instr_s.displacement(14) = '1') then
295                         instr_s.displacement(31 downto 15) := (others => '1');
296                 end if;
297
298                 if (instr_s.opcode = "10001") then
299                         instr_s.op_detail(HWORD_OPT) := '1';
300                 end if;
301                 
302                 if (instr_s.opcode = "10011") then
303                         instr_s.op_detail(BYTE_OPT) := '1';
304                 end if;
305
306         end if;
307
308         -- ===============================================================
309         
310         if (instr_s.opcode = "01011") then      -- stack op
311                 instr_s.reg_src1_addr := instruction(22 downto 19);
312                 instr_s.reg_dest_addr := instruction(22 downto 19);
313                 instr_s.op_group := STACK_OP;
314                 instr_s.op_detail(NO_PSW_OPT) := '1';
315         
316                 case instruction(18 downto 17) is
317                         when "00" => 
318                                 instr_s.op_detail(PUSH_OPT) := '0';
319                         
320                         when "01" => null;
321                         
322                         when "10" => null;
323                         
324                         when "11" =>
325                                 instr_s.op_detail(PUSH_OPT) := '1';
326                                 
327                         when others => null;
328                 end case;
329         
330         end if;
331         
332 --      when "10001" =>         --sth
333 --              instr_s.reg_src1_addr := instruction(22 downto 19);
334 --              instr_s.reg_src2_addr := instruction(18 downto 15);
335 --              instr_s.displacement(14 downto 0) := instruction(14 downto 0);
336
337 --      when "10011" =>         --stb
338 --              instr_s.reg_src1_addr := instruction(22 downto 19);
339 --              instr_s.reg_src2_addr := instruction(18 downto 15);
340 --              instr_s.displacement(14 downto 0) := instruction(14 downto 0);
341
342 --      when "10101" =>         --stx
343 --              instr_s.reg_src1_addr := instruction(22 downto 19);
344 --              instr_s.reg_src2_addr := instruction(18 downto 15);
345 --              instr_s.displacement(14 downto 0) := instruction(14 downto 0);
346
347 --=================================================================
348         if (instr_s.opcode = "10110" or instr_s.opcode = "10111") then
349
350 --      when "10110" =>         --jumpop
351                 instr_s.reg_src1_addr := instruction(22 downto 19);     -- register value
352                 instr_s.immediate(15 downto 0) := instruction(22 downto 7);
353                 instr_s.bp := instruction(1);
354                 instr_s.jmptype := instruction(3 downto 2);
355                 instr_s.signext := instruction(0);
356                 instr_s.op_detail(NO_PSW_OPT) := '1';
357                 instr_s.op_detail(DIRECT_JUMP_OPT) := instruction(4);
358                 instr_s.int := instruction(4);
359
360                 if (instr_s.opcode = "10110") then
361                         instr_s.op_detail(IMM_OPT) := '1';      
362                 else
363                         instr_s.immediate(31 downto 0) := (others => '0');
364                         instr_s.op_detail(JMP_REG_OPT) := '1';
365                         instr_s.op_detail(IMM_OPT) := '1';      
366                 end if;
367
368                 if (instr_s.signext = '1' and instr_s.immediate(15) = '1') then
369                         instr_s.immediate(31 downto 16) := (others => '1');
370                 end if;
371
372                 if (instr_s.jmptype = "00") then
373 --                      instr_s.op_detail(SUB_OPT) := not instr_s.opcode(0);
374                         instr_s.op_group := JMP_OP;
375                 end if;
376                 
377                 if (instr_s.jmptype = "01") then
378                         instr_s.op_group := JMP_ST_OP;
379                 --      instr_s.op_detail(RET_OPT) := '0';
380                 end if;
381
382                 if (instr_s.jmptype = "10") then
383                         instr_s.op_group := JMP_ST_OP;
384                         instr_s.op_detail(RET_OPT) := '1';
385                 end if;
386
387                 if (instr_s.predicates = "1111" or instr_s.jmptype = "10") then
388                         instr_s.bp := '0';
389                 end if;
390         end if;
391
392 --      when "10111" =>         --brreg
393 --              instr_s.reg_src1_addr := instruction(22 downto 19);     -- register value
394 --              instr_s.immediate(15 downto 0) := instruction(22 downto 7);     -- negligible
395 --              instr_s.bp := instruction(1);                           -- negligible
396 --              instr_s.jmptype := instruction(3 downto 2);             -- only lsb
397 --              instr_s.signext := instruction(0);                      -- negligible
398
399 --=================================================================
400         if (instr_s.opcode = "11000" or instr_s.opcode = "11001") then
401
402 --      when "11000" =>         --cmp
403                 instr_s.reg_src1_addr := instruction(22 downto 19);
404                 instr_s.reg_src2_addr := instruction(18 downto 15);
405
406                 if (instr_s.opcode = "11001") then
407                         instr_s.immediate(15 downto 0) := instruction(18 downto 3);
408                         instr_s.signext := instruction(2);              
409
410                         if (instr_s.signext = '1' and instr_s.immediate(15) = '1') then
411                                 instr_s.immediate(31 downto 16) := (others => '1');
412                         end if;
413
414                         instr_s.op_detail(IMM_OPT) := '1';
415                 end if;
416                 instr_s.op_detail(NO_DST_OPT) := '1';
417                 instr_s.op_group := ADDSUB_OP;
418                 instr_s.op_detail(SUB_OPT) := '1';
419
420         end if;
421
422 --      when "11001" =>         --cmpi
423 --              instr_s.reg_src1_addr := instruction(22 downto 19);
424 --              instr_s.reg_src2_addr := instruction(18 downto 15);
425 --              instr_s.immediate(15 downto 0) := instruction(18 downto 3);
426
427 --      when others => null;
428
429 --      end case;
430
431
432
433         instr_spl <= instr_s;
434
435 end process;
436
437 end behav_d;
438
439
440 --===========================================================================
441
442