scc

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

ins.c (3368B)


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