|
|
1.1 root 1: /*ident "%W%" */
2: /**************************************************************************
3: Copyright (c) 1984 AT&T
4: All Rights Reserved
5:
6: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T
7:
8: The copyright notice above does not evidence any
9: actual or intended publication of such source code.
10:
11: *****************************************************************************/
12: #include "hw_stack.h"
13:
14: /* Machine-dependent asms and functions for task library.
15: * Porting these requires intimate knowledge of the stack frame layout,
16: * call and return sequences for the machine.
17: */
18:
19: #ifdef PROC_3B
20:
21: asm(" .text");
22: asm(" .globl SAVE_REGS");
23: asm(" .align 4");
24: asm("SAVE_REGS:");
25: asm(" save &6");
26: asm(" movw 0(%ap),%r1 "); /* ptr to HW_REGS */
27: asm(" movw -24(%fp),0(%r1) "); /* move caller's r3 to arg.r3 */
28: asm(" movw -20(%fp),4(%r1) "); /* move caller's r4 to arg.r4 */
29: asm(" movw -16(%fp),8(%r1) "); /* move caller's r5 to arg.r5 */
30: asm(" movw -12(%fp),12(%r1) "); /* move caller's r6 to arg.r6 */
31: asm(" movw -8(%fp),16(%r1) "); /* move caller's r7 to arg.r7 */
32: asm(" movw -4(%fp),20(%r1) "); /* move caller's r8 to arg.r8 */
33: asm(" ret &6");
34:
35: /* save_saved_regs copies n_saved regs saved in stack frame defined by fp
36: * to a HW_REGS structure.
37: */
38: void
39: save_saved_regs(HW_REGS *regsp, int* fp)
40: {
41: FrameLayout layout(fp);
42: register int* p = FIRST_SAVED_REG_P(fp, layout.n_saved);
43: switch(layout.n_saved) {
44: case 6:
45: regsp->r3 = *p++;
46: /* FALLTHROUGH */
47: case 5:
48: regsp->r4 = *p++;
49: /* FALLTHROUGH */
50: case 4:
51: regsp->r5 = *p++;
52: /* FALLTHROUGH */
53: case 3:
54: regsp->r6 = *p++;
55: /* FALLTHROUGH */
56: case 2:
57: regsp->r7 = *p++;
58: /* FALLTHROUGH */
59: case 1:
60: regsp->r8 = *p++;
61: /* FALLTHROUGH */
62: default:
63: break;
64: }
65: }
66:
67: /* On the 3Bs, the current ap is the caller's sp, but we want caller's sp - 1
68: * to point to last used word in stack, to correspond with sp's on 386, vax,
69: * sun
70: */
71: asm(" .text");
72: asm(" .globl TOP");
73: asm(" .align 4");
74: asm("TOP:");
75: asm(" save &0");
76: asm(" movw %ap,%r0"); /* caller's sp */
77: asm(" addw2 &4,%r0"); /* caller's sp - 1 */
78: asm(" ret &0");
79:
80: /* These assembly language functions should be replaced by new-style
81: * asms, when (if) they are implemented for C++.
82: * for example:
83: * asm void
84: * set_r3(p)
85: * {
86: * % mem p;
87: * movw *p,%r3
88: * }
89: */
90:
91: asm(" .text");
92: asm(" .globl set_r3");
93: asm(" .align 4");
94: asm("set_r3:");
95: asm(" save &0");
96: asm(" movw 0(%ap),%r1 "); /* ptr to register saved in stack */
97: asm(" movw 0(%r1),%r3 ");
98: asm(" ret &0");
99:
100: asm(" .text");
101: asm(" .globl set_r4");
102: asm(" .align 4");
103: asm("set_r4:");
104: asm(" save &0");
105: asm(" movw 0(%ap),%r1 "); /* ptr to register saved in stack */
106: asm(" movw 0(%r1),%r4 ");
107: asm(" ret &0");
108:
109: asm(" .text");
110: asm(" .globl set_r5");
111: asm(" .align 4");
112: asm("set_r5:");
113: asm(" save &0");
114: asm(" movw 0(%ap),%r1 "); /* ptr to register saved in stack */
115: asm(" movw 0(%r1),%r5 ");
116: asm(" ret &0");
117:
118: asm(" .text");
119: asm(" .globl set_r6");
120: asm(" .align 4");
121: asm("set_r6:");
122: asm(" save &0");
123: asm(" movw 0(%ap),%r1 "); /* ptr to register saved in stack */
124: asm(" movw 0(%r1),%r6 ");
125: asm(" ret &0");
126:
127: asm(" .text");
128: asm(" .globl set_r7");
129: asm(" .align 4");
130: asm("set_r7:");
131: asm(" save &0");
132: asm(" movw 0(%ap),%r1 "); /* ptr to register saved in stack */
133: asm(" movw 0(%r1),%r7 ");
134: asm(" ret &0");
135:
136: asm(" .text");
137: asm(" .globl set_r8");
138: asm(" .align 4");
139: asm("set_r8:");
140: asm(" save &0");
141: asm(" movw 0(%ap),%r1 "); /* ptr to register saved in stack */
142: asm(" movw 0(%r1),%r8 ");
143: asm(" ret &0");
144:
145: #ifdef u3b
146:
147: asm(" .text");
148: asm(" .globl AP");
149: asm(" .align 4");
150: asm("AP:");
151: asm(" save &0");
152: asm(" movw -48(%fp),%r0"); /* r0 = caller's ap */
153: asm(" ret &0");
154:
155: asm(" .text");
156: asm(" .globl FP");
157: asm(" .align 4");
158: asm("FP:");
159: asm(" save &0");
160: asm(" movw -44(%fp),%r0"); /* r0 = caller's fp */
161: asm(" ret &0");
162:
163: /* On the 3B20 the sp is restored from the current ap on a return
164: * FUDGE_SP overwrites the saved ap with a new value (the 1st arg), causing
165: * the caller's ap to be changed to the new value.
166: * As a precaution, the 1st arg of caller is copied down to where new ap
167: * will point. (In case caller references 1st arg (implicit "this" arg)
168: * to set return value.)
169: * 2nd arg unnecessary on 3B20.
170: */
171: asm(" .text");
172: asm(" .globl FUDGE_SP");
173: asm(" .align 4");
174: asm("FUDGE_SP:");
175: asm(" save &0");
176: asm(" movw -48(%fp),%r1"); /* r1 = caller's ap */
177: asm(" movw 0(%ap),%r0"); /* r0 = 1st arg (de_ap) */
178: asm(" movw 0(%r1),0(%r0)"); /* *r0 = caller's 1st arg */
179: asm(" movw 0(%ap),-48(%fp)"); /* overwrite saved ap */
180: asm(" ret &0");
181:
182: #else /* BELLMAC_CHIP */
183:
184:
185: asm(" .text");
186: asm(" .globl AP");
187: asm(" .align 4");
188: asm("AP:");
189: asm(" save &0");
190: asm(" movw -32(%fp),%r0"); /* r0 = caller's ap */
191: asm(" ret &0");
192:
193: asm(" .text");
194: asm(" .globl FP");
195: asm(" .align 4");
196: asm("FP:");
197: asm(" save &0");
198: asm(" movw -28(%fp),%r0"); /* r0 = caller's fp */
199: asm(" ret &0");
200:
201: /* On BELLMAC_CHIP machines, sp is restored from current ap on return.
202: * FUDGE_SP overwrites the saved ap with a new value (the 1st arg), causing
203: * the caller's ap to be changed to the new value.
204: * As a precaution, the 1st arg of caller is copied down to where new ap
205: * will point. (In case caller references 1st arg (implicit "this" arg)
206: * to set return value.)
207: * 2nd arg unnecessary on BELLMAC_CHIP machines.
208: */
209: asm(" .text");
210: asm(" .globl FUDGE_SP");
211: asm(" .align 4");
212: asm("FUDGE_SP:");
213: asm(" save &0");
214: asm(" movw -32(%fp),%r1"); /* r1 = caller's ap */
215: asm(" movw 0(%ap),%r0"); /* r0 = 1st arg (de_ap) */
216: asm(" movw 0(%r1),0(%r0)"); /* *r0 = caller's 1st arg */
217: asm(" movw 0(%ap),-32(%fp)"); /* overwrite saved ap */
218: asm(" ret &0");
219: #endif /* BELLMAC_CHIP */
220: #endif /* PROC_3B */
221:
222:
223: #ifdef vax
224: /* save all caller regs in HW_REGS structure */
225: asm(" .globl _SAVE_REGS");
226: asm(" .align 1");
227: asm("_SAVE_REGS:");
228: asm(" .word 0xfc0 "); /* entry mask; save all user regs (r11-r6) */
229: asm(" movl 4(ap),r1 "); /* ptr to HW_REGS */
230: asm(" movl 20(fp),0(r1) "); /* move caller's r6 to arg.r6 */
231: asm(" movl 24(fp),4(r1) "); /* move caller's r7 to arg.r7 */
232: asm(" movl 28(fp),8(r1) "); /* move caller's r8 to arg.r8 */
233: asm(" movl 32(fp),12(r1) "); /* move caller's r9 to arg.r9 */
234: asm(" movl 36(fp),16(r1) "); /* move caller's r10 to arg.r10 */
235: asm(" movl 40(fp),20(r1) "); /* move caller's r11 to arg.r11 */
236: asm(" ret");
237:
238: asm(" .globl _FP");
239: asm(" .align 1");
240: asm("_FP:");
241: asm(" .word 0x0000"); /* entry mask; save no regs */
242: asm(" movl 12(fp),r0"); /* r0 = caller's fp */
243: asm(" ret");
244:
245: /* On the vax, when there are no args, the current ap is the caller's sp */
246: asm(" .globl _TOP");
247: asm(" .align 1");
248: asm("_TOP:");
249: asm(" .word 0x0000"); /* entry mask; save no regs */
250: asm(" movl ap,r0"); /* r0 = caller's sp */
251: asm(" ret");
252: /* More general (independent of #args) would be: addl3 $1,(ap),r0 # r0=nargs + 1
253: * ashl $2,r0,r0 # r0 = nargs * 4 (scale to bytes) addl2 ap,r0 #caller's sp
254: */
255:
256: asm(" .globl _set_r6");
257: asm(" .align 1");
258: asm("_set_r6:");
259: asm(" .word 0x0 "); /* save no regs */
260: asm(" movl 4(ap),r1 "); /* ptr to register saved in stack */
261: asm(" movl (r1),r6 ");
262: asm(" ret");
263:
264: asm(" .globl _set_r7");
265: asm(" .align 1");
266: asm("_set_r7:");
267: asm(" .word 0x0 "); /* save no regs */
268: asm(" movl 4(ap),r1 "); /* ptr to register saved in stack */
269: asm(" movl (r1),r7 ");
270: asm(" ret");
271:
272: asm(" .globl _set_r8");
273: asm(" .align 1");
274: asm("_set_r8:");
275: asm(" .word 0x0 "); /* save no regs */
276: asm(" movl 4(ap),r1 "); /* ptr to register saved in stack */
277: asm(" movl (r1),r8 ");
278: asm(" ret");
279:
280: asm(" .globl _set_r9");
281: asm(" .align 1");
282: asm("_set_r9:");
283: asm(" .word 0x0 "); /* save no regs */
284: asm(" movl 4(ap),r1 "); /* ptr to register saved in stack */
285: asm(" movl (r1),r9 ");
286: asm(" ret");
287:
288: asm(" .globl _set_r10");
289: asm(" .align 1");
290: asm("_set_r10:");
291: asm(" .word 0x0 "); /* save no regs */
292: asm(" movl 4(ap),r1 "); /* ptr to register saved in stack */
293: asm(" movl (r1),r10 ");
294: asm(" ret");
295:
296: asm(" .globl _set_r11");
297: asm(" .align 1");
298: asm("_set_r11:");
299: asm(" .word 0x0 "); /* save no regs */
300: asm(" movl 4(ap),r1 "); /* ptr to register saved in stack */
301: asm(" movl (r1),r11 ");
302: asm(" ret");
303:
304: #endif
305:
306: #ifdef mc68000 /* Really, ifdef sun--stack frame layout
307: * is different on a UNIX PC, for example
308: */
309: asm(" .text");
310: asm(" .globl _SAVE_REGS");
311: asm("_SAVE_REGS:");
312: asm(" link a6,#-40");
313: asm(" moveml #0x3cfc,sp@"); /* save d2-d7, a2-a5 */
314: asm(" movl a6@(8),a0"); /* a0 = arg--ptr to HW_REGS */
315: asm(" movl a6@(-40),a0@"); /* move caller's d2 to arg.d2 */
316: asm(" movl a6@(-36),a0@(4)"); /* move caller's d3 to arg.d3 */
317: asm(" movl a6@(-32),a0@(8)"); /* move caller's d4 to arg.d4 */
318: asm(" movl a6@(-28),a0@(12)"); /* move caller's d5 to arg.d5 */
319: asm(" movl a6@(-24),a0@(16)"); /* move caller's d6 to arg.d6 */
320: asm(" movl a6@(-20),a0@(20)"); /* move caller's d7 to arg.d7 */
321: asm(" movl a6@(-16),a0@(32)"); /* move caller's a2 to arg.a2 */
322: asm(" movl a6@(-12),a0@(36)"); /* move caller's a3 to arg.a3 */
323: asm(" movl a6@(-8),a0@(40)"); /* move caller's a4 to arg.a4 */
324: asm(" movl a6@(-4),a0@(44)"); /* move caller's a5 to arg.a5 */
325: asm(" moveml a6@(-40),#0x3cfc"); /* restore d2-d7, a2-a5 */
326: asm(" unlk a6");
327: asm(" rts");
328:
329: /* save_saved_regs copies regs saved in stack frame defined by fp
330: * to a HW_REGS structure. Uses FrameLayout() to find which regs are saved.
331: */
332: void
333: save_saved_regs(HW_REGS *regsp, int* fp)
334: {
335: FrameLayout layout(fp);
336: register int* p = FIRST_SAVED_REG_P(fp,layout.offset);
337: register int* rp = (int*)regsp;
338:
339: register unsigned short mask = layout.mask;
340: // start with d2, end with a5
341: for (register int m = 0x4; m != 0x2000; m <<=1) {
342: if (m & mask) {
343: *rp++ = *p++;
344: } else {
345: rp++;
346: }
347: }
348: }
349:
350: /* On the 68k, without a link inst, fp (a6) doesn't move on a call */
351: asm(" .text");
352: asm(" .globl _FP");
353: asm("_FP:");
354: asm(" lea a6@,a0");
355: asm(" movl a0,d0"); /* for compilers that return everything in d0*/
356: asm(" rts");
357:
358: /* On the 68k, a call (via jsr or bsr) pushes the pc on the stack;
359: the caller's sp is the current sp + 1 */
360: asm(" .text");
361: asm(" .globl _TOP");
362: asm("_TOP:");
363: asm(" lea sp@(4),a0");
364: asm(" movl a0,d0"); /* for compilers that return everything in d0*/
365: asm(" rts");
366:
367: /* On the 68k, immediately before the rts, the sp is pointing at the
368: * return pc on the stack. The rts pops the pc off the stack.
369: * To reset the sp correctly after fudging the stack, we'll save the
370: * pointer to "skip's" return-pc in Skip_pc_p, and fudge_return() will
371: * overwrite task::task's return pc with the address of fudge_sp,
372: * a function that will reset the sp to Skip_pc_p, and then do the rts.
373: * Ugly, but it should work.
374: */
375: // NOTE: The following definition of Skip_pc_p appears in fudge.c.68k,
376: // because of an apparent bug in the Sun-3 compiler. It seems to get
377: // confused by intermingling of definitions and asms.
378: // int* Skip_pc_p; // global to hold fudged return pc.
379: // Set in FUDGE_SP, used by fudge_sp a few instructions
380: // later. Be careful not to add intervening insts.
381: //Note: 1st arg unnecessary on Sun-2/3
382: void
383: FUDGE_SP(int*, int* de_fp)
384: {
385: Skip_pc_p = OLD_PC_P(de_fp);
386: }
387:
388: asm(" .text");
389: asm(" .globl _fudge_sp");
390: asm("_fudge_sp:");
391: asm(" movl _Skip_pc_p,a7");
392: asm(" rts");
393:
394: asm(" .text");
395: asm(" .globl _set_d2");
396: asm("_set_d2:");
397: asm(" movl sp@(4),a0"); /* arg is ptr to register saved in stack */
398: asm(" movl a0@,d2");
399: asm(" rts");
400:
401: asm(" .text");
402: asm(" .globl _set_d3");
403: asm("_set_d3:");
404: asm(" movl sp@(4),a0"); /* arg is ptr to register saved in stack */
405: asm(" movl a0@,d3");
406: asm(" rts");
407:
408: asm(" .text");
409: asm(" .globl _set_d4");
410: asm("_set_d4:");
411: asm(" movl sp@(4),a0"); /* arg is ptr to register saved in stack */
412: asm(" movl a0@,d4");
413: asm(" rts");
414:
415: asm(" .text");
416: asm(" .globl _set_d5");
417: asm("_set_d5:");
418: asm(" movl sp@(4),a0"); /* arg is ptr to register saved in stack */
419: asm(" movl a0@,d5");
420: asm(" rts");
421:
422: asm(" .text");
423: asm(" .globl _set_d6");
424: asm("_set_d6:");
425: asm(" movl sp@(4),a0"); /* arg is ptr to register saved in stack */
426: asm(" movl a0@,d6");
427: asm(" rts");
428:
429: asm(" .text");
430: asm(" .globl _set_d7");
431: asm("_set_d7:");
432: asm(" movl sp@(4),a0"); /* arg is ptr to register saved in stack */
433: asm(" movl a0@,d7");
434: asm(" rts");
435:
436: asm(" .text");
437: asm(" .globl _set_a2");
438: asm("_set_a2:");
439: asm(" movl sp@(4),a0"); /* arg is ptr to register saved in stack */
440: asm(" movl a0@,a2");
441: asm(" rts");
442:
443: asm(" .text");
444: asm(" .globl _set_a3");
445: asm("_set_a3:");
446: asm(" movl sp@(4),a0"); /* arg is ptr to register saved in stack */
447: asm(" movl a0@,a3");
448: asm(" rts");
449:
450: asm(" .text");
451: asm(" .globl _set_a4");
452: asm("_set_a4:");
453: asm(" movl sp@(4),a0"); /* arg is ptr to register saved in stack */
454: asm(" movl a0@,a4");
455: asm(" rts");
456:
457: asm(" .text");
458: asm(" .globl _set_a5");
459: asm("_set_a5:");
460: asm(" movl sp@(4),a0"); /* arg is ptr to register saved in stack */
461: asm(" movl a0@,a5");
462: asm(" rts");
463:
464: #endif /* mc68000 */
465:
466: #ifdef i386
467:
468: asm(" .text");
469: asm(" .globl SAVE_REGS");
470: asm("SAVE_REGS:");
471: asm(" pushl %ebp"); /* save caller's fp */
472: asm(" movl %esp,%ebp"); /* fp = sp */
473: asm(" pushl %edi"); /* save edi */
474: asm(" pushl %esi"); /* save esi */
475: asm(" pushl %ebx"); /* save ebx */
476: asm(" movl 8(%ebp),%eax"); /* eax = arg--ptr to HW_REGS */
477: asm(" movl -4(%ebp),%ecx"); /* ecx = caller's edi */
478: asm(" movl %ecx,0(%eax)"); /* arg.edi = ecx */
479: asm(" movl -8(%ebp),%ecx"); /* ecx = caller's esi */
480: asm(" movl %ecx,4(%eax)"); /* arg.esi = ecx */
481: asm(" movl -12(%ebp),%ecx"); /* ecx = caller's ebx */
482: asm(" movl %ecx,8(%eax)"); /* arg.ebx = ecx */
483: asm(" popl %ebx");
484: asm(" popl %esi");
485: asm(" popl %edi");
486: asm(" leave");
487: asm(" ret");
488:
489: /* save_saved_regs copies regs saved in stack frame defined by fp
490: * to a HW_REGS structure. Uses FrameLayout() to find which regs are saved.
491: */
492: void
493: save_saved_regs(HW_REGS *regsp, int* fp)
494: {
495: FrameLayout layout(fp);
496: register int* p = FIRST_SAVED_REG_P(fp,layout.offset);
497: register int* rp = (int*)regsp;
498:
499: register unsigned short mask = layout.mask;
500: for (register short m = 1; m != 0x08; m <<=1) {
501: if (m & mask) {
502: *rp++ = *p--;
503: } else {
504: rp++;
505: }
506: }
507: }
508:
509: /* On the i386, without a specific inst, fp (ebp) doesn't move on a call */
510: asm(".text");
511: asm(".globl FP");
512: asm("FP:");
513: asm(" movl %ebp,%eax");
514: asm(" ret");
515:
516: /* On the i386, a call pushes the pc on the stack;
517: the caller's sp is the current sp + 1 */
518: asm(".text");
519: asm(".globl TOP");
520: asm("TOP:");
521: asm(" leal 4(%esp),%eax");
522: asm(" ret");
523:
524:
525: /* On the i386, immediately before the ret, the sp is pointing at the
526: * return pc on the stack. The ret pops the pc off the stack.
527: * To reset the sp correctly after fudging the stack, we'll save the
528: * pointer to "skip's" return-pc in Skip_pc_p, and fudge_return() will
529: * overwrite task::task's return pc with the address of fudge_sp,
530: * a function that will reset the sp to Skip_pc_p, and then do the ret.
531: * Ugly, but it should work.
532: */
533: // NOTE: The following definition of Skip_pc_p appears in fudge.c.386,
534: // because of an apparent bug in the Sun-3 compiler. It seems to get
535: // confused by intermingling of definitions and asms.
536: // int* Skip_pc_p; // global to hold fudged return pc.
537: // Set in FUDGE_SP, used by fudge_sp a few instructions
538: // later. Be careful not to add intervening insts.
539: //Note: 1st arg unnecessary on i386
540: void
541: FUDGE_SP(int*, int* de_fp)
542: {
543: Skip_pc_p = OLD_PC_P(de_fp);
544: }
545:
546: asm(" .text");
547: asm(" .globl fudge_sp");
548: asm("fudge_sp:");
549: asm(" movl Skip_pc_p,%esp");
550: asm(" ret");
551:
552: asm(".text");
553: asm(".globl set_edi");
554: asm("set_edi:");
555: asm(" movl 4(%esp),%eax");
556: asm(" movl 0(%eax),%edi");
557: asm(" ret");
558:
559: asm(".text");
560: asm(".globl set_esi");
561: asm("set_esi:");
562: asm(" movl 4(%esp),%eax");
563: asm(" movl 0(%eax),%esi");
564: asm(" ret");
565:
566: asm(".text");
567: asm(".globl set_ebx");
568: asm("set_ebx:");
569: asm(" movl 4(%esp),%eax");
570: asm(" movl 0(%eax),%ebx");
571: asm(" ret");
572:
573: #endif /* i386 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.