diff --git a/Makefile b/Makefile index 0beb23d..0b8fd91 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,12 @@ .POSIX: .SUFFIXES: .o .c +LIBRARY = libqbe.a +HEADER = libqbe.h + PREFIX = /usr/local -BINDIR = $(PREFIX)/bin +LIBDIR = $(PREFIX)/lib +INCDIR = $(PREFIX)/include COMMOBJ = libqbe.o util.o parse.o abi.o cfg.o mem.o ssa.o alias.o load.o \ copy.o fold.o simpl.o live.o spill.o rega.o emit.o @@ -15,7 +19,7 @@ SRCALL = $(OBJ:.o=.c) CC = cc AR = ar -CFLAGS = -std=c99 -g -Wall -Wextra -Wpedantic +CFLAGS = -std=gnu99 -g -Wall -Wextra -Wpedantic libqbe.a: $(OBJ) $(AR) rcs $@ $(OBJ) @@ -23,13 +27,13 @@ libqbe.a: $(OBJ) .c.o: $(CC) $(CFLAGS) -c $< -o $@ -$(OBJ): all.h ops.h +$(OBJ): qbe/all.h qbe/ops.h $(AMD64OBJ): amd64/all.h $(ARM64OBJ): arm64/all.h $(RV64OBJ): rv64/all.h -libqbe.o: config.h +libqbe.o: qbe/config.h -config.h: +qbe/config.h: @case `uname` in \ *Darwin*) \ case `uname -m` in \ @@ -56,27 +60,19 @@ config.h: ;; \ esac > $@ -install: qbe - mkdir -p "$(DESTDIR)$(BINDIR)" - install -m755 qbe "$(DESTDIR)$(BINDIR)/qbe" +install: $(LIBRARY) $(HEADER) + mkdir -p "$(DESTDIR)$(LIBDIR)" + cp "$(LIBRARY)" "$(DESTDIR)$(LIBDIR)/" + cp -r "$(HEADER)" "qbe/" "$(DESTDIR)$(INCDIR)/" uninstall: - rm -f "$(DESTDIR)$(BINDIR)/qbe" + rm -f "$(DESTDIR)$(LIBDIR)/$(LIBRARY)" "$(DESTDIR)$(INCDIR)/$(HEADER)" "$(DESTDIR)$(INCDIR)/qbe" clean: - rm -f *.o */*.o qbe + rm -r *.o */*.o clean-gen: clean - rm -f config.h - -check: qbe - tools/test.sh all - -check-arm64: qbe - TARGET=arm64 tools/test.sh all - -check-rv64: qbe - TARGET=rv64 tools/test.sh all + rm -f qbe/config.h src: @echo $(SRCALL) diff --git a/README b/README index 69d0aa9..74b6487 100644 --- a/README +++ b/README @@ -1,9 +1,7 @@ QBE - Backend Compiler http://c9x.me/compile/ -doc/ Documentation. -minic/ An example C frontend for QBE. -tools/ Miscellaneous tools (testing). -test/ Tests. +I did not create QBE, I simply turned it into a C library. + amd64/ arm64/ rv64/ Architecture-specific code. @@ -15,4 +13,4 @@ The LICENSE file applies to all files distributed. Invoke make in this directory to create the executable file qbe. Install using 'make install', the standard DESTDIR and PREFIX environment variables are supported. -Alternatively, you may simply copy the qbe binary manually. +Alternatively, you may simply copy the libqbe.a and libqbe.h files manually. diff --git a/all.h b/all.h deleted file mode 100644 index 3479d27..0000000 --- a/all.h +++ /dev/null @@ -1,585 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#define MAKESURE(what, x) typedef char make_sure_##what[(x)?1:-1] -#define die(...) die_(__FILE__, __VA_ARGS__) - -typedef unsigned char uchar; -typedef unsigned int uint; -typedef unsigned long ulong; -typedef unsigned long long bits; - -typedef struct BSet BSet; -typedef struct Ref Ref; -typedef struct Op Op; -typedef struct Ins Ins; -typedef struct Phi Phi; -typedef struct Blk Blk; -typedef struct Use Use; -typedef struct Sym Sym; -typedef struct Num Num; -typedef struct Alias Alias; -typedef struct Tmp Tmp; -typedef struct Con Con; -typedef struct Addr Mem; -typedef struct Fn Fn; -typedef struct Typ Typ; -typedef struct Field Field; -typedef struct Dat Dat; -typedef struct Lnk Lnk; -typedef struct Target Target; - -enum { - NString = 80, - NIns = 1 << 20, - NAlign = 3, - NField = 32, - NBit = CHAR_BIT * sizeof(bits), -}; - -struct Target { - char name[16]; - char apple; - int gpr0; /* first general purpose reg */ - int ngpr; - int fpr0; /* first floating point reg */ - int nfpr; - bits rglob; /* globally live regs (e.g., sp, fp) */ - int nrglob; - int *rsave; /* caller-save */ - int nrsave[2]; - bits (*retregs)(Ref, int[2]); - bits (*argregs)(Ref, int[2]); - int (*memargs)(int); - void (*abi0)(Fn *); - void (*abi1)(Fn *); - void (*isel)(Fn *); - void (*emitfn)(Fn *, FILE *); - void (*emitfin)(FILE *); - char asloc[4]; - char assym[4]; -}; - -#define BIT(n) ((bits)1 << (n)) - -enum { - RXX = 0, - Tmp0 = NBit, /* first non-reg temporary */ -}; - -struct BSet { - uint nt; - bits *t; -}; - -struct Ref { - uint type:3; - uint val:29; -}; - -enum { - RTmp, - RCon, - RInt, - RType, /* last kind to come out of the parser */ - RSlot, - RCall, - RMem, -}; - -#define R (Ref){RTmp, 0} -#define UNDEF (Ref){RCon, 0} /* represents uninitialized data */ -#define CON_Z (Ref){RCon, 1} -#define TMP(x) (Ref){RTmp, x} -#define CON(x) (Ref){RCon, x} -#define SLOT(x) (Ref){RSlot, (x)&0x1fffffff} -#define TYPE(x) (Ref){RType, x} -#define CALL(x) (Ref){RCall, x} -#define MEM(x) (Ref){RMem, x} -#define INT(x) (Ref){RInt, (x)&0x1fffffff} - -static inline int req(Ref a, Ref b) -{ - return a.type == b.type && a.val == b.val; -} - -static inline int rtype(Ref r) -{ - if (req(r, R)) - return -1; - return r.type; -} - -static inline int rsval(Ref r) -{ - return ((int)r.val ^ 0x10000000) - 0x10000000; -} - -enum CmpI { - Cieq, - Cine, - Cisge, - Cisgt, - Cisle, - Cislt, - Ciuge, - Ciugt, - Ciule, - Ciult, - NCmpI, -}; - -enum CmpF { - Cfeq, - Cfge, - Cfgt, - Cfle, - Cflt, - Cfne, - Cfo, - Cfuo, - NCmpF, - NCmp = NCmpI + NCmpF, -}; - -enum O { - Oxxx, -#define O(op, x, y) O##op, - #include "ops.h" - NOp, -}; - -enum J { - Jxxx, -#define JMPS(X) \ - X(retw) X(retl) X(rets) X(retd) \ - X(retsb) X(retub) X(retsh) X(retuh) \ - X(retc) X(ret0) X(jmp) X(jnz) \ - X(jfieq) X(jfine) X(jfisge) X(jfisgt) \ - X(jfisle) X(jfislt) X(jfiuge) X(jfiugt) \ - X(jfiule) X(jfiult) X(jffeq) X(jffge) \ - X(jffgt) X(jffle) X(jfflt) X(jffne) \ - X(jffo) X(jffuo) X(hlt) -#define X(j) J##j, - JMPS(X) -#undef X - NJmp -}; - -enum { - Ocmpw = Oceqw, - Ocmpw1 = Ocultw, - Ocmpl = Oceql, - Ocmpl1 = Ocultl, - Ocmps = Oceqs, - Ocmps1 = Ocuos, - Ocmpd = Oceqd, - Ocmpd1 = Ocuod, - Oalloc = Oalloc4, - Oalloc1 = Oalloc16, - Oflag = Oflagieq, - Oflag1 = Oflagfuo, - NPubOp = Onop, - Jjf = Jjfieq, - Jjf1 = Jjffuo, -}; - -#define INRANGE(x, l, u) ((unsigned)(x) - l <= u - l) /* linear in x */ -#define isstore(o) INRANGE(o, Ostoreb, Ostored) -#define isload(o) INRANGE(o, Oloadsb, Oload) -#define isext(o) INRANGE(o, Oextsb, Oextuw) -#define ispar(o) INRANGE(o, Opar, Opare) -#define isarg(o) INRANGE(o, Oarg, Oargv) -#define isret(j) INRANGE(j, Jretw, Jret0) -#define isparbh(o) INRANGE(o, Oparsb, Oparuh) -#define isargbh(o) INRANGE(o, Oargsb, Oarguh) -#define isretbh(j) INRANGE(j, Jretsb, Jretuh) - -enum { - Kx = -1, /* "top" class (see usecheck() and clsmerge()) */ - Kw, - Kl, - Ks, - Kd -}; - -#define KWIDE(k) ((k)&1) -#define KBASE(k) ((k)>>1) - -struct Op { - char *name; - short argcls[2][4]; - uint canfold:1; - uint hasid:1; - uint idval:1; /* identity value 0/1 */ -}; - -struct Ins { - uint op:30; - uint cls:2; - Ref to; - Ref arg[2]; -}; - -struct Phi { - Ref to; - Ref *arg; - Blk **blk; - uint narg; - int cls; - Phi *link; -}; - -struct Blk { - Phi *phi; - Ins *ins; - uint nins; - struct { - short type; - Ref arg; - } jmp; - Blk *s1; - Blk *s2; - Blk *link; - - uint id; - uint visit; - - Blk *idom; - Blk *dom, *dlink; - Blk **fron; - uint nfron; - - Blk **pred; - uint npred; - BSet in[1], out[1], gen[1]; - int nlive[2]; - int loop; - char name[NString]; -}; - -struct Use { - enum { - UXXX, - UPhi, - UIns, - UJmp, - } type; - uint bid; - union { - Ins *ins; - Phi *phi; - } u; -}; - -struct Sym { - enum { - SGlo, - SThr, - } type; - uint32_t id; -}; - -struct Num { - uchar n; - uchar nl, nr; - Ref l, r; -}; - -enum { - NoAlias, - MayAlias, - MustAlias -}; - -struct Alias { - enum { - ABot = 0, - ALoc = 1, /* stack local */ - ACon = 2, - AEsc = 3, /* stack escaping */ - ASym = 4, - AUnk = 6, - #define astack(t) ((t) & 1) - } type; - int base; - int64_t offset; - union { - Sym sym; - struct { - int sz; /* -1 if > NBit */ - bits m; - } loc; - } u; - Alias *slot; -}; - -struct Tmp { - char name[NString]; - Ins *def; - Use *use; - uint ndef, nuse; - uint bid; /* id of a defining block */ - uint cost; - int slot; /* -1 for unset */ - short cls; - struct { - int r; /* register or -1 */ - int w; /* weight */ - bits m; /* avoid these registers */ - } hint; - int phi; - Alias alias; - enum { - WFull, - Wsb, /* must match Oload/Oext order */ - Wub, - Wsh, - Wuh, - Wsw, - Wuw - } width; - int visit; -}; - -struct Con { - enum { - CUndef, - CBits, - CAddr, - } type; - Sym sym; - union { - int64_t i; - double d; - float s; - } bits; - char flt; /* 1 to print as s, 2 to print as d */ -}; - -typedef struct Addr Addr; - -struct Addr { /* amd64 addressing */ - Con offset; - Ref base; - Ref index; - int scale; -}; - -struct Lnk { - char export; - char thread; - char common; - char align; - char *sec; - char *secf; -}; - -struct Fn { - Blk *start; - Tmp *tmp; - Con *con; - Mem *mem; - int ntmp; - int ncon; - int nmem; - uint nblk; - int retty; /* index in typ[], -1 if no aggregate return */ - Ref retr; - Blk **rpo; - bits reg; - int slot; - char vararg; - char dynalloc; - char name[NString]; - Lnk lnk; -}; - -struct Typ { - char name[NString]; - char isdark; - char isunion; - int align; - uint64_t size; - uint nunion; - struct Field { - enum { - FEnd, - Fb, - Fh, - Fw, - Fl, - Fs, - Fd, - FPad, - FTyp, - } type; - uint len; /* or index in typ[] for FTyp */ - } (*fields)[NField+1]; -}; - -struct Dat { - enum { - DStart, - DEnd, - DB, - DH, - DW, - DL, - DZ - } type; - char *name; - Lnk *lnk; - union { - int64_t num; - double fltd; - float flts; - char *str; - struct { - char *name; - int64_t off; - } ref; - } u; - char isref; - char isstr; -}; - -/* main.c */ -extern Target T; -extern char debug['Z'+1]; - -/* util.c */ -typedef enum { - PHeap, /* free() necessary */ - PFn, /* discarded after processing the function */ -} Pool; - -extern Typ *typ; -extern Ins insb[NIns], *curi; -uint32_t hash(char *); -void die_(char *, char *, ...) __attribute__((noreturn)); -void *emalloc(size_t); -void *alloc(size_t); -void freeall(void); -void *vnew(ulong, size_t, Pool); -void vfree(void *); -void vgrow(void *, ulong); -void strf(char[NString], char *, ...); -uint32_t intern(char *); -char *str(uint32_t); -int argcls(Ins *, int); -int isreg(Ref); -int iscmp(int, int *, int *); -void emit(int, int, Ref, Ref, Ref); -void emiti(Ins); -void idup(Ins **, Ins *, ulong); -Ins *icpy(Ins *, Ins *, ulong); -int cmpop(int); -int cmpneg(int); -int clsmerge(short *, short); -int phicls(int, Tmp *); -Ref newtmp(char *, int, Fn *); -void chuse(Ref, int, Fn *); -int symeq(Sym, Sym); -Ref newcon(Con *, Fn *); -Ref getcon(int64_t, Fn *); -int addcon(Con *, Con *, int); -void salloc(Ref, Ref, Fn *); -void dumpts(BSet *, Tmp *, FILE *); -void runmatch(uchar *, Num *, Ref, Ref *); - -void bsinit(BSet *, uint); -void bszero(BSet *); -uint bscount(BSet *); -void bsset(BSet *, uint); -void bsclr(BSet *, uint); -void bscopy(BSet *, BSet *); -void bsunion(BSet *, BSet *); -void bsinter(BSet *, BSet *); -void bsdiff(BSet *, BSet *); -int bsequal(BSet *, BSet *); -int bsiter(BSet *, int *); - -static inline int -bshas(BSet *bs, uint elt) -{ - assert(elt < bs->nt * NBit); - return (bs->t[elt/NBit] & BIT(elt%NBit)) != 0; -} - -/* parse.c */ -extern Op optab[NOp]; -void parse(FILE *, char *, void (char *), void (Dat *), void (Fn *)); -void printfn(Fn *, FILE *); -void printref(Ref, Fn *, FILE *); -void err(char *, ...) __attribute__((noreturn)); - -/* abi.c */ -void elimsb(Fn *); - -/* cfg.c */ -Blk *newblk(void); -void edgedel(Blk *, Blk **); -void fillpreds(Fn *); -void fillrpo(Fn *); -void filldom(Fn *); -int sdom(Blk *, Blk *); -int dom(Blk *, Blk *); -void fillfron(Fn *); -void loopiter(Fn *, void (*)(Blk *, Blk *)); -void fillloop(Fn *); -void simpljmp(Fn *); - -/* mem.c */ -void promote(Fn *); -void coalesce(Fn *); - -/* alias.c */ -void fillalias(Fn *); -void getalias(Alias *, Ref, Fn *); -int alias(Ref, int, int, Ref, int, int *, Fn *); -int escapes(Ref, Fn *); - -/* load.c */ -int loadsz(Ins *); -int storesz(Ins *); -void loadopt(Fn *); - -/* ssa.c */ -void filluse(Fn *); -void ssa(Fn *); -void ssacheck(Fn *); - -/* copy.c */ -void copy(Fn *); - -/* fold.c */ -void fold(Fn *); - -/* simpl.c */ -void simpl(Fn *); - -/* live.c */ -void liveon(BSet *, Blk *, Blk *); -void filllive(Fn *); - -/* spill.c */ -void fillcost(Fn *); -void spill(Fn *); - -/* rega.c */ -void rega(Fn *); - -/* emit.c */ -void emitfnlnk(char *, Lnk *, FILE *); -void emitdat(Dat *, FILE *); -void emitdbgfile(char *, FILE *); -void emitdbgloc(uint, uint, FILE *); -int stashbits(void *, int); -void elf_emitfnfin(char *, FILE *); -void elf_emitfin(FILE *); -void macho_emitfin(FILE *); diff --git a/all.h b/all.h new file mode 120000 index 0000000..3e90ec4 --- /dev/null +++ b/all.h @@ -0,0 +1 @@ +qbe/all.h \ No newline at end of file diff --git a/libqbe.c b/libqbe.c index 9f06157..2577879 100644 --- a/libqbe.c +++ b/libqbe.c @@ -1,5 +1,4 @@ #include "libqbe.h" -#include #include #include @@ -100,7 +99,7 @@ dbgfile(char *fn) } const char* -qbe_emit(Target target, const char* ssa) +qbe_gen(Target target, const char* ssa) { T = target; FILE *inf = tmpfile(); @@ -127,3 +126,20 @@ qbe_emit(Target target, const char* ssa) return buf; } + +void +qbe_emit(const char* filename, const char* assembly) { + char cc[255]; + snprintf(cc, 255, "cc -x assembler -o %s -", filename); + + FILE* cc_pipe = popen(cc, "w"); + if(fputs(assembly, cc_pipe) == EOF) { + perror("fputs"); + } + pclose(cc_pipe); +} + +void +qbe_gen_and_emit(Target target, const char* filename, const char* ssa) { + qbe_emit(filename, qbe_gen(target, ssa)); +} diff --git a/libqbe.h b/libqbe.h index 834fefd..d360495 100644 --- a/libqbe.h +++ b/libqbe.h @@ -1,5 +1,5 @@ -#include "all.h" -#include "config.h" +#include "qbe/all.h" +#include "qbe/config.h" #ifndef __LIBQBE_H__ #define __LIBQBE_H__ @@ -10,6 +10,8 @@ extern Target T_arm64; extern Target T_arm64_apple; extern Target T_rv64; -const char* qbe_emit(Target target, const char* ssa); +const char* qbe_gen(Target target, const char* ssa); +void qbe_emit(const char* filename, const char* assembly); +void qbe_gen_and_emit(Target target, const char* filename, const char* ssa); #endif diff --git a/ops.h b/ops.h deleted file mode 100644 index beaa6f3..0000000 --- a/ops.h +++ /dev/null @@ -1,199 +0,0 @@ -#ifndef X /* amd64 */ - #define X(NMemArgs, SetsZeroFlag, LeavesFlags) -#endif - -#ifndef V /* riscv64 */ - #define V(Imm) -#endif - -#ifndef P - #define P(CanFold, HasId, IdVal) -#endif - - -#define T(a,b,c,d,e,f,g,h) { \ - {[Kw]=K##a, [Kl]=K##b, [Ks]=K##c, [Kd]=K##d}, \ - {[Kw]=K##e, [Kl]=K##f, [Ks]=K##g, [Kd]=K##h} \ -} - - -/*********************/ -/* PUBLIC OPERATIONS */ -/*********************/ - -/* Arithmetic and Bits */ -O(add, T(w,l,s,d, w,l,s,d), P(1,1,0)) X(2,1,0) V(1) -O(sub, T(w,l,s,d, w,l,s,d), P(1,1,0)) X(2,1,0) V(0) -O(neg, T(w,l,s,d, x,x,x,x), P(1,0,0)) X(1,1,0) V(0) -O(div, T(w,l,s,d, w,l,s,d), P(1,1,1)) X(0,0,0) V(0) -O(rem, T(w,l,e,e, w,l,e,e), P(1,0,0)) X(0,0,0) V(0) -O(udiv, T(w,l,e,e, w,l,e,e), P(1,1,1)) X(0,0,0) V(0) -O(urem, T(w,l,e,e, w,l,e,e), P(1,0,0)) X(0,0,0) V(0) -O(mul, T(w,l,s,d, w,l,s,d), P(1,1,1)) X(2,0,0) V(0) -O(and, T(w,l,e,e, w,l,e,e), P(1,0,0)) X(2,1,0) V(1) -O(or, T(w,l,e,e, w,l,e,e), P(1,1,0)) X(2,1,0) V(1) -O(xor, T(w,l,e,e, w,l,e,e), P(1,1,0)) X(2,1,0) V(1) -O(sar, T(w,l,e,e, w,w,e,e), P(1,1,0)) X(1,1,0) V(1) -O(shr, T(w,l,e,e, w,w,e,e), P(1,1,0)) X(1,1,0) V(1) -O(shl, T(w,l,e,e, w,w,e,e), P(1,1,0)) X(1,1,0) V(1) - -/* Comparisons */ -O(ceqw, T(w,w,e,e, w,w,e,e), P(1,0,0)) X(0,1,0) V(0) -O(cnew, T(w,w,e,e, w,w,e,e), P(1,0,0)) X(0,1,0) V(0) -O(csgew, T(w,w,e,e, w,w,e,e), P(1,0,0)) X(0,1,0) V(0) -O(csgtw, T(w,w,e,e, w,w,e,e), P(1,0,0)) X(0,1,0) V(0) -O(cslew, T(w,w,e,e, w,w,e,e), P(1,0,0)) X(0,1,0) V(0) -O(csltw, T(w,w,e,e, w,w,e,e), P(1,0,0)) X(0,1,0) V(1) -O(cugew, T(w,w,e,e, w,w,e,e), P(1,0,0)) X(0,1,0) V(0) -O(cugtw, T(w,w,e,e, w,w,e,e), P(1,0,0)) X(0,1,0) V(0) -O(culew, T(w,w,e,e, w,w,e,e), P(1,0,0)) X(0,1,0) V(0) -O(cultw, T(w,w,e,e, w,w,e,e), P(1,0,0)) X(0,1,0) V(1) - -O(ceql, T(l,l,e,e, l,l,e,e), P(1,0,0)) X(0,1,0) V(0) -O(cnel, T(l,l,e,e, l,l,e,e), P(1,0,0)) X(0,1,0) V(0) -O(csgel, T(l,l,e,e, l,l,e,e), P(1,0,0)) X(0,1,0) V(0) -O(csgtl, T(l,l,e,e, l,l,e,e), P(1,0,0)) X(0,1,0) V(0) -O(cslel, T(l,l,e,e, l,l,e,e), P(1,0,0)) X(0,1,0) V(0) -O(csltl, T(l,l,e,e, l,l,e,e), P(1,0,0)) X(0,1,0) V(1) -O(cugel, T(l,l,e,e, l,l,e,e), P(1,0,0)) X(0,1,0) V(0) -O(cugtl, T(l,l,e,e, l,l,e,e), P(1,0,0)) X(0,1,0) V(0) -O(culel, T(l,l,e,e, l,l,e,e), P(1,0,0)) X(0,1,0) V(0) -O(cultl, T(l,l,e,e, l,l,e,e), P(1,0,0)) X(0,1,0) V(1) - -O(ceqs, T(s,s,e,e, s,s,e,e), P(1,0,0)) X(0,1,0) V(0) -O(cges, T(s,s,e,e, s,s,e,e), P(1,0,0)) X(0,1,0) V(0) -O(cgts, T(s,s,e,e, s,s,e,e), P(1,0,0)) X(0,1,0) V(0) -O(cles, T(s,s,e,e, s,s,e,e), P(1,0,0)) X(0,1,0) V(0) -O(clts, T(s,s,e,e, s,s,e,e), P(1,0,0)) X(0,1,0) V(0) -O(cnes, T(s,s,e,e, s,s,e,e), P(1,0,0)) X(0,1,0) V(0) -O(cos, T(s,s,e,e, s,s,e,e), P(1,0,0)) X(0,1,0) V(0) -O(cuos, T(s,s,e,e, s,s,e,e), P(1,0,0)) X(0,1,0) V(0) - -O(ceqd, T(d,d,e,e, d,d,e,e), P(1,0,0)) X(0,1,0) V(0) -O(cged, T(d,d,e,e, d,d,e,e), P(1,0,0)) X(0,1,0) V(0) -O(cgtd, T(d,d,e,e, d,d,e,e), P(1,0,0)) X(0,1,0) V(0) -O(cled, T(d,d,e,e, d,d,e,e), P(1,0,0)) X(0,1,0) V(0) -O(cltd, T(d,d,e,e, d,d,e,e), P(1,0,0)) X(0,1,0) V(0) -O(cned, T(d,d,e,e, d,d,e,e), P(1,0,0)) X(0,1,0) V(0) -O(cod, T(d,d,e,e, d,d,e,e), P(1,0,0)) X(0,1,0) V(0) -O(cuod, T(d,d,e,e, d,d,e,e), P(1,0,0)) X(0,1,0) V(0) - -/* Memory */ -O(storeb, T(w,e,e,e, m,e,e,e), P(0,0,0)) X(0,0,1) V(0) -O(storeh, T(w,e,e,e, m,e,e,e), P(0,0,0)) X(0,0,1) V(0) -O(storew, T(w,e,e,e, m,e,e,e), P(0,0,0)) X(0,0,1) V(0) -O(storel, T(l,e,e,e, m,e,e,e), P(0,0,0)) X(0,0,1) V(0) -O(stores, T(s,e,e,e, m,e,e,e), P(0,0,0)) X(0,0,1) V(0) -O(stored, T(d,e,e,e, m,e,e,e), P(0,0,0)) X(0,0,1) V(0) - -O(loadsb, T(m,m,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0) -O(loadub, T(m,m,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0) -O(loadsh, T(m,m,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0) -O(loaduh, T(m,m,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0) -O(loadsw, T(m,m,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0) -O(loaduw, T(m,m,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0) -O(load, T(m,m,m,m, x,x,x,x), P(0,0,0)) X(0,0,1) V(0) - -/* Extensions and Truncations */ -O(extsb, T(w,w,e,e, x,x,e,e), P(1,0,0)) X(0,0,1) V(0) -O(extub, T(w,w,e,e, x,x,e,e), P(1,0,0)) X(0,0,1) V(0) -O(extsh, T(w,w,e,e, x,x,e,e), P(1,0,0)) X(0,0,1) V(0) -O(extuh, T(w,w,e,e, x,x,e,e), P(1,0,0)) X(0,0,1) V(0) -O(extsw, T(e,w,e,e, e,x,e,e), P(1,0,0)) X(0,0,1) V(0) -O(extuw, T(e,w,e,e, e,x,e,e), P(1,0,0)) X(0,0,1) V(0) - -O(exts, T(e,e,e,s, e,e,e,x), P(1,0,0)) X(0,0,1) V(0) -O(truncd, T(e,e,d,e, e,e,x,e), P(1,0,0)) X(0,0,1) V(0) -O(stosi, T(s,s,e,e, x,x,e,e), P(1,0,0)) X(0,0,1) V(0) -O(stoui, T(s,s,e,e, x,x,e,e), P(1,0,0)) X(0,0,1) V(0) -O(dtosi, T(d,d,e,e, x,x,e,e), P(1,0,0)) X(0,0,1) V(0) -O(dtoui, T(d,d,e,e, x,x,e,e), P(1,0,0)) X(0,0,1) V(0) -O(swtof, T(e,e,w,w, e,e,x,x), P(1,0,0)) X(0,0,1) V(0) -O(uwtof, T(e,e,w,w, e,e,x,x), P(1,0,0)) X(0,0,1) V(0) -O(sltof, T(e,e,l,l, e,e,x,x), P(1,0,0)) X(0,0,1) V(0) -O(ultof, T(e,e,l,l, e,e,x,x), P(1,0,0)) X(0,0,1) V(0) -O(cast, T(s,d,w,l, x,x,x,x), P(1,0,0)) X(0,0,1) V(0) - -/* Stack Allocation */ -O(alloc4, T(e,l,e,e, e,x,e,e), P(0,0,0)) X(0,0,0) V(0) -O(alloc8, T(e,l,e,e, e,x,e,e), P(0,0,0)) X(0,0,0) V(0) -O(alloc16, T(e,l,e,e, e,x,e,e), P(0,0,0)) X(0,0,0) V(0) - -/* Variadic Function Helpers */ -O(vaarg, T(m,m,m,m, x,x,x,x), P(0,0,0)) X(0,0,0) V(0) -O(vastart, T(m,e,e,e, x,e,e,e), P(0,0,0)) X(0,0,0) V(0) - -O(copy, T(w,l,s,d, x,x,x,x), P(0,0,0)) X(0,0,1) V(0) - -/* Debug */ -O(dbgloc, T(w,e,e,e, w,e,e,e), P(0,0,0)) X(0,0,1) V(0) - -/****************************************/ -/* INTERNAL OPERATIONS (keep nop first) */ -/****************************************/ - -/* Miscellaneous and Architecture-Specific Operations */ -O(nop, T(x,x,x,x, x,x,x,x), P(0,0,0)) X(0,0,1) V(0) -O(addr, T(m,m,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0) -O(blit0, T(m,e,e,e, m,e,e,e), P(0,0,0)) X(0,1,0) V(0) -O(blit1, T(w,e,e,e, x,e,e,e), P(0,0,0)) X(0,1,0) V(0) -O(swap, T(w,l,s,d, w,l,s,d), P(0,0,0)) X(1,0,0) V(0) -O(sign, T(w,l,e,e, x,x,e,e), P(0,0,0)) X(0,0,0) V(0) -O(salloc, T(e,l,e,e, e,x,e,e), P(0,0,0)) X(0,0,0) V(0) -O(xidiv, T(w,l,e,e, x,x,e,e), P(0,0,0)) X(1,0,0) V(0) -O(xdiv, T(w,l,e,e, x,x,e,e), P(0,0,0)) X(1,0,0) V(0) -O(xcmp, T(w,l,s,d, w,l,s,d), P(0,0,0)) X(1,1,0) V(0) -O(xtest, T(w,l,e,e, w,l,e,e), P(0,0,0)) X(1,1,0) V(0) -O(acmp, T(w,l,e,e, w,l,e,e), P(0,0,0)) X(0,0,0) V(0) -O(acmn, T(w,l,e,e, w,l,e,e), P(0,0,0)) X(0,0,0) V(0) -O(afcmp, T(e,e,s,d, e,e,s,d), P(0,0,0)) X(0,0,0) V(0) -O(reqz, T(w,l,e,e, x,x,e,e), P(0,0,0)) X(0,0,0) V(0) -O(rnez, T(w,l,e,e, x,x,e,e), P(0,0,0)) X(0,0,0) V(0) - -/* Arguments, Parameters, and Calls */ -O(par, T(x,x,x,x, x,x,x,x), P(0,0,0)) X(0,0,0) V(0) -O(parsb, T(x,x,x,x, x,x,x,x), P(0,0,0)) X(0,0,0) V(0) -O(parub, T(x,x,x,x, x,x,x,x), P(0,0,0)) X(0,0,0) V(0) -O(parsh, T(x,x,x,x, x,x,x,x), P(0,0,0)) X(0,0,0) V(0) -O(paruh, T(x,x,x,x, x,x,x,x), P(0,0,0)) X(0,0,0) V(0) -O(parc, T(e,x,e,e, e,x,e,e), P(0,0,0)) X(0,0,0) V(0) -O(pare, T(e,x,e,e, e,x,e,e), P(0,0,0)) X(0,0,0) V(0) -O(arg, T(w,l,s,d, x,x,x,x), P(0,0,0)) X(0,0,0) V(0) -O(argsb, T(w,e,e,e, x,x,x,x), P(0,0,0)) X(0,0,0) V(0) -O(argub, T(w,e,e,e, x,x,x,x), P(0,0,0)) X(0,0,0) V(0) -O(argsh, T(w,e,e,e, x,x,x,x), P(0,0,0)) X(0,0,0) V(0) -O(arguh, T(w,e,e,e, x,x,x,x), P(0,0,0)) X(0,0,0) V(0) -O(argc, T(e,x,e,e, e,l,e,e), P(0,0,0)) X(0,0,0) V(0) -O(arge, T(e,l,e,e, e,x,e,e), P(0,0,0)) X(0,0,0) V(0) -O(argv, T(x,x,x,x, x,x,x,x), P(0,0,0)) X(0,0,0) V(0) -O(call, T(m,m,m,m, x,x,x,x), P(0,0,0)) X(0,0,0) V(0) - -/* Flags Setting */ -O(flagieq, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0) -O(flagine, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0) -O(flagisge, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0) -O(flagisgt, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0) -O(flagisle, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0) -O(flagislt, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0) -O(flagiuge, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0) -O(flagiugt, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0) -O(flagiule, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0) -O(flagiult, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0) -O(flagfeq, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0) -O(flagfge, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0) -O(flagfgt, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0) -O(flagfle, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0) -O(flagflt, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0) -O(flagfne, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0) -O(flagfo, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0) -O(flagfuo, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0) - - -#undef T -#undef X -#undef V -#undef O - -/* -| column -t -o ' ' -*/ diff --git a/ops.h b/ops.h new file mode 120000 index 0000000..caaf4a4 --- /dev/null +++ b/ops.h @@ -0,0 +1 @@ +qbe/ops.h \ No newline at end of file