qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

gdbstub.c (4423B)


      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.1 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 "cpu.h"
     22 #include "internal.h"
     23 #include "exec/gdbstub.h"
     24 #include "fpu_helper.h"
     25 
     26 int mips_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
     27 {
     28     MIPSCPU *cpu = MIPS_CPU(cs);
     29     CPUMIPSState *env = &cpu->env;
     30 
     31     if (n < 32) {
     32         return gdb_get_regl(mem_buf, env->active_tc.gpr[n]);
     33     }
     34     if (env->CP0_Config1 & (1 << CP0C1_FP) && n >= 38 && n < 72) {
     35         switch (n) {
     36         case 70:
     37             return gdb_get_regl(mem_buf, (int32_t)env->active_fpu.fcr31);
     38         case 71:
     39             return gdb_get_regl(mem_buf, (int32_t)env->active_fpu.fcr0);
     40         default:
     41             if (env->CP0_Status & (1 << CP0St_FR)) {
     42                 return gdb_get_regl(mem_buf,
     43                     env->active_fpu.fpr[n - 38].d);
     44             } else {
     45                 return gdb_get_regl(mem_buf,
     46                     env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX]);
     47             }
     48         }
     49     }
     50     switch (n) {
     51     case 32:
     52         return gdb_get_regl(mem_buf, (int32_t)env->CP0_Status);
     53     case 33:
     54         return gdb_get_regl(mem_buf, env->active_tc.LO[0]);
     55     case 34:
     56         return gdb_get_regl(mem_buf, env->active_tc.HI[0]);
     57     case 35:
     58         return gdb_get_regl(mem_buf, env->CP0_BadVAddr);
     59     case 36:
     60         return gdb_get_regl(mem_buf, (int32_t)env->CP0_Cause);
     61     case 37:
     62         return gdb_get_regl(mem_buf, env->active_tc.PC |
     63                                      !!(env->hflags & MIPS_HFLAG_M16));
     64     case 72:
     65         return gdb_get_regl(mem_buf, 0); /* fp */
     66     case 89:
     67         return gdb_get_regl(mem_buf, (int32_t)env->CP0_PRid);
     68     default:
     69         if (n > 89) {
     70             return 0;
     71         }
     72         /* 16 embedded regs.  */
     73         return gdb_get_regl(mem_buf, 0);
     74     }
     75 
     76     return 0;
     77 }
     78 
     79 int mips_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
     80 {
     81     MIPSCPU *cpu = MIPS_CPU(cs);
     82     CPUMIPSState *env = &cpu->env;
     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) && n >= 38 && n < 72) {
     92         switch (n) {
     93         case 70:
     94             env->active_fpu.fcr31 = (tmp & env->active_fpu.fcr31_rw_bitmask) |
     95                   (env->active_fpu.fcr31 & ~(env->active_fpu.fcr31_rw_bitmask));
     96             restore_fp_status(env);
     97             break;
     98         case 71:
     99             /* FIR is read-only.  Ignore writes.  */
    100             break;
    101         default:
    102             if (env->CP0_Status & (1 << CP0St_FR)) {
    103                 env->active_fpu.fpr[n - 38].d = tmp;
    104             } else {
    105                 env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX] = tmp;
    106             }
    107             break;
    108         }
    109         return sizeof(target_ulong);
    110     }
    111     switch (n) {
    112     case 32:
    113 #ifndef CONFIG_USER_ONLY
    114         cpu_mips_store_status(env, tmp);
    115 #endif
    116         break;
    117     case 33:
    118         env->active_tc.LO[0] = tmp;
    119         break;
    120     case 34:
    121         env->active_tc.HI[0] = tmp;
    122         break;
    123     case 35:
    124         env->CP0_BadVAddr = tmp;
    125         break;
    126     case 36:
    127 #ifndef CONFIG_USER_ONLY
    128         cpu_mips_store_cause(env, tmp);
    129 #endif
    130         break;
    131     case 37:
    132         env->active_tc.PC = tmp & ~(target_ulong)1;
    133         if (tmp & 1) {
    134             env->hflags |= MIPS_HFLAG_M16;
    135         } else {
    136             env->hflags &= ~(MIPS_HFLAG_M16);
    137         }
    138         break;
    139     case 72: /* fp, ignored */
    140         break;
    141     default:
    142         if (n > 89) {
    143             return 0;
    144         }
    145         /* Other registers are readonly.  Ignore writes.  */
    146         break;
    147     }
    148 
    149     return sizeof(target_ulong);
    150 }