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:
parent
e897df33e6
commit
b29d5ac7b1
17 changed files with 10348 additions and 0 deletions
185
sys/src/cmd/7a/a.h
Normal file
185
sys/src/cmd/7a/a.h
Normal 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
878
sys/src/cmd/7a/a.y
Normal 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
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
19
sys/src/cmd/7a/mkfile
Normal 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
517
sys/src/cmd/7c/7.out.h
Normal 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
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
358
sys/src/cmd/7c/gc.h
Normal 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
329
sys/src/cmd/7c/list.c
Normal 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
81
sys/src/cmd/7c/machcap.c
Normal 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
15
sys/src/cmd/7c/mkenam
Normal 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
41
sys/src/cmd/7c/mkfile
Normal 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
609
sys/src/cmd/7c/mul.c
Normal 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
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
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
247
sys/src/cmd/7c/sgen.c
Normal 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
654
sys/src/cmd/7c/swt.c
Normal file
|
@ -0,0 +1,654 @@
|
|||
#include "gc.h"
|
||||
|
||||
void
|
||||
swit1(C1 *q, int nc, long def, Node *n)
|
||||
{
|
||||
Node tn;
|
||||
|
||||
regalloc(&tn, ®node, 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
1412
sys/src/cmd/7c/txt.c
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue