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

4.104.114.84.95
Last change on this file since a625ccd was c64e4ed4, checked in by Joel Sherrill <joel.sherrill@…>, on 01/15/96 at 21:50:28

updates from Tony Bennett for PA and UNIX ports

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