Snap for 6424126 from 1c483ec4ae552bb09d699f74ee93f60291e19042 to rvc-d1-release

Change-Id: I382d07d82c81520ac51e726af1258b1648ad4f84
diff --git a/Android.bp b/Android.bp
index 6f11f53..3c1f7ca 100644
--- a/Android.bp
+++ b/Android.bp
@@ -33,6 +33,7 @@
         "-Wno-switch",
         "-Wno-unused-private-field",
         "-Wno-implicit-fallthrough",
+        "-Wno-constant-logical-operand",
         "-fexceptions",
     ],
     rtti: true,
@@ -44,48 +45,13 @@
     },
 
     srcs: [
-        "decoder/source/etmv3/trc_cmp_cfg_etmv3.cpp",
-        "decoder/source/etmv3/trc_pkt_decode_etmv3.cpp",
-        "decoder/source/etmv3/trc_pkt_elem_etmv3.cpp",
-        "decoder/source/etmv3/trc_pkt_proc_etmv3.cpp",
-        "decoder/source/etmv3/trc_pkt_proc_etmv3_impl.cpp",
-        "decoder/source/etmv4/trc_cmp_cfg_etmv4.cpp",
-        "decoder/source/etmv4/trc_etmv4_stack_elem.cpp",
-        "decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp",
-        "decoder/source/etmv4/trc_pkt_elem_etmv4d.cpp",
-        "decoder/source/etmv4/trc_pkt_elem_etmv4i.cpp",
-        "decoder/source/etmv4/trc_pkt_proc_etmv4.cpp",
-        "decoder/source/etmv4/trc_pkt_proc_etmv4i_impl.cpp",
-        "decoder/source/i_dec/trc_idec_arminst.cpp",
-        "decoder/source/i_dec/trc_i_decode.cpp",
-        "decoder/source/mem_acc/trc_mem_acc_base.cpp",
-        "decoder/source/mem_acc/trc_mem_acc_bufptr.cpp",
-        "decoder/source/mem_acc/trc_mem_acc_cache.cpp",
-        "decoder/source/mem_acc/trc_mem_acc_cb.cpp",
-        "decoder/source/mem_acc/trc_mem_acc_file.cpp",
-        "decoder/source/mem_acc/trc_mem_acc_mapper.cpp",
-        "decoder/source/ocsd_code_follower.cpp",
-        "decoder/source/ocsd_dcd_tree.cpp",
-        "decoder/source/ocsd_error.cpp",
-        "decoder/source/ocsd_error_logger.cpp",
-        "decoder/source/ocsd_gen_elem_list.cpp",
-        "decoder/source/ocsd_lib_dcd_register.cpp",
-        "decoder/source/ocsd_msg_logger.cpp",
-        "decoder/source/ocsd_version.cpp",
-        "decoder/source/pkt_printers/raw_frame_printer.cpp",
-        "decoder/source/pkt_printers/trc_print_fact.cpp",
-        "decoder/source/ptm/trc_cmp_cfg_ptm.cpp",
-        "decoder/source/ptm/trc_pkt_decode_ptm.cpp",
-        "decoder/source/ptm/trc_pkt_elem_ptm.cpp",
-        "decoder/source/ptm/trc_pkt_proc_ptm.cpp",
-        "decoder/source/stm/trc_pkt_decode_stm.cpp",
-        "decoder/source/stm/trc_pkt_elem_stm.cpp",
-        "decoder/source/stm/trc_pkt_proc_stm.cpp",
-        "decoder/source/trc_component.cpp",
-        "decoder/source/trc_core_arch_map.cpp",
-        "decoder/source/trc_frame_deformatter.cpp",
-        "decoder/source/trc_gen_elem.cpp",
-        "decoder/source/trc_printable_elem.cpp",
-        "decoder/source/trc_ret_stack.cpp",
+        "decoder/source/*.cpp",
+        "decoder/source/etmv3/*.cpp",
+        "decoder/source/etmv4/*.cpp",
+        "decoder/source/i_dec/*.cpp",
+        "decoder/source/mem_acc/*.cpp",
+        "decoder/source/pkt_printers/*.cpp",
+        "decoder/source/ptm/*.cpp",
+        "decoder/source/stm/*.cpp",
     ],
-}
\ No newline at end of file
+}
diff --git a/HOWTO.md b/HOWTO.md
index b16294a..c1196ce 100644
--- a/HOWTO.md
+++ b/HOWTO.md
@@ -4,37 +4,39 @@
 @brief Using command line perf and OpenCSD to collect and decode trace.
 
 This HOWTO explains how to use the perf cmd line tools and the openCSD
-library to collect and extract program flow traces generated by the 
+library to collect and extract program flow traces generated by the
 CoreSight IP blocks on a Linux system.  The examples have been generated using
-an aarch64 Juno-r0 platform.  All information is considered accurate and tested
-using the latest version of the library and the `master` branch on the
-[perf-opencsd github repository][1].
+an aarch64 Juno-r0 platform.
 
 
 On Target Trace Acquisition - Perf Record
 -----------------------------------------
-All the enhancement to the Perf tools that support the new `cs_etm` pmu have
-not been upstreamed yet.  To get the required functionality branch
-`perf-opencsd-master` needs to be downloaded to the target system where
-traces are to be collected.  This branch is a vanilla upstream kernel
-supplemented with modifications to the CoreSight framework and drivers to be
-usable by the Perf core.  The remaining out of tree patches are being
-upstreamed incrementally.
 
-From there compiling the perf tools with `make -C tools/perf CORESIGHT=1` will
-yield a `perf` executable that will support CoreSight trace collection.  Note
-that if traces are to be decompressed *off* target, there is no need to download
+Compile the perf tool from the same kernel source code version you are using with:
+	
+	make -C tools/perf
+	
+This will yield a `perf` executable that will support CoreSight trace collection.
+
+*Note:* If traces are to be decompressed **off** target, there is no need to download
 and compile the openCSD library (on the target).
 
+If you are instead planning to use perf to record and decode the trace on the target,
+compile the perf tool linking against the openCSD library, in the following way:
+
+	make -C tools/perf VF=1 CORESIGHT=1
+
+Further information on the needed build environments and options are detailed later 
+in the section **Off Target Perf Tools Compilation**.
+
 Before launching a trace run a sink that will collect trace data needs to be
 identified.  All CoreSight blocks identified by the framework are registed in
 sysFS:
 
 
     linaro@linaro-nano:~$ ls /sys/bus/coresight/devices/
-    20010000.etf   20040000.main_funnel  22040000.etm 22140000.etm  
-    230c0000.A53_funnel  23240000.etm  replicator@20020000 20030000.tpiu
-    20070000.etr 220c0000.A57_funnel  23040000.etm  23140000.etm 23340000.etm
+    etm0  etm2  etm4  etm6  funnel0  funnel2  funnel4      stm0      tmc_etr0
+    etm1  etm3  etm5  etm7  funnel1  funnel3  replicator0  tmc_etf0
 
 
 CoreSight blocks are listed in the device tree for a specific system and
@@ -43,7 +45,7 @@
 option on the perf command line.  Once a sink has been identify trace collection
 can start.  An easy and yet interesting example is the `uname` command:
 
-    linaro@linaro-nano:~/kernel$ ./tools/perf/perf record -e cs_etm/@20070000.etr/ --per-thread uname
+    linaro@linaro-nano:~/kernel$ ./tools/perf/perf record -e cs_etm/@tmc_etr0/ --per-thread uname
 
 This will generate a `perf.data` file where execution has been traced for both
 user and kernel space.  To narrow the field to either user or kernel space the
@@ -51,7 +53,7 @@
 traces to user space:
 
 
-    linaro@linaro-nano:~/kernel$ ./tools/perf/perf record -vvv -e cs_etm/@20070000.etr/u --per-thread uname
+    linaro@linaro-nano:~/kernel$ ./tools/perf/perf record -vvv -e cs_etm/@tmc_etr0/u --per-thread uname
     Problems setting modules path maps, continuing anyway...
     -----------------------------------------------------------
     perf_event_attr:
@@ -131,9 +133,9 @@
 range will not be traced.  Address range filters can be specified for both
 user and kernel space session:
 
-    perf record -e cs_etm/@20070000.etr/k --filter 'filter 0xffffff8008562d0c/0x48' --per-thread uname
+    perf record -e cs_etm/@tmc_etr0/k --filter 'filter 0xffffff8008562d0c/0x48' --per-thread uname
 
-    perf record -e cs_etm/@20070000.etr/u --filter 'filter 0x72c/0x40@/opt/lib/libcstest.so.1.0' --per-thread ./main
+    perf record -e cs_etm/@tmc_etr0/u --filter 'filter 0x72c/0x40@/opt/lib/libcstest.so.1.0' --per-thread ./main
 
 When dealing with kernel space trace addresses are typically taken in the
 'System.map' file.  In user space addresses are relocatable and can be
@@ -171,20 +173,20 @@
 insruction pointer is equal to the stop address.  Anything that happens between
 there to events is traced:
 
-    perf record -e cs_etm/@20070000.etr/k --filter 'start 0xffffff800856bc50,stop 0xffffff800856bcb0' --per-thread uname
+    perf record -e cs_etm/@tmc_etr0/k --filter 'start 0xffffff800856bc50,stop 0xffffff800856bcb0' --per-thread  uname
 
-    perf record -vvv -e cs_etm/@20070000.etr/u --filter 'start 0x72c@/opt/lib/libcstest.so.1.0,    \
+    perf record -vvv -e cs_etm/@tmc_etr0/u --filter 'start 0x72c@/opt/lib/libcstest.so.1.0,    \
                                                          stop 0x40082c@/home/linaro/main'          \
-                                                         --per-thread ./main
+                                                     --per-thread ./main
 
 **Limitation on address filters:**
 The only limitation on address filters is the amount of address comparator
 found on an implementation and the mutual exclusion between range and
 start stop filters.  As such the following example would _not_ work:
 
-    perf record -e cs_etm/@20070000.etr/k --filter 'start 0xffffff800856bc50,stop 0xffffff800856bcb0, \  // start/stop
+    perf record -e cs_etm/@tmc_etr0/k --filter 'start 0xffffff800856bc50,stop 0xffffff800856bcb0, \  // start/stop
                                                     filter 0x72c/0x40@/opt/lib/libcstest.so.1.0'      \  // address range
-                                                    --per-thread uname
+                                                    --per-thread  uname
 
 Additional Trace Options
 ------------------------
@@ -198,10 +200,32 @@
 
 Command line options in `perf record` to use these features are part of the options for the `cs_etm` event:
 
-    perf record -e cs_etm/timestamp,cycacc,@20070000.etr/ --per-thread uname
+    perf record -e cs_etm/timestamp,cycacc,@tmc_etr0/ --per-thread uname
 
 At current version,  `perf record` and `perf script` do not use this additional information.
 
+The cs_etm perf event
+---------------------
+
+System information for this perf pmu event can be found at: 
+
+	/sys/devices/cs_etm
+
+This contains internal format of the parameters described above:	
+
+	root@linaro-developer:~# ls /sys/devices/cs_etm/format
+	contextid  cycacc  retstack  sinkid  timestamp
+
+and names of registered sinks:
+	
+	root@linaro-developer:~# ls /sys/devices/cs_etm/sinks
+	tmc_etf0  tmc_etr0  tpiu0
+
+Note: The `sinkid` parameter is there to document the usage of a 32-bit internal parameter to
+pass the sink name used in the cs_etm/@sink/ command to the kernel drivers. It can be used 
+directly as cs_etm/sinkid=<hash_value>/ but this is not recommended as the values used are 
+considered opaque and subject to changes.
+
 On Target Trace Collection
 --------------------------
 The entire program flow will have been recorded in the `perf.data` file.
@@ -248,7 +272,7 @@
 [github][1] and needs to be compiled before the perf tools. Checkout the
 required branch/tag version into a local directory.
 
-    linaro@t430:~/linaro/coresight$ git clone -b v0.8 https://github.com/Linaro/OpenCSD.git my-opencsd
+    linaro@t430:~/linaro/coresight$ git clone https://github.com/Linaro/OpenCSD.git my-opencsd
     Cloning into 'OpenCSD'...
     remote: Counting objects: 2063, done.
     remote: Total 2063 (delta 0), reused 0 (delta 0), pack-reused 2063
@@ -301,7 +325,8 @@
 
 Off Target Perf Tools Compilation
 ---------------------------------
-As mentionned above the openCSD library is not part of the perf tools' code base
+
+As mentioned above the openCSD library is not part of the perf tools' code base
 and needs to be installed on a system prior to compilation.  Information about
 the status of the openCSD library on a system is given at compile time by the
 perf tools build script:
@@ -366,8 +391,8 @@
     
 Set to any other value will remove the RAW_PACKED lines.
 
-Working with a debug version of the openCSD library
----------------------------------------------------
+Working with an alternate version of the openCSD library
+--------------------------------------------------------
 When compiling the perf tools it is possible to reference another version of
 the openCSD library than the one installed on the system.  This is useful when
 working with multiple development trees or having the desire to keep system
@@ -407,9 +432,13 @@
     -rw------- 1 linaro linaro   78016 Feb 24 12:21 perf.data
     -rw-rw-r-- 1 linaro linaro 1245881 Feb 24 12:25 uname.v4.user.sept20.tgz
 
-Perf is expecting files related to the trace capture (`perf.data`) to be located
-under `~/.debug` [3].  This example will remove the current `~/.debug` directory
-to be sure everything is clean.  
+Perf is expecting files related to the trace capture (`perf.data`) to be located in the `buildid` directory.
+By default this is under `~/.debug`.  Alternatively the default `buildid` directory can be changed 
+using the command:
+
+     perf config --system buildid.dir=/my/own/buildid/dir
+
+This example will remove the current `~/.debug` directory to be sure everything is clean.  
 
     linaro@t430:~/linaro/coresight/sept20$ rm -rf ~/.debug
     linaro@t430:~/linaro/coresight/sept20$ cp -dpR .debug ~/
@@ -586,12 +615,18 @@
 
 1. Prior to building perf, edit `perf-setup-env.bash` to conform to your environment. There are four lines at the top of the file that will require editing.
 
-2. Execute the script using the command
+2. Execute the script using the command:
 
         source perf-setup-env.bash
 
-   This will set up all the environment variables mentioned in the sections on building and running
-   perf above, and these are used by the `perf-test...` scripts to run the tests.
+   This will set up a perf execute environment for using the perf report and script commands.
+	
+   Alternatively use the command:
+   
+		source perf-setup-env.base buildenv
+		
+   This will add in the build environment variables mentioned in the sections on building above alongside the
+   environment for using the used by the `perf-test...` scripts to run the tests.
 
 3. Build perf as described above.
 4. Follow the instructions for downloading the test capture, or create a capture from your target.
@@ -629,8 +664,6 @@
 *The Linaro CoreSight Team*
 
 --------------------------------------
-[1]: https://github.com/Linaro/perf-opencsd "perf-opencsd Github"
+[1]: https://github.com/Linaro/OpenCSD
 
 [2]: http://people.linaro.org/~mathieu.poirier/openCSD/uname.v4.user.sept20.tgz
- 
-[3]: Get in touch with us if you know a way to change this.
diff --git a/METADATA b/METADATA
index 12e6c73..a947e0f 100644
--- a/METADATA
+++ b/METADATA
@@ -9,10 +9,10 @@
     type: GIT
     value: "https://github.com/Linaro/OpenCSD.git"
   }
-  version: "v0.12.1"
+  version: "v0.14.0"
   last_upgrade_date {
-    year: 2019
-    month: 10
-    day: 29
+    year: 2020
+    month: 3
+    day: 30
   }
 }
diff --git a/README.md b/README.md
index 7a1c493..6805eac 100644
--- a/README.md
+++ b/README.md
@@ -27,11 +27,11 @@
 CoreSight Trace Component Support.
 ----------------------------------
 
-_Current Version 0.12.1_
+_Current Version 0.14.0_
 
 ### Current support:
 
-- ETMv4 (v4.4) instruction trace - packet processing and packet decode.
+- ETMv4 (v4.5 [A/R profile] v4.4 [M profile]) instruction trace - packet processing and packet decode.
 - PTM   (v1.1) instruction trace - packet processing and packet decode.
 - ETMv3 (v3.5) instruction trace - packet processing and packet decode.
 - ETMv3 (v3.5) data trace - packet processing.
@@ -55,12 +55,11 @@
 This git repository for OpenCSD contains only source for the OpenCSD decoder library.
 From version 0.4, releases appear as versioned tags on the master branch.
 
-From version 0.7.4, the required updates to CoreSight drivers and perf, that are not
-currently upstream in the linux kernel tree, are now contained in a separate
-repository to be found at:
+CoreSight kernel drivers and perf suport for CoreSight trace is maintained in the latest
+upstream kernel versions.
 
-https://github.com/Linaro/perf-opencsd
-
+One exception is a minor patch required for autoFDO support. 
+See [autofdo.md](@ref AutoFDO).
 
 Documentation
 -------------
@@ -170,6 +169,23 @@
                     __Bugfix__: Instruction decode - v8.3 B[L]A{A|B}[Z] instructions mis-identified.
                     __Bugfix__: Transition from A64 to A32 can be mis-decoded if the trace implementation represents the transition 
                     as an individual address packet followed by a context packet. 
+- _Version 0.12.2_: __Bugfix__: Clean up memory leaks.
+                    __Bugfix__: ETMv4: Ensure addressing history zeroed after TINFO.
+                    __Update__: Allow GCC version to be included in build output path.
+                    __Bugfix__: Packet printing update when WFI/WFE is P0 element.
+
+- _Version 0.13.x_ : Intermediate development version.
+
+- _Version 0.14.0_: __Update__: ETMv4 - decoder update & simplification to handle advanced trace features.
+                    __Update__: ETMv4 - decoder support for speculative trace.
+                    __Update__: Generic Elements: Additional information in EOT, UNSYNC, ON packets to give reason.
+                    __Update__: Memaccess: Add EL2 secure memory space flag.
+                    __Update__: Documentation: Updated for release changes and to reflect latest kernel version support for CoreSight.
+                    __Update__: Perf helper scripts updated to reflect latest build flow.
+                    __Bugfix__: Fix for component operational flag inputs.
+                    
+
+
 
 
 Licence Information
diff --git a/decoder/build/linux/makefile.dev b/decoder/build/linux/makefile.dev
index 7c02328..5eb1ec9 100644
--- a/decoder/build/linux/makefile.dev
+++ b/decoder/build/linux/makefile.dev
@@ -56,7 +56,12 @@
 CFLAGS += $(MFLAG)
 LDFLAGS += $(MFLAG)
 
+ifdef GCCDIR
+GCCVER:= $(shell $(CROSS_COMPILE)gcc -dumpversion | cut -c 1-3)
+PLAT_DIR=builddir/linux$(BIT_VARIANT)/GCC_$(GCCVER)
+else
 PLAT_DIR=linux$(BIT_VARIANT)/$(BUILD_VARIANT)
+endif
 
 # include the main makefile
 include makefile
diff --git a/decoder/build/linux/ref_trace_decode_lib/makefile b/decoder/build/linux/ref_trace_decode_lib/makefile
index 373e824..7087036 100644
--- a/decoder/build/linux/ref_trace_decode_lib/makefile
+++ b/decoder/build/linux/ref_trace_decode_lib/makefile
@@ -59,11 +59,9 @@
 			$(BUILD_DIR)/trc_pkt_proc_etmv3_impl.o
 
 ETMV4OBJ=	$(BUILD_DIR)/trc_cmp_cfg_etmv4.o \
-			$(BUILD_DIR)/trc_pkt_proc_etmv4.o \
-			$(BUILD_DIR)/trc_pkt_proc_etmv4i_impl.o \
+			$(BUILD_DIR)/trc_pkt_proc_etmv4i.o \
 			$(BUILD_DIR)/trc_pkt_decode_etmv4i.o \
 			$(BUILD_DIR)/trc_pkt_elem_etmv4i.o \
-			$(BUILD_DIR)/trc_pkt_elem_etmv4d.o \
 			$(BUILD_DIR)/trc_etmv4_stack_elem.o
 
 PTMOBJ=		$(BUILD_DIR)/trc_cmp_cfg_ptm.o \
@@ -94,6 +92,7 @@
 		$(BUILD_DIR)/ocsd_error.o \
 		$(BUILD_DIR)/ocsd_error_logger.o \
 		$(BUILD_DIR)/ocsd_gen_elem_list.o \
+		$(BUILD_DIR)/ocsd_gen_elem_stack.o \
 		$(BUILD_DIR)/ocsd_lib_dcd_register.o \
 		$(BUILD_DIR)/ocsd_msg_logger.o \
 		$(BUILD_DIR)/ocsd_version.o \
diff --git a/decoder/build/win-vs2015/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj b/decoder/build/win-vs2015/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj
index 095f27b..f1aaece 100644
--- a/decoder/build/win-vs2015/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj
+++ b/decoder/build/win-vs2015/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj
@@ -323,6 +323,7 @@
     <ClInclude Include="..\..\..\include\common\ocsd_error.h" />
     <ClInclude Include="..\..\..\include\common\ocsd_error_logger.h" />
     <ClInclude Include="..\..\..\include\common\ocsd_gen_elem_list.h" />
+    <ClInclude Include="..\..\..\include\common\ocsd_gen_elem_stack.h" />
     <ClInclude Include="..\..\..\include\common\ocsd_lib_dcd_register.h" />
     <ClInclude Include="..\..\..\include\common\ocsd_msg_logger.h" />
     <ClInclude Include="..\..\..\include\common\ocsd_pe_context.h" />
@@ -400,8 +401,6 @@
     <ClInclude Include="..\..\..\include\opencsd\trc_gen_elem_types.h" />
     <ClInclude Include="..\..\..\include\opencsd\trc_pkt_types.h" />
     <ClInclude Include="..\..\..\source\etmv3\trc_pkt_proc_etmv3_impl.h" />
-    <ClInclude Include="..\..\..\source\etmv4\trc_pkt_proc_etmv4d_impl.h" />
-    <ClInclude Include="..\..\..\source\etmv4\trc_pkt_proc_etmv4i_impl.h" />
     <ClInclude Include="..\..\..\source\trc_frame_deformatter_impl.h" />
   </ItemGroup>
   <ItemGroup>
@@ -413,10 +412,8 @@
     <ClCompile Include="..\..\..\source\etmv4\trc_cmp_cfg_etmv4.cpp" />
     <ClCompile Include="..\..\..\source\etmv4\trc_etmv4_stack_elem.cpp" />
     <ClCompile Include="..\..\..\source\etmv4\trc_pkt_decode_etmv4i.cpp" />
-    <ClCompile Include="..\..\..\source\etmv4\trc_pkt_elem_etmv4d.cpp" />
     <ClCompile Include="..\..\..\source\etmv4\trc_pkt_elem_etmv4i.cpp" />
-    <ClCompile Include="..\..\..\source\etmv4\trc_pkt_proc_etmv4.cpp" />
-    <ClCompile Include="..\..\..\source\etmv4\trc_pkt_proc_etmv4i_impl.cpp" />
+    <ClCompile Include="..\..\..\source\etmv4\trc_pkt_proc_etmv4i.cpp" />
     <ClCompile Include="..\..\..\source\i_dec\trc_idec_arminst.cpp" />
     <ClCompile Include="..\..\..\source\i_dec\trc_i_decode.cpp" />
     <ClCompile Include="..\..\..\source\mem_acc\trc_mem_acc_base.cpp" />
@@ -430,6 +427,7 @@
     <ClCompile Include="..\..\..\source\ocsd_error.cpp" />
     <ClCompile Include="..\..\..\source\ocsd_error_logger.cpp" />
     <ClCompile Include="..\..\..\source\ocsd_gen_elem_list.cpp" />
+    <ClCompile Include="..\..\..\source\ocsd_gen_elem_stack.cpp" />
     <ClCompile Include="..\..\..\source\ocsd_lib_dcd_register.cpp" />
     <ClCompile Include="..\..\..\source\ocsd_msg_logger.cpp" />
     <ClCompile Include="..\..\..\source\ocsd_version.cpp" />
diff --git a/decoder/build/win-vs2015/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj.filters b/decoder/build/win-vs2015/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj.filters
index 1ef8720..cdb6f84 100644
--- a/decoder/build/win-vs2015/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj.filters
+++ b/decoder/build/win-vs2015/ref_trace_decode_lib/ref_trace_decode_lib.vcxproj.filters
@@ -221,12 +221,6 @@
     <ClInclude Include="..\..\..\include\opencsd\ptm\trc_pkt_decode_ptm.h">
       <Filter>Header Files\ptm</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\..\source\etmv4\trc_pkt_proc_etmv4d_impl.h">
-      <Filter>Source Files\etmv4</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\..\source\etmv4\trc_pkt_proc_etmv4i_impl.h">
-      <Filter>Source Files\etmv4</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\..\source\etmv3\trc_pkt_proc_etmv3_impl.h">
       <Filter>Source Files\etmv3</Filter>
     </ClInclude>
@@ -359,6 +353,9 @@
     <ClInclude Include="..\..\..\include\opencsd\ocsd_if_version.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\..\include\common\ocsd_gen_elem_stack.h">
+      <Filter>Header Files\common</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\source\trc_component.cpp">
@@ -385,18 +382,9 @@
     <ClCompile Include="..\..\..\source\ptm\trc_pkt_proc_ptm.cpp">
       <Filter>Source Files\ptm</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\..\source\etmv4\trc_pkt_elem_etmv4d.cpp">
-      <Filter>Source Files\etmv4</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\..\source\etmv4\trc_pkt_elem_etmv4i.cpp">
       <Filter>Source Files\etmv4</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\..\source\etmv4\trc_pkt_proc_etmv4.cpp">
-      <Filter>Source Files\etmv4</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\..\source\etmv4\trc_pkt_proc_etmv4i_impl.cpp">
-      <Filter>Source Files\etmv4</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\..\source\etmv4\trc_pkt_decode_etmv4i.cpp">
       <Filter>Source Files\etmv4</Filter>
     </ClCompile>
@@ -490,5 +478,11 @@
     <ClCompile Include="..\..\..\source\mem_acc\trc_mem_acc_cache.cpp">
       <Filter>Source Files\mem_acc</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\source\etmv4\trc_pkt_proc_etmv4i.cpp">
+      <Filter>Source Files\etmv4</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\source\ocsd_gen_elem_stack.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/decoder/docs/doxygen_config.dox b/decoder/docs/doxygen_config.dox
index b4db933..b60bbb8 100644
--- a/decoder/docs/doxygen_config.dox
+++ b/decoder/docs/doxygen_config.dox
@@ -38,7 +38,7 @@
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 0.12.1
+PROJECT_NUMBER         = 0.14.0
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
diff --git a/decoder/include/common/ocsd_dcd_mngr.h b/decoder/include/common/ocsd_dcd_mngr.h
index ba7d8a8..3342eac 100644
--- a/decoder/include/common/ocsd_dcd_mngr.h
+++ b/decoder/include/common/ocsd_dcd_mngr.h
@@ -115,6 +115,9 @@
     if(!pkt_proc)
         return OCSD_ERR_MEM;
 
+    // set the op mode flags
+    pkt_proc->setComponentOpMode(create_flags & (OCSD_OPFLG_COMP_MODE_MASK | OCSD_OPFLG_PKTPROC_COMMON));
+
     // set the configuration
     TrcPktProcBase<P,Pt,Pc> *pProcBase = dynamic_cast< TrcPktProcBase<P,Pt,Pc> *>(pkt_proc);       
     if(pProcBase == 0)
@@ -133,6 +136,9 @@
         if(!pkt_dcd)
             return OCSD_ERR_MEM;
 
+        // set the op mode flags
+        pkt_dcd->setComponentOpMode(create_flags & (OCSD_OPFLG_COMP_MODE_MASK | OCSD_OPFLG_PKTDEC_COMMON));
+
         // get the decoder base
         TrcPktDecodeBase<P,Pc> *pBase = dynamic_cast< TrcPktDecodeBase<P,Pc> *>(pkt_dcd);       
         if(pBase == 0)
diff --git a/decoder/include/common/ocsd_gen_elem_list.h b/decoder/include/common/ocsd_gen_elem_list.h
index 0ff1bd5..2dab240 100644
--- a/decoder/include/common/ocsd_gen_elem_list.h
+++ b/decoder/include/common/ocsd_gen_elem_list.h
@@ -1,6 +1,6 @@
 /*
- * \file       ocsd_gen_elem_stack.h
- * \brief      OpenCSD : Generic element output stack.
+ * \file       ocsd_gen_elem_list.h
+ * \brief      OpenCSD : Generic element output list.
  * 
  * \copyright  Copyright (c) 2016, ARM Limited. All Rights Reserved.
  */
@@ -47,7 +47,7 @@
  * This should remove some of the requirement on the packet processing to be re-enterant,
  * simplifying this code.
  *
- * Last element(s) on this stack can be marked pending to allow for later cancellation.
+ * Last element(s) on this list can be marked pending to allow for later cancellation.
  * (This required for cancel element in ETMv3 exeception branch).
  * 
  * The "list" is actually a ring buffer - maintaining pointers to indicate current valid elements.
