add arm64 c compiler and assembler (thanks charles forsyth)

this is the the initial sync of charles forsyths plan9 c
compiler suite from http://bitbucket.org/plan9-from-bell-labs/9-cc
at changeset version 54:65fb8bb56c59
This commit is contained in:
cinap_lenrek 2019-04-08 13:45:49 +02:00
parent e897df33e6
commit b29d5ac7b1
17 changed files with 10348 additions and 0 deletions

185
sys/src/cmd/7a/a.h Normal file
View file

@ -0,0 +1,185 @@
/*
* arm64
*/
#include <u.h>
#include <libc.h>
#include <bio.h>
#include "../7c/7.out.h"
typedef vlong int64;
#ifndef EXTERN
#define EXTERN extern
#endif
typedef struct Sym Sym;
typedef struct Gen Gen;
typedef struct Io Io;
typedef struct Hist Hist;
#define MAXALIGN 7
#define FPCHIP 1
#define NSYMB 8192
#define BUFSIZ 8192
#define HISTSZ 20
#define NINCLUDE 10
#define NHUNK 10000
#define EOF (-1)
#define IGN (-2)
#define GETC() ((--fi.c < 0)? filbuf(): *fi.p++ & 0xff)
#define NHASH 503
#define STRINGSZ 200
#define NMACRO 10
struct Sym
{
Sym* link;
char* macro;
long value;
ushort type;
char *name;
char sym;
};
#define S ((Sym*)0)
EXTERN struct
{
char* p;
int c;
} fi;
struct Io
{
Io* link;
char b[BUFSIZ];
char* p;
short c;
short f;
};
#define I ((Io*)0)
EXTERN struct
{
Sym* sym;
short type;
} h[NSYM];
struct Gen
{
Sym* sym;
int64 offset;
short type;
short reg;
short xreg;
short name;
short ext;
double dval;
char sval[NSNAME];
};
struct Hist
{
Hist* link;
char* name;
long line;
long offset;
};
#define H ((Hist*)0)
enum
{
CLAST,
CMACARG,
CMACRO,
CPREPROC,
};
EXTERN char debug[256];
EXTERN Sym* hash[NHASH];
EXTERN char* Dlist[30];
EXTERN int nDlist;
EXTERN Hist* ehist;
EXTERN int newflag;
EXTERN Hist* hist;
EXTERN char* hunk;
EXTERN char* include[NINCLUDE];
EXTERN Io* iofree;
EXTERN Io* ionext;
EXTERN Io* iostack;
EXTERN long lineno;
EXTERN int nerrors;
EXTERN long nhunk;
EXTERN int ninclude;
EXTERN Gen nullgen;
EXTERN char* outfile;
EXTERN int pass;
EXTERN char* pathname;
EXTERN long pc;
EXTERN int peekc;
EXTERN int sym;
EXTERN char symb[NSYMB];
EXTERN int thechar;
EXTERN char* thestring;
EXTERN long thunk;
EXTERN Biobuf obuf;
void* alloc(long);
void* allocn(void*, long, long);
void errorexit(void);
void pushio(void);
void newio(void);
void newfile(char*, int);
Sym* slookup(char*);
Sym* lookup(void);
void syminit(Sym*);
long yylex(void);
int getc(void);
int getnsc(void);
void unget(int);
int escchar(int);
void cinit(void);
void pinit(char*);
void cclean(void);
void outcode(int, Gen*, int, Gen*);
void outcodec(int, int, Gen*, int, Gen*);
void outcode4(int, Gen*, int, Gen*, Gen*);
void zname(char*, int, int);
void zaddr(Gen*, int);
void ieeedtod(Ieee*, double);
int filbuf(void);
Sym* getsym(void);
void domacro(void);
void macund(void);
void macdef(void);
void macexpand(Sym*, char*);
void macinc(void);
void maclin(void);
void macprag(void);
void macif(int);
void macend(void);
void outhist(void);
void dodefine(char*);
void prfile(long);
void linehist(char*, int);
void gethunk(void);
void yyerror(char*, ...);
int yyparse(void);
void setinclude(char*);
int assemble(char*);
/*
* system-dependent stuff from ../cc/compat.c
*/
enum /* keep in synch with ../cc/cc.h */
{
Plan9 = 1<<0,
Unix = 1<<1,
Windows = 1<<2,
};
int mywait(int*);
int mycreat(char*, int);
int systemtype(int);
int pathchar(void);
int myfork(void);
void* mysbrk(ulong);

878
sys/src/cmd/7a/a.y Normal file
View file

