summaryrefslogtreecommitdiff
path: root/bcc/label.c
diff options
context:
space:
mode:
Diffstat (limited to 'bcc/label.c')
-rw-r--r--bcc/label.c429
1 files changed, 429 insertions, 0 deletions
diff --git a/bcc/label.c b/bcc/label.c
new file mode 100644
index 0000000..5b07af9
--- /dev/null
+++ b/bcc/label.c
@@ -0,0 +1,429 @@
+/* label.c - label handling routines for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "condcode.h"
+#include "gencode.h"
+#include "label.h"
+#include "output.h"
+#include "sc.h"
+#include "scan.h"
+#include "sizes.h"
+#include "type.h"
+
+#ifdef I8088
+# define outlbranch() outop3str( "b")
+# define outsbranch() outop2str( "j")
+#endif
+#ifdef MC6809
+# define outlbranch() outop3str( "LB")
+# define outsbranch() outop2str( "B")
+#endif
+
+#define MAXVISLAB 32
+
+struct labdatstruct
+{
+ label_t labnum; /* 0 if not active */
+ offset_t lablc; /* location counter for branch or label */
+ char *labpatch; /* buffer ptr for branch, NULL for label */
+ ccode_t labcond; /* condition code for branch */
+};
+
+#ifdef I8088
+PRIVATE char lcondnames[][2] = /* names of long condition codes */
+{
+ { 'e', 'q', }, { 'n', 'e', }, { 'r', ' ', }, { 'r', 'n', },
+ { 'l', 't', }, { 'g', 'e', }, { 'l', 'e', }, { 'g', 't', },
+ { 'l', 'o', }, { 'h', 'i', }, { 'l', 'o', }, { 'h', 'i' },
+};
+PRIVATE char scondnames[][2] = /* names of short condition codes */
+{
+ { 'e', ' ', }, { 'n', 'e', }, { 'm', 'p', }, { 'n', 0, },
+ { 'l', ' ', }, { 'g', 'e', }, { 'l', 'e', }, { 'g', ' ', },
+ { 'b', ' ', }, { 'a', 'e', }, { 'b', 'e', }, { 'a', ' ', },
+};
+#endif
+
+#ifdef MC6809
+PRIVATE char condnames[][2] = /* names of condition codes */
+{
+ { 'E', 'Q', }, { 'N', 'E', }, { 'R', 'A', }, { 'R', 'N', },
+ { 'L', 'T', }, { 'G', 'E', }, { 'L', 'E', }, { 'G', 'T', },
+ { 'L', 'O', }, { 'H', 'S', }, { 'L', 'S', }, { 'H', 'I', },
+};
+#endif
+
+PRIVATE label_t lasthighlab = 0xFFFF+1; /* temp & temp init so labels fixed */
+ /* lint */
+PRIVATE label_t lastlab; /* bss init to 0 */
+PRIVATE offset_t lc; /* bss init to 0 */
+
+PRIVATE struct labdatstruct vislab[MAXVISLAB]; /* bss, all labnum's init 0 */
+PRIVATE smalin_t nextvislab; /* bss init to NULL */
+PRIVATE struct symstruct *namedfirst; /* bss init to NULL */
+PRIVATE struct symstruct *namedlast; /* bss init to NULL */
+
+FORWARD void addlabel P((ccode_pt cond, label_t label, char *patch));
+FORWARD struct labdatstruct *findlabel P((label_t label));
+
+/* add label to circular list */
+
+PRIVATE void addlabel(cond, label, patch)
+ccode_pt cond;
+label_t label;
+char *patch;
+{
+ register struct labdatstruct *labptr;
+
+ labptr = &vislab[(int)nextvislab];
+ labptr->labcond = cond;
+ labptr->labnum = label;
+ labptr->lablc = lc;
+ labptr->labpatch = patch;
+ if (++nextvislab == MAXVISLAB)
+ nextvislab = 0;
+}
+
+/* bump location counter */
+
+PUBLIC void bumplc()
+{
+ ++lc;
+}
+
+/* bump location counter by 2 */
+
+PUBLIC void bumplc2()
+{
+ lc += 2;
+}
+
+/* bump location counter by 3 */
+
+PUBLIC void bumplc3()
+{
+ lc += 3;
+}
+
+/* clear out labels in function */
+
+PUBLIC void clearfunclabels()
+{
+ register struct symstruct *symptr;
+ register struct symstruct *tmp;
+
+ for (symptr = namedfirst; symptr != NULL;)
+ {
+ if (symptr->indcount == 2)
+ error("undefined label");
+ symptr->indcount = 0;
+ tmp = symptr;
+ symptr = (struct symstruct *) symptr->type;
+ tmp->type = NULL;
+ }
+ namedlast = namedfirst = NULL;
+}
+
+/* clear out labels no longer in buffer */
+
+PUBLIC void clearlabels(patchbuf, patchtop)
+char *patchbuf;
+char *patchtop;
+{
+ register struct labdatstruct *labptr;
+ struct labdatstruct *labtop;
+ register char *labpatch;
+
+ for (labptr = &vislab[0], labtop = &vislab[MAXVISLAB];
+ labptr < labtop; ++labptr)
+ if ((labpatch = labptr->labpatch) >= patchbuf && labpatch < patchtop)
+ labptr->labnum = 0;
+}
+
+/* clear out labels in switch statement */
+
+PUBLIC void clearswitchlabels()
+{
+ register struct symstruct *symptr;
+
+ for (symptr = namedfirst; symptr != NULL;
+ symptr = (struct symstruct *) symptr->type)
+ if (symptr->indcount == 3)
+ {
+ equlab(symptr->offset.offlabel, lowsp);
+ symptr->indcount = 4;
+ }
+}
+
+/* return location counter */
+
+PUBLIC uoffset_t getlc()
+{
+ return (uoffset_t) lc;
+}
+
+/* define location of label and backpatch references to it */
+
+PUBLIC void deflabel(label)
+label_t label;
+{
+ char *cnameptr;
+ struct labdatstruct *labmin;
+ struct labdatstruct *labmax;
+ struct labdatstruct *labmid;
+ struct labdatstruct *labptrsave;
+ offset_t nlonger;
+
+ outnlabel(label);
+ {
+ register struct labdatstruct *labptr;
+ register char *labpatch;
+
+ labmin = &vislab[0];
+ labmax = &vislab[MAXVISLAB];
+ labptr = labmid = &vislab[(int)nextvislab];
+ if (!watchlc)
+ do
+ {
+ if (labptr == labmin)
+ labptr = &vislab[MAXVISLAB];
+ --labptr;
+ if (labptr->labnum == label)
+ {
+ if ((labpatch = labptr->labpatch) != NULL &&
+ isshortbranch(lc - labptr->lablc))
+ {
+#ifdef I8088 /* patch "bcc(c) to j(c)(c)( ) */
+ *labpatch = 'j';
+ *(labpatch + 1) =
+ *(cnameptr = scondnames[(int)labptr->labcond]);
+#endif
+#ifdef MC6809
+# ifdef NEW_MC6809 /* patch JMP\t> or LBCC\t to BCC \t */
+ *labpatch = 'B';
+ *(labpatch + 4) = '\t'; /* redundant unless JMP */
+ *(labpatch + 1) =
+ *(cnameptr = condnames[labptr->labcond]);
+# else
+ if (labptr->labcond == RA)
+ strncpy(labpatch, "BRA\t\t", 5);
+ else
+ *labpatch = '\t';
+ goto over;
+# endif
+#endif
+ *(labpatch + 2) = *(cnameptr + 1);
+ *(labpatch + 3) = ' ';
+#ifdef MC6809
+# ifndef NEW_MC6809 /* patch JMP\t> or LBCC\t to BCC \t */
+ over: ; /* temp regression test kludge */
+# endif
+#endif
+ nlonger = jcclonger;
+ if (labptr->labcond == RA)
+ nlonger = jmplonger;
+ lc -= nlonger;
+ labptrsave = labptr;
+ while (++labptr != labmid)
+ if (labptr == labmax)
+ labptr = &vislab[-1];
+ else
+ labptr->lablc -= nlonger;
+ labptr = labptrsave;
+ }
+ }
+ }
+ while (labptr != labmid);
+ }
+ addlabel((ccode_pt) 0, label, (char *) NULL);
+}
+
+PRIVATE struct labdatstruct *findlabel(label)
+label_t label;
+{
+ register struct labdatstruct *labptr;
+ struct labdatstruct *labtop;
+
+ for (labptr = &vislab[0], labtop = &vislab[MAXVISLAB];
+ labptr < labtop; ++labptr)
+ if (labptr->labnum == label)
+ {
+ if (labptr->labpatch != 0)
+ break;
+ return labptr;
+ }
+ return (struct labdatstruct *) NULL;
+}
+
+/* reserve a new label, from top down to temp avoid renumbering low labels */
+
+PUBLIC label_t gethighlabel()
+{
+ return --lasthighlab;
+}
+
+/* reserve a new label */
+
+PUBLIC label_t getlabel()
+{
+ return ++lastlab;
+}
+
+/* jump to label */
+
+PUBLIC void jump(label)
+label_t label;
+{
+ lbranch(RA, label);
+}
+
+/* long branch on condition to label */
+
+PUBLIC void lbranch(cond, label)
+ccode_pt cond;
+label_t label;
+{
+#ifdef I8088
+ char *cnameptr;
+
+#endif
+ struct labdatstruct *labptr;
+ char *oldoutptr;
+
+ if ((ccode_t) cond == RN)
+ return;
+ if ((labptr = findlabel(label)) != NULL &&
+ isshortbranch(lc - labptr->lablc + 2))
+ {
+ sbranch(cond, label);
+ return;
+ }
+ oldoutptr = outbufptr;
+ if (cond == RA)
+ outjumpstring();
+ else
+ {
+ outlbranch();
+#ifdef I8088
+ outbyte(*(cnameptr = lcondnames[(int) cond]));
+ outbyte(*(cnameptr + 1));
+ if ((ccode_t) cond == LS || (ccode_t) cond == HS)
+ outbyte('s'); /* "blos" or "bhis" */
+ else
+ outbyte(' ');
+ outtab();
+ bumplc2();
+ if (i386_32)
+ bumplc();
+#endif
+#ifdef MC6809
+ outcond(cond);
+ bumplc();
+#endif
+ }
+ outlabel(label);
+ outnl();
+ if (labptr == NULL && oldoutptr < outbufptr) /* no wrap-around */
+ addlabel(cond, label, oldoutptr);
+}
+
+/* look up the name gsname in label space, install it if new */
+
+PUBLIC struct symstruct *namedlabel()
+{
+ struct symstruct *symptr;
+
+ gs2name[1] = 0xFF;
+ if ((symptr = findlorg(gs2name + 1)) == NULL)
+ {
+ symptr = addglb(gs2name + 1, vtype);
+ symptr->flags = LABELLED;
+ }
+ if (symptr->indcount < 2)
+ {
+ symptr->indcount = 2;
+ symptr->offset.offlabel = gethighlabel();
+ if (namedfirst == NULL)
+ namedfirst = symptr;
+ else
+ namedlast->type = (struct typestruct *) symptr;
+ namedlast = symptr;
+ symptr->type = NULL;
+ }
+ return symptr;
+}
+
+#ifdef MC6809
+
+/* print condition code name */
+
+PUBLIC void outcond(cond)
+ccode_pt cond;
+{
+ char *cnameptr;
+
+ outbyte(*(cnameptr = condnames[(ccode_t) cond]));
+ outbyte(*(cnameptr + 1));
+ outtab();
+}
+
+#endif
+
+/* print label */
+
+PUBLIC void outlabel(label)
+label_t label;
+{
+ outbyte(LABELSTARTCHAR);
+ outhexdigs((uoffset_t) label);
+}
+
+/* print label and newline */
+
+PUBLIC void outnlabel(label)
+label_t label;
+{
+ outlabel(label);
+#ifdef LABELENDCHAR
+ outnbyte(LABELENDCHAR);
+#else
+ outnl();
+#endif
+}
+
+/* short branch on condition to label */
+
+PUBLIC void sbranch(cond, label)
+ccode_pt cond;
+label_t label;
+{
+#ifdef I8088
+ char *cnameptr;
+
+ if ((ccode_t) cond != RN)
+ {
+ outsbranch();
+ outbyte(*(cnameptr = scondnames[(int) cond]));
+ outbyte(*(cnameptr + 1));
+ outtab();
+ outlabel(label);
+ outnl();
+ }
+#endif
+#ifdef MC6809
+ outsbranch();
+ outcond(cond);
+ outlabel(label);
+ outnl();
+#endif
+}
+
+/* reverse bump location counter */
+
+PUBLIC void unbumplc()
+{
+ --lc;
+}