Updated printf commands that were complaining about long-words as necessary.
[rmac] / mark.c
1 //
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
7 //
8
9 #include "mark.h"
10 #include "error.h"
11 #include "object.h"
12 #include "risca.h"
13
14 MCHUNK *firstmch;                                           // First mark chunk
15 MCHUNK *curmch;                                             // Current mark chunk
16 PTR markptr;                                                // Deposit point in current mark chunk
17 LONG mcalloc;                                               // #bytes alloc'd to current mark chunk
18 LONG mcused;                                                // #bytes used in current mark chunk
19 WORD curfrom;                                               // Current "from" section
20
21 //
22 // --- Initialize Marker ---------------------------------------------------------------------------
23 //
24
25 void init_mark(void) {
26    firstmch = curmch = NULL;
27    mcalloc = mcused = 0;
28    curfrom = 0;
29 }
30
31 //
32 // --- Wrap up marker (called after final mark is made) --------------------------------------------
33 //
34
35 void stopmark(void) {
36    if(curmch) {
37       *markptr.wp = MCHEND;                                 // Mark end of block
38       curmch->mcused = mcused;                              // Update #used in mark block
39    }
40 }
41
42 //
43 // --- Mark a word or longword relocatable ---------------------------------------------------------
44 //
45
46 int rmark(int from, LONG loc, int to, int size, SYM *symbol) {
47    WORD w;
48
49    if((mcalloc - mcused) < MIN_MARK_MEM)
50       amark();
51
52    w = (WORD)(size | to);
53    if(from != curfrom)
54       w |= MCHFROM;
55    if(symbol != NULL)
56       w |= MSYMBOL;
57
58    mcused += sizeof(WORD) + sizeof(LONG);
59    *markptr.wp++ = w;
60    *markptr.lp++ = loc;
61
62    if(w & MCHFROM) {
63       *markptr.wp++ = (WORD)from;
64       curfrom = (WORD)from;
65       mcused += sizeof(WORD);
66    }
67
68    if(w & MSYMBOL) {
69       *markptr.sy++ = symbol;
70       mcused += sizeof(LONG);
71    }
72
73    *markptr.wp = 0x0000;
74
75    return(0);
76 }
77
78 //
79 // --- Allocate another chunk of mark space --------------------------------------------------------
80 //
81
82 int amark(void) {
83    MCHUNK *p;
84
85    // Alloc mark block header (and data) and set it up.
86    p = (MCHUNK *)amem((long)(sizeof(MCHUNK)) + MARK_ALLOC_INCR);
87    p->mcnext = NULL;
88    p->mcalloc = MARK_ALLOC_INCR;
89    p->mcptr.cp = (char *)(((char *)p) + sizeof(MCHUNK));
90
91    if(curmch) {                                             // Link onto previous chunk 
92       *markptr.wp++ = MCHEND;                               // Mark end of block 
93       curmch->mcused = mcused;
94       curmch->mcnext = p;
95    }
96    if(!firstmch)
97       firstmch = p;
98
99    curmch = p;                                              // Setup global vars 
100    markptr = p->mcptr;
101    mcalloc = MARK_ALLOC_INCR;
102    mcused = 0;
103
104    return(0);
105 }
106
107 //
108 // --- Make mark image for BSD .o file -------------------------------------------------------------
109 //
110
111 LONG bsdmarkimg(char *mp, LONG siz, LONG tsize, int reqseg) {
112    MCHUNK *mch;                                             // Mark chunk
113    PTR p;                                                   // Source point from within mark chunk
114    WORD from;                                               // Section fixups are currently FROM
115    WORD w;                                                  // A word (temp)
116    LONG loc;                                                // Location (temp) 
117    SYM *symbol;                                             // Symbols (temp)
118    char *wp;                                                // Pointer into raw relocation info
119    char *dp;                                                // Deposit point for RELMOD info
120    LONG diff;                                               // Difference to relocate (RELMOD)
121    LONG raddr, rflag = 0;                                   // BSD relocation address and flags
122    LONG rsize;                                              // Relocation size
123    int validsegment = 0;                                    // Valid segment being processed
124
125    rsize = 0;                                               // Initialise relocation size
126    chptr = mp;
127
128    from = 0;
129    for(mch = firstmch; mch != NULL; mch = mch->mcnext)
130       for(p = mch->mcptr;;) {
131          w = *p.wp++;                                       // Next mark entry
132
133          if(w & MCHEND) break;                              // End of mark chunk
134
135          // Get mark record
136          symbol = NULL;
137          loc = *p.lp++;                                     // Mark location
138          if(w & MCHFROM) {                                  // Maybe change "from" section
139             from = *p.wp++;
140             if(obj_format == BSD) {
141                if(reqseg == TEXT) {                         // Requested segment is TEXT
142                   if(from == TEXT) validsegment = 1; 
143                   else validsegment = 0;
144                } else {                                     // Requested segment is DATA
145                   if(from == DATA) validsegment = 1; 
146                   else validsegment = 0;
147                }
148             }
149          }
150
151          if(w & MSYMBOL)                                    // Maybe includes a symbol
152             symbol = *p.sy++;
153
154          if(obj_format == BSD) {
155             raddr = loc;                                    // Set relocation address
156             if(validsegment)
157                D_long(raddr);                               // Write relocation address
158             if(w & MPCREL)
159                rflag = 0x000000A0;                          // PC-relative fixup
160             else
161                rflag = 0x00000040;                          // Absolute fixup
162             if(w & MMOVEI)
163                rflag |= 0x00000001;
164          }
165
166          // Compute mark position in relocation information;
167          // in RELMOD mode, get address of data to fix up.
168          if(from == DATA)
169             loc += tsize;
170          wp = (char *)(mp + loc);
171
172          if(symbol) {
173             // Deposit external reference
174             if(obj_format == BSD) {
175                rflag |= 0x00000010;                         // Set external reloc flag bit
176                rflag |= (symbol->senv << 8);                // Put symbol index in flags
177                if(symbol->sattre & RISCSYM) rflag |= 0x00000001;
178                if(validsegment) {
179                   D_long(rflag);                            // Write relocation flags
180                   rsize += 8;                               // Increment relocation size
181                }
182             }
183
184          } else {
185
186             if(obj_format == BSD) {
187                w &= TDB;                                    // Set reloc flags to segment
188                switch(w) {
189                   case TEXT: rflag |= 0x00000400; break;
190                   case DATA: rflag |= 0x00000600; break;
191                   case BSS:  rflag |= 0x00000800; break;
192                }
193                if(validsegment) {
194                   D_long(rflag);                            // Write relocation flags
195                   rsize += 8;                               // Increment relocation size
196                }
197                w &= TDB;
198                if(validsegment) {
199                   if(w & (DATA|BSS)) {
200                      dp = objimage + BSDHDRSIZE + loc;
201                      diff = ((LONG)(*dp++ & 0xff)) << 24;
202                      diff |= ((LONG)(*dp++ & 0xff)) << 16;
203                      diff |= ((LONG)(*dp++ & 0xff)) << 8;
204                      diff |= (LONG)(*dp & 0xff);
205                      DEBUG printf("diff=%ux ==> ", diff);
206                      if(rflag & 0x01)
207                         diff = ((diff >> 16) & 0x0000FFFF) | ((diff << 16) & 0xFFFF0000);
208                      diff += sect[TEXT].sloc;
209                      if(w == BSS)
210                         diff += sect[DATA].sloc;
211                      if(rflag & 0x01)
212                         diff = ((diff >> 16) & 0x0000FFFF) | ((diff << 16) & 0xFFFF0000);
213                      dp = objimage + BSDHDRSIZE + loc;
214                      *dp++ = (char)(diff >> 24);
215                      *dp++ = (char)(diff >> 16);
216                      *dp++ = (char)(diff >> 8);
217                      *dp = (char)diff;
218                      DEBUG printf("%ux\n", diff);
219                   }
220                }
221             }
222          }
223       }
224
225    if(obj_format == BSD)                                    // Return relocation size
226       return(rsize);                                        
227    else
228       return(siz);
229 }