blob: 82e07a456228d8f0dda84dd54a16209db950c8e9 [file] [log] [blame] [raw]
Leo Broukhisb4eeaa72014-12-30 00:41:31 -08001/*
2 * besm6_sys.c: BESM-6 simulator interface
3 *
4 * Copyright (c) 2009, Serge Vakulenko
5 * Copyright (c) 2009, Leonid Broukhis
6 *
Leo Broukhisaa168572015-01-04 23:14:51 -08007 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * SERGE VAKULENKO OR LEONID BROUKHIS BE LIABLE FOR ANY CLAIM, DAMAGES
21 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
Serge Vakulenko5ed19092015-01-21 12:29:29 -080022 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
Leo Broukhisaa168572015-01-04 23:14:51 -080023 * OR OTHER DEALINGS IN THE SOFTWARE.
24
25 * Except as contained in this notice, the name of Leonid Broukhis or
26 * Serge Vakulenko shall not be used in advertising or otherwise to promote
27 * the sale, use or other dealings in this Software without prior written
28 * authorization from Leonid Broukhis and Serge Vakulenko.
Leo Broukhisb4eeaa72014-12-30 00:41:31 -080029 *
30 * This file implements three essential functions:
31 *
32 * sim_load() - loading and dumping memory and CPU state
Leo Broukhiscc332572014-12-30 11:42:52 -080033 * in a way, specific for BESM-6 architecture
Leo Broukhisb4eeaa72014-12-30 00:41:31 -080034 * fprint_sym() - print a machune instruction using
Leo Broukhiscc332572014-12-30 11:42:52 -080035 * opcode mnemonic or in a digital format
36 * parse_sym() - scan a string and build an instruction
37 * word from it
Leo Broukhisb4eeaa72014-12-30 00:41:31 -080038 */
39#include "besm6_defs.h"
40#include <math.h>
Leo Broukhisb4eeaa72014-12-30 00:41:31 -080041
42const char *opname_short_bemsh [64] = {
Leo Broukhiscc332572014-12-30 11:42:52 -080043 "зп", "зпм", "рег", "счм", "сл", "вч", "вчоб","вчаб",
44 "сч", "и", "нтж", "слц", "знак","или", "дел", "умн",
45 "сбр", "рзб", "чед", "нед", "слп", "вчп", "сд", "рж",
46 "счрж","счмр","э32", "увв", "слпа","вчпа","сда", "ржа",
47 "уи", "уим", "счи", "счим","уии", "сли", "э46", "э47",
48 "э50", "э51", "э52", "э53", "э54", "э55", "э56", "э57",
49 "э60", "э61", "э62", "э63", "э64", "э65", "э66", "э67",
50 "э70", "э71", "э72", "э73", "э74", "э75", "э76", "э77",
Leo Broukhisb4eeaa72014-12-30 00:41:31 -080051};
52
53static const char *opname_long_bemsh [16] = {
Leo Broukhiscc332572014-12-30 11:42:52 -080054 "э20", "э21", "мода","мод", "уиа", "слиа","по", "пе",
55 "пб", "пв", "выпр","стоп","пио", "пино","э36", "цикл",
Leo Broukhisb4eeaa72014-12-30 00:41:31 -080056};
57
58const char *opname_short_madlen [64] = {
Leo Broukhiscc332572014-12-30 11:42:52 -080059 "atx", "stx", "mod", "xts", "a+x", "a-x", "x-a", "amx",
60 "xta", "aax", "aex", "arx", "avx", "aox", "a/x", "a*x",
61 "apx", "aux", "acx", "anx", "e+x", "e-x", "asx", "xtr",
62 "rte", "yta", "*32", "ext", "e+n", "e-n", "asn", "ntr",
63 "ati", "sti", "ita", "its", "mtj", "j+m", "*46", "*47",
64 "*50", "*51", "*52", "*53", "*54", "*55", "*56", "*57",
65 "*60", "*61", "*62", "*63", "*64", "*65", "*66", "*67",
66 "*70", "*71", "*72", "*73", "*74", "*75", "*76", "*77",
Leo Broukhisb4eeaa72014-12-30 00:41:31 -080067};
68
69static const char *opname_long_madlen [16] = {
Leo Broukhiscc332572014-12-30 11:42:52 -080070 "*20", "*21", "utc", "wtc", "vtm", "utm", "uza", "u1a",
71 "uj", "vjm", "ij", "stop", "vzm", "v1m", "*36", "vlm",
Leo Broukhisb4eeaa72014-12-30 00:41:31 -080072};
73
74/*
75 * Выдача мнемоники по коду инструкции.
76 * Код должен быть в диапазоне 000..077 или 0200..0370.
77 */
78const char *besm6_opname (int opcode)
79{
Leo Broukhiscc332572014-12-30 11:42:52 -080080 if (sim_switches & SWMASK ('L')) {
81 /* Latin mnemonics. */
82 if (opcode & 0200)
83 return opname_long_madlen [(opcode >> 3) & 017];
84 return opname_short_madlen [opcode];
85 }
86 if (opcode & 0200)
87 return opname_long_bemsh [(opcode >> 3) & 017];
88 return opname_short_bemsh [opcode];
89}
Leo Broukhisb4eeaa72014-12-30 00:41:31 -080090
91/*
92 * Выдача кода инструкции по мнемонике (UTF-8).
93 */
94int besm6_opcode (char *instr)
95{
Leo Broukhiscc332572014-12-30 11:42:52 -080096 int i;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -080097
Leo Broukhiscc332572014-12-30 11:42:52 -080098 for (i=0; i<64; ++i)
99 if (strcmp (opname_short_bemsh[i], instr) == 0 ||
100 strcmp (opname_short_madlen[i], instr) == 0)
101 return i;
102 for (i=0; i<16; ++i)
103 if (strcmp (opname_long_bemsh[i], instr) == 0 ||
104 strcmp (opname_long_madlen[i], instr) == 0)
105 return (i << 3) | 0200;
106 return -1;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800107}
108
109/*
110 * Выдача на консоль и в файл протокола.
111 * Если первый символ формата - подчерк, на консоль не печатаем.
112 * Добавляет перевод строки.
113 */
114void besm6_log (const char *fmt, ...)
115{
Leo Broukhiscc332572014-12-30 11:42:52 -0800116 va_list args;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800117
Leo Broukhiscc332572014-12-30 11:42:52 -0800118 if (*fmt == '_')
119 ++fmt;
120 else {
121 va_start (args, fmt);
122 vprintf (fmt, args);
123 printf ("\r\n");
124 va_end (args);
125 }
126 if (sim_log) {
127 va_start (args, fmt);
128 vfprintf (sim_log, fmt, args);
129 if (sim_log == stdout)
130 fprintf (sim_log, "\r");
131 fprintf (sim_log, "\n");
132 fflush (sim_log);
133 va_end (args);
134 }
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800135}
136
137/*
138 * Не добавляет перевод строки.
139 */
140void besm6_log_cont (const char *fmt, ...)
141{
Leo Broukhiscc332572014-12-30 11:42:52 -0800142 va_list args;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800143
Leo Broukhiscc332572014-12-30 11:42:52 -0800144 if (*fmt == '_')
145 ++fmt;
146 else {
147 va_start (args, fmt);
148 vprintf (fmt, args);
149 va_end (args);
150 }
151 if (sim_log) {
152 va_start (args, fmt);
153 vfprintf (sim_log, fmt, args);
154 fflush (sim_log);
155 va_end (args);
156 }
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800157}
158
159/*
160 * Выдача на консоль и в файл отладки: если включён режим "cpu debug".
161 * Добавляет перевод строки.
162 */
163void besm6_debug (const char *fmt, ...)
164{
Leo Broukhiscc332572014-12-30 11:42:52 -0800165 va_list args;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800166
Leo Broukhiscc332572014-12-30 11:42:52 -0800167 va_start (args, fmt);
168 vprintf (fmt, args);
169 printf ("\r\n");
170 va_end (args);
171 if (sim_deb && sim_deb != stdout) {
172 va_start (args, fmt);
173 vfprintf (sim_deb, fmt, args);
174 fprintf (sim_deb, "\n");
175 fflush (sim_deb);
176 va_end (args);
177 }
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800178}
179
180/*
181 * Преобразование вещественного числа в формат БЭСМ-6.
182 *
183 * Представление чисел в IEEE 754 (double):
Leo Broukhiscc332572014-12-30 11:42:52 -0800184 * 64 63———53 52————–1
185 * знак порядок мантисса
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800186 * Старший (53-й) бит мантиссы не хранится и всегда равен 1.
187 *
188 * Представление чисел в БЭСМ-6:
189 * 48——–42 41 40————————————————–1
190 * порядок знак мантисса в доп. коде
191 */
192t_value ieee_to_besm6 (double d)
193{
Leo Broukhiscc332572014-12-30 11:42:52 -0800194 t_value word;
195 int exponent;
196 int sign;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800197
Leo Broukhiscc332572014-12-30 11:42:52 -0800198 sign = d < 0;
199 if (sign)
200 d = -d;
201 d = frexp (d, &exponent);
202 /* 0.5 <= d < 1.0 */
203 d = ldexp (d, 40);
Mark Pizzolato76dd31a2014-12-30 17:52:13 -0800204 word = (t_value)d;
Leo Broukhiscc332572014-12-30 11:42:52 -0800205 if (d - word >= 0.5)
206 word += 1; /* Округление. */
207 if (exponent < -64)
208 return 0LL; /* Близкое к нулю число */
209 if (exponent > 63) {
210 return sign ?
211 0xFEFFFFFFFFFFLL : /* Максимальное число */
212 0xFF0000000000LL; /* Минимальное число */
213 }
214 if (sign)
215 word = 0x20000000000LL-word; /* Знак. */
216 word |= ((t_value) (exponent + 64)) << 41;
217 return word;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800218}
219
220double besm6_to_ieee (t_value word)
221{
Leo Broukhiscc332572014-12-30 11:42:52 -0800222 double mantissa;
Mark Pizzolato76dd31a2014-12-30 17:52:13 -0800223 int exponent;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800224
Leo Broukhiscc332572014-12-30 11:42:52 -0800225 /* Убираем свертку */
226 word &= BITS48;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800227
Leo Broukhiscc332572014-12-30 11:42:52 -0800228 /* Сдвигаем так, чтобы знак мантиссы пришелся на знак целого;
229 * таким образом, mantissa равно исходной мантиссе, умноженной на 2**63.
230 */
Mark Pizzolato76dd31a2014-12-30 17:52:13 -0800231 mantissa = (double)(((t_int64) word) << (64 - 48 + 7));
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800232
Mark Pizzolato76dd31a2014-12-30 17:52:13 -0800233 exponent = word >> 41;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800234
Leo Broukhiscc332572014-12-30 11:42:52 -0800235 /* Порядок смещен вверх на 64, и мантиссу нужно скорректировать */
236 return ldexp (mantissa, exponent - 64 - 63);
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800237}
238
239/*
240 * Пропуск пробелов.
241 */
Mark Pizzolato5531ccb2016-05-15 15:25:33 -0700242CONST char *skip_spaces (CONST char *p)
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800243{
Leo Broukhiscc332572014-12-30 11:42:52 -0800244 for (;;) {
245 if (*p == (char) 0xEF && p[1] == (char) 0xBB && p[2] == (char) 0xBF) {
246 /* Skip zero width no-break space. */
247 p += 3;
248 continue;
249 }
250 if (*p == ' ' || *p == '\t' || *p == '\r') {
251 ++p;
252 continue;
253 }
254 return p;
255 }
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800256}
257
258/*
259 * Fetch Unicode symbol from UTF-8 string.
260 * Advance string pointer.
261 */
Mark Pizzolato5531ccb2016-05-15 15:25:33 -0700262int utf8_to_unicode (CONST char **p)
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800263{
Leo Broukhiscc332572014-12-30 11:42:52 -0800264 int c1, c2, c3;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800265
Leo Broukhiscc332572014-12-30 11:42:52 -0800266 c1 = (unsigned char) *(*p)++;
267 if (! (c1 & 0x80))
268 return c1;
269 c2 = (unsigned char) *(*p)++;
270 if (! (c1 & 0x20))
271 return (c1 & 0x1f) << 6 | (c2 & 0x3f);
272 c3 = (unsigned char) *(*p)++;
273 return (c1 & 0x0f) << 12 | (c2 & 0x3f) << 6 | (c3 & 0x3f);
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800274}
275
Mark Pizzolato5531ccb2016-05-15 15:25:33 -0700276char *besm6_parse_octal (const char *cptr, int *offset)
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800277{
Leo Broukhiscc332572014-12-30 11:42:52 -0800278 char *eptr;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800279
Leo Broukhiscc332572014-12-30 11:42:52 -0800280 *offset = strtol (cptr, &eptr, 8);
281 if (eptr == cptr)
282 return 0;
283 return eptr;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800284}
285
Mark Pizzolato5531ccb2016-05-15 15:25:33 -0700286static CONST char *get_alnum (CONST char *iptr, char *optr)
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800287{
Leo Broukhiscc332572014-12-30 11:42:52 -0800288 while ((*iptr >= 'a' && *iptr<='z') ||
289 (*iptr >= 'A' && *iptr<='Z') ||
290 (*iptr >= '0' && *iptr<='9') || (*iptr & 0x80)) {
291 *optr++ = *iptr++;
292 }
293 *optr = 0;
294 return iptr;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800295}
296
297/*
298 * Parse single instruction (half word).
299 * Allow mnemonics or octal code.
300 */
Mark Pizzolato5531ccb2016-05-15 15:25:33 -0700301CONST char *parse_instruction (CONST char *cptr, uint32 *val)
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800302{
Leo Broukhiscc332572014-12-30 11:42:52 -0800303 int opcode, reg, addr, negate;
304 char gbuf[CBUFSIZE];
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800305
Leo Broukhiscc332572014-12-30 11:42:52 -0800306 cptr = skip_spaces (cptr); /* absorb spaces */
307 if (*cptr >= '0' && *cptr <= '7') {
308 /* Восьмеричное представление. */
309 cptr = besm6_parse_octal (cptr, &reg); /* get register */
310 if (! cptr || reg > 15) {
311 /*printf ("Bad register\n");*/
312 return 0;
313 }
314 cptr = skip_spaces (cptr); /* absorb spaces */
315 if (*cptr == '2' || *cptr == '3') {
316 /* Длинная команда. */
317 cptr = besm6_parse_octal (cptr, &opcode);
318 if (! cptr || opcode < 020 || opcode > 037) {
319 /*printf ("Bad long opcode\n");*/
320 return 0;
321 }
322 opcode <<= 3;
323 } else {
324 /* Короткая команда. */
325 cptr = besm6_parse_octal (cptr, &opcode);
326 if (! cptr || opcode > 0177) {
327 /*printf ("Bad short opcode\n");*/
328 return 0;
329 }
330 }
331 cptr = besm6_parse_octal (cptr, &addr); /* get address */
332 if (! cptr || addr > BITS(15) ||
333 (opcode <= 0177 && addr > BITS(12))) {
334 /*printf ("Bad address\n");*/
335 return 0;
336 }
337 } else {
338 /* Мнемоническое представление команды. */
339 cptr = get_alnum (cptr, gbuf); /* get opcode */
340 opcode = besm6_opcode (gbuf);
341 if (opcode < 0) {
342 /*printf ("Bad opname: %s\n", gbuf);*/
343 return 0;
344 }
345 negate = 0;
346 cptr = skip_spaces (cptr); /* absorb spaces */
347 if (*cptr == '-') { /* negative offset */
348 negate = 1;
349 cptr = skip_spaces (cptr + 1); /* absorb spaces */
350 }
351 addr = 0;
352 if (*cptr >= '0' && *cptr <= '7') {
353 /* Восьмеричный адрес. */
354 cptr = besm6_parse_octal (cptr, &addr);
355 if (! cptr || addr > BITS(15)) {
356 /*printf ("Bad address: %o\n", addr);*/
357 return 0;
358 }
359 if (negate)
360 addr = (- addr) & BITS(15);
361 if (opcode <= 077 && addr > BITS(12)) {
362 if (addr < 070000) {
363 /*printf ("Bad short address: %o\n", addr);*/
364 return 0;
365 }
366 opcode |= 0100;
367 addr &= BITS(12);
368 }
369 }
370 reg = 0;
371 cptr = skip_spaces (cptr); /* absorb spaces */
372 if (*cptr == '(') {
373 /* Индекс-регистр в скобках. */
374 cptr = besm6_parse_octal (cptr+1, &reg);
375 if (! cptr || reg > 15) {
376 /*printf ("Bad register: %o\n", reg);*/
377 return 0;
378 }
379 cptr = skip_spaces (cptr); /* absorb spaces */
380 if (*cptr != ')') {
381 /*printf ("No closing brace\n");*/
382 return 0;
383 }
384 ++cptr;
385 }
386 }
387 *val = reg << 20 | opcode << 12 | addr;
388 return cptr;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800389}
390
391/*
392 * Instruction parse: two commands per word.
393 */
Mark Pizzolato5531ccb2016-05-15 15:25:33 -0700394t_stat parse_instruction_word (CONST char *cptr, t_value *val)
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800395{
Leo Broukhiscc332572014-12-30 11:42:52 -0800396 uint32 left, right;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800397
Leo Broukhiscc332572014-12-30 11:42:52 -0800398 *val = 0;
399 cptr = parse_instruction (cptr, &left);
400 if (! cptr)
401 return SCPE_ARG;
402 right = 0;
403 cptr = skip_spaces (cptr);
404 if (*cptr == ',') {
405 cptr = parse_instruction (cptr + 1, &right);
406 if (! cptr)
407 return SCPE_ARG;
408 }
409 cptr = skip_spaces (cptr); /* absorb spaces */
410 if (*cptr != 0 && *cptr != ';' && *cptr != '\n' && *cptr != '\r') {
411 /*printf ("Extra symbols at eoln: %s\n", cptr);*/
412 return SCPE_2MARG;
413 }
414 *val = (t_value) left << 24 | right;
415 return SCPE_OK;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800416}
417
418/*
419 * Печать машинной инструкции с мнемоникой.
420 */
421void besm6_fprint_cmd (FILE *of, uint32 cmd)
422{
Leo Broukhiscc332572014-12-30 11:42:52 -0800423 int reg, opcode, addr;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800424
Leo Broukhiscc332572014-12-30 11:42:52 -0800425 reg = (cmd >> 20) & 017;
426 if (cmd & BBIT(20)) {
427 opcode = (cmd >> 12) & 0370;
428 addr = cmd & BITS(15);
429 } else {
430 opcode = (cmd >> 12) & 077;
431 addr = cmd & 07777;
432 if (cmd & BBIT(19))
433 addr |= 070000;
434 }
435 fprintf (of, "%s", besm6_opname (opcode));
436 if (addr) {
437 fprintf (of, " ");
438 if (addr >= 077700)
439 fprintf (of, "-%o", (addr ^ 077777) + 1);
440 else
441 fprintf (of, "%o", addr);
442 }
443 if (reg) {
444 if (! addr)
445 fprintf (of, " ");
446 fprintf (of, "(%o)", reg);
447 }
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800448}
449
450/*
451 * Печать машинной инструкции в восьмеричном виде.
452 */
453void besm6_fprint_insn (FILE *of, uint32 insn)
454{
Leo Broukhiscc332572014-12-30 11:42:52 -0800455 if (insn & BBIT(20))
456 fprintf (of, "%02o %02o %05o ",
457 insn >> 20, (insn >> 15) & 037, insn & BITS(15));
458 else
459 fprintf (of, "%02o %03o %04o ",
460 insn >> 20, (insn >> 12) & 0177, insn & 07777);
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800461}
462
463/*
464 * Symbolic decode
465 *
466 * Inputs:
Leo Broukhiscc332572014-12-30 11:42:52 -0800467 * *of = output stream
468 * addr = current PC
469 * *val = pointer to data
470 * *uptr = pointer to unit
471 * sw = switches
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800472 * Outputs:
Leo Broukhiscc332572014-12-30 11:42:52 -0800473 * return = status code
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800474 */
475t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
Leo Broukhiscc332572014-12-30 11:42:52 -0800476 UNIT *uptr, int32 sw)
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800477{
Leo Broukhiscc332572014-12-30 11:42:52 -0800478 t_value cmd;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800479
Leo Broukhiscc332572014-12-30 11:42:52 -0800480 if (uptr && (uptr != &cpu_unit)) /* must be CPU */
481 return SCPE_ARG;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800482
Leo Broukhiscc332572014-12-30 11:42:52 -0800483 cmd = val[0];
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800484
485
Leo Broukhiscc332572014-12-30 11:42:52 -0800486 if (sw & SWMASK ('M')) { /* symbolic decode? */
487 if (sw & SIM_SW_STOP && addr == PC && !(RUU & RUU_RIGHT_INSTR))
488 fprintf (of, "-> ");
Mark Pizzolato76dd31a2014-12-30 17:52:13 -0800489 besm6_fprint_cmd (of, (uint32)(cmd >> 24));
Leo Broukhiscc332572014-12-30 11:42:52 -0800490 if (sw & SIM_SW_STOP) /* stop point */
491 fprintf (of, ", ");
492 else
493 fprintf (of, ",\n\t");
494 if (sw & SIM_SW_STOP && addr == PC && (RUU & RUU_RIGHT_INSTR))
495 fprintf (of, "-> ");
496 besm6_fprint_cmd (of, cmd & BITS(24));
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800497
Leo Broukhiscc332572014-12-30 11:42:52 -0800498 } else if (sw & SWMASK ('I')) {
499 besm6_fprint_insn (of, (cmd >> 24) & BITS(24));
500 besm6_fprint_insn (of, cmd & BITS(24));
501 } else if (sw & SWMASK ('F')) {
502 fprintf (of, "%#.2g", besm6_to_ieee(cmd));
503 } else if (sw & SWMASK ('B')) {
504 fprintf (of, "%03o %03o %03o %03o %03o %03o",
505 (int) (cmd >> 40) & 0377,
506 (int) (cmd >> 32) & 0377,
507 (int) (cmd >> 24) & 0377,
508 (int) (cmd >> 16) & 0377,
509 (int) (cmd >> 8) & 0377,
510 (int) cmd & 0377);
511 } else if (sw & SWMASK ('X')) {
512 fprintf (of, "%013llx", cmd);
513 } else
514 fprintf (of, "%04o %04o %04o %04o",
515 (int) (cmd >> 36) & 07777,
516 (int) (cmd >> 24) & 07777,
517 (int) (cmd >> 12) & 07777,
518 (int) cmd & 07777);
519 return SCPE_OK;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800520}
521
522/*
523 * Symbolic input
524 *
525 * Inputs:
Leo Broukhiscc332572014-12-30 11:42:52 -0800526 * *cptr = pointer to input string
527 * addr = current PC
528 * *uptr = pointer to unit
529 * *val = pointer to output values
530 * sw = switches
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800531 * Outputs:
Leo Broukhiscc332572014-12-30 11:42:52 -0800532 * status = error status
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800533 */
Mark Pizzolato5531ccb2016-05-15 15:25:33 -0700534t_stat parse_sym (CONST char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800535{
Leo Broukhiscc332572014-12-30 11:42:52 -0800536 int32 i;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800537
Leo Broukhiscc332572014-12-30 11:42:52 -0800538 if (uptr && (uptr != &cpu_unit)) /* must be CPU */
539 return SCPE_ARG;
540 if (! parse_instruction_word (cptr, val)) /* symbolic parse? */
541 return SCPE_OK;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800542
Leo Broukhiscc332572014-12-30 11:42:52 -0800543 val[0] = 0;
544 for (i=0; i<16; i++) {
545 if (*cptr < '0' || *cptr > '7')
546 break;
547 val[0] = (val[0] << 3) | (*cptr - '0');
548 cptr = skip_spaces (cptr+1); /* next char */
549 }
550 if (*cptr != 0 && *cptr != ';' && *cptr != '\n' && *cptr != '\r') {
551 /*printf ("Extra symbols at eoln: %s\n", cptr);*/
552 return SCPE_2MARG;
553 }
554 return SCPE_OK;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800555}
556
557/*
558 * Чтение строки входного файла.
559 * Форматы строк:
Leo Broukhiscc332572014-12-30 11:42:52 -0800560 * п 76543 - адрес пуска
561 * в 12345 - адрес ввода
Serge Vakulenko5ed19092015-01-21 12:29:29 -0800562 * ч -123.45e+6 - вещественное число
Leo Broukhiscc332572014-12-30 11:42:52 -0800563 * с 0123 4567 0123 4567 - восьмеричное слово
564 * к 00 22 00000 00 010 0000 - команды
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800565 */
566t_stat besm6_read_line (FILE *input, int *type, t_value *val)
567{
Mark Pizzolato5531ccb2016-05-15 15:25:33 -0700568 char buf [512];
569 CONST char *p;
Leo Broukhiscc332572014-12-30 11:42:52 -0800570 int i, c;
571 again:
572 if (! fgets (buf, sizeof (buf), input)) {
573 *type = 0;
574 return SCPE_OK;
575 }
576 p = skip_spaces (buf);
577 if (*p == '\n' || *p == ';')
578 goto again;
579 c = utf8_to_unicode (&p);
580 if (c == CYRILLIC_SMALL_LETTER_VE ||
581 c == CYRILLIC_CAPITAL_LETTER_VE ||
582 c == 'b' || c == 'B') {
583 /* Адрес размещения данных. */
584 *type = ':';
585 *val = strtol (p, 0, 8);
586 return SCPE_OK;
587 }
588 if (c == CYRILLIC_SMALL_LETTER_PE ||
589 c == CYRILLIC_CAPITAL_LETTER_PE ||
590 c == 'p' || c == 'P') {
591 /* Стартовый адрес. */
592 *type = '@';
593 *val = strtol (p, 0, 8);
594 return SCPE_OK;
595 }
596 if (c == CYRILLIC_SMALL_LETTER_CHE ||
597 c == CYRILLIC_CAPITAL_LETTER_CHE ||
598 c == 'f' || c == 'F') {
599 /* Вещественное число. */
600 *type = '=';
601 *val = ieee_to_besm6 (strtod (p, 0));
602 return SCPE_OK;
603 }
604 if (c == CYRILLIC_SMALL_LETTER_ES ||
605 c == CYRILLIC_CAPITAL_LETTER_ES ||
606 c == 'c' || c == 'C') {
607 /* Восьмеричное слово. */
608 *type = '=';
609 *val = 0;
610 for (i=0; i<16; ++i) {
611 p = skip_spaces (p);
612 if (*p < '0' || *p > '7') {
613 if (i == 0) {
614 /* слишком короткое слово */
615 goto bad;
616 }
617 break;
618 }
619 *val = *val << 3 | (*p++ - '0');
620 }
621 return SCPE_OK;
622 }
623 if (c == CYRILLIC_SMALL_LETTER_KA ||
624 c == CYRILLIC_CAPITAL_LETTER_KA ||
625 c == 'k' || c == 'K') {
626 /* Команда. */
627 *type = '*';
628 if (parse_instruction_word (p, val) != SCPE_OK)
629 goto bad;
630 return SCPE_OK;
631 }
632 /* Неверная строка входного файла */
633 bad: besm6_log ("Invalid input line: %s", buf);
634 return SCPE_FMT;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800635}
636
637/*
638 * Load memory from file.
639 */
640t_stat besm6_load (FILE *input)
641{
Leo Broukhiscc332572014-12-30 11:42:52 -0800642 int addr, type;
643 t_value word;
644 t_stat err;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800645
Leo Broukhiscc332572014-12-30 11:42:52 -0800646 addr = 1;
647 PC = 1;
648 for (;;) {
649 err = besm6_read_line (input, &type, &word);
650 if (err)
651 return err;
652 switch (type) {
653 case 0: /* EOF */
654 return SCPE_OK;
655 case ':': /* address */
Mark Pizzolato76dd31a2014-12-30 17:52:13 -0800656 addr = (int)word;
Leo Broukhiscc332572014-12-30 11:42:52 -0800657 break;
658 case '=': /* word */
659 if (addr < 010)
Leo Broukhisd4cb5e82015-02-13 09:33:40 -0800660 pult [0][addr] = SET_PARITY (word, PARITY_NUMBER);
Leo Broukhiscc332572014-12-30 11:42:52 -0800661 else
Leo Broukhisd4cb5e82015-02-13 09:33:40 -0800662 memory [addr] = SET_PARITY (word, PARITY_NUMBER);
Leo Broukhiscc332572014-12-30 11:42:52 -0800663 ++addr;
664 break;
665 case '*': /* instruction */
666 if (addr < 010)
Leo Broukhisd4cb5e82015-02-13 09:33:40 -0800667 pult [0][addr] = SET_PARITY (word, PARITY_INSN);
Leo Broukhiscc332572014-12-30 11:42:52 -0800668 else
Leo Broukhisd4cb5e82015-02-13 09:33:40 -0800669 memory [addr] = SET_PARITY (word, PARITY_INSN);
Leo Broukhiscc332572014-12-30 11:42:52 -0800670 ++addr;
671 break;
672 case '@': /* start address */
Mark Pizzolato76dd31a2014-12-30 17:52:13 -0800673 PC = (uint32)word;
Leo Broukhiscc332572014-12-30 11:42:52 -0800674 break;
675 }
676 if (addr > MEMSIZE)
677 return SCPE_FMT;
678 }
679 return SCPE_OK;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800680}
681
682/*
683 * Dump memory to file.
684 */
Mark Pizzolato5531ccb2016-05-15 15:25:33 -0700685t_stat besm6_dump (FILE *of, const char *fnam)
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800686{
Leo Broukhiscc332572014-12-30 11:42:52 -0800687 int addr, last_addr = -1;
688 t_value word;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800689
Leo Broukhiscc332572014-12-30 11:42:52 -0800690 fprintf (of, "; %s\n", fnam);
691 for (addr=1; addr<MEMSIZE; ++addr) {
692 if (addr < 010)
Leo Broukhis9ff642f2015-01-14 00:39:55 -0800693 word = pult [0][addr];
Leo Broukhiscc332572014-12-30 11:42:52 -0800694 else
695 word = memory [addr];
696 if (word == 0)
697 continue;
698 if (addr != last_addr+1) {
699 fprintf (of, "\nв %05o\n", addr);
700 }
701 last_addr = addr;
702 if (IS_INSN (word)) {
703 fprintf (of, "к ");
Mark Pizzolato76dd31a2014-12-30 17:52:13 -0800704 besm6_fprint_cmd (of, (uint32)(word >> 24));
Leo Broukhiscc332572014-12-30 11:42:52 -0800705 fprintf (of, ", ");
706 besm6_fprint_cmd (of, word & BITS(24));
707 fprintf (of, "\t\t; %05o - ", addr);
708 fprintf (of, "%04o %04o %04o %04o\n",
709 (int) (word >> 36) & 07777,
710 (int) (word >> 24) & 07777,
711 (int) (word >> 12) & 07777,
712 (int) word & 07777);
713 } else {
714 fprintf (of, "с %04o %04o %04o %04o",
715 (int) (word >> 36) & 07777,
716 (int) (word >> 24) & 07777,
717 (int) (word >> 12) & 07777,
718 (int) word & 07777);
719 fprintf (of, "\t\t; %05o\n", addr);
720 }
721 }
722 return SCPE_OK;
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800723}
724
725/*
726 * Loader/dumper
727 */
Mark Pizzolato5531ccb2016-05-15 15:25:33 -0700728t_stat sim_load (FILE *fi, CONST char *cptr, CONST char *fnam, int dump_flag)
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800729{
Leo Broukhiscc332572014-12-30 11:42:52 -0800730 if (dump_flag)
731 return besm6_dump (fi, fnam);
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800732
Leo Broukhiscc332572014-12-30 11:42:52 -0800733 return besm6_load (fi);
Leo Broukhisb4eeaa72014-12-30 00:41:31 -0800734}