638747560cb08f9c66762477c84ef0fa2220db6d
[fw/openocd] / src / target / register.c
1 /***************************************************************************
2  *   Copyright (C) 2005 by Dominic Rath                                    *
3  *   Dominic.Rath@gmx.de                                                   *
4  *                                                                         *
5  *   Copyright (C) 2007,2008 Ã˜yvind Harboe                                 *
6  *   oyvind.harboe@zylin.com                                               *
7  *                                                                         *
8  *   This program is free software; you can redistribute it and/or modify  *
9  *   it under the terms of the GNU General Public License as published by  *
10  *   the Free Software Foundation; either version 2 of the License, or     *
11  *   (at your option) any later version.                                   *
12  *                                                                         *
13  *   This program is distributed in the hope that it will be useful,       *
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
16  *   GNU General Public License for more details.                          *
17  *                                                                         *
18  *   You should have received a copy of the GNU General Public License     *
19  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
20  ***************************************************************************/
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "register.h"
27 #include <helper/log.h>
28
29 /**
30  * @file
31  * Holds utilities to work with register caches.
32  *
33  * OpenOCD uses machine registers internally, and exposes them by name
34  * to Tcl scripts.  Sets of related registers are grouped into caches.
35  * For example, a CPU core will expose a set of registers, and there
36  * may be separate registers associated with debug or trace modules.
37  */
38
39 struct reg *register_get_by_number(struct reg_cache *first,
40                 uint32_t reg_num, bool search_all)
41 {
42         struct reg_cache *cache = first;
43
44         while (cache) {
45                 for (unsigned int i = 0; i < cache->num_regs; i++) {
46                         if (!cache->reg_list[i].exist)
47                                 continue;
48                         if (cache->reg_list[i].number == reg_num)
49                                 return &(cache->reg_list[i]);
50                 }
51
52                 if (!search_all)
53                         break;
54
55                 cache = cache->next;
56         }
57
58         return NULL;
59 }
60
61 struct reg *register_get_by_name(struct reg_cache *first,
62                 const char *name, bool search_all)
63 {
64         struct reg_cache *cache = first;
65
66         while (cache) {
67                 for (unsigned int i = 0; i < cache->num_regs; i++) {
68                         if (!cache->reg_list[i].exist)
69                                 continue;
70                         if (strcmp(cache->reg_list[i].name, name) == 0)
71                                 return &(cache->reg_list[i]);
72                 }
73
74                 if (!search_all)
75                         break;
76
77                 cache = cache->next;
78         }
79
80         return NULL;
81 }
82
83 struct reg_cache **register_get_last_cache_p(struct reg_cache **first)
84 {
85         struct reg_cache **cache_p = first;
86
87         if (*cache_p)
88                 while (*cache_p)
89                         cache_p = &((*cache_p)->next);
90         else
91                 return first;
92
93         return cache_p;
94 }
95
96 void register_unlink_cache(struct reg_cache **cache_p, const struct reg_cache *cache)
97 {
98         while (*cache_p && *cache_p != cache)
99                 cache_p = &((*cache_p)->next);
100         if (*cache_p)
101                 *cache_p = cache->next;
102 }
103
104 /** Marks the contents of the register cache as invalid (and clean). */
105 void register_cache_invalidate(struct reg_cache *cache)
106 {
107         struct reg *reg = cache->reg_list;
108
109         for (unsigned int n = cache->num_regs; n != 0; n--, reg++) {
110                 if (!reg->exist)
111                         continue;
112                 reg->valid = false;
113                 reg->dirty = false;
114         }
115 }
116
117 static int register_get_dummy_core_reg(struct reg *reg)
118 {
119         return ERROR_OK;
120 }
121
122 static int register_set_dummy_core_reg(struct reg *reg, uint8_t *buf)
123 {
124         reg->dirty = true;
125         reg->valid = true;
126
127         return ERROR_OK;
128 }
129
130 static const struct reg_arch_type dummy_type = {
131         .get = register_get_dummy_core_reg,
132         .set = register_set_dummy_core_reg,
133 };
134
135 void register_init_dummy(struct reg *reg)
136 {
137         reg->type = &dummy_type;
138 }