OpenCores
URL https://opencores.org/ocsvn/i650/i650/trunk

Subversion Repositories i650

[/] [i650/] [trunk/] [utils/] [ibm650_soap2/] [ibm650_soap2/] [soap2.cpp] - Blame information for rev 29

Details | Compare with Previous | View Log

Line No. Rev Author Line
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 "soap2.h"
31
 
32
static addr_type get_addr_type(int32_t addr)
33
{
34
    if ((addr >= 0) && (addr <= 1999))
35
        return addr_gs;
36
    if ((addr >= 9000) && (addr <= 9059))
37
        return addr_ias;
38
    if ((addr >= 8000) && (addr <= 8003))
39
        return addr_800X;
40
    if ((addr >= 8005) && (addr <= 8007))
41
        return addr_800X;
42
 
43
    return addr_invalid;
44
}
45
 
46
static inline char zone_x(int c)
47
{
48
    c = (c < '0')? '0' : (c > '9')? '9' : c;
49
    c = (c == '0')? '!' : (c - '0' + 'J');
50
    return c;
51
}
52
 
53
static inline char zone_y(int c)
54
{
55
    c = (c < '0')? '0' : (c > '9')? '9' : c;
56
    c = (c == '0')? '?' : (c - '0' + 'A');
57
    return c;
58
}
59
 
60
asmfield::asmfield(const string &f, u_int8_t h) : src(f), type(field_error)
61
{
62
    if (src == "     ") {
63
        type = field_blank;
64
        return;
65
    }
66
 
67
    if (src[0] == ' ') {
68
        for (int i = 1; i < 5; i++)
69
            if (!isdigit(src[i])) return;
70
        type = field_numeric;
71
        nval = stoi(src.substr(1,4));
72
        return;
73
    }
74
 
75
    if (isalpha(src[0])) {
76
        bool numeric = true;
77
        for (int i = 1; i < 5; i++)
78
            if (!isdigit(src[i])) numeric = false;
79
        if (numeric) {
80
            type = field_region;
81
            nval = stoi(src.substr(1, 4));
82
            region = src[0];
83
            return;
84
        }
85
    }
86
 
87
    type = field_symbolic;
88
    symbol = src;
89
    if (symbol[4] == ' ')
90
        symbol[4] = h;
91
}
92
 
93
void memory::load_7wd_deck(istream &d7)
94
{
95
    bool ctl_word = true;
96
    bool op_fld   = true;
97
    bool op_d     = false;
98
    bool op_i     = false;
99
    string number = "";
100
    char ch;
101
 
102
    bool word_valid = false;
103
    u_int32_t addr = 0;
104
    bool sign = false; // true is minus
105
    u_int32_t op = 0;
106
    u_int32_t d  = 0;
107
    u_int32_t i  = 0;
108
 
109
    while (EOF != (ch = d7.get())) {
110
        if ('\n' == ch) {
111
            if (word_valid) {
112
                i = stoi(number);
113
                int64_t v = op * 100000000LL + d * 10000 + i;
114
                mem[addr].set_sign(sign);
115
                mem[addr].set_value(v);
116
                addr++;
117
                sign = false;
118
                op = d = i = 0;
119
                word_valid = false;
120
            }
121
            ctl_word = true;
122
            op_fld   = true;
123
            op_d     = false;
124
            op_i     = false;
125
            number   = "";
126
        } else if (isdigit(ch)) {
127
            word_valid = true;
128
            number += ch;
129
        } else if (' ' == ch) {
130
            if (number != "") {
131
                if (op_fld) {
132
                    op = stoi(number);
133
                    op_fld = false;
134
                    op_d = true;
135
                } else if (op_d) {
136
                    d = stoi(number);
137
                    op_d = false;
138
                    op_i = true;
139
                } else if (op_i) {
140
                    i = stoi(number);
141
                    op_i = false;
142
                    op_fld = true;
143
                    if (ctl_word) {
144
                        addr = d;
145
                        ctl_word = false;
146
                    } else {
147
                        int64_t v = op * 100000000LL + d * 10000 + i;
148
                        mem[addr].set_sign(sign);
149
                        mem[addr].set_value(v);
150
                        addr++;
151
                        sign = false;
152
                        op = d = i = 0;
153
                        word_valid = false;
154
                    }
155
                }
156
                number = "";
157
            }
158
        } else if ('-' == ch) {
159
            sign = true;
160
        }
161
    }
162
}
163
 
164
memmap::memmap(u_int32_t s, u_int32_t o)
165
    : size(s)
166
    , origin(o)
167
    , freectr(s)
168
{
169
    allocmap.resize(size, false);
170
}
171
 
172
void memmap::reserve(u_int32_t addr)
173
{
174
    if ((addr >= origin) && (addr < (origin + size))) {
175
        if (!allocmap[addr-origin]) {
176
            freectr--;
177
            allocmap[addr-origin] = true;
178
        }
179
    }
180
}
181
 
182
void memmap::reserve(u_int32_t fwa, u_int32_t sz)
183
{
184
    for (int i = 0; i < sz; i++)
185
        reserve(fwa+i);
186
}
187
 
188
void memmap::unreserve(u_int32_t addr)
189
{
190
    if ((addr >= origin) && (addr < (origin + size))) {
191
        if (allocmap[addr-origin]) {
192
            freectr--;
193
            allocmap[addr-origin] = false;
194
        }
195
    }
196
}
197
 
198
void memmap::unreserve(u_int32_t fwa, u_int32_t sz)
199
{
200
    for (int i= 0; i < sz; i++)
201
        unreserve(fwa+i);
202
}
203
 
204
void memmap::reset()
205
{
206
    for (int i = 0; i < size; i++)
207
        allocmap[i] = false;
208
    freectr = size;
209
}
210
 
