w11 - vhd 0.794
W11 CPU core and support modules
Loading...
Searching...
No Matches
pdp11_decode.vhd
Go to the documentation of this file.
1-- $Id: pdp11_decode.vhd 1325 2022-12-07 11:52:36Z mueller $
2-- SPDX-License-Identifier: GPL-3.0-or-later
3-- Copyright 2006-2022 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4--
5------------------------------------------------------------------------------
6-- Module Name: pdp11_decode - syn
7-- Description: pdp11: instruction decoder
8--
9-- Dependencies: -
10-- Test bench: tb/tb_pdp11_core (implicit)
11-- Target Devices: generic
12-- Tool versions: ise 8.2-14.7; viv 2014.4-2022.1; ghdl 0.18-2.0.0
13-- Revision History:
14-- Date Rev Version Comment
15-- 2022-12-02 1324 1.0.9 use op_rti rather op_rtt
16-- 2022-10-25 1309 1.0.8 rename _gpr -> _gr
17-- 2022-10-03 1301 1.0.7 add STAT.is_dstpcmode1
18-- 2011-11-18 427 1.0.6 now numeric_std clean
19-- 2010-09-18 300 1.0.5 rename (adlm)box->(oalm)unit
20-- 2008-11-30 174 1.0.4 BUGFIX: add updt_dstadsrc; set for MFP(I/D)
21-- 2008-05-03 143 1.0.3 get fork_srcr,fork_dstr,fork_dsta assign out of if
22-- 2008-04-27 139 1.0.2 BUGFIX: mtp now via do_fork_op; is_dsta logic mods
23-- 2007-06-14 56 1.0.1 Use slvtypes.all
24-- 2007-05-12 26 1.0 Initial version
25------------------------------------------------------------------------------
26
27library ieee;
28use ieee.std_logic_1164.all;
29use ieee.numeric_std.all;
30
31use work.slvtypes.all;
32use work.pdp11.all;
33
34-- ----------------------------------------------------------------------------
35
36entity pdp11_decode is -- instruction decoder
37 port (
38 IREG : in slv16; -- input instruction word
39 STAT : out decode_stat_type -- status output
40 );
41end pdp11_decode;
42
43architecture syn of pdp11_decode is
44
45begin
46
47 proc_idecode: process (IREG)
48
49 alias OPCODE : slv4 is IREG(15 downto 12); -- basic opcode (upper 4 bits)
50 alias OPPRIM : slv3 is IREG(14 downto 12); -- basic opcode without B bit
51 alias OPBYTE : slbit is IREG(15); -- byte flag of basic opcode
52 alias OPEXT1 : slv3 is IREG(11 downto 9); -- extended opcode, part 1
53 alias OPEXT2 : slv3 is IREG(8 downto 6); -- extended opcode, part 2
54 alias OPEXT3 : slv3 is IREG(5 downto 3); -- extended opcode, part 3
55 alias OPEXT4 : slv3 is IREG(2 downto 0); -- extended opcode, part 4
56
57 alias SRCMODF : slv3 is IREG(11 downto 9); -- src register full mode
58 alias DSTMODF : slv3 is IREG(5 downto 3); -- dst register full mode
59
60 alias SRCMOD : slv2 is IREG(11 downto 10); -- src register mode high
61 alias SRCDEF : slbit is IREG(9); -- src register mode defered
62 alias SRCREG : slv3 is IREG(8 downto 6); -- src register number
63 alias DSTMOD : slv2 is IREG(5 downto 4); -- dst register mode high
64 alias DSTDEF : slbit is IREG(3); -- dst register mode defered
65 alias DSTREG : slv3 is IREG(2 downto 0); -- dst register number
66
67 variable nstat : decode_stat_type;
68
69 variable is_srcr : slbit := '0'; -- source is read
70 variable is_dstr : slbit := '0'; -- destination is read
71 variable is_dstm : slbit := '0'; -- destination is modified
72 variable is_dstw : slbit := '0'; -- destination is written
73
74 variable is_srcmode0 : slbit := '0'; -- source is register mode
75 variable is_dstmode0notpc : slbit := '0'; -- dest. is register mode, not PC
76
77 begin
78
79 is_srcr := '0';
80 is_dstr := '0';
81 is_dstm := '0';
82 is_dstw := '0';
83
84 is_srcmode0 := '0';
85 is_dstmode0notpc := '0';
86
87 nstat.is_dstmode0 := '0';
88 nstat.is_srcpc := '0';
89 nstat.is_srcpcmode1 := '0';
90 nstat.is_dstpc := '0';
91 nstat.is_dstpcmode1 := '0';
92 nstat.is_dstw_reg := '0';
93 nstat.is_dstw_pc := '0';
94 nstat.is_rmwop := '0';
95 nstat.is_bytop := '0';
96 nstat.is_res := '1';
97 nstat.op_rti := '0';
98 nstat.op_mov := '0';
99 nstat.trap_vec := "000";
100 nstat.force_srcsp := '0';
101 nstat.updt_dstadsrc := '0';
102
103 nstat.aunit_srcmod := c_aunit_mod_pass;
104 nstat.aunit_dstmod := c_aunit_mod_pass;
105 nstat.aunit_cimod := c_aunit_mod_pass;
106 nstat.aunit_cc1op := '0';
107 nstat.aunit_ccmode := IREG(8 downto 6); -- STATIC
108 nstat.lunit_func := (others=>'0');
109 nstat.munit_func := (others=>'0');
110 nstat.res_sel := c_dpath_res_ounit;
111
112 nstat.fork_op := (others=>'0');
113 nstat.fork_srcr := (others=>'0');
114 nstat.fork_dstr := (others=>'0');
115 nstat.fork_dsta := (others=>'0');
116 nstat.fork_opg := (others=>'0');
117 nstat.fork_opa := (others=>'0');
118
119 nstat.do_fork_op := '0';
120 nstat.do_fork_srcr := '0';
121 nstat.do_fork_dstr := '0';
122 nstat.do_fork_dsta := '0';
123 nstat.do_fork_opg := '0';
124
125 nstat.do_pref_dec := '0';
126
127 if SRCMODF = "000" then
128 is_srcmode0 := '1';
129 end if;
130
131 if DSTMODF = "000" then
132 nstat.is_dstmode0 := '1';
133 if DSTREG /= c_gr_pc then
134 is_dstmode0notpc := '1';
135 end if;
136 end if;
137
138 if SRCREG = c_gr_pc then
139 nstat.is_srcpc := '1';
140 if SRCMODF = "001" then
141 nstat.is_srcpcmode1 := '1';
142 end if;
143 end if;
144
145 if DSTREG = c_gr_pc then
146 nstat.is_dstpc := '1';
147 if DSTMODF = "001" then
148 nstat.is_dstpcmode1 := '1';
149 end if;
150 end if;
151
152 if OPPRIM = "000" then
153
154 if OPBYTE='0' and OPEXT1="000" then
155
156 if OPEXT2="000" and OPEXT3="000" then -- HALT,...,RTT
157 nstat.is_res := '0';
158 case OPEXT4 is
159
160 when "000" => -- HALT
161 nstat.fork_op := c_fork_op_halt;
162 nstat.do_fork_op := '1';
163
164 when "001" => -- WAIT
165 nstat.fork_op := c_fork_op_wait;
166 nstat.do_fork_op := '1';
167
168 when "010" => -- RTI
169 nstat.op_rti := '1';
170 nstat.force_srcsp := '1';
171 nstat.fork_op := c_fork_op_rtti;
172 nstat.do_fork_op := '1';
173
174 when "011" => -- BPT (trap to 14)
175 nstat.trap_vec := "011";
176 nstat.fork_op := c_fork_op_trap;
177 nstat.do_fork_op := '1';
178
179 when "100" => -- IOT (trap to 20)
180 nstat.trap_vec := "100";
181 nstat.fork_op := c_fork_op_trap;
182 nstat.do_fork_op := '1';
183
184 when "101" => -- RESET
185 nstat.fork_op := c_fork_op_reset;
186 nstat.do_fork_op := '1';
187
188 when "110" => -- RTT
189 nstat.force_srcsp := '1';
190 nstat.fork_op := c_fork_op_rtti;
191 nstat.do_fork_op := '1';
192
193 when others =>
194 nstat.is_res := '1';
195
196 end case;
197 end if;
198
199 if OPEXT2 = "001" then -- JMP
200 nstat.is_res := '0';
201 nstat.fork_opa := c_fork_opa_jmp;
202 nstat.do_fork_dsta := '1';
203 end if;
204
205 if OPEXT2 = "010" then
206 if OPEXT3 = "000" then -- RTS
207 nstat.is_res := '0';
208 nstat.force_srcsp := '1';
209 nstat.fork_op := c_fork_op_rts;
210 nstat.do_fork_op := '1';
211 end if;
212 if OPEXT3 = "011" then -- SPL
213 nstat.is_res := '0';
214 nstat.fork_op := c_fork_op_spl;
215 nstat.do_fork_op := '1';
216 end if;
217 end if;
218
219 if OPEXT2 = "010" then
220 if OPEXT3(2) = '1' then -- SEx/CLx
221 nstat.is_res := '0';
222 nstat.fork_op := c_fork_op_mcc;
223 nstat.do_fork_op := '1';
225 end if;
226 end if;
227
228 if OPEXT2 = "011" then -- SWAP
229 nstat.is_res := '0';
230 is_dstm := '1';
231 nstat.fork_opg := c_fork_opg_gen;
232 nstat.do_fork_opg := '1';
233 nstat.do_pref_dec := is_dstmode0notpc;
234 nstat.lunit_func := c_lunit_func_swap;
235 nstat.res_sel := c_dpath_res_lunit;
236 end if;
237
238 end if; -- OPBYTE='0' and OPEXT1="000"
239
240 if OPEXT1(2)='0' and -- BR class instructions
241 ((OPBYTE='0' and OPEXT2(2)='1') or -- BR
242 (OPBYTE='0' and (OPEXT1(0)='1' or OPEXT1(1)='1')) or -- BNE,..,BLE
243 OPBYTE='1') then -- BPL,..,BCS
244 nstat.is_res := '0';
245 nstat.fork_op := c_fork_op_br;
246 nstat.do_fork_op := '1';
247 end if;
248
249 if OPBYTE='0' and OPEXT1="100" then -- JSR
250 nstat.is_res := '0';
251 nstat.fork_opa := c_fork_opa_jsr;
252 nstat.do_fork_dsta := '1';
253 end if;
254
255 if OPBYTE='1' and OPEXT1="100" then -- EMT, TRAP
256 nstat.is_res := '0';
257 if OPEXT2(2) = '0' then -- EMT (trap tp 30)
258 nstat.trap_vec := "110";
259 else -- TRAP (trap to 34)
260 nstat.trap_vec := "111";
261 end if;
262 nstat.fork_op := c_fork_op_trap;
263 nstat.do_fork_op := '1';
264 end if;
265
266 if OPEXT1 = "101" then -- CLR(B),...,TST(B)
267 nstat.is_res := '0';
268 nstat.res_sel := c_dpath_res_aunit;
269 if OPBYTE = '1' then
270 nstat.is_bytop := '1';
271 end if;
272
273 nstat.aunit_cc1op := '1';
274
275 case OPEXT2 is
276 when "000" => -- CLR: 0 + 0 + 0 (0)
277 is_dstw := '1';
278 nstat.aunit_srcmod := c_aunit_mod_zero;
279 nstat.aunit_dstmod := c_aunit_mod_zero;
280 nstat.aunit_cimod := c_aunit_mod_zero;
281 when "001" => -- COM: 0 + ~DST + 0 (~dst)
282 is_dstm := '1';
283 nstat.aunit_srcmod := c_aunit_mod_zero;
284 nstat.aunit_dstmod := c_aunit_mod_inv;
285 nstat.aunit_cimod := c_aunit_mod_zero;
286 when "010" => -- INC: 0 + DST + 1 (dst+1)
287 is_dstm := '1';
288 nstat.aunit_srcmod := c_aunit_mod_zero;
289 nstat.aunit_dstmod := c_aunit_mod_pass;
290 nstat.aunit_cimod := c_aunit_mod_one;
291 when "011" => -- DEC: ~0 + DST + 0 (dst-1)
292 is_dstm := '1';
293 nstat.aunit_srcmod := c_aunit_mod_one;
294 nstat.aunit_dstmod := c_aunit_mod_pass;
295 nstat.aunit_cimod := c_aunit_mod_zero;
296 when "100" => -- NEG: 0 + ~DST + 1 (-dst)
297 is_dstm := '1';
298 nstat.aunit_srcmod := c_aunit_mod_zero;
299 nstat.aunit_dstmod := c_aunit_mod_inv;
300 nstat.aunit_cimod := c_aunit_mod_one;
301 when "101" => -- ADC: 0 + DST + CI (dst+ci)
302 is_dstm := '1';
303 nstat.aunit_srcmod := c_aunit_mod_zero;
304 nstat.aunit_dstmod := c_aunit_mod_pass;
305 nstat.aunit_cimod := c_aunit_mod_pass;
306 when "110" => -- SBC: ~0 + DST + ~CI (dst-ci)
307 is_dstm := '1';
308 nstat.aunit_srcmod := c_aunit_mod_one;
309 nstat.aunit_dstmod := c_aunit_mod_pass;
310 nstat.aunit_cimod := c_aunit_mod_inv;
311 when "111" => -- TST: 0 + DST + 0 (dst)
312 is_dstr := '1';
313 nstat.aunit_srcmod := c_aunit_mod_zero;
314 nstat.aunit_dstmod := c_aunit_mod_pass;
315 nstat.aunit_cimod := c_aunit_mod_zero;
316 when others => null;
317 end case;
318
319 nstat.fork_opg := c_fork_opg_gen;
320 nstat.do_fork_opg := '1';
321 nstat.do_pref_dec := is_dstmode0notpc;
322
323 end if;
324
325 if OPEXT1 = "110" then
326 if OPEXT2(2) = '0' then -- ROR(B),...,ASL(B)
327 nstat.is_res := '0';
328 is_dstm := '1';
329 nstat.fork_opg := c_fork_opg_gen;
330 nstat.do_fork_opg := '1';
331 nstat.do_pref_dec := is_dstmode0notpc;
332 if OPBYTE = '1' then
333 nstat.is_bytop := '1';
334 end if;
335 nstat.res_sel := c_dpath_res_lunit;
336 case OPEXT2(1 downto 0) is
337 when "00" => -- ROR
338 nstat.lunit_func := c_lunit_func_ror;
339 when "01" => -- ROL
340 nstat.lunit_func := c_lunit_func_rol;
341 when "10" => -- ASR
342 nstat.lunit_func := c_lunit_func_asr;
343 when "11" => -- ASL
344 nstat.lunit_func := c_lunit_func_asl;
345 when others => null;
346 end case;
347 end if;
348
349 if OPBYTE='0' and OPEXT2="100" then -- MARK
350 nstat.is_res := '0';
351 nstat.fork_op := c_fork_op_mark;
352 nstat.do_fork_op := '1';
353 end if;
354
355 if OPEXT2 = "101" then -- MFP(I/D)
356 nstat.is_res := '0';
357 nstat.force_srcsp := '1';
358 if DSTREG = c_gr_sp then -- is dst reg == sp ?
359 nstat.updt_dstadsrc := '1'; -- ensure DSRC update in dsta flow
360 end if;
361 nstat.res_sel := c_dpath_res_ounit;
362 if nstat.is_dstmode0 = '1' then
363 nstat.fork_opa := c_fork_opa_mfp_reg;
364 else
365 nstat.fork_opa := c_fork_opa_mfp_mem;
366 end if;
367 nstat.do_fork_dsta := '1';
368 end if;
369
370 if OPEXT2 = "110" then -- MTP(I/D)
371 nstat.is_res := '0';
372 nstat.force_srcsp := '1';
373 nstat.res_sel := c_dpath_res_ounit;
374 nstat.fork_opa := c_fork_opa_mtp;
375 nstat.fork_op := c_fork_op_mtp;
376 nstat.do_fork_op := '1';
377 end if;
378
379 if OPBYTE='0' and OPEXT2="111" then -- SXT
380 nstat.is_res := '0';
381 is_dstw := '1';
382 nstat.fork_opg := c_fork_opg_gen;
383 nstat.do_fork_opg := '1';
384 nstat.do_pref_dec := is_dstmode0notpc;
385 nstat.lunit_func := c_lunit_func_sxt;
386 nstat.res_sel := c_dpath_res_lunit;
387 end if;
388 end if;
389
390 end if; -- OPPRIM="000"
391
392 if OPPRIM/="000" and OPPRIM/="111" then
393 nstat.is_res := '0';
394 case OPPRIM is
395 when "001" => -- MOV
396 is_srcr := '1';
397 is_dstw := '1';
398 nstat.op_mov := '1';
399 nstat.lunit_func := c_lunit_func_mov;
400 nstat.res_sel := c_dpath_res_lunit;
401 nstat.is_bytop := OPBYTE;
402 when "010" => -- CMP
403 is_srcr := '1';
404 is_dstr := '1';
405 nstat.res_sel := c_dpath_res_aunit;
406 nstat.aunit_srcmod := c_aunit_mod_pass;
407 nstat.aunit_dstmod := c_aunit_mod_inv;
408 nstat.aunit_cimod := c_aunit_mod_one;
409 nstat.is_bytop := OPBYTE;
410 when "011" => -- BIT
411 is_srcr := '1';
412 is_dstr := '1';
413 nstat.lunit_func := c_lunit_func_bit;
414 nstat.res_sel := c_dpath_res_lunit;
415 nstat.is_bytop := OPBYTE;
416 when "100" => -- BIC
417 is_srcr := '1';
418 is_dstm := '1';
419 nstat.lunit_func := c_lunit_func_bic;
420 nstat.res_sel := c_dpath_res_lunit;
421 nstat.is_bytop := OPBYTE;
422 when "101" => -- BIS
423 is_srcr := '1';
424 is_dstm := '1';
425 nstat.lunit_func := c_lunit_func_bis;
426 nstat.res_sel := c_dpath_res_lunit;
427 nstat.is_bytop := OPBYTE;
428 when "110" =>
429 is_srcr := '1';
430 is_dstm := '1';
431 nstat.res_sel := c_dpath_res_aunit;
432 if OPBYTE = '0' then -- ADD
433 nstat.aunit_srcmod := c_aunit_mod_pass;
434 nstat.aunit_dstmod := c_aunit_mod_pass;
435 nstat.aunit_cimod := c_aunit_mod_zero;
436 else -- SUB
437 nstat.aunit_srcmod := c_aunit_mod_inv;
438 nstat.aunit_dstmod := c_aunit_mod_pass;
439 nstat.aunit_cimod := c_aunit_mod_one;
440 end if;
441 when others => null;
442 end case;
443
444 nstat.fork_opg := c_fork_opg_gen;
445 nstat.do_fork_opg := '1';
446 nstat.do_pref_dec := is_srcmode0 and is_dstmode0notpc;
447
448 end if;
449
450 if OPBYTE='0' and OPPRIM="111" then
451 case OPEXT1 is
452 when "000" => -- MUL
453 nstat.is_res := '0';
454 is_dstr := '1';
455 nstat.munit_func := c_munit_func_mul;
456 nstat.res_sel := c_dpath_res_munit;
457 nstat.fork_opg := c_fork_opg_mul;
458 nstat.do_fork_opg := '1';
459 when "001" => -- DIV
460 nstat.is_res := '0';
461 is_dstr := '1';
462 nstat.munit_func := c_munit_func_div;
463 nstat.res_sel := c_dpath_res_munit;
464 nstat.fork_opg := c_fork_opg_div;
465 nstat.do_fork_opg := '1';
466 when "010" => -- ASH
467 nstat.is_res := '0';
468 is_dstr := '1';
469 nstat.munit_func := c_munit_func_ash;
470 nstat.res_sel := c_dpath_res_munit;
471 nstat.fork_opg := c_fork_opg_ash;
472 nstat.do_fork_opg := '1';
473 when "011" => -- ASHC
474 nstat.is_res := '0';
475 is_dstr := '1';
476 nstat.munit_func := c_munit_func_ashc;
477 nstat.res_sel := c_dpath_res_munit;
478 nstat.fork_opg := c_fork_opg_ashc;
479 nstat.do_fork_opg := '1';
480 when "100" => -- XOR
481 nstat.is_res := '0';
482 is_dstm := '1';
483 nstat.lunit_func := c_lunit_func_xor;
484 nstat.res_sel := c_dpath_res_lunit;
485 nstat.fork_opg := c_fork_opg_gen;
486 nstat.do_fork_opg := '1';
487 nstat.do_pref_dec := is_dstmode0notpc;
488 when "111" => -- SOB: SRC + ~0 + 0 (src-1)
489 nstat.is_res := '0';
490 nstat.aunit_srcmod := c_aunit_mod_pass;
491 nstat.aunit_dstmod := c_aunit_mod_one;
492 nstat.aunit_cimod := c_aunit_mod_zero;
493 nstat.res_sel := c_dpath_res_aunit;
494 nstat.fork_op := c_fork_op_sob;
495 nstat.do_fork_op := '1';
496 when others => null;
497 end case;
498
499 end if;
500
501 if OPBYTE='1' and OPPRIM="111" then -- FPU
502 nstat.is_res := '1'; -- ??? FPU not yet handled
503 end if;
504
505 case SRCMOD is
506 when "00" => nstat.fork_srcr := c_fork_srcr_def;
507 when "01" => nstat.fork_srcr := c_fork_srcr_inc;
508 when "10" => nstat.fork_srcr := c_fork_srcr_dec;
509 when "11" => nstat.fork_srcr := c_fork_srcr_ind;
510 when others => null;
511 end case;
512
513 if is_srcr='1' and SRCMODF /="000" then
514 nstat.do_fork_srcr := '1';
515 end if;
516
517 case DSTMOD is
518 when "00" => nstat.fork_dstr := c_fork_dstr_def;
519 when "01" => nstat.fork_dstr := c_fork_dstr_inc;
520 when "10" => nstat.fork_dstr := c_fork_dstr_dec;
521 when "11" => nstat.fork_dstr := c_fork_dstr_ind;
522 when others => null;
523 end case;
524
525 if (is_dstr or is_dstm)='1' and nstat.is_dstmode0='0' then
526 nstat.do_fork_dstr := '1';
527 end if;
528
529 if is_dstw='1' and nstat.is_dstmode0='0' then
530 case DSTMOD is
531 when "00" => nstat.fork_opg := c_fork_opg_wdef;
532 when "01" => nstat.fork_opg := c_fork_opg_winc;
533 when "10" => nstat.fork_opg := c_fork_opg_wdec;
534 when "11" => nstat.fork_opg := c_fork_opg_wind;
535 when others => null;
536 end case;
537 end if;
538
539 if is_dstm='1' and nstat.is_dstmode0='0' then
540 nstat.is_rmwop := '1';
541 end if;
542
543 case DSTMOD is
544 when "00" => nstat.fork_dsta := c_fork_dsta_def;
545 when "01" => nstat.fork_dsta := c_fork_dsta_inc;
546 when "10" => nstat.fork_dsta := c_fork_dsta_dec;
547 when "11" => nstat.fork_dsta := c_fork_dsta_ind;
548 when others => null;
549 end case;
550
551 if (is_dstw or is_dstm)='1' and nstat.is_dstmode0='1' then
552 nstat.is_dstw_reg := '1';
553 if DSTREG = c_gr_pc then
554 nstat.is_dstw_pc := '1'; --??? hack rename -> is_dstw_pc
555 end if;
556 end if;
557
558 STAT <= nstat;
559
560 end process proc_idecode;
561
562end syn;
in IREG slv16
out STAT decode_stat_type
Definition: pdp11.vhd:123
std_logic_vector( 3 downto 0) slv4
Definition: slvtypes.vhd:36
std_logic_vector( 2 downto 0) slv3
Definition: slvtypes.vhd:35
std_logic_vector( 15 downto 0) slv16
Definition: slvtypes.vhd:48
std_logic slbit
Definition: slvtypes.vhd:30
std_logic_vector( 1 downto 0) slv2
Definition: slvtypes.vhd:34