11# pyOCD debugger
2- # Copyright (c) 2016-2020 Arm Limited
2+ # Copyright (c) 2016-2020,2025 Arm Limited
33# SPDX-License-Identifier: Apache-2.0
44#
55# Licensed under the Apache License, Version 2.0 (the "License");
@@ -35,26 +35,27 @@ class RegisterCache(object):
3535 Same logic applies for XPSR submasks.
3636 """
3737
38- CFBP_INDEX = index_for_reg ('cfbp' )
38+ CFBP_INDEX_LIST = [
39+ index_for_reg ('cfbp' ),
40+ index_for_reg ('cfbp_s' ),
41+ index_for_reg ('cfbp_ns' )
42+ ]
43+
44+ CFBP_REGS_LIST = [
45+ [index_for_reg (name ) for name in ['control' , 'faultmask' , 'basepri' , 'primask' ]],
46+ [index_for_reg (name ) for name in ['control_s' , 'faultmask_s' , 'basepri_s' , 'primask_s' ]],
47+ [index_for_reg (name ) for name in ['control_ns' , 'faultmask_ns' , 'basepri_ns' , 'primask_ns' ]]
48+ ]
49+
3950 XPSR_INDEX = index_for_reg ('xpsr' )
4051
41- CFBP_REGS = [index_for_reg (name ) for name in [
42- 'cfbp' ,
43- 'control' ,
44- 'faultmask' ,
45- 'basepri' ,
46- 'primask' ,
47- ]]
48-
49- XPSR_REGS = [index_for_reg (name ) for name in [
50- 'xpsr' ,
51- 'apsr' ,
52- 'iapsr' ,
53- 'eapsr' ,
54- 'ipsr' ,
55- 'epsr' ,
56- 'iepsr' ,
57- ]]
52+ XPSR_REGS = [
53+ index_for_reg (name ) for name in ['apsr' , 'iapsr' , 'eapsr' , 'ipsr' , 'epsr' , 'iepsr' ]
54+ ]
55+
56+ SP_REGS = [
57+ index_for_reg (name ) for name in ['sp' , 'msp' , 'psp' , 'msp_s' , 'psp_s' , 'msp_ns' , 'psp_ns' ]
58+ ]
5859
5960 def __init__ (self , context , core ):
6061 self ._context = context
@@ -103,18 +104,20 @@ def read_core_registers_raw(self, reg_list):
103104 cached_set = set (r for r in reg_list if r in self ._cache )
104105 self ._metrics .hits += len (cached_set )
105106
106- # Read uncached registers from the target .
107+ # Create list of uncached registers .
107108 read_list = list (reg_set .difference (cached_set ))
108- reading_cfbp = any (r for r in read_list if r in self .CFBP_REGS )
109- reading_xpsr = any (r for r in read_list if r in self .XPSR_REGS )
110- if reading_cfbp :
111- if not self .CFBP_INDEX in read_list :
112- read_list .append (self .CFBP_INDEX )
113- cfbp_index = read_list .index (self .CFBP_INDEX )
114- if reading_xpsr :
115- if not self .XPSR_INDEX in read_list :
116- read_list .append (self .XPSR_INDEX )
117- xpsr_index = read_list .index (self .XPSR_INDEX )
109+
110+ read_cfbp_flags = []
111+ for index , regs in zip (self .CFBP_INDEX_LIST , self .CFBP_REGS_LIST ):
112+ read_cfpb = any (r for r in read_list if r in regs or r == index )
113+ read_cfbp_flags .append (read_cfpb )
114+ if read_cfpb and index not in read_list :
115+ read_list .append (index )
116+
117+ read_xpsr = any (r for r in read_list if r in self .XPSR_REGS or r == self .XPSR_INDEX )
118+ if read_xpsr and self .XPSR_INDEX not in read_list :
119+ read_list .append (self .XPSR_INDEX )
120+
118121 self ._metrics .misses += len (read_list )
119122
120123 # Read registers not in the cache from the target.
@@ -129,21 +132,20 @@ def read_core_registers_raw(self, reg_list):
129132 values = []
130133
131134 # Update all CFBP based registers.
132- if reading_cfbp :
133- v = values [ cfbp_index ]
134- self . _cache [ self . CFBP_INDEX ] = v
135- for r in self . CFBP_REGS :
136- if r == self . CFBP_INDEX :
137- continue
138- self ._cache [r ] = (v >> ((- r - 1 ) * 8 )) & 0xff
135+ for read_cfbp , index , regs in zip ( read_cfbp_flags , self . CFBP_INDEX_LIST , self . CFBP_REGS_LIST ) :
136+ if read_cfbp :
137+ i = read_list . index ( index )
138+ v = values [ i ]
139+ self . _cache [ index ] = v
140+ for r in regs :
141+ self ._cache [r ] = (v >> ((r & 3 ) * 8 )) & 0xff
139142
140143 # Update all XPSR based registers.
141- if reading_xpsr :
142- v = values [xpsr_index ]
144+ if read_xpsr :
145+ i = read_list .index (self .XPSR_INDEX )
146+ v = values [i ]
143147 self ._cache [self .XPSR_INDEX ] = v
144148 for r in self .XPSR_REGS :
145- if r == self .XPSR_INDEX :
146- continue
147149 self ._cache [r ] = v & CortexMCoreRegisterInfo .get (r ).psr_mask
148150
149151 # Build the results list in the same order as requested registers.
@@ -170,21 +172,34 @@ def write_core_registers_raw(self, reg_list, data_list):
170172 reg_list = self ._convert_and_check_registers (reg_list )
171173 self ._metrics .writes += len (reg_list )
172174
173- writing_cfbp = any (r for r in reg_list if r in self .CFBP_REGS )
174- writing_xpsr = any (r for r in reg_list if r in self .XPSR_REGS )
175-
176175 # Update cached register values.
177176 for i , r in enumerate (reg_list ):
178177 v = data_list [i ]
179178 self ._cache [r ] = v
180179
181- # Just remove all cached CFBP and XPSR based register values.
182- if writing_cfbp :
183- for r in self .CFBP_REGS :
180+ # Remove cached CFBP based register values when writing to them.
181+ if any (r for r in reg_list if r in self .CFBP_INDEX_LIST ):
182+ # If writing to any variant of CFBP register, remove all CFBP based registers from the cache.
183+ for index , regs in zip (self .CFBP_INDEX_LIST , self .CFBP_REGS_LIST ):
184+ for r in regs + [index ]:
185+ self ._cache .pop (r , None )
186+ else :
187+ # If writing to any variant of CFBP sub-register (CONTROL, FAULTMASK, BASEPRI, PRIMASK),
188+ # remove only variants of that sub-register from the cache.
189+ for pos in range (len (self .CFBP_REGS_LIST [0 ])):
190+ sub_regs = [regs [pos ] for regs in self .CFBP_REGS_LIST ]
191+ if any (r in sub_regs for r in reg_list ):
192+ for r in sub_regs :
193+ self ._cache .pop (r , None )
194+
195+ # Remove all cached XPSR based register values when writing any of them.
196+ if any (r for r in reg_list if r in self .XPSR_REGS or r == self .XPSR_INDEX ):
197+ for r in self .XPSR_REGS + [self .XPSR_INDEX ]:
184198 self ._cache .pop (r , None )
185199
186- if writing_xpsr :
187- for r in self .XPSR_REGS :
200+ # Remove all cached SP register values when writing any of them.
201+ if any (r for r in reg_list if r in self .SP_REGS ):
202+ for r in self .SP_REGS :
188203 self ._cache .pop (r , None )
189204
190205 # Write new register values to target.
@@ -197,4 +212,3 @@ def write_core_registers_raw(self, reg_list, data_list):
197212
198213 def invalidate (self ):
199214 self ._reset_cache ()
200-
0 commit comments