coverage-reporting:  Add OP-TEE SPMC coverage support
diff --git a/coverage-tool/coverage-plugin/trace_sources.h b/coverage-tool/coverage-plugin/trace_sources.h
index 57f6462..e200bc5 100644
--- a/coverage-tool/coverage-plugin/trace_sources.h
+++ b/coverage-tool/coverage-plugin/trace_sources.h
@@ -26,7 +26,7 @@
 typedef std::map<uint32_t, InstStat> InstStatMap;
 
 //Defining types for fields
-enum enum_types {u32, boolT};
+enum enum_types {u32, boolT, u8};
 typedef enum_types ValueTypes;
 
 /*
@@ -108,6 +108,9 @@
             case boolT: it->second.value = new bool(
                 record->GetBool(event_class, it->second.index));
                 break;
+            case u8: it->second.value = new uint8_t(
+                record->Get<uint8_t>(event_class, it->second.index));
+                break;
         }
     }
     return tc;
@@ -137,6 +140,10 @@
                     target->params[it->first].value =
                         new bool(*((bool*)it->second.value));
                     break;
+                case u8:
+                    target->params[it->first].value =
+                        new uint8_t(*((uint8_t*)it->second.value));
+                    break;
             }
         }
 }
@@ -226,4 +233,91 @@
     };
 };
 
+struct mode_change_type {
+    uint8_t mode_value;
+    char name[5];
+};
+const struct mode_change_type types[] = {
+    {0x0 , "EL0t"}, //0
+    {0x4 , "EL1t"}, //1
+    {0x5 , "EL1h"}, //2
+    {0x8 , "EL2t"}, //3
+    {0x9 , "EL2h"}, //4
+    {0xc , "EL3t"}, //5
+    {0xd , "EL3h"}, //6
+    {0x10 , "usr"}, //7
+    {0x11 , "fiq"}, //8
+    {0x12 , "irq"}, //9
+    {0x13 , "svc"}, //10
+    {0x16 , "mon"}, //11
+    {0x17 , "abt"}, //12
+    {0x1a , "hyp"}, //13
+    {0x1b , "und"}, //14
+    {0x1f , "sys"},  //15
+    /* Secure modes */
+    {0x0 , "EL0t"}, //16
+    {0x4 , "EL1t"}, //17
+    {0x5 , "EL1h"}, //18
+    {0x8 , "EL2t"}, //19
+    {0x9 , "EL2h"}, //20
+    {0xc , "EL3t"}, //21
+    {0xd , "EL3h"}, //22
+    {0x10 , "usr"}, //23
+    {0x11 , "fiq"}, //24
+    {0x12 , "irq"}, //25
+    {0x13 , "svc"}, //26
+    {0x16 , "mon"}, //27
+    {0x17 , "abt"}, //28
+    {0x1a , "hyp"}, //29
+    {0x1b , "und"}, //30
+    {0x1f , "sys"}  //31
+};
+
+class ModeChangeTraceContext: public TraceSourceContext {
+    public:
+        using TraceSourceContext::TraceSourceContext;
+        MTI::EventClass *event;
+        uint32_t mode_mask;
+        InstructionTraceContext* itc;
+
+
+        static void Callback(void* user_data,
+                             const MTI::EventClass *event_class,
+                             const MTI::EventRecord *record)
+        {
+            ModeChangeTraceContext* mtc = static_cast<ModeChangeTraceContext*>
+                (user_data);
+            static bool trace = false;
+            bool new_trace = false;
+            uint8_t mode = record->GetAs<char>(event_class,
+                    mtc->fields["MODE"].index);
+            uint8_t nsecure = record->Get<char>(event_class,
+                    mtc->fields["NON_SECURE"].index);
+            int start_mask  = 0;
+
+            if(nsecure) {
+                start_mask = 0;
+            } else {
+                start_mask = 16;
+            }
+
+            for (int i = start_mask; i < start_mask + 16; i++) {
+                if (types[i].mode_value == mode) {
+                    new_trace = new_trace || (mtc->mode_mask & (1 << i));
+                    break;
+                }
+            }
+
+            if (new_trace && !trace) {
+                mtc->event->RegisterCallback(InstructionTraceContext::Callback,
+                                             mtc->itc);
+            } else if (!new_trace && trace){
+                mtc->event->UnregisterCallback(
+                        InstructionTraceContext::Callback,
+                        mtc->itc);
+            }
+            trace = new_trace;
+        };
+
+};
 #endif // _COVERAGE_TOOL_COVERAGE_PLUGIN_TRACE_SOURCES_H_