mirror of
https://github.com/pkimpel/retro-220.git
synced 2026-01-14 23:46:43 +00:00
1. Commit original paper tape images B220_Paper_Tapes.zip and TR1101_TR1301.zip archives from http://bitsavers.org/bits/Burroughs/B220/. 2. Update and reorganize software/Diagnostics folder; Add README.txt. 3. Commit Michael Mahon's consolidation of the TR1202..TR1206 tests as Mahon-Regression-Test.pt. 4. Correct formatting of "*" (current assembler location) operand in BAC-Disassembler.html. 5. Minor corrections to 220-Paper-Tape-Decoder.html. 6. Commit new 220-Format-Band-Disassembler.html script to generate BAC- Assembler FBGR pseudo ops from memory images of Cardatron format bands.
1474 lines
51 KiB
HTML
1474 lines
51 KiB
HTML
<!DOCTYPE html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
|
<title>BAC-220 Disassembler</title>
|
|
<!--
|
|
/***********************************************************************
|
|
* 220/software/tools BAC-Disassembler.html
|
|
************************************************************************
|
|
* Copyright (c) 2016, Paul Kimpel.
|
|
* Licensed under the MIT License, see
|
|
* http://www.opensource.org/licenses/mit-license.php
|
|
************************************************************************
|
|
* Cross-Disassembler for the Burroughs 220. Generates assembler source
|
|
* compatible with the BAC-Assembler used with the BALGOL compiler and
|
|
* library.
|
|
*
|
|
* Input is a text file in retro-220 paper-tape image format with one
|
|
* decimal word per line. For details on that format, see:
|
|
* https://github.com/pkimpel/retro-220/wiki/UsingTheSPOAndPaperTape.
|
|
*
|
|
* The disasssembler is written in Javascript embedded within an HTML
|
|
* web page. To use, load the assembler into a browser, e.g., from
|
|
* https://github.com/pkimpel/retro-220/wiki/UsingTheSPOAndPaperTape.
|
|
* Select the desired output mode (listing only or listing plus assembly
|
|
* deck), then use the file picker to select the paper-tape image file.
|
|
* Selecting the file initiates the disassembly process.
|
|
*
|
|
************************************************************************
|
|
* 2020-08-19 P.Kimpel
|
|
* Original version, cloned from BAC-Assembler.html.
|
|
***********************************************************************/
|
|
-->
|
|
<meta name="Author" content="Paul Kimpel">
|
|
<meta http-equiv="Content-Script-Type" content="text/javascript">
|
|
<meta http-equiv="Content-Style-Type" content="text/css">
|
|
|
|
<style>
|
|
HTML {
|
|
height: 100%}
|
|
|
|
BODY {
|
|
position: relative;
|
|
background-color: #FFC;
|
|
font-family: Arial, Helvetica, sans-serif;
|
|
height: calc(100% - 3ex);
|
|
margin: 1ex}
|
|
|
|
DIV.heading {
|
|
margin-top: 12px;
|
|
margin-bottom: 6px;
|
|
width: 640px;
|
|
font-weight: bold}
|
|
|
|
LABEL {
|
|
font-size: smaller}
|
|
|
|
#TapeReaderPanel {
|
|
color: white;
|
|
background-color: #666;
|
|
width: 640px;
|
|
border: 1px solid black;
|
|
border-radius: 8px;
|
|
font-size: smaller;
|
|
padding: 8px}
|
|
|
|
#TapeReaderTable {
|
|
border-spacing: 0;
|
|
border-collapse: collapse;
|
|
table-layout: fixed;
|
|
width: 100%}
|
|
#TapeReaderCol1 {
|
|
width: 18ex}
|
|
#TapeReaderTable TD {
|
|
text-align: left;
|
|
vertical-align: top;
|
|
padding-top: 1px;
|
|
padding-bottom: 1px;
|
|
padding-left: 2px;
|
|
padding-right: 2px}
|
|
|
|
#CRPoolSelector {
|
|
width: 100%;
|
|
border: 1px solid white}
|
|
|
|
#OptionsTable {
|
|
margin-top: 4px;
|
|
margin-bottom: 4px;
|
|
width: 640px}
|
|
|
|
#TextPanel {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 160px; /* initially */
|
|
bottom: 0px;
|
|
width: 640px;
|
|
white-space: pre;
|
|
overflow: scroll;
|
|
padding: 4px;
|
|
border: 1px solid black;
|
|
color: black;
|
|
background-color: white;
|
|
font-family: DejaVu Sans Mono, Consolas, Courier, monospace;
|
|
font-size: 8pt;
|
|
font-weight: normal}
|
|
|
|
#Spinner {
|
|
position: absolute;
|
|
top: 200px;
|
|
left: 200px;
|
|
z-index: 10}
|
|
|
|
.center {
|
|
text-align: center}
|
|
.floatRight {
|
|
float: right}
|
|
.rj {
|
|
text-align: right}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
<div class=heading>
|
|
<!--
|
|
<div class=floatRight>
|
|
<a href="https://github.com/pkimpel/retro-220/wiki/UsingBACAssembler"
|
|
target="_new" title="Wiki page for the BAC-Disassembler">Help</a>
|
|
</div>
|
|
-->
|
|
|
|
Disassembler for the Burroughs 220
|
|
</div>
|
|
|
|
<div id=OptionsDiv>
|
|
<table id=OptionsTable>
|
|
<thead>
|
|
<tr>
|
|
<th><label for=Pass1ListCheck>List Pass 1</label>
|
|
<th><label for=Pass2ListCheck>List Pass 2</label>
|
|
<th><label for=OutputModeSelect>Output Mode</label>
|
|
<th>
|
|
<tbody>
|
|
<tr>
|
|
<td class=center>
|
|
<input id=Pass1ListCheck type=checkbox value=1 DISABLED>
|
|
<td class=center>
|
|
<input id=Pass2ListCheck type=checkbox value=1 DISABLED CHECKED>
|
|
<td class=center>
|
|
<select id=OutputModeSelect>
|
|
<option value="" SELECTED>Listing only
|
|
<option value=D >List + Asm Deck
|
|
</select>
|
|
<td class=rj>
|
|
<button id=ExtractListing type=button>Extract Listing</button>
|
|
</table>
|
|
|
|
<div id=TapeReaderPanel>
|
|
<table id=TapeReaderTable>
|
|
<colgroup><col id=TapeReaderCol1><col id=TapeReaderCol2></colgroup>
|
|
<tr><td>Load Source & Go
|
|
<td><input id=CRFileSelector type=file size=90>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<div id=TextPanel></div> <!-- Don't add any whitespace inside the div! -->
|
|
|
|
|
|
<script>
|
|
"use strict";
|
|
|
|
window.addEventListener("load", function() {
|
|
|
|
// Tape reader properties
|
|
var buffer = "";
|
|
var bufferLength = 0;
|
|
var bufferOffset = 0;
|
|
var sourceName = "?";
|
|
|
|
var eolRex = /([^\n\r\f]*)((:?\r[\n\f]?)|\n|\f)?/g;
|
|
var rTrimRex = /\s*$/;
|
|
var sprintLimit = 100; // cards processed before yielding control
|
|
|
|
// Card 0-relative column offsets
|
|
var labelIndex = 4;
|
|
var opCodeIndex = labelIndex + 6;
|
|
var operandIndex = labelIndex + 12;
|
|
var commentIndex = operandIndex + 14;
|
|
var operandLength = 55;
|
|
|
|
// Code word data structure
|
|
var wordData = {
|
|
atEOF: false,
|
|
offset: 0,
|
|
length: 0,
|
|
serial: 0,
|
|
text: "",
|
|
word: 0}
|
|
|
|
var pass1List = false;
|
|
var pass2List = true;
|
|
|
|
var generateDeck = false; // true if generating a source deck
|
|
var deckWin = null; // window for the output source deck
|
|
var deckDoc = null; // window document object for the source deck
|
|
var deck = null; // deck window text area
|
|
|
|
var panel = $$("TextPanel");
|
|
var cardReaderUnit = 1; // Cardatron input unit number for object card decks
|
|
|
|
// Assembly storage
|
|
var errorCount = 0; // assembler error count
|
|
var lineNr = 1; // assembly output line number
|
|
var location = 0; // current instruction address
|
|
var startAddress = 0; // starting execution address, from FINI card
|
|
|
|
var p10 = [ 1, // powers of 10 table
|
|
10,
|
|
100,
|
|
1000,
|
|
10000,
|
|
100000,
|
|
1000000,
|
|
10000000,
|
|
100000000,
|
|
1000000000,
|
|
10000000000,
|
|
100000000000,
|
|
1000000000000,
|
|
10000000000000,
|
|
100000000000000,
|
|
1000000000000000,
|
|
10000000000000000];
|
|
|
|
var xlateANSI220 = [ // translate ANSI to 220 internal character codes
|
|
// 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
|
|
17, 17, 17, 17, 17, 17, 17, 17, 17, 26, 35, 17, 15, 16, 17, 17, // 00-0F
|
|
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, // 10-1F
|
|
0, 17, 36, 33, 13, 24, 10, 34, 24, 4, 14, 10, 23, 20, 3, 21, // 20-2F
|
|
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 27, 13, 4, 33, 5, 17, // 30-3F
|
|
34, 41, 42, 43, 44, 45, 46, 47, 48, 49, 51, 52, 53, 54, 55, 56, // 40-4F
|
|
57, 58, 59, 62, 63, 64, 65, 66, 67, 68, 69, 32, 6, 12, 15, 2, // 50-5F
|
|
37, 41, 42, 43, 44, 45, 46, 47, 48, 49, 51, 52, 53, 54, 55, 56, // 60-6F
|
|
57, 58, 59, 62, 63, 64, 65, 66, 67, 68, 69, 22, 16, 25, 26, 17]; // 70-7F
|
|
|
|
var xlate220ANSI = [ // translate internal B220 code to ANSI (Algol glyphs)
|
|
// 00 01 02 03 04 05 06 07 08 09
|
|
" ", "?", "_", ".", "<", ">", "\\","?", "?", "?", // 00-09
|
|
"&", "?", "]", "$", "*", "^", "|", "?", "?", "?", // 10-19
|
|
"-", "/", "{", ",", "%", "}", "~", ":", "?", "?", // 20-29
|
|
"?", "?", "[", "#", "@", "\n","\"","`", "?", "?", // 30-39
|
|
"?", "A", "B", "C", "D", "E", "F", "G", "H", "I", // 40-49
|
|
"?", "J", "K", "L", "M", "N", "O", "P", "Q", "R", // 50-59
|
|
"?", "?", "S", "T", "U", "V", "W", "X", "Y", "Z", // 60-69
|
|
"?", "?", "?", "?", "?", "?", "?", "?", "?", "?", // 70-79
|
|
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", // 80-89
|
|
"?", "?", "?", "?", "?", "?", "?", "?", "?", "?"]; // 90-99
|
|
|
|
/***************************************
|
|
* Opcode table:
|
|
* Each 220 assembler op code is defined by an array with a variable number
|
|
* of elements. The first element is the operation code, including any variant
|
|
* digit in (41) and is always required. The variant digit may be overlaid by
|
|
* other fields in the instruction. If the code is negative, it indicates a
|
|
* pseudo-operator or other special handling.
|
|
*
|
|
* The remainder of the array consists of number pairs, one for each comma-
|
|
* delimited operand field that may be present. The first number is a code
|
|
* indicating the type of field, the second is the default value for that
|
|
* field if it is not specified (or is empty) in the operand area of the
|
|
* instruction. If the default value is negative, that operand is not optional
|
|
* and must be specified.
|
|
*
|
|
* Type codes:
|
|
* 1 = address field, inserted in (04)
|
|
* 2 = secondary value inserted in (33)
|
|
* 3 = secondary value inserted in (44)
|
|
* 4 = unit or count digit inserted in (11)
|
|
* 5 = variant digit inserted in (41)
|
|
* 6 = sL field designator inserted in (22); if specified, insert 1 in (31)
|
|
* 7 = sL field designator inserted in (22); (31) is undisturbed
|
|
* 8 = value inserted in (32)
|
|
* 9 = value inserted in (42)
|
|
* 10 = value inserted in (21)
|
|
* 11 = value inserted in (62)
|
|
* 12 = value inserted in (64)
|
|
* 13 = BU pair for CRF/CWF: (B-1)*2 added to (41), U in (11)
|
|
* 14 = reload-lockout value added to (41)
|
|
* 15 = digit inserted in (11); if specified, insert 1 in (41)
|
|
* 16 = Cardatron c-digit inserted in (31) for T-relays (carriage control)
|
|
* 17 = variant value added to (41)
|
|
* 18 = mag tape unit/lane as LLU, inserted as ULL in (33)
|
|
* 19 = resolved address only in (04)
|
|
* 20 = optional address in (04)
|
|
***************************************/
|
|
|
|
// Pseudo-instruction codes
|
|
var pseudoDEFN = -1;
|
|
var pseudoLOCN = -2;
|
|
var pseudoCNST = -3;
|
|
var pseudoF244 = -4;
|
|
var pseudoF424 = -5;
|
|
var pseudoFBGR = -6;
|
|
var pseudoFINI = -9;
|
|
|
|
// Table of the primary field (sL code) for each opTab table field type code.
|
|
var fieldTab = [-1,
|
|
4, 33, 44, 11, 41, 22, 22, 32, 42, 21, 62, 64, 11, 41, 41, 31, 41, 33, 4, 4];
|
|
|
|
var opTab = {
|
|
"HLT": [ 0, 20, 0, 3, 0],
|
|
"NOP": [ 1, 20, 0, 3, 0],
|
|
"PRD": [ 3, 1, -1, 4, -1, 8, -1, 5, 0],
|
|
"PRB": [ 4, 1, -1, 4, -1, 5, 0, 8, 0],
|
|
"PRI": [ 5, 1, -1, 4, -1, 8, -1, 5, 0],
|
|
"PWR": [ 6, 1, -1, 4, -1, 8, -1],
|
|
"PWI": [ 7, 1, -1, 4, -1],
|
|
"KAD": [ 8, 20, 0, 3, 0],
|
|
"SPO": [ 9, 1, -1, 8, -1, 15, 0],
|
|
"CAD": [ 10, 1, -1, 3, 0],
|
|
"CAA": [ 110, 1, -1, 3, 0],
|
|
"CSU": [ 11, 1, -1, 3, 0],
|
|
"CSA": [ 111, 1, -1, 3, 0],
|
|
"ADD": [ 12, 1, -1, 3, 0],
|
|
"ADA": [ 112, 1, -1, 3, 0],
|
|
"SUB": [ 13, 1, -1, 3, 0],
|
|
"SUA": [ 113, 1, -1, 3, 0],
|
|
"MUL": [ 14, 1, -1, 3, 0],
|
|
"DIV": [ 15, 1, -1, 3, 0],
|
|
"RND": [ 16, 20, 0, 3, 0],
|
|
"EXT": [ 17, 1, -1, 3, 0],
|
|
"CFA": [ 18, 1, -1, 6, 0],
|
|
"CFR": [ 118, 1, -1, 6, 0],
|
|
"ADL": [ 19, 1, -1, 3, 0],
|
|
"IBB": [ 20, 1, -1, 3, -1],
|
|
"DBB": [ 21, 1, -1, 3, -1],
|
|
"FAD": [ 22, 1, -1, 4, 0],
|
|
"FAA": [ 122, 1, -1, 4, 0],
|
|
"FSU": [ 23, 1, -1, 4, 0],
|
|
"FSA": [ 123, 1, -1, 4, 0],
|
|
"FMU": [ 24, 1, -1, 3, 0],
|
|
"FDV": [ 25, 1, -1, 3, 0],
|
|
"IFL": [ 26, 1, -1, 7, -1, 9, -1],
|
|
"DFL": [ 27, 1, -1, 7, -1, 9, -1],
|
|
"DLB": [ 28, 1, -1, 7, -1, 9, -1],
|
|
"RTF": [ 29, 1, -1, 8, -1],
|
|
"BUN": [ 30, 1, -1, 3, 0],
|
|
"BOF": [ 31, 1, -1, 3, 0],
|
|
"BRP": [ 32, 1, -1, 3, 0],
|
|
"BSA": [ 33, 1, -1, 5, -1, 2, 0],
|
|
"BPA": [ 33, 1, -1, 5, 0, 2, 0],
|
|
"BMA": [ 33, 1, -1, 5, 1, 2, 0],
|
|
"BCH": [ 34, 1, -1, 2, 0],
|
|
"BCL": [ 134, 1, -1, 2, 0],
|
|
"BCE": [ 35, 1, -1, 2, 0],
|
|
"BCU": [ 135, 1, -1, 2, 0],
|
|
"BFA": [ 36, 1, -1, 7, -1, 9, -1],
|
|
"BZA": [ 36, 1, -1, 7, 0, 9, 0],
|
|
"BFR": [ 37, 1, -1, 7, -1, 9, -1],
|
|
"BZR": [ 37, 1, -1, 7, 0, 9, 0],
|
|
"BCS": [ 38, 1, -1, 4, -1],
|
|
"SOR": [ 39, 20, 0, 2, 0],
|
|
"SOH": [ 139, 20, 0, 2, 0],
|
|
"IOM": [ 239, 1, -1, 2, 0],
|
|
"STA": [ 40, 1, -1, 6, 0],
|
|
"STR": [ 140, 1, -1, 6, 0],
|
|
"STB": [ 240, 1, -1, 6, 0],
|
|
"LDR": [ 41, 1, -1, 3, 0],
|
|
"LDB": [ 42, 1, -1, 2, 0],
|
|
"LBC": [ 142, 1, -1, 2, 0],
|
|
"LSA": [ 43, 5, -1, 20, 0, 2, 0],
|
|
"STP": [ 44, 1, -1, 3, 0],
|
|
"CLA": [ 145, 20, 0, 2, 0],
|
|
"CLR": [ 245, 20, 0, 2, 0],
|
|
"CAR": [ 345, 20, 0, 2, 0],
|
|
"CLB": [ 445, 20, 0, 2, 0],
|
|
"CAB": [ 545, 20, 0, 2, 0],
|
|
"CRB": [ 645, 20, 0, 2, 0],
|
|
"CLT": [ 745, 20, 0, 2, 0],
|
|
"CLL": [ 46, 1, -1, 3, 0],
|
|
"SRA": [ 48, 1, -1, 2, 0],
|
|
"SRT": [ 148, 1, -1, 2, 0],
|
|
"SRS": [ 248, 1, -1, 2, 0],
|
|
"SLA": [ 49, 1, -1, 2, 0],
|
|
"SLT": [ 149, 1, -1, 2, 0],
|
|
"SLS": [ 249, 1, -1, 2, 0],
|
|
"MTS": [ 50, 1, -1, 18, -1],
|
|
"MFS": [4000050, 1, -1, 18, -1],
|
|
"MLS": [ 450, 18, -1, 20, 0],
|
|
"MRW": [ 850, 18, -1, 20, 0],
|
|
"MDA": [ 950, 18, -1, 20, 0],
|
|
"MTC": [ 51, 1, -1, 18, -1, 5, -1],
|
|
"MFC": [4000051, 1, -1, 18, -1, 5, -1],
|
|
"MRD": [ 52, 1, -1, 4, -1, 10, -1, 17, 0],
|
|
"MNC": [ 152, 1, -1, 4, -1, 10, -1, 17, 0],
|
|
"MRR": [ 53, 1, -1, 4, -1, 10, -1, 17, 0],
|
|
"MIW": [ 54, 1, -1, 4, -1, 10, -1, 9, 0],
|
|
"MIR": [ 55, 1, -1, 4, -1, 10, -1, 9, 0],
|
|
"MOW": [ 56, 1, -1, 4, -1, 10, -1, 9, 0],
|
|
"MOR": [ 57, 1, -1, 4, -1, 10, -1, 9, 0],
|
|
"MPF": [ 58, 4, -1, 10, -1, 20, 0],
|
|
"MPB": [ 158, 4, -1, 10, -1, 20, 0],
|
|
"MPE": [ 258, 4, -1, 20, 0],
|
|
"MIB": [ 59, 1, -1, 4, -1, 8, 0],
|
|
"MIE": [ 159, 1, -1, 4, -1, 8, 0],
|
|
"CRD": [ 60, 1, -1, 4, -1, 5, 0, 8, 0],
|
|
"CNC": [ 1060, 1, -1, 4, -1, 5, 0],
|
|
"CWR": [ 61, 1, -1, 13, -1, 16, 0],
|
|
"CRF": [ 62, 1, -1, 13, -1, 14, 0],
|
|
"CWF": [ 63, 1, -1, 13, -1, 14, 0],
|
|
"CRI": [ 64, 1, -1, 4, -1],
|
|
"CWI": [ 65, 1, -1, 4, -1],
|
|
"HPW": [ 66, 1, -1, 8, -1],
|
|
"HPI": [ 67, 1, 0, 3, 0],
|
|
|
|
// Pseudo-ops
|
|
"DEFN": [pseudoDEFN, // define symbol
|
|
19, -1],
|
|
"LOCN": [pseudoLOCN, // set location counter
|
|
19, -1],
|
|
"CNST": [pseudoCNST], // assemble list of literal values
|
|
"F244": [pseudoF244, // assemble word from 22-64-04 fields
|
|
7, 0, 12, 0, 1, 0],
|
|
"F424": [pseudoF424, // assemble word from 44-62-04 fields
|
|
3, 0, 11, 0, 1, 0],
|
|
"FBGR": [pseudoFBGR], // assemble Cardatron format band
|
|
"FINI": [pseudoFINI, // finish assembly, output literal pool
|
|
1, 0]
|
|
};
|
|
|
|
|
|
/*******************************************************************
|
|
* Miscellaneous Utility Functions *
|
|
*******************************************************************/
|
|
|
|
/**************************************/
|
|
function $$(id) {
|
|
return document.getElementById(id);
|
|
}
|
|
|
|
/**************************************/
|
|
function padLeft(s, len, fill) {
|
|
/* Pads the string "s" on the left to length "len" with the filler character
|
|
"fill". If fill is empty or missing, space is used. If the initial string is
|
|
longer than "len", it is truncated on the left to that length */
|
|
var pad = (fill || " ").charAt(0);
|
|
var result = s.toString();
|
|
var rLen = result.length;
|
|
|
|
if (rLen > len) {
|
|
result = result.substring(rLen-len);
|
|
} else {
|
|
while (rLen < len) {
|
|
result = pad + result;
|
|
++rLen;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**************************************/
|
|
function padRight(s, len, fill) {
|
|
/* Pads the string "s" on the right to length "len" with the filler character
|
|
"fill". If fill is empty or missing, space is used. If the initial string is
|
|
longer than "len", it is truncated on the right to that length */
|
|
var pad = (fill || " ").charAt(0);
|
|
var result = s.toString();
|
|
var rLen = s.length;
|
|
|
|
if (rLen > len) {
|
|
result = result.substring(0, len);
|
|
} else {
|
|
while (rLen < len) {
|
|
result = result + pad;
|
|
++rLen;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**************************************/
|
|
function rTrim(s) {
|
|
/* Returns the string "s" stripped of any trailing whitespace */
|
|
var x = s.search(rTrimRex);
|
|
|
|
if (x < 0 ) {
|
|
return s;
|
|
} else if (x < 1) {
|
|
return "";
|
|
} else {
|
|
return s.substring(0, x);
|
|
}
|
|
}
|
|
|
|
/**************************************/
|
|
function tensComp(value) {
|
|
/* If "value" is algebraically negative, returns its 11-digit tens
|
|
complement. Otherwise returns the 11-digit value */
|
|
|
|
if (value < 0) {
|
|
return p10[11] + value%p10[11];
|
|
} else {
|
|
return value%p10[11];
|
|
}
|
|
}
|
|
|
|
/**************************************/
|
|
function applySign(word, sign) {
|
|
/* Applies an unsigned "sign" digit to a 220 "word" value. If the word
|
|
value is algebraically negative, it is first converted to a 10-digit
|
|
number with a 220 sign in the 11-th high-order digit. The low-order bit
|
|
of "sign" and the low-order bit of the word's sign digit are XOR-ed so
|
|
that each of those bits designates negation. Returns the new value as an
|
|
11-digit unsigned 220 word in binary */
|
|
var s = 0;
|
|
var value = 0;
|
|
|
|
if (word < 0) {
|
|
value = (-word)%p10[10];
|
|
s = 1;
|
|
} else {
|
|
value = word%p10[10];
|
|
s = (word%p10[11] - value)/p10[10];
|
|
}
|
|
|
|
return (sign%10 ^ s)*p10[10] + value;
|
|
}
|
|
|
|
/**************************************/
|
|
function getField(word, sL) {
|
|
/* Extracts an n-digit value from an 11-digit "word" and returns it.
|
|
"sL" is the same as for putField(). The word is a Javascript Number
|
|
object, but is treated as if it represents an 11-digit decimal integer */
|
|
var L = sL%10;
|
|
var s = (sL%100 - L)/10;
|
|
var result = applySign(word, 0);
|
|
|
|
s = (s == 0 ? 0 : 10-s);
|
|
L = (L == 0 ? 10 : L);
|
|
|
|
if (sL < 0 || sL > 99 || s+L > 11) {
|
|
result = -1;
|
|
} else {
|
|
result = (result%p10[s+L] - result%p10[s])/p10[s];
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**************************************/
|
|
function putField(word, value, sL) {
|
|
/* Inserts an n-digit "value" into designated digits of an 11-digit
|
|
"word". "sL" is the partial-word field in standard 220 start-Length
|
|
notation. Note that Javascript flags literal integers of the form "0n"
|
|
as the old C-style octal literal notation is deprecated. This routine
|
|
uses only the two low-order digits of "sL", however, so you can pass sL
|
|
literal values like 104 (or even 57321604) for /04 without ill effect.
|
|
The "value" and "word" are Javascript Number objects, but are treated as
|
|
if they represent 11-digit decimal integers. If value is negative, it is
|
|
converted to its 10s-complement value before insertion into word.
|
|
Returns a new word with the inserted field */
|
|
var L = sL%10;
|
|
var s = (sL%100 - L)/10;
|
|
var upperPart = 0;
|
|
var lowerPart = 0;
|
|
var result = applySign(word, 0);
|
|
|
|
s = (s == 0 ? 0 : 10-s);
|
|
L = (L == 0 ? 10 : L);
|
|
|
|
if (sL < 0 || s+L > 11) {
|
|
printError("INVALID /SL VALUE: ", sL);
|
|
} else {
|
|
upperPart = result%p10[11] - result%p10[s+L];
|
|
if (s > 0) {
|
|
lowerPart = result%p10[s];
|
|
}
|
|
|
|
result = (tensComp(value)%p10[L])*p10[s] + upperPart + lowerPart;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
* Listing Utilities *
|
|
*******************************************************************/
|
|
|
|
/**************************************/
|
|
function clearPanel() {
|
|
/* Clears the text panel */
|
|
var kid;
|
|
|
|
while (kid = panel.firstChild) {
|
|
panel.removeChild(kid);
|
|
}
|
|
}
|
|
|
|
/**************************************/
|
|
function readAWord() {
|
|
/* Reads one word from the buffer, converts it to decimal, and
|
|
fills in the global "wordData" structure with the word and its
|
|
location in the buffer */
|
|
var bx = bufferOffset; // current buffer offset
|
|
var line = ""; // line image
|
|
var lineLength = 0; // original delimited line image length
|
|
var match = null; // regular expression match result
|
|
var w = 0; // decimal word
|
|
|
|
wordData.offset = bx;
|
|
if (bx >= bufferLength) {
|
|
wordData.atEOF = true;
|
|
wordData.length = 0;
|
|
wordData.word = -99999999999;
|
|
} else {
|
|
eolRex.lastIndex = bx;
|
|
match = eolRex.exec(buffer);
|
|
if (!match) {
|
|
line = "";
|
|
} else {
|
|
bx += match[0].length;
|
|
line = match[1].trim();
|
|
}
|
|
|
|
lineLength = line.length;
|
|
if (lineLength > 0) {
|
|
if (line.charAt(0) == "2") {
|
|
if (lineLength > 6) {
|
|
line = line.substring(0, 6);
|
|
} else if (lineLength < 6) {
|
|
line = padRight(line, 6, " ");
|
|
}
|
|
|
|
w = ((((200 +
|
|
xlateANSI220[line.charCodeAt(1)])*100 +
|
|
xlateANSI220[line.charCodeAt(2)])*100 +
|
|
xlateANSI220[line.charCodeAt(3)])*100 +
|
|
xlateANSI220[line.charCodeAt(4)])*100 +
|
|
xlateANSI220[line.charCodeAt(5)];
|
|
} else {
|
|
if (lineLength > 11) {
|
|
printError("Input line too long: " + line);
|
|
line = line.substring(lineLength-11, 11);
|
|
}
|
|
|
|
w = parseInt(line, 10);
|
|
if (isNaN(w)) {
|
|
w = 0;
|
|
printError("Non-decimal word in input: \"" + line + "\"");
|
|
}
|
|
}
|
|
}
|
|
|
|
wordData.text = line;
|
|
wordData.word = w;
|
|
wordData.length = bx - bufferOffset;
|
|
++wordData.serial;
|
|
bufferOffset = bx;
|
|
}
|
|
}
|
|
|
|
/**************************************/
|
|
function printLine(text) {
|
|
/* Appends "text"+NL as a new text node to the panel DOM element */
|
|
var e = document.createTextNode(text + "\n");
|
|
|
|
panel.appendChild(e);
|
|
panel.scrollTop += 30;
|
|
}
|
|
|
|
/**************************************/
|
|
function printError(msg) {
|
|
/* Prints an error message to the text panel and bumps the error count */
|
|
|
|
++errorCount;
|
|
printLine("******** " + msg);
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
* Disassembler Output *
|
|
*******************************************************************/
|
|
|
|
/**************************************/
|
|
function extractListing(ev) {
|
|
/* Copies the text contents of the "paper" area of the assembler listing,
|
|
opens a new temporary window, and pastes that text into the window so it
|
|
can be copied or saved by the user */
|
|
var doc = null; // temp window document object
|
|
var text = panel.textContent;
|
|
var title = "BAC-Disassembler Listing";
|
|
var win = window.open("../../webUI/B220FramePaper.html", "BAC-Asm-Listing",
|
|
"scrollbars,resizable,width=600,height=500");
|
|
|
|
function copyText(ev) {
|
|
var doc = ev.target;
|
|
var win = doc.defaultView;
|
|
|
|
win.removeEventListener("load", copyText, false);
|
|
doc = win.document;
|
|
doc.title = title;
|
|
doc.getElementById("Paper").textContent = text;
|
|
}
|
|
|
|
//clearPanel();
|
|
win.addEventListener("load", copyText, false);
|
|
win.moveTo((screen.availWidth-win.outerWidth)/2, (screen.availHeight-win.outerHeight)/2);
|
|
ev.preventDefault();
|
|
ev.stopPropagation();
|
|
}
|
|
|
|
/**************************************/
|
|
function writeDeck(card) {
|
|
/* Writes one card-image line to the output source deck */
|
|
|
|
deck.appendChild(deckDoc.createTextNode(card + "\n"));
|
|
}
|
|
|
|
/**************************************/
|
|
function emitLine(location, word, lab, op, sign, operand, comment) {
|
|
/* Formats one line of disassembler output */
|
|
var card = "";
|
|
var line = " " + padLeft(lineNr, 4, " ") +
|
|
" " + padLeft(location, 4, "0") + " ";
|
|
var text = "";
|
|
|
|
++lineNr;
|
|
if (word === null) {
|
|
line += " ";
|
|
} else {
|
|
text = padLeft(word, 11, "0");
|
|
line += text.substring(0, 1) + " " + text.substring(1, 5) + " " +
|
|
text.substring(5, 7) + " " + text.substring(7, 11) + " ";
|
|
}
|
|
|
|
card = padRight(lab, 6, " ") + padRight(op, 4, " ");
|
|
if (sign == 0) {
|
|
card += " ";
|
|
} else if (sign == 1) {
|
|
card += "- ";
|
|
} else {
|
|
card += padLeft(sign, 1, "") + " ";
|
|
}
|
|
|
|
if ((comment || "").length == 0) {
|
|
card += operand;
|
|
} else {
|
|
if (operand.length < 14) {
|
|
card += padLeft(operand, 14);
|
|
} else {
|
|
card += operand + " ";
|
|
}
|
|
|
|
card += comment;
|
|
}
|
|
|
|
printLine(line + card);
|
|
if (generateDeck) {
|
|
writeDeck("1 " + card);
|
|
}
|
|
}
|
|
|
|
/**************************************/
|
|
function emitPseudo(location, word, lab, op, sign, operand, comment) {
|
|
/* Emits one line of disassambler for a pseudo-op */
|
|
|
|
emitLine(location, word, lab, op, sign, operand, comment);
|
|
}
|
|
|
|
/**************************************/
|
|
function emitConstant(location, word, lab, sign, comment) {
|
|
/* Emits one word as a CNST pseudo */
|
|
var char = 0;
|
|
var temp = word;
|
|
var text = "";
|
|
|
|
if (sign != 2) {
|
|
emitPseudo(location, word, lab, "CNST", 0, word.toString());
|
|
} else {
|
|
while (temp > 2) {
|
|
char = temp%100;
|
|
text = xlate220ANSI[char] + text;
|
|
temp = (temp-char)/100;
|
|
}
|
|
|
|
emitPseudo(location, word, lab, "CNST", 0, "$" + text + "$");
|
|
}
|
|
}
|
|
|
|
/**************************************/
|
|
function emitAsm(location, word, lab, op, sign, comment) {
|
|
/* Emits one line of disassembler for a machine operator,
|
|
decoding the operand fields of the word according to op */
|
|
var noField = false; // flag to indicate an empty field
|
|
var operand = ""; // generated operand string
|
|
var opDesc = opTab[op]; // operand descriptor array
|
|
var opTop = opDesc.length; // length of op code description array
|
|
var ox = 0; // opDesc[] index
|
|
var w1; // word field 1
|
|
var w2; // word field 2
|
|
|
|
function optional(field) {
|
|
for (w1=opTop-1; w1>ox; w1-=2) {
|
|
if (opDesc[w1] < 0) {
|
|
break; // a required field
|
|
} else {
|
|
w2 = fieldTab[opDesc[w1-1]];
|
|
if (opDesc[w1] != getField(word, w2)) {
|
|
break; // non-required field not default value
|
|
}
|
|
}
|
|
}
|
|
|
|
if (w1 > ox) { // some remaining field is not default
|
|
operand += getField(word, field);
|
|
} else {
|
|
noField = true;
|
|
}
|
|
}
|
|
|
|
if (!opDesc) {
|
|
printError("Invalid op code: " + op);
|
|
return;
|
|
}
|
|
|
|
for (ox=1; ox<opTop; ox+=2) {
|
|
noField = false;
|
|
switch (opDesc[ox]) {
|
|
case 1: // address field, inserted in (04)
|
|
case 19: // resolved address only in (04)
|
|
w1 = getField(word, 4);
|
|
w2 = w1 - location;
|
|
if (Math.abs(w2) > 3) {
|
|
operand += w1;
|
|
} else if (w2 > 0) {
|
|
operand += "*+" + w2;
|
|
} else if (w2 < 0) {
|
|
operand += "*" + w2;
|
|
} else {
|
|
operand += "*";
|
|
}
|
|
break;
|
|
case 2: // secondary value inserted in (33)
|
|
optional(33);
|
|
break;
|
|
case 3: // secondary value inserted in (44)
|
|
optional(44);
|
|
break;
|
|
case 4: // unit or count digit inserted in (11)
|
|
optional(11);
|
|
break;
|
|
case 5: // variant digit inserted in (41)
|
|
optional(41);
|
|
break;
|
|
case 6: // sL field designator inserted in (22); if specified, insert 1 in (31)
|
|
if (getField(word, 31)) {
|
|
operand += getField(word, 22);
|
|
} else {
|
|
noField = true;
|
|
}
|
|
break;
|
|
case 7: // sL field designator inserted in (22); (31) is undisturbed
|
|
optional(22);
|
|
break;
|
|
case 8: // value inserted in (32)
|
|
optional(32);
|
|
break;
|
|
case 9: // value inserted in (42)
|
|
optional(42);
|
|
break;
|
|
case 10: // value inserted in (21)
|
|
optional(21);
|
|
break;
|
|
case 11: // value inserted in (62)
|
|
optional(62);
|
|
break;
|
|
case 12: // value inserted in (64)
|
|
optional(64);
|
|
break;
|
|
case 13: // BU pair for CRF/CWF: (B-1)*2 added to (41), U in (11)
|
|
w1 = getField(word, 11); // unit number
|
|
w2 = getField(word, 41); // (B-1)*2
|
|
w2 = (w2 >> 1) + 1; // band number
|
|
operand += padLeft(w2*10 + w1, 2, "0");
|
|
break;
|
|
case 14: // reload-lockout value added to (41)
|
|
w1 = getField(word, 41) & 0x01;
|
|
if (w1 == 1) {
|
|
operand += "RLO";
|
|
} else {
|
|
noField = true;
|
|
}
|
|
break;
|
|
case 15: // digit inserted in (11); if specified, insert 1 in (41)
|
|
if (getField(word, 41)) {
|
|
optional(11);
|
|
} else {
|
|
noField = true;
|
|
}
|
|
break;
|
|
case 16: // Cardatron c-digit inserted in (31) for T-relays (carriage control)
|
|
w1 = getField(word, 31);
|
|
if (w1) {
|
|
operand += w1;
|
|
} else {
|
|
noField = true;
|
|
}
|
|
break;
|
|
case 17: // BMOD value added to (41)
|
|
w1 = getField(word, 41) & 0x08;
|
|
if (w1 == 8) {
|
|
operand += "BMOD";
|
|
} else {
|
|
noField = true;
|
|
}
|
|
break;
|
|
case 18: // mag tape unit/lane as LLU, inserted as ULL in (33)
|
|
w1 = getField(word, 32); // LL=lane number
|
|
w2 = getField(word, 11); // U=unit number
|
|
operand += (w1*10 + w2);
|
|
break;
|
|
case 20: // optional address in (04)
|
|
optional(4);
|
|
break;
|
|
default:
|
|
printError("INVALID OPDESC INDEX: " + opDesc[ox]);
|
|
break;
|
|
} // switch opDesc[ox]
|
|
|
|
if (!noField) {
|
|
operand += ",";
|
|
}
|
|
} // for ox
|
|
|
|
ox = operand.length;
|
|
while (ox > 0) {
|
|
--ox;
|
|
if (operand.charAt(ox) != ",") {
|
|
break;
|
|
}
|
|
}
|
|
|
|
emitLine(location, word, lab, op, sign, operand.substring(0, ox+1), comment);
|
|
}
|
|
|
|
/**************************************/
|
|
function disassembleWord() {
|
|
/* Disassembles one word of code */
|
|
var addr = 0;
|
|
var op = 0;
|
|
var sign = 0;
|
|
var control = 0;
|
|
var w = 0;
|
|
|
|
readAWord();
|
|
if (wordData.atEOF) {
|
|
return;
|
|
}
|
|
|
|
w = wordData.word;
|
|
addr = getField(w, 4);
|
|
op = getField(w, 62);
|
|
control = getField(w, 44);
|
|
sign = ((w - w%10000000000)/10000000000)%10;
|
|
|
|
if (sign > 1) {
|
|
if ((sign & 0x06) == 6) {
|
|
switch (op) {
|
|
case 4:
|
|
emitPseudo(location, null, "", "LOCN", 0, addr);
|
|
location = addr;
|
|
return;
|
|
break;
|
|
case 30:
|
|
startAddress = addr;
|
|
break;
|
|
}
|
|
} else if ((sign & 0x04) == 4 && (op == 50 || op == 51)) {
|
|
// fall through for MFS and MFC
|
|
} else {
|
|
emitConstant(location, w, "", sign);
|
|
++location;
|
|
return;
|
|
}
|
|
}
|
|
|
|
switch (op) {
|
|
case 0:
|
|
emitAsm(location, w, "", "HLT", sign);
|
|
break;
|
|
case 1:
|
|
emitAsm(location, w, "", "NOP", sign);
|
|
break;
|
|
case 3:
|
|
emitAsm(location, w, "", "PRD", sign);
|
|
break;
|
|
case 4:
|
|
emitAsm(location, w, "", "PRB", sign);
|
|
break;
|
|
case 5:
|
|
emitAsm(location, w, "", "PRI", sign);
|
|
break;
|
|
case 6:
|
|
emitAsm(location, w, "", "PWR", sign);
|
|
break;
|
|
case 7:
|
|
emitAsm(location, w, "", "PWI", sign);
|
|
break;
|
|
case 8:
|
|
emitAsm(location, w, "", "KAD", sign);
|
|
break;
|
|
case 9:
|
|
emitAsm(location, w, "", "SPO", sign);
|
|
break;
|
|
case 10:
|
|
emitAsm(location, w, "", (control%10==1 ? "CAA" : "CAD"), sign);
|
|
break;
|
|
case 11:
|
|
emitAsm(location, w, "", (control%10==1 ? "CSA" : "CSU"), sign);
|
|
break;
|
|
case 12:
|
|
emitAsm(location, w, "", (control%10==1 ? "ADA" : "ADD"), sign);
|
|
break;
|
|
case 13:
|
|
emitAsm(location, w, "", (control%10==1 ? "SUA" : "SUB"), sign);
|
|
break;
|
|
case 14:
|
|
emitAsm(location, w, "", "MUL", sign);
|
|
break;
|
|
case 15:
|
|
emitAsm(location, w, "", "DIV", sign);
|
|
break;
|
|
case 16:
|
|
emitAsm(location, w, "", "RND", sign);
|
|
break;
|
|
case 17:
|
|
emitAsm(location, w, "", "EXT", sign);
|
|
break;
|
|
case 18:
|
|
emitAsm(location, w, "", (control%10==1 ? "CFR" : "CFA"), sign);
|
|
break;
|
|
case 19:
|
|
emitAsm(location, w, "", "ADL", sign);
|
|
break;
|
|
case 20:
|
|
emitAsm(location, w, "", "IBB", sign);
|
|
break;
|
|
case 21:
|
|
emitAsm(location, w, "", "DBB", sign);
|
|
break;
|
|
case 22:
|
|
emitAsm(location, w, "", (control%10==1 ? "FAA" : "FAD"), sign);
|
|
break;
|
|
case 23:
|
|
emitAsm(location, w, "", (control%10==1 ? "FSA" : "FSU"), sign);
|
|
break;
|
|
case 24:
|
|
emitAsm(location, w, "", "FMU", sign);
|
|
break;
|
|
case 25:
|
|
emitAsm(location, w, "", "FDV", sign);
|
|
break;
|
|
case 26:
|
|
emitAsm(location, w, "", "IFL", sign);
|
|
break;
|
|
case 27:
|
|
emitAsm(location, w, "", "DFL", sign);
|
|
break;
|
|
case 28:
|
|
emitAsm(location, w, "", "DLB", sign);
|
|
break;
|
|
case 29:
|
|
emitAsm(location, w, "", "RTF", sign);
|
|
break;
|
|
case 30:
|
|
emitAsm(location, w, "", "BUN", sign);
|
|
break;
|
|
case 31:
|
|
emitAsm(location, w, "", "BOF", sign);
|
|
break;
|
|
case 32:
|
|
emitAsm(location, w, "", "BRP", sign);
|
|
break;
|
|
case 33:
|
|
emitAsm(location, w, "", "BSA", sign);
|
|
break;
|
|
case 34:
|
|
emitAsm(location, w, "", (control%10==1 ? "BCL" : "BCH"), sign);
|
|
break;
|
|
case 35:
|
|
emitAsm(location, w, "", (control%10==1 ? "BCU" : "BCE"), sign);
|
|
break;
|
|
case 36:
|
|
emitAsm(location, w, "", "BFA", sign);
|
|
break;
|
|
case 37:
|
|
emitAsm(location, w, "", "BFR", sign);
|
|
break;
|
|
case 38:
|
|
emitAsm(location, w, "", "BCS", sign);
|
|
break;
|
|
case 39:
|
|
if ((control & 0x02) == 0x02) {
|
|
emitAsm(location, w, "", "IOM", sign);
|
|
} else if ((control & 0x01) == 0x01) {
|
|
emitAsm(location, w, "", "SOH", sign);
|
|
} else {
|
|
emitAsm(location, w, "", "SOR", sign);
|
|
}
|
|
break;
|
|
case 40:
|
|
switch (control%10) {
|
|
case 2:
|
|
emitAsm(location, w, "", "STB", sign);
|
|
break;
|
|
case 1:
|
|
emitAsm(location, w, "", "STR", sign);
|
|
break;
|
|
default:
|
|
emitAsm(location, w, "", "STA", sign);
|
|
break;
|
|
}
|
|
break;
|
|
case 41:
|
|
emitAsm(location, w, "", "LDR", sign);
|
|
break;
|
|
case 42:
|
|
emitAsm(location, w, "", (control%10==1 ? "LBC" : "LDB"), sign);
|
|
break;
|
|
case 43:
|
|
emitAsm(location, w, "", "LSA", sign);
|
|
break;
|
|
case 44:
|
|
emitAsm(location, w, "", "STP", sign);
|
|
break;
|
|
case 45:
|
|
switch (control%10) {
|
|
case 1:
|
|
case 9:
|
|
emitAsm(location, w, "", "CLA", sign);
|
|
break;
|
|
case 2:
|
|
emitAsm(location, w, "", "CLR", sign);
|
|
break;
|
|
case 3:
|
|
emitAsm(location, w, "", "CAR", sign);
|
|
break;
|
|
case 4:
|
|
emitAsm(location, w, "", "CLB", sign);
|
|
break;
|
|
case 5:
|
|
emitAsm(location, w, "", "CAB", sign);
|
|
break;
|
|
case 6:
|
|
emitAsm(location, w, "", "CRB", sign);
|
|
break;
|
|
case 7:
|
|
emitAsm(location, w, "", "CLT", sign);
|
|
break;
|
|
default:
|
|
emitConstant(location, w, "", sign, "**INVALID CLEAR REG**");
|
|
break;
|
|
}
|
|
break;
|
|
case 46:
|
|
emitAsm(location, w, "", "CLL", sign);
|
|
break;
|
|
case 48:
|
|
switch (control%10) {
|
|
case 1:
|
|
emitAsm(location, w, "", "SRT", sign);
|
|
break;
|
|
case 2:
|
|
emitAsm(location, w, "", "SRS", sign);
|
|
break;
|
|
default:
|
|
emitAsm(location, w, "", "SRA", sign);
|
|
break;
|
|
}
|
|
break;
|
|
case 49:
|
|
switch (control%10) {
|
|
case 1:
|
|
emitAsm(location, w, "", "SLT", sign);
|
|
break;
|
|
case 2:
|
|
emitAsm(location, w, "", "SLS", sign);
|
|
break;
|
|
default:
|
|
emitAsm(location, w, "", "SLA", sign);
|
|
break;
|
|
}
|
|
break;
|
|
case 50:
|
|
switch (control%10) {
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
if ((sign & 0x04) == 0x04) {
|
|
emitAsm(location, w, "", "MFS", sign);
|
|
} else {
|
|
emitAsm(location, w, "", "MTS", sign);
|
|
}
|
|
break;
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
emitAsm(location, w, "", "MLS", sign);
|
|
break;
|
|
case 8:
|
|
emitAsm(location, w, "", "MRW", sign);
|
|
break;
|
|
case 9:
|
|
emitAsm(location, w, "", "MDA", sign);
|
|
break;
|
|
default:
|
|
emitConstant(location, w, "", sign, "**INVALID MAG TAPE**");
|
|
break;
|
|
}
|
|
break;
|
|
case 51:
|
|
if ((sign & 0x04) == 0x04) {
|
|
emitAsm(location, w, "", "MFC", sign);
|
|
} else {
|
|
emitAsm(location, w, "", "MTC", sign);
|
|
}
|
|
break;
|
|
case 52:
|
|
emitAsm(location, w, "", "MRD", sign);
|
|
break;
|
|
case 53:
|
|
emitAsm(location, w, "", "MRR", sign);
|
|
break;
|
|
case 54:
|
|
emitAsm(location, w, "", "MIW", sign);
|
|
break;
|
|
case 55:
|
|
emitAsm(location, w, "", "MIR", sign);
|
|
break;
|
|
case 56:
|
|
emitAsm(location, w, "", "MOW", sign);
|
|
break;
|
|
case 57:
|
|
emitAsm(location, w, "", "MOR", sign);
|
|
break;
|
|
case 58:
|
|
switch (control%10) {
|
|
case 1:
|
|
emitAsm(location, w, "", "MPB", sign);
|
|
break;
|
|
case 2:
|
|
emitAsm(location, w, "", "MPE", sign);
|
|
break;
|
|
default:
|
|
emitAsm(location, w, "", "MPF", sign);
|
|
break;
|
|
}
|
|
break;
|
|
case 59:
|
|
switch (control%10) {
|
|
case 1:
|
|
emitAsm(location, w, "", "MIE", sign);
|
|
break;
|
|
default:
|
|
emitAsm(location, w, "", "MIB", sign);
|
|
break;
|
|
}
|
|
break;
|
|
case 60:
|
|
emitAsm(location, w, "", "CRD", sign);
|
|
break;
|
|
case 61:
|
|
emitAsm(location, w, "", "CWR", sign);
|
|
break;
|
|
case 62:
|
|
emitAsm(location, w, "", "CRF", sign);
|
|
break;
|
|
case 63:
|
|
emitAsm(location, w, "", "CWF", sign);
|
|
break;
|
|
case 64:
|
|
emitAsm(location, w, "", "CRI", sign);
|
|
break;
|
|
case 65:
|
|
emitAsm(location, w, "", "CWI", sign);
|
|
break;
|
|
case 66:
|
|
emitAsm(location, w, "", "HPW", sign);
|
|
break;
|
|
case 67:
|
|
emitAsm(location, w, "", "HPI", sign);
|
|
break;
|
|
default:
|
|
emitConstant(location, w, "", sign);
|
|
break;
|
|
}
|
|
|
|
++location;
|
|
}
|
|
|
|
/**************************************/
|
|
function disassembleFile() {
|
|
/* Initializes or reinitializes the assembler for a new file */
|
|
var stamp = new Date();
|
|
|
|
clearPanel();
|
|
printLine("Disassembler for the Burroughs 220 BALGOL Compiler & Library -- " +
|
|
stamp.getFullYear().toString() + "-" +
|
|
padLeft(stamp.getMonth()+1, 2, "0") + "-" +
|
|
padLeft(stamp.getDate(), 2, "0") + " " +
|
|
padLeft(stamp.getHours(), 2, "0") + ":" +
|
|
padLeft(stamp.getMinutes(), 2, "0"));
|
|
printLine("");
|
|
printLine("Source File: " + sourceName);
|
|
printLine("");
|
|
|
|
errorCount = 0;
|
|
lineNr = 0;
|
|
location = 0;
|
|
wordData.atEOF = false;
|
|
wordData.serial = 0;
|
|
startAddress = 0;
|
|
|
|
emitPseudo(0, null, "", "REM", 0, "", sourceName.toUpperCase());
|
|
do {
|
|
disassembleWord();
|
|
} while (!wordData.atEOF);
|
|
|
|
emitPseudo(location, null, "", "FINI", 0, startAddress)
|
|
document.body.removeChild($$("Spinner")); // remove the spinner image
|
|
$$("CRFileSelector").value = null; // reset the <input> elements
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
* Initialization and Termination *
|
|
*******************************************************************/
|
|
|
|
/**************************************/
|
|
function configureOutput() {
|
|
/* Determines the output mode. Opens the source deck window if
|
|
needed and sets it up. Finally, calls disassembleFile() */
|
|
var index = 0;
|
|
var select = $$("OutputModeSelect");
|
|
var title = "220 BAC-Disassembler Source Deck";
|
|
|
|
function configureDeck(ev) {
|
|
generateDeck = true;
|
|
deckWin.removeEventListener("load", configureDeck, false);
|
|
deckDoc = deckWin.document;
|
|
deckDoc.title = title;
|
|
deck = deckDoc.getElementById("Paper");
|
|
deckWin.moveTo((screen.availWidth-deckWin.outerWidth)/2,
|
|
(screen.availHeight-deckWin.outerHeight)/2);
|
|
setTimeout(disassembleFile, 100);
|
|
}
|
|
|
|
index = select.selectedIndex;
|
|
if (index < 0) {
|
|
setTimeout(disassembleFile, 100);
|
|
} else {
|
|
switch (select.options[index].value) {
|
|
case "D":
|
|
if (!deckWin) {
|
|
deckWin = window.open("", "BAC-Asm-Source", "");
|
|
}
|
|
|
|
deckWin.close();
|
|
deckWin = window.open("../../webUI/B220FramePaper.html", "BAC-Asm-Source",
|
|
"scrollbars,resizable,width=600,height=500");
|
|
deckWin.addEventListener("load", configureDeck, false);
|
|
break;
|
|
default:
|
|
setTimeout(disassembleFile, 100);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**************************************/
|
|
function loadCodeFile(ev) {
|
|
/* Handle the <input type=file> onchange event when a file is selected */
|
|
var e; // spinner image DOM element
|
|
var f = ev.target.files[0];
|
|
var reader = new FileReader();
|
|
|
|
function fileLoader_onLoad(ev) {
|
|
/* Handles the onload event for a readAsText FileReader */
|
|
|
|
buffer = ev.target.result;
|
|
bufferOffset = 0;
|
|
bufferLength = buffer.length;
|
|
configureOutput();
|
|
}
|
|
|
|
sourceName = f.name;
|
|
/********************
|
|
alert("File selected: " + f.name +
|
|
"\nModified " + f.lastModifiedDate +
|
|
"\nType=" + f.type + ", Size=" + f.size + " octets");
|
|
********************/
|
|
|
|
// initiate the spinner to run while disassembling
|
|
e = document.createElement("img");
|
|
e.src = "../../webUI/resources/ajax-spinner.gif";
|
|
e.id = "Spinner";
|
|
document.body.appendChild(e);
|
|
|
|
reader.onload = fileLoader_onLoad;
|
|
reader.readAsText(f);
|
|
}
|
|
|
|
/**************************************/
|
|
function checkBrowser() {
|
|
/* Checks whether this browser can support the necessary stuff */
|
|
var missing = "";
|
|
|
|
if (!window.File ) {missing += ", File"}
|
|
if (!window.FileReader ) {missing += ", FileReader"}
|
|
if (!window.FileList ) {missing += ", FileList"}
|
|
if (!window.DOMTokenList) {missing += ", DOMTokenList"}
|
|
if (!window.ArrayBuffer ) {missing += ", ArrayBuffer"}
|
|
if (!window.DataView ) {missing += ", DataView"}
|
|
if (!window.Promise ) {missing += ", Promise"}
|
|
|
|
if (missing.length == 0) {
|
|
return false;
|
|
} else {
|
|
alert("No can do... your browser does not\n" +
|
|
"support the following features:\n" + missing.substring(2));
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/**************************************/
|
|
function repositionTextPanel() {
|
|
/* Repositions and resizes the #TextPanel element so that it fills the
|
|
bottom portion of the window */
|
|
var opts = $$("OptionsDiv");
|
|
var panel = $$("TextPanel");
|
|
|
|
panel.style.top = (opts.offsetTop + opts.offsetHeight + 8).toFixed() + "px";
|
|
}
|
|
|
|
/******************** Start of window.onload() ********************/
|
|
repositionTextPanel();
|
|
if (checkBrowser()) {
|
|
return;
|
|
}
|
|
|
|
$$("CRFileSelector").value = null; // clear any prior file selection
|
|
$$("CRFileSelector").addEventListener("change", loadCodeFile, false);
|
|
|
|
pass1List = $$("Pass1ListCheck").checked;
|
|
$$("Pass1ListCheck").addEventListener("click", function(ev) {
|
|
pass1List = ev.target.checked;
|
|
});
|
|
|
|
pass2List = $$("Pass2ListCheck").checked;
|
|
$$("Pass2ListCheck").addEventListener("click", function(ev) {
|
|
pass2List = ev.target.checked;
|
|
});
|
|
|
|
$$("ExtractListing").addEventListener("click", extractListing);
|
|
}, false);
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|