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