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 */ 20814ac26cSAndreas Färber 21814ac26cSAndreas Färber static int cpu_gdb_read_register(CPUMIPSState *env, uint8_t *mem_buf, int n) 22814ac26cSAndreas Färber { 23814ac26cSAndreas Färber if (n < 32) { 24814ac26cSAndreas Färber GET_REGL(env->active_tc.gpr[n]); 25814ac26cSAndreas Färber } 26814ac26cSAndreas Färber if (env->CP0_Config1 & (1 << CP0C1_FP)) { 27814ac26cSAndreas Färber if (n >= 38 && n < 70) { 28814ac26cSAndreas Färber if (env->CP0_Status & (1 << CP0St_FR)) { 29814ac26cSAndreas Färber GET_REGL(env->active_fpu.fpr[n - 38].d); 30814ac26cSAndreas Färber } else { 31814ac26cSAndreas Färber GET_REGL(env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX]); 32814ac26cSAndreas Färber } 33814ac26cSAndreas Färber } 34814ac26cSAndreas Färber switch (n) { 35814ac26cSAndreas Färber case 70: 36814ac26cSAndreas Färber GET_REGL((int32_t)env->active_fpu.fcr31); 37814ac26cSAndreas Färber case 71: 38814ac26cSAndreas Färber GET_REGL((int32_t)env->active_fpu.fcr0); 39814ac26cSAndreas Färber } 40814ac26cSAndreas Färber } 41814ac26cSAndreas Färber switch (n) { 42814ac26cSAndreas Färber case 32: 43814ac26cSAndreas Färber GET_REGL((int32_t)env->CP0_Status); 44814ac26cSAndreas Färber case 33: 45814ac26cSAndreas Färber GET_REGL(env->active_tc.LO[0]); 46814ac26cSAndreas Färber case 34: 47814ac26cSAndreas Färber GET_REGL(env->active_tc.HI[0]); 48814ac26cSAndreas Färber case 35: 49814ac26cSAndreas Färber GET_REGL(env->CP0_BadVAddr); 50814ac26cSAndreas Färber case 36: 51814ac26cSAndreas Färber GET_REGL((int32_t)env->CP0_Cause); 52814ac26cSAndreas Färber case 37: 53814ac26cSAndreas Färber GET_REGL(env->active_tc.PC | !!(env->hflags & MIPS_HFLAG_M16)); 54814ac26cSAndreas Färber case 72: 55814ac26cSAndreas Färber GET_REGL(0); /* fp */ 56814ac26cSAndreas Färber case 89: 57814ac26cSAndreas Färber GET_REGL((int32_t)env->CP0_PRid); 58814ac26cSAndreas Färber } 59814ac26cSAndreas Färber if (n >= 73 && n <= 88) { 60814ac26cSAndreas Färber /* 16 embedded regs. */ 61814ac26cSAndreas Färber GET_REGL(0); 62814ac26cSAndreas Färber } 63814ac26cSAndreas Färber 64814ac26cSAndreas Färber return 0; 65814ac26cSAndreas Färber } 66814ac26cSAndreas Färber 67814ac26cSAndreas Färber /* convert MIPS rounding mode in FCR31 to IEEE library */ 68814ac26cSAndreas Färber static unsigned int ieee_rm[] = { 69814ac26cSAndreas Färber float_round_nearest_even, 70814ac26cSAndreas Färber float_round_to_zero, 71814ac26cSAndreas Färber float_round_up, 72814ac26cSAndreas Färber float_round_down 73814ac26cSAndreas Färber }; 74814ac26cSAndreas Färber #define RESTORE_ROUNDING_MODE \ 75814ac26cSAndreas Färber set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], \ 76814ac26cSAndreas Färber &env->active_fpu.fp_status) 77814ac26cSAndreas Färber 78814ac26cSAndreas Färber static int cpu_gdb_write_register(CPUMIPSState *env, uint8_t *mem_buf, int n) 79814ac26cSAndreas Färber { 80814ac26cSAndreas Färber target_ulong tmp; 81814ac26cSAndreas Färber 82814ac26cSAndreas Färber tmp = ldtul_p(mem_buf); 83814ac26cSAndreas Färber 84814ac26cSAndreas Färber if (n < 32) { 85814ac26cSAndreas Färber env->active_tc.gpr[n] = tmp; 86814ac26cSAndreas Färber return sizeof(target_ulong); 87814ac26cSAndreas Färber } 88814ac26cSAndreas Färber if (env->CP0_Config1 & (1 << CP0C1_FP) 89814ac26cSAndreas Färber && n >= 38 && n < 73) { 90814ac26cSAndreas Färber if (n < 70) { 91814ac26cSAndreas Färber if (env->CP0_Status & (1 << CP0St_FR)) { 92814ac26cSAndreas Färber env->active_fpu.fpr[n - 38].d = tmp; 93814ac26cSAndreas Färber } else { 94814ac26cSAndreas Färber env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX] = tmp; 95814ac26cSAndreas Färber } 96814ac26cSAndreas Färber } 97814ac26cSAndreas Färber switch (n) { 98814ac26cSAndreas Färber case 70: 99814ac26cSAndreas Färber env->active_fpu.fcr31 = tmp & 0xFF83FFFF; 100814ac26cSAndreas Färber /* set rounding mode */ 101814ac26cSAndreas Färber RESTORE_ROUNDING_MODE; 102814ac26cSAndreas Färber break; 103814ac26cSAndreas Färber case 71: 104814ac26cSAndreas Färber env->active_fpu.fcr0 = tmp; 105814ac26cSAndreas Färber break; 106814ac26cSAndreas Färber } 107814ac26cSAndreas Färber return sizeof(target_ulong); 108814ac26cSAndreas Färber } 109814ac26cSAndreas Färber switch (n) { 110814ac26cSAndreas Färber case 32: 111814ac26cSAndreas Färber env->CP0_Status = tmp; 112814ac26cSAndreas Färber break; 113814ac26cSAndreas Färber case 33: 114814ac26cSAndreas Färber env->active_tc.LO[0] = tmp; 115814ac26cSAndreas Färber break; 116814ac26cSAndreas Färber case 34: 117814ac26cSAndreas Färber env->active_tc.HI[0] = tmp; 118814ac26cSAndreas Färber break; 119814ac26cSAndreas Färber case 35: 120814ac26cSAndreas Färber env->CP0_BadVAddr = tmp; 121814ac26cSAndreas Färber break; 122814ac26cSAndreas Färber case 36: 123814ac26cSAndreas Färber env->CP0_Cause = tmp; 124814ac26cSAndreas Färber break; 125814ac26cSAndreas Färber case 37: 126814ac26cSAndreas Färber env->active_tc.PC = tmp & ~(target_ulong)1; 127814ac26cSAndreas Färber if (tmp & 1) { 128814ac26cSAndreas Färber env->hflags |= MIPS_HFLAG_M16; 129814ac26cSAndreas Färber } else { 130814ac26cSAndreas Färber env->hflags &= ~(MIPS_HFLAG_M16); 131814ac26cSAndreas Färber } 132814ac26cSAndreas Färber break; 133814ac26cSAndreas Färber case 72: /* fp, ignored */ 134814ac26cSAndreas Färber break; 135814ac26cSAndreas Färber default: 136814ac26cSAndreas Färber if (n > 89) { 137814ac26cSAndreas Färber return 0; 138814ac26cSAndreas Färber } 139814ac26cSAndreas Färber /* Other registers are readonly. Ignore writes. */ 140814ac26cSAndreas Färber break; 141814ac26cSAndreas Färber } 142814ac26cSAndreas Färber 143814ac26cSAndreas Färber return sizeof(target_ulong); 144814ac26cSAndreas Färber } 145