1 // Externe Routinen zu ARILEV1.D 2 // Prozessor: 80386 im native mode 3 // Assembler-Syntax: GNU oder SUN, Moves von links nach rechts 4 // Compiler: GNU-C oder SUN-C 5 // Parameter-Übergabe: auf dem Stack 4(%esp),8(%esp),... 6 // Register: %eax,%edx,%ecx dürfen stets verändert werden, alles andere retten. 7 // Ergebnis-Übergabe: in %eax 8 // Einstellungen: intCsize=32, intDsize=32. 9 10 // Bruno Haible 14.8.1992 11 // Zum Teil abgeschrieben von Bernhard Degels "v-i386.s" 12 13 #ifdef ASM_UNDERSCORE 14 #if defined(__STDC__) || defined (__cplusplus) 15 #define C(entrypoint) _##entrypoint 16 #else 17 #define C(entrypoint) _/**/entrypoint 18 #endif 19 #else 20 #define C(entrypoint) entrypoint 21 #endif 22 #ifdef ASM_UNDERSCORE 23 #if defined(__STDC__) || defined (__cplusplus) 24 #define L(label) L##label 25 #else 26 #define L(label) L/**/label 27 #endif 28 #else 29 #if defined(__STDC__) || defined (__cplusplus) 30 #define L(label) .L##label 31 #else 32 #define L(label) .L/**/label 33 #endif 34 #endif 35 #if defined(ASM_UNDERSCORE) || defined(COHERENT) /* defined(__EMX__) || defined(__GO32__) || defined(linux) || defined(__386BSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(COHERENT) || ... */ 36 // GNU-Assembler oder MWC-Assembler 37 #define repz repe 38 #define shcl %cl, 39 #else /* defined(sun) || ... */ 40 // SUN-Assembler oder Consensys-Assembler 41 #define jecxz orl %ecx,%ecx ; jz 42 #define shcl 43 #endif 44 #if defined(__EMX__) 45 // Direction-Flag ist defaultmäßig gelöscht 46 #define dir0start 47 #define dir0end 48 #define dir1start std 49 #define dir1end cld 50 #elif 1 51 // Wir gehen auf Nummer sicher. 52 #define dir0start cld 53 #define dir0end 54 #define dir1start std 55 #define dir1end cld 56 #else 57 // Direction-Flag darf nach Belieben modifiziert werden 58 #define dir0start cld 59 #define dir0end 60 #define dir1start std 61 #define dir1end 62 #endif 63 // Alignment. Note that some assemblers need ".align 3,0x90" whereas other 64 // assemblers don't like this syntax. So we put in the "nop"s by hand. 65 #if defined(ASM_UNDERSCORE) && !(defined(__CYGWIN32__) || defined(__MINGW32__)) 66 // BSD syntax assembler 67 #define ALIGN .align 3 68 #else 69 // ELF syntax assembler 70 #define ALIGN .align 8 71 #endif 72 // When this file is compiled into a shared library, ELF linkers need to 73 // know which symbols are functions. 74 #if defined(__svr4__) || defined(__ELF__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__ROSE__) || defined(_SEQUENT_) || defined(DGUX) || defined(_SCO_COFF) || defined(_SCO_ELF) 75 #define DECLARE_FUNCTION(name) .type C(name),@function 76 #else 77 #define DECLARE_FUNCTION(name) 78 #endif 79 80 .text 81 82 .globl C(copy_loop_up) 83 .globl C(copy_loop_down) 84 .globl C(fill_loop_up) 85 .globl C(fill_loop_down) 86 .globl C(clear_loop_up) 87 .globl C(clear_loop_down) 88 .globl C(test_loop_up) 89 .globl C(test_loop_down) 90 .globl C(xor_loop_up) 91 .globl C(compare_loop_up) 92 .globl C(shiftleftcopy_loop_up) 93 .globl C(shiftxor_loop_up) 94 #if CL_DS_BIG_ENDIAN_P 95 .globl C(or_loop_up) 96 .globl C(and_loop_up) 97 .globl C(eqv_loop_up) 98 .globl C(nand_loop_up) 99 .globl C(nor_loop_up) 100 .globl C(andc2_loop_up) 101 .globl C(orc2_loop_up) 102 .globl C(not_loop_up) 103 .globl C(and_test_loop_up) 104 .globl C(add_loop_down) 105 .globl C(addto_loop_down) 106 .globl C(inc_loop_down) 107 .globl C(sub_loop_down) 108 .globl C(subx_loop_down) 109 .globl C(subfrom_loop_down) 110 .globl C(dec_loop_down) 111 .globl C(neg_loop_down) 112 .globl C(shift1left_loop_down) 113 .globl C(shiftleft_loop_down) 114 .globl C(shiftleftcopy_loop_down) 115 .globl C(shift1right_loop_up) 116 .globl C(shiftright_loop_up) 117 .globl C(shiftrightsigned_loop_up) 118 .globl C(shiftrightcopy_loop_up) 119 .globl C(mulusmall_loop_down) 120 .globl C(mulu_loop_down) 121 .globl C(muluadd_loop_down) 122 .globl C(mulusub_loop_down) 123 .globl C(divu_loop_up) 124 .globl C(divucopy_loop_up) 125 #else 126 .globl C(or_loop_down) 127 .globl C(xor_loop_down) 128 .globl C(and_loop_down) 129 .globl C(eqv_loop_down) 130 .globl C(nand_loop_down) 131 .globl C(nor_loop_down) 132 .globl C(andc2_loop_down) 133 .globl C(orc2_loop_down) 134 .globl C(not_loop_down) 135 .globl C(and_test_loop_down) 136 .globl C(compare_loop_down) 137 .globl C(add_loop_up) 138 .globl C(addto_loop_up) 139 .globl C(inc_loop_up) 140 .globl C(sub_loop_up) 141 .globl C(subx_loop_up) 142 .globl C(subfrom_loop_up) 143 .globl C(dec_loop_up) 144 .globl C(neg_loop_up) 145 .globl C(shift1left_loop_up) 146 .globl C(shiftleft_loop_up) 147 .globl C(shift1right_loop_down) 148 .globl C(shiftright_loop_down) 149 .globl C(shiftrightsigned_loop_down) 150 .globl C(shiftrightcopy_loop_down) 151 .globl C(mulusmall_loop_up) 152 .globl C(mulu_loop_up) 153 .globl C(muluadd_loop_up) 154 .globl C(mulusub_loop_up) 155 .globl C(divu_loop_down) 156 .globl C(divucopy_loop_down) 157 #endif 158 159 #ifndef __GNUC__ /* mit GNU-C machen wir mulu32() als Macro, der inline multipliziert */ 160 161 // extern struct { uint32 lo; uint32 hi; } mulu32_ (uint32 arg1, uint32 arg2); 162 // 2^32*hi+lo := arg1*arg2. 163 .globl C(mulu32_) 164 ALIGN 165 DECLARE_FUNCTION(mulu32_) 166 C(mulu32_:) 167 movl 4(%esp),%eax // arg1 168 mull 8(%esp) // %edx|%eax := arg1 * arg2 169 movl %edx,C(mulu32_high) // %edx = hi abspeichern 170 ret // %eax = lo als Ergebnis 171 172 #endif 173 174 #ifndef __GNUC__ /* mit GNU-C machen wir divu_6432_3232() als Macro, der inline dividiert */ 175 176 // extern struct { uint32 q; uint32 r; } divu_6432_3232_ (uint32 xhi, uint32 xlo, uint32 y); 177 // x = 2^32*xhi+xlo = q*y+r schreiben. Sei bekannt, daß 0 <= x < 2^32*y . 178 .globl C(divu_6432_3232_) 179 ALIGN 180 DECLARE_FUNCTION(divu_6432_3232_) 181 C(divu_6432_3232_:) 182 movl 4(%esp),%edx 183 movl 8(%esp),%eax 184 divl 12(%esp) // x = %edx|%eax durch dividieren 185 movl %edx,C(divu_32_rest) // Rest %edx = r abspeichern 186 ret // Quotient %eax = q als Ergebnis 187 188 #endif 189 190 // extern uintD* copy_loop_up (uintD* sourceptr, uintD* destptr, uintC count); 191 ALIGN 192 DECLARE_FUNCTION(copy_loop_up) 193 C(copy_loop_up:) 194 movl %edi,%edx // %edi retten 195 movl %esi,%eax // %esi retten 196 movl 4(%esp),%esi // %esi = sourceptr 197 movl 8(%esp),%edi // %edi = destptr 198 movl 12(%esp),%ecx // %ecx = count 199 dir0start 200 rep 201 movsl // %ecx mal aufwärts (%edi) := (%esi) 202 dir0end 203 movl %eax,%esi // %esi zurück 204 movl %edi,%eax // %edi als Ergebnis 205 movl %edx,%edi // %edi zurück 206 ret 207 208 // extern uintD* copy_loop_down (uintD* sourceptr, uintD* destptr, uintC count); 209 ALIGN 210 DECLARE_FUNCTION(copy_loop_down) 211 C(copy_loop_down:) 212 movl %edi,%edx // %edi retten 213 movl %esi,%eax // %esi retten 214 movl 4(%esp),%esi // %esi = sourceptr 215 movl 8(%esp),%edi // %edi = destptr 216 movl 12(%esp),%ecx // %ecx = count 217 leal -4(%esi),%esi 218 leal -4(%edi),%edi 219 dir1start 220 rep 221 movsl // %ecx mal abwärts (%edi) := (%esi) 222 dir1end 223 movl %eax,%esi // %esi zurück 224 leal 4(%edi),%eax // %edi als Ergebnis 225 movl %edx,%edi // %edi zurück 226 ret 227 228 // extern uintD* fill_loop_up (uintD* destptr, uintC count, uintD filler); 229 ALIGN 230 DECLARE_FUNCTION(fill_loop_up) 231 C(fill_loop_up:) 232 movl %edi,%edx // %edi retten 233 movl 4(%esp),%edi // %edi = destptr 234 movl 8(%esp),%ecx // %ecx = count 235 movl 12(%esp),%eax // %eax = filler 236 dir0start 237 rep 238 stosl // %ecx mal aufwärts (%edi) := %eax 239 dir0end 240 movl %edi,%eax // %edi als Ergebnis 241 movl %edx,%edi // %edi zurück 242 ret 243 244 // extern uintD* fill_loop_down (uintD* destptr, uintC count, uintD filler); 245 ALIGN 246 DECLARE_FUNCTION(fill_loop_down) 247 C(fill_loop_down:) 248 movl %edi,%edx // %edi retten 249 movl 4(%esp),%edi // %edi = destptr 250 movl 8(%esp),%ecx // %ecx = count 251 movl 12(%esp),%eax // %eax = filler 252 leal -4(%edi),%edi 253 dir1start 254 rep 255 stosl // %ecx mal abwärts (%edi) := %eax 256 dir1end 257 leal 4(%edi),%eax // %edi als Ergebnis 258 movl %edx,%edi // %edi zurück 259 ret 260 261 // extern uintD* clear_loop_up (uintD* destptr, uintC count); 262 ALIGN 263 DECLARE_FUNCTION(clear_loop_up) 264 C(clear_loop_up:) 265 movl %edi,%edx // %edi retten 266 movl 4(%esp),%edi // %edi = destptr 267 movl 8(%esp),%ecx // %ecx = count 268 xorl %eax,%eax // %eax = 0 269 dir0start 270 rep 271 stosl // %ecx mal aufwärts (%edi) := %eax 272 dir0end 273 movl %edi,%eax // %edi als Ergebnis 274 movl %edx,%edi // %edi zurück 275 ret 276 277 // extern uintD* clear_loop_down (uintD* destptr, uintC count); 278 ALIGN 279 DECLARE_FUNCTION(clear_loop_down) 280 C(clear_loop_down:) 281 movl %edi,%edx // %edi retten 282 movl 4(%esp),%edi // %edi = destptr 283 movl 8(%esp),%ecx // %ecx = count 284 leal -4(%edi),%edi 285 xorl %eax,%eax // %eax = 0 286 dir1start 287 rep 288 stosl // %ecx mal abwärts (%edi) := %eax 289 dir1end 290 leal 4(%edi),%eax // %edi als Ergebnis 291 movl %edx,%edi // %edi zurück 292 ret 293 294 // extern boolean test_loop_up (uintD* ptr, uintC count); 295 ALIGN 296 DECLARE_FUNCTION(test_loop_up) 297 C(test_loop_up:) 298 movl %edi,%edx // %edi retten 299 movl 4(%esp),%edi // %edi = ptr 300 movl 8(%esp),%ecx // %ecx = count 301 xorl %eax,%eax // %eax = 0 302 dir0start 303 repz // Falls %ecx > 0: 304 scasl // %ecx mal aufwärts (%edi) testen 305 // und weiterschleifen, falls Z, d.h. (%edi)=0. 306 dir0end 307 // Noch ist %eax = 0. 308 jz L(tlu1) // alles =0 -> Ergebnis 0 309 incl %eax // Ergebnis 1 310 L(tlu1:) movl %edx,%edi // %edi zurück 311 ret 312 313 // extern boolean test_loop_down (uintD* ptr, uintC count); 314 ALIGN 315 DECLARE_FUNCTION(test_loop_down) 316 C(test_loop_down:) 317 movl %edi,%edx // %edi retten 318 movl 4(%esp),%edi // %edi = ptr 319 movl 8(%esp),%ecx // %ecx = count 320 xorl %eax,%eax // %eax = 0 321 leal -4(%edi),%edi 322 dir1start 323 repz // Falls %ecx > 0: 324 scasl // %ecx mal aufwärts (%edi) testen 325 // und weiterschleifen, falls Z, d.h. (%edi)=0. 326 dir1end 327 // Noch ist %eax = 0. 328 jz L(tld1) // alles =0 -> Ergebnis 0 329 incl %eax // Ergebnis 1 330 L(tld1:) movl %edx,%edi // %edi zurück 331 ret 332 333 #if CL_DS_BIG_ENDIAN_P 334 335 // extern void or_loop_up (uintD* xptr, uintD* yptr, uintC count); 336 ALIGN 337 DECLARE_FUNCTION(or_loop_up) 338 C(or_loop_up:) 339 pushl %esi // %esi retten 340 movl 8(%esp),%edx // %edx = xptr 341 movl 12(%esp),%esi // %esi = yptr 342 movl 16(%esp),%ecx // %ecx = count 343 subl %edx,%esi 344 jecxz L(olu2) // %ecx = 0 ? 345 L(olu1:) movl (%edx,%esi),%eax // *yptr 346 orl %eax,(%edx) // *xptr |= ... 347 leal 4(%edx),%edx // xptr++, yptr++ 348 decl %ecx 349 jnz L(olu1) 350 L(olu2:) popl %esi // %esi zurück 351 ret 352 353 #endif 354 355 // extern void xor_loop_up (uintD* xptr, uintD* yptr, uintC count); 356 ALIGN 357 DECLARE_FUNCTION(xor_loop_up) 358 C(xor_loop_up:) 359 pushl %esi // %esi retten 360 movl 8(%esp),%edx // %edx = xptr 361 movl 12(%esp),%esi // %esi = yptr 362 movl 16(%esp),%ecx // %ecx = count 363 subl %edx,%esi 364 jecxz L(xlu2) // %ecx = 0 ? 365 L(xlu1:) movl (%edx,%esi),%eax // *yptr 366 xorl %eax,(%edx) // *xptr ^= ... 367 leal 4(%edx),%edx // xptr++, yptr++ 368 decl %ecx 369 jnz L(xlu1) 370 L(xlu2:) popl %esi // %esi zurück 371 ret 372 373 #if CL_DS_BIG_ENDIAN_P 374 375 // extern void and_loop_up (uintD* xptr, uintD* yptr, uintC count); 376 ALIGN 377 DECLARE_FUNCTION(and_loop_up) 378 C(and_loop_up:) 379 pushl %esi // %esi retten 380 movl 8(%esp),%edx // %edx = xptr 381 movl 12(%esp),%esi // %esi = yptr 382 movl 16(%esp),%ecx // %ecx = count 383 subl %edx,%esi 384 jecxz L(alu2) // %ecx = 0 ? 385 L(alu1:) movl (%edx,%esi),%eax // *yptr 386 andl %eax,(%edx) // *xptr &= ... 387 leal 4(%edx),%edx // xptr++, yptr++ 388 decl %ecx 389 jnz L(alu1) 390 L(alu2:) popl %esi // %esi zurück 391 ret 392 393 // extern void eqv_loop_up (uintD* xptr, uintD* yptr, uintC count); 394 ALIGN 395 DECLARE_FUNCTION(eqv_loop_up) 396 C(eqv_loop_up:) 397 pushl %esi // %esi retten 398 movl 8(%esp),%edx // %edx = xptr 399 movl 12(%esp),%esi // %esi = yptr 400 movl 16(%esp),%ecx // %ecx = count 401 subl %edx,%esi 402 jecxz L(elu2) // %ecx = 0 ? 403 L(elu1:) movl (%edx),%eax // *xptr 404 xorl (%edx,%esi),%eax // ^ *yptr 405 notl %eax // ~(...) 406 movl %eax,(%edx) // =: *xptr 407 leal 4(%edx),%edx // xptr++, yptr++ 408 decl %ecx 409 jnz L(elu1) 410 L(elu2:) popl %esi // %esi zurück 411 ret 412 413 // extern void nand_loop_up (uintD* xptr, uintD* yptr, uintC count); 414 ALIGN 415 DECLARE_FUNCTION(nand_loop_up) 416 C(nand_loop_up:) 417 pushl %esi // %esi retten 418 movl 8(%esp),%edx // %edx = xptr 419 movl 12(%esp),%esi // %esi = yptr 420 movl 16(%esp),%ecx // %ecx = count 421 subl %edx,%esi 422 jecxz L(nalu2) // %ecx = 0 ? 423 L(nalu1:) movl (%edx),%eax // *xptr 424 andl (%edx,%esi),%eax // & *yptr 425 notl %eax // ~(...) 426 movl %eax,(%edx) // =: *xptr 427 leal 4(%edx),%edx // xptr++, yptr++ 428 decl %ecx 429 jnz L(nalu1) 430 L(nalu2:) popl %esi // %esi zurück 431 ret 432 433 // extern void nor_loop_up (uintD* xptr, uintD* yptr, uintC count); 434 ALIGN 435 DECLARE_FUNCTION(nor_loop_up) 436 C(nor_loop_up:) 437 pushl %esi // %esi retten 438 movl 8(%esp),%edx // %edx = xptr 439 movl 12(%esp),%esi // %esi = yptr 440 movl 16(%esp),%ecx // %ecx = count 441 subl %edx,%esi 442 jecxz L(nolu2) // %ecx = 0 ? 443 L(nolu1:) movl (%edx),%eax // *xptr 444 orl (%edx,%esi),%eax // | *yptr 445 notl %eax // ~(...) 446 movl %eax,(%edx) // =: *xptr 447 leal 4(%edx),%edx // xptr++, yptr++ 448 decl %ecx 449 jnz L(nolu1) 450 L(nolu2:) popl %esi // %esi zurück 451 ret 452 453 // extern void andc2_loop_up (uintD* xptr, uintD* yptr, uintC count); 454 ALIGN 455 DECLARE_FUNCTION(andc2_loop_up) 456 C(andc2_loop_up:) 457 pushl %esi // %esi retten 458 movl 8(%esp),%edx // %edx = xptr 459 movl 12(%esp),%esi // %esi = yptr 460 movl 16(%esp),%ecx // %ecx = count 461 subl %edx,%esi 462 jecxz L(aclu2) // %ecx = 0 ? 463 L(aclu1:) movl (%edx,%esi),%eax // *yptr 464 notl %eax // ~ *yptr 465 andl %eax,(%edx) // *xptr &= ... 466 leal 4(%edx),%edx // xptr++, yptr++ 467 decl %ecx 468 jnz L(aclu1) 469 L(aclu2:) popl %esi // %esi zurück 470 ret 471 472 // extern void orc2_loop_up (uintD* xptr, uintD* yptr, uintC count); 473 ALIGN 474 DECLARE_FUNCTION(orc2_loop_up) 475 C(orc2_loop_up:) 476 pushl %esi // %esi retten 477 movl 8(%esp),%edx // %edx = xptr 478 movl 12(%esp),%esi // %esi = yptr 479 movl 16(%esp),%ecx // %ecx = count 480 subl %edx,%esi 481 jecxz L(oclu2) // %ecx = 0 ? 482 L(oclu1:) movl (%edx,%esi),%eax // *yptr 483 notl %eax // ~ *yptr 484 orl %eax,(%edx) // *xptr |= ... 485 leal 4(%edx),%edx // xptr++, yptr++ 486 decl %ecx 487 jnz L(oclu1) 488 L(oclu2:) popl %esi // %esi zurück 489 ret 490 491 // extern void not_loop_up (uintD* xptr, uintC count); 492 ALIGN 493 DECLARE_FUNCTION(not_loop_up) 494 C(not_loop_up:) 495 movl 4(%esp),%edx // %edx = xptr 496 movl 8(%esp),%ecx // %ecx = count 497 jecxz L(nlu2) // %ecx = 0 ? 498 nop ; nop ; nop ; nop ; nop ; nop 499 L(nlu1:) notl (%edx) // ~= *xptr 500 leal 4(%edx),%edx // xptr++ 501 decl %ecx 502 jnz L(nlu1) 503 L(nlu2:) ret 504 505 // extern boolean and_test_loop_up (uintD* xptr, uintD* yptr, uintC count); 506 ALIGN 507 DECLARE_FUNCTION(and_test_loop_up) 508 C(and_test_loop_up:) 509 pushl %esi // %esi retten 510 movl 8(%esp),%edx // %edx = xptr 511 movl 12(%esp),%esi // %esi = yptr 512 movl 16(%esp),%ecx // %ecx = count 513 jecxz L(atlu2) // %ecx = 0 ? 514 subl %edx,%esi 515 L(atlu1:) movl (%edx,%esi),%eax // *yptr 516 andl (%edx),%eax // *xptr & ... 517 jnz L(atlu3) 518 leal 4(%edx),%edx // xptr++, yptr++ 519 decl %ecx 520 jnz L(atlu1) 521 L(atlu2:) xorl %eax,%eax // Ergebnis 0 522 popl %esi // %esi zurück 523 ret 524 L(atlu3:) movl $1,%eax // Ergebnis 1 (nicht irgendwas /=0 !) 525 popl %esi // %esi zurück 526 ret 527 528 #endif 529 530 // extern cl_signean compare_loop_up (uintD* xptr, uintD* yptr, uintC count); 531 ALIGN 532 DECLARE_FUNCTION(compare_loop_up) 533 C(compare_loop_up:) 534 movl %esi,%edx // %esi retten 535 movl %edi,%eax // %edi retten 536 movl 4(%esp),%esi // %esi = xptr 537 movl 8(%esp),%edi // %edi = yptr 538 movl 12(%esp),%ecx // %ecx = count 539 cmpl %ecx,%ecx // initialize flags for the case %ecx is 0 540 dir0start 541 repz // Falls %ecx > 0: 542 cmpsl // %ecx mal aufwärts (%edi) und (%esi) vergleichen 543 // und weiterschleifen, falls Z, d.h. (%edi)=(%esi). 544 dir0end 545 // Flags -> Ergebnis: 546 // Z,NC -> bis zum Schluß (%esi)-(%edi) = 0 -> x=y -> Ergebnis 0 547 // NZ,C -> schließlich (%esi)-(%edi) < 0 -> x<y -> Ergebnis -1 548 // NZ,NC -> schließlich (%esi)-(%edi) > 0 -> x>y -> Ergebnis +1 549 movl %eax,%edi // %edi zurück 550 movl %edx,%esi // %esi zurück 551 jbe L(cmlu1) // "be" = Z oder C 552 movl $1,%eax // Ergebnis +1 553 ret 554 L(cmlu1:) sbbl %eax,%eax // Ergebnis -1 (falls C) oder 0 (falls NC) 555 ret 556 557 #if CL_DS_BIG_ENDIAN_P 558 559 // extern uintD add_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); 560 ALIGN 561 DECLARE_FUNCTION(add_loop_down) 562 C(add_loop_down:) 563 pushl %esi // %esi retten 564 pushl %edi // %edi retten 565 movl 12(%esp),%edx // %edx = sourceptr1 566 movl 16(%esp),%esi // %esi = sourceptr2 567 movl 20(%esp),%edi // %edi = destptr 568 movl 24(%esp),%ecx // %ecx = count 569 subl %edi,%edx 570 subl %edi,%esi 571 orl %ecx,%ecx // %ecx = 0 ?, Carry löschen 572 jz L(ald2) 573 L(ald1:) leal -4(%edi),%edi // sourceptr1--, sourceptr2--, destptr-- 574 movl (%edx,%edi),%eax // *sourceptr1 575 adcl (%esi,%edi),%eax // + *sourceptr2 + carry 576 movl %eax,(%edi) // =: *destptr, neuen Carry behalten 577 decl %ecx 578 jnz L(ald1) 579 L(ald2:) sbbl %eax,%eax // Ergebnis := - Carry 580 popl %edi // %edi zurück 581 popl %esi // %esi zurück 582 ret 583 584 // extern uintD addto_loop_down (uintD* sourceptr, uintD* destptr, uintC count); 585 ALIGN 586 DECLARE_FUNCTION(addto_loop_down) 587 C(addto_loop_down:) 588 pushl %edi // %edi retten 589 movl 8(%esp),%edx // %edx = sourceptr 590 movl 12(%esp),%edi // %edi = destptr 591 movl 16(%esp),%ecx // %ecx = count 592 subl %edi,%edx 593 orl %ecx,%ecx // %ecx = 0 ?, Carry löschen 594 jz L(atld2) 595 L(atld1:) leal -4(%edi),%edi // sourceptr--, destptr-- 596 movl (%edx,%edi),%eax // *sourceptr 597 adcl %eax,(%edi) // + *destptr + carry =: *destptr, neuer Carry 598 decl %ecx 599 jnz L(atld1) 600 L(atld2:) sbbl %eax,%eax // Ergebnis := - Carry 601 popl %edi // %edi zurück 602 ret 603 604 // extern uintD inc_loop_down (uintD* ptr, uintC count); 605 ALIGN 606 DECLARE_FUNCTION(inc_loop_down) 607 C(inc_loop_down:) 608 movl 4(%esp),%edx // %edx = ptr 609 movl 8(%esp),%ecx // %ecx = count 610 jecxz L(ild2) // %ecx = 0 ? 611 L(ild1:) leal -4(%edx),%edx 612 addl $1,(%edx) // (*ptr)++ 613 jnc L(ild3) // kein Carry -> fertig 614 decl %ecx 615 jnz L(ild1) 616 L(ild2:) movl $1,%eax // Ergebnis := 1 617 ret 618 L(ild3:) xorl %eax,%eax // Ergebnis := 0 619 ret 620 621 // extern uintD sub_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); 622 ALIGN 623 DECLARE_FUNCTION(sub_loop_down) 624 C(sub_loop_down:) 625 pushl %esi // %esi retten 626 pushl %edi // %edi retten 627 movl 12(%esp),%edx // %edx = sourceptr1 628 movl 16(%esp),%esi // %esi = sourceptr2 629 movl 20(%esp),%edi // %edi = destptr 630 movl 24(%esp),%ecx // %ecx = count 631 subl %edi,%edx 632 subl %edi,%esi 633 orl %ecx,%ecx // %ecx = 0 ?, Carry löschen 634 jz L(sld2) 635 L(sld1:) leal -4(%edi),%edi // sourceptr1--, sourceptr2--, destptr-- 636 movl (%edx,%edi),%eax // *sourceptr1 637 sbbl (%esi,%edi),%eax // - *sourceptr2 - carry 638 movl %eax,(%edi) // =: *destptr, neuen Carry behalten 639 decl %ecx 640 jnz L(sld1) 641 L(sld2:) sbbl %eax,%eax // Ergebnis := - Carry 642 popl %edi // %edi zurück 643 popl %esi // %esi zurück 644 ret 645 646 // extern uintD subx_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry); 647 ALIGN 648 DECLARE_FUNCTION(subx_loop_down) 649 C(subx_loop_down:) 650 pushl %esi // %esi retten 651 pushl %edi // %edi retten 652 movl 12(%esp),%edx // %edx = sourceptr1 653 movl 16(%esp),%esi // %esi = sourceptr2 654 movl 20(%esp),%edi // %edi = destptr 655 movl 24(%esp),%ecx // %ecx = count 656 jecxz L(sxld2) // %ecx = 0 ? 657 subl %edi,%edx 658 subl %edi,%esi 659 movl 28(%esp),%eax // carry, 0 oder -1 660 addl %eax,%eax // Bit 31 davon in den Carry 661 nop ; nop 662 L(sxld1:) leal -4(%edi),%edi // sourceptr1--, sourceptr2--, destptr-- 663 movl (%edx,%edi),%eax // *sourceptr1 664 sbbl (%esi,%edi),%eax // - *sourceptr2 - carry 665 movl %eax,(%edi) // =: *destptr, neuen Carry behalten 666 decl %ecx 667 jnz L(sxld1) 668 sbbl %eax,%eax // Ergebnis := - Carry 669 popl %edi // %edi zurück 670 popl %esi // %esi zurück 671 ret 672 L(sxld2:) movl 28(%esp),%eax // Ergebnis := carry 673 popl %edi // %edi zurück 674 popl %esi // %esi zurück 675 ret 676 677 // extern uintD subfrom_loop_down (uintD* sourceptr, uintD* destptr, uintC count); 678 ALIGN 679 DECLARE_FUNCTION(subfrom_loop_down) 680 C(subfrom_loop_down:) 681 pushl %edi // %edi retten 682 movl 8(%esp),%edx // %edx = sourceptr 683 movl 12(%esp),%edi // %edi = destptr 684 movl 16(%esp),%ecx // %ecx = count 685 subl %edi,%edx 686 orl %ecx,%ecx // %ecx = 0 ?, Carry löschen 687 jz L(sfld2) 688 L(sfld1:) leal -4(%edi),%edi // sourceptr--, destptr-- 689 movl (%edx,%edi),%eax // *sourceptr 690 sbbl %eax,(%edi) // *destptr - *sourceptr - carry =: *destptr, neuer Carry 691 decl %ecx 692 jnz L(sfld1) 693 L(sfld2:) sbbl %eax,%eax // Ergebnis := - Carry 694 popl %edi // %edi zurück 695 ret 696 697 // extern uintD dec_loop_down (uintD* ptr, uintC count); 698 ALIGN 699 DECLARE_FUNCTION(dec_loop_down) 700 C(dec_loop_down:) 701 movl 4(%esp),%edx // %edx = ptr 702 movl 8(%esp),%ecx // %ecx = count 703 jecxz L(dld2) // %ecx = 0 ? 704 L(dld1:) leal -4(%edx),%edx 705 subl $1,(%edx) // (*ptr)-- 706 jnc L(dld3) // kein Carry -> fertig 707 decl %ecx 708 jnz L(dld1) 709 L(dld2:) movl $-1,%eax // Ergebnis := -1 710 ret 711 L(dld3:) xorl %eax,%eax // Ergebnis := 0 712 ret 713 714 // extern uintD neg_loop_down (uintD* ptr, uintC count); 715 ALIGN 716 DECLARE_FUNCTION(neg_loop_down) 717 C(neg_loop_down:) 718 movl 4(%esp),%edx // %edx = ptr 719 movl 8(%esp),%ecx // %ecx = count 720 // erstes Digit /=0 suchen: 721 jecxz L(nld2) // %ecx = 0 ? 722 L(nld1:) leal -4(%edx),%edx 723 negl (%edx) 724 jnz L(nld3) 725 decl %ecx 726 jnz L(nld1) 727 L(nld2:) xorl %eax,%eax // Ergebnis := 0 728 ret 729 nop ; nop ; nop ; nop ; nop ; nop 730 L(nld3:) // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys 731 // alle anderen Digits invertieren: 732 decl %ecx 733 jz L(nld5) 734 L(nld4:) leal -4(%edx),%edx 735 notl (%edx) 736 decl %ecx 737 jnz L(nld4) 738 L(nld5:) movl $-1,%eax // Ergebnis := -1 739 ret 740 741 // extern uintD shift1left_loop_down (uintD* ptr, uintC count); 742 ALIGN 743 DECLARE_FUNCTION(shift1left_loop_down) 744 C(shift1left_loop_down:) 745 movl 4(%esp),%edx // %edx = ptr 746 movl 8(%esp),%ecx // %ecx = count 747 orl %ecx,%ecx // %ecx = 0 ?, Carry löschen 748 jz L(s1lld2) 749 nop ; nop ; nop ; nop 750 L(s1lld1:) leal -4(%edx),%edx // ptr-- 751 rcll $1,(%edx) // *ptr und Carry um 1 Bit links rotieren 752 decl %ecx 753 jnz L(s1lld1) 754 L(s1lld2:) sbbl %eax,%eax // Ergebnis := - Carry 755 ret 756 757 // extern uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry); 758 ALIGN 759 DECLARE_FUNCTION(shiftleft_loop_down) 760 C(shiftleft_loop_down:) 761 pushl %edi // %edi retten 762 pushl %ebx // %ebx retten 763 movl 12(%esp),%edi // %edi = ptr 764 movl 16(%esp),%edx // %edx = count 765 movb 20(%esp),%cl // %cl = i 766 orl %edx,%edx // count = 0 ? 767 jz L(slld4) 768 // erstes Digit shiften: 769 leal -4(%edi),%edi 770 movl (%edi),%eax // Digit in %eax halten 771 movl %eax,%ebx // und in %ebx rechnen: 772 shll %cl,%ebx // um i Bits links shiften 773 orl 24(%esp),%ebx // und die unteren i Bits eintragen 774 movl %ebx,(%edi) // und wieder ablegen 775 // Letztes Digit in %eax. 776 decl %edx 777 jz L(slld2) 778 nop ; nop ; nop ; nop 779 L(slld1:) // weiteres Digit shiften: 780 leal -4(%edi),%edi 781 movl (%edi),%ebx 782 shldl shcl %eax,(%edi) // (%edi) um %cl=i Bits links shiften, %eax von rechts reinshiften 783 // Letztes Digit in %ebx. 784 decl %edx 785 jz L(slld3) 786 // weiteres Digit shiften: 787 leal -4(%edi),%edi 788 movl (%edi),%eax 789 shldl shcl %ebx,(%edi) // (%edi) um %cl=i Bits links shiften, %ebx von rechts reinshiften 790 // Letztes Digit in %eax. 791 decl %edx 792 jnz L(slld1) 793 L(slld2:) movl %eax,%ebx 794 L(slld3:) xorl %eax,%eax // %eax := 0 795 shldl shcl %ebx,%eax // %eax := höchste %cl=i Bits von %ebx 796 popl %ebx // %ebx zurück 797 popl %edi // %edi zurück 798 ret 799 L(slld4:) movl 24(%esp),%eax // %eax := carry 800 popl %ebx // %ebx zurück 801 popl %edi // %edi zurück 802 ret 803 804 // extern uintD shiftleftcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i); 805 ALIGN 806 DECLARE_FUNCTION(shiftleftcopy_loop_down) 807 C(shiftleftcopy_loop_down:) 808 pushl %esi // %esi retten 809 pushl %edi // %edi retten 810 pushl %ebx // %ebx retten 811 movl 16(%esp),%esi // %esi = sourceptr 812 movl 20(%esp),%edi // %edi = destptr 813 movl 24(%esp),%edx // count 814 movb 28(%esp),%cl // i 815 orl %edx,%edx // count = 0 ? 816 jz L(slcld4) 817 subl %edi,%esi 818 // erstes Digit shiften: 819 leal -4(%edi),%edi // sourceptr--, destptr-- 820 movl (%edi,%esi),%ebx // *sourceptr in %ebx halten 821 movl %ebx,%eax // und in %eax rechnen: 822 shll %cl,%eax // um i Bits links shiften, rechts Nullen rein 823 movl %eax,(%edi) // und als *destptr ablegen 824 // Letztes Digit in %ebx. 825 negb %cl // 32-i 826 decl %edx 827 jz L(slcld2) 828 L(slcld1:) // weiteres Digit shiften: 829 leal -4(%edi),%edi // sourceptr--, destptr-- 830 movl (%edi,%esi),%eax // nächstes Digit nach %eax 831 shrdl shcl %eax,%ebx // %ebx um %cl=32-i Bits rechts shiften, %eax von links reinshiften 832 movl %ebx,(%edi) // %ebx als *destptr ablegen 833 // Letztes Digit in %eax. 834 decl %edx 835 jz L(slcld3) 836 // weiteres Digit shiften: 837 leal -4(%edi),%edi // sourceptr--, destptr-- 838 movl (%edi,%esi),%ebx // nächstes Digit nach %ebx 839 shrdl shcl %ebx,%eax // %eax um %cl=32-i Bits rechts shiften, %ebx von links reinshiften 840 movl %eax,(%edi) // %eax als *destptr ablegen 841 // Letztes Digit in %ebx. 842 decl %edx 843 jnz L(slcld1) 844 L(slcld2:) movl %ebx,%eax 845 L(slcld3:) shrl %cl,%eax // %eax um 32-i Bits nach rechts shiften 846 popl %ebx // %ebx zurück 847 popl %edi // %edi zurück 848 popl %esi // %esi zurück 849 ret 850 L(slcld4:) xorl %eax,%eax // %eax := 0 851 popl %ebx // %ebx zurück 852 popl %edi // %edi zurück 853 popl %esi // %esi zurück 854 ret 855 856 // extern uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry); 857 ALIGN 858 DECLARE_FUNCTION(shift1right_loop_up) 859 C(shift1right_loop_up:) 860 movl 4(%esp),%edx // %edx = ptr 861 movl 8(%esp),%ecx // %ecx = count 862 movl 12(%esp),%eax // %eax = carry (0 oder -1) 863 jecxz L(s1rld3) // %ecx = 0 ? 864 addl %eax,%eax // Carry := Bit 31 von carry 865 L(s1rld1:) rcrl $1,(%edx) // *ptr und Carry um 1 Bit rechts rotieren 866 leal 4(%edx),%edx // ptr++ 867 decl %ecx 868 jnz L(s1rld1) 869 L(s1rld2:) sbbl %eax,%eax // Ergebnis := - Carry 870 L(s1rld3:) ret 871 872 // extern uintD shiftright_loop_up (uintD* ptr, uintC count, uintC i); 873 ALIGN 874 DECLARE_FUNCTION(shiftright_loop_up) 875 C(shiftright_loop_up:) 876 pushl %edi // %edi retten 877 pushl %ebx // %ebx retten 878 movl 12(%esp),%edi // %edi = ptr 879 movl 16(%esp),%edx // %edx = count 880 movb 20(%esp),%cl // %cl = i 881 orl %edx,%edx // count = 0 ? 882 jz L(srlu4) 883 // erstes Digit shiften: 884 movl (%edi),%eax // Digit in %eax halten 885 movl %eax,%ebx // und in %ebx rechnen: 886 shrl %cl,%ebx // um i Bits rechts shiften 887 movl %ebx,(%edi) // und wieder ablegen 888 // Letztes Digit in %eax. 889 decl %edx 890 jz L(srlu2) 891 nop ; nop ; nop 892 L(srlu1:) // weiteres Digit shiften: 893 leal 4(%edi),%edi 894 movl (%edi),%ebx 895 shrdl shcl %eax,(%edi) // (%edi) um %cl=i Bits rechts shiften, %eax von links reinshiften 896 // Letztes Digit in %ebx. 897 decl %edx 898 jz L(srlu3) 899 // weiteres Digit shiften: 900 leal 4(%edi),%edi 901 movl (%edi),%eax 902 shrdl shcl %ebx,(%edi) // (%edi) um %cl=i Bits rechts shiften, %ebx von links reinshiften 903 // Letztes Digit in %eax. 904 decl %edx 905 jnz L(srlu1) 906 L(srlu2:) movl %eax,%ebx 907 L(srlu3:) xorl %eax,%eax // %eax := 0 908 shrdl shcl %ebx,%eax // %eax := niedrigste %cl=i Bits von %ebx, als Bits 31..32-i 909 popl %ebx // %ebx zurück 910 popl %edi // %edi zurück 911 ret 912 L(srlu4:) xorl %eax,%eax // %eax := 0 913 popl %ebx // %ebx zurück 914 popl %edi // %edi zurück 915 ret 916 917 // extern uintD shiftrightsigned_loop_up (uintD* ptr, uintC count, uintC i); 918 ALIGN 919 DECLARE_FUNCTION(shiftrightsigned_loop_up) 920 C(shiftrightsigned_loop_up:) 921 pushl %edi // %edi retten 922 pushl %ebx // %ebx retten 923 movl 12(%esp),%edi // %edi = ptr 924 movl 16(%esp),%edx // %edx = count 925 movb 20(%esp),%cl // %cl = i 926 // erstes Digit shiften: 927 movl (%edi),%eax // Digit in %eax halten 928 movl %eax,%ebx // und in %ebx rechnen: 929 sarl %cl,%ebx // um i Bits rechts shiften, Vorzeichen vervielfachen 930 movl %ebx,(%edi) // und wieder ablegen 931 // Letztes Digit in %eax. 932 decl %edx 933 jz L(srslu2) 934 L(srslu1:) // weiteres Digit shiften: 935 leal 4(%edi),%edi 936 movl (%edi),%ebx 937 shrdl shcl %eax,(%edi) // (%edi) um %cl=i Bits rechts shiften, %eax von links reinshiften 938 // Letztes Digit in %ebx. 939 decl %edx 940 jz L(srslu3) 941 // weiteres Digit shiften: 942 leal 4(%edi),%edi 943 movl (%edi),%eax 944 shrdl shcl %ebx,(%edi) // (%edi) um %cl=i Bits rechts shiften, %ebx von links reinshiften 945 // Letztes Digit in %eax. 946 decl %edx 947 jnz L(srslu1) 948 L(srslu2:) movl %eax,%ebx 949 L(srslu3:) xorl %eax,%eax // %eax := 0 950 shrdl shcl %ebx,%eax // %eax := niedrigste %cl=i Bits von %ebx, als Bits 31..32-i 951 popl %ebx // %ebx zurück 952 popl %edi // %edi zurück 953 ret 954 955 // extern uintD shiftrightcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry); 956 ALIGN 957 DECLARE_FUNCTION(shiftrightcopy_loop_up) 958 C(shiftrightcopy_loop_up:) 959 pushl %esi // %esi retten 960 pushl %edi // %edi retten 961 pushl %ebx // %ebx retten 962 movl 16(%esp),%esi // %esi = sourceptr 963 movl 20(%esp),%edi // %edi = destptr 964 movl 24(%esp),%edx // count 965 movb 28(%esp),%cl // i 966 negb %cl // 32-i 967 movl 32(%esp),%eax // %eax = carry 968 orl %edx,%edx // count = 0 ? 969 jz L(srcld3) 970 subl %edi,%esi 971 // erstes Digit shiften: 972 movl (%edi,%esi),%ebx // *sourceptr in %ebx halten 973 shldl shcl %ebx,%eax // carry um %cl=32-i Bits links shiften, dabei *sourceptr rein 974 movl %eax,(%edi) // und als *destptr ablegen 975 // Letztes Digit in %ebx. 976 decl %edx 977 jz L(srcld2) 978 L(srcld1:) // weiteres Digit shiften: 979 leal 4(%edi),%edi // sourceptr++, destptr++ 980 movl (%edi,%esi),%eax // nächstes Digit nach %eax 981 shldl shcl %eax,%ebx // %ebx um %cl=32-i Bits links shiften, %eax von rechts reinshiften 982 movl %ebx,(%edi) // %ebx als *destptr ablegen 983 // Letztes Digit in %eax. 984 decl %edx 985 jz L(srcld3) 986 // weiteres Digit shiften: 987 leal 4(%edi),%edi // sourceptr++, destptr++ 988 movl (%edi,%esi),%ebx // nächstes Digit nach %ebx 989 shldl shcl %ebx,%eax // %eax um %cl=32-i Bits links shiften, %ebx von rechts reinshiften 990 movl %eax,(%edi) // %eax als *destptr ablegen 991 // Letztes Digit in %ebx. 992 decl %edx 993 jnz L(srcld1) 994 L(srcld2:) movl %ebx,%eax 995 L(srcld3:) shll %cl,%eax // %eax um 32-i Bits nach links shiften 996 popl %ebx // %ebx zurück 997 popl %edi // %edi zurück 998 popl %esi // %esi zurück 999 ret 1000 1001 // extern uintD mulusmall_loop_down (uintD digit, uintD* ptr, uintC len, uintD newdigit); 1002 ALIGN 1003 DECLARE_FUNCTION(mulusmall_loop_down) 1004 C(mulusmall_loop_down:) 1005 pushl %ebp // %ebp retten 1006 pushl %edi // %edi retten 1007 pushl %ebx // %ebx retten 1008 movl 16(%esp),%ebx // %ebx = digit 1009 movl 20(%esp),%edi // %edi = ptr 1010 movl 24(%esp),%ecx // %ecx = len 1011 movl 28(%esp),%ebp // %ebp = carry := newdigit 1012 movl %ecx,%eax 1013 negl %eax // %eax = -len 1014 jz L(msld2) 1015 leal -4(%edi,%eax,4),%edi // %edi = &ptr[-1-len] 1016 nop ; nop ; nop 1017 L(msld1:) movl (%edi,%ecx,4),%eax // *ptr 1018 mull %ebx // %edx|%eax := digit * *ptr 1019 addl %ebp,%eax // carry und Low-Teil des Produktes addieren 1020 movl $0,%ebp 1021 adcl %edx,%ebp // Übertrag zum High-Teil %edx dazu, gibt neuen carry 1022 movl %eax,(%edi,%ecx,4) // Low-Teil als *ptr ablegen 1023 decl %ecx // count--, ptr-- 1024 jnz L(msld1) 1025 L(msld2:) movl %ebp,%eax // Ergebnis := letzter Übertrag 1026 popl %ebx // %ebx zurück 1027 popl %edi // %edi zurück 1028 popl %ebp // %ebp zurück 1029 ret 1030 1031 // extern void mulu_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); 1032 ALIGN 1033 DECLARE_FUNCTION(mulu_loop_down) 1034 C(mulu_loop_down:) 1035 pushl %ebp // %ebp retten 1036 pushl %edi // %edi retten 1037 pushl %esi // %esi retten 1038 pushl %ebx // %ebx retten 1039 movl 20(%esp),%ebx // %ebx = digit 1040 movl 24(%esp),%esi // %esi = sourceptr 1041 movl 28(%esp),%edi // %edi = destptr 1042 movl 32(%esp),%ecx // %ecx = len 1043 movl %ecx,%eax 1044 notl %eax // %eax = -1-len 1045 leal (%esi,%eax,4),%esi // %esi = &sourceptr[-1-len] 1046 leal (%edi,%eax,4),%edi // %edi = &destptr[-1-len] 1047 xorl %ebp,%ebp // %epb = carry := 0 1048 L(muld1:) movl (%esi,%ecx,4),%eax // *sourceptr 1049 mull %ebx // %edx|%eax := digit * *sourceptr 1050 addl %ebp,%eax // carry und Low-Teil des Produktes addieren 1051 movl $0,%ebp 1052 adcl %edx,%ebp // Übertrag zum High-Teil %edx dazu, gibt neuen carry 1053 movl %eax,(%edi,%ecx,4) // Low-Teil als *destptr ablegen 1054 decl %ecx // count--, sourceptr--, destptr-- 1055 jnz L(muld1) 1056 movl %ebp,(%edi) // letzten Übertrag ablegen 1057 popl %ebx // %ebx zurück 1058 popl %esi // %esi zurück 1059 popl %edi // %edi zurück 1060 popl %ebp // %ebp zurück 1061 ret 1062 1063 // extern uintD muluadd_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); 1064 ALIGN 1065 DECLARE_FUNCTION(muluadd_loop_down) 1066 C(muluadd_loop_down:) 1067 pushl %ebp // %ebp retten 1068 pushl %edi // %edi retten 1069 pushl %esi // %esi retten 1070 pushl %ebx // %ebx retten 1071 movl 20(%esp),%ebx // %ebx = digit 1072 movl 24(%esp),%esi // %esi = sourceptr 1073 movl 28(%esp),%edi // %edi = destptr 1074 movl 32(%esp),%ecx // %ecx = len 1075 movl %ecx,%eax 1076 notl %eax // %eax = -1-len 1077 leal (%esi,%eax,4),%esi // %esi = &sourceptr[-1-len] 1078 leal (%edi,%eax,4),%edi // %edi = &destptr[-1-len] 1079 xorl %ebp,%ebp // %epb = carry := 0 1080 L(muald1:) movl (%esi,%ecx,4),%eax // *sourceptr 1081 mull %ebx // %edx|%eax := digit * *sourceptr 1082 addl %ebp,%eax // carry und Low-Teil des Produktes addieren 1083 movl $0,%ebp 1084 adcl %ebp,%edx // Übertrag zum High-Teil %edx dazu 1085 addl %eax,(%edi,%ecx,4) // Low-Teil zu *destptr addieren 1086 adcl %edx,%ebp // zweiten Übertrag zu %edx addieren, gibt neuen carry 1087 decl %ecx // count--, sourceptr--, destptr-- 1088 jnz L(muald1) 1089 movl %ebp,%eax // Ergebnis := letzter Übertrag 1090 popl %ebx // %ebx zurück 1091 popl %esi // %esi zurück 1092 popl %edi // %edi zurück 1093 popl %ebp // %ebp zurück 1094 ret 1095 1096 // extern uintD mulusub_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); 1097 ALIGN 1098 DECLARE_FUNCTION(mulusub_loop_down) 1099 C(mulusub_loop_down:) 1100 pushl %ebp // %ebp retten 1101 pushl %edi // %edi retten 1102 pushl %esi // %esi retten 1103 pushl %ebx // %ebx retten 1104 movl 20(%esp),%ebx // %ebx = digit 1105 movl 24(%esp),%esi // %esi = sourceptr 1106 movl 28(%esp),%edi // %edi = destptr 1107 movl 32(%esp),%ecx // %ecx = len 1108 movl %ecx,%eax 1109 notl %eax // %eax = -1-len 1110 leal (%esi,%eax,4),%esi // %esi = &sourceptr[-1-len] 1111 leal (%edi,%eax,4),%edi // %edi = &destptr[-1-len] 1112 xorl %ebp,%ebp // %epb = carry := 0 1113 L(musld1:) movl (%esi,%ecx,4),%eax // *sourceptr 1114 mull %ebx // %edx|%eax := digit * *sourceptr 1115 addl %ebp,%eax // carry und Low-Teil des Produktes addieren 1116 movl $0,%ebp 1117 adcl %ebp,%edx // Übertrag zum High-Teil %edx dazu 1118 subl %eax,(%edi,%ecx,4) // Low-Teil von *destptr subtrahieren 1119 adcl %edx,%ebp // zweiten Übertrag zu %edx addieren, gibt neuen carry 1120 decl %ecx // count--, sourceptr--, destptr-- 1121 jnz L(musld1) 1122 movl %ebp,%eax // Ergebnis := letzter Übertrag 1123 popl %ebx // %ebx zurück 1124 popl %esi // %esi zurück 1125 popl %edi // %edi zurück 1126 popl %ebp // %ebp zurück 1127 ret 1128 1129 // extern uintD divu_loop_up (uintD digit, uintD* ptr, uintC len); 1130 ALIGN 1131 DECLARE_FUNCTION(divu_loop_up) 1132 C(divu_loop_up:) 1133 pushl %edi // %edi retten 1134 pushl %ebx // %ebx retten 1135 movl 12(%esp),%ebx // %ebx = digit 1136 movl 16(%esp),%edi // %edi = ptr 1137 movl 20(%esp),%ecx // %ecx = len 1138 xorl %edx,%edx // %edx = Rest := 0 1139 jecxz L(dlu2) // %ecx = 0 ? 1140 L(dlu1:) movl (%edi),%eax // nächstes Digit *ptr 1141 divl %ebx // Division von %edx|%eax durch %ebx 1142 movl %eax,(%edi) // Quotient %eax ablegen, Rest in %edx behalten 1143 leal 4(%edi),%edi // ptr++ 1144 decl %ecx 1145 jnz L(dlu1) 1146 L(dlu2:) movl %edx,%eax // Ergebnis := letzter Rest 1147 popl %ebx // %ebx zurück 1148 popl %edi // %edi zurück 1149 ret 1150 1151 // extern uintD divucopy_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); 1152 ALIGN 1153 DECLARE_FUNCTION(divucopy_loop_up) 1154 C(divucopy_loop_up:) 1155 pushl %edi // %edi retten 1156 pushl %esi // %esi retten 1157 pushl %ebx // %ebx retten 1158 movl 16(%esp),%ebx // %ebx = digit 1159 movl 20(%esp),%esi // %esi = sourceptr 1160 movl 24(%esp),%edi // %edi = destptr 1161 movl 28(%esp),%ecx // %ecx = len 1162 xorl %edx,%edx // %edx = Rest := 0 1163 jecxz L(dclu2) // %ecx = 0 ? 1164 subl %edi,%esi 1165 L(dclu1:) movl (%esi,%edi),%eax // nächstes Digit *ptr 1166 divl %ebx // Division von %edx|%eax durch %ebx 1167 movl %eax,(%edi) // Quotient %eax ablegen, Rest in %edx behalten 1168 leal 4(%edi),%edi // sourceptr++, destptr++ 1169 decl %ecx 1170 jnz L(dclu1) 1171 L(dclu2:) movl %edx,%eax // Ergebnis := letzter Rest 1172 popl %ebx // %ebx zurück 1173 popl %esi // %esi zurück 1174 popl %edi // %edi zurück 1175 ret 1176 1177 #endif 1178 1179 #if !CL_DS_BIG_ENDIAN_P 1180 1181 // extern void or_loop_down (uintD* xptr, uintD* yptr, uintC count); 1182 ALIGN 1183 DECLARE_FUNCTION(or_loop_down) 1184 C(or_loop_down:) 1185 pushl %esi // %esi retten 1186 movl 8(%esp),%edx // %edx = xptr 1187 movl 12(%esp),%esi // %esi = yptr 1188 movl 16(%esp),%ecx // %ecx = count 1189 subl %edx,%esi 1190 jecxz L(old2) // %ecx = 0 ? 1191 L(old1:) leal -4(%edx),%edx // xptr--, yptr-- 1192 movl (%edx,%esi),%eax // *yptr 1193 orl %eax,(%edx) // *xptr |= ... 1194 decl %ecx 1195 jnz L(old1) 1196 L(old2:) popl %esi // %esi zurück 1197 ret 1198 1199 // extern void xor_loop_down (uintD* xptr, uintD* yptr, uintC count); 1200 ALIGN 1201 DECLARE_FUNCTION(xor_loop_down) 1202 C(xor_loop_down:) 1203 pushl %esi // %esi retten 1204 movl 8(%esp),%edx // %edx = xptr 1205 movl 12(%esp),%esi // %esi = yptr 1206 movl 16(%esp),%ecx // %ecx = count 1207 subl %edx,%esi 1208 jecxz L(xld2) // %ecx = 0 ? 1209 L(xld1:) leal -4(%edx),%edx // xptr--, yptr-- 1210 movl (%edx,%esi),%eax // *yptr 1211 xorl %eax,(%edx) // *xptr ^= ... 1212 decl %ecx 1213 jnz L(xld1) 1214 L(xld2:) popl %esi // %esi zurück 1215 ret 1216 1217 // extern void and_loop_down (uintD* xptr, uintD* yptr, uintC count); 1218 ALIGN 1219 DECLARE_FUNCTION(and_loop_down) 1220 C(and_loop_down:) 1221 pushl %esi // %esi retten 1222 movl 8(%esp),%edx // %edx = xptr 1223 movl 12(%esp),%esi // %esi = yptr 1224 movl 16(%esp),%ecx // %ecx = count 1225 subl %edx,%esi 1226 jecxz L(ald2) // %ecx = 0 ? 1227 L(ald1:) leal -4(%edx),%edx // xptr--, yptr-- 1228 movl (%edx,%esi),%eax // *yptr 1229 andl %eax,(%edx) // *xptr &= ... 1230 decl %ecx 1231 jnz L(ald1) 1232 L(ald2:) popl %esi // %esi zurück 1233 ret 1234 1235 // extern void eqv_loop_down (uintD* xptr, uintD* yptr, uintC count); 1236 ALIGN 1237 DECLARE_FUNCTION(eqv_loop_down) 1238 C(eqv_loop_down:) 1239 pushl %esi // %esi retten 1240 movl 8(%esp),%edx // %edx = xptr 1241 movl 12(%esp),%esi // %esi = yptr 1242 movl 16(%esp),%ecx // %ecx = count 1243 subl %edx,%esi 1244 jecxz L(eld2) // %ecx = 0 ? 1245 L(eld1:) leal -4(%edx),%edx // xptr--, yptr-- 1246 movl (%edx),%eax // *xptr 1247 xorl (%edx,%esi),%eax // ^ *yptr 1248 notl %eax // ~(...) 1249 movl %eax,(%edx) // =: *xptr 1250 decl %ecx 1251 jnz L(eld1) 1252 L(eld2:) popl %esi // %esi zurück 1253 ret 1254 1255 // extern void nand_loop_down (uintD* xptr, uintD* yptr, uintC count); 1256 ALIGN 1257 DECLARE_FUNCTION(nand_loop_down) 1258 C(nand_loop_down:) 1259 pushl %esi // %esi retten 1260 movl 8(%esp),%edx // %edx = xptr 1261 movl 12(%esp),%esi // %esi = yptr 1262 movl 16(%esp),%ecx // %ecx = count 1263 subl %edx,%esi 1264 jecxz L(nald2) // %ecx = 0 ? 1265 L(nald1:) leal -4(%edx),%edx // xptr--, yptr-- 1266 movl (%edx),%eax // *xptr 1267 andl (%edx,%esi),%eax // & *yptr 1268 notl %eax // ~(...) 1269 movl %eax,(%edx) // =: *xptr 1270 decl %ecx 1271 jnz L(nald1) 1272 L(nald2:) popl %esi // %esi zurück 1273 ret 1274 1275 // extern void nor_loop_down (uintD* xptr, uintD* yptr, uintC count); 1276 ALIGN 1277 DECLARE_FUNCTION(nor_loop_down) 1278 C(nor_loop_down:) 1279 pushl %esi // %esi retten 1280 movl 8(%esp),%edx // %edx = xptr 1281 movl 12(%esp),%esi // %esi = yptr 1282 movl 16(%esp),%ecx // %ecx = count 1283 subl %edx,%esi 1284 jecxz L(nold2) // %ecx = 0 ? 1285 L(nold1:) leal -4(%edx),%edx // xptr--, yptr-- 1286 movl (%edx),%eax // *xptr 1287 orl (%edx,%esi),%eax // | *yptr 1288 notl %eax // ~(...) 1289 movl %eax,(%edx) // =: *xptr 1290 decl %ecx 1291 jnz L(nold1) 1292 L(nold2:) popl %esi // %esi zurück 1293 ret 1294 1295 // extern void andc2_loop_down (uintD* xptr, uintD* yptr, uintC count); 1296 ALIGN 1297 DECLARE_FUNCTION(andc2_loop_down) 1298 C(andc2_loop_down:) 1299 pushl %esi // %esi retten 1300 movl 8(%esp),%edx // %edx = xptr 1301 movl 12(%esp),%esi // %esi = yptr 1302 movl 16(%esp),%ecx // %ecx = count 1303 subl %edx,%esi 1304 jecxz L(acld2) // %ecx = 0 ? 1305 L(acld1:) leal -4(%edx),%edx // xptr--, yptr-- 1306 movl (%edx,%esi),%eax // *yptr 1307 notl %eax // ~ *yptr 1308 andl %eax,(%edx) // *xptr &= ... 1309 decl %ecx 1310 jnz L(acld1) 1311 L(acld2:) popl %esi // %esi zurück 1312 ret 1313 1314 // extern void orc2_loop_down (uintD* xptr, uintD* yptr, uintC count); 1315 ALIGN 1316 DECLARE_FUNCTION(orc2_loop_down) 1317 C(orc2_loop_down:) 1318 pushl %esi // %esi retten 1319 movl 8(%esp),%edx // %edx = xptr 1320 movl 12(%esp),%esi // %esi = yptr 1321 movl 16(%esp),%ecx // %ecx = count 1322 subl %edx,%esi 1323 jecxz L(ocld2) // %ecx = 0 ? 1324 L(ocld1:) leal -4(%edx),%edx // xptr--, yptr-- 1325 movl (%edx,%esi),%eax // *yptr 1326 notl %eax // ~ *yptr 1327 orl %eax,(%edx) // *xptr |= ... 1328 decl %ecx 1329 jnz L(ocld1) 1330 L(ocld2:) popl %esi // %esi zurück 1331 ret 1332 1333 // extern void not_loop_down (uintD* xptr, uintC count); 1334 ALIGN 1335 DECLARE_FUNCTION(not_loop_down) 1336 C(not_loop_down:) 1337 movl 4(%esp),%edx // %edx = xptr 1338 movl 8(%esp),%ecx // %ecx = count 1339 jecxz L(nld2) // %ecx = 0 ? 1340 nop ; nop ; nop ; nop ; nop ; nop 1341 L(nld1:) leal -4(%edx),%edx // xptr-- 1342 notl (%edx) // ~= *xptr 1343 decl %ecx 1344 jnz L(nld1) 1345 L(nld2:) ret 1346 1347 // extern boolean and_test_loop_down (uintD* xptr, uintD* yptr, uintC count); 1348 ALIGN 1349 DECLARE_FUNCTION(and_test_loop_down) 1350 C(and_test_loop_down:) 1351 pushl %esi // %esi retten 1352 movl 8(%esp),%edx // %edx = xptr 1353 movl 12(%esp),%esi // %esi = yptr 1354 movl 16(%esp),%ecx // %ecx = count 1355 jecxz L(atld2) // %ecx = 0 ? 1356 subl %edx,%esi 1357 L(atld1:) leal -4(%edx),%edx // xptr--, yptr-- 1358 movl (%edx,%esi),%eax // *yptr 1359 andl (%edx),%eax // *xptr & ... 1360 jnz L(atld3) 1361 decl %ecx 1362 jnz L(atld1) 1363 L(atld2:) xorl %eax,%eax // Ergebnis 0 1364 popl %esi // %esi zurück 1365 ret 1366 L(atld3:) movl $1,%eax // Ergebnis 1 (nicht irgendwas /=0 !) 1367 popl %esi // %esi zurück 1368 ret 1369 1370 // extern cl_signean compare_loop_down (uintD* xptr, uintD* yptr, uintC count); 1371 ALIGN 1372 DECLARE_FUNCTION(compare_loop_down) 1373 C(compare_loop_down:) 1374 movl %esi,%edx // %esi retten 1375 movl %edi,%eax // %edi retten 1376 movl 4(%esp),%esi // %esi = xptr 1377 movl 8(%esp),%edi // %edi = yptr 1378 movl 12(%esp),%ecx // %ecx = count 1379 leal -4(%esi),%esi 1380 leal -4(%edi),%edi 1381 cmpl %ecx,%ecx // initialize flags for the case %ecx is 0 1382 dir1start 1383 repz // Falls %ecx > 0: 1384 cmpsl // %ecx mal aufwärts (%edi) und (%esi) vergleichen 1385 // und weiterschleifen, falls Z, d.h. (%edi)=(%esi). 1386 dir1end 1387 // Flags -> Ergebnis: 1388 // Z,NC -> bis zum Schluß (%esi)-(%edi) = 0 -> x=y -> Ergebnis 0 1389 // NZ,C -> schließlich (%esi)-(%edi) < 0 -> x<y -> Ergebnis -1 1390 // NZ,NC -> schließlich (%esi)-(%edi) > 0 -> x>y -> Ergebnis +1 1391 movl %eax,%edi // %edi zurück 1392 movl %edx,%esi // %esi zurück 1393 jbe L(cmld1) // "be" = Z oder C 1394 movl $1,%eax // Ergebnis +1 1395 ret 1396 L(cmld1:) sbbl %eax,%eax // Ergebnis -1 (falls C) oder 0 (falls NC) 1397 ret 1398 1399 // extern uintD add_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); 1400 ALIGN 1401 DECLARE_FUNCTION(add_loop_up) 1402 C(add_loop_up:) 1403 pushl %esi // %esi retten 1404 pushl %edi // %edi retten 1405 movl 12(%esp),%edx // %edx = sourceptr1 1406 movl 16(%esp),%esi // %esi = sourceptr2 1407 movl 20(%esp),%edi // %edi = destptr 1408 movl 24(%esp),%ecx // %ecx = count 1409 subl %edi,%edx 1410 subl %edi,%esi 1411 orl %ecx,%ecx // %ecx = 0 ?, Carry löschen 1412 jz L(alu2) 1413 L(alu1:) movl (%edx,%edi),%eax // *sourceptr1 1414 adcl (%esi,%edi),%eax // + *sourceptr2 + carry 1415 movl %eax,(%edi) // =: *destptr, neuen Carry behalten 1416 leal 4(%edi),%edi // sourceptr1++, sourceptr2++, destptr++ 1417 decl %ecx 1418 jnz L(alu1) 1419 L(alu2:) sbbl %eax,%eax // Ergebnis := - Carry 1420 popl %edi // %edi zurück 1421 popl %esi // %esi zurück 1422 ret 1423 1424 // extern uintD addto_loop_up (uintD* sourceptr, uintD* destptr, uintC count); 1425 ALIGN 1426 DECLARE_FUNCTION(addto_loop_up) 1427 C(addto_loop_up:) 1428 pushl %edi // %edi retten 1429 movl 8(%esp),%edx // %edx = sourceptr 1430 movl 12(%esp),%edi // %edi = destptr 1431 movl 16(%esp),%ecx // %ecx = count 1432 subl %edi,%edx 1433 orl %ecx,%ecx // %ecx = 0 ?, Carry löschen 1434 jz L(atlu2) 1435 L(atlu1:) movl (%edx,%edi),%eax // *sourceptr 1436 adcl %eax,(%edi) // + *destptr + carry =: *destptr, neuer Carry 1437 leal 4(%edi),%edi // sourceptr++, destptr++ 1438 decl %ecx 1439 jnz L(atlu1) 1440 L(atlu2:) sbbl %eax,%eax // Ergebnis := - Carry 1441 popl %edi // %edi zurück 1442 ret 1443 1444 // extern uintD inc_loop_up (uintD* ptr, uintC count); 1445 ALIGN 1446 DECLARE_FUNCTION(inc_loop_up) 1447 C(inc_loop_up:) 1448 movl 4(%esp),%edx // %edx = ptr 1449 movl 8(%esp),%ecx // %ecx = count 1450 jecxz L(ilu2) // %ecx = 0 ? 1451 L(ilu1:) addl $1,(%edx) // (*ptr)++ 1452 jnc L(ilu3) // kein Carry -> fertig 1453 leal 4(%edx),%edx 1454 decl %ecx 1455 jnz L(ilu1) 1456 L(ilu2:) movl $1,%eax // Ergebnis := 1 1457 ret 1458 L(ilu3:) xorl %eax,%eax // Ergebnis := 0 1459 ret 1460 1461 // extern uintD sub_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); 1462 ALIGN 1463 DECLARE_FUNCTION(sub_loop_up) 1464 C(sub_loop_up:) 1465 pushl %esi // %esi retten 1466 pushl %edi // %edi retten 1467 movl 12(%esp),%edx // %edx = sourceptr1 1468 movl 16(%esp),%esi // %esi = sourceptr2 1469 movl 20(%esp),%edi // %edi = destptr 1470 movl 24(%esp),%ecx // %ecx = count 1471 subl %edi,%edx 1472 subl %edi,%esi 1473 orl %ecx,%ecx // %ecx = 0 ?, Carry löschen 1474 jz L(slu2) 1475 L(slu1:) movl (%edx,%edi),%eax // *sourceptr1 1476 sbbl (%esi,%edi),%eax // - *sourceptr2 - carry 1477 movl %eax,(%edi) // =: *destptr, neuen Carry behalten 1478 leal 4(%edi),%edi // sourceptr1++, sourceptr2++, destptr++ 1479 decl %ecx 1480 jnz L(slu1) 1481 L(slu2:) sbbl %eax,%eax // Ergebnis := - Carry 1482 popl %edi // %edi zurück 1483 popl %esi // %esi zurück 1484 ret 1485 1486 // extern uintD subx_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry); 1487 ALIGN 1488 DECLARE_FUNCTION(subx_loop_up) 1489 C(subx_loop_up:) 1490 pushl %esi // %esi retten 1491 pushl %edi // %edi retten 1492 movl 12(%esp),%edx // %edx = sourceptr1 1493 movl 16(%esp),%esi // %esi = sourceptr2 1494 movl 20(%esp),%edi // %edi = destptr 1495 movl 24(%esp),%ecx // %ecx = count 1496 jecxz L(sxlu2) // %ecx = 0 ? 1497 subl %edi,%edx 1498 subl %edi,%esi 1499 movl 28(%esp),%eax // carry, 0 oder -1 1500 addl %eax,%eax // Bit 31 davon in den Carry 1501 nop ; nop 1502 L(sxlu1:) movl (%edx,%edi),%eax // *sourceptr1 1503 sbbl (%esi,%edi),%eax // - *sourceptr2 - carry 1504 movl %eax,(%edi) // =: *destptr, neuen Carry behalten 1505 leal 4(%edi),%edi // sourceptr1++, sourceptr2++, destptr++ 1506 decl %ecx 1507 jnz L(sxlu1) 1508 sbbl %eax,%eax // Ergebnis := - Carry 1509 popl %edi // %edi zurück 1510 popl %esi // %esi zurück 1511 ret 1512 L(sxlu2:) movl 28(%esp),%eax // Ergebnis := carry 1513 popl %edi // %edi zurück 1514 popl %esi // %esi zurück 1515 ret 1516 1517 // extern uintD subfrom_loop_up (uintD* sourceptr, uintD* destptr, uintC count); 1518 ALIGN 1519 DECLARE_FUNCTION(subfrom_loop_up) 1520 C(subfrom_loop_up:) 1521 pushl %edi // %edi retten 1522 movl 8(%esp),%edx // %edx = sourceptr 1523 movl 12(%esp),%edi // %edi = destptr 1524 movl 16(%esp),%ecx // %ecx = count 1525 subl %edi,%edx 1526 orl %ecx,%ecx // %ecx = 0 ?, Carry löschen 1527 jz L(sflu2) 1528 L(sflu1:) movl (%edx,%edi),%eax // *sourceptr 1529 sbbl %eax,(%edi) // *destptr - *sourceptr - carry =: *destptr, neuer Carry 1530 leal 4(%edi),%edi // sourceptr++, destptr++ 1531 decl %ecx 1532 jnz L(sflu1) 1533 L(sflu2:) sbbl %eax,%eax // Ergebnis := - Carry 1534 popl %edi // %edi zurück 1535 ret 1536 1537 // extern uintD dec_loop_up (uintD* ptr, uintC count); 1538 ALIGN 1539 DECLARE_FUNCTION(dec_loop_up) 1540 C(dec_loop_up:) 1541 movl 4(%esp),%edx // %edx = ptr 1542 movl 8(%esp),%ecx // %ecx = count 1543 jecxz L(dlu2) // %ecx = 0 ? 1544 L(dlu1:) subl $1,(%edx) // (*ptr)-- 1545 jnc L(dlu3) // kein Carry -> fertig 1546 leal 4(%edx),%edx 1547 decl %ecx 1548 jnz L(dlu1) 1549 L(dlu2:) movl $-1,%eax // Ergebnis := -1 1550 ret 1551 L(dlu3:) xorl %eax,%eax // Ergebnis := 0 1552 ret 1553 1554 // extern uintD neg_loop_up (uintD* ptr, uintC count); 1555 ALIGN 1556 DECLARE_FUNCTION(neg_loop_up) 1557 C(neg_loop_up:) 1558 movl 4(%esp),%edx // %edx = ptr 1559 movl 8(%esp),%ecx // %ecx = count 1560 // erstes Digit /=0 suchen: 1561 jecxz L(nlu2) // %ecx = 0 ? 1562 L(nlu1:) negl (%edx) 1563 jnz L(nlu3) 1564 leal 4(%edx),%edx 1565 decl %ecx 1566 jnz L(nlu1) 1567 L(nlu2:) xorl %eax,%eax // Ergebnis := 0 1568 ret 1569 nop ; nop ; nop ; nop ; nop ; nop 1570 L(nlu3:) // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys 1571 // alle anderen Digits invertieren: 1572 decl %ecx 1573 jz L(nlu5) 1574 L(nlu4:) leal 4(%edx),%edx 1575 notl (%edx) 1576 decl %ecx 1577 jnz L(nlu4) 1578 L(nlu5:) movl $-1,%eax // Ergebnis := -1 1579 ret 1580 1581 // extern uintD shift1left_loop_up (uintD* ptr, uintC count); 1582 ALIGN 1583 DECLARE_FUNCTION(shift1left_loop_up) 1584 C(shift1left_loop_up:) 1585 movl 4(%esp),%edx // %edx = ptr 1586 movl 8(%esp),%ecx // %ecx = count 1587 orl %ecx,%ecx // %ecx = 0 ?, Carry löschen 1588 jz L(s1llu2) 1589 nop ; nop ; nop ; nop 1590 L(s1llu1:) rcll $1,(%edx) // *ptr und Carry um 1 Bit links rotieren 1591 leal 4(%edx),%edx // ptr++ 1592 decl %ecx 1593 jnz L(s1llu1) 1594 L(s1llu2:) sbbl %eax,%eax // Ergebnis := - Carry 1595 ret 1596 1597 // extern uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry); 1598 ALIGN 1599 DECLARE_FUNCTION(shiftleft_loop_up) 1600 C(shiftleft_loop_up:) 1601 pushl %edi // %edi retten 1602 pushl %ebx // %ebx retten 1603 movl 12(%esp),%edi // %edi = ptr 1604 movl 16(%esp),%edx // %edx = count 1605 movb 20(%esp),%cl // %cl = i 1606 orl %edx,%edx // count = 0 ? 1607 jz L(sllu4) 1608 // erstes Digit shiften: 1609 movl (%edi),%eax // Digit in %eax halten 1610 movl %eax,%ebx // und in %ebx rechnen: 1611 shll %cl,%ebx // um i Bits links shiften 1612 orl 24(%esp),%ebx // und die unteren i Bits eintragen 1613 movl %ebx,(%edi) // und wieder ablegen 1614 leal 4(%edi),%edi 1615 // Letztes Digit in %eax. 1616 decl %edx 1617 jz L(sllu2) 1618 nop ; nop ; nop ; nop 1619 L(sllu1:) // weiteres Digit shiften: 1620 movl (%edi),%ebx 1621 shldl shcl %eax,(%edi) // (%edi) um %cl=i Bits links shiften, %eax von rechts reinshiften 1622 leal 4(%edi),%edi 1623 // Letztes Digit in %ebx. 1624 decl %edx 1625 jz L(sllu3) 1626 // weiteres Digit shiften: 1627 movl (%edi),%eax 1628 shldl shcl %ebx,(%edi) // (%edi) um %cl=i Bits links shiften, %ebx von rechts reinshiften 1629 leal 4(%edi),%edi 1630 // Letztes Digit in %eax. 1631 decl %edx 1632 jnz L(sllu1) 1633 L(sllu2:) movl %eax,%ebx 1634 L(sllu3:) xorl %eax,%eax // %eax := 0 1635 shldl shcl %ebx,%eax // %eax := höchste %cl=i Bits von %ebx 1636 popl %ebx // %ebx zurück 1637 popl %edi // %edi zurück 1638 ret 1639 L(sllu4:) movl 24(%esp),%eax // %eax := carry 1640 popl %ebx // %ebx zurück 1641 popl %edi // %edi zurück 1642 ret 1643 1644 #endif 1645 1646 // extern uintD shiftleftcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i); 1647 ALIGN 1648 DECLARE_FUNCTION(shiftleftcopy_loop_up) 1649 C(shiftleftcopy_loop_up:) 1650 pushl %esi // %esi retten 1651 pushl %edi // %edi retten 1652 pushl %ebx // %ebx retten 1653 movl 16(%esp),%esi // %esi = sourceptr 1654 movl 20(%esp),%edi // %edi = destptr 1655 movl 24(%esp),%edx // count 1656 movb 28(%esp),%cl // i 1657 orl %edx,%edx // count = 0 ? 1658 jz L(slclu4) 1659 subl %edi,%esi 1660 // erstes Digit shiften: 1661 movl (%edi,%esi),%ebx // *sourceptr in %ebx halten 1662 movl %ebx,%eax // und in %eax rechnen: 1663 shll %cl,%eax // um i Bits links shiften, rechts Nullen rein 1664 movl %eax,(%edi) // und als *destptr ablegen 1665 leal 4(%edi),%edi // sourceptr++, destptr++ 1666 // Letztes Digit in %ebx. 1667 negb %cl // 32-i 1668 decl %edx 1669 jz L(slclu2) 1670 L(slclu1:) // weiteres Digit shiften: 1671 movl (%edi,%esi),%eax // nächstes Digit nach %eax 1672 shrdl shcl %eax,%ebx // %ebx um %cl=32-i Bits rechts shiften, %eax von links reinshiften 1673 movl %ebx,(%edi) // %ebx als *destptr ablegen 1674 leal 4(%edi),%edi // sourceptr++, destptr++ 1675 // Letztes Digit in %eax. 1676 decl %edx 1677 jz L(slclu3) 1678 // weiteres Digit shiften: 1679 movl (%edi,%esi),%ebx // nächstes Digit nach %ebx 1680 shrdl shcl %ebx,%eax // %eax um %cl=32-i Bits rechts shiften, %ebx von links reinshiften 1681 movl %eax,(%edi) // %eax als *destptr ablegen 1682 leal 4(%edi),%edi // sourceptr++, destptr++ 1683 // Letztes Digit in %ebx. 1684 decl %edx 1685 jnz L(slclu1) 1686 L(slclu2:) movl %ebx,%eax 1687 L(slclu3:) shrl %cl,%eax // %eax um 32-i Bits nach rechts shiften 1688 popl %ebx // %ebx zurück 1689 popl %edi // %edi zurück 1690 popl %esi // %esi zurück 1691 ret 1692 L(slclu4:) xorl %eax,%eax // %eax := 0 1693 popl %ebx // %ebx zurück 1694 popl %edi // %edi zurück 1695 popl %esi // %esi zurück 1696 ret 1697 1698 #if !CL_DS_BIG_ENDIAN_P 1699 1700 // extern uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry); 1701 ALIGN 1702 DECLARE_FUNCTION(shift1right_loop_down) 1703 C(shift1right_loop_down:) 1704 movl 4(%esp),%edx // %edx = ptr 1705 movl 8(%esp),%ecx // %ecx = count 1706 movl 12(%esp),%eax // %eax = carry (0 oder -1) 1707 jecxz L(s1rlu3) // %ecx = 0 ? 1708 addl %eax,%eax // Carry := Bit 31 von carry 1709 L(s1rlu1:) leal -4(%edx),%edx // ptr-- 1710 rcrl $1,(%edx) // *ptr und Carry um 1 Bit rechts rotieren 1711 decl %ecx 1712 jnz L(s1rlu1) 1713 L(s1rlu2:) sbbl %eax,%eax // Ergebnis := - Carry 1714 L(s1rlu3:) ret 1715 1716 // extern uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i); 1717 ALIGN 1718 DECLARE_FUNCTION(shiftright_loop_down) 1719 C(shiftright_loop_down:) 1720 pushl %edi // %edi retten 1721 pushl %ebx // %ebx retten 1722 movl 12(%esp),%edi // %edi = ptr 1723 movl 16(%esp),%edx // %edx = count 1724 movb 20(%esp),%cl // %cl = i 1725 orl %edx,%edx // count = 0 ? 1726 jz L(srld4) 1727 // erstes Digit shiften: 1728 leal -4(%edi),%edi 1729 movl (%edi),%eax // Digit in %eax halten 1730 movl %eax,%ebx // und in %ebx rechnen: 1731 shrl %cl,%ebx // um i Bits rechts shiften 1732 movl %ebx,(%edi) // und wieder ablegen 1733 // Letztes Digit in %eax. 1734 decl %edx 1735 jz L(srld2) 1736 L(srld1:) // weiteres Digit shiften: 1737 leal -4(%edi),%edi 1738 movl (%edi),%ebx 1739 shrdl shcl %eax,(%edi) // (%edi) um %cl=i Bits rechts shiften, %eax von links reinshiften 1740 // Letztes Digit in %ebx. 1741 decl %edx 1742 jz L(srld3) 1743 // weiteres Digit shiften: 1744 leal -4(%edi),%edi 1745 movl (%edi),%eax 1746 shrdl shcl %ebx,(%edi) // (%edi) um %cl=i Bits rechts shiften, %ebx von links reinshiften 1747 // Letztes Digit in %eax. 1748 decl %edx 1749 jnz L(srld1) 1750 L(srld2:) movl %eax,%ebx 1751 L(srld3:) xorl %eax,%eax // %eax := 0 1752 shrdl shcl %ebx,%eax // %eax := niedrigste %cl=i Bits von %ebx, als Bits 31..32-i 1753 popl %ebx // %ebx zurück 1754 popl %edi // %edi zurück 1755 ret 1756 L(srld4:) xorl %eax,%eax // %eax := 0 1757 popl %ebx // %ebx zurück 1758 popl %edi // %edi zurück 1759 ret 1760 1761 // extern uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i); 1762 ALIGN 1763 DECLARE_FUNCTION(shiftrightsigned_loop_down) 1764 C(shiftrightsigned_loop_down:) 1765 pushl %edi // %edi retten 1766 pushl %ebx // %ebx retten 1767 movl 12(%esp),%edi // %edi = ptr 1768 movl 16(%esp),%edx // %edx = count 1769 movb 20(%esp),%cl // %cl = i 1770 // erstes Digit shiften: 1771 leal -4(%edi),%edi 1772 movl (%edi),%eax // Digit in %eax halten 1773 movl %eax,%ebx // und in %ebx rechnen: 1774 sarl %cl,%ebx // um i Bits rechts shiften, Vorzeichen vervielfachen 1775 movl %ebx,(%edi) // und wieder ablegen 1776 // Letztes Digit in %eax. 1777 decl %edx 1778 jz L(srsld2) 1779 nop ; nop ; nop ; nop 1780 L(srsld1:) // weiteres Digit shiften: 1781 leal -4(%edi),%edi 1782 movl (%edi),%ebx 1783 shrdl shcl %eax,(%edi) // (%edi) um %cl=i Bits rechts shiften, %eax von links reinshiften 1784 // Letztes Digit in %ebx. 1785 decl %edx 1786 jz L(srsld3) 1787 // weiteres Digit shiften: 1788 leal -4(%edi),%edi 1789 movl (%edi),%eax 1790 shrdl shcl %ebx,(%edi) // (%edi) um %cl=i Bits rechts shiften, %ebx von links reinshiften 1791 // Letztes Digit in %eax. 1792 decl %edx 1793 jnz L(srsld1) 1794 L(srsld2:) movl %eax,%ebx 1795 L(srsld3:) xorl %eax,%eax // %eax := 0 1796 shrdl shcl %ebx,%eax // %eax := niedrigste %cl=i Bits von %ebx, als Bits 31..32-i 1797 popl %ebx // %ebx zurück 1798 popl %edi // %edi zurück 1799 ret 1800 1801 // extern uintD shiftrightcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry); 1802 ALIGN 1803 DECLARE_FUNCTION(shiftrightcopy_loop_down) 1804 C(shiftrightcopy_loop_down:) 1805 pushl %esi // %esi retten 1806 pushl %edi // %edi retten 1807 pushl %ebx // %ebx retten 1808 movl 16(%esp),%esi // %esi = sourceptr 1809 movl 20(%esp),%edi // %edi = destptr 1810 movl 24(%esp),%edx // count 1811 movb 28(%esp),%cl // i 1812 negb %cl // 32-i 1813 movl 32(%esp),%eax // %eax = carry 1814 orl %edx,%edx // count = 0 ? 1815 jz L(srclu3) 1816 subl %edi,%esi 1817 // erstes Digit shiften: 1818 leal -4(%edi),%edi // sourceptr--, destptr-- 1819 movl (%edi,%esi),%ebx // *sourceptr in %ebx halten 1820 shldl shcl %ebx,%eax // carry um %cl=32-i Bits links shiften, dabei *sourceptr rein 1821 movl %eax,(%edi) // und als *destptr ablegen 1822 // Letztes Digit in %ebx. 1823 decl %edx 1824 jz L(srclu2) 1825 nop ; nop ; nop 1826 L(srclu1:) // weiteres Digit shiften: 1827 leal -4(%edi),%edi // sourceptr--, destptr-- 1828 movl (%edi,%esi),%eax // nächstes Digit nach %eax 1829 shldl shcl %eax,%ebx // %ebx um %cl=32-i Bits links shiften, %eax von rechts reinshiften 1830 movl %ebx,(%edi) // %ebx als *destptr ablegen 1831 // Letztes Digit in %eax. 1832 decl %edx 1833 jz L(srclu3) 1834 // weiteres Digit shiften: 1835 leal -4(%edi),%edi // sourceptr--, destptr-- 1836 movl (%edi,%esi),%ebx // nächstes Digit nach %ebx 1837 shldl shcl %ebx,%eax // %eax um %cl=32-i Bits links shiften, %ebx von rechts reinshiften 1838 movl %eax,(%edi) // %eax als *destptr ablegen 1839 // Letztes Digit in %ebx. 1840 decl %edx 1841 jnz L(srclu1) 1842 L(srclu2:) movl %ebx,%eax 1843 L(srclu3:) shll %cl,%eax // %eax um 32-i Bits nach links shiften 1844 popl %ebx // %ebx zurück 1845 popl %edi // %edi zurück 1846 popl %esi // %esi zurück 1847 ret 1848 1849 // extern uintD mulusmall_loop_up (uintD digit, uintD* ptr, uintC len, uintD newdigit); 1850 ALIGN 1851 DECLARE_FUNCTION(mulusmall_loop_up) 1852 C(mulusmall_loop_up:) 1853 pushl %ebp // %ebp retten 1854 pushl %edi // %edi retten 1855 pushl %ebx // %ebx retten 1856 movl 16(%esp),%ebx // %ebx = digit 1857 movl 20(%esp),%edi // %edi = ptr 1858 movl 24(%esp),%ecx // %ecx = len 1859 movl 28(%esp),%ebp // %ebp = carry := newdigit 1860 leal (%edi,%ecx,4),%edi // %edi = &ptr[len] 1861 negl %ecx // %ecx = -count 1862 jz L(mslu2) 1863 L(mslu1:) movl (%edi,%ecx,4),%eax // *ptr 1864 mull %ebx // %edx|%eax := digit * *ptr 1865 addl %ebp,%eax // carry und Low-Teil des Produktes addieren 1866 movl $0,%ebp 1867 adcl %edx,%ebp // Übertrag zum High-Teil %edx dazu, gibt neuen carry 1868 movl %eax,(%edi,%ecx,4) // Low-Teil als *ptr ablegen 1869 incl %ecx // count--, ptr++ 1870 jnz L(mslu1) 1871 L(mslu2:) movl %ebp,%eax // Ergebnis := letzter Übertrag 1872 popl %ebx // %ebx zurück 1873 popl %edi // %edi zurück 1874 popl %ebp // %ebp zurück 1875 ret 1876 1877 // extern void mulu_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); 1878 ALIGN 1879 DECLARE_FUNCTION(mulu_loop_up) 1880 C(mulu_loop_up:) 1881 pushl %ebp // %ebp retten 1882 pushl %edi // %edi retten 1883 pushl %esi // %esi retten 1884 pushl %ebx // %ebx retten 1885 movl 20(%esp),%ebx // %ebx = digit 1886 movl 24(%esp),%esi // %esi = sourceptr 1887 movl 28(%esp),%edi // %edi = destptr 1888 movl 32(%esp),%ecx // %ecx = len 1889 leal (%esi,%ecx,4),%esi // %esi = &sourceptr[len] 1890 leal (%edi,%ecx,4),%edi // %edi = &destptr[len] 1891 negl %ecx // %ecx = -count 1892 xorl %ebp,%ebp // %epb = carry := 0 1893 nop ; nop 1894 L(mulu1:) movl (%esi,%ecx,4),%eax // *sourceptr 1895 mull %ebx // %edx|%eax := digit * *sourceptr 1896 addl %ebp,%eax // carry und Low-Teil des Produktes addieren 1897 movl $0,%ebp 1898 adcl %edx,%ebp // Übertrag zum High-Teil %edx dazu, gibt neuen carry 1899 movl %eax,(%edi,%ecx,4) // Low-Teil als *destptr ablegen 1900 incl %ecx // count--, sourceptr++, destptr++ 1901 jnz L(mulu1) 1902 movl %ebp,(%edi) // letzten Übertrag ablegen 1903 popl %ebx // %ebx zurück 1904 popl %esi // %esi zurück 1905 popl %edi // %edi zurück 1906 popl %ebp // %ebp zurück 1907 ret 1908 1909 // extern uintD muluadd_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); 1910 ALIGN 1911 DECLARE_FUNCTION(muluadd_loop_up) 1912 C(muluadd_loop_up:) 1913 pushl %ebp // %ebp retten 1914 pushl %edi // %edi retten 1915 pushl %esi // %esi retten 1916 pushl %ebx // %ebx retten 1917 movl 20(%esp),%ebx // %ebx = digit 1918 movl 24(%esp),%esi // %esi = sourceptr 1919 movl 28(%esp),%edi // %edi = destptr 1920 movl 32(%esp),%ecx // %ecx = len 1921 leal (%esi,%ecx,4),%esi // %esi = &sourceptr[len] 1922 leal (%edi,%ecx,4),%edi // %edi = &destptr[len] 1923 negl %ecx // %ecx = -count 1924 xorl %ebp,%ebp // %epb = carry := 0 1925 nop ; nop 1926 L(mualu1:) movl (%esi,%ecx,4),%eax // *sourceptr 1927 mull %ebx // %edx|%eax := digit * *sourceptr 1928 addl %ebp,%eax // carry und Low-Teil des Produktes addieren 1929 movl $0,%ebp 1930 adcl %ebp,%edx // Übertrag zum High-Teil %edx dazu 1931 addl %eax,(%edi,%ecx,4) // Low-Teil zu *destptr addieren 1932 adcl %edx,%ebp // zweiten Übertrag zu %edx addieren, gibt neuen carry 1933 incl %ecx // count--, sourceptr++, destptr++ 1934 jnz L(mualu1) 1935 movl %ebp,%eax // Ergebnis := letzter Übertrag 1936 popl %ebx // %ebx zurück 1937 popl %esi // %esi zurück 1938 popl %edi // %edi zurück 1939 popl %ebp // %ebp zurück 1940 ret 1941 1942 // extern uintD mulusub_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); 1943 ALIGN 1944 DECLARE_FUNCTION(mulusub_loop_up) 1945 C(mulusub_loop_up:) 1946 pushl %ebp // %ebp retten 1947 pushl %edi // %edi retten 1948 pushl %esi // %esi retten 1949 pushl %ebx // %ebx retten 1950 movl 20(%esp),%ebx // %ebx = digit 1951 movl 24(%esp),%esi // %esi = sourceptr 1952 movl 28(%esp),%edi // %edi = destptr 1953 movl 32(%esp),%ecx // %ecx = len 1954 leal (%esi,%ecx,4),%esi // %esi = &sourceptr[len] 1955 leal (%edi,%ecx,4),%edi // %edi = &destptr[len] 1956 negl %ecx // %ecx = -count 1957 xorl %ebp,%ebp // %epb = carry := 0 1958 nop ; nop 1959 L(muslu1:) movl (%esi,%ecx,4),%eax // *sourceptr 1960 mull %ebx // %edx|%eax := digit * *sourceptr 1961 addl %ebp,%eax // carry und Low-Teil des Produktes addieren 1962 movl $0,%ebp 1963 adcl %ebp,%edx // Übertrag zum High-Teil %edx dazu 1964 subl %eax,(%edi,%ecx,4) // Low-Teil von *destptr subtrahieren 1965 adcl %edx,%ebp // zweiten Übertrag zu %edx addieren, gibt neuen carry 1966 incl %ecx // count--, sourceptr++, destptr++ 1967 jnz L(muslu1) 1968 movl %ebp,%eax // Ergebnis := letzter Übertrag 1969 popl %ebx // %ebx zurück 1970 popl %esi // %esi zurück 1971 popl %edi // %edi zurück 1972 popl %ebp // %ebp zurück 1973 ret 1974 1975 // extern uintD divu_loop_down (uintD digit, uintD* ptr, uintC len); 1976 ALIGN 1977 DECLARE_FUNCTION(divu_loop_down) 1978 C(divu_loop_down:) 1979 pushl %edi // %edi retten 1980 pushl %ebx // %ebx retten 1981 movl 12(%esp),%ebx // %ebx = digit 1982 movl 16(%esp),%edi // %edi = ptr 1983 movl 20(%esp),%ecx // %ecx = len 1984 xorl %edx,%edx // %edx = Rest := 0 1985 jecxz L(dld2) // %ecx = 0 ? 1986 L(dld1:) leal -4(%edi),%edi // ptr-- 1987 movl (%edi),%eax // nächstes Digit *ptr 1988 divl %ebx // Division von %edx|%eax durch %ebx 1989 movl %eax,(%edi) // Quotient %eax ablegen, Rest in %edx behalten 1990 decl %ecx 1991 jnz L(dld1) 1992 L(dld2:) movl %edx,%eax // Ergebnis := letzter Rest 1993 popl %ebx // %ebx zurück 1994 popl %edi // %edi zurück 1995 ret 1996 1997 // extern uintD divucopy_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); 1998 ALIGN 1999 DECLARE_FUNCTION(divucopy_loop_down) 2000 C(divucopy_loop_down:) 2001 pushl %edi // %edi retten 2002 pushl %esi // %esi retten 2003 pushl %ebx // %ebx retten 2004 movl 16(%esp),%ebx // %ebx = digit 2005 movl 20(%esp),%esi // %esi = sourceptr 2006 movl 24(%esp),%edi // %edi = destptr 2007 movl 28(%esp),%ecx // %ecx = len 2008 xorl %edx,%edx // %edx = Rest := 0 2009 jecxz L(dcld2) // %ecx = 0 ? 2010 subl %edi,%esi 2011 L(dcld1:) leal -4(%edi),%edi // sourceptr--, destptr-- 2012 movl (%esi,%edi),%eax // nächstes Digit *ptr 2013 divl %ebx // Division von %edx|%eax durch %ebx 2014 movl %eax,(%edi) // Quotient %eax ablegen, Rest in %edx behalten 2015 decl %ecx 2016 jnz L(dcld1) 2017 L(dcld2:) movl %edx,%eax // Ergebnis := letzter Rest 2018 popl %ebx // %ebx zurück 2019 popl %esi // %esi zurück 2020 popl %edi // %edi zurück 2021 ret 2022 2023 #endif 2024 2025 // extern void shiftxor_loop_up (uintD* xptr, const uintD* yptr, uintC count, uintC i); 2026 ALIGN 2027 DECLARE_FUNCTION(shiftxor_loop_up) 2028 C(shiftxor_loop_up:) 2029 pushl %esi // %esi retten 2030 pushl %edi // %edi retten 2031 pushl %ebx // %ebx retten 2032 movl 16(%esp),%esi // %esi = xptr 2033 movl 20(%esp),%edi // %edi = yptr 2034 movl 24(%esp),%edx // count 2035 movb 28(%esp),%cl // i 2036 orl %edx,%edx // count = 0 ? 2037 jz L(shxlu4) 2038 subl %esi,%edi 2039 // erstes Digit shiften: 2040 movl (%esi,%edi),%ebx // *yptr in %ebx halten 2041 movl %ebx,%eax // und in %eax rechnen: 2042 shll %cl,%eax // um i Bits links shiften, rechts Nullen rein 2043 xorl %eax,(%esi) // und mit *xptr verknüpfen und ablegen 2044 leal 4(%esi),%esi // sourceptr++, destptr++ 2045 // Letztes Digit in %ebx. 2046 negb %cl // 32-i 2047 decl %edx 2048 jz L(shxlu2) 2049 L(shxlu1:) // weiteres Digit shiften: 2050 movl (%esi,%edi),%eax // nächstes Digit nach %eax 2051 shrdl shcl %eax,%ebx // %ebx um %cl=32-i Bits rechts shiften, %eax von links reinshiften 2052 xorl %ebx,(%esi) // %ebx mit *xptr verknüpfen und ablegen 2053 leal 4(%esi),%esi // xptr++, yptr++ 2054 // Letztes Digit in %eax. 2055 decl %edx 2056 jz L(shxlu3) 2057 // weiteres Digit shiften: 2058 movl (%esi,%edi),%ebx // nächstes Digit nach %ebx 2059 shrdl shcl %ebx,%eax // %eax um %cl=32-i Bits rechts shiften, %ebx von links reinshiften 2060 xorl %eax,(%esi) // %eax mit *xptr verknüpfen und ablegen 2061 leal 4(%esi),%esi // xptr++, yptr++ 2062 // Letztes Digit in %ebx. 2063 decl %edx 2064 jnz L(shxlu1) 2065 L(shxlu2:) movl %ebx,%eax 2066 L(shxlu3:) shrl %cl,%eax // %eax um 32-i Bits nach rechts shiften 2067 xorl %eax,(%esi) // und mit *xptr verknüpfen und ablegen 2068 L(shxlu4:) popl %ebx // %ebx zurück 2069 popl %edi // %edi zurück 2070 popl %esi // %esi zurück 2071 ret 2072 2073