Raymond Toy pushed to branch sparc64-dev at cmucl / cmucl

Commits:

2 changed files:

Changes:

  • src/lisp/Config.sparc64_sunc
    1
    # -*- Mode: makefile -*-
    
    2
    
    
    3
    # Build cmucl using Sun C compiler.  We assume cc is Sun's C compiler.
    
    4
    # If you don't have it, why are you using this Config anyway?  You're
    
    5
    # on your own if you use this Config without Sun C compiler available.
    
    6
    
    
    7
    include Config.sparc_common
    
    8
    
    
    9
    # For v8plus support (allows 64-bit integer support on V9
    
    10
    # architectures), uncomment the definitions for CC_V8PLUS and
    
    11
    # AS_V8PLUS.  The -Wa,xarch=v8plus option tells the assembler to
    
    12
    # accept v8plus instructions and generate a v8plus object files and
    
    13
    # executable.
    
    14
    #
    
    15
    # However, we should also make sure the binary is marked as v8plus by
    
    16
    # enabling AS_V8PLUS whenever we have the :sparc-v9 *feature* enabled
    
    17
    # because we really are a v8plus application by using some of the v9
    
    18
    # instructions, even if we don't use the 64-bit registers.
    
    19
    
    
    20
    ifdef FEATURE_SPARC_V9
    
    21
    # For SunStudio 11, use -xarch=v8plus.  For SunStudio 12, that is
    
    22
    # deprecated; use -m32 -xarch=sparc.
    
    23
    CC_V8PLUS = -xarch=sparc
    
    24
    AS_V8PLUS = -xarch=sparc
    
    25
    endif
    
    26
    
    
    27
    ASSEM_SRC = sparcv9-assem.S
    
    28
    CFLAGS += -xlibmieee -O
    
    29
    DEPEND_FLAGS = -xM
    
    30
    ASFLAGS = $(AS_V8PLUS)
    
    31
    OS_LINK_FLAGS = -M /usr/lib/ld/map.noexstk

  • src/lisp/sparc64-assem.S
    1
    
    
    2
    #ifdef SOLARIS
    
    3
    #define _ASM
    
    4
    #include <sys/asm_linkage.h>
    
    5
    #include <sys/psw.h>
    
    6
    #include <sys/trap.h>
    
    7
    #ifdef __STDC__
    
    8
    #define FUNCDEF(x)	.type x, \#function
    
    9
    #else
    
    10
    #define FUNCDEF(x)	.type x, #function
    
    11
    #endif
    
    12
    #else
    
    13
    #endif
    
    14
    
    
    15
    #define LANGUAGE_ASSEMBLY
    
    16
    #include "lispregs.h"
    
    17
    #include "internals.h"
    
    18
    #include "globals.h"
    
    19
    
    
    20
    #define load(sym, reg) \
    
    21
            sethi %hi(sym), reg; ld [reg+%lo(sym)], reg
    
    22
    #define store(reg, sym) \
    
    23
            sethi %hi(sym), reg_L0; st reg, [reg_L0+%lo(sym)]
    
    24
    
    
    25
    /*
    
    26
     * Our frame size needs to be large enough to hold our window, 
    
    27
     * the structure return pointer, and some temp space.  The temp space
    
    28
     * is to hold the 64-bit %o registers that might be converted to %i 
    
    29
     * registers.  A task switch will will not preserve all 64 bits of the
    
    30
     * %i registers, so we need to save our %o registers before entering C.
    
    31
     * Since %o0 and %o1 contain the return results, we do not have to save 
    
    32
     * these.
    
    33
     */
    
    34
    #ifdef v8plus	
    
    35
    #define FRAMESIZE (SA(WINDOWSIZE+4 + 6*8))
    
    36
    #else	
    
    37
    #define FRAMESIZE (SA(MINFRAME))
    
    38
    #endif
    
    39
            .seg    "text"
    
    40
            .global call_into_lisp
    
    41
    	FUNCDEF(call_into_lisp)
    
    42
    call_into_lisp:
    
    43
            save    %sp, -FRAMESIZE, %sp
    
    44
    	/* Flush all of C's register windows to the stack. */
    
    45
    	ta	ST_FLUSH_WINDOWS
    
    46
    
    
    47
            /* Save the return address. */
    
    48
            st      %i7, [%fp-4]
    
    49
    
    
    50
            /* Clear the descriptor regs. (See sparc/vm.lisp) */
    
    51
            mov     reg_ZERO, reg_A0
    
    52
            mov     reg_ZERO, reg_A1
    
    53
            mov     reg_ZERO, reg_A2
    
    54
            mov     reg_ZERO, reg_A3
    
    55
            mov     reg_ZERO, reg_A4
    
    56
            mov     reg_ZERO, reg_A5
    
    57
            mov     reg_ZERO, reg_OCFP
    
    58
            mov     reg_ZERO, reg_LRA
    
    59
            mov     reg_ZERO, reg_CODE
    
    60
    
    
    61
            /* Establish NIL */
    
    62
            set     NIL, reg_NIL
    
    63
    
    
    64
    	/* Set the pseudo-atomic flag. */
    
    65
    	set	pseudo_atomic_Value, reg_ALLOC
    
    66
    
    
    67
    	/* Turn off foreign function call. */
    
    68
            sethi   %hi(foreign_function_call_active), reg_NL0
    
    69
            st      reg_ZERO, [reg_NL0+%lo(foreign_function_call_active)]
    
    70
    
    
    71
            /* Load the rest of lisp state. */
    
    72
            load(current_dynamic_space_free_pointer, reg_NL0)
    
    73
    	add	reg_NL0, reg_ALLOC, reg_ALLOC
    
    74
            load(current_binding_stack_pointer, reg_BSP)
    
    75
            load(current_control_stack_pointer, reg_CSP)
    
    76
            load(current_control_frame_pointer, reg_OCFP)
    
    77
    
    
    78
            /* No longer atomic, and check for interrupt. */
    
    79
    	andn	reg_ALLOC, pseudo_atomic_Value, reg_ALLOC
    
    80
    	andcc	reg_ALLOC, pseudo_atomic_InterruptedValue, reg_ZERO
    
    81
    	tne	trap_PseudoAtomic
    
    82
    
    
    83
            /* Pass in the args. */
    
    84
            sll     %i2, 2, reg_NARGS
    
    85
            mov     %i1, reg_CFP
    
    86
    	mov	%i0, reg_LEXENV
    
    87
            ld      [reg_CFP+0], reg_A0
    
    88
            ld      [reg_CFP+4], reg_A1
    
    89
            ld      [reg_CFP+8], reg_A2
    
    90
            ld      [reg_CFP+12], reg_A3
    
    91
            ld      [reg_CFP+16], reg_A4
    
    92
            ld      [reg_CFP+20], reg_A5
    
    93
    
    
    94
            /* Calculate LRA */
    
    95
            set     lra + type_OtherPointer, reg_LRA
    
    96
    
    
    97
            /* Indirect closure */
    
    98
            ld      [reg_LEXENV+CLOSURE_FUNCTION_OFFSET], reg_CODE
    
    99
    
    
    100
            jmp     reg_CODE+FUNCTION_CODE_OFFSET
    
    101
            nop
    
    102
    
    
    103
            .align  8
    
    104
    lra:
    
    105
            .word   type_ReturnPcHeader
    
    106
    
    
    107
            /* Blow off any extra values. */
    
    108
            mov     reg_OCFP, reg_CSP
    
    109
            nop
    
    110
    
    
    111
            /* Return the one value. */
    
    112
            mov     reg_A0, %i0
    
    113
    
    
    114
            /* Turn on pseudo_atomic */
    
    115
    	or	reg_ALLOC, pseudo_atomic_Value, reg_ALLOC
    
    116
    
    
    117
            /* Store LISP state */
    
    118
    	andn	reg_ALLOC, lowtag_Mask, reg_NL1
    
    119
            store(reg_NL1,current_dynamic_space_free_pointer)
    
    120
            store(reg_BSP,current_binding_stack_pointer)
    
    121
            store(reg_CSP,current_control_stack_pointer)
    
    122
            store(reg_CFP,current_control_frame_pointer)
    
    123
    
    
    124
            /* No longer in Lisp. */
    
    125
            store(reg_NL1,foreign_function_call_active)
    
    126
    
    
    127
            /* Were we interrupted? */
    
    128
    	andn	reg_ALLOC, pseudo_atomic_Value, reg_ALLOC
    
    129
    	andcc	reg_ALLOC, pseudo_atomic_InterruptedValue, reg_ZERO
    
    130
    	tne	trap_PseudoAtomic
    
    131
    
    
    132
            /* Back to C we go. */
    
    133
    	ld	[%sp+FRAMESIZE-4], %i7
    
    134
            ret
    
    135
            restore	%sp, FRAMESIZE, %sp
    
    136
    	SET_SIZE(call_into_lisp)
    
    137
    
    
    138
    
    
    139
    
    
    140
            .global call_into_c
    
    141
    	FUNCDEF(call_into_c)
    
    142
    call_into_c:
    
    143
    #ifdef v8plus
    
    144
    	stx	%o2, [%fp - 8 - 1*8]
    
    145
    	stx	%o3, [%fp - 8 - 2*8]
    
    146
    	stx	%o4, [%fp - 8 - 3*8]
    
    147
    	stx	%o5, [%fp - 8 - 4*8]
    
    148
    	stx	%o6, [%fp - 8 - 5*8]
    
    149
    	stx	%o7, [%fp - 8 - 6*8]
    
    150
    #endif		
    
    151
            /* Build a lisp stack frame */
    
    152
            mov     reg_CFP, reg_OCFP
    
    153
            mov     reg_CSP, reg_CFP
    
    154
            add     reg_CSP, 32, reg_CSP
    
    155
            st      reg_OCFP, [reg_CFP]
    
    156
            st      reg_CODE, [reg_CFP+8]
    
    157
    
    
    158
            /* Turn on pseudo-atomic. */
    
    159
    	or	reg_ALLOC, pseudo_atomic_Value, reg_ALLOC
    
    160
    
    
    161
    	/* Convert the return address to an offset and save it on the stack. */
    
    162
    	sub	reg_LIP, reg_CODE, reg_L0
    
    163
    	add	reg_L0, type_OtherPointer, reg_L0
    
    164
    	st	reg_L0, [reg_CFP+4]
    
    165
    
    
    166
            /* Store LISP state */
    
    167
            store(reg_BSP,current_binding_stack_pointer)
    
    168
            store(reg_CSP,current_control_stack_pointer)
    
    169
            store(reg_CFP,current_control_frame_pointer)
    
    170
    
    
    171
    	/* Use reg_CFP as a work register, and restore it */
    
    172
    	andn	reg_ALLOC, lowtag_Mask, reg_CFP
    
    173
            store(reg_CFP,current_dynamic_space_free_pointer)
    
    174
    	load(current_control_frame_pointer, reg_CFP)
    
    175
    
    
    176
            /* No longer in Lisp. */
    
    177
            store(reg_CSP,foreign_function_call_active)
    
    178
    
    
    179
            /* Were we interrupted? */
    
    180
    	andn	reg_ALLOC, pseudo_atomic_Value, reg_ALLOC
    
    181
    	andcc	reg_ALLOC, pseudo_atomic_InterruptedValue, reg_ZERO
    
    182
    	tne	trap_PseudoAtomic
    
    183
    
    
    184
            /* Into C we go. */
    
    185
            call    reg_CFUNC
    
    186
            nop
    
    187
    
    
    188
    	/*
    
    189
    	 * Note: C calling conventions (32-bit) say that %o0 and %o1
    
    190
    	 * are used to return function results.  In particular 64-bit
    
    191
    	 * results are in %o0 (hi) and %o1 (low).  
    
    192
    	 */
    
    193
    	
    
    194
            /* Re-establish NIL */
    
    195
            set     NIL, reg_NIL
    
    196
    
    
    197
    	/* Atomic. */
    
    198
    	set	pseudo_atomic_Value, reg_ALLOC
    
    199
    
    
    200
            /* No longer in foreign function call. */
    
    201
            sethi   %hi(foreign_function_call_active), reg_NL2
    
    202
            st      reg_ZERO, [reg_NL2+%lo(foreign_function_call_active)]
    
    203
    
    
    204
            /* Load the rest of lisp state. */
    
    205
            load(current_dynamic_space_free_pointer, reg_NL2)
    
    206
    	add	reg_NL2, reg_ALLOC, reg_ALLOC
    
    207
            load(current_binding_stack_pointer, reg_BSP)
    
    208
            load(current_control_stack_pointer, reg_CSP)
    
    209
            load(current_control_frame_pointer, reg_CFP)
    
    210
    
    
    211
    	/* Get the return address back. */
    
    212
    	ld	[reg_CFP+4], reg_LIP
    
    213
    	ld	[reg_CFP+8], reg_CODE
    
    214
    	add	reg_LIP, reg_CODE, reg_LIP
    
    215
    	sub	reg_LIP, type_OtherPointer, reg_LIP
    
    216
    
    
    217
            /* No longer atomic. */
    
    218
    	andn	reg_ALLOC, pseudo_atomic_Value, reg_ALLOC
    
    219
    	andcc	reg_ALLOC, pseudo_atomic_InterruptedValue, reg_ZERO
    
    220
    	tne	trap_PseudoAtomic
    
    221
    
    
    222
            /* Reset the lisp stack. */
    
    223
            /* Note: OCFP is in one of the locals, it gets preserved across C. */
    
    224
            mov     reg_CFP, reg_CSP
    
    225
            mov     reg_OCFP, reg_CFP
    
    226
    
    
    227
    #ifdef v8plus
    
    228
    	ldx	[%fp - 8 - 1*8], %o2
    
    229
    	ldx	[%fp - 8 - 2*8], %o3
    
    230
    	ldx	[%fp - 8 - 3*8], %o4
    
    231
    	ldx	[%fp - 8 - 4*8], %o5
    
    232
    	ldx	[%fp - 8 - 5*8], %o6
    
    233
    	ldx	[%fp - 8 - 6*8], %o7
    
    234
    #endif		
    
    235
            /* And back into lisp. */
    
    236
            ret
    
    237
            nop
    
    238
    
    
    239
    	SET_SIZE(call_into_c)
    
    240
    
    
    241
    #if 0
    
    242
    /* undefined_tramp and closure_tramp are now Lisp assembly routines.
    
    243
     * so we don't need these anymore.  Leave them here for a bit so 
    
    244
     * we can look at the "real" versions for a while.  But eventually,
    
    245
     * remove these.
    
    246
     */
    
    247
            .global _undefined_tramp
    
    248
    	FUNCDEF(_undefined_tramp)
    
    249
            .align  8
    
    250
            .byte   0
    
    251
    _undefined_tramp:
    
    252
            .byte   0, 0, type_FunctionHeader
    
    253
            .word   _undefined_tramp
    
    254
            .word   NIL
    
    255
            .word   NIL
    
    256
            .word   NIL
    
    257
            .word   NIL
    
    258
    
    
    259
    	b	1f
    
    260
            unimp   trap_Cerror
    
    261
            /* Number of argument bytes */
    
    262
            .byte	4
    
    263
            .byte	UNDEFINED_SYMBOL_ERROR
    
    264
            /* Escape to create 16bit number from following two bytes, 
    
    265
    	   in little-endian order */
    
    266
            .byte	254
    
    267
            /* SC_OFFSET(sc_DescriptorReg,reg_FDEFN) */
    
    268
    	.byte	SC_OFFSET_LO(sc_DescriptorReg,reg_FDEFN_NUM)
    
    269
    	.byte	SC_OFFSET_HI(sc_DescriptorReg,reg_FDEFN_NUM)
    
    270
    		
    
    271
    	.align	4
    
    272
    1:
    
    273
    	ld	[reg_FDEFN+FDEFN_RAW_ADDR_OFFSET], reg_CODE
    
    274
    	jmp	reg_CODE+FUNCTION_CODE_OFFSET
    
    275
    	nop
    
    276
    	SET_SIZE(_undefined_tramp)
    
    277
    
    
    278
    	.global	_closure_tramp
    
    279
    	FUNCDEF(_closure_tramp)
    
    280
    	.align	8
    
    281
    	.byte	0
    
    282
    _closure_tramp:
    
    283
    	.byte	0, 0, type_FunctionHeader
    
    284
    	.word	_closure_tramp
    
    285
    	.word	NIL
    
    286
            .word   NIL
    
    287
    	.word	NIL
    
    288
    	.word	NIL
    
    289
    
    
    290
    	ld	[reg_FDEFN+FDEFN_FUNCTION_OFFSET], reg_LEXENV
    
    291
    	ld	[reg_LEXENV+CLOSURE_FUNCTION_OFFSET], reg_CODE
    
    292
    	jmp	reg_CODE+FUNCTION_CODE_OFFSET
    
    293
    	nop
    
    294
    	SET_SIZE(_closure_tramp)
    
    295
    #endif
    
    296
    
    
    297
    
    
    298
    /*
    
    299
     * Function-end breakpoint magic.
    
    300
     */
    
    301
    
    
    302
    	.text
    
    303
    	.align	8
    
    304
    	.global	function_end_breakpoint_guts
    
    305
    function_end_breakpoint_guts:
    
    306
    	.word	type_ReturnPcHeader
    
    307
    	b	1f
    
    308
    	nop
    
    309
    	mov	reg_CSP, reg_OCFP
    
    310
    	add	4, reg_CSP, reg_CSP
    
    311
    	mov	4, reg_NARGS
    
    312
    	mov	reg_NIL, reg_A1
    
    313
    	mov	reg_NIL, reg_A2
    
    314
    	mov	reg_NIL, reg_A3
    
    315
    	mov	reg_NIL, reg_A4
    
    316
    	mov	reg_NIL, reg_A5
    
    317
    1:
    
    318
    
    
    319
    	.global	function_end_breakpoint_trap
    
    320
    function_end_breakpoint_trap:
    
    321
    	unimp	trap_FunctionEndBreakpoint
    
    322
    	b	1b
    
    323
    	nop
    
    324
    
    
    325
    	.global	function_end_breakpoint_end
    
    326
    function_end_breakpoint_end:
    
    327
    
    
    328
    	.global flush_icache
    
    329
    	FUNCDEF(flush_icache)
    
    330
    flush_icache:
    
    331
            add %o0,%o1,%o2
    
    332
    1:      iflush %o0			! flush instruction cache
    
    333
            add %o0,8,%o0
    
    334
            cmp %o0,%o2
    
    335
            blt 1b
    
    336
            nop
    
    337
    	retl				! return from leaf routine
    
    338
            nop
    
    339
    	SET_SIZE(flush_icache)
    
    340
    
    
    341
            .global do_pending_interrupt
    
    342
    	FUNCDEF(do_pending_interrupt)
    
    343
    do_pending_interrupt:
    
    344
    	unimp trap_PendingInterrupt
    
    345
    	retl
    
    346
    	nop
    
    347
    	SET_SIZE(do_pending_interrupt)
    
    348
    
    
    349
    #ifdef trap_DynamicSpaceOverflowError
    
    350
    	.global do_dynamic_space_overflow_error
    
    351
    	FUNCDEF(do_dynamic_space_overflow_error)
    
    352
    do_dynamic_space_overflow_error:	
    
    353
    	unimp trap_DynamicSpaceOverflowError
    
    354
    	retl
    
    355
    	nop
    
    356
    	SET_SIZE(do_dynamic_space_overflow_error)		
    
    357
    #endif				
    
    358
    
    
    359
    #ifdef trap_DynamicSpaceOverflowWarning
    
    360
    	.global do_dynamic_space_overflow_warning
    
    361
    	FUNCDEF(do_dynamic_space_overflow_warning)
    
    362
    do_dynamic_space_overflow_warning:	
    
    363
    	unimp trap_DynamicSpaceOverflowWarning
    
    364
    	retl
    
    365
    	nop
    
    366
    	SET_SIZE(do_dynamic_space_overflow_warning)		
    
    367
    #endif				
    
    368
    		
    
    369
    #ifdef LINKAGE_TABLE
    
    370
    /*
    
    371
     * Call into C code to resolve a linkage entry.
    
    372
     *
    
    373
     * We get here by Lisp calling call_into_c with an address of the
    
    374
     * desired function which is contained in the register reg_CFUNC (aka
    
    375
     * %i4, aka %r28).  This is the address of the entry in the linkage
    
    376
     * table, which is what we need to figure out what function we really
    
    377
     * wanted.
    
    378
     *
    
    379
     * Note that because we get here from call_into_c, all necessary live
    
    380
     * registers have been saved, including FP registers.  Hence, no need
    
    381
     * to save them.
    
    382
     */
    
    383
    	.global lazy_resolve_linkage
    
    384
    	.global resolve_linkage_tramp
    
    385
    	FUNCDEF(resolve_linkage_tramp)
    
    386
    resolve_linkage_tramp:
    
    387
    	/*
    
    388
    	 * At this point, all of the global %g registers have been
    
    389
    	 * saved by call_into_c, so we can use them as temps.  %g2,
    
    390
    	 * aka reg_NIL, aka null-tn is a good choice.  reg_L0 contains
    
    391
    	 * the address of the jmpl instruction in the linkage jump
    
    392
    	 * table.  (See sparc-arch.c.)
    
    393
    	 */
    
    394
    
    
    395
    	mov	reg_L0, reg_NIL
    
    396
    		
    
    397
    	/* 
    
    398
    	 * New stack frame so the %o regs become %i.  We can't touch
    
    399
    	 * the original %o because they contain the parameters to the
    
    400
    	 * function!
    
    401
    	 */
    
    402
    	save	%sp, -FRAMESIZE, %sp
    
    403
    
    
    404
    	/* %g2 tells where we came from in the linkage table */
    
    405
    	call	lazy_resolve_linkage
    
    406
    	mov	reg_NIL, %o0		! in the delay slot
    
    407
    
    
    408
    	mov	%o0, reg_NIL
    
    409
    	restore	%sp, FRAMESIZE, %sp
    
    410
    
    
    411
    	/* And away we go! */
    
    412
    	jmp	reg_NIL
    
    413
    	nop
    
    414
    	
    
    415
    	SET_SIZE(resolve_linkage_tramp)						
    
    416
    		
    
    417
    	.global undefined_foreign_symbol_trap
    
    418
    	FUNCDEF(undefined_foreign_symbol_trap)
    
    419
    /*
    
    420
     * When we get called, %o0 contains the address of the data_vector object 
    
    421
     * which is a string naming the bad symbol.
    
    422
     */
    
    423
    undefined_foreign_symbol_trap:
    
    424
    	/*
    
    425
    	   Need to restore all the global registers with the Lisp values that 
    
    426
    	   were saved away in call_into_c.  (This routine is only called from 
    
    427
    	   os_link_one_symbol, which is called from resolve_linkage_tramp, which 
    
    428
    	   is called from call_into_c.)
    
    429
    
    
    430
    	   The global registers are volatile across function calls, so who
    
    431
    	   knows what values have been they contain now!
    
    432
    		
    
    433
    	*/
    
    434
    
    
    435
    	load(current_dynamic_space_free_pointer, reg_ALLOC)
    
    436
            load(current_binding_stack_pointer, reg_BSP)
    
    437
            load(current_control_stack_pointer, reg_CSP)
    
    438
            load(current_control_frame_pointer, reg_CFP)
    
    439
    		
    
    440
    	set	NIL, reg_NIL
    
    441
    
    
    442
    	mov	%o0, reg_A0			
    
    443
    	unimp	trap_Error
    
    444
    	.byte	4	/* Number of argument bytes */
    
    445
    	.byte	UNDEFINED_FOREIGN_SYMBOL_ERROR
    
    446
            /* Escape to create 16bit number from following two bytes, in 
    
    447
    	   little-endian order */
    
    448
            .byte	254
    
    449
    	.byte	SC_OFFSET_LO(sc_DescriptorReg, reg_A0_NUM)
    
    450
    	.byte	SC_OFFSET_HI(sc_DescriptorReg, reg_A0_NUM)
    
    451
    	.align	4
    
    452
    					
    
    453
    #endif
    
    454
    /*
    
    455
     * Save the FPU state.  %o0 contains a pointer to where we can 
    
    456
     * store our state.
    
    457
     */			
    
    458
    
    
    459
    /* 
    
    460
     * Note we only save the 16 double-float registers (which saves
    
    461
     * the 32 single-float values too, I think).  If we're compiling for 
    
    462
     * a sparc v9, the Lisp code can actually use all 32 double-float 
    
    463
     * registers.  For later.
    
    464
     */
    
    465
    	.global fpu_save
    
    466
    	FUNCDEF(fpu_save)
    
    467
    fpu_save:			
    
    468
    	std	%f0, [%o0 + 4*0]
    
    469
    	std	%f2, [%o0 + 4*2]	
    
    470
    	std	%f4, [%o0 + 4*4]	
    
    471
    	std	%f6, [%o0 + 4*6]	
    
    472
    	std	%f8, [%o0 + 4*8]	
    
    473
    	std	%f10, [%o0 + 4*10]	
    
    474
    	std	%f12, [%o0 + 4*12]	
    
    475
    	std	%f14, [%o0 + 4*14]	
    
    476
    	std	%f16, [%o0 + 4*16]	
    
    477
    	std	%f18, [%o0 + 4*18]	
    
    478
    	std	%f20, [%o0 + 4*20]	
    
    479
    	std	%f22, [%o0 + 4*22]	
    
    480
    	std	%f24, [%o0 + 4*24]	
    
    481
    	std	%f26, [%o0 + 4*26]	
    
    482
    	std	%f28, [%o0 + 4*28]
    
    483
    	std	%f30, [%o0 + 4*30]	
    
    484
    #ifdef FEATURE_SPARC_V9
    
    485
    	std	%f32, [%o0 + 4*32]	
    
    486
    	std	%f34, [%o0 + 4*34]	
    
    487
    	std	%f36, [%o0 + 4*36]	
    
    488
    	std	%f38, [%o0 + 4*38]	
    
    489
    	std	%f40, [%o0 + 4*40]	
    
    490
    	std	%f42, [%o0 + 4*42]	
    
    491
    	std	%f44, [%o0 + 4*44]	
    
    492
    	std	%f46, [%o0 + 4*46]	
    
    493
    	std	%f48, [%o0 + 4*48]	
    
    494
    	std	%f50, [%o0 + 4*50]	
    
    495
    	std	%f52, [%o0 + 4*52]	
    
    496
    	std	%f54, [%o0 + 4*54]	
    
    497
    	std	%f56, [%o0 + 4*56]	
    
    498
    	std	%f58, [%o0 + 4*58]	
    
    499
    	std	%f60, [%o0 + 4*60]	
    
    500
    	std	%f62, [%o0 + 4*62]	
    
    501
    	st	%fsr, [%o0 + 4*64]
    
    502
    #else
    
    503
    	st	%fsr, [%o0 + 4*32]
    
    504
    #endif
    
    505
    	retl
    
    506
    	nop
    
    507
    	SET_SIZE(fpu_save)						
    
    508
    
    
    509
    	.global fpu_restore
    
    510
    	FUNCDEF(fpu_restore)
    
    511
    fpu_restore:			
    
    512
    	ldd	[%o0 + 4*0], %f0
    
    513
    	ldd	[%o0 + 4*2], %f2	
    
    514
    	ldd	[%o0 + 4*4], %f4	
    
    515
    	ldd	[%o0 + 4*6], %f6	
    
    516
    	ldd	[%o0 + 4*8], %f8	
    
    517
    	ldd	[%o0 + 4*10], %f10	
    
    518
    	ldd	[%o0 + 4*12], %f12	
    
    519
    	ldd	[%o0 + 4*14], %f14	
    
    520
    	ldd	[%o0 + 4*16], %f16	
    
    521
    	ldd	[%o0 + 4*18], %f18	
    
    522
    	ldd	[%o0 + 4*20], %f20	
    
    523
    	ldd	[%o0 + 4*22], %f22	
    
    524
    	ldd	[%o0 + 4*24], %f24	
    
    525
    	ldd	[%o0 + 4*26], %f26	
    
    526
    	ldd	[%o0 + 4*28], %f28
    
    527
    	ldd	[%o0 + 4*30], %f30	
    
    528
    #ifdef FEATURE_SPARC_V9
    
    529
    	ldd	[%o0 + 4*32], %f32	
    
    530
    	ldd	[%o0 + 4*34], %f34	
    
    531
    	ldd	[%o0 + 4*36], %f36	
    
    532
    	ldd	[%o0 + 4*38], %f38	
    
    533
    	ldd	[%o0 + 4*40], %f40	
    
    534
    	ldd	[%o0 + 4*42], %f42	
    
    535
    	ldd	[%o0 + 4*44], %f44	
    
    536
    	ldd	[%o0 + 4*46], %f46	
    
    537
    	ldd	[%o0 + 4*48], %f48	
    
    538
    	ldd	[%o0 + 4*50], %f50	
    
    539
    	ldd	[%o0 + 4*52], %f52	
    
    540
    	ldd	[%o0 + 4*54], %f54	
    
    541
    	ldd	[%o0 + 4*56], %f56	
    
    542
    	ldd	[%o0 + 4*58], %f58	
    
    543
    	ldd	[%o0 + 4*60], %f60	
    
    544
    	ldd	[%o0 + 4*62], %f62	
    
    545
    	ld	[%o0 + 4*64], %fsr
    
    546
    #else
    
    547
    	ld	[%o0 + 4*32], %fsr
    
    548
    #endif
    
    549
    	retl
    
    550
    	nop
    
    551
    	SET_SIZE(fpu_restore)						
    
    552
    
    
    553
    	.global save_context
    
    554
    	FUNCDEF(save_context)
    
    555
    save_context:
    
    556
    	ta	ST_FLUSH_WINDOWS	! flush register windows
    
    557
    	retl				! return from leaf routine
    
    558
    	nop
    
    559
    	SET_SIZE(save_context)
    
    560
    /*
    
    561
     * Local variables:
    
    562
     * tab-width: 8
    
    563
     * End:
    
    564
     */						
    
    565