]> git.sur5r.net Git - cc65/commitdiff
New code for the shift functions
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 5 Jul 2004 22:24:06 +0000 (22:24 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 5 Jul 2004 22:24:06 +0000 (22:24 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@3143 b7a2c559-68d2-44c3-8de9-860c34a00d81

libsrc/runtime/Makefile
libsrc/runtime/asr.s [new file with mode: 0644]
libsrc/runtime/lasr.s [new file with mode: 0644]
libsrc/runtime/lshl.s
libsrc/runtime/lshr.s
libsrc/runtime/shl.s
libsrc/runtime/shr.s

index b42a5bba9e35c616352ae3b7c331f0b40dcb0373..f394f6ae31950883c7c6e3437346d4d91077bf6a 100644 (file)
@@ -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 (file)
index 0000000..8a3565e
--- /dev/null
@@ -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 (file)
index 0000000..c96f1e1
--- /dev/null
@@ -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
+
index d481fa69c2befa132a456fb82299afc44e6547e8..3c4e7080b91170b9a1177a8a0bf3d720a0e03885 100644 (file)
@@ -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
 
 
index 2e3e051012cf576876cf52fc358554f9a8f28e59..9c2a6e3a882a17790e187ab52302fdff1661f05f 100644 (file)
 ;
-; 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
 
 
 
index 73f48314295a3f9a32482dc580c3c4747dec406d..1963abbdc8a87bec390bf5ae955e28f19b7a5fae 100644 (file)
@@ -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
 
index 2b51500bcc4fa2794a0eec8da8eb8c7a95f2d83a..3b505e74dbe6002102c404a01302e0c5910a30e3 100644 (file)
 ;
-; 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