1cfae5c90SAndreas Färber /* 2cfae5c90SAndreas Färber * s390x gdb server stub 3cfae5c90SAndreas Färber * 4cfae5c90SAndreas Färber * Copyright (c) 2003-2005 Fabrice Bellard 5cfae5c90SAndreas Färber * Copyright (c) 2013 SUSE LINUX Products GmbH 6cfae5c90SAndreas Färber * 7cfae5c90SAndreas Färber * This library is free software; you can redistribute it and/or 8cfae5c90SAndreas Färber * modify it under the terms of the GNU Lesser General Public 9cfae5c90SAndreas Färber * License as published by the Free Software Foundation; either 10cfae5c90SAndreas Färber * version 2 of the License, or (at your option) any later version. 11cfae5c90SAndreas Färber * 12cfae5c90SAndreas Färber * This library is distributed in the hope that it will be useful, 13cfae5c90SAndreas Färber * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cfae5c90SAndreas Färber * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cfae5c90SAndreas Färber * Lesser General Public License for more details. 16cfae5c90SAndreas Färber * 17cfae5c90SAndreas Färber * You should have received a copy of the GNU Lesser General Public 18cfae5c90SAndreas Färber * License along with this library; if not, see <http://www.gnu.org/licenses/>. 19cfae5c90SAndreas Färber */ 205b50e790SAndreas Färber #include "config.h" 215b50e790SAndreas Färber #include "qemu-common.h" 225b50e790SAndreas Färber #include "exec/gdbstub.h" 235b50e790SAndreas Färber #include "qemu/bitops.h" 24cfae5c90SAndreas Färber 255b50e790SAndreas Färber int s390_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) 26cfae5c90SAndreas Färber { 275b50e790SAndreas Färber S390CPU *cpu = S390_CPU(cs); 285b50e790SAndreas Färber CPUS390XState *env = &cpu->env; 29cfae5c90SAndreas Färber uint64_t val; 30cfae5c90SAndreas Färber int cc_op; 31cfae5c90SAndreas Färber 32cfae5c90SAndreas Färber switch (n) { 33cfae5c90SAndreas Färber case S390_PSWM_REGNUM: 3497fa52f0SDavid Hildenbrand if (tcg_enabled()) { 3597fa52f0SDavid Hildenbrand cc_op = calc_cc(env, env->cc_op, env->cc_src, env->cc_dst, 3697fa52f0SDavid Hildenbrand env->cc_vr); 37cfae5c90SAndreas Färber val = deposit64(env->psw.mask, 44, 2, cc_op); 38986a2998SAndreas Färber return gdb_get_regl(mem_buf, val); 3997fa52f0SDavid Hildenbrand } 4097fa52f0SDavid Hildenbrand return gdb_get_regl(mem_buf, env->psw.mask); 41cfae5c90SAndreas Färber case S390_PSWA_REGNUM: 42986a2998SAndreas Färber return gdb_get_regl(mem_buf, env->psw.addr); 43cfae5c90SAndreas Färber case S390_R0_REGNUM ... S390_R15_REGNUM: 44986a2998SAndreas Färber return gdb_get_regl(mem_buf, env->regs[n - S390_R0_REGNUM]); 45cfae5c90SAndreas Färber } 46cfae5c90SAndreas Färber return 0; 47cfae5c90SAndreas Färber } 48cfae5c90SAndreas Färber 495b50e790SAndreas Färber int s390_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) 50cfae5c90SAndreas Färber { 515b50e790SAndreas Färber S390CPU *cpu = S390_CPU(cs); 525b50e790SAndreas Färber CPUS390XState *env = &cpu->env; 5373d510c9SDavid Hildenbrand target_ulong tmpl = ldtul_p(mem_buf); 54cfae5c90SAndreas Färber 55cfae5c90SAndreas Färber switch (n) { 56cfae5c90SAndreas Färber case S390_PSWM_REGNUM: 57cfae5c90SAndreas Färber env->psw.mask = tmpl; 5897fa52f0SDavid Hildenbrand if (tcg_enabled()) { 59cfae5c90SAndreas Färber env->cc_op = extract64(tmpl, 44, 2); 6097fa52f0SDavid Hildenbrand } 61cfae5c90SAndreas Färber break; 62cfae5c90SAndreas Färber case S390_PSWA_REGNUM: 63cfae5c90SAndreas Färber env->psw.addr = tmpl; 64cfae5c90SAndreas Färber break; 65cfae5c90SAndreas Färber case S390_R0_REGNUM ... S390_R15_REGNUM: 66cfae5c90SAndreas Färber env->regs[n - S390_R0_REGNUM] = tmpl; 67cfae5c90SAndreas Färber break; 68cfae5c90SAndreas Färber default: 69cfae5c90SAndreas Färber return 0; 70cfae5c90SAndreas Färber } 7173d510c9SDavid Hildenbrand return 8; 7273d510c9SDavid Hildenbrand } 7373d510c9SDavid Hildenbrand 7473d510c9SDavid Hildenbrand /* the values represent the positions in s390-acr.xml */ 7573d510c9SDavid Hildenbrand #define S390_A0_REGNUM 0 7673d510c9SDavid Hildenbrand #define S390_A15_REGNUM 15 7773d510c9SDavid Hildenbrand /* total number of registers in s390-acr.xml */ 7873d510c9SDavid Hildenbrand #define S390_NUM_AC_REGS 16 7973d510c9SDavid Hildenbrand 8073d510c9SDavid Hildenbrand static int cpu_read_ac_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 8173d510c9SDavid Hildenbrand { 8273d510c9SDavid Hildenbrand switch (n) { 8373d510c9SDavid Hildenbrand case S390_A0_REGNUM ... S390_A15_REGNUM: 8473d510c9SDavid Hildenbrand return gdb_get_reg32(mem_buf, env->aregs[n]); 8573d510c9SDavid Hildenbrand default: 8673d510c9SDavid Hildenbrand return 0; 8773d510c9SDavid Hildenbrand } 8873d510c9SDavid Hildenbrand } 8973d510c9SDavid Hildenbrand 9073d510c9SDavid Hildenbrand static int cpu_write_ac_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 9173d510c9SDavid Hildenbrand { 9273d510c9SDavid Hildenbrand switch (n) { 9373d510c9SDavid Hildenbrand case S390_A0_REGNUM ... S390_A15_REGNUM: 9473d510c9SDavid Hildenbrand env->aregs[n] = ldl_p(mem_buf); 9555b1b753SDavid Hildenbrand cpu_synchronize_post_init(ENV_GET_CPU(env)); 9673d510c9SDavid Hildenbrand return 4; 9773d510c9SDavid Hildenbrand default: 9873d510c9SDavid Hildenbrand return 0; 9973d510c9SDavid Hildenbrand } 10073d510c9SDavid Hildenbrand } 10173d510c9SDavid Hildenbrand 10273d510c9SDavid Hildenbrand /* the values represent the positions in s390-fpr.xml */ 10373d510c9SDavid Hildenbrand #define S390_FPC_REGNUM 0 10473d510c9SDavid Hildenbrand #define S390_F0_REGNUM 1 10573d510c9SDavid Hildenbrand #define S390_F15_REGNUM 16 10673d510c9SDavid Hildenbrand /* total number of registers in s390-fpr.xml */ 10773d510c9SDavid Hildenbrand #define S390_NUM_FP_REGS 17 10873d510c9SDavid Hildenbrand 10973d510c9SDavid Hildenbrand static int cpu_read_fp_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 11073d510c9SDavid Hildenbrand { 11173d510c9SDavid Hildenbrand switch (n) { 11273d510c9SDavid Hildenbrand case S390_FPC_REGNUM: 11373d510c9SDavid Hildenbrand return gdb_get_reg32(mem_buf, env->fpc); 11473d510c9SDavid Hildenbrand case S390_F0_REGNUM ... S390_F15_REGNUM: 115c498d8e3SEric Farman return gdb_get_reg64(mem_buf, get_freg(env, n - S390_F0_REGNUM)->ll); 11673d510c9SDavid Hildenbrand default: 11773d510c9SDavid Hildenbrand return 0; 11873d510c9SDavid Hildenbrand } 11973d510c9SDavid Hildenbrand } 12073d510c9SDavid Hildenbrand 12173d510c9SDavid Hildenbrand static int cpu_write_fp_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 12273d510c9SDavid Hildenbrand { 12373d510c9SDavid Hildenbrand switch (n) { 12473d510c9SDavid Hildenbrand case S390_FPC_REGNUM: 12573d510c9SDavid Hildenbrand env->fpc = ldl_p(mem_buf); 12673d510c9SDavid Hildenbrand return 4; 12773d510c9SDavid Hildenbrand case S390_F0_REGNUM ... S390_F15_REGNUM: 128c498d8e3SEric Farman get_freg(env, n - S390_F0_REGNUM)->ll = ldtul_p(mem_buf); 12973d510c9SDavid Hildenbrand return 8; 13073d510c9SDavid Hildenbrand default: 13173d510c9SDavid Hildenbrand return 0; 13273d510c9SDavid Hildenbrand } 13373d510c9SDavid Hildenbrand } 13473d510c9SDavid Hildenbrand 135ca343c7aSEric Farman /* the values represent the positions in s390-vx.xml */ 136ca343c7aSEric Farman #define S390_V0L_REGNUM 0 137ca343c7aSEric Farman #define S390_V15L_REGNUM 15 138ca343c7aSEric Farman #define S390_V16_REGNUM 16 139ca343c7aSEric Farman #define S390_V31_REGNUM 31 140ca343c7aSEric Farman /* total number of registers in s390-vx.xml */ 141ca343c7aSEric Farman #define S390_NUM_VREGS 32 142ca343c7aSEric Farman 143ca343c7aSEric Farman static int cpu_read_vreg(CPUS390XState *env, uint8_t *mem_buf, int n) 144ca343c7aSEric Farman { 145ca343c7aSEric Farman int ret; 146ca343c7aSEric Farman 147ca343c7aSEric Farman switch (n) { 148ca343c7aSEric Farman case S390_V0L_REGNUM ... S390_V15L_REGNUM: 149ca343c7aSEric Farman ret = gdb_get_reg64(mem_buf, env->vregs[n][1].ll); 150ca343c7aSEric Farman break; 151ca343c7aSEric Farman case S390_V16_REGNUM ... S390_V31_REGNUM: 152ca343c7aSEric Farman ret = gdb_get_reg64(mem_buf, env->vregs[n][0].ll); 153ca343c7aSEric Farman ret += gdb_get_reg64(mem_buf + 8, env->vregs[n][1].ll); 154ca343c7aSEric Farman break; 155ca343c7aSEric Farman default: 156ca343c7aSEric Farman ret = 0; 157ca343c7aSEric Farman } 158ca343c7aSEric Farman 159ca343c7aSEric Farman return ret; 160ca343c7aSEric Farman } 161ca343c7aSEric Farman 162ca343c7aSEric Farman static int cpu_write_vreg(CPUS390XState *env, uint8_t *mem_buf, int n) 163ca343c7aSEric Farman { 164ca343c7aSEric Farman switch (n) { 165ca343c7aSEric Farman case S390_V0L_REGNUM ... S390_V15L_REGNUM: 166ca343c7aSEric Farman env->vregs[n][1].ll = ldtul_p(mem_buf + 8); 167ca343c7aSEric Farman return 8; 168ca343c7aSEric Farman case S390_V16_REGNUM ... S390_V31_REGNUM: 169ca343c7aSEric Farman env->vregs[n][0].ll = ldtul_p(mem_buf); 170ca343c7aSEric Farman env->vregs[n][1].ll = ldtul_p(mem_buf + 8); 171ca343c7aSEric Farman return 16; 172ca343c7aSEric Farman default: 173ca343c7aSEric Farman return 0; 174ca343c7aSEric Farman } 175ca343c7aSEric Farman } 176ca343c7aSEric Farman 1775b9f6345SDavid Hildenbrand /* the values represent the positions in s390-cr.xml */ 1785b9f6345SDavid Hildenbrand #define S390_C0_REGNUM 0 1795b9f6345SDavid Hildenbrand #define S390_C15_REGNUM 15 1805b9f6345SDavid Hildenbrand /* total number of registers in s390-cr.xml */ 1815b9f6345SDavid Hildenbrand #define S390_NUM_C_REGS 16 1825b9f6345SDavid Hildenbrand 1835b9f6345SDavid Hildenbrand #ifndef CONFIG_USER_ONLY 1845b9f6345SDavid Hildenbrand static int cpu_read_c_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 1855b9f6345SDavid Hildenbrand { 1865b9f6345SDavid Hildenbrand switch (n) { 1875b9f6345SDavid Hildenbrand case S390_C0_REGNUM ... S390_C15_REGNUM: 1885b9f6345SDavid Hildenbrand return gdb_get_regl(mem_buf, env->cregs[n]); 1895b9f6345SDavid Hildenbrand default: 1905b9f6345SDavid Hildenbrand return 0; 1915b9f6345SDavid Hildenbrand } 1925b9f6345SDavid Hildenbrand } 1935b9f6345SDavid Hildenbrand 1945b9f6345SDavid Hildenbrand static int cpu_write_c_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 1955b9f6345SDavid Hildenbrand { 1965b9f6345SDavid Hildenbrand switch (n) { 1975b9f6345SDavid Hildenbrand case S390_C0_REGNUM ... S390_C15_REGNUM: 1985b9f6345SDavid Hildenbrand env->cregs[n] = ldtul_p(mem_buf); 1995b9f6345SDavid Hildenbrand if (tcg_enabled()) { 2005b9f6345SDavid Hildenbrand tlb_flush(ENV_GET_CPU(env), 1); 2015b9f6345SDavid Hildenbrand } 2025b9f6345SDavid Hildenbrand cpu_synchronize_post_init(ENV_GET_CPU(env)); 2035b9f6345SDavid Hildenbrand return 8; 2045b9f6345SDavid Hildenbrand default: 2055b9f6345SDavid Hildenbrand return 0; 2065b9f6345SDavid Hildenbrand } 2075b9f6345SDavid Hildenbrand } 2085b9f6345SDavid Hildenbrand #endif 2095b9f6345SDavid Hildenbrand 21073d510c9SDavid Hildenbrand void s390_cpu_gdb_init(CPUState *cs) 21173d510c9SDavid Hildenbrand { 21273d510c9SDavid Hildenbrand gdb_register_coprocessor(cs, cpu_read_ac_reg, 21373d510c9SDavid Hildenbrand cpu_write_ac_reg, 21473d510c9SDavid Hildenbrand S390_NUM_AC_REGS, "s390-acr.xml", 0); 21573d510c9SDavid Hildenbrand 21673d510c9SDavid Hildenbrand gdb_register_coprocessor(cs, cpu_read_fp_reg, 21773d510c9SDavid Hildenbrand cpu_write_fp_reg, 21873d510c9SDavid Hildenbrand S390_NUM_FP_REGS, "s390-fpr.xml", 0); 219ca343c7aSEric Farman 220ca343c7aSEric Farman gdb_register_coprocessor(cs, cpu_read_vreg, 221ca343c7aSEric Farman cpu_write_vreg, 222ca343c7aSEric Farman S390_NUM_VREGS, "s390-vx.xml", 0); 2235b9f6345SDavid Hildenbrand 2245b9f6345SDavid Hildenbrand #ifndef CONFIG_USER_ONLY 2255b9f6345SDavid Hildenbrand gdb_register_coprocessor(cs, cpu_read_c_reg, 2265b9f6345SDavid Hildenbrand cpu_write_c_reg, 2275b9f6345SDavid Hildenbrand S390_NUM_C_REGS, "s390-cr.xml", 0); 2285b9f6345SDavid Hildenbrand #endif 229cfae5c90SAndreas Färber } 230