@@ -150,4 +150,4 @@
     m_sendIf = pGenElemIf;
 }
 
-/* End of File ocsd_gen_elem_stack.h */
+/* End of File ocsd_gen_elem_list.h */
diff --git a/decoder/include/common/ocsd_gen_elem_stack.h b/decoder/include/common/ocsd_gen_elem_stack.h
new file mode 100644
index 0000000..64c525d
--- /dev/null
+++ b/decoder/include/common/ocsd_gen_elem_stack.h
@@ -0,0 +1,109 @@
+/*
+* \file       ocsd_gen_elem_stack.h
+* \brief      OpenCSD : Generic element output stack.
+*
+* \copyright  Copyright (c) 2020, ARM Limited. All Rights Reserved.
+*/
+
+/*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+*
+* 1. Redistributions of source code must retain the above copyright notice,
+* this list of conditions and the following disclaimer.
+*
+* 2. Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* 3. Neither the name of the copyright holder nor the names of its contributors
+* may be used to endorse or promote products derived from this software without
+* specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "trc_gen_elem.h"
+#include "comp_attach_pt_t.h"
+#include "interfaces/trc_gen_elem_in_i.h"
+
+/* element stack to handle cases where a trace element can generate multiple output packets 
+  
+   maintains the "current" element, which might be sent independently of this stack, and also
+   ensures that persistent data in the output elements is maintained between elements.
+*/
+class OcsdGenElemStack
+{
+public:
+    OcsdGenElemStack();
+    ~OcsdGenElemStack();
+
+    void initSendIf(componentAttachPt<ITrcGenElemIn> *pGenElemIf);
+    void initCSID(const uint8_t CSID) { m_CSID = CSID; };
+
+    OcsdTraceElement &getCurrElem();    //!< get the current element. 
+    ocsd_err_t resetElemStack();        //!< set pointers to base of stack
+    ocsd_err_t addElem(const ocsd_trc_index_t trc_pkt_idx);    //!< add elem to stack and set current.
+    void setCurrElemIdx(const ocsd_trc_index_t trc_pkt_idx);   //!< packet index for this element
+    ocsd_err_t addElemType(const ocsd_trc_index_t trc_pkt_idx, ocsd_gen_trc_elem_t elem_type);
+
+    ocsd_datapath_resp_t sendElements();    //!< send elements on the stack
+    const int numElemToSend() const;
+
+private:
+    typedef struct _elemPtr {
+        OcsdTraceElement *pElem;        //!< pointer to the listed trace element
+        ocsd_trc_index_t trc_pkt_idx;   //!< packet index in the trace stream
+    } elemPtr_t;
+
+    const bool isInit();              //!< check correctly initialised.
+
+    ocsd_err_t growArray();
+    void copyPersistentData(int src, int dst);  //!< copy across persistent state data between elements
+    void resetIndexes();    //!< clear down all indexes - reset or send complete.
+
+    elemPtr_t *m_pElemArray;    //!< an array of pointers to elements.
+    int m_elemArraySize;        //!< number of element pointers in the array 
+
+    int m_elem_to_send;     //!< number of live elements in the stack - init to 1.
+    int m_curr_elem_idx;    //!< index into the element array.
+    int m_send_elem_idx;    //!< next element to send.
+
+    //!< send packet info
+    uint8_t m_CSID;
+    componentAttachPt<ITrcGenElemIn> *m_sendIf; //!< element send interface.
+
+    bool m_is_init;
+};
+
+inline const int OcsdGenElemStack::numElemToSend() const
+{
+    return m_elem_to_send;
+}
+
+inline void OcsdGenElemStack::initSendIf(componentAttachPt<ITrcGenElemIn> *pGenElemIf)
+{
+    m_sendIf = pGenElemIf;
+}
+
+inline void OcsdGenElemStack::setCurrElemIdx(const ocsd_trc_index_t trc_pkt_idx)
+{
+    m_pElemArray[m_curr_elem_idx].trc_pkt_idx = trc_pkt_idx;
+}
+
+inline OcsdTraceElement &OcsdGenElemStack::getCurrElem()
+{
+    return *(m_pElemArray[m_curr_elem_idx].pElem);
+}
+
+
+/* End of File ocsd_gen_elem_stack.h */
diff --git a/decoder/include/common/trc_gen_elem.h b/decoder/include/common/trc_gen_elem.h
index 1c4a47b..5d8983a 100644
--- a/decoder/include/common/trc_gen_elem.h
+++ b/decoder/include/common/trc_gen_elem.h
@@ -72,6 +72,7 @@
 
 
     void setTraceOnReason(const trace_on_reason_t reason);
+    void setUnSyncEOTReason(const unsync_info_t reason);
 
     void setAddrRange(const ocsd_vaddr_t  st_addr, const ocsd_vaddr_t en_addr, const int num_instr = 1);
     void setLastInstrInfo(const bool exec, const ocsd_instr_type last_i_type, const ocsd_instr_subtype last_i_subtype, const uint8_t size);
@@ -94,7 +95,8 @@
     // return current context
     const ocsd_pe_context &getContext() const {  return context; };
 
-    
+    void copyPersistentData(const OcsdTraceElement &src);
+
 private:
     void printSWInfoPkt(std::ostringstream &oss) const;
     void clearPerPktData(); //!< clear flags that indicate validity / have values on a per packet basis
@@ -171,8 +173,8 @@
 
 inline void OcsdTraceElement::clearPerPktData()
 {
-    flag_bits = 0; // union with trace_on_reason / trace_event
-
+    flag_bits = 0;          // bit-field with various flags.
+    exception_number = 0;   // union with trace_on_reason / trace_event
     ptr_extended_data = 0;  // extended data pointer
 }
 
@@ -181,6 +183,11 @@
     trace_on_reason = reason;
 }
 
+inline void OcsdTraceElement::setUnSyncEOTReason(const unsync_info_t reason)
+{
+    unsync_eot_info = reason;
+}
+
 inline void OcsdTraceElement::setISA(const ocsd_isa isa_update)
 {
     isa = isa_update;
@@ -201,6 +208,12 @@
     ptr_extended_data = data_ptr;
 }
 
+// set persistent data between output packets.
+inline void OcsdTraceElement::copyPersistentData(const OcsdTraceElement &src)
+{
+    isa = src.isa;
+    context = src.context;
+}
 
 /** @}*/
 
diff --git a/decoder/include/common/trc_pkt_decode_base.h b/decoder/include/common/trc_pkt_decode_base.h
index 2bbf5e5..da70206 100644
--- a/decoder/include/common/trc_pkt_decode_base.h
+++ b/decoder/include/common/trc_pkt_decode_base.h
@@ -85,7 +85,10 @@
     virtual ocsd_err_t onProtocolConfig() = 0;
     virtual const uint8_t getCoreSightTraceID() = 0;
 
+    /* init handling */
     const bool checkInit();
+    /* Called on first init confirmation */
+    virtual void onFirstInitOK() {};
 
     /* data output */
     ocsd_datapath_resp_t outputTraceElement(const OcsdTraceElement &elem);    // use current index
@@ -147,6 +150,8 @@
             init_err_msg = "No instruction decoder interface attached and enabled";
         else
             m_decode_init_ok = true;
+        if (m_decode_init_ok)
+            onFirstInitOK();
     }
     return m_decode_init_ok;
 }
diff --git a/decoder/include/common/trc_raw_buffer.h b/decoder/include/common/trc_raw_buffer.h
new file mode 100644
index 0000000..67b8d24
--- /dev/null
+++ b/decoder/include/common/trc_raw_buffer.h
@@ -0,0 +1,96 @@
+/*
+* \file       trc_raw_buffer.h
+* \brief      OpenCSD : Trace raw data byte buffer
+*
+* \copyright  Copyright (c) 2019, ARM Limited. All Rights Reserved.
+*/
+
+/*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+*
+* 1. Redistributions of source code must retain the above copyright notice,
+* this list of conditions and the following disclaimer.
+*
+* 2. Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* 3. Neither the name of the copyright holder nor the names of its contributors
+* may be used to endorse or promote products derived from this software without
+* specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef ARM_TRC_RAW_BUFFER_H_INCLUDED
+#define ARM_TRC_RAW_BUFFER_H_INCLUDED
+
+#include <vector>
+
+class TraceRawBuffer
+{
+public:
+    TraceRawBuffer() : 
+        m_bufSize(0), 
+        m_bufProcessed(0), 
+        m_pBuffer(0), 
+        pkt(0)
+    {};
+    ~TraceRawBuffer() {};
+
+    // init the buffer
+    void init(const uint32_t size, const uint8_t *rawtrace, std::vector<uint8_t> *out_packet);
+    void copyByteToPkt();   // move a byte to the packet buffer     
+    uint8_t peekNextByte(); // value of next byte in buffer.
+
+    bool empty() { return m_bufProcessed == m_bufSize; };
+    // bytes processed.
+    uint32_t processed() { return m_bufProcessed; };
+    // buffer size;
+    uint32_t size() { return m_bufSize; }
+
+private:
+    uint32_t m_bufSize;
+    uint32_t m_bufProcessed;
+    const uint8_t *m_pBuffer;
+    std::vector<uint8_t> *pkt;
+
+};
+
+// init the buffer
+inline void TraceRawBuffer::init(const uint32_t size, const uint8_t *rawtrace, std::vector<uint8_t> *out_packet)
+{
+    m_bufSize = size;
+    m_bufProcessed = 0;
+    m_pBuffer = rawtrace;
+    pkt = out_packet;
+}
+
+inline void TraceRawBuffer::copyByteToPkt()
+{
+    if (!empty()) {
+        pkt->push_back(m_pBuffer[m_bufProcessed]);
+        m_bufProcessed++;
+    }
+}
+
+inline uint8_t TraceRawBuffer::peekNextByte()
+{
+    uint8_t val = 0;
+    if (!empty())
+        val = m_pBuffer[m_bufProcessed];
+    return val;
+}
+
+#endif // ARM_TRC_RAW_BUFFER_H_INCLUDED
+
diff --git a/decoder/include/opencsd/etmv3/trc_pkt_decode_etmv3.h b/decoder/include/opencsd/etmv3/trc_pkt_decode_etmv3.h
index b2139c0..9027706 100644
--- a/decoder/include/opencsd/etmv3/trc_pkt_decode_etmv3.h
+++ b/decoder/include/opencsd/etmv3/trc_pkt_decode_etmv3.h
@@ -264,6 +264,7 @@
     } processor_state_t;
 
     processor_state_t m_curr_state;
+    unsync_info_t m_unsync_info;    //!< additional state for unsync
 
     uint8_t m_CSID; //!< Coresight trace ID for this decoder.
 };
diff --git a/decoder/include/opencsd/etmv4/etmv4_decoder.h b/decoder/include/opencsd/etmv4/etmv4_decoder.h
index 05bdd44..5d18363 100644
--- a/decoder/include/opencsd/etmv4/etmv4_decoder.h
+++ b/decoder/include/opencsd/etmv4/etmv4_decoder.h
@@ -38,7 +38,6 @@
 
 #include "trc_cmp_cfg_etmv4.h"
 #include "trc_pkt_elem_etmv4i.h"
-#include "trc_pkt_elem_etmv4d.h"
 #include "trc_pkt_proc_etmv4.h"
 #include "trc_pkt_types_etmv4.h"
 #include "trc_pkt_decode_etmv4i.h"
diff --git a/decoder/include/opencsd/etmv4/trc_etmv4_stack_elem.h b/decoder/include/opencsd/etmv4/trc_etmv4_stack_elem.h
index 1f5911c..5a283c5 100644
--- a/decoder/include/opencsd/etmv4/trc_etmv4_stack_elem.h
+++ b/decoder/include/opencsd/etmv4/trc_etmv4_stack_elem.h
@@ -56,6 +56,7 @@
     P0_TS,
     P0_CC,
     P0_TS_CC,
+    P0_Q,
     P0_OVERFLOW,
     P0_FUNC_RET,
 } p0_elem_t;
@@ -120,6 +121,44 @@
 }
 
 /************************************************************/
+/** Q element */
+class TrcStackQElem : public TrcStackElem
+{
+protected:
+    TrcStackQElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index);
+    virtual ~TrcStackQElem() {};
+
+    friend class EtmV4P0Stack;
+
+public:
+    void setInstrCount(const int instr_count) { m_instr_count = instr_count; };
+    const int getInstrCount() const { return m_instr_count;  }
+
+    void setAddr(const etmv4_addr_val_t &addr_val) 
+    {
+        m_addr_val = addr_val; 
+        m_has_addr = true; 
+    };
+    const etmv4_addr_val_t &getAddr() const { return m_addr_val; };
+    const bool hasAddr() const { return  m_has_addr; };
+
+private:
+    bool m_has_addr;
+    etmv4_addr_val_t m_addr_val;
+    int m_instr_count;
+
+};
+
+inline TrcStackQElem::TrcStackQElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index) :
+    TrcStackElem(P0_Q , true, root_pkt, root_index)
+{
+    m_addr_val.val = 0;
+    m_addr_val.isa = 0;
+    m_has_addr = false;
+    m_instr_count = 0;
+}
+
+/************************************************************/
 /** Context element */
     
 class TrcStackElemCtxt : public TrcStackElem
@@ -191,6 +230,7 @@
 
     const ocsd_atm_val commitOldest();
     int cancelNewest(const int nCancel);
+    void mispredictNewest();
     const bool isEmpty() const { return (m_atom.num == 0); };
 
 private:
@@ -220,6 +260,16 @@
     return nRemove;
 }
 
+// mispredict newest - flip the bit of the newest atom
+inline void TrcStackElemAtom::mispredictNewest()
+{
+    uint32_t mask = 0x1 << (m_atom.num - 1);
+    if (m_atom.En_bits & mask)
+        m_atom.En_bits &= ~mask;
+    else
+        m_atom.En_bits |= mask;
+}
+
 /************************************************************/
 /** Generic param element */
 
@@ -255,12 +305,20 @@
 
     void push_front(TrcStackElem *pElem);
     void push_back(TrcStackElem *pElem);        // insert element when processing
-    void pop_back();
+    void pop_back(bool pend_delete = true);
+    void pop_front(bool pend_delete = true);
     TrcStackElem *back();
+    TrcStackElem *front();
     size_t size();
 
+    // iterate through stack from front
+    void from_front_init();
+    TrcStackElem *from_front_next();
+    void erase_curr_from_front();  // erase the element last returned 
+    
     void delete_all();
     void delete_back();
+    void delete_front();
     void delete_popped();
 
     // creation functions - create and push if successful.
@@ -268,13 +326,13 @@
     TrcStackElem *createParamElemNoParam(const p0_elem_t p0_type, const bool isP0, const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, bool back = false);
     TrcStackElemAtom *createAtomElem (const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const ocsd_pkt_atom &atom);
     TrcStackElemExcept *createExceptElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const bool bSame, const uint16_t excepNum);
-    TrcStackElemCtxt *createContextElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const etmv4_context_t &context, const uint8_t IS);
+    TrcStackElemCtxt *createContextElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const etmv4_context_t &context, const uint8_t IS, const bool back = false);
     TrcStackElemAddr *createAddrElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const etmv4_addr_val_t &addr_val);
-
+    TrcStackQElem *createQElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const int count);
 private:
     std::deque<TrcStackElem *> m_P0_stack;  //!< P0 decode element stack
     std::vector<TrcStackElem *> m_popped_elem;  //!< save list of popped but not deleted elements.
-
+    std::deque<TrcStackElem *>::iterator m_iter;    //!< iterate across the list w/o removing stuff
 };
 
 inline EtmV4P0Stack::~EtmV4P0Stack()
@@ -296,12 +354,20 @@
 }
 
 // pop last element pointer off the stack and stash it for later deletion
-inline void EtmV4P0Stack::pop_back()
+inline void EtmV4P0Stack::pop_back(bool pend_delete /* = true */)
 {
-    m_popped_elem.push_back(m_P0_stack.back());
+    if (pend_delete)
+        m_popped_elem.push_back(m_P0_stack.back());
     m_P0_stack.pop_back();
 }
 
+inline void EtmV4P0Stack::pop_front(bool pend_delete /* = true */)
+{
+    if (pend_delete)
+        m_popped_elem.push_back(m_P0_stack.front());
+    m_P0_stack.pop_front();
+}
+
 // pop last element pointer off the stack and delete immediately
 inline void EtmV4P0Stack::delete_back()
 {
@@ -313,12 +379,30 @@
     }
 }
 
+// pop first element pointer off the stack and delete immediately
+inline void EtmV4P0Stack::delete_front()
+{
+    if (m_P0_stack.size() > 0)
+    {
+        TrcStackElem* pElem = m_P0_stack.front();
+        delete pElem;
+        m_P0_stack.pop_front();
+    }
+}
+
+
+
 // get a pointer to the last element on the stack
 inline TrcStackElem *EtmV4P0Stack::back()
 {
     return m_P0_stack.back();
 }
 
+inline TrcStackElem *EtmV4P0Stack::front()
+{
+    return m_P0_stack.front();
+}
+
 // remove and delete all the elements left on the stack
 inline void EtmV4P0Stack::delete_all()
 {
diff --git a/decoder/include/opencsd/etmv4/trc_pkt_decode_etmv4i.h b/decoder/include/opencsd/etmv4/trc_pkt_decode_etmv4i.h
index c73c97e..c85bf48 100644
--- a/decoder/include/opencsd/etmv4/trc_pkt_decode_etmv4i.h
+++ b/decoder/include/opencsd/etmv4/trc_pkt_decode_etmv4i.h
@@ -40,6 +40,7 @@
 #include "opencsd/etmv4/trc_cmp_cfg_etmv4.h"
 #include "common/trc_gen_elem.h"
 #include "common/trc_ret_stack.h"
+#include "common/ocsd_gen_elem_stack.h"
 #include "opencsd/etmv4/trc_etmv4_stack_elem.h"
 
 class TrcStackElem;
@@ -65,26 +66,34 @@
     /* local decode methods */
     void initDecoder();      // initial state on creation (zeros all config)
     void resetDecoder();     // reset state to start of decode. (moves state, retains config)
+    virtual void onFirstInitOK(); // override to set init related info.
 
-    ocsd_datapath_resp_t decodePacket(bool &Complete);    // return true to indicate decode complete - can change FSM to commit state - return is false.
-    ocsd_datapath_resp_t commitElements(bool &Complete);   // commit elements - may get wait response, or flag completion.
-    ocsd_datapath_resp_t flushEOT();
+    ocsd_err_t decodePacket();    // decode packet into trace elements. return true to indicate decode complete - can change FSM to commit state - return is false.
+    ocsd_datapath_resp_t resolveElements();   // commit/cancel trace elements generated from latest / prior packets & send to output - may get wait response, or flag completion.
+    ocsd_err_t commitElements(); // commit elements - process element stack to generate output packets.
+    ocsd_err_t commitElemOnEOT();
+    ocsd_err_t cancelElements();    // cancel elements. These not output  
+    ocsd_err_t mispredictAtom();    // mispredict an atom
+    ocsd_err_t discardElements();   // discard elements and flush
 
     void doTraceInfoPacket();
-    void updateContext(TrcStackElemCtxt *pCtxtElem);
+    void updateContext(TrcStackElemCtxt *pCtxtElem, OcsdTraceElement &elem);
     
-    // process atom will output instruction trace, or no memory access trace elements. 
-    ocsd_datapath_resp_t processAtom(const ocsd_atm_val, bool &bCont);
+    // process atom will create instruction trace, or no memory access trace output elements. 
+    ocsd_err_t processAtom(const ocsd_atm_val atom);
 
     // process an exception element - output instruction trace + exception generic type.
-    ocsd_datapath_resp_t processException(); 
+    ocsd_err_t processException(); 
+
+    // process an element that cannot be cancelled / discarded
+    ocsd_err_t processTS_CC_EventElem(TrcStackElem *pElem); 
 
     // process a bad packet
-    ocsd_datapath_resp_t handleBadPacket(const char *reason);
+    ocsd_err_t handleBadPacket(const char *reason);
 
-    ocsd_datapath_resp_t outputCC(TrcStackElemParam *pParamElem);
-    ocsd_datapath_resp_t outputTS(TrcStackElemParam *pParamElem, bool withCC);
-    ocsd_datapath_resp_t outputEvent(TrcStackElemParam *pParamElem);
+    ocsd_err_t addElemCC(TrcStackElemParam *pParamElem);
+    ocsd_err_t addElemTS(TrcStackElemParam *pParamElem, bool withCC);
+    ocsd_err_t addElemEvent(TrcStackElemParam *pParamElem);
      
 private:
     void SetInstrInfoInAddrISA(const ocsd_vaddr_t addr_val, const uint8_t isa); 
@@ -94,12 +103,29 @@
             return ocsd_isa_aarch64;
         return (IS == 0) ? ocsd_isa_arm : ocsd_isa_thumb2;
     }
+    typedef enum {
+        WP_NOT_FOUND,
+        WP_FOUND,
+        WP_NACC
+    } WP_res_t;
 
-    ocsd_err_t traceInstrToWP(bool &bWPFound, const bool traceToAddrNext = false, const ocsd_vaddr_t nextAddrMatch = 0);      //!< follow instructions from the current address to a WP. true if good, false if memory cannot be accessed.
+    typedef struct {
+        ocsd_vaddr_t st_addr;
+        ocsd_vaddr_t en_addr;
+        uint32_t num_instr;
+    } instr_range_t;
 
-    ocsd_datapath_resp_t returnStackPop();  // pop return stack and update instruction address.
+    //!< follow instructions from the current address to a WP. true if good, false if memory cannot be accessed.
+    ocsd_err_t traceInstrToWP(instr_range_t &instr_range, WP_res_t &WPRes, const bool traceToAddrNext = false, const ocsd_vaddr_t nextAddrMatch = 0);
 
-    ocsd_datapath_resp_t outputTraceRange(const bool executed, ocsd_trc_index_t index);
+    inline const bool WPFound(WP_res_t res) const { return (res == WP_FOUND); };
+    inline const bool WPNacc(WP_res_t res) const { return (res == WP_NACC); };
+        
+    ocsd_err_t returnStackPop();  // pop return stack and update instruction address.
+
+    void setElemTraceRange(OcsdTraceElement &elemIn, const instr_range_t &addr_range, const bool executed, ocsd_trc_index_t index);
+
+    ocsd_mem_space_acc_t getCurrMemSpace();
 
 //** intra packet state (see ETMv4 spec 6.2.1);
 
@@ -116,10 +142,13 @@
     // cycle counts 
     int m_cc_threshold;
 
-    // speculative trace (unsupported at present in the decoder).
+    // speculative trace 
     int m_curr_spec_depth;                
-    int m_max_spec_depth; 
-    
+    int m_max_spec_depth;   // nax depth - from ID reg, beyond which auto-commit occurs 
+    int m_unseen_spec_elem; // speculative elements at decode start
+
+/** Remove elements that are associated with data trace */
+#ifdef DATA_TRACE_SUPPORTED
     // data trace associative elements (unsupported at present in the decoder).
     int m_p0_key;
     int m_p0_key_max;
@@ -128,6 +157,7 @@
     int m_cond_c_key;
     int m_cond_r_key;
     int m_cond_key_max_incr;
+#endif
 
     uint8_t m_CSID; //!< Coresight trace ID for this decoder.
 
@@ -141,55 +171,53 @@
         WAIT_SYNC,      //!< waiting for sync packet.
         WAIT_TINFO,     //!< waiting for trace info packet.
         DECODE_PKTS,    //!< processing packets - creating decode elements on stack
-        COMMIT_ELEM,    //!< commit elements for execution - create generic trace elements and pass on.
+        RESOLVE_ELEM,   //!< analyze / resolve decode elements - create generic trace elements and pass on.
     } processor_state_t;
 
     processor_state_t m_curr_state;
+    unsync_info_t m_unsync_eot_info;   //!< addition info when / why unsync / eot
 
 //** P0 element stack
     EtmV4P0Stack m_P0_stack;    //!< P0 decode element stack
 
-    int m_P0_commit;    //!< number of elements to commit
+    // element resolution
+    struct {
+        int P0_commit;    //!< number of elements to commit
+        int P0_cancel;    //!< elements to cancel
+        bool mispredict;  //!< mispredict latest atom
+        bool discard;     //!< discard elements 
+    } m_elem_res;
+
+    //! true if any of the element resolution fields are non-zero
+    const bool isElemForRes() const {
+        return (m_elem_res.P0_commit || m_elem_res.P0_cancel || 
+            m_elem_res.mispredict || m_elem_res.discard);
+    }
+
+    void clearElemRes() {
+        m_elem_res.P0_commit = 0;
+        m_elem_res.P0_cancel = 0;
+        m_elem_res.mispredict = false;
+        m_elem_res.discard = false;
+    }
 
     // packet decode state
     bool m_need_ctxt;   //!< need context to continue
     bool m_need_addr;   //!< need an address to continue
-    bool m_except_pending_addr;    //!< next address packet is part of exception.
-
-    // exception packet processing state (may need excep elem only, range+excep, range+
-    typedef enum {
-        EXCEP_POP, // start of processing read exception packets off the stack and analyze
-        EXCEP_RANGE, // output a range element
-        EXCEP_NACC,  // output a nacc element
-        EXCEP_CTXT,  // output a ctxt element
-        EXCEP_EXCEP, // output an ecxeption element.
-    } excep_proc_state_t;
-
-    struct {
-        excep_proc_state_t proc;    //!< state of exception processing
-        etmv4_addr_val_t addr;      //!< excetion return address.
-        uint32_t number;            //!< exception number.
-        ocsd_trc_index_t index;     //!< trace index for exception element
-        bool addr_b_tgt;            //!< return address is also branch tgt address.
-    } m_excep_info; //!< exception info when processing exception packets
+    bool m_elem_pending_addr;    //!< next address packet is needed for prev element.
 
     ocsd_instr_info m_instr_info;  //!< instruction info for code follower - in address is the next to be decoded.
 
-    bool m_mem_nacc_pending;    //!< need to output a memory access failure packet
-    ocsd_vaddr_t m_nacc_addr;  //!< record unaccessible address 
-
     ocsd_pe_context m_pe_context;  //!< current context information
     etmv4_trace_info_t m_trace_info; //!< trace info for this trace run.
 
     bool m_prev_overflow;
 
-    bool m_flush_EOT;           //!< true if doing an end of trace flush - cleans up lingering events / TS / CC
+    TrcAddrReturnStack m_return_stack;  //!< the address return stack.
 
-    TrcAddrReturnStack m_return_stack;
-
-//** output element
-    OcsdTraceElement m_output_elem;
-
+//** output element handling
+    OcsdGenElemStack m_out_elem;  //!< output element stack.
+    OcsdTraceElement &outElem() { return m_out_elem.getCurrElem(); };   //!< current  out element
 };
 
 #endif // ARM_TRC_PKT_DECODE_ETMV4I_H_INCLUDED
diff --git a/decoder/include/opencsd/etmv4/trc_pkt_elem_etmv4d.h b/decoder/include/opencsd/etmv4/trc_pkt_elem_etmv4d.h
deleted file mode 100644
index bb6a002..0000000
--- a/decoder/include/opencsd/etmv4/trc_pkt_elem_etmv4d.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * \file       trc_pkt_elem_etmv4d.h
- * \brief      OpenCSD : 
- * 
- * \copyright  Copyright (c) 2015, ARM Limited. All Rights Reserved.
- */
-
-/* 
- * Redistribution and use in source and binary forms, with or without modification, 
- * are permitted provided that the following conditions are met:
- * 
- * 1. Redistributions of source code must retain the above copyright notice, 
- * this list of conditions and the following disclaimer.
- * 
- * 2. Redistributions in binary form must reproduce the above copyright notice, 
- * this list of conditions and the following disclaimer in the documentation 
- * and/or other materials provided with the distribution. 
- * 
- * 3. Neither the name of the copyright holder nor the names of its contributors 
- * may be used to endorse or promote products derived from this software without 
- * specific prior written permission. 
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND 
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */ 
-
-#ifndef ARM_TRC_PKT_ELEM_ETMV4D_H_INCLUDED
-#define ARM_TRC_PKT_ELEM_ETMV4D_H_INCLUDED
-
-#include "trc_pkt_types_etmv4.h"
-#include "common/trc_printable_elem.h"
-#include "common/trc_pkt_elem_base.h"
-
-/** @addtogroup trc_pkts
-@{*/
-/*!
- * @class EtmV4DTrcPacket   
- * @brief ETMv4 Data Trace Protocol Packet .
- * 
- *  This class represents a single ETMv4 instruction trace packet, along with intra packet state.
- * 
- */
-class EtmV4DTrcPacket :  public TrcPacketBase, public ocsd_etmv4_d_pkt, trcPrintableElem
-{
-public:
-    EtmV4DTrcPacket();
-    ~EtmV4DTrcPacket();
-
-    // update interface - set packet values
-
-
-
-    // packet status interface - get packet info.
-
-
-    // printing
-    virtual void toString(std::string &str) const;
-    virtual void toStringFmt(const uint32_t fmtFlags, std::string &str) const;
-};
-
-/** @}*/
-
-#endif // ARM_TRC_PKT_ELEM_ETMV4D_H_INCLUDED
-
-/* End of File trc_pkt_elem_etmv4d.h */
diff --git a/decoder/include/opencsd/etmv4/trc_pkt_elem_etmv4i.h b/decoder/include/opencsd/etmv4/trc_pkt_elem_etmv4i.h
index 02adfc5..8ccf36b 100644
--- a/decoder/include/opencsd/etmv4/trc_pkt_elem_etmv4i.h
+++ b/decoder/include/opencsd/etmv4/trc_pkt_elem_etmv4i.h
@@ -57,14 +57,7 @@
 public:
     Etmv4PktAddrStack()
     {
-        for (int i = 0; i < 3; i++)
-        {
-            m_v_addr[i].pkt_bits = 0;
-            m_v_addr[i].size = VA_64BIT;
-            m_v_addr[i].val = 0;
-            m_v_addr[i].valid_bits = 0;
-            m_v_addr_ISA[i] = 0;
-        }
+        reset_stack();
     }
     ~Etmv4PktAddrStack() {};
 
