diff options
Diffstat (limited to 'gdb/w65-tdep.c')
-rw-r--r-- | gdb/w65-tdep.c | 295 |
1 files changed, 295 insertions, 0 deletions
diff --git a/gdb/w65-tdep.c b/gdb/w65-tdep.c new file mode 100644 index 0000000..9546616 --- /dev/null +++ b/gdb/w65-tdep.c @@ -0,0 +1,295 @@ +/* Target-machine dependent code for WDC-65816, for GDB. + Copyright (C) 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* + Contributed by Steve Chamberlain + sac@cygnus.com + */ + +#include "defs.h" +#include "frame.h" +#include "obstack.h" +#include "symtab.h" +#include "gdbcmd.h" +#include "gdbtypes.h" +#include "dis-asm.h" +#include "gdbcore.h" + +/* Return the saved PC from this frame. */ + + +CORE_ADDR +w65_frame_saved_pc (frame) + struct frame_info *frame; +{ + return (read_memory_integer (frame->frame + 2, 4) & 0xffffff); +} + +CORE_ADDR +w65_addr_bits_remove (addr) + CORE_ADDR addr; +{ + return ((addr) & 0xffffff); +} + +read_memory_pointer (x) + CORE_ADDR x; +{ + return read_memory_integer (ADDR_BITS_REMOVE (x), 4); +} + +init_frame_pc () +{ + abort (); +} + +void +w65_push_dummy_frame () +{ + 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. + + 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); +} + +int +saved_pc_after_call () +{ + int sp = read_register (SP_REGNUM); + int val = read_memory_integer (sp + 1, 4); + return ADDR_BITS_REMOVE (val); +} + + +extract_return_value (type, regbuf, valbuf) + struct type *type; + char *regbuf; + char *valbuf; +{ + int b; + int len = TYPE_LENGTH (type); + + for (b = 0; b < len; b += 2) + { + int todo = len - b; + if (todo > 2) + todo = 2; + memcpy (valbuf + b, regbuf + b, todo); + } +} + +void +write_return_value (type, valbuf) + struct type *type; + char *valbuf; +{ + int reg; + int len; + for (len = 0; len < TYPE_LENGTH (type); len += 2) + { + write_register_bytes (REGISTER_BYTE (len / 2 + 2), valbuf + len, 2); + } +} + +void +store_struct_return (addr, sp) + CORE_ADDR addr; + CORE_ADDR sp; +{ + write_register (2, addr); +} + +void +w65_pop_frame () +{ +} + +init_extra_frame_info () +{ +} + +pop_frame () +{ +} + +w65_frame_chain (thisframe) + struct frame_info *thisframe; +{ + return 0xffff & read_memory_integer ((thisframe)->frame, 2); +} + +static int +gb (x) +{ + return read_memory_integer (x, 1) & 0xff; +} + +extern CORE_ADDR +w65_skip_prologue (pc) + CORE_ADDR pc; +{ + CORE_ADDR too_far = pc + 20; + + /* looking for bits of the prologue, we can expect to + see this in a frameful function: + + stack adjust: + + 3B tsc + 1A inc a + 18 clc + 69E2FF adc #0xffe2 + 3A dec a + 1B tcs + 1A inc a + + link: + + A500 lda <r15 + 48 pha + 3B tsc + 1a inc a + 8500 sta <r15 + + */ + +#define TSC 0x3b +#define TCS 0x1b +#define INCA 0x1a +#define PHA 0x48 +#define LDADIR 0xa5 +#define STADIR 0x85 + + /* Skip a stack adjust - any area between a tsc and tcs */ + if (gb (pc) == TSC) + { + while (pc < too_far && gb (pc) != TCS) + { + pc++; + } + pc++; + /* Skip a stupid inc a */ + if (gb (pc) == INCA) + pc++; + + } + /* Stack adjust can also be done with n pha's */ + while (gb (pc) == PHA) + pc++; + + /* Skip a link - that's a ld/ph/tsc/inc/sta */ + + if (gb (pc) == LDADIR + && gb (pc + 5) == STADIR + && gb (pc + 1) == gb (pc + 6) + && gb (pc + 2) == PHA + && gb (pc + 3) == TSC + && gb (pc + 4) == INCA) + { + pc += 7; + } + + return pc; +} + + +register_raw_size (n) +{ + return sim_reg_size (n); +} + + +void +print_register_hook (regno) +{ + if (regno == P_REGNUM) + { + /* CCR register */ + + int C, Z, N, V, I, D, X, M; + unsigned char b[1]; + unsigned char l; + + read_relative_register_raw_bytes (regno, b); + l = b[0]; + printf_unfiltered ("\t"); + C = (l & 0x1) != 0; + Z = (l & 0x2) != 0; + I = (l & 0x4) != 0; + D = (l & 0x8) != 0; + X = (l & 0x10) != 0; + M = (l & 0x20) != 0; + V = (l & 0x40) != 0; + N = (l & 0x80) != 0; + + printf_unfiltered ("N-%d ", N); + printf_unfiltered ("V-%d ", V); + printf_unfiltered ("M-%d ", M); + printf_unfiltered ("X-%d ", X); + printf_unfiltered ("D-%d ", D); + printf_unfiltered ("I-%d ", I); + printf_unfiltered ("Z-%d ", Z); + printf_unfiltered ("C-%d ", C); + if ((C | Z) == 0) + printf_unfiltered ("u> "); + if ((C | Z) == 1) + printf_unfiltered ("u<= "); + if ((C == 0)) + printf_unfiltered ("u>= "); + if (C == 1) + printf_unfiltered ("u< "); + if (Z == 0) + printf_unfiltered ("!= "); + if (Z == 1) + printf_unfiltered ("== "); + if ((N ^ V) == 0) + printf_unfiltered (">= "); + if ((N ^ V) == 1) + printf_unfiltered ("< "); + if ((Z | (N ^ V)) == 0) + printf_unfiltered ("> "); + if ((Z | (N ^ V)) == 1) + printf_unfiltered ("<= "); + } +} + +void +_initialize_w65_tdep () +{ + tm_print_insn = print_insn_w65; +} |