#! /usr/bin/env python
# -*- coding: UTF-8 -*-
#———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

import sys, interrupt_names_teensy_3_6

#———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

def ENDC () :
  return '\033[0m'

#······················································································································*

def RED () :
  return '\033[91m'

#······················································································································*

def BOLD () :
  return '\033[1m'

#······················································································································*

def BOLD_RED () :
  return BOLD () + RED ()

#———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

def asSeparator () :
  return "@" + ("-" * 119) + "\n"

#———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

def cppSeparator () :
  return "//" + ("-" * 118) + "\n"

#———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

def generateSVChandler ():
  sFile = asSeparator ()
  sFile += "@                 S V C    H A N D L E R    ( D O U B L E    S T A C K    M O D E )\n"
  sFile += asSeparator ()
  sFile += "@\n"
  sFile += "@          PSP+32 -> |                            |\n"
  sFile += "@                    |----------------------------| \\\n"
  sFile += "@          PSP+28 -> | xPSR                       |  |\n"
  sFile += "@                    |----------------------------|  |\n"
  sFile += "@          PSP+24 -> | PC (after SVC instruction) |  |\n"
  sFile += "@                    |----------------------------|  |\n"
  sFile += "@          PSP+20 -> | LR                         |  |\n"
  sFile += "@                    |----------------------------|  |\n"
  sFile += "@          PSP+16 -> | R12                        |  |  Saved by interrupt response\n"
  sFile += "@                    |----------------------------|  |\n"
  sFile += "@          PSP+12 -> | R3                         |  |\n"
  sFile += "@                    |----------------------------|  |\n"
  sFile += "@          PSP+8  -> | R2                         |  |\n"
  sFile += "@                    |----------------------------|  |\n"
  sFile += "@          PSP+4  -> | R1                         |  |\n"
  sFile += "@                    |----------------------------|  |\n"
  sFile += "@     /--- PSP ----> | R0                         |  |\n"
  sFile += "@     |              |----------------------------| /\n"
  sFile += "@     |              |                            |\n"
  sFile += "@     |\n"
  sFile += "@     |                                          *---------------------*\n"
  sFile += "@     |                                          | LR return code      | +36 [ 9]\n"
  sFile += "@     |                                          *---------------------*\n"
  sFile += "@     \----------------------------------------- | R13 (PSP)           | +32 [ 8]\n"
  sFile += "@                                                *---------------------*\n"
  sFile += "@                                                | R11                 | +28 [ 7]\n"
  sFile += "@                                                *---------------------*\n"
  sFile += "@                                                | R10                 | +24 [ 6]\n"
  sFile += "@                                                *---------------------*\n"
  sFile += "@                                                | R9                  | +20 [ 5]\n"
  sFile += "@                                                *---------------------*\n"
  sFile += "@                                                | R8                  | +16 [ 4]\n"
  sFile += "@                                                *---------------------*\n"
  sFile += "@                                                | R7                  | +12 [ 3]\n"
  sFile += "@                                                *---------------------*\n"
  sFile += "@                                                | R6                  | + 8 [ 2]\n"
  sFile += "@                                                *---------------------*\n"
  sFile += "@                                                | R5                  | + 4 [ 1]\n"
  sFile += "@  *------------------------------------*        *---------------------*\n"
  sFile += "@  | var.running.task.control.block.ptr +------> | R4                  | + 0 [ 0]\n"
  sFile += "@  *------------------------------------*        *---------------------*\n"
  sFile += "@\n"
  sFile += asSeparator () + "\n"
  sFile += "	.section	.bss.var.background.task.context, \"aw\", %nobits\n"
  sFile += "  .align	  2\n\n"
  sFile += "var.background.task.context:\n"
  sFile += "  .space  4\n\n"
  sFile += asSeparator () + "\n"
  sFile += "	.section	.text.interrupt.SVC, \"ax\", %progbits\n\n"
  sFile += "  .global interrupt.SVC\n"
  sFile += "  .type interrupt.SVC, %function\n\n"
  sFile += "interrupt.SVC:\n"
  sFile += "@----------------------------------------- Save preserved registers\n"
  sFile += "  push  {r4, lr}\n"
  sFile += "@----------------------------------------- R4 <- thread SP\n"
  sFile += "  mrs   r4, psp\n"
  sFile += "@----------------------------------------- Restore R0, R1, R2 and R3 from saved stack\n"
  sFile += "  ldmia r4!, {r0, r1, r2, r3}       @ R4 incremented by 16\n"
  sFile += "@----------------------------------------- R4 <- Address of SVC instruction\n"
  sFile += "  ldr   r4, [r4, #8]                @ 8 : 2 stacked registers before saved PC\n"
  sFile += "@----------------------------------------- R12 <- bits 0-7 of SVC instruction\n"
  sFile += "  ldrb  r12, [r4, #-2]              @ R12 is service call index\n"
  sFile += "@----------------------------------------- R4 <- address of dispatcher table\n"
  sFile += "  ldr   r4, =svc.dispatcher.table\n"
  sFile += "@----------------------------------------- R12 <- address of routine to call\n"
  sFile += "  ldr   r12, [r4, r12, lsl #2]      @ R12 = R4 + (R12 << 2)\n"
  sFile += "@----------------------------------------- R4 <- calling task context\n"
  sFile += "  ldr   r4, =var.running.task.control.block.ptr\n"
  sFile += "  ldr   r4, [r4]\n"
  sFile += "@----------------------------------------- Call service routine\n"
  sFile += "  blx   r12                         @ R4:calling task context address\n"
  sFile += "@--- Continues in sequence to handle.context.switch\n\n"
  sFile += asSeparator ()
  sFile += "@\n"
  sFile += "@                 H A N D L E    C O N T E X T    S W I T C H    ( D O U B L E    S T A C K    M O D E )\n"
  sFile += "@\n"
  sFile += "@  On entry:\n"
  sFile += "@    - R4 contains the runnning task save context address,\n"
  sFile += "@    - R4 and LR of running task have been pushed on handler stack.\n"
  sFile += "@\n"
  sFile += asSeparator () + "\n"
  sFile += "handle.context.switch:\n"
  sFile += "@----------------------------------------- Select task to run\n"
  sFile += "  bl    kernel.select.task.to.run\n"
  sFile += "@----------------------------------------- R0 <- calling task context, R1 <- new task context\n"
  sFile += "  ldr   r1, =var.running.task.control.block.ptr\n"
  sFile += "  mov   r0, r4\n"
  sFile += "  ldr   r1, [r1]\n"
  sFile += "@----------------------------------------- Restore preserved registers\n"
  sFile += "  pop   {r4, lr}\n"
  sFile += "@----------------------------------------- Running task did change ?\n"
  sFile += "  cmp   r0, r1  @ R0:calling task context, R1:new task context\n"
  sFile += "  bne   running.state.did.change\n"
  sFile += "  bx    lr  @ No change\n"
  sFile += "@----------------------------------------- Save context of preempted task\n"
  sFile += "running.state.did.change:\n"
  sFile += "  mrs   r12, psp\n"
  sFile += "  cbz   r0, save.background.task.context\n"
  sFile += "@--- Save registers r4 to r11, PSP (stored in R12), LR\n"
  sFile += "  stmia r0, {r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}\n"
  sFile += "  b     perform.restore.context\n"
  sFile += "save.background.task.context:\n"
  sFile += "  ldr   r2, =var.background.task.context\n"
  sFile += "  str   r12, [r2]\n"
  sFile += "@----------------------------------------- Restore context of activated task\n"
  sFile += "perform.restore.context:\n"
  sFile += "  cbz   r1, restore.background.task.context\n"
  sFile += "  ldmia r1, {r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}\n"
  sFile += "  msr   psp, r12\n"
  sFile += "  bx    lr\n"
  sFile += "@----------------------------------------- Restore background task context\n"
  sFile += "restore.background.task.context:\n"
  sFile += "  ldr   r2, =var.background.task.context\n"
  sFile += "  ldr   r2, [r2]\n"
  sFile += "  msr   psp, r2\n"
  sFile += "  bx    lr\n\n"
  return sFile

