root/src/dps8/dps8_utils.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dump_flags
  2. dps8_strupr
  3. get_iwb_info
  4. disassemble
  5. get_mod_string
  6. Add36b
  7. Sub36b
  8. Add18b
  9. Sub18b
  10. Add72b
  11. Sub72b
  12. compl36
  13. compl18
  14. copyBytes
  15. copyChars
  16. putByte
  17. putChar
  18. convert_to_word72
  19. convert_to_word36
  20. cmp36
  21. cmp18
  22. cmp36wl
  23. cmp72
  24. strlower
  25. strmask
  26. rtrim
  27. ltrim
  28. trim
  29. stripquotes
  30. cfg_parse
  31. cfg_parse_done
  32. strdupesc
  33. extrASCII36
  34. extr36
  35. putASCII36
  36. put36
  37. extractASCII36FromBuffer
  38. extractWord36FromBuffer
  39. insertASCII36toBuffer
  40. insertWord36toBuffer
  41. print_uint128o_r
  42. print_int128o
  43. print_uint128_r
  44. print_int128
  45. timespec_diff

   1 /*
   2  * vim: filetype=c:tabstop=4:ai:expandtab
   3  * SPDX-License-Identifier: ICU
   4  * scspell-id: 1414c8ee-f62f-11ec-885a-80ee73e9b8e7
   5  *
   6  * ---------------------------------------------------------------------------
   7  *
   8  * Copyright (c) 2007-2013 Michael Mondy
   9  * Copyright (c) 2012-2016 Harry Reed
  10  * Copyright (c) 2013-2016 Charles Anthony
  11  * Copyright (c) 2021-2022 The DPS8M Development Team
  12  *
  13  * All rights reserved.
  14  *
  15  * This software is made available under the terms of the ICU
  16  * License, version 1.8.1 or later.  For more details, see the
  17  * LICENSE.md file at the top-level directory of this distribution.
  18  *
  19  * ---------------------------------------------------------------------------
  20  */
  21 
  22 #include <stdio.h>
  23 #include <string.h>
  24 #include <signal.h>
  25 #include <ctype.h>
  26 
  27 #include "dps8.h"
  28 #include "dps8_sys.h"
  29 #include "dps8_faults.h"
  30 #include "dps8_scu.h"
  31 #include "dps8_iom.h"
  32 #include "dps8_cable.h"
  33 #include "dps8_cpu.h"
  34 #include "dps8_ins.h"
  35 #include "dps8_opcodetable.h"
  36 #include "dps8_utils.h"
  37 
  38 #define DBG_CTR 1
  39 
  40 #ifdef TESTING
  41 # undef FREE
  42 # define FREE(p) free(p)
  43 #endif /* ifdef TESTING */
  44 
  45 /*
  46  * misc utility routines used by simulator
  47  */
  48 
  49 char * dump_flags(char * buffer, word18 flags)
     /* [previous][next][first][last][top][bottom][index][help] */
  50 {
  51     sprintf(buffer, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
  52             flags & I_HEX   ? "Hex "   : "",  // L68 will never have I_HEX set, so no need to DPS8M-only
  53             flags & I_ABS   ? "Abs "   : "",
  54             flags & I_MIF   ? "MIF "   : "",
  55             flags & I_TRUNC ? "Trunc " : "",
  56             flags & I_NBAR  ? "~BAR "  : "",
  57             flags & I_PMASK ? "PMask " : "",
  58             flags & I_PERR  ? "PErr"   : "",
  59             flags & I_TALLY ? "Tally " : "",
  60             flags & I_OMASK ? "OMASK " : "",
  61             flags & I_EUFL  ? "EUFL "  : "",
  62             flags & I_EOFL  ? "EOFL "  : "",
  63             flags & I_OFLOW ? "Ovr "   : "",
  64             flags & I_CARRY ? "Carry " : "",
  65             flags & I_NEG   ? "Neg "   : "",
  66             flags & I_ZERO  ? "Zero "  : ""
  67             );
  68     return buffer;
  69 
  70 }
  71 
  72 static char * dps8_strupr(char *str)
     /* [previous][next][first][last][top][bottom][index][help] */
  73 {
  74     char *s;
  75 
  76     for(s = str; *s; s++)
  77         *s = (char) toupper((unsigned char)*s);
  78     return str;
  79 }
  80 
  81 //! get instruction info for IWB ...
  82 
  83 static struct opcode_s unimplented = {"(unimplemented)", 0, 0, 0, 0};
  84 
  85 struct opcode_s * get_iwb_info  (DCDstruct * i)
     /* [previous][next][first][last][top][bottom][index][help] */
  86   {
  87     struct opcode_s * p = &opcodes10[i->opcode10];
  88     return p->mne ? p : &unimplented;
  89   }
  90 
  91 char *disassemble(char * result, word36 instruction)
     /* [previous][next][first][last][top][bottom][index][help] */
  92 {
  93     uint32 opcode   = GET_OP(instruction);   ///< get opcode
  94     uint32 opcodeX  = GET_OPX(instruction);  ///< opcode extension
  95     uint32 opcode10 = opcode | (opcodeX ? 01000 : 0);
  96     word18 address  = GET_ADDR(instruction);
  97     word1  a        = GET_A(instruction);
  98     //int32 i       = GET_I(instruction);
  99     word6  tag      = GET_TAG(instruction);
 100 
 101     //static char result[132] = "???";
 102     strcpy(result, "???");
 103 
 104     // get mnemonic ...
 105     if (opcodes10[opcode10].mne)
 106         strcpy(result, opcodes10[opcode10].mne);
 107 
 108     // XXX need to reconstruct multi-word EIS instruction.
 109 
 110     char buff[64];
 111 
 112     if (a)
 113     {
 114         int n = (address >> 15) & 07;
 115         int offset = address & 077777;
 116 
 117         sprintf(buff, " pr%d|%o", n, offset);
 118         strcat (result, buff);
 119         // return dps8_strupr(result);
 120     } else {
 121         sprintf(buff, " %06o", address);
 122         strcat (result, buff);
 123     }
 124     // get mod
 125     strcpy(buff, "");
 126     for(uint n = 0 ; n < 0100 ; n++)
 127         if (extMods[n].mod)
 128             if(n == tag)
 129             {
 130                 strcpy(buff, extMods[n].mod);
 131                 break;
 132             }
 133 
 134     if (strlen(buff))
 135     {
 136         strcat(result, ",");
 137         strcat(result, buff);
 138     }
 139 
 140     return dps8_strupr(result);
 141 }
 142 
 143 /*
 144  * get_mod__string ()
 145  *
 146  * Convert instruction address modifier tag to printable string
 147  * WARNING: returns pointer to statically allocated string
 148  */
 149 
 150 char *get_mod_string(char * msg, word6 tag)
     /* [previous][next][first][last][top][bottom][index][help] */
 151 {
 152     strcpy(msg, "none");
 153 
 154     if (tag >= 0100) //-V536
 155     {
 156         sprintf(msg, "getModReg(tag out-of-range %o)", tag);
 157     } else {
 158         for(uint n = 0 ; n < 0100 ; n++) //-V536
 159             if (extMods[n].mod)
 160                 if(n == tag)
 161                 {
 162                     strcpy(msg, extMods[n].mod);
 163                     break;
 164                 }
 165 
 166     }
 167     return msg;
 168 }
 169 
 170 /*
 171  * 36-bit arithmetic stuff ...
 172  */
 173 /* Single word integer routines */
 174 
 175 word36 Add36b (word36 op1, word36 op2, word1 carryin, word18 flagsToSet, word18 * flags, bool * ovf)
     /* [previous][next][first][last][top][bottom][index][help] */
 176   {
 177     CPT (cpt2L, 17); // Add36b
 178     sim_debug (DBG_TRACEEXT, & cpu_dev, "Add36b op1 %012"PRIo64" op2 %012"PRIo64" carryin %o flagsToSet %06o flags %06o\n", op1, op2, carryin, flagsToSet, * flags);
 179 
 180 // See: https://en.wikipedia.org/wiki/Two%27s_complement#Addition
 181 
 182     // 37 bit arithmetic for the above N+1 algorithm
 183     word38 op1e = op1 & MASK36;
 184     word38 op2e = op2 & MASK36;
 185     word38 ci   = carryin ? 1 : 0;
 186 
 187     // extend sign bits
 188     if (op1e & SIGN36)
 189       op1e |= BIT37;
 190     if (op2e & SIGN36)
 191       op2e |= BIT37;
 192 
 193     // Do the math
 194     word38 res = op1e + op2e + ci;
 195 
 196     // Extract the overflow bits
 197     bool r37 = res & BIT37 ? true : false;
 198     bool r36 = res & SIGN36 ? true : false;
 199 
 200     // Extract the carry bit
 201     bool r38 = res & BIT38 ? true : false;
 202 
 203     // Check for overflow
 204     * ovf = r37 ^ r36;
 205 
 206     // Check for carry
 207     bool cry = r38;
 208 
 209     // Truncate the result
 210     res &= MASK36;
 211 
 212 #ifdef PANEL68
 213     if (cry) CPT (cpt2L, 28); // carry
 214     if (ovf) CPT (cpt2L, 29); // ovf
 215     if (!res) CPT (cpt2L, 30); // zero
 216     if (res & SIGN36) CPT (cpt2L, 31); // neg
 217 #endif
 218 
 219     if (flagsToSet & I_CARRY)
 220       {
 221         if (cry)
 222           SETF (* flags, I_CARRY);
 223         else
 224           CLRF (* flags, I_CARRY);
 225       }
 226 
 227     if (chkOVF () && (flagsToSet & I_OFLOW))
 228       {
 229         if (* ovf)
 230           SETF (* flags, I_OFLOW);      // overflow
 231       }
 232 
 233     if (flagsToSet & I_ZERO)
 234       {
 235         if (res)
 236           CLRF (* flags, I_ZERO);
 237         else
 238           SETF (* flags, I_ZERO);       // zero result
 239       }
 240 
 241     if (flagsToSet & I_NEG)
 242       {
 243         if (res & SIGN36)
 244           SETF (* flags, I_NEG);
 245         else
 246           CLRF (* flags, I_NEG);
 247       }
 248 
 249     sim_debug (DBG_TRACEEXT, & cpu_dev, "Add36b res %012"PRIo64" flags %06o ovf %o\n", res, * flags, * ovf);
 250     return res;
 251   }
 252 
 253 word36 Sub36b (word36 op1, word36 op2, word1 carryin, word18 flagsToSet, word18 * flags, bool * ovf)
     /* [previous][next][first][last][top][bottom][index][help] */
 254   {
 255     CPT (cpt2L, 18); // Sub36b
 256 
 257 // See: https://en.wikipedia.org/wiki/Two%27s_complement
 258 
 259 // AL39:
 260 //
 261 //  If carry indicator ON, then C(A) - C(Y) -> C(A)
 262 //  If carry indicator OFF, then C(A) - C(Y) - 1 -> C(A)
 263 
 264     // 38 bit arithmetic for the above N+1 algorithm
 265     word38 op1e = op1 & MASK36;
 266     word38 op2e = op2 & MASK36;
 267     // Note that carryin has an inverted sense for borrow
 268     word38 ci   = carryin ? 0 : 1;
 269 
 270     // extend sign bits
 271     if (op1e & SIGN36)
 272       op1e |= BIT37;
 273     if (op2e & SIGN36)
 274       op2e |= BIT37;
 275 
 276     // Do the math
 277     // word38 res = op1e - op2e - ci;
 278     // ubsan
 279     word38 res = (word38) (((word38s) op1e) - ((word38s) op2e) - ((word38) ci));
 280 
 281     // Extract the overflow bits
 282     bool r37 = (res & BIT37) ? true : false;
 283     bool r36 = (res & SIGN36) ? true : false;
 284 
 285     // Extract the carry bit
 286     bool r38 = res & BIT38 ? true : false;
 287 
 288     // Truncate the result
 289     res &= MASK36;
 290 
 291     // Check for overflow
 292     * ovf = r37 ^ r36;
 293 
 294     // Check for carry
 295     bool cry = r38;
 296 
 297 #ifdef PANEL68
 298     if (cry) CPT (cpt2L, 28); // carry
 299     if (ovf) CPT (cpt2L, 29); // ovf
 300     if (!res) CPT (cpt2L, 30); // zero
 301     if (res & SIGN36) CPT (cpt2L, 31); // neg
 302 #endif
 303 
 304     if (flagsToSet & I_CARRY)
 305       {
 306         if (cry) // Note inverted logic for subtraction
 307           CLRF (* flags, I_CARRY);
 308         else
 309           SETF (* flags, I_CARRY);
 310       }
 311 
 312     if (chkOVF () && (flagsToSet & I_OFLOW))
 313       {
 314         if (* ovf)
 315           SETF (* flags, I_OFLOW);      // overflow
 316       }
 317 
 318     if (flagsToSet & I_ZERO)
 319       {
 320         if (res)
 321           CLRF (* flags, I_ZERO);
 322         else
 323           SETF (* flags, I_ZERO);       // zero result
 324       }
 325 
 326     if (flagsToSet & I_NEG)
 327       {
 328         if (res & SIGN36)
 329           SETF (* flags, I_NEG);
 330         else
 331           CLRF (* flags, I_NEG);
 332       }
 333 
 334     return res;
 335   }
 336 
 337 word18 Add18b (word18 op1, word18 op2, word1 carryin, word18 flagsToSet, word18 * flags, bool * ovf)
     /* [previous][next][first][last][top][bottom][index][help] */
 338   {
 339     CPT (cpt2L, 19); // Add18b
 340 
 341 // See: https://en.wikipedia.org/wiki/Two%27s_complement#Addition
 342 
 343     // 19 bit arithmetic for the above N+1 algorithm
 344     word20 op1e = op1 & MASK18;
 345     word20 op2e = op2 & MASK18;
 346     word20 ci   = carryin ? 1 : 0;
 347 
 348     // extend sign bits
 349     if (op1e & SIGN18)
 350       op1e |= BIT19;
 351     if (op2e & SIGN18)
 352       op2e |= BIT19;
 353 
 354     // Do the math
 355     word20 res = op1e + op2e + ci;
 356 
 357     // Extract the overflow bits
 358     bool r19 = (res & BIT19)  ? true : false;
 359     bool r18 = (res & SIGN18) ? true : false;
 360 
 361     // Extract the carry bit
 362     bool r20 = res & BIT20 ? true : false;
 363 
 364     // Truncate the result
 365     res &= MASK18;
 366 
 367     // Check for overflow
 368     * ovf = r19 ^ r18;
 369 
 370     // Check for carry
 371     bool cry = r20;
 372 
 373 #ifdef PANEL68
 374     if (cry) CPT (cpt2L, 28); // carry
 375     if (ovf) CPT (cpt2L, 29); // ovf
 376     if (!res) CPT (cpt2L, 30); // zero
 377     if (res & SIGN36) CPT (cpt2L, 31); // neg
 378 #endif
 379 
 380     if (flagsToSet & I_CARRY)
 381       {
 382         if (cry)
 383           SETF (* flags, I_CARRY);
 384         else
 385           CLRF (* flags, I_CARRY);
 386       }
 387 
 388     if (chkOVF () && (flagsToSet & I_OFLOW))
 389       {
 390         if (* ovf)
 391           SETF (* flags, I_OFLOW);      // overflow
 392       }
 393 
 394     if (flagsToSet & I_ZERO)
 395       {
 396         if (res)
 397           CLRF (* flags, I_ZERO);
 398         else
 399           SETF (* flags, I_ZERO);       // zero result
 400       }
 401 
 402     if (flagsToSet & I_NEG)
 403       {
 404         if (res & SIGN18)
 405           SETF (* flags, I_NEG);
 406         else
 407           CLRF (* flags, I_NEG);
 408       }
 409 
 410     return (word18) res;
 411   }
 412 
 413 word18 Sub18b (word18 op1, word18 op2, word1 carryin, word18 flagsToSet, word18 * flags, bool * ovf)
     /* [previous][next][first][last][top][bottom][index][help] */
 414   {
 415     CPT (cpt2L, 20); // Sub18b
 416 
 417 // See: https://en.wikipedia.org/wiki/Two%27s_complement
 418 
 419 // AL39:
 420 //
 421 //  If carry indicator ON, then C(A) - C(Y) -> C(A)
 422 //  If carry indicator OFF, then C(A) - C(Y) - 1 -> C(A)
 423 
 424     // 19 bit arithmetic for the above N+1 algorithm
 425     word20 op1e = op1 & MASK18;
 426     word20 op2e = op2 & MASK18;
 427     // Note that carryin has an inverted sense for borrow
 428     word20 ci   = carryin ? 0 : 1;
 429 
 430     // extend sign bits
 431     if (op1e & SIGN18)
 432       op1e |= BIT19;
 433     if (op2e & SIGN18)
 434       op2e |= BIT19;
 435 
 436     // Do the math
 437     // word20 res = op1e - op2e - ci;
 438     // ubsan
 439     word20 res = (word20) (((word20s) op1e) - ((word20s) op2e) - ((word20s) ci));
 440 
 441     // Extract the overflow bits
 442     bool r19 = res & BIT19  ? true : false;
 443     bool r18 = res & SIGN18 ? true : false;
 444 
 445     // Extract the carry bit
 446     bool r20 = res & BIT20 ? true : false;
 447 
 448     // Truncate the result
 449     res &= MASK18;
 450 
 451     // Check for overflow
 452     * ovf = r19 ^ r18;
 453 
 454     // Check for carry
 455     bool cry = r20;
 456 
 457 #ifdef PANEL68
 458     if (cry) CPT (cpt2L, 28); // carry
 459     if (ovf) CPT (cpt2L, 29); // ovf
 460     if (!res) CPT (cpt2L, 30); // zero
 461     if (res & SIGN36) CPT (cpt2L, 31); // neg
 462 #endif
 463 
 464     if (flagsToSet & I_CARRY)
 465       {
 466         if (cry) // Note inverted logic for subtraction
 467           CLRF (* flags, I_CARRY);
 468         else
 469           SETF (* flags, I_CARRY);
 470       }
 471 
 472     if (chkOVF () && (flagsToSet & I_OFLOW))
 473       {
 474         if (* ovf)
 475           SETF (* flags, I_OFLOW);      // overflow
 476       }
 477 
 478     if (flagsToSet & I_ZERO)
 479       {
 480         if (res)
 481           CLRF (* flags, I_ZERO);
 482         else
 483           SETF (* flags, I_ZERO);       // zero result
 484       }
 485 
 486     if (flagsToSet & I_NEG)
 487       {
 488         if (res & SIGN18)
 489           SETF (* flags, I_NEG);
 490         else
 491           CLRF (* flags, I_NEG);
 492       }
 493 
 494     return res;
 495   }
 496 
 497 word72 Add72b (word72 op1, word72 op2, word1 carryin, word18 flagsToSet, word18 * flags, bool * ovf)
     /* [previous][next][first][last][top][bottom][index][help] */
 498   {
 499     CPT (cpt2L, 21); // Add72b
 500 
 501 // See: https://en.wikipedia.org/wiki/Two%27s_complement#Addition
 502 
 503     // 73 bit arithmetic for the above N+1 algorithm
 504 #ifdef NEED_128
 505     word74 op1e = and_128 (op1, MASK72);
 506     word74 op2e = and_128 (op2, MASK72);
 507     word74 ci   = construct_128 (0, carryin ? 1 : 0);
 508 #else
 509     word74 op1e = op1 & MASK72;
 510     word74 op2e = op2 & MASK72;
 511     word74 ci   = carryin ? 1 : 0;
 512 #endif
 513 
 514     // extend sign bits
 515 #ifdef NEED_128
 516     if (isnonzero_128 (and_128 (op1e, SIGN72)))
 517       op1e = or_128 (op1e, BIT73);
 518     if (isnonzero_128 (and_128 (op2e, SIGN72)))
 519       op2e = or_128 (op2e, BIT73);
 520 #else
 521     if (op1e & SIGN72)
 522       op1e |= BIT73;
 523     if (op2e & SIGN72)
 524       op2e |= BIT73;
 525 #endif
 526 
 527     // Do the math
 528 #ifdef NEED_128
 529     word74 res = add_128 (op1e, add_128 (op2e, ci));
 530 #else
 531     word74 res = op1e + op2e + ci;
 532 #endif
 533 
 534     // Extract the overflow bits
 535 #ifdef NEED_128
 536     bool r73 = isnonzero_128 (and_128 (res, BIT73));
 537     bool r72 = isnonzero_128 (and_128 (res, SIGN72));
 538 #else
 539     bool r73 = res & BIT73  ? true : false;
 540     bool r72 = res & SIGN72 ? true : false;
 541 #endif
 542 
 543     // Extract the carry bit
 544 #ifdef NEED_128
 545     bool r74 = isnonzero_128 (and_128 (res, BIT74));
 546 #else
 547     bool r74 = res & BIT74 ? true : false;
 548 #endif
 549 
 550     // Truncate the result
 551 #ifdef NEED_128
 552     res = and_128 (res, MASK72);
 553 #else
 554     res &= MASK72;
 555 #endif
 556 
 557     // Check for overflow
 558     * ovf = r73 ^ r72;
 559 
 560     // Check for carry
 561     bool cry = r74;
 562 
 563 #ifdef PANEL68
 564     if (cry) CPT (cpt2L, 28); // carry
 565     if (ovf) CPT (cpt2L, 29); // ovf
 566     if (!res) CPT (cpt2L, 30); // zero
 567     if (res & SIGN36) CPT (cpt2L, 31); // neg
 568 #endif
 569 
 570     if (flagsToSet & I_CARRY)
 571       {
 572         if (cry)
 573           SETF (* flags, I_CARRY);
 574         else
 575           CLRF (* flags, I_CARRY);
 576       }
 577 
 578     if (chkOVF () && (flagsToSet & I_OFLOW))
 579       {
 580         if (* ovf)
 581           SETF (* flags, I_OFLOW);      // overflow
 582       }
 583 
 584     if (flagsToSet & I_ZERO)
 585       {
 586 #ifdef NEED_128
 587         if (isnonzero_128 (res))
 588 #else
 589         if (res)
 590 #endif
 591           CLRF (* flags, I_ZERO);
 592         else
 593           SETF (* flags, I_ZERO);       // zero result
 594       }
 595 
 596     if (flagsToSet & I_NEG)
 597       {
 598 #ifdef NEED_128
 599         if (isnonzero_128 (and_128 (res, SIGN72)))
 600 #else
 601         if (res & SIGN72)
 602 #endif
 603           SETF (* flags, I_NEG);
 604         else
 605           CLRF (* flags, I_NEG);
 606       }
 607 
 608     return res;
 609   }
 610 
 611 word72 Sub72b (word72 op1, word72 op2, word1 carryin, word18 flagsToSet, word18 * flags, bool * ovf)
     /* [previous][next][first][last][top][bottom][index][help] */
 612   {
 613     CPT (cpt2L, 22); // Sub72b
 614 #ifdef NEED_128
 615     sim_debug (DBG_TRACEEXT, & cpu_dev, "Sub72b op1 %012"PRIo64"%012"PRIo64" op2 %012"PRIo64"%012"PRIo64" carryin %o flagsToSet %06o flags %06o\n",
 616  (word36) ((rshift_128 (op1, 36).l) & MASK36), (word36) (op1.l & MASK36), (word36) (rshift_128 (op2, 36).l & MASK36), (word36) (op2.l & MASK36), carryin, flagsToSet, * flags);
 617 #else
 618     sim_debug (DBG_TRACEEXT, & cpu_dev, "Sub72b op1 %012"PRIo64"%012"PRIo64" op2 %012"PRIo64"%012"PRIo64" carryin %o flagsToSet %06o flags %06o\n",
 619  (word36) ((op1 >> 36) & MASK36), (word36) (op1 & MASK36), (word36) ((op2 >> 36) & MASK36), (word36) (op2 & MASK36), carryin, flagsToSet, * flags);
 620 #endif
 621 
 622 // See: https://en.wikipedia.org/wiki/Two%27s_complement
 623 
 624 // AL39:
 625 //
 626 //  If carry indicator ON, then C(A) - C(Y) -> C(A)
 627 //  If carry indicator OFF, then C(A) - C(Y) - 1 -> C(A)
 628 
 629     // 73 bit arithmetic for the above N+1 algorithm
 630 #ifdef NEED_128
 631     word74 op1e = and_128 (op1, MASK72);
 632     word74 op2e = and_128 (op2, MASK72);
 633 #else
 634     word74 op1e = op1 & MASK72;
 635     word74 op2e = op2 & MASK72;
 636 #endif
 637     // Note that carryin has an inverted sense for borrow
 638 #ifdef NEED_128
 639     word74 ci = construct_128 (0, carryin ? 0 : 1);
 640 #else
 641     word74 ci = carryin ? 0 : 1;
 642 #endif
 643 
 644     // extend sign bits
 645 #ifdef NEED_128
 646     if (isnonzero_128 (and_128 (op1e, SIGN72)))
 647       op1e = or_128 (op1e, BIT73);
 648     if (isnonzero_128 (and_128 (op2e, SIGN72)))
 649       op2e = or_128 (op2e, BIT73);
 650 #else
 651     if (op1e & SIGN72)
 652       op1e |= BIT73;
 653     if (op2e & SIGN72)
 654       op2e |= BIT73;
 655 #endif
 656 
 657     // Do the math
 658 #ifdef NEED_128
 659     sim_debug (DBG_TRACEEXT, & cpu_dev, "Sub72b op1e %012"PRIo64"%012"PRIo64" op2e %012"PRIo64"%012"PRIo64" carryin %o flagsToSet %06o flags %06o\n",
 660  (word36) ((rshift_128 (op1e, 36).l) & MASK36), (word36) (op1e.l & MASK36), (word36) (rshift_128 (op2e, 36).l & MASK36), (word36) (op2e.l & MASK36), carryin, flagsToSet, * flags);
 661 #else
 662     sim_debug (DBG_TRACEEXT, & cpu_dev, "Sub72b op1e %012"PRIo64"%012"PRIo64" op2e %012"PRIo64"%012"PRIo64" carryin %o flagsToSet %06o flags %06o\n",
 663  (word36) ((op1e >> 36) & MASK36), (word36) (op1e & MASK36), (word36) ((op2e >> 36) & MASK36), (word36) (op2e & MASK36), carryin, flagsToSet, * flags);
 664 #endif
 665 #ifdef NEED_128
 666     word74 res = subtract_128 (subtract_128 (op1e, op2e), ci);
 667 #else
 668     // word74 res = op1e - op2e - ci;
 669     // ubsan
 670     word74 res = (word72) (((word72s) op1e) - ((word72s) op2e) - ((word72s) ci));
 671 #endif
 672 #ifdef NEED_128
 673     sim_debug (DBG_TRACEEXT, & cpu_dev, "Sub72b res %012"PRIo64"%012"PRIo64" flags %06o ovf %o\n", (word36) (rshift_128 (res, 36).l & MASK36), (word36) (res.l & MASK36), * flags, * ovf);
 674 #else
 675     sim_debug (DBG_TRACEEXT, & cpu_dev, "Sub72b res %012"PRIo64"%012"PRIo64" flags %06o ovf %o\n", (word36) ((res >> 36) & MASK36), (word36) (res & MASK36), * flags, * ovf);
 676 #endif
 677 
 678     // Extract the overflow bits
 679 #ifdef NEED_128
 680     bool r73 = isnonzero_128 (and_128 (res, BIT73));
 681     bool r72 = isnonzero_128 (and_128 (res, SIGN72));
 682 #else
 683     bool r73 = res & BIT73  ? true : false;
 684     bool r72 = res & SIGN72 ? true : false;
 685 #endif
 686 
 687     // Extract the carry bit
 688 #ifdef NEED_128
 689     bool r74 = isnonzero_128 (and_128 (res, BIT74));
 690 #else
 691     bool r74 = res & BIT74 ? true : false;
 692 #endif
 693 
 694     // Truncate the result
 695 #ifdef NEED_128
 696     res = and_128 (res, MASK72);
 697 #else
 698     res &= MASK72;
 699 #endif
 700 
 701     // Check for overflow
 702     * ovf = r73 ^ r72;
 703 
 704     // Check for carry
 705     bool cry = r74;
 706 
 707 #ifdef PANEL68
 708     if (cry) CPT (cpt2L, 28); // carry
 709     if (ovf) CPT (cpt2L, 29); // ovf
 710     if (!res) CPT (cpt2L, 30); // zero
 711     if (res & SIGN36) CPT (cpt2L, 31); // neg
 712 #endif
 713 
 714     if (flagsToSet & I_CARRY)
 715       {
 716         if (cry) // Note inverted logic for subtraction
 717           CLRF (* flags, I_CARRY);
 718         else
 719           SETF (* flags, I_CARRY);
 720       }
 721 
 722     if (chkOVF () && (flagsToSet & I_OFLOW))
 723       {
 724         if (* ovf)
 725           SETF (* flags, I_OFLOW);      // overflow
 726       }
 727 
 728     if (flagsToSet & I_ZERO)
 729       {
 730 #ifdef NEED_128
 731         if (isnonzero_128 (res))
 732 #else
 733         if (res)
 734 #endif
 735           CLRF (* flags, I_ZERO);
 736         else
 737           SETF (* flags, I_ZERO);       // zero result
 738       }
 739 
 740     if (flagsToSet & I_NEG)
 741       {
 742 #ifdef NEED_128
 743         if (isnonzero_128 (and_128 (res, SIGN72)))
 744 #else
 745         if (res & SIGN72)
 746 #endif
 747           SETF (* flags, I_NEG);
 748         else
 749           CLRF (* flags, I_NEG);
 750       }
 751 
 752 #ifdef NEED_128
 753     sim_debug (DBG_TRACEEXT, & cpu_dev, "Sub72b res %012"PRIo64"%012"PRIo64" flags %06o ovf %o\n", (word36) (rshift_128 (res, 36).l & MASK36), (word36) (res.l & MASK36), * flags, * ovf);
 754 #else
 755     sim_debug (DBG_TRACEEXT, & cpu_dev, "Sub72b res %012"PRIo64"%012"PRIo64" flags %06o ovf %o\n", (word36) ((res >> 36) & MASK36), (word36) (res & MASK36), * flags, * ovf);
 756 #endif
 757     return res;
 758   }
 759 
 760 // CANFAULT
 761 word36 compl36(word36 op1, word18 *flags, bool * ovf)
     /* [previous][next][first][last][top][bottom][index][help] */
 762 {
 763     CPT (cpt2L, 23); // compl36
 764     //printf("op1 = %"PRIo64" %"PRIo64"\n", op1, (-op1) & DMASK);
 765 
 766     op1 &= DMASK;
 767 
 768     // word36 res = -op1 & DMASK;
 769     // ubsan
 770     word36 res = ((word36) (- ((word36s) op1))) & DMASK;
 771 
 772     * ovf = op1 == MAXNEG;
 773 
 774 #ifdef PANEL68
 775     if (* ovf) CPT (cpt2L, 29); // ovf
 776     if (!res) CPT (cpt2L, 30); // zero
 777     if (res & SIGN36) CPT (cpt2L, 31); // neg
 778 #endif
 779 
 780     if (chkOVF () && * ovf)
 781         SETF(*flags, I_OFLOW);
 782 
 783     if (res & SIGN36)
 784         SETF(*flags, I_NEG);
 785     else
 786         CLRF(*flags, I_NEG);
 787 
 788     if (res == 0)
 789         SETF(*flags, I_ZERO);
 790     else
 791         CLRF(*flags, I_ZERO);
 792 
 793     return res;
 794 }
 795 
 796 // CANFAULT
 797 word18 compl18(word18 op1, word18 *flags, bool * ovf)
     /* [previous][next][first][last][top][bottom][index][help] */
 798 {
 799     CPT (cpt2L, 24); // compl18
 800     //printf("op1 = %"PRIo64" %"PRIo64"\n", op1, (-op1) & DMASK);
 801 
 802     op1 &= MASK18;
 803 
 804     // word18 res = -op1 & MASK18;
 805     // ubsan
 806     word18 res = ((word18) (- (word18s) op1)) & MASK18;
 807 
 808     * ovf = op1 == MAX18NEG;
 809 #ifdef PANEL68
 810     if (* ovf) CPT (cpt2L, 29); // ovf
 811     if (!res) CPT (cpt2L, 30); // zero
 812     if (res & SIGN18) CPT (cpt2L, 31); // neg
 813 #endif
 814 
 815     if (chkOVF () && * ovf)
 816         SETF(*flags, I_OFLOW);
 817     if (res & SIGN18)
 818         SETF(*flags, I_NEG);
 819     else
 820         CLRF(*flags, I_NEG);
 821 
 822     if (res == 0)
 823         SETF(*flags, I_ZERO);
 824     else
 825         CLRF(*flags, I_ZERO);
 826 
 827     return res;
 828 }
 829 
 830 void copyBytes(int posn, word36 src, word36 *dst)
     /* [previous][next][first][last][top][bottom][index][help] */
 831 {
 832     word36 mask = 0;
 833 
 834     if (posn & 8) // bit 30 - byte 0 - (bits 0-8)
 835         mask |= 0777000000000LL;
 836 
 837     if (posn & 4) // bit 31 - byte 1 - (bits 9-17)
 838         mask |= 0000777000000LL;
 839 
 840     if (posn & 2) // bit 32 - byte 2 - (bits 18-26)
 841         mask |= 0000000777000LL;
 842 
 843     if (posn & 1) // bit 33 - byte 3 - (bits 27-35)
 844         mask |= 0000000000777LL;
 845 
 846     word36 byteVals = src & mask;   // get byte bits
 847 
 848     // clear the bits in dst
 849     *dst &= ~mask;
 850 
 851     // and set the bits in dst
 852     *dst |= byteVals;
 853 }
 854 
 855 void copyChars(int posn, word36 src, word36 *dst)
     /* [previous][next][first][last][top][bottom][index][help] */
 856 {
 857     word36 mask = 0;
 858 
 859     if (posn & 32) // bit 30 - char 0 - (bits 0-5)
 860         mask |= 0770000000000LL;
 861 
 862     if (posn & 16) // bit 31 - char 1 - (bits 6-11)
 863         mask |= 0007700000000LL;
 864 
 865     if (posn & 8) // bit 32 - char 2 - (bits 12-17)
 866         mask |= 0000077000000LL;
 867 
 868     if (posn & 4) // bit 33 - char 3 - (bits 18-23)
 869         mask |= 0000000770000LL;
 870 
 871     if (posn & 2) // bit 34 - char 4 - (bits 24-29)
 872         mask |= 0000000007700LL;
 873 
 874     if (posn & 1) // bit 35 - char 5 - (bits 30-35)
 875         mask |= 0000000000077LL;
 876 
 877     word36 byteVals = src & mask;   // get byte bits
 878 
 879     // clear the bits in dst
 880     *dst &= ~mask;
 881 
 882     // and set the bits in dst
 883     *dst |= byteVals;
 884 }
 885 
 886 /*!
 887  * write 9-bit byte into 36-bit word....
 888  */
 889 void putByte(word36 *dst, word9 data, int posn)
     /* [previous][next][first][last][top][bottom][index][help] */
 890 {
 891     // XXX which is faster switch() or calculation?
 892 
 893 //    int offset = 27 - (9 * posn);//    0;
 894 //    switch (posn)
 895 //    {
 896 //        case 0:
 897 //            offset = 27;
 898 //            break;
 899 //        case 1:
 900 //            offset = 18;
 901 //            break;
 902 //        case 2:
 903 //            offset = 9;
 904 //            break;
 905 //        case 3:
 906 //            offset = 0;
 907 //            break;
 908 //    }
 909     putbits36_9 (dst, (uint) posn * 9, data);
 910 }
 911 
 912 void putChar(word36 *dst, word6 data, int posn)
     /* [previous][next][first][last][top][bottom][index][help] */
 913 {
 914     // XXX which is faster switch() or calculation?
 915 
 916 //    int offset = 30 - (6 * posn);   //0;
 917 //    switch (posn)
 918 //    {
 919 //        case 0:
 920 //            offset = 30;
 921 //            break;
 922 //        case 1:
 923 //            offset = 24;
 924 //            break;
 925 //        case 2:
 926 //            offset = 18;
 927 //            break;
 928 //        case 3:
 929 //            offset = 12;
 930 //            break;
 931 //        case 4:
 932 //            offset = 6;
 933 //            break;
 934 //        case 5:
 935 //            offset = 0;
 936 //            break;
 937 //    }
 938     putbits36_6 (dst, (uint) posn * 6, data);
 939 }
 940 
 941 word72 convert_to_word72(word36 even, word36 odd)
     /* [previous][next][first][last][top][bottom][index][help] */
 942 {
 943 #ifdef NEED_128
 944     return or_128 (lshift_128 (construct_128 (0, even), 36), construct_128 (0, odd));
 945 #else
 946     return ((word72)even << 36) | (word72)odd;
 947 #endif
 948 }
 949 
 950 void convert_to_word36 (word72 src, word36 *even, word36 *odd)
     /* [previous][next][first][last][top][bottom][index][help] */
 951 {
 952 #ifdef NEED_128
 953     *even = rshift_128 (src, 36).l & DMASK;
 954     *odd  = src.l & DMASK;
 955 #else
 956     *even = (word36)(src >> 36) & DMASK;
 957     *odd  = (word36)src & DMASK;
 958 #endif
 959 }
 960 
 961 void cmp36(word36 oP1, word36 oP2, word18 *flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 962   {
 963     CPT (cpt2L, 25); // cmp36
 964     L68_ (cpu.ou.cycle |= ou_GOS;)
 965     t_int64 op1 = SIGNEXT36_64(oP1 & DMASK);
 966     t_int64 op2 = SIGNEXT36_64(oP2 & DMASK);
 967 
 968     word36 sign1 = (word36) op1 & SIGN36;
 969     word36 sign2 = (word36) op2 & SIGN36;
 970 
 971     if ((! sign1) && sign2)  // op1 > 0, op2 < 0 :: op1 > op2
 972       CLRF (* flags, I_ZERO | I_NEG | I_CARRY);
 973 
 974     else if (sign1 == sign2) // both operands have the same sign
 975       {
 976          if (op1 > op2)
 977            {
 978              CPT (cpt2L, 28); // carry
 979              SETF (* flags, I_CARRY);
 980              CLRF (* flags, I_ZERO | I_NEG);
 981            }
 982          else if (op1 == op2)
 983            {
 984              CPT (cpt2L, 28); // carry
 985              CPT (cpt2L, 30); // zero
 986              SETF (* flags, I_ZERO | I_CARRY);
 987              CLRF (* flags, I_NEG);
 988            }
 989          else //  op1 < op2
 990           {
 991             CPT (cpt2L, 31); // neg
 992             SETF (* flags, I_NEG);
 993             CLRF (* flags, I_ZERO | I_CARRY);
 994           }
 995       }
 996     else // op1 < 0, op2 > 0 :: op1 < op2
 997       {
 998         CPT  (cpt2L, 28); // carry
 999         CPT  (cpt2L, 31); // neg
1000         SETF (* flags, I_CARRY | I_NEG);
1001         CLRF (* flags, I_ZERO);
1002       }
1003   }
1004 
1005 void cmp18(word18 oP1, word18 oP2, word18 *flags)
     /* [previous][next][first][last][top][bottom][index][help] */
1006   {
1007     CPT (cpt2L, 26); // cmp18
1008     L68_ (cpu.ou.cycle |= ou_GOS;)
1009     int32 op1 = SIGNEXT18_32 (oP1 & MASK18);
1010     int32 op2 = SIGNEXT18_32 (oP2 & MASK18);
1011 
1012     word18 sign1 = (word18) op1 & SIGN18;
1013     word18 sign2 = (word18) op2 & SIGN18;
1014 
1015     if ((! sign1) && sign2)  // op1 > 0, op2 < 0 :: op1 > op2
1016       CLRF (* flags, I_ZERO | I_NEG | I_CARRY);
1017 
1018     else if (sign1 == sign2) // both operands have the same sign
1019       {
1020         if (op1 > op2)
1021           {
1022             CPT (cpt2L, 28); // carry
1023             SETF (* flags, I_CARRY);
1024             CLRF (* flags, I_ZERO | I_NEG);
1025           }
1026         else if (op1 == op2)
1027           {
1028             CPT (cpt2L, 28); // carry
1029             CPT (cpt2L, 30); // zero
1030             SETF (* flags, I_ZERO | I_CARRY);
1031             CLRF (* flags, I_NEG);
1032           }
1033         else //  op1 < op2
1034           {
1035             CPT (cpt2L, 31); // neg
1036             SETF (* flags, I_NEG);
1037             CLRF (* flags, I_ZERO | I_CARRY);
1038           }
1039       }
1040     else // op1 < 0, op2 > 0 :: op1 < op2
1041       {
1042         CPT (cpt2L, 28); // carry
1043         CPT (cpt2L, 31); // neg
1044         SETF (* flags, I_CARRY | I_NEG);
1045         CLRF (* flags, I_ZERO);
1046       }
1047   }
1048 
1049 void cmp36wl(word36 A, word36 Y, word36 Q, word18 *flags)
     /* [previous][next][first][last][top][bottom][index][help] */
1050 {
1051     CPT (cpt2L, 26); // cmp36wl
1052     // This is wrong; signed math is needed.
1053 
1054     //bool Z = (A <= Y && Y <= Q) || (A >= Y && Y >= Q);
1055 
1056     L68_ (cpu.ou.cycle |= ou_GOS;)
1057     t_int64 As = (word36s) SIGNEXT36_64(A & DMASK);
1058     t_int64 Ys = (word36s) SIGNEXT36_64(Y & DMASK);
1059     t_int64 Qs = (word36s) SIGNEXT36_64(Q & DMASK);
1060     bool Z = (As <= Ys && Ys <= Qs) || (As >= Ys && Ys >= Qs);
1061 
1062     SCF(Z, *flags, I_ZERO);
1063 
1064     if (!(Q & SIGN36) && (Y & SIGN36) && (Qs > Ys))
1065         CLRF(*flags, I_NEG | I_CARRY);
1066     else if (((Q & SIGN36) == (Y & SIGN36)) && (Qs >= Ys))
1067     {
1068         CPT (cpt2L, 28); // carry
1069         SETF(*flags, I_CARRY);
1070         CLRF(*flags, I_NEG);
1071     } else if (((Q & SIGN36) == (Y & SIGN36)) && (Qs < Ys))
1072     {
1073         CPT (cpt2L, 31); // neg
1074         CLRF(*flags, I_CARRY);
1075         SETF(*flags, I_NEG);
1076     } else if ((Q & SIGN36) && !(Y & SIGN36) && (Qs < Ys))
1077     {
1078         CPT (cpt2L, 28); // carry
1079         CPT (cpt2L, 31); // neg
1080         SETF(*flags, I_NEG | I_CARRY);
1081     }
1082 }
1083 
1084 void cmp72(word72 op1, word72 op2, word18 *flags)
     /* [previous][next][first][last][top][bottom][index][help] */
1085 {
1086     CPT (cpt2L, 27); // cmp72
1087    // The case of op1 == 400000000000000000000000 and op2 == 0 falls through
1088    // this code.
1089     L68_ (cpu.ou.cycle |= ou_GOS;)
1090 #ifdef NEED_128
1091 sim_debug (DBG_TRACEEXT, & cpu_dev, "op1 %016"PRIx64"%016"PRIx64"\n", op1.h, op1.l);
1092 sim_debug (DBG_TRACEEXT, & cpu_dev, "op2 %016"PRIx64"%016"PRIx64"\n", op2.h, op2.l);
1093     int128 op1s =  SIGNEXT72_128 (and_128 (op1, MASK72));
1094     int128 op2s =  SIGNEXT72_128 (and_128 (op2, MASK72));
1095 sim_debug (DBG_TRACEEXT, & cpu_dev, "op1s %016"PRIx64"%016"PRIx64"\n", op1s.h, op1s.l);
1096 sim_debug (DBG_TRACEEXT, & cpu_dev, "op2s %016"PRIx64"%016"PRIx64"\n", op2s.h, op2s.l);
1097 #else
1098 sim_debug (DBG_TRACEEXT, & cpu_dev, "op1 %016"PRIx64"%016"PRIx64"\n", (uint64_t) (op1>>64), (uint64_t) op1);
1099 sim_debug (DBG_TRACEEXT, & cpu_dev, "op2 %016"PRIx64"%016"PRIx64"\n", (uint64_t) (op2>>64), (uint64_t) op2);
1100     int128 op1s =  SIGNEXT72_128 (op1 & MASK72);
1101     int128 op2s =  SIGNEXT72_128 (op2 & MASK72);
1102 sim_debug (DBG_TRACEEXT, & cpu_dev, "op1s %016"PRIx64"%016"PRIx64"\n", (uint64_t) (op1s>>64), (uint64_t) op1s);
1103 sim_debug (DBG_TRACEEXT, & cpu_dev, "op2s %016"PRIx64"%016"PRIx64"\n", (uint64_t) (op2s>>64), (uint64_t) op2s);
1104 #endif
1105 #ifdef NEED_128
1106     if (isgt_s128 (op1s, op2s))
1107 #else
1108     if (op1s > op2s)
1109 #endif
1110       {
1111 #ifdef NEED_128
1112         if (isnonzero_128 (and_128 (op2, SIGN72)))
1113 #else
1114         if (op2 & SIGN72)
1115 #endif
1116           CLRF (* flags, I_CARRY);
1117         else
1118           {
1119             CPT (cpt2L, 28); // carry
1120             SETF (* flags, I_CARRY);
1121           }
1122         CLRF (* flags, I_ZERO | I_NEG);
1123       }
1124 #ifdef NEED_128
1125     else if (iseq_128 (cast_128 (op1s), cast_128 (op2s)))
1126 #else
1127     else if (op1s == op2s)
1128 #endif
1129       {
1130         CPT (cpt2L, 28); // carry
1131         CPT (cpt2L, 30); // zero
1132         SETF (* flags, I_CARRY | I_ZERO);
1133         CLRF (* flags, I_NEG);
1134       }
1135     else /* op1s < op2s */
1136       {
1137         CPT (cpt2L, 31); // neg
1138 #ifdef NEED_128
1139         if (isnonzero_128 (and_128 (op1, SIGN72)))
1140 #else
1141         if (op1 & SIGN72)
1142 #endif
1143           {
1144             CPT (cpt2L, 28); // carry
1145             SETF (* flags, I_CARRY);
1146           }
1147         else
1148           CLRF (* flags, I_CARRY);
1149         CLRF (* flags, I_ZERO);
1150         SETF (* flags, I_NEG);
1151       }
1152 }
1153 
1154 /*
1155  * String utilities ...
1156  */
1157 
1158 char * strlower(char *q)
     /* [previous][next][first][last][top][bottom][index][help] */
1159 {
1160         char *s = q;
1161 
1162         while (*s) {
1163                 if (isupper((unsigned char)*s))
1164                         *s = (char) tolower(*s);
1165                 s++;
1166         }
1167         return q;
1168 }
1169 
1170 /*  state definitions  */
1171 #define STAR    0
1172 #define NOTSTAR 1
1173 #define RESET   2
1174 
1175 int strmask (char * str, char * mask)
     /* [previous][next][first][last][top][bottom][index][help] */
1176 /*!
1177  Tests string 'str' against mask string 'mask'
1178  Returns TRUE if the string matches the mask.
1179 
1180  The mask can contain '?' and '*' wild card characters.
1181  '?' matches any        single character.
1182  '*' matches any number of any characters.
1183 
1184  For example:
1185  strmask("Hello", "Hello");     ---> TRUE
1186  strmask("Hello", "Jello");     ---> FALSE
1187  strmask("Hello", "H*o");       ---> TRUE
1188  strmask("Hello", "H*g");       ---> FALSE
1189  strmask("Hello", "?ello");     ---> TRUE
1190  strmask("Hello", "H????");     ---> TRUE
1191  strmask("H", "H????");         ---> FALSE
1192  */
1193   {
1194     char * sp, * mp, * reset_string, * reset_mask, * sn;
1195     int state;
1196 
1197     sp = str;
1198     mp = mask;
1199 
1200     while (1)
1201       {
1202         switch (* mp)
1203           {
1204             case '\0':
1205               return * sp ? false : true;
1206 
1207             case '?':
1208               sp ++;
1209               mp ++;
1210               break;
1211 
1212             default:
1213               if (* mp == * sp)
1214                 {
1215                   sp ++;
1216                   mp ++;
1217                   break;
1218                 }
1219               else
1220                 {
1221                   return false;
1222                 }
1223 
1224             case '*':
1225               if (* (mp + 1) == '\0')
1226                 {
1227                   return true;
1228                 }
1229               if ((sn = strchr (sp, * (mp + 1))) == NULL)
1230                 {
1231                   return false;
1232                 }
1233 
1234               /* save place -- match rest of string */
1235               /* if fail, reset to here */
1236               reset_mask = mp;
1237               reset_string = sn + 1;
1238 
1239               mp = mp + 2;
1240               sp = sn + 1;
1241               state = NOTSTAR;
1242               while (state == NOTSTAR)
1243                 {
1244                   switch (* mp)
1245                     {
1246                       case '\0':
1247                         if (* sp == '\0')
1248                           return false;
1249                         else
1250                           state = RESET;
1251                         break;
1252                       case '?':
1253                         sp ++;
1254                         mp ++;
1255                         break;
1256                       default:
1257                         if (* mp == * sp)
1258                           {
1259                             sp ++;
1260                             mp ++;
1261                           }
1262                         else
1263                           state = RESET;
1264                         break;
1265                       case '*':
1266                         state = STAR;
1267                         break;
1268                     }
1269                 } // while STATE == NOTSTAR
1270               /* we've reach a new star or should reset to last star */
1271               if (state == RESET)
1272                 {
1273                   sp = reset_string;
1274                   mp = reset_mask;
1275                 }
1276               break;
1277           } // switch (* mp)
1278       } // while (1)
1279     /*NOTREACHED*/ /* unreachable */
1280     return false;
1281   }
1282 
1283 
1284 
1285 
1286 
1287 
1288 
1289 
1290 
1291 
1292 
1293 
1294 
1295 
1296 
1297 
1298 
1299 
1300 
1301 
1302 
1303 
1304 
1305 
1306 
1307 
1308 
1309 
1310 
1311 
1312 
1313 
1314 
1315 
1316 
1317 
1318 
1319 
1320 
1321 
1322 
1323 
1324 
1325 
1326 
1327 
1328 
1329 
1330 
1331 
1332 
1333 
1334 
1335 
1336 
1337 
1338 
1339 
1340 
1341 
1342 
1343 
1344 
1345 
1346 
1347 
1348 
1349 
1350 
1351 
1352 
1353 
1354 
1355 
1356 
1357 
1358 
1359 
1360 
1361 
1362 
1363 
1364 
1365 
1366 
1367 
1368 
1369 
1370 
1371 
1372 
1373 
1374 
1375 
1376 
1377 
1378 
1379 
1380 /*
1381  * Removes the trailing spaces from a string.
1382  */
1383 char *rtrim(char *s)
     /* [previous][next][first][last][top][bottom][index][help] */
1384 {
1385     if (! s)
1386       return s;
1387     int index;
1388 
1389     //for (index = (int)strlen(s) - 1; index >= 0 && (s[index] == ' ' || s[index] == '\t'); index--)
1390     for (index = (int)strlen(s) - 1; index >= 0 && isspace((unsigned char)s[index]); index--)
1391     {
1392         s[index] = '\0';
1393     }
1394     return(s);
1395 }
1396 
1397 char *ltrim(char *s)
     /* [previous][next][first][last][top][bottom][index][help] */
1398 /*
1399  * Removes the leading spaces from a string.
1400  */
1401 {
1402     char *p;
1403     if (s == NULL)
1404         return NULL;
1405 
1406     //for (p = s; (*p == ' ' || *p == '\t') && *p != '\0'; p++)
1407     for (p = s; isspace((unsigned char)*p) && *p != '\0'; p++)
1408         ;
1409 
1410     //strcpy(s, p);
1411     memmove(s, p, strlen(p) + 1);
1412     return(s);
1413 }
1414 
1415 char *trim(char *s)
     /* [previous][next][first][last][top][bottom][index][help] */
1416 {
1417     return ltrim(rtrim(s));
1418 }
1419 
1420 char *
1421 stripquotes(char *s)
     /* [previous][next][first][last][top][bottom][index][help] */
1422 {
1423     if (! s || ! *s)
1424         return s;
1425     /*
1426      char *p;
1427 
1428      while ((p = strchr(s, '"')))
1429      *p = ' ';
1430      strchop(s);
1431 
1432      return s;
1433      */
1434     int nLast = (int)strlen(s) - 1;
1435     // trim away leading/trailing "'s
1436     if (s[0] == '"')
1437         s[0] = ' ';
1438     if (s[nLast] == '"')
1439         s[nLast] = ' ';
1440     return trim(s);
1441 }
1442 
1443 #include <ctype.h>
1444 
1445 // XXX what about config=addr7=123, where clist has a "addr%"?
1446 
1447 // return -2: error; -1: done; >= 0 option found
1448 int cfg_parse (const char * tag, const char * cptr, config_list_t * clist, config_state_t * state, int64_t * result)
     /* [previous][next][first][last][top][bottom][index][help] */
1449   {
1450     if (! cptr)
1451       return -2;
1452     char * start = NULL;
1453     if (! state -> copy)
1454       {
1455         state -> copy            = strdup (cptr);
1456         if (! state->copy)
1457           {
1458             fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1459                      __func__, __FILE__, __LINE__);
1460 #if defined(USE_BACKTRACE)
1461 # ifdef SIGUSR2
1462             (void)raise(SIGUSR2);
1463             /*NOTREACHED*/ /* unreachable */
1464 # endif /* ifdef SIGUSR2 */
1465 #endif /* if defined(USE_BACKTRACE) */
1466             abort();
1467           }
1468         start                    = state -> copy;
1469         state ->  statement_save = NULL;
1470       }
1471 
1472     int ret = -2; // error
1473 
1474     // grab every thing up to the next semicolon
1475     char * statement;
1476     statement = strtok_r (start, ";", & state -> statement_save);
1477     start = NULL;
1478     if (! statement)
1479       {
1480         ret = -1; // done
1481         goto done;
1482       }
1483 
1484     // extract name
1485     char * name_start = statement;
1486     char * name_save  = NULL;
1487     char * name;
1488     name = strtok_r (name_start, "=", & name_save);
1489     if (! name)
1490       {
1491         sim_printf ("error: %s: can't parse name\n", tag);
1492         goto done;
1493       }
1494 
1495     // lookup name
1496     config_list_t * p = clist;
1497     while (p -> name)
1498       {
1499         if (strcasecmp (name, p -> name) == 0)
1500           break;
1501         p ++;
1502       }
1503     if (! p -> name)
1504       {
1505         sim_printf ("error: %s: don't know name <%s>\n", tag, name);
1506         goto done;
1507       }
1508 
1509     // extract value
1510     char * value;
1511     value = strtok_r (NULL, "", & name_save);
1512     if (! value)
1513       {
1514         // Special case; min>max and no value list
1515         // means that a missing value is ok
1516         if (p -> min > p -> max && ! p -> value_list)
1517           {
1518             return (int) (p - clist);
1519           }
1520         sim_printf ("error: %s: can't parse value\n", tag);
1521         goto done;
1522       }
1523 
1524     // first look to value in the value list
1525     config_value_list_t * v = p -> value_list;
1526     if (v)
1527       {
1528         while (v -> value_name)
1529           {
1530             if (strcasecmp (value, v -> value_name) == 0)
1531               break;
1532             v ++;
1533           }
1534 
1535         // Hit?
1536         if (v -> value_name)
1537           {
1538             * result = v -> value;
1539             return (int) (p - clist);
1540           }
1541       }
1542 
1543     // Must be a number
1544     if (p -> min > p -> max)
1545       {
1546         sim_printf ("error: %s: can't parse value\n", tag);
1547         goto done;
1548       }
1549 
1550     if (strlen (value) == 0)
1551       {
1552          sim_printf ("error: %s: missing value\n", tag);
1553          goto done;
1554       }
1555     char * endptr;
1556     int64_t n = strtoll (value, & endptr, 0);
1557     if (* endptr)
1558       {
1559         sim_printf ("error: %s: can't parse value\n", tag);
1560         goto done;
1561       }
1562 
1563 // XXX small bug; doesn't check for junk after number...
1564     if (n < p -> min || n > p -> max)
1565       {
1566         sim_printf ("error: %s: value out of range\n", tag);
1567         goto done;
1568       }
1569 
1570     * result = n;
1571     return (int) (p - clist);
1572 
1573 done:
1574     FREE (state -> copy);
1575     state -> copy = NULL;
1576     return ret;
1577   }
1578 
1579 void cfg_parse_done (config_state_t * state)
     /* [previous][next][first][last][top][bottom][index][help] */
