Hello,
Pushing diff in attachement to not depend of google drive.
Rémy

Le mer. 8 déc. 2021 à 18:38, Rémy <grizzlyf...@gmail.com> a écrit :

> Hello,
>
> My company have to works with *atxmega128a1 *and *atxmega128a4u *devices
> but unfortunately these are not implemented on Simulavr project.
> We use Simulavr for running unit test on our programs.
>
> I have developed a patch for implementing the basic features of the
> atxmega microcontroller. It can be found at
> https://drive.google.com/file/d/18jhbJ9M7zGnB_K132_1OYwk5ZpIDLyH9/view?usp=sharing
> (The savannah account is not working yet and i can not do pull request)
> It will provided without any counterpart, in order to improve *simulavr *
> software.
>
> The patch will manage
> - The CPU implementation
> - The full set of atxmega32/64/128 instructions
> - RAM addressing, and extended addressing
> - Hardware GPIO port
> - EEPROM and non-volatile memory controller for eeprom part.
> These features will be sufficient for running our unit tests and checking
> algorithms.
>
> However,
> - The most of IO registers are mapped to RAM.
> - No interruption are implemented
> - Timers are not implemented
> - Communication lines like SPI, UART, I2C are not implemented
> - GPIO special functions like detecting edge or PWM are not implemented
> - Read and write into flash memory are not tested yet
> - Some feature use atmega128 implementation, near to atXmega but
> uncompleted regarding to atXmega features.
>
> The software was tested with code running on atxmega128a1 and
> atxmega128a4u devices. We have also take care of not breaking the existing
> compatibility. Checks had done with atmega32/64/128 code as far as we could
> have.
>
> Thanks,
> MALMARTEL Rémy
>
>
>
diff --git a/Makefile b/Makefile
index d2029cc..1ec0ba2 100644
--- a/Makefile
+++ b/Makefile
@@ -43,22 +44,22 @@ check-config:
 # build targets
 
 clean: check-config
-	@make ${BUILD_CONFIG_OPTS} clean
+	@+make ${BUILD_CONFIG_OPTS} clean
 
 build: check-config
-	@make ${BUILD_CONFIG_OPTS}
+	@+make ${BUILD_CONFIG_OPTS}
 
 check: check-config
-	@make ${BUILD_CONFIG_OPTS} check
+	@+make ${BUILD_CONFIG_OPTS} check
 
 doc: check-config
-	@make ${BUILD_CONFIG_OPTS} doc
+	@+make ${BUILD_CONFIG_OPTS} doc
 
 doxygen: check-config
-	@make ${BUILD_CONFIG_OPTS} doxygen
+	@+make ${BUILD_CONFIG_OPTS} doxygen
 
 debian: check-config
-	@make ${BUILD_CONFIG_OPTS} debian
+	@+make ${BUILD_CONFIG_OPTS} debian
 
 # configure targets
 
@@ -113,6 +114,6 @@ simple:
 # maintainance targets
 
 keytrans: check-config
-	@make ${BUILD_CONFIG_OPTS} keytrans
+	@+make ${BUILD_CONFIG_OPTS} keytrans
 
 # EOF
