root/src/dps8/dps8.h

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

INCLUDED FROM


   1 /*
   2  * vim: filetype=c:tabstop=4:ai:expandtab
   3  * SPDX-License-Identifier: ICU
   4  * scspell-id: 6965b612-f62e-11ec-a432-80ee73e9b8e7
   5  *
   6  * ---------------------------------------------------------------------------
   7  *
   8  * Copyright (c) 2012-2016 Harry Reed
   9  * Copyright (c) 2012 Dave Jordan
  10  * Copyright (c) 2013-2018 Charles Anthony
  11  * Copyright (c) 2016 Jean-Michel Merliot
  12  * Copyright (c) 2021-2022 The DPS8M Development Team
  13  *
  14  * All rights reserved.
  15  *
  16  * This software is made available under the terms of the ICU
  17  * License, version 1.8.1 or later.  For more details, see the
  18  * LICENSE.md file at the top-level directory of this distribution.
  19  *
  20  * ---------------------------------------------------------------------------
  21  */
  22 
  23 #ifndef DPS8_H
  24 # define DPS8_H
  25 
  26 # include <stdio.h>
  27 # include <stdbool.h>
  28 # include <errno.h>
  29 # include <inttypes.h>
  30 # include <sys/stat.h>
  31 # include <sys/time.h>
  32 # include <setjmp.h>  // for setjmp/longjmp used by interrupts & faults
  33 
  34 # if (defined(__APPLE__) && defined(__MACH__)) || defined(__ANDROID__)
  35 #  include <libgen.h>  // needed for macOS and Android
  36 # endif
  37 
  38 typedef int64_t __int64_t;
  39 
  40 # ifdef NEED_128
  41 typedef struct { uint64_t h; uint64_t l; } x__uint128_t;
  42 typedef struct { int64_t h;  uint64_t l; } x__int128_t;
  43 #  define construct_128(h, l) ((uint128) { (h), (l) })
  44 #  define construct_s128(h, l) ((int128) { (h), (l) })
  45 # endif /* ifdef NEED_128 */
  46 
  47 // Quiet compiler unused warnings
  48 # define QUIET_UNUSED
  49 
  50 // Enable speed over debugging if not TESTING
  51 # ifndef TESTING
  52 #  define SPEED
  53 # endif /* ifndef TESTING */
  54 
  55 // Experimental dial_out line disconnect delay
  56 // FNP polled ~100Hz; 2 secs. is 200 polls
  57 # define DISC_DELAY 200
  58 
  59 //
  60 // Dependencies
  61 //
  62 
  63 # ifdef PANEL68
  64 #  define PNL(x) x
  65 # else
  66 #  define PNL(x)
  67 # endif
  68 
  69 # define L68_(x) if (cpu.tweaks.l68_mode) { x }
  70 # define DPS8M_(x) if (! cpu.tweaks.l68_mode) { x }
  71 
  72 // Debugging tool
  73 # ifdef TESTING
  74 #  define IF1 if (cpu.tweaks.isolts_mode)
  75 # else
  76 #  define IF1 if (0)
  77 # endif
  78 
  79 // DPS8-M supports Hex Mode Floating Point
  80 # define HEX_MODE
  81 
  82 // Instruction profiler
  83 // #define MATRIX
  84 
  85 // Run TR on work done, not wall clock.
  86 // Define one of these; tied to memory access (MEM) or to instruction
  87 // execution (EXEC)
  88 
  89 //#define TR_WORK_MEM
  90 # define TR_WORK_EXEC
  91 
  92 // Multi-threading may require 'volatile' in some places
  93 # if defined(THREADZ) || defined(LOCKLESS)
  94 #  define vol volatile
  95 # else
  96 #  define vol
  97 # endif
  98 
  99 # ifndef NEED_128
 100 #  ifdef PRIu64
 101 #   undef PRIu64
 102 #  endif
 103 #  ifndef PRIu64
 104 #   define PRIu64 "llu"
 105 #  endif
 106 #  ifdef PRId64
 107 #   undef PRId64
 108 #  endif
 109 #  ifndef PRId64
 110 #   define PRId64 "lld"
 111 #  endif
 112 #  ifdef PRIo64
 113 #   undef PRIo64
 114 #  endif
 115 #  ifndef PRIo64
 116 #   ifdef __HAIKU__
 117 #    define PRIo64 "lo"
 118 #    undef llo
 119 #    define llo "lo"
 120 #   else
 121 #    define PRIo64 "llo"
 122 #   endif
 123 #  endif
 124 # endif
 125 
 126 # include "sim_defs.h"                                   /* simulator defns */
 127 # include "sim_tape.h"
 128 
 129 // patch supplied by Dave Jordan (jordandave@gmail.com) 29 Nov 2012
 130 # ifdef __MINGW32__
 131 #  include <stdint.h>
 132 typedef t_uint64    u_int64_t;
 133 # endif
 134 # ifdef __HAIKU__
 135 #  include <stdint.h>
 136 typedef long int64;
 137 typedef unsigned long uint64;
 138 # endif
 139 # ifndef __HAIKU__
 140 typedef t_uint64    uint64;
 141 # endif
 142 # ifndef _AIX
 143 #  ifndef __HAIKU__
 144 typedef t_int64     int64;
 145 #  endif
 146 # else
 147 typedef long        int64;
 148 # endif
 149 
 150 /* Data types */
 151 
 152 typedef uint8        word1;
 153 typedef uint8        word2;
 154 typedef uint8        word3;
 155 typedef uint8        word4;
 156 typedef uint8        word5;
 157 typedef uint8        word6;
 158 typedef uint8        word7;
 159 typedef uint8        word8;
 160 typedef int8         word8s; // signed 8-bit quantity
 161 typedef uint16       word9;
 162 typedef uint16       word10;
 163 typedef uint16       word11;
 164 typedef uint16       word12;
 165 typedef int16        word12s;
 166 typedef uint16       word13;
 167 typedef uint16       word14;
 168 typedef uint16       word15;
 169 typedef uint16       word16;
 170 typedef uint32       word17;
 171 typedef uint32       word18;
 172 typedef uint32       word19;
 173 typedef int32        word18s;
 174 typedef uint32       word20;
 175 typedef int32        word20s;
 176 typedef uint32       word21;
 177 typedef uint32       word22;
 178 typedef uint32       word23;
 179 typedef uint32       word24;
 180 typedef uint32       word27;
 181 typedef int32        word27s;
 182 typedef uint32       word28;
 183 typedef uint32       word32;
 184 typedef uint64       word34;
 185 typedef uint64       word36;
 186 typedef uint64       word37;
 187 typedef uint64       word38;
 188 typedef int64        word38s;
 189 typedef int64        word36s;
 190 # ifndef NEED_128
 191 typedef __uint128_t  word72;
 192 typedef __int128_t   word72s;
 193 typedef __uint128_t  word73;
 194 typedef __uint128_t  word74;
 195 typedef __uint128_t  uint128;
 196 typedef __int128_t   int128;
 197 # else
 198 typedef x__uint128_t word72;
 199 typedef x__int128_t  word72s;
 200 typedef x__uint128_t word73;
 201 typedef x__uint128_t word74;
 202 typedef x__uint128_t uint128;
 203 typedef x__int128_t  int128;
 204 # endif
 205 
 206 typedef word36       float36;   // single precision float
 207 typedef word72       float72;   // double precision float
 208 
 209 typedef unsigned int uint;   //-V677   // efficient unsigned int, at least 32 bits
 210 
 211 # include "dps8_simh.h"
 212 # include "dps8_sys.h"
 213 # include "dps8_math128.h"
 214 # include "dps8_hw_consts.h"
 215 # include "dps8_em_consts.h"
 216 
 217 # define SETF(flags, x)       flags = ((flags) |  (x))
 218 # define CLRF(flags, x)       flags = ((flags) & ~(x))
 219 # define TSTF(flags, x)       (((flags) & (x)) ? 1 : 0)
 220 # define SCF(cond, flags, x)  { if (cond) SETF((flags), x); else CLRF((flags), x); }
 221 
 222 # define SETBIT(dst, bitno)   ((dst)  |  (1LLU << (bitno)))
 223 # define CLRBIT(dst, bitno)   ((dst)  & ~(1LLU << (bitno)))
 224 # define TSTBIT(dst, bitno)   (((dst) &  (1LLU << (bitno))) ? 1: 0)
 225 
 226 typedef enum
 227   {
 228     UNKNOWN_CYCLE = 0,
 229     OPERAND_STORE,
 230     OPERAND_READ,
 231     INDIRECT_WORD_FETCH,
 232     RTCD_OPERAND_FETCH,
 233     INSTRUCTION_FETCH,
 234     APU_DATA_READ,
 235     APU_DATA_STORE,
 236     ABSA_CYCLE,
 237 # ifdef LOCKLESS
 238     OPERAND_RMW,
 239     APU_DATA_RMW,
 240 # endif
 241   } processor_cycle_type;
 242 
 243 # ifndef LOCKLESS
 244 #  define OPERAND_RMW   OPERAND_READ
 245 #  define APU_DATA_RMW  APU_DATA_READ
 246 # endif
 247 
 248 # ifndef EIS_PTR4
 249 // some breakpoint stuff ...
 250 typedef enum
 251   {
 252     UnknownMAT       = 0,
 253     OperandRead,
 254     OperandWrite,
 255     viaPR
 256   } MemoryAccessType;
 257 # endif
 258 
 259 // get 6-bit char @ pos
 260 # define GETCHAR(src, pos) (word6)(((word36)src >> (word36)((5 - pos) * 6)) & 077)
 261 // get 9-bit byte @ pos
 262 # define GETBYTE(src, pos) (word9)(((word36)src >> (word36)((3 - pos) * 9)) & 0777)
 263 
 264 # ifdef NEED_128
 265 #  define YPAIRTO72(ypair) construct_128 ((ypair[0] >> 28) & MASK8,    \
 266                                          ((ypair[0] & MASK28) << 36) | \
 267                                           (ypair[1] & MASK36));
 268 # else
 269 #  define YPAIRTO72(ypair)    (((((word72)(ypair[0] & DMASK)) << 36) | \
 270                                           (ypair[1] & DMASK)) & MASK72)
 271 # endif
 272 
 273 # define GET_TALLY(src) (((src) >> 6) & MASK12)   // 12-bits
 274 # define GET_DELTA(src)  ((src) & MASK6)          // 6-bits
 275 
 276 # ifndef max
 277 #  define max(a,b)   max2((a),(b))
 278 # endif
 279 # define max2(a,b)   ((a) > (b) ? (a) : (b))
 280 # define max3(a,b,c) max((a), max((b),(c)))
 281 
 282 # ifndef min
 283 #  define min(a,b)   min2((a),(b))
 284 # endif
 285 # define min2(a,b)   ((a) < (b) ? (a) : (b))
 286 # define min3(a,b,c) min((a), min((b),(c)))
 287 
 288 // opcode metadata (flag) ...
 289 typedef enum
 290   {
 291     READ_OPERAND    = (1U <<  0),  // fetches/reads operand (CA) from memory
 292     STORE_OPERAND   = (1U <<  1),  // stores/writes operand to memory (its a STR-OP)
 293 # define RMW             (READ_OPERAND | STORE_OPERAND) // a Read-Modify-Write instruction
 294     READ_YPAIR      = (1U <<  2),  // fetches/reads Y-pair operand (CA) from memory
 295     STORE_YPAIR     = (1U <<  3),  // stores/writes Y-pair operand to memory
 296     READ_YBLOCK8    = (1U <<  4),  // fetches/reads Y-block8 operand (CA) from memory
 297     NO_RPT          = (1U <<  5),  // Repeat instructions not allowed
 298 //#define NO_RPD          (1U << 6)
 299     NO_RPL          = (1U <<  7),
 300 //#define NO_RPX          (NO_RPT | NO_RPD | NO_RPL)
 301     READ_YBLOCK16   = (1U <<  8),  // fetches/reads Y-block16 operands from memory
 302     STORE_YBLOCK16  = (1U <<  9),  // fetches/reads Y-block16 operands from memory
 303     TRANSFER_INS    = (1U << 10),  // a transfer instruction
 304     TSPN_INS        = (1U << 11),  // a TSPn instruction
 305     CALL6_INS       = (1U << 12),  // a call6 instruction
 306     PREPARE_CA      = (1U << 13),  // prepare TPR.CA for instruction
 307     STORE_YBLOCK8   = (1U << 14),  // stores/writes Y-block8 operand to memory
 308     IGN_B29         = (1U << 15),  // Bit-29 has an instruction specific meaning. Ignore.
 309     NO_TAG          = (1U << 16),  // tag is interpreted differently and for addressing purposes is effectively 0
 310     PRIV_INS        = (1U << 17),  // privileged instruction
 311     NO_BAR          = (1U << 18),  // not allowed in BAR mode
 312 //  NO_XEC          = (1U << 19),  // can't be executed via xec/xed
 313     NO_XED          = (1U << 20),  // No execution via XEC/XED instruction
 314 
 315 // EIS operand types
 316 
 317 # define EOP_ALPHA 1U
 318 
 319 // bits 21, 22
 320     EOP1_ALPHA      = (EOP_ALPHA << 21),
 321     EOP1_MASK       = (3U << 21),
 322 # define EOP1_SHIFT 21
 323 
 324 // bits 23, 24
 325     EOP2_ALPHA      = (EOP_ALPHA << 23),
 326     EOP2_MASK       = (3U << 23),
 327 # define EOP2_SHIFT 23
 328 
 329 // bits 25, 26
 330     EOP3_ALPHA      = (EOP_ALPHA << 25),
 331     EOP3_MASK       = (3U << 25),
 332 # define EOP3_SHIFT 25
 333 
 334     READ_YBLOCK32   = (1U << 27),  // fetches/reads Y-block16 operands from memory
 335     STORE_YBLOCK32  = (1U << 28),  // fetches/reads Y-block16 operands from memory
 336   } opc_flag;
 337 
 338 // opcode metadata (disallowed) modifications
 339 enum opc_mod
 340   {
 341     NO_DU           = (1U << 0),   // No DU modification allowed (Can these 2 be combined into 1?)
 342     NO_DL           = (1U << 1),   // No DL modification allowed
 343 # define NO_DUDL    (NO_DU | NO_DL)
 344 
 345     NO_CI           = (1U << 2),   // No character indirect modification (can these next 3 be combined?_
 346     NO_SC           = (1U << 3),   // No sequence character modification
 347     NO_SCR          = (1U << 4),   // No sequence character reverse modification
 348 # define NO_CSS     (NO_CI | NO_SC | NO_SCR)
 349 
 350 # define NO_DLCSS   (NO_DU   | NO_CSS)
 351 # define NO_DDCSS   (NO_DUDL | NO_CSS)
 352 
 353     ONLY_AU_QU_AL_QL_XN = (1U << 5)    // None except au, qu, al, ql, xn
 354   };
 355 
 356 // None except au, qu, al, ql, xn for MF1 and REG
 357 // None except du, au, qu, al, ql, xn for MF2
 358 // None except au, qu, al, ql, xn for MF1, MF2, and MF3
 359 
 360 # define IS_NONE(tag) (!(tag))
 361 /*! non-tally: du or dl */
 362 # define IS_DD(tag) ((_TM(tag) != 040U) && \
 363     ((_TD(tag) == 003U) || (_TD(tag) == 007U)))
 364 /*! tally: ci, sc, or scr */
 365 # define IS_CSS(tag) ((_TM(tag) == 040U) && \
 366     ((_TD(tag) == 050U) || (_TD(tag) == 052U) || \
 367     (_TD(tag) == 045U)))
 368 # define IS_DDCSS(tag) (IS_DD(tag) || IS_CSS(tag))
 369 /*! just dl or css */
 370 # define IS_DCSS(tag) (((_TM(tag) != 040U) && (_TD(tag) == 007U)) || IS_CSS(tag))
 371 
 372 // !%WRD  ~0200000  017
 373 // !%9    ~0100000  027
 374 // !%6    ~0040000  033
 375 // !%4    ~0020000  035
 376 // !%1    ~0010000  036
 377 enum reg_use { is_WRD =  0174000,
 378                is_9  =   0274000,
 379                is_6  =   0334000,
 380                is_4  =   0354000,
 381                is_1  =   0364000,
 382                is_DU =   04000,
 383                is_OU =   02000,
 384                ru_A  =   02000 | 01000,
 385                ru_Q  =   02000 |  0400,
 386                ru_X0 =   02000 |  0200,
 387                ru_X1 =   02000 |  0100,
 388                ru_X2 =   02000 |   040,
 389                ru_X3 =   02000 |   020,
 390                ru_X4 =   02000 |   010,
 391                ru_X5 =   02000 |    04,
 392                ru_X6 =   02000 |    02,
 393                ru_X7 =   02000 |    01,
 394                ru_none = 02000 |     0 };
 395 //, ru_notou = 1024 };
 396 
 397 # define ru_AQ (ru_A | ru_Q)
 398 # define ru_Xn(n) (1 << (7 - (n)))
 399 
 400 // Basic + EIS opcodes .....
 401 struct opcode_s {
 402     const char *mne;       // mnemonic
 403     opc_flag flags;        // various and sundry flags
 404     enum opc_mod mods;          // disallowed addr mods
 405     uint ndes;             // number of operand descriptor words for instruction (mw EIS)
 406     enum reg_use reg_use;  // register usage
 407 };
 408 
 409 // operations stuff
 410 
 411 /*! Y of instruc word */
 412 # define Y(i) (i & MASKHI18)
 413 /*! X from opcodes in instruc word */
 414 # define OPSX(i) ((i & 0007000LLU) >> 9)
 415 /*! X from OP_* enum, and X from  */
 416 # define X(i) (i & 07U)
 417 
 418 enum { OP_1     = 00001U,
 419     OP_E        = 00002U,
 420     OP_BAR      = 00003U,
 421     OP_IC       = 00004U,
 422     OP_A        = 00005U,
 423     OP_Q        = 00006U,
 424     OP_AQ       = 00007U,
 425     OP_IR       = 00010U,
 426     OP_TR       = 00011U,
 427     OP_REGS     = 00012U,
 428 
 429     /* 645/6180 */
 430     OP_CPR      = 00021U,
 431     OP_DBR      = 00022U,
 432     OP_PTP      = 00023U,
 433     OP_PTR      = 00024U,
 434     OP_RA       = 00025U,
 435     OP_SDP      = 00026U,
 436     OP_SDR      = 00027U,
 437 
 438     OP_X        = 01000U
 439 };
 440 
 441 enum eCAFoper {
 442     unknown = 0,
 443     readCY,
 444     writeCY,
 445     rmwCY,      // Read-Modify-Write
 446 //    readCYpair,
 447 //    writeCYpair,
 448 //    readCYblock8,
 449 //    writeCYblock8,
 450 //    readCYblock16,
 451 //    writeCYblock16,
 452 
 453     prepareCA,
 454 };
 455 typedef enum eCAFoper eCAFoper;
 456 
 457 # define READOP(i) ((bool) (i->info->flags    &  \
 458                            (READ_OPERAND      |  \
 459                             READ_YPAIR        |  \
 460                             READ_YBLOCK8      |  \
 461                             READ_YBLOCK16     |  \
 462                             READ_YBLOCK32)))
 463 
 464 # define WRITEOP(i) ((bool) (i->info->flags   &  \
 465                             (STORE_OPERAND    |  \
 466                              STORE_YPAIR      |  \
 467                              STORE_YBLOCK8    |  \
 468                              STORE_YBLOCK16   |  \
 469                              STORE_YBLOCK32)))
 470 
 471 // if it's both read and write it's a RMW
 472 # define RMWOP(i) ((bool) READOP(i) && WRITEOP(i))
 473 
 474 # define TRANSOP(i) ((bool) (i->info->flags & (TRANSFER_INS) ))
 475 
 476 //
 477 // EIS stuff ...
 478 //
 479 
 480 // Numeric operand descriptors
 481 
 482 // AL39 Table 4-3. Alphanumeric Data Type (TA) Codes
 483 enum
 484   {
 485     CTA9   = 0U, // 9-bit bytes
 486     CTA6   = 1U, // 6-bit characters
 487     CTA4   = 2U, // 4-bit decimal
 488     CTAILL = 3U  // Illegal
 489   };
 490 
 491 // TN - Type Numeric AL39 Table 4-3. Alphanumeric Data Type (TN) Codes
 492 enum
 493   {
 494     CTN9 = 0U,   // 9-bit
 495     CTN4 = 1U    // 4-bit
 496   };
 497 
 498 // S - Sign and Decimal Type (AL39 Table 4-4. Sign and Decimal Type (S) Codes)
 499 
 500 enum
 501   {
 502     CSFL = 0U,   // Floating-point, leading sign
 503     CSLS = 1U,   // Scaled fixed-point, leading sign
 504     CSTS = 2U,   // Scaled fixed-point, trailing sign
 505     CSNS = 3U    // Scaled fixed-point, unsigned
 506   };
 507 
 508 enum
 509   {
 510     // Address register flag. This flag controls interpretation of the ADDRESS
 511     // field of the operand descriptor just as the "A" flag controls
 512     // interpretation of the ADDRESS field of the basic and EIS single-word
 513     // instructions.
 514     MFkAR = 0x40U,
 515     // Register length control. If RL = 0, then the length (N) field of the
 516     // operand descriptor contains the length of the operand. If RL = 1, then
 517     // the length (N) field of the operand descriptor contains a selector value
 518     // specifying a register holding the operand length. Operand length is
 519     // interpreted as units of the data size (1-, 4-, 6-, or 9-bit) given in
 520     // the associated operand descriptor.
 521     MFkRL = 0x20U,
 522     // Indirect descriptor control. If ID = 1 for Mfk, then the kth word
 523     // following the instruction word is an indirect pointer to the operand
 524     // descriptor for the kth operand; otherwise, that word is the operand
 525     // descriptor.
 526     MFkID = 0x10U,
 527 
 528     MFkREGMASK = 0xfU
 529   };
 530 
 531 // EIS instruction take on a life of their own. Need to take into account
 532 // RNR/SNR/BAR etc.
 533 typedef enum
 534   {
 535     eisUnknown = 0,  // uninitialized
 536     eisTA      = 1,  // type alphanumeric
 537     eisTN      = 2,  // type numeric
 538     eisBIT     = 3   // bit string
 539   } eisDataType;
 540 
 541 typedef enum
 542   {
 543     eRWreadBit = 0,
 544     eRWwriteBit
 545   } eRW;
 546 
 547 // Misc constants and macros
 548 
 549 # define ARRAY_SIZE(a) ( sizeof(a) / sizeof((a)[0]) )
 550 
 551 # undef FREE
 552 # ifdef TESTING
 553 #  define FREE(p) free(p)
 554 # else
 555 #  define FREE(p) do  \
 556   {                   \
 557     free((p));        \
 558     (p) = NULL;       \
 559   } while(0)
 560 # endif /* ifdef TESTING */
 561 
 562 # if defined (__MINGW64__) || \
 563     defined (__MINGW32__)  || \
 564     defined (__GNUC__)     || \
 565     defined (__clang_version__)
 566 #  define NO_RETURN __attribute__ ((noreturn))
 567 #  define UNUSED    __attribute__ ((unused))
 568 # else
 569 #  define NO_RETURN
 570 #  define UNUSED
 571 # endif
 572 
 573 # define MAX_DEV_NAME_LEN 64
 574 
 575 // TESTING realloc wrapper function
 576 # ifdef TESTING
 577 void * trealloc(void *ptr, size_t size);
 578 # endif /* ifdef TESTING */
 579 
 580 // Basic STDIO for MinGW
 581 # ifndef __CYGWIN__
 582 #  if defined( __MINGW32__ ) || defined( __MINGW64__ ) || defined( CROSS_MINGW32 ) || defined( CROSS_MINGW64 )
 583 #   define WIN_STDIO    1
 584 #  endif /* if defined( __MINGW32__ ) || defined( __MINGW64__ ) || defined( CROSS_MINGW32 ) || defined( CROSS_MINGW64 ) */
 585 # endif /* ifndef __CYGWIN__ */
 586 
 587 #endif // ifdef DPS8_H

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