Advertisement
Guest User

Untitled

a guest
Mar 21st, 2017
149
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.54 KB | None | 0 0
  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
  49.     // addition with corf:
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement