From: Martin Meloun Date: Tue, 24 Sep 2013 15:27:27 +0000 (+0200) Subject: Customized instruction set (with compatibility mode) X-Git-Url: https://rtime.felk.cvut.cz/gitweb/fpga/lx-cpu1/tumbl.git/commitdiff_plain/d161f700f83405651daa3225a48979e67c849b7b Customized instruction set (with compatibility mode) 1) Removed done_o signal, replaced with HALT instruction 2) Nuked delay slot (muck) and removed related instructions 3) Added RTI, RTS, BRL, BRLI, BRALI instructions 4) Recoded CMP instruction, added CMPI 5) Added macro for compatibility mode (recognizes original instruction set, i.e delay slot, original CMP instruction - and keeps HALT, and some new instruction where blocking them would require additional logic (extra no delay variants of existing instructions) 6) Simplified flushing 7) Given patched binutils, gcc and newlib, mb-dasm has been removed for redundancy Signed-off-by: Martin Meloun --- diff --git a/hw/core_ctrl.vhd b/hw/core_ctrl.vhd index 5e9d5a4..a0d7143 100644 --- a/hw/core_ctrl.vhd +++ b/hw/core_ctrl.vhd @@ -21,18 +21,21 @@ LIBRARY IEEE; USE IEEE.std_logic_1164.all; USE WORK.mbl_Pkg.all; - -------------------------------------------------------------------------------- ENTITY core_ctrl IS -------------------------------------------------------------------------------- + GENERIC ( + COMPATIBILITY_MODE_g : BOOLEAN := FALSE + ); PORT ( clk_i : IN STD_LOGIC; rst_i : IN STD_LOGIC; halt_i : IN STD_LOGIC; + bad_op_i : IN STD_LOGIC; int_i : IN STD_LOGIC; trace_i : IN STD_LOGIC; trace_kick_i : IN STD_LOGIC; - core_clk_en_o : OUT STD_LOGIC; + core_clken_o : OUT STD_LOGIC; -- specific fetch i/o imem_addr_o : OUT STD_LOGIC_VECTOR (31 DOWNTO 0); imem_clken_o : OUT STD_LOGIC; @@ -48,6 +51,8 @@ ENTITY core_ctrl IS -- exeq to fetch feedback registers EX2IF_REG_i : IN EX2IF_Type; EX2IF_REG_o : OUT EX2IF_Type; + -- exeq to core (halting) + exeq_halt_i : IN STD_LOGIC; -- exeq to mem pipeline registers EX2MEM_REG_i : IN EX2MEM_Type; EX2MEM_REG_o : OUT EX2MEM_Type; @@ -70,8 +75,7 @@ ENTITY core_ctrl IS MSR_i : IN MSR_Type; MSR_o : OUT MSR_Type; -- miscellaneous - MEM2CTRL_i : IN MEM2CTRL_Type; - done_o : OUT STD_LOGIC + MEM2CTRL_i : IN MEM2CTRL_Type ); END ENTITY core_ctrl; @@ -81,15 +85,13 @@ ARCHITECTURE rtl OF core_ctrl IS SIGNAL rst_r : STD_LOGIC; SIGNAL reset_s : STD_LOGIC; - SIGNAL core_clk_en_s : STD_LOGIC; + SIGNAL core_clken_s : STD_LOGIC; SIGNAL ID2EX_REG_r : ID2EX_Type; SIGNAL EX2IF_REG_r : EX2IF_Type; - SIGNAL delayBit_r : STD_LOGIC; - SIGNAL delayBit_2r : STD_LOGIC; SIGNAL IMM_LOCK_r : IMM_LOCK_Type; SIGNAL HAZARD_WRB_r : HAZARD_WRB_Type; - + SIGNAL delayBit_r : STD_LOGIC; SIGNAL clken_s : STD_LOGIC; SIGNAL clken_pipe_s : STD_LOGIC; SIGNAL flush_ID2EX_s : STD_LOGIC; @@ -99,7 +101,6 @@ ARCHITECTURE rtl OF core_ctrl IS SIGNAL setup_int_r : STD_LOGIC; SIGNAL int_busy_r : STD_LOGIC; - BEGIN -- static connections @@ -108,16 +109,17 @@ BEGIN imem_addr_o <= IF2ID_REG_i.program_counter; -- Tracing -- Reset_s is 1 when rst_i is one and then gets deactivated - core_clk_en_s <= reset_s OR (NOT trace_i) OR trace_kick_i; - core_clk_en_o <= core_clk_en_s; + core_clken_s <= reset_s OR ((NOT bad_op_i) AND (((NOT trace_i) AND (NOT exeq_halt_i)) OR trace_kick_i)); + core_clken_o <= core_clken_s; -- clock/wait control lines clken_s <= MEM2CTRL_i.clken OR rst_i; clken_pipe_s <= clken_s AND (NOT HAZARD_WRB_i.hazard); imem_clken_o <= clken_pipe_s; gprf_clken_o <= clken_s; -- signals for clearing the ID2EX and EX2MEM registers during branches - flush_ID2EX_s <= EX2IF_REG_r.take_branch; - flush_EX2MEM_s <= (flush_ID2EX_s AND (NOT delayBit_2r)) OR HAZARD_WRB_i.hazard; + flush_ID2EX_s <= ((EX2IF_REG_i.take_branch AND (NOT delayBit_r)) OR EX2IF_REG_r.take_branch) WHEN COMPATIBILITY_MODE_g = TRUE + ELSE (EX2IF_REG_i.take_branch OR EX2IF_REG_r.take_branch); + flush_EX2MEM_s <= HAZARD_WRB_i.hazard; -- outputs that need to be readable too, so needing shadowing signals ID2EX_REG_o <= ID2EX_REG_r; EX2IF_REG_o <= EX2IF_REG_r; @@ -129,12 +131,12 @@ BEGIN INT_CTRL_o.int_busy <= int_busy_r; regd_proc: - PROCESS ( clk_i, rst_i, halt_i, core_clk_en_s, + PROCESS ( clk_i, rst_i, halt_i, core_clken_s, -- complete sensitivity list for synthesizer reset_s, MEM2CTRL_i, clken_pipe_s, IF2ID_REG_i, flush_ID2EX_s, flush_EX2MEM_s, HAZARD_WRB_i, MEM_REG_i, ID2CTRL_i, int_i, MSR_i, - int_busy_r, delayBit_r, IMM_LOCK_i, ID2EX_REG_i, ID2EX_REG_r, + int_busy_r, IMM_LOCK_i, ID2EX_REG_i, ID2EX_REG_r, EX2IF_REG_i, EX_WRB_i, EX2MEM_REG_i ) -- some local procedures @@ -217,18 +219,22 @@ regd_proc: BEGIN IF (RISING_EDGE (clk_i) AND (MEM2CTRL_i.clken = '1')) AND halt_i = '0' AND - core_clk_en_s = '1' THEN + core_clken_s = '1' THEN rst_r <= rst_i; + IF (reset_s = '1') THEN -- synchronous reset ... lp_rst_IF2ID_REG; -- ... so lasts at least one clock_cycle lp_rst_MSR; lp_rst_HAZARD_WRB; lp_rst_MEM_REG; - delayBit_r <= '0'; + + IF (COMPATIBILITY_MODE_g = TRUE) THEN + delayBit_r <= '0'; + END IF; + flush_ID2EX_r <= '0'; setup_int_r <= '0'; int_busy_r <= '0'; - done_o <= '0'; ID2EX_REG_r.program_counter <= (OTHERS => '0'); ELSE IF (clken_pipe_s = '1') THEN @@ -241,15 +247,18 @@ regd_proc: END IF; -- decode-to-exeq unit registers IF ((reset_s = '1') OR (flush_ID2EX_s = '1')) THEN + setup_int_r <= '0'; lp_rst_ID2EX_REG; - delayBit_r <= '0'; + IF (COMPATIBILITY_MODE_g = TRUE) THEN + delayBit_r <= '0'; + END IF; -- check for the need and possibility to handle active interrupt requests ELSIF (((int_i = '1') OR (MEM2CTRL_i.int = '1')) AND (MSR_i.IE = '1') AND (ID2CTRL_i.int_busy = '0') AND (int_busy_r = '0') AND -- pending branch should be taken before interrupt can be executed -- dectected by Matthis Meier, TU Dortmund (Sept 2012) (EX2IF_REG_i.take_branch = '0') AND - (delayBit_r = '0') AND + (EX2IF_REG_r.take_branch = '0') AND -- it is still pending a cycle after branching (IMM_LOCK_i.locked = '0') AND (HAZARD_WRB_i.hazard = '0')) THEN setup_int_r <= '1'; @@ -257,12 +266,10 @@ regd_proc: lp_rst_ID2EX_REG; ELSIF (clken_pipe_s = '1') THEN setup_int_r <= '0'; - if (EX2IF_REG_i.take_branch = '1') THEN - lp_rst_ID2EX_REG; - ELSE - ID2EX_REG_r <= ID2EX_REG_i; + ID2EX_REG_r <= ID2EX_REG_i; + IF (COMPATIBILITY_MODE_g = TRUE) THEN + delayBit_r <= ID2CTRL_i.delayBit; END IF; - delayBit_r <= ID2CTRL_i.delayBit; END IF; -- exeq-to-mem unit registers IF ((reset_s = '1') OR (flush_EX2MEM_s = '1')) THEN @@ -270,11 +277,9 @@ regd_proc: lp_rst_EX2MEM_REG; lp_rst_EX_WRB; lp_rst_IMM_LOCK; - delayBit_2r <= '0'; ELSE IF (clken_pipe_s = '1') THEN EX2IF_REG_r <= EX2IF_REG_i; - delayBit_2r <= delayBit_r; EX_WRB_o <= EX_WRB_i; END IF; IF (clken_s = '1') THEN @@ -287,14 +292,6 @@ regd_proc: MSR_o <= MSR_i; END IF; END IF; - -- check on End-Of-Program viz. "bri 0x00" - -- use delayBit to distinguish between "bri" and "rtsd/rtid" - IF ((ID2EX_REG_r.branch_Action = BR) AND - (ID2EX_REG_r.alu_Op2 = ALU_IN_IMM) AND - (ID2EX_REG_r.IMM16 = C_16_ZEROS) AND - (delayBit_r = '0') AND (flush_EX2MEM_s = '0')) THEN - done_o <= '1'; - END IF; END IF; -- rising edge clk_i ... END PROCESS regd_proc; diff --git a/hw/decode.vhd b/hw/decode.vhd index c7d9c86..9d02421 100644 --- a/hw/decode.vhd +++ b/hw/decode.vhd @@ -25,8 +25,9 @@ USE WORK.mbl_Pkg.all; ENTITY decode IS -------------------------------------------------------------------------------- GENERIC ( - USE_HW_MUL_g : BOOLEAN := FALSE; - USE_BARREL_g : BOOLEAN := FALSE + USE_HW_MUL_g : BOOLEAN := TRUE; + USE_BARREL_g : BOOLEAN := TRUE; + COMPATIBILITY_MODE_g : BOOLEAN := FALSE ); PORT ( IF2ID_i : IN IF2ID_Type; @@ -37,8 +38,8 @@ ENTITY decode IS -- INT_CTRL_i : IN INT_CTRL_Type; ID2CTRL_o : OUT ID2CTRL_Type; - -- - noLiteOpc_o : OUT STD_LOGIC + -- + noLiteOpc_o : OUT STD_LOGIC ); END ENTITY decode; @@ -82,7 +83,9 @@ p_decode: rB_v := instruction_v (15 DOWNTO 11); IMM16_v := instruction_v (15 DOWNTO 0); IMM_Lock_v := '0'; - delayBit_v := '0'; + IF (COMPATIBILITY_MODE_g = TRUE) THEN + delayBit_v := '0'; + END IF; alu_Cin_v := CIN_ZERO; alu_Action_v := A_NOP; msr_Action_v := KEEP_CARRY; @@ -120,8 +123,8 @@ p_decode: CASE opcIx_v (5 DOWNTO 4) IS - WHEN "00" => -- ADD / RSUB / CMP - IF (opcIx_v(0) = '1') THEN -- RSUB / CMP + WHEN "00" => -- ADD / RSUB + IF (opcIx_v(0) = '1') THEN -- RSUB alu_Op1_v := ALU_IN_NOT_REGA; END IF; IF (opcIx_v(1) = '0') THEN -- xxx @@ -133,8 +136,8 @@ p_decode: ELSE -- xxxC alu_Cin_v := FROM_MSR; END IF; - IF ((opcIx_v(3 DOWNTO 0) = "0101") AND (IMM16_v(0)= '1')) THEN - -- special CMP(U) and not RSUB(I)K + IF ((COMPATIBILITY_MODE_g = TRUE) AND (opcIx_v(3 DOWNTO 0) = "0101") AND (IMM16_v(0)= '1')) THEN + -- special CMP(U) and not RSUB(I)K, supported only in compatibility mode IF (IMM16_v(1) = '1') THEN -- U-bit set, CMPU alu_Action_v := A_CMPU; ELSE @@ -169,6 +172,16 @@ p_decode: ELSE noLiteOpc_o <= '1'; END IF; + WHEN "010" => -- CMP / CMPU / CMPI (new format) + IF (COMPATIBILITY_MODE_g = FALSE) THEN + IF (IMM16_v(5) = '1') THEN -- U-bit set, CMPU + alu_Action_v := A_CMPU; + ELSE + alu_Action_v := A_CMP; + END IF; + ELSE + noLiteOpc_o <= '1'; + END IF; WHEN OTHERS => noLiteOpc_o <= '1'; END CASE; @@ -202,19 +215,19 @@ p_decode: alu_Action_v := A_NOP; wrb_Action_v := NO_WRB; ELSIF (opcIx_v (3 DOWNTO 0) = "1101") THEN - CASE rD_v IS - WHEN "10001" => -- RTID + CASE rD_v (3 DOWNTO 0) IS + WHEN "0001" => -- RTI(D) int_busy_v := '0'; - WHEN "10000" => -- RTSD --- WHEN "10010" => -- RTBD --- WHEN "10100" => -- RTED + WHEN "0000" => -- RTS(D) WHEN OTHERS => noLiteOpc_o <= '1'; END CASE; alu_Action_v := A_ADD; branch_Action_v := BR; wrb_Action_v := NO_WRB; - delayBit_v := '1'; + IF (COMPATIBILITY_MODE_g = TRUE) THEN + delayBit_v := rD_v(4); + END IF; ELSIF (opcIx_v (3 DOWNTO 0) = "0101") THEN CASE IMM16_v IS WHEN X"8001" => -- MFS (MSR only) @@ -241,7 +254,7 @@ p_decode: ELSE alu_Op2_v := ALU_IN_NOT_IMM; END IF; - WHEN "110" => -- BR(I) + WHEN "110" => -- BR(I)(D) IF (rA_v(2) = '1') THEN branch_Action_v := BRL; ELSE @@ -253,10 +266,10 @@ p_decode: ELSE alu_Op1_v := ALU_IN_PC; END IF; - IF (rA_v(4) = '1') THEN - delayBit_v := '1'; - END IF; alu_Action_v := A_ADD; + IF (COMPATIBILITY_MODE_g = TRUE) THEN + delayBit_v := rA_v(4); + END IF; WHEN "111" => CASE rD_v(3 DOWNTO 0) IS WHEN "0000" => -- BEQ @@ -276,28 +289,35 @@ p_decode: END CASE; alu_Action_v := A_ADD; alu_Op1_v := ALU_IN_PC; - delayBit_v := rD_v(4); - wrb_Action_v := NO_WRB; -- evaluate and update/overwrite in exeq + IF (COMPATIBILITY_MODE_g = TRUE) THEN + delayBit_v := rD_v(4); + END IF; + wrb_Action_v := NO_WRB; -- evaluate and update/overwrite in exeq WHEN OTHERS => noLiteOpc_o <= '1'; END CASE; END IF; WHEN "11" => - alu_Action_v := A_ADD; - CASE opcIx_v (1 DOWNTO 0) IS - WHEN "00" => transfer_Size_v := BYTE; - WHEN "01" => transfer_Size_v := HALFWORD; - WHEN "10" => transfer_Size_v := WORD; - WHEN OTHERS => - noLiteOpc_o <= '1'; - END CASE; - IF (opcIx_v(2) = '0') THEN - mem_Action_v := RD_MEM; - wrb_Action_v := WRB_MEM; - ELSE - mem_Action_v := WR_MEM; + IF (opcIx_v (3 DOWNTO 0) = "1111") THEN -- HALT + alu_Action_v := A_HALT; wrb_Action_v := NO_WRB; + ELSE + alu_Action_v := A_ADD; + CASE opcIx_v (1 DOWNTO 0) IS + WHEN "00" => transfer_Size_v := BYTE; + WHEN "01" => transfer_Size_v := HALFWORD; + WHEN "10" => transfer_Size_v := WORD; + WHEN OTHERS => + noLiteOpc_o <= '1'; + END CASE; + IF (opcIx_v(2) = '0') THEN + mem_Action_v := RD_MEM; + wrb_Action_v := WRB_MEM; + ELSE + mem_Action_v := WR_MEM; + wrb_Action_v := NO_WRB; + END IF; END IF; WHEN OTHERS => @@ -327,11 +347,11 @@ p_decode: ID2EX_o.transfer_Size <= transfer_Size_v; ID2EX_o.wrb_Action <= wrb_Action_v; -- - ID2CTRL_o.delayBit <= delayBit_v; + IF (COMPATIBILITY_MODE_g = TRUE) THEN + ID2CTRL_o.delayBit <= delayBit_v; + END IF; ID2CTRL_o.int_busy <= int_busy_v; - - END PROCESS; END ARCHITECTURE rtl; diff --git a/hw/exeq.vhd b/hw/exeq.vhd index 6e53725..fc338b8 100644 --- a/hw/exeq.vhd +++ b/hw/exeq.vhd @@ -30,13 +30,14 @@ USE WORK.mbl_Pkg.all; ENTITY exeq IS ---------------------------------------------------------- GENERIC ( - USE_HW_MUL_g : BOOLEAN := FALSE; - USE_BARREL_g : BOOLEAN := FALSE + USE_HW_MUL_g : BOOLEAN := TRUE; + USE_BARREL_g : BOOLEAN := TRUE ); PORT ( ID2EX_i : IN ID2EX_Type; GPRF2EX_i : IN GPRF2EX_Type; EX2IF_o : OUT EX2IF_Type; + HALT_o : OUT HALT_Type; -- EX_WRB_i : IN WRB_Type; EX_WRB_o : OUT WRB_Type; @@ -101,6 +102,8 @@ p_exeq: VARIABLE byte_Enable_v : STD_LOGIC_VECTOR ( 3 DOWNTO 0); VARIABLE tmp64_v : STD_LOGIC_VECTOR (63 DOWNTO 0); VARIABLE padVec_v : STD_LOGIC_VECTOR (15 DOWNTO 0); + VARIABLE halt_v : STD_LOGIC; + VARIABLE halt_code_v : STD_LOGIC_VECTOR ( 4 DOWNTO 0); BEGIN @@ -113,6 +116,8 @@ p_exeq: carry_o_v := '0'; do_branch_v := '0'; byte_Enable_v := "0000"; + halt_v := '0'; + halt_code_v := "00000"; -- create some helper variables IF (ID2EX_i.rdix_rA = EX_WRB_i.wrix_rD) THEN @@ -269,6 +274,9 @@ p_exeq: result_v := reverse_bits (result_v); END IF; END IF; -- (USE_BARREL_g = TRUE) + WHEN A_HALT => + halt_v := '1'; + halt_code_v := ID2EX_i.IMM16(4 DOWNTO 0); WHEN OTHERS => NULL; END CASE; @@ -297,6 +305,10 @@ p_exeq: EX2IF_o.branch_target <= C_32_ZEROS; END IF; + -- Halting + HALT_o.halt <= halt_v; + HALT_o.halt_code <= halt_code_v; + -- WR_MEM/RD_MEM: result_v --> exeq_result --> mem_address, -- WR_MEM: data_rD --> data_out_to_mem -- BRL: prog_counter --> exeq_result diff --git a/hw/mbl_Pkg.vhd b/hw/mbl_Pkg.vhd index f3a35bc..2b53585 100644 --- a/hw/mbl_Pkg.vhd +++ b/hw/mbl_Pkg.vhd @@ -45,7 +45,7 @@ PACKAGE mbl_Pkg IS TYPE ALU_ACTION_Type IS (A_NOP, A_ADD, A_CMP, A_CMPU, A_OR, A_AND, A_XOR, A_SHIFT, A_SEXT8, A_SEXT16, A_MFS, A_MTS, - A_MUL, A_BSLL, A_BSRL, A_BSRA); + A_MUL, A_BSLL, A_BSRL, A_BSRA, A_HALT); TYPE ALU_IN1_Type IS (ALU_IN_REGA, ALU_IN_NOT_REGA, ALU_IN_PC, ALU_IN_ZERO); TYPE ALU_IN2_Type IS (ALU_IN_REGB, ALU_IN_NOT_REGB, ALU_IN_IMM, ALU_IN_NOT_IMM); TYPE ALU_CIN_Type IS (CIN_ZERO, CIN_ONE, FROM_MSR, FROM_IN1); @@ -116,6 +116,11 @@ PACKAGE mbl_Pkg IS branch_target : STD_LOGIC_VECTOR (31 DOWNTO 0); END RECORD; + TYPE HALT_Type IS RECORD + halt : STD_LOGIC; + halt_code : STD_LOGIC_VECTOR ( 4 DOWNTO 0); + END RECORD; + TYPE EX2MEM_Type IS RECORD mem_Action : MEM_ACTION_Type; -- RD_MEM implies writeback wrb_Action : WRB_ACTION_Type; @@ -183,8 +188,9 @@ PACKAGE mbl_Pkg IS COMPONENT decode IS GENERIC ( - USE_HW_MUL_g : BOOLEAN := FALSE; - USE_BARREL_g : BOOLEAN := FALSE + USE_HW_MUL_g : BOOLEAN := TRUE; + USE_BARREL_g : BOOLEAN := TRUE; + COMPATIBILITY_MODE_g : BOOLEAN := FALSE ); PORT ( IF2ID_i : IN IF2ID_Type; @@ -195,8 +201,8 @@ PACKAGE mbl_Pkg IS -- INT_CTRL_i : IN INT_CTRL_Type; ID2CTRL_o : OUT ID2CTRL_Type; - -- - noLiteOpc_o : OUT STD_LOGIC + -- + noLiteOpc_o : OUT STD_LOGIC ); END COMPONENT; @@ -223,6 +229,7 @@ PACKAGE mbl_Pkg IS ID2EX_i : IN ID2EX_Type; GPRF2EX_i : IN GPRF2EX_Type; EX2IF_o : OUT EX2IF_Type; + HALT_o : OUT HALT_Type; -- EX_WRB_i : IN WRB_Type; EX_WRB_o : OUT WRB_Type; @@ -257,14 +264,18 @@ PACKAGE mbl_Pkg IS END COMPONENT; COMPONENT core_ctrl IS + GENERIC ( + COMPATIBILITY_MODE_g : BOOLEAN := FALSE + ); PORT ( clk_i : IN STD_LOGIC; rst_i : IN STD_LOGIC; halt_i : IN STD_LOGIC; + bad_op_i : IN STD_LOGIC; int_i : IN STD_LOGIC; trace_i : IN STD_LOGIC; trace_kick_i : IN STD_LOGIC; - core_clk_en_o : OUT STD_LOGIC; + core_clken_o : OUT STD_LOGIC; -- specific fetch i/o imem_addr_o : OUT STD_LOGIC_VECTOR (31 DOWNTO 0); imem_clken_o : OUT STD_LOGIC; @@ -280,6 +291,8 @@ PACKAGE mbl_Pkg IS -- exeq to fetch feedback registers EX2IF_REG_i : IN EX2IF_Type; EX2IF_REG_o : OUT EX2IF_Type; + -- exeq to core (halting) + exeq_halt_i : IN STD_LOGIC; -- exeq to mem pipeline registers EX2MEM_REG_i : IN EX2MEM_Type; EX2MEM_REG_o : OUT EX2MEM_Type; @@ -302,8 +315,7 @@ PACKAGE mbl_Pkg IS MSR_i : IN MSR_Type; MSR_o : OUT MSR_Type; -- miscellaneous - MEM2CTRL_i : IN MEM2CTRL_Type; - done_o : OUT STD_LOGIC + MEM2CTRL_i : IN MEM2CTRL_Type ); END COMPONENT; diff --git a/utils/mb-dasm.cpp b/utils/mb-dasm.cpp deleted file mode 100644 index d582a3e..0000000 --- a/utils/mb-dasm.cpp +++ /dev/null @@ -1,299 +0,0 @@ -/******************************************************************************* -* -* File: dasm.c -* Description: Disassembler for TUMBL binary code. -* Syntax: mb-dasm [binFilename] -* if no binFilename specified, defaults to imem.bin in local -* directory. -* -* Author: Huib Lincklaen Arriens -* Date: August 2010 -* -* Note: No checks, e.g. on inputfile being a multiple of 4 bytes -* -********************************************************************************/ - - -#include -#include -#include -#include -#include -#include - - -// TUMBL Opcodes to be handled explicitely -#define OP_CMP 0x05 - -#define OP_MUL 0x10 -#define OP_BS 0x11 -#define OP_IDIV 0x12 -#define OP_FSL 0x13 -#define OP_FP 0x16 -#define OP_MULI 0x18 -#define OP_BSI 0x19 -#define OP_FSLD 0x1B - -#define OP_SEXT 0x24 -#define OP_SPR 0x25 -#define OP_BR 0x26 // for br brd brld bra brad brald brk -#define OP_BRC 0x27 // for beq bne blt ble bgt bge -#define OP_IMM 0x2C -#define OP_RTBD 0x2D -#define OP_BRI 0x2E // for bri brid brlid brai braid -#define OP_BRCI 0x2F // for beqi bnei blti blei bgti bgei - - -using namespace std; - -static const int MAXMEM = 65536; - -static const char *opc_Tbl[] = - { "add ", "rsub ", "addc ", "rsubc ", "addk ", "x_cmp ", "addkc ", "rsubkc ", - "addi ", "rsubi ", "addic ", "rsubic ", "addik ", "rsubik ", "addikc ", "rsubikc ", - "mul ", "bs ", "idiv ", "FSLd ", "-- ", "-- ", "FPI ", "-- ", - "muli ", "bsi ", "-- ", "FSL ", "-- ", "-- ", "-- ", "-- ", - "or ", "and ", "xor ", "andn ", "sext ", "SPR ", "br ", "brc ", - "ori ", "andi ", "xori ", "andni ", "imm ", "rtbd ", "bri ", "brci ", - "lbu ", "lhu ", "lw ", "-- ", "sb ", "sh ", "sw ", "-- ", - "lbui ", "lhui ", "lwi ", "-- ", "sbi ", "shi ", "swi ", "-- " }; - -static const char *brc_Tbl[] = - { "beq", "bne", "blt", "ble", "bgt", "bge" }; - - -char s1str[80] = ""; -char s2str[25] = ""; -const char spc_str[17] = " "; -unsigned int imem[MAXMEM]; -unsigned int mem_size; - - -void print_Usage (char *cmd_name) -{ - fprintf( stderr, "Usage: %s [binFilename]\n", cmd_name); - fprintf( stderr, "where the optional binFilename references a binary (Little Endian) code file.\n"); - fprintf( stderr, "If not specified binFilename tries to read imem.bin in the local directory.\n"); -} - -void read_bin (char *binFilename, unsigned int *imem, unsigned int *mem_size) -{ - ifstream binFile( binFilename, ios::in | ios::binary ); - // the next type should be "char" because the iostream needs it like that .... - char bin_bytes[MAXMEM]; // 4 Bytes in a Word - int isize; - int i, j; - - cout << "Reading " << binFilename << " ..." << endl << endl; - if ( binFile.fail() ) {cout << "Cannot open " << binFilename << " ..." << endl; exit (1);} - // get length of file: - binFile.seekg (0, ios::end); - isize = binFile.tellg(); - if (isize > sizeof(bin_bytes)) { - cout << binFilename << " larger than " << MAXMEM/1024 << " kBytes (" - << MAXMEM/4096 << " kWords) ..." << endl << endl; - exit (1); - } - *mem_size = isize/4; - binFile.seekg (0, ios::beg); - // read data as a block: - binFile.read (bin_bytes, isize); - if ( binFile.fail() ) {cout << "Read error ..." << endl; exit (2);} - binFile.close(); - for (i = 0, j = 0; i < isize; i += 4, j++ ) { - // remember iostream only read signed chars ... - imem[j] = ((unsigned char)bin_bytes[i] << 24) + - ((unsigned char)bin_bytes[i+1] << 16) + - ((unsigned char)bin_bytes[i+2] << 8) + - (unsigned char)bin_bytes[i+3]; - } -} - -void disasm (unsigned int pci) -{ - unsigned int pcb, ins; - unsigned int opc; - unsigned int rd, ra, rb, imm; - int s_imm; - unsigned int s1len; - bool a, l, d, b; - bool xpand, valid_code; - - pcb = 4*pci; - ins = imem[pci]; - // decode the current instruction - opc = (ins >> 26) & 0x3F; - ra = (ins >> 16) & 0x1F; - rd = (ins >> 21) & 0x1F; - if (!(opc & 0x08)) { - rb = (ins >> 11) & 0x1F; - imm = ins & 0x07FF; // not really imm!! - sprintf (s2str, "r%d, r%d, r%d", rd, ra, rb); - } - else { - imm = ins & 0xFFFF; - // 32 bit extension of a 16 bit or an 8 bit number - s_imm = imm & 0x8000 ? 0xffff0000 | imm : imm; - sprintf (s2str, "r%d, r%d, 0x%0x", rd, ra, imm); - } - - if (ins == 0) - sprintf (s1str, "nop"); - else { - xpand = 1; - switch (opc) - { - case OP_BR: // BR / BRA / BRD / BRAD / BRLD / BRALD - if ((ra & 0x1F) == 0x0C) // BRK - { - printf ("BRK"); //// ?????? - } - l = ra & 0x04; - a = ra & 0x08; - d = ra & 0x10; - b = (ra & 0x1F) == 0x0C; - if (b) sprintf (s1str, "brk r%d, r%d", rd, rb); - else - if (!l) { - s1len = sprintf (s1str, "br%s%s", a ? "a" : "", d ? "d" : ""); - sprintf (s1str, "%s r%d", strncat(s1str," ",6-s1len), rb); - } else { - s1len = sprintf (s1str, "br%sl%s", a ? "a" : "", d ? "d" : ""); - sprintf (s1str, "%s r%d, r%d", strncat(s1str," ",6-s1len), rd, rb); - } - break; - case OP_BRC: - if ((rd & 0xf) <= 0x5) - sprintf (s1str, "%s%s r%d, 0x%x", brc_Tbl[rd & 0xf], rd & 0x10 ? "d" : " ", ra, rb); - else - sprintf (s1str, "brc (opcode 0x27) has some errors, please check\n"); - break; - case OP_BRI: // BRI / BRAI / BRID / BRAID / BRLID / BRAILD - if ((ra & 0x1F) == 0x0C) // BRK - printf ("BRK"); //// ?????? - l = ra & 0x04; - a = ra & 0x08; - d = ra & 0x10; - b = (ra & 0x1F) == 0x0C; - if (b) sprintf (s1str, "brki r%d, 0x%x", rd, imm); - else { - if (!l) { - s1len = sprintf (s1str, "bri%s%s", a ? "a" : "", d ? "d" : "" ); - s1len = sprintf (s1str, "%s %d", strncat(s1str," ",6-s1len), s_imm); - } else { - s1len = sprintf (s1str, "bri%sl%s", a ? "a" : "", d ? "d" : ""); - s1len = sprintf (s1str, "%s r%d, %d", strncat(s1str," ",6-s1len), rd, s_imm); - } - if (a) - sprintf (s1str, "%s// 0x%x", strncat(s1str,spc_str,25-s1len), imm); - else - sprintf (s1str, "%s// 0x%x", strncat(s1str,spc_str,25-s1len), pcb + s_imm); - } - break; - case OP_BRCI: - if ((rd & 0xf) <= 0x5) { - s1len = sprintf (s1str, "%si%s r%d, %d", brc_Tbl[rd & 0xf], rd & 0x10 ? "d" : " ", ra, s_imm); - sprintf (s1str, "%s// 0x%x", strncat(s1str,spc_str,25-s1len), pcb + s_imm); - } else - sprintf (s1str, "brci (opcode 0x2f) has some errors, please check\n"); - break; - case OP_BSI: - sprintf (s2str, "r%d, r%d, 0x%0x", rd, ra, imm & 0x1F); - // !! no break - case OP_BS: - if (imm & 0x400) // left shift - s1len = sprintf (s1str, "bsll%s %s", opc & 0x08 ? "i" : " ", s2str); - else - s1len = sprintf (s1str, "bsr%s%s %s", - imm & 0x200 ? "a" : "l", opc & 0x08 ? "i" : " ", s2str); - break; - case OP_CMP: // or RSUBK - if (imm & 1) - sprintf (s1str, "cmp%s %s", imm & 2 ? "u" : " ", s2str); - else - sprintf (s1str, "rsubk %s", s2str); - break; - case OP_FP: - sprintf (s1str, "Floating Point Instruction NOT IMPLEMENTED IN TUMBL"); - break; - case OP_FSL: - case OP_FSLD: - sprintf (s1str, "FSL Instruction NOT IMPLEMENTED IN TUMBL"); - break; - case OP_IDIV: - s1len = sprintf (s1str, "idiv%s %s", imm & 0x02 ? "u" : " ", s2str); - sprintf (s1str, "%s NOT IMPLEMENTED IN TUMBL", strncat(s1str,spc_str,25-s1len)); - break; - case OP_IMM: - sprintf (s1str, "imm 0x%04x // %d", imm, s_imm); - break; - case OP_MUL: - case OP_MULI: - s1len = sprintf (s1str, "%s%s", opc_Tbl[opc], s2str); - break; - case OP_RTBD: - valid_code = 1; - switch(rd) { - case 0x12: sprintf (s2str, "rtbd"); break; // RTBD - case 0x11: sprintf (s2str, "rtid"); break; // RTID - case 0x14: sprintf (s2str, "rted"); break; // RTED - case 0x10: sprintf (s2str, "rtsd"); break; // RTSD - default: - sprintf (s1str, "Illegal subopcode in OP_RTBD"); - valid_code = 0; - } - if (valid_code) - sprintf (s1str, "%s r%d, 0x%x", s2str, ra, imm); - break; - case OP_SEXT: - valid_code = 1; - switch (imm) { - case 0x61: sprintf (s2str, "sext16"); break; // SEXT16 - case 0x60: sprintf (s2str, "sext8 "); break; // SEXT8 - case 0x01: sprintf (s2str, "sra "); break; // SRA - case 0x21: sprintf (s2str, "src "); break; // SRC - case 0x41: sprintf (s2str, "srl "); break; // SRL - default : - sprintf (s1str, "OP_SEXT has some errors, please check" ); - valid_code = 0; - } - if (valid_code) - sprintf (s1str, "%s r%d, r%d", s2str, rd, ra); - break; - case OP_SPR: - sprintf (s1str, "SP-Reg Instruction NOT IMPLEMENTED IN TUMBL"); - break; - default: - xpand = 0; - } // switch (opc) - - if (!xpand) { - if (strncmp(opc_Tbl[opc],"--",2)) - sprintf (s1str, "%s%s", opc_Tbl[opc], s2str); - else - sprintf (s1str, "Unknown instruction / possibly data ?"); - } - } - printf ("%6x: %08x %s\n", pcb, ins, s1str); -} - - -int main(int argc, char *argv[]) -{ - char binFilename[132]; - - // note: strncmp == 0 if the parts of the strings are equal - if ((argc > 2) || ((argc == 2) && !strncmp(argv[1],"-",1))) { - print_Usage( argv[0]); - return (1); - } - - if (argc == 2) - sprintf( binFilename, argv[1]); - else - sprintf( binFilename, "imem.bin"); - read_bin (binFilename, imem, &mem_size); - for (int pci = 0; pci < mem_size; pci++) - disasm (pci); -} -