Statistics
| Branch: | Revision:

root / target-mips / gdbstub.c @ 986a2998

History | View | Annotate | Download (4.2 kB)

1
/*
2
 * MIPS 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

    
21
static int cpu_gdb_read_register(CPUMIPSState *env, uint8_t *mem_buf, int n)
22
{
23
    if (n < 32) {
24
        return gdb_get_regl(mem_buf, env->active_tc.gpr[n]);
25
    }
26
    if (env->CP0_Config1 & (1 << CP0C1_FP)) {
27
        if (n >= 38 && n < 70) {
28
            if (env->CP0_Status & (1 << CP0St_FR)) {
29
                return gdb_get_regl(mem_buf,
30
                    env->active_fpu.fpr[n - 38].d);
31
            } else {
32
                return gdb_get_regl(mem_buf,
33
                    env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX]);
34
            }
35
        }
36
        switch (n) {
37
        case 70:
38
            return gdb_get_regl(mem_buf, (int32_t)env->active_fpu.fcr31);
39
        case 71:
40
            return gdb_get_regl(mem_buf, (int32_t)env->active_fpu.fcr0);
41
        }
42
    }
43
    switch (n) {
44
    case 32:
45
        return gdb_get_regl(mem_buf, (int32_t)env->CP0_Status);
46
    case 33:
47
        return gdb_get_regl(mem_buf, env->active_tc.LO[0]);
48
    case 34:
49
        return gdb_get_regl(mem_buf, env->active_tc.HI[0]);
50
    case 35:
51
        return gdb_get_regl(mem_buf, env->CP0_BadVAddr);
52
    case 36:
53
        return gdb_get_regl(mem_buf, (int32_t)env->CP0_Cause);
54
    case 37:
55
        return gdb_get_regl(mem_buf, env->active_tc.PC |
56
                                     !!(env->hflags & MIPS_HFLAG_M16));
57
    case 72:
58
        return gdb_get_regl(mem_buf, 0); /* fp */
59
    case 89:
60
        return gdb_get_regl(mem_buf, (int32_t)env->CP0_PRid);
61
    }
62
    if (n >= 73 && n <= 88) {
63
        /* 16 embedded regs.  */
64
        return gdb_get_regl(mem_buf, 0);
65
    }
66

    
67
    return 0;
68
}
69

    
70
/* convert MIPS rounding mode in FCR31 to IEEE library */
71
static unsigned int ieee_rm[] = {
72
    float_round_nearest_even,
73
    float_round_to_zero,
74
    float_round_up,
75
    float_round_down
76
};
77
#define RESTORE_ROUNDING_MODE \
78
    set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], \
79
                            &env->active_fpu.fp_status)
80

    
81
static int cpu_gdb_write_register(CPUMIPSState *env, uint8_t *mem_buf, int n)
82
{
83
    target_ulong tmp;
84

    
85
    tmp = ldtul_p(mem_buf);
86

    
87
    if (n < 32) {
88
        env->active_tc.gpr[n] = tmp;
89
        return sizeof(target_ulong);
90
    }
91
    if (env->CP0_Config1 & (1 << CP0C1_FP)
92
            && n >= 38 && n < 73) {
93
        if (n < 70) {
94
            if (env->CP0_Status & (1 << CP0St_FR)) {
95
                env->active_fpu.fpr[n - 38].d = tmp;
96
            } else {
97
                env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX] = tmp;
98
            }
99
        }
100
        switch (n) {
101
        case 70:
102
            env->active_fpu.fcr31 = tmp & 0xFF83FFFF;
103
            /* set rounding mode */
104
            RESTORE_ROUNDING_MODE;
105
            break;
106
        case 71:
107
            env->active_fpu.fcr0 = tmp;
108
            break;
109
        }
110
        return sizeof(target_ulong);
111
    }
112
    switch (n) {
113
    case 32:
114
        env->CP0_Status = tmp;
115
        break;
116
    case 33:
117
        env->active_tc.LO[0] = tmp;
118
        break;
119
    case 34:
120
        env->active_tc.HI[0] = tmp;
121
        break;
122
    case 35:
123
        env->CP0_BadVAddr = tmp;
124
        break;
125
    case 36:
126
        env->CP0_Cause = tmp;
127
        break;
128
    case 37:
129
        env->active_tc.PC = tmp & ~(target_ulong)1;
130
        if (tmp & 1) {
131
            env->hflags |= MIPS_HFLAG_M16;
132
        } else {
133
            env->hflags &= ~(MIPS_HFLAG_M16);
134
        }
135
        break;
136
    case 72: /* fp, ignored */
137
        break;
138
    default:
139
        if (n > 89) {
140
            return 0;
141
        }
142
        /* Other registers are readonly.  Ignore writes.  */
143
        break;
144
    }
145

    
146
    return sizeof(target_ulong);
147
}