/*********************************************************************
*               SEGGER MICROCONTROLLER GmbH                          *
*       Solutions for real time microcontroller applications         *
**********************************************************************
*                                                                    *
*       (c) 1995 - 2025  SEGGER Microcontroller GmbH                 *
*                                                                    *
*       www.segger.com     Support: support@segger.com               *
*                                                                    *
**********************************************************************
*                                                                    *
*       Please note:                                                 *
*                                                                    *
*       Knowledge of this file may under no circumstances            *
*       be used to write a similar product                           *
*                                                                    *
*       Thank you for your fairness !                                *
*                                                                    *
**********************************************************************
*                                                                    *
*       Current version number will be inserted here                 *
*       when shipment is built.                                      *
*                                                                    *
**********************************************************************

----------------------------------------------------------------------
Purpose     : Ozone FreeRTOS-awareness JavaScript Plugin for Legacy ARM
---------------------------END-OF-HEADER------------------------------
*/

/*********************************************************************
*
*       Defines
*
**********************************************************************
*/

var arch = "ARM"

/**** ARM Register indices, constant ********************************/
var arm_r0  =  0;
var arm_r1  =  1;
var arm_r2  =  2;
var arm_r3  =  3;
var arm_r4  =  4;
var arm_r5  =  5;
var arm_r6  =  6;
var arm_r7  =  7;
var arm_r8  =  8;
var arm_r9  =  9;
var arm_r10 = 10;
var arm_r11 = 11;
var arm_r12 = 12;
var arm_r13 = 13;  // On ARM devices the SP may be used as working register
var arm_sp  = 13;
var arm_lr  = 14;
var arm_pc  = 15;
var arm_psr = 16;

/**** RISC-V Register indices, constant ********************************/
var riscv_pc  =  0;
var riscv_ra  =  1;
var riscv_sp  =  2;
var riscv_gp  =  3;
var riscv_tp  =  4;
var riscv_t0  =  5;
var riscv_t1  =  6;
var riscv_t2  =  7;
var riscv_s0  =  8;
var riscv_s1  =  9;
var riscv_a0  = 10;
var riscv_a1  = 11;
var riscv_a2  = 12;
var riscv_a3  = 13;
var riscv_a4  = 14;
var riscv_a5  = 15;
var riscv_a6  = 16;
var riscv_a7  = 17;
var riscv_s2  = 18;
var riscv_s3  = 19;
var riscv_s4  = 20;
var riscv_s5  = 21;
var riscv_s6  = 22;
var riscv_s7  = 23;
var riscv_s8  = 24;
var riscv_s9  = 25;
var riscv_s10 = 26;
var riscv_s11 = 27;
var riscv_t3  = 28;
var riscv_t4  = 29;
var riscv_t5  = 30;
var riscv_t6  = 31;

/*********************************************************************
*
*       Local Functions
*
**********************************************************************
*/

/*********************************************************************
*
*       GetTaskStackGrowDir
*
* Function description
*   Indicates if the task stack grows in positive (1) or negative (-1) memory direction
*
* Notes
*   (1) The stack grow direction depends on the FreeRTOS-port.
*       Currently, a positive grow direction is only used on the PIC architecture.
*/
function GetTaskStackGrowDir() {
  return -1;
}

/*********************************************************************
*
*       GetTaskPrioName
*
* Function description
*   Returns the display text of a task priority
*
* Parameters
*   Priority: task priority (integer)
*/
function GetTaskPrioName(Priority) {

  var sName;

  if (Priority == 0) {
    sName = "Idle"
  } else if (Priority == 1) {
    sName = "Low"
  } else if (Priority == 2) {
    sName = "Normal";
  } else if (Priority == 3) {
    sName = "High";
  } else if (Priority == 4) {
    sName = "Highest";
  } else {
    return Priority.toString();
  }
  sName = sName + " (" + Priority + ")";
  return sName;
}