@ -0,0 +1,878 @@
%{
#include "a.h"
%}
%union
{
Sym *sym;
vlong lval;
double dval;
char sval[NSNAME];
Gen gen;
}
%left '|'
%left '^'
%left '&'
%left '<' '>'
%left '+' '-'
%left '*' '/' '%'
%token <lval> LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4 LTYPE5
%token <lval> LTYPE6 LTYPE7 LTYPE8 LTYPE9 LTYPEA
%token <lval> LTYPEB LTYPEC LTYPED LTYPEE LTYPEF
%token <lval> LTYPEG LTYPEH LTYPEI LTYPEJ LTYPEK
%token <lval> LTYPEL LTYPEM LTYPEN LTYPEO LTYPEP LTYPEQ
%token <lval> LTYPER LTYPES LTYPET LTYPEU LTYPEV LTYPEW LTYPEX LTYPEY LTYPEZ
%token <lval> LMOVK LDMB LSTXR
%token <lval> LCONST LSP LSB LFP LPC
%token <lval> LR LREG LF LFREG LV LVREG LC LCREG LFCR LFCSEL
%token <lval> LCOND LS LAT LEXT LSPR LSPREG LVTYPE
%token <dval> LFCONST
%token <sval> LSCONST
%token <sym> LNAME LLAB LVAR
%type <lval> con expr pointer offset sreg spreg
%type <lval> scon indexreg vset vreglist
%type <gen> gen rel reg freg vreg shift fcon frcon extreg vlane vgen
%type <gen> imm ximm name oreg nireg ioreg imsr spr cond sysarg
%%
prog:
| prog line
line:
LLAB ':'
{
if($1->value != pc)
yyerror("redeclaration of %s", $1->name);
$1->value = pc;
}
line
| LNAME ':'
{
$1->type = LLAB;
$1->value = pc;
}
line
| LNAME '=' expr ';'
{
$1->type = LVAR;
$1->value = $3;
}
| LVAR '=' expr ';'
{
if($1->value != $3)
yyerror("redeclaration of %s", $1->name);
$1->value = $3;
}
| ';'
| inst ';'
| error ';'
inst:
/*
* ERET
*/
LTYPE0 comma
{
outcode($1, &nullgen, NREG, &nullgen);
}
/*
* ADD
*/
| LTYPE1 imsr ',' spreg ',' reg
{
outcode($1, &$2, $4, &$6);
}
| LTYPE1 imsr ',' spreg ','
{
outcode($1, &$2, $4, &nullgen);
}
| LTYPE1 imsr ',' reg
{
outcode($1, &$2, NREG, &$4);
}
/*
* CLS
*/
| LTYPE2 imsr ',' reg
{
outcode($1, &$2, NREG, &$4);
}
/*
* MOV
*/
| LTYPE3 gen ',' gen
{
outcode($1, &$2, NREG, &$4);
}
/*
* MOVK
*/
| LMOVK imm ',' reg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVK imm '<' '<' con ',' reg
{
Gen g;
g = nullgen;
g.type = D_CONST;
g.offset = $5;
outcode4($1, &$2, NREG, &g, &$7);
}
/*
* B/BL
*/
| LTYPE4 comma rel
{
outcode($1, &nullgen, NREG, &$3);
}
| LTYPE4 comma nireg
{
outcode($1, &nullgen, NREG, &$3);
}
/*
* BEQ
*/
| LTYPE5 comma rel
{
outcode($1, &nullgen, NREG, &$3);
}
/*
* SVC
*/
| LTYPE6 comma gen
{
outcode($1, &nullgen, NREG, &$3);
}
| LTYPE6
{
outcode($1, &nullgen, NREG, &nullgen);
}
/*
* CMP
*/
| LTYPE7 imsr ',' spreg comma
{
outcode($1, &$2, $4, &nullgen);
}
/*
* CBZ
*/
| LTYPE8 reg ',' rel
{
outcode($1, &$2, NREG, &$4);
}
/*
* CSET
*/
| LTYPER cond ',' reg
{
outcode($1, &$2, NREG, &$4);
}
/*
* CSEL/CINC/CNEG/CINV
*/
| LTYPES cond ',' reg ',' reg ',' reg
{
outcode4($1, &$2, $6.reg, &$4, &$8);
}
| LTYPES cond ',' reg ',' reg
{
outcode($1, &$2, $4.reg, &$6);
}
/*
* TBZ
*/
| LTYPET imm ',' reg ',' rel
{
outcode($1, &$2, $4.reg, &$6);
}
/*
* CCMN
*/
| LTYPEU cond ',' imsr ',' reg ',' imm comma
{
outcode4($1, &$2, $6.reg, &$4, &$8);
}
/*
* ADR
*/
| LTYPEV rel ',' reg
{
outcode($1, &$2, NREG, &$4);
}
| LTYPEV '$' name ',' reg
{
outcode($1, &$3, NREG, &$5);
}
/*
* BFM/BFI
*/
| LTYPEY imm ',' imm ',' spreg ',' reg
{
outcode4($1, &$2, $6, &$4, &$8);
}
/*
* EXTR
*/
| LTYPEP imm ',' reg ',' spreg ',' reg
{
outcode4($1, &$2, $6, &$4, &$8);
}
/*
* RET/RETURN
*/
| LTYPEA comma
{
outcode($1, &nullgen, NREG, &nullgen);
}
| LTYPEA reg
{
outcode($1, &nullgen, NREG, &$2);
}
/*
* NOP
*/
| LTYPEQ comma
{
outcode($1, &nullgen, NREG, &nullgen);
}
| LTYPEQ reg comma
{
outcode($1, &$2, NREG, &nullgen);
}
| LTYPEQ freg comma
{
outcode($1, &$2, NREG, &nullgen);
}
| LTYPEQ ',' reg
{
outcode($1, &nullgen, NREG, &$3);
}
| LTYPEQ ',' freg
{
outcode($1, &nullgen, NREG, &$3);
}
/*
* TEXT/GLOBL
*/
| LTYPEB name ',' imm
{
outcode($1, &$2, NREG, &$4);
}
| LTYPEB name ',' con ',' imm
{
outcode($1, &$2, $4, &$6);
}
/*
* DATA
*/
| LTYPEC name '/' con ',' ximm
{
outcode($1, &$2, $4, &$6);
}
/*
* CASE
*/
| LTYPED reg ',' reg
{
outcode($1, &$2, NREG, &$4);
}
/*
* word
*/
| LTYPEH comma ximm
{
outcode($1, &nullgen, NREG, &$3);
}
/*
* floating-point
*/
| LTYPEI freg ',' freg
{
outcode($1, &$2, NREG, &$4);
}
/*
* FADDD
*/
| LTYPEK frcon ',' freg
{
outcode($1, &$2, NREG, &$4);
}
| LTYPEK frcon ',' freg ',' freg
{
outcode($1, &$2, $4.reg, &$6);
}
/*
* FCMP
*/
| LTYPEL frcon ',' freg comma
{
outcode($1, &$2, $4.reg, &nullgen);
}
/*
* FCCMP
*/
| LTYPEF cond ',' freg ',' freg ',' imm comma
{
outcode4($1, &$2, $6.reg, &$4, &$8);
}
/*
* FMULA
*/
| LTYPE9 freg ',' freg ', ' freg ',' freg comma
{
outcode4($1, &$2, $4.reg, &$6, &$8);
}
/*
* FCSEL
*/
| LFCSEL cond ',' freg ',' freg ',' freg
{
outcode4($1, &$2, $6.reg, &$4, &$8);
}
/*
* SIMD
*/
| LTYPEW vgen ',' vgen
{
outcode($1, &$2, NREG, &$4);
}
| LTYPEW vgen ',' vgen ',' vgen
{
outcode($1, &$2, $4.reg, &$6);
}
/*
* MOVP/MOVNP
*/
| LTYPEJ gen ',' sreg ',' gen
{
outcode($1, &$2, $4, &$6);
}
/*
* MADD Rn,Rm,Ra,Rd
*/
| LTYPEM reg ',' reg ',' sreg ',' reg
{
outcode4($1, &$2, $6, &$4, &$8);
}
/*
* SYS/SYSL
*/
| LTYPEN sysarg
{
outcode($1, &$2, NREG, &nullgen);
}
| LTYPEN reg ',' sysarg
{
outcode($1, &$4, $2.reg, &nullgen);
}
| LTYPEO sysarg ',' reg
{
outcode($1, &$2, NREG, &$4);
}
/*
* DMB, HINT
*/
| LDMB imm
{
outcode($1, &$2, NREG, &nullgen);
}
/*
* STXR
*/
| LSTXR reg ',' gen ',' sreg
{
outcode($1, &$2, $6, &$4);
}
/*
* END
*/
| LTYPEE comma
{
outcode($1, &nullgen, NREG, &nullgen);
}
cond:
LCOND
{
$$ = nullgen;
$$.type = D_COND;
$$.reg = $1;
}
comma:
| ',' comma
sysarg:
con ',' con ',' con ',' con
{
$$ = nullgen;
$$.type = D_CONST;
$$.offset = SYSARG4($1, $3, $5, $7);
}
| imm
rel:
con '(' LPC ')'
{
$$ = nullgen;
$$.type = D_BRANCH;
$$.offset = $1 + pc;
}
| LNAME offset
{
$$ = nullgen;
if(pass == 2)
yyerror("undefined label: %s", $1->name);
$$.type = D_BRANCH;
$$.sym = $1;
$$.offset = $2;
}
| LLAB offset
{
$$ = nullgen;
$$.type = D_BRANCH;
$$.sym = $1;
$$.offset = $1->value + $2;
}
ximm: '$' con
{
$$ = nullgen;
$$.type = D_CONST;
$$.offset = $2;
}
| '$' oreg
{
$$ = $2;
$$.type = D_CONST;
}
| '$' '*' '$' oreg
{
$$ = $4;
$$.type = D_OCONST;
}
| '$' LSCONST
{
$$ = nullgen;
$$.type = D_SCONST;
memmove($$.sval, $2, sizeof($$.sval));
}
| fcon
fcon:
'$' LFCONST
{
$$ = nullgen;
$$.type = D_FCONST;
$$.dval = $2;
}
| '$' '-' LFCONST
{
$$ = nullgen;
$$.type = D_FCONST;
$$.dval = -$3;
}
gen:
reg
| ximm
| LFCR
{
$$ = nullgen;
$$.type = D_SPR;
$$.offset = $1;
}
| con
{
$$ = nullgen;
$$.type = D_OREG;
$$.offset = $1;
}
| oreg
| freg
| vreg
| spr
nireg:
'(' sreg ')'
{
$$ = nullgen;
$$.type = D_OREG;
$$.reg = $2;
$$.offset = 0;
}
| name
{
$$ = $1;
if($1.name != D_EXTERN && $1.name != D_STATIC) {
}
}
oreg:
name
| name '(' sreg ')'
{
$$ = $1;
$$.type = D_OREG;
$$.reg = $3;
}
| ioreg
ioreg:
'(' sreg ')'
{
$$ = nullgen;
$$.type = D_OREG;
$$.reg = $2;
$$.offset = 0;
}
| con '(' sreg ')'
{
$$ = nullgen;
$$.type = D_OREG;
$$.reg = $3;
$$.offset = $1;
}
| con '(' sreg ')' '!'
{
$$ = nullgen;
$$.type = D_XPRE;
$$.reg = $3;
$$.offset = $1;
}
| '(' sreg ')' con '!'
{
$$.type = D_XPOST;
$$.offset = $2;
}
| '(' sreg ')' '(' indexreg ')'
{
$$ = nullgen;
$$.type = D_ROFF;
$$.reg = $2;
$$.xreg = $5 & 0x1f;
$$.offset = $5;
}
| '(' sreg ')' '[' indexreg ']'
{
$$ = nullgen;
$$.type = D_ROFF;
$$.reg = $2;
$$.xreg = $5 & 0x1f;
$$.offset = $5 | (1<<16);
}
imsr:
imm
| shift
| extreg
imm: '$' con
{
$$ = nullgen;
$$.type = D_CONST;
$$.offset = $2;
}
reg:
sreg
{
$$ = nullgen;
$$.type = D_REG;
$$.reg = $1;
}
| LSP
{
$$ = nullgen;
$$.type = D_SP;
$$.reg = REGSP;
}
shift:
sreg '<' '<' scon
{
$$ = nullgen;
$$.type = D_SHIFT;
$$.offset = ($1 << 16) | ($4 << 10) | (0 << 22);
}
| sreg '>' '>' scon
{
$$ = nullgen;
$$.type = D_SHIFT;
$$.offset = (($1&0x1F) << 16) | ($4 << 10) | (1 << 22);
}
| sreg '-' '>' scon
{
$$ = nullgen;
$$.type = D_SHIFT;
$$.offset = ($1 << 16) | ($4 << 10) | (2 << 22);
}
| sreg LAT '>' scon
{
$$ = nullgen;
$$.type = D_SHIFT;
$$.offset = ($1 << 16) | ($4 << 10) | (3 << 22);
}
extreg:
sreg
{
$$ = nullgen;
$$.type = D_REG;
$$.reg = $1;
}
| sreg LEXT
{
$$ = nullgen;
$$.type = D_EXTREG;
$$.reg = $1;
$$.offset = ($1 << 16) | ($2 << 13);
}
| sreg LEXT '<' '<' con
{
if($5 < 0 || $5 > 4)
yyerror("shift value out of range");
$$ = nullgen;
$$.type = D_EXTREG;
$$.reg = $1;
$$.offset = ($1 << 16) | ($2 << 13) | ($5 << 10);
}
indexreg:
sreg
{
$$ = (3 << 8) | $1;
}
| sreg LEXT
{
$$ = ($2 << 8) | $1;
}
scon:
con
{
if($$ < 0 || $$ >= 64)
yyerror("shift value out of range");
$$ = $1&0x3F;
}
sreg:
LREG
| LR '(' expr ')'
{
if($3 < 0 || $3 >= NREG)
print("register value out of range\n");
$$ = $3;
}
spreg:
sreg
| LSP
{
$$ = REGSP;
}
spr:
LSPREG
{
$$ = nullgen;
$$.type = D_SPR;
$$.offset = $1;
}
| LSPR '(' con ')'
{
$$ = nullgen;
$$.type = $1;
$$.offset = $3;
}
frcon:
freg
| fcon
freg:
LFREG
{
$$ = nullgen;
$$.type = D_FREG;
$$.reg = $1;
}
| LF '(' con ')'
{
$$ = nullgen;
$$.type = D_FREG;
$$.reg = $3;
}
vgen:
oreg
| vreg
| vlane
| vset
{
$$ = nullgen;
$$.type = D_VSET;
$$.offset = $1;
}
vlane:
vreg '[' con ']'
{
$$.type = D_VLANE;
$$.offset = $3;
}
| vset '[' con ']'
{
$$.type = D_VLANE;
$$.offset = $3;
}
vset:
'{' vreglist '}'
{
$$ = $2;
}
vreglist:
vreg
{
$$ = 1 << $1.reg;
}
| vreg '-' vreg
{
int i;
$$=0;
for(i=$1.reg; i<=$3.reg; i++)
$$ |= 1<<i;
for(i=$3.reg; i<=$1.reg; i++)
$$ |= 1<<i;
}
| vreg comma vreglist
{
$$ = (1<<$1.reg) | $3;
}
vreg:
LVREG
{
$$ = nullgen;
$$.type = D_VREG;
$$.reg = $1;
/* TO DO: slice */
}
| LV '(' con ')'
{
$$ = nullgen;
$$.type = D_VREG;
$$.reg = $3;
}
name:
con '(' pointer ')'
{
$$ = nullgen;
$$.type = D_OREG;
$$.name = $3;
$$.sym = S;
$$.offset = $1;
}
| LNAME offset '(' pointer ')'
{
$$ = nullgen;
$$.type = D_OREG;
$$.name = $4;
$$.sym = $1;
$$.offset = $2;
}
| LNAME '<' '>' offset '(' LSB ')'
{
$$ = nullgen;
$$.type = D_OREG;
$$.name = D_STATIC;
$$.sym = $1;
$$.offset = $4;
}
offset:
{
$$ = 0;
}
| '+' con
{
$$ = $2;
}
| '-' con
{
$$ = -$2;
}
pointer:
LSB
| LSP
| LFP
con:
LCONST
| LVAR
{
$$ = $1->value;
}
| '-' con
{
$$ = -$2;
}
| '+' con
{
$$ = $2;
}
| '~' con
{
$$ = ~$2;
}
| '(' expr ')'
{
$$ = $2;
}
expr:
con
| expr '+' expr
{
$$ = $1 + $3;
}
| expr '-' expr
{
$$ = $1 - $3;
}
| expr '*' expr
{
$$ = $1 * $3;
}
| expr '/' expr
{
$$ = $1 / $3;
}
| expr '%' expr
{
$$ = $1 % $3;
}
| expr '<' '<' expr
{
$$ = $1 << $4;
}
| expr '>' '>' expr
{
$$ = $1 >> $4;
}
| expr '&' expr
{
$$ = $1 & $3;
}
| expr '^' expr
{
$$ = $1 ^ $3;
}
| expr '|' expr
{
$$ = $1 | $3;
}

1041
sys/src/cmd/7a/lex.c Normal file

