/[cmucl]/src/lisp/mips-arch.c
ViewVC logotype

Contents of /src/lisp/mips-arch.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.12 - (show annotations)
Wed Mar 19 09:17:13 2008 UTC (6 years, 1 month ago) by cshapiro
Branch: MAIN
CVS Tags: sparc-tramp-assem-base, post-merge-intl-branch, merged-unicode-utf16-extfmt-2009-06-11, unicode-utf16-extfmt-2009-03-27, snapshot-2008-08, snapshot-2008-09, sse2-packed-2008-11-12, snapshot-2008-05, snapshot-2008-06, snapshot-2008-07, intl-branch-working-2010-02-19-1000, unicode-string-buffer-impl-base, sse2-base, release-20b-pre1, release-20b-pre2, unicode-string-buffer-base, sse2-packed-base, sparc-tramp-assem-2010-07-19, amd64-dd-start, release-19f-pre1, snapshot-2008-12, snapshot-2008-11, intl-2-branch-base, GIT-CONVERSION, unicode-utf16-sync-2008-12, cross-sol-x86-merged, label-2009-03-16, release-19f-base, merge-sse2-packed, merge-with-19f, intl-branch-working-2010-02-11-1000, unicode-snapshot-2009-05, unicode-snapshot-2009-06, unicode-utf16-sync-2008-07, unicode-utf16-sync-2008-09, unicode-utf16-extfmts-sync-2008-12, RELEASE_20b, snapshot-2008-04, unicode-utf16-sync-label-2009-03-16, RELEASE_19f, release-20a-base, cross-sol-x86-base, unicode-utf16-char-support-2009-03-26, unicode-utf16-char-support-2009-03-25, unicode-utf16-extfmts-pre-sync-2008-11, snapshot-2008-10, snapshot-2010-12, snapshot-2010-11, unicode-utf16-sync-2008-11, snapshot-2011-09, snapshot-2011-06, snapshot-2011-07, snapshot-2011-04, snapshot-2011-02, snapshot-2011-03, snapshot-2011-01, pre-merge-intl-branch, snapshot-2010-05, snapshot-2010-04, snapshot-2010-07, snapshot-2010-06, snapshot-2010-01, snapshot-2010-03, snapshot-2010-02, snapshot-2010-08, label-2009-03-25, cross-sol-x86-2010-12-20, sse2-checkpoint-2008-10-01, intl-branch-2010-03-18-1300, sse2-merge-with-2008-11, sse2-merge-with-2008-10, RELEASE_20a, release-20a-pre1, snapshot-2009-11, snapshot-2009-12, unicode-utf16-extfmt-2009-06-11, portable-clx-import-2009-06-16, unicode-utf16-string-support, cross-sparc-branch-base, intl-branch-base, unicode-utf16-base, portable-clx-base, snapshot-2009-08, snapshot-2009-02, snapshot-2009-01, snapshot-2009-07, snapshot-2009-05, snapshot-2009-04, HEAD
Branch point for: RELEASE-19F-BRANCH, portable-clx-branch, cross-sparc-branch, RELEASE-20B-BRANCH, unicode-string-buffer-branch, sparc-tramp-assem-branch, sse2-packed-branch, RELEASE-20A-BRANCH, amd64-dd-branch, unicode-string-buffer-impl-branch, intl-branch, unicode-utf16-branch, cross-sol-x86-branch, sse2-branch, intl-2-branch, unicode-utf16-extfmt-branch
Changes since 1.11: +2 -2 lines
File MIME type: text/plain
Always use prototype style function definitions.  Consistently use the
void keyword to specify empty parameter lists.
1 /*
2
3 $Header: /tiger/var/lib/cvsroots/cmucl/src/lisp/mips-arch.c,v 1.12 2008/03/19 09:17:13 cshapiro Rel $
4
5 This code was written as part of the CMU Common Lisp project at
6 Carnegie Mellon University, and has been placed in the public domain.
7
8 */
9
10 #include <stdio.h>
11
12 #ifdef mach
13 #include <mips/cpu.h>
14 #else
15 #ifdef irix
16 #include <sys/sbd.h>
17 #endif
18 #endif
19
20 #include "lisp.h"
21 #include "globals.h"
22 #include "validate.h"
23 #include "os.h"
24 #include "internals.h"
25 #include "arch.h"
26 #include "lispregs.h"
27 #include "signal.h"
28 #include "alloc.h"
29 #include "interrupt.h"
30 #include "interr.h"
31 #include "breakpoint.h"
32
33 char *
34 arch_init(void)
35 {
36 return NULL;
37 }
38
39 os_vm_address_t
40 arch_get_bad_addr(int sig, int code, struct sigcontext * scp)
41 {
42 /* Finding the bad address on the mips is easy. */
43 return (os_vm_address_t) scp->sc_badvaddr;
44 }
45
46 #ifdef irix
47 void
48 emulate_branch(struct sigcontext *scp, unsigned long inst)
49 {
50 long opcode = inst >> 26;
51 long r1 = (inst >> 21) & 0x1f;
52 long r2 = (inst >> 16) & 0x1f;
53 long bdisp = (inst & (1 << 15)) ? inst | (-1 << 16) : inst & 0xffff;
54 long jdisp = (inst & (1 << 25)) ? inst | (-1 << 26) : inst & 0xffff;
55 long disp = 0;
56
57 switch (opcode) {
58 case 0x1: /* bltz, bgez, bltzal, bgezal */
59 switch ((inst >> 16) & 0x1f) {
60 case 0x00: /* bltz */
61 if (scp->sc_regs[r1] < 0)
62 disp = bdisp;
63 break;
64 case 0x01: /* bgez */
65 if (scp->sc_regs[r1] >= 0)
66 disp = bdisp;
67 break;
68 case 0x10: /* bltzal */
69 if (scp->sc_regs[r1] < 0)
70 disp = bdisp;
71 scp->sc_regs[31] = scp->sc_pc + 4;
72 break;
73 case 0x11: /* bgezal */
74 if (scp->sc_regs[r1] >= 0)
75 disp = bdisp;
76 scp->sc_regs[31] = scp->sc_pc + 4;
77 break;
78 }
79 break;
80 case 0x4: /* beq */
81 if (scp->sc_regs[r1] == scp->sc_regs[r2])
82 disp = bdisp;
83 break;
84 case 0x5: /* bne */
85 if (scp->sc_regs[r1] != scp->sc_regs[r2])
86 disp = bdisp;
87 break;
88 case 0x6: /* ble */
89 if (scp->sc_regs[r1] <= scp->sc_regs[r2])
90 disp = bdisp;
91 break;
92 case 0x7: /* bgtz */
93 if (scp->sc_regs[r1] >= scp->sc_regs[r2])
94 disp = bdisp;
95 break;
96 case 0x2: /* j */
97 disp = jdisp;
98 break;
99 case 0x3: /* jal */
100 disp = jdisp;
101 scp->sc_regs[31] = scp->sc_pc + 4;
102 break;
103 }
104 scp->sc_pc += disp * 4;
105 }
106 #endif
107
108 void
109 arch_skip_instruction(scp)
110 struct sigcontext *scp;
111 {
112 /* Skip the offending instruction */
113 if (scp->sc_cause & CAUSE_BD)
114 emulate_branch(scp, *(unsigned long *) scp->sc_pc);
115 else
116 scp->sc_pc += 4;
117 }
118
119 unsigned char *
120 arch_internal_error_arguments(struct sigcontext *scp)
121 {
122 if (scp->sc_cause & CAUSE_BD)
123 return (unsigned char *) (scp->sc_pc + 8);
124 else
125 return (unsigned char *) (scp->sc_pc + 4);
126 }
127
128 boolean
129 arch_pseudo_atomic_atomic(struct sigcontext *scp)
130 {
131 return (scp->sc_regs[reg_ALLOC] & 1);
132 }
133
134 #define PSEUDO_ATOMIC_INTERRUPTED_BIAS 0x7f000000
135
136 void
137 arch_set_pseudo_atomic_interrupted(struct sigcontext *scp)
138 {
139 scp->sc_regs[reg_NL4] += PSEUDO_ATOMIC_INTERRUPTED_BIAS;
140 }
141
142 unsigned long
143 arch_install_breakpoint(void *pc)
144 {
145 unsigned long *ptr = (unsigned long *) pc;
146 unsigned long result = *ptr;
147
148 *ptr = (trap_Breakpoint << 16) | 0xd;
149
150 os_flush_icache((os_vm_address_t) ptr, sizeof(unsigned long));
151
152 return result;
153 }
154
155 void
156 arch_remove_breakpoint(void *pc, unsigned long orig_inst)
157 {
158 *(unsigned long *) pc = orig_inst;
159
160 os_flush_icache((os_vm_address_t) pc, sizeof(unsigned long));
161 }
162
163 static unsigned long *skipped_break_addr, displaced_after_inst;
164 static int orig_sigmask;
165
166 void
167 arch_do_displaced_inst(struct sigcontext *scp, unsigned long orig_inst)
168 {
169 unsigned long *pc = (unsigned long *) scp->sc_pc;
170 unsigned long *break_pc, *next_pc;
171 unsigned long next_inst;
172 int opcode;
173 struct sigcontext tmp;
174
175 orig_sigmask = scp->sc_mask;
176 scp->sc_mask = BLOCKABLE;
177
178 /* Figure out where the breakpoint is, and what happens next. */
179 if (scp->sc_cause & CAUSE_BD) {
180 break_pc = pc + 1;
181 next_inst = *pc;
182 } else {
183 break_pc = pc;
184 next_inst = orig_inst;
185 }
186
187 /* Put the original instruction back. */
188 *break_pc = orig_inst;
189 os_flush_icache((os_vm_address_t) break_pc, sizeof(unsigned long));
190
191 skipped_break_addr = break_pc;
192
193 /* Figure out where it goes. */
194 opcode = next_inst >> 26;
195 if (opcode == 1 || ((opcode & 0x3c) == 0x4)
196 || ((next_inst & 0xf00e0000) == 0x80000000)) {
197 tmp = *scp;
198 emulate_branch(&tmp, next_inst);
199 next_pc = (unsigned long *) tmp.sc_pc;
200 } else
201 next_pc = pc + 1;
202
203 displaced_after_inst = *next_pc;
204 *next_pc = (trap_AfterBreakpoint << 16) | 0xd;
205 os_flush_icache((os_vm_address_t) next_pc, sizeof(unsigned long));
206
207 #ifdef mach
208 sigreturn(scp);
209 #endif
210 }
211
212 static void
213 sigtrap_handler(int signal, int code, struct sigcontext *scp)
214 {
215 /* Don't disallow recursive breakpoint traps. Otherwise, we can't */
216 /* use debugger breakpoints anywhere in here. */
217 sigsetmask(scp->sc_mask);
218
219 switch (code) {
220 case trap_PendingInterrupt:
221 arch_skip_instruction(scp);
222 interrupt_handle_pending(scp);
223 break;
224
225 case trap_Halt:
226 fake_foreign_function_call(scp);
227 lose("%%primitive halt called; the party is over.\n");
228
229 case trap_Error:
230 case trap_Cerror:
231 interrupt_internal_error(signal, code, scp, code == trap_Cerror);
232 break;
233
234 case trap_Breakpoint:
235 handle_breakpoint(signal, code, scp);
236 break;
237
238 case trap_FunctionEndBreakpoint:
239 scp->sc_pc = (int) handle_function_end_breakpoint(signal, code, scp);
240 break;
241
242 case trap_AfterBreakpoint:
243 *skipped_break_addr = (trap_Breakpoint << 16) | 0xd;
244 os_flush_icache((os_vm_address_t) skipped_break_addr,
245
246 sizeof(unsigned long));
247 skipped_break_addr = NULL;
248 *(unsigned long *) scp->sc_pc = displaced_after_inst;
249 os_flush_icache((os_vm_address_t) scp->sc_pc, sizeof(unsigned long));
250
251 scp->sc_mask = orig_sigmask;
252 break;
253
254 default:
255 interrupt_handle_now(signal, code, scp);
256 break;
257 }
258 }
259
260 static void
261 sigfpe_handler(int signal, int code, struct sigcontext *scp)
262 {
263 unsigned long bad_inst;
264 unsigned int op, rs, rt, rd, funct, dest;
265 int immed;
266 long result;
267
268 if (scp->sc_cause & CAUSE_BD)
269 bad_inst = *(unsigned long *) (scp->sc_pc + 4);
270 else
271 bad_inst = *(unsigned long *) (scp->sc_pc);
272
273 op = (bad_inst >> 26) & 0x3f;
274 rs = (bad_inst >> 21) & 0x1f;
275 rt = (bad_inst >> 16) & 0x1f;
276 rd = (bad_inst >> 11) & 0x1f;
277 funct = bad_inst & 0x3f;
278 immed = (((int) (bad_inst & 0xffff)) << 16) >> 16;
279
280 switch (op) {
281 case 0x0: /* SPECIAL */
282 switch (funct) {
283 case 0x20: /* ADD */
284 /* Check to see if this is really a pa_interrupted hit */
285 if (rs == reg_ALLOC && rt == reg_NL4) {
286 scp->sc_regs[reg_ALLOC] +=
287 (scp->sc_regs[reg_NL4] -
288 PSEUDO_ATOMIC_INTERRUPTED_BIAS);
289 arch_skip_instruction(scp);
290 interrupt_handle_pending(scp);
291 return;
292 }
293 result =
294 fixnum_value(scp->sc_regs[rs]) +
295 fixnum_value(scp->sc_regs[rt]);
296 dest = rd;
297 break;
298
299 case 0x22: /* SUB */
300 result =
301 fixnum_value(scp->sc_regs[rs]) -
302 fixnum_value(scp->sc_regs[rt]);
303 dest = rd;
304 break;
305
306 default:
307 dest = 32;
308 break;
309 }
310 break;
311
312 case 0x8: /* ADDI */
313 result = fixnum_value(scp->sc_regs[rs]) + (immed >> 2);
314 dest = rt;
315 break;
316
317 default:
318 dest = 32;
319 break;
320 }
321
322 if (dest < 32) {
323 current_dynamic_space_free_pointer =
324 (lispobj *) scp->sc_regs[reg_ALLOC];
325
326 scp->sc_regs[dest] = alloc_number(result);
327
328 scp->sc_regs[reg_ALLOC] =
329 (unsigned long) current_dynamic_space_free_pointer;
330
331 arch_skip_instruction(scp);
332
333 } else
334 interrupt_handle_now(signal, code, scp);
335 }
336
337 void
338 arch_install_interrupt_handlers(void)
339 {
340 interrupt_install_low_level_handler(SIGTRAP, sigtrap_handler);
341 interrupt_install_low_level_handler(SIGFPE, sigfpe_handler);
342 }
343
344 extern lispobj call_into_lisp(lispobj fun, lispobj * args, int nargs);
345
346 lispobj
347 funcall0(lispobj function)
348 {
349 lispobj *args = current_control_stack_pointer;
350
351 return call_into_lisp(function, args, 0);
352 }
353
354 lispobj
355 funcall1(lispobj function, lispobj arg0)
356 {
357 lispobj *args = current_control_stack_pointer;
358
359 current_control_stack_pointer += 1;
360 args[0] = arg0;
361
362 return call_into_lisp(function, args, 1);
363 }
364
365 lispobj
366 funcall2(lispobj function, lispobj arg0, lispobj arg1)
367 {
368 lispobj *args = current_control_stack_pointer;
369
370 current_control_stack_pointer += 2;
371 args[0] = arg0;
372 args[1] = arg1;
373
374 return call_into_lisp(function, args, 2);
375 }
376
377 lispobj
378 funcall3(lispobj function, lispobj arg0, lispobj arg1, lispobj arg2)
379 {
380 lispobj *args = current_control_stack_pointer;
381
382 current_control_stack_pointer += 3;
383 args[0] = arg0;
384 args[1] = arg1;
385 args[2] = arg2;
386
387 return call_into_lisp(function, args, 3);
388 }
389
390
391 /* This is apparently called by emulate_branch, but isn't defined. So */
392 /* just do nothing and hope it works... */
393
394 void
395 cacheflush(void)
396 {
397 }

  ViewVC Help
Powered by ViewVC 1.1.5