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

4.104.114.84.95
Last change on this file since 5c491aef was ca201c9, checked in by Joel Sherrill <joel.sherrill@…>, on 12/05/95 at 15:28:12

minor changes so it would compile

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