File diff suppressed because it is too large Load diff

19
sys/src/cmd/7a/mkfile Normal file
View file

@ -0,0 +1,19 @@
</$objtype/mkfile
TARG=7a
OFILES=\
y.tab.$O\
lex.$O\
HFILES=\
../7c/7.out.h\
y.tab.h\
a.h\
YFILES=a.y\
BIN=/$objtype/bin
< /sys/src/cmd/mkone
YFLAGS=-D1 -d
lex.$O: ../cc/macbody ../cc/lexbody

517
sys/src/cmd/7c/7.out.h Normal file
View file

@ -0,0 +1,517 @@
/*
* arm64
*/
#define NSNAME 8
#define NSYM 50
#define NREG 32
#define NOPROF (1<<0)
#define DUPOK (1<<1)
#define REGRET 0
#define REGARG 0
/* R1 to R7 are potential parameter/return registers */
#define REGIRL 8 /* indirect result location (TO DO) */
/* compiler allocates R9 up as temps */
/* compiler allocates register variables R10 up */
#define REGMIN 9
#define REGMAX 15
#define REGIP0 16
#define REGIP1 17
#define REGTMP REGIP1
/* compiler allocates external registers R27 down */
#define REGEXT 27
#define REGSB 28
#define REGFP 29
#define REGLINK 30
#define REGSP 31
#define REGZERO 31
#define NFREG 32
#define FREGRET 0
#define FREGMIN 7
#define FREGEXT 15
/* compiler allocates register variables F0 up */
/* compiler allocates external registers F15 down */
enum as
{
AXXX,
AADC,
AADCS,
AADCSW,
AADCW,
AADD,
AADDS,
AADDSW,
AADDW,
AADR,
AADRP,
AAND,
AANDS,
AANDSW,
AANDW,
AASR,
AASRW,
AAT,
AB,
ABFI,
ABFIW,
ABFM,
ABFMW,
ABFXIL,
ABFXILW,
ABIC,
ABICS,
ABICSW,
ABICW,
ABL,
ABRK,
ACBNZ,
ACBNZW,
ACBZ,
ACBZW,
ACCMN,
ACCMNW,
ACCMP,
ACCMPW,
ACINC,
ACINCW,
ACINV,
ACINVW,
ACLREX,
ACLS,
ACLSW,
ACLZ,
ACLZW,
ACMN,
ACMNW,
ACMP,
ACMPW,
ACNEG,
ACNEGW,
ACRC32B,
ACRC32CB,
ACRC32CH,
ACRC32CW,
ACRC32CX,
ACRC32H,
ACRC32W,
ACRC32X,
ACSEL,
ACSELW,
ACSET,
ACSETM,
ACSETMW,
ACSETW,
ACSINC,
ACSINCW,
ACSINV,
ACSINVW,
ACSNEG,
ACSNEGW,
ADC,
ADCPS1,
ADCPS2,
ADCPS3,
ADMB,
ADRPS,
ADSB,
AEON,
AEONW,
AEOR,
AEORW,
AERET,
AEXTR,
AEXTRW,
AHINT,
AHLT,
AHVC,
AIC,
AISB,
ALDAR,
ALDARB,
ALDARH,
ALDARW,
ALDAXP,
ALDAXPW,
ALDAXR,
ALDAXRB,
ALDAXRH,
ALDAXRW,
ALDXR,
ALDXRB,
ALDXRH,
ALDXRW,
ALDXP,
ALDXPW,
ALSL,
ALSLW,
ALSR,
ALSRW,
AMADD,
AMADDW,
AMNEG,
AMNEGW,
AMOVK,
AMOVKW,
AMOVN,
AMOVNW,
AMOVZ,
AMOVZW,
AMRS,
AMSR,
AMSUB,
AMSUBW,
AMUL,
AMULW,
AMVN,
AMVNW,
ANEG,
ANEGS,
ANEGSW,
ANEGW,
ANGC,
ANGCS,
ANGCSW,
ANGCW,
ANOP,
AORN,
AORNW,
AORR,
AORRW,
APRFM,
APRFUM,
ARBIT,
ARBITW,
AREM,
AREMW,
ARET,
AREV,
AREV16,
AREV16W,
AREV32,
AREVW,
AROR,
ARORW,
ASBC,
ASBCS,
ASBCSW,
ASBCW,
ASBFIZ,
ASBFIZW,
ASBFM,
ASBFMW,
ASBFX,
ASBFXW,
ASDIV,
ASDIVW,
ASEV,
ASEVL,
ASMADDL,
ASMC,
ASMNEGL,
ASMSUBL,
ASMULH,
ASMULL,
ASTXR,
ASTXRB,
ASTXRH,
ASTXP,
ASTXPW,
ASTXRW,
ASTLP,
ASTLPW,
ASTLR,
ASTLRB,
ASTLRH,
ASTLRW,
ASTLXP,
ASTLXPW,
ASTLXR,
ASTLXRB,
ASTLXRH,
ASTLXRW,
ASUB,
ASUBS,
ASUBSW,
ASUBW,
ASVC,
ASXTB,
ASXTBW,
ASXTH,
ASXTHW,
ASXTW,
ASYS,
ASYSL,
ATBNZ,
ATBZ,
ATLBI,
ATST,
ATSTW,
AUBFIZ,
AUBFIZW,
AUBFM,
AUBFMW,
AUBFX,
AUBFXW,
AUDIV,
AUDIVW,
AUMADDL,
AUMNEGL,
AUMSUBL,
AUMULH,
AUMULL,
AUREM,
AUREMW,
AUXTB,
AUXTH,
AUXTW,
AUXTBW,
AUXTHW,
AWFE,
AWFI,
AYIELD,
AMOVB,
AMOVBU,
AMOVH,
AMOVHU,
AMOVW,
AMOVWU,
AMOV,
AMOVNP,
AMOVNPW,
AMOVP,
AMOVPD,
AMOVPQ,
AMOVPS,
AMOVPSW,
AMOVPW,
/*
* Do not reorder or fragment the conditional branch
* opcodes, or the predication code will break
*/
ABEQ,
ABNE,
ABCS,
ABHS,
ABCC,
ABLO,
ABMI,
ABPL,
ABVS,
ABVC,
ABHI,
ABLS,
ABGE,
ABLT,
ABGT,
ABLE,
AFABSD,
AFABSS,
AFADDD,
AFADDS,
AFCCMPD,
AFCCMPED,
AFCCMPS,
AFCCMPES,
AFCMPD,
AFCMPED,
AFCMPES,
AFCMPS,
AFCVTSD,
AFCVTDS,
AFCVTZSD,
AFCVTZSDW,
AFCVTZSS,
AFCVTZSSW,
AFCVTZUD,
AFCVTZUDW,
AFCVTZUS,
AFCVTZUSW,
AFDIVD,
AFDIVS,
AFMOVD,
AFMOVS,
AFMULD,
AFMULS,
AFNEGD,
AFNEGS,
AFSQRTD,
AFSQRTS,
AFSUBD,
AFSUBS,
ASCVTFD,
ASCVTFS,
ASCVTFWD,
ASCVTFWS,
AUCVTFD,
AUCVTFS,
AUCVTFWD,
AUCVTFWS,
ATEXT,
ADATA,
AGLOBL,
AHISTORY,
ANAME,
AWORD,
ADYNT,
AINIT,
ABCASE,
ACASE,
ADWORD,
ASIGNAME,
AGOK,
ARETURN,
AEND,
AFCSELS,
AFCSELD,
AFMAXS,
AFMINS,
AFMAXD,
AFMIND,
AFMAXNMS,
AFMAXNMD,
AFNMULS,
AFNMULD,
AFRINTNS,
AFRINTND,
AFRINTPS,
AFRINTPD,
AFRINTMS,
AFRINTMD,
AFRINTZS,
AFRINTZD,
AFRINTAS,
AFRINTAD,
AFRINTXS,
AFRINTXD,
AFRINTIS,
AFRINTID,
AFMADDS,
AFMADDD,
AFMSUBS,
AFMSUBD,
AFNMADDS,
AFNMADDD,
AFNMSUBS,
AFNMSUBD,
AFMINNMS,
AFMINNMD,
AFCVTDH,
AFCVTHS,
AFCVTHD,
AFCVTSH,
AAESD,
AAESE,
AAESIMC,
AAESMC,
ASHA1C,
ASHA1H,
ASHA1M,
ASHA1P,
ASHA1SU0,
ASHA1SU1,
ASHA256H,
ASHA256H2,
ASHA256SU0,
ASHA256SU1,
ALAST,
};
/* form offset parameter to SYS; special register number */
#define SYSARG5(op0,op1,Cn,Cm,op2) ((op0)<<19|(op1)<<16|(Cn)<<12|(Cm)<<8|(op2)<<5)
#define SYSARG4(op1,Cn,Cm,op2) SYSARG5(0,op1,Cn,Cm,op2)
/* type/name */
enum
{
D_GOK = 0,
D_NONE,
/* name */
D_EXTERN,
D_STATIC,
D_AUTO,
D_PARAM,
/* type */
D_BRANCH,
D_OREG, /* offset(reg) */
D_XPRE, /* offset(reg)! - pre-indexed */
D_XPOST, /* (reg)offset! - post-indexed */
D_CONST, /* 32-bit constant */
D_DCONST, /* 64-bit constant */
D_FCONST, /* floating-point constant */
D_SCONST, /* short string constant */
D_REG, /* Rn = Wn or Xn depending on op */
D_SP, /* distinguish REGSP from REGZERO */
D_FREG, /* Fn = Sn or Dn depending on op */
D_VREG, /* Vn = SIMD register */
D_SPR, /* special processor register */
D_FILE,
D_OCONST, /* absolute address constant (unused) */
D_FILE1,
D_SHIFT, /* Rm{, ashift #imm} */
D_PAIR, /* pair of gprs */
D_ADDR, /* address constant (dynamic loading) */
D_ADRP, /* pc-relative addressing, page */
D_ADRLO, /* low-order 12 bits of external reference */
D_EXTREG, /* Rm{, ext #imm} */
D_ROFF, /* register offset Rn+ext(Rm)<<s */
D_COND, /* condition EQ, NE, etc */
D_VLANE, /* Vn lane */
D_VSET, /* set of Vn */
/* offset iff type is D_SPR */
D_DAIF = SYSARG5(3,3,4,2,1),
D_NZCV = SYSARG5(3,3,4,2,0),
D_FPSR = SYSARG5(3,3,4,4,1),
D_FPCR = SYSARG5(3,3,4,4,0),
D_SPSR_EL1 = SYSARG5(3,0,4,0,0),
D_ELR_EL1 = SYSARG5(3,0,4,0,1),
D_SPSR_EL2 = SYSARG5(3,4,4,0,0),
D_ELR_EL2 = SYSARG5(3,4,4,0,1),
// D_SPSR_EL3 = SYSARG5(3,x,4,x,x),
// D_ELR_EL3 = SYSARG5(3,x,4,x,x),
// D_LR_EL0 = SYSARG5(3,x,4,x,x),
D_CurrentEL = SYSARG5(3,0,4,2,2),
D_SP_EL0 = SYSARG5(3,0,4,1,0),
// D_SP_EL1 = SYSARG5(3,x,4,x,x),
// D_SP_EL2 = SYSARG5(3,x,4,x,x),
D_SPSel = SYSARG5(3,0,4,2,0),
// D_SPSR_abt = SYSARG5(3,x,4,x,x),
// D_SPSR_fiq = SYSARG5(3,x,4,x,x),
// D_SPSR_ieq = SYSARG5(3,x,4,x,x),
// D_SPSR_und = SYSARG5(3,x,4,x,x),
D_DAIFSet = (1<<30)|0,
D_DAIFClr = (1<<30)|1
};
/*
* this is the ranlib header
*/
#define SYMDEF "__.SYMDEF"
/*
* this is the simulated IEEE floating point
*/
typedef struct Ieee Ieee;
struct Ieee
{
long l; /* contains ls-man 0xffffffff */
long h; /* contains sign 0x80000000
exp 0x7ff00000
ms-man 0x000fffff */
};