#———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

def generateBreakpointHandler () :
  sFile = asSeparator ()
  sFile += "@\n"
  sFile += "@                 B K P T    H A N D L E R    ( D O U B L E    S T A C K    M O D E )\n"
  sFile += "@\n"
  sFile += asSeparator ()
  sFile += "@\n"
  sFile += "@                    |                            |\n"
  sFile += "@          PSP+32 -> |----------------------------| \\\n"
  sFile += "@                    | xPSR                       |  |\n"
  sFile += "@          PSP+28 -> |----------------------------|  |\n"
  sFile += "@                    | PC (BKPT instruction)      |  |\n"
  sFile += "@          PSP+24 -> |----------------------------|  |\n"
  sFile += "@                    | LR                         |  |\n"
  sFile += "@          PSP+20 -> |----------------------------|  |\n"
  sFile += "@                    | R12                        |  |  Saved by interrupt response\n"
  sFile += "@          PSP+16 -> |----------------------------|  |\n"
  sFile += "@                    | R3                         |  |\n"
  sFile += "@          PSP+12 -> |----------------------------|  |\n"
  sFile += "@                    | R2                         |  |\n"
  sFile += "@          PSP+8  -> |----------------------------|  |\n"
  sFile += "@                    | R1                         |  |\n"
  sFile += "@          PSP+4  -> |----------------------------|  |\n"
  sFile += "@                    | R0                         |  |\n"
  sFile += "@          PSP    -> |----------------------------| /\n"
  sFile += "@\n"
  sFile += asSeparator () + "\n"
  sFile += "  .section  .text.interrupt.DebugMonitor, \"ax\", %progbits\n\n"
  sFile += "  .global interrupt.DebugMonitor\n"
  sFile += "  .type interrupt.DebugMonitor, %function\n\n"
  sFile += "interrupt.DebugMonitor:\n"
  sFile += "@--------------------- Save preserved registers\n"
  sFile += "  push  {r5, lr}\n"
  sFile += "@--------------------- R5 <- thread SP\n"
  sFile += "  mrs   r5, psp\n"
  sFile += "  ldmia r5, {r0, r1, r2, r3}\n"
  sFile += "@--------------------- LR <- Address of BKPT instruction\n"
  sFile += "  ldr   lr, [r5, #24]     @ 24 : 6 stacked registers before saved PC\n"
  sFile += "@--------------------- Set return address to instruction following BKPT\n"
  sFile += "@  adds  lr, #2\n"
  sFile += "@  str   lr, [r5, #24]\n"
  sFile += "@--------------------- R12 <- address of dispatcher\n"
  sFile += "  ldr   r12, =section.dispatcher.table\n"
  sFile += "@--------------------- LR <- bits 0-7 of BKPT instruction\n"
  sFile += "  ldrb  lr, [lr, #-2]            @ LR is service call index\n"
  sFile += "@--------------------- r12 <- address of routine to call\n"
  sFile += "  ldr   r12, [r12, lr, lsl #2]   @ R12 = [R12 + LR * 4]\n"
  sFile += "@--------------------- Call service routine\n"
  sFile += "  blx   r12\n"
  sFile += "@--------------------- Set return code (from R0 to R3) in stacked registers\n"
  sFile += "  stmia r5!, {r0, r1, r2, r3}\n"
  sFile += "@--------------------- Restore preserved registers, return from interrupt\n"
  sFile += "  pop   {r5, pc}\n\n"
  return sFile

