source: rtems/c/src/exec/score/cpu/hppa1.1/cpu_asm.S @ fe7acdcf

4.104.114.84.95
Last change on this file since fe7acdcf was fe7acdcf, checked in by Joel Sherrill <joel.sherrill@…>, on 01/03/01 at 16:36:23

2001-01-03 Joel Sherrill <joel@…>

  • rtems/score/cpu.h: Added _CPU_Initialize_vectors().
  • cpu_asm.S: Modify to properly dereference _ISR_Vector_table now that it is dynamically allocated.
  • Property mode set to 100644
File size: 21.9 KB
Line 
1/*
2 * TODO:
3 *       Context_switch needs to only save callee save registers
4 *       I think this means can skip:    r1, r2, r19-29, r31
5 *       Ref:     p 3-2 of Procedure Calling Conventions Manual
6 *       This should be #ifndef DEBUG so that debugger has
7 *       accurate visibility into all registers
8 *
9 *  This file contains the assembly code for the HPPA implementation
10 *  of RTEMS.
11 *
12 *  COPYRIGHT (c) 1994,95 by Division Incorporated
13 *
14 *  The license and distribution terms for this file may be
15 *  found in the file LICENSE in this distribution or at
16 *  http://www.OARcorp.com/rtems/license.html.
17 *
18 *  $Id$
19 */
20
21#include <rtems/score/hppa.h>
22#include <rtems/score/cpu_asm.h>
23#include <rtems/score/cpu.h>
24#include <rtems/score/offsets.h>
25
26        .SPACE $PRIVATE$
27        .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
28        .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
29        .SPACE $TEXT$
30        .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
31        .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
32        .SPACE $TEXT$
33        .SUBSPA $CODE$
34
35/*
36 * Special register usage for context switch and interrupts
37 * Stay away from %cr28 which is used for TLB misses on 72000
38 */
39
40isr_arg0           .reg    %cr24
41isr_r9             .reg    %cr25
42isr_r8             .reg    %cr26
43
44/*
45 * Interrupt stack frame looks like this
46 *
47 *  offset                                   item
48 * -----------------------------------------------------------------
49 *   INTEGER_CONTEXT_OFFSET             Context_Control
50 *   FP_CONTEXT_OFFSET                  Context_Control_fp
51 *
52 * It is padded out to a multiple of 64
53 */
54
55
56/*PAGE^L
57 *  void _Generic_ISR_Handler()
58 *
59 *  This routine provides the RTEMS interrupt management.
60 *
61 *   We jump here from the interrupt vector.
62 *   The HPPA hardware has done some stuff for us:
63 *       PSW saved in IPSW
64 *       PSW set to 0
65 *       PSW[E] set to default (0)
66 *       PSW[M] set to 1 iff this is HPMC
67 *
68 *       IIA queue is frozen (since PSW[Q] is now 0)
69 *       privilege level promoted to 0
70 *       IIR, ISR, IOR potentially updated if PSW[Q] was 1 at trap
71 *       registers GR  1,8,9,16,17,24,25 copied to shadow regs
72 *                 SHR 0 1 2  3  4  5  6
73 *
74 *   Our vector stub (in the BSP) MUST have done the following: 
75 *
76 *   a) Saved the original %r9 into %isr_r9 (%cr25)
77 *   b) Placed the vector number in %r9
78 *   c) Was allowed to also destroy $isr_r8 (%cr26),
79 *      but the stub was NOT allowed to destroy any other registers.
80 *
81 *   The typical stub sequence (in the BSP) should look like this:
82 *
83 *   a)     mtctl   %r9,isr_r9     ; (save r9 in cr25)
84 *   b)     ldi     vector,%r9     ; (load constant vector number in r9)
85 *   c)     mtctl   %r8,isr_r8     ; (save r8 in cr26)
86 *   d)     ldil    L%MY_BSP_first_level_interrupt_handler,%r8
87 *   e)     ldo     R%MY_BSP_first_level_interrupt_handler(%r8),%r8
88 *                                 ; (point to BSP raw handler table)
89 *   f)     ldwx,s  %r9(%r8),%r8   ; (load value from raw handler table)
90 *   g)     bv      0(%r8)         ; (call raw handler: _Generic_ISR_Handler)
91 *   h)     mfctl   isr_r8,%r8     ; (restore r8 from cr26 in delay slot)
92 *
93 *   Optionally, steps (c) thru (h) _could_ be replaced with a single
94 *          bl,n    _Generic_ISR_Handler,%r0
95 *
96 *
97 */
98        .EXPORT _Generic_ISR_Handler,ENTRY,PRIV_LEV=0
99_Generic_ISR_Handler:
100        .PROC
101        .CALLINFO FRAME=0,NO_CALLS
102        .ENTRY
103
104        mtctl     arg0, isr_arg0
105
106/*
107 * save interrupt state
108 */
109        mfctl     ipsw, arg0
110        stw       arg0, IPSW_OFFSET(sp)
111
112        mfctl     iir, arg0
113        stw       arg0, IIR_OFFSET(sp)
114
115        mfctl     ior, arg0
116        stw       arg0, IOR_OFFSET(sp)
117
118        mfctl     pcoq, arg0
119        stw       arg0, PCOQFRONT_OFFSET(sp)
120
121        mtctl     %r0, pcoq
122        mfctl     pcoq, arg0
123        stw       arg0, PCOQBACK_OFFSET(sp)
124
125        mfctl     %sar, arg0
126        stw       arg0, SAR_OFFSET(sp)
127
128/*
129 * Build an interrupt frame to hold the contexts we will need.
130 * We have already saved the interrupt items on the stack
131 *
132 * At this point the following registers are damaged wrt the interrupt
133 *  reg    current value        saved value
134 * ------------------------------------------------
135 *  arg0   scratch               isr_arg0  (cr24)
136 *  r9     vector number         isr_r9    (cr25)
137 *
138 * Point to beginning of integer context and
139 * save the integer context
140 */
141        stw         %r1,R1_OFFSET(sp)
142        stw         %r2,R2_OFFSET(sp)
143        stw         %r3,R3_OFFSET(sp)
144        stw         %r4,R4_OFFSET(sp)
145        stw         %r5,R5_OFFSET(sp)
146        stw         %r6,R6_OFFSET(sp)
147        stw         %r7,R7_OFFSET(sp)
148        stw         %r8,R8_OFFSET(sp)
149/*
150 * skip r9
151 */
152        stw         %r10,R10_OFFSET(sp)
153        stw         %r11,R11_OFFSET(sp)
154        stw         %r12,R12_OFFSET(sp)
155        stw         %r13,R13_OFFSET(sp)
156        stw         %r14,R14_OFFSET(sp)
157        stw         %r15,R15_OFFSET(sp)
158        stw         %r16,R16_OFFSET(sp)
159        stw         %r17,R17_OFFSET(sp)
160        stw         %r18,R18_OFFSET(sp)
161        stw         %r19,R19_OFFSET(sp)
162        stw         %r20,R20_OFFSET(sp)
163        stw         %r21,R21_OFFSET(sp)
164        stw         %r22,R22_OFFSET(sp)
165        stw         %r23,R23_OFFSET(sp)
166        stw         %r24,R24_OFFSET(sp)
167        stw         %r25,R25_OFFSET(sp)
168/*
169 * skip arg0
170 */
171        stw         %r27,R27_OFFSET(sp)
172        stw         %r28,R28_OFFSET(sp)
173        stw         %r29,R29_OFFSET(sp)
174        stw         %r30,R30_OFFSET(sp)
175        stw         %r31,R31_OFFSET(sp)
176
177/* Now most registers are available since they have been saved
178 *
179 * The following items are currently wrong in the integer context
180 *  reg    current value        saved value
181 * ------------------------------------------------
182 *  arg0   scratch               isr_arg0  (cr24)
183 *  r9     vector number         isr_r9    (cr25)
184 *
185 * Fix them
186 */
187
188         mfctl      isr_arg0,%r3
189         stw        %r3,ARG0_OFFSET(sp)
190
191         mfctl      isr_r9,%r3
192         stw        %r3,R9_OFFSET(sp)
193
194/*
195 * At this point we are done with isr_arg0, and isr_r9 control registers
196 *
197 * Prepare to re-enter virtual mode
198 * We need Q in case the interrupt handler enables interrupts
199 */
200
201        ldil      L%CPU_PSW_DEFAULT, arg0
202        ldo       R%CPU_PSW_DEFAULT(arg0), arg0
203        mtctl     arg0, ipsw
204
205/*
206 * Now jump to "rest_of_isr_handler" with the rfi
207 * We are assuming the space queues are all correct already
208 */
209
210        ldil      L%rest_of_isr_handler, arg0
211        ldo       R%rest_of_isr_handler(arg0), arg0
212        mtctl     arg0, pcoq
213        ldo       4(arg0), arg0
214        mtctl     arg0, pcoq
215
216        rfi
217        nop
218
219/*
220 * At this point we are back in virtual mode and all our
221 *  normal addressing is once again ok.
222 *
223 *  It is now ok to take an exception or trap
224 */
225
226rest_of_isr_handler:
227
228/*
229 * Point to beginning of float context and
230 * save the floating point context -- doing whatever patches are necessary
231 */
232
233        .call ARGW0=GR
234        bl          _CPU_Save_float_context,%r2
235        ldo         FP_CONTEXT_OFFSET(sp),arg0
236
237/*
238 * save the ptr to interrupt frame as an argument for the interrupt handler
239 */
240
241        copy        sp, arg1
242
243/*
244 * Advance the frame to point beyond all interrupt contexts (integer & float)
245 * this also includes the pad to align to 64byte stack boundary
246 */
247        ldo         CPU_INTERRUPT_FRAME_SIZE(sp), sp
248
249/*
250 *    r3  -- &_ISR_Nest_level
251 *    r5  -- value _ISR_Nest_level
252 *    r4  -- &_Thread_Dispatch_disable_level
253 *    r6  -- value _Thread_Dispatch_disable_level
254 *    r9  -- vector number
255 */
256
257        .import   _ISR_Nest_level,data
258        ldil      L%_ISR_Nest_level,%r3
259        ldo       R%_ISR_Nest_level(%r3),%r3
260        ldw       0(%r3),%r5
261
262        .import   _Thread_Dispatch_disable_level,data
263        ldil      L%_Thread_Dispatch_disable_level,%r4
264        ldo       R%_Thread_Dispatch_disable_level(%r4),%r4
265        ldw       0(%r4),%r6
266
267/*
268 * increment interrupt nest level counter.  If outermost interrupt
269 * switch the stack and squirrel away the previous sp.
270 */
271        addi      1,%r5,%r5
272        stw       %r5, 0(%r3)
273
274/*
275 * compute and save new stack (with frame)
276 * just in case we are nested -- simpler this way
277 */
278        comibf,=  1,%r5,stack_done
279        ldo       128(sp),%r7
280
281/*
282 * Switch to interrupt stack allocated by the interrupt manager (intr.c)
283 */
284        .import   _CPU_Interrupt_stack_low,data
285        ldil      L%_CPU_Interrupt_stack_low,%r7
286        ldw       R%_CPU_Interrupt_stack_low(%r7),%r7
287        ldo       128(%r7),%r7
288
289stack_done:
290/*
291 * save our current stack pointer where the "old sp" is supposed to be
292 */
293        stw       sp, -4(%r7)
294/*
295 * and switch stacks (or advance old stack in nested case)
296 */
297        copy      %r7, sp
298
299/*
300 * increment the dispatch disable level counter.
301 */
302        addi      1,%r6,%r6
303        stw       %r6, 0(%r4)
304
305/*
306 * load address of user handler
307 * Note:  No error checking is done, it is assumed that the
308 *        vector table contains a valid address or a stub
309 *        spurious handler.
310 */
311        .import   _ISR_Vector_table,data
312        ldil      L%_ISR_Vector_table,%r8
313        ldo       R%_ISR_Vector_table(%r8),%r8
314        ldw       (%r8),%r8
315        ldwx,s    %r9(%r8),%r8
316
317/*
318 * invoke user interrupt handler
319 * Interrupts are currently disabled, as per RTEMS convention
320 * The handler has the option of re-enabling interrupts
321 * NOTE:  can not use 'bl' since it uses "pc-relative" addressing
322 *    and we are using a hard coded address from a table
323 *  So... we fudge r2 ourselves (ala dynacall)
324 *  arg0 = vector number, arg1 = ptr to rtems_interrupt_frame
325 */
326        copy      %r9, %r26
327        .call  ARGW0=GR, ARGW1=GR
328        blr       %r0, rp
329        bv,n      0(%r8)
330
331post_user_interrupt_handler:
332
333/*
334 * Back from user handler(s)
335 * Disable external interrupts (since the interrupt handler could
336 * have turned them on) and return to the interrupted task stack (assuming
337 * (_ISR_Nest_level == 0)
338 */
339
340        rsm        HPPA_PSW_I + HPPA_PSW_R, %r0
341        ldw        -4(sp), sp
342
343/*
344 *    r3  -- (most of) &_ISR_Nest_level
345 *    r5  -- value _ISR_Nest_level
346 *    r4  -- (most of) &_Thread_Dispatch_disable_level
347 *    r6  -- value _Thread_Dispatch_disable_level
348 *    r7  -- (most of) &_ISR_Signals_to_thread_executing
349 *    r8  -- value _ISR_Signals_to_thread_executing
350 */
351
352        .import   _ISR_Nest_level,data
353        ldil      L%_ISR_Nest_level,%r3
354        ldw       R%_ISR_Nest_level(%r3),%r5
355
356        .import   _Thread_Dispatch_disable_level,data
357        ldil      L%_Thread_Dispatch_disable_level,%r4
358        ldw       R%_Thread_Dispatch_disable_level(%r4),%r6
359
360        .import    _ISR_Signals_to_thread_executing,data
361        ldil       L%_ISR_Signals_to_thread_executing,%r7
362
363/*
364 * decrement isr nest level
365 */
366        addi      -1, %r5, %r5
367        stw       %r5, R%_ISR_Nest_level(%r3)
368
369/*
370 * decrement dispatch disable level counter and, if not 0, go on
371 */
372        addi       -1,%r6,%r6
373        comibf,=   0,%r6,isr_restore
374        stw        %r6, R%_Thread_Dispatch_disable_level(%r4)
375
376/*
377 * check whether or not a context switch is necessary
378 */
379        .import    _Context_Switch_necessary,data
380        ldil       L%_Context_Switch_necessary,%r8
381        ldw        R%_Context_Switch_necessary(%r8),%r8
382        comibf,=,n 0,%r8,ISR_dispatch
383
384/*
385 * check whether or not a context switch is necessary because an ISR
386 *    sent signals to the interrupted task
387 */
388        ldw        R%_ISR_Signals_to_thread_executing(%r7),%r8
389        comibt,=,n 0,%r8,isr_restore
390
391
392/*
393 * OK, something happened while in ISR and we need to switch to a task
394 * other than the one which was interrupted or the
395 *    ISR_Signals_to_thread_executing case
396 * We also turn on interrupts, since the interrupted task had them
397 *   on (obviously :-) and Thread_Dispatch is happy to leave ints on.
398 */
399
400ISR_dispatch:
401        stw        %r0, R%_ISR_Signals_to_thread_executing(%r7)
402
403        ssm        HPPA_PSW_I, %r0
404
405        .import    _Thread_Dispatch,code
406        .call
407        bl         _Thread_Dispatch,%r2
408        ldo        128(sp),sp
409
410        ldo        -128(sp),sp
411
412isr_restore:
413
414/*
415 * enable interrupts during most of restore
416 */
417        ssm        HPPA_PSW_I, %r0
418
419/*
420 * Get a pointer to beginning of our stack frame
421 */
422        ldo        -CPU_INTERRUPT_FRAME_SIZE(sp), %arg1
423
424/*
425 * restore float
426 */
427        .call ARGW0=GR
428        bl         _CPU_Restore_float_context,%r2
429        ldo        FP_CONTEXT_OFFSET(%arg1), arg0
430
431        copy       %arg1, %arg0
432
433/*
434 *   ********** FALL THRU **********
435 */
436
437/*
438 * Jump here from bottom of Context_Switch
439 * Also called directly by _CPU_Context_Restart_self via _Thread_Restart_self
440 * restore interrupt state
441 */
442
443        .EXPORT _CPU_Context_restore
444_CPU_Context_restore:
445
446/*
447 * restore integer state
448 */
449        ldw         R1_OFFSET(arg0),%r1
450        ldw         R2_OFFSET(arg0),%r2
451        ldw         R3_OFFSET(arg0),%r3
452        ldw         R4_OFFSET(arg0),%r4
453        ldw         R5_OFFSET(arg0),%r5
454        ldw         R6_OFFSET(arg0),%r6
455        ldw         R7_OFFSET(arg0),%r7
456        ldw         R8_OFFSET(arg0),%r8
457        ldw         R9_OFFSET(arg0),%r9
458        ldw         R10_OFFSET(arg0),%r10
459        ldw         R11_OFFSET(arg0),%r11
460        ldw         R12_OFFSET(arg0),%r12
461        ldw         R13_OFFSET(arg0),%r13
462        ldw         R14_OFFSET(arg0),%r14
463        ldw         R15_OFFSET(arg0),%r15
464        ldw         R16_OFFSET(arg0),%r16
465        ldw         R17_OFFSET(arg0),%r17
466        ldw         R18_OFFSET(arg0),%r18
467        ldw         R19_OFFSET(arg0),%r19
468        ldw         R20_OFFSET(arg0),%r20
469        ldw         R21_OFFSET(arg0),%r21
470        ldw         R22_OFFSET(arg0),%r22
471        ldw         R23_OFFSET(arg0),%r23
472        ldw         R24_OFFSET(arg0),%r24
473/*
474 * skipping r25; used as scratch register below
475 * skipping r26 (arg0) until we are done with it
476 */
477        ldw         R27_OFFSET(arg0),%r27
478        ldw         R28_OFFSET(arg0),%r28
479        ldw         R29_OFFSET(arg0),%r29
480/*
481 * skipping r30 (sp) until we turn off interrupts
482 */
483        ldw         R31_OFFSET(arg0),%r31
484
485/*
486 * Turn off Q & R & I so we can write r30 and interrupt control registers
487 */
488        rsm        HPPA_PSW_Q + HPPA_PSW_R + HPPA_PSW_I, %r0
489
490/*
491 * now safe to restore r30
492 */
493        ldw         R30_OFFSET(arg0),%r30
494
495        ldw        IPSW_OFFSET(arg0), %r25
496        mtctl      %r25, ipsw
497
498        ldw        SAR_OFFSET(arg0), %r25
499        mtctl      %r25, sar
500
501        ldw        PCOQFRONT_OFFSET(arg0), %r25
502        mtctl      %r25, pcoq
503
504        ldw        PCOQBACK_OFFSET(arg0), %r25
505        mtctl      %r25, pcoq
506
507/*
508 * Load r25 with interrupts off
509 */
510        ldw         R25_OFFSET(arg0),%r25
511/*
512 * Must load r26 (arg0) last
513 */
514        ldw         R26_OFFSET(arg0),%r26
515
516isr_exit:
517        rfi
518        .EXIT
519        .PROCEND
520
521/*
522 *  This section is used to context switch floating point registers.
523 *  Ref:  6-35 of Architecture 1.1
524 *
525 *  NOTE:    since integer multiply uses the floating point unit,
526 *           we have to save/restore fp on every trap.  We cannot
527 *           just try to keep track of fp usage.
528 */
529
530        .align 32
531        .EXPORT _CPU_Save_float_context,ENTRY,PRIV_LEV=0
532_CPU_Save_float_context:
533        .PROC
534        .CALLINFO FRAME=0,NO_CALLS
535        .ENTRY
536        fstds,ma    %fr0,8(%arg0)
537        fstds,ma    %fr1,8(%arg0)
538        fstds,ma    %fr2,8(%arg0)
539        fstds,ma    %fr3,8(%arg0)
540        fstds,ma    %fr4,8(%arg0)
541        fstds,ma    %fr5,8(%arg0)
542        fstds,ma    %fr6,8(%arg0)
543        fstds,ma    %fr7,8(%arg0)
544        fstds,ma    %fr8,8(%arg0)
545        fstds,ma    %fr9,8(%arg0)
546        fstds,ma    %fr10,8(%arg0)
547        fstds,ma    %fr11,8(%arg0)
548        fstds,ma    %fr12,8(%arg0)
549        fstds,ma    %fr13,8(%arg0)
550        fstds,ma    %fr14,8(%arg0)
551        fstds,ma    %fr15,8(%arg0)
552        fstds,ma    %fr16,8(%arg0)
553        fstds,ma    %fr17,8(%arg0)
554        fstds,ma    %fr18,8(%arg0)
555        fstds,ma    %fr19,8(%arg0)
556        fstds,ma    %fr20,8(%arg0)
557        fstds,ma    %fr21,8(%arg0)
558        fstds,ma    %fr22,8(%arg0)
559        fstds,ma    %fr23,8(%arg0)
560        fstds,ma    %fr24,8(%arg0)
561        fstds,ma    %fr25,8(%arg0)
562        fstds,ma    %fr26,8(%arg0)
563        fstds,ma    %fr27,8(%arg0)
564        fstds,ma    %fr28,8(%arg0)
565        fstds,ma    %fr29,8(%arg0)
566        fstds,ma    %fr30,8(%arg0)
567        fstds       %fr31,0(%arg0)
568        bv          0(%r2)
569        addi        -(31*8), %arg0, %arg0        ; restore arg0 just for fun
570        .EXIT
571        .PROCEND
572
573        .align 32
574        .EXPORT _CPU_Restore_float_context,ENTRY,PRIV_LEV=0
575_CPU_Restore_float_context:
576        .PROC
577        .CALLINFO FRAME=0,NO_CALLS
578        .ENTRY
579        addi        (31*8), %arg0, %arg0         ; point at last double
580        fldds       0(%arg0),%fr31
581        fldds,mb    -8(%arg0),%fr30
582        fldds,mb    -8(%arg0),%fr29
583        fldds,mb    -8(%arg0),%fr28
584        fldds,mb    -8(%arg0),%fr27
585        fldds,mb    -8(%arg0),%fr26
586        fldds,mb    -8(%arg0),%fr25
587        fldds,mb    -8(%arg0),%fr24
588        fldds,mb    -8(%arg0),%fr23
589        fldds,mb    -8(%arg0),%fr22
590        fldds,mb    -8(%arg0),%fr21
591        fldds,mb    -8(%arg0),%fr20
592        fldds,mb    -8(%arg0),%fr19
593        fldds,mb    -8(%arg0),%fr18
594        fldds,mb    -8(%arg0),%fr17
595        fldds,mb    -8(%arg0),%fr16
596        fldds,mb    -8(%arg0),%fr15
597        fldds,mb    -8(%arg0),%fr14
598        fldds,mb    -8(%arg0),%fr13
599        fldds,mb    -8(%arg0),%fr12
600        fldds,mb    -8(%arg0),%fr11
601        fldds,mb    -8(%arg0),%fr10
602        fldds,mb    -8(%arg0),%fr9
603        fldds,mb    -8(%arg0),%fr8
604        fldds,mb    -8(%arg0),%fr7
605        fldds,mb    -8(%arg0),%fr6
606        fldds,mb    -8(%arg0),%fr5
607        fldds,mb    -8(%arg0),%fr4
608        fldds,mb    -8(%arg0),%fr3
609        fldds,mb    -8(%arg0),%fr2
610        fldds,mb    -8(%arg0),%fr1
611        bv          0(%r2)
612        fldds,mb    -8(%arg0),%fr0
613        .EXIT
614        .PROCEND
615
616/*
617 * These 2 small routines are unused right now.
618 * Normally we just go thru _CPU_Save_float_context (and Restore)
619 *
620 * Here we just deref the ptr and jump up, letting _CPU_Save_float_context
621 *  do the return for us.
622 */
623
624        .EXPORT _CPU_Context_save_fp,ENTRY,PRIV_LEV=0
625_CPU_Context_save_fp:
626        .PROC
627        .CALLINFO FRAME=0,NO_CALLS
628        .ENTRY
629        bl          _CPU_Save_float_context, %r0
630        ldw         0(%arg0), %arg0
631        .EXIT
632        .PROCEND
633
634        .EXPORT _CPU_Context_restore_fp,ENTRY,PRIV_LEV=0
635_CPU_Context_restore_fp:
636        .PROC
637        .CALLINFO FRAME=0,NO_CALLS
638        .ENTRY
639        bl          _CPU_Restore_float_context, %r0
640        ldw         0(%arg0), %arg0
641        .EXIT
642        .PROCEND
643
644
645/*
646 *  void _CPU_Context_switch( run_context, heir_context )
647 *
648 *  This routine performs a normal non-FP context switch.
649 */
650
651        .align 32
652        .EXPORT _CPU_Context_switch,ENTRY,PRIV_LEV=0,ARGW0=GR,ARGW1=GR
653_CPU_Context_switch:
654        .PROC
655        .CALLINFO FRAME=64
656        .ENTRY
657
658/*
659 * Save the integer context
660 */
661        stw         %r1,R1_OFFSET(arg0)
662        stw         %r2,R2_OFFSET(arg0)
663        stw         %r3,R3_OFFSET(arg0)
664        stw         %r4,R4_OFFSET(arg0)
665        stw         %r5,R5_OFFSET(arg0)
666        stw         %r6,R6_OFFSET(arg0)
667        stw         %r7,R7_OFFSET(arg0)
668        stw         %r8,R8_OFFSET(arg0)
669        stw         %r9,R9_OFFSET(arg0)
670        stw         %r10,R10_OFFSET(arg0)
671        stw         %r11,R11_OFFSET(arg0)
672        stw         %r12,R12_OFFSET(arg0)
673        stw         %r13,R13_OFFSET(arg0)
674        stw         %r14,R14_OFFSET(arg0)
675        stw         %r15,R15_OFFSET(arg0)
676        stw         %r16,R16_OFFSET(arg0)
677        stw         %r17,R17_OFFSET(arg0)
678        stw         %r18,R18_OFFSET(arg0)
679        stw         %r19,R19_OFFSET(arg0)
680        stw         %r20,R20_OFFSET(arg0)
681        stw         %r21,R21_OFFSET(arg0)
682        stw         %r22,R22_OFFSET(arg0)
683        stw         %r23,R23_OFFSET(arg0)
684        stw         %r24,R24_OFFSET(arg0)
685        stw         %r25,R25_OFFSET(arg0)
686        stw         %r26,R26_OFFSET(arg0)
687        stw         %r27,R27_OFFSET(arg0)
688        stw         %r28,R28_OFFSET(arg0)
689        stw         %r29,R29_OFFSET(arg0)
690        stw         %r30,R30_OFFSET(arg0)
691        stw         %r31,R31_OFFSET(arg0)
692
693/*
694 * fill in interrupt context section
695 */
696        stw         %r2, PCOQFRONT_OFFSET(%arg0)
697        ldo         4(%r2), %r2
698        stw         %r2, PCOQBACK_OFFSET(%arg0)
699
700/*
701 * Generate a suitable IPSW by using the system default psw
702 *  with the current low bits added in.
703 */
704
705        ldil        L%CPU_PSW_DEFAULT, %r2
706        ldo         R%CPU_PSW_DEFAULT(%r2), %r2
707        ssm         0, %arg2
708        dep         %arg2, 31, 8, %r2
709        stw         %r2, IPSW_OFFSET(%arg0)
710
711/*
712 * at this point, the running task context is completely saved
713 * Now jump to the bottom of the interrupt handler to load the
714 * heirs context
715 */
716
717        b           _CPU_Context_restore
718        copy        %arg1, %arg0
719
720        .EXIT
721        .PROCEND
722
723
724/*
725 * Find first bit
726 * NOTE:
727 *   This is used (and written) only for the ready chain code and
728 *   priority bit maps.
729 *   Any other use constitutes fraud.
730 *   Returns first bit from the least significant side.
731 *   Eg:  if input is 0x8001
732 *        output will indicate the '1' bit and return 0.
733 *   This is counter to HPPA bit numbering which calls this
734 *   bit 31.  This way simplifies the macros _CPU_Priority_Mask
735 *   and _CPU_Priority_Bits_index.
736 *
737 *   NOTE:
738 *       We just use 16 bit version
739 *       does not handle zero case
740 *
741 *  Based on the UTAH Mach libc version of ffs.
742 */
743
744        .align 32
745        .EXPORT hppa_rtems_ffs,ENTRY,PRIV_LEV=0,ARGW0=GR
746hppa_rtems_ffs:
747        .PROC
748        .CALLINFO FRAME=0,NO_CALLS
749        .ENTRY
750
751#ifdef RETURN_ERROR_ON_ZERO
752        comb,=  %arg0,%r0,ffsdone       ; If arg0 is 0
753        ldi     -1,%ret0                ;   return -1
754#endif
755
756#if BITFIELD_SIZE == 32
757        ldi     31,%ret0                ; Set return to high bit
758        extru,= %arg0,31,16,%r0         ; If low 16 bits are non-zero
759        addi,tr -16,%ret0,%ret0         ;   subtract 16 from bitpos
760        shd     %r0,%arg0,16,%arg0      ; else shift right 16 bits
761#else
762        ldi     15,%ret0                ; Set return to high bit
763#endif
764        extru,= %arg0,31,8,%r0          ; If low 8 bits are non-zero
765        addi,tr -8,%ret0,%ret0          ;   subtract 8 from bitpos
766        shd     %r0,%arg0,8,%arg0       ; else shift right 8 bits
767        extru,= %arg0,31,4,%r0          ; If low 4 bits are non-zero
768        addi,tr -4,%ret0,%ret0          ;   subtract 4 from bitpos
769        shd     %r0,%arg0,4,%arg0       ; else shift right 4 bits
770        extru,= %arg0,31,2,%r0          ; If low 2 bits are non-zero
771        addi,tr -2,%ret0,%ret0          ;   subtract 2 from bitpos
772        shd     %r0,%arg0,2,%arg0       ; else shift right 2 bits
773        extru,= %arg0,31,1,%r0          ; If low bit is non-zero
774        addi    -1,%ret0,%ret0          ;   subtract 1 from bitpos
775ffsdone:
776        bv,n    0(%r2)
777        nop
778        .EXIT
779        .PROCEND
Note: See TracBrowser for help on using the repository browser.