source: trunk/hal/tsar_mips32/core/hal_context.c @ 307

Last change on this file since 307 was 296, checked in by alain, 5 years ago

Several modifs in the generic scheduler and in the hal_context to
fix the context switch mechanism.

File size: 19.8 KB
Line 
1/*
2 * hal_context.c - implementation of Thread Context API for TSAR-MIPS32
3 *
4 * Author  Alain Greiner    (2016)
5 *
6 * Copyright (c)  UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH.is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH.is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH.; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <hal_types.h>
25#include <memcpy.h>
26#include <thread.h>
27#include <string.h>
28#include <process.h>
29#include <printk.h>
30#include <vmm.h>
31#include <core.h>
32#include <cluster.h>
33
34#include <hal_context.h>
35
36/////////////////////////////////////////////////////////////////////////////////////////
37//       Define various SR values for TSAR-MIPS32
38/////////////////////////////////////////////////////////////////////////////////////////
39
40#define SR_USR_MODE       0xFC11
41#define SR_USR_MODE_FPU   0x2000FC11
42#define SR_SYS_MODE       0xFC00
43
44/////////////////////////////////////////////////////////////////////////////////////////
45// These structuree defines the cpu_context anf fpu_context for TSAR MIPS32.
46// These registers are saved/restored at each context switch.
47// WARNING : update the hal_***_context_save() and hal_***_context_restore()
48//           functions when modifying this structure, and check the two
49//           CONFIG_CPU_CTX_SIZE & CONFIGFPU_CTX_SIZE configuration parameterss.
50/////////////////////////////////////////////////////////////////////////////////////////
51
52typedef struct hal_cpu_context_s
53{
54    uint32_t c0_epc;     // slot 0
55    uint32_t at_01;      // slot 1
56    uint32_t v0_02;      // slot 2
57    uint32_t v1_03;      // slot 3
58    uint32_t a0_04;      // slot 4
59    uint32_t a1_05;      // slot 5
60    uint32_t a2_06;      // slot 6
61    uint32_t a3_07;      // slot 7
62
63    uint32_t t0_08;      // slot 8
64    uint32_t t1_09;      // slot 9
65    uint32_t t2_10;      // slot 10
66    uint32_t t3_11;      // slot 11
67    uint32_t t4_12;      // slot 12
68    uint32_t t5_13;      // slot 13
69    uint32_t t6_14;      // slot 14
70    uint32_t t7_15;      // slot 15
71
72        uint32_t s0_16;      // slot 16
73        uint32_t s1_17;      // slot 17
74        uint32_t s2_18;      // slot 18
75        uint32_t s3_19;      // slot 19
76        uint32_t s4_20;      // slot 20
77        uint32_t s5_21;      // slot 21
78        uint32_t s6_22;      // slot 22
79        uint32_t s7_23;      // slot 23
80
81    uint32_t t8_24;      // slot 24
82    uint32_t t8_25;      // slot 25
83    uint32_t hi_26;      // slot 26
84    uint32_t lo_27;      // slot 27
85    uint32_t gp_28;      // slot 28
86        uint32_t sp_29;      // slot 29
87        uint32_t fp_30;      // slot 30
88        uint32_t ra_31;      // slot 31
89
90        uint32_t c2_ptpr;    // slot 32
91        uint32_t c2_mode;    // slot 33
92
93        uint32_t c0_sr;      // slot 34
94        uint32_t c0_th;      // slot 35
95} 
96hal_cpu_context_t;
97
98/////////////////////////////////////////////////////////////////////////////////////////
99// This structure defines the fpu_context for TSAR MIPS32.
100/////////////////////////////////////////////////////////////////////////////////////////
101
102typedef struct hal_fpu_context_s
103{
104        uint32_t   fpu_regs[32];     
105}
106hal_fpu_context_t;
107
108
109
110/////////////////////////////////////////////////////////////////////////////////////////
111//        CPU context access functions
112/////////////////////////////////////////////////////////////////////////////////////////
113
114
115/////////////////////////////////////////////////////////////////////////////////////////
116// Seven registers are initialised by this function:
117// GPR : sp_29 / fp_30 / ra_31
118// CP0 : c0_sr / c0_th
119// CP2 : c2_ptpr / c2_mode
120/////////////////////////////////////////////////////////////////////////////////////////
121error_t hal_cpu_context_create( thread_t * thread )
122{
123    kmem_req_t  req;
124
125    context_dmsg("\n[INFO] %s : enters for thread %x in process %x\n",
126                 __FUNCTION__ , thread->trdid , thread->process->pid );
127
128    // allocate memory for cpu_context
129    req.type   = KMEM_CPU_CTX;
130    req.size   = sizeof(hal_cpu_context_t);
131    req.flags  = AF_KERNEL | AF_ZERO;
132
133    hal_cpu_context_t * context = (hal_cpu_context_t *)kmem_alloc( &req );
134    if( context == NULL ) return ENOMEM;
135
136    // set cpu context pointer in thread
137    thread->cpu_context = (void*)context;
138
139    // stack pointer, status register and mmu_mode depends on thread type
140        uint32_t sp_29;
141    uint32_t c0_sr;
142    uint32_t c2_mode;
143    if( thread->type == THREAD_USER )
144    {
145        sp_29   = ((uint32_t)thread->u_stack_base) + thread->u_stack_size;
146        c0_sr   = SR_USR_MODE;
147        c2_mode = 0xF;
148    }
149    else
150    {
151        sp_29   = ((uint32_t)thread->k_stack_base) + thread->k_stack_size;
152        c0_sr   = SR_SYS_MODE;
153        c2_mode = 0x3;
154    }
155
156    // align stack pointer on a double word boundary
157        sp_29 = (sp_29 - 8) & (~ 0x7);
158
159    // initialise context
160        context->sp_29      = sp_29; 
161        context->fp_30      = sp_29;                          // TODO check this [AG]
162    context->ra_31      = (uint32_t)thread->entry_func;
163        context->c0_sr      = c0_sr;
164        context->c0_th      = (uint32_t)thread; 
165        context->c2_ptpr    = (uint32_t)((thread->process->vmm.gpt.ppn) >> 1);
166        context->c2_mode    = c2_mode;
167
168    context_dmsg("\n[INFO] %s : exit for thread %x in process %x / ra = %x\n",
169                 __FUNCTION__ , thread->trdid , thread->process->pid , context->ra_31 );
170
171    return 0;
172}  // end hal_cpu_context_create()
173
174/////////////////////////////////////////////////
175void hal_cpu_context_display( thread_t * thread )
176{
177    hal_cpu_context_t * ctx = (hal_cpu_context_t *)thread->cpu_context;
178
179    printk("\n*** cpu_context for thread %x in cluster %x / ctx = %x ***\n" 
180           " gp_28   = %X    sp_29   = %X    ra_31   = %X\n" 
181           " c0_sr   = %X    c0_epc  = %X    c0_th = %X\n"
182           " c2_ptpr = %X    c2_mode = %X\n",
183           thread->trdid, local_cxy, ctx,
184           ctx->gp_28   , ctx->sp_29   , ctx->ra_31,
185           ctx->c0_sr   , ctx->c0_epc  , ctx->c0_th,
186           ctx->c2_ptpr , ctx->c2_mode );
187}
188
189/////////////////////////////////////////////////////////////////////////////////////////
190// These registers are saved to CPU context defined by <ctx> argument.
191// - GPR : all, but (zero, k0, k1), plus (hi, lo)
192// - CP0 : c0_th , c0_sr
193// - CP2 : c2_ptpr , C2_mode, C2_epc
194/////////////////////////////////////////////////////////////////////////////////////////
195void hal_cpu_context_save( void * ctx )
196{
197    asm volatile(
198    ".set noat                     \n"
199    ".set noreorder                \n"
200    "move    $26,   $4             \n"   /* $26 <= &ctx */
201
202    "mfc0    $27,   $14            \n"
203    "sw      $27,   0*4($26)       \n"   /* save c0_epc to slot 0 */
204 
205    "sw      $1,    1*4($26)       \n"
206    "sw      $2,    2*4($26)       \n"
207    "sw      $3,    3*4($26)       \n"
208    "sw      $4,    4*4($26)       \n"
209    "sw      $5,    5*4($26)       \n"
210    "sw      $6,    6*4($26)       \n"
211    "sw      $7,    7*4($26)       \n"
212
213    "sw      $8,    8*4($26)       \n"
214    "sw      $9,    9*4($26)       \n"
215    "sw      $10,  10*4($26)       \n"
216    "sw      $11,  11*4($26)       \n"
217    "sw      $12,  12*4($26)       \n"
218    "sw      $13,  13*4($26)       \n"
219    "sw      $14,  14*4($26)       \n"
220    "sw      $15,  15*4($26)       \n"
221
222    "sw      $16,  16*4($26)       \n"
223    "sw      $17,  17*4($26)       \n"
224    "sw      $18,  18*4($26)       \n"
225    "sw      $19,  19*4($26)       \n"
226    "sw      $20,  20*4($26)       \n"
227    "sw      $21,  21*4($26)       \n"
228    "sw      $22,  22*4($26)       \n"
229    "sw      $23,  23*4($26)       \n"
230
231    "sw      $24,  24*4($26)       \n"
232    "sw      $25,  25*4($26)       \n"
233
234    "mfhi    $27                   \n"
235    "sw      $27,  26*4($26)       \n"   /* save hi to slot 26 */
236    "mflo    $27                   \n"
237    "sw      $27,  27*4($26)       \n"   /* save lo to slot 27 */
238
239    "sw      $28,  28*4($26)       \n"
240    "sw      $29,  29*4($26)       \n"
241    "sw      $30,  30*4($26)       \n"
242    "sw      $31,  31*4($26)       \n"
243
244        "mfc2    $27,  $0              \n"
245        "sw      $27,  32*4($26)       \n"   /* save c2_ptpr to slot 32 */
246        "mfc2    $27,  $1              \n"
247        "sw      $27,  33*4($26)       \n"   /* save c2_mode to slot 33 */
248
249    "mfc0        $27,  $12             \n"
250        "sw      $27,  34*4($26)       \n"   /* save c0_sr to slot 34 */
251    "mfc0        $27,  $4, 2           \n"
252        "sw      $27,  35*4($26)       \n"   /* save c0_th to slot 35 */
253
254    "sync                          \n"
255
256    "move    $4,   $27               \n"
257    "jal     hal_cpu_context_display \n"    /* display context */
258    "nop                             \n"
259
260        ".set reorder                  \n"
261    ".set at                       \n"
262    : : : "$26" , "$27" , "memory" ); 
263}
264
265/////////////////////////////////////////////////////////////////////////////////////////
266// These registers are restored from cpu context defined by <ctx> argument:
267// - GPR : all, but (zero, k0, k1), plus (hi, lo)
268// - CP0 : c0_th , c0_sr
269// - CP2 : c2_ptpr , C2_mode
270/////////////////////////////////////////////////////////////////////////////////////////
271void hal_cpu_context_restore( void * ctx )
272{
273    asm volatile(
274    ".set noat                     \n"
275    ".set noreorder                \n"
276    "move    $26,   $4             \n"   /* $26 <= &ctx */
277
278    "lw      $4,   35*4($26)         \n"
279    "jal     hal_cpu_context_display \n"    /* display context */ 
280    "nop                             \n"
281
282    "lw      $27,   0*4($26)       \n"
283    "mtc0    $27,   $14            \n"   /* restore C0_epc from slot 0 */
284
285    "lw      $1,    1*4($26)       \n"
286    "lw      $2,    2*4($26)       \n"
287    "lw      $3,    3*4($26)       \n"
288    "lw      $4,    4*4($26)       \n"
289    "lw      $5,    5*4($26)       \n"
290    "lw      $6,    6*4($26)       \n"
291    "lw      $7,    7*4($26)       \n"
292
293    "lw      $8,    8*4($26)       \n"
294    "lw      $9,    9*4($26)       \n"
295    "lw      $10,  10*4($26)       \n"
296    "lw      $11,  11*4($26)       \n"
297    "lw      $12,  12*4($26)       \n"
298    "lw      $13,  13*4($26)       \n"
299    "lw      $14,  14*4($26)       \n"
300    "lw      $15,  15*4($26)       \n"
301
302        "lw      $16,  16*4($26)       \n"
303        "lw      $17,  17*4($26)       \n"
304    "lw      $18,  18*4($26)       \n"
305    "lw      $19,  19*4($26)       \n"
306    "lw      $20,  20*4($26)       \n"
307    "lw      $21,  21*4($26)       \n"
308    "lw      $22,  22*4($26)       \n"
309    "lw      $23,  23*4($26)       \n"
310
311    "lw      $24,  24*4($26)       \n"
312    "lw      $25,  25*4($26)       \n"
313
314    "lw      $27,  26*4($26)       \n"
315    "mthi    $27                   \n"   /* restore hi from slot 26 */
316    "lw      $27,  27*4($26)       \n"
317    "mtlo    $27                   \n"   /* restote lo from slot 27 */
318
319        "lw      $28,  28*4($26)       \n"
320        "lw      $29,  29*4($26)       \n"
321        "lw      $30,  30*4($26)       \n"
322        "lw      $31,  31*4($26)       \n"
323
324        "lw      $27,  32*4($26)       \n"
325        "mtc2    $27,  $0              \n"   /* restore c2_ptpr from slot 32 */
326        "lw      $27,  33*4($26)       \n"
327        "mtc2    $27,  $1              \n"   /* restore c2_mode from slot 33 */
328
329        "lw      $27,  34*4($26)       \n"
330    "mtc0        $27,  $12             \n"   /* restore c0_sr from slot 34 */
331        "lw      $27,  35*4($26)       \n"
332    "mtc0        $27,  $4, 2           \n"   /* restore co_th from slot 35 */
333
334    ".set reorder                  \n"
335    ".set at                       \n"
336    : : : "$26" , "$27" ); 
337}
338
339/////////////////////////////////////////////
340error_t hal_cpu_context_copy( thread_t * dst,
341                              thread_t * src )
342{
343    kmem_req_t  req;
344
345    // allocate memory for dst cpu_context
346    req.type   = KMEM_CPU_CTX;
347    req.size   = sizeof(hal_cpu_context_t);
348    req.flags  = AF_KERNEL | AF_ZERO;
349
350    hal_cpu_context_t * dst_context = (hal_cpu_context_t *)kmem_alloc( &req );
351    if( dst_context == NULL ) return ENOMEM;
352
353    // set cpu context pointer in dst thread
354    dst->cpu_context = dst_context;
355
356    // get cpu context pointer from src thread
357    hal_cpu_context_t * src_context = src->cpu_context;
358
359    // copy CPU context from src to dst
360    memcpy( dst_context , src_context , sizeof(hal_cpu_context_t) );
361
362    return 0;
363}  // end hal_cpu_context_copy()
364
365/////////////////////////////////////////////////
366void hal_cpu_context_destroy( thread_t * thread )
367{
368    kmem_req_t  req;
369
370    req.type = KMEM_CPU_CTX;
371    req.ptr  = thread->cpu_context;
372    kmem_free( &req );
373
374}  // end hal_cpu_context_destroy()
375
376///////////////////////////////////////////////////
377error_t hal_fpu_context_create( thread_t * thread )
378{
379    kmem_req_t  req;
380
381    // allocate memory for uzone
382    req.type   = KMEM_FPU_CTX;
383    req.size   = sizeof(hal_fpu_context_t);
384    req.flags  = AF_KERNEL | AF_ZERO;
385
386    hal_fpu_context_t * context = (hal_fpu_context_t *)kmem_alloc( &req );
387    if( context == NULL ) return ENOMEM;
388
389    // set fpu context pointer in thread
390    thread->fpu_context = (void*)context;
391   
392    return 0;
393}  // hal_fpu_context_create()
394
395/////////////////////////////////////////////
396error_t hal_fpu_context_copy( thread_t * dst,
397                              thread_t * src )
398{
399    kmem_req_t  req;
400
401    // allocate memory for dst fpu_context
402    req.type   = KMEM_FPU_CTX;
403    req.size   = sizeof(hal_fpu_context_t);
404    req.flags  = AF_KERNEL | AF_ZERO;
405
406    hal_fpu_context_t * dst_context = (hal_fpu_context_t *)kmem_alloc( &req );
407    if( dst_context == NULL ) return ENOMEM;
408
409    // set fpu context pointer in dst thread
410    dst->fpu_context = (void*)dst_context;
411
412    // get fpu context pointer from src thread
413    hal_fpu_context_t * src_context = src->fpu_context;
414
415    // copy CPU context from src to dst
416    memcpy( dst_context , src_context , sizeof(hal_fpu_context_t) );
417
418    return 0;
419}  // end hal_fpu_context_copy()
420
421/////////////////////////////////////////////////
422void hal_fpu_context_destroy( thread_t * thread )
423{
424    kmem_req_t  req;
425
426    req.type = KMEM_FPU_CTX;
427    req.ptr  = thread->fpu_context;
428    kmem_free( &req );
429
430}  // end hal_fpu_context_destroy()
431
432/////////////////////////////////////////////////////////////////////////////////////////
433// These registers are initialised:
434// - GPR : sp_29 , fp_30 , a0
435// - CP0 : c0_sr , c0_epc , c0_th
436// - CP2 : C2_ptpr , c2_mode
437// TODO Quand cette fonction est-elle appelée? [AG]
438/////////////////////////////////////////////////////////////////////////////////////////
439void hal_cpu_context_load( thread_t * thread )
440{
441    // get relevant values from thread context
442    hal_cpu_context_t * ctx     = (hal_cpu_context_t *)thread->cpu_context;     
443    uint32_t            sp_29   = ctx->sp_29;
444    uint32_t            fp_30   = ctx->fp_30;
445    uint32_t            c0_th   = ctx->c0_th;
446    uint32_t            c0_sr   = ctx->c0_sr;
447    uint32_t            c2_ptpr = ctx->c2_ptpr;
448    uint32_t            c2_mode = ctx->c2_mode;
449 
450    // get pointer on entry function & argument from thread attributes
451    uint32_t            func    = (uint32_t)thread->entry_func;
452    uint32_t            args    = (uint32_t)thread->entry_args;
453
454    // reset loadable field in thread descriptor
455    thread->flags &= ~THREAD_FLAG_LOADABLE;
456
457    // load registers
458    asm volatile(
459    ".set noreorder                \n"
460        "or       $26,    %0,    $0    \n"   /* $26 <= stack pointer                */
461        "or       $27,    %2,    $0    \n"   /* $27 <= status register              */
462        "addiu    $26,    $26,  -4     \n"   /* decrement stack pointer             */
463        "or       $4,     %7,   $0     \n"   /* load a0                             */
464        "sw       $4,     ($26)        \n"   /* set entry_args in stack             */
465        "ori      $27,    $27,  0x2    \n"   /* set EXL flag in status register     */
466        "mtc0     $27,    $12          \n"   /* load c0_sr                          */
467        "mtc0     %3,     $4,    2     \n"   /* load c0_th                          */
468        "mtc2     %4,     $0           \n"   /* load c2 ptpr                        */
469        "mtc0     %6,     $14          \n"   /* load c0_epc                         */
470        "or           $29,        $16,  $0     \n"   /* load sp_29                          */
471        "or           $30,        %1,   $0     \n"   /* load fp_30                          */
472    "mtc2     %5,     $1           \n"   /* load c2_mode                        */
473    "nop                           \n"
474    "eret                          \n"   /* jump to user code                   */
475    "nop                           \n"
476    ".set reorder                  \n"
477    : 
478    : "r"(sp_29),"r"(fp_30),"r"(c0_sr),"r"(c0_th),
479      "r"(c2_ptpr),"r"(c2_mode),"r"(func),"r"(args)
480    : "$4","$26","$27","$29","$30" );
481
482}  // end hal_cpu_context_load()
483
484
485//////////////////////////////////////////////
486void hal_fpu_context_save( thread_t * thread )
487{
488    uint32_t ctx = (uint32_t)thread->fpu_context;
489
490    asm volatile(
491    ".set noreorder           \n"
492    "swc1    $f0,    0*4(%0)  \n"   
493    "swc1    $f1,    1*4(%0)  \n"   
494    "swc1    $f2,    2*4(%0)  \n"   
495    "swc1    $f3,    3*4(%0)  \n"   
496    "swc1    $f4,    4*4(%0)  \n"   
497    "swc1    $f5,    5*4(%0)  \n"   
498    "swc1    $f6,    6*4(%0)  \n"   
499    "swc1    $f7,    7*4(%0)  \n"   
500    "swc1    $f8,    8*4(%0)  \n"   
501    "swc1    $f9,    9*4(%0)  \n"   
502    "swc1    $f10,  10*4(%0)  \n"   
503    "swc1    $f11,  11*4(%0)  \n"   
504    "swc1    $f12,  12*4(%0)  \n"   
505    "swc1    $f13,  13*4(%0)  \n"   
506    "swc1    $f14,  14*4(%0)  \n"   
507    "swc1    $f15,  15*4(%0)  \n"   
508    "swc1    $f16,  16*4(%0)  \n"   
509    "swc1    $f17,  17*4(%0)  \n"   
510    "swc1    $f18,  18*4(%0)  \n"   
511    "swc1    $f19,  19*4(%0)  \n"   
512    "swc1    $f20,  20*4(%0)  \n"   
513    "swc1    $f21,  21*4(%0)  \n"   
514    "swc1    $f22,  22*4(%0)  \n"   
515    "swc1    $f23,  23*4(%0)  \n"   
516    "swc1    $f24,  24*4(%0)  \n"   
517    "swc1    $f25,  25*4(%0)  \n"   
518    "swc1    $f26,  26*4(%0)  \n"   
519    "swc1    $f27,  27*4(%0)  \n"   
520    "swc1    $f28,  28*4(%0)  \n"   
521    "swc1    $f29,  29*4(%0)  \n"   
522    "swc1    $f30,  30*4(%0)  \n"   
523    "swc1    $f31,  31*4(%0)  \n"   
524    ".set reorder             \n"
525    : : "r"(ctx) );
526
527}  // end hal_cpu_context_save()
528
529/////////////////////////////////////////////////
530void hal_fpu_context_restore( thread_t * thread )
531{
532    uint32_t ctx = (uint32_t)thread->fpu_context;
533
534    asm volatile(
535    ".set noreorder           \n"
536    "lwc1    $f0,    0*4(%0)  \n"   
537    "lwc1    $f1,    1*4(%0)  \n"   
538    "lwc1    $f2,    2*4(%0)  \n"   
539    "lwc1    $f3,    3*4(%0)  \n"   
540    "lwc1    $f4,    4*4(%0)  \n"   
541    "lwc1    $f5,    5*4(%0)  \n"   
542    "lwc1    $f6,    6*4(%0)  \n"   
543    "lwc1    $f7,    7*4(%0)  \n"   
544    "lwc1    $f8,    8*4(%0)  \n"   
545    "lwc1    $f9,    9*4(%0)  \n"   
546    "lwc1    $f10,  10*4(%0)  \n"   
547    "lwc1    $f11,  11*4(%0)  \n"   
548    "lwc1    $f12,  12*4(%0)  \n"   
549    "lwc1    $f13,  13*4(%0)  \n"   
550    "lwc1    $f14,  14*4(%0)  \n"   
551    "lwc1    $f15,  15*4(%0)  \n"   
552    "lwc1    $f16,  16*4(%0)  \n"   
553    "lwc1    $f17,  17*4(%0)  \n"   
554    "lwc1    $f18,  18*4(%0)  \n"   
555    "lwc1    $f19,  19*4(%0)  \n"   
556    "lwc1    $f20,  20*4(%0)  \n"   
557    "lwc1    $f21,  21*4(%0)  \n"   
558    "lwc1    $f22,  22*4(%0)  \n"   
559    "lwc1    $f23,  23*4(%0)  \n"   
560    "lwc1    $f24,  24*4(%0)  \n"   
561    "lwc1    $f25,  25*4(%0)  \n"   
562    "lwc1    $f26,  26*4(%0)  \n"   
563    "lwc1    $f27,  27*4(%0)  \n"   
564    "lwc1    $f28,  28*4(%0)  \n"   
565    "lwc1    $f29,  29*4(%0)  \n"   
566    "lwc1    $f30,  30*4(%0)  \n"   
567    "lwc1    $f31,  31*4(%0)  \n"   
568    ".set reorder             \n"
569    : : "r"(ctx) );
570
571} // end hal_cpu_context_restore()
572
573/////////////////////////////////////
574void hal_fpu_context_dup( xptr_t dst,
575                          xptr_t src )
576{
577        hal_remote_memcpy( dst , src , sizeof(hal_fpu_context_t) );
578}
579
Note: See TracBrowser for help on using the repository browser.