#———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

def generateBreakpointSection (sectionName, idx):
  sFile  = asSeparator () + "\n"
  sFile += "  .section .text." + section + ", \"ax\", %progbits\n"
  sFile += "  .global " + section +"\n"
  sFile += "  .align 1\n"
  sFile += "  .type " + section +", %function\n\n"
  sFile += section +":\n"
  sFile += "  .fnstart\n"
  sFile += "  mrs  r12, IPSR @ r12 <- 0x??????00 in thread mode, 0x??????nn, nn ≠ 0 in handler mode\n"
  sFile += "  ands r12, #255\n"
  sFile += "  bne  section." + section + " @ in handler mode, call implementation routine directly\n"
  sFile += "  bkpt #" + str (idx) + "\n"
  sFile += "  bx   lr\n\n"
  sFile += ".Lfunc_end_" + section +":\n"
  sFile += "  .size " + section +", .Lfunc_end_" + section +" - " + section +"\n"
  sFile += "  .cantunwind\n"
  sFile += "  .fnend\n\n"
  return sFile

#———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

def generateSoftwareInterruptandler () :
  sFile = asSeparator ()
  sFile += "@\n"
  sFile += "@     SECTIONS: Software Interrupt Handler (two stack mode)\n"
  sFile += "@\n"
  sFile += asSeparator ()
  sFile += "@\n"
  sFile += "@                    |                            |\n"
  sFile += "@          PSP+32 -> |----------------------------| \\\n"
  sFile += "@                    | xPSR                       |  |\n"
  sFile += "@          PSP+28 -> |----------------------------|  |\n"
  sFile += "@                    | PC                         |  |\n"
  sFile += "@          PSP+24 -> |----------------------------|  |\n"
  sFile += "@                    | LR                         |  |\n"
  sFile += "@          PSP+20 -> |----------------------------|  |\n"
  sFile += "@                    | R12                        |  |  Saved by interrupt response\n"
  sFile += "@          PSP+16 -> |----------------------------|  |\n"
  sFile += "@                    | R3                         |  |\n"
  sFile += "@          PSP+12 -> |----------------------------|  |\n"
  sFile += "@                    | R2                         |  |\n"
  sFile += "@          PSP+8  -> |----------------------------|  |\n"
  sFile += "@                    | R1                         |  |\n"
  sFile += "@          PSP+4  -> |----------------------------|  |\n"
  sFile += "@                    | R0                         |  |\n"
  sFile += "@          PSP    -> |----------------------------| /\n"
  sFile += "@\n"
  sFile += asSeparator () + "\n"
  sFile += "  .section  .text.interrupt.SWINT, \"ax\", %progbits\n\n"
  sFile += "  .global interrupt.SWINT\n"
  sFile += "  .type interrupt.SWINT, %function\n\n"
  sFile += "interrupt.SWINT:\n"
  sFile += "@--------------------- Save preserved registers\n"
  sFile += "  push  {r5, lr}\n"
  sFile += "@--------------------- R5 <- thread SP\n"
  sFile += "  mrs   r5, psp\n"
  sFile += "@--------------------- Restore R0, R1, R2 and R3 from saved stack\n"
  sFile += "  ldmia r5, {r0, r1, r2, r3}\n"
  sFile += "@--------------------- R12 <- Address section routine\n"
  sFile += "  ldr   r12, [r5, #16]     @ 16 : 4 stacked registers before saved R12\n"
  sFile += "@--------------------- Call section routine\n"
  sFile += "  blx   r12\n"
  sFile += "@--------------------- Set return code (from R0 to R3) in stacked registers\n"
  sFile += "  stmia r5!, {r0, r1, r2, r3}    @ R5 is thread SP\n"
  sFile += "@--------------------- Set R12 stacked register to 0\n"
  sFile += "  mov   r0, #0\n"
  sFile += "  str   r0, [r5]\n"
  sFile += "@--------------------- Restore preserved registers, return from interrupt\n"
  sFile += "  pop   {r5, pc}\n\n"
  sFile += asSeparator () + "\n"
  sFile += "  .section  .text.direct.call.or.call.software.interrupt, \"ax\", %progbits\n\n"
  sFile += "  .type direct.call.or.call.software.interrupt, %function\n\n"
  sFile += "direct.call.or.call.software.interrupt: @ R12 contains the address of section implementation function\n"
  sFile += "@--------------------- Save preserved registers\n"
  sFile += "  push {r6, r7}\n"
  sFile += "  mrs  r6, IPSR          @ IPSR[8...0] ≠ 0 in handler mode, = 0 in thread mode\n"
  sFile += "  mov  r7, #511\n"
  sFile += "  tst  r6, r7\n"
  sFile += "  bne  direct.call\n"
  sFile += "@--------------------- Software interrupt\n"
  sFile += "  ldr  r6, = 0xE000EF00  @ Address of STIR control register\n"
  sFile += "  movs r7, # (80 - 16)   @ Software Interrupt has number #80\n"
  sFile += "  str  r7, [r6]          @ Generate Software Interrupt\n"
  sFile += "@--------------------- Wait for the exception is carried out\n"
  sFile += "wait.software.interrupt.done: @ R12 is reset by interrupt handler\n"
  sFile += "  cmp  r12, #0\n"
  sFile += "  bne  wait.software.interrupt.done\n"
  sFile += "@--------------------- Restore preserved registers\n"
  sFile += "  pop  {r6, r7}\n"
  sFile += "  bx   lr\n"
  sFile += "@--------------------- Direct call\n"
  sFile += "direct.call:\n"
  sFile += "  pop  {r6, r7}\n"
  sFile += "  bx   r12              @ in handler mode, call implementation routine directly\n\n"
  return sFile