@@ -87,6 +80,20 @@
         }
     }
 
+    // explicit reset for TInfo.
+    void reset_stack()
+    {
+        for (int i = 0; i < 3; i++)
+        {
+            m_v_addr[i].pkt_bits = 0;
+            m_v_addr[i].size = OCSD_MAX_VA_BITSIZE == 64 ? VA_64BIT : VA_32BIT;
+            m_v_addr[i].val = 0;
+            m_v_addr[i].valid_bits = OCSD_MAX_VA_BITSIZE;
+            m_v_addr_ISA[i] = 0;
+        }
+
+    }
+
 private:
     ocsd_pkt_vaddr m_v_addr[3];         //!< most recently broadcast address packet
     uint8_t        m_v_addr_ISA[3];
@@ -172,6 +179,7 @@
 
     // atom
     const ocsd_pkt_atom &getAtom() const { return atom; };
+    const int getNumAtoms() const { return atom.num; };
 
     // context
     const etmv4_context_t &getContext() const { return context; };
@@ -188,6 +196,10 @@
     // cc
     const uint32_t getCC() const { return pkt_valid.bits.cc_valid ? cycle_count : 0; };
 
+    // speculation
+    const int getCommitElem() const { return commit_elements; };
+    const int getCancelElem() const { return cancel_elements; };
+
     // packet type
     const bool isBadPacket() const;
 
@@ -227,6 +239,10 @@
     // set these as defaults - if they don't appear in TINFO this is the state.
     setTraceInfo(0);        
     setTraceInfoSpec(0);   
+
+    // explicitly reset the stack & zero the current address. 
+    m_addr_stack.reset_stack();
+    m_addr_stack.get_idx(0, v_addr, v_addr_ISA);
 }
 
 inline void EtmV4ITrcPacket::setTraceInfo(const uint32_t infoVal)
@@ -450,17 +466,17 @@
 	if (pkt_valid.bits.context_valid && context.SF)
 	{
 		v_addr.size = VA_64BIT;
-		if (v_addr.valid_bits < 32) // may be updating a 64 bit address so only set 32 if currently less.
-			v_addr.valid_bits = 32;
 		v_addr.val = (v_addr.val & ~mask) | (addr & mask);
 	}
     else
     {
 		v_addr.val = addr;
         v_addr.size = VA_32BIT;
-		v_addr.valid_bits = 32;
 	}
-	    
+
+    if (v_addr.valid_bits < 32) // may be updating a 64 bit address so only set 32 if currently less.
+        v_addr.valid_bits = 32;
+
     v_addr_ISA = IS;
     push_vaddr();
 }
diff --git a/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4.h b/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4.h
index 0d9ccea..25bdf51 100644
--- a/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4.h
+++ b/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4.h
@@ -35,70 +35,13 @@
 #ifndef ARM_TRC_PKT_PROC_ETMV4_H_INCLUDED
 #define ARM_TRC_PKT_PROC_ETMV4_H_INCLUDED
 
+// split I & D into separate files, retain this header for backward compatibility
+// for now just include the I packet processor as that is the only one implemented.
 
 #include "trc_pkt_types_etmv4.h"
+#include "trc_pkt_proc_etmv4i.h"
 #include "common/trc_pkt_proc_base.h"
 
-class EtmV4IPktProcImpl;    /**< ETMv4 I channel packet processor */
-class EtmV4DPktProcImpl;    /**< ETMv4 D channel packet processor */
-class EtmV4ITrcPacket;
-class EtmV4DTrcPacket;
-class EtmV4Config;
-
-/** @addtogroup ocsd_pkt_proc
-@{*/
-
-class TrcPktProcEtmV4I : public TrcPktProcBase< EtmV4ITrcPacket,  ocsd_etmv4_i_pkt_type, EtmV4Config>
-{
-public:
-    TrcPktProcEtmV4I();
-    TrcPktProcEtmV4I(int instIDNum);
-    virtual ~TrcPktProcEtmV4I();
-
-protected:
-    /* implementation packet processing interface */
-    virtual ocsd_datapath_resp_t processData(  const ocsd_trc_index_t index,
-                                                const uint32_t dataBlockSize,
-                                                const uint8_t *pDataBlock,
-                                                uint32_t *numBytesProcessed);
-    virtual ocsd_datapath_resp_t onEOT();
-    virtual ocsd_datapath_resp_t onReset();
-    virtual ocsd_datapath_resp_t onFlush();
-    virtual ocsd_err_t onProtocolConfig();
-    virtual const bool isBadPacket() const;
-
-    friend class EtmV4IPktProcImpl;
-
-    EtmV4IPktProcImpl *m_pProcessor;
-};
-
-
-class TrcPktProcEtmV4D : public TrcPktProcBase< EtmV4DTrcPacket,  ocsd_etmv4_d_pkt_type, EtmV4Config>
-{
-public:
-    TrcPktProcEtmV4D();
-    TrcPktProcEtmV4D(int instIDNum);
-    virtual ~TrcPktProcEtmV4D();
-
-protected:
-    /* implementation packet processing interface */
-    virtual ocsd_datapath_resp_t processData(  const ocsd_trc_index_t index,
-                                                const uint32_t dataBlockSize,
-                                                const uint8_t *pDataBlock,
-                                                uint32_t *numBytesProcessed);
-    virtual ocsd_datapath_resp_t onEOT();
-    virtual ocsd_datapath_resp_t onReset();
-    virtual ocsd_datapath_resp_t onFlush();
-    virtual ocsd_err_t onProtocolConfig();
-    virtual const bool isBadPacket() const;
-
-    friend class EtmV4DPktProcImpl;
-
-    EtmV4DPktProcImpl *m_pProcessor;
-};
-
-/** @}*/
-
 #endif // ARM_TRC_PKT_PROC_ETMV4_H_INCLUDED
 
 /* End of File trc_pkt_proc_etmv4.h */
diff --git a/decoder/source/etmv4/trc_pkt_proc_etmv4i_impl.h b/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4i.h
similarity index 82%
rename from decoder/source/etmv4/trc_pkt_proc_etmv4i_impl.h
rename to decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4i.h
index 429f327..abc3226 100644
--- a/decoder/source/etmv4/trc_pkt_proc_etmv4i_impl.h
+++ b/decoder/include/opencsd/etmv4/trc_pkt_proc_etmv4i.h
@@ -1,8 +1,8 @@
 /*
- * \file       trc_pkt_proc_etmv4i_impl.h
+ * \file       trc_pkt_proc_etmv4i.h
  * \brief      OpenCSD : Implementation of ETMv4 packet processing
  * 
- * \copyright  Copyright (c) 2015, ARM Limited. All Rights Reserved.
+ * \copyright  Copyright (c) 2015, 2019 ARM Limited. All Rights Reserved.
  */
 
 /* 
@@ -35,54 +35,37 @@
 #ifndef ARM_TRC_PKT_PROC_ETMV4I_IMPL_H_INCLUDED
 #define ARM_TRC_PKT_PROC_ETMV4I_IMPL_H_INCLUDED
 
+#include "trc_pkt_types_etmv4.h"
 #include "opencsd/etmv4/trc_pkt_proc_etmv4.h"
 #include "opencsd/etmv4/trc_cmp_cfg_etmv4.h"
 #include "opencsd/etmv4/trc_pkt_elem_etmv4i.h"
+#include "common/trc_raw_buffer.h"
+#include "common/trc_pkt_proc_base.h"
 
-class TraceRawBuffer
+class EtmV4ITrcPacket;
+class EtmV4Config;
+
+/** @addtogroup ocsd_pkt_proc
+@{*/
+
+class TrcPktProcEtmV4I : public TrcPktProcBase< EtmV4ITrcPacket, ocsd_etmv4_i_pkt_type, EtmV4Config>
 {
 public:
-    TraceRawBuffer();
-    ~TraceRawBuffer() {};
+    TrcPktProcEtmV4I();
+    TrcPktProcEtmV4I(int instIDNum);
+    virtual ~TrcPktProcEtmV4I();
 
-    // init the buffer
-    void init(const uint32_t size, const uint8_t *rawtrace, std::vector<uint8_t> *out_packet);
-    void copyByteToPkt();   // move a byte to the packet buffer     
-    uint8_t peekNextByte(); // value of next byte in buffer.
-
-    bool empty() { return m_bufProcessed == m_bufSize; };
-    // bytes processed.
-    uint32_t processed() { return m_bufProcessed; }; 
-    // buffer size;
-    uint32_t size() { return m_bufSize; } 
-
-private:
-    uint32_t m_bufSize;
-    uint32_t m_bufProcessed;
-    const uint8_t *m_pBuffer;
-    std::vector<uint8_t> *pkt;
-
-};
-
-class EtmV4IPktProcImpl
-{
-public:
-    EtmV4IPktProcImpl();
-    ~EtmV4IPktProcImpl();
-
-    void Initialise(TrcPktProcEtmV4I *p_interface);
-
-    ocsd_err_t Configure(const EtmV4Config *p_config);
-
-
-    ocsd_datapath_resp_t processData(  const ocsd_trc_index_t index,
+protected:
+    /* implementation packet processing interface */
+    virtual ocsd_datapath_resp_t processData(  const ocsd_trc_index_t index,
                                         const uint32_t dataBlockSize,
                                         const uint8_t *pDataBlock,
                                         uint32_t *numBytesProcessed);
-    ocsd_datapath_resp_t onEOT();
-    ocsd_datapath_resp_t onReset();
-    ocsd_datapath_resp_t onFlush();
-    const bool isBadPacket() const;
+    virtual ocsd_datapath_resp_t onEOT();
+    virtual ocsd_datapath_resp_t onReset();
+    virtual ocsd_datapath_resp_t onFlush();
+    virtual ocsd_err_t onProtocolConfig();
+    virtual const bool isBadPacket() const;
 
 protected:
     typedef enum _process_state {
@@ -100,7 +83,6 @@
 
     /** packet processor configuration **/
     bool m_isInit;
-    TrcPktProcEtmV4I *m_interface;       /**< The interface to the other decode components */
 
     // etmv4 hardware configuration
     EtmV4Config m_config;
@@ -111,7 +93,6 @@
     int m_currPktIdx;   // index into raw packet when expanding
     EtmV4ITrcPacket m_curr_packet;  // expanded packet
     ocsd_trc_index_t m_packet_index;   // index of the start of the current packet
-//    uint32_t m_blockBytesProcessed;     // number of bytes processed in the current data block
     ocsd_trc_index_t m_blockIndex;     // index at the start of the current data block being processed
 
     // searching for sync
@@ -207,7 +188,7 @@
     int extractShortAddr(const std::vector<uint8_t> &buffer, const int st_idx, const uint8_t IS, uint32_t &value, int &bits);
 
     // packet processing is table driven.    
-    typedef void (EtmV4IPktProcImpl::*PPKTFN)(uint8_t);
+    typedef void (TrcPktProcEtmV4I::*PPKTFN)(uint8_t);
     PPKTFN m_pIPktFn;
 
     struct _pkt_i_table_t {
@@ -221,11 +202,13 @@
 };
 
 
-inline const bool EtmV4IPktProcImpl::isBadPacket() const
+inline const bool TrcPktProcEtmV4I::isBadPacket() const
 {
     return m_curr_packet.isBadPacket();
 }
 
+/** @}*/
+
 #endif // ARM_TRC_PKT_PROC_ETMV4I_IMPL_H_INCLUDED
 
 /* End of File trc_pkt_proc_etmv4i_impl.h */
diff --git a/decoder/include/opencsd/etmv4/trc_pkt_types_etmv4.h b/decoder/include/opencsd/etmv4/trc_pkt_types_etmv4.h
index dd69a4b..7e98050 100644
--- a/decoder/include/opencsd/etmv4/trc_pkt_types_etmv4.h
+++ b/decoder/include/opencsd/etmv4/trc_pkt_types_etmv4.h
@@ -85,7 +85,8 @@
 
     // speculation 
         ETM4_PKT_I_COMMIT =             0x2D,   /*!< b00101101 */
-        ETM4_PKT_I_CANCEL_F1 =          0x2E,   /*!< b0010111x */
+        ETM4_PKT_I_CANCEL_F1 =          0x2E,   /*!< b00101110 */
+        ETM4_PKT_I_CANCEL_F1_MISPRED =  0x2F,   /*!< b00101111 */
         ETM4_PKT_I_MISPREDICT =         0x30,   /*!< b001100xx */
         ETM4_PKT_I_CANCEL_F2 =          0x34,   /*!< b001101xx */
         ETM4_PKT_I_CANCEL_F3 =          0x38,   /*!< b00111xxx */
diff --git a/decoder/include/opencsd/ocsd_if_types.h b/decoder/include/opencsd/ocsd_if_types.h
index 7d74d77..1c0e631 100644
--- a/decoder/include/opencsd/ocsd_if_types.h
+++ b/decoder/include/opencsd/ocsd_if_types.h
@@ -430,9 +430,10 @@
     OCSD_MEM_SPACE_EL1N = 0x2, /**< NS EL1/0 */
     OCSD_MEM_SPACE_EL2 =  0x4, /**< NS EL2   */
     OCSD_MEM_SPACE_EL3 =  0x8, /**<  S EL3   */
-    OCSD_MEM_SPACE_S =    0x9, /**< Any  S   */
+    OCSD_MEM_SPACE_EL2S = 0x10, /**< S EL2   */
+    OCSD_MEM_SPACE_S =    0x19, /**< Any  S  */
     OCSD_MEM_SPACE_N =    0x6, /**< Any NS   */
-    OCSD_MEM_SPACE_ANY =  0xF, /**< Any sec level / EL - live system use current EL + sec state */
+    OCSD_MEM_SPACE_ANY =  0x1F, /**< Any sec level / EL - live system use current EL + sec state */
 } ocsd_mem_space_acc_t;
 
 /**
@@ -494,13 +495,14 @@
 
 /** @name Packet Processor Operation Control Flags
     common operational flags - bottom 16 bits,
-    component specific - top 16 bits.
+    protocol component specific - top 16 bits.
+    (common flags share bitfield with pkt decoder common flags and create flags)
 @{*/
 
-#define OCSD_OPFLG_PKTPROC_NOFWD_BAD_PKTS  0x00000001  /**< don't forward bad packets up data path */
-#define OCSD_OPFLG_PKTPROC_NOMON_BAD_PKTS  0x00000002  /**< don't forward bad packets to monitor interface */
-#define OCSD_OPFLG_PKTPROC_ERR_BAD_PKTS    0x00000004  /**< throw error for bad packets - halt decoding. */
-#define OCSD_OPFLG_PKTPROC_UNSYNC_ON_BAD_PKTS 0x00000008  /**< switch to unsynced state on bad packets - wait for next sync point */
+#define OCSD_OPFLG_PKTPROC_NOFWD_BAD_PKTS  0x00000010  /**< don't forward bad packets up data path */
+#define OCSD_OPFLG_PKTPROC_NOMON_BAD_PKTS  0x00000020  /**< don't forward bad packets to monitor interface */
+#define OCSD_OPFLG_PKTPROC_ERR_BAD_PKTS    0x00000040  /**< throw error for bad packets - halt decoding. */
+#define OCSD_OPFLG_PKTPROC_UNSYNC_ON_BAD_PKTS 0x00000080  /**< switch to unsynced state on bad packets - wait for next sync point */
 
 /** mask to combine all common packet processor operational control flags */
 #define OCSD_OPFLG_PKTPROC_COMMON (OCSD_OPFLG_PKTPROC_NOFWD_BAD_PKTS | \
@@ -508,14 +510,18 @@
                                     OCSD_OPFLG_PKTPROC_ERR_BAD_PKTS | \
                                     OCSD_OPFLG_PKTPROC_UNSYNC_ON_BAD_PKTS  )
 
+/** mask for the component spcific flags */
+#define OCSD_OPFLG_COMP_MODE_MASK 0xFFFF0000
+
 /** @}*/
 
 /** @name Packet Decoder Operation Control Flags
     common operational flags - bottom 16 bits,
-    component specific - top 16 bits.
-@{*/
+    protcol component specific - top 16 bits.
+    (common flags share bitfield with pkt processor common flags and create flags)
+    @{*/
 
-#define OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS  0x00000001  /**< throw error on bad packets input (default is to unsync and wait) */
+#define OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS  0x00000100  /**< throw error on bad packets input (default is to unsync and wait) */
 
 /** mask to combine all common packet processor operational control flags */
 #define OCSD_OPFLG_PKTDEC_COMMON (OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS)
@@ -524,7 +530,8 @@
 
 /** @name Decoder creation information
 
-    Flags to use when creating decoders by name
+    Flags to use when creating decoders by name.
+    - share bitfield with pkt processor flags and packet decoder common flags.
 
     Builtin decoder names.
 
diff --git a/decoder/include/opencsd/ocsd_if_version.h b/decoder/include/opencsd/ocsd_if_version.h
index 31e4ffc..ad8d710 100644
--- a/decoder/include/opencsd/ocsd_if_version.h
+++ b/decoder/include/opencsd/ocsd_if_version.h
@@ -43,8 +43,8 @@
 /** @name Library Versioning
 @{*/
 #define OCSD_VER_MAJOR 0x0 /**< Library Major Version */
-#define OCSD_VER_MINOR 0xC /**< Library Minor Version */
-#define OCSD_VER_PATCH 0x1 /**< Library Patch Version */
+#define OCSD_VER_MINOR 0xE /**< Library Minor Version */
+#define OCSD_VER_PATCH 0x0 /**< Library Patch Version */
 
 /** Library version number - MMMMnnpp format.
     MMMM = major version, 
@@ -53,7 +53,7 @@
 */
 #define OCSD_VER_NUM ((OCSD_VER_MAJOR << 16) | (OCSD_VER_MINOR << 8) | OCSD_VER_PATCH) 
 
-#define OCSD_VER_STRING "0.12.1"    /**< Library Version string */
+#define OCSD_VER_STRING "0.14.0"    /**< Library Version string */
 #define OCSD_LIB_NAME "OpenCSD Library"  /**< Library name string */
 #define OCSD_LIB_SHORT_NAME "OCSD"    /**< Library Short name string */
 /** @}*/
diff --git a/decoder/include/opencsd/ptm/trc_pkt_decode_ptm.h b/decoder/include/opencsd/ptm/trc_pkt_decode_ptm.h
index 395b316..f9e1abe 100644
--- a/decoder/include/opencsd/ptm/trc_pkt_decode_ptm.h
+++ b/decoder/include/opencsd/ptm/trc_pkt_decode_ptm.h
@@ -154,6 +154,7 @@
     } processor_state_t;
 
     processor_state_t m_curr_state;
+    unsync_info_t m_unsync_info;
 
     const bool processStateIsCont() const;
 
diff --git a/decoder/include/opencsd/stm/trc_pkt_decode_stm.h b/decoder/include/opencsd/stm/trc_pkt_decode_stm.h
index a480720..bd29caf 100644
--- a/decoder/include/opencsd/stm/trc_pkt_decode_stm.h
+++ b/decoder/include/opencsd/stm/trc_pkt_decode_stm.h
@@ -79,6 +79,7 @@
     } processor_state_t;
 
     processor_state_t m_curr_state;  
+    unsync_info_t m_unsync_info;
 
     ocsd_swt_info_t m_swt_packet_info;
 
diff --git a/decoder/include/opencsd/trc_gen_elem_types.h b/decoder/include/opencsd/trc_gen_elem_types.h
index 1d77b53..1a285a0 100644
--- a/decoder/include/opencsd/trc_gen_elem_types.h
+++ b/decoder/include/opencsd/trc_gen_elem_types.h
@@ -52,6 +52,7 @@
     OCSD_GEN_TRC_ELEM_EO_TRACE,        /*!< end of the available trace in the buffer.  */
     OCSD_GEN_TRC_ELEM_PE_CONTEXT,      /*!< PE status update / change (arch, ctxtid, vmid etc).  */
     OCSD_GEN_TRC_ELEM_INSTR_RANGE,     /*!< traced N consecutive instructions from addr (no intervening events or data elements), may have data assoc key  */
+    OCSD_GEN_TRC_ELEM_I_RANGE_NOPATH,  /*!< traced N instructions in a range, but incomplete information as to program execution path from start to end of range */
     OCSD_GEN_TRC_ELEM_ADDR_NACC,       /*!< tracing in inaccessible memory area  */ 
     OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN,    /*!< address currently unknown - need address packet update */
     OCSD_GEN_TRC_ELEM_EXCEPTION,       /*!< exception - start address may be exception target, end address may be preferred ret addr. */
@@ -75,6 +76,16 @@
     uint16_t ev_number;        /**< event number if numbered event type */
 } trace_event_t;
 
+typedef enum _unsync_info_t {
+    UNSYNC_UNKNOWN,         /**< unknown /undefined */
+    UNSYNC_INIT_DECODER,    /**< decoder intialisation - start of trace. */
+    UNSYNC_RESET_DECODER,   /**< decoder reset. */
+    UNSYNC_OVERFLOW,        /**< overflow packet - need to re-sync / end of trace after overflow. */
+    UNSYNC_DISCARD,         /**< specl trace discard - need to re-sync. */
+    UNSYNC_BAD_PACKET,      /**< bad packet at input - resync to restart. */
+    UNSYNC_EOT,             /**< end of trace - no additional info */
+} unsync_info_t;
+
 typedef struct _ocsd_generic_trace_elem {
     ocsd_gen_trc_elem_t elem_type;   /**< Element type - remaining data interpreted according to this value */
     ocsd_isa           isa;          /**< instruction set for executed instructions */
@@ -110,6 +121,7 @@
         trace_on_reason_t trace_on_reason;  /**< reason for the trace on packet */
         ocsd_swt_info_t sw_trace_info;      /**< software trace packet info    */
 		uint32_t num_instr_range;	        /**< number of instructions covered by range packet (for T32 this cannot be calculated from en-st/i_size) */
+        unsync_info_t unsync_eot_info;      /**< additional information for unsync / end-of-trace packets. */
     };
 
     const void *ptr_extended_data;        /**< pointer to extended data buffer (data trace, sw trace payload) / custom structure */
diff --git a/decoder/source/etmv3/trc_pkt_decode_etmv3.cpp b/decoder/source/etmv3/trc_pkt_decode_etmv3.cpp
index 0a15a33..e68a73f 100644
--- a/decoder/source/etmv3/trc_pkt_decode_etmv3.cpp
+++ b/decoder/source/etmv3/trc_pkt_decode_etmv3.cpp
@@ -130,6 +130,7 @@
     try {
         pElem = GetNextOpElem(resp);
         pElem->setType(OCSD_GEN_TRC_ELEM_EO_TRACE);
+        pElem->setUnSyncEOTReason(UNSYNC_EOT);
         m_outputElemList.commitAllPendElem();
         m_curr_state = SEND_PKTS;
         resp = m_outputElemList.sendElements();
@@ -147,6 +148,7 @@
 ocsd_datapath_resp_t TrcPktDecodeEtmV3::onReset()
 {
     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
+    m_unsync_info = UNSYNC_RESET_DECODER;
     resetDecoder();
     return resp;
 }
@@ -199,6 +201,7 @@
 {
     m_CSID = 0;
     resetDecoder();
+    m_unsync_info = UNSYNC_INIT_DECODER;
     m_code_follower.initInterfaces(getMemoryAccessAttachPt(),getInstrDecodeAttachPt());
     m_outputElemList.initSendIf(getTraceElemOutAttachPt());
 }
@@ -355,6 +358,7 @@
     catch(ocsdError &err)
     {
         LogError(err);
+        m_unsync_info = UNSYNC_BAD_PACKET;
         resetDecoder(); // mark decoder as unsynced - dump any current state.
         pktDone = true;
     }
@@ -362,6 +366,7 @@
     {
         LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_FAIL,m_index_curr_pkt,m_CSID,"Bad Packet sequence."));
         resp = OCSD_RESP_FATAL_SYS_ERR;
+        m_unsync_info = UNSYNC_BAD_PACKET;
         resetDecoder(); // mark decoder as unsynced - dump any current state.
         pktDone = true;
     }
@@ -375,11 +380,13 @@
     try {
         pElem = GetNextOpElem(resp);
         pElem->setType(OCSD_GEN_TRC_ELEM_NO_SYNC);
+        pElem->setUnSyncEOTReason(m_unsync_info);
         resp = m_outputElemList.sendElements();
     }
     catch(ocsdError &err)
     {
         LogError(err);
+        m_unsync_info = UNSYNC_BAD_PACKET;
         resetDecoder(); // mark decoder as unsynced - dump any current state.
     }
     return resp;
@@ -464,6 +471,7 @@
     catch(ocsdError &err)
     {
         LogError(err);
+        m_unsync_info = UNSYNC_BAD_PACKET;
         resetDecoder(); // mark decoder as unsynced - dump any current state.
     }
     return resp;
@@ -531,6 +539,7 @@
         catch(ocsdError &err)
         {
             LogError(err);
+            m_unsync_info = UNSYNC_BAD_PACKET;
             resetDecoder(); // mark decoder as unsynced - dump any current state.
         }
     }       
@@ -647,6 +656,7 @@
     catch(ocsdError &err)
     {
         LogError(err);
+        m_unsync_info = UNSYNC_BAD_PACKET;
         resetDecoder(); // mark decoder as unsynced - dump any current state.
     }
     return resp;
diff --git a/decoder/source/etmv4/trc_etmv4_stack_elem.cpp b/decoder/source/etmv4/trc_etmv4_stack_elem.cpp
index 0abdc31..8e9ba9a 100644
--- a/decoder/source/etmv4/trc_etmv4_stack_elem.cpp
+++ b/decoder/source/etmv4/trc_etmv4_stack_elem.cpp
@@ -90,14 +90,17 @@
     return pElem;
 }
 
-TrcStackElemCtxt *EtmV4P0Stack::createContextElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const etmv4_context_t &context, const uint8_t IS)
+TrcStackElemCtxt *EtmV4P0Stack::createContextElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const etmv4_context_t &context, const uint8_t IS, const bool back /*= false*/)
 {
     TrcStackElemCtxt *pElem = new (std::nothrow) TrcStackElemCtxt(root_pkt, root_index);
     if (pElem)
     {
         pElem->setContext(context);
         pElem->setIS(IS);
-        push_front(pElem);
+        if (back)
+            push_back(pElem);
+        else
+            push_front(pElem);
     }
     return pElem;
 
@@ -114,4 +117,40 @@
     return pElem;
 }
 
+TrcStackQElem *EtmV4P0Stack::createQElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const int count)
+{
+    TrcStackQElem *pElem = new (std::nothrow) TrcStackQElem(root_pkt, root_index);
+    if (pElem)
+    {
+        pElem->setInstrCount(count);
+        push_front(pElem);
+    }
+    return pElem;
+}
+
+// iteration functions
+void EtmV4P0Stack::from_front_init()
+{
+    m_iter = m_P0_stack.begin();
+}
+
+TrcStackElem *EtmV4P0Stack::from_front_next()
+{
+    TrcStackElem *pElem = 0;
+    if (m_iter != m_P0_stack.end())
+    {
+        pElem = *m_iter++;
+    }
+    return pElem;
+}
+
+void EtmV4P0Stack::erase_curr_from_front()
+{
+    std::deque<TrcStackElem *>::iterator erase_iter;
+    erase_iter = m_iter;
+    erase_iter--;
+    m_P0_stack.erase(erase_iter);
+}
+
+
 /* End of file trc_etmv4_stack_elem.cpp */
diff --git a/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp b/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp
index 700d2a1..d429f21 100644
--- a/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp
+++ b/decoder/source/etmv4/trc_pkt_decode_etmv4i.cpp
@@ -5,7 +5,6 @@
  * \copyright  Copyright (c) 2015, ARM Limited. All Rights Reserved.
  */
 