/*********************************************************************
*
*       GetTaskName
*
* Function description
*   Returns the display text of a task name
*
* Parameters
*   tcb:   task control block (type tskTCB)
*   Addr:  control block memory location
*/
function GetTaskName(tcb, Addr) {

   var sTaskName;

   sTaskName = Debug.evaluate("(char*)(*(tskTCB*)" + Addr + ").pcTaskName");
   if (sTaskName == undefined) {
     sTaskName = Debug.evaluate("(char*)(*(TCB_t*)" + Addr + ").pcTaskName");
   }

   if (tcb.uxTCBNumber != undefined) {
     sTaskName = "#" + tcb.uxTCBNumber + " \"" + sTaskName + "\"";
   }
   return sTaskName;
}

/*********************************************************************
*
*       GetTaskID
*
* Function description
*   Returns the display text of a task ID
*
* Parameters
*   tcb:   task control block (type tskTCB)
*   Addr:  control block memory location
*/
function GetTaskID(tcb, Addr) {
   return  "0x" + (tcb.uxTCBNumber == undefined ? Addr.toString(16) : tcb.uxTCBNumber.toString(16));
}

/*********************************************************************
*
*       GetTCB
*
* Function description
*   Returns the task control block of a task
*
* Parameters
*   Addr: control block memory location
*/
function GetTCB(Addr) {
  var tcb;
  tcb = Debug.evaluate("*(tskTCB*)" + Addr);
  if (tcb == undefined) {
    tcb = Debug.evaluate("*(TCB_t*)" + Addr);
  }
  return tcb;
}

/*********************************************************************
*
*       GetTaskNotifyStateStr
*
* Function description
*   Returns the display string of a task notify state
*
* Parameters
*   tcb: task control block (type tskTCB)
*/
function GetTaskNotifyStateStr(tcb) {

   if (tcb.ucNotifyState == undefined) {
     return tcb.eNotifyState == undefined ? "N/A" : tcb.eNotifyState.toString();
   } else {
     return tcb.ucNotifyState.toString()
   }
}

/*********************************************************************
*
*       GetTaskStackInfoStr
*
* Function description
*   Returns a display text of the format "<free space> / <stack size>"
*
* Parameters
*   tcb: task control block (type tskTCB)
*
* Notes
*   (1) pxEndOfStack is only available when FreeRTOS was compiled with
*       configRECORD_STACK_HIGH_ADDRESS == 1
*/
function GetTaskStackInfoStr(tcb) {
  var FreeSpace;
  var UsedSpace;
  var Size;
  //                                GrowDir == 0     GrowDir == 1
  //
  // pxStack       |  Low Addr   |  Stack Top     |  Stack Base    |
  //               |             |                |                |
  // pxTopOfStack  |             |  Stack Pointer |  Stack Pointer |
  //               |             |                |                |
  // pxEndOfStack  |  High Addr  |  Stack Base    |  Stack Top     |
  //
  if (GetTaskStackGrowDir() == 1) { // stack grows in positive address direction

    if (tcb.pxEndOfStack == undefined) {
      UsedSpace  =  tcb.pxTopOfStack - tcb.pxStack;
      FreeSpace  =  undefined;
      Size       =  undefined;
    } else {
      FreeSpace  =  tcb.pxEndOfStack - tcb.pxTopOfStack;
      UsedSpace  =  tcb.pxTopOfStack - tcb.pxStack;
      Size       =  FreeSpace + UsedSpace;
    }
  } else {    // stack grows in negative address direction

    if (tcb.pxEndOfStack == undefined) {
      FreeSpace  =  tcb.pxTopOfStack - tcb.pxStack;
      UsedSpace  =  undefined;
      Size       =  undefined;
    } else {
      FreeSpace  =  tcb.pxTopOfStack - tcb.pxStack;
      UsedSpace  =  tcb.pxEndOfStack - tcb.pxTopOfStack;
      Size       =  FreeSpace + UsedSpace;
    }
  }
  return FreeSpace + " / " + (Size == undefined ? "N/A" : Size);
}

