1 |
29 |
eightycc |
//////////////////////////////////////////////////////////////////////////////////
|
2 |
|
|
// IBM 650 Reconstruction in Verilog (i650)
|
3 |
|
|
//
|
4 |
|
|
// This file is part of the IBM 650 Reconstruction in Verilog (i650) project
|
5 |
|
|
// http:////www.opencores.org/project,i650
|
6 |
|
|
//
|
7 |
|
|
// Description: An implementation of SOAP 2 for the IBM 650.
|
8 |
|
|
//
|
9 |
|
|
// Additional Comments: .
|
10 |
|
|
//
|
11 |
|
|
// Copyright (c) 2015 Robert Abeles
|
12 |
|
|
//
|
13 |
|
|
// This source file is free software; you can redistribute it
|
14 |
|
|
// and/or modify it under the terms of the GNU Lesser General
|
15 |
|
|
// Public License as published by the Free Software Foundation;
|
16 |
|
|
// either version 2.1 of the License, or (at your option) any
|
17 |
|
|
// later version.
|
18 |
|
|
//
|
19 |
|
|
// This source is distributed in the hope that it will be
|
20 |
|
|
// useful, but WITHOUT ANY WARRANTY; without even the implied
|
21 |
|
|
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
22 |
|
|
// PURPOSE. See the GNU Lesser General Public License for more
|
23 |
|
|
// details.
|
24 |
|
|
//
|
25 |
|
|
// You should have received a copy of the GNU Lesser General
|
26 |
|
|
// Public License along with this source; if not, download it
|
27 |
|
|
// from http://www.opencores.org/lgpl.shtml
|
28 |
|
|
//////////////////////////////////////////////////////////////////////////////////
|
29 |
|
|
|
30 |
|
|
#include "ibm_codec.h"
|
31 |
|
|
#include <iostream>
|
32 |
|
|
#include <iomanip>
|
33 |
|
|
|
34 |
|
|
using namespace std;
|
35 |
|
|
|
36 |
|
|
// -------------------------------------------------------------------------
|
37 |
|
|
// Hollerith zone and digit punches.
|
38 |
|
|
// -------------------------------------------------------------------------
|
39 |
|
|
enum holl_zn {
|
40 |
|
|
holl_znone,
|
41 |
|
|
holl_z0,
|
42 |
|
|
holl_z11, // aka X punch
|
43 |
|
|
holl_z12 // aka Y punch
|
44 |
|
|
};
|
45 |
|
|
enum holl_dig {
|
46 |
|
|
holl_dnone,
|
47 |
|
|
holl_d0,
|
48 |
|
|
holl_d1,
|
49 |
|
|
holl_d2,
|
50 |
|
|
holl_d3,
|
51 |
|
|
holl_d4,
|
52 |
|
|
holl_d5,
|
53 |
|
|
holl_d6,
|
54 |
|
|
holl_d7,
|
55 |
|
|
holl_d8,
|
56 |
|
|
holl_d9,
|
57 |
|
|
holl_d8_2,
|
58 |
|
|
holl_d8_3,
|
59 |
|
|
holl_d8_4,
|
60 |
|
|
holl_d8_5,
|
61 |
|
|
holl_d8_6,
|
62 |
|
|
holl_d8_7
|
63 |
|
|
};
|
64 |
|
|
|
65 |
|
|
// -------------------------------------------------------------------------
|
66 |
|
|
// Glyph specification.
|
67 |
|
|
// -------------------------------------------------------------------------
|
68 |
|
|
struct glyph_spec {
|
69 |
|
|
holl_zn zone;
|
70 |
|
|
holl_dig digit;
|
71 |
|
|
int unicode;
|
72 |
|
|
int ascii;
|
73 |
|
|
int keycode; // Qt keycode
|
74 |
|
|
int code650;
|
75 |
|
|
int bcd704;
|
76 |
|
|
int bcd705;
|
77 |
|
|
int codeset;
|
78 |
|
|
};
|
79 |
|
|
|
80 |
|
|
// -------------------------------------------------------------------------
|
81 |
|
|
// Not all BCD characters have readily available keyboard equivalents.
|
82 |
|
|
// To these characters, we assign a modifier plus an alphabetic key.
|
83 |
|
|
// When the keycode field is not negative, it contains the unmodified
|
84 |
|
|
// keycode of the alphabetic key that when entered with a platform-
|
85 |
|
|
// pecific modifier key will enter the unavailable code. For example,
|
86 |
|
|
// pressing alt-R on a Mac will enter the unicode 'square root' character.
|
87 |
|
|
// Pressing the modifier key with a digit, '-', or '=' key will act
|
88 |
|
|
// as a multipunch, where '-' is an 11 punch and '=' is a 12 punch.
|
89 |
|
|
//
|
90 |
|
|
// The special characters in the final group, shown below, have
|
91 |
|
|
// several alternate encodings, designated by IBM as special character
|
92 |
|
|
// arrangements A through K. Encodings A, F and H are implemented above.
|
93 |
|
|
//
|
94 |
|
|
// A - &.^-$*,%/#@
|
95 |
|
|
// B - /.^-$*,%&#@
|
96 |
|
|
// C - &.^-$*,%0#@
|
97 |
|
|
// D - -.^-$*,%/#@
|
98 |
|
|
// E - -.<./*,%&#>
|
99 |
|
|
// F - +.)-$*,(/=-
|
100 |
|
|
// G - +.^-$*,%/+-
|
101 |
|
|
// H - +.)-$*,(/='
|
102 |
|
|
// J - +.^-$*,%/#@
|
103 |
|
|
// K - +.)-$*,(/=@
|
104 |
|
|
//
|
105 |
|
|
// In addition to the standard 48 BCD encodings shown above, the 705
|
106 |
|
|
// uses 6 additional encodings, 4 for marks (tape mark, record mark,
|
107 |
|
|
// group mark, storage and drum mark), and 2 encodings for signed zeroes
|
108 |
|
|
// (plus zero, minus zero).
|
109 |
|
|
//
|
110 |
|
|
// A word about marks. Some of the BCD character codes have special meaning to
|
111 |
|
|
// early IBM business computers. The 702 and its successor machines (705, 7070)
|
112 |
|
|
// were 'character oriented', i.e., they operated on variable length BCD character
|
113 |
|
|
// strings. Mark characters ('tape mark', 'record mark', 'group mark',
|
114 |
|
|
// 'segment mark', and 'word separator') served to delineate variable length
|
115 |
|
|
// objects on tape and in memory.
|
116 |
|
|
//
|
117 |
|
|
// In fact, a six bit character can have 64 unique values. The remaining
|
118 |
|
|
// unused BCD character codes were assigned by subsequent machines until
|
119 |
|
|
// all possible codes were accounted for. Mappings between BCD and Hollerith
|
120 |
|
|
// remain stable across the IBM product line, but glyph assignment differs
|
121 |
|
|
// between systems, options, and RPQs.
|
122 |
|
|
// -------------------------------------------------------------------------
|
123 |
|
|
#define A48 cs_bcd48_a
|
124 |
|
|
#define F48 cs_bcd48_f
|
125 |
|
|
#define H48 cs_bcd48_h
|
126 |
|
|
#define BCD48 cs_bcd48
|
127 |
|
|
#define BCD64 cs_bcd64
|
128 |
|
|
|
129 |
|
|
static glyph_spec glyph_codes[] = {
|
130 |
|
|
// zone digit unicode ascii keycd 650 704 14xx codeset(s)
|
131 |
|
|
// BCD BCD BCD
|
132 |
|
|
{holl_znone, holl_dnone, ' ', ' ', -1, 00, 060, 000, BCD48},
|
133 |
|
|
{holl_znone, holl_d0, '0', '0', -1, 90, 000, 012, BCD48},
|
134 |
|
|
{holl_znone, holl_d1, '1', '1', -1, 91, 001, 001, BCD48},
|
135 |
|
|
{holl_znone, holl_d2, '2', '2', -1, 92, 002, 002, BCD48},
|
136 |
|
|
{holl_znone, holl_d3, '3', '3', -1, 93, 003, 003, BCD48},
|
137 |
|
|
{holl_znone, holl_d4, '4', '4', -1, 94, 004, 004, BCD48},
|
138 |
|
|
{holl_znone, holl_d5, '5', '5', -1, 95, 005, 005, BCD48},
|
139 |
|
|
{holl_znone, holl_d6, '6', '6', -1, 96, 006, 006, BCD48},
|
140 |
|
|
{holl_znone, holl_d7, '7', '7', -1, 97, 007, 007, BCD48},
|
141 |
|
|
{holl_znone, holl_d8, '8', '8', -1, 98, 010, 010, BCD48},
|
142 |
|
|
{holl_znone, holl_d9, '9', '9', -1, 99, 011, 011, BCD48},
|
143 |
|
|
|
144 |
|
|
{holl_z12, holl_d0, '?', '?', -1, -1, 032, 072, BCD64}, // plus zero
|
145 |
|
|
{holl_z12, holl_d1, 'A', 'A', -1, 61, 021, 061, BCD48},
|
146 |
|
|
{holl_z12, holl_d2, 'B', 'B', -1, 62, 022, 062, BCD48},
|
147 |
|
|
{holl_z12, holl_d3, 'C', 'C', -1, 63, 023, 063, BCD48},
|
148 |
|
|
{holl_z12, holl_d4, 'D', 'D', -1, 64, 024, 064, BCD48},
|
149 |
|
|
{holl_z12, holl_d5, 'E', 'E', -1, 65, 025, 065, BCD48},
|
150 |
|
|
{holl_z12, holl_d6, 'F', 'F', -1, 66, 026, 066, BCD48},
|
151 |
|
|
{holl_z12, holl_d7, 'G', 'G', -1, 67, 027, 067, BCD48},
|
152 |
|
|
{holl_z12, holl_d8, 'H', 'H', -1, 68, 030, 070, BCD48},
|
153 |
|
|
{holl_z12, holl_d9, 'I', 'I', -1, 69, 031, 071, BCD48},
|
154 |
|
|
|
155 |
|
|
{holl_z11, holl_d0, '!', '!', -1, -1, 052, 052, BCD64}, // minus zero
|
156 |
|
|
{holl_z11, holl_d1, 'J', 'J', -1, 71, 041, 041, BCD48},
|
157 |
|
|
{holl_z11, holl_d2, 'K', 'K', -1, 72, 042, 042, BCD48},
|
158 |
|
|
{holl_z11, holl_d3, 'L', 'L', -1, 73, 043, 043, BCD48},
|
159 |
|
|
{holl_z11, holl_d4, 'M', 'M', -1, 74, 044, 044, BCD48},
|
160 |
|
|
{holl_z11, holl_d5, 'N', 'N', -1, 75, 045, 045, BCD48},
|
161 |
|
|
{holl_z11, holl_d6, 'O', 'O', -1, 76, 046, 046, BCD48},
|
162 |
|
|
{holl_z11, holl_d7, 'P', 'P', -1, 77, 047, 047, BCD48},
|
163 |
|
|
{holl_z11, holl_d8, 'Q', 'Q', -1, 78, 050, 050, BCD48},
|
164 |
|
|
{holl_z11, holl_d9, 'R', 'R', -1, 79, 051, 051, BCD48},
|
165 |
|
|
|
166 |
|
|
{holl_z0, holl_d1, '/', '/', -1, 31, 061, 021, A48+F48+H48},
|
167 |
|
|
{holl_z0, holl_d2, 'S', 'S', -1, 82, 062, 022, BCD48},
|
168 |
|
|
{holl_z0, holl_d3, 'T', 'T', -1, 83, 063, 023, BCD48},
|
169 |
|
|
{holl_z0, holl_d4, 'U', 'U', -1, 84, 064, 024, BCD48},
|
170 |
|
|
{holl_z0, holl_d5, 'V', 'V', -1, 85, 065, 025, BCD48},
|
171 |
|
|
{holl_z0, holl_d6, 'W', 'W', -1, 86, 066, 026, BCD48},
|
172 |
|
|
{holl_z0, holl_d7, 'X', 'X', -1, 87, 067, 027, BCD48},
|
173 |
|
|
{holl_z0, holl_d8, 'Y', 'Y', -1, 88, 070, 030, BCD48},
|
174 |
|
|
{holl_z0, holl_d9, 'Z', 'Z', -1, 89, 071, 031, BCD48},
|
175 |
|
|
|
176 |
|
|
{holl_z12, holl_dnone, '&', '&', -1, 20, 020, 060, A48},
|
177 |
|
|
{holl_z12, holl_dnone, '+', '+', -1, 20, 020, 060, F48+H48},
|
178 |
|
|
{holl_z12, holl_d8_3, '.', '.', -1, 18, 033, 073, A48+F48+H48},
|
179 |
|
|
{holl_z12, holl_d8_4, L'⌑', '^', 'L', 19, 034, 074, A48}, // unicode 'square lozenge'
|
180 |
|
|
{holl_z12, holl_d8_4, ')', ')', -1, 19, 034, 074, F48+H48},
|
181 |
|
|
{holl_z12, holl_d8_5, '[', '[', -1, -1, 035, 075, BCD64},
|
182 |
|
|
{holl_z12, holl_d8_6, '<', '<', -1, -1, 036, 076, BCD64},
|
183 |
|
|
{holl_z12, holl_d8_7,L'\uF000', -1, 'G', -1, 037, 077, BCD64}, // group mark, use uF000 for triple dagger
|
184 |
|
|
|
185 |
|
|
{holl_z11, holl_dnone, '-', '-', -1, 30, 040, 040, A48+F48+H48},
|
186 |
|
|
{holl_z11, holl_d8_3, '$', '$', -1, 28, 053, 053, A48+F48+H48},
|
187 |
|
|
{holl_z11, holl_d8_4, '*', '*', -1, 29, 054, 054, A48+F48+H48},
|
188 |
|
|
{holl_z11, holl_d8_5, ']', ']', -1, 29, 055, 055, BCD64},
|
189 |
|
|
{holl_z11, holl_d8_6, ';', ';', -1, 29, 056, 056, BCD64},
|
190 |
|
|
{holl_z11, holl_d8_7,L'\uF004', -1, 'D', 29, 057, 057, BCD64}, // delta -> unicode uppercase delta
|
191 |
|
|
|
192 |
|
|
{holl_z0, holl_d8_2, L'‡', -1, 'R', -1, 073, 033, BCD64}, // record mark -> double dagger
|
193 |
|
|
{holl_z0, holl_d8_3, ',', ',', -1, 38, 073, 033, A48+F48+H48},
|
194 |
|
|
{holl_z0, holl_d8_4, '%', '%', -1, 39, 074, 034, A48},
|
195 |
|
|
{holl_z0, holl_d8_4, '(', '(', -1, 39, 074, 034, F48+H48},
|
196 |
|
|
{holl_z0, holl_d8_5,L'\u2423', -1, 'W', -1, 075, 035, BCD64}, // word separator -> open box
|
197 |
|
|
{holl_z0, holl_d8_6, '\\', '\\', -1, -1, 076, 036, BCD64}, // left oblique
|
198 |
|
|
{holl_z0, holl_d8_7,L'\u29FB', -1, 'S', -1, 077, 037, BCD64}, // segment mark -> triple plus
|
199 |
|
|
|
200 |
|
|
{holl_znone, holl_d8_2,L'\u2422',' ', ' ', -1, 060, 020, BCD64}, // alternate blank
|
201 |
|
|
{holl_znone, holl_d8_3, '#', '#', -1, 48, 013, 013, A48},
|
202 |
|
|
{holl_znone, holl_d8_3, '=', '=', -1, 48, 013, 013, F48+H48},
|
203 |
|
|
{holl_znone, holl_d8_4, '@', '@', -1, 49, 014, 014, A48},
|
204 |
|
|
{holl_znone, holl_d8_4, '-', '-', -1, 49, 014, 014, F48}, // FORTRAN's other minus
|
205 |
|
|
{holl_znone, holl_d8_4, '\'', '\'', -1, 49, 014, 014, H48},
|
206 |
|
|
{holl_znone, holl_d8_5, ':', ':', -1, -1, 015, 015, BCD64}, // colon
|
207 |
|
|
{holl_znone, holl_d8_6, '>', '>', -1, -1, 016, 016, BCD64}, // greater than
|
208 |
|
|
{holl_znone, holl_d8_7, L'√', -1, 'T', -1, 017, 017, BCD64} // radical
|
209 |
|
|
};
|
210 |
|
|
|
211 |
|
|
static uint16_t make_holl(int z, int d)
|
212 |
|
|
{
|
213 |
|
|
uint16_t h = 0;
|
214 |
|
|
switch (z) {
|
215 |
|
|
case holl_znone:
|
216 |
|
|
break;
|
217 |
|
|
case holl_z0:
|
218 |
|
|
h += (1 << 9);
|
219 |
|
|
break;
|
220 |
|
|
case holl_z11:
|
221 |
|
|
h += (1 << 10);
|
222 |
|
|
break;
|
223 |
|
|
case holl_z12:
|
224 |
|
|
h += (1 << 11);
|
225 |
|
|
break;
|
226 |
|
|
default:
|
227 |
|
|
break;
|
228 |
|
|
}
|
229 |
|
|
switch (d) {
|
230 |
|
|
case holl_dnone:
|
231 |
|
|
break;
|
232 |
|
|
case holl_d0:
|
233 |
|
|
h += (1 << 9);
|
234 |
|
|
break;
|
235 |
|
|
case holl_d1:
|
236 |
|
|
h += (1 << 8);
|
237 |
|
|
break;
|
238 |
|
|
case holl_d2:
|
239 |
|
|
h += (1 << 7);
|
240 |
|
|
break;
|
241 |
|
|
case holl_d3:
|
242 |
|
|
h += (1 << 6);
|
243 |
|
|
break;
|
244 |
|
|
case holl_d4:
|
245 |
|
|
h += (1 << 5);
|
246 |
|
|
break;
|
247 |
|
|
case holl_d5:
|
248 |
|
|
h += (1 << 4);
|
249 |
|
|
break;
|
250 |
|
|
case holl_d6:
|
251 |
|
|
h += (1 << 3);
|
252 |
|
|
break;
|
253 |
|
|
case holl_d7:
|
254 |
|
|
h += (1 << 2);
|
255 |
|
|
break;
|
256 |
|
|
case holl_d8:
|
257 |
|
|
h += (1 << 1);
|
258 |
|
|
break;
|
259 |
|
|
case holl_d9:
|
260 |
|
|
h += (1 << 0);
|
261 |
|
|
break;
|
262 |
|
|
case holl_d8_2:
|
263 |
|
|
h += (1 << 1) + (1 << 7);
|
264 |
|
|
break;
|
265 |
|
|
case holl_d8_3:
|
266 |
|
|
h += (1 << 1) + (1 << 6);
|
267 |
|
|
break;
|
268 |
|
|
case holl_d8_4:
|
269 |
|
|
h += (1 << 1) + (1 << 5);
|
270 |
|
|
break;
|
271 |
|
|
case holl_d8_5:
|
272 |
|
|
h += (1 << 1) + (1 << 4);
|
273 |
|
|
break;
|
274 |
|
|
case holl_d8_6:
|
275 |
|
|
h += (1 << 1) + (1 << 3);
|
276 |
|
|
break;
|
277 |
|
|
case holl_d8_7:
|
278 |
|
|
h += (1 << 1) + (1 << 2);
|
279 |
|
|
break;
|
280 |
|
|
default:
|
281 |
|
|
break;
|
282 |
|
|
}
|
283 |
|
|
return h;
|
284 |
|
|
}
|
285 |
|
|
|
286 |
|
|
void ibm_codec::setup_tables(int c) {
|
287 |
|
|
hollerith_to_code650_.resize(4096);
|
288 |
|
|
code650_to_hollerith_.resize(100);
|
289 |
|
|
hollerith_to_unicode_.resize(4096);
|
290 |
|
|
unicode_to_hollerith_.resize(65536);
|
291 |
|
|
hollerith_to_ascii_ .resize(4096);
|
292 |
|
|
ascii_to_hollerith_ .resize(256);
|
293 |
|
|
ascii_to_code650_ .resize(256);
|
294 |
|
|
code650_to_ascii_ .resize(100);
|
295 |
|
|
keycode_to_unicode_ .resize(256);
|
296 |
|
|
|
297 |
|
|
// mark all translations invalid (-1)
|
298 |
|
|
for (int i = 0; i < 65536; i++) {
|
299 |
|
|
unicode_to_hollerith_[i] = -1;
|
300 |
|
|
if (i < 4096) {
|
301 |
|
|
hollerith_to_code650_[i] = -1;
|
302 |
|
|
hollerith_to_unicode_[i] = -1;
|
303 |
|
|
hollerith_to_ascii_[i] = -1;
|
304 |
|
|
}
|
305 |
|
|
if (i < 256) {
|
306 |
|
|
ascii_to_code650_[i] = -1;
|
307 |
|
|
ascii_to_hollerith_[i] = -1;
|
308 |
|
|
keycode_to_unicode_[i] = -1;
|
309 |
|
|
}
|
310 |
|
|
if (i < 100) {
|
311 |
|
|
code650_to_hollerith_[i] = -1;
|
312 |
|
|
code650_to_ascii_[i] = -1;
|
313 |
|
|
}
|
314 |
|
|
}
|
315 |
|
|
|
316 |
|
|
// Fill in glyphs from table that are in the specified codeset(s).
|
317 |
|
|
// When multiple glyphs map to the same codepoint, the first
|
318 |
|
|
// glyph encoutered in the table occupying a codepoint takes
|
319 |
|
|
// precedence.
|
320 |
|
|
for (auto glyph : glyph_codes) {
|
321 |
|
|
if (!(glyph.codeset & c)) continue;
|
322 |
|
|
uint16_t hcode = make_holl(glyph.zone, glyph.digit);
|
323 |
|
|
if (hollerith_to_code650_[hcode] < 0)
|
324 |
|
|
hollerith_to_code650_[hcode] = glyph.code650;
|
325 |
|
|
if (code650_to_hollerith_[glyph.code650] < 0)
|
326 |
|
|
code650_to_hollerith_[glyph.code650] = hcode;
|
327 |
|
|
if (hollerith_to_unicode_[hcode] < 0)
|
328 |
|
|
hollerith_to_unicode_[hcode] = glyph.unicode;
|
329 |
|
|
if (unicode_to_hollerith_[glyph.unicode] < 0)
|
330 |
|
|
unicode_to_hollerith_[glyph.unicode] = hcode;
|
331 |
|
|
if (keycode_to_unicode_[glyph.keycode] < 0)
|
332 |
|
|
keycode_to_unicode_[glyph.keycode] = glyph.unicode;
|
333 |
|
|
if (hollerith_to_ascii_[hcode] < 0)
|
334 |
|
|
hollerith_to_ascii_[hcode] = glyph.ascii;
|
335 |
|
|
if (ascii_to_hollerith_[glyph.ascii] < 0)
|
336 |
|
|
ascii_to_hollerith_[glyph.ascii] = hcode;
|
337 |
|
|
if (ascii_to_code650_[glyph.ascii] < 0)
|
338 |
|
|
ascii_to_code650_[glyph.ascii] = glyph.code650;
|
339 |
|
|
if (code650_to_ascii_[glyph.code650] < 0)
|
340 |
|
|
code650_to_ascii_[glyph.code650] = glyph.ascii;
|
341 |
|
|
}
|
342 |
|
|
}
|