-
 /* 
  * Redistribution and use in source and binary forms, with or without modification, 
  * are permitted provided that the following conditions are met:
@@ -63,6 +62,7 @@
 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processPacket()
 {
     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
+    ocsd_err_t err = OCSD_OK;
     bool bPktDone = false;
 
     while(!bPktDone)
@@ -71,9 +71,18 @@
         {
         case NO_SYNC:
             // output the initial not synced packet to the sink
-            m_output_elem.setType(OCSD_GEN_TRC_ELEM_NO_SYNC);
-            resp = outputTraceElement(m_output_elem);
-            m_curr_state = WAIT_SYNC;
+            err = m_out_elem.resetElemStack();
+            if (!err)
+                err = m_out_elem.addElemType(m_index_curr_pkt, OCSD_GEN_TRC_ELEM_NO_SYNC);
+            if (!err)
+            {
+                outElem().setUnSyncEOTReason(m_unsync_eot_info);
+                resp = m_out_elem.sendElements();
+                m_curr_state = WAIT_SYNC;
+            }
+            else
+                resp = OCSD_RESP_FATAL_SYS_ERR;
+
             // fall through to check if the current packet is the async we are waiting for.
             break;
 
@@ -96,13 +105,31 @@
             break;
 
         case DECODE_PKTS:
-            resp = decodePacket(bPktDone);  // this may change the state to commit elem;
+            // this may change the state to RESOLVE_ELEM if required;
+            err = decodePacket();
+            if (err)
+            {
+#ifdef OCSD_WARN_UNSUPPORTED
+                if (err == OCSD_ERR_UNSUPP_DECODE_PKT)
+                    resp = OCSD_RESP_WARN_CONT;
+                else
+#else
+                resp = OCSD_RESP_FATAL_INVALID_DATA;
+#endif
+
+                bPktDone = true;
+            }
+            else if (m_curr_state != RESOLVE_ELEM)
+                bPktDone = true;
             break;
 
-        case COMMIT_ELEM:
-            resp = commitElements(bPktDone); // this will change the state to DECODE_PKTS once all elem committed.
+        case RESOLVE_ELEM:
+            // this will change the state to DECODE_PKTS once required elem resolved & 
+            // needed generic packets output
+            resp = resolveElements(); 
+            if ((m_curr_state == DECODE_PKTS) || (!OCSD_DATA_RESP_IS_CONT(resp)))
+                bPktDone = true;
             break;
-
         }
     }
     return resp;
@@ -111,14 +138,21 @@
 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::onEOT()
 {
     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
-    m_flush_EOT = true;
-    resp = flushEOT();
+    ocsd_err_t err;
+    if ((err = commitElemOnEOT()) != OCSD_OK)
+    {
+        resp = OCSD_RESP_FATAL_INVALID_DATA;
+        LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, "Error flushing element stack at end of trace data."));
+    }
+    else
+        resp = m_out_elem.sendElements();
     return resp;
 }
 
 ocsd_datapath_resp_t TrcPktDecodeEtmV4I::onReset()
 {
     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
+    m_unsync_eot_info = UNSYNC_RESET_DECODER;
     resetDecoder();
     return resp;
 }
@@ -127,15 +161,10 @@
 {
     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
 
-    // continue exception processing (can't go through processPacket as elements no longer on stack)
-    if(m_excep_info.proc != EXCEP_POP)
-        resp = processException();
-    // continue ongoing output operations on comitted elements.
-    else if(m_curr_state == COMMIT_ELEM)
-        resp = processPacket(); 
-    // continue flushing at end of trace
-    else if(m_flush_EOT)
-        resp = flushEOT();
+    if (m_curr_state == RESOLVE_ELEM)
+        resp = resolveElements();
+    else
+        resp = m_out_elem.sendElements();
     return resp;
 }
 
@@ -146,8 +175,14 @@
     // set some static config elements
     m_CSID = m_config->getTraceID();
     m_max_spec_depth = m_config->MaxSpecDepth();
+
+    // elements associated with data trace
+#ifdef DATA_TRACE_SUPPORTED
     m_p0_key_max = m_config->P0_Key_Max();
     m_cond_key_max_incr = m_config->CondKeyMaxIncr();
+#endif
+
+    m_out_elem.initCSID(m_CSID);
 
     // set up static trace instruction decode elements
     m_instr_info.dsb_dmb_waypoints = 0;
@@ -168,12 +203,7 @@
     // check config compatible with current decoder support level.
     // at present no data trace, no spec depth, no return stack, no QE
     // Remove these checks as support is added.
-    if(m_max_spec_depth != 0)
-    {
-        err = OCSD_ERR_HW_CFG_UNSUPP;
-        LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : None-zero speculation depth not supported"));
-    }
-    else if(m_config->enabledDataTrace())
+    if(m_config->enabledDataTrace())
     {
         err = OCSD_ERR_HW_CFG_UNSUPP;
         LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_HW_CFG_UNSUPP,"ETMv4 instruction decode : Data trace elements not supported"));
@@ -196,7 +226,6 @@
     return err;
 }
 
-
 /************* local decode methods */
 void TrcPktDecodeEtmV4I::initDecoder()
 {
@@ -205,12 +234,17 @@
 
     /* init elements that get set by config */
     m_max_spec_depth = 0;
-    m_p0_key_max = 0;
     m_CSID = 0;
-    m_cond_key_max_incr = 0;
     m_IASize64 = false;
 
+    // elements associated with data trace
+#ifdef DATA_TRACE_SUPPORTED
+    m_p0_key_max = 0;
+    m_cond_key_max_incr = 0;
+#endif
+
     // reset decoder state to unsynced
+    m_unsync_eot_info = UNSYNC_INIT_DECODER;
     resetDecoder();
 }
 
@@ -224,31 +258,36 @@
     m_is_64bit = false;
     m_cc_threshold = 0;
     m_curr_spec_depth = 0;
+    m_need_ctxt = true;
+    m_need_addr = true;
+    m_elem_pending_addr = false;
+    m_prev_overflow = false;
+    m_P0_stack.delete_all();
+    m_out_elem.resetElemStack();
+    m_last_IS = 0;
+    clearElemRes();
+
+    // elements associated with data trace
+#ifdef DATA_TRACE_SUPPORTED
     m_p0_key = 0;
     m_cond_c_key = 0;
     m_cond_r_key = 0;
-    m_need_ctxt = true;
-    m_need_addr = true;
-    m_except_pending_addr = false;
-    m_mem_nacc_pending = false;
-    m_prev_overflow = false;
-    m_P0_stack.delete_all();
-    m_output_elem.init();
-    m_excep_info.proc = EXCEP_POP;
-    m_flush_EOT = false;
-    m_last_IS = 0;
+#endif
 }
 
-// this function can output an immediate generic element if this covers the complete packet decode, 
-// or stack P0 and other elements for later processing on commit or cancel.
-ocsd_datapath_resp_t TrcPktDecodeEtmV4I::decodePacket(bool &Complete)
+void TrcPktDecodeEtmV4I::onFirstInitOK()
 {
+    // once init, set the output element interface to the out elem list.
+    m_out_elem.initSendIf(this->getTraceElemOutAttachPt());
+}
+
+// Changes a packet into stack of trace elements - these will be resolved and output later
+ocsd_err_t TrcPktDecodeEtmV4I::decodePacket()
+{
+    ocsd_err_t err = OCSD_OK;
     bool bAllocErr = false;
-    ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
-    Complete = true;
     bool is_addr = false;
-    bool is_except = false;
-    
+
     switch(m_curr_packet_in->getType())
     {
     case ETM4_PKT_I_ASYNC: // nothing to do with this packet.
@@ -267,13 +306,6 @@
         }
         break;
 
-    case ETM4_PKT_I_OVERFLOW:
-        {
-            if (m_P0_stack.createParamElemNoParam(P0_OVERFLOW, false, m_curr_packet_in->getType(), m_index_curr_pkt) == 0)
-                bAllocErr = true;
-        }
-        break;
-
     case ETM4_PKT_I_ATOM_F1:
     case ETM4_PKT_I_ATOM_F2:
     case ETM4_PKT_I_ATOM_F3:
@@ -314,7 +346,7 @@
     case ETM4_PKT_I_ADDR_CTXT_L_32IS1:    
         {
             m_last_IS = m_curr_packet_in->getAddrIS();
-            if (m_P0_stack.createContextElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getContext(),m_last_IS) == 0)
+            if (m_P0_stack.createContextElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getContext(), m_last_IS) == 0)
                 bAllocErr = true;
         }
     case ETM4_PKT_I_ADDR_L_32IS0:
@@ -343,10 +375,7 @@
                                             m_curr_packet_in->exception_info.exceptionType) == 0)
                 bAllocErr = true;
             else
-            {
-                m_except_pending_addr = true;  // wait for following packets before marking for commit.
-                is_except = true;
-            }
+                m_elem_pending_addr = true;  // wait for following packets before marking for commit.
         }
         break;
 
@@ -415,18 +444,49 @@
         break;
 
     case ETM4_PKT_I_BAD_SEQUENCE:
-        resp = handleBadPacket("Bad byte sequence in packet.");
+        err = handleBadPacket("Bad byte sequence in packet.");
         break;
 
     case ETM4_PKT_I_BAD_TRACEMODE:
-        resp = handleBadPacket("Invalid packet type for trace mode.");
+        err = handleBadPacket("Invalid packet type for trace mode.");
         break;
 
     case ETM4_PKT_I_RESERVED:
-        resp = handleBadPacket("Reserved packet header");
+        err = handleBadPacket("Reserved packet header");
+        break;
+
+    // speculation 
+    case ETM4_PKT_I_MISPREDICT:
+    case ETM4_PKT_I_CANCEL_F1_MISPRED:
+    case ETM4_PKT_I_CANCEL_F2:
+    case ETM4_PKT_I_CANCEL_F3:
+        m_elem_res.mispredict = true;
+        if (m_curr_packet_in->getNumAtoms())
+        {
+            if (m_P0_stack.createAtomElem(m_curr_packet_in->getType(), m_index_curr_pkt, m_curr_packet_in->getAtom()) == 0)
+                bAllocErr = true;
+            else
+                m_curr_spec_depth += m_curr_packet_in->getNumAtoms();
+        }
+
+    case ETM4_PKT_I_CANCEL_F1:
+        m_elem_res.P0_cancel = m_curr_packet_in->getCancelElem();
+        break;
+                                
+    case ETM4_PKT_I_COMMIT:
+        m_elem_res.P0_commit = m_curr_packet_in->getCommitElem();
+        break;
+
+    case ETM4_PKT_I_OVERFLOW:
+        m_prev_overflow = true;
+    case ETM4_PKT_I_DISCARD:
+        m_curr_spec_depth = 0;
+        m_elem_res.discard = true;
         break;
 
     /*** presently unsupported packets ***/
+    /* Q elemnts */
+    case ETM4_PKT_I_Q:
     /* conditional instruction tracing */
     case ETM4_PKT_I_COND_FLUSH:
     case ETM4_PKT_I_COND_I_F1:
@@ -436,90 +496,134 @@
     case ETM4_PKT_I_COND_RES_F2:
     case ETM4_PKT_I_COND_RES_F3:
     case ETM4_PKT_I_COND_RES_F4:
-    // speculation 
-    case ETM4_PKT_I_CANCEL_F1:
-    case ETM4_PKT_I_CANCEL_F2:
-    case ETM4_PKT_I_CANCEL_F3:
-    case ETM4_PKT_I_COMMIT:
-    case ETM4_PKT_I_MISPREDICT:
-    case ETM4_PKT_I_DISCARD:
     // data synchronisation markers
     case ETM4_PKT_I_NUM_DS_MKR:
     case ETM4_PKT_I_UNNUM_DS_MKR:
-    /* Q packets */
-    case ETM4_PKT_I_Q:
-        resp = OCSD_RESP_FATAL_INVALID_DATA;
-        LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_DECODE_PKT,"Unsupported packet type."));
+        // all currently unsupported
+        {
+        ocsd_err_severity_t sev = OCSD_ERR_SEV_ERROR;
+#ifdef OCSD_WARN_UNSUPPORTED
+        sev = OCSD_ERR_SEV_WARN;
+        //resp = OCSD_RESP_WARN_CONT;
+#else
+        //resp = OCSD_RESP_FATAL_INVALID_DATA;
+#endif
+        err = OCSD_ERR_UNSUPP_DECODE_PKT;
+        LogError(ocsdError(sev, err, "Data trace releated, unsupported packet type."));
+        }
         break;
 
     default:
         // any other packet - bad packet error
-        resp = OCSD_RESP_FATAL_INVALID_DATA;
-        LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_DECODE_PKT,"Unknown packet type."));
+        err = OCSD_ERR_BAD_DECODE_PKT;
+        LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,"Unknown packet type."));
         break;
-
     }
 
-    // we need to wait for following address after exception 
+    // we need to wait for following address after certain packets
     // - work out if we have seen enough here...
-    if(m_except_pending_addr && !is_except)
+    if (is_addr && m_elem_pending_addr)
     {
-        m_except_pending_addr = false;  //next packet has to be an address
-        // exception packet sequence complete
-        if(is_addr)
-        {
-            m_curr_spec_depth++;   // exceptions are P0 elements so up the spec depth to commit if needed.
-        }
-        else
-        {
-            resp = OCSD_RESP_FATAL_INVALID_DATA;
-            LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_DECODE_PKT,"Expected Address packet to follow exception packet."));
-        }
+        m_curr_spec_depth++;  // increase spec depth for element waiting on address.
+        m_elem_pending_addr = false;  // can't be waiting on both
     }
 
     if(bAllocErr)
     {
-        resp = OCSD_RESP_FATAL_SYS_ERR;
+        err = OCSD_ERR_MEM;
         LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_MEM,"Memory allocation error."));       
     }
     else if(m_curr_spec_depth > m_max_spec_depth)
     {
         // auto commit anything above max spec depth 
         // (this will auto commit anything if spec depth not supported!)
-        m_P0_commit = m_curr_spec_depth - m_max_spec_depth;
-        m_curr_state = COMMIT_ELEM;
-        Complete = false;   // force the processing of the commit elements.        
+        m_elem_res.P0_commit = m_curr_spec_depth - m_max_spec_depth;
     }
-    return resp;
+
+    if (!err && isElemForRes())
+        m_curr_state = RESOLVE_ELEM;
+    return err;
 }
 
 void TrcPktDecodeEtmV4I::doTraceInfoPacket()
 {
     m_trace_info = m_curr_packet_in->getTraceInfo();
     m_cc_threshold = m_curr_packet_in->getCCThreshold();
-    m_p0_key = m_curr_packet_in->getP0Key();
     m_curr_spec_depth = m_curr_packet_in->getCurrSpecDepth();
+
+    // elements associated with data trace
+#ifdef DATA_TRACE_SUPPORTED
+    m_p0_key = m_curr_packet_in->getP0Key();
+#endif
+}
+
+/* Element resolution
+ * Commit or cancel elements as required
+ * Send any buffered output packets.
+ */
+ocsd_datapath_resp_t TrcPktDecodeEtmV4I::resolveElements()
+{
+    ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
+    bool Complete = false;
+
+    while (!Complete)
+    {
+        if (m_out_elem.numElemToSend())
+            resp = m_out_elem.sendElements();
+        else if (isElemForRes())
+        {
+            ocsd_err_t err = OCSD_OK;
+            if (m_elem_res.P0_commit)
+                err = commitElements();
+
+            if (!err && m_elem_res.P0_cancel)
+                err = cancelElements();
+
+            if (!err && m_elem_res.mispredict)
+                err = mispredictAtom();
+            
+            if (!err && m_elem_res.discard)
+                err = discardElements();
+
+            if (err != OCSD_OK)
+                resp = OCSD_RESP_FATAL_INVALID_DATA;
+        }
+        
+        // break out on error or wait request.
+        if (!OCSD_DATA_RESP_IS_CONT(resp))
+            break;
+
+        // completion is nothing to send and nothing to commit
+        Complete = !m_out_elem.numElemToSend() && !isElemForRes();
+
+        // done all elements - need more packets.
+        if (Complete) {
+            // if we are still in resolve, the goto decode.
+            if (m_curr_state == RESOLVE_ELEM)
+                m_curr_state = DECODE_PKTS;
+        }        
+    }
+    return resp;
 }
 
 /*
  * Walks through the element stack, processing from oldest element to the newest, 
    according to the number of P0 elements that need committing.
+   Build a stack of output elements in the process.
  */
-ocsd_datapath_resp_t TrcPktDecodeEtmV4I::commitElements(bool &Complete)
+ocsd_err_t TrcPktDecodeEtmV4I::commitElements()
 {
-    ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
-    bool bPause = false;    // pause commit operation 
+    ocsd_err_t err = OCSD_OK;
     bool bPopElem = true;       // do we remove the element from the stack (multi atom elements may need to stay!)
-    int num_commit_req = m_P0_commit;
+    int num_commit_req = m_elem_res.P0_commit;
     ocsd_trc_index_t err_idx = 0;
-
-    Complete = true; // assume we exit due to completion of commit operation
-
     TrcStackElem *pElem = 0;    // stacked element pointer
 
-    while(m_P0_commit && !bPause)
+    err = m_out_elem.resetElemStack();
+
+    while(m_elem_res.P0_commit && !err)
     {
-        if(m_P0_stack.size() > 0)
+        if (m_P0_stack.size() > 0)
         {
             pElem = m_P0_stack.back();  // get oldest element
             err_idx = pElem->getRootIndex(); // save index in case of error.
@@ -528,11 +632,13 @@
             {
             // indicates a trace restart - beginning of trace or discontinuiuty
             case P0_TRC_ON:
-                m_output_elem.setType(OCSD_GEN_TRC_ELEM_TRACE_ON);
-                m_output_elem.trace_on_reason = m_prev_overflow ? TRACE_ON_OVERFLOW : TRACE_ON_NORMAL;
-                m_prev_overflow = false;
-                resp = outputTraceElementIdx(pElem->getRootIndex(),m_output_elem);
-                m_return_stack.flush();
+                err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_TRACE_ON);
+                if (!err)
+                {
+                    m_out_elem.getCurrElem().trace_on_reason = m_prev_overflow ? TRACE_ON_OVERFLOW : TRACE_ON_NORMAL;
+                    m_prev_overflow = false;
+                    m_return_stack.flush();
+                }
                 break;
 
             case P0_ADDR:
@@ -555,50 +661,20 @@
                     etmv4_context_t ctxt = pCtxtElem->getContext();
                     // check this is an updated context
                     if(ctxt.updated)
-                    {
-                        updateContext(pCtxtElem);
-
-                        m_output_elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT);
-                        resp = outputTraceElementIdx(pElem->getRootIndex(),m_output_elem);
+                    {                        
+                        err = m_out_elem.addElem(pElem->getRootIndex());
+                        if (!err)
+                            updateContext(pCtxtElem, outElem());
                     }
                 }
                 }
                 break;
 
             case P0_EVENT:
-                {
-                TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
-                if(pParamElem)
-                    resp = this->outputEvent(pParamElem);
-                }
-                break;
-
             case P0_TS:
-                {
-                TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
-                if(pParamElem)
-                    resp = outputTS(pParamElem,false);
-                }
-                break;
-
             case P0_CC:
-                {
-                TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
-                if(pParamElem)
-                    resp = outputCC(pParamElem);
-                }
-                break;
-
             case P0_TS_CC:
-                {
-                TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
-                if(pParamElem)
-                    resp = outputTS(pParamElem,true);
-                }
-                break;
-
-            case P0_OVERFLOW:
-                m_prev_overflow = true;
+                err = processTS_CC_EventElem(pElem);
                 break;
 
             case P0_ATOM:
@@ -607,22 +683,21 @@
 
                 if(pAtomElem)
                 {
-                    bool bContProcess = true;
-                    while(!pAtomElem->isEmpty() && m_P0_commit && bContProcess)
+                    while(!pAtomElem->isEmpty() && m_elem_res.P0_commit && !err)
                     {
                         ocsd_atm_val atom = pAtomElem->commitOldest();
 
                         // check if prev atom left us an indirect address target on the return stack
-                        if ((resp = returnStackPop()) != OCSD_RESP_CONT)
+                        if ((err = returnStackPop()) != OCSD_OK)
                             break;
 
                         // if address and context do instruction trace follower.
                         // otherwise skip atom and reduce committed elements
                         if(!m_need_ctxt && !m_need_addr)
                         {
-                            resp = processAtom(atom,bContProcess);
+                            err = processAtom(atom);
                         }
-                        m_P0_commit--; // mark committed 
+                        m_elem_res.P0_commit--; // mark committed 
                     }
                     if(!pAtomElem->isEmpty())   
                         bPopElem = false;   // don't remove if still atoms to process.
@@ -632,68 +707,58 @@
 
             case P0_EXCEP:
                 // check if prev atom left us an indirect address target on the return stack
-                if ((resp = returnStackPop()) != OCSD_RESP_CONT)
+                if ((err = returnStackPop()) != OCSD_OK)
                     break;
 
-                m_excep_info.proc = EXCEP_POP;   // set state in case we need to stop part way through
-                resp = processException();  // output trace + exception elements.
-                m_P0_commit--;
+                err = processException();  // output trace + exception elements.
+                m_elem_res.P0_commit--;
                 break;
 
             case P0_EXCEP_RET:
-                m_output_elem.setType(OCSD_GEN_TRC_ELEM_EXCEPTION_RET);
-                resp = outputTraceElementIdx(pElem->getRootIndex(),m_output_elem);
-                if(pElem->isP0()) // are we on a core that counts ERET as P0?
-                    m_P0_commit--;
+                err = m_out_elem.addElemType(pElem->getRootIndex(), OCSD_GEN_TRC_ELEM_EXCEPTION_RET);
+                if (!err)
+                {
+                    if (pElem->isP0()) // are we on a core that counts ERET as P0?
+                        m_elem_res.P0_commit--;
+                }
                 break;
 
             case P0_FUNC_RET:
                 // func ret is V8M - data trace only - hint that data has been popped off the stack.
                 // at this point nothing to do till the decoder starts handling data trace.
                 if (pElem->isP0()) 
-                    m_P0_commit--;
+                    m_elem_res.P0_commit--;
                 break;
             }
 
             if(bPopElem)
                 m_P0_stack.delete_back();  // remove element from stack;
-
-            // if response not continue, then break out of the loop.
-            if(!OCSD_DATA_RESP_IS_CONT(resp))
-            {
-                bPause = true;
-            }
         }
         else
         {
             // too few elements for commit operation - decode error.
-            resp = OCSD_RESP_FATAL_INVALID_DATA;
+            err = OCSD_ERR_COMMIT_PKT_OVERRUN;
             LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_COMMIT_PKT_OVERRUN,err_idx,m_CSID,"Not enough elements to commit"));
-            bPause = true;
         }
     }
 
-    // done all elements - need more packets.
-    if(m_P0_commit == 0)    
-        m_curr_state = DECODE_PKTS;
-
     // reduce the spec depth by number of comitted elements
-    m_curr_spec_depth -= (num_commit_req-m_P0_commit);
-    return resp;
+    m_curr_spec_depth -= (num_commit_req-m_elem_res.P0_commit);
+    return err;
 }
 
-ocsd_datapath_resp_t TrcPktDecodeEtmV4I::returnStackPop()
+ocsd_err_t TrcPktDecodeEtmV4I::returnStackPop()
 {
-    ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
+    ocsd_err_t err = OCSD_OK;
     ocsd_isa nextISA;
-    
+       
     if (m_return_stack.pop_pending())
     {
         ocsd_vaddr_t popAddr = m_return_stack.pop(nextISA);
         if (m_return_stack.overflow())
         {
-            resp = OCSD_RESP_FATAL_INVALID_DATA;
-            LogError(ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_RET_STACK_OVERFLOW, "Trace Return Stack Overflow."));
+            err = OCSD_ERR_RET_STACK_OVERFLOW;
+            LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, "Trace Return Stack Overflow."));
         }
         else
         {
@@ -702,20 +767,23 @@
             m_need_addr = false;
         }
     }
-    return resp;
+    return err;
 }
 
-ocsd_datapath_resp_t TrcPktDecodeEtmV4I::flushEOT()
+ocsd_err_t TrcPktDecodeEtmV4I::commitElemOnEOT()
 {
-    ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
-    if(m_flush_EOT)
+    ocsd_err_t err = OCSD_OK;
+    TrcStackElem *pElem = 0;
+
+    // nothing outstanding - reset the stack before we add more
+    if (!m_out_elem.numElemToSend())
+        m_out_elem.resetElemStack();
+
+    while((m_P0_stack.size() > 0) && !err)
     {
-        TrcStackElem *pElem = 0;
-        while(OCSD_DATA_RESP_IS_CONT(resp) && (m_P0_stack.size() > 0))
-        {
-            // scan for outstanding events, TS and CC, before any outstanding
-            // P0 commit elements.
-            pElem = m_P0_stack.back();
+        // scan for outstanding events, TS and CC, that appear before any outstanding
+        // uncommited P0 element.
+        pElem = m_P0_stack.back();
             
             switch(pElem->getP0Type())
             {
@@ -729,101 +797,289 @@
                 m_P0_stack.delete_all();
                 break;
 
-                //skip
-            case P0_ADDR:
-            case P0_CTXT:
-                break;
+            //skip
+        case P0_ADDR:
+        case P0_CTXT:
+            break;
 
-                // output
-            case P0_EVENT:
-                {
-                TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
-                if(pParamElem)
-                    resp = this->outputEvent(pParamElem);
-                }
-                break;
-
-            case P0_TS:
-                {
-                TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
-                if(pParamElem)
-                    resp = outputTS(pParamElem,false);
-                }
-                break;
-
-            case P0_CC:
-                {
-                TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
-                if(pParamElem)
-                    resp = outputCC(pParamElem);
-                }
-                break;
-
-            case P0_TS_CC:
-                {
-                TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
-                if(pParamElem)
-                    resp = outputTS(pParamElem,true);
-                }
-                break;
-            }
-            m_P0_stack.delete_back();
+            // output
+        case P0_EVENT:
+        case P0_TS:
+        case P0_CC:
+        case P0_TS_CC:
+            err = processTS_CC_EventElem(pElem);
+            break;
         }
+        m_P0_stack.delete_back();
+    }
 
-        if(OCSD_DATA_RESP_IS_CONT(resp) && (m_P0_stack.size() == 0))
+    if(!err)
+    {
+        err = m_out_elem.addElemType(m_index_curr_pkt, OCSD_GEN_TRC_ELEM_EO_TRACE);
+        outElem().setUnSyncEOTReason(m_prev_overflow ? UNSYNC_OVERFLOW : UNSYNC_EOT);
+    }
+    return err;
+}
+
+// cancel elements. These not output  
+ocsd_err_t TrcPktDecodeEtmV4I::cancelElements()
+{
+    ocsd_err_t err = OCSD_OK;
+    bool P0StackDone = false;  // checked all P0 elements on the stack
+    TrcStackElem *pElem = 0;   // stacked element pointer
+    EtmV4P0Stack temp;
+    int num_cancel_req = m_elem_res.P0_cancel;
+    
+    while (m_elem_res.P0_cancel)
+    {
+        //search the stack for the newest elements 
+        if (!P0StackDone)
         {
-            m_output_elem.setType(OCSD_GEN_TRC_ELEM_EO_TRACE);
-            resp = outputTraceElement(m_output_elem);
-            m_flush_EOT = false;
+            if (m_P0_stack.size() == 0)
+                P0StackDone = true;
+            else
+            {
+                // get the newest element
+                pElem = m_P0_stack.front();
+                if (pElem->isP0()) {
+                    if (pElem->getP0Type() == P0_ATOM)
+                    { 
+                        TrcStackElemAtom *pAtomElem = (TrcStackElemAtom *)pElem;
+                        // atom - cancel N atoms
+                        m_elem_res.P0_cancel -= pAtomElem->cancelNewest(m_elem_res.P0_cancel);
+                        if (pAtomElem->isEmpty())
+                            m_P0_stack.delete_front();  // remove the element
+                    }
+                    else
+                    {
+                        m_elem_res.P0_cancel--;
+                        m_P0_stack.delete_front();  // remove the element
+                    }
+                } else {
+                // not P0, make a keep / remove decision
+                    switch (pElem->getP0Type())
+                    {
+                    // keep these 
+                    case P0_EVENT:
+                    case P0_TS:
+                    case P0_CC:
+                    case P0_TS_CC:
+                        m_P0_stack.pop_front(false);
+                        temp.push_back(pElem);
+                        break;
+
+                    default:
+                        m_P0_stack.delete_front();
+                        break;
+                    }
+                }
+            }
+        }
+        // may have some unseen elements
+        else if (m_unseen_spec_elem)
+        {
+            m_unseen_spec_elem--;
+            m_elem_res.P0_cancel--;
+        }
+        // otherwise we have some sort of overrun
+        else
+        {
+            // too few elements for commit operation - decode error.
+            err = OCSD_ERR_COMMIT_PKT_OVERRUN;
+            LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, m_index_curr_pkt, m_CSID, "Not enough elements to cancel"));
+            m_elem_res.P0_cancel = 0;
+            break;
+        }
+       
+        if (temp.size())
+        {
+            while (temp.size())
+            {
+                pElem = temp.back();
+                m_P0_stack.push_front(pElem);
+                temp.pop_back(false);
+            }
         }
     }
-    return resp;
+    m_curr_spec_depth -= num_cancel_req - m_elem_res.P0_cancel;
+    return err;
 }
 
