From: cuz Date: Mon, 5 Jul 2004 22:24:06 +0000 (+0000) Subject: New code for the shift functions X-Git-Tag: V2.12.0~689 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=c122f18605d908139064b2cf99c1bf06d3a9d2fc;p=cc65 New code for the shift functions git-svn-id: svn://svn.cc65.org/cc65/trunk@3143 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- diff --git a/libsrc/runtime/Makefile b/libsrc/runtime/Makefile index b42a5bba9..f394f6ae3 100644 --- a/libsrc/runtime/Makefile +++ b/libsrc/runtime/Makefile @@ -29,6 +29,7 @@ OBJS = add.o \ asleax2.o \ asleax3.o \ asleax4.o \ + asr.o \ asrax1.o \ asrax2.o \ asrax3.o \ diff --git a/libsrc/runtime/asr.s b/libsrc/runtime/asr.s new file mode 100644 index 000000000..8a3565e7d --- /dev/null +++ b/libsrc/runtime/asr.s @@ -0,0 +1,60 @@ +; +; Ullrich von Bassewitz, 2004-06-30 +; +; CC65 runtime: right shift support for ints +; +; Note: The standard declares a shift count that is negative or >= the +; bitcount of the shifted type for undefined behaviour. +; +; Note^2: The compiler knowns about the register/zero page usage of this +; function, so you need to change the compiler source if you change it! +; + + + .export tosasrax + .import popax + .importzp tmp1 + +tosasrax: + and #$0F ; Bring the shift count into a valid range + sta tmp1 ; Save it + + jsr popax ; Get the left hand operand + + ldy tmp1 ; Get shift count + beq L9 ; Bail out if shift count zero + + cpy #8 ; Shift count 8 or greater? + bcc L1 ; Jump if not + +; Shift count is greater 8. The carry is set when we enter here. + + tya + sbc #8 + tay ; Adjust shift count + txa + ldx #$00 ; Shift by 8 bits + cmp #$00 ; Test sign bit + bpl L1 + dex ; Make X the correct sign extended value + +; Save the high byte so we can shift it + +L1: stx tmp1 ; Save high byte + jmp L3 + +; Do the actual shift + +L2: cpx #$80 ; Copy bit 15 into the carry + ror tmp1 + ror a +L3: dey + bpl L2 + +; Done with shift + + ldx tmp1 +L9: rts + + + diff --git a/libsrc/runtime/lasr.s b/libsrc/runtime/lasr.s new file mode 100644 index 000000000..c96f1e1f5 --- /dev/null +++ b/libsrc/runtime/lasr.s @@ -0,0 +1,44 @@ +; +; Ullrich von Bassewitz, 2004-06-30 +; +; CC65 runtime: right shift support for longs +; +; Note: The standard declares a shift count that is negative or >= the +; bitcount of the shifted type for undefined behaviour. +; +; Note^2: The compiler knowns about the register/zero page usage of this +; function, so you need to change the compiler source if you change it! +; + + + .export tosasreax + .import popeax + .importzp sreg, tmp1 + + +tosasreax: + and #$1F ; Bring the shift count into a valid range + sta tmp1 ; Save it + + jsr popeax ; Get the left hand operand + + ldy tmp1 ; Get shift count + beq L9 ; Bail out if shift count zero + stx tmp1 ; Save byte 1 + ldx sreg+1 ; Load byte 3 + +; Do the actual shift. Faster solutions are possible but need a lot more code. + +L2: cpx #$80 ; Copy bit 31 into the carry + ror sreg+1 + ror sreg + ror tmp1 + ror a + dey + bne L2 + +; Shift done + + ldx tmp1 +L9: rts + diff --git a/libsrc/runtime/lshl.s b/libsrc/runtime/lshl.s index d481fa69c..3c4e7080b 100644 --- a/libsrc/runtime/lshl.s +++ b/libsrc/runtime/lshl.s @@ -1,95 +1,44 @@ ; -; Ullrich von Bassewitz, 20.09.1998 +; Ullrich von Bassewitz, 2004-06-30 ; -; CC65 runtime: left shift support for longs +; CC65 runtime: left shift support for long and unsigned long +; +; Note: The standard declares a shift count that is negative or >= the +; bitcount of the shifted type for undefined behaviour. +; +; Note^2: The compiler knowns about the register/zero page usage of this +; function, so you need to change the compiler source if you change it! ; .export tosasleax, tosshleax - .import addysp1 - .importzp sp, sreg, ptr1, ptr2 + .import popeax + .importzp sreg, tmp1 tosshleax: tosasleax: + and #$1F ; Bring the shift count into a valid range + sta tmp1 ; Save it -; Get the lhs from stack into ptr1/ptr2 - - pha - ldy #0 - lda (sp),y - sta ptr1 - iny - lda (sp),y - sta ptr1+1 - iny - lda (sp),y - sta ptr2 - iny - lda (sp),y - sta ptr2+1 - pla - jsr addysp1 - -; Check for shift overflow or zero shift - - tay ; Low byte of shift count into y - txa ; Get byte 2 - ora sreg - ora sreg+1 ; Check high 24 bit - bne @L6 ; Shift count too large - cpy #32 - bcs @L6 - - cpy #0 ; Shift count zero? - beq @L5 - -; We must shift. Shift by multiples of eight if possible - - tya -@L1: cmp #8 - bcc @L3 - sbc #8 - ldx ptr2 - stx ptr2+1 - ldx ptr1+1 - stx ptr2 - ldx ptr1 - stx ptr1+1 - ldx #0 - stx ptr1 - beq @L1 - -; Shift count is now less than eight. Do a real shift. - -@L3: tay ; Shift count to Y - lda ptr1 ; Get one byte into A for speed - cpy #0 - beq @L4a ; Jump if done -@L4: asl a - rol ptr1+1 - rol ptr2 - rol ptr2+1 - dey - bne @L4 - -; Put the result in place + jsr popeax ; Get the left hand operand -@L4a: ldx ptr2 - stx sreg - ldx ptr2+1 - stx sreg+1 - ldx ptr1+1 -@L5: rts + ldy tmp1 ; Get shift count + beq L9 ; Bail out if shift count zero + stx tmp1 ; Save byte 1 -; Jump here if shift count overflow +; Do the actual shift. Faster solutions are possible but need a lot more code. -@L6: lda #0 - sta sreg+1 - sta sreg - tax - rts +L2: asl a + rol tmp1 + rol sreg + rol sreg+1 + dey + bne L2 +; Shift done + ldx tmp1 +L9: rts diff --git a/libsrc/runtime/lshr.s b/libsrc/runtime/lshr.s index 2e3e05101..9c2a6e3a8 100644 --- a/libsrc/runtime/lshr.s +++ b/libsrc/runtime/lshr.s @@ -1,181 +1,44 @@ ; -; Ullrich von Bassewitz, 20.09.1998 +; Ullrich von Bassewitz, 2004-06-30 ; -; CC65 runtime: right shift support for longs +; CC65 runtime: right shift support for unsigned longs ; +; Note: The standard declares a shift count that is negative or >= the +; bitcount of the shifted type for undefined behaviour. +; +; Note^2: The compiler knowns about the register/zero page usage of this +; function, so you need to change the compiler source if you change it! +; + + + .export tosshreax + .import popeax + .importzp sreg, tmp1 + + +tosshreax: + and #$1F ; Bring the shift count into a valid range + sta tmp1 ; Save it + + jsr popeax ; Get the left hand operand + + ldy tmp1 ; Get shift count + beq L9 ; Bail out if shift count zero + stx tmp1 ; Save byte 1 + +; Do the actual shift. Faster solutions are possible but need a lot more code. +L2: lsr sreg+1 + ror sreg + ror tmp1 + ror a + dey + bne L2 - .export tosasreax, tosshreax - .import addysp1 - .importzp sp, sreg, ptr1, ptr2 - -; -------------------------------------------------------------------- -; signed shift - -.proc tosasreax - - jsr getlhs ; Get the lhs from the stack - - jsr checkovf ; Check for overflow - bcs L6 ; Jump if shift count too large - - cpy #0 ; Shift count zero? - beq L5 - -; We must shift. Shift by multiples of eight if possible - - tya -L1: cmp #8 - bcc L3 - sbc #8 - ldx ptr1+1 - stx ptr1 - ldx ptr2 - stx ptr1+1 - ldy #0 - ldx ptr2+1 - stx ptr2 - bpl L2 - dey ; Get sign -L2: sty ptr2+1 - jmp L1 - -; Shift count is now less than eight. Do a real shift. - -L3: tay ; Shift count to Y - lda ptr2+1 ; Get one byte into A for speed - cpy #0 - beq L4a ; Jump if done -L4: cmp #$80 ; Get sign bit into C - ror a - ror ptr2 - ror ptr1+1 - ror ptr1 - dey - bne L4 - -; Put the result in place - -L4a: sta sreg+1 - lda ptr2 - sta sreg - ldx ptr1+1 - lda ptr1 -L5: rts - -; Jump here if shift count overflow - -L6: ldx #0 - lda ptr2+1 ; Check sign - bpl L7 - dex -L7: stx sreg+1 - stx sreg - txa - rts - -.endproc - -; -------------------------------------------------------------------- -; unsigned shift - -.proc tosshreax - - jsr getlhs ; Get the lhs from the stack - - jsr checkovf ; Check for overflow - bcs L6 ; Jump if shift count too large - - cpy #0 ; Shift count zero? - beq L5 - -; We must shift. Shift by multiples of eight if possible - - tya -L1: cmp #8 - bcc L3 - sbc #8 - ldx ptr1+1 - stx ptr1 - ldx ptr2 - stx ptr1+1 - ldx ptr2+1 - stx ptr2 - ldx #0 - stx ptr2+1 - beq L1 - -; Shift count is now less than eight. Do a real shift. - -L3: tay ; Shift count to Y - lda ptr2+1 ; Get one byte into A for speed - cpy #0 - beq L4a ; Jump if done -L4: lsr a - ror ptr2 - ror ptr1+1 - ror ptr1 - dey - bne L4 - -; Put the result in place - -L4a: sta sreg+1 - lda ptr2 - sta sreg - ldx ptr1+1 - lda ptr1 -L5: rts - -; Jump here if shift count overflow - -L6: lda #0 - sta sreg+1 - sta sreg - tax - rts - -.endproc - -; -------------------------------------------------------------------- -; Helpers - -.proc getlhs ; Get the lhs from stack into ptr1/ptr2 - - pha - ldy #0 - lda (sp),y - sta ptr1 - iny - lda (sp),y - sta ptr1+1 - iny - lda (sp),y - sta ptr2 - iny - lda (sp),y - sta ptr2+1 - pla - jmp addysp1 - -.endproc - - -.proc checkovf ; Check for shift overflow - - tay ; Low byte of shift count into y - txa ; Get byte 2 - ora sreg - ora sreg+1 ; Check high 24 bit - bne TooLarge ; Shift count too large - cpy #32 - bcc Ok -TooLarge: - sec -Ok: rts - -.endproc +; Shift done + ldx tmp1 +L9: rts diff --git a/libsrc/runtime/shl.s b/libsrc/runtime/shl.s index 73f483142..1963abbdc 100644 --- a/libsrc/runtime/shl.s +++ b/libsrc/runtime/shl.s @@ -1,69 +1,58 @@ ; -; Ullrich von Bassewitz, 05.08.1998 +; Ullrich von Bassewitz, 1998-08-05, 2004-06-25 ; -; CC65 runtime: left shift support for ints +; CC65 runtime: left shift support for ints and unsigneds ; +; Note: The standard declares a shift count that is negative or >= the +; bitcount of the shifted type for undefined behaviour. +; +; Note^2: The compiler knowns about the register/zero page usage of this +; function, so you need to change the compiler source if you change it! +; + - .export tosasla0, tosaslax, tosshla0, tosshlax - .import popsreg, return0 - .importzp sreg + .export tosaslax, tosshlax + .import popax + .importzp tmp1 -tosshla0: -tosasla0: - ldx #0 tosshlax: tosaslax: - jsr popsreg ; get TOS into sreg - cpx #0 - bne TooLarge - cmp #16 - bcs TooLarge + and #$0F ; Bring the shift count into a valid range + sta tmp1 ; Save it - cmp #8 ; Shift count greater 8? - beq L3 ; Jump if exactly 8 - bcc L1 ; Jump if no + jsr popax ; Get the left hand operand -; Shift count is greater 8. Do the first 8 bits the fast way + ldy tmp1 ; Get shift count + beq L9 ; Bail out if shift count zero - ldy sreg - sty sreg+1 - stx sreg ; Low byte = 0 - sec - sbc #8 + cpy #8 ; Shift count 8 or greater? + bcc L3 ; Jump if not -; Shift count less than 8 if we come here +; Shift count is greater 7. The carry is set when we enter here. -L1: tay ; Shift count --> Y - beq Zero ; Done if shift count zero + tax + tya + sbc #8 + tay + txa + jmp L2 +L1: asl a +L2: dey + bpl L1 + tax + lda #$00 + rts - lda sreg ; get low byte for faster shift +; Shift count is less than 8. -; Do the actual shift - -L2: asl a - rol sreg+1 - dey - bne L2 +L3: stx tmp1 ; Save high byte of lhs +L4: asl a + rol tmp1 + dey + bne L4 ; Done with shift - ldx sreg+1 - rts - -; Shift count == 8 - -L3: txa ; X == 0, now A == 0 - ldx sreg - rts - -; Shift count was zero - -Zero: lda sreg - ldx sreg+1 - rts - -; Shift count too large, result is zero - -TooLarge: - jmp return0 + ldx tmp1 +L9: rts diff --git a/libsrc/runtime/shr.s b/libsrc/runtime/shr.s index 2b51500bc..3b505e74d 100644 --- a/libsrc/runtime/shr.s +++ b/libsrc/runtime/shr.s @@ -1,127 +1,55 @@ ; -; Ullrich von Bassewitz, 05.08.1998 +; Ullrich von Bassewitz, 2004-06-30 ; -; CC65 runtime: right shift support for ints +; CC65 runtime: right shift support for unsigneds +; +; Note: The standard declares a shift count that is negative or >= the +; bitcount of the shifted type for undefined behaviour. +; +; Note^2: The compiler knowns about the register/zero page usage of this +; function, so you need to change the compiler source if you change it! ; -; -------------------------------------------------------------------- -; signed shift - - .export tosasra0, tosasrax - .import popsreg, return0 - .importzp sreg - -tosasra0: - ldx #0 -tosasrax: - jsr popsreg ; get TOS into sreg - cpx #0 - bne TooLarge - cmp #16 - bcs TooLarge - - cmp #8 ; Shift count greater 8? - beq L4 ; Jump if exactly 8 - bcc L2 ; Jump if no - -; Shift count is greater 8. Do the first 8 bits the fast way - - ldy #0 - ldx sreg+1 - stx sreg - bpl L1 - dey ; Create correct sign bits -L1: sty sreg+1 - sec - sbc #8 - -; Shift count less than 8 if we come here - -L2: tay ; Shift count --> Y - beq Zero ; Done if shift count zero - - lda sreg ; get low byte for faster shift - ldx sreg+1 ; get high byte - -; Do the actual shift - -L3: cpx #$80 ; get bit 7 into carry - ror sreg+1 - ror a - dey - bne L3 - -; Done with shift - - ldx sreg+1 - rts - -; Shift count == 8 - -L4: lda sreg+1 ; X is zero - bpl *+3 - dex ; X == 0xFF - rts - -; Shift count was zero - -Zero: lda sreg - ldx sreg+1 - rts - -; Shift count too large, result is zero - -TooLarge: - jmp return0 - - -; -------------------------------------------------------------------- -; unsigned shift - - .export tosshra0, tosshrax + .export tosshrax + .import popax + .importzp tmp1 -tosshra0: - ldx #0 tosshrax: - jsr popsreg ; get TOS into sreg - cpx #0 - bne TooLarge - cmp #16 - bcs TooLarge + and #$0F ; Bring the shift count into a valid range + sta tmp1 ; Save it - cmp #8 ; Shift count greater 8? - beq L8 ; Jump if exactly 8 - bcc L6 ; Jump if no + jsr popax ; Get the left hand operand -; Shift count is greater 8. Do the first 8 bits the fast way + ldy tmp1 ; Get shift count + beq L9 ; Bail out if shift count zero - sbc #8 ; Carry already set - ldy sreg+1 - sty sreg - stx sreg+1 ; High byte = 0 + cpy #8 ; Shift count 8 or greater? + bcc L3 ; Jump if not -; Shift count less than 8 if we come here +; Shift count is greater 7. The carry is set when we enter here. -L6: tay ; Shift count --> Y - beq Zero ; Done if shift count zero + tya + sbc #8 + tay ; Adjust shift count + txa + ldx #$00 ; Shift by 8 bits + beq L2 ; Branch always +L1: lsr a +L2: dey + bpl L1 + rts - lda sreg ; get low byte for faster shift +; Shift count is less than 8. Do the actual shift. -; Do the actual shift - -L7: lsr sreg+1 - ror a - dey - bne L7 +L3: stx tmp1 ; Save high byte of lhs +L4: lsr tmp1 + ror a + dey + bne L4 ; Done with shift - ldx sreg+1 - rts - -; Shift count == 8 - -L8: lda sreg+1 ; X is zero - rts + ldx tmp1 +L9: rts