1#include <string.h>23#include <scc/mach.h>4#include <scc/scc.h>56#include "as.h"78extern Section *sabs, *sbss, *sdata, *stext;910enum {11 EQU,12 COMMON,13 SIZE,14 XSTRING,15 ASCII,16 TYPE,17};1819static void20reloc(Symbol *sym,21 unsigned flags,22 unsigned size,23 unsigned nbits,24 unsigned shift)25{26}2728unsigned char *29tobytes(unsigned long long v, int nbytes, int inc)30{31 static unsigned char buf[sizeof(unsigned long long)];32 int idx;3334 idx = (inc < 0) ? nbytes-1 : 0;35 while (nbytes--) {36 buf[idx] = v;37 idx += inc;38 v >>= 8;39 }4041 if (v)42 error("overflow in immediate value");43 return buf;44}4546void47noargs(Op *op, Node **args)48{49 emit(op->bytes, op->size);50}5152static void53xstring(int which, Node **args)54{55 Node *np;56 char *s;57 size_t len;5859 while (np = *args++) {60 s = np->sym->name;61 len = strlen(s);62 len += which == XSTRING;63 emit((unsigned char *)s, len);64 }65}6667void68string(Op *op, Node **args)69{70 xstring(STRING, args);71}7273void74ascii(Op *op, Node **args)75{76 xstring(STRING, args);77}7879void80def(Node **args, int siz)81{82 Node *np;8384 while (np = *args++) {85 Symbol *sym = np->sym;8687 if ((sym->flags & FABS) == 0)88 reloc(sym, 0, siz, siz * 8, 0);89 emit(tobytes(sym->value, siz, endian), siz);90 }91}9293void94defb(Op *op, Node **args)95{96 def(args, 1);97}9899void100defw(Op *op, Node **args)101{102 def(args, 2);103}104105void106defd(Op *op, Node **args)107{108 def(args, 4);109}110111void112defq(Op *op, Node **args)113{114 def(args, 8);115}116117static void118symexp(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];127128 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 }137138 if ((exp->flags & FABS) == 0)139 error("%s expression is not an absolute expression", cmd);140141 switch (which) {142 case EQU:143 if (pass == 1 && (sym->flags & FDEF))144 error("redefinition of symbol '%s'", sym->name);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->dtype = exp->value;155 break;156 }157}158159void160equ(Op *op, Node **args)161{162 symexp(EQU, op, args);163}164165void166common(Op *op, Node **args)167{168 symexp(COMMON, op, args);169}170171void172size(Op *op, Node **args)173{174 symexp(SIZE, op, args);175}176177void178type(Op *op, Node **args)179{180 symexp(TYPE, op, args);181}182183void184section(Op *op, Node **args)185{186 Symbol *sym = args[0]->sym;187 char *attr = NULL;188189 if (args[1])190 attr = args[1]->sym->name;191192 defsec(sym->name, attr);193}194195void196text(Op *op, Node **args)197{198 cursec = stext;199}200201void202data(Op *op, Node **args)203{204 cursec = sdata;205}206207void208bss(Op *op, Node **args)209{210 cursec = sbss;211}212213void214extrn(Op *op, Node **args)215{216 Symbol *sym = args[0]->sym;217218 sym->flags |= FEXTERN;219}220221void222global(Op *op, Node **args)223{224 Symbol *sym = args[0]->sym;225226 sym->flags |= FGLOBAL;227}228229void230align(Op *op, Node **args)231{232 Symbol *sym = args[0]->sym;233 unsigned long long pcal, pc, al;234235 if ((sym->flags & FABS) == 0)236 error("align expression is not an absolute expression");237 if ((al = sym->value) == 0)238 return;239240 al--;241 pc = getpc();242 pcal = pc+al & ~al;243244 for (al = pcal - pc; al > 0; --al)245 emit((unsigned char []) {0}, 1);246}247248void249end(Op *op, Node **args)250{251 endpass = 1;252}253254void255include(Op *op, Node **args)256{257 addinput(args[0]->sym->name);258}