summaryrefslogtreecommitdiff
path: root/gdb/w65-tdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/w65-tdep.c')
-rw-r--r--gdb/w65-tdep.c295
1 files changed, 295 insertions, 0 deletions
diff --git a/gdb/w65-tdep.c b/gdb/w65-tdep.c
new file mode 100644
index 00000000000..9546616af4e
--- /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;
+}