/*********************************************************************
*
*       AddTask
*
* Function description
*   Adds a task to the task window
*
* Parameters
*   Addr:            memory location of the task's control block (TCB)
*   CurrTaskAddr:    memory location of the executing task's control block (TCB)
*   sState:          state of the task (e.g. "executing")
*/
function AddTask(Addr, CurrTaskAddr, sState) {
  var tcb;
  var sTaskName;
  var sPriority;
  var sRunCnt;
  var sMutexCnt;
  var sTimeout;
  var sStackInfo;
  var sID;
  var sNotifiedValue;
  var sNotifyState;

  tcb            = GetTCB(Addr);
  sTaskName      = GetTaskName(tcb, Addr);
  sID            = GetTaskID(tcb, Addr);
  sStackInfo     = GetTaskStackInfoStr(tcb);
  sPriority      = GetTaskPrioName(tcb.uxPriority);
  sNotifyState   = GetTaskNotifyStateStr(tcb);
  sTimeout       = (tcb.Timeout          == undefined ? "N/A" : tcb.Timeout.toString());
  sRunCnt        = (tcb.ulRunTimeCounter == undefined ? "N/A" : tcb.ulRunTimeCounter.toString());
  sNotifiedValue = (tcb.ulNotifiedValue  == undefined ? "N/A" : tcb.ulNotifiedValue.toString());
  sMutexCnt      = (tcb.uxMutexesHeld    == undefined ? "N/A" : tcb.uxMutexesHeld.toString());

  if (Addr == CurrTaskAddr) {
    sState = "executing";
  }
  Threads.add(sTaskName, sRunCnt, sPriority, sState, sTimeout, sStackInfo, sID, sMutexCnt, sNotifiedValue, sNotifyState, (Addr == CurrTaskAddr) ? undefined : Addr);
}

/*********************************************************************
*
*       AddList
*
* Function description
*   Adds all tasks of a task list to the task window
*
* Parameters
*   List:            task list (type xLIST)
*   CurrTaskAddr:    memory location of the executing task's control block (TCB)
*   sState:          common state of all tasks within 'list'
*/
function AddList(List, CurrTaskAddr, sState) {
  var i;
  var Index;
  var Item;
  var TaskAddr;

  if ((List != undefined) && (List.uxNumberOfItems > 0)) {

    Index = List.xListEnd.pxNext;

    for (i = 0; i < List.uxNumberOfItems; i++) {

      Item = Debug.evaluate("*(xLIST_ITEM*)" + Index);
      //
      // Check if Item is valid value. If not stop evaluating list.
      // This may happen if define configUSE_PORT_OPTIMISED_TASK_SELECTION
      // in the FreeRTOSConfig.h is set to 1.
      //
      if (Item == undefined) {
        break;
      }

      TaskAddr = Item != 0 ? Item.pvOwner : 0;

      if (TaskAddr != 0) {
        AddTask(TaskAddr, CurrTaskAddr, sState);
      }
      Index = Item.pxNext;

      if (i > 1000) { // infinite loop guard
        break;
      }
    }
  }
}

/*********************************************************************
*
*       API Functions
*
**********************************************************************
*/

/*********************************************************************
*
*       init
*
* Function description
*   Initializes the task window
*/
function init() {

  Threads.clear();
  Threads.newqueue("Task List");
  Threads.setColumns("Name", "Run Count", "Priority", "Status", "Timeout", "Stack Info", "ID", "Mutex Count", "Notified Value", "Notify State");
  Threads.setSortByNumber("Priority");
  Threads.setSortByNumber("Timeout");
  Threads.setSortByNumber("Run Count");
  Threads.setSortByNumber("ID");
  Threads.setSortByNumber("Mutex Count");
  Threads.setSortByNumber("Notified Value");
  Threads.setSortByNumber("Notify State");
  Threads.setColor("Status", "ready", "executing", "blocked");
}

/*********************************************************************
*
*       update
*
* Function description
*   Updates the task window
*/
function update() {
  var i;
  var pList;
  var List;
  var MaxPriority;
  var CurrTaskAddr;

  Threads.clear();

  if((Debug.evaluate("pxCurrentTCB") == 0) || (Debug.evaluate("pxCurrentTCB") == undefined)) {
    return;
  }
  MaxPriority  = Debug.evaluate("uxTopReadyPriority");
  CurrTaskAddr = Debug.evaluate("pxCurrentTCB");

  for (i = MaxPriority; i >= 0; i--) {
    List = Debug.evaluate("pxReadyTasksLists[" + i + "]");
    AddList(List, CurrTaskAddr, "ready");
  }

  pList = Debug.evaluate("pxDelayedTaskList");
  if (pList != 0) {
    List = Debug.evaluate("*(xLIST*)" + pList);
    AddList(List, CurrTaskAddr, "blocked");
  }

  pList = Debug.evaluate("pxOverflowDelayedTaskList");
  if (pList != 0) {
    List = Debug.evaluate("*(xLIST*)" + pList);
    AddList(List, CurrTaskAddr, "blocked");
  }

  List = Debug.evaluate("xSuspendedTaskList");
  if (List != 0) {
    AddList(List, CurrTaskAddr, "suspended");
  }
}