#———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

def generateSoftwareInterruptSection (sectionName, idx):
  sFile  = asSeparator () + "\n"
  sFile += "  .section .text." + sectionName + ", \"ax\", %progbits\n"
  sFile += "  .global " + sectionName +"\n"
  sFile += "  .align 1\n"
  sFile += "  .type " + sectionName +", %function\n\n"
  sFile += sectionName +":\n"
  sFile += "  .fnstart\n"
  sFile += "  ldr  r12, =section." + sectionName + "\n"
  sFile += "  b    direct.call.or.call.software.interrupt\n\n"
  sFile += ".Lfunc_end_" + sectionName +":\n"
  sFile += "  .size " + sectionName +", .Lfunc_end_" + sectionName +" - " + sectionName +"\n"
  sFile += "  .cantunwind\n"
  sFile += "  .fnend\n\n"
  return sFile

#———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

def generateCppForBreakpointSection ():
  s = "#include \"all-headers.h\"\n\n"
  s += cppSeparator () + "\n"
  s += "static void enableDebugMonitorInterruption (BOOT_MODE) {\n"
  s += "//--- Enable DebugMonitor interrupt\n"
  s += "  #define DEMCR (* ((volatile uint32_t *) 0xE000EDFC))\n"
  s += "  DEMCR |= (1 << 16) ; // Set MON_EN\n"
  s += "}\n\n"
  s += cppSeparator () + "\n"
  s += "MACRO_BOOT_ROUTINE (enableDebugMonitorInterruption) ;\n\n"
  s += cppSeparator ()
  return s