211
int32_t memmap::optimum(u_int32_t rot)
212
{
213
    // 50 words per band
214
    // 40 bands per drum
215
    if (isfull())
216
        return -1;
217
    u_int32_t addr = rot;
218
    for (signed ctr = 0; ctr < size; ctr++) {
219
        if (!allocmap[addr]) {
220
            allocmap[addr] = true;
221
            freectr--;
222
            break;
223
        }
224
        addr += 50;
225
        if (addr >= size)
226
            addr = (addr % 50) + 1;
227
    }
228
    return addr;
229
}
230
 
231
static opcode optab[] = {
232
    // the flags field is encoded 8 for on, 9 for off
233
    // the digits in the flag field are, left to right,
234
    // A, B, and C.
235
    // A is on for index reg ops and for the SRD op
236
    // B is on for shift ops
237
    // C is on for index reg ops, shift ops, branch ops, HLT, NOP, etc.
238
 
239
    // SOAP2 decodes the flags with a nest of conditional branches.
240
    //
241
    //             |------------------------------- Decimal opcode
242
    //             |  |---------------------------- Idx reg ops and SRD
243
    //             |  ||--------------------------- Shift ops
244
    //             |  |||-------------------------- Idx reg, shift, branch, etc.
245
    //             |  |||  |----------------------- D even
246
    //             |  |||  |  |-------------------- D odd
247
    //             |  |||  |  |   |---------------- I even
248
    //             |  |||  |  |   |   |------------ I odd
249
    //             v  vvv  v  v   v   v
250
    opcode("ALO", 15, 999, 3, 3,  5,  4, real_op),
251
    opcode("AML", 17, 999, 3, 3,  5,  4, real_op),
252
    opcode("AUP", 10, 999, 3, 3,  5,  4, real_op),
253
    opcode("AXA", 50, 898, 0, 0,  0,  0, real_op),
254
    opcode("AXB", 52, 898, 0, 0,  0,  0, real_op),
255
    opcode("AXC", 58, 898, 0, 0,  0,  0, real_op),
256
    opcode("BDO", 90, 998, 4, 4,  5,  5, real_op),
257
    opcode("BD1", 91, 998, 3, 3,  5,  5, real_op),
258
    opcode("BD2", 92, 998, 3, 3,  5,  5, real_op),
259
    opcode("BD3", 93, 998, 3, 3,  5,  5, real_op),
260
    opcode("BD4", 94, 998, 3, 3,  5,  5, real_op),
261
    opcode("BD5", 95, 998, 3, 3,  5,  5, real_op),
262
    opcode("BD6", 96, 998, 3, 3,  5,  5, real_op),
263
    opcode("BD7", 97, 998, 3, 3,  5,  5, real_op),
264
    opcode("BD8", 98, 998, 3, 3,  5,  5, real_op),
265
    opcode("BD9", 99, 998, 4, 4,  5,  5, real_op),
266
    opcode("BIN", 26, 998, 0, 0,  5,  5, real_op),
267
    opcode("BMA", 41, 998, 3, 3,  4,  4, real_op),
268
    opcode("BMB", 43, 998, 3, 3,  4,  4, real_op),
269
    opcode("BMC", 49, 998, 3, 3,  4,  4, real_op),
270
    opcode("BMI", 46, 998, 3, 3,  4,  4, real_op),
271
    opcode("BOV", 47, 998, 3, 3,  5,  5, real_op),
272
    opcode("BST", 57, 998, 0, 0,  5,  5, real_op),
273
    opcode("DIV", 14, 999, 3, 3, 10, 11, real_op),  // modified from 11,10
274
    opcode("DVR", 64, 999, 3, 3, 11, 10, real_op),
275
    opcode("FAD", 32, 999, 3, 3, 27, 26, real_op),
276
    opcode("FAM", 37, 999, 3, 3, 27, 26, real_op),
277
    opcode("FDV", 34, 999, 3, 3,  0,  0, real_op),
278
    opcode("FMP", 39, 999, 3, 3,  0,  0, real_op),
279
    opcode("FSB", 33, 999, 3, 3, 27, 26, real_op),
280
    opcode("FSM", 38, 999, 3, 3, 27, 26, real_op),
281
    opcode("HLT",  1, 998, 0, 0,  4,  4, real_op),
282
    opcode("LDD", 69, 999, 3, 3,  3,  3, real_op),
283
    opcode("LDI",  9, 999, 3, 3,  2,  2, real_op),
284
    opcode("LIB",  8, 999, 3, 3, 12, 12, real_op),
285
    opcode("MPY", 19, 999, 3, 3, 20, 21, real_op),  // modified from 21,20
286
    opcode("NEF", 54, 998, 4, 4,  5,  5, real_op),
287
    opcode("NOP",  0, 998, 0, 0,  4,  4, real_op),
288
    opcode("NTS", 25, 998, 4, 4,  5,  5, real_op),
289
    opcode("NZA", 40, 998, 3, 3,  4,  4, real_op),
290
    opcode("NZB", 42, 998, 3, 3,  4,  4, real_op),
291
    opcode("NZC", 48, 998, 3, 3,  4,  4, real_op),
292
    opcode("NZE", 45, 998, 4, 3,  5,  4, real_op),
293
    opcode("NZU", 44, 998, 3, 4,  4,  5, real_op),
294
    opcode("RAA", 80, 898, 0, 0,  0,  0, real_op),
295
    opcode("RAB", 82, 898, 0, 0,  0,  0, real_op),
296
    opcode("RAC", 88, 898, 0, 0,  0,  0, real_op),
297
    opcode("RAL", 65, 999, 3, 3,  5,  4, real_op),
298
    opcode("RAM", 67, 999, 3, 3,  5,  4, real_op),
299
    opcode("RAU", 60, 999, 3, 3,  5,  4, real_op),
300
    opcode("RC1", 72, 999, 0, 0,  0,  0, real_op),
301
    opcode("RC2", 75, 999, 0, 0,  0,  0, real_op),
302
    opcode("RC3", 78, 999, 0, 0,  0,  0, real_op),
303
    opcode("RD1", 70, 999, 0, 0,  0,  0, real_op),
304
    opcode("RD2", 73, 999, 0, 0,  0,  0, real_op),
305
    opcode("RD3", 76, 999, 0, 0,  0,  0, real_op),
306
    opcode("RDS", 86, 998, 0, 0,  6,  6, real_op),
307
    opcode("RPY", 79, 999, 0, 0,  5,  5, real_op),
308
    opcode("RSA", 81, 898, 0, 0,  0,  0, real_op),
309
    opcode("RSB", 83, 898, 0, 0,  0,  0, real_op),
310
    opcode("RSC", 89, 898, 0, 0,  0,  0, real_op),
311
    opcode("RSL", 66, 999, 3, 3,  5,  4, real_op),
312
    opcode("RSM", 68, 999, 3, 3,  5,  4, real_op),
313
    opcode("RSU", 61, 999, 3, 3,  5,  4, real_op),
314
    opcode("RTA",  5, 998, 0, 0,  5,  5, real_op),
315
    opcode("RTC",  3, 998, 0, 0,  5,  5, real_op),
316
    opcode("RTN",  4, 998, 0, 0,  5,  5, real_op),
317
    opcode("RWD", 55, 998, 0, 0,  5,  5, real_op),
318
    opcode("SCT", 36, 988, 0, 0,  0,  0, real_op),
319
    opcode("SDA", 22, 999, 3, 4,  3,  3, real_op),
320
    opcode("SDS", 85, 998, 0, 0,  6,  6, real_op),
321
    opcode("SET", 27, 998, 0, 0,  5,  5, real_op),
322
    opcode("SIA", 23, 999, 3, 4,  3,  3, real_op),
323
    opcode("SIB", 28, 999, 3, 3, 12, 12, real_op),
324
    opcode("SLO", 16, 999, 3, 3,  5,  4, real_op),
325
    opcode("SLT", 35, 988, 0, 0,  0,  0, real_op),
326
    opcode("SML", 18, 999, 3, 3,  5,  4, real_op),
327
    opcode("SRD", 31, 888, 0, 0,  0,  0, real_op),
328
    opcode("SRT", 30, 988, 0, 0,  0,  0, real_op),
329
    opcode("STD", 24, 999, 3, 3,  3,  3, real_op),
330
    opcode("STI", 29, 999, 3, 3,  2,  2, real_op),
331
    opcode("STL", 20, 999, 5, 4,  3,  3, real_op),
332
    opcode("STU", 21, 999, 4, 5,  3,  3, real_op),
333
    opcode("SUP", 11, 999, 3, 3,  5,  4, real_op),
334
    opcode("SXA", 51, 898, 0, 0,  0,  0, real_op),
335
    opcode("SXB", 53, 898, 0, 0,  0,  0, real_op),
336
    opcode("SXC", 59, 898, 0, 0,  0,  0, real_op),
337
    opcode("TLU", 84, 999, 3, 3,  5,  6, real_op),
338
    opcode("UFA",  2, 999, 3, 3, 23, 22, real_op),
339
    opcode("WDS", 87, 998, 0, 0,  6,  6, real_op),
340
    opcode("WR1", 71, 999, 0, 0,  0,  0, real_op),
341
    opcode("WR2", 74, 999, 0, 0,  0,  0, real_op),
342
    opcode("WR3", 77, 999, 0, 0,  0,  0, real_op),
343
    opcode("WTA",  7, 998, 0, 0,  5,  5, real_op),
344
    opcode("WTM", 56, 998, 0, 0,  5,  5, real_op),
345
    opcode("WTN",  6, 998, 0, 0,  5,  5, real_op),
346
#if 0
347
    opcode("",12,Unused op,,,,,,,,
348
    opcode("",13,Unused op,,,,,,,,
349
    opcode("",62,Unused op,,,,,,,,
350
    opcode("",63,Unused op,,,,,,,,
351
#endif
352
    // symbolic op aliases
353
    opcode("RCD", "RD1"),
354
    opcode("PCH", "WR1"),
355
    opcode("BD0", "BDO"),
356
 
357
    // pseudo ops
358
    opcode("ALF", pseudo_alf,   0, 0, 0,  0,  0, pseudo_op),
359
    opcode("BLA", pseudo_bla,   0, 0, 0,  0,  0, pseudo_op),
360
    opcode("BLR", pseudo_blr,   0, 0, 0,  0,  0, pseudo_op),
361
    opcode("BOP", pseudo_bop,   0, 0, 0,  0,  0, pseudo_op),
362
    opcode("EQU", pseudo_equ,   0, 0, 0,  0,  0, pseudo_op),
363
    opcode("HED", pseudo_hed,   0, 0, 0,  0,  0, pseudo_op),
364
    opcode("PAT", pseudo_pat,   0, 0, 0,  0,  0, pseudo_op),
365
    opcode("RBR", pseudo_rbr,   0, 0, 0,  0,  0, pseudo_op),
366
    opcode("REG", pseudo_reg,   0, 0, 0,  0,  0, pseudo_op),
367
    opcode("REL", pseudo_rel,   0, 0, 0,  0,  0, pseudo_op),
368
    opcode("REQ", pseudo_req,   0, 0, 0,  0,  0, pseudo_op),
369
    opcode("SYN", pseudo_syn,   0, 0, 0,  0,  0, pseudo_op),
370
 
371
    opcode("FIN",  0,   0, 0, 0,  0,  0, final_op),
372
};
373
 
374
static opcode dummy_op("DUM", 0, 999, 5, 5, 5, 5, real_op);
375
 
376
void soap2::init_opcodetab()
377
{
378
    // initialize opcode lookup by-symbol and by-opcode tables
379
    opbycodetab.resize(100, &dummy_op);
380
    for (int i=0; optab[i].type != final_op; i++) {
381
        opcodetab[optab[i].op] = &optab[i];
382
        if (optab[i].type == real_op)
383
            opbycodetab[optab[i].code] = &optab[i];
384
    }
385
 
386
}
387
 
388
soap2::soap2(int c, int f, istream &cds_in, ostream &cds_out, ostream &listing, istream &ck_deck)
389
    : gsmap       (2000, 0)
390
    , input_deck  (cds_in)
391
    , output_deck (cds_out)
392
    , listing     (listing)
393
    , check_deck  (ck_deck)
394
    , ibm_obj     (2000)
395
    , codec       (c)
396
    , flags       (f)
397
{
398
    init_opcodetab();
399
    if (flags & asmflag_k)
400
        ibm_obj.load_7wd_deck(check_deck);
401
    assemble();
402
}
403
 
404
void soap2::error_message(const string &msg)
405
{
406
    errors << cardnumber << ": " << msg << endl;
407
}
408
 
409
void soap2::assemble()
410
{
411
    char inbuf[102];
412
    hed_char = ' ';
413
    opt_addr = -1;
414
    opt_gs   = -1;
415
    opt_ias  = -1;
416
    opt_800x = -1;
417
    cardnumber = 0;
418
    while (!input_deck.eof()) {
419
        ++cardnumber;
420
        input_deck.getline(&inbuf[0], 100);
421
        src = inbuf;
422
        src.resize(80, ' ');
423
        assemble_statement();
424
    }
425
    if (!errors.str().empty()) {
426
        cout << "Errors:" << endl;
427
        cout << errors.str();
428
        listing << endl << "Errors:" << endl;
429
        listing << errors.str();
430
    }
431
    print_symtab(listing);
432
    print_availtab(listing);
433
    print_regiontab(listing);
434
}
435
 
436
void soap2::assemble_statement()
437
{
438
    // resets for new statement
439
    asm_loc = 0;
440
    asm_op = 0;
441
    asm_d = 0;
442
    asm_i = 0;
443
    op = NULL;
444
    blank_loc = false;
445
    blank_op = false;
446
    blank_d = false;
447
    blank_i = false;
448
    punch_800x = false;
449
    bypass = false;
450
 
451
    // break statement into assembler fields
452
    src_type = src.substr(40,  1);
453
    src_sign = src.substr(41,  1);
454
    src_loc  = src.substr(42,  5);
455
    src_op   = src.substr(47,  3);
456
    src_d    = src.substr(50,  5);
457
    src_dtag = src.substr(55,  1);
458
    src_i    = src.substr(56,  5);
459
    src_itag = src.substr(61,  1);
460
    src_comm = src.substr(62, 10);
461
    src_fcom = src.substr(42, 30);
462
 
463
    // determine type and invoke processor
464
    switch (src_type[0]) {
465
        case ' ':
466
            assemble_command();
467
            punch_command(output_deck);
468
            print_command(listing);
469
            break;
470
        case '1':
471
            assemble_comment();
472
            if (flags & asmflag_c)
473
                punch_comment(output_deck);
474
            print_comment(listing);
475
            break;
476
        case '2':
477
            error_message("Relocatable statements no supported.");
478
            //assemble_relocate();
479
            break;
480
        default:
481
            error_message("Invalid statement type code");
482
            break;
483
    }
484
}
485
 
486
void soap2::assemble_command()
487
{
488
    process_op();
489
    if (op) {
490
        switch (op->type) {
491
            case real_op:
492
                assemble_realop();
493
                break;
494
            case pseudo_op:
495
                assemble_pseudo();
496
                break;
497
            default:
498
                error_message("Internal error, invalid op type");
499
                break;
500
        }
501
    } else {
502
        error_message("Invalid opcode");
503
    }
504
}
505
 
506
void soap2::punch_command(ostream &os)
507
{
508
    if (op) {
509
        if ((op->type == real_op) || (op->code == pseudo_alf)) {
510
            if (punch_800x && (flags & asmflag_e)) {
511
                os << zone_y('6') << "91954800" << zone_y('0')
512
                   << "      "
513
                   << setfill('0') << setw(4) << dec << (cardnumber % 10000)
514
                   << "24" << setfill('0') << setw(4) << dec << asm_loc
515
                   << "800" << zone_y('0')
516
                   << setfill('0') << setw(2) << dec << asm_op
517
                   << setfill('0') << setw(4) << dec << asm_d
518
                   << setfill('0') << setw(3) << dec << (asm_i / 10)
519
                   << ((src_sign == " ")? zone_y(asm_i % 10 + '0')
520
                                        : zone_x(asm_i % 10 + '0'))
521
                   << src_type
522
                   << ((src_sign == " ")? ' ' : '-')
523
                   << src_fcom
524
                   << " " << '-' << "     "
525
                   << endl;
526
            } else {
527
                os << zone_y('6') << "91954195" << zone_y('3')
528
                   << "      "
529
                   << setfill('0') << setw(4) << dec << (cardnumber % 10000)
530
                   << "24" << setfill('0') << setw(4) << dec << asm_loc
531
                   << "800" << zone_y('0')
532
                   << setfill('0') << setw(2) << dec << asm_op
533
                   << setfill('0') << setw(4) << dec << asm_d
534
                   << setfill('0') << setw(3) << dec << (asm_i / 10)
535
                   << ((src_sign == " ")? zone_y(asm_i % 10 + '0')
536
                                        : zone_x(asm_i % 10 + '0'))
537
                   << src_type
538
                   << ((src_sign == " ")? ' ' : '-')
539
                   << src_fcom
540
                   << "       "
541
                   << endl;
542
            }
543
        } else if ((op->type == pseudo_op) && (flags & asmflag_p)) {
544
                os << zone_y('0') << "00000800" << zone_y('0')
545
                   << "      "
546
                   << setfill('0') << setw(4) << dec << (cardnumber % 10000)
547
                   << "                    "
548
                   << src_type
549
                   << ((src_sign == " ")? ' ' : '-')
550
                   << src_fcom
551
                   << "9      "
552
                   << endl;
553
        }
554
    }
555
}
556
 
557
void soap2::print_command(ostream &os)
558
{
559
    if (op) {
560
        if ((op->type == real_op) || (op->code == pseudo_alf)) {
561
            os << dec << setfill(' ') << setw(4) << cardnumber << ": "
562
               << src_loc
563
               << ' ' << src_op
564
               << ' ' << src_d << src_dtag
565
               << ' ' << src_i << src_itag
566
               << ' ' << src_comm << "  "
567
               << dec << setfill(' ') << setw(4) << asm_loc << ": "
568
               << setfill('0') << setw(2) << asm_op
569
               << ' ' << setw(4) << asm_d
570
               << ' ' << setw(4) << asm_i;
571
            check_obj(os);
572
            os << endl;
573
        } else if (op->type == pseudo_op) {
574
            os << setfill(' ') << setw(4) << dec << cardnumber
575
               << ": "
576
               << src_loc
577
               << ' ' << src_op
578
               << ' ' << src_d << src_dtag
579
               << ' ' << src_i << src_itag
580
               << ' ' << src_comm
581
               << endl;
582
        }
583
    }
584
}
585
 
586
void soap2::assemble_comment()
587
{
588
}
589
 
590
void soap2::punch_comment(ostream &os)
591
{
592
    os << zone_y('0') << "00000800" << zone_y('0')
593
       << "      "
594
       << setfill('0') << setw(4) << dec << (cardnumber % 10000)
595
       << "                    "
596
       << src_type
597
       << ((src_sign == " ")? ' ' : '-')
598
       << src_fcom
599
       << "9" << "      "
600
       << endl;
601
}
602
 
603
void soap2::print_comment(ostream &os)
604
{
605
    os << setfill(' ') << setw(4) << dec << cardnumber
606
       << ":           "
607
       << src_fcom
608
       << endl;
609
}
610
 
611
void soap2::assemble_relocate()
612
{
613
}
614
 
615
void soap2::assemble_realop()
616
{
617
    process_loc();
618
    process_d();
619
    process_i();
620
}
621
 
622
void soap2::assemble_pseudo()
623
{
624
    asmfield d(src_d, ' ');
625
    asmfield i(src_i, ' ');
626
    switch (op->code) {
627
        case pseudo_alf:
628
            process_loc();
629
            asm_op = ascii_to_650(src_d[0]);
630
            asm_d =  ascii_to_650(src_d[1]) * 100 + ascii_to_650(src_d[2]);
631
            asm_i =  ascii_to_650(src_d[3]) * 100 + ascii_to_650(src_d[4]);
632
            if ((src_i) == "     ")
633
                src_i = "SOAP2";
634
            break;
635
 
636
        case pseudo_bla:
637
            if (d.type == field_numeric) {
638
                if (i.type == field_numeric) {
639
                    if (gsmap.isvalid(d.nval, i.nval - d.nval + 1))
640
                        gsmap.unreserve(d.nval, i.nval - d.nval + 1);
641
                    else
642
                        error_message("Invalid address range");
643
                } else {
644
                    error_message("Invalid I field");
645
                }
646
            } else {
647
                error_message("Invalid D field");
648
            }
649
            break;
650
 
651
        case pseudo_blr:
652
            if (d.type == field_numeric) {
653
                if (i.type == field_numeric) {
654
                    if (gsmap.isvalid(d.nval, i.nval - d.nval + 1))
655
                        gsmap.reserve(d.nval, i.nval - d.nval + 1);
656
                    else
657
                        error_message("Invalid address range");
658
                } else {
659
                    error_message("Invalid I field");
660
                }
661
            } else {
662
                error_message("Invalid D field");
663
            }
664
            break;
665
 
666
        case pseudo_bop:
667
            error_message("BOP not supported");
668
            break;
669
 
670
        case pseudo_syn:
671
        case pseudo_equ: {
672
            int32_t eaddr = -1;
673
            switch (i.type) {
674
                case field_numeric:
675
                    eaddr = i.nval;
676
                    break;
677
 
678
                case field_region: {
679
                    regiter ri = regiontab.find(i.region);
680
                    if (ri == regiontab.end()) {
681
                        error_message("Region not defined");
682
                        bypass = true;
683
                    } else {
684
                        eaddr = ri->second->start + i.nval;
685
                    }
686
                }
687
                    break;
688
 
689
                case field_symbolic: {
690
                    symiter si = symboltab.find(i.symbol);
691
                    if (si == symboltab.end()) {
692
                        error_message("Symbol not defined");
693
                        bypass = true;
694
                    } else {
695
                        eaddr = si->second->location;
696
                        si->second->add_ref(cardnumber);
697
                    }
698
                }
699
                    break;
700
 
701
                case field_blank:
702
                    error_message("I field may not be blank");
703
                    bypass = true;
704
                    break;
705
 
706
                case field_error:
707
                    error_message("Invalid I field");
708
                    bypass = true;
709
                    break;
710
 
711
                default:
712
                    error_message("Internal error: unknown field code");
713
                    bypass = true;
714
                    break;
715
            }
716
            if (!bypass) {
717
                if (d.type != field_symbolic) {
718
                    error_message("D field must be a symbol");
719
                    bypass = true;
720
                } else {
721
                    symboltab[d.symbol] = new symbol(d.symbol, eaddr, cardnumber);
722
                    if (op->code == pseudo_syn)
723
                        gsmap.reserve(eaddr);
724
                }
725
            }
726
        }
727
            break;
728
 
729
        case pseudo_hed:
730
            hed_char = src_d[0];
731
            break;
732
 
733
        case pseudo_pat:
734
            print_availtab(cout);
735
            //error_message("PAT not supported");
736
            break;
737
 
738
        case pseudo_rbr:
739
            error_message("RBR not supported");
740
            break;
741
 
742
        case pseudo_reg:
743
            switch (d.type) {
744
                case field_numeric:
745
                case field_region:
746
                    switch (i.type) {
747
                        case field_numeric:
748
                            if (d.type == field_region) {
749
                                regiter ri = regiontab.find(d.region);
750
                                if (ri == regiontab.end()) {
751
                                    regiontab[d.region] = new region(d.region, d.nval);
752
                                } else {
753
                                    ri->second->start = d.nval;
754
                                }
755
                            }
756
                            if (d.nval < i.nval)
757
                                gsmap.reserve(d.nval, i.nval - d.nval + 1);
758
                            break;
759
                        default:
760
                            error_message("Invalid I field");
761
                            break;
762
                    }
763
                    break;
764
                default:
765
                    error_message("Invalid D field");
766
                    break;
767
            }
768
            break;
769
 
770
        case pseudo_rel:
771
            error_message("REL not supported");
772
            break;
773
 
774
        case pseudo_req:
775
            error_message("REQ not supported");
776
            break;
777
 
778
        default:
779
            error_message("Internal error, invalid pseudo op");
780
            break;
781
    }
782
}
783
 
784
void soap2::check_obj(ostream &os)
785
{
786
    if (((op->type == real_op) && !punch_800x) || (op->code == pseudo_alf)) {
787
        int64_t v = asm_op * 100000000LL + asm_d * 10000 + asm_i;
788
        if ((v != ibm_obj[asm_loc].value()) || ((src_sign == " ") && ibm_obj[asm_loc].sign())) {
789
            int64_t ov = ibm_obj[asm_loc].value();
790
            os << " : " << setfill('0') << setw(2) << ov / 100000000LL
791
               << ' ' << setw(4) << ov / 10000 % 10000
792
               << ' ' << setw(4) << ov % 10000;
793
        }
794
    }
795
}
796
 
797
struct opt_deltas {
798
    int even;
799
    int odd;
800
 
801
    opt_deltas(int even, int odd) : even(even), odd(odd) {}
802
    opt_deltas() : even(0), odd(0) {}
803
};
804
 
805
static opt_deltas shift_deltas[] = {
806
    opt_deltas(23, 22),
807
    opt_deltas( 7,  6),
808
    opt_deltas( 7,  6),
809
    opt_deltas( 9,  8),
810
    opt_deltas(11, 10),
811
    opt_deltas(13, 12),
812
    opt_deltas(15, 14),
813
    opt_deltas(17, 16),
814
    opt_deltas(19, 18),
815
    opt_deltas(21, 20)
816
};
817
 
818
static opt_deltas srd_deltas[] = {
819
    opt_deltas(25, 24),
820
    opt_deltas( 7,  6),
821
    opt_deltas( 9,  8),
822
    opt_deltas(11, 10),
823
    opt_deltas(13, 12),
824
    opt_deltas(15, 14),
825
    opt_deltas(17, 16),
826
    opt_deltas(19, 18),
827
    opt_deltas(21, 20),
828
    opt_deltas(23, 22)
829
};
830
 
831
u_int32_t soap2::find_optimal_wt(opt_type ot)
832
{
833
    opt_deltas deltas;
834
 
835
    if (opt_addr < 0) {
836
        return 0;
837
    }
838
    if (opt_i == ot) {
839
        deltas = opt_deltas(op->i_even, op->i_odd);
840
        if (op->opt_B()) {
841
            int scount = asm_d % 10;
842
            deltas = (op->opt_A())? srd_deltas[scount] : shift_deltas[scount];
843
        } else if (op->opt_A()) {
844
            if (asm_d <= 1999)      deltas = opt_deltas( 6,  6);
845
            else if (asm_d <= 7999) deltas = opt_deltas( 6,  6);
846
            else if (asm_d == 8000) deltas = opt_deltas( 8,  8);
847
            else if (asm_d == 8001) deltas = opt_deltas( 6,  6);
848
            else if (asm_d == 8002) deltas = opt_deltas( 9,  8);
849
            else if (asm_d == 8003) deltas = opt_deltas( 8,  9);
850
            else if (asm_d <= 9059) deltas = opt_deltas( 8,  8);
851
            else                    deltas = opt_deltas( 9,  9);
852
 
853
        }
854
    } else {
855
        deltas = opt_deltas(op->d_even, op->d_odd);
856
    }
857
    int delta = (opt_addr & 1)? deltas.odd : deltas.even;
858
    return (opt_addr + delta) % 50;
859
}
860
 
861
u_int32_t soap2::find_optimal_800x(opt_type ot, u_int32_t opa)
862
{
863
    u_int32_t opta = find_optimal_wt(ot);
864
    if (8002 == opa) {
865
        if ((opta & 1)) opta++;
866
    } else if (8003 == opa) {
867
        if (!(opta & 1)) opta++;
868
    }
869
    return opta % 50;
870
}
871
 
872
void soap2::process_loc_addr()
873
{
874
    switch (get_addr_type(asm_loc)) {
875
        case addr_gs:
876
            opt_addr = asm_loc;
877
            break;
878
 
879
        case addr_800X:
880
            opt_addr = opt_800x;
881
            punch_800x = true;
882
            break;
883
 
884
        case addr_ias:
885
            opt_addr = opt_ias;
886
            break;
887
 
888
        case addr_invalid:
889
            error_message("Invalid location address");
890
            blank_loc = true;
891
            break;
892
 
893
        default:
894
            break;
895
    }
896
}
897
 
898
void soap2::process_loc()
899
{
900
    asmfield field(src_loc, hed_char);
901
    switch (field.type) {
902
        case field_blank:
903
            if (opt_addr < 0) {
904
                error_message("Cannot assign location, optimal address invalid");
905
                blank_loc = true;
906
            } else {
907
                asm_loc = opt_addr;
908
            }
909
            break;
910
 
911
        case field_symbolic: {
912
            symiter symi = symboltab.find(field.symbol);
913
            if (symi == symboltab.end()) {
914
                int32_t oaddr = gsmap.optimum(0);
915
                if (oaddr < 0) {
916
                    error_message("General storage packed");
917
                    blank_loc = true;
918
                } else {
919
                    symboltab[field.symbol] = new symbol(field.symbol, oaddr, cardnumber);
920
                    opt_addr = oaddr;
921
                    asm_loc = oaddr;
922
                }
923
            } else {
924
                asm_loc = symi->second->location;
925
                symi->second->add_ref(cardnumber);
926
                process_loc_addr();
927
            }
928
        }
929
            break;
930
        case field_numeric:
931
            asm_loc = field.nval;
932
            process_loc_addr();
933
            break;
934
 
935
        case field_region: {
936
            regiter regi = regiontab.find(field.region);
937
            if (regi == regiontab.end()) {
938
                error_message("Undefined region");
939
                blank_loc = true;
940
            } else {
941
                asm_loc = field.nval - 1 + regi->second->start;
942
                process_loc_addr();
943
            }
944
        }
945
            break;
946
 
947
        case field_error:
948
            error_message("Invalid location field");
949
            blank_loc = true;
950
            break;
951
 
952
        default:
953
            error_message("Internal error: processing location");
954
            blank_loc = true;
955
            break;
956
    }
957
}
958
 
959
void soap2::process_op()
960
{
961
    op = NULL;
962
    if (src_op[0] == ' ') {
963
        bool numeric = true;
964
        for (int i = 1; i < 3; i++)
965
            if (!isdigit(src_op[i]))
966
                numeric = false;
967
        if (numeric) {
968
            int opcode = stoi(src_op.substr(1, 2));
969
            op = opbycodetab[opcode];
970
            asm_op = opcode;
971
            return;
972
        } else {
973
            error_message("Malformed opcode");
974
            blank_op = true;
975
            return;
976
        }
977
    }
978
    opiter oi = opcodetab.find(src_op);
979
    if (oi != opcodetab.end()) {
980
        if (oi->second->type == alias_op) {
981
            oi = opcodetab.find(oi->second->alias);
982
            if (oi == opcodetab.end()) {
983
                error_message("Internal error: opcode alias not found");
984
                blank_op = true;
985
                return;
986
            }
987
        }
988
        op = oi->second;
989
        asm_op = op->code;
990
    } else {
991
        error_message("Invalid symbolic opcode");
992
        op = &dummy_op;
993
        blank_op = true;
994
    }
995
}
996
 
997
void soap2::process_d_addr()
998
{
999
    switch (get_addr_type(asm_d)) {
1000
        case addr_gs:
1001
            // todo: index
1002
            if (!op->opt_C())
1003
                opt_addr = asm_d;
1004
            break;
1005
 
1006
        case addr_800X:
1007
            opt_800x = find_optimal_800x(opt_d, asm_d);
1008
            opt_addr = opt_800x;
1009
            break;
1010
 
1011
        case addr_ias:
1012
            // todo: index
1013
            opt_ias = find_optimal_wt(opt_d);
1014
            if (!op->opt_C())
1015
                opt_addr = asm_d;
1016
            break;
1017
 
1018
        case addr_invalid:
1019
            if (!op->opt_C())
1020
                opt_addr = asm_d;
1021
            break;
1022
 
1023
        default:
1024
            error_message("Internal error: processing D field");
1025
            blank_d = true;
1026
            break;
1027
    }
1028
}
1029
 
1030
void soap2::process_d()
1031
{
1032
    asmfield field(src_d, hed_char);
1033
    switch (field.type) {
1034
        case field_blank: {
1035
            int32_t oaddr = gsmap.optimum(find_optimal_wt(opt_d));
1036
            if (oaddr < 0) {
1037
                error_message("General storage packed");
1038
                blank_d = true;
1039
            } else {
1040
                opt_b = oaddr;
1041
                asm_d = oaddr;
1042
                if (!op->opt_C())
1043
                    opt_addr = oaddr;
1044
            }
1045
        }
1046
            break;
1047
 
1048
        case field_numeric:
1049
            asm_d = field.nval;
1050
            process_d_addr();
1051
            break;
1052
 
1053
        case field_symbolic: {
1054
            symiter symi = symboltab.find(field.symbol);
1055
            if (symi == symboltab.end()) {
1056
                int32_t oaddr = gsmap.optimum(find_optimal_wt(opt_d));
1057
                if (oaddr < 0) {
1058
                    error_message("General storage packed");
1059
                    blank_d = true;
1060
                } else {
1061
                    symboltab[field.symbol] = new symbol(field.symbol, oaddr, cardnumber);
1062
                    asm_d = oaddr;
1063
                    if (!op->opt_C())
1064
                        opt_addr = oaddr;
1065
                }
1066
            } else {
1067
                asm_d = symi->second->location;
1068
                symi->second->add_ref(cardnumber);
1069
                process_d_addr();
1070
            }
1071
        }
1072
            break;
1073
 
1074
        case field_region: {
1075
            regiter regi = regiontab.find(field.region);
1076
            if (regi == regiontab.end()) {
1077
                error_message("Undefined region");
1078
                blank_d = true;
1079
            } else {
1080
                asm_d = field.nval - 1 + regi->second->start;
1081
                process_d_addr();
1082
            }
1083
        }
1084
            break;
1085
 
1086
        case field_error:
1087
            error_message("Invalid D field");
1088
            blank_loc = true;
1089
            break;
1090
 
1091
        default:
1092
            error_message("Internal error: processing D field");
1093
            blank_loc = true;
1094
            break;
1095
    }
1096
}
1097
 
1098
void soap2::process_i_addr()
1099
{
1100
    switch (get_addr_type(asm_i)) {
1101
        case addr_gs:
1102
            // todo: index
1103
            break;
1104
 
1105
        case addr_800X: {
1106
            opt_800x = find_optimal_800x(opt_i, asm_i);
1107
            break;
1108
        }
1109
        case addr_ias:
1110
            // todo: index
1111
            opt_ias = find_optimal_wt(opt_i);
1112
            break;
1113
 
1114
        case addr_invalid:
1115
            break;
1116
 
1117
        default:
1118
            error_message("Internal error: processing I field");
1119
            blank_i = true;
1120
            break;
1121
    }
1122
    opt_addr = opt_b;
1123
}
1124
 
1125
void soap2::process_i()
1126
{
1127
    asmfield field(src_i, hed_char);
1128
    asmfield field_d(src_d, hed_char);
1129
    switch (field.type) {
1130
        case field_blank:
1131
            if (field_blank == field_d.type) {
1132
                if (gsmap.isfull()) {
1133
                    blank_i = true;
1134
                } else {
1135
                    asm_i = opt_b;
1136
                    opt_addr = opt_b;
1137
                }
1138
            } else {
1139
                int32_t oaddr = gsmap.optimum(find_optimal_wt(opt_i));
1140
                if (oaddr < 0) {
1141
                    error_message("General storage packed");
1142
                    blank_i = true;
1143
                } else {
1144
                    opt_b = oaddr;
1145
                    asm_i = oaddr;
1146
                    opt_addr = oaddr;
1147
                }
1148
            }
1149
            break;
1150
 
1151
        case field_numeric:
1152
            asm_i = field.nval;
1153
            process_i_addr();
1154
            break;
1155
 
1156
        case field_symbolic: {
1157
            symiter symi = symboltab.find(field.symbol);
1158
            if (symi == symboltab.end()) {
1159
                int32_t oaddr = gsmap.optimum(find_optimal_wt(opt_i));
1160
                if (oaddr < 0) {
1161
                    error_message("General storage packed");
1162
                    blank_i = true;
1163
                } else {
1164
                    symboltab[field.symbol] = new symbol(field.symbol, oaddr, cardnumber);
1165
                    asm_i = oaddr;
1166
                    opt_addr = opt_b;
1167
                }
1168
            } else {
1169
                asm_i = symi->second->location;
1170
                symi->second->add_ref(cardnumber);
1171
                process_i_addr();
1172
            }
1173
        }
1174
            break;
1175
 
1176
        case field_region: {
1177
            regiter regi = regiontab.find(field.region);
1178
            if (regi == regiontab.end()) {
1179
                error_message("Undefined region");
1180
                blank_i = true;
1181
            } else {
1182
                asm_i = field.nval - 1 + regi->second->start;
1183
                process_i_addr();
1184
            }
1185
        }
1186
            break;
1187
 
1188
        case field_error:
1189
            error_message("Invalid I field");
1190
            blank_loc = true;
1191
            break;
1192
 
1193
        default:
1194
            error_message("Internal error: processing I field");
1195
            blank_loc = true;
1196
            break;
1197
    }
1198
}
1199
 
1200
void soap2::print_symtab(ostream &sout)
1201
{
1202
    sout << endl << "Symbol Table:" << endl;
1203
    symiter siter;
1204
    for (siter = symboltab.begin(); siter != symboltab.end(); siter++) {
1205
        sout << siter->first << ": " << setfill(' ') << setw(4) << dec << siter->second->location;
1206
        int rctr = 0;
1207
        for (int ref : siter->second->ref_line) {
1208
            if (0 == (++rctr % 20)) sout << endl << "      ";
1209
            sout << " " << setfill(' ') << setw(4) << dec << ref;
1210
        }
1211
        sout << endl;
1212
    }
1213
}
1214
 
1215
void memmap::print_availtab(ostream &sout)
1216
{
1217
    sout << endl << "Availability Table:" << endl;
1218
    for (int i = 0; i < size; i++) {
1219
        sout.width(4);
1220
        if (0 == i % 50) sout << endl << i << ":";
1221
        sout.width(1);
1222
        if (0 == i % 10)  sout << " ";
1223
        sout << ((allocmap[i])? '1' : '0');
1224
    }
1225
    sout << endl;
1226
    for (int i = 0; i < 50; i++) {
1227
        sout << setw(2) << i << ':';
1228
        int addr = i;
1229
        int ctr = 0;
1230
        while (addr < size) {
1231
            if (0 == allocmap[addr]) {
1232
                if (ctr == 20) {
1233
                    sout << endl << "   ";
1234
                    ctr = 0;
1235
                }
1236
                sout << ' ' << setw(4) << addr;
1237
                ctr++;
1238
            }
1239
            addr += 50;
1240
        }
1241
        sout << endl;
1242
    }
1243
}
1244
 
1245
void soap2::print_availtab(ostream &sout)
1246
{
1247
    gsmap.print_availtab(sout);
1248
}
1249
 
1250
void soap2::print_regiontab(ostream &sout)
1251
{
1252
    sout << endl << "Region Table:" << endl;
1253
    for (regiter riter = regiontab.begin(); riter != regiontab.end(); riter++) {
1254
        sout << riter->first << ": " << riter->second->start << endl;
1255
    }
1256
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.