123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365 |
- /* assemble.c - main loop for assembler */
- #include "syshead.h"
- #include "const.h"
- #include "type.h"
- #include "address.h"
- #include "globvar.h"
- #include "opcode.h"
- #include "scan.h"
- PRIVATE bool_t nocolonlabel; /* set for labels not followed by ':' */
- PRIVATE void (*routine) P((void));
- #ifdef I80386
- PRIVATE opcode_t rep = 0; /* which rep/repne prefix was seen */
- #endif
- PRIVATE pfv rout_table[] =
- {
- pelse,
- pelseif,
- pelsifc,
- pendif,
- pif,
- pifc,
- /* start of non-conditionals */
- palign,
- pasciz,
- pblkw,
- pblock,
- pbss,
- pcomm,
- pcomm1,
- pdata,
- pendb,
- penter,
- pentry,
- pequ,
- peven,
- pexport,
- pfail,
- pfcb,
- pfcc,
- pfdb,
- #if SIZEOF_OFFSET_T > 2
- pfqb,
- #endif
- pget,
- pglobl,
- pident,
- pimport,
- plcomm,
- plcomm1,
- plist,
- ploc,
- pmaclist,
- pmacro,
- pmap,
- porg,
- pproceof,
- prmb,
- psect,
- pset,
- psetdp,
- ptext,
- #ifdef I80386
- puse16,
- puse32,
- #endif
- pwarn,
- /* end of pseudo-ops */
- #ifdef I80386
- mbcc,
- mbswap,
- mcall,
- mcalli,
- mdivmul,
- menter,
- mEwGw,
- mExGx,
- mf_inher,
- mf_m,
- mf_m2,
- mf_m2_ax,
- mf_m2_m4,
- mf_m2_m4_m8,
- mf_m4_m8_optst,
- mf_m4_m8_st,
- mf_m4_m8_stst,
- mf_m4_m8_m10_st,
- mf_m10,
- mf_optst,
- mf_st,
- mf_stst,
- mf_w_inher,
- mf_w_m,
- mf_w_m2,
- mf_w_m2_ax,
- mgroup1,
- mgroup2,
- mgroup6,
- mgroup7,
- mgroup8,
- mGvEv,
- mGvMa,
- mGvMp,
- mimul,
- min,
- mincdec,
- minher,
- minher16,
- minher32,
- minhera,
- mint,
- mjcc,
- mjcxz,
- mlea,
- mmov,
- mmovx,
- mnegnot,
- mout,
- mpushpop,
- mret,
- mseg,
- msetcc,
- mshdouble,
- mtest,
- mxchg,
- #endif /* I80386 */
- #ifdef MC6809
- mall, /* all address modes allowed, like LDA */
- malter, /* all but immediate, like STA */
- mimmed, /* immediate only (ANDCC, ORCC) */
- mindex, /* indexed (LEA's) */
- minher, /* inherent, like CLC or CLRA */
- mlong, /* long branches */
- mshort, /* short branches */
- msstak, /* S-stack (PSHS, PULS) */
- mswap, /* TFR, EXG */
- mustak, /* U-stack (PSHU,PULU) */
- #endif /* MC6809 */
- };
- FORWARD void asline P((void));
- /*
- This uses registers as follows: A is for work and is not preserved by
- the subroutines.B holds the last symbol code, X usually points to data
- about the last symbol, U usually holds the value of last expression
- or symbol, and Y points to the current char. The value in Y is needed
- by READCH and GETSYM. EXPRES needs B and Y, and returns a value in U.
- If the expression starts with an identifier, X must point to its string.
- LOOKUP needs a string pointer in X and length in A. It returns a table
- pointer in X (unless not assembling and not found), symbol type in A
- and overflow in CC.
- */
- PUBLIC void assemble()
- {
- while (TRUE)
- {
- asline();
- if (label != NUL_PTR) /* must be confirmed if still set */
- { /* it is nulled by EQU, COMM and SET */
- #ifndef MC6809
- #define NEEDENDLABEL ILLAB
- if (nocolonlabel)
- error(NEEDENDLABEL);
- #endif
- if(pass && label->value_reg_or_op.value != oldlabel)
- {
- dirty_pass = TRUE;
- if( pass == last_pass )
- error(UNSTABLE_LABEL);
- }
- label->type |= LABIT; /* confirm, perhaps redundant */
- if (label->type & REDBIT)
- {
- /* REDBIT meant 'GLOBLBIT' while LABIT was not set. */
- label->type |= EXPBIT;
- label->type &= ~REDBIT;
- }
- if ((mcount | popflags) == 0)
- /* unaccompanied label, display adr like EQU and SET */
- showlabel();
- label = NUL_PTR; /* reset for next line */
- }
- skipline();
- listline();
- genbin();
- genobj();
- binmbuf = lc += lcjump
- #ifdef I80386
- + immcount
- #endif
- ;
- }
- }
- PRIVATE void asline()
- {
- register struct sym_s *symptr;
- postb = popflags = pcrflag =
- #ifdef I80386
- sprefix = oprefix = aprefix =
- #endif
- immcount = lastexp.data = lcjump = 0;
- #ifdef I80386
- sib = NO_SIB;
- #endif
- #if SIZEOF_OFFSET_T > 2
- fqflag =
- #endif
- fdflag = fcflag = FALSE;
- cpuwarn();
- readline();
- getsym();
- if (sym != IDENT) /* expect label, mnemonic or macro */
- {
- /* Warn if not a comment marker or a hash (for /lib/cpp) */
- if( sym != EOLSYM && sym != IMMEDIATE )
- list_force = TRUE;
- return; /* anything else is a comment */
- }
- symptr = gsymptr;
- if (!ifflag)
- /* not assembling, just test for IF/ELSE/ELSEIF/ENDIF */
- {
- if (symptr == NUL_PTR || !(symptr->type & MNREGBIT) ||
- symptr->data & REGBIT ||
- symptr->value_reg_or_op.op.routine >= MIN_NONCOND)
- return;
- }
- else if (!(symptr->type & (MACBIT | MNREGBIT)))
- /* not macro, op, pseudo-op or register, expect label */
- {
- oldlabel = symptr->value_reg_or_op.value;
- if ((nocolonlabel = (*lineptr - ':')) == 0) /* exported label? */
- {
- sym = COLON;
- ++lineptr;
- }
- if (symptr->type & (LABIT | VARBIT))
- {
- if (symptr->type & REDBIT)
- labelerror(RELAB);
- label = symptr;
- if (pass && !(symptr->type & VARBIT) /*&& last_pass>1*/)
- {
- label->data = (label->data & FORBIT) | lcdata;
- label->value_reg_or_op.value = lc;
- }
- }
- else if (checksegrel(symptr))
- {
- symptr->type &= ~COMMBIT; /* ignore COMM, PCOMM gives warning */
- #ifdef MC6809
- #if 0
- if (sym == COLON)
- symptr->type |= EXPBIT;
- #endif
- #endif
- /* remember if forward referenced */
- symptr->data = (symptr->data & FORBIT) | lcdata;
- symptr->value_reg_or_op.value = lc;
- /* unless changed by EQU,COMM or SET */
- label = symptr;
- }
- getsym();
- if (sym != IDENT)
- {
- if (sym == EQOP)
- {
- getsym();
- pequ();
- }
- return; /* anything but ident is comment */
- }
- symptr = gsymptr;
- }
- if (symptr->type & MACBIT)
- {
- entermac(symptr);
- return;
- }
- if (!(symptr->type & MNREGBIT))
- {
- error(OPEXP);
- return;
- }
- if (symptr->data & REGBIT)
- {
- error(REGUID);
- return;
- }
- mnsize = 0;
- if ((page = (symptr->data & (PAGE1 | PAGE2))) != 0)
- {
- #ifdef MNSIZE
- if (page == (PAGE1 | PAGE2))
- {
- mnsize = 1;
- page = 0;
- }
- else
- #endif
- {
- #ifdef PAGE2_OPCODE
- if (page == PAGE2)
- page = PAGE2_OPCODE;
- else
- #endif
- page = PAGE1_OPCODE;
- mcount = 1;
- }
- }
- opcode = symptr->value_reg_or_op.op.opcode;
- #ifdef I80386
- needcpu((page==0 && ((opcode&0xF0) == 0x60||(opcode&0xF6)==0xC0))?1:0);
- #endif
- routine = rout_table[symptr->value_reg_or_op.op.routine];
- getsym();
- (*routine)();
- #ifdef I80386
- /* We handle "rep[ne]" refix as separate instruction; check if its use is valid */
- if (opcode == 0xF2 || opcode == 0xF3) { /* REP */
- rep = opcode;
- /* Not another prefix */
- } else if (opcode != 0x2E && /* CSEG */
- opcode != 0x3E && /* DSEG */
- opcode != 0x26 && /* ESEG */
- opcode != 0x64 && /* FSEG */
- opcode != 0x65 && /* GSEG */
- opcode != 0x36 && /* SSEG */
- opcode != 0xF0) { /* LOCK */
- if (rep == 0xF2 && (opcode&0xF6) != 0xA6) /* REPNE CMPS/SCAS */
- error (REPNE_STRING);
- if (rep == 0xF3 && !((opcode&0xFC) == 0x6C || /* REP INS/OUTS */
- (opcode&0xFC) == 0xA4 || /* REP MOVS/CMPS */
- (opcode&0xFC) == 0xAC || /* REP SCAS/LODS */
- (opcode&0xFE) == 0xAA)) /* REP STOS */
- error (REP_STRING);
- rep = 0;
- }
- #endif
- if (sym != EOLSYM)
- error(JUNK_AFTER_OPERANDS);
- #ifdef I80386
- needcpu(page==PAGE1_OPCODE?2:0);
- if (aprefix != 0)
- ++mcount;
- if (oprefix != 0)
- ++mcount;
- if (sprefix != 0)
- ++mcount;
- #endif
- }
|