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