diff --git a/src/.uviemon_history b/src/.uviemon_history
index 8a570aa5cff964caabdf881cf517c408bd873f8d..ae47117fe4299be5d738c7fe9afefece6a898e0a 100644
--- a/src/.uviemon_history
+++ b/src/.uviemon_history
@@ -76,3 +76,51 @@ quit
 exit
 exit
 exit
+mem 0xff9110000
+mem 0xff9110004
+mem 0xff9200000
+mem 0xff9200000 128
+mem 0xff9200000 164
+mem 0xff9200000 64
+mem 0xff9200000 68
+mem 0xff9100000 64
+quit
+exit
+inst
+inst
+inst 11
+inst
+inst
+break leon3_dsu.c:493
+quit
+inst
+inst
+inst
+inst
+inst
+inst
+isnt
+inst
+inst
+mem 0xE010ffb0
+mem 0xE010ffb0 128
+inst
+isnt
+inst
+inst
+isnt
+inst
+inst
+inst
+inst
+inst
+inst
+mem 0xe0110000
+0xe0100000
+mem 0xe0100000
+inst
+inst
+inst
+inst
+inst
+inst
diff --git a/src/leon3_dsu.c b/src/leon3_dsu.c
index ff539afdd3b93f8b7df96b3c1f18136926fcaec7..e449064bd70d0cddcd88cf2b6247fbccbf44909c 100644
--- a/src/leon3_dsu.c
+++ b/src/leon3_dsu.c
@@ -40,6 +40,7 @@
  */
 
 #include <stddef.h>	// size_t
+#include <stdlib.h> // malloc, free
 #include "leon3_dsu.h"
 
 #include "ftdi_device.hpp"
@@ -918,3 +919,66 @@ void dsu_set_reg_fp(uint32_t cpu, uint32_t cwp, uint32_t val)
 	if (reg)
 		iowrite32((uint32_t) reg, val);
 }
+
+
+
+/**
+ * @brief get the last line_count lines from the instruction trace buffer
+ *
+ * @param cpu the cpu number
+ * @param buffer the buffer to write the lines to
+ * @param line_count the number of lines to read (instructions can be multiple lines)
+ * @param line_start the number of lines to skip when going backwards
+ */
+void dsu_get_instr_trace_buffer(uint32_t cpu, struct instr_trace_buffer_line *buffer, uint32_t line_count, uint32_t line_start)
+{
+	
+	DWORD *data = (DWORD*) malloc(DSU_INST_TRCE_BUF_LINE_SIZE * line_count);
+	
+	uint32_t inst_trce_ctrl_reg = ioread32((uint32_t) DSU_BASE(cpu) + DSU_INST_TRCE_CTRL);
+	uint32_t inst_pointer = inst_trce_ctrl_reg & 0xFF;
+
+	/* inst_pointer points next line that will be written
+	 * ignore line_start lines
+	 * go back line_count lines to read them
+	 * this can very likely overflow, that is the reason for the modulo operation
+	 */
+	uint32_t first_line_to_read = inst_pointer - line_start - line_count;
+	uint32_t offset_start = (first_line_to_read * DSU_INST_TRCE_BUF_LINE_SIZE) % DSU_INST_TRCE_BUF_SIZE;
+	uint32_t read_size, line_ptr = 0;
+
+	/* if an overflow in the instruction trace would occur read only until the
+	 * end of the buffer in the first step
+	 */
+	if (offset_start + line_count * DSU_INST_TRCE_BUF_LINE_SIZE > DSU_INST_TRCE_BUF_SIZE)
+		read_size = DSU_INST_TRCE_BUF_SIZE - offset_start;
+	else
+		read_size = line_count * DSU_INST_TRCE_BUF_LINE_SIZE;
+
+	/* Read size in dwords */
+	ioread32(DSU_BASE(cpu) + DSU_INST_TRCE_BUF_START + offset_start, data, read_size / 4);
+
+	for(uint32_t i = 0; i < read_size / 4; i += 4) {
+		buffer[line_ptr].field[0] = data[i + 0];
+		buffer[line_ptr].field[1] = data[i + 1];
+		buffer[line_ptr].field[2] = data[i + 2];
+		buffer[line_ptr].field[3] = data[i + 3];
+		line_ptr++;
+	}
+
+	/* Read remaining data in case of an overflow in the circular instruction trace buffer  */
+	uint32_t remaining_size = line_count * DSU_INST_TRCE_BUF_LINE_SIZE - read_size;
+	if (remaining_size > 0) {
+		ioread32(DSU_BASE(cpu) + DSU_INST_TRCE_BUF_START, data, remaining_size / 4);
+		
+		for(uint32_t i = 0; i < remaining_size / 4; i += 4) {
+			buffer[line_ptr].field[0] = data[i + 0];
+			buffer[line_ptr].field[1] = data[i + 1];
+			buffer[line_ptr].field[2] = data[i + 2];
+			buffer[line_ptr].field[3] = data[i + 3];
+			line_ptr++;
+		}
+	}
+
+	free(data);	
+}
diff --git a/src/leon3_dsu.h b/src/leon3_dsu.h
index 8afdd127dbe7d6124d6c600f6c7c6cf0b04a3196..680e8eba2d777ac21ffb4b5b4159a6e9adab94db 100644
--- a/src/leon3_dsu.h
+++ b/src/leon3_dsu.h
@@ -64,7 +64,9 @@
 #define DSU_AHB_MASK_2		0x00005c
 
 #define DSU_INST_TRCE_BUF_START	0x100000