1580   {
1581     if (state -> copy)
1582       FREE (state -> copy);
1583     state -> copy = NULL;
1584   }
1585 
1586 // strdup with limited C-style escape processing
1587 //
1588 //  strdupesc ("foo\nbar") --> 'f' 'o' 'o' 012 'b' 'a' 'r'
1589 //
1590 //  Handles:
1591 //   \\  backslash
1592 //   \n  newline
1593 //   \t  tab
1594 //   \f  formfeed
1595 //   \r  carriage return
1596 //   \0  null              // doesn't work, commented out.
1597 //
1598 // \\ doesn't seem to work...
1599 //  Also, a scp specific:
1600 //
1601 //   \e  (end simulation)
1602 //
1603 //  the scp parser doesn't handle these very well...
1604 //
1605 //   \_  space
1606 //   \c  comma
1607 //   \s  semicolon
1608 //   \d  dollar
1609 //   \q  double quote
1610 //   \w  <backslash>
1611 //   \z  ^D eof (DECism)
1612 //   \^  caret
1613 //   \x  expect; used by the autoinput parser
1614 //
1615 // And a special case:
1616 //
1617 //   \TZ replaced with the timezone string. Three characters are used
1618 //       to allow for space in the buffer.
1619 //
1620 //  all others silently ignored and left unprocessed
1621 //
1622 
1623 char * strdupesc (const char * str)
     /* [previous][next][first][last][top][bottom][index][help] */
