+#define DATA_ROWS 26
+
+enum
+{
+ COL_NAME = 0,
+ COL_VAL,
+ N_COLUMNS,
+};
+
+#define HEX_DIGITS_2 2
+#define HEX_DIGITS_4 4
+
+struct regwin_infos_t {
+ char *name; /* Register name */
+ int w; /* Number of hex digits to display */
+ unsigned int (*read_func)(int addr); /* Function to read value */
+ void (*write_func)(int param, int val); /* Function to write value */
+ int param; /* Optional parameter to pass to read function. */
+};
+
+/* Generic read/write functions */
+static unsigned int
+regwin_read(int addr, int width)
+{
+ if (width == 2)
+ return memory_sfr_read8(addr);
+ else if (width == 4) {
+ /* Address is low address. */
+ return (memory_sfr_read8(addr + 1) << 8) |
+ memory_sfr_read8(addr);
+ } else
+ return 0xFFFFFFFF;
+}
+
+static void
+regwin_write(int addr, int val, int width)
+{
+ if (width == 2)
+ memory_sfr_write8(addr, (u_int8_t) val);
+ else if (width == 4) {
+ /* Address is low address. */
+ memory_sfr_write8(addr + 1, (u_int8_t) ((val & 0x0000FFFF) >> 8));
+ memory_sfr_write8(addr, (u_int8_t) val);
+ }
+};
+
+/* Specific read/write functions for special registers. */
+
+static unsigned int
+regwin_read_pc(int dummy)
+{
+ return cpu8051.pc;
+}
+
+static void
+regwin_write_pc(int param, int val)
+{
+ cpu8051.pc = (u_int16_t) val;
+}
+
+static unsigned int
+regwin_read_timer(int timer_low_addr)
+{
+ return (memory_sfr_read8(timer_low_addr + 2) << 8) |
+ memory_sfr_read8(timer_low_addr);
+}
+
+static void
+regwin_write_timer(int timer_low_addr, int val)
+{
+ memory_sfr_write8(timer_low_addr + 2, (u_int8_t) ((val & 0x0000FFFF) >> 8));
+ memory_sfr_write8(timer_low_addr, (u_int8_t) val);
+}
+
+static u_int8_t
+regwin_read_bank_offset(void)
+{
+ return memory_sfr_read8(_PSW_) & 0x18;
+}
+
+static unsigned int
+regwin_read_bank(int dummy)
+{
+ return regwin_read_bank_offset() >> 3;
+}
+
+static void
+regwin_write_bank(int param, int bank_number)
+{
+ u_int8_t psw = memory_sfr_read8(_PSW_);
+
+ if ((bank_number < 0) || (bank_number > 3)) {
+ log_info("Error: invalid bank number: %d", bank_number);
+ bank_number = 0;
+ }
+
+ memory_sfr_write8(_PSW_, (psw & ~0x18) | (bank_number << 3));
+}
+
+/* Indirect read of R0 - R7 in current bank from internal memory. */
+static unsigned int
+regwin_read_rx(int offset)
+{
+ return memory_read8(INT_MEM_ID, regwin_read_bank_offset() + offset);
+}
+
+/* Indirect write to R0 - R7 in current bank to internal memory. */
+static void
+regwin_write_rx(int offset, int val)
+{
+ memory_write8(INT_MEM_ID, regwin_read_bank_offset() + offset, (u_int8_t) val);
+}
+
+/* This array defines how to read value for each register. */
+static struct regwin_infos_t regwin_infos[DATA_ROWS] = {
+ {
+ "PC",
+ HEX_DIGITS_4,
+ regwin_read_pc, regwin_write_pc,
+ 0, /* Dummy */
+ },
+ {
+ "SP",
+ HEX_DIGITS_2,
+ NULL, NULL,
+ _SP_,
+ },
+ {
+ "A",
+ HEX_DIGITS_2,
+ NULL, NULL,
+ _ACC_,
+ },
+ {
+ "B",
+ HEX_DIGITS_2,
+ NULL, NULL,
+ _B_,
+ },
+ {
+ "DPTR",
+ HEX_DIGITS_4,
+ NULL, NULL,
+ _DPL_,
+ },
+ {
+ "PSW",
+ HEX_DIGITS_2,
+ NULL, NULL,
+ _PSW_,
+ },
+ {
+ "P0",
+ HEX_DIGITS_2,
+ NULL, NULL,
+ _P0_,
+ },
+ {
+ "P1",
+ HEX_DIGITS_2,
+ NULL, NULL,
+ _P1_,
+ },
+ {
+ "P2",
+ HEX_DIGITS_2,
+ NULL, NULL,
+ _P2_,
+ },
+ {
+ "P3",
+ HEX_DIGITS_2,
+ NULL, NULL,
+ _P3_,
+ },
+ {
+ "TCON",
+ HEX_DIGITS_2,
+ NULL, NULL,
+ _TCON_,
+ },
+ {
+ "TMOD",
+ HEX_DIGITS_2,
+ NULL, NULL,
+ _TMOD_,
+ },
+ {
+ "TIMER0",
+ HEX_DIGITS_4,
+ regwin_read_timer, regwin_write_timer,
+ _TL0_,
+ },
+ {
+ "TIMER1",
+ HEX_DIGITS_4,
+ regwin_read_timer, regwin_write_timer,
+ _TL1_,
+ },
+ {
+ "SCON",
+ HEX_DIGITS_2,
+ NULL, NULL,
+ _SCON_,
+ },
+ {
+ "IE",
+ HEX_DIGITS_2,
+ NULL, NULL,
+ _IE_,
+ },
+ {
+ "IP",
+ HEX_DIGITS_2,
+ NULL, NULL,
+ _IP_,
+ },
+ {
+ "BANK",
+ HEX_DIGITS_2,
+ regwin_read_bank, regwin_write_bank,
+ 0, /* Dummy */
+ },
+ /* R0-R7 Registers in current Bank */
+ {
+ "R0",
+ HEX_DIGITS_2,
+ regwin_read_rx, regwin_write_rx,
+ _R0_,
+ },
+ {
+ "R1",
+ HEX_DIGITS_2,
+ regwin_read_rx, regwin_write_rx,
+ _R1_,
+ },
+ {
+ "R2",
+ HEX_DIGITS_2,
+ regwin_read_rx, regwin_write_rx,
+ _R2_,
+ },
+ {
+ "R3",
+ HEX_DIGITS_2,
+ regwin_read_rx, regwin_write_rx,
+ _R3_,
+ },
+ {
+ "R4",
+ HEX_DIGITS_2,
+ regwin_read_rx, regwin_write_rx,
+ _R4_,
+ },
+ {
+ "R5",
+ HEX_DIGITS_2,
+ regwin_read_rx, regwin_write_rx,
+ _R5_,
+ },
+ {
+ "R6",
+ HEX_DIGITS_2,
+ regwin_read_rx, regwin_write_rx,
+ _R6_,
+ },
+ {
+ "R7",
+ HEX_DIGITS_2,
+ regwin_read_rx, regwin_write_rx,
+ _R7_,
+ },
+};
+
+/* Creating a model */
+static GtkListStore *
+regwin_init_store(void)
+{
+ GtkTreeIter iter;
+ int row;
+ int col;
+ GtkListStore *store;
+ GType col_types[N_COLUMNS];
+
+ /* No need for static array, all our columns are of the same type. */
+ for (col = 0; col < N_COLUMNS; col++)
+ col_types[col] = G_TYPE_STRING;
+
+ store = gtk_list_store_newv(N_COLUMNS, col_types);
+
+ /* Add rows. */
+ for (row = 0; row < DATA_ROWS; row++)
+ gtk_list_store_append(store, &iter);
+
+ return store;
+}
+
+static int
+regwin_find_row(const char *regname)
+{
+ int row;
+
+ for (row = 0; row < DATA_ROWS; row++) {
+ if (strcmp(regwin_infos[row].name, regname) == 0)
+ return row;
+ }
+
+ return -1; /* Programming error. */
+}
+
+static void
+regwin_cell_edited(GtkCellRendererText *cell, gchar *path_string,
+ gchar *new_str, gpointer model)