diff options
-rw-r--r-- | sux.h | 22 | ||||
-rw-r--r-- | test/rotate.s | 61 |
2 files changed, 77 insertions, 6 deletions
@@ -351,20 +351,30 @@ static inline uint64_t asr(struct sux *cpu, uint64_t reg, uint64_t value, uint8_ } static inline uint64_t rol(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) { - uint64_t sum = reg << value; - sum |= getflag(C); + uint64_t sum; + uint64_t c = getflag(C); + switch (value & 0x3F) { + case 0 : return reg; + case 1 : sum = (reg << 1) | (c & 1); break; + default: sum = (reg << value) | (c << (value-1)) | (reg >> (65-value)); break; + } setflag(sum == 0, Z); setflag(sum >> 63, N); - setflag(reg >> (uint64_t)(64-value), C); + setflag((reg >> (64-value)) & 1, C); return sum; } static inline uint64_t ror(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) { - uint64_t sum = reg >> value; - sum |= (uint64_t)getflag(C) << (uint64_t)(64-value); + uint64_t sum; + uint64_t c = getflag(C); + switch (value & 0x3F) { + case 0 : return reg; + case 1 : sum = (reg >> 1) | (c << 63); break; + default: sum = (reg >> value) | (c << (64-value)) | (reg << (65-value)); break; + } setflag(sum == 0, Z); setflag(sum >> 63, N); - setflag(reg & 1, C); + setflag((reg >> (value-1)) & 1, C); return sum; } diff --git a/test/rotate.s b/test/rotate.s new file mode 100644 index 0000000..6115e94 --- /dev/null +++ b/test/rotate.s @@ -0,0 +1,61 @@ +; Test rol, and ror. + +.org 0 +count: + .res 1 +tmp: + .res 8 + +.org $8000 +reset: + cps ; + ldx.w #$FFFF ; + txs ; + and #0 ; + tax ; + tab ; + tay ; + + +start: + ldb #8 ; Set the loop count to 8. +@loop: + lda #$AA ; Set A to magic byte. + deb ; Decrement the loop count. + beq @savemagic ; Save the magic number, if the loop count is zero. + lsl #8 ; Shift the magic number by one byte, if the loop count is non zero. + bra @loop ; Keep looping. +@savemagic: + sta.q tmp ; Save the magic number. + + +rotate: + ldb #0 ; Reset B. +@loop: + and #0 ; Reset A. + lda #$40 ; Set the shift count to 64. + sta count ; + lda.q tmp ; Get our magic number. + inb ; Increment our shift amount by one. + cpb #$40 ; Is the shift amount greater than, or equal to 64? + bcs rotate ; Yes, so reset B. +@rotl: + rol b ; Rotate the magic number left by our shift amount. + dec count ; Decrement the shift count. + beq @rotr ; Start rotating right, if the shift count is zero. + bra @rotl ; Keep looping, if the shift count is non zero. +@rotr: + and #0 ; Reset A. + lda #$40 ; Set the shift count to 64. + sta count ; + lda.q tmp ; Get our magic number. +@rotr2: + ror b ; Rotate the magic number right by our shift amount. + dec count ; Decrement the shift count. + beq @loop ; Increment the shift amount, if the shift count is zero. + bra @rotr2 ; Keep looping, if the shift count is non zero. + +.org $FFC0 +.qword reset +a +d |