#———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

def generateCppForSoftwareInterruptSection ():
  s = "#include \"all-headers.h\"\n\n"
  s += cppSeparator () + "\n"
  s += "static void enableSoftwareInterrupt (BOOT_MODE) {\n"
  s += "//--- Enable software interrupt\n"
  s += "  NVIC_ENABLE_IRQ (ISRSlot::SWINT) ;\n"
  s += "//--- Make STIR register accessible in unprivileged mode\n"
  s += "  #define CCR (* ((volatile uint32_t *) 0xE000ED14))\n"
  s += "  CCR |= (1 << 1) ;\n"
  s += "}\n\n"
  s += cppSeparator () + "\n"
  s += "MACRO_BOOT_ROUTINE (enableSoftwareInterrupt) ;\n\n"
  s += cppSeparator ()
  return s

#———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

def generateDisableInterruptSection (sectionName):
  sFile  = asSeparator ()
  sFile += "@   SECTION - " + sectionName + "\n"
  sFile += asSeparator () + "\n"
  sFile += "  .section .text." + sectionName + ", \"ax\", %progbits\n"
  sFile += "  .global " + sectionName +"\n"
  sFile += "  .align 1\n"
  sFile += "  .type " + sectionName +", %function\n\n"
  sFile += sectionName +":\n"
  sFile += "  .fnstart\n"
  sFile += "@--- Save preserved registers\n"
  sFile += "  push  {r6, lr}\n"
  sFile += "@--- Save interrupt enabled state\n"
  sFile += "  mrs   r6, PRIMASK\n"
  sFile += "@--- Disable interrupt\n"
  sFile += "  cpsid i\n"
  sFile += "@--- Call section, interrupts disabled\n"
  sFile += "  bl    section." + sectionName + "\n"
  sFile += "@--- Restore interrupt state\n"
  sFile += "  msr   PRIMASK, r6\n"
  sFile += "@--- Restore preserved registers and return\n"
  sFile += "  pop   {r6, pc}\n\n"
  sFile += ".Lfunc_end_" + sectionName +":\n"
  sFile += "  .size " + sectionName +", .Lfunc_end_" + sectionName +" - " + sectionName +"\n"
  sFile += "  .cantunwind\n"
  sFile += "  .fnend\n\n"
  return sFile

