summaryrefslogtreecommitdiffstats
path: root/target-ppc/gdbstub.c
blob: 1c910902ea483925914b4b99058d2c45fd160532 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
 * PowerPC gdb server stub
 *
 * Copyright (c) 2003-2005 Fabrice Bellard
 * Copyright (c) 2013 SUSE LINUX Products GmbH
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */
#include "config.h"
#include "qemu-common.h"
#include "exec/gdbstub.h"

/* Old gdb always expects FP registers.  Newer (xml-aware) gdb only
 * expects whatever the target description contains.  Due to a
 * historical mishap the FP registers appear in between core integer
 * regs and PC, MSR, CR, and so forth.  We hack round this by giving the
 * FP regs zero size when talking to a newer gdb.
 */

int ppc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
{
    PowerPCCPU *cpu = POWERPC_CPU(cs);
    CPUPPCState *env = &cpu->env;

    if (n < 32) {
        /* gprs */
        return gdb_get_regl(mem_buf, env->gpr[n]);
    } else if (n < 64) {
        /* fprs */
        if (gdb_has_xml) {
            return 0;
        }
        stfq_p(mem_buf, env->fpr[n-32]);
        return 8;
    } else {
        switch (n) {
        case 64:
            return gdb_get_regl(mem_buf, env->nip);
        case 65:
            return gdb_get_regl(mem_buf, env->msr);
        case 66:
            {
                uint32_t cr = 0;
                int i;
                for (i = 0; i < 8; i++) {
                    cr |= env->crf[i] << (32 - ((i + 1) * 4));
                }
                return gdb_get_reg32(mem_buf, cr);
            }
        case 67:
            return gdb_get_regl(mem_buf, env->lr);
        case 68:
            return gdb_get_regl(mem_buf, env->ctr);
        case 69:
            return gdb_get_regl(mem_buf, env->xer);
        case 70:
            {
                if (gdb_has_xml) {
                    return 0;
                }
                return gdb_get_reg32(mem_buf, env->fpscr);
            }
        }
    }
    return 0;
}

int ppc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
{
    PowerPCCPU *cpu = POWERPC_CPU(cs);
    CPUPPCState *env = &cpu->env;

    if (n < 32) {
        /* gprs */
        env->gpr[n] = ldtul_p(mem_buf);
        return sizeof(target_ulong);
    } else if (n < 64) {
        /* fprs */
        if (gdb_has_xml) {
            return 0;
        }
        env->fpr[n-32] = ldfq_p(mem_buf);
        return 8;
    } else {
        switch (n) {
        case 64:
            env->nip = ldtul_p(mem_buf);
            return sizeof(target_ulong);
        case 65:
            ppc_store_msr(env, ldtul_p(mem_buf));
            return sizeof(target_ulong);
        case 66:
            {
                uint32_t cr = ldl_p(mem_buf);
                int i;
                for (i = 0; i < 8; i++) {
                    env->crf[i] = (cr >> (32 - ((i + 1) * 4))) & 0xF;
                }
                return 4;
            }
        case 67:
            env->lr = ldtul_p(mem_buf);
            return sizeof(target_ulong);
        case 68:
            env->ctr = ldtul_p(mem_buf);
            return sizeof(target_ulong);
        case 69:
            env->xer = ldtul_p(mem_buf);
            return sizeof(target_ulong);
        case 70:
            /* fpscr */
            if (gdb_has_xml) {
                return 0;
            }
            store_fpscr(env, ldtul_p(mem_buf), 0xffffffff);
            return sizeof(target_ulong);
        }
    }
    return 0;
}