gdb: Read/write SREG values correctly
authorJakob Gruber <jakob.gruber@gmail.com>
Wed, 18 Jul 2012 10:37:50 +0000 (12:37 +0200)
committerJakob Gruber <jakob.gruber@gmail.com>
Wed, 18 Jul 2012 10:43:28 +0000 (12:43 +0200)
Accessing SREG through gdb seems to have been broken since SREG is no
longer synthesized at each instruction (2f67001d). As a quick fix, make
SREG accessors public and use them in sim_gdb.

Note that invalid avr->sreg values no longer trigger the CRASH macro.

simavr/sim/sim_core.c
simavr/sim/sim_core.h
simavr/sim/sim_gdb.c

index f3106ef..33073c8 100644 (file)
@@ -155,8 +155,7 @@ static inline void _avr_set_r(avr_t * avr, uint8_t r, uint8_t v)
        if (r == R_SREG) {
                avr->data[R_SREG] = v;
                // unsplit the SREG
-               for (int i = 0; i < 8; i++)
-                       avr->sreg[i] = (v & (1 << i)) != 0;
+               SET_SREG_FROM(avr, v);
                SREG();
        }
        if (r > 31) {
@@ -209,13 +208,7 @@ static inline uint8_t _avr_get_ram(avr_t * avr, uint16_t addr)
                 * SREG is special it's reconstructed when read
                 * while the core itself uses the "shortcut" array
                 */
-               avr->data[R_SREG] = 0;
-               for (int i = 0; i < 8; i++)
-                       if (avr->sreg[i] > 1) {
-                               printf("** Invalid SREG!!\n");
-                               CRASH();
-                       } else if (avr->sreg[i])
-                               avr->data[R_SREG] |= (1 << i);
+               READ_SREG_INTO(avr, avr->data[R_SREG]);
                
        } else if (addr > 31 && addr < 256) {
                uint8_t io = AVR_DATA_TO_IO(addr);
index 9f83654..a3a4c28 100644 (file)
@@ -95,6 +95,26 @@ void avr_dump_state(avr_t * avr);
 
 #endif 
 
+/**
+ * Reconstructs the SREG value from avr->sreg into dst.
+ */
+#define READ_SREG_INTO(avr, dst) { \
+                       dst = 0; \
+                       for (int i = 0; i < 8; i++) \
+                               if (avr->sreg[i] > 1) { \
+                                       printf("** Invalid SREG!!\n"); \
+                               } else if (avr->sreg[i]) \
+                                       dst |= (1 << i); \
+               }
+
+/**
+ * Splits the SREG value from src into the avr->sreg array.
+ */
+#define SET_SREG_FROM(avr, src) { \
+                       for (int i = 0; i < 8; i++) \
+                               avr->sreg[i] = (src & (1 << i)) != 0; \
+               }
+
 #ifdef __cplusplus
 };
 #endif
index d5313fd..ac6d068 100644 (file)
@@ -32,6 +32,7 @@
 #include <poll.h>
 #include <pthread.h>
 #include "sim_avr.h"
+#include "sim_core.h" // for SET_SREG_FROM, READ_SREG_INTO
 #include "sim_hex.h"
 #include "avr_eeprom.h"
 #include "sim_gdb.h"
@@ -210,6 +211,7 @@ static int gdb_write_register(avr_gdb_t * g, int regi, uint8_t * src)
                        return 1;
                case 32:
                        g->avr->data[R_SREG] = *src;
+                       SET_SREG_FROM(g->avr, *src);
                        return 1;
                case 33:
                        g->avr->data[R_SPL] = src[0];
@@ -228,8 +230,11 @@ static int gdb_read_register(avr_gdb_t * g, int regi, char * rep)
                case 0 ... 31:
                        sprintf(rep, "%02x", g->avr->data[regi]);
                        break;
-               case 32:
-                       sprintf(rep, "%02x", g->avr->data[R_SREG]);
+               case 32: {
+                               uint8_t sreg;
+                               READ_SREG_INTO(g->avr, sreg);
+                               sprintf(rep, "%02x", sreg);
+                       }
                        break;
                case 33:
                        sprintf(rep, "%02x%02x", g->avr->data[R_SPL], g->avr->data[R_SPH]);