scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | README | LICENSE

ins.c (3411B)


      1 static char sccsid[] = "@(#) ./as/ins.c";
      2 
      3 #include <string.h>
      4 
      5 #include <scc/scc.h>
      6 #include "as.h"
      7 
      8 extern Section *sabs, *sbss, *sdata, *stext;
      9 
     10 enum {
     11 	EQU,
     12 	COMMON,
     13 	SIZE,
     14 	XSTRING,
     15 	ASCII,
     16 	TYPE,
     17 };
     18 
     19 static void
     20 reloc(Symbol *sym,
     21        unsigned flags,
     22        unsigned size,
     23        unsigned nbits,
     24        unsigned shift)
     25 {
     26 }
     27 
     28 char *
     29 tobytes(TUINT v, int nbytes, int inc)
     30 {
     31 	static char buf[sizeof(TUINT)];
     32 	int idx;
     33 
     34 	idx = (inc < 0) ? nbytes-1 : 0;
     35 	while (nbytes--) {
     36 		buf[idx] = v;
     37 		idx += inc;
     38 		v >>= 8;
     39 	}
     40 
     41 	if (v)
     42 		error("overflow in immediate value");
     43 	return buf;
     44 }
     45 
     46 void
     47 noargs(Op *op, Node **args)
     48 {
     49 	emit(op->bytes, op->size);
     50 }
     51 
     52 static void
     53 xstring(int which, Node **args)
     54 {
     55 	Node *np;
     56 	char *s;
     57 	size_t len;
     58 
     59 	while (np = *args++) {
     60 		s = np->sym->name.buf;
     61 		len = strlen(s);
     62 		len += which == XSTRING;
     63 		emit(s, len);
     64 	}
     65 }
     66 
     67 void
     68 string(Op *op, Node **args)
     69 {
     70 	xstring(STRING, args);
     71 }
     72 
     73 void
     74 ascii(Op *op, Node **args)
     75 {
     76 	xstring(STRING, args);
     77 }
     78 
     79 void
     80 def(Node **args, int siz)
     81 {
     82 	Node *np;
     83 
     84 	while (np = *args++) {
     85 		Symbol *sym = np->sym;
     86 
     87 		if ((sym->flags & FABS) == 0)
     88 			reloc(sym, 0, siz, siz * 8, 0);
     89 		emit(tobytes(sym->value, siz, endian), siz);
     90 	}
     91 }
     92 
     93 void
     94 defb(Op *op, Node **args)
     95 {
     96 	def(args, 1);
     97 }
     98 
     99 void
    100 defw(Op *op, Node **args)
    101 {
    102 	def(args, 2);
    103 }
    104 
    105 void
    106 defd(Op *op, Node **args)
    107 {
    108 	def(args, 4);
    109 }
    110 
    111 void
    112 defq(Op *op, Node **args)
    113 {
    114 	def(args, 8);
    115 }
    116 
    117 static void
    118 symexp(int which, Op *op, Node **args)
    119 {
    120 	Symbol *sym, *exp;
    121 	static char *cmds[] = {
    122 		[EQU] = "equ",
    123 		[COMMON] = "common",
    124 		[SIZE] = "size",
    125 	};
    126 	char *cmd = cmds[which];
    127 
    128 	if (args[1]) {
    129 		sym = args[0]->sym;
    130 		exp = args[1]->sym;
    131 	} else if (linesym) {
    132 		sym = linesym;
    133 		exp = args[0]->sym;
    134 	} else {
    135 		error("%s pseudo instruction lacks a label", cmd);
    136 	}
    137 
    138 	if ((exp->flags & FABS) == 0)
    139 		error("%s expression is not an absolute expression", cmd);
    140 
    141 	switch (which) {
    142 	case EQU:
    143 		if (pass == 1 && (sym->flags & FDEF))
    144 			error("redefinition of symbol '%s'", sym->name.buf);
    145 		sym->value = exp->value;
    146 		sym->flags |= FDEF;
    147 		break;
    148 	case COMMON:
    149 		sym->flags |= FCOMMON;
    150 	case SIZE:
    151 		sym->size = exp->value;
    152 		break;
    153 	case TYPE:
    154 		sym->type.buf = xstrdup(exp->name.buf);
    155 		break;
    156 	}
    157 }
    158 
    159 void
    160 equ(Op *op, Node **args)
    161 {
    162 	symexp(EQU, op, args);
    163 }
    164 
    165 void
    166 common(Op *op, Node **args)
    167 {
    168 	symexp(COMMON, op, args);
    169 }
    170 
    171 void
    172 size(Op *op, Node **args)
    173 {
    174 	symexp(SIZE, op, args);
    175 }
    176 
    177 void
    178 type(Op *op, Node **args)
    179 {
    180 	symexp(TYPE, op, args);
    181 }
    182 
    183 void
    184 section(Op *op, Node **args)
    185 {
    186 	Symbol *sym = args[0]->sym;
    187 	char *attr = NULL;
    188 
    189 	if (args[1])
    190 		attr = args[1]->sym->name.buf;
    191 
    192 	setsec(sym->name.buf, attr);
    193 }
    194 
    195 void
    196 text(Op *op, Node **args)
    197 {
    198 	cursec = stext;
    199 }
    200 
    201 void
    202 data(Op *op, Node **args)
    203 {
    204 	cursec = sdata;
    205 }
    206 
    207 void
    208 bss(Op *op, Node **args)
    209 {
    210 	cursec = sbss;
    211 }
    212 
    213 void
    214 extrn(Op *op, Node **args)
    215 {
    216 	Symbol *sym = args[0]->sym;
    217 
    218 	sym->flags |= FEXTERN;
    219 }
    220 
    221 void
    222 global(Op *op, Node **args)
    223 {
    224 	Symbol *sym = args[0]->sym;
    225 
    226 	sym->flags |= FGLOBAL;
    227 }
    228 
    229 void
    230 align(Op *op, Node **args)
    231 {
    232 	Symbol *sym = args[0]->sym;
    233 	TUINT curpc, pc, al;
    234 
    235 	if ((sym->flags & FABS) == 0)
    236 		error("align expression is not an absolute expression");
    237 	if ((al = sym->value) == 0)
    238 		return;
    239 
    240 	al--;
    241 	curpc = cursec->curpc;
    242 	pc = curpc+al & ~al;
    243 
    244 	for (al = pc - curpc; al > 0; --al)
    245 		emit((char []) {0}, 1);
    246 }
    247 
    248 void
    249 end(Op *op, Node **args)
    250 {
    251 	endpass = 1;
    252 }
    253 
    254 void
    255 include(Op *op, Node **args)
    256 {
    257 	addinput(args[0]->sym->name.buf);
    258 }