-ocsd_datapath_resp_t TrcPktDecodeEtmV4I::outputCC(TrcStackElemParam *pParamElem)
+// mispredict an atom
+ocsd_err_t TrcPktDecodeEtmV4I::mispredictAtom()
 {
-    m_output_elem.setType(OCSD_GEN_TRC_ELEM_CYCLE_COUNT);
-    m_output_elem.setCycleCount(pParamElem->getParam(0));
-    return outputTraceElementIdx(pParamElem->getRootIndex(),m_output_elem);
+    ocsd_err_t err = OCSD_OK;
+    bool bFoundAtom = false, bDone = false;
+    TrcStackElem *pElem = 0;
+       
+    m_P0_stack.from_front_init();   // init iterator at front.
+    while (!bDone)
+    {
+        pElem = m_P0_stack.from_front_next();
+        if (pElem)
+        {
+            if (pElem->getP0Type() == P0_ATOM)
+            {
+                TrcStackElemAtom *pAtomElem = dynamic_cast<TrcStackElemAtom *>(pElem);
+                if (pAtomElem)
+                {
+                    pAtomElem->mispredictNewest();
+                    bFoundAtom = true;
+                }
+                bDone = true;
+            }
+            else if (pElem->getP0Type() == P0_ADDR)
+            {
+                // need to disregard any addresses that appear between mispredict and the atom in question
+                m_P0_stack.erase_curr_from_front();
+            }
+        }
+        else
+            bDone = true;
+    }
+   
+    // if missed atom then either overrun error or mispredict on unseen element
+    if (!bFoundAtom && !m_unseen_spec_elem)
+    {
+        err = OCSD_ERR_COMMIT_PKT_OVERRUN;
+        LogError(ocsdError(OCSD_ERR_SEV_ERROR, err, m_index_curr_pkt, m_CSID, "Not found mispredict atom"));
+    }
+    m_elem_res.mispredict = false;
+    return err;
 }
 
-ocsd_datapath_resp_t TrcPktDecodeEtmV4I::outputTS(TrcStackElemParam *pParamElem, bool withCC)
+// discard elements and flush
+ocsd_err_t TrcPktDecodeEtmV4I::discardElements()
 {
-    m_output_elem.setType(OCSD_GEN_TRC_ELEM_TIMESTAMP);
-    m_output_elem.timestamp = (uint64_t)(pParamElem->getParam(0)) | (((uint64_t)pParamElem->getParam(1)) << 32);
-    if(withCC)
-        m_output_elem.setCycleCount(pParamElem->getParam(2));
-    return outputTraceElementIdx(pParamElem->getRootIndex(),m_output_elem);
+    ocsd_err_t err = OCSD_OK;
+    TrcStackElem *pElem = 0;   // stacked element pointer
+
+    // dump P0, elemnts - output remaining CC / TS
+    while ((m_P0_stack.size() > 0) && !err)
+    {
+        pElem = m_P0_stack.back();
+        err = processTS_CC_EventElem(pElem);
+        m_P0_stack.delete_back();
+    }
+
+    // clear all speculation info
+    clearElemRes(); 
+    m_curr_spec_depth = 0;
+
+    // set decode state
+    m_curr_state = NO_SYNC;
+    m_unsync_eot_info = m_prev_overflow ? UNSYNC_OVERFLOW : UNSYNC_DISCARD;
+
+    // unsync so need context & address.
+    m_need_ctxt = true;
+    m_need_addr = true;
+    m_elem_pending_addr = false;
+    return err;
 }
 
-ocsd_datapath_resp_t TrcPktDecodeEtmV4I::outputEvent(TrcStackElemParam *pParamElem)
+ocsd_err_t TrcPktDecodeEtmV4I::processTS_CC_EventElem(TrcStackElem *pElem)
 {
-    m_output_elem.setType(OCSD_GEN_TRC_ELEM_EVENT);
-    m_output_elem.trace_event.ev_type = EVENT_NUMBERED;
-    m_output_elem.trace_event.ev_number = pParamElem->getParam(0);
-    return outputTraceElementIdx(pParamElem->getRootIndex(),m_output_elem);
+    ocsd_err_t err = OCSD_OK;
+
+    switch (pElem->getP0Type())
+    {
+        case P0_EVENT:
+        {
+            TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
+            if (pParamElem)
+                err = addElemEvent(pParamElem);
+        }
+        break;
+
+        case P0_TS:
+        {
+            TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
+            if (pParamElem)
+                err = addElemTS(pParamElem, false);
+        }
+        break;
+
+        case P0_CC:
+        {
+            TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
+            if (pParamElem)
+                err = addElemCC(pParamElem);
+        }
+        break;
+
+        case P0_TS_CC:
+        {
+            TrcStackElemParam *pParamElem = dynamic_cast<TrcStackElemParam *>(pElem);
+            if (pParamElem)
+                err = addElemTS(pParamElem, true);
+        }
+        break;
+    }
+    return err;
+
 }
 
-ocsd_datapath_resp_t TrcPktDecodeEtmV4I::outputTraceRange(const bool executed, ocsd_trc_index_t index)
+ocsd_err_t TrcPktDecodeEtmV4I::addElemCC(TrcStackElemParam *pParamElem)
 {
-    m_output_elem.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE);
-    m_output_elem.setLastInstrInfo(executed, m_instr_info.type, m_instr_info.sub_type, m_instr_info.instr_size);
-    m_output_elem.setISA(m_instr_info.isa);
-    m_output_elem.setLastInstrCond(m_instr_info.is_conditional);
+    ocsd_err_t err = OCSD_OK;
+
+    err = m_out_elem.addElemType(pParamElem->getRootIndex(), OCSD_GEN_TRC_ELEM_CYCLE_COUNT);
+    if (!err)
+        outElem().setCycleCount(pParamElem->getParam(0));
+    return err;
+}
+
+ocsd_err_t TrcPktDecodeEtmV4I::addElemTS(TrcStackElemParam *pParamElem, bool withCC)
+{
+    ocsd_err_t err = OCSD_OK;
+
+    err = m_out_elem.addElemType(pParamElem->getRootIndex(), OCSD_GEN_TRC_ELEM_TIMESTAMP);
+    if (!err)
+    {
+        outElem().timestamp = (uint64_t)(pParamElem->getParam(0)) | (((uint64_t)pParamElem->getParam(1)) << 32);
+        if (withCC)
+            outElem().setCycleCount(pParamElem->getParam(2));
+    }
+    return err;
+}
+
+ocsd_err_t TrcPktDecodeEtmV4I::addElemEvent(TrcStackElemParam *pParamElem)
+{
+    ocsd_err_t err = OCSD_OK;
+
+    err = m_out_elem.addElemType(pParamElem->getRootIndex(), OCSD_GEN_TRC_ELEM_EVENT);
+    if (!err)
+    {
+        outElem().trace_event.ev_type = EVENT_NUMBERED;
+        outElem().trace_event.ev_number = pParamElem->getParam(0);
+    }
+    return err;
+}
+
+void TrcPktDecodeEtmV4I::setElemTraceRange(OcsdTraceElement &elemIn, const instr_range_t &addr_range, 
+                                           const bool executed, ocsd_trc_index_t index)
+{
+    elemIn.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE);
+    elemIn.setLastInstrInfo(executed, m_instr_info.type, m_instr_info.sub_type, m_instr_info.instr_size);
+    elemIn.setISA(m_instr_info.isa);
+    elemIn.setLastInstrCond(m_instr_info.is_conditional);
+    elemIn.setAddrRange(addr_range.st_addr, addr_range.en_addr, addr_range.num_instr);
     if (executed)
         m_instr_info.isa = m_instr_info.next_isa;
-    return outputTraceElementIdx(index, m_output_elem);
 }
 
-ocsd_datapath_resp_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom, bool &bCont)
+ocsd_err_t TrcPktDecodeEtmV4I::processAtom(const ocsd_atm_val atom)
 {
-    ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
-    TrcStackElem *pElem = m_P0_stack.back();  // get the atom element
-    bool bWPFound = false;
     ocsd_err_t err;
-    bCont = true;
+    TrcStackElem *pElem = m_P0_stack.back();  // get the atom element
+    WP_res_t WPRes;
+    instr_range_t addr_range;
 
-    err = traceInstrToWP(bWPFound);
+    // new element for this processed atom
+    if ((err = m_out_elem.addElem(pElem->getRootIndex())) != OCSD_OK)
+        return err;
+
+    err = traceInstrToWP(addr_range, WPRes);
     if(err != OCSD_OK)
     {
         if(err == OCSD_ERR_UNSUPPORTED_ISA)
@@ -832,18 +1088,16 @@
              m_need_ctxt = true;
              LogError(ocsdError(OCSD_ERR_SEV_WARN,err,pElem->getRootIndex(),m_CSID,"Warning: unsupported instruction set processing atom packet."));  
              // wait for next context
-             return resp;
+             return OCSD_OK;
         }
         else
         {
-            bCont = false;
-            resp = OCSD_RESP_FATAL_INVALID_DATA;
             LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,pElem->getRootIndex(),m_CSID,"Error processing atom packet."));  
-            return resp;
+            return err;
         }
     }
 
-    if(bWPFound)
+    if(WPFound(WPRes))
     {
         //  save recorded next instuction address
         ocsd_vaddr_t nextAddr = m_instr_info.instr_addr;
@@ -871,125 +1125,113 @@
             }
             break;
         }
-        resp = outputTraceRange((atom == ATOM_E), pElem->getRootIndex());
-
+        setElemTraceRange(outElem(), addr_range, (atom == ATOM_E), pElem->getRootIndex());
     }
     else
     {
         // no waypoint - likely inaccessible memory range.
         m_need_addr = true; // need an address update 
 
-        if(m_output_elem.st_addr != m_output_elem.en_addr)
+        if(addr_range.st_addr != addr_range.en_addr)
         {
             // some trace before we were out of memory access range
-            resp = outputTraceRange(true, pElem->getRootIndex());
+            setElemTraceRange(outElem(), addr_range, true, pElem->getRootIndex());
+
+            // another element for the nacc...
+            if (WPNacc(WPRes))
+                err = m_out_elem.addElem(pElem->getRootIndex());
         }
 
-        if(m_mem_nacc_pending && OCSD_DATA_RESP_IS_CONT(resp))
+        if(WPNacc(WPRes) && !err)
         {
-            m_output_elem.setType(OCSD_GEN_TRC_ELEM_ADDR_NACC);
-            m_output_elem.st_addr = m_nacc_addr;
-            resp = outputTraceElementIdx(pElem->getRootIndex(),m_output_elem);
-            m_mem_nacc_pending = false;
+            outElem().setType(OCSD_GEN_TRC_ELEM_ADDR_NACC);
+            outElem().st_addr = m_instr_info.instr_addr;
         }
     }
-
-    if(!OCSD_DATA_RESP_IS_CONT(resp))
-        bCont = false;
-
-    return resp;
+    return err;
 }
 
 // Exception processor
-ocsd_datapath_resp_t  TrcPktDecodeEtmV4I::processException()
+ocsd_err_t TrcPktDecodeEtmV4I::processException()
 {
-    ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 
-    TrcStackElemExcept *pExceptElem;
+    ocsd_err_t err;
+    TrcStackElem *pElem = 0;
+    TrcStackElemExcept *pExceptElem = 0;
+    TrcStackElemAddr *pAddressElem = 0;
+    TrcStackElemCtxt *pCtxtElem = 0;
+    bool branch_target = false;    // exception address implies prior branch target address
+    ocsd_vaddr_t excep_ret_addr;
+    ocsd_trc_index_t excep_pkt_index;
+    WP_res_t WPRes = WP_NOT_FOUND;
 
-    m_excep_info.addr_b_tgt = false;
-    
-    if(m_excep_info.proc == EXCEP_POP)
+    // grab the exception element off the stack
+    pExceptElem = dynamic_cast<TrcStackElemExcept *>(m_P0_stack.back());  // get the exception element
+    excep_pkt_index = pExceptElem->getRootIndex();
+    branch_target = pExceptElem->getPrevSame();
+    m_P0_stack.pop_back(); // remove the exception element
+
+    pElem = m_P0_stack.back();  // look at next element.
+    if(pElem->getP0Type() == P0_CTXT)
     {
-        pExceptElem = dynamic_cast<TrcStackElemExcept *>(m_P0_stack.back());  // get the exception element
-        TrcStackElemAddr *pAddressElem = 0;
-        TrcStackElemCtxt *pCtxtElem = 0;
-        TrcStackElem *pElem = 0;
-    
-        m_P0_stack.pop_back(); // remove the exception element
-        pElem = m_P0_stack.back();  // look at next element.
-        if(pElem->getP0Type() == P0_CTXT)
-        {
-            pCtxtElem = dynamic_cast<TrcStackElemCtxt *>(pElem);
-            m_P0_stack.pop_back(); // remove the context element
-            pElem = m_P0_stack.back();  // next one should be an address element
-        }
+        pCtxtElem = dynamic_cast<TrcStackElemCtxt *>(pElem);
+        m_P0_stack.pop_back(); // remove the context element
+        pElem = m_P0_stack.back();  // next one should be an address element
+    }
    
-        if(pElem->getP0Type() != P0_ADDR)
+   if(pElem->getP0Type() != P0_ADDR)
+   {
+       // no following address element - indicate processing error.      
+       LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ, excep_pkt_index,m_CSID,"Address missing in exception packet."));
+       return OCSD_ERR_BAD_PACKET_SEQ;
+   }
+   else
+   {
+        // extract address
+        pAddressElem = static_cast<TrcStackElemAddr *>(pElem);
+        excep_ret_addr = pAddressElem->getAddr().val;
+
+        // see if there is an address + optional context element implied 
+        // prior to the exception.
+        if (branch_target)
         {
-            // no following address element - indicate processing error.
-            resp = OCSD_RESP_FATAL_INVALID_DATA;
-            LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,pExceptElem->getRootIndex(),m_CSID,"Address missing in exception packet."));  
-        }
-        else
-        {
-            // extract address
-            pAddressElem = static_cast<TrcStackElemAddr *>(pElem);
-
-            // fill in exception info for use later
-            m_excep_info.addr = pAddressElem->getAddr();                
-            m_excep_info.number = pExceptElem->getExcepNum();
-            m_excep_info.index = pExceptElem->getRootIndex();
-            m_excep_info.addr_b_tgt = pExceptElem->getPrevSame();
-
-            // see if there is an address + optional context element implied 
-            // prior to the exception.
-            if (m_excep_info.addr_b_tgt)
-            {
-                // this was a branch target address - update current setting
-                bool b64bit = m_instr_info.isa == ocsd_isa_aarch64;
-                if (pCtxtElem) {
-                    b64bit = pCtxtElem->getContext().SF;
-                }
-                m_instr_info.instr_addr = m_excep_info.addr.val;
-                m_instr_info.isa = (m_excep_info.addr.isa == 0) ? 
-                    (b64bit ? ocsd_isa_aarch64 : ocsd_isa_arm) : ocsd_isa_thumb2;
-                m_need_addr = false;
-            }
-
-            // figure out next move
+            // this was a branch target address - update current setting
+            bool b64bit = m_instr_info.isa == ocsd_isa_aarch64;
             if (pCtxtElem) {
-                m_excep_info.proc = EXCEP_CTXT;
-                updateContext(pCtxtElem);
+                b64bit = pCtxtElem->getContext().SF;
             }
-            else if(m_excep_info.addr.val == m_instr_info.instr_addr)
-                m_excep_info.proc = EXCEP_EXCEP;
-            else
-                m_excep_info.proc = EXCEP_RANGE;
+
+            // as the exception address was also a branch target address then update the 
+            // current maintained address value. This also means that there is no range to
+            // output before the exception packet.
+            m_instr_info.instr_addr = excep_ret_addr; 
+            m_instr_info.isa = (pAddressElem->getAddr().isa == 0) ?
+                    (b64bit ? ocsd_isa_aarch64 : ocsd_isa_arm) : ocsd_isa_thumb2;
+            m_need_addr = false;
         }
-        m_P0_stack.delete_popped();
+    }   
+
+    // need to output something - set up an element
+    if ((err = m_out_elem.addElem(excep_pkt_index)))
+        return err;  
+
+    // output a context element if present
+    if (pCtxtElem)
+    {
+        updateContext(pCtxtElem, outElem());
+
+        // used the element - need another for later stages
+        if ((err = m_out_elem.addElem(excep_pkt_index)))
+            return err;
     }
 
-    // output a context element
-    if (m_excep_info.proc == EXCEP_CTXT)
-    {
-        m_output_elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT);
-        resp = outputTraceElementIdx(m_excep_info.index, m_output_elem);
-        m_excep_info.proc = EXCEP_EXCEP;
-        if (!OCSD_DATA_RESP_IS_CONT(resp))
-            return resp;
-    }
-
-    // output a range element
-    if(m_excep_info.proc == EXCEP_RANGE) 
-    {
-        bool bWPFound = false;
-        ocsd_err_t err;
-
-        // last instr_info address is the start address
-        m_output_elem.st_addr = m_instr_info.instr_addr;
+    // if the preferred return address is not the end of the last output range...
+    if (m_instr_info.instr_addr != excep_ret_addr)
+    {        
+        bool range_out = false;
+        instr_range_t addr_range;
 
         // look for match to return address.
-        err = traceInstrToWP(bWPFound,true,m_excep_info.addr.val);
+        err = traceInstrToWP(addr_range, WPRes, true, excep_ret_addr);
 
         if(err != OCSD_OK)
         {
@@ -997,59 +1239,65 @@
             {
                 m_need_addr = true;
                 m_need_ctxt = true;
-                LogError(ocsdError(OCSD_ERR_SEV_WARN,err,m_excep_info.index,m_CSID,"Warning: unsupported instruction set processing exception packet."));  
+                LogError(ocsdError(OCSD_ERR_SEV_WARN,err, excep_pkt_index,m_CSID,"Warning: unsupported instruction set processing exception packet."));
             }
             else
             {
-                resp = OCSD_RESP_FATAL_INVALID_DATA;
-                LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,m_excep_info.index,m_CSID,"Error processing exception packet."));  
-                m_excep_info.proc = EXCEP_POP;  // nothing more to do, reset to start of exception handling
+                LogError(ocsdError(OCSD_ERR_SEV_ERROR,err, excep_pkt_index,m_CSID,"Error processing exception packet."));
             }
+            return err;
         }
 
-        if(bWPFound)
+        if(WPFound(WPRes))
         {
             // waypoint address found - output range
-            resp = outputTraceRange(true, m_excep_info.index);
-            m_excep_info.proc = EXCEP_EXCEP;
+            setElemTraceRange(outElem(), addr_range, true, excep_pkt_index);
+            range_out = true;
         }
         else
         {
             // no waypoint - likely inaccessible memory range.
             m_need_addr = true; // need an address update 
             
-            if(m_output_elem.st_addr != m_output_elem.en_addr)
+            if(addr_range.st_addr != addr_range.en_addr)
             {
                 // some trace before we were out of memory access range
-                resp = outputTraceRange(true, m_excep_info.index);
+                setElemTraceRange(outElem(), addr_range, true, excep_pkt_index);
+                range_out = true;
             }
-
-            m_excep_info.proc = m_mem_nacc_pending ? EXCEP_NACC : EXCEP_EXCEP;
         }
-    }  
-    
-    if((m_excep_info.proc == EXCEP_NACC) && OCSD_DATA_RESP_IS_CONT(resp))
+
+        // used the element need another for NACC or EXCEP.
+        if (range_out)
+        {
+            if ((err = m_out_elem.addElem(excep_pkt_index)))
+                return err;
+        }
+    }
+   
+    // watchpoint walk resulted in inaccessible memory call...
+    if (WPNacc(WPRes))
     {
-        m_output_elem.setType(OCSD_GEN_TRC_ELEM_ADDR_NACC);
-        m_output_elem.st_addr = m_nacc_addr;
-        resp = outputTraceElementIdx(m_excep_info.index,m_output_elem);
-        m_excep_info.proc = EXCEP_EXCEP;
-        m_mem_nacc_pending = false;
+        
+        outElem().setType(OCSD_GEN_TRC_ELEM_ADDR_NACC);
+        outElem().st_addr = m_instr_info.instr_addr;
+
+        // used the element - need another for the final exception packet.
+        if ((err = m_out_elem.addElem(excep_pkt_index)))
+            return err;
     }
     
-    if((m_excep_info.proc == EXCEP_EXCEP) && OCSD_DATA_RESP_IS_CONT(resp))
-    {
-        // output element.
-        m_output_elem.setType(OCSD_GEN_TRC_ELEM_EXCEPTION);
-        // add end address as preferred return address to end addr in element
-        m_output_elem.en_addr = m_excep_info.addr.val;
-        m_output_elem.excep_ret_addr = 1;
-        m_output_elem.excep_ret_addr_br_tgt = m_excep_info.addr_b_tgt;
-        m_output_elem.exception_number = m_excep_info.number;
-        resp = outputTraceElementIdx(m_excep_info.index,m_output_elem);  
-        m_excep_info.proc = EXCEP_POP;
-    }   
-    return resp;
+    // output exception element.
+    outElem().setType(OCSD_GEN_TRC_ELEM_EXCEPTION);
+
+    // add end address as preferred return address to end addr in element
+    outElem().en_addr = excep_ret_addr;
+    outElem().excep_ret_addr = 1;
+    outElem().excep_ret_addr_br_tgt = branch_target;
+    outElem().exception_number = pExceptElem->getExcepNum();
+
+    m_P0_stack.delete_popped();     // clear the used elements from the stack
+    return err;
 }
 
 void TrcPktDecodeEtmV4I::SetInstrInfoInAddrISA(const ocsd_vaddr_t addr_val, const uint8_t isa)
@@ -1059,25 +1307,22 @@
 }
 
 // trace an instruction range to a waypoint - and set next address to restart from.
-ocsd_err_t TrcPktDecodeEtmV4I::traceInstrToWP(bool &bWPFound, const bool traceToAddrNext /*= false*/, const ocsd_vaddr_t nextAddrMatch /*= 0*/)
+ocsd_err_t TrcPktDecodeEtmV4I::traceInstrToWP(instr_range_t &range, WP_res_t &WPRes, const bool traceToAddrNext /*= false*/, const ocsd_vaddr_t nextAddrMatch /*= 0*/)
 {
     uint32_t opcode;
     uint32_t bytesReq;
     ocsd_err_t err = OCSD_OK;
 
-    // TBD?: update mem space to allow for EL as well.
-    ocsd_mem_space_acc_t mem_space = m_is_secure ? OCSD_MEM_SPACE_S : OCSD_MEM_SPACE_N;
+    range.st_addr = range.en_addr = m_instr_info.instr_addr;
+    range.num_instr = 0;
 
-    m_output_elem.st_addr = m_output_elem.en_addr = m_instr_info.instr_addr;
-    m_output_elem.num_instr_range = 0;
+    WPRes = WP_NOT_FOUND;
 
-    bWPFound = false;
-
-    while(!bWPFound && !m_mem_nacc_pending)
+    while(WPRes == WP_NOT_FOUND)
     {
         // start off by reading next opcode;
         bytesReq = 4;
-        err = accessMemory(m_instr_info.instr_addr,mem_space,&bytesReq,(uint8_t *)&opcode);
+        err = accessMemory(m_instr_info.instr_addr, getCurrMemSpace(),&bytesReq,(uint8_t *)&opcode);
         if(err != OCSD_OK) break;
 
         if(bytesReq == 4) // got data back
@@ -1088,72 +1333,100 @@
 
             // increment address - may be adjusted by direct branch value later
             m_instr_info.instr_addr += m_instr_info.instr_size;
-
-            // update the range decoded address in the output packet.
-            m_output_elem.en_addr = m_instr_info.instr_addr;
-            m_output_elem.num_instr_range++;
+            range.num_instr++;
 
             // either walking to match the next instruction address or a real watchpoint
-            if(traceToAddrNext)
-                bWPFound = (m_output_elem.en_addr == nextAddrMatch);
-            else
-                bWPFound = (m_instr_info.type != OCSD_INSTR_OTHER);
+            if (traceToAddrNext)
+            {
+                if (m_instr_info.instr_addr == nextAddrMatch) 
+                    WPRes = WP_FOUND;
+            }
+            else if (m_instr_info.type != OCSD_INSTR_OTHER)
+                WPRes = WP_FOUND;
         }
         else
         {
             // not enough memory accessible.
-            m_mem_nacc_pending = true;
-            m_nacc_addr = m_instr_info.instr_addr;           
+            WPRes = WP_NACC;
         }
     }
+    // update the range decoded address in the output packet.
+    range.en_addr = m_instr_info.instr_addr;
     return err;
 }
 
-void TrcPktDecodeEtmV4I::updateContext(TrcStackElemCtxt *pCtxtElem)
+void TrcPktDecodeEtmV4I::updateContext(TrcStackElemCtxt *pCtxtElem, OcsdTraceElement &elem)
 {
     etmv4_context_t ctxt = pCtxtElem->getContext();
-    // map to output element  and local saved state.
+    
+    elem.setType(OCSD_GEN_TRC_ELEM_PE_CONTEXT);
+
+    // map to output element and local saved state.
     m_is_64bit = (ctxt.SF != 0);
-    m_output_elem.context.bits64 = ctxt.SF;
+    elem.context.bits64 = ctxt.SF;
     m_is_secure = (ctxt.NS == 0);
-    m_output_elem.context.security_level = ctxt.NS ? ocsd_sec_nonsecure : ocsd_sec_secure;
-    m_output_elem.context.exception_level = (ocsd_ex_level)ctxt.EL;
-    m_output_elem.context.el_valid = 1;
+    elem.context.security_level = ctxt.NS ? ocsd_sec_nonsecure : ocsd_sec_secure;
+    elem.context.exception_level = (ocsd_ex_level)ctxt.EL;
+    elem.context.el_valid = 1;
     if(ctxt.updated_c)
     {
-        m_output_elem.context.ctxt_id_valid = 1;
-        m_context_id = m_output_elem.context.context_id = ctxt.ctxtID;
+        elem.context.ctxt_id_valid = 1;
+        m_context_id = elem.context.context_id = ctxt.ctxtID;
     }
     if(ctxt.updated_v)
     {
-        m_output_elem.context.vmid_valid = 1;
-        m_vmid_id = m_output_elem.context.vmid = ctxt.VMID;
+        elem.context.vmid_valid = 1;
+        m_vmid_id = elem.context.vmid = ctxt.VMID;
     }
 
     // need to update ISA in case context follows address.
-    m_output_elem.isa = m_instr_info.isa = calcISA(m_is_64bit, pCtxtElem->getIS());
+    elem.isa = m_instr_info.isa = calcISA(m_is_64bit, pCtxtElem->getIS());
     m_need_ctxt = false;
 }
 
-ocsd_datapath_resp_t TrcPktDecodeEtmV4I::handleBadPacket(const char *reason)
+ocsd_err_t TrcPktDecodeEtmV4I::handleBadPacket(const char *reason)
 {
-    ocsd_datapath_resp_t resp  = OCSD_RESP_CONT;   
+    ocsd_err_t err = OCSD_OK;
 
     if(getComponentOpMode() && OCSD_OPFLG_PKTDEC_ERROR_BAD_PKTS)
     {
         // error out - stop decoding
-        resp = OCSD_RESP_FATAL_INVALID_DATA;
-        LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_DECODE_PKT,reason));
+        err = OCSD_ERR_BAD_DECODE_PKT;
+        LogError(ocsdError(OCSD_ERR_SEV_ERROR,err,reason));
     }
     else
     {
+        LogError(ocsdError(OCSD_ERR_SEV_WARN, OCSD_ERR_BAD_DECODE_PKT, reason));
         // switch to unsync - clear decode state
-        m_output_elem.setType(OCSD_GEN_TRC_ELEM_NO_SYNC);
-        resp = outputTraceElement(m_output_elem);
         resetDecoder();
-        m_curr_state = WAIT_SYNC;
+        m_curr_state = NO_SYNC;
+        m_unsync_eot_info = UNSYNC_BAD_PACKET;
     }
-    return resp;
+    return err;
 }
 
+inline ocsd_mem_space_acc_t TrcPktDecodeEtmV4I::getCurrMemSpace()
+{
+    static ocsd_mem_space_acc_t SMemSpace[] = {
+        OCSD_MEM_SPACE_EL1S,
+        OCSD_MEM_SPACE_EL1S,
+        OCSD_MEM_SPACE_EL2S,
+        OCSD_MEM_SPACE_EL3
+    };
+
+    static ocsd_mem_space_acc_t NSMemSpace[] = {
+        OCSD_MEM_SPACE_EL1N,
+        OCSD_MEM_SPACE_EL1N,
+        OCSD_MEM_SPACE_EL2,
+        OCSD_MEM_SPACE_EL3
+    };
+
+    /* if no valid EL value - just use S/NS */
+    if (!outElem().context.el_valid)
+        return  m_is_secure ? OCSD_MEM_SPACE_S : OCSD_MEM_SPACE_N;
+    
+    /* mem space according to EL + S/NS */
+    int el = (int)(outElem().context.exception_level) & 0x3;
+    return m_is_secure ? SMemSpace[el] : NSMemSpace[el];
+}
 /* End of File trc_pkt_decode_etmv4i.cpp */