1256
sys/src/cmd/7c/cgen.c Normal file

File diff suppressed because it is too large Load diff

358
sys/src/cmd/7c/gc.h Normal file
View file

@ -0,0 +1,358 @@
#include "../cc/cc.h"
#include "../7c/7.out.h"
/*
* 7c/arm64
* Arm64
*/
#define SZ_CHAR 1
#define SZ_SHORT 2
#define SZ_INT 4
#define SZ_LONG 4
#define SZ_IND 8
#define SZ_FLOAT 4
#define SZ_VLONG 8
#define SZ_DOUBLE 8
#define FNX 100
#define BTRUE 0x1000
typedef struct Adr Adr;
typedef struct Prog Prog;
typedef struct Case Case;
typedef struct C1 C1;
typedef struct Multab Multab;
typedef struct Hintab Hintab;
typedef struct Var Var;
typedef struct Reg Reg;
typedef struct Rgn Rgn;
struct Adr
{
vlong offset;
double dval;
char sval[NSNAME];
Ieee ieee;
Sym* sym;
char type;
char reg;
char name;
char etype;
};
#define A ((Adr*)0)
#define INDEXED 9
struct Prog
{
Adr from;
Adr to;
Prog* link;
long lineno;
ushort as;
char reg;
uchar scond;
};
#define P ((Prog*)0)
struct Case
{
Case* link;
vlong val;
long label;
char def;
char isv;
};
#define C ((Case*)0)
struct C1
{
vlong val;
long label;
};
struct Multab
{
long val;
char code[20];
};
struct Hintab
{
ushort val;
char hint[10];
};
struct Var
{
vlong offset;
Sym* sym;
char name;
char etype;
};
struct Reg
{
long pc;
long rpo; /* reverse post ordering */
Bits set;
Bits use1;
Bits use2;
Bits refbehind;
Bits refahead;
Bits calbehind;
Bits calahead;
Bits regdiff;
Bits act;
long regu;
long loop; /* could be shorter */
Reg* log5;
long active;
Reg* p1;
Reg* p2;
Reg* p2link;
Reg* s1;
Reg* s2;
Reg* link;
Prog* prog;
};
#define R ((Reg*)0)
#define NRGN 1000 /* was 600; raised for paranoia.c */
struct Rgn
{
Reg* enter;
short cost;
short varno;
short regno;
};
EXTERN long breakpc;
EXTERN long nbreak;
EXTERN Case* cases;
EXTERN Node constnode;
EXTERN Node fconstnode;
EXTERN Node vconstnode;
EXTERN long continpc;
EXTERN long curarg;
EXTERN long cursafe;
EXTERN Prog* firstp;
EXTERN Prog* lastp;
EXTERN long maxargsafe;
EXTERN int mnstring;
EXTERN Multab multab[20];
EXTERN int hintabsize;
EXTERN Node* nodrat;
EXTERN Node* nodret;
EXTERN Node* nodsafe;
EXTERN long nrathole;
EXTERN long nstring;
EXTERN Prog* p;
EXTERN long pc;
EXTERN Node regnode;
EXTERN Node qregnode;
EXTERN char string[NSNAME];
EXTERN Sym* symrathole;
EXTERN Node znode;
EXTERN Prog zprog;
EXTERN char reg[NREG+NFREG];
EXTERN long exregoffset;
EXTERN long exfregoffset;
EXTERN int suppress;
EXTERN uchar typechlpv[NTYPE];
#define BLOAD(r) band(bnot(r->refbehind), r->refahead)
#define BSTORE(r) band(bnot(r->calbehind), r->calahead)
#define LOAD(r) (~r->refbehind.b[z] & r->refahead.b[z])
#define STORE(r) (~r->calbehind.b[z] & r->calahead.b[z])
#define bset(a,n) ((a).b[(n)/32]&(1L<<(n)%32))
#define CLOAD 4
#define CREF 5
#define CINF 1000
#define LOOP 3
EXTERN Rgn region[NRGN];
EXTERN Rgn* rgp;
EXTERN int nregion;
EXTERN int nvar;
EXTERN Bits externs;
EXTERN Bits params;
EXTERN Bits consts;
EXTERN Bits addrs;
EXTERN long regbits;
EXTERN long exregbits;
EXTERN int change;
EXTERN Reg* firstr;
EXTERN Reg* lastr;
EXTERN Reg zreg;
EXTERN Reg* freer;
EXTERN Var var[NVAR];
EXTERN long* idom;
EXTERN Reg** rpo2r;
EXTERN long maxnr;
extern char* anames[];
extern Hintab hintab[];
/*
* sgen.c
*/
void codgen(Node*, Node*);
void gen(Node*);
void noretval(int);
void usedset(Node*, int);
void xcom(Node*);
int bcomplex(Node*, Node*);
/*
* cgen.c
*/
int castup(Type*, Type*);
void cgen(Node*, Node*);
void cgenrel(Node*, Node*, int);
int cond(int);
int hardconst(Node*);
void reglcgen(Node*, Node*, Node*);
void layout(Node*, Node*, int, int, Node*);
void lcgen(Node*, Node*);
void bcgen(Node*, int);
void boolgen(Node*, int, Node*);
void sugen(Node*, Node*, long);
void layout(Node*, Node*, int, int, Node*);
/*
* txt.c
*/
void ginit(void);
void gclean(void);
void nextpc(void);
void gargs(Node*, Node*, Node*);
void garg1(Node*, Node*, Node*, int, Node**);
Node* nodconst(long);
Node* nod32const(vlong);
Node* nodfconst(double);
void nodreg(Node*, Node*, int);
void regret(Node*, Node*);
void regalloc(Node*, Node*, Node*);
void regfree(Node*);
void regialloc(Node*, Node*, Node*);
void regsalloc(Node*, Node*);
void regaalloc1(Node*, Node*);
void regaalloc(Node*, Node*);
void regind(Node*, Node*);
void gprep(Node*, Node*);
void raddr(Node*, Prog*);
void naddr(Node*, Adr*);
void gmovm(Node*, Node*, int);
void gmove(Node*, Node*);
void gmover(Node*, Node*);
void gins(int a, Node*, Node*);
void gopcode(int, Node*, Node*, Node*);
int samaddr(Node*, Node*);
void gbranch(int);
void patch(Prog*, long);
int sconst(Node*);
int sval(long);
void gpseudo(int, Sym*, Node*);
int usableoffset(Node*, vlong, Node*);
/*
* swt.c
*/
int swcmp(void*, void*);
void doswit(Node*);
void swit1(C1*, int, long, Node*);
void swit2(C1*, int, long, Node*, Node*);
void casf(void);
void bitload(Node*, Node*, Node*, Node*, Node*);
void bitstore(Node*, Node*, Node*, Node*, Node*);
long outstring(char*, long);
int mulcon(Node*, Node*);
Multab* mulcon0(long);
void nullwarn(Node*, Node*);
void gextern(Sym*, Node*, long, long);
void outcode(void);
void ieeedtod(Ieee*, double);
/*
* list
*/
void listinit(void);
int Pconv(Fmt*);
int Aconv(Fmt*);
int Dconv(Fmt*);
int Sconv(Fmt*);
int Nconv(Fmt*);
int Bconv(Fmt*);
int Rconv(Fmt*);
/*
* reg.c
*/
Reg* rega(void);
int rcmp(void*, void*);
void regopt(Prog*);
void addmove(Reg*, int, int, int);
Bits mkvar(Adr*, int);
void prop(Reg*, Bits, Bits);
void loopit(Reg*, long);
void synch(Reg*, Bits);
ulong allreg(ulong, Rgn*);
void paint1(Reg*, int);
ulong paint2(Reg*, int);
void paint3(Reg*, int, long, int);
void addreg(Adr*, int);
/*
* peep.c
*/
void peep(void);
void excise(Reg*);
Reg* uniqp(Reg*);
Reg* uniqs(Reg*);
int regtyp(Adr*);
int regzer(Adr*);
int anyvar(Adr*);
int subprop(Reg*);
int copyprop(Reg*);
int shiftprop(Reg*);
void constprop(Adr*, Adr*, Reg*);
int copy1(Adr*, Adr*, Reg*, int);
int copyu(Prog*, Adr*, Adr*);
int copyas(Adr*, Adr*);
int copyau(Adr*, Adr*);
int copyau1(Prog*, Adr*);
int copysub(Adr*, Adr*, Adr*, int);
int copysub1(Prog*, Adr*, Adr*, int);
long RtoB(int);
long FtoB(int);
int BtoR(long);
int BtoF(long);
void predicate(void);
int isbranch(Prog *);
int predicable(Prog *p);
int modifiescpsr(Prog *p);
#pragma varargck type "A" int
#pragma varargck type "A" uint
#pragma varargck type "B" Bits
#pragma varargck type "D" Adr*
#pragma varargck type "N" Adr*
#pragma varargck type "R" Adr*
#pragma varargck type "P" Prog*
#pragma varargck type "S" char*

329
sys/src/cmd/7c/list.c Normal file
View file

