diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /gcc/config/m68hc11/larith.asm | |
download | cbb-gcc-4.6.4-15d2061ac0796199866debe9ac87130894b0cdd3.tar.bz2 cbb-gcc-4.6.4-15d2061ac0796199866debe9ac87130894b0cdd3.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'gcc/config/m68hc11/larith.asm')
-rw-r--r-- | gcc/config/m68hc11/larith.asm | 1333 |
1 files changed, 1333 insertions, 0 deletions
diff --git a/gcc/config/m68hc11/larith.asm b/gcc/config/m68hc11/larith.asm new file mode 100644 index 000000000..09f946cbf --- /dev/null +++ b/gcc/config/m68hc11/larith.asm @@ -0,0 +1,1333 @@ +/* libgcc routines for M68HC11 & M68HC12. + Copyright (C) 1999, 2000, 2001, 2002, 2003, 2008, 2009 + Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3, or (at your option) any +later version. + +This file is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + +#ifdef __HAVE_SHORT_INT__ + .mode mshort +#else + .mode mlong +#endif + + .macro declare_near name + .globl \name + .type \name,@function + .size \name,.Lend-\name +\name: + .endm + +#if defined(__USE_RTC__) +# define ARG(N) N+1 + + .macro ret +#if defined(mc68hc12) + rtc +#else + jmp __return_32 +#endif + .endm + + .macro declare name + .globl \name + .type \name,@function + .size \name,.Lend-\name + .far \name +\name: + .endm + + .macro farsym name + .far NAME + .endm + +#else +# define ARG(N) N + + .macro ret + rts + .endm + + .macro farsym name + .endm + + .macro declare name + .globl \name + .type \name,@function + .size \name,.Lend-\name +\name: + .endm + +#endif + + .sect .text + + +#define REG(NAME) \ +NAME: .dc.w 1; \ + .type NAME,@object ; \ + .size NAME,2 + +#ifdef L_regs_min +/* Pseudo hard registers used by gcc. + They should be located in page0. */ + + .sect .softregs + .globl _.tmp + .globl _.z,_.xy +REG(_.tmp) +REG(_.z) +REG(_.xy) + +#endif + +#ifdef L_regs_frame + .sect .softregs + .globl _.frame +REG(_.frame) +#endif + +#ifdef L_regs_d1_2 + .sect .softregs + .globl _.d1,_.d2 +REG(_.d1) +REG(_.d2) +#endif + +#ifdef L_regs_d3_4 + .sect .softregs + .globl _.d3,_.d4 +REG(_.d3) +REG(_.d4) +#endif + +#ifdef L_regs_d5_6 + .sect .softregs + .globl _.d5,_.d6 +REG(_.d5) +REG(_.d6) +#endif + +#ifdef L_regs_d7_8 + .sect .softregs + .globl _.d7,_.d8 +REG(_.d7) +REG(_.d8) +#endif + +#ifdef L_regs_d9_16 +/* Pseudo hard registers used by gcc. + They should be located in page0. */ + .sect .softregs + .globl _.d9,_.d10,_.d11,_.d12,_.d13,_.d14 + .globl _.d15,_.d16 +REG(_.d9) +REG(_.d10) +REG(_.d11) +REG(_.d12) +REG(_.d13) +REG(_.d14) +REG(_.d15) +REG(_.d16) + +#endif + +#ifdef L_regs_d17_32 +/* Pseudo hard registers used by gcc. + They should be located in page0. */ + .sect .softregs + .globl _.d17,_.d18,_.d19,_.d20,_.d21,_.d22 + .globl _.d23,_.d24,_.d25,_.d26,_.d27,_.d28 + .globl _.d29,_.d30,_.d31,_.d32 +REG(_.d17) +REG(_.d18) +REG(_.d19) +REG(_.d20) +REG(_.d21) +REG(_.d22) +REG(_.d23) +REG(_.d24) +REG(_.d25) +REG(_.d26) +REG(_.d27) +REG(_.d28) +REG(_.d29) +REG(_.d30) +REG(_.d31) +REG(_.d32) +#endif + +#ifdef L_premain +;; +;; Specific initialization for 68hc11 before the main. +;; Nothing special for a generic routine; Just enable interrupts. +;; + declare_near __premain + clra + tap ; Clear both I and X. + rts +#endif + +#ifdef L__exit +;; +;; Exit operation. Just loop forever and wait for interrupts. +;; (no other place to go) +;; This operation is split in several pieces collected together by +;; the linker script. This allows to support destructors at the +;; exit stage while not impacting program sizes when there is no +;; destructors. +;; +;; _exit: +;; *(.fini0) /* Beginning of finish code (_exit symbol). */ +;; *(.fini1) /* Place holder for applications. */ +;; *(.fini2) /* C++ destructors. */ +;; *(.fini3) /* Place holder for applications. */ +;; *(.fini4) /* Runtime exit. */ +;; + .sect .fini0,"ax",@progbits + .globl _exit + .globl exit + .weak exit + farsym exit + farsym _exit +exit: +_exit: + + .sect .fini4,"ax",@progbits +fatal: + cli + wai + bra fatal +#endif + +#ifdef L_abort +;; +;; Abort operation. This is defined for the GCC testsuite. +;; + declare abort + + ldd #255 ; +#ifdef mc68hc12 + trap #0x30 +#else + .byte 0xCD ; Generate an illegal instruction trap + .byte 0x03 ; The simulator catches this and stops. +#endif + jmp _exit +#endif + +#ifdef L_cleanup +;; +;; Cleanup operation used by exit(). +;; + declare _cleanup + + ret +#endif + +;----------------------------------------- +; required gcclib code +;----------------------------------------- +#ifdef L_memcpy + declare memcpy + declare __memcpy + + .weak memcpy +;;; +;;; void* memcpy(void*, const void*, size_t) +;;; +;;; D = dst Pmode +;;; 2,sp = src Pmode +;;; 4,sp = size HImode (size_t) +;;; +#ifdef mc68hc12 + ldx ARG(2),sp + ldy ARG(4),sp + pshd + xgdy + lsrd + bcc Start + movb 1,x+,1,y+ +Start: + beq Done +Loop: + movw 2,x+,2,y+ + dbne d,Loop +Done: + puld + ret +#else + xgdy + tsx + ldd ARG(4),x + ldx ARG(2),x ; SRC = X, DST = Y + cpd #0 + beq End + pshy + inca ; Correction for the deca below +L0: + psha ; Save high-counter part +L1: + ldaa 0,x ; Copy up to 256 bytes + staa 0,y + inx + iny + decb + bne L1 + pula + deca + bne L0 + puly ; Restore Y to return the DST +End: + xgdy + ret +#endif +#endif + +#ifdef L_memset + declare memset + declare __memset +;;; +;;; void* memset(void*, int value, size_t) +;;; +#ifndef __HAVE_SHORT_INT__ +;;; D = dst Pmode +;;; 2,sp = src SImode +;;; 6,sp = size HImode (size_t) + val = ARG(5) + size = ARG(6) +#else +;;; D = dst Pmode +;;; 2,sp = src SImode +;;; 6,sp = size HImode (size_t) + val = ARG(3) + size = ARG(4) +#endif +#ifdef mc68hc12 + xgdx + ldab val,sp + ldy size,sp + pshx + beq End +Loop: + stab 1,x+ + dbne y,Loop +End: + puld + ret +#else + xgdx + tsy + ldab val,y + ldy size,y ; DST = X, CNT = Y + beq End + pshx +L0: + stab 0,x ; Fill up to 256 bytes + inx + dey + bne L0 + pulx ; Restore X to return the DST +End: + xgdx + ret +#endif +#endif + +#ifdef L_adddi3 + declare ___adddi3 + + tsx + xgdy + ldd ARG(8),x ; Add LSB + addd ARG(16),x + std 6,y ; Save (carry preserved) + + ldd ARG(6),x + adcb ARG(15),x + adca ARG(14),x + std 4,y + + ldd ARG(4),x + adcb ARG(13),x + adca ARG(12),x + std 2,y + + ldd ARG(2),x + adcb ARG(11),x ; Add MSB + adca ARG(10),x + std 0,y + + xgdy + ret +#endif + +#ifdef L_subdi3 + declare ___subdi3 + + tsx + xgdy + ldd ARG(8),x ; Subtract LSB + subd ARG(16),x + std 6,y ; Save, borrow preserved + + ldd ARG(6),x + sbcb ARG(15),x + sbca ARG(14),x + std 4,y + + ldd ARG(4),x + sbcb ARG(13),x + sbca ARG(12),x + std 2,y + + ldd ARG(2),x ; Subtract MSB + sbcb ARG(11),x + sbca ARG(10),x + std 0,y + + xgdy ; + ret +#endif + +#ifdef L_notdi2 + declare ___notdi2 + + tsy + xgdx + ldd ARG(8),y + coma + comb + std 6,x + + ldd ARG(6),y + coma + comb + std 4,x + + ldd ARG(4),y + coma + comb + std 2,x + + ldd ARG(2),y + coma + comb + std 0,x + xgdx + ret +#endif + +#ifdef L_negsi2 + declare_near ___negsi2 + + comb + coma + xgdx + comb + coma + inx + xgdx + bne done + inx +done: + rts +#endif + +#ifdef L_one_cmplsi2 + declare_near ___one_cmplsi2 + + comb + coma + xgdx + comb + coma + xgdx + rts +#endif + +#ifdef L_ashlsi3 + declare_near ___ashlsi3 + + xgdy + clra + andb #0x1f + xgdy + beq Return +Loop: + lsld + xgdx + rolb + rola + xgdx + dey + bne Loop +Return: + rts +#endif + +#ifdef L_ashrsi3 + declare_near ___ashrsi3 + + xgdy + clra + andb #0x1f + xgdy + beq Return +Loop: + xgdx + asra + rorb + xgdx + rora + rorb + dey + bne Loop +Return: + rts +#endif + +#ifdef L_lshrsi3 + declare_near ___lshrsi3 + + xgdy + clra + andb #0x1f + xgdy + beq Return +Loop: + xgdx + lsrd + xgdx + rora + rorb + dey + bne Loop +Return: + rts +#endif + +#ifdef L_lshrhi3 + declare_near ___lshrhi3 + + cpx #16 + bge Return_zero + cpx #0 + beq Return +Loop: + lsrd + dex + bne Loop +Return: + rts +Return_zero: + clra + clrb + rts +#endif + +#ifdef L_lshlhi3 + declare_near ___lshlhi3 + + cpx #16 + bge Return_zero + cpx #0 + beq Return +Loop: + lsld + dex + bne Loop +Return: + rts +Return_zero: + clra + clrb + rts +#endif + +#ifdef L_rotrhi3 + declare_near ___rotrhi3 + +___rotrhi3: + xgdx + clra + andb #0x0f + xgdx + beq Return +Loop: + tap + rorb + rora + dex + bne Loop +Return: + rts +#endif + +#ifdef L_rotlhi3 + declare_near ___rotlhi3 + +___rotlhi3: + xgdx + clra + andb #0x0f + xgdx + beq Return +Loop: + asrb + rolb + rola + rolb + dex + bne Loop +Return: + rts +#endif + +#ifdef L_ashrhi3 + declare_near ___ashrhi3 + + cpx #16 + bge Return_minus_1_or_zero + cpx #0 + beq Return +Loop: + asra + rorb + dex + bne Loop +Return: + rts +Return_minus_1_or_zero: + clrb + tsta + bpl Return_zero + comb +Return_zero: + tba + rts +#endif + +#ifdef L_ashrqi3 + declare_near ___ashrqi3 + + cmpa #8 + bge Return_minus_1_or_zero + tsta + beq Return +Loop: + asrb + deca + bne Loop +Return: + rts +Return_minus_1_or_zero: + clrb + tstb + bpl Return_zero + coma +Return_zero: + tab + rts +#endif + +#ifdef L_lshlqi3 + declare_near ___lshlqi3 + + cmpa #8 + bge Return_zero + tsta + beq Return +Loop: + lslb + deca + bne Loop +Return: + rts +Return_zero: + clrb + rts +#endif + +#ifdef L_divmodhi4 +#ifndef mc68hc12 +/* 68HC12 signed divisions are generated inline (idivs). */ + + declare_near __divmodhi4 + +; +;; D = numerator +;; X = denominator +;; +;; Result: D = D / X +;; X = D % X +;; + tsta + bpl Numerator_pos + comb ; D = -D <=> D = (~D) + 1 + coma + xgdx + inx + tsta + bpl Numerator_neg_denominator_pos +Numerator_neg_denominator_neg: + comb ; X = -X + coma + addd #1 + xgdx + idiv + coma + comb + xgdx ; Remainder <= 0 and result >= 0 + inx + rts + +Numerator_pos_denominator_pos: + xgdx + idiv + xgdx ; Both values are >= 0 + rts + +Numerator_pos: + xgdx + tsta + bpl Numerator_pos_denominator_pos +Numerator_pos_denominator_neg: + coma ; X = -X + comb + xgdx + inx + idiv + xgdx ; Remainder >= 0 but result <= 0 + coma + comb + addd #1 + rts + +Numerator_neg_denominator_pos: + xgdx + idiv + coma ; One value is > 0 and the other < 0 + comb ; Change the sign of result and remainder + xgdx + inx + coma + comb + addd #1 + rts +#endif /* !mc68hc12 */ +#endif + +#ifdef L_mulqi3 + declare_near ___mulqi3 + +; +; short __mulqi3(signed char a, signed char b); +; +; signed char a -> register A +; signed char b -> register B +; +; returns the signed result of A * B in register D. +; + tsta + bmi A_neg + tstb + bmi B_neg + mul + rts +B_neg: + negb + bra A_or_B_neg +A_neg: + nega + tstb + bmi AB_neg +A_or_B_neg: + mul + coma + comb + addd #1 + rts +AB_neg: + negb + mul + rts +#endif + +#ifdef L_mulhi3 + declare_near ___mulhi3 + +; +; +; unsigned short ___mulhi3(unsigned short a, unsigned short b) +; +; a = register D +; b = register X +; +#ifdef mc68hc12 + pshx ; Preserve X + exg x,y + emul + exg x,y + pulx + rts +#else +#ifdef NO_TMP + ; + ; 16-bit multiplication without temp memory location. + ; (smaller but slower) + ; + pshx ; (4) + ins ; (3) + pshb ; (3) + psha ; (3) + pshx ; (4) + pula ; (4) + pulx ; (5) + mul ; (10) B.high * A.low + xgdx ; (3) + mul ; (10) B.low * A.high + abx ; (3) + pula ; (4) + pulb ; (4) + mul ; (10) B.low * A.low + pshx ; (4) + tsx ; (3) + adda 1,x ; (4) + pulx ; (5) + rts ; (5) 20 bytes + ; --- + ; 91 cycles +#else + stx *_.tmp ; (4) + pshb ; (3) + ldab *_.tmp+1 ; (3) + mul ; (10) A.high * B.low + ldaa *_.tmp ; (3) + stab *_.tmp ; (3) + pulb ; (4) + pshb ; (4) + mul ; (10) A.low * B.high + addb *_.tmp ; (4) + stab *_.tmp ; (3) + ldaa *_.tmp+1 ; (3) + pulb ; (4) + mul ; (10) A.low * B.low + adda *_.tmp ; (4) + rts ; (5) 24/32 bytes + ; 77/85 cycles +#endif +#endif +#endif + +#ifdef L_mulhi32 + +; +; +; unsigned long __mulhi32(unsigned short a, unsigned short b) +; +; a = register D +; b = value on stack +; +; +---------------+ +; | B low | <- 7,x +; +---------------+ +; | B high | <- 6,x +; +---------------+ +; | PC low | +; +---------------+ +; | PC high | +; +---------------+ +; | Tmp low | +; +---------------+ +; | Tmp high | +; +---------------+ +; | A low | +; +---------------+ +; | A high | +; +---------------+ <- 0,x +; +; +; <B-low> 5,x +; <B-high> 4,x +; <ret> 2,x +; <A-low> 1,x +; <A-high> 0,x +; + declare_near __mulhi32 + +#ifdef mc68hc12 + ldy 2,sp + emul + exg x,y + rts +#else + pshx ; Room for temp value + pshb + psha + tsx + ldab 6,x + mul + xgdy ; A.high * B.high + ldab 7,x + pula + mul ; A.high * B.low + std 2,x + ldaa 1,x + ldab 6,x + mul ; A.low * B.high + addd 2,x + stab 2,x + tab + aby + bcc N + ldab #0xff + aby + iny +N: + ldab 7,x + pula + mul ; A.low * B.low + adda 2,x + pulx ; Drop temp location + pshy ; Put high part in X + pulx + bcc Ret + inx +Ret: + rts +#endif +#endif + +#ifdef L_mulsi3 + +; +; <B-low> 8,y +; <B-high> 6,y +; <ret> 4,y +; <tmp> 2,y +; <A-low> 0,y +; +; D,X -> A +; Stack -> B +; +; The result is: +; +; (((A.low * B.high) + (A.high * B.low)) << 16) + (A.low * B.low) +; +; +; + + declare __mulsi3 + +#ifdef mc68hc12 + pshd ; Save A.low + ldy ARG(4),sp + emul ; A.low * B.high + ldy ARG(6),sp + exg x,d + emul ; A.high * B.low + leax d,x + ldy ARG(6),sp + puld + emul ; A.low * B.low + exg d,y + leax d,x + exg d,y + ret +#else +B_low = ARG(8) +B_high = ARG(6) +A_low = 0 +A_high = 2 + pshx + pshb + psha + tsy +; +; If B.low is 0, optimize into: (A.low * B.high) << 16 +; + ldd B_low,y + beq B_low_zero +; +; If A.high is 0, optimize into: (A.low * B.high) << 16 + (A.low * B.low) +; + cpx #0 + beq A_high_zero + bsr ___mulhi3 ; A.high * B.low +; +; If A.low is 0, optimize into: (A.high * B.low) << 16 +; + ldx A_low,y + beq A_low_zero ; X = 0, D = A.high * B.low + std 2,y +; +; If B.high is 0, we can avoid the (A.low * B.high) << 16 term. +; + ldd B_high,y + beq B_high_zero + bsr ___mulhi3 ; A.low * B.high + addd 2,y + std 2,y +; +; Here, we know that A.low and B.low are not 0. +; +B_high_zero: + ldd B_low,y ; A.low is on the stack + bsr __mulhi32 ; A.low * B.low + xgdx + tsy ; Y was clobbered, get it back + addd 2,y +A_low_zero: ; See A_low_zero_non_optimized below + xgdx +Return: + ins + ins + ins + ins + ret +; +; +; A_low_zero_non_optimized: +; +; At this step, X = 0 and D = (A.high * B.low) +; Optimize into: (A.high * B.low) << 16 +; +; xgdx +; clra ; Since X was 0, clearing D is superfuous. +; clrb +; bra Return +; ---------------- +; B.low == 0, the result is: (A.low * B.high) << 16 +; +; At this step: +; D = B.low = 0 +; X = A.high ? +; A.low is at A_low,y ? +; B.low is at B_low,y ? +; +B_low_zero: + ldd A_low,y + beq Zero1 + ldx B_high,y + beq Zero2 + bsr ___mulhi3 +Zero1: + xgdx +Zero2: + clra + clrb + bra Return +; ---------------- +; A.high is 0, optimize into: (A.low * B.high) << 16 + (A.low * B.low) +; +; At this step: +; D = B.low != 0 +; X = A.high = 0 +; A.low is at A_low,y ? +; B.low is at B_low,y ? +; +A_high_zero: + ldd A_low,y ; A.low + beq Zero1 + ldx B_high,y ; B.high + beq A_low_B_low + bsr ___mulhi3 + std 2,y + bra B_high_zero ; Do the (A.low * B.low) and the add. + +; ---------------- +; A.high and B.high are 0 optimize into: (A.low * B.low) +; +; At this step: +; D = B.high = 0 +; X = A.low != 0 +; A.low is at A_low,y != 0 +; B.high is at B_high,y = 0 +; +A_low_B_low: + ldd B_low,y ; A.low is on the stack + bsr __mulhi32 + bra Return +#endif +#endif + +#ifdef L_map_data + + .sect .install2,"ax",@progbits + .globl __map_data_section + .globl __data_image +#ifdef mc68hc12 + .globl __data_section_size +#endif +__map_data_section: +#ifdef mc68hc12 + ldx #__data_image + ldy #__data_section_start + ldd #__data_section_size + beq Done +Loop: + movb 1,x+,1,y+ + dbne d,Loop +#else + ldx #__data_image + ldy #__data_section_start + bra Start_map +Loop: + ldaa 0,x + staa 0,y + inx + iny +Start_map: + cpx #__data_image_end + blo Loop +#endif +Done: + +#endif + +#ifdef L_init_bss + + .sect .install2,"ax",@progbits + .globl __init_bss_section + +__init_bss_section: + ldd #__bss_size + beq Done + ldx #__bss_start +Loop: +#ifdef mc68hc12 + clr 1,x+ + dbne d,Loop +#else + clr 0,x + inx + subd #1 + bne Loop +#endif +Done: + +#endif + +#ifdef L_ctor + +; End of constructor table + .sect .install3,"ax",@progbits + .globl __do_global_ctors + +__do_global_ctors: + ; Start from the end - sizeof(void*) + ldx #__CTOR_END__-2 +ctors_loop: + cpx #__CTOR_LIST__ + blo ctors_done + pshx + ldx 0,x + jsr 0,x + pulx + dex + dex + bra ctors_loop +ctors_done: + +#endif + +#ifdef L_dtor + + .sect .fini3,"ax",@progbits + .globl __do_global_dtors + +;; +;; This piece of code is inserted in the _exit() code by the linker. +;; +__do_global_dtors: + pshb ; Save exit code + psha + ldx #__DTOR_LIST__ +dtors_loop: + cpx #__DTOR_END__ + bhs dtors_done + pshx + ldx 0,x + jsr 0,x + pulx + inx + inx + bra dtors_loop +dtors_done: + pula ; Restore exit code + pulb + +#endif + +#ifdef L_far_tramp +#ifdef mc68hc12 + .sect .tramp,"ax",@progbits + .globl __far_trampoline + +;; This is a trampoline used by the linker to invoke a function +;; using rtc to return and being called with jsr/bsr. +;; The trampoline generated is: +;; +;; foo_tramp: +;; ldy #foo +;; call __far_trampoline,page(foo) +;; +;; The linker transforms: +;; +;; jsr foo +;; +;; into +;; jsr foo_tramp +;; +;; The linker generated trampoline and _far_trampoline must be in +;; non-banked memory. +;; +__far_trampoline: + movb 0,sp, 2,sp ; Copy page register below the caller's return + leas 2,sp ; address. + jmp 0,y ; We have a 'call/rtc' stack layout now + ; and can jump to the far handler + ; (whose memory bank is mapped due to the + ; call to the trampoline). +#endif + +#ifdef mc68hc11 + .sect .tramp,"ax",@progbits + .globl __far_trampoline + +;; Trampoline generated by gcc for 68HC11: +;; +;; pshb +;; ldab #%page(func) +;; ldy #%addr(func) +;; jmp __far_trampoline +;; +__far_trampoline: + psha ; (2) Save function parameter (high) + ;; <Read current page in A> + psha ; (2) + ;; <Set currenge page from B> + pshx ; (4) + tsx ; (3) + ldab 4,x ; (4) Restore function parameter (low) + ldaa 2,x ; (4) Get saved page number + staa 4,x ; (4) Save it below return PC + pulx ; (5) + pula ; (3) + pula ; (3) Restore function parameter (high) + jmp 0,y ; (4) +#endif +#endif + +#ifdef L_call_far +#ifdef mc68hc11 + .sect .tramp,"ax",@progbits + .globl __call_a16 + .globl __call_a32 +;; +;; The call methods are used for 68HC11 to support memory bank switching. +;; Every far call is redirected to these call methods. Its purpose is to: +;; +;; 1/ Save the current page on the stack (1 byte to follow 68HC12 call frame) +;; 2/ Install the new page +;; 3/ Jump to the real function +;; +;; The page switching (get/save) is board dependent. The default provided +;; here does nothing (just create the appropriate call frame). +;; +;; Call sequence (10 bytes, 13 cycles): +;; +;; ldx #page ; (3) +;; ldy #func ; (4) +;; jsr __call_a16 ; (6) +;; +;; Call trampoline (11 bytes, 19 cycles): +;; +__call_a16: + ;; xgdx ; (3) + ;; <Read current page in A> ; (3) ldaa _current_page + psha ; (2) + ;; <Set current page from B> ; (4) staa _current_page + ;; xgdx ; (3) + jmp 0,y ; (4) + +;; +;; Call sequence (10 bytes, 14 cycles): +;; +;; pshb ; (2) +;; ldab #page ; (2) +;; ldy #func ; (4) +;; jsr __call_a32 ; (6) +;; +;; Call trampoline (87 bytes, 57 cycles): +;; +__call_a32: + pshx ; (4) + psha ; (2) + ;; <Read current page in A> ; (3) ldaa _current_page + psha ; (2) + ;; <Set current page from B> ; (4) staa _current_page + tsx ; (3) + ldab 6,x ; (4) Restore function parameter + ldaa 5,x ; (4) Move PC return at good place + staa 6,x ; (4) + ldaa 4,x ; (4) + staa 5,x ; (4) + pula ; (3) + staa 4,x ; (4) + pula ; (3) + pulx ; (5) + jmp 0,y ; (4) +#endif +#endif + +#ifdef L_return_far +#ifdef mc68hc11 + .sect .tramp,"ax",@progbits + .globl __return_void + .globl __return_16 + .globl __return_32 + +__return_void: + ;; pulb + ;; <Set current page from B> (Board specific) + ;; rts +__return_16: + ;; xgdx + ;; pulb + ;; <Set current page from B> (Board specific) + ;; xgdx + ;; rts +__return_32: + ;; xgdy + ;; pulb + ;; <Set current page from B> (Board specific) + ;; xgdy + ;; rts + ins + rts +#endif +#endif +.Lend: +;----------------------------------------- +; end required gcclib code +;----------------------------------------- |