1624   {
1625     char * buf = strdup (str);
1626     if (!buf)
1627       {
1628         fprintf(stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1629                 __func__, __FILE__, __LINE__);
1630 #if defined(USE_BACKTRACE)
1631 # ifdef SIGUSR2
1632         (void)raise(SIGUSR2);
1633         /*NOTREACHED*/ /* unreachable */
1634 # endif /* ifdef SIGUSR2 */
1635 #endif /* if defined(USE_BACKTRACE) */
1636         abort();
1637       }
1638     char * p = buf;
1639     while (* p)
1640       {
1641         if (* p != '\\')
1642           {
1643             p ++;
1644             continue;
1645           }
1646         if (p [1] == '\\')           //   \\    backslash
1647           * p = '\\'; //-V1048
1648         else if (p [1] == 'a')       //   \a    ^A
1649           * p = '\001';
1650         else if (p [1] == 'w')       //   \w    backslash
1651           * p = '\\'; //-V1048
1652         else if (p [1] == 'n')       //   \n    newline
1653           * p = '\n';
1654         else if (p [1] == 't')       //  \t    tab
1655           * p = '\t';
1656         else if (p [1] == 'f')       //  \f    formfeed
1657           * p = '\f';
1658         else if (p [1] == 'r')       //  \r    carriage return
1659           * p = '\r';
1660         else if (p [1] == 'e')       //  \e    ^E; Multics escape char.
1661           * p = '\005';
1662         else if (p [1] == '_')       //  \_    space; needed for leading or
1663                                      //        trailing spaces (scp parser
1664                                      //        issue)
1665           * p = ' ';
1666         else if (p [1] == 'c')       //  \c    comma (scp parser issue)
1667           * p = ',';
1668         else if (p [1] == 's')       //  \s    semicolon (scp parser issue)
1669           * p = ';';
1670         else if (p [1] == 'd')       //  \d    dollar sign (scp parser issue)
1671           * p = '$';
1672         else if (p [1] == 'q')       //  \q    double quote (scp parser issue)
1673           * p = '"';
1674         else if (p [1] == 'z')       //  \z    ^D eof (VAXism)
1675           * p = '\004';
1676         else if (p [1] == 'k')       //  \k    caret
1677           * p = '^';
1678         else if (p [1] == 'x')       //  \x    expect
1679           * p = '\030';
1680         else if (p [1] == 'y')       //  \y    expect
1681           * p = '\031';
1682         //else if (p [1] == '0')       //  \0    null; used as end of expect string
1683           //* p = 0;
1684 
1685 
1686 
1687 
1688 
1689 
1690 
1691 
1692 
1693 
1694 
1695 
1696 
1697 
1698 
1699 
1700 
1701         else
1702           {
1703             p ++;
1704             continue;
1705           }
1706         p ++;
1707         memmove (p, p + 1, strlen (p + 1) + 1);
1708       }
1709     return buf;
1710   }
1711 
1712 // Layout of data as read from tape file format
1713 //
1714 //   bits: buffer of bits from tape. The data is
1715 //   packed as 2 36 bit words in 9 eight bit bytes
1716 //     (2 * 36 == 7 * 9)
1717 //   The of the bytes in bits is
1718 //      byte     value
1719 //       0       most significant byte in word 0
1720 //       1       2nd msb in word 0
1721 //       2       3rd msb in word 0
1722 //       3       4th msb in word 0
1723 //       4       upper half is 4 least significant bits in word 0
1724 //               lower half is 4 most significant bit in word 1
1725 //       5       5th to 13th most significant bits in word 1
1726 //       6       ...
1727 //       7       ...
1728 //       8       least significant byte in word 1
1729 //
1730 
1731 // Multics humor: this is idiotic
1732 
1733 // Data conversion routines
1734 //
1735 //  'bits' is the packed bit stream read from the tape
1736 //    it is assumed to start at an even word36 address
1737 //
1738 //   extr36
1739 //     extract the word36 at woffset
1740 //
1741 
1742 static word36 extrASCII36 (uint8 * bits, uint woffset)
     /* [previous][next][first][last][top][bottom][index][help] */
