add extra functions and clean up makefile and readme

This commit is contained in:
sam 2024-10-29 22:41:07 +13:00
parent d2f4528797
commit a5741ed125
6 changed files with 44 additions and 814 deletions

View file

@ -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)

8
README
View file

@ -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.

585
all.h
View file

@ -1,585 +0,0 @@
#include <assert.h>
#include <inttypes.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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 *);

1
all.h Symbolic link
View file

@ -0,0 +1 @@
qbe/all.h

View file

@ -1,5 +1,4 @@
#include "libqbe.h"
#include <ctype.h>
#include <getopt.h>
#include <stdio.h>
@ -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));
}

View file

@ -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

199
ops.h
View file

@ -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 ' '
*/

1
ops.h Symbolic link
View file

@ -0,0 +1 @@
qbe/ops.h