+#define DSU_INST_TRCE_BUF_SIZE 0x10000
 #define DSU_INST_TRCE_BUF_LINES	256
+#define DSU_INST_TRCE_BUF_LINE_SIZE 16
 #define DSU_INST_TRCE_CTRL	0x110000
 
 #define DSU_AHB_TRCE_BUF_START	0x200000
@@ -181,7 +183,10 @@ struct instr_trace_buffer_line {
 			uint32_t multi_cycle_inst :1;
 			uint32_t timetag	  :30;
 			uint32_t load_store_param :32;
-			uint32_t program_cntr	  :30;
+			/* program_cntr is still a 32bit number,
+			 * but the two lsb are always 0 and thus used for something else
+			 */
+			uint32_t program_cntr	  :30; 
 			uint32_t instr_trap	  :1;
 			uint32_t proc_error_mode  :1;
 			uint32_t opcode		  :32;
@@ -259,6 +264,9 @@ uint32_t dsu_get_reg_tbr(uint32_t cpu);
 uint32_t dsu_get_reg_trap(uint32_t cpu);
 void dsu_set_reg_psr(uint32_t cpu, uint32_t val);
 
+/* line_start is relative with 0 being the last executed line */
+void dsu_get_instr_trace_buffer(uint32_t cpu, struct instr_trace_buffer_line *buffer, uint32_t line_count, uint32_t line_start); 
+
 uint32_t dsu_get_reg_wim(uint32_t cpu);
 uint32_t dsu_get_reg_pc(uint32_t cpu);
 uint32_t dsu_get_reg_sp(uint32_t cpu, uint32_t cwp);
diff --git a/src/uviemon.cpp b/src/uviemon.cpp
index 4680bce3c0b3d2ac8a89c1d1cfdacb5a0c1d0ec5..7ebc905a2a12f47b90742205cc935d2168f78adc 100644
--- a/src/uviemon.cpp
+++ b/src/uviemon.cpp
@@ -39,10 +39,12 @@ void console()
 		
 		raw_input = readline("uviemon> "); // Read input from the user
 
+		if (!raw_input)
+			break;
+
 		if (raw_input && *raw_input)
 			add_history(raw_input);
 
-
 		parse_result = parse_input(raw_input);
 		free(raw_input);
 	}
diff --git a/src/uviemon_cli.cpp b/src/uviemon_cli.cpp
index a7acf79a6781618d06438bdf3a3044b9c464a131..8594fa5c3bd8181b822f0bfeff89b933c4e6886c 100644
--- a/src/uviemon_cli.cpp
+++ b/src/uviemon_cli.cpp
@@ -18,12 +18,16 @@
 #include <fstream>	// For loading a file in load()
 #include <cmath>	// For std::ceil in load()
 
+#include <stdlib.h>
+
+#include "leon3_dsu.h"
+
 
 using namespace std;
 
 //static int command_count;
 
