summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sux.h22
-rw-r--r--test/rotate.s61
2 files changed, 77 insertions, 6 deletions
diff --git a/sux.h b/sux.h
index 9004c74..744a2cc 100644
--- a/sux.h
+++ b/sux.h
@@ -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