1 /* 2 * Copyright (c) 2012-2016 Harry Reed 3 * Copyright (c) 2012 Dave Jordan 4 * Copyright (c) 2013-2018 Charles Anthony 5 * Copyright (c) 2016 Jean-Michel Merliot 6 * Copyright (c) 2021 The DPS8M Development Team 7 * 8 * All rights reserved. 9 * 10 * This software is made available under the terms of the ICU 11 * License, version 1.8.1 or later. For more details, see the 12 * LICENSE.md file at the top-level directory of this distribution. 13 */ 14 15 #ifndef DPS8_H 16 # define DPS8_H 17 18 # include <stdio.h> 19 # include <stdbool.h> 20 # include <errno.h> 21 # include <inttypes.h> 22 # include <sys/stat.h> 23 # include <sys/time.h> 24 # include <setjmp.h> // for setjmp/longjmp used by interrupts & faults 25 26 # if (defined(__APPLE__) && defined(__MACH__)) || defined(__ANDROID__) 27 # include <libgen.h> // needed for OS/X and Android 28 # endif 29 30 # ifndef L68 31 # ifndef DPS8M 32 # define DPS8M 33 # endif 34 # endif 35 36 # ifdef NEED_128 37 typedef struct { uint64_t h; uint64_t l; } __uint128_t; 38 typedef struct { int64_t h; uint64_t l; } __int128_t; 39 # define construct_128(h, l) ((uint128) { (h), (l) }) 40 # define construct_s128(h, l) ((int128) { (h), (l) }) 41 # endif /* ifdef NEED_128 */ 42 43 // Quiet compiler unused warnings 44 # define QUIET_UNUSED 45 46 # ifndef TESTING 47 // Enable speed over debugging if not TESTING 48 # define SPEED 49 # endif /* ifndef TESTING */ 50 51 // Enable round-robin multi-CPU 52 //#define ROUND_ROBIN 53 54 // Experimential dial_out line disconnect delay 55 // FNP polled ~100Hz; 2 secs. is 200 polls 56 # define DISC_DELAY 200 57 58 // 59 // Dependencies 60 // 61 62 // PANEL only works on L68 63 # ifdef PANEL 64 # ifdef DPS8M 65 # error "PANEL works with L68, not DPS8M" 66 # endif 67 # ifndef L68 68 # define L68 69 # endif 70 # endif 71 72 # ifdef PANEL 73 # define PNL(x) x 74 # else 75 # define PNL(x) 76 # endif 77 78 # ifdef L68 79 # define L68_(x) x 80 # else 81 # define L68_(x) 82 # endif 83 84 # ifdef DPS8M 85 # define DPS8M_(x) x 86 # else 87 # define DPS8M_(x) 88 # endif 89 90 // debugging tool 91 # ifdef TESTING 92 # define IF1 if (cpu.switches.isolts_mode) 93 # else 94 # define IF1 if (0) 95 # endif 96 97 //#define OSCAR 98 99 // DPS8-M support Hex Mode Floating Point 100 # ifdef DPS8M 101 # define HEX_MODE 102 # endif 103 104 // Instruction profiler 105 // #define MATRIX 106 107 // Run TR on work done, not wall clock. 108 // Define one of these; tied to memory access (MEM) or to instruction 109 // execution (EXEC) 110 111 //#define TR_WORK_MEM 112 # define TR_WORK_EXEC 113 114 // Multi-threading may require 'volatile' in some place; make it easy 115 // to support both configurations 116 117 # if defined(THREADZ) || defined(LOCKLESS) 118 # define vol volatile 119 # else 120 # define vol 121 # endif 122 123 # ifndef NEED_128 124 # ifdef PRIu64 125 # undef PRIu64 126 # endif 127 # ifndef PRIu64 128 # define PRIu64 "llu" 129 # endif 130 # ifdef PRId64 131 # undef PRId64 132 # endif 133 # ifndef PRId64 134 # define PRId64 "lld" 135 # endif 136 # ifdef PRIo64 137 # undef PRIo64 138 # endif 139 # ifndef PRIo64 140 # define PRIo64 "llo" 141 # endif 142 # endif 143 144 # include "sim_defs.h" /* simulator defns */ 145 # include "sim_tape.h" 146 147 // patch supplied by Dave Jordan (jordandave@gmail.com) 29 Nov 2012 148 # ifdef __MINGW32__ 149 # include <stdint.h> 150 typedef t_uint64 u_int64_t; 151 # endif 152 typedef t_uint64 uint64; 153 # ifndef _AIX 154 typedef t_int64 int64; 155 # else 156 typedef long int64; 157 # endif 158 159 /* Data types */ 160 161 typedef uint8 word1; 162 typedef uint8 word2; 163 typedef uint8 word3; 164 typedef uint8 word4; 165 typedef uint8 word5; 166 typedef uint8 word6; 167 typedef uint8 word7; 168 typedef uint8 word8; 169 typedef int8 word8s; // signed 8-bit quantity 170 typedef uint16 word9; 171 typedef uint16 word10; 172 typedef uint16 word11; 173 typedef uint16 word12; 174 typedef uint16 word13; 175 typedef uint16 word14; 176 typedef uint16 word15; 177 typedef uint16 word16; 178 typedef uint32 word17; 179 typedef uint32 word18; 180 typedef uint32 word19; 181 typedef int32 word18s; 182 typedef uint32 word20; 183 typedef uint32 word21; 184 typedef uint32 word22; 185 typedef uint32 word23; 186 typedef uint32 word24; 187 typedef uint32 word27; 188 typedef uint32 word28; 189 typedef uint32 word32; 190 typedef uint64 word34; 191 typedef uint64 word36; 192 typedef uint64 word37; 193 typedef uint64 word38; 194 typedef int64 word36s; 195 typedef __uint128_t word72; 196 typedef __int128_t word72s; 197 typedef __uint128_t word73; 198 typedef __uint128_t word74; 199 200 typedef __uint128_t uint128; 201 typedef __int128_t int128; 202 203 typedef word36 float36; // single precision float 204 typedef word72 float72; // double precision float 205 206 typedef unsigned int uint; // efficient unsigned int, at least 32 bits 207 208 # include "dps8_simh.h" 209 # include "dps8_sys.h" 210 # include "dps8_math128.h" 211 # include "dps8_hw_consts.h" 212 # include "dps8_em_consts.h" 213 214 215 # define SETF(flags, x) flags = ((flags) | (x)) 216 # define CLRF(flags, x) flags = ((flags) & ~(x)) 217 # define TSTF(flags, x) (((flags) & (x)) ? 1 : 0) 218 # define SCF(cond, flags, x) { if (cond) SETF((flags), x); else CLRF((flags), x); } 219 220 # define SETBIT(dst, bitno) ((dst) | (1LLU << (bitno))) 221 # define CLRBIT(dst, bitno) ((dst) & ~(1LLU << (bitno))) 222 # define TSTBIT(dst, bitno) (((dst) & (1LLU << (bitno))) ? 1: 0) 223 224 typedef enum 225 { 226 UNKNOWN_CYCLE = 0, 227 OPERAND_STORE, 228 OPERAND_READ, 229 INDIRECT_WORD_FETCH, 230 RTCD_OPERAND_FETCH, 231 INSTRUCTION_FETCH, 232 APU_DATA_READ, 233 APU_DATA_STORE, 234 ABSA_CYCLE, 235 # ifdef LOCKLESS 236 OPERAND_RMW, 237 APU_DATA_RMW, 238 # endif 239 } processor_cycle_type; 240 241 # ifndef LOCKLESS 242 # define OPERAND_RMW OPERAND_READ 243 # define APU_DATA_RMW APU_DATA_READ 244 # endif 245 246 # ifndef EIS_PTR4 247 // some breakpoint stuff ... 248 typedef enum 249 { 250 UnknownMAT = 0, 251 OperandRead, 252 OperandWrite, 253 viaPR 254 } MemoryAccessType; 255 # endif 256 257 // get 6-bit char @ pos 258 # define GETCHAR(src, pos) (word6)(((word36)src >> (word36)((5 - pos) * 6)) & 077) 259 // get 9-bit byte @ pos 260 # define GETBYTE(src, pos) (word9)(((word36)src >> (word36)((3 - pos) * 9)) & 0777) 261 262 # ifdef NEED_128 263 # define YPAIRTO72(ypair) construct_128 ((ypair[0] >> 28) & MASK8, \ 264 ((ypair[0] & MASK28) << 36) | \ 265 (ypair[1] & MASK36)); 266 # else 267 # define YPAIRTO72(ypair) (((((word72)(ypair[0] & DMASK)) << 36) | \ 268 (ypair[1] & DMASK)) & MASK72) 269 # endif 270 271 # define GET_TALLY(src) (((src) >> 6) & MASK12) // 12-bits 272 # define GET_DELTA(src) ((src) & MASK6) // 6-bits 273 274 # ifndef max 275 # define max(a,b) max2((a),(b)) 276 # endif 277 # define max2(a,b) ((a) > (b) ? (a) : (b)) 278 # define max3(a,b,c) max((a), max((b),(c))) 279 280 # ifndef min 281 # define min(a,b) min2((a),(b)) 282 # endif 283 # define min2(a,b) ((a) < (b) ? (a) : (b)) 284 # define min3(a,b,c) min((a), min((b),(c))) 285 286 // opcode metadata (flag) ... 287 typedef enum 288 { 289 READ_OPERAND = (1U << 0), // fetches/reads operand (CA) from memory 290 STORE_OPERAND = (1U << 1), // stores/writes operand to memory (its a STR-OP) 291 # define RMW (READ_OPERAND | STORE_OPERAND) // a Read-Modify-Write instruction 292 READ_YPAIR = (1U << 2), // fetches/reads Y-pair operand (CA) from memory 293 STORE_YPAIR = (1U << 3), // stores/writes Y-pair operand to memory 294 READ_YBLOCK8 = (1U << 4), // fetches/reads Y-block8 operand (CA) from memory 295 NO_RPT = (1U << 5), // Repeat instructions not allowed 296 //#define NO_RPD (1U << 6) 297 NO_RPL = (1U << 7), 298 //#define NO_RPX (NO_RPT | NO_RPD | NO_RPL) 299 READ_YBLOCK16 = (1U << 8), // fetches/reads Y-block16 operands from memory 300 STORE_YBLOCK16 = (1U << 9), // fetches/reads Y-block16 operands from memory 301 TRANSFER_INS = (1U << 10), // a transfer instruction 302 TSPN_INS = (1U << 11), // a TSPn instruction 303 CALL6_INS = (1U << 12), // a call6 instruction 304 PREPARE_CA = (1U << 13), // prepare TPR.CA for instruction 305 STORE_YBLOCK8 = (1U << 14), // stores/writes Y-block8 operand to memory 306 IGN_B29 = (1U << 15), // Bit-29 has an instruction specific meaning. Ignore. 307 NO_TAG = (1U << 16), // tag is interpreted differently and for addressing purposes is effectively 0 308 PRIV_INS = (1U << 17), // priveleged instruction 309 NO_BAR = (1U << 18), // not allowed in BAR mode 310 // NO_XEC = (1U << 19), // can't be executed via xec/xed 311 NO_XED = (1U << 20), // No execution via XEC/XED instruction 312 313 // EIS operand types 314 315 # define EOP_ALPHA 1U 316 317 // bits 21, 22 318 EOP1_ALPHA = (EOP_ALPHA << 21), 319 EOP1_MASK = (3U << 21), 320 # define EOP1_SHIFT 21 321 322 // bits 23, 24 323 EOP2_ALPHA = (EOP_ALPHA << 23), 324 EOP2_MASK = (3U << 23), 325 # define EOP2_SHIFT 23 326 327 // bits 25, 26 328 EOP3_ALPHA = (EOP_ALPHA << 25), 329 EOP3_MASK = (3U << 25), 330 # define EOP3_SHIFT 25 331 332 READ_YBLOCK32 = (1U << 27), // fetches/reads Y-block16 operands from memory 333 STORE_YBLOCK32 = (1U << 28), // fetches/reads Y-block16 operands from memory 334 } opc_flag; 335 336 337 // opcode metadata (disallowed) modifications 338 typedef enum opc_mod 339 { 340 NO_DU = (1U << 0), // No DU modification allowed (Can these 2 be combined into 1?) 341 NO_DL = (1U << 1), // No DL modification allowed 342 # define NO_DUDL (NO_DU | NO_DL) 343 344 NO_CI = (1U << 2), // No character indirect modification (can these next 3 be combined?_ 345 NO_SC = (1U << 3), // No sequence character modification 346 NO_SCR = (1U << 4), // No sequence character reverse modification 347 # define NO_CSS (NO_CI | NO_SC | NO_SCR) 348 349 # define NO_DLCSS (NO_DU | NO_CSS) 350 # define NO_DDCSS (NO_DUDL | NO_CSS) 351 352 ONLY_AU_QU_AL_QL_XN = (1U << 5) // None except au, qu, al, ql, xn 353 } opc_mod; 354 355 // None except au, qu, al, ql, xn for MF1 and REG 356 // None except du, au, qu, al, ql, xn for MF2 357 // None except au, qu, al, ql, xn for MF1, MF2, and MF3 358 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 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 442 enum eCAFoper { 443 unknown = 0, 444 readCY, 445 writeCY, 446 rmwCY, // Read-Modify-Write 447 // readCYpair, 448 // writeCYpair, 449 // readCYblock8, 450 // writeCYblock8, 451 // readCYblock16, 452 // writeCYblock16, 453 454 prepareCA, 455 }; 456 typedef enum eCAFoper eCAFoper; 457 458 # define READOP(i) ((bool) (i->info->flags & \ 459 (READ_OPERAND | \ 460 READ_YPAIR | \ 461 READ_YBLOCK8 | \ 462 READ_YBLOCK16 | \ 463 READ_YBLOCK32))) 464 465 # define WRITEOP(i) ((bool) (i->info->flags & \ 466 (STORE_OPERAND | \ 467 STORE_YPAIR | \ 468 STORE_YBLOCK8 | \ 469 STORE_YBLOCK16 | \ 470 STORE_YBLOCK32))) 471 472 // if it's both read and write it's a RMW 473 # define RMWOP(i) ((bool) READOP(i) && WRITEOP(i)) 474 475 # define TRANSOP(i) ((bool) (i->info->flags & (TRANSFER_INS) )) 476 477 // 478 // EIS stuff ... 479 // 480 481 // Numeric operand descriptors 482 483 484 // AL39 Table 4-3. Alphanumeric Data Type (TA) Codes 485 enum 486 { 487 CTA9 = 0U, // 9-bit bytes 488 CTA6 = 1U, // 6-bit characters 489 CTA4 = 2U, // 4-bit decimal 490 CTAILL = 3U // Illegal 491 }; 492 493 // TN - Type Numeric AL39 Table 4-3. Alphanumeric Data Type (TN) Codes 494 enum 495 { 496 CTN9 = 0U, // 9-bit 497 CTN4 = 1U // 4-bit 498 }; 499 500 // S - Sign and Decimal Type (AL39 Table 4-4. Sign and Decimal Type (S) Codes) 501 502 enum 503 { 504 CSFL = 0U, // Floating-point, leading sign 505 CSLS = 1U, // Scaled fixed-point, leading sign 506 CSTS = 2U, // Scaled fixed-point, trailing sign 507 CSNS = 3U // Scaled fixed-point, unsigned 508 }; 509 510 511 enum 512 { 513 // Address register flag. This flag controls interpretation of the ADDRESS 514 // field of the operand descriptor just as the "A" flag controls 515 // interpretation of the ADDRESS field of the basic and EIS single-word 516 // instructions. 517 MFkAR = 0x40U, 518 // Register length control. If RL = 0, then the length (N) field of the 519 // operand descriptor contains the length of the operand. If RL = 1, then 520 // the length (N) field of the operand descriptor contains a selector value 521 // specifying a register holding the operand length. Operand length is 522 // interpreted as units of the data size (1-, 4-, 6-, or 9-bit) given in 523 // the associated operand descriptor. 524 MFkRL = 0x20U, 525 // Indirect descriptor control. If ID = 1 for Mfk, then the kth word 526 // following the instruction word is an indirect pointer to the operand 527 // descriptor for the kth operand; otherwise, that word is the operand 528 // descriptor. 529 MFkID = 0x10U, 530 531 MFkREGMASK = 0xfU 532 }; 533 534 535 // EIS instruction take on a life of their own. Need to take into account 536 // RNR/SNR/BAR etc. 537 typedef enum 538 { 539 eisUnknown = 0, // uninitialized 540 eisTA = 1, // type alphanumeric 541 eisTN = 2, // type numeric 542 eisBIT = 3 // bit string 543 } eisDataType; 544 545 typedef enum 546 { 547 eRWreadBit = 0, 548 eRWwriteBit 549 } eRW; 550 551 // Misc constants and macros 552 553 # define ARRAY_SIZE(a) ( sizeof(a) / sizeof((a)[0]) ) 554 555 # if defined (__MINGW64__) || \ 556 defined (__MINGW32__) || \ 557 defined (__GNUC__) || \ 558 defined (__clang_version__) 559 # define NO_RETURN __attribute__ ((noreturn)) 560 # define UNUSED __attribute__ ((unused)) 561 # else 562 # define NO_RETURN 563 # define UNUSED 564 # endif 565 566 # define MAX_DEV_NAME_LEN 64 567 568 #endif // ifdef DPS8_H 569