• API
• FAQ
• Tools
• Archive
SHARE
TWEET

# Untitled

a guest Mar 21st, 2017 11 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
1. #include <iostream>
2. #include <iomanip>
3. #include <cstdint>
4. #include <sstream>
5. using namespace std;
6.
7. struct Context {
8.     uint8_t X:1;
9.     uint8_t N:1;
10.     uint8_t Z:1;
11.     uint8_t V:1;
12.     uint8_t C:1;
13.     Context(uint8_t _X, uint8_t _Z)
14.     : X(_X != 0), N(0), Z(_Z != 0), V(0), C(_X != 0) {
15.     }
16.     bool operator==(const Context& other) {
17.         return X == other.X &&
18.                N == other.N &&
19.                Z == other.Z &&
20.                V == other.V &&
21.                C == other.C;
22.     }
23.     bool operator!=(const Context& other) {
24.         return !(*this == other);
25.     }
26. };
27.
28. ostream& operator<<(ostream& out, const Context& ctx) {
29.     out << (ctx.X ? 'X' : 'x')
30.         << (ctx.N ? 'N' : 'n')
31.         << (ctx.Z ? 'Z' : 'z')
32.         << (ctx.V ? 'V' : 'v')
33.         << (ctx.C ? 'C' : 'c');
34.     return out;
35. }
36.
37. uint8_t abcd(Context *ctx, uint8_t xx, uint8_t yy) {
38.     uint8_t ss = xx + yy + ctx->X;
39.     // Normal carry computation for addition:
40.     // (sm & dm) | (~rm & dm) | (sm & ~rm)
41.     uint8_t bc = ((xx & yy) | (~ss & xx) | (~ss & yy)) & 0x88;
42.     // Compute if we have a decimal carry in both nibbles:
43.     uint8_t dc = (((ss + 0x66) ^ ss) & 0x110) >> 1;
44.     uint8_t corf = (bc | dc) - ((bc | dc) >> 2);
45.     uint8_t rr = ss + corf;
46.     // Compute flags.
47.     // Carry has two parts: normal carry for addition
48.     // (computed above) OR'ed with normal carry for
50.     // (sm & dm) | (~rm & dm) | (sm & ~rm)
51.     // but simplified because sm = 0 and ~sm = 1 for corf:
52.     ctx->X = ctx->C = (bc | (ss & ~rr)) >> 7;
53.     // Normal overflow computation for addition with corf:
54.     // (sm & dm & ~rm) | (~sm & ~dm & rm)
55.     // but simplified because sm = 0 and ~sm = 1 for corf:
56.     ctx->V = (~ss & rr) >> 7;
57.     // Accumulate zero flag:
58.     ctx->Z = ctx->Z & (rr == 0);
59.     ctx->N = rr >> 7;
60.     return rr;
61. }
62.
63. uint8_t sbcd(Context *ctx, uint8_t xx, uint8_t yy) {
64.     uint8_t dd = xx - yy - ctx->X;
65.     // Normal carry computation for subtraction:
66.     // (sm & ~dm) | (rm & ~dm) | (sm & rm)
67.     uint8_t bc = ((~xx & yy) | (dd & ~xx) | (dd & yy)) & 0x88;
68.     uint8_t corf = bc - (bc >> 2);
69.     uint8_t rr = dd - corf;
70.     // Compute flags.
71.     // Carry has two parts: normal carry for subtraction
72.     // (computed above) OR'ed with normal carry for
73.     // subtraction with corf:
74.     // (sm & ~dm) | (rm & ~dm) | (sm & rm)
75.     // but simplified because sm = 0 and ~sm = 1 for corf:
76.     ctx->X = ctx->C = (bc | (~dd & rr)) >> 7;
77.     // Normal overflow computation for subtraction with corf:
78.     // (~sm & dm & ~rm) | (sm & ~dm & rm)
79.     // but simplified because sm = 0 and ~sm = 1 for corf:
80.     ctx->V = (dd & ~rr) >> 7;
81.     // Accumulate zero flag:
82.     ctx->Z = ctx->Z & (rr == 0);
83.     ctx->N = rr >> 7;
84.     return rr;
85. }
86.
87.
88. uint8_t abcd_emu(Context *ctx, uint8_t xx, uint8_t yy) {
89.     uint8_t n1, n2, res, sum;
90.
91.     sum = xx + yy + ctx->X;
92.     n1 = (xx&0xF) + (yy&0xF) + (ctx->X);
93.     if (n1 > 9) {
94.         n1 += 6;
95.     }
96.
97.     n2 = (xx>>4) + (yy>>4) + (n1>>4);
98.
99.     if (n2 > 9) {
100.         ctx->X = ctx->C = 1; // X & C flags
101.         n2 += 6;
102.     } else {
103.         ctx->X = ctx->C = 0; // X & C flags
104.     }
105.     res = ((n1&0xF) + ((uint16_t)n2<<4));
106.     ctx->Z = (res & 0xff) ? 0 : ctx->Z; // Z flag
107.     ctx->N = (res & 0x80) ? 1 : 0; // N flag
108.     ctx->V = ((res & 0x80) != 0 && (sum & 0x80) == 0) ? 1 : 0; // V flag
109.     return res;
110. }
111.
112. uint8_t sbcd_emu(Context *ctx, uint8_t xx, uint8_t yy) {
113.     uint8_t c = (xx&0xF) - (yy&0xF) - (ctx->X);
114.     uint16_t res = ((uint16_t)xx) - yy - (ctx->X);
115.     uint8_t corf = 0;
116.     if ((res & 0xF) >= 0xA || c > 0) {
117.         corf = 0x6;
118.     }
119.     if ((res & 0xF0) >= 0xA0 || res > 0xFF) {
120.         corf += 0x60;
121.     }
122.     ctx->X = ctx->C = (res > 0xff) ? 1 : 0; // X & C flags
123.     ctx->Z = (res & 0xff) ? 0 : ctx->Z; // Z flag
124.     ctx->N = (res & 0x80) ? 1 : 0; // N flag
125.     ctx->V = ((res & 0xff) + corf > 0xff) ? 1 : 0; // V flag
126.     return res & 0xFF;
127. }
128.
129. int main() {
130.     stringstream sout;
131.     cout << setfill('0') << uppercase << hex;
132.     sout << setfill('0') << uppercase << hex;
133.     uint32_t results, flags;
134.     results = 0;
135.     flags = 0;
136.     cout << "\t\terrors value  flags\n";
137.     for (int ii = 0; ii < 256; ii++) {
138.         for (int jj = 0; jj < 256; jj++) {
139.             for (int cin = 0; cin < 2; cin++) {
140.                 for (int zin = 0; zin < 2; zin++) {
141.                     Context ctx1(cin, zin), ctx2(cin, zin);
142.                     uint8_t val1 = abcd(&ctx1, jj, ii);
143.                     uint8_t val2 = abcd_emu(&ctx2, jj, ii);
144.                     if (val1 != val2 || ctx1 != ctx2) {
145.                         if (val1 != val2) {
146.                             results++;
147.                         }
148.                         if (ctx1 != ctx2) {
149.                             flags++;
150.                         }
151.                         sout << Context(cin, zin) << " abcd "
152.                              << '\$' << setw(2) << +jj << ','
153.                              << '\$' << setw(2) << +ii << '='
154.                              << '\$' << setw(2) << +val2 << ' '
155.                              << ctx2 << " ("
156.                              << '\$' << setw(2) << +val1 << ' '
157.                              << ctx1 << ")\n";
158.                     }
159.                 }
160.             }
161.         }
162.     }
163.     cout << "\t\tabcd  \$" << setw(5) << results
164.          << " \$" << setw(5) << flags << '\n';
165.     results = 0;
166.     flags = 0;
167.     for (int ii = 0; ii < 256; ii++) {
168.         for (int jj = 0; jj < 256; jj++) {
169.             for (int cin = 0; cin < 2; cin++) {
170.                 for (int zin = 0; zin < 2; zin++) {
171.                     Context ctx1(cin, zin), ctx2(cin, zin);
172.                     uint8_t val1 = sbcd(&ctx1, jj, ii);
173.                     uint8_t val2 = sbcd_emu(&ctx2, jj, ii);
174.                     if (val1 != val2 || ctx1 != ctx2) {
175.                         if (val1 != val2) {
176.                             results++;
177.                         }
178.                         if (ctx1 != ctx2) {
179.                             flags++;
180.                         }
181.                         sout << Context(cin, zin) << " sbcd "
182.                              << '\$' << setw(2) << +jj << ','
183.                              << '\$' << setw(2) << +ii << '='
184.                              << '\$' << setw(2) << +val2 << ' '
185.                              << ctx2 << " ("
186.                              << '\$' << setw(2) << +val1 << ' '
187.                              << ctx1 << ")\n";
188.                     }
189.                 }
190.             }
191.         }
192.     }
193.     cout << "\t\tsbcd  \$" << setw(5) << results
194.          << " \$" << setw(5) << flags << '\n';
195.     cout << sout.rdbuf();
196. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy.
Not a member of Pastebin yet?