Commit | Line | Data |
---|---|---|
c906108c | 1 | /* Target-machine dependent code for WDC-65816, for GDB. |
b6ba6518 | 2 | Copyright 1995, 1996, 2000, 2001 Free Software Foundation, Inc. |
c906108c SS |
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 | |
c5aa993b JM |
18 | Foundation, Inc., 59 Temple Place - Suite 330, |
19 | Boston, MA 02111-1307, USA. */ | |
c906108c SS |
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" | |
4e052eda | 34 | #include "regcache.h" |
c906108c SS |
35 | |
36 | /* Return the saved PC from this frame. */ | |
37 | ||
38 | ||
39 | CORE_ADDR | |
fba45db2 | 40 | w65_frame_saved_pc (struct frame_info *frame) |
c906108c SS |
41 | { |
42 | return (read_memory_integer (frame->frame + 2, 4) & 0xffffff); | |
43 | } | |
44 | ||
45 | CORE_ADDR | |
fba45db2 | 46 | w65_addr_bits_remove (CORE_ADDR addr) |
c906108c SS |
47 | { |
48 | return ((addr) & 0xffffff); | |
49 | } | |
50 | ||
fba45db2 | 51 | read_memory_pointer (CORE_ADDR x) |
c906108c SS |
52 | { |
53 | return read_memory_integer (ADDR_BITS_REMOVE (x), 4); | |
54 | } | |
55 | ||
fba45db2 | 56 | init_frame_pc (void) |
c906108c | 57 | { |
e1e9e218 | 58 | internal_error (__FILE__, __LINE__, "failed internal consistency check"); |
c906108c SS |
59 | } |
60 | ||
61 | void | |
fba45db2 | 62 | w65_push_dummy_frame (void) |
c906108c | 63 | { |
e1e9e218 | 64 | internal_error (__FILE__, __LINE__, "failed internal consistency check"); |
c906108c SS |
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 | |
fba45db2 | 77 | frame_find_saved_regs (struct frame_info *fip, struct frame_saved_regs *fsrp) |
c906108c SS |
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 | |
fba45db2 | 88 | saved_pc_after_call (void) |
c906108c SS |
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 | ||
fba45db2 | 96 | extract_return_value (struct type *type, char *regbuf, char *valbuf) |
c906108c SS |
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 | |
fba45db2 | 111 | write_return_value (struct type *type, char *valbuf) |
c906108c SS |
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 | |
fba45db2 | 122 | store_struct_return (CORE_ADDR addr, CORE_ADDR sp) |
c906108c SS |
123 | { |
124 | write_register (2, addr); | |
125 | } | |
126 | ||
127 | void | |
fba45db2 | 128 | w65_pop_frame (void) |
c906108c SS |
129 | { |
130 | } | |
131 | ||
fba45db2 | 132 | init_extra_frame_info (void) |
c906108c SS |
133 | { |
134 | } | |
135 | ||
fba45db2 | 136 | pop_frame (void) |
c906108c SS |
137 | { |
138 | } | |
139 | ||
fba45db2 | 140 | w65_frame_chain (struct frame_info *thisframe) |
c906108c SS |
141 | { |
142 | return 0xffff & read_memory_integer ((thisframe)->frame, 2); | |
143 | } | |
144 | ||
145 | static int | |
fba45db2 | 146 | gb (int x) |
c906108c SS |
147 | { |
148 | return read_memory_integer (x, 1) & 0xff; | |
149 | } | |
150 | ||
c5aa993b | 151 | extern CORE_ADDR |
fba45db2 | 152 | w65_skip_prologue (CORE_ADDR pc) |
c906108c SS |
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 | ||
fba45db2 | 219 | register_raw_size (int n) |
c906108c SS |
220 | { |
221 | return sim_reg_size (n); | |
222 | } | |
223 | ||
224 | ||
225 | void | |
fba45db2 | 226 | print_register_hook (int regno) |
c906108c SS |
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 | |
fba45db2 | 280 | _initialize_w65_tdep (void) |
c906108c SS |
281 | { |
282 | tm_print_insn = print_insn_w65; | |
283 | } |