1/* libgcc routines for M68HC11 & M68HC12. 2 Copyright (C) 1999, 2000, 2001, 2002, 2003, 2008, 2009 3 Free Software Foundation, Inc. 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it 8under the terms of the GNU General Public License as published by the 9Free Software Foundation; either version 3, or (at your option) any 10later version. 11 12This file is distributed in the hope that it will be useful, but 13WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15General Public License for more details. 16 17Under Section 7 of GPL version 3, you are granted additional 18permissions described in the GCC Runtime Library Exception, version 193.1, as published by the Free Software Foundation. 20 21You should have received a copy of the GNU General Public License and 22a copy of the GCC Runtime Library Exception along with this program; 23see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24<http://www.gnu.org/licenses/>. */ 25 26#ifdef __HAVE_SHORT_INT__ 27 .mode mshort 28#else 29 .mode mlong 30#endif 31 32 .macro declare_near name 33 .globl \name 34 .type \name,@function 35 .size \name,.Lend-\name 36\name: 37 .endm 38 39#if defined(__USE_RTC__) 40# define ARG(N) N+1 41 42 .macro ret 43#if defined(mc68hc12) 44 rtc 45#else 46 jmp __return_32 47#endif 48 .endm 49 50 .macro declare name 51 .globl \name 52 .type \name,@function 53 .size \name,.Lend-\name 54 .far \name 55\name: 56 .endm 57 58 .macro farsym name 59 .far NAME 60 .endm 61 62#else 63# define ARG(N) N 64 65 .macro ret 66 rts 67 .endm 68 69 .macro farsym name 70 .endm 71 72 .macro declare name 73 .globl \name 74 .type \name,@function 75 .size \name,.Lend-\name 76\name: 77 .endm 78 79#endif 80 81 .sect .text 82 83 84#define REG(NAME) \ 85NAME: .dc.w 1; \ 86 .type NAME,@object ; \ 87 .size NAME,2 88 89#ifdef L_regs_min 90/* Pseudo hard registers used by gcc. 91 They should be located in page0. */ 92 93 .sect .softregs 94 .globl _.tmp 95 .globl _.z,_.xy 96REG(_.tmp) 97REG(_.z) 98REG(_.xy) 99 100#endif 101 102#ifdef L_regs_frame 103 .sect .softregs 104 .globl _.frame 105REG(_.frame) 106#endif 107 108#ifdef L_regs_d1_2 109 .sect .softregs 110 .globl _.d1,_.d2 111REG(_.d1) 112REG(_.d2) 113#endif 114 115#ifdef L_regs_d3_4 116 .sect .softregs 117 .globl _.d3,_.d4 118REG(_.d3) 119REG(_.d4) 120#endif 121 122#ifdef L_regs_d5_6 123 .sect .softregs 124 .globl _.d5,_.d6 125REG(_.d5) 126REG(_.d6) 127#endif 128 129#ifdef L_regs_d7_8 130 .sect .softregs 131 .globl _.d7,_.d8 132REG(_.d7) 133REG(_.d8) 134#endif 135 136#ifdef L_regs_d9_16 137/* Pseudo hard registers used by gcc. 138 They should be located in page0. */ 139 .sect .softregs 140 .globl _.d9,_.d10,_.d11,_.d12,_.d13,_.d14 141 .globl _.d15,_.d16 142REG(_.d9) 143REG(_.d10) 144REG(_.d11) 145REG(_.d12) 146REG(_.d13) 147REG(_.d14) 148REG(_.d15) 149REG(_.d16) 150 151#endif 152 153#ifdef L_regs_d17_32 154/* Pseudo hard registers used by gcc. 155 They should be located in page0. */ 156 .sect .softregs 157 .globl _.d17,_.d18,_.d19,_.d20,_.d21,_.d22 158 .globl _.d23,_.d24,_.d25,_.d26,_.d27,_.d28 159 .globl _.d29,_.d30,_.d31,_.d32 160REG(_.d17) 161REG(_.d18) 162REG(_.d19) 163REG(_.d20) 164REG(_.d21) 165REG(_.d22) 166REG(_.d23) 167REG(_.d24) 168REG(_.d25) 169REG(_.d26) 170REG(_.d27) 171REG(_.d28) 172REG(_.d29) 173REG(_.d30) 174REG(_.d31) 175REG(_.d32) 176#endif 177 178#ifdef L_premain 179;; 180;; Specific initialization for 68hc11 before the main. 181;; Nothing special for a generic routine; Just enable interrupts. 182;; 183 declare_near __premain 184 clra 185 tap ; Clear both I and X. 186 rts 187#endif 188 189#ifdef L__exit 190;; 191;; Exit operation. Just loop forever and wait for interrupts. 192;; (no other place to go) 193;; This operation is split in several pieces collected together by 194;; the linker script. This allows to support destructors at the 195;; exit stage while not impacting program sizes when there is no 196;; destructors. 197;; 198;; _exit: 199;; *(.fini0) /* Beginning of finish code (_exit symbol). */ 200;; *(.fini1) /* Place holder for applications. */ 201;; *(.fini2) /* C++ destructors. */ 202;; *(.fini3) /* Place holder for applications. */ 203;; *(.fini4) /* Runtime exit. */ 204;; 205 .sect .fini0,"ax",@progbits 206 .globl _exit 207 .globl exit 208 .weak exit 209 farsym exit 210 farsym _exit 211exit: 212_exit: 213 214 .sect .fini4,"ax",@progbits 215fatal: 216 cli 217 wai 218 bra fatal 219#endif 220 221#ifdef L_abort 222;; 223;; Abort operation. This is defined for the GCC testsuite. 224;; 225 declare abort 226 227 ldd #255 ; 228#ifdef mc68hc12 229 trap #0x30 230#else 231 .byte 0xCD ; Generate an illegal instruction trap 232 .byte 0x03 ; The simulator catches this and stops. 233#endif 234 jmp _exit 235#endif 236 237#ifdef L_cleanup 238;; 239;; Cleanup operation used by exit(). 240;; 241 declare _cleanup 242 243 ret 244#endif 245 246;----------------------------------------- 247; required gcclib code 248;----------------------------------------- 249#ifdef L_memcpy 250 declare memcpy 251 declare __memcpy 252 253 .weak memcpy 254;;; 255;;; void* memcpy(void*, const void*, size_t) 256;;; 257;;; D = dst Pmode 258;;; 2,sp = src Pmode 259;;; 4,sp = size HImode (size_t) 260;;; 261#ifdef mc68hc12 262 ldx ARG(2),sp 263 ldy ARG(4),sp 264 pshd 265 xgdy 266 lsrd 267 bcc Start 268 movb 1,x+,1,y+ 269Start: 270 beq Done 271Loop: 272 movw 2,x+,2,y+ 273 dbne d,Loop 274Done: 275 puld 276 ret 277#else 278 xgdy 279 tsx 280 ldd ARG(4),x 281 ldx ARG(2),x ; SRC = X, DST = Y 282 cpd #0 283 beq End 284 pshy 285 inca ; Correction for the deca below 286L0: 287 psha ; Save high-counter part 288L1: 289 ldaa 0,x ; Copy up to 256 bytes 290 staa 0,y 291 inx 292 iny 293 decb 294 bne L1 295 pula 296 deca 297 bne L0 298 puly ; Restore Y to return the DST 299End: 300 xgdy 301 ret 302#endif 303#endif 304 305#ifdef L_memset 306 declare memset 307 declare __memset 308;;; 309;;; void* memset(void*, int value, size_t) 310;;; 311#ifndef __HAVE_SHORT_INT__ 312;;; D = dst Pmode 313;;; 2,sp = src SImode 314;;; 6,sp = size HImode (size_t) 315 val = ARG(5) 316 size = ARG(6) 317#else 318;;; D = dst Pmode 319;;; 2,sp = src SImode 320;;; 6,sp = size HImode (size_t) 321 val = ARG(3) 322 size = ARG(4) 323#endif 324#ifdef mc68hc12 325 xgdx 326 ldab val,sp 327 ldy size,sp 328 pshx 329 beq End 330Loop: 331 stab 1,x+ 332 dbne y,Loop 333End: 334 puld 335 ret 336#else 337 xgdx 338 tsy 339 ldab val,y 340 ldy size,y ; DST = X, CNT = Y 341 beq End 342 pshx 343L0: 344 stab 0,x ; Fill up to 256 bytes 345 inx 346 dey 347 bne L0 348 pulx ; Restore X to return the DST 349End: 350 xgdx 351 ret 352#endif 353#endif 354 355#ifdef L_adddi3 356 declare ___adddi3 357 358 tsx 359 xgdy 360 ldd ARG(8),x ; Add LSB 361 addd ARG(16),x 362 std 6,y ; Save (carry preserved) 363 364 ldd ARG(6),x 365 adcb ARG(15),x 366 adca ARG(14),x 367 std 4,y 368 369 ldd ARG(4),x 370 adcb ARG(13),x 371 adca ARG(12),x 372 std 2,y 373 374 ldd ARG(2),x 375 adcb ARG(11),x ; Add MSB 376 adca ARG(10),x 377 std 0,y 378 379 xgdy 380 ret 381#endif 382 383#ifdef L_subdi3 384 declare ___subdi3 385 386 tsx 387 xgdy 388 ldd ARG(8),x ; Subtract LSB 389 subd ARG(16),x 390 std 6,y ; Save, borrow preserved 391 392 ldd ARG(6),x 393 sbcb ARG(15),x 394 sbca ARG(14),x 395 std 4,y 396 397 ldd ARG(4),x 398 sbcb ARG(13),x 399 sbca ARG(12),x 400 std 2,y 401 402 ldd ARG(2),x ; Subtract MSB 403 sbcb ARG(11),x 404 sbca ARG(10),x 405 std 0,y 406 407 xgdy ; 408 ret 409#endif 410 411#ifdef L_notdi2 412 declare ___notdi2 413 414 tsy 415 xgdx 416 ldd ARG(8),y 417 coma 418 comb 419 std 6,x 420 421 ldd ARG(6),y 422 coma 423 comb 424 std 4,x 425 426 ldd ARG(4),y 427 coma 428 comb 429 std 2,x 430 431 ldd ARG(2),y 432 coma 433 comb 434 std 0,x 435 xgdx 436 ret 437#endif 438 439#ifdef L_negsi2 440 declare_near ___negsi2 441 442 comb 443 coma 444 xgdx 445 comb 446 coma 447 inx 448 xgdx 449 bne done 450 inx 451done: 452 rts 453#endif 454 455#ifdef L_one_cmplsi2 456 declare_near ___one_cmplsi2 457 458 comb 459 coma 460 xgdx 461 comb 462 coma 463 xgdx 464 rts 465#endif 466 467#ifdef L_ashlsi3 468 declare_near ___ashlsi3 469 470 xgdy 471 clra 472 andb #0x1f 473 xgdy 474 beq Return 475Loop: 476 lsld 477 xgdx 478 rolb 479 rola 480 xgdx 481 dey 482 bne Loop 483Return: 484 rts 485#endif 486 487#ifdef L_ashrsi3 488 declare_near ___ashrsi3 489 490 xgdy 491 clra 492 andb #0x1f 493 xgdy 494 beq Return 495Loop: 496 xgdx 497 asra 498 rorb 499 xgdx 500 rora 501 rorb 502 dey 503 bne Loop 504Return: 505 rts 506#endif 507 508#ifdef L_lshrsi3 509 declare_near ___lshrsi3 510 511 xgdy 512 clra 513 andb #0x1f 514 xgdy 515 beq Return 516Loop: 517 xgdx 518 lsrd 519 xgdx 520 rora 521 rorb 522 dey 523 bne Loop 524Return: 525 rts 526#endif 527 528#ifdef L_lshrhi3 529 declare_near ___lshrhi3 530 531 cpx #16 532 bge Return_zero 533 cpx #0 534 beq Return 535Loop: 536 lsrd 537 dex 538 bne Loop 539Return: 540 rts 541Return_zero: 542 clra 543 clrb 544 rts 545#endif 546 547#ifdef L_lshlhi3 548 declare_near ___lshlhi3 549 550 cpx #16 551 bge Return_zero 552 cpx #0 553 beq Return 554Loop: 555 lsld 556 dex 557 bne Loop 558Return: 559 rts 560Return_zero: 561 clra 562 clrb 563 rts 564#endif 565 566#ifdef L_rotrhi3 567 declare_near ___rotrhi3 568 569___rotrhi3: 570 xgdx 571 clra 572 andb #0x0f 573 xgdx 574 beq Return 575Loop: 576 tap 577 rorb 578 rora 579 dex 580 bne Loop 581Return: 582 rts 583#endif 584 585#ifdef L_rotlhi3 586 declare_near ___rotlhi3 587 588___rotlhi3: 589 xgdx 590 clra 591 andb #0x0f 592 xgdx 593 beq Return 594Loop: 595 asrb 596 rolb 597 rola 598 rolb 599 dex 600 bne Loop 601Return: 602 rts 603#endif 604 605#ifdef L_ashrhi3 606 declare_near ___ashrhi3 607 608 cpx #16 609 bge Return_minus_1_or_zero 610 cpx #0 611 beq Return 612Loop: 613 asra 614 rorb 615 dex 616 bne Loop 617Return: 618 rts 619Return_minus_1_or_zero: 620 clrb 621 tsta 622 bpl Return_zero 623 comb 624Return_zero: 625 tba 626 rts 627#endif 628 629#ifdef L_ashrqi3 630 declare_near ___ashrqi3 631 632 cmpa #8 633 bge Return_minus_1_or_zero 634 tsta 635 beq Return 636Loop: 637 asrb 638 deca 639 bne Loop 640Return: 641 rts 642Return_minus_1_or_zero: 643 clrb 644 tstb 645 bpl Return_zero 646 coma 647Return_zero: 648 tab 649 rts 650#endif 651 652#ifdef L_lshlqi3 653 declare_near ___lshlqi3 654 655 cmpa #8 656 bge Return_zero 657 tsta 658 beq Return 659Loop: 660 lslb 661 deca 662 bne Loop 663Return: 664 rts 665Return_zero: 666 clrb 667 rts 668#endif 669 670#ifdef L_divmodhi4 671#ifndef mc68hc12 672/* 68HC12 signed divisions are generated inline (idivs). */ 673 674 declare_near __divmodhi4 675 676; 677;; D = numerator 678;; X = denominator 679;; 680;; Result: D = D / X 681;; X = D % X 682;; 683 tsta 684 bpl Numerator_pos 685 comb ; D = -D <=> D = (~D) + 1 686 coma 687 xgdx 688 inx 689 tsta 690 bpl Numerator_neg_denominator_pos 691Numerator_neg_denominator_neg: 692 comb ; X = -X 693 coma 694 addd #1 695 xgdx 696 idiv 697 coma 698 comb 699 xgdx ; Remainder <= 0 and result >= 0 700 inx 701 rts 702 703Numerator_pos_denominator_pos: 704 xgdx 705 idiv 706 xgdx ; Both values are >= 0 707 rts 708 709Numerator_pos: 710 xgdx 711 tsta 712 bpl Numerator_pos_denominator_pos 713Numerator_pos_denominator_neg: 714 coma ; X = -X 715 comb 716 xgdx 717 inx 718 idiv 719 xgdx ; Remainder >= 0 but result <= 0 720 coma 721 comb 722 addd #1 723 rts 724 725Numerator_neg_denominator_pos: 726 xgdx 727 idiv 728 coma ; One value is > 0 and the other < 0 729 comb ; Change the sign of result and remainder 730 xgdx 731 inx 732 coma 733 comb 734 addd #1 735 rts 736#endif /* !mc68hc12 */ 737#endif 738 739#ifdef L_mulqi3 740 declare_near ___mulqi3 741 742; 743; short __mulqi3(signed char a, signed char b); 744; 745; signed char a -> register A 746; signed char b -> register B 747; 748; returns the signed result of A * B in register D. 749; 750 tsta 751 bmi A_neg 752 tstb 753 bmi B_neg 754 mul 755 rts 756B_neg: 757 negb 758 bra A_or_B_neg 759A_neg: 760 nega 761 tstb 762 bmi AB_neg 763A_or_B_neg: 764 mul 765 coma 766 comb 767 addd #1 768 rts 769AB_neg: 770 negb 771 mul 772 rts 773#endif 774 775#ifdef L_mulhi3 776 declare_near ___mulhi3 777 778; 779; 780; unsigned short ___mulhi3(unsigned short a, unsigned short b) 781; 782; a = register D 783; b = register X 784; 785#ifdef mc68hc12 786 pshx ; Preserve X 787 exg x,y 788 emul 789 exg x,y 790 pulx 791 rts 792#else 793#ifdef NO_TMP 794 ; 795 ; 16-bit multiplication without temp memory location. 796 ; (smaller but slower) 797 ; 798 pshx ; (4) 799 ins ; (3) 800 pshb ; (3) 801 psha ; (3) 802 pshx ; (4) 803 pula ; (4) 804 pulx ; (5) 805 mul ; (10) B.high * A.low 806 xgdx ; (3) 807 mul ; (10) B.low * A.high 808 abx ; (3) 809 pula ; (4) 810 pulb ; (4) 811 mul ; (10) B.low * A.low 812 pshx ; (4) 813 tsx ; (3) 814 adda 1,x ; (4) 815 pulx ; (5) 816 rts ; (5) 20 bytes 817 ; --- 818 ; 91 cycles 819#else 820 stx *_.tmp ; (4) 821 pshb ; (3) 822 ldab *_.tmp+1 ; (3) 823 mul ; (10) A.high * B.low 824 ldaa *_.tmp ; (3) 825 stab *_.tmp ; (3) 826 pulb ; (4) 827 pshb ; (4) 828 mul ; (10) A.low * B.high 829 addb *_.tmp ; (4) 830 stab *_.tmp ; (3) 831 ldaa *_.tmp+1 ; (3) 832 pulb ; (4) 833 mul ; (10) A.low * B.low 834 adda *_.tmp ; (4) 835 rts ; (5) 24/32 bytes 836 ; 77/85 cycles 837#endif 838#endif 839#endif 840 841#ifdef L_mulhi32 842 843; 844; 845; unsigned long __mulhi32(unsigned short a, unsigned short b) 846; 847; a = register D 848; b = value on stack 849; 850; +---------------+ 851; | B low | <- 7,x 852; +---------------+ 853; | B high | <- 6,x 854; +---------------+ 855; | PC low | 856; +---------------+ 857; | PC high | 858; +---------------+ 859; | Tmp low | 860; +---------------+ 861; | Tmp high | 862; +---------------+ 863; | A low | 864; +---------------+ 865; | A high | 866; +---------------+ <- 0,x 867; 868; 869; <B-low> 5,x 870; <B-high> 4,x 871; <ret> 2,x 872; <A-low> 1,x 873; <A-high> 0,x 874; 875 declare_near __mulhi32 876 877#ifdef mc68hc12 878 ldy 2,sp 879 emul 880 exg x,y 881 rts 882#else 883 pshx ; Room for temp value 884 pshb 885 psha 886 tsx 887 ldab 6,x 888 mul 889 xgdy ; A.high * B.high 890 ldab 7,x 891 pula 892 mul ; A.high * B.low 893 std 2,x 894 ldaa 1,x 895 ldab 6,x 896 mul ; A.low * B.high 897 addd 2,x 898 stab 2,x 899 tab 900 aby 901 bcc N 902 ldab #0xff 903 aby 904 iny 905N: 906 ldab 7,x 907 pula 908 mul ; A.low * B.low 909 adda 2,x 910 pulx ; Drop temp location 911 pshy ; Put high part in X 912 pulx 913 bcc Ret 914 inx 915Ret: 916 rts 917#endif 918#endif 919 920#ifdef L_mulsi3 921 922; 923; <B-low> 8,y 924; <B-high> 6,y 925; <ret> 4,y 926; <tmp> 2,y 927; <A-low> 0,y 928; 929; D,X -> A 930; Stack -> B 931; 932; The result is: 933; 934; (((A.low * B.high) + (A.high * B.low)) << 16) + (A.low * B.low) 935; 936; 937; 938 939 declare __mulsi3 940 941#ifdef mc68hc12 942 pshd ; Save A.low 943 ldy ARG(4),sp 944 emul ; A.low * B.high 945 ldy ARG(6),sp 946 exg x,d 947 emul ; A.high * B.low 948 leax d,x 949 ldy ARG(6),sp 950 puld 951 emul ; A.low * B.low 952 exg d,y 953 leax d,x 954 exg d,y 955 ret 956#else 957B_low = ARG(8) 958B_high = ARG(6) 959A_low = 0 960A_high = 2 961 pshx 962 pshb 963 psha 964 tsy 965; 966; If B.low is 0, optimize into: (A.low * B.high) << 16 967; 968 ldd B_low,y 969 beq B_low_zero 970; 971; If A.high is 0, optimize into: (A.low * B.high) << 16 + (A.low * B.low) 972; 973 cpx #0 974 beq A_high_zero 975 bsr ___mulhi3 ; A.high * B.low 976; 977; If A.low is 0, optimize into: (A.high * B.low) << 16 978; 979 ldx A_low,y 980 beq A_low_zero ; X = 0, D = A.high * B.low 981 std 2,y 982; 983; If B.high is 0, we can avoid the (A.low * B.high) << 16 term. 984; 985 ldd B_high,y 986 beq B_high_zero 987 bsr ___mulhi3 ; A.low * B.high 988 addd 2,y 989 std 2,y 990; 991; Here, we know that A.low and B.low are not 0. 992; 993B_high_zero: 994 ldd B_low,y ; A.low is on the stack 995 bsr __mulhi32 ; A.low * B.low 996 xgdx 997 tsy ; Y was clobbered, get it back 998 addd 2,y 999A_low_zero: ; See A_low_zero_non_optimized below 1000 xgdx 1001Return: 1002 ins 1003 ins 1004 ins 1005 ins 1006 ret 1007; 1008; 1009; A_low_zero_non_optimized: 1010; 1011; At this step, X = 0 and D = (A.high * B.low) 1012; Optimize into: (A.high * B.low) << 16 1013; 1014; xgdx 1015; clra ; Since X was 0, clearing D is superfuous. 1016; clrb 1017; bra Return 1018; ---------------- 1019; B.low == 0, the result is: (A.low * B.high) << 16 1020; 1021; At this step: 1022; D = B.low = 0 1023; X = A.high ? 1024; A.low is at A_low,y ? 1025; B.low is at B_low,y ? 1026; 1027B_low_zero: 1028 ldd A_low,y 1029 beq Zero1 1030 ldx B_high,y 1031 beq Zero2 1032 bsr ___mulhi3 1033Zero1: 1034 xgdx 1035Zero2: 1036 clra 1037 clrb 1038 bra Return 1039; ---------------- 1040; A.high is 0, optimize into: (A.low * B.high) << 16 + (A.low * B.low) 1041; 1042; At this step: 1043; D = B.low != 0 1044; X = A.high = 0 1045; A.low is at A_low,y ? 1046; B.low is at B_low,y ? 1047; 1048A_high_zero: 1049 ldd A_low,y ; A.low 1050 beq Zero1 1051 ldx B_high,y ; B.high 1052 beq A_low_B_low 1053 bsr ___mulhi3 1054 std 2,y 1055 bra B_high_zero ; Do the (A.low * B.low) and the add. 1056 1057; ---------------- 1058; A.high and B.high are 0 optimize into: (A.low * B.low) 1059; 1060; At this step: 1061; D = B.high = 0 1062; X = A.low != 0 1063; A.low is at A_low,y != 0 1064; B.high is at B_high,y = 0 1065; 1066A_low_B_low: 1067 ldd B_low,y ; A.low is on the stack 1068 bsr __mulhi32 1069 bra Return 1070#endif 1071#endif 1072 1073#ifdef L_map_data 1074 1075 .sect .install2,"ax",@progbits 1076 .globl __map_data_section 1077 .globl __data_image 1078#ifdef mc68hc12 1079 .globl __data_section_size 1080#endif 1081__map_data_section: 1082#ifdef mc68hc12 1083 ldx #__data_image 1084 ldy #__data_section_start 1085 ldd #__data_section_size 1086 beq Done 1087Loop: 1088 movb 1,x+,1,y+ 1089 dbne d,Loop 1090#else 1091 ldx #__data_image 1092 ldy #__data_section_start 1093 bra Start_map 1094Loop: 1095 ldaa 0,x 1096 staa 0,y 1097 inx 1098 iny 1099Start_map: 1100 cpx #__data_image_end 1101 blo Loop 1102#endif 1103Done: 1104 1105#endif 1106 1107#ifdef L_init_bss 1108 1109 .sect .install2,"ax",@progbits 1110 .globl __init_bss_section 1111 1112__init_bss_section: 1113 ldd #__bss_size 1114 beq Done 1115 ldx #__bss_start 1116Loop: 1117#ifdef mc68hc12 1118 clr 1,x+ 1119 dbne d,Loop 1120#else 1121 clr 0,x 1122 inx 1123 subd #1 1124 bne Loop 1125#endif 1126Done: 1127 1128#endif 1129 1130#ifdef L_ctor 1131 1132; End of constructor table 1133 .sect .install3,"ax",@progbits 1134 .globl __do_global_ctors 1135 1136__do_global_ctors: 1137 ; Start from the end - sizeof(void*) 1138 ldx #__CTOR_END__-2 1139ctors_loop: 1140 cpx #__CTOR_LIST__ 1141 blo ctors_done 1142 pshx 1143 ldx 0,x 1144 jsr 0,x 1145 pulx 1146 dex 1147 dex 1148 bra ctors_loop 1149ctors_done: 1150 1151#endif 1152 1153#ifdef L_dtor 1154 1155 .sect .fini3,"ax",@progbits 1156 .globl __do_global_dtors 1157 1158;; 1159;; This piece of code is inserted in the _exit() code by the linker. 1160;; 1161__do_global_dtors: 1162 pshb ; Save exit code 1163 psha 1164 ldx #__DTOR_LIST__ 1165dtors_loop: 1166 cpx #__DTOR_END__ 1167 bhs dtors_done 1168 pshx 1169 ldx 0,x 1170 jsr 0,x 1171 pulx 1172 inx 1173 inx 1174 bra dtors_loop 1175dtors_done: 1176 pula ; Restore exit code 1177 pulb 1178 1179#endif 1180 1181#ifdef L_far_tramp 1182#ifdef mc68hc12 1183 .sect .tramp,"ax",@progbits 1184 .globl __far_trampoline 1185 1186;; This is a trampoline used by the linker to invoke a function 1187;; using rtc to return and being called with jsr/bsr. 1188;; The trampoline generated is: 1189;; 1190;; foo_tramp: 1191;; ldy #foo 1192;; call __far_trampoline,page(foo) 1193;; 1194;; The linker transforms: 1195;; 1196;; jsr foo 1197;; 1198;; into 1199;; jsr foo_tramp 1200;; 1201;; The linker generated trampoline and _far_trampoline must be in 1202;; non-banked memory. 1203;; 1204__far_trampoline: 1205 movb 0,sp, 2,sp ; Copy page register below the caller's return 1206 leas 2,sp ; address. 1207 jmp 0,y ; We have a 'call/rtc' stack layout now 1208 ; and can jump to the far handler 1209 ; (whose memory bank is mapped due to the 1210 ; call to the trampoline). 1211#endif 1212 1213#ifdef mc68hc11 1214 .sect .tramp,"ax",@progbits 1215 .globl __far_trampoline 1216 1217;; Trampoline generated by gcc for 68HC11: 1218;; 1219;; pshb 1220;; ldab #%page(func) 1221;; ldy #%addr(func) 1222;; jmp __far_trampoline 1223;; 1224__far_trampoline: 1225 psha ; (2) Save function parameter (high) 1226 ;; <Read current page in A> 1227 psha ; (2) 1228 ;; <Set currenge page from B> 1229 pshx ; (4) 1230 tsx ; (3) 1231 ldab 4,x ; (4) Restore function parameter (low) 1232 ldaa 2,x ; (4) Get saved page number 1233 staa 4,x ; (4) Save it below return PC 1234 pulx ; (5) 1235 pula ; (3) 1236 pula ; (3) Restore function parameter (high) 1237 jmp 0,y ; (4) 1238#endif 1239#endif 1240 1241#ifdef L_call_far 1242#ifdef mc68hc11 1243 .sect .tramp,"ax",@progbits 1244 .globl __call_a16 1245 .globl __call_a32 1246;; 1247;; The call methods are used for 68HC11 to support memory bank switching. 1248;; Every far call is redirected to these call methods. Its purpose is to: 1249;; 1250;; 1/ Save the current page on the stack (1 byte to follow 68HC12 call frame) 1251;; 2/ Install the new page 1252;; 3/ Jump to the real function 1253;; 1254;; The page switching (get/save) is board dependent. The default provided 1255;; here does nothing (just create the appropriate call frame). 1256;; 1257;; Call sequence (10 bytes, 13 cycles): 1258;; 1259;; ldx #page ; (3) 1260;; ldy #func ; (4) 1261;; jsr __call_a16 ; (6) 1262;; 1263;; Call trampoline (11 bytes, 19 cycles): 1264;; 1265__call_a16: 1266 ;; xgdx ; (3) 1267 ;; <Read current page in A> ; (3) ldaa _current_page 1268 psha ; (2) 1269 ;; <Set current page from B> ; (4) staa _current_page 1270 ;; xgdx ; (3) 1271 jmp 0,y ; (4) 1272 1273;; 1274;; Call sequence (10 bytes, 14 cycles): 1275;; 1276;; pshb ; (2) 1277;; ldab #page ; (2) 1278;; ldy #func ; (4) 1279;; jsr __call_a32 ; (6) 1280;; 1281;; Call trampoline (87 bytes, 57 cycles): 1282;; 1283__call_a32: 1284 pshx ; (4) 1285 psha ; (2) 1286 ;; <Read current page in A> ; (3) ldaa _current_page 1287 psha ; (2) 1288 ;; <Set current page from B> ; (4) staa _current_page 1289 tsx ; (3) 1290 ldab 6,x ; (4) Restore function parameter 1291 ldaa 5,x ; (4) Move PC return at good place 1292 staa 6,x ; (4) 1293 ldaa 4,x ; (4) 1294 staa 5,x ; (4) 1295 pula ; (3) 1296 staa 4,x ; (4) 1297 pula ; (3) 1298 pulx ; (5) 1299 jmp 0,y ; (4) 1300#endif 1301#endif 1302 1303#ifdef L_return_far 1304#ifdef mc68hc11 1305 .sect .tramp,"ax",@progbits 1306 .globl __return_void 1307 .globl __return_16 1308 .globl __return_32 1309 1310__return_void: 1311 ;; pulb 1312 ;; <Set current page from B> (Board specific) 1313 ;; rts 1314__return_16: 1315 ;; xgdx 1316 ;; pulb 1317 ;; <Set current page from B> (Board specific) 1318 ;; xgdx 1319 ;; rts 1320__return_32: 1321 ;; xgdy 1322 ;; pulb 1323 ;; <Set current page from B> (Board specific) 1324 ;; xgdy 1325 ;; rts 1326 ins 1327 rts 1328#endif 1329#endif 1330.Lend: 1331;----------------------------------------- 1332; end required gcclib code 1333;----------------------------------------- 1334