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 */ 205b50e790SAndreas Färber #include "config.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 } 32814ac26cSAndreas Färber if (env->CP0_Config1 & (1 << CP0C1_FP)) { 33814ac26cSAndreas Färber if (n >= 38 && n < 70) { 34814ac26cSAndreas Färber if (env->CP0_Status & (1 << CP0St_FR)) { 35986a2998SAndreas Färber return gdb_get_regl(mem_buf, 36986a2998SAndreas Färber env->active_fpu.fpr[n - 38].d); 37814ac26cSAndreas Färber } else { 38986a2998SAndreas Färber return gdb_get_regl(mem_buf, 39986a2998SAndreas Färber env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX]); 40814ac26cSAndreas Färber } 41814ac26cSAndreas Färber } 42814ac26cSAndreas Färber switch (n) { 43814ac26cSAndreas Färber case 70: 44986a2998SAndreas Färber return gdb_get_regl(mem_buf, (int32_t)env->active_fpu.fcr31); 45814ac26cSAndreas Färber case 71: 46986a2998SAndreas Färber return gdb_get_regl(mem_buf, (int32_t)env->active_fpu.fcr0); 47814ac26cSAndreas Färber } 48814ac26cSAndreas Färber } 49814ac26cSAndreas Färber switch (n) { 50814ac26cSAndreas Färber case 32: 51986a2998SAndreas Färber return gdb_get_regl(mem_buf, (int32_t)env->CP0_Status); 52814ac26cSAndreas Färber case 33: 53986a2998SAndreas Färber return gdb_get_regl(mem_buf, env->active_tc.LO[0]); 54814ac26cSAndreas Färber case 34: 55986a2998SAndreas Färber return gdb_get_regl(mem_buf, env->active_tc.HI[0]); 56814ac26cSAndreas Färber case 35: 57986a2998SAndreas Färber return gdb_get_regl(mem_buf, env->CP0_BadVAddr); 58814ac26cSAndreas Färber case 36: 59986a2998SAndreas Färber return gdb_get_regl(mem_buf, (int32_t)env->CP0_Cause); 60814ac26cSAndreas Färber case 37: 61986a2998SAndreas Färber return gdb_get_regl(mem_buf, env->active_tc.PC | 62986a2998SAndreas Färber !!(env->hflags & MIPS_HFLAG_M16)); 63814ac26cSAndreas Färber case 72: 64986a2998SAndreas Färber return gdb_get_regl(mem_buf, 0); /* fp */ 65814ac26cSAndreas Färber case 89: 66986a2998SAndreas Färber return gdb_get_regl(mem_buf, (int32_t)env->CP0_PRid); 67814ac26cSAndreas Färber } 68814ac26cSAndreas Färber if (n >= 73 && n <= 88) { 69814ac26cSAndreas Färber /* 16 embedded regs. */ 70986a2998SAndreas Färber return gdb_get_regl(mem_buf, 0); 71814ac26cSAndreas Färber } 72814ac26cSAndreas Färber 73814ac26cSAndreas Färber return 0; 74814ac26cSAndreas Färber } 75814ac26cSAndreas Färber 76814ac26cSAndreas Färber /* convert MIPS rounding mode in FCR31 to IEEE library */ 77814ac26cSAndreas Färber static unsigned int ieee_rm[] = { 78814ac26cSAndreas Färber float_round_nearest_even, 79814ac26cSAndreas Färber float_round_to_zero, 80814ac26cSAndreas Färber float_round_up, 81814ac26cSAndreas Färber float_round_down 82814ac26cSAndreas Färber }; 83814ac26cSAndreas Färber #define RESTORE_ROUNDING_MODE \ 84814ac26cSAndreas Färber set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], \ 85814ac26cSAndreas Färber &env->active_fpu.fp_status) 86814ac26cSAndreas Färber 875b50e790SAndreas Färber int mips_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) 88814ac26cSAndreas Färber { 895b50e790SAndreas Färber MIPSCPU *cpu = MIPS_CPU(cs); 905b50e790SAndreas Färber CPUMIPSState *env = &cpu->env; 91814ac26cSAndreas Färber target_ulong tmp; 92814ac26cSAndreas Färber 93814ac26cSAndreas Färber tmp = ldtul_p(mem_buf); 94814ac26cSAndreas Färber 95814ac26cSAndreas Färber if (n < 32) { 96814ac26cSAndreas Färber env->active_tc.gpr[n] = tmp; 97814ac26cSAndreas Färber return sizeof(target_ulong); 98814ac26cSAndreas Färber } 99814ac26cSAndreas Färber if (env->CP0_Config1 & (1 << CP0C1_FP) 100814ac26cSAndreas Färber && n >= 38 && n < 73) { 101814ac26cSAndreas Färber if (n < 70) { 102814ac26cSAndreas Färber if (env->CP0_Status & (1 << CP0St_FR)) { 103814ac26cSAndreas Färber env->active_fpu.fpr[n - 38].d = tmp; 104814ac26cSAndreas Färber } else { 105814ac26cSAndreas Färber env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX] = tmp; 106814ac26cSAndreas Färber } 107814ac26cSAndreas Färber } 108814ac26cSAndreas Färber switch (n) { 109814ac26cSAndreas Färber case 70: 110814ac26cSAndreas Färber env->active_fpu.fcr31 = tmp & 0xFF83FFFF; 111814ac26cSAndreas Färber /* set rounding mode */ 112814ac26cSAndreas Färber RESTORE_ROUNDING_MODE; 113814ac26cSAndreas Färber break; 114814ac26cSAndreas Färber case 71: 115814ac26cSAndreas Färber env->active_fpu.fcr0 = tmp; 116814ac26cSAndreas Färber break; 117814ac26cSAndreas Färber } 118814ac26cSAndreas Färber return sizeof(target_ulong); 119814ac26cSAndreas Färber } 120814ac26cSAndreas Färber switch (n) { 121814ac26cSAndreas Färber case 32: 122814ac26cSAndreas Färber env->CP0_Status = tmp; 123814ac26cSAndreas Färber break; 124814ac26cSAndreas Färber case 33: 125814ac26cSAndreas Färber env->active_tc.LO[0] = tmp; 126814ac26cSAndreas Färber break; 127814ac26cSAndreas Färber case 34: 128814ac26cSAndreas Färber env->active_tc.HI[0] = tmp; 129814ac26cSAndreas Färber break; 130814ac26cSAndreas Färber case 35: 131814ac26cSAndreas Färber env->CP0_BadVAddr = tmp; 132814ac26cSAndreas Färber break; 133814ac26cSAndreas Färber case 36: 134814ac26cSAndreas Färber env->CP0_Cause = tmp; 135814ac26cSAndreas Färber break; 136814ac26cSAndreas Färber case 37: 137814ac26cSAndreas Färber env->active_tc.PC = tmp & ~(target_ulong)1; 138814ac26cSAndreas Färber if (tmp & 1) { 139814ac26cSAndreas Färber env->hflags |= MIPS_HFLAG_M16; 140814ac26cSAndreas Färber } else { 141814ac26cSAndreas Färber env->hflags &= ~(MIPS_HFLAG_M16); 142814ac26cSAndreas Färber } 143814ac26cSAndreas Färber break; 144814ac26cSAndreas Färber case 72: /* fp, ignored */ 145814ac26cSAndreas Färber break; 146814ac26cSAndreas Färber default: 147814ac26cSAndreas Färber if (n > 89) { 148814ac26cSAndreas Färber return 0; 149814ac26cSAndreas Färber } 150814ac26cSAndreas Färber /* Other registers are readonly. Ignore writes. */ 151814ac26cSAndreas Färber break; 152814ac26cSAndreas Färber } 153814ac26cSAndreas Färber 154814ac26cSAndreas Färber return sizeof(target_ulong); 155814ac26cSAndreas Färber } 156