ed9ed4a290cf3178670836d0800b19fcd058154f
[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                 instr_s.op_detail(PWREN_OPT) := '1';
316         
317                 case instruction(18 downto 17) is
318                         when "00" => --pop
319                                 instr_s.op_detail(PUSH_OPT) := '0';
320                         
321                         when "01" => --disc
322                                 instr_s.op_detail(PUSH_OPT) := '0';
323                                 instr_s.op_detail(NO_DST_OPT) := '1';
324                         
325                         when "10" => --fetch
326                                 instr_s.op_detail(PUSH_OPT) := '0';
327                                 instr_s.op_detail(PWREN_OPT) := '0';
328                         
329                         when "11" => --push
330                                 instr_s.op_detail(PUSH_OPT) := '1';
331                                 
332                         when others => null;
333                 end case;
334         
335         end if;
336         
337 --      when "10001" =>         --sth
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 "10011" =>         --stb
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 --      when "10101" =>         --stx
348 --              instr_s.reg_src1_addr := instruction(22 downto 19);
349 --              instr_s.reg_src2_addr := instruction(18 downto 15);
350 --              instr_s.displacement(14 downto 0) := instruction(14 downto 0);
351
352 --=================================================================
353         if (instr_s.opcode = "10110" or instr_s.opcode = "10111") then
354
355 --      when "10110" =>         --jumpop
356                 instr_s.reg_src1_addr := instruction(22 downto 19);     -- register value
357                 instr_s.immediate(15 downto 0) := instruction(22 downto 7);
358                 instr_s.bp := instruction(1);
359                 instr_s.jmptype := instruction(3 downto 2);
360                 instr_s.signext := instruction(0);
361                 instr_s.op_detail(NO_PSW_OPT) := '1';
362                 instr_s.op_detail(DIRECT_JUMP_OPT) := instruction(4);
363                 instr_s.int := instruction(4);
364
365                 if (instr_s.opcode = "10110") then
366                         instr_s.op_detail(IMM_OPT) := '1';      
367                 else
368                         instr_s.immediate(31 downto 0) := (others => '0');
369                         instr_s.op_detail(JMP_REG_OPT) := '1';
370                         instr_s.op_detail(IMM_OPT) := '1';      
371                 end if;
372
373                 if (instr_s.signext = '1' and instr_s.immediate(15) = '1') then
374                         instr_s.immediate(31 downto 16) := (others => '1');
375                 end if;
376
377                 case instr_s.jmptype is 
378                         when "00" =>
379                                 instr_s.op_group := JMP_OP;
380                         
381                         when "01" =>
382                                 instr_s.op_group := JMP_ST_OP;
383                         
384                         when "10" =>
385                                 instr_s.op_group := JMP_ST_OP;
386                                 instr_s.op_detail(RET_OPT) := '1';
387                         
388                         when "11" =>
389                                 instr_s.op_group := JMP_OP;
390                                 instr_s.op_detail(JMP_REG_OPT) := '1';
391                                 instr_s.op_detail(IMM_OPT) := '1';
392                                 instr_s.immediate := (others => '0');
393                         
394                         when others => null;
395                 end case;
396                 
397 --              if (instr_s.jmptype = "00") then
398 ----                    instr_s.op_detail(SUB_OPT) := not instr_s.opcode(0);
399 --                      instr_s.op_group := JMP_OP;
400 --              end if;
401 --              
402 --              if (instr_s.jmptype = "01") then
403 --                      instr_s.op_group := JMP_ST_OP;
404 --              --      instr_s.op_detail(RET_OPT) := '0';
405 --              end if;
406 --
407 --              if (instr_s.jmptype = "10") then
408 --                      instr_s.op_group := JMP_ST_OP;
409 --                      instr_s.op_detail(RET_OPT) := '1';
410 --              end if;
411 --              
412 --              if (instr_s.jmptype = "11") then
413 --                      instr_s.op_group := JMP_OP;
414 --                      instr_s.op_detail(JMP_REG_OPT) := '1';
415 --                      instr_s.op_detail(IMM_OPT) := '1';
416 --                      instr_s.immediate := (others => '0');
417 --              end if;
418
419                 if (instr_s.predicates = "1111" or instr_s.jmptype = "10") then
420                         instr_s.bp := '0';
421                 end if;
422         end if;
423
424 --      when "10111" =>         --brreg
425 --              instr_s.reg_src1_addr := instruction(22 downto 19);     -- register value
426 --              instr_s.immediate(15 downto 0) := instruction(22 downto 7);     -- negligible
427 --              instr_s.bp := instruction(1);                           -- negligible
428 --              instr_s.jmptype := instruction(3 downto 2);             -- only lsb
429 --              instr_s.signext := instruction(0);                      -- negligible
430
431 --=================================================================
432         if (instr_s.opcode = "11000" or instr_s.opcode = "11001") then
433
434 --      when "11000" =>         --cmp
435                 instr_s.reg_src1_addr := instruction(22 downto 19);
436                 instr_s.reg_src2_addr := instruction(18 downto 15);
437
438                 if (instr_s.opcode = "11001") then
439                         instr_s.immediate(15 downto 0) := instruction(18 downto 3);
440                         instr_s.signext := instruction(2);              
441
442                         if (instr_s.signext = '1' and instr_s.immediate(15) = '1') then
443                                 instr_s.immediate(31 downto 16) := (others => '1');
444                         end if;
445
446                         instr_s.op_detail(IMM_OPT) := '1';
447                 end if;
448                 instr_s.op_detail(NO_DST_OPT) := '1';
449                 instr_s.op_group := ADDSUB_OP;
450                 instr_s.op_detail(SUB_OPT) := '1';
451
452         end if;
453
454 --      when "11001" =>         --cmpi
455 --              instr_s.reg_src1_addr := instruction(22 downto 19);
456 --              instr_s.reg_src2_addr := instruction(18 downto 15);
457 --              instr_s.immediate(15 downto 0) := instruction(18 downto 3);
458
459 --      when others => null;
460
461 --      end case;
462
463
464
465         instr_spl <= instr_s;
466
467 end process;
468
469 end behav_d;
470
471
472 --===========================================================================
473
474