diff --git a/app/gdbserver.cpp b/app/gdbserver.cpp
index 632ede9..2941c6d 100644
--- a/app/gdbserver.cpp
+++ b/app/gdbserver.cpp
@@ -124,7 +124,7 @@ int GdbServerSocketUnix::ReadByte(void) {
 }
 
 void GdbServerSocketUnix::Write(const void* buf, size_t count) {
-    int res;
+    ssize_t res;
 
     res = write(conn, buf, count);
 
@@ -134,8 +134,8 @@ void GdbServerSocketUnix::Write(const void* buf, size_t count) {
 
     /* FIXME: if this happens a lot, we could try to resend the
     unsent bytes. */
-    if((unsigned int)res != count)
-        avr_error("write only wrote %d of %lu bytes", res, count);
+    if((size_t)res != count)
+        avr_error("write only wrote %d of %u bytes", res, count);
 }
 
 void GdbServerSocketUnix::SetBlockingMode(int mode) {
diff --git a/app/main.cpp b/app/main.cpp
index 41e50cb..7b4d1de 100644
--- a/app/main.cpp
+++ b/app/main.cpp
@@ -27,6 +27,7 @@
 #include <sstream>
 #include <string>
 #include <map>
+#include <list>
 #include <limits>
 
 
@@ -221,12 +222,10 @@ int main(int argc, char *argv[]) {
     unsigned long long maxRunTime = 0;
     UserInterface *ui;
     
-    unsigned long writeToPipeOffset = 0x20;
-    unsigned long readFromPipeOffset = 0x21;
     unsigned long writeToAbort = 0;
     unsigned long writeToExit = 0;
-    std::string readFromPipeFileName = "";
-    std::string writeToPipeFileName = "";
+    std::list<std::string> listReadFromPipeFileName;
+    std::list<std::string> listWriteToPipeFileName;
     
     std::vector<std::string> terminationArgs;
     
@@ -279,15 +278,13 @@ int main(int argc, char *argv[]) {
             case 'v':
                 global_verbose_on = 1;
                 break;
-            
-            case 'R': //read from pipe 
-                readFromPipeFileName = 
-                    SplitOffsetFile(optarg, "readFromPipe", 16, &readFromPipeOffset);
+
+            case 'R': //read from pipe
+                listReadFromPipeFileName.push_back(optarg);
                 break;
-            
+
             case 'W': //write to pipe
-                writeToPipeFileName = 
-                   SplitOffsetFile(optarg, "writeToPipe", 16, &writeToPipeOffset);
+                listWriteToPipeFileName.push_back(optarg);
                 break;
             
             case 'a': // write to abort
@@ -475,18 +472,26 @@ int main(int argc, char *argv[]) {
     }
     
     //if we want to insert some special "pipe" Registers we could do this here:
-    if(readFromPipeFileName != "") {
-        avr_message("Add ReadFromPipe-Register at 0x%lx and read from file: %s",
-                    readFromPipeOffset, readFromPipeFileName.c_str());
-        dev1->ReplaceIoRegister(readFromPipeOffset,
-            new RWReadFromFile(dev1, "FREAD", readFromPipeFileName.c_str()));
+    for (std::list<std::string>::iterator it = listReadFromPipeFileName.begin();
+        it != listReadFromPipeFileName.end(); it++) {
+      unsigned long readFromPipeOffset = 0x21;
+      const std::string readFromPipeFileName =
+        SplitOffsetFile(it->c_str(), "readFromPipe", 16, &readFromPipeOffset);
+      avr_message("Add ReadFromPipe-Register at 0x%lx and read from file: %s",
+                      readFromPipeOffset, readFromPipeFileName.c_str());
+      dev1->ReplaceIoRegister(readFromPipeOffset,
+        new RWReadFromFile(dev1, std::string("FREAD") + std::to_string((long long unsigned)readFromPipeOffset), readFromPipeFileName.c_str()));
     }
-    
-    if(writeToPipeFileName != "") {
-        avr_message("Add WriteToPipe-Register at 0x%lx and write to file: %s",
-                    writeToPipeOffset, writeToPipeFileName.c_str());
-        dev1->ReplaceIoRegister(writeToPipeOffset,
-            new RWWriteToFile(dev1, "FWRITE", writeToPipeFileName.c_str()));
+
+    for (std::list<std::string>::iterator it = listWriteToPipeFileName.begin();
+        it != listWriteToPipeFileName.end(); it++) {
+      unsigned long writeToPipeOffset = 0x20;
+      const std::string writeFromPipeFileName =
+        SplitOffsetFile(it->c_str(), "writeFromPipe", 16, &writeToPipeOffset);
+      avr_message("Add WriteToPipe-Register at 0x%lx and write from file: %s",
+                      writeToPipeOffset, writeFromPipeFileName.c_str());
+      dev1->ReplaceIoRegister(writeToPipeOffset,
+        new RWWriteToFile(dev1, std::string("FWRITE") + std::to_string((long long unsigned)writeToPipeOffset), writeFromPipeFileName.c_str()));
     }
     
     if(writeToAbort) {
diff --git a/include/atxmega128aubase.h b/include/atxmega128aubase.h
new file mode 100644
index 0000000..65acf79
--- /dev/null
+++ b/include/atxmega128aubase.h
@@ -0,0 +1,174 @@
+ /*
+ ****************************************************************************
+ *
+ * simulavr - A simulator for the Atmel AVR family of microcontrollers.
+ * Copyright (C) 2021
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ ****************************************************************************
+ *
+ *  $Id$
+ */
+
+
+#ifndef ATXMEGA128AUBASE
+#define ATXMEGA128AUBASE
+
+#include "avrdevice.h"
+#include "hardware.h"
+#include "rwmem.h"
+#include "hwtimer/timerprescaler.h"
+#include "hwtimer/timerirq.h"
+#include "hwtimer/hwtimer.h"
+#include "externalirq.h"
+#include "hwuart.h"
+#include "hwport.h"
+#include "hwxport.h"
+#include "hwspi.h"
+#include "hwad.h"
+#include "hwacomp.h"
+#include "hwnvm.h"
+#include "pin.h"
+
+#include "ioregs.h" //only for rampz here
+
+#include <list>
+
+// Poly2: https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-8331-8-and-16-bit-AVR-Microcontroller-XMEGA-AU_Manual.pdf
+// Poly5: https://ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-instruction-set-manual.pdf
+//! AVRDevice class for ATXMEGAxxxA4U
+class AvrDevice_atxmega128aubase: public AvrDevice {
+    public:
+      // GPIORegister gpio[16]; // General purpose IO registers
+      HWPort vport0; // Virtual Port
+      HWPort vport1; // Virtual Port
+      HWPort vport2; // Virtual Port
+      HWPort vport3; // Virtual Port
+      // HWAd * adca[4]; // Analog to digital converter on port A
+      // HWAd * adcb[4]; // Analog to digital converter on port B
+      // HWAcomp * aca; // Analog comparator pair on port A
+      // HWAcomp * acb; // Analog comparator pair on port B
+      HWxPort porta; // Port A
+      HWxPort portb; // Port B
+      HWxPort portc; // Port C
+      HWxPort portd; // Port D
+      HWxPort porte; // Port E
+      HWxPort portf; // Port F
+      HWxPort portg; // Port G
+      HWxPort porth; // Port H
+      HWxPort portj; // Port J
+      HWxPort portk; // Port K
+      HWxPort portl; // Port L
+      HWxPort portm; // Port M
+      HWxPort portn; // Port N
+      HWxPort portp; // Port P
+      HWxPort portq; // Port Q
+      HWxPort portr; // Port R
+
+      HWAdmuxM16 *admux;
+      HWARef4 * aref;
+      HWNvm * nvm;
+
+      AvrDevice_atxmega128aubase(unsigned flash_bytes, unsigned ee_bytes, unsigned ext_bytes, unsigned nrww_start);
+      ~AvrDevice_atxmega128aubase();
+
+  private:
+      std::list<RAM*> ioMem;
+      void changeIoToRam(unsigned int s_add, unsigned int e_add);
+      void changeToInvalidRam(unsigned int s_add, unsigned int e_add);
+};
+
+/* Name           Flash+Btd eep ram
+ATxmega128A1-AU   128K + 8K 2K  8K
+ATxmega128A1-AUR  128K + 8K 2K  8K
+ATxmega128A1-CU   128K + 8K 2K  8K
+ATxmega128A1CUR   128K + 8K 2K  8K
+ATxmega128A1-C7U  128K + 8K 2K  8K
+ATxmega128A1-C7UR 128K + 8K 2K  8K
+ATxmega64A1-AU     64K + 8K 2K  4K
+ATxmega64A1-CU     64K + 8K 2K  4K
+ATxmega64A1-CUR    64K + 8K 2K  4K
+ATxmega64A1-C7U    64K + 8K 2K  4K
+ATxmega64A1-C7UR   64K + 8K 2K  4K
+*/
+class AvrDevice_atxmega128a1 : public AvrDevice_atxmega128aubase {
+	public: AvrDevice_atxmega128a1();
+};
+
+class AvrDevice_atxmega64a1 : public AvrDevice_atxmega128aubase {
+	public: AvrDevice_atxmega64a1();
+};
+
+/* Name              Flash+Btd eep ram
+ATxmega128A4U-AN     128K + 8K 2K 8K
+ATxmega128A4U-ANR(4) 128K + 8K 2K 8K
+ATxmega128A4U-AU     128K + 8K 2K 8K
+ATxmega128A4U-AUR(4) 128K + 8K 2K 8K
+ATxmega128A4U-CU     128K + 8K 2K 8K
+ATxmega128A4U-CUR(4) 128K + 8K 2K 8K
+ATxmega128A4U-M7     128K + 8K 2K 8K
+ATxmega128A4U-M7R(4) 128K + 8K 2K 8K
+ATxmega128A4U-MH     128K + 8K 2K 8K
+ATxmega128A4U-MHR(4) 128K + 8K 2K 8K
+ATxmega64A4U-AN       64K + 4K 2K 4K
+ATxmega64A4U-ANR(4)   64K + 4K 2K 4K
+ATxmega64A4U-AU       64K + 4K 2K 4K
+ATxmega64A4U-AUR(4)   64K + 4K 2K 4K
+ATxmega64A4U-CU       64K + 4K 2K 4K
+ATxmega64A4U-CUR(4)   64K + 4K 2K 4K
+ATxmega64A4U-M7       64K + 4K 2K 4K
+ATxmega64A4U-M7R(4)   64K + 4K 2K 4K
+ATxmega64A4U-MH       64K + 4K 2K 4K
+ATxmega64A4U-MHR(4)   64K + 4K 2K 4K
+ATxmega32A4U-AN       32K + 4K 1K 4K
+ATxmega32A4U-ANR(4)   32K + 4K 1K 4K
+ATxmega32A4U-AU       32K + 4K 1K 4K
+ATxmega32A4U-AUR(4)   32K + 4K 1K 4K
+ATxmega32A4U-CU       32K + 4K 1K 4K
+ATxmega32A4U-CUR(4)   32K + 4K 1K 4K
+ATxmega32A4U-M7       32K + 4K 1K 4K
+ATxmega32A4U-M7R(4)   32K + 4K 1K 4K
+ATxmega32A4U-MH       32K + 4K 1K 4K
+ATxmega32A4U-MHR(4)   32K + 4K 1K 4K
+ATxmega16A4U-AN       16K + 4K 1K 2K
+ATxmega16A4U-ANR(4)   16K + 4K 1K 2K
+ATxmega16A4U-AU       16K + 4K 1K 2K
+ATxmega16A4U-AUR(4)   16K + 4K 1K 2K
+ATxmega16A4U-CU       16K + 4K 1K 2K
+ATxmega16A4U-CUR(4)   16K + 4K 1K 2k
+ATxmega16A4U-M7       16K + 4K 1K 2K
+ATxmega16A4U-M7R(4)   16K + 4K 1K 2K
+ATxmega16A4U-MH       16K + 4K 1K 2K
+ATxmega16A4U-MHR(4)   16K + 4K 1K 2K
+*/
+
+class AvrDevice_atxmega128a4u : public AvrDevice_atxmega128aubase {
+	public: AvrDevice_atxmega128a4u();
+};
+
+class AvrDevice_atxmega64a4u : public AvrDevice_atxmega128aubase {
+	public: AvrDevice_atxmega64a4u();
+};
+
+class AvrDevice_atxmega32a4u : public AvrDevice_atxmega128aubase {
+	public: AvrDevice_atxmega32a4u();
+};
+
+class AvrDevice_atxmega16a4u : public AvrDevice_atxmega128aubase {
+	public: AvrDevice_atxmega16a4u();
+};
+
+#endif // ATXMEGA128AUBASE
diff --git a/include/avrdevice.h b/include/avrdevice.h
index 21c0111..7f5dfd5 100644
--- a/include/avrdevice.h
+++ b/include/avrdevice.h
@@ -102,6 +102,9 @@ class AvrDevice: public SimulationMember, public TraceValueRegister {
         HWEeprom *eeprom;
         Data *data;  ///< a hack for symbol look-up
         HWIrqSystem *irqSystem;
+        AddressExtensionRegister *rampd; //!< RAMPD address extension register
+        AddressExtensionRegister *rampx; //!< RAMPX address extension register
+        AddressExtensionRegister *rampy; //!< RAMPY address extension register
         AddressExtensionRegister *rampz; //!< RAMPZ address extension register
         AddressExtensionRegister *eind; //!< EIND address extension register
         bool abortOnInvalidAccess; //!< Flag, that simulation abort if an invalid access occured, default is false
diff --git a/include/decoder.h b/include/decoder.h
index ca78a9b..cbce0d1 100644
--- a/include/decoder.h
+++ b/include/decoder.h
@@ -2075,8 +2075,114 @@ class avr_op_BREAK: public DecodedInstruction
         int Trace();
 };
 
+class avr_op_DES: public DecodedInstruction
+{
+  /*
+   * Data Encryption Standard
+   *
+   * Opcode     : 0100 0100 KKKK 1011
+   * Usage      : DES K
+   * Operation  : If H = 0 then Encrypt round (R7-R0, R15-R8, K)
+   *              If H = 1 thenDecrypt round (R7-R0, R15-R8, K)
+   * Flags      : None
+   * Num Clocks : 1
+   */
+  protected:
+     unsigned char K;
+
+  public:
+    avr_op_DES(word opcode, AvrDevice *c);
+    int operator()();
+    int Trace();
+};
+
+
+class avr_op_XCH: public DecodedInstruction
+{
+  /*
+   * Exchange
+   *
+   * Opcode     : 1001 001r rrrr 0100
+   * Usage      : XCH Z,Rd
+   * Operation  : (Z) <- Rd, Rd <- (Z)
+   * Flags      : None
+   * Num Clocks : 2
+   */
+
+  protected:
+    unsigned char R1;
+
+  public:
+    avr_op_XCH(word opcode, AvrDevice *c);
+    int operator()();
+    int Trace();
+};
+
+class avr_op_LAS: public DecodedInstruction
+{
+  /*
+   * Load and Set
+   *
+   * Opcode     : 1001 001r rrrr 0101
+   * Usage      : LAS Z,Rd
+   * Operation  : (Z) <- Rd v (Z), Rd <- (Z)
+   * Flags      : None
+   * Num Clocks : 2
+   */
+
+  protected:
+    unsigned char R1;
+
+  public:
+    avr_op_LAS(word opcode, AvrDevice *c);
+    int operator()();
+    int Trace();
+};
+
+class avr_op_LAC: public DecodedInstruction
+{
+  /*
+   * Load and Clear
+   *
+   * Opcode     : 1001 001r rrrr 0110
+   * Usage      : LAC Z,Rd
+   * Operation  : (Z) <- ($FF -Rd) . (Z), Rd <- (Z)
+   * Flags      : None
+   * Num Clocks : 2
+   */
+
+  protected:
+    unsigned char R1;
+
+  public:
+    avr_op_LAC(word opcode, AvrDevice *c);
+    int operator()();
+    int Trace();
+};
+
+class avr_op_LAT: public DecodedInstruction
+{
+  /*
+   * Load and Toggle
+   *
+   * Opcode     : 1001 001r rrrr 0111
+   * Usage      : LAT Z,Rd
+   * Operation  : (Z) <- Rd ^ (Z), Rd <- (Z)
+   * Flags      : None
+   * Num Clocks : 2
+   */
+
+  protected:
+    unsigned char R1;
+
+  public:
+    avr_op_LAT(word opcode, AvrDevice *c);
+    int operator()();
+    int Trace();
+};
+
 class avr_op_ILLEGAL: public DecodedInstruction
-{ 
+{
     //illegal instruction
 
     public:
diff --git a/include/flashprog.h b/include/flashprog.h
index 595358c..ee8d571 100644
--- a/include/flashprog.h
+++ b/include/flashprog.h
@@ -101,7 +101,7 @@ class AvrFuses {
 
     private:
         int fuseBitsSize;       //!< count of bits in fuses
-        unsigned long fuseBits; //!< fuse data
+        unsigned long long fuseBits; //!< fuse data
         unsigned int nrwwAddr;  //!< start address NRWW section
         unsigned int nrwwSize;  //!< size of NRWW section in byte
         int bitPosBOOTSZ;       //!< bit position BOOTSZ fuses (2 Bit) in fuseBits
@@ -116,7 +116,7 @@ class AvrFuses {
 
         AvrFuses(void);
         //! Configure fuses
-        void SetFuseConfiguration(int size, unsigned long defvalue);
+        void SetFuseConfiguration(int size, unsigned long long defvalue);
         //! Initialize fuses from elf, checks proper size
         bool LoadFuses(const unsigned char *buffer, int size);
         //! Get fuse byte by index
diff --git a/include/hwnvm.h b/include/hwnvm.h
new file mode 100644
index 0000000..e3fe2d4
--- /dev/null
+++ b/include/hwnvm.h
@@ -0,0 +1,131 @@
+/*
+ ****************************************************************************
+ *
+ * simulavr - A simulator for the Atmel AVR family of microcontrollers.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ ****************************************************************************
+ *
+ *  $Id$
+ */
+
+#ifndef HWNVM_H
+#define HWNVM_H
+
+#include "rwmem.h"
+#include "hardware.h"
+#include "traceval.h"
+#include "avrdevice.h"
+
+// This class emulate an eeprom throught an nvm module. Data can be acceded
+// throught diret addressing, by mapping IO reg or throught NVM command
+// Warning: interrupt not implemented
+// see http://ww1.microchip.com/downloads/en/AppNotes/doc8066.pdf
+class HWNvm : public Hardware, public TraceValueRegister {
+  public:
+    enum Command {
+      // from iox128a1.h
+      NVM_CMD_NO_OPERATION = 0x00,  // Noop/Ordinary LPM
+      NVM_CMD_READ_USER_SIG_ROW = 0x01,  // Read user signature row
+      NVM_CMD_READ_CALIB_ROW = 0x02,  // Read calibration row
+      NVM_CMD_READ_EEPROM = 0x06,  // Read EEPROM
+      NVM_CMD_READ_FUSES = 0x07,  // Read fuse byte
+      NVM_CMD_WRITE_LOCK_BITS = 0x08,  // Write lock bits
+      NVM_CMD_ERASE_USER_SIG_ROW = 0x18,  // Erase user signature row
+      NVM_CMD_WRITE_USER_SIG_ROW = 0x1A, // Write user signature row
+      NVM_CMD_ERASE_APP = 0x20, // Erase Application Section
+      NVM_CMD_ERASE_APP_PAGE = 0x22, // Erase Application Section page
+      NVM_CMD_LOAD_FLASH_BUFFER = 0x23, // Load Flash page buffer
+      NVM_CMD_WRITE_APP_PAGE = 0x24, // Write Application Section page
+      NVM_CMD_ERASE_WRITE_APP_PAGE = 0x25, // Erase-and-write Application Section page
+      NVM_CMD_ERASE_FLASH_BUFFER = 0x26, // Erase/flush Flash page buffer
+      NVM_CMD_ERASE_BOOT_PAGE = 0x2A, // Erase Boot Section page
+      NVM_CMD_WRITE_BOOT_PAGE = 0x2C, // Write Boot Section page
+      NVM_CMD_ERASE_WRITE_BOOT_PAGE = 0x2D, // Erase-and-write Boot Section page
+      NVM_CMD_ERASE_EEPROM = 0x30, // Erase EEPROM
+      NVM_CMD_ERASE_EEPROM_PAGE = 0x32, // Erase EEPROM page
+      NVM_CMD_LOAD_EEPROM_BUFFER = 0x33, // Load EEPROM page buffer
+      NVM_CMD_WRITE_EEPROM_PAGE = 0x34, // Write EEPROM page
+      NVM_CMD_ERASE_WRITE_EEPROM_PAGE = 0x35, // Erase-and-write EEPROM page
+      NVM_CMD_ERASE_EEPROM_BUFFER = 0x36, // Erase/flush EEPROM page buffer
+      NVM_CMD_APP_CRC = 0x38, // Generate Application section CRC
+      NVM_CMD_BOOT_CRC = 0x39, // Generate Boot Section CRC
+      NVM_CMD_FLASH_RANGE_CRC = 0x3A, // Generate Flash Range CRC
+    };
+
+    HWNvm(AvrDevice *core, unsigned int memoryMapSize);
+    virtual ~HWNvm();
+
+    virtual unsigned int CpuCycle();
+    void Reset();
+
+    void SetAddr0(unsigned char);
+    void SetAddr1(unsigned char);
+    void SetAddr2(unsigned char);
+    void SetData0(unsigned char);
+    void SetData1(unsigned char);
+    void SetData2(unsigned char);
+    void SetCmd(unsigned char);
+    void SetCmdEx(unsigned char);
+    void SetCtrlb(unsigned char);
+    void SetIntctrl(unsigned char);
+    void SetStatus(unsigned char);
+    void SetLockbits(unsigned char);
+    void SetCcp(unsigned char);
+
+    unsigned char GetAddr0();
+    unsigned char GetAddr1();
+    unsigned char GetAddr2();
+    unsigned char GetData0();
+    unsigned char GetData1();
+    unsigned char GetData2();
+    unsigned char GetCmd();
+    unsigned char GetStatus();
+    unsigned char GetCtrlb();
+    unsigned char GetIntctrl();
+    unsigned char GetLockbits();
+    unsigned char GetCcp();
+
+    IOReg<HWNvm>
+        addr0_reg, // low
+        addr1_reg, // high
+        addr2_reg, // extended
+        data0_reg, // low
+        data1_reg, // high
+        data2_reg, // extended
+        cmd_reg,
+        ctrla_reg, // CMDEX
+        ctrlb_reg,
+        intctrl_reg,
+        status_reg,
+        lockbits_reg,
+        ccp_reg;
+
+  protected:
+    AvrDevice *m_core;
+
+  private:
+    unsigned m_address;
+    unsigned m_data;
+    unsigned char m_command;
+
+    unsigned char m_ctrlb;
+    unsigned char m_intctrl;
+    unsigned char m_lockbits;
+    unsigned char m_ccp;
+};
+
+#endif // HWEEPROM_NVM_H
diff --git a/include/hwxport.h b/include/hwxport.h
new file mode 100644
index 0000000..91eaf94
--- /dev/null
+++ b/include/hwxport.h
@@ -0,0 +1,81 @@
+/*
+ ****************************************************************************
+ *
+ * simulavr - A simulator for the Atmel AVR family of microcontrollers.
+ * Copyright (C) 2021
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ ****************************************************************************
+ *
+ *  $Id$
+ */
+
+#ifndef HWXPORT
+#define HWXPORT
+
+#include "hardware.h"
+#include "hwport.h"
+#include "pin.h"
+#include "rwmem.h"
+#include "traceval.h"
+
+#include <string>
+
+//! Defines extended Port for atxmega, e.g. a hardware device for GPIO
+/*! Example for use alternateDdr and useAlternateDdr:
+  If the UART Tx will be enabled, the UART set alternateDdr to output,
+  useAlternateDdr to 1 and sets port according to Tx Pin value, thats all :-)
+
+  useAlternatePortIfDdrSet: special case for the OCR outputs, which only be
+  connected to pin if ddr is set to output! */
+class HWxPort: public HWPort {
+    protected:
+      void setDirset(unsigned char value);
+      void setPinBitDirset(bool val, unsigned int bit);
+      void setDirclr(unsigned char value);
+      void setPinBitDirclr(bool val, unsigned int bit);
+      void setDirtgl(unsigned char value);
+      void setPinBitDirtgl(bool val, unsigned int bit);
+      void setOutset(unsigned char value);
+      void setPinBitOutset(bool val, unsigned int bit);
+      void setOutclr(unsigned char value);
+      void setPinBitOutclr(bool val, unsigned int bit);
+      void setOuttgl(unsigned char value);
+      void setPinBitOuttgl(bool val, unsigned int bit);
+      void setInset(unsigned char value);
+      void setPinBitInset(bool val, unsigned int bit);
+      void setInclr(unsigned char value);
+      void setPinBitInclr(bool val, unsigned int bit);
+      void setIntgl(unsigned char value);
+      void setPinBitIntgl(bool val, unsigned int bit);
+
+    public:
+        HWxPort(AvrDevice *core, const std::string &name, int size = 8);
+        ~HWxPort();
+
+        IOReg<HWxPort>
+            // dir_reg is ddr_reg
+            dirset_reg,
+            dirclr_reg,
+            dirtgl_reg,
+            // out_reg is port_reg
+            outset_reg,
+            outclr_reg,
+            outtgl_reg;
+
+};
+
+#endif // HWXPORT
diff --git a/include/rwmem.h b/include/rwmem.h
index d1c9479..a749331 100644
--- a/include/rwmem.h
+++ b/include/rwmem.h
@@ -216,6 +216,45 @@ class RAM : public RWMemoryMember {
         TraceValueCoreRegister *corereg;
 };
 
+//! One byte, in avr eeprom/flash Ram
+/*! Allows clean read and write accesses with external pointer. */
+class MemPtr: public RWMemoryMember {
+
+    public:
+        MemPtr(TraceValueCoreRegister *registry,
+            const std::string &tracename,
+            unsigned char *ptrval,
+            const size_t number,
+            const size_t maxsize);
+
+    protected:
+        unsigned char get() const;
+        void set(unsigned char);
+
+    private:
+        unsigned char *pValue;
+        TraceValueCoreRegister *corereg;
+};
+
+//! Constant memory
+class CstMem: public RWMemoryMember {
+    public:
+        CstMem(TraceValueCoreRegister *registry,
+            const std::string &tracename,
+            unsigned char v,
+            const size_t number,
+            const size_t maxsize);
+
+    protected:
+        unsigned char get() const;
+        void set(unsigned char);
+
+    private:
+        unsigned char value;
+        TraceValueCoreRegister *corereg;
+};
+
+
 //! Memory on which access should be avoided! :-)
 /*! All accesses to this type of memory will produce an error. */
 class InvalidMem : public RWMemoryMember {
@@ -297,16 +336,16 @@ class IOReg: public RWMemoryMember {
         IOReg(TraceValueRegister *registry,
               const std::string &tracename,
               P *_p,
-              getter_t _g=0,
-              setter_t _s=0,
-              getter_bit_t _gb=0,
-              setter_bit_t _sb=0):
+              getter_t _g = nullptr,
+              setter_t _s = nullptr,
+              getter_bit_t _gb = nullptr,
+              setter_bit_t _sb = nullptr):
             RWMemoryMember(registry, tracename),
             p(_p),
-            g(_g),
-            s(_s),
-            gb(_gb),
-            sb(_sb)
+            getValueFuncPtr(_g),
+            setValueFuncPtr(_s),
+            getValueFuncPtrBitwise(_gb),
+            setValueFuncPtrBitwise(_sb)
         {
             // 'undefined state' doesn't really make sense for IO registers 
             if (tv)
@@ -326,14 +365,14 @@ class IOReg: public RWMemoryMember {
 
         /*! bitwise access to IOReg from SBI
           */
-        virtual void set_bit( unsigned int bitaddr ) {
-            if (sb) {
-                (p->*sb)( 1, bitaddr);
+        void set_bit( unsigned int bitaddr ) override {
+            if (setValueFuncPtrBitwise) {
+                (p->*setValueFuncPtrBitwise)( 1, bitaddr);
             } else { // default to byte access
-                if (g && s) {
-                    unsigned char val = (p->*g)();
+                if (getValueFuncPtr && setValueFuncPtr) {
+                    unsigned char val = (p->*getValueFuncPtr)();
                     val|= 1<<bitaddr;
-                    (p->*s)(val);
+                    (p->*setValueFuncPtr)(val);
                 } else {
                     avr_warning("Bitwise access of '%s' is not supported.", tv->name().c_str());
                 }
@@ -342,14 +381,14 @@ class IOReg: public RWMemoryMember {
 
         /*! bitwise access to IOReg from CBI
           */
-        virtual void clear_bit( unsigned int bitaddr ) {
-            if (sb) {
-                (p->*sb)( 0, bitaddr);
+        void clear_bit( unsigned int bitaddr ) override {
+            if (setValueFuncPtrBitwise) {
+                (p->*setValueFuncPtrBitwise)( 0, bitaddr);
             } else { // default to byte access
-                if (g && s) {
-                    unsigned char val = (p->*g)();
+                if (getValueFuncPtr && setValueFuncPtr) {
+                    unsigned char val = (p->*getValueFuncPtr)();
                     val&= ~(1<<bitaddr);
-                    (p->*s)(val);
+                    (p->*setValueFuncPtr)(val);
                 } else {
                     avr_warning("Bitwise access of '%s' is not supported.", tv->name().c_str());
                 }
@@ -358,16 +397,16 @@ class IOReg: public RWMemoryMember {
 
     protected:
         unsigned char get() const {
-            if (g)
-                return (p->*g)();
+            if (getValueFuncPtr)
+                return (p->*getValueFuncPtr)();
             else if (tv) {
                 avr_warning("Reading of '%s' is not supported.", tv->name().c_str());
             }
             return 0;
         }
         void set(unsigned char val) {
-            if (s)
-                (p->*s)(val);
+            if (setValueFuncPtr)
+                (p->*setValueFuncPtr)(val);
             else if (tv) {
                 avr_warning("Writing of '%s' (with %d) is not supported.", tv->name().c_str(), val);
             }
@@ -375,10 +414,10 @@ class IOReg: public RWMemoryMember {
         
     private:
         P *p;
-        getter_t g;
-        setter_t s;
-        getter_bit_t gb;
-        setter_bit_t sb;
+        getter_t getValueFuncPtr;
+        setter_t setValueFuncPtr;
+        getter_bit_t getValueFuncPtrBitwise;
+        setter_bit_t setValueFuncPtrBitwise;
 };
 
 class IOSpecialReg;
diff --git a/include/simulationmember.h b/include/simulationmember.h
index c3cb11a..0bafce6 100644
--- a/include/simulationmember.h
+++ b/include/simulationmember.h
@@ -36,6 +36,7 @@ class SimulationMember {
         virtual ~SimulationMember() { }
         /// Return nonzero if a breakpoint was hit.
         virtual int Step(bool &trueHwStep, SystemClockOffset *timeToNextStepIn_ns=0)=0;
+        virtual SystemClockOffset GetClockFreq() { return -1; }
 };
 
 #endif 
diff --git a/libsim/atxmega128aubase.cpp b/libsim/atxmega128aubase.cpp
new file mode 100644
index 0000000..1675adf
--- /dev/null
+++ b/libsim/atxmega128aubase.cpp
@@ -0,0 +1,734 @@
+ /*
+ ****************************************************************************
+ *
+ * simulavr - A simulator for the Atmel AVR family of microcontrollers.
+ * Copyright (C) 2021
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ ****************************************************************************
+ */
+#include "atxmega128aubase.h"
+
+#include "hardware.h"
+#include "irqsystem.h"
+#include "hwxport.h"
+#include "hwstack.h"
+#include "hwspi.h"
+#include "hweeprom.h"
+#include "hwwado.h"
+#include "hwsreg.h"
+#include "rwmem.h"
+
+#include "avrfactory.h"
+
+#include <list>
+
+AVR_REGISTER(atxmega128a1, AvrDevice_atxmega128a1);
+AVR_REGISTER(atxmega64a1, AvrDevice_atxmega64a1);
+AVR_REGISTER(atxmega128a4u, AvrDevice_atxmega128a4u);
+AVR_REGISTER(atxmega64a4u, AvrDevice_atxmega64a4u);
+AVR_REGISTER(atxmega32a4u, AvrDevice_atxmega32a4u);
+AVR_REGISTER(atxmega16a4u, AvrDevice_atxmega16a4u);
+
+#define IO_OFFSET 0x20
+
+// A1U
+AvrDevice_atxmega128a1::AvrDevice_atxmega128a1():
+  AvrDevice_atxmega128aubase(128 * 1024, 2 * 1024, 8 * 1024, 0x10000)
+{ }
+
+AvrDevice_atxmega64a1::AvrDevice_atxmega64a1():
+  AvrDevice_atxmega128aubase(64 * 1024, 2 * 1024, 4 * 1024, 0x10000)
+{ }
+
+// A4U
+AvrDevice_atxmega128a4u::AvrDevice_atxmega128a4u():
+  AvrDevice_atxmega128aubase(128 * 1024, 2 * 1024, 8 * 1024, 0x10000)
+{ }
+
+AvrDevice_atxmega64a4u::AvrDevice_atxmega64a4u():
+  AvrDevice_atxmega128aubase(64 * 1024, 2 * 1024, 4 * 1024, 0x8000)
+{ }
+
+AvrDevice_atxmega32a4u::AvrDevice_atxmega32a4u():
+  AvrDevice_atxmega128aubase(32 * 1024, 1 * 1024, 4 * 1024, 0x4000)
+{ }
+
+AvrDevice_atxmega16a4u::AvrDevice_atxmega16a4u():
+  AvrDevice_atxmega128aubase(16 * 1024, 1 * 1024, 2 * 1024, 0x2000)
+{ }
+
+AvrDevice_atxmega128aubase::~AvrDevice_atxmega128aubase() {
+
+  // for (unsigned int i = 0; i < sizeof(adca) / sizeof(adca[0]); i++) {
+  //   delete adca[i];
+  // }
+  // for (unsigned int i = 0; i < sizeof(adcb) / sizeof(adcb[0]); i++) {
+  //   delete adcb[i];
+  // }
+  // delete aref;
+  // delete admux;
+  delete rampz;
+  delete rampy;
+  delete rampx;
+  delete rampd;
+  delete nvm;
+  delete stack;
+  delete eeprom;
+  delete irqSystem;
+  delete spmRegister;
+  for (std::list<RAM*>::iterator it = ioMem.begin(); it != ioMem.end(); it++) {
+    delete *it;
+  }
+}
+
+AvrDevice_atxmega128aubase::AvrDevice_atxmega128aubase(unsigned flash_bytes,
+                                                       unsigned ee_bytes,
+                                                       unsigned ram_bytes,
+                                                       unsigned nrww_start):
+    // IO take address from 0x0020 to 0x0BC4+0x20 (Call with 0x20 as base). Registers take 32 bytes (0x20)
+    // Define Iosise to 0x1000 in order to have aligned memory with doc.
+    AvrDevice(
+      0x1000, // IO max size (to have invalid ram in this place)
+      0x1000, // internal ram (mapped on eeprom content)
+      ram_bytes, // extended ram
+      flash_bytes,
+      3 // Pc size
+    ),
+    // AvrDevice (0x0BC4, 4096, ram_bytes, flash_bytes),
+    vport0(this, "Virt0"),
+    vport1(this, "Virt1"),
+    vport2(this, "Virt2"),
+    vport3(this, "Virt3"),
+    porta(this, "A"),
+    portb(this, "B"),
+    portc(this, "C"),
+    portd(this, "D"),
+    porte(this, "E"),
+    portf(this, "F"),
+    portg(this, "G"),
+    porth(this, "H"),
+    portj(this, "J"),
+    portk(this, "K"),
+    portl(this, "L"),
+    portm(this, "M"),
+    portn(this, "N"),
+    portp(this, "P"),
+    portq(this, "Q"),
+    portr(this, "R")
+{
+    // Fixme: To be checked
+    spmRegister = new FlashProgramming(this, 128, nrww_start, FlashProgramming::SPM_MEGA_MODE);
+    irqSystem = new HWIrqSystem(this, 2, 35); //2 bytes per vector, 35 vectors
+    eeprom = new HWEeprom(this, NULL, ee_bytes, 0, HWEeprom::DEVMODE_NORMAL);
+    stack = new HWStackSram(this, 16);
+    nvm = new HWNvm(this, ee_bytes);
+    AddToResetList(nvm);
+    // AddToCycleList(nvm);
+
+    rampd = new AddressExtensionRegister(this, "RAMPD", 1);
+    rampx = new AddressExtensionRegister(this, "RAMPX", 1);
+    rampy = new AddressExtensionRegister(this, "RAMPY", 1);
+    rampz = new AddressExtensionRegister(this, "RAMPZ", 1);
+    eind = new AddressExtensionRegister(this, "EIND", 1);
+
+    flagELPMInstructions = true;
+    flagEIJMPInstructions = true;
+    flagXMega = true;
+
+    fuses->SetFuseConfiguration(48, 0xff00ff00ffd0UL);
+    // Fixme: wrong values
+    fuses->SetBootloaderConfig(nrww_start, 0x2000, 24, 23);
+
+    // EEprom memory
+    // Will be deleted by avrDevice (parent)
+    for (unsigned addr = 0x0000; addr < ee_bytes; addr++) {
+      ReplaceMemRegister (IO_OFFSET + 0x1000 + addr, new MemPtr(&coreTraceGroup, "EEPROM_map", &eeprom->myMemory[addr], addr, ee_bytes));
+    };
+    for (unsigned addr = ee_bytes + 0x1000; addr < 0x2000; addr++) {
+      ReplaceMemRegister (IO_OFFSET + addr, new InvalidMem (this, addr));
+    }
+
+    // GPIO
+    changeIoToRam(0x0000, 0x000F);
+    /*rw[IO_OFFSET + 0x0000] = & gpio[0];
+    rw[IO_OFFSET + 0x0001] = & gpio[1];
+    rw[IO_OFFSET + 0x0002] = & gpio[2];
+    rw[IO_OFFSET + 0x0003] = & gpio[3];
+    rw[IO_OFFSET + 0x0004] = & gpio[4];
+    rw[IO_OFFSET + 0x0005] = & gpio[5];
+    rw[IO_OFFSET + 0x0006] = & gpio[6];
+    rw[IO_OFFSET + 0x0007] = & gpio[7];
+    rw[IO_OFFSET + 0x0008] = & gpio[8];
+    rw[IO_OFFSET + 0x0009] = & gpio[9];
+    rw[IO_OFFSET + 0x000A] = & gpio[10];
+    rw[IO_OFFSET + 0x000B] = & gpio[11];
+    rw[IO_OFFSET + 0x000C] = & gpio[12];
+    rw[IO_OFFSET + 0x000D] = & gpio[13];
+    rw[IO_OFFSET + 0x000E] = & gpio[14];
+    rw[IO_OFFSET + 0x000F] = & gpio[15]; */
+
+    // Virtual port
+    rw[IO_OFFSET + 0x0010] = & vport0.ddr_reg;
+    rw[IO_OFFSET + 0x0011] = & vport0.port_reg;
+    rw[IO_OFFSET + 0x0012] = & vport0.pin_reg;
+
+    rw[IO_OFFSET + 0x0014] = & vport1.ddr_reg;
+    rw[IO_OFFSET + 0x0015] = & vport1.port_reg;
+    rw[IO_OFFSET + 0x0016] = & vport1.pin_reg;
+
+    rw[IO_OFFSET + 0x0018] = & vport2.ddr_reg;
+    rw[IO_OFFSET + 0x0019] = & vport2.port_reg;
+    rw[IO_OFFSET + 0x001A] = & vport2.pin_reg;
+
+    rw[IO_OFFSET + 0x001C] = & vport3.ddr_reg;
+    rw[IO_OFFSET + 0x001D] = & vport3.port_reg;
+    rw[IO_OFFSET + 0x001E] = & vport3.ddr_reg;
+
+    // CPU
+    rw[IO_OFFSET + 0x0034] = & nvm->ccp_reg;
+    // rw[IO_OFFSET + 0x0034] = ccp;
+    rw[IO_OFFSET + 0x0038] = & rampd->ext_reg;
+    rw[IO_OFFSET + 0x0039] = & rampx->ext_reg;
+    rw[IO_OFFSET + 0x003A] = & rampy->ext_reg;
+    rw[IO_OFFSET + 0x003B] = & rampz->ext_reg;
+    rw[IO_OFFSET + 0x003C] = & eind->ext_reg;
+    rw[IO_OFFSET + 0x003D] = & ((HWStackSram *)stack)->spl_reg;
+    rw[IO_OFFSET + 0x003E] = & ((HWStackSram *)stack)->sph_reg;
+    rw[IO_OFFSET + 0x003F] = statusRegister;
+
+    // Clock control
+    changeIoToRam(0x0040, 0x0044);
+
+    // Sleep control
+    changeIoToRam(0x0048, 0x0048);
+
+    // Oscillator control
+    changeIoToRam(0x0050, 0x0050);
+    rw[IO_OFFSET + 0x0051] = new CstMem (&coreTraceGroup, "OSC.STATUS", 0x01F , 0, 1);
+    changeIoToRam(0x0052, 0x0056);
+
+    // DFLL for the 32 MHz internal oscillator
+    changeIoToRam(0x0060, 0x0066);
+
+    // DFLL for the 2 MHz RC oscillator
+    changeIoToRam(0x0068, 0x006e);
+
+    // Power reduction
+    changeIoToRam(0x0070, 0x0076);
+
+    // Reset controller
+    changeIoToRam(0x0078, 0x007a);
+
+    // Watch-dog timer
+    rw[IO_OFFSET + 0x0080] = & wado->wdtcr_reg; // incomplete
+    changeIoToRam(0x0081, 0x0083);
+
+    // MCU control
+    changeIoToRam(0x0090, 0x0099);
+
+    // Programmable multilevel interrupt controller
+    changeIoToRam(0x00A0, 0x00A2);
+
+    // Port configuration
+    changeIoToRam(0x00B0, 0x00B0);
+    changeIoToRam(0x00B2, 0x00B6);
+
+    // AES module
+    changeIoToRam(0x00C0, 0x00C4);
+
+    // CRC module
+    changeIoToRam(0x00D0, 0x00D1);
+    changeIoToRam(0x00D3, 0x00D7);
+
+    // Battery backup system
+    changeIoToRam(0x00F0, 0x00F4);
+
+    // DMA controller
+    changeIoToRam(0x0100, 0x0100);
+    changeIoToRam(0x0103, 0x0104);
+    changeIoToRam(0x0106, 0x0107);
+    changeIoToRam(0x0110, 0x0116);
+    changeIoToRam(0x0118, 0x011A);
+    changeIoToRam(0x011C, 0x011E);
+    changeIoToRam(0x0120, 0x0126);
+    changeIoToRam(0x0128, 0x012A);
+    changeIoToRam(0x012C, 0x012E);
+    changeIoToRam(0x0130, 0x0136);
+    changeIoToRam(0x0138, 0x013A);
+    changeIoToRam(0x013C, 0x013E);
+    changeIoToRam(0x0140, 0x0146);
+    changeIoToRam(0x0148, 0x014A);
+    changeIoToRam(0x011C, 0x014E);
+
+    // Event system
+    changeIoToRam(0x0180, 0x0191);
+
+    // Non volatile memory controller
+    rw[IO_OFFSET + 0x01C0] = & nvm->addr0_reg; // low
+    rw[IO_OFFSET + 0x01C1] = & nvm->addr1_reg; // high
+    rw[IO_OFFSET + 0x01C2] = & nvm->addr2_reg; // extended
+    rw[IO_OFFSET + 0x01C4] = & nvm->data0_reg; // low
+    rw[IO_OFFSET + 0x01C5] = & nvm->data1_reg; // high
+    rw[IO_OFFSET + 0x01C6] = & nvm->data2_reg; // extended
+    rw[IO_OFFSET + 0x01CA] = & nvm->cmd_reg;
+    rw[IO_OFFSET + 0x01CB] = & nvm->ctrla_reg;
+    rw[IO_OFFSET + 0x01CC] = & nvm->ctrlb_reg;
+    rw[IO_OFFSET + 0x01CD] = & nvm->intctrl_reg;
+    rw[IO_OFFSET + 0x01CE] = & nvm->lockbits_reg;
+    rw[IO_OFFSET + 0x01CF] = & nvm->status_reg;
+    rw[IO_OFFSET + 0x01D0] = & nvm->lockbits_reg;
+
+    // Analog to digital converter on port A
+    changeIoToRam(0x0200, 0x0206);
+
+    // Analog to digital converter on port B
+    changeIoToRam(0x0240, 0x0246);
+
+    // Digital to analog converter on port A
+    changeIoToRam(0x0300, 0x0304);
+    changeIoToRam(0x0305, 0x0305);
+    changeIoToRam(0x0308, 0x030B);
+    changeIoToRam(0x0318, 0x031B);
+
+    // Digital to analog converter on port B
+    changeIoToRam(0x0320, 0x0324);
+    changeIoToRam(0x0325, 0x0325);
+    changeIoToRam(0x0328, 0x032B);
+    changeIoToRam(0x0338, 0x033B);
+
+    // Analog comparator pair on port A
+    changeIoToRam(0x0380, 0x0389);
+
+    // Analog comparator pair on port B
+    changeIoToRam(0x0390, 0x0399);
+
+    // Real time counter
+    changeIoToRam(0x0400, 0x0404);
+    changeIoToRam(0x0408, 0x040D);
+
+    // 32-bit Real time counter
+    changeIoToRam(0x0420, 0x042F);
+
+    // External bus interface
+    changeIoToRam(0x0440, 0x0441);
+    changeIoToRam(0x0444, 0x0449);
+    changeIoToRam(0x0450, 0x045C);
+
+    // Two wire interface on port C
+    changeIoToRam(0x0480, 0x048D);
+
+    // Two wire interface on port D
+    changeIoToRam(0x0490, 0x049D);
+
+    // Two wire interface on port E
+    changeIoToRam(0x04A0, 0x04AD);
+
+    // Two wire interface on port F
+    changeIoToRam(0x04B0, 0x04BD);
+
+    // USB device
+    changeIoToRam(0x04C0, 0x04CD);
+    changeIoToRam(0x04FA, 0x04FB);
+
+    // Port A
+    rw[IO_OFFSET + 0x0600] = & porta.ddr_reg;
+    rw[IO_OFFSET + 0x0601] = & porta.dirset_reg;
+    rw[IO_OFFSET + 0x0602] = & porta.dirclr_reg;
+    rw[IO_OFFSET + 0x0603] = & porta.dirtgl_reg;
+    rw[IO_OFFSET + 0x0604] = & porta.port_reg;
+    rw[IO_OFFSET + 0x0605] = & porta.outset_reg;
+    rw[IO_OFFSET + 0x0606] = & porta.outclr_reg;
+    rw[IO_OFFSET + 0x0607] = & porta.outtgl_reg;
+    rw[IO_OFFSET + 0x0608] = & porta.pin_reg;
+    changeIoToRam (0x0609, 0x060C);
+    changeIoToRam (0x060E, 0x060E);
+    changeIoToRam (0x0610, 0x0617);
+
+    // Port B
+    rw[IO_OFFSET + 0x0620] = & portb.ddr_reg;
+    rw[IO_OFFSET + 0x0621] = & portb.dirset_reg;
+    rw[IO_OFFSET + 0x0622] = & portb.dirclr_reg;
+    rw[IO_OFFSET + 0x0623] = & portb.dirtgl_reg;
+    rw[IO_OFFSET + 0x0624] = & portb.port_reg;
+    rw[IO_OFFSET + 0x0625] = & portb.outset_reg;
+    rw[IO_OFFSET + 0x0626] = & portb.outclr_reg;
+    rw[IO_OFFSET + 0x0627] = & portb.outtgl_reg;
+    rw[IO_OFFSET + 0x0628] = & portb.pin_reg;
+    changeIoToRam (0x0629, 0x062C);
+    changeIoToRam (0x062E, 0x062E);
+    changeIoToRam (0x0630, 0x0637);
+
+    // Port C
+    rw[IO_OFFSET + 0x0640] = & portc.ddr_reg;
+    rw[IO_OFFSET + 0x0641] = & portc.dirset_reg;
+    rw[IO_OFFSET + 0x0642] = & portc.dirclr_reg;
+    rw[IO_OFFSET + 0x0643] = & portc.dirtgl_reg;
+    rw[IO_OFFSET + 0x0644] = & portc.port_reg;
+    rw[IO_OFFSET + 0x0645] = & portc.outset_reg;
+    rw[IO_OFFSET + 0x0646] = & portc.outclr_reg;
+    rw[IO_OFFSET + 0x0647] = & portc.outtgl_reg;
+    rw[IO_OFFSET + 0x0648] = & portc.pin_reg;
+    changeIoToRam (0x0649, 0x064C);
+    changeIoToRam (0x064E, 0x064E);
+    changeIoToRam (0x0650, 0x0657);
+
+    // Port D
+    rw[IO_OFFSET + 0x0660] = & portd.ddr_reg;
+    rw[IO_OFFSET + 0x0661] = & portd.dirset_reg;
+    rw[IO_OFFSET + 0x0662] = & portd.dirclr_reg;
+    rw[IO_OFFSET + 0x0663] = & portd.dirtgl_reg;
+    rw[IO_OFFSET + 0x0664] = & portd.port_reg;
+    rw[IO_OFFSET + 0x0665] = & portd.outset_reg;
+    rw[IO_OFFSET + 0x0666] = & portd.outclr_reg;
+    rw[IO_OFFSET + 0x0667] = & portd.outtgl_reg;
+    rw[IO_OFFSET + 0x0668] = & portd.pin_reg;
+    changeIoToRam (0x0669, 0x066C);
+    changeIoToRam (0x066E, 0x066E);
+    changeIoToRam (0x0670, 0x0677);
+
+    // Port E
+    rw[IO_OFFSET + 0x0680] = & porte.ddr_reg;
+    rw[IO_OFFSET + 0x0681] = & porte.dirset_reg;
+    rw[IO_OFFSET + 0x0682] = & porte.dirclr_reg;
+    rw[IO_OFFSET + 0x0683] = & porte.dirtgl_reg;
+    rw[IO_OFFSET + 0x0684] = & porte.port_reg;
+    rw[IO_OFFSET + 0x0685] = & porte.outset_reg;
+    rw[IO_OFFSET + 0x0686] = & porte.outclr_reg;
+    rw[IO_OFFSET + 0x0687] = & porte.outtgl_reg;
+    rw[IO_OFFSET + 0x0688] = & porte.pin_reg;
+    changeIoToRam (0x0689, 0x068C);
+    changeIoToRam (0x068E, 0x068E);
+    changeIoToRam (0x0690, 0x0697);
+
+    // Port F
+    rw[IO_OFFSET + 0x06A0] = & portf.ddr_reg;
+    rw[IO_OFFSET + 0x06A1] = & portf.dirset_reg;
+    rw[IO_OFFSET + 0x06A2] = & portf.dirclr_reg;
+    rw[IO_OFFSET + 0x06A3] = & portf.dirtgl_reg;
+    rw[IO_OFFSET + 0x06A4] = & portf.port_reg;
+    rw[IO_OFFSET + 0x06A5] = & portf.outset_reg;
+    rw[IO_OFFSET + 0x06A6] = & portf.outclr_reg;
+    rw[IO_OFFSET + 0x06A7] = & portf.outtgl_reg;
+    rw[IO_OFFSET + 0x06A8] = & portf.pin_reg;
+    changeIoToRam (0x06A9, 0x06AC);
+    changeIoToRam (0x06AE, 0x06AE);
+    changeIoToRam (0x06B0, 0x06B7);
+
+    // not in doc
+    // Port G
+    rw[IO_OFFSET + 0x06C0] = & portg.ddr_reg;
+    rw[IO_OFFSET + 0x06C1] = & portg.dirset_reg;
+    rw[IO_OFFSET + 0x06C2] = & portg.dirclr_reg;
+    rw[IO_OFFSET + 0x06C3] = & portg.dirtgl_reg;
+    rw[IO_OFFSET + 0x06C4] = & portg.port_reg;
+    rw[IO_OFFSET + 0x06C5] = & portg.outset_reg;
+    rw[IO_OFFSET + 0x06C6] = & portg.outclr_reg;
+    rw[IO_OFFSET + 0x06C7] = & portg.outtgl_reg;
+    rw[IO_OFFSET + 0x06C8] = & portg.pin_reg;
+    changeIoToRam (0x06C9, 0x06CC);
+    changeIoToRam (0x06CE, 0x06CE);
+    changeIoToRam (0x06D0, 0x06D7);
+
+    // Port H
+    rw[IO_OFFSET + 0x06E0] = & porth.ddr_reg;
+    rw[IO_OFFSET + 0x06E1] = & porth.dirset_reg;
+    rw[IO_OFFSET + 0x06E2] = & porth.dirclr_reg;
+    rw[IO_OFFSET + 0x06E3] = & porth.dirtgl_reg;
+    rw[IO_OFFSET + 0x06E4] = & porth.port_reg;
+    rw[IO_OFFSET + 0x06E5] = & porth.outset_reg;
+    rw[IO_OFFSET + 0x06E6] = & porth.outclr_reg;
+    rw[IO_OFFSET + 0x06E7] = & porth.outtgl_reg;
+    rw[IO_OFFSET + 0x06E8] = & porth.pin_reg;
+    changeIoToRam (0x06E9, 0x06EC);
+    changeIoToRam (0x06EE, 0x06EE);
+    changeIoToRam (0x06F0, 0x06F7);
+
+    // Port J
+    rw[IO_OFFSET + 0x0700] = & portj.ddr_reg;
+    rw[IO_OFFSET + 0x0701] = & portj.dirset_reg;
+    rw[IO_OFFSET + 0x0702] = & portj.dirclr_reg;
+    rw[IO_OFFSET + 0x0703] = & portj.dirtgl_reg;
+    rw[IO_OFFSET + 0x0704] = & portj.port_reg;
+    rw[IO_OFFSET + 0x0705] = & portj.outset_reg;
+    rw[IO_OFFSET + 0x0706] = & portj.outclr_reg;
+    rw[IO_OFFSET + 0x0707] = & portj.outtgl_reg;
+    rw[IO_OFFSET + 0x0708] = & portj.pin_reg;
+    changeIoToRam (0x0709, 0x070D);
+    changeIoToRam (0x070E, 0x070F);
+    changeIoToRam (0x0710, 0x0717);
+
+    // Port K
+    rw[IO_OFFSET + 0x0720] = & portk.ddr_reg;
+    rw[IO_OFFSET + 0x0721] = & portk.dirset_reg;
+    rw[IO_OFFSET + 0x0722] = & portk.dirclr_reg;
+    rw[IO_OFFSET + 0x0723] = & portk.dirtgl_reg;
+    rw[IO_OFFSET + 0x0724] = & portk.port_reg;
+    rw[IO_OFFSET + 0x0725] = & portk.outset_reg;
+    rw[IO_OFFSET + 0x0726] = & portk.outclr_reg;
+    rw[IO_OFFSET + 0x0727] = & portk.outtgl_reg;
+    rw[IO_OFFSET + 0x0728] = & portk.pin_reg;
+    changeIoToRam (0x0729, 0x072D);
+    changeIoToRam (0x072E, 0x072F);
+    changeIoToRam (0x0730, 0x0737);
+
+    // Port L
+    // not in doc
+    rw[IO_OFFSET + 0x0740] = & portl.ddr_reg;
+    rw[IO_OFFSET + 0x0741] = & portl.dirset_reg;
+    rw[IO_OFFSET + 0x0742] = & portl.dirclr_reg;
+    rw[IO_OFFSET + 0x0743] = & portl.dirtgl_reg;
+    rw[IO_OFFSET + 0x0744] = & portl.port_reg;
+    rw[IO_OFFSET + 0x0745] = & portl.outset_reg;
+    rw[IO_OFFSET + 0x0746] = & portl.outclr_reg;
+    rw[IO_OFFSET + 0x0747] = & portl.outtgl_reg;
+    rw[IO_OFFSET + 0x0748] = & portl.pin_reg;
+    changeIoToRam (0x0749, 0x074D);
+    changeIoToRam (0x074E, 0x074F);
+    changeIoToRam (0x0750, 0x0757);
+
+    // Port M
+    // not in doc
+    rw[IO_OFFSET + 0x0760] = & portm.ddr_reg;
+    rw[IO_OFFSET + 0x0761] = & portm.dirset_reg;
+    rw[IO_OFFSET + 0x0762] = & portm.dirclr_reg;
+    rw[IO_OFFSET + 0x0763] = & portm.dirtgl_reg;
+    rw[IO_OFFSET + 0x0764] = & portm.port_reg;
+    rw[IO_OFFSET + 0x0765] = & portm.outset_reg;
+    rw[IO_OFFSET + 0x0766] = & portm.outclr_reg;
+    rw[IO_OFFSET + 0x0767] = & portm.outtgl_reg;
+    rw[IO_OFFSET + 0x0768] = & portm.pin_reg;
+    changeIoToRam (0x0769, 0x076D);
+    changeIoToRam (0x076E, 0x076F);
+    changeIoToRam (0x0770, 0x0777);
+
+    // Port N
+    // not in doc
+    rw[IO_OFFSET + 0x0780] = & portn.ddr_reg;
+    rw[IO_OFFSET + 0x0781] = & portn.dirset_reg;
+    rw[IO_OFFSET + 0x0782] = & portn.dirclr_reg;
+    rw[IO_OFFSET + 0x0783] = & portn.dirtgl_reg;
+    rw[IO_OFFSET + 0x0784] = & portn.port_reg;
+    rw[IO_OFFSET + 0x0785] = & portn.outset_reg;
+    rw[IO_OFFSET + 0x0786] = & portn.outclr_reg;
+    rw[IO_OFFSET + 0x0787] = & portn.outtgl_reg;
+    rw[IO_OFFSET + 0x0788] = & portn.pin_reg;
+    changeIoToRam (0x0789, 0x078D);
+    changeIoToRam (0x078E, 0x078F);
+    changeIoToRam (0x0790, 0x0797);
+
+    // Port P
+    // not in doc
+    rw[IO_OFFSET + 0x07A0] = & portp.ddr_reg;
+    rw[IO_OFFSET + 0x07A1] = & portp.dirset_reg;
+    rw[IO_OFFSET + 0x07A2] = & portp.dirclr_reg;
+    rw[IO_OFFSET + 0x07A3] = & portp.dirtgl_reg;
+    rw[IO_OFFSET + 0x07A4] = & portp.port_reg;
+    rw[IO_OFFSET + 0x07A5] = & portp.outset_reg;
+    rw[IO_OFFSET + 0x07A6] = & portp.outclr_reg;
+    rw[IO_OFFSET + 0x07A7] = & portp.outtgl_reg;
+    rw[IO_OFFSET + 0x07A8] = & portp.pin_reg;
+    changeIoToRam (0x07A9, 0x07AD);
+    changeIoToRam (0x07AE, 0x07AF);
+    changeIoToRam (0x07B0, 0x07B7);
+
+    // Port Q
+    rw[IO_OFFSET + 0x07C0] = & portq.ddr_reg;
+    rw[IO_OFFSET + 0x07C1] = & portq.dirset_reg;
+    rw[IO_OFFSET + 0x07C2] = & portq.dirclr_reg;
+    rw[IO_OFFSET + 0x07C3] = & portq.dirtgl_reg;
+    rw[IO_OFFSET + 0x07C4] = & portq.port_reg;
+    rw[IO_OFFSET + 0x07C5] = & portq.outset_reg;
+    rw[IO_OFFSET + 0x07C6] = & portq.outclr_reg;
+    rw[IO_OFFSET + 0x07C7] = & portq.outtgl_reg;
+    rw[IO_OFFSET + 0x07C8] = & portq.pin_reg;
+    changeIoToRam (0x07C9, 0x07CD);
+    changeIoToRam (0x07CE, 0x07CF);
+    changeIoToRam (0x07D0, 0x07D7);
+
+    // Port R
+    rw[IO_OFFSET + 0x07E0] = & portr.ddr_reg;
+    rw[IO_OFFSET + 0x07E1] = & portr.dirset_reg;
+    rw[IO_OFFSET + 0x07E2] = & portr.dirclr_reg;
+    rw[IO_OFFSET + 0x07E3] = & portr.dirtgl_reg;
+    rw[IO_OFFSET + 0x07E4] = & portr.port_reg;
+    rw[IO_OFFSET + 0x07E5] = & portr.outset_reg;
+    rw[IO_OFFSET + 0x07E6] = & portr.outclr_reg;
+    rw[IO_OFFSET + 0x07E7] = & portr.outtgl_reg;
+    rw[IO_OFFSET + 0x07E8] = & portr.pin_reg;
+    changeIoToRam (0x07E9, 0x07ED);
+    changeIoToRam (0x07EE, 0x07EF);
+    changeIoToRam (0x07F0, 0x07F7);
+
+    // Timer/counter 0 on port C
+    changeIoToRam(0x0800, 0x0804);
+    changeIoToRam(0x0806, 0x080C);
+    changeIoToRam(0x080F, 0x080F);
+    changeIoToRam(0x0820, 0x0821);
+    changeIoToRam(0x0826, 0x082F);
+    changeIoToRam(0x0836, 0x083F);
+
+    // Timer/counter 1 on port C
+    changeIoToRam(0x0840, 0x0844);
+    changeIoToRam(0x0846, 0x084C);
+    changeIoToRam(0x084F, 0x084F);
+    changeIoToRam(0x0860, 0x0861);
+    changeIoToRam(0x0866, 0x086F);
+    changeIoToRam(0x0876, 0x087F);
+
+    // Advanced waveform extension on port C
+    changeIoToRam(0x0880, 0x0880);
+    changeIoToRam(0x0882, 0x0884);
+    changeIoToRam(0x0886, 0x088C);
+
+    // High resolution extension on port C
+    changeIoToRam(0x0890, 0x0890);
+
+    // USART 0 on port C
+    changeIoToRam(0x08A0, 0x08A1);
+    changeIoToRam(0x08A3, 0x08A7);
+
+    // USART 1 on port C
+    changeIoToRam(0x08B0, 0x08B1);
+    changeIoToRam(0x08B3, 0x08B7);
+
+    // Serial peripheral interface on port C
+    changeIoToRam(0x08C0, 0x08C3);
+
+    // Infrared communication module
+    changeIoToRam(0x08F8, 0x08FA);
+
+    // Timer/counter 1 on port D
+    changeIoToRam(0x0900, 0x0904);
+    changeIoToRam(0x0906, 0x090C);
+    changeIoToRam(0x090F, 0x090F);
+    changeIoToRam(0x0920, 0x0921);
+    changeIoToRam(0x0926, 0x092F);
+    changeIoToRam(0x0936, 0x093F);
+
+    // Timer/counter 1 on port D
+    changeIoToRam(0x0900, 0x0904);
+    changeIoToRam(0x0906, 0x090C);
+    changeIoToRam(0x090F, 0x090F);
+    changeIoToRam(0x0920, 0x0921);
+    changeIoToRam(0x0926, 0x092F);
+    changeIoToRam(0x0936, 0x093F);
+
+    // Advanced waveform extension on port D
+    changeIoToRam(0x0980, 0x0980);
+    changeIoToRam(0x0982, 0x0984);
+    changeIoToRam(0x0986, 0x098C);
+
+    // High resolution extension on port D
+    changeIoToRam(0x0990, 0x0990);
+
+    // USART 0 on port D
+    changeIoToRam(0x09A0, 0x09A1);
+    changeIoToRam(0x09A3, 0x09A7);
+
+    // USART 1 on port D
+    changeIoToRam(0x09B0, 0x09B1);
+    changeIoToRam(0x09B3, 0x09B7);
+
+    // Serial peripheral interface on port D
+    changeIoToRam(0x09C0, 0x09C3);
+
+    // Timer/counter 1 on port E
+    changeIoToRam(0x0A00, 0x0A04);
+    changeIoToRam(0x0A06, 0x0A0C);
+    changeIoToRam(0x0A0F, 0x0A0F);
+    changeIoToRam(0x0A20, 0x0A21);
+    changeIoToRam(0x0A26, 0x0A2F);
+    changeIoToRam(0x0A36, 0x0A3F);
+
+    // Timer/counter 1 on port E
+    changeIoToRam(0x0A00, 0x0A04);
+    changeIoToRam(0x0A06, 0x0A0C);
+    changeIoToRam(0x0A0F, 0x0A0F);
+    changeIoToRam(0x0A20, 0x0A21);
+    changeIoToRam(0x0A26, 0x0A2F);
+    changeIoToRam(0x0A36, 0x0A3F);
+
+    // Advanced waveform extension on port E
+    changeIoToRam(0x0A80, 0x0A80);
+    changeIoToRam(0x0A82, 0x0A84);
+    changeIoToRam(0x0A86, 0x0A8C);
+
+    // High resolution extension on port E
+    changeIoToRam(0x0A90, 0x0A90);
+
+    // USART 0 on port E
+    changeIoToRam(0x0AA0, 0x0AA1);
+    changeIoToRam(0x0AA3, 0x0AA7);
+
+    // USART 1 on port E
+    changeIoToRam(0x0AB0, 0x0AB1);
+    changeIoToRam(0x0AB3, 0x0AB7);
+
+    // Serial peripheral interface on port E
+    changeIoToRam(0x0AC0, 0x0AC3);
+
+    // Timer/counter 1 on port F
+    changeIoToRam(0x0B00, 0x0B04);
+    changeIoToRam(0x0B06, 0x0B0C);
+    changeIoToRam(0x0B0F, 0x0B0F);
+    changeIoToRam(0x0B20, 0x0B21);
+    changeIoToRam(0x0B26, 0x0B2F);
+    changeIoToRam(0x0B36, 0x0B3F);
+
+    // Timer/counter 1 on port F
+    changeIoToRam(0x0B00, 0x0B04);
+    changeIoToRam(0x0B06, 0x0B0C);
+    changeIoToRam(0x0B0F, 0x0B0F);
+    changeIoToRam(0x0B20, 0x0B21);
+    changeIoToRam(0x0B26, 0x0B2F);
+    changeIoToRam(0x0B36, 0x0B3F);
+
+    // Advanced waveform extension on port F
+    changeIoToRam(0x0B80, 0x0B80);
+    changeIoToRam(0x0B82, 0x0B84);
+    changeIoToRam(0x0B86, 0x0B8C);
+
+    // High resolution extension on port F
+    changeIoToRam(0x0B90, 0x0B90);
+
+    // USART 0 on port F
+    changeIoToRam(0x0BA0, 0x0BA1);
+    changeIoToRam(0x0BA3, 0x0BA7);
+
+    // USART 1 on port F
+    changeIoToRam(0x0BB0, 0x0BB1);
+    changeIoToRam(0x0BB3, 0x0BB7);
+
+    // Serial peripheral interface on port F
+    changeIoToRam(0x0BC0, 0x0BC3);
+
+    Reset();
+}
+
+// Will properly switch the Io to Ram register
+void AvrDevice_atxmega128aubase::changeIoToRam(unsigned int s_add, unsigned int e_add)
+{
+  RAM *ptr;
+  unsigned nb = ioMem.size();
+  for (; s_add <= e_add; s_add++)
+  {
+    ptr = new RAM(&coreTraceGroup, "IO_RAM", nb, nb + 1);
+    nb++;
+    rw[IO_OFFSET + s_add] = ptr;
+    ioMem.push_front (ptr);
+  }
+}
diff --git a/libsim/avrdevice.cpp b/libsim/avrdevice.cpp
index c0233fa..6225aad 100644
--- a/libsim/avrdevice.cpp
+++ b/libsim/avrdevice.cpp
@@ -137,6 +137,9 @@ AvrDevice::AvrDevice(unsigned int _ioSpaceSize,
     eRamSize(ERamSize),
     devSignature(std::numeric_limits<unsigned int>::max()),
     PC_size(pcSize),
+    rampd(nullptr),
+    rampx(nullptr),
+    rampy(nullptr),
     rampz(nullptr),
     eind(nullptr),
     abortOnInvalidAccess(false),
@@ -383,7 +386,8 @@ int AvrDevice::Step(bool &untilCoreStepFinished, SystemClockOffset *nextStepIn_n
     }
 
     untilCoreStepFinished = !((cpuCycles > 0) || hwWait);
-    dumpManager->cycle();
+    if(trace_on == 1)
+      dumpManager->cycle();
     return (cpuCycles < 0) ? cpuCycles : 0;
 }
 
@@ -410,9 +414,20 @@ void AvrDevice::SetDeviceNameAndSignature(const std::string &name, unsigned int
 }
 
 void AvrDevice::ReplaceIoRegister(unsigned int offset, RWMemoryMember *newMember) {
+  // Compiling the following code '(*((volatile char *)0x20)) = 0xAA;'
+  // with atmega128 give 'ldi r24, 0xAA; out 0x00, r24;'
+  // with atxmega128a1 give 'ldi r24, 0xAA; out 0x20, r24;'
+  // We conclude that 'out' work differently according to the chip
+  if (flagXMega) {
+    if (offset >= ioSpaceSize) // callers do use 0x00 base, not 0x20
+        avr_error("Could not replace register in non existing IoRegisterSpace");
+    rw[offset + registerSpaceSize] = newMember;
+  }
+  else {
     if (offset >= ioSpaceSize + registerSpaceSize)
         avr_error("Could not replace register in non existing IoRegisterSpace");
     rw[offset] = newMember;
+  }
 }
 
 bool AvrDevice::ReplaceMemRegister(unsigned int offset, RWMemoryMember *newMember) {
@@ -444,16 +459,31 @@ void AvrDevice::DebugOnJump()
 }
 
 unsigned char AvrDevice::GetRWMem(unsigned addr) {
+  if (flagXMega) {
+    if(addr + registerSpaceSize >= GetMemTotalSize())
+        return 0;
+    return *(rw[addr + registerSpaceSize]);
+  }
+  else {
     if(addr >= GetMemTotalSize())
         return 0;
     return *(rw[addr]);
+  }
 }
 
 bool AvrDevice::SetRWMem(unsigned addr, unsigned char val) {
+  if (flagXMega) {
+    if(addr + registerSpaceSize >= GetMemTotalSize())
+        return false;
+    *(rw[addr + registerSpaceSize]) = val;
+    return true;
+  }
+  else {
     if(addr >= GetMemTotalSize())
         return false;
     *(rw[addr]) = val;
     return true;
+  }
 }
 
 unsigned char AvrDevice::GetCoreReg(unsigned addr) {
diff --git a/libsim/avrreadelf.cpp b/libsim/avrreadelf.cpp
index 393b815..3dac513 100644
--- a/libsim/avrreadelf.cpp
+++ b/libsim/avrreadelf.cpp
@@ -105,7 +105,7 @@ void ELFLoad(const AvrDevice * core) {
                 } else if(value >= 0x840000 && value < 0x840400) {
                     /* signature space starting from 0x840000, do nothing */;
                 } else
-                    avr_warning("Unknown symbol address range found! (symbol='%s', address=0x%lx)",
+                    avr_warning("Unknown symbol address range found! (symbol='%s', address=0x%llx)",
                                 name.c_str(),
                                 value);
 
@@ -148,7 +148,7 @@ void ELFLoad(const AvrDevice * core) {
             } else if(vma >= 0x840000 && vma < 0x840400) {
                 // read and check signature, if available, space from 0x840000 to 0x840400
                 if(filesize != 3)
-                    avr_error("wrong device signature size in elf file, expected=3, given=%lu",
+                    avr_error("wrong device signature size in elf file, expected=3, given=%llu",
                               filesize);
                 else {
                     unsigned int sig = (((data[2] << 8) + data[1]) << 8) + data[0];
@@ -190,7 +190,7 @@ unsigned int ELFGetSignature(const char *filename) {
             if(vma >= 0x840000 && vma < 0x840400) {
                 // read and check signature, if available, space from 0x840000 to 0x840400
                 if(filesize != 3)
-                    avr_error("wrong device signature size in elf file, expected=3, given=%lu",
+                    avr_error("wrong device signature size in elf file, expected=3, given=%llu",
                               filesize);
                 else {
                     const unsigned char* data = (const unsigned char*)pseg->get_data();
diff --git a/libsim/avrsignature.cpp b/libsim/avrsignature.cpp
index ce4c192..a32342b 100644
--- a/libsim/avrsignature.cpp
+++ b/libsim/avrsignature.cpp
@@ -142,6 +142,10 @@ std::map<unsigned int, std::string> AvrSignatureToNameMap = InitMap<unsigned int
         << std::make_pair<unsigned int, std::string>(0x1e9108, "attiny25")
         << std::make_pair<unsigned int, std::string>(0x1e910b, "attiny24")
         << std::make_pair<unsigned int, std::string>(0x1e920a, "atmega48p")
+        << std::make_pair<unsigned int, std::string>(0x1e9746, "atxmega128a4u")
+        << std::make_pair<unsigned int, std::string>(0x1e9646, "atxmega64a4u")
+        << std::make_pair<unsigned int, std::string>(0x1e9541, "atxmega32a4u")
+        << std::make_pair<unsigned int, std::string>(0x1e9441, "atxmega16a4u")
 // MARK end
 ;
 
@@ -252,6 +256,10 @@ std::map<std::string, unsigned int> AvrNameToSignatureMap = InitMap<std::string,
         << std::make_pair<std::string, unsigned int>("attiny25", 0x1e9108)
         << std::make_pair<std::string, unsigned int>("attiny24", 0x1e910b)
         << std::make_pair<std::string, unsigned int>("atmega48p", 0x1e920a)
+        << std::make_pair<std::string, unsigned int>("atxmega128a4u", 0x1e9746)
+        << std::make_pair<std::string, unsigned int>("atxmega64a4u", 0x1e9646)
+        << std::make_pair<std::string, unsigned int>("atxmega32a4u", 0x1e9541)
+        << std::make_pair<std::string, unsigned int>("atxmega16a4u", 0x1e9441)
 // MARK end
 ;
 
diff --git a/libsim/decoder.cpp b/libsim/decoder.cpp
index 3ea13a6..8000cf4 100644
--- a/libsim/decoder.cpp
+++ b/libsim/decoder.cpp
@@ -773,7 +773,9 @@ avr_op_LDD_Y::avr_op_LDD_Y(word opcode, AvrDevice *c):
 
 int avr_op_LDD_Y::operator()() {
     /* Y is R29:R28 */
-    word Y = core->GetRegY();
+    unsigned Y = core->GetRegY();
+    if (core->rampy && core->flagXMega)
+      Y = (core->rampy->GetRegVal() << 16) | Y;
 
     core->SetCoreReg(Rd, core->GetRWMem(Y + K));
     
@@ -787,7 +789,9 @@ avr_op_LDD_Z::avr_op_LDD_Z(word opcode, AvrDevice *c):
 
 int avr_op_LDD_Z::operator()() {
     /* Z is R31:R30 */
-    word Z = core->GetRegZ();
+    unsigned Z = core->GetRegZ();
+    if (core->rampz && core->flagXMega)
+      Z = (core->rampz->GetRegVal() << 16) | Z;
 
     core->SetCoreReg(Rd, core->GetRWMem(Z + K));
 
@@ -814,8 +818,11 @@ avr_op_LDS::avr_op_LDS(word opcode, AvrDevice *c):
 
 int avr_op_LDS::operator()() {
     /* Get data at k in current data segment and put into Rd */
-    word offset = core->Flash->ReadMemWord((core->PC + 1) * 2);
-    
+    unsigned offset = core->Flash->ReadMemWord((core->PC + 1) * 2);
+    if (core->rampd && core->flagXMega) {
+      offset = (core->rampd->GetRegVal() << 16) | offset;
+    }
+
     core->SetCoreReg(R1, core->GetRWMem(offset));
     core->PC++;
     
@@ -828,7 +835,10 @@ avr_op_LD_X::avr_op_LD_X(word opcode, AvrDevice *c):
 
 int avr_op_LD_X::operator()() {
     /* X is R27:R26 */
-    word X = core->GetRegX();
+    unsigned X = core->GetRegX();
+
+    if (core->rampx && core->flagXMega)
+      X = (core->rampx->GetRegVal() << 16) | X;
 
     core->SetCoreReg(Rd, core->GetRWMem(X));
     
@@ -841,16 +851,22 @@ avr_op_LD_X_decr::avr_op_LD_X_decr(word opcode, AvrDevice *c):
 
 int avr_op_LD_X_decr::operator()() {
     /* X is R27:R26 */
-    word X = core->GetRegX();
+    unsigned X = core->GetRegX();
     if (Rd == 26 || Rd == 27)
         avr_error( "Result of operation is undefined" );
 
+    if (core->rampx && core->flagXMega)
+      X = (core->rampx->GetRegVal() << 16) | X;
+
     /* Perform pre-decrement */
     X--;
     core->SetCoreReg(Rd, core->GetRWMem(X));
     core->SetCoreReg(26, X & 0xff);
     core->SetCoreReg(27, (X >> 8) & 0xff);
 
+    if (core->rampx)
+      core->rampx->SetRegVal((X >> 16) & 0xff);
+
     return core->flagTiny10 ? 3 : 2;
 }
 
@@ -860,16 +876,22 @@ avr_op_LD_X_incr::avr_op_LD_X_incr(word opcode, AvrDevice *c):
 
 int avr_op_LD_X_incr::operator()() {
     /* X is R27:R26 */
-    word X = core->GetRegX();
+    unsigned X = core->GetRegX();
     if (Rd == 26 || Rd == 27)
        avr_error( "Result of operation is undefined" );
 
+    if (core->rampx && core->flagXMega )
+      X = (core->rampx->GetRegVal() << 16) | X;
+
     /* Perform post-increment */
     core->SetCoreReg(Rd, core->GetRWMem(X));
     X++;
     core->SetCoreReg(26, X & 0xff);
     core->SetCoreReg(27, (X >> 8) & 0xff);
 
+    if (core->rampx && core->flagXMega)
+      core->rampx->SetRegVal((X >> 16) & 0xff);
+
     return core->flagXMega ? 1 : 2;
 }
 
@@ -879,16 +901,22 @@ avr_op_LD_Y_decr::avr_op_LD_Y_decr(word opcode, AvrDevice *c):
 
 int avr_op_LD_Y_decr::operator()() {
     /* Y is R29:R28 */
-    word Y = core->GetRegY();
+    unsigned Y = core->GetRegY();
     if (Rd == 28 || Rd == 29)
         avr_error( "Result of operation is undefined" );
 
+    if (core->rampy && core->flagXMega)
+      Y = (core->rampy->GetRegVal() << 16) | Y;
+
     /* Perform pre-decrement */
     Y--;
     core->SetCoreReg(Rd, core->GetRWMem(Y));
     core->SetCoreReg(28, Y & 0xff);
     core->SetCoreReg(29, (Y >> 8) & 0xff);
 
+    if (core->rampy && core->flagXMega)
+      core->rampy->SetRegVal((Y >> 16) & 0xff);
+
     return core->flagTiny10 ? 3 : 2;
 }
 
@@ -898,16 +926,22 @@ avr_op_LD_Y_incr::avr_op_LD_Y_incr(word opcode, AvrDevice *c):
 
 int avr_op_LD_Y_incr::operator()() {
     /* Y is R29:R28 */
-    word Y = core->GetRegY();
+    unsigned Y = core->GetRegY();
     if (Rd == 28 || Rd == 29)
         avr_error( "Result of operation is undefined" );
 
+    if (core->rampy && core->flagXMega)
+      Y = (core->rampy->GetRegVal() << 16) | Y;
+
     /* Perform post-increment */
     core->SetCoreReg(Rd, core->GetRWMem(Y));
     Y++;
     core->SetCoreReg(28, Y & 0xff);
     core->SetCoreReg(29, (Y >> 8) & 0xff);
 
+    if (core->rampy && core->flagXMega)
+      core->rampy->SetRegVal((Y >> 16) & 0xff);
+
     return core->flagXMega ? 1 : 2;
 }
 
@@ -917,16 +951,22 @@ avr_op_LD_Z_incr::avr_op_LD_Z_incr(word opcode, AvrDevice *c):
 
 int avr_op_LD_Z_incr::operator()() {
     /* Z is R31:R30 */
-    word Z = core->GetRegZ();
+    unsigned Z = core->GetRegZ();
     if (Rd == 30 || Rd == 31)
         avr_error( "Result of operation is undefined" );
 
+    if (core->rampz && core->flagXMega)
+      Z = (core->rampz->GetRegVal() << 16) | Z;
+
     /* Perform post-increment */
     core->SetCoreReg(Rd, core->GetRWMem(Z));
     Z++;
     core->SetCoreReg(30, Z & 0xff);
     core->SetCoreReg(31, (Z >> 8) & 0xff);
 
+    if (core->rampz && core->flagXMega)
+      core->rampz->SetRegVal((Z >> 16) & 0xff);
+
     return core->flagXMega ? 1 : 2;
 }
 
@@ -936,16 +976,22 @@ avr_op_LD_Z_decr::avr_op_LD_Z_decr(word opcode, AvrDevice *c):
 
 int avr_op_LD_Z_decr::operator()() {
     /* Z is R31:R30 */
-    word Z = core->GetRegZ();
+    unsigned Z = core->GetRegZ();
     if (Rd == 30 || Rd == 31)
         avr_error( "Result of operation is undefined" );
 
+    if (core->rampz && core->flagXMega)
+      Z = (core->rampz->GetRegVal() << 16) | Z;
+
     /* Perform pre-decrement */
     Z--;
     core->SetCoreReg(Rd, core->GetRWMem(Z));
     core->SetCoreReg(30, Z & 0xff);
     core->SetCoreReg(31, (Z >> 8) & 0xff);
 
+    if (core->rampz && core->flagXMega)
+      core->rampz->SetRegVal((Z >> 16) & 0xff);
+
     return core->flagTiny10 ? 3 : 2;
 }
 
@@ -956,6 +1002,7 @@ avr_op_LPM_Z::avr_op_LPM_Z(word opcode, AvrDevice *c):
 int  avr_op_LPM_Z::operator()() {
     /* Z is R31:R30 */
     word Z = core->GetRegZ();
+    // Do not use RAMPZ
 
     Z ^= 0x0001;
     core->SetCoreReg(Rd , core->Flash->ReadMem(Z));
@@ -969,7 +1016,8 @@ avr_op_LPM::avr_op_LPM(word opcode, AvrDevice *c):
 int avr_op_LPM::operator()() {
     /* Z is R31:R30 */
     word Z = core->GetRegZ();
-    
+    // Do not use RAMPZ
+
     Z ^= 0x0001;
     core->SetCoreReg(0 , core->Flash->ReadMem(Z));
 
@@ -983,6 +1031,7 @@ avr_op_LPM_Z_incr::avr_op_LPM_Z_incr(word opcode, AvrDevice *c):
 int avr_op_LPM_Z_incr::operator()() {
     /* Z is R31:R30 */
     word Z = core->GetRegZ();
+    // Do not use RAMPZ
 
     core->SetCoreReg(Rd , core->Flash->ReadMem(Z ^ 0x0001));
 
@@ -1549,7 +1598,11 @@ avr_op_STS::avr_op_STS(word opcode, AvrDevice *c):
 
 int avr_op_STS::operator()() {
     /* Get data at k in current data segment and put into Rd */
-    word k = core->Flash->ReadMemWord((core->PC + 1) * 2);
+    unsigned k = core->Flash->ReadMemWord((core->PC + 1) * 2);
+
+    if (core->rampd && core->flagXMega) {
+      k = (core->rampd->GetRegVal() << 16) | k;
+    }
 
     core->SetRWMem(k, core->GetCoreReg(R1));
     core->PC++;
@@ -1563,8 +1616,11 @@ avr_op_ST_X::avr_op_ST_X(word opcode, AvrDevice *c):
 
 int avr_op_ST_X::operator()() {
     /* X is R27:R26 */
-    word X = core->GetRegX();
+    unsigned X = core->GetRegX();
     
+    if (core->rampx && core->flagXMega)
+      X = (core->rampx->GetRegVal() << 16) | X;
+
     core->SetRWMem(X, core->GetCoreReg(R1));
 
     return (core->flagXMega || core->flagTiny10) ? 1 : 2;
@@ -1576,17 +1632,23 @@ avr_op_ST_X_decr::avr_op_ST_X_decr(word opcode, AvrDevice *c):
 
 int avr_op_ST_X_decr::operator()() {
     /* X is R27:R26 */
-    word X = core->GetRegX();
+    unsigned X = core->GetRegX();
     if (R1 == 26 || R1 == 27)
         avr_error( "Result of operation is undefined" );
 
+    if (core->rampx && core->flagXMega)
+      X = (core->rampx->GetRegVal() << 16) | X;
+
     /* Perform pre-decrement */
     X--;
     core->SetCoreReg(26, X & 0xff);
     core->SetCoreReg(27, (X >> 8) & 0xff);
     core->SetRWMem(X, core->GetCoreReg(R1));
 
-    return 2;
+    if (core->rampx && core->flagXMega)
+      core->rampx->SetRegVal((X >> 16) & 0xff);
+
+    return (core->flagXMega || core->flagTiny10) ? 1 : 2;
 }
 
 avr_op_ST_X_incr::avr_op_ST_X_incr(word opcode, AvrDevice *c):
@@ -1595,10 +1657,13 @@ avr_op_ST_X_incr::avr_op_ST_X_incr(word opcode, AvrDevice *c):
 
 int avr_op_ST_X_incr::operator()() {
     /* X is R27:R26 */
-    word X = core->GetRegX();
+    unsigned X = core->GetRegX();
     if (R1 == 26 || R1 == 27)
         avr_error( "Result of operation is undefined" );
 
+    if (core->rampx && core->flagXMega)
+      X = (core->rampx->GetRegVal() << 16) | X;
+
     core->SetRWMem(X, core->GetCoreReg(R1));
 
     /* Perform post-increment */
@@ -1606,6 +1671,9 @@ int avr_op_ST_X_incr::operator()() {
     core->SetCoreReg(26, X & 0xff);
     core->SetCoreReg(27, (X >> 8) & 0xff);
 
+    if (core->rampx && core->flagXMega)
+      core->rampx->SetRegVal((X >> 16) & 0xff);
+
     return (core->flagXMega || core->flagTiny10) ? 1 : 2;
 }
 
@@ -1615,16 +1683,22 @@ avr_op_ST_Y_decr::avr_op_ST_Y_decr(word opcode, AvrDevice *c):
 
 int avr_op_ST_Y_decr::operator()() {
     /* Y is R29:R28 */
-    word Y = core->GetRegY();
+    unsigned Y = core->GetRegY();
     if (R1 == 28 || R1 == 29)
         avr_error( "Result of operation is undefined" );
- 
+
+    if (core->rampy && core->flagXMega)
+      Y = (core->rampy->GetRegVal() << 16) | Y;
+
     /* Perform pre-decrement */
     Y--;
     core->SetCoreReg(28, Y & 0xff);
     core->SetCoreReg(29, (Y >> 8) & 0xff);
     core->SetRWMem(Y, core->GetCoreReg(R1));
 
+    if (core->rampy && core->flagXMega)
+      core->rampy->SetRegVal((Y >> 16) & 0xff);
+
     return 2;
 }
 
@@ -1634,17 +1708,22 @@ avr_op_ST_Y_incr::avr_op_ST_Y_incr(word opcode, AvrDevice *c):
 
 int avr_op_ST_Y_incr::operator()() {
     /* Y is R29:R28 */
-    word Y = core->GetRegY();
+    unsigned Y = core->GetRegY();
     if (R1 == 28 || R1 == 29)
         avr_error( "Result of operation is undefined" );
 
-    core->SetRWMem(Y, core->GetCoreReg(R1));
+    if (core->rampy && core->flagXMega)
+      Y = (core->rampy->GetRegVal() << 16) | Y;
 
     /* Perform post-increment */
+    core->SetRWMem(Y, core->GetCoreReg(R1));
     Y++;
     core->SetCoreReg(28, Y & 0xff);
     core->SetCoreReg(29, (Y >> 8) & 0xff);
 
+    if (core->rampy && core->flagXMega)
+      core->rampy->SetRegVal((Y >> 16) & 0xff);
+
     return (core->flagXMega || core->flagTiny10) ? 1 : 2;
 }
 
@@ -1654,9 +1733,12 @@ avr_op_ST_Z_decr::avr_op_ST_Z_decr(word opcode, AvrDevice *c):
 
 int avr_op_ST_Z_decr::operator()() {
     /* Z is R31:R30 */
-    word Z = core->GetRegZ();
+    unsigned Z = core->GetRegZ();
     if (R1 == 30 || R1 == 31)
         avr_error( "Result of operation is undefined" );
+
+    if (core->rampz && core->flagXMega)
+      Z = (core->rampz->GetRegVal() << 16) | Z;
  
     /* Perform pre-decrement */
     Z--;
@@ -1664,6 +1746,9 @@ int avr_op_ST_Z_decr::operator()() {
     core->SetCoreReg(31, (Z >> 8) & 0xff);
     core->SetRWMem(Z, core->GetCoreReg(R1));
 
+    if (core->rampz && core->flagXMega)
+      core->rampz->SetRegVal((Z >> 16) & 0xff);
+
     return 2;
 }
 
@@ -1673,17 +1758,22 @@ avr_op_ST_Z_incr::avr_op_ST_Z_incr(word opcode, AvrDevice *c):
 
 int avr_op_ST_Z_incr::operator()() {
     /* Z is R31:R30 */
-    word Z = core->GetRegZ();
+    unsigned Z = core->GetRegZ();
     if (R1 == 30 || R1 == 31)
         avr_error( "Result of operation is undefined" );
 
-    core->SetRWMem(Z, core->GetCoreReg(R1));
+    if (core->rampz && core->flagXMega)
+      Z = (core->rampz->GetRegVal() << 16) | Z;
 
     /* Perform post-increment */
+    core->SetRWMem(Z, core->GetCoreReg(R1));
     Z++;
     core->SetCoreReg(30, Z & 0xff);
     core->SetCoreReg(31, (Z >> 8) & 0xff);
 
+    if (core->rampz && core->flagXMega)
+      core->rampz->SetRegVal((Z >> 16) & 0xff);
+
     return (core->flagXMega || core->flagTiny10) ? 1 : 2;
 }
 
@@ -1769,6 +1859,81 @@ int avr_op_BREAK::operator()() {
     return BREAK_POINT+1;
 }
 
+avr_op_DES::avr_op_DES(word opcode, AvrDevice *c):
+  DecodedInstruction(c),
+  K(get_rd_4(opcode)) {}
+
+int avr_op_DES::operator()() {
+    // TODO - Data encription standart
+    return 1;
+}
+
+avr_op_XCH::avr_op_XCH(word opcode, AvrDevice *c):
+  DecodedInstruction(c),
+  R1(get_rd_5(opcode)) {}
+
+int avr_op_XCH::operator()() {
+    /* Z is RAMPZ:R31:R30 */
+    unsigned Z = core->GetRegZ();
+    if (core->rampz)
+      Z = (core->rampz->GetRegVal() << 16) | Z;
+
+    unsigned char tmp = core->GetCoreReg(R1);
+    core->SetCoreReg(R1, core->GetRWMem(Z));
+    core->SetRWMem(Z, tmp);
+    return 2;
+}
+
+avr_op_LAC::avr_op_LAC(word opcode, AvrDevice *c):
+  DecodedInstruction(c),
+  R1(get_rd_5(opcode)) {}
+
+int avr_op_LAC::operator()() {
+    /* Z is RAMPZ:R31:R30 */
+    unsigned Z = core->GetRegZ();
+    if (core->rampz)
+      Z = (core->rampz->GetRegVal() << 16) | Z;
+
+    unsigned char tmp_r = core->GetCoreReg(R1);
+    unsigned char tmp_m = core->GetRWMem(Z);
+    core->SetCoreReg(R1, tmp_m);
+    core->SetRWMem(Z, (~tmp_r) & tmp_m);
+    return 2;
+}
+
+avr_op_LAS::avr_op_LAS(word opcode, AvrDevice *c):
+  DecodedInstruction(c),
+  R1(get_rd_5(opcode)) {}
+
+int avr_op_LAS::operator()() {
+    /* Z is RAMPZ:R31:R30 */
+    unsigned Z = core->GetRegZ();
+    if (core->rampz)
+      Z = (core->rampz->GetRegVal() << 16) | Z;
+
+    unsigned char tmp_r = core->GetCoreReg(R1);
+    unsigned char tmp_m = core->GetRWMem(Z);
+    core->SetCoreReg(R1, tmp_m);
+    core->SetRWMem(Z, tmp_r | tmp_m);
+    return 2;
+}
+
+avr_op_LAT::avr_op_LAT(word opcode, AvrDevice *c):
+  DecodedInstruction(c),
+  R1(get_rd_5(opcode)) {}
+
+int avr_op_LAT::operator()() {
+    /* Z is RAMPZ:R31:R30 */
+    unsigned Z = core->GetRegZ();
+    if (core->rampz)
+      Z = (core->rampz->GetRegVal() << 16) | Z;
+    unsigned char tmp_r = core->GetCoreReg(R1);
+    unsigned char tmp_m = core->GetRWMem(Z);
+    core->SetCoreReg(R1, tmp_m);
+    core->SetRWMem(Z, tmp_r ^ tmp_m);
+    return 2;
+}
+
 avr_op_ILLEGAL::avr_op_ILLEGAL(word opcode, AvrDevice *c):
     DecodedInstruction(c) {}
 
@@ -2145,6 +2310,40 @@ DecodedInstruction* lookup_opcode( word opcode, AvrDevice *core )
                                  else
                                      return new avr_op_ILLEGAL(opcode, core);
                              case 0x9402: return new  avr_op_SWAP(opcode, core);        /* 1001 010d dddd 0010 | SWAP */
+
+                             case 0x9204:
+                               if (!core->flagXMega)
+                                 return new avr_op_ILLEGAL(opcode, core);
+                               else
+                                 return new avr_op_XCH(opcode, core);                   /* 1001 010d dddd 0100 | XCH */
+
+                             case 0x9205:
+                               if (!core->flagXMega)
+                                 return new avr_op_ILLEGAL(opcode, core);
+                               else
+                                 return new avr_op_LAS(opcode, core);                   /* 1001 010d dddd 0101 | LAS */
+
+                             case 0x9206:
+                               if (!core->flagXMega)
+                                 return new avr_op_ILLEGAL(opcode, core);
+                               else
+                                 return new avr_op_LAC(opcode, core);                   /* 1001 010d dddd 0110 | LAC */
+
+                             case 0x9207:
+                               if (!core->flagXMega)
+                                 return new avr_op_ILLEGAL(opcode, core);
+                               else
+                                 return new avr_op_LAT(opcode, core);                   /* 1001 010d dddd 0111 | LAT */
+                         }
+
+                         /* opcodes with single 4-bit register (Rd) operand */
+                         decode = opcode & ~(mask_Rd_4);
+                         switch ( decode ) {
+                           case 0x940B:
+                             if (!core->flagXMega)
+                               return new avr_op_ILLEGAL(opcode, core);
+                             else
+                               return new avr_op_DES(opcode, core);                     /* 1001 1000 dddd 1011 | DEC */
                          }
 
                          /* opcodes with a register (Rd) and a constant data (K) as operands */
diff --git a/libsim/decoder_trace.cpp b/libsim/decoder_trace.cpp
index c66d161..e76bddf 100644
--- a/libsim/decoder_trace.cpp
+++ b/libsim/decoder_trace.cpp
@@ -750,6 +750,36 @@ int avr_op_BREAK::Trace() {
     return ret;
 }
 
+int avr_op_DES::Trace() {
+    traceOut << "DES "<< (int)K << " ";
+    int ret = this->operator()();
+    return ret;
+}
+
+int avr_op_XCH::Trace() {
+    traceOut << "XCH Z,R" << (int)R1 << " ";
+    int ret = this->operator()();
+    return ret;
+}
+
+int avr_op_LAS::Trace() {
+    traceOut << "LAS Z,R" << (int)R1 << " ";
+    int ret = this->operator()();
+    return ret;
+}
+
+int avr_op_LAC::Trace() {
+    traceOut << "LAC Z,R" << (int)R1 << " ";
+    int ret = this->operator()();
+    return ret;
+}
+
+int avr_op_LAT::Trace() {
+    traceOut << "LAT Z,R" << (int)R1 << " ";
+    int ret = this->operator()();
+    return ret;
+}
+
 int avr_op_ILLEGAL::Trace() {
     traceOut << "Invalid Instruction! ";
     int ret = this->operator()();
diff --git a/libsim/flashprog.cpp b/libsim/flashprog.cpp
index a3985f5..57ee0a7 100644
--- a/libsim/flashprog.cpp
+++ b/libsim/flashprog.cpp
@@ -231,7 +231,7 @@ void FlashProgramming::SetSpmcr(unsigned char v) {
 
 AvrFuses::AvrFuses(void):
     fuseBitsSize(2),
-    fuseBits(0xfffffffd),
+    fuseBits(0xfffffffffffffffd),
     nrwwAddr(0),
     nrwwSize(0),
     bitPosBOOTSZ(-1),
@@ -242,7 +242,7 @@ AvrFuses::AvrFuses(void):
     // do nothing!
 }
 
-void AvrFuses::SetFuseConfiguration(int size, unsigned long defvalue) {
+void AvrFuses::SetFuseConfiguration(int size, unsigned long long defvalue) {
     fuseBitsSize = size;
     fuseBits = defvalue;
 }
diff --git a/libsim/hwnvm.cpp b/libsim/hwnvm.cpp
new file mode 100644
index 0000000..32c7997
--- /dev/null
+++ b/libsim/hwnvm.cpp
@@ -0,0 +1,436 @@
+/*
+ ****************************************************************************
+ *
+ * simulavr - A simulator for the Atmel AVR family of microcontrollers.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ ****************************************************************************
+ *
+ *  $Id$
+ */
+
+#include "hwnvm.h"
+#include "hweeprom.h"
+#define NVM_MASK 0x00FFFFFF
+
+// #define FLASH_PAGE_SIZE 256
+// #define EEPROM_PAGE_SIZE 32
+
+HWNvm::HWNvm(AvrDevice *_core, unsigned int _memoryMapSize):
+  Hardware(_core),
+  TraceValueRegister(_core, "NVM"),
+  addr0_reg(this, "ADDR0", this,
+          &HWNvm::GetAddr0, &HWNvm::SetAddr0,
+          nullptr, nullptr),
+  addr1_reg(this, "ADDR1", this,
+          &HWNvm::GetAddr1, &HWNvm::SetAddr1,
+          nullptr, nullptr),
+  addr2_reg(this, "ADDR2", this,
+          &HWNvm::GetAddr2, &HWNvm::SetAddr2,
+          nullptr, nullptr),
+  data0_reg(this, "DATA0", this,
+          &HWNvm::GetData0, &HWNvm::SetData0,
+          nullptr, nullptr),
+  data1_reg(this, "DATA1", this,
+          &HWNvm::GetData1, &HWNvm::SetData1,
+          nullptr, nullptr),
+  data2_reg(this, "DATA2", this,
+          &HWNvm::GetData2, &HWNvm::SetData2,
+          nullptr, nullptr),
+  cmd_reg(this, "CMD", this,
+          &HWNvm::GetCmd, &HWNvm::SetCmd,
+          nullptr, nullptr),
+  ctrla_reg(this, "CTRLA", this,
+          nullptr, &HWNvm::SetCmdEx,
+          nullptr, nullptr),
+  ctrlb_reg(this, "CTRLB", this,
+          &HWNvm::GetCtrlb, &HWNvm::SetCtrlb,
+          nullptr, nullptr),
+  intctrl_reg(this, "INTCTRL", this,
+          &HWNvm::GetIntctrl, &HWNvm::SetIntctrl,
+          nullptr, nullptr),
+  status_reg(this, "STATUS", this,
+          &HWNvm::GetStatus, nullptr,
+          nullptr, nullptr),
+  lockbits_reg(this, "LOCKBITS", this,
+          &HWNvm::GetLockbits, &HWNvm::SetLockbits,
+          nullptr, nullptr),
+  ccp_reg(this, "CCP", this,
+          &HWNvm::GetCcp, &HWNvm::SetCcp,
+          nullptr, nullptr),
+  m_core(_core) {
+  Reset();
+}
+
+HWNvm::~HWNvm() {
+}
+
+unsigned int HWNvm::CpuCycle() {
+  return 0;
+}
+
+void HWNvm::Reset() {
+  m_address = 0x000000;
+  m_data = 0x000000;
+  m_command = NVM_CMD_NO_OPERATION;
+
+  m_ctrlb = 0x00;
+  m_intctrl = 0x00;
+  m_lockbits = 0x00;
+  m_ccp = 0;
+}
+
+void HWNvm::SetAddr0(unsigned char val) {
+  m_address = ((m_address & 0x00FFFF00) | (val << 0)) & NVM_MASK;
+  if (m_core->trace_on == 1)
+    traceOut << "NVM_ADDR0=0x" << std::hex << val << std::dec;
+}
+
+void HWNvm::SetAddr1(unsigned char val) {
+  m_address = ((m_address & 0x00FF00FF) | (val << 8)) & NVM_MASK;
+  if (m_core->trace_on == 1)
+    traceOut << "NVM_ADDR1=0x" << std::hex << val << std::dec;
+}
+
+void HWNvm::SetAddr2(unsigned char val) {
+  m_address = ((m_address & 0x0000FFFF) | (val << 16)) & NVM_MASK;
+  if (m_core->trace_on == 1)
+    traceOut << "NVM_ADDR2=0x" << std::hex << val << std::dec;
+}
+
+void HWNvm::SetData0(unsigned char val) {
+  m_data = ((m_data & 0x00FFFF00) | (val << 0)) & NVM_MASK;
+  if (m_core->trace_on == 1)
+    traceOut << "NVM_DATA0=0x" << std::hex << val << std::dec;
+
+  if (m_command == NVM_CMD_LOAD_EEPROM_BUFFER ||
+      m_command == NVM_CMD_LOAD_FLASH_BUFFER) {
+    // set in data 0 will trig load operation
+    SetCmdEx(0x01);
+  }
+}
+
+void HWNvm::SetData1(unsigned char val) {
+  m_data = ((m_data & 0x00FF00FF) | (val << 8)) & NVM_MASK;
+  if (m_core->trace_on == 1)
+    traceOut << "NVM_DATA1=0x" << std::hex << val << std::dec;
+}
+
+void HWNvm::SetData2(unsigned char val) {
+  m_data = ((m_data & 0x0000FFFF) | (val << 16)) & NVM_MASK;
+  if (m_core->trace_on == 1)
+    traceOut << "NVM_DATA2=0x" << std::hex << val << std::dec;
+}
+
+void HWNvm::SetCmd(unsigned char val) {
+  m_command = val;
+  if (m_core->trace_on)
+        traceOut << "NVM_CMD=0x" << std::hex << val << std::dec;
+}
+
+void HWNvm::SetCmdEx(unsigned char val) {
+  // The CMDEX is set to 1, located on bit 0. Do nothing in any other case
+  if (val != 1) {
+    avr_warning("Only set CMDEX is supported. NVM_CTRLA received 0x%02x", val);
+  }
+  if (~val & 1) return;
+  switch (m_command) {
+    case NVM_CMD_NO_OPERATION:
+      // Do nothing
+      break;
+
+    case NVM_CMD_READ_CALIB_ROW:
+      m_data = 0;
+      avr_warning ("Command READ_CALIB_ROW (0x%02x) is not supported.", m_command);
+      break;
+
+    case NVM_CMD_READ_USER_SIG_ROW:
+      m_data = m_core->GetDeviceSignature();
+      break;
+
+    case NVM_CMD_READ_EEPROM:
+      m_data = 0;
+      if (m_core->eeprom) {
+        if (m_address > 0xFFFF) {
+          avr_warning ("Reading eeprom at address 0x%08x is not supported.", m_address);
+        }
+        else {
+          m_core->eeprom->SetEearl((m_address >> 0) & 0xFF);
+          m_core->eeprom->SetEearh((m_address >> 8) & 0xFF);
+          m_core->eeprom->SetEecr(HWEeprom::CTRL_READ);
+          m_data = m_core->eeprom->GetEedr();
+        }
+      }
+      else {
+        avr_warning ("Command READ_EEPROM (0x%02x) is not supported.", m_command);
+      }
+      break;
+
+    case NVM_CMD_READ_FUSES:
+      m_data = 0;
+      if (m_core->fuses) {
+        m_data = m_core->fuses->GetFuseByte(3) |
+                 m_core->fuses->GetFuseByte(2) |
+                 m_core->fuses->GetFuseByte(1) |
+                 m_core->fuses->GetFuseByte(0) ;
+      }
+      else {
+        avr_warning ("Command READ_FUSES (0x%02x) is not supported.", m_command);
+      }
+      break;
+
+    case NVM_CMD_WRITE_LOCK_BITS:
+      if (m_core->lockbits) {
+        m_core->lockbits->SetLockBits(m_data & 0xFF);
+      }
+      else {
+        avr_warning ("Command WRITE_LOCK_BITS (0x%02x) is not supported.", m_command);
+      }
+      break;
+
+    case NVM_CMD_ERASE_USER_SIG_ROW:
+      avr_warning ("Command ERASE_USER_SIG_ROW (0x%02x) is not supported.", m_command);
+      break;
+
+    case NVM_CMD_WRITE_USER_SIG_ROW:
+      avr_warning ("Command WRITE_USER_SIG_ROW (0x%02x) is not supported.", m_command);
+      break;
+
+    case NVM_CMD_ERASE_APP:
+      avr_warning ("Command ERASE_APP (0x%02x) is not supported.", m_command);
+      break;
+
+    case NVM_CMD_ERASE_APP_PAGE:
+      avr_warning ("Command ERASE_APP_PAGE (0x%02x) is not supported.", m_command);
+      break;
+
+    case NVM_CMD_LOAD_FLASH_BUFFER:
+      avr_warning ("Command LOAD_FLASH_BUFFER (0x%02x) is not supported.", m_command);
+      break;
+
+    case NVM_CMD_WRITE_APP_PAGE:
+      avr_warning ("Command WRITE_APP_PAGE (0x%02x) is not supported.", m_command);
+      break;
+
+    case NVM_CMD_ERASE_WRITE_APP_PAGE:
+      avr_warning ("Command ERASE_WRITE_APP_PAGE (0x%02x) is not supported.", m_command);
+      break;
+
+    case NVM_CMD_ERASE_FLASH_BUFFER:
+      avr_warning ("Command ERASE_FLASH_BUFFER (0x%02x) is not supported.", m_command);
+      break;
+
+    case NVM_CMD_ERASE_BOOT_PAGE:
+      avr_warning ("Command ERASE_BOOT_PAGE (0x%02x) is not supported.", m_command);
+      break;
+
+    case NVM_CMD_WRITE_BOOT_PAGE:
+      avr_warning ("Command WRITE_BOOT_PAGE (0x%02x) is not supported.", m_command);
+      break;
+
+    case NVM_CMD_ERASE_WRITE_BOOT_PAGE:
+      avr_warning ("Command ERASE_WRITE_BOOT_PAGE (0x%02x) is not supported.", m_command);
+      break;
+
+    case NVM_CMD_ERASE_EEPROM:
+      if (m_core->eeprom) {
+        for (int i = m_core->eeprom->GetSize() - 1; i >=0; --i) {
+          m_core->eeprom->WriteAtAddress(i, 0xFF);
+        }
+      }
+      else {
+        avr_warning ("Command ERASE_EEPROM (0x%02x) is not supported.", m_command);
+      }
+      break;
+
+    case NVM_CMD_ERASE_EEPROM_PAGE:
+      if (m_core->eeprom) {
+        if (m_address > 0xFFFF) {
+          avr_warning ("Erasing eeprom at address 0x%08x is not supported.", m_address);
+        }
+        else {
+          m_core->eeprom->SetEearl((m_address >> 0) & 0xFF);
+          m_core->eeprom->SetEearh((m_address >> 8) & 0xFF);
+          m_core->eeprom->SetEedr(0xFF);
+          m_core->eeprom->SetEecr(HWEeprom::CTRL_ENABLE);
+          m_core->eeprom->SetEecr(HWEeprom::CTRL_MODE_ERASE | HWEeprom::CTRL_WRITE);
+        }
+      }
+      else {
+        avr_warning ("Command ERASE_EEPROM_PAGE (0x%02x) is not supported.", m_command);
+      }
+      break;
+
+    case NVM_CMD_LOAD_EEPROM_BUFFER:
+      if (m_core->eeprom) {
+        if (m_address > 0xFFFF) {
+          avr_warning ("Writing eeprom at address 0x%08x is not supported.", m_address);
+        }
+        else {
+          m_core->eeprom->SetEearl((m_address >> 0) & 0xFF);
+          m_core->eeprom->SetEearh((m_address >> 8) & 0xFF);
+          m_core->eeprom->SetEedr(m_data & 0xFF);
+        }
+      }
+      else {
+        avr_warning ("Command LOAD_EEPROM_BUFFER (0x%02x) is not supported.", m_command);
+      }
+      break;
+
+    case NVM_CMD_WRITE_EEPROM_PAGE:
+      if (m_core->eeprom) {
+         // m_core->eeprom->WriteAtAddress ((m_core->eeprom->GetEearh() << 8) | (m_core->eeprom->GetEearl() << 0), m_core->eeprom->GetEedr());
+        m_core->eeprom->SetEecr(HWEeprom::CTRL_ENABLE);
+        m_core->eeprom->SetEecr(HWEeprom::CTRL_MODE_WRITE | HWEeprom::CTRL_WRITE);
+      }
+      else {
+        avr_warning ("Command WRITE_EEPROM_PAGE (0x%02x) is not supported.", m_command);
+      }
+      break;
+
+    case NVM_CMD_ERASE_WRITE_EEPROM_PAGE:
+      if (m_core->eeprom) {
+         // m_core->eeprom->WriteAtAddress ((m_core->eeprom->GetEearh() << 8) | (m_core->eeprom->GetEearl() << 0), m_core->eeprom->GetEedr());
+         m_core->eeprom->SetEecr(HWEeprom::CTRL_ENABLE);
+         m_core->eeprom->SetEecr(HWEeprom::CTRL_MODE_WRITE | HWEeprom::CTRL_WRITE);
+      }
+      else {
+        avr_warning ("Command ERASE_WRITE_EEPROM_PAGE (0x%02x) is not supported.", m_command);
+      }
+      break;
+
+    case NVM_CMD_ERASE_EEPROM_BUFFER:
+      if (m_core->eeprom) {
+         // m_core->eeprom->WriteAtAddress ((m_core->eeprom->GetEearh() << 8) | (m_core->eeprom->GetEearl() << 0), m_core->eeprom->GetEedr());
+         m_core->eeprom->SetEecr(HWEeprom::CTRL_ENABLE);
+         m_core->eeprom->SetEecr(HWEeprom::CTRL_MODE_ERASE | HWEeprom::CTRL_WRITE);
+      }
+      else {
+        avr_warning ("Command ERASE_EEPROM_BUFFER (0x%02x) is not supported.", m_command);
+      }
+      break;
+
+    case NVM_CMD_APP_CRC:
+      avr_warning ("Command APP_CRC (0x%02x) is not supported.", m_command);
+      break;
+
+    case NVM_CMD_BOOT_CRC:
+      avr_warning ("Command BOOT_CRC (0x%02x) is not supported.", m_command);
+      break;
+
+    case NVM_CMD_FLASH_RANGE_CRC:
+      avr_warning ("Command FLASH_RANGE_CRC (0x%02x) is not supported.", m_command);
+      break;
+
+    default:
+      avr_warning ("Command %1$d (0x%1$02x) is not supported.", m_command);
+      break;
+  }
+}
+
+void HWNvm::SetCtrlb(unsigned char val) {
+  m_ctrlb = val;
+}
+void HWNvm::SetIntctrl(unsigned char val) {
+  m_intctrl = val;
+}
+void HWNvm::SetLockbits(unsigned char val) {
+  m_lockbits = val;
+}
+void HWNvm::SetCcp(unsigned char val) {
+  m_ccp = val;
+}
+
+unsigned char HWNvm::GetAddr0() {
+  return (m_address >> 0) & 0xFF;
+}
+
+unsigned char HWNvm::GetAddr1() {
+  return (m_address >> 8) & 0xFF;
+}
+
+unsigned char HWNvm::GetAddr2() {
+  return (m_address >> 16) & 0xFF;
+}
+
+unsigned char HWNvm::GetData0() {
+  return (m_data >> 0) & 0xFF;
+}
+
+unsigned char HWNvm::GetData1() {
+  return (m_data >> 8) & 0xFF;
+}
+
+unsigned char HWNvm::GetData2() {
+  return (m_data >> 16) & 0xFF;
+}
+
+unsigned char HWNvm::GetCmd() {
+  return m_command;
+}
+
+unsigned char HWNvm::GetStatus() {
+  const unsigned char eecr = (m_core->eeprom != NULL ? m_core->eeprom->GetEecr() : 0);
+  const unsigned char spmcsr = (m_core->spmRegister != NULL ? m_core->spmRegister->GetSpmcr() : 0);
+  unsigned char status = 0;
+
+  // FLOAD
+  if (spmcsr & (
+     (1 << 1) |  // PGERS: Page Erase
+     (1 << 2))   // PGWRT: Page Write
+  ) {
+    status |= 0x01;
+  }
+
+  // ELOAD
+  if (eecr & (
+      (1 << 0) | // EERE: EEPROM Read Enable
+      (1 << 1))  // EEWE: EEPROM Write Enable
+  ) {
+    status |= 0x02;
+  }
+
+  // FBUSY
+  if (spmcsr & (
+    (1 << 0) | // SPMEN: Store Program Memory Enable
+    (1 << 6))  // RWWSB: Read-While-Write Section Busy
+  ) {
+    status |= 0x40;
+  }
+
+  // NVMBUSY
+  if (status) {
+    status |= 0x80;
+  }
+
+  return status;
+}
+
+unsigned char HWNvm::GetCtrlb() {
+  return m_ctrlb;
+}
+
+unsigned char HWNvm::GetIntctrl() {
+  return m_intctrl;
+}
+
+unsigned char HWNvm::GetLockbits() {
+  return m_lockbits;
+}
+
+unsigned char HWNvm::GetCcp() {
+  return m_ccp;
+}
diff --git a/libsim/hwxport.cpp b/libsim/hwxport.cpp
new file mode 100644
index 0000000..2085af2
--- /dev/null
+++ b/libsim/hwxport.cpp
@@ -0,0 +1,117 @@
+/*
+ ****************************************************************************
+ *
+ * simulavr - A simulator for the Atmel AVR family of microcontrollers.
+ * Copyright (C) 2021
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ ****************************************************************************
+ *
+ *  $Id$
+ */
+
+#include <iostream>
+
+#include "hwxport.h"
+#include "avrdevice.h"
+#include "avrerror.h"
+#include <assert.h>
+
+HWxPort::HWxPort(AvrDevice *core, const std::string &name, int size):
+		HWPort(core, name, false, size),
+    dirset_reg(this, "DIRSET", this,
+            nullptr, &HWxPort::setDirset,
+            nullptr, &HWxPort::setPinBitDirset),
+    dirclr_reg(this, "DIRCLR", this,
+            nullptr, &HWxPort::setDirclr,
+            nullptr, &HWxPort::setPinBitDirclr),
+    dirtgl_reg(this, "DIRTGL", this,
+            nullptr, &HWxPort::setDirtgl,
+            nullptr, &HWxPort::setPinBitDirtgl),
+
+    outset_reg(this, "OUTSET", this,
+            nullptr, &HWxPort::setOutset,
+            nullptr, &HWxPort::setPinBitOutset),
+    outclr_reg(this, "OUTCLR", this,
+            nullptr, &HWxPort::setOutclr,
+            nullptr, &HWxPort::setPinBitOutclr),
+    outtgl_reg(this, "OUTTGL", this,
+            nullptr, &HWxPort::setOuttgl,
+            nullptr, &HWxPort::setPinBitOuttgl)
+
+{
+   // port_reg.tracename = "OUT";
+   // pin_reg.tracename = "IN";
+   // ddr_reg.tracename = "DIR";
+}
+
+HWxPort::~HWxPort() { }
+
+void HWxPort::setDirset(unsigned char value)
+{
+  SetDdr(GetDdr() | value);
+}
+void HWxPort::setPinBitDirset(bool val, unsigned int bit)
+{
+  assert((bit >= 0) && (bit < sizeof(p)/sizeof(p[0])));
+  setDirset(val << bit);
+}
+void HWxPort::setDirclr(unsigned char value)
+{
+  SetDdr(GetDdr() & ~value);
+}
+void HWxPort::setPinBitDirclr(bool val, unsigned int bit)
+{
+  assert((bit >= 0) && (bit < sizeof(p)/sizeof(p[0])));
+  setDirclr(val << bit);
+}
+void HWxPort::setDirtgl(unsigned char value)
+{
+  SetDdr(GetDdr() ^ value);
+}
+void HWxPort::setPinBitDirtgl(bool val, unsigned int bit)
+{
+  assert((bit >= 0) && (bit < sizeof(p)/sizeof(p[0])));
+  setDirtgl((val << bit));
+}
+
+void HWxPort::setOutset(unsigned char value)
+{
+  SetPort(GetPort() | value);
+}
+void HWxPort::setPinBitOutset(bool val, unsigned int bit)
+{
+  assert((bit >= 0) && (bit < sizeof(p)/sizeof(p[0])));
+  setOutset(val << bit);
+}
+void HWxPort::setOutclr(unsigned char value)
+{
+  SetPort(GetPort() & ~value);
+}
+void HWxPort::setPinBitOutclr(bool val, unsigned int bit)
+{
+  assert((bit >= 0) && (bit < sizeof(p)/sizeof(p[0])));
+  setOutclr(val << bit);
+}
+void HWxPort::setOuttgl(unsigned char value)
+{
+  SetPort(GetPort() ^ value);
+}
+void HWxPort::setPinBitOuttgl(bool val, unsigned int bit)
+{
+  assert((bit >= 0) && (bit < sizeof(p)/sizeof(p[0])));
+  setOuttgl(val << bit);
+}
diff --git a/libsim/rwmem.cpp b/libsim/rwmem.cpp
index aec8b06..d6f8565 100644
--- a/libsim/rwmem.cpp
+++ b/libsim/rwmem.cpp
@@ -205,6 +205,42 @@ unsigned char RAM::get() const { return value; }
 
 void RAM::set(unsigned char v) { value=v; }
 
+
+MemPtr::MemPtr(TraceValueCoreRegister *_reg, const std::string &name, unsigned char *ptrvalue, const size_t number, const size_t maxsize) {
+    corereg = _reg;
+    if (ptrvalue == NULL)
+      avr_error("No pointer provided for MemPtr memory");
+    pValue = ptrvalue;
+    if(name.size()) {
+        tv = new TraceValue(8, corereg->GetTraceValuePrefix() + name, number);
+        if(!corereg) {
+            avr_error("registry not initialized for RWMemoryMember '%s'.", name.c_str());
+        }
+        corereg->RegisterTraceSetValue(tv, name, maxsize);
+    } else {
+        tv = NULL;
+    }
+}
+unsigned char MemPtr::get() const { return *pValue; }
+void MemPtr::set(unsigned char v) { *pValue=v; }
+
+CstMem::CstMem(TraceValueCoreRegister *_reg, const std::string &name, unsigned char v, const size_t number, const size_t maxsize) {
+    corereg = _reg;
+    value = v;
+    if(name.size()) {
+        tv = new TraceValue(8, corereg->GetTraceValuePrefix() + name, number);
+        if(!corereg) {
+            avr_error("registry not initialized for CstMem '%s'.", name.c_str());
+        }
+        corereg->RegisterTraceSetValue(tv, name, maxsize);
+    } else {
+        tv = NULL;
+    }
+}
+unsigned char CstMem::get() const { return value; }
+void CstMem::set(unsigned char v) { avr_error("Writing into constant register %s not allowed",  tv->name().c_str()); }
+
+
 InvalidMem::InvalidMem(AvrDevice* _c, int _a):
     RWMemoryMember(),
     core(_c),
diff --git a/libsim/traceval.cpp b/libsim/traceval.cpp
index 2826e1f..a4e028b 100644
--- a/libsim/traceval.cpp
+++ b/libsim/traceval.cpp
@@ -321,6 +321,9 @@ void TraceValueCoreRegister::RegisterTraceSetValue(TraceValue *t, const std::str
         std::pair<std::string*, TraceSet*> v(s, set);
         _tvr_valset.insert(v);
     }
+    else if(set->size() < size) {
+      set->resize(size, NULL);
+    }
     // set TraceValue to set[idx]
     (*set)[t->index()] = t;
 }

Reply via email to