1743   {
1744     uint8 * p = bits + woffset * 4;
1745 
1746     uint64 w;
1747     w  = ((uint64) p [0]) << 27;
1748     w |= ((uint64) p [1]) << 18;
1749     w |= ((uint64) p [2]) << 9;
1750     w |= ((uint64) p [3]);
1751     // mask shouldn't be necessary but is robust
1752     return (word36) (w & MASK36);
1753   }
1754 
1755 // Data conversion routines
1756 //
1757 //  'bits' is the packed bit stream read from the tape
1758 //    it is assumed to start at an even word36 address
1759 //
1760 //   extr36
1761 //     extract the word36 at woffset
1762 //
1763 
1764 word36 extr36 (uint8 * bits, uint woffset)
     /* [previous][next][first][last][top][bottom][index][help] */
1765   {
1766     uint isOdd = woffset % 2;
1767     uint dwoffset = woffset / 2;
1768     uint8 * p = bits + dwoffset * 9;
1769 
1770     uint64 w;
1771     if (isOdd)
1772       {
1773         w  = (((uint64) p [4]) & 0xf) << 32;
1774         w |=  ((uint64) p [5]) << 24;
1775         w |=  ((uint64) p [6]) << 16;
1776         w |=  ((uint64) p [7]) << 8;
1777         w |=  ((uint64) p [8]);
1778       }
1779     else
1780       {
1781         w  =  ((uint64) p [0]) << 28;
1782         w |=  ((uint64) p [1]) << 20;
1783         w |=  ((uint64) p [2]) << 12;
1784         w |=  ((uint64) p [3]) << 4;
1785         w |= (((uint64) p [4]) >> 4) & 0xf;
1786       }
1787     // mask shouldn't be necessary but is robust
1788     return (word36) (w & MASK36);
1789   }
1790 
1791 static void putASCII36 (word36 val, uint8 * bits, uint woffset)
     /* [previous][next][first][last][top][bottom][index][help] */