diff --git a/decoder/source/etmv4/trc_pkt_elem_etmv4d.cpp b/decoder/source/etmv4/trc_pkt_elem_etmv4d.cpp
deleted file mode 100644
index 58343b4..0000000
--- a/decoder/source/etmv4/trc_pkt_elem_etmv4d.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * \file       trc_pkt_elem_etmv4d.cpp
- * \brief      OpenCSD : 
- * 
- * \copyright  Copyright (c) 2015, ARM Limited. All Rights Reserved.
- */
-
-
-/* 
- * Redistribution and use in source and binary forms, with or without modification, 
- * are permitted provided that the following conditions are met:
- * 
- * 1. Redistributions of source code must retain the above copyright notice, 
- * this list of conditions and the following disclaimer.
- * 
- * 2. Redistributions in binary form must reproduce the above copyright notice, 
- * this list of conditions and the following disclaimer in the documentation 
- * and/or other materials provided with the distribution. 
- * 
- * 3. Neither the name of the copyright holder nor the names of its contributors 
- * may be used to endorse or promote products derived from this software without 
- * specific prior written permission. 
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND 
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */ 
-
-#include "opencsd/etmv4/trc_pkt_elem_etmv4d.h"
-
-EtmV4DTrcPacket::EtmV4DTrcPacket()
-{
-}
-
-EtmV4DTrcPacket::~EtmV4DTrcPacket()
-{
-}
-
-    // printing
-void EtmV4DTrcPacket::toString(std::string &str) const
-{
-}
-
-void EtmV4DTrcPacket::toStringFmt(const uint32_t fmtFlags, std::string &str) const
-{
-}
-
-
-
-/* End of File trc_pkt_elem_etmv4d.cpp */
diff --git a/decoder/source/etmv4/trc_pkt_elem_etmv4i.cpp b/decoder/source/etmv4/trc_pkt_elem_etmv4i.cpp
index 3f9d534..8ba258a 100644
--- a/decoder/source/etmv4/trc_pkt_elem_etmv4i.cpp
+++ b/decoder/source/etmv4/trc_pkt_elem_etmv4i.cpp
@@ -161,6 +161,7 @@
         {
             std::ostringstream oss;
             oss << "; INFO=" << std::hex << "0x" << trace_info.val;
+            oss << " { CC." << std::dec << trace_info.bits.cc_enabled << " }";
             if (trace_info.bits.cc_enabled)
                 oss << "; CC_THRESHOLD=" << std::hex << "0x" << cc_threshold;
             str += oss.str();
@@ -176,6 +177,68 @@
             str += oss.str();
         }
         break;
+
+    case ETM4_PKT_I_CANCEL_F1:
+        {
+            std::ostringstream oss;
+            oss << "; Cancel(" << std::dec << cancel_elements << ")";
+            str += oss.str();
+        }
+        break;
+
+    case ETM4_PKT_I_CANCEL_F1_MISPRED:
+        {
+            std::ostringstream oss;
+            oss << "; Cancel(" << std::dec << cancel_elements << "), Mispredict";
+            str += oss.str();
+        }
+        break;
+
+    case ETM4_PKT_I_MISPREDICT:
+        {
+            std::ostringstream oss;
+            oss << "; ";
+            if (atom.num) {
+                atomSeq(valStr);
+                oss << "Atom: " << valStr << ", ";
+            }
+            oss << "Mispredict";
+            str += oss.str();
+        }
+        break;
+
+    case ETM4_PKT_I_CANCEL_F2:
+        {
+            std::ostringstream oss;
+            oss << "; ";
+            if (atom.num) {
+                atomSeq(valStr);
+                oss << "Atom: " << valStr << ", ";
+            }
+            oss << "Cancel(1), Mispredict";
+            str += oss.str();
+        }
+        break;
+
+    case ETM4_PKT_I_CANCEL_F3:
+        {
+            std::ostringstream oss;
+            oss << "; ";
+            if (atom.num) {
+                oss << "Atom: E, ";
+            }
+            oss << "Cancel(" << std::dec << cancel_elements << "), Mispredict";
+            str += oss.str();
+        }
+        break;
+
+    case ETM4_PKT_I_COMMIT:
+        {
+            std::ostringstream oss;
+            oss << "; Commit(" << std::dec << commit_elements << ")";
+            str += oss.str();
+        }
+        break;
     }
 }
 
@@ -296,6 +359,12 @@
         pDesc = "Cancel Format 1.";
         break;
 
+    case ETM4_PKT_I_CANCEL_F1_MISPRED:
+        pName = "I_CANCEL_F1_MISPRED";
+        pDesc = "Cancel Format 1 + Mispredict.";
+        break;
+
+
     case ETM4_PKT_I_MISPREDICT:
         pName = "I_MISPREDICT";
         pDesc = "Mispredict.";
diff --git a/decoder/source/etmv4/trc_pkt_proc_etmv4.cpp b/decoder/source/etmv4/trc_pkt_proc_etmv4.cpp
deleted file mode 100644
index b8c4f81..0000000
--- a/decoder/source/etmv4/trc_pkt_proc_etmv4.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * \file       trc_pkt_proc_etmv4.cpp
- * \brief      OpenCSD : 
- * 
- * \copyright  Copyright (c) 2015, ARM Limited. All Rights Reserved.
- */
-
-
-/* 
- * Redistribution and use in source and binary forms, with or without modification, 
- * are permitted provided that the following conditions are met:
- * 
- * 1. Redistributions of source code must retain the above copyright notice, 
- * this list of conditions and the following disclaimer.
- * 
- * 2. Redistributions in binary form must reproduce the above copyright notice, 
- * this list of conditions and the following disclaimer in the documentation 
- * and/or other materials provided with the distribution. 
- * 
- * 3. Neither the name of the copyright holder nor the names of its contributors 
- * may be used to endorse or promote products derived from this software without 
- * specific prior written permission. 
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND 
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */ 
-
-#include "opencsd/etmv4/trc_pkt_proc_etmv4.h"
-#include "trc_pkt_proc_etmv4i_impl.h"
-#include "common/ocsd_error.h"
-
-#ifdef __GNUC__
-// G++ doesn't like the ## pasting
-#define ETMV4I_PKTS_NAME "PKTP_ETMV4I"
-#else
-// VC++ is fine
-#define ETMV4I_PKTS_NAME OCSD_CMPNAME_PREFIX_PKTPROC##"_ETMV4I"
-#endif
-
-static const uint32_t ETMV4_SUPPORTED_OP_FLAGS = OCSD_OPFLG_PKTPROC_COMMON;
-
-/***************************************************************************/
-/*******************ETM V4 INSTRUCTION *************************************/
-/***************************************************************************/
-
-TrcPktProcEtmV4I::TrcPktProcEtmV4I() : TrcPktProcBase(ETMV4I_PKTS_NAME), 
-    m_pProcessor(0)
-{
-    m_supported_op_flags = ETMV4_SUPPORTED_OP_FLAGS;
-}
-
-TrcPktProcEtmV4I::TrcPktProcEtmV4I(int instIDNum) : TrcPktProcBase(ETMV4I_PKTS_NAME, instIDNum),
-    m_pProcessor(0)
-{
-    m_supported_op_flags = ETMV4_SUPPORTED_OP_FLAGS;
-}
-
-TrcPktProcEtmV4I::~TrcPktProcEtmV4I()
-{
-    if(m_pProcessor)
-        delete m_pProcessor;
-    m_pProcessor = 0;
-}
-
-ocsd_err_t TrcPktProcEtmV4I::onProtocolConfig()
-{
-    if(m_pProcessor == 0)
-    {
-        m_pProcessor = new (std::nothrow) EtmV4IPktProcImpl();
-        if(m_pProcessor == 0)
-        {           
-            LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_MEM));
-            return OCSD_ERR_MEM;
-        }
-        m_pProcessor->Initialise(this);
-    }
-    return m_pProcessor->Configure(m_config);
-}
-
-ocsd_datapath_resp_t TrcPktProcEtmV4I::processData(  const ocsd_trc_index_t index,
-                                                const uint32_t dataBlockSize,
-                                                const uint8_t *pDataBlock,
-                                                uint32_t *numBytesProcessed)
-{
-    if(m_pProcessor)
-        return m_pProcessor->processData(index,dataBlockSize,pDataBlock,numBytesProcessed);
-    return OCSD_RESP_FATAL_NOT_INIT;
-}
-
-ocsd_datapath_resp_t TrcPktProcEtmV4I::onEOT()
-{
-    if(m_pProcessor)
-        return m_pProcessor->onEOT();
-    return OCSD_RESP_FATAL_NOT_INIT;
-}
-
-ocsd_datapath_resp_t TrcPktProcEtmV4I::onReset()
-{
-    if(m_pProcessor)
-        return m_pProcessor->onReset();
-    return OCSD_RESP_FATAL_NOT_INIT;
-}
-
-ocsd_datapath_resp_t TrcPktProcEtmV4I::onFlush()
-{
-    if(m_pProcessor)
-        return m_pProcessor->onFlush();
-    return OCSD_RESP_FATAL_NOT_INIT;
-}
-
-const bool TrcPktProcEtmV4I::isBadPacket() const
-{
-    if(m_pProcessor)
-        return m_pProcessor->isBadPacket();
-    return false;
-}
-
-/* End of File trc_pkt_proc_etmv4.cpp */
diff --git a/decoder/source/etmv4/trc_pkt_proc_etmv4d_impl.h b/decoder/source/etmv4/trc_pkt_proc_etmv4d_impl.h
deleted file mode 100644
index 3be35bd..0000000
--- a/decoder/source/etmv4/trc_pkt_proc_etmv4d_impl.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * \file       trc_pkt_proc_etmv4d_impl.h
- * \brief      OpenCSD : 
- * 
- * \copyright  Copyright (c) 2015, ARM Limited. All Rights Reserved.
- */
-
-/* 
- * Redistribution and use in source and binary forms, with or without modification, 
- * are permitted provided that the following conditions are met:
- * 
- * 1. Redistributions of source code must retain the above copyright notice, 
- * this list of conditions and the following disclaimer.
- * 
- * 2. Redistributions in binary form must reproduce the above copyright notice, 
- * this list of conditions and the following disclaimer in the documentation 
- * and/or other materials provided with the distribution. 
- * 
- * 3. Neither the name of the copyright holder nor the names of its contributors 
- * may be used to endorse or promote products derived from this software without 
- * specific prior written permission. 
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND 
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */ 
-
-#ifndef ARM_TRC_PKT_PROC_ETMV4D_IMPL_H_INCLUDED
-#define ARM_TRC_PKT_PROC_ETMV4D_IMPL_H_INCLUDED
-
-#include "etmv4/trc_pkt_proc_etmv4.h"
-#include "etmv4/trc_cmp_cfg_etmv4.h"
-
-class EtmV4DPktProcImpl
-{
-public:
-    EtmV4DPktProcImpl();
-    ~EtmV4DPktProcImpl();
-
-    void Initialise(TrcPktProcEtmV4D *p_interface);
-
-    ocsd_err_t Configure(const EtmV4Config *p_config);
-
-
-    ocsd_datapath_resp_t processData(  const ocsd_trc_index_t index,
-                                        const uint32_t dataBlockSize,
-                                        const uint8_t *pDataBlock,
-                                        uint32_t *numBytesProcessed);
-    ocsd_datapath_resp_t onEOT();
-    ocsd_datapath_resp_t onReset();
-    ocsd_datapath_resp_t onFlush();
-
-protected:
-
-    bool m_isInit;
-    TrcPktProcEtmV4D *m_interface;       /**< The interface to the other decode components */
-    
-    EtmV4Config m_config;
-};
-
-
-#endif // ARM_TRC_PKT_PROC_ETMV4D_IMPL_H_INCLUDED
-
-/* End of File trc_pkt_proc_etmv4d_impl.h */
diff --git a/decoder/source/etmv4/trc_pkt_proc_etmv4i_impl.cpp b/decoder/source/etmv4/trc_pkt_proc_etmv4i.cpp
similarity index 81%
rename from decoder/source/etmv4/trc_pkt_proc_etmv4i_impl.cpp
rename to decoder/source/etmv4/trc_pkt_proc_etmv4i.cpp
index 0607c19..ee05b36 100644
--- a/decoder/source/etmv4/trc_pkt_proc_etmv4i_impl.cpp
+++ b/decoder/source/etmv4/trc_pkt_proc_etmv4i.cpp
@@ -1,8 +1,8 @@
 /*
- * \file       trc_pkt_proc_etmv4i_impl.cpp
- * \brief      OpenCSD : 
+ * \file       trc_pkt_proc_etmv4i.cpp
+ * \brief      OpenCSD : Packet processor for ETMv4
  * 
- * \copyright  Copyright (c) 2015, ARM Limited. All Rights Reserved.
+ * \copyright  Copyright (c) 2015, 2019, ARM Limited. All Rights Reserved.
  */
 
 /* 
@@ -32,87 +32,58 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */ 
 
-#include "trc_pkt_proc_etmv4i_impl.h"
+#include "opencsd/etmv4/trc_pkt_proc_etmv4.h"
+#include "common/ocsd_error.h"
 
-/* Trace raw input buffer class */
-TraceRawBuffer::TraceRawBuffer()
-{
-    m_bufSize = 0;
-    m_bufProcessed = 0;
-    m_pBuffer = 0;
-    pkt = 0;
-}
+#ifdef __GNUC__
+ // G++ doesn't like the ## pasting
+#define ETMV4I_PKTS_NAME "PKTP_ETMV4I"
+#else
+ // VC++ is fine
+#define ETMV4I_PKTS_NAME OCSD_CMPNAME_PREFIX_PKTPROC##"_ETMV4I"
+#endif
 
-// init the buffer
-void TraceRawBuffer::init(const uint32_t size, const uint8_t *rawtrace, std::vector<uint8_t> *out_packet)
-{
-    m_bufSize = size;
-    m_bufProcessed = 0;
-    m_pBuffer = rawtrace;
-    pkt = out_packet;
-}
-
-void TraceRawBuffer::copyByteToPkt()
-{
-    if (!empty()) {
-        pkt->push_back(m_pBuffer[m_bufProcessed]);
-        m_bufProcessed++;
-    }
-}
-uint8_t TraceRawBuffer::peekNextByte()
-{
-    uint8_t val = 0;
-    if (!empty())
-        val = m_pBuffer[m_bufProcessed];
-    return val;
-}
+static const uint32_t ETMV4_SUPPORTED_OP_FLAGS = OCSD_OPFLG_PKTPROC_COMMON;
 
 /* trace etmv4 packet processing class */
-EtmV4IPktProcImpl::EtmV4IPktProcImpl() :
+TrcPktProcEtmV4I::TrcPktProcEtmV4I() : TrcPktProcBase(ETMV4I_PKTS_NAME),
     m_isInit(false),
-    m_interface(0),
     m_first_trace_info(false)
 {
-    
+    m_supported_op_flags = ETMV4_SUPPORTED_OP_FLAGS;
 }
 
-EtmV4IPktProcImpl::~EtmV4IPktProcImpl()
+TrcPktProcEtmV4I::TrcPktProcEtmV4I(int instIDNum) : TrcPktProcBase(ETMV4I_PKTS_NAME, instIDNum),
+    m_isInit(false),
+    m_first_trace_info(false)
+{
+    m_supported_op_flags = ETMV4_SUPPORTED_OP_FLAGS;
+}
+
+
+TrcPktProcEtmV4I::~TrcPktProcEtmV4I()
 {
 }
 
-void EtmV4IPktProcImpl::Initialise(TrcPktProcEtmV4I *p_interface)
+ocsd_err_t TrcPktProcEtmV4I::onProtocolConfig()
 {
-     if(p_interface)
-     {
-         m_interface = p_interface;
-         m_isInit = true;
-     }
-     InitProcessorState();
+    InitProcessorState();
+    m_config = *TrcPktProcBase::getProtocolConfig();
+    BuildIPacketTable();    // packet table based on config
+    m_isInit = true;
+    return OCSD_OK;
 }
 
-ocsd_err_t EtmV4IPktProcImpl::Configure(const EtmV4Config *p_config)
-{
-    ocsd_err_t err = OCSD_OK;
-    if(p_config != 0)
-    {
-        m_config = *p_config;
-        BuildIPacketTable();    // packet table based on config
-    }
-    else
-    {
-        err = OCSD_ERR_INVALID_PARAM_VAL;
-        if(m_isInit)
-            m_interface->LogError(ocsdError(OCSD_ERR_SEV_ERROR,err));
-    }
-    return err;
-}
-
-ocsd_datapath_resp_t EtmV4IPktProcImpl::processData(  const ocsd_trc_index_t index,
+ocsd_datapath_resp_t TrcPktProcEtmV4I::processData(  const ocsd_trc_index_t index,
                                     const uint32_t dataBlockSize,
                                     const uint8_t *pDataBlock,
                                     uint32_t *numBytesProcessed)
 {
     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
+
+    if (!m_isInit)
+        return OCSD_RESP_FATAL_NOT_INIT;
+
     m_trcIn.init(dataBlockSize, pDataBlock, &m_currPacketData);
     m_blockIndex = index;
     bool done = false;
@@ -122,9 +93,6 @@
     {
         try 
         {
-           /* while (((m_blockBytesProcessed < dataBlockSize) ||
-                ((m_blockBytesProcessed == dataBlockSize) && (m_process_state == SEND_PKT))) &&
-                OCSD_DATA_RESP_IS_CONT(resp))*/
             while ( (!m_trcIn.empty() || (m_process_state == SEND_PKT)) &&
                     OCSD_DATA_RESP_IS_CONT(resp)
                 )
@@ -142,7 +110,7 @@
                     else
                     {
                         // unsynced - process data until we see a sync point
-                        m_pIPktFn = &EtmV4IPktProcImpl::iNotSync;
+                        m_pIPktFn = &TrcPktProcEtmV4I::iNotSync;
                         m_curr_packet.type = ETM4_PKT_I_NOTSYNC;
                     }
                     m_process_state = PROC_DATA;
@@ -153,8 +121,6 @@
                     {
                         nextByte = m_trcIn.peekNextByte();
                         m_trcIn.copyByteToPkt();  // move next byte into the packet
-    //                    m_currPacketData.push_back(pDataBlock[m_blockBytesProcessed]);
-    //                    m_blockBytesProcessed++;
                         (this->*m_pIPktFn)(nextByte);
                     }
                     break;
@@ -181,7 +147,7 @@
         catch(ocsdError &err)
         {
             done = true;
-            m_interface->LogError(err);
+            LogError(err);
             if( (err.getErrorCode() == OCSD_ERR_BAD_PACKET_SEQ) ||
                 (err.getErrorCode() == OCSD_ERR_INVALID_PCKT_HDR))
             {
@@ -201,7 +167,7 @@
             /// vv bad at this point.
             resp = OCSD_RESP_FATAL_SYS_ERR;
             const ocsdError &fatal = ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_FAIL,m_packet_index,m_config.getTraceID(),"Unknown System Error decoding trace.");
-            m_interface->LogError(fatal);
+           LogError(fatal);
         }
     } while (!done);
 
@@ -209,9 +175,12 @@
     return resp;
 }
 
-ocsd_datapath_resp_t EtmV4IPktProcImpl::onEOT()
+ocsd_datapath_resp_t TrcPktProcEtmV4I::onEOT()
 {
     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
+    if (!m_isInit)
+        return OCSD_RESP_FATAL_NOT_INIT;
+
     // if we have a partial packet then send to attached sinks
     if(m_currPacketData.size() != 0)
     {
@@ -222,31 +191,37 @@
     return resp;
 }
 
-ocsd_datapath_resp_t EtmV4IPktProcImpl::onReset()
+ocsd_datapath_resp_t TrcPktProcEtmV4I::onReset()
 {
+    if (!m_isInit)
+        return OCSD_RESP_FATAL_NOT_INIT;
+
     // prepare for new decoding session
     InitProcessorState();
     return OCSD_RESP_CONT;
 }
 
-ocsd_datapath_resp_t EtmV4IPktProcImpl::onFlush()
+ocsd_datapath_resp_t TrcPktProcEtmV4I::onFlush()
 {
+    if (!m_isInit)
+        return OCSD_RESP_FATAL_NOT_INIT;
+
     // packet processor never holds on to flushable data (may have partial packet, 
     // but any full packets are immediately sent)
     return OCSD_RESP_CONT;
 }
 
-void EtmV4IPktProcImpl::InitPacketState()
+void TrcPktProcEtmV4I::InitPacketState()
 {
     m_currPacketData.clear();
     m_curr_packet.initNextPacket(); // clear for next packet.
     m_update_on_unsync_packet_index = 0;
 }
 
-void EtmV4IPktProcImpl::InitProcessorState()
+void TrcPktProcEtmV4I::InitProcessorState()
 {
     InitPacketState();
-    m_pIPktFn = &EtmV4IPktProcImpl::iNotSync;
+    m_pIPktFn = &TrcPktProcEtmV4I::iNotSync;
     m_packet_index = 0;
     m_is_sync = false;
     m_first_trace_info = false;
@@ -255,23 +230,23 @@
     m_curr_packet.initStartState();
 }
 
-ocsd_datapath_resp_t EtmV4IPktProcImpl::outputPacket()
+ocsd_datapath_resp_t TrcPktProcEtmV4I::outputPacket()
 {
     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
-    resp = m_interface->outputOnAllInterfaces(m_packet_index,&m_curr_packet,&m_curr_packet.type,m_currPacketData);
+    resp = outputOnAllInterfaces(m_packet_index,&m_curr_packet,&m_curr_packet.type,m_currPacketData);
     return resp;
 }
 
-ocsd_datapath_resp_t EtmV4IPktProcImpl::outputUnsyncedRawPacket()
+ocsd_datapath_resp_t TrcPktProcEtmV4I::outputUnsyncedRawPacket()
 {
     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
     
 
-    m_interface->outputRawPacketToMonitor(m_packet_index,&m_curr_packet,m_dump_unsynced_bytes,&m_currPacketData[0]);
+   outputRawPacketToMonitor(m_packet_index,&m_curr_packet,m_dump_unsynced_bytes,&m_currPacketData[0]);
         
     if(!m_sent_notsync_packet)
     {        
-        resp = m_interface->outputDecodedPacket(m_packet_index,&m_curr_packet);
+        resp = outputDecodedPacket(m_packet_index,&m_curr_packet);
         m_sent_notsync_packet = true;
     }
     
@@ -283,7 +258,7 @@
     return resp;
 }
 
-void EtmV4IPktProcImpl::iNotSync(const uint8_t lastByte)
+void TrcPktProcEtmV4I::iNotSync(const uint8_t lastByte)
 {
     // is it an extension byte? 
     if (lastByte == 0x00) // TBD : add check for forced sync in here?
@@ -309,7 +284,7 @@
     }
 }
 
-void EtmV4IPktProcImpl::iPktNoPayload(const uint8_t lastByte)
+void TrcPktProcEtmV4I::iPktNoPayload(const uint8_t lastByte)
 {
     // some expansion may be required...
     switch(m_curr_packet.type)
@@ -338,26 +313,26 @@
     m_process_state = SEND_PKT; // now just send it....
 }
 
-void EtmV4IPktProcImpl::iPktReserved(const uint8_t lastByte)
+void TrcPktProcEtmV4I::iPktReserved(const uint8_t lastByte)
 {
     m_curr_packet.updateErrType(ETM4_PKT_I_RESERVED, lastByte);   // swap type for err type
     throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_INVALID_PCKT_HDR,m_packet_index,m_config.getTraceID());
 }
 
-void EtmV4IPktProcImpl::iPktInvalidCfg(const uint8_t lastByte)
+void TrcPktProcEtmV4I::iPktInvalidCfg(const uint8_t lastByte)
 {
     m_curr_packet.updateErrType(ETM4_PKT_I_RESERVED_CFG, lastByte);   // swap type for err type
     throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_INVALID_PCKT_HDR, m_packet_index, m_config.getTraceID());
 }
 
-void EtmV4IPktProcImpl::iPktExtension(const uint8_t lastByte)
+void TrcPktProcEtmV4I::iPktExtension(const uint8_t lastByte)
 {
     if(m_currPacketData.size() == 2)
     {
         // not sync and not next by 0x00 - not sync sequence
         if(!m_is_sync && (lastByte != 0x00))
         {
-            m_pIPktFn = &EtmV4IPktProcImpl::iNotSync;
+            m_pIPktFn = &TrcPktProcEtmV4I::iNotSync;
             m_curr_packet.type = ETM4_PKT_I_NOTSYNC;
             return;
         }
@@ -376,7 +351,7 @@
 
         case 0x00:
             m_curr_packet.type = ETM4_PKT_I_ASYNC;
-            m_pIPktFn = &EtmV4IPktProcImpl::iPktASync;  // handle subsequent bytes as async
+            m_pIPktFn = &TrcPktProcEtmV4I::iPktASync;  // handle subsequent bytes as async
             break;
 
         default:
@@ -388,14 +363,14 @@
     }
 }
 
-void EtmV4IPktProcImpl::iPktASync(const uint8_t lastByte)
+void TrcPktProcEtmV4I::iPktASync(const uint8_t lastByte)
 {
     if(lastByte != 0x00)
     {
         // not sync and not next by 0x00 - not sync sequence if < 12
         if(!m_is_sync && m_currPacketData.size() != 12)
         {
-            m_pIPktFn = &EtmV4IPktProcImpl::iNotSync;
+            m_pIPktFn = &TrcPktProcEtmV4I::iNotSync;
             m_curr_packet.type = ETM4_PKT_I_NOTSYNC;
             return;
         }
@@ -428,7 +403,7 @@
     }
 }
 
-void EtmV4IPktProcImpl::iPktTraceInfo(const uint8_t lastByte)
+void TrcPktProcEtmV4I::iPktTraceInfo(const uint8_t lastByte)
 {
     if(m_currPacketData.size() == 1)    // header
     {
@@ -500,7 +475,7 @@
 
 }
 
-void EtmV4IPktProcImpl::iPktTimestamp(const uint8_t lastByte)
+void TrcPktProcEtmV4I::iPktTimestamp(const uint8_t lastByte)
 {
     // process the header byte
     if(m_currPacketData.size() == 1)
@@ -550,7 +525,7 @@
     }
 }
 
-void EtmV4IPktProcImpl::iPktException(const uint8_t lastByte)
+void TrcPktProcEtmV4I::iPktException(const uint8_t lastByte)
 {
     uint16_t excep_type = 0;
 
@@ -582,7 +557,7 @@
     }
 }
 
-void EtmV4IPktProcImpl::iPktCycleCntF123(const uint8_t lastByte)
+void TrcPktProcEtmV4I::iPktCycleCntF123(const uint8_t lastByte)
 {
     ocsd_etmv4_i_pkt_type format = m_curr_packet.type;
 
@@ -657,7 +632,7 @@
     }
 }
 
-void EtmV4IPktProcImpl::iPktSpeclRes(const uint8_t lastByte)
+void TrcPktProcEtmV4I::iPktSpeclRes(const uint8_t lastByte)
 {    
     if(m_currPacketData.size() == 1)
     {
@@ -671,8 +646,10 @@
             case 0x2: m_curr_packet.setAtomPacket(ATOM_PATTERN, 0x3, 2); break; // EE
             case 0x3: m_curr_packet.setAtomPacket(ATOM_PATTERN, 0x0, 1); break; // N
             }
-            if(m_curr_packet.getType() == ETM4_PKT_I_CANCEL_F2)
+            if (m_curr_packet.getType() == ETM4_PKT_I_CANCEL_F2)
                 m_curr_packet.setCancelElements(1);
+            else
+                m_curr_packet.setCancelElements(0);
             m_process_state = SEND_PKT;
             break;
 
@@ -694,13 +671,12 @@
                 m_curr_packet.setCommitElements(field_val);
             else
                 m_curr_packet.setCancelElements(field_val);
-            // TBD: sanity check with max spec depth here?
             m_process_state = SEND_PKT;
         }
     }
 }
 
-void EtmV4IPktProcImpl::iPktCondInstr(const uint8_t lastByte)
+void TrcPktProcEtmV4I::iPktCondInstr(const uint8_t lastByte)
 {
     bool bF1Done = false;
 
@@ -740,7 +716,7 @@
     }
 }
 
-void EtmV4IPktProcImpl::iPktCondResult(const uint8_t lastByte)
+void TrcPktProcEtmV4I::iPktCondResult(const uint8_t lastByte)
 {
     if(m_currPacketData.size() == 1)    
     {
@@ -810,7 +786,7 @@
     }
 }
 
-void EtmV4IPktProcImpl::iPktContext(const uint8_t lastByte)
+void TrcPktProcEtmV4I::iPktContext(const uint8_t lastByte)
 {
     bool bSendPacket = false;
     
@@ -852,7 +828,7 @@
     }
 }
 
-void EtmV4IPktProcImpl::extractAndSetContextInfo(const std::vector<uint8_t> &buffer, const int st_idx)
+void TrcPktProcEtmV4I::extractAndSetContextInfo(const std::vector<uint8_t> &buffer, const int st_idx)
 {
     // on input, buffer index points at the info byte - always present
     uint8_t infoByte = m_currPacketData[st_idx];
@@ -887,7 +863,7 @@
     }
 }
 
