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;
-- 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;
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;
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;
SIGNAL setup_int_r : STD_LOGIC;
SIGNAL int_busy_r : STD_LOGIC;
-
BEGIN
-- static connections
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;
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
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
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';
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
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
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;
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;
--
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;
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;
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
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
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;
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)
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
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
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 =>
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;
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;
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
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
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;
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
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);
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;
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;
--
INT_CTRL_i : IN INT_CTRL_Type;
ID2CTRL_o : OUT ID2CTRL_Type;
- --
- noLiteOpc_o : OUT STD_LOGIC
+ --
+ noLiteOpc_o : OUT STD_LOGIC
);
END COMPONENT;
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;
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;
-- 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;
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;
+++ /dev/null
-/*******************************************************************************
-*
-* 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 <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <iostream>
-#include <fstream>
-#include <iomanip>
-
-
-// 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);
-}
-