#———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
#    ENTRY POINT
#———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

#------------------------------ Interrupt dictionary
interruptDictionary = interrupt_names_teensy_3_6.interruptNames ()
# print "Dest " + destinationFile
#------------------------------ Assembly destination file
destinationCppFile = sys.argv [1]
# print "Dest " + destinationAssemblerFile
#------------------------------ Assembly destination file
destinationAssemblerFile = sys.argv [2]
# print "Dest " + destinationAssemblerFile
#------------------------------ Service scheme
serviceScheme = sys.argv [3]
#------------------------------ Section scheme
sectionScheme = sys.argv [4]
#------------------------------ Header files
headerFiles = []
for i in range (5, len (sys.argv)):
  headerFiles.append (sys.argv [i])
#print headerFiles
#------------------------------ Destination file string
cppFile = ""
sFile  = "  .syntax unified\n"
sFile += "  .cpu cortex-m4\n"
sFile += "  .thumb\n\n"
#------------------------------ Explore header files
interruptServiceList = []
interruptSectionList = []
boolServiceSet = set ()
serviceList = []
sectionList = []
for header in headerFiles:
  with open (header) as f:
    for line in f:
      splitStr = line.strip ().split ("//$interrupt-section ")
      if len (splitStr) == 2 :
        interruptName = splitStr [1].strip ()
        if interruptName in interruptDictionary :
          interruptSectionList.append (interruptName)
          del interruptDictionary [interruptName]
        else:
          print (BOLD_RED () + "Error, interrupt '" + interruptName + "' does not exist, or is already assigned." + ENDC ())
          sys.exit (1)
      splitStr = line.strip ().split ("//$interrupt-service ")
      if len (splitStr) == 2 :
        interruptName = splitStr [1].strip ()
        if interruptName in interruptDictionary :
          interruptServiceList.append (interruptName)
          del interruptDictionary [interruptName]
        else:
          print (BOLD_RED () + "Error, interrupt '" + interruptName + "' does not exist, or is already assigned." + ENDC ())
          sys.exit (1)
      splitStr = line.strip ().split ("//$service ")
      if len (splitStr) == 2 :
        serviceName = splitStr [1].strip ()
        serviceList.append (serviceName)
      splitStr = line.strip ().split ("//$bool-service ")
      if len (splitStr) == 2 :
        serviceName = splitStr [1].strip ()
        serviceList.append (serviceName)
        boolServiceSet.add (serviceName)
      splitStr = line.strip ().split ("//$section ")
      if len (splitStr) == 2 :
        sectionName = splitStr [1].strip ()
        sectionList.append (sectionName)
