int a_type; /* Type */
VALUE a_value; /* Index offset, etc */
int a_segment; /* Segment relative to */
+ struct SYM *a_sym; /* Symbol tied to this address */
+ /* NULL indicates simple own segment */
} ADDR;
/*
int s_type; /* Type */
VALUE s_value; /* Value */
int s_segment; /* Segment this symbol is relative to */
+ uint16_t s_number; /* Symbol number 1..n */
} SYM;
/*
extern jmp_buf env;
extern VALUE dot[NSEGMENT];
extern int segment;
+extern int debug_write;
extern void asmline(void);
extern void asmld(void);
if ((sp->s_type&TMMODE) != TNEW
&& (sp->s_type&TMASG) == 0)
err('m');
- sp->s_type &= ~TMMODE;
+ sp->s_type &= ~(TMMODE|TPUBLIC);
sp->s_type |= TUSER|TMASG;
sp->s_value = a1.a_value;
sp->s_segment = a1.a_segment;
+ /* FIXME: review .equ to an external symbol/offset and
+ what should happen */
laddr = a1.a_value;
lmode = ALIST;
goto loop;
case TEXPORT:
getid(id, getnb());
- sp = lookup(id, phash, 1);
+ sp = lookup(id, uhash, 1);
sp->s_type |= TPUBLIC;
break;
/* .code etc */
absolute either way around produces a segment offset */
if ((left->a_segment == ABSOLUTE || right->a_segment == ABSOLUTE) &&
op == '+') {
+ if (left->a_sym)
+ right->a_sym = left->a_sym;
+ else if (right->a_sym)
+ left->a_sym = right->a_sym;
left->a_segment += right->a_segment;
return;
}
/* Subtraction within segment produces an absolute */
if (left->a_segment == right->a_segment && op == '-') {
left->a_segment = ABSOLUTE;
+ left->a_sym = NULL;
return;
}
+ left->a_sym = NULL;
aerr();
}
ap->a_value = 0;
return;
}
- if (mode == TNEW)
+ /* An external symbol has to be tracked and output in
+ the relocations. Any known internal symbol is just
+ encoded as a relocation relative to a segment */
+ if (mode == TNEW) {
uerr(id);
+ ap->a_sym = sp;
+ } else
+ ap->a_sym = NULL;
ap->a_type = TUSER;
ap->a_value = sp->s_value;
ap->a_segment = sp->s_segment;
{
if (a->a_segment != ABSOLUTE) {
/* FIXME@ handle symbols */
- if (segment == BSS && a->a_value)
+ if (segment == BSS)
err('b');
- outbyte(REL_ESC);
- outbyte((2 << 4) | REL_SIMPLE | a->a_segment);
+ if (a->a_sym == NULL) {
+ outbyte(REL_ESC);
+ outbyte((1 << 4) | REL_SIMPLE | a->a_segment);
+ } else {
+ outbyte(REL_ESC);
+ outbyte((1 << 4 ) | REL_SYMBOL);
+ outbyte(a->a_sym->s_number & 0xFF);
+ outbyte(a->a_sym->s_number >> 8);
+ }
}
outaw(a->a_value);
}
void outrab(ADDR *a)
{
/* FIXME: handle symbols */
- if (segment == BSS && a->a_value) {
- err('b');
- outbyte(REL_ESC);
- outbyte((2 << 4) | REL_SIMPLE | a->a_segment);
+ if (a->a_segment != ABSOLUTE) {
+ if (segment == BSS)
+ err('b');
+ if (a->a_sym == NULL) {
+ outbyte(REL_ESC);
+ outbyte((0 << 4) | REL_SIMPLE | a->a_segment);
+ } else {
+ outbyte(REL_ESC);
+ outbyte((0 << 4 ) | REL_SYMBOL);
+ outbyte(a->a_sym->s_number & 0xFF);
+ outbyte(a->a_sym->s_number >> 8);
+ }
}
outab(a->a_value);
}
+static void putsymbol(SYM *s, FILE *ofp)
+{
+ int i;
+ uint8_t flag = 0;
+ printf("Putsymbol %s\n", s->s_id);
+ if (s->s_type == TNEW)
+ flag |= S_UNKNOWN;
+ else {
+ if (s->s_type & TPUBLIC)
+ flag |= S_PUBLIC;
+ flag |= s->s_segment;
+ }
+ putc(flag, ofp);
+ putc(s->s_number, ofp);
+ putc(s->s_number >> 8, ofp);
+ for (i = 0; i < 16; i++) {
+ putc(s->s_id[i], ofp);
+ if (!s->s_id[i])
+ break;
+ }
+ if (!(flag & S_UNKNOWN)) {
+ putc(s->s_value, ofp);
+ putc(s->s_value >> 8, ofp);
+ }
+}
+
+static void writesymbols(SYM *hash[], FILE *ofp, int flag)
+{
+ int i;
+ fseek(ofp, obh.o_symbase, SEEK_SET);
+ for (i = 0; i < NHASH; i++) {
+ SYM *s;
+ for (s = hash[i]; s != NULL; s = s->s_fp) {
+ int t = s->s_type & TMMODE;
+ int n;
+ if (t != TUSER && t != TNEW)
+ continue;
+ n = (t == TNEW) || (t == TUSER && (s->s_type & TPUBLIC));
+ if (n == flag)
+ putsymbol(s, ofp);
+ }
+ }
+}
+
/*
* Put out the end of file
* hex item at the very end of
*/
void outeof(void)
{
+ writesymbols(phash, ofp, 1);
+ writesymbols(uhash, ofp, 1);
+ if (debug_write) {
+ obh.o_dbgbase = ftell(ofp);
+ writesymbols(phash, ofp, 0);
+ writesymbols(uhash, ofp, 0);
+ }
rewind(ofp);
obh.o_magic = MAGIC_OBJ;
fwrite(&obh, sizeof(obh), 1, ofp);