1792   {
1793     uint8 * p = bits + woffset * 4;
1794     p [0]  = (val >> 27) & 0xff;
1795     p [1]  = (val >> 18) & 0xff;
1796     p [2]  = (val >>  9) & 0xff;
1797     p [3]  = (val      ) & 0xff;
1798   }
1799 
1800 void put36 (word36 val, uint8 * bits, uint woffset)
     /* [previous][next][first][last][top][bottom][index][help] */
1801   {
1802     uint isOdd = woffset % 2;
1803     uint dwoffset = woffset / 2;
1804     uint8 * p = bits + dwoffset * 9;
1805 
1806     if (isOdd)
1807       {
1808         p [4] &=               0xf0;
1809         p [4] |= (val >> 32) & 0x0f;
1810         p [5]  = (val >> 24) & 0xff;
1811         p [6]  = (val >> 16) & 0xff;
1812         p [7]  = (val >>  8) & 0xff;
1813         p [8]  = (val >>  0) & 0xff;
1814         //w  = ((uint64) (p [4] & 0xf)) << 32;
1815         //w |=  (uint64) (p [5]) << 24;
1816         //w |=  (uint64) (p [6]) << 16;
1817         //w |=  (uint64) (p [7]) << 8;
1818         //w |=  (uint64) (p [8]);
1819       }
1820     else
1821       {
1822         p [0]  = (val >> 28) & 0xff;
1823         p [1]  = (val >> 20) & 0xff;
1824         p [2]  = (val >> 12) & 0xff;
1825         p [3]  = (val >>  4) & 0xff;
1826         p [4] &=               0x0f;
1827         p [4] |= (val <<  4) & 0xf0;
1828         //w  =  (uint64) (p [0]) << 28;
1829         //w |=  (uint64) (p [1]) << 20;
1830         //w |=  (uint64) (p [2]) << 12;
1831         //w |=  (uint64) (p [3]) << 4;
1832         //w |= ((uint64) (p [4]) >> 4) & 0xf;
1833       }
1834     // mask shouldn't be necessary but is robust
1835   }
1836 
1837 int extractASCII36FromBuffer (uint8 * bufp, t_mtrlnt tbc, uint * words_processed, word36 *wordp)
     /* [previous][next][first][last][top][bottom][index][help] */