-void EtmV4IPktProcImpl::iPktAddrCtxt(const uint8_t lastByte)
+void TrcPktProcEtmV4I::iPktAddrCtxt(const uint8_t lastByte)
 {
     if( m_currPacketData.size() == 1)    
     {        
@@ -955,7 +931,7 @@
     }
 }
 
-void EtmV4IPktProcImpl::iPktShortAddr(const uint8_t lastByte)
+void TrcPktProcEtmV4I::iPktShortAddr(const uint8_t lastByte)
 {
     if (m_currPacketData.size() == 1)
     {
@@ -980,7 +956,7 @@
     }
 }
 
-int EtmV4IPktProcImpl::extractShortAddr(const std::vector<uint8_t> &buffer, const int st_idx, const uint8_t IS, uint32_t &value, int &bits)
+int TrcPktProcEtmV4I::extractShortAddr(const std::vector<uint8_t> &buffer, const int st_idx, const uint8_t IS, uint32_t &value, int &bits)
 {
     int IS_shift = (IS == 0) ? 2 : 1;
     int idx = 0;
@@ -1000,7 +976,7 @@
     return idx;
 }
 
-void EtmV4IPktProcImpl::iPktLongAddr(const uint8_t lastByte)
+void TrcPktProcEtmV4I::iPktLongAddr(const uint8_t lastByte)
 {
     if(m_currPacketData.size() == 1)    
     {
@@ -1044,7 +1020,7 @@
     }
 }
 
-void EtmV4IPktProcImpl::iPktQ(const uint8_t lastByte)
+void TrcPktProcEtmV4I::iPktQ(const uint8_t lastByte)
 {
     if(m_currPacketData.size() == 1)
     {
@@ -1156,7 +1132,7 @@
 
 }
 
-void EtmV4IPktProcImpl::iAtom(const uint8_t lastByte)
+void TrcPktProcEtmV4I::iAtom(const uint8_t lastByte)
 {
     // patterns lsbit = oldest atom, ms bit = newest.
     static const uint32_t f4_patterns[] = {
@@ -1228,32 +1204,32 @@
 }
 
 // header byte processing is table driven.
-void EtmV4IPktProcImpl::BuildIPacketTable()   
+void TrcPktProcEtmV4I::BuildIPacketTable()   
 {
     // initialise everything as reserved.
     for(int i = 0; i < 256; i++)
     {
         m_i_table[i].pkt_type = ETM4_PKT_I_RESERVED;
-        m_i_table[i].pptkFn = &EtmV4IPktProcImpl::iPktReserved;
+        m_i_table[i].pptkFn = &TrcPktProcEtmV4I::iPktReserved;
     }
 
     // 0x00 - extension 
     m_i_table[0x00].pkt_type = ETM4_PKT_I_EXTENSION;
-    m_i_table[0x00].pptkFn   = &EtmV4IPktProcImpl::iPktExtension;
+    m_i_table[0x00].pptkFn   = &TrcPktProcEtmV4I::iPktExtension;
 
     // 0x01 - Trace info
     m_i_table[0x01].pkt_type = ETM4_PKT_I_TRACE_INFO;
-    m_i_table[0x01].pptkFn   = &EtmV4IPktProcImpl::iPktTraceInfo;
+    m_i_table[0x01].pptkFn   = &TrcPktProcEtmV4I::iPktTraceInfo;
 
     // b0000001x - timestamp
     m_i_table[0x02].pkt_type = ETM4_PKT_I_TIMESTAMP;
-    m_i_table[0x02].pptkFn   = &EtmV4IPktProcImpl::iPktTimestamp;
+    m_i_table[0x02].pptkFn   = &TrcPktProcEtmV4I::iPktTimestamp;
     m_i_table[0x03].pkt_type = ETM4_PKT_I_TIMESTAMP;
-    m_i_table[0x03].pptkFn   = &EtmV4IPktProcImpl::iPktTimestamp;
+    m_i_table[0x03].pptkFn   = &TrcPktProcEtmV4I::iPktTimestamp;
 
     // b0000 0100 - trace on
     m_i_table[0x04].pkt_type = ETM4_PKT_I_TRACE_ON;
-    m_i_table[0x04].pptkFn   = &EtmV4IPktProcImpl::iPktNoPayload;
+    m_i_table[0x04].pptkFn   = &TrcPktProcEtmV4I::iPktNoPayload;
 
 
     // b0000 0101 - Funct ret V8M
@@ -1262,30 +1238,30 @@
         (OCSD_IS_V8_ARCH(m_config.archVersion())) &&
         (m_config.FullVersion() >= 0x42))
     {        
-        m_i_table[0x05].pptkFn = &EtmV4IPktProcImpl::iPktNoPayload;
+        m_i_table[0x05].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;
     }
 
     // b0000 0110 - exception 
     m_i_table[0x06].pkt_type = ETM4_PKT_I_EXCEPT;
-    m_i_table[0x06].pptkFn   = &EtmV4IPktProcImpl::iPktException;
+    m_i_table[0x06].pptkFn   = &TrcPktProcEtmV4I::iPktException;
 
     // b0000 0111 - exception return 
     m_i_table[0x07].pkt_type = ETM4_PKT_I_EXCEPT_RTN;
-    m_i_table[0x07].pptkFn = &EtmV4IPktProcImpl::iPktNoPayload;
+    m_i_table[0x07].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;
 
     // b0000 110x - cycle count f2
     // b0000 111x - cycle count f1
     for(int i = 0; i < 4; i++)
     {
         m_i_table[0x0C+i].pkt_type = (i >= 2) ? ETM4_PKT_I_CCNT_F1 : ETM4_PKT_I_CCNT_F2;
-        m_i_table[0x0C+i].pptkFn   = &EtmV4IPktProcImpl::iPktCycleCntF123;
+        m_i_table[0x0C+i].pptkFn   = &TrcPktProcEtmV4I::iPktCycleCntF123;
     }
 
     // b0001 xxxx - cycle count f3
     for(int i = 0; i < 16; i++)
     {
         m_i_table[0x10+i].pkt_type = ETM4_PKT_I_CCNT_F3;
-        m_i_table[0x10+i].pptkFn   = &EtmV4IPktProcImpl::iPktCycleCntF123;
+        m_i_table[0x10+i].pptkFn   = &TrcPktProcEtmV4I::iPktCycleCntF123;
     }
 
     // b0010 0xxx - NDSM
@@ -1293,9 +1269,9 @@
     {
         m_i_table[0x20 + i].pkt_type = ETM4_PKT_I_NUM_DS_MKR;
         if (m_config.enabledDataTrace())
-            m_i_table[0x20+i].pptkFn = &EtmV4IPktProcImpl::iPktNoPayload;
+            m_i_table[0x20+i].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;
         else
-            m_i_table[0x20+i].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg;
+            m_i_table[0x20+i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;
     }
 
     // b0010 10xx, b0010 1100 - UDSM
@@ -1303,43 +1279,40 @@
     {
         m_i_table[0x28+i].pkt_type = ETM4_PKT_I_UNNUM_DS_MKR;
         if (m_config.enabledDataTrace())
-            m_i_table[0x28+i].pptkFn = &EtmV4IPktProcImpl::iPktNoPayload;
+            m_i_table[0x28+i].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;
         else
-            m_i_table[0x28+i].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg;
+            m_i_table[0x28+i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;
     }
 
     // b0010 1101 - commit
     m_i_table[0x2D].pkt_type = ETM4_PKT_I_COMMIT;
-    m_i_table[0x2D].pptkFn   = &EtmV4IPktProcImpl::iPktSpeclRes;
+    m_i_table[0x2D].pptkFn   = &TrcPktProcEtmV4I::iPktSpeclRes;
 
-    // b0010 111x - cancel f1
-    for(int i = 0; i < 2; i++)
-    {
-        // G++ doesn't understand [0x2E+i] so...
-        int idx = i + 0x2E;
-        m_i_table[idx].pkt_type = ETM4_PKT_I_CANCEL_F1;
-        m_i_table[idx].pptkFn   = &EtmV4IPktProcImpl::iPktSpeclRes;
-    }
+    // b0010 111x - cancel f1 (mis pred)
+    m_i_table[0x2E].pkt_type = ETM4_PKT_I_CANCEL_F1;
+    m_i_table[0x2E].pptkFn = &TrcPktProcEtmV4I::iPktSpeclRes;
+    m_i_table[0x2F].pkt_type = ETM4_PKT_I_CANCEL_F1_MISPRED;
+    m_i_table[0x2F].pptkFn = &TrcPktProcEtmV4I::iPktSpeclRes;
 
     // b0011 00xx - mis predict
     for(int i = 0; i < 4; i++)
     {
         m_i_table[0x30+i].pkt_type = ETM4_PKT_I_MISPREDICT;
-        m_i_table[0x30+i].pptkFn   =  &EtmV4IPktProcImpl::iPktSpeclRes;
+        m_i_table[0x30+i].pptkFn   =  &TrcPktProcEtmV4I::iPktSpeclRes;
     }
 
     // b0011 01xx - cancel f2
     for(int i = 0; i < 4; i++)
     {
         m_i_table[0x34+i].pkt_type = ETM4_PKT_I_CANCEL_F2;
-        m_i_table[0x34+i].pptkFn   =  &EtmV4IPktProcImpl::iPktSpeclRes;
+        m_i_table[0x34+i].pptkFn   =  &TrcPktProcEtmV4I::iPktSpeclRes;
     }
 
     // b0011 1xxx - cancel f3
     for(int i = 0; i < 8; i++)
     {
         m_i_table[0x38+i].pkt_type = ETM4_PKT_I_CANCEL_F3;
-        m_i_table[0x38+i].pptkFn   =  &EtmV4IPktProcImpl::iPktSpeclRes;
+        m_i_table[0x38+i].pptkFn   =  &TrcPktProcEtmV4I::iPktSpeclRes;
     }
 
     bool bCondValid = m_config.hasCondTrace() && m_config.enabledCondITrace();
@@ -1349,26 +1322,26 @@
     {
         m_i_table[0x40 + i].pkt_type = ETM4_PKT_I_COND_I_F2;
         if (bCondValid)
-            m_i_table[0x40 + i].pptkFn = &EtmV4IPktProcImpl::iPktCondInstr;
+            m_i_table[0x40 + i].pptkFn = &TrcPktProcEtmV4I::iPktCondInstr;
         else
-            m_i_table[0x40 + i].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg;
+            m_i_table[0x40 + i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;
     }
 
     // b0100 0011 - cond flush
     m_i_table[0x43].pkt_type = ETM4_PKT_I_COND_FLUSH;
     if (bCondValid)
-        m_i_table[0x43].pptkFn = &EtmV4IPktProcImpl::iPktNoPayload;
+        m_i_table[0x43].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;
     else
-        m_i_table[0x43].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg;
+        m_i_table[0x43].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;
 
     // b0100 010x, b0100 0110 - cond res f4
     for (int i = 0; i < 3; i++)
     {
         m_i_table[0x44 + i].pkt_type = ETM4_PKT_I_COND_RES_F4;
         if (bCondValid)
-            m_i_table[0x44 + i].pptkFn = &EtmV4IPktProcImpl::iPktCondResult;
+            m_i_table[0x44 + i].pptkFn = &TrcPktProcEtmV4I::iPktCondResult;
         else
-            m_i_table[0x44 + i].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg;
+            m_i_table[0x44 + i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;
     }
 
     // b0100 100x, b0100 0110 - cond res f2
@@ -1377,17 +1350,17 @@
     {
         m_i_table[0x48 + i].pkt_type = ETM4_PKT_I_COND_RES_F2;
         if (bCondValid)
-            m_i_table[0x48 + i].pptkFn = &EtmV4IPktProcImpl::iPktCondResult;
+            m_i_table[0x48 + i].pptkFn = &TrcPktProcEtmV4I::iPktCondResult;
         else
-            m_i_table[0x48 + i].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg;
+            m_i_table[0x48 + i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;
     }
     for (int i = 0; i < 3; i++)
     {
         m_i_table[0x4C + i].pkt_type = ETM4_PKT_I_COND_RES_F2;
         if (bCondValid)
-            m_i_table[0x4C + i].pptkFn = &EtmV4IPktProcImpl::iPktCondResult;
+            m_i_table[0x4C + i].pptkFn = &TrcPktProcEtmV4I::iPktCondResult;
         else
-            m_i_table[0x4C + i].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg;
+            m_i_table[0x4C + i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;
     }
 
     // b0101xxxx - cond res f3
@@ -1395,9 +1368,9 @@
     {
         m_i_table[0x50 + i].pkt_type = ETM4_PKT_I_COND_RES_F3;
         if (bCondValid)
-            m_i_table[0x50 + i].pptkFn = &EtmV4IPktProcImpl::iPktCondResult;
+            m_i_table[0x50 + i].pptkFn = &TrcPktProcEtmV4I::iPktCondResult;
         else
-            m_i_table[0x50 + i].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg;
+            m_i_table[0x50 + i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;
     }
 
     // b011010xx - cond res f1
@@ -1405,24 +1378,24 @@
     {
         m_i_table[0x68 + i].pkt_type = ETM4_PKT_I_COND_RES_F1;
         if (bCondValid)
-            m_i_table[0x68 + i].pptkFn = &EtmV4IPktProcImpl::iPktCondResult;
+            m_i_table[0x68 + i].pptkFn = &TrcPktProcEtmV4I::iPktCondResult;
         else
-            m_i_table[0x68 + i].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg;
+            m_i_table[0x68 + i].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;
     }
 
     // b0110 1100 - cond instr f1
     m_i_table[0x6C].pkt_type = ETM4_PKT_I_COND_I_F1;
     if (bCondValid)
-        m_i_table[0x6C].pptkFn = &EtmV4IPktProcImpl::iPktCondInstr;
+        m_i_table[0x6C].pptkFn = &TrcPktProcEtmV4I::iPktCondInstr;
     else
-        m_i_table[0x6C].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg;
+        m_i_table[0x6C].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;
 
     // b0110 1101 - cond instr f3
     m_i_table[0x6D].pkt_type = ETM4_PKT_I_COND_I_F3;
     if (bCondValid)
-        m_i_table[0x6D].pptkFn = &EtmV4IPktProcImpl::iPktCondInstr;
+        m_i_table[0x6D].pptkFn = &TrcPktProcEtmV4I::iPktCondInstr;
     else
-        m_i_table[0x6D].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg;
+        m_i_table[0x6D].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;
 
     // b0110111x - cond res f1
     for (int i = 0; i < 2; i++)
@@ -1430,30 +1403,30 @@
         // G++ cannot understand [0x6E+i] so change these round
         m_i_table[i + 0x6E].pkt_type = ETM4_PKT_I_COND_RES_F1;
         if (bCondValid)
-            m_i_table[i + 0x6E].pptkFn = &EtmV4IPktProcImpl::iPktCondResult;
+            m_i_table[i + 0x6E].pptkFn = &TrcPktProcEtmV4I::iPktCondResult;
         else
-            m_i_table[i + 0x6E].pptkFn = &EtmV4IPktProcImpl::iPktInvalidCfg;
+            m_i_table[i + 0x6E].pptkFn = &TrcPktProcEtmV4I::iPktInvalidCfg;
     }
 
     // ETM 4.3 introduces ignore packets
     if (m_config.FullVersion() >= 0x43)
     {
         m_i_table[0x70].pkt_type = ETM4_PKT_I_IGNORE;
-        m_i_table[0x70].pptkFn = &EtmV4IPktProcImpl::iPktNoPayload;
+        m_i_table[0x70].pptkFn = &TrcPktProcEtmV4I::iPktNoPayload;
     }
 
     // b01110001 - b01111111 - event trace
     for(int i = 0; i < 15; i++)
     {
         m_i_table[0x71+i].pkt_type = ETM4_PKT_I_EVENT;
-        m_i_table[0x71+i].pptkFn   = &EtmV4IPktProcImpl::iPktNoPayload;
+        m_i_table[0x71+i].pptkFn   = &TrcPktProcEtmV4I::iPktNoPayload;
     }
     
     // 0b1000 000x - context 
     for(int i = 0; i < 2; i++)
     {
         m_i_table[0x80+i].pkt_type = ETM4_PKT_I_CTXT;
-        m_i_table[0x80+i].pptkFn   = &EtmV4IPktProcImpl::iPktContext;
+        m_i_table[0x80+i].pptkFn   = &TrcPktProcEtmV4I::iPktContext;
     }
 
     // 0b1000 0010 to b1000 0011 - addr with ctxt
@@ -1461,27 +1434,27 @@
     for(int i = 0; i < 2; i++)
     {
         m_i_table[0x82+i].pkt_type =  (i == 0) ? ETM4_PKT_I_ADDR_CTXT_L_32IS0 : ETM4_PKT_I_ADDR_CTXT_L_32IS1;
-        m_i_table[0x82+i].pptkFn   = &EtmV4IPktProcImpl::iPktAddrCtxt;
+        m_i_table[0x82+i].pptkFn   = &TrcPktProcEtmV4I::iPktAddrCtxt;
     }
 
     for(int i = 0; i < 2; i++)
     {
         m_i_table[0x85+i].pkt_type = (i == 0) ? ETM4_PKT_I_ADDR_CTXT_L_64IS0 : ETM4_PKT_I_ADDR_CTXT_L_64IS1;
-        m_i_table[0x85+i].pptkFn   = &EtmV4IPktProcImpl::iPktAddrCtxt;
+        m_i_table[0x85+i].pptkFn   = &TrcPktProcEtmV4I::iPktAddrCtxt;
     }
 
     // 0b1001 0000 to b1001 0010 - exact match addr
     for(int i = 0; i < 3; i++)
     {
         m_i_table[0x90+i].pkt_type = ETM4_PKT_I_ADDR_MATCH;
-        m_i_table[0x90+i].pptkFn   = &EtmV4IPktProcImpl::iPktNoPayload;
+        m_i_table[0x90+i].pptkFn   = &TrcPktProcEtmV4I::iPktNoPayload;
     }
 
     // b1001 0101 - b1001 0110 - addr short address
     for(int i = 0; i < 2; i++)
     {
         m_i_table[0x95+i].pkt_type =  (i == 0) ? ETM4_PKT_I_ADDR_S_IS0 : ETM4_PKT_I_ADDR_S_IS1;
-        m_i_table[0x95+i].pptkFn   = &EtmV4IPktProcImpl::iPktShortAddr;
+        m_i_table[0x95+i].pptkFn   = &TrcPktProcEtmV4I::iPktShortAddr;
     }
 
     // b10011010 - b10011011 - addr long address 
@@ -1489,12 +1462,12 @@
     for(int i = 0; i < 2; i++)
     {
         m_i_table[0x9A+i].pkt_type =  (i == 0) ? ETM4_PKT_I_ADDR_L_32IS0 : ETM4_PKT_I_ADDR_L_32IS1;
-        m_i_table[0x9A+i].pptkFn   = &EtmV4IPktProcImpl::iPktLongAddr;
+        m_i_table[0x9A+i].pptkFn   = &TrcPktProcEtmV4I::iPktLongAddr;
     }
     for(int i = 0; i < 2; i++)
     {
         m_i_table[0x9D+i].pkt_type =  (i == 0) ? ETM4_PKT_I_ADDR_L_64IS0 : ETM4_PKT_I_ADDR_L_64IS1;
-        m_i_table[0x9D+i].pptkFn   = &EtmV4IPktProcImpl::iPktLongAddr;
+        m_i_table[0x9D+i].pptkFn   = &TrcPktProcEtmV4I::iPktLongAddr;
     }
     
     // b1010xxxx - Q packet
@@ -1515,7 +1488,7 @@
         default:
             // if this config supports Q elem - otherwise reserved again.
             if (m_config.hasQElem())
-                m_i_table[0xA0 + i].pptkFn = &EtmV4IPktProcImpl::iPktQ;
+                m_i_table[0xA0 + i].pptkFn = &TrcPktProcEtmV4I::iPktQ;
         }
     }
 
@@ -1523,46 +1496,46 @@
     for(int i = 0xC0; i <= 0xD4; i++)   // atom f6
     {
         m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F6;
-        m_i_table[i].pptkFn   = &EtmV4IPktProcImpl::iAtom;
+        m_i_table[i].pptkFn   = &TrcPktProcEtmV4I::iAtom;
     }
     for(int i = 0xD5; i <= 0xD7; i++)  // atom f5
     {
         m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F5;
-        m_i_table[i].pptkFn   = &EtmV4IPktProcImpl::iAtom;
+        m_i_table[i].pptkFn   = &TrcPktProcEtmV4I::iAtom;
     }
     for(int i = 0xD8; i <= 0xDB; i++)  // atom f2
     {
         m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F2;
-        m_i_table[i].pptkFn   = &EtmV4IPktProcImpl::iAtom;
+        m_i_table[i].pptkFn   = &TrcPktProcEtmV4I::iAtom;
     }
     for(int i = 0xDC; i <= 0xDF; i++)  // atom f4
     {
         m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F4;
-        m_i_table[i].pptkFn   = &EtmV4IPktProcImpl::iAtom;
+        m_i_table[i].pptkFn   = &TrcPktProcEtmV4I::iAtom;
     }
     for(int i = 0xE0; i <= 0xF4; i++)  // atom f6
     {
         m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F6;
-        m_i_table[i].pptkFn   = &EtmV4IPktProcImpl::iAtom;
+        m_i_table[i].pptkFn   = &TrcPktProcEtmV4I::iAtom;
     }
     
     // atom f5
     m_i_table[0xF5].pkt_type = ETM4_PKT_I_ATOM_F5;
-    m_i_table[0xF5].pptkFn   = &EtmV4IPktProcImpl::iAtom;
+    m_i_table[0xF5].pptkFn   = &TrcPktProcEtmV4I::iAtom;
 
     for(int i = 0xF6; i <= 0xF7; i++)  // atom f1
     {
         m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F1;
-        m_i_table[i].pptkFn   = &EtmV4IPktProcImpl::iAtom;
+        m_i_table[i].pptkFn   = &TrcPktProcEtmV4I::iAtom;
     }
     for(int i = 0xF8; i <= 0xFF; i++)  // atom f3
     {
         m_i_table[i].pkt_type = ETM4_PKT_I_ATOM_F3;
-        m_i_table[i].pptkFn   = &EtmV4IPktProcImpl::iAtom;
+        m_i_table[i].pptkFn   = &TrcPktProcEtmV4I::iAtom;
     }
 }
 
- unsigned EtmV4IPktProcImpl::extractContField(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint32_t &value, const unsigned byte_limit /*= 5*/)
+ unsigned TrcPktProcEtmV4I::extractContField(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint32_t &value, const unsigned byte_limit /*= 5*/)
 {
     unsigned idx = 0;
     bool lastByte = false;
@@ -1586,7 +1559,7 @@
     return idx;
 }
 
-unsigned EtmV4IPktProcImpl::extractContField64(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint64_t &value, const unsigned byte_limit /*= 9*/)
+unsigned TrcPktProcEtmV4I::extractContField64(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint64_t &value, const unsigned byte_limit /*= 9*/)
 {
     unsigned idx = 0;
     bool lastByte = false;
@@ -1610,7 +1583,7 @@
     return idx;
 }
 
- unsigned EtmV4IPktProcImpl::extractCondResult(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint32_t& key, uint8_t &result)
+ unsigned TrcPktProcEtmV4I::extractCondResult(const std::vector<uint8_t> &buffer, const unsigned st_idx, uint32_t& key, uint8_t &result)
 {
     unsigned idx = 0;
     bool lastByte = false;
@@ -1644,7 +1617,7 @@
     return idx;
 }
 
-int EtmV4IPktProcImpl::extract64BitLongAddr(const std::vector<uint8_t> &buffer, const int st_idx, const uint8_t IS, uint64_t &value)
+int TrcPktProcEtmV4I::extract64BitLongAddr(const std::vector<uint8_t> &buffer, const int st_idx, const uint8_t IS, uint64_t &value)
 {
     value = 0;
     if(IS == 0)
@@ -1666,7 +1639,7 @@
     return 8;    
 }
 
-int EtmV4IPktProcImpl::extract32BitLongAddr(const std::vector<uint8_t> &buffer, const int st_idx, const uint8_t IS, uint32_t &value)
+int TrcPktProcEtmV4I::extract32BitLongAddr(const std::vector<uint8_t> &buffer, const int st_idx, const uint8_t IS, uint32_t &value)
 {
     value = 0;
     if(IS == 0)
@@ -1684,11 +1657,11 @@
     return 4;
 }
 
-void EtmV4IPktProcImpl::throwBadSequenceError(const char *pszExtMsg)
+void TrcPktProcEtmV4I::throwBadSequenceError(const char *pszExtMsg)
 {
     m_curr_packet.updateErrType(ETM4_PKT_I_BAD_SEQUENCE);   // swap type for err type
     throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_BAD_PACKET_SEQ,m_packet_index,m_config.getTraceID(),pszExtMsg);
 }
 
 
-/* End of File trc_pkt_proc_etmv4i_impl.cpp */
+/* End of File trc_pkt_proc_etmv4i.cpp */
diff --git a/decoder/source/ocsd_dcd_tree.cpp b/decoder/source/ocsd_dcd_tree.cpp
index cf75e56..be15e36 100644
--- a/decoder/source/ocsd_dcd_tree.cpp
+++ b/decoder/source/ocsd_dcd_tree.cpp
@@ -111,6 +111,7 @@
         destroyDecodeElement(i);
     }
     PktPrinterFact::destroyAllPrinters(m_printer_list);
+    delete m_frame_deformatter_root;
 }
 
 
diff --git a/decoder/source/ocsd_gen_elem_stack.cpp b/decoder/source/ocsd_gen_elem_stack.cpp
new file mode 100644
index 0000000..bb75842
--- /dev/null
+++ b/decoder/source/ocsd_gen_elem_stack.cpp
@@ -0,0 +1,196 @@
+/*
+* \file       ocsd_gen_elem_stack.cpp
+* \brief      OpenCSD : List of Generic trace elements for output.
+*
+* \copyright  Copyright (c) 2020, ARM Limited. All Rights Reserved.
+*/
+
+
+/*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+*
+* 1. Redistributions of source code must retain the above copyright notice,
+* this list of conditions and the following disclaimer.
+*
+* 2. Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following disclaimer in the documentation
+* and/or other materials provided with the distribution.
+*
+* 3. Neither the name of the copyright holder nor the names of its contributors
+* may be used to endorse or promote products derived from this software without
+* specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "common/ocsd_gen_elem_stack.h"
+
+OcsdGenElemStack::OcsdGenElemStack() :
+    m_pElemArray(0),
+    m_elemArraySize(0),
+    m_elem_to_send(0),
+    m_curr_elem_idx(0),
+    m_send_elem_idx(0),
+    m_CSID(0),
+    m_is_init(false)
+{
+
+}
+
+OcsdGenElemStack::~OcsdGenElemStack()
+{
+    for (int i = 0; i<m_elemArraySize; i++)
+    {
+        delete m_pElemArray[i].pElem;
+    }
+    delete [] m_pElemArray;
+    m_pElemArray = 0;
+}
+
+ocsd_err_t OcsdGenElemStack::addElem(const ocsd_trc_index_t trc_pkt_idx)
+{
+    ocsd_err_t err = OCSD_OK;
+
+    if (((m_curr_elem_idx + 1) == m_elemArraySize) || !m_pElemArray)
+    {
+        err = growArray();
+        if (err)
+            return err;
+    }
+
+    // if there is a least one element then copy and increment
+    // otherwise we are at base of stack.
+    if (m_elem_to_send)
+    {
+        copyPersistentData(m_curr_elem_idx, m_curr_elem_idx + 1);
+        m_curr_elem_idx++;
+    }
+    m_pElemArray[m_curr_elem_idx].trc_pkt_idx = trc_pkt_idx;
+    m_elem_to_send++;
+    return err;
+}
+
+ocsd_err_t OcsdGenElemStack::addElemType(const ocsd_trc_index_t trc_pkt_idx, ocsd_gen_trc_elem_t elem_type)
+{
+    ocsd_err_t err = addElem(trc_pkt_idx);
+    if (!err)
+        getCurrElem().setType(elem_type);
+    return err;
+}
+
+ocsd_err_t OcsdGenElemStack::resetElemStack()
+{
+    ocsd_err_t err = OCSD_OK;
+    if (!m_pElemArray)
+    {
+        err = growArray();
+        if (err)
+            return err;
+    }
+
+    if (!isInit())
+        return OCSD_ERR_NOT_INIT;
+
+    resetIndexes();
+    return err;
+}
+
+void OcsdGenElemStack::resetIndexes()
+{
+    // last time there was more than one element on stack
+    if (m_curr_elem_idx > 0)
+        copyPersistentData(m_curr_elem_idx, 0);
+
+    // indexes to bottom of stack, nothing in use at present
+    m_curr_elem_idx = 0;
+    m_send_elem_idx = 0;
+    m_elem_to_send = 0;
+}
+
+ocsd_datapath_resp_t OcsdGenElemStack::sendElements()
+{
+    ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
+    if (!isInit())
+        return OCSD_RESP_FATAL_NOT_INIT;
+
+    while (m_elem_to_send && OCSD_DATA_RESP_IS_CONT(resp))
+    {
+        resp = m_sendIf->first()->TraceElemIn(m_pElemArray[m_send_elem_idx].trc_pkt_idx, m_CSID, *(m_pElemArray[m_send_elem_idx].pElem));
+        m_send_elem_idx++;
+        m_elem_to_send--;
+    }
+
+    // clear the indexes if we are done.
+    if (!m_elem_to_send)
+        resetIndexes();
+    return resp;
+}
+
+ocsd_err_t OcsdGenElemStack::growArray()
+{
+    elemPtr_t *p_new_array = 0;
+    const int increment = 4;
+    
+    p_new_array = new (std::nothrow) elemPtr_t[m_elemArraySize + increment];
+
+    if (p_new_array != 0)
+    {
+        OcsdTraceElement *pElem = 0;
+
+        // fill the last increment elements with new objects
+        for (int i = 0; i < increment; i++)
+        {
+            pElem = new (std::nothrow) OcsdTraceElement();
+            if (!pElem)
+                return OCSD_ERR_MEM;
+            pElem->init();
+            p_new_array[m_elemArraySize + i].pElem = pElem;
+        }
+
+        // copy the existing objects from the old array to the start of the new one
+        if (m_elemArraySize > 0)
+        {            
+            for (int i = 0; i < m_elemArraySize; i++)
+            {
+                p_new_array[i].pElem = m_pElemArray[i].pElem;
+                p_new_array[i].trc_pkt_idx = m_pElemArray[i].trc_pkt_idx;
+            }
+        }
+
+        // delete the old pointer array.
+        delete[] m_pElemArray;
+        m_elemArraySize += increment;
+        m_pElemArray = p_new_array;
+    }
+    else
+        return OCSD_ERR_MEM;
+
+    return OCSD_OK;
+}
+
+void OcsdGenElemStack::copyPersistentData(int src, int dst)
+{
+    m_pElemArray[dst].pElem->copyPersistentData(*(m_pElemArray[src].pElem));
+}
+
+const bool OcsdGenElemStack::isInit()
+{
+    if (!m_is_init) {
+        if (m_elemArraySize && m_pElemArray && m_sendIf)
+            m_is_init = true;
+    }
+    return m_is_init;
+}
+
+
+/* End of File ocsd_gen_elem_stack.cpp */
diff --git a/decoder/source/ptm/trc_pkt_decode_ptm.cpp b/decoder/source/ptm/trc_pkt_decode_ptm.cpp
index 94ed5ac..7abee84 100644
--- a/decoder/source/ptm/trc_pkt_decode_ptm.cpp
+++ b/decoder/source/ptm/trc_pkt_decode_ptm.cpp
@@ -67,6 +67,7 @@
         case NO_SYNC:
             // no sync - output a no sync packet then transition to wait sync.
             m_output_elem.elem_type = OCSD_GEN_TRC_ELEM_NO_SYNC;
+            m_output_elem.unsync_eot_info = m_unsync_info;
             resp = outputTraceElement(m_output_elem);
             m_curr_state = (m_curr_packet_in->getType() == PTM_PKT_A_SYNC) ? WAIT_ISYNC : WAIT_SYNC;
             bPktDone = true;
@@ -108,6 +109,7 @@
     // shouldn't be any packets left to be processed - flush shoudl have done this.
     // just output the end of trace marker
     m_output_elem.setType(OCSD_GEN_TRC_ELEM_EO_TRACE);
+    m_output_elem.setUnSyncEOTReason(UNSYNC_EOT);
     resp = outputTraceElement(m_output_elem);
     return resp;
 }
@@ -115,6 +117,7 @@
 ocsd_datapath_resp_t TrcPktDecodePtm::onReset()
 {
     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
+    m_unsync_info = UNSYNC_RESET_DECODER;
     resetDecoder();
     return resp;
 }
@@ -191,6 +194,7 @@
     m_instr_info.pe_type.profile = profile_Unknown;
     m_instr_info.pe_type.arch = ARCH_UNKNOWN;
     m_instr_info.dsb_dmb_waypoints = 0;
+    m_unsync_info = UNSYNC_INIT_DECODER;
     resetDecoder();
 }
 