-#define COMMAND_COUNT 13
+#define COMMAND_COUNT 14
 
 static command commands[COMMAND_COUNT] =  {
 	{ "help", &help },
@@ -40,6 +44,8 @@ static command commands[COMMAND_COUNT] =  {
 
 	{ "bdump", &bdump },
 
+	{ "inst", &inst },
+
 	{ "load", &load },
 	{ "verify", &verify },
 	{ "run", &run }
@@ -49,6 +55,8 @@ static command commands[COMMAND_COUNT] =  {
 //static void register_command(command com, const char *name, void (*function)(const char*, int, char [MAX_PARAMETERS][MAX_PARAM_LENGTH]));
 static DWORD parse_parameter(char *param);
 
+static void parse_opcode(char *buffer, uint32_t opcode, uint32_t address);
+
 std::unordered_map<int, std::string> tt_errors = {
 	{0x0, "[reset]: Power-on reset"},
 	{0x2b, "[write_error]: write buffer error"},
@@ -249,7 +257,9 @@ void help(const char *command, int param_count, char params[MAX_PARAMETERS][MAX_
 	printf("  wmemh: \t Write <data#2> 16-bit WORD to a memory <address#1>\n");
 	printf("  wmemb: \t Write <data#2> 8-bit BYTE to a memory <address#1>\n\n");
 
-	printf("  bdump: \t Read <length#2> BYTEs of data from memory starting at an <address#1>, saving the data to a <filePath#1>\n\n");
+	printf("  bdump:\t Read <length#2> BYTEs of data from memory starting at an <address#1>, saving the data to a <filePath#1>\n\n");
+
+	printf("  isnt:\t Prints the last <instruction_cnt#1> instruction to stdout\n\n");
 
 	printf("  load: \t Write a file with <filePath#1> to the device memory\n");
 	printf("  verify: \t Verify a file written to the device memory with <filePath#1>\n");
@@ -437,6 +447,118 @@ void wmemx(const char *command, int param_count, char params[MAX_PARAMETERS][MAX
 	}
 }
 
+void inst(const char* command, int param_count, char params[MAX_PARAMETERS][MAX_PARAM_LENGTH])
+{
+	uint32_t instr_count = 11;
+
+	if (param_count > 1) {
+		printf("Inst only needs 1 parameter: the number of lines");
+		return;
+	}
+
+	if (param_count == 1) {
+		if ( (instr_count = strtol(params[0], NULL, 10)) == 0) {
+			printf("Parameter 1 must be a positive integer");
+			return;
+		}
+	}
+
+	
+	struct instr_trace_buffer_line *buffer = (instr_trace_buffer_line*) malloc(sizeof(instr_trace_buffer_line) * instr_count * 2);
+
+	/* TODO: manage active cpu */
+	dsu_get_instr_trace_buffer(0, buffer, instr_count * 2, 0);
+
+
+	uint32_t i_cntr = 0;
+	int i, page = 0;
+
+	/* go back instr_count number of instructions counting multi line instructions  */
+	/* there must be a better way to do this */
+	while(i_cntr < instr_count) {
+		for(i = instr_count * 2; i > -1; i--) {
+			/* count all non multi-line instruction as unique instructions  */
+			if ((buffer[i].field[0] & 0x40000000) == 0)
+				i_cntr++;
+
+			if (i_cntr == instr_count)
+				break;
+		}
+
+		if (i_cntr < instr_count) {
+			page++;
+			dsu_get_instr_trace_buffer(0, buffer, instr_count * 2, page * instr_count * 2);
+		}
+	}
+
+	uint32_t first_line = i;
+	char operation[31];
+ 
+	/* print header */
+	printf("    %9s  %8s  %30s  %10s  %10s\n", "TIME    ", "ADDRESS ", "INSTRUCTION        ", "RESULT  ", "SYMBOL");
+	while(page > -1) {
+		for(uint32_t j = first_line; j < instr_count * 2; j++) {
+			/* Check for non multi-line instruction second bit is zero  */
+			if ((buffer[j].field[0] & 0x40000000) == 0) {
+				if (j != first_line) {
+					printf("]  -\n");
+				}
+
+				/* first is the time tag with first 2 bits set to zero
+				 * second is program counter with last two bits set to zero
+				 */
+				parse_opcode(operation, buffer[j].field[3], buffer[j].field[2] & 0xFFFFFFFC); 
+				printf("    %9u  %08x  %-30s  [",
+					   buffer[j].field[0] & 0x3FFFFFFF,
+					   buffer[j].field[2] & 0xFFFFFFFC,
+					   operation);
+
+
+				/* Check for instruction trap bit 2 is set */
+				if ((buffer[j].field[2] & 0x2) == 0x2)
+					printf("  TRAP  ");
+				else
+					printf("%08x", buffer[j].load_store_param);
+
+			} else {
+				printf(" %08x", buffer[j].load_store_param);
+			}
+		}
+
+		if (--page < 0)
+			break;
+		
+		dsu_get_instr_trace_buffer(0, buffer, instr_count * 2, page * instr_count * 2);
+	}
+
+	printf("]  -\n");
+
+
+	free(buffer);
+}
+
+
+static void parse_opcode(char *buffer, uint32_t opcode, uint32_t address)
+{
+	struct opcode op;
+	op.opcode_raw = opcode;
+
+	switch (op.op_call.op) {
+	case 0:
+		sprintf(buffer, "%#08x", opcode);
+		break;
+	case 1:
+		sprintf(buffer, "call  %#08x", address + 4 * op.op_call.disp30);
+		break;
+	case 2:
+		sprintf(buffer, "%#08x", opcode);
+		break;
+	case 3:
+		sprintf(buffer, "%#08x", opcode);
+		break;
+	}
+}
+
 void wmem(DWORD addr, DWORD data)
 {
 	printf("Writing to memory... ");
diff --git a/src/uviemon_cli.hpp b/src/uviemon_cli.hpp
index 99e935a587b23db3596ef71cecafc54f3fbd0083..0e9931dbce65913dd006a5eacb99f7d156b1a18e 100644
--- a/src/uviemon_cli.hpp
+++ b/src/uviemon_cli.hpp
@@ -20,6 +20,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <string.h>
+#include <stdint.h>
 
 #define MAX_PARAMETERS 3
 #define MAX_PARAM_LENGTH 50
@@ -44,6 +45,61 @@ int parse_input(char *input);
 void print_help_text();
 //void cleanup();
 
+struct op_call_t {
+	uint32_t disp30 :30;
+	uint32_t op     :2;
+};
+struct op_sethi_t  {
+	uint32_t imm22 :22;
+	uint32_t op2   :3;
+	uint32_t rd    :5;
+	uint32_t op    :2;
+};
+struct op_branch_t {
+	uint32_t disp22 :22;
+	uint32_t op2    :3;
+	uint32_t cond   :4;
+	uint32_t a      :1;	
+	uint32_t op     :2;
+};
+struct op_other_1_t {
+	uint32_t rs2 :5;
+	uint32_t asi :8;
+	uint32_t i   :1;
+	uint32_t rs1 :5;
+	uint32_t op3 :6;	
+	uint32_t rd  :5;	
+	uint32_t op  :2;
+};
+struct op_other_2_t {
+	uint32_t simm13 :13;
+	uint32_t i      :1;	
+	uint32_t rs1    :5;
+	uint32_t op3    :6;
+	uint32_t rd     :5;	
+	uint32_t op     :2;
+};
+struct op_other_3_t {
+	uint32_t rs2 :5;
+	uint32_t opf :9;
+	uint32_t rs1 :5;
+	uint32_t op3 :6;
+	uint32_t rd  :5;	
+	uint32_t op  :2;
+};
+
+
+struct opcode {
+	union {
+		struct op_call_t op_call;
+		struct op_sethi_t op_sethi;
+		struct op_branch_t op_branch;
+		struct op_other_1_t op_other_1;
+		struct op_other_2_t op_other_2;
+		struct op_other_3_t op_other_3;
+		uint32_t opcode_raw;
+	};
+}__attribute__((packed));
 
 /* Command functions  */
 void help  (const char *command, int param_count, char params[MAX_PARAMETERS][MAX_PARAM_LENGTH]);
@@ -56,6 +112,7 @@ void load  (const char *command, int param_count, char params[MAX_PARAMETERS][MA
 void verify(const char *command, int param_count, char params[MAX_PARAMETERS][MAX_PARAM_LENGTH]);
 void bdump (const char *command, int param_count, char params[MAX_PARAMETERS][MAX_PARAM_LENGTH]);
 void wash  (const char *command, int param_count, char params[MAX_PARAMETERS][MAX_PARAM_LENGTH]);
+void inst  (const char *command, int param_count, char params[MAX_PARAMETERS][MAX_PARAM_LENGTH]);
 
 void wmem(DWORD addr, DWORD data);
 void wmemh(DWORD addr, WORD data);