/*********************************************************************
*
*       getregs
*
* Function description
*   Returns the register set of a task.
*   For ARM cores, this function is expected to return the values
*   of registers R0 to R15 and PSR.
*
* Parameters
*   hTask: integer number identifiying the task.
*   Identical to the last parameter supplied to method Threads.add.
*   For convenience, this should be the address of the TCB.
*
* Return Values
*   An array of unsigned integers containing the task's register values.
*   The array must be sorted according to the logical indexes of the regs.
*   The logical register indexing scheme is defined by the ELF-DWARF ABI.
*
**********************************************************************
*/
function getregs(hTask) {
  var aRegs;

  if (arch == "Cortex-M") {
    aRegs = getregs_cortexm(hTask);
  } else if (arch == "ARM"      ||
             arch == "Cortex-A") {
    aRegs = getregs_arm(hTask);
  } else if (arch == "RISC-V") {
    aRegs = getregs_riscv(hTask);
  }
  return aRegs;
}

/*********************************************************************
*
*       getregs_cortexm
*
* Function description
*   Returns the register set of a task when running on Cortex-M.
*
* Parameters
*   hTask: integer number identifiying the task.
*   Identical to the last parameter supplied to method Threads.add.
*   For convenience, this should be the address of the TCB.
*
* Return Values
*   An array of unsigned integers containing the task's register values.
*   The array must be sorted according to the logical indexes of the regs.
*   The logical register indexing scheme is defined by the ELF-DWARF ABI.
*
**********************************************************************
*/
function getregs_cortexm(hTask) {
  var tcb;
  var Addr;
  var CPACR;
  var EXEC_RET;
  var SavedFPContext;
  var aRegs   = new Array(17);
  var Has_FPU = 0;

  tcb  = GetTCB(hTask);
  Addr = tcb.pxTopOfStack;  // Evaluate stack pointer of the task
  //
  // Check whether an FPU is available
  //
  CPACR = TargetInterface.peekWord(0xE000ED88);
  if ((CPACR & 0x00F00000) != 0) {  // Is the FPU enabled (CPACR b23..b20)?
    Has_FPU = 1;
  }
  //
  // The following registers are pushed by the FreeRTOS-scheduler
  // R4...R11
  //
  aRegs[arm_r4] = TargetInterface.peekWord(Addr);
  Addr += 4;
  aRegs[arm_r5] = TargetInterface.peekWord(Addr);
  Addr += 4;
  aRegs[arm_r6] = TargetInterface.peekWord(Addr);
  Addr += 4;
  aRegs[arm_r7] = TargetInterface.peekWord(Addr);
  Addr += 4;
  aRegs[arm_r8] = TargetInterface.peekWord(Addr);
  Addr += 4;
  aRegs[arm_r9] = TargetInterface.peekWord(Addr);
  Addr += 4;
  aRegs[arm_r10] = TargetInterface.peekWord(Addr);
  Addr += 4;
  aRegs[arm_r11] = TargetInterface.peekWord(Addr);
  Addr += 4;
  //
  // EXEC_RET, S16...S31
  //
  if (Has_FPU == 1) {
      EXEC_RET = TargetInterface.peekWord(Addr);
      Addr += 4;
      SavedFPContext = ((EXEC_RET & 0x10) != 0x10);
      if (SavedFPContext) {
        Addr += 4 * 16;  // Skip S16..S31
      }
  }
  //
  // The following registers are pushed by the ARM core
  // R0...R3
  //
  aRegs[arm_r0] = TargetInterface.peekWord(Addr);
  Addr += 4;
  aRegs[arm_r1] = TargetInterface.peekWord(Addr);
  Addr += 4;
  aRegs[arm_r2] = TargetInterface.peekWord(Addr);
  Addr += 4;
  aRegs[arm_r3] = TargetInterface.peekWord(Addr);
  Addr += 4;
  //
  // R12, LR, PC, PSR
  //
  aRegs[arm_r12] = TargetInterface.peekWord(Addr);
  Addr += 4;
  aRegs[arm_lr] = TargetInterface.peekWord(Addr);
  Addr += 4;
  aRegs[arm_pc] = TargetInterface.peekWord(Addr);
  Addr += 4;
  aRegs[arm_psr] = TargetInterface.peekWord(Addr);
  Addr += 4;
  //
  // S0..S15
  //
  if (Has_FPU == 1) {
    if (SavedFPContext) {
      Addr += 4*18;  // Skip S0...S15
    }
  }
  if (aRegs[arm_psr] & (1 << 9)) {  // Stack has been 8-byte aligned
    Addr += 4;
  }
  //
  // SP
  //
  aRegs[arm_sp] = Addr;

  return aRegs;
}

