]>
Commit | Line | Data |
---|---|---|
c2d751d5 JK |
1 | /* Low level interface to ns532 running mach 3.0. |
2 | Copyright (C) 1992 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. */ |
c2d751d5 JK |
19 | |
20 | #include "defs.h" | |
21 | #include "inferior.h" | |
22 | ||
23 | #include <stdio.h> | |
24 | ||
25 | #include <mach.h> | |
26 | #include <mach/message.h> | |
27 | #include <mach/exception.h> | |
28 | #include <mach_error.h> | |
29 | ||
30 | #define private static | |
31 | ||
32 | \f | |
33 | /* Find offsets to thread states at compile time. | |
34 | * If your compiler does not grok this, calculate offsets | |
35 | * offsets yourself and use them (or get a compatible compiler :-) | |
36 | */ | |
37 | ||
38 | #define REG_N_OFFSET(reg) (int)(&((struct ns532_combined_state *)0)->ts.reg) | |
39 | #define REG_F_OFFSET(reg) (int)(&((struct ns532_combined_state *)0)->fs.reg) | |
40 | ||
41 | /* at reg_offset[i] is the offset to the ns532_combined_state | |
42 | * location where the gdb registers[i] is stored. | |
43 | */ | |
44 | ||
45 | static int reg_offset[] = | |
46 | { | |
47 | REG_N_OFFSET(r0), REG_N_OFFSET(r1), REG_N_OFFSET(r2), REG_N_OFFSET(r3), | |
48 | REG_N_OFFSET(r4), REG_N_OFFSET(r5), REG_N_OFFSET(r6), REG_N_OFFSET(r7), | |
49 | REG_F_OFFSET(l0a), REG_F_OFFSET(l1a),REG_F_OFFSET(l2a),REG_F_OFFSET(l3a), | |
50 | REG_F_OFFSET(l4a), REG_F_OFFSET(l5a),REG_F_OFFSET(l6a),REG_F_OFFSET(l7a), | |
51 | REG_N_OFFSET(sp), REG_N_OFFSET(fp), REG_N_OFFSET(pc), REG_N_OFFSET(psr), | |
52 | REG_F_OFFSET(fsr), | |
53 | REG_F_OFFSET(l0a), REG_F_OFFSET(l2a),REG_F_OFFSET(l4a),REG_F_OFFSET(l6a) | |
54 | /* @@@ 532 has more double length floating point regs, not accessed currently */ | |
55 | }; | |
56 | ||
57 | /* Fetch COUNT contiguous registers from thread STATE starting from REGNUM | |
58 | * Caller knows that the regs handled in one transaction are of same size. | |
59 | */ | |
60 | #define FETCH_REGS(state, regnum, count) \ | |
a6e0dae9 JK |
61 | memcpy (®isters[REGISTER_BYTE (regnum)], \ |
62 | (char *)state+reg_offset[ regnum ], \ | |
f4f0d174 | 63 | count*REGISTER_SIZE) |
c2d751d5 JK |
64 | |
65 | /* Store COUNT contiguous registers to thread STATE starting from REGNUM */ | |
66 | #define STORE_REGS(state, regnum, count) \ | |
a6e0dae9 JK |
67 | memcpy ((char *)state+reg_offset[ regnum ], \ |
68 | ®isters[REGISTER_BYTE (regnum)], \ | |
f4f0d174 | 69 | count*REGISTER_SIZE) |
c2d751d5 | 70 | \f |
c2d751d5 JK |
71 | /* |
72 | * Fetch inferiors registers for gdb. | |
73 | * REGNO specifies which (as gdb views it) register, -1 for all. | |
74 | */ | |
75 | ||
76 | void | |
77 | fetch_inferior_registers (regno) | |
78 | int regno; | |
79 | { | |
80 | kern_return_t ret; | |
81 | thread_state_data_t state; | |
82 | unsigned int stateCnt = NS532_COMBINED_STATE_COUNT; | |
83 | int index; | |
84 | ||
85 | if (! MACH_PORT_VALID (current_thread)) | |
86 | error ("fetch inferior registers: Invalid thread"); | |
87 | ||
88 | if (must_suspend_thread) | |
89 | setup_thread (current_thread, 1); | |
90 | ||
91 | ret = thread_get_state (current_thread, | |
92 | NS532_COMBINED_STATE, | |
93 | state, | |
94 | &stateCnt); | |
95 | ||
96 | if (ret != KERN_SUCCESS) | |
97 | message ("fetch_inferior_registers: %s ", | |
98 | mach_error_string (ret)); | |
99 | #if 0 | |
100 | /* It may be more effective to store validate all of them, | |
101 | * since we fetched them all anyway | |
102 | */ | |
103 | else if (regno != -1) | |
104 | supply_register (regno, (char *)state+reg_offset[regno]); | |
105 | #endif | |
106 | else | |
107 | { | |
108 | for (index = 0; index < NUM_REGS; index++) | |
109 | supply_register (index, (char *)state+reg_offset[index]); | |
110 | } | |
111 | ||
112 | if (must_suspend_thread) | |
113 | setup_thread (current_thread, 0); | |
114 | } | |
115 | \f | |
116 | /* Store our register values back into the inferior. | |
117 | * If REGNO is -1, do this for all registers. | |
118 | * Otherwise, REGNO specifies which register | |
119 | * | |
120 | * On mach3 all registers are always saved in one call. | |
121 | */ | |
122 | void | |
123 | store_inferior_registers (regno) | |
124 | int regno; | |
125 | { | |
126 | kern_return_t ret; | |
127 | thread_state_data_t state; | |
128 | unsigned int stateCnt = NS532_COMBINED_STATE_COUNT; | |
129 | register int index; | |
130 | ||
131 | if (! MACH_PORT_VALID (current_thread)) | |
132 | error ("store inferior registers: Invalid thread"); | |
133 | ||
134 | if (must_suspend_thread) | |
135 | setup_thread (current_thread, 1); | |
136 | ||
137 | /* Fetch the state of the current thread */ | |
138 | ret = thread_get_state (current_thread, | |
139 | NS532_COMBINED_STATE, | |
140 | state, | |
141 | &stateCnt); | |
142 | ||
143 | if (ret != KERN_SUCCESS) | |
144 | { | |
145 | message ("store_inferior_registers (get): %s", | |
146 | mach_error_string (ret)); | |
147 | if (must_suspend_thread) | |
148 | setup_thread (current_thread, 0); | |
149 | return; | |
150 | } | |
151 | ||
152 | /* move gdb's registers to thread's state | |
153 | * | |
154 | * Since we save all registers anyway, save the ones | |
155 | * that gdb thinks are valid (e.g. ignore the regno | |
156 | * parameter) | |
157 | */ | |
158 | #if 0 | |
159 | if (regno != -1) | |
160 | STORE_REGS (state, regno, 1); | |
161 | else | |
162 | #endif | |
163 | { | |
164 | for (index = 0; index < NUM_REGS; index++) | |
165 | STORE_REGS (state, index, 1); | |
166 | } | |
167 | ||
168 | /* Write gdb's current view of register to the thread | |
169 | */ | |
170 | ret = thread_set_state (current_thread, | |
171 | NS532_COMBINED_STATE, | |
172 | state, | |
173 | NS532_COMBINED_STATE_COUNT); | |
174 | ||
175 | if (ret != KERN_SUCCESS) | |
176 | message ("store_inferior_registers (set): %s", | |
177 | mach_error_string (ret)); | |
178 | ||
179 | if (must_suspend_thread) | |
180 | setup_thread (current_thread, 0); | |
181 | } |