1838   {
1839     uint wp = * words_processed; // How many words have been processed
1840 
1841     // 1 dps8m word == 4 bytes
1842 
1843     uint bytes_processed = wp * 4;
1844     if (bytes_processed >= tbc)
1845       return 1;
1846     //sim_printf ("store 0%08lo@0%012"PRIo64"\n", wordp - M, extr36 (bufp, wp));
1847 
1848     * wordp = extrASCII36 (bufp, wp);
1849     //if (* wordp & ~MASK36) sim_printf (">>>>>>> extr %012"PRIo64"\n", * wordp);
1850     //sim_printf ("* %06lo = %012"PRIo64"\n", wordp - M, * wordp);
1851     (* words_processed) ++;
1852 
1853     return 0;
1854   }
1855 
1856 int extractWord36FromBuffer (uint8 * bufp, t_mtrlnt tbc, uint * words_processed, word36 *wordp)
     /* [previous][next][first][last][top][bottom][index][help] */
1857   {
1858     uint wp = * words_processed; // How many words have been processed
1859 
1860     // 2 dps8m words == 9 bytes
1861 
1862     uint bytes_processed = (wp * 9 + 1) / 2;
1863     if (bytes_processed >= tbc)
1864       return 1;
1865     //sim_printf ("store 0%08lo@0%012"PRIo64"\n", wordp - M, extr36 (bufp, wp));
1866 
1867     * wordp = extr36 (bufp, wp);
1868     //if (* wordp & ~MASK36) sim_printf (">>>>>>> extr %012"PRIo64"\n", * wordp);
1869     //sim_printf ("* %06lo = %012"PRIo64"\n", wordp - M, * wordp);
1870     (* words_processed) ++;
1871 
1872     return 0;
1873   }
1874 
1875 int insertASCII36toBuffer (uint8 * bufp, t_mtrlnt tbc, uint * words_processed, word36 word)
     /* [previous][next][first][last][top][bottom][index][help] */
