X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=cpu%2Fsrc%2Fdecoder_b.vhd;h=abeedb9806ef1e2371a876e229f4eeb6f8f66922;hb=1968f329b10681b760faec9369aa893cd2af8d44;hp=b0ae0dd787eba34a5effccd7011d6ec2684fafa0;hpb=65d0fb429344b9db6cd115842c8c534b1f05c20b;p=calu.git diff --git a/cpu/src/decoder_b.vhd b/cpu/src/decoder_b.vhd index b0ae0dd..abeedb9 100644 --- a/cpu/src/decoder_b.vhd +++ b/cpu/src/decoder_b.vhd @@ -1,3 +1,24 @@ +-- `Deep Thought', a softcore CPU implemented on a FPGA +-- +-- Copyright (C) 2010 Markus Hofstaetter +-- Copyright (C) 2010 Martin Perner +-- Copyright (C) 2010 Stefan Rebernig +-- Copyright (C) 2010 Manfred Schwarz +-- Copyright (C) 2010 Bernhard Urban +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . + library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; @@ -31,6 +52,8 @@ begin instr_s.signext := '0'; instr_s.bp := '0'; instr_s.op_detail := (others => '0'); + instr_s.displacement := (others => '0'); + instr_s.int := '0'; instr_s.op_group := ADDSUB_OP; @@ -153,7 +176,7 @@ begin instr_s.op_detail(IMM_OPT) := '1'; instr_s.op_detail(NO_PSW_OPT) := instruction(0); - if (instr_s.opcode = "00111") then + if (instr_s.opcode = "00101") then instr_s.op_group := AND_OP; end if; @@ -183,7 +206,7 @@ begin -- instr_s.sreg_update := instruction(0); -- --================================================================= - if (instr_s.opcode = "01010" or instr_s.opcode = "01011") then + if (instr_s.opcode = "01010") then -- when "01010" => --shift instr_s.reg_dest_addr := instruction(22 downto 19); @@ -214,18 +237,44 @@ begin -- when "01110" => --ldw instr_s.reg_dest_addr := instruction(22 downto 19); instr_s.reg_src1_addr := instruction(18 downto 15); - instr_s.immediate(15 downto 0) := instruction(18 downto 3); instr_s.signext := instruction(2); instr_s.high_low := instruction(1); + instr_s.displacement(14 downto 0) := instruction(14 downto 0); + + instr_s.op_group := LDST_OP; + instr_s.op_detail(NO_PSW_OPT) := '1'; + + if (instr_s.displacement(14) = '1') then + instr_s.displacement(31 downto 15) := (others => '1'); + end if; + + if (instr_s.opcode = "11010") then --ldi + instr_s.reg_src1_addr := instr_s.reg_dest_addr; + instr_s.op_detail(LOW_HIGH_OPT) := instr_s.high_low; + instr_s.op_detail(LDI_REPLACE_OPT) := instr_s.signext; + + if (instr_s.high_low = '1') then + instr_s.immediate(31 downto 16) := instruction(18 downto 3); + instr_s.immediate(15 downto 0) := (others => '0'); + else + instr_s.immediate(15 downto 0) := instruction(18 downto 3); + instr_s.immediate(31 downto 16) := (others => '0'); + end if; - if (instr_s.opcode = "11010") then if (instr_s.signext = '1' and instr_s.immediate(11) = '1') then instr_s.immediate(31 downto 16) := (others => '1'); end if; - instr_s.immediate(14 downto 0) := instruction(14 downto 0); - instr_s.immediate(WORD_WIDTH-1 downto 15) := (others => '0'); + instr_s.op_detail(IMM_OPT) := '1'; end if; + + if (instr_s.opcode = "10000") then + instr_s.op_detail(HWORD_OPT) := '1'; + end if; + + if (instr_s.opcode = "10010") then + instr_s.op_detail(BYTE_OPT) := '1'; + end if; end if; -- when "10000" => --ldh @@ -256,11 +305,56 @@ begin if (instr_s.opcode = "01111" or instr_s.opcode = "10001" or instr_s.opcode = "10011" or instr_s.opcode = "10101") then --when "01111" => --stw - instr_s.reg_src1_addr := instruction(22 downto 19); -- register value - instr_s.reg_src2_addr := instruction(18 downto 15); -- mem addr - instr_s.immediate(14 downto 0) := instruction(14 downto 0); + instr_s.reg_src2_addr := instruction(22 downto 19); -- register value + instr_s.reg_src1_addr := instruction(18 downto 15); -- mem addr + instr_s.displacement(14 downto 0) := instruction(14 downto 0); + instr_s.op_detail(NO_PSW_OPT) := '1'; + instr_s.op_detail(ST_OPT) := '1'; + instr_s.op_group := LDST_OP; + + if (instr_s.displacement(14) = '1') then + instr_s.displacement(31 downto 15) := (others => '1'); + end if; + + if (instr_s.opcode = "10001") then + instr_s.op_detail(HWORD_OPT) := '1'; + end if; + + if (instr_s.opcode = "10011") then + instr_s.op_detail(BYTE_OPT) := '1'; + end if; + end if; + -- =============================================================== + + if (instr_s.opcode = "01011") then -- stack op + instr_s.reg_src1_addr := instruction(22 downto 19); + instr_s.reg_dest_addr := instruction(22 downto 19); + instr_s.op_group := STACK_OP; + instr_s.op_detail(NO_PSW_OPT) := '1'; + instr_s.op_detail(PWREN_OPT) := '1'; + + case instruction(18 downto 17) is + when "00" => --pop + instr_s.op_detail(PUSH_OPT) := '0'; + + when "01" => --disc + instr_s.op_detail(PUSH_OPT) := '0'; + instr_s.op_detail(NO_DST_OPT) := '1'; + + when "10" => --fetch + instr_s.op_detail(PUSH_OPT) := '0'; + instr_s.op_detail(PWREN_OPT) := '0'; + + when "11" => --push + instr_s.op_detail(PUSH_OPT) := '1'; + + when others => null; + end case; + + end if; + -- when "10001" => --sth -- instr_s.reg_src1_addr := instruction(22 downto 19); -- instr_s.reg_src2_addr := instruction(18 downto 15); @@ -285,6 +379,67 @@ begin instr_s.bp := instruction(1); instr_s.jmptype := instruction(3 downto 2); instr_s.signext := instruction(0); + instr_s.op_detail(NO_PSW_OPT) := '1'; + instr_s.op_detail(DIRECT_JUMP_OPT) := instruction(4); + instr_s.int := instruction(4); + + if (instr_s.opcode = "10110") then + instr_s.op_detail(IMM_OPT) := '1'; + else + instr_s.immediate(31 downto 0) := (others => '0'); + instr_s.op_detail(JMP_REG_OPT) := '1'; + instr_s.op_detail(IMM_OPT) := '1'; + end if; + + if (instr_s.signext = '1' and instr_s.immediate(15) = '1') then + instr_s.immediate(31 downto 16) := (others => '1'); + end if; + + case instr_s.jmptype is + when "00" => + instr_s.op_group := JMP_OP; + + when "01" => + instr_s.op_group := JMP_ST_OP; + + when "10" => + instr_s.op_group := JMP_ST_OP; + instr_s.op_detail(RET_OPT) := '1'; + + when "11" => + instr_s.op_group := JMP_OP; + instr_s.op_detail(JMP_REG_OPT) := '1'; + instr_s.op_detail(IMM_OPT) := '1'; + instr_s.immediate := (others => '0'); + + when others => null; + end case; + +-- if (instr_s.jmptype = "00") then +---- instr_s.op_detail(SUB_OPT) := not instr_s.opcode(0); +-- instr_s.op_group := JMP_OP; +-- end if; +-- +-- if (instr_s.jmptype = "01") then +-- instr_s.op_group := JMP_ST_OP; +-- -- instr_s.op_detail(RET_OPT) := '0'; +-- end if; +-- +-- if (instr_s.jmptype = "10") then +-- instr_s.op_group := JMP_ST_OP; +-- instr_s.op_detail(RET_OPT) := '1'; +-- end if; +-- +-- if (instr_s.jmptype = "11") then +-- instr_s.op_group := JMP_OP; +-- instr_s.op_detail(JMP_REG_OPT) := '1'; +-- instr_s.op_detail(IMM_OPT) := '1'; +-- instr_s.immediate := (others => '0'); +-- end if; + + if (instr_s.predicates = "1111" or instr_s.jmptype = "10") then + instr_s.bp := '0'; + end if; end if; -- when "10111" => --brreg @@ -311,6 +466,9 @@ begin instr_s.op_detail(IMM_OPT) := '1'; end if; + instr_s.op_detail(NO_DST_OPT) := '1'; + instr_s.op_group := ADDSUB_OP; + instr_s.op_detail(SUB_OPT) := '1'; end if;