Interdata_v6/usr/source/as/as3.c
/*
* Assembler pseudo-op processing
*
*
* Copyright (C) 1978, Richard Miller
*/
#define EXTERN extern
#include "as.h"
/*
* Ignored opcode
*/
donull()
{
nexttoken = EOL;
}
/*
* Illegal opcode
*/
dobad()
{
xerror(errc);
}
/*
* Data definition pseudo-ops
*/
#define DB 0
#define DC 1
#define DAC 2
#define DCF 3
#define DCX 4
#define DCY 5
#define DCZ 6
dodata(op)
{
register t;
dcflag = 1; /* a()-type constants are legal */
switch (op) {
case DC:
case DCX:
case DCZ:
align(2);
break;
case DAC:
case DCF:
case DCY:
align(4);
break;
case DB:
/*
* Stupid special case:
* "DB *" is equivalent to "ALIGN 2"
*/
if ((t = token()) == STAR && eol()) {
label();
align(2);
return;
}
nexttoken = t;
}
label();
do switch (op) {
/*
* fullword or halfword constant
*/
case DC:
case DAC:
case DCF:
case DCZ:
if ((t = token()) == STRING)
puts((strlen+01)&~01);
else {
nexttoken = t;
expr();
/*
* relocate
*/
switch (exp.rel) {
case RBSS:
exp.val += hdr.dsize;
case RDATA:
exp.val += hdr.tsize;
}
if (exp.half || op == DCZ) {
if (passg && (exp.val < 0xffff8000
|| exp.val > 0xffff))
error(errh);
puth(exp.val, exp.rel);
} else
putw(exp.val, exp.rel);
}
continue;
/*
* Hex constant
*/
case DCX:
t = getnum(16);
if (t < 0xffff8000 || t > 0xffff)
error(errh);
puth(t, RABS);
continue;
case DCY:
t = getnum(16);
putw(t, RABS);
continue;
/*
* Byte constant
*/
case DB:
if ((t = token()) == STRING && strlen > 1) {
puts(strlen);
continue;
}
nexttoken = t;
t = expr();
if (passg)
if (t != RABS
|| exp.val < -127 || exp.val > 255)
error(errv);
putb(exp.val);
if (passl)
lstb(exp.val);
continue;
}
while ((t = token()) == COMMA);
nexttoken = t;
}
/*
* Location counter pseudo-ops
*/
#define IMPURE 0
#define PURE 1
#define ALIGN 2
#define DS 3
#define DSF 4
#define ORG 5
#define COMN 6
#define STRUC 7
#define ENDS 8
#define BSS 9
#define BDATA 10
#define BORG 11
#define DSH 12
#define DLIST 13
#define CNOP 14
#define NOPR 0x0200 /* NO-OP instruction */
doloc(op)
{
static struct segment *saveseg; /* previous segment (while in
a STRUC or COMN */
static int saverel; /* previous relocatability */
register t;
register struct symbol *blk;
switch (op) {
case IMPURE:
label();
curseg = &impure;
currel = RDATA;
align(2);
nexttoken = EOL;
break;
case PURE:
label();
curseg = &pure;
currel = RTEXT;
align(2);
nexttoken = EOL;
break;
case BSS:
label();
curseg = &bss;
currel = RBSS;
align(2);
nexttoken = EOL;
break;
case ALIGN:
case CNOP:
if (expr() != RABS)
xerror(erra);
if ((t = exp.val) != 2 && t != 4 && t != 8)
t = 4;
if (op == ALIGN) {
align(t);
label();
break;
}
align(2);
label();
while (curseg->loc & (t-1))
puth(NOPR, RABS);
break;
case DSF:
align(4);
case DSH:
align(2);
case DS:
label();
if (expr() != RABS)
xerror(erra);
if ((t = exp.val) < 0) {
t = 0;
error(errv);
}
if (op == DSF)
t *= 4;
else if (op == DSH)
t *= 2;
org(curseg->loc + t);
break;
case DLIST:
if (expr() != RABS)
error(erra);
if ((t = exp.val) < 0) {
t = 0;
error(errv);
}
align(4);
label();
puth(t, RABS);
puth(0, RABS);
putw(0, RABS);
org(curseg->loc + t*4);
break;
case ORG:
label();
switch (t = expr()) {
case RTEXT:
curseg = &pure;
break;
default:
if (t == currel)
break;
error(errr);
t = RDATA;
case RDATA:
curseg = &impure;
break;
}
currel = t;
org(exp.val);
break;
case COMN:
if (curcomm)
xerror(erri);
if (!curlab)
xerror(errl);
curcomm = curlab;
if ((t = curlab->type&SSEG) != SUNDEF &&
(t != SDATA || (bdata && pass == 0)))
error(errm);
curlab->type = SEXT | (bdata? SUNDEF : t);
saverel = currel;
saveseg = curseg;
currel = REXT | ((curlab-usymtab)<<4);
curseg = &comm;
nexttoken = EOL;
break;
case STRUC:
if (curcomm)
error(erri);
if (curlab) {
curcomm = curlab;
deflab(RABS, 0, 0);
}
else
curcomm = -1;
saverel = currel;
saveseg = curseg;
currel = RABS;
curseg = &comm;
nexttoken = EOL;
break;
case ENDS:
if (!curcomm)
xerror(erri);
if (comm.loc > comm.maxloc)
comm.maxloc = comm.loc;
if ((currel != RABS && curcomm->type == (SEXT|SUNDEF))
|| (currel == RABS && curcomm != -1))
curcomm->value = comm.maxloc;
/*
* Block Data program: change common to data
*/
if (bdata && currel != RABS) {
curseg = &impure;
currel = RDATA;
curcomm->type = SDATA | SEXT;
curcomm->value = impure.loc;
org(impure.loc + comm.maxloc);
}
currel = saverel;
curseg = saveseg;
curcomm = 0;
comm.loc = comm.maxloc = 0;
nexttoken = EOL;
break;
case BDATA:
bdata++;
mflag++; /* allow redefinitions in Fortran blkdata */
nexttoken = EOL;
break;
case BORG:
if (token() != SYMBOL)
xerror(errs);
blk = cursym;
if (token() != LPAREN)
xerror(errs);
if (blk->type != (SDATA|SEXT))
xerror(errr);
switch (t = expr()&RSEG) {
case RABS:
case REXT:
t = blk->value;
break;
case RDATA:
t = 0;
break;
default:
xerror(errr);
}
if (token() != RPAREN)
xerror(errx);
currel = RDATA;
curseg = &impure;
org(t + exp.val);
break;
}
}
/*
* Other pseudo-ops
*/
#define EQU 0
#define EXTRN 1
#define ENTRY 2
#define DO 3
#define SQUEZ 4
#define NOSQZ 5
#define NORX3 6
dopseud(op)
{
register t;
register t1, t2;
switch(op) {
/*
* EQUate
*/
case EQU:
if (!curlab) {
xerror(errl);
}
expr();
deflab(exp.rel, exp.val, mflag);
if (passl)
lstaddr(exp.val, exp.rel);
break;
case EXTRN:
case ENTRY:
do {
if (!getsym())
xerror(errs);
else
if (symlook(1))
cursym->type |= SEXT;
} while ((t = token()) == COMMA);
nexttoken = t;
break;
case DO:
label();
docount = 0;
if (expr() != RABS)
error(erra);
if ((t = exp.val) < 0)
t = 0;
if (!getline())
xerror(erre);
docount = t;
break;
case SQUEZ:
opt = 1;
break;
case NOSQZ:
opt = 0;
break;
case NORX3:
opt = -1;
break;
}
}
/*
* Conditional assembly pseudo-ops
*/
#define IFZ 0
#define IFNZ 1
#define IFP 2
#define IFNP 3
#define IFM 4
#define IFNM 5
#define IFE 6
#define IFO 7
#define IFU 8
#define IFD 9
#define IFCOND 9 /* last compound if */
#define ELSE 10
#define ENDC 11
#define IF 12
#define END 13
docond(op)
{
register v, cond;
label();
/*
* Compound IF statements
*/
if (op <= IFCOND) {
/* Evaluate expression -- must be previously defined */
if (op < IFU) {
if (expr() == RUNDEF)
error(erru);
v = exp.val;
} else
if (!getsym())
error(errs);
else
v = symlook(1);
/* Evaluate condition */
switch (op) {
case IFU:
case IFZ: cond = (v == 0); break;
case IFD:
case IFNZ: cond = (v != 0); break;
case IFP: cond = (v > 0); break;
case IFNP: cond = (v <= 0); break;
case IFM: cond = (v < 0); break;
case IFNM: cond = (v >= 0); break;
case IFE: cond = !(v & 01); break;
case IFO: cond = (v & 01); break;
}
/* Adjust conditional assembly & nesting level */
if (!cond || ifcount)
ifcount++;
ifnest++;
return;
}
/*
* Other compound conditionals
*/
if (op != IF)
nexttoken = EOL;
switch (op) {
case ELSE:
if (!ifnest)
error(erri);
if (ifcount <= 1)
ifcount = 1-ifcount;
break;
case ENDC:
if (!ifnest)
error(erri);
if (ifcount)
ifcount--;
ifnest--;
break;
/*
* Simple IF
*/
case IF:
if (expr() == RUNDEF)
error(erru);
noasm = !(exp.val);
break;
/*
* END statement - set switch for assemble()
*/
case END:
endswitch = 1;
break;
}
}