/*********************************************************************
*
*       getregs_arm
*
* Function description
*   Returns the register set of a task when running on legacy ARM and Cortex-A/R.
*
* Parameters
*   hTask: integer number identifiying the task.
*   Identical to the last parameter supplied to method Threads.add.
*   For convenience, this should be the address of the TCB.
*
* Return Values
*   An array of unsigned integers containing the task's register values.
*   The array must be sorted according to the logical indexes of the regs.
*   The logical register indexing scheme is defined by the ELF-DWARF ABI.
*
**********************************************************************
*/
function getregs_arm(hTask) {
  var tcb;
  var Addr;
  var aRegs = new Array(17);

  tcb  = GetTCB(hTask);
  Addr = tcb.pxTopOfStack;  // Evaluate stack pointer of the task

  if (arch == "ARM") {
    //
    // CPSR
    //
    aRegs[arm_psr] = TargetInterface.peekWord(Addr);
    Addr += 4;
  }
  //
  // R0...R12
  //
  aRegs[arm_r0] = TargetInterface.peekWord(Addr);
  Addr += 4;
  aRegs[arm_r1] = TargetInterface.peekWord(Addr);
  Addr += 4;
  aRegs[arm_r2] = TargetInterface.peekWord(Addr);
  Addr += 4;
  aRegs[arm_r3] = TargetInterface.peekWord(Addr);
  Addr += 4;
  aRegs[arm_r4] = TargetInterface.peekWord(Addr);
  Addr += 4;
  aRegs[arm_r5] = TargetInterface.peekWord(Addr);
  Addr += 4;
  aRegs[arm_r6] = TargetInterface.peekWord(Addr);
  Addr += 4;
  aRegs[arm_r7] = TargetInterface.peekWord(Addr);
  Addr += 4;
  aRegs[arm_r8] = TargetInterface.peekWord(Addr);
  Addr += 4;
  aRegs[arm_r9] = TargetInterface.peekWord(Addr);
  Addr += 4;
  aRegs[arm_r10] = TargetInterface.peekWord(Addr)
  Addr += 4;
  aRegs[arm_r11] = TargetInterface.peekWord(Addr)
  Addr += 4;
  aRegs[arm_r12] = TargetInterface.peekWord(Addr)
  Addr += 4;

  if (arch == "ARM") {
    //
    // R13
    //
    aRegs[arm_r13] = TargetInterface.peekWord(Addr);
    Addr += 4;
  }
  //
  // LR
  //
  aRegs[arm_lr] = TargetInterface.peekWord(Addr);
  Addr += 4;
  //
  // PC
  //
  aRegs[arm_pc] = TargetInterface.peekWord(Addr);
  Addr += 4;
  if (arch == "Cortex-A") {
    //
    // XPSR
    //
    aRegs[arm_psr] = TargetInterface.peekWord(Addr);
    Addr += 4;
    //
    // Skip 3 dummy registers
    //
    Addr += 12;
  }
  //
  // SP
  //
  aRegs[arm_sp] = Addr;

  return aRegs;
}

