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