source: soft/giet_vm/giet_common/utils.c @ 745

Last change on this file since 745 was 745, checked in by alain, 9 years ago

Fix a bug in memcpy() when both buffers are word aligned,
but the size is not a multiple of 4 bytes.

File size: 25.0 KB
RevLine 
[523]1///////////////////////////////////////////////////////////////////////////
[258]2// File     : utils.c
3// Date     : 18/10/2013
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
[523]6///////////////////////////////////////////////////////////////////////////
[258]7// The utils.c and utils.h files are part of the GIET-VM nano-kernel.
[523]8///////////////////////////////////////////////////////////////////////////
[258]9
[442]10#include <utils.h>
[455]11#include <tty0.h>
[258]12#include <giet_config.h>
[324]13#include <hard_config.h>
[258]14#include <mapping_info.h>
[442]15#include <tty_driver.h>
[258]16#include <ctx_handler.h>
17
[709]18// This variable is allocated in boot.c file or in kernel_init.c file
19extern static_scheduler_t*  _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX];
[258]20
[523]21///////////////////////////////////////////////////////////////////////////
[399]22//         CP0 registers access functions
[523]23///////////////////////////////////////////////////////////////////////////
[258]24
[709]25////////////////////////////////
26static_scheduler_t* _get_sched() 
[258]27{
28    unsigned int ret;
[295]29    asm volatile( "mfc0      %0,     $4,2    \n" 
30                  : "=r"(ret) );
[709]31
32    return (static_scheduler_t*)ret;
[258]33}
[408]34///////////////////////
[378]35unsigned int _get_epc() 
[258]36{
37    unsigned int ret;
[295]38    asm volatile( "mfc0      %0,    $14     \n"
39                  : "=r"(ret) );
[258]40    return ret;
41}
[408]42////////////////////////
[378]43unsigned int _get_bvar() 
[258]44{
45    unsigned int ret;
[295]46    asm volatile( "mfc0      %0,    $8     \n"
47                  : "=r"(ret));
[258]48    return ret;
49}
[408]50//////////////////////
[378]51unsigned int _get_cr() 
[258]52{
53    unsigned int ret;
[295]54    asm volatile( "mfc0      %0,    $13    \n"
55                  : "=r"(ret));
[258]56    return ret;
57}
[408]58//////////////////////
[378]59unsigned int _get_sr() 
[258]60{
61    unsigned int ret;
[295]62    asm volatile( "mfc0      %0,     $12   \n"
63                  : "=r"(ret));
[258]64    return ret;
65}
[408]66//////////////////////////
[378]67unsigned int _get_procid() 
[258]68{
69    unsigned int ret;
[295]70    asm volatile ( "mfc0     %0,     $15, 1  \n"
71                   :"=r" (ret) );
[430]72    return (ret & 0xFFF);
[258]73}
[408]74////////////////////////////
[378]75unsigned int _get_proctime() 
[258]76{
77    unsigned int ret;
[295]78    asm volatile ( "mfc0     %0,     $9      \n"
79                   :"=r" (ret) );
[258]80    return ret;
81}
[408]82
83/////////////////////////////////////////////
[378]84void _it_disable( unsigned int * save_sr_ptr) 
[258]85{
[345]86    unsigned int sr = 0;
[295]87    asm volatile( "li      $3,        0xFFFFFFFE    \n"
88                  "mfc0    %0,        $12           \n"
89                  "and     $3,        $3,   %0      \n" 
90                  "mtc0    $3,        $12           \n" 
[345]91                  : "+r"(sr)
[295]92                  :
[345]93                  : "$3" );
[295]94    *save_sr_ptr = sr;
[258]95}
[408]96//////////////////////////////////////////////
[378]97void _it_restore( unsigned int * save_sr_ptr ) 
[295]98{
99    unsigned int sr = *save_sr_ptr;
100    asm volatile( "mtc0    %0,        $12           \n" 
101                  :
[301]102                  : "r"(sr)
103                  : "memory" );
[295]104}
105
[408]106/////////////////////////////////
[399]107void _set_sched(unsigned int val) 
108{
109    asm volatile ( "mtc0     %0,     $4, 2          \n"
110                   :
111                   :"r" (val) );
112}
[408]113//////////////////////////////
114void _set_sr(unsigned int val) 
115{
116    asm volatile ( "mtc0     %0,     $12            \n"
117                   :
118                   :"r" (val) );
119}
[399]120
[408]121
[523]122///////////////////////////////////////////////////////////////////////////
[399]123//         CP2 registers access functions
[523]124///////////////////////////////////////////////////////////////////////////
[399]125
[408]126////////////////////////////
[399]127unsigned int _get_mmu_ptpr() 
128{
129    unsigned int ret;
130    asm volatile( "mfc2      %0,     $0      \n"
131                  : "=r"(ret) );
132    return ret;
133}
[408]134////////////////////////////
[399]135unsigned int _get_mmu_mode() 
136{
137    unsigned int ret;
138    asm volatile( "mfc2      %0,     $1      \n"
139                  : "=r"(ret) );
140    return ret;
141}
[408]142////////////////////////////////////
[378]143void _set_mmu_ptpr(unsigned int val) 
[258]144{
[408]145    asm volatile ( "mtc2     %0,     $0      \n"
[295]146                   :
[345]147                   :"r" (val)
148                   :"memory" );
[258]149}
[408]150////////////////////////////////////
[378]151void _set_mmu_mode(unsigned int val) 
[258]152{
[408]153    asm volatile ( "mtc2     %0,     $1      \n"
[295]154                   :
[345]155                   :"r" (val)
156                   :"memory" );
[258]157}
[408]158////////////////////////////////////////////
159void _set_mmu_dcache_inval(unsigned int val) 
160{
161    asm volatile ( "mtc2     %0,     $7      \n"
162                   :
163                   :"r" (val)
164                   :"memory" );
165}
[258]166
[408]167
[523]168///////////////////////////////////////////////////////////////////////////
[258]169//          Physical addressing related functions
[523]170///////////////////////////////////////////////////////////////////////////
[258]171
[442]172///////////////////////////////////////////////////////
[378]173unsigned int _physical_read( unsigned long long paddr ) 
[258]174{
175    unsigned int value;
176    unsigned int lsb = (unsigned int) paddr;
177    unsigned int msb = (unsigned int) (paddr >> 32);
[301]178    unsigned int sr;
[258]179
[301]180    _it_disable(&sr);
[258]181
[523]182    asm volatile( "mfc2   $2,     $1            \n"  /* $2 <= MMU_MODE   */
183                  "andi   $3,     $2,     0xb   \n"
184                  "mtc2   $3,     $1            \n"  /* DTLB off         */   
[258]185
[523]186                  "mtc2   %2,     $24           \n"  /* PADDR_EXT <= msb */   
187                  "lw     %0,     0(%1)         \n"  /* value <= *paddr  */
188                  "mtc2   $0,     $24           \n"  /* PADDR_EXT <= 0   */   
[344]189
[523]190                  "mtc2   $2,     $1            \n"  /* restore MMU_MODE */
[344]191                  : "=r" (value)
192                  : "r" (lsb), "r" (msb)
193                  : "$2", "$3" );
194
[301]195    _it_restore(&sr);
[258]196    return value;
197}
[442]198////////////////////////////////////////////////
[378]199void _physical_write( unsigned long long paddr, 
[430]200                      unsigned int       value ) 
[258]201{
202    unsigned int lsb = (unsigned int)paddr;
203    unsigned int msb = (unsigned int)(paddr >> 32);
[301]204    unsigned int sr;
[258]205
[430]206   _it_disable(&sr);
[258]207
[523]208    asm volatile( "mfc2   $2,     $1           \n"  /* $2 <= MMU_MODE   */
209                  "andi   $3,     $2,    0xb   \n"
210                  "mtc2   $3,     $1           \n"  /* DTLB off         */   
[258]211
[523]212                  "mtc2   %2,     $24          \n"  /* PADDR_EXT <= msb */   
213                  "sw     %0,     0(%1)        \n"  /* *paddr <= value  */
214                  "mtc2   $0,     $24          \n"  /* PADDR_EXT <= 0   */   
[344]215
[523]216                  "mtc2   $2,     $1           \n"  /* restore MMU_MODE */
217                  "sync                        \n"
[344]218                  :
219                  : "r" (value), "r" (lsb), "r" (msb)
220                  : "$2", "$3" );
221
[301]222    _it_restore(&sr);
[258]223}
224
[442]225/////////////////////////////////////////////////////////////////
[378]226unsigned long long _physical_read_ull( unsigned long long paddr ) 
[370]227{
228    unsigned int data_lsb;
229    unsigned int data_msb;
230    unsigned int addr_lsb = (unsigned int) paddr;
231    unsigned int addr_msb = (unsigned int) (paddr >> 32);
232    unsigned int sr;
233
234    _it_disable(&sr);
235
[523]236    asm volatile( "mfc2   $2,     $1           \n"  /* $2 <= MMU_MODE       */
237                  "andi   $3,     $2,    0xb   \n"
238                  "mtc2   $3,     $1           \n"  /* DTLB off             */   
[370]239
[523]240                  "mtc2   %3,     $24          \n"  /* PADDR_EXT <= msb     */   
241                  "lw     %0,     0(%2)        \n"  /* data_lsb <= *paddr   */
242                  "lw     %1,     4(%2)        \n"  /* data_msb <= *paddr+4 */
243                  "mtc2   $0,     $24          \n"  /* PADDR_EXT <= 0       */   
[370]244
[523]245                  "mtc2   $2,     $1           \n"  /* restore MMU_MODE     */
[370]246                  : "=r" (data_lsb), "=r"(data_msb)
247                  : "r" (addr_lsb), "r" (addr_msb)
248                  : "$2", "$3" );
249
250    _it_restore(&sr);
251
252    return ( (((unsigned long long)data_msb)<<32) +
253             (((unsigned long long)data_lsb)) );
254}
255
[442]256///////////////////////////////////////////////////
[378]257void _physical_write_ull( unsigned long long paddr, 
[399]258                          unsigned long long value ) 
[370]259{
260    unsigned int addr_lsb = (unsigned int)paddr;
261    unsigned int addr_msb = (unsigned int)(paddr >> 32);
262    unsigned int data_lsb = (unsigned int)value;
263    unsigned int data_msb = (unsigned int)(value >> 32);
264    unsigned int sr;
265
266    _it_disable(&sr);
267
[523]268    asm volatile( "mfc2   $2,     $1           \n"  /* $2 <= MMU_MODE     */
269                  "andi   $3,     $2,    0xb   \n"
270                  "mtc2   $3,     $1           \n"  /* DTLB off           */   
[370]271
[523]272                  "mtc2   %3,     $24          \n"  /* PADDR_EXT <= msb   */   
273                  "sw     %0,     0(%2)        \n"  /* *paddr <= value    */
274                  "sw     %1,     4(%2)        \n"  /* *paddr+4 <= value  */
275                  "mtc2   $0,     $24          \n"  /* PADDR_EXT <= 0     */   
[370]276
[523]277                  "mtc2   $2,     $1           \n"  /* restore MMU_MODE   */
278                  "sync                        \n"
[370]279                  :
[523]280                  : "r"(data_lsb),"r"(data_msb),"r"(addr_lsb),"r"(addr_msb)
[370]281                  : "$2", "$3" );
282
283    _it_restore(&sr);
284}
285
[442]286////////////////////////////////////////////////////
[523]287void _physical_memcpy( unsigned long long dst_paddr,  // dest buffer paddr
[399]288                       unsigned long long src_paddr,  // source buffer paddr
289                       unsigned int size )            // bytes
[344]290{
291    // check alignment constraints
292    if ( (dst_paddr & 3) || (src_paddr & 3) || (size & 3) ) 
293    {
[442]294        _puts("\n[GIET ERROR] in _physical_memcpy() : buffer unaligned\n");
[344]295        _exit();
296    }
297
298    unsigned int src_lsb = (unsigned int)src_paddr;
299    unsigned int src_msb = (unsigned int)(src_paddr >> 32);
300    unsigned int dst_lsb = (unsigned int)dst_paddr;
301    unsigned int dst_msb = (unsigned int)(dst_paddr >> 32);
302    unsigned int iter    = size>>2;
303    unsigned int data;
304    unsigned int sr;
305
306    _it_disable(&sr);
307
[523]308    asm volatile( "mfc2   $2,     $1         \n" /* $2 <= current MMU_MODE */
309                  "andi   $3,     $2,   0xb  \n" /* $3 <= new MMU_MODE     */
310                  "mtc2   $3,     $1         \n" /* DTLB off               */   
[344]311
[523]312                  "move   $4,     %5         \n" /* $4 < iter              */
313                  "move   $5,     %1         \n" /* $5 < src_lsb           */
314                  "move   $6,     %3         \n" /* $6 < src_lsb           */
[344]315
[523]316                  "ph_memcpy_loop:           \n"
317                  "mtc2   %2,     $24        \n" /* PADDR_EXT <= src_msb   */   
318                  "lw     %0,     0($5)      \n" /* data <= *src_paddr     */
319                  "mtc2   %4,     $24        \n" /* PADDR_EXT <= dst_msb   */   
320                  "sw     %0,     0($6)      \n" /* *dst_paddr <= data     */
[344]321
[523]322                  "addi   $4,     $4,   -1   \n" /* iter = iter - 1        */
323                  "addi   $5,     $5,   4    \n" /* src_lsb += 4           */
324                  "addi   $6,     $6,   4    \n" /* dst_lsb += 4           */
[344]325                  "bne    $4,     $0, ph_memcpy_loop \n"
[523]326                  "nop                       \n"
[344]327
[523]328                  "mtc2   $0,     $24        \n" /* PADDR_EXT <= 0         */   
329                  "mtc2   $2,     $1         \n" /* restore MMU_MODE       */
[344]330                  : "=r" (data)
[523]331                  : "r"(src_lsb),"r"(src_msb),"r"(dst_lsb),
332                    "r"(dst_msb), "r"(iter)
[344]333                  : "$2", "$3", "$4", "$5", "$6" );
334
335    _it_restore(&sr);
[430]336} // end _physical_memcpy()
[344]337
[442]338////////////////////////////////////////////////
[523]339void _physical_memset( unsigned long long paddr,     // dest buffer paddr
[430]340                       unsigned int       size,      // bytes
341                       unsigned int       data )     // written value
342{
343    // check alignment constraints
[433]344    if ( (paddr & 3) || (size & 7) )
[430]345    {
[442]346        _puts("\n[GIET ERROR] in _physical_memset() : buffer unaligned\n");
[430]347        _exit();
348    }
349
350    unsigned int lsb  = (unsigned int)paddr;
351    unsigned int msb  = (unsigned int)(paddr >> 32);
352    unsigned int sr;
353
354    _it_disable(&sr);
355
[523]356    asm volatile( "mfc2   $8,     $1         \n" /* $8 <= current MMU_MODE */
357                  "andi   $9,     $8,   0xb  \n" /* $9 <= new MMU_MODE     */
358                  "mtc2   $9,     $1         \n" /* DTLB off               */
359                  "mtc2   %3,     $24        \n" /* PADDR_EXT <= msb       */
[430]360
[523]361                  "1:                        \n" /* set 8 bytes per iter   */
362                  "sw     %2,     0(%0)      \n" /* *src_paddr     = data  */
363                  "sw     %2,     4(%0)      \n" /* *(src_paddr+4) = data  */
364                  "addi   %1,     %1,   -8   \n" /* size -= 8              */
365                  "addi   %0,     %0,    8   \n" /* src_paddr += 8         */
366                  "bnez   %1,     1b         \n" /* loop while size != 0   */
[430]367
[523]368                  "mtc2   $0,     $24        \n" /* PADDR_EXT <= 0         */
369                  "mtc2   $8,     $1         \n" /* restore MMU_MODE       */
[433]370                  : "+r"(lsb), "+r"(size)
371                  : "r"(data), "r" (msb)
372                  : "$8", "$9", "memory" );
[430]373
374    _it_restore(&sr);
[433]375}  // _physical_memset()
[430]376
[442]377///////////////////////////////////////////////
[378]378void _io_extended_write( unsigned int*  vaddr,
[399]379                         unsigned int   value )
[295]380{
381    unsigned long long paddr;
382
383    if ( _get_mmu_mode() & 0x4 )  // MMU activated : use virtual address
384    {
385        *vaddr = value;
386    }
387    else                          // use paddr extension for IO
388    {
389        paddr = (unsigned long long)(unsigned int)vaddr +
390                (((unsigned long long)((X_IO<<Y_WIDTH) + Y_IO))<<32); 
391        _physical_write( paddr, value );
392    }
393    asm volatile("sync" ::: "memory");
394}
395
[442]396//////////////////////////////////////////////////////
[378]397unsigned int _io_extended_read( unsigned int*  vaddr )
[295]398{
399    unsigned long long paddr;
400
401    if ( _get_mmu_mode() & 0x4 )  // MMU activated : use virtual address
402    {
403        return *(volatile unsigned int*)vaddr;
404    }
405    else                          // use paddr extension for IO
406    {
407        paddr = (unsigned long long)(unsigned int)vaddr +
408                (((unsigned long long)((X_IO<<Y_WIDTH) + Y_IO))<<32); 
409        return _physical_read( paddr );
410    }
411}
412
[523]413////////////////////////////////////////////////////////////////////////////
[709]414//           Scheduler and threads context access functions
[523]415////////////////////////////////////////////////////////////////////////////
[258]416
[430]417
[709]418///////////////////////////////
419unsigned int _get_thread_ltid() 
[258]420{
[709]421    static_scheduler_t* psched = (static_scheduler_t *) _get_sched();
422    return psched->current;
[258]423}
[442]424
[709]425////////////////////////////////
426unsigned int _get_thread_trdid() 
[258]427{
[709]428    static_scheduler_t* psched  = (static_scheduler_t *) _get_sched();
429    unsigned int        current = psched->current;
430    return psched->context[current].slot[CTX_TRDID_ID];
431}
432
433//////////////////////////////////////////////
434unsigned int _get_thread_slot( unsigned int x,
435                               unsigned int y,
436                               unsigned int p,
437                               unsigned int ltid,
438                               unsigned int slotid )
439{
[430]440    static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[x][y][p];
[709]441    return psched->context[ltid].slot[slotid];
[258]442}
[442]443
[709]444//////////////////////////////////////
445void _set_thread_slot( unsigned int x,
446                       unsigned int y,
447                       unsigned int p,
448                       unsigned int ltid,
449                       unsigned int slotid,
450                       unsigned int value )
[258]451{
[430]452    static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[x][y][p];
[709]453    psched->context[ltid].slot[slotid] = value;
[258]454}
[442]455
[709]456/////////////////////////////////////////////////////
457unsigned int _get_context_slot( unsigned int slotid )
[258]458{
459    static_scheduler_t* psched  = (static_scheduler_t*)_get_sched();
[709]460    unsigned int        ltid    = psched->current;
461    return psched->context[ltid].slot[slotid];
[258]462}
[442]463
[709]464////////////////////////////////////////////
465void _set_context_slot( unsigned int slotid,
466                        unsigned int value )
[258]467{
468    static_scheduler_t* psched  = (static_scheduler_t*)_get_sched();
[709]469    unsigned int        ltid    = psched->current;
470    psched->context[ltid].slot[slotid] = value;
[258]471}
472
473/////////////////////////////////////////////////////////////////////////////
474//      Access functions to mapping_info data structure
475/////////////////////////////////////////////////////////////////////////////
[442]476
477////////////////////////////////////////////////////////////////
[378]478mapping_cluster_t * _get_cluster_base(mapping_header_t * header) 
[258]479{
480    return (mapping_cluster_t *) ((char *) header +
481            MAPPING_HEADER_SIZE);
482}
[442]483//////////////////////////////////////////////////////////
[378]484mapping_pseg_t * _get_pseg_base(mapping_header_t * header) 
[258]485{
486    return (mapping_pseg_t *) ((char *) header +
487            MAPPING_HEADER_SIZE +
[263]488            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE);
[258]489}
[442]490//////////////////////////////////////////////////////////////
[378]491mapping_vspace_t * _get_vspace_base(mapping_header_t * header) 
[258]492{
493    return (mapping_vspace_t *)  ((char *) header +
494            MAPPING_HEADER_SIZE +
[263]495            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
[258]496            MAPPING_PSEG_SIZE * header->psegs);
497}
[442]498//////////////////////////////////////////////////////////
[378]499mapping_vseg_t * _get_vseg_base(mapping_header_t * header)
[258]500{
501    return (mapping_vseg_t *) ((char *) header +
502            MAPPING_HEADER_SIZE +
[263]503            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
[258]504            MAPPING_PSEG_SIZE * header->psegs +
505            MAPPING_VSPACE_SIZE * header->vspaces);
506}
[709]507//////////////////////////////////////////////////////////////
508mapping_thread_t * _get_thread_base(mapping_header_t * header) 
[258]509{
[709]510    return (mapping_thread_t *) ((char *) header +
[258]511            MAPPING_HEADER_SIZE +
[263]512            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
[258]513            MAPPING_PSEG_SIZE * header->psegs +
514            MAPPING_VSPACE_SIZE * header->vspaces +
515            MAPPING_VSEG_SIZE * header->vsegs);
516}
[442]517/////////////////////////////////////////////////////////
[378]518mapping_proc_t *_get_proc_base(mapping_header_t * header) 
[258]519{
520    return (mapping_proc_t *) ((char *) header +
521            MAPPING_HEADER_SIZE +
[263]522            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
[258]523            MAPPING_PSEG_SIZE * header->psegs +
524            MAPPING_VSPACE_SIZE * header->vspaces +
525            MAPPING_VSEG_SIZE * header->vsegs +
[709]526            MAPPING_THREAD_SIZE * header->threads);
[258]527}
[442]528///////////////////////////////////////////////////////
[378]529mapping_irq_t *_get_irq_base(mapping_header_t * header) 
[258]530{
531    return (mapping_irq_t *) ((char *) header +
532            MAPPING_HEADER_SIZE +
[263]533            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
[258]534            MAPPING_PSEG_SIZE * header->psegs +
535            MAPPING_VSPACE_SIZE * header->vspaces +
536            MAPPING_VSEG_SIZE * header->vsegs +
[709]537            MAPPING_THREAD_SIZE * header->threads +
[258]538            MAPPING_PROC_SIZE * header->procs);
539}
[442]540///////////////////////////////////////////////////////////////
[378]541mapping_periph_t *_get_periph_base(mapping_header_t * header) 
[258]542{
543    return (mapping_periph_t *) ((char *) header +
544            MAPPING_HEADER_SIZE +
[263]545            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
[258]546            MAPPING_PSEG_SIZE * header->psegs +
547            MAPPING_VSPACE_SIZE * header->vspaces +
548            MAPPING_VSEG_SIZE * header->vsegs +
[709]549            MAPPING_THREAD_SIZE * header->threads +
[258]550            MAPPING_PROC_SIZE * header->procs +
[523]551            MAPPING_IRQ_SIZE * header->irqs);
[258]552}
553
[523]554///////////////////////////////////////////////////////////////////////////
[442]555//             Miscelaneous functions
[523]556///////////////////////////////////////////////////////////////////////////
[399]557
[442]558//////////////////////////////////////
559__attribute__((noreturn)) void _exit() 
560{
[523]561    unsigned int procid = _get_procid();
562    unsigned int x      = (procid >> (Y_WIDTH + P_WIDTH)) & ((1<<X_WIDTH)-1);
563    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
564    unsigned int lpid   = procid & ((1<<P_WIDTH)-1);
[442]565
566
[734]567    _printf("\n[GIET PANIC] P[%d,%d,%d] suicide at cycle %d",
568            x , y , lpid , _get_proctime() );
[442]569
570    while (1) { asm volatile ("nop"); }
571}
572
573/////////////////////////////////////
[399]574void _random_wait( unsigned int val )
575{
576    unsigned int mask  = (1<<(val&0x1F))-1;
577    unsigned int delay = (_get_proctime() ^ (_get_procid()<<4)) & mask;
578    asm volatile( "move  $3,   %0                 \n"
579                  "loop_nic_completed:            \n"
[466]580                  "nop                            \n"
[399]581                  "addi  $3,   $3, -1             \n"
582                  "bnez  $3,   loop_nic_completed \n"
583                  "nop                            \n"
584                  :
585                  : "r" (delay)
586                  : "$3" ); 
587}
[442]588
589///////////////////////////
[399]590void _break( char* string ) 
591{
592    char byte;
593
[442]594    _puts("\n[GIET DEBUG] break from ");
595    _puts( string );
596    _puts(" / stoke any key to continue\n");
[399]597    _getc( &byte );
598}
599
[594]600////////////////////////////////////
601unsigned int _strlen( char* string )
602{
603    unsigned int i = 0;
604    while ( string[i] != 0 ) i++;
605    return i;
606}
607
[442]608///////////////////////////////////////
[618]609unsigned int _strcmp( const char * s1,
610                      const char * s2 )
611{
612    while (1)
613    {
614        if (*s1 != *s2) return 1;
615        if (*s1 == 0)   break;
616        s1++, s2++;
617    }
618    return 0;
619}
620
621///////////////////////////////////////
[399]622unsigned int _strncmp( const char * s1, 
623                       const char * s2, 
624                       unsigned int n ) 
625{
626    unsigned int i;
627    for (i = 0; i < n; i++) 
628    {
629        if (s1[i] != s2[i])  return 1; 
630        if (s1[i] == 0)      break;
631    }
632    return 0;
633}
634
[442]635/////////////////////////////////////////
[399]636char* _strcpy( char* dest, char* source )
637{
638    if (!dest || !source) return dest;
639
640    while (*source)
[594]641    {
642        *(dest) = *(source);
643        dest++;
644        source++;
645    }
646    *dest = 0;
[399]647    return dest;
648}
649
[442]650/////////////////////////////////////////////////////
[408]651void _dcache_buf_invalidate( unsigned int buf_vbase, 
652                             unsigned int buf_size ) 
[399]653{
[408]654    unsigned int offset;
[399]655    unsigned int tmp;
[408]656    unsigned int line_size;   // bytes
[399]657
658    // compute data cache line size based on config register (bits 12:10)
659    asm volatile(
660                 "mfc0 %0, $16, 1" 
661                 : "=r" (tmp) );
[408]662
[399]663    tmp = ((tmp >> 10) & 0x7);
664    line_size = 2 << tmp;
665
666    // iterate on cache lines
[408]667    for ( offset = 0; offset < buf_size; offset += line_size) 
[399]668    {
[408]669        _set_mmu_dcache_inval( buf_vbase + offset );
[399]670    }
671}
672
673
674
[495]675/////////////////////////////////////////////
676void _get_sqt_footprint( unsigned int* width,
677                         unsigned int* heigth,
678                         unsigned int* levels )
679{
680    mapping_header_t*   header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
681    mapping_cluster_t*  cluster = _get_cluster_base(header);
682
683    unsigned int x;
684    unsigned int y;
685    unsigned int cid;
686    unsigned int w = 0;
687    unsigned int h = 0;
688
689    // scan all clusters to compute SQT footprint (w,h)
690    for ( x = 0 ; x < X_SIZE ; x++ )
691    {
692        for ( y = 0 ; y < Y_SIZE ; y++ )
693        {
694            cid = x * Y_SIZE + y;
695            if ( cluster[cid].procs )  // cluster contains processors
696            {
697                if ( x > w ) w = x;
698                if ( y > h ) h = y;
699            }
700        }
701    }           
702    *width  = w + 1;
703    *heigth = h + 1;
704   
705    // compute SQT levels
706    unsigned int z = (h > w) ? h : w;
707    *levels = (z < 1) ? 1 : (z < 2) ? 2 : (z < 4) ? 3 : (z < 8) ? 4 : 5;
708}
709     
710
711
[523]712///////////////////////////////////////////////////////////////////////////
[399]713//   Required by GCC
[523]714///////////////////////////////////////////////////////////////////////////
[399]715
[442]716////////////////////////////////
[399]717void* memcpy( void*        dest,     // dest buffer vbase
718              const void*  source,   // source buffer vbase
719              unsigned int size )    // bytes
720{
721    unsigned int* idst = (unsigned int*)dest;
722    unsigned int* isrc = (unsigned int*)source;
723
[745]724    // word-by-word copy if both buffers are word aligned
[399]725    if (!((unsigned int) idst & 3) && !((unsigned int) isrc & 3)) 
726    {
727        while (size > 3) 
728        {
729            *idst++ = *isrc++;
730            size -= 4;
731        }
732    }
733
[745]734    unsigned char* cdst = (unsigned char*)idst;
735    unsigned char* csrc = (unsigned char*)isrc;
[399]736
[745]737    // byte-by-byte copy if size not multiple of 4 bytes
738    while (size) 
[399]739    {
740        *cdst++ = *csrc++;
[745]741        size--;
[399]742    }
[745]743
[399]744    return dest;
745}
[442]746
747/////////////////////////////////
[594]748void* memset( void*        dst, 
749              int          value, 
750              unsigned int count ) 
[399]751{
752    // word-by-word copy
[442]753    unsigned int* idst = dst;
[399]754    unsigned int  data = (((unsigned char)value)      ) |
755                         (((unsigned char)value) <<  8) |
756                         (((unsigned char)value) << 16) |
757                         (((unsigned char)value) << 24) ;
758
759    if ( ! ((unsigned int)idst & 3) )
760    {
761        while ( count > 3 )
762        {
763            *idst++ = data;
764            count -= 4;
765        }
766    }
767   
768    // byte-by-byte copy
[442]769    unsigned char* cdst = dst;
[399]770    while (count--) 
771    {
772        *cdst++ = (unsigned char)value;
773    }
[442]774    return dst;
[399]775}
776
777
[258]778// Local Variables:
779// tab-width: 4
780// c-basic-offset: 4
781// c-file-offsets:((innamespace . 0)(inline-open . 0))
782// indent-tabs-mode: nil
783// End:
784// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
785
Note: See TracBrowser for help on using the repository browser.