@@ -504,11 +508,15 @@
     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
     bool bWPFound = false;
     std::ostringstream oss;
+    ocsd_err_t err = OCSD_OK;
 
     m_instr_info.instr_addr = m_curr_pe_state.instr_addr;
     m_instr_info.isa = m_curr_pe_state.isa;
 
-    ocsd_err_t err = traceInstrToWP(bWPFound,traceWPOp,nextAddrMatch);
+    // set type (which resets out-elem) before traceInstrToWP modifies out-elem values
+    m_output_elem.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE); 
+    
+    err = traceInstrToWP(bWPFound,traceWPOp,nextAddrMatch);
     if(err != OCSD_OK)
     {
         if(err == OCSD_ERR_UNSUPPORTED_ISA)
@@ -576,7 +584,6 @@
             break;
         }
         
-        m_output_elem.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE);
         m_output_elem.setLastInstrInfo((A == ATOM_E),m_instr_info.type, m_instr_info.sub_type,m_instr_info.instr_size);
         m_output_elem.setISA(m_curr_pe_state.isa);
         if(m_curr_packet_in->hasCC())
@@ -595,7 +602,6 @@
         if(m_output_elem.st_addr != m_output_elem.en_addr)
         {
             // some trace before we were out of memory access range
-            m_output_elem.setType(OCSD_GEN_TRC_ELEM_INSTR_RANGE);
             m_output_elem.setLastInstrInfo(true,m_instr_info.type, m_instr_info.sub_type,m_instr_info.instr_size);
             m_output_elem.setISA(m_curr_pe_state.isa);
             m_output_elem.setLastInstrCond(m_instr_info.is_conditional);
diff --git a/decoder/source/stm/trc_pkt_decode_stm.cpp b/decoder/source/stm/trc_pkt_decode_stm.cpp
index a47e963..1bb8d73 100644
--- a/decoder/source/stm/trc_pkt_decode_stm.cpp
+++ b/decoder/source/stm/trc_pkt_decode_stm.cpp
@@ -68,6 +68,7 @@
         {
         case NO_SYNC:
             m_output_elem.setType(OCSD_GEN_TRC_ELEM_NO_SYNC);
+            m_output_elem.setUnSyncEOTReason(m_unsync_info);
             resp = outputTraceElement(m_output_elem);
             m_curr_state = WAIT_SYNC;
             break;
@@ -90,6 +91,7 @@
 {
     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
     m_output_elem.setType(OCSD_GEN_TRC_ELEM_EO_TRACE);
+    m_output_elem.setUnSyncEOTReason(UNSYNC_EOT);
     resp = outputTraceElement(m_output_elem);
     return resp;
 }
@@ -97,6 +99,7 @@
 ocsd_datapath_resp_t TrcPktDecodeStm::onReset()
 {
     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
+    m_unsync_info = UNSYNC_RESET_DECODER;
     resetDecoder();
     return resp;
 }
@@ -127,7 +130,7 @@
     // base decoder state - STM requires no memory and instruction decode.
     setUsesMemAccess(false);
     setUsesIDecode(false);
-
+    m_unsync_info = UNSYNC_INIT_DECODER;
     resetDecoder();
 }
 
@@ -166,6 +169,7 @@
     case STM_PKT_BAD_SEQUENCE:   /**< Incorrect protocol sequence */
     case STM_PKT_RESERVED:
         resp = OCSD_RESP_FATAL_INVALID_DATA;
+        m_unsync_info = UNSYNC_BAD_PACKET;
     case STM_PKT_NOTSYNC:
         resetDecoder();
         break;
diff --git a/decoder/source/trc_component.cpp b/decoder/source/trc_component.cpp
index 47200a1..dae92d4 100644
--- a/decoder/source/trc_component.cpp
+++ b/decoder/source/trc_component.cpp
@@ -41,7 +41,13 @@
     {
         m_pComp = 0;
     };
-    virtual ~ errLogAttachMonitor() {};
+    virtual ~ errLogAttachMonitor()
+    {
+        if (m_pComp)
+            m_pComp->getErrorLogAttachPt()->set_notifier(0);
+        m_pComp = 0;
+        
+    };
     virtual void attachNotify(const int num_attached)
     {
         if(m_pComp)
@@ -73,6 +79,8 @@
 
 TraceComponent::~TraceComponent()
 {
+    if (m_pErrAttachMon)
+        delete m_pErrAttachMon;
 }
 
 void TraceComponent::Init(const std::string &name)
@@ -140,9 +148,7 @@
 
 ocsd_err_t TraceComponent::setComponentOpMode(uint32_t op_flags)
 {
-    if( (~m_supported_op_flags & op_flags) != 0)
-        return OCSD_ERR_INVALID_PARAM_VAL;
-    m_op_flags = op_flags;
+    m_op_flags = op_flags & m_supported_op_flags;
     return OCSD_OK;
 }
 
diff --git a/decoder/source/trc_gen_elem.cpp b/decoder/source/trc_gen_elem.cpp
index b3ec75f..544f906 100644
--- a/decoder/source/trc_gen_elem.cpp
+++ b/decoder/source/trc_gen_elem.cpp
@@ -46,6 +46,7 @@
     {"OCSD_GEN_TRC_ELEM_EO_TRACE","End of the available trace in the buffer."},
     {"OCSD_GEN_TRC_ELEM_PE_CONTEXT","PE status update / change (arch, ctxtid, vmid etc)."},
     {"OCSD_GEN_TRC_ELEM_INSTR_RANGE","Traced N consecutive instructions from addr (no intervening events or data elements), may have data assoc key"},
+    {"OCSD_GEN_TRC_ELEM_I_RANGE_NOPATH","Traced N instructions in a range, but incomplete information as to program execution path from start to end of range"},
     {"OCSD_GEN_TRC_ELEM_ADDR_NACC","Tracing in inaccessible memory area."},
     {"OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN","Tracing unknown address area."},
     {"OCSD_GEN_TRC_ELEM_EXCEPTION","Exception"},
@@ -62,7 +63,8 @@
     "BR  ",
     "iBR ",
     "ISB ",
-    "DSB.DMB"
+    "DSB.DMB",
+    "WFI.WFE"
 };
 
 #define T_SIZE (sizeof(instr_type) / sizeof(const char *))
@@ -94,6 +96,16 @@
    "Unk"       /**< ISA not yet known */
 };
 
+static const char *s_unsync_reason[] = {
+    "undefined",            // UNSYNC_UNKNOWN - unknown /undefined
+    "init-decoder",         // UNSYNC_INIT_DECODER - decoder intialisation - start of trace.
+    "reset-decoder",        // UNSYNC_RESET_DECODER - decoder reset.
+    "overflow",             // UNSYNC_OVERFLOW - overflow packet - need to re-sync
+    "discard",              // UNSYNC_DISCARD - specl trace discard - need to re-sync
+    "bad-packet",           // UNSYNC_BAD_PACKET - bad packet at input - resync to restart.
+    "end-of-trace",         // UNSYNC_EOT - end of trace info.
+};
+
 void OcsdTraceElement::toString(std::string &str) const
 {
     std::ostringstream oss;
@@ -122,6 +134,11 @@
             oss << " 0x" << std::hex << st_addr << " ";
             break;
 
+        case OCSD_GEN_TRC_ELEM_I_RANGE_NOPATH:
+            oss << "first 0x" << std::hex << st_addr << ":[next 0x" << en_addr << "] ";
+            oss << "num_i(" << std::dec << num_instr_range << ") ";
+            break;
+
         case OCSD_GEN_TRC_ELEM_EXCEPTION:
             if (excep_ret_addr == 1)
             {
@@ -167,6 +184,12 @@
                 oss << " Numbered:" << std::dec << trace_event.ev_number << "; ";
             break;
 
+        case OCSD_GEN_TRC_ELEM_EO_TRACE:
+        case OCSD_GEN_TRC_ELEM_NO_SYNC:
+            if (unsync_eot_info <= UNSYNC_EOT)
+                oss << " [" << s_unsync_reason[unsync_eot_info] << "]";
+            break;
+
         default: break;
         }
         if(has_cc)
diff --git a/decoder/tests/auto-fdo/autofdo.md b/decoder/tests/auto-fdo/autofdo.md
index b1f2241..69ed152 100644
--- a/decoder/tests/auto-fdo/autofdo.md
+++ b/decoder/tests/auto-fdo/autofdo.md
@@ -99,6 +99,8 @@
 appropriate branch using git or generating patches (using `git
 format-patch`).
 
+For 5.x based kernel onwards, the only patch which needs to be applied is the one enabling strobing - etm4x: `Enable strobing of ETM`.
+
 For 4.9 based kernels, use the `coresight-4.9-etr-etm_strobe` branch:
 
 ```
@@ -129,7 +131,7 @@
 
 The CoreSight trace drivers must also be enabled in the kernel
 configuration.  This can be done using the configuration menu (`make
-menuconfig`), selecting `Kernel hacking` / `CoreSight Tracing Support` and
+menuconfig`), selecting `Kernel hacking` / `arm64 Debugging`  /`CoreSight Tracing Support` and
 enabling all options, or by setting the following in the configuration
 file:
 
@@ -165,11 +167,15 @@
 
 ```
 # ls /sys/bus/coresight/devices/
-28440000.etm  28540000.etm  28640000.etm  28740000.etm
-28c03000.funnel  28c04000.etf  28c05000.replicator  28c06000.etr
-28c07000.tpiu
+etm0  etm2  etm4  etm6  funnel0  funnel2  funnel4      stm0      tmc_etr0
+etm1  etm3  etm5  etm7  funnel1  funnel3  replicator0  tmc_etf0
 ```
 
+The naming convention for etm devices can be different according to the kernel version you're using.
+For more information about the naming scheme, please check out the [Linux Kernel Documentation](https://www.kernel.org/doc/html/latest/trace/coresight/coresight.html#device-naming-scheme)
+
+If `/sys/bus/coresight/devices/` is empty, you may want to check out your Kernel configuration to make sure your .config file is including CoreSight dependencies, such as the clock.
+
 ### Perf tools
 
 The perf tool is used to capture execution trace, configuring the trace
@@ -180,9 +186,12 @@
 on the target.  This can be built from the same kernel sources with
 
 ```
-make -C tools/perf ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- 
+make -C tools/perf CORESIGHT=1 VF=1 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
 ```
 
+When specifying CORESIGHT=1, perf will be built using the installed OpenCSD library.
+If you are cross compiling, then additional setup is required to ensure the build process links against the correct version of the library.
+
 If the post-processing (`perf inject`) of the captured data is not being
 done on the target, then the OpenCSD library is not required for this build
 of perf.
@@ -193,13 +202,22 @@
 parameters.  For example:
 
 ```
-perf record -e cs_etm/@28c06000.etr/u --per-thread -- /bin/ls
+perf record -e cs_etm/@tmc_etr0/u --per-thread -- /bin/ls
 ```
-    
-Will record the userspace execution of '/bin/ls' into the ETR located at
-0x28c06000.  Note the `--per-thread` option is required - perf currently
-only supports trace of a single thread of execution.  CPU wide trace is a
-work in progresss.
+
+Will record the userspace execution of '/bin/ls' using tmc_etr0 as sink.
+
+## Capturing modes
+
+You can trace a single-threaded program in two different ways:
+
+1. By specifying `--per-thread`, and in this case the CoreSight subsystem will
+record only a trace relative to the given program.
+
+2. By NOT specifying `--per-thread`, and in this case CPU-wide tracing will
+be enabled. In this scenario the trace will contain both the target program trace
+and other workloads that were executing on the same CPU
+
 
 
 ## Processing trace and profiles
@@ -241,26 +259,42 @@
 and a period of 10000 - this will collect 5000 cycles of trace every 50M
 cycles.  With these proof-of-concept patches, the strobe parameters are
 configured via sysfs - each ETM will have `strobe_window` and
-`strobe_period` parameters in `/sys/bus/coresight/devices/NNNNNNNN.etm` and
+`strobe_period` parameters in `/sys/bus/coresight/devices/<sink>` and
 these values will have to be written to each (In a future version, this
-will be integrated into the drivers and perf tool).  The `record.sh`
-script in this directory [`<opencsd>/decoder/tests/auto-fdo`] automates this process.
+will be integrated into the drivers and perf tool).
+The `set_strobing.sh` script in this directory [`<opencsd>/decoder/tests/auto-fdo`] automates this process.
 
 To collect trace from an application using ETM strobing, run:
 
 ```
-taskset -c 0 ./record.sh --strobe 5000 10000 28c06000.etr ./my_application arg1 arg2
+sudo ./set_strobing.sh 5000 10000
+perf record -e cs_etm/@tmc_etr0/u --per-thread -- <your app>"
 ```
 
-The taskset command is used to ensure the process stays on the same CPU
-during execution.
-
 The raw trace can be examined using the `perf report` command:
 
 ```
 perf report -D -i perf.data --stdio
 ```
 
+Perf needs to be built from your linux kernel version souce code repository against the OpenCSD library in order to be able to properly read ETM-gathered samples and post-process them.
+If running `perf report` produces an error like:
+
+```
+0x1f8 [0x268]: failed to process type: 70 [Operation not permitted]
+Error:
+failed to process sample
+```
+or
+
+```
+"file uses a more recent and unsupported ABI (8 bytes extra). incompatible file format".
+```
+
+You are probably using a perf version which is not using this library: please make sure to install this project in your system by either compiling it from [Source Code]( <https://github.com/Linaro/OpenCSD>) from v0.9.1 or later and compile perf using this library.
+Otherwise, this project is packaged for debian (install the libopencsd0, libopencsd-dev packages).
+
+
 For example:
 
 ```
@@ -295,6 +329,8 @@
 decodes the execution trace and generates periodic instruction samples,
 with branch histories:
 
+!! Careful: if you are using a device different than the one used to collect the profiling data,
+you'll need to run `perf buildid-cache` as described below.
 ```
 perf inject -i perf.data -o inj.data --itrace=i100000il
 ```
@@ -393,7 +429,8 @@
 The basic commands to run an application and create a compiler profile are:
 
 ```
-taskset -c 0 ./record.sh --strobe 5000 10000 28c06000.etr ./my_application arg1 arg2
+sudo ./set_strobing.sh 5000 10000
+perf record -e cs_etm/@tmc_etr0/u --per-thread -- <your app>"
 perf inject -i perf.data -o inj.data --itrace=i100000il
 create_llvm_prof -binary=/path/to/binary -profile=inj.data -out=program.llvmprof
 ```
diff --git a/decoder/tests/auto-fdo/record.sh b/decoder/tests/auto-fdo/record.sh
deleted file mode 100644
index 16d4ba2..0000000
--- a/decoder/tests/auto-fdo/record.sh
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/bin/sh
-
-BUFFER_ETF_A53=ec802000.etf
-BUFFER_ETF_A73=ed002000.etf
-BUFFER_ETF_SYS=ec036000.etf
-BUFFER_ETR=ec033000.etr
-
-OUT_FILE=perf.data
-
-STROBE=
-
-while :; do
-  case $1 in
-    --strobe)
-      STROBE=y
-      WINDOW=$2
-      PERIOD=$3
-      shift 3
-      ;;
-    
-    *)
-      break ;;
-  esac
-done
-
-case $1 in
-  etr)
-    BUFFER=$BUFFER_ETR
-    ;;
-
-  etf-sys)
-    BUFFER=$BUFFER_ETF_SYS
-    ;;
-
-  "")
-    BUFFER=$BUFFER_ETR
-    ;;
-
-  *)
-    BUFFER=$1
-    ;;
-esac
-
-shift 1
-
-case $0 in 
- /*) F=$0 ;;
- *) F=$(pwd)/$0 ;;
-esac
-
-SCRIPT_DIR=$(dirname $F)
-
-if [ "$STROBE" ]; then
-  for e in /sys/bus/coresight/devices/*.etm/; do
-    printf "%x" $WINDOW | sudo tee $e/strobe_window > /dev/null
-    printf "%x" $PERIOD | sudo tee $e/strobe_period > /dev/null
-  done
-fi
-
-PERF=$SCRIPT_DIR/perf
-
-export LD_LIBRARY_PATH=$SCRIPT_DIR:$LD_LIBRARY_PATH
-
-sudo LD_LIBRARY_PATH=$SCRIPT_DIR:$LD_LIBRARY_PATH $PERF record $PERF_ARGS -e cs_etm/@$BUFFER/u --per-thread "$@"
-
-sudo chown $(id -u):$(id -g) $OUT_FILE
-
-
diff --git a/decoder/tests/auto-fdo/set_strobing.sh b/decoder/tests/auto-fdo/set_strobing.sh
new file mode 100644
index 0000000..081f371
--- /dev/null
+++ b/decoder/tests/auto-fdo/set_strobing.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+WINDOW=$1
+PERIOD=$2
+
+if [[ -z $WINDOW ]] || [[ -z $PERIOD ]]; then
+       echo "Window or Period not specified!"
+       echo "Example usage: ./set_strobing.sh <WINDOW VALUE> <PERIOD VALUE>"
+       echo "Example usage: ./set_strobing.sh 5000 10000"
+       exit -1
+fi
+
+
+if [[ $EUID != 0 ]]; then
+    echo "Please run as root"
+    exit -1
+fi
+
+for e in /sys/bus/coresight/devices/etm*/; do
+       printf "%x" $WINDOW | tee $e/strobe_window > /dev/null
+       printf "%x" $PERIOD | tee $e/strobe_period > /dev/null
+       echo "Strobing period for $e set to $((`cat $e/strobe_period`))"
+       echo "Strobing window for $e set to $((`cat $e/strobe_window`))"
+done
+
+## Shows the user a simple usage example
+echo ">> Done! <<"
+echo "You can now run perf to trace your application, for example:"
+echo "perf record -e cs_etm/@tmc_etr0/u -- <your app>"
diff --git a/decoder/tests/auto-fdo/show_strobing.sh b/decoder/tests/auto-fdo/show_strobing.sh
new file mode 100644
index 0000000..44302ae
--- /dev/null
+++ b/decoder/tests/auto-fdo/show_strobing.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+for e in /sys/bus/coresight/devices/etm*/; do
+       echo "Strobing period for $e is $((`cat $e/strobe_period`))"
+       echo "Strobing window for $e is $((`cat $e/strobe_window`))"
+done
diff --git a/decoder/tests/perf-test-scripts/perf-setup-env.bash b/decoder/tests/perf-test-scripts/perf-setup-env.bash
index 09431a7..95bfdc8 100755
--- a/decoder/tests/perf-test-scripts/perf-setup-env.bash
+++ b/decoder/tests/perf-test-scripts/perf-setup-env.bash
@@ -5,35 +5,44 @@
 #
 # to use this script:-
 #
+# 1) for perf exec env only
 # source perf-setup-env.bash
 #
+# 2) for perf build and exec env
+# source perf-setup-env.bash buildenv
+#
 
 #------ User Edits Start -------
 # Edit as required for user system.
 
 # Root of the opencsd library project as cloned from github
-export OPENCSD_ROOT=~/OpenCSD/opencsd-github/opencsd
+export OPENCSD_ROOT=~/work/opencsd-master
 
 # the opencsd build library directory to use.
-export OCSD_LIB_DIR=lib/linux64/rel
+export OCSD_LIB_DIR=lib/builddir
 
 # the root of the perf branch / perf dev-tree as checked out
-export PERF_ROOT=~/work2/perf-opencsd/mp-4.7-rc4/coresight
+export PERF_ROOT=~/work/kernel-dev
 
 # the arm x-compiler toolchain path
-export XTOOLS_PATH=~/work2/toolchain-aarch64/gcc-linaro-4.9-2015.05-1-rc1-x86_64_aarch64-linux-gnu/bin/
+export XTOOLS_PATH=~/work/gcc-x-aarch64-6.2/bin
 
 #------ User Edits End -------
 
 # path to source/include root dir - used by perf build to 
 # include Opencsd decoder.
-export CSTRACE_PATH=${OPENCSD_ROOT}/decoder
 
-# add library to lib path
-if [ "${LD_LIBRARY_PATH}" == ""  ]; then 
-    export LD_LIBRARY_PATH=${CSTRACE_PATH}/${OCSD_LIB_DIR}
-else
-    export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${CSTRACE_PATH}/${OCSD_LIB_DIR}
+if [ "$1" == "buildenv" ]; then
+   export CSTRACE_PATH=${OPENCSD_ROOT}/decoder
+   export CSLIBS=${CSTRACE_PATH}/${OCSD_LIB_DIR}
+   export CSINCLUDES=${CSTRACE_PATH}/include
+
+   # add library to lib path
+   if [ "${LD_LIBRARY_PATH}" == ""  ]; then 
+       export LD_LIBRARY_PATH=${CSLIBS}
+   else
+       export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${CSLIBS}
+   fi
 fi
 
 # perf script defines
diff --git a/decoder/tests/run_pkt_decode_tests.bash b/decoder/tests/run_pkt_decode_tests.bash
index ba23923..c9b4aee 100755
--- a/decoder/tests/run_pkt_decode_tests.bash
+++ b/decoder/tests/run_pkt_decode_tests.bash
@@ -72,6 +72,10 @@
     echo "Done : Return $?"
 done
 
+# === test a packet only example ===
+echo "Testing init-short-addr..."
+${BIN_DIR}/trc_pkt_lister -ss_dir "${SNAPSHOT_DIR}/init-short-addr" -pkt_mon -logfilename "${OUT_DIR}/init-short-addr.ppl"
+
 # === test the TPIU deformatter ===
 echo "Testing a55-test-tpiu..."
 ${BIN_DIR}/trc_pkt_lister -ss_dir "${SNAPSHOT_DIR}/a55-test-tpiu" -dstream_format -o_raw_packed -o_raw_unpacked -logfilename "${OUT_DIR}/a55-test-tpiu.ppl"
@@ -79,5 +83,7 @@
 
 # === test the C-API lib ===
 echo "Testing C-API library"
-${BIN_DIR}/c_api_pkt_print_test -ss_path ${SNAPSHOT_DIR} -decode
+${BIN_DIR}/c_api_pkt_print_test -ss_path ${SNAPSHOT_DIR} -decode > /dev/null
+echo "Done : Return $?"
+echo "moving result file."
 mv ./c_api_test.log ./${OUT_DIR}/c_api_test.ppl
diff --git a/decoder/tests/snapshots/init-short-addr/device1.ini b/decoder/tests/snapshots/init-short-addr/device1.ini
new file mode 100644
index 0000000..9b6d0bf
--- /dev/null
+++ b/decoder/tests/snapshots/init-short-addr/device1.ini
@@ -0,0 +1,4 @@
+[device]
+name=Cortex-A57_0
+class=core
+type=Cortex-A57
diff --git a/decoder/tests/snapshots/init-short-addr/device2.ini b/decoder/tests/snapshots/init-short-addr/device2.ini
new file mode 100644
index 0000000..0b5ffbb
--- /dev/null
+++ b/decoder/tests/snapshots/init-short-addr/device2.ini
@@ -0,0 +1,17 @@
+[device]
+name=CSETM_0
+class=trace_source
+type=ETM4.4
+
+[regs]
+TRCCONFIGR(id:0x4)=0x00000001
+TRCTRACEIDR(id:0x10)=0x00000000
+TRCIDR8(id:0x60)=0x00000000
+TRCIDR9(id:0x61)=0x00000000
+TRCIDR10(id:0x62)=0x00000000
+TRCIDR11(id:0x63)=0x00000000
+TRCIDR12(id:0x64)=0x00000000
+TRCIDR13(id:0x65)=0x00000000
+TRCIDR0(id:0x78)=0x08000CA1
+TRCIDR1(id:0x79)=0x4200F440
+TRCIDR2(id:0x7A)=0x20001088
diff --git a/decoder/tests/snapshots/init-short-addr/snapshot.ini b/decoder/tests/snapshots/init-short-addr/snapshot.ini
new file mode 100644
index 0000000..f5d6df7
--- /dev/null
+++ b/decoder/tests/snapshots/init-short-addr/snapshot.ini
@@ -0,0 +1,12 @@
+; DS-5 snapshot
+
+[snapshot]
+version=1.0
+
+[device_list]
+device1=device1.ini
+device2=device2.ini
+
+[trace]
+metadata=trace.ini
+
diff --git a/decoder/tests/snapshots/init-short-addr/trace.ini b/decoder/tests/snapshots/init-short-addr/trace.ini
new file mode 100644
index 0000000..9a3ea3b
--- /dev/null
+++ b/decoder/tests/snapshots/init-short-addr/trace.ini
@@ -0,0 +1,16 @@
+; DS-5 trace metadata
+
+[trace_buffers]
+buffers=buffer0
+
+[buffer0]
+name=CSTMC_TRACE_FIFO
+file=tracebuffer.bin
+format=source_data
+
+[core_trace_sources]
+Cortex-A57_0=CSETM_0
+
+[source_buffers]
+CSETM_0=CSTMC_TRACE_FIFO
+
diff --git a/decoder/tests/snapshots/init-short-addr/tracebuffer.bin b/decoder/tests/snapshots/init-short-addr/tracebuffer.bin
new file mode 100644
index 0000000..3b20fd5
--- /dev/null
+++ b/decoder/tests/snapshots/init-short-addr/tracebuffer.bin
Binary files differ