+//
+// Make mark image for Alcyon .o file
+// okflag: 1, ok to deposit reloc information
+//
+uint32_t MarkImage(register uint8_t * mp, uint32_t siz, uint32_t tsize, int okflag)
+{
+ uint16_t from = 0; // Section fixups are currently FROM
+ uint32_t loc; // Location (temp)
+ uint32_t lastloc; // Last location fixed up (RELMOD)
+ uint8_t * wp; // Pointer into raw relocation information
+ register uint8_t * dp; // Deposit point for RELMOD information
+
+ if (okflag)
+ memset(mp, 0, siz); // zero relocation buffer
+
+ for(MCHUNK * mch=firstmch; mch!=NULL; mch=mch->mcnext)
+ {
+ for(PTR p=mch->mcptr;;)
+ {
+ uint16_t w = *p.wp++;// w = next mark entry
+
+ if (w & MCHEND) // (end of mark chunk)
+ break;
+
+ // Get mark record
+ SYM * symbol = NULL;
+ loc = *p.lp++; // mark location
+
+ if (w & MCHFROM) // maybe change "from" section
+ from = *p.wp++;
+
+ if (w & MSYMBOL) // maybe includes a symbol
+ symbol = *p.sy++;
+
+ // Compute mark position in relocation information; in RELMOD mode,
+ // get address of data to fix up.
+ if (from == DATA)
+ loc += tsize;
+
+ wp = (uint8_t *)(mp + loc);
+
+ if (okflag && (w & MLONG)) // indicate first word of long
+ {
+ wp[1] = 5;
+ wp += 2;
+ }
+
+ if (symbol)
+ {
+ // Deposit external reference
+ if (okflag)
+ {
+ if (w & MPCREL)
+ w = 6; // PC-relative fixup
+ else
+ w = 4; // Absolute fixup
+
+ w |= symbol->senv << 3;
+ *wp++ = w >> 8;
+ *wp = (uint8_t)w;
+ }
+ }
+ else
+ {
+ // Deposit section-relative mark; in RELMOD mode, fix it up in
+ // the chunk, kind of like a sleazoid linker.
+ //
+ // In RELMOD mode, marks to words (MWORDs) "cannot happen,"
+ // checks are made when mark() is called, so we don't have to
+ // check again here.
+ w &= TDB;
+
+ if (okflag)
+ wp[1] = mark_tr[w];
+ else if (prg_flag && (w & (DATA | BSS)))
+ {
+ uint32_t diff = GETBE32(wp, 0);
+#ifdef DO_DEBUG
+ DEBUG printf("diff=%lx ==> ", diff);
+#endif
+ diff += sect[TEXT].sloc;
+
+ if (w == BSS)
+ diff += sect[DATA].sloc;
+
+ SETBE32(wp, 0, diff)
+#ifdef DO_DEBUG
+ DEBUG printf("%lx\n", diff);
+#endif
+ }
+ }
+ }
+ }
+
+ // Generate ".PRG" relocation information in place in the relocation words
+ // (the "RELMOD" operation).
+ if (okflag && prg_flag)
+ {
+ int firstp = 1;
+ wp = dp = mp;
+
+ for(loc=0; loc<siz;)
+ {
+ if ((wp[1] & 7) == 5)
+ {
+ if (firstp)
+ {
+ SETBE32(dp, 0, loc);
+ dp += 4;
+ firstp = 0;
+ }
+ else
+ {
+ uint32_t diff;
+
+ for(diff=loc-lastloc; diff>254; diff-=254)
+ *dp++ = 1;
+
+ *dp++ = (uint8_t)diff;
+ }
+
+ lastloc = loc;
+ loc += 4;
+ wp += 4;
+ }
+ else
+ {
+ loc += 2;
+ wp += 2;
+ }
+ }
+
+ // Terminate relocation list with 0L (if there was no relocation) or
+ // 0.B (if relocation information was written).
+ if (!firstp)
+ *dp++ = 0;
+ else
+ for(firstp=0; firstp<4; firstp++)
+ *dp++ = 0;
+
+ // Return size of relocation information
+ loc = dp - mp;
+ return loc;
+ }
+
+ return siz;
+}
+
+