1876   {
1877     uint wp = * words_processed; // How many words have been processed
1878 
1879     // 1 dps8m word == 4 bytes
1880 
1881     uint bytes_processed = wp * 4;
1882     if (bytes_processed >= tbc)
1883       return 1;
1884     //sim_printf ("store 0%08lo@0%012"PRIo64"\n", wordp - M, extr36 (bufp, wp));
1885 
1886     putASCII36 (word, bufp, wp);
1887     //sim_printf ("* %06lo = %012"PRIo64"\n", wordp - M, * wordp);
1888     (* words_processed) ++;
1889 
1890     return 0;
1891   }
1892 
1893 int insertWord36toBuffer (uint8 * bufp, t_mtrlnt tbc, uint * words_processed, word36 word)
     /* [previous][next][first][last][top][bottom][index][help] */
1894   {
1895     uint wp = * words_processed; // How many words have been processed
1896 
1897     // 2 dps8m words == 9 bytes
1898 
1899     uint bytes_processed = (wp * 9 + 1) / 2;
1900     if (bytes_processed >= tbc)
1901       return 1;
1902     //sim_printf ("store 0%08lo@0%012"PRIo64"\n", wordp - M, extr36 (bufp, wp));
1903 
1904     put36 (word, bufp, wp);
1905     //sim_printf ("* %06lo = %012"PRIo64"\n", wordp - M, * wordp);
1906     (* words_processed) ++;
1907 
1908     return 0;
1909   }
1910 
1911 #ifndef NEED_128
1912 static void print_uint128o_r (uint128 n, char * p)
     /* [previous][next][first][last][top][bottom][index][help] */
