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" 225b50e790SAndreas Färber #include "exec/gdbstub.h" 23814ac26cSAndreas Färber 245b50e790SAndreas Färber int mips_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) 25814ac26cSAndreas Färber { 265b50e790SAndreas Färber MIPSCPU *cpu = MIPS_CPU(cs); 275b50e790SAndreas Färber CPUMIPSState *env = &cpu->env; 285b50e790SAndreas Färber 29814ac26cSAndreas Färber if (n < 32) { 30986a2998SAndreas Färber return gdb_get_regl(mem_buf, env->active_tc.gpr[n]); 31814ac26cSAndreas Färber } 32cbb26c9aSMaciej W. Rozycki if (env->CP0_Config1 & (1 << CP0C1_FP) && n >= 38 && n < 72) { 33cbb26c9aSMaciej W. Rozycki switch (n) { 34cbb26c9aSMaciej W. Rozycki case 70: 35cbb26c9aSMaciej W. Rozycki return gdb_get_regl(mem_buf, (int32_t)env->active_fpu.fcr31); 36cbb26c9aSMaciej W. Rozycki case 71: 37cbb26c9aSMaciej W. Rozycki return gdb_get_regl(mem_buf, (int32_t)env->active_fpu.fcr0); 38cbb26c9aSMaciej W. Rozycki default: 39814ac26cSAndreas Färber if (env->CP0_Status & (1 << CP0St_FR)) { 40986a2998SAndreas Färber return gdb_get_regl(mem_buf, 41986a2998SAndreas Färber env->active_fpu.fpr[n - 38].d); 42814ac26cSAndreas Färber } else { 43986a2998SAndreas Färber return gdb_get_regl(mem_buf, 44986a2998SAndreas Färber env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX]); 45814ac26cSAndreas Färber } 46814ac26cSAndreas Färber } 47814ac26cSAndreas Färber } 48814ac26cSAndreas Färber switch (n) { 49814ac26cSAndreas Färber case 32: 50986a2998SAndreas Färber return gdb_get_regl(mem_buf, (int32_t)env->CP0_Status); 51814ac26cSAndreas Färber case 33: 52986a2998SAndreas Färber return gdb_get_regl(mem_buf, env->active_tc.LO[0]); 53814ac26cSAndreas Färber case 34: 54986a2998SAndreas Färber return gdb_get_regl(mem_buf, env->active_tc.HI[0]); 55814ac26cSAndreas Färber case 35: 56986a2998SAndreas Färber return gdb_get_regl(mem_buf, env->CP0_BadVAddr); 57814ac26cSAndreas Färber case 36: 58986a2998SAndreas Färber return gdb_get_regl(mem_buf, (int32_t)env->CP0_Cause); 59814ac26cSAndreas Färber case 37: 60986a2998SAndreas Färber return gdb_get_regl(mem_buf, env->active_tc.PC | 61986a2998SAndreas Färber !!(env->hflags & MIPS_HFLAG_M16)); 62814ac26cSAndreas Färber case 72: 63986a2998SAndreas Färber return gdb_get_regl(mem_buf, 0); /* fp */ 64814ac26cSAndreas Färber case 89: 65986a2998SAndreas Färber return gdb_get_regl(mem_buf, (int32_t)env->CP0_PRid); 66cbb26c9aSMaciej W. Rozycki default: 67cbb26c9aSMaciej W. Rozycki if (n > 89) { 68cbb26c9aSMaciej W. Rozycki return 0; 69814ac26cSAndreas Färber } 70814ac26cSAndreas Färber /* 16 embedded regs. */ 71986a2998SAndreas Färber return gdb_get_regl(mem_buf, 0); 72814ac26cSAndreas Färber } 73814ac26cSAndreas Färber 74814ac26cSAndreas Färber return 0; 75814ac26cSAndreas Färber } 76814ac26cSAndreas Färber 775b50e790SAndreas Färber int mips_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) 78814ac26cSAndreas Färber { 795b50e790SAndreas Färber MIPSCPU *cpu = MIPS_CPU(cs); 805b50e790SAndreas Färber CPUMIPSState *env = &cpu->env; 81814ac26cSAndreas Färber target_ulong tmp; 82814ac26cSAndreas Färber 83814ac26cSAndreas Färber tmp = ldtul_p(mem_buf); 84814ac26cSAndreas Färber 85814ac26cSAndreas Färber if (n < 32) { 86814ac26cSAndreas Färber env->active_tc.gpr[n] = tmp; 87814ac26cSAndreas Färber return sizeof(target_ulong); 88814ac26cSAndreas Färber } 89cbb26c9aSMaciej W. Rozycki if (env->CP0_Config1 & (1 << CP0C1_FP) && n >= 38 && n < 72) { 90814ac26cSAndreas Färber switch (n) { 91814ac26cSAndreas Färber case 70: 92814ac26cSAndreas Färber env->active_fpu.fcr31 = tmp & 0xFF83FFFF; 93814ac26cSAndreas Färber /* set rounding mode */ 94bb962386SMaciej W. Rozycki restore_rounding_mode(env); 95bb962386SMaciej W. Rozycki /* set flush-to-zero mode */ 96bb962386SMaciej W. Rozycki restore_flush_mode(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