Pristine Ack-5.5
[Ack-5.5.git] / util / ass / ass50.c
1 /*
2  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3  * See the copyright notice in the ACK home directory, in the file "Copyright".
4  *
5  */
6
7 #include        "ass00.h"
8 #include        "assex.h"
9 #include        "ip_spec.h"
10
11 #ifndef NORCSID
12 static char rcs_id[] = "$Id: ass50.c,v 2.5 1994/06/24 10:15:14 ceriel Exp $" ;
13 #endif
14
15 /*
16 ** Pass 5 of EM1 assembler/loader
17 ** Fix reloc tables
18 ** Write out code
19 */
20
21 pass_5() {
22         register line_t *lnp;
23         cons_t off1;
24         char defined ;
25         int afterlength, partype ;
26         register int inslength, ope;
27         char *op_curr ;
28
29         pass = 5;
30         afterlength = 0;
31         for (lnp = pstate.s_fline ; lnp ; lnp= lnp->l_next, line_num++ ) {
32                 ope = ctrunc(lnp->instr_num);
33                 if ( ope==sp_ilb1 ) continue ;
34                 if ( ope==sp_fpseu ) {
35                         line_num = lnp->ad.ad_ln.ln_first ;
36                         continue ;
37                 }
38                 off1 = parval(lnp,&defined);
39                 if ( (op_curr = lnp->opoff)==NO_OFF ) {
40                         fatal("opoff assertion failed") ;
41                 }
42                 inslength = oplength(*op_curr) ;
43                 afterlength += inslength ;
44
45                 /*
46                  * Change absolute offset to a relative for branches.
47                  */
48
49
50                 partype= em_flag[ope]&EM_PAR ;
51                 if ( partype==PAR_B && defined ) {
52                         off1 -= afterlength;
53                 }
54
55 #ifdef JOHAN
56                 if ( jflag ) {
57                         extern char em_mnem[][4] ;
58                         printf("%s %ld\n",em_mnem[ope],off1) ;
59                 }
60 #endif
61
62                 if ( !defined && partype==PAR_G ) { /* must be external */
63                         text_reloc((lnp->type1==GLOSYM ?
64                                         lnp->ad.ad_gp:lnp->ad.ad_df.df_gp),
65                                 (FOFFSET)(textbytes+afterlength-inslength) ,
66                                         op_curr-opchoice);
67                         xputarb(inslength,off1,tfile);
68                         textoff += inslength ;
69                 } else {
70                         genop(op_curr,off1,partype) ;
71                 }
72         } /* end forloop */
73         line_num-- ;
74
75         patchcase();
76         textbytes += prog_size;
77         if ( textbytes>maxadr ) fatal("Maximum code area size exceeded") ;
78
79 } /* end pass_5 */
80
81 genop(startc,value,i_flag) char *startc ; cons_t value ; int i_flag ; {
82         char *currc ;
83         register flag ;
84         char opc ;
85
86         /*
87          * Real code generation.
88          */
89
90         currc= startc ;
91         flag = ctrunc(*currc++);
92         opc  = *currc++;
93         if ( (flag&OPTYPE)!=OPNO ) {
94
95                 if ( !opfit(flag,*currc,value,i_flag) ) {
96                    fatal("parameter value unsuitable for selected opcode") ;
97                 }
98                 if ( flag&OPWORD ) {
99                         if ( value%wordsize!=0 ) {
100                                 error("parameter not word multiple");
101                         }
102                         value /= wordsize ;
103                 }
104                 if ( flag&OPNZ ) {
105                         if ( value<=0 ) error("negative parameter");
106                         value-- ;
107                 }
108         }
109         if ( flag&OPESC ) put8(ESC) ;
110
111         switch ( flag&OPTYPE ) {
112         case OPMINI :
113                 opc += value<0 ? -1-value : value ;
114                 break ;
115         case OPSHORT :
116                 if ( value<0 ) {
117                         opc += -1-(value>>8) ;
118                 } else {
119                         opc += value>>8 ;
120                 }
121                 break ;
122         case OP32 :
123         case OP64 :
124                 put8(ESC_L) ;
125         }
126
127 #ifdef DUMP
128         if ( c_flag ) {
129                 switch(flag&OPTYPE) {
130                 case OP32 :
131                 case OP64 :
132                         opcnt3[opc&0377]= 1 ;
133                         break ;
134                 default :
135                         if ( flag&OPESC ) opcnt2[opc&0377]= 1 ;
136                         else              opcnt1[opc&0377]= 1 ;
137                         break ;
138                 }
139         }
140 #endif
141
142         put8(opc) ;
143         switch( flag&OPTYPE ) {
144         case OPNO:
145         case OPMINI:
146                 break ;
147         case OPSHORT:
148         case OP8:
149                 put8((char)value) ;
150                 break ;
151         case OP16:
152         case OP16U:
153                 put16(int_cast value) ;
154                 break ;
155         case OP32:
156                 put32(value) ;
157                 break ;
158         case OP64:
159                 put64(value) ;
160                 break ;
161         }
162 }
163
164 patchcase() {
165         register relc_t *r;
166         register locl_t *k;
167
168         if ( r= pstate.s_fdata ) {
169                 r= r->r_next ;
170         } else {
171                 r= f_data ;
172         }
173         for( ; r ; r= r->r_next ) {
174                 if (r->r_typ == RELLOC) {
175                         r->r_typ = RELADR;
176                         k = r->r_val.rel_lp;
177                         if (k->l_defined==YES)
178                                 r->r_val.rel_i = k->l_min + textbytes;
179                         else
180                                 error("case label at line %d undefined",
181                                         k->l_min);
182                 }
183         }
184 }