1/*********************************************************************
2*                   (c) SEGGER Microcontroller GmbH                  *
3*                        The Embedded Experts                        *
4*                           www.segger.com                           *
5**********************************************************************
6*                                                                    *
7*            (c) 1995 - 2020 SEGGER Microcontroller GmbH             *
8*                                                                    *
9*       www.segger.com     Support: support@segger.com               *
10*                                                                    *
11**********************************************************************
12*                                                                    *
13* All rights reserved.                                               *
14*                                                                    *
15* SEGGER strongly recommends to not make any changes                 *
16* to or modify the source code of this software in order to stay     *
17* compatible with the monitor mode protocol and J-Link.              *
18*                                                                    *
19* Redistribution and use in source and binary forms, with or         *
20* without modification, are permitted provided that the following    *
21* conditions are met:                                                *
22*                                                                    *
23* - Redistributions of source code must retain the above copyright   *
24*   notice, this list of conditions and the following disclaimer.    *
25*                                                                    *
26* - Redistributions in binary form must reproduce the above          *
27*   copyright notice, this list of conditions and the following      *
28*   disclaimer in the documentation and/or other materials provided  *
29*   with the distribution.                                           *
30*                                                                    *
31* - Neither the name of SEGGER Microcontroller GmbH                  *
32*   nor the names of its contributors may be used to endorse or      *
33*   promote products derived from this software without specific     *
34*   prior written permission.                                        *
35*                                                                    *
36* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND             *
37* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,        *
38* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF           *
39* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE           *
40* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
41* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR           *
42* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  *
43* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;    *
44* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF      *
45* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT          *
46* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE  *
47* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   *
48* DAMAGE.                                                            *
49*                                                                    *
50**********************************************************************
51----------------------------------------------------------------------
52File    : JLINK_MONITOR_ISR_SES.s
53Purpose : Implementation of debug monitor for J-Link monitor mode
54          debug on Cortex-M devices, supporting SES compiler.
55--------  END-OF-HEADER  ---------------------------------------------
56*/
57
58        .name JLINK_MONITOR_ISR
59        .syntax unified
60
61        .extern JLINK_MONITOR_OnEnter
62        .extern JLINK_MONITOR_OnExit
63        .extern JLINK_MONITOR_OnPoll
64
65        .global z_arm_debug_monitor
66
67/*********************************************************************
68*
69*       Defines, configurable
70*
71**********************************************************************
72*/
73
74#define _MON_VERSION  100  // V x.yy
75
76/*********************************************************************
77*
78*       Defines, fixed
79*
80**********************************************************************
81*/
82
83#define _APP_SP_OFF_R0                  0x00
84#define _APP_SP_OFF_R1                  0x04
85#define _APP_SP_OFF_R2                  0x08
86#define _APP_SP_OFF_R3                  0x0C
87#define _APP_SP_OFF_R12                 0x10
88#define _APP_SP_OFF_R14_LR              0x14
89#define _APP_SP_OFF_PC                  0x18
90#define _APP_SP_OFF_XPSR                0x1C
91#define _APP_SP_OFF_S0                  0x20
92#define _APP_SP_OFF_S1                  0x24
93#define _APP_SP_OFF_S2                  0x28
94#define _APP_SP_OFF_S3                  0x2C
95#define _APP_SP_OFF_S4                  0x30
96#define _APP_SP_OFF_S5                  0x34
97#define _APP_SP_OFF_S6                  0x38
98#define _APP_SP_OFF_S7                  0x3C
99#define _APP_SP_OFF_S8                  0x40
100#define _APP_SP_OFF_S9                  0x44
101#define _APP_SP_OFF_S10                 0x48
102#define _APP_SP_OFF_S11                 0x4C
103#define _APP_SP_OFF_S12                 0x50
104#define _APP_SP_OFF_S13                 0x54
105#define _APP_SP_OFF_S14                 0x58
106#define _APP_SP_OFF_S15                 0x5C
107#define _APP_SP_OFF_FPSCR               0x60
108
109#define _NUM_BYTES_BASIC_STACKFRAME     32
110#define _NUM_BYTES_EXTENDED_STACKFRAME  104        // Values for stackframes are explained at location where they are used
111
112#define _SYSTEM_DCRDR_OFF               0x00
113#define _SYSTEM_DEMCR_OFF               0x04
114
115#define _SYSTEM_DHCSR                   0xE000EDF0 // Debug Halting Control and Status Register (DHCSR)
116#define _SYSTEM_DCRSR                   0xE000EDF4 // Debug Core Register Selector Register (DCRSR)
117#define _SYSTEM_DCRDR                   0xE000EDF8 // Debug Core Register Data Register (DCRDR)
118#define _SYSTEM_DEMCR                   0xE000EDFC // Debug Exception and Monitor Control Register (DEMCR)
119
120#define _SYSTEM_FPCCR                   0xE000EF34 // Floating-Point Context Control Register (FPCCR)
121#define _SYSTEM_FPCAR                   0xE000EF38 // Floating-Point Context Address Register (FPCAR)
122#define _SYSTEM_FPDSCR                  0xE000EF3C // Floating-Point Default Status Control Register (FPDSCR)
123#define _SYSTEM_MVFR0                   0xE000EF40 // Media and FP Feature Register 0 (MVFR0)
124#define _SYSTEM_MVFR1                   0xE000EF44 // Media and FP Feature Register 1 (MVFR1)
125
126/*
127* Defines for determining if the current debug config supports FPU registers
128* For some compilers like IAR EWARM when disabling the FPU in the compiler settings an error is thrown when
129*/
130#ifdef __FPU_PRESENT
131  #if __FPU_PRESENT
132   #define _HAS_FPU_REGS  1
133  #else
134   #define _HAS_FPU_REGS  0
135  #endif
136#else
137  #define _HAS_FPU_REGS  0
138#endif
139
140/*********************************************************************
141*
142*       Signature of monitor
143*
144*  Function description
145*    Needed for targets where also a boot ROM is present that possibly specifies a vector table with a valid debug monitor exception entry
146*/
147        .section .text, "ax"
148
149        //
150        // JLINKMONHANDLER
151        //
152        .byte 0x4A
153        .byte 0x4C
154        .byte 0x49
155        .byte 0x4E
156        .byte 0x4B
157        .byte 0x4D
158        .byte 0x4F
159        .byte 0x4E
160        .byte 0x48
161        .byte 0x41
162        .byte 0x4E
163        .byte 0x44
164        .byte 0x4C
165        .byte 0x45
166        .byte 0x52
167        .byte 0x00      // Align to 8-bytes
168
169/*********************************************************************
170*
171*       z_arm_debug_monitor()
172*
173*  Function description
174*    Debug monitor handler. CPU enters this handler in case a "halt" request is made from the debugger.
175*    This handler is also responsible for handling commands that are sent by the debugger.
176*
177*  Notes
178*    This is actually the ISR for the debug inerrupt (exception no. 12)
179*/
180        .thumb_func
181
182z_arm_debug_monitor:
183        /*
184        General procedure:
185        DCRDR is used as communication register
186        DEMCR[19] is used as ready flag
187        For the command J-Link sends to the monitor: DCRDR[7:0] == Cmd, DCRDR[31:8] == ParamData
188
189        1) Monitor sets DEMCR[19] whenever it is ready to receive new commands/data
190           DEMCR[19] is initially set on debug monitor entry
191        2) J-Link will clear DEMCR[19] it has placed command/data in DCRDR for monitor
192        3) Monitor will wait for DEMCR[19] to be cleared
193        4) Monitor will process command (May cause additional data transfers etc., depends on command). Monitor will set DEMCR[19] whenever it has placed data for J-Link in the DCRDR
194        5) No restart-CPU command? => Back to 2), Otherwise => 6)
195        6) Monitor will clear DEMCR[19] 19 to indicate that it is no longer ready
196        */
197        PUSH     {LR}
198        BL       JLINK_MONITOR_OnEnter
199        POP      {LR}
200        LDR.N    R3,_AddrDCRDR                             // 0xe000edf8 == _SYSTEM_DCRDR
201        B.N      _IndicateMonReady
202_WaitProbeReadIndicateMonRdy:                              // while(_SYSTEM_DEMCR & (1uL << 19));  => Wait until J-Link has read item
203        LDR      R0,[R3, #+_SYSTEM_DEMCR_OFF]              // _SYSTEM_DEMCR
204        LSLS     R0,R0,#+12
205        BMI.N    _WaitProbeReadIndicateMonRdy
206_IndicateMonReady:
207        LDR      R0,[R3, #+_SYSTEM_DEMCR_OFF]              // _SYSTEM_DEMCR |= (1uL << 19);  => Set MON_REQ bit, so J-Link knows monitor is ready to receive commands
208        ORR      R0,R0,#0x80000
209        STR      R0,[R3, #+_SYSTEM_DEMCR_OFF]
210        /*
211        During command loop:
212        R0  = Tmp
213        R1  = Tmp
214        R2  = Tmp
215        R3  = &_SYSTEM_DCRDR  (allows also access to DEMCR with offset)
216        R12 = Tmp
217
218        Outside command loop R0-R3 and R12 may be overwritten by MONITOR_OnPoll()
219        */
220_WaitForJLinkCmd:                                          // do {
221        PUSH     {LR}
222        BL       JLINK_MONITOR_OnPoll
223        POP      {LR}
224        LDR.N    R3,_AddrDCRDR                             // 0xe000edf8 == _SYSTEM_DCRDR
225        LDR      R0,[R3, #+_SYSTEM_DEMCR_OFF]
226        LSRS     R0,R0,#+20                                // DEMCR[19] -> Carry Clear? => J-Link has placed command for us
227        BCS     _WaitForJLinkCmd
228        /*
229        Perform command
230        Command is placed by J-Link in DCRDR[7:0] and additional parameter data is stored in DCRDR[31:8]
231        J-Link clears DEMCR[19] to indicate that it placed a command/data or read data
232        Monitor sets DEMCR[19] to indicate that it placed data or read data / is ready for a new command
233        Setting DEMCR[19] indicates "monitor ready for new command / data" and also indicates: "data has been placed in DCRDR by monitor, for J-Link"
234        Therefore it is responsibility of the commands to respond to the commands accordingly
235
236        Commands for debug monitor
237        Commands must not exceed 0xFF (255) as we only defined 8-bits for command-part. Higher 24-bits are parameter info for current command
238
239        Protocol for different commands:
240          J-Link: Cmd -> DCRDR,  DEMCR[19] -> 0 => Cmd placed by probe
241        */
242        LDR      R0,[R3, #+_SYSTEM_DCRDR_OFF]              // ParamInfo = _SYSTEM_DCRDR
243        LSRS     R1,R0,#+8                                 // ParamInfo >>= 8
244        LSLS     R0,R0,#+24
245        LSRS     R0,R0,#+24                                // Cmd = ParamInfo & 0xFF
246        //
247        // switch (Cmd)
248        //
249        CMP      R0,#+0
250        BEQ.N    _HandleGetMonVersion                      // case _MON_CMD_GET_MONITOR_VERSION
251        CMP      R0,#+2
252        BEQ.N    _HandleReadReg                            // case _MON_CMD_READ_REG
253        BCC.N    _HandleRestartCPU                         // case _MON_CMD_RESTART_CPU
254        CMP      R0,#+3
255        BEQ.N    _HandleWriteReg_Veneer                    // case _MON_CMD_WRITE_REG
256        B.N      _IndicateMonReady                         // default : while (1);
257        /*
258        Return
259        _MON_CMD_RESTART_CPU
260          CPU:                   DEMCR[19] -> 0 => Monitor no longer ready
261        */
262_HandleRestartCPU:
263        LDR      R0,[R3, #+_SYSTEM_DEMCR_OFF]              // _SYSTEM_DEMCR &= ~(1uL << 19);  => Clear MON_REQ to indicate that monitor is no longer active
264        BIC      R0,R0,#0x80000
265        STR      R0,[R3, #+_SYSTEM_DEMCR_OFF]
266        PUSH     {LR}
267        BL       JLINK_MONITOR_OnExit
268        POP      {PC}
269        //
270        // Place data section here to not get in trouble with load-offsets
271        //
272        .section .text, "ax", %progbits
273        .align 2
274_AddrDCRDR:
275        .long     0xE000EDF8
276_AddrCPACR:
277        .long     0xE000ED88
278
279        .section .text, "ax"
280        .thumb_func
281
282;/*********************************************************************
283;*
284;*       _HandleGetMonVersion
285;*
286;*/
287_HandleGetMonVersion:
288        /*
289        _MON_CMD_GET_MONITOR_VERSION
290          CPU:    Data -> DCRDR, DEMCR[19] -> 1 => Data ready
291          J-Link: DCRDR -> Read, DEMCR[19] -> 0 => Data read
292          CPU:                   DEMCR[19] -> 1 => Mon ready
293        */
294        MOVS     R0,#+_MON_VERSION
295        STR      R0,[R3, #+_SYSTEM_DCRDR_OFF]              // _SYSTEM_DCRDR = x
296        LDR      R0,[R3, #+_SYSTEM_DEMCR_OFF]              // _SYSTEM_DEMCR |= (1uL << 19);  => Set MON_REQ bit, so J-Link knows monitor is ready to receive commands
297        ORR      R0,R0,#0x80000
298        STR      R0,[R3, #+_SYSTEM_DEMCR_OFF]              // Indicate data ready
299        B        _WaitProbeReadIndicateMonRdy
300
301/*********************************************************************
302*
303*       _HandleReadReg
304*
305*/
306_HandleWriteReg_Veneer:
307        B.N      _HandleWriteReg
308_HandleReadReg:
309        /*
310        _MON_CMD_READ_REG
311          CPU:    Data -> DCRDR, DEMCR[19] -> 1 => Data ready
312          J-Link: DCRDR -> Read, DEMCR[19] -> 0 => Data read
313          CPU:                   DEMCR[19] -> 1 => Mon ready
314
315
316        Register indexes
317        0-15: R0-R15       (13 == R13 reserved => is banked ... Has to be read as PSP / MSP. Decision has to be done by J-Link DLL side!)
318        16: XPSR
319        17: MSP
320        18: PSP
321        19: CFBP           CONTROL/FAULTMASK/BASEPRI/PRIMASK (packed into 4 bytes of word. CONTROL = CFBP[31:24], FAULTMASK = CFBP[16:23], BASEPRI = CFBP[15:8], PRIMASK = CFBP[7:0]
322        20: FPSCR
323        21-52: FPS0-FPS31
324
325
326        Register usage when entering this "subroutine":
327        R0 Cmd
328        R1 ParamInfo
329        R2 ---
330        R3  = &_SYSTEM_DCRDR  (allows also access to DEMCR with offset)
331        R12 ---
332
333        Table B1-9 EXC_RETURN definition of exception return behavior, with FP extension
334        LR           Return to     Return SP   Frame type
335        ---------------------------------------------------------
336        0xFFFFFFE1   Handler mode. MSP         Extended
337        0xFFFFFFE9   Thread mode   MSP         Extended
338        0xFFFFFFED   Thread mode   PSP         Extended
339        0xFFFFFFF1   Handler mode. MSP         Basic
340        0xFFFFFFF9   Thread mode   MSP         Basic
341        0xFFFFFFFD   Thread mode   PSP         Basic
342
343        So LR[2] == 1 => Return stack == PSP else MSP
344
345        R0-R3, R12, PC, xPSR can be read from application stackpointer
346        Other regs can be read directly
347        */
348        LSRS     R2,LR,#+3                         // Shift LR[2] into carry => Carry clear means that CPU was running on MSP
349        ITE      CS
350        MRSCS    R2,PSP
351        MRSCC    R2,MSP
352        CMP      R1,#+4                            // if (RegIndex < 4) { (R0-R3)
353        BCS      _HandleReadRegR4
354        LDR      R0,[R2, R1, LSL #+2]              // v = [SP + Rx * 4] (R0-R3)
355        B.N      _HandleReadRegDone
356_HandleReadRegR4:
357        CMP      R1,#+5                          // if (RegIndex < 5) { (R4)
358        BCS      _HandleReadRegR5
359        MOV      R0,R4
360        B.N      _HandleReadRegDone
361_HandleReadRegR5:
362        CMP      R1,#+6                          // if (RegIndex < 6) { (R5)
363        BCS      _HandleReadRegR6
364        MOV      R0,R5
365        B.N      _HandleReadRegDone
366_HandleReadRegR6:
367        CMP      R1,#+7                          // if (RegIndex < 7) { (R6)
368        BCS      _HandleReadRegR7
369        MOV      R0,R6
370        B.N      _HandleReadRegDone
371_HandleReadRegR7:
372        CMP      R1,#+8                          // if (RegIndex < 8) { (R7)
373        BCS      _HandleReadRegR8
374        MOV      R0,R7
375        B.N      _HandleReadRegDone
376_HandleReadRegR8:
377        CMP      R1,#+9                          // if (RegIndex < 9) { (R8)
378        BCS      _HandleReadRegR9
379        MOV      R0,R8
380        B.N      _HandleReadRegDone
381_HandleReadRegR9:
382        CMP      R1,#+10                         // if (RegIndex < 10) { (R9)
383        BCS      _HandleReadRegR10
384        MOV      R0,R9
385        B.N      _HandleReadRegDone
386_HandleReadRegR10:
387        CMP      R1,#+11                         // if (RegIndex < 11) { (R10)
388        BCS      _HandleReadRegR11
389        MOV      R0,R10
390        B.N      _HandleReadRegDone
391_HandleReadRegR11:
392        CMP      R1,#+12                         // if (RegIndex < 12) { (R11)
393        BCS      _HandleReadRegR12
394        MOV      R0,R11
395        B.N      _HandleReadRegDone
396_HandleReadRegR12:
397        CMP      R1,#+14                         // if (RegIndex < 14) { (R12)
398        BCS      _HandleReadRegR14
399        LDR      R0,[R2, #+_APP_SP_OFF_R12]
400        B.N      _HandleReadRegDone
401_HandleReadRegR14:
402        CMP      R1,#+15                         // if (RegIndex < 15) { (R14 / LR)
403        BCS      _HandleReadRegR15
404        LDR      R0,[R2, #+_APP_SP_OFF_R14_LR]
405        B.N      _HandleReadRegDone
406_HandleReadRegR15:
407        CMP      R1,#+16                         // if (RegIndex < 16) { (R15 / PC)
408        BCS      _HandleReadRegXPSR
409        LDR      R0,[R2, #+_APP_SP_OFF_PC]
410        B.N      _HandleReadRegDone
411_HandleReadRegXPSR:
412        CMP      R1,#+17                         // if (RegIndex < 17) { (xPSR)
413        BCS      _HandleReadRegMSP
414        LDR      R0,[R2, #+_APP_SP_OFF_XPSR]
415        B.N      _HandleReadRegDone
416_HandleReadRegMSP:
417        /*
418        Stackpointer is tricky because we need to get some info about the SP used in the user app, first
419
420        Handle reading R0-R3 which can be read right from application stackpointer
421
422        Table B1-9 EXC_RETURN definition of exception return behavior, with FP extension
423        LR           Return to     Return SP   Frame type
424        ---------------------------------------------------------
425        0xFFFFFFE1   Handler mode. MSP         Extended
426        0xFFFFFFE9   Thread mode   MSP         Extended
427        0xFFFFFFED   Thread mode   PSP         Extended
428        0xFFFFFFF1   Handler mode. MSP         Basic
429        0xFFFFFFF9   Thread mode   MSP         Basic
430        0xFFFFFFFD   Thread mode   PSP         Basic
431
432        So LR[2] == 1 => Return stack == PSP else MSP
433        Per architecture definition: Inside monitor (exception) SP = MSP
434
435        Stack pointer handling is complicated because it is different what is pushed on the stack before entering the monitor ISR...
436        Cortex-M: 8 regs
437        Cortex-M + forced-stack-alignment: 8 regs + 1 dummy-word if stack was not 8-byte aligned
438        Cortex-M + FPU: 8 regs + 17 FPU regs + 1 dummy-word + 1-dummy word if stack was not 8-byte aligned
439        Cortex-M + FPU + lazy mode: 8 regs + 17 dummy-words + 1 dummy-word + 1-dummy word if stack was not 8-byte aligned
440        */
441        CMP      R1,#+18                           // if (RegIndex < 18) { (MSP)
442        BCS      _HandleReadRegPSP
443        MRS      R0,MSP
444        LSRS     R1,LR,#+3                         // LR[2] -> Carry == 0 => CPU was running on MSP => Needs correction
445        BCS      _HandleReadRegDone_Veneer         // CPU was running on PSP? => No correction necessary
446_HandleSPCorrection:
447        LSRS     R1,LR,#+5                         // LR[4] -> Carry == 0 => extended stack frame has been allocated. See ARM DDI0403D, B1.5.7 Stack alignment on exception entry
448        ITE      CS
449        ADDCS    R0,R0,#+_NUM_BYTES_BASIC_STACKFRAME
450        ADDCC    R0,R0,#+_NUM_BYTES_EXTENDED_STACKFRAME
451        LDR      R1,[R2, #+_APP_SP_OFF_XPSR]       // Get xPSR from application stack (R2 has been set to app stack on beginning of _HandleReadReg)
452        LSRS     R1,R1,#+5                         // xPSR[9] -> Carry == 1 => Stack has been force-aligned before pushing regs. See ARM DDI0403D, B1.5.7 Stack alignment on exception entry
453        IT       CS
454        ADDCS    R0,R0,#+4
455        B        _HandleReadRegDone
456_HandleReadRegPSP:                                 // RegIndex == 18
457        CMP      R1,#+19                           // if (RegIndex < 19) {
458        BCS      _HandleReadRegCFBP
459        MRS      R0,PSP                            // PSP is not touched by monitor
460        LSRS     R1,LR,#+3                         // LR[2] -> Carry == 1 => CPU was running on PSP => Needs correction
461        BCC      _HandleReadRegDone_Veneer         // CPU was running on MSP? => No correction of PSP necessary
462        B        _HandleSPCorrection
463_HandleReadRegCFBP:
464        /*
465        CFBP is a register that can only be read via debug probe and is a merger of the following regs:
466        CONTROL/FAULTMASK/BASEPRI/PRIMASK (packed into 4 bytes of word. CONTROL = CFBP[31:24], FAULTMASK = CFBP[16:23], BASEPRI = CFBP[15:8], PRIMASK = CFBP[7:0]
467        To keep J-Link side the same for monitor and halt mode, we also return CFBP in monitor mode
468        */
469        CMP      R1,#+20                           // if (RegIndex < 20) { (CFBP)
470        BCS      _HandleReadRegFPU
471        MOVS     R0,#+0
472        MRS      R2,PRIMASK
473        ORRS     R0,R2                             // Merge PRIMASK into CFBP[7:0]
474        MRS      R2,BASEPRI
475        LSLS     R2,R2,#+8                         // Merge BASEPRI into CFBP[15:8]
476        ORRS     R0,R2
477        MRS      R2,FAULTMASK
478        LSLS     R2,R2,#+16                        // Merge FAULTMASK into CFBP[23:16]
479        ORRS     R0,R2
480        MRS      R2,CONTROL
481        LSRS     R1,LR,#3                               // LR[2] -> Carry. CONTROL.SPSEL is saved to LR[2] on exception entry => ARM DDI0403D, B1.5.6 Exception entry behavior
482        IT       CS                                     // As J-Link sees value of CONTROL at application time, we need reconstruct original value of CONTROL
483        ORRCS    R2,R2,#+2                              // CONTROL.SPSEL (CONTROL[1]) == 0 inside monitor
484        LSRS     R1,LR,#+5                              // LR[4] == NOT(CONTROL.FPCA)  -> Carry
485        ITE      CS                                     // Merge original value of FPCA (CONTROL[2]) into read data
486        BICCS    R2,R2,#+0x04                           // Remember LR contains NOT(CONTROL)
487        ORRCC    R2,R2,#+0x04
488        LSLS     R2,R2,#+24
489        ORRS     R0,R2
490        B.N      _HandleReadRegDone
491_HandleReadRegFPU:
492#if _HAS_FPU_REGS
493        CMP      R1,#+53                               // if (RegIndex < 53) { (20 (FPSCR), 21-52 FPS0-FPS31)
494        BCS      _HandleReadRegDone_Veneer
495        /*
496        Read Coprocessor Access Control Register (CPACR) to check if CP10 and CP11 are enabled
497        If not, access to floating point is not possible
498        CPACR[21:20] == CP10 enable. 0b01 = Privileged access only. 0b11 = Full access. Other = reserved
499        CPACR[23:22] == CP11 enable. 0b01 = Privileged access only. 0b11 = Full access. Other = reserved
500        */
501        LDR      R0,_AddrCPACR
502        LDR      R0,[R0]
503        LSLS     R0,R0,#+8
504        LSRS     R0,R0,#+28
505        CMP      R0,#+0xF
506        BEQ      _HandleReadRegFPU_Allowed
507        CMP      R0,#+0x5
508        BNE      _HandleReadRegDone_Veneer
509_HandleReadRegFPU_Allowed:
510        CMP      R1,#+21                                  // if (RegIndex < 21) (20 == FPSCR)
511        BCS      _HandleReadRegFPS0_FPS31
512        LSRS     R0,LR,#+5                                // CONTROL[2] == FPCA => NOT(FPCA) saved to LR[4]. LR[4] == 0 => Extended stack frame, so FPU regs possibly on stack
513        BCS      _HandleReadFPSCRLazyMode                 // Remember: NOT(FPCA) is stored to LR. == 0 means: Extended stack frame
514        LDR      R0,=_SYSTEM_FPCCR
515        LDR      R0,[R0]
516        LSLS     R0,R0,#+2                                // FPCCR[30] -> Carry == 1 indicates if lazy mode is active, so space on stack is reserved but FPU registers are not saved on stack
517        BCS      _HandleReadFPSCRLazyMode
518        LDR      R0,[R2, #+_APP_SP_OFF_FPSCR]
519        B        _HandleReadRegDone
520_HandleReadFPSCRLazyMode:
521        VMRS     R0,FPSCR
522        B        _HandleReadRegDone
523_HandleReadRegFPS0_FPS31:                                 // RegIndex == 21-52
524        LSRS     R0,LR,#+5                                // CONTROL[2] == FPCA => NOT(FPCA) saved to LR[4]. LR[4] == 0 => Extended stack frame, so FPU regs possibly on stack
525        BCS      _HandleReadFPS0_FPS31LazyMode            // Remember: NOT(FPCA) is stored to LR. == 0 means: Extended stack frame
526        LDR      R0,=_SYSTEM_FPCCR
527        LDR      R0,[R0]
528        LSLS     R0,R0,#+2                                // FPCCR[30] -> Carry == 1 indicates if lazy mode is active, so space on stack is reserved but FPU registers are not saved on stack
529        BCS      _HandleReadFPS0_FPS31LazyMode
530        SUBS     R1,#+21                                  // Convert absolute reg index into rel. one
531        LSLS     R1,R1,#+2                                // RegIndex to position on stack
532        ADDS     R1,#+_APP_SP_OFF_S0
533        LDR      R0,[R2, R1]
534_HandleReadRegDone_Veneer:
535        B        _HandleReadRegDone
536_HandleReadFPS0_FPS31LazyMode:
537        SUBS R1,#+20                                   // convert abs. RegIndex into rel. one
538        MOVS R0,#+6
539        MULS R1,R0,R1
540        LDR R0,=_HandleReadRegUnknown
541        SUB      R0,R0,R1                              // _HandleReadRegUnknown - 6 * ((RegIndex - 21) + 1)
542        ORR      R0,R0,#1                              // Thumb bit needs to be set in DestAddr
543        BX       R0
544        //
545        // Table for reading FPS0-FPS31
546        //
547        VMOV     R0,S31                                // v = FPSx
548        B        _HandleReadRegDone
549        VMOV     R0,S30
550        B        _HandleReadRegDone
551        VMOV     R0,S29
552        B        _HandleReadRegDone
553        VMOV     R0,S28
554        B        _HandleReadRegDone
555        VMOV     R0,S27
556        B        _HandleReadRegDone
557        VMOV     R0,S26
558        B        _HandleReadRegDone
559        VMOV     R0,S25
560        B        _HandleReadRegDone
561        VMOV     R0,S24
562        B        _HandleReadRegDone
563        VMOV     R0,S23
564        B        _HandleReadRegDone
565        VMOV     R0,S22
566        B        _HandleReadRegDone
567        VMOV     R0,S21
568        B        _HandleReadRegDone
569        VMOV     R0,S20
570        B        _HandleReadRegDone
571        VMOV     R0,S19
572        B        _HandleReadRegDone
573        VMOV     R0,S18
574        B        _HandleReadRegDone
575        VMOV     R0,S17
576        B        _HandleReadRegDone
577        VMOV     R0,S16
578        B        _HandleReadRegDone
579        VMOV     R0,S15
580        B        _HandleReadRegDone
581        VMOV     R0,S14
582        B        _HandleReadRegDone
583        VMOV     R0,S13
584        B        _HandleReadRegDone
585        VMOV     R0,S12
586        B        _HandleReadRegDone
587        VMOV     R0,S11
588        B        _HandleReadRegDone
589        VMOV     R0,S10
590        B        _HandleReadRegDone
591        VMOV     R0,S9
592        B        _HandleReadRegDone
593        VMOV     R0,S8
594        B        _HandleReadRegDone
595        VMOV     R0,S7
596        B        _HandleReadRegDone
597        VMOV     R0,S6
598        B        _HandleReadRegDone
599        VMOV     R0,S5
600        B        _HandleReadRegDone
601        VMOV     R0,S4
602        B        _HandleReadRegDone
603        VMOV     R0,S3
604        B        _HandleReadRegDone
605        VMOV     R0,S2
606        B        _HandleReadRegDone
607        VMOV     R0,S1
608        B        _HandleReadRegDone
609        VMOV     R0,S0
610        B        _HandleReadRegDone
611#else
612        B        _HandleReadRegUnknown
613_HandleReadRegDone_Veneer:
614        B        _HandleReadRegDone
615#endif
616_HandleReadRegUnknown:
617        MOVS     R0,#+0                                // v = 0
618        B.N      _HandleReadRegDone
619_HandleReadRegDone:
620
621        // Send register content to J-Link and wait until J-Link has read the data
622
623        STR      R0,[R3, #+_SYSTEM_DCRDR_OFF]          // DCRDR = v;
624        LDR      R0,[R3, #+_SYSTEM_DEMCR_OFF]          // _SYSTEM_DEMCR |= (1uL << 19);  => Set MON_REQ bit, so J-Link knows monitor is ready to receive commands
625        ORR      R0,R0,#0x80000
626        STR      R0,[R3, #+_SYSTEM_DEMCR_OFF]          // Indicate data ready
627        B        _WaitProbeReadIndicateMonRdy
628
629        // Data section for register addresses
630
631_HandleWriteReg:
632        /*
633        _MON_CMD_WRITE_REG
634          CPU:                   DEMCR[19] -> 1 => Mon ready
635          J-Link: Data -> DCRDR, DEMCR[19] -> 0 => Data placed by probe
636          CPU:    DCRDR -> Read, Process command, DEMCR[19] -> 1 => Data read & mon ready
637
638        Register indexes
639        0-15: R0-R15       (13 == R13 reserved => is banked ... Has to be read as PSP / MSP. Decision has to be done by J-Link DLL side!)
640        16: XPSR
641        17: MSP
642        18: PSP
643        19: CFBP           CONTROL/FAULTMASK/BASEPRI/PRIMASK (packed into 4 bytes of word. CONTROL = CFBP[31:24], FAULTMASK = CFBP[16:23], BASEPRI = CFBP[15:8], PRIMASK = CFBP[7:0]
644        20: FPSCR
645        21-52: FPS0-FPS31
646
647
648        Register usage when entering this "subroutine":
649        R0 Cmd
650        R1 ParamInfo
651        R2 ---
652        R3  = &_SYSTEM_DCRDR  (allows also access to DEMCR with offset)
653        R12 ---
654
655        Table B1-9 EXC_RETURN definition of exception return behavior, with FP extension
656        LR           Return to     Return SP   Frame type
657        ---------------------------------------------------------
658        0xFFFFFFE1   Handler mode. MSP         Extended
659        0xFFFFFFE9   Thread mode   MSP         Extended
660        0xFFFFFFED   Thread mode   PSP         Extended
661        0xFFFFFFF1   Handler mode. MSP         Basic
662        0xFFFFFFF9   Thread mode   MSP         Basic
663        0xFFFFFFFD   Thread mode   PSP         Basic
664
665        So LR[2] == 1 => Return stack == PSP else MSP
666
667        R0-R3, R12, PC, xPSR can be written via application stackpointer
668        Other regs can be written directly
669
670
671        Read register data from J-Link into R0
672        */
673        LDR      R0,[R3, #+_SYSTEM_DEMCR_OFF]              // _SYSTEM_DEMCR |= (1uL << 19);  => Monitor is ready to receive register data
674        ORR      R0,R0,#0x80000
675        STR      R0,[R3, #+_SYSTEM_DEMCR_OFF]
676_HandleWRegWaitUntilDataRecv:
677        LDR      R0,[R3, #+_SYSTEM_DEMCR_OFF]
678        LSLS     R0,R0,#+12
679        BMI.N    _HandleWRegWaitUntilDataRecv              // DEMCR[19] == 0 => J-Link has placed new data for us
680        LDR      R0,[R3, #+_SYSTEM_DCRDR_OFF]              // Get register data
681        //
682        // Determine application SP
683        //
684        LSRS     R2,LR,#+3                         // Shift LR[2] into carry => Carry clear means that CPU was running on MSP
685        ITE      CS
686        MRSCS    R2,PSP
687        MRSCC    R2,MSP
688        CMP      R1,#+4                            // if (RegIndex < 4) { (R0-R3)
689        BCS      _HandleWriteRegR4
690        STR      R0,[R2, R1, LSL #+2]              // v = [SP + Rx * 4] (R0-R3)
691        B.N      _HandleWriteRegDone
692_HandleWriteRegR4:
693        CMP      R1,#+5                          // if (RegIndex < 5) { (R4)
694        BCS      _HandleWriteRegR5
695        MOV      R4,R0
696        B.N      _HandleWriteRegDone
697_HandleWriteRegR5:
698        CMP      R1,#+6                          // if (RegIndex < 6) { (R5)
699        BCS      _HandleWriteRegR6
700        MOV      R5,R0
701        B.N      _HandleWriteRegDone
702_HandleWriteRegR6:
703        CMP      R1,#+7                          // if (RegIndex < 7) { (R6)
704        BCS      _HandleWriteRegR7
705        MOV      R6,R0
706        B.N      _HandleWriteRegDone
707_HandleWriteRegR7:
708        CMP      R1,#+8                          // if (RegIndex < 8) { (R7)
709        BCS      _HandleWriteRegR8
710        MOV      R7,R0
711        B.N      _HandleWriteRegDone
712_HandleWriteRegR8:
713        CMP      R1,#+9                          // if (RegIndex < 9) { (R8)
714        BCS      _HandleWriteRegR9
715        MOV      R8,R0
716        B.N      _HandleWriteRegDone
717_HandleWriteRegR9:
718        CMP      R1,#+10                         // if (RegIndex < 10) { (R9)
719        BCS      _HandleWriteRegR10
720        MOV      R9,R0
721        B.N      _HandleWriteRegDone
722_HandleWriteRegR10:
723        CMP      R1,#+11                         // if (RegIndex < 11) { (R10)
724        BCS      _HandleWriteRegR11
725        MOV      R10,R0
726        B.N      _HandleWriteRegDone
727_HandleWriteRegR11:
728        CMP      R1,#+12                         // if (RegIndex < 12) { (R11)
729        BCS      _HandleWriteRegR12
730        MOV      R11,R0
731        B.N      _HandleWriteRegDone
732_HandleWriteRegR12:
733        CMP      R1,#+14                         // if (RegIndex < 14) { (R12)
734        BCS      _HandleWriteRegR14
735        STR      R0,[R2, #+_APP_SP_OFF_R12]
736        B.N      _HandleWriteRegDone
737_HandleWriteRegR14:
738        CMP      R1,#+15                         // if (RegIndex < 15) { (R14 / LR)
739        BCS      _HandleWriteRegR15
740        STR      R0,[R2, #+_APP_SP_OFF_R14_LR]
741        B.N      _HandleWriteRegDone
742_HandleWriteRegR15:
743        CMP      R1,#+16                         // if (RegIndex < 16) { (R15 / PC)
744        BCS      _HandleWriteRegXPSR
745        STR      R0,[R2, #+_APP_SP_OFF_PC]
746        B.N      _HandleWriteRegDone
747_HandleWriteRegXPSR:
748        CMP      R1,#+17                         // if (RegIndex < 17) { (xPSR)
749        BCS      _HandleWriteRegMSP
750        STR      R0,[R2, #+_APP_SP_OFF_XPSR]
751        B.N      _HandleWriteRegDone
752_HandleWriteRegMSP:
753        //
754        // For now, SP cannot be modified because it is needed to jump back from monitor mode
755        //
756        CMP      R1,#+18                            // if (RegIndex < 18) { (MSP)
757        BCS      _HandleWriteRegPSP
758        B.N      _HandleWriteRegDone
759_HandleWriteRegPSP:                                 // RegIndex == 18
760        CMP      R1,#+19                            // if (RegIndex < 19) {
761        BCS      _HandleWriteRegCFBP
762        B.N      _HandleWriteRegDone
763_HandleWriteRegCFBP:
764        /*
765        CFBP is a register that can only be read via debug probe and is a merger of the following regs:
766        CONTROL/FAULTMASK/BASEPRI/PRIMASK (packed into 4 bytes of word. CONTROL = CFBP[31:24], FAULTMASK = CFBP[16:23], BASEPRI = CFBP[15:8], PRIMASK = CFBP[7:0]
767        To keep J-Link side the same for monitor and halt mode, we also return CFBP in monitor mode
768        */
769        CMP      R1,#+20                                // if (RegIndex < 20) { (CFBP)
770        BCS      _HandleWriteRegFPU
771        LSLS     R1,R0,#+24
772        LSRS     R1,R1,#+24                             // Extract CFBP[7:0] => PRIMASK
773        MSR      PRIMASK,R1
774        LSLS     R1,R0,#+16
775        LSRS     R1,R1,#+24                             // Extract CFBP[15:8] => BASEPRI
776        MSR      BASEPRI,R1
777        LSLS     R1,R0,#+8                              // Extract CFBP[23:16] => FAULTMASK
778        LSRS     R1,R1,#+24
779        MSR      FAULTMASK,R1
780        LSRS     R1,R0,#+24                             // Extract CFBP[31:24] => CONTROL
781        LSRS     R0,R1,#2                               // Current CONTROL[1] -> Carry
782        ITE      CS                                     // Update saved CONTROL.SPSEL (CONTROL[1]). CONTROL.SPSEL is saved to LR[2] on exception entry => ARM DDI0403D, B1.5.6 Exception entry behavior
783        ORRCS    LR,LR,#+4
784        BICCC    LR,LR,#+4
785        BIC      R1,R1,#+2                              // CONTROL.SPSEL (CONTROL[1]) == 0 inside monitor. Otherwise behavior is UNPREDICTABLE
786        LSRS     R0,R1,#+3                              // New CONTROL.FPCA (CONTROL[2]) -> Carry
787        ITE      CS                                     // CONTROL[2] == FPCA => NOT(FPCA) saved to LR[4]. LR[4] == 0 => Extended stack frame, so FPU regs possibly on stack
788        BICCS    LR,LR,#+0x10                           // Remember: NOT(FPCA) is stored to LR. == 0 means: Extended stack frame
789        ORRCC    LR,LR,#+0x10
790        MRS      R0,CONTROL
791        LSRS     R0,R0,#+3                              // CONTROL[2] -> Carry
792        ITE      CS                                     // Preserve original value of current CONTROL[2]
793        ORRCS    R1,R1,#+0x04
794        BICCC    R1,R1,#+0x04
795        MSR      CONTROL,R1
796        ISB                                             // Necessary after writing to CONTROL, see ARM DDI0403D, B1.4.4 The special-purpose CONTROL register
797        B.N      _HandleWriteRegDone
798_HandleWriteRegFPU:
799#if _HAS_FPU_REGS
800        CMP      R1,#+53                                // if (RegIndex < 53) { (20 (FPSCR), 21-52 FPS0-FPS31)
801        BCS      _HandleWriteRegDone_Veneer
802        /*
803        Read Coprocessor Access Control Register (CPACR) to check if CP10 and CP11 are enabled
804        If not, access to floating point is not possible
805        CPACR[21:20] == CP10 enable. 0b01 = Privileged access only. 0b11 = Full access. Other = reserved
806        CPACR[23:22] == CP11 enable. 0b01 = Privileged access only. 0b11 = Full access. Other = reserved
807        */
808        MOV      R12,R0                                  // Save register data
809        LDR      R0,_AddrCPACR
810        LDR      R0,[R0]
811        LSLS     R0,R0,#+8
812        LSRS     R0,R0,#+28
813        CMP      R0,#+0xF
814        BEQ      _HandleWriteRegFPU_Allowed
815        CMP      R0,#+0x5
816        BNE      _HandleWriteRegDone_Veneer
817_HandleWriteRegFPU_Allowed:
818        CMP      R1,#+21                                  // if (RegIndex < 21) (20 == FPSCR)
819        BCS      _HandleWriteRegFPS0_FPS31
820        LSRS     R0,LR,#+5                                // CONTROL[2] == FPCA => NOT(FPCA) saved to LR[4]. LR[4] == 0 => Extended stack frame, so FPU regs possibly on stack
821        BCS      _HandleWriteFPSCRLazyMode                // Remember: NOT(FPCA) is stored to LR. == 0 means: Extended stack frame
822        LDR      R0,=_SYSTEM_FPCCR
823        LDR      R0,[R0]
824        LSLS     R0,R0,#+2                                // FPCCR[30] -> Carry == 1 indicates if lazy mode is active, so space on stack is reserved but FPU registers are not saved on stack
825        BCS      _HandleWriteFPSCRLazyMode
826        STR      R12,[R2, #+_APP_SP_OFF_FPSCR]
827        B        _HandleWriteRegDone
828_HandleWriteFPSCRLazyMode:
829        VMSR     FPSCR,R12
830        B        _HandleWriteRegDone
831_HandleWriteRegFPS0_FPS31:                                // RegIndex == 21-52
832        LDR      R0,=_SYSTEM_FPCCR
833        LDR      R0,[R0]
834        LSLS     R0,R0,#+2                                // FPCCR[30] -> Carry == 1 indicates if lazy mode is active, so space on stack is reserved but FPU registers are not saved on stack
835        BCS      _HandleWriteFPS0_FPS31LazyMode
836        LSRS     R0,LR,#+5                                // CONTROL[2] == FPCA => NOT(FPCA) saved to LR[4]. LR[4] == 0 => Extended stack frame, so FPU regs possibly on stack
837        BCS     _HandleWriteFPS0_FPS31LazyMode            // Remember: NOT(FPCA) is stored to LR. == 0 means: Extended stack frame
838        SUBS     R1,#+21                                  // Convert absolute reg index into rel. one
839        LSLS     R1,R1,#+2                                // RegIndex to position on stack
840        ADDS     R1,#+_APP_SP_OFF_S0
841        STR      R12,[R2, R1]
842_HandleWriteRegDone_Veneer:
843        B        _HandleWriteRegDone
844_HandleWriteFPS0_FPS31LazyMode:
845        SUBS     R1,#+20                                  // Convert abs. RegIndex into rel. one
846        MOVS     R0,#+6
847        MULS     R1,R0,R1
848        LDR      R0,=_HandleReadRegUnknown
849        SUB      R0,R0,R1                                 // _HandleReadRegUnknown - 6 * ((RegIndex - 21) + 1)
850        ORR      R0,R0,#1                                 // Thumb bit needs to be set in DestAddr
851        BX       R0
852        //
853        // Table for reading FPS0-FPS31
854        //
855        VMOV     S31,R12                                  // v = FPSx
856        B        _HandleWriteRegDone
857        VMOV     S30,R12
858        B        _HandleWriteRegDone
859        VMOV     S29,R12
860        B        _HandleWriteRegDone
861        VMOV     S28,R12
862        B        _HandleWriteRegDone
863        VMOV     S27,R12
864        B        _HandleWriteRegDone
865        VMOV     S26,R12
866        B        _HandleWriteRegDone
867        VMOV     S25,R12
868        B        _HandleWriteRegDone
869        VMOV     S24,R12
870        B        _HandleWriteRegDone
871        VMOV     S23,R12
872        B        _HandleWriteRegDone
873        VMOV     S22,R12
874        B        _HandleWriteRegDone
875        VMOV     S21,R12
876        B        _HandleWriteRegDone
877        VMOV     S20,R12
878        B        _HandleWriteRegDone
879        VMOV     S19,R12
880        B        _HandleWriteRegDone
881        VMOV     S18,R12
882        B        _HandleWriteRegDone
883        VMOV     S17,R12
884        B        _HandleWriteRegDone
885        VMOV     S16,R12
886        B        _HandleWriteRegDone
887        VMOV     S15,R12
888        B        _HandleWriteRegDone
889        VMOV     S14,R12
890        B        _HandleWriteRegDone
891        VMOV     S13,R12
892        B        _HandleWriteRegDone
893        VMOV     S12,R12
894        B        _HandleWriteRegDone
895        VMOV     S11,R12
896        B        _HandleWriteRegDone
897        VMOV     S10,R12
898        B        _HandleWriteRegDone
899        VMOV     S9,R12
900        B        _HandleWriteRegDone
901        VMOV     S8,R12
902        B        _HandleWriteRegDone
903        VMOV     S7,R12
904        B        _HandleWriteRegDone
905        VMOV     S6,R12
906        B        _HandleWriteRegDone
907        VMOV     S5,R12
908        B        _HandleWriteRegDone
909        VMOV     S4,R12
910        B        _HandleWriteRegDone
911        VMOV     S3,R12
912        B        _HandleWriteRegDone
913        VMOV     S2,R12
914        B        _HandleWriteRegDone
915        VMOV     S1,R12
916        B        _HandleWriteRegDone
917        VMOV     S0,R12
918        B        _HandleWriteRegDone
919#else
920        B        _HandleWriteRegUnknown
921#endif
922_HandleWriteRegUnknown:
923        B.N      _HandleWriteRegDone
924_HandleWriteRegDone:
925        B        _IndicateMonReady                     // Indicate that monitor has read data, processed command and is ready for a new one
926        .end
927/****** End Of File *************************************************/
928