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