From: Steve Chamberlain Date: Mon, 1 Feb 1993 22:53:24 +0000 (+0000) Subject: * remote-z8k.c, z8k-tdep.c: support for the Z8001 and Z8002. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a332e593227213eedcf63a6a4bc56e1cc85884be;p=binutils-gdb.git * remote-z8k.c, z8k-tdep.c: support for the Z8001 and Z8002. * parse.c (std_regs): Only declare if NO_STD_REGS is defined. --- diff --git a/gdb/parse.c b/gdb/parse.c index 1327d601c1f..9d9697593c6 100644 --- a/gdb/parse.c +++ b/gdb/parse.c @@ -50,7 +50,12 @@ prefixify_subexp PARAMS ((struct expression *, struct expression *, int, int)); /* Assign machine-independent names to certain registers (unless overridden by the REGISTER_NAMES table) */ +#ifdef NO_STD_REGS +unsigned num_std_regs = 0; +struct std_regs std_regs[1]; +#else struct std_regs std_regs[] = { + #ifdef PC_REGNUM { "pc", PC_REGNUM }, #endif @@ -63,10 +68,13 @@ struct std_regs std_regs[] = { #ifdef PS_REGNUM { "ps", PS_REGNUM }, #endif + }; unsigned num_std_regs = (sizeof std_regs / sizeof std_regs[0]); +#endif + /* Begin counting arguments for a function call, saving the data about any containing call. */ diff --git a/gdb/remote-z8k.c b/gdb/remote-z8k.c new file mode 100644 index 00000000000..48d6a71a683 --- /dev/null +++ b/gdb/remote-z8k.c @@ -0,0 +1,445 @@ +/* Remote debugging interface for Zilog Z8000 simulator + Copyright 1992 Free Software Foundation, Inc. + Contributed by Cygnus Support. Written by Steve Chamberlain + (sac@cygnus.com). + +This file is part of GDB. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "defs.h" +#include "inferior.h" +#include "wait.h" +#include "value.h" +#include +#include +#include +#include +#include +#include +#include "terminal.h" +#include "target.h" +#include "gdbcore.h" +#include "../z8ksim/sim.h" + +/* External data declarations */ +extern int stop_soon_quietly; /* for wait_for_inferior */ + +/* Forward data declarations */ +extern struct target_ops sim_ops; /* Forward declaration */ + +/* Forward function declarations */ +static void sim_fetch_registers (); +static void sim_close (); + +void sim_store_register(); + +void sim_set_oc(); + + +int +sim_write_inferior_memory (memaddr, myaddr, len) + CORE_ADDR memaddr; + unsigned char *myaddr; + int len; +{ +return sim_write(memaddr, myaddr, len); +} + +static int +store_register(regno) +int regno; +{ + if (regno == -1) + { + for (regno = 0; regno < 16; regno++) + store_register(regno); + } + else + { + sim_store_register(regno,read_register(regno)); + } + return 0; +} + + + +void +sim_kill(arg,from_tty) +char *arg; +int from_tty; +{ + +} + + + +/* + * Download a file specified in 'args', to the sim. + */ +static void +sim_load(args,fromtty) +char *args; +int fromtty; +{ + bfd *abfd; + asection *s; + + inferior_pid = 0; + abfd = bfd_openr(args,"coff-z8k"); + + if (!abfd) + { + printf_filtered("Unable to open file %s\n", args); + return; + } + + if (bfd_check_format(abfd, bfd_object) ==0) + { + printf_filtered("File is not an object file\n"); + return ; + } + + s = abfd->sections; + while (s != (asection *)NULL) + { + if (s->flags & SEC_LOAD) + { + int i; + int delta = 4096; + char *buffer = xmalloc(delta); + printf_filtered("%s\t: 0x%4x .. 0x%4x ", + s->name, s->vma, s->vma + s->_raw_size); + for (i = 0; i < s->_raw_size; i+= delta) + { + int sub_delta = delta; + if (sub_delta > s->_raw_size - i) + sub_delta = s->_raw_size - i ; + + bfd_get_section_contents(abfd, s, buffer, i, sub_delta); + sim_write_inferior_memory(s->vma + i, buffer, sub_delta); + printf_filtered("*"); + fflush(stdout); + } + printf_filtered( "\n"); + free(buffer); + } + s = s->next; + } + + sim_set_pc(abfd->start_address); +} + +/* This is called not only when we first attach, but also when the + user types "run" after having attached. */ +void +sim_create_inferior (execfile, args, env) + char *execfile; + char *args; + char **env; +{ + int entry_pt; + char buffer[100]; + + if (args && *args) + error ("Can't pass arguments to remote sim process."); + + if (execfile == 0 || exec_bfd == 0) + error ("No exec file specified"); + + entry_pt = (int) bfd_get_start_address (exec_bfd); + + + + sim_kill(NULL,NULL); + sim_clear_breakpoints(); + init_wait_for_inferior (); + + + + insert_breakpoints (); /* Needed to get correct instruction in cache */ + proceed(entry_pt, -1, 0); +} + + + +static void +sim_open (name, from_tty) + char *name; + int from_tty; +{ + if(name == 0) + { + name = ""; + } + + /* Clear any break points */ + sim_clear_breakpoints(); + + push_target (&sim_ops); + target_fetch_registers(-1); + + printf_filtered("Connected to the Z8000 Simulator.\n"); +} + +/* Close out all files and local state before this target loses control. */ + +static void +sim_close (quitting) + int quitting; +{ + + + /* Clear any break points */ + sim_clear_breakpoints(); + + /* Put this port back into REMOTE mode */ + sleep(1); /* Let any output make it all the way back */ +} + +/* Terminate the open connection to the remote debugger. + Use this when you want to detach and do something else + with your gdb. */ +int +sim_detach (args,from_tty) + char *args; + int from_tty; +{ + sim_clear_breakpoints(); + + pop_target(); /* calls sim_close to do the real work */ + if (from_tty) + printf_filtered ("Ending remote %s debugging\n", target_shortname); + return 0; +} + +/* Tell the remote machine to resume. */ + + +/* Wait until the remote machine stops, then return, + storing status in STATUS just as `wait' would. */ + +int +sim_wait (status) + WAITTYPE *status; +{ + +*status = sim_stop_signal(); +return 0; +} + +/* Return the name of register number REGNO + in the form input and output by sim. + + Returns a pointer to a static buffer containing the answer. */ +static char * +get_reg_name (regno) + int regno; +{ + static char *rn[NUM_REGS]= REGISTER_NAMES; + return rn[regno]; +} + + + + + +/* Get ready to modify the registers array. On machines which store + individual registers, this doesn't need to do anything. On machines + which store all the registers in one fell swoop, this makes sure + that registers contains all the registers from the program being + debugged. */ + +void +sim_prepare_to_store () +{ + /* Do nothing, since we can store individual regs */ +} + +static CORE_ADDR +translate_addr(addr) +CORE_ADDR addr; +{ + + return(addr); + +} + +/* Read a word from remote address ADDR and return it. + * This goes through the data cache. + */ +int +sim_fetch_word (addr) + CORE_ADDR addr; +{ +/* return dcache_fetch (addr);*/ +} + + +static void +fetch_register(regno) +int regno; +{ + if (regno == -1) + { + for (regno = 0; regno < 16; regno++) + fetch_register(regno); + } + else { + char buf[MAX_REGISTER_RAW_SIZE]; + sim_fetch_register(regno, buf); + supply_register(regno, buf); + } +} + +/* Write a word WORD into remote address ADDR. + This goes through the data cache. */ + +void +sim_store_word (addr, word) + CORE_ADDR addr; + int word; +{ +/* dcache_poke (addr, word);*/ +} + +int +sim_xfer_inferior_memory(memaddr, myaddr, len, write, target) + CORE_ADDR memaddr; + char *myaddr; + int len; + int write; + struct target_ops *target; /* ignored */ +{ + if (write) + { + sim_write(memaddr, myaddr, len); + + } + else + { + sim_read(memaddr, myaddr, len); + } + return len; +} + +void +sim_files_info () +{ +char *file = "nothing"; +if (exec_bfd) + file = bfd_get_filename(exec_bfd); + +if (exec_bfd) +#ifdef __GO32__ + printf_filtered("\tAttached to DOS asynctsr and running program %s\n",file); +#else + printf_filtered("\tAttached to %s at %d baud and running program %s\n",file); +#endif + printf_filtered("\ton an H8/300 processor.\n"); +} + +/* This routine is run as a hook, just before the main command loop is + entered. If gdb is configured for the H8, but has not had its + target specified yet, this will loop prompting the user to do so. +*/ + +void +sim_before_main_loop () +{ + char ttyname[100]; + char *p, *p2; + extern FILE *instream; + extern jmp_buf to_top_level; + + push_target (&sim_ops); +} + + +#define MAX_BREAKS 16 +static int num_brkpts=0; +static int +sim_insert_breakpoint(addr, save) +CORE_ADDR addr; +char *save; /* Throw away, let sim save instructions */ +{ + abort(); +} +static int +sim_remove_breakpoint(addr, save) +CORE_ADDR addr; +char *save; /* Throw away, let sim save instructions */ +{ + abort(); +} + +/* Clear the sims notion of what the break points are */ +static int +sim_mourn() +{ + sim_clear_breakpoints(); + generic_mourn_inferior (); + return 0; +} + +static int rem_resume(a,b) +{ + sim_resume(a,b); + return 0; +} + +/* Define the target subroutine names */ + +struct target_ops sim_ops = +{ + "sim", "Remote SIM monitor", + "Use the Z8000 simulator", + sim_open, sim_close, + 0, sim_detach, rem_resume, sim_wait, /* attach */ + fetch_register, store_register, + sim_prepare_to_store, + sim_xfer_inferior_memory, + sim_files_info, + 0, 0, /* Breakpoints */ + 0, 0, 0, 0, 0, /* Terminal handling */ + sim_kill, /* FIXME, kill */ + sim_load, + 0, /* lookup_symbol */ + sim_create_inferior, /* create_inferior */ + sim_mourn, /* mourn_inferior FIXME */ + 0, /* can_run */ + 0, /* notice_signals */ + process_stratum, 0, /* next */ + 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */ + 0,0, /* Section pointers */ + OPS_MAGIC, /* Always the last thing */ +}; + + + + + + +/***********************************************************************/ + +void +_initialize_remote_sim () +{ + extern int sim_z8001_mode; + sim_z8001_mode = z8001_mode; + add_target (&sim_ops); +} + + diff --git a/gdb/z8k-tdep.c b/gdb/z8k-tdep.c new file mode 100644 index 00000000000..852c0f0da44 --- /dev/null +++ b/gdb/z8k-tdep.c @@ -0,0 +1,378 @@ +/* Target-machine dependent code for Zilog Z8000, for GDB. + Copyright (C) 1992 Free Software Foundation, Inc. + +This file is part of GDB. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* + Contributed by Steve Chamberlain + sac@cygnus.com + */ + + +#include "defs.h" +#include "frame.h" +#include "obstack.h" +#include "symtab.h" +#include "gdbtypes.h" + + +/* Return the saved PC from this frame. + + If the frame has a memory copy of SRP_REGNUM, use that. If not, + just use the register SRP_REGNUM itself. */ + +CORE_ADDR +frame_saved_pc (frame) +FRAME frame; +{ + return ( read_memory_pointer(frame->frame+(BIG ? 4 : 2))); +} + +#define IS_PUSHL(x) (BIG ? ((x & 0xfff0) == 0x91e0):((x & 0xfff0) == 0x91F0)) +#define IS_PUSHW(x) (BIG ? ((x & 0xfff0) == 0x93e0):((x & 0xfff0)==0x93f0)) +#define IS_MOVE_FP(x) (BIG ? x == 0xa1ea : x == 0xa1fa) +#define IS_MOV_SP_FP(x) (BIG ? x == 0x94ea : x == 0x0d76) +#define IS_SUB2_SP(x) (x==0x1b87) +#define IS_MOVK_R5(x) (x==0x7905) +#define IS_SUB_SP(x) ((x & 0xffff) == 0x020f) +#define IS_PUSH_FP(x) (BIG ? (x == 0x93ea) : (x == 0x93fa)) + + +/* work out how much local space is on the stack and + return the pc pointing to the first push */ + +static +CORE_ADDR +skip_adjust(pc, size) +CORE_ADDR pc; +int *size; +{ + *size = 0; + + if (IS_PUSH_FP(read_memory_short(pc)) + && IS_MOV_SP_FP(read_memory_short(pc+2))) + { + /* This is a function with an explict frame pointer */ + pc += 4; + *size += 2; /* remember the frame pointer */ + } + + /* remember any stack adjustment */ + if (IS_SUB_SP(read_memory_short(pc))) + { + *size += read_memory_short(pc+2); + pc += 4; + } + return pc; +} + + +int +examine_frame(pc, regs, sp) +CORE_ADDR pc; +struct frame_saved_regs *regs; +CORE_ADDR sp; +{ + int w = read_memory_short(pc); + int offset = 0; + int regno; + + + + for (regno = 0; regno < NUM_REGS; regno++) + regs->regs[regno] = 0; + + while (IS_PUSHW(w) || IS_PUSHL(w)) + { + /* work out which register is being pushed to where */ + if (IS_PUSHL(w)) + { + regs->regs[w & 0xf] = offset; + regs->regs[(w & 0xf) + 1] = offset +2; + offset += 4; + } + else { + regs->regs[w & 0xf] = offset; + offset += 2; + } + pc += 2; + w = read_memory_short(pc); + } + + if (IS_MOVE_FP(w)) + { + /* We know the fp */ + + } + else if (IS_SUB_SP(w)) + { + /* Subtracting a value from the sp, so were in a function + which needs stack space for locals, but has no fp. We fake up + the values as if we had an fp */ + regs->regs[FP_REGNUM] = sp; + } + else + { + /* This one didn't have an fp, we'll fake it up */ + regs->regs[SP_REGNUM] = sp; + } + /* stack pointer contains address of next frame */ +/* regs->regs[fp_regnum()] = fp;*/ + regs->regs[SP_REGNUM] = sp; + return pc; +} + +CORE_ADDR z8k_skip_prologue(start_pc) +CORE_ADDR start_pc; +{ + struct frame_saved_regs dummy; + return examine_frame(start_pc, &dummy, 0); +} + +CORE_ADDR addr_bits_remove(x) +CORE_ADDR x; +{ + return x & PTR_MASK; +} + +read_memory_pointer(x) +CORE_ADDR x; +{ + +return read_memory_integer(ADDR_BITS_REMOVE(x), BIG ? 4 : 2); +} + +FRAME_ADDR +frame_chain (thisframe) + FRAME thisframe; +{ + if (thisframe->prev == 0) + { + /* This is the top of the stack, let's get the sp for real */ + } + if (!inside_entry_file ((thisframe)->pc)) + { +return read_memory_pointer ((thisframe)->frame); + } + + return 0; +} + +init_frame_pc() { abort(); } + +/* Put here the code to store, into a struct frame_saved_regs, + the addresses of the saved registers of frame described by FRAME_INFO. + This includes special registers such as pc and fp saved in special + ways in the stack frame. sp is even more special: + the address we return for it IS the sp for the next frame. */ + +void get_frame_saved_regs(frame_info, frame_saved_regs) + struct frame_info *frame_info; + struct frame_saved_regs *frame_saved_regs; + +{ +CORE_ADDR pc; +int w; +bzero(frame_saved_regs, sizeof(*frame_saved_regs)); +pc = get_pc_function_start(frame_info->pc); + +/* wander down the instruction stream */ +examine_frame(pc, frame_saved_regs, frame_info->frame); + +} + + +extract_return_value(valtype, regbuf, valbuf) +struct type *valtype; +char regbuf[REGISTER_BYTES]; +char *valbuf; +{ + bcopy(regbuf + REGISTER_BYTE(2), valbuf, TYPE_LENGTH(valtype)); +} +void z8k_push_dummy_frame() { abort(); } + +int print_insn(memaddr, stream) +CORE_ADDR memaddr; +FILE *stream; +{ + char temp[20]; + read_memory (memaddr, temp, 20); + if (BIG) { + return print_insn_z8001(memaddr, temp, stream); + } + else { + return print_insn_z8002(memaddr, temp, stream); + } +} + +void +store_return_value() +{ +abort(); +} +void +store_struct_return() { abort(); } + + + +/* Fetch the instruction at ADDR, returning 0 if ADDR is beyond LIM or + is not the address of a valid instruction, the address of the next + instruction beyond ADDR otherwise. *PWORD1 receives the first word + of the instruction.*/ + + +CORE_ADDR +NEXT_PROLOGUE_INSN(addr, lim, pword1) +CORE_ADDR addr; +CORE_ADDR lim; +short *pword1; +{ + if (addr < lim+8) + { + read_memory (addr, pword1, sizeof(*pword1)); + SWAP_TARGET_AND_HOST (pword1, sizeof (short)); + return addr + 2; + } + + return 0; + +} + + +/* Put here the code to store, into a struct frame_saved_regs, + the addresses of the saved registers of frame described by FRAME_INFO. + This includes special registers such as pc and fp saved in special + ways in the stack frame. sp is even more special: + the address we return for it IS the sp for the next frame. + + We cache the result of doing this in the frame_cache_obstack, since + it is fairly expensive. */ + +void +frame_find_saved_regs (fip, fsrp) + struct frame_info *fip; + struct frame_saved_regs *fsrp; +{ + int locals; + CORE_ADDR pc; + CORE_ADDR adr; + int i; + + memset (fsrp, 0, sizeof *fsrp); + + pc = skip_adjust(get_pc_function_start (fip->pc), &locals); + + { + adr = fip->frame - locals; + for (i = 0; i < 8; i++) + { + int word = read_memory_short(pc); + pc += 2 ; + if (IS_PUSHL(word)) { + fsrp->regs[word & 0xf] = adr; + fsrp->regs[(word & 0xf) + 1] = adr - 2; + adr -= 4; + } + else if (IS_PUSHW(word)) { + fsrp->regs[word & 0xf] = adr; + adr -= 2; + } + else + break; + } + + } + + fsrp->regs[PC_REGNUM] = fip->frame + 4; + fsrp->regs[FP_REGNUM] = fip->frame; + +} + +void +addr_bits_set() { abort(); } + +int +saved_pc_after_call() +{ + return addr_bits_remove(read_memory_integer(read_register(SP_REGNUM), PTR_SIZE)); +} + +void +print_register_hook(regno) +int regno; +{ + + if ((regno & 1)==0 && regno < 16) + { + unsigned short l[2]; + read_relative_register_raw_bytes(regno, (char *)(l+0)); + read_relative_register_raw_bytes(regno+1, (char *)(l+1)); + printf("\t"); + printf("%04x%04x", l[0],l[1]); + } + + if ((regno & 3)== 0 && regno < 16) + { + unsigned short l[4]; + read_relative_register_raw_bytes(regno, l+0); + read_relative_register_raw_bytes(regno+1, l+1); + read_relative_register_raw_bytes(regno+2, l+2); + read_relative_register_raw_bytes(regno+3, l+3); + + printf("\t"); + printf("%04x%04x%04x%04x", l[0],l[1],l[2],l[3]); + } + if (regno == 15) + { + unsigned short rval; + int i; + read_relative_register_raw_bytes(regno, (char *)(&rval)); + + printf("\n"); + for (i = 0; i < 10; i+=2) { + printf("(sp+%d=%04x)",i, read_memory_short(rval+i)); + } + } + +} + + +void +register_convert_to_virtual(regnum, from, to) +unsigned char *from; +unsigned char *to; +{ + to[0] = from[0]; + to[1] = from[1]; + to[2] = from[2]; + to[3] = from[3]; +} + +void +register_convert_to_raw(regnum, to, from) +char *to; +char *from; +{ + to[0] = from[0]; + to[1] = from[1]; + to[2] = from[2]; + to[3] = from[3]; +} + + + +void z8k_pop_frame() { }