1913   {
1914     if (n == 0)
1915       return;
1916 
1917     print_uint128o_r(n / 8, p);
1918     if (p)
1919       {
1920         char s [2];
1921         s [0] = n % 8 + '0';
1922         s [1] = '\0';
1923         strcat (p, s);
1924       }
1925     else
1926       sim_printf("%c", (int) (n%8+0x30));
1927   }
1928 
1929 char * print_int128o (int128 n, char * p)
     /* [previous][next][first][last][top][bottom][index][help] */
1930   {
1931     if (n == 0)
1932       {
1933         if (p)
1934           strcat (p, "0");
1935         else
1936           sim_printf ("0");
1937         return p;
1938       }
1939     print_uint128o_r ((uint128) n, p);
1940     return p;
1941   }
1942 
1943 static void print_uint128_r (uint128 n, char * p)
     /* [previous][next][first][last][top][bottom][index][help] */
1944   {
1945     if (n == 0)
1946       return;
1947 
1948     print_uint128_r(n / 10, p);
1949     if (p)
1950       {
1951         char s [2];
1952         s [0] = n % 10 + '0';
1953         s [1] = '\0';
1954         strcat (p, s);
1955       }
1956     else
1957       sim_printf("%c", (int) (n%10+0x30));
1958   }
1959 
1960 void print_int128 (int128 n, char * p)
     /* [previous][next][first][last][top][bottom][index][help] */
1961   {
1962     if (n == 0)
1963       {
1964         if (p)
1965           strcat (p, "0");
1966         else
1967           sim_printf ("0");
1968         return;
1969       }
1970     if (n < 0)
1971       {
1972         if (p)
1973           strcat (p, "-");
1974         else
1975           sim_printf ("-");
1976         n = -n;
1977       }
1978     print_uint128_r ((uint128) n, p);
1979   }
1980 #endif
1981 
1982 void timespec_diff(struct timespec * start, struct timespec * stop,
     /* [previous][next][first][last][top][bottom][index][help] */
1983                    struct timespec * result)
1984 {
1985     if ((stop->tv_nsec - start->tv_nsec) < 0) {
1986         result->tv_sec = stop->tv_sec - start->tv_sec - 1;
1987         result->tv_nsec = stop->tv_nsec - start->tv_nsec + 1000000000L;
1988     } else {
1989         result->tv_sec = stop->tv_sec - start->tv_sec;
1990         result->tv_nsec = stop->tv_nsec - start->tv_nsec;
1991     }
1992 
1993     return;
1994 }
1995 
1996 
1997 
1998 
1999 
2000 
2001 
2002 
2003 
2004 
2005 
2006 
2007 
2008 
2009 
2010 
2011 
2012 
2013 
2014 
2015 
2016 
2017 
2018 
2019 
2020 
2021 
2022 
2023 
2024 
2025 
2026 
2027 
2028 

/* [previous][next][first][last][top][bottom][index][help] */