source: rtems/c/src/exec/score/cpu/hppa1.1/cpu_asm.s @ 8b2ecf85

4.104.114.84.95
Last change on this file since 8b2ecf85 was 8b2ecf85, checked in by Joel Sherrill <joel.sherrill@…>, on 05/23/96 at 15:37:38

updates from Tony Bennett

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