1814ac26cSAndreas Färber /* 2814ac26cSAndreas Färber * MIPS gdb server stub 3814ac26cSAndreas Färber * 4814ac26cSAndreas Färber * Copyright (c) 2003-2005 Fabrice Bellard 5814ac26cSAndreas Färber * Copyright (c) 2013 SUSE LINUX Products GmbH 6814ac26cSAndreas Färber * 7814ac26cSAndreas Färber * This library is free software; you can redistribute it and/or 8814ac26cSAndreas Färber * modify it under the terms of the GNU Lesser General Public 9814ac26cSAndreas Färber * License as published by the Free Software Foundation; either 10814ac26cSAndreas Färber * version 2 of the License, or (at your option) any later version. 11814ac26cSAndreas Färber * 12814ac26cSAndreas Färber * This library is distributed in the hope that it will be useful, 13814ac26cSAndreas Färber * but WITHOUT ANY WARRANTY; without even the implied warranty of 14814ac26cSAndreas Färber * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15814ac26cSAndreas Färber * Lesser General Public License for more details. 16814ac26cSAndreas Färber * 17814ac26cSAndreas Färber * You should have received a copy of the GNU Lesser General Public 18814ac26cSAndreas Färber * License along with this library; if not, see <http://www.gnu.org/licenses/>. 19814ac26cSAndreas Färber */ 20c684822aSPeter Maydell #include "qemu/osdep.h" 215b50e790SAndreas Färber #include "qemu-common.h" 2233c11879SPaolo Bonzini #include "cpu.h" 23*26aa3d9aSPhilippe Mathieu-Daudé #include "internal.h" 245b50e790SAndreas Färber #include "exec/gdbstub.h" 25814ac26cSAndreas Färber 265b50e790SAndreas Färber int mips_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) 27814ac26cSAndreas Färber { 285b50e790SAndreas Färber MIPSCPU *cpu = MIPS_CPU(cs); 295b50e790SAndreas Färber CPUMIPSState *env = &cpu->env; 305b50e790SAndreas Färber 31814ac26cSAndreas Färber if (n < 32) { 32986a2998SAndreas Färber return gdb_get_regl(mem_buf, env->active_tc.gpr[n]); 33814ac26cSAndreas Färber } 34cbb26c9aSMaciej W. Rozycki if (env->CP0_Config1 & (1 << CP0C1_FP) && n >= 38 && n < 72) { 35cbb26c9aSMaciej W. Rozycki switch (n) { 36cbb26c9aSMaciej W. Rozycki case 70: 37cbb26c9aSMaciej W. Rozycki return gdb_get_regl(mem_buf, (int32_t)env->active_fpu.fcr31); 38cbb26c9aSMaciej W. Rozycki case 71: 39cbb26c9aSMaciej W. Rozycki return gdb_get_regl(mem_buf, (int32_t)env->active_fpu.fcr0); 40cbb26c9aSMaciej W. Rozycki default: 41814ac26cSAndreas Färber if (env->CP0_Status & (1 << CP0St_FR)) { 42986a2998SAndreas Färber return gdb_get_regl(mem_buf, 43986a2998SAndreas Färber env->active_fpu.fpr[n - 38].d); 44814ac26cSAndreas Färber } else { 45986a2998SAndreas Färber return gdb_get_regl(mem_buf, 46986a2998SAndreas Färber env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX]); 47814ac26cSAndreas Färber } 48814ac26cSAndreas Färber } 49814ac26cSAndreas Färber } 50814ac26cSAndreas Färber switch (n) { 51814ac26cSAndreas Färber case 32: 52986a2998SAndreas Färber return gdb_get_regl(mem_buf, (int32_t)env->CP0_Status); 53814ac26cSAndreas Färber case 33: 54986a2998SAndreas Färber return gdb_get_regl(mem_buf, env->active_tc.LO[0]); 55814ac26cSAndreas Färber case 34: 56986a2998SAndreas Färber return gdb_get_regl(mem_buf, env->active_tc.HI[0]); 57814ac26cSAndreas Färber case 35: 58986a2998SAndreas Färber return gdb_get_regl(mem_buf, env->CP0_BadVAddr); 59814ac26cSAndreas Färber case 36: 60986a2998SAndreas Färber return gdb_get_regl(mem_buf, (int32_t)env->CP0_Cause); 61814ac26cSAndreas Färber case 37: 62986a2998SAndreas Färber return gdb_get_regl(mem_buf, env->active_tc.PC | 63986a2998SAndreas Färber !!(env->hflags & MIPS_HFLAG_M16)); 64814ac26cSAndreas Färber case 72: 65986a2998SAndreas Färber return gdb_get_regl(mem_buf, 0); /* fp */ 66814ac26cSAndreas Färber case 89: 67986a2998SAndreas Färber return gdb_get_regl(mem_buf, (int32_t)env->CP0_PRid); 68cbb26c9aSMaciej W. Rozycki default: 69cbb26c9aSMaciej W. Rozycki if (n > 89) { 70cbb26c9aSMaciej W. Rozycki return 0; 71814ac26cSAndreas Färber } 72814ac26cSAndreas Färber /* 16 embedded regs. */ 73986a2998SAndreas Färber return gdb_get_regl(mem_buf, 0); 74814ac26cSAndreas Färber } 75814ac26cSAndreas Färber 76814ac26cSAndreas Färber return 0; 77814ac26cSAndreas Färber } 78814ac26cSAndreas Färber 795b50e790SAndreas Färber int mips_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) 80814ac26cSAndreas Färber { 815b50e790SAndreas Färber MIPSCPU *cpu = MIPS_CPU(cs); 825b50e790SAndreas Färber CPUMIPSState *env = &cpu->env; 83814ac26cSAndreas Färber target_ulong tmp; 84814ac26cSAndreas Färber 85814ac26cSAndreas Färber tmp = ldtul_p(mem_buf); 86814ac26cSAndreas Färber 87814ac26cSAndreas Färber if (n < 32) { 88814ac26cSAndreas Färber env->active_tc.gpr[n] = tmp; 89814ac26cSAndreas Färber return sizeof(target_ulong); 90814ac26cSAndreas Färber } 91cbb26c9aSMaciej W. Rozycki if (env->CP0_Config1 & (1 << CP0C1_FP) && n >= 38 && n < 72) { 92814ac26cSAndreas Färber switch (n) { 93814ac26cSAndreas Färber case 70: 94599bc5e8SAleksandar Markovic env->active_fpu.fcr31 = (tmp & env->active_fpu.fcr31_rw_bitmask) | 95599bc5e8SAleksandar Markovic (env->active_fpu.fcr31 & ~(env->active_fpu.fcr31_rw_bitmask)); 96599bc5e8SAleksandar Markovic restore_fp_status(env); 97814ac26cSAndreas Färber break; 98814ac26cSAndreas Färber case 71: 99c7d4d98aSMaciej W. Rozycki /* FIR is read-only. Ignore writes. */ 100814ac26cSAndreas Färber break; 101cbb26c9aSMaciej W. Rozycki default: 102cbb26c9aSMaciej W. Rozycki if (env->CP0_Status & (1 << CP0St_FR)) { 103cbb26c9aSMaciej W. Rozycki env->active_fpu.fpr[n - 38].d = tmp; 104cbb26c9aSMaciej W. Rozycki } else { 105cbb26c9aSMaciej W. Rozycki env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX] = tmp; 106cbb26c9aSMaciej W. Rozycki } 107cbb26c9aSMaciej W. Rozycki break; 108814ac26cSAndreas Färber } 109814ac26cSAndreas Färber return sizeof(target_ulong); 110814ac26cSAndreas Färber } 111814ac26cSAndreas Färber switch (n) { 112814ac26cSAndreas Färber case 32: 11381a423e6SMaciej W. Rozycki #ifndef CONFIG_USER_ONLY 11481a423e6SMaciej W. Rozycki cpu_mips_store_status(env, tmp); 11581a423e6SMaciej W. Rozycki #endif 116814ac26cSAndreas Färber break; 117814ac26cSAndreas Färber case 33: 118814ac26cSAndreas Färber env->active_tc.LO[0] = tmp; 119814ac26cSAndreas Färber break; 120814ac26cSAndreas Färber case 34: 121814ac26cSAndreas Färber env->active_tc.HI[0] = tmp; 122814ac26cSAndreas Färber break; 123814ac26cSAndreas Färber case 35: 124814ac26cSAndreas Färber env->CP0_BadVAddr = tmp; 125814ac26cSAndreas Färber break; 126814ac26cSAndreas Färber case 36: 12781a423e6SMaciej W. Rozycki #ifndef CONFIG_USER_ONLY 12881a423e6SMaciej W. Rozycki cpu_mips_store_cause(env, tmp); 12981a423e6SMaciej W. Rozycki #endif 130814ac26cSAndreas Färber break; 131814ac26cSAndreas Färber case 37: 132814ac26cSAndreas Färber env->active_tc.PC = tmp & ~(target_ulong)1; 133814ac26cSAndreas Färber if (tmp & 1) { 134814ac26cSAndreas Färber env->hflags |= MIPS_HFLAG_M16; 135814ac26cSAndreas Färber } else { 136814ac26cSAndreas Färber env->hflags &= ~(MIPS_HFLAG_M16); 137814ac26cSAndreas Färber } 138814ac26cSAndreas Färber break; 139814ac26cSAndreas Färber case 72: /* fp, ignored */ 140814ac26cSAndreas Färber break; 141814ac26cSAndreas Färber default: 142814ac26cSAndreas Färber if (n > 89) { 143814ac26cSAndreas Färber return 0; 144814ac26cSAndreas Färber } 145814ac26cSAndreas Färber /* Other registers are readonly. Ignore writes. */ 146814ac26cSAndreas Färber break; 147814ac26cSAndreas Färber } 148814ac26cSAndreas Färber 149814ac26cSAndreas Färber return sizeof(target_ulong); 150814ac26cSAndreas Färber } 151