2 // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
3 // MARK.C - A record of things that are defined relative to any of the sections
4 // Copyright (C) 199x Landon Dyer, 2011-2012 Reboot and Friends
5 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
6 // Source utilised with the kind permission of Landon Dyer
15 MCHUNK * firstmch; // First mark chunk
16 MCHUNK * curmch; // Current mark chunk
17 PTR markptr; // Deposit point in current mark chunk
18 LONG mcalloc; // #bytes alloc'd to current mark chunk
19 LONG mcused; // #bytes used in current mark chunk
20 uint16_t curfrom; // Current "from" section
21 LONG markimg(register char * mp, LONG siz, LONG tsize, int okflag);
26 extern int prg_flag; // 1, write ".PRG" relocatable executable
28 //#define DEBUG_IMAGE_MARKING
36 firstmch = curmch = NULL;
43 // Wrap up marker (called after final mark is made)
49 *markptr.wp = MCHEND; // Mark end of block
50 curmch->mcused = mcused; // Update #used in mark block
56 // Mark a word or longword relocatable
58 int rmark(uint16_t from, uint32_t loc, uint16_t to, uint16_t size, SYM * symbol)
60 #ifdef DEBUG_IMAGE_MARKING
61 printf("rmark: from=%i, loc=$%X, to=$%X, size=$%x, symbol=$%X\n", from, loc, to, size, symbol);
63 printf(" symbol->stype=$%02X, sattr=$%04X, sattre=$%08X, svalue=%i, sname=%s\n", symbol->stype, symbol->sattr, symbol->sattre, symbol->svalue, symbol->sname);
66 if ((mcalloc - mcused) < MIN_MARK_MEM)
69 uint16_t flags = (size | to);
78 // Complain about some things are not allowed in `-p' mode:
79 // o marks that aren't to LONGs;
80 // o external references.
84 if ((flags & MLONG) == 0)
85 error("illegal word relocatable (in .PRG mode)");
88 errors("illegal external reference (in .PRG mode) to '%s'",
92 mcused += sizeof(WORD) + sizeof(LONG);
93 *markptr.wp++ = flags;
100 mcused += sizeof(WORD);
105 *markptr.sy++ = symbol;
106 mcused += sizeof(SYM *);
109 *markptr.wp = 0x0000;
116 // Allocate another chunk of mark space
122 // Alloc mark block header (and data) and set it up.
123 // p = (MCHUNK *)amem((long)(sizeof(MCHUNK)) + MARK_ALLOC_INCR);
124 MCHUNK * p = (MCHUNK *)malloc(sizeof(MCHUNK) + MARK_ALLOC_INCR);
126 p->mcalloc = MARK_ALLOC_INCR;
127 p->mcptr.cp = (char *)(((char *)p) + sizeof(MCHUNK));
131 // Link onto previous chunk
132 *markptr.wp++ = MCHEND; // Mark end of block
133 curmch->mcused = mcused;
140 curmch = p; // Setup global vars
142 mcalloc = MARK_ALLOC_INCR;
150 * Table to convert from TDB to fixup triad
153 static char mark_tr[] = {
155 2, /* TEXT relocatable */
156 1, 0, /* DATA relocatable */
157 3 /* BSS relocatable */
162 * Make mark image for Alcyon .o file
163 * okflag -- 1, ok to deposit reloc information
165 LONG markimg(register char * mp, LONG siz, LONG tsize, int okflag)
167 MCHUNK * mch; /* -> mark chunk */
168 register PTR p; /* source point from within mark chunk */
169 WORD from; /* section fixups are currently FROM */
170 register WORD w; /* a word (temp) */
171 LONG loc; /* location (temp) */
172 LONG lastloc; /* last location fixed up (RELMOD) */
173 SYM * symbol; /* -> symbols (temp) */
174 char * wp; /* pointer into raw relocation information */
175 register char * dp; /* deposit point for RELMOD information */
176 int firstp; /* 1, first relocation (RELMOD) */
177 LONG diff; /* difference to relocate (RELMOD) */
180 //clear(mp, siz); /* zero relocation buffer */
181 memset(mp, 0, siz); /* zero relocation buffer */
185 for(mch=firstmch; mch!=NULL; mch=mch->mcnext)
189 w = *p.wp++; /* w = next mark entry */
191 if (w & MCHEND) /* (end of mark chunk) */
198 loc = *p.lp++; /* mark location */
200 if (w & MCHFROM) /* maybe change "from" section */
203 if (w & MSYMBOL) /* maybe includes a symbol */
207 * Compute mark position in relocation information;
208 * in RELMOD mode, get address of data to fix up.
213 wp = (char *)(mp + loc);
215 if (okflag && (w & MLONG)) /* indicate first word of long */
224 * Deposit external reference
229 w = 6; /* pc-relative fixup */
231 w = 4; /* absolute fixup */
233 w |= symbol->senv << 3;
241 * Deposit section-relative mark;
242 * in RELMOD mode, fix it up in the chunk,
243 * kind of like a sleazoid linker.
245 * In RELMOD mode, marks to words (MWORDs) "cannot happen,"
246 * checks are made when mark() is called, so we don't have
247 * to check again here.
253 else if (prg_flag && (w & (DATA | BSS)))
256 diff = ((LONG)(*dp++ & 0xff)) << 24;
257 diff |= ((LONG)(*dp++ & 0xff)) << 16;
258 diff |= ((LONG)(*dp++ & 0xff)) << 8;
259 diff |= (LONG)(*dp & 0xff);
262 DEBUG printf("diff=%lx ==> ", diff);
264 diff += sect[TEXT].sloc;
267 diff += sect[DATA].sloc;
270 *dp++ = (char)(diff >> 24);
271 *dp++ = (char)(diff >> 16);
272 *dp++ = (char)(diff >> 8);
275 DEBUG printf("%lx\n", diff);
283 * Generate ".PRG" relocation information in place in
284 * the relocation words (the ``RELMOD'' operation).
286 if (okflag && prg_flag)
294 if ((wp[1] & 7) == 5)
298 *dp++ = (char)(loc >> 24);
299 *dp++ = (char)(loc >> 16);
300 *dp++ = (char)(loc >> 8);
306 for(diff=loc-lastloc; diff>254; diff-= 254)
324 * Terminate relocation list with 0L (if there was no
325 * relocation) or 0.B (if relocation information was
330 else for (firstp = 0; firstp < 4; ++firstp)
334 * Return size of relocation information
345 // Make mark image for BSD .o file
347 uint32_t bsdmarkimg(char * mp, LONG siz, LONG tsize, int reqseg)
349 MCHUNK * mch; // Mark chunk
350 PTR p; // Source point from within mark chunk
351 uint16_t from; // Section fixups are currently FROM
352 uint16_t w; // A word (temp)
353 uint32_t loc; // Location (temp)
354 SYM * symbol; // Symbols (temp)
355 uint8_t * wp; // Pointer into raw relocation info
356 uint8_t * dp; // Deposit point for RELMOD info
357 uint32_t diff; // Difference to relocate (RELMOD)
358 uint32_t raddr, rflag = 0; // BSD relocation address and flags
359 uint32_t rsize; // Relocation size
360 int validsegment = 0; // Valid segment being processed
362 #ifdef DEBUG_IMAGE_MARKING
363 printf("bsdmarkimg():\n");
365 // Initialise relocation size
370 for(mch=firstmch; mch!=NULL; mch=mch->mcnext)
374 w = *p.wp++; // Next mark entry
377 break; // End of mark chunk
381 loc = *p.lp++; // Mark location
385 // Maybe change "from" section
388 if (obj_format == BSD)
392 // Requested segment is TEXT
400 // Requested segment is DATA
409 if (w & MSYMBOL) // Maybe includes a symbol
412 if (obj_format == BSD)
414 raddr = loc; // Set relocation address
417 #ifdef DEBUG_IMAGE_MARKING
419 printf(" validsegment: raddr = $%08X\n", raddr);
421 D_long(raddr); // Write relocation address
422 #ifdef DEBUG_IMAGE_MARKING
427 rflag = 0x000000A0; // PC-relative fixup
429 rflag = 0x00000040; // Absolute fixup
431 // This flag tells the linker to WORD swap the LONG when doing the fixup.
434 //printf("bsdmarkimg: ORing $01 to rflag (MMOVEI) [symbol=%s]...\n", symbol->sname);
439 // Compute mark position in relocation information;
440 // in RELMOD mode, get address of data to fix up.
444 wp = (uint8_t *)(mp + loc);
448 // Deposit external reference
449 if (obj_format == BSD)
451 rflag |= 0x00000010; // Set external reloc flag bit
452 rflag |= (symbol->senv << 8); // Put symbol index in flags
454 // Looks like this is completely unnecessary (considering it does the wrong thing!)
456 if (symbol->sattre & RISCSYM)
458 printf("bsdmarkimg: ORing $01 to rflag (RISCSYM) [symbol=%s]...\n", symbol->sname);
465 #ifdef DEBUG_IMAGE_MARKING
466 printf(" validsegment(2): rflag = $%08X\n", rflag);
468 D_long(rflag); // Write relocation flags
469 rsize += 8; // Increment relocation size
475 if (obj_format == BSD)
477 #ifdef DEBUG_IMAGE_MARKING
478 printf(" w = $%04X\n", w);
480 w &= TDB; // Set reloc flags to segment
484 case TEXT: rflag |= 0x00000400; break;
485 case DATA: rflag |= 0x00000600; break;
486 case BSS: rflag |= 0x00000800; break;
491 #ifdef DEBUG_IMAGE_MARKING
492 printf(" validsegment(3): rflag = $%08X\n", rflag);
494 D_long(rflag); // Write relocation flags
495 rsize += 8; // Increment relocation size
504 dp = objImage + BSDHDRSIZE + loc;
505 diff = ((LONG)(*dp++ & 0xFF)) << 24;
506 diff |= ((LONG)(*dp++ & 0xFF)) << 16;
507 diff |= ((LONG)(*dp++ & 0xFF)) << 8;
508 diff |= (LONG)(*dp & 0xFF);
509 DEBUG printf("diff=%ux ==> ", diff);
510 #ifdef DEBUG_IMAGE_MARKING
511 printf(" validsegment(4): diff = $%08X --> ", diff);
515 diff = ((diff >> 16) & 0x0000FFFF) | ((diff << 16) & 0xFFFF0000);
517 diff += sect[TEXT].sloc;
520 diff += sect[DATA].sloc;
523 diff = ((diff >> 16) & 0x0000FFFF) | ((diff << 16) & 0xFFFF0000);
525 dp = objImage + BSDHDRSIZE + loc;
526 *dp++ = (char)(diff >> 24);
527 *dp++ = (char)(diff >> 16);
528 *dp++ = (char)(diff >> 8);
530 DEBUG printf("%ux\n", diff);
531 #ifdef DEBUG_IMAGE_MARKING
532 printf("$%08X\n", diff);
541 // Return relocation size
542 if (obj_format == BSD)
543 #ifdef DEBUG_IMAGE_MARKING
545 printf(" rsize = $%X\n", rsize);
548 #ifdef DEBUG_IMAGE_MARKING