1185023Sraj/* FreeBSD/ARM specific low level interface, for the remote server for GDB. 2185023Sraj Copyright 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004 3185023Sraj Free Software Foundation, Inc. 4185023Sraj 5185023Sraj This file is part of GDB. 6185023Sraj 7185023Sraj This program is free software; you can redistribute it and/or modify 8185023Sraj it under the terms of the GNU General Public License as published by 9185023Sraj the Free Software Foundation; either version 2 of the License, or 10185023Sraj (at your option) any later version. 11185023Sraj 12185023Sraj This program is distributed in the hope that it will be useful, 13185023Sraj but WITHOUT ANY WARRANTY; without even the implied warranty of 14185023Sraj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15185023Sraj GNU General Public License for more details. 16185023Sraj 17185023Sraj You should have received a copy of the GNU General Public License 18185023Sraj along with this program; if not, write to the Free Software 19185023Sraj Foundation, Inc., 59 Temple Place - Suite 330, 20185023Sraj Boston, MA 02111-1307, USA. */ 21185023Sraj 22185023Sraj#include <sys/cdefs.h> 23185023Sraj__FBSDID("$FreeBSD: releng/11.0/gnu/usr.bin/gdb/gdbserver/fbsd-arm-low.c 185023 2008-11-17 16:32:57Z raj $"); 24185023Sraj 25185023Sraj#include "server.h" 26185023Sraj#include "fbsd-low.h" 27185023Sraj 28185023Sraj#ifdef HAVE_SYS_REG_H 29185023Sraj#include <sys/reg.h> 30185023Sraj#endif 31185023Sraj 32185023Sraj#include <sys/procfs.h> 33185023Sraj#include <sys/ptrace.h> 34185023Sraj 35185023Sraj#define arm_num_regs 26 36185023Sraj 37185023Srajstatic int arm_regmap[] = { 38185023Sraj 0, 4, 8, 12, 16, 20, 24, 28, 39185023Sraj 32, 36, 40, 44, 48, 52, 56, 60, 40185023Sraj -1, -1, -1, -1, -1, -1, -1, -1, -1, 41185023Sraj 64 42185023Sraj}; 43185023Sraj 44185023Srajstatic int 45185023Srajarm_cannot_store_register (int regno) 46185023Sraj{ 47185023Sraj return (regno >= arm_num_regs); 48185023Sraj} 49185023Sraj 50185023Srajstatic int 51185023Srajarm_cannot_fetch_register (int regno) 52185023Sraj{ 53185023Sraj return (regno >= arm_num_regs); 54185023Sraj} 55185023Sraj 56185023Srajextern int debug_threads; 57185023Sraj 58185023Srajstatic CORE_ADDR 59185023Srajarm_get_pc () 60185023Sraj{ 61185023Sraj unsigned long pc; 62185023Sraj collect_register_by_name ("pc", &pc); 63185023Sraj if (debug_threads) 64185023Sraj fprintf (stderr, "stop pc is %08lx\n", pc); 65185023Sraj return pc; 66185023Sraj} 67185023Sraj 68185023Srajstatic void 69185023Srajarm_set_pc (CORE_ADDR pc) 70185023Sraj{ 71185023Sraj unsigned long newpc = pc; 72185023Sraj supply_register_by_name ("pc", &newpc); 73185023Sraj} 74185023Sraj 75185023Sraj/* Correct in either endianness. We do not support Thumb yet. */ 76185023Srajstatic const unsigned long arm_breakpoint = 0xef9f0001; 77185023Sraj#define arm_breakpoint_len 4 78185023Sraj 79185023Srajstatic int 80185023Srajarm_breakpoint_at (CORE_ADDR where) 81185023Sraj{ 82185023Sraj unsigned long insn; 83185023Sraj 84185023Sraj (*the_target->read_memory) (where, (char *) &insn, 4); 85185023Sraj if (insn == arm_breakpoint) 86185023Sraj return 1; 87185023Sraj 88185023Sraj /* If necessary, recognize more trap instructions here. GDB only uses the 89185023Sraj one. */ 90185023Sraj return 0; 91185023Sraj} 92185023Sraj 93185023Sraj/* We only place breakpoints in empty marker functions, and thread locking 94185023Sraj is outside of the function. So rather than importing software single-step, 95185023Sraj we can just run until exit. */ 96185023Srajstatic CORE_ADDR 97185023Srajarm_reinsert_addr () 98185023Sraj{ 99185023Sraj unsigned long pc; 100185023Sraj collect_register_by_name ("lr", &pc); 101185023Sraj return pc; 102185023Sraj} 103185023Sraj 104185023Srajstatic void 105185023Srajarm_fill_gregset (void *buf) 106185023Sraj{ 107185023Sraj int i; 108185023Sraj 109185023Sraj for (i = 0; i < arm_num_regs; i++) 110185023Sraj if (arm_regmap[i] != -1) 111185023Sraj collect_register (i, ((char *) buf) + arm_regmap[i]); 112185023Sraj 113185023Sraj} 114185023Sraj 115185023Srajstatic void 116185023Srajarm_store_gregset (const void *buf) 117185023Sraj{ 118185023Sraj int i; 119185023Sraj 120185023Sraj for (i = 0; i < arm_num_regs; i++) 121185023Sraj if (arm_regmap[i] != -1) 122185023Sraj supply_register (i, ((char *) buf) + arm_regmap[i]); 123185023Sraj 124185023Sraj} 125185023Sraj 126185023Sraj 127185023Srajstruct regset_info target_regsets[] = { 128185023Sraj {PT_GETREGS, PT_SETREGS, sizeof (struct reg), 129185023Sraj GENERAL_REGS, 130185023Sraj arm_fill_gregset, arm_store_gregset }, 131185023Sraj { 0, 0, -1, -1, NULL, NULL } 132185023Sraj}; 133185023Sraj 134185023Srajstruct fbsd_target_ops the_low_target = { 135185023Sraj arm_num_regs, 136185023Sraj arm_regmap, 137185023Sraj arm_cannot_fetch_register, 138185023Sraj arm_cannot_store_register, 139185023Sraj arm_get_pc, 140185023Sraj arm_set_pc, 141185023Sraj (const char *) &arm_breakpoint, 142185023Sraj arm_breakpoint_len, 143185023Sraj arm_reinsert_addr, 144185023Sraj 0, 145185023Sraj arm_breakpoint_at, 146185023Sraj}; 147