@ -0,0 +1,329 @@
#define EXTERN
#include "gc.h"
void
listinit(void)
{
fmtinstall('A', Aconv);
fmtinstall('P', Pconv);
fmtinstall('S', Sconv);
fmtinstall('N', Nconv);
fmtinstall('B', Bconv);
fmtinstall('D', Dconv);
fmtinstall('R', Rconv);
}
int
Bconv(Fmt *fp)
{
char str[STRINGSZ], ss[STRINGSZ], *s;
Bits bits;
int i;
str[0] = 0;
bits = va_arg(fp->args, Bits);
while(bany(&bits)) {
i = bnum(bits);
if(str[0])
strcat(str, " ");
if(var[i].sym == S) {
snprint(ss, sizeof(ss), "$%lld", var[i].offset);
s = ss;
} else
s = var[i].sym->name;
if(strlen(str) + strlen(s) + 1 >= STRINGSZ)
break;
strcat(str, s);
bits.b[i/32] &= ~(1L << (i%32));
}
return fmtstrcpy(fp, str);
}
static char *conds[] = {
".EQ", ".NE", ".CS", ".CC",
".MI", ".PL", ".VS", ".VC",
".HI", ".LS", ".GE", ".LT",
".GT", ".LE", "", ".NV",
};
int
Pconv(Fmt *fp)
{
char str[STRINGSZ];
Prog *p;
int a;
p = va_arg(fp->args, Prog*);
a = p->as;
if(a == ADATA)
snprint(str, sizeof(str), " %A %D/%d,%D", a, &p->from, p->reg, &p->to);
else
if(p->as == ATEXT)
snprint(str, sizeof(str), " %A %D,%d,%D", a, &p->from, p->reg, &p->to);
else
if(p->reg == NREG)
snprint(str, sizeof(str), " %A %D,%D", a, &p->from, &p->to);
else
if(p->from.type != D_FREG)
snprint(str, sizeof(str), " %A %D,R%d,%D", a, &p->from, p->reg, &p->to);
else
snprint(str, sizeof(str), " %A %D,F%d,%D", a, &p->from, p->reg, &p->to);
return fmtstrcpy(fp, str);
}
int
Aconv(Fmt *fp)
{
char *s;
int a;
a = va_arg(fp->args, int);
s = "???";
if(a >= AXXX && a < ALAST)
s = anames[a];
return fmtstrcpy(fp, s);
}
int
Dconv(Fmt *fp)
{
char str[STRINGSZ];
Adr *a;
char *op;
int v;
static char *extop[] = {".UB", ".UH", ".UW", ".UX", ".SB", ".SH", ".SW", ".SX"};
a = va_arg(fp->args, Adr*);
switch(a->type) {
default:
snprint(str, sizeof(str), "GOK-type(%d)", a->type);
break;
case D_NONE:
str[0] = 0;
if(a->name != D_NONE || a->reg != NREG || a->sym != S)
snprint(str, sizeof(str), "%N(R%d)(NONE)", a, a->reg);
break;
case D_CONST:
if(a->reg != NREG)
snprint(str, sizeof(str), "$%N(R%d)", a, a->reg);
else
snprint(str, sizeof(str), "$%N", a);
break;
case D_SHIFT:
v = a->offset;
op = "<<>>->@>" + (((v>>5) & 3) << 1);
if(v & (1<<4))
snprint(str, sizeof(str), "R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15);
else
snprint(str, sizeof(str), "R%d%c%c%d", v&15, op[0], op[1], (v>>7)&31);
if(a->reg != NREG)
sprint(str+strlen(str), "(R%d)", a->reg);
break;
case D_OREG:
if(a->reg != NREG)
snprint(str, sizeof(str), "%N(R%d)", a, a->reg);
else
snprint(str, sizeof(str), "%N", a);
break;
case D_XPRE:
if(a->reg != NREG)
snprint(str, sizeof(str), "%N(R%d)!", a, a->reg);
else
snprint(str, sizeof(str), "%N!", a);
break;
case D_XPOST:
if(a->reg != NREG)
snprint(str, sizeof(str), "(R%d)%N!", a->reg, a);
else
snprint(str, sizeof(str), "%N!", a);
break;
case D_EXTREG:
v = a->offset;
if(v & (7<<10))
snprint(str, sizeof(str), "R%d%s<<%d", (v>>16)&31, extop[(v>>13)&7], (v>>10)&7);
else
snprint(str, sizeof(str), "R%d%s", (v>>16)&31, extop[(v>>13)&7]);
break;
case D_REG:
snprint(str, sizeof(str), "R%d", a->reg);
if(a->name != D_NONE || a->sym != S)
snprint(str, sizeof(str), "%N(R%d)(REG)", a, a->reg);
break;
case D_SP:
if(a->name != D_NONE || a->sym != S)
snprint(str, sizeof(str), "%N(R%d)(REG)", a, a->reg);
else
strcpy(str, "SP");
break;
case D_FREG:
snprint(str, sizeof(str), "F%d", a->reg);
if(a->name != D_NONE || a->sym != S)
snprint(str, sizeof(str), "%N(R%d)(REG)", a, a->reg);
break;
case D_SPR:
switch((ulong)a->offset){
case D_FPSR:
sprint(str, "FPSR");
break;
case D_FPCR:
sprint(str, "FPCR");
break;
case D_NZCV:
sprint(str, "NZCV");
break;
default:
sprint(str, "SPR(%#llux)", a->offset);
break;
}
if(a->name != D_NONE || a->sym != S)
snprint(str, sizeof(str), "%N(SPR(%lld))(REG)", a, a->offset);
break;
case D_BRANCH:
snprint(str, sizeof(str), "%lld(PC)", a->offset-pc);
break;
case D_FCONST:
snprint(str, sizeof(str), "$%.17e", a->dval);
break;
case D_SCONST:
snprint(str, sizeof(str), "$\"%S\"", a->sval);
break;
}
return fmtstrcpy(fp, str);
}
int
Rconv(Fmt *fp)
{
char str[STRINGSZ], *p, *e;
Adr *a;
int i, v;
a = va_arg(fp->args, Adr*);
snprint(str, sizeof(str), "GOK-reglist");
switch(a->type) {
case D_CONST:
if(a->reg != NREG)
break;
if(a->sym != S)
break;
v = a->offset;
p = str;
e = str+sizeof(str);
for(i=0; i<NREG; i++) {
if(v & (1<<i)) {
if(p == str)
p = seprint(p, e, "[R%d", i);
else
p = seprint(p, e, ",R%d", i);
}
}
seprint(p, e, "]");
}
return fmtstrcpy(fp, str);
}
int
Sconv(Fmt *fp)
{
int i, c;
char str[STRINGSZ], *p, *a;
a = va_arg(fp->args, char*);
p = str;
for(i=0; i<NSNAME; i++) {
c = a[i] & 0xff;
if(c >= 'a' && c <= 'z' ||
c >= 'A' && c <= 'Z' ||
c >= '0' && c <= '9' ||
c == ' ' || c == '%') {
*p++ = c;
continue;
}
*p++ = '\\';
switch(c) {
case 0:
*p++ = 'z';
continue;
case '\\':
case '"':
*p++ = c;
continue;
case '\n':
*p++ = 'n';
continue;
case '\t':
*p++ = 't';
continue;
case '\r':
*p++ = 'r';
continue;
case '\f':
*p++ = 'f';
continue;
}
*p++ = (c>>6) + '0';
*p++ = ((c>>3) & 7) + '0';
*p++ = (c & 7) + '0';
}
*p = 0;
return fmtstrcpy(fp, str);
}
int
Nconv(Fmt *fp)
{
char str[STRINGSZ];
Adr *a;
Sym *s;
a = va_arg(fp->args, Adr*);
s = a->sym;
if(s == S) {
snprint(str, sizeof(str), "%lld", a->offset);
goto out;
}
switch(a->name) {
default:
snprint(str, sizeof(str), "GOK-name(%d)", a->name);
break;
case D_NONE:
snprint(str, sizeof(str), "%lld", a->offset);
break;
case D_EXTERN:
snprint(str, sizeof(str), "%s+%lld(SB)", s->name, a->offset);
break;
case D_STATIC:
snprint(str, sizeof(str), "%s<>+%lld(SB)", s->name, a->offset);
break;
case D_AUTO:
snprint(str, sizeof(str), "%s-%lld(SP)", s->name, -a->offset);
break;
case D_PARAM:
snprint(str, sizeof(str), "%s+%lld(FP)", s->name, a->offset);
break;
}
out:
return fmtstrcpy(fp, str);
}

81
sys/src/cmd/7c/machcap.c Normal file
View file

@ -0,0 +1,81 @@
#include "gc.h"
int
machcap(Node *n)
{
if(n == Z)
return 1; /* test */
switch(n->op) {
case OMUL:
case OLMUL:
case OASMUL:
case OASLMUL:
if(typechlv[n->type->etype])
return 1;
break;
case OADD:
case OAND:
case OOR:
case OSUB:
case OXOR:
case OASHL:
case OLSHR:
case OASHR:
if(typechlv[n->left->type->etype])
return 1;
break;
case OCAST:
return 1;
case OCOND:
case OCOMMA:
case OLIST:
case OANDAND:
case OOROR:
case ONOT:
return 1;
case OASADD:
case OASSUB:
case OASAND:
case OASOR:
case OASXOR:
return 1;
case OASASHL:
case OASASHR:
case OASLSHR:
return 1;
case OPOSTINC:
case OPOSTDEC:
case OPREINC:
case OPREDEC:
return 1;
case OEQ:
case ONE:
case OLE:
case OGT:
case OLT:
case OGE:
case OHI:
case OHS:
case OLO:
case OLS:
return 1;
case ONEG:
if(typechlv[n->left->type->etype])
return 1;
break;
case OCOM:
break;
}
return 0;
}

15
sys/src/cmd/7c/mkenam Normal file
View file

@ -0,0 +1,15 @@
ed - ../7c/7.out.h <<'!'
v/^ A/d
,s/^ A/ "/
g/ .*$/s///
,s/,*$/",/
1i
char* anames[] =
{
.
$a
};
.
w enam.c
Q
!

41
sys/src/cmd/7c/mkfile Normal file
View file

@ -0,0 +1,41 @@
</$objtype/mkfile
TARG=7c
OFILES=\
cgen.$O\
enam.$O\
list.$O\
machcap.$O\
mul.$O\
peep.$O\
pgen.$O\
pswt.$O\
reg.$O\
sgen.$O\
swt.$O\
txt.$O\
HFILES=\
gc.h\
7.out.h\
../cc/cc.h\
LIB=../cc/cc.a$O
BIN=/$objtype/bin
</sys/src/cmd/mkone
$LIB: ../cc/cc.h
cd ../cc
mk install
%.$O: ../cc/%.c
$CC $CFLAGS ../cc/$stem.c
t:V: $O.out
$O.out -S t
$LD -o t.out t.$O
t.out
enam.c: 7.out.h
rc mkenam

609
sys/src/cmd/7c/mul.c Normal file
View file

@ -0,0 +1,609 @@
#include "gc.h"
/*
* code sequences for multiply by constant.
* [a-l][0-3]
* lsl $(A-'a'),r0,r1
* [+][0-7]
* add r0,r1,r2
* [-][0-7]
* sub r0,r1,r2
*/
static int maxmulops = 3; /* max # of ops to replace mul with */
static int multabp;
static long mulval;
static char* mulcp;
static long valmax;
static int shmax;
static int docode(char *hp, char *cp, int r0, int r1);
static int gen1(int len);
static int gen2(int len, long r1);
static int gen3(int len, long r0, long r1, int flag);
enum
{
SR1 = 1<<0, /* r1 has been shifted */
SR0 = 1<<1, /* r0 has been shifted */
UR1 = 1<<2, /* r1 has not been used */
UR0 = 1<<3, /* r0 has not been used */
};
Multab*
mulcon0(long v)
{
int a1, a2, g;
Multab *m, *m1;
char hint[10];
if(v < 0)
v = -v;
/*
* look in cache
*/
m = multab;
for(g=0; g<nelem(multab); g++) {
if(m->val == v) {
if(m->code[0] == 0)
return 0;
return m;
}
m++;
}
/*
* select a spot in cache to overwrite
*/
multabp++;
if(multabp < 0 || multabp >= nelem(multab))
multabp = 0;
m = multab+multabp;
m->val = v;
mulval = v;
/*
* look in execption hint table
*/
a1 = 0;
a2 = hintabsize;
for(;;) {
if(a1 >= a2)
goto no;
g = (a2 + a1)/2;
if(v < hintab[g].val) {
a2 = g;
continue;
}
if(v > hintab[g].val) {
a1 = g+1;
continue;
}
break;
}
if(docode(hintab[g].hint, m->code, 1, 0))
return m;
print("multiply table failure %ld\n", v);
m->code[0] = 0;
return 0;
no:
/*
* try to search
*/
hint[0] = 0;
for(g=1; g<=maxmulops; g++) {
if(g >= maxmulops && v >= 65535)
break;
mulcp = hint+g;
*mulcp = 0;
if(gen1(g)) {
if(docode(hint, m->code, 1, 0))
return m;
print("multiply table failure %ld\n", v);
break;
}
}
/*
* try a recur followed by a shift
*/
g = 0;
while(!(v & 1)) {
g++;
v >>= 1;
}
if(g) {
m1 = mulcon0(v);
if(m1) {
strcpy(m->code, m1->code);
sprint(strchr(m->code, 0), "%c0", g+'a');
return m;
}
}
m->code[0] = 0;
return 0;
}
static int
docode(char *hp, char *cp, int r0, int r1)
{
int c, i;
c = *hp++;
*cp = c;
cp += 2;
switch(c) {
default:
c -= 'a';
if(c < 1 || c >= 30)
break;
for(i=0; i<4; i++) {
switch(i) {
case 0:
if(docode(hp, cp, r0<<c, r1))
goto out;
break;
case 1:
if(docode(hp, cp, r1<<c, r1))
goto out;
break;
case 2:
if(docode(hp, cp, r0, r0<<c))
goto out;
break;
case 3:
if(docode(hp, cp, r0, r1<<c))
goto out;
break;
}
}
break;
case '+':
for(i=0; i<8; i++) {
cp[-1] = i+'0';
switch(i) {
case 1:
if(docode(hp, cp, r0+r1, r1))
goto out;
break;
case 5:
if(docode(hp, cp, r0, r0+r1))
goto out;
break;
}
}
break;
case '-':
for(i=0; i<8; i++) {
cp[-1] = i+'0';
switch(i) {
case 1:
if(docode(hp, cp, r0-r1, r1))
goto out;
break;
case 2:
if(docode(hp, cp, r1-r0, r1))
goto out;
break;
case 5:
if(docode(hp, cp, r0, r0-r1))
goto out;
break;
case 6:
if(docode(hp, cp, r0, r1-r0))
goto out;
break;
}
}
break;
case 0:
if(r0 == mulval)
return 1;
}
return 0;
out:
cp[-1] = i+'0';
return 1;
}
static int
gen1(int len)
{
int i;
for(shmax=1; shmax<30; shmax++) {
valmax = 1<<shmax;
if(valmax >= mulval)
break;
}
if(mulval == 1)
return 1;
len--;
for(i=1; i<=shmax; i++)
if(gen2(len, 1<<i)) {
*--mulcp = 'a'+i;
return 1;
}
return 0;
}
static int
gen2(int len, long r1)
{
int i;
if(len <= 0) {
if(r1 == mulval)
return 1;
return 0;
}
len--;
if(len == 0)
goto calcr0;
if(gen3(len, r1, r1+1, UR1)) {
i = '+';
goto out;
}
if(gen3(len, r1-1, r1, UR0)) {
i = '-';
goto out;
}
if(gen3(len, 1, r1+1, UR1)) {
i = '+';
goto out;
}
if(gen3(len, 1, r1-1, UR1)) {
i = '-';
goto out;
}
return 0;
calcr0:
if(mulval == r1+1) {
i = '+';
goto out;
}
if(mulval == r1-1) {
i = '-';
goto out;
}
return 0;
out:
*--mulcp = i;
return 1;
}
static int
gen3(int len, long r0, long r1, int flag)
{
int i, f1, f2;
long x;
if(r0 <= 0 ||
r0 >= r1 ||
r1 > valmax)
return 0;
len--;
if(len == 0)
goto calcr0;
if(!(flag & UR1)) {
f1 = UR1|SR1;
for(i=1; i<=shmax; i++) {
x = r0<<i;
if(x > valmax)
break;
if(gen3(len, r0, x, f1)) {
i += 'a';
goto out;
}
}
}
if(!(flag & UR0)) {
f1 = UR1|SR1;
for(i=1; i<=shmax; i++) {
x = r1<<i;
if(x > valmax)
break;
if(gen3(len, r1, x, f1)) {
i += 'a';
goto out;
}
}
}
if(!(flag & SR1)) {
f1 = UR1|SR1|(flag&UR0);
for(i=1; i<=shmax; i++) {
x = r1<<i;
if(x > valmax)
break;
if(gen3(len, r0, x, f1)) {
i += 'a';
goto out;
}
}
}
if(!(flag & SR0)) {
f1 = UR0|SR0|(flag&(SR1|UR1));
f2 = UR1|SR1;
if(flag & UR1)
f2 |= UR0;
if(flag & SR1)
f2 |= SR0;
for(i=1; i<=shmax; i++) {
x = r0<<i;
if(x > valmax)
break;
if(x > r1) {
if(gen3(len, r1, x, f2)) {
i += 'a';
goto out;
}
} else
if(gen3(len, x, r1, f1)) {
i += 'a';
goto out;
}
}
}
x = r1+r0;
if(gen3(len, r0, x, UR1)) {
i = '+';
goto out;
}
if(gen3(len, r1, x, UR1)) {
i = '+';
goto out;
}
x = r1-r0;
if(gen3(len, x, r1, UR0)) {
i = '-';
goto out;
}
if(x > r0) {
if(gen3(len, r0, x, UR1)) {
i = '-';
goto out;
}
} else
if(gen3(len, x, r0, UR0)) {
i = '-';
goto out;
}
return 0;
calcr0:
f1 = flag & (UR0|UR1);
if(f1 == UR1) {
for(i=1; i<=shmax; i++) {
x = r1<<i;
if(x >= mulval) {
if(x == mulval) {
i += 'a';
goto out;
}
break;
}
}
}
if(mulval == r1+r0) {
i = '+';
goto out;
}
if(mulval == r1-r0) {
i = '-';
goto out;
}
return 0;
out:
*--mulcp = i;
return 1;
}
/*
* hint table has numbers that
* the search algorithm fails on.
* <1000:
* all numbers
* <5000:
* ÷ by 5
* <10000:
* ÷ by 50
* <65536:
* ÷ by 250
*/
Hintab hintab[] =
{
683, "b++d+e+",
687, "b+e++e-",
691, "b++d+e+",
731, "b++d+e+",
811, "b++d+i+",
821, "b++e+e+",
843, "b+d++e+",
851, "b+f-+e-",
853, "b++e+e+",
877, "c++++g-",
933, "b+c++g-",
981, "c-+e-d+",
1375, "b+c+b+h-",
1675, "d+b++h+",
2425, "c++f-e+",
2675, "c+d++f-",
2750, "b+d-b+h-",
2775, "c-+g-e-",
3125, "b++e+g+",
3275, "b+c+g+e+",
3350, "c++++i+",
3475, "c-+e-f-",
3525, "c-+d+g-",
3625, "c-+e-j+",
3675, "b+d+d+e+",
3725, "b+d-+h+",
3925, "b+d+f-d-",
4275, "b+g++e+",
4325, "b+h-+d+",
4425, "b+b+g-j-",
4525, "b+d-d+f+",
4675, "c++d-g+",
4775, "b+d+b+g-",
4825, "c+c-+i-",
4850, "c++++i-",
4925, "b++e-g-",
4975, "c+f++e-",
5500, "b+g-c+d+",
6700, "d+b++i+",
9700, "d++++j-",
11000, "b+f-c-h-",
11750, "b+d+g+j-",
12500, "b+c+e-k+",
13250, "b+d+e-f+",
13750, "b+h-c-d+",
14250, "b+g-c+e-",
14500, "c+f+j-d-",
14750, "d-g--f+",
16750, "b+e-d-n+",
17750, "c+h-b+e+",
18250, "d+b+h-d+",
18750, "b+g-++f+",
19250, "b+e+b+h+",
19750, "b++h--f-",
20250, "b+e-l-c+",
20750, "c++bi+e-",
21250, "b+i+l+c+",
22000, "b+e+d-g-",
22250, "b+d-h+k-",
22750, "b+d-e-g+",
23250, "b+c+h+e-",
23500, "b+g-c-g-",
23750, "b+g-b+h-",
24250, "c++g+m-",
24750, "b+e+e+j-",
25000, "b++dh+g+",
25250, "b+e+d-g-",
25750, "b+e+b+j+",
26250, "b+h+c+e+",
26500, "b+h+c+g+",
26750, "b+d+e+g-",
27250, "b+e+e+f+",
27500, "c-i-c-d+",
27750, "b+bd++j+",
28250, "d-d-++i-",
28500, "c+c-h-e-",
29000, "b+g-d-f+",
29500, "c+h+++e-",
29750, "b+g+f-c+",
30250, "b+f-g-c+",
33500, "c-f-d-n+",
33750, "b+d-b+j-",
34250, "c+e+++i+",
35250, "e+b+d+k+",
35500, "c+e+d-g-",
35750, "c+i-++e+",
36250, "b+bh-d+e+",
36500, "c+c-h-e-",
36750, "d+e--i+",
37250, "b+g+g+b+",
37500, "b+h-b+f+",
37750, "c+be++j-",
38500, "b+e+b+i+",
38750, "d+i-b+d+",
39250, "b+g-l-+d+",
39500, "b+g-c+g-",
39750, "b+bh-c+f-",
40250, "b+bf+d+g-",
40500, "b+g-c+g+",
40750, "c+b+i-e+",
41250, "d++bf+h+",
41500, "b+j+c+d-",
41750, "c+f+b+h-",
42500, "c+h++g+",
42750, "b+g+d-f-",
43250, "b+l-e+d-",
43750, "c+bd+h+f-",
44000, "b+f+g-d-",
44250, "b+d-g--f+",
44500, "c+e+c+h+",
44750, "b+e+d-h-",
45250, "b++g+j-g+",
45500, "c+d+e-g+",
45750, "b+d-h-e-",
46250, "c+bd++j+",
46500, "b+d-c-j-",
46750, "e-e-b+g-",
47000, "b+c+d-j-",
47250, "b+e+e-g-",
47500, "b+g-c-h-",
47750, "b+f-c+h-",
48250, "d--h+n-",
48500, "b+c-g+m-",
48750, "b+e+e-g+",
49500, "c-f+e+j-",
49750, "c+c+g++f-",
50000, "b+e+e+k+",
50250, "b++i++g+",
50500, "c+g+f-i+",
50750, "b+e+d+k-",
51500, "b+i+c-f+",
51750, "b+bd+g-e-",
52250, "b+d+g-j+",
52500, "c+c+f+g+",
52750, "b+c+e+i+",
53000, "b+i+c+g+",
53500, "c+g+g-n+",
53750, "b+j+d-c+",
54250, "b+d-g-j-",
54500, "c-f+e+f+",
54750, "b+f-+c+g+",
55000, "b+g-d-g-",
55250, "b+e+e+g+",
55500, "b+cd++j+",
55750, "b+bh-d-f-",
56250, "c+d-b+j-",
56500, "c+d+c+i+",
56750, "b+e+d++h-",
57000, "b+d+g-f+",
57250, "b+f-m+d-",
57750, "b+i+c+e-",
58000, "b+e+d+h+",
58250, "c+b+g+g+",
58750, "d-e-j--e+",
59000, "d-i-+e+",
59250, "e--h-m+",
59500, "c+c-h+f-",
59750, "b+bh-e+i-",
60250, "b+bh-e-e-",
60500, "c+c-g-g-",
60750, "b+e-l-e-",
61250, "b+g-g-c+",
61750, "b+g-c+g+",
62250, "f--+c-i-",
62750, "e+f--+g+",
64750, "b+f+d+p-",
};
int hintabsize = nelem(hintab);

1546
sys/src/cmd/7c/peep.c Normal file

File diff suppressed because it is too large Load diff

1160
sys/src/cmd/7c/reg.c Normal file

File diff suppressed because it is too large Load diff

247
sys/src/cmd/7c/sgen.c Normal file
View file

@ -0,0 +1,247 @@
#include "gc.h"
void
noretval(int n)
{
if(n & 1) {
gins(ANOP, Z, Z);
p->to.type = D_REG;
p->to.reg = REGRET;
}
if(n & 2) {
gins(ANOP, Z, Z);
p->to.type = D_FREG;
p->to.reg = FREGRET;
}
}
/*
* calculate addressability as follows
* CONST ==> 20 $value
* NAME ==> 10 name
* REGISTER ==> 11 register
* INDREG ==> 12 *[(reg)+offset]
* &10 ==> 2 $name
* ADD(2, 20) ==> 2 $name+offset
* ADD(3, 20) ==> 3 $(reg)+offset
* &12 ==> 3 $(reg)+offset
* *11 ==> 11 ??
* *2 ==> 10 name
* *3 ==> 12 *(reg)+offset
* calculate complexity (number of registers)
*/
void
xcom(Node *n)
{
Node *l, *r;
int t;
if(n == Z)
return;
l = n->left;
r = n->right;
n->addable = 0;
n->complex = 0;
switch(n->op) {
case OCONST:
n->addable = 20;
return;
case OREGISTER:
n->addable = 11;
return;
case OINDREG:
n->addable = 12;
return;
case ONAME:
n->addable = 10;
return;
case OADDR:
xcom(l);
if(l->addable == 10)
n->addable = 2;
if(l->addable == 12)
n->addable = 3;
break;
case OIND:
xcom(l);
if(l->addable == 11)
n->addable = 12;
if(l->addable == 3)
n->addable = 12;
if(l->addable == 2)
n->addable = 10;
break;
case OADD:
xcom(l);
xcom(r);
if(l->addable == 20) {
if(r->addable == 2)
n->addable = 2;
if(r->addable == 3)
n->addable = 3;
}
if(r->addable == 20) {
if(l->addable == 2)
n->addable = 2;
if(l->addable == 3)
n->addable = 3;
}
break;
case OASMUL:
case OASLMUL:
xcom(l);
xcom(r);
t = vlog(r);
if(t >= 0) {
n->op = OASASHL;
r->vconst = t;
r->type = types[TINT];
}
break;
case OMUL:
case OLMUL:
xcom(l);
xcom(r);
t = vlog(r);
if(t >= 0) {
n->op = OASHL;
r->vconst = t;
r->type = types[TINT];
}
t = vlog(l);
if(t >= 0) {
n->op = OASHL;
n->left = r;
n->right = l;
r = l;
l = n->left;
r->vconst = t;
r->type = types[TINT];
simplifyshift(n);
}
break;
case OASLDIV:
xcom(l);
xcom(r);
t = vlog(r);
if(t >= 0) {
n->op = OASLSHR;
r->vconst = t;
r->type = types[TINT];
}
break;
case OLDIV:
xcom(l);
xcom(r);
t = vlog(r);
if(t >= 0) {
n->op = OLSHR;
r->vconst = t;
r->type = types[TINT];
simplifyshift(n);
}
break;
case OASLMOD:
xcom(l);
xcom(r);
t = vlog(r);
if(t >= 0) {
n->op = OASAND;
r->vconst--;
}
break;
case OLMOD:
xcom(l);
xcom(r);
t = vlog(r);
if(t >= 0) {
n->op = OAND;
r->vconst--;
}
break;
case OLSHR:
case OASHL:
case OASHR:
xcom(l);
xcom(r);
simplifyshift(n);
break;
default:
if(l != Z)
xcom(l);
if(r != Z)
xcom(r);
break;
}
if(n->addable >= 10)
return;
if(l != Z)
n->complex = l->complex;
if(r != Z) {
if(r->complex == n->complex)
n->complex = r->complex+1;
else
if(r->complex > n->complex)
n->complex = r->complex;
}
if(n->complex == 0)
n->complex++;
// if(com64(n))
// return;
switch(n->op) {
case OFUNC:
n->complex = FNX;
break;
case OEQ:
case ONE:
case OLE:
case OLT:
case OGE:
case OGT:
case OHI:
case OHS:
case OLO:
case OLS:
/*
* immediate operators, make const on right
*/
if(l->op == OCONST) {
n->left = r;
n->right = l;
n->op = invrel[relindex(n->op)];
}
break;
case OADD:
case OXOR:
case OAND:
case OOR:
/*
* immediate operators, make const on right
*/
if(l->op == OCONST) {
n->left = r;
n->right = l;
}
break;
}
}

654
sys/src/cmd/7c/swt.c Normal file
View file

@ -0,0 +1,654 @@
#include "gc.h"
void
swit1(C1 *q, int nc, long def, Node *n)
{
Node tn;
regalloc(&tn, &regnode, Z);
swit2(q, nc, def, n, &tn);
regfree(&tn);
}
void
swit2(C1 *q, int nc, long def, Node *n, Node *tn)
{
C1 *r;
int i;
long v;
Prog *sp;
if(nc >= 3) {
i = (q+nc-1)->val - (q+0)->val;
if(i > 0 && i < nc*2)
goto direct;
}
if(nc < 5) {
for(i=0; i<nc; i++) {
if(debug['K'])
print("case = %.8llux\n", q->val);
gopcode(OEQ, nodconst(q->val), n, Z);
patch(p, q->label);
q++;
}
gbranch(OGOTO);
patch(p, def);
return;
}
i = nc / 2;
r = q+i;
if(debug['K'])
print("case > %.8llux\n", r->val);
gopcode(OGT, nodconst(r->val), n, Z);
sp = p;
gopcode(OEQ, nodconst(r->val), n, Z); /* just gen the B.EQ */
patch(p, r->label);
swit2(q, i, def, n, tn);
if(debug['K'])
print("case < %.8llux\n", r->val);
patch(sp, pc);
swit2(r+1, nc-i-1, def, n, tn);
return;
direct:
v = q->val;
if(v != 0)
gopcode(OSUB, nodconst(v), Z, n);
gopcode(OHI, nodconst((q+nc-1)->val - v), n, Z);
patch(p, def);
gopcode(OCASE, n, Z, tn);
for(i=0; i<nc; i++) {
if(debug['K'])
print("case = %.8llux\n", q->val);
while(q->val != v) {
nextpc();
p->as = ABCASE;
patch(p, def);
v++;
}
nextpc();
p->as = ABCASE;
patch(p, q->label);
q++;
v++;
}
gbranch(OGOTO); /* so that regopt() won't be confused */
patch(p, def);
}
void
bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
{
int sh;
long v;
Node *l;
/*
* n1 gets adjusted/masked value
* n2 gets address of cell
* n3 gets contents of cell
*/
l = b->left;
if(n2 != Z) {
regalloc(n1, l, nn);
reglcgen(n2, l, Z);
regalloc(n3, l, Z);
gopcode(OAS, n2, Z, n3);
gopcode(OAS, n3, Z, n1);
} else {
regalloc(n1, l, nn);
cgen(l, n1);
}
if(b->type->shift == 0 && typeu[b->type->etype]) {
v = ~0 + (1L << b->type->nbits);
gopcode(OAND, nodconst(v), Z, n1);
} else {
sh = 32 - b->type->shift - b->type->nbits;
if(sh > 0)
gopcode(OASHL, nodconst(sh), Z, n1);
sh += b->type->shift;
if(sh > 0)
if(typeu[b->type->etype])
gopcode(OLSHR, nodconst(sh), Z, n1);
else
gopcode(OASHR, nodconst(sh), Z, n1);
}
}
void
bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
{
long v;
Node nod, *l;
int sh;
/*
* n1 has adjusted/masked value
* n2 has address of cell
* n3 has contents of cell
*/
l = b->left;
regalloc(&nod, l, Z);
v = ~0 + (1L << b->type->nbits);
gopcode(OAND, nodconst(v), Z, n1);
gopcode(OAS, n1, Z, &nod);
if(nn != Z)
gopcode(OAS, n1, Z, nn);
sh = b->type->shift;
if(sh > 0)
gopcode(OASHL, nodconst(sh), Z, &nod);
v <<= sh;
gopcode(OAND, nodconst(~v), Z, n3);
gopcode(OOR, n3, Z, &nod);
gopcode(OAS, &nod, Z, n2);
regfree(&nod);
regfree(n1);
regfree(n2);
regfree(n3);
}
long
outstring(char *s, long n)
{
long r;
if(suppress)
return nstring;
r = nstring;
while(n) {
string[mnstring] = *s++;
mnstring++;
nstring++;
if(mnstring >= NSNAME) {
gpseudo(ADATA, symstring, nodconst(0L));
p->from.offset += nstring - NSNAME;
p->reg = NSNAME;
p->to.type = D_SCONST;
memmove(p->to.sval, string, NSNAME);
mnstring = 0;
}
n--;
}
return r;
}
int
mulcon(Node *n, Node *nn)
{
Node *l, *r, nod1, nod2;
Multab *m;
long v, vs;
int o;
char code[sizeof(m->code)+2], *p;
if(typefd[n->type->etype])
return 0;
l = n->left;
r = n->right;
if(l->op == OCONST) {
l = r;
r = n->left;
}
if(r->op != OCONST)
return 0;
v = convvtox(r->vconst, n->type->etype);
if(v != r->vconst) {
if(debug['M'])
print("%L multiply conv: %lld\n", n->lineno, r->vconst);
return 0;
}
m = mulcon0(v);
if(!m) {
if(debug['M'])
print("%L multiply table: %lld\n", n->lineno, r->vconst);
return 0;
}
if(debug['M'] && debug['v'])
print("%L multiply: %ld\n", n->lineno, v);
memmove(code, m->code, sizeof(m->code));
code[sizeof(m->code)] = 0;
p = code;
if(p[1] == 'i')
p += 2;
regalloc(&nod1, n, nn);
cgen(l, &nod1);
vs = v;
regalloc(&nod2, n, Z);
loop:
switch(*p) {
case 0:
regfree(&nod2);
if(vs < 0) {
gopcode(OAS, &nod1, Z, &nod1);
gopcode(ONEG, &nod1, Z, nn);
} else
gopcode(OAS, &nod1, Z, nn);
regfree(&nod1);
return 1;
case '+':
o = OADD;
goto addsub;
case '-':
o = OSUB;
addsub: /* number is r,n,l */
v = p[1] - '0';
r = &nod1;
if(v&4)
r = &nod2;
n = &nod1;
if(v&2)
n = &nod2;
l = &nod1;
if(v&1)
l = &nod2;
gopcode(o, l, n, r);
break;
default: /* op is shiftcount, number is r,l */
v = p[1] - '0';
r = &nod1;
if(v&2)
r = &nod2;
l = &nod1;
if(v&1)
l = &nod2;
v = *p - 'a';
if(v < 0 || v >= 32) {
diag(n, "mulcon unknown op: %c%c", p[0], p[1]);
break;
}
gopcode(OASHL, nodconst(v), l, r);
break;
}
p += 2;
goto loop;
}
void
gextern(Sym *s, Node *a, long o, long w)
{
if(a->op == OCONST && typev[a->type->etype]) {
if(align(0, types[TCHAR], Aarg1)) /* isbigendian */
gpseudo(ADATA, s, nod32const(a->vconst>>32));
else
gpseudo(ADATA, s, nod32const(a->vconst));
p->from.offset += o;
p->reg = 4;
if(align(0, types[TCHAR], Aarg1)) /* isbigendian */
gpseudo(ADATA, s, nod32const(a->vconst));
else
gpseudo(ADATA, s, nod32const(a->vconst>>32));
p->from.offset += o + 4;
p->reg = 4;
return;
}
gpseudo(ADATA, s, a);
p->from.offset += o;
p->reg = w;
if(p->to.type == D_OREG)
p->to.type = D_CONST;
}
void zname(Biobuf*, Sym*, int);
char* zaddr(char*, Adr*, int);
void zwrite(Biobuf*, Prog*, int, int);
void outhist(Biobuf*);
void
zwrite(Biobuf *b, Prog *p, int sf, int st)
{
char bf[100], *bp;
long l;
bf[0] = p->as;
bf[1] = p->as>>8;
bf[2] = p->reg;
l = p->lineno;
bf[3] = l;
bf[4] = l>>8;
bf[5] = l>>16;
bf[6] = l>>24;
bp = zaddr(bf+7, &p->from, sf);
bp = zaddr(bp, &p->to, st);
Bwrite(b, bf, bp-bf);
}
void
outcode(void)
{
struct { Sym *sym; short type; } h[NSYM];
Prog *p;
Sym *s;
int sf, st, t, sym;
if(debug['S']) {
for(p = firstp; p != P; p = p->link)
if(p->as != ADATA && p->as != AGLOBL)
pc--;
for(p = firstp; p != P; p = p->link) {
print("%P\n", p);
if(p->as != ADATA && p->as != AGLOBL)
pc++;
}
}
outhist(&outbuf);
for(sym=0; sym<NSYM; sym++) {
h[sym].sym = S;
h[sym].type = 0;
}
sym = 1;
for(p = firstp; p != P; p = p->link) {
jackpot:
sf = 0;
s = p->from.sym;
while(s != S) {
sf = s->sym;
if(sf < 0 || sf >= NSYM)
sf = 0;
t = p->from.name;
if(h[sf].type == t)
if(h[sf].sym == s)
break;
s->sym = sym;
zname(&outbuf, s, t);
h[sym].sym = s;
h[sym].type = t;
sf = sym;
sym++;
if(sym >= NSYM)
sym = 1;
break;
}
st = 0;
s = p->to.sym;
while(s != S) {
st = s->sym;
if(st < 0 || st >= NSYM)
st = 0;
t = p->to.name;
if(h[st].type == t)
if(h[st].sym == s)
break;
s->sym = sym;
zname(&outbuf, s, t);
h[sym].sym = s;
h[sym].type = t;
st = sym;
sym++;
if(sym >= NSYM)
sym = 1;
if(st == sf)
goto jackpot;
break;
}
zwrite(&outbuf, p, sf, st);
}
firstp = P;
lastp = P;
}
void
outhist(Biobuf *b)
{
Hist *h;
char *p, *q, *op, c;
Prog pg;
int n;
pg = zprog;
pg.as = AHISTORY;
c = pathchar();
for(h = hist; h != H; h = h->link) {
p = h->name;
op = 0;
/* on windows skip drive specifier in pathname */
if(systemtype(Windows) && p && p[1] == ':'){
p += 2;
c = *p;
}
if(p && p[0] != c && h->offset == 0 && pathname){
/* on windows skip drive specifier in pathname */
if(systemtype(Windows) && pathname[1] == ':') {
op = p;
p = pathname+2;
c = *p;
} else if(pathname[0] == c){
op = p;
p = pathname;
}
}
while(p) {
q = utfrune(p, c);
if(q) {
n = q-p;
if(n == 0){
n = 1; /* leading "/" */
*p = '/'; /* don't emit "\" on windows */
}
q++;
} else {
n = strlen(p);
q = 0;
}
if(n) {
Bputc(b, ANAME);
Bputc(b, ANAME>>8);
Bputc(b, D_FILE);
Bputc(b, 1);
Bputc(b, '<');
Bwrite(b, p, n);
Bputc(b, 0);
}
p = q;
if(p == 0 && op) {
p = op;
op = 0;
}
}
pg.lineno = h->line;
pg.to.type = zprog.to.type;
pg.to.offset = h->offset;
if(h->offset)
pg.to.type = D_CONST;
zwrite(b, &pg, 0, 0);
}
}
void
zname(Biobuf *b, Sym *s, int t)
{
char *n, bf[8];
ulong sig;
n = s->name;
if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){
sig = sign(s);
bf[0] = ASIGNAME;
bf[1] = ASIGNAME>>8;
bf[2] = sig;
bf[3] = sig>>8;
bf[4] = sig>>16;
bf[5] = sig>>24;
bf[6] = t;
bf[7] = s->sym;
Bwrite(b, bf, 8);
s->sig = SIGDONE;
}
else{
bf[0] = ANAME;
bf[1] = ANAME>>8;
bf[2] = t; /* type */
bf[3] = s->sym; /* sym */
Bwrite(b, bf, 4);
}
Bwrite(b, n, strlen(n)+1);
}
char*
zaddr(char *bp, Adr *a, int s)
{
long l;
Ieee e;
if(a->type == D_CONST){
l = a->offset;
if((vlong)l != a->offset)
a->type = D_DCONST;
}
bp[0] = a->type;
bp[1] = a->reg;
bp[2] = s;
bp[3] = a->name;
bp += 4;
switch(a->type) {
default:
diag(Z, "unknown type %d in zaddr", a->type);
case D_NONE:
case D_REG:
case D_SP:
case D_FREG:
case D_VREG:
break;
case D_PAIR:
*bp++ = a->offset;
break;
case D_OREG:
case D_XPRE:
case D_XPOST:
case D_CONST:
case D_BRANCH:
case D_SHIFT:
case D_EXTREG:
case D_SPR:
l = a->offset;
bp[0] = l;
bp[1] = l>>8;
bp[2] = l>>16;
bp[3] = l>>24;
bp += 4;
break;
case D_DCONST:
l = a->offset;
bp[0] = l;
bp[1] = l>>8;
bp[2] = l>>16;
bp[3] = l>>24;
bp += 4;
l = a->offset>>32;
bp[0] = l;
bp[1] = l>>8;
bp[2] = l>>16;
bp[3] = l>>24;
bp += 4;
break;
case D_SCONST:
memmove(bp, a->sval, NSNAME);
bp += NSNAME;
break;
case D_FCONST:
ieeedtod(&e, a->dval);
l = e.l;
bp[0] = l;
bp[1] = l>>8;
bp[2] = l>>16;
bp[3] = l>>24;
bp += 4;
l = e.h;
bp[0] = l;
bp[1] = l>>8;
bp[2] = l>>16;
bp[3] = l>>24;
bp += 4;
break;
}
return bp;
}
long
align(long i, Type *t, int op)
{
long o;
Type *v;
int w;
o = i;
w = 1;
switch(op) {
default:
diag(Z, "unknown align opcode %d", op);
break;
case Asu2: /* padding at end of a struct */
w = SZ_VLONG;
if(packflg)
w = packflg;
break;
case Ael1: /* initial align of struct element */
for(v=t; v->etype==TARRAY; v=v->link)
;
w = ewidth[v->etype];
if(w <= 0 || w >= SZ_VLONG)
w = SZ_VLONG;
if(packflg)
w = packflg;
break;
case Ael2: /* width of a struct element */
o += t->width;
break;
case Aarg0: /* initial passbyptr argument in arg list */
if(typesu[t->etype]) {
o = align(o, types[TIND], Aarg1);
o = align(o, types[TIND], Aarg2);
}
break;
case Aarg1: /* initial align of parameter */
w = ewidth[t->etype];
if(w <= 0 || w >= SZ_VLONG) {
w = SZ_VLONG;
break;
}
w = 1; /* little endian no adjustment */
break;
case Aarg2: /* width of a parameter */
o += t->width;
w = SZ_VLONG;
break;
case Aaut3: /* total align of automatic */
o = align(o, t, Ael2);
o = align(o, t, Ael1);
w = SZ_LONG; /* because of a pun in cc/dcl.c:contig() */
break;
}
o = round(o, w);
if(debug['A'])
print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
return o;
}
long
maxround(long max, long v)
{
v = round(v, SZ_VLONG);
if(v > max)
return v;
return max;
}

1412
sys/src/cmd/7c/txt.c Normal file

File diff suppressed because it is too large Load diff