/*********************************************************************
*
*       getregs_riscv
*
* Function description
*   Returns the register set of a task when running on RISC-V.
*
* Parameters
*   hTask: integer number identifiying the task.
*   Identical to the last parameter supplied to method Threads.add.
*   For convenience, this should be the address of the TCB.
*
* Return Values
*   An array of unsigned integers containing the task's register values.
*   The array must be sorted according to the logical indexes of the regs.
*   The logical register indexing scheme is defined by the ELF-DWARF ABI.
*
**********************************************************************
*/
function getregs_riscv(hTask) {
  var tcb;
  var Addr;
  var aRegs = new Array(32);

  tcb  = GetTCB(hTask);
  Addr = tcb.pxTopOfStack;  // Evaluate stack pointer of the task
  //
  //  sp, ra
  //
  aRegs[riscv_sp]  = TargetInterface.peekWord(Addr +  0);  // Load sp
  TargetInterface.message ("aRegs[riscv_sp] == " + aRegs[riscv_sp]);
  Addr += 4;
  aRegs[riscv_ra]  = TargetInterface.peekWord(Addr);  // Load ra
  TargetInterface.message ("aRegs[riscv_ra] == " + aRegs[riscv_ra]);
  Addr += 4;
  //
  //  t0..t2
  //
  aRegs[riscv_t0]  = TargetInterface.peekWord(Addr);  // Load t0
  TargetInterface.message ("aRegs[riscv_t0] == " + aRegs[riscv_t0]);
  Addr += 4;
  aRegs[riscv_t1]  = TargetInterface.peekWord(Addr);  // Load t1
  TargetInterface.message ("aRegs[riscv_t1] == " + aRegs[riscv_t1]);
  Addr += 4;
  aRegs[riscv_t2]  = TargetInterface.peekWord(Addr);  // Load t2
  TargetInterface.message ("aRegs[riscv_t2] == " + aRegs[riscv_t2]);
  Addr += 4;
  //
  //  s0..s1
  //
  aRegs[riscv_s0]  = TargetInterface.peekWord(Addr);  // Load s0
  TargetInterface.message ("aRegs[riscv_s0] == " + aRegs[riscv_s0]);
  Addr += 4;
  aRegs[riscv_s1]  = TargetInterface.peekWord(Addr);  // Load s1
  TargetInterface.message ("aRegs[riscv_s1] == " + aRegs[riscv_s1]);
  Addr += 4;
  //
  //  a0..a7
  //
  aRegs[riscv_a0]  = TargetInterface.peekWord(Addr);  // Load a0
  TargetInterface.message ("aRegs[riscv_a0] == " + aRegs[riscv_a0]);
  Addr += 4;
  aRegs[riscv_a1]  = TargetInterface.peekWord(Addr);  // Load a1
  TargetInterface.message ("aRegs[riscv_a1] == " + aRegs[riscv_a1]);
  Addr += 4;
  aRegs[riscv_a2]  = TargetInterface.peekWord(Addr);  // Load a2
  TargetInterface.message ("aRegs[riscv_a2] == " + aRegs[riscv_a2]);
  Addr += 4;
  aRegs[riscv_a3]  = TargetInterface.peekWord(Addr);  // Load a3
  TargetInterface.message ("aRegs[riscv_a3] == " + aRegs[riscv_a3]);
  Addr += 4;
  aRegs[riscv_a4]  = TargetInterface.peekWord(Addr);  // Load a4
  TargetInterface.message ("aRegs[riscv_a4] == " + aRegs[riscv_a4]);
  Addr += 4;
  aRegs[riscv_a5]  = TargetInterface.peekWord(Addr);  // Load a5
  TargetInterface.message ("aRegs[riscv_a5] == " + aRegs[riscv_a5]);
  Addr += 4;
  aRegs[riscv_a6]  = TargetInterface.peekWord(Addr);  // Load a6
  TargetInterface.message ("aRegs[riscv_a6] == " + aRegs[riscv_a6]);
  Addr += 4;
  aRegs[riscv_a7]  = TargetInterface.peekWord(Addr);  // Load a7
  TargetInterface.message ("aRegs[riscv_a7] == " + aRegs[riscv_a7]);
  Addr += 4;
  //
  //  s2..s11
  //
  aRegs[riscv_s2]  = TargetInterface.peekWord(Addr);  // Load s2
  TargetInterface.message ("aRegs[riscv_s2] == " + aRegs[riscv_s2]);
  Addr += 4;
  aRegs[riscv_s3]  = TargetInterface.peekWord(Addr);  // Load s3
  TargetInterface.message ("aRegs[riscv_s3] == " + aRegs[riscv_s3]);
  Addr += 4;
  aRegs[riscv_s4]  = TargetInterface.peekWord(Addr);  // Load s4
  TargetInterface.message ("aRegs[riscv_s4] == " + aRegs[riscv_s4]);
  Addr += 4;
  aRegs[riscv_s5]  = TargetInterface.peekWord(Addr);  // Load s5
  TargetInterface.message ("aRegs[riscv_s5] == " + aRegs[riscv_s5]);
  Addr += 4;
  aRegs[riscv_s6]  = TargetInterface.peekWord(Addr);  // Load s6
  TargetInterface.message ("aRegs[riscv_s6] == " + aRegs[riscv_s6]);
  Addr += 4;
  aRegs[riscv_s7]  = TargetInterface.peekWord(Addr);  // Load s7
  TargetInterface.message ("aRegs[riscv_s2] == " + aRegs[riscv_s2]);
  Addr += 4;
  aRegs[riscv_s8]  = TargetInterface.peekWord(Addr);  // Load s8
  TargetInterface.message ("aRegs[riscv_s8] == " + aRegs[riscv_s8]);
  Addr += 4;
  aRegs[riscv_s9]  = TargetInterface.peekWord(Addr);  // Load s9
  TargetInterface.message ("aRegs[riscv_s9] == " + aRegs[riscv_s9]);
  Addr += 4;
  aRegs[riscv_s10] = TargetInterface.peekWord(Addr);  // Load s10
  TargetInterface.message ("aRegs[riscv_s10] == " + aRegs[riscv_s10]);
  Addr += 4;
  aRegs[riscv_s11] = TargetInterface.peekWord(Addr);  // Load s11
  TargetInterface.message ("aRegs[riscv_s11] == " + aRegs[riscv_s11]);
  Addr += 4;
  //
  //  t3..t6
  //
  aRegs[riscv_t3] = TargetInterface.peekWord(Addr);  // Load t3
  TargetInterface.message ("aRegs[riscv_t3] == " + aRegs[riscv_t3]);
  Addr += 4;
  aRegs[riscv_t4] = TargetInterface.peekWord(Addr);  // Load t4
  TargetInterface.message ("aRegs[riscv_t4] == " + aRegs[riscv_t4]);
  Addr += 4;
  aRegs[riscv_t5] = TargetInterface.peekWord(Addr);  // Load t5
  TargetInterface.message ("aRegs[riscv_t5] == " + aRegs[riscv_t5]);
  Addr += 4;
  aRegs[riscv_t6] = TargetInterface.peekWord(Addr);  // Load t6
  TargetInterface.message ("aRegs[riscv_t6] == " + aRegs[riscv_t6]);
  Addr += 4;
  //
  // Evaluate gp and tp
  //
  aRegs[riscv_gp] = Debug.evaluate("__global_pointer$") || 0;
  aRegs[riscv_tp] = Debug.evaluate("__thread_pointer$") || 0;

  return aRegs;
}

/*********************************************************************
*
*       getContextSwitchAddrs
*
*  Functions description
*    Returns an unsigned integer array containing the base addresses
*    of all functions that complete a task switch when executed.
*/
function getContextSwitchAddrs() {

  var aAddrs;
  var Addr;

  Addr = Debug.evaluate("&vTaskSwitchContext");

  if (Addr != undefined) {
    aAddrs = new Array(1);
    aAddrs[0] = Addr;
    return aAddrs;
  }
  return [];
}

/*********************************************************************
*
*       getOSName()
*
*  Functions description:
*    Returns the name of the RTOS this script supplies support for
*/
function getOSName() {
  return "FreeRTOS";
}
