73b7973b9090ab4fb94d4da311f269134bae7f39
[binutils-gdb.git] / gdb / w65-tdep.c
1 /* Target-machine dependent code for WDC-65816, for GDB.
2 Copyright 1995, 1996, 2000, 2001 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 /*
22 Contributed by Steve Chamberlain
23 sac@cygnus.com
24 */
25
26 #include "defs.h"
27 #include "frame.h"
28 #include "obstack.h"
29 #include "symtab.h"
30 #include "gdbcmd.h"
31 #include "gdbtypes.h"
32 #include "dis-asm.h"
33 #include "gdbcore.h"
34 #include "regcache.h"
35
36 /* Return the saved PC from this frame. */
37
38
39 CORE_ADDR
40 w65_frame_saved_pc (struct frame_info *frame)
41 {
42 return (read_memory_integer (frame->frame + 2, 4) & 0xffffff);
43 }
44
45 CORE_ADDR
46 w65_addr_bits_remove (CORE_ADDR addr)
47 {
48 return ((addr) & 0xffffff);
49 }
50
51 read_memory_pointer (CORE_ADDR x)
52 {
53 return read_memory_integer (ADDR_BITS_REMOVE (x), 4);
54 }
55
56 init_frame_pc (void)
57 {
58 internal_error (__FILE__, __LINE__, "failed internal consistency check");
59 }
60
61 void
62 w65_push_dummy_frame (void)
63 {
64 internal_error (__FILE__, __LINE__, "failed internal consistency check");
65 }
66
67 /* Put here the code to store, into a struct frame_saved_regs,
68 the addresses of the saved registers of frame described by FRAME_INFO.
69 This includes special registers such as pc and fp saved in special
70 ways in the stack frame. sp is even more special:
71 the address we return for it IS the sp for the next frame.
72
73 We cache the result of doing this in the frame_cache_obstack, since
74 it is fairly expensive. */
75
76 void
77 frame_find_saved_regs (struct frame_info *fip, struct frame_saved_regs *fsrp)
78 {
79 int locals;
80 CORE_ADDR pc;
81 CORE_ADDR adr;
82 int i;
83
84 memset (fsrp, 0, sizeof *fsrp);
85 }
86
87 int
88 saved_pc_after_call (void)
89 {
90 int sp = read_register (SP_REGNUM);
91 int val = read_memory_integer (sp + 1, 4);
92 return ADDR_BITS_REMOVE (val);
93 }
94
95
96 extract_return_value (struct type *type, char *regbuf, char *valbuf)
97 {
98 int b;
99 int len = TYPE_LENGTH (type);
100
101 for (b = 0; b < len; b += 2)
102 {
103 int todo = len - b;
104 if (todo > 2)
105 todo = 2;
106 memcpy (valbuf + b, regbuf + b, todo);
107 }
108 }
109
110 void
111 write_return_value (struct type *type, char *valbuf)
112 {
113 int reg;
114 int len;
115 for (len = 0; len < TYPE_LENGTH (type); len += 2)
116 {
117 write_register_bytes (REGISTER_BYTE (len / 2 + 2), valbuf + len, 2);
118 }
119 }
120
121 void
122 store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
123 {
124 write_register (2, addr);
125 }
126
127 void
128 w65_pop_frame (void)
129 {
130 }
131
132 init_extra_frame_info (void)
133 {
134 }
135
136 pop_frame (void)
137 {
138 }
139
140 w65_frame_chain (struct frame_info *thisframe)
141 {
142 return 0xffff & read_memory_integer ((thisframe)->frame, 2);
143 }
144
145 static int
146 gb (int x)
147 {
148 return read_memory_integer (x, 1) & 0xff;
149 }
150
151 extern CORE_ADDR
152 w65_skip_prologue (CORE_ADDR pc)
153 {
154 CORE_ADDR too_far = pc + 20;
155
156 /* looking for bits of the prologue, we can expect to
157 see this in a frameful function:
158
159 stack adjust:
160
161 3B tsc
162 1A inc a
163 18 clc
164 69E2FF adc #0xffe2
165 3A dec a
166 1B tcs
167 1A inc a
168
169 link:
170
171 A500 lda <r15
172 48 pha
173 3B tsc
174 1a inc a
175 8500 sta <r15
176
177 */
178
179 #define TSC 0x3b
180 #define TCS 0x1b
181 #define INCA 0x1a
182 #define PHA 0x48
183 #define LDADIR 0xa5
184 #define STADIR 0x85
185
186 /* Skip a stack adjust - any area between a tsc and tcs */
187 if (gb (pc) == TSC)
188 {
189 while (pc < too_far && gb (pc) != TCS)
190 {
191 pc++;
192 }
193 pc++;
194 /* Skip a stupid inc a */
195 if (gb (pc) == INCA)
196 pc++;
197
198 }
199 /* Stack adjust can also be done with n pha's */
200 while (gb (pc) == PHA)
201 pc++;
202
203 /* Skip a link - that's a ld/ph/tsc/inc/sta */
204
205 if (gb (pc) == LDADIR
206 && gb (pc + 5) == STADIR
207 && gb (pc + 1) == gb (pc + 6)
208 && gb (pc + 2) == PHA
209 && gb (pc + 3) == TSC
210 && gb (pc + 4) == INCA)
211 {
212 pc += 7;
213 }
214
215 return pc;
216 }
217
218
219 register_raw_size (int n)
220 {
221 return sim_reg_size (n);
222 }
223
224
225 void
226 print_register_hook (int regno)
227 {
228 if (regno == P_REGNUM)
229 {
230 /* CCR register */
231
232 int C, Z, N, V, I, D, X, M;
233 unsigned char b[1];
234 unsigned char l;
235
236 read_relative_register_raw_bytes (regno, b);
237 l = b[0];
238 printf_unfiltered ("\t");
239 C = (l & 0x1) != 0;
240 Z = (l & 0x2) != 0;
241 I = (l & 0x4) != 0;
242 D = (l & 0x8) != 0;
243 X = (l & 0x10) != 0;
244 M = (l & 0x20) != 0;
245 V = (l & 0x40) != 0;
246 N = (l & 0x80) != 0;
247
248 printf_unfiltered ("N-%d ", N);
249 printf_unfiltered ("V-%d ", V);
250 printf_unfiltered ("M-%d ", M);
251 printf_unfiltered ("X-%d ", X);
252 printf_unfiltered ("D-%d ", D);
253 printf_unfiltered ("I-%d ", I);
254 printf_unfiltered ("Z-%d ", Z);
255 printf_unfiltered ("C-%d ", C);
256 if ((C | Z) == 0)
257 printf_unfiltered ("u> ");
258 if ((C | Z) == 1)
259 printf_unfiltered ("u<= ");
260 if ((C == 0))
261 printf_unfiltered ("u>= ");
262 if (C == 1)
263 printf_unfiltered ("u< ");
264 if (Z == 0)
265 printf_unfiltered ("!= ");
266 if (Z == 1)
267 printf_unfiltered ("== ");
268 if ((N ^ V) == 0)
269 printf_unfiltered (">= ");
270 if ((N ^ V) == 1)
271 printf_unfiltered ("< ");
272 if ((Z | (N ^ V)) == 0)
273 printf_unfiltered ("> ");
274 if ((Z | (N ^ V)) == 1)
275 printf_unfiltered ("<= ");
276 }
277 }
278
279 void
280 _initialize_w65_tdep (void)
281 {
282 tm_print_insn = print_insn_w65;
283 }