📄 larith.asm
字号:
bne LoopReturn: rtsReturn_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_posNumerator_neg_denominator_neg: comb ; X = -X coma addd #1 xgdx idiv coma comb xgdx ; Remainder <= 0 and result >= 0 inx rtsNumerator_pos_denominator_pos: xgdx idiv xgdx ; Both values are >= 0 rts Numerator_pos: xgdx tsta bpl Numerator_pos_denominator_posNumerator_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 rtsB_neg: negb bra A_or_B_negA_neg: nega tstb bmi AB_negA_or_B_neg: mul coma comb addd #1 rtsAB_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 inyN: 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 inxRet: 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#elseB_low = ARG(8)B_high = ARG(6)A_low = 0A_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,yA_low_zero: ; See A_low_zero_non_optimized below xgdxReturn: 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 ___mulhi3Zero1: xgdxZero2: 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 DoneLoop: movb 1,x+,1,y+ dbne d,Loop#else ldx #__data_image ldy #__data_section_start bra Start_mapLoop: ldaa 0,x staa 0,y inx inyStart_map: cpx #__data_image_end blo Loop#endifDone:#endif#ifdef L_init_bss .sect .install2,"ax",@progbits .globl __init_bss_section__init_bss_section: ldd #__bss_size beq Done ldx #__bss_startLoop:#ifdef mc68hc12 clr 1,x+ dbne d,Loop#else clr 0,x inx subd #1 bne Loop#endifDone:#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__-2ctors_loop: cpx #__CTOR_LIST__ blo ctors_done pshx ldx 0,x jsr 0,x pulx dex dex bra ctors_loopctors_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_loopdtors_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;-----------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -