mirror of
https://github.com/open-simh/simtools.git
synced 2026-01-26 20:21:45 +00:00
931 lines
26 KiB
C
931 lines
26 KiB
C
/*
|
|
** HPASM.C -- Assembler for HP2100
|
|
*/
|
|
/****************************************************/
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
/****************************************************/
|
|
#define MXSYM 1500
|
|
#define MXLABEL 5
|
|
#define ALLOW_SPECIALS_IN_LABEL 1
|
|
/****************************************************/
|
|
typedef struct {
|
|
char name[MXLABEL+1];
|
|
long value;
|
|
} SYM;
|
|
/****************************************************/
|
|
long nbsyms;
|
|
SYM symtab[MXSYM];
|
|
long pass;
|
|
long addr;
|
|
char line[80];
|
|
long lp;
|
|
long line_count;
|
|
long err_count;
|
|
long print_flag; /* =1 if current line has been printed */
|
|
int ifn_flag=0; /* =1 if IFN does not skip */
|
|
int ifz_flag=0; /* =1 if IFZ does not skip */
|
|
int xif_flag=0; /* =1 if we are skipping until XIF */
|
|
int rep_count=0; /* >0 if REP statement in process */
|
|
/****************************************************/
|
|
/*
|
|
** Variables for listing output routines
|
|
*/
|
|
char listfilename[256];
|
|
FILE *listfile;
|
|
/****************************************************/
|
|
start_listing (nam)
|
|
/*
|
|
** Initialize listing output file
|
|
*/
|
|
char *nam;
|
|
{
|
|
char *ppos;
|
|
|
|
strncpy (listfilename, nam, 250);
|
|
if (ppos = strrchr (listfilename, '.')) strcpy (ppos, ".lst");
|
|
else strcat (listfilename, ".lst");
|
|
listfile = fopen (listfilename, "w");
|
|
}
|
|
/****************************************************/
|
|
finish_listing () {
|
|
/*
|
|
** Finish off listing output file
|
|
*/
|
|
fclose (listfile);
|
|
printf ("Listing is in %s\n", listfilename);
|
|
}
|
|
/****************************************************/
|
|
/*
|
|
** Variables for binary output routines
|
|
*/
|
|
char outfilename[256];
|
|
FILE *outfile;
|
|
long outaddr;
|
|
long outcount;
|
|
long outbufsize=27;
|
|
long outbuf[27];
|
|
/****************************************************/
|
|
start_output (nam)
|
|
/*
|
|
** Initialize binary output file
|
|
*/
|
|
char *nam;
|
|
{
|
|
char *ppos;
|
|
|
|
strncpy (outfilename, nam, 250);
|
|
if (ppos = strrchr (outfilename, '.')) strcpy (ppos, ".bin");
|
|
else strcat (outfilename, ".bin");
|
|
outfile = fopen (outfilename, "wb");
|
|
outaddr = 0;
|
|
outcount = 0;
|
|
}
|
|
/****************************************************/
|
|
send_output () {
|
|
/*
|
|
** Write block to binary output file
|
|
*/
|
|
long ii,sum;
|
|
|
|
fputc (outcount, outfile);
|
|
fputc (0, outfile);
|
|
fputc (outaddr >> 8, outfile);
|
|
fputc (outaddr & 255, outfile);
|
|
sum = outaddr;
|
|
for (ii=0 ; ii < outcount ; ii++) {
|
|
fputc (outbuf[ii] >> 8, outfile);
|
|
fputc (outbuf[ii] & 255, outfile);
|
|
sum += outbuf[ii];
|
|
}
|
|
fputc (sum >> 8, outfile);
|
|
fputc (sum & 255, outfile);
|
|
outcount = 0;
|
|
}
|
|
/****************************************************/
|
|
output_word (addr,word)
|
|
/*
|
|
** Write word to binary output file
|
|
*/
|
|
long addr;
|
|
long word;
|
|
{
|
|
if (outcount && (outaddr + outcount) != addr) {
|
|
send_output();
|
|
}
|
|
if (!outcount) outaddr = addr;
|
|
outbuf[outcount++] = word;
|
|
if (outcount == outbufsize) {
|
|
send_output();
|
|
}
|
|
}
|
|
/****************************************************/
|
|
finish_output () {
|
|
/*
|
|
** Finish current output block, write trailing leader,
|
|
** and close output file
|
|
*/
|
|
int ii;
|
|
if (outcount) send_output();
|
|
for (ii=0; ii<20; ii++) fputc (0, outfile);
|
|
fclose (outfile);
|
|
printf ("Output is in %s\n", outfilename);
|
|
}
|
|
/****************************************************/
|
|
emit (code)
|
|
long code;
|
|
{
|
|
fprintf (listfile, " %05lo %06lo ", addr, code);
|
|
if (!print_flag) {
|
|
fprintf (listfile, "%s", line);
|
|
print_flag = 1;
|
|
}
|
|
fprintf (listfile, "\n");
|
|
|
|
output_word (addr, code);
|
|
addr++;
|
|
}
|
|
/****************************************************/
|
|
err (text)
|
|
char *text;
|
|
{
|
|
if (!print_flag) {
|
|
fprintf (listfile, " %12s %s\n", " ", line);
|
|
print_flag = 1;
|
|
}
|
|
fprintf (listfile, "ERROR: %s\n", text);
|
|
err_count++;
|
|
}
|
|
/****************************************************/
|
|
int is_valid_label_char (ch)
|
|
char ch;
|
|
{
|
|
if (isalpha(ch)) return (1);
|
|
if (isdigit(ch)) return (1);
|
|
if (ch=='.') return (1);
|
|
#if ALLOW_SPECIALS_IN_LABEL
|
|
if (ch=='&') return (1);
|
|
if (ch=='?') return (1);
|
|
if (ch=='#') return (1);
|
|
if (ch=='/') return (1);
|
|
if (ch=='%') return (1);
|
|
if (ch=='$') return (1);
|
|
if (ch=='[') return (1);
|
|
if (ch=='@') return (1);
|
|
if (ch=='!') return (1);
|
|
if (ch=='^') return (1);
|
|
#endif
|
|
return (0);
|
|
}
|
|
/****************************************************/
|
|
void insert_label (label, value)
|
|
char *label;
|
|
long value;
|
|
/*
|
|
** Insert label into symbol table
|
|
*/
|
|
{
|
|
long i;
|
|
if (strlen(label)>MXLABEL) {
|
|
err ("Symbol name > 5");
|
|
return;
|
|
}
|
|
for (i=0; i<nbsyms; i++) {
|
|
if (!strcmp(symtab[i].name, label)) {
|
|
err ("Duplicate symbol");
|
|
return;
|
|
}
|
|
}
|
|
if (nbsyms == MXSYM) {
|
|
err ("Symbol table is full!");
|
|
return;
|
|
}
|
|
strcpy (symtab[nbsyms].name, label);
|
|
symtab[nbsyms].value = value;
|
|
nbsyms++;
|
|
}
|
|
/****************************************************/
|
|
void find_label (label, value)
|
|
char *label;
|
|
long *value;
|
|
{
|
|
long i;
|
|
for (i=0; i<nbsyms; i++) {
|
|
if (!strcmp(symtab[i].name, label)) {
|
|
*value = symtab[i].value;
|
|
return;
|
|
}
|
|
}
|
|
err ("Undefined symbol");
|
|
*value=0;
|
|
}
|
|
/****************************************************/
|
|
show_labels ()
|
|
{
|
|
long i;
|
|
for (i=0; i<nbsyms; i++) {
|
|
fprintf (listfile, "%-6s %06lo \n", symtab[i].name, symtab[i].value );
|
|
}
|
|
}
|
|
/****************************************************/
|
|
int double_to_hp (num, a, b)
|
|
double num;
|
|
long *a,*b;
|
|
/*
|
|
** Convert floating point number to HP 21xx format
|
|
** Accepts:
|
|
** num Number to convert
|
|
** Returns:
|
|
** a,b Number in HP format
|
|
** ret 0=Success, -2=Underflow, -3=Overflow
|
|
*/
|
|
{
|
|
int neg=0;
|
|
long frac;
|
|
int exp=0;
|
|
|
|
*a = 0; *b = 0;
|
|
|
|
if (num == 0.0) return (0);
|
|
|
|
if (num < 0.0) { num = -num; neg = 1; }
|
|
|
|
while (num >= 1.0) { num = num / 2; exp++; }
|
|
while (num < 0.5) { num = num * 2; exp--; }
|
|
|
|
if (neg) num = -num;
|
|
|
|
if (neg) num += (0177 / 65536.0 / 65536.0);
|
|
else num += (0200 / 65536.0 / 65536.0);
|
|
|
|
if (neg && num >= -0.5) { num = num * 2; exp--; }
|
|
if (!neg && num >= 1.0) { num = num / 2; exp++; }
|
|
|
|
if (exp < -128) return (-2);
|
|
|
|
if (exp > 127) {
|
|
if (neg) { *a = 0x8000; *b = 0x01FE; }
|
|
else { *a = 0x7FFF; *b = 0xFFFE; }
|
|
return (-3);
|
|
}
|
|
|
|
frac = num * 65536.0 * 128.0 * 256.0;
|
|
exp = exp << 1;
|
|
if (exp < 0) exp++;
|
|
*a = (frac >> 16) & 0xFFFF;
|
|
*b = (frac & 0xFF00) | (exp & 0x00FF);
|
|
|
|
return (0);
|
|
}
|
|
/****************************************************/
|
|
parse_digits (base, out)
|
|
int base;
|
|
long *out;
|
|
{
|
|
long dig, val;
|
|
val = 0;
|
|
dig = line[lp] - '0';
|
|
while (dig>=0 && dig<base) {
|
|
val = val*base + dig;
|
|
dig = line[++lp] - '0';
|
|
}
|
|
*out = val;
|
|
}
|
|
/****************************************************/
|
|
parse_const (out)
|
|
long *out;
|
|
{
|
|
long save, val;
|
|
save = lp;
|
|
parse_digits (10, &val);
|
|
if (toupper(line[lp])=='B') {
|
|
lp = save;
|
|
parse_digits (8,&val);
|
|
if (toupper(line[lp])=='B') lp++;
|
|
else err ("Illegal octal digit");
|
|
}
|
|
*out = val;
|
|
}
|
|
/****************************************************/
|
|
parse_sym (out)
|
|
long *out;
|
|
{
|
|
char sym[MXLABEL+1];
|
|
int count,done;
|
|
char ch;
|
|
count=0;
|
|
done=0;
|
|
while (!done) {
|
|
ch = line[lp];
|
|
if (is_valid_label_char(ch)) {
|
|
if (count<MXLABEL) sym[count]=ch;
|
|
count++;
|
|
lp++;
|
|
} else {
|
|
done=1;
|
|
}
|
|
}
|
|
if (count>MXLABEL) {
|
|
err ("Illegal symbol");
|
|
*out=0;
|
|
} else {
|
|
sym[count]=0;
|
|
find_label (sym, out);
|
|
}
|
|
}
|
|
/****************************************************/
|
|
parse_term (out)
|
|
long *out;
|
|
{
|
|
char ch;
|
|
ch = line[lp];
|
|
if (isdigit(ch)) parse_const (out);
|
|
else if (is_valid_label_char(ch)) parse_sym (out);
|
|
else if (ch=='*') { lp++; *out = addr; }
|
|
else {
|
|
err ("Syntax error in expression");
|
|
*out=0;
|
|
}
|
|
}
|
|
/****************************************************/
|
|
parse_neg (out)
|
|
long *out;
|
|
{
|
|
long temp;
|
|
if (line[lp]=='-') {
|
|
lp++;
|
|
parse_term (&temp);
|
|
*out = (-temp) & 0xFFFF;
|
|
} else if (line[lp]=='+') {
|
|
lp++;
|
|
parse_term (out);
|
|
} else {
|
|
parse_term (out);
|
|
}
|
|
}
|
|
/****************************************************/
|
|
parse_sum (out)
|
|
long *out;
|
|
{
|
|
long v1,v2,op;
|
|
parse_neg (&v1);
|
|
while (line[lp]=='+' || line[lp]=='-') {
|
|
op = line[lp++];
|
|
parse_neg (&v2);
|
|
if (op=='+') v1 = v1 + v2;
|
|
if (op=='-') v1 = v1 - v2;
|
|
}
|
|
*out = v1 & 0xFFFF;
|
|
}
|
|
/****************************************************/
|
|
parse_arg (out)
|
|
long *out;
|
|
{
|
|
while (isspace (line[lp])) lp++;
|
|
/* while (line[lp]==' ') lp++; */
|
|
parse_sum (out);
|
|
}
|
|
/****************************************************/
|
|
parse_oct (out)
|
|
long *out;
|
|
{
|
|
long sign,val;
|
|
|
|
while (isspace (line[lp])) lp++;
|
|
/* while (line[lp]==' ') lp++; */
|
|
sign = line[lp];
|
|
if (sign=='+' || sign=='-') lp++;
|
|
parse_digits (8, &val);
|
|
if (sign=='-') val = (-val) & 0xFFFF;
|
|
*out =val;
|
|
}
|
|
/****************************************************/
|
|
parse_dec (out, nbwords)
|
|
long *out, *nbwords;
|
|
{
|
|
long save,sign,val,a,b;
|
|
extern double atof();
|
|
double num;
|
|
|
|
while (isspace (line[lp])) lp++;
|
|
/* while (line[lp]==' ') lp++; */
|
|
save = lp;
|
|
sign = line[lp];
|
|
if (sign=='+' || sign=='-') lp++;
|
|
parse_digits (10, &val);
|
|
if (sign=='-') val = (-val) & 0xFFFF;
|
|
out[0] = val;
|
|
*nbwords = 1;
|
|
|
|
if (line[lp]=='.' || toupper(line[lp])=='E') {
|
|
num = atof( &(line[save]) );
|
|
while (isdigit(line[lp]) || line[lp]=='.' || toupper(line[lp])=='E') lp++;
|
|
double_to_hp (num, &a, &b);
|
|
out[0] = a;
|
|
out[1] = b;
|
|
*nbwords = 2;
|
|
}
|
|
}
|
|
/****************************************************/
|
|
mem_group (opcode, code)
|
|
int opcode;
|
|
long *code;
|
|
{
|
|
long arg, out;
|
|
parse_arg (&arg);
|
|
if (arg < 02000) {
|
|
out = opcode + arg;
|
|
} else if ((arg & 0776000) == (addr & 0776000)) {
|
|
out = opcode + 02000 + (arg & 01777);
|
|
} else {
|
|
err ("Operand page error");
|
|
out = opcode;
|
|
}
|
|
if (line[lp]==',' && toupper(line[lp+1])=='I') {
|
|
out = out + 0100000L;
|
|
lp += 2;
|
|
}
|
|
code[0] = out;
|
|
}
|
|
/****************************************************/
|
|
io_group (opcode, code)
|
|
int opcode;
|
|
long *code;
|
|
{
|
|
long arg, out;
|
|
parse_arg (&arg);
|
|
if (arg > 077) {
|
|
err ("Select code > 77B");
|
|
arg = 0;
|
|
}
|
|
out = opcode + arg;
|
|
if (line[lp]==',' && toupper(line[lp+1])=='C') {
|
|
out += 001000;
|
|
lp += 2;
|
|
}
|
|
code[0] = out;
|
|
}
|
|
/****************************************************/
|
|
overflow_group (opcode, code)
|
|
int opcode;
|
|
long *code;
|
|
{
|
|
code[0] = opcode;
|
|
if (isspace (line[lp]) && toupper(line[lp+1])=='C') {
|
|
/* if (line[lp]==' ' && line[lp+1]=='C') { */
|
|
code[0] += 001000;
|
|
lp += 2;
|
|
}
|
|
}
|
|
/****************************************************/
|
|
parse_label (label)
|
|
char *label;
|
|
{
|
|
int i=0;
|
|
while (is_valid_label_char(line[lp])) {
|
|
if (i<MXLABEL) label[i++]=line[lp];
|
|
lp++;
|
|
}
|
|
label[i]=0;
|
|
}
|
|
/****************************************************/
|
|
int try (instr)
|
|
char *instr;
|
|
{
|
|
int ii,out;
|
|
for (ii=0; instr[ii]; ii++) {
|
|
if (toupper(line[lp+ii]) != instr[ii]) {
|
|
return (0);
|
|
}
|
|
}
|
|
if (isalpha(line[lp+ii])) out=0;
|
|
else {
|
|
lp += ii;
|
|
if (line[lp]==',') lp++;
|
|
out=1;
|
|
}
|
|
return (out);
|
|
}
|
|
/****************************************************/
|
|
int end_of_line()
|
|
{
|
|
int ll,out;
|
|
ll=lp;
|
|
out=0;
|
|
if (isspace (line[ll])) return 1;
|
|
while (isspace (line[ll])) ll++;
|
|
/* if (line[ll]=' ') return(1);
|
|
while (line[ll]==' ') ll++; */
|
|
if (line[ll]==';' || line[ll]=='\n' || line[ll]==0) {
|
|
out=1;
|
|
}
|
|
return (out);
|
|
}
|
|
/****************************************************/
|
|
int try_mem_group (code)
|
|
long *code;
|
|
{
|
|
int ok=1;
|
|
if (try("NOP")) code[0]=0;
|
|
else if (try("AND")) mem_group (010000, code);
|
|
else if (try("XOR")) mem_group (020000, code);
|
|
else if (try("IOR")) mem_group (030000, code);
|
|
else if (try("JSB")) mem_group (014000, code);
|
|
else if (try("JMP")) mem_group (024000, code);
|
|
else if (try("ISZ")) mem_group (034000, code);
|
|
else if (try("ADA")) mem_group (040000, code);
|
|
else if (try("ADB")) mem_group (044000, code);
|
|
else if (try("CPA")) mem_group (050000, code);
|
|
else if (try("CPB")) mem_group (054000, code);
|
|
else if (try("LDA")) mem_group (060000, code);
|
|
else if (try("LDB")) mem_group (064000, code);
|
|
else if (try("STA")) mem_group (070000, code);
|
|
else if (try("STB")) mem_group (074000, code);
|
|
else ok=0;
|
|
return (ok);
|
|
}
|
|
/****************************************************/
|
|
int try_srg_a (code)
|
|
long *code;
|
|
{
|
|
int ok=0;
|
|
long out=0;
|
|
long save=lp;
|
|
if (try("ALS")) out += 001000;
|
|
else if (try("ARS")) out += 001100;
|
|
else if (try("RAL")) out += 001200;
|
|
else if (try("RAR")) out += 001300;
|
|
else if (try("ALR")) out += 001400;
|
|
else if (try("ERA")) out += 001500;
|
|
else if (try("ELA")) out += 001600;
|
|
else if (try("ALF")) out += 001700;
|
|
if (try("CLE")) out += 000040;
|
|
if (try("SLA")) out += 000010;
|
|
if (try("ALS")) out += 000020;
|
|
else if (try("ARS")) out += 000021;
|
|
else if (try("RAL")) out += 000022;
|
|
else if (try("RAR")) out += 000023;
|
|
else if (try("ALR")) out += 000024;
|
|
else if (try("ERA")) out += 000025;
|
|
else if (try("ELA")) out += 000026;
|
|
else if (try("ALF")) out += 000027;
|
|
if (out && end_of_line()) {
|
|
code[0] = out;
|
|
ok=1;
|
|
} else {
|
|
lp = save;
|
|
ok=0;
|
|
}
|
|
return (ok);
|
|
}
|
|
/****************************************************/
|
|
int try_srg_b (code)
|
|
long *code;
|
|
{
|
|
int ok=0;
|
|
long out=0;
|
|
long save=lp;
|
|
if (try("BLS")) out += 001000;
|
|
else if (try("BRS")) out += 001100;
|
|
else if (try("RBL")) out += 001200;
|
|
else if (try("RBR")) out += 001300;
|
|
else if (try("BLR")) out += 001400;
|
|
else if (try("ERB")) out += 001500;
|
|
else if (try("ELB")) out += 001600;
|
|
else if (try("BLF")) out += 001700;
|
|
if (try("CLE")) out += 000040;
|
|
if (try("SLB")) out += 000010;
|
|
if (try("BLS")) out += 000020;
|
|
else if (try("BRS")) out += 000021;
|
|
else if (try("RBL")) out += 000022;
|
|
else if (try("RBR")) out += 000023;
|
|
else if (try("BLR")) out += 000024;
|
|
else if (try("ERB")) out += 000025;
|
|
else if (try("ELB")) out += 000026;
|
|
else if (try("BLF")) out += 000027;
|
|
if (out && end_of_line()) {
|
|
code[0] = out + 004000;
|
|
ok=1;
|
|
} else {
|
|
lp = save;
|
|
ok=0;
|
|
}
|
|
return (ok);
|
|
}
|
|
/****************************************************/
|
|
int try_asg_a (code)
|
|
long *code;
|
|
{
|
|
int ok=0;
|
|
long out=0;
|
|
long save=lp;
|
|
if (try("CLA")) out += 000400;
|
|
else if (try("CMA")) out += 001000;
|
|
else if (try("CCA")) out += 001400;
|
|
if (try("SEZ")) out += 000040;
|
|
if (try("CLE")) out += 000100;
|
|
else if (try("CME")) out += 000200;
|
|
else if (try("CCE")) out += 000300;
|
|
if (try("SSA")) out += 000020;
|
|
if (try("SLA")) out += 000010;
|
|
if (try("INA")) out += 000004;
|
|
if (try("SZA")) out += 000002;
|
|
if (try("RSS")) out += 000001;
|
|
if (out && end_of_line()) {
|
|
code[0] = out + 002000;
|
|
ok=1;
|
|
} else {
|
|
lp = save;
|
|
ok=0;
|
|
}
|
|
return (ok);
|
|
}
|
|
/****************************************************/
|
|
int try_asg_b (code)
|
|
long *code;
|
|
{
|
|
int ok=0;
|
|
long out=0;
|
|
long save=lp;
|
|
if (try("CLB")) out += 000400;
|
|
else if (try("CMB")) out += 001000;
|
|
else if (try("CCB")) out += 001400;
|
|
if (try("SEZ")) out += 000040;
|
|
if (try("CLE")) out += 000100;
|
|
else if (try("CME")) out += 000200;
|
|
else if (try("CCE")) out += 000300;
|
|
if (try("SSB")) out += 000020;
|
|
if (try("SLB")) out += 000010;
|
|
if (try("INB")) out += 000004;
|
|
if (try("SZB")) out += 000002;
|
|
if (try("RSS")) out += 000001;
|
|
if (out && end_of_line()) {
|
|
code[0] = out + 006000;
|
|
ok=1;
|
|
} else {
|
|
lp = save;
|
|
ok=0;
|
|
}
|
|
return (ok);
|
|
}
|
|
/****************************************************/
|
|
int try_io_group (code)
|
|
long *code;
|
|
{
|
|
int ok=1;
|
|
if (try("NOP")) code[0]=0;
|
|
else if (try("HLT")) io_group (0102000, code);
|
|
else if (try("STF")) io_group (0102100, code);
|
|
else if (try("CLF")) io_group (0103100, code);
|
|
else if (try("SFC")) io_group (0102200, code);
|
|
else if (try("SFS")) io_group (0102300, code);
|
|
else if (try("MIA")) io_group (0102400, code);
|
|
else if (try("MIB")) io_group (0106400, code);
|
|
else if (try("LIA")) io_group (0102500, code);
|
|
else if (try("LIB")) io_group (0106500, code);
|
|
else if (try("OTA")) io_group (0102600, code);
|
|
else if (try("OTB")) io_group (0106600, code);
|
|
else if (try("STC")) io_group (0102700, code);
|
|
else if (try("CLC")) io_group (0106700, code);
|
|
else ok=0;
|
|
return (ok);
|
|
}
|
|
|
|
/****************************************************/
|
|
int try_overflow (code)
|
|
long *code;
|
|
{
|
|
int ok=1;
|
|
if (try("STO")) code[0] = 0102101;
|
|
else if (try("CLO")) code[0] = 0103101;
|
|
else if (try("SOC")) overflow_group (0102201, code);
|
|
else if (try("SOS")) overflow_group (0102301, code);
|
|
else ok=0;
|
|
return (ok);
|
|
}
|
|
/****************************************************/
|
|
asm_pass (f)
|
|
FILE *f;
|
|
{
|
|
int done,count;
|
|
char label[MXLABEL+1];
|
|
long arg,code[2];
|
|
done=0;
|
|
while (!done) {
|
|
if (!fgets(line, sizeof(line), f)) {
|
|
done=1;
|
|
} else {
|
|
line_count++;
|
|
lp=strlen(line);
|
|
if (lp>0 && line[lp-1]=='\n') line[lp-1]=0;
|
|
print_flag = 0;
|
|
count = rep_count;
|
|
if (!count) count=1;
|
|
rep_count=0;
|
|
if (line[0]=='*') {
|
|
if (pass==2) {
|
|
fprintf (listfile, "%s\n", line);
|
|
print_flag = 1;
|
|
}
|
|
} else
|
|
while (count > 0) {
|
|
count--;
|
|
lp=0;
|
|
parse_label (label);
|
|
while (isspace (line[lp])) lp++;
|
|
/* while (line[lp]==' ') lp++; */
|
|
if (try("IFN")) {
|
|
if (!ifn_flag) xif_flag=1;
|
|
} else if (try("IFZ")) {
|
|
if (!ifz_flag) xif_flag=1;
|
|
} else if (try("XIF")) {
|
|
xif_flag=0;
|
|
} else if (xif_flag) {
|
|
while (line[lp]) lp++;
|
|
} else if (try("ORG")) {
|
|
parse_arg (&arg);
|
|
addr = arg;
|
|
if (pass==2) {
|
|
fprintf (listfile, " %05lo %s\n", addr, line);
|
|
print_flag = 1;
|
|
if (strlen(label)) err ("Unexpected label");
|
|
}
|
|
} else if (try("EQU")) {
|
|
parse_arg (&arg);
|
|
if (pass==1) {
|
|
if (strlen(label)) insert_label (label, arg);
|
|
} else {
|
|
fprintf (listfile, " %05lo %s\n", arg, line);
|
|
print_flag = 1;
|
|
if (!strlen(label)) err ("Label required");
|
|
}
|
|
} else if (!isalpha(line[lp])) {
|
|
if (pass==2) err ("No instruction on line");
|
|
} else {
|
|
|
|
if (pass==1 && strlen(label)) insert_label (label,addr);
|
|
|
|
if (try("HED") || try("SUP") || try("SPC") ||
|
|
try("SKP") || try("UNS") || try("UNL") ||
|
|
try("LST")) {
|
|
|
|
/* Listing control ops are ignored */
|
|
|
|
} else if (try("END")) {
|
|
|
|
/* No action required */
|
|
|
|
} else if (try("REP")) {
|
|
parse_arg (&arg);
|
|
if (arg < 1 || arg > 9999) {
|
|
err ("Illegal repeat count");
|
|
} else {
|
|
rep_count = arg;
|
|
}
|
|
} else if (try("ABS")) {
|
|
if (pass==1) addr++;
|
|
else {
|
|
parse_arg (code);
|
|
emit (code[0]);
|
|
}
|
|
} else if (try("DEF")) {
|
|
if (pass==1) addr++;
|
|
else {
|
|
parse_arg (code);
|
|
if (line[lp]==',' && toupper(line[lp+1])=='I') {
|
|
code[0] |= 0x8000;
|
|
lp += 2;
|
|
}
|
|
emit (code[0]);
|
|
}
|
|
} else if (try("DEC")) {
|
|
long nbwords;
|
|
parse_dec (code, &nbwords);
|
|
if (pass==1) addr += nbwords;
|
|
else {
|
|
if (nbwords > 0) emit (code[0]);
|
|
if (nbwords > 1) emit (code[1]);
|
|
}
|
|
} else if (try("OCT")) {
|
|
while (1) {
|
|
parse_oct (code);
|
|
if (pass==1) addr++;
|
|
else emit (code[0]);
|
|
if (line[lp]==',') lp++;
|
|
else break;
|
|
}
|
|
} else if (try("ASC")) {
|
|
long nbwords,c1,c2;
|
|
parse_arg (&nbwords);
|
|
if (pass==1) addr += nbwords;
|
|
else if (line[lp++]!=',') err ("Missing comma");
|
|
else
|
|
while (nbwords>0) {
|
|
if (line[lp]>31) c1=line[lp++]; else c1=' ';
|
|
if (line[lp]>31) c2=line[lp++]; else c2=' ';
|
|
emit (c1*256 + c2);
|
|
nbwords--;
|
|
}
|
|
} else if (try("BSS")) {
|
|
long nbwords;
|
|
if (pass==2) {
|
|
fprintf (listfile, " %05lo %s\n",
|
|
addr, line);
|
|
print_flag = 1;
|
|
}
|
|
parse_arg (&nbwords);
|
|
addr += nbwords;
|
|
}
|
|
else if (pass==1) addr++;
|
|
else if (try_mem_group(code)) emit (code[0]);
|
|
else if (try_srg_a(code)) emit (code[0]);
|
|
else if (try_srg_b(code)) emit (code[0]);
|
|
else if (try_asg_a(code)) emit (code[0]);
|
|
else if (try_asg_b(code)) emit (code[0]);
|
|
else if (try_io_group(code)) emit (code[0]);
|
|
else if (try_overflow(code)) emit (code[0]);
|
|
else {
|
|
emit (0L);
|
|
err ("Unknown instruction");
|
|
}
|
|
}
|
|
if (pass==2 && !end_of_line()) err ("Missing End-of-line");
|
|
if (pass==2 && !print_flag) fprintf (listfile, " %12s %s\n",
|
|
" ", line);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/****************************************************/
|
|
main (argc,argv)
|
|
int argc;
|
|
char *argv[];
|
|
{
|
|
FILE *f1;
|
|
int ii,jj;
|
|
|
|
jj=1;
|
|
for (ii=1 ; ii < argc ; ii++) {
|
|
if (!strcmp(argv[ii],"-n")) ifn_flag=1;
|
|
else if (!strcmp(argv[ii],"-z")) ifz_flag=1;
|
|
else argv[jj++] = argv[ii];
|
|
}
|
|
argc = jj;
|
|
|
|
if (argc < 2) {
|
|
printf ("Usage: hpasm options filename...\n");
|
|
return (-1);
|
|
}
|
|
|
|
start_output (argv[1]);
|
|
start_listing (argv[1]);
|
|
|
|
printf ("<< PASS 1 >>\n");
|
|
nbsyms=0;
|
|
err_count=0;
|
|
pass=1;
|
|
|
|
for (ii=1 ; ii < argc; ii++) {
|
|
f1 = fopen (argv[ii], "r");
|
|
if (!f1) {
|
|
printf ("File '%s' not found!\n\n", argv[ii]);
|
|
} else {
|
|
line_count=0;
|
|
printf ("%s ", argv[ii]);
|
|
fflush (stdout);
|
|
asm_pass (f1);
|
|
fclose (f1);
|
|
printf ("%d lines\n", line_count);
|
|
}
|
|
}
|
|
|
|
show_labels();
|
|
|
|
printf ("<< PASS 2 >>\n");
|
|
pass=2;
|
|
|
|
for (ii=1 ; ii < argc; ii++) {
|
|
f1 = fopen (argv[ii], "r");
|
|
if (!f1) {
|
|
printf ("File '%s' not found!\n\n", argv[ii]);
|
|
} else {
|
|
line_count=0;
|
|
printf ("%s ", argv[ii]);
|
|
fflush (stdout);
|
|
asm_pass (f1);
|
|
printf ("%d lines\n", line_count);
|
|
fclose (f1);
|
|
}
|
|
}
|
|
|
|
fprintf (listfile, "%ld ERRORS\n", err_count);
|
|
printf ("%ld ERRORS\n", err_count);
|
|
|
|
finish_output();
|
|
finish_listing();
|
|
|
|
return (0);
|
|
}
|
|
/****************************************************/
|