xref: /openbmc/qemu/target/xtensa/gdbstub.c (revision 9cdd2a73)
1 /*
2  * Xtensa gdb server stub
3  *
4  * Copyright (c) 2003-2005 Fabrice Bellard
5  * Copyright (c) 2013 SUSE LINUX Products GmbH
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19  */
20 #include "qemu/osdep.h"
21 #include "qemu-common.h"
22 #include "cpu.h"
23 #include "exec/gdbstub.h"
24 #include "qemu/log.h"
25 
26 int xtensa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
27 {
28     XtensaCPU *cpu = XTENSA_CPU(cs);
29     CPUXtensaState *env = &cpu->env;
30     const XtensaGdbReg *reg = env->config->gdb_regmap.reg + n;
31 #ifdef CONFIG_USER_ONLY
32     int num_regs = env->config->gdb_regmap.num_core_regs;
33 #else
34     int num_regs = env->config->gdb_regmap.num_regs;
35 #endif
36     unsigned i;
37 
38     if (n < 0 || n >= num_regs) {
39         return 0;
40     }
41 
42     switch (reg->type) {
43     case 9: /*pc*/
44         return gdb_get_reg32(mem_buf, env->pc);
45 
46     case 1: /*ar*/
47         xtensa_sync_phys_from_window(env);
48         return gdb_get_reg32(mem_buf, env->phys_regs[(reg->targno & 0xff)
49                                                      % env->config->nareg]);
50 
51     case 2: /*SR*/
52         return gdb_get_reg32(mem_buf, env->sregs[reg->targno & 0xff]);
53 
54     case 3: /*UR*/
55         return gdb_get_reg32(mem_buf, env->uregs[reg->targno & 0xff]);
56 
57     case 4: /*f*/
58         i = reg->targno & 0x0f;
59         switch (reg->size) {
60         case 4:
61             return gdb_get_reg32(mem_buf,
62                                  float32_val(env->fregs[i].f32[FP_F32_LOW]));
63         case 8:
64             return gdb_get_reg64(mem_buf, float64_val(env->fregs[i].f64));
65         default:
66             qemu_log_mask(LOG_UNIMP, "%s from reg %d of unsupported size %d\n",
67                           __func__, n, reg->size);
68             memset(mem_buf, 0, reg->size);
69             return reg->size;
70         }
71 
72     case 8: /*a*/
73         return gdb_get_reg32(mem_buf, env->regs[reg->targno & 0x0f]);
74 
75     default:
76         qemu_log_mask(LOG_UNIMP, "%s from reg %d of unsupported type %d\n",
77                       __func__, n, reg->type);
78         memset(mem_buf, 0, reg->size);
79         return reg->size;
80     }
81 }
82 
83 int xtensa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
84 {
85     XtensaCPU *cpu = XTENSA_CPU(cs);
86     CPUXtensaState *env = &cpu->env;
87     uint32_t tmp;
88     const XtensaGdbReg *reg = env->config->gdb_regmap.reg + n;
89 #ifdef CONFIG_USER_ONLY
90     int num_regs = env->config->gdb_regmap.num_core_regs;
91 #else
92     int num_regs = env->config->gdb_regmap.num_regs;
93 #endif
94 
95     if (n < 0 || n >= num_regs) {
96         return 0;
97     }
98 
99     tmp = ldl_p(mem_buf);
100 
101     switch (reg->type) {
102     case 9: /*pc*/
103         env->pc = tmp;
104         break;
105 
106     case 1: /*ar*/
107         env->phys_regs[(reg->targno & 0xff) % env->config->nareg] = tmp;
108         xtensa_sync_window_from_phys(env);
109         break;
110 
111     case 2: /*SR*/
112         env->sregs[reg->targno & 0xff] = tmp;
113         break;
114 
115     case 3: /*UR*/
116         env->uregs[reg->targno & 0xff] = tmp;
117         break;
118 
119     case 4: /*f*/
120         switch (reg->size) {
121         case 4:
122             env->fregs[reg->targno & 0x0f].f32[FP_F32_LOW] = make_float32(tmp);
123             return 4;
124         case 8:
125             env->fregs[reg->targno & 0x0f].f64 = make_float64(tmp);
126             return 8;
127         default:
128             qemu_log_mask(LOG_UNIMP, "%s to reg %d of unsupported size %d\n",
129                           __func__, n, reg->size);
130             return reg->size;
131         }
132 
133     case 8: /*a*/
134         env->regs[reg->targno & 0x0f] = tmp;
135         break;
136 
137     default:
138         qemu_log_mask(LOG_UNIMP, "%s to reg %d of unsupported type %d\n",
139                       __func__, n, reg->type);
140         return reg->size;
141     }
142 
143     return 4;
144 }
145