;
-; 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