#------------------------------ Has service ?
if (len (serviceList) > 0) and (serviceScheme == "") :
  print (BOLD_RED ()
         + "As the project defines service(s), the makefile.json file should have a \"SERVICE-SCHEME\" "
         + "entry (asoociated value: \"svc\")"
         +  ENDC ())
  sys.exit (1)
#------------------------------ Has sections ?
if (len (sectionList) > 0) and (sectionScheme == "") :
  print (BOLD_RED ()
         + "As the project defines section(s), the makefile.json file should have a \"SECTION-SCHEME\" "
         + "entry (possible associated value: \"disableInterrupt\", \"bkpt\", \"swint\")"
         +  ENDC ())
  sys.exit (1)
#------------------------------ Services
if serviceScheme == "svc" :
  sFile += generateSVChandler ()
  del interruptDictionary ["SVC"]
  sFile += asSeparator ()
  sFile += "@   SERVICES\n"
  idx = 1
  for service in serviceList :
    sFile += asSeparator () + "\n"
    sFile += "  .section .text." + service + ", \"ax\", %progbits\n"
    sFile += "  .global " + service +"\n"
    sFile += "  .align 1\n"
    sFile += "  .type " + service +", %function\n\n"
    sFile += service +":\n"
    sFile += "  .fnstart\n"
    sFile += "  svc #" + str (idx) + "\n"
    if service in boolServiceSet :
      sFile += "  b   get.user.result\n\n"
    else:
      sFile += "  bx  lr\n\n"
    sFile += ".Lfunc_end_" + service +":\n"
    sFile += "  .size " + service +", .Lfunc_end_" + service +" - " + service +"\n"
    sFile += "  .cantunwind\n"
    sFile += "  .fnend\n\n"
    idx += 1
  sFile += asSeparator ()
  sFile += "@    SERVICE DISPATCHER TABLE\n"
  sFile += asSeparator () + "\n"
  sFile += "  .align   2\n"
  sFile += "  .global  svc.dispatcher.table\n\n"
  sFile += "svc.dispatcher.table:\n"
  sFile += "  .word start.phase2 @ 0\n"
  idx = 1
  for service in serviceList :
    sFile += "  .word service." + service + " @ " + str (idx) + "\n"
    idx += 1
  sFile += "\n"
#------------------------------ Generate section handler
if sectionScheme == "bkpt" :
  cppFile += generateCppForBreakpointSection ()
  sFile += generateBreakpointHandler ()
  del interruptDictionary ["DebugMonitor"]
  sFile += asSeparator ()
  sFile += "@   SECTIONS\n"
  idx = 0
  for section in sectionList :
    sFile += generateBreakpointSection (section, idx)
    idx += 1
  sFile += asSeparator ()
  sFile += "@    SECTION DISPATCHER TABLE\n"
  sFile += asSeparator () + "\n"
  sFile += "  .global section.dispatcher.table\n\n"
  sFile += "section.dispatcher.table:\n"
  idx = 0
  for section in sectionList :
    sFile += "  .word section." + section + " @ " + str (idx) + "\n"
    idx += 1
  sFile += "\n"
elif sectionScheme == "swint" :
  cppFile += generateCppForSoftwareInterruptSection ()
  sFile += generateSoftwareInterruptandler ()
  del interruptDictionary ["SWINT"]
  sFile += asSeparator ()
  sFile += "@   SECTIONS\n"
  idx = 0
  for section in sectionList :
    sFile += generateSoftwareInterruptSection (section, idx)
    idx += 1
elif sectionScheme == "disableInterrupt" :
  for section in sectionList :
    sFile += generateDisableInterruptSection (section)
elif len (sectionList) > 0 :
  print (BOLD_RED ()
         + "In the makefile.json file, the \"SECTION-SCHEME\" key has an invalid \"" + sectionScheme + "\" value; "
         + "(possible value: \"disableInterrupt\", \"bkpt\", \"swint\")"
         +  ENDC ())
  sys.exit (1)
#------------------------------ Interrupts as service
for interruptServiceName in interruptServiceList :
  sFile += asSeparator ()
  sFile += "@   INTERRUPT - SERVICE: " + interruptServiceName + "\n"
  sFile += asSeparator () + "\n"
  sFile += "  .section .text.interrupt." + interruptServiceName + ", \"ax\", %progbits\n\n"
  sFile += "  .align  1\n"
  sFile += "  .global interrupt." + interruptServiceName + "\n"
  sFile += "  .type interrupt." + interruptServiceName + ", %function\n\n"
  sFile += "interrupt." + interruptServiceName + ":\n"
  sFile += "@----------------------------------------- Save preserved registers\n"
  sFile += "  push  {r4, lr}\n"
  sFile += "@----------------------------------------- Activity led On\n"
  sFile += "  ldr   r0, =0x400FF084  @ Address of GPIOC_PSOR control register\n"
  sFile += "  movs  r1, # (1 << 5)   @ Port D13 is PORTC:5\n"
  sFile += "  str   r1, [r0]         @ turn on\n"
  sFile += "@----------------------------------------- R4 <- running task context\n"
  sFile += "  ldr   r4, =var.running.task.control.block.ptr\n"
  sFile += "  ldr   r4, [r4]\n"
  sFile += "@----------------------------------------- Call Interrupt handler\n"
  sFile += "  bl    interrupt.service." + interruptServiceName + "\n"
  sFile += "@----------------------------------------- Perform the context switch, if needed\n"
  sFile += "  b     handle.context.switch\n\n"
#------------------------------ Interrupts as section
for interruptSectionName in interruptSectionList :
  sFile += asSeparator ()
  sFile += "@   INTERRUPT - SECTION: " + interruptSectionName + "\n"
  sFile += asSeparator () + "\n"
  sFile += "  .section .text.interrupt." + interruptSectionName + ", \"ax\", %progbits\n\n"
  sFile += "  .align  1\n"
  sFile += "  .global interrupt." + interruptSectionName + "\n"
  sFile += "  .type interrupt." + interruptSectionName + ", %function\n\n"
  sFile += "interrupt." + interruptSectionName + ":\n"
  sFile += "@----------------------------------------- Activity led On\n"
  sFile += "  ldr   r0, =0x400FF084  @ Address of GPIOC_PSOR control register\n"
  sFile += "  movs  r1, # (1 << 5)   @ Port D13 is PORTC:5\n"
  sFile += "  str   r1, [r0]         @ turn on\n"
  sFile += "@----------------------------------------- Goto interrupt function\n"
  sFile += "  b     interrupt.section." + interruptSectionName + "\n\n"
#------------------------------ Unused interrupts
for unusedInterruptName in interruptDictionary.keys () :
  sFile += asSeparator ()
  sFile += "@   INTERRUPT - UNUSED: " + unusedInterruptName + "\n"
  sFile += asSeparator () + "\n"
  sFile += "  .section .text.interrupt." + unusedInterruptName + ", \"ax\", %progbits\n\n"
  sFile += "  .align  1\n"
  sFile += "  .type interrupt." + unusedInterruptName + ", %function\n"
  sFile += "  .global interrupt." + unusedInterruptName + "\n\n"
  sFile += "interrupt." + unusedInterruptName + ":\n"
  sFile += "  movs r0, #" + str (interruptDictionary [unusedInterruptName]) + "\n"
  sFile += "  b    unused.interrupt\n\n"
#------------------------------ Write destination file
sFile += asSeparator ()
f = open (destinationAssemblerFile, "wt")
f.write (sFile)
f.close()
f = open (destinationCppFile, "wt")
f.write (cppFile)
f.close()

#———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————