summaryrefslogtreecommitdiff
path: root/sux.c
blob: 43699d385dc52ed8b868f7f759a83865a6421ac2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include "opcode.h"
#include <stdint.h>
uint64_t a; /* Accumulator. */
uint64_t y; /* Y index. */
uint64_t x; /* X index. */
uint64_t ps; /* Processor status. */

uint64_t alu(uint8_t opcode, uint64_t value) {
	uint64_t sum;
	uint8_t carry, vf;
	switch(opcode) {
		/* Add with carry. */
		case ADC:
			sum = a+value+carry;
			vf = (~(a^value) & (a^sum & 0x80));
			carry = (sum < value) ? 1 : 0;
			a |= sum;
			break;
		/* Subtract with carry. */
		case SBC:
			sum = a-value-!carry;
			vf = (a^value) & (a^sum) & 0x80;
			carry = (sum > value) ? 1 : 0;
			a |= sum;
			break;
		/* Multiply with accumulator. */
		case MUL:
			sum = a*value+carry;
			vf = (~(a^value) & (a^sum & 0x80));
			carry = (sum < value) ? 1 : 0;
			a |= sum;
			break;
		/* Divide with accumulator. */
		case DIV:
			sum = a/value-!carry;
			vf = (a^value) & (a^sum) & 0x80;
			carry = (sum > value) ? 1 : 0;
			a |= sum;
			break;
		/* Bitwise AND. */
		case AND:
		case AAY:
		case AAX:
			a &= value;
			if (opcode == AAY)
				y &= value;
			if (opcode == AAX)
				x &= value;
			break;
		case ANY:
			y &= value;
			break;
		case ANX:
			x &= value;
			break;
		/* Bitwise OR. */
		case ORA:
		case OAY:
		case OAX:
			a |= value;
			if (opcode == OAY)
				y |= value;
			if (opcode == OAX)
				x |= value;
			break;
		case ORY:
			y |= value;
			break;
		case ORX:
			x |= value;
			break;
		/* Bitwise Exclusive OR. */
		case XOR:
		case XAY:
		case XAX:
			a ^= value;
			if (opcode == XAY)
				y ^= value;
			if (opcode == XAX)
				x ^= value;
			break;
		case XRY:
			y ^= value;
			break;
		case XRX:
			x ^= value;
			break;
		/* Shift accumulator left. */
		case SLA:
			a <<= value;
			break;
		/* Shift accumulator right. */
		case SRA:
			a >>= value;
			break;
		/* Rotate accumulator left. */
		case ROL:
			(a << value) | (a >> (64-value));
			break;
		/* Rotate accumulator right. */
		case ROR:
			(a >> value) | (a << (64-value));
			break;
	}
}