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 1041c6a6ddSThomas Huth * version 2.1 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 */ 2014a48c1dSMarkus Armbruster 219615495aSPeter Maydell #include "qemu/osdep.h" 2233c11879SPaolo Bonzini #include "cpu.h" 23b6b47223SCho, Yu-Chen #include "s390x-internal.h" 2463c91552SPaolo Bonzini #include "exec/exec-all.h" 255b50e790SAndreas Färber #include "exec/gdbstub.h" 264ea5fe99SAlex Bennée #include "gdbstub/helpers.h" 275b50e790SAndreas Färber #include "qemu/bitops.h" 28b3946626SVincent Palatin #include "sysemu/hw_accel.h" 2914a48c1dSMarkus Armbruster #include "sysemu/tcg.h" 30cfae5c90SAndreas Färber 31a010bdbeSAlex Bennée int s390_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) 32cfae5c90SAndreas Färber { 33d0143fa9SPhilippe Mathieu-Daudé CPUS390XState *env = cpu_env(cs); 34cfae5c90SAndreas Färber 35cfae5c90SAndreas Färber switch (n) { 36cfae5c90SAndreas Färber case S390_PSWM_REGNUM: 37deb60cc7SRichard Henderson return gdb_get_regl(mem_buf, s390_cpu_get_psw_mask(env)); 38cfae5c90SAndreas Färber case S390_PSWA_REGNUM: 39986a2998SAndreas Färber return gdb_get_regl(mem_buf, env->psw.addr); 40cfae5c90SAndreas Färber case S390_R0_REGNUM ... S390_R15_REGNUM: 41986a2998SAndreas Färber return gdb_get_regl(mem_buf, env->regs[n - S390_R0_REGNUM]); 42cfae5c90SAndreas Färber } 43cfae5c90SAndreas Färber return 0; 44cfae5c90SAndreas Färber } 45cfae5c90SAndreas Färber 465b50e790SAndreas Färber int s390_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) 47cfae5c90SAndreas Färber { 48d0143fa9SPhilippe Mathieu-Daudé CPUS390XState *env = cpu_env(cs); 4973d510c9SDavid Hildenbrand target_ulong tmpl = ldtul_p(mem_buf); 50cfae5c90SAndreas Färber 51cfae5c90SAndreas Färber switch (n) { 52cfae5c90SAndreas Färber case S390_PSWM_REGNUM: 53deb60cc7SRichard Henderson s390_cpu_set_psw(env, tmpl, env->psw.addr); 54cfae5c90SAndreas Färber break; 55cfae5c90SAndreas Färber case S390_PSWA_REGNUM: 56cfae5c90SAndreas Färber env->psw.addr = tmpl; 57cfae5c90SAndreas Färber break; 58cfae5c90SAndreas Färber case S390_R0_REGNUM ... S390_R15_REGNUM: 59cfae5c90SAndreas Färber env->regs[n - S390_R0_REGNUM] = tmpl; 60cfae5c90SAndreas Färber break; 61cfae5c90SAndreas Färber default: 62cfae5c90SAndreas Färber return 0; 63cfae5c90SAndreas Färber } 6473d510c9SDavid Hildenbrand return 8; 6573d510c9SDavid Hildenbrand } 6673d510c9SDavid Hildenbrand 6773d510c9SDavid Hildenbrand /* the values represent the positions in s390-acr.xml */ 6873d510c9SDavid Hildenbrand #define S390_A0_REGNUM 0 6973d510c9SDavid Hildenbrand #define S390_A15_REGNUM 15 7073d510c9SDavid Hildenbrand 71a010bdbeSAlex Bennée static int cpu_read_ac_reg(CPUS390XState *env, GByteArray *buf, int n) 7273d510c9SDavid Hildenbrand { 7373d510c9SDavid Hildenbrand switch (n) { 7473d510c9SDavid Hildenbrand case S390_A0_REGNUM ... S390_A15_REGNUM: 75a010bdbeSAlex Bennée return gdb_get_reg32(buf, env->aregs[n]); 7673d510c9SDavid Hildenbrand default: 7773d510c9SDavid Hildenbrand return 0; 7873d510c9SDavid Hildenbrand } 7973d510c9SDavid Hildenbrand } 8073d510c9SDavid Hildenbrand 8173d510c9SDavid Hildenbrand static int cpu_write_ac_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 8273d510c9SDavid Hildenbrand { 8373d510c9SDavid Hildenbrand switch (n) { 8473d510c9SDavid Hildenbrand case S390_A0_REGNUM ... S390_A15_REGNUM: 8573d510c9SDavid Hildenbrand env->aregs[n] = ldl_p(mem_buf); 8629a0af61SRichard Henderson cpu_synchronize_post_init(env_cpu(env)); 8773d510c9SDavid Hildenbrand return 4; 8873d510c9SDavid Hildenbrand default: 8973d510c9SDavid Hildenbrand return 0; 9073d510c9SDavid Hildenbrand } 9173d510c9SDavid Hildenbrand } 9273d510c9SDavid Hildenbrand 9373d510c9SDavid Hildenbrand /* the values represent the positions in s390-fpr.xml */ 9473d510c9SDavid Hildenbrand #define S390_FPC_REGNUM 0 9573d510c9SDavid Hildenbrand #define S390_F0_REGNUM 1 9673d510c9SDavid Hildenbrand #define S390_F15_REGNUM 16 9773d510c9SDavid Hildenbrand 98a010bdbeSAlex Bennée static int cpu_read_fp_reg(CPUS390XState *env, GByteArray *buf, int n) 9973d510c9SDavid Hildenbrand { 10073d510c9SDavid Hildenbrand switch (n) { 10173d510c9SDavid Hildenbrand case S390_FPC_REGNUM: 102a010bdbeSAlex Bennée return gdb_get_reg32(buf, env->fpc); 10373d510c9SDavid Hildenbrand case S390_F0_REGNUM ... S390_F15_REGNUM: 104a010bdbeSAlex Bennée return gdb_get_reg64(buf, *get_freg(env, n - S390_F0_REGNUM)); 10573d510c9SDavid Hildenbrand default: 10673d510c9SDavid Hildenbrand return 0; 10773d510c9SDavid Hildenbrand } 10873d510c9SDavid Hildenbrand } 10973d510c9SDavid Hildenbrand 11073d510c9SDavid Hildenbrand static int cpu_write_fp_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 11173d510c9SDavid Hildenbrand { 11273d510c9SDavid Hildenbrand switch (n) { 11373d510c9SDavid Hildenbrand case S390_FPC_REGNUM: 11473d510c9SDavid Hildenbrand env->fpc = ldl_p(mem_buf); 11573d510c9SDavid Hildenbrand return 4; 11673d510c9SDavid Hildenbrand case S390_F0_REGNUM ... S390_F15_REGNUM: 1174f83d7d2SDavid Hildenbrand *get_freg(env, n - S390_F0_REGNUM) = ldtul_p(mem_buf); 11873d510c9SDavid Hildenbrand return 8; 11973d510c9SDavid Hildenbrand default: 12073d510c9SDavid Hildenbrand return 0; 12173d510c9SDavid Hildenbrand } 12273d510c9SDavid Hildenbrand } 12373d510c9SDavid Hildenbrand 124ca343c7aSEric Farman /* the values represent the positions in s390-vx.xml */ 125ca343c7aSEric Farman #define S390_V0L_REGNUM 0 126ca343c7aSEric Farman #define S390_V15L_REGNUM 15 127ca343c7aSEric Farman #define S390_V16_REGNUM 16 128ca343c7aSEric Farman #define S390_V31_REGNUM 31 129ca343c7aSEric Farman 130a010bdbeSAlex Bennée static int cpu_read_vreg(CPUS390XState *env, GByteArray *buf, int n) 131ca343c7aSEric Farman { 132ca343c7aSEric Farman int ret; 133ca343c7aSEric Farman 134ca343c7aSEric Farman switch (n) { 135ca343c7aSEric Farman case S390_V0L_REGNUM ... S390_V15L_REGNUM: 136a010bdbeSAlex Bennée ret = gdb_get_reg64(buf, env->vregs[n][1]); 137ca343c7aSEric Farman break; 138ca343c7aSEric Farman case S390_V16_REGNUM ... S390_V31_REGNUM: 139a010bdbeSAlex Bennée ret = gdb_get_reg64(buf, env->vregs[n][0]); 140a010bdbeSAlex Bennée ret += gdb_get_reg64(buf, env->vregs[n][1]); 141ca343c7aSEric Farman break; 142ca343c7aSEric Farman default: 143ca343c7aSEric Farman ret = 0; 144ca343c7aSEric Farman } 145ca343c7aSEric Farman 146ca343c7aSEric Farman return ret; 147ca343c7aSEric Farman } 148ca343c7aSEric Farman 149ca343c7aSEric Farman static int cpu_write_vreg(CPUS390XState *env, uint8_t *mem_buf, int n) 150ca343c7aSEric Farman { 151ca343c7aSEric Farman switch (n) { 152ca343c7aSEric Farman case S390_V0L_REGNUM ... S390_V15L_REGNUM: 1534f83d7d2SDavid Hildenbrand env->vregs[n][1] = ldtul_p(mem_buf + 8); 154ca343c7aSEric Farman return 8; 155ca343c7aSEric Farman case S390_V16_REGNUM ... S390_V31_REGNUM: 1564f83d7d2SDavid Hildenbrand env->vregs[n][0] = ldtul_p(mem_buf); 1574f83d7d2SDavid Hildenbrand env->vregs[n][1] = ldtul_p(mem_buf + 8); 158ca343c7aSEric Farman return 16; 159ca343c7aSEric Farman default: 160ca343c7aSEric Farman return 0; 161ca343c7aSEric Farman } 162ca343c7aSEric Farman } 163ca343c7aSEric Farman 1645b9f6345SDavid Hildenbrand /* the values represent the positions in s390-cr.xml */ 1655b9f6345SDavid Hildenbrand #define S390_C0_REGNUM 0 1665b9f6345SDavid Hildenbrand #define S390_C15_REGNUM 15 1675b9f6345SDavid Hildenbrand 1685b9f6345SDavid Hildenbrand #ifndef CONFIG_USER_ONLY 169a010bdbeSAlex Bennée static int cpu_read_c_reg(CPUS390XState *env, GByteArray *buf, int n) 1705b9f6345SDavid Hildenbrand { 1715b9f6345SDavid Hildenbrand switch (n) { 1725b9f6345SDavid Hildenbrand case S390_C0_REGNUM ... S390_C15_REGNUM: 173a010bdbeSAlex Bennée return gdb_get_regl(buf, env->cregs[n]); 1745b9f6345SDavid Hildenbrand default: 1755b9f6345SDavid Hildenbrand return 0; 1765b9f6345SDavid Hildenbrand } 1775b9f6345SDavid Hildenbrand } 1785b9f6345SDavid Hildenbrand 1795b9f6345SDavid Hildenbrand static int cpu_write_c_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 1805b9f6345SDavid Hildenbrand { 1815b9f6345SDavid Hildenbrand switch (n) { 1825b9f6345SDavid Hildenbrand case S390_C0_REGNUM ... S390_C15_REGNUM: 1835b9f6345SDavid Hildenbrand env->cregs[n] = ldtul_p(mem_buf); 1845b9f6345SDavid Hildenbrand if (tcg_enabled()) { 18529a0af61SRichard Henderson tlb_flush(env_cpu(env)); 1865b9f6345SDavid Hildenbrand } 18729a0af61SRichard Henderson cpu_synchronize_post_init(env_cpu(env)); 1885b9f6345SDavid Hildenbrand return 8; 1895b9f6345SDavid Hildenbrand default: 1905b9f6345SDavid Hildenbrand return 0; 1915b9f6345SDavid Hildenbrand } 1925b9f6345SDavid Hildenbrand } 1938a641ff6SDavid Hildenbrand 1948a641ff6SDavid Hildenbrand /* the values represent the positions in s390-virt.xml */ 1958a641ff6SDavid Hildenbrand #define S390_VIRT_CKC_REGNUM 0 1968a641ff6SDavid Hildenbrand #define S390_VIRT_CPUTM_REGNUM 1 1978a641ff6SDavid Hildenbrand #define S390_VIRT_BEA_REGNUM 2 1988a641ff6SDavid Hildenbrand #define S390_VIRT_PREFIX_REGNUM 3 1998a641ff6SDavid Hildenbrand 200a010bdbeSAlex Bennée static int cpu_read_virt_reg(CPUS390XState *env, GByteArray *mem_buf, int n) 2018a641ff6SDavid Hildenbrand { 2028a641ff6SDavid Hildenbrand switch (n) { 2038a641ff6SDavid Hildenbrand case S390_VIRT_CKC_REGNUM: 2048a641ff6SDavid Hildenbrand return gdb_get_regl(mem_buf, env->ckc); 2058a641ff6SDavid Hildenbrand case S390_VIRT_CPUTM_REGNUM: 2068a641ff6SDavid Hildenbrand return gdb_get_regl(mem_buf, env->cputm); 2078a641ff6SDavid Hildenbrand case S390_VIRT_BEA_REGNUM: 2088a641ff6SDavid Hildenbrand return gdb_get_regl(mem_buf, env->gbea); 2098a641ff6SDavid Hildenbrand case S390_VIRT_PREFIX_REGNUM: 2108a641ff6SDavid Hildenbrand return gdb_get_regl(mem_buf, env->psa); 2118a641ff6SDavid Hildenbrand default: 2128a641ff6SDavid Hildenbrand return 0; 2138a641ff6SDavid Hildenbrand } 2148a641ff6SDavid Hildenbrand } 2158a641ff6SDavid Hildenbrand 2168a641ff6SDavid Hildenbrand static int cpu_write_virt_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 2178a641ff6SDavid Hildenbrand { 2188a641ff6SDavid Hildenbrand switch (n) { 2198a641ff6SDavid Hildenbrand case S390_VIRT_CKC_REGNUM: 2208a641ff6SDavid Hildenbrand env->ckc = ldtul_p(mem_buf); 22129a0af61SRichard Henderson cpu_synchronize_post_init(env_cpu(env)); 2228a641ff6SDavid Hildenbrand return 8; 2238a641ff6SDavid Hildenbrand case S390_VIRT_CPUTM_REGNUM: 2248a641ff6SDavid Hildenbrand env->cputm = ldtul_p(mem_buf); 22529a0af61SRichard Henderson cpu_synchronize_post_init(env_cpu(env)); 2268a641ff6SDavid Hildenbrand return 8; 2278a641ff6SDavid Hildenbrand case S390_VIRT_BEA_REGNUM: 2288a641ff6SDavid Hildenbrand env->gbea = ldtul_p(mem_buf); 22929a0af61SRichard Henderson cpu_synchronize_post_init(env_cpu(env)); 2308a641ff6SDavid Hildenbrand return 8; 2318a641ff6SDavid Hildenbrand case S390_VIRT_PREFIX_REGNUM: 2328a641ff6SDavid Hildenbrand env->psa = ldtul_p(mem_buf); 23329a0af61SRichard Henderson cpu_synchronize_post_init(env_cpu(env)); 2348a641ff6SDavid Hildenbrand return 8; 2358afc43eaSIlya Leoshkevich default: 2368afc43eaSIlya Leoshkevich return 0; 2378afc43eaSIlya Leoshkevich } 2388afc43eaSIlya Leoshkevich } 2398afc43eaSIlya Leoshkevich 2408afc43eaSIlya Leoshkevich /* the values represent the positions in s390-virt-kvm.xml */ 2418afc43eaSIlya Leoshkevich #define S390_VIRT_KVM_PP_REGNUM 0 2428afc43eaSIlya Leoshkevich #define S390_VIRT_KVM_PFT_REGNUM 1 2438afc43eaSIlya Leoshkevich #define S390_VIRT_KVM_PFS_REGNUM 2 2448afc43eaSIlya Leoshkevich #define S390_VIRT_KVM_PFC_REGNUM 3 2458afc43eaSIlya Leoshkevich 2468afc43eaSIlya Leoshkevich static int cpu_read_virt_kvm_reg(CPUS390XState *env, GByteArray *mem_buf, int n) 2478afc43eaSIlya Leoshkevich { 2488afc43eaSIlya Leoshkevich switch (n) { 2498afc43eaSIlya Leoshkevich case S390_VIRT_KVM_PP_REGNUM: 2508afc43eaSIlya Leoshkevich return gdb_get_regl(mem_buf, env->pp); 2518afc43eaSIlya Leoshkevich case S390_VIRT_KVM_PFT_REGNUM: 2528afc43eaSIlya Leoshkevich return gdb_get_regl(mem_buf, env->pfault_token); 2538afc43eaSIlya Leoshkevich case S390_VIRT_KVM_PFS_REGNUM: 2548afc43eaSIlya Leoshkevich return gdb_get_regl(mem_buf, env->pfault_select); 2558afc43eaSIlya Leoshkevich case S390_VIRT_KVM_PFC_REGNUM: 2568afc43eaSIlya Leoshkevich return gdb_get_regl(mem_buf, env->pfault_compare); 2578afc43eaSIlya Leoshkevich default: 2588afc43eaSIlya Leoshkevich return 0; 2598afc43eaSIlya Leoshkevich } 2608afc43eaSIlya Leoshkevich } 2618afc43eaSIlya Leoshkevich 2628afc43eaSIlya Leoshkevich static int cpu_write_virt_kvm_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 2638afc43eaSIlya Leoshkevich { 2648afc43eaSIlya Leoshkevich switch (n) { 2658afc43eaSIlya Leoshkevich case S390_VIRT_KVM_PP_REGNUM: 2668a641ff6SDavid Hildenbrand env->pp = ldtul_p(mem_buf); 26729a0af61SRichard Henderson cpu_synchronize_post_init(env_cpu(env)); 2688a641ff6SDavid Hildenbrand return 8; 2698afc43eaSIlya Leoshkevich case S390_VIRT_KVM_PFT_REGNUM: 2708a641ff6SDavid Hildenbrand env->pfault_token = ldtul_p(mem_buf); 27129a0af61SRichard Henderson cpu_synchronize_post_init(env_cpu(env)); 2728a641ff6SDavid Hildenbrand return 8; 2738afc43eaSIlya Leoshkevich case S390_VIRT_KVM_PFS_REGNUM: 2748a641ff6SDavid Hildenbrand env->pfault_select = ldtul_p(mem_buf); 27529a0af61SRichard Henderson cpu_synchronize_post_init(env_cpu(env)); 2768a641ff6SDavid Hildenbrand return 8; 2778afc43eaSIlya Leoshkevich case S390_VIRT_KVM_PFC_REGNUM: 2788a641ff6SDavid Hildenbrand env->pfault_compare = ldtul_p(mem_buf); 27929a0af61SRichard Henderson cpu_synchronize_post_init(env_cpu(env)); 2808a641ff6SDavid Hildenbrand return 8; 2818a641ff6SDavid Hildenbrand default: 2828a641ff6SDavid Hildenbrand return 0; 2838a641ff6SDavid Hildenbrand } 2848a641ff6SDavid Hildenbrand } 2855b9f6345SDavid Hildenbrand #endif 2865b9f6345SDavid Hildenbrand 28786158a2aSChristian Borntraeger /* the values represent the positions in s390-gs.xml */ 28886158a2aSChristian Borntraeger #define S390_GS_RESERVED_REGNUM 0 28986158a2aSChristian Borntraeger #define S390_GS_GSD_REGNUM 1 29086158a2aSChristian Borntraeger #define S390_GS_GSSM_REGNUM 2 29186158a2aSChristian Borntraeger #define S390_GS_GSEPLA_REGNUM 3 29286158a2aSChristian Borntraeger 293a010bdbeSAlex Bennée static int cpu_read_gs_reg(CPUS390XState *env, GByteArray *buf, int n) 29486158a2aSChristian Borntraeger { 295a010bdbeSAlex Bennée return gdb_get_regl(buf, env->gscb[n]); 29686158a2aSChristian Borntraeger } 29786158a2aSChristian Borntraeger 29886158a2aSChristian Borntraeger static int cpu_write_gs_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 29986158a2aSChristian Borntraeger { 30086158a2aSChristian Borntraeger env->gscb[n] = ldtul_p(mem_buf); 30129a0af61SRichard Henderson cpu_synchronize_post_init(env_cpu(env)); 30286158a2aSChristian Borntraeger return 8; 30386158a2aSChristian Borntraeger } 30486158a2aSChristian Borntraeger 30573d510c9SDavid Hildenbrand void s390_cpu_gdb_init(CPUState *cs) 30673d510c9SDavid Hildenbrand { 30773d510c9SDavid Hildenbrand gdb_register_coprocessor(cs, cpu_read_ac_reg, 30873d510c9SDavid Hildenbrand cpu_write_ac_reg, 309*ac1e8671SAkihiko Odaki gdb_find_static_feature("s390-acr.xml"), 0); 31073d510c9SDavid Hildenbrand 31173d510c9SDavid Hildenbrand gdb_register_coprocessor(cs, cpu_read_fp_reg, 31273d510c9SDavid Hildenbrand cpu_write_fp_reg, 313*ac1e8671SAkihiko Odaki gdb_find_static_feature("s390-fpr.xml"), 0); 314ca343c7aSEric Farman 315ca343c7aSEric Farman gdb_register_coprocessor(cs, cpu_read_vreg, 316ca343c7aSEric Farman cpu_write_vreg, 317*ac1e8671SAkihiko Odaki gdb_find_static_feature("s390-vx.xml"), 0); 3185b9f6345SDavid Hildenbrand 31986158a2aSChristian Borntraeger gdb_register_coprocessor(cs, cpu_read_gs_reg, 32086158a2aSChristian Borntraeger cpu_write_gs_reg, 321*ac1e8671SAkihiko Odaki gdb_find_static_feature("s390-gs.xml"), 0); 32286158a2aSChristian Borntraeger 3235b9f6345SDavid Hildenbrand #ifndef CONFIG_USER_ONLY 3245b9f6345SDavid Hildenbrand gdb_register_coprocessor(cs, cpu_read_c_reg, 3255b9f6345SDavid Hildenbrand cpu_write_c_reg, 326*ac1e8671SAkihiko Odaki gdb_find_static_feature("s390-cr.xml"), 0); 3278a641ff6SDavid Hildenbrand 3288a641ff6SDavid Hildenbrand gdb_register_coprocessor(cs, cpu_read_virt_reg, 3298a641ff6SDavid Hildenbrand cpu_write_virt_reg, 330*ac1e8671SAkihiko Odaki gdb_find_static_feature("s390-virt.xml"), 0); 3318afc43eaSIlya Leoshkevich 3328afc43eaSIlya Leoshkevich if (kvm_enabled()) { 3338afc43eaSIlya Leoshkevich gdb_register_coprocessor(cs, cpu_read_virt_kvm_reg, 3348afc43eaSIlya Leoshkevich cpu_write_virt_kvm_reg, 335*ac1e8671SAkihiko Odaki gdb_find_static_feature("s390-virt-kvm.xml"), 3368afc43eaSIlya Leoshkevich 0); 3378a641ff6SDavid Hildenbrand } 3385b9f6345SDavid Hildenbrand #endif 339cfae5c90SAndreas Färber } 340