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