crypto/elliptic: add Name field to CurveParams struct (https://golang.org/cl/2133)
crypto/tls: change default minimum version to TLS 1.0. (https://golang.org/cl/1791)
encoding/base64: add unpadded encodings (https://golang.org/cl/1511)
-log: add global Output function (https://golang.org/cl/2686)
+log: add SetOutput functions (https://golang.org/cl/2686, https://golang.org/cl/3023)
net/http: support for setting trailers from a server Handler (https://golang.org/cl/2157)
net/smtp: add TLSConnectionState accessor (https://golang.org/cl/2151)
runtime, syscall: use SYSCALL instruction on FreeBSD (Go 1.5 now requires FreeBSD 8-STABLE+) (https://golang.org/cl/3020)
strings: add Compare(x, y string) int, for symmetry with bytes.Compare (https://golang.org/cl/2828)
+testing/quick: support generation of arrays (https://golang.org/cl/3865)
Tools:
typedef struct Pcdata Pcdata;
typedef struct Pciter Pciter;
-// prevent incompatible type signatures between liblink and 8l on Plan 9
-#pragma incomplete struct Node
-
+// An Addr is an argument to an instruction.
+// The general forms and their encodings are:
+//
+// sym±offset(symkind)(reg)(index*scale)
+// Memory reference at address &sym(symkind) + offset + reg + index*scale.
+// Any of sym(symkind), ±offset, (reg), (index*scale), and *scale can be omitted.
+// If (reg) and *scale are both omitted, the resulting expression (index) is parsed as (reg).
+// To force a parsing as index*scale, write (index*1).
+// Encoding:
+// type = TYPE_MEM
+// name = symkind (NAME_AUTO, ...) or 0 (NAME_NONE)
+// sym = sym
+// offset = ±offset
+// reg = reg (REG_*)
+// index = index (REG_*)
+// scale = scale (1, 2, 4, 8)
+//
+// $<mem>
+// Effective address of memory reference <mem>, defined above.
+// Encoding: same as memory reference, but type = TYPE_ADDR.
+//
+// $<±integer value>
+// This is a special case of $<mem>, in which only ±offset is present.
+// It has a separate type for easy recognition.
+// Encoding:
+// type = TYPE_CONST
+// offset = ±integer value
+//
+// *<mem>
+// Indirect reference through memory reference <mem>, defined above.
+// Only used on x86 for CALL/JMP *sym(SB), which calls/jumps to a function
+// pointer stored in the data word sym(SB), not a function named sym(SB).
+// Encoding: same as above, but type = TYPE_INDIR.
+//
+// $*$<mem>
+// No longer used.
+// On machines with actual SB registers, $*$<mem> forced the
+// instruction encoding to use a full 32-bit constant, never a
+// reference relative to SB.
+//
+// $<floating point literal>
+// Floating point constant value.
+// Encoding:
+// type = TYPE_FCONST
+// u.dval = floating point value
+//
+// $<string literal, up to 8 chars>
+// String literal value (raw bytes used for DATA instruction).
+// Encoding:
+// type = TYPE_SCONST
+// u.sval = string
+//
+// <register name>
+// Any register: integer, floating point, control, segment, and so on.
+// If looking for specific register kind, must check type and reg value range.
+// Encoding:
+// type = TYPE_REG
+// reg = reg (REG_*)
+//
+// x(PC)
+// Encoding:
+// type = TYPE_BRANCH
+// u.branch = Prog* reference OR ELSE offset = target pc (branch takes priority)
+//
+// $±x-±y
+// Final argument to TEXT, specifying local frame size x and argument size y.
+// In this form, x and y are integer literals only, not arbitrary expressions.
+// This avoids parsing ambiguities due to the use of - as a separator.
+// The ± are optional.
+// If the final argument to TEXT omits the -±y, the encoding should still
+// use TYPE_TEXTSIZE (not TYPE_CONST), with u.argsize = ArgsSizeUnknown.
+// Encoding:
+// type = TYPE_TEXTSIZE
+// offset = x
+// u.argsize = y
+//
+// reg<<shift, reg>>shift, reg->shift, reg@>shift
+// Shifted register value, for ARM.
+// In this form, reg must be a register and shift can be a register or an integer constant.
+// Encoding:
+// type = TYPE_SHIFT
+// offset = (reg&15) | shifttype<<5 | count
+// shifttype = 0, 1, 2, 3 for <<, >>, ->, @>
+// count = (reg&15)<<8 | 1<<4 for a register shift count, (n&31)<<7 for an integer constant.
+//
+// (reg, reg)
+// A destination register pair. When used as the last argument of an instruction,
+// this form makes clear that both registers are destinations.
+// Encoding:
+// type = TYPE_REGREG
+// reg = first register
+// offset = second register
+//
+// reg, reg
+// TYPE_REGREG2, to be removed.
+//
struct Addr
{
- vlong offset;
-
+ int16 type; // could be int8
+ int16 reg;
+ int16 index;
+ int8 scale;
+ int8 name;
+ int64 offset;
+ LSym* sym;
+
union
{
char sval[8];
float64 dval;
- Prog* branch; // for 5g, 6g, 8g, 9g
+ Prog* branch;
+ int32 argsize; // for 5l, 8l
+ uint64 bits; // raw union bits, for testing if anything has been written to any field
} u;
- LSym* sym;
+ // gotype is the name of the Go type descriptor for sym.
+ // It cannot be set using assembly syntax.
+ // It is generated by the Go compiler for global declarations,
+ // to convey information about pointer locations to the back end
+ // and for use in generating debug information.
LSym* gotype;
- short type;
- uint8 index;
- int8 scale;
- int8 reg; // for 5l, 9l; GPRs and FPRs both start at 0
- int8 name; // for 5l, 9l
- int8 class; // for 5l, 9l
- uint8 etype; // for 5g, 6g, 8g
- int32 offset2; // for 5l, 8l
- struct Node* node; // for 5g, 6g, 8g
- int64 width; // for 5g, 6g, 8g
+
+ int8 class; // for internal use by liblink
+ uint8 etype; // for internal use by 5g, 6g, 8g
+ void* node; // for internal use by 5g, 6g, 8g
+ int64 width; // for internal use by 5g, 6g, 8g
+};
+
+enum {
+ NAME_NONE = 0,
+ NAME_EXTERN,
+ NAME_STATIC,
+ NAME_AUTO,
+ NAME_PARAM,
+};
+
+enum {
+ TYPE_NONE = 0,
+ TYPE_BRANCH = 5, // avoid accidental conflicts with NAME_*
+ TYPE_TEXTSIZE,
+ TYPE_MEM,
+ TYPE_CONST,
+ TYPE_FCONST,
+ TYPE_SCONST,
+ TYPE_REG,
+ TYPE_ADDR,
+ TYPE_SHIFT,
+ TYPE_REGREG,
+ TYPE_REGREG2,
+ TYPE_INDIR,
};
struct Reloc
LSym* xsym;
};
+// TODO(rsc): Describe prog.
+// TODO(rsc): Describe TEXT/GLOBL flag in from3, DATA width in from3.
struct Prog
{
vlong pc;
// operands
Addr from;
- uchar reg; // arm, ppc64 only (e.g., ADD from, reg, to);
+ int16 reg; // arm, ppc64 only (e.g., ADD from, reg, to);
// starts at 0 for both GPRs and FPRs;
// also used for ADATA width on arm, ppc64
- Addr from3; // ppc64 only (e.g., RLWM/FMADD from, reg, from3, to)
+ Addr from3; // addl source argument (e.g., RLWM/FMADD from, reg, from3, to)
Addr to;
// for 5g, 6g, 8g internal use
void* opt;
- // for 5l, 6l, 8l internal use
+ // for liblink internal use
Prog* forwd;
Prog* pcond;
- Prog* comefrom; // 6l, 8l
- Prog* pcrel; // 5l
+ Prog* comefrom; // amd64, 386
+ Prog* pcrel; // arm
int32 spadj;
uint16 mark;
- uint16 optab; // 5l, 9l
- uchar back; // 6l, 8l
- uchar ft; /* 6l, 8l oclass cache */
- uchar tt; // 6l, 8l
- uchar isize; // 6l, 8l
+ uint16 optab; // arm, ppc64
+ uchar back; // amd64, 386
+ uchar ft; // oclass cache
+ uchar tt; // oclass cache
+ uchar isize; // amd64, 386
uchar printed;
char width; /* fake for DATA */
char mode; /* 16, 32, or 64 in 6l, 8l; internal use in 5g, 6g, 8g */
+};
+
+extern Prog zprog; // zeroed Prog
+
+// Prog.as opcodes.
+// These are the portable opcodes, common to all architectures.
+// Each architecture defines many more arch-specific opcodes,
+// with values starting at A_ARCHSPECIFIC.
+enum {
+ AXXX = 0,
+
+ ACALL,
+ ACHECKNIL,
+ ADATA,
+ ADUFFCOPY,
+ ADUFFZERO,
+ AEND,
+ AFUNCDATA,
+ AGLOBL,
+ AJMP,
+ ANOP,
+ APCDATA,
+ ARET,
+ ATEXT,
+ ATYPE,
+ AUNDEF,
+ AUSEFIELD,
+ AVARDEF,
+ AVARKILL,
- /*c2go uchar TEXTFLAG; */
+ A_ARCHSPECIFIC, // first architecture-specific opcode value
};
// prevent incompatible type signatures between liblink and 8l on Plan 9
RV_TYPE_MASK = (RV_CHECK_OVERFLOW - 1),
};
-// Auto.type
+// Auto.name
enum
{
A_AUTO = 1,
LSym* asym;
Auto* link;
int32 aoffset;
- int16 type;
+ int16 name;
LSym* gotype;
};
int thechar; // '5', '6', and so on
int32 endian; // LittleEndian or BigEndian
- void (*addstacksplit)(Link*, LSym*);
+ void (*preprocess)(Link*, LSym*);
void (*assemble)(Link*, LSym*);
- int (*datasize)(Prog*);
void (*follow)(Link*, LSym*);
- int (*iscall)(Prog*);
- int (*isdata)(Prog*);
- Prog* (*prg)(void);
void (*progedit)(Link*, Prog*);
- void (*settextflag)(Prog*, int);
- int (*symtype)(Addr*);
- int (*textflag)(Prog*);
int minlc;
int ptrsize;
int regsize;
-
- // TODO: Give these the same values on all systems.
- int D_ADDR;
- int D_AUTO;
- int D_BRANCH;
- int D_CONST;
- int D_EXTERN;
- int D_FCONST;
- int D_NONE;
- int D_PARAM;
- int D_SCONST;
- int D_STATIC;
- int D_OREG;
-
- int ACALL;
- int ADATA;
- int AEND;
- int AFUNCDATA;
- int AGLOBL;
- int AJMP;
- int ANOP;
- int APCDATA;
- int ARET;
- int ATEXT;
- int ATYPE;
- int AUSEFIELD;
};
/* executable header types */
void* erealloc(void *p, long n);
char* estrdup(char *p);
char* expandpkg(char *t0, char *pkg);
+void linksetexp(void);
+char* expstring(void);
+
+extern int fieldtrack_enabled;
+extern int framepointer_enabled;
// ld.c
void addhist(Link *ctxt, int32 line, int type);
extern LinkArch linkppc64;
extern LinkArch linkppc64le;
+extern int linkbasepointer;
+extern void linksetexp(void);
+
#pragma varargck type "A" int
#pragma varargck type "E" uint
#pragma varargck type "D" Addr*
#include <stddef.h>
#include <math.h>
#include <ctype.h> /* for tolower */
-#include <signal.h>
#include <time.h>
+#ifdef _WIN32
+#include <signal.h>
+#endif
+
/*
* OS-specific crap
*/
OS: b.OS,
Arch: b.Arch,
Checksum: sum,
+ Size: len(file),
Kind: kind,
})
if err != nil {
Arch string
Version string
Checksum string `datastore:",noindex"`
+ Size int `datastore:",noindex"`
Kind string // "archive", "installer", "source"
}
for _, file := range files {
hdr := &tar.Header{
Name: file.Name,
+ Mode: 0600,
Size: int64(len(file.Body)),
}
if err := tw.WriteHeader(hdr); err != nil {
return true
}
-// explode splits s into a slice of UTF-8 sequences, one per Unicode character (still slices of bytes),
+// explode splits s into a slice of UTF-8 sequences, one per Unicode code point (still slices of bytes),
// up to a maximum of n byte slices. Invalid UTF-8 sequences are chopped into individual bytes.
func explode(s []byte, n int) [][]byte {
if n <= 0 {
}
// Count counts the number of non-overlapping instances of sep in s.
+// If sep is an empty slice, Count returns 1 + the number of Unicode code points in s.
func Count(s, sep []byte) int {
n := len(sep)
if n == 0 {
CMACARG,
CMACRO,
CPREPROC,
-
- Always = 14,
+
+ Always = C_SCOND_NONE,
};
EXTERN int debug[256];
EXTERN Biobuf obuf;
EXTERN Link* ctxt;
EXTERN Biobuf bstdout;
+EXTERN Prog* lastpc;
void* alloc(int32);
void* allocn(void*, int32, int32);
%left '*' '/' '%'
%token <lval> LTYPE1 LTYPE2 LTYPE3 LTYPE4 LTYPE5
%token <lval> LTYPE6 LTYPE7 LTYPE8 LTYPE9 LTYPEA
-%token <lval> LTYPEB LTYPEC LTYPED LTYPEE
+%token <lval> LTYPEB LGLOBL LTYPEC LTYPED LTYPEE
%token <lval> LTYPEG LTYPEH LTYPEI LTYPEJ LTYPEK
%token <lval> LTYPEL LTYPEM LTYPEN LTYPEBX LTYPEPLD
%token <lval> LCONST LSP LSB LFP LPC
%token <sym> LNAME LLAB LVAR
%type <lval> con expr oexpr pointer offset sreg spreg creg
%type <lval> rcon cond reglist
-%type <addr> gen rel reg regreg freg shift fcon frcon
+%type <addr> gen rel reg regreg freg shift fcon frcon textsize
%type <addr> imm ximm name oreg ireg nireg ioreg imsr
%%
prog:
}
| LTYPE1 cond imsr ',' reg
{
- outcode($1, $2, &$3, NREG, &$5);
+ outcode($1, $2, &$3, 0, &$5);
}
/*
* MVN
*/
| LTYPE2 cond imsr ',' reg
{
- outcode($1, $2, &$3, NREG, &$5);
+ outcode($1, $2, &$3, 0, &$5);
}
/*
* MOVW
*/
| LTYPE3 cond gen ',' gen
{
- outcode($1, $2, &$3, NREG, &$5);
+ outcode($1, $2, &$3, 0, &$5);
}
/*
* B/BL
*/
| LTYPE4 cond comma rel
{
- outcode($1, $2, &nullgen, NREG, &$4);
+ outcode($1, $2, &nullgen, 0, &$4);
}
| LTYPE4 cond comma nireg
{
- outcode($1, $2, &nullgen, NREG, &$4);
+ outcode($1, $2, &nullgen, 0, &$4);
}
/*
* BX
*/
| LTYPEBX comma ireg
{
- outcode($1, Always, &nullgen, NREG, &$3);
+ outcode($1, Always, &nullgen, 0, &$3);
}
/*
* BEQ
*/
| LTYPE5 comma rel
{
- outcode($1, Always, &nullgen, NREG, &$3);
+ outcode($1, Always, &nullgen, 0, &$3);
}
/*
* SWI
*/
| LTYPE6 cond comma gen
{
- outcode($1, $2, &nullgen, NREG, &$4);
+ outcode($1, $2, &nullgen, 0, &$4);
}
/*
* CMP
Addr g;
g = nullgen;
- g.type = D_CONST;
+ g.type = TYPE_CONST;
g.offset = $6;
- outcode($1, $2, &$3, NREG, &g);
+ outcode($1, $2, &$3, 0, &g);
}
| LTYPE8 cond '[' reglist ']' ',' ioreg
{
Addr g;
g = nullgen;
- g.type = D_CONST;
+ g.type = TYPE_CONST;
g.offset = $4;
- outcode($1, $2, &g, NREG, &$7);
+ outcode($1, $2, &g, 0, &$7);
}
/*
* SWAP
*/
| LTYPEA cond comma
{
- outcode($1, $2, &nullgen, NREG, &nullgen);
+ outcode($1, $2, &nullgen, 0, &nullgen);
}
/*
- * TEXT/GLOBL
+ * TEXT
*/
-| LTYPEB name ',' imm
+| LTYPEB name ',' '$' textsize
{
settext($2.sym);
- $4.type = D_CONST2;
- $4.offset2 = ArgsSizeUnknown;
- outcode($1, Always, &$2, 0, &$4);
+ outcode($1, Always, &$2, 0, &$5);
}
-| LTYPEB name ',' con ',' imm
+| LTYPEB name ',' con ',' '$' textsize
{
settext($2.sym);
- $6.type = D_CONST2;
- $6.offset2 = ArgsSizeUnknown;
- outcode($1, Always, &$2, $4, &$6);
+ outcode($1, Always, &$2, 0, &$7);
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = $4;
+ }
}
-| LTYPEB name ',' con ',' imm '-' con
+/*
+ * GLOBL
+ */
+| LGLOBL name ',' imm
{
settext($2.sym);
- $6.type = D_CONST2;
- $6.offset2 = $8;
- outcode($1, Always, &$2, $4, &$6);
+ outcode($1, Always, &$2, 0, &$4);
+ }
+| LGLOBL name ',' con ',' imm
+ {
+ settext($2.sym);
+ outcode($1, Always, &$2, 0, &$6);
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = $4;
+ }
}
/*
* DATA
*/
| LTYPEC name '/' con ',' ximm
{
- outcode($1, Always, &$2, $4, &$6);
+ outcode($1, Always, &$2, 0, &$6);
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = $4;
+ }
}
/*
* CASE
*/
| LTYPED cond reg comma
{
- outcode($1, $2, &$3, NREG, &nullgen);
+ outcode($1, $2, &$3, 0, &nullgen);
}
/*
* word
*/
| LTYPEH comma ximm
{
- outcode($1, Always, &nullgen, NREG, &$3);
+ outcode($1, Always, &nullgen, 0, &$3);
}
/*
* floating-point coprocessor
*/
| LTYPEI cond freg ',' freg
{
- outcode($1, $2, &$3, NREG, &$5);
+ outcode($1, $2, &$3, 0, &$5);
}
| LTYPEK cond frcon ',' freg
{
- outcode($1, $2, &$3, NREG, &$5);
+ outcode($1, $2, &$3, 0, &$5);
}
| LTYPEK cond frcon ',' LFREG ',' freg
{
Addr g;
g = nullgen;
- g.type = D_CONST;
+ g.type = TYPE_CONST;
g.offset =
(0xe << 24) | /* opcode */
($1 << 20) | /* MCR/MRC */
- ($2 << 28) | /* scond */
+ (($2^C_SCOND_XOR) << 28) | /* scond */
(($3 & 15) << 8) | /* coprocessor number */
(($5 & 7) << 21) | /* coprocessor operation */
(($7 & 15) << 12) | /* arm register */
(($11 & 15) << 0) | /* Crm */
(($12 & 7) << 5) | /* coprocessor information */
(1<<4); /* must be set */
- outcode(AMRC, Always, &nullgen, NREG, &g);
+ outcode(AMRC, Always, &nullgen, 0, &g);
}
/*
* MULL r1,r2,(hi,lo)
*/
| LTYPEN cond reg ',' reg ',' reg ',' spreg
{
- $7.type = D_REGREG2;
+ $7.type = TYPE_REGREG2;
$7.offset = $9;
outcode($1, $2, &$3, $5.reg, &$7);
}
*/
| LTYPEPLD oreg
{
- outcode($1, Always, &$2, NREG, &nullgen);
+ outcode($1, Always, &$2, 0, &nullgen);
}
/*
* PCDATA
*/
| LTYPEPC gen ',' gen
{
- if($2.type != D_CONST || $4.type != D_CONST)
+ if($2.type != TYPE_CONST || $4.type != TYPE_CONST)
yyerror("arguments to PCDATA must be integer constants");
- outcode($1, Always, &$2, NREG, &$4);
+ outcode($1, Always, &$2, 0, &$4);
}
/*
* FUNCDATA
*/
| LTYPEF gen ',' gen
{
- if($2.type != D_CONST)
+ if($2.type != TYPE_CONST)
yyerror("index for FUNCDATA must be integer constant");
- if($4.type != D_EXTERN && $4.type != D_STATIC && $4.type != D_OREG)
+ if($4.type != NAME_EXTERN && $4.type != NAME_STATIC && $4.type != TYPE_MEM)
yyerror("value for FUNCDATA must be symbol reference");
- outcode($1, Always, &$2, NREG, &$4);
+ outcode($1, Always, &$2, 0, &$4);
}
/*
* END
*/
| LTYPEE comma
{
- outcode($1, Always, &nullgen, NREG, &nullgen);
+ outcode($1, Always, &nullgen, 0, &nullgen);
}
cond:
con '(' LPC ')'
{
$$ = nullgen;
- $$.type = D_BRANCH;
+ $$.type = TYPE_BRANCH;
$$.offset = $1 + pc;
}
| LNAME offset
$$ = nullgen;
if(pass == 2 && $1->type != LLAB)
yyerror("undefined label: %s", $1->labelname);
- $$.type = D_BRANCH;
+ $$.type = TYPE_BRANCH;
$$.offset = $1->value + $2;
}
+textsize:
+ LCONST
+ {
+ $$ = nullgen;
+ $$.type = TYPE_TEXTSIZE;
+ $$.offset = $1;
+ $$.u.argsize = ArgsSizeUnknown;
+ }
+| '-' LCONST
+ {
+ $$ = nullgen;
+ $$.type = TYPE_TEXTSIZE;
+ $$.offset = -$2;
+ $$.u.argsize = ArgsSizeUnknown;
+ }
+| LCONST '-' LCONST
+ {
+ $$ = nullgen;
+ $$.type = TYPE_TEXTSIZE;
+ $$.offset = $1;
+ $$.u.argsize = $3;
+ }
+| '-' LCONST '-' LCONST
+ {
+ $$ = nullgen;
+ $$.type = TYPE_TEXTSIZE;
+ $$.offset = -$2;
+ $$.u.argsize = $4;
+ }
+
ximm: '$' con
{
$$ = nullgen;
- $$.type = D_CONST;
+ $$.type = TYPE_CONST;
$$.offset = $2;
}
| '$' oreg
{
$$ = $2;
- $$.type = D_CONST;
- }
-| '$' '*' '$' oreg
- {
- $$ = $4;
- $$.type = D_OCONST;
+ $$.type = TYPE_ADDR;
}
| '$' LSCONST
{
$$ = nullgen;
- $$.type = D_SCONST;
+ $$.type = TYPE_SCONST;
memcpy($$.u.sval, $2, sizeof($$.u.sval));
}
| fcon
'$' LFCONST
{
$$ = nullgen;
- $$.type = D_FCONST;
+ $$.type = TYPE_FCONST;
$$.u.dval = $2;
}
| '$' '-' LFCONST
{
$$ = nullgen;
- $$.type = D_FCONST;
+ $$.type = TYPE_FCONST;
$$.u.dval = -$3;
}
| LPSR
{
$$ = nullgen;
- $$.type = D_PSR;
+ $$.type = TYPE_REG;
$$.reg = $1;
}
| LFCR
{
$$ = nullgen;
- $$.type = D_FPCR;
+ $$.type = TYPE_REG;
$$.reg = $1;
}
| con
{
$$ = nullgen;
- $$.type = D_OREG;
+ $$.type = TYPE_MEM;
$$.offset = $1;
}
| oreg
| name
{
$$ = $1;
- if($1.name != D_EXTERN && $1.name != D_STATIC) {
+ if($1.name != NAME_EXTERN && $1.name != NAME_STATIC) {
}
}
'(' spreg ')'
{
$$ = nullgen;
- $$.type = D_OREG;
+ $$.type = TYPE_MEM;
$$.reg = $2;
$$.offset = 0;
}
| con '(' sreg ')'
{
$$ = nullgen;
- $$.type = D_OREG;
+ $$.type = TYPE_MEM;
$$.reg = $3;
$$.offset = $1;
}
| name '(' sreg ')'
{
$$ = $1;
- $$.type = D_OREG;
+ $$.type = TYPE_MEM;
$$.reg = $3;
}
| ioreg
imm: '$' con
{
$$ = nullgen;
- $$.type = D_CONST;
+ $$.type = TYPE_CONST;
$$.offset = $2;
}
spreg
{
$$ = nullgen;
- $$.type = D_REG;
+ $$.type = TYPE_REG;
$$.reg = $1;
}
'(' spreg ',' spreg ')'
{
$$ = nullgen;
- $$.type = D_REGREG;
+ $$.type = TYPE_REGREG;
$$.reg = $2;
$$.offset = $4;
}
spreg '<' '<' rcon
{
$$ = nullgen;
- $$.type = D_SHIFT;
- $$.offset = $1 | $4 | (0 << 5);
+ $$.type = TYPE_SHIFT;
+ $$.offset = $1&15 | $4 | (0 << 5);
}
| spreg '>' '>' rcon
{
$$ = nullgen;
- $$.type = D_SHIFT;
- $$.offset = $1 | $4 | (1 << 5);
+ $$.type = TYPE_SHIFT;
+ $$.offset = $1&15 | $4 | (1 << 5);
}
| spreg '-' '>' rcon
{
$$ = nullgen;
- $$.type = D_SHIFT;
- $$.offset = $1 | $4 | (2 << 5);
+ $$.type = TYPE_SHIFT;
+ $$.offset = $1&15 | $4 | (2 << 5);
}
| spreg LAT '>' rcon
{
$$ = nullgen;
- $$.type = D_SHIFT;
- $$.offset = $1 | $4 | (3 << 5);
+ $$.type = TYPE_SHIFT;
+ $$.offset = $1&15 | $4 | (3 << 5);
}
rcon:
spreg
{
- if($$ < 0 || $$ >= 16)
- print("register value out of range\n");
+ if($$ < REG_R0 || $$ > REG_R15)
+ print("register value out of range in shift\n");
$$ = (($1&15) << 8) | (1 << 4);
}
| con
| LR '(' expr ')'
{
if($3 < 0 || $3 >= NREG)
- print("register value out of range\n");
- $$ = $3;
+ print("register value out of range in R(...)\n");
+ $$ = REG_R0 + $3;
}
spreg:
| LC '(' expr ')'
{
if($3 < 0 || $3 >= NREG)
- print("register value out of range\n");
- $$ = $3;
+ print("register value out of range in C(...)\n");
+ $$ = $3; // TODO(rsc): REG_C0+$3
}
frcon:
LFREG
{
$$ = nullgen;
- $$.type = D_FREG;
+ $$.type = TYPE_REG;
$$.reg = $1;
}
| LF '(' con ')'
{
$$ = nullgen;
- $$.type = D_FREG;
- $$.reg = $3;
+ $$.type = TYPE_REG;
+ $$.reg = REG_F0 + $3;
}
name:
con '(' pointer ')'
{
$$ = nullgen;
- $$.type = D_OREG;
+ $$.type = TYPE_MEM;
$$.name = $3;
$$.sym = nil;
$$.offset = $1;
| LNAME offset '(' pointer ')'
{
$$ = nullgen;
- $$.type = D_OREG;
+ $$.type = TYPE_MEM;
$$.name = $4;
$$.sym = linklookup(ctxt, $1->name, 0);
$$.offset = $2;
| LNAME '<' '>' offset '(' LSB ')'
{
$$ = nullgen;
- $$.type = D_OREG;
- $$.name = D_STATIC;
+ $$.type = TYPE_MEM;
+ $$.name = NAME_STATIC;
$$.sym = linklookup(ctxt, $1->name, 1);
$$.offset = $4;
}
ushort value;
} itab[] =
{
- "SP", LSP, D_AUTO,
- "SB", LSB, D_EXTERN,
- "FP", LFP, D_PARAM,
- "PC", LPC, D_BRANCH,
-
- "R", LR, 0,
- "R0", LREG, 0,
- "R1", LREG, 1,
- "R2", LREG, 2,
- "R3", LREG, 3,
- "R4", LREG, 4,
- "R5", LREG, 5,
- "R6", LREG, 6,
- "R7", LREG, 7,
- "R8", LREG, 8,
- "R9", LREG, 9,
- "g", LREG, 10, // avoid unintentionally clobber g using R10
- "R11", LREG, 11,
- "R12", LREG, 12,
- "R13", LREG, 13,
- "R14", LREG, 14,
- "R15", LREG, 15,
-
- "F", LF, 0,
-
- "F0", LFREG, 0,
- "F1", LFREG, 1,
- "F2", LFREG, 2,
- "F3", LFREG, 3,
- "F4", LFREG, 4,
- "F5", LFREG, 5,
- "F6", LFREG, 6,
- "F7", LFREG, 7,
- "F8", LFREG, 8,
- "F9", LFREG, 9,
- "F10", LFREG, 10,
- "F11", LFREG, 11,
- "F12", LFREG, 12,
- "F13", LFREG, 13,
- "F14", LFREG, 14,
- "F15", LFREG, 15,
+ "SP", LSP, NAME_AUTO,
+ "SB", LSB, NAME_EXTERN,
+ "FP", LFP, NAME_PARAM,
+ "PC", LPC, TYPE_BRANCH,
+
+ "R", LR, REG_F0,
+
+ "R0", LREG, REG_R0,
+ "R1", LREG, REG_R1,
+ "R2", LREG, REG_R2,
+ "R3", LREG, REG_R3,
+ "R4", LREG, REG_R4,
+ "R5", LREG, REG_R5,
+ "R6", LREG, REG_R6,
+ "R7", LREG, REG_R7,
+ "R8", LREG, REG_R8,
+ "R9", LREG, REG_R9,
+ "g", LREG, REG_R10, // avoid unintentionally clobber g using R10
+ "R11", LREG, REG_R11,
+ "R12", LREG, REG_R12,
+ "R13", LREG, REG_R13,
+ "R14", LREG, REG_R14,
+ "R15", LREG, REG_R15,
+
+ "F", LF, REG_F0,
+
+ "F0", LFREG, REG_F0,
+ "F1", LFREG, REG_F1,
+ "F2", LFREG, REG_F2,
+ "F3", LFREG, REG_F3,
+ "F4", LFREG, REG_F4,
+ "F5", LFREG, REG_F5,
+ "F6", LFREG, REG_F6,
+ "F7", LFREG, REG_F7,
+ "F8", LFREG, REG_F8,
+ "F9", LFREG, REG_F9,
+ "F10", LFREG, REG_F10,
+ "F11", LFREG, REG_F11,
+ "F12", LFREG, REG_F12,
+ "F13", LFREG, REG_F13,
+ "F14", LFREG, REG_F14,
+ "F15", LFREG, REG_F15,
"C", LC, 0,
"C14", LCREG, 14,
"C15", LCREG, 15,
- "CPSR", LPSR, 0,
- "SPSR", LPSR, 1,
-
- "FPSR", LFCR, 0,
- "FPCR", LFCR, 1,
-
- ".EQ", LCOND, 0,
- ".NE", LCOND, 1,
- ".CS", LCOND, 2,
- ".HS", LCOND, 2,
- ".CC", LCOND, 3,
- ".LO", LCOND, 3,
- ".MI", LCOND, 4,
- ".PL", LCOND, 5,
- ".VS", LCOND, 6,
- ".VC", LCOND, 7,
- ".HI", LCOND, 8,
- ".LS", LCOND, 9,
- ".GE", LCOND, 10,
- ".LT", LCOND, 11,
- ".GT", LCOND, 12,
- ".LE", LCOND, 13,
- ".AL", LCOND, Always,
+ "CPSR", LPSR, REG_CPSR,
+ "SPSR", LPSR, REG_SPSR,
+
+ "FPSR", LFCR, REG_FPSR,
+ "FPCR", LFCR, REG_FPCR,
+
+ ".EQ", LCOND, C_SCOND_EQ,
+ ".NE", LCOND, C_SCOND_NE,
+ ".CS", LCOND, C_SCOND_HS,
+ ".HS", LCOND, C_SCOND_HS,
+ ".CC", LCOND, C_SCOND_LO,
+ ".LO", LCOND, C_SCOND_LO,
+ ".MI", LCOND, C_SCOND_MI,
+ ".PL", LCOND, C_SCOND_PL,
+ ".VS", LCOND, C_SCOND_VS,
+ ".VC", LCOND, C_SCOND_VC,
+ ".HI", LCOND, C_SCOND_HI,
+ ".LS", LCOND, C_SCOND_LS,
+ ".GE", LCOND, C_SCOND_GE,
+ ".LT", LCOND, C_SCOND_LT,
+ ".GT", LCOND, C_SCOND_GT,
+ ".LE", LCOND, C_SCOND_LE,
+ ".AL", LCOND, C_SCOND_NONE,
".U", LS, C_UBIT,
".S", LS, C_SBIT,
"RFE", LTYPEA, ARFE,
"TEXT", LTYPEB, ATEXT,
- "GLOBL", LTYPEB, AGLOBL,
+ "GLOBL", LGLOBL, AGLOBL,
"DATA", LTYPEC, ADATA,
"CASE", LTYPED, ACASE,
"END", LTYPEE, AEND,
Sym *s;
int i;
- nullgen.type = D_NONE;
- nullgen.name = D_NONE;
- nullgen.reg = NREG;
+ nullgen.type = TYPE_NONE;
+ nullgen.name = NAME_NONE;
nerrors = 0;
iostack = I;
void
cclean(void)
{
- outcode(AEND, Always, &nullgen, NREG, &nullgen);
+ outcode(AEND, Always, &nullgen, 0, &nullgen);
}
static int bcode[] =
ANOP,
};
-static Prog *lastpc;
-
void
outcode(int a, int scond, Addr *g1, int reg, Addr *g2)
{
/* hack to make B.NE etc. work: turn it into the corresponding conditional */
if(a == AB){
- a = bcode[scond&0xf];
- scond = (scond & ~0xf) | Always;
+ a = bcode[(scond^C_SCOND_XOR)&0xf];
+ scond = (scond & ~0xf) | C_SCOND_NONE;
}
if(pass == 1)
LTYPE9 = 266,
LTYPEA = 267,
LTYPEB = 268,
- LTYPEC = 269,
- LTYPED = 270,
- LTYPEE = 271,
- LTYPEG = 272,
- LTYPEH = 273,
- LTYPEI = 274,
- LTYPEJ = 275,
- LTYPEK = 276,
- LTYPEL = 277,
- LTYPEM = 278,
- LTYPEN = 279,
- LTYPEBX = 280,
- LTYPEPLD = 281,
- LCONST = 282,
- LSP = 283,
- LSB = 284,
- LFP = 285,
- LPC = 286,
- LTYPEX = 287,
- LTYPEPC = 288,
- LTYPEF = 289,
- LR = 290,
- LREG = 291,
- LF = 292,
- LFREG = 293,
- LC = 294,
- LCREG = 295,
- LPSR = 296,
- LFCR = 297,
- LCOND = 298,
- LS = 299,
- LAT = 300,
- LFCONST = 301,
- LSCONST = 302,
- LNAME = 303,
- LLAB = 304,
- LVAR = 305
+ LGLOBL = 269,
+ LTYPEC = 270,
+ LTYPED = 271,
+ LTYPEE = 272,
+ LTYPEG = 273,
+ LTYPEH = 274,
+ LTYPEI = 275,
+ LTYPEJ = 276,
+ LTYPEK = 277,
+ LTYPEL = 278,
+ LTYPEM = 279,
+ LTYPEN = 280,
+ LTYPEBX = 281,
+ LTYPEPLD = 282,
+ LCONST = 283,
+ LSP = 284,
+ LSB = 285,
+ LFP = 286,
+ LPC = 287,
+ LTYPEX = 288,
+ LTYPEPC = 289,
+ LTYPEF = 290,
+ LR = 291,
+ LREG = 292,
+ LF = 293,
+ LFREG = 294,
+ LC = 295,
+ LCREG = 296,
+ LPSR = 297,
+ LFCR = 298,
+ LCOND = 299,
+ LS = 300,
+ LAT = 301,
+ LFCONST = 302,
+ LSCONST = 303,
+ LNAME = 304,
+ LLAB = 305,
+ LVAR = 306
};
#endif
/* Tokens. */
#define LTYPE9 266
#define LTYPEA 267
#define LTYPEB 268
-#define LTYPEC 269
-#define LTYPED 270
-#define LTYPEE 271
-#define LTYPEG 272
-#define LTYPEH 273
-#define LTYPEI 274
-#define LTYPEJ 275
-#define LTYPEK 276
-#define LTYPEL 277
-#define LTYPEM 278
-#define LTYPEN 279
-#define LTYPEBX 280
-#define LTYPEPLD 281
-#define LCONST 282
-#define LSP 283
-#define LSB 284
-#define LFP 285
-#define LPC 286
-#define LTYPEX 287
-#define LTYPEPC 288
-#define LTYPEF 289
-#define LR 290
-#define LREG 291
-#define LF 292
-#define LFREG 293
-#define LC 294
-#define LCREG 295
-#define LPSR 296
-#define LFCR 297
-#define LCOND 298
-#define LS 299
-#define LAT 300
-#define LFCONST 301
-#define LSCONST 302
-#define LNAME 303
-#define LLAB 304
-#define LVAR 305
+#define LGLOBL 269
+#define LTYPEC 270
+#define LTYPED 271
+#define LTYPEE 272
+#define LTYPEG 273
+#define LTYPEH 274
+#define LTYPEI 275
+#define LTYPEJ 276
+#define LTYPEK 277
+#define LTYPEL 278
+#define LTYPEM 279
+#define LTYPEN 280
+#define LTYPEBX 281
+#define LTYPEPLD 282
+#define LCONST 283
+#define LSP 284
+#define LSB 285
+#define LFP 286
+#define LPC 287
+#define LTYPEX 288
+#define LTYPEPC 289
+#define LTYPEF 290
+#define LR 291
+#define LREG 292
+#define LF 293
+#define LFREG 294
+#define LC 295
+#define LCREG 296
+#define LPSR 297
+#define LFCR 298
+#define LCOND 299
+#define LS 300
+#define LAT 301
+#define LFCONST 302
+#define LSCONST 303
+#define LNAME 304
+#define LLAB 305
+#define LVAR 306
Addr addr;
}
/* Line 193 of yacc.c. */
-#line 212 "y.tab.c"
+#line 214 "y.tab.c"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
/* Line 216 of yacc.c. */
-#line 225 "y.tab.c"
+#line 227 "y.tab.c"
#ifdef short
# undef short
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 2
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 640
+#define YYLAST 655
/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 71
+#define YYNTOKENS 72
/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 34
+#define YYNNTS 35
/* YYNRULES -- Number of rules. */
-#define YYNRULES 130
+#define YYNRULES 134
/* YYNRULES -- Number of states. */
-#define YYNSTATES 333
+#define YYNSTATES 344
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
#define YYUNDEFTOK 2
-#define YYMAXUTOK 305
+#define YYMAXUTOK 306
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 69, 12, 5, 2,
- 67, 68, 10, 8, 64, 9, 2, 11, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 61, 63,
- 6, 62, 7, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 68, 12, 5, 2,
+ 69, 70, 10, 8, 65, 9, 2, 11, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 62, 64,
+ 6, 63, 7, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 65, 2, 66, 4, 2, 2, 2, 2, 2,
+ 2, 66, 2, 67, 4, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 3, 2, 70, 2, 2, 2,
+ 2, 2, 2, 2, 3, 2, 71, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
- 55, 56, 57, 58, 59, 60
+ 55, 56, 57, 58, 59, 60, 61
};
#if YYDEBUG
0, 0, 3, 4, 5, 9, 10, 15, 20, 25,
27, 30, 33, 41, 48, 54, 60, 66, 71, 76,
80, 84, 89, 96, 104, 112, 120, 127, 134, 138,
- 143, 150, 159, 166, 171, 175, 181, 187, 195, 202,
- 215, 223, 233, 236, 241, 246, 249, 250, 253, 256,
- 257, 260, 265, 268, 271, 274, 279, 282, 284, 287,
- 291, 293, 297, 301, 303, 305, 307, 312, 314, 316,
- 318, 320, 322, 324, 326, 330, 332, 337, 339, 344,
- 346, 348, 350, 352, 355, 357, 363, 368, 373, 378,
- 383, 385, 387, 389, 391, 396, 398, 400, 402, 407,
- 409, 411, 413, 418, 423, 429, 437, 438, 441, 444,
- 446, 448, 450, 452, 454, 457, 460, 463, 467, 468,
- 471, 473, 477, 481, 485, 489, 493, 498, 503, 507,
- 511
+ 144, 152, 157, 164, 171, 176, 180, 186, 192, 200,
+ 207, 220, 228, 238, 241, 246, 251, 254, 255, 258,
+ 261, 262, 265, 270, 273, 275, 278, 282, 287, 290,
+ 293, 296, 298, 301, 305, 307, 311, 315, 317, 319,
+ 321, 326, 328, 330, 332, 334, 336, 338, 340, 344,
+ 346, 351, 353, 358, 360, 362, 364, 366, 369, 371,
+ 377, 382, 387, 392, 397, 399, 401, 403, 405, 410,
+ 412, 414, 416, 421, 423, 425, 427, 432, 437, 443,
+ 451, 452, 455, 458, 460, 462, 464, 466, 468, 471,
+ 474, 477, 481, 482, 485, 487, 491, 495, 499, 503,
+ 507, 512, 517, 521, 525
};
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
static const yytype_int8 yyrhs[] =
{
- 72, 0, -1, -1, -1, 72, 73, 74, -1, -1,
- 58, 61, 75, 74, -1, 58, 62, 104, 63, -1,
- 60, 62, 104, 63, -1, 63, -1, 76, 63, -1,
- 1, 63, -1, 13, 77, 88, 64, 95, 64, 90,
- -1, 13, 77, 88, 64, 95, 64, -1, 13, 77,
- 88, 64, 90, -1, 14, 77, 88, 64, 90, -1,
- 15, 77, 83, 64, 83, -1, 16, 77, 78, 79,
- -1, 16, 77, 78, 84, -1, 35, 78, 85, -1,
- 17, 78, 79, -1, 18, 77, 78, 83, -1, 19,
- 77, 88, 64, 95, 78, -1, 20, 77, 86, 64,
- 65, 82, 66, -1, 20, 77, 65, 82, 66, 64,
- 86, -1, 21, 77, 90, 64, 85, 64, 90, -1,
- 21, 77, 90, 64, 85, 78, -1, 21, 77, 78,
- 85, 64, 90, -1, 22, 77, 78, -1, 23, 99,
- 64, 89, -1, 23, 99, 64, 102, 64, 89, -1,
- 23, 99, 64, 102, 64, 89, 9, 102, -1, 24,
- 99, 11, 102, 64, 80, -1, 25, 77, 90, 78,
- -1, 28, 78, 80, -1, 29, 77, 98, 64, 98,
- -1, 31, 77, 97, 64, 98, -1, 31, 77, 97,
- 64, 48, 64, 98, -1, 32, 77, 98, 64, 98,
- 78, -1, 30, 77, 102, 64, 104, 64, 95, 64,
- 96, 64, 96, 103, -1, 33, 77, 90, 64, 90,
- 64, 91, -1, 34, 77, 90, 64, 90, 64, 90,
- 64, 95, -1, 36, 87, -1, 43, 83, 64, 83,
- -1, 44, 83, 64, 83, -1, 26, 78, -1, -1,
- 77, 53, -1, 77, 54, -1, -1, 64, 78, -1,
- 102, 67, 41, 68, -1, 58, 100, -1, 69, 102,
- -1, 69, 87, -1, 69, 10, 69, 87, -1, 69,
- 57, -1, 81, -1, 69, 56, -1, 69, 9, 56,
- -1, 95, -1, 95, 9, 95, -1, 95, 78, 82,
- -1, 90, -1, 80, -1, 92, -1, 92, 67, 95,
- 68, -1, 51, -1, 52, -1, 102, -1, 87, -1,
- 98, -1, 85, -1, 99, -1, 67, 95, 68, -1,
- 85, -1, 102, 67, 94, 68, -1, 99, -1, 99,
- 67, 94, 68, -1, 86, -1, 90, -1, 89, -1,
- 92, -1, 69, 102, -1, 95, -1, 67, 95, 64,
- 95, 68, -1, 95, 6, 6, 93, -1, 95, 7,
- 7, 93, -1, 95, 9, 7, 93, -1, 95, 55,
- 7, 93, -1, 95, -1, 102, -1, 46, -1, 41,
- -1, 45, 67, 104, 68, -1, 94, -1, 38, -1,
- 50, -1, 49, 67, 104, 68, -1, 98, -1, 81,
- -1, 48, -1, 47, 67, 102, 68, -1, 102, 67,
- 101, 68, -1, 58, 100, 67, 101, 68, -1, 58,
- 6, 7, 100, 67, 39, 68, -1, -1, 8, 102,
- -1, 9, 102, -1, 39, -1, 38, -1, 40, -1,
- 37, -1, 60, -1, 9, 102, -1, 8, 102, -1,
- 70, 102, -1, 67, 104, 68, -1, -1, 64, 104,
- -1, 102, -1, 104, 8, 104, -1, 104, 9, 104,
- -1, 104, 10, 104, -1, 104, 11, 104, -1, 104,
- 12, 104, -1, 104, 6, 6, 104, -1, 104, 7,
- 7, 104, -1, 104, 5, 104, -1, 104, 4, 104,
- -1, 104, 3, 104, -1
+ 73, 0, -1, -1, -1, 73, 74, 75, -1, -1,
+ 59, 62, 76, 75, -1, 59, 63, 106, 64, -1,
+ 61, 63, 106, 64, -1, 64, -1, 77, 64, -1,
+ 1, 64, -1, 13, 78, 90, 65, 97, 65, 92,
+ -1, 13, 78, 90, 65, 97, 65, -1, 13, 78,
+ 90, 65, 92, -1, 14, 78, 90, 65, 92, -1,
+ 15, 78, 85, 65, 85, -1, 16, 78, 79, 80,
+ -1, 16, 78, 79, 86, -1, 36, 79, 87, -1,
+ 17, 79, 80, -1, 18, 78, 79, 85, -1, 19,
+ 78, 90, 65, 97, 79, -1, 20, 78, 88, 65,
+ 66, 84, 67, -1, 20, 78, 66, 84, 67, 65,
+ 88, -1, 21, 78, 92, 65, 87, 65, 92, -1,
+ 21, 78, 92, 65, 87, 79, -1, 21, 78, 79,
+ 87, 65, 92, -1, 22, 78, 79, -1, 23, 101,
+ 65, 68, 81, -1, 23, 101, 65, 104, 65, 68,
+ 81, -1, 24, 101, 65, 91, -1, 24, 101, 65,
+ 104, 65, 91, -1, 25, 101, 11, 104, 65, 82,
+ -1, 26, 78, 92, 79, -1, 29, 79, 82, -1,
+ 30, 78, 100, 65, 100, -1, 32, 78, 99, 65,
+ 100, -1, 32, 78, 99, 65, 49, 65, 100, -1,
+ 33, 78, 100, 65, 100, 79, -1, 31, 78, 104,
+ 65, 106, 65, 97, 65, 98, 65, 98, 105, -1,
+ 34, 78, 92, 65, 92, 65, 93, -1, 35, 78,
+ 92, 65, 92, 65, 92, 65, 97, -1, 37, 89,
+ -1, 44, 85, 65, 85, -1, 45, 85, 65, 85,
+ -1, 27, 79, -1, -1, 78, 54, -1, 78, 55,
+ -1, -1, 65, 79, -1, 104, 69, 42, 70, -1,
+ 59, 102, -1, 38, -1, 9, 38, -1, 38, 9,
+ 38, -1, 9, 38, 9, 38, -1, 68, 104, -1,
+ 68, 89, -1, 68, 58, -1, 83, -1, 68, 57,
+ -1, 68, 9, 57, -1, 97, -1, 97, 9, 97,
+ -1, 97, 79, 84, -1, 92, -1, 82, -1, 94,
+ -1, 94, 69, 97, 70, -1, 52, -1, 53, -1,
+ 104, -1, 89, -1, 100, -1, 87, -1, 101, -1,
+ 69, 97, 70, -1, 87, -1, 104, 69, 96, 70,
+ -1, 101, -1, 101, 69, 96, 70, -1, 88, -1,
+ 92, -1, 91, -1, 94, -1, 68, 104, -1, 97,
+ -1, 69, 97, 65, 97, 70, -1, 97, 6, 6,
+ 95, -1, 97, 7, 7, 95, -1, 97, 9, 7,
+ 95, -1, 97, 56, 7, 95, -1, 97, -1, 104,
+ -1, 47, -1, 42, -1, 46, 69, 106, 70, -1,
+ 96, -1, 39, -1, 51, -1, 50, 69, 106, 70,
+ -1, 100, -1, 83, -1, 49, -1, 48, 69, 104,
+ 70, -1, 104, 69, 103, 70, -1, 59, 102, 69,
+ 103, 70, -1, 59, 6, 7, 102, 69, 40, 70,
+ -1, -1, 8, 104, -1, 9, 104, -1, 40, -1,
+ 39, -1, 41, -1, 38, -1, 61, -1, 9, 104,
+ -1, 8, 104, -1, 71, 104, -1, 69, 106, 70,
+ -1, -1, 65, 106, -1, 104, -1, 106, 8, 106,
+ -1, 106, 9, 106, -1, 106, 10, 106, -1, 106,
+ 11, 106, -1, 106, 12, 106, -1, 106, 6, 6,
+ 106, -1, 106, 7, 7, 106, -1, 106, 5, 106,
+ -1, 106, 4, 106, -1, 106, 3, 106, -1
};
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
0, 68, 68, 70, 69, 77, 76, 85, 90, 96,
97, 98, 104, 108, 112, 119, 126, 133, 137, 144,
151, 158, 165, 172, 181, 193, 197, 201, 208, 215,
- 222, 229, 239, 246, 253, 260, 264, 268, 272, 279,
- 301, 309, 318, 325, 334, 345, 351, 354, 358, 363,
- 364, 367, 373, 383, 389, 394, 399, 405, 408, 414,
- 422, 426, 435, 441, 442, 443, 444, 449, 455, 461,
- 467, 468, 471, 472, 480, 489, 490, 499, 500, 506,
- 509, 510, 511, 513, 521, 529, 538, 544, 550, 556,
- 564, 570, 578, 579, 583, 591, 592, 598, 599, 607,
- 608, 611, 617, 625, 633, 641, 651, 654, 658, 664,
- 665, 666, 669, 670, 674, 678, 682, 686, 692, 695,
- 701, 702, 706, 710, 714, 718, 722, 726, 730, 734,
- 738
+ 220, 232, 237, 249, 260, 267, 274, 278, 282, 286,
+ 293, 315, 323, 332, 339, 348, 359, 365, 368, 372,
+ 377, 378, 381, 387, 398, 405, 412, 419, 427, 433,
+ 438, 444, 447, 453, 461, 465, 474, 480, 481, 482,
+ 483, 488, 494, 500, 506, 507, 510, 511, 519, 528,
+ 529, 538, 539, 545, 548, 549, 550, 552, 560, 568,
+ 577, 583, 589, 595, 603, 609, 617, 618, 622, 630,
+ 631, 637, 638, 646, 647, 650, 656, 664, 672, 680,
+ 690, 693, 697, 703, 704, 705, 708, 709, 713, 717,
+ 721, 725, 731, 734, 740, 741, 745, 749, 753, 757,
+ 761, 765, 769, 773, 777
};
#endif
"$end", "error", "$undefined", "'|'", "'^'", "'&'", "'<'", "'>'", "'+'",
"'-'", "'*'", "'/'", "'%'", "LTYPE1", "LTYPE2", "LTYPE3", "LTYPE4",
"LTYPE5", "LTYPE6", "LTYPE7", "LTYPE8", "LTYPE9", "LTYPEA", "LTYPEB",
- "LTYPEC", "LTYPED", "LTYPEE", "LTYPEG", "LTYPEH", "LTYPEI", "LTYPEJ",
- "LTYPEK", "LTYPEL", "LTYPEM", "LTYPEN", "LTYPEBX", "LTYPEPLD", "LCONST",
- "LSP", "LSB", "LFP", "LPC", "LTYPEX", "LTYPEPC", "LTYPEF", "LR", "LREG",
- "LF", "LFREG", "LC", "LCREG", "LPSR", "LFCR", "LCOND", "LS", "LAT",
- "LFCONST", "LSCONST", "LNAME", "LLAB", "LVAR", "':'", "'='", "';'",
- "','", "'['", "']'", "'('", "')'", "'$'", "'~'", "$accept", "prog", "@1",
- "line", "@2", "inst", "cond", "comma", "rel", "ximm", "fcon", "reglist",
- "gen", "nireg", "ireg", "ioreg", "oreg", "imsr", "imm", "reg", "regreg",
- "shift", "rcon", "sreg", "spreg", "creg", "frcon", "freg", "name",
- "offset", "pointer", "con", "oexpr", "expr", 0
+ "LGLOBL", "LTYPEC", "LTYPED", "LTYPEE", "LTYPEG", "LTYPEH", "LTYPEI",
+ "LTYPEJ", "LTYPEK", "LTYPEL", "LTYPEM", "LTYPEN", "LTYPEBX", "LTYPEPLD",
+ "LCONST", "LSP", "LSB", "LFP", "LPC", "LTYPEX", "LTYPEPC", "LTYPEF",
+ "LR", "LREG", "LF", "LFREG", "LC", "LCREG", "LPSR", "LFCR", "LCOND",
+ "LS", "LAT", "LFCONST", "LSCONST", "LNAME", "LLAB", "LVAR", "':'", "'='",
+ "';'", "','", "'['", "']'", "'$'", "'('", "')'", "'~'", "$accept",
+ "prog", "@1", "line", "@2", "inst", "cond", "comma", "rel", "textsize",
+ "ximm", "fcon", "reglist", "gen", "nireg", "ireg", "ioreg", "oreg",
+ "imsr", "imm", "reg", "regreg", "shift", "rcon", "sreg", "spreg", "creg",
+ "frcon", "freg", "name", "offset", "pointer", "con", "oexpr", "expr", 0
};
#endif
275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
295, 296, 297, 298, 299, 300, 301, 302, 303, 304,
- 305, 58, 61, 59, 44, 91, 93, 40, 41, 36,
- 126
+ 305, 306, 58, 61, 59, 44, 91, 93, 36, 40,
+ 41, 126
};
# endif
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
static const yytype_uint8 yyr1[] =
{
- 0, 71, 72, 73, 72, 75, 74, 74, 74, 74,
- 74, 74, 76, 76, 76, 76, 76, 76, 76, 76,
- 76, 76, 76, 76, 76, 76, 76, 76, 76, 76,
- 76, 76, 76, 76, 76, 76, 76, 76, 76, 76,
- 76, 76, 76, 76, 76, 76, 77, 77, 77, 78,
- 78, 79, 79, 80, 80, 80, 80, 80, 81, 81,
- 82, 82, 82, 83, 83, 83, 83, 83, 83, 83,
- 83, 83, 84, 84, 85, 86, 86, 87, 87, 87,
- 88, 88, 88, 89, 90, 91, 92, 92, 92, 92,
- 93, 93, 94, 94, 94, 95, 95, 96, 96, 97,
- 97, 98, 98, 99, 99, 99, 100, 100, 100, 101,
- 101, 101, 102, 102, 102, 102, 102, 102, 103, 103,
- 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
- 104
+ 0, 72, 73, 74, 73, 76, 75, 75, 75, 75,
+ 75, 75, 77, 77, 77, 77, 77, 77, 77, 77,
+ 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
+ 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
+ 77, 77, 77, 77, 77, 77, 77, 78, 78, 78,
+ 79, 79, 80, 80, 81, 81, 81, 81, 82, 82,
+ 82, 82, 83, 83, 84, 84, 84, 85, 85, 85,
+ 85, 85, 85, 85, 85, 85, 86, 86, 87, 88,
+ 88, 89, 89, 89, 90, 90, 90, 91, 92, 93,
+ 94, 94, 94, 94, 95, 95, 96, 96, 96, 97,
+ 97, 98, 98, 99, 99, 100, 100, 101, 101, 101,
+ 102, 102, 102, 103, 103, 103, 104, 104, 104, 104,
+ 104, 104, 105, 105, 106, 106, 106, 106, 106, 106,
+ 106, 106, 106, 106, 106
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
{
0, 2, 0, 0, 3, 0, 4, 4, 4, 1,
2, 2, 7, 6, 5, 5, 5, 4, 4, 3,
- 3, 4, 6, 7, 7, 7, 6, 6, 3, 4,
- 6, 8, 6, 4, 3, 5, 5, 7, 6, 12,
- 7, 9, 2, 4, 4, 2, 0, 2, 2, 0,
- 2, 4, 2, 2, 2, 4, 2, 1, 2, 3,
- 1, 3, 3, 1, 1, 1, 4, 1, 1, 1,
- 1, 1, 1, 1, 3, 1, 4, 1, 4, 1,
- 1, 1, 1, 2, 1, 5, 4, 4, 4, 4,
- 1, 1, 1, 1, 4, 1, 1, 1, 4, 1,
- 1, 1, 4, 4, 5, 7, 0, 2, 2, 1,
- 1, 1, 1, 1, 2, 2, 2, 3, 0, 2,
- 1, 3, 3, 3, 3, 3, 4, 4, 3, 3,
- 3
+ 3, 4, 6, 7, 7, 7, 6, 6, 3, 5,
+ 7, 4, 6, 6, 4, 3, 5, 5, 7, 6,
+ 12, 7, 9, 2, 4, 4, 2, 0, 2, 2,
+ 0, 2, 4, 2, 1, 2, 3, 4, 2, 2,
+ 2, 1, 2, 3, 1, 3, 3, 1, 1, 1,
+ 4, 1, 1, 1, 1, 1, 1, 1, 3, 1,
+ 4, 1, 4, 1, 1, 1, 1, 2, 1, 5,
+ 4, 4, 4, 4, 1, 1, 1, 1, 4, 1,
+ 1, 1, 4, 1, 1, 1, 4, 4, 5, 7,
+ 0, 2, 2, 1, 1, 1, 1, 1, 2, 2,
+ 2, 3, 0, 2, 1, 3, 3, 3, 3, 3,
+ 4, 4, 3, 3, 3
};
/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
means the default is an error. */
static const yytype_uint8 yydefact[] =
{
- 2, 3, 1, 0, 0, 46, 46, 46, 46, 49,
- 46, 46, 46, 46, 46, 0, 0, 46, 49, 49,
- 46, 46, 46, 46, 46, 46, 49, 0, 0, 0,
- 0, 0, 9, 4, 0, 11, 0, 0, 0, 49,
- 49, 0, 49, 0, 0, 49, 49, 0, 0, 112,
- 106, 113, 0, 0, 0, 0, 0, 0, 45, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 75, 79,
- 42, 77, 0, 96, 93, 0, 92, 0, 101, 67,
- 68, 0, 64, 57, 0, 70, 63, 65, 95, 84,
- 71, 69, 0, 5, 0, 0, 10, 47, 48, 0,
- 0, 81, 80, 82, 0, 0, 0, 50, 106, 20,
- 0, 0, 0, 0, 0, 0, 0, 0, 84, 28,
- 115, 114, 0, 0, 0, 0, 120, 0, 116, 0,
- 0, 0, 49, 34, 0, 0, 0, 100, 0, 99,
- 0, 0, 0, 0, 19, 0, 0, 0, 0, 0,
- 0, 0, 58, 56, 54, 53, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 83, 0, 0, 0,
- 106, 17, 18, 72, 73, 0, 52, 0, 21, 0,
- 0, 49, 0, 0, 0, 0, 106, 107, 108, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 117, 29, 0, 110, 109, 111, 0, 0, 33, 0,
- 0, 0, 0, 0, 0, 0, 74, 0, 0, 0,
- 0, 59, 0, 43, 0, 0, 0, 0, 0, 44,
- 6, 7, 8, 14, 84, 15, 16, 52, 0, 0,
- 49, 0, 0, 0, 0, 0, 49, 0, 0, 130,
- 129, 128, 0, 0, 121, 122, 123, 124, 125, 0,
- 103, 0, 35, 0, 101, 36, 49, 0, 0, 78,
- 76, 94, 102, 55, 66, 86, 90, 91, 87, 88,
- 89, 13, 51, 22, 0, 61, 62, 0, 27, 49,
- 26, 0, 104, 126, 127, 30, 32, 0, 0, 38,
- 0, 0, 12, 24, 23, 25, 0, 0, 0, 37,
- 0, 40, 0, 105, 31, 0, 0, 0, 0, 97,
- 0, 0, 41, 0, 0, 0, 0, 118, 85, 98,
- 0, 39, 119
+ 2, 3, 1, 0, 0, 47, 47, 47, 47, 50,
+ 47, 47, 47, 47, 47, 0, 0, 0, 47, 50,
+ 50, 47, 47, 47, 47, 47, 47, 50, 0, 0,
+ 0, 0, 0, 9, 4, 0, 11, 0, 0, 0,
+ 50, 50, 0, 50, 0, 0, 50, 50, 0, 0,
+ 116, 110, 117, 0, 0, 0, 0, 0, 0, 0,
+ 46, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 79, 83, 43, 81, 0, 100, 97, 0, 96, 0,
+ 105, 71, 72, 0, 68, 61, 0, 74, 67, 69,
+ 99, 88, 75, 73, 0, 5, 0, 0, 10, 48,
+ 49, 0, 0, 85, 84, 86, 0, 0, 0, 51,
+ 110, 20, 0, 0, 0, 0, 0, 0, 0, 0,
+ 88, 28, 119, 118, 0, 0, 0, 0, 124, 0,
+ 120, 0, 0, 0, 0, 50, 35, 0, 0, 0,
+ 104, 0, 103, 0, 0, 0, 0, 19, 0, 0,
+ 0, 0, 0, 0, 62, 60, 59, 58, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 87, 0,
+ 0, 0, 110, 17, 18, 76, 77, 0, 53, 0,
+ 21, 0, 0, 50, 0, 0, 0, 0, 110, 111,
+ 112, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 121, 0, 0, 114, 113, 115, 0, 31,
+ 0, 0, 34, 0, 0, 0, 0, 0, 0, 0,
+ 78, 0, 0, 0, 0, 63, 44, 0, 0, 0,
+ 0, 0, 45, 6, 7, 8, 14, 88, 15, 16,
+ 53, 0, 0, 50, 0, 0, 0, 0, 0, 50,
+ 0, 0, 134, 133, 132, 0, 0, 125, 126, 127,
+ 128, 129, 0, 54, 29, 0, 107, 0, 0, 36,
+ 0, 105, 37, 50, 0, 0, 82, 80, 98, 106,
+ 70, 90, 94, 95, 91, 92, 93, 13, 52, 22,
+ 0, 65, 66, 0, 27, 50, 26, 0, 108, 130,
+ 131, 55, 0, 0, 32, 33, 0, 0, 39, 0,
+ 0, 12, 24, 23, 25, 0, 0, 56, 30, 0,
+ 38, 0, 41, 0, 109, 57, 0, 0, 0, 0,
+ 101, 0, 0, 42, 0, 0, 0, 0, 122, 89,
+ 102, 0, 40, 123
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int16 yydefgoto[] =
{
- -1, 1, 3, 33, 163, 34, 36, 107, 109, 82,
- 83, 180, 84, 172, 68, 69, 85, 100, 101, 86,
- 311, 87, 275, 88, 118, 320, 138, 90, 71, 125,
- 206, 126, 331, 127
+ -1, 1, 3, 34, 165, 35, 37, 109, 111, 264,
+ 84, 85, 182, 86, 174, 70, 71, 87, 102, 103,
+ 88, 322, 89, 281, 90, 120, 331, 141, 92, 73,
+ 127, 208, 128, 342, 129
};
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
-#define YYPACT_NINF -125
+#define YYPACT_NINF -130
static const yytype_int16 yypact[] =
{
- -125, 7, -125, 308, -41, -125, -125, -125, -125, -19,
- -125, -125, -125, -125, -125, 80, 80, -125, -19, -19,
- -125, -125, -125, -125, -125, -125, -19, 405, 364, 364,
- -31, -15, -125, -125, -2, -125, 528, 528, 337, -18,
- -19, 409, -18, 528, 230, 187, -18, 448, 448, -125,
- 257, -125, 448, 448, -6, 15, 94, 309, -125, 49,
- 19, 44, 95, 19, 309, 309, 63, 391, -125, -125,
- -125, 90, 137, -125, -125, 145, -125, 146, -125, -125,
- -125, 66, -125, -125, 52, -125, -125, 150, -125, 147,
- -125, 137, 57, -125, 448, 448, -125, -125, -125, 448,
- 167, -125, -125, -125, 184, 200, 431, -125, 47, -125,
- 201, 364, 217, 189, 223, 221, 63, 228, -125, -125,
- -125, -125, 289, 448, 448, 231, -125, 181, -125, 411,
- 54, 448, -19, -125, 237, 238, 12, -125, 240, -125,
- 241, 244, 246, 189, -125, 245, 114, 319, 448, 448,
- 417, 243, -125, -125, -125, 137, 364, 189, 293, 312,
- 313, 341, 364, 308, 542, 552, -125, 189, 189, 364,
- 257, -125, -125, -125, -125, 282, -125, 315, -125, 189,
- 287, 42, 296, 114, 303, 63, 47, -125, -125, 54,
- 448, 448, 448, 363, 369, 448, 448, 448, 448, 448,
- -125, -125, 306, -125, -125, -125, 311, 316, -125, 53,
- 448, 321, 65, 53, 189, 189, -125, 318, 324, 250,
- 325, -125, 405, -125, 326, 391, 391, 391, 391, -125,
- -125, -125, -125, -125, 317, -125, -125, 231, 130, 328,
- -19, 323, 189, 189, 189, 189, 334, 336, 340, 602,
- 621, 628, 448, 448, 197, 197, -125, -125, -125, 352,
- -125, 49, -125, 516, 359, -125, -19, 366, 371, -125,
- -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
- -125, 189, -125, -125, 474, -125, -125, 361, -125, 165,
- -125, 399, -125, 235, 235, 432, -125, 189, 53, -125,
- 376, 189, -125, -125, -125, -125, 377, 448, 380, -125,
- 189, -125, 383, -125, -125, 112, 385, 189, 386, -125,
- 388, 189, -125, 448, 112, 382, 267, 395, -125, -125,
- 448, -125, 613
+ -130, 12, -130, 305, -35, -130, -130, -130, -130, -33,
+ -130, -130, -130, -130, -130, 427, 427, 427, -130, -33,
+ -33, -130, -130, -130, -130, -130, -130, -33, 445, 370,
+ 370, 10, -24, -130, -130, -30, -130, 140, 140, 335,
+ -13, -33, 449, -13, 140, 70, 484, -13, 359, 359,
+ -130, 114, -130, 359, 359, 27, -11, 62, 76, 167,
+ -130, 7, 171, 424, 64, 171, 167, 167, 65, 405,
+ -130, -130, -130, 68, 74, -130, -130, 78, -130, 86,
+ -130, -130, -130, 402, -130, -130, 96, -130, -130, 107,
+ -130, 21, -130, 74, 118, -130, 359, 359, -130, -130,
+ -130, 359, 131, -130, -130, -130, 150, 158, 473, -130,
+ 98, -130, 155, 370, 187, 43, 192, 199, 65, 205,
+ -130, -130, -130, -130, 262, 359, 359, 203, -130, 90,
+ -130, 106, 164, 233, 359, -33, -130, 211, 223, -3,
+ -130, 226, -130, 231, 235, 240, 43, -130, 220, 122,
+ 608, 359, 359, 491, -130, -130, -130, 74, 370, 43,
+ 287, 291, 300, 301, 370, 305, 560, 582, -130, 43,
+ 43, 370, 114, -130, -130, -130, -130, 264, -130, 267,
+ -130, 43, 279, -4, 281, 122, 283, 65, 98, -130,
+ -130, 164, 359, 359, 359, 345, 356, 359, 359, 359,
+ 359, 359, -130, 15, 306, -130, -130, -130, 282, -130,
+ 307, 310, -130, 32, 359, 308, 132, 32, 43, 43,
+ -130, 315, 316, 225, 321, -130, -130, 322, 405, 405,
+ 405, 405, -130, -130, -130, -130, -130, 311, -130, -130,
+ 203, 204, 323, -33, 333, 43, 43, 43, 43, 334,
+ 331, 337, 631, 611, 547, 359, 359, 228, 228, -130,
+ -130, -130, 332, 371, -130, 353, -130, 357, 7, -130,
+ 350, 336, -130, -33, 340, 361, -130, -130, -130, -130,
+ -130, -130, -130, -130, -130, -130, -130, 43, -130, -130,
+ 513, -130, -130, 360, -130, 146, -130, 384, -130, 303,
+ 303, 425, 399, 15, -130, -130, 43, 32, -130, 373,
+ 43, -130, -130, -130, -130, 375, 408, -130, -130, 383,
+ -130, 43, -130, 385, -130, -130, 120, 390, 43, 380,
+ -130, 391, 43, -130, 359, 120, 394, 275, 403, -130,
+ -130, 359, -130, 622
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int16 yypgoto[] =
{
- -125, -125, -125, 292, -125, -125, 578, 45, 354, -56,
- 400, -48, -25, -125, -7, -42, -21, -5, -124, 5,
- -125, -10, 89, -118, -28, 140, -125, -46, 4, -90,
- 277, -4, -125, -16
+ -130, -130, -130, 302, -130, -130, 589, 24, 362, 166,
+ -58, 411, -57, -8, -130, -61, -43, -7, 22, -129,
+ -21, -130, 72, 34, -94, -29, 137, -130, -51, 3,
+ -84, 286, 20, -130, 61
};
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
positive, shift that token. If negative, reduce the rule which
number is the opposite. If zero, do what YYDEFACT says.
If YYTABLE_NINF, syntax error. */
-#define YYTABLE_NINF -61
+#define YYTABLE_NINF -65
static const yytype_int16 yytable[] =
{
- 89, 89, 114, 133, 92, 201, 70, 2, 89, 89,
- 89, 55, 55, 105, 134, 89, 139, 140, 176, 54,
- 56, 211, 35, 72, 91, 91, 103, 103, 217, 218,
- 93, 94, 104, 103, 91, 97, 98, 110, 112, 145,
- 115, 102, 102, 120, 121, 40, 40, 95, 102, 128,
- 117, 242, 47, 48, 41, 123, 124, 135, 129, 144,
- 154, 96, 132, 58, 59, 218, 77, 78, 152, 141,
- 142, 66, 97, 98, 47, 150, 151, 155, 164, 165,
- 237, 49, 130, 89, 106, 181, 178, 111, 47, 48,
- 116, 119, 203, 204, 205, 166, 247, 97, 98, 173,
- 77, 78, 175, 49, 51, 131, 40, 91, -60, 184,
- 174, 52, 77, 264, 53, 145, 156, 49, 81, 187,
- 188, 162, 152, 153, 50, 202, 51, 207, 89, 224,
- 143, 223, 219, 67, 89, 295, 53, 229, 50, 234,
- 51, 89, 77, 78, 236, 220, 121, 52, 97, 98,
- 53, 240, 91, 158, 159, 74, 160, 146, 91, 75,
- 76, 318, 319, 262, 136, 91, 265, 266, 203, 204,
- 205, 239, 233, 235, 249, 250, 251, 208, 246, 254,
- 255, 256, 257, 258, 190, 191, 192, 193, 194, 195,
- 196, 197, 198, 199, 263, 286, 287, 276, 276, 276,
- 276, 273, 161, 73, 147, 296, 74, 197, 198, 199,
- 75, 76, 148, 149, 285, 181, 181, 157, 72, 267,
- 268, 277, 277, 277, 277, 73, 243, 73, 74, 40,
- 74, 167, 75, 76, 75, 76, 293, 294, 47, 48,
- 97, 98, 303, 195, 196, 197, 198, 199, 168, 200,
- 288, 40, 309, 190, 191, 192, 193, 194, 195, 196,
- 197, 198, 199, 122, 169, 123, 124, 49, 177, 308,
- 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
- 115, 179, 316, 97, 98, 283, 302, 182, 183, 322,
- 51, 290, 185, 325, 305, 113, 186, 67, 189, 225,
- 53, 209, 210, 314, 212, 213, 312, 326, 214, 4,
- 215, 299, 222, 216, 332, 278, 279, 280, 271, 226,
- 227, 5, 6, 7, 8, 9, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 329, 19, 20, 21, 22,
- 23, 24, 25, 26, 27, 47, 48, 73, 228, 238,
- 74, 28, 29, 241, 75, 76, 239, 203, 204, 205,
- 74, 244, 97, 98, 75, 76, 30, 245, 31, 252,
- 259, 32, 47, 48, 49, 73, 253, 221, 74, 260,
- 261, 281, 75, 76, 77, 78, 269, 284, 79, 80,
- 97, 98, 270, 272, 274, 50, 282, 51, 289, 47,
- 48, 49, 73, 291, 67, 74, 81, 53, 292, 75,
- 76, 77, 78, 47, 48, 79, 80, 47, 48, 47,
- 48, 99, 50, 298, 51, 47, 48, 304, 49, 73,
- 300, 67, 74, 81, 53, 301, 75, 76, 306, 47,
- 48, 307, 49, 310, 315, 313, 49, 317, 49, 321,
- 328, 51, 324, 323, 49, 230, 47, 48, 52, 330,
- 171, 53, 137, 50, 327, 51, 248, 108, 49, 51,
- 0, 51, 67, 221, 0, 53, 52, 51, 52, 53,
- 99, 53, 47, 48, 52, 49, 0, 53, 0, 170,
- 0, 51, 0, 0, 0, 0, 0, 0, 67, 0,
- 0, 53, 0, 0, 0, 0, 0, 0, 51, 0,
- 0, 49, 0, 0, 0, 52, 0, 0, 53, 190,
- 191, 192, 193, 194, 195, 196, 197, 198, 199, 0,
- 0, 0, 0, 0, 51, 0, 0, 0, 0, 0,
- 0, 67, 0, 0, 53, 190, 191, 192, 193, 194,
- 195, 196, 197, 198, 199, 190, 191, 192, 193, 194,
- 195, 196, 197, 198, 199, 0, 73, 0, 0, 74,
- 0, 0, 0, 75, 76, 0, 0, 0, 0, 0,
- 297, 97, 98, 0, 37, 38, 39, 0, 42, 43,
- 44, 45, 46, 0, 0, 57, 0, 99, 60, 61,
- 62, 63, 64, 65, 0, 231, 191, 192, 193, 194,
- 195, 196, 197, 198, 199, 232, 190, 191, 192, 193,
- 194, 195, 196, 197, 198, 199, 192, 193, 194, 195,
- 196, 197, 198, 199, 193, 194, 195, 196, 197, 198,
- 199
+ 91, 91, 116, 136, 209, 245, 215, 147, 91, 91,
+ 91, 137, 2, 142, 143, 91, 104, 104, 55, 57,
+ 58, 72, 94, 104, 262, 119, 178, 160, 161, 36,
+ 162, 107, 41, 42, 98, 56, 56, 56, 135, 97,
+ 148, 99, 100, 60, 61, 144, 145, 175, 74, 93,
+ 93, 68, 41, 263, 154, 221, 222, 186, 132, 93,
+ 106, 41, 112, -64, 108, 117, 114, 113, 122, 123,
+ 118, 121, 95, 96, 130, 83, 156, 163, 48, 49,
+ 79, 80, 75, 138, 91, 76, 183, 134, 240, 77,
+ 78, 222, 131, 192, 193, 194, 195, 196, 197, 198,
+ 199, 200, 201, 157, 250, 180, 125, 126, 50, 105,
+ 105, 176, 79, 80, 48, 49, 105, 148, 99, 100,
+ 124, 168, 125, 126, 99, 100, 249, 133, 177, 91,
+ 227, 52, 139, 93, 146, 91, 115, 149, 304, 69,
+ 237, 54, 91, 150, 50, 189, 190, 151, 236, 238,
+ 226, 204, 243, 210, 211, 152, 232, 166, 167, 212,
+ 202, 158, 269, 239, 76, 272, 273, 52, 77, 78,
+ 329, 330, 224, 123, 203, 53, 159, 54, 93, 75,
+ 79, 271, 76, 164, 93, 75, 77, 78, 76, 292,
+ 293, 93, 77, 78, 99, 100, 169, 274, 275, 282,
+ 282, 282, 282, 205, 206, 207, 75, 246, 101, 76,
+ 305, 41, 223, 77, 78, 170, 291, 183, 183, 79,
+ 80, 99, 100, 171, 179, 99, 100, 294, 192, 193,
+ 194, 195, 196, 197, 198, 199, 200, 201, 199, 200,
+ 201, 48, 49, 205, 206, 207, 242, 312, 283, 283,
+ 283, 283, 181, 252, 253, 254, 320, 184, 257, 258,
+ 259, 260, 261, 284, 285, 286, 311, 289, 185, 188,
+ 187, 50, 191, 296, 314, 270, 213, 319, 192, 193,
+ 194, 195, 196, 197, 198, 199, 200, 201, 214, 323,
+ 220, 216, 327, 228, 52, 278, 217, 308, 229, 333,
+ 218, 101, 53, 336, 54, 219, 4, 230, 231, 242,
+ 117, 197, 198, 199, 200, 201, 299, 300, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 241, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 48, 49, 340, 244, 247, 248, 29,
+ 30, 255, 266, 192, 193, 194, 195, 196, 197, 198,
+ 199, 200, 201, 256, 31, 225, 32, 48, 49, 33,
+ 301, 265, 267, 50, 75, 268, 287, 76, 48, 49,
+ 302, 77, 78, 79, 80, 276, 277, 81, 82, 99,
+ 100, 279, 280, 288, 51, 337, 52, 50, 290, 295,
+ 297, 307, 343, 83, 69, 309, 54, 298, 50, 75,
+ 48, 153, 76, 48, 49, 306, 77, 78, 79, 80,
+ 52, 303, 81, 82, 315, 101, 310, 313, 53, 51,
+ 54, 52, 48, 49, 316, 48, 49, 317, 83, 69,
+ 50, 54, 321, 50, 75, 324, 325, 76, 326, 334,
+ 328, 77, 78, 48, 49, 332, 335, 48, 49, 154,
+ 155, 51, 50, 52, 339, 50, 52, 233, 341, 318,
+ 173, 69, 338, 54, 53, 140, 54, 251, 99, 100,
+ 0, 48, 49, 50, 0, 52, 51, 50, 52, 0,
+ 0, 0, 0, 53, 0, 54, 53, 0, 54, 48,
+ 49, 0, 0, 0, 51, 0, 52, 0, 110, 0,
+ 52, 50, 0, 0, 69, 0, 54, 0, 53, 0,
+ 54, 48, 49, 75, 0, 0, 76, 0, 0, 50,
+ 77, 78, 172, 0, 52, 0, 0, 0, 99, 100,
+ 0, 0, 69, 0, 54, 0, 0, 0, 225, 41,
+ 0, 50, 52, 195, 196, 197, 198, 199, 200, 201,
+ 53, 0, 54, 192, 193, 194, 195, 196, 197, 198,
+ 199, 200, 201, 0, 52, 0, 0, 0, 0, 0,
+ 0, 0, 69, 0, 54, 192, 193, 194, 195, 196,
+ 197, 198, 199, 200, 201, 38, 39, 40, 0, 43,
+ 44, 45, 46, 47, 0, 0, 0, 59, 0, 0,
+ 62, 63, 64, 65, 66, 67, 194, 195, 196, 197,
+ 198, 199, 200, 201, 234, 192, 193, 194, 195, 196,
+ 197, 198, 199, 200, 201, 193, 194, 195, 196, 197,
+ 198, 199, 200, 201, 0, 0, 235, 205, 206, 207,
+ 76, 0, 0, 0, 77, 78
};
static const yytype_int16 yycheck[] =
{
- 28, 29, 44, 59, 29, 129, 27, 0, 36, 37,
- 38, 15, 16, 38, 60, 43, 62, 63, 108, 15,
- 16, 9, 63, 27, 28, 29, 36, 37, 146, 147,
- 61, 62, 37, 43, 38, 53, 54, 41, 43, 67,
- 44, 36, 37, 47, 48, 64, 64, 62, 43, 53,
- 45, 9, 8, 9, 9, 8, 9, 61, 64, 66,
- 81, 63, 57, 18, 19, 183, 47, 48, 56, 64,
- 65, 26, 53, 54, 8, 9, 10, 81, 94, 95,
- 170, 37, 67, 111, 39, 113, 111, 42, 8, 9,
- 45, 46, 38, 39, 40, 99, 186, 53, 54, 106,
- 47, 48, 106, 37, 60, 11, 64, 111, 66, 116,
- 106, 67, 47, 48, 70, 143, 64, 37, 69, 123,
- 124, 64, 56, 57, 58, 129, 60, 131, 156, 157,
- 67, 156, 148, 67, 162, 259, 70, 162, 58, 167,
- 60, 169, 47, 48, 169, 149, 150, 67, 53, 54,
- 70, 179, 156, 6, 7, 41, 9, 67, 162, 45,
- 46, 49, 50, 209, 69, 169, 212, 213, 38, 39,
- 40, 41, 167, 168, 190, 191, 192, 132, 185, 195,
- 196, 197, 198, 199, 3, 4, 5, 6, 7, 8,
- 9, 10, 11, 12, 210, 243, 244, 225, 226, 227,
- 228, 222, 55, 38, 67, 261, 41, 10, 11, 12,
- 45, 46, 67, 67, 242, 243, 244, 67, 222, 214,
- 215, 225, 226, 227, 228, 38, 181, 38, 41, 64,
- 41, 64, 45, 46, 45, 46, 252, 253, 8, 9,
- 53, 54, 284, 8, 9, 10, 11, 12, 64, 68,
- 245, 64, 298, 3, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 6, 64, 8, 9, 37, 67, 297,
- 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
- 284, 64, 310, 53, 54, 240, 281, 64, 67, 317,
- 60, 246, 64, 321, 289, 65, 7, 67, 67, 6,
- 70, 64, 64, 307, 64, 64, 301, 323, 64, 1,
- 64, 266, 69, 68, 330, 226, 227, 228, 68, 7,
- 7, 13, 14, 15, 16, 17, 18, 19, 20, 21,
- 22, 23, 24, 25, 26, 68, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 8, 9, 38, 7, 67,
- 41, 43, 44, 66, 45, 46, 41, 38, 39, 40,
- 41, 65, 53, 54, 45, 46, 58, 64, 60, 6,
- 64, 63, 8, 9, 37, 38, 7, 56, 41, 68,
- 64, 64, 45, 46, 47, 48, 68, 64, 51, 52,
- 53, 54, 68, 68, 68, 58, 68, 60, 64, 8,
- 9, 37, 38, 67, 67, 41, 69, 70, 68, 45,
- 46, 47, 48, 8, 9, 51, 52, 8, 9, 8,
- 9, 69, 58, 64, 60, 8, 9, 66, 37, 38,
- 64, 67, 41, 69, 70, 64, 45, 46, 39, 8,
- 9, 9, 37, 67, 64, 68, 37, 64, 37, 64,
- 68, 60, 64, 67, 37, 163, 8, 9, 67, 64,
- 106, 70, 62, 58, 324, 60, 189, 58, 37, 60,
- -1, 60, 67, 56, -1, 70, 67, 60, 67, 70,
- 69, 70, 8, 9, 67, 37, -1, 70, -1, 58,
- -1, 60, -1, -1, -1, -1, -1, -1, 67, -1,
- -1, 70, -1, -1, -1, -1, -1, -1, 60, -1,
- -1, 37, -1, -1, -1, 67, -1, -1, 70, 3,
- 4, 5, 6, 7, 8, 9, 10, 11, 12, -1,
- -1, -1, -1, -1, 60, -1, -1, -1, -1, -1,
- -1, 67, -1, -1, 70, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, -1, 38, -1, -1, 41,
- -1, -1, -1, 45, 46, -1, -1, -1, -1, -1,
- 64, 53, 54, -1, 6, 7, 8, -1, 10, 11,
- 12, 13, 14, -1, -1, 17, -1, 69, 20, 21,
- 22, 23, 24, 25, -1, 63, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 63, 3, 4, 5, 6,
- 7, 8, 9, 10, 11, 12, 5, 6, 7, 8,
- 9, 10, 11, 12, 6, 7, 8, 9, 10, 11,
- 12
+ 29, 30, 45, 61, 133, 9, 9, 68, 37, 38,
+ 39, 62, 0, 64, 65, 44, 37, 38, 15, 16,
+ 17, 28, 30, 44, 9, 46, 110, 6, 7, 64,
+ 9, 39, 65, 9, 64, 15, 16, 17, 59, 63,
+ 69, 54, 55, 19, 20, 66, 67, 108, 28, 29,
+ 30, 27, 65, 38, 57, 149, 150, 118, 69, 39,
+ 38, 65, 42, 67, 40, 45, 44, 43, 48, 49,
+ 46, 47, 62, 63, 54, 68, 83, 56, 8, 9,
+ 48, 49, 39, 63, 113, 42, 115, 11, 172, 46,
+ 47, 185, 65, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 83, 188, 113, 8, 9, 38, 37,
+ 38, 108, 48, 49, 8, 9, 44, 146, 54, 55,
+ 6, 101, 8, 9, 54, 55, 187, 65, 108, 158,
+ 159, 61, 68, 113, 69, 164, 66, 69, 267, 69,
+ 169, 71, 171, 69, 38, 125, 126, 69, 169, 170,
+ 158, 131, 181, 133, 134, 69, 164, 96, 97, 135,
+ 70, 65, 213, 171, 42, 216, 217, 61, 46, 47,
+ 50, 51, 152, 153, 68, 69, 69, 71, 158, 39,
+ 48, 49, 42, 65, 164, 39, 46, 47, 42, 246,
+ 247, 171, 46, 47, 54, 55, 65, 218, 219, 228,
+ 229, 230, 231, 39, 40, 41, 39, 183, 68, 42,
+ 268, 65, 151, 46, 47, 65, 245, 246, 247, 48,
+ 49, 54, 55, 65, 69, 54, 55, 248, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 10, 11,
+ 12, 8, 9, 39, 40, 41, 42, 290, 228, 229,
+ 230, 231, 65, 192, 193, 194, 307, 65, 197, 198,
+ 199, 200, 201, 229, 230, 231, 287, 243, 69, 7,
+ 65, 38, 69, 249, 295, 214, 65, 306, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 65, 310,
+ 70, 65, 321, 6, 61, 70, 65, 273, 7, 328,
+ 65, 68, 69, 332, 71, 65, 1, 7, 7, 42,
+ 290, 8, 9, 10, 11, 12, 255, 256, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 69, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 8, 9, 70, 67, 66, 65, 44,
+ 45, 6, 70, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 7, 59, 57, 61, 8, 9, 64,
+ 38, 65, 65, 38, 39, 65, 65, 42, 8, 9,
+ 9, 46, 47, 48, 49, 70, 70, 52, 53, 54,
+ 55, 70, 70, 70, 59, 334, 61, 38, 65, 65,
+ 69, 65, 341, 68, 69, 65, 71, 70, 38, 39,
+ 8, 9, 42, 8, 9, 65, 46, 47, 48, 49,
+ 61, 68, 52, 53, 40, 68, 65, 67, 69, 59,
+ 71, 61, 8, 9, 9, 8, 9, 38, 68, 69,
+ 38, 71, 69, 38, 39, 70, 38, 42, 65, 69,
+ 65, 46, 47, 8, 9, 65, 65, 8, 9, 57,
+ 58, 59, 38, 61, 70, 38, 61, 165, 65, 303,
+ 108, 69, 335, 71, 69, 64, 71, 191, 54, 55,
+ -1, 8, 9, 38, -1, 61, 59, 38, 61, -1,
+ -1, -1, -1, 69, -1, 71, 69, -1, 71, 8,
+ 9, -1, -1, -1, 59, -1, 61, -1, 59, -1,
+ 61, 38, -1, -1, 69, -1, 71, -1, 69, -1,
+ 71, 8, 9, 39, -1, -1, 42, -1, -1, 38,
+ 46, 47, 59, -1, 61, -1, -1, -1, 54, 55,
+ -1, -1, 69, -1, 71, -1, -1, -1, 57, 65,
+ -1, 38, 61, 6, 7, 8, 9, 10, 11, 12,
+ 69, -1, 71, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, -1, 61, -1, -1, -1, -1, -1,
+ -1, -1, 69, -1, 71, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 6, 7, 8, -1, 10,
+ 11, 12, 13, 14, -1, -1, -1, 18, -1, -1,
+ 21, 22, 23, 24, 25, 26, 5, 6, 7, 8,
+ 9, 10, 11, 12, 64, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, -1, -1, 64, 39, 40, 41,
+ 42, -1, -1, -1, 46, 47
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
static const yytype_uint8 yystos[] =
{
- 0, 72, 0, 73, 1, 13, 14, 15, 16, 17,
- 18, 19, 20, 21, 22, 23, 24, 25, 26, 28,
- 29, 30, 31, 32, 33, 34, 35, 36, 43, 44,
- 58, 60, 63, 74, 76, 63, 77, 77, 77, 77,
- 64, 78, 77, 77, 77, 77, 77, 8, 9, 37,
- 58, 60, 67, 70, 99, 102, 99, 77, 78, 78,
- 77, 77, 77, 77, 77, 77, 78, 67, 85, 86,
- 87, 99, 102, 38, 41, 45, 46, 47, 48, 51,
- 52, 69, 80, 81, 83, 87, 90, 92, 94, 95,
- 98, 102, 83, 61, 62, 62, 63, 53, 54, 69,
- 88, 89, 90, 92, 88, 83, 78, 78, 58, 79,
- 102, 78, 88, 65, 86, 102, 78, 90, 95, 78,
- 102, 102, 6, 8, 9, 100, 102, 104, 102, 64,
- 67, 11, 90, 80, 98, 102, 69, 81, 97, 98,
- 98, 90, 90, 67, 85, 95, 67, 67, 67, 67,
- 9, 10, 56, 57, 87, 102, 64, 67, 6, 7,
- 9, 55, 64, 75, 104, 104, 102, 64, 64, 64,
- 58, 79, 84, 85, 99, 102, 100, 67, 83, 64,
- 82, 95, 64, 67, 85, 64, 7, 102, 102, 67,
- 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
- 68, 89, 102, 38, 39, 40, 101, 102, 78, 64,
- 64, 9, 64, 64, 64, 64, 68, 94, 94, 104,
- 102, 56, 69, 83, 95, 6, 7, 7, 7, 83,
- 74, 63, 63, 90, 95, 90, 83, 100, 67, 41,
- 95, 66, 9, 78, 65, 64, 85, 100, 101, 104,
- 104, 104, 6, 7, 104, 104, 104, 104, 104, 64,
- 68, 64, 98, 104, 48, 98, 98, 90, 90, 68,
- 68, 68, 68, 87, 68, 93, 95, 102, 93, 93,
- 93, 64, 68, 78, 64, 95, 82, 82, 90, 64,
- 78, 67, 68, 104, 104, 89, 80, 64, 64, 78,
- 64, 64, 90, 86, 66, 90, 39, 9, 95, 98,
- 67, 91, 90, 68, 102, 64, 95, 64, 49, 50,
- 96, 64, 95, 67, 64, 95, 104, 96, 68, 68,
- 64, 103, 104
+ 0, 73, 0, 74, 1, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 44,
+ 45, 59, 61, 64, 75, 77, 64, 78, 78, 78,
+ 78, 65, 79, 78, 78, 78, 78, 78, 8, 9,
+ 38, 59, 61, 69, 71, 101, 104, 101, 101, 78,
+ 79, 79, 78, 78, 78, 78, 78, 78, 79, 69,
+ 87, 88, 89, 101, 104, 39, 42, 46, 47, 48,
+ 49, 52, 53, 68, 82, 83, 85, 89, 92, 94,
+ 96, 97, 100, 104, 85, 62, 63, 63, 64, 54,
+ 55, 68, 90, 91, 92, 94, 90, 85, 79, 79,
+ 59, 80, 104, 79, 90, 66, 88, 104, 79, 92,
+ 97, 79, 104, 104, 6, 8, 9, 102, 104, 106,
+ 104, 65, 69, 65, 11, 92, 82, 100, 104, 68,
+ 83, 99, 100, 100, 92, 92, 69, 87, 97, 69,
+ 69, 69, 69, 9, 57, 58, 89, 104, 65, 69,
+ 6, 7, 9, 56, 65, 76, 106, 106, 104, 65,
+ 65, 65, 59, 80, 86, 87, 101, 104, 102, 69,
+ 85, 65, 84, 97, 65, 69, 87, 65, 7, 104,
+ 104, 69, 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 70, 68, 104, 39, 40, 41, 103, 91,
+ 104, 104, 79, 65, 65, 9, 65, 65, 65, 65,
+ 70, 96, 96, 106, 104, 57, 85, 97, 6, 7,
+ 7, 7, 85, 75, 64, 64, 92, 97, 92, 85,
+ 102, 69, 42, 97, 67, 9, 79, 66, 65, 87,
+ 102, 103, 106, 106, 106, 6, 7, 106, 106, 106,
+ 106, 106, 9, 38, 81, 65, 70, 65, 65, 100,
+ 106, 49, 100, 100, 92, 92, 70, 70, 70, 70,
+ 70, 95, 97, 104, 95, 95, 95, 65, 70, 79,
+ 65, 97, 84, 84, 92, 65, 79, 69, 70, 106,
+ 106, 38, 9, 68, 91, 82, 65, 65, 79, 65,
+ 65, 92, 88, 67, 92, 40, 9, 38, 81, 97,
+ 100, 69, 93, 92, 70, 38, 65, 97, 65, 50,
+ 51, 98, 65, 97, 69, 65, 97, 106, 98, 70,
+ 70, 65, 105, 106
};
#define yyerrok (yyerrstatus = 0)
case 14:
#line 113 "a.y"
{
- outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), NREG, &(yyvsp[(5) - (5)].addr));
+ outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), 0, &(yyvsp[(5) - (5)].addr));
}
break;
case 15:
#line 120 "a.y"
{
- outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), NREG, &(yyvsp[(5) - (5)].addr));
+ outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), 0, &(yyvsp[(5) - (5)].addr));
}
break;
case 16:
#line 127 "a.y"
{
- outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), NREG, &(yyvsp[(5) - (5)].addr));
+ outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), 0, &(yyvsp[(5) - (5)].addr));
}
break;
case 17:
#line 134 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), (yyvsp[(2) - (4)].lval), &nullgen, NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), (yyvsp[(2) - (4)].lval), &nullgen, 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 18:
#line 138 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), (yyvsp[(2) - (4)].lval), &nullgen, NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), (yyvsp[(2) - (4)].lval), &nullgen, 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 19:
#line 145 "a.y"
{
- outcode((yyvsp[(1) - (3)].lval), Always, &nullgen, NREG, &(yyvsp[(3) - (3)].addr));
+ outcode((yyvsp[(1) - (3)].lval), Always, &nullgen, 0, &(yyvsp[(3) - (3)].addr));
}
break;
case 20:
#line 152 "a.y"
{
- outcode((yyvsp[(1) - (3)].lval), Always, &nullgen, NREG, &(yyvsp[(3) - (3)].addr));
+ outcode((yyvsp[(1) - (3)].lval), Always, &nullgen, 0, &(yyvsp[(3) - (3)].addr));
}
break;
case 21:
#line 159 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), (yyvsp[(2) - (4)].lval), &nullgen, NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), (yyvsp[(2) - (4)].lval), &nullgen, 0, &(yyvsp[(4) - (4)].addr));
}
break;
Addr g;
g = nullgen;
- g.type = D_CONST;
+ g.type = TYPE_CONST;
g.offset = (yyvsp[(6) - (7)].lval);
- outcode((yyvsp[(1) - (7)].lval), (yyvsp[(2) - (7)].lval), &(yyvsp[(3) - (7)].addr), NREG, &g);
+ outcode((yyvsp[(1) - (7)].lval), (yyvsp[(2) - (7)].lval), &(yyvsp[(3) - (7)].addr), 0, &g);
}
break;
Addr g;
g = nullgen;
- g.type = D_CONST;
+ g.type = TYPE_CONST;
g.offset = (yyvsp[(4) - (7)].lval);
- outcode((yyvsp[(1) - (7)].lval), (yyvsp[(2) - (7)].lval), &g, NREG, &(yyvsp[(7) - (7)].addr));
+ outcode((yyvsp[(1) - (7)].lval), (yyvsp[(2) - (7)].lval), &g, 0, &(yyvsp[(7) - (7)].addr));
}
break;
case 28:
#line 209 "a.y"
{
- outcode((yyvsp[(1) - (3)].lval), (yyvsp[(2) - (3)].lval), &nullgen, NREG, &nullgen);
+ outcode((yyvsp[(1) - (3)].lval), (yyvsp[(2) - (3)].lval), &nullgen, 0, &nullgen);
}
break;
case 29:
#line 216 "a.y"
{
- settext((yyvsp[(2) - (4)].addr).sym);
- (yyvsp[(4) - (4)].addr).type = D_CONST2;
- (yyvsp[(4) - (4)].addr).offset2 = ArgsSizeUnknown;
- outcode((yyvsp[(1) - (4)].lval), Always, &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
+ settext((yyvsp[(2) - (5)].addr).sym);
+ outcode((yyvsp[(1) - (5)].lval), Always, &(yyvsp[(2) - (5)].addr), 0, &(yyvsp[(5) - (5)].addr));
}
break;
case 30:
-#line 223 "a.y"
+#line 221 "a.y"
{
- settext((yyvsp[(2) - (6)].addr).sym);
- (yyvsp[(6) - (6)].addr).type = D_CONST2;
- (yyvsp[(6) - (6)].addr).offset2 = ArgsSizeUnknown;
- outcode((yyvsp[(1) - (6)].lval), Always, &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+ settext((yyvsp[(2) - (7)].addr).sym);
+ outcode((yyvsp[(1) - (7)].lval), Always, &(yyvsp[(2) - (7)].addr), 0, &(yyvsp[(7) - (7)].addr));
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = (yyvsp[(4) - (7)].lval);
+ }
}
break;
case 31:
-#line 230 "a.y"
+#line 233 "a.y"
{
- settext((yyvsp[(2) - (8)].addr).sym);
- (yyvsp[(6) - (8)].addr).type = D_CONST2;
- (yyvsp[(6) - (8)].addr).offset2 = (yyvsp[(8) - (8)].lval);
- outcode((yyvsp[(1) - (8)].lval), Always, &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].lval), &(yyvsp[(6) - (8)].addr));
+ settext((yyvsp[(2) - (4)].addr).sym);
+ outcode((yyvsp[(1) - (4)].lval), Always, &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 32:
-#line 240 "a.y"
+#line 238 "a.y"
{
- outcode((yyvsp[(1) - (6)].lval), Always, &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+ settext((yyvsp[(2) - (6)].addr).sym);
+ outcode((yyvsp[(1) - (6)].lval), Always, &(yyvsp[(2) - (6)].addr), 0, &(yyvsp[(6) - (6)].addr));
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = (yyvsp[(4) - (6)].lval);
+ }
}
break;
case 33:
-#line 247 "a.y"
+#line 250 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), (yyvsp[(2) - (4)].lval), &(yyvsp[(3) - (4)].addr), NREG, &nullgen);
+ outcode((yyvsp[(1) - (6)].lval), Always, &(yyvsp[(2) - (6)].addr), 0, &(yyvsp[(6) - (6)].addr));
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = (yyvsp[(4) - (6)].lval);
+ }
}
break;
case 34:
-#line 254 "a.y"
+#line 261 "a.y"
{
- outcode((yyvsp[(1) - (3)].lval), Always, &nullgen, NREG, &(yyvsp[(3) - (3)].addr));
+ outcode((yyvsp[(1) - (4)].lval), (yyvsp[(2) - (4)].lval), &(yyvsp[(3) - (4)].addr), 0, &nullgen);
}
break;
case 35:
-#line 261 "a.y"
+#line 268 "a.y"
{
- outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), NREG, &(yyvsp[(5) - (5)].addr));
+ outcode((yyvsp[(1) - (3)].lval), Always, &nullgen, 0, &(yyvsp[(3) - (3)].addr));
}
break;
case 36:
-#line 265 "a.y"
+#line 275 "a.y"
{
- outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), NREG, &(yyvsp[(5) - (5)].addr));
+ outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), 0, &(yyvsp[(5) - (5)].addr));
}
break;
case 37:
-#line 269 "a.y"
+#line 279 "a.y"
{
- outcode((yyvsp[(1) - (7)].lval), (yyvsp[(2) - (7)].lval), &(yyvsp[(3) - (7)].addr), (yyvsp[(5) - (7)].lval), &(yyvsp[(7) - (7)].addr));
+ outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), 0, &(yyvsp[(5) - (5)].addr));
}
break;
case 38:
-#line 273 "a.y"
+#line 283 "a.y"
{
- outcode((yyvsp[(1) - (6)].lval), (yyvsp[(2) - (6)].lval), &(yyvsp[(3) - (6)].addr), (yyvsp[(5) - (6)].addr).reg, &nullgen);
+ outcode((yyvsp[(1) - (7)].lval), (yyvsp[(2) - (7)].lval), &(yyvsp[(3) - (7)].addr), (yyvsp[(5) - (7)].lval), &(yyvsp[(7) - (7)].addr));
}
break;
case 39:
-#line 280 "a.y"
+#line 287 "a.y"
+ {
+ outcode((yyvsp[(1) - (6)].lval), (yyvsp[(2) - (6)].lval), &(yyvsp[(3) - (6)].addr), (yyvsp[(5) - (6)].addr).reg, &nullgen);
+ }
+ break;
+
+ case 40:
+#line 294 "a.y"
{
Addr g;
g = nullgen;
- g.type = D_CONST;
+ g.type = TYPE_CONST;
g.offset =
(0xe << 24) | /* opcode */
((yyvsp[(1) - (12)].lval) << 20) | /* MCR/MRC */
- ((yyvsp[(2) - (12)].lval) << 28) | /* scond */
+ (((yyvsp[(2) - (12)].lval)^C_SCOND_XOR) << 28) | /* scond */
(((yyvsp[(3) - (12)].lval) & 15) << 8) | /* coprocessor number */
(((yyvsp[(5) - (12)].lval) & 7) << 21) | /* coprocessor operation */
(((yyvsp[(7) - (12)].lval) & 15) << 12) | /* arm register */
(((yyvsp[(11) - (12)].lval) & 15) << 0) | /* Crm */
(((yyvsp[(12) - (12)].lval) & 7) << 5) | /* coprocessor information */
(1<<4); /* must be set */
- outcode(AMRC, Always, &nullgen, NREG, &g);
+ outcode(AMRC, Always, &nullgen, 0, &g);
}
break;
- case 40:
-#line 302 "a.y"
+ case 41:
+#line 316 "a.y"
{
outcode((yyvsp[(1) - (7)].lval), (yyvsp[(2) - (7)].lval), &(yyvsp[(3) - (7)].addr), (yyvsp[(5) - (7)].addr).reg, &(yyvsp[(7) - (7)].addr));
}
break;
- case 41:
-#line 310 "a.y"
+ case 42:
+#line 324 "a.y"
{
- (yyvsp[(7) - (9)].addr).type = D_REGREG2;
+ (yyvsp[(7) - (9)].addr).type = TYPE_REGREG2;
(yyvsp[(7) - (9)].addr).offset = (yyvsp[(9) - (9)].lval);
outcode((yyvsp[(1) - (9)].lval), (yyvsp[(2) - (9)].lval), &(yyvsp[(3) - (9)].addr), (yyvsp[(5) - (9)].addr).reg, &(yyvsp[(7) - (9)].addr));
}
break;
- case 42:
-#line 319 "a.y"
+ case 43:
+#line 333 "a.y"
{
- outcode((yyvsp[(1) - (2)].lval), Always, &(yyvsp[(2) - (2)].addr), NREG, &nullgen);
+ outcode((yyvsp[(1) - (2)].lval), Always, &(yyvsp[(2) - (2)].addr), 0, &nullgen);
}
break;
- case 43:
-#line 326 "a.y"
+ case 44:
+#line 340 "a.y"
{
- if((yyvsp[(2) - (4)].addr).type != D_CONST || (yyvsp[(4) - (4)].addr).type != D_CONST)
+ if((yyvsp[(2) - (4)].addr).type != TYPE_CONST || (yyvsp[(4) - (4)].addr).type != TYPE_CONST)
yyerror("arguments to PCDATA must be integer constants");
- outcode((yyvsp[(1) - (4)].lval), Always, &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), Always, &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
- case 44:
-#line 335 "a.y"
+ case 45:
+#line 349 "a.y"
{
- if((yyvsp[(2) - (4)].addr).type != D_CONST)
+ if((yyvsp[(2) - (4)].addr).type != TYPE_CONST)
yyerror("index for FUNCDATA must be integer constant");
- if((yyvsp[(4) - (4)].addr).type != D_EXTERN && (yyvsp[(4) - (4)].addr).type != D_STATIC && (yyvsp[(4) - (4)].addr).type != D_OREG)
+ if((yyvsp[(4) - (4)].addr).type != NAME_EXTERN && (yyvsp[(4) - (4)].addr).type != NAME_STATIC && (yyvsp[(4) - (4)].addr).type != TYPE_MEM)
yyerror("value for FUNCDATA must be symbol reference");
- outcode((yyvsp[(1) - (4)].lval), Always, &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), Always, &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
- case 45:
-#line 346 "a.y"
+ case 46:
+#line 360 "a.y"
{
- outcode((yyvsp[(1) - (2)].lval), Always, &nullgen, NREG, &nullgen);
+ outcode((yyvsp[(1) - (2)].lval), Always, &nullgen, 0, &nullgen);
}
break;
- case 46:
-#line 351 "a.y"
+ case 47:
+#line 365 "a.y"
{
(yyval.lval) = Always;
}
break;
- case 47:
-#line 355 "a.y"
+ case 48:
+#line 369 "a.y"
{
(yyval.lval) = ((yyvsp[(1) - (2)].lval) & ~C_SCOND) | (yyvsp[(2) - (2)].lval);
}
break;
- case 48:
-#line 359 "a.y"
+ case 49:
+#line 373 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (2)].lval) | (yyvsp[(2) - (2)].lval);
}
break;
- case 51:
-#line 368 "a.y"
+ case 52:
+#line 382 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_BRANCH;
+ (yyval.addr).type = TYPE_BRANCH;
(yyval.addr).offset = (yyvsp[(1) - (4)].lval) + pc;
}
break;
- case 52:
-#line 374 "a.y"
+ case 53:
+#line 388 "a.y"
{
(yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym));
(yyval.addr) = nullgen;
if(pass == 2 && (yyvsp[(1) - (2)].sym)->type != LLAB)
yyerror("undefined label: %s", (yyvsp[(1) - (2)].sym)->labelname);
- (yyval.addr).type = D_BRANCH;
+ (yyval.addr).type = TYPE_BRANCH;
(yyval.addr).offset = (yyvsp[(1) - (2)].sym)->value + (yyvsp[(2) - (2)].lval);
}
break;
- case 53:
-#line 384 "a.y"
+ case 54:
+#line 399 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_CONST;
- (yyval.addr).offset = (yyvsp[(2) - (2)].lval);
+ (yyval.addr).type = TYPE_TEXTSIZE;
+ (yyval.addr).offset = (yyvsp[(1) - (1)].lval);
+ (yyval.addr).u.argsize = ArgsSizeUnknown;
}
break;
- case 54:
-#line 390 "a.y"
+ case 55:
+#line 406 "a.y"
{
- (yyval.addr) = (yyvsp[(2) - (2)].addr);
- (yyval.addr).type = D_CONST;
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = TYPE_TEXTSIZE;
+ (yyval.addr).offset = -(yyvsp[(2) - (2)].lval);
+ (yyval.addr).u.argsize = ArgsSizeUnknown;
}
break;
- case 55:
-#line 395 "a.y"
+ case 56:
+#line 413 "a.y"
{
- (yyval.addr) = (yyvsp[(4) - (4)].addr);
- (yyval.addr).type = D_OCONST;
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = TYPE_TEXTSIZE;
+ (yyval.addr).offset = (yyvsp[(1) - (3)].lval);
+ (yyval.addr).u.argsize = (yyvsp[(3) - (3)].lval);
}
break;
- case 56:
-#line 400 "a.y"
+ case 57:
+#line 420 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_SCONST;
- memcpy((yyval.addr).u.sval, (yyvsp[(2) - (2)].sval), sizeof((yyval.addr).u.sval));
+ (yyval.addr).type = TYPE_TEXTSIZE;
+ (yyval.addr).offset = -(yyvsp[(2) - (4)].lval);
+ (yyval.addr).u.argsize = (yyvsp[(4) - (4)].lval);
}
break;
case 58:
-#line 409 "a.y"
+#line 428 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_FCONST;
- (yyval.addr).u.dval = (yyvsp[(2) - (2)].dval);
+ (yyval.addr).type = TYPE_CONST;
+ (yyval.addr).offset = (yyvsp[(2) - (2)].lval);
}
break;
case 59:
-#line 415 "a.y"
+#line 434 "a.y"
+ {
+ (yyval.addr) = (yyvsp[(2) - (2)].addr);
+ (yyval.addr).type = TYPE_ADDR;
+ }
+ break;
+
+ case 60:
+#line 439 "a.y"
+ {
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = TYPE_SCONST;
+ memcpy((yyval.addr).u.sval, (yyvsp[(2) - (2)].sval), sizeof((yyval.addr).u.sval));
+ }
+ break;
+
+ case 62:
+#line 448 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_FCONST;
+ (yyval.addr).type = TYPE_FCONST;
+ (yyval.addr).u.dval = (yyvsp[(2) - (2)].dval);
+ }
+ break;
+
+ case 63:
+#line 454 "a.y"
+ {
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = TYPE_FCONST;
(yyval.addr).u.dval = -(yyvsp[(3) - (3)].dval);
}
break;
- case 60:
-#line 423 "a.y"
+ case 64:
+#line 462 "a.y"
{
(yyval.lval) = 1 << (yyvsp[(1) - (1)].lval);
}
break;
- case 61:
-#line 427 "a.y"
+ case 65:
+#line 466 "a.y"
{
int i;
(yyval.lval)=0;
}
break;
- case 62:
-#line 436 "a.y"
+ case 66:
+#line 475 "a.y"
{
(yyval.lval) = (1<<(yyvsp[(1) - (3)].lval)) | (yyvsp[(3) - (3)].lval);
}
break;
- case 66:
-#line 445 "a.y"
+ case 70:
+#line 484 "a.y"
{
(yyval.addr) = (yyvsp[(1) - (4)].addr);
(yyval.addr).reg = (yyvsp[(3) - (4)].lval);
}
break;
- case 67:
-#line 450 "a.y"
+ case 71:
+#line 489 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_PSR;
+ (yyval.addr).type = TYPE_REG;
(yyval.addr).reg = (yyvsp[(1) - (1)].lval);
}
break;
- case 68:
-#line 456 "a.y"
+ case 72:
+#line 495 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_FPCR;
+ (yyval.addr).type = TYPE_REG;
(yyval.addr).reg = (yyvsp[(1) - (1)].lval);
}
break;
- case 69:
-#line 462 "a.y"
+ case 73:
+#line 501 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_OREG;
+ (yyval.addr).type = TYPE_MEM;
(yyval.addr).offset = (yyvsp[(1) - (1)].lval);
}
break;
- case 73:
-#line 473 "a.y"
+ case 77:
+#line 512 "a.y"
{
(yyval.addr) = (yyvsp[(1) - (1)].addr);
- if((yyvsp[(1) - (1)].addr).name != D_EXTERN && (yyvsp[(1) - (1)].addr).name != D_STATIC) {
+ if((yyvsp[(1) - (1)].addr).name != NAME_EXTERN && (yyvsp[(1) - (1)].addr).name != NAME_STATIC) {
}
}
break;
- case 74:
-#line 481 "a.y"
+ case 78:
+#line 520 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_OREG;
+ (yyval.addr).type = TYPE_MEM;
(yyval.addr).reg = (yyvsp[(2) - (3)].lval);
(yyval.addr).offset = 0;
}
break;
- case 76:
-#line 491 "a.y"
+ case 80:
+#line 530 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_OREG;
+ (yyval.addr).type = TYPE_MEM;
(yyval.addr).reg = (yyvsp[(3) - (4)].lval);
(yyval.addr).offset = (yyvsp[(1) - (4)].lval);
}
break;
- case 78:
-#line 501 "a.y"
+ case 82:
+#line 540 "a.y"
{
(yyval.addr) = (yyvsp[(1) - (4)].addr);
- (yyval.addr).type = D_OREG;
+ (yyval.addr).type = TYPE_MEM;
(yyval.addr).reg = (yyvsp[(3) - (4)].lval);
}
break;
- case 83:
-#line 514 "a.y"
+ case 87:
+#line 553 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_CONST;
+ (yyval.addr).type = TYPE_CONST;
(yyval.addr).offset = (yyvsp[(2) - (2)].lval);
}
break;
- case 84:
-#line 522 "a.y"
+ case 88:
+#line 561 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_REG;
+ (yyval.addr).type = TYPE_REG;
(yyval.addr).reg = (yyvsp[(1) - (1)].lval);
}
break;
- case 85:
-#line 530 "a.y"
+ case 89:
+#line 569 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_REGREG;
+ (yyval.addr).type = TYPE_REGREG;
(yyval.addr).reg = (yyvsp[(2) - (5)].lval);
(yyval.addr).offset = (yyvsp[(4) - (5)].lval);
}
break;
- case 86:
-#line 539 "a.y"
+ case 90:
+#line 578 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_SHIFT;
- (yyval.addr).offset = (yyvsp[(1) - (4)].lval) | (yyvsp[(4) - (4)].lval) | (0 << 5);
+ (yyval.addr).type = TYPE_SHIFT;
+ (yyval.addr).offset = (yyvsp[(1) - (4)].lval)&15 | (yyvsp[(4) - (4)].lval) | (0 << 5);
}
break;
- case 87:
-#line 545 "a.y"
+ case 91:
+#line 584 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_SHIFT;
- (yyval.addr).offset = (yyvsp[(1) - (4)].lval) | (yyvsp[(4) - (4)].lval) | (1 << 5);
+ (yyval.addr).type = TYPE_SHIFT;
+ (yyval.addr).offset = (yyvsp[(1) - (4)].lval)&15 | (yyvsp[(4) - (4)].lval) | (1 << 5);
}
break;
- case 88:
-#line 551 "a.y"
+ case 92:
+#line 590 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_SHIFT;
- (yyval.addr).offset = (yyvsp[(1) - (4)].lval) | (yyvsp[(4) - (4)].lval) | (2 << 5);
+ (yyval.addr).type = TYPE_SHIFT;
+ (yyval.addr).offset = (yyvsp[(1) - (4)].lval)&15 | (yyvsp[(4) - (4)].lval) | (2 << 5);
}
break;
- case 89:
-#line 557 "a.y"
+ case 93:
+#line 596 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_SHIFT;
- (yyval.addr).offset = (yyvsp[(1) - (4)].lval) | (yyvsp[(4) - (4)].lval) | (3 << 5);
+ (yyval.addr).type = TYPE_SHIFT;
+ (yyval.addr).offset = (yyvsp[(1) - (4)].lval)&15 | (yyvsp[(4) - (4)].lval) | (3 << 5);
}
break;
- case 90:
-#line 565 "a.y"
+ case 94:
+#line 604 "a.y"
{
- if((yyval.lval) < 0 || (yyval.lval) >= 16)
- print("register value out of range\n");
+ if((yyval.lval) < REG_R0 || (yyval.lval) > REG_R15)
+ print("register value out of range in shift\n");
(yyval.lval) = (((yyvsp[(1) - (1)].lval)&15) << 8) | (1 << 4);
}
break;
- case 91:
-#line 571 "a.y"
+ case 95:
+#line 610 "a.y"
{
if((yyval.lval) < 0 || (yyval.lval) >= 32)
print("shift value out of range\n");
}
break;
- case 93:
-#line 580 "a.y"
+ case 97:
+#line 619 "a.y"
{
(yyval.lval) = REGPC;
}
break;
- case 94:
-#line 584 "a.y"
+ case 98:
+#line 623 "a.y"
{
if((yyvsp[(3) - (4)].lval) < 0 || (yyvsp[(3) - (4)].lval) >= NREG)
- print("register value out of range\n");
- (yyval.lval) = (yyvsp[(3) - (4)].lval);
+ print("register value out of range in R(...)\n");
+ (yyval.lval) = REG_R0 + (yyvsp[(3) - (4)].lval);
}
break;
- case 96:
-#line 593 "a.y"
+ case 100:
+#line 632 "a.y"
{
(yyval.lval) = REGSP;
}
break;
- case 98:
-#line 600 "a.y"
+ case 102:
+#line 639 "a.y"
{
if((yyvsp[(3) - (4)].lval) < 0 || (yyvsp[(3) - (4)].lval) >= NREG)
- print("register value out of range\n");
- (yyval.lval) = (yyvsp[(3) - (4)].lval);
+ print("register value out of range in C(...)\n");
+ (yyval.lval) = (yyvsp[(3) - (4)].lval); // TODO(rsc): REG_C0+$3
}
break;
- case 101:
-#line 612 "a.y"
+ case 105:
+#line 651 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_FREG;
+ (yyval.addr).type = TYPE_REG;
(yyval.addr).reg = (yyvsp[(1) - (1)].lval);
}
break;
- case 102:
-#line 618 "a.y"
+ case 106:
+#line 657 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_FREG;
- (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
+ (yyval.addr).type = TYPE_REG;
+ (yyval.addr).reg = REG_F0 + (yyvsp[(3) - (4)].lval);
}
break;
- case 103:
-#line 626 "a.y"
+ case 107:
+#line 665 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_OREG;
+ (yyval.addr).type = TYPE_MEM;
(yyval.addr).name = (yyvsp[(3) - (4)].lval);
(yyval.addr).sym = nil;
(yyval.addr).offset = (yyvsp[(1) - (4)].lval);
}
break;
- case 104:
-#line 634 "a.y"
+ case 108:
+#line 673 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_OREG;
+ (yyval.addr).type = TYPE_MEM;
(yyval.addr).name = (yyvsp[(4) - (5)].lval);
(yyval.addr).sym = linklookup(ctxt, (yyvsp[(1) - (5)].sym)->name, 0);
(yyval.addr).offset = (yyvsp[(2) - (5)].lval);
}
break;
- case 105:
-#line 642 "a.y"
+ case 109:
+#line 681 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_OREG;
- (yyval.addr).name = D_STATIC;
+ (yyval.addr).type = TYPE_MEM;
+ (yyval.addr).name = NAME_STATIC;
(yyval.addr).sym = linklookup(ctxt, (yyvsp[(1) - (7)].sym)->name, 1);
(yyval.addr).offset = (yyvsp[(4) - (7)].lval);
}
break;
- case 106:
-#line 651 "a.y"
+ case 110:
+#line 690 "a.y"
{
(yyval.lval) = 0;
}
break;
- case 107:
-#line 655 "a.y"
+ case 111:
+#line 694 "a.y"
{
(yyval.lval) = (yyvsp[(2) - (2)].lval);
}
break;
- case 108:
-#line 659 "a.y"
+ case 112:
+#line 698 "a.y"
{
(yyval.lval) = -(yyvsp[(2) - (2)].lval);
}
break;
- case 113:
-#line 671 "a.y"
+ case 117:
+#line 710 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (1)].sym)->value;
}
break;
- case 114:
-#line 675 "a.y"
+ case 118:
+#line 714 "a.y"
{
(yyval.lval) = -(yyvsp[(2) - (2)].lval);
}
break;
- case 115:
-#line 679 "a.y"
+ case 119:
+#line 718 "a.y"
{
(yyval.lval) = (yyvsp[(2) - (2)].lval);
}
break;
- case 116:
-#line 683 "a.y"
+ case 120:
+#line 722 "a.y"
{
(yyval.lval) = ~(yyvsp[(2) - (2)].lval);
}
break;
- case 117:
-#line 687 "a.y"
+ case 121:
+#line 726 "a.y"
{
(yyval.lval) = (yyvsp[(2) - (3)].lval);
}
break;
- case 118:
-#line 692 "a.y"
+ case 122:
+#line 731 "a.y"
{
(yyval.lval) = 0;
}
break;
- case 119:
-#line 696 "a.y"
+ case 123:
+#line 735 "a.y"
{
(yyval.lval) = (yyvsp[(2) - (2)].lval);
}
break;
- case 121:
-#line 703 "a.y"
+ case 125:
+#line 742 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval);
}
break;
- case 122:
-#line 707 "a.y"
+ case 126:
+#line 746 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval);
}
break;
- case 123:
-#line 711 "a.y"
+ case 127:
+#line 750 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval);
}
break;
- case 124:
-#line 715 "a.y"
+ case 128:
+#line 754 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval);
}
break;
- case 125:
-#line 719 "a.y"
+ case 129:
+#line 758 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval);
}
break;
- case 126:
-#line 723 "a.y"
+ case 130:
+#line 762 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval);
}
break;
- case 127:
-#line 727 "a.y"
+ case 131:
+#line 766 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval);
}
break;
- case 128:
-#line 731 "a.y"
+ case 132:
+#line 770 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval);
}
break;
- case 129:
-#line 735 "a.y"
+ case 133:
+#line 774 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval);
}
break;
- case 130:
-#line 739 "a.y"
+ case 134:
+#line 778 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) | (yyvsp[(3) - (3)].lval);
}
/* Line 1267 of yacc.c. */
-#line 2576 "y.tab.c"
+#line 2630 "y.tab.c"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
LTYPE9 = 266,
LTYPEA = 267,
LTYPEB = 268,
- LTYPEC = 269,
- LTYPED = 270,
- LTYPEE = 271,
- LTYPEG = 272,
- LTYPEH = 273,
- LTYPEI = 274,
- LTYPEJ = 275,
- LTYPEK = 276,
- LTYPEL = 277,
- LTYPEM = 278,
- LTYPEN = 279,
- LTYPEBX = 280,
- LTYPEPLD = 281,
- LCONST = 282,
- LSP = 283,
- LSB = 284,
- LFP = 285,
- LPC = 286,
- LTYPEX = 287,
- LTYPEPC = 288,
- LTYPEF = 289,
- LR = 290,
- LREG = 291,
- LF = 292,
- LFREG = 293,
- LC = 294,
- LCREG = 295,
- LPSR = 296,
- LFCR = 297,
- LCOND = 298,
- LS = 299,
- LAT = 300,
- LFCONST = 301,
- LSCONST = 302,
- LNAME = 303,
- LLAB = 304,
- LVAR = 305
+ LGLOBL = 269,
+ LTYPEC = 270,
+ LTYPED = 271,
+ LTYPEE = 272,
+ LTYPEG = 273,
+ LTYPEH = 274,
+ LTYPEI = 275,
+ LTYPEJ = 276,
+ LTYPEK = 277,
+ LTYPEL = 278,
+ LTYPEM = 279,
+ LTYPEN = 280,
+ LTYPEBX = 281,
+ LTYPEPLD = 282,
+ LCONST = 283,
+ LSP = 284,
+ LSB = 285,
+ LFP = 286,
+ LPC = 287,
+ LTYPEX = 288,
+ LTYPEPC = 289,
+ LTYPEF = 290,
+ LR = 291,
+ LREG = 292,
+ LF = 293,
+ LFREG = 294,
+ LC = 295,
+ LCREG = 296,
+ LPSR = 297,
+ LFCR = 298,
+ LCOND = 299,
+ LS = 300,
+ LAT = 301,
+ LFCONST = 302,
+ LSCONST = 303,
+ LNAME = 304,
+ LLAB = 305,
+ LVAR = 306
};
#endif
/* Tokens. */
#define LTYPE9 266
#define LTYPEA 267
#define LTYPEB 268
-#define LTYPEC 269
-#define LTYPED 270
-#define LTYPEE 271
-#define LTYPEG 272
-#define LTYPEH 273
-#define LTYPEI 274
-#define LTYPEJ 275
-#define LTYPEK 276
-#define LTYPEL 277
-#define LTYPEM 278
-#define LTYPEN 279
-#define LTYPEBX 280
-#define LTYPEPLD 281
-#define LCONST 282
-#define LSP 283
-#define LSB 284
-#define LFP 285
-#define LPC 286
-#define LTYPEX 287
-#define LTYPEPC 288
-#define LTYPEF 289
-#define LR 290
-#define LREG 291
-#define LF 292
-#define LFREG 293
-#define LC 294
-#define LCREG 295
-#define LPSR 296
-#define LFCR 297
-#define LCOND 298
-#define LS 299
-#define LAT 300
-#define LFCONST 301
-#define LSCONST 302
-#define LNAME 303
-#define LLAB 304
-#define LVAR 305
+#define LGLOBL 269
+#define LTYPEC 270
+#define LTYPED 271
+#define LTYPEE 272
+#define LTYPEG 273
+#define LTYPEH 274
+#define LTYPEI 275
+#define LTYPEJ 276
+#define LTYPEK 277
+#define LTYPEL 278
+#define LTYPEM 279
+#define LTYPEN 280
+#define LTYPEBX 281
+#define LTYPEPLD 282
+#define LCONST 283
+#define LSP 284
+#define LSB 285
+#define LFP 286
+#define LPC 287
+#define LTYPEX 288
+#define LTYPEPC 289
+#define LTYPEF 290
+#define LR 291
+#define LREG 292
+#define LF 293
+#define LFREG 294
+#define LC 295
+#define LCREG 296
+#define LPSR 297
+#define LFCR 298
+#define LCOND 299
+#define LS 300
+#define LAT 301
+#define LFCONST 302
+#define LSCONST 303
+#define LNAME 304
+#define LLAB 305
+#define LVAR 306
Addr addr;
}
/* Line 1529 of yacc.c. */
-#line 157 "y.tab.h"
+#line 159 "y.tab.h"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
regalloc(&n3, types[tptr], res);
p1 = gins(AMOVW, N, &n3);
datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from);
- p1->from.type = D_CONST;
+ p1->from.type = TYPE_ADDR;
} else
if(isslice(nl->type) || nl->type->etype == TSTRING) {
n1 = n3;
regalloc(&nend, types[TUINT32], N);
p = gins(AMOVW, &src, &nend);
- p->from.type = D_CONST;
+ p->from.type = TYPE_ADDR;
if(dir < 0)
p->from.offset = dir;
else
// move src and dest to the end of block if necessary
if(dir < 0) {
p = gins(AMOVW, &src, &src);
- p->from.type = D_CONST;
+ p->from.type = TYPE_ADDR;
p->from.offset = w + dir;
p = gins(AMOVW, &dst, &dst);
- p->from.type = D_CONST;
+ p->from.type = TYPE_ADDR;
p->from.offset = w + dir;
}
// move
if(c >= 4) {
p = gins(op, &src, &tmp);
- p->from.type = D_OREG;
+ p->from.type = TYPE_MEM;
p->from.offset = dir;
p->scond |= C_PBIT;
ploop = p;
p = gins(op, &tmp, &dst);
- p->to.type = D_OREG;
+ p->to.type = TYPE_MEM;
p->to.offset = dir;
p->scond |= C_PBIT;
} else {
while(c-- > 0) {
p = gins(op, &src, &tmp);
- p->from.type = D_OREG;
+ p->from.type = TYPE_MEM;
p->from.offset = dir;
p->scond |= C_PBIT;
p = gins(op, &tmp, &dst);
- p->to.type = D_OREG;
+ p->to.type = TYPE_MEM;
p->to.offset = dir;
p->scond |= C_PBIT;
}
// bl * cl -> ah al
p1 = gins(AMULLU, N, N);
- p1->from.type = D_REG;
+ p1->from.type = TYPE_REG;
p1->from.reg = bl.val.u.reg;
p1->reg = cl.val.u.reg;
- p1->to.type = D_REGREG;
+ p1->to.type = TYPE_REGREG;
p1->to.reg = ah.val.u.reg;
p1->to.offset = al.val.u.reg;
//print("%P\n", p1);
// bl * ch + ah -> ah
p1 = gins(AMULA, N, N);
- p1->from.type = D_REG;
+ p1->from.type = TYPE_REG;
p1->from.reg = bl.val.u.reg;
p1->reg = ch.val.u.reg;
- p1->to.type = D_REGREG2;
+ p1->to.type = TYPE_REGREG2;
p1->to.reg = ah.val.u.reg;
p1->to.offset = ah.val.u.reg;
//print("%P\n", p1);
// bh * cl + ah -> ah
p1 = gins(AMULA, N, N);
- p1->from.type = D_REG;
+ p1->from.type = TYPE_REG;
p1->from.reg = bh.val.u.reg;
p1->reg = cl.val.u.reg;
- p1->to.type = D_REGREG2;
+ p1->to.type = TYPE_REGREG2;
p1->to.reg = ah.val.u.reg;
p1->to.offset = ah.val.u.reg;
//print("%P\n", p1);
widthint = 4;
widthreg = 4;
- zprog.link = P;
- zprog.as = AGOK;
- zprog.scond = C_SCOND_NONE;
- zprog.reg = NREG;
- zprog.from.type = D_NONE;
- zprog.from.name = D_NONE;
- zprog.from.reg = NREG;
- zprog.to = zprog.from;
-
listinit5();
}
+
+void
+main(int argc, char **argv)
+{
+ arch.thechar = thechar;
+ arch.thestring = thestring;
+ arch.thelinkarch = thelinkarch;
+ arch.typedefs = typedefs;
+ arch.MAXWIDTH = MAXWIDTH;
+ arch.afunclit = afunclit;
+ arch.anyregalloc = anyregalloc;
+ arch.betypeinit = betypeinit;
+ arch.bgen = bgen;
+ arch.cgen = cgen;
+ arch.cgen_asop = cgen_asop;
+ arch.cgen_call = cgen_call;
+ arch.cgen_callinter = cgen_callinter;
+ arch.cgen_ret = cgen_ret;
+ arch.clearfat = clearfat;
+ arch.clearp = clearp;
+ arch.defframe = defframe;
+ arch.dgostringptr = dgostringptr;
+ arch.dgostrlitptr = dgostrlitptr;
+ arch.dsname = dsname;
+ arch.dsymptr = dsymptr;
+ arch.dumpdata = dumpdata;
+ arch.dumpit = dumpit;
+ arch.excise = excise;
+ arch.expandchecks = expandchecks;
+ arch.fixautoused = fixautoused;
+ arch.gclean = gclean;
+ arch.gdata = gdata;
+ arch.gdatacomplex = gdatacomplex;
+ arch.gdatastring = gdatastring;
+ arch.ggloblnod = ggloblnod;
+ arch.ggloblsym = ggloblsym;
+ arch.ginit = ginit;
+ arch.gins = gins;
+ arch.ginscall = ginscall;
+ arch.gjmp = gjmp;
+ arch.gtrack = gtrack;
+ arch.gused = gused;
+ arch.igen = igen;
+ arch.isfat = isfat;
+ arch.linkarchinit = linkarchinit;
+ arch.markautoused = markautoused;
+ arch.naddr = naddr;
+ arch.newplist = newplist;
+ arch.nodarg = nodarg;
+ arch.patch = patch;
+ arch.proginfo = proginfo;
+ arch.regalloc = regalloc;
+ arch.regfree = regfree;
+ arch.regopt = regopt;
+ arch.regtyp = regtyp;
+ arch.sameaddr = sameaddr;
+ arch.smallindir = smallindir;
+ arch.stackaddr = stackaddr;
+ arch.unpatch = unpatch;
+
+ gcmain(argc, argv);
+}
#include "../gc/go.h"
#include "../5l/5.out.h"
-#define TEXTFLAG reg
-
enum
{
- REGALLOC_R0 = 0,
+ REGALLOC_R0 = REG_R0,
REGALLOC_RMAX = REGEXT,
- REGALLOC_F0 = NREG,
- REGALLOC_FMAX = REGALLOC_F0 + FREGEXT,
+ REGALLOC_F0 = REG_F0,
+ REGALLOC_FMAX = FREGEXT,
};
EXTERN int32 dynloc;
EXTERN uchar reg[REGALLOC_FMAX+1];
EXTERN int32 pcloc; // instruction counter
EXTERN Strlit emptystring;
-EXTERN Prog zprog;
-EXTERN Node* newproc;
-EXTERN Node* deferproc;
-EXTERN Node* deferreturn;
-EXTERN Node* panicindex;
-EXTERN Node* panicslice;
-EXTERN Node* throwreturn;
extern long unmappedzero;
/*
void listinit(void);
void zaddr(Biobuf*, Addr*, int, int);
+
+void afunclit(Addr*, Node*);
+int anyregalloc(void);
+void betypeinit(void);
+void bgen(Node*, int, int, Prog*);
+void cgen(Node*, Node*);
+void cgen_asop(Node*);
+void cgen_call(Node*, int);
+void cgen_callinter(Node*, Node*, int);
+void cgen_ret(Node*);
+void clearfat(Node*);
+void clearp(Prog*);
+void defframe(Prog*);
+int dgostringptr(Sym*, int, char*);
+int dgostrlitptr(Sym*, int, Strlit*);
+int dsname(Sym*, int, char*, int);
+int dsymptr(Sym*, int, Sym*, int);
+void dumpdata(void);
+void dumpit(char*, Flow*, int);
+void excise(Flow*);
+void expandchecks(Prog*);
+void fixautoused(Prog*);
+void gclean(void);
+void gdata(Node*, Node*, int);
+void gdatacomplex(Node*, Mpcplx*);
+void gdatastring(Node*, Strlit*);
+void ggloblnod(Node *nam);
+void ggloblsym(Sym *s, int32 width, int8 flags);
+void ginit(void);
+Prog* gins(int, Node*, Node*);
+void ginscall(Node*, int);
+Prog* gjmp(Prog*);
+void gtrack(Sym*);
+void gused(Node*);
+void igen(Node*, Node*, Node*);
+int isfat(Type*);
+void linkarchinit(void);
+void markautoused(Prog*);
+void naddr(Node*, Addr*, int);
+Plist* newplist(void);
+Node* nodarg(Type*, int);
+void patch(Prog*, Prog*);
+void proginfo(ProgInfo*, Prog*);
+void regalloc(Node*, Type*, Node*);
+void regfree(Node*);
+void regopt(Prog*);
+int regtyp(Addr*);
+int sameaddr(Addr*, Addr*);
+int smallindir(Addr*, Addr*);
+int stackaddr(Addr*);
+Prog* unpatch(Prog*);
NodeList *l;
Node *n;
- // fill in argument size
- ptxt->to.type = D_CONST2;
- ptxt->to.offset2 = rnd(curfn->type->argwid, widthptr);
-
- // fill in final stack size
- frame = rnd(stksize+maxarg, widthptr);
+ // fill in argument size, stack size
+ ptxt->to.type = TYPE_TEXTSIZE;
+ ptxt->to.u.argsize = rnd(curfn->type->argwid, widthptr);
+ frame = rnd(stksize+maxarg, widthreg);
ptxt->to.offset = frame;
// insert code to contain ambiguously live variables
if(cnt == 0)
return p;
if(*r0 == 0) {
- p = appendpp(p, AMOVW, D_CONST, NREG, 0, D_REG, 0, 0);
+ p = appendpp(p, AMOVW, TYPE_CONST, 0, 0, TYPE_REG, REG_R0, 0);
*r0 = 1;
}
if(cnt < 4*widthptr) {
for(i = 0; i < cnt; i += widthptr)
- p = appendpp(p, AMOVW, D_REG, 0, 0, D_OREG, REGSP, 4+frame+lo+i);
+ p = appendpp(p, AMOVW, TYPE_REG, REG_R0, 0, TYPE_MEM, REGSP, 4+frame+lo+i);
} else if(!nacl && (cnt <= 128*widthptr)) {
- p = appendpp(p, AADD, D_CONST, NREG, 4+frame+lo, D_REG, 1, 0);
+ p = appendpp(p, AADD, TYPE_CONST, 0, 4+frame+lo, TYPE_REG, REG_R1, 0);
p->reg = REGSP;
- p = appendpp(p, ADUFFZERO, D_NONE, NREG, 0, D_OREG, NREG, 0);
+ p = appendpp(p, ADUFFZERO, TYPE_NONE, 0, 0, TYPE_MEM, 0, 0);
f = sysfunc("duffzero");
naddr(f, &p->to, 1);
afunclit(&p->to, f);
p->to.offset = 4*(128-cnt/widthptr);
} else {
- p = appendpp(p, AADD, D_CONST, NREG, 4+frame+lo, D_REG, 1, 0);
+ p = appendpp(p, AADD, TYPE_CONST, 0, 4+frame+lo, TYPE_REG, REG_R1, 0);
p->reg = REGSP;
- p = appendpp(p, AADD, D_CONST, NREG, cnt, D_REG, 2, 0);
- p->reg = 1;
- p1 = p = appendpp(p, AMOVW, D_REG, 0, 0, D_OREG, 1, 4);
+ p = appendpp(p, AADD, TYPE_CONST, 0, cnt, TYPE_REG, REG_R2, 0);
+ p->reg = REG_R1;
+ p1 = p = appendpp(p, AMOVW, TYPE_REG, REG_R0, 0, TYPE_MEM, REG_R1, 4);
p->scond |= C_PBIT;
- p = appendpp(p, ACMP, D_REG, 1, 0, D_NONE, 0, 0);
- p->reg = 2;
- p = appendpp(p, ABNE, D_NONE, NREG, 0, D_BRANCH, NREG, 0);
+ p = appendpp(p, ACMP, TYPE_REG, REG_R1, 0, TYPE_NONE, 0, 0);
+ p->reg = REG_R2;
+ p = appendpp(p, ABNE, TYPE_NONE, 0, 0, TYPE_BRANCH, 0, 0);
patch(p, p1);
}
return p;
continue;
if (p->from.node)
- p->from.node->used = 1;
+ ((Node*)(p->from.node))->used = 1;
if (p->to.node)
- p->to.node->used = 1;
+ ((Node*)(p->to.node))->used = 1;
}
}
Prog **lp;
for (lp=&p; (p=*lp) != P; ) {
- if (p->as == ATYPE && p->from.node && p->from.name == D_AUTO && !p->from.node->used) {
+ if (p->as == ATYPE && p->from.node && p->from.name == NAME_AUTO && !((Node*)(p->from.node))->used) {
*lp = p->link;
continue;
}
- if ((p->as == AVARDEF || p->as == AVARKILL) && p->to.node && !p->to.node->used) {
+ if ((p->as == AVARDEF || p->as == AVARKILL) && p->to.node && !((Node*)(p->to.node))->used) {
// Cannot remove VARDEF instruction, because - unlike TYPE handled above -
// VARDEFs are interspersed with other code, and a jump might be using the
// VARDEF as a target. Replace with a no-op instead. A later pass will remove
// the no-ops.
- p->to.type = D_NONE;
- p->to.node = N;
- p->as = ANOP;
+ nopout(p);
continue;
}
- if (p->from.name == D_AUTO && p->from.node)
- p->from.offset += p->from.node->stkdelta;
+ if (p->from.name == NAME_AUTO && p->from.node)
+ p->from.offset += ((Node*)(p->from.node))->stkdelta;
- if (p->to.name == D_AUTO && p->to.node)
- p->to.offset += p->to.node->stkdelta;
+ if (p->to.name == NAME_AUTO && p->to.node)
+ p->to.offset += ((Node*)(p->to.node))->stkdelta;
lp = &p->link;
}
// ARM NOP 0x00000000 is really AND.EQ R0, R0, R0.
// Use the latter form because the NOP pseudo-instruction
// would be removed by the linker.
- nodreg(&r, types[TINT], 0);
+ nodreg(&r, types[TINT], REG_R0);
p = gins(AAND, &r, &r);
p->scond = C_SCOND_EQ;
}
gins(AUNDEF, N, N);
break;
}
- nodreg(&r, types[tptr], 7);
- nodreg(&r1, types[tptr], 1);
+ nodreg(&r, types[tptr], REG_R7);
+ nodreg(&r1, types[tptr], REG_R1);
gmove(f, &r);
r.op = OINDREG;
gmove(&r, &r1);
nodconst(&con, types[TINT32], argsize(f->type));
gins(AMOVW, &con, &r);
p = gins(AMOVW, &r, N);
- p->to.type = D_OREG;
+ p->to.type = TYPE_MEM;
p->to.reg = REGSP;
p->to.offset = 4;
n1.left = f;
gins(AMOVW, &n1, &r);
p = gins(AMOVW, &r, N);
- p->to.type = D_OREG;
+ p->to.type = TYPE_MEM;
p->to.reg = REGSP;
p->to.offset = 8;
if(proc == 2) {
nodconst(&con, types[TINT32], 0);
p = gins(ACMP, &con, N);
- p->reg = 0;
+ p->reg = REG_R0;
p = gbranch(ABEQ, T, +1);
cgen_ret(N);
patch(p, pc);
} else {
// go/defer. generate go func value.
p = gins(AMOVW, &nodo, &nodr);
- p->from.type = D_CONST; // REG = &(20+offset(REG)) -- i.tab->fun[f]
+ p->from.type = TYPE_ADDR; // REG = &(20+offset(REG)) -- i.tab->fun[f]
}
nodr.type = n->left->type;
genlist(curfn->exit);
p = gins(ARET, N, N);
if(n != N && n->op == ORETJMP) {
- p->to.name = D_EXTERN;
- p->to.type = D_CONST;
+ p->to.name = NAME_EXTERN;
+ p->to.type = TYPE_ADDR;
p->to.sym = linksym(n->left->sym);
}
}
p = gins(AMULLU, &n2, N);
// n2 * n1 -> (n1 n2)
p->reg = n1.val.u.reg;
- p->to.type = D_REGREG;
+ p->to.type = TYPE_REGREG;
p->to.reg = n1.val.u.reg;
p->to.offset = n2.val.u.reg;
break;
if(q > 128) {
regalloc(&end, types[tptr], N);
p = gins(AMOVW, &dst, &end);
- p->from.type = D_CONST;
+ p->from.type = TYPE_ADDR;
p->from.offset = q*4;
p = gins(AMOVW, &nz, &dst);
- p->to.type = D_OREG;
+ p->to.type = TYPE_MEM;
p->to.offset = 4;
p->scond |= C_PBIT;
pl = p;
} else
while(q > 0) {
p = gins(AMOVW, &nz, &dst);
- p->to.type = D_OREG;
+ p->to.type = TYPE_MEM;
p->to.offset = 4;
p->scond |= C_PBIT;
//print("1. %P\n", p);
while(c > 0) {
p = gins(AMOVB, &nz, &dst);
- p->to.type = D_OREG;
+ p->to.type = TYPE_MEM;
p->to.offset = 1;
p->scond |= C_PBIT;
//print("2. %P\n", p);
continue;
if(debug_checknil && p->lineno > 1) // p->lineno==1 in generated wrappers
warnl(p->lineno, "generated nil check");
- if(p->from.type != D_REG)
+ if(p->from.type != TYPE_REG)
fatal("invalid nil check %P", p);
reg = p->from.reg;
// check is
p1->lineno = p->lineno;
p1->pc = 9999;
p1->as = AMOVW;
- p1->from.type = D_REG;
+ p1->from.type = TYPE_REG;
p1->from.reg = reg;
- p1->to.type = D_OREG;
+ p1->to.type = TYPE_MEM;
p1->to.reg = reg;
p1->to.offset = 0;
p1->scond = C_SCOND_EQ;
p->as = ACMP;
- p->from.type = D_CONST;
- p->from.reg = NREG;
+ p->from.type = TYPE_CONST;
+ p->from.reg = 0;
p->from.offset = 0;
p->reg = reg;
}
Prog *p;
p = gins(ADATA, N, N);
- p->from.type = D_OREG;
- p->from.name = D_EXTERN;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.etype = TINT32;
p->from.offset = off;
- p->from.reg = NREG;
+ p->from.reg = 0;
p->from.sym = linksym(sym);
- p->reg = n;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = n;
- p->to.type = D_SCONST;
- p->to.name = D_NONE;
- p->to.reg = NREG;
+ p->to.type = TYPE_SCONST;
+ p->to.name = NAME_NONE;
+ p->to.reg = 0;
p->to.offset = 0;
memmove(p->to.u.sval, t, n);
return off + n;
Sym *sym;
sym = stringsym(s, len);
- a->type = D_OREG;
- a->name = D_EXTERN;
+ a->type = TYPE_MEM;
+ a->name = NAME_EXTERN;
a->etype = TINT32;
a->offset = widthptr+4; // skip header
- a->reg = NREG;
+ a->reg = 0;
a->sym = linksym(sym);
a->node = sym->def;
}
Sym *sym;
sym = stringsym(sval->s, sval->len);
- a->type = D_OREG;
- a->name = D_EXTERN;
+ a->type = TYPE_MEM;
+ a->name = NAME_EXTERN;
a->etype = TSTRING;
a->offset = 0; // header
- a->reg = NREG;
+ a->reg = 0;
a->sym = linksym(sym);
a->node = sym->def;
}
if(wid == 8 && is64(nr->type)) {
v = mpgetfix(nr->val.u.xval);
p = gins(ADATA, nam, nodintconst(v));
- p->reg = 4;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = 4;
p = gins(ADATA, nam, nodintconst(v>>32));
- p->reg = 4;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = 4;
p->from.offset += 4;
return;
}
p = gins(ADATA, nam, nr);
- p->reg = wid;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = wid;
}
void
w = types[w]->width;
p = gins(ADATA, nam, N);
- p->reg = w;
- p->to.type = D_FCONST;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = w;
+ p->to.type = TYPE_FCONST;
p->to.u.dval = mpgetflt(&cval->real);
p = gins(ADATA, nam, N);
- p->reg = w;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = w;
p->from.offset += w;
- p->to.type = D_FCONST;
+ p->to.type = TYPE_FCONST;
p->to.u.dval = mpgetflt(&cval->imag);
}
p = gins(ADATA, nam, N);
datastring(sval->s, sval->len, &p->to);
- p->reg = types[tptr]->width;
- p->to.type = D_CONST;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = types[tptr]->width;
+ p->to.type = TYPE_CONST;
p->to.etype = TINT32;
//print("%P\n", p);
nodconst(&nod1, types[TINT32], sval->len);
p = gins(ADATA, nam, &nod1);
- p->reg = types[TINT32]->width;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = types[TINT32]->width;
p->from.offset += types[tptr]->width;
}
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
- p->from.type = D_OREG;
- p->from.name = D_EXTERN;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
- p->reg = widthptr;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = widthptr;
datastring(str, strlen(str)+1, &p->to);
- p->to.type = D_CONST;
+ p->to.type = TYPE_CONST;
p->to.etype = TINT32;
off += widthptr;
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
- p->from.type = D_OREG;
- p->from.name = D_EXTERN;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
- p->reg = widthptr;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = widthptr;
datagostring(lit, &p->to);
- p->to.type = D_CONST;
+ p->to.type = TYPE_CONST;
p->to.etype = TINT32;
off += widthptr;
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
- p->from.type = D_OREG;
- p->from.name = D_EXTERN;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
- p->reg = widthptr;
- p->to.type = D_CONST;
- p->to.name = D_EXTERN;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = widthptr;
+ p->to.type = TYPE_ADDR;
+ p->to.name = NAME_EXTERN;
p->to.sym = linksym(x);
p->to.offset = xoff;
off += widthptr;
nopout(Prog *p)
{
p->as = ANOP;
+ p->scond = zprog.scond;
+ p->from = zprog.from;
+ p->to = zprog.to;
+ p->reg = zprog.reg;
}
clearp(Prog *p)
{
p->as = AEND;
- p->reg = NREG;
+ p->reg = 0;
p->scond = C_SCOND_NONE;
- p->from.type = D_NONE;
- p->from.name = D_NONE;
- p->from.reg = NREG;
- p->to.type = D_NONE;
- p->to.name = D_NONE;
- p->to.reg = NREG;
+ p->from.type = TYPE_NONE;
+ p->from.name = NAME_NONE;
+ p->from.reg = 0;
+ p->to.type = TYPE_NONE;
+ p->to.name = NAME_NONE;
+ p->to.reg = 0;
p->pc = pcloc;
pcloc++;
}
USED(likely); // TODO: record this for linker
p = prog(as);
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
p->to.u.branch = P;
return p;
}
void
patch(Prog *p, Prog *to)
{
- if(p->to.type != D_BRANCH)
+ if(p->to.type != TYPE_BRANCH)
fatal("patch: not a branch");
p->to.u.branch = to;
p->to.offset = to->pc;
{
Prog *q;
- if(p->to.type != D_BRANCH)
+ if(p->to.type != TYPE_BRANCH)
fatal("unpatch: not a branch");
q = p->to.u.branch;
p->to.u.branch = P;
p->lineno = nam->lineno;
p->from.sym->gotype = linksym(ngotype(nam));
p->to.sym = nil;
- p->to.type = D_CONST;
+ p->to.type = TYPE_CONST;
p->to.offset = nam->type->width;
if(nam->readonly)
- p->reg = RODATA;
+ p->from3.offset = RODATA;
if(nam->type != T && !haspointers(nam->type))
- p->reg |= NOPTR;
+ p->from3.offset |= NOPTR;
}
void
Prog *p;
p = gins(AGLOBL, N, N);
- p->from.type = D_OREG;
- p->from.name = D_EXTERN;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
- p->to.type = D_CONST;
- p->to.name = D_NONE;
+ p->to.type = TYPE_CONST;
+ p->to.name = NAME_NONE;
p->to.offset = width;
- p->reg = flags;
+ p->from3.offset = flags;
}
void
Prog *p;
p = gins(AUSEFIELD, N, N);
- p->from.type = D_OREG;
- p->from.name = D_EXTERN;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
}
* naddr of func generates code for address of func.
* if using opcode that can take address implicitly,
* call afunclit to fix up the argument.
- * also fix up direct register references to be D_OREG.
+ * also fix up direct register references to be TYPE_MEM.
*/
void
afunclit(Addr *a, Node *n)
{
- if(a->type == D_CONST && a->name == D_EXTERN || a->type == D_REG) {
- a->type = D_OREG;
+ if(a->type == TYPE_ADDR && a->name == NAME_EXTERN || a->type == TYPE_REG) {
+ a->type = TYPE_MEM;
if(n->op == ONAME)
a->sym = linksym(n->sym);
}
yyerror("regalloc: unknown type %T", t);
err:
- nodreg(n, t, 0);
+ nodreg(n, t, REG_R0);
return;
out:
regalloc(&r2, thi.type, N);
gmove(f, &r1);
p1 = gins(AMOVW, &r1, &r2);
- p1->from.type = D_SHIFT;
- p1->from.offset = 2 << 5 | 31 << 7 | r1.val.u.reg; // r1->31
- p1->from.reg = NREG;
+ p1->from.type = TYPE_SHIFT;
+ p1->from.offset = 2 << 5 | 31 << 7 | (r1.val.u.reg&15); // r1->31
+ p1->from.reg = 0;
//print("gmove: %P\n", p1);
gins(AMOVW, &r1, &tlo);
gins(AMOVW, &r2, &thi);
Addr a;
naddr(n, &a, 1);
- if(a.type != D_REG && a.type != D_FREG) {
+ if(a.type != TYPE_REG) {
if(n)
fatal("bad in raddr: %O", n->op);
else
fatal("bad in raddr: <null>");
- p->reg = NREG;
+ p->reg = 0;
} else
p->reg = a.reg;
}
sval = sval&0x1f;
p = gins(as, N, rhs);
- p->from.type = D_SHIFT;
- p->from.offset = stype | sval<<7 | lhs->val.u.reg;
+ p->from.type = TYPE_SHIFT;
+ p->from.offset = stype | sval<<7 | (lhs->val.u.reg&15);
return p;
}
{
Prog *p;
p = gins(as, N, rhs);
- p->from.type = D_SHIFT;
- p->from.offset = stype | reg->val.u.reg << 8 | 1<<4 | lhs->val.u.reg;
+ p->from.type = TYPE_SHIFT;
+ p->from.offset = stype | (reg->val.u.reg&15) << 8 | 1<<4 | (lhs->val.u.reg&15);
return p;
}
{
Sym *s;
- a->type = D_NONE;
- a->name = D_NONE;
- a->reg = NREG;
+ a->type = TYPE_NONE;
+ a->name = NAME_NONE;
+ a->reg = 0;
a->gotype = nil;
a->node = N;
a->etype = 0;
break;
case OREGISTER:
- if(n->val.u.reg <= REGALLOC_RMAX) {
- a->type = D_REG;
- a->reg = n->val.u.reg;
- } else {
- a->type = D_FREG;
- a->reg = n->val.u.reg - REGALLOC_F0;
- }
+ a->type = TYPE_REG;
+ a->reg = n->val.u.reg;
a->sym = nil;
break;
// if(a->type >= D_AX && a->type <= D_DI)
// a->type += D_INDIR;
// else
-// if(a->type == D_CONST)
-// a->type = D_NONE+D_INDIR;
+// if(a->type == TYPE_ADDR)
+// a->type = TYPE_NONE+D_INDIR;
// else
-// if(a->type == D_ADDR) {
+// if(a->type == TYPE_ADDR) {
// a->type = a->index;
-// a->index = D_NONE;
+// a->index = TYPE_NONE;
// } else
// goto bad;
// if(n->op == OINDEX) {
// break;
case OINDREG:
- a->type = D_OREG;
+ a->type = TYPE_MEM;
a->reg = n->val.u.reg;
a->sym = linksym(n->sym);
a->offset = n->xoffset;
a->width = n->left->type->width;
a->offset = n->xoffset;
a->sym = linksym(n->left->sym);
- a->type = D_OREG;
- a->name = D_PARAM;
+ a->type = TYPE_MEM;
+ a->name = NAME_PARAM;
a->node = n->left->orig;
break;
case OCLOSUREVAR:
if(!curfn->needctxt)
fatal("closurevar without needctxt");
- a->type = D_OREG;
- a->reg = 7;
+ a->type = TYPE_MEM;
+ a->reg = REG_R7;
a->offset = n->xoffset;
a->sym = nil;
break;
case ONAME:
a->etype = 0;
a->width = 0;
- a->reg = NREG;
+ a->reg = 0;
if(n->type != T) {
a->etype = simtype[n->type->etype];
a->width = n->type->width;
s = pkglookup(s->name, n->type->sym->pkg);
}
- a->type = D_OREG;
+ a->type = TYPE_MEM;
switch(n->class) {
default:
fatal("naddr: ONAME class %S %d\n", n->sym, n->class);
case PEXTERN:
- a->name = D_EXTERN;
+ a->name = NAME_EXTERN;
break;
case PAUTO:
- a->name = D_AUTO;
+ a->name = NAME_AUTO;
break;
case PPARAM:
case PPARAMOUT:
- a->name = D_PARAM;
+ a->name = NAME_PARAM;
break;
case PFUNC:
- a->name = D_EXTERN;
- a->type = D_CONST;
+ a->name = NAME_EXTERN;
+ a->type = TYPE_ADDR;
s = funcsym(s);
break;
}
fatal("naddr: const %lT", n->type);
break;
case CTFLT:
- a->type = D_FCONST;
+ a->type = TYPE_FCONST;
a->u.dval = mpgetflt(n->val.u.fval);
break;
case CTINT:
case CTRUNE:
a->sym = nil;
- a->type = D_CONST;
+ a->type = TYPE_CONST;
a->offset = mpgetfix(n->val.u.xval);
break;
case CTSTR:
break;
case CTBOOL:
a->sym = nil;
- a->type = D_CONST;
+ a->type = TYPE_CONST;
a->offset = n->val.u.bval;
break;
case CTNIL:
a->sym = nil;
- a->type = D_CONST;
+ a->type = TYPE_CONST;
a->offset = 0;
break;
}
// itable of interface value
naddr(n->left, a, canemitcode);
a->etype = simtype[tptr];
- if(a->type == D_CONST && a->offset == 0)
+ if(a->type == TYPE_CONST && a->offset == 0)
break; // len(nil)
a->width = widthptr;
break;
case OSPTR:
// pointer in a string or slice
naddr(n->left, a, canemitcode);
- if(a->type == D_CONST && a->offset == 0)
+ if(a->type == TYPE_CONST && a->offset == 0)
break; // ptr(nil)
a->etype = simtype[tptr];
a->offset += Array_array;
// len of string or slice
naddr(n->left, a, canemitcode);
a->etype = TINT32;
- if(a->type == D_CONST && a->offset == 0)
+ if(a->type == TYPE_CONST && a->offset == 0)
break; // len(nil)
a->offset += Array_nel;
break;
// cap of string or slice
naddr(n->left, a, canemitcode);
a->etype = TINT32;
- if(a->type == D_CONST && a->offset == 0)
+ if(a->type == TYPE_CONST && a->offset == 0)
break; // cap(nil)
a->offset += Array_cap;
break;
naddr(n->left, a, canemitcode);
a->etype = tptr;
switch(a->type) {
- case D_OREG:
- a->type = D_CONST;
+ case TYPE_MEM:
+ a->type = TYPE_ADDR;
break;
- case D_REG:
- case D_CONST:
+ case TYPE_REG:
+ case TYPE_ADDR:
break;
default:
if(t == T)
fatal("optoas: t is nil");
- a = AGOK;
+ a = AXXX;
switch(CASE(op, simtype[t->etype])) {
default:
fatal("optoas: no entry %O-%T etype %T simtype %T", op, t, types[t->etype], types[simtype[t->etype]]);
n1.xoffset = -(oary[i]+1);
}
- a->type = D_NONE;
- a->name = D_NONE;
+ a->type = TYPE_NONE;
+ a->name = NAME_NONE;
n1.type = n->type;
naddr(&n1, a, 1);
goto yes;
}
naddr(reg1, a, 1);
- a->type = D_OREG;
+ a->type = TYPE_MEM;
a->reg = reg->val.u.reg;
a->offset = 0;
goto yes;
n2 = *reg;
n2.op = OINDREG;
n2.xoffset = v * (*w);
- a->type = D_NONE;
- a->name = D_NONE;
+ a->type = TYPE_NONE;
+ a->name = NAME_NONE;
naddr(&n2, a, 1);
goto yes;
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include "../gc/popt.h"
#define Z N
#define Adr Addr
-#define D_HI D_NONE
-#define D_LO D_NONE
+#define D_HI TYPE_NONE
+#define D_LO TYPE_NONE
#define BLOAD(r) band(bnot(r->refbehind), r->refahead)
#define BSTORE(r) band(bnot(r->calbehind), r->calahead)
extern Node *Z;
enum
{
- D_HI = D_NONE,
- D_LO = D_NONE,
+ D_HI = TYPE_NONE,
+ D_LO = TYPE_NONE,
CLOAD = 5,
CREF = 5,
CINF = 1000,
short regno;
};
-EXTERN int32 exregoffset; // not set
-EXTERN int32 exfregoffset; // not set
EXTERN Reg zreg;
EXTERN Reg* freer;
EXTERN Reg** rpo2r;
EXTERN int nregion;
EXTERN int nvar;
EXTERN int32 regbits;
-EXTERN int32 exregbits;
EXTERN Bits externs;
EXTERN Bits params;
EXTERN Bits consts;
/*
* prog.c
*/
-typedef struct ProgInfo ProgInfo;
-struct ProgInfo
-{
- uint32 flags; // the bits below
-};
-
-enum
-{
- // Pseudo-op, like TEXT, GLOBL, TYPE, PCDATA, FUNCDATA.
- Pseudo = 1<<1,
-
- // There's nothing to say about the instruction,
- // but it's still okay to see.
- OK = 1<<2,
-
- // Size of right-side write, or right-side read if no write.
- SizeB = 1<<3,
- SizeW = 1<<4,
- SizeL = 1<<5,
- SizeQ = 1<<6,
- SizeF = 1<<7, // float aka float32
- SizeD = 1<<8, // double aka float64
-
- // Left side (Prog.from): address taken, read, write.
- LeftAddr = 1<<9,
- LeftRead = 1<<10,
- LeftWrite = 1<<11,
-
- // Register in middle (Prog.reg); only ever read.
- RegRead = 1<<12,
- CanRegRead = 1<<13,
-
- // Right side (Prog.to): address taken, read, write.
- RightAddr = 1<<14,
- RightRead = 1<<15,
- RightWrite = 1<<16,
-
- // Instruction kinds
- Move = 1<<17, // straight move
- Conv = 1<<18, // size conversion
- Cjmp = 1<<19, // conditional jump
- Break = 1<<20, // breaks control flow (no fallthrough)
- Call = 1<<21, // function call
- Jump = 1<<22, // jump
- Skip = 1<<23, // data instruction
-};
-
void proginfo(ProgInfo*, Prog*);
-
-// To allow use of AJMP and ACALL in ../gc/popt.c.
-enum
-{
- AJMP = AB,
- ACALL = ABL,
-};
static Flow* findpre(Flow *r, Adr *v);
static int copyau1(Prog *p, Adr *v);
static int isdconst(Addr *a);
+static int isfloatreg(Addr*);
static uint32 gactive;
void constprop(Adr *c1, Adr *v1, Flow *r);
void predicate(Graph*);
+
void
peep(Prog *firstp)
{
case ASRL:
case ASRA:
/*
- * elide shift into D_SHIFT operand of subsequent instruction
+ * elide shift into TYPE_SHIFT operand of subsequent instruction
*/
// if(shiftprop(r)) {
// excise(r);
case AMOVF:
case AMOVD:
if(regtyp(&p->from))
- if(p->from.type == p->to.type)
+ if(p->from.type == p->to.type && isfloatreg(&p->from) == isfloatreg(&p->to))
if(p->scond == C_SCOND_NONE) {
if(copyprop(g, r)) {
excise(r);
case AMOVHU:
case AMOVBS:
case AMOVBU:
- if(p->from.type == D_REG) {
+ if(p->from.type == TYPE_REG) {
if(shortprop(r))
t++;
}
break;
#ifdef NOTDEF
+XXX
if(p->scond == C_SCOND_NONE)
if(regtyp(&p->to))
if(isdconst(&p->from)) {
*/
if(isdconst(&p->from) && p->from.offset == -1) {
p->as = AMVN;
- p->from.type = D_REG;
- if(p->reg != NREG)
+ p->from.type = TYPE_REG;
+ if(p->reg != 0)
p->from.reg = p->reg;
else
p->from.reg = p->to.reg;
- p->reg = NREG;
+ p->reg = 0;
}
break;
}
case AMOVB:
case AMOVBS:
case AMOVBU:
- if(p->from.type == D_OREG && p->from.offset == 0)
+ if(p->from.type == TYPE_MEM && p->from.offset == 0)
xtramodes(g, r, &p->from);
else
- if(p->to.type == D_OREG && p->to.offset == 0)
+ if(p->to.type == TYPE_MEM && p->to.offset == 0)
xtramodes(g, r, &p->to);
else
continue;
// if(r1 == nil)
// continue;
// p1 = r1->prog;
-// if(p1->to.type != D_REG)
+// if(p1->to.type != TYPE_REG)
// continue;
// if(p1->to.reg != p->reg)
-// if(!(p1->as == AMOVW && p1->from.type == D_REG && p1->from.reg == p->reg))
+// if(!(p1->as == AMOVW && p1->from.type == TYPE_REG && p1->from.reg == p->reg))
// continue;
//
// switch(p1->as) {
// default:
// continue;
// case AMOVW:
-// if(p1->from.type != D_REG)
+// if(p1->from.type != TYPE_REG)
// continue;
// case AAND:
// case AEOR:
int
regtyp(Adr *a)
{
-
- if(a->type == D_REG)
- return 1;
- if(a->type == D_FREG)
- return 1;
- return 0;
+ return a->type == TYPE_REG && (REG_R0 <= a->reg && a->reg <= REG_R15 || REG_F0 <= a->reg && a->reg <= REG_F15);
}
/*
if(info.flags & Call)
return 0;
- if((info.flags & CanRegRead) && p->to.type == D_REG) {
+ if((info.flags & CanRegRead) && p->to.type == TYPE_REG) {
info.flags |= RegRead;
info.flags &= ~(CanRegRead | RightRead);
p->reg = p->to.reg;
Adr a;
p = r->prog;
- if(p->to.type != D_REG)
+ if(p->to.type != TYPE_REG)
FAIL("BOTCH: result not reg");
n = p->to.reg;
a = zprog.from;
- if(p->reg != NREG && p->reg != p->to.reg) {
- a.type = D_REG;
+ if(p->reg != 0 && p->reg != p->to.reg) {
+ a.type = TYPE_REG;
a.reg = p->reg;
}
if(debug['P'])
print("\n%P", p1);
switch(copyu(p1, &p->to, nil)) {
case 0: /* not used or set */
- if((p->from.type == D_REG && copyu(p1, &p->from, nil) > 1) ||
- (a.type == D_REG && copyu(p1, &a, nil) > 1))
+ if((p->from.type == TYPE_REG && copyu(p1, &p->from, nil) > 1) ||
+ (a.type == TYPE_REG && copyu(p1, &a, nil) > 1))
FAIL("args modified");
continue;
case 3: /* set, not used */
case ASBC:
case ARSB:
case ARSC:
- if(p1->reg == n || (p1->reg == NREG && p1->to.type == D_REG && p1->to.reg == n)) {
- if(p1->from.type != D_REG)
+ if(p1->reg == n || (p1->reg == 0 && p1->to.type == TYPE_REG && p1->to.reg == n)) {
+ if(p1->from.type != TYPE_REG)
FAIL("can't swap");
p1->reg = p1->from.reg;
p1->from.reg = n;
case ACMN:
if(p1->reg == n)
FAIL("can't swap");
- if(p1->reg == NREG && p1->to.reg == n)
+ if(p1->reg == 0 && p1->to.reg == n)
FAIL("shift result used twice");
// case AMVN:
- if(p1->from.type == D_SHIFT)
+ if(p1->from.type == TYPE_SHIFT)
FAIL("shift result used in shift");
- if(p1->from.type != D_REG || p1->from.reg != n)
+ if(p1->from.type != TYPE_REG || p1->from.reg != n)
FAIL("BOTCH: where is it used?");
break;
}
}
/* make the substitution */
- p2->from.type = D_SHIFT;
- p2->from.reg = NREG;
+ p2->from.reg = 0;
o = p->reg;
- if(o == NREG)
+ if(o == 0)
o = p->to.reg;
+ o &= 15;
switch(p->from.type){
- case D_CONST:
+ case TYPE_CONST:
o |= (p->from.offset&0x1f)<<7;
break;
- case D_REG:
- o |= (1<<4) | (p->from.reg<<8);
+ case TYPE_REG:
+ o |= (1<<4) | ((p->from.reg&15)<<8);
break;
}
switch(p->as){
o |= 2<<5;
break;
}
+ p2->from = zprog.from;
+ p2->from.type = TYPE_SHIFT;
p2->from.offset = o;
if(debug['P'])
print("\t=>%P\tSUCCEED\n", p2);
if(r == r2)
return 1;
n = 0;
- if(p->reg != NREG && p->reg != p->to.reg) {
- a[n].type = D_REG;
+ if(p->reg != 0 && p->reg != p->to.reg) {
+ a[n].type = TYPE_REG;
a[n++].reg = p->reg;
}
switch(p->from.type) {
- case D_SHIFT:
- a[n].type = D_REG;
- a[n++].reg = p->from.offset&0xf;
- case D_REG:
- a[n].type = D_REG;
+ case TYPE_SHIFT:
+ a[n].type = TYPE_REG;
+ a[n++].reg = REG_R0 + (p->from.offset&0xf);
+ case TYPE_REG:
+ a[n].type = TYPE_REG;
a[n++].reg = p->from.reg;
}
if(n == 0)
p = r->prog;
v = *a;
- v.type = D_REG;
+ v.type = TYPE_REG;
r1 = findpre(r, &v);
if(r1 != nil) {
p1 = r1->prog;
- if(p1->to.type == D_REG && p1->to.reg == v.reg)
+ if(p1->to.type == TYPE_REG && p1->to.reg == v.reg)
switch(p1->as) {
case AADD:
if(p1->scond & C_SBIT)
// avoid altering ADD.S/ADC sequences.
break;
- if(p1->from.type == D_REG ||
- (p1->from.type == D_SHIFT && (p1->from.offset&(1<<4)) == 0 &&
+ if(p1->from.type == TYPE_REG ||
+ (p1->from.type == TYPE_SHIFT && (p1->from.offset&(1<<4)) == 0 &&
((p->as != AMOVB && p->as != AMOVBS) || (a == &p->from && (p1->from.offset&~0xf) == 0))) ||
- (p1->from.type == D_CONST &&
+ ((p1->from.type == TYPE_ADDR || p1->from.type == TYPE_CONST) &&
p1->from.offset > -4096 && p1->from.offset < 4096))
if(nochange(uniqs(r1), r, p1)) {
if(a != &p->from || v.reg != p->to.reg)
if (finduse(g, r->s1, &v)) {
- if(p1->reg == NREG || p1->reg == v.reg)
+ if(p1->reg == 0 || p1->reg == v.reg)
/* pre-indexing */
p->scond |= C_WBIT;
else return 0;
}
switch (p1->from.type) {
- case D_REG:
+ case TYPE_REG:
/* register offset */
if(nacl)
return 0;
- a->type = D_SHIFT;
- a->offset = p1->from.reg;
+ *a = zprog.from;
+ a->type = TYPE_SHIFT;
+ a->offset = p1->from.reg&15;
break;
- case D_SHIFT:
+ case TYPE_SHIFT:
/* scaled register offset */
if(nacl)
return 0;
- a->type = D_SHIFT;
- case D_CONST:
+ *a = zprog.from;
+ a->type = TYPE_SHIFT;
+ case TYPE_CONST:
+ case TYPE_ADDR:
/* immediate offset */
a->offset = p1->from.offset;
break;
}
- if(p1->reg != NREG)
+ if(p1->reg != 0)
a->reg = p1->reg;
excise(r1);
return 1;
}
break;
case AMOVW:
- if(p1->from.type == D_REG)
+ if(p1->from.type == TYPE_REG)
if((r2 = findinc(r1, r, &p1->from)) != nil) {
for(r3=uniqs(r2); r3->prog->as==ANOP; r3=uniqs(r3))
;
return 2;
case AMOVM:
- if(v->type != D_REG)
+ if(v->type != TYPE_REG)
return 0;
- if(p->from.type == D_CONST) { /* read reglist, read/rar */
+ if(p->from.type == TYPE_CONST) { /* read reglist, read/rar */
if(s != nil) {
if(p->from.offset&(1<<v->reg))
return 1;
case AMOVFD:
case AMOVDF:
if(p->scond&(C_WBIT|C_PBIT))
- if(v->type == D_REG) {
- if(p->from.type == D_OREG || p->from.type == D_SHIFT) {
+ if(v->type == TYPE_REG) {
+ if(p->from.type == TYPE_MEM || p->from.type == TYPE_SHIFT) {
if(p->from.reg == v->reg)
return 2;
} else {
if(copyas(&p->to, v)) {
if(p->scond != C_SCOND_NONE)
return 2;
- if(p->reg == NREG)
+ if(p->reg == 0)
p->reg = p->to.reg;
if(copyau(&p->from, v))
return 4;
return 3;
case ABL: /* funny */
- if(v->type == D_REG) {
- if(v->reg <= REGEXT && v->reg > exregoffset)
+ if(v->type == TYPE_REG) {
+ // TODO(rsc): REG_R0 and REG_F0 used to be
+ // (when register numbers started at 0) exregoffset and exfregoffset,
+ // which are unset entirely.
+ // It's strange that this handles R0 and F0 differently from the other
+ // registers. Possible failure to optimize?
+ if(REG_R0 < v->reg && v->reg <= REGEXT)
return 2;
if(v->reg == REGARG)
return 2;
- }
- if(v->type == D_FREG)
- if(v->reg <= FREGEXT && v->reg > exfregoffset)
+ if(REG_F0 < v->reg && v->reg <= FREGEXT)
return 2;
- if(p->from.type == D_REG && v->type == D_REG && p->from.reg == v->reg)
+ }
+ if(p->from.type == TYPE_REG && v->type == TYPE_REG && p->from.reg == v->reg)
return 2;
if(s != nil) {
case ADUFFZERO:
// R0 is zero, used by DUFFZERO, cannot be substituted.
// R1 is ptr to memory, used and set, cannot be substituted.
- if(v->type == D_REG) {
+ if(v->type == TYPE_REG) {
if(v->reg == REGALLOC_R0)
return 1;
if(v->reg == REGALLOC_R0+1)
case ADUFFCOPY:
// R0 is scratch, set by DUFFCOPY, cannot be substituted.
// R1, R2 areptr to src, dst, used and set, cannot be substituted.
- if(v->type == D_REG) {
+ if(v->type == TYPE_REG) {
if(v->reg == REGALLOC_R0)
return 3;
if(v->reg == REGALLOC_R0+1 || v->reg == REGALLOC_R0+2)
return 0;
case ATEXT: /* funny */
- if(v->type == D_REG)
+ if(v->type == TYPE_REG)
if(v->reg == REGARG)
return 3;
return 0;
if(a->reg == v->reg)
return 1;
} else
- if(v->type == D_CONST) { /* for constprop */
+ if(v->type == TYPE_CONST) { /* for constprop */
if(a->type == v->type)
if(a->name == v->name)
if(a->sym == v->sym)
return 0;
if(regtyp(v) && a->reg == v->reg)
return 1;
- if(v->type == D_AUTO || v->type == D_PARAM) {
- if(v->offset == a->offset)
- return 1;
- }
+ // TODO(rsc): Change v->type to v->name and enable.
+ //if(v->type == NAME_AUTO || v->type == NAME_PARAM) {
+ // if(v->offset == a->offset)
+ // return 1;
+ //}
return 0;
}
if(copyas(a, v))
return 1;
- if(v->type == D_REG) {
- if(a->type == D_CONST && a->reg != NREG) {
+ if(v->type == TYPE_REG) {
+ if(a->type == TYPE_ADDR && a->reg != 0) {
if(a->reg == v->reg)
return 1;
} else
- if(a->type == D_OREG) {
+ if(a->type == TYPE_MEM) {
if(a->reg == v->reg)
return 1;
} else
- if(a->type == D_REGREG || a->type == D_REGREG2) {
+ if(a->type == TYPE_REGREG || a->type == TYPE_REGREG2) {
if(a->reg == v->reg)
return 1;
if(a->offset == v->reg)
return 1;
} else
- if(a->type == D_SHIFT) {
- if((a->offset&0xf) == v->reg)
+ if(a->type == TYPE_SHIFT) {
+ if((a->offset&0xf) == v->reg - REG_R0)
return 1;
- if((a->offset&(1<<4)) && (a->offset>>8) == v->reg)
+ if((a->offset&(1<<4)) && ((a->offset>>8)&0xf) == v->reg - REG_R0)
return 1;
}
}
return 0;
}
-static int
-a2type(Prog *p)
-{
- if(p->reg == NREG)
- return D_NONE;
-
- switch(p->as) {
- default:
- fatal("a2type: unhandled %P", p);
-
- case AAND:
- case AEOR:
- case ASUB:
- case ARSB:
- case AADD:
- case AADC:
- case ASBC:
- case ARSC:
- case ATST:
- case ATEQ:
- case ACMP:
- case ACMN:
- case AORR:
- case ABIC:
- case AMVN:
- case ASRL:
- case ASRA:
- case ASLL:
- case AMULU:
- case ADIVU:
- case AMUL:
- case ADIV:
- case AMOD:
- case AMODU:
- case AMULA:
- case AMULL:
- case AMULAL:
- case AMULLU:
- case AMULALU:
- case AMULWT:
- case AMULWB:
- case AMULAWT:
- case AMULAWB:
- return D_REG;
-
- case ACMPF:
- case ACMPD:
- case AADDF:
- case AADDD:
- case ASUBF:
- case ASUBD:
- case AMULF:
- case AMULD:
- case ADIVF:
- case ADIVD:
- case ASQRTF:
- case ASQRTD:
- case AABSF:
- case AABSD:
- return D_FREG;
- }
-}
-
/*
* compare v to the center
* register in p (p->reg)
static int
copyau1(Prog *p, Adr *v)
{
- if(v->type == D_REG && v->reg == NREG)
+ if(v->type == TYPE_REG && v->reg == 0)
return 0;
- return p->reg == v->reg && a2type(p) == v->type;
+ return p->reg == v->reg;
}
/*
if(f)
if(copyau(a, v)) {
- if(a->type == D_SHIFT) {
- if((a->offset&0xf) == v->reg)
- a->offset = (a->offset&~0xf)|s->reg;
- if((a->offset&(1<<4)) && (a->offset>>8) == v->reg)
- a->offset = (a->offset&~(0xf<<8))|(s->reg<<8);
+ if(a->type == TYPE_SHIFT) {
+ if((a->offset&0xf) == v->reg - REG_R0)
+ a->offset = (a->offset&~0xf)|(s->reg&0xf);
+ if((a->offset&(1<<4)) && ((a->offset>>8)&0xf) == v->reg - REG_R0)
+ a->offset = (a->offset&~(0xf<<8))|((s->reg&0xf)<<8);
} else
- if(a->type == D_REGREG || a->type == D_REGREG2) {
+ if(a->type == TYPE_REGREG || a->type == TYPE_REGREG2) {
if(a->offset == v->reg)
a->offset = s->reg;
if(a->reg == v->reg)
case AXXX:
case ADATA:
case AGLOBL:
- case AGOK:
- case AHISTORY:
- case ANAME:
- case ASIGNAME:
case ATEXT:
case AWORD:
case ABCASE:
static int
isdconst(Addr *a)
{
- if(a->type == D_CONST && a->reg == NREG)
- return 1;
- return 0;
+ return a->type == TYPE_CONST;
+}
+
+static int
+isfloatreg(Addr *a)
+{
+ return REG_F0 <= a->reg && a->reg <= REG_F15;
}
int
int
smallindir(Addr *a, Addr *reg)
{
- return reg->type == D_REG && a->type == D_OREG &&
+ return reg->type == TYPE_REG && a->type == TYPE_MEM &&
a->reg == reg->reg &&
0 <= a->offset && a->offset < 4096;
}
if(info->flags == 0)
fatal("unknown instruction %P", p);
- if(p->from.type == D_CONST && p->from.sym != nil && (info->flags & LeftRead)) {
+ if(p->from.type == TYPE_ADDR && p->from.sym != nil && (info->flags & LeftRead)) {
info->flags &= ~LeftRead;
info->flags |= LeftAddr;
}
- if((info->flags & RegRead) && p->reg == NREG) {
+ if((info->flags & RegRead) && p->reg == 0) {
info->flags &= ~RegRead;
info->flags |= CanRegRead | RightRead;
}
Prog *p;
p = r->prog;
- p->as = ANOP;
- p->scond = zprog.scond;
- p->from = zprog.from;
- p->to = zprog.to;
- p->reg = zprog.reg;
+ nopout(p);
}
static void
proginfo(&info, p);
// Avoid making variables for direct-called functions.
- if(p->as == ABL && p->to.name == D_EXTERN)
+ if(p->as == ABL && p->to.name == NAME_EXTERN)
continue;
bit = mkvar(r, &p->from);
if(info.flags & LeftAddr)
setaddrs(bit);
- if(info.flags & RegRead) {
- if(p->from.type != D_FREG)
- r->use1.b[0] |= RtoB(p->reg);
- else
- r->use1.b[0] |= FtoB(p->reg);
- }
+ if(info.flags & RegRead)
+ r->use1.b[0] |= RtoB(p->reg);
if(info.flags & (RightAddr | RightRead | RightWrite)) {
bit = mkvar(r, &p->to);
/* the mod/div runtime routines smash R12 */
if(p->as == ADIV || p->as == ADIVU || p->as == AMOD || p->as == AMODU)
- r->set.b[0] |= RtoB(12);
+ r->set.b[0] |= RtoB(REG_R12);
}
if(firstr == R)
return;
}
for(r = firstr; r != R; r = (Reg*)r->f.link) {
p = r->f.prog;
- if(p->as == AVARDEF && isfat(p->to.node->type) && p->to.node->opt != nil) {
+ if(p->as == AVARDEF && isfat(((Node*)(p->to.node))->type) && ((Node*)(p->to.node))->opt != nil) {
active++;
walkvardef(p->to.node, r, active);
}
vreg = paint2(rgp->enter, rgp->varno, 0);
vreg = allreg(vreg, rgp);
if(debug['R']) {
- if(rgp->regno >= NREG)
- print("%L $%d F%d: %Q\n",
- rgp->enter->f.prog->lineno,
- rgp->cost,
- rgp->regno-NREG,
- bit);
- else
- print("%L $%d R%d: %Q\n",
- rgp->enter->f.prog->lineno,
- rgp->cost,
- rgp->regno,
- bit);
+ print("%L $%d %R: %Q\n",
+ rgp->enter->f.prog->lineno,
+ rgp->cost,
+ rgp->regno,
+ bit);
}
if(rgp->regno != 0)
paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
for(p = firstp; p != P; p = p->link) {
while(p->link != P && p->link->as == ANOP)
p->link = p->link->link;
- if(p->to.type == D_BRANCH)
+ if(p->to.type == TYPE_BRANCH)
while(p->to.u.branch != P && p->to.u.branch->as == ANOP)
p->to.u.branch = p->to.u.branch->link;
if(p->as == AMOVW && p->to.reg == 13) {
// print("%P adjusting %d\n", p, vreg);
continue;
}
- if(p->from.type == D_CONST && p->to.type == D_REG) {
+ if(p->from.type == TYPE_CONST && p->to.type == TYPE_REG) {
if(p->from.offset != vreg)
print("in and out different\n");
// print("%P finish %d\n", p, vreg);
continue;
}
-// print("%P %d %d from type\n", p, p->from.type, D_CONST);
-// print("%P %d %d to type\n\n", p, p->to.type, D_REG);
+// print("%P %d %d from type\n", p, p->from.type, TYPE_CONST);
+// print("%P %d %d to type\n\n", p, p->to.type, TYPE_REG);
}
if(p->as == AMOVW && vreg != 0) {
if(p->from.sym != nil)
- if(p->from.name == D_AUTO || p->from.name == D_PARAM) {
+ if(p->from.name == NAME_AUTO || p->from.name == NAME_PARAM) {
p->from.offset += vreg;
// print("%P adjusting from %d %d\n", p, vreg, p->from.type);
}
if(p->to.sym != nil)
- if(p->to.name == D_AUTO || p->to.name == D_PARAM) {
+ if(p->to.name == NAME_AUTO || p->to.name == NAME_PARAM) {
p->to.offset += vreg;
// print("%P adjusting to %d %d\n", p, vreg, p->from.type);
}
// If there's a stack fixup coming (after BL newproc or BL deferproc),
// delay the load until after the fixup.
p2 = p->link;
- if(p2 && p2->as == AMOVW && p2->from.type == D_CONST && p2->from.reg == REGSP && p2->to.reg == REGSP && p2->to.type == D_REG)
+ if(p2 && p2->as == AMOVW && p2->from.type == TYPE_ADDR && p2->from.reg == REGSP && p2->to.reg == REGSP && p2->to.type == TYPE_REG)
p = p2;
p1->link = p->link;
a->sym = linksym(v->node->sym);
a->offset = v->offset;
a->etype = v->etype;
- a->type = D_OREG;
- if(a->etype == TARRAY || a->sym == nil)
- a->type = D_CONST;
+ a->type = TYPE_MEM;
+ if(a->etype == TARRAY)
+ a->type = TYPE_ADDR;
+ else if(a->sym == nil)
+ a->type = TYPE_CONST;
if(v->addr)
fatal("addmove: shouldn't be doing this %A\n", a);
break;
}
- p1->from.type = D_REG;
+ p1->from.type = TYPE_REG;
p1->from.reg = rn;
- if(rn >= NREG) {
- p1->from.type = D_FREG;
- p1->from.reg = rn-NREG;
- }
if(!f) {
p1->from = *a;
*a = zprog.from;
- a->type = D_REG;
+ a->type = TYPE_REG;
a->reg = rn;
- if(rn >= NREG) {
- a->type = D_FREG;
- a->reg = rn-NREG;
- }
if(v->etype == TUINT8 || v->etype == TBOOL)
p1->as = AMOVBU;
if(v->etype == TUINT16)
print("type %d %d %D\n", t, a->name, a);
goto none;
- case D_NONE:
- case D_FCONST:
- case D_BRANCH:
+ case TYPE_NONE:
+ case TYPE_FCONST:
+ case TYPE_BRANCH:
break;
- case D_REGREG:
- case D_REGREG2:
+ case TYPE_REGREG:
+ case TYPE_REGREG2:
bit = zbits;
- if(a->offset != NREG)
+ if(a->offset != 0)
bit.b[0] |= RtoB(a->offset);
- if(a->reg != NREG)
+ if(a->reg != 0)
bit.b[0] |= RtoB(a->reg);
return bit;
+
+ case TYPE_CONST:
+ if(a->reg != 0)
+ fatal("found CONST instead of ADDR: %D", a);
+ break;
- case D_CONST:
- case D_REG:
- case D_SHIFT:
- if(a->reg != NREG) {
+ case TYPE_ADDR:
+ case TYPE_REG:
+ case TYPE_SHIFT:
+ if(a->reg != 0) {
bit = zbits;
bit.b[0] = RtoB(a->reg);
return bit;
}
break;
- case D_OREG:
- if(a->reg != NREG) {
+ case TYPE_MEM:
+ if(a->reg != 0) {
if(a == &r->f.prog->from)
r->use1.b[0] |= RtoB(a->reg);
else
r->set.b[0] |= RtoB(a->reg);
}
break;
-
- case D_FREG:
- if(a->reg != NREG) {
- bit = zbits;
- bit.b[0] = FtoB(a->reg);
- return bit;
- }
- break;
}
switch(a->name) {
default:
goto none;
- case D_EXTERN:
- case D_STATIC:
- case D_AUTO:
- case D_PARAM:
+ case NAME_EXTERN:
+ case NAME_STATIC:
+ case NAME_AUTO:
+ case NAME_PARAM:
n = a->name;
break;
}
node->opt = v;
bit = blsh(i);
- if(n == D_EXTERN || n == D_STATIC)
+ if(n == NAME_EXTERN || n == NAME_STATIC)
for(z=0; z<BITS; z++)
externs.b[z] |= bit.b[z];
- if(n == D_PARAM)
+ if(n == NAME_PARAM)
for(z=0; z<BITS; z++)
params.b[z] |= bit.b[z];
case TFLOAT64:
i = BtoF(~b);
if(i && r->cost >= 0) {
- r->regno = i+NREG;
- return FtoB(i);
+ r->regno = i;
+ return RtoB(i);
}
break;
{
a->sym = nil;
a->node = nil;
- a->name = D_NONE;
- a->type = D_REG;
+ a->name = NAME_NONE;
+ a->type = TYPE_REG;
a->reg = rn;
- if(rn >= NREG) {
- a->type = D_FREG;
- a->reg = rn-NREG;
- }
}
/*
* ... ...
* 10 R10
* 12 R12
+ *
+ * bit reg
+ * 18 F2
+ * 19 F3
+ * ... ...
+ * 31 F15
*/
uint32
RtoB(int r)
{
- if(r >= REGTMP-2 && r != 12) // excluded R9 and R10 for m and g, but not R12
- return 0;
- return 1L << r;
+ if(REG_R0 <= r && r <= REG_R15) {
+ if(r >= REGTMP-2 && r != REG_R12) // excluded R9 and R10 for m and g, but not R12
+ return 0;
+ return 1L << (r - REG_R0);
+ }
+
+ if(REG_F0 <= r && r <= REG_F15) {
+ if(r < REG_F2 || r > REG_F0+NFREG-1)
+ return 0;
+ return 1L << ((r - REG_F0) + 16);
+ }
+
+ return 0;
}
int
b &= 0x11fcL; // excluded R9 and R10 for m and g, but not R12
if(b == 0)
return 0;
- return bitno(b);
-}
-
-/*
- * bit reg
- * 18 F2
- * 19 F3
- * ... ...
- * 31 F15
- */
-uint32
-FtoB(int f)
-{
-
- if(f < 2 || f > NFREG-1)
- return 0;
- return 1L << (f + 16);
+ return bitno(b) + REG_R0;
}
int
BtoF(uint32 b)
{
-
b &= 0xfffc0000L;
if(b == 0)
return 0;
- return bitno(b) - 16;
+ return bitno(b) - 16 + REG_F0;
}
void
enum
{
- REGRET = 0,
+ REG_R0 = 32, // must be 16-aligned
+ REG_R1,
+ REG_R2,
+ REG_R3,
+ REG_R4,
+ REG_R5,
+ REG_R6,
+ REG_R7,
+ REG_R8,
+ REG_R9,
+ REG_R10,
+ REG_R11,
+ REG_R12,
+ REG_R13,
+ REG_R14,
+ REG_R15,
+
+ REG_F0, // must be 16-aligned
+ REG_F1,
+ REG_F2,
+ REG_F3,
+ REG_F4,
+ REG_F5,
+ REG_F6,
+ REG_F7,
+ REG_F8,
+ REG_F9,
+ REG_F10,
+ REG_F11,
+ REG_F12,
+ REG_F13,
+ REG_F14,
+ REG_F15,
+
+ REG_FPSR, // must be 2-aligned
+ REG_FPCR,
+
+ REG_CPSR, // must be 2-aligned
+ REG_SPSR,
+
+ REGRET = REG_R0,
/* compiler allocates R1 up as temps */
/* compiler allocates register variables R3 up */
/* compiler allocates external registers R10 down */
- REGEXT = 10,
+ REGEXT = REG_R10,
/* these two registers are declared in runtime.h */
REGG = REGEXT-0,
REGM = REGEXT-1,
- REGTMP = 11,
- REGSP = 13,
- REGLINK = 14,
- REGPC = 15,
+ REGTMP = REG_R11,
+ REGSP = REG_R13,
+ REGLINK = REG_R14,
+ REGPC = REG_R15,
NFREG = 16,
- FREGRET = 0,
- FREGEXT = 7,
- FREGTMP = 15,
+ FREGRET = REG_F0,
+ FREGEXT = REG_F7,
+ FREGTMP = REG_F15,
};
/* compiler allocates register variables F0 up */
/* compiler allocates external registers F7 down */
C_HREG,
C_ADDR, /* reference to relocatable address */
+ C_TEXTSIZE,
C_GOK,
enum
{
- AXXX,
-
- AAND,
+ AAND = A_ARCHSPECIFIC,
AEOR,
ASUB,
ARSB,
AMVN,
- AB,
- ABL,
-
/*
* Do not reorder or fragment the conditional branch
* opcodes, or the predication code will break
ASWPBU,
ASWPW,
- ANOP,
ARFE,
ASWI,
AMULA,
- ADATA,
- AGLOBL,
- AGOK,
- AHISTORY,
- ANAME,
- ARET,
- ATEXT,
AWORD,
- ADYNT_,
- AINIT_,
ABCASE,
ACASE,
- AEND,
AMULL,
AMULAL,
ABXRET,
ADWORD,
- ASIGNAME,
ALDREX,
ASTREX,
APLD,
- AUNDEF,
ACLZ,
AMULAWT,
AMULAWB,
- AUSEFIELD,
- ATYPE,
- AFUNCDATA,
- APCDATA,
- ACHECKNIL,
- AVARDEF,
- AVARKILL,
- ADUFFCOPY,
- ADUFFZERO,
ADATABUNDLE,
ADATABUNDLEEND,
AMRC, // MRC/MCR
ALAST,
+
+ // aliases
+ AB = AJMP,
+ ABL = ACALL,
};
/* scond byte */
C_FBIT = 1<<7, /* psr flags-only */
C_UBIT = 1<<7, /* up bit, unsigned bit */
- C_SCOND_EQ = 0,
- C_SCOND_NE = 1,
- C_SCOND_HS = 2,
- C_SCOND_LO = 3,
- C_SCOND_MI = 4,
- C_SCOND_PL = 5,
- C_SCOND_VS = 6,
- C_SCOND_VC = 7,
- C_SCOND_HI = 8,
- C_SCOND_LS = 9,
- C_SCOND_GE = 10,
- C_SCOND_LT = 11,
- C_SCOND_GT = 12,
- C_SCOND_LE = 13,
- C_SCOND_NONE = 14,
- C_SCOND_NV = 15,
+ // These constants are the ARM condition codes encodings,
+ // XORed with 14 so that C_SCOND_NONE has value 0,
+ // so that a zeroed Prog.scond means "always execute".
+ C_SCOND_XOR = 14,
+
+ C_SCOND_EQ = 0 ^ C_SCOND_XOR,
+ C_SCOND_NE = 1 ^ C_SCOND_XOR,
+ C_SCOND_HS = 2 ^ C_SCOND_XOR,
+ C_SCOND_LO = 3 ^ C_SCOND_XOR,
+ C_SCOND_MI = 4 ^ C_SCOND_XOR,
+ C_SCOND_PL = 5 ^ C_SCOND_XOR,
+ C_SCOND_VS = 6 ^ C_SCOND_XOR,
+ C_SCOND_VC = 7 ^ C_SCOND_XOR,
+ C_SCOND_HI = 8 ^ C_SCOND_XOR,
+ C_SCOND_LS = 9 ^ C_SCOND_XOR,
+ C_SCOND_GE = 10 ^ C_SCOND_XOR,
+ C_SCOND_LT = 11 ^ C_SCOND_XOR,
+ C_SCOND_GT = 12 ^ C_SCOND_XOR,
+ C_SCOND_LE = 13 ^ C_SCOND_XOR,
+ C_SCOND_NONE = 14 ^ C_SCOND_XOR,
+ C_SCOND_NV = 15 ^ C_SCOND_XOR,
/* D_SHIFT type */
SHIFT_LL = 0<<5,
SHIFT_RR = 3<<5,
};
-enum
-{
-/* type/name */
- D_GOK = 0,
- D_NONE = 1,
-
-/* type */
- D_BRANCH = (D_NONE+1),
- D_OREG = (D_NONE+2),
- D_CONST = (D_NONE+7),
- D_FCONST = (D_NONE+8),
- D_SCONST = (D_NONE+9),
- D_PSR = (D_NONE+10),
- D_REG = (D_NONE+12),
- D_FREG = (D_NONE+13),
- D_FILE = (D_NONE+16),
- D_OCONST = (D_NONE+17),
- D_FILE1 = (D_NONE+18),
-
- D_SHIFT = (D_NONE+19),
- D_FPCR = (D_NONE+20),
- D_REGREG = (D_NONE+21), // (reg, reg)
- D_ADDR = (D_NONE+22),
-
- D_SBIG = (D_NONE+23),
- D_CONST2 = (D_NONE+24),
-
- D_REGREG2 = (D_NONE+25), // reg, reg
-
-/* name */
- D_EXTERN = (D_NONE+3),
- D_STATIC = (D_NONE+4),
- D_AUTO = (D_NONE+5),
- D_PARAM = (D_NONE+6),
-
- D_LAST = (D_NONE+26),
-};
/*
* this is the ranlib header
EXTERN Biobuf obuf;
EXTERN Link* ctxt;
EXTERN Biobuf bstdout;
+EXTERN Prog* lastpc;
void* alloc(int32);
void* allocn(void*, int32, int32);
%token <dval> LFCONST
%token <sval> LSCONST LSP
%token <sym> LNAME LLAB LVAR
-%type <lval> con con2 expr pointer offset
-%type <addr> mem imm imm2 reg nam rel rem rim rom omem nmem
+%type <lval> con expr pointer offset
+%type <addr> mem imm reg nam rel rem rim rom omem nmem textsize
%type <addr2> nonnon nonrel nonrem rimnon rimrem remrim
-%type <addr2> spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8 spec9
-%type <addr2> spec10 spec11 spec12 spec13
+%type <addr2> spec3 spec4 spec5 spec6 spec7 spec8 spec9
+%type <addr2> spec10 spec12 spec13
%%
prog:
| prog
| LTYPE3 rimrem { outcode($1, &$2); }
| LTYPE4 remrim { outcode($1, &$2); }
| LTYPER nonrel { outcode($1, &$2); }
-| LTYPED spec1 { outcode($1, &$2); }
-| LTYPET spec2 { outcode($1, &$2); }
+| spec1
+| spec2
| LTYPEC spec3 { outcode($1, &$2); }
| LTYPEN spec4 { outcode($1, &$2); }
| LTYPES spec5 { outcode($1, &$2); }
| LTYPEXC spec8 { outcode($1, &$2); }
| LTYPEX spec9 { outcode($1, &$2); }
| LTYPERT spec10 { outcode($1, &$2); }
-| LTYPEG spec11 { outcode($1, &$2); }
+| spec11
| LTYPEPC spec12 { outcode($1, &$2); }
| LTYPEF spec13 { outcode($1, &$2); }
}
spec1: /* DATA */
- nam '/' con ',' imm
+ LTYPED nam '/' con ',' imm
{
- $$.from = $1;
- $$.from.scale = $3;
- $$.to = $5;
+ Addr2 a;
+ a.from = $2;
+ a.to = $6;
+ outcode(ADATA, &a);
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = $4;
+ }
}
spec2: /* TEXT */
- mem ',' imm2
+ LTYPET mem ',' '$' textsize
{
- settext($1.sym);
- $$.from = $1;
- $$.to = $3;
+ Addr2 a;
+ settext($2.sym);
+ a.from = $2;
+ a.to = $5;
+ outcode(ATEXT, &a);
}
-| mem ',' con ',' imm2
+| LTYPET mem ',' con ',' '$' textsize
{
- settext($1.sym);
- $$.from = $1;
- $$.from.scale = $3;
- $$.to = $5;
+ Addr2 a;
+ settext($2.sym);
+ a.from = $2;
+ a.to = $7;
+ outcode(ATEXT, &a);
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = $4;
+ }
+ }
+
+spec11: /* GLOBL */
+ LTYPEG mem ',' imm
+ {
+ Addr2 a;
+ settext($2.sym);
+ a.from = $2;
+ a.to = $4;
+ outcode(AGLOBL, &a);
+ }
+| LTYPEG mem ',' con ',' imm
+ {
+ Addr2 a;
+ settext($2.sym);
+ a.from = $2;
+ a.to = $6;
+ outcode(AGLOBL, &a);
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = $4;
+ }
}
spec3: /* JMP/CALL */
{
$$.from = $1;
$$.to = $3;
- if($$.from.index != D_NONE)
+ if($$.from.index != TYPE_NONE)
yyerror("dp shift with lhs index");
$$.from.index = $5;
}
{
$$.from = $1;
$$.to = $3;
- if($$.to.index != D_NONE)
+ if($$.to.index != TYPE_NONE)
yyerror("dp move with lhs index");
$$.to.index = $5;
}
{
$$.from = $3;
$$.to = $5;
- if($1.type != D_CONST)
+ if($1.type != TYPE_CONST)
yyerror("illegal constant");
$$.to.offset = $1.offset;
}
$$.to = nullgen;
}
-spec11: /* GLOBL */
- mem ',' imm
- {
- $$.from = $1;
- $$.to = $3;
- }
-| mem ',' con ',' imm
- {
- $$.from = $1;
- $$.from.scale = $3;
- $$.to = $5;
- }
-
spec12: /* PCDATA */
rim ',' rim
{
- if($1.type != D_CONST || $3.type != D_CONST)
+ if($1.type != TYPE_CONST || $3.type != TYPE_CONST)
yyerror("arguments to PCDATA must be integer constants");
$$.from = $1;
$$.to = $3;
spec13: /* FUNCDATA */
rim ',' rim
{
- if($1.type != D_CONST)
+ if($1.type != TYPE_CONST)
yyerror("index for FUNCDATA must be integer constant");
- if($3.type != D_EXTERN && $3.type != D_STATIC)
+ if($3.type != TYPE_MEM || ($3.name != NAME_EXTERN && $3.name != NAME_STATIC))
yyerror("value for FUNCDATA must be symbol reference");
$$.from = $1;
$$.to = $3;
con '(' LPC ')'
{
$$ = nullgen;
- $$.type = D_BRANCH;
+ $$.type = TYPE_BRANCH;
$$.offset = $1 + pc;
}
| LNAME offset
$$ = nullgen;
if(pass == 2 && $1->type != LLAB)
yyerror("undefined label: %s", $1->labelname);
- $$.type = D_BRANCH;
+ $$.type = TYPE_BRANCH;
$$.offset = $1->value + $2;
}
LBREG
{
$$ = nullgen;
- $$.type = $1;
+ $$.type = TYPE_REG;
+ $$.reg = $1;
}
| LFREG
{
$$ = nullgen;
- $$.type = $1;
+ $$.type = TYPE_REG;
+ $$.reg = $1;
}
| LLREG
{
$$ = nullgen;
- $$.type = $1;
+ $$.type = TYPE_REG;
+ $$.reg = $1;
}
| LMREG
{
$$ = nullgen;
- $$.type = $1;
+ $$.type = TYPE_REG;
+ $$.reg = $1;
}
| LSP
{
$$ = nullgen;
- $$.type = D_SP;
+ $$.type = TYPE_REG;
+ $$.reg = REG_SP;
}
| LSREG
{
$$ = nullgen;
- $$.type = $1;
+ $$.type = TYPE_REG;
+ $$.reg = $1;
}
| LXREG
{
$$ = nullgen;
- $$.type = $1;
- }
-imm2:
- '$' con2
- {
- $$ = nullgen;
- $$.type = D_CONST;
- $$.offset = $2;
+ $$.type = TYPE_REG;
+ $$.reg = $1;
}
imm:
'$' con
{
$$ = nullgen;
- $$.type = D_CONST;
+ $$.type = TYPE_CONST;
$$.offset = $2;
}
| '$' nam
{
$$ = $2;
- $$.index = $2.type;
- $$.type = D_ADDR;
+ $$.type = TYPE_ADDR;
/*
if($2.type == D_AUTO || $2.type == D_PARAM)
yyerror("constant cannot be automatic: %s",
| '$' LSCONST
{
$$ = nullgen;
- $$.type = D_SCONST;
+ $$.type = TYPE_SCONST;
memcpy($$.u.sval, $2, sizeof($$.u.sval));
}
| '$' LFCONST
{
$$ = nullgen;
- $$.type = D_FCONST;
+ $$.type = TYPE_FCONST;
$$.u.dval = $2;
}
| '$' '(' LFCONST ')'
{
$$ = nullgen;
- $$.type = D_FCONST;
+ $$.type = TYPE_FCONST;
$$.u.dval = $3;
}
| '$' '(' '-' LFCONST ')'
{
$$ = nullgen;
- $$.type = D_FCONST;
+ $$.type = TYPE_FCONST;
$$.u.dval = -$4;
}
| '$' '-' LFCONST
{
$$ = nullgen;
- $$.type = D_FCONST;
+ $$.type = TYPE_FCONST;
$$.u.dval = -$3;
}
con
{
$$ = nullgen;
- $$.type = D_INDIR+D_NONE;
+ $$.type = TYPE_MEM;
$$.offset = $1;
}
| con '(' LLREG ')'
{
$$ = nullgen;
- $$.type = D_INDIR+$3;
+ $$.type = TYPE_MEM;
+ $$.reg = $3;
$$.offset = $1;
}
| con '(' LSP ')'
{
$$ = nullgen;
- $$.type = D_INDIR+D_SP;
+ $$.type = TYPE_MEM;
+ $$.reg = REG_SP;
$$.offset = $1;
}
| con '(' LSREG ')'
{
$$ = nullgen;
- $$.type = D_INDIR+$3;
+ $$.type = TYPE_MEM;
+ $$.reg = $3;
$$.offset = $1;
}
| con '(' LLREG '*' con ')'
{
$$ = nullgen;
- $$.type = D_INDIR+D_NONE;
+ $$.type = TYPE_MEM;
$$.offset = $1;
$$.index = $3;
$$.scale = $5;
| con '(' LLREG ')' '(' LLREG '*' con ')'
{
$$ = nullgen;
- $$.type = D_INDIR+$3;
+ $$.type = TYPE_MEM;
+ $$.reg = $3;
$$.offset = $1;
$$.index = $6;
$$.scale = $8;
| con '(' LLREG ')' '(' LSREG '*' con ')'
{
$$ = nullgen;
- $$.type = D_INDIR+$3;
+ $$.type = TYPE_MEM;
+ $$.reg = $3;
$$.offset = $1;
$$.index = $6;
$$.scale = $8;
| '(' LLREG ')'
{
$$ = nullgen;
- $$.type = D_INDIR+$2;
+ $$.type = TYPE_MEM;
+ $$.reg = $2;
}
| '(' LSP ')'
{
$$ = nullgen;
- $$.type = D_INDIR+D_SP;
+ $$.type = TYPE_MEM;
+ $$.reg = REG_SP;
}
| '(' LLREG '*' con ')'
{
$$ = nullgen;
- $$.type = D_INDIR+D_NONE;
+ $$.type = TYPE_MEM;
$$.index = $2;
$$.scale = $4;
checkscale($$.scale);
| '(' LLREG ')' '(' LLREG '*' con ')'
{
$$ = nullgen;
- $$.type = D_INDIR+$2;
+ $$.type = TYPE_MEM;
+ $$.reg = $2;
$$.index = $5;
$$.scale = $7;
checkscale($$.scale);
LNAME offset '(' pointer ')'
{
$$ = nullgen;
- $$.type = $4;
+ $$.type = TYPE_MEM;
+ $$.name = $4;
$$.sym = linklookup(ctxt, $1->name, 0);
$$.offset = $2;
}
| LNAME '<' '>' offset '(' LSB ')'
{
$$ = nullgen;
- $$.type = D_STATIC;
+ $$.type = TYPE_MEM;
+ $$.name = NAME_STATIC;
$$.sym = linklookup(ctxt, $1->name, 1);
$$.offset = $4;
}
LSB
| LSP
{
- $$ = D_AUTO;
+ $$ = NAME_AUTO;
}
| LFP
$$ = $2;
}
-con2:
+textsize:
LCONST
{
- $$ = ($1 & 0xffffffffLL) +
- ((vlong)ArgsSizeUnknown << 32);
+ $$ = nullgen;
+ $$.type = TYPE_TEXTSIZE;
+ $$.offset = $1;
+ $$.u.argsize = ArgsSizeUnknown;
}
| '-' LCONST
{
- $$ = (-$2 & 0xffffffffLL) +
- ((vlong)ArgsSizeUnknown << 32);
+ $$ = nullgen;
+ $$.type = TYPE_TEXTSIZE;
+ $$.offset = -$2;
+ $$.u.argsize = ArgsSizeUnknown;
}
| LCONST '-' LCONST
{
- $$ = ($1 & 0xffffffffLL) +
- (($3 & 0xffffLL) << 32);
+ $$ = nullgen;
+ $$.type = TYPE_TEXTSIZE;
+ $$.offset = $1;
+ $$.u.argsize = $3;
}
| '-' LCONST '-' LCONST
{
- $$ = (-$2 & 0xffffffffLL) +
- (($4 & 0xffffLL) << 32);
+ $$ = nullgen;
+ $$.type = TYPE_TEXTSIZE;
+ $$.offset = -$2;
+ $$.u.argsize = $4;
}
expr:
ushort value;
} itab[] =
{
- "SP", LSP, D_AUTO,
- "SB", LSB, D_EXTERN,
- "FP", LFP, D_PARAM,
- "PC", LPC, D_BRANCH,
+ "SP", LSP, NAME_AUTO,
+ "SB", LSB, NAME_EXTERN,
+ "FP", LFP, NAME_PARAM,
- "AL", LBREG, D_AL,
- "CL", LBREG, D_CL,
- "DL", LBREG, D_DL,
- "BL", LBREG, D_BL,
-/* "SPB", LBREG, D_SPB, */
- "SIB", LBREG, D_SIB,
- "DIB", LBREG, D_DIB,
- "BPB", LBREG, D_BPB,
- "R8B", LBREG, D_R8B,
- "R9B", LBREG, D_R9B,
- "R10B", LBREG, D_R10B,
- "R11B", LBREG, D_R11B,
- "R12B", LBREG, D_R12B,
- "R13B", LBREG, D_R13B,
- "R14B", LBREG, D_R14B,
- "R15B", LBREG, D_R15B,
+ "PC", LPC, TYPE_BRANCH,
- "AH", LBREG, D_AH,
- "CH", LBREG, D_CH,
- "DH", LBREG, D_DH,
- "BH", LBREG, D_BH,
+ "AL", LBREG, REG_AL,
+ "CL", LBREG, REG_CL,
+ "DL", LBREG, REG_DL,
+ "BL", LBREG, REG_BL,
+/* "SPB", LBREG, REG_SPB, */
+ "SIB", LBREG, REG_SIB,
+ "DIB", LBREG, REG_DIB,
+ "BPB", LBREG, REG_BPB,
+ "R8B", LBREG, REG_R8B,
+ "R9B", LBREG, REG_R9B,
+ "R10B", LBREG, REG_R10B,
+ "R11B", LBREG, REG_R11B,
+ "R12B", LBREG, REG_R12B,
+ "R13B", LBREG, REG_R13B,
+ "R14B", LBREG, REG_R14B,
+ "R15B", LBREG, REG_R15B,
- "AX", LLREG, D_AX,
- "CX", LLREG, D_CX,
- "DX", LLREG, D_DX,
- "BX", LLREG, D_BX,
-/* "SP", LLREG, D_SP, */
- "BP", LLREG, D_BP,
- "SI", LLREG, D_SI,
- "DI", LLREG, D_DI,
- "R8", LLREG, D_R8,
- "R9", LLREG, D_R9,
- "R10", LLREG, D_R10,
- "R11", LLREG, D_R11,
- "R12", LLREG, D_R12,
- "R13", LLREG, D_R13,
- "R14", LLREG, D_R14,
- "R15", LLREG, D_R15,
+ "AH", LBREG, REG_AH,
+ "CH", LBREG, REG_CH,
+ "DH", LBREG, REG_DH,
+ "BH", LBREG, REG_BH,
+
+ "AX", LLREG, REG_AX,
+ "CX", LLREG, REG_CX,
+ "DX", LLREG, REG_DX,
+ "BX", LLREG, REG_BX,
+/* "SP", LLREG, REG_SP, */
+ "BP", LLREG, REG_BP,
+ "SI", LLREG, REG_SI,
+ "DI", LLREG, REG_DI,
+ "R8", LLREG, REG_R8,
+ "R9", LLREG, REG_R9,
+ "R10", LLREG, REG_R10,
+ "R11", LLREG, REG_R11,
+ "R12", LLREG, REG_R12,
+ "R13", LLREG, REG_R13,
+ "R14", LLREG, REG_R14,
+ "R15", LLREG, REG_R15,
"RARG", LLREG, REGARG,
- "F0", LFREG, D_F0+0,
- "F1", LFREG, D_F0+1,
- "F2", LFREG, D_F0+2,
- "F3", LFREG, D_F0+3,
- "F4", LFREG, D_F0+4,
- "F5", LFREG, D_F0+5,
- "F6", LFREG, D_F0+6,
- "F7", LFREG, D_F0+7,
+ "F0", LFREG, REG_F0+0,
+ "F1", LFREG, REG_F0+1,
+ "F2", LFREG, REG_F0+2,
+ "F3", LFREG, REG_F0+3,
+ "F4", LFREG, REG_F0+4,
+ "F5", LFREG, REG_F0+5,
+ "F6", LFREG, REG_F0+6,
+ "F7", LFREG, REG_F0+7,
- "M0", LMREG, D_M0+0,
- "M1", LMREG, D_M0+1,
- "M2", LMREG, D_M0+2,
- "M3", LMREG, D_M0+3,
- "M4", LMREG, D_M0+4,
- "M5", LMREG, D_M0+5,
- "M6", LMREG, D_M0+6,
- "M7", LMREG, D_M0+7,
+ "M0", LMREG, REG_M0+0,
+ "M1", LMREG, REG_M0+1,
+ "M2", LMREG, REG_M0+2,
+ "M3", LMREG, REG_M0+3,
+ "M4", LMREG, REG_M0+4,
+ "M5", LMREG, REG_M0+5,
+ "M6", LMREG, REG_M0+6,
+ "M7", LMREG, REG_M0+7,
- "X0", LXREG, D_X0+0,
- "X1", LXREG, D_X0+1,
- "X2", LXREG, D_X0+2,
- "X3", LXREG, D_X0+3,
- "X4", LXREG, D_X0+4,
- "X5", LXREG, D_X0+5,
- "X6", LXREG, D_X0+6,
- "X7", LXREG, D_X0+7,
- "X8", LXREG, D_X0+8,
- "X9", LXREG, D_X0+9,
- "X10", LXREG, D_X0+10,
- "X11", LXREG, D_X0+11,
- "X12", LXREG, D_X0+12,
- "X13", LXREG, D_X0+13,
- "X14", LXREG, D_X0+14,
- "X15", LXREG, D_X0+15,
+ "X0", LXREG, REG_X0+0,
+ "X1", LXREG, REG_X0+1,
+ "X2", LXREG, REG_X0+2,
+ "X3", LXREG, REG_X0+3,
+ "X4", LXREG, REG_X0+4,
+ "X5", LXREG, REG_X0+5,
+ "X6", LXREG, REG_X0+6,
+ "X7", LXREG, REG_X0+7,
+ "X8", LXREG, REG_X0+8,
+ "X9", LXREG, REG_X0+9,
+ "X10", LXREG, REG_X0+10,
+ "X11", LXREG, REG_X0+11,
+ "X12", LXREG, REG_X0+12,
+ "X13", LXREG, REG_X0+13,
+ "X14", LXREG, REG_X0+14,
+ "X15", LXREG, REG_X0+15,
- "CS", LSREG, D_CS,
- "SS", LSREG, D_SS,
- "DS", LSREG, D_DS,
- "ES", LSREG, D_ES,
- "FS", LSREG, D_FS,
- "GS", LSREG, D_GS,
+ "CS", LSREG, REG_CS,
+ "SS", LSREG, REG_SS,
+ "DS", LSREG, REG_DS,
+ "ES", LSREG, REG_ES,
+ "FS", LSREG, REG_FS,
+ "GS", LSREG, REG_GS,
- "GDTR", LBREG, D_GDTR,
- "IDTR", LBREG, D_IDTR,
- "LDTR", LBREG, D_LDTR,
- "MSW", LBREG, D_MSW,
- "TASK", LBREG, D_TASK,
+ "GDTR", LBREG, REG_GDTR,
+ "IDTR", LBREG, REG_IDTR,
+ "LDTR", LBREG, REG_LDTR,
+ "MSW", LBREG, REG_MSW,
+ "TASK", LBREG, REG_TASK,
- "CR0", LBREG, D_CR+0,
- "CR1", LBREG, D_CR+1,
- "CR2", LBREG, D_CR+2,
- "CR3", LBREG, D_CR+3,
- "CR4", LBREG, D_CR+4,
- "CR5", LBREG, D_CR+5,
- "CR6", LBREG, D_CR+6,
- "CR7", LBREG, D_CR+7,
- "CR8", LBREG, D_CR+8,
- "CR9", LBREG, D_CR+9,
- "CR10", LBREG, D_CR+10,
- "CR11", LBREG, D_CR+11,
- "CR12", LBREG, D_CR+12,
- "CR13", LBREG, D_CR+13,
- "CR14", LBREG, D_CR+14,
- "CR15", LBREG, D_CR+15,
+ "CR0", LBREG, REG_CR+0,
+ "CR1", LBREG, REG_CR+1,
+ "CR2", LBREG, REG_CR+2,
+ "CR3", LBREG, REG_CR+3,
+ "CR4", LBREG, REG_CR+4,
+ "CR5", LBREG, REG_CR+5,
+ "CR6", LBREG, REG_CR+6,
+ "CR7", LBREG, REG_CR+7,
+ "CR8", LBREG, REG_CR+8,
+ "CR9", LBREG, REG_CR+9,
+ "CR10", LBREG, REG_CR+10,
+ "CR11", LBREG, REG_CR+11,
+ "CR12", LBREG, REG_CR+12,
+ "CR13", LBREG, REG_CR+13,
+ "CR14", LBREG, REG_CR+14,
+ "CR15", LBREG, REG_CR+15,
- "DR0", LBREG, D_DR+0,
- "DR1", LBREG, D_DR+1,
- "DR2", LBREG, D_DR+2,
- "DR3", LBREG, D_DR+3,
- "DR4", LBREG, D_DR+4,
- "DR5", LBREG, D_DR+5,
- "DR6", LBREG, D_DR+6,
- "DR7", LBREG, D_DR+7,
+ "DR0", LBREG, REG_DR+0,
+ "DR1", LBREG, REG_DR+1,
+ "DR2", LBREG, REG_DR+2,
+ "DR3", LBREG, REG_DR+3,
+ "DR4", LBREG, REG_DR+4,
+ "DR5", LBREG, REG_DR+5,
+ "DR6", LBREG, REG_DR+6,
+ "DR7", LBREG, REG_DR+7,
- "TR0", LBREG, D_TR+0,
- "TR1", LBREG, D_TR+1,
- "TR2", LBREG, D_TR+2,
- "TR3", LBREG, D_TR+3,
- "TR4", LBREG, D_TR+4,
- "TR5", LBREG, D_TR+5,
- "TR6", LBREG, D_TR+6,
- "TR7", LBREG, D_TR+7,
- "TLS", LSREG, D_TLS,
+ "TR0", LBREG, REG_TR+0,
+ "TR1", LBREG, REG_TR+1,
+ "TR2", LBREG, REG_TR+2,
+ "TR3", LBREG, REG_TR+3,
+ "TR4", LBREG, REG_TR+4,
+ "TR5", LBREG, REG_TR+5,
+ "TR6", LBREG, REG_TR+6,
+ "TR7", LBREG, REG_TR+7,
+ "TLS", LSREG, REG_TLS,
"AAA", LTYPE0, AAAA,
"AAD", LTYPE0, AAAD,
Sym *s;
int i;
- nullgen.type = D_NONE;
- nullgen.index = D_NONE;
+ nullgen.type = TYPE_NONE;
+ nullgen.index = TYPE_NONE;
nerrors = 0;
iostack = I;
outcode(AEND, &g2);
}
-static Prog *lastpc;
-
void
outcode(int a, Addr2 *g2)
{
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 2
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 549
+#define YYLAST 524
/* YYNTOKENS -- Number of terminals. */
#define YYNTOKENS 56
/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 41
+#define YYNNTS 40
/* YYNRULES -- Number of rules. */
-#define YYNRULES 134
+#define YYNRULES 133
/* YYNRULES -- Number of states. */
#define YYNSTATES 271
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 54, 12, 5, 2,
- 52, 53, 10, 8, 51, 9, 2, 11, 2, 2,
+ 2, 2, 2, 2, 2, 2, 52, 12, 5, 2,
+ 53, 54, 10, 8, 51, 9, 2, 11, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 48, 49,
6, 50, 7, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
static const yytype_uint16 yyprhs[] =
{
0, 0, 3, 4, 5, 9, 10, 15, 17, 20,
- 23, 27, 31, 34, 37, 40, 43, 46, 49, 52,
- 55, 58, 61, 64, 67, 70, 73, 76, 79, 82,
- 85, 88, 89, 91, 95, 99, 102, 104, 107, 109,
- 112, 114, 118, 124, 128, 134, 137, 139, 141, 143,
- 147, 153, 157, 163, 166, 168, 172, 178, 184, 185,
- 187, 191, 197, 201, 205, 207, 209, 211, 213, 216,
- 219, 221, 223, 225, 227, 232, 235, 237, 239, 241,
- 243, 245, 247, 249, 252, 255, 258, 261, 264, 269,
- 275, 279, 281, 283, 285, 290, 295, 300, 307, 317,
- 327, 331, 335, 341, 350, 352, 359, 365, 373, 374,
- 377, 380, 382, 384, 386, 388, 390, 393, 396, 399,
- 403, 405, 408, 412, 417, 419, 423, 427, 431, 435,
- 439, 444, 449, 453, 457
+ 23, 27, 31, 34, 37, 40, 43, 46, 49, 51,
+ 53, 56, 59, 62, 65, 68, 71, 74, 77, 79,
+ 82, 85, 86, 88, 92, 96, 99, 101, 104, 106,
+ 109, 111, 115, 122, 128, 136, 141, 148, 151, 153,
+ 155, 157, 161, 167, 171, 177, 180, 182, 186, 192,
+ 198, 199, 201, 205, 209, 211, 213, 215, 217, 220,
+ 223, 225, 227, 229, 231, 236, 239, 241, 243, 245,
+ 247, 249, 251, 253, 256, 259, 262, 265, 270, 276,
+ 280, 282, 284, 286, 291, 296, 301, 308, 318, 328,
+ 332, 336, 342, 351, 353, 360, 366, 374, 375, 378,
+ 381, 383, 385, 387, 389, 391, 394, 397, 400, 404,
+ 406, 409, 413, 418, 420, 424, 428, 432, 436, 440,
+ 445, 450, 454, 458
};
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
{
57, 0, -1, -1, -1, 57, 58, 59, -1, -1,
45, 48, 60, 59, -1, 49, -1, 61, 49, -1,
- 1, 49, -1, 45, 50, 96, -1, 47, 50, 96,
+ 1, 49, -1, 45, 50, 95, -1, 47, 50, 95,
-1, 13, 62, -1, 14, 66, -1, 15, 65, -1,
- 16, 63, -1, 17, 64, -1, 21, 67, -1, 19,
- 68, -1, 22, 69, -1, 18, 70, -1, 20, 71,
- -1, 25, 72, -1, 26, 73, -1, 27, 74, -1,
- 28, 75, -1, 29, 76, -1, 30, 77, -1, 23,
- 78, -1, 24, 79, -1, 31, 80, -1, -1, 51,
- -1, 83, 51, 81, -1, 81, 51, 83, -1, 83,
- 51, -1, 83, -1, 51, 81, -1, 81, -1, 51,
- 84, -1, 84, -1, 87, 51, 84, -1, 91, 11,
- 94, 51, 87, -1, 88, 51, 86, -1, 88, 51,
- 94, 51, 86, -1, 51, 82, -1, 82, -1, 62,
- -1, 66, -1, 83, 51, 81, -1, 83, 51, 81,
- 48, 37, -1, 83, 51, 81, -1, 83, 51, 81,
- 48, 38, -1, 83, 51, -1, 83, -1, 83, 51,
- 81, -1, 85, 51, 81, 51, 94, -1, 87, 51,
- 81, 51, 85, -1, -1, 87, -1, 88, 51, 87,
- -1, 88, 51, 94, 51, 87, -1, 83, 51, 83,
- -1, 83, 51, 83, -1, 85, -1, 88, -1, 84,
- -1, 90, -1, 10, 85, -1, 10, 89, -1, 85,
- -1, 89, -1, 81, -1, 87, -1, 94, 52, 34,
- 53, -1, 45, 92, -1, 36, -1, 39, -1, 37,
- -1, 40, -1, 44, -1, 38, -1, 41, -1, 54,
- 95, -1, 54, 94, -1, 54, 91, -1, 54, 43,
- -1, 54, 42, -1, 54, 52, 42, 53, -1, 54,
- 52, 9, 42, 53, -1, 54, 9, 42, -1, 89,
- -1, 90, -1, 94, -1, 94, 52, 37, 53, -1,
- 94, 52, 44, 53, -1, 94, 52, 38, 53, -1,
- 94, 52, 37, 10, 94, 53, -1, 94, 52, 37,
- 53, 52, 37, 10, 94, 53, -1, 94, 52, 37,
- 53, 52, 38, 10, 94, 53, -1, 52, 37, 53,
- -1, 52, 44, 53, -1, 52, 37, 10, 94, 53,
- -1, 52, 37, 53, 52, 37, 10, 94, 53, -1,
- 91, -1, 91, 52, 37, 10, 94, 53, -1, 45,
- 92, 52, 93, 53, -1, 45, 6, 7, 92, 52,
- 35, 53, -1, -1, 8, 94, -1, 9, 94, -1,
- 35, -1, 44, -1, 33, -1, 32, -1, 47, -1,
- 9, 94, -1, 8, 94, -1, 55, 94, -1, 52,
- 96, 53, -1, 32, -1, 9, 32, -1, 32, 9,
- 32, -1, 9, 32, 9, 32, -1, 94, -1, 96,
- 8, 96, -1, 96, 9, 96, -1, 96, 10, 96,
- -1, 96, 11, 96, -1, 96, 12, 96, -1, 96,
- 6, 6, 96, -1, 96, 7, 7, 96, -1, 96,
- 5, 96, -1, 96, 4, 96, -1, 96, 3, 96,
- -1
+ 16, 63, -1, 17, 64, -1, 21, 67, -1, 68,
+ -1, 69, -1, 18, 71, -1, 20, 72, -1, 25,
+ 73, -1, 26, 74, -1, 27, 75, -1, 28, 76,
+ -1, 29, 77, -1, 30, 78, -1, 70, -1, 24,
+ 79, -1, 31, 80, -1, -1, 51, -1, 83, 51,
+ 81, -1, 81, 51, 83, -1, 83, 51, -1, 83,
+ -1, 51, 81, -1, 81, -1, 51, 84, -1, 84,
+ -1, 86, 51, 84, -1, 19, 90, 11, 93, 51,
+ 86, -1, 22, 87, 51, 52, 94, -1, 22, 87,
+ 51, 93, 51, 52, 94, -1, 23, 87, 51, 86,
+ -1, 23, 87, 51, 93, 51, 86, -1, 51, 82,
+ -1, 82, -1, 62, -1, 66, -1, 83, 51, 81,
+ -1, 83, 51, 81, 48, 37, -1, 83, 51, 81,
+ -1, 83, 51, 81, 48, 38, -1, 83, 51, -1,
+ 83, -1, 83, 51, 81, -1, 85, 51, 81, 51,
+ 93, -1, 86, 51, 81, 51, 85, -1, -1, 86,
+ -1, 83, 51, 83, -1, 83, 51, 83, -1, 85,
+ -1, 87, -1, 84, -1, 89, -1, 10, 85, -1,
+ 10, 88, -1, 85, -1, 88, -1, 81, -1, 86,
+ -1, 93, 53, 34, 54, -1, 45, 91, -1, 36,
+ -1, 39, -1, 37, -1, 40, -1, 44, -1, 38,
+ -1, 41, -1, 52, 93, -1, 52, 90, -1, 52,
+ 43, -1, 52, 42, -1, 52, 53, 42, 54, -1,
+ 52, 53, 9, 42, 54, -1, 52, 9, 42, -1,
+ 88, -1, 89, -1, 93, -1, 93, 53, 37, 54,
+ -1, 93, 53, 44, 54, -1, 93, 53, 38, 54,
+ -1, 93, 53, 37, 10, 93, 54, -1, 93, 53,
+ 37, 54, 53, 37, 10, 93, 54, -1, 93, 53,
+ 37, 54, 53, 38, 10, 93, 54, -1, 53, 37,
+ 54, -1, 53, 44, 54, -1, 53, 37, 10, 93,
+ 54, -1, 53, 37, 54, 53, 37, 10, 93, 54,
+ -1, 90, -1, 90, 53, 37, 10, 93, 54, -1,
+ 45, 91, 53, 92, 54, -1, 45, 6, 7, 91,
+ 53, 35, 54, -1, -1, 8, 93, -1, 9, 93,
+ -1, 35, -1, 44, -1, 33, -1, 32, -1, 47,
+ -1, 9, 93, -1, 8, 93, -1, 55, 93, -1,
+ 53, 95, 54, -1, 32, -1, 9, 32, -1, 32,
+ 9, 32, -1, 9, 32, 9, 32, -1, 93, -1,
+ 95, 8, 95, -1, 95, 9, 95, -1, 95, 10,
+ 95, -1, 95, 11, 95, -1, 95, 12, 95, -1,
+ 95, 6, 6, 95, -1, 95, 7, 7, 95, -1,
+ 95, 5, 95, -1, 95, 4, 95, -1, 95, 3,
+ 95, -1
};
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
88, 93, 99, 100, 101, 102, 103, 104, 105, 106,
107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
117, 120, 124, 131, 138, 145, 150, 157, 162, 169,
- 174, 179, 186, 194, 200, 209, 214, 221, 222, 225,
- 230, 240, 245, 255, 260, 265, 272, 280, 290, 294,
- 301, 306, 314, 323, 334, 335, 338, 339, 340, 344,
- 348, 349, 352, 353, 356, 362, 373, 378, 383, 388,
- 393, 398, 403, 409, 417, 423, 434, 440, 446, 452,
- 458, 466, 467, 470, 476, 482, 488, 494, 503, 512,
- 521, 526, 531, 539, 549, 553, 562, 569, 578, 581,
- 585, 591, 592, 596, 599, 600, 604, 608, 612, 616,
- 622, 627, 632, 637, 644, 645, 649, 653, 657, 661,
- 665, 669, 673, 677, 681
+ 174, 179, 186, 199, 207, 221, 229, 243, 248, 255,
+ 256, 259, 264, 274, 279, 289, 294, 299, 306, 314,
+ 324, 328, 335, 344, 355, 356, 359, 360, 361, 365,
+ 369, 370, 373, 374, 377, 383, 394, 400, 406, 412,
+ 418, 424, 430, 438, 444, 454, 460, 466, 472, 478,
+ 486, 487, 490, 496, 503, 510, 517, 526, 536, 546,
+ 552, 558, 566, 577, 581, 590, 598, 608, 611, 615,
+ 621, 622, 626, 629, 630, 634, 638, 642, 646, 652,
+ 659, 666, 673, 682, 683, 687, 691, 695, 699, 703,
+ 707, 711, 715, 719
};
#endif
"LTYPEPC", "LTYPES", "LTYPEM", "LTYPEI", "LTYPEXC", "LTYPEX", "LTYPERT",
"LTYPEF", "LCONST", "LFP", "LPC", "LSB", "LBREG", "LLREG", "LSREG",
"LFREG", "LMREG", "LXREG", "LFCONST", "LSCONST", "LSP", "LNAME", "LLAB",
- "LVAR", "':'", "';'", "'='", "','", "'('", "')'", "'$'", "'~'",
+ "LVAR", "':'", "';'", "'='", "','", "'$'", "'('", "')'", "'~'",
"$accept", "prog", "@1", "line", "@2", "inst", "nonnon", "rimrem",
- "remrim", "rimnon", "nonrem", "nonrel", "spec1", "spec2", "spec3",
- "spec4", "spec5", "spec6", "spec7", "spec8", "spec9", "spec10", "spec11",
- "spec12", "spec13", "rem", "rom", "rim", "rel", "reg", "imm2", "imm",
- "mem", "omem", "nmem", "nam", "offset", "pointer", "con", "con2", "expr", 0
+ "remrim", "rimnon", "nonrem", "nonrel", "spec1", "spec2", "spec11",
+ "spec3", "spec4", "spec5", "spec6", "spec7", "spec8", "spec9", "spec10",
+ "spec12", "spec13", "rem", "rom", "rim", "rel", "reg", "imm", "mem",
+ "omem", "nmem", "nam", "offset", "pointer", "con", "textsize", "expr", 0
};
#endif
265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
285, 286, 287, 288, 289, 290, 291, 292, 58, 59,
- 61, 44, 40, 41, 36, 126
+ 61, 44, 36, 40, 41, 126
};
# endif
61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
61, 62, 62, 63, 64, 65, 65, 66, 66, 67,
67, 67, 68, 69, 69, 70, 70, 71, 71, 72,
- 72, 73, 73, 74, 74, 74, 75, 76, 77, 77,
+ 72, 73, 73, 74, 74, 75, 75, 75, 76, 77,
78, 78, 79, 80, 81, 81, 82, 82, 82, 82,
82, 82, 83, 83, 84, 84, 85, 85, 85, 85,
- 85, 85, 85, 86, 87, 87, 87, 87, 87, 87,
- 87, 88, 88, 89, 89, 89, 89, 89, 89, 89,
- 89, 89, 89, 89, 90, 90, 91, 91, 92, 92,
- 92, 93, 93, 93, 94, 94, 94, 94, 94, 94,
- 95, 95, 95, 95, 96, 96, 96, 96, 96, 96,
- 96, 96, 96, 96, 96
+ 85, 85, 85, 86, 86, 86, 86, 86, 86, 86,
+ 87, 87, 88, 88, 88, 88, 88, 88, 88, 88,
+ 88, 88, 88, 89, 89, 90, 90, 91, 91, 91,
+ 92, 92, 92, 93, 93, 93, 93, 93, 93, 94,
+ 94, 94, 94, 95, 95, 95, 95, 95, 95, 95,
+ 95, 95, 95, 95
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
static const yytype_uint8 yyr2[] =
{
0, 2, 0, 0, 3, 0, 4, 1, 2, 2,
- 3, 3, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 2, 2, 2, 2, 2, 2, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 1, 2,
2, 0, 1, 3, 3, 2, 1, 2, 1, 2,
- 1, 3, 5, 3, 5, 2, 1, 1, 1, 3,
- 5, 3, 5, 2, 1, 3, 5, 5, 0, 1,
- 3, 5, 3, 3, 1, 1, 1, 1, 2, 2,
+ 1, 3, 6, 5, 7, 4, 6, 2, 1, 1,
+ 1, 3, 5, 3, 5, 2, 1, 3, 5, 5,
+ 0, 1, 3, 3, 1, 1, 1, 1, 2, 2,
1, 1, 1, 1, 4, 2, 1, 1, 1, 1,
- 1, 1, 1, 2, 2, 2, 2, 2, 4, 5,
- 3, 1, 1, 1, 4, 4, 4, 6, 9, 9,
- 3, 3, 5, 8, 1, 6, 5, 7, 0, 2,
- 2, 1, 1, 1, 1, 1, 2, 2, 2, 3,
- 1, 2, 3, 4, 1, 3, 3, 3, 3, 3,
- 4, 4, 3, 3, 3
+ 1, 1, 1, 2, 2, 2, 2, 4, 5, 3,
+ 1, 1, 1, 4, 4, 4, 6, 9, 9, 3,
+ 3, 5, 8, 1, 6, 5, 7, 0, 2, 2,
+ 1, 1, 1, 1, 1, 2, 2, 2, 3, 1,
+ 2, 3, 4, 1, 3, 3, 3, 3, 3, 4,
+ 4, 3, 3, 3
};
/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
{
2, 3, 1, 0, 0, 31, 0, 0, 0, 0,
0, 0, 31, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 58, 0, 0, 0, 7, 4, 0, 9,
- 32, 12, 0, 0, 114, 76, 78, 81, 77, 79,
- 82, 80, 108, 115, 0, 0, 0, 13, 38, 64,
- 65, 91, 92, 104, 93, 0, 14, 72, 36, 73,
- 15, 0, 16, 0, 0, 108, 0, 20, 46, 66,
- 70, 71, 67, 93, 18, 0, 32, 47, 48, 21,
- 108, 0, 0, 17, 40, 0, 0, 19, 0, 28,
- 0, 29, 0, 22, 0, 23, 0, 24, 54, 25,
- 0, 26, 0, 27, 59, 30, 0, 5, 0, 0,
- 8, 117, 116, 0, 0, 0, 0, 37, 0, 0,
- 124, 0, 118, 0, 0, 0, 87, 86, 0, 85,
- 84, 35, 0, 0, 68, 69, 75, 45, 0, 0,
- 75, 39, 0, 0, 0, 0, 0, 0, 0, 53,
- 0, 0, 0, 0, 10, 11, 108, 109, 110, 0,
- 0, 100, 101, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 119, 0, 0, 0, 0, 90, 0,
- 0, 33, 34, 0, 0, 41, 0, 43, 0, 60,
- 0, 62, 49, 51, 55, 0, 0, 63, 6, 0,
- 113, 111, 112, 0, 0, 0, 134, 133, 132, 0,
- 0, 125, 126, 127, 128, 129, 0, 0, 94, 96,
- 95, 0, 88, 74, 0, 0, 120, 83, 0, 0,
- 0, 0, 0, 0, 0, 106, 102, 0, 130, 131,
- 0, 0, 0, 89, 42, 121, 0, 44, 61, 50,
- 52, 56, 57, 0, 0, 105, 97, 0, 0, 0,
- 122, 107, 0, 0, 0, 123, 103, 0, 0, 98,
- 99
+ 0, 0, 60, 0, 0, 0, 7, 4, 0, 18,
+ 19, 28, 9, 32, 12, 0, 0, 113, 76, 78,
+ 81, 77, 79, 82, 80, 107, 114, 0, 0, 0,
+ 13, 38, 64, 65, 90, 91, 103, 92, 0, 14,
+ 72, 36, 73, 15, 0, 16, 0, 0, 107, 0,
+ 20, 48, 66, 70, 71, 67, 92, 0, 32, 49,
+ 50, 21, 107, 0, 0, 17, 40, 0, 0, 0,
+ 0, 29, 0, 22, 0, 23, 0, 24, 56, 25,
+ 0, 26, 0, 27, 61, 30, 0, 5, 0, 0,
+ 8, 116, 115, 0, 0, 0, 0, 37, 0, 0,
+ 123, 0, 117, 0, 0, 0, 86, 85, 0, 84,
+ 83, 35, 0, 0, 68, 69, 75, 47, 0, 0,
+ 75, 39, 0, 0, 0, 0, 0, 0, 0, 55,
+ 0, 0, 0, 0, 10, 11, 107, 108, 109, 0,
+ 0, 99, 100, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 118, 0, 0, 0, 0, 89, 0,
+ 0, 33, 34, 0, 0, 41, 0, 0, 45, 0,
+ 62, 51, 53, 57, 0, 0, 63, 6, 0, 112,
+ 110, 111, 0, 0, 0, 133, 132, 131, 0, 0,
+ 124, 125, 126, 127, 128, 0, 0, 93, 95, 94,
+ 0, 87, 74, 0, 0, 119, 43, 0, 0, 0,
+ 0, 0, 0, 0, 105, 101, 0, 129, 130, 0,
+ 0, 0, 88, 42, 120, 0, 0, 46, 52, 54,
+ 58, 59, 0, 0, 104, 96, 0, 0, 0, 121,
+ 44, 106, 0, 0, 0, 122, 102, 0, 0, 97,
+ 98
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int16 yydefgoto[] =
{
- -1, 1, 3, 27, 153, 28, 31, 60, 62, 56,
- 47, 83, 74, 87, 67, 79, 93, 95, 97, 99,
- 101, 103, 89, 91, 105, 57, 68, 58, 69, 49,
- 187, 59, 50, 51, 52, 53, 116, 203, 54, 227,
- 121
+ -1, 1, 3, 27, 153, 28, 34, 63, 65, 59,
+ 50, 85, 29, 30, 31, 70, 81, 93, 95, 97,
+ 99, 101, 103, 91, 105, 60, 71, 61, 72, 52,
+ 62, 53, 54, 55, 56, 116, 202, 57, 226, 121
};
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
-#define YYPACT_NINF -89
+#define YYPACT_NINF -87
static const yytype_int16 yypact[] =
{
- -89, 18, -89, 163, -5, -13, 219, 253, 253, 335,
- 194, 16, 274, 369, 418, 418, 253, 253, 253, 253,
- 240, 0, 0, 253, -17, 19, -89, -89, 24, -89,
- -89, -89, 479, 479, -89, -89, -89, -89, -89, -89,
- -89, -89, 111, -89, 335, 397, 479, -89, -89, -89,
- -89, -89, -89, 33, 51, 390, -89, -89, 65, -89,
- -89, 72, -89, 73, 356, 111, 314, -89, -89, -89,
- -89, -89, -89, 74, -89, 30, 335, -89, -89, -89,
- 70, 422, 479, -89, -89, 82, 86, -89, 88, -89,
- 89, -89, 90, -89, 91, -89, 92, -89, 101, -89,
- 105, -89, 114, -89, -89, -89, 116, -89, 479, 479,
- -89, -89, -89, 118, 479, 479, 120, -89, 5, 115,
- -89, 83, -89, 133, -12, 404, -89, -89, 439, -89,
- -89, -89, 335, 253, -89, -89, 120, -89, 9, 479,
- -89, -89, 422, 141, 119, 452, 253, 335, 335, 335,
- 335, 335, 253, 163, 327, 327, 70, -89, -89, 4,
- 479, 143, -89, 479, 479, 479, 190, 191, 479, 479,
- 479, 479, 479, -89, 187, 6, 148, 152, -89, 470,
- 156, -89, -89, 158, 162, -89, 8, -89, 164, -89,
- 166, -89, 170, 171, -89, 169, 172, -89, -89, 173,
- -89, -89, -89, 161, 176, 199, 102, 530, 537, 479,
- 479, 39, 39, -89, -89, -89, 479, 479, 185, -89,
- -89, 189, -89, -89, 0, 208, 234, -89, 193, 0,
- 211, 212, 479, 240, 217, -89, -89, 255, 55, 55,
- 214, 215, 59, -89, -89, 260, 241, -89, -89, -89,
- -89, -89, -89, 222, 479, -89, -89, 262, 276, 256,
- -89, -89, 242, 479, 479, -89, -89, 243, 246, -89,
- -89
+ -87, 24, -87, 211, 20, -5, 236, 256, 256, 330,
+ 156, 25, 290, 55, 364, 364, 256, 256, 256, 256,
+ 145, 29, 29, 256, 17, 46, -87, -87, 26, -87,
+ -87, -87, -87, -87, -87, 451, 451, -87, -87, -87,
+ -87, -87, -87, -87, -87, 27, -87, 330, 270, 451,
+ -87, -87, -87, -87, -87, -87, 39, 44, 48, -87,
+ -87, 65, -87, -87, 66, -87, 68, 350, 27, 310,
+ -87, -87, -87, -87, -87, -87, 71, 110, 330, -87,
+ -87, -87, 23, 384, 451, -87, -87, 75, 72, 77,
+ 82, -87, 85, -87, 87, -87, 88, -87, 89, -87,
+ 90, -87, 91, -87, -87, -87, 92, -87, 451, 451,
+ -87, -87, -87, 120, 451, 451, 98, -87, 7, 113,
+ -87, 168, -87, 115, 5, 391, -87, -87, 398, -87,
+ -87, -87, 330, 256, -87, -87, 98, -87, 3, 451,
+ -87, -87, 384, 122, 416, 426, 256, 330, 330, 330,
+ 330, 330, 256, 211, 504, 504, 23, -87, -87, 76,
+ 451, 117, -87, 451, 451, 451, 162, 180, 451, 451,
+ 451, 451, 451, -87, 181, 8, 136, 148, -87, 433,
+ 150, -87, -87, 154, 159, -87, 12, 163, -87, 165,
+ -87, 169, 170, -87, 204, 206, -87, -87, 160, -87,
+ -87, -87, 205, 207, 182, 485, 512, 240, 451, 451,
+ 102, 102, -87, -87, -87, 451, 451, 209, -87, -87,
+ 212, -87, -87, 29, 231, 258, -87, 217, 29, 233,
+ 244, 451, 145, 249, -87, -87, 261, 42, 42, 232,
+ 250, -22, -87, -87, 276, 273, 12, -87, -87, -87,
+ -87, -87, 252, 451, -87, -87, 280, 300, 281, -87,
+ -87, -87, 262, 451, 451, -87, -87, 267, 278, -87,
+ -87
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int16 yypgoto[] =
{
- -89, -89, -89, 134, -89, -89, 289, -89, -89, -89,
- 290, -89, -89, -89, -89, -89, -89, -89, -89, -89,
- -89, -89, -89, -89, -89, -2, 237, 11, -11, -9,
- 76, -8, 87, -4, 2, -3, -56, -89, -10, -89,
- -88
+ -87, -87, -87, 171, -87, -87, 303, -87, -87, -87,
+ 321, -87, -87, -87, -87, -87, -87, -87, -87, -87,
+ -87, -87, -87, -87, -87, -2, 243, 11, -11, -9,
+ -8, 74, -1, 2, -3, -62, -87, -10, 94, -86
};
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
#define YYTABLE_NINF -1
static const yytype_uint16 yytable[] =
{
- 73, 70, 84, 86, 48, 85, 71, 63, 75, 136,
- 48, 100, 72, 102, 104, 160, 217, 225, 2, 61,
- 154, 155, 111, 112, 140, 175, 176, 92, 94, 96,
- 98, 107, 177, 108, 106, 120, 122, 200, 30, 201,
- 226, 139, 117, 183, 29, 130, 175, 176, 202, 170,
- 171, 172, 129, 177, 55, 134, 73, 70, 161, 218,
- 135, 42, 71, 168, 169, 170, 171, 172, 72, 109,
- 141, 86, 120, 110, 117, 206, 207, 208, 114, 115,
- 211, 212, 213, 214, 215, 123, 163, 164, 165, 166,
- 167, 168, 169, 170, 171, 172, 257, 258, 120, 120,
- 199, 88, 90, 124, 157, 158, 164, 165, 166, 167,
- 168, 169, 170, 171, 172, 112, 131, 113, 120, 114,
- 115, 238, 239, 132, 133, 156, 138, 32, 33, 184,
- 181, 185, 86, 142, 188, 190, 173, 189, 143, 144,
- 145, 146, 147, 148, 182, 192, 193, 194, 195, 196,
- 204, 34, 149, 120, 120, 120, 150, 191, 120, 120,
- 120, 120, 120, 197, 4, 151, 43, 152, 162, 112,
- 174, 82, 159, 186, 46, 183, 5, 6, 7, 8,
- 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
- 19, 20, 21, 22, 23, 205, 209, 216, 210, 120,
- 120, 219, 32, 33, 64, 220, 240, 241, 24, 222,
- 25, 223, 26, 224, 235, 228, 244, 229, 230, 231,
- 232, 248, 251, 233, 252, 234, 34, 32, 33, 236,
- 35, 36, 37, 38, 39, 40, 237, 242, 41, 65,
- 245, 43, 243, 246, 262, 66, 45, 186, 249, 46,
- 250, 34, 253, 267, 268, 35, 36, 37, 38, 39,
- 40, 32, 33, 41, 42, 254, 43, 255, 256, 259,
- 44, 45, 263, 260, 46, 261, 35, 36, 37, 38,
- 39, 40, 32, 33, 41, 34, 264, 198, 265, 35,
- 36, 37, 38, 39, 40, 266, 269, 41, 42, 270,
- 43, 77, 78, 137, 247, 45, 34, 55, 46, 0,
- 35, 36, 37, 38, 39, 40, 0, 0, 41, 42,
- 0, 43, 32, 33, 64, 76, 45, 0, 0, 46,
- 163, 164, 165, 166, 167, 168, 169, 170, 171, 172,
- 0, 0, 0, 32, 33, 0, 34, 0, 0, 0,
- 35, 36, 37, 38, 39, 40, 0, 0, 41, 65,
- 0, 43, 0, 0, 32, 33, 45, 34, 0, 46,
- 0, 35, 36, 37, 38, 39, 40, 32, 33, 41,
- 42, 0, 43, 0, 0, 0, 0, 45, 34, 0,
- 46, 0, 35, 36, 37, 38, 39, 40, 32, 125,
- 41, 34, 0, 43, 0, 32, 33, 0, 45, 0,
- 0, 46, 32, 33, 80, 0, 43, 0, 0, 0,
- 81, 82, 34, 55, 46, 0, 32, 33, 0, 34,
- 32, 33, 126, 127, 118, 42, 34, 43, 0, 0,
- 0, 119, 128, 0, 43, 46, 178, 32, 179, 82,
- 34, 43, 46, 0, 34, 0, 82, 0, 0, 46,
- 32, 33, 0, 42, 0, 43, 0, 80, 0, 43,
- 45, 34, 0, 46, 82, 0, 0, 46, 32, 33,
- 0, 180, 0, 0, 34, 0, 43, 32, 33, 0,
- 0, 82, 0, 0, 46, 0, 0, 0, 0, 43,
- 0, 0, 34, 0, 82, 0, 55, 46, 0, 0,
- 0, 34, 221, 0, 0, 0, 0, 43, 0, 0,
- 0, 0, 82, 0, 0, 46, 43, 0, 0, 0,
- 0, 82, 0, 0, 46, 165, 166, 167, 168, 169,
- 170, 171, 172, 166, 167, 168, 169, 170, 171, 172
+ 76, 73, 86, 88, 51, 87, 136, 66, 77, 74,
+ 51, 100, 75, 102, 104, 256, 257, 160, 216, 64,
+ 140, 224, 154, 155, 2, 111, 112, 92, 94, 96,
+ 98, 114, 115, 113, 106, 114, 115, 183, 120, 122,
+ 175, 176, 175, 176, 225, 117, 33, 177, 130, 177,
+ 168, 169, 170, 171, 172, 129, 35, 125, 134, 76,
+ 73, 161, 217, 35, 36, 107, 135, 108, 74, 32,
+ 45, 75, 141, 88, 120, 110, 117, 205, 206, 207,
+ 37, 58, 210, 211, 212, 213, 214, 37, 89, 90,
+ 126, 127, 123, 45, 198, 46, 109, 124, 120, 120,
+ 82, 128, 46, 49, 157, 158, 83, 58, 84, 199,
+ 49, 200, 170, 171, 172, 112, 131, 132, 120, 133,
+ 201, 139, 237, 238, 138, 143, 142, 156, 144, 184,
+ 181, 185, 88, 145, 187, 189, 146, 188, 147, 148,
+ 149, 150, 151, 152, 182, 191, 192, 193, 194, 195,
+ 203, 159, 174, 120, 120, 120, 183, 190, 120, 120,
+ 120, 120, 120, 196, 35, 36, 67, 162, 208, 112,
+ 204, 163, 164, 165, 166, 167, 168, 169, 170, 171,
+ 172, 38, 39, 40, 41, 42, 43, 209, 37, 44,
+ 218, 215, 38, 39, 40, 41, 42, 43, 120, 120,
+ 44, 68, 219, 46, 221, 239, 240, 69, 222, 48,
+ 223, 49, 4, 233, 227, 243, 228, 229, 230, 236,
+ 247, 250, 173, 251, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 262, 35, 36, 166, 167, 168, 169,
+ 170, 171, 172, 267, 268, 231, 24, 232, 25, 234,
+ 26, 235, 241, 244, 35, 36, 242, 245, 37, 246,
+ 248, 253, 38, 39, 40, 41, 42, 43, 35, 36,
+ 44, 45, 249, 46, 252, 258, 254, 47, 37, 48,
+ 263, 49, 38, 39, 40, 41, 42, 43, 35, 36,
+ 44, 45, 37, 46, 255, 259, 261, 118, 58, 48,
+ 264, 49, 137, 265, 119, 79, 266, 46, 35, 36,
+ 67, 269, 37, 84, 197, 49, 38, 39, 40, 41,
+ 42, 43, 270, 80, 44, 45, 0, 46, 35, 36,
+ 260, 78, 37, 48, 0, 49, 38, 39, 40, 41,
+ 42, 43, 0, 0, 44, 68, 0, 46, 35, 36,
+ 0, 0, 37, 48, 0, 49, 38, 39, 40, 41,
+ 42, 43, 35, 36, 44, 45, 0, 46, 0, 0,
+ 0, 0, 37, 48, 0, 49, 38, 39, 40, 41,
+ 42, 43, 35, 36, 44, 0, 37, 46, 0, 35,
+ 36, 0, 0, 48, 0, 49, 35, 179, 0, 45,
+ 0, 46, 0, 0, 0, 0, 37, 48, 0, 49,
+ 0, 0, 0, 37, 35, 36, 0, 0, 0, 82,
+ 37, 46, 0, 178, 35, 36, 0, 84, 46, 49,
+ 180, 35, 36, 0, 84, 46, 49, 0, 37, 0,
+ 0, 84, 0, 49, 0, 0, 0, 0, 37, 35,
+ 36, 0, 0, 46, 0, 37, 0, 0, 186, 84,
+ 0, 49, 0, 46, 0, 220, 0, 0, 58, 84,
+ 46, 49, 0, 37, 0, 0, 84, 0, 49, 164,
+ 165, 166, 167, 168, 169, 170, 171, 172, 46, 0,
+ 0, 0, 0, 0, 84, 0, 49, 163, 164, 165,
+ 166, 167, 168, 169, 170, 171, 172, 165, 166, 167,
+ 168, 169, 170, 171, 172
};
static const yytype_int16 yycheck[] =
{
- 10, 10, 13, 13, 6, 13, 10, 9, 11, 65,
- 12, 20, 10, 21, 22, 10, 10, 9, 0, 8,
- 108, 109, 32, 33, 80, 37, 38, 16, 17, 18,
- 19, 48, 44, 50, 23, 45, 46, 33, 51, 35,
- 32, 11, 44, 34, 49, 55, 37, 38, 44, 10,
- 11, 12, 55, 44, 54, 64, 66, 66, 53, 53,
- 64, 45, 66, 8, 9, 10, 11, 12, 66, 50,
- 81, 81, 82, 49, 76, 163, 164, 165, 8, 9,
- 168, 169, 170, 171, 172, 52, 3, 4, 5, 6,
- 7, 8, 9, 10, 11, 12, 37, 38, 108, 109,
- 156, 14, 15, 52, 114, 115, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 125, 51, 6, 128, 8,
- 9, 209, 210, 51, 51, 7, 52, 8, 9, 139,
- 132, 142, 142, 51, 144, 145, 53, 145, 52, 51,
+ 10, 10, 13, 13, 6, 13, 68, 9, 11, 10,
+ 12, 20, 10, 21, 22, 37, 38, 10, 10, 8,
+ 82, 9, 108, 109, 0, 35, 36, 16, 17, 18,
+ 19, 8, 9, 6, 23, 8, 9, 34, 48, 49,
+ 37, 38, 37, 38, 32, 47, 51, 44, 58, 44,
+ 8, 9, 10, 11, 12, 58, 8, 9, 67, 69,
+ 69, 54, 54, 8, 9, 48, 67, 50, 69, 49,
+ 45, 69, 83, 83, 84, 49, 78, 163, 164, 165,
+ 32, 52, 168, 169, 170, 171, 172, 32, 14, 15,
+ 42, 43, 53, 45, 156, 47, 50, 53, 108, 109,
+ 45, 53, 47, 55, 114, 115, 51, 52, 53, 33,
+ 55, 35, 10, 11, 12, 125, 51, 51, 128, 51,
+ 44, 11, 208, 209, 53, 53, 51, 7, 51, 139,
+ 132, 142, 142, 51, 144, 145, 51, 145, 51, 51,
51, 51, 51, 51, 133, 147, 148, 149, 150, 151,
- 160, 32, 51, 163, 164, 165, 51, 146, 168, 169,
- 170, 171, 172, 152, 1, 51, 47, 51, 53, 179,
- 37, 52, 52, 54, 55, 34, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
- 27, 28, 29, 30, 31, 52, 6, 10, 7, 209,
- 210, 53, 8, 9, 10, 53, 216, 217, 45, 53,
- 47, 53, 49, 51, 53, 51, 224, 51, 48, 48,
- 51, 229, 232, 51, 233, 52, 32, 8, 9, 53,
- 36, 37, 38, 39, 40, 41, 37, 52, 44, 45,
- 32, 47, 53, 9, 254, 51, 52, 54, 37, 55,
- 38, 32, 35, 263, 264, 36, 37, 38, 39, 40,
- 41, 8, 9, 44, 45, 10, 47, 53, 53, 9,
- 51, 52, 10, 32, 55, 53, 36, 37, 38, 39,
- 40, 41, 8, 9, 44, 32, 10, 153, 32, 36,
- 37, 38, 39, 40, 41, 53, 53, 44, 45, 53,
- 47, 12, 12, 66, 228, 52, 32, 54, 55, -1,
- 36, 37, 38, 39, 40, 41, -1, -1, 44, 45,
- -1, 47, 8, 9, 10, 51, 52, -1, -1, 55,
- 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
- -1, -1, -1, 8, 9, -1, 32, -1, -1, -1,
- 36, 37, 38, 39, 40, 41, -1, -1, 44, 45,
- -1, 47, -1, -1, 8, 9, 52, 32, -1, 55,
- -1, 36, 37, 38, 39, 40, 41, 8, 9, 44,
- 45, -1, 47, -1, -1, -1, -1, 52, 32, -1,
- 55, -1, 36, 37, 38, 39, 40, 41, 8, 9,
- 44, 32, -1, 47, -1, 8, 9, -1, 52, -1,
- -1, 55, 8, 9, 45, -1, 47, -1, -1, -1,
- 51, 52, 32, 54, 55, -1, 8, 9, -1, 32,
- 8, 9, 42, 43, 37, 45, 32, 47, -1, -1,
- -1, 44, 52, -1, 47, 55, 42, 8, 9, 52,
- 32, 47, 55, -1, 32, -1, 52, -1, -1, 55,
- 8, 9, -1, 45, -1, 47, -1, 45, -1, 47,
- 52, 32, -1, 55, 52, -1, -1, 55, 8, 9,
- -1, 42, -1, -1, 32, -1, 47, 8, 9, -1,
- -1, 52, -1, -1, 55, -1, -1, -1, -1, 47,
- -1, -1, 32, -1, 52, -1, 54, 55, -1, -1,
- -1, 32, 42, -1, -1, -1, -1, 47, -1, -1,
- -1, -1, 52, -1, -1, 55, 47, -1, -1, -1,
- -1, 52, -1, -1, 55, 5, 6, 7, 8, 9,
- 10, 11, 12, 6, 7, 8, 9, 10, 11, 12
+ 160, 53, 37, 163, 164, 165, 34, 146, 168, 169,
+ 170, 171, 172, 152, 8, 9, 10, 54, 6, 179,
+ 53, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 36, 37, 38, 39, 40, 41, 7, 32, 44,
+ 54, 10, 36, 37, 38, 39, 40, 41, 208, 209,
+ 44, 45, 54, 47, 54, 215, 216, 51, 54, 53,
+ 51, 55, 1, 53, 51, 223, 51, 48, 48, 37,
+ 228, 231, 54, 232, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 253, 8, 9, 6, 7, 8, 9,
+ 10, 11, 12, 263, 264, 51, 45, 51, 47, 54,
+ 49, 54, 53, 32, 8, 9, 54, 9, 32, 52,
+ 37, 10, 36, 37, 38, 39, 40, 41, 8, 9,
+ 44, 45, 38, 47, 35, 9, 54, 51, 32, 53,
+ 10, 55, 36, 37, 38, 39, 40, 41, 8, 9,
+ 44, 45, 32, 47, 54, 32, 54, 37, 52, 53,
+ 10, 55, 69, 32, 44, 12, 54, 47, 8, 9,
+ 10, 54, 32, 53, 153, 55, 36, 37, 38, 39,
+ 40, 41, 54, 12, 44, 45, -1, 47, 8, 9,
+ 246, 51, 32, 53, -1, 55, 36, 37, 38, 39,
+ 40, 41, -1, -1, 44, 45, -1, 47, 8, 9,
+ -1, -1, 32, 53, -1, 55, 36, 37, 38, 39,
+ 40, 41, 8, 9, 44, 45, -1, 47, -1, -1,
+ -1, -1, 32, 53, -1, 55, 36, 37, 38, 39,
+ 40, 41, 8, 9, 44, -1, 32, 47, -1, 8,
+ 9, -1, -1, 53, -1, 55, 8, 9, -1, 45,
+ -1, 47, -1, -1, -1, -1, 32, 53, -1, 55,
+ -1, -1, -1, 32, 8, 9, -1, -1, -1, 45,
+ 32, 47, -1, 42, 8, 9, -1, 53, 47, 55,
+ 42, 8, 9, -1, 53, 47, 55, -1, 32, -1,
+ -1, 53, -1, 55, -1, -1, -1, -1, 32, 8,
+ 9, -1, -1, 47, -1, 32, -1, -1, 52, 53,
+ -1, 55, -1, 47, -1, 42, -1, -1, 52, 53,
+ 47, 55, -1, 32, -1, -1, 53, -1, 55, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 47, -1,
+ -1, -1, -1, -1, 53, -1, 55, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 5, 6, 7,
+ 8, 9, 10, 11, 12
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
{
0, 57, 0, 58, 1, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
- 28, 29, 30, 31, 45, 47, 49, 59, 61, 49,
- 51, 62, 8, 9, 32, 36, 37, 38, 39, 40,
- 41, 44, 45, 47, 51, 52, 55, 66, 81, 85,
- 88, 89, 90, 91, 94, 54, 65, 81, 83, 87,
- 63, 83, 64, 81, 10, 45, 51, 70, 82, 84,
- 85, 89, 90, 94, 68, 91, 51, 62, 66, 71,
- 45, 51, 52, 67, 84, 87, 94, 69, 88, 78,
- 88, 79, 83, 72, 83, 73, 83, 74, 83, 75,
- 85, 76, 87, 77, 87, 80, 83, 48, 50, 50,
- 49, 94, 94, 6, 8, 9, 92, 81, 37, 44,
- 94, 96, 94, 52, 52, 9, 42, 43, 52, 91,
- 94, 51, 51, 51, 85, 89, 92, 82, 52, 11,
- 92, 84, 51, 52, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 60, 96, 96, 7, 94, 94, 52,
- 10, 53, 53, 3, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 53, 37, 37, 38, 44, 42, 9,
- 42, 81, 83, 34, 94, 84, 54, 86, 94, 87,
- 94, 83, 81, 81, 81, 81, 81, 83, 59, 92,
- 33, 35, 44, 93, 94, 52, 96, 96, 96, 6,
- 7, 96, 96, 96, 96, 96, 10, 10, 53, 53,
- 53, 42, 53, 53, 51, 9, 32, 95, 51, 51,
- 48, 48, 51, 51, 52, 53, 53, 37, 96, 96,
- 94, 94, 52, 53, 87, 32, 9, 86, 87, 37,
- 38, 94, 85, 35, 10, 53, 53, 37, 38, 9,
- 32, 53, 94, 10, 10, 32, 53, 94, 94, 53,
- 53
+ 28, 29, 30, 31, 45, 47, 49, 59, 61, 68,
+ 69, 70, 49, 51, 62, 8, 9, 32, 36, 37,
+ 38, 39, 40, 41, 44, 45, 47, 51, 53, 55,
+ 66, 81, 85, 87, 88, 89, 90, 93, 52, 65,
+ 81, 83, 86, 63, 83, 64, 81, 10, 45, 51,
+ 71, 82, 84, 85, 88, 89, 93, 90, 51, 62,
+ 66, 72, 45, 51, 53, 67, 84, 86, 93, 87,
+ 87, 79, 83, 73, 83, 74, 83, 75, 83, 76,
+ 85, 77, 86, 78, 86, 80, 83, 48, 50, 50,
+ 49, 93, 93, 6, 8, 9, 91, 81, 37, 44,
+ 93, 95, 93, 53, 53, 9, 42, 43, 53, 90,
+ 93, 51, 51, 51, 85, 88, 91, 82, 53, 11,
+ 91, 84, 51, 53, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 60, 95, 95, 7, 93, 93, 53,
+ 10, 54, 54, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 54, 37, 37, 38, 44, 42, 9,
+ 42, 81, 83, 34, 93, 84, 52, 93, 86, 93,
+ 83, 81, 81, 81, 81, 81, 83, 59, 91, 33,
+ 35, 44, 92, 93, 53, 95, 95, 95, 6, 7,
+ 95, 95, 95, 95, 95, 10, 10, 54, 54, 54,
+ 42, 54, 54, 51, 9, 32, 94, 51, 51, 48,
+ 48, 51, 51, 53, 54, 54, 37, 95, 95, 93,
+ 93, 53, 54, 86, 32, 9, 52, 86, 37, 38,
+ 93, 85, 35, 10, 54, 54, 37, 38, 9, 32,
+ 94, 54, 93, 10, 10, 32, 54, 93, 93, 54,
+ 54
};
#define yyerrok (yyerrstatus = 0)
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
break;
- case 18:
-#line 105 "a.y"
- { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
- break;
-
- case 19:
-#line 106 "a.y"
- { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
- break;
-
case 20:
#line 107 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
break;
- case 28:
-#line 115 "a.y"
- { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
- break;
-
case 29:
#line 116 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
case 42:
#line 187 "a.y"
{
- (yyval.addr2).from = (yyvsp[(1) - (5)].addr);
- (yyval.addr2).from.scale = (yyvsp[(3) - (5)].lval);
- (yyval.addr2).to = (yyvsp[(5) - (5)].addr);
+ Addr2 a;
+ a.from = (yyvsp[(2) - (6)].addr);
+ a.to = (yyvsp[(6) - (6)].addr);
+ outcode(ADATA, &a);
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = (yyvsp[(4) - (6)].lval);
+ }
}
break;
case 43:
-#line 195 "a.y"
+#line 200 "a.y"
{
- settext((yyvsp[(1) - (3)].addr).sym);
- (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
- (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
+ Addr2 a;
+ settext((yyvsp[(2) - (5)].addr).sym);
+ a.from = (yyvsp[(2) - (5)].addr);
+ a.to = (yyvsp[(5) - (5)].addr);
+ outcode(ATEXT, &a);
}
break;
case 44:
-#line 201 "a.y"
- {
- settext((yyvsp[(1) - (5)].addr).sym);
- (yyval.addr2).from = (yyvsp[(1) - (5)].addr);
- (yyval.addr2).from.scale = (yyvsp[(3) - (5)].lval);
- (yyval.addr2).to = (yyvsp[(5) - (5)].addr);
+#line 208 "a.y"
+ {
+ Addr2 a;
+ settext((yyvsp[(2) - (7)].addr).sym);
+ a.from = (yyvsp[(2) - (7)].addr);
+ a.to = (yyvsp[(7) - (7)].addr);
+ outcode(ATEXT, &a);
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = (yyvsp[(4) - (7)].lval);
+ }
}
break;
case 45:
-#line 210 "a.y"
+#line 222 "a.y"
+ {
+ Addr2 a;
+ settext((yyvsp[(2) - (4)].addr).sym);
+ a.from = (yyvsp[(2) - (4)].addr);
+ a.to = (yyvsp[(4) - (4)].addr);
+ outcode(AGLOBL, &a);
+ }
+ break;
+
+ case 46:
+#line 230 "a.y"
+ {
+ Addr2 a;
+ settext((yyvsp[(2) - (6)].addr).sym);
+ a.from = (yyvsp[(2) - (6)].addr);
+ a.to = (yyvsp[(6) - (6)].addr);
+ outcode(AGLOBL, &a);
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = (yyvsp[(4) - (6)].lval);
+ }
+ }
+ break;
+
+ case 47:
+#line 244 "a.y"
{
(yyval.addr2).from = nullgen;
(yyval.addr2).to = (yyvsp[(2) - (2)].addr);
}
break;
- case 46:
-#line 215 "a.y"
+ case 48:
+#line 249 "a.y"
{
(yyval.addr2).from = nullgen;
(yyval.addr2).to = (yyvsp[(1) - (1)].addr);
}
break;
- case 49:
-#line 226 "a.y"
+ case 51:
+#line 260 "a.y"
{
(yyval.addr2).from = (yyvsp[(1) - (3)].addr);
(yyval.addr2).to = (yyvsp[(3) - (3)].addr);
}
break;
- case 50:
-#line 231 "a.y"
+ case 52:
+#line 265 "a.y"
{
(yyval.addr2).from = (yyvsp[(1) - (5)].addr);
(yyval.addr2).to = (yyvsp[(3) - (5)].addr);
- if((yyval.addr2).from.index != D_NONE)
+ if((yyval.addr2).from.index != TYPE_NONE)
yyerror("dp shift with lhs index");
(yyval.addr2).from.index = (yyvsp[(5) - (5)].lval);
}
break;
- case 51:
-#line 241 "a.y"
+ case 53:
+#line 275 "a.y"
{
(yyval.addr2).from = (yyvsp[(1) - (3)].addr);
(yyval.addr2).to = (yyvsp[(3) - (3)].addr);
}
break;
- case 52:
-#line 246 "a.y"
+ case 54:
+#line 280 "a.y"
{
(yyval.addr2).from = (yyvsp[(1) - (5)].addr);
(yyval.addr2).to = (yyvsp[(3) - (5)].addr);
- if((yyval.addr2).to.index != D_NONE)
+ if((yyval.addr2).to.index != TYPE_NONE)
yyerror("dp move with lhs index");
(yyval.addr2).to.index = (yyvsp[(5) - (5)].lval);
}
break;
- case 53:
-#line 256 "a.y"
+ case 55:
+#line 290 "a.y"
{
(yyval.addr2).from = (yyvsp[(1) - (2)].addr);
(yyval.addr2).to = nullgen;
}
break;
- case 54:
-#line 261 "a.y"
+ case 56:
+#line 295 "a.y"
{
(yyval.addr2).from = (yyvsp[(1) - (1)].addr);
(yyval.addr2).to = nullgen;
}
break;
- case 55:
-#line 266 "a.y"
+ case 57:
+#line 300 "a.y"
{
(yyval.addr2).from = (yyvsp[(1) - (3)].addr);
(yyval.addr2).to = (yyvsp[(3) - (3)].addr);
}
break;
- case 56:
-#line 273 "a.y"
+ case 58:
+#line 307 "a.y"
{
(yyval.addr2).from = (yyvsp[(1) - (5)].addr);
(yyval.addr2).to = (yyvsp[(3) - (5)].addr);
}
break;
- case 57:
-#line 281 "a.y"
+ case 59:
+#line 315 "a.y"
{
(yyval.addr2).from = (yyvsp[(3) - (5)].addr);
(yyval.addr2).to = (yyvsp[(5) - (5)].addr);
- if((yyvsp[(1) - (5)].addr).type != D_CONST)
+ if((yyvsp[(1) - (5)].addr).type != TYPE_CONST)
yyerror("illegal constant");
(yyval.addr2).to.offset = (yyvsp[(1) - (5)].addr).offset;
}
break;
- case 58:
-#line 290 "a.y"
+ case 60:
+#line 324 "a.y"
{
(yyval.addr2).from = nullgen;
(yyval.addr2).to = nullgen;
}
break;
- case 59:
-#line 295 "a.y"
+ case 61:
+#line 329 "a.y"
{
(yyval.addr2).from = (yyvsp[(1) - (1)].addr);
(yyval.addr2).to = nullgen;
}
break;
- case 60:
-#line 302 "a.y"
- {
- (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
- (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
- }
- break;
-
- case 61:
-#line 307 "a.y"
- {
- (yyval.addr2).from = (yyvsp[(1) - (5)].addr);
- (yyval.addr2).from.scale = (yyvsp[(3) - (5)].lval);
- (yyval.addr2).to = (yyvsp[(5) - (5)].addr);
- }
- break;
-
case 62:
-#line 315 "a.y"
+#line 336 "a.y"
{
- if((yyvsp[(1) - (3)].addr).type != D_CONST || (yyvsp[(3) - (3)].addr).type != D_CONST)
+ if((yyvsp[(1) - (3)].addr).type != TYPE_CONST || (yyvsp[(3) - (3)].addr).type != TYPE_CONST)
yyerror("arguments to PCDATA must be integer constants");
(yyval.addr2).from = (yyvsp[(1) - (3)].addr);
(yyval.addr2).to = (yyvsp[(3) - (3)].addr);
break;
case 63:
-#line 324 "a.y"
+#line 345 "a.y"
{
- if((yyvsp[(1) - (3)].addr).type != D_CONST)
+ if((yyvsp[(1) - (3)].addr).type != TYPE_CONST)
yyerror("index for FUNCDATA must be integer constant");
- if((yyvsp[(3) - (3)].addr).type != D_EXTERN && (yyvsp[(3) - (3)].addr).type != D_STATIC)
+ if((yyvsp[(3) - (3)].addr).type != TYPE_MEM || ((yyvsp[(3) - (3)].addr).name != NAME_EXTERN && (yyvsp[(3) - (3)].addr).name != NAME_STATIC))
yyerror("value for FUNCDATA must be symbol reference");
(yyval.addr2).from = (yyvsp[(1) - (3)].addr);
(yyval.addr2).to = (yyvsp[(3) - (3)].addr);
break;
case 68:
-#line 341 "a.y"
+#line 362 "a.y"
{
(yyval.addr) = (yyvsp[(2) - (2)].addr);
}
break;
case 69:
-#line 345 "a.y"
+#line 366 "a.y"
{
(yyval.addr) = (yyvsp[(2) - (2)].addr);
}
break;
case 74:
-#line 357 "a.y"
+#line 378 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_BRANCH;
+ (yyval.addr).type = TYPE_BRANCH;
(yyval.addr).offset = (yyvsp[(1) - (4)].lval) + pc;
}
break;
case 75:
-#line 363 "a.y"
+#line 384 "a.y"
{
(yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym));
(yyval.addr) = nullgen;
if(pass == 2 && (yyvsp[(1) - (2)].sym)->type != LLAB)
yyerror("undefined label: %s", (yyvsp[(1) - (2)].sym)->labelname);
- (yyval.addr).type = D_BRANCH;
+ (yyval.addr).type = TYPE_BRANCH;
(yyval.addr).offset = (yyvsp[(1) - (2)].sym)->value + (yyvsp[(2) - (2)].lval);
}
break;
case 76:
-#line 374 "a.y"
+#line 395 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = (yyvsp[(1) - (1)].lval);
+ (yyval.addr).type = TYPE_REG;
+ (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
}
break;
case 77:
-#line 379 "a.y"
+#line 401 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = (yyvsp[(1) - (1)].lval);
+ (yyval.addr).type = TYPE_REG;
+ (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
}
break;
case 78:
-#line 384 "a.y"
+#line 407 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = (yyvsp[(1) - (1)].lval);
+ (yyval.addr).type = TYPE_REG;
+ (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
}
break;
case 79:
-#line 389 "a.y"
+#line 413 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = (yyvsp[(1) - (1)].lval);
+ (yyval.addr).type = TYPE_REG;
+ (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
}
break;
case 80:
-#line 394 "a.y"
+#line 419 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_SP;
+ (yyval.addr).type = TYPE_REG;
+ (yyval.addr).reg = REG_SP;
}
break;
case 81:
-#line 399 "a.y"
+#line 425 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = (yyvsp[(1) - (1)].lval);
+ (yyval.addr).type = TYPE_REG;
+ (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
}
break;
case 82:
-#line 404 "a.y"
+#line 431 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = (yyvsp[(1) - (1)].lval);
+ (yyval.addr).type = TYPE_REG;
+ (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
}
break;
case 83:
-#line 410 "a.y"
+#line 439 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_CONST;
+ (yyval.addr).type = TYPE_CONST;
(yyval.addr).offset = (yyvsp[(2) - (2)].lval);
}
break;
case 84:
-#line 418 "a.y"
- {
- (yyval.addr) = nullgen;
- (yyval.addr).type = D_CONST;
- (yyval.addr).offset = (yyvsp[(2) - (2)].lval);
- }
- break;
-
- case 85:
-#line 424 "a.y"
+#line 445 "a.y"
{
(yyval.addr) = (yyvsp[(2) - (2)].addr);
- (yyval.addr).index = (yyvsp[(2) - (2)].addr).type;
- (yyval.addr).type = D_ADDR;
+ (yyval.addr).type = TYPE_ADDR;
/*
if($2.type == D_AUTO || $2.type == D_PARAM)
yyerror("constant cannot be automatic: %s",
}
break;
- case 86:
-#line 435 "a.y"
+ case 85:
+#line 455 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_SCONST;
+ (yyval.addr).type = TYPE_SCONST;
memcpy((yyval.addr).u.sval, (yyvsp[(2) - (2)].sval), sizeof((yyval.addr).u.sval));
}
break;
- case 87:
-#line 441 "a.y"
+ case 86:
+#line 461 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_FCONST;
+ (yyval.addr).type = TYPE_FCONST;
(yyval.addr).u.dval = (yyvsp[(2) - (2)].dval);
}
break;
- case 88:
-#line 447 "a.y"
+ case 87:
+#line 467 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_FCONST;
+ (yyval.addr).type = TYPE_FCONST;
(yyval.addr).u.dval = (yyvsp[(3) - (4)].dval);
}
break;
- case 89:
-#line 453 "a.y"
+ case 88:
+#line 473 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_FCONST;
+ (yyval.addr).type = TYPE_FCONST;
(yyval.addr).u.dval = -(yyvsp[(4) - (5)].dval);
}
break;
- case 90:
-#line 459 "a.y"
+ case 89:
+#line 479 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_FCONST;
+ (yyval.addr).type = TYPE_FCONST;
(yyval.addr).u.dval = -(yyvsp[(3) - (3)].dval);
}
break;
- case 93:
-#line 471 "a.y"
+ case 92:
+#line 491 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_INDIR+D_NONE;
+ (yyval.addr).type = TYPE_MEM;
(yyval.addr).offset = (yyvsp[(1) - (1)].lval);
}
break;
- case 94:
-#line 477 "a.y"
+ case 93:
+#line 497 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_INDIR+(yyvsp[(3) - (4)].lval);
+ (yyval.addr).type = TYPE_MEM;
+ (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
(yyval.addr).offset = (yyvsp[(1) - (4)].lval);
}
break;
- case 95:
-#line 483 "a.y"
+ case 94:
+#line 504 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_INDIR+D_SP;
+ (yyval.addr).type = TYPE_MEM;
+ (yyval.addr).reg = REG_SP;
(yyval.addr).offset = (yyvsp[(1) - (4)].lval);
}
break;
- case 96:
-#line 489 "a.y"
+ case 95:
+#line 511 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_INDIR+(yyvsp[(3) - (4)].lval);
+ (yyval.addr).type = TYPE_MEM;
+ (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
(yyval.addr).offset = (yyvsp[(1) - (4)].lval);
}
break;
- case 97:
-#line 495 "a.y"
+ case 96:
+#line 518 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_INDIR+D_NONE;
+ (yyval.addr).type = TYPE_MEM;
(yyval.addr).offset = (yyvsp[(1) - (6)].lval);
(yyval.addr).index = (yyvsp[(3) - (6)].lval);
(yyval.addr).scale = (yyvsp[(5) - (6)].lval);
}
break;
- case 98:
-#line 504 "a.y"
+ case 97:
+#line 527 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_INDIR+(yyvsp[(3) - (9)].lval);
+ (yyval.addr).type = TYPE_MEM;
+ (yyval.addr).reg = (yyvsp[(3) - (9)].lval);
(yyval.addr).offset = (yyvsp[(1) - (9)].lval);
(yyval.addr).index = (yyvsp[(6) - (9)].lval);
(yyval.addr).scale = (yyvsp[(8) - (9)].lval);
}
break;
- case 99:
-#line 513 "a.y"
+ case 98:
+#line 537 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_INDIR+(yyvsp[(3) - (9)].lval);
+ (yyval.addr).type = TYPE_MEM;
+ (yyval.addr).reg = (yyvsp[(3) - (9)].lval);
(yyval.addr).offset = (yyvsp[(1) - (9)].lval);
(yyval.addr).index = (yyvsp[(6) - (9)].lval);
(yyval.addr).scale = (yyvsp[(8) - (9)].lval);
}
break;
- case 100:
-#line 522 "a.y"
+ case 99:
+#line 547 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_INDIR+(yyvsp[(2) - (3)].lval);
+ (yyval.addr).type = TYPE_MEM;
+ (yyval.addr).reg = (yyvsp[(2) - (3)].lval);
}
break;
- case 101:
-#line 527 "a.y"
+ case 100:
+#line 553 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_INDIR+D_SP;
+ (yyval.addr).type = TYPE_MEM;
+ (yyval.addr).reg = REG_SP;
}
break;
- case 102:
-#line 532 "a.y"
+ case 101:
+#line 559 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_INDIR+D_NONE;
+ (yyval.addr).type = TYPE_MEM;
(yyval.addr).index = (yyvsp[(2) - (5)].lval);
(yyval.addr).scale = (yyvsp[(4) - (5)].lval);
checkscale((yyval.addr).scale);
}
break;
- case 103:
-#line 540 "a.y"
+ case 102:
+#line 567 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_INDIR+(yyvsp[(2) - (8)].lval);
+ (yyval.addr).type = TYPE_MEM;
+ (yyval.addr).reg = (yyvsp[(2) - (8)].lval);
(yyval.addr).index = (yyvsp[(5) - (8)].lval);
(yyval.addr).scale = (yyvsp[(7) - (8)].lval);
checkscale((yyval.addr).scale);
}
break;
- case 104:
-#line 550 "a.y"
+ case 103:
+#line 578 "a.y"
{
(yyval.addr) = (yyvsp[(1) - (1)].addr);
}
break;
- case 105:
-#line 554 "a.y"
+ case 104:
+#line 582 "a.y"
{
(yyval.addr) = (yyvsp[(1) - (6)].addr);
(yyval.addr).index = (yyvsp[(3) - (6)].lval);
}
break;
- case 106:
-#line 563 "a.y"
+ case 105:
+#line 591 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = (yyvsp[(4) - (5)].lval);
+ (yyval.addr).type = TYPE_MEM;
+ (yyval.addr).name = (yyvsp[(4) - (5)].lval);
(yyval.addr).sym = linklookup(ctxt, (yyvsp[(1) - (5)].sym)->name, 0);
(yyval.addr).offset = (yyvsp[(2) - (5)].lval);
}
break;
- case 107:
-#line 570 "a.y"
+ case 106:
+#line 599 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_STATIC;
+ (yyval.addr).type = TYPE_MEM;
+ (yyval.addr).name = NAME_STATIC;
(yyval.addr).sym = linklookup(ctxt, (yyvsp[(1) - (7)].sym)->name, 1);
(yyval.addr).offset = (yyvsp[(4) - (7)].lval);
}
break;
- case 108:
-#line 578 "a.y"
+ case 107:
+#line 608 "a.y"
{
(yyval.lval) = 0;
}
break;
- case 109:
-#line 582 "a.y"
+ case 108:
+#line 612 "a.y"
{
(yyval.lval) = (yyvsp[(2) - (2)].lval);
}
break;
- case 110:
-#line 586 "a.y"
+ case 109:
+#line 616 "a.y"
{
(yyval.lval) = -(yyvsp[(2) - (2)].lval);
}
break;
- case 112:
-#line 593 "a.y"
+ case 111:
+#line 623 "a.y"
{
- (yyval.lval) = D_AUTO;
+ (yyval.lval) = NAME_AUTO;
}
break;
- case 115:
-#line 601 "a.y"
+ case 114:
+#line 631 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (1)].sym)->value;
}
break;
- case 116:
-#line 605 "a.y"
+ case 115:
+#line 635 "a.y"
{
(yyval.lval) = -(yyvsp[(2) - (2)].lval);
}
break;
- case 117:
-#line 609 "a.y"
+ case 116:
+#line 639 "a.y"
{
(yyval.lval) = (yyvsp[(2) - (2)].lval);
}
break;
- case 118:
-#line 613 "a.y"
+ case 117:
+#line 643 "a.y"
{
(yyval.lval) = ~(yyvsp[(2) - (2)].lval);
}
break;
- case 119:
-#line 617 "a.y"
+ case 118:
+#line 647 "a.y"
{
(yyval.lval) = (yyvsp[(2) - (3)].lval);
}
break;
- case 120:
-#line 623 "a.y"
+ case 119:
+#line 653 "a.y"
{
- (yyval.lval) = ((yyvsp[(1) - (1)].lval) & 0xffffffffLL) +
- ((vlong)ArgsSizeUnknown << 32);
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = TYPE_TEXTSIZE;
+ (yyval.addr).offset = (yyvsp[(1) - (1)].lval);
+ (yyval.addr).u.argsize = ArgsSizeUnknown;
}
break;
- case 121:
-#line 628 "a.y"
+ case 120:
+#line 660 "a.y"
{
- (yyval.lval) = (-(yyvsp[(2) - (2)].lval) & 0xffffffffLL) +
- ((vlong)ArgsSizeUnknown << 32);
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = TYPE_TEXTSIZE;
+ (yyval.addr).offset = -(yyvsp[(2) - (2)].lval);
+ (yyval.addr).u.argsize = ArgsSizeUnknown;
}
break;
- case 122:
-#line 633 "a.y"
+ case 121:
+#line 667 "a.y"
{
- (yyval.lval) = ((yyvsp[(1) - (3)].lval) & 0xffffffffLL) +
- (((yyvsp[(3) - (3)].lval) & 0xffffLL) << 32);
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = TYPE_TEXTSIZE;
+ (yyval.addr).offset = (yyvsp[(1) - (3)].lval);
+ (yyval.addr).u.argsize = (yyvsp[(3) - (3)].lval);
}
break;
- case 123:
-#line 638 "a.y"
+ case 122:
+#line 674 "a.y"
{
- (yyval.lval) = (-(yyvsp[(2) - (4)].lval) & 0xffffffffLL) +
- (((yyvsp[(4) - (4)].lval) & 0xffffLL) << 32);
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = TYPE_TEXTSIZE;
+ (yyval.addr).offset = -(yyvsp[(2) - (4)].lval);
+ (yyval.addr).u.argsize = (yyvsp[(4) - (4)].lval);
}
break;
- case 125:
-#line 646 "a.y"
+ case 124:
+#line 684 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval);
}
break;
- case 126:
-#line 650 "a.y"
+ case 125:
+#line 688 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval);
}
break;
- case 127:
-#line 654 "a.y"
+ case 126:
+#line 692 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval);
}
break;
- case 128:
-#line 658 "a.y"
+ case 127:
+#line 696 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval);
}
break;
- case 129:
-#line 662 "a.y"
+ case 128:
+#line 700 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval);
}
break;
- case 130:
-#line 666 "a.y"
+ case 129:
+#line 704 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval);
}
break;
- case 131:
-#line 670 "a.y"
+ case 130:
+#line 708 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval);
}
break;
- case 132:
-#line 674 "a.y"
+ case 131:
+#line 712 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval);
}
break;
- case 133:
-#line 678 "a.y"
+ case 132:
+#line 716 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval);
}
break;
- case 134:
-#line 682 "a.y"
+ case 133:
+#line 720 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) | (yyvsp[(3) - (3)].lval);
}
/* Line 1267 of yacc.c. */
-#line 2572 "y.tab.c"
+#line 2587 "y.tab.c"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
// nothing to do
} else if(w == 1 || w == 2 || w == 4 || w == 8) {
p1 = gins(ALEAQ, &n2, &n3);
+ p1->from.type = TYPE_MEM;
p1->from.scale = w;
- p1->from.index = p1->from.type;
- p1->from.type = p1->to.type + D_INDIR;
+ p1->from.index = p1->from.reg;
+ p1->from.reg = p1->to.reg;
} else {
ginscon(optoas(OMUL, t), w, &n2);
gins(optoas(OADD, types[tptr]), &n2, &n3);
case OINDREG:
// Increase the refcount of the register so that igen's caller
// has to call regfree.
- if(n->val.u.reg != D_SP)
+ if(n->val.u.reg != REG_SP)
reg[n->val.u.reg]++;
*a = *n;
return;
fp = structfirst(&flist, getoutarg(n->left->type));
memset(a, 0, sizeof *a);
a->op = OINDREG;
- a->val.u.reg = D_SP;
+ a->val.u.reg = REG_SP;
a->addable = 1;
a->xoffset = fp->width;
a->type = n->type;
agenr(n, &nodr, N);
}
- nodreg(&noddi, types[tptr], D_DI);
- nodreg(&nodsi, types[tptr], D_SI);
+ nodreg(&noddi, types[tptr], REG_DI);
+ nodreg(&nodsi, types[tptr], REG_SI);
gmove(&nodl, &noddi);
gmove(&nodr, &nodsi);
regfree(&nodl);
c = w % 8; // bytes
q = w / 8; // quads
- savex(D_CX, &cx, &oldcx, N, types[TINT64]);
+ savex(REG_CX, &cx, &oldcx, N, types[TINT64]);
// if we are copying forward on the stack and
// the src and dst overlap, then reverse direction
// reverse direction
gins(ASTD, N, N); // set direction flag
if(c > 0) {
- gconreg(addptr, w-1, D_SI);
- gconreg(addptr, w-1, D_DI);
+ gconreg(addptr, w-1, REG_SI);
+ gconreg(addptr, w-1, REG_DI);
- gconreg(movptr, c, D_CX);
+ gconreg(movptr, c, REG_CX);
gins(AREP, N, N); // repeat
gins(AMOVSB, N, N); // MOVB *(SI)-,*(DI)-
}
if(q > 0) {
if(c > 0) {
- gconreg(addptr, -7, D_SI);
- gconreg(addptr, -7, D_DI);
+ gconreg(addptr, -7, REG_SI);
+ gconreg(addptr, -7, REG_DI);
} else {
- gconreg(addptr, w-8, D_SI);
- gconreg(addptr, w-8, D_DI);
+ gconreg(addptr, w-8, REG_SI);
+ gconreg(addptr, w-8, REG_DI);
}
- gconreg(movptr, q, D_CX);
+ gconreg(movptr, q, REG_CX);
gins(AREP, N, N); // repeat
gins(AMOVSQ, N, N); // MOVQ *(SI)-,*(DI)-
}
} else {
// normal direction
if(q > 128 || (nacl && q >= 4)) {
- gconreg(movptr, q, D_CX);
+ gconreg(movptr, q, REG_CX);
gins(AREP, N, N); // repeat
gins(AMOVSQ, N, N); // MOVQ *(SI)+,*(DI)+
} else if (q >= 4) {
p = gins(ADUFFCOPY, N, N);
- p->to.type = D_ADDR;
+ p->to.type = TYPE_ADDR;
p->to.sym = linksym(pkglookup("duffcopy", runtimepkg));
// 14 and 128 = magic constants: see ../../runtime/asm_amd64.s
p->to.offset = 14*(128-q);
void
linkarchinit(void)
{
- if(strcmp(getgoarch(), "amd64p32") == 0)
+ if(strcmp(getgoarch(), "amd64p32") == 0) {
thelinkarch = &linkamd64p32;
+ arch.thelinkarch = thelinkarch;
+ thestring = "amd64p32";
+ arch.thestring = "amd64p32";
+ }
}
vlong MAXWIDTH = 1LL<<50;
}
- zprog.link = P;
- zprog.as = AGOK;
- zprog.from.type = D_NONE;
- zprog.from.index = D_NONE;
- zprog.from.scale = 0;
- zprog.to = zprog.from;
-
listinit6();
}
+
+void
+main(int argc, char **argv)
+{
+ arch.thechar = thechar;
+ arch.thestring = thestring;
+ arch.thelinkarch = thelinkarch;
+ arch.typedefs = typedefs;
+ arch.MAXWIDTH = MAXWIDTH;
+ arch.afunclit = afunclit;
+ arch.anyregalloc = anyregalloc;
+ arch.betypeinit = betypeinit;
+ arch.bgen = bgen;
+ arch.cgen = cgen;
+ arch.cgen_asop = cgen_asop;
+ arch.cgen_call = cgen_call;
+ arch.cgen_callinter = cgen_callinter;
+ arch.cgen_ret = cgen_ret;
+ arch.clearfat = clearfat;
+ arch.clearp = clearp;
+ arch.defframe = defframe;
+ arch.dgostringptr = dgostringptr;
+ arch.dgostrlitptr = dgostrlitptr;
+ arch.dsname = dsname;
+ arch.dsymptr = dsymptr;
+ arch.dumpdata = dumpdata;
+ arch.dumpit = dumpit;
+ arch.excise = excise;
+ arch.expandchecks = expandchecks;
+ arch.fixautoused = fixautoused;
+ arch.gclean = gclean;
+ arch.gdata = gdata;
+ arch.gdatacomplex = gdatacomplex;
+ arch.gdatastring = gdatastring;
+ arch.ggloblnod = ggloblnod;
+ arch.ggloblsym = ggloblsym;
+ arch.ginit = ginit;
+ arch.gins = gins;
+ arch.ginscall = ginscall;
+ arch.gjmp = gjmp;
+ arch.gtrack = gtrack;
+ arch.gused = gused;
+ arch.igen = igen;
+ arch.isfat = isfat;
+ arch.linkarchinit = linkarchinit;
+ arch.markautoused = markautoused;
+ arch.naddr = naddr;
+ arch.newplist = newplist;
+ arch.nodarg = nodarg;
+ arch.patch = patch;
+ arch.proginfo = proginfo;
+ arch.regalloc = regalloc;
+ arch.regfree = regfree;
+ arch.regopt = regopt;
+ arch.regtyp = regtyp;
+ arch.sameaddr = sameaddr;
+ arch.smallindir = smallindir;
+ arch.stackaddr = stackaddr;
+ arch.unpatch = unpatch;
+
+ gcmain(argc, argv);
+}
#include "../gc/go.h"
#include "../6l/6.out.h"
-#define TEXTFLAG from.scale
-
EXTERN int32 dynloc;
-EXTERN uchar reg[D_NONE];
+EXTERN uchar reg[MAXREG];
EXTERN int32 pcloc; // instruction counter
EXTERN Strlit emptystring;
-EXTERN Prog zprog;
-EXTERN Node* newproc;
-EXTERN Node* deferproc;
-EXTERN Node* deferreturn;
-EXTERN Node* panicindex;
-EXTERN Node* panicslice;
EXTERN Node* panicdiv;
-EXTERN Node* throwreturn;
extern vlong unmappedzero;
extern int addptr;
extern int cmpptr;
void listinit(void);
void zaddr(Biobuf*, Addr*, int, int);
+
+void afunclit(Addr*, Node*);
+int anyregalloc(void);
+void betypeinit(void);
+void bgen(Node*, int, int, Prog*);
+void cgen(Node*, Node*);
+void cgen_asop(Node*);
+void cgen_call(Node*, int);
+void cgen_callinter(Node*, Node*, int);
+void cgen_ret(Node*);
+void clearfat(Node*);
+void clearp(Prog*);
+void defframe(Prog*);
+int dgostringptr(Sym*, int, char*);
+int dgostrlitptr(Sym*, int, Strlit*);
+int dsname(Sym*, int, char*, int);
+int dsymptr(Sym*, int, Sym*, int);
+void dumpdata(void);
+void dumpit(char*, Flow*, int);
+void excise(Flow*);
+void expandchecks(Prog*);
+void fixautoused(Prog*);
+void gclean(void);
+void gdata(Node*, Node*, int);
+void gdatacomplex(Node*, Mpcplx*);
+void gdatastring(Node*, Strlit*);
+void ggloblnod(Node *nam);
+void ggloblsym(Sym *s, int32 width, int8 flags);
+void ginit(void);
+Prog* gins(int, Node*, Node*);
+void ginscall(Node*, int);
+Prog* gjmp(Prog*);
+void gtrack(Sym*);
+void gused(Node*);
+void igen(Node*, Node*, Node*);
+int isfat(Type*);
+void linkarchinit(void);
+void markautoused(Prog*);
+void naddr(Node*, Addr*, int);
+Plist* newplist(void);
+Node* nodarg(Type*, int);
+void patch(Prog*, Prog*);
+void proginfo(ProgInfo*, Prog*);
+void regalloc(Node*, Type*, Node*);
+void regfree(Node*);
+void regopt(Prog*);
+int regtyp(Addr*);
+int sameaddr(Addr*, Addr*);
+int smallindir(Addr*, Addr*);
+int stackaddr(Addr*);
+Prog* unpatch(Prog*);
+
#include "gg.h"
#include "opt.h"
-static Prog *appendpp(Prog*, int, int, vlong, int, vlong);
+static Prog *appendpp(Prog*, int, int, int, vlong, int, int, vlong);
static Prog *zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *ax);
void
NodeList *l;
Node *n;
- // fill in argument size
- ptxt->to.offset = rnd(curfn->type->argwid, widthptr);
-
- // fill in final stack size
- ptxt->to.offset <<= 32;
+ // fill in argument size, stack size
+ ptxt->to.type = TYPE_TEXTSIZE;
+ ptxt->to.u.argsize = rnd(curfn->type->argwid, widthptr);
frame = rnd(stksize+maxarg, widthreg);
- ptxt->to.offset |= frame;
+ ptxt->to.offset = frame;
// insert code to zero ambiguously live variables
// so that the garbage collector only sees initialized values
if(cnt == 0)
return p;
if(*ax == 0) {
- p = appendpp(p, AMOVQ, D_CONST, 0, D_AX, 0);
+ p = appendpp(p, AMOVQ, TYPE_CONST, 0, 0, TYPE_REG, REG_AX, 0);
*ax = 1;
}
if(cnt % widthreg != 0) {
// should only happen with nacl
if(cnt % widthptr != 0)
fatal("zerorange count not a multiple of widthptr %d", cnt);
- p = appendpp(p, AMOVL, D_AX, 0, D_SP+D_INDIR, frame+lo);
+ p = appendpp(p, AMOVL, TYPE_REG, REG_AX, 0, TYPE_MEM, REG_SP, frame+lo);
lo += widthptr;
cnt -= widthptr;
}
if(cnt <= 4*widthreg) {
for(i = 0; i < cnt; i += widthreg) {
- p = appendpp(p, AMOVQ, D_AX, 0, D_SP+D_INDIR, frame+lo+i);
+ p = appendpp(p, AMOVQ, TYPE_REG, REG_AX, 0, TYPE_MEM, REG_SP, frame+lo+i);
}
} else if(!nacl && (cnt <= 128*widthreg)) {
- p = appendpp(p, leaptr, D_SP+D_INDIR, frame+lo, D_DI, 0);
- p = appendpp(p, ADUFFZERO, D_NONE, 0, D_ADDR, 2*(128-cnt/widthreg));
+ p = appendpp(p, leaptr, TYPE_MEM, REG_SP, frame+lo, TYPE_REG, REG_DI, 0);
+ p = appendpp(p, ADUFFZERO, TYPE_NONE, 0, 0, TYPE_ADDR, 0, 2*(128-cnt/widthreg));
p->to.sym = linksym(pkglookup("duffzero", runtimepkg));
} else {
- p = appendpp(p, AMOVQ, D_CONST, cnt/widthreg, D_CX, 0);
- p = appendpp(p, leaptr, D_SP+D_INDIR, frame+lo, D_DI, 0);
- p = appendpp(p, AREP, D_NONE, 0, D_NONE, 0);
- p = appendpp(p, ASTOSQ, D_NONE, 0, D_NONE, 0);
+ p = appendpp(p, AMOVQ, TYPE_CONST, 0, cnt/widthreg, TYPE_REG, REG_CX, 0);
+ p = appendpp(p, leaptr, TYPE_MEM, REG_SP, frame+lo, TYPE_REG, REG_DI, 0);
+ p = appendpp(p, AREP, TYPE_NONE, 0, 0, TYPE_NONE, 0, 0);
+ p = appendpp(p, ASTOSQ, TYPE_NONE, 0, 0, TYPE_NONE, 0, 0);
}
return p;
}
static Prog*
-appendpp(Prog *p, int as, int ftype, vlong foffset, int ttype, vlong toffset)
+appendpp(Prog *p, int as, int ftype, int freg, vlong foffset, int ttype, int treg, vlong toffset)
{
Prog *q;
q = mal(sizeof(*q));
clearp(q);
q->as = as;
q->lineno = p->lineno;
- q->from.type = ftype;
+ q->from.type = ftype;
+ q->from.reg = freg;
q->from.offset = foffset;
q->to.type = ttype;
+ q->to.reg = treg;
q->to.offset = toffset;
q->link = p->link;
p->link = q;
continue;
if (p->from.node)
- p->from.node->used = 1;
+ ((Node*)(p->from.node))->used = 1;
if (p->to.node)
- p->to.node->used = 1;
+ ((Node*)(p->to.node))->used = 1;
}
}
Prog **lp;
for (lp=&p; (p=*lp) != P; ) {
- if (p->as == ATYPE && p->from.node && p->from.type == D_AUTO && !p->from.node->used) {
+ if (p->as == ATYPE && p->from.node && p->from.name == NAME_AUTO && !((Node*)(p->from.node))->used) {
*lp = p->link;
continue;
}
- if ((p->as == AVARDEF || p->as == AVARKILL) && p->to.node && !p->to.node->used) {
+ if ((p->as == AVARDEF || p->as == AVARKILL) && p->to.node && !((Node*)(p->to.node))->used) {
// Cannot remove VARDEF instruction, because - unlike TYPE handled above -
// VARDEFs are interspersed with other code, and a jump might be using the
// VARDEF as a target. Replace with a no-op instead. A later pass will remove
// the no-ops.
- p->to.type = D_NONE;
- p->to.node = N;
- p->as = ANOP;
+ nopout(p);
continue;
}
- if (p->from.type == D_AUTO && p->from.node)
- p->from.offset += p->from.node->stkdelta;
+ if (p->from.name == NAME_AUTO && p->from.node)
+ p->from.offset += ((Node*)(p->from.node))->stkdelta;
- if (p->to.type == D_AUTO && p->to.node)
- p->to.offset += p->to.node->stkdelta;
+ if (p->to.name == NAME_AUTO && p->to.node)
+ p->to.offset += ((Node*)(p->to.node))->stkdelta;
lp = &p->link;
}
// x86 NOP 0x90 is really XCHG AX, AX; use that description
// because the NOP pseudo-instruction would be removed by
// the linker.
- nodreg(®, types[TINT], D_AX);
+ nodreg(®, types[TINT], REG_AX);
gins(AXCHGL, ®, ®);
}
p = gins(ACALL, N, f);
gins(AUNDEF, N, N);
break;
}
- nodreg(®, types[tptr], D_DX);
- nodreg(&r1, types[tptr], D_BX);
+ nodreg(®, types[tptr], REG_DX);
+ nodreg(&r1, types[tptr], REG_BX);
gmove(f, ®);
reg.op = OINDREG;
gmove(®, &r1);
case 2: // deferred call (defer)
memset(&stk, 0, sizeof(stk));
stk.op = OINDREG;
- stk.val.u.reg = D_SP;
+ stk.val.u.reg = REG_SP;
stk.xoffset = 0;
if(widthptr == 8) {
// FuncVal* at 8(SP)
stk.xoffset = widthptr;
- nodreg(®, types[TINT64], D_AX);
+ nodreg(®, types[TINT64], REG_AX);
gmove(f, ®);
gins(AMOVQ, ®, &stk);
} else {
// FuncVal* at 4(SP)
stk.xoffset = widthptr;
- nodreg(®, types[TINT32], D_AX);
+ nodreg(®, types[TINT32], REG_AX);
gmove(f, ®);
gins(AMOVL, ®, &stk);
}
ginscall(deferproc, 0);
}
if(proc == 2) {
- nodreg(®, types[TINT32], D_AX);
+ nodreg(®, types[TINT32], REG_AX);
gins(ATESTL, ®, ®);
p = gbranch(AJEQ, T, +1);
cgen_ret(N);
// register to hold its address.
igen(i, &nodi, res); // REG = &inter
- nodindreg(&nodsp, types[tptr], D_SP);
- nodsp.xoffset = 0;
+ nodindreg(&nodsp, types[tptr], REG_SP);
+ nodsp.xoffset = 0;
if(proc != 0)
nodsp.xoffset += 2 * widthptr; // leave room for size & fn
nodi.type = types[tptr];
memset(&nod, 0, sizeof(nod));
nod.op = OINDREG;
- nod.val.u.reg = D_SP;
+ nod.val.u.reg = REG_SP;
nod.addable = 1;
nod.xoffset = fp->width;
memset(&nod1, 0, sizeof(nod1));
nod1.op = OINDREG;
- nod1.val.u.reg = D_SP;
+ nod1.val.u.reg = REG_SP;
nod1.addable = 1;
nod1.xoffset = fp->width;
genlist(curfn->exit);
p = gins(ARET, N, N);
if(n != N && n->op == ORETJMP) {
- p->to.type = D_EXTERN;
+ p->to.type = TYPE_MEM;
+ p->to.name = NAME_EXTERN;
p->to.sym = linksym(n->left->sym);
}
}
regalloc(&n3, t0, N);
if(nl->ullman >= nr->ullman) {
- savex(D_AX, &ax, &oldax, res, t0);
+ savex(REG_AX, &ax, &oldax, res, t0);
cgen(nl, &ax);
regalloc(&ax, t0, &ax); // mark ax live during cgen
cgen(nr, &n3);
regfree(&ax);
} else {
cgen(nr, &n3);
- savex(D_AX, &ax, &oldax, res, t0);
+ savex(REG_AX, &ax, &oldax, res, t0);
cgen(nl, &ax);
}
if(t != t0) {
p2 = gbranch(AJMP, T, 0);
patch(p1, pc);
}
- savex(D_DX, &dx, &olddx, res, t);
+ savex(REG_DX, &dx, &olddx, res, t);
if(!issigned[t->etype]) {
nodconst(&n4, t, 0);
gmove(&n4, &dx);
}
cgenr(nl, &n1, res);
cgenr(nr, &n2, N);
- nodreg(&ax, t, D_AX);
+ nodreg(&ax, t, REG_AX);
gmove(&n1, &ax);
gins(a, &n2, N);
regfree(&n2);
if(t->width == 1) {
// byte multiply behaves differently.
- nodreg(&ax, t, D_AH);
- nodreg(&dx, t, D_DX);
+ nodreg(&ax, t, REG_AH);
+ nodreg(&dx, t, REG_DX);
gmove(&ax, &dx);
}
- nodreg(&dx, t, D_DX);
+ nodreg(&dx, t, REG_DX);
gmove(&dx, res);
}
nr = &n5;
}
- rcx = reg[D_CX];
- nodreg(&n1, types[TUINT32], D_CX);
+ rcx = reg[REG_CX];
+ nodreg(&n1, types[TUINT32], REG_CX);
// Allow either uint32 or uint64 as shift type,
// to avoid unnecessary conversion from uint32 to uint64
regalloc(&n1, nr->type, &n1); // to hold the shift type in CX
regalloc(&n3, tcount, &n1); // to clear high bits of CX
- nodreg(&cx, types[TUINT64], D_CX);
+ nodreg(&cx, types[TUINT64], REG_CX);
memset(&oldcx, 0, sizeof oldcx);
if(rcx > 0 && !samereg(&cx, res)) {
regalloc(&oldcx, types[TUINT64], N);
return;
}
- savex(D_DI, &n1, &oldn1, N, types[tptr]);
+ savex(REG_DI, &n1, &oldn1, N, types[tptr]);
agen(nl, &n1);
- savex(D_AX, &ax, &oldax, N, types[tptr]);
- gconreg(AMOVL, 0, D_AX);
+ savex(REG_AX, &ax, &oldax, N, types[tptr]);
+ gconreg(AMOVL, 0, REG_AX);
if(q > 128 || nacl) {
- gconreg(movptr, q, D_CX);
+ gconreg(movptr, q, REG_CX);
gins(AREP, N, N); // repeat
gins(ASTOSQ, N, N); // STOQ AL,*(DI)+
} else {
p = gins(ADUFFZERO, N, N);
- p->to.type = D_ADDR;
+ p->to.type = TYPE_ADDR;
p->to.sym = linksym(pkglookup("duffzero", runtimepkg));
// 2 and 128 = magic constants: see ../../runtime/asm_amd64.s
p->to.offset = 2*(128-q);
p1->pc = 9999;
p2->pc = 9999;
p->as = cmpptr;
- p->to.type = D_CONST;
+ p->to.type = TYPE_CONST;
p->to.offset = 0;
p1->as = AJNE;
- p1->from.type = D_CONST;
+ p1->from.type = TYPE_CONST;
p1->from.offset = 1; // likely
- p1->to.type = D_BRANCH;
+ p1->to.type = TYPE_BRANCH;
p1->to.u.branch = p2->link;
// crash by write to memory address 0.
// if possible, since we know arg is 0, use 0(arg),
// which will be shorter to encode than plain 0.
p2->as = AMOVL;
- p2->from.type = D_AX;
- if(regtyp(&p->from))
- p2->to.type = p->from.type + D_INDIR;
- else
- p2->to.type = D_INDIR+D_NONE;
+ p2->from.type = TYPE_REG;
+ p2->from.reg = REG_AX;
+ if(regtyp(&p->from)) {
+ p2->to.type = TYPE_MEM;
+ p2->to.reg = p->from.reg;
+ } else {
+ p2->to.type = TYPE_MEM;
+ p2->to.reg = REG_NONE;
+ }
p2->to.offset = 0;
}
}
Prog *p;
p = gins(ADATA, N, N);
- p->from.type = D_EXTERN;
- p->from.index = D_NONE;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.offset = off;
- p->from.scale = n;
p->from.sym = linksym(s);
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = n;
- p->to.type = D_SCONST;
- p->to.index = D_NONE;
+ p->to.type = TYPE_SCONST;
memmove(p->to.u.sval, t, n);
return off + n;
}
Sym *sym;
sym = stringsym(s, len);
- a->type = D_EXTERN;
+ a->type = TYPE_MEM;
+ a->name = NAME_EXTERN;
a->sym = linksym(sym);
a->node = sym->def;
a->offset = widthptr+widthint; // skip header
Sym *sym;
sym = stringsym(sval->s, sval->len);
- a->type = D_EXTERN;
+ a->type = TYPE_MEM;
+ a->name = NAME_EXTERN;
a->sym = linksym(sym);
a->node = sym->def;
a->offset = 0; // header
}
}
p = gins(ADATA, nam, nr);
- p->from.scale = wid;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = wid;
}
void
w = types[w]->width;
p = gins(ADATA, nam, N);
- p->from.scale = w;
- p->to.type = D_FCONST;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = w;
+ p->to.type = TYPE_FCONST;
p->to.u.dval = mpgetflt(&cval->real);
p = gins(ADATA, nam, N);
- p->from.scale = w;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = w;
p->from.offset += w;
- p->to.type = D_FCONST;
+ p->to.type = TYPE_FCONST;
p->to.u.dval = mpgetflt(&cval->imag);
}
p = gins(ADATA, nam, N);
datastring(sval->s, sval->len, &p->to);
- p->from.scale = types[tptr]->width;
- p->to.index = p->to.type;
- p->to.type = D_ADDR;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = types[tptr]->width;
+ p->to.type = TYPE_ADDR;
//print("%P\n", p);
nodconst(&nod1, types[TINT], sval->len);
p = gins(ADATA, nam, &nod1);
- p->from.scale = widthint;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = widthint;
p->from.offset += widthptr;
}
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
- p->from.type = D_EXTERN;
- p->from.index = D_NONE;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
- p->from.scale = widthptr;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = widthptr;
datastring(str, strlen(str)+1, &p->to);
- p->to.index = p->to.type;
- p->to.type = D_ADDR;
+ p->to.type = TYPE_ADDR;
p->to.etype = simtype[TINT];
off += widthptr;
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
- p->from.type = D_EXTERN;
- p->from.index = D_NONE;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
- p->from.scale = widthptr;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = widthptr;
datagostring(lit, &p->to);
- p->to.index = p->to.type;
- p->to.type = D_ADDR;
+ p->to.type = TYPE_ADDR;
p->to.etype = simtype[TINT];
off += widthptr;
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
- p->from.type = D_EXTERN;
- p->from.index = D_NONE;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
- p->from.scale = widthptr;
- p->to.type = D_ADDR;
- p->to.index = D_EXTERN;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = widthptr;
+ p->to.type = TYPE_ADDR;
+ p->to.name = NAME_EXTERN;
p->to.sym = linksym(x);
p->to.offset = xoff;
off += widthptr;
nopout(Prog *p)
{
p->as = ANOP;
+ p->from = zprog.from;
+ p->to = zprog.to;
}
clearp(Prog *p)
{
p->as = AEND;
- p->from.type = D_NONE;
- p->from.index = D_NONE;
- p->to.type = D_NONE;
- p->to.index = D_NONE;
+ p->from.type = TYPE_NONE;
+ p->from.index = TYPE_NONE;
+ p->to.type = TYPE_NONE;
+ p->to.index = TYPE_NONE;
p->pc = pcloc;
pcloc++;
}
USED(t);
p = prog(as);
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
p->to.u.branch = P;
if(as != AJMP && likely != 0) {
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = likely > 0;
}
return p;
void
patch(Prog *p, Prog *to)
{
- if(p->to.type != D_BRANCH)
+ if(p->to.type != TYPE_BRANCH)
fatal("patch: not a branch");
p->to.u.branch = to;
p->to.offset = to->pc;
{
Prog *q;
- if(p->to.type != D_BRANCH)
+ if(p->to.type != TYPE_BRANCH)
fatal("unpatch: not a branch");
q = p->to.u.branch;
p->to.u.branch = P;
p->lineno = nam->lineno;
p->from.sym->gotype = linksym(ngotype(nam));
p->to.sym = nil;
- p->to.type = D_CONST;
+ p->to.type = TYPE_CONST;
p->to.offset = nam->type->width;
if(nam->readonly)
- p->from.scale = RODATA;
+ p->from3.offset = RODATA;
if(nam->type != T && !haspointers(nam->type))
- p->from.scale |= NOPTR;
+ p->from3.offset |= NOPTR;
}
void
Prog *p;
p = gins(AUSEFIELD, N, N);
- p->from.type = D_EXTERN;
- p->from.index = D_NONE;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
}
Prog *p;
p = gins(AGLOBL, N, N);
- p->from.type = D_EXTERN;
- p->from.index = D_NONE;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
- p->to.type = D_CONST;
- p->to.index = D_NONE;
+ p->to.type = TYPE_CONST;
p->to.offset = width;
- p->from.scale = flags;
+ p->from3.offset = flags;
}
int
void
afunclit(Addr *a, Node *n)
{
- if(a->type == D_ADDR && a->index == D_EXTERN) {
- a->type = D_EXTERN;
- a->index = D_NONE;
+ if(a->type == TYPE_ADDR && a->name == NAME_EXTERN) {
+ a->type = TYPE_MEM;
a->sym = linksym(n->sym);
}
}
static int resvd[] =
{
- D_DI, // for movstring
- D_SI, // for movstring
+ REG_DI, // for movstring
+ REG_SI, // for movstring
- D_AX, // for divide
- D_CX, // for shift
- D_DX, // for divide
- D_SP, // for stack
+ REG_AX, // for divide
+ REG_CX, // for shift
+ REG_DX, // for divide
+ REG_SP, // for stack
};
void
for(i=0; i<nelem(reg); i++)
reg[i] = 1;
- for(i=D_AX; i<=D_R15; i++)
+ for(i=REG_AX; i<=REG_R15; i++)
reg[i] = 0;
- for(i=D_X0; i<=D_X15; i++)
+ for(i=REG_X0; i<=REG_X15; i++)
reg[i] = 0;
for(i=0; i<nelem(resvd); i++)
reg[resvd[i]]++;
if(nacl) {
- reg[D_BP]++;
- reg[D_R15]++;
+ reg[REG_BP]++;
+ reg[REG_R15]++;
+ } else if(framepointer_enabled) {
+ // BP is part of the calling convention of framepointer_enabled.
+ reg[REG_BP]++;
}
}
for(i=0; i<nelem(resvd); i++)
reg[resvd[i]]--;
if(nacl) {
- reg[D_BP]--;
- reg[D_R15]--;
+ reg[REG_BP]--;
+ reg[REG_R15]--;
+ } else if(framepointer_enabled) {
+ reg[REG_BP]--;
}
- for(i=D_AX; i<=D_R15; i++)
+ for(i=REG_AX; i<=REG_R15; i++)
if(reg[i])
yyerror("reg %R left allocated\n", i);
- for(i=D_X0; i<=D_X15; i++)
+ for(i=REG_X0; i<=REG_X15; i++)
if(reg[i])
yyerror("reg %R left allocated\n", i);
}
{
int i, j;
- for(i=D_AX; i<=D_R15; i++) {
+ for(i=REG_AX; i<=REG_R15; i++) {
if(reg[i] == 0)
goto ok;
for(j=0; j<nelem(resvd); j++)
return 0;
}
-static uintptr regpc[D_R15+1 - D_AX];
+static uintptr regpc[REG_R15+1 - REG_AX];
/*
* allocate register of type t, leave in n.
case TBOOL:
if(o != N && o->op == OREGISTER) {
i = o->val.u.reg;
- if(i >= D_AX && i <= D_R15)
+ if(i >= REG_AX && i <= REG_R15)
goto out;
}
- for(i=D_AX; i<=D_R15; i++)
+ for(i=REG_AX; i<=REG_R15; i++)
if(reg[i] == 0) {
- regpc[i-D_AX] = (uintptr)getcallerpc(&n);
+ regpc[i-REG_AX] = (uintptr)getcallerpc(&n);
goto out;
}
flusherrors();
- for(i=0; i+D_AX<=D_R15; i++)
+ for(i=0; i+REG_AX<=REG_R15; i++)
print("%d %p\n", i, regpc[i]);
fatal("out of fixed registers");
case TFLOAT64:
if(o != N && o->op == OREGISTER) {
i = o->val.u.reg;
- if(i >= D_X0 && i <= D_X15)
+ if(i >= REG_X0 && i <= REG_X15)
goto out;
}
- for(i=D_X0; i<=D_X15; i++)
+ for(i=REG_X0; i<=REG_X15; i++)
if(reg[i] == 0)
goto out;
fatal("out of floating registers");
if(n->op != OREGISTER && n->op != OINDREG)
fatal("regfree: not a register");
i = n->val.u.reg;
- if(i == D_SP)
+ if(i == REG_SP)
return;
if(i < 0 || i >= nelem(reg))
fatal("regfree: reg out of range");
if(reg[i] <= 0)
fatal("regfree: reg not allocated");
reg[i]--;
- if(reg[i] == 0 && D_AX <= i && i <= D_R15)
- regpc[i - D_AX] = 0;
+ if(reg[i] == 0 && REG_AX <= i && i <= REG_R15)
+ regpc[i - REG_AX] = 0;
}
/*
switch(fp) {
case 0: // output arg
n->op = OINDREG;
- n->val.u.reg = D_SP;
+ n->val.u.reg = REG_SP;
break;
case 1: // input arg
case 2: // offset output arg
fatal("shouldn't be used");
n->op = OINDREG;
- n->val.u.reg = D_SP;
+ n->val.u.reg = REG_SP;
n->xoffset += types[tptr]->width;
break;
}
dump("t", t);
fatal("bad width: %P (%d, %d)\n", p, af.width, at.width);
}
+ if(p->to.type == TYPE_ADDR && w > 0)
+ fatal("bad use of addr: %P", p);
return p;
}
return;
if(n->op != OINDREG)
return;
- if(n->val.u.reg == D_SP) // stack offset cannot be large
+ if(n->val.u.reg == REG_SP) // stack offset cannot be large
return;
if(n->xoffset != (int32)n->xoffset) {
// offset too large, add to register instead.
Sym *s;
a->scale = 0;
- a->index = D_NONE;
- a->type = D_NONE;
+ a->reg = REG_NONE;
+ a->index = REG_NONE;
+ a->type = TYPE_NONE;
+ a->name = NAME_NONE;
a->gotype = nil;
a->node = N;
a->width = 0;
break;
case OREGISTER:
- a->type = n->val.u.reg;
+ a->type = TYPE_REG;
+ a->reg = n->val.u.reg;
a->sym = nil;
break;
-// case OINDEX:
-// case OIND:
-// naddr(n->left, a);
-// if(a->type >= D_AX && a->type <= D_DI)
-// a->type += D_INDIR;
-// else
-// if(a->type == D_CONST)
-// a->type = D_NONE+D_INDIR;
-// else
-// if(a->type == D_ADDR) {
-// a->type = a->index;
-// a->index = D_NONE;
-// } else
-// goto bad;
-// if(n->op == OINDEX) {
-// a->index = idx.reg;
-// a->scale = n->scale;
-// }
-// break;
-
case OINDREG:
- a->type = n->val.u.reg+D_INDIR;
+ a->type = TYPE_MEM;
+ a->reg = n->val.u.reg;
a->sym = linksym(n->sym);
a->offset = n->xoffset;
if(a->offset != (int32)a->offset)
a->width = n->left->type->width;
a->offset = n->xoffset;
a->sym = linksym(n->left->sym);
- a->type = D_PARAM;
+ a->type = TYPE_MEM;
+ a->name = NAME_PARAM;
a->node = n->left->orig;
break;
case OCLOSUREVAR:
if(!curfn->needctxt)
fatal("closurevar without needctxt");
- a->type = D_DX+D_INDIR;
+ a->type = TYPE_MEM;
+ a->reg = REG_DX;
a->sym = nil;
a->offset = n->xoffset;
break;
s = pkglookup(s->name, n->type->sym->pkg);
}
+ a->type = TYPE_MEM;
switch(n->class) {
default:
fatal("naddr: ONAME class %S %d\n", n->sym, n->class);
case PEXTERN:
- a->type = D_EXTERN;
+ a->name = NAME_EXTERN;
break;
case PAUTO:
- a->type = D_AUTO;
+ a->name = NAME_AUTO;
break;
case PPARAM:
case PPARAMOUT:
- a->type = D_PARAM;
+ a->name = NAME_PARAM;
break;
case PFUNC:
- a->index = D_EXTERN;
- a->type = D_ADDR;
+ a->name = NAME_EXTERN;
+ a->type = TYPE_ADDR;
a->width = widthptr;
s = funcsym(s);
break;
fatal("naddr: const %lT", n->type);
break;
case CTFLT:
- a->type = D_FCONST;
+ a->type = TYPE_FCONST;
a->u.dval = mpgetflt(n->val.u.fval);
break;
case CTINT:
case CTRUNE:
a->sym = nil;
- a->type = D_CONST;
+ a->type = TYPE_CONST;
a->offset = mpgetfix(n->val.u.xval);
break;
case CTSTR:
break;
case CTBOOL:
a->sym = nil;
- a->type = D_CONST;
+ a->type = TYPE_CONST;
a->offset = n->val.u.bval;
break;
case CTNIL:
a->sym = nil;
- a->type = D_CONST;
+ a->type = TYPE_CONST;
a->offset = 0;
break;
}
case OADDR:
naddr(n->left, a, canemitcode);
a->width = widthptr;
- if(a->type >= D_INDIR) {
- a->type -= D_INDIR;
- break;
- }
- if(a->type == D_EXTERN || a->type == D_STATIC ||
- a->type == D_AUTO || a->type == D_PARAM)
- if(a->index == D_NONE) {
- a->index = a->type;
- a->type = D_ADDR;
- break;
- }
- fatal("naddr: OADDR\n");
+ if(a->type != TYPE_MEM)
+ fatal("naddr: OADDR %D", a);
+ a->type = TYPE_ADDR;
+ break;
case OITAB:
// itable of interface value
naddr(n->left, a, canemitcode);
- if(a->type == D_CONST && a->offset == 0)
+ if(a->type == TYPE_CONST && a->offset == 0)
break; // itab(nil)
a->etype = tptr;
a->width = widthptr;
case OSPTR:
// pointer in a string or slice
naddr(n->left, a, canemitcode);
- if(a->type == D_CONST && a->offset == 0)
+ if(a->type == TYPE_CONST && a->offset == 0)
break; // ptr(nil)
a->etype = simtype[tptr];
a->offset += Array_array;
case OLEN:
// len of string or slice
naddr(n->left, a, canemitcode);
- if(a->type == D_CONST && a->offset == 0)
+ if(a->type == TYPE_CONST && a->offset == 0)
break; // len(nil)
a->etype = simtype[TUINT];
a->offset += Array_nel;
case OCAP:
// cap of string or slice
naddr(n->left, a, canemitcode);
- if(a->type == D_CONST && a->offset == 0)
+ if(a->type == TYPE_CONST && a->offset == 0)
break; // cap(nil)
a->etype = simtype[TUINT];
a->offset += Array_cap;
if(t == T)
fatal("optoas: t is nil");
- a = AGOK;
+ a = AXXX;
switch(CASE(op, simtype[t->etype])) {
default:
fatal("optoas: no entry %O-%T", op, t);
n1.xoffset = -(oary[i]+1);
}
- a->type = D_NONE;
- a->index = D_NONE;
+ a->type = TYPE_NONE;
+ a->index = TYPE_NONE;
fixlargeoffset(&n1);
naddr(&n1, a, 1);
goto yes;
naddr(reg1, a, 1);
a->offset = 0;
a->scale = w;
- a->index = a->type;
- a->type = reg->val.u.reg + D_INDIR;
+ a->index = a->reg;
+ a->type = TYPE_MEM;
+ a->reg = reg->val.u.reg;
} else {
naddr(reg1, a, 1);
a->offset = 0;
a->scale = w;
- a->index = a->type;
- a->type = reg->val.u.reg + D_INDIR;
+ a->index = a->reg;
+ a->type = TYPE_MEM;
+ a->reg = reg->val.u.reg;
}
goto yes;
n2.op = OINDREG;
n2.xoffset = v*w;
fixlargeoffset(&n2);
- a->type = D_NONE;
- a->index = D_NONE;
+ a->type = TYPE_NONE;
+ a->index = TYPE_NONE;
naddr(&n2, a, 1);
goto yes;
}
}
n1.xoffset += v*w;
fixlargeoffset(&n1);
- a->type = D_NONE;
- a->index= D_NONE;
+ a->type = TYPE_NONE;
+ a->index= TYPE_NONE;
naddr(&n1, a, 1);
goto yes;
n2.op = OINDREG;
n2.xoffset = v*w;
fixlargeoffset(&n2);
- a->type = D_NONE;
- a->index = D_NONE;
+ a->type = TYPE_NONE;
+ a->index = TYPE_NONE;
naddr(&n2, a, 1);
goto yes;
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include "../gc/popt.h"
#define Z N
#define Adr Addr
-#define D_HI D_NONE
-#define D_LO D_NONE
+#define D_HI TYPE_NONE
+#define D_LO TYPE_NONE
#define BLOAD(r) band(bnot(r->refbehind), r->refahead)
#define BSTORE(r) band(bnot(r->calbehind), r->calahead)
extern Node *Z;
enum
{
- D_HI = D_NONE,
- D_LO = D_NONE,
+ D_HI = TYPE_NONE,
+ D_LO = TYPE_NONE,
CLOAD = 5,
CREF = 5,
CINF = 1000,
/*
* prog.c
*/
-typedef struct ProgInfo ProgInfo;
-struct ProgInfo
-{
- uint32 flags; // the bits below
- uint32 reguse; // registers implicitly used by this instruction
- uint32 regset; // registers implicitly set by this instruction
- uint32 regindex; // registers used by addressing mode
-};
-
-enum
-{
- // Pseudo-op, like TEXT, GLOBL, TYPE, PCDATA, FUNCDATA.
- Pseudo = 1<<1,
-
- // There's nothing to say about the instruction,
- // but it's still okay to see.
- OK = 1<<2,
-
- // Size of right-side write, or right-side read if no write.
- SizeB = 1<<3,
- SizeW = 1<<4,
- SizeL = 1<<5,
- SizeQ = 1<<6,
- SizeF = 1<<7, // float aka float32
- SizeD = 1<<8, // double aka float64
-
- // Left side (Prog.from): address taken, read, write.
- LeftAddr = 1<<9,
- LeftRead = 1<<10,
- LeftWrite = 1<<11,
-
- // Right side (Prog.to): address taken, read, write.
- RightAddr = 1<<12,
- RightRead = 1<<13,
- RightWrite = 1<<14,
-
- // Set, use, or kill of carry bit.
- // Kill means we never look at the carry bit after this kind of instruction.
- SetCarry = 1<<15,
- UseCarry = 1<<16,
- KillCarry = 1<<17,
-
- // Instruction kinds
- Move = 1<<18, // straight move
- Conv = 1<<19, // size conversion
- Cjmp = 1<<20, // conditional jump
- Break = 1<<21, // breaks control flow (no fallthrough)
- Call = 1<<22, // function call
- Jump = 1<<23, // jump
- Skip = 1<<24, // data instruction
-
- // Special cases for register use.
- ShiftCX = 1<<25, // possible shift by CX
- ImulAXDX = 1<<26, // possible multiply into DX:AX
-};
void proginfo(ProgInfo*, Prog*);
if(r != nil)
for(;;) {
p = r->prog;
- if(p->as != ANOP || p->from.type != D_NONE || p->to.type != D_NONE)
+ if(p->as != ANOP || p->from.type != TYPE_NONE || p->to.type != TYPE_NONE)
break;
r1 = uniqs(r);
if(r1 == nil)
case ALEAQ:
if(regtyp(&p->to))
if(p->from.sym != nil)
- if(p->from.index == D_NONE || p->from.index == D_CONST)
+ if(p->from.index == REG_NONE)
conprop(r);
break;
case AMOVSS:
case AMOVSD:
if(regtyp(&p->to))
- if(p->from.type == D_CONST || p->from.type == D_FCONST)
+ if(p->from.type == TYPE_CONST || p->from.type == TYPE_FCONST)
conprop(r);
break;
}
r1 = rnops(uniqs(r));
if(r1 != nil) {
p1 = r1->prog;
- if(p->as == p1->as && p->to.type == p1->from.type){
+ if(p->as == p1->as && p->to.type == p1->from.type && p->to.reg == p1->from.reg){
p1->as = AMOVL;
t++;
}
r1 = rnops(uniqs(r));
if(r1 != nil) {
p1 = r1->prog;
- if(p->as == p1->as && p->to.type == p1->from.type){
+ if(p->as == p1->as && p->to.type == p1->from.type && p->to.reg == p1->from.reg){
p1->as = AMOVQ;
t++;
}
case AADDL:
case AADDQ:
case AADDW:
- if(p->from.type != D_CONST || needc(p->link))
+ if(p->from.type != TYPE_CONST || needc(p->link))
break;
if(p->from.offset == -1){
if(p->as == AADDQ)
case ASUBL:
case ASUBQ:
case ASUBW:
- if(p->from.type != D_CONST || needc(p->link))
+ if(p->from.type != TYPE_CONST || needc(p->link))
break;
if(p->from.offset == -1) {
if(p->as == ASUBQ)
p = r->prog;
if(p->as == AMOVLQZX)
if(regtyp(&p->from))
- if(p->from.type == p->to.type)
- if(prevl(r, p->from.type))
+ if(p->from.type == p->to.type && p->from.reg == p->to.reg)
+ if(prevl(r, p->from.reg))
excise(r);
if(p->as == AMOVSD)
if(debug['P'] && debug['v'])
print("%P ===delete===\n", p);
- p->as = ANOP;
- p->from = zprog.from;
- p->to = zprog.to;
+ nopout(p);
ostats.ndelmov++;
}
int
regtyp(Adr *a)
{
- int t;
-
- t = a->type;
- if(t >= D_AX && t <= D_R15)
- return 1;
- if(t >= D_X0 && t <= D_X15)
- return 1;
- return 0;
+ return a->type == TYPE_REG && (REG_AX <= a->reg && a->reg <= REG_R15 || REG_X0 <= a->reg && a->reg <= REG_X15);
}
// movb elimination.
p->as = ANOTQ;
break;
}
- if(regtyp(&p->from) || p->from.type == D_CONST) {
+ if(regtyp(&p->from) || p->from.type == TYPE_CONST) {
// move or artihmetic into partial register.
// from another register or constant can be movl.
// we don't switch to 64-bit arithmetic if it can
p->as = ASHLQ;
break;
}
- } else if(p->from.type >= D_NONE) {
+ } else if(p->from.type != TYPE_REG) {
// explicit zero extension, but don't
// do that if source is a byte register
// (only AH can occur and it's forbidden).
if(regtyp(a))
return 1;
switch(a->type) {
- case D_CONST:
- case D_FCONST:
- case D_SCONST:
- case D_ADDR:
+ case TYPE_CONST:
+ case TYPE_FCONST:
+ case TYPE_SCONST:
+ case TYPE_ADDR: // TODO(rsc): Not all TYPE_ADDRs are constants.
return 1;
}
return 0;
for(r=uniqp(r0); r!=nil; r=uniqp(r)) {
p = r->prog;
- if(p->to.type == reg) {
+ if(p->to.type == TYPE_REG && p->to.reg == reg) {
proginfo(&info, p);
if(info.flags & RightWrite) {
if(info.flags & SizeL)
return 0;
}
- if((info.flags & Move) && (info.flags & (SizeL|SizeQ|SizeF|SizeD)) && p->to.type == v1->type)
+ if((info.flags & Move) && (info.flags & (SizeL|SizeQ|SizeF|SizeD)) && p->to.type == v1->type && p->to.reg == v1->reg)
goto gotit;
if(copyau(&p->from, v2) ||
copysub(&p->to, v1, v2, 1);
if(debug['P']) {
print("gotit: %D->%D\n%P", v1, v2, r->prog);
- if(p->from.type == v2->type)
+ if(p->from.type == v2->type && p->from.reg == v2->reg)
print(" excise");
print("\n");
}
if(debug['P'])
print("%P\n", r->prog);
}
- t = v1->type;
- v1->type = v2->type;
- v2->type = t;
+ t = v1->reg;
+ v1->reg = v2->reg;
+ v2->reg = t;
if(debug['P'])
print("%P last\n", r->prog);
return 1;
return 3;
case ACALL:
- if(REGEXT && v->type <= REGEXT && v->type > exregoffset)
+ if(REGEXT && v->type == TYPE_REG && v->reg <= REGEXT && v->reg > exregoffset)
return 2;
- if(REGARG >= 0 && v->type == (uchar)REGARG)
+ if(REGARG >= 0 && v->type == TYPE_REG && v->reg == (uchar)REGARG)
return 2;
- if(v->type == p->from.type)
+ if(v->type == p->from.type && v->reg == p->from.reg)
return 2;
if(s != nil) {
return 3;
case ATEXT:
- if(REGARG >= 0 && v->type == (uchar)REGARG)
+ if(REGARG >= 0 && v->type == TYPE_REG && v->reg == (uchar)REGARG)
return 3;
return 0;
}
return 0;
proginfo(&info, p);
- if((info.reguse|info.regset) & RtoB(v->type))
+ if((info.reguse|info.regset) & RtoB(v->reg))
return 2;
if(info.flags & LeftAddr)
static int
copyas(Adr *a, Adr *v)
{
- if(D_AL <= a->type && a->type <= D_R15B)
+ if(REG_AL <= a->reg && a->reg <= REG_R15B)
fatal("use of byte register");
- if(D_AL <= v->type && v->type <= D_R15B)
+ if(REG_AL <= v->reg && v->reg <= REG_R15B)
fatal("use of byte register");
- if(a->type != v->type)
+ if(a->type != v->type || a->name != v->name || a->reg != v->reg)
return 0;
if(regtyp(v))
return 1;
- if(v->type == D_AUTO || v->type == D_PARAM)
+ if(v->type == TYPE_MEM && (v->name == NAME_AUTO || v->name == NAME_PARAM))
if(v->offset == a->offset)
return 1;
return 0;
int
sameaddr(Addr *a, Addr *v)
{
- if(a->type != v->type)
+ if(a->type != v->type || a->name != v->name || a->reg != v->reg)
return 0;
if(regtyp(v))
return 1;
- if(v->type == D_AUTO || v->type == D_PARAM)
+ if(v->type == TYPE_MEM && (v->name == NAME_AUTO || v->name == NAME_PARAM))
if(v->offset == a->offset)
return 1;
return 0;
return 1;
}
if(regtyp(v)) {
- if(a->type-D_INDIR == v->type) {
+ if(a->type == TYPE_MEM && a->reg == v->reg) {
if(debug['P'] && debug['v'])
print("\tcopyau: found indir use - return 1\n");
return 1;
}
- if(a->index == v->type) {
+ if(a->index == v->reg) {
if(debug['P'] && debug['v'])
print("\tcopyau: found index use - return 1\n");
return 1;
static int
copysub(Adr *a, Adr *v, Adr *s, int f)
{
- int t;
+ int reg;
if(copyas(a, v)) {
- t = s->type;
- if(t >= D_AX && t <= D_R15 || t >= D_X0 && t <= D_X0+15) {
+ reg = s->reg;
+ if(reg >= REG_AX && reg <= REG_R15 || reg >= REG_X0 && reg <= REG_X0+15) {
if(f)
- a->type = t;
+ a->reg = reg;
}
return 0;
}
if(regtyp(v)) {
- t = v->type;
- if(a->type == t+D_INDIR) {
- if((s->type == D_BP || s->type == D_R13) && a->index != D_NONE)
+ reg = v->reg;
+ if(a->type == TYPE_MEM && a->reg == reg) {
+ if((s->reg == REG_BP || s->reg == REG_R13) && a->index != REG_NONE)
return 1; /* can't use BP-base with index */
if(f)
- a->type = s->type+D_INDIR;
+ a->reg = s->reg;
// return 0;
}
- if(a->index == t) {
+ if(a->index == reg) {
if(f)
- a->index = s->type;
+ a->index = s->reg;
return 0;
}
return 0;
case 3: // set
if(p->as == p0->as)
if(p->from.type == p0->from.type)
+ if(p->from.reg == p0->from.reg)
if(p->from.node == p0->from.node)
if(p->from.offset == p0->from.offset)
if(p->from.scale == p0->from.scale)
- if(p->from.type == D_FCONST && p->from.u.dval == p0->from.u.dval)
+ if(p->from.type == TYPE_FCONST && p->from.u.dval == p0->from.u.dval)
if(p->from.index == p0->from.index) {
excise(r);
goto loop;
smallindir(Addr *a, Addr *reg)
{
return regtyp(reg) &&
- a->type == D_INDIR + reg->type &&
- a->index == D_NONE &&
+ a->type == TYPE_MEM && a->reg == reg->reg &&
+ a->index == REG_NONE &&
0 <= a->offset && a->offset < 4096;
}
int
stackaddr(Addr *a)
{
- return regtyp(a) && a->type == D_SP;
+ return a->type == TYPE_REG && a->reg == REG_SP;
}
#include "opt.h"
// Matches real RtoB but can be used in global initializer.
-#define RtoB(r) (1<<((r)-D_AX))
+#define RtoB(r) (1<<((r)-REG_AX))
enum {
- AX = RtoB(D_AX),
- BX = RtoB(D_BX),
- CX = RtoB(D_CX),
- DX = RtoB(D_DX),
- DI = RtoB(D_DI),
- SI = RtoB(D_SI),
+ AX = RtoB(REG_AX),
+ BX = RtoB(REG_BX),
+ CX = RtoB(REG_CX),
+ DX = RtoB(REG_DX),
+ DI = RtoB(REG_DI),
+ SI = RtoB(REG_SI),
LeftRdwr = LeftRead | LeftWrite,
RightRdwr = RightRead | RightWrite,
if(info->flags == 0)
fatal("unknown instruction %P", p);
- if((info->flags & ShiftCX) && p->from.type != D_CONST)
+ if((info->flags & ShiftCX) && p->from.type != TYPE_CONST)
info->reguse |= CX;
if(info->flags & ImulAXDX) {
- if(p->to.type == D_NONE) {
+ if(p->to.type == TYPE_NONE) {
info->reguse |= AX;
info->regset |= AX | DX;
} else {
}
// Addressing makes some registers used.
- if(p->from.type >= D_INDIR)
- info->regindex |= RtoB(p->from.type-D_INDIR);
- if(p->from.index != D_NONE)
+ if(p->from.type == TYPE_MEM && p->from.name == NAME_NONE)
+ info->regindex |= RtoB(p->from.reg);
+ if(p->from.index != REG_NONE)
info->regindex |= RtoB(p->from.index);
- if(p->to.type >= D_INDIR)
- info->regindex |= RtoB(p->to.type-D_INDIR);
- if(p->to.index != D_NONE)
+ if(p->to.type == TYPE_MEM && p->to.name == NAME_NONE)
+ info->regindex |= RtoB(p->to.reg);
+ if(p->to.index != REG_NONE)
info->regindex |= RtoB(p->to.index);
}
if(first) {
fmtinstall('Q', Qconv);
- exregoffset = D_R15;
+ exregoffset = REG_R15;
first = 0;
}
var[i].node = regnodes[i];
}
- regbits = RtoB(D_SP);
+ regbits = RtoB(REG_SP);
for(z=0; z<BITS; z++) {
externs.b[z] = 0;
params.b[z] = 0;
proginfo(&info, p);
// Avoid making variables for direct-called functions.
- if(p->as == ACALL && p->to.type == D_EXTERN)
+ if(p->as == ACALL && p->to.type == TYPE_MEM && p->to.name == NAME_EXTERN)
continue;
r->use1.b[0] |= info.reguse | info.regindex;
}
for(r = firstr; r != R; r = (Reg*)r->f.link) {
p = r->f.prog;
- if(p->as == AVARDEF && isfat(p->to.node->type) && p->to.node->opt != nil) {
+ if(p->as == AVARDEF && isfat(((Node*)(p->to.node))->type) && ((Node*)(p->to.node))->opt != nil) {
active++;
walkvardef(p->to.node, r, active);
}
for(p=firstp; p!=P; p=p->link) {
while(p->link != P && p->link->as == ANOP)
p->link = p->link->link;
- if(p->to.type == D_BRANCH)
+ if(p->to.type == TYPE_BRANCH)
while(p->to.u.branch != P && p->to.u.branch->as == ANOP)
p->to.u.branch = p->to.u.branch->link;
}
a = &p1->to;
a->offset = v->offset;
a->etype = v->etype;
- a->type = v->name;
+ a->type = TYPE_MEM;
+ a->name = v->name;
a->node = v->node;
a->sym = linksym(v->node->sym);
break;
}
- p1->from.type = rn;
+ p1->from.type = TYPE_REG;
+ p1->from.reg = rn;
+ p1->from.name = NAME_NONE;
if(!f) {
p1->from = *a;
*a = zprog.from;
- a->type = rn;
+ a->type = TYPE_REG;
+ a->reg = rn;
if(v->etype == TUINT8)
p1->as = AMOVB;
if(v->etype == TUINT16)
uint32 b;
b = 0;
- if(r >= D_INDIR)
- r -= D_INDIR;
- if(r >= D_AX && r <= D_R15)
+ if(r >= REG_AX && r <= REG_R15)
b |= RtoB(r);
else
- if(r >= D_AL && r <= D_R15B)
- b |= RtoB(r-D_AL+D_AX);
+ if(r >= REG_AL && r <= REG_R15B)
+ b |= RtoB(r-REG_AL+REG_AX);
else
- if(r >= D_AH && r <= D_BH)
- b |= RtoB(r-D_AH+D_AX);
+ if(r >= REG_AH && r <= REG_BH)
+ b |= RtoB(r-REG_AH+REG_AX);
else
- if(r >= D_X0 && r <= D_X0+15)
+ if(r >= REG_X0 && r <= REG_X0+15)
b |= FtoB(r);
return b;
}
mkvar(Reg *r, Adr *a)
{
Var *v;
- int i, t, n, et, z, flag;
+ int i, n, et, z, flag;
int64 w;
uint32 regu;
int64 o;
/*
* mark registers used
*/
- t = a->type;
- if(t == D_NONE)
+ if(a->type == TYPE_NONE)
goto none;
if(r != R)
r->use1.b[0] |= doregbits(a->index);
- if(t >= D_INDIR && t < 2*D_INDIR)
- goto none;
-
- switch(t) {
+ switch(a->type) {
default:
- regu = doregbits(t);
+ regu = doregbits(a->reg);
if(regu == 0)
goto none;
bit = zbits;
bit.b[0] = regu;
return bit;
- case D_ADDR:
- a->type = a->index;
+ case TYPE_ADDR:
+ a->type = TYPE_MEM;
bit = mkvar(r, a);
setaddrs(bit);
- a->type = t;
+ a->type = TYPE_ADDR;
ostats.naddr++;
goto none;
- case D_EXTERN:
- case D_STATIC:
- case D_PARAM:
- case D_AUTO:
- n = t;
- break;
+ case TYPE_MEM:
+ switch(a->name) {
+ default:
+ goto none;
+ case NAME_EXTERN:
+ case NAME_STATIC:
+ case NAME_PARAM:
+ case NAME_AUTO:
+ n = a->name;
+ break;
+ }
}
node = a->node;
node->opt = v;
bit = blsh(i);
- if(n == D_EXTERN || n == D_STATIC)
+ if(n == NAME_EXTERN || n == NAME_STATIC)
for(z=0; z<BITS; z++)
externs.b[z] |= bit.b[z];
- if(n == D_PARAM)
+ if(n == NAME_PARAM)
for(z=0; z<BITS; z++)
params.b[z] |= bit.b[z];
a->sym = nil;
a->node = nil;
a->offset = 0;
- a->type = rn;
+ a->type = TYPE_REG;
+ a->reg = rn;
+ a->name = 0;
ostats.ncvtreg++;
}
RtoB(int r)
{
- if(r < D_AX || r > D_R15)
+ if(r < REG_AX || r > REG_R15)
return 0;
- return 1L << (r-D_AX);
+ return 1L << (r-REG_AX);
}
int
{
b &= 0xffffL;
if(nacl)
- b &= ~((1<<(D_BP-D_AX)) | (1<<(D_R15-D_AX)));
+ b &= ~((1<<(REG_BP-REG_AX)) | (1<<(REG_R15-REG_AX)));
+ else if(framepointer_enabled)
+ // BP is part of the calling convention if framepointer_enabled.
+ b &= ~(1<<(REG_BP-REG_AX));
if(b == 0)
return 0;
- return bitno(b) + D_AX;
+ return bitno(b) + REG_AX;
}
/*
uint32
FtoB(int f)
{
- if(f < D_X0 || f > D_X15)
+ if(f < REG_X0 || f > REG_X15)
return 0;
- return 1L << (f - D_X0 + 16);
+ return 1L << (f - REG_X0 + 16);
}
int
b &= 0xFFFF0000L;
if(b == 0)
return 0;
- return bitno(b) - 16 + D_X0;
+ return bitno(b) - 16 + REG_X0;
}
void
enum
{
- AXXX,
- AAAA,
+ AAAA = A_ARCHSPECIFIC,
AAAD,
AAAM,
AAAS,
ABTSL,
ABTSW,
ABYTE,
- ACALL,
ACLC,
ACLD,
ACLI,
ACMPSW,
ADAA,
ADAS,
- ADATA,
ADECB,
ADECL,
ADECQ,
ADIVL,
ADIVW,
AENTER,
- AGLOBL,
- AGOK,
- AHISTORY,
AHLT,
AIDIVB,
AIDIVL,
AJLS,
AJLT,
AJMI,
- AJMP,
AJNE,
AJOC,
AJOS,
AMULB,
AMULL,
AMULW,
- ANAME,
ANEGB,
ANEGL,
ANEGW,
- ANOP,
ANOTB,
ANOTL,
ANOTW,
ARCRW,
AREP,
AREPN,
- ARET,
AROLB,
AROLL,
AROLW,
ATESTB,
ATESTL,
ATESTW,
- ATEXT,
AVERR,
AVERW,
AWAIT,
AFYL2X,
AFYL2XP1,
- AEND,
- ADYNT_,
- AINIT_,
- ASIGNAME,
/* extra 32-bit operations */
ACMPXCHGB,
ABSWAPL,
ABSWAPQ,
- AUNDEF,
AAESENC,
AAESENCLAST,
APSHUFD,
APCLMULQDQ,
- AUSEFIELD,
- ATYPE,
- AFUNCDATA,
- APCDATA,
- ACHECKNIL,
- AVARDEF,
- AVARKILL,
- ADUFFCOPY,
- ADUFFZERO,
ALAST
};
enum
{
+ REG_NONE = 0,
+
+ REG_AL = 0+16,
+ REG_CL,
+ REG_DL,
+ REG_BL,
+ REG_SPB,
+ REG_BPB,
+ REG_SIB,
+ REG_DIB,
+ REG_R8B,
+ REG_R9B,
+ REG_R10B,
+ REG_R11B,
+ REG_R12B,
+ REG_R13B,
+ REG_R14B,
+ REG_R15B,
+
+ REG_AX = 16+16,
+ REG_CX,
+ REG_DX,
+ REG_BX,
+ REG_SP,
+ REG_BP,
+ REG_SI,
+ REG_DI,
+ REG_R8,
+ REG_R9,
+ REG_R10,
+ REG_R11,
+ REG_R12,
+ REG_R13,
+ REG_R14,
+ REG_R15,
+
+ REG_AH = 32+16,
+ REG_CH,
+ REG_DH,
+ REG_BH,
+
+ REG_F0 = 36+16,
+
+ REG_M0 = 44+16,
+
+ REG_X0 = 52+16,
+ REG_X1,
+ REG_X2,
+ REG_X3,
+ REG_X4,
+ REG_X5,
+ REG_X6,
+ REG_X7,
+ REG_X8,
+ REG_X9,
+ REG_X10,
+ REG_X11,
+ REG_X12,
+ REG_X13,
+ REG_X14,
+ REG_X15,
+
+ REG_CS = 68+16,
+ REG_SS,
+ REG_DS,
+ REG_ES,
+ REG_FS,
+ REG_GS,
+
+ REG_GDTR, /* global descriptor table register */
+ REG_IDTR, /* interrupt descriptor table register */
+ REG_LDTR, /* local descriptor table register */
+ REG_MSW, /* machine status word */
+ REG_TASK, /* task register */
+
+ REG_CR = 79+16,
+ REG_DR = 95+16,
+ REG_TR = 103+16,
+
+ REG_TLS = 111+16,
+ MAXREG,
- D_AL = 0,
- D_CL,
- D_DL,
- D_BL,
- D_SPB,
- D_BPB,
- D_SIB,
- D_DIB,
- D_R8B,
- D_R9B,
- D_R10B,
- D_R11B,
- D_R12B,
- D_R13B,
- D_R14B,
- D_R15B,
-
- D_AX = 16,
- D_CX,
- D_DX,
- D_BX,
- D_SP,
- D_BP,
- D_SI,
- D_DI,
- D_R8,
- D_R9,
- D_R10,
- D_R11,
- D_R12,
- D_R13,
- D_R14,
- D_R15,
-
- D_AH = 32,
- D_CH,
- D_DH,
- D_BH,
-
- D_F0 = 36,
-
- D_M0 = 44,
-
- D_X0 = 52,
- D_X1,
- D_X2,
- D_X3,
- D_X4,
- D_X5,
- D_X6,
- D_X7,
- D_X8,
- D_X9,
- D_X10,
- D_X11,
- D_X12,
- D_X13,
- D_X14,
- D_X15,
-
- D_CS = 68,
- D_SS,
- D_DS,
- D_ES,
- D_FS,
- D_GS,
-
- D_GDTR, /* global descriptor table register */
- D_IDTR, /* interrupt descriptor table register */
- D_LDTR, /* local descriptor table register */
- D_MSW, /* machine status word */
- D_TASK, /* task register */
-
- D_CR = 79,
- D_DR = 95,
- D_TR = 103,
-
- D_TLS = 111,
- D_NONE = 112,
-
- D_BRANCH = 113,
- D_EXTERN = 114,
- D_STATIC = 115,
- D_AUTO = 116,
- D_PARAM = 117,
- D_CONST = 118,
- D_FCONST = 119,
- D_SCONST = 120,
- D_ADDR = 121,
-
- D_INDIR, /* additive */
-
- D_LAST,
+ REGARG = -1,
+ REGRET = REG_AX,
+ FREGRET = REG_X0,
+ REGSP = REG_SP,
+ REGTMP = REG_DI,
+ REGEXT = REG_R15, /* compiler allocates external registers R15 down */
+ FREGMIN = REG_X0+5, /* first register variable */
+ FREGEXT = REG_X0+15, /* first external register */
T_TYPE = 1<<0,
T_INDEX = 1<<1,
T_SCONST = 1<<5,
T_64 = 1<<6,
T_GOTYPE = 1<<7,
-
- REGARG = -1,
- REGRET = D_AX,
- FREGRET = D_X0,
- REGSP = D_SP,
- REGTMP = D_DI,
- REGEXT = D_R15, /* compiler allocates external registers R15 down */
- FREGMIN = D_X0+5, /* first register variable */
- FREGEXT = D_X0+15 /* first external register */
};
/*
EXTERN Biobuf obuf;
EXTERN Link* ctxt;
EXTERN Biobuf bstdout;
+EXTERN Prog* lastpc;
void* alloc(int32);
void* allocn(void*, int32, int32);
%union {
Sym *sym;
int32 lval;
- struct {
- int32 v1;
- int32 v2;
- } con2;
double dval;
char sval[8];
Addr addr;
%token <sval> LSCONST LSP
%token <sym> LNAME LLAB LVAR
%type <lval> con expr pointer offset
-%type <con2> con2
-%type <addr> mem imm imm2 reg nam rel rem rim rom omem nmem
+%type <addr> mem imm reg nam rel rem rim rom omem nmem textsize
%type <addr2> nonnon nonrel nonrem rimnon rimrem remrim
-%type <addr2> spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8 spec9 spec10 spec11 spec12
+%type <addr2> spec3 spec4 spec5 spec6 spec7 spec9 spec10 spec11 spec12
%%
prog:
| prog
| LTYPE3 rimrem { outcode($1, &$2); }
| LTYPE4 remrim { outcode($1, &$2); }
| LTYPER nonrel { outcode($1, &$2); }
-| LTYPED spec1 { outcode($1, &$2); }
-| LTYPET spec2 { outcode($1, &$2); }
+| spec1
+| spec2
| LTYPEC spec3 { outcode($1, &$2); }
| LTYPEN spec4 { outcode($1, &$2); }
| LTYPES spec5 { outcode($1, &$2); }
| LTYPEM spec6 { outcode($1, &$2); }
| LTYPEI spec7 { outcode($1, &$2); }
-| LTYPEG spec8 { outcode($1, &$2); }
+| spec8
| LTYPEXC spec9 { outcode($1, &$2); }
| LTYPEX spec10 { outcode($1, &$2); }
| LTYPEPC spec11 { outcode($1, &$2); }
}
spec1: /* DATA */
- nam '/' con ',' imm
+ LTYPED nam '/' con ',' imm
{
- $$.from = $1;
- $$.from.scale = $3;
- $$.to = $5;
+ Addr2 a;
+ a.from = $2;
+ a.to = $6;
+ outcode(ADATA, &a);
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = $4;
+ }
}
spec2: /* TEXT */
- mem ',' imm2
+ LTYPET mem ',' '$' textsize
{
- settext($1.sym);
- $$.from = $1;
- $$.to = $3;
+ Addr2 a;
+ settext($2.sym);
+ a.from = $2;
+ a.to = $5;
+ outcode(ATEXT, &a);
}
-| mem ',' con ',' imm2
+| LTYPET mem ',' con ',' '$' textsize
{
- settext($1.sym);
- $$.from = $1;
- $$.from.scale = $3;
- $$.to = $5;
+ Addr2 a;
+ settext($2.sym);
+ a.from = $2;
+ a.to = $7;
+ outcode(ATEXT, &a);
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = $4;
+ }
+ }
+
+spec8: /* GLOBL */
+ LTYPEG mem ',' imm
+ {
+ Addr2 a;
+ settext($2.sym);
+ a.from = $2;
+ a.to = $4;
+ outcode(AGLOBL, &a);
+ }
+| LTYPEG mem ',' con ',' imm
+ {
+ Addr2 a;
+ settext($2.sym);
+ a.from = $2;
+ a.to = $6;
+ outcode(AGLOBL, &a);
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = $4;
+ }
}
spec3: /* JMP/CALL */
{
$$.from = nullgen;
$$.to = $2;
- $$.to.index = $2.type;
- $$.to.type = D_INDIR+D_ADDR;
+ $$.to.type = TYPE_INDIR;
}
spec4: /* NOP */
{
$$.from = $1;
$$.to = $3;
- if($$.from.index != D_NONE)
+ if($$.from.index != TYPE_NONE)
yyerror("dp shift with lhs index");
$$.from.index = $5;
}
{
$$.from = $1;
$$.to = $3;
- if($$.to.index != D_NONE)
+ if($$.to.index != TYPE_NONE)
yyerror("dp move with lhs index");
$$.to.index = $5;
}
$$.to = $3;
}
-spec8: /* GLOBL */
- mem ',' imm
- {
- $$.from = $1;
- $$.to = $3;
- }
-| mem ',' con ',' imm
- {
- $$.from = $1;
- $$.from.scale = $3;
- $$.to = $5;
- }
-
spec9: /* CMPPS/CMPPD */
reg ',' rem ',' con
{
{
$$.from = $3;
$$.to = $5;
- if($1.type != D_CONST)
+ if($1.type != TYPE_CONST)
yyerror("illegal constant");
$$.to.offset = $1.offset;
}
spec11: /* PCDATA */
rim ',' rim
{
- if($1.type != D_CONST || $3.type != D_CONST)
+ if($1.type != TYPE_CONST || $3.type != TYPE_CONST)
yyerror("arguments to PCDATA must be integer constants");
$$.from = $1;
$$.to = $3;
spec12: /* FUNCDATA */
rim ',' rim
{
- if($1.type != D_CONST)
+ if($1.type != TYPE_CONST)
yyerror("index for FUNCDATA must be integer constant");
- if($3.type != D_EXTERN && $3.type != D_STATIC)
+ if($3.type != TYPE_MEM || ($3.name != NAME_EXTERN && $3.name != NAME_STATIC))
yyerror("value for FUNCDATA must be symbol reference");
$$.from = $1;
$$.to = $3;
con '(' LPC ')'
{
$$ = nullgen;
- $$.type = D_BRANCH;
+ $$.type = TYPE_BRANCH;
$$.offset = $1 + pc;
}
| LNAME offset
$$ = nullgen;
if(pass == 2 && $1->type != LLAB)
yyerror("undefined label: %s", $1->labelname);
- $$.type = D_BRANCH;
+ $$.type = TYPE_BRANCH;
$$.offset = $1->value + $2;
}
LBREG
{
$$ = nullgen;
- $$.type = $1;
+ $$.type = TYPE_REG;
+ $$.reg = $1;
}
| LFREG
{
$$ = nullgen;
- $$.type = $1;
+ $$.type = TYPE_REG;
+ $$.reg = $1;
}
| LLREG
{
$$ = nullgen;
- $$.type = $1;
+ $$.type = TYPE_REG;
+ $$.reg = $1;
}
| LXREG
{
$$ = nullgen;
- $$.type = $1;
+ $$.type = TYPE_REG;
+ $$.reg = $1;
}
| LSP
{
$$ = nullgen;
- $$.type = D_SP;
+ $$.type = TYPE_REG;
+ $$.reg = REG_SP;
}
| LSREG
{
$$ = nullgen;
- $$.type = $1;
+ $$.type = TYPE_REG;
+ $$.reg = $1;
}
imm:
'$' con
{
$$ = nullgen;
- $$.type = D_CONST;
+ $$.type = TYPE_CONST;
$$.offset = $2;
}
| '$' nam
{
$$ = $2;
- $$.index = $2.type;
- $$.type = D_ADDR;
+ $$.type = TYPE_ADDR;
/*
- if($2.type == D_AUTO || $2.type == D_PARAM)
+ if($2.name == NAME_AUTO || $2.name == NAME_PARAM)
yyerror("constant cannot be automatic: %s",
$2.sym->name);
*/
| '$' LSCONST
{
$$ = nullgen;
- $$.type = D_SCONST;
+ $$.type = TYPE_SCONST;
memcpy($$.u.sval, $2, sizeof($$.u.sval));
}
| '$' LFCONST
{
$$ = nullgen;
- $$.type = D_FCONST;
+ $$.type = TYPE_FCONST;
$$.u.dval = $2;
}
| '$' '(' LFCONST ')'
{
$$ = nullgen;
- $$.type = D_FCONST;
+ $$.type = TYPE_FCONST;
$$.u.dval = $3;
}
| '$' '(' '-' LFCONST ')'
{
$$ = nullgen;
- $$.type = D_FCONST;
+ $$.type = TYPE_FCONST;
$$.u.dval = -$4;
}
| '$' '-' LFCONST
{
$$ = nullgen;
- $$.type = D_FCONST;
+ $$.type = TYPE_FCONST;
$$.u.dval = -$3;
}
-imm2:
- '$' con2
- {
- $$ = nullgen;
- $$.type = D_CONST2;
- $$.offset = $2.v1;
- $$.offset2 = $2.v2;
- }
-
-con2:
+textsize:
LCONST
{
- $$.v1 = $1;
- $$.v2 = ArgsSizeUnknown;
+ $$ = nullgen;
+ $$.type = TYPE_TEXTSIZE;
+ $$.offset = $1;
+ $$.u.argsize = ArgsSizeUnknown;
}
| '-' LCONST
{
- $$.v1 = -$2;
- $$.v2 = ArgsSizeUnknown;
+ $$ = nullgen;
+ $$.type = TYPE_TEXTSIZE;
+ $$.offset = -$2;
+ $$.u.argsize = ArgsSizeUnknown;
}
| LCONST '-' LCONST
{
- $$.v1 = $1;
- $$.v2 = $3;
+ $$ = nullgen;
+ $$.type = TYPE_TEXTSIZE;
+ $$.offset = $1;
+ $$.u.argsize = $3;
}
| '-' LCONST '-' LCONST
{
- $$.v1 = -$2;
- $$.v2 = $4;
+ $$ = nullgen;
+ $$.type = TYPE_TEXTSIZE;
+ $$.offset = -$2;
+ $$.u.argsize = $4;
}
mem:
con
{
$$ = nullgen;
- $$.type = D_INDIR+D_NONE;
+ $$.type = TYPE_MEM;
+ $$.reg = REG_NONE;
$$.offset = $1;
}
| con '(' LLREG ')'
{
$$ = nullgen;
- $$.type = D_INDIR+$3;
+ $$.type = TYPE_MEM;
+ $$.reg = $3;
$$.offset = $1;
}
| con '(' LSP ')'
{
$$ = nullgen;
- $$.type = D_INDIR+D_SP;
+ $$.type = TYPE_MEM;
+ $$.reg = REG_SP;
$$.offset = $1;
}
| con '(' LLREG '*' con ')'
{
$$ = nullgen;
- $$.type = D_INDIR+D_NONE;
+ $$.type = TYPE_MEM;
+ $$.reg = REG_NONE;
$$.offset = $1;
$$.index = $3;
$$.scale = $5;
| con '(' LLREG ')' '(' LLREG '*' con ')'
{
$$ = nullgen;
- $$.type = D_INDIR+$3;
+ $$.type = TYPE_MEM;
+ $$.reg = $3;
$$.offset = $1;
$$.index = $6;
$$.scale = $8;
| con '(' LLREG ')' '(' LSREG '*' con ')'
{
$$ = nullgen;
- $$.type = D_INDIR+$3;
+ $$.type = TYPE_MEM;
+ $$.reg = $3;
$$.offset = $1;
$$.index = $6;
$$.scale = $8;
| '(' LLREG ')'
{
$$ = nullgen;
- $$.type = D_INDIR+$2;
+ $$.type = TYPE_MEM;
+ $$.reg = $2;
}
| '(' LSP ')'
{
$$ = nullgen;
- $$.type = D_INDIR+D_SP;
+ $$.type = TYPE_MEM;
+ $$.reg = REG_SP;
}
| con '(' LSREG ')'
{
$$ = nullgen;
- $$.type = D_INDIR+$3;
+ $$.type = TYPE_MEM;
+ $$.reg = $3;
$$.offset = $1;
}
| '(' LLREG '*' con ')'
{
$$ = nullgen;
- $$.type = D_INDIR+D_NONE;
+ $$.type = TYPE_MEM;
+ $$.reg = REG_NONE;
$$.index = $2;
$$.scale = $4;
checkscale($$.scale);
| '(' LLREG ')' '(' LLREG '*' con ')'
{
$$ = nullgen;
- $$.type = D_INDIR+$2;
+ $$.type = TYPE_MEM;
+ $$.reg = $2;
$$.index = $5;
$$.scale = $7;
checkscale($$.scale);
LNAME offset '(' pointer ')'
{
$$ = nullgen;
- $$.type = $4;
+ $$.type = TYPE_MEM;
+ $$.name = $4;
$$.sym = linklookup(ctxt, $1->name, 0);
$$.offset = $2;
}
| LNAME '<' '>' offset '(' LSB ')'
{
$$ = nullgen;
- $$.type = D_STATIC;
+ $$.type = TYPE_MEM;
+ $$.name = NAME_STATIC;
$$.sym = linklookup(ctxt, $1->name, 1);
$$.offset = $4;
}
LSB
| LSP
{
- $$ = D_AUTO;
+ $$ = NAME_AUTO;
}
| LFP
ushort value;
} itab[] =
{
- "SP", LSP, D_AUTO,
- "SB", LSB, D_EXTERN,
- "FP", LFP, D_PARAM,
- "PC", LPC, D_BRANCH,
-
- "AL", LBREG, D_AL,
- "CL", LBREG, D_CL,
- "DL", LBREG, D_DL,
- "BL", LBREG, D_BL,
- "AH", LBREG, D_AH,
- "CH", LBREG, D_CH,
- "DH", LBREG, D_DH,
- "BH", LBREG, D_BH,
-
- "AX", LLREG, D_AX,
- "CX", LLREG, D_CX,
- "DX", LLREG, D_DX,
- "BX", LLREG, D_BX,
-/* "SP", LLREG, D_SP, */
- "BP", LLREG, D_BP,
- "SI", LLREG, D_SI,
- "DI", LLREG, D_DI,
-
- "F0", LFREG, D_F0+0,
- "F1", LFREG, D_F0+1,
- "F2", LFREG, D_F0+2,
- "F3", LFREG, D_F0+3,
- "F4", LFREG, D_F0+4,
- "F5", LFREG, D_F0+5,
- "F6", LFREG, D_F0+6,
- "F7", LFREG, D_F0+7,
-
- "X0", LXREG, D_X0+0,
- "X1", LXREG, D_X0+1,
- "X2", LXREG, D_X0+2,
- "X3", LXREG, D_X0+3,
- "X4", LXREG, D_X0+4,
- "X5", LXREG, D_X0+5,
- "X6", LXREG, D_X0+6,
- "X7", LXREG, D_X0+7,
-
- "CS", LSREG, D_CS,
- "SS", LSREG, D_SS,
- "DS", LSREG, D_DS,
- "ES", LSREG, D_ES,
- "FS", LSREG, D_FS,
- "GS", LSREG, D_GS,
- "TLS", LSREG, D_TLS,
-
- "GDTR", LBREG, D_GDTR,
- "IDTR", LBREG, D_IDTR,
- "LDTR", LBREG, D_LDTR,
- "MSW", LBREG, D_MSW,
- "TASK", LBREG, D_TASK,
-
- "CR0", LBREG, D_CR+0,
- "CR1", LBREG, D_CR+1,
- "CR2", LBREG, D_CR+2,
- "CR3", LBREG, D_CR+3,
- "CR4", LBREG, D_CR+4,
- "CR5", LBREG, D_CR+5,
- "CR6", LBREG, D_CR+6,
- "CR7", LBREG, D_CR+7,
-
- "DR0", LBREG, D_DR+0,
- "DR1", LBREG, D_DR+1,
- "DR2", LBREG, D_DR+2,
- "DR3", LBREG, D_DR+3,
- "DR4", LBREG, D_DR+4,
- "DR5", LBREG, D_DR+5,
- "DR6", LBREG, D_DR+6,
- "DR7", LBREG, D_DR+7,
-
- "TR0", LBREG, D_TR+0,
- "TR1", LBREG, D_TR+1,
- "TR2", LBREG, D_TR+2,
- "TR3", LBREG, D_TR+3,
- "TR4", LBREG, D_TR+4,
- "TR5", LBREG, D_TR+5,
- "TR6", LBREG, D_TR+6,
- "TR7", LBREG, D_TR+7,
+ "SP", LSP, NAME_AUTO,
+ "SB", LSB, NAME_EXTERN,
+ "FP", LFP, NAME_PARAM,
+
+ "PC", LPC, TYPE_BRANCH,
+
+ "AL", LBREG, REG_AL,
+ "CL", LBREG, REG_CL,
+ "DL", LBREG, REG_DL,
+ "BL", LBREG, REG_BL,
+ "AH", LBREG, REG_AH,
+ "CH", LBREG, REG_CH,
+ "DH", LBREG, REG_DH,
+ "BH", LBREG, REG_BH,
+
+ "AX", LLREG, REG_AX,
+ "CX", LLREG, REG_CX,
+ "DX", LLREG, REG_DX,
+ "BX", LLREG, REG_BX,
+/* "SP", LLREG, REG_SP, */
+ "BP", LLREG, REG_BP,
+ "SI", LLREG, REG_SI,
+ "DI", LLREG, REG_DI,
+
+ "F0", LFREG, REG_F0+0,
+ "F1", LFREG, REG_F0+1,
+ "F2", LFREG, REG_F0+2,
+ "F3", LFREG, REG_F0+3,
+ "F4", LFREG, REG_F0+4,
+ "F5", LFREG, REG_F0+5,
+ "F6", LFREG, REG_F0+6,
+ "F7", LFREG, REG_F0+7,
+
+ "X0", LXREG, REG_X0+0,
+ "X1", LXREG, REG_X0+1,
+ "X2", LXREG, REG_X0+2,
+ "X3", LXREG, REG_X0+3,
+ "X4", LXREG, REG_X0+4,
+ "X5", LXREG, REG_X0+5,
+ "X6", LXREG, REG_X0+6,
+ "X7", LXREG, REG_X0+7,
+
+ "CS", LSREG, REG_CS,
+ "SS", LSREG, REG_SS,
+ "DS", LSREG, REG_DS,
+ "ES", LSREG, REG_ES,
+ "FS", LSREG, REG_FS,
+ "GS", LSREG, REG_GS,
+ "TLS", LSREG, REG_TLS,
+
+ "GDTR", LBREG, REG_GDTR,
+ "IDTR", LBREG, REG_IDTR,
+ "LDTR", LBREG, REG_LDTR,
+ "MSW", LBREG, REG_MSW,
+ "TASK", LBREG, REG_TASK,
+
+ "CR0", LBREG, REG_CR+0,
+ "CR1", LBREG, REG_CR+1,
+ "CR2", LBREG, REG_CR+2,
+ "CR3", LBREG, REG_CR+3,
+ "CR4", LBREG, REG_CR+4,
+ "CR5", LBREG, REG_CR+5,
+ "CR6", LBREG, REG_CR+6,
+ "CR7", LBREG, REG_CR+7,
+
+ "DR0", LBREG, REG_DR+0,
+ "DR1", LBREG, REG_DR+1,
+ "DR2", LBREG, REG_DR+2,
+ "DR3", LBREG, REG_DR+3,
+ "DR4", LBREG, REG_DR+4,
+ "DR5", LBREG, REG_DR+5,
+ "DR6", LBREG, REG_DR+6,
+ "DR7", LBREG, REG_DR+7,
+
+ "TR0", LBREG, REG_TR+0,
+ "TR1", LBREG, REG_TR+1,
+ "TR2", LBREG, REG_TR+2,
+ "TR3", LBREG, REG_TR+3,
+ "TR4", LBREG, REG_TR+4,
+ "TR5", LBREG, REG_TR+5,
+ "TR6", LBREG, REG_TR+6,
+ "TR7", LBREG, REG_TR+7,
"AAA", LTYPE0, AAAA,
"AAD", LTYPE0, AAAD,
Sym *s;
int i;
- nullgen.type = D_NONE;
- nullgen.index = D_NONE;
+ nullgen.type = TYPE_NONE;
+ nullgen.index = TYPE_NONE;
nerrors = 0;
iostack = I;
outcode(AEND, &g2);
}
-static Prog *lastpc;
-
void
outcode(int a, Addr2 *g2)
{
{
Sym *sym;
int32 lval;
- struct {
- int32 v1;
- int32 v2;
- } con2;
double dval;
char sval[8];
Addr addr;
Addr2 addr2;
}
/* Line 193 of yacc.c. */
-#line 187 "y.tab.c"
+#line 183 "y.tab.c"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
/* Line 216 of yacc.c. */
-#line 200 "y.tab.c"
+#line 196 "y.tab.c"
#ifdef short
# undef short
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 2
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 561
+#define YYLAST 544
/* YYNTOKENS -- Number of terminals. */
#define YYNTOKENS 54
/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 40
+#define YYNNTS 39
/* YYNRULES -- Number of rules. */
-#define YYNRULES 132
+#define YYNRULES 131
/* YYNRULES -- Number of states. */
#define YYNSTATES 270
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 52, 12, 5, 2,
- 50, 51, 10, 8, 49, 9, 2, 11, 2, 2,
+ 2, 2, 2, 2, 2, 2, 50, 12, 5, 2,
+ 51, 52, 10, 8, 49, 9, 2, 11, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 46, 47,
6, 48, 7, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
static const yytype_uint16 yyprhs[] =
{
0, 0, 3, 4, 5, 9, 10, 15, 17, 20,
- 23, 27, 31, 34, 37, 40, 43, 46, 49, 52,
- 55, 58, 61, 64, 67, 70, 73, 76, 79, 82,
- 85, 86, 88, 92, 96, 99, 101, 104, 106, 109,
- 111, 115, 121, 125, 131, 134, 136, 139, 141, 143,
- 147, 153, 157, 163, 166, 168, 172, 176, 182, 188,
- 194, 198, 202, 204, 206, 208, 210, 213, 216, 218,
- 220, 222, 224, 226, 231, 234, 236, 238, 240, 242,
- 244, 246, 249, 252, 255, 258, 263, 269, 273, 276,
- 278, 281, 285, 290, 292, 294, 296, 301, 306, 313,
- 323, 333, 337, 341, 346, 352, 361, 363, 370, 376,
- 384, 385, 388, 391, 393, 395, 397, 399, 401, 404,
- 407, 410, 414, 416, 420, 424, 428, 432, 436, 441,
- 446, 450, 454
+ 23, 27, 31, 34, 37, 40, 43, 46, 49, 51,
+ 53, 56, 59, 62, 65, 68, 70, 73, 76, 79,
+ 82, 83, 85, 89, 93, 96, 98, 101, 103, 106,
+ 108, 112, 119, 125, 133, 138, 145, 148, 150, 153,
+ 155, 157, 161, 167, 171, 177, 180, 182, 186, 192,
+ 198, 202, 206, 208, 210, 212, 214, 217, 220, 222,
+ 224, 226, 228, 230, 235, 238, 240, 242, 244, 246,
+ 248, 250, 253, 256, 259, 262, 267, 273, 277, 279,
+ 282, 286, 291, 293, 295, 297, 302, 307, 314, 324,
+ 334, 338, 342, 347, 353, 362, 364, 371, 377, 385,
+ 386, 389, 392, 394, 396, 398, 400, 402, 405, 408,
+ 411, 415, 417, 421, 425, 429, 433, 437, 442, 447,
+ 451, 455
};
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
{
55, 0, -1, -1, -1, 55, 56, 57, -1, -1,
43, 46, 58, 57, -1, 47, -1, 59, 47, -1,
- 1, 47, -1, 43, 48, 93, -1, 45, 48, 93,
+ 1, 47, -1, 43, 48, 92, -1, 45, 48, 92,
-1, 13, 60, -1, 14, 64, -1, 15, 63, -1,
- 16, 61, -1, 17, 62, -1, 21, 65, -1, 19,
- 66, -1, 22, 67, -1, 18, 68, -1, 20, 69,
- -1, 23, 70, -1, 24, 71, -1, 25, 72, -1,
- 26, 73, -1, 27, 74, -1, 28, 75, -1, 29,
- 76, -1, 30, 77, -1, -1, 49, -1, 80, 49,
- 78, -1, 78, 49, 80, -1, 80, 49, -1, 80,
- -1, 49, 78, -1, 78, -1, 49, 81, -1, 81,
- -1, 83, 49, 81, -1, 89, 11, 92, 49, 83,
- -1, 86, 49, 84, -1, 86, 49, 92, 49, 84,
- -1, 49, 79, -1, 79, -1, 10, 89, -1, 60,
- -1, 64, -1, 80, 49, 78, -1, 80, 49, 78,
- 46, 36, -1, 80, 49, 78, -1, 80, 49, 78,
- 46, 37, -1, 80, 49, -1, 80, -1, 80, 49,
- 78, -1, 86, 49, 83, -1, 86, 49, 92, 49,
- 83, -1, 82, 49, 78, 49, 92, -1, 83, 49,
- 78, 49, 82, -1, 80, 49, 80, -1, 80, 49,
- 80, -1, 82, -1, 86, -1, 81, -1, 88, -1,
- 10, 82, -1, 10, 87, -1, 82, -1, 87, -1,
- 83, -1, 78, -1, 83, -1, 92, 50, 33, 51,
- -1, 43, 90, -1, 35, -1, 38, -1, 36, -1,
- 39, -1, 42, -1, 37, -1, 52, 92, -1, 52,
- 89, -1, 52, 41, -1, 52, 40, -1, 52, 50,
- 40, 51, -1, 52, 50, 9, 40, 51, -1, 52,
- 9, 40, -1, 52, 85, -1, 31, -1, 9, 31,
- -1, 31, 9, 31, -1, 9, 31, 9, 31, -1,
- 87, -1, 88, -1, 92, -1, 92, 50, 36, 51,
- -1, 92, 50, 42, 51, -1, 92, 50, 36, 10,
- 92, 51, -1, 92, 50, 36, 51, 50, 36, 10,
- 92, 51, -1, 92, 50, 36, 51, 50, 37, 10,
- 92, 51, -1, 50, 36, 51, -1, 50, 42, 51,
- -1, 92, 50, 37, 51, -1, 50, 36, 10, 92,
- 51, -1, 50, 36, 51, 50, 36, 10, 92, 51,
- -1, 89, -1, 89, 50, 36, 10, 92, 51, -1,
- 43, 90, 50, 91, 51, -1, 43, 6, 7, 90,
- 50, 34, 51, -1, -1, 8, 92, -1, 9, 92,
- -1, 34, -1, 42, -1, 32, -1, 31, -1, 45,
- -1, 9, 92, -1, 8, 92, -1, 53, 92, -1,
- 50, 93, 51, -1, 92, -1, 93, 8, 93, -1,
- 93, 9, 93, -1, 93, 10, 93, -1, 93, 11,
- 93, -1, 93, 12, 93, -1, 93, 6, 6, 93,
- -1, 93, 7, 7, 93, -1, 93, 5, 93, -1,
- 93, 4, 93, -1, 93, 3, 93, -1
+ 16, 61, -1, 17, 62, -1, 21, 65, -1, 66,
+ -1, 67, -1, 18, 69, -1, 20, 70, -1, 23,
+ 71, -1, 24, 72, -1, 25, 73, -1, 68, -1,
+ 27, 74, -1, 28, 75, -1, 29, 76, -1, 30,
+ 77, -1, -1, 49, -1, 80, 49, 78, -1, 78,
+ 49, 80, -1, 80, 49, -1, 80, -1, 49, 78,
+ -1, 78, -1, 49, 81, -1, 81, -1, 83, 49,
+ 81, -1, 19, 88, 11, 91, 49, 83, -1, 22,
+ 85, 49, 50, 84, -1, 22, 85, 49, 91, 49,
+ 50, 84, -1, 26, 85, 49, 83, -1, 26, 85,
+ 49, 91, 49, 83, -1, 49, 79, -1, 79, -1,
+ 10, 88, -1, 60, -1, 64, -1, 80, 49, 78,
+ -1, 80, 49, 78, 46, 36, -1, 80, 49, 78,
+ -1, 80, 49, 78, 46, 37, -1, 80, 49, -1,
+ 80, -1, 80, 49, 78, -1, 82, 49, 78, 49,
+ 91, -1, 83, 49, 78, 49, 82, -1, 80, 49,
+ 80, -1, 80, 49, 80, -1, 82, -1, 85, -1,
+ 81, -1, 87, -1, 10, 82, -1, 10, 86, -1,
+ 82, -1, 86, -1, 83, -1, 78, -1, 83, -1,
+ 91, 51, 33, 52, -1, 43, 89, -1, 35, -1,
+ 38, -1, 36, -1, 39, -1, 42, -1, 37, -1,
+ 50, 91, -1, 50, 88, -1, 50, 41, -1, 50,
+ 40, -1, 50, 51, 40, 52, -1, 50, 51, 9,
+ 40, 52, -1, 50, 9, 40, -1, 31, -1, 9,
+ 31, -1, 31, 9, 31, -1, 9, 31, 9, 31,
+ -1, 86, -1, 87, -1, 91, -1, 91, 51, 36,
+ 52, -1, 91, 51, 42, 52, -1, 91, 51, 36,
+ 10, 91, 52, -1, 91, 51, 36, 52, 51, 36,
+ 10, 91, 52, -1, 91, 51, 36, 52, 51, 37,
+ 10, 91, 52, -1, 51, 36, 52, -1, 51, 42,
+ 52, -1, 91, 51, 37, 52, -1, 51, 36, 10,
+ 91, 52, -1, 51, 36, 52, 51, 36, 10, 91,
+ 52, -1, 88, -1, 88, 51, 36, 10, 91, 52,
+ -1, 43, 89, 51, 90, 52, -1, 43, 6, 7,
+ 89, 51, 34, 52, -1, -1, 8, 91, -1, 9,
+ 91, -1, 34, -1, 42, -1, 32, -1, 31, -1,
+ 45, -1, 9, 91, -1, 8, 91, -1, 53, 91,
+ -1, 51, 92, 52, -1, 91, -1, 92, 8, 92,
+ -1, 92, 9, 92, -1, 92, 10, 92, -1, 92,
+ 11, 92, -1, 92, 12, 92, -1, 92, 6, 6,
+ 92, -1, 92, 7, 7, 92, -1, 92, 5, 92,
+ -1, 92, 4, 92, -1, 92, 3, 92, -1
};
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
- 0, 69, 69, 71, 70, 78, 77, 86, 87, 88,
- 91, 96, 102, 103, 104, 105, 106, 107, 108, 109,
- 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
- 122, 126, 133, 140, 147, 152, 159, 164, 171, 176,
- 181, 188, 196, 202, 211, 216, 221, 230, 231, 234,
- 239, 249, 254, 264, 269, 274, 281, 286, 294, 302,
- 312, 321, 332, 333, 336, 337, 338, 342, 346, 347,
- 348, 351, 352, 355, 361, 372, 377, 382, 387, 392,
- 397, 404, 410, 421, 427, 433, 439, 445, 453, 462,
- 467, 472, 477, 484, 485, 488, 494, 500, 506, 515,
- 524, 533, 538, 543, 549, 557, 567, 571, 580, 587,
- 596, 599, 603, 609, 610, 614, 617, 618, 622, 626,
- 630, 634, 640, 641, 645, 649, 653, 657, 661, 665,
- 669, 673, 677
+ 0, 64, 64, 66, 65, 73, 72, 81, 82, 83,
+ 86, 91, 97, 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
+ 117, 121, 128, 135, 142, 147, 154, 159, 166, 171,
+ 176, 183, 196, 204, 218, 226, 240, 245, 250, 258,
+ 259, 262, 267, 277, 282, 292, 297, 302, 309, 317,
+ 327, 336, 347, 348, 351, 352, 353, 357, 361, 362,
+ 363, 366, 367, 370, 376, 387, 393, 399, 405, 411,
+ 417, 425, 431, 441, 447, 453, 459, 465, 473, 480,
+ 487, 494, 503, 504, 507, 514, 521, 528, 538, 548,
+ 558, 564, 570, 577, 586, 597, 601, 610, 618, 628,
+ 631, 635, 641, 642, 646, 649, 650, 654, 658, 662,
+ 666, 672, 673, 677, 681, 685, 689, 693, 697, 701,
+ 705, 709
};
#endif
"LTYPEM", "LTYPEI", "LTYPEG", "LTYPEXC", "LTYPEX", "LTYPEPC", "LTYPEF",
"LCONST", "LFP", "LPC", "LSB", "LBREG", "LLREG", "LSREG", "LFREG",
"LXREG", "LFCONST", "LSCONST", "LSP", "LNAME", "LLAB", "LVAR", "':'",
- "';'", "'='", "','", "'('", "')'", "'$'", "'~'", "$accept", "prog", "@1",
+ "';'", "'='", "','", "'$'", "'('", "')'", "'~'", "$accept", "prog", "@1",
"line", "@2", "inst", "nonnon", "rimrem", "remrim", "rimnon", "nonrem",
- "nonrel", "spec1", "spec2", "spec3", "spec4", "spec5", "spec6", "spec7",
- "spec8", "spec9", "spec10", "spec11", "spec12", "rem", "rom", "rim",
- "rel", "reg", "imm", "imm2", "con2", "mem", "omem", "nmem", "nam",
- "offset", "pointer", "con", "expr", 0
+ "nonrel", "spec1", "spec2", "spec8", "spec3", "spec4", "spec5", "spec6",
+ "spec7", "spec9", "spec10", "spec11", "spec12", "rem", "rom", "rim",
+ "rel", "reg", "imm", "textsize", "mem", "omem", "nmem", "nam", "offset",
+ "pointer", "con", "expr", 0
};
#endif
265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
285, 286, 287, 288, 289, 290, 58, 59, 61, 44,
- 40, 41, 36, 126
+ 36, 40, 41, 126
};
# endif
59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
60, 60, 61, 62, 63, 63, 64, 64, 65, 65,
- 65, 66, 67, 67, 68, 68, 68, 69, 69, 70,
- 70, 71, 71, 72, 72, 72, 73, 73, 74, 75,
+ 65, 66, 67, 67, 68, 68, 69, 69, 69, 70,
+ 70, 71, 71, 72, 72, 73, 73, 73, 74, 75,
76, 77, 78, 78, 79, 79, 79, 79, 79, 79,
79, 80, 80, 81, 81, 82, 82, 82, 82, 82,
- 82, 83, 83, 83, 83, 83, 83, 83, 84, 85,
- 85, 85, 85, 86, 86, 87, 87, 87, 87, 87,
- 87, 87, 87, 87, 87, 87, 88, 88, 89, 89,
- 90, 90, 90, 91, 91, 91, 92, 92, 92, 92,
- 92, 92, 93, 93, 93, 93, 93, 93, 93, 93,
- 93, 93, 93
+ 82, 83, 83, 83, 83, 83, 83, 83, 84, 84,
+ 84, 84, 85, 85, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 87, 87, 88, 88, 89,
+ 89, 89, 90, 90, 90, 91, 91, 91, 91, 91,
+ 91, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
static const yytype_uint8 yyr2[] =
{
0, 2, 0, 0, 3, 0, 4, 1, 2, 2,
- 3, 3, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 2, 2, 2, 2, 2, 2, 1, 1,
+ 2, 2, 2, 2, 2, 1, 2, 2, 2, 2,
0, 1, 3, 3, 2, 1, 2, 1, 2, 1,
- 3, 5, 3, 5, 2, 1, 2, 1, 1, 3,
- 5, 3, 5, 2, 1, 3, 3, 5, 5, 5,
+ 3, 6, 5, 7, 4, 6, 2, 1, 2, 1,
+ 1, 3, 5, 3, 5, 2, 1, 3, 5, 5,
3, 3, 1, 1, 1, 1, 2, 2, 1, 1,
1, 1, 1, 4, 2, 1, 1, 1, 1, 1,
- 1, 2, 2, 2, 2, 4, 5, 3, 2, 1,
- 2, 3, 4, 1, 1, 1, 4, 4, 6, 9,
- 9, 3, 3, 4, 5, 8, 1, 6, 5, 7,
- 0, 2, 2, 1, 1, 1, 1, 1, 2, 2,
- 2, 3, 1, 3, 3, 3, 3, 3, 4, 4,
- 3, 3, 3
+ 1, 2, 2, 2, 2, 4, 5, 3, 1, 2,
+ 3, 4, 1, 1, 1, 4, 4, 6, 9, 9,
+ 3, 3, 4, 5, 8, 1, 6, 5, 7, 0,
+ 2, 2, 1, 1, 1, 1, 1, 2, 2, 2,
+ 3, 1, 3, 3, 3, 3, 3, 4, 4, 3,
+ 3, 3
};
/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
{
2, 3, 1, 0, 0, 30, 0, 0, 0, 0,
0, 0, 30, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 7, 4, 0, 9, 31,
- 12, 0, 0, 116, 75, 77, 80, 76, 78, 79,
- 110, 117, 0, 0, 0, 13, 37, 62, 63, 93,
- 94, 106, 95, 0, 14, 71, 35, 72, 15, 0,
- 16, 0, 0, 110, 0, 20, 45, 64, 68, 70,
- 69, 65, 95, 18, 0, 31, 47, 48, 21, 110,
- 0, 0, 17, 39, 0, 0, 19, 0, 22, 0,
- 23, 0, 24, 54, 25, 0, 26, 0, 27, 0,
- 28, 0, 29, 0, 5, 0, 0, 8, 119, 118,
- 0, 0, 0, 0, 36, 0, 0, 122, 0, 120,
+ 0, 0, 0, 0, 0, 7, 4, 0, 18, 19,
+ 25, 9, 31, 12, 0, 0, 115, 75, 77, 80,
+ 76, 78, 79, 109, 116, 0, 0, 0, 13, 37,
+ 62, 63, 92, 93, 105, 94, 0, 14, 71, 35,
+ 72, 15, 0, 16, 0, 0, 109, 0, 20, 47,
+ 64, 68, 70, 69, 65, 94, 0, 31, 49, 50,
+ 21, 109, 0, 0, 17, 39, 0, 0, 0, 22,
+ 0, 23, 0, 24, 56, 0, 26, 0, 27, 0,
+ 28, 0, 29, 0, 5, 0, 0, 8, 118, 117,
+ 0, 0, 0, 0, 36, 0, 0, 121, 0, 119,
0, 0, 0, 84, 83, 0, 82, 81, 34, 0,
- 0, 66, 67, 46, 74, 0, 44, 0, 0, 74,
- 38, 0, 0, 0, 0, 0, 53, 0, 0, 0,
- 0, 0, 0, 10, 11, 110, 111, 112, 0, 0,
- 101, 102, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 121, 0, 0, 0, 0, 87, 0, 0,
- 32, 33, 0, 0, 40, 0, 42, 0, 49, 51,
- 55, 56, 0, 0, 0, 60, 61, 6, 0, 115,
- 113, 114, 0, 0, 0, 132, 131, 130, 0, 0,
- 123, 124, 125, 126, 127, 0, 0, 96, 103, 97,
- 0, 85, 73, 0, 0, 89, 88, 0, 0, 0,
- 0, 0, 0, 0, 108, 104, 0, 128, 129, 0,
- 0, 0, 86, 41, 90, 0, 43, 50, 52, 57,
- 58, 59, 0, 0, 107, 98, 0, 0, 0, 91,
- 109, 0, 0, 0, 92, 105, 0, 0, 99, 100
+ 0, 66, 67, 48, 74, 0, 46, 0, 0, 74,
+ 38, 0, 0, 0, 0, 0, 55, 0, 0, 0,
+ 0, 0, 0, 10, 11, 109, 110, 111, 0, 0,
+ 100, 101, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 120, 0, 0, 0, 0, 87, 0, 0,
+ 32, 33, 0, 0, 40, 0, 0, 51, 53, 57,
+ 44, 0, 0, 0, 60, 61, 6, 0, 114, 112,
+ 113, 0, 0, 0, 131, 130, 129, 0, 0, 122,
+ 123, 124, 125, 126, 0, 0, 95, 102, 96, 0,
+ 85, 73, 0, 0, 88, 42, 0, 0, 0, 0,
+ 0, 0, 0, 107, 103, 0, 127, 128, 0, 0,
+ 0, 86, 41, 89, 0, 0, 52, 54, 45, 58,
+ 59, 0, 0, 106, 97, 0, 0, 0, 90, 43,
+ 108, 0, 0, 0, 91, 104, 0, 0, 98, 99
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int16 yydefgoto[] =
{
- -1, 1, 3, 26, 152, 27, 30, 58, 60, 54,
- 45, 82, 73, 86, 65, 78, 88, 90, 92, 94,
- 96, 98, 100, 102, 55, 66, 56, 67, 47, 57,
- 186, 226, 48, 49, 50, 51, 113, 202, 52, 118
+ -1, 1, 3, 26, 152, 27, 33, 61, 63, 57,
+ 48, 84, 28, 29, 30, 68, 80, 89, 91, 93,
+ 96, 98, 100, 102, 58, 69, 59, 70, 50, 60,
+ 225, 51, 52, 53, 54, 113, 201, 55, 118
};
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
-#define YYPACT_NINF -89
+#define YYPACT_NINF -87
static const yytype_int16 yypact[] =
{
- -89, 8, -89, 211, -33, -23, 288, 308, 308, 360,
- 236, -11, 340, 54, 41, 308, 308, 308, 41, 106,
- -13, 308, 308, 62, -4, -89, -89, 45, -89, -89,
- -89, 484, 484, -89, -89, -89, -89, -89, -89, -89,
- 81, -89, 360, 413, 484, -89, -89, -89, -89, -89,
- -89, 38, 48, 407, -89, -89, -2, -89, -89, 64,
- -89, 78, 360, 81, 256, -89, -89, -89, -89, -89,
- -89, -89, 61, -89, 107, 360, -89, -89, -89, 59,
- 431, 484, -89, -89, 86, 79, -89, 87, -89, 89,
- -89, 91, -89, 97, -89, 102, -89, 116, -89, 120,
- -89, 148, -89, 151, -89, 484, 484, -89, -89, -89,
- 123, 484, 484, 105, -89, 1, 150, -89, 169, -89,
- 166, 9, 69, -89, -89, 456, -89, -89, -89, 360,
- 308, -89, -89, -89, 105, 392, -89, -17, 484, -89,
- -89, 431, 170, 460, 360, 360, 360, 469, 360, 360,
- 308, 308, 211, 179, 179, 59, -89, -89, 6, 484,
- 154, -89, 484, 484, 484, 201, 149, 484, 484, 484,
- 484, 484, -89, 198, 13, 158, 159, -89, 480, 160,
- -89, -89, 162, 165, -89, 0, -89, 167, 171, 172,
- -89, -89, 193, 199, 200, -89, -89, -89, 197, -89,
- -89, -89, 168, 204, 214, 534, 542, 549, 484, 484,
- 113, 113, -89, -89, -89, 484, 484, 207, -89, -89,
- 208, -89, -89, -13, 220, 251, -89, 209, 226, 231,
- -13, 484, 106, 229, -89, -89, 259, 184, 184, 219,
- 225, 80, -89, -89, 268, 249, -89, -89, -89, -89,
- -89, -89, 232, 484, -89, -89, 272, 274, 269, -89,
- -89, 239, 484, 484, -89, -89, 252, 253, -89, -89
+ -87, 35, -87, 242, 2, -4, 164, 313, 313, 361,
+ 265, 8, 337, 60, 410, 313, 313, 313, 410, 241,
+ -11, 313, 313, -31, 17, -87, -87, 23, -87, -87,
+ -87, -87, -87, -87, 474, 474, -87, -87, -87, -87,
+ -87, -87, -87, 20, -87, 361, 401, 474, -87, -87,
+ -87, -87, -87, -87, 16, 28, 185, -87, -87, 22,
+ -87, -87, 25, -87, 31, 361, 20, 289, -87, -87,
+ -87, -87, -87, -87, -87, 48, 29, 361, -87, -87,
+ -87, 13, 417, 474, -87, -87, 51, 53, 57, -87,
+ 58, -87, 59, -87, 70, 71, -87, 75, -87, 80,
+ -87, 86, -87, 102, -87, 474, 474, -87, -87, -87,
+ 37, 474, 474, 76, -87, 1, 103, -87, 175, -87,
+ 126, 50, 85, -87, -87, 426, -87, -87, -87, 361,
+ 313, -87, -87, -87, 76, 385, -87, 81, 474, -87,
+ -87, 417, 130, 436, 361, 361, 361, 464, 361, 361,
+ 313, 313, 242, 525, 525, 13, -87, -87, 18, 474,
+ 113, -87, 474, 474, 474, 165, 167, 474, 474, 474,
+ 474, 474, -87, 186, 3, 123, 156, -87, 467, 158,
+ -87, -87, 159, 163, -87, 7, 169, 173, 177, -87,
+ -87, 182, 183, 184, -87, -87, -87, 178, -87, -87,
+ -87, 172, 187, 198, 136, 239, 532, 474, 474, 78,
+ 78, -87, -87, -87, 474, 474, 189, -87, -87, 202,
+ -87, -87, -11, 204, 228, -87, 191, 245, 247, -11,
+ 474, 241, 248, -87, -87, 276, 180, 180, 236, 238,
+ -5, -87, -87, 282, 261, 7, -87, -87, -87, -87,
+ -87, 243, 474, -87, -87, 283, 284, 274, -87, -87,
+ -87, 254, 474, 474, -87, -87, 257, 259, -87, -87
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int16 yypgoto[] =
{
- -89, -89, -89, 153, -89, -89, 290, -89, -89, -89,
- 295, -89, -89, -89, -89, -89, -89, -89, -89, -89,
- -89, -89, -89, -89, 18, 246, 20, -7, -9, -8,
- 84, -89, 51, -3, -6, 4, -50, -89, -10, -88
+ -87, -87, -87, 160, -87, -87, 301, -87, -87, -87,
+ 305, -87, -87, -87, -87, -87, -87, -87, -87, -87,
+ -87, -87, -87, -87, 21, 252, 26, -7, -9, -8,
+ 84, 0, -3, -6, -2, -58, -87, -10, -86
};
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
#define YYTABLE_NINF -1
static const yytype_uint16 yytable[] =
{
- 72, 68, 69, 85, 71, 84, 83, 70, 2, 224,
- 97, 159, 99, 134, 28, 74, 182, 153, 154, 174,
- 175, 108, 109, 216, 46, 176, 29, 61, 59, 139,
- 46, 225, 40, 117, 119, 89, 91, 93, 199, 53,
- 200, 101, 103, 127, 106, 174, 175, 128, 201, 31,
- 32, 176, 160, 131, 72, 68, 69, 126, 71, 132,
- 114, 70, 31, 32, 217, 87, 133, 111, 112, 95,
- 85, 117, 33, 140, 205, 206, 207, 31, 32, 210,
- 211, 212, 213, 214, 40, 33, 41, 110, 120, 111,
- 112, 43, 107, 114, 44, 117, 117, 79, 121, 41,
- 33, 156, 157, 80, 81, 198, 53, 44, 104, 177,
- 105, 137, 109, 129, 41, 117, 256, 257, 138, 81,
- 237, 238, 44, 169, 170, 171, 131, 130, 183, 142,
- 155, 85, 132, 187, 184, 141, 143, 192, 144, 191,
- 145, 34, 35, 36, 37, 38, 146, 180, 39, 203,
- 181, 147, 117, 117, 117, 158, 209, 117, 117, 117,
- 117, 117, 188, 189, 190, 148, 193, 194, 109, 149,
- 195, 196, 162, 163, 164, 165, 166, 167, 168, 169,
- 170, 171, 162, 163, 164, 165, 166, 167, 168, 169,
- 170, 171, 167, 168, 169, 170, 171, 150, 117, 117,
- 151, 161, 173, 182, 204, 239, 240, 208, 215, 218,
- 219, 221, 4, 222, 223, 243, 227, 228, 229, 234,
- 172, 250, 249, 251, 5, 6, 7, 8, 9, 10,
- 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
- 21, 22, 230, 261, 31, 32, 62, 233, 231, 232,
- 236, 244, 266, 267, 23, 235, 24, 241, 25, 242,
- 245, 185, 247, 252, 31, 32, 135, 33, 248, 253,
- 254, 34, 35, 36, 37, 38, 255, 258, 39, 63,
- 259, 41, 262, 260, 263, 64, 43, 33, 53, 44,
- 265, 34, 35, 36, 37, 38, 31, 32, 39, 63,
- 264, 41, 76, 268, 269, 197, 43, 77, 53, 44,
- 136, 246, 0, 0, 0, 0, 31, 32, 0, 33,
- 0, 0, 0, 34, 35, 36, 37, 38, 0, 0,
- 39, 40, 0, 41, 0, 0, 0, 42, 43, 33,
- 0, 44, 0, 34, 35, 36, 37, 38, 31, 32,
- 39, 40, 0, 41, 0, 0, 0, 0, 43, 0,
- 53, 44, 0, 0, 0, 0, 0, 0, 31, 32,
- 0, 33, 0, 0, 0, 34, 35, 36, 37, 38,
- 0, 0, 39, 40, 0, 41, 0, 0, 0, 75,
- 43, 33, 0, 44, 0, 34, 35, 36, 37, 38,
- 31, 32, 39, 40, 0, 41, 0, 0, 0, 0,
- 43, 0, 0, 44, 0, 31, 122, 0, 0, 0,
- 0, 31, 32, 33, 0, 0, 0, 34, 35, 36,
- 37, 38, 0, 0, 39, 0, 0, 41, 33, 31,
- 32, 0, 43, 0, 33, 44, 0, 123, 124, 115,
- 40, 0, 41, 0, 0, 116, 0, 125, 41, 0,
- 44, 0, 33, 81, 31, 178, 44, 0, 31, 32,
- 0, 0, 0, 0, 79, 0, 41, 31, 32, 0,
- 0, 81, 0, 0, 44, 0, 0, 33, 31, 32,
- 0, 33, 31, 32, 0, 0, 179, 0, 0, 0,
- 33, 41, 0, 0, 0, 41, 81, 0, 0, 44,
- 81, 33, 185, 44, 41, 33, 0, 0, 0, 81,
- 220, 53, 44, 0, 0, 41, 0, 0, 0, 41,
- 81, 0, 0, 44, 81, 0, 0, 44, 163, 164,
- 165, 166, 167, 168, 169, 170, 171, 164, 165, 166,
- 167, 168, 169, 170, 171, 165, 166, 167, 168, 169,
- 170, 171
+ 75, 71, 72, 87, 74, 86, 85, 73, 134, 76,
+ 97, 159, 99, 215, 88, 104, 223, 105, 95, 153,
+ 154, 111, 112, 139, 108, 109, 110, 49, 111, 112,
+ 64, 255, 256, 49, 62, 2, 117, 119, 224, 56,
+ 138, 90, 92, 94, 155, 32, 127, 101, 103, 31,
+ 198, 43, 199, 160, 126, 216, 131, 75, 71, 72,
+ 200, 74, 132, 133, 73, 106, 114, 120, 34, 35,
+ 107, 128, 87, 117, 129, 140, 204, 205, 206, 121,
+ 130, 209, 210, 211, 212, 213, 174, 175, 169, 170,
+ 171, 36, 176, 34, 35, 117, 117, 197, 114, 137,
+ 141, 156, 157, 81, 142, 44, 143, 144, 145, 82,
+ 56, 83, 109, 47, 182, 117, 36, 174, 175, 146,
+ 147, 236, 237, 176, 148, 177, 131, 158, 183, 149,
+ 44, 87, 132, 186, 184, 150, 83, 191, 47, 190,
+ 163, 164, 165, 166, 167, 168, 169, 170, 171, 202,
+ 180, 151, 117, 117, 117, 161, 181, 117, 117, 117,
+ 117, 117, 173, 182, 203, 187, 188, 189, 109, 192,
+ 193, 207, 34, 35, 208, 217, 194, 195, 162, 163,
+ 164, 165, 166, 167, 168, 169, 170, 171, 167, 168,
+ 169, 170, 171, 34, 122, 36, 214, 117, 117, 37,
+ 38, 39, 40, 41, 238, 239, 42, 43, 218, 44,
+ 220, 221, 222, 45, 242, 46, 36, 47, 226, 227,
+ 249, 248, 250, 228, 233, 123, 124, 172, 43, 232,
+ 44, 229, 230, 231, 235, 243, 125, 244, 47, 234,
+ 240, 245, 261, 4, 164, 165, 166, 167, 168, 169,
+ 170, 171, 266, 267, 241, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 34, 35, 65, 37, 38, 39, 40,
+ 41, 246, 251, 42, 247, 23, 252, 24, 253, 25,
+ 254, 257, 258, 262, 263, 260, 36, 34, 35, 135,
+ 37, 38, 39, 40, 41, 264, 265, 42, 66, 268,
+ 44, 269, 196, 78, 67, 56, 46, 79, 47, 136,
+ 36, 34, 35, 0, 37, 38, 39, 40, 41, 259,
+ 0, 42, 66, 0, 44, 0, 0, 0, 0, 56,
+ 46, 0, 47, 0, 36, 34, 35, 0, 37, 38,
+ 39, 40, 41, 0, 0, 42, 43, 0, 44, 0,
+ 0, 0, 0, 56, 46, 0, 47, 0, 36, 34,
+ 35, 0, 37, 38, 39, 40, 41, 0, 0, 42,
+ 43, 0, 44, 0, 0, 0, 77, 0, 46, 0,
+ 47, 0, 36, 34, 35, 0, 37, 38, 39, 40,
+ 41, 0, 0, 42, 43, 0, 44, 0, 0, 34,
+ 35, 0, 46, 0, 47, 0, 36, 0, 34, 35,
+ 37, 38, 39, 40, 41, 34, 35, 42, 0, 0,
+ 44, 0, 36, 0, 34, 178, 46, 115, 47, 0,
+ 0, 36, 0, 116, 34, 35, 44, 0, 36, 0,
+ 0, 0, 83, 43, 47, 44, 0, 36, 0, 0,
+ 81, 46, 44, 47, 0, 0, 179, 36, 83, 0,
+ 47, 44, 34, 35, 0, 34, 35, 83, 0, 47,
+ 0, 44, 34, 35, 0, 0, 185, 83, 0, 47,
+ 0, 0, 0, 0, 0, 36, 0, 0, 36, 0,
+ 0, 0, 0, 0, 0, 36, 0, 219, 0, 44,
+ 0, 0, 44, 0, 56, 83, 0, 47, 83, 44,
+ 47, 0, 0, 0, 0, 83, 0, 47, 162, 163,
+ 164, 165, 166, 167, 168, 169, 170, 171, 165, 166,
+ 167, 168, 169, 170, 171
};
static const yytype_int16 yycheck[] =
{
- 10, 10, 10, 13, 10, 13, 13, 10, 0, 9,
- 19, 10, 20, 63, 47, 11, 33, 105, 106, 36,
- 37, 31, 32, 10, 6, 42, 49, 9, 8, 79,
- 12, 31, 43, 43, 44, 15, 16, 17, 32, 52,
- 34, 21, 22, 53, 48, 36, 37, 49, 42, 8,
- 9, 42, 51, 62, 64, 64, 64, 53, 64, 62,
- 42, 64, 8, 9, 51, 14, 62, 8, 9, 18,
- 80, 81, 31, 80, 162, 163, 164, 8, 9, 167,
- 168, 169, 170, 171, 43, 31, 45, 6, 50, 8,
- 9, 50, 47, 75, 53, 105, 106, 43, 50, 45,
- 31, 111, 112, 49, 50, 155, 52, 53, 46, 40,
- 48, 50, 122, 49, 45, 125, 36, 37, 11, 50,
- 208, 209, 53, 10, 11, 12, 135, 49, 138, 50,
- 7, 141, 135, 143, 141, 49, 49, 147, 49, 147,
- 49, 35, 36, 37, 38, 39, 49, 129, 42, 159,
- 130, 49, 162, 163, 164, 50, 7, 167, 168, 169,
- 170, 171, 144, 145, 146, 49, 148, 149, 178, 49,
- 150, 151, 3, 4, 5, 6, 7, 8, 9, 10,
- 11, 12, 3, 4, 5, 6, 7, 8, 9, 10,
- 11, 12, 8, 9, 10, 11, 12, 49, 208, 209,
- 49, 51, 36, 33, 50, 215, 216, 6, 10, 51,
- 51, 51, 1, 51, 49, 223, 49, 46, 46, 51,
- 51, 231, 230, 232, 13, 14, 15, 16, 17, 18,
- 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
- 29, 30, 49, 253, 8, 9, 10, 50, 49, 49,
- 36, 31, 262, 263, 43, 51, 45, 50, 47, 51,
- 9, 52, 36, 34, 8, 9, 10, 31, 37, 10,
- 51, 35, 36, 37, 38, 39, 51, 9, 42, 43,
- 31, 45, 10, 51, 10, 49, 50, 31, 52, 53,
- 51, 35, 36, 37, 38, 39, 8, 9, 42, 43,
- 31, 45, 12, 51, 51, 152, 50, 12, 52, 53,
- 64, 227, -1, -1, -1, -1, 8, 9, -1, 31,
- -1, -1, -1, 35, 36, 37, 38, 39, -1, -1,
- 42, 43, -1, 45, -1, -1, -1, 49, 50, 31,
- -1, 53, -1, 35, 36, 37, 38, 39, 8, 9,
- 42, 43, -1, 45, -1, -1, -1, -1, 50, -1,
- 52, 53, -1, -1, -1, -1, -1, -1, 8, 9,
- -1, 31, -1, -1, -1, 35, 36, 37, 38, 39,
- -1, -1, 42, 43, -1, 45, -1, -1, -1, 49,
- 50, 31, -1, 53, -1, 35, 36, 37, 38, 39,
- 8, 9, 42, 43, -1, 45, -1, -1, -1, -1,
- 50, -1, -1, 53, -1, 8, 9, -1, -1, -1,
- -1, 8, 9, 31, -1, -1, -1, 35, 36, 37,
- 38, 39, -1, -1, 42, -1, -1, 45, 31, 8,
- 9, -1, 50, -1, 31, 53, -1, 40, 41, 36,
- 43, -1, 45, -1, -1, 42, -1, 50, 45, -1,
- 53, -1, 31, 50, 8, 9, 53, -1, 8, 9,
- -1, -1, -1, -1, 43, -1, 45, 8, 9, -1,
- -1, 50, -1, -1, 53, -1, -1, 31, 8, 9,
- -1, 31, 8, 9, -1, -1, 40, -1, -1, -1,
- 31, 45, -1, -1, -1, 45, 50, -1, -1, 53,
- 50, 31, 52, 53, 45, 31, -1, -1, -1, 50,
- 40, 52, 53, -1, -1, 45, -1, -1, -1, 45,
- 50, -1, -1, 53, 50, -1, -1, 53, 4, 5,
- 6, 7, 8, 9, 10, 11, 12, 5, 6, 7,
- 8, 9, 10, 11, 12, 6, 7, 8, 9, 10,
- 11, 12
+ 10, 10, 10, 13, 10, 13, 13, 10, 66, 11,
+ 19, 10, 20, 10, 14, 46, 9, 48, 18, 105,
+ 106, 8, 9, 81, 34, 35, 6, 6, 8, 9,
+ 9, 36, 37, 12, 8, 0, 46, 47, 31, 50,
+ 11, 15, 16, 17, 7, 49, 56, 21, 22, 47,
+ 32, 43, 34, 52, 56, 52, 65, 67, 67, 67,
+ 42, 67, 65, 65, 67, 48, 45, 51, 8, 9,
+ 47, 49, 82, 83, 49, 82, 162, 163, 164, 51,
+ 49, 167, 168, 169, 170, 171, 36, 37, 10, 11,
+ 12, 31, 42, 8, 9, 105, 106, 155, 77, 51,
+ 49, 111, 112, 43, 51, 45, 49, 49, 49, 49,
+ 50, 51, 122, 53, 33, 125, 31, 36, 37, 49,
+ 49, 207, 208, 42, 49, 40, 135, 51, 138, 49,
+ 45, 141, 135, 143, 141, 49, 51, 147, 53, 147,
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 159,
+ 129, 49, 162, 163, 164, 52, 130, 167, 168, 169,
+ 170, 171, 36, 33, 51, 144, 145, 146, 178, 148,
+ 149, 6, 8, 9, 7, 52, 150, 151, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 8, 9,
+ 10, 11, 12, 8, 9, 31, 10, 207, 208, 35,
+ 36, 37, 38, 39, 214, 215, 42, 43, 52, 45,
+ 52, 52, 49, 49, 222, 51, 31, 53, 49, 46,
+ 230, 229, 231, 46, 52, 40, 41, 52, 43, 51,
+ 45, 49, 49, 49, 36, 31, 51, 9, 53, 52,
+ 51, 50, 252, 1, 5, 6, 7, 8, 9, 10,
+ 11, 12, 262, 263, 52, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 8, 9, 10, 35, 36, 37, 38,
+ 39, 36, 34, 42, 37, 43, 10, 45, 52, 47,
+ 52, 9, 31, 10, 10, 52, 31, 8, 9, 10,
+ 35, 36, 37, 38, 39, 31, 52, 42, 43, 52,
+ 45, 52, 152, 12, 49, 50, 51, 12, 53, 67,
+ 31, 8, 9, -1, 35, 36, 37, 38, 39, 245,
+ -1, 42, 43, -1, 45, -1, -1, -1, -1, 50,
+ 51, -1, 53, -1, 31, 8, 9, -1, 35, 36,
+ 37, 38, 39, -1, -1, 42, 43, -1, 45, -1,
+ -1, -1, -1, 50, 51, -1, 53, -1, 31, 8,
+ 9, -1, 35, 36, 37, 38, 39, -1, -1, 42,
+ 43, -1, 45, -1, -1, -1, 49, -1, 51, -1,
+ 53, -1, 31, 8, 9, -1, 35, 36, 37, 38,
+ 39, -1, -1, 42, 43, -1, 45, -1, -1, 8,
+ 9, -1, 51, -1, 53, -1, 31, -1, 8, 9,
+ 35, 36, 37, 38, 39, 8, 9, 42, -1, -1,
+ 45, -1, 31, -1, 8, 9, 51, 36, 53, -1,
+ -1, 31, -1, 42, 8, 9, 45, -1, 31, -1,
+ -1, -1, 51, 43, 53, 45, -1, 31, -1, -1,
+ 43, 51, 45, 53, -1, -1, 40, 31, 51, -1,
+ 53, 45, 8, 9, -1, 8, 9, 51, -1, 53,
+ -1, 45, 8, 9, -1, -1, 50, 51, -1, 53,
+ -1, -1, -1, -1, -1, 31, -1, -1, 31, -1,
+ -1, -1, -1, -1, -1, 31, -1, 40, -1, 45,
+ -1, -1, 45, -1, 50, 51, -1, 53, 51, 45,
+ 53, -1, -1, -1, -1, 51, -1, 53, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 6, 7,
+ 8, 9, 10, 11, 12
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
{
0, 55, 0, 56, 1, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
- 28, 29, 30, 43, 45, 47, 57, 59, 47, 49,
- 60, 8, 9, 31, 35, 36, 37, 38, 39, 42,
- 43, 45, 49, 50, 53, 64, 78, 82, 86, 87,
- 88, 89, 92, 52, 63, 78, 80, 83, 61, 80,
- 62, 78, 10, 43, 49, 68, 79, 81, 82, 83,
- 87, 88, 92, 66, 89, 49, 60, 64, 69, 43,
- 49, 50, 65, 81, 83, 92, 67, 86, 70, 80,
- 71, 80, 72, 80, 73, 86, 74, 82, 75, 83,
- 76, 80, 77, 80, 46, 48, 48, 47, 92, 92,
- 6, 8, 9, 90, 78, 36, 42, 92, 93, 92,
- 50, 50, 9, 40, 41, 50, 89, 92, 49, 49,
- 49, 82, 87, 89, 90, 10, 79, 50, 11, 90,
- 81, 49, 50, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 58, 93, 93, 7, 92, 92, 50, 10,
- 51, 51, 3, 4, 5, 6, 7, 8, 9, 10,
- 11, 12, 51, 36, 36, 37, 42, 40, 9, 40,
- 78, 80, 33, 92, 81, 52, 84, 92, 78, 78,
- 78, 83, 92, 78, 78, 80, 80, 57, 90, 32,
- 34, 42, 91, 92, 50, 93, 93, 93, 6, 7,
- 93, 93, 93, 93, 93, 10, 10, 51, 51, 51,
- 40, 51, 51, 49, 9, 31, 85, 49, 46, 46,
- 49, 49, 49, 50, 51, 51, 36, 93, 93, 92,
- 92, 50, 51, 83, 31, 9, 84, 36, 37, 83,
- 92, 82, 34, 10, 51, 51, 36, 37, 9, 31,
- 51, 92, 10, 10, 31, 51, 92, 92, 51, 51
+ 28, 29, 30, 43, 45, 47, 57, 59, 66, 67,
+ 68, 47, 49, 60, 8, 9, 31, 35, 36, 37,
+ 38, 39, 42, 43, 45, 49, 51, 53, 64, 78,
+ 82, 85, 86, 87, 88, 91, 50, 63, 78, 80,
+ 83, 61, 80, 62, 78, 10, 43, 49, 69, 79,
+ 81, 82, 83, 86, 87, 91, 88, 49, 60, 64,
+ 70, 43, 49, 51, 65, 81, 83, 91, 85, 71,
+ 80, 72, 80, 73, 80, 85, 74, 82, 75, 83,
+ 76, 80, 77, 80, 46, 48, 48, 47, 91, 91,
+ 6, 8, 9, 89, 78, 36, 42, 91, 92, 91,
+ 51, 51, 9, 40, 41, 51, 88, 91, 49, 49,
+ 49, 82, 86, 88, 89, 10, 79, 51, 11, 89,
+ 81, 49, 51, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 58, 92, 92, 7, 91, 91, 51, 10,
+ 52, 52, 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 52, 36, 36, 37, 42, 40, 9, 40,
+ 78, 80, 33, 91, 81, 50, 91, 78, 78, 78,
+ 83, 91, 78, 78, 80, 80, 57, 89, 32, 34,
+ 42, 90, 91, 51, 92, 92, 92, 6, 7, 92,
+ 92, 92, 92, 92, 10, 10, 52, 52, 52, 40,
+ 52, 52, 49, 9, 31, 84, 49, 46, 46, 49,
+ 49, 49, 51, 52, 52, 36, 92, 92, 91, 91,
+ 51, 52, 83, 31, 9, 50, 36, 37, 83, 91,
+ 82, 34, 10, 52, 52, 36, 37, 9, 31, 84,
+ 52, 91, 10, 10, 31, 52, 91, 91, 52, 52
};
#define yyerrok (yyerrstatus = 0)
switch (yyn)
{
case 3:
-#line 71 "a.y"
+#line 66 "a.y"
{
stmtline = lineno;
}
break;
case 5:
-#line 78 "a.y"
+#line 73 "a.y"
{
(yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym));
if((yyvsp[(1) - (2)].sym)->type == LLAB && (yyvsp[(1) - (2)].sym)->value != pc)
break;
case 10:
-#line 92 "a.y"
+#line 87 "a.y"
{
(yyvsp[(1) - (3)].sym)->type = LVAR;
(yyvsp[(1) - (3)].sym)->value = (yyvsp[(3) - (3)].lval);
break;
case 11:
-#line 97 "a.y"
+#line 92 "a.y"
{
if((yyvsp[(1) - (3)].sym)->value != (yyvsp[(3) - (3)].lval))
yyerror("redeclaration of %s", (yyvsp[(1) - (3)].sym)->name);
break;
case 12:
-#line 102 "a.y"
+#line 97 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
break;
case 13:
-#line 103 "a.y"
+#line 98 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
break;
case 14:
-#line 104 "a.y"
+#line 99 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
break;
case 15:
-#line 105 "a.y"
+#line 100 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
break;
case 16:
-#line 106 "a.y"
+#line 101 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
break;
case 17:
-#line 107 "a.y"
- { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
- break;
-
- case 18:
-#line 108 "a.y"
- { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
- break;
-
- case 19:
-#line 109 "a.y"
+#line 102 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
break;
case 20:
-#line 110 "a.y"
+#line 105 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
break;
case 21:
-#line 111 "a.y"
+#line 106 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
break;
case 22:
-#line 112 "a.y"
+#line 107 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
break;
case 23:
-#line 113 "a.y"
+#line 108 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
break;
case 24:
-#line 114 "a.y"
- { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
- break;
-
- case 25:
-#line 115 "a.y"
+#line 109 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
break;
case 26:
-#line 116 "a.y"
+#line 111 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
break;
case 27:
-#line 117 "a.y"
+#line 112 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
break;
case 28:
-#line 118 "a.y"
+#line 113 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
break;
case 29:
-#line 119 "a.y"
+#line 114 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
break;
case 30:
-#line 122 "a.y"
+#line 117 "a.y"
{
(yyval.addr2).from = nullgen;
(yyval.addr2).to = nullgen;
break;
case 31:
-#line 127 "a.y"
+#line 122 "a.y"
{
(yyval.addr2).from = nullgen;
(yyval.addr2).to = nullgen;
break;
case 32:
-#line 134 "a.y"
+#line 129 "a.y"
{
(yyval.addr2).from = (yyvsp[(1) - (3)].addr);
(yyval.addr2).to = (yyvsp[(3) - (3)].addr);
break;
case 33:
-#line 141 "a.y"
+#line 136 "a.y"
{
(yyval.addr2).from = (yyvsp[(1) - (3)].addr);
(yyval.addr2).to = (yyvsp[(3) - (3)].addr);
break;
case 34:
-#line 148 "a.y"
+#line 143 "a.y"
{
(yyval.addr2).from = (yyvsp[(1) - (2)].addr);
(yyval.addr2).to = nullgen;
break;
case 35:
-#line 153 "a.y"
+#line 148 "a.y"
{
(yyval.addr2).from = (yyvsp[(1) - (1)].addr);
(yyval.addr2).to = nullgen;
break;
case 36:
-#line 160 "a.y"
+#line 155 "a.y"
{
(yyval.addr2).from = nullgen;
(yyval.addr2).to = (yyvsp[(2) - (2)].addr);
break;
case 37:
-#line 165 "a.y"
+#line 160 "a.y"
{
(yyval.addr2).from = nullgen;
(yyval.addr2).to = (yyvsp[(1) - (1)].addr);
break;
case 38:
-#line 172 "a.y"
+#line 167 "a.y"
{
(yyval.addr2).from = nullgen;
(yyval.addr2).to = (yyvsp[(2) - (2)].addr);
break;
case 39:
-#line 177 "a.y"
+#line 172 "a.y"
{
(yyval.addr2).from = nullgen;
(yyval.addr2).to = (yyvsp[(1) - (1)].addr);
break;
case 40:
-#line 182 "a.y"
+#line 177 "a.y"
{
(yyval.addr2).from = (yyvsp[(1) - (3)].addr);
(yyval.addr2).to = (yyvsp[(3) - (3)].addr);
break;
case 41:
-#line 189 "a.y"
- {
- (yyval.addr2).from = (yyvsp[(1) - (5)].addr);
- (yyval.addr2).from.scale = (yyvsp[(3) - (5)].lval);
- (yyval.addr2).to = (yyvsp[(5) - (5)].addr);
+#line 184 "a.y"
+ {
+ Addr2 a;
+ a.from = (yyvsp[(2) - (6)].addr);
+ a.to = (yyvsp[(6) - (6)].addr);
+ outcode(ADATA, &a);
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = (yyvsp[(4) - (6)].lval);
+ }
}
break;
case 42:
#line 197 "a.y"
{
- settext((yyvsp[(1) - (3)].addr).sym);
- (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
- (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
+ Addr2 a;
+ settext((yyvsp[(2) - (5)].addr).sym);
+ a.from = (yyvsp[(2) - (5)].addr);
+ a.to = (yyvsp[(5) - (5)].addr);
+ outcode(ATEXT, &a);
}
break;
case 43:
-#line 203 "a.y"
- {
- settext((yyvsp[(1) - (5)].addr).sym);
- (yyval.addr2).from = (yyvsp[(1) - (5)].addr);
- (yyval.addr2).from.scale = (yyvsp[(3) - (5)].lval);
- (yyval.addr2).to = (yyvsp[(5) - (5)].addr);
+#line 205 "a.y"
+ {
+ Addr2 a;
+ settext((yyvsp[(2) - (7)].addr).sym);
+ a.from = (yyvsp[(2) - (7)].addr);
+ a.to = (yyvsp[(7) - (7)].addr);
+ outcode(ATEXT, &a);
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = (yyvsp[(4) - (7)].lval);
+ }
}
break;
case 44:
-#line 212 "a.y"
+#line 219 "a.y"
+ {
+ Addr2 a;
+ settext((yyvsp[(2) - (4)].addr).sym);
+ a.from = (yyvsp[(2) - (4)].addr);
+ a.to = (yyvsp[(4) - (4)].addr);
+ outcode(AGLOBL, &a);
+ }
+ break;
+
+ case 45:
+#line 227 "a.y"
+ {
+ Addr2 a;
+ settext((yyvsp[(2) - (6)].addr).sym);
+ a.from = (yyvsp[(2) - (6)].addr);
+ a.to = (yyvsp[(6) - (6)].addr);
+ outcode(AGLOBL, &a);
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = (yyvsp[(4) - (6)].lval);
+ }
+ }
+ break;
+
+ case 46:
+#line 241 "a.y"
{
(yyval.addr2).from = nullgen;
(yyval.addr2).to = (yyvsp[(2) - (2)].addr);
}
break;
- case 45:
-#line 217 "a.y"
+ case 47:
+#line 246 "a.y"
{
(yyval.addr2).from = nullgen;
(yyval.addr2).to = (yyvsp[(1) - (1)].addr);
}
break;
- case 46:
-#line 222 "a.y"
+ case 48:
+#line 251 "a.y"
{
(yyval.addr2).from = nullgen;
(yyval.addr2).to = (yyvsp[(2) - (2)].addr);
- (yyval.addr2).to.index = (yyvsp[(2) - (2)].addr).type;
- (yyval.addr2).to.type = D_INDIR+D_ADDR;
+ (yyval.addr2).to.type = TYPE_INDIR;
}
break;
- case 49:
-#line 235 "a.y"
+ case 51:
+#line 263 "a.y"
{
(yyval.addr2).from = (yyvsp[(1) - (3)].addr);
(yyval.addr2).to = (yyvsp[(3) - (3)].addr);
}
break;
- case 50:
-#line 240 "a.y"
+ case 52:
+#line 268 "a.y"
{
(yyval.addr2).from = (yyvsp[(1) - (5)].addr);
(yyval.addr2).to = (yyvsp[(3) - (5)].addr);
- if((yyval.addr2).from.index != D_NONE)
+ if((yyval.addr2).from.index != TYPE_NONE)
yyerror("dp shift with lhs index");
(yyval.addr2).from.index = (yyvsp[(5) - (5)].lval);
}
break;
- case 51:
-#line 250 "a.y"
+ case 53:
+#line 278 "a.y"
{
(yyval.addr2).from = (yyvsp[(1) - (3)].addr);
(yyval.addr2).to = (yyvsp[(3) - (3)].addr);
}
break;
- case 52:
-#line 255 "a.y"
+ case 54:
+#line 283 "a.y"
{
(yyval.addr2).from = (yyvsp[(1) - (5)].addr);
(yyval.addr2).to = (yyvsp[(3) - (5)].addr);
- if((yyval.addr2).to.index != D_NONE)
+ if((yyval.addr2).to.index != TYPE_NONE)
yyerror("dp move with lhs index");
(yyval.addr2).to.index = (yyvsp[(5) - (5)].lval);
}
break;
- case 53:
-#line 265 "a.y"
+ case 55:
+#line 293 "a.y"
{
(yyval.addr2).from = (yyvsp[(1) - (2)].addr);
(yyval.addr2).to = nullgen;
}
break;
- case 54:
-#line 270 "a.y"
+ case 56:
+#line 298 "a.y"
{
(yyval.addr2).from = (yyvsp[(1) - (1)].addr);
(yyval.addr2).to = nullgen;
}
break;
- case 55:
-#line 275 "a.y"
- {
- (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
- (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
- }
- break;
-
- case 56:
-#line 282 "a.y"
+ case 57:
+#line 303 "a.y"
{
(yyval.addr2).from = (yyvsp[(1) - (3)].addr);
(yyval.addr2).to = (yyvsp[(3) - (3)].addr);
}
break;
- case 57:
-#line 287 "a.y"
- {
- (yyval.addr2).from = (yyvsp[(1) - (5)].addr);
- (yyval.addr2).from.scale = (yyvsp[(3) - (5)].lval);
- (yyval.addr2).to = (yyvsp[(5) - (5)].addr);
- }
- break;
-
case 58:
-#line 295 "a.y"
+#line 310 "a.y"
{
(yyval.addr2).from = (yyvsp[(1) - (5)].addr);
(yyval.addr2).to = (yyvsp[(3) - (5)].addr);
break;
case 59:
-#line 303 "a.y"
+#line 318 "a.y"
{
(yyval.addr2).from = (yyvsp[(3) - (5)].addr);
(yyval.addr2).to = (yyvsp[(5) - (5)].addr);
- if((yyvsp[(1) - (5)].addr).type != D_CONST)
+ if((yyvsp[(1) - (5)].addr).type != TYPE_CONST)
yyerror("illegal constant");
(yyval.addr2).to.offset = (yyvsp[(1) - (5)].addr).offset;
}
break;
case 60:
-#line 313 "a.y"
+#line 328 "a.y"
{
- if((yyvsp[(1) - (3)].addr).type != D_CONST || (yyvsp[(3) - (3)].addr).type != D_CONST)
+ if((yyvsp[(1) - (3)].addr).type != TYPE_CONST || (yyvsp[(3) - (3)].addr).type != TYPE_CONST)
yyerror("arguments to PCDATA must be integer constants");
(yyval.addr2).from = (yyvsp[(1) - (3)].addr);
(yyval.addr2).to = (yyvsp[(3) - (3)].addr);
break;
case 61:
-#line 322 "a.y"
+#line 337 "a.y"
{
- if((yyvsp[(1) - (3)].addr).type != D_CONST)
+ if((yyvsp[(1) - (3)].addr).type != TYPE_CONST)
yyerror("index for FUNCDATA must be integer constant");
- if((yyvsp[(3) - (3)].addr).type != D_EXTERN && (yyvsp[(3) - (3)].addr).type != D_STATIC)
+ if((yyvsp[(3) - (3)].addr).type != TYPE_MEM || ((yyvsp[(3) - (3)].addr).name != NAME_EXTERN && (yyvsp[(3) - (3)].addr).name != NAME_STATIC))
yyerror("value for FUNCDATA must be symbol reference");
(yyval.addr2).from = (yyvsp[(1) - (3)].addr);
(yyval.addr2).to = (yyvsp[(3) - (3)].addr);
break;
case 66:
-#line 339 "a.y"
+#line 354 "a.y"
{
(yyval.addr) = (yyvsp[(2) - (2)].addr);
}
break;
case 67:
-#line 343 "a.y"
+#line 358 "a.y"
{
(yyval.addr) = (yyvsp[(2) - (2)].addr);
}
break;
case 73:
-#line 356 "a.y"
+#line 371 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_BRANCH;
+ (yyval.addr).type = TYPE_BRANCH;
(yyval.addr).offset = (yyvsp[(1) - (4)].lval) + pc;
}
break;
case 74:
-#line 362 "a.y"
+#line 377 "a.y"
{
(yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym));
(yyval.addr) = nullgen;
if(pass == 2 && (yyvsp[(1) - (2)].sym)->type != LLAB)
yyerror("undefined label: %s", (yyvsp[(1) - (2)].sym)->labelname);
- (yyval.addr).type = D_BRANCH;
+ (yyval.addr).type = TYPE_BRANCH;
(yyval.addr).offset = (yyvsp[(1) - (2)].sym)->value + (yyvsp[(2) - (2)].lval);
}
break;
case 75:
-#line 373 "a.y"
+#line 388 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = (yyvsp[(1) - (1)].lval);
+ (yyval.addr).type = TYPE_REG;
+ (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
}
break;
case 76:
-#line 378 "a.y"
+#line 394 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = (yyvsp[(1) - (1)].lval);
+ (yyval.addr).type = TYPE_REG;
+ (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
}
break;
case 77:
-#line 383 "a.y"
+#line 400 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = (yyvsp[(1) - (1)].lval);
+ (yyval.addr).type = TYPE_REG;
+ (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
}
break;
case 78:
-#line 388 "a.y"
+#line 406 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = (yyvsp[(1) - (1)].lval);
+ (yyval.addr).type = TYPE_REG;
+ (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
}
break;
case 79:
-#line 393 "a.y"
+#line 412 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_SP;
+ (yyval.addr).type = TYPE_REG;
+ (yyval.addr).reg = REG_SP;
}
break;
case 80:
-#line 398 "a.y"
+#line 418 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = (yyvsp[(1) - (1)].lval);
+ (yyval.addr).type = TYPE_REG;
+ (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
}
break;
case 81:
-#line 405 "a.y"
+#line 426 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_CONST;
+ (yyval.addr).type = TYPE_CONST;
(yyval.addr).offset = (yyvsp[(2) - (2)].lval);
}
break;
case 82:
-#line 411 "a.y"
+#line 432 "a.y"
{
(yyval.addr) = (yyvsp[(2) - (2)].addr);
- (yyval.addr).index = (yyvsp[(2) - (2)].addr).type;
- (yyval.addr).type = D_ADDR;
+ (yyval.addr).type = TYPE_ADDR;
/*
- if($2.type == D_AUTO || $2.type == D_PARAM)
+ if($2.name == NAME_AUTO || $2.name == NAME_PARAM)
yyerror("constant cannot be automatic: %s",
$2.sym->name);
*/
break;
case 83:
-#line 422 "a.y"
+#line 442 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_SCONST;
+ (yyval.addr).type = TYPE_SCONST;
memcpy((yyval.addr).u.sval, (yyvsp[(2) - (2)].sval), sizeof((yyval.addr).u.sval));
}
break;
case 84:
-#line 428 "a.y"
+#line 448 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_FCONST;
+ (yyval.addr).type = TYPE_FCONST;
(yyval.addr).u.dval = (yyvsp[(2) - (2)].dval);
}
break;
case 85:
-#line 434 "a.y"
+#line 454 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_FCONST;
+ (yyval.addr).type = TYPE_FCONST;
(yyval.addr).u.dval = (yyvsp[(3) - (4)].dval);
}
break;
case 86:
-#line 440 "a.y"
+#line 460 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_FCONST;
+ (yyval.addr).type = TYPE_FCONST;
(yyval.addr).u.dval = -(yyvsp[(4) - (5)].dval);
}
break;
case 87:
-#line 446 "a.y"
+#line 466 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_FCONST;
+ (yyval.addr).type = TYPE_FCONST;
(yyval.addr).u.dval = -(yyvsp[(3) - (3)].dval);
}
break;
case 88:
-#line 454 "a.y"
+#line 474 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_CONST2;
- (yyval.addr).offset = (yyvsp[(2) - (2)].con2).v1;
- (yyval.addr).offset2 = (yyvsp[(2) - (2)].con2).v2;
+ (yyval.addr).type = TYPE_TEXTSIZE;
+ (yyval.addr).offset = (yyvsp[(1) - (1)].lval);
+ (yyval.addr).u.argsize = ArgsSizeUnknown;
}
break;
case 89:
-#line 463 "a.y"
+#line 481 "a.y"
{
- (yyval.con2).v1 = (yyvsp[(1) - (1)].lval);
- (yyval.con2).v2 = ArgsSizeUnknown;
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = TYPE_TEXTSIZE;
+ (yyval.addr).offset = -(yyvsp[(2) - (2)].lval);
+ (yyval.addr).u.argsize = ArgsSizeUnknown;
}
break;
case 90:
-#line 468 "a.y"
+#line 488 "a.y"
{
- (yyval.con2).v1 = -(yyvsp[(2) - (2)].lval);
- (yyval.con2).v2 = ArgsSizeUnknown;
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = TYPE_TEXTSIZE;
+ (yyval.addr).offset = (yyvsp[(1) - (3)].lval);
+ (yyval.addr).u.argsize = (yyvsp[(3) - (3)].lval);
}
break;
case 91:
-#line 473 "a.y"
- {
- (yyval.con2).v1 = (yyvsp[(1) - (3)].lval);
- (yyval.con2).v2 = (yyvsp[(3) - (3)].lval);
- }
- break;
-
- case 92:
-#line 478 "a.y"
+#line 495 "a.y"
{
- (yyval.con2).v1 = -(yyvsp[(2) - (4)].lval);
- (yyval.con2).v2 = (yyvsp[(4) - (4)].lval);
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = TYPE_TEXTSIZE;
+ (yyval.addr).offset = -(yyvsp[(2) - (4)].lval);
+ (yyval.addr).u.argsize = (yyvsp[(4) - (4)].lval);
}
break;
- case 95:
-#line 489 "a.y"
+ case 94:
+#line 508 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_INDIR+D_NONE;
+ (yyval.addr).type = TYPE_MEM;
+ (yyval.addr).reg = REG_NONE;
(yyval.addr).offset = (yyvsp[(1) - (1)].lval);
}
break;
- case 96:
-#line 495 "a.y"
+ case 95:
+#line 515 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_INDIR+(yyvsp[(3) - (4)].lval);
+ (yyval.addr).type = TYPE_MEM;
+ (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
(yyval.addr).offset = (yyvsp[(1) - (4)].lval);
}
break;
- case 97:
-#line 501 "a.y"
+ case 96:
+#line 522 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_INDIR+D_SP;
+ (yyval.addr).type = TYPE_MEM;
+ (yyval.addr).reg = REG_SP;
(yyval.addr).offset = (yyvsp[(1) - (4)].lval);
}
break;
- case 98:
-#line 507 "a.y"
+ case 97:
+#line 529 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_INDIR+D_NONE;
+ (yyval.addr).type = TYPE_MEM;
+ (yyval.addr).reg = REG_NONE;
(yyval.addr).offset = (yyvsp[(1) - (6)].lval);
(yyval.addr).index = (yyvsp[(3) - (6)].lval);
(yyval.addr).scale = (yyvsp[(5) - (6)].lval);
}
break;
- case 99:
-#line 516 "a.y"
+ case 98:
+#line 539 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_INDIR+(yyvsp[(3) - (9)].lval);
+ (yyval.addr).type = TYPE_MEM;
+ (yyval.addr).reg = (yyvsp[(3) - (9)].lval);
(yyval.addr).offset = (yyvsp[(1) - (9)].lval);
(yyval.addr).index = (yyvsp[(6) - (9)].lval);
(yyval.addr).scale = (yyvsp[(8) - (9)].lval);
}
break;
- case 100:
-#line 525 "a.y"
+ case 99:
+#line 549 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_INDIR+(yyvsp[(3) - (9)].lval);
+ (yyval.addr).type = TYPE_MEM;
+ (yyval.addr).reg = (yyvsp[(3) - (9)].lval);
(yyval.addr).offset = (yyvsp[(1) - (9)].lval);
(yyval.addr).index = (yyvsp[(6) - (9)].lval);
(yyval.addr).scale = (yyvsp[(8) - (9)].lval);
}
break;
- case 101:
-#line 534 "a.y"
+ case 100:
+#line 559 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_INDIR+(yyvsp[(2) - (3)].lval);
+ (yyval.addr).type = TYPE_MEM;
+ (yyval.addr).reg = (yyvsp[(2) - (3)].lval);
}
break;
- case 102:
-#line 539 "a.y"
+ case 101:
+#line 565 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_INDIR+D_SP;
+ (yyval.addr).type = TYPE_MEM;
+ (yyval.addr).reg = REG_SP;
}
break;
- case 103:
-#line 544 "a.y"
+ case 102:
+#line 571 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_INDIR+(yyvsp[(3) - (4)].lval);
+ (yyval.addr).type = TYPE_MEM;
+ (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
(yyval.addr).offset = (yyvsp[(1) - (4)].lval);
}
break;
- case 104:
-#line 550 "a.y"
+ case 103:
+#line 578 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_INDIR+D_NONE;
+ (yyval.addr).type = TYPE_MEM;
+ (yyval.addr).reg = REG_NONE;
(yyval.addr).index = (yyvsp[(2) - (5)].lval);
(yyval.addr).scale = (yyvsp[(4) - (5)].lval);
checkscale((yyval.addr).scale);
}
break;
- case 105:
-#line 558 "a.y"
+ case 104:
+#line 587 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_INDIR+(yyvsp[(2) - (8)].lval);
+ (yyval.addr).type = TYPE_MEM;
+ (yyval.addr).reg = (yyvsp[(2) - (8)].lval);
(yyval.addr).index = (yyvsp[(5) - (8)].lval);
(yyval.addr).scale = (yyvsp[(7) - (8)].lval);
checkscale((yyval.addr).scale);
}
break;
- case 106:
-#line 568 "a.y"
+ case 105:
+#line 598 "a.y"
{
(yyval.addr) = (yyvsp[(1) - (1)].addr);
}
break;
- case 107:
-#line 572 "a.y"
+ case 106:
+#line 602 "a.y"
{
(yyval.addr) = (yyvsp[(1) - (6)].addr);
(yyval.addr).index = (yyvsp[(3) - (6)].lval);
}
break;
- case 108:
-#line 581 "a.y"
+ case 107:
+#line 611 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = (yyvsp[(4) - (5)].lval);
+ (yyval.addr).type = TYPE_MEM;
+ (yyval.addr).name = (yyvsp[(4) - (5)].lval);
(yyval.addr).sym = linklookup(ctxt, (yyvsp[(1) - (5)].sym)->name, 0);
(yyval.addr).offset = (yyvsp[(2) - (5)].lval);
}
break;
- case 109:
-#line 588 "a.y"
+ case 108:
+#line 619 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_STATIC;
+ (yyval.addr).type = TYPE_MEM;
+ (yyval.addr).name = NAME_STATIC;
(yyval.addr).sym = linklookup(ctxt, (yyvsp[(1) - (7)].sym)->name, 1);
(yyval.addr).offset = (yyvsp[(4) - (7)].lval);
}
break;
- case 110:
-#line 596 "a.y"
+ case 109:
+#line 628 "a.y"
{
(yyval.lval) = 0;
}
break;
- case 111:
-#line 600 "a.y"
+ case 110:
+#line 632 "a.y"
{
(yyval.lval) = (yyvsp[(2) - (2)].lval);
}
break;
- case 112:
-#line 604 "a.y"
+ case 111:
+#line 636 "a.y"
{
(yyval.lval) = -(yyvsp[(2) - (2)].lval);
}
break;
- case 114:
-#line 611 "a.y"
+ case 113:
+#line 643 "a.y"
{
- (yyval.lval) = D_AUTO;
+ (yyval.lval) = NAME_AUTO;
}
break;
- case 117:
-#line 619 "a.y"
+ case 116:
+#line 651 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (1)].sym)->value;
}
break;
- case 118:
-#line 623 "a.y"
+ case 117:
+#line 655 "a.y"
{
(yyval.lval) = -(yyvsp[(2) - (2)].lval);
}
break;
- case 119:
-#line 627 "a.y"
+ case 118:
+#line 659 "a.y"
{
(yyval.lval) = (yyvsp[(2) - (2)].lval);
}
break;
- case 120:
-#line 631 "a.y"
+ case 119:
+#line 663 "a.y"
{
(yyval.lval) = ~(yyvsp[(2) - (2)].lval);
}
break;
- case 121:
-#line 635 "a.y"
+ case 120:
+#line 667 "a.y"
{
(yyval.lval) = (yyvsp[(2) - (3)].lval);
}
break;
- case 123:
-#line 642 "a.y"
+ case 122:
+#line 674 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval);
}
break;
- case 124:
-#line 646 "a.y"
+ case 123:
+#line 678 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval);
}
break;
- case 125:
-#line 650 "a.y"
+ case 124:
+#line 682 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval);
}
break;
- case 126:
-#line 654 "a.y"
+ case 125:
+#line 686 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval);
}
break;
- case 127:
-#line 658 "a.y"
+ case 126:
+#line 690 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval);
}
break;
- case 128:
-#line 662 "a.y"
+ case 127:
+#line 694 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval);
}
break;
- case 129:
-#line 666 "a.y"
+ case 128:
+#line 698 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval);
}
break;
- case 130:
-#line 670 "a.y"
+ case 129:
+#line 702 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval);
}
break;
- case 131:
-#line 674 "a.y"
+ case 130:
+#line 706 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval);
}
break;
- case 132:
-#line 678 "a.y"
+ case 131:
+#line 710 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) | (yyvsp[(3) - (3)].lval);
}
/* Line 1267 of yacc.c. */
-#line 2552 "y.tab.c"
+#line 2565 "y.tab.c"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
{
Sym *sym;
int32 lval;
- struct {
- int32 v1;
- int32 v2;
- } con2;
double dval;
char sval[8];
Addr addr;
Addr2 addr2;
}
/* Line 1529 of yacc.c. */
-#line 132 "y.tab.h"
+#line 128 "y.tab.h"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
// LEAL (n3)(n2*w), n3
p1 = gins(ALEAL, &n2, &n3);
p1->from.scale = w;
- p1->from.index = p1->from.type;
- p1->from.type = p1->to.type + D_INDIR;
+ p1->from.type = TYPE_MEM;
+ p1->from.index = p1->from.reg;
+ p1->from.reg = p1->to.reg;
} else {
nodconst(&tmp, types[TUINT32], w);
gins(optoas(OMUL, types[TUINT32]), &tmp, &n2);
case OINDREG:
// Increase the refcount of the register so that igen's caller
// has to call regfree.
- if(n->val.u.reg != D_SP)
+ if(n->val.u.reg != REG_SP)
reg[n->val.u.reg]++;
*a = *n;
return;
fp = structfirst(&flist, getoutarg(n->left->type));
memset(a, 0, sizeof *a);
a->op = OINDREG;
- a->val.u.reg = D_SP;
+ a->val.u.reg = REG_SP;
a->addable = 1;
a->xoffset = fp->width;
a->type = n->type;
return;
}
- nodreg(&dst, types[tptr], D_DI);
- nodreg(&src, types[tptr], D_SI);
+ nodreg(&dst, types[tptr], REG_DI);
+ nodreg(&src, types[tptr], REG_SI);
tempname(&tsrc, types[tptr]);
tempname(&tdst, types[tptr]);
// reverse direction
gins(ASTD, N, N); // set direction flag
if(c > 0) {
- gconreg(AADDL, w-1, D_SI);
- gconreg(AADDL, w-1, D_DI);
+ gconreg(AADDL, w-1, REG_SI);
+ gconreg(AADDL, w-1, REG_DI);
- gconreg(AMOVL, c, D_CX);
+ gconreg(AMOVL, c, REG_CX);
gins(AREP, N, N); // repeat
gins(AMOVSB, N, N); // MOVB *(SI)-,*(DI)-
}
if(q > 0) {
if(c > 0) {
- gconreg(AADDL, -3, D_SI);
- gconreg(AADDL, -3, D_DI);
+ gconreg(AADDL, -3, REG_SI);
+ gconreg(AADDL, -3, REG_DI);
} else {
- gconreg(AADDL, w-4, D_SI);
- gconreg(AADDL, w-4, D_DI);
+ gconreg(AADDL, w-4, REG_SI);
+ gconreg(AADDL, w-4, REG_DI);
}
- gconreg(AMOVL, q, D_CX);
+ gconreg(AMOVL, q, REG_CX);
gins(AREP, N, N); // repeat
gins(AMOVSL, N, N); // MOVL *(SI)-,*(DI)-
}
gins(ACLD, N, N); // paranoia. TODO(rsc): remove?
// normal direction
if(q > 128 || (q >= 4 && nacl)) {
- gconreg(AMOVL, q, D_CX);
+ gconreg(AMOVL, q, REG_CX);
gins(AREP, N, N); // repeat
gins(AMOVSL, N, N); // MOVL *(SI)+,*(DI)+
} else if(q >= 4) {
p = gins(ADUFFCOPY, N, N);
- p->to.type = D_ADDR;
+ p->to.type = TYPE_ADDR;
p->to.sym = linksym(pkglookup("duffcopy", runtimepkg));
// 10 and 128 = magic constants: see ../../runtime/asm_386.s
p->to.offset = 10*(128-q);
r = &t2;
}
- nodreg(&ax, types[TINT32], D_AX);
- nodreg(&cx, types[TINT32], D_CX);
- nodreg(&dx, types[TINT32], D_DX);
+ nodreg(&ax, types[TINT32], REG_AX);
+ nodreg(&cx, types[TINT32], REG_CX);
+ nodreg(&dx, types[TINT32], REG_DX);
// Setup for binary operation.
split64(l, &lo1, &hi1);
} else {
gins(AMOVL, &dx, &cx);
p1 = gins(ASHLL, ncon(v), &dx);
- p1->from.index = D_AX; // double-width shift
+ p1->from.index = REG_AX; // double-width shift
p1->from.scale = 0;
p1 = gins(ASHLL, ncon(v), &ax);
- p1->from.index = D_CX; // double-width shift
+ p1->from.index = REG_CX; // double-width shift
p1->from.scale = 0;
}
break;
gins(AMOVL, &lo1, &ax);
gins(AMOVL, &hi1, &dx);
p1 = gins(ASHLL, ncon(v), &dx);
- p1->from.index = D_AX; // double-width shift
+ p1->from.index = REG_AX; // double-width shift
p1->from.scale = 0;
gins(ASHLL, ncon(v), &ax);
break;
// general shift
p1 = gins(ASHLL, &cx, &dx);
- p1->from.index = D_AX; // double-width shift
+ p1->from.index = REG_AX; // double-width shift
p1->from.scale = 0;
gins(ASHLL, &cx, &ax);
patch(p2, pc);
gins(AMOVL, &lo1, &ax);
gins(AMOVL, &hi1, &dx);
p1 = gins(ASHRL, ncon(v), &ax);
- p1->from.index = D_DX; // double-width shift
+ p1->from.index = REG_DX; // double-width shift
p1->from.scale = 0;
gins(optoas(ORSH, hi1.type), ncon(v), &dx);
break;
// general shift
p1 = gins(ASHRL, &cx, &ax);
- p1->from.index = D_DX; // double-width shift
+ p1->from.index = REG_DX; // double-width shift
p1->from.scale = 0;
gins(optoas(ORSH, hi1.type), &cx, &dx);
patch(p2, pc);
widthint = 4;
widthreg = 4;
- zprog.link = P;
- zprog.as = AGOK;
- zprog.from.type = D_NONE;
- zprog.from.index = D_NONE;
- zprog.from.scale = 0;
- zprog.to = zprog.from;
-
listinit8();
}
+
+void
+main(int argc, char **argv)
+{
+ arch.thechar = thechar;
+ arch.thestring = thestring;
+ arch.thelinkarch = thelinkarch;
+ arch.typedefs = typedefs;
+ arch.MAXWIDTH = MAXWIDTH;
+ arch.afunclit = afunclit;
+ arch.anyregalloc = anyregalloc;
+ arch.betypeinit = betypeinit;
+ arch.bgen = bgen;
+ arch.cgen = cgen;
+ arch.cgen_asop = cgen_asop;
+ arch.cgen_call = cgen_call;
+ arch.cgen_callinter = cgen_callinter;
+ arch.cgen_ret = cgen_ret;
+ arch.clearfat = clearfat;
+ arch.clearp = clearp;
+ arch.defframe = defframe;
+ arch.dgostringptr = dgostringptr;
+ arch.dgostrlitptr = dgostrlitptr;
+ arch.dsname = dsname;
+ arch.dsymptr = dsymptr;
+ arch.dumpdata = dumpdata;
+ arch.dumpit = dumpit;
+ arch.excise = excise;
+ arch.expandchecks = expandchecks;
+ arch.fixautoused = fixautoused;
+ arch.gclean = gclean;
+ arch.gdata = gdata;
+ arch.gdatacomplex = gdatacomplex;
+ arch.gdatastring = gdatastring;
+ arch.ggloblnod = ggloblnod;
+ arch.ggloblsym = ggloblsym;
+ arch.ginit = ginit;
+ arch.gins = gins;
+ arch.ginscall = ginscall;
+ arch.gjmp = gjmp;
+ arch.gtrack = gtrack;
+ arch.gused = gused;
+ arch.igen = igen;
+ arch.isfat = isfat;
+ arch.linkarchinit = linkarchinit;
+ arch.markautoused = markautoused;
+ arch.naddr = naddr;
+ arch.newplist = newplist;
+ arch.nodarg = nodarg;
+ arch.patch = patch;
+ arch.proginfo = proginfo;
+ arch.regalloc = regalloc;
+ arch.regfree = regfree;
+ arch.regopt = regopt;
+ arch.regtyp = regtyp;
+ arch.sameaddr = sameaddr;
+ arch.smallindir = smallindir;
+ arch.stackaddr = stackaddr;
+ arch.unpatch = unpatch;
+
+ gcmain(argc, argv);
+}
#include "../gc/go.h"
#include "../8l/8.out.h"
-#define TEXTFLAG from.scale
-
// foptoas flags
enum
{
};
EXTERN int32 dynloc;
-EXTERN uchar reg[D_NONE];
+EXTERN uchar reg[MAXREG];
EXTERN int32 pcloc; // instruction counter
EXTERN Strlit emptystring;
-EXTERN Prog zprog;
-EXTERN Node* newproc;
-EXTERN Node* deferproc;
-EXTERN Node* deferreturn;
-EXTERN Node* panicindex;
-EXTERN Node* panicslice;
EXTERN Node* panicdiv;
-EXTERN Node* throwreturn;
extern uint32 unmappedzero;
void listinit(void);
void zaddr(Biobuf*, Addr*, int, int);
+
+void afunclit(Addr*, Node*);
+int anyregalloc(void);
+void betypeinit(void);
+void bgen(Node*, int, int, Prog*);
+void cgen(Node*, Node*);
+void cgen_asop(Node*);
+void cgen_call(Node*, int);
+void cgen_callinter(Node*, Node*, int);
+void cgen_ret(Node*);
+void clearfat(Node*);
+void clearp(Prog*);
+void defframe(Prog*);
+int dgostringptr(Sym*, int, char*);
+int dgostrlitptr(Sym*, int, Strlit*);
+int dsname(Sym*, int, char*, int);
+int dsymptr(Sym*, int, Sym*, int);
+void dumpdata(void);
+void dumpit(char*, Flow*, int);
+void excise(Flow*);
+void expandchecks(Prog*);
+void fixautoused(Prog*);
+void gclean(void);
+void gdata(Node*, Node*, int);
+void gdatacomplex(Node*, Mpcplx*);
+void gdatastring(Node*, Strlit*);
+void ggloblnod(Node *nam);
+void ggloblsym(Sym *s, int32 width, int8 flags);
+void ginit(void);
+Prog* gins(int, Node*, Node*);
+void ginscall(Node*, int);
+Prog* gjmp(Prog*);
+void gtrack(Sym*);
+void gused(Node*);
+void igen(Node*, Node*, Node*);
+int isfat(Type*);
+void linkarchinit(void);
+void markautoused(Prog*);
+void naddr(Node*, Addr*, int);
+Plist* newplist(void);
+Node* nodarg(Type*, int);
+void patch(Prog*, Prog*);
+void proginfo(ProgInfo*, Prog*);
+void regalloc(Node*, Type*, Node*);
+void regfree(Node*);
+void regopt(Prog*);
+int regtyp(Addr*);
+int sameaddr(Addr*, Addr*);
+int smallindir(Addr*, Addr*);
+int stackaddr(Addr*);
+Prog* unpatch(Prog*);
#include "gg.h"
#include "opt.h"
-static Prog *appendpp(Prog*, int, int, vlong, int, vlong);
+static Prog *appendpp(Prog*, int, int, int, vlong, int, int, vlong);
static Prog *zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *ax);
void
NodeList *l;
Node *n;
- // fill in argument size
- ptxt->to.offset2 = rnd(curfn->type->argwid, widthptr);
-
- // fill in final stack size
- frame = rnd(stksize+maxarg, widthptr);
+ // fill in argument size, stack size
+ ptxt->to.type = TYPE_TEXTSIZE;
+ ptxt->to.u.argsize = rnd(curfn->type->argwid, widthptr);
+ frame = rnd(stksize+maxarg, widthreg);
ptxt->to.offset = frame;
// insert code to zero ambiguously live variables
if(cnt == 0)
return p;
if(*ax == 0) {
- p = appendpp(p, AMOVL, D_CONST, 0, D_AX, 0);
+ p = appendpp(p, AMOVL, TYPE_CONST, 0, 0, TYPE_REG, REG_AX, 0);
*ax = 1;
}
if(cnt <= 4*widthreg) {
for(i = 0; i < cnt; i += widthreg) {
- p = appendpp(p, AMOVL, D_AX, 0, D_SP+D_INDIR, frame+lo+i);
+ p = appendpp(p, AMOVL, TYPE_REG, REG_AX, 0, TYPE_MEM, REG_SP, frame+lo+i);
}
} else if(!nacl && cnt <= 128*widthreg) {
- p = appendpp(p, ALEAL, D_SP+D_INDIR, frame+lo, D_DI, 0);
- p = appendpp(p, ADUFFZERO, D_NONE, 0, D_ADDR, 1*(128-cnt/widthreg));
+ p = appendpp(p, ALEAL, TYPE_MEM, REG_SP, frame+lo, TYPE_REG, REG_DI, 0);
+ p = appendpp(p, ADUFFZERO, TYPE_NONE, 0, 0, TYPE_ADDR, 0, 1*(128-cnt/widthreg));
p->to.sym = linksym(pkglookup("duffzero", runtimepkg));
} else {
- p = appendpp(p, AMOVL, D_CONST, cnt/widthreg, D_CX, 0);
- p = appendpp(p, ALEAL, D_SP+D_INDIR, frame+lo, D_DI, 0);
- p = appendpp(p, AREP, D_NONE, 0, D_NONE, 0);
- p = appendpp(p, ASTOSL, D_NONE, 0, D_NONE, 0);
+ p = appendpp(p, AMOVL, TYPE_CONST, 0, cnt/widthreg, TYPE_REG, REG_CX, 0);
+ p = appendpp(p, ALEAL, TYPE_MEM, REG_SP, frame+lo, TYPE_REG, REG_DI, 0);
+ p = appendpp(p, AREP, TYPE_NONE, 0, 0, TYPE_NONE, 0, 0);
+ p = appendpp(p, ASTOSL, TYPE_NONE, 0, 0, TYPE_NONE, 0, 0);
}
return p;
}
static Prog*
-appendpp(Prog *p, int as, int ftype, vlong foffset, int ttype, vlong toffset)
+appendpp(Prog *p, int as, int ftype, int freg, vlong foffset, int ttype, int treg, vlong toffset)
{
Prog *q;
q = mal(sizeof(*q));
q->as = as;
q->lineno = p->lineno;
q->from.type = ftype;
+ q->from.reg = freg;
q->from.offset = foffset;
q->to.type = ttype;
+ q->to.reg = treg;
q->to.offset = toffset;
q->link = p->link;
p->link = q;
continue;
if (p->from.node)
- p->from.node->used = 1;
+ ((Node*)(p->from.node))->used = 1;
if (p->to.node)
- p->to.node->used = 1;
+ ((Node*)(p->to.node))->used = 1;
}
}
Prog **lp;
for (lp=&p; (p=*lp) != P; ) {
- if (p->as == ATYPE && p->from.node && p->from.type == D_AUTO && !p->from.node->used) {
+ if (p->as == ATYPE && p->from.node && p->from.name == NAME_AUTO && !((Node*)(p->from.node))->used) {
*lp = p->link;
continue;
}
- if ((p->as == AVARDEF || p->as == AVARKILL) && p->to.node && !p->to.node->used) {
+ if ((p->as == AVARDEF || p->as == AVARKILL) && p->to.node && !((Node*)(p->to.node))->used) {
// Cannot remove VARDEF instruction, because - unlike TYPE handled above -
// VARDEFs are interspersed with other code, and a jump might be using the
// VARDEF as a target. Replace with a no-op instead. A later pass will remove
// the no-ops.
- p->to.type = D_NONE;
- p->to.node = N;
- p->as = ANOP;
+ nopout(p);
continue;
}
- if (p->from.type == D_AUTO && p->from.node)
- p->from.offset += p->from.node->stkdelta;
+ if (p->from.type == TYPE_MEM && p->from.name == NAME_AUTO && p->from.node)
+ p->from.offset += ((Node*)(p->from.node))->stkdelta;
- if (p->to.type == D_AUTO && p->to.node)
- p->to.offset += p->to.node->stkdelta;
+ if (p->to.type == TYPE_MEM && p->to.name == NAME_AUTO && p->to.node)
+ p->to.offset += ((Node*)(p->to.node))->stkdelta;
lp = &p->link;
}
return;
}
- nodreg(&n1, types[tptr], D_DI);
+ nodreg(&n1, types[tptr], REG_DI);
agen(nl, &n1);
- gconreg(AMOVL, 0, D_AX);
+ gconreg(AMOVL, 0, REG_AX);
if(q > 128 || (q >= 4 && nacl)) {
- gconreg(AMOVL, q, D_CX);
+ gconreg(AMOVL, q, REG_CX);
gins(AREP, N, N); // repeat
gins(ASTOSL, N, N); // STOL AL,*(DI)+
} else if(q >= 4) {
p = gins(ADUFFZERO, N, N);
- p->to.type = D_ADDR;
+ p->to.type = TYPE_ADDR;
p->to.sym = linksym(pkglookup("duffzero", runtimepkg));
// 1 and 128 = magic constants: see ../../runtime/asm_386.s
p->to.offset = 1*(128-q);
// x86 NOP 0x90 is really XCHG AX, AX; use that description
// because the NOP pseudo-instruction will be removed by
// the linker.
- nodreg(®, types[TINT], D_AX);
+ nodreg(®, types[TINT], REG_AX);
gins(AXCHGL, ®, ®);
}
p = gins(ACALL, N, f);
gins(AUNDEF, N, N);
break;
}
- nodreg(®, types[tptr], D_DX);
- nodreg(&r1, types[tptr], D_BX);
+ nodreg(®, types[tptr], REG_DX);
+ nodreg(&r1, types[tptr], REG_BX);
gmove(f, ®);
reg.op = OINDREG;
gmove(®, &r1);
case 2: // deferred call (defer)
memset(&stk, 0, sizeof(stk));
stk.op = OINDREG;
- stk.val.u.reg = D_SP;
+ stk.val.u.reg = REG_SP;
stk.xoffset = 0;
// size of arguments at 0(SP)
else
ginscall(deferproc, 0);
if(proc == 2) {
- nodreg(®, types[TINT32], D_AX);
+ nodreg(®, types[TINT32], REG_AX);
gins(ATESTL, ®, ®);
p = gbranch(AJEQ, T, +1);
cgen_ret(N);
// register to hold its address.
igen(i, &nodi, res); // REG = &inter
- nodindreg(&nodsp, types[tptr], D_SP);
+ nodindreg(&nodsp, types[tptr], REG_SP);
nodsp.xoffset = 0;
if(proc != 0)
nodsp.xoffset += 2 * widthptr; // leave room for size & fn
memset(&nod, 0, sizeof(nod));
nod.op = OINDREG;
- nod.val.u.reg = D_SP;
+ nod.val.u.reg = REG_SP;
nod.addable = 1;
nod.xoffset = fp->width;
memset(&nod1, 0, sizeof(nod1));
nod1.op = OINDREG;
- nod1.val.u.reg = D_SP;
+ nod1.val.u.reg = REG_SP;
nod1.addable = 1;
nod1.xoffset = fp->width;
genlist(curfn->exit);
p = gins(ARET, N, N);
if(n != N && n->op == ORETJMP) {
- p->to.type = D_EXTERN;
+ p->to.type = TYPE_MEM;
+ p->to.name = NAME_EXTERN;
p->to.sym = linksym(n->left->sym);
}
}
t = types[TINT32];
else
t = types[TUINT32];
- savex(D_AX, &ax, &oldax, res, t);
- savex(D_DX, &dx, &olddx, res, t);
+ savex(REG_AX, &ax, &oldax, res, t);
+ savex(REG_DX, &dx, &olddx, res, t);
dodiv(op, nl, nr, res, &ax, &dx);
restx(&dx, &olddx);
restx(&ax, &oldax);
}
memset(&oldcx, 0, sizeof oldcx);
- nodreg(&cx, types[TUINT32], D_CX);
- if(reg[D_CX] > 1 && !samereg(&cx, res)) {
+ nodreg(&cx, types[TUINT32], REG_CX);
+ if(reg[REG_CX] > 1 && !samereg(&cx, res)) {
tempname(&oldcx, types[TUINT32]);
gmove(&cx, &oldcx);
}
tempname(&nt, nr->type);
n1 = nt;
} else {
- nodreg(&n1, types[TUINT32], D_CX);
+ nodreg(&n1, types[TUINT32], REG_CX);
regalloc(&n1, nr->type, &n1); // to hold the shift type in CX
}
if(bounded) {
if(nr->type->width > 4) {
// delayed reg alloc
- nodreg(&n1, types[TUINT32], D_CX);
+ nodreg(&n1, types[TUINT32], REG_CX);
regalloc(&n1, types[TUINT32], &n1); // to hold the shift type in CX
split64(&nt, &lo, &hi);
gmove(&lo, &n1);
} else {
if(nr->type->width > 4) {
// delayed reg alloc
- nodreg(&n1, types[TUINT32], D_CX);
+ nodreg(&n1, types[TUINT32], REG_CX);
regalloc(&n1, types[TUINT32], &n1); // to hold the shift type in CX
split64(&nt, &lo, &hi);
gmove(&lo, &n1);
cgen(nr, &n2);
// multiply.
- nodreg(&ax, t, D_AX);
+ nodreg(&ax, t, REG_AX);
gmove(&n2, &ax);
gins(a, &n1, N);
regfree(&n2);
if(t->width == 1) {
// byte multiply behaves differently.
- nodreg(&ax, t, D_AH);
- nodreg(&dx, t, D_DX);
+ nodreg(&ax, t, REG_AH);
+ nodreg(&dx, t, REG_DX);
gmove(&ax, &dx);
}
- nodreg(&dx, t, D_DX);
+ nodreg(&dx, t, REG_DX);
gmove(&dx, res);
}
nl = n->left;
nr = n->right;
- nodreg(&f0, nl->type, D_F0);
- nodreg(&f1, n->type, D_F0+1);
+ nodreg(&f0, nl->type, REG_F0);
+ nodreg(&f1, n->type, REG_F0+1);
if(nr != N)
goto flt2;
a = brrev(a);
}
- nodreg(&tmp, nr->type, D_F0);
- nodreg(&n2, nr->type, D_F0 + 1);
- nodreg(&ax, types[TUINT16], D_AX);
+ nodreg(&tmp, nr->type, REG_F0);
+ nodreg(&n2, nr->type, REG_F0 + 1);
+ nodreg(&ax, types[TUINT16], REG_AX);
et = simsimtype(nr->type);
if(et == TFLOAT64) {
if(nl->ullman > nr->ullman) {
p1->pc = 9999;
p2->pc = 9999;
p->as = ACMPL;
- p->to.type = D_CONST;
+ p->to.type = TYPE_CONST;
p->to.offset = 0;
p1->as = AJNE;
- p1->from.type = D_CONST;
+ p1->from.type = TYPE_CONST;
p1->from.offset = 1; // likely
- p1->to.type = D_BRANCH;
+ p1->to.type = TYPE_BRANCH;
p1->to.u.branch = p2->link;
// crash by write to memory address 0.
// if possible, since we know arg is 0, use 0(arg),
// which will be shorter to encode than plain 0.
p2->as = AMOVL;
- p2->from.type = D_AX;
- if(regtyp(&p->from))
- p2->to.type = p->from.type + D_INDIR;
- else
- p2->to.type = D_INDIR+D_NONE;
+ p2->from.type = TYPE_REG;
+ p2->from.reg = REG_AX;
+ if(regtyp(&p->from)) {
+ p2->to.type = TYPE_MEM;
+ p2->to.reg = p->from.reg;
+ } else
+ p2->to.type = TYPE_MEM;
p2->to.offset = 0;
}
}
Prog *p;
p = gins(ADATA, N, N);
- p->from.type = D_EXTERN;
- p->from.index = D_NONE;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.offset = off;
- p->from.scale = n;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = n;
p->from.sym = linksym(s);
- p->to.type = D_SCONST;
- p->to.index = D_NONE;
+ p->to.type = TYPE_SCONST;
memmove(p->to.u.sval, t, n);
return off + n;
}
Sym *sym;
sym = stringsym(s, len);
- a->type = D_EXTERN;
+ a->type = TYPE_MEM;
+ a->name = NAME_EXTERN;
a->sym = linksym(sym);
a->node = sym->def;
a->offset = widthptr+4; // skip header
Sym *sym;
sym = stringsym(sval->s, sval->len);
- a->type = D_EXTERN;
+ a->type = TYPE_MEM;
+ a->name = NAME_EXTERN;
a->sym = linksym(sym);
a->node = sym->def;
a->offset = 0; // header
if(wid == 8 && is64(nr->type)) {
v = mpgetfix(nr->val.u.xval);
p = gins(ADATA, nam, nodintconst(v));
- p->from.scale = 4;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = 4;
p = gins(ADATA, nam, nodintconst(v>>32));
- p->from.scale = 4;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = 4;
p->from.offset += 4;
return;
}
p = gins(ADATA, nam, nr);
- p->from.scale = wid;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = wid;
}
void
w = types[w]->width;
p = gins(ADATA, nam, N);
- p->from.scale = w;
- p->to.type = D_FCONST;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = w;
+ p->to.type = TYPE_FCONST;
p->to.u.dval = mpgetflt(&cval->real);
p = gins(ADATA, nam, N);
- p->from.scale = w;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = w;
p->from.offset += w;
- p->to.type = D_FCONST;
+ p->to.type = TYPE_FCONST;
p->to.u.dval = mpgetflt(&cval->imag);
}
p = gins(ADATA, nam, N);
datastring(sval->s, sval->len, &p->to);
- p->from.scale = types[tptr]->width;
- p->to.index = p->to.type;
- p->to.type = D_ADDR;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = types[tptr]->width;
+ p->to.type = TYPE_ADDR;
//print("%P\n", p);
nodconst(&nod1, types[TINT32], sval->len);
p = gins(ADATA, nam, &nod1);
- p->from.scale = types[TINT32]->width;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = types[TINT32]->width;
p->from.offset += types[tptr]->width;
}
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
- p->from.type = D_EXTERN;
- p->from.index = D_NONE;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
- p->from.scale = widthptr;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = widthptr;
datastring(str, strlen(str)+1, &p->to);
- p->to.index = p->to.type;
- p->to.type = D_ADDR;
+ p->to.type = TYPE_ADDR;
p->to.etype = TINT32;
off += widthptr;
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
- p->from.type = D_EXTERN;
- p->from.index = D_NONE;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
- p->from.scale = widthptr;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = widthptr;
datagostring(lit, &p->to);
- p->to.index = p->to.type;
- p->to.type = D_ADDR;
+ p->to.type = TYPE_ADDR;
p->to.etype = TINT32;
off += widthptr;
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
- p->from.type = D_EXTERN;
- p->from.index = D_NONE;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
- p->from.scale = widthptr;
- p->to.type = D_ADDR;
- p->to.index = D_EXTERN;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = widthptr;
+ p->to.type = TYPE_ADDR;
+ p->to.name = NAME_EXTERN;
p->to.sym = linksym(x);
p->to.offset = xoff;
off += widthptr;
nopout(Prog *p)
{
p->as = ANOP;
+ p->from = zprog.from;
+ p->to = zprog.to;
}
clearp(Prog *p)
{
p->as = AEND;
- p->from.type = D_NONE;
- p->from.index = D_NONE;
- p->to.type = D_NONE;
- p->to.index = D_NONE;
+ p->from.type = TYPE_NONE;
+ p->from.index = TYPE_NONE;
+ p->to.type = TYPE_NONE;
+ p->to.index = TYPE_NONE;
p->pc = pcloc;
pcloc++;
}
USED(t);
p = prog(as);
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
p->to.u.branch = P;
if(likely != 0) {
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = likely > 0;
}
return p;
void
patch(Prog *p, Prog *to)
{
- if(p->to.type != D_BRANCH)
+ if(p->to.type != TYPE_BRANCH)
fatal("patch: not a branch");
p->to.u.branch = to;
p->to.offset = to->pc;
{
Prog *q;
- if(p->to.type != D_BRANCH)
+ if(p->to.type != TYPE_BRANCH)
fatal("unpatch: not a branch");
q = p->to.u.branch;
p->to.u.branch = P;
p->lineno = nam->lineno;
p->from.sym->gotype = linksym(ngotype(nam));
p->to.sym = nil;
- p->to.type = D_CONST;
+ p->to.type = TYPE_CONST;
p->to.offset = nam->type->width;
if(nam->readonly)
- p->from.scale = RODATA;
+ p->from3.offset = RODATA;
if(nam->type != T && !haspointers(nam->type))
- p->from.scale |= NOPTR;
+ p->from3.offset |= NOPTR;
}
void
Prog *p;
p = gins(AGLOBL, N, N);
- p->from.type = D_EXTERN;
- p->from.index = D_NONE;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
+ p->from.index = REG_NONE;
p->from.sym = linksym(s);
- p->to.type = D_CONST;
- p->to.index = D_NONE;
+ p->to.type = TYPE_CONST;
+ p->to.index = REG_NONE;
p->to.offset = width;
- p->from.scale = flags;
+ p->from3.offset = flags;
}
void
Prog *p;
p = gins(AUSEFIELD, N, N);
- p->from.type = D_EXTERN;
- p->from.index = D_NONE;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
}
void
afunclit(Addr *a, Node *n)
{
- if(a->type == D_ADDR && a->index == D_EXTERN) {
- a->type = D_EXTERN;
- a->index = D_NONE;
+ if(a->type == TYPE_ADDR && a->name == NAME_EXTERN) {
+ a->type = TYPE_MEM;
a->sym = linksym(n->sym);
}
}
if(t == T)
fatal("optoas: t is nil");
- a = AGOK;
+ a = AXXX;
switch(CASE(op, simtype[t->etype])) {
default:
fatal("optoas: no entry %O-%T", op, t);
{
int et, a;
- a = AGOK;
+ a = AXXX;
et = simtype[t->etype];
if(use_sse)
static int resvd[] =
{
-// D_DI, // for movstring
-// D_SI, // for movstring
+// REG_DI, // for movstring
+// REG_SI, // for movstring
- D_AX, // for divide
- D_CX, // for shift
- D_DX, // for divide
- D_SP, // for stack
+ REG_AX, // for divide
+ REG_CX, // for shift
+ REG_DX, // for divide
+ REG_SP, // for stack
- D_BL, // because D_BX can be allocated
- D_BH,
+ REG_BL, // because REG_BX can be allocated
+ REG_BH,
};
void
for(i=0; i<nelem(reg); i++)
reg[i] = 1;
- for(i=D_AX; i<=D_DI; i++)
+ for(i=REG_AX; i<=REG_DI; i++)
reg[i] = 0;
- for(i=D_X0; i<=D_X7; i++)
+ for(i=REG_X0; i<=REG_X7; i++)
reg[i] = 0;
for(i=0; i<nelem(resvd); i++)
reg[resvd[i]]++;
}
-uintptr regpc[D_NONE];
+uintptr regpc[MAXREG];
void
gclean(void)
for(i=0; i<nelem(resvd); i++)
reg[resvd[i]]--;
- for(i=D_AX; i<=D_DI; i++)
+ for(i=REG_AX; i<=REG_DI; i++)
if(reg[i])
yyerror("reg %R left allocated at %ux", i, regpc[i]);
- for(i=D_X0; i<=D_X7; i++)
+ for(i=REG_X0; i<=REG_X7; i++)
if(reg[i])
yyerror("reg %R left allocated\n", i);
}
{
int i, j;
- for(i=D_AX; i<=D_DI; i++) {
+ for(i=REG_AX; i<=REG_DI; i++) {
if(reg[i] == 0)
goto ok;
for(j=0; j<nelem(resvd); j++)
return 1;
ok:;
}
- for(i=D_X0; i<=D_X7; i++)
+ for(i=REG_X0; i<=REG_X7; i++)
if(reg[i])
return 1;
return 0;
case TBOOL:
if(o != N && o->op == OREGISTER) {
i = o->val.u.reg;
- if(i >= D_AX && i <= D_DI)
+ if(i >= REG_AX && i <= REG_DI)
goto out;
}
- for(i=D_AX; i<=D_DI; i++)
+ for(i=REG_AX; i<=REG_DI; i++)
if(reg[i] == 0)
goto out;
fprint(2, "registers allocated at\n");
- for(i=D_AX; i<=D_DI; i++)
+ for(i=REG_AX; i<=REG_DI; i++)
fprint(2, "\t%R\t%#lux\n", i, regpc[i]);
fatal("out of fixed registers");
goto err;
case TFLOAT32:
case TFLOAT64:
if(!use_sse) {
- i = D_F0;
+ i = REG_F0;
goto out;
}
if(o != N && o->op == OREGISTER) {
i = o->val.u.reg;
- if(i >= D_X0 && i <= D_X7)
+ if(i >= REG_X0 && i <= REG_X7)
goto out;
}
- for(i=D_X0; i<=D_X7; i++)
+ for(i=REG_X0; i<=REG_X7; i++)
if(reg[i] == 0)
goto out;
fprint(2, "registers allocated at\n");
- for(i=D_X0; i<=D_X7; i++)
+ for(i=REG_X0; i<=REG_X7; i++)
fprint(2, "\t%R\t%#lux\n", i, regpc[i]);
fatal("out of floating registers");
}
return;
out:
- if (i == D_SP)
+ if(i == REG_SP)
print("alloc SP\n");
if(reg[i] == 0) {
regpc[i] = (uintptr)getcallerpc(&n);
- if(i == D_AX || i == D_CX || i == D_DX || i == D_SP) {
+ if(i == REG_AX || i == REG_CX || i == REG_DX || i == REG_SP) {
dump("regalloc-o", o);
fatal("regalloc %R", i);
}
if(n->op != OREGISTER && n->op != OINDREG)
fatal("regfree: not a register");
i = n->val.u.reg;
- if(i == D_SP)
+ if(i == REG_SP)
return;
if(i < 0 || i >= nelem(reg))
fatal("regfree: reg out of range");
if(reg[i] <= 0)
fatal("regfree: reg not allocated");
reg[i]--;
- if(reg[i] == 0 && (i == D_AX || i == D_CX || i == D_DX || i == D_SP))
+ if(reg[i] == 0 && (i == REG_AX || i == REG_CX || i == REG_DX || i == REG_SP))
fatal("regfree %R", i);
}
case 0: // output arg
n->op = OINDREG;
- n->val.u.reg = D_SP;
+ n->val.u.reg = REG_SP;
break;
case 1: // input arg
case CASE(TINT64, TUINT8):
case CASE(TUINT64, TUINT8):
split64(f, &flo, &fhi);
- nodreg(&r1, t->type, D_AX);
+ nodreg(&r1, t->type, REG_AX);
gmove(&flo, &r1);
gins(AMOVB, &r1, t);
splitclean();
case CASE(TINT64, TUINT16):
case CASE(TUINT64, TUINT16):
split64(f, &flo, &fhi);
- nodreg(&r1, t->type, D_AX);
+ nodreg(&r1, t->type, REG_AX);
gmove(&flo, &r1);
gins(AMOVW, &r1, t);
splitclean();
case CASE(TINT64, TUINT32):
case CASE(TUINT64, TUINT32):
split64(f, &flo, &fhi);
- nodreg(&r1, t->type, D_AX);
+ nodreg(&r1, t->type, REG_AX);
gmove(&flo, &r1);
gins(AMOVL, &r1, t);
splitclean();
gins(AMOVL, &flo, &tlo);
gins(AMOVL, &fhi, &thi);
} else {
- nodreg(&r1, t->type, D_AX);
- nodreg(&r2, t->type, D_DX);
+ nodreg(&r1, t->type, REG_AX);
+ nodreg(&r2, t->type, REG_DX);
gins(AMOVL, &flo, &r1);
gins(AMOVL, &fhi, &r2);
gins(AMOVL, &r1, &tlo);
case CASE(TINT32, TINT64): // sign extend int32
case CASE(TINT32, TUINT64):
split64(t, &tlo, &thi);
- nodreg(&flo, tlo.type, D_AX);
- nodreg(&fhi, thi.type, D_DX);
+ nodreg(&flo, tlo.type, REG_AX);
+ nodreg(&fhi, thi.type, REG_DX);
gmove(f, &flo);
gins(ACDQ, N, N);
gins(AMOVL, &flo, &tlo);
cvt = f->type;
goto hardmem;
}
- nodreg(&r1, types[ft], D_F0);
+ nodreg(&r1, types[ft], REG_F0);
if(ft == TFLOAT32)
gins(AFMOVF, f, &r1);
else
goto hardmem;
}
bignodes();
- nodreg(&f0, types[ft], D_F0);
- nodreg(&f1, types[ft], D_F0 + 1);
- nodreg(&ax, types[TUINT16], D_AX);
+ nodreg(&f0, types[ft], REG_F0);
+ nodreg(&f1, types[ft], REG_F0 + 1);
+ nodreg(&ax, types[TUINT16], REG_AX);
if(ft == TFLOAT32)
gins(AFMOVF, f, &f0);
case CASE(TINT64, TFLOAT64):
if(t->op == OREGISTER)
goto hardmem;
- nodreg(&f0, t->type, D_F0);
+ nodreg(&f0, t->type, REG_F0);
gins(AFMOVV, f, &f0);
if(tt == TFLOAT32)
gins(AFMOVFP, &f0, t);
// algorithm is:
// if small enough, use native int64 -> float64 conversion.
// otherwise, halve (rounding to odd?), convert, and double.
- nodreg(&ax, types[TUINT32], D_AX);
- nodreg(&dx, types[TUINT32], D_DX);
- nodreg(&cx, types[TUINT32], D_CX);
+ nodreg(&ax, types[TUINT32], REG_AX);
+ nodreg(&dx, types[TUINT32], REG_DX);
+ nodreg(&cx, types[TUINT32], REG_CX);
tempname(&t1, f->type);
split64(&t1, &tlo, &thi);
gmove(f, &t1);
gins(ACMPL, &thi, ncon(0));
p1 = gbranch(AJLT, T, 0);
// native
- nodreg(&r1, types[tt], D_F0);
+ nodreg(&r1, types[tt], REG_F0);
gins(AFMOVV, &t1, &r1);
if(tt == TFLOAT32)
gins(AFMOVFP, &r1, t);
gmove(&tlo, &ax);
gmove(&thi, &dx);
p1 = gins(ASHRL, ncon(1), &ax);
- p1->from.index = D_DX; // double-width shift DX -> AX
+ p1->from.index = REG_DX; // double-width shift DX -> AX
p1->from.scale = 0;
gins(AMOVL, ncon(0), &cx);
gins(ASETCC, N, &cx);
gins(ASHRL, ncon(1), &dx);
gmove(&dx, &thi);
gmove(&ax, &tlo);
- nodreg(&r1, types[tt], D_F0);
- nodreg(&r2, types[tt], D_F0 + 1);
+ nodreg(&r1, types[tt], REG_F0);
+ nodreg(&r2, types[tt], REG_F0 + 1);
gins(AFMOVV, &t1, &r1);
gins(AFMOVD, &r1, &r1);
gins(AFADDDP, &r1, &r2);
case CASE(TFLOAT64, TINT64):
if(t->op == OREGISTER)
goto hardmem;
- nodreg(&r1, types[ft], D_F0);
+ nodreg(&r1, types[ft], REG_F0);
if(f->op != OREGISTER) {
if(ft == TFLOAT32)
gins(AFMOVF, f, &r1);
if(ismem(f) && ismem(t))
goto hard;
if(f->op == OREGISTER && t->op == OREGISTER) {
- if(f->val.u.reg != D_F0 || t->val.u.reg != D_F0)
+ if(f->val.u.reg != REG_F0 || t->val.u.reg != REG_F0)
goto fatal;
return;
}
if(ft == TFLOAT64)
a = AFMOVD;
if(ismem(t)) {
- if(f->op != OREGISTER || f->val.u.reg != D_F0)
+ if(f->op != OREGISTER || f->val.u.reg != REG_F0)
fatal("gmove %N", f);
a = AFMOVFP;
if(ft == TFLOAT64)
if(ismem(f) && ismem(t))
goto hard;
if(f->op == OREGISTER && t->op == OREGISTER) {
- if(f->val.u.reg != D_F0 || t->val.u.reg != D_F0)
+ if(f->val.u.reg != REG_F0 || t->val.u.reg != REG_F0)
goto fatal;
return;
}
fatal("gins MOVF reg, reg");
if(as == ACVTSD2SS && f && f->op == OLITERAL)
fatal("gins CVTSD2SS const");
- if(as == AMOVSD && t && t->op == OREGISTER && t->val.u.reg == D_F0)
+ if(as == AMOVSD && t && t->op == OREGISTER && t->val.u.reg == REG_F0)
fatal("gins MOVSD into F0");
switch(as) {
dump("bad width to:", t);
fatal("bad width: %P (%d, %d)\n", p, af.width, at.width);
}
+ if(p->to.type == TYPE_ADDR && w > 0)
+ fatal("bad use of addr: %P", p);
return p;
}
Sym *s;
a->scale = 0;
- a->index = D_NONE;
- a->type = D_NONE;
+ a->reg = REG_NONE;
+ a->index = REG_NONE;
+ a->type = TYPE_NONE;
+ a->name = NAME_NONE;
a->gotype = nil;
a->node = N;
if(n == N)
break;
case OREGISTER:
- a->type = n->val.u.reg;
+ a->type = TYPE_REG;
+ a->reg = n->val.u.reg;
a->sym = nil;
break;
case OINDREG:
- a->type = n->val.u.reg+D_INDIR;
+ a->type = TYPE_MEM;
+ a->reg = n->val.u.reg;
a->sym = linksym(n->sym);
a->offset = n->xoffset;
break;
a->width = n->left->type->width;
a->offset = n->xoffset;
a->sym = linksym(n->left->sym);
- a->type = D_PARAM;
+ a->type = TYPE_MEM;
+ a->name = NAME_PARAM;
a->node = n->left->orig;
break;
case OCLOSUREVAR:
if(!curfn->needctxt)
fatal("closurevar without needctxt");
- a->type = D_DX+D_INDIR;
+ a->type = TYPE_MEM;
+ a->reg = REG_DX;
a->offset = n->xoffset;
a->sym = nil;
break;
default:
fatal("naddr: ONAME class %S %d\n", n->sym, n->class);
case PEXTERN:
- a->type = D_EXTERN;
+ a->type = TYPE_MEM;
+ a->name = NAME_EXTERN;
break;
case PAUTO:
- a->type = D_AUTO;
+ a->type = TYPE_MEM;
+ a->name = NAME_AUTO;
break;
case PPARAM:
case PPARAMOUT:
- a->type = D_PARAM;
+ a->type = TYPE_MEM;
+ a->name = NAME_PARAM;
break;
case PFUNC:
- a->index = D_EXTERN;
- a->type = D_ADDR;
+ a->type = TYPE_ADDR;
+ a->name = NAME_EXTERN;
s = funcsym(s);
break;
}
fatal("naddr: const %lT", n->type);
break;
case CTFLT:
- a->type = D_FCONST;
+ a->type = TYPE_FCONST;
a->u.dval = mpgetflt(n->val.u.fval);
break;
case CTINT:
case CTRUNE:
a->sym = nil;
- a->type = D_CONST;
+ a->type = TYPE_CONST;
a->offset = mpgetfix(n->val.u.xval);
break;
case CTSTR:
break;
case CTBOOL:
a->sym = nil;
- a->type = D_CONST;
+ a->type = TYPE_CONST;
a->offset = n->val.u.bval;
break;
case CTNIL:
a->sym = nil;
- a->type = D_CONST;
+ a->type = TYPE_CONST;
a->offset = 0;
break;
}
case OADDR:
naddr(n->left, a, canemitcode);
- if(a->type >= D_INDIR) {
- a->type -= D_INDIR;
- break;
- }
- if(a->type == D_EXTERN || a->type == D_STATIC ||
- a->type == D_AUTO || a->type == D_PARAM)
- if(a->index == D_NONE) {
- a->index = a->type;
- a->type = D_ADDR;
- break;
- }
- fatal("naddr: OADDR\n");
+ if(a->type != TYPE_MEM)
+ fatal("naddr: OADDR %D", a);
+ a->type = TYPE_ADDR;
+ break;
case OITAB:
// itable of interface value
naddr(n->left, a, canemitcode);
- if(a->type == D_CONST && a->offset == 0)
+ if(a->type == TYPE_CONST && a->offset == 0)
break; // len(nil)
a->etype = tptr;
a->width = widthptr;
case OSPTR:
// pointer in a string or slice
naddr(n->left, a, canemitcode);
- if(a->type == D_CONST && a->offset == 0)
+ if(a->type == TYPE_CONST && a->offset == 0)
break; // ptr(nil)
a->etype = simtype[tptr];
a->offset += Array_array;
case OLEN:
// len of string or slice
naddr(n->left, a, canemitcode);
- if(a->type == D_CONST && a->offset == 0)
+ if(a->type == TYPE_CONST && a->offset == 0)
break; // len(nil)
a->etype = TUINT32;
a->offset += Array_nel;
case OCAP:
// cap of string or slice
naddr(n->left, a, canemitcode);
- if(a->type == D_CONST && a->offset == 0)
+ if(a->type == TYPE_CONST && a->offset == 0)
break; // cap(nil)
a->etype = TUINT32;
a->offset += Array_cap;
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include "../gc/popt.h"
#define Z N
#define Adr Addr
-#define D_HI D_NONE
-#define D_LO D_NONE
-
#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])
extern Node *Z;
enum
{
- D_HI = D_NONE,
- D_LO = D_NONE,
CLOAD = 5,
CREF = 5,
CINF = 1000,
/*
* prog.c
*/
-typedef struct ProgInfo ProgInfo;
-struct ProgInfo
-{
- uint32 flags; // the bits below
- uint32 reguse; // registers implicitly used by this instruction
- uint32 regset; // registers implicitly set by this instruction
- uint32 regindex; // registers used by addressing mode
-};
-
-enum
-{
- // Pseudo-op, like TEXT, GLOBL, TYPE, PCDATA, FUNCDATA.
- Pseudo = 1<<1,
-
- // There's nothing to say about the instruction,
- // but it's still okay to see.
- OK = 1<<2,
-
- // Size of right-side write, or right-side read if no write.
- SizeB = 1<<3,
- SizeW = 1<<4,
- SizeL = 1<<5,
- SizeQ = 1<<6,
- SizeF = 1<<7, // float aka float32
- SizeD = 1<<8, // double aka float64
-
- // Left side (Prog.from): address taken, read, write.
- LeftAddr = 1<<9,
- LeftRead = 1<<10,
- LeftWrite = 1<<11,
-
- // Right side (Prog.to): address taken, read, write.
- RightAddr = 1<<12,
- RightRead = 1<<13,
- RightWrite = 1<<14,
-
- // Set, use, or kill of carry bit.
- // Kill means we never look at the carry bit after this kind of instruction.
- SetCarry = 1<<15,
- UseCarry = 1<<16,
- KillCarry = 1<<17,
-
- // Instruction kinds
- Move = 1<<18, // straight move
- Conv = 1<<19, // size conversion
- Cjmp = 1<<20, // conditional jump
- Break = 1<<21, // breaks control flow (no fallthrough)
- Call = 1<<22, // function call
- Jump = 1<<23, // jump
- Skip = 1<<24, // data instruction
-
- // Special cases for register use.
- ShiftCX = 1<<25, // possible shift by CX
- ImulAXDX = 1<<26, // possible multiply into DX:AX
-};
-
void proginfo(ProgInfo*, Prog*);
if(r != nil)
for(;;) {
p = r->prog;
- if(p->as != ANOP || p->from.type != D_NONE || p->to.type != D_NONE)
+ if(p->as != ANOP || p->from.type != TYPE_NONE || p->to.type != TYPE_NONE)
break;
r1 = uniqs(r);
if(r1 == nil)
case ALEAL:
if(regtyp(&p->to))
if(p->from.sym != nil)
- if(p->from.index == D_NONE || p->from.index == D_CONST)
+ if(p->from.index == REG_NONE)
conprop(r);
break;
case AMOVSS:
case AMOVSD:
if(regtyp(&p->to))
- if(p->from.type == D_CONST || p->from.type == D_FCONST)
+ if(p->from.type == TYPE_CONST || p->from.type == TYPE_FCONST)
conprop(r);
break;
}
r1 = rnops(uniqs(r));
if(r1 != nil) {
p1 = r1->prog;
- if(p->as == p1->as && p->to.type == p1->from.type){
+ if(p->as == p1->as && p->to.type == p1->from.type && p->to.reg == p1->from.reg){
p1->as = AMOVL;
t++;
}
case AADDL:
case AADDW:
- if(p->from.type != D_CONST || needc(p->link))
+ if(p->from.type != TYPE_CONST || needc(p->link))
break;
if(p->from.offset == -1){
if(p->as == AADDL)
case ASUBL:
case ASUBW:
- if(p->from.type != D_CONST || needc(p->link))
+ if(p->from.type != TYPE_CONST || needc(p->link))
break;
if(p->from.offset == -1) {
if(p->as == ASUBL)
if(debug['P'] && debug['v'])
print("%P ===delete===\n", p);
- p->as = ANOP;
- p->from = zprog.from;
- p->to = zprog.to;
+ nopout(p);
ostats.ndelmov++;
}
int
regtyp(Adr *a)
{
- int t;
-
- t = a->type;
- if(t >= D_AX && t <= D_DI)
- return 1;
- if(t >= D_X0 && t <= D_X7)
- return 1;
- return 0;
+ return a->type == TYPE_REG && (REG_AX <= a->reg && a->reg <= REG_DI || REG_X0 <= a->reg && a->reg <= REG_X7);
}
// movb elimination.
p->as = ANOTL;
break;
}
- if(regtyp(&p->from) || p->from.type == D_CONST) {
+ if(regtyp(&p->from) || p->from.type == TYPE_CONST) {
// move or artihmetic into partial register.
// from another register or constant can be movl.
// we don't switch to 32-bit arithmetic if it can
if(info.reguse | info.regset)
return 0;
- if((info.flags & Move) && (info.flags & (SizeL|SizeQ|SizeF|SizeD)) && p->to.type == v1->type)
+ if((info.flags & Move) && (info.flags & (SizeL|SizeQ|SizeF|SizeD)) && p->to.type == v1->type && p->to.reg == v1->reg)
goto gotit;
if(copyau(&p->from, v2) || copyau(&p->to, v2))
copysub(&p->to, v1, v2, 1);
if(debug['P']) {
print("gotit: %D->%D\n%P", v1, v2, r->prog);
- if(p->from.type == v2->type)
+ if(p->from.type == v2->type && p->from.reg == v2->reg)
print(" excise");
print("\n");
}
if(debug['P'])
print("%P\n", r->prog);
}
- t = v1->type;
- v1->type = v2->type;
- v2->type = t;
+ t = v1->reg;
+ v1->reg = v2->reg;
+ v2->reg = t;
if(debug['P'])
print("%P last\n", r->prog);
return 1;
return 3;
case ACALL:
- if(REGEXT && v->type <= REGEXT && v->type > exregoffset)
+ if(REGEXT && v->type == TYPE_REG && v->reg <= REGEXT && v->reg > exregoffset)
return 2;
- if(REGARG >= 0 && v->type == (uchar)REGARG)
+ if(REGARG >= 0 && v->type == TYPE_REG && v->reg == (uchar)REGARG)
return 2;
- if(v->type == p->from.type)
+ if(v->type == p->from.type && v->reg == p->from.reg)
return 2;
if(s != nil) {
return 3;
case ATEXT:
- if(REGARG >= 0 && v->type == (uchar)REGARG)
+ if(REGARG >= 0 && v->type == TYPE_REG && v->reg == (uchar)REGARG)
return 3;
return 0;
}
return 0;
proginfo(&info, p);
- if((info.reguse|info.regset) & RtoB(v->type))
+ if((info.reguse|info.regset) & RtoB(v->reg))
return 2;
if(info.flags & LeftAddr)
static int
copyas(Adr *a, Adr *v)
{
- if(D_AL <= a->type && a->type <= D_BL)
+ if(REG_AL <= a->reg && a->reg <= REG_BL)
fatal("use of byte register");
- if(D_AL <= v->type && v->type <= D_BL)
+ if(REG_AL <= v->reg && v->reg <= REG_BL)
fatal("use of byte register");
- if(a->type != v->type)
+ if(a->type != v->type || a->name != v->name || a->reg != v->reg)
return 0;
if(regtyp(v))
return 1;
- if(v->type == D_AUTO || v->type == D_PARAM)
+ if(v->type == TYPE_MEM && (v->name == NAME_AUTO || v->name == NAME_PARAM))
if(v->offset == a->offset)
return 1;
return 0;
int
sameaddr(Addr *a, Addr *v)
{
- if(a->type != v->type)
+ if(a->type != v->type || a->name != v->name || a->reg != v->reg)
return 0;
if(regtyp(v))
return 1;
- if(v->type == D_AUTO || v->type == D_PARAM)
+ if(v->type == TYPE_MEM && (v->name == NAME_AUTO || v->name == NAME_PARAM))
if(v->offset == a->offset)
return 1;
return 0;
if(copyas(a, v))
return 1;
if(regtyp(v)) {
- if(a->type-D_INDIR == v->type)
+ if(a->type == TYPE_MEM && a->reg == v->reg)
return 1;
- if(a->index == v->type)
+ if(a->index == v->reg)
return 1;
}
return 0;
static int
copysub(Adr *a, Adr *v, Adr *s, int f)
{
- int t;
+ int reg;
if(copyas(a, v)) {
- t = s->type;
- if(t >= D_AX && t <= D_DI || t >= D_X0 && t <= D_X7) {
+ reg = s->reg;
+ if(reg >= REG_AX && reg <= REG_DI || reg >= REG_X0 && reg <= REG_X7) {
if(f)
- a->type = t;
+ a->reg = reg;
}
return 0;
}
if(regtyp(v)) {
- t = v->type;
- if(a->type == t+D_INDIR) {
- if((s->type == D_BP) && a->index != D_NONE)
+ reg = v->reg;
+ if(a->type == TYPE_MEM && a->reg == reg) {
+ if((s->reg == REG_BP) && a->index != TYPE_NONE)
return 1; /* can't use BP-base with index */
if(f)
- a->type = s->type+D_INDIR;
+ a->reg = s->reg;
// return 0;
}
- if(a->index == t) {
+ if(a->index == reg) {
if(f)
- a->index = s->type;
+ a->index = s->reg;
return 0;
}
return 0;
case 3: // set
if(p->as == p0->as)
if(p->from.type == p0->from.type)
+ if(p->from.reg == p0->from.reg)
if(p->from.node == p0->from.node)
if(p->from.offset == p0->from.offset)
if(p->from.scale == p0->from.scale)
- if(p->from.type == D_FCONST && p->from.u.dval == p0->from.u.dval)
+ if(p->from.type == TYPE_FCONST && p->from.u.dval == p0->from.u.dval)
if(p->from.index == p0->from.index) {
excise(r);
goto loop;
smallindir(Addr *a, Addr *reg)
{
return regtyp(reg) &&
- a->type == D_INDIR + reg->type &&
- a->index == D_NONE &&
+ a->type == TYPE_MEM && a->reg == reg->reg &&
+ a->index == REG_NONE &&
0 <= a->offset && a->offset < 4096;
}
int
stackaddr(Addr *a)
{
- return regtyp(a) && a->type == D_SP;
+ return a->type == TYPE_REG && a->reg == REG_SP;
}
#include "opt.h"
// Matches real RtoB but can be used in global initializer.
-#define RtoB(r) (1<<((r)-D_AX))
+#define RtoB(r) (1<<((r)-REG_AX))
enum {
- AX = RtoB(D_AX),
- BX = RtoB(D_BX),
- CX = RtoB(D_CX),
- DX = RtoB(D_DX),
- DI = RtoB(D_DI),
- SI = RtoB(D_SI),
+ AX = RtoB(REG_AX),
+ BX = RtoB(REG_BX),
+ CX = RtoB(REG_CX),
+ DX = RtoB(REG_DX),
+ DI = RtoB(REG_DI),
+ SI = RtoB(REG_SI),
LeftRdwr = LeftRead | LeftWrite,
RightRdwr = RightRead | RightWrite,
if(info->flags == 0)
fatal("unknown instruction %P", p);
- if((info->flags & ShiftCX) && p->from.type != D_CONST)
+ if((info->flags & ShiftCX) && p->from.type != TYPE_CONST)
info->reguse |= CX;
if(info->flags & ImulAXDX) {
- if(p->to.type == D_NONE) {
+ if(p->to.type == TYPE_NONE) {
info->reguse |= AX;
info->regset |= AX | DX;
} else {
}
// Addressing makes some registers used.
- if(p->from.type >= D_INDIR)
- info->regindex |= RtoB(p->from.type-D_INDIR);
- if(p->from.index != D_NONE)
+ if(p->from.type == TYPE_MEM && p->from.name == NAME_NONE)
+ info->regindex |= RtoB(p->from.reg);
+ if(p->from.index != REG_NONE)
info->regindex |= RtoB(p->from.index);
- if(p->to.type >= D_INDIR)
- info->regindex |= RtoB(p->to.type-D_INDIR);
- if(p->to.index != D_NONE)
+ if(p->to.type == TYPE_MEM && p->to.name == NAME_NONE)
+ info->regindex |= RtoB(p->to.reg);
+ if(p->to.index != REG_NONE)
info->regindex |= RtoB(p->to.index);
}
if(first) {
fmtinstall('Q', Qconv);
- exregoffset = D_DI; // no externals
+ exregoffset = REG_DI; // no externals
first = 0;
}
var[i].node = regnodes[i];
}
- regbits = RtoB(D_SP);
+ regbits = RtoB(REG_SP);
for(z=0; z<BITS; z++) {
externs.b[z] = 0;
params.b[z] = 0;
proginfo(&info, p);
// Avoid making variables for direct-called functions.
- if(p->as == ACALL && p->to.type == D_EXTERN)
+ if(p->as == ACALL && p->to.type == TYPE_MEM && p->to.name == NAME_EXTERN)
continue;
r->use1.b[0] |= info.reguse | info.regindex;
}
for(r = firstr; r != R; r = (Reg*)r->f.link) {
p = r->f.prog;
- if(p->as == AVARDEF && isfat(p->to.node->type) && p->to.node->opt != nil) {
+ if(p->as == AVARDEF && isfat(((Node*)(p->to.node))->type) && ((Node*)(p->to.node))->opt != nil) {
active++;
walkvardef(p->to.node, r, active);
}
for(p=firstp; p!=P; p=p->link) {
while(p->link != P && p->link->as == ANOP)
p->link = p->link->link;
- if(p->to.type == D_BRANCH)
+ if(p->to.type == TYPE_BRANCH)
while(p->to.u.branch != P && p->to.u.branch->as == ANOP)
p->to.u.branch = p->to.u.branch->link;
}
if(!use_sse)
for(p=firstp; p!=P; p=p->link) {
- if(p->from.type >= D_X0 && p->from.type <= D_X7)
- fatal("invalid use of %R with GO386=387: %P", p->from.type, p);
- if(p->to.type >= D_X0 && p->to.type <= D_X7)
- fatal("invalid use of %R with GO386=387: %P", p->to.type, p);
+ if(p->from.reg >= REG_X0 && p->from.reg <= REG_X7)
+ fatal("invalid use of %R with GO386=387: %P", p->from.reg, p);
+ if(p->to.reg >= REG_X0 && p->to.reg <= REG_X7)
+ fatal("invalid use of %R with GO386=387: %P", p->to.reg, p);
}
if(debug['R']) {
a = &p1->to;
a->offset = v->offset;
a->etype = v->etype;
- a->type = v->name;
+ a->type = TYPE_MEM;
+ a->name = v->name;
a->node = v->node;
a->sym = linksym(v->node->sym);
break;
}
- p1->from.type = rn;
+ p1->from.type = TYPE_REG;
+ p1->from.reg = rn;
+ p1->from.name = 0;
if(!f) {
p1->from = *a;
*a = zprog.from;
- a->type = rn;
+ a->type = TYPE_REG;
+ a->reg = rn;
if(v->etype == TUINT8)
p1->as = AMOVB;
if(v->etype == TUINT16)
uint32 b;
b = 0;
- if(r >= D_INDIR)
- r -= D_INDIR;
- if(r >= D_AX && r <= D_DI)
+ if(r >= REG_AX && r <= REG_DI)
b |= RtoB(r);
else
- if(r >= D_AL && r <= D_BL)
- b |= RtoB(r-D_AL+D_AX);
+ if(r >= REG_AL && r <= REG_BL)
+ b |= RtoB(r-REG_AL+REG_AX);
else
- if(r >= D_AH && r <= D_BH)
- b |= RtoB(r-D_AH+D_AX);
+ if(r >= REG_AH && r <= REG_BH)
+ b |= RtoB(r-REG_AH+REG_AX);
else
- if(r >= D_X0 && r <= D_X0+7)
+ if(r >= REG_X0 && r <= REG_X0+7)
b |= FtoB(r);
return b;
}
mkvar(Reg *r, Adr *a)
{
Var *v;
- int i, t, n, et, z, w, flag, regu;
+ int i, n, et, z, w, flag, regu;
int32 o;
Bits bit;
Node *node;
/*
* mark registers used
*/
- t = a->type;
- if(t == D_NONE)
+ if(a->type == TYPE_NONE)
goto none;
if(r != R)
r->use1.b[0] |= doregbits(a->index);
- switch(t) {
+ switch(a->type) {
default:
- regu = doregbits(t);
+ regu = doregbits(a->reg);
if(regu == 0)
goto none;
bit = zbits;
bit.b[0] = regu;
return bit;
- case D_ADDR:
- a->type = a->index;
+ case TYPE_ADDR:
+ a->type = TYPE_MEM;
bit = mkvar(r, a);
setaddrs(bit);
- a->type = t;
+ a->type = TYPE_ADDR;
ostats.naddr++;
goto none;
- case D_EXTERN:
- case D_STATIC:
- case D_PARAM:
- case D_AUTO:
- n = t;
- break;
+ case TYPE_MEM:
+ switch(a->name) {
+ default:
+ goto none;
+ case NAME_EXTERN:
+ case NAME_STATIC:
+ case NAME_PARAM:
+ case NAME_AUTO:
+ n = a->name;
+ break;
+ }
}
node = a->node;
node->opt = v;
bit = blsh(i);
- if(n == D_EXTERN || n == D_STATIC)
+ if(n == NAME_EXTERN || n == NAME_STATIC)
for(z=0; z<BITS; z++)
externs.b[z] |= bit.b[z];
- if(n == D_PARAM)
+ if(n == NAME_PARAM)
for(z=0; z<BITS; z++)
params.b[z] |= bit.b[z];
if(r->use1.b[z] & bb) {
change += CREF * r->f.loop;
if(p->as == AFMOVL || p->as == AFMOVW)
- if(BtoR(bb) != D_F0)
+ if(BtoR(bb) != REG_F0)
change = -CINF;
}
if((r->use2.b[z]|r->set.b[z]) & bb) {
change += CREF * r->f.loop;
if(p->as == AFMOVL || p->as == AFMOVW)
- if(BtoR(bb) != D_F0)
+ if(BtoR(bb) != REG_F0)
change = -CINF;
}
}
if(STORE(r) & r->regdiff.b[z] & bb) {
change -= CLOAD * r->f.loop;
if(p->as == AFMOVL || p->as == AFMOVW)
- if(BtoR(bb) != D_F0)
+ if(BtoR(bb) != REG_F0)
change = -CINF;
}
a->sym = nil;
a->node = nil;
a->offset = 0;
- a->type = rn;
+ a->type = TYPE_REG;
+ a->reg = rn;
+ a->name = 0;
ostats.ncvtreg++;
}
RtoB(int r)
{
- if(r < D_AX || r > D_DI)
+ if(r < REG_AX || r > REG_DI)
return 0;
- return 1L << (r-D_AX);
+ return 1L << (r-REG_AX);
}
int
b &= 0xffL;
if(b == 0)
return 0;
- return bitno(b) + D_AX;
+ return bitno(b) + REG_AX;
}
uint32
FtoB(int f)
{
- if(f < D_X0 || f > D_X7)
+ if(f < REG_X0 || f > REG_X7)
return 0;
- return 1L << (f - D_X0 + 8);
+ return 1L << (f - REG_X0 + 8);
}
int
b &= 0xFF00L;
if(b == 0)
return 0;
- return bitno(b) - 8 + D_X0;
+ return bitno(b) - 8 + REG_X0;
}
void
enum
{
- AXXX,
- AAAA,
+ AAAA = A_ARCHSPECIFIC,
AAAD,
AAAM,
AAAS,
ABTSL,
ABTSW,
ABYTE,
- ACALL,
ACLC,
ACLD,
ACLI,
ACMPSW,
ADAA,
ADAS,
- ADATA,
ADECB,
ADECL,
ADECW,
ADIVL,
ADIVW,
AENTER,
- AGLOBL,
- AGOK,
- AHISTORY,
AHLT,
AIDIVB,
AIDIVL,
AJLS,
AJLT,
AJMI,
- AJMP,
AJNE,
AJOC,
AJOS,
AMULB,
AMULL,
AMULW,
- ANAME,
ANEGB,
ANEGL,
ANEGW,
- ANOP,
ANOTB,
ANOTL,
ANOTW,
ARCRW,
AREP,
AREPN,
- ARET,
AROLB,
AROLL,
AROLW,
ATESTB,
ATESTL,
ATESTW,
- ATEXT,
AVERR,
AVERW,
AWAIT,
AFYL2X,
AFYL2XP1,
- AEND,
- ADYNT_,
- AINIT_,
- ASIGNAME,
ACMPXCHGB,
ACMPXCHGL,
ABSWAPL,
- AUNDEF,
// SSE2
AADDPD,
APINSRD,
APSHUFB,
- AUSEFIELD,
- ATYPE,
- AFUNCDATA,
- APCDATA,
- ACHECKNIL,
- AVARDEF,
- AVARKILL,
- ADUFFCOPY,
- ADUFFZERO,
ALAST
};
enum
{
- D_AL = 0,
- D_CL,
- D_DL,
- D_BL,
-
- D_AH = 4,
- D_CH,
- D_DH,
- D_BH,
-
- D_AX = 8,
- D_CX,
- D_DX,
- D_BX,
- D_SP,
- D_BP,
- D_SI,
- D_DI,
-
- D_F0 = 16,
- D_F7 = D_F0 + 7,
-
- D_CS = 24,
- D_SS,
- D_DS,
- D_ES,
- D_FS,
- D_GS,
-
- D_GDTR, /* global descriptor table register */
- D_IDTR, /* interrupt descriptor table register */
- D_LDTR, /* local descriptor table register */
- D_MSW, /* machine status word */
- D_TASK, /* task register */
-
- D_CR = 35,
- D_DR = 43,
- D_TR = 51,
-
- D_X0 = 59,
- D_X1,
- D_X2,
- D_X3,
- D_X4,
- D_X5,
- D_X6,
- D_X7,
+ REG_NONE = 0,
+
+ REG_AL = 0+16,
+ REG_CL,
+ REG_DL,
+ REG_BL,
+
+ REG_AH = 4+16,
+ REG_CH,
+ REG_DH,
+ REG_BH,
+
+ REG_AX = 8+16,
+ REG_CX,
+ REG_DX,
+ REG_BX,
+ REG_SP,
+ REG_BP,
+ REG_SI,
+ REG_DI,
+
+ REG_F0 = 16+16,
+ REG_F7 = REG_F0 + 7+16,
+
+ REG_CS = 24+16,
+ REG_SS,
+ REG_DS,
+ REG_ES,
+ REG_FS,
+ REG_GS,
+
+ REG_GDTR, /* global descriptor table register */
+ REG_IDTR, /* interrupt descriptor table register */
+ REG_LDTR, /* local descriptor table register */
+ REG_MSW, /* machine status word */
+ REG_TASK, /* task register */
+
+ REG_CR = 35+16,
+ REG_DR = 43+16,
+ REG_TR = 51+16,
+
+ REG_X0 = 59+16,
+ REG_X1,
+ REG_X2,
+ REG_X3,
+ REG_X4,
+ REG_X5,
+ REG_X6,
+ REG_X7,
- D_TLS = 67,
- D_NONE = 68,
-
- D_BRANCH = 69,
- D_EXTERN = 70,
- D_STATIC = 71,
- D_AUTO = 72,
- D_PARAM = 73,
- D_CONST = 74,
- D_FCONST = 75,
- D_SCONST = 76,
- D_ADDR = 77,
-
- D_INDIR, /* additive */
-
- D_CONST2 = D_INDIR+D_INDIR,
-
- D_LAST,
+ REG_TLS = 67+16,
+ MAXREG = 68+16,
T_TYPE = 1<<0,
T_INDEX = 1<<1,
T_GOTYPE = 1<<7,
REGARG = -1,
- REGRET = D_AX,
- FREGRET = D_F0,
- REGSP = D_SP,
- REGTMP = D_DI,
+ REGRET = REG_AX,
+ FREGRET = REG_F0,
+ REGSP = REG_SP,
+ REGTMP = REG_DI,
};
/*
EXTERN Biobuf obuf;
EXTERN Link* ctxt;
EXTERN Biobuf bstdout;
+EXTERN Prog* lastpc;
void* alloc(int32);
void* allocn(void*, int32, int32);
%left '*' '/' '%'
%token <lval> LMOVW LMOVB LABS LLOGW LSHW LADDW LCMP LCROP
%token <lval> LBRA LFMOV LFCONV LFCMP LFADD LFMA LTRAP LXORW
-%token <lval> LNOP LEND LRETT LWORD LTEXT LDATA LRETRN
+%token <lval> LNOP LEND LRETT LWORD LTEXT LGLOBL LDATA LRETRN
%token <lval> LCONST LSP LSB LFP LPC LCREG LFLUSH
%token <lval> LREG LFREG LR LCR LF LFPSCR
%token <lval> LLR LCTR LSPR LSPREG LSEG LMSR
%token <sval> LSCONST
%token <sym> LNAME LLAB LVAR
%type <lval> con expr pointer offset sreg
-%type <addr> addr rreg regaddr name creg freg xlreg lr ctr
-%type <addr> imm ximm fimm rel psr lcr cbit fpscr fpscrf msr mask
+%type <addr> addr rreg regaddr name creg freg xlreg lr ctr textsize
+%type <addr> imm ximm fimm rel psr lcr cbit fpscr msr mask
%%
prog:
| prog line
*/
LMOVW rreg ',' rreg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LMOVW addr ',' rreg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LMOVW regaddr ',' rreg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LMOVB rreg ',' rreg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LMOVB addr ',' rreg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LMOVB regaddr ',' rreg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
/*
* load floats
*/
| LFMOV addr ',' freg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LFMOV regaddr ',' freg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LFMOV fimm ',' freg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LFMOV freg ',' freg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LFMOV freg ',' addr
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LFMOV freg ',' regaddr
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
/*
* store ints and bytes
*/
| LMOVW rreg ',' addr
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LMOVW rreg ',' regaddr
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LMOVB rreg ',' addr
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LMOVB rreg ',' regaddr
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
/*
* store floats
*/
| LMOVW freg ',' addr
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LMOVW freg ',' regaddr
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
/*
* floating point status
*/
| LMOVW fpscr ',' freg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LMOVW freg ',' fpscr
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LMOVW freg ',' imm ',' fpscr
{
- outgcode($1, &$2, NREG, &$4, &$6);
+ outgcode($1, &$2, 0, &$4, &$6);
}
| LMOVW fpscr ',' creg
{
- outcode($1, &$2, NREG, &$4);
- }
-| LMOVW imm ',' fpscrf
- {
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LMTFSB imm ',' con
{
*/
| LMOVW rreg ',' imm ',' lcr
{
- outgcode($1, &$2, NREG, &$4, &$6);
+ outgcode($1, &$2, 0, &$4, &$6);
}
| LMOVW rreg ',' creg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LMOVW rreg ',' lcr
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
/*
* integer operations
}
| LADDW rreg ',' imm ',' rreg
{
- outgcode($1, &$2, NREG, &$4, &$6);
+ outgcode($1, &$2, 0, &$4, &$6);
}
| LADDW rreg ',' rreg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LADDW imm ',' rreg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LLOGW rreg ',' sreg ',' rreg
{
}
| LLOGW rreg ',' rreg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LSHW rreg ',' sreg ',' rreg
{
}
| LSHW rreg ',' rreg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LSHW imm ',' sreg ',' rreg
{
}
| LSHW imm ',' rreg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LABS rreg ',' rreg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LABS rreg
{
- outcode($1, &$2, NREG, &$2);
+ outcode($1, &$2, 0, &$2);
}
/*
* multiply-accumulate
*/
| LMOVW imm ',' rreg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LMOVW ximm ',' rreg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
/*
* condition register operations
*/
| LMOVW creg ',' creg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LMOVW psr ',' creg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LMOVW lcr ',' rreg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LMOVW psr ',' rreg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LMOVW xlreg ',' rreg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LMOVW rreg ',' xlreg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LMOVW creg ',' psr
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LMOVW rreg ',' psr
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
/*
* branch, branch conditional
*/
| LBRA rel
{
- outcode($1, &nullgen, NREG, &$2);
+ outcode($1, &nullgen, 0, &$2);
}
| LBRA addr
{
- outcode($1, &nullgen, NREG, &$2);
+ outcode($1, &nullgen, 0, &$2);
}
| LBRA '(' xlreg ')'
{
- outcode($1, &nullgen, NREG, &$3);
+ outcode($1, &nullgen, 0, &$3);
}
| LBRA ',' rel
{
- outcode($1, &nullgen, NREG, &$3);
+ outcode($1, &nullgen, 0, &$3);
}
| LBRA ',' addr
{
- outcode($1, &nullgen, NREG, &$3);
+ outcode($1, &nullgen, 0, &$3);
}
| LBRA ',' '(' xlreg ')'
{
- outcode($1, &nullgen, NREG, &$4);
+ outcode($1, &nullgen, 0, &$4);
}
| LBRA creg ',' rel
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LBRA creg ',' addr
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LBRA creg ',' '(' xlreg ')'
{
- outcode($1, &$2, NREG, &$5);
+ outcode($1, &$2, 0, &$5);
}
| LBRA con ',' rel
{
{
Addr g;
g = nullgen;
- g.type = D_CONST;
+ g.type = TYPE_CONST;
g.offset = $2;
- outcode($1, &g, $4, &$6);
+ outcode($1, &g, REG_R0+$4, &$6);
}
| LBRA con ',' con ',' addr
{
Addr g;
g = nullgen;
- g.type = D_CONST;
+ g.type = TYPE_CONST;
g.offset = $2;
- outcode($1, &g, $4, &$6);
+ outcode($1, &g, REG_R0+$4, &$6);
}
| LBRA con ',' con ',' '(' xlreg ')'
{
Addr g;
g = nullgen;
- g.type = D_CONST;
+ g.type = TYPE_CONST;
g.offset = $2;
- outcode($1, &g, $4, &$7);
+ outcode($1, &g, REG_R0+$4, &$7);
}
/*
* conditional trap
}
| LTRAP rreg comma
{
- outcode($1, &$2, NREG, &nullgen);
+ outcode($1, &$2, 0, &nullgen);
}
| LTRAP comma
{
- outcode($1, &nullgen, NREG, &nullgen);
+ outcode($1, &nullgen, 0, &nullgen);
}
/*
* floating point operate
*/
| LFCONV freg ',' freg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LFADD freg ',' freg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LFADD freg ',' freg ',' freg
{
}
| LFCMP freg ',' freg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LFCMP freg ',' freg ',' creg
{
*/
| LCMP rreg ',' rreg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LCMP rreg ',' imm
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LCMP rreg ',' rreg ',' creg
{
*/
| LMOVMW addr ',' rreg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LMOVMW rreg ',' addr
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
/*
* various indexed load/store
*/
| LXLD regaddr ',' rreg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LXLD regaddr ',' imm ',' rreg
{
- outgcode($1, &$2, NREG, &$4, &$6);
+ outgcode($1, &$2, 0, &$4, &$6);
}
| LXST rreg ',' regaddr
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LXST rreg ',' imm ',' regaddr
{
- outgcode($1, &$2, NREG, &$4, &$6);
+ outgcode($1, &$2, 0, &$4, &$6);
}
| LXMV regaddr ',' rreg
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LXMV rreg ',' regaddr
{
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
| LXOP regaddr
{
- outcode($1, &$2, NREG, &nullgen);
+ outcode($1, &$2, 0, &nullgen);
}
/*
* NOP
*/
| LNOP comma
{
- outcode($1, &nullgen, NREG, &nullgen);
+ outcode($1, &nullgen, 0, &nullgen);
}
| LNOP rreg comma
{
- outcode($1, &$2, NREG, &nullgen);
+ outcode($1, &$2, 0, &nullgen);
}
| LNOP freg comma
{
- outcode($1, &$2, NREG, &nullgen);
+ outcode($1, &$2, 0, &nullgen);
}
| LNOP ',' rreg
{
- outcode($1, &nullgen, NREG, &$3);
+ outcode($1, &nullgen, 0, &$3);
}
| LNOP ',' freg
{
- outcode($1, &nullgen, NREG, &$3);
+ outcode($1, &nullgen, 0, &$3);
}
| LNOP imm /* SYSCALL $num: load $num to R0 before syscall and restore R0 to 0 afterwards. */
{
- outcode($1, &$2, NREG, &nullgen);
+ outcode($1, &$2, 0, &nullgen);
}
/*
* word
*/
| LWORD imm comma
{
- outcode($1, &$2, NREG, &nullgen);
+ outcode($1, &$2, 0, &nullgen);
}
| LWORD ximm comma
{
- outcode($1, &$2, NREG, &nullgen);
+ outcode($1, &$2, 0, &nullgen);
}
/*
* PCDATA
*/
| LPCDAT imm ',' imm
{
- if($2.type != D_CONST || $4.type != D_CONST)
+ if($2.type != TYPE_CONST || $4.type != TYPE_CONST)
yyerror("arguments to PCDATA must be integer constants");
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
/*
* FUNCDATA
*/
| LFUNCDAT imm ',' addr
{
- if($2.type != D_CONST)
+ if($2.type != TYPE_CONST)
yyerror("index for FUNCDATA must be integer constant");
- if($4.type != D_EXTERN && $4.type != D_STATIC && $4.type != D_OREG)
+ if($4.type != NAME_EXTERN && $4.type != NAME_STATIC && $4.type != TYPE_MEM)
yyerror("value for FUNCDATA must be symbol reference");
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$4);
}
/*
* END
*/
| LEND comma
{
- outcode($1, &nullgen, NREG, &nullgen);
+ outcode($1, &nullgen, 0, &nullgen);
}
/*
- * TEXT/GLOBL
+ * TEXT
*/
-| LTEXT name ',' imm
+| LTEXT name ',' '$' textsize
{
settext($2.sym);
- outcode($1, &$2, NREG, &$4);
+ outcode($1, &$2, 0, &$5);
}
-| LTEXT name ',' con ',' imm
+| LTEXT name ',' con ',' '$' textsize
{
settext($2.sym);
- $6.offset &= 0xffffffffull;
- $6.offset |= (vlong)ArgsSizeUnknown << 32;
- outcode($1, &$2, $4, &$6);
+ outcode($1, &$2, 0, &$7);
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = $4;
+ }
}
-| LTEXT name ',' con ',' imm '-' con
+/*
+ * GLOBL
+ */
+| LGLOBL name ',' imm
{
settext($2.sym);
- $6.offset &= 0xffffffffull;
- $6.offset |= ($8 & 0xffffffffull) << 32;
- outcode($1, &$2, $4, &$6);
+ outcode($1, &$2, 0, &$4);
}
+| LGLOBL name ',' con ',' imm
+ {
+ settext($2.sym);
+ outcode($1, &$2, 0, &$6);
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = $4;
+ }
+ }
+
/*
* DATA
*/
| LDATA name '/' con ',' imm
{
- outcode($1, &$2, $4, &$6);
+ outcode($1, &$2, 0, &$6);
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = $4;
+ }
}
| LDATA name '/' con ',' ximm
{
- outcode($1, &$2, $4, &$6);
+ outcode($1, &$2, 0, &$6);
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = $4;
+ }
}
| LDATA name '/' con ',' fimm
{
- outcode($1, &$2, $4, &$6);
+ outcode($1, &$2, 0, &$6);
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = $4;
+ }
}
/*
* RETURN
*/
| LRETRN comma
{
- outcode($1, &nullgen, NREG, &nullgen);
+ outcode($1, &nullgen, 0, &nullgen);
}
rel:
con '(' LPC ')'
{
$$ = nullgen;
- $$.type = D_BRANCH;
+ $$.type = TYPE_BRANCH;
$$.offset = $1 + pc;
}
| LNAME offset
$$ = nullgen;
if(pass == 2 && $1->type != LLAB)
yyerror("undefined label: %s", $1->labelname);
- $$.type = D_BRANCH;
+ $$.type = TYPE_BRANCH;
$$.offset = $1->value + $2;
}
sreg
{
$$ = nullgen;
- $$.type = D_REG;
+ $$.type = TYPE_REG;
$$.reg = $1;
}
LLR
{
$$ = nullgen;
- $$.type = D_SPR;
- $$.offset = $1;
+ $$.type = TYPE_REG;
+ $$.reg = $1;
}
lcr:
LCR
{
$$ = nullgen;
- $$.type = D_CREG;
- $$.reg = NREG; /* whole register */
+ $$.type = TYPE_REG;
+ $$.reg = $1; /* whole register */
}
ctr:
LCTR
{
$$ = nullgen;
- $$.type = D_SPR;
- $$.offset = $1;
+ $$.type = TYPE_REG;
+ $$.reg = $1;
}
msr:
LMSR
{
$$ = nullgen;
- $$.type = D_MSR;
+ $$.type = TYPE_REG;
+ $$.reg = $1;
}
psr:
LSPREG
{
$$ = nullgen;
- $$.type = D_SPR;
- $$.offset = $1;
+ $$.type = TYPE_REG;
+ $$.reg = $1;
}
| LSPR '(' con ')'
{
+ if($3 < 0 || $3 >= 1024)
+ yyerror("SPR/DCR out of range");
$$ = nullgen;
- $$.type = $1;
- $$.offset = $3;
+ $$.type = TYPE_REG;
+ $$.reg = $1 + $3;
}
| msr
LFPSCR
{
$$ = nullgen;
- $$.type = D_FPSCR;
- $$.reg = NREG;
- }
-
-fpscrf:
- LFPSCR '(' con ')'
- {
- $$ = nullgen;
- $$.type = D_FPSCR;
- $$.reg = $3;
+ $$.type = TYPE_REG;
+ $$.reg = $1;
}
freg:
LFREG
{
$$ = nullgen;
- $$.type = D_FREG;
+ $$.type = TYPE_REG;
$$.reg = $1;
}
| LF '(' con ')'
{
$$ = nullgen;
- $$.type = D_FREG;
- $$.reg = $3;
+ $$.type = TYPE_REG;
+ $$.reg = REG_F0 + $3;
}
creg:
LCREG
{
$$ = nullgen;
- $$.type = D_CREG;
+ $$.type = TYPE_REG;
$$.reg = $1;
}
| LCR '(' con ')'
{
$$ = nullgen;
- $$.type = D_CREG;
- $$.reg = $3;
+ $$.type = TYPE_REG;
+ $$.reg = REG_C0 + $3;
}
cbit: con
{
$$ = nullgen;
- $$.type = D_REG;
+ $$.type = TYPE_REG;
$$.reg = $1;
}
uint32 v;
$$ = nullgen;
- $$.type = D_CONST;
+ $$.type = TYPE_CONST;
mb = $1;
me = $3;
if(mb < 0 || mb > 31 || me < 0 || me > 31){
$$.offset = v;
}
+textsize:
+ LCONST
+ {
+ $$ = nullgen;
+ $$.type = TYPE_TEXTSIZE;
+ $$.offset = $1;
+ $$.u.argsize = ArgsSizeUnknown;
+ }
+| '-' LCONST
+ {
+ $$ = nullgen;
+ $$.type = TYPE_TEXTSIZE;
+ $$.offset = -$2;
+ $$.u.argsize = ArgsSizeUnknown;
+ }
+| LCONST '-' LCONST
+ {
+ $$ = nullgen;
+ $$.type = TYPE_TEXTSIZE;
+ $$.offset = $1;
+ $$.u.argsize = $3;
+ }
+| '-' LCONST '-' LCONST
+ {
+ $$ = nullgen;
+ $$.type = TYPE_TEXTSIZE;
+ $$.offset = -$2;
+ $$.u.argsize = $4;
+ }
+
ximm:
'$' addr
{
$$ = $2;
- $$.type = D_CONST;
+ $$.type = TYPE_ADDR;
}
| '$' LSCONST
{
$$ = nullgen;
- $$.type = D_SCONST;
+ $$.type = TYPE_SCONST;
memcpy($$.u.sval, $2, sizeof($$.u.sval));
}
'$' LFCONST
{
$$ = nullgen;
- $$.type = D_FCONST;
+ $$.type = TYPE_FCONST;
$$.u.dval = $2;
}
| '$' '-' LFCONST
{
$$ = nullgen;
- $$.type = D_FCONST;
+ $$.type = TYPE_FCONST;
$$.u.dval = -$3;
}
imm: '$' con
{
$$ = nullgen;
- $$.type = D_CONST;
+ $$.type = TYPE_CONST;
$$.offset = $2;
}
{
if($$ < 0 || $$ >= NREG)
print("register value out of range\n");
- $$ = $3;
+ $$ = REG_R0 + $3;
}
regaddr:
'(' sreg ')'
{
$$ = nullgen;
- $$.type = D_OREG;
+ $$.type = TYPE_MEM;
$$.reg = $2;
$$.offset = 0;
}
| '(' sreg '+' sreg ')'
{
$$ = nullgen;
- $$.type = D_OREG;
+ $$.type = TYPE_MEM;
$$.reg = $2;
$$.scale = $4;
$$.offset = 0;
| con '(' sreg ')'
{
$$ = nullgen;
- $$.type = D_OREG;
+ $$.type = TYPE_MEM;
$$.reg = $3;
$$.offset = $1;
}
con '(' pointer ')'
{
$$ = nullgen;
- $$.type = D_OREG;
+ $$.type = TYPE_MEM;
$$.name = $3;
$$.sym = nil;
$$.offset = $1;
| LNAME offset '(' pointer ')'
{
$$ = nullgen;
- $$.type = D_OREG;
+ $$.type = TYPE_MEM;
$$.name = $4;
$$.sym = linklookup(ctxt, $1->name, 0);
$$.offset = $2;
| LNAME '<' '>' offset '(' LSB ')'
{
$$ = nullgen;
- $$.type = D_OREG;
- $$.name = D_STATIC;
+ $$.type = TYPE_MEM;
+ $$.name = NAME_STATIC;
$$.sym = linklookup(ctxt, $1->name, 0);
$$.offset = $4;
}
ushort value;
} itab[] =
{
- "SP", LSP, D_AUTO,
- "SB", LSB, D_EXTERN,
- "FP", LFP, D_PARAM,
- "PC", LPC, D_BRANCH,
-
- "LR", LLR, D_LR,
- "CTR", LCTR, D_CTR,
-
- "XER", LSPREG, D_XER,
- "MSR", LMSR, D_MSR,
- "FPSCR", LFPSCR, D_FPSCR,
- "SPR", LSPR, D_SPR,
- "DCR", LSPR, D_DCR,
-
- "CR", LCR, 0,
- "CR0", LCREG, 0,
- "CR1", LCREG, 1,
- "CR2", LCREG, 2,
- "CR3", LCREG, 3,
- "CR4", LCREG, 4,
- "CR5", LCREG, 5,
- "CR6", LCREG, 6,
- "CR7", LCREG, 7,
+ "SP", LSP, NAME_AUTO,
+ "SB", LSB, NAME_EXTERN,
+ "FP", LFP, NAME_PARAM,
+ "PC", LPC, TYPE_BRANCH,
+
+ "LR", LLR, REG_LR,
+ "CTR", LCTR, REG_CTR,
+
+ "XER", LSPREG, REG_XER,
+ "MSR", LMSR, REG_MSR,
+ "FPSCR", LFPSCR, REG_FPSCR,
+ "SPR", LSPR, REG_SPR0,
+ "DCR", LSPR, REG_DCR0,
+
+ "CR", LCR, REG_CR,
+ "CR0", LCREG, REG_C0,
+ "CR1", LCREG, REG_C1,
+ "CR2", LCREG, REG_C2,
+ "CR3", LCREG, REG_C3,
+ "CR4", LCREG, REG_C4,
+ "CR5", LCREG, REG_C5,
+ "CR6", LCREG, REG_C6,
+ "CR7", LCREG, REG_C7,
"R", LR, 0,
- "R0", LREG, 0,
- "R1", LREG, 1,
- "R2", LREG, 2,
- "R3", LREG, 3,
- "R4", LREG, 4,
- "R5", LREG, 5,
- "R6", LREG, 6,
- "R7", LREG, 7,
- "R8", LREG, 8,
- "R9", LREG, 9,
- "R10", LREG, 10,
- "R11", LREG, 11,
- "R12", LREG, 12,
- "R13", LREG, 13,
- "R14", LREG, 14,
- "R15", LREG, 15,
- "R16", LREG, 16,
- "R17", LREG, 17,
- "R18", LREG, 18,
- "R19", LREG, 19,
- "R20", LREG, 20,
- "R21", LREG, 21,
- "R22", LREG, 22,
- "R23", LREG, 23,
- "R24", LREG, 24,
- "R25", LREG, 25,
- "R26", LREG, 26,
- "R27", LREG, 27,
- "R28", LREG, 28,
- "R29", LREG, 29,
- "g", LREG, 30, // avoid unintentionally clobbering g using R30
- "R31", LREG, 31,
+ "R0", LREG, REG_R0,
+ "R1", LREG, REG_R1,
+ "R2", LREG, REG_R2,
+ "R3", LREG, REG_R3,
+ "R4", LREG, REG_R4,
+ "R5", LREG, REG_R5,
+ "R6", LREG, REG_R6,
+ "R7", LREG, REG_R7,
+ "R8", LREG, REG_R8,
+ "R9", LREG, REG_R9,
+ "R10", LREG, REG_R10,
+ "R11", LREG, REG_R11,
+ "R12", LREG, REG_R12,
+ "R13", LREG, REG_R13,
+ "R14", LREG, REG_R14,
+ "R15", LREG, REG_R15,
+ "R16", LREG, REG_R16,
+ "R17", LREG, REG_R17,
+ "R18", LREG, REG_R18,
+ "R19", LREG, REG_R19,
+ "R20", LREG, REG_R20,
+ "R21", LREG, REG_R21,
+ "R22", LREG, REG_R22,
+ "R23", LREG, REG_R23,
+ "R24", LREG, REG_R24,
+ "R25", LREG, REG_R25,
+ "R26", LREG, REG_R26,
+ "R27", LREG, REG_R27,
+ "R28", LREG, REG_R28,
+ "R29", LREG, REG_R29,
+ "g", LREG, REG_R30, // avoid unintentionally clobbering g using R30
+ "R31", LREG, REG_R31,
"F", LF, 0,
- "F0", LFREG, 0,
- "F1", LFREG, 1,
- "F2", LFREG, 2,
- "F3", LFREG, 3,
- "F4", LFREG, 4,
- "F5", LFREG, 5,
- "F6", LFREG, 6,
- "F7", LFREG, 7,
- "F8", LFREG, 8,
- "F9", LFREG, 9,
- "F10", LFREG, 10,
- "F11", LFREG, 11,
- "F12", LFREG, 12,
- "F13", LFREG, 13,
- "F14", LFREG, 14,
- "F15", LFREG, 15,
- "F16", LFREG, 16,
- "F17", LFREG, 17,
- "F18", LFREG, 18,
- "F19", LFREG, 19,
- "F20", LFREG, 20,
- "F21", LFREG, 21,
- "F22", LFREG, 22,
- "F23", LFREG, 23,
- "F24", LFREG, 24,
- "F25", LFREG, 25,
- "F26", LFREG, 26,
- "F27", LFREG, 27,
- "F28", LFREG, 28,
- "F29", LFREG, 29,
- "F30", LFREG, 30,
- "F31", LFREG, 31,
+ "F0", LFREG, REG_F0,
+ "F1", LFREG, REG_F1,
+ "F2", LFREG, REG_F2,
+ "F3", LFREG, REG_F3,
+ "F4", LFREG, REG_F4,
+ "F5", LFREG, REG_F5,
+ "F6", LFREG, REG_F6,
+ "F7", LFREG, REG_F7,
+ "F8", LFREG, REG_F8,
+ "F9", LFREG, REG_F9,
+ "F10", LFREG, REG_F10,
+ "F11", LFREG, REG_F11,
+ "F12", LFREG, REG_F12,
+ "F13", LFREG, REG_F13,
+ "F14", LFREG, REG_F14,
+ "F15", LFREG, REG_F15,
+ "F16", LFREG, REG_F16,
+ "F17", LFREG, REG_F17,
+ "F18", LFREG, REG_F18,
+ "F19", LFREG, REG_F19,
+ "F20", LFREG, REG_F20,
+ "F21", LFREG, REG_F21,
+ "F22", LFREG, REG_F22,
+ "F23", LFREG, REG_F23,
+ "F24", LFREG, REG_F24,
+ "F25", LFREG, REG_F25,
+ "F26", LFREG, REG_F26,
+ "F27", LFREG, REG_F27,
+ "F28", LFREG, REG_F28,
+ "F29", LFREG, REG_F29,
+ "F30", LFREG, REG_F30,
+ "F31", LFREG, REG_F31,
"CREQV", LCROP, ACREQV,
"CRXOR", LCROP, ACRXOR,
"FMOVS", LFMOV, AFMOVS,
"FMOVDCC", LFCONV, AFMOVDCC, /* fmr. */
- "GLOBL", LTEXT, AGLOBL,
+ "GLOBL", LGLOBL, AGLOBL,
"MOVB", LMOVB, AMOVB,
"MOVBZ", LMOVB, AMOVBZ,
Sym *s;
int i;
- nullgen.type = D_NONE;
- nullgen.name = D_NONE;
- nullgen.reg = NREG;
- nullgen.scale = NREG; // replaced Gen.xreg with Prog.scale
+ nullgen.type = TYPE_NONE;
+ nullgen.name = NAME_NONE;
+ nullgen.reg = 0;
+ nullgen.scale = 0; // replaced Gen.xreg with Prog.scale
nerrors = 0;
iostack = I;
cclean(void)
{
- outcode(AEND, &nullgen, NREG, &nullgen);
+ outcode(AEND, &nullgen, 0, &nullgen);
}
-static Prog *lastpc;
-
void
outcode(int a, Addr *g1, int reg, Addr *g2)
{
if(pass == 1)
goto out;
- if(g1->scale != NREG) {
- if(reg != NREG || g2->scale != NREG)
+ if(g1->scale != 0) {
+ if(reg != 0 || g2->scale != 0)
yyerror("bad addressing modes");
reg = g1->scale;
} else
- if(g2->scale != NREG) {
- if(reg != NREG)
+ if(g2->scale != 0) {
+ if(reg != 0)
yyerror("bad addressing modes");
reg = g2->scale;
}
- p = ctxt->arch->prg();
+ p = emallocz(sizeof(Prog));
p->as = a;
p->lineno = lineno;
if(nosched)
if(pass == 1)
goto out;
- p = ctxt->arch->prg();
+ p = emallocz(sizeof(Prog));
p->as = a;
p->lineno = lineno;
if(nosched)
LRETT = 276,
LWORD = 277,
LTEXT = 278,
- LDATA = 279,
- LRETRN = 280,
- LCONST = 281,
- LSP = 282,
- LSB = 283,
- LFP = 284,
- LPC = 285,
- LCREG = 286,
- LFLUSH = 287,
- LREG = 288,
- LFREG = 289,
- LR = 290,
- LCR = 291,
- LF = 292,
- LFPSCR = 293,
- LLR = 294,
- LCTR = 295,
- LSPR = 296,
- LSPREG = 297,
- LSEG = 298,
- LMSR = 299,
- LPCDAT = 300,
- LFUNCDAT = 301,
- LSCHED = 302,
- LXLD = 303,
- LXST = 304,
- LXOP = 305,
- LXMV = 306,
- LRLWM = 307,
- LMOVMW = 308,
- LMOVEM = 309,
- LMOVFL = 310,
- LMTFSB = 311,
- LMA = 312,
- LFCONST = 313,
- LSCONST = 314,
- LNAME = 315,
- LLAB = 316,
- LVAR = 317
+ LGLOBL = 279,
+ LDATA = 280,
+ LRETRN = 281,
+ LCONST = 282,
+ LSP = 283,
+ LSB = 284,
+ LFP = 285,
+ LPC = 286,
+ LCREG = 287,
+ LFLUSH = 288,
+ LREG = 289,
+ LFREG = 290,
+ LR = 291,
+ LCR = 292,
+ LF = 293,
+ LFPSCR = 294,
+ LLR = 295,
+ LCTR = 296,
+ LSPR = 297,
+ LSPREG = 298,
+ LSEG = 299,
+ LMSR = 300,
+ LPCDAT = 301,
+ LFUNCDAT = 302,
+ LSCHED = 303,
+ LXLD = 304,
+ LXST = 305,
+ LXOP = 306,
+ LXMV = 307,
+ LRLWM = 308,
+ LMOVMW = 309,
+ LMOVEM = 310,
+ LMOVFL = 311,
+ LMTFSB = 312,
+ LMA = 313,
+ LFCONST = 314,
+ LSCONST = 315,
+ LNAME = 316,
+ LLAB = 317,
+ LVAR = 318
};
#endif
/* Tokens. */
#define LRETT 276
#define LWORD 277
#define LTEXT 278
-#define LDATA 279
-#define LRETRN 280
-#define LCONST 281
-#define LSP 282
-#define LSB 283
-#define LFP 284
-#define LPC 285
-#define LCREG 286
-#define LFLUSH 287
-#define LREG 288
-#define LFREG 289
-#define LR 290
-#define LCR 291
-#define LF 292
-#define LFPSCR 293
-#define LLR 294
-#define LCTR 295
-#define LSPR 296
-#define LSPREG 297
-#define LSEG 298
-#define LMSR 299
-#define LPCDAT 300
-#define LFUNCDAT 301
-#define LSCHED 302
-#define LXLD 303
-#define LXST 304
-#define LXOP 305
-#define LXMV 306
-#define LRLWM 307
-#define LMOVMW 308
-#define LMOVEM 309
-#define LMOVFL 310
-#define LMTFSB 311
-#define LMA 312
-#define LFCONST 313
-#define LSCONST 314
-#define LNAME 315
-#define LLAB 316
-#define LVAR 317
+#define LGLOBL 279
+#define LDATA 280
+#define LRETRN 281
+#define LCONST 282
+#define LSP 283
+#define LSB 284
+#define LFP 285
+#define LPC 286
+#define LCREG 287
+#define LFLUSH 288
+#define LREG 289
+#define LFREG 290
+#define LR 291
+#define LCR 292
+#define LF 293
+#define LFPSCR 294
+#define LLR 295
+#define LCTR 296
+#define LSPR 297
+#define LSPREG 298
+#define LSEG 299
+#define LMSR 300
+#define LPCDAT 301
+#define LFUNCDAT 302
+#define LSCHED 303
+#define LXLD 304
+#define LXST 305
+#define LXOP 306
+#define LXMV 307
+#define LRLWM 308
+#define LMOVMW 309
+#define LMOVEM 310
+#define LMOVFL 311
+#define LMTFSB 312
+#define LMA 313
+#define LFCONST 314
+#define LSCONST 315
+#define LNAME 316
+#define LLAB 317
+#define LVAR 318
Addr addr;
}
/* Line 193 of yacc.c. */
-#line 236 "y.tab.c"
+#line 238 "y.tab.c"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
/* Line 216 of yacc.c. */
-#line 249 "y.tab.c"
+#line 251 "y.tab.c"
#ifdef short
# undef short
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 2
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 862
+#define YYLAST 932
/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 81
+#define YYNTOKENS 82
/* YYNNTS -- Number of nonterminals. */
#define YYNNTS 31
/* YYNRULES -- Number of rules. */
-#define YYNRULES 183
+#define YYNRULES 186
/* YYNRULES -- Number of states. */
-#define YYNSTATES 453
+#define YYNSTATES 462
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
#define YYUNDEFTOK 2
-#define YYMAXUTOK 317
+#define YYMAXUTOK 318
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 79, 12, 5, 2,
- 77, 78, 10, 8, 76, 9, 2, 11, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 73, 75,
- 6, 74, 7, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 80, 12, 5, 2,
+ 78, 79, 10, 8, 77, 9, 2, 11, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 74, 76,
+ 6, 75, 7, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 4, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 3, 2, 80, 2, 2, 2,
+ 2, 2, 2, 2, 3, 2, 81, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
- 65, 66, 67, 68, 69, 70, 71, 72
+ 65, 66, 67, 68, 69, 70, 71, 72, 73
};
#if YYDEBUG
0, 0, 3, 4, 7, 8, 13, 18, 23, 26,
28, 31, 34, 39, 44, 49, 54, 59, 64, 69,
74, 79, 84, 89, 94, 99, 104, 109, 114, 119,
- 124, 129, 134, 141, 146, 151, 156, 163, 168, 173,
- 180, 187, 194, 199, 204, 211, 216, 223, 228, 235,
- 240, 245, 248, 255, 260, 265, 270, 277, 282, 287,
- 292, 297, 302, 307, 312, 317, 320, 323, 328, 332,
- 336, 342, 347, 352, 359, 364, 369, 376, 383, 390,
- 399, 404, 409, 413, 416, 421, 426, 433, 442, 447,
- 454, 459, 464, 471, 478, 487, 496, 505, 514, 519,
- 524, 529, 536, 541, 548, 553, 558, 561, 564, 568,
- 572, 576, 580, 583, 587, 591, 596, 601, 604, 609,
- 616, 625, 632, 639, 646, 649, 654, 657, 659, 661,
- 663, 665, 667, 669, 671, 673, 678, 680, 682, 687,
- 689, 694, 696, 701, 703, 707, 710, 713, 716, 720,
- 723, 725, 730, 734, 740, 742, 747, 752, 758, 766,
- 767, 769, 770, 773, 776, 778, 780, 782, 784, 786,
- 789, 792, 795, 799, 801, 805, 809, 813, 817, 821,
- 826, 831, 835, 839
+ 124, 129, 134, 141, 146, 151, 158, 163, 168, 175,
+ 182, 189, 194, 199, 206, 211, 218, 223, 230, 235,
+ 240, 243, 250, 255, 260, 265, 272, 277, 282, 287,
+ 292, 297, 302, 307, 312, 315, 318, 323, 327, 331,
+ 337, 342, 347, 354, 359, 364, 371, 378, 385, 394,
+ 399, 404, 408, 411, 416, 421, 428, 437, 442, 449,
+ 454, 459, 466, 473, 482, 491, 500, 509, 514, 519,
+ 524, 531, 536, 543, 548, 553, 556, 559, 563, 567,
+ 571, 575, 578, 582, 586, 591, 596, 599, 605, 613,
+ 618, 625, 632, 639, 646, 649, 654, 657, 659, 661,
+ 663, 665, 667, 669, 671, 673, 678, 680, 682, 684,
+ 689, 691, 696, 698, 702, 704, 707, 711, 716, 719,
+ 722, 725, 729, 732, 734, 739, 743, 749, 751, 756,
+ 761, 767, 775, 776, 778, 779, 782, 785, 787, 789,
+ 791, 793, 795, 798, 801, 804, 808, 810, 814, 818,
+ 822, 826, 830, 835, 840, 844, 848
};
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
static const yytype_int8 yyrhs[] =
{
- 82, 0, -1, -1, 82, 83, -1, -1, 70, 73,
- 84, 83, -1, 70, 74, 111, 75, -1, 72, 74,
- 111, 75, -1, 57, 75, -1, 75, -1, 85, 75,
- -1, 1, 75, -1, 13, 87, 76, 87, -1, 13,
- 105, 76, 87, -1, 13, 104, 76, 87, -1, 14,
- 87, 76, 87, -1, 14, 105, 76, 87, -1, 14,
- 104, 76, 87, -1, 22, 105, 76, 96, -1, 22,
- 104, 76, 96, -1, 22, 101, 76, 96, -1, 22,
- 96, 76, 96, -1, 22, 96, 76, 105, -1, 22,
- 96, 76, 104, -1, 13, 87, 76, 105, -1, 13,
- 87, 76, 104, -1, 14, 87, 76, 105, -1, 14,
- 87, 76, 104, -1, 13, 96, 76, 105, -1, 13,
- 96, 76, 104, -1, 13, 94, 76, 96, -1, 13,
- 96, 76, 94, -1, 13, 96, 76, 102, 76, 94,
- -1, 13, 94, 76, 97, -1, 13, 102, 76, 95,
- -1, 66, 102, 76, 110, -1, 13, 87, 76, 102,
- 76, 90, -1, 13, 87, 76, 97, -1, 13, 87,
- 76, 90, -1, 18, 87, 76, 103, 76, 87, -1,
- 18, 102, 76, 103, 76, 87, -1, 18, 87, 76,
- 102, 76, 87, -1, 18, 87, 76, 87, -1, 18,
- 102, 76, 87, -1, 16, 87, 76, 103, 76, 87,
- -1, 16, 87, 76, 87, -1, 17, 87, 76, 103,
- 76, 87, -1, 17, 87, 76, 87, -1, 17, 102,
- 76, 103, 76, 87, -1, 17, 102, 76, 87, -1,
- 15, 87, 76, 87, -1, 15, 87, -1, 67, 87,
- 76, 103, 76, 87, -1, 13, 102, 76, 87, -1,
- 13, 100, 76, 87, -1, 20, 98, 76, 98, -1,
- 20, 98, 76, 110, 76, 98, -1, 13, 97, 76,
- 97, -1, 13, 93, 76, 97, -1, 13, 90, 76,
- 87, -1, 13, 93, 76, 87, -1, 13, 88, 76,
- 87, -1, 13, 87, 76, 88, -1, 13, 97, 76,
- 93, -1, 13, 87, 76, 93, -1, 21, 86, -1,
- 21, 105, -1, 21, 77, 88, 78, -1, 21, 76,
- 86, -1, 21, 76, 105, -1, 21, 76, 77, 88,
- 78, -1, 21, 97, 76, 86, -1, 21, 97, 76,
- 105, -1, 21, 97, 76, 77, 88, 78, -1, 21,
- 110, 76, 86, -1, 21, 110, 76, 105, -1, 21,
- 110, 76, 77, 88, 78, -1, 21, 110, 76, 110,
- 76, 86, -1, 21, 110, 76, 110, 76, 105, -1,
- 21, 110, 76, 110, 76, 77, 88, 78, -1, 27,
- 87, 76, 103, -1, 27, 102, 76, 103, -1, 27,
- 87, 107, -1, 27, 107, -1, 23, 96, 76, 96,
- -1, 25, 96, 76, 96, -1, 25, 96, 76, 96,
- 76, 96, -1, 26, 96, 76, 96, 76, 96, 76,
- 96, -1, 24, 96, 76, 96, -1, 24, 96, 76,
- 96, 76, 97, -1, 19, 87, 76, 87, -1, 19,
- 87, 76, 102, -1, 19, 87, 76, 87, 76, 97,
- -1, 19, 87, 76, 102, 76, 97, -1, 62, 102,
- 76, 87, 76, 102, 76, 87, -1, 62, 102, 76,
- 87, 76, 99, 76, 87, -1, 62, 87, 76, 87,
- 76, 102, 76, 87, -1, 62, 87, 76, 87, 76,
- 99, 76, 87, -1, 63, 105, 76, 87, -1, 63,
- 87, 76, 105, -1, 58, 104, 76, 87, -1, 58,
- 104, 76, 102, 76, 87, -1, 59, 87, 76, 104,
- -1, 59, 87, 76, 102, 76, 104, -1, 61, 104,
- 76, 87, -1, 61, 87, 76, 104, -1, 60, 104,
- -1, 29, 107, -1, 29, 87, 107, -1, 29, 96,
- 107, -1, 29, 76, 87, -1, 29, 76, 96, -1,
- 29, 102, -1, 32, 102, 107, -1, 32, 100, 107,
- -1, 55, 102, 76, 102, -1, 56, 102, 76, 105,
- -1, 30, 107, -1, 33, 106, 76, 102, -1, 33,
- 106, 76, 110, 76, 102, -1, 33, 106, 76, 110,
- 76, 102, 9, 110, -1, 34, 106, 11, 110, 76,
- 102, -1, 34, 106, 11, 110, 76, 100, -1, 34,
- 106, 11, 110, 76, 101, -1, 35, 107, -1, 110,
- 77, 40, 78, -1, 70, 108, -1, 103, -1, 89,
- -1, 91, -1, 49, -1, 46, -1, 50, -1, 54,
- -1, 52, -1, 51, 77, 110, 78, -1, 92, -1,
- 48, -1, 48, 77, 110, 78, -1, 44, -1, 47,
- 77, 110, 78, -1, 41, -1, 46, 77, 110, 78,
- -1, 110, -1, 110, 76, 110, -1, 79, 105, -1,
- 79, 69, -1, 79, 68, -1, 79, 9, 68, -1,
- 79, 110, -1, 43, -1, 45, 77, 110, 78, -1,
- 77, 103, 78, -1, 77, 103, 8, 103, 78, -1,
- 106, -1, 110, 77, 103, 78, -1, 110, 77, 109,
- 78, -1, 70, 108, 77, 109, 78, -1, 70, 6,
- 7, 108, 77, 38, 78, -1, -1, 76, -1, -1,
- 8, 110, -1, 9, 110, -1, 38, -1, 37, -1,
- 39, -1, 36, -1, 72, -1, 9, 110, -1, 8,
- 110, -1, 80, 110, -1, 77, 111, 78, -1, 110,
- -1, 111, 8, 111, -1, 111, 9, 111, -1, 111,
- 10, 111, -1, 111, 11, 111, -1, 111, 12, 111,
- -1, 111, 6, 6, 111, -1, 111, 7, 7, 111,
- -1, 111, 5, 111, -1, 111, 4, 111, -1, 111,
- 3, 111, -1
+ 83, 0, -1, -1, 83, 84, -1, -1, 71, 74,
+ 85, 84, -1, 71, 75, 112, 76, -1, 73, 75,
+ 112, 76, -1, 58, 76, -1, 76, -1, 86, 76,
+ -1, 1, 76, -1, 13, 88, 77, 88, -1, 13,
+ 106, 77, 88, -1, 13, 105, 77, 88, -1, 14,
+ 88, 77, 88, -1, 14, 106, 77, 88, -1, 14,
+ 105, 77, 88, -1, 22, 106, 77, 96, -1, 22,
+ 105, 77, 96, -1, 22, 102, 77, 96, -1, 22,
+ 96, 77, 96, -1, 22, 96, 77, 106, -1, 22,
+ 96, 77, 105, -1, 13, 88, 77, 106, -1, 13,
+ 88, 77, 105, -1, 14, 88, 77, 106, -1, 14,
+ 88, 77, 105, -1, 13, 96, 77, 106, -1, 13,
+ 96, 77, 105, -1, 13, 95, 77, 96, -1, 13,
+ 96, 77, 95, -1, 13, 96, 77, 103, 77, 95,
+ -1, 13, 95, 77, 97, -1, 67, 103, 77, 111,
+ -1, 13, 88, 77, 103, 77, 91, -1, 13, 88,
+ 77, 97, -1, 13, 88, 77, 91, -1, 18, 88,
+ 77, 104, 77, 88, -1, 18, 103, 77, 104, 77,
+ 88, -1, 18, 88, 77, 103, 77, 88, -1, 18,
+ 88, 77, 88, -1, 18, 103, 77, 88, -1, 16,
+ 88, 77, 104, 77, 88, -1, 16, 88, 77, 88,
+ -1, 17, 88, 77, 104, 77, 88, -1, 17, 88,
+ 77, 88, -1, 17, 103, 77, 104, 77, 88, -1,
+ 17, 103, 77, 88, -1, 15, 88, 77, 88, -1,
+ 15, 88, -1, 68, 88, 77, 104, 77, 88, -1,
+ 13, 103, 77, 88, -1, 13, 101, 77, 88, -1,
+ 20, 98, 77, 98, -1, 20, 98, 77, 111, 77,
+ 98, -1, 13, 97, 77, 97, -1, 13, 94, 77,
+ 97, -1, 13, 91, 77, 88, -1, 13, 94, 77,
+ 88, -1, 13, 89, 77, 88, -1, 13, 88, 77,
+ 89, -1, 13, 97, 77, 94, -1, 13, 88, 77,
+ 94, -1, 21, 87, -1, 21, 106, -1, 21, 78,
+ 89, 79, -1, 21, 77, 87, -1, 21, 77, 106,
+ -1, 21, 77, 78, 89, 79, -1, 21, 97, 77,
+ 87, -1, 21, 97, 77, 106, -1, 21, 97, 77,
+ 78, 89, 79, -1, 21, 111, 77, 87, -1, 21,
+ 111, 77, 106, -1, 21, 111, 77, 78, 89, 79,
+ -1, 21, 111, 77, 111, 77, 87, -1, 21, 111,
+ 77, 111, 77, 106, -1, 21, 111, 77, 111, 77,
+ 78, 89, 79, -1, 27, 88, 77, 104, -1, 27,
+ 103, 77, 104, -1, 27, 88, 108, -1, 27, 108,
+ -1, 23, 96, 77, 96, -1, 25, 96, 77, 96,
+ -1, 25, 96, 77, 96, 77, 96, -1, 26, 96,
+ 77, 96, 77, 96, 77, 96, -1, 24, 96, 77,
+ 96, -1, 24, 96, 77, 96, 77, 97, -1, 19,
+ 88, 77, 88, -1, 19, 88, 77, 103, -1, 19,
+ 88, 77, 88, 77, 97, -1, 19, 88, 77, 103,
+ 77, 97, -1, 63, 103, 77, 88, 77, 103, 77,
+ 88, -1, 63, 103, 77, 88, 77, 99, 77, 88,
+ -1, 63, 88, 77, 88, 77, 103, 77, 88, -1,
+ 63, 88, 77, 88, 77, 99, 77, 88, -1, 64,
+ 106, 77, 88, -1, 64, 88, 77, 106, -1, 59,
+ 105, 77, 88, -1, 59, 105, 77, 103, 77, 88,
+ -1, 60, 88, 77, 105, -1, 60, 88, 77, 103,
+ 77, 105, -1, 62, 105, 77, 88, -1, 62, 88,
+ 77, 105, -1, 61, 105, -1, 29, 108, -1, 29,
+ 88, 108, -1, 29, 96, 108, -1, 29, 77, 88,
+ -1, 29, 77, 96, -1, 29, 103, -1, 32, 103,
+ 108, -1, 32, 101, 108, -1, 56, 103, 77, 103,
+ -1, 57, 103, 77, 106, -1, 30, 108, -1, 33,
+ 107, 77, 80, 100, -1, 33, 107, 77, 111, 77,
+ 80, 100, -1, 34, 107, 77, 103, -1, 34, 107,
+ 77, 111, 77, 103, -1, 35, 107, 11, 111, 77,
+ 103, -1, 35, 107, 11, 111, 77, 101, -1, 35,
+ 107, 11, 111, 77, 102, -1, 36, 108, -1, 111,
+ 78, 41, 79, -1, 71, 109, -1, 104, -1, 90,
+ -1, 92, -1, 50, -1, 47, -1, 51, -1, 55,
+ -1, 53, -1, 52, 78, 111, 79, -1, 93, -1,
+ 49, -1, 45, -1, 48, 78, 111, 79, -1, 42,
+ -1, 47, 78, 111, 79, -1, 111, -1, 111, 77,
+ 111, -1, 37, -1, 9, 37, -1, 37, 9, 37,
+ -1, 9, 37, 9, 37, -1, 80, 106, -1, 80,
+ 70, -1, 80, 69, -1, 80, 9, 69, -1, 80,
+ 111, -1, 44, -1, 46, 78, 111, 79, -1, 78,
+ 104, 79, -1, 78, 104, 8, 104, 79, -1, 107,
+ -1, 111, 78, 104, 79, -1, 111, 78, 110, 79,
+ -1, 71, 109, 78, 110, 79, -1, 71, 6, 7,
+ 109, 78, 39, 79, -1, -1, 77, -1, -1, 8,
+ 111, -1, 9, 111, -1, 39, -1, 38, -1, 40,
+ -1, 37, -1, 73, -1, 9, 111, -1, 8, 111,
+ -1, 81, 111, -1, 78, 112, 79, -1, 111, -1,
+ 112, 8, 112, -1, 112, 9, 112, -1, 112, 10,
+ 112, -1, 112, 11, 112, -1, 112, 12, 112, -1,
+ 112, 6, 6, 112, -1, 112, 7, 7, 112, -1,
+ 112, 5, 112, -1, 112, 4, 112, -1, 112, 3,
+ 112, -1
};
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
0, 66, 66, 67, 71, 70, 79, 84, 90, 94,
95, 96, 102, 106, 110, 114, 118, 122, 129, 133,
137, 141, 145, 149, 156, 160, 164, 168, 175, 179,
- 186, 190, 194, 198, 202, 206, 213, 217, 221, 231,
+ 186, 190, 194, 198, 202, 209, 213, 217, 227, 231,
235, 239, 243, 247, 251, 255, 259, 263, 267, 271,
- 275, 279, 286, 293, 297, 304, 308, 316, 320, 324,
- 328, 332, 336, 340, 344, 353, 357, 361, 365, 369,
- 373, 377, 381, 385, 389, 393, 397, 401, 409, 417,
- 428, 432, 436, 440, 447, 451, 455, 459, 463, 467,
- 474, 478, 482, 486, 493, 497, 501, 505, 512, 516,
- 524, 528, 532, 536, 540, 544, 548, 555, 559, 563,
- 567, 571, 575, 582, 586, 593, 602, 613, 620, 625,
- 632, 642, 646, 650, 657, 663, 669, 680, 688, 689,
- 692, 700, 708, 716, 723, 729, 735, 738, 746, 754,
- 760, 768, 774, 782, 790, 811, 816, 824, 830, 837,
- 845, 846, 854, 861, 871, 872, 881, 889, 897, 906,
- 907, 910, 913, 917, 923, 924, 925, 928, 929, 933,
- 937, 941, 945, 951, 952, 956, 960, 964, 968, 972,
- 976, 980, 984, 988
+ 275, 282, 289, 293, 300, 304, 312, 316, 320, 324,
+ 328, 332, 336, 340, 349, 353, 357, 361, 365, 369,
+ 373, 377, 381, 385, 389, 393, 397, 405, 413, 424,
+ 428, 432, 436, 443, 447, 451, 455, 459, 463, 470,
+ 474, 478, 482, 489, 493, 497, 501, 508, 512, 520,
+ 524, 528, 532, 536, 540, 544, 551, 555, 559, 563,
+ 567, 571, 578, 582, 589, 598, 609, 616, 621, 633,
+ 638, 651, 659, 667, 678, 684, 690, 701, 709, 710,
+ 713, 721, 729, 737, 745, 751, 759, 762, 770, 776,
+ 784, 790, 798, 806, 827, 834, 841, 848, 857, 862,
+ 870, 876, 883, 891, 892, 900, 907, 917, 918, 927,
+ 935, 943, 952, 953, 956, 959, 963, 969, 970, 971,
+ 974, 975, 979, 983, 987, 991, 997, 998, 1002, 1006,
+ 1010, 1014, 1018, 1022, 1026, 1030, 1034
};
#endif
"'-'", "'*'", "'/'", "'%'", "LMOVW", "LMOVB", "LABS", "LLOGW", "LSHW",
"LADDW", "LCMP", "LCROP", "LBRA", "LFMOV", "LFCONV", "LFCMP", "LFADD",
"LFMA", "LTRAP", "LXORW", "LNOP", "LEND", "LRETT", "LWORD", "LTEXT",
- "LDATA", "LRETRN", "LCONST", "LSP", "LSB", "LFP", "LPC", "LCREG",
- "LFLUSH", "LREG", "LFREG", "LR", "LCR", "LF", "LFPSCR", "LLR", "LCTR",
- "LSPR", "LSPREG", "LSEG", "LMSR", "LPCDAT", "LFUNCDAT", "LSCHED", "LXLD",
- "LXST", "LXOP", "LXMV", "LRLWM", "LMOVMW", "LMOVEM", "LMOVFL", "LMTFSB",
- "LMA", "LFCONST", "LSCONST", "LNAME", "LLAB", "LVAR", "':'", "'='",
- "';'", "','", "'('", "')'", "'$'", "'~'", "$accept", "prog", "line",
- "@1", "inst", "rel", "rreg", "xlreg", "lr", "lcr", "ctr", "msr", "psr",
- "fpscr", "fpscrf", "freg", "creg", "cbit", "mask", "ximm", "fimm", "imm",
- "sreg", "regaddr", "addr", "name", "comma", "offset", "pointer", "con",
- "expr", 0
+ "LGLOBL", "LDATA", "LRETRN", "LCONST", "LSP", "LSB", "LFP", "LPC",
+ "LCREG", "LFLUSH", "LREG", "LFREG", "LR", "LCR", "LF", "LFPSCR", "LLR",
+ "LCTR", "LSPR", "LSPREG", "LSEG", "LMSR", "LPCDAT", "LFUNCDAT", "LSCHED",
+ "LXLD", "LXST", "LXOP", "LXMV", "LRLWM", "LMOVMW", "LMOVEM", "LMOVFL",
+ "LMTFSB", "LMA", "LFCONST", "LSCONST", "LNAME", "LLAB", "LVAR", "':'",
+ "'='", "';'", "','", "'('", "')'", "'$'", "'~'", "$accept", "prog",
+ "line", "@1", "inst", "rel", "rreg", "xlreg", "lr", "lcr", "ctr", "msr",
+ "psr", "fpscr", "freg", "creg", "cbit", "mask", "textsize", "ximm",
+ "fimm", "imm", "sreg", "regaddr", "addr", "name", "comma", "offset",
+ "pointer", "con", "expr", 0
};
#endif
285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
295, 296, 297, 298, 299, 300, 301, 302, 303, 304,
305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
- 315, 316, 317, 58, 61, 59, 44, 40, 41, 36,
- 126
+ 315, 316, 317, 318, 58, 61, 59, 44, 40, 41,
+ 36, 126
};
# endif
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
static const yytype_uint8 yyr1[] =
{
- 0, 81, 82, 82, 84, 83, 83, 83, 83, 83,
- 83, 83, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 86, 86, 87, 88, 88,
- 89, 90, 91, 92, 93, 93, 93, 94, 95, 96,
- 96, 97, 97, 98, 99, 100, 100, 101, 101, 102,
- 103, 103, 104, 104, 105, 105, 106, 106, 106, 107,
- 107, 108, 108, 108, 109, 109, 109, 110, 110, 110,
- 110, 110, 110, 111, 111, 111, 111, 111, 111, 111,
- 111, 111, 111, 111
+ 0, 82, 83, 83, 85, 84, 84, 84, 84, 84,
+ 84, 84, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 87, 87, 88, 89, 89,
+ 90, 91, 92, 93, 94, 94, 94, 95, 96, 96,
+ 97, 97, 98, 99, 100, 100, 100, 100, 101, 101,
+ 102, 102, 103, 104, 104, 105, 105, 106, 106, 107,
+ 107, 107, 108, 108, 109, 109, 109, 110, 110, 110,
+ 111, 111, 111, 111, 111, 111, 112, 112, 112, 112,
+ 112, 112, 112, 112, 112, 112, 112
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
0, 2, 0, 2, 0, 4, 4, 4, 2, 1,
2, 2, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 6, 4, 4, 4, 6, 4, 4, 6,
- 6, 6, 4, 4, 6, 4, 6, 4, 6, 4,
- 4, 2, 6, 4, 4, 4, 6, 4, 4, 4,
- 4, 4, 4, 4, 4, 2, 2, 4, 3, 3,
- 5, 4, 4, 6, 4, 4, 6, 6, 6, 8,
- 4, 4, 3, 2, 4, 4, 6, 8, 4, 6,
- 4, 4, 6, 6, 8, 8, 8, 8, 4, 4,
- 4, 6, 4, 6, 4, 4, 2, 2, 3, 3,
- 3, 3, 2, 3, 3, 4, 4, 2, 4, 6,
- 8, 6, 6, 6, 2, 4, 2, 1, 1, 1,
- 1, 1, 1, 1, 1, 4, 1, 1, 4, 1,
- 4, 1, 4, 1, 3, 2, 2, 2, 3, 2,
- 1, 4, 3, 5, 1, 4, 4, 5, 7, 0,
- 1, 0, 2, 2, 1, 1, 1, 1, 1, 2,
- 2, 2, 3, 1, 3, 3, 3, 3, 3, 4,
- 4, 3, 3, 3
+ 4, 4, 6, 4, 4, 6, 4, 4, 6, 6,
+ 6, 4, 4, 6, 4, 6, 4, 6, 4, 4,
+ 2, 6, 4, 4, 4, 6, 4, 4, 4, 4,
+ 4, 4, 4, 4, 2, 2, 4, 3, 3, 5,
+ 4, 4, 6, 4, 4, 6, 6, 6, 8, 4,
+ 4, 3, 2, 4, 4, 6, 8, 4, 6, 4,
+ 4, 6, 6, 8, 8, 8, 8, 4, 4, 4,
+ 6, 4, 6, 4, 4, 2, 2, 3, 3, 3,
+ 3, 2, 3, 3, 4, 4, 2, 5, 7, 4,
+ 6, 6, 6, 6, 2, 4, 2, 1, 1, 1,
+ 1, 1, 1, 1, 1, 4, 1, 1, 1, 4,
+ 1, 4, 1, 3, 1, 2, 3, 4, 2, 2,
+ 2, 3, 2, 1, 4, 3, 5, 1, 4, 4,
+ 5, 7, 0, 1, 0, 2, 2, 1, 1, 1,
+ 1, 1, 2, 2, 2, 3, 1, 3, 3, 3,
+ 3, 3, 4, 4, 3, 3, 3
};
/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
static const yytype_uint8 yydefact[] =
{
2, 0, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 159, 159,
- 159, 0, 0, 0, 159, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 9, 3,
- 0, 11, 0, 0, 167, 141, 150, 139, 0, 131,
- 0, 137, 130, 132, 0, 134, 133, 161, 168, 0,
- 0, 0, 0, 0, 128, 0, 129, 136, 0, 0,
- 0, 0, 0, 0, 127, 0, 0, 154, 0, 0,
- 0, 0, 51, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 143, 0, 161, 0, 0, 65, 0, 66,
+ 0, 0, 0, 0, 0, 0, 0, 0, 162, 162,
+ 162, 0, 0, 0, 0, 162, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
+ 3, 0, 11, 0, 0, 170, 140, 153, 138, 0,
+ 131, 0, 137, 130, 132, 0, 134, 133, 164, 171,
+ 0, 0, 0, 0, 0, 128, 0, 129, 136, 0,
+ 0, 0, 0, 0, 0, 127, 0, 0, 157, 0,
+ 0, 0, 0, 50, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 142, 0, 164, 0, 0, 64, 0,
+ 65, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 163, 162, 0, 82, 163, 162, 162, 111, 106,
+ 116, 162, 162, 0, 0, 0, 0, 124, 0, 0,
+ 8, 0, 0, 0, 105, 0, 0, 0, 0, 0,
+ 0, 0, 0, 4, 0, 0, 10, 173, 172, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 176, 0,
+ 149, 148, 152, 174, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 160, 159, 0, 83, 160, 159, 159, 112, 107, 117,
- 159, 159, 0, 0, 0, 124, 0, 0, 8, 0,
- 0, 0, 106, 0, 0, 0, 0, 0, 0, 0,
- 0, 4, 0, 0, 10, 170, 169, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 173, 0, 146, 145,
- 149, 171, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 149,
- 0, 0, 0, 0, 0, 0, 126, 0, 68, 69,
- 0, 0, 0, 0, 0, 0, 147, 0, 0, 0,
- 0, 0, 0, 0, 0, 160, 82, 0, 110, 111,
- 108, 109, 114, 113, 0, 0, 0, 0, 0, 0,
+ 0, 152, 0, 0, 0, 0, 0, 0, 126, 0,
+ 67, 68, 0, 0, 0, 0, 0, 0, 150, 0,
+ 0, 0, 0, 0, 0, 0, 0, 163, 81, 0,
+ 109, 110, 107, 108, 113, 112, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 161, 162, 163, 0,
- 0, 152, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 172, 12, 62, 38, 64, 37, 0, 25,
- 24, 61, 59, 60, 58, 30, 33, 31, 0, 29,
- 28, 63, 57, 54, 0, 53, 34, 14, 13, 165,
- 164, 166, 0, 0, 15, 27, 26, 17, 16, 50,
- 45, 127, 47, 127, 49, 127, 42, 0, 127, 43,
- 127, 90, 91, 55, 143, 0, 67, 0, 71, 72,
- 0, 74, 75, 0, 0, 148, 21, 23, 22, 20,
- 19, 18, 84, 88, 85, 0, 80, 81, 118, 0,
- 0, 115, 116, 100, 0, 0, 102, 105, 104, 0,
- 0, 99, 98, 35, 0, 5, 6, 7, 151, 142,
- 140, 135, 0, 0, 0, 183, 182, 181, 0, 0,
- 174, 175, 176, 177, 178, 0, 0, 0, 155, 156,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 70,
- 0, 0, 0, 125, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 157, 153, 179, 180, 131,
- 36, 32, 0, 44, 46, 48, 41, 39, 40, 92,
- 93, 56, 73, 76, 0, 77, 78, 89, 86, 0,
- 119, 0, 122, 123, 121, 101, 103, 0, 0, 0,
- 0, 0, 52, 0, 138, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 158, 79, 87, 120, 97, 96,
- 144, 95, 94
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 164,
+ 165, 166, 0, 0, 155, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 175, 12, 61, 37, 63,
+ 36, 0, 25, 24, 60, 58, 59, 57, 30, 33,
+ 31, 0, 29, 28, 62, 56, 53, 52, 14, 13,
+ 168, 167, 169, 0, 0, 15, 27, 26, 17, 16,
+ 49, 44, 127, 46, 127, 48, 127, 41, 0, 127,
+ 42, 127, 89, 90, 54, 142, 0, 66, 0, 70,
+ 71, 0, 73, 74, 0, 0, 151, 21, 23, 22,
+ 20, 19, 18, 83, 87, 84, 0, 79, 80, 0,
+ 0, 119, 0, 0, 114, 115, 99, 0, 0, 101,
+ 104, 103, 0, 0, 98, 97, 34, 0, 5, 6,
+ 7, 154, 141, 139, 135, 0, 0, 0, 186, 185,
+ 184, 0, 0, 177, 178, 179, 180, 181, 0, 0,
+ 158, 159, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 69, 0, 0, 0, 125, 0, 0, 0, 0,
+ 144, 117, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 160, 156, 182, 183, 131, 35, 32, 43, 45,
+ 47, 40, 38, 39, 91, 92, 55, 72, 75, 0,
+ 76, 77, 88, 85, 0, 145, 0, 0, 120, 0,
+ 122, 123, 121, 100, 102, 0, 0, 0, 0, 0,
+ 51, 0, 0, 0, 0, 146, 118, 0, 0, 0,
+ 0, 0, 0, 161, 78, 86, 147, 96, 95, 143,
+ 94, 93
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int16 yydefgoto[] =
{
- -1, 1, 39, 229, 40, 97, 62, 63, 64, 65,
- 66, 67, 68, 69, 276, 70, 71, 91, 427, 72,
- 103, 73, 74, 75, 159, 77, 113, 154, 283, 156,
- 157
+ -1, 1, 40, 232, 41, 98, 63, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, 92, 435, 391, 73,
+ 104, 74, 75, 76, 161, 78, 114, 156, 284, 158,
+ 159
};
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
-#define YYPACT_NINF -176
+#define YYPACT_NINF -179
static const yytype_int16 yypact[] =
{
- -176, 464, -176, -63, 560, 637, 97, 97, -24, -24,
- 97, 556, 317, 618, 12, 12, 12, 12, -27, 47,
- -47, -29, 725, 725, -47, -26, -26, -43, -17, 97,
- -17, -23, -24, 658, -26, 97, 51, -11, -176, -176,
- -2, -176, 556, 556, -176, -176, -176, -176, -1, 2,
- 11, -176, -176, -176, 24, -176, -176, 91, -176, 26,
- 716, 556, 57, 65, -176, 85, -176, -176, 92, 98,
- 104, 110, 119, 134, -176, 155, 160, -176, 69, 162,
- 165, 170, 172, 176, 556, 179, 180, 182, 183, 185,
- 556, 187, -176, 2, 91, 736, 326, -176, 196, -176,
- 52, 6, 197, 198, 202, 203, 215, 216, 217, 222,
- -176, 223, 235, -176, 73, -47, -47, -176, -176, -176,
- -47, -47, 239, 79, 178, -176, 240, 246, -176, 97,
- 247, 248, -176, 252, 253, 255, 262, 263, 266, 267,
- 268, -176, 556, 556, -176, -176, -176, 556, 556, 556,
- 556, 193, 556, 556, 166, 9, -176, 278, -176, -176,
- 69, -176, 607, 97, 97, 109, 20, 683, 61, 97,
- 27, 97, 97, 340, 637, 97, 97, 97, 97, -176,
- 97, 97, -24, 97, -24, 556, 166, 326, -176, -176,
- 199, 152, 742, 762, 153, 283, -176, 696, 12, 12,
- 12, 12, 12, 12, 12, 97, -176, 97, -176, -176,
- -176, -176, -176, -176, 382, 4, 556, -26, 725, -24,
- 72, -17, 97, 97, 97, 725, 97, 556, 97, 527,
- 436, 567, 274, 276, 277, 279, 154, -176, -176, 4,
- 97, -176, 556, 556, 556, 353, 339, 556, 556, 556,
- 556, 556, -176, -176, -176, -176, -176, -176, 284, -176,
- -176, -176, -176, -176, -176, -176, -176, -176, 295, -176,
- -176, -176, -176, -176, 303, -176, -176, -176, -176, -176,
- -176, -176, 304, 308, -176, -176, -176, -176, -176, -176,
- -176, 305, -176, 316, -176, 323, -176, 325, 333, -176,
- 334, 335, 336, -176, 343, 342, -176, 326, -176, -176,
- 326, -176, -176, 139, 344, -176, -176, -176, -176, -176,
- -176, -176, -176, 345, 348, 349, -176, -176, -176, 354,
- 355, -176, -176, -176, 356, 357, -176, -176, -176, 360,
- 373, -176, -176, -176, 374, -176, -176, -176, -176, -176,
- -176, -176, 327, 377, 379, 298, 612, 506, 556, 556,
- 125, 125, -176, -176, -176, 405, 410, 556, -176, -176,
- 97, 97, 97, 97, 97, 97, -8, -8, 556, -176,
- 385, 388, 782, -176, -8, 12, 12, -26, 381, 97,
- -17, 382, 382, 97, 429, -176, -176, 498, 498, -176,
- -176, -176, 390, -176, -176, -176, -176, -176, -176, -176,
- -176, -176, -176, -176, 326, -176, -176, -176, -176, 393,
- 462, 712, -176, -176, -176, -176, -176, 398, 399, 416,
- 419, 426, -176, 451, -176, 454, 12, 556, 328, 97,
- 97, 556, 97, 97, -176, -176, -176, -176, -176, -176,
- -176, -176, -176
+ -179, 484, -179, -64, 581, 686, 74, 74, -24, -24,
+ 74, 845, 641, 656, -29, -29, -29, -29, 19, -11,
+ -54, -38, 747, 747, 747, -54, -19, -19, -50, -6,
+ 74, -6, -14, -24, 707, -19, 74, -36, 18, -179,
+ -179, 2, -179, 845, 845, -179, -179, -179, -179, 24,
+ 27, 48, -179, -179, -179, 61, -179, -179, 188, -179,
+ 717, 738, 845, 79, 81, -179, 93, -179, -179, 99,
+ 107, 116, 126, 127, 130, -179, 132, 133, -179, 87,
+ 136, 138, 157, 159, 171, 845, 176, 179, 182, 184,
+ 186, 845, 194, -179, 27, 188, 762, 764, -179, 196,
+ -179, 66, 8, 198, 200, 201, 202, 203, 206, 215,
+ 216, -179, 217, 219, -179, 181, -54, -54, -179, -179,
+ -179, -54, -54, 220, 167, 221, 178, -179, 223, 224,
+ -179, 74, 225, 226, -179, 227, 231, 232, 233, 234,
+ 236, 237, 238, -179, 845, 845, -179, -179, -179, 845,
+ 845, 845, 845, 242, 845, 845, 229, 3, -179, 377,
+ -179, -179, 87, -179, 629, 74, 74, 172, 26, 732,
+ 39, 74, 74, 74, 74, 230, 686, 74, 74, 74,
+ 74, -179, 74, 74, -24, 74, -24, 845, 229, 764,
+ -179, -179, 241, 243, 784, 814, 111, 254, -179, 67,
+ -29, -29, -29, -29, -29, -29, -29, 74, -179, 74,
+ -179, -179, -179, -179, -179, -179, 821, 45, 830, 845,
+ -19, 747, -24, 49, -6, 74, 74, 74, 747, 74,
+ 845, 74, 548, 463, 518, 246, 247, 248, 249, 155,
+ -179, -179, 45, 74, -179, 845, 845, 845, 323, 325,
+ 845, 845, 845, 845, 845, -179, -179, -179, -179, -179,
+ -179, 259, -179, -179, -179, -179, -179, -179, -179, -179,
+ -179, 260, -179, -179, -179, -179, -179, -179, -179, -179,
+ -179, -179, -179, 265, 266, -179, -179, -179, -179, -179,
+ -179, -179, 269, -179, 270, -179, 272, -179, 278, 279,
+ -179, 280, 283, 284, -179, 285, 275, -179, 764, -179,
+ -179, 764, -179, -179, 105, 286, -179, -179, -179, -179,
+ -179, -179, -179, -179, 289, 296, 297, -179, -179, 9,
+ 299, -179, 301, 319, -179, -179, -179, 320, 321, -179,
+ -179, -179, 324, 327, -179, -179, -179, 328, -179, -179,
+ -179, -179, -179, -179, -179, 329, 333, 334, 591, 430,
+ 451, 845, 845, 78, 78, -179, -179, -179, 316, 353,
+ -179, -179, 74, 74, 74, 74, 74, 74, 20, 20,
+ 845, -179, 335, 336, 841, -179, 20, -29, -29, 369,
+ 399, -179, 338, -19, 339, 74, -6, 830, 830, 74,
+ 382, -179, -179, 277, 277, -179, -179, -179, -179, -179,
+ -179, -179, -179, -179, -179, -179, -179, -179, -179, 764,
+ -179, -179, -179, -179, 345, 414, 387, 9, -179, 322,
+ -179, -179, -179, -179, -179, 350, 351, 352, 354, 355,
+ -179, 366, 372, -29, 393, -179, -179, 851, 74, 74,
+ 845, 74, 74, -179, -179, -179, -179, -179, -179, -179,
+ -179, -179
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int16 yypgoto[] =
{
- -176, -176, 306, -176, -176, -88, -5, -73, -176, -154,
- -176, -176, -137, -158, -176, 67, 39, -175, 141, -15,
- 149, 113, 167, 80, 32, 200, 124, -83, 299, 35,
- 70
+ -179, -179, 222, -179, -179, -72, -5, -61, -179, -157,
+ -179, -179, -149, -161, 38, 31, -178, 50, 28, -15,
+ 58, 98, 168, 82, 96, 112, 25, -85, 211, 36,
+ 88
};
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
#define YYTABLE_NINF -1
static const yytype_uint16 yytable[] =
{
- 79, 82, 83, 85, 87, 89, 120, 188, 255, 267,
- 303, 186, 41, 111, 115, 195, 46, 240, 48, 46,
- 46, 48, 48, 191, 131, 256, 133, 135, 137, 110,
- 140, 271, 128, 45, 42, 43, 76, 81, 93, 78,
- 78, 279, 280, 281, 99, 105, 92, 100, 78, 110,
- 60, 98, 84, 84, 129, 84, 47, 123, 123, 50,
- 129, 45, 44, 143, 47, 138, 93, 50, 78, 46,
- 46, 48, 48, 144, 196, 274, 147, 145, 146, 148,
- 102, 106, 107, 108, 109, 80, 116, 241, 149, 254,
- 46, 47, 48, 104, 50, 160, 161, 151, 58, 152,
- 153, 150, 45, 90, 308, 311, 61, 93, 130, 208,
- 132, 134, 54, 55, 305, 56, 46, 47, 48, 179,
- 50, 86, 88, 114, 141, 142, 84, 189, 193, 194,
- 190, 112, 117, 162, 121, 249, 250, 251, 126, 127,
- 46, 163, 48, 118, 119, 136, 173, 139, 125, 129,
- 45, 84, 46, 352, 48, 93, 215, 253, 261, 262,
- 263, 164, 152, 153, 273, 275, 277, 278, 165, 284,
- 287, 288, 289, 290, 166, 292, 294, 296, 299, 301,
- 167, 209, 232, 233, 234, 235, 168, 237, 238, 216,
- 279, 280, 281, 314, 260, 169, 46, 78, 48, 270,
- 236, 257, 78, 411, 264, 266, 286, 272, 401, 78,
- 170, 400, 230, 231, 333, 382, 194, 338, 339, 340,
- 304, 342, 122, 124, 309, 312, 155, 190, 313, 318,
- 306, 171, 78, 265, 380, 206, 172, 381, 174, 210,
- 211, 175, 259, 239, 212, 213, 176, 269, 177, 329,
- 332, 330, 178, 78, 285, 180, 181, 341, 182, 183,
- 78, 184, 343, 185, 316, 319, 320, 321, 322, 323,
- 324, 325, 192, 197, 198, 258, 194, 317, 199, 200,
- 268, 242, 243, 244, 245, 246, 247, 248, 249, 250,
- 251, 201, 202, 203, 415, 297, 155, 302, 204, 205,
- 336, 337, 243, 244, 245, 246, 247, 248, 249, 250,
- 251, 207, 355, 356, 357, 214, 217, 360, 361, 362,
- 363, 364, 218, 219, 220, 42, 43, 328, 221, 222,
- 331, 223, 334, 335, 42, 43, 42, 43, 224, 225,
- 282, 435, 226, 227, 228, 291, 359, 293, 295, 298,
- 300, 315, 348, 44, 349, 350, 252, 351, 45, 358,
- 365, 282, 44, 93, 44, 403, 404, 405, 406, 407,
- 408, 366, 326, 422, 327, 52, 53, 279, 280, 281,
- 367, 370, 368, 46, 425, 48, 369, 94, 432, 58,
- 42, 43, 371, 95, 96, 344, 315, 61, 58, 372,
- 58, 373, 402, 90, 394, 90, 61, 354, 61, 374,
- 375, 376, 377, 92, 416, 409, 410, 190, 44, 378,
- 379, 384, 383, 417, 385, 386, 429, 429, 397, 398,
- 387, 388, 389, 390, 448, 449, 391, 451, 452, 242,
- 243, 244, 245, 246, 247, 248, 249, 250, 251, 392,
- 393, 399, 418, 419, 58, 395, 160, 396, 51, 90,
- 421, 84, 61, 412, 2, 3, 413, 433, 434, 436,
- 426, 437, 447, 146, 439, 440, 450, 4, 5, 6,
+ 80, 83, 84, 86, 88, 90, 121, 258, 270, 304,
+ 188, 243, 42, 112, 116, 259, 48, 197, 389, 51,
+ 47, 274, 49, 111, 190, 133, 130, 135, 137, 139,
+ 47, 142, 49, 47, 48, 49, 193, 51, 143, 144,
+ 79, 79, 61, 99, 119, 120, 390, 93, 101, 79,
+ 127, 103, 107, 108, 109, 110, 85, 117, 124, 124,
+ 124, 85, 46, 47, 131, 49, 115, 94, 46, 85,
+ 79, 48, 131, 94, 51, 43, 44, 198, 146, 147,
+ 148, 46, 244, 280, 281, 282, 94, 81, 252, 253,
+ 254, 55, 56, 145, 57, 105, 111, 162, 163, 85,
+ 77, 82, 149, 257, 45, 150, 87, 89, 100, 106,
+ 210, 132, 48, 134, 136, 51, 113, 118, 47, 122,
+ 49, 181, 309, 312, 128, 129, 151, 131, 306, 85,
+ 140, 138, 192, 141, 123, 125, 126, 208, 58, 152,
+ 59, 212, 213, 195, 196, 60, 214, 215, 62, 280,
+ 281, 282, 315, 211, 355, 47, 164, 49, 165, 256,
+ 264, 265, 266, 154, 155, 175, 276, 277, 278, 279,
+ 166, 285, 288, 289, 290, 291, 167, 293, 295, 297,
+ 300, 302, 384, 196, 168, 235, 236, 237, 238, 219,
+ 240, 241, 191, 169, 153, 260, 154, 155, 267, 269,
+ 79, 275, 416, 170, 171, 79, 268, 172, 407, 173,
+ 174, 406, 79, 176, 46, 177, 47, 336, 49, 94,
+ 341, 342, 343, 305, 345, 47, 48, 49, 157, 51,
+ 192, 314, 233, 234, 178, 79, 179, 317, 320, 321,
+ 322, 323, 324, 325, 326, 217, 262, 382, 180, 239,
+ 383, 272, 330, 182, 332, 333, 183, 79, 286, 184,
+ 263, 185, 261, 186, 79, 273, 346, 271, 280, 281,
+ 282, 187, 287, 194, 47, 199, 49, 200, 201, 202,
+ 203, 318, 298, 204, 303, 250, 251, 252, 253, 254,
+ 310, 313, 205, 206, 207, 319, 209, 216, 218, 157,
+ 220, 221, 222, 223, 224, 339, 340, 242, 225, 226,
+ 227, 228, 420, 229, 230, 231, 331, 335, 334, 196,
+ 337, 338, 307, 316, 344, 351, 352, 353, 354, 361,
+ 43, 447, 362, 358, 359, 360, 368, 369, 363, 364,
+ 365, 366, 367, 283, 370, 371, 372, 373, 292, 374,
+ 294, 296, 299, 301, 381, 375, 376, 377, 442, 45,
+ 378, 379, 380, 405, 283, 385, 386, 408, 409, 410,
+ 411, 412, 413, 387, 388, 327, 392, 328, 393, 430,
+ 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
+ 433, 198, 160, 58, 440, 59, 394, 395, 396, 347,
+ 91, 397, 52, 62, 398, 399, 425, 400, 426, 414,
+ 415, 357, 401, 402, 417, 418, 93, 422, 427, 429,
+ 192, 441, 443, 444, 445, 423, 424, 448, 449, 450,
+ 456, 451, 452, 437, 437, 247, 248, 249, 250, 251,
+ 252, 253, 254, 457, 458, 453, 460, 461, 438, 403,
+ 404, 454, 431, 356, 348, 446, 255, 248, 249, 250,
+ 251, 252, 253, 254, 0, 162, 245, 246, 247, 248,
+ 249, 250, 251, 252, 253, 254, 0, 0, 434, 0,
+ 421, 455, 0, 148, 2, 3, 459, 0, 0, 0,
+ 0, 428, 432, 0, 0, 436, 439, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, 441, 19, 20, 442, 21, 22, 23, 24,
- 420, 424, 443, 446, 428, 431, 247, 248, 249, 250,
- 251, 346, 245, 246, 247, 248, 249, 250, 251, 25,
- 26, 27, 28, 29, 30, 31, 32, 33, 3, 444,
- 34, 35, 445, 430, 36, 345, 37, 423, 353, 38,
- 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 0, 19, 20, 0, 21,
- 22, 23, 24, 0, 42, 43, 0, 0, 42, 43,
- 242, 243, 244, 245, 246, 247, 248, 249, 250, 251,
- 0, 0, 25, 26, 27, 28, 29, 30, 31, 32,
- 33, 0, 44, 34, 35, 0, 44, 36, 0, 37,
- 0, 45, 38, 46, 47, 48, 49, 50, 51, 52,
- 53, 54, 55, 0, 56, 42, 43, 244, 245, 246,
- 247, 248, 249, 250, 251, 0, 42, 43, 58, 0,
- 57, 0, 58, 90, 0, 0, 61, 59, 0, 60,
- 61, 0, 347, 44, 0, 42, 43, 0, 45, 0,
- 46, 0, 48, 49, 44, 0, 52, 53, 54, 55,
- 0, 56, 47, 0, 0, 50, 42, 43, 0, 0,
- 0, 0, 0, 44, 0, 0, 0, 57, 0, 58,
- 46, 0, 48, 0, 59, 0, 84, 61, 57, 0,
- 58, 42, 43, 0, 44, 59, 0, 101, 61, 0,
- 0, 46, 0, 48, 42, 43, 0, 57, 0, 58,
- 0, 0, 0, 0, 59, 0, 0, 61, 0, 44,
- 42, 438, 0, 0, 42, 43, 0, 0, 57, 0,
- 58, 51, 44, 42, 43, 90, 0, 0, 61, 0,
- 47, 0, 0, 50, 42, 43, 0, 0, 44, 0,
- 42, 43, 44, 57, 0, 58, 0, 0, 0, 0,
- 59, 44, 84, 61, 0, 0, 57, 0, 58, 0,
- 42, 43, 44, 59, 0, 0, 61, 0, 44, 0,
- 196, 158, 57, 0, 58, 158, 57, 0, 58, 90,
- 42, 43, 61, 90, 0, 57, 61, 58, 44, 0,
- 0, 0, 90, 0, 0, 61, 94, 0, 58, 0,
- 0, 0, 94, 187, 58, 0, 61, 0, 44, 307,
- 0, 0, 61, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 94, 0, 58, 0, 0, 0, 0, 310,
- 0, 0, 61, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 94, 0, 58, 0, 0, 0, 0, 414,
- 0, 0, 61
+ 17, 18, 0, 19, 20, 0, 21, 22, 23, 24,
+ 25, 245, 246, 247, 248, 249, 250, 251, 252, 253,
+ 254, 0, 0, 0, 0, 0, 0, 0, 0, 349,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 3,
+ 0, 35, 36, 0, 0, 37, 0, 38, 0, 0,
+ 39, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 0, 19, 20, 0,
+ 21, 22, 23, 24, 25, 0, 0, 0, 0, 43,
+ 44, 0, 0, 0, 350, 246, 247, 248, 249, 250,
+ 251, 252, 253, 254, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 0, 0, 35, 36, 0, 45, 37,
+ 0, 38, 0, 46, 39, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 0, 57, 43, 44, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 43,
+ 44, 0, 58, 0, 59, 0, 0, 0, 0, 60,
+ 0, 61, 62, 0, 43, 44, 45, 0, 0, 0,
+ 0, 46, 0, 47, 0, 49, 50, 0, 45, 53,
+ 54, 55, 56, 46, 57, 0, 0, 0, 94, 0,
+ 0, 0, 0, 45, 43, 44, 0, 0, 0, 0,
+ 58, 48, 59, 0, 51, 0, 0, 60, 0, 85,
+ 62, 0, 95, 0, 59, 43, 44, 0, 96, 97,
+ 0, 0, 62, 45, 0, 43, 44, 58, 0, 59,
+ 47, 0, 49, 0, 60, 0, 102, 62, 0, 0,
+ 43, 44, 0, 0, 45, 0, 43, 44, 0, 0,
+ 0, 47, 0, 49, 45, 43, 44, 58, 0, 59,
+ 0, 47, 0, 49, 60, 0, 0, 62, 0, 45,
+ 43, 44, 43, 44, 0, 45, 0, 0, 58, 0,
+ 59, 52, 0, 0, 45, 91, 0, 0, 62, 0,
+ 59, 0, 43, 44, 0, 91, 0, 0, 62, 45,
+ 0, 45, 0, 58, 0, 59, 0, 0, 160, 58,
+ 60, 59, 85, 62, 53, 54, 91, 0, 58, 62,
+ 59, 45, 43, 44, 0, 91, 0, 0, 62, 43,
+ 44, 0, 0, 95, 0, 59, 0, 59, 43, 44,
+ 189, 0, 91, 62, 0, 62, 0, 0, 0, 43,
+ 44, 45, 0, 43, 44, 95, 0, 59, 45, 43,
+ 44, 0, 308, 0, 0, 62, 0, 45, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 45, 0,
+ 0, 0, 45, 0, 0, 95, 0, 59, 45, 0,
+ 0, 0, 311, 0, 59, 62, 0, 0, 0, 91,
+ 0, 329, 62, 59, 0, 0, 0, 0, 91, 0,
+ 85, 62, 95, 0, 59, 0, 0, 0, 59, 419,
+ 316, 0, 62, 91, 59, 0, 62, 0, 0, 91,
+ 0, 0, 62
};
static const yytype_int16 yycheck[] =
{
- 5, 6, 7, 8, 9, 10, 21, 95, 162, 167,
- 185, 94, 75, 18, 19, 9, 43, 8, 45, 43,
- 43, 45, 45, 96, 29, 162, 31, 32, 33, 76,
- 35, 168, 75, 41, 8, 9, 4, 5, 46, 4,
- 5, 37, 38, 39, 12, 13, 11, 12, 13, 76,
- 79, 12, 79, 79, 77, 79, 44, 22, 23, 47,
- 77, 41, 36, 74, 44, 33, 46, 47, 33, 43,
- 43, 45, 45, 75, 68, 48, 77, 42, 43, 77,
- 13, 14, 15, 16, 17, 5, 19, 78, 77, 162,
- 43, 44, 45, 13, 47, 60, 61, 6, 72, 8,
- 9, 77, 41, 77, 192, 193, 80, 46, 28, 114,
- 30, 31, 51, 52, 187, 54, 43, 44, 45, 84,
- 47, 8, 9, 76, 73, 74, 79, 95, 76, 77,
- 95, 18, 19, 76, 21, 10, 11, 12, 25, 26,
- 43, 76, 45, 19, 20, 32, 77, 34, 24, 77,
- 41, 79, 43, 236, 45, 46, 77, 162, 163, 164,
- 165, 76, 8, 9, 169, 170, 171, 172, 76, 174,
- 175, 176, 177, 178, 76, 180, 181, 182, 183, 184,
- 76, 114, 147, 148, 149, 150, 76, 152, 153, 11,
- 37, 38, 39, 40, 162, 76, 43, 162, 45, 167,
- 7, 162, 167, 378, 165, 166, 174, 168, 366, 174,
- 76, 365, 142, 143, 219, 76, 77, 222, 223, 224,
- 185, 226, 22, 23, 192, 193, 59, 192, 193, 197,
- 78, 76, 197, 166, 307, 111, 76, 310, 76, 115,
- 116, 76, 162, 77, 120, 121, 76, 167, 76, 214,
- 218, 216, 76, 218, 174, 76, 76, 225, 76, 76,
- 225, 76, 227, 76, 197, 198, 199, 200, 201, 202,
- 203, 204, 76, 76, 76, 162, 77, 197, 76, 76,
- 167, 3, 4, 5, 6, 7, 8, 9, 10, 11,
- 12, 76, 76, 76, 382, 182, 129, 184, 76, 76,
- 220, 221, 4, 5, 6, 7, 8, 9, 10, 11,
- 12, 76, 242, 243, 244, 76, 76, 247, 248, 249,
- 250, 251, 76, 76, 76, 8, 9, 214, 76, 76,
- 217, 76, 219, 220, 8, 9, 8, 9, 76, 76,
- 173, 414, 76, 76, 76, 178, 7, 180, 181, 182,
- 183, 68, 78, 36, 78, 78, 78, 78, 41, 6,
- 76, 194, 36, 46, 36, 370, 371, 372, 373, 374,
- 375, 76, 205, 388, 207, 49, 50, 37, 38, 39,
- 77, 76, 78, 43, 389, 45, 78, 70, 393, 72,
- 8, 9, 76, 76, 77, 228, 68, 80, 72, 76,
- 72, 76, 367, 77, 77, 77, 80, 240, 80, 76,
- 76, 76, 76, 378, 382, 376, 377, 382, 36, 76,
- 78, 76, 78, 384, 76, 76, 391, 392, 358, 359,
- 76, 76, 76, 76, 439, 440, 76, 442, 443, 3,
- 4, 5, 6, 7, 8, 9, 10, 11, 12, 76,
- 76, 46, 385, 386, 72, 78, 421, 78, 48, 77,
- 79, 79, 80, 78, 0, 1, 78, 38, 78, 76,
- 390, 9, 437, 438, 76, 76, 441, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
- 26, 27, 76, 29, 30, 76, 32, 33, 34, 35,
- 387, 388, 76, 436, 391, 392, 8, 9, 10, 11,
- 12, 75, 6, 7, 8, 9, 10, 11, 12, 55,
- 56, 57, 58, 59, 60, 61, 62, 63, 1, 78,
- 66, 67, 78, 392, 70, 229, 72, 388, 239, 75,
- 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
- 23, 24, 25, 26, 27, -1, 29, 30, -1, 32,
- 33, 34, 35, -1, 8, 9, -1, -1, 8, 9,
+ 5, 6, 7, 8, 9, 10, 21, 164, 169, 187,
+ 95, 8, 76, 18, 19, 164, 45, 9, 9, 48,
+ 44, 170, 46, 77, 96, 30, 76, 32, 33, 34,
+ 44, 36, 46, 44, 45, 46, 97, 48, 74, 75,
+ 4, 5, 80, 12, 19, 20, 37, 11, 12, 13,
+ 25, 13, 14, 15, 16, 17, 80, 19, 22, 23,
+ 24, 80, 42, 44, 78, 46, 77, 47, 42, 80,
+ 34, 45, 78, 47, 48, 8, 9, 69, 76, 43,
+ 44, 42, 79, 38, 39, 40, 47, 5, 10, 11,
+ 12, 52, 53, 75, 55, 13, 77, 61, 62, 80,
+ 4, 5, 78, 164, 37, 78, 8, 9, 12, 13,
+ 115, 29, 45, 31, 32, 48, 18, 19, 44, 21,
+ 46, 85, 194, 195, 26, 27, 78, 78, 189, 80,
+ 34, 33, 96, 35, 22, 23, 24, 112, 71, 78,
+ 73, 116, 117, 77, 78, 78, 121, 122, 81, 38,
+ 39, 40, 41, 115, 239, 44, 77, 46, 77, 164,
+ 165, 166, 167, 8, 9, 78, 171, 172, 173, 174,
+ 77, 176, 177, 178, 179, 180, 77, 182, 183, 184,
+ 185, 186, 77, 78, 77, 149, 150, 151, 152, 11,
+ 154, 155, 96, 77, 6, 164, 8, 9, 167, 168,
+ 164, 170, 380, 77, 77, 169, 168, 77, 369, 77,
+ 77, 368, 176, 77, 42, 77, 44, 222, 46, 47,
+ 225, 226, 227, 187, 229, 44, 45, 46, 60, 48,
+ 194, 195, 144, 145, 77, 199, 77, 199, 200, 201,
+ 202, 203, 204, 205, 206, 78, 164, 308, 77, 7,
+ 311, 169, 216, 77, 218, 219, 77, 221, 176, 77,
+ 164, 77, 164, 77, 228, 169, 230, 169, 38, 39,
+ 40, 77, 176, 77, 44, 77, 46, 77, 77, 77,
+ 77, 199, 184, 77, 186, 8, 9, 10, 11, 12,
+ 194, 195, 77, 77, 77, 199, 77, 77, 77, 131,
+ 77, 77, 77, 77, 77, 223, 224, 78, 77, 77,
+ 77, 77, 384, 77, 77, 77, 218, 221, 220, 78,
+ 222, 223, 79, 69, 228, 79, 79, 79, 79, 6,
+ 8, 9, 7, 245, 246, 247, 77, 77, 250, 251,
+ 252, 253, 254, 175, 79, 79, 77, 77, 180, 77,
+ 182, 183, 184, 185, 79, 77, 77, 77, 419, 37,
+ 77, 77, 77, 47, 196, 79, 77, 372, 373, 374,
+ 375, 376, 377, 77, 77, 207, 77, 209, 77, 394,
3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
- -1, -1, 55, 56, 57, 58, 59, 60, 61, 62,
- 63, -1, 36, 66, 67, -1, 36, 70, -1, 72,
- -1, 41, 75, 43, 44, 45, 46, 47, 48, 49,
- 50, 51, 52, -1, 54, 8, 9, 5, 6, 7,
- 8, 9, 10, 11, 12, -1, 8, 9, 72, -1,
- 70, -1, 72, 77, -1, -1, 80, 77, -1, 79,
- 80, -1, 75, 36, -1, 8, 9, -1, 41, -1,
- 43, -1, 45, 46, 36, -1, 49, 50, 51, 52,
- -1, 54, 44, -1, -1, 47, 8, 9, -1, -1,
- -1, -1, -1, 36, -1, -1, -1, 70, -1, 72,
- 43, -1, 45, -1, 77, -1, 79, 80, 70, -1,
- 72, 8, 9, -1, 36, 77, -1, 79, 80, -1,
- -1, 43, -1, 45, 8, 9, -1, 70, -1, 72,
- -1, -1, -1, -1, 77, -1, -1, 80, -1, 36,
- 8, 9, -1, -1, 8, 9, -1, -1, 70, -1,
- 72, 48, 36, 8, 9, 77, -1, -1, 80, -1,
- 44, -1, -1, 47, 8, 9, -1, -1, 36, -1,
- 8, 9, 36, 70, -1, 72, -1, -1, -1, -1,
- 77, 36, 79, 80, -1, -1, 70, -1, 72, -1,
- 8, 9, 36, 77, -1, -1, 80, -1, 36, -1,
- 68, 69, 70, -1, 72, 69, 70, -1, 72, 77,
- 8, 9, 80, 77, -1, 70, 80, 72, 36, -1,
- -1, -1, 77, -1, -1, 80, 70, -1, 72, -1,
- -1, -1, 70, 77, 72, -1, 80, -1, 36, 77,
- -1, -1, 80, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 70, -1, 72, -1, -1, -1, -1, 77,
- -1, -1, 80, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 70, -1, 72, -1, -1, -1, -1, 77,
- -1, -1, 80
+ 395, 69, 70, 71, 399, 73, 77, 77, 77, 231,
+ 78, 77, 49, 81, 77, 77, 37, 78, 9, 378,
+ 379, 243, 79, 79, 79, 79, 380, 386, 80, 80,
+ 384, 39, 77, 9, 37, 387, 388, 77, 77, 77,
+ 37, 77, 77, 397, 398, 5, 6, 7, 8, 9,
+ 10, 11, 12, 448, 449, 79, 451, 452, 398, 361,
+ 362, 79, 394, 242, 232, 427, 79, 6, 7, 8,
+ 9, 10, 11, 12, -1, 429, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, -1, -1, 396, -1,
+ 384, 443, -1, 447, 0, 1, 450, -1, -1, -1,
+ -1, 393, 394, -1, -1, 397, 398, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, -1, 29, 30, -1, 32, 33, 34, 35,
+ 36, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, -1, -1, -1, -1, -1, -1, -1, -1, 76,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 1,
+ -1, 67, 68, -1, -1, 71, -1, 73, -1, -1,
+ 76, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, -1, 29, 30, -1,
+ 32, 33, 34, 35, 36, -1, -1, -1, -1, 8,
+ 9, -1, -1, -1, 76, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, -1, -1, 67, 68, -1, 37, 71,
+ -1, 73, -1, 42, 76, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, -1, 55, 8, 9, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 8,
+ 9, -1, 71, -1, 73, -1, -1, -1, -1, 78,
+ -1, 80, 81, -1, 8, 9, 37, -1, -1, -1,
+ -1, 42, -1, 44, -1, 46, 47, -1, 37, 50,
+ 51, 52, 53, 42, 55, -1, -1, -1, 47, -1,
+ -1, -1, -1, 37, 8, 9, -1, -1, -1, -1,
+ 71, 45, 73, -1, 48, -1, -1, 78, -1, 80,
+ 81, -1, 71, -1, 73, 8, 9, -1, 77, 78,
+ -1, -1, 81, 37, -1, 8, 9, 71, -1, 73,
+ 44, -1, 46, -1, 78, -1, 80, 81, -1, -1,
+ 8, 9, -1, -1, 37, -1, 8, 9, -1, -1,
+ -1, 44, -1, 46, 37, 8, 9, 71, -1, 73,
+ -1, 44, -1, 46, 78, -1, -1, 81, -1, 37,
+ 8, 9, 8, 9, -1, 37, -1, -1, 71, -1,
+ 73, 49, -1, -1, 37, 78, -1, -1, 81, -1,
+ 73, -1, 8, 9, -1, 78, -1, -1, 81, 37,
+ -1, 37, -1, 71, -1, 73, -1, -1, 70, 71,
+ 78, 73, 80, 81, 50, 51, 78, -1, 71, 81,
+ 73, 37, 8, 9, -1, 78, -1, -1, 81, 8,
+ 9, -1, -1, 71, -1, 73, -1, 73, 8, 9,
+ 78, -1, 78, 81, -1, 81, -1, -1, -1, 8,
+ 9, 37, -1, 8, 9, 71, -1, 73, 37, 8,
+ 9, -1, 78, -1, -1, 81, -1, 37, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 37, -1,
+ -1, -1, 37, -1, -1, 71, -1, 73, 37, -1,
+ -1, -1, 78, -1, 73, 81, -1, -1, -1, 78,
+ -1, 80, 81, 73, -1, -1, -1, -1, 78, -1,
+ 80, 81, 71, -1, 73, -1, -1, -1, 73, 78,
+ 69, -1, 81, 78, 73, -1, 81, -1, -1, 78,
+ -1, -1, 81
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
static const yytype_uint8 yystos[] =
{
- 0, 82, 0, 1, 13, 14, 15, 16, 17, 18,
+ 0, 83, 0, 1, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 29,
- 30, 32, 33, 34, 35, 55, 56, 57, 58, 59,
- 60, 61, 62, 63, 66, 67, 70, 72, 75, 83,
- 85, 75, 8, 9, 36, 41, 43, 44, 45, 46,
- 47, 48, 49, 50, 51, 52, 54, 70, 72, 77,
- 79, 80, 87, 88, 89, 90, 91, 92, 93, 94,
- 96, 97, 100, 102, 103, 104, 105, 106, 110, 87,
- 104, 105, 87, 87, 79, 87, 102, 87, 102, 87,
- 77, 98, 110, 46, 70, 76, 77, 86, 97, 105,
- 110, 79, 96, 101, 104, 105, 96, 96, 96, 96,
- 76, 87, 102, 107, 76, 87, 96, 102, 107, 107,
- 100, 102, 106, 110, 106, 107, 102, 102, 75, 77,
- 104, 87, 104, 87, 104, 87, 102, 87, 105, 102,
- 87, 73, 74, 74, 75, 110, 110, 77, 77, 77,
- 77, 6, 8, 9, 108, 103, 110, 111, 69, 105,
- 110, 110, 76, 76, 76, 76, 76, 76, 76, 76,
- 76, 76, 76, 77, 76, 76, 76, 76, 76, 110,
- 76, 76, 76, 76, 76, 76, 108, 77, 86, 105,
- 110, 88, 76, 76, 77, 9, 68, 76, 76, 76,
- 76, 76, 76, 76, 76, 76, 107, 76, 87, 96,
- 107, 107, 107, 107, 76, 77, 11, 76, 76, 76,
- 76, 76, 76, 76, 76, 76, 76, 76, 76, 84,
- 111, 111, 110, 110, 110, 110, 7, 110, 110, 77,
- 8, 78, 3, 4, 5, 6, 7, 8, 9, 10,
- 11, 12, 78, 87, 88, 90, 93, 97, 102, 104,
- 105, 87, 87, 87, 97, 96, 97, 94, 102, 104,
- 105, 93, 97, 87, 48, 87, 95, 87, 87, 37,
- 38, 39, 103, 109, 87, 104, 105, 87, 87, 87,
- 87, 103, 87, 103, 87, 103, 87, 102, 103, 87,
- 103, 87, 102, 98, 110, 88, 78, 77, 86, 105,
- 77, 86, 105, 110, 40, 68, 96, 104, 105, 96,
- 96, 96, 96, 96, 96, 96, 103, 103, 102, 110,
- 110, 102, 105, 87, 102, 102, 104, 104, 87, 87,
- 87, 105, 87, 110, 103, 83, 75, 75, 78, 78,
- 78, 78, 108, 109, 103, 111, 111, 111, 6, 7,
- 111, 111, 111, 111, 111, 76, 76, 77, 78, 78,
- 76, 76, 76, 76, 76, 76, 76, 76, 76, 78,
- 88, 88, 76, 78, 76, 76, 76, 76, 76, 76,
- 76, 76, 76, 76, 77, 78, 78, 111, 111, 46,
- 90, 94, 110, 87, 87, 87, 87, 87, 87, 97,
- 97, 98, 78, 78, 77, 86, 105, 97, 96, 96,
- 102, 79, 100, 101, 102, 87, 104, 99, 102, 110,
- 99, 102, 87, 38, 78, 88, 76, 9, 9, 76,
- 76, 76, 76, 76, 78, 78, 96, 110, 87, 87,
- 110, 87, 87
+ 30, 32, 33, 34, 35, 36, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 67, 68, 71, 73, 76,
+ 84, 86, 76, 8, 9, 37, 42, 44, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 55, 71, 73,
+ 78, 80, 81, 88, 89, 90, 91, 92, 93, 94,
+ 95, 96, 97, 101, 103, 104, 105, 106, 107, 111,
+ 88, 105, 106, 88, 88, 80, 88, 103, 88, 103,
+ 88, 78, 98, 111, 47, 71, 77, 78, 87, 97,
+ 106, 111, 80, 96, 102, 105, 106, 96, 96, 96,
+ 96, 77, 88, 103, 108, 77, 88, 96, 103, 108,
+ 108, 101, 103, 107, 111, 107, 107, 108, 103, 103,
+ 76, 78, 105, 88, 105, 88, 105, 88, 103, 88,
+ 106, 103, 88, 74, 75, 75, 76, 111, 111, 78,
+ 78, 78, 78, 6, 8, 9, 109, 104, 111, 112,
+ 70, 106, 111, 111, 77, 77, 77, 77, 77, 77,
+ 77, 77, 77, 77, 77, 78, 77, 77, 77, 77,
+ 77, 111, 77, 77, 77, 77, 77, 77, 109, 78,
+ 87, 106, 111, 89, 77, 77, 78, 9, 69, 77,
+ 77, 77, 77, 77, 77, 77, 77, 77, 108, 77,
+ 88, 96, 108, 108, 108, 108, 77, 78, 77, 11,
+ 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
+ 77, 77, 85, 112, 112, 111, 111, 111, 111, 7,
+ 111, 111, 78, 8, 79, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 79, 88, 89, 91, 94,
+ 97, 103, 105, 106, 88, 88, 88, 97, 96, 97,
+ 95, 103, 105, 106, 94, 97, 88, 88, 88, 88,
+ 38, 39, 40, 104, 110, 88, 105, 106, 88, 88,
+ 88, 88, 104, 88, 104, 88, 104, 88, 103, 104,
+ 88, 104, 88, 103, 98, 111, 89, 79, 78, 87,
+ 106, 78, 87, 106, 111, 41, 69, 96, 105, 106,
+ 96, 96, 96, 96, 96, 96, 96, 104, 104, 80,
+ 111, 103, 111, 111, 103, 106, 88, 103, 103, 105,
+ 105, 88, 88, 88, 106, 88, 111, 104, 84, 76,
+ 76, 79, 79, 79, 79, 109, 110, 104, 112, 112,
+ 112, 6, 7, 112, 112, 112, 112, 112, 77, 77,
+ 79, 79, 77, 77, 77, 77, 77, 77, 77, 77,
+ 77, 79, 89, 89, 77, 79, 77, 77, 77, 9,
+ 37, 100, 77, 77, 77, 77, 77, 77, 77, 77,
+ 78, 79, 79, 112, 112, 47, 91, 95, 88, 88,
+ 88, 88, 88, 88, 97, 97, 98, 79, 79, 78,
+ 87, 106, 97, 96, 96, 37, 9, 80, 103, 80,
+ 101, 102, 103, 88, 105, 99, 103, 111, 99, 103,
+ 88, 39, 89, 77, 9, 37, 100, 9, 77, 77,
+ 77, 77, 77, 79, 79, 96, 37, 88, 88, 111,
+ 88, 88
};
#define yyerrok (yyerrstatus = 0)
case 12:
#line 103 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 13:
#line 107 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 14:
#line 111 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 15:
#line 115 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 16:
#line 119 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 17:
#line 123 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 18:
#line 130 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 19:
#line 134 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 20:
#line 138 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 21:
#line 142 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 22:
#line 146 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 23:
#line 150 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 24:
#line 157 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 25:
#line 161 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 26:
#line 165 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 27:
#line 169 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 28:
#line 176 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 29:
#line 180 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 30:
#line 187 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 31:
#line 191 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 32:
#line 195 "a.y"
{
- outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
+ outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), 0, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
}
break;
case 33:
#line 199 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 34:
#line 203 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].lval), &nullgen);
}
break;
case 35:
-#line 207 "a.y"
+#line 210 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].lval), &nullgen);
+ outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), 0, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
}
break;
case 36:
#line 214 "a.y"
{
- outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 37:
#line 218 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 38:
-#line 222 "a.y"
+#line 228 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
}
break;
case 40:
#line 236 "a.y"
{
- outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+ outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), 0, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
}
break;
case 41:
#line 240 "a.y"
{
- outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 42:
#line 244 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 43:
#line 248 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
}
break;
case 44:
#line 252 "a.y"
{
- outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 45:
#line 256 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
}
break;
case 46:
#line 260 "a.y"
{
- outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 47:
#line 264 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
}
break;
case 48:
#line 268 "a.y"
{
- outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 49:
#line 272 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 50:
#line 276 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr), 0, &(yyvsp[(2) - (2)].addr));
}
break;
case 51:
-#line 280 "a.y"
+#line 283 "a.y"
{
- outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr), NREG, &(yyvsp[(2) - (2)].addr));
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
}
break;
case 52:
-#line 287 "a.y"
+#line 290 "a.y"
{
- outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 53:
#line 294 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 54:
-#line 298 "a.y"
+#line 301 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].addr).reg, &(yyvsp[(4) - (4)].addr));
}
break;
case 55:
#line 305 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].addr).reg, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
}
break;
case 56:
-#line 309 "a.y"
+#line 313 "a.y"
{
- outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 57:
#line 317 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 58:
#line 321 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 59:
#line 325 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 60:
#line 329 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 61:
#line 333 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 62:
#line 337 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 63:
#line 341 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 64:
-#line 345 "a.y"
+#line 350 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (2)].lval), &nullgen, 0, &(yyvsp[(2) - (2)].addr));
}
break;
case 65:
#line 354 "a.y"
{
- outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &(yyvsp[(2) - (2)].addr));
+ outcode((yyvsp[(1) - (2)].lval), &nullgen, 0, &(yyvsp[(2) - (2)].addr));
}
break;
case 66:
#line 358 "a.y"
{
- outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &(yyvsp[(2) - (2)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &nullgen, 0, &(yyvsp[(3) - (4)].addr));
}
break;
case 67:
#line 362 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &nullgen, NREG, &(yyvsp[(3) - (4)].addr));
+ outcode((yyvsp[(1) - (3)].lval), &nullgen, 0, &(yyvsp[(3) - (3)].addr));
}
break;
case 68:
#line 366 "a.y"
{
- outcode((yyvsp[(1) - (3)].lval), &nullgen, NREG, &(yyvsp[(3) - (3)].addr));
+ outcode((yyvsp[(1) - (3)].lval), &nullgen, 0, &(yyvsp[(3) - (3)].addr));
}
break;
case 69:
#line 370 "a.y"
{
- outcode((yyvsp[(1) - (3)].lval), &nullgen, NREG, &(yyvsp[(3) - (3)].addr));
+ outcode((yyvsp[(1) - (5)].lval), &nullgen, 0, &(yyvsp[(4) - (5)].addr));
}
break;
case 70:
#line 374 "a.y"
{
- outcode((yyvsp[(1) - (5)].lval), &nullgen, NREG, &(yyvsp[(4) - (5)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 71:
#line 378 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 72:
#line 382 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), 0, &(yyvsp[(5) - (6)].addr));
}
break;
case 73:
#line 386 "a.y"
{
- outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(5) - (6)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &nullgen, (yyvsp[(2) - (4)].lval), &(yyvsp[(4) - (4)].addr));
}
break;
case 75:
#line 394 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &nullgen, (yyvsp[(2) - (4)].lval), &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (6)].lval), &nullgen, (yyvsp[(2) - (6)].lval), &(yyvsp[(5) - (6)].addr));
}
break;
case 76:
#line 398 "a.y"
{
- outcode((yyvsp[(1) - (6)].lval), &nullgen, (yyvsp[(2) - (6)].lval), &(yyvsp[(5) - (6)].addr));
+ Addr g;
+ g = nullgen;
+ g.type = TYPE_CONST;
+ g.offset = (yyvsp[(2) - (6)].lval);
+ outcode((yyvsp[(1) - (6)].lval), &g, REG_R0+(yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
}
break;
case 77:
-#line 402 "a.y"
+#line 406 "a.y"
{
Addr g;
g = nullgen;
- g.type = D_CONST;
+ g.type = TYPE_CONST;
g.offset = (yyvsp[(2) - (6)].lval);
- outcode((yyvsp[(1) - (6)].lval), &g, (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+ outcode((yyvsp[(1) - (6)].lval), &g, REG_R0+(yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
}
break;
case 78:
-#line 410 "a.y"
+#line 414 "a.y"
{
Addr g;
g = nullgen;
- g.type = D_CONST;
- g.offset = (yyvsp[(2) - (6)].lval);
- outcode((yyvsp[(1) - (6)].lval), &g, (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+ g.type = TYPE_CONST;
+ g.offset = (yyvsp[(2) - (8)].lval);
+ outcode((yyvsp[(1) - (8)].lval), &g, REG_R0+(yyvsp[(4) - (8)].lval), &(yyvsp[(7) - (8)].addr));
}
break;
case 79:
-#line 418 "a.y"
+#line 425 "a.y"
{
- Addr g;
- g = nullgen;
- g.type = D_CONST;
- g.offset = (yyvsp[(2) - (8)].lval);
- outcode((yyvsp[(1) - (8)].lval), &g, (yyvsp[(4) - (8)].lval), &(yyvsp[(7) - (8)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].lval), &nullgen);
}
break;
case 81:
#line 433 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].lval), &nullgen);
+ outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), 0, &nullgen);
}
break;
case 82:
#line 437 "a.y"
{
- outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), NREG, &nullgen);
+ outcode((yyvsp[(1) - (2)].lval), &nullgen, 0, &nullgen);
}
break;
case 83:
-#line 441 "a.y"
+#line 444 "a.y"
{
- outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &nullgen);
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 84:
#line 448 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 85:
#line 452 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].addr).reg, &(yyvsp[(6) - (6)].addr));
}
break;
case 86:
#line 456 "a.y"
{
- outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].addr).reg, &(yyvsp[(6) - (6)].addr));
+ outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr));
}
break;
case 87:
#line 460 "a.y"
{
- outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 88:
#line 464 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(6) - (6)].addr).reg, &(yyvsp[(4) - (6)].addr));
}
break;
case 89:
-#line 468 "a.y"
+#line 471 "a.y"
{
- outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(6) - (6)].addr).reg, &(yyvsp[(4) - (6)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 90:
#line 475 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 91:
#line 479 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(6) - (6)].addr).reg, &(yyvsp[(4) - (6)].addr));
}
break;
break;
case 93:
-#line 487 "a.y"
+#line 490 "a.y"
{
- outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(6) - (6)].addr).reg, &(yyvsp[(4) - (6)].addr));
+ outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr));
}
break;
break;
case 97:
-#line 506 "a.y"
+#line 509 "a.y"
{
- outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 98:
#line 513 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 99:
-#line 517 "a.y"
+#line 521 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 100:
#line 525 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), 0, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
}
break;
case 101:
#line 529 "a.y"
{
- outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 102:
#line 533 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), 0, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
}
break;
case 103:
#line 537 "a.y"
{
- outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 104:
#line 541 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 105:
#line 545 "a.y"
{
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr), 0, &nullgen);
}
break;
case 106:
-#line 549 "a.y"
+#line 552 "a.y"
{
- outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr), NREG, &nullgen);
+ outcode((yyvsp[(1) - (2)].lval), &nullgen, 0, &nullgen);
}
break;
case 107:
#line 556 "a.y"
{
- outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &nullgen);
+ outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), 0, &nullgen);
}
break;
case 108:
#line 560 "a.y"
{
- outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), NREG, &nullgen);
+ outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), 0, &nullgen);
}
break;
case 109:
#line 564 "a.y"
{
- outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), NREG, &nullgen);
+ outcode((yyvsp[(1) - (3)].lval), &nullgen, 0, &(yyvsp[(3) - (3)].addr));
}
break;
case 110:
#line 568 "a.y"
{
- outcode((yyvsp[(1) - (3)].lval), &nullgen, NREG, &(yyvsp[(3) - (3)].addr));
+ outcode((yyvsp[(1) - (3)].lval), &nullgen, 0, &(yyvsp[(3) - (3)].addr));
}
break;
case 111:
#line 572 "a.y"
{
- outcode((yyvsp[(1) - (3)].lval), &nullgen, NREG, &(yyvsp[(3) - (3)].addr));
+ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr), 0, &nullgen);
}
break;
case 112:
-#line 576 "a.y"
+#line 579 "a.y"
{
- outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr), NREG, &nullgen);
+ outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), 0, &nullgen);
}
break;
case 113:
#line 583 "a.y"
{
- outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), NREG, &nullgen);
+ outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), 0, &nullgen);
}
break;
case 114:
-#line 587 "a.y"
+#line 590 "a.y"
{
- outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), NREG, &nullgen);
+ if((yyvsp[(2) - (4)].addr).type != TYPE_CONST || (yyvsp[(4) - (4)].addr).type != TYPE_CONST)
+ yyerror("arguments to PCDATA must be integer constants");
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 115:
-#line 594 "a.y"
+#line 599 "a.y"
{
- if((yyvsp[(2) - (4)].addr).type != D_CONST || (yyvsp[(4) - (4)].addr).type != D_CONST)
- yyerror("arguments to PCDATA must be integer constants");
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ if((yyvsp[(2) - (4)].addr).type != TYPE_CONST)
+ yyerror("index for FUNCDATA must be integer constant");
+ if((yyvsp[(4) - (4)].addr).type != NAME_EXTERN && (yyvsp[(4) - (4)].addr).type != NAME_STATIC && (yyvsp[(4) - (4)].addr).type != TYPE_MEM)
+ yyerror("value for FUNCDATA must be symbol reference");
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 116:
-#line 603 "a.y"
+#line 610 "a.y"
{
- if((yyvsp[(2) - (4)].addr).type != D_CONST)
- yyerror("index for FUNCDATA must be integer constant");
- if((yyvsp[(4) - (4)].addr).type != D_EXTERN && (yyvsp[(4) - (4)].addr).type != D_STATIC && (yyvsp[(4) - (4)].addr).type != D_OREG)
- yyerror("value for FUNCDATA must be symbol reference");
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ outcode((yyvsp[(1) - (2)].lval), &nullgen, 0, &nullgen);
}
break;
case 117:
-#line 614 "a.y"
+#line 617 "a.y"
{
- outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &nullgen);
+ settext((yyvsp[(2) - (5)].addr).sym);
+ outcode((yyvsp[(1) - (5)].lval), &(yyvsp[(2) - (5)].addr), 0, &(yyvsp[(5) - (5)].addr));
}
break;
case 118:
-#line 621 "a.y"
+#line 622 "a.y"
{
- settext((yyvsp[(2) - (4)].addr).sym);
- outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ settext((yyvsp[(2) - (7)].addr).sym);
+ outcode((yyvsp[(1) - (7)].lval), &(yyvsp[(2) - (7)].addr), 0, &(yyvsp[(7) - (7)].addr));
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = (yyvsp[(4) - (7)].lval);
+ }
}
break;
case 119:
-#line 626 "a.y"
+#line 634 "a.y"
{
- settext((yyvsp[(2) - (6)].addr).sym);
- (yyvsp[(6) - (6)].addr).offset &= 0xffffffffull;
- (yyvsp[(6) - (6)].addr).offset |= (vlong)ArgsSizeUnknown << 32;
- outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+ settext((yyvsp[(2) - (4)].addr).sym);
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
}
break;
case 120:
-#line 633 "a.y"
+#line 639 "a.y"
{
- settext((yyvsp[(2) - (8)].addr).sym);
- (yyvsp[(6) - (8)].addr).offset &= 0xffffffffull;
- (yyvsp[(6) - (8)].addr).offset |= ((yyvsp[(8) - (8)].lval) & 0xffffffffull) << 32;
- outcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].lval), &(yyvsp[(6) - (8)].addr));
+ settext((yyvsp[(2) - (6)].addr).sym);
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), 0, &(yyvsp[(6) - (6)].addr));
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = (yyvsp[(4) - (6)].lval);
+ }
}
break;
case 121:
-#line 643 "a.y"
+#line 652 "a.y"
{
- outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), 0, &(yyvsp[(6) - (6)].addr));
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = (yyvsp[(4) - (6)].lval);
+ }
}
break;
case 122:
-#line 647 "a.y"
+#line 660 "a.y"
{
- outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), 0, &(yyvsp[(6) - (6)].addr));
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = (yyvsp[(4) - (6)].lval);
+ }
}
break;
case 123:
-#line 651 "a.y"
+#line 668 "a.y"
{
- outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), 0, &(yyvsp[(6) - (6)].addr));
+ if(pass > 1) {
+ lastpc->from3.type = TYPE_CONST;
+ lastpc->from3.offset = (yyvsp[(4) - (6)].lval);
+ }
}
break;
case 124:
-#line 658 "a.y"
+#line 679 "a.y"
{
- outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &nullgen);
+ outcode((yyvsp[(1) - (2)].lval), &nullgen, 0, &nullgen);
}
break;
case 125:
-#line 664 "a.y"
+#line 685 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_BRANCH;
+ (yyval.addr).type = TYPE_BRANCH;
(yyval.addr).offset = (yyvsp[(1) - (4)].lval) + pc;
}
break;
case 126:
-#line 670 "a.y"
+#line 691 "a.y"
{
(yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym));
(yyval.addr) = nullgen;
if(pass == 2 && (yyvsp[(1) - (2)].sym)->type != LLAB)
yyerror("undefined label: %s", (yyvsp[(1) - (2)].sym)->labelname);
- (yyval.addr).type = D_BRANCH;
+ (yyval.addr).type = TYPE_BRANCH;
(yyval.addr).offset = (yyvsp[(1) - (2)].sym)->value + (yyvsp[(2) - (2)].lval);
}
break;
case 127:
-#line 681 "a.y"
+#line 702 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_REG;
+ (yyval.addr).type = TYPE_REG;
(yyval.addr).reg = (yyvsp[(1) - (1)].lval);
}
break;
case 130:
-#line 693 "a.y"
+#line 714 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_SPR;
- (yyval.addr).offset = (yyvsp[(1) - (1)].lval);
+ (yyval.addr).type = TYPE_REG;
+ (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
}
break;
case 131:
-#line 701 "a.y"
+#line 722 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_CREG;
- (yyval.addr).reg = NREG; /* whole register */
+ (yyval.addr).type = TYPE_REG;
+ (yyval.addr).reg = (yyvsp[(1) - (1)].lval); /* whole register */
}
break;
case 132:
-#line 709 "a.y"
+#line 730 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_SPR;
- (yyval.addr).offset = (yyvsp[(1) - (1)].lval);
+ (yyval.addr).type = TYPE_REG;
+ (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
}
break;
case 133:
-#line 717 "a.y"
+#line 738 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_MSR;
+ (yyval.addr).type = TYPE_REG;
+ (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
}
break;
case 134:
-#line 724 "a.y"
+#line 746 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_SPR;
- (yyval.addr).offset = (yyvsp[(1) - (1)].lval);
+ (yyval.addr).type = TYPE_REG;
+ (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
}
break;
case 135:
-#line 730 "a.y"
+#line 752 "a.y"
{
+ if((yyvsp[(3) - (4)].lval) < 0 || (yyvsp[(3) - (4)].lval) >= 1024)
+ yyerror("SPR/DCR out of range");
(yyval.addr) = nullgen;
- (yyval.addr).type = (yyvsp[(1) - (4)].lval);
- (yyval.addr).offset = (yyvsp[(3) - (4)].lval);
+ (yyval.addr).type = TYPE_REG;
+ (yyval.addr).reg = (yyvsp[(1) - (4)].lval) + (yyvsp[(3) - (4)].lval);
}
break;
case 137:
-#line 739 "a.y"
+#line 763 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_FPSCR;
- (yyval.addr).reg = NREG;
+ (yyval.addr).type = TYPE_REG;
+ (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
}
break;
case 138:
-#line 747 "a.y"
+#line 771 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_FPSCR;
- (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
+ (yyval.addr).type = TYPE_REG;
+ (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
}
break;
case 139:
-#line 755 "a.y"
+#line 777 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_FREG;
- (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
+ (yyval.addr).type = TYPE_REG;
+ (yyval.addr).reg = REG_F0 + (yyvsp[(3) - (4)].lval);
}
break;
case 140:
-#line 761 "a.y"
+#line 785 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_FREG;
- (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
+ (yyval.addr).type = TYPE_REG;
+ (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
}
break;
case 141:
-#line 769 "a.y"
+#line 791 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_CREG;
- (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
+ (yyval.addr).type = TYPE_REG;
+ (yyval.addr).reg = REG_C0 + (yyvsp[(3) - (4)].lval);
}
break;
case 142:
-#line 775 "a.y"
- {
- (yyval.addr) = nullgen;
- (yyval.addr).type = D_CREG;
- (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
- }
- break;
-
- case 143:
-#line 783 "a.y"
+#line 799 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_REG;
+ (yyval.addr).type = TYPE_REG;
(yyval.addr).reg = (yyvsp[(1) - (1)].lval);
}
break;
- case 144:
-#line 791 "a.y"
+ case 143:
+#line 807 "a.y"
{
int mb, me;
uint32 v;
(yyval.addr) = nullgen;
- (yyval.addr).type = D_CONST;
+ (yyval.addr).type = TYPE_CONST;
mb = (yyvsp[(1) - (3)].lval);
me = (yyvsp[(3) - (3)].lval);
if(mb < 0 || mb > 31 || me < 0 || me > 31){
}
break;
+ case 144:
+#line 828 "a.y"
+ {
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = TYPE_TEXTSIZE;
+ (yyval.addr).offset = (yyvsp[(1) - (1)].lval);
+ (yyval.addr).u.argsize = ArgsSizeUnknown;
+ }
+ break;
+
case 145:
-#line 812 "a.y"
+#line 835 "a.y"
{
- (yyval.addr) = (yyvsp[(2) - (2)].addr);
- (yyval.addr).type = D_CONST;
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = TYPE_TEXTSIZE;
+ (yyval.addr).offset = -(yyvsp[(2) - (2)].lval);
+ (yyval.addr).u.argsize = ArgsSizeUnknown;
}
break;
case 146:
-#line 817 "a.y"
+#line 842 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_SCONST;
- memcpy((yyval.addr).u.sval, (yyvsp[(2) - (2)].sval), sizeof((yyval.addr).u.sval));
+ (yyval.addr).type = TYPE_TEXTSIZE;
+ (yyval.addr).offset = (yyvsp[(1) - (3)].lval);
+ (yyval.addr).u.argsize = (yyvsp[(3) - (3)].lval);
}
break;
case 147:
-#line 825 "a.y"
+#line 849 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_FCONST;
- (yyval.addr).u.dval = (yyvsp[(2) - (2)].dval);
+ (yyval.addr).type = TYPE_TEXTSIZE;
+ (yyval.addr).offset = -(yyvsp[(2) - (4)].lval);
+ (yyval.addr).u.argsize = (yyvsp[(4) - (4)].lval);
}
break;
case 148:
-#line 831 "a.y"
+#line 858 "a.y"
+ {
+ (yyval.addr) = (yyvsp[(2) - (2)].addr);
+ (yyval.addr).type = TYPE_ADDR;
+ }
+ break;
+
+ case 149:
+#line 863 "a.y"
+ {
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = TYPE_SCONST;
+ memcpy((yyval.addr).u.sval, (yyvsp[(2) - (2)].sval), sizeof((yyval.addr).u.sval));
+ }
+ break;
+
+ case 150:
+#line 871 "a.y"
+ {
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = TYPE_FCONST;
+ (yyval.addr).u.dval = (yyvsp[(2) - (2)].dval);
+ }
+ break;
+
+ case 151:
+#line 877 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_FCONST;
+ (yyval.addr).type = TYPE_FCONST;
(yyval.addr).u.dval = -(yyvsp[(3) - (3)].dval);
}
break;
- case 149:
-#line 838 "a.y"
+ case 152:
+#line 884 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_CONST;
+ (yyval.addr).type = TYPE_CONST;
(yyval.addr).offset = (yyvsp[(2) - (2)].lval);
}
break;
- case 151:
-#line 847 "a.y"
+ case 154:
+#line 893 "a.y"
{
if((yyval.lval) < 0 || (yyval.lval) >= NREG)
print("register value out of range\n");
- (yyval.lval) = (yyvsp[(3) - (4)].lval);
+ (yyval.lval) = REG_R0 + (yyvsp[(3) - (4)].lval);
}
break;
- case 152:
-#line 855 "a.y"
+ case 155:
+#line 901 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_OREG;
+ (yyval.addr).type = TYPE_MEM;
(yyval.addr).reg = (yyvsp[(2) - (3)].lval);
(yyval.addr).offset = 0;
}
break;
- case 153:
-#line 862 "a.y"
+ case 156:
+#line 908 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_OREG;
+ (yyval.addr).type = TYPE_MEM;
(yyval.addr).reg = (yyvsp[(2) - (5)].lval);
(yyval.addr).scale = (yyvsp[(4) - (5)].lval);
(yyval.addr).offset = 0;
}
break;
- case 155:
-#line 873 "a.y"
+ case 158:
+#line 919 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_OREG;
+ (yyval.addr).type = TYPE_MEM;
(yyval.addr).reg = (yyvsp[(3) - (4)].lval);
(yyval.addr).offset = (yyvsp[(1) - (4)].lval);
}
break;
- case 156:
-#line 882 "a.y"
+ case 159:
+#line 928 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_OREG;
+ (yyval.addr).type = TYPE_MEM;
(yyval.addr).name = (yyvsp[(3) - (4)].lval);
(yyval.addr).sym = nil;
(yyval.addr).offset = (yyvsp[(1) - (4)].lval);
}
break;
- case 157:
-#line 890 "a.y"
+ case 160:
+#line 936 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_OREG;
+ (yyval.addr).type = TYPE_MEM;
(yyval.addr).name = (yyvsp[(4) - (5)].lval);
(yyval.addr).sym = linklookup(ctxt, (yyvsp[(1) - (5)].sym)->name, 0);
(yyval.addr).offset = (yyvsp[(2) - (5)].lval);
}
break;
- case 158:
-#line 898 "a.y"
+ case 161:
+#line 944 "a.y"
{
(yyval.addr) = nullgen;
- (yyval.addr).type = D_OREG;
- (yyval.addr).name = D_STATIC;
+ (yyval.addr).type = TYPE_MEM;
+ (yyval.addr).name = NAME_STATIC;
(yyval.addr).sym = linklookup(ctxt, (yyvsp[(1) - (7)].sym)->name, 0);
(yyval.addr).offset = (yyvsp[(4) - (7)].lval);
}
break;
- case 161:
-#line 910 "a.y"
+ case 164:
+#line 956 "a.y"
{
(yyval.lval) = 0;
}
break;
- case 162:
-#line 914 "a.y"
+ case 165:
+#line 960 "a.y"
{
(yyval.lval) = (yyvsp[(2) - (2)].lval);
}
break;
- case 163:
-#line 918 "a.y"
+ case 166:
+#line 964 "a.y"
{
(yyval.lval) = -(yyvsp[(2) - (2)].lval);
}
break;
- case 168:
-#line 930 "a.y"
+ case 171:
+#line 976 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (1)].sym)->value;
}
break;
- case 169:
-#line 934 "a.y"
+ case 172:
+#line 980 "a.y"
{
(yyval.lval) = -(yyvsp[(2) - (2)].lval);
}
break;
- case 170:
-#line 938 "a.y"
+ case 173:
+#line 984 "a.y"
{
(yyval.lval) = (yyvsp[(2) - (2)].lval);
}
break;
- case 171:
-#line 942 "a.y"
+ case 174:
+#line 988 "a.y"
{
(yyval.lval) = ~(yyvsp[(2) - (2)].lval);
}
break;
- case 172:
-#line 946 "a.y"
+ case 175:
+#line 992 "a.y"
{
(yyval.lval) = (yyvsp[(2) - (3)].lval);
}
break;
- case 174:
-#line 953 "a.y"
+ case 177:
+#line 999 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval);
}
break;
- case 175:
-#line 957 "a.y"
+ case 178:
+#line 1003 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval);
}
break;
- case 176:
-#line 961 "a.y"
+ case 179:
+#line 1007 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval);
}
break;
- case 177:
-#line 965 "a.y"
+ case 180:
+#line 1011 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval);
}
break;
- case 178:
-#line 969 "a.y"
+ case 181:
+#line 1015 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval);
}
break;
- case 179:
-#line 973 "a.y"
+ case 182:
+#line 1019 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval);
}
break;
- case 180:
-#line 977 "a.y"
+ case 183:
+#line 1023 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval);
}
break;
- case 181:
-#line 981 "a.y"
+ case 184:
+#line 1027 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval);
}
break;
- case 182:
-#line 985 "a.y"
+ case 185:
+#line 1031 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval);
}
break;
- case 183:
-#line 989 "a.y"
+ case 186:
+#line 1035 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) | (yyvsp[(3) - (3)].lval);
}
/* Line 1267 of yacc.c. */
-#line 3185 "y.tab.c"
+#line 3256 "y.tab.c"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
LRETT = 276,
LWORD = 277,
LTEXT = 278,
- LDATA = 279,
- LRETRN = 280,
- LCONST = 281,
- LSP = 282,
- LSB = 283,
- LFP = 284,
- LPC = 285,
- LCREG = 286,
- LFLUSH = 287,
- LREG = 288,
- LFREG = 289,
- LR = 290,
- LCR = 291,
- LF = 292,
- LFPSCR = 293,
- LLR = 294,
- LCTR = 295,
- LSPR = 296,
- LSPREG = 297,
- LSEG = 298,
- LMSR = 299,
- LPCDAT = 300,
- LFUNCDAT = 301,
- LSCHED = 302,
- LXLD = 303,
- LXST = 304,
- LXOP = 305,
- LXMV = 306,
- LRLWM = 307,
- LMOVMW = 308,
- LMOVEM = 309,
- LMOVFL = 310,
- LMTFSB = 311,
- LMA = 312,
- LFCONST = 313,
- LSCONST = 314,
- LNAME = 315,
- LLAB = 316,
- LVAR = 317
+ LGLOBL = 279,
+ LDATA = 280,
+ LRETRN = 281,
+ LCONST = 282,
+ LSP = 283,
+ LSB = 284,
+ LFP = 285,
+ LPC = 286,
+ LCREG = 287,
+ LFLUSH = 288,
+ LREG = 289,
+ LFREG = 290,
+ LR = 291,
+ LCR = 292,
+ LF = 293,
+ LFPSCR = 294,
+ LLR = 295,
+ LCTR = 296,
+ LSPR = 297,
+ LSPREG = 298,
+ LSEG = 299,
+ LMSR = 300,
+ LPCDAT = 301,
+ LFUNCDAT = 302,
+ LSCHED = 303,
+ LXLD = 304,
+ LXST = 305,
+ LXOP = 306,
+ LXMV = 307,
+ LRLWM = 308,
+ LMOVMW = 309,
+ LMOVEM = 310,
+ LMOVFL = 311,
+ LMTFSB = 312,
+ LMA = 313,
+ LFCONST = 314,
+ LSCONST = 315,
+ LNAME = 316,
+ LLAB = 317,
+ LVAR = 318
};
#endif
/* Tokens. */
#define LRETT 276
#define LWORD 277
#define LTEXT 278
-#define LDATA 279
-#define LRETRN 280
-#define LCONST 281
-#define LSP 282
-#define LSB 283
-#define LFP 284
-#define LPC 285
-#define LCREG 286
-#define LFLUSH 287
-#define LREG 288
-#define LFREG 289
-#define LR 290
-#define LCR 291
-#define LF 292
-#define LFPSCR 293
-#define LLR 294
-#define LCTR 295
-#define LSPR 296
-#define LSPREG 297
-#define LSEG 298
-#define LMSR 299
-#define LPCDAT 300
-#define LFUNCDAT 301
-#define LSCHED 302
-#define LXLD 303
-#define LXST 304
-#define LXOP 305
-#define LXMV 306
-#define LRLWM 307
-#define LMOVMW 308
-#define LMOVEM 309
-#define LMOVFL 310
-#define LMTFSB 311
-#define LMA 312
-#define LFCONST 313
-#define LSCONST 314
-#define LNAME 315
-#define LLAB 316
-#define LVAR 317
+#define LGLOBL 279
+#define LDATA 280
+#define LRETRN 281
+#define LCONST 282
+#define LSP 283
+#define LSB 284
+#define LFP 285
+#define LPC 286
+#define LCREG 287
+#define LFLUSH 288
+#define LREG 289
+#define LFREG 290
+#define LR 291
+#define LCR 292
+#define LF 293
+#define LFPSCR 294
+#define LLR 295
+#define LCTR 296
+#define LSPR 297
+#define LSPREG 298
+#define LSEG 299
+#define LMSR 300
+#define LPCDAT 301
+#define LFUNCDAT 302
+#define LSCHED 303
+#define LXLD 304
+#define LXST 305
+#define LXOP 306
+#define LXMV 307
+#define LRLWM 308
+#define LMOVMW 309
+#define LMOVEM 310
+#define LMOVFL 311
+#define LMTFSB 312
+#define LMA 313
+#define LFCONST 314
+#define LSCONST 315
+#define LNAME 316
+#define LLAB 317
+#define LVAR 318
Addr addr;
}
/* Line 1529 of yacc.c. */
-#line 181 "y.tab.h"
+#line 183 "y.tab.h"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
else {
regalloc(&n4, types[TUINT64], N);
p1 = gins(AMOVD, N, &n4);
- p1->from.type = D_CONST;
+ p1->from.type = TYPE_CONST;
p1->from.offset = nl->type->bound;
}
}
regalloc(&n3, types[tptr], res);
p1 = gins(AMOVD, N, &n3);
datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from);
- p1->from.type = D_CONST;
+ p1->from.type = TYPE_ADDR;
} else if(isslice(nl->type) || nl->type->etype == TSTRING) {
n1 = n3;
n1.op = OINDREG;
case OINDREG:
// Increase the refcount of the register so that igen's caller
// has to call regfree.
- if(n->val.u.reg != D_R0+REGSP)
+ if(n->val.u.reg != REGSP)
reg[n->val.u.reg]++;
*a = *n;
return;
fp = structfirst(&flist, getoutarg(n->left->type));
memset(a, 0, sizeof *a);
a->op = OINDREG;
- a->val.u.reg = D_R0+REGSP;
+ a->val.u.reg = REGSP;
a->addable = 1;
a->xoffset = fp->width + widthptr; // +widthptr: saved lr at 0(SP)
a->type = n->type;
}
p = gins(AADD, N, &src);
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = w;
p = gins(AADD, N, &dst);
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = w;
} else {
p = gins(AADD, N, &src);
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = -dir;
p = gins(AADD, N, &dst);
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = -dir;
if(c >= 4) {
regalloc(&nend, types[tptr], N);
p = gins(AMOVD, &src, &nend);
- p->from.type = D_CONST;
+ p->from.type = TYPE_ADDR;
p->from.offset = w;
}
}
// TODO: enable duffcopy for larger copies.
if(c >= 4) {
p = gins(op, &src, &tmp);
- p->from.type = D_OREG;
+ p->from.type = TYPE_MEM;
p->from.offset = dir;
ploop = p;
p = gins(op, &tmp, &dst);
- p->to.type = D_OREG;
+ p->to.type = TYPE_MEM;
p->to.offset = dir;
p = gins(ACMP, &src, &nend);
patch(gbranch(ABNE, T, 0), ploop);
regfree(&nend);
} else {
+ // TODO(austin): Instead of generating ADD $-8,R8; ADD
+ // $-8,R7; n*(MOVDU 8(R8),R9; MOVDU R9,8(R7);) just
+ // generate the offsets directly and eliminate the
+ // ADDs. That will produce shorter, more
+ // pipeline-able code.
while(c-- > 0) {
p = gins(op, &src, &tmp);
- p->from.type = D_OREG;
+ p->from.type = TYPE_MEM;
p->from.offset = dir;
p = gins(op, &tmp, &dst);
- p->to.type = D_OREG;
+ p->to.type = TYPE_MEM;
p->to.offset = dir;
}
}
linkarchinit(void)
{
thestring = getgoarch();
+ arch.thestring = thestring;
if(strcmp(thestring, "ppc64le") == 0)
thelinkarch = &linkppc64le;
else
thelinkarch = &linkppc64;
+ arch.thelinkarch = thelinkarch;
}
vlong MAXWIDTH = 1LL<<50;
widthint = 8;
widthreg = 8;
- zprog.link = P;
- zprog.as = AGOK;
- zprog.reg = NREG;
- zprog.from.name = D_NONE;
- zprog.from.type = D_NONE;
- zprog.from.reg = NREG;
- zprog.to = zprog.from;
- zprog.from3 = zprog.from;
-
listinit9();
}
+
+void
+main(int argc, char **argv)
+{
+ arch.thechar = thechar;
+ arch.thestring = thestring;
+ arch.thelinkarch = thelinkarch;
+ arch.typedefs = typedefs;
+ arch.MAXWIDTH = MAXWIDTH;
+ arch.afunclit = afunclit;
+ arch.anyregalloc = anyregalloc;
+ arch.betypeinit = betypeinit;
+ arch.bgen = bgen;
+ arch.cgen = cgen;
+ arch.cgen_asop = cgen_asop;
+ arch.cgen_call = cgen_call;
+ arch.cgen_callinter = cgen_callinter;
+ arch.cgen_ret = cgen_ret;
+ arch.clearfat = clearfat;
+ arch.clearp = clearp;
+ arch.defframe = defframe;
+ arch.dgostringptr = dgostringptr;
+ arch.dgostrlitptr = dgostrlitptr;
+ arch.dsname = dsname;
+ arch.dsymptr = dsymptr;
+ arch.dumpdata = dumpdata;
+ arch.dumpit = dumpit;
+ arch.excise = excise;
+ arch.expandchecks = expandchecks;
+ arch.fixautoused = fixautoused;
+ arch.gclean = gclean;
+ arch.gdata = gdata;
+ arch.gdatacomplex = gdatacomplex;
+ arch.gdatastring = gdatastring;
+ arch.ggloblnod = ggloblnod;
+ arch.ggloblsym = ggloblsym;
+ arch.ginit = ginit;
+ arch.gins = gins;
+ arch.ginscall = ginscall;
+ arch.gjmp = gjmp;
+ arch.gtrack = gtrack;
+ arch.gused = gused;
+ arch.igen = igen;
+ arch.isfat = isfat;
+ arch.linkarchinit = linkarchinit;
+ arch.markautoused = markautoused;
+ arch.naddr = naddr;
+ arch.newplist = newplist;
+ arch.nodarg = nodarg;
+ arch.patch = patch;
+ arch.proginfo = proginfo;
+ arch.regalloc = regalloc;
+ arch.regfree = regfree;
+ arch.regopt = regopt;
+ arch.regtyp = regtyp;
+ arch.sameaddr = sameaddr;
+ arch.smallindir = smallindir;
+ arch.stackaddr = stackaddr;
+ arch.unpatch = unpatch;
+
+ gcmain(argc, argv);
+}
// TODO(minux): Remove when no longer used.
#define noimpl sysfatal("%s not implemented (%s:%d).", __func__, __FILE__, __LINE__)
-#define TEXTFLAG reg
-
EXTERN int32 dynloc;
EXTERN uchar reg[NREG+NFREG];
EXTERN int32 pcloc; // instruction counter
EXTERN Strlit emptystring;
-EXTERN Prog zprog;
-EXTERN Node* newproc;
-EXTERN Node* deferproc;
-EXTERN Node* deferreturn;
-EXTERN Node* panicindex;
-EXTERN Node* panicslice;
EXTERN Node* panicdiv;
-EXTERN Node* throwreturn;
extern vlong unmappedzero;
/*
void listinit(void);
void zaddr(Biobuf*, Addr*, int, int);
+
+void afunclit(Addr*, Node*);
+int anyregalloc(void);
+void betypeinit(void);
+void bgen(Node*, int, int, Prog*);
+void cgen(Node*, Node*);
+void cgen_asop(Node*);
+void cgen_call(Node*, int);
+void cgen_callinter(Node*, Node*, int);
+void cgen_ret(Node*);
+void clearfat(Node*);
+void clearp(Prog*);
+void defframe(Prog*);
+int dgostringptr(Sym*, int, char*);
+int dgostrlitptr(Sym*, int, Strlit*);
+int dsname(Sym*, int, char*, int);
+int dsymptr(Sym*, int, Sym*, int);
+void dumpdata(void);
+void dumpit(char*, Flow*, int);
+void excise(Flow*);
+void expandchecks(Prog*);
+void fixautoused(Prog*);
+void gclean(void);
+void gdata(Node*, Node*, int);
+void gdatacomplex(Node*, Mpcplx*);
+void gdatastring(Node*, Strlit*);
+void ggloblnod(Node *nam);
+void ggloblsym(Sym *s, int32 width, int8 flags);
+void ginit(void);
+Prog* gins(int, Node*, Node*);
+void ginscall(Node*, int);
+Prog* gjmp(Prog*);
+void gtrack(Sym*);
+void gused(Node*);
+void igen(Node*, Node*, Node*);
+int isfat(Type*);
+void linkarchinit(void);
+void markautoused(Prog*);
+void naddr(Node*, Addr*, int);
+Plist* newplist(void);
+Node* nodarg(Type*, int);
+void patch(Prog*, Prog*);
+void proginfo(ProgInfo*, Prog*);
+void regalloc(Node*, Type*, Node*);
+void regfree(Node*);
+void regopt(Prog*);
+int regtyp(Addr*);
+int sameaddr(Addr*, Addr*);
+int smallindir(Addr*, Addr*);
+int stackaddr(Addr*);
+Prog* unpatch(Prog*);
+
NodeList *l;
Node *n;
- // fill in argument size
- ptxt->to.offset = rnd(curfn->type->argwid, widthptr);
-
- // fill in final stack size
- ptxt->to.offset <<= 32;
+ // fill in argument size, stack size
+ ptxt->to.type = TYPE_TEXTSIZE;
+ ptxt->to.u.argsize = rnd(curfn->type->argwid, widthptr);
frame = rnd(stksize+maxarg, widthreg);
- ptxt->to.offset |= frame;
+ ptxt->to.offset = frame;
// insert code to zero ambiguously live variables
// so that the garbage collector only sees initialized values
return p;
if(cnt < 4*widthptr) {
for(i = 0; i < cnt; i += widthptr)
- p = appendpp(p, AMOVD, D_REG, REGZERO, 0, D_OREG, REGSP, 8+frame+lo+i);
+ p = appendpp(p, AMOVD, TYPE_REG, REGZERO, 0, TYPE_MEM, REGSP, 8+frame+lo+i);
} else if(cnt <= 128*widthptr) {
- p = appendpp(p, AADD, D_CONST, NREG, 8+frame+lo-8, D_REG, REGRT1, 0);
+ p = appendpp(p, AADD, TYPE_CONST, 0, 8+frame+lo-8, TYPE_REG, REGRT1, 0);
p->reg = REGSP;
- p = appendpp(p, ADUFFZERO, D_NONE, NREG, 0, D_OREG, NREG, 0);
+ p = appendpp(p, ADUFFZERO, TYPE_NONE, 0, 0, TYPE_MEM, 0, 0);
f = sysfunc("duffzero");
naddr(f, &p->to, 1);
afunclit(&p->to, f);
p->to.offset = 4*(128-cnt/widthptr);
} else {
- p = appendpp(p, AMOVD, D_CONST, NREG, 8+frame+lo-8, D_REG, REGTMP, 0);
- p = appendpp(p, AADD, D_REG, REGTMP, 0, D_REG, REGRT1, 0);
+ p = appendpp(p, AMOVD, TYPE_CONST, 0, 8+frame+lo-8, TYPE_REG, REGTMP, 0);
+ p = appendpp(p, AADD, TYPE_REG, REGTMP, 0, TYPE_REG, REGRT1, 0);
p->reg = REGSP;
- p = appendpp(p, AMOVD, D_CONST, NREG, cnt, D_REG, REGTMP, 0);
- p = appendpp(p, AADD, D_REG, REGTMP, 0, D_REG, REGRT2, 0);
+ p = appendpp(p, AMOVD, TYPE_CONST, 0, cnt, TYPE_REG, REGTMP, 0);
+ p = appendpp(p, AADD, TYPE_REG, REGTMP, 0, TYPE_REG, REGRT2, 0);
p->reg = REGRT1;
- p1 = p = appendpp(p, AMOVDU, D_REG, REGZERO, 0, D_OREG, REGRT1, widthptr);
- p = appendpp(p, ACMP, D_REG, REGRT1, 0, D_REG, REGRT2, 0);
- p = appendpp(p, ABNE, D_NONE, NREG, 0, D_BRANCH, NREG, 0);
+ p1 = p = appendpp(p, AMOVDU, TYPE_REG, REGZERO, 0, TYPE_MEM, REGRT1, widthptr);
+ p = appendpp(p, ACMP, TYPE_REG, REGRT1, 0, TYPE_REG, REGRT2, 0);
+ p = appendpp(p, ABNE, TYPE_NONE, 0, 0, TYPE_BRANCH, 0, 0);
patch(p, p1);
}
return p;
continue;
if (p->from.node)
- p->from.node->used = 1;
+ ((Node*)(p->from.node))->used = 1;
if (p->to.node)
- p->to.node->used = 1;
+ ((Node*)(p->to.node))->used = 1;
}
}
Prog **lp;
for (lp=&p; (p=*lp) != P; ) {
- if (p->as == ATYPE && p->from.node && p->from.name == D_AUTO && !p->from.node->used) {
+ if (p->as == ATYPE && p->from.node && p->from.name == NAME_AUTO && !((Node*)(p->from.node))->used) {
*lp = p->link;
continue;
}
- if ((p->as == AVARDEF || p->as == AVARKILL) && p->to.node && !p->to.node->used) {
+ if ((p->as == AVARDEF || p->as == AVARKILL) && p->to.node && !((Node*)(p->to.node))->used) {
// Cannot remove VARDEF instruction, because - unlike TYPE handled above -
// VARDEFs are interspersed with other code, and a jump might be using the
// VARDEF as a target. Replace with a no-op instead. A later pass will remove
// the no-ops.
- p->to.type = D_NONE;
- p->to.node = N;
- p->as = ANOP;
+ nopout(p);
continue;
}
- if (p->from.name == D_AUTO && p->from.node)
- p->from.offset += p->from.node->stkdelta;
+ if (p->from.name == NAME_AUTO && p->from.node)
+ p->from.offset += ((Node*)(p->from.node))->stkdelta;
- if (p->to.name == D_AUTO && p->to.node)
- p->to.offset += p->to.node->stkdelta;
+ if (p->to.name == NAME_AUTO && p->to.node)
+ p->to.offset += ((Node*)(p->to.node))->stkdelta;
lp = &p->link;
}
{
Prog *p;
p = gins(AMOVD, f, N);
- p->to.type = D_SPR;
- p->to.offset = D_CTR;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_CTR;
p = gins(ABL, reg, N);
- p->to.type = D_SPR;
- p->to.offset = D_CTR;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_CTR;
}
/*
// The ppc64 NOP is really or r0, r0, r0; use that description
// because the NOP pseudo-instruction would be removed by
// the linker.
- nodreg(®, types[TINT], D_R0);
+ nodreg(®, types[TINT], REG_R0);
gins(AOR, ®, ®);
}
p = gins(ABL, N, f);
gins(AUNDEF, N, N);
break;
}
- nodreg(®, types[tptr], D_R0+REGENV);
- nodreg(&r1, types[tptr], D_R0+3);
+ nodreg(®, types[tptr], REGENV);
+ nodreg(&r1, types[tptr], REG_R3);
gmove(f, ®);
reg.op = OINDREG;
gmove(®, &r1);
case 1: // call in new proc (go)
case 2: // deferred call (defer)
nodconst(&con, types[TINT64], argsize(f->type));
- nodreg(®, types[TINT64], D_R0+3);
- nodreg(®2, types[TINT64], D_R0+4);
+ nodreg(®, types[TINT64], REG_R3);
+ nodreg(®2, types[TINT64], REG_R4);
gmove(f, ®);
gmove(&con, ®2);
p = gins(AMOVW, ®2, N);
- p->to.type = D_OREG;
+ p->to.type = TYPE_MEM;
p->to.reg = REGSP;
p->to.offset = 8;
p = gins(AMOVD, ®, N);
- p->to.type = D_OREG;
+ p->to.type = TYPE_MEM;
p->to.reg = REGSP;
p->to.offset = 16;
}
if(proc == 2) {
- nodreg(®, types[TINT64], D_R0+3);
+ nodreg(®, types[TINT64], REG_R3);
p = gins(ACMP, ®, N);
- p->to.type = D_REG;
- p->to.reg = D_R0;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_R0;
p = gbranch(ABEQ, T, +1);
cgen_ret(N);
patch(p, pc);
// register to hold its address.
igen(i, &nodi, res); // REG = &inter
- nodindreg(&nodsp, types[tptr], D_R0+REGSP);
+ nodindreg(&nodsp, types[tptr], REGSP);
nodsp.xoffset = widthptr;
if(proc != 0)
nodsp.xoffset += 2 * widthptr; // leave room for size & fn
} else {
// go/defer. generate go func value.
p = gins(AMOVD, &nodo, &nodr); // REG = &(32+offset(REG)) -- i.tab->fun[f]
- p->from.type = D_CONST;
+ p->from.type = TYPE_ADDR;
}
nodr.type = n->left->type;
memset(&nod, 0, sizeof(nod));
nod.op = OINDREG;
- nod.val.u.reg = D_R0+REGSP;
+ nod.val.u.reg = REGSP;
nod.addable = 1;
nod.xoffset = fp->width + widthptr; // +widthptr: saved LR at 0(R1)
memset(&nod1, 0, sizeof(nod1));
nod1.op = OINDREG;
- nod1.val.u.reg = D_R0 + REGSP;
+ nod1.val.u.reg = REGSP;
nod1.addable = 1;
nod1.xoffset = fp->width + widthptr; // +widthptr: saved lr at 0(SP)
genlist(curfn->exit);
p = gins(ARET, N, N);
if(n != N && n->op == ORETJMP) {
- p->to.name = D_EXTERN;
- p->to.type = D_CONST;
+ p->to.name = NAME_EXTERN;
+ p->to.type = TYPE_ADDR;
p->to.sym = linksym(n->left->sym);
}
}
// Handle divide-by-zero panic.
p1 = gins(optoas(OCMP, t), &tr, N);
- p1->to.type = D_REG;
+ p1->to.type = TYPE_REG;
p1->to.reg = REGZERO;
p1 = gbranch(optoas(ONE, t), T, +1);
if(panicdiv == N)
case TINT32:
gins(optoas(OMUL, t), &n2, &n1);
p = gins(ASRAD, N, &n1);
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = w;
break;
case TUINT8:
case TUINT32:
gins(optoas(OMUL, t), &n2, &n1);
p = gins(ASRD, N, &n1);
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = w;
break;
case TINT64:
if(reg[REGRT1] > 0)
fatal("R%d in use during clearfat", REGRT1);
- nodreg(&r0, types[TUINT64], 0); // r0 is always zero
- nodreg(&dst, types[tptr], D_R0+REGRT1);
+ nodreg(&r0, types[TUINT64], REG_R0); // r0 is always zero
+ nodreg(&dst, types[tptr], REGRT1);
reg[REGRT1]++;
agen(nl, &dst);
if(q > 128) {
p = gins(ASUB, N, &dst);
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = 8;
regalloc(&end, types[tptr], N);
p = gins(AMOVD, &dst, &end);
- p->from.type = D_CONST;
+ p->from.type = TYPE_ADDR;
p->from.offset = q*8;
p = gins(AMOVDU, &r0, &dst);
- p->to.type = D_OREG;
+ p->to.type = TYPE_MEM;
p->to.offset = 8;
pl = p;
boff = 8;
} else if(q >= 4) {
p = gins(ASUB, N, &dst);
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = 8;
f = sysfunc("duffzero");
p = gins(ADUFFZERO, N, f);
} else {
for(t = 0; t < q; t++) {
p = gins(AMOVD, &r0, &dst);
- p->to.type = D_OREG;
+ p->to.type = TYPE_MEM;
p->to.offset = 8*t;
}
boff = 8*q;
for(t = 0; t < c; t++) {
p = gins(AMOVB, &r0, &dst);
- p->to.type = D_OREG;
+ p->to.type = TYPE_MEM;
p->to.offset = t+boff;
}
reg[REGRT1]--;
continue;
if(debug_checknil && p->lineno > 1) // p->lineno==1 in generated wrappers
warnl(p->lineno, "generated nil check");
- if(p->from.type != D_REG)
+ if(p->from.type != TYPE_REG)
fatal("invalid nil check %P\n", p);
/*
// check is
reg = p->from.reg;
p->as = ATD;
p->from = p->to = p->from3 = zprog.from;
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = 4;
- p->from.reg = NREG;
- p->reg = 0;
- p->to.type = D_REG;
+ p->from.reg = 0;
+ p->reg = REG_R0;
+ p->to.type = TYPE_REG;
p->to.reg = reg;
*/
// check is
p1->pc = 9999;
p2->pc = 9999;
p->as = ACMP;
- p->to.type = D_REG;
+ p->to.type = TYPE_REG;
p->to.reg = REGZERO;
p1->as = ABNE;
- //p1->from.type = D_CONST;
+ //p1->from.type = TYPE_CONST;
//p1->from.offset = 1; // likely
- p1->to.type = D_BRANCH;
+ p1->to.type = TYPE_BRANCH;
p1->to.u.branch = p2->link;
// crash by write to memory address 0.
p2->as = AMOVD;
- p2->from.type = D_REG;
- p2->from.reg = 0;
- p2->to.type = D_OREG;
- p2->to.reg = 0;
+ p2->from.type = TYPE_REG;
+ p2->from.reg = REG_R0;
+ p2->to.type = TYPE_MEM;
+ p2->to.reg = REG_R0;
p2->to.offset = 0;
}
}
Prog *p;
p = gins(ADATA, N, N);
- p->from.type = D_OREG;
- p->from.name = D_EXTERN;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.offset = off;
- p->from.reg = NREG;
p->from.sym = linksym(s);
- p->reg = n;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = n;
- p->to.type = D_SCONST;
- p->to.name = D_NONE;
- p->to.reg = NREG;
+ p->to.type = TYPE_SCONST;
+ p->to.name = NAME_NONE;
p->to.offset = 0;
memmove(p->to.u.sval, t, n);
return off + n;
Sym *sym;
sym = stringsym(s, len);
- a->type = D_OREG;
- a->name = D_EXTERN;
+ a->type = TYPE_MEM;
+ a->name = NAME_EXTERN;
a->etype = simtype[TINT];
a->offset = widthptr+widthint; // skip header
- a->reg = NREG;
+ a->reg = 0;
a->sym = linksym(sym);
a->node = sym->def;
}
Sym *sym;
sym = stringsym(sval->s, sval->len);
- a->type = D_OREG;
- a->name = D_EXTERN;
+ a->type = TYPE_MEM;
+ a->name = NAME_EXTERN;
a->sym = linksym(sym);
- a->reg = NREG;
+ a->reg = 0;
a->node = sym->def;
a->offset = 0; // header
a->etype = TSTRING;
}
}
p = gins(ADATA, nam, nr);
- p->reg = wid;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = wid;
}
void
w = types[w]->width;
p = gins(ADATA, nam, N);
- p->reg = w;
- p->to.type = D_FCONST;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = w;
+ p->to.type = TYPE_FCONST;
p->to.u.dval = mpgetflt(&cval->real);
p = gins(ADATA, nam, N);
- p->reg = w;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = w;
p->from.offset += w;
- p->to.type = D_FCONST;
+ p->to.type = TYPE_FCONST;
p->to.u.dval = mpgetflt(&cval->imag);
}
p = gins(ADATA, nam, N);
datastring(sval->s, sval->len, &p->to);
- p->reg = types[tptr]->width;
- p->to.type = D_CONST;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = types[tptr]->width;
+ p->to.type = TYPE_ADDR;
p->to.etype = simtype[tptr];
nodconst(&nod1, types[TINT], sval->len);
p = gins(ADATA, nam, &nod1);
- p->reg = widthint;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = widthint;
p->from.offset += widthptr;
}
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
- p->from.type = D_OREG;
- p->from.name = D_EXTERN;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
- p->reg = widthptr;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = widthptr;
datastring(str, strlen(str)+1, &p->to);
- p->to.type = D_CONST;
+ p->to.type = TYPE_CONST;
p->to.etype = simtype[TINT];
off += widthptr;
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
- p->from.type = D_OREG;
- p->from.name = D_EXTERN;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
- p->reg = widthptr;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = widthptr;
datagostring(lit, &p->to);
- p->to.type = D_CONST;
+ p->to.type = TYPE_ADDR;
p->to.etype = simtype[TINT];
off += widthptr;
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
- p->from.type = D_OREG;
- p->from.name = D_EXTERN;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
- p->reg = widthptr;
- p->to.type = D_CONST;
- p->to.name = D_EXTERN;
+ p->from3.type = TYPE_CONST;
+ p->from3.offset = widthptr;
+ p->to.type = TYPE_ADDR;
+ p->to.name = NAME_EXTERN;
p->to.sym = linksym(x);
p->to.offset = xoff;
off += widthptr;
nopout(Prog *p)
{
p->as = ANOP;
+ p->from = zprog.from;
+ p->from3 = zprog.from3;
+ p->reg = zprog.reg;
+ p->to = zprog.to;
}
-
USED(t);
p = prog(as);
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
p->to.u.branch = P;
// TODO(minux): Enable this code.
// Note: liblink used Bcc CR0, label form, so we need another way
// to set likely/unlikely flag. Also note the y bit is not exactly
// likely/unlikely bit.
if(0 && as != ABR && likely != 0) {
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = likely > 0;
}
return p;
void
patch(Prog *p, Prog *to)
{
- if(p->to.type != D_BRANCH)
+ if(p->to.type != TYPE_BRANCH)
fatal("patch: not a branch");
p->to.u.branch = to;
p->to.offset = to->pc;
{
Prog *q;
- if(p->to.type != D_BRANCH)
+ if(p->to.type != TYPE_BRANCH)
fatal("unpatch: not a branch");
q = p->to.u.branch;
p->to.u.branch = P;
p->lineno = nam->lineno;
p->from.sym->gotype = linksym(ngotype(nam));
p->to.sym = nil;
- p->to.type = D_CONST;
+ p->to.type = TYPE_CONST;
p->to.offset = nam->type->width;
if(nam->readonly)
- p->reg = RODATA;
+ p->from3.offset = RODATA;
if(nam->type != T && !haspointers(nam->type))
- p->reg |= NOPTR;
+ p->from3.offset |= NOPTR;
}
void
Prog *p;
p = gins(AUSEFIELD, N, N);
- p->from.type = D_OREG;
- p->from.name = D_EXTERN;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
}
Prog *p;
p = gins(AGLOBL, N, N);
- p->from.type = D_OREG;
- p->from.name = D_EXTERN;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
- p->to.type = D_CONST;
- p->to.name = D_NONE;
+ p->to.type = TYPE_CONST;
+ p->to.name = NAME_NONE;
p->to.offset = width;
- p->reg = flags;
+ p->from3.offset = flags;
}
int
void
afunclit(Addr *a, Node *n)
{
- if(a->type == D_CONST && a->name == D_EXTERN) {
- a->type = D_OREG;
+ if(a->type == TYPE_ADDR && a->name == NAME_EXTERN) {
+ a->type = TYPE_MEM;
a->sym = linksym(n->sym);
}
}
// TODO(austin): Consolidate REGTLS and REGG?
REGG,
REGTMP, // REGTMP
- FREGCVI+NREG,
- FREGZERO+NREG,
- FREGHALF+NREG,
- FREGONE+NREG,
- FREGTWO+NREG,
+ FREGCVI,
+ FREGZERO,
+ FREGHALF,
+ FREGONE,
+ FREGTWO,
};
void
for(i=0; i<nelem(reg); i++)
reg[i] = 1;
- for(i=0; i<NREG; i++)
- reg[i] = 0;
- for(i=NREG; i<NREG+NREG; i++)
+ for(i=0; i<NREG+NFREG; i++)
reg[i] = 0;
for(i=0; i<nelem(resvd); i++)
- reg[resvd[i]]++;
+ reg[resvd[i] - REG_R0]++;
}
static uintptr regpc[nelem(reg)];
int i;
for(i=0; i<nelem(resvd); i++)
- reg[resvd[i]]--;
+ reg[resvd[i] - REG_R0]--;
for(i=0; i<nelem(reg); i++)
if(reg[i])
- yyerror("reg %R left allocated, %p\n", i, regpc[i]);
+ yyerror("reg %R left allocated, %p\n", i+REG_R0, regpc[i]);
}
int32
if(debug['r']) {
fixfree = 0;
fltfree = 0;
- for(i = D_R0; i < D_F0+NREG; i++)
- if(reg[i] == 0) {
- if(i < D_F0)
+ for(i = REG_R0; i < REG_F31; i++)
+ if(reg[i - REG_R0] == 0) {
+ if(i < REG_F0)
fixfree++;
else
fltfree++;
case TBOOL:
if(o != N && o->op == OREGISTER) {
i = o->val.u.reg;
- if(i >= D_R0+REGMIN && i <= D_R0+REGMAX)
+ if(i >= REGMIN && i <= REGMAX)
goto out;
}
- for(i=D_R0+REGMIN; i<=D_R0+REGMAX; i++)
- if(reg[i] == 0) {
- regpc[i] = (uintptr)getcallerpc(&n);
+ for(i=REGMIN; i<=REGMAX; i++)
+ if(reg[i - REG_R0] == 0) {
+ regpc[i - REG_R0] = (uintptr)getcallerpc(&n);
goto out;
}
flusherrors();
- for(i=D_R0; i<D_R0+NREG; i++)
- print("R%d %p\n", i, regpc[i]);
+ for(i=REG_R0; i<REG_R0+NREG; i++)
+ print("R%d %p\n", i, regpc[i - REG_R0]);
fatal("out of fixed registers");
case TFLOAT32:
case TFLOAT64:
if(o != N && o->op == OREGISTER) {
i = o->val.u.reg;
- if(i >= D_F0+FREGMIN && i <= D_F0+FREGMAX)
+ if(i >= FREGMIN && i <= FREGMAX)
goto out;
}
- for(i=D_F0+FREGMIN; i<=D_F0+FREGMAX; i++)
- if(reg[i] == 0) {
- regpc[i] = (uintptr)getcallerpc(&n);
+ for(i=FREGMIN; i<=FREGMAX; i++)
+ if(reg[i - REG_R0] == 0) {
+ regpc[i - REG_R0] = (uintptr)getcallerpc(&n);
goto out;
}
flusherrors();
- for(i=D_F0; i<D_F0+NREG; i++)
- print("F%d %p\n", i, regpc[i]);
+ for(i=REG_F0; i<REG_F0+NREG; i++)
+ print("F%d %p\n", i, regpc[i - REG_R0]);
fatal("out of floating registers");
case TCOMPLEX64:
return;
out:
- reg[i]++;
+ reg[i - REG_R0]++;
nodreg(n, t, i);
}
return;
if(n->op != OREGISTER && n->op != OINDREG)
fatal("regfree: not a register");
- i = n->val.u.reg;
- if(i == D_R0 + REGSP)
+ i = n->val.u.reg - REG_R0;
+ if(i == REGSP - REG_R0)
return;
if(i < 0 || i >= nelem(reg))
fatal("regfree: reg out of range");
case 0: // output arg for calling another function
n->op = OINDREG;
- n->val.u.reg = D_R0+REGSP;
+ n->val.u.reg = REGSP;
n->xoffset += 8;
break;
case 2: // offset output arg
fatal("shouldn't be used");
n->op = OINDREG;
- n->val.u.reg = D_R0 + REGSP;
+ n->val.u.reg = REGSP;
n->xoffset += types[tptr]->width;
break;
}
regalloc(&r3, types[TINT64], t);
gins(AFCTIDZ, &r1, &r2);
p1 = gins(AFMOVD, &r2, N);
- p1->to.type = D_OREG;
+ p1->to.type = TYPE_MEM;
p1->to.reg = REGSP;
p1->to.offset = -8;
p1 = gins(AMOVD, N, &r3);
- p1->from.type = D_OREG;
+ p1->from.type = TYPE_MEM;
p1->from.reg = REGSP;
p1->from.offset = -8;
regfree(&r2);
regfree(&r1);
if(tt == TUINT64) {
p1 = gbranch(optoas(OLT, types[TFLOAT64]), T, +1); // use CR0 here again
- nodreg(&r1, types[TINT64], D_R0+REGTMP);
+ nodreg(&r1, types[TINT64], REGTMP);
gins(AMOVD, &bigi, &r1);
gins(AADD, &r1, &r3);
patch(p1, pc);
regalloc(&r1, types[TINT64], N);
gmove(f, &r1);
if(ft == TUINT64) {
- nodreg(&r2, types[TUINT64], D_R0+REGTMP);
+ nodreg(&r2, types[TUINT64], REGTMP);
gmove(&bigi, &r2);
gins(ACMPU, &r1, &r2);
p1 = gbranch(optoas(OLT, types[TUINT64]), T, +1);
p2 = gins(ASRD, N, &r1);
- p2->from.type = D_CONST;
+ p2->from.type = TYPE_CONST;
p2->from.offset = 1;
patch(p1, pc);
}
regalloc(&r2, types[TFLOAT64], t);
p1 = gins(AMOVD, &r1, N);
- p1->to.type = D_OREG;
+ p1->to.type = TYPE_MEM;
p1->to.reg = REGSP;
p1->to.offset = -8;
p1 = gins(AFMOVD, N, &r2);
- p1->from.type = D_OREG;
+ p1->from.type = TYPE_MEM;
p1->from.reg = REGSP;
p1->from.offset = -8;
gins(AFCFID, &r2, &r2);
regfree(&r1);
if(ft == TUINT64) {
p1 = gbranch(optoas(OLT, types[TUINT64]), T, +1); // use CR0 here again
- nodreg(&r1, types[TFLOAT64], D_F0+FREGTWO);
+ nodreg(&r1, types[TFLOAT64], FREGTWO);
gins(AFMUL, &r1, &r2);
patch(p1, pc);
}
p->from = af;
if(t != N)
p->to = at;
- if(as == ATEXT)
- p->reg = 0;
if(debug['g'])
print("%P\n", p);
break;
case AMOVD:
case AMOVDU:
- if(af.type == D_CONST)
+ if(af.type == TYPE_CONST || af.type == TYPE_ADDR)
break;
w = 8;
break;
}
- if(w != 0 && ((f != N && af.width < w) || (t != N && at.type != D_REG && at.width > w))) {
+ if(w != 0 && ((f != N && af.width < w) || (t != N && at.type != TYPE_REG && at.width > w))) {
dump("f", f);
dump("t", t);
fatal("bad width: %P (%d, %d)\n", p, af.width, at.width);
return;
if(n->op != OINDREG)
return;
- if(n->val.u.reg == D_R0+REGSP) // stack offset cannot be large
+ if(n->val.u.reg == REGSP) // stack offset cannot be large
return;
if(n->xoffset != (int32)n->xoffset) {
// TODO(minux): offset too large, move into R31 and add to R31 instead.
{
Sym *s;
- a->type = D_NONE;
- a->name = D_NONE;
- a->reg = NREG;
+ a->type = TYPE_NONE;
+ a->name = NAME_NONE;
+ a->reg = 0;
a->gotype = nil;
a->node = N;
a->etype = 0;
case ONAME:
a->etype = 0;
- a->reg = NREG;
+ a->reg = 0;
if(n->type != T)
a->etype = simtype[n->type->etype];
a->offset = n->xoffset;
s = pkglookup(s->name, n->type->sym->pkg);
}
- a->type = D_OREG;
+ a->type = TYPE_MEM;
switch(n->class) {
default:
fatal("naddr: ONAME class %S %d\n", n->sym, n->class);
case PEXTERN:
- a->name = D_EXTERN;
+ a->name = NAME_EXTERN;
break;
case PAUTO:
- a->name = D_AUTO;
+ a->name = NAME_AUTO;
break;
case PPARAM:
case PPARAMOUT:
- a->name = D_PARAM;
+ a->name = NAME_PARAM;
break;
case PFUNC:
- a->name = D_EXTERN;
- a->type = D_CONST;
+ a->name = NAME_EXTERN;
+ a->type = TYPE_ADDR;
a->width = widthptr;
s = funcsym(s);
break;
fatal("naddr: const %lT", n->type);
break;
case CTFLT:
- a->type = D_FCONST;
+ a->type = TYPE_FCONST;
a->u.dval = mpgetflt(n->val.u.fval);
break;
case CTINT:
case CTRUNE:
a->sym = nil;
- a->type = D_CONST;
+ a->type = TYPE_CONST;
a->offset = mpgetfix(n->val.u.xval);
break;
case CTSTR:
break;
case CTBOOL:
a->sym = nil;
- a->type = D_CONST;
+ a->type = TYPE_CONST;
a->offset = n->val.u.bval;
break;
case CTNIL:
a->sym = nil;
- a->type = D_CONST;
+ a->type = TYPE_CONST;
a->offset = 0;
break;
}
break;
case OREGISTER:
- if(n->val.u.reg < D_F0) {
- a->type = D_REG;
- a->reg = n->val.u.reg;
- } else {
- a->type = D_FREG;
- a->reg = n->val.u.reg - D_F0;
- }
+ a->type = TYPE_REG;
+ a->reg = n->val.u.reg;
a->sym = nil;
break;
case OINDREG:
- a->type = D_OREG;
+ a->type = TYPE_MEM;
a->reg = n->val.u.reg;
a->sym = linksym(n->sym);
a->offset = n->xoffset;
a->width = n->left->type->width;
a->offset = n->xoffset;
a->sym = linksym(n->left->sym);
- a->type = D_OREG;
- a->name = D_PARAM;
+ a->type = TYPE_MEM;
+ a->name = NAME_PARAM;
a->node = n->left->orig;
break;
case OCLOSUREVAR:
if(!curfn->needctxt)
fatal("closurevar without needctxt");
- a->type = D_OREG;
+ a->type = TYPE_MEM;
a->reg = REGENV;
a->offset = n->xoffset;
a->sym = nil;
// itable of interface value
naddr(n->left, a, canemitcode);
a->etype = simtype[tptr];
- if(a->type == D_CONST && a->offset == 0)
+ if(a->type == TYPE_CONST && a->offset == 0)
break; // itab(nil)
a->width = widthptr;
break;
// pointer in a string or slice
naddr(n->left, a, canemitcode);
a->etype = simtype[tptr];
- if(a->type == D_CONST && a->offset == 0)
+ if(a->type == TYPE_CONST && a->offset == 0)
break; // ptr(nil)
a->offset += Array_array;
a->width = widthptr;
// len of string or slice
naddr(n->left, a, canemitcode);
a->etype = simtype[TINT];
- if(a->type == D_CONST && a->offset == 0)
+ if(a->type == TYPE_CONST && a->offset == 0)
break; // len(nil)
a->offset += Array_nel;
a->width = widthint;
// cap of string or slice
naddr(n->left, a, canemitcode);
a->etype = simtype[TINT];
- if(a->type == D_CONST && a->offset == 0)
+ if(a->type == TYPE_CONST && a->offset == 0)
break; // cap(nil)
a->offset += Array_cap;
a->width = widthint;
naddr(n->left, a, canemitcode);
a->etype = tptr;
switch(a->type) {
- case D_OREG:
- a->type = D_CONST;
+ case TYPE_MEM:
+ a->type = TYPE_ADDR;
break;
- case D_REG:
- case D_CONST:
+ case TYPE_REG:
+ case TYPE_CONST:
break;
default:
if(t == T)
fatal("optoas: t is nil");
- a = AGOK;
+ a = AXXX;
switch(CASE(op, simtype[t->etype])) {
default:
fatal("optoas: no entry for op=%O type=%T", op, t);
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include "../gc/popt.h"
#define Z N
#define Adr Addr
/*
* prog.c
*/
-typedef struct ProgInfo ProgInfo;
-struct ProgInfo
-{
- uint32 flags; // the bits below
- uint64 reguse; // registers implicitly used by this instruction
- uint64 regset; // registers implicitly set by this instruction
- uint64 regindex; // registers used by addressing mode
-};
-
-enum
-{
- // Pseudo-op, like TEXT, GLOBL, TYPE, PCDATA, FUNCDATA.
- Pseudo = 1<<1,
-
- // There's nothing to say about the instruction,
- // but it's still okay to see.
- OK = 1<<2,
-
- // Size of right-side write, or right-side read if no write.
- SizeB = 1<<3,
- SizeW = 1<<4,
- SizeL = 1<<5,
- SizeQ = 1<<6,
- SizeF = 1<<7, // float aka float32
- SizeD = 1<<8, // double aka float64
-
- // Left side (Prog.from): address taken, read, write.
- LeftAddr = 1<<9,
- LeftRead = 1<<10,
- LeftWrite = 1<<11,
-
- // Register in middle (Prog.reg); only ever read.
- RegRead = 1<<12,
- CanRegRead = 1<<13,
-
- // Right side (Prog.to): address taken, read, write.
- RightAddr = 1<<14,
- RightRead = 1<<15,
- RightWrite = 1<<16,
-
- // Instruction updates whichever of from/to is type D_OREG
- PostInc = 1<<17,
-
- // Instruction kinds
- Move = 1<<18, // straight move
- Conv = 1<<19, // size conversion
- Cjmp = 1<<20, // conditional jump
- Break = 1<<21, // breaks control flow (no fallthrough)
- Call = 1<<22, // function call
- Jump = 1<<23, // jump
- Skip = 1<<24, // data instruction
-};
-
void proginfo(ProgInfo*, Prog*);
// Many Power ISA arithmetic and logical instructions come in four
int as2variant(int);
int variant2as(int, int);
-
-// To allow use of AJMP, ACALL, ARET in ../gc/popt.c.
-enum
-{
- AJMP = ABR,
- ACALL = ABL,
- ARET = ARETURN,
-};
// Convert uses to $0 to uses of R0 and
// propagate R0
if(regzer(&p->from))
- if(p->to.type == D_REG) {
- p->from.type = D_REG;
+ if(p->to.type == TYPE_REG) {
+ p->from.type = TYPE_REG;
p->from.reg = REGZERO;
if(copyprop(r)) {
excise(r);
case AMOVBZ:
case AMOVW:
case AMOVWZ:
- if(p->to.type != D_REG)
+ if(p->to.type != TYPE_REG)
continue;
break;
}
p1 = r1->prog;
if(p1->as != p->as)
continue;
- if(p1->from.type != D_REG || p1->from.reg != p->to.reg)
+ if(p1->from.type != TYPE_REG || p1->from.reg != p->to.reg)
continue;
- if(p1->to.type != D_REG || p1->to.reg != p->to.reg)
+ if(p1->to.type != TYPE_REG || p1->to.reg != p->to.reg)
continue;
excise(r1);
}
if(r1 == nil)
continue;
p1 = r1->prog;
- if(p1->to.type != D_REG || p1->to.reg != p->from.reg)
+ if(p1->to.type != TYPE_REG || p1->to.reg != p->from.reg)
continue;
switch(p1->as) {
case ASUB:
case AXOR:
case AOR:
/* irregular instructions */
- if(p1->from.type == D_CONST)
+ if(p1->from.type == TYPE_CONST || p1->from.type == TYPE_ADDR)
continue;
break;
}
continue;
case AMOVW:
case AMOVD:
- if(p1->from.type != D_REG)
+ if(p1->from.type != TYPE_REG)
continue;
continue;
case AANDCC:
void
excise(Flow *r)
{
- Prog *p, *l;
+ Prog *p;
p = r->prog;
if(debug['P'] && debug['v'])
print("%P ===delete===\n", p);
- l = p->link;
- *p = zprog;
- p->as = ANOP;
- p->link = l;
+ nopout(p);
ostats.ndelmov++;
}
static int
regzer(Addr *a)
{
- if(a->type == D_CONST)
- if(a->sym == nil && a->reg == NREG)
+ if(a->type == TYPE_CONST || a->type == TYPE_ADDR)
+ if(a->sym == nil && a->reg == 0)
if(a->offset == 0)
return 1;
- if(a->type == D_REG)
+ if(a->type == TYPE_REG)
if(a->reg == REGZERO)
return 1;
return 0;
int
regtyp(Adr *a)
{
- switch(a->type) {
- default:
- return 0;
- case D_REG:
- if(a->reg == REGZERO)
- return 0;
- case D_FREG:
- return 1;
- }
+ // TODO(rsc): Floating point register exclusions?
+ return a->type == TYPE_REG && REG_R0 <= a->reg && a->reg <= REG_F31 && a->reg != REGZERO;
}
/*
int
copyu(Prog *p, Addr *v, Addr *s)
{
- if(p->from3.type != D_NONE)
+ if(p->from3.type != TYPE_NONE)
// 9g never generates a from3
print("copyu: from3 (%D) not implemented\n", p->from3);
}
if(copyas(&p->to, v)) {
// Fix up implicit from
- if(p->from.type == D_NONE)
+ if(p->from.type == TYPE_NONE)
p->from = p->to;
if(copyau(&p->from, v))
return 4;
case AMOVHZU:
case AMOVWZU:
case AMOVDU:
- if(p->from.type == D_OREG) {
+ if(p->from.type == TYPE_MEM) {
if(copyas(&p->from, v))
// No s!=nil check; need to fail
// anyway in that case
}
if(copyas(&p->to, v))
return 3;
- } else if (p->to.type == D_OREG) {
+ } else if (p->to.type == TYPE_MEM) {
if(copyas(&p->to, v))
return 2;
if(s != nil) {
return 0;
}
if(copyas(&p->to, v)) {
- if(p->reg == NREG)
+ if(p->reg == 0)
// Fix up implicit reg (e.g., ADD
// R3,R4 -> ADD R3,R4,R4) so we can
// update reg and to separately.
return 3;
case ABL: /* funny */
- if(v->type == D_REG) {
- if(v->reg <= REGEXT && v->reg > exregoffset)
+ if(v->type == TYPE_REG) {
+ // TODO(rsc): REG_R0 and REG_F0 used to be
+ // (when register numbers started at 0) exregoffset and exfregoffset,
+ // which are unset entirely.
+ // It's strange that this handles R0 and F0 differently from the other
+ // registers. Possible failure to optimize?
+ if(REG_R0 < v->reg && v->reg <= REGEXT)
return 2;
if(v->reg == REGARG)
return 2;
- }
- if(v->type == D_FREG) {
- if(v->reg <= FREGEXT && v->reg > exfregoffset)
+ if(REG_F0 < v->reg && v->reg <= FREGEXT)
return 2;
}
- if(p->from.type == D_REG && v->type == D_REG && p->from.reg == v->reg)
+ if(p->from.type == TYPE_REG && v->type == TYPE_REG && p->from.reg == v->reg)
return 2;
if(s != nil) {
case ADUFFZERO:
// R0 is zero, used by DUFFZERO, cannot be substituted.
// R3 is ptr to memory, used and set, cannot be substituted.
- if(v->type == D_REG) {
+ if(v->type == TYPE_REG) {
if(v->reg == 0)
return 1;
if(v->reg == 3)
case ADUFFCOPY:
// R3, R4 are ptr to src, dst, used and set, cannot be substituted.
// R5 is scratch, set by DUFFCOPY, cannot be substituted.
- if(v->type == D_REG) {
+ if(v->type == TYPE_REG) {
if(v->reg == 3 || v->reg == 4)
return 2;
if(v->reg == 5)
return 0;
case ATEXT: /* funny */
- if(v->type == D_REG)
+ if(v->type == TYPE_REG)
if(v->reg == REGARG)
return 3;
return 0;
}
}
-int
-a2type(Prog *p)
-{
- ProgInfo info;
- proginfo(&info, p);
- if(info.flags & (SizeB|SizeW|SizeL|SizeQ))
- return D_REG;
- if(info.flags & (SizeF|SizeD))
- return D_FREG;
- return D_NONE;
-}
-
// copyas returns 1 if a and v address the same register.
//
// If a is the from operand, this means this operation reads the
{
if(copyas(a, v))
return 1;
- if(v->type == D_REG)
- if(a->type == D_OREG || (a->type == D_CONST && a->reg != NREG))
+ if(v->type == TYPE_REG)
+ if(a->type == TYPE_MEM || (a->type == TYPE_ADDR && a->reg != 0))
if(v->reg == a->reg)
return 1;
return 0;
static int
copyau1(Prog *p, Addr *v)
{
- if(regtyp(v))
- if(p->from.type == v->type || p->to.type == v->type)
- if(p->reg == v->reg) {
- // Whether p->reg is a GPR or an FPR is
- // implied by the instruction (both are
- // numbered from 0). But the type should
- // match v->type. Sanity check this.
- if(a2type(p) != v->type)
- print("botch a2type %P\n", p);
+ if(regtyp(v) && v->reg != 0)
+ if(p->reg == v->reg)
return 1;
- }
return 0;
}
return 0;
if(regtyp(v) && a->reg == v->reg)
return 1;
- if(v->type == D_AUTO || v->type == D_PARAM)
+ if(v->type == NAME_AUTO || v->type == NAME_PARAM)
if(v->offset == a->offset)
return 1;
return 0;
int
smallindir(Addr *a, Addr *reg)
{
- return reg->type == D_REG && a->type == D_OREG &&
+ return reg->type == TYPE_REG && a->type == TYPE_MEM &&
a->reg == reg->reg &&
0 <= a->offset && a->offset < 4096;
}
int
stackaddr(Addr *a)
{
- return a->type == D_REG && a->reg == REGSP;
+ return a->type == TYPE_REG && a->reg == REGSP;
}
fatal("proginfo: unknown instruction %P", p);
}
- if((info->flags & RegRead) && p->reg == NREG) {
+ if((info->flags & RegRead) && p->reg == 0) {
info->flags &= ~RegRead;
info->flags |= /*CanRegRead |*/ RightRead;
}
- if((p->from.type == D_OREG || p->from.type == D_CONST) && p->from.reg != NREG) {
+ if((p->from.type == TYPE_MEM || p->from.type == TYPE_ADDR) && p->from.reg != 0) {
info->regindex |= RtoB(p->from.reg);
if(info->flags & PostInc) {
info->regset |= RtoB(p->from.reg);
}
}
- if((p->to.type == D_OREG || p->to.type == D_CONST) && p->to.reg != NREG) {
+ if((p->to.type == TYPE_MEM || p->to.type == TYPE_ADDR) && p->to.reg != 0) {
info->regindex |= RtoB(p->to.reg);
if(info->flags & PostInc) {
info->regset |= RtoB(p->to.reg);
}
}
- if(p->from.type == D_CONST && p->from.sym != nil && (info->flags & LeftRead)) {
+ if(p->from.type == TYPE_ADDR && p->from.sym != nil && (info->flags & LeftRead)) {
info->flags &= ~LeftRead;
info->flags |= LeftAddr;
}
if(p->as == ADUFFZERO) {
- info->reguse |= (1<<D_R0) | RtoB(3);
- info->regset |= RtoB(3);
+ info->reguse |= (1<<0) | RtoB(REG_R3);
+ info->regset |= RtoB(REG_R3);
}
if(p->as == ADUFFCOPY) {
// TODO(austin) Revisit when duffcopy is implemented
- info->reguse |= RtoB(3) | RtoB(4) | RtoB(5);
- info->regset |= RtoB(3) | RtoB(4);
+ info->reguse |= RtoB(REG_R3) | RtoB(REG_R4) | RtoB(REG_R5);
+ info->regset |= RtoB(REG_R3) | RtoB(REG_R4);
}
}
}
// Exclude registers with fixed functions
- regbits = (1<<D_R0)|RtoB(REGSP)|RtoB(REGG)|RtoB(REGTLS);
+ regbits = (1<<0)|RtoB(REGSP)|RtoB(REGG)|RtoB(REGTLS);
// Also exclude floating point registers with fixed constants
- regbits |= FtoB(D_F0+27)|FtoB(D_F0+28)|FtoB(D_F0+29)|FtoB(D_F0+30)|FtoB(D_F0+31);
+ regbits |= RtoB(REG_F27)|RtoB(REG_F28)|RtoB(REG_F29)|RtoB(REG_F30)|RtoB(REG_F31);
externs = zbits;
params = zbits;
consts = zbits;
proginfo(&info, p);
// Avoid making variables for direct-called functions.
- if(p->as == ABL && p->to.name == D_EXTERN)
+ if(p->as == ABL && p->to.name == NAME_EXTERN)
continue;
// from vs to doesn't matter for registers
r->use1.b[z] |= bit.b[z];
// Compute used register for reg
- if(info.flags & RegRead) {
- if(p->from.type != D_FREG)
- r->use1.b[0] |= RtoB(p->reg);
- else
- r->use1.b[0] |= FtoB(D_F0+p->reg);
- }
+ if(info.flags & RegRead)
+ r->use1.b[0] |= RtoB(p->reg);
// Currently we never generate three register forms.
// If we do, this will need to change.
- if(p->from3.type != D_NONE)
+ if(p->from3.type != TYPE_NONE)
fatal("regopt not implemented for from3");
// Compute used register for to
}
for(r = firstr; r != R; r = (Reg*)r->f.link) {
p = r->f.prog;
- if(p->as == AVARDEF && isfat(p->to.node->type) && p->to.node->opt != nil) {
+ if(p->as == AVARDEF && isfat(((Node*)(p->to.node))->type) && ((Node*)(p->to.node))->opt != nil) {
active++;
walkvardef(p->to.node, r, active);
}
for(p=firstp; p!=P; p=p->link) {
while(p->link != P && p->link->as == ANOP)
p->link = p->link->link;
- if(p->to.type == D_BRANCH)
+ if(p->to.type == TYPE_BRANCH)
while(p->to.u.branch != P && p->to.u.branch->as == ANOP)
p->to.u.branch = p->to.u.branch->link;
}
// If there's a stack fixup coming (ADD $n,R1 after BL newproc or BL deferproc),
// delay the load until after the fixup.
p2 = p->link;
- if(p2 && p2->as == AADD && p2->to.reg == REGSP && p2->to.type == D_REG)
+ if(p2 && p2->as == AADD && p2->to.reg == REGSP && p2->to.type == TYPE_REG)
p = p2;
p1->link = p->link;
a->sym = linksym(v->node->sym);
a->offset = v->offset;
a->etype = v->etype;
- a->type = D_OREG;
- if(a->etype == TARRAY || a->sym == nil)
- a->type = D_CONST;
+ a->type = TYPE_MEM;
+ if(a->etype == TARRAY)
+ a->type = TYPE_ADDR;
+ else if(a->sym == nil)
+ a->type = TYPE_CONST;
if(v->addr)
fatal("addmove: shouldn't be doing this %A\n", a);
break;
}
- p1->from.type = D_REG;
+ p1->from.type = TYPE_REG;
p1->from.reg = rn;
- if(rn >= NREG) {
- p1->from.type = D_FREG;
- p1->from.reg = rn-NREG;
- }
if(!f) {
p1->from = *a;
*a = zprog.from;
- a->type = D_REG;
+ a->type = TYPE_REG;
a->reg = rn;
- if(rn >= NREG) {
- a->type = D_FREG;
- a->reg = rn-NREG;
- }
if(v->etype == TUINT8 || v->etype == TBOOL)
p1->as = AMOVBZ;
if(v->etype == TUINT16)
print("type %d %d %D\n", t, a->name, a);
goto none;
- case D_NONE:
+ case TYPE_NONE:
goto none;
- case D_BRANCH:
- case D_CONST:
- case D_FCONST:
- case D_SCONST:
- case D_SPR:
- case D_OREG:
+ case TYPE_BRANCH:
+ case TYPE_CONST:
+ case TYPE_FCONST:
+ case TYPE_SCONST:
+ case TYPE_MEM:
+ case TYPE_ADDR:
break;
- case D_REG:
- if(a->reg != NREG) {
+ case TYPE_REG:
+ if(a->reg != 0) {
bit = zbits;
bit.b[0] = RtoB(a->reg);
return bit;
}
break;
-
- case D_FREG:
- if(a->reg != NREG) {
- bit = zbits;
- bit.b[0] = FtoB(D_F0+a->reg);
- return bit;
- }
- break;
}
switch(a->name) {
default:
goto none;
- case D_EXTERN:
- case D_STATIC:
- case D_AUTO:
- case D_PARAM:
+ case NAME_EXTERN:
+ case NAME_STATIC:
+ case NAME_AUTO:
+ case NAME_PARAM:
n = a->name;
break;
}
node->opt = v;
bit = blsh(i);
- if(n == D_EXTERN || n == D_STATIC)
+ if(n == NAME_EXTERN || n == NAME_STATIC)
for(z=0; z<BITS; z++)
externs.b[z] |= bit.b[z];
- if(n == D_PARAM)
+ if(n == NAME_PARAM)
for(z=0; z<BITS; z++)
params.b[z] |= bit.b[z];
i = BtoF(~b);
if(i && r->cost > 0) {
r->regno = i;
- return FtoB(i);
+ return RtoB(i);
}
break;
}
{
a->sym = nil;
a->node = nil;
- a->name = D_NONE;
- a->type = D_REG;
+ a->name = NAME_NONE;
+ a->type = TYPE_REG;
a->reg = rn;
- if(rn >= NREG) {
- a->type = D_FREG;
- a->reg = rn-NREG;
- }
ostats.ncvtreg++;
}
uint64
RtoB(int r)
{
- if(r > D_R0 && r <= D_R0+31)
- return 1ULL << (r - D_R0);
+ if(r > REG_R0 && r <= REG_R31)
+ return 1ULL << (r - REG_R0);
+ if(r >= REG_F0 && r <= REG_F31)
+ return 1ULL << (32 + r - REG_F0);
return 0;
}
b &= 0xffffffffull;
if(b == 0)
return 0;
- return bitno(b) + D_R0;
-}
-
-uint64
-FtoB(int r)
-{
- if(r >= D_F0 && r <= D_F0+31)
- return 1ULL << (32 + r - D_F0);
- return 0;
+ return bitno(b) + REG_R0;
}
int
b >>= 32;
if(b == 0)
return 0;
- return bitno(b) + D_F0;
+ return bitno(b) + REG_F0;
}
void
#include "../ld/textflag.h"
+// avoid conflict with ucontext.h. sigh.
+#undef REG_R0
+#undef REG_R1
+#undef REG_R2
+#undef REG_R3
+#undef REG_R4
+#undef REG_R5
+#undef REG_R6
+#undef REG_R7
+#undef REG_R8
+#undef REG_R9
+#undef REG_R10
+#undef REG_R11
+#undef REG_R12
+#undef REG_R13
+#undef REG_R14
+#undef REG_R15
+#undef REG_R16
+#undef REG_R17
+#undef REG_R18
+#undef REG_R19
+#undef REG_R20
+#undef REG_R21
+#undef REG_R22
+#undef REG_R23
+#undef REG_R24
+#undef REG_R25
+#undef REG_R26
+#undef REG_R27
+#undef REG_R28
+#undef REG_R29
+#undef REG_R30
+#undef REG_R31
+#define REG_R0 GO_REG_R0
+#define REG_R1 GO_REG_R1
+#define REG_R2 GO_REG_R2
+#define REG_R3 GO_REG_R3
+#define REG_R4 GO_REG_R4
+#define REG_R5 GO_REG_R5
+#define REG_R6 GO_REG_R6
+#define REG_R7 GO_REG_R7
+#define REG_R8 GO_REG_R8
+#define REG_R9 GO_REG_R9
+#define REG_R10 GO_REG_R10
+#define REG_R11 GO_REG_R11
+#define REG_R12 GO_REG_R12
+#define REG_R13 GO_REG_R13
+#define REG_R14 GO_REG_R14
+#define REG_R15 GO_REG_R15
+#define REG_R16 GO_REG_R16
+#define REG_R17 GO_REG_R17
+#define REG_R18 GO_REG_R18
+#define REG_R19 GO_REG_R19
+#define REG_R20 GO_REG_R20
+#define REG_R21 GO_REG_R21
+#define REG_R22 GO_REG_R22
+#define REG_R23 GO_REG_R23
+#define REG_R24 GO_REG_R24
+#define REG_R25 GO_REG_R25
+#define REG_R26 GO_REG_R26
+#define REG_R27 GO_REG_R27
+#define REG_R28 GO_REG_R28
+#define REG_R29 GO_REG_R29
+#define REG_R30 GO_REG_R30
+#define REG_R31 GO_REG_R31
+
enum
{
- REGZERO = 0, /* set to zero */
- REGSP = 1,
- REGSB = 2,
- REGRET = 3,
+ REG_R0 = 32,
+ REG_R1,
+ REG_R2,
+ REG_R3,
+ REG_R4,
+ REG_R5,
+ REG_R6,
+ REG_R7,
+ REG_R8,
+ REG_R9,
+ REG_R10,
+ REG_R11,
+ REG_R12,
+ REG_R13,
+ REG_R14,
+ REG_R15,
+ REG_R16,
+ REG_R17,
+ REG_R18,
+ REG_R19,
+ REG_R20,
+ REG_R21,
+ REG_R22,
+ REG_R23,
+ REG_R24,
+ REG_R25,
+ REG_R26,
+ REG_R27,
+ REG_R28,
+ REG_R29,
+ REG_R30,
+ REG_R31,
+
+ REG_F0 = 64,
+ REG_F1,
+ REG_F2,
+ REG_F3,
+ REG_F4,
+ REG_F5,
+ REG_F6,
+ REG_F7,
+ REG_F8,
+ REG_F9,
+ REG_F10,
+ REG_F11,
+ REG_F12,
+ REG_F13,
+ REG_F14,
+ REG_F15,
+ REG_F16,
+ REG_F17,
+ REG_F18,
+ REG_F19,
+ REG_F20,
+ REG_F21,
+ REG_F22,
+ REG_F23,
+ REG_F24,
+ REG_F25,
+ REG_F26,
+ REG_F27,
+ REG_F28,
+ REG_F29,
+ REG_F30,
+ REG_F31,
+
+ REG_SPECIAL = 96,
+
+ REG_C0 = 96,
+ REG_C1,
+ REG_C2,
+ REG_C3,
+ REG_C4,
+ REG_C5,
+ REG_C6,
+ REG_C7,
+
+ REG_MSR = 104,
+ REG_FPSCR,
+ REG_CR,
+
+ REG_SPR0 = 1024, // first of 1024 registers
+ REG_DCR0 = 2048, // first of 1024 registers
+
+ REG_XER = REG_SPR0 + 1,
+ REG_LR = REG_SPR0 + 8,
+ REG_CTR = REG_SPR0 + 9,
+
+ REGZERO = REG_R0, /* set to zero */
+ REGSP = REG_R1,
+ REGSB = REG_R2,
+ REGRET = REG_R3,
REGARG = -1, /* -1 disables passing the first argument in register */
- REGRT1 = 3, /* reserved for runtime, duffzero and duffcopy */
- REGRT2 = 4, /* reserved for runtime, duffcopy */
- REGMIN = 7, /* register variables allocated from here to REGMAX */
- REGENV = 11, /* environment for closures */
- REGTLS = 13, /* C ABI TLS base pointer */
- REGMAX = 27,
- REGEXT = 30, /* external registers allocated from here down */
- REGG = 30, /* G */
- REGTMP = 31, /* used by the linker */
+ REGRT1 = REG_R3, /* reserved for runtime, duffzero and duffcopy */
+ REGRT2 = REG_R4, /* reserved for runtime, duffcopy */
+ REGMIN = REG_R7, /* register variables allocated from here to REGMAX */
+ REGENV = REG_R11, /* environment for closures */
+ REGTLS = REG_R13, /* C ABI TLS base pointer */
+ REGMAX = REG_R27,
+ REGEXT = REG_R30, /* external registers allocated from here down */
+ REGG = REG_R30, /* G */
+ REGTMP = REG_R31, /* used by the linker */
- FREGRET = 0,
- FREGMIN = 17, /* first register variable */
- FREGMAX = 26, /* last register variable for 9g only */
- FREGEXT = 26, /* first external register */
- FREGCVI = 27, /* floating conversion constant */
- FREGZERO = 28, /* both float and double */
- FREGHALF = 29, /* double */
- FREGONE = 30, /* double */
- FREGTWO = 31 /* double */
+ FREGRET = REG_F0,
+ FREGMIN = REG_F17, /* first register variable */
+ FREGMAX = REG_F26, /* last register variable for 9g only */
+ FREGEXT = REG_F26, /* first external register */
+ FREGCVI = REG_F27, /* floating conversion constant */
+ FREGZERO = REG_F28, /* both float and double */
+ FREGHALF = REG_F29, /* double */
+ FREGONE = REG_F30, /* double */
+ FREGTWO = REG_F31 /* double */
/*
* GENERAL:
*
C_ANY,
C_GOK,
C_ADDR,
+ C_TEXTSIZE,
C_NCLASS, /* must be the last */
};
enum
{
- AXXX,
- AADD,
+ AADD = A_ARCHSPECIFIC,
AADDCC,
AADDV,
AADDVCC,
ABEQ,
ABGE,
ABGT,
- ABL,
ABLE,
ABLT,
ABNE,
- ABR,
ABVC,
ABVS,
ACMP,
ATW,
ASYSCALL,
- ADATA,
- AGLOBL,
- AGOK,
- AHISTORY,
- ANAME,
- ANOP,
- ARETURN,
- ATEXT,
AWORD,
- AEND,
- ADYNT,
- AINIT,
- ASIGNAME,
ARFCI,
/* more 64-bit operations */
AHRFID,
- AUNDEF,
- AUSEFIELD,
- ATYPE,
- AFUNCDATA,
- APCDATA,
- ACHECKNIL,
- AVARDEF,
- AVARKILL,
- ADUFFCOPY,
- ADUFFZERO,
-
- ALAST
-};
-
-/* type/name */
-enum
-{
- D_GOK = 0,
- D_NONE,
-
-/* name */
- D_EXTERN,
- D_STATIC,
- D_AUTO,
- D_PARAM,
-
-/* type */
- D_BRANCH,
- D_OREG,
- D_CONST,
- D_FCONST,
- D_SCONST,
- D_REG,
- D_FPSCR,
- D_MSR,
- D_FREG,
- D_CREG,
- D_SPR,
- D_OPT, /* branch/trap option */
- D_FILE,
- D_FILE1,
- D_DCR, /* device control register */
- D_DCONST,
- D_ADDR, // not used, use D_CONST with non-empty sym.
-
- D_LAST,
-
-/* reg names for 9g OREGISTER */
- D_R0 = 0, // type is D_REG
- D_F0 = D_R0+NREG, // type is D_FREG
-
-/* reg names in offset field iff type is D_SPR */
- D_XER = 1,
- D_LR = 8,
- D_CTR = 9
- /* and many supervisor level registers */
+ ALAST,
+
+ // aliases
+ ABR = AJMP,
+ ABL = ACALL,
+ ARETURN = ARET,
};
/*
return []string{"-m32"}
case "arm":
return []string{"-marm"} // not thumb
+ case "s390":
+ return []string{"-m31"}
+ case "s390x":
+ return []string{"-m64"}
}
return nil
}
"arm": 4,
"ppc64": 8,
"ppc64le": 8,
+ "s390": 4,
+ "s390x": 8,
}
var intSizeMap = map[string]int64{
"arm": 4,
"ppc64": 8,
"ppc64le": 8,
+ "s390": 4,
+ "s390x": 4,
}
var cPrefix string
"anames9.c",
}},
{"cmd/gc", []string{
- "-cplx.c",
- "-pgen.c",
- "-plive.c",
- "-popt.c",
- "-y1.tab.c", // makefile dreg
"opnames.h",
}},
{"cmd/5g", []string{
- "../gc/cplx.c",
- "../gc/pgen.c",
- "../gc/plive.c",
- "../gc/popt.c",
- "../gc/popt.h",
"$GOROOT/pkg/obj/${GOHOSTOS}_$GOHOSTARCH/libgc.a",
}},
{"cmd/6g", []string{
- "../gc/cplx.c",
- "../gc/pgen.c",
- "../gc/plive.c",
- "../gc/popt.c",
- "../gc/popt.h",
"$GOROOT/pkg/obj/${GOHOSTOS}_$GOHOSTARCH/libgc.a",
}},
{"cmd/8g", []string{
- "../gc/cplx.c",
- "../gc/pgen.c",
- "../gc/plive.c",
- "../gc/popt.c",
- "../gc/popt.h",
"$GOROOT/pkg/obj/${GOHOSTOS}_$GOHOSTARCH/libgc.a",
}},
{"cmd/9g", []string{
- "../gc/cplx.c",
- "../gc/pgen.c",
- "../gc/plive.c",
- "../gc/popt.c",
- "../gc/popt.h",
"$GOROOT/pkg/obj/${GOHOSTOS}_$GOHOSTARCH/libgc.a",
}},
{"cmd/5l", []string{
"$GOROOT/pkg/obj/${GOHOSTOS}_$GOHOSTARCH/lib9.a",
}},
{"runtime", []string{
- "zaexperiment.h",
"zversion.go",
}},
}
{"anames9.c", mkanames},
{"zdefaultcc.go", mkzdefaultcc},
{"zversion.go", mkzversion},
- {"zaexperiment.h", mkzexperiment},
// not generated anymore, but delete the file if we see it
{"enam.c", nil},
)
}
- // gc/lex.c records the GOEXPERIMENT setting used during the build.
- if name == "lex.c" {
+ // liblink/go.c records the GOEXPERIMENT setting used during the build.
+ if name == "go.c" {
compile = append(compile,
"-D", fmt.Sprintf("GOEXPERIMENT=%q", os.Getenv("GOEXPERIMENT")))
}
import (
"bytes"
"fmt"
- "strconv"
"strings"
)
// mkanames reads [5689].out.h and writes anames[5689].c
// The format is much the same as the Go opcodes above.
-// It also writes out cnames array for C_* constants and the dnames
-// array for D_* constants.
+// It also writes out cnames array for C_* constants.
func mkanames(dir, file string) {
ch := file[len(file)-3]
targ := pathf("%s/../cmd/%cl/%c.out.h", dir, ch, ch)
- in := readfile(targ)
+ in := readfile(pathf("%s/../../include/link.h", dir)) + readfile(targ)
lines := splitlines(in)
// Include link.h so that the extern declaration there is
fmt.Fprintf(&out, "char* anames%c[] = {\n", ch)
for _, line := range lines {
- if strings.HasPrefix(line, "\tA") {
+ // Use all A names found in the headers,
+ // except don't use A_ARCHSPECIFIC (left to arch to define),
+ // and don't use any aliases (= A...),
+ // except do use the arch-defined alias for A_ARCHSPECIFIC.
+ if strings.Contains(line, ";") {
+ continue
+ }
+ if strings.HasPrefix(line, "\tA") && !strings.Contains(line, "\tA_") && (!strings.Contains(line, "= A") || strings.Contains(line, "= A_ARCHSPECIFIC")) {
if i := strings.Index(line, ","); i >= 0 {
line = line[:i]
}
+ if i := strings.Index(line, "="); i >= 0 {
+ line = line[:i]
+ }
if i := strings.Index(line, "\n"); i >= 0 {
line = line[:i]
}
out.Write(out2.Bytes())
}
- var dnames [128][]string
- j = 0
- unknown := false
- n := -1
- for _, line := range lines {
- if strings.HasPrefix(line, "\tD_") {
- if i := strings.Index(line, ","); i >= 0 {
- line = line[:i]
- }
-
- // Parse explicit value, if any
- if i := strings.Index(line, "="); i >= 0 {
- value := strings.TrimSpace(line[i+1:])
- line = strings.TrimSpace(line[:i])
- var err error
- n, err = strconv.Atoi(value)
- if err != nil {
- // We can't do anything about
- // non-numeric values or anything that
- // follows.
- unknown = true
- continue
- }
- unknown = false
- } else {
- n++
- }
-
- if unknown || n < 0 || n >= len(dnames) {
- continue
- }
-
- line = strings.TrimSpace(line)
- line = line[len("D_"):]
-
- if strings.Contains(line, "LAST") {
- continue
- }
- dnames[n] = append(dnames[n], line)
- j++
- }
- }
-
- if j > 0 {
- fmt.Fprintf(&out, "char* dnames%c[D_LAST] = {\n", ch)
- for _, d := range dnames {
- if len(d) == 0 {
- continue
- }
- fmt.Fprintf(&out, "\t[D_%s] = \"", d[0])
- for k, name := range d {
- if k > 0 {
- fmt.Fprintf(&out, "/")
- }
- fmt.Fprintf(&out, "%s", name)
- }
- fmt.Fprintf(&out, "\",\n")
- }
- fmt.Fprintf(&out, "};\n")
- }
-
writefile(out.String(), file, 0)
}
"\n"+
"const defaultGoroot = `%s`\n"+
"const theVersion = `%s`\n"+
- "\n"+
- "var buildVersion = theVersion\n", goroot_final, goversion)
-
- writefile(out, file, 0)
-}
-
-// mkzexperiment writes zaexperiment.h (sic):
-//
-// #define GOEXPERIMENT "experiment string"
-//
-func mkzexperiment(dir, file string) {
- out := fmt.Sprintf(
- "// auto generated by go tool dist\n"+
- "\n"+
- "#define GOEXPERIMENT \"%s\"\n", os.Getenv("GOEXPERIMENT"))
+ "const goexperiment = `%s`\n"+
+ "var buildVersion = theVersion\n", goroot_final, goversion, os.Getenv("GOEXPERIMENT"))
writefile(out, file, 0)
}
// try to run "vmov.f64 d0, d0" instruction
TEXT ·useVFPv1(SB),NOSPLIT,$0
- WORD $0xeeb00b40 // vomv.f64 d0, d0
+ WORD $0xeeb00b40 // vmov.f64 d0, d0
RET
// try to run VFPv3-only "vmov.f64 d0, #112" instruction
TEXT ·useVFPv3(SB),NOSPLIT,$0
- WORD $0xeeb70b00 // vmov.f64 d0, #112
+ WORD $0xeeb70b00 // vmov.f64 d0, #112
RET
rnd(vlong o, vlong r)
{
if(r < 1 || r > 8 || (r&(r-1)) != 0)
- fatal("rnd");
+ fatal("rnd %lld", r);
return (o+r-1)&~(r-1);
}
fatal("offmod: not TFIELD: %lT", f);
f->width = o;
o += widthptr;
- if(o >= MAXWIDTH) {
+ if(o >= arch.MAXWIDTH) {
yyerror("interface too large");
o = widthptr;
}
if(w == 0)
lastzero = o;
o += w;
- if(o >= MAXWIDTH) {
+ if(o >= arch.MAXWIDTH) {
yyerror("type %lT too large", errtype);
o = 8; // small but nonzero
}
dowidth(t->type);
if(t->type->width != 0) {
- cap = (MAXWIDTH-1) / t->type->width;
+ cap = (arch.MAXWIDTH-1) / t->type->width;
if(t->bound > cap)
yyerror("type %lT larger than address space", t);
}
simtype[TFUNC] = tptr;
simtype[TUNSAFEPTR] = tptr;
- /* pick up the backend typedefs */
- for(i=0; typedefs[i].name; i++) {
- s = lookup(typedefs[i].name);
- s1 = pkglookup(typedefs[i].name, builtinpkg);
+ /* pick up the backend arch.typedefs */
+ for(i=0; arch.typedefs[i].name; i++) {
+ s = lookup(arch.typedefs[i].name);
+ s1 = pkglookup(arch.typedefs[i].name, builtinpkg);
- etype = typedefs[i].etype;
+ etype = arch.typedefs[i].etype;
if(etype < 0 || etype >= nelem(types))
fatal("typeinit: %s bad etype", s->name);
- sameas = typedefs[i].sameas;
+ sameas = arch.typedefs[i].sameas;
if(sameas < 0 || sameas >= nelem(types))
fatal("typeinit: %s bad sameas", s->name);
simtype[etype] = sameas;
DEFAULTCAPACITY = 16,
};
-struct Array
-{
- int32 length; // number of elements
- int32 size; // element size
- int32 capacity; // size of data in elements
- char *data; // element storage
-};
-
Array*
-arraynew(int32 capacity, int32 size)
+arraynew(int capacity, int32 size)
{
Array *result;
free(array);
}
-int32
+int
arraylength(Array *array)
{
return array->length;
}
void*
-arrayget(Array *array, int32 index)
+arrayget(Array *array, int index)
{
if(array == nil)
fatal("arrayget: array is nil\n");
}
void
-arrayset(Array *array, int32 index, void *element)
+arrayset(Array *array, int index, void *element)
{
if(array == nil)
fatal("arrayset: array is nil\n");
}
static void
-ensurecapacity(Array *array, int32 capacity)
+ensurecapacity(Array *array, int capacity)
{
int32 newcapacity;
char *newdata;
"func @\"\".printsp ()\n"
"func @\"\".printlock ()\n"
"func @\"\".printunlock ()\n"
- "func @\"\".concatstring2 (? string, ? string) (? string)\n"
- "func @\"\".concatstring3 (? string, ? string, ? string) (? string)\n"
- "func @\"\".concatstring4 (? string, ? string, ? string, ? string) (? string)\n"
- "func @\"\".concatstring5 (? string, ? string, ? string, ? string, ? string) (? string)\n"
- "func @\"\".concatstrings (? []string) (? string)\n"
+ "func @\"\".concatstring2 (? *[32]byte, ? string, ? string) (? string)\n"
+ "func @\"\".concatstring3 (? *[32]byte, ? string, ? string, ? string) (? string)\n"
+ "func @\"\".concatstring4 (? *[32]byte, ? string, ? string, ? string, ? string) (? string)\n"
+ "func @\"\".concatstring5 (? *[32]byte, ? string, ? string, ? string, ? string, ? string) (? string)\n"
+ "func @\"\".concatstrings (? *[32]byte, ? []string) (? string)\n"
"func @\"\".cmpstring (? string, ? string) (? int)\n"
"func @\"\".eqstring (? string, ? string) (? bool)\n"
- "func @\"\".intstring (? int64) (? string)\n"
- "func @\"\".slicebytetostring (? []byte) (? string)\n"
+ "func @\"\".intstring (? *[4]byte, ? int64) (? string)\n"
+ "func @\"\".slicebytetostring (? *[32]byte, ? []byte) (? string)\n"
"func @\"\".slicebytetostringtmp (? []byte) (? string)\n"
"func @\"\".slicerunetostring (? []rune) (? string)\n"
"func @\"\".stringtoslicebyte (? string) (? []byte)\n"
+ "func @\"\".stringtoslicebytetmp (? string) (? []byte)\n"
"func @\"\".stringtoslicerune (? string) (? []rune)\n"
"func @\"\".stringiter (? string, ? int) (? int)\n"
"func @\"\".stringiter2 (? string, ? int) (@\"\".retk·1 int, @\"\".retv·2 rune)\n"
#include "go.h"
enum {
- WORDSIZE = sizeof(uint32),
+ WORDSIZE = 4,
WORDBITS = 32,
WORDMASK = WORDBITS - 1,
WORDSHIFT = 5,
for(l=func->cvars; l; l=l->next) {
v = l->n;
v->closure->closure = v->outer;
- v->heapaddr = nod(OADDR, oldname(v->sym), N);
+ v->outerexpr = oldname(v->sym);
}
return func;
void
typecheckclosure(Node *func, int top)
{
- Node *oldfn;
+ Node *oldfn, *n;
NodeList *l;
- Node *v;
+ int olddd;
+
+ for(l=func->cvars; l; l=l->next) {
+ n = l->n->closure;
+ if(!n->captured) {
+ n->captured = 1;
+ if(n->decldepth == 0)
+ fatal("typecheckclosure: var %hN does not have decldepth assigned", n);
+ // Ignore assignments to the variable in straightline code
+ // preceding the first capturing by a closure.
+ if(n->decldepth == decldepth)
+ n->assigned = 0;
+ }
+ }
+
+ for(l=func->dcl; l; l=l->next)
+ if(l->n->op == ONAME && (l->n->class == PPARAM || l->n->class == PPARAMOUT))
+ l->n->decldepth = 1;
oldfn = curfn;
typecheck(&func->ntype, Etype);
func->type = func->ntype->type;
-
+
// Type check the body now, but only if we're inside a function.
// At top level (in a variable initialization: curfn==nil) we're not
// ready to type check code yet; we'll check it later, because the
// underlying closure function we create is added to xtop.
if(curfn && func->type != T) {
curfn = func;
+ olddd = decldepth;
+ decldepth = 1;
typechecklist(func->nbody, Etop);
+ decldepth = olddd;
curfn = oldfn;
}
- // type check the & of closed variables outside the closure,
- // so that the outer frame also grabs them and knows they
- // escape.
- func->enter = nil;
- for(l=func->cvars; l; l=l->next) {
- v = l->n;
- if(v->type == T) {
- // if v->type is nil, it means v looked like it was
- // going to be used in the closure but wasn't.
- // this happens because when parsing a, b, c := f()
- // the a, b, c gets parsed as references to older
- // a, b, c before the parser figures out this is a
- // declaration.
- v->op = 0;
- continue;
- }
- // For a closure that is called in place, but not
- // inside a go statement, avoid moving variables to the heap.
- if ((top & (Ecall|Eproc)) == Ecall)
- v->heapaddr->etype = 1;
- typecheck(&v->heapaddr, Erv);
- func->enter = list(func->enter, v->heapaddr);
- v->heapaddr = N;
- }
+ // Remember closure context for capturevars.
+ func->etype = (top & (Ecall|Eproc)) == Ecall;
// Create top-level function
xtop = list(xtop, makeclosure(func));
static Node*
makeclosure(Node *func)
{
- Node *xtype, *v, *addr, *xfunc, *cv;
- NodeList *l, *body;
+ Node *xtype, *xfunc;
static int closgen;
- char *p;
- vlong offset;
/*
* wrap body in external function
xfunc->nname->funcdepth = func->funcdepth;
xfunc->funcdepth = func->funcdepth;
xfunc->endlineno = func->endlineno;
+
+ xfunc->nbody = func->nbody;
+ xfunc->dcl = concat(func->dcl, xfunc->dcl);
+ if(xfunc->nbody == nil)
+ fatal("empty body - won't generate any code");
+ typecheck(&xfunc, Etop);
+
+ xfunc->closure = func;
+ func->closure = xfunc;
- // declare variables holding addresses taken from closure
- // and initialize in entry prologue.
+ func->nbody = nil;
+ func->list = nil;
+ func->rlist = nil;
+
+ return xfunc;
+}
+
+// capturevars is called in a separate phase after all typechecking is done.
+// It decides whether each variable captured by a closure should be captured
+// by value or by reference.
+// We use value capturing for values <= 128 bytes that are never reassigned
+// after declaration.
+void
+capturevars(Node *xfunc)
+{
+ Node *func, *v, *addr, *cv, *outer;
+ NodeList *l, *body;
+ char *p;
+ vlong offset;
+ int nvar, lno;
+
+ lno = lineno;
+ lineno = xfunc->lineno;
+
+ nvar = 0;
body = nil;
offset = widthptr;
- xfunc->needctxt = func->cvars != nil;
+ func = xfunc->closure;
+ func->enter = nil;
for(l=func->cvars; l; l=l->next) {
v = l->n;
- if(v->op == 0)
+ if(v->type == T) {
+ // if v->type is nil, it means v looked like it was
+ // going to be used in the closure but wasn't.
+ // this happens because when parsing a, b, c := f()
+ // the a, b, c gets parsed as references to older
+ // a, b, c before the parser figures out this is a
+ // declaration.
+ v->op = OXXX;
continue;
+ }
+ nvar++;
+
+ // type check the & of closed variables outside the closure,
+ // so that the outer frame also grabs them and knows they escape.
+ dowidth(v->type);
+ outer = v->outerexpr;
+ v->outerexpr = N;
+ // out parameters will be assigned to implicitly upon return.
+ if(outer->class != PPARAMOUT && !v->closure->addrtaken && !v->closure->assigned && v->type->width <= 128)
+ v->byval = 1;
+ else {
+ outer = nod(OADDR, outer, N);
+ // For a closure that is called in place, but not
+ // inside a go statement, avoid moving variables to the heap.
+ outer->etype = func->etype;
+ }
+ if(debug['m'] > 1)
+ warnl(v->lineno, "%S capturing by %s: %S (addr=%d assign=%d width=%d)",
+ (v->curfn && v->curfn->nname) ? v->curfn->nname->sym : S, v->byval ? "value" : "ref",
+ v->sym, v->closure->addrtaken, v->closure->assigned, (int32)v->type->width);
+ typecheck(&outer, Erv);
+ func->enter = list(func->enter, outer);
+
+ // declare variables holding addresses taken from closure
+ // and initialize in entry prologue.
addr = nod(ONAME, N, N);
p = smprint("&%s", v->sym->name);
addr->sym = lookup(p);
xfunc->dcl = list(xfunc->dcl, addr);
v->heapaddr = addr;
cv = nod(OCLOSUREVAR, N, N);
- cv->type = ptrto(v->type);
- cv->xoffset = offset;
- body = list(body, nod(OAS, addr, cv));
- offset += widthptr;
+ if(v->byval) {
+ cv->type = v->type;
+ offset = rnd(offset, v->type->align);
+ cv->xoffset = offset;
+ offset += v->type->width;
+ body = list(body, nod(OAS, addr, nod(OADDR, cv, N)));
+ } else {
+ v->closure->addrtaken = 1;
+ cv->type = ptrto(v->type);
+ offset = rnd(offset, widthptr);
+ cv->xoffset = offset;
+ offset += widthptr;
+ body = list(body, nod(OAS, addr, cv));
+ }
}
typechecklist(body, Etop);
walkstmtlist(body);
xfunc->enter = body;
+ xfunc->needctxt = nvar > 0;
+ func->etype = 0;
- xfunc->nbody = func->nbody;
- xfunc->dcl = concat(func->dcl, xfunc->dcl);
- if(xfunc->nbody == nil)
- fatal("empty body - won't generate any code");
- typecheck(&xfunc, Etop);
-
- xfunc->closure = func;
- func->closure = xfunc;
-
- func->nbody = nil;
- func->list = nil;
- func->rlist = nil;
-
- return xfunc;
+ lineno = lno;
}
Node*
walkclosure(Node *func, NodeList **init)
{
- Node *clos, *typ;
+ Node *clos, *typ, *typ1, *v;
NodeList *l;
- char buf[20];
- int narg;
// If no closure vars, don't bother wrapping.
if(func->cvars == nil)
// the struct is unnamed so that closures in multiple packages with the
// same struct type can share the descriptor.
- narg = 0;
typ = nod(OTSTRUCT, N, N);
typ->list = list1(nod(ODCLFIELD, newname(lookup("F")), typenod(types[TUINTPTR])));
for(l=func->cvars; l; l=l->next) {
- if(l->n->op == 0)
+ v = l->n;
+ if(v->op == OXXX)
continue;
- snprint(buf, sizeof buf, "A%d", narg++);
- typ->list = list(typ->list, nod(ODCLFIELD, newname(lookup(buf)), l->n->heapaddr->ntype));
+ typ1 = typenod(v->type);
+ if(!v->byval)
+ typ1 = nod(OIND, typ1, N);
+ typ->list = list(typ->list, nod(ODCLFIELD, newname(v->sym), typ1));
}
clos = nod(OCOMPLIT, N, nod(OIND, typ, N));
spkg = basetype->sym->pkg;
if(spkg == nil) {
if(gopkg == nil)
- gopkg = mkpkg(strlit("go"));
+ gopkg = mkpkg(newstrlit("go"));
spkg = gopkg;
}
sym = pkglookup(p, spkg);
#include <u.h>
#include <libc.h>
-#include "gg.h"
+#include "go.h"
static void subnode(Node *nr, Node *ni, Node *nc);
static void minus(Node *nl, Node *res);
#define CASE(a,b) (((a)<<16)|((b)<<0))
+/*c2go
+static int
+CASE(int a, int b)
+{
+ return a<<16 | b;
+}
+*/
+
static int
overlap(Node *f, Node *t)
{
subnode(&n1, &n2, f);
subnode(&n3, &n4, t);
- cgen(&n1, &n3);
- cgen(&n2, &n4);
+ arch.cgen(&n1, &n3);
+ arch.cgen(&n2, &n4);
break;
}
}
if(res->addable) {
subnode(&n1, &n2, res);
tempname(&tmp, n1.type);
- cgen(n->left, &tmp);
- cgen(n->right, &n2);
- cgen(&tmp, &n1);
+ arch.cgen(n->left, &tmp);
+ arch.cgen(n->right, &n2);
+ arch.cgen(&tmp, &n1);
return;
}
break;
}
subnode(&n1, &n2, nl);
if(n->op == OREAL) {
- cgen(&n1, res);
+ arch.cgen(&n1, res);
return;
}
- cgen(&n2, res);
+ arch.cgen(&n2, res);
return;
}
}
if(!res->addable) {
- igen(res, &n1, N);
- cgen(n, &n1);
- regfree(&n1);
+ arch.igen(res, &n1, N);
+ arch.cgen(n, &n1);
+ arch.regfree(&n1);
return;
}
if(n->addable) {
case OCALLFUNC:
case OCALLMETH:
case OCALLINTER:
- igen(n, &n1, res);
+ arch.igen(n, &n1, res);
complexmove(&n1, res);
- regfree(&n1);
+ arch.regfree(&n1);
return;
case OCONV:
if(nr != N) {
if(nl->ullman > nr->ullman && !nl->addable) {
tempname(&tnl, nl->type);
- cgen(nl, &tnl);
+ arch.cgen(nl, &tnl);
nl = &tnl;
}
if(!nr->addable) {
tempname(&tnr, nr->type);
- cgen(nr, &tnr);
+ arch.cgen(nr, &tnr);
nr = &tnr;
}
}
if(!nl->addable) {
tempname(&tnl, nl->type);
- cgen(nl, &tnl);
+ arch.cgen(nl, &tnl);
nl = &tnl;
}
if(nr != N) {
if(nl->ullman > nr->ullman && !nl->addable) {
tempname(&tnl, nl->type);
- cgen(nl, &tnl);
+ arch.cgen(nl, &tnl);
nl = &tnl;
}
if(!nr->addable) {
tempname(&tnr, nr->type);
- cgen(nr, &tnr);
+ arch.cgen(nr, &tnr);
nr = &tnr;
}
}
if(!nl->addable) {
tempname(&tnl, nl->type);
- cgen(nl, &tnl);
+ arch.cgen(nl, &tnl);
nl = &tnl;
}
na.right = &nc;
na.type = types[TBOOL];
- memset(&nb, 0, sizeof(na));
+ memset(&nb, 0, sizeof(nb));
nb.op = OEQ;
nb.left = &n1;
nb.right = &n3;
nb.type = types[TBOOL];
- memset(&nc, 0, sizeof(na));
+ memset(&nc, 0, sizeof(nc));
nc.op = OEQ;
nc.left = &n2;
nc.right = &n4;
if(op == ONE)
true = !true;
- bgen(&na, true, likely, to);
+ arch.bgen(&na, true, likely, to);
}
void
ra.op = OMINUS;
ra.left = nl;
ra.type = nl->type;
- cgen(&ra, res);
+ arch.cgen(&ra, res);
}
// build and execute tree
ra.left = &n1;
ra.right = &n3;
ra.type = n1.type;
- cgen(&ra, &n5);
+ arch.cgen(&ra, &n5);
memset(&ra, 0, sizeof(ra));
ra.op = op;
ra.left = &n2;
ra.right = &n4;
ra.type = n2.type;
- cgen(&ra, &n6);
+ arch.cgen(&ra, &n6);
}
// build and execute tree
tempname(&tmp, n5.type);
// real part -> tmp
- memset(&rm1, 0, sizeof(ra));
+ memset(&rm1, 0, sizeof(rm1));
rm1.op = OMUL;
rm1.left = &n1;
rm1.right = &n3;
rm1.type = n1.type;
- memset(&rm2, 0, sizeof(ra));
+ memset(&rm2, 0, sizeof(rm2));
rm2.op = OMUL;
rm2.left = &n2;
rm2.right = &n4;
ra.left = &rm1;
ra.right = &rm2;
ra.type = rm1.type;
- cgen(&ra, &tmp);
+ arch.cgen(&ra, &tmp);
// imag part
- memset(&rm1, 0, sizeof(ra));
+ memset(&rm1, 0, sizeof(rm1));
rm1.op = OMUL;
rm1.left = &n1;
rm1.right = &n4;
rm1.type = n1.type;
- memset(&rm2, 0, sizeof(ra));
+ memset(&rm2, 0, sizeof(rm2));
rm2.op = OMUL;
rm2.left = &n2;
rm2.right = &n3;
ra.left = &rm1;
ra.right = &rm2;
ra.type = rm1.type;
- cgen(&ra, &n6);
+ arch.cgen(&ra, &n6);
// tmp ->real part
- cgen(&tmp, &n5);
+ arch.cgen(&tmp, &n5);
}
c->funcdepth = funcdepth;
c->outer = n->closure;
n->closure = c;
- n->addrtaken = 1;
c->closure = n;
c->xoffset = 0;
curfn->cvars = list(curfn->cvars, c);
}
if(spkg == nil) {
if(toppkg == nil)
- toppkg = mkpkg(strlit("go"));
+ toppkg = mkpkg(newstrlit("go"));
spkg = toppkg;
}
s = pkglookup(p, spkg);
for(f=pa->method; f!=T; f=f->down) {
d = f;
if(f->etype != TFIELD)
- fatal("addmethod: not TFIELD: %N", f);
+ fatal("addmethod: not TFIELD: %lT", f);
if(strcmp(sf->name, f->sym->name) != 0)
continue;
if(!eqtype(t, f->type))
return tags[mask];
snprint(buf, sizeof buf, "esc:0x%x", mask);
- s = strlit(buf);
+ s = newstrlit(buf);
if(mask < nelem(tags))
tags[mask] = s;
return s;
{
int lno;
NodeList *ll, *lr;
- Node *a;
+ Node *a, *v;
if(n == N)
return;
case OAS:
case OASOP:
+ // Filter out the following special case.
+ //
+ // func (b *Buffer) Foo() {
+ // n, m := ...
+ // b.buf = b.buf[n:m]
+ // }
+ //
+ // This assignment is a no-op for escape analysis,
+ // it does not store any new pointers into b that were not already there.
+ // However, without this special case b will escape, because we assign to OIND/ODOTPTR.
+ if((n->left->op == OIND || n->left->op == ODOTPTR) && n->left->left->op == ONAME && // dst is ONAME dereference
+ (n->right->op == OSLICE || n->right->op == OSLICE3 || n->right->op == OSLICESTR) && // src is slice operation
+ (n->right->left->op == OIND || n->right->left->op == ODOTPTR) && n->right->left->left->op == ONAME && // slice is applied to ONAME dereference
+ n->left->left == n->right->left->left) { // dst and src reference the same base ONAME
+ // Here we also assume that the statement will not contain calls,
+ // that is, that order will move any calls to init.
+ // Otherwise base ONAME value could change between the moments
+ // when we evaluate it for dst and for src.
+ //
+ // Note, this optimization does not apply to OSLICEARR,
+ // because it does introduce a new pointer into b that was not already there
+ // (pointer to b itself). After such assignment, if b contents escape,
+ // b escapes as well. If we ignore such OSLICEARR, we will conclude
+ // that b does not escape when b contents do.
+ if(debug['m']) {
+ warnl(n->lineno, "%S ignoring self-assignment to %hN",
+ (n->curfn && n->curfn->nname) ? n->curfn->nname->sym : S, n->left);
+ }
+ break;
+ }
escassign(e, n->left, n->right);
break;
for(ll=n->list; ll; ll=ll->next)
escassign(e, n, ll->n->right);
break;
-
+
case OPTRLIT:
n->esc = EscNone; // until proven otherwise
e->noesc = list(e->noesc, n);
n->escloopdepth = e->loopdepth;
- // Contents make it to memory, lose track.
- escassign(e, &e->theSink, n->left);
+ // Link OSTRUCTLIT to OPTRLIT; if OPTRLIT escapes, OSTRUCTLIT elements do too.
+ escassign(e, n, n->left);
break;
-
+
case OCALLPART:
n->esc = EscNone; // until proven otherwise
e->noesc = list(e->noesc, n);
case OCLOSURE:
// Link addresses of captured variables to closure.
for(ll=n->cvars; ll; ll=ll->next) {
- if(ll->n->op == OXXX) // unnamed out argument; see dcl.c:/^funcargs
+ v = ll->n;
+ if(v->op == OXXX) // unnamed out argument; see dcl.c:/^funcargs
continue;
- a = nod(OADDR, ll->n->closure, N);
- a->lineno = ll->n->lineno;
- a->escloopdepth = e->loopdepth;
- typecheck(&a, Erv);
+ a = v->closure;
+ if(!v->byval) {
+ a = nod(OADDR, a, N);
+ a->lineno = v->lineno;
+ a->escloopdepth = e->loopdepth;
+ typecheck(&a, Erv);
+ }
escassign(e, n, a);
}
// fallthrough
e->noesc = list(e->noesc, n);
break;
+ case OARRAYBYTESTR:
+ case ORUNESTR:
+ n->escloopdepth = e->loopdepth;
+ n->esc = EscNone; // until proven otherwise
+ e->noesc = list(e->noesc, n);
+ break;
+
+ case OADDSTR:
+ n->escloopdepth = e->loopdepth;
+ n->esc = EscNone; // until proven otherwise
+ e->noesc = list(e->noesc, n);
+ // Arguments of OADDSTR do not escape.
+ break;
+
case OADDR:
n->esc = EscNone; // until proven otherwise
e->noesc = list(e->noesc, n);
case OCONVNOP:
case OMAPLIT:
case OSTRUCTLIT:
+ case OPTRLIT:
case OCALLPART:
break;
case OMAKECHAN:
case OMAKEMAP:
case OMAKESLICE:
+ case OARRAYBYTESTR:
+ case OADDSTR:
case ONEW:
case OCLOSURE:
case OCALLPART:
+ case ORUNESTR:
escflows(e, dst, src);
break;
case OSLICE3:
case OSLICEARR:
case OSLICE3ARR:
+ case OSLICESTR:
// Conversions, field access, slice all preserve the input value.
escassign(e, dst, src->left);
break;
case OMAKECHAN:
case OMAKEMAP:
case OMAKESLICE:
+ case OARRAYBYTESTR:
+ case OADDSTR:
case OMAPLIT:
case ONEW:
case OCLOSURE:
case OCALLPART:
+ case ORUNESTR:
if(leaks) {
src->esc = EscHeap;
if(debug['m'])
case OSLICEARR:
case OSLICE3:
case OSLICE3ARR:
+ case OSLICESTR:
escwalk(e, level, dst, src->left);
break;
}
static int
-methcmp(const void *va, const void *vb)
+methodbyname(const void *va, const void *vb)
{
Type *a, *b;
i = 0;
for(f=t->method; f!=T; f=f->down)
m[i++] = f;
- qsort(m, n, sizeof m[0], methcmp);
+ qsort(m, n, sizeof m[0], methodbyname);
Bprint(bout, "\ttype %#S %#lT\n", t->sym, t);
for(i=0; i<n; i++) {
b = Bopen(asmhdr, OWRITE);
if(b == nil)
fatal("open %s: %r", asmhdr);
- Bprint(b, "// generated by %cg -asmhdr from package %s\n\n", thechar, localpkg->name);
+ Bprint(b, "// generated by %cg -asmhdr from package %s\n\n", arch.thechar, localpkg->name);
for(l=asmlist; l; l=l->next) {
n = l->n;
if(isblanksym(n->sym))
if(n->embedded != 0)
fmtprint(fp, " embedded(%d)", n->embedded);
+ if(n->addrtaken != 0)
+ fmtprint(fp, " addrtaken");
+
+ if(n->assigned != 0)
+ fmtprint(fp, " assigned");
+
if(!c && n->used != 0)
fmtprint(fp, " used(%d)", n->used);
return 0;
//dump("gen", n);
lno = setlineno(n);
- wasregalloc = anyregalloc();
+ wasregalloc = arch.anyregalloc();
if(n == N)
goto ret;
// if there are pending gotos, resolve them all to the current pc.
for(p1=lab->gotopc; p1; p1=p2) {
- p2 = unpatch(p1);
- patch(p1, pc);
+ p2 = arch.unpatch(p1);
+ arch.patch(p1, pc);
}
lab->gotopc = P;
if(lab->labelpc == P)
// of the label in the OLABEL case above.)
lab = newlab(n);
if(lab->labelpc != P)
- gjmp(lab->labelpc);
+ arch.gjmp(lab->labelpc);
else
- lab->gotopc = gjmp(lab->gotopc);
+ lab->gotopc = arch.gjmp(lab->gotopc);
break;
case OBREAK:
yyerror("invalid break label %S", n->left->sym);
break;
}
- gjmp(lab->breakpc);
+ arch.gjmp(lab->breakpc);
break;
}
if(breakpc == P) {
yyerror("break is not in a loop");
break;
}
- gjmp(breakpc);
+ arch.gjmp(breakpc);
break;
case OCONTINUE:
yyerror("invalid continue label %S", n->left->sym);
break;
}
- gjmp(lab->continpc);
+ arch.gjmp(lab->continpc);
break;
}
if(continpc == P) {
yyerror("continue is not in a loop");
break;
}
- gjmp(continpc);
+ arch.gjmp(continpc);
break;
case OFOR:
sbreak = breakpc;
- p1 = gjmp(P); // goto test
- breakpc = gjmp(P); // break: goto done
+ p1 = arch.gjmp(P); // goto test
+ breakpc = arch.gjmp(P); // break: goto done
scontin = continpc;
continpc = pc;
lab->continpc = continpc;
}
gen(n->nincr); // contin: incr
- patch(p1, pc); // test:
- bgen(n->ntest, 0, -1, breakpc); // if(!test) goto break
+ arch.patch(p1, pc); // test:
+ arch.bgen(n->ntest, 0, -1, breakpc); // if(!test) goto break
genlist(n->nbody); // body
- gjmp(continpc);
- patch(breakpc, pc); // done:
+ arch.gjmp(continpc);
+ arch.patch(breakpc, pc); // done:
continpc = scontin;
breakpc = sbreak;
if(lab) {
break;
case OIF:
- p1 = gjmp(P); // goto test
- p2 = gjmp(P); // p2: goto else
- patch(p1, pc); // test:
- bgen(n->ntest, 0, -n->likely, p2); // if(!test) goto p2
+ p1 = arch.gjmp(P); // goto test
+ p2 = arch.gjmp(P); // p2: goto else
+ arch.patch(p1, pc); // test:
+ arch.bgen(n->ntest, 0, -n->likely, p2); // if(!test) goto p2
genlist(n->nbody); // then
- p3 = gjmp(P); // goto done
- patch(p2, pc); // else:
+ p3 = arch.gjmp(P); // goto done
+ arch.patch(p2, pc); // else:
genlist(n->nelse); // else
- patch(p3, pc); // done:
+ arch.patch(p3, pc); // done:
break;
case OSWITCH:
sbreak = breakpc;
- p1 = gjmp(P); // goto test
- breakpc = gjmp(P); // break: goto done
+ p1 = arch.gjmp(P); // goto test
+ breakpc = arch.gjmp(P); // break: goto done
// define break label
if((lab = stmtlabel(n)) != L)
lab->breakpc = breakpc;
- patch(p1, pc); // test:
+ arch.patch(p1, pc); // test:
genlist(n->nbody); // switch(test) body
- patch(breakpc, pc); // done:
+ arch.patch(breakpc, pc); // done:
breakpc = sbreak;
if(lab != L)
lab->breakpc = P;
case OSELECT:
sbreak = breakpc;
- p1 = gjmp(P); // goto test
- breakpc = gjmp(P); // break: goto done
+ p1 = arch.gjmp(P); // goto test
+ breakpc = arch.gjmp(P); // break: goto done
// define break label
if((lab = stmtlabel(n)) != L)
lab->breakpc = breakpc;
- patch(p1, pc); // test:
+ arch.patch(p1, pc); // test:
genlist(n->nbody); // select() body
- patch(breakpc, pc); // done:
+ arch.patch(breakpc, pc); // done:
breakpc = sbreak;
if(lab != L)
lab->breakpc = P;
break;
case OASOP:
- cgen_asop(n);
+ arch.cgen_asop(n);
break;
case ODCL:
break;
case OCALLINTER:
- cgen_callinter(n, N, 0);
+ arch.cgen_callinter(n, N, 0);
break;
case OCALLFUNC:
- cgen_call(n, 0);
+ arch.cgen_call(n, 0);
break;
case OPROC:
case ORETURN:
case ORETJMP:
- cgen_ret(n);
+ arch.cgen_ret(n);
break;
case OCHECKNIL:
}
ret:
- if(anyregalloc() != wasregalloc) {
+ if(arch.anyregalloc() != wasregalloc) {
dump("node", n);
fatal("registers left allocated");
}
if(n2.left->op == ONAME)
n2.left->class = PFUNC;
- cgen_call(&n2, proc);
+ arch.cgen_call(&n2, proc);
}
/*
break;
case OCALLINTER:
- cgen_callinter(n->left, N, proc);
+ arch.cgen_callinter(n->left, N, proc);
break;
case OCALLFUNC:
- cgen_call(n->left, proc);
+ arch.cgen_call(n->left, proc);
break;
}
switch(nr->op) {
case ONAME:
if(!(nr->class & PHEAP) && nr->class != PEXTERN && nr->class != PFUNC && nr->class != PPARAMREF)
- gused(nr);
+ arch.gused(nr);
break;
// unary
default:
tempname(&tmp, nr->type);
cgen_as(&tmp, nr);
- gused(&tmp);
+ arch.gused(&tmp);
}
}
}
ullmancalc(&z);
- cgen(&z, n);
+ arch.cgen(&z, n);
}
/*
tl = nl->type;
if(tl == T)
return;
- if(isfat(tl)) {
+ if(arch.isfat(tl)) {
if(nl->op == ONAME)
gvardef(nl);
- clearfat(nl);
+ arch.clearfat(nl);
return;
}
clearslim(nl);
if(tl == T)
return;
- cgen(nr, nl);
+ arch.cgen(nr, nl);
}
/*
Node *tmp;
tmp = temp(types[tptr]);
- cgen(n->right, tmp);
+ arch.cgen(n->right, tmp);
gvardef(res);
dst = *res;
dst.type = types[tptr];
dst.xoffset += widthptr;
- cgen(tmp, &dst);
+ arch.cgen(tmp, &dst);
dst.xoffset -= widthptr;
- cgen(n->left, &dst);
+ arch.cgen(n->left, &dst);
}
/*
if(isnil(n->left)) {
tempname(&src, n->left->type);
- cgen(n->left, &src);
+ arch.cgen(n->left, &src);
} else
src = *n->left;
if(n->op == OSLICE || n->op == OSLICE3 || n->op == OSLICESTR)
if(n->op == OSLICEARR || n->op == OSLICE3ARR) {
if(!isptr[n->left->type->etype])
fatal("slicearr is supposed to work on pointer: %+N\n", n);
- cgen(&src, base);
+ arch.cgen(&src, base);
cgen_checknil(base);
} else {
src.type = types[tptr];
- cgen(&src, base);
+ arch.cgen(&src, base);
}
// committed to the update
// compute len and cap.
// len = n-i, cap = m-i, and offs = i*width.
// computing offs last lets the multiply overwrite i.
- cgen(len, tmplen);
+ arch.cgen(len, tmplen);
if(n->op != OSLICESTR)
- cgen(cap, tmpcap);
+ arch.cgen(cap, tmpcap);
// if new cap != 0 { base += add }
// This avoids advancing base past the end of the underlying array/string,
// In essence we are replacing x[i:j:k] where i == j == k
// or x[i:j] where i == j == cap(x) with x[0:0:0].
if(offs != N) {
- p1 = gjmp(P);
- p2 = gjmp(P);
- patch(p1, pc);
+ p1 = arch.gjmp(P);
+ p2 = arch.gjmp(P);
+ arch.patch(p1, pc);
nodconst(&con, tmpcap->type, 0);
cmp = nod(OEQ, tmpcap, &con);
typecheck(&cmp, Erv);
- bgen(cmp, 1, -1, p2);
+ arch.bgen(cmp, 1, -1, p2);
add = nod(OADD, base, offs);
typecheck(&add, Erv);
- cgen(add, base);
+ arch.cgen(add, base);
- patch(p2, pc);
+ arch.patch(p2, pc);
}
// dst.array = src.array [ + lo *width ]
dst = *res;
dst.xoffset += Array_array;
dst.type = types[tptr];
- cgen(base, &dst);
+ arch.cgen(base, &dst);
// dst.len = hi [ - lo ]
dst = *res;
dst.xoffset += Array_nel;
dst.type = types[simtype[TUINT]];
- cgen(tmplen, &dst);
+ arch.cgen(tmplen, &dst);
if(n->op != OSLICESTR) {
// dst.cap = cap [ - lo ]
dst = *res;
dst.xoffset += Array_cap;
dst.type = types[simtype[TUINT]];
- cgen(tmpcap, &dst);
+ arch.cgen(tmpcap, &dst);
}
}
MaxStackVarSize = 10*1024*1024,
};
-extern vlong MAXWIDTH;
-
/*
* note this is the representation
* of the compilers string literals,
Strlit* sval; // string CTSTR
} u;
};
-
-// prevent incompatible type signatures between libgc and 8g on Plan 9
-#pragma incomplete struct Array
-
typedef struct Array Array;
typedef struct Bvec Bvec;
typedef struct Pkg Pkg;
typedef struct Type Type;
typedef struct Label Label;
+struct Array
+{
+ int32 length; // number of elements
+ int32 size; // element size
+ int32 capacity; // size of data in elements
+ char *data; // element storage
+};
+
struct Type
{
uchar etype;
uchar readonly;
uchar implicit;
uchar addrtaken; // address taken, even if not moved to heap
+ uchar assigned; // is the variable ever assigned to
+ uchar captured; // is the variable captured by a closure
+ uchar byval; // is the variable captured by value or by reference
uchar dupok; // duplicate definitions ok (for func)
uchar wrapper; // is method wrapper (for func)
uchar reslice; // this is a reslice x = x[0:y] or x = append(x, ...)
Node* pack; // real package for import . names
Node* curfn; // function for local variables
Type* paramfld; // TFIELD for this PPARAM; also for ODOT, curfn
+ int decldepth; // declaration loop depth, increased for every loop or label
// ONAME func param with PHEAP
Node* heapaddr; // temp holding heap address of param
+ Node* outerexpr; // expression copied into closure for variable
Node* stackparam; // OPARAM node referring to stack copy of param
Node* alloc; // allocation call
OARRAYBYTESTRTMP, // string(bytes) ephemeral
OARRAYRUNESTR, // string(runes)
OSTRARRAYBYTE, // []byte(s)
+ OSTRARRAYBYTETMP, // []byte(s) ephemeral
OSTRARRAYRUNE, // []rune(s)
OAS, // x = y or x := y
OAS2, // x, y, z = xx, yy, zz
Ecomplit = 1<<11, // type in composite literal
};
-#define BITS 3
-#define NVAR (BITS*sizeof(uint64)*8)
+enum {
+ BITS = 3,
+ NVAR = (BITS*64)
+};
typedef struct Bits Bits;
struct Bits
int sameas;
};
-extern Typedef typedefs[];
-
typedef struct Sig Sig;
struct Sig
{
EXTERN int nerrors;
EXTERN int nsavederrors;
EXTERN int nsyntaxerrors;
+EXTERN int decldepth;
EXTERN int safemode;
EXTERN int nolocalimports;
EXTERN char namebuf[NSYMB];
EXTERN NodeList* xtop;
EXTERN NodeList* externdcl;
-EXTERN NodeList* closures;
EXTERN NodeList* exportlist;
EXTERN NodeList* importlist; // imported functions and methods with inlinable bodies
EXTERN NodeList* funcsyms;
EXTERN Node* typesw;
EXTERN Node* nblank;
-extern int thechar;
-extern char* thestring;
-extern LinkArch* thelinkarch;
EXTERN int use_sse;
EXTERN char* hunk;
EXTERN int typecheckok;
EXTERN int compiling_runtime;
EXTERN int compiling_wrappers;
+EXTERN int inl_nonlocal;
EXTERN int use_writebarrier;
EXTERN int pure_go;
EXTERN char* flag_installsuffix;
EXTERN Link* ctxt;
EXTERN int nointerface;
-EXTERN int fieldtrack_enabled;
-EXTERN int precisestack_enabled;
EXTERN int writearchive;
EXTERN Biobuf bstdout;
Node* closurebody(NodeList *body);
void closurehdr(Node *ntype);
void typecheckclosure(Node *func, int top);
+void capturevars(Node *func);
Node* walkclosure(Node *func, NodeList **init);
void typecheckpartialcall(Node*, Node*);
Node* walkpartialcall(Node*, NodeList**);
int duint64(Sym *s, int off, uint64 v);
int duint8(Sym *s, int off, uint8 v);
int duintptr(Sym *s, int off, uint64 v);
-int dsname(Sym *s, int off, char *dat, int ndat);
void dumpobj(void);
Sym* stringsym(char*, int);
void slicebytes(Node*, char*, int);
void smagic(Magic *m);
Type* sortinter(Type *t);
uint32 stringhash(char *p);
-Strlit* strlit(char *s);
+Strlit* newstrlit(char *s);
int structcount(Type *t);
Type* structfirst(Iter *s, Type **nn);
Type* structnext(Iter *s);
Node* typecheckdef(Node *n);
void copytype(Node *n, Type *t);
void checkreturn(Node*);
+void checkassign(Node *stmt, Node*);
void queuemethod(Node *n);
/*
EXTERN int disable_checknil;
EXTERN vlong zerosize;
-int anyregalloc(void);
-void betypeinit(void);
-void bgen(Node *n, int true, int likely, Prog *to);
void checknil(Node*, NodeList**);
-void expandchecks(Prog*);
-void cgen(Node*, Node*);
-void cgen_asop(Node *n);
-void cgen_call(Node *n, int proc);
-void cgen_callinter(Node *n, Node *res, int proc);
void cgen_checknil(Node*);
-void cgen_ret(Node *n);
-void clearfat(Node *n);
void compile(Node*);
-void defframe(Prog*);
-int dgostringptr(Sym*, int off, char *str);
-int dgostrlitptr(Sym*, int off, Strlit*);
-int dstringptr(Sym *s, int off, char *str);
-int dsymptr(Sym *s, int off, Sym *x, int xoff);
int duintxx(Sym *s, int off, uint64 v, int wid);
-void dumpdata(void);
-void fixautoused(Prog*);
-void gdata(Node*, Node*, int);
-void gdatacomplex(Node*, Mpcplx*);
-void gdatastring(Node*, Strlit*);
-void ggloblnod(Node *nam);
-void ggloblsym(Sym *s, int32 width, int8 flags);
void gvardef(Node*);
void gvarkill(Node*);
-Prog* gjmp(Prog*);
-void gused(Node*);
void movelarge(NodeList*);
-int isfat(Type*);
-void linkarchinit(void);
void liveness(Node*, Prog*, Sym*, Sym*);
void twobitwalktype1(Type*, vlong*, Bvec*);
-void markautoused(Prog*);
-Plist* newplist(void);
-Node* nodarg(Type*, int);
void nopout(Prog*);
-void patch(Prog*, Prog*);
-Prog* unpatch(Prog*);
#pragma varargck type "B" Mpint*
#pragma varargck type "E" int
* racewalk.c
*/
void racewalk(Node *fn);
+
+/*
+ * flow.c
+ */
+typedef struct Flow Flow;
+typedef struct Graph Graph;
+
+struct Flow {
+ Prog* prog; // actual instruction
+ Flow* p1; // predecessors of this instruction: p1,
+ Flow* p2; // and then p2 linked though p2link.
+ Flow* p2link;
+ Flow* s1; // successors of this instruction (at most two: s1 and s2).
+ Flow* s2;
+ Flow* link; // next instruction in function code
+
+ int32 active; // usable by client
+
+ int32 rpo; // reverse post ordering
+ uint16 loop; // x5 for every loop
+ uchar refset; // diagnostic generated
+};
+
+struct Graph
+{
+ Flow* start;
+ int num;
+
+ // After calling flowrpo, rpo lists the flow nodes in reverse postorder,
+ // and each non-dead Flow node f has g->rpo[f->rpo] == f.
+ Flow** rpo;
+};
+
+void fixjmp(Prog*);
+Graph* flowstart(Prog*, int);
+void flowrpo(Graph*);
+void flowend(Graph*);
+void mergetemp(Prog*);
+void nilopt(Prog*);
+int noreturn(Prog*);
+Flow* uniqp(Flow*);
+Flow* uniqs(Flow*);
+
+/*
+ * interface to back end
+ */
+
+typedef struct ProgInfo ProgInfo;
+struct ProgInfo
+{
+ uint32 flags; // the bits below
+ uint64 reguse; // registers implicitly used by this instruction
+ uint64 regset; // registers implicitly set by this instruction
+ uint64 regindex; // registers used by addressing mode
+};
+
+enum
+{
+ // Pseudo-op, like TEXT, GLOBL, TYPE, PCDATA, FUNCDATA.
+ Pseudo = 1<<1,
+
+ // There's nothing to say about the instruction,
+ // but it's still okay to see.
+ OK = 1<<2,
+
+ // Size of right-side write, or right-side read if no write.
+ SizeB = 1<<3,
+ SizeW = 1<<4,
+ SizeL = 1<<5,
+ SizeQ = 1<<6,
+ SizeF = 1<<7, // float aka float32
+ SizeD = 1<<8, // double aka float64
+
+ // Left side (Prog.from): address taken, read, write.
+ LeftAddr = 1<<9,
+ LeftRead = 1<<10,
+ LeftWrite = 1<<11,
+
+ // Register in middle (Prog.reg); only ever read. (arm, ppc64)
+ RegRead = 1<<12,
+ CanRegRead = 1<<13,
+
+ // Right side (Prog.to): address taken, read, write.
+ RightAddr = 1<<14,
+ RightRead = 1<<15,
+ RightWrite = 1<<16,
+
+ // Instruction kinds
+ Move = 1<<17, // straight move
+ Conv = 1<<18, // size conversion
+ Cjmp = 1<<19, // conditional jump
+ Break = 1<<20, // breaks control flow (no fallthrough)
+ Call = 1<<21, // function call
+ Jump = 1<<22, // jump
+ Skip = 1<<23, // data instruction
+
+ // Set, use, or kill of carry bit.
+ // Kill means we never look at the carry bit after this kind of instruction.
+ SetCarry = 1<<24,
+ UseCarry = 1<<25,
+ KillCarry = 1<<26,
+
+ // Special cases for register use. (amd64, 386)
+ ShiftCX = 1<<27, // possible shift by CX
+ ImulAXDX = 1<<28, // possible multiply into DX:AX
+
+ // Instruction updates whichever of from/to is type D_OREG. (ppc64)
+ PostInc = 1<<29,
+};
+
+typedef struct Arch Arch;
+
+struct Arch
+{
+ int thechar;
+ char *thestring;
+ LinkArch *thelinkarch;
+ Typedef *typedefs;
+
+ vlong MAXWIDTH;
+
+ void (*afunclit)(Addr*, Node*);
+ int (*anyregalloc)(void);
+ void (*betypeinit)(void);
+ void (*bgen)(Node*, int, int, Prog*);
+ void (*cgen)(Node*, Node*);
+ void (*cgen_asop)(Node*);
+ void (*cgen_call)(Node*, int);
+ void (*cgen_callinter)(Node*, Node*, int);
+ void (*cgen_ret)(Node*);
+ void (*clearfat)(Node*);
+ void (*clearp)(Prog*);
+ void (*defframe)(Prog*);
+ int (*dgostringptr)(Sym*, int, char*);
+ int (*dgostrlitptr)(Sym*, int, Strlit*);
+ int (*dsname)(Sym*, int, char*, int);
+ int (*dsymptr)(Sym*, int, Sym*, int);
+ void (*dumpdata)(void);
+ void (*dumpit)(char*, Flow*, int);
+ void (*excise)(Flow*);
+ void (*expandchecks)(Prog*);
+ void (*fixautoused)(Prog*);
+ void (*gclean)(void);
+ void (*gdata)(Node*, Node*, int);
+ void (*gdatacomplex)(Node*, Mpcplx*);
+ void (*gdatastring)(Node*, Strlit*);
+ void (*ggloblnod)(Node*);
+ void (*ggloblsym)(Sym*, int32, int8);
+ void (*ginit)(void);
+ Prog* (*gins)(int, Node*, Node*);
+ void (*ginscall)(Node*, int);
+ Prog* (*gjmp)(Prog*);
+ void (*gtrack)(Sym*);
+ void (*gused)(Node*);
+ void (*igen)(Node*, Node*, Node*);
+ int (*isfat)(Type*);
+ void (*linkarchinit)(void);
+ void (*markautoused)(Prog*);
+ void (*naddr)(Node*, Addr*, int);
+ Plist* (*newplist)(void);
+ Node* (*nodarg)(Type*, int);
+ void (*patch)(Prog*, Prog*);
+ void (*proginfo)(ProgInfo*, Prog*);
+ void (*regalloc)(Node*, Type*, Node*);
+ void (*regfree)(Node*);
+ void (*regopt)(Prog*);
+ int (*regtyp)(Addr*);
+ int (*sameaddr)(Addr*, Addr*);
+ int (*smallindir)(Addr*, Addr*);
+ int (*stackaddr)(Addr*);
+ Prog* (*unpatch)(Prog*);
+};
+
+EXTERN Arch arch;
+
+EXTERN Node *newproc;
+EXTERN Node *deferproc;
+EXTERN Node *deferreturn;
+EXTERN Node *panicindex;
+EXTERN Node *panicslice;
+EXTERN Node *throwreturn;
+
+int gcmain(int, char**);
n->curfn = curfn; // the calling function, not the called one
n->addrtaken = var->addrtaken;
- // esc pass wont run if we're inlining into a iface wrapper
- // luckily, we can steal the results from the target func
- if(var->esc == EscHeap)
+ // Esc pass wont run if we're inlining into a iface wrapper.
+ // Luckily, we can steal the results from the target func.
+ // If inlining a function defined in another package after
+ // escape analysis is done, treat all local vars as escaping.
+ // See issue 9537.
+ if(var->esc == EscHeap || (inl_nonlocal && var->op == ONAME))
addrescapes(n);
curfn->dcl = list(curfn->dcl, n);
#include "y.tab.h"
#include <ar.h>
+#ifndef PLAN9
+#include <signal.h>
+#endif
+
#undef getc
#undef ungetc
#define getc ccgetc
#define BOM 0xFEFF
-// Compiler experiments.
-// These are controlled by the GOEXPERIMENT environment
-// variable recorded when the compiler is built.
-static struct {
- char *name;
- int *val;
-} exper[] = {
-// {"rune32", &rune32},
- {"fieldtrack", &fieldtrack_enabled},
- {"precisestack", &precisestack_enabled},
- {nil, nil},
-};
-
// Debug arguments.
// These can be specified with the -d flag, as in "-d nil"
// to set the debug_checknil variable. In general the list passed
int *val;
} debugtab[] = {
{"nil", &debug_checknil},
- {nil, nil},
};
-static void
-addexp(char *s)
-{
- int i;
-
- for(i=0; exper[i].name != nil; i++) {
- if(strcmp(exper[i].name, s) == 0) {
- *exper[i].val = 1;
- return;
- }
- }
-
- print("unknown experiment %s\n", s);
- exits("unknown experiment");
-}
-
-static void
-setexp(void)
-{
- char *f[20];
- int i, nf;
-
- precisestack_enabled = 1; // on by default
-
- // cmd/dist #defines GOEXPERIMENT for us.
- nf = getfields(GOEXPERIMENT, f, nelem(f), 1, ",");
- for(i=0; i<nf; i++)
- addexp(f[i]);
-}
-
-char*
-expstring(void)
-{
- int i;
- static char buf[512];
-
- strcpy(buf, "X");
- for(i=0; exper[i].name != nil; i++)
- if(*exper[i].val)
- seprint(buf+strlen(buf), buf+sizeof buf, ",%s", exper[i].name);
- if(strlen(buf) == 1)
- strcpy(buf, "X,none");
- buf[1] = ':';
- return buf;
-}
-
// Our own isdigit, isspace, isalpha, isalnum that take care
// of EOF and other out of range arguments.
static int
void
usage(void)
{
- print("usage: %cg [options] file.go...\n", thechar);
+ print("usage: %cg [options] file.go...\n", arch.thechar);
flagprint(1);
exits("usage");
}
void
doversion(void)
{
- char *p;
+ char *p, *sep;
p = expstring();
if(strcmp(p, "X:none") == 0)
p = "";
- print("%cg version %s%s%s\n", thechar, getgoversion(), *p ? " " : "", p);
+ sep = "";
+ if(*p)
+ sep = " ";
+ print("%cg version %s%s%s\n", arch.thechar, getgoversion(), sep, p);
exits(0);
}
int
-main(int argc, char *argv[])
+gcmain(int argc, char *argv[])
{
int i;
NodeList *l;
char *p;
-
+
#ifdef SIGBUS
signal(SIGBUS, fault);
signal(SIGSEGV, fault);
// Tell the FPU to handle all exceptions.
setfcr(FPPDBL|FPRNR);
#endif
- // Allow GOARCH=thestring or GOARCH=thestringsuffix,
+ // Allow GOARCH=arch.thestring or GOARCH=arch.thestringsuffix,
// but not other values.
p = getgoarch();
- if(strncmp(p, thestring, strlen(thestring)) != 0)
- sysfatal("cannot use %cg with GOARCH=%s", thechar, p);
+ if(strncmp(p, arch.thestring, strlen(arch.thestring)) != 0)
+ sysfatal("cannot use %cg with GOARCH=%s", arch.thechar, p);
goarch = p;
- linkarchinit();
- ctxt = linknew(thelinkarch);
+ arch.linkarchinit();
+ ctxt = linknew(arch.thelinkarch);
ctxt->diag = yyerror;
ctxt->bso = &bstdout;
Binit(&bstdout, 1, OWRITE);
- localpkg = mkpkg(strlit(""));
+ localpkg = mkpkg(newstrlit(""));
localpkg->prefix = "\"\"";
// pseudo-package, for scoping
- builtinpkg = mkpkg(strlit("go.builtin"));
+ builtinpkg = mkpkg(newstrlit("go.builtin"));
// pseudo-package, accessed by import "unsafe"
- unsafepkg = mkpkg(strlit("unsafe"));
+ unsafepkg = mkpkg(newstrlit("unsafe"));
unsafepkg->name = "unsafe";
// real package, referred to by generated runtime calls
- runtimepkg = mkpkg(strlit("runtime"));
+ runtimepkg = mkpkg(newstrlit("runtime"));
runtimepkg->name = "runtime";
// pseudo-packages used in symbol tables
- gostringpkg = mkpkg(strlit("go.string"));
+ gostringpkg = mkpkg(newstrlit("go.string"));
gostringpkg->name = "go.string";
gostringpkg->prefix = "go.string"; // not go%2estring
- itabpkg = mkpkg(strlit("go.itab"));
+ itabpkg = mkpkg(newstrlit("go.itab"));
itabpkg->name = "go.itab";
itabpkg->prefix = "go.itab"; // not go%2eitab
- weaktypepkg = mkpkg(strlit("go.weak.type"));
+ weaktypepkg = mkpkg(newstrlit("go.weak.type"));
weaktypepkg->name = "go.weak.type";
weaktypepkg->prefix = "go.weak.type"; // not go%2eweak%2etype
- typelinkpkg = mkpkg(strlit("go.typelink"));
+ typelinkpkg = mkpkg(newstrlit("go.typelink"));
typelinkpkg->name = "go.typelink";
typelinkpkg->prefix = "go.typelink"; // not go%2etypelink
- trackpkg = mkpkg(strlit("go.track"));
+ trackpkg = mkpkg(newstrlit("go.track"));
trackpkg->name = "go.track";
trackpkg->prefix = "go.track"; // not go%2etrack
- typepkg = mkpkg(strlit("type"));
+ typepkg = mkpkg(newstrlit("type"));
typepkg->name = "type";
goroot = getgoroot();
if(nacl)
flag_largemodel = 1;
- setexp();
-
fmtstrinit(&pragcgobuf);
quotefmtinstall();
flagcount("wb", "enable write barrier", &use_writebarrier);
flagcount("x", "debug lexer", &debug['x']);
flagcount("y", "debug declarations in canned imports (with -d)", &debug['y']);
- if(thechar == '6')
+ if(arch.thechar == '6')
flagcount("largemodel", "generate code that assumes a large memory model", &flag_largemodel);
flagparse(&argc, &argv, usage);
usage();
if(flag_race) {
- racepkg = mkpkg(strlit("runtime/race"));
+ racepkg = mkpkg(newstrlit("runtime/race"));
racepkg->name = "race";
}
nf = getfields(debugstr, f, nelem(f), 1, ",");
for(i=0; i<nf; i++) {
- for(j=0; debugtab[j].name != nil; j++) {
+ for(j=0; j<nelem(debugtab); j++) {
if(strcmp(debugtab[j].name, f[i]) == 0) {
- *debugtab[j].val = 1;
+ if(debugtab[j].val != nil)
+ *debugtab[j].val = 1;
break;
}
}
- if(debugtab[j].name == nil)
+ if(j >= nelem(debugtab))
sysfatal("unknown debug information -d '%s'\n", f[i]);
}
}
if(debug['l'] <= 1)
debug['l'] = 1 - debug['l'];
- if(thechar == '8') {
+ if(arch.thechar == '8') {
p = getgo386();
if(strcmp(p, "387") == 0)
use_sse = 0;
}
fmtinstallgo();
- betypeinit();
+ arch.betypeinit();
if(widthptr == 0)
fatal("betypeinit failed");
for(l=xtop; l; l=l->next) {
if(l->n->op == ODCLFUNC || l->n->op == OCLOSURE) {
curfn = l->n;
+ decldepth = 1;
saveerrors();
typechecklist(l->n->nbody, Etop);
checkreturn(l->n);
}
}
+ // Phase 4: Decide how to capture variables
+ // and transform closure bodies accordingly.
+ for(l=xtop; l; l=l->next) {
+ if(l->n->op == ODCLFUNC && l->n->closure) {
+ curfn = l->n;
+ capturevars(l->n);
+ }
+ }
+
curfn = nil;
if(nsavederrors+nerrors)
errorexit();
- // Phase 4: Inlining
+ // Phase 5: Inlining
if(debug['l'] > 1) {
// Typecheck imported function bodies if debug['l'] > 1,
// otherwise lazily when used or re-exported.
inlcalls(l->n);
}
- // Phase 5: Escape analysis.
+ // Phase 6: Escape analysis.
// Required for moving heap allocations onto stack,
// which in turn is required by the closure implementation,
// which stores the addresses of stack variables into the closure.
// Move large values off stack too.
movelarge(xtop);
- // Phase 6: Compile top level functions.
+ // Phase 7: Compile top level functions.
for(l=xtop; l; l=l->next)
if(l->n->op == ODCLFUNC)
funccompile(l->n, 0);
if(nsavederrors+nerrors == 0)
fninit(xtop);
- // Phase 7: Check external declarations.
+ // Phase 8: Check external declarations.
for(l=externdcl; l; l=l->next)
if(l->n->op == ONAME)
typecheck(&l->n, Erv);
snprint(namebuf, sizeof(namebuf), "%Z.a", name);
if(access(namebuf, 0) >= 0)
return 1;
- snprint(namebuf, sizeof(namebuf), "%Z.%c", name, thechar);
+ snprint(namebuf, sizeof(namebuf), "%Z.%c", name, arch.thechar);
if(access(namebuf, 0) >= 0)
return 1;
return 0;
snprint(namebuf, sizeof(namebuf), "%s/%Z.a", p->dir, name);
if(access(namebuf, 0) >= 0)
return 1;
- snprint(namebuf, sizeof(namebuf), "%s/%Z.%c", p->dir, name, thechar);
+ snprint(namebuf, sizeof(namebuf), "%s/%Z.%c", p->dir, name, arch.thechar);
if(access(namebuf, 0) >= 0)
return 1;
}
snprint(namebuf, sizeof(namebuf), "%s/pkg/%s_%s%s%s/%Z.a", goroot, goos, goarch, suffixsep, suffix, name);
if(access(namebuf, 0) >= 0)
return 1;
- snprint(namebuf, sizeof(namebuf), "%s/pkg/%s_%s%s%s/%Z.%c", goroot, goos, goarch, suffixsep, suffix, name, thechar);
+ snprint(namebuf, sizeof(namebuf), "%s/pkg/%s_%s%s%s/%Z.%c", goroot, goos, goarch, suffixsep, suffix, name, arch.thechar);
if(access(namebuf, 0) >= 0)
return 1;
}
static void
fakeimport(void)
{
- importpkg = mkpkg(strlit("fake"));
+ importpkg = mkpkg(newstrlit("fake"));
cannedimports("fake.6", "$$\n");
}
strcat(cleanbuf, "/");
strcat(cleanbuf, path->s);
cleanname(cleanbuf);
- path = strlit(cleanbuf);
+ path = newstrlit(cleanbuf);
if(isbadimport(path)) {
fakeimport();
if(c >= Runeself) {
ungetc(c);
rune = getr();
- // 0xb7 · is used for internal names
+ // 0xb7 · is used for internal names
if(!isalpharune(rune) && !isdigitrune(rune) && (importpkg == nil || rune != 0xb7))
yyerror("invalid identifier character U+%04x", rune);
cp += runetochar(cp, &rune);
}
// backend-specific builtin types (e.g. int).
- for(i=0; typedefs[i].name; i++) {
- s = lookup(typedefs[i].name);
+ for(i=0; arch.typedefs[i].name; i++) {
+ s = lookup(arch.typedefs[i].name);
if(s->def == N) {
- s->def = typenod(types[typedefs[i].etype]);
+ s->def = typenod(types[arch.typedefs[i].etype]);
s->origpkg = builtinpkg;
}
}
p = strrchr(namebuf, '.');
if(p != nil)
*p = 0;
- outfile = smprint("%s.%c", namebuf, thechar);
+ outfile = smprint("%s.%c", namebuf, arch.thechar);
}
}
externdcl = tmp;
zero = pkglookup("zerovalue", runtimepkg);
- ggloblsym(zero, zerosize, DUPOK|RODATA);
+ arch.ggloblsym(zero, zerosize, DUPOK|RODATA);
- dumpdata();
+ arch.dumpdata();
writeobj(ctxt, bout);
if(writearchive) {
if(size&1)
Bputc(bout, 0);
Bseek(bout, startobj - ArhdrSize, 0);
- snprint(namebuf, sizeof namebuf, "_go_.%c", thechar);
+ snprint(namebuf, sizeof namebuf, "_go_.%c", arch.thechar);
formathdr(arhdr, namebuf, size);
Bwrite(bout, arhdr, ArhdrSize);
}
continue;
dowidth(n->type);
- ggloblnod(n);
+ arch.ggloblnod(n);
}
for(l=funcsyms; l; l=l->next) {
n = l->n;
- dsymptr(n->sym, 0, n->sym->def->shortname->sym, 0);
- ggloblsym(n->sym, widthptr, DUPOK|RODATA);
+ arch.dsymptr(n->sym, 0, n->sym->def->shortname->sym, 0);
+ arch.ggloblsym(n->sym, widthptr, DUPOK|RODATA);
}
// Do not reprocess funcsyms on next dumpglobls call.
off = 0;
// string header
- off = dsymptr(sym, off, sym, widthptr+widthint);
+ off = arch.dsymptr(sym, off, sym, widthptr+widthint);
off = duintxx(sym, off, len, widthint);
// string data
m = 8;
if(m > len-n)
m = len-n;
- off = dsname(sym, off, s+n, m);
+ off = arch.dsname(sym, off, s+n, m);
}
off = duint8(sym, off, 0); // terminating NUL for runtime
off = (off+widthptr-1)&~(widthptr-1); // round to pointer alignment
- ggloblsym(sym, off, DUPOK|RODATA);
+ arch.ggloblsym(sym, off, DUPOK|RODATA);
return sym;
}
m = 8;
if(m > len-n)
m = len-n;
- off = dsname(sym, off, s+n, m);
+ off = arch.dsname(sym, off, s+n, m);
}
- ggloblsym(sym, off, NOPTR);
+ arch.ggloblsym(sym, off, NOPTR);
if(nam->op != ONAME)
fatal("slicebytes %N", nam);
off = nam->xoffset;
- off = dsymptr(nam->sym, off, sym, 0);
+ off = arch.dsymptr(nam->sym, off, sym, 0);
off = duintxx(nam->sym, off, len, widthint);
duintxx(nam->sym, off, len, widthint);
}
void
order(Node *fn)
{
+ char s[50];
+
+ if(debug['W'] > 1) {
+ snprint(s, sizeof(s), "\nbefore order %S", fn->nname->sym);
+ dumplist(s, fn->nbody);
+ }
+
orderblock(&fn->nbody);
}
default:
fatal("orderstmt range %T", n->type);
case TARRAY:
+ // Mark []byte(str) range expression to reuse string backing storage.
+ // It is safe because the storage cannot be mutated.
+ if(n->right->op == OSTRARRAYBYTE)
+ n->right->op = OSTRARRAYBYTETMP;
if(count(n->list) < 2 || isblank(n->list->next->n)) {
// for i := range x will only use x once, to compute len(x).
// No need to copy it.
Node *n;
NodeList *mark, *l;
Type *t;
- int lno;
+ int lno, haslit, hasbyte;
n = *np;
if(n == N)
t->type = types[TSTRING];
n->alloc = ordertemp(t, order, 0);
}
+
+ // Mark string(byteSlice) arguments to reuse byteSlice backing
+ // buffer during conversion. String concatenation does not
+ // memorize the strings for later use, so it is safe.
+ // However, we can do it only if there is at least one non-empty string literal.
+ // Otherwise if all other arguments are empty strings,
+ // concatstrings will return the reference to the temp string
+ // to the caller.
+ hasbyte = 0;
+ haslit = 0;
+ for(l=n->list; l != nil; l=l->next) {
+ hasbyte |= l->n->op == OARRAYBYTESTR;
+ haslit |= l->n->op == OLITERAL && l->n->val.u.sval->len != 0;
+ }
+ if(haslit && hasbyte) {
+ for(l=n->list; l != nil; l=l->next) {
+ if(l->n->op == OARRAYBYTESTR)
+ l->n->op = OARRAYBYTESTRTMP;
+ }
+ }
+ break;
+
+ case OCMPSTR:
+ orderexpr(&n->left, order);
+ orderexpr(&n->right, order);
+ // Mark string(byteSlice) arguments to reuse byteSlice backing
+ // buffer during conversion. String comparison does not
+ // memorize the strings for later use, so it is safe.
+ if(n->left->op == OARRAYBYTESTR)
+ n->left->op = OARRAYBYTESTRTMP;
+ if(n->right->op == OARRAYBYTESTR)
+ n->right->op = OARRAYBYTESTRTMP;
break;
case OINDEXMAP:
#include <u.h>
#include <libc.h>
#include "md5.h"
-#include "gg.h"
-#include "opt.h"
+#include "go.h"
+//#include "opt.h"
#include "../../runtime/funcdata.h"
+#include "../ld/textflag.h"
static void allocauto(Prog* p);
static void emitptrargsmap(void);
pnod = newname(sym);
pnod->class = PEXTERN;
nodconst(&nod, types[TINT32], funcdatakind);
- gins(AFUNCDATA, &nod, pnod);
+ arch.gins(AFUNCDATA, &nod, pnod);
return sym;
}
// where a complete initialization (definition) of a variable begins.
// Since the liveness analysis can see initialization of single-word
// variables quite easy, gvardef is usually only called for multi-word
-// or 'fat' variables, those satisfying isfat(n->type).
+// or 'fat' variables, those satisfying arch.isfat(n->type).
// However, gvardef is also called when a non-fat variable is initialized
// via a block move; the only time this happens is when you have
// return f()
case PAUTO:
case PPARAM:
case PPARAMOUT:
- gins(as, N, n);
+ arch.gins(as, N, n);
}
}
for(p = firstp; p != P; p = p->link) {
while(p->link != P && (p->link->as == AVARDEF || p->link->as == AVARKILL))
p->link = p->link->link;
- if(p->to.type == D_BRANCH)
+ if(p->to.type == TYPE_BRANCH)
while(p->to.u.branch != P && (p->to.u.branch->as == AVARDEF || p->to.u.branch->as == AVARKILL))
p->to.u.branch = p->to.u.branch->link;
}
continpc = P;
breakpc = P;
- pl = newplist();
+ pl = arch.newplist();
pl->name = linksym(curfn->nname->sym);
setlineno(curfn);
nodconst(&nod1, types[TINT32], 0);
- ptxt = gins(ATEXT, isblank(curfn->nname) ? N : curfn->nname, &nod1);
+ ptxt = arch.gins(ATEXT, isblank(curfn->nname) ? N : curfn->nname, &nod1);
if(fn->dupok)
- ptxt->TEXTFLAG |= DUPOK;
+ ptxt->from3.offset |= DUPOK;
if(fn->wrapper)
- ptxt->TEXTFLAG |= WRAPPER;
+ ptxt->from3.offset |= WRAPPER;
if(fn->needctxt)
- ptxt->TEXTFLAG |= NEEDCTXT;
+ ptxt->from3.offset |= NEEDCTXT;
if(fn->nosplit)
- ptxt->TEXTFLAG |= NOSPLIT;
+ ptxt->from3.offset |= NOSPLIT;
// Clumsy but important.
// See test/recover.go for test cases and src/reflect/value.go
// for the actual functions being considered.
if(myimportpath != nil && strcmp(myimportpath, "reflect") == 0) {
if(strcmp(curfn->nname->sym->name, "callReflect") == 0 || strcmp(curfn->nname->sym->name, "callMethod") == 0)
- ptxt->TEXTFLAG |= WRAPPER;
+ ptxt->from3.offset |= WRAPPER;
}
- afunclit(&ptxt->from, curfn->nname);
+ arch.afunclit(&ptxt->from, curfn->nname);
- ginit();
+ arch.ginit();
gcargs = makefuncdatasym("gcargs·%d", FUNCDATA_ArgsPointerMaps);
gclocals = makefuncdatasym("gclocals·%d", FUNCDATA_LocalsPointerMaps);
for(t=curfn->paramfld; t; t=t->down)
- gtrack(tracksym(t->type));
+ arch.gtrack(tracksym(t->type));
for(l=fn->dcl; l; l=l->next) {
n = l->n;
case PPARAM:
case PPARAMOUT:
nodconst(&nod1, types[TUINTPTR], l->n->type->width);
- p = gins(ATYPE, l->n, &nod1);
+ p = arch.gins(ATYPE, l->n, &nod1);
p->from.gotype = linksym(ngotype(l->n));
break;
}
genlist(curfn->enter);
genlist(curfn->nbody);
- gclean();
+ arch.gclean();
checklabels();
if(nerrors != 0)
goto ret;
lineno = curfn->endlineno;
if(curfn->type->outtuple != 0)
- ginscall(throwreturn, 0);
+ arch.ginscall(throwreturn, 0);
- ginit();
+ arch.ginit();
// TODO: Determine when the final cgen_ret can be omitted. Perhaps always?
- cgen_ret(nil);
+ arch.cgen_ret(nil);
if(hasdefer) {
// deferreturn pretends to have one uintptr argument.
// Reserve space for it so stack scanner is happy.
if(maxarg < widthptr)
maxarg = widthptr;
}
- gclean();
+ arch.gclean();
if(nerrors != 0)
goto ret;
fixjmp(ptxt);
if(!debug['N'] || debug['R'] || debug['P']) {
- regopt(ptxt);
+ arch.regopt(ptxt);
nilopt(ptxt);
}
- expandchecks(ptxt);
+ arch.expandchecks(ptxt);
oldstksize = stksize;
allocauto(ptxt);
gcsymdup(gcargs);
gcsymdup(gclocals);
- defframe(ptxt);
+ arch.defframe(ptxt);
if(0)
frame(0);
for(j = 0; j < bv->n; j += 32)
off = duint32(sym, off, bv->b[j/32]);
}
- ggloblsym(sym, off, RODATA);
+ arch.ggloblsym(sym, off, RODATA);
free(bv);
}
{
int ap, bp;
- if (a->class != b->class)
- return (a->class == PAUTO) ? +1 : -1;
+ if (a->class != b->class) {
+ if(a->class == PAUTO)
+ return +1;
+ return -1;
+ }
if (a->class != PAUTO) {
if (a->xoffset < b->xoffset)
return -1;
if (ll->n->class == PAUTO)
ll->n->used = 0;
- markautoused(ptxt);
+ arch.markautoused(ptxt);
listsort(&curfn->dcl, cmpstackvar);
if (n->class == PAUTO && n->op == ONAME && !n->used) {
// No locals used at all
curfn->dcl = nil;
- fixautoused(ptxt);
+ arch.fixautoused(ptxt);
return;
}
dowidth(n->type);
w = n->type->width;
- if(w >= MAXWIDTH || w < 0)
+ if(w >= arch.MAXWIDTH || w < 0)
fatal("bad width");
stksize += w;
stksize = rnd(stksize, n->type->align);
if(haspointers(n->type))
stkptrsize = stksize;
- if(thechar == '5' || thechar == '9')
+ if(arch.thechar == '5' || arch.thechar == '9')
stksize = rnd(stksize, widthptr);
if(stksize >= (1ULL<<31)) {
setlineno(curfn);
stksize = rnd(stksize, widthreg);
stkptrsize = rnd(stkptrsize, widthreg);
- fixautoused(ptxt);
+ arch.fixautoused(ptxt);
// The debug information needs accurate offsets on the symbols.
for(ll = curfn->dcl; ll != nil; ll=ll->next) {
dump("checknil", n);
fatal("bad checknil");
}
- if(((thechar == '5' || thechar == '9') && n->op != OREGISTER) || !n->addable || n->op == OLITERAL) {
- regalloc(®, types[tptr], n);
- cgen(n, ®);
- gins(ACHECKNIL, ®, N);
- regfree(®);
+ if(((arch.thechar == '5' || arch.thechar == '9') && n->op != OREGISTER) || !n->addable || n->op == OLITERAL) {
+ arch.regalloc(®, types[tptr], n);
+ arch.cgen(n, ®);
+ arch.gins(ACHECKNIL, ®, N);
+ arch.regfree(®);
return;
}
- gins(ACHECKNIL, n, N);
+ arch.gins(ACHECKNIL, n, N);
}
#include <u.h>
#include <libc.h>
-#include "gg.h"
-#include "opt.h"
+#include "go.h"
#include "../ld/textflag.h"
#include "../../runtime/funcdata.h"
#include "../../runtime/mgc0.h"
bb = newblock(firstp);
arrayadd(cfg, &bb);
for(p = firstp; p != P; p = p->link) {
- if(p->to.type == D_BRANCH) {
+ if(p->to.type == TYPE_BRANCH) {
if(p->to.u.branch == nil)
fatal("prog branch to nil");
if(p->to.u.branch->opt == nil) {
if(isselectgocall(p))
arrayadd(selectgo, &bb);
}
- if(bb->last->to.type == D_BRANCH)
+ if(bb->last->to.type == TYPE_BRANCH)
addedge(bb, bb->last->to.u.branch->opt);
if(bb->last->link != nil) {
// Add a fall-through when the instruction is
// not an unconditional control transfer.
- switch(bb->last->as) {
- case AJMP:
- case ARET:
- case AUNDEF:
- break;
- default:
+ if(bb->last->as != AJMP && bb->last->as != ARET && bb->last->as != AUNDEF)
addedge(bb, bb->last->link->opt);
- }
}
}
BasicBlock *bb0;
Prog *p;
int32 i;
- int32 len;
+ int32 n;
- len = arraylength(cfg);
- if(len > 0) {
+ n = arraylength(cfg);
+ if(n > 0) {
bb0 = *(BasicBlock**)arrayget(cfg, 0);
for(p = bb0->first; p != P; p = p->link) {
p->opt = nil;
}
- for(i = 0; i < len; i++) {
+ for(i = 0; i < n; i++) {
bb = *(BasicBlock**)arrayget(cfg, i);
freeblock(bb);
}
bvresetall(varkill);
bvresetall(avarinit);
- proginfo(&info, prog);
+ arch.proginfo(&info, prog);
if(prog->as == ARET) {
// Return instructions implicitly read all the arguments. For
// the sake of correctness, out arguments must be read. For the
// If we added it to uevar too, we'd not see any kill
// and decide that the varible was live entry, which it is not.
// So only use uevar in the non-addrtaken case.
- // The p->to.type == D_NONE limits the bvset to
+ // The p->to.type == arch.D_NONE limits the bvset to
// non-tail-call return instructions; see note above
// the for loop for details.
- if(!node->addrtaken && prog->to.type == D_NONE)
+ if(!node->addrtaken && prog->to.type == TYPE_NONE)
bvset(uevar, i);
break;
}
}
if(info.flags & (LeftRead | LeftWrite | LeftAddr)) {
from = &prog->from;
- if (from->node != nil && from->sym != nil && from->node->curfn == curfn) {
- switch(from->node->class & ~PHEAP) {
+ if (from->node != nil && from->sym != nil && ((Node*)(from->node))->curfn == curfn) {
+ switch(((Node*)(from->node))->class & ~PHEAP) {
case PAUTO:
case PPARAM:
case PPARAMOUT:
- pos = (int)(uintptr)from->node->opt - 1; // index in vars
+ pos = (int)(uintptr)((Node*)(from->node))->opt - 1; // index in vars
if(pos == -1)
goto Next;
if(pos >= arraylength(vars) || *(Node**)arrayget(vars, pos) != from->node)
fatal("bad bookkeeping in liveness %N %d", from->node, pos);
- if(from->node->addrtaken) {
+ if(((Node*)(from->node))->addrtaken) {
bvset(avarinit, pos);
} else {
if(info.flags & (LeftRead | LeftAddr))
bvset(uevar, pos);
if(info.flags & LeftWrite)
- if(from->node != nil && !isfat(from->node->type))
+ if(from->node != nil && !arch.isfat(((Node*)(from->node))->type))
bvset(varkill, pos);
}
}
Next:
if(info.flags & (RightRead | RightWrite | RightAddr)) {
to = &prog->to;
- if (to->node != nil && to->sym != nil && to->node->curfn == curfn) {
- switch(to->node->class & ~PHEAP) {
+ if (to->node != nil && to->sym != nil && ((Node*)(to->node))->curfn == curfn) {
+ switch(((Node*)(to->node))->class & ~PHEAP) {
case PAUTO:
case PPARAM:
case PPARAMOUT:
- pos = (int)(uintptr)to->node->opt - 1; // index in vars
+ pos = (int)(uintptr)((Node*)(to->node))->opt - 1; // index in vars
if(pos == -1)
goto Next1;
if(pos >= arraylength(vars) || *(Node**)arrayget(vars, pos) != to->node)
fatal("bad bookkeeping in liveness %N %d", to->node, pos);
- if(to->node->addrtaken) {
+ if(((Node*)(to->node))->addrtaken) {
if(prog->as != AVARKILL)
bvset(avarinit, pos);
if(prog->as == AVARDEF || prog->as == AVARKILL)
if((info.flags & RightRead) || (info.flags & (RightAddr|RightWrite)) == RightAddr)
bvset(uevar, pos);
if(info.flags & RightWrite)
- if(to->node != nil && (!isfat(to->node->type) || prog->as == AVARDEF))
+ if(to->node != nil && (!arch.isfat(((Node*)(to->node))->type) || prog->as == AVARDEF))
bvset(varkill, pos);
}
}
char *p;
char *a;
- p = haspointers(node->type) ? "^" : "";
- a = node->addrtaken ? "@" : "";
+ p = "";
+ if(haspointers(node->type))
+ p = "^";
+ a = "";
+ if(node->addrtaken)
+ a = "@";
print(" %N%s%s", node, p, a);
}
if(l->n->op == ONAME && l->n->class == PAUTO && l->n == n)
return;
+ if(n == nil) {
+ print("%L: checkauto %N: nil node in %P\n", p->lineno, curfn, p);
+ return;
+ }
print("checkauto %N: %N (%p; class=%d) not found in %P\n", curfn, n, n, n->class, p);
for(l = fn->dcl; l != nil; l = l->next)
print("\t%N (%p; class=%d)\n", l->n, l->n, l->n->class);
static void
checkprog(Node *fn, Prog *p)
{
- if(p->from.type == D_AUTO)
+ if(p->from.name == NAME_AUTO)
checkauto(fn, p, p->from.node);
- if(p->from.type == D_PARAM)
+ if(p->from.name == NAME_PARAM)
checkparam(fn, p, p->from.node);
- if(p->to.type == D_AUTO)
+ if(p->to.name == NAME_AUTO)
checkauto(fn, p, p->to.node);
- if(p->to.type == D_PARAM)
+ if(p->to.name == NAME_PARAM)
checkparam(fn, p, p->to.node);
}
for(p = firstp; p != P; p = p->link) {
if(0)
print("analyzing '%P'\n", p);
- switch(p->as) {
- case ADATA:
- case AGLOBL:
- case ANAME:
- case ASIGNAME:
- case ATYPE:
- continue;
- }
- checkprog(fn, p);
+ if(p->as != ADATA && p->as != AGLOBL && p->as != ATYPE)
+ checkprog(fn, p);
}
}
Prog *p;
p = mal(sizeof(*p));
- clearp(p);
+ arch.clearp(p);
p->as = as;
return p;
}
nodconst(&to, types[TINT32], index);
pcdata = unlinkedprog(APCDATA);
pcdata->lineno = prog->lineno;
- naddr(&from, &pcdata->from, 0);
- naddr(&to, &pcdata->to, 0);
+ arch.naddr(&from, &pcdata->from, 0);
+ arch.naddr(&to, &pcdata->to, 0);
return pcdata;
}
// Annotate ambiguously live variables so that they can
// be zeroed at function entry.
// livein and liveout are dead here and used as temporaries.
- // For now, only enabled when using GOEXPERIMENT=precisestack
- // during make.bash / all.bash.
- if(precisestack_enabled) {
- bvresetall(livein);
- bvandnot(liveout, any, all);
- if(!bvisempty(liveout)) {
- for(pos = 0; pos < liveout->n; pos++) {
- if(!bvget(liveout, pos))
- continue;
- bvset(all, pos); // silence future warnings in this block
- n = *(Node**)arrayget(lv->vars, pos);
- if(!n->needzero) {
- n->needzero = 1;
- if(debuglive >= 1)
- warnl(p->lineno, "%N: %lN is ambiguously live", curfn->nname, n);
- // Record in 'ambiguous' bitmap.
- xoffset = n->xoffset + stkptrsize;
- twobitwalktype1(n->type, &xoffset, ambig);
- }
+ bvresetall(livein);
+ bvandnot(liveout, any, all);
+ if(!bvisempty(liveout)) {
+ for(pos = 0; pos < liveout->n; pos++) {
+ if(!bvget(liveout, pos))
+ continue;
+ bvset(all, pos); // silence future warnings in this block
+ n = *(Node**)arrayget(lv->vars, pos);
+ if(!n->needzero) {
+ n->needzero = 1;
+ if(debuglive >= 1)
+ warnl(p->lineno, "%N: %lN is ambiguously live", curfn->nname, n);
+ // Record in 'ambiguous' bitmap.
+ xoffset = n->xoffset + stkptrsize;
+ twobitwalktype1(n->type, &xoffset, ambig);
}
}
}
fmtstrinit(&fmt);
fmtprint(&fmt, "%L: live at ", p->lineno);
if(p->as == ACALL && p->to.node)
- fmtprint(&fmt, "call to %s:", p->to.node->sym->name);
+ fmtprint(&fmt, "call to %s:", ((Node*)(p->to.node))->sym->name);
else if(p->as == ACALL)
fmtprint(&fmt, "indirect call:");
else
- fmtprint(&fmt, "entry to %s:", p->from.node->sym->name);
+ fmtprint(&fmt, "entry to %s:", ((Node*)(p->from.node))->sym->name);
numlive = 0;
for(j = 0; j < arraylength(lv->vars); j++) {
n = *(Node**)arrayget(lv->vars, j);
static uint32
hashbitmap(uint32 h, Bvec *bv)
{
- uchar *p, *ep;
+ int i, n;
+ uint32 w;
- p = (uchar*)bv->b;
- ep = p + 4*((bv->n+31)/32);
- while(p < ep)
- h = (h*Hp) ^ *p++;
+ n = (bv->n+31)/32;
+ for(i=0; i<n; i++) {
+ w = bv->b[i];
+ h = (h*Hp) ^ (w&0xff);
+ h = (h*Hp) ^ ((w>>8)&0xff);
+ h = (h*Hp) ^ ((w>>16)&0xff);
+ h = (h*Hp) ^ ((w>>24)&0xff);
+ }
return h;
}
}
}
duint32(sym, 0, i); // number of bitmaps
- ggloblsym(sym, off, RODATA);
+ arch.ggloblsym(sym, off, RODATA);
}
static void
#include <u.h>
#include <libc.h>
-#include "gg.h"
-#include "opt.h"
+#include "go.h"
// p is a call instruction. Does the call fail to return?
int
if(p->to.node == nil)
return 0;
- s = p->to.node->sym;
+ s = ((Node*)(p->to.node))->sym;
if(s == S)
return 0;
for(i=0; symlist[i]!=S; i++)
int n;
n = 0;
- while(p != P && p->as == AJMP && p->to.type == D_BRANCH) {
+ while(p != P && p->as == AJMP && p->to.type == TYPE_BRANCH) {
if(++n > 10) {
*jmploop = 1;
break;
if(p->opt != dead)
break;
p->opt = alive;
- if(p->as != ACALL && p->to.type == D_BRANCH && p->to.u.branch)
+ if(p->as != ACALL && p->to.type == TYPE_BRANCH && p->to.u.branch)
mark(p->to.u.branch);
if(p->as == AJMP || p->as == ARET || p->as == AUNDEF)
break;
for(p=firstp; p; p=p->link) {
if(debug['R'] && debug['v'])
print("%P\n", p);
- if(p->as != ACALL && p->to.type == D_BRANCH && p->to.u.branch && p->to.u.branch->as == AJMP) {
+ if(p->as != ACALL && p->to.type == TYPE_BRANCH && p->to.u.branch && p->to.u.branch->as == AJMP) {
p->to.u.branch = chasejmp(p->to.u.branch, &jmploop);
if(debug['R'] && debug['v'])
print("->%P\n", p);
if(!jmploop) {
last = nil;
for(p=firstp; p; p=p->link) {
- if(p->as == AJMP && p->to.type == D_BRANCH && p->to.u.branch == p->link) {
+ if(p->as == AJMP && p->to.type == TYPE_BRANCH && p->to.u.branch == p->link) {
if(debug['R'] && debug['v'])
print("del %P\n", p);
continue;
nf = 0;
for(p = firstp; p != P; p = p->link) {
p->opt = nil; // should be already, but just in case
- proginfo(&info, p);
+ arch.proginfo(&info, p);
if(info.flags & Skip)
continue;
p->opt = (void*)1;
// Fill in pred/succ information.
for(f = start; f != nil; f = f->link) {
p = f->prog;
- proginfo(&info, p);
+ arch.proginfo(&info, p);
if(!(info.flags & Break)) {
f1 = f->link;
f->s1 = f1;
f1->p1 = f;
}
- if(p->to.type == D_BRANCH) {
+ if(p->to.type == TYPE_BRANCH) {
if(p->to.u.branch == P)
fatal("pnil %P", p);
f1 = p->to.u.branch->opt;
return 0;
}
+enum {
+ LOOP = 3,
+};
+
static void
loopmark(Flow **rpo2r, int32 head, Flow *r)
{
// single-use (that's why we have so many!).
for(r = (TempFlow*)g->start; r != nil; r = (TempFlow*)r->f.link) {
p = r->f.prog;
- proginfo(&info, p);
+ arch.proginfo(&info, p);
- if(p->from.node != N && p->from.node->opt && p->to.node != N && p->to.node->opt)
+ if(p->from.node != N && ((Node*)(p->from.node))->opt && p->to.node != N && ((Node*)(p->to.node))->opt)
fatal("double node %P", p);
- if((n = p->from.node) != N && (v = n->opt) != nil ||
- (n = p->to.node) != N && (v = n->opt) != nil) {
+ v = nil;
+ if((n = p->from.node) != N)
+ v = n->opt;
+ if(v == nil && (n = p->to.node) != N)
+ v = n->opt;
+ if(v != nil) {
if(v->def == nil)
v->def = r;
r->uselink = v->use;
}
if(Debug > 1)
- dumpit("before", g->start, 0);
+ arch.dumpit("before", g->start, 0);
nkill = 0;
// Used in only one instruction, which had better be a write.
if((r = v->use) != nil && r->uselink == nil) {
p = r->f.prog;
- proginfo(&info, p);
+ arch.proginfo(&info, p);
if(p->to.node == v->node && (info.flags & RightWrite) && !(info.flags & RightRead)) {
p->as = ANOP;
p->to = zprog.to;
// no jumps to the next instruction. Happens mainly in 386 compiler.
if((r = v->use) != nil && r->f.link == &r->uselink->f && r->uselink->uselink == nil && uniqp(r->f.link) == &r->f) {
p = r->f.prog;
- proginfo(&info, p);
+ arch.proginfo(&info, p);
p1 = r->f.link->prog;
- proginfo(&info1, p1);
+ arch.proginfo(&info1, p1);
enum {
SizeAny = SizeB | SizeW | SizeL | SizeQ | SizeF | SizeD,
};
!((info.flags|info1.flags) & (LeftAddr|RightAddr)) &&
(info.flags & SizeAny) == (info1.flags & SizeAny)) {
p1->from = p->from;
- excise(&r->f);
+ arch.excise(&r->f);
v->removed = 1;
if(Debug)
print("drop immediate-use %S\n", v->node->sym);
}
if(Debug > 1)
- dumpit("after", g->start, 0);
+ arch.dumpit("after", g->start, 0);
}
// Update node references to use merged temporaries.
return;
if(debug_checknil > 1 /* || strcmp(curfn->nname->sym->name, "f1") == 0 */)
- dumpit("nilopt", g->start, 0);
+ arch.dumpit("nilopt", g->start, 0);
ncheck = 0;
nkill = 0;
for(r = (NilFlow*)g->start; r != nil; r = (NilFlow*)r->f.link) {
p = r->f.prog;
- if(p->as != ACHECKNIL || !regtyp(&p->from))
+ if(p->as != ACHECKNIL || !arch.regtyp(&p->from))
continue;
ncheck++;
- if(stackaddr(&p->from)) {
+ if(arch.stackaddr(&p->from)) {
if(debug_checknil && p->lineno > 1)
warnl(p->lineno, "removed nil check of SP address");
r->kill = 1;
for(r = (NilFlow*)g->start; r != nil; r = (NilFlow*)r->f.link) {
if(r->kill) {
nkill++;
- excise(&r->f);
+ arch.excise(&r->f);
}
}
for(r = rcheck; r != nil; r = (NilFlow*)uniqp(&r->f)) {
p = r->f.prog;
- proginfo(&info, p);
- if((info.flags & RightWrite) && sameaddr(&p->to, &rcheck->f.prog->from)) {
+ arch.proginfo(&info, p);
+ if((info.flags & RightWrite) && arch.sameaddr(&p->to, &rcheck->f.prog->from)) {
// Found initialization of value we're checking for nil.
// without first finding the check, so this one is unchecked.
return;
}
- if(r != rcheck && p->as == ACHECKNIL && sameaddr(&p->from, &rcheck->f.prog->from)) {
+ if(r != rcheck && p->as == ACHECKNIL && arch.sameaddr(&p->from, &rcheck->f.prog->from)) {
rcheck->kill = 1;
return;
}
// If same check, stop this loop but still check
// alternate predecessors up to this point.
- if(r1 != rcheck && p->as == ACHECKNIL && sameaddr(&p->from, &rcheck->f.prog->from))
+ if(r1 != rcheck && p->as == ACHECKNIL && arch.sameaddr(&p->from, &rcheck->f.prog->from))
break;
- proginfo(&info, p);
- if((info.flags & RightWrite) && sameaddr(&p->to, &rcheck->f.prog->from)) {
+ arch.proginfo(&info, p);
+ if((info.flags & RightWrite) && arch.sameaddr(&p->to, &rcheck->f.prog->from)) {
// Found initialization of value we're checking for nil.
// without first finding the check, so this one is unchecked.
rcheck->kill = 0;
if(r1->f.p1 == nil && r1->f.p2 == nil) {
print("lost pred for %P\n", rcheck->f.prog);
for(r1=r0; r1!=nil; r1=(NilFlow*)r1->f.p1) {
- proginfo(&info, r1->f.prog);
- print("\t%P %d %d %D %D\n", r1->f.prog, info.flags&RightWrite, sameaddr(&r1->f.prog->to, &rcheck->f.prog->from), &r1->f.prog->to, &rcheck->f.prog->from);
+ arch.proginfo(&info, r1->f.prog);
+ print("\t%P %d %d %D %D\n", r1->f.prog, info.flags&RightWrite, arch.sameaddr(&r1->f.prog->to, &rcheck->f.prog->from), &r1->f.prog->to, &rcheck->f.prog->from);
}
fatal("lost pred trail");
}
last = nil;
for(r = (NilFlow*)uniqs(&rcheck->f); r != nil; r = (NilFlow*)uniqs(&r->f)) {
p = r->f.prog;
- proginfo(&info, p);
+ arch.proginfo(&info, p);
- if((info.flags & LeftRead) && smallindir(&p->from, &rcheck->f.prog->from)) {
+ if((info.flags & LeftRead) && arch.smallindir(&p->from, &rcheck->f.prog->from)) {
rcheck->kill = 1;
return;
}
- if((info.flags & (RightRead|RightWrite)) && smallindir(&p->to, &rcheck->f.prog->from)) {
+ if((info.flags & (RightRead|RightWrite)) && arch.smallindir(&p->to, &rcheck->f.prog->from)) {
rcheck->kill = 1;
return;
}
if(p->as == ACHECKNIL)
return;
// Stop if value is lost.
- if((info.flags & RightWrite) && sameaddr(&p->to, &rcheck->f.prog->from))
+ if((info.flags & RightWrite) && arch.sameaddr(&p->to, &rcheck->f.prog->from))
return;
// Stop if memory write.
- if((info.flags & RightWrite) && !regtyp(&p->to))
+ if((info.flags & RightWrite) && !arch.regtyp(&p->to))
return;
// Stop if we jump backward.
// This test is valid because all the NilFlow* are pointers into
+++ /dev/null
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-typedef struct Flow Flow;
-typedef struct Graph Graph;
-
-struct Flow {
- Prog* prog; // actual instruction
- Flow* p1; // predecessors of this instruction: p1,
- Flow* p2; // and then p2 linked though p2link.
- Flow* p2link;
- Flow* s1; // successors of this instruction (at most two: s1 and s2).
- Flow* s2;
- Flow* link; // next instruction in function code
-
- int32 active; // usable by client
-
- int32 rpo; // reverse post ordering
- uint16 loop; // x5 for every loop
- uchar refset; // diagnostic generated
-};
-
-struct Graph
-{
- Flow* start;
- int num;
-
- // After calling flowrpo, rpo lists the flow nodes in reverse postorder,
- // and each non-dead Flow node f has g->rpo[f->rpo] == f.
- Flow** rpo;
-};
-
-void fixjmp(Prog*);
-Graph* flowstart(Prog*, int);
-void flowrpo(Graph*);
-void flowend(Graph*);
-void mergetemp(Prog*);
-void nilopt(Prog*);
-int noreturn(Prog*);
-int regtyp(Addr*);
-int sameaddr(Addr*, Addr*);
-int smallindir(Addr*, Addr*);
-int stackaddr(Addr*);
-Flow* uniqp(Flow*);
-Flow* uniqs(Flow*);
static int
callinstr(Node **np, NodeList **init, int wr, int skip)
{
+ char *name;
Node *f, *b, *n;
Type *t;
int class, hascalls;
n = treecopy(n);
makeaddable(n);
if(t->etype == TSTRUCT || isfixedarray(t)) {
- f = mkcall(wr ? "racewriterange" : "racereadrange", T, init, uintptraddr(n),
- nodintconst(t->width));
- } else
- f = mkcall(wr ? "racewrite" : "raceread", T, init, uintptraddr(n));
+ name = "racereadrange";
+ if(wr)
+ name = "racewriterange";
+ f = mkcall(name, T, init, uintptraddr(n), nodintconst(t->width));
+ } else {
+ name = "raceread";
+ if(wr)
+ name = "racewrite";
+ f = mkcall(name, T, init, uintptraddr(n));
+ }
*init = list(*init, f);
return 1;
}
Node *v1, *v2;
NodeList *ll;
+ // Typechecking order is important here:
+ // 0. first typecheck range expression (slice/map/chan),
+ // it is evaluated only once and so logically it is not part of the loop.
+ // 1. typcheck produced values,
+ // this part can declare new vars and so it must be typechecked before body,
+ // because body can contain a closure that captures the vars.
+ // 2. decldepth++ to denote loop body.
+ // 3. typecheck body.
+ // 4. decldepth--.
+
+ typecheck(&n->right, Erv);
+ if((t = n->right->type) == T)
+ goto out;
+
// delicate little dance. see typecheckas2
for(ll=n->list; ll; ll=ll->next)
if(ll->n->defn != n)
typecheck(&ll->n, Erv | Easgn);
- typecheck(&n->right, Erv);
- if((t = n->right->type) == T)
- goto out;
if(isptr[t->etype] && isfixedarray(t->type))
t = t->type;
n->type = t;
v1->type = t1;
else if(v1->type != T && assignop(t1, v1->type, &why) == 0)
yyerror("cannot assign type %T to %lN in range%s", t1, v1, why);
+ checkassign(n, v1);
}
if(v2) {
if(v2->defn == n)
v2->type = t2;
else if(v2->type != T && assignop(t2, v2->type, &why) == 0)
yyerror("cannot assign type %T to %lN in range%s", t2, v2, why);
+ checkassign(n, v2);
}
out:
- typechecklist(n->nbody, Etop);
-
// second half of dance
n->typecheck = 1;
for(ll=n->list; ll; ll=ll->next)
if(ll->n->typecheck == 0)
typecheck(&ll->n, Erv | Easgn);
+
+ decldepth++;
+ typechecklist(n->nbody, Etop);
+ decldepth--;
}
void
valuesfield->down = overflowfield;
overflowfield->down = T;
+ // See comment on hmap.overflow in ../../runtime/hashmap.go.
+ if(!haspointers(t->type) && !haspointers(t->down))
+ bucket->haspointers = 1; // no pointers
+
bucket->width = offset;
bucket->local = t->local;
t->bucket = bucket;
hmap(Type *t)
{
Type *h, *bucket;
- Type *bucketsfield, *oldbucketsfield;
+ Type *bucketsfield, *oldbucketsfield, *overflowfield;
int32 offset;
if(t->hmap != T)
h->noalg = 1;
offset = widthint; // count
- offset += 4; // flags
- offset += 4; // hash0
+ offset += 1; // flags
offset += 1; // B
+ offset += 2; // padding
+ offset += 4; // hash0
offset = (offset + widthptr - 1) / widthptr * widthptr;
bucketsfield = typ(TFIELD);
oldbucketsfield->sym->name = "oldbuckets";
offset += widthptr;
- offset += widthptr; // nevacuate (last field in Hmap)
+ offset += widthptr; // nevacuate
+
+ overflowfield = typ(TFIELD);
+ overflowfield->type = types[TUNSAFEPTR];
+ overflowfield->width = offset;
+ overflowfield->sym = mal(sizeof(Sym));
+ overflowfield->sym->name = "overflow";
+ offset += widthptr;
// link up fields
h->type = bucketsfield;
bucketsfield->down = oldbucketsfield;
- oldbucketsfield->down = T;
+ oldbucketsfield->down = overflowfield;
+ overflowfield->down = T;
h->width = offset;
h->local = t->local;
hiter(Type *t)
{
int32 n, off;
- Type *field[7];
+ Type *field[9];
Type *i;
if(t->hiter != T)
// h *Hmap
// buckets *Bucket
// bptr *Bucket
+ // overflow unsafe.Pointer
// other [4]uintptr
// }
// must match ../../runtime/hashmap.c:hash_iter.
field[5]->sym = mal(sizeof(Sym));
field[5]->sym->name = "bptr";
- // all other non-pointer fields
field[6] = typ(TFIELD);
- field[6]->type = typ(TARRAY);
- field[6]->type->type = types[TUINTPTR];
- field[6]->type->bound = 4;
- field[6]->type->width = 4 * widthptr;
+ field[6]->type = types[TUNSAFEPTR];
field[6]->sym = mal(sizeof(Sym));
- field[6]->sym->name = "other";
+ field[6]->sym->name = "overflow0";
+
+ field[7] = typ(TFIELD);
+ field[7]->type = types[TUNSAFEPTR];
+ field[7]->sym = mal(sizeof(Sym));
+ field[7]->sym->name = "overflow1";
+
+ // all other non-pointer fields
+ field[8] = typ(TFIELD);
+ field[8]->type = typ(TARRAY);
+ field[8]->type->type = types[TUINTPTR];
+ field[8]->type->bound = 4;
+ field[8]->type->width = 4 * widthptr;
+ field[8]->sym = mal(sizeof(Sym));
+ field[8]->sym->name = "other";
// build iterator struct holding the above fields
i = typ(TSTRUCT);
i->noalg = 1;
i->type = field[0];
off = 0;
- for(n = 0; n < 6; n++) {
+ for(n = 0; n < nelem(field)-1; n++) {
field[n]->down = field[n+1];
field[n]->width = off;
off += field[n]->type->width;
}
- field[6]->down = T;
- off += field[6]->type->width;
- if(off != 10 * widthptr)
- yyerror("hash_iter size not correct %d %d", off, 10 * widthptr);
+ field[nelem(field)-1]->down = T;
+ off += field[nelem(field)-1]->type->width;
+ if(off != 12 * widthptr)
+ yyerror("hash_iter size not correct %d %d", off, 11 * widthptr);
t->hiter = i;
i->map = t;
return i;
return;
if(gopkg == nil) {
- gopkg = mkpkg(strlit("go"));
+ gopkg = mkpkg(newstrlit("go"));
gopkg->name = "go";
}
nam = smprint("importpath.%s.", p->prefix);
n->xoffset = 0;
p->pathsym = n->sym;
- gdatastring(n, p->path);
- ggloblsym(n->sym, types[TSTRING]->width, DUPOK|RODATA);
+ arch.gdatastring(n, p->path);
+ arch.ggloblsym(n->sym, types[TSTRING]->width, DUPOK|RODATA);
}
static int
dgopkgpath(Sym *s, int ot, Pkg *pkg)
{
if(pkg == nil)
- return dgostringptr(s, ot, nil);
+ return arch.dgostringptr(s, ot, nil);
// Emit reference to go.importpath.""., which 6l will
// rewrite using the correct import path. Every package
static Sym *ns;
if(ns == nil)
- ns = pkglookup("importpath.\"\".", mkpkg(strlit("go")));
- return dsymptr(s, ot, ns, 0);
+ ns = pkglookup("importpath.\"\".", mkpkg(newstrlit("go")));
+ return arch.dsymptr(s, ot, ns, 0);
}
dimportpath(pkg);
- return dsymptr(s, ot, pkg->pathsym, 0);
+ return arch.dsymptr(s, ot, pkg->pathsym, 0);
}
/*
// fill in *extraType pointer in header
off = rnd(off, widthptr);
- dsymptr(sym, ptroff, sym, off);
+ arch.dsymptr(sym, ptroff, sym, off);
n = 0;
for(a=m; a; a=a->link) {
ot = off;
s = sym;
if(t->sym) {
- ot = dgostringptr(s, ot, t->sym->name);
+ ot = arch.dgostringptr(s, ot, t->sym->name);
if(t != types[t->etype] && t != errortype)
ot = dgopkgpath(s, ot, t->sym->pkg);
else
- ot = dgostringptr(s, ot, nil);
+ ot = arch.dgostringptr(s, ot, nil);
} else {
- ot = dgostringptr(s, ot, nil);
- ot = dgostringptr(s, ot, nil);
+ ot = arch.dgostringptr(s, ot, nil);
+ ot = arch.dgostringptr(s, ot, nil);
}
// slice header
- ot = dsymptr(s, ot, s, ot + widthptr + 2*widthint);
+ ot = arch.dsymptr(s, ot, s, ot + widthptr + 2*widthint);
ot = duintxx(s, ot, n, widthint);
ot = duintxx(s, ot, n, widthint);
for(a=m; a; a=a->link) {
// method
// ../../runtime/type.go:/method
- ot = dgostringptr(s, ot, a->name);
+ ot = arch.dgostringptr(s, ot, a->name);
ot = dgopkgpath(s, ot, a->pkg);
- ot = dsymptr(s, ot, dtypesym(a->mtype), 0);
- ot = dsymptr(s, ot, dtypesym(a->type), 0);
+ ot = arch.dsymptr(s, ot, dtypesym(a->mtype), 0);
+ ot = arch.dsymptr(s, ot, dtypesym(a->type), 0);
if(a->isym)
- ot = dsymptr(s, ot, a->isym, 0);
+ ot = arch.dsymptr(s, ot, a->isym, 0);
else
ot = duintptr(s, ot, 0);
if(a->tsym)
- ot = dsymptr(s, ot, a->tsym, 0);
+ ot = arch.dsymptr(s, ot, a->tsym, 0);
else
ot = duintptr(s, ot, 0);
}
i |= KindGCProg;
ot = duint8(s, ot, i); // kind
if(algsym == S)
- ot = dsymptr(s, ot, algarray, alg*sizeofAlg);
+ ot = arch.dsymptr(s, ot, algarray, alg*sizeofAlg);
else
- ot = dsymptr(s, ot, algsym, 0);
+ ot = arch.dsymptr(s, ot, algsym, 0);
// gc
if(gcprog) {
gengcprog(t, &gcprog0, &gcprog1);
if(gcprog0 != S)
- ot = dsymptr(s, ot, gcprog0, 0);
+ ot = arch.dsymptr(s, ot, gcprog0, 0);
else
ot = duintptr(s, ot, 0);
- ot = dsymptr(s, ot, gcprog1, 0);
+ ot = arch.dsymptr(s, ot, gcprog1, 0);
} else {
gengcmask(t, gcmask);
x1 = 0;
sbits->flags |= SymUniq;
for(i = 0; i < 2*widthptr; i++)
duint8(sbits, i, gcmask[i]);
- ggloblsym(sbits, 2*widthptr, DUPOK|RODATA);
+ arch.ggloblsym(sbits, 2*widthptr, DUPOK|RODATA);
}
- ot = dsymptr(s, ot, sbits, 0);
+ ot = arch.dsymptr(s, ot, sbits, 0);
ot = duintptr(s, ot, 0);
}
p = smprint("%-uT", t);
//print("dcommontype: %s\n", p);
- ot = dgostringptr(s, ot, p); // string
+ ot = arch.dgostringptr(s, ot, p); // string
free(p);
// skip pointer to extraType,
// otherwise linker will assume 0.
ot += widthptr;
- ot = dsymptr(s, ot, sptr, 0); // ptrto type
- ot = dsymptr(s, ot, zero, 0); // ptr to zero value
+ ot = arch.dsymptr(s, ot, sptr, 0); // ptrto type
+ ot = arch.dsymptr(s, ot, zero, 0); // ptr to zero value
return ot;
}
s2 = dtypesym(t2);
ot = dcommontype(s, ot, t);
xt = ot - 3*widthptr;
- ot = dsymptr(s, ot, s1, 0);
- ot = dsymptr(s, ot, s2, 0);
+ ot = arch.dsymptr(s, ot, s1, 0);
+ ot = arch.dsymptr(s, ot, s2, 0);
ot = duintptr(s, ot, t->bound);
} else {
// ../../runtime/type.go:/SliceType
s1 = dtypesym(t->type);
ot = dcommontype(s, ot, t);
xt = ot - 3*widthptr;
- ot = dsymptr(s, ot, s1, 0);
+ ot = arch.dsymptr(s, ot, s1, 0);
}
break;
s1 = dtypesym(t->type);
ot = dcommontype(s, ot, t);
xt = ot - 3*widthptr;
- ot = dsymptr(s, ot, s1, 0);
+ ot = arch.dsymptr(s, ot, s1, 0);
ot = duintptr(s, ot, t->chan);
break;
// two slice headers: in and out.
ot = rnd(ot, widthptr);
- ot = dsymptr(s, ot, s, ot+2*(widthptr+2*widthint));
+ ot = arch.dsymptr(s, ot, s, ot+2*(widthptr+2*widthint));
n = t->thistuple + t->intuple;
ot = duintxx(s, ot, n, widthint);
ot = duintxx(s, ot, n, widthint);
- ot = dsymptr(s, ot, s, ot+1*(widthptr+2*widthint)+n*widthptr);
+ ot = arch.dsymptr(s, ot, s, ot+1*(widthptr+2*widthint)+n*widthptr);
ot = duintxx(s, ot, t->outtuple, widthint);
ot = duintxx(s, ot, t->outtuple, widthint);
// slice data
for(t1=getthisx(t)->type; t1; t1=t1->down, n++)
- ot = dsymptr(s, ot, dtypesym(t1->type), 0);
+ ot = arch.dsymptr(s, ot, dtypesym(t1->type), 0);
for(t1=getinargx(t)->type; t1; t1=t1->down, n++)
- ot = dsymptr(s, ot, dtypesym(t1->type), 0);
+ ot = arch.dsymptr(s, ot, dtypesym(t1->type), 0);
for(t1=getoutargx(t)->type; t1; t1=t1->down, n++)
- ot = dsymptr(s, ot, dtypesym(t1->type), 0);
+ ot = arch.dsymptr(s, ot, dtypesym(t1->type), 0);
break;
case TINTER:
// ../../runtime/type.go:/InterfaceType
ot = dcommontype(s, ot, t);
xt = ot - 3*widthptr;
- ot = dsymptr(s, ot, s, ot+widthptr+2*widthint);
+ ot = arch.dsymptr(s, ot, s, ot+widthptr+2*widthint);
ot = duintxx(s, ot, n, widthint);
ot = duintxx(s, ot, n, widthint);
for(a=m; a; a=a->link) {
// ../../runtime/type.go:/imethod
- ot = dgostringptr(s, ot, a->name);
+ ot = arch.dgostringptr(s, ot, a->name);
ot = dgopkgpath(s, ot, a->pkg);
- ot = dsymptr(s, ot, dtypesym(a->type), 0);
+ ot = arch.dsymptr(s, ot, dtypesym(a->type), 0);
}
break;
s4 = dtypesym(hmap(t));
ot = dcommontype(s, ot, t);
xt = ot - 3*widthptr;
- ot = dsymptr(s, ot, s1, 0);
- ot = dsymptr(s, ot, s2, 0);
- ot = dsymptr(s, ot, s3, 0);
- ot = dsymptr(s, ot, s4, 0);
+ ot = arch.dsymptr(s, ot, s1, 0);
+ ot = arch.dsymptr(s, ot, s2, 0);
+ ot = arch.dsymptr(s, ot, s3, 0);
+ ot = arch.dsymptr(s, ot, s4, 0);
if(t->down->width > MAXKEYSIZE) {
ot = duint8(s, ot, widthptr);
ot = duint8(s, ot, 1); // indirect
s1 = dtypesym(t->type);
ot = dcommontype(s, ot, t);
xt = ot - 3*widthptr;
- ot = dsymptr(s, ot, s1, 0);
+ ot = arch.dsymptr(s, ot, s1, 0);
break;
case TSTRUCT:
}
ot = dcommontype(s, ot, t);
xt = ot - 3*widthptr;
- ot = dsymptr(s, ot, s, ot+widthptr+2*widthint);
+ ot = arch.dsymptr(s, ot, s, ot+widthptr+2*widthint);
ot = duintxx(s, ot, n, widthint);
ot = duintxx(s, ot, n, widthint);
for(t1=t->type; t1!=T; t1=t1->down) {
// ../../runtime/type.go:/structField
if(t1->sym && !t1->embedded) {
- ot = dgostringptr(s, ot, t1->sym->name);
+ ot = arch.dgostringptr(s, ot, t1->sym->name);
if(exportname(t1->sym->name))
- ot = dgostringptr(s, ot, nil);
+ ot = arch.dgostringptr(s, ot, nil);
else
ot = dgopkgpath(s, ot, t1->sym->pkg);
} else {
- ot = dgostringptr(s, ot, nil);
+ ot = arch.dgostringptr(s, ot, nil);
if(t1->type->sym != S && t1->type->sym->pkg == builtinpkg)
ot = dgopkgpath(s, ot, localpkg);
else
- ot = dgostringptr(s, ot, nil);
+ ot = arch.dgostringptr(s, ot, nil);
}
- ot = dsymptr(s, ot, dtypesym(t1->type), 0);
- ot = dgostrlitptr(s, ot, t1->note);
+ ot = arch.dsymptr(s, ot, dtypesym(t1->type), 0);
+ ot = arch.dgostrlitptr(s, ot, t1->note);
ot = duintptr(s, ot, t1->width); // field offset
}
break;
}
ot = dextratype(s, ot, t, xt);
- ggloblsym(s, ot, dupok|RODATA);
+ arch.ggloblsym(s, ot, dupok|RODATA);
// generate typelink.foo pointing at s = type.foo.
// The linker will leave a table of all the typelinks for
case TCHAN:
case TMAP:
slink = typelinksym(t);
- dsymptr(slink, 0, s, 0);
- ggloblsym(slink, widthptr, dupok|RODATA);
+ arch.dsymptr(slink, 0, s, 0);
+ arch.ggloblsym(slink, widthptr, dupok|RODATA);
}
}
dimportpath(runtimepkg);
if(flag_race)
dimportpath(racepkg);
- dimportpath(mkpkg(strlit("main")));
+ dimportpath(mkpkg(newstrlit("main")));
}
}
hashfunc = pkglookup(p, typepkg);
free(p);
ot = 0;
- ot = dsymptr(hashfunc, ot, pkglookup("memhash_varlen", runtimepkg), 0);
+ ot = arch.dsymptr(hashfunc, ot, pkglookup("memhash_varlen", runtimepkg), 0);
ot = duintxx(hashfunc, ot, t->width, widthptr); // size encoded in closure
- ggloblsym(hashfunc, ot, DUPOK|RODATA);
+ arch.ggloblsym(hashfunc, ot, DUPOK|RODATA);
// make equality closure
p = smprint(".eqfunc%lld", t->width);
eqfunc = pkglookup(p, typepkg);
free(p);
ot = 0;
- ot = dsymptr(eqfunc, ot, pkglookup("memequal_varlen", runtimepkg), 0);
+ ot = arch.dsymptr(eqfunc, ot, pkglookup("memequal_varlen", runtimepkg), 0);
ot = duintxx(eqfunc, ot, t->width, widthptr);
- ggloblsym(eqfunc, ot, DUPOK|RODATA);
+ arch.ggloblsym(eqfunc, ot, DUPOK|RODATA);
} else {
// generate an alg table specific to this type
s = typesymprefix(".alg", t);
geneq(eq, t);
// make Go funcs (closures) for calling hash and equal from Go
- dsymptr(hashfunc, 0, hash, 0);
- ggloblsym(hashfunc, widthptr, DUPOK|RODATA);
- dsymptr(eqfunc, 0, eq, 0);
- ggloblsym(eqfunc, widthptr, DUPOK|RODATA);
+ arch.dsymptr(hashfunc, 0, hash, 0);
+ arch.ggloblsym(hashfunc, widthptr, DUPOK|RODATA);
+ arch.dsymptr(eqfunc, 0, eq, 0);
+ arch.ggloblsym(eqfunc, widthptr, DUPOK|RODATA);
}
// ../../runtime/alg.go:/typeAlg
ot = 0;
- ot = dsymptr(s, ot, hashfunc, 0);
- ot = dsymptr(s, ot, eqfunc, 0);
- ggloblsym(s, ot, DUPOK|RODATA);
+ ot = arch.dsymptr(s, ot, hashfunc, 0);
+ ot = arch.dsymptr(s, ot, eqfunc, 0);
+ arch.ggloblsym(s, ot, DUPOK|RODATA);
return s;
}
// Unfold the mask for the GC bitmap format:
// 4 bits per word, 2 high bits encode pointer info.
- pos = (uint8*)gcmask;
+ pos = gcmask;
nptr = (t->width+widthptr-1)/widthptr;
half = 0;
// If number of words is odd, repeat the mask.
// Don't generate it if it's too large, runtime will unroll directly into GC bitmap.
if(size <= MaxGCMask) {
gc0 = typesymprefix(".gc", t);
- ggloblsym(gc0, size, DUPOK|NOPTR);
+ arch.ggloblsym(gc0, size, DUPOK|NOPTR);
*pgc0 = gc0;
}
xoffset = 0;
gengcprog1(&g, t, &xoffset);
ot = proggenfini(&g);
- ggloblsym(gc1, ot, DUPOK|RODATA);
+ arch.ggloblsym(gc1, ot, DUPOK|RODATA);
*pgc1 = gc1;
}
func printlock()
func printunlock()
-func concatstring2(string, string) string
-func concatstring3(string, string, string) string
-func concatstring4(string, string, string, string) string
-func concatstring5(string, string, string, string, string) string
-func concatstrings([]string) string
+func concatstring2(*[32]byte, string, string) string
+func concatstring3(*[32]byte, string, string, string) string
+func concatstring4(*[32]byte, string, string, string, string) string
+func concatstring5(*[32]byte, string, string, string, string, string) string
+func concatstrings(*[32]byte, []string) string
func cmpstring(string, string) int
func eqstring(string, string) bool
-func intstring(int64) string
-func slicebytetostring([]byte) string
+func intstring(*[4]byte, int64) string
+func slicebytetostring(*[32]byte, []byte) string
func slicebytetostringtmp([]byte) string
func slicerunetostring([]rune) string
func stringtoslicebyte(string) []byte
+func stringtoslicebytetmp(string) []byte
func stringtoslicerune(string) []rune
func stringiter(string, int) int
func stringiter2(string, int) (retk int, retv rune)
case OLITERAL:
if(iszero(r))
return 1;
- gdata(l, r, l->type->width);
+ arch.gdata(l, r, l->type->width);
return 1;
case OADDR:
switch(r->left->op) {
case ONAME:
- gdata(l, r, l->type->width);
+ arch.gdata(l, r, l->type->width);
return 1;
}
break;
case OSTRUCTLIT:
case OMAPLIT:
// copy pointer
- gdata(l, nod(OADDR, r->nname, N), l->type->width);
+ arch.gdata(l, nod(OADDR, r->nname, N), l->type->width);
return 1;
}
break;
a = r->nname;
n1 = *l;
n1.xoffset = l->xoffset + Array_array;
- gdata(&n1, nod(OADDR, a, N), widthptr);
+ arch.gdata(&n1, nod(OADDR, a, N), widthptr);
n1.xoffset = l->xoffset + Array_nel;
- gdata(&n1, r->right, widthint);
+ arch.gdata(&n1, r->right, widthint);
n1.xoffset = l->xoffset + Array_cap;
- gdata(&n1, r->right, widthint);
+ arch.gdata(&n1, r->right, widthint);
return 1;
}
// fall through
n1.xoffset = l->xoffset + e->xoffset;
n1.type = e->expr->type;
if(e->expr->op == OLITERAL)
- gdata(&n1, e->expr, n1.type->width);
+ arch.gdata(&n1, e->expr, n1.type->width);
else {
ll = nod(OXXX, N, N);
*ll = n1;
case OLITERAL:
if(iszero(r))
return 1;
- gdata(l, r, l->type->width);
+ arch.gdata(l, r, l->type->width);
return 1;
case OADDR:
if(stataddr(&nam, r->left)) {
n1 = *r;
n1.left = &nam;
- gdata(l, &n1, l->type->width);
+ arch.gdata(l, &n1, l->type->width);
return 1;
}
// Init pointer.
a = staticname(r->left->type, 1);
r->nname = a;
- gdata(l, nod(OADDR, a, N), l->type->width);
+ arch.gdata(l, nod(OADDR, a, N), l->type->width);
// Init underlying literal.
if(!staticassign(a, r->left, out))
*out = list(*out, nod(OAS, a, r->left));
r->nname = a;
n1 = *l;
n1.xoffset = l->xoffset + Array_array;
- gdata(&n1, nod(OADDR, a, N), widthptr);
+ arch.gdata(&n1, nod(OADDR, a, N), widthptr);
n1.xoffset = l->xoffset + Array_nel;
- gdata(&n1, r->right, widthint);
+ arch.gdata(&n1, r->right, widthint);
n1.xoffset = l->xoffset + Array_cap;
- gdata(&n1, r->right, widthint);
+ arch.gdata(&n1, r->right, widthint);
// Fall through to init underlying array.
l = a;
}
n1.xoffset = l->xoffset + e->xoffset;
n1.type = e->expr->type;
if(e->expr->op == OLITERAL)
- gdata(&n1, e->expr, n1.type->width);
+ arch.gdata(&n1, e->expr, n1.type->width);
else {
a = nod(OXXX, N, N);
*a = n1;
if(l < 0)
break;
// Check for overflow.
- if(n->type->width != 0 && MAXWIDTH/n->type->width <= l)
+ if(n->type->width != 0 && arch.MAXWIDTH/n->type->width <= l)
break;
nam->xoffset += l*n->type->width;
nam->type = n->type;
case TPTR64:
case TFLOAT32:
case TFLOAT64:
- gdata(&nam, nr, nr->type->width);
+ arch.gdata(&nam, nr, nr->type->width);
break;
case TCOMPLEX64:
case TCOMPLEX128:
- gdatacomplex(&nam, nr->val.u.cval);
+ arch.gdatacomplex(&nam, nr->val.u.cval);
break;
case TSTRING:
- gdatastring(&nam, nr->val.u.sval);
+ arch.gdatastring(&nam, nr->val.u.sval);
break;
}
return 1;
slice:
- gused(N); // in case the data is the dest of a goto
+ arch.gused(N); // in case the data is the dest of a goto
nl = nr;
if(nr == N || nr->op != OADDR)
goto no;
goto no;
nam.xoffset += Array_array;
- gdata(&nam, nl, types[tptr]->width);
+ arch.gdata(&nam, nl, types[tptr]->width);
nam.xoffset += Array_nel-Array_array;
nodconst(&nod1, types[TINT], nr->type->bound);
- gdata(&nam, &nod1, widthint);
+ arch.gdata(&nam, &nod1, widthint);
nam.xoffset += Array_cap-Array_nel;
- gdata(&nam, &nod1, widthint);
+ arch.gdata(&nam, &nod1, widthint);
goto yes;
methcmp(const void *va, const void *vb)
{
Type *a, *b;
- int i;
+ int k;
a = *(Type**)va;
b = *(Type**)vb;
return -1;
if(b->sym == S)
return 1;
- i = strcmp(a->sym->name, b->sym->name);
- if(i != 0)
- return i;
+ k = strcmp(a->sym->name, b->sym->name);
+ if(k != 0)
+ return k;
if(!exportname(a->sym->name)) {
- i = strcmp(a->sym->pkg->path->s, b->sym->pkg->path->s);
- if(i != 0)
- return i;
+ k = strcmp(a->sym->pkg->path->s, b->sym->pkg->path->s);
+ if(k != 0)
+ return k;
}
return 0;
}
case OLE: return OGT;
case OGE: return OLT;
}
- fatal("brcom: no com for %A\n", a);
+ fatal("brcom: no com for %O\n", a);
return a;
}
case OLE: return OGE;
case OGE: return OLE;
}
- fatal("brcom: no rev for %A\n", a);
+ fatal("brcom: no rev for %O\n", a);
return a;
}
dowidth(t);
w = t->argwid;
- if(w >= MAXWIDTH)
+ if(w >= arch.MAXWIDTH)
fatal("bad argwid %T", t);
w += extra;
- if(w >= MAXWIDTH)
+ if(w >= arch.MAXWIDTH)
fatal("bad argwid %d + %T", extra, t);
if(w > maxarg)
maxarg = w;
// so no space cost to use them here.
l = nil;
v.ctype = CTSTR;
- v.u.sval = strlit(rcvr->type->sym->pkg->name); // package name
+ v.u.sval = newstrlit(rcvr->type->sym->pkg->name); // package name
l = list(l, nodlit(v));
- v.u.sval = strlit(rcvr->type->sym->name); // type name
+ v.u.sval = newstrlit(rcvr->type->sym->name); // type name
l = list(l, nodlit(v));
- v.u.sval = strlit(method->sym->name);
+ v.u.sval = newstrlit(method->sym->name);
l = list(l, nodlit(v)); // method name
call = nod(OCALL, syslook("panicwrap", 0), N);
call->list = l;
fn->dupok = 1;
typecheck(&fn, Etop);
typechecklist(fn->nbody, Etop);
+
+ // Set inl_nonlocal to whether we are calling a method on a
+ // type defined in a different package. Checked in inlvar.
+ if(!methodrcvr->local)
+ inl_nonlocal = 1;
+
inlcalls(fn);
+
+ inl_nonlocal = 0;
+
curfn = nil;
funccompile(fn, 0);
}
}
Strlit*
-strlit(char *s)
+newstrlit(char *s)
{
Strlit *t;
// multiple entry type switch or default
nvar->ntype = typenod(n->type);
}
+ typecheck(&nvar, Erv | Easgn);
+ ncase->nname = nvar;
}
}
typechecklist(ncase->nbody, Etop);
static void typecheckas(Node*);
static void typecheckfunc(Node*);
static void checklvalue(Node*, char*);
-static void checkassign(Node*);
-static void checkassignlist(NodeList*);
+static void checkassignlist(Node*, NodeList*);
static void stringtoarraylit(Node**);
static Node* resolve(Node*);
static void checkdefergo(Node*);
goto ret;
case ONAME:
+ if(n->decldepth == 0)
+ n->decldepth = decldepth;
if(n->etype != 0) {
ok |= Ecall;
goto ret;
case OASOP:
ok |= Etop;
l = typecheck(&n->left, Erv);
- checkassign(n->left);
r = typecheck(&n->right, Erv);
+ checkassign(n, n->left);
if(l->type == T || r->type == T)
goto error;
op = n->etype;
l->typecheck = 1;
n->left = l;
t = l->type;
- } else if(l->type->etype != TBLANK && (aop = assignop(r->type, l->type, nil)) != 0) {
+ goto converted;
+ }
+ if(l->type->etype != TBLANK && (aop = assignop(r->type, l->type, nil)) != 0) {
if(isinter(l->type) && !isinter(r->type) && algtype1(r->type, nil) == ANOEQ) {
yyerror("invalid operation: %N (operator %O not defined on %s)", n, op, typekind(r->type));
goto error;
n->right = r;
t = r->type;
}
+ converted:
et = t->etype;
}
if(t->etype != TIDEAL && !eqtype(l->type, r->type)) {
goto error;
checklvalue(n->left, "take the address of");
r = outervalue(n->left);
- for(l = n->left; l != r; l = l->left)
+ for(l = n->left; l != r; l = l->left) {
l->addrtaken = 1;
+ if(l->closure)
+ l->closure->addrtaken = 1;
+ }
if(l->orig != l && l->op == ONAME)
fatal("found non-orig name node %N", l);
l->addrtaken = 1;
+ if(l->closure)
+ l->closure->addrtaken = 1;
defaultlit(&n->left, T);
l = n->left;
if((t = l->type) == T)
goto error;
// Unpack multiple-return result before type-checking.
- if(istype(t, TSTRUCT)) {
+ if(istype(t, TSTRUCT) && t->funarg) {
t = t->type;
if(istype(t, TFIELD))
t = t->type;
case OAS:
ok |= Etop;
typecheckas(n);
+ // Code that creates temps does not bother to set defn, so do it here.
+ if(n->left->op == ONAME && strncmp(n->left->sym->name, "autotmp_", 8) == 0)
+ n->left->defn = n;
goto ret;
case OAS2:
case ODCL:
case OEMPTY:
case OGOTO:
- case OLABEL:
case OXFALL:
case OVARKILL:
ok |= Etop;
goto ret;
+ case OLABEL:
+ ok |= Etop;
+ decldepth++;
+ goto ret;
+
case ODEFER:
ok |= Etop;
typecheck(&n->left, Etop|Erv);
case OFOR:
ok |= Etop;
typechecklist(n->ninit, Etop);
+ decldepth++;
typecheck(&n->ntest, Erv);
if(n->ntest != N && (t = n->ntest->type) != T && t->etype != TBOOL)
yyerror("non-bool %lN used as for condition", n->ntest);
typecheck(&n->nincr, Etop);
typechecklist(n->nbody, Etop);
+ decldepth--;
goto ret;
case OIF:
*/
static void
-fielddup(Node *n, Node *hash[], ulong nhash)
+fielddup(Node *n, Node **hash, ulong nhash)
{
uint h;
char *s;
}
static void
-keydup(Node *n, Node *hash[], ulong nhash)
+keydup(Node *n, Node **hash, ulong nhash)
{
uint h;
ulong b;
}
static void
-indexdup(Node *n, Node *hash[], ulong nhash)
+indexdup(Node *n, Node **hash, ulong nhash)
{
uint h;
Node *a;
typecheckcomplit(Node **np)
{
int bad, i, nerr;
- int64 len;
+ int64 length;
Node *l, *n, *norig, *r, **hash;
NodeList *ll;
Type *t, *f;
case TARRAY:
nhash = inithash(n, &hash, autohash, nelem(autohash));
- len = 0;
+ length = 0;
i = 0;
for(ll=n->list; ll; ll=ll->next) {
l = ll->n;
if(i >= 0)
indexdup(l->left, hash, nhash);
i++;
- if(i > len) {
- len = i;
- if(t->bound >= 0 && len > t->bound) {
+ if(i > length) {
+ length = i;
+ if(t->bound >= 0 && length > t->bound) {
setlineno(l);
- yyerror("array index %lld out of bounds [0:%lld]", len-1, t->bound);
+ yyerror("array index %lld out of bounds [0:%lld]", length-1, t->bound);
t->bound = -1; // no more errors
}
}
l->right = assignconv(r, t->type, "array element");
}
if(t->bound == -100)
- t->bound = len;
+ t->bound = length;
if(t->bound < 0)
- n->right = nodintconst(len);
+ n->right = nodintconst(length);
n->op = OARRAYLIT;
break;
yyerror("cannot %s %N", verb, n);
}
-static void
-checkassign(Node *n)
+void
+checkassign(Node *stmt, Node *n)
{
+ Node *r, *l;
+
+ // Variables declared in ORANGE are assigned on every iteration.
+ if(n->defn != stmt || stmt->op == ORANGE) {
+ r = outervalue(n);
+ for(l = n; l != r; l = l->left) {
+ l->assigned = 1;
+ if(l->closure)
+ l->closure->assigned = 1;
+ }
+ l->assigned = 1;
+ if(l->closure)
+ l->closure->assigned = 1;
+ }
+
if(islvalue(n))
return;
if(n->op == OINDEXMAP) {
}
static void
-checkassignlist(NodeList *l)
+checkassignlist(Node *stmt, NodeList *l)
{
for(; l; l=l->next)
- checkassign(l->n);
+ checkassign(stmt, l->n);
}
// Check whether l and r are the same side effect-free expression,
if(n->left->defn != n || n->left->ntype)
typecheck(&n->left, Erv | Easgn);
- checkassign(n->left);
typecheck(&n->right, Erv);
+ checkassign(n, n->left);
if(n->right && n->right->type != T) {
if(n->left->type != T)
n->right = assignconv(n->right, n->left->type, "assignment");
}
cl = count(n->list);
cr = count(n->rlist);
- checkassignlist(n->list);
if(cl > 1 && cr == 1)
typecheck(&n->rlist->n, Erv | Efnstruct);
else
typechecklist(n->rlist, Erv);
+ checkassignlist(n, n->list);
if(cl == cr) {
// easy
typecheckfunc(Node *n)
{
Type *t, *rcvr;
+ NodeList *l;
typecheck(&n->nname, Erv | Easgn);
if((t = n->nname->type) == T)
rcvr = getthisx(t)->type;
if(rcvr != nil && n->shortname != N && !isblank(n->shortname))
addmethod(n->shortname->sym, t, 1, n->nname->nointerface);
+
+ for(l=n->dcl; l; l=l->next)
+ if(l->n->op == ONAME && (l->n->class == PPARAM || l->n->class == PPARAMOUT))
+ l->n->decldepth = 1;
}
static void
fn = nn->left;
args = nn->list;
- if(safemode || fn == N || fn->op != ONAME || (s = fn->sym) == S)
+ if(safemode || fn == N || fn->op != ONAME)
+ goto no;
+ if((s = fn->sym) == S)
goto no;
if(s->pkg != unsafepkg)
goto no;
static Mpint mpzero;
static void walkprintfunc(Node**, NodeList**);
+// The constant is known to runtime.
+enum
+{
+ tmpstringbufsize = 32,
+};
+
void
walk(Node *fn)
{
int32 lno;
Node *n, *fn, *n1, *n2;
Sym *sym;
- char buf[100], *p;
+ char buf[100], *p, *from, *to;
n = *np;
n1 = nod(OADDR, n->left, N);
r = n->right; // i.(T)
- strcpy(buf, "assertI2T");
+ from = "I";
+ to = "T";
if(isnilinter(r->left->type))
- buf[6] = 'E';
+ from = "E";
if(isnilinter(r->type))
- buf[8] = 'E';
+ to = "E";
else if(isinter(r->type))
- buf[8] = 'I';
+ to = "I";
+ snprint(buf, sizeof buf, "assert%s2%s", from, to);
+
fn = syslook(buf, 1);
argtype(fn, r->left->type);
argtype(fn, r->type);
n1 = nod(OADDR, n->list->n, N);
n1->etype = 1; // addr does not escape
- strcpy(buf, "assertI2T2");
+ from = "I";
+ to = "T";
if(isnilinter(r->left->type))
- buf[6] = 'E';
+ from = "E";
if(isnilinter(r->type))
- buf[8] = 'E';
+ to = "E";
else if(isinter(r->type))
- buf[8] = 'I';
+ to = "I";
+ snprint(buf, sizeof buf, "assert%s2%s2", from, to);
fn = syslook(buf, 1);
argtype(fn, r->left->type);
case OCONVIFACE:
walkexpr(&n->left, init);
- // Optimize convT2E as a two-word copy when T is uintptr-shaped.
- if(isnilinter(n->type) && isdirectiface(n->left->type) && n->left->type->width == widthptr && isint[simsimtype(n->left->type)]) {
+ // Optimize convT2E as a two-word copy when T is pointer-shaped.
+ if(isnilinter(n->type) && isdirectiface(n->left->type)) {
l = nod(OEFACE, typename(n->left->type), n->left);
l->type = n->type;
l->typecheck = n->typecheck;
// Build name of function: convI2E etc.
// Not all names are possible
// (e.g., we'll never generate convE2E or convE2I).
- strcpy(buf, "conv");
- p = buf+strlen(buf);
+ from = "T";
+ to = "I";
if(isnilinter(n->left->type))
- *p++ = 'E';
+ from = "E";
else if(isinter(n->left->type))
- *p++ = 'I';
- else
- *p++ = 'T';
- *p++ = '2';
+ from = "I";
if(isnilinter(n->type))
- *p++ = 'E';
- else
- *p++ = 'I';
- *p = '\0';
+ to = "E";
+ snprint(buf, sizeof buf, "conv%s2%s", from, to);
fn = syslook(buf, 1);
ll = nil;
l->class = PEXTERN;
l->xoffset = 0;
sym->def = l;
- ggloblsym(sym, widthptr, DUPOK|NOPTR);
+ arch.ggloblsym(sym, widthptr, DUPOK|NOPTR);
}
l = nod(OADDR, sym->def, N);
l->addable = 1;
ll = list(ll, l);
- if(isdirectiface(n->left->type) && n->left->type->width == widthptr && isint[simsimtype(n->left->type)]) {
+ if(isdirectiface(n->left->type)) {
/* For pointer types, we can make a special form of optimization
*
* These statements are put onto the expression init list:
case OCONV:
case OCONVNOP:
- if(thechar == '5') {
+ if(arch.thechar == '5') {
if(isfloat[n->left->type->etype]) {
if(n->type->etype == TINT64) {
n = mkcall("float64toint64", n->type, init, conv(n->left, types[TFLOAT64]));
goto ret;
case ORUNESTR:
- // sys_intstring(v)
- n = mkcall("intstring", n->type, init,
- conv(n->left, types[TINT64]));
+ a = nodnil();
+ if(n->esc == EscNone) {
+ t = aindex(nodintconst(4), types[TUINT8]);
+ var = temp(t);
+ a = nod(OADDR, var, N);
+ }
+ // intstring(*[4]byte, rune)
+ n = mkcall("intstring", n->type, init, a, conv(n->left, types[TINT64]));
goto ret;
case OARRAYBYTESTR:
- // slicebytetostring([]byte) string;
- n = mkcall("slicebytetostring", n->type, init, n->left);
+ a = nodnil();
+ if(n->esc == EscNone) {
+ // Create temporary buffer for string on stack.
+ t = aindex(nodintconst(tmpstringbufsize), types[TUINT8]);
+ a = nod(OADDR, temp(t), N);
+ }
+ // slicebytetostring(*[32]byte, []byte) string;
+ n = mkcall("slicebytetostring", n->type, init, a, n->left);
goto ret;
case OARRAYBYTESTRTMP:
n = mkcall("stringtoslicebyte", n->type, init, conv(n->left, types[TSTRING]));
goto ret;
+ case OSTRARRAYBYTETMP:
+ // stringtoslicebytetmp(string) []byte;
+ n = mkcall("stringtoslicebytetmp", n->type, init, conv(n->left, types[TSTRING]));
+ goto ret;
+
case OSTRARRAYRUNE:
// stringtoslicerune(string) []rune
n = mkcall("stringtoslicerune", n->type, init, n->left);
l = tmp;
}
- a = nod(OAS, l, nodarg(r, fp));
+ a = nod(OAS, l, arch.nodarg(r, fp));
a = convas(a, init);
ullmancalc(a);
if(a->ullman >= UINF) {
walkexpr(&n, init);
}
- a = nod(OAS, nodarg(l, fp), n);
+ a = nod(OAS, arch.nodarg(l, fp), n);
nn = list(nn, convas(a, init));
return nn;
}
if(r != N && lr->next == nil && r->type->etype == TSTRUCT && r->type->funarg) {
// optimization - can do block copy
if(eqtypenoname(r->type, *nl)) {
- a = nodarg(*nl, fp);
+ a = arch.nodarg(*nl, fp);
r = nod(OCONVNOP, r, N);
r->type = a->type;
nn = list1(convas(nod(OAS, a, r), init));
// argument to a ddd parameter then it is
// passed thru unencapsulated
if(r != N && lr->next == nil && isddd && eqtype(l->type, r->type)) {
- a = nod(OAS, nodarg(l, fp), r);
+ a = nod(OAS, arch.nodarg(l, fp), r);
a = convas(a, init);
nn = list(nn, a);
goto ret;
goto ret;
}
- a = nod(OAS, nodarg(l, fp), r);
+ a = nod(OAS, arch.nodarg(l, fp), r);
a = convas(a, init);
nn = list(nn, a);
static int
isstack(Node *n)
{
+ Node *defn;
+
while(n->op == ODOT || n->op == OPAREN || n->op == OCONVNOP || n->op == OINDEX && isfixedarray(n->left->type))
n = n->left;
-
+
+ // If n is *autotmp and autotmp = &foo, replace n with foo.
+ // We introduce such temps when initializing struct literals.
+ if(n->op == OIND && n->left->op == ONAME && strncmp(n->left->sym->name, "autotmp_", 8) == 0) {
+ defn = n->left->defn;
+ if(defn != N && defn->op == OAS && defn->right->op == OADDR)
+ n = defn->right->left;
+ }
+
switch(n->op) {
case OINDREG:
// OINDREG only ends up in walk if it's indirect of SP.
{
while(n->op == ODOT || n->op == OPAREN || n->op == OCONVNOP || n->op == OINDEX && isfixedarray(n->left->type))
n = n->left;
-
+
switch(n->op) {
case ONAME:
switch(n->class) {
v = t->nname;
if(v && v->sym && v->sym->name[0] == '~' && v->sym->name[1] == 'r') // unnamed result
v = N;
- // In precisestack mode, the garbage collector assumes results
+ // For precise stacks, the garbage collector assumes results
// are always live, so zero them always.
- if(out && (precisestack_enabled || (v == N && hasdefer))) {
+ if(out) {
// Defer might stop a panic and show the
// return values as they exist at the time of panic.
// Make sure to zero them on entry to the function.
- nn = list(nn, nod(OAS, nodarg(t, 1), N));
+ nn = list(nn, nod(OAS, arch.nodarg(t, 1), N));
}
if(v == N || !(v->class & PHEAP))
continue;
static Node*
addstr(Node *n, NodeList **init)
{
- Node *r, *cat, *slice;
+ Node *r, *cat, *slice, *buf;
NodeList *args, *l;
int c;
+ vlong sz;
Type *t;
// orderexpr rewrote OADDSTR to have a list of strings.
if(c < 2)
yyerror("addstr count %d too small", c);
+ buf = nodnil();
+ if(n->esc == EscNone) {
+ sz = 0;
+ for(l=n->list; l != nil; l=l->next) {
+ if(n->op == OLITERAL)
+ sz += n->val.u.sval->len;
+ }
+ // Don't allocate the buffer if the result won't fit.
+ if(sz < tmpstringbufsize) {
+ // Create temporary buffer for result string on stack.
+ t = aindex(nodintconst(tmpstringbufsize), types[TUINT8]);
+ buf = nod(OADDR, temp(t), N);
+ }
+ }
+
// build list of string arguments
- args = nil;
+ args = list1(buf);
for(l=n->list; l != nil; l=l->next)
args = list(args, conv(l->n, types[TSTRING]));
t->bound = -1;
slice = nod(OCOMPLIT, N, typenod(t));
slice->alloc = n->alloc;
- slice->list = args;
+ slice->list = args->next; // skip buf arg
+ args = list1(buf);
+ args = list(args, slice);
slice->esc = EscNone;
- args = list1(slice);
}
cat = syslook(namebuf, 1);
r = nod(OCALL, cat, N);
Node *l, *r;
Node *n;
- if(thechar == '9')
+ if(arch.thechar == '9')
return;
n = *np;
Magic m;
// TODO(minux)
- if(thechar == '9')
+ if(arch.thechar == '9')
return;
n = *np;
-x
print the commands.
- -ccflags 'arg list'
- arguments to pass on each 5c, 6c, or 8c compiler invocation.
-compiler name
name of compiler to use, as in runtime.Compiler (gccgo or gc).
-gccgoflags 'arg list'
arguments to pass on each gccgo compiler/linker invocation.
-gcflags 'arg list'
- arguments to pass on each 5g, 6g, or 8g compiler invocation.
+ arguments to pass on each 5g, 6g, 8g, or 9g compiler invocation.
-installsuffix suffix
a suffix to use in the name of the package installation directory,
in order to keep output separate from default builds.
If using the -race flag, the install suffix is automatically set to race
or, if set explicitly, has _race appended to it.
-ldflags 'flag list'
- arguments to pass on each 5l, 6l, or 8l linker invocation.
+ arguments to pass on each 5l, 6l, 8l, or 9l linker invocation.
-tags 'tag list'
a list of build tags to consider satisfied during the build.
For more information about build tags, see the description of
build constraints in the documentation for the go/build package.
+ -toolexec 'cmd args'
+ a program to use to invoke toolchain programs like 5a, 5g, and 5l.
+ For example, instead of running 5g, the go command will run
+ 'cmd args /path/to/5g <arguments for 5g>'.
The list flags accept a space-separated list of strings. To embed spaces
in an element in the list, surround it with either single or double quotes.
var buildO = cmdBuild.Flag.String("o", "", "output file")
var buildWork bool // -work flag
var buildGcflags []string // -gcflags flag
-var buildCcflags []string // -ccflags flag
var buildLdflags []string // -ldflags flag
var buildGccgoflags []string // -gccgoflags flag
var buildRace bool // -race flag
+var buildToolExec []string // -toolexec flag
var buildContext = build.Default
var buildToolchain toolchain = noToolchain{}
cmd.Flag.BoolVar(&buildX, "x", false, "")
cmd.Flag.BoolVar(&buildWork, "work", false, "")
cmd.Flag.Var((*stringsFlag)(&buildGcflags), "gcflags", "")
- cmd.Flag.Var((*stringsFlag)(&buildCcflags), "ccflags", "")
cmd.Flag.Var((*stringsFlag)(&buildLdflags), "ldflags", "")
cmd.Flag.Var((*stringsFlag)(&buildGccgoflags), "gccgoflags", "")
cmd.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "tags", "")
cmd.Flag.Var(buildCompiler{}, "compiler", "")
cmd.Flag.BoolVar(&buildRace, "race", false, "")
+ cmd.Flag.Var((*stringsFlag)(&buildToolExec), "toolexec", "")
}
func addBuildFlagsNX(cmd *Command) {
// go tool cover -mode=b.coverMode -var="varName" -o dst.go src.go
func (b *builder) cover(a *action, dst, src string, perm os.FileMode, varName string) error {
return b.run(a.objdir, "cover "+a.p.ImportPath, nil,
+ buildToolExec,
tool("cover"),
"-mode", a.p.coverMode,
"-var", varName,
gcargs = append(gcargs, "-installsuffix", buildContext.InstallSuffix)
}
- args := stringList(tool(archChar+"g"), "-o", ofile, "-trimpath", b.work, buildGcflags, gcargs, "-D", p.localPrefix, importArgs)
+ args := stringList(buildToolExec, tool(archChar+"g"), "-o", ofile, "-trimpath", b.work, buildGcflags, gcargs, "-D", p.localPrefix, importArgs)
if ofile == archive {
args = append(args, "-pack")
}
// Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files.
inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch))
sfile = mkAbs(p.Dir, sfile)
- args := []interface{}{tool(archChar + "a"), "-o", ofile, "-trimpath", b.work, "-I", obj, "-I", inc, "-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch, sfile}
+ args := []interface{}{buildToolExec, tool(archChar + "a"), "-o", ofile, "-trimpath", b.work, "-I", obj, "-I", inc, "-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch, sfile}
if err := b.run(p.Dir, p.ImportPath, nil, args...); err != nil {
return err
}
// Need actual pack.
cmdline[0] = tool("pack")
- return b.run(p.Dir, p.ImportPath, nil, cmdline)
+ return b.run(p.Dir, p.ImportPath, nil, buildToolExec, cmdline)
}
func packInternal(b *builder, afile string, ofiles []string) error {
}
}
ldflags = append(ldflags, buildLdflags...)
- return b.run(".", p.ImportPath, nil, tool(archChar+"l"), "-o", out, importArgs, ldflags, mainpkg)
+ return b.run(".", p.ImportPath, nil, stringList(buildToolExec, tool(archChar+"l"), "-o", out, importArgs, ldflags, mainpkg))
}
func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
}
objExt = "o"
}
- if err := b.run(p.Dir, p.ImportPath, cgoenv, cgoExe, "-objdir", obj, cgoflags, "--", cgoCPPFLAGS, cgoexeCFLAGS, p.CgoFiles); err != nil {
+ if err := b.run(p.Dir, p.ImportPath, cgoenv, buildToolExec, cgoExe, "-objdir", obj, cgoflags, "--", cgoCPPFLAGS, cgoexeCFLAGS, p.CgoFiles); err != nil {
return nil, nil, err
}
outGo = append(outGo, gofiles...)
if p.Standard && p.ImportPath == "runtime/cgo" {
cgoflags = append(cgoflags, "-dynlinker") // record path to dynamic linker
}
- if err := b.run(p.Dir, p.ImportPath, nil, cgoExe, "-objdir", obj, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags); err != nil {
+ if err := b.run(p.Dir, p.ImportPath, nil, buildToolExec, cgoExe, "-objdir", obj, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags); err != nil {
return nil, nil, err
}
outGo = append(outGo, importGo)
}
buildGcflags = append(buildGcflags, "-race")
buildLdflags = append(buildLdflags, "-race")
- buildCcflags = append(buildCcflags, "-D", "RACE")
if buildContext.InstallSuffix != "" {
buildContext.InstallSuffix += "_"
}
-x
print the commands.
- -ccflags 'arg list'
- arguments to pass on each 5c, 6c, or 8c compiler invocation.
-compiler name
name of compiler to use, as in runtime.Compiler (gccgo or gc).
-gccgoflags 'arg list'
arguments to pass on each gccgo compiler/linker invocation.
-gcflags 'arg list'
- arguments to pass on each 5g, 6g, or 8g compiler invocation.
+ arguments to pass on each 5g, 6g, 8g, or 9g compiler invocation.
-installsuffix suffix
a suffix to use in the name of the package installation directory,
in order to keep output separate from default builds.
If using the -race flag, the install suffix is automatically set to race
or, if set explicitly, has _race appended to it.
-ldflags 'flag list'
- arguments to pass on each 5l, 6l, or 8l linker invocation.
+ arguments to pass on each 5l, 6l, 8l, or 9l linker invocation.
-tags 'tag list'
a list of build tags to consider satisfied during the build.
For more information about build tags, see the description of
build constraints in the documentation for the go/build package.
+ -toolexec 'cmd args'
+ a program to use to invoke toolchain programs like 5a, 5g, and 5l.
+ For example, instead of running 5g, the go command will run
+ 'cmd args /path/to/5g <arguments for 5g>'.
The list flags accept a space-separated list of strings. To embed spaces
in an element in the list, surround it with either single or double quotes.
-timeout t
If a test runs longer than t, panic.
+ -trace trace.out
+ Write an execution trace to the specified file before exiting.
+ Writes test binary as -c would.
+
-v
Verbose output: log all tests as they are run. Also print all
text from Log and Logf calls even if the test succeeds.
// Use pkg.gofiles instead of pkg.Dir so that
// the command only applies to this package,
// not to packages in subdirectories.
- run(stringList(tool("fix"), relPaths(pkg.allgofiles)))
+ run(stringList(buildToolExec, tool("fix"), relPaths(pkg.allgofiles)))
}
}
// due to wildcard expansion.
for _, p := range pkgs {
if *getFix {
- run(stringList(tool("fix"), relPaths(p.allgofiles)))
+ run(buildToolExec, stringList(tool("fix"), relPaths(p.allgofiles)))
// The imports might have changed, so reload again.
p = reloadPackage(arg, stk)
if buildRace && (!p.Standard || !raceExclude[p.ImportPath]) {
importPaths = append(importPaths, "runtime/race")
}
+ // On ARM with GOARM=5, everything depends on math for the link.
+ if p.ImportPath == "main" && goarch == "arm" {
+ importPaths = append(importPaths, "math")
+ }
}
// Build list of full paths to all Go files in the package,
-timeout t
If a test runs longer than t, panic.
+ -trace trace.out
+ Write an execution trace to the specified file before exiting.
+ Writes test binary as -c would.
+
-v
Verbose output: log all tests as they are run. Also print all
text from Log and Logf calls even if the test succeeds.
-run="": passes -test.run to test
-short=false: passes -test.short to test
-timeout=0: passes -test.timeout to test
+ -trace="": passes -test.trace to test
-v=false: passes -test.v to test
`
{name: "x", boolVar: &buildX},
{name: "i", boolVar: &buildI},
{name: "work", boolVar: &buildWork},
- {name: "ccflags"},
{name: "gcflags"},
{name: "exec"},
{name: "ldflags"},
{name: "run", passToTest: true},
{name: "short", boolVar: new(bool), passToTest: true},
{name: "timeout", passToTest: true},
+ {name: "trace", passToTest: true},
{name: "v", boolVar: &testV, passToTest: true},
}
if err != nil {
fatalf("invalid flag argument for -%s: %v", f.name, err)
}
- case "ccflags":
- buildCcflags, err = splitQuotedFields(value)
- if err != nil {
- fatalf("invalid flag argument for -%s: %v", f.name, err)
- }
case "gcflags":
buildGcflags, err = splitQuotedFields(value)
if err != nil {
testBench = true
case "timeout":
testTimeout = value
- case "blockprofile", "cpuprofile", "memprofile":
+ case "blockprofile", "cpuprofile", "memprofile", "trace":
testProfile = true
testNeedBinary = true
case "coverpkg":
for i := range files {
files[i] = filepath.Join(p.Dir, files[i])
}
- run(tool("vet"), relPaths(files))
+ run(buildToolExec, tool("vet"), relPaths(files))
}
#include "../../runtime/typekind.h"
// Decoding the type.* symbols. This has to be in sync with
-// ../../runtime/type.go, or more specificaly, with what
+// ../../runtime/type.go, or more specifically, with what
// ../gc/reflect.c stuffs in these.
static Reloc*
dwfunc->hash = varhash; // enable indexing of children by name
memset(varhash, 0, sizeof varhash);
for(a = s->autom; a; a = a->link) {
- switch (a->type) {
+ switch (a->name) {
case A_AUTO:
dt = DW_ABRV_AUTO;
offs = a->aoffset - PtrSize;
for(a=s->autom; a; a=a->link) {
// Emit a or p according to actual offset, even if label is wrong.
// This avoids negative offsets, which cannot be encoded.
- if(a->type != A_AUTO && a->type != A_PARAM)
+ if(a->name != A_AUTO && a->name != A_PARAM)
continue;
// compute offset relative to FP
- if(a->type == A_PARAM)
+ if(a->name == A_PARAM)
off = a->aoffset;
else
off = a->aoffset - PtrSize;
// Package ecdsa implements the Elliptic Curve Digital Signature Algorithm, as
// defined in FIPS 186-3.
+//
+// This implementation derives the nonce from an AES-CTR CSPRNG keyed by
+// ChopMD(256, SHA2-512(priv.D || entropy || hash)). The CSPRNG key is IRO by
+// a result of Coron; the AES-CTR stream is IRO under standard assumptions.
package ecdsa
// References:
import (
"crypto"
+ "crypto/aes"
+ "crypto/cipher"
"crypto/elliptic"
+ "crypto/sha512"
"encoding/asn1"
"io"
"math/big"
)
+const (
+ aesIV = "IV for ECDSA CTR"
+)
+
// PublicKey represents an ECDSA public key.
type PublicKey struct {
elliptic.Curve
// pair of integers. The security of the private key depends on the entropy of
// rand.
func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
+ // Get max(log2(q) / 2, 256) bits of entropy from rand.
+ entropylen := (priv.Curve.Params().BitSize + 7) / 16
+ if entropylen > 32 {
+ entropylen = 32
+ }
+ entropy := make([]byte, entropylen)
+ _, err = rand.Read(entropy)
+ if err != nil {
+ return
+ }
+
+ // Initialize an SHA-512 hash context; digest ...
+ md := sha512.New()
+ md.Write(priv.D.Bytes()) // the private key,
+ md.Write(entropy) // the entropy,
+ md.Write(hash) // and the input hash;
+ key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512),
+ // which is an indifferentiable MAC.
+
+ // Create an AES-CTR instance to use as a CSPRNG.
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // Create a CSPRNG that xors a stream of zeros with
+ // the output of the AES-CTR instance.
+ csprng := cipher.StreamReader{
+ R: zeroReader,
+ S: cipher.NewCTR(block, []byte(aesIV)),
+ }
+
// See [NSA] 3.4.1
c := priv.PublicKey.Curve
N := c.Params().N
var k, kInv *big.Int
for {
for {
- k, err = randFieldElement(c, rand)
+ k, err = randFieldElement(c, csprng)
if err != nil {
r = nil
return
x.Mod(x, N)
return x.Cmp(r) == 0
}
+
+type zr struct {
+ io.Reader
+}
+
+// Read replaces the contents of dst with zeros.
+func (z *zr) Read(dst []byte) (n int, err error) {
+ for i := range dst {
+ dst[i] = 0
+ }
+ return len(dst), nil
+}
+
+var zeroReader = &zr{}
testSignAndVerify(t, elliptic.P521(), "p521")
}
+func testNonceSafety(t *testing.T, c elliptic.Curve, tag string) {
+ priv, _ := GenerateKey(c, rand.Reader)
+
+ hashed := []byte("testing")
+ r0, s0, err := Sign(zeroReader, priv, hashed)
+ if err != nil {
+ t.Errorf("%s: error signing: %s", tag, err)
+ return
+ }
+
+ hashed = []byte("testing...")
+ r1, s1, err := Sign(zeroReader, priv, hashed)
+ if err != nil {
+ t.Errorf("%s: error signing: %s", tag, err)
+ return
+ }
+
+ if s0.Cmp(s1) == 0 {
+ // This should never happen.
+ t.Errorf("%s: the signatures on two different messages were the same")
+ }
+
+ if r0.Cmp(r1) == 0 {
+ t.Errorf("%s: the nonce used for two diferent messages was the same")
+ }
+}
+
+func TestNonceSafety(t *testing.T) {
+ testNonceSafety(t, elliptic.P224(), "p224")
+ if testing.Short() {
+ return
+ }
+ testNonceSafety(t, elliptic.P256(), "p256")
+ testNonceSafety(t, elliptic.P384(), "p384")
+ testNonceSafety(t, elliptic.P521(), "p521")
+}
+
+func testINDCCA(t *testing.T, c elliptic.Curve, tag string) {
+ priv, _ := GenerateKey(c, rand.Reader)
+
+ hashed := []byte("testing")
+ r0, s0, err := Sign(rand.Reader, priv, hashed)
+ if err != nil {
+ t.Errorf("%s: error signing: %s", tag, err)
+ return
+ }
+
+ r1, s1, err := Sign(rand.Reader, priv, hashed)
+ if err != nil {
+ t.Errorf("%s: error signing: %s", tag, err)
+ return
+ }
+
+ if s0.Cmp(s1) == 0 {
+ t.Errorf("%s: two signatures of the same message produced the same result")
+ }
+
+ if r0.Cmp(r1) == 0 {
+ t.Errorf("%s: two signatures of the same message produced the same nonce")
+ }
+}
+
+func TestINDCCA(t *testing.T) {
+ testINDCCA(t, elliptic.P224(), "p224")
+ if testing.Short() {
+ return
+ }
+ testINDCCA(t, elliptic.P256(), "p256")
+ testINDCCA(t, elliptic.P384(), "p384")
+ testINDCCA(t, elliptic.P521(), "p521")
+}
+
func fromHex(s string) *big.Int {
r, ok := new(big.Int).SetString(s, 16)
if !ok {
package tls
import (
+ "crypto"
"crypto/aes"
"crypto/cipher"
"crypto/des"
ivLen int
ka func(version uint16) keyAgreement
// flags is a bitmask of the suite* values, above.
- flags int
- cipher func(key, iv []byte, isRead bool) interface{}
- mac func(version uint16, macKey []byte) macFunction
- aead func(key, fixedNonce []byte) cipher.AEAD
+ flags int
+ cipher func(key, iv []byte, isRead bool) interface{}
+ mac func(version uint16, macKey []byte) macFunction
+ aead func(key, fixedNonce []byte) cipher.AEAD
+ tls12Hash crypto.Hash
}
var cipherSuites = []*cipherSuite{
// Ciphersuite order is chosen so that ECDHE comes before plain RSA
// and RC4 comes before AES (because of the Lucky13 attack).
- {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadAESGCM},
- {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadAESGCM},
- {TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, suiteECDHE, cipherRC4, macSHA1, nil},
- {TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherRC4, macSHA1, nil},
- {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
- {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
- {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
- {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
- {TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, 0, cipherRC4, macSHA1, nil},
- {TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
- {TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
- {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil},
- {TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, 0, cipher3DES, macSHA1, nil},
+ {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadAESGCM, crypto.SHA256},
+ {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadAESGCM, crypto.SHA256},
+ {TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadAESGCM, crypto.SHA384},
+ {TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadAESGCM, crypto.SHA384},
+ {TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, suiteECDHE, cipherRC4, macSHA1, nil, crypto.SHA256},
+ {TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherRC4, macSHA1, nil, crypto.SHA256},
+ {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil, crypto.SHA256},
+ {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil, crypto.SHA256},
+ {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil, crypto.SHA256},
+ {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil, crypto.SHA256},
+ {TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, 0, cipherRC4, macSHA1, nil, crypto.SHA256},
+ {TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil, crypto.SHA256},
+ {TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil, crypto.SHA256},
+ {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil, crypto.SHA256},
+ {TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, 0, cipher3DES, macSHA1, nil, crypto.SHA256},
}
func cipherRC4(key, iv []byte, isRead bool) interface{} {
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xc014
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02f
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02b
+ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc030
+ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc02c
// TLS_FALLBACK_SCSV isn't a standard cipher suite but an indicator
// that the client is doing version fallback. See
serverHello: serverHello,
hello: hello,
suite: suite,
- finishedHash: newFinishedHash(c.vers),
+ finishedHash: newFinishedHash(c.vers, suite.tls12Hash),
session: session,
}
c.writeRecord(recordTypeHandshake, certVerify.marshal())
}
- hs.masterSecret = masterFromPreMasterSecret(c.vers, preMasterSecret, hs.hello.random, hs.serverHello.random)
+ hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite.tls12Hash, preMasterSecret, hs.hello.random, hs.serverHello.random)
return nil
}
c := hs.c
clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
- keysFromMasterSecret(c.vers, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
+ keysFromMasterSecret(c.vers, hs.suite.tls12Hash, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
var clientCipher, serverCipher interface{}
var clientHash, serverHash macFunction
if hs.suite.cipher != nil {
// connection.
var tcpConn net.Conn
for i := uint(0); i < 5; i++ {
- var err error
tcpConn, err = net.DialTCP("tcp", nil, &net.TCPAddr{
IP: net.IPv4(127, 0, 0, 1),
Port: serverPort,
}
time.Sleep((1 << i) * 5 * time.Millisecond)
}
- if tcpConn == nil {
+ if err != nil {
close(stdin)
out.WriteTo(os.Stdout)
cmd.Process.Kill()
doneChan := make(chan bool)
go func() {
if _, err := client.Write([]byte("hello\n")); err != nil {
- t.Logf("Client.Write failed: %s", err)
+ t.Errorf("Client.Write failed: %s", err)
}
if test.validate != nil {
if err := test.validate(client.ConnectionState()); err != nil {
runClientTestTLS12(t, test)
}
+func TestHandshakeClientAES256GCMSHA384(t *testing.T) {
+ test := &clientTest{
+ name: "ECDHE-ECDSA-AES256-GCM-SHA384",
+ command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES256-GCM-SHA384"},
+ cert: testECDSACertificate,
+ key: testECDSAPrivateKey,
+ }
+ runClientTestTLS12(t, test)
+}
+
func TestHandshakeClientCertRSA(t *testing.T) {
config := *testConfig
cert, _ := X509KeyPair([]byte(clientCertificatePEM), []byte(clientKeyPEM))
if err != nil {
return err
}
+ hs.finishedHash = newFinishedHash(hs.c.vers, hs.suite.tls12Hash)
+ hs.finishedHash.Write(hs.clientHello.marshal())
// For an overview of TLS handshaking, see https://tools.ietf.org/html/rfc5246#section-7.3
if isResume {
}
c.haveVers = true
- hs.finishedHash = newFinishedHash(c.vers)
- hs.finishedHash.Write(hs.clientHello.marshal())
-
hs.hello = new(serverHelloMsg)
supportedCurve := false
}
var ok bool
- if hs.sessionState, ok = c.decryptTicket(hs.clientHello.sessionTicket); !ok {
+ var sessionTicket = append([]uint8{}, hs.clientHello.sessionTicket...)
+ if hs.sessionState, ok = c.decryptTicket(sessionTicket); !ok {
return false
}
hs.finishedHash.Write(certVerify.marshal())
}
-
preMasterSecret, err := keyAgreement.processClientKeyExchange(config, hs.cert, ckx, c.vers)
if err != nil {
c.sendAlert(alertHandshakeFailure)
return err
}
- hs.masterSecret = masterFromPreMasterSecret(c.vers, preMasterSecret, hs.clientHello.random, hs.hello.random)
+ hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite.tls12Hash, preMasterSecret, hs.clientHello.random, hs.hello.random)
return nil
}
c := hs.c
clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
- keysFromMasterSecret(c.vers, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
+ keysFromMasterSecret(c.vers, hs.suite.tls12Hash, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
var clientCipher, serverCipher interface{}
var clientHash, serverHash macFunction
runServerTestTLS12(t, test)
}
+func TestHandshakeServerAES256GCMSHA384(t *testing.T) {
+ test := &serverTest{
+ name: "RSA-AES256-GCM-SHA384",
+ command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "ECDHE-RSA-AES256-GCM-SHA384"},
+ }
+ runServerTestTLS12(t, test)
+}
+
func TestHandshakeServerECDHEECDSAAES(t *testing.T) {
config := *testConfig
config.Certificates = make([]Certificate, 1)
"crypto/hmac"
"crypto/md5"
"crypto/sha1"
- "crypto/sha256"
"hash"
)
}
}
-// prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, section 5.
-func prf12(result, secret, label, seed []byte) {
- labelAndSeed := make([]byte, len(label)+len(seed))
- copy(labelAndSeed, label)
- copy(labelAndSeed[len(label):], seed)
-
- pHash(result, secret, labelAndSeed, sha256.New)
+// prf12New returns a function implementing the TLS 1.2 pseudo-random function,
+// as defined in RFC 5246, section 5, using the given hash.
+func prf12New(tls12Hash crypto.Hash) func(result, secret, label, seed []byte) {
+ return func(result, secret, label, seed []byte) {
+ labelAndSeed := make([]byte, len(label)+len(seed))
+ copy(labelAndSeed, label)
+ copy(labelAndSeed[len(label):], seed)
+ pHash(result, secret, labelAndSeed, tls12Hash.New)
+ }
}
// prf30 implements the SSL 3.0 pseudo-random function, as defined in
var clientFinishedLabel = []byte("client finished")
var serverFinishedLabel = []byte("server finished")
-func prfForVersion(version uint16) func(result, secret, label, seed []byte) {
+func prfForVersion(version uint16, tls12Hash crypto.Hash) func(result, secret, label, seed []byte) {
switch version {
case VersionSSL30:
return prf30
case VersionTLS10, VersionTLS11:
return prf10
case VersionTLS12:
- return prf12
+ return prf12New(tls12Hash)
default:
panic("unknown version")
}
// masterFromPreMasterSecret generates the master secret from the pre-master
// secret. See http://tools.ietf.org/html/rfc5246#section-8.1
-func masterFromPreMasterSecret(version uint16, preMasterSecret, clientRandom, serverRandom []byte) []byte {
+func masterFromPreMasterSecret(version uint16, tls12Hash crypto.Hash, preMasterSecret, clientRandom, serverRandom []byte) []byte {
var seed [tlsRandomLength * 2]byte
copy(seed[0:len(clientRandom)], clientRandom)
copy(seed[len(clientRandom):], serverRandom)
masterSecret := make([]byte, masterSecretLength)
- prfForVersion(version)(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])
+ prfForVersion(version, tls12Hash)(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])
return masterSecret
}
// keysFromMasterSecret generates the connection keys from the master
// secret, given the lengths of the MAC key, cipher key and IV, as defined in
// RFC 2246, section 6.3.
-func keysFromMasterSecret(version uint16, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
+func keysFromMasterSecret(version uint16, tls12Hash crypto.Hash, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
var seed [tlsRandomLength * 2]byte
copy(seed[0:len(clientRandom)], serverRandom)
copy(seed[len(serverRandom):], clientRandom)
n := 2*macLen + 2*keyLen + 2*ivLen
keyMaterial := make([]byte, n)
- prfForVersion(version)(keyMaterial, masterSecret, keyExpansionLabel, seed[0:])
+ prfForVersion(version, tls12Hash)(keyMaterial, masterSecret, keyExpansionLabel, seed[0:])
clientMAC = keyMaterial[:macLen]
keyMaterial = keyMaterial[macLen:]
serverMAC = keyMaterial[:macLen]
return
}
-func newFinishedHash(version uint16) finishedHash {
+func newFinishedHash(version uint16, tls12Hash crypto.Hash) finishedHash {
if version >= VersionTLS12 {
- return finishedHash{sha256.New(), sha256.New(), nil, nil, version}
+ return finishedHash{tls12Hash.New(), tls12Hash.New(), nil, nil, version, prfForVersion(version, tls12Hash)}
}
- return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), version}
+ return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), version, prfForVersion(version, tls12Hash)}
}
// A finishedHash calculates the hash of a set of handshake messages suitable
serverMD5 hash.Hash
version uint16
+ prf func(result, secret, label, seed []byte)
}
func (h finishedHash) Write(msg []byte) (n int, err error) {
out := make([]byte, finishedVerifyLength)
if h.version >= VersionTLS12 {
seed := h.client.Sum(nil)
- prf12(out, masterSecret, clientFinishedLabel, seed)
+ h.prf(out, masterSecret, clientFinishedLabel, seed)
} else {
seed := make([]byte, 0, md5.Size+sha1.Size)
seed = h.clientMD5.Sum(seed)
seed = h.client.Sum(seed)
- prf10(out, masterSecret, clientFinishedLabel, seed)
+ h.prf(out, masterSecret, clientFinishedLabel, seed)
}
return out
}
out := make([]byte, finishedVerifyLength)
if h.version >= VersionTLS12 {
seed := h.server.Sum(nil)
- prf12(out, masterSecret, serverFinishedLabel, seed)
+ h.prf(out, masterSecret, serverFinishedLabel, seed)
} else {
seed := make([]byte, 0, md5.Size+sha1.Size)
seed = h.serverMD5.Sum(seed)
seed = h.server.Sum(seed)
- prf10(out, masterSecret, serverFinishedLabel, seed)
+ h.prf(out, masterSecret, serverFinishedLabel, seed)
}
return out
}
package tls
import (
+ "crypto"
"encoding/hex"
"testing"
)
type testKeysFromTest struct {
version uint16
+ hash crypto.Hash
preMasterSecret string
clientRandom, serverRandom string
masterSecret string
clientRandom, _ := hex.DecodeString(test.clientRandom)
serverRandom, _ := hex.DecodeString(test.serverRandom)
- masterSecret := masterFromPreMasterSecret(test.version, in, clientRandom, serverRandom)
+ masterSecret := masterFromPreMasterSecret(test.version, test.hash, in, clientRandom, serverRandom)
if s := hex.EncodeToString(masterSecret); s != test.masterSecret {
t.Errorf("#%d: bad master secret %s, want %s", i, s, test.masterSecret)
continue
}
- clientMAC, serverMAC, clientKey, serverKey, _, _ := keysFromMasterSecret(test.version, masterSecret, clientRandom, serverRandom, test.macLen, test.keyLen, 0)
+ clientMAC, serverMAC, clientKey, serverKey, _, _ := keysFromMasterSecret(test.version, test.hash, masterSecret, clientRandom, serverRandom, test.macLen, test.keyLen, 0)
clientMACString := hex.EncodeToString(clientMAC)
serverMACString := hex.EncodeToString(serverMAC)
clientKeyString := hex.EncodeToString(clientKey)
var testKeysFromTests = []testKeysFromTest{
{
VersionTLS10,
+ crypto.SHA1,
"0302cac83ad4b1db3b9ab49ad05957de2a504a634a386fc600889321e1a971f57479466830ac3e6f468e87f5385fa0c5",
"4ae66303755184a3917fcb44880605fcc53baa01912b22ed94473fc69cebd558",
"4ae663020ec16e6bb5130be918cfcafd4d765979a3136a5d50c593446e4e44db",
},
{
VersionTLS10,
+ crypto.SHA1,
"03023f7527316bc12cbcd69e4b9e8275d62c028f27e65c745cfcddc7ce01bd3570a111378b63848127f1c36e5f9e4890",
"4ae66364b5ea56b20ce4e25555aed2d7e67f42788dd03f3fee4adae0459ab106",
"4ae66363ab815cbf6a248b87d6b556184e945e9b97fbdf247858b0bdafacfa1c",
},
{
VersionTLS10,
+ crypto.SHA1,
"832d515f1d61eebb2be56ba0ef79879efb9b527504abb386fb4310ed5d0e3b1f220d3bb6b455033a2773e6d8bdf951d278a187482b400d45deb88a5d5a6bb7d6a7a1decc04eb9ef0642876cd4a82d374d3b6ff35f0351dc5d411104de431375355addc39bfb1f6329fb163b0bc298d658338930d07d313cd980a7e3d9196cac1",
"4ae663b2ee389c0de147c509d8f18f5052afc4aaf9699efe8cb05ece883d3a5e",
"4ae664d503fd4cff50cfc1fb8fc606580f87b0fcdac9554ba0e01d785bdf278e",
},
{
VersionSSL30,
+ crypto.SHA1,
"832d515f1d61eebb2be56ba0ef79879efb9b527504abb386fb4310ed5d0e3b1f220d3bb6b455033a2773e6d8bdf951d278a187482b400d45deb88a5d5a6bb7d6a7a1decc04eb9ef0642876cd4a82d374d3b6ff35f0351dc5d411104de431375355addc39bfb1f6329fb163b0bc298d658338930d07d313cd980a7e3d9196cac1",
"4ae663b2ee389c0de147c509d8f18f5052afc4aaf9699efe8cb05ece883d3a5e",
"4ae664d503fd4cff50cfc1fb8fc606580f87b0fcdac9554ba0e01d785bdf278e",
>>> Flow 1 (client to server)
-00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......|
+00000000 16 03 01 00 79 01 00 00 75 03 03 00 00 00 00 00 |....y...u.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../|
-00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............|
-00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............|
-00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................|
-00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................|
-00000070 03 02 01 02 03 ff 01 00 01 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
+00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 2e |...../.5........|
+00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
+00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0a 00 |................|
+00000070 08 04 01 04 03 02 01 02 03 ff 01 00 01 00 |..............|
>>> Flow 2 (server to client)
-00000000 16 03 01 00 59 02 00 00 55 03 01 53 04 f1 03 46 |....Y...U..S...F|
-00000010 0f 84 c4 cb 55 ef 85 f6 4f d7 0e e1 4b 10 d4 bb |....U...O...K...|
-00000020 35 87 2d f3 d7 18 ec 4e 95 4b f4 20 28 82 94 d9 |5.-....N.K. (...|
-00000030 df c4 fc ee 21 23 c1 e2 76 3e 7b 09 af 2c 39 23 |....!#..v>{..,9#|
-00000040 f8 46 6c 31 88 42 f0 79 de 37 2b 00 c0 09 00 00 |.Fl1.B.y.7+.....|
+00000000 16 03 01 00 59 02 00 00 55 03 01 43 60 d4 9a c4 |....Y...U..C`...|
+00000010 28 6c b9 56 de 43 c6 e4 05 f5 ab 71 87 ef ae b8 |(l.V.C.....q....|
+00000020 cf da 13 b5 98 b7 ab cc 35 44 48 20 2c 7f 10 60 |........5DH ,..`|
+00000030 98 a8 13 4d a8 7c d6 45 48 aa c5 aa f2 f7 bb 98 |...M.|.EH.......|
+00000040 53 6e 5d 3f 56 de 17 ba c9 a8 d1 81 c0 09 00 00 |Sn]?V...........|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
00000060 01 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..|
00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....|
00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....|
00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.|
00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....|
-00000270 2a 16 03 01 00 d5 0c 00 00 d1 03 00 17 41 04 4f |*............A.O|
-00000280 47 16 72 98 9e 9f 2e 8e 78 e9 0f fe 95 83 7b aa |G.r.....x.....{.|
-00000290 e5 3d c0 7d cf 83 bd 22 0b fd 48 f1 a7 49 a5 7d |.=.}..."..H..I.}|
-000002a0 8e 0c 83 7f e1 2d 71 03 cc 90 09 ab f7 35 81 48 |.....-q......5.H|
-000002b0 a4 1e 7d 87 21 23 12 58 2c 47 f3 af c7 6c 71 00 |..}.!#.X,G...lq.|
-000002c0 8a 30 81 87 02 42 00 b4 03 38 60 43 d9 32 ef 64 |.0...B...8`C.2.d|
-000002d0 5a 9c 91 95 0d 10 21 53 c7 78 f8 bf 50 ed 13 5d |Z.....!S.x..P..]|
-000002e0 c3 e7 71 d6 11 04 f1 e4 9d ce 17 99 8d 1a 87 1f |..q.............|
-000002f0 cb dd f8 1b ae cd bc 4a 77 ab 7c 50 bf 73 c3 ea |.......Jw.|P.s..|
-00000300 d6 df 88 56 f6 b1 03 83 02 41 66 3d fb 4e 7e af |...V.....Af=.N~.|
-00000310 4e c1 60 fe 09 fa 7e 74 99 66 7f de b4 b2 74 89 |N.`...~t.f....t.|
-00000320 1c a4 cf 74 1a 55 a5 be 74 f9 36 21 3d ae c8 c3 |...t.U..t.6!=...|
-00000330 24 8e ad db a3 26 67 8f 98 27 e3 93 ee d9 5c fb |$....&g..'....\.|
-00000340 85 82 e2 13 c3 50 ab e9 f6 39 2b 16 03 01 00 0e |.....P...9+.....|
-00000350 0d 00 00 06 03 01 02 40 00 00 0e 00 00 00 |.......@......|
+00000270 2a 16 03 01 00 d4 0c 00 00 d0 03 00 17 41 04 ef |*............A..|
+00000280 89 a9 4f 05 2f ee ee c9 cb 73 d0 57 cc c9 45 ca |..O./....s.W..E.|
+00000290 d8 61 4d 0d 5b cf 83 c1 19 bd 6d a7 49 de ba 6c |.aM.[.....m.I..l|
+000002a0 63 b5 88 c9 4d a8 44 9f f2 ec 3c 88 d6 ec 20 f3 |c...M.D...<... .|
+000002b0 6f 25 cd 99 0a 42 71 19 67 6d dd 65 6a 52 f8 00 |o%...Bq.gm.ejR..|
+000002c0 89 30 81 86 02 41 42 4f 70 eb fa 2a bf 06 0f 16 |.0...ABOp..*....|
+000002d0 62 d8 25 d5 d4 c4 bb 2e d1 f9 84 3b a0 57 78 7f |b.%........;.Wx.|
+000002e0 fe 29 50 49 e1 f0 a1 c6 1f 87 98 7f d5 63 b9 72 |.)PI.........c.r|
+000002f0 f5 2f 70 a8 bc 5f 45 22 57 07 99 e1 f8 51 30 b0 |./p.._E"W....Q0.|
+00000300 2f 6e 6d 8c b5 4a 34 02 41 05 86 7d e4 16 b2 bf |/nm..J4.A..}....|
+00000310 70 de 5a 69 43 6e e2 ec a2 4f 97 b0 ae 99 07 08 |p.ZiCn...O......|
+00000320 32 d2 9d f4 56 80 71 d7 96 94 36 59 b5 95 7f 10 |2...V.q...6Y....|
+00000330 8a aa a5 90 db cc a3 47 02 53 b1 9e 2d c7 db bc |.......G.S..-...|
+00000340 58 1d b5 01 07 9c 9c 74 b5 a7 16 03 01 00 0e 0d |X......t........|
+00000350 00 00 06 03 01 02 40 00 00 0e 00 00 00 |......@......|
>>> Flow 3 (client to server)
00000000 16 03 01 02 0a 0b 00 02 06 00 02 03 00 02 00 30 |...............0|
00000010 82 01 fc 30 82 01 5e 02 09 00 9a 30 84 6c 26 35 |...0..^....0.l&5|
00000230 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 |$ >.V...(^.+-O..|
00000240 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 |..lK[.V.2B.X..I.|
00000250 b5 68 1a 41 03 56 6b dc 5a 89 16 03 01 00 90 0f |.h.A.Vk.Z.......|
-00000260 00 00 8c 00 8a 30 81 87 02 42 00 c6 85 8e 06 b7 |.....0...B......|
-00000270 04 04 e9 cd 9e 3e cb 66 23 95 b4 42 9c 64 81 39 |.....>.f#..B.d.9|
-00000280 05 3f b5 21 f8 28 af 60 6b 4d 3d ba a1 4b 5e 77 |.?.!.(.`kM=..K^w|
-00000290 ef e7 59 28 fe 1d c1 27 a2 ff a8 de 33 48 b3 c1 |..Y(...'....3H..|
-000002a0 85 6a 42 9b f9 7e 7e 31 c2 e5 bd 66 02 41 4b 49 |.jB..~~1...f.AKI|
-000002b0 c6 cd 02 e3 83 f7 03 50 18 6d b4 c9 51 02 c0 ab |.......P.m..Q...|
-000002c0 87 bc e0 3e 4b 89 53 3a e2 65 89 97 02 c1 87 f1 |...>K.S:.e......|
-000002d0 67 d0 f2 06 28 4e 51 4e fd f0 01 be 41 3c 52 42 |g...(NQN....A<RB|
-000002e0 10 44 73 88 3e 44 24 bb 2e 77 01 77 6f a8 ac 14 |.Ds.>D$..w.wo...|
-000002f0 03 01 00 01 01 16 03 01 00 30 a3 da 45 22 96 83 |.........0..E"..|
-00000300 59 90 e9 6b ec 3b 77 50 05 89 e6 0c 61 d1 1d 2b |Y..k.;wP....a..+|
-00000310 da d4 49 bf b9 c6 dd ad c3 9c 82 bd 53 62 e8 57 |..I.........Sb.W|
-00000320 a4 6a e7 9f b1 d5 39 77 88 6d |.j....9w.m|
+00000260 00 00 8c 00 8a 30 81 87 02 42 01 0f 51 63 8f 2e |.....0...B..Qc..|
+00000270 fa 3a 3a 15 a9 4b 7f 04 c9 23 73 be 44 f5 28 37 |.::..K...#s.D.(7|
+00000280 2c 00 34 20 86 e6 94 00 bf 11 40 ec de a9 54 03 |,.4 ......@...T.|
+00000290 dc 9d 19 67 39 22 5e c4 55 3b f4 b6 9a a8 4f 6e |...g9"^.U;....On|
+000002a0 21 20 f0 9a 9a 10 a8 01 3a 20 ac 8b 02 41 34 ad |! ......: ...A4.|
+000002b0 89 da ec cc 8b b7 d7 5a 6c fe 6f 13 fa 58 40 2e |.......Zl.o..X@.|
+000002c0 a6 bf 32 69 97 a5 21 44 7c 3d d2 51 b3 b3 bb 9c |..2i..!D|=.Q....|
+000002d0 ed fa 5d bd 09 f3 c0 71 ee 3d 98 24 13 e1 e2 c8 |..]....q.=.$....|
+000002e0 e7 75 fc ac c3 61 9a f3 47 b2 7c 97 01 99 2d 14 |.u...a..G.|...-.|
+000002f0 03 01 00 01 01 16 03 01 00 30 d7 d1 c3 57 a3 f8 |.........0...W..|
+00000300 71 eb 97 9d a8 ac 15 88 f4 b4 f7 e6 8c 2e eb fe |q...............|
+00000310 25 d1 77 82 20 06 d1 36 20 3d bc 82 ab 30 4d 85 |%.w. ..6 =...0M.|
+00000320 1b 7b c2 9e 60 8f 7e 05 73 3e |.{..`.~.s>|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 30 a4 45 dd 99 df |..........0.E...|
-00000010 66 ae f5 c7 bd 1a eb 6a ff ac a6 38 14 81 b5 07 |f......j...8....|
-00000020 86 24 80 f1 09 59 ad 33 3d 43 ed 9e 43 b1 1e 9f |.$...Y.3=C..C...|
-00000030 bd 8c b3 e0 41 83 a1 34 91 c5 a1 |....A..4...|
+00000000 14 03 01 00 01 01 16 03 01 00 30 7a 5e 9e 4b 7d |..........0z^.K}|
+00000010 44 8f 70 5f fd a9 50 a9 d8 52 cf 89 f9 b0 08 ea |D.p_..P..R......|
+00000020 bb a2 80 44 73 09 da 81 98 33 b1 44 88 0c ef e3 |...Ds....3.D....|
+00000030 c6 8b 2f 28 9b e1 f7 59 26 9c 54 |../(...Y&.T|
>>> Flow 5 (client to server)
-00000000 17 03 01 00 20 ae e3 ae 7f 2d e3 a2 f7 1b 4e 69 |.... ....-....Ni|
-00000010 cb 18 c6 68 42 f8 de 61 92 4c fa d6 19 7c 8c 09 |...hB..a.L...|..|
-00000020 82 e2 f2 32 19 17 03 01 00 20 2a 77 65 1f c1 fd |...2..... *we...|
-00000030 5e 37 b7 15 f6 1f 4c 7f 5f 89 52 b4 32 27 4d 17 |^7....L._.R.2'M.|
-00000040 33 c6 e8 50 ac 70 c8 b9 2d 0a 15 03 01 00 20 e0 |3..P.p..-..... .|
-00000050 cb ce 07 80 55 a0 46 ca a7 25 4c 5f 9d 7c 73 37 |....U.F..%L_.|s7|
-00000060 de 72 6d 36 a8 e4 be fd 2a e7 f8 8d 14 80 b7 |.rm6....*......|
+00000000 17 03 01 00 20 f1 61 1b 1f 1e 91 85 c1 ce 93 38 |.... .a........8|
+00000010 6b d0 ee c5 2e 00 f0 42 e3 a9 f0 82 92 a6 9b df |k......B........|
+00000020 ac 3c e3 18 aa 17 03 01 00 20 2a 72 5b 1a 57 10 |.<....... *r[.W.|
+00000030 cb 64 c4 5f b2 2d f9 03 41 ca 8d 72 93 f7 ae 19 |.d._.-..A..r....|
+00000040 37 3a 8c d5 f5 ad d8 83 20 9c 15 03 01 00 20 f9 |7:...... ..... .|
+00000050 53 1a 9f 34 27 91 f1 3f 7c 33 eb 1f 5d 0e bc 89 |S..4'..?|3..]...|
+00000060 5e 08 20 9e 5c e4 a0 70 8d 03 63 c6 9a 62 14 |^. .\..p..c..b.|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......|
+00000000 16 03 01 00 79 01 00 00 75 03 03 00 00 00 00 00 |....y...u.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../|
-00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............|
-00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............|
-00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................|
-00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................|
-00000070 03 02 01 02 03 ff 01 00 01 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
+00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 2e |...../.5........|
+00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
+00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0a 00 |................|
+00000070 08 04 01 04 03 02 01 02 03 ff 01 00 01 00 |..............|
>>> Flow 2 (server to client)
-00000000 16 03 01 00 51 02 00 00 4d 03 01 53 04 f1 02 ed |....Q...M..S....|
-00000010 86 9c 56 84 5a d3 7d d7 f3 4e 6f 2c 69 0d f0 59 |..V.Z.}..No,i..Y|
-00000020 a5 d1 de 2d 03 2f dd 63 c3 ab fa 20 30 d6 5a 24 |...-./.c... 0.Z$|
-00000030 5c 31 67 36 8d 4c 43 e1 64 c4 8a 2c a5 fd 39 92 |\1g6.LC.d..,..9.|
-00000040 c5 6f 58 47 a3 fe 63 14 98 92 11 90 00 05 00 00 |.oXG..c.........|
+00000000 16 03 01 00 51 02 00 00 4d 03 01 8b 2e 89 18 f7 |....Q...M.......|
+00000010 c8 0f 16 f0 81 91 e7 88 7c e8 20 a2 de 0e 28 ce |........|. ...(.|
+00000020 f3 12 54 68 79 ec b2 05 0b d1 74 20 bc c6 22 fd |..Thy.....t ..".|
+00000030 45 00 2c a6 bf 65 38 fd 2f 6e 71 9c b8 14 7a 0a |E.,..e8./nq...z.|
+00000040 5b 8e 71 c9 b6 32 99 41 f7 43 91 ad 00 05 00 00 |[.q..2.A.C......|
00000050 05 ff 01 00 01 00 16 03 01 02 be 0b 00 02 ba 00 |................|
00000060 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......|
00000070 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..|
00000270 bd 77 82 6f 23 b6 e0 bd a2 92 b7 3a ac e8 56 f1 |.w.o#......:..V.|
00000280 af 54 5e 46 87 e9 3b 33 e7 b8 28 b7 d6 c8 90 35 |.T^F..;3..(....5|
00000290 d4 1c 43 d1 30 6f 55 4e 0a 70 16 03 01 00 90 0f |..C.0oUN.p......|
-000002a0 00 00 8c 00 8a 30 81 87 02 42 00 c6 85 8e 06 b7 |.....0...B......|
-000002b0 04 04 e9 cd 9e 3e cb 66 23 95 b4 42 9c 64 81 39 |.....>.f#..B.d.9|
-000002c0 05 3f b5 21 f8 28 af 60 6b 4d 3d ba a1 4b 5e 77 |.?.!.(.`kM=..K^w|
-000002d0 ef e7 59 28 fe 1d c1 27 a2 ff a8 de 33 48 b3 c1 |..Y(...'....3H..|
-000002e0 85 6a 42 9b f9 7e 7e 31 c2 e5 bd 66 02 41 4b 49 |.jB..~~1...f.AKI|
-000002f0 c6 cd 02 e3 83 f7 03 50 18 6d b4 c9 51 02 c0 ab |.......P.m..Q...|
-00000300 87 bc e0 3e 4b 89 53 3a e2 65 89 97 02 c1 87 f1 |...>K.S:.e......|
-00000310 67 d0 f2 06 28 4e 51 4e fd f0 01 47 e7 c9 d9 23 |g...(NQN...G...#|
-00000320 21 6b 87 d2 55 e3 c9 f7 eb 86 d5 1e 50 df d5 14 |!k..U.......P...|
-00000330 03 01 00 01 01 16 03 01 00 24 95 62 42 be 90 39 |.........$.bB..9|
-00000340 68 ae f5 77 47 21 14 b9 ac ee 81 2d e3 9e c7 34 |h..wG!.....-...4|
-00000350 3a 00 5c c9 12 1d c0 5a 7c e7 ef e0 cd fd |:.\....Z|.....|
+000002a0 00 00 8c 00 8a 30 81 87 02 41 59 10 98 e1 27 39 |.....0...AY...'9|
+000002b0 62 42 32 98 8d 04 14 6a 95 27 b0 3b 62 46 f3 8e |bB2....j.'.;bF..|
+000002c0 5a 86 28 4f 3d a8 49 44 85 d8 8d 02 15 52 72 4f |Z.(O=.ID.....RrO|
+000002d0 87 4c 16 73 98 f6 6f 93 bb 9a c3 11 be 7f 35 81 |.L.s..o.......5.|
+000002e0 52 9f 17 6e 10 5e 33 ad c9 24 ad 02 42 01 c3 cb |R..n.^3..$..B...|
+000002f0 e7 4f a9 c5 b1 5f ab c7 d2 42 92 05 a0 9b ca a6 |.O..._...B......|
+00000300 33 ad 5c bd 22 94 c2 f7 d3 b4 3a 25 ae b4 bc c4 |3.\.".....:%....|
+00000310 f3 b6 38 8a a2 aa e7 e8 55 d9 8a 32 1f c7 05 a0 |..8.....U..2....|
+00000320 55 58 46 aa 78 37 d8 c6 57 bc 9b 2a 31 b4 15 14 |UXF.x7..W..*1...|
+00000330 03 01 00 01 01 16 03 01 00 24 fd 98 09 ef 50 d2 |.........$....P.|
+00000340 a5 90 9c 55 eb aa 67 33 24 a3 1e db 4b 2e 6b cb |...U..g3$...K.k.|
+00000350 b5 17 8b c0 c1 2e a6 c6 49 7d 84 0c d7 96 |........I}....|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 24 ea 98 c0 fb 86 |..........$.....|
-00000010 87 7a 2e e1 c7 68 61 3e 5b cc da 1f d6 7b ab 5a |.z...ha>[....{.Z|
-00000020 a0 ae a2 cf d0 54 44 19 12 db 75 2b 8c 73 8c |.....TD...u+.s.|
+00000000 14 03 01 00 01 01 16 03 01 00 24 b3 e4 bb 70 4b |..........$...pK|
+00000010 21 71 de 80 27 48 7f 15 60 23 65 a5 3f 94 b3 e7 |!q..'H..`#e.?...|
+00000020 91 3a fe 4c 70 60 22 6c 67 ca 85 85 23 f4 83 |.:.Lp`"lg...#..|
>>> Flow 5 (client to server)
-00000000 17 03 01 00 1a f3 28 77 31 33 4c b3 7c 4b 75 61 |......(w13L.|Kua|
-00000010 38 69 6b ae c9 36 ab 2e 56 16 29 6a 9a 00 2f 15 |8ik..6..V.)j../.|
-00000020 03 01 00 16 6b ed 68 18 ed ff 44 39 9b 4a e4 a2 |....k.h...D9.J..|
-00000030 cd 79 ef 2a 3e 5a 4d b1 5d 56 |.y.*>ZM.]V|
+00000000 17 03 01 00 1a d6 19 a3 b8 82 ff dc 69 4f ee 36 |............iO.6|
+00000010 2b 95 c8 c0 e6 d8 84 ea e7 d9 40 39 10 ba 33 15 |+.........@9..3.|
+00000020 03 01 00 16 85 1b 41 3b e8 71 07 3c 6e 9f b9 e0 |......A;.q.<n...|
+00000030 0d 67 77 d8 b2 84 9f 76 05 9e |.gw....v..|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......|
+00000000 16 03 01 00 79 01 00 00 75 03 03 00 00 00 00 00 |....y...u.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../|
-00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............|
-00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............|
-00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................|
-00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................|
-00000070 03 02 01 02 03 ff 01 00 01 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
+00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 2e |...../.5........|
+00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
+00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0a 00 |................|
+00000070 08 04 01 04 03 02 01 02 03 ff 01 00 01 00 |..............|
>>> Flow 2 (server to client)
-00000000 16 03 01 00 59 02 00 00 55 03 01 53 04 f1 02 4f |....Y...U..S...O|
-00000010 73 06 2d 72 41 36 a1 b2 d3 50 97 55 8c c5 f1 43 |s.-rA6...P.U...C|
-00000020 37 1f 1a 2a fe 51 70 0b 2f 25 9e 20 50 61 86 80 |7..*.Qp./%. Pa..|
-00000030 9a 9c 6d 6f c9 ea 5c ce 0c b7 7c ce e3 be d0 e5 |..mo..\...|.....|
-00000040 be d0 c4 80 78 c3 c7 17 0c 2d 8e c8 c0 09 00 00 |....x....-......|
+00000000 16 03 01 00 59 02 00 00 55 03 01 60 fd 2a c3 90 |....Y...U..`.*..|
+00000010 e3 1d e7 96 4a e7 2c d3 c7 35 80 67 7f 7e 57 8f |....J.,..5.g.~W.|
+00000020 f1 9c 65 35 36 cd e3 98 ae ed 1e 20 58 3f 0d 2f |..e56...... X?./|
+00000030 77 10 eb 1a b6 03 96 09 f3 6d 22 9f 4b 96 21 06 |w........m".K.!.|
+00000040 84 d2 da 9a 14 09 b4 d8 be 62 45 91 c0 09 00 00 |.........bE.....|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
00000060 01 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..|
00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....|
00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....|
00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.|
00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....|
-00000270 2a 16 03 01 00 d6 0c 00 00 d2 03 00 17 41 04 b1 |*............A..|
-00000280 0f 0f 4a 18 ed 25 32 b3 a3 19 ed 4b 61 b6 eb e4 |..J..%2....Ka...|
-00000290 d3 f7 77 13 ac 9f 60 c7 8d 6d cb f1 ee 99 1a 71 |..w...`..m.....q|
-000002a0 68 aa d3 a7 70 7f 38 d0 f6 23 ab 9a f6 dd 19 4f |h...p.8..#.....O|
-000002b0 ce 10 ef d5 cf 64 85 2f 75 f6 20 06 4b f0 b9 00 |.....d./u. .K...|
-000002c0 8b 30 81 88 02 42 01 00 b9 6b 80 91 59 0a 48 3f |.0...B...k..Y.H?|
-000002d0 72 16 96 8f 21 2c 28 e4 6d 03 74 66 35 16 7d ec |r...!,(.m.tf5.}.|
-000002e0 c7 08 9b 52 b5 05 d9 38 d8 b7 51 42 a7 4a 9f 9b |...R...8..QB.J..|
-000002f0 1a 37 14 de c5 f5 16 96 83 81 58 d3 a6 1e ce 8a |.7........X.....|
-00000300 bc 19 47 30 fe c5 85 55 02 42 01 4f 61 59 68 85 |..G0...U.B.OaYh.|
-00000310 c7 64 23 22 f6 83 53 cc 58 38 25 b5 ce 74 c1 68 |.d#"..S.X8%..t.h|
-00000320 9f 32 72 33 ea c9 62 e0 26 63 92 e3 5f 34 10 0b |.2r3..b.&c.._4..|
-00000330 3c d5 83 fe 9f 67 69 ef 33 6b 19 c1 ec d6 6c 35 |<....gi.3k....l5|
-00000340 89 33 17 d3 9d 93 e2 e5 6e 89 9a a1 16 03 01 00 |.3......n.......|
-00000350 0e 0d 00 00 06 03 01 02 40 00 00 0e 00 00 00 |........@......|
+00000270 2a 16 03 01 00 d5 0c 00 00 d1 03 00 17 41 04 b2 |*............A..|
+00000280 dd fb 15 7b ac 21 6d 89 5f 18 69 18 d7 b2 ef f7 |...{.!m._.i.....|
+00000290 b6 83 99 2d 06 98 38 72 5b 58 b6 6d 09 d3 00 2e |...-..8r[X.m....|
+000002a0 a0 06 02 46 4d c6 d0 1f a8 cb c9 74 7e e1 1e 0d |...FM......t~...|
+000002b0 f4 36 2b 38 b7 ab 29 bd 39 73 a8 b8 55 2a b1 00 |.6+8..).9s..U*..|
+000002c0 8a 30 81 87 02 41 7d 26 e5 9f 73 c4 eb ea d7 59 |.0...A}&..s....Y|
+000002d0 ab b8 7a b9 b7 f6 70 6d 9e 8b a6 4a c2 fc 73 5a |..z...pm...J..sZ|
+000002e0 78 2c 27 ef ff 52 91 4a 74 12 43 2f 49 d7 55 18 |x,'..R.Jt.C/I.U.|
+000002f0 9f 72 c6 a6 25 0a 2a 94 47 5d 66 08 13 e8 ef af |.r..%.*.G]f.....|
+00000300 df 12 fa 70 91 86 87 02 42 00 dc 98 50 24 fa 27 |...p....B...P$.'|
+00000310 95 cb 01 c1 ee e9 18 7e 5b b0 b1 e3 f9 e2 56 ff |.......~[.....V.|
+00000320 d7 d7 41 f3 f1 b1 28 1f a1 19 62 29 74 1d 0e 4d |..A...(...b)t..M|
+00000330 57 3f 99 50 c6 a8 78 57 4d 36 1a 42 6b 64 1c 14 |W?.P..xWM6.Bkd..|
+00000340 e8 36 c6 a8 cc f7 75 f7 f7 7d c9 16 03 01 00 0e |.6....u..}......|
+00000350 0d 00 00 06 03 01 02 40 00 00 0e 00 00 00 |.......@......|
>>> Flow 3 (client to server)
00000000 16 03 01 01 fb 0b 00 01 f7 00 01 f4 00 01 f1 30 |...............0|
00000010 82 01 ed 30 82 01 58 a0 03 02 01 02 02 01 00 30 |...0..X........0|
00000220 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.|
00000230 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
00000240 a6 b5 68 1a 41 03 56 6b dc 5a 89 16 03 01 00 86 |..h.A.Vk.Z......|
-00000250 0f 00 00 82 00 80 20 2c 5a 08 3a 00 33 50 19 b2 |...... ,Z.:.3P..|
-00000260 0f ba 6c 76 7f 5c 92 e2 78 55 3e 32 32 bb 33 bc |..lv.\..xU>22.3.|
-00000270 ab a9 34 e0 83 cf 82 cd 9e 6b 3f 9d e6 49 61 29 |..4......k?..Ia)|
-00000280 8b b4 ed e8 12 cd a9 52 86 11 48 64 08 61 72 8d |.......R..Hd.ar.|
-00000290 d6 6a ac 42 cc e4 07 5f 08 56 9f 2f c5 35 d3 9b |.j.B..._.V./.5..|
-000002a0 e9 0d 91 82 c0 e9 bb 9f a9 8f df 96 85 08 9a 69 |...............i|
-000002b0 a4 93 b3 72 37 ba f9 b1 a4 0b b0 9f 43 6a 15 ec |...r7.......Cj..|
-000002c0 79 b8 fd 9c 1f 5f 0d 2c 56 33 c7 15 d5 4a b7 82 |y...._.,V3...J..|
-000002d0 ea 44 80 20 c5 80 14 03 01 00 01 01 16 03 01 00 |.D. ............|
-000002e0 30 c9 c0 7c d7 57 d3 00 ab 87 eb 78 56 6b a1 69 |0..|.W.....xVk.i|
-000002f0 1d fa ec ae 38 f3 ef 5d 49 19 0d 4b f0 73 63 af |....8..]I..K.sc.|
-00000300 89 b6 cb 76 cf fb b9 c1 99 98 06 0a 54 67 a0 6e |...v........Tg.n|
-00000310 e7 |.|
+00000250 0f 00 00 82 00 80 1c 5e 19 d9 f9 4f 97 8d 92 a5 |.......^...O....|
+00000260 73 87 be 46 df 6b 39 be 2c f2 13 73 da a4 04 47 |s..F.k9.,..s...G|
+00000270 44 11 72 6f ea a9 2d ea fc 6a aa e4 e5 85 d3 60 |D.ro..-..j.....`|
+00000280 3c aa 2f 81 dd bc 4f 7b bb 77 58 f7 78 15 6f 21 |<./...O{.wX.x.o!|
+00000290 7c c4 bb 95 af 85 49 ab 3f 68 cf bd 18 be e1 3e ||.....I.?h.....>|
+000002a0 9e 59 64 47 39 37 d5 cf ba 84 44 2a 4b 8b 2d cb |.YdG97....D*K.-.|
+000002b0 36 24 87 c4 c5 ba 96 91 b2 b3 d0 30 87 b3 7e 2d |6$.........0..~-|
+000002c0 8f 51 0e 47 af c6 0c 33 48 fd 37 d8 bb f2 95 2c |.Q.G...3H.7....,|
+000002d0 72 ca c6 3c ab 8d 14 03 01 00 01 01 16 03 01 00 |r..<............|
+000002e0 30 52 e6 b2 ba 4c be e7 e9 ad bf 9b 86 2d fb 90 |0R...L.......-..|
+000002f0 1c 90 86 55 7e 3e 75 63 df 38 54 d6 20 25 37 ae |...U~>uc.8T. %7.|
+00000300 ab 4f ab 85 84 03 61 f7 eb 56 bd 1a 17 f3 da f6 |.O....a..V......|
+00000310 6d |m|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 30 20 db fd ed ed |..........0 ....|
-00000010 7c d5 bf 8f 06 3b 86 1b c1 60 7d a4 74 e9 a6 c9 ||....;...`}.t...|
-00000020 f5 7c c7 f4 65 91 06 d5 53 88 d7 57 a4 22 b6 1f |.|..e...S..W."..|
-00000030 f1 02 e9 79 36 e6 a1 22 51 3a 4c |...y6.."Q:L|
+00000000 14 03 01 00 01 01 16 03 01 00 30 ae 6b 02 f3 d5 |..........0.k...|
+00000010 ff 91 fb 05 87 22 c6 f7 ac a8 83 d8 2a 10 89 69 |....."......*..i|
+00000020 e8 16 83 a9 5c 64 14 d2 15 40 94 ac 14 15 8f 75 |....\d...@.....u|
+00000030 27 19 a7 75 e9 8d e7 48 8b 62 0c |'..u...H.b.|
>>> Flow 5 (client to server)
-00000000 17 03 01 00 20 00 66 51 6a 14 ca ea e2 21 48 74 |.... .fQj....!Ht|
-00000010 c4 c1 6e b9 8b 23 af 7c 33 c9 00 f8 0b ec ab 35 |..n..#.|3......5|
-00000020 e7 42 0a d1 ae 17 03 01 00 20 00 1c 6d 60 75 5d |.B....... ..m`u]|
-00000030 b3 fb 40 2e e0 b7 0d 48 f4 87 ac d4 bf ea 01 0d |..@....H........|
-00000040 fe 10 0d 05 04 43 6b 19 ed f2 15 03 01 00 20 f8 |.....Ck....... .|
-00000050 03 ac 62 4b 1f db 2e d2 4e 00 c3 a4 57 3c 0a 62 |..bK....N...W<.b|
-00000060 05 a0 ef bd 2b 9b 9a 63 27 72 d7 d8 f1 8d 84 |....+..c'r.....|
+00000000 17 03 01 00 20 09 0e f5 bb d9 7a 54 db 9e e6 22 |.... .....zT..."|
+00000010 ea 9d 98 7e e6 af ba b1 dc c3 55 ad cc 4a f0 fa |...~......U..J..|
+00000020 0d 3a 9f 49 80 17 03 01 00 20 d0 96 b0 1d 37 42 |.:.I..... ....7B|
+00000030 0d 03 64 1d 87 24 84 ff f1 62 28 e3 6b 86 a1 54 |..d..$...b(.k..T|
+00000040 f2 65 5e ae 01 db 59 77 b1 c3 15 03 01 00 20 a0 |.e^...Yw...... .|
+00000050 88 b0 60 07 a6 05 13 dd cd f4 7c e7 57 09 b1 98 |..`.......|.W...|
+00000060 bf b1 93 f1 02 cb 86 67 36 c5 e2 a8 81 c8 8f |.......g6......|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......|
+00000000 16 03 01 00 79 01 00 00 75 03 03 00 00 00 00 00 |....y...u.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../|
-00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............|
-00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............|
-00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................|
-00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................|
-00000070 03 02 01 02 03 ff 01 00 01 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
+00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 2e |...../.5........|
+00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
+00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0a 00 |................|
+00000070 08 04 01 04 03 02 01 02 03 ff 01 00 01 00 |..............|
>>> Flow 2 (server to client)
-00000000 16 03 01 00 51 02 00 00 4d 03 01 53 04 f1 02 73 |....Q...M..S...s|
-00000010 ee 5f 70 a4 aa 0d be d7 46 a3 25 3f e3 5d ef 7b |._p.....F.%?.].{|
-00000020 73 49 7c b6 82 4d 99 2f 31 fc 8b 20 2d a3 33 7c |sI|..M./1.. -.3||
-00000030 a5 c3 85 86 ba 61 4d 05 b0 5e d3 5e 88 6e c3 4b |.....aM..^.^.n.K|
-00000040 95 d3 e9 67 f1 96 24 58 7a 6f e6 c5 00 05 00 00 |...g..$Xzo......|
+00000000 16 03 01 00 51 02 00 00 4d 03 01 ba 22 84 d4 ec |....Q...M..."...|
+00000010 cb 49 cc 28 17 ea 00 19 6f 89 6f 4a c7 36 32 f2 |.I.(....o.oJ.62.|
+00000020 db da de 60 a7 93 b9 4e 64 9e ee 20 48 76 9f d5 |...`...Nd.. Hv..|
+00000030 c9 8a 74 95 ef 4b 7c 92 fd da 04 88 76 d3 6f 5a |..t..K|.....v.oZ|
+00000040 b5 7f fa f3 3a d0 c3 b2 b1 19 09 a6 00 05 00 00 |....:...........|
00000050 05 ff 01 00 01 00 16 03 01 02 be 0b 00 02 ba 00 |................|
00000060 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......|
00000070 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..|
00000260 e6 bd 77 82 6f 23 b6 e0 bd a2 92 b7 3a ac e8 56 |..w.o#......:..V|
00000270 f1 af 54 5e 46 87 e9 3b 33 e7 b8 28 b7 d6 c8 90 |..T^F..;3..(....|
00000280 35 d4 1c 43 d1 30 6f 55 4e 0a 70 16 03 01 00 86 |5..C.0oUN.p.....|
-00000290 0f 00 00 82 00 80 0f 4c d2 b2 f0 94 6d 61 d1 2c |.......L....ma.,|
-000002a0 db 6f 79 03 bd 40 b2 d2 1d 61 ef 83 1b 4a 0c 7b |.oy..@...a...J.{|
-000002b0 c5 73 1e 1a 81 e7 67 0a d6 aa 2d 04 04 cc 0e 4b |.s....g...-....K|
-000002c0 2e da 96 7f 15 6c 05 ee c4 53 7e 33 89 28 7d db |.....l...S~3.(}.|
-000002d0 a1 77 43 ba a3 51 a9 1c b9 f5 ec 9a 8d eb 2c 46 |.wC..Q........,F|
-000002e0 5c 33 59 6b 16 af de f4 9b 80 76 a3 22 30 5d bb |\3Yk......v."0].|
-000002f0 02 b9 77 96 8a db 36 9f 54 95 00 d8 58 e1 aa 04 |..w...6.T...X...|
-00000300 98 c9 0c 32 ae 62 81 12 0c f6 1b 76 c6 58 a7 8c |...2.b.....v.X..|
-00000310 0e d8 b7 8e ed 0f 14 03 01 00 01 01 16 03 01 00 |................|
-00000320 24 1d c0 20 02 2d da 69 54 29 8c ff af 5c 56 a8 |$.. .-.iT)...\V.|
-00000330 eb d0 09 95 29 8f 52 8c e2 7b 9f 36 3e 47 a0 33 |....).R..{.6>G.3|
-00000340 2e 63 a2 24 93 |.c.$.|
+00000290 0f 00 00 82 00 80 20 f0 61 14 6c 45 b1 29 c0 56 |...... .a.lE.).V|
+000002a0 9d 26 45 01 50 d5 56 04 6d cd 66 79 81 e0 cf 5c |.&E.P.V.m.fy...\|
+000002b0 ee bc 39 f0 a1 a1 3a 43 9d 1f 8f a2 52 6e 5c 77 |..9...:C....Rn\w|
+000002c0 90 2e b3 56 37 ec 78 bd 79 53 a2 a4 8e 7d 49 13 |...V7.x.yS...}I.|
+000002d0 3a cb 88 0c d4 d8 9d d9 33 ef 47 dd d8 08 64 4a |:.......3.G...dJ|
+000002e0 69 33 84 c4 c4 78 59 6b 84 50 70 2c d9 f8 8a 39 |i3...xYk.Pp,...9|
+000002f0 37 78 3c b4 c3 70 73 8d ff aa be 8e 93 54 05 7d |7x<..ps......T.}|
+00000300 a2 cd 8b ef 8c 8c 64 7a b3 2a af 3e 20 67 a1 7b |......dz.*.> g.{|
+00000310 a3 07 3b f1 d3 88 14 03 01 00 01 01 16 03 01 00 |..;.............|
+00000320 24 93 a0 0a 95 c2 ee 2c 4b 92 f2 09 e0 a6 80 c8 |$......,K.......|
+00000330 95 fb b1 ef a0 41 bb 27 e6 ad c9 d2 11 29 8a e4 |.....A.'.....)..|
+00000340 1e 9a d6 92 2b |....+|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 24 99 e8 fb 65 f4 |..........$...e.|
-00000010 95 ae 8b 71 cc 5d a4 95 a7 27 98 fd 16 3f 7a 1a |...q.]...'...?z.|
-00000020 b6 bd bf 0a 58 72 77 97 1f 8e b1 dd 4b 12 12 |....Xrw.....K..|
+00000000 14 03 01 00 01 01 16 03 01 00 24 a4 54 34 b8 11 |..........$.T4..|
+00000010 2b ad bc 55 7d 8b 71 e3 c5 7a a1 9b 0b 7f c3 48 |+..U}.q..z.....H|
+00000020 69 32 5a 8d 0a f4 43 a0 c6 b7 e8 7d a4 f4 62 |i2Z...C....}..b|
>>> Flow 5 (client to server)
-00000000 17 03 01 00 1a 42 70 c0 89 78 12 5c 91 7e 88 2d |.....Bp..x.\.~.-|
-00000010 2f 8f be f2 f2 12 9d 81 ae 78 08 38 5e 6d 1b 15 |/........x.8^m..|
-00000020 03 01 00 16 1a 64 b1 6f 8a ff d3 63 6a c7 b8 95 |.....d.o...cj...|
-00000030 3d b0 87 bc 62 e9 88 5b 26 bd |=...b..[&.|
+00000000 17 03 01 00 1a 26 c4 9a 35 54 80 41 f6 28 6b 0e |.....&..5T.A.(k.|
+00000010 d9 e2 3d 37 ad fa db 91 3b fc 1b 5b 82 da 72 15 |..=7....;..[..r.|
+00000020 03 01 00 16 99 b3 54 b5 20 f4 3e bf e2 00 0e 4e |......T. .>....N|
+00000030 2a 1e 37 55 56 c2 3b 30 62 20 |*.7UV.;0b |
>>> Flow 1 (client to server)
-00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......|
+00000000 16 03 01 00 79 01 00 00 75 03 03 00 00 00 00 00 |....y...u.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../|
-00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............|
-00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............|
-00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................|
-00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................|
-00000070 03 02 01 02 03 ff 01 00 01 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
+00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 2e |...../.5........|
+00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
+00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0a 00 |................|
+00000070 08 04 01 04 03 02 01 02 03 ff 01 00 01 00 |..............|
>>> Flow 2 (server to client)
-00000000 16 03 01 00 59 02 00 00 55 03 01 53 04 f1 02 b2 |....Y...U..S....|
-00000010 e0 f6 f6 b5 c9 5b 28 d0 5d 58 1b 6f 4e 2b 9d 05 |.....[(.]X.oN+..|
-00000020 2a b9 b4 da 45 cf f3 10 b2 23 44 20 f8 4d 59 05 |*...E....#D .MY.|
-00000030 ad 27 f2 a0 ee 7f ec cc 20 dc e7 a2 1b 07 b3 a5 |.'...... .......|
-00000040 37 7e 61 3d d6 5c 03 cf cc f5 9b ca c0 09 00 00 |7~a=.\..........|
+00000000 16 03 01 00 59 02 00 00 55 03 01 49 fe 00 1f fb |....Y...U..I....|
+00000010 be ed 3e 36 55 b8 01 4b a0 ea 7f e4 0e db 8a d0 |..>6U..K........|
+00000020 70 b3 0f 51 47 f3 d6 bd 1f f0 fa 20 60 0c b2 85 |p..QG...... `...|
+00000030 e3 f3 b9 90 25 e5 35 d2 9a 75 31 86 d6 7e 6c b6 |....%.5..u1..~l.|
+00000040 75 96 1c 35 54 10 3a 79 85 7d 3c ce c0 09 00 00 |u..5T.:y.}<.....|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
00000060 01 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..|
00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....|
00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....|
00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.|
00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....|
-00000270 2a 16 03 01 00 d5 0c 00 00 d1 03 00 17 41 04 da |*............A..|
-00000280 5a fd 09 e5 d6 c0 70 41 5e 3a 87 eb df 0c ad 90 |Z.....pA^:......|
-00000290 22 8a 2f 90 81 0c 24 00 68 92 f3 d5 95 2f 93 43 |"./...$.h..../.C|
-000002a0 e9 58 2d 18 28 62 ee 33 5b 21 2e 49 87 21 4d 32 |.X-.(b.3[!.I.!M2|
-000002b0 32 19 b3 ba fe 2d 9a 85 12 0e a1 77 08 06 75 00 |2....-.....w..u.|
-000002c0 8a 30 81 87 02 42 01 91 14 fc 68 74 95 10 4b d4 |.0...B....ht..K.|
-000002d0 67 60 12 46 bb b0 f6 98 77 a3 41 b8 01 5c 49 54 |g`.F....w.A..\IT|
-000002e0 9e 3e 81 e7 97 a3 b9 73 6e 15 74 67 be e5 d9 eb |.>.....sn.tg....|
-000002f0 8b 87 c5 22 ab ab 58 28 4f d1 b6 80 94 1b f5 f7 |..."..X(O.......|
-00000300 12 43 ef 0a c7 3e 1a 76 02 41 7a 00 49 cb 9f 3b |.C...>.v.Az.I..;|
-00000310 91 6e 38 58 0a d3 d0 d1 ee 67 f0 b6 5d cd fa 23 |.n8X.....g..]..#|
-00000320 b6 98 43 af 9c 71 90 1e 1d 50 a2 6e 61 5b f2 92 |..C..q...P.na[..|
-00000330 b4 69 73 f2 3b 54 bf 1c 9d 05 19 97 e4 4e 41 9e |.is.;T.......NA.|
-00000340 f2 9a 76 77 9a 86 43 1f 1f 30 a2 16 03 01 00 04 |..vw..C..0......|
+00000270 2a 16 03 01 00 d5 0c 00 00 d1 03 00 17 41 04 f3 |*............A..|
+00000280 35 bb 79 ff 75 d2 57 d2 e8 8f ac b5 4b 39 ae fa |5.y.u.W.....K9..|
+00000290 d4 22 b0 74 57 c3 55 aa cd 26 b8 e0 8c f9 35 85 |.".tW.U..&....5.|
+000002a0 da 55 95 e0 cd e1 49 2c ff 4b 20 de 88 de c2 4c |.U....I,.K ....L|
+000002b0 36 e3 ca c6 69 cc 04 c6 ca 99 52 60 7f b4 cb 00 |6...i.....R`....|
+000002c0 8a 30 81 87 02 42 01 e0 54 72 b0 6b 7e 33 73 68 |.0...B..Tr.k~3sh|
+000002d0 8f 3f 81 4b c5 4c a7 bd 78 01 f4 15 54 1a 23 3a |.?.K.L..x...T.#:|
+000002e0 dd 58 90 a9 27 5d b0 06 fa e5 b8 e7 f5 aa e8 0a |.X..']..........|
+000002f0 fe 16 14 5e b8 0d 13 9e 8f 5a 29 a8 e2 c4 fd 34 |...^.....Z)....4|
+00000300 78 89 44 42 24 98 d9 24 02 41 2a b0 f6 1a f8 9d |x.DB$..$.A*.....|
+00000310 60 8a 5f 3e f2 d4 cd bd d2 73 6f 83 cf b4 87 1d |`._>.....so.....|
+00000320 29 e5 e2 f0 d5 0c 49 96 82 2f bf ce ab b2 bd e7 |).....I../......|
+00000330 6a ab 1b fe 1a 32 94 43 55 5c b1 76 61 e4 00 c1 |j....2.CU\.va...|
+00000340 f3 cf b2 74 fe b6 a1 ac f8 1f 11 16 03 01 00 04 |...t............|
00000350 0e 00 00 00 |....|
>>> Flow 3 (client to server)
00000000 16 03 01 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..|
00000020 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.|
00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 01 00 01 |..h.A.Vk.Z......|
-00000050 01 16 03 01 00 30 88 60 65 b2 d7 51 1f ad 96 56 |.....0.`e..Q...V|
-00000060 4e 0a 20 eb b5 b0 1a dd 4c f6 1a cf d4 5c 47 c4 |N. .....L....\G.|
-00000070 9c 7c a0 36 dd d1 1b 96 91 99 c0 a7 2d 9a 7c 42 |.|.6........-.|B|
-00000080 51 d1 de 87 2b a4 |Q...+.|
+00000050 01 16 03 01 00 30 fd 33 1e 7c cb c1 58 78 d3 ab |.....0.3.|..Xx..|
+00000060 d9 a0 1b d8 d2 e6 1d ff f0 4e 07 9f e5 dc eb be |.........N......|
+00000070 b9 49 b6 d9 26 53 96 c4 70 f1 ea 01 ec c9 49 2f |.I..&S..p.....I/|
+00000080 63 9e ed c1 d3 16 |c.....|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 30 86 6c b5 94 69 |..........0.l..i|
-00000010 2e e0 55 a2 4d a8 63 f2 5b 1f ae 34 21 c8 21 6a |..U.M.c.[..4!.!j|
-00000020 00 b6 56 ed 4e 2a b0 ff 01 2f da ce a1 c0 41 03 |..V.N*.../....A.|
-00000030 a9 1b 6e 2e e1 88 50 ba 62 14 88 |..n...P.b..|
+00000000 14 03 01 00 01 01 16 03 01 00 30 b9 bc fb cc 21 |..........0....!|
+00000010 b7 06 cd 88 a4 f5 36 c9 ef 0a 77 fe 11 25 30 83 |......6...w..%0.|
+00000020 a7 34 9b 1e bb 67 80 89 3c 43 a9 4d b6 70 fd cf |.4...g..<C.M.p..|
+00000030 f6 86 7e ba 09 26 19 2f 25 9e 3a |..~..&./%.:|
>>> Flow 5 (client to server)
-00000000 17 03 01 00 20 a6 63 0a 2f a5 dc e1 fb cb 7b 1f |.... .c./.....{.|
-00000010 f2 da 74 c3 ff e9 f5 8b 9c 5f 0c d3 f7 1f 44 e6 |..t......_....D.|
-00000020 90 13 5c 48 50 17 03 01 00 20 c7 75 b5 ff bc 09 |..\HP.... .u....|
-00000030 34 f2 45 db 0d 22 08 8e f1 35 cd b6 0f b0 eb 2a |4.E.."...5.....*|
-00000040 b7 1a d0 8e 14 a4 54 84 f9 dc 15 03 01 00 20 e0 |......T....... .|
-00000050 36 3d aa b3 a9 b4 20 23 ca 9e 8c 5d fc a8 c8 b7 |6=.... #...]....|
-00000060 f5 c2 b6 d0 5a e2 ce a5 7b 68 a0 48 86 95 6a |....Z...{h.H..j|
+00000000 17 03 01 00 20 aa 90 92 5c a6 07 91 99 3e 54 0b |.... ...\....>T.|
+00000010 dd 9c 59 4a 9e 91 f9 4f e4 fb 14 9e 65 18 ef 1a |..YJ...O....e...|
+00000020 8c ad a7 d4 b9 17 03 01 00 20 d7 73 8a 1a fe cb |......... .s....|
+00000030 fd f7 fc 3e 03 5e 2f 03 97 12 a2 a9 31 df e4 76 |...>.^/.....1..v|
+00000040 88 c4 32 5a 90 6e bb 40 49 5c 15 03 01 00 20 c1 |..2Z.n.@I\.... .|
+00000050 92 ce bd 9e 23 50 8e da 96 d4 98 98 bc 18 e6 e7 |....#P..........|
+00000060 33 74 be 8b b7 d8 d4 19 62 1d e8 f1 4c fd 1c |3t......b...L..|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......|
+00000000 16 03 01 00 79 01 00 00 75 03 03 00 00 00 00 00 |....y...u.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../|
-00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............|
-00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............|
-00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................|
-00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................|
-00000070 03 02 01 02 03 ff 01 00 01 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
+00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 2e |...../.5........|
+00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
+00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0a 00 |................|
+00000070 08 04 01 04 03 02 01 02 03 ff 01 00 01 00 |..............|
>>> Flow 2 (server to client)
-00000000 16 03 01 00 59 02 00 00 55 03 01 53 04 f1 02 21 |....Y...U..S...!|
-00000010 67 b5 2b 34 fb 62 d7 36 4f cf 68 2e 29 39 d0 28 |g.+4.b.6O.h.)9.(|
-00000020 3a 02 32 82 8f 95 de 62 d6 03 77 20 e6 98 56 cd |:.2....b..w ..V.|
-00000030 96 24 d1 b9 4d eb 51 19 bb b7 71 f4 9c 29 32 d4 |.$..M.Q...q..)2.|
-00000040 e5 c6 0a 54 e0 4a 20 29 3e bd 06 0d c0 13 00 00 |...T.J )>.......|
+00000000 16 03 01 00 59 02 00 00 55 03 01 52 5c cd ba 77 |....Y...U..R\..w|
+00000010 cd 8e 48 de c2 b6 d7 eb 88 c2 e3 b3 8e fd 36 37 |..H...........67|
+00000020 71 c6 79 43 89 13 48 99 98 dc 78 20 cd 26 72 7b |q.yC..H...x .&r{|
+00000030 84 c3 dd 55 e3 83 99 af da 65 a7 5f 10 ef 8b 3a |...U.....e._...:|
+00000040 4c 59 7b 11 d6 6a 61 68 d6 20 3c 3e c0 13 00 00 |LY{..jah. <>....|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
00000060 01 02 be 0b 00 02 ba 00 02 b7 00 02 b4 30 82 02 |.............0..|
00000070 b0 30 82 02 19 a0 03 02 01 02 02 09 00 85 b0 bb |.0..............|
000002f0 5f 33 c4 b6 d8 c9 75 90 96 8c 0f 52 98 b5 cd 98 |_3....u....R....|
00000300 1f 89 20 5f f2 a0 1c a3 1b 96 94 dd a9 fd 57 e9 |.. _..........W.|
00000310 70 e8 26 6d 71 99 9b 26 6e 38 50 29 6c 90 a7 bd |p.&mq..&n8P)l...|
-00000320 d9 16 03 01 00 cb 0c 00 00 c7 03 00 17 41 04 05 |.............A..|
-00000330 45 33 f8 4b e9 96 0e 4a fd ec 54 76 21 9b 24 8a |E3.K...J..Tv!.$.|
-00000340 75 0b 80 84 c7 30 2b 22 f0 85 57 a4 a9 79 d6 f6 |u....0+"..W..y..|
-00000350 6d 80 b0 71 d9 66 c9 6c dd 76 fc 32 d0 c6 bc 52 |m..q.f.l.v.2...R|
-00000360 2f f1 c9 62 17 53 76 ec be a6 1c 93 f2 b4 5d 00 |/..b.Sv.......].|
-00000370 80 72 d9 20 52 70 7c 03 b1 33 fa 51 23 cd 05 97 |.r. Rp|..3.Q#...|
-00000380 6f d6 89 2f 8d 2e 3a 17 32 eb f2 ff 6b 39 70 5e |o../..:.2...k9p^|
-00000390 21 41 8d 69 02 c8 9a 17 19 e4 48 9b 51 c3 7f 9b |!A.i......H.Q...|
-000003a0 8d 4a 83 97 07 0e 30 f1 8b 6b e9 92 12 01 d6 96 |.J....0..k......|
-000003b0 f2 1a a2 10 7f 59 87 16 1a fb 55 67 68 fc 78 c6 |.....Y....Ugh.x.|
-000003c0 57 ac 05 dd f3 6f 77 84 eb ae b0 33 2d 19 2c ba |W....ow....3-.,.|
-000003d0 b8 ae 9f 95 69 85 95 45 5e 37 f4 17 17 9b 03 c1 |....i..E^7......|
-000003e0 50 b1 36 42 bd 60 5c 8b d8 b6 f3 c8 34 c8 9d 9d |P.6B.`\.....4...|
-000003f0 75 16 03 01 00 04 0e 00 00 00 |u.........|
+00000320 d9 16 03 01 00 cb 0c 00 00 c7 03 00 17 41 04 25 |.............A.%|
+00000330 0b 65 90 de 1c eb d0 7c fe cb 71 2c 62 dd f9 7c |.e.....|..q,b..||
+00000340 bd bc f5 bd a9 79 df a1 38 36 2a 98 7b 5d ce 17 |.....y..86*.{]..|
+00000350 67 a7 71 b9 9e 0a f2 02 f4 f3 19 a6 96 bc 53 45 |g.q...........SE|
+00000360 2e e0 df f1 e6 50 8b a2 36 a1 e9 59 1e d2 8f 00 |.....P..6..Y....|
+00000370 80 5a c1 19 13 94 5e ee 89 33 4a 22 e6 5d fa bc |.Z....^..3J".]..|
+00000380 78 20 f2 5d 73 39 c9 84 1f e0 de 77 99 72 2b 77 |x .]s9.....w.r+w|
+00000390 58 f2 b6 a7 6e 3d e3 f9 95 b6 23 6e 27 36 45 f7 |X...n=....#n'6E.|
+000003a0 75 87 ff 4a 49 e1 d0 ea 83 52 97 b1 77 c6 00 8e |u..JI....R..w...|
+000003b0 62 af 4f d0 cd 5e a4 9b 2f 72 ca dc 87 96 6b 73 |b.O..^../r....ks|
+000003c0 08 2c a5 75 d8 9d d5 a3 ba 25 45 78 07 db f1 86 |.,.u.....%Ex....|
+000003d0 08 4a 56 26 9d da f6 10 43 74 c1 93 ae 89 17 f1 |.JV&....Ct......|
+000003e0 1c 22 10 15 30 81 47 78 25 de fe 30 6d da 7d 0f |."..0.Gx%..0m.}.|
+000003f0 36 16 03 01 00 04 0e 00 00 00 |6.........|
>>> Flow 3 (client to server)
00000000 16 03 01 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..|
00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.|
00000020 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.|
00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 01 00 01 |..h.A.Vk.Z......|
-00000050 01 16 03 01 00 30 ca d1 1b 08 27 9b 44 e7 e9 b4 |.....0....'.D...|
-00000060 90 16 4d 30 4e 65 5c 0d 47 ba 46 86 cf c9 80 e7 |..M0Ne\.G.F.....|
-00000070 64 31 f5 a1 9e dc 39 15 d3 be 16 4f c7 90 b6 62 |d1....9....O...b|
-00000080 5d 6d 7f 41 4e 3e |]m.AN>|
+00000050 01 16 03 01 00 30 fa 12 bd 34 6f ca 53 e6 9a 77 |.....0...4o.S..w|
+00000060 ec 0c de 3e 96 ab fe ac 52 7b 04 61 21 29 ab 86 |...>....R{.a!)..|
+00000070 7a 0b 4f 4b 9a f2 2d fe 89 96 07 a5 20 38 71 8b |z.OK..-..... 8q.|
+00000080 2e 76 9c 4e de 26 |.v.N.&|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 30 98 81 24 8e cd |..........0..$..|
-00000010 b6 48 2f 80 de 8e 24 3c cd 02 67 80 34 97 d7 92 |.H/...$<..g.4...|
-00000020 78 c2 44 3d 5d 05 eb 88 76 79 46 7a c3 fa ca 73 |x.D=]...vyFz...s|
-00000030 45 82 ad c1 81 00 ca 40 c1 2f 13 |E......@./.|
+00000000 14 03 01 00 01 01 16 03 01 00 30 54 5d dc 18 0e |..........0T]...|
+00000010 76 37 48 8c 06 e6 6c 26 6d af 3d 57 fa 57 4f 6b |v7H...l&m.=W.WOk|
+00000020 3d 00 e5 d6 81 ac 86 ae 1c 82 9c 08 4d 37 fd fc |=...........M7..|
+00000030 27 d4 38 1e 28 8e 2b 0e 50 23 80 |'.8.(.+.P#.|
>>> Flow 5 (client to server)
-00000000 17 03 01 00 20 ee 19 59 67 67 a9 8b db 99 87 50 |.... ..Ygg.....P|
-00000010 01 e2 02 c1 d5 6d 36 79 af aa ec 1b 80 0e b6 5e |.....m6y.......^|
-00000020 5f fa 03 01 cc 17 03 01 00 20 ec e2 04 b7 3b a5 |_........ ....;.|
-00000030 f2 e0 13 1f 17 48 e7 6e d3 eb f0 fa 36 ef 6e 2e |.....H.n....6.n.|
-00000040 fb ea c8 39 c4 5f 4b 28 d4 50 15 03 01 00 20 c7 |...9._K(.P.... .|
-00000050 45 ff fb c7 07 0c d8 0e 35 a3 c5 31 47 b7 03 0e |E.......5..1G...|
-00000060 14 c8 29 fd 53 70 5f 15 ac d2 1c 4c 69 fb d6 |..).Sp_....Li..|
+00000000 17 03 01 00 20 28 98 f6 dd a7 6f 74 c6 5c 6d 54 |.... (....ot.\mT|
+00000010 8a 69 99 c8 db 88 73 9e 94 a6 d7 81 9e be 5f ba |.i....s......._.|
+00000020 9e 6d 46 72 be 17 03 01 00 20 a9 d1 38 e1 eb 0f |.mFr..... ..8...|
+00000030 7a fd c7 81 12 8b 5e 8e 4e e8 e2 8b 40 af 74 e3 |z.....^.N...@.t.|
+00000040 80 6d 52 40 13 d5 d4 a0 d9 29 15 03 01 00 20 7c |.mR@.....).... ||
+00000050 3f d7 27 13 2b d5 41 4e 17 93 10 79 20 f2 f6 21 |?.'.+.AN...y ..!|
+00000060 c7 21 08 f4 bc 5f 97 61 46 2e 4f 35 86 15 79 |.!..._.aF.O5..y|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......|
+00000000 16 03 01 00 79 01 00 00 75 03 03 00 00 00 00 00 |....y...u.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../|
-00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............|
-00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............|
-00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................|
-00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................|
-00000070 03 02 01 02 03 ff 01 00 01 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
+00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 2e |...../.5........|
+00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
+00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0a 00 |................|
+00000070 08 04 01 04 03 02 01 02 03 ff 01 00 01 00 |..............|
>>> Flow 2 (server to client)
-00000000 16 03 01 00 51 02 00 00 4d 03 01 53 04 f1 02 76 |....Q...M..S...v|
-00000010 e8 45 7f 57 f3 42 4b 33 0b 06 fa a6 fa c4 3d 84 |.E.W.BK3......=.|
-00000020 5a 45 dc 93 41 a5 8d 79 6e 8f 11 20 e7 c6 29 2b |ZE..A..yn.. ..)+|
-00000030 ff 4a 6e 63 67 a6 10 cb 49 19 46 1e 5e 0a d5 70 |.Jncg...I.F.^..p|
-00000040 96 88 9a 32 48 ef c3 4a 45 4c 6d e0 00 05 00 00 |...2H..JELm.....|
+00000000 16 03 01 00 51 02 00 00 4d 03 01 5c 40 79 8d 40 |....Q...M..\@y.@|
+00000010 c0 fd 1f 3c 2d 85 e1 19 12 c8 dc 95 8a 52 44 a5 |...<-........RD.|
+00000020 3a c1 9a 41 9a 72 9d cf d8 8e 3c 20 76 d2 7d 3d |:..A.r....< v.}=|
+00000030 b9 0f a9 b0 05 a6 c7 ac 53 7a fa 0f 7a d5 25 ec |........Sz..z.%.|
+00000040 51 5f fb da a4 9e f2 45 10 40 38 13 00 05 00 00 |Q_.....E.@8.....|
00000050 05 ff 01 00 01 00 16 03 01 02 be 0b 00 02 ba 00 |................|
00000060 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......|
00000070 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..|
00000060 e6 bd 77 82 6f 23 b6 e0 bd a2 92 b7 3a ac e8 56 |..w.o#......:..V|
00000070 f1 af 54 5e 46 87 e9 3b 33 e7 b8 28 b7 d6 c8 90 |..T^F..;3..(....|
00000080 35 d4 1c 43 d1 30 6f 55 4e 0a 70 14 03 01 00 01 |5..C.0oUN.p.....|
-00000090 01 16 03 01 00 24 cd c0 68 dc 2e 69 cc c7 5b c5 |.....$..h..i..[.|
-000000a0 3f bd 40 cf a0 0f 41 34 ce 16 37 10 26 c8 3f d1 |?.@...A4..7.&.?.|
-000000b0 46 3b ad 7b b0 31 f3 c5 36 e7 |F;.{.1..6.|
+00000090 01 16 03 01 00 24 c0 e9 f1 c2 c5 a1 75 6b b8 84 |.....$......uk..|
+000000a0 cf d8 46 e6 e1 d4 a0 65 d9 89 29 55 91 4c 38 5e |..F....e..)U.L8^|
+000000b0 8c 90 ac 2e db 28 68 e6 00 b4 |.....(h...|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 24 ea 77 6f 3c 42 |..........$.wo<B|
-00000010 12 16 51 de e8 b6 f9 85 06 d9 6d 05 75 50 2b 27 |..Q.......m.uP+'|
-00000020 93 b7 6b 65 e9 14 99 48 53 3e be e4 be 03 5d |..ke...HS>....]|
+00000000 14 03 01 00 01 01 16 03 01 00 24 20 d1 dd c0 6f |..........$ ...o|
+00000010 2c f2 1e 30 c6 8c 59 e9 5b 31 e6 a6 ce ea 57 06 |,..0..Y.[1....W.|
+00000020 59 39 a2 b9 78 6e a4 fc cb 0c 9c 26 05 3b 16 |Y9..xn.....&.;.|
>>> Flow 5 (client to server)
-00000000 17 03 01 00 1a 9e ae ca 55 df c4 d9 47 04 55 dd |........U...G.U.|
-00000010 3b 33 e1 a6 16 6f a1 94 b1 9b 4d 0d cb 6c 3b 15 |;3...o....M..l;.|
-00000020 03 01 00 16 92 5d 76 07 e9 b7 31 29 09 c5 b1 09 |.....]v...1)....|
-00000030 2d 64 3d 85 8d f1 d1 40 54 b8 |-d=....@T.|
+00000000 17 03 01 00 1a 25 ef 34 80 3d 18 91 ae ba 40 79 |.....%.4.=....@y|
+00000010 0e 2e 59 ac 30 0d 47 77 bd 61 b8 16 a7 08 b0 15 |..Y.0.Gw.a......|
+00000020 03 01 00 16 54 73 7f 48 c4 49 55 97 2a 2d 00 71 |....Ts.H.IU.*-.q|
+00000030 fc 82 c8 7a 63 2a ea 9e 8d 6f |...zc*...o|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......|
+00000000 16 03 01 00 79 01 00 00 75 03 03 00 00 00 00 00 |....y...u.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../|
-00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............|
-00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............|
-00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................|
-00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................|
-00000070 03 02 01 02 03 ff 01 00 01 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
+00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 2e |...../.5........|
+00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
+00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0a 00 |................|
+00000070 08 04 01 04 03 02 01 02 03 ff 01 00 01 00 |..............|
>>> Flow 2 (server to client)
-00000000 16 03 02 00 59 02 00 00 55 03 02 53 04 f1 02 1c |....Y...U..S....|
-00000010 d1 1c 6a 5f 7a 5c 26 69 92 cd ee c3 57 ed 96 90 |..j_z\&i....W...|
-00000020 e3 c5 f1 ee 8b ee 99 5f 46 2c e6 20 c8 50 6a a4 |......._F,. .Pj.|
-00000030 4b 93 e6 da ba 6d d4 87 f6 75 a8 9d 44 db b5 43 |K....m...u..D..C|
-00000040 df 12 57 de a4 f1 bc fb b8 7a 3f 6a c0 09 00 00 |..W......z?j....|
+00000000 16 03 02 00 59 02 00 00 55 03 02 48 99 38 25 1c |....Y...U..H.8%.|
+00000010 df 79 d9 78 68 90 92 ad 3f e7 a0 38 b2 d8 ab 50 |.y.xh...?..8...P|
+00000020 2c fb b0 16 00 5a 5c 87 a6 dc 16 20 70 3f 2a fd |,....Z\.... p?*.|
+00000030 ef 14 aa 68 d5 08 c4 1e 4c 04 7a 08 63 ec cb 0d |...h....L.z.c...|
+00000040 1f 2b 08 17 f2 29 7c da a3 d0 6f 07 c0 09 00 00 |.+...)|...o.....|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
00000060 02 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..|
00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....|
00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....|
00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.|
00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....|
-00000270 2a 16 03 02 00 d4 0c 00 00 d0 03 00 17 41 04 7b |*............A.{|
-00000280 c4 00 37 35 51 de c3 f2 a4 95 2c 19 21 3e a6 94 |..75Q.....,.!>..|
-00000290 7b fd 04 d7 b7 1c 56 e6 af 3c ee 36 cb 55 e6 f0 |{.....V..<.6.U..|
-000002a0 e6 24 34 6b 8a 02 66 71 f9 e2 f5 a6 c9 d7 6c dc |.$4k..fq......l.|
-000002b0 65 59 ff 1c c9 ec a9 8b 07 d6 52 2c 01 3c c3 00 |eY........R,.<..|
-000002c0 89 30 81 86 02 41 74 89 1a 31 72 e6 8b c0 4a ce |.0...At..1r...J.|
-000002d0 8f 5a 49 a7 52 2d 6d b9 8b 50 17 62 2a 99 d6 3b |.ZI.R-m..P.b*..;|
-000002e0 02 85 41 4d 34 53 b5 09 bd e3 ac 16 c1 9b e9 83 |..AM4S..........|
-000002f0 cc 83 e3 9c 23 34 67 71 72 d4 05 a2 34 f7 08 29 |....#4gqr...4..)|
-00000300 62 43 2e cc bc 08 01 02 41 59 de 5a d0 dd d7 6b |bC......AY.Z...k|
-00000310 db 9c 35 29 79 f8 96 91 56 74 1f 18 7b ee 25 83 |..5)y...Vt..{.%.|
-00000320 f2 37 0e 77 ab 38 fb 5e 04 0b 09 d9 b4 1f 3f be |.7.w.8.^......?.|
-00000330 2e e3 60 e3 96 f3 29 c1 6d 8f 56 1b fd 62 14 48 |..`...).m.V..b.H|
-00000340 e3 d9 2a ea 2f be 93 d0 8b 31 16 03 02 00 04 0e |..*./....1......|
-00000350 00 00 00 |...|
+00000270 2a 16 03 02 00 d6 0c 00 00 d2 03 00 17 41 04 5f |*............A._|
+00000280 ea cb dd 6a 2c 16 40 15 d1 e7 ea 41 19 08 5d 1c |...j,.@....A..].|
+00000290 e8 f2 f2 75 84 96 f5 d4 c8 5b fd 4b ba 3b 79 8c |...u.....[.K.;y.|
+000002a0 86 a3 2a ce 77 2d 97 ea 39 3d 52 8e a4 c7 da bd |..*.w-..9=R.....|
+000002b0 52 68 46 b4 f2 ba 1f 73 30 29 2f 29 d4 82 66 00 |RhF....s0)/)..f.|
+000002c0 8b 30 81 88 02 42 00 c3 d3 8d 5e f9 a8 03 27 d8 |.0...B....^...'.|
+000002d0 be 19 80 53 8e 5a 58 4f 13 2a 04 25 8c 73 71 9a |...S.ZXO.*.%.sq.|
+000002e0 15 7e 05 09 d4 a2 8d 3e 16 0e 2d a8 73 97 bc 1a |.~.....>..-.s...|
+000002f0 b4 48 81 f0 c9 2a e7 c2 39 13 5d 25 3e b1 82 d1 |.H...*..9.]%>...|
+00000300 cf 3e 46 f5 f6 f8 e3 e2 02 42 01 a2 ba f5 05 eb |.>F......B......|
+00000310 84 26 34 06 f2 85 ae e0 54 95 cd f9 8a 2e 01 a5 |.&4.....T.......|
+00000320 65 d0 ab da cd ec 33 7a 12 51 1c 75 3f 4f be 7f |e.....3z.Q.u?O..|
+00000330 f7 a6 02 81 2e 6d 3b 58 d6 5f 2d 53 d0 43 61 2d |.....m;X._-S.Ca-|
+00000340 0c d8 7d e5 08 48 48 da 51 47 8b a5 16 03 02 00 |..}..HH.QG......|
+00000350 04 0e 00 00 00 |.....|
>>> Flow 3 (client to server)
00000000 16 03 02 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..|
00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.|
00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 02 00 01 |..h.A.Vk.Z......|
00000050 01 16 03 02 00 40 00 00 00 00 00 00 00 00 00 00 |.....@..........|
-00000060 00 00 00 00 00 00 b6 98 a2 a9 48 34 12 6b 0a 94 |..........H4.k..|
-00000070 89 fc 38 04 63 5a 6f 63 36 3e d9 35 12 64 8c 28 |..8.cZoc6>.5.d.(|
-00000080 99 a6 cf 2e 57 e3 14 6d 0a 8a ab f0 a6 58 37 7c |....W..m.....X7||
-00000090 96 04 d3 71 bc d4 |...q..|
+00000060 00 00 00 00 00 00 20 a1 aa ad 8d db ed 19 63 64 |...... .......cd|
+00000070 60 73 8a 59 0d 59 81 51 b8 44 7b c8 86 ac fe db |`s.Y.Y.Q.D{.....|
+00000080 9f da 5e af fd 54 a3 6e c6 f0 d6 45 fe 93 70 f1 |..^..T.n...E..p.|
+00000090 45 99 06 3e 6a 28 |E..>j(|
>>> Flow 4 (server to client)
-00000000 14 03 02 00 01 01 16 03 02 00 40 c5 01 c9 0a b0 |..........@.....|
-00000010 d8 ca 5e c1 19 dc 37 6c 2e a0 b3 11 a8 87 65 5a |..^...7l......eZ|
-00000020 09 41 b9 fe 53 c4 c9 76 97 6d 7f ac c0 be d2 07 |.A..S..v.m......|
-00000030 84 e5 5b 78 37 34 ee da 3b cb 3e 82 52 79 91 44 |..[x74..;.>.Ry.D|
-00000040 b4 e4 1c ec 3a c0 c0 9d cd ff 13 |....:......|
+00000000 14 03 02 00 01 01 16 03 02 00 40 b7 6f dc 1c 48 |..........@.o..H|
+00000010 cc 3d ac 1d 6b b2 bc 9c dd 25 02 9d b0 77 8d ca |.=..k....%...w..|
+00000020 5a 4c d6 d3 c0 e0 a6 8c 03 00 e5 85 3a 2f 5e df |ZL..........:/^.|
+00000030 17 5b 9a 2e e3 54 20 60 fe 39 ef 51 23 bc 13 ea |.[...T `.9.Q#...|
+00000040 86 6f 4f e5 8c 5f a0 3e ae e9 69 |.oO.._.>..i|
>>> Flow 5 (client to server)
00000000 17 03 02 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
-00000010 00 00 00 00 00 46 60 13 39 2b 2f 72 95 ed 0e aa |.....F`.9+/r....|
-00000020 69 6e b4 64 3e 83 43 d0 f9 7f 37 7c 1d b9 ce 11 |in.d>.C...7|....|
-00000030 d9 41 66 60 6d 15 03 02 00 30 00 00 00 00 00 00 |.Af`m....0......|
-00000040 00 00 00 00 00 00 00 00 00 00 b1 26 d0 5d 08 98 |...........&.]..|
-00000050 eb 28 42 74 31 58 42 95 c5 ad 1a 92 0a f5 5f ed |.(Bt1XB......._.|
-00000060 45 98 e0 90 e5 a3 b6 8b 8d 18 |E.........|
+00000010 00 00 00 00 00 31 e9 1b b8 b7 ed a1 dd 34 87 9c |.....1.......4..|
+00000020 3c 8a 0d 41 8c d3 3f 0e 54 62 d5 31 07 4a a5 8f |<..A..?.Tb.1.J..|
+00000030 0e 07 3d da 91 15 03 02 00 30 00 00 00 00 00 00 |..=......0......|
+00000040 00 00 00 00 00 00 00 00 00 00 d2 62 91 56 10 c8 |...........b.V..|
+00000050 c9 f8 25 3f ef ab b1 a7 88 a6 85 2b 1b 02 47 36 |..%?.......+..G6|
+00000060 3a 08 b0 63 da c1 cb ea 11 2c |:..c.....,|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......|
+00000000 16 03 01 00 79 01 00 00 75 03 03 00 00 00 00 00 |....y...u.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../|
-00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............|
-00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............|
-00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................|
-00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................|
-00000070 03 02 01 02 03 ff 01 00 01 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
+00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 2e |...../.5........|
+00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
+00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0a 00 |................|
+00000070 08 04 01 04 03 02 01 02 03 ff 01 00 01 00 |..............|
>>> Flow 2 (server to client)
-00000000 16 03 02 00 59 02 00 00 55 03 02 53 04 f1 02 fe |....Y...U..S....|
-00000010 17 8b 79 ad 93 2e d3 89 66 9b 5d 9b b4 03 3e ba |..y.....f.]...>.|
-00000020 65 2a f1 55 f9 3c 33 de 2c a7 47 20 fa 4f 82 11 |e*.U.<3.,.G .O..|
-00000030 96 81 d0 70 2e 65 b3 68 2e 3a 6d d7 6c 74 22 33 |...p.e.h.:m.lt"3|
-00000040 d4 ae 6c aa c8 f0 c7 20 8b 10 21 e7 c0 13 00 00 |..l.... ..!.....|
+00000000 16 03 02 00 59 02 00 00 55 03 02 95 77 16 4d 9c |....Y...U...w.M.|
+00000010 0c e7 a4 de e2 49 a2 28 d5 5b ec 44 24 89 7c 47 |.....I.(.[.D$.|G|
+00000020 f2 a6 03 d4 76 08 92 99 5f 3f af 20 f9 55 14 a9 |....v..._?. .U..|
+00000030 de 8c 1a 77 37 9c 1b d9 95 30 e6 25 93 9a 3f 6f |...w7....0.%..?o|
+00000040 cc c0 27 4c 4a cd 61 eb 53 a0 b2 59 c0 13 00 00 |..'LJ.a.S..Y....|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
00000060 02 02 be 0b 00 02 ba 00 02 b7 00 02 b4 30 82 02 |.............0..|
00000070 b0 30 82 02 19 a0 03 02 01 02 02 09 00 85 b0 bb |.0..............|
000002f0 5f 33 c4 b6 d8 c9 75 90 96 8c 0f 52 98 b5 cd 98 |_3....u....R....|
00000300 1f 89 20 5f f2 a0 1c a3 1b 96 94 dd a9 fd 57 e9 |.. _..........W.|
00000310 70 e8 26 6d 71 99 9b 26 6e 38 50 29 6c 90 a7 bd |p.&mq..&n8P)l...|
-00000320 d9 16 03 02 00 cb 0c 00 00 c7 03 00 17 41 04 26 |.............A.&|
-00000330 56 18 02 e5 66 d4 aa 24 7e ae 39 e5 ca 78 6c c1 |V...f..$~.9..xl.|
-00000340 90 02 c3 c4 ad 79 2c 47 a8 bf 54 e2 8a 22 b6 ef |.....y,G..T.."..|
-00000350 99 d4 7a 7f 8f 78 6a 78 4e 14 2a 16 0d bb 54 38 |..z..xjxN.*...T8|
-00000360 59 1f 7a 53 1b c7 73 10 89 4b de c3 66 39 7a 00 |Y.zS..s..K..f9z.|
-00000370 80 3a 88 38 c8 15 07 ab 2f 0f 0d cb 19 07 84 ac |.:.8..../.......|
-00000380 24 fd 8b d2 9d 05 45 c6 11 c3 d6 84 58 95 5a 08 |$.....E.....X.Z.|
-00000390 b9 a4 2c c0 41 4e 34 e0 b2 24 98 94 b7 67 27 50 |..,.AN4..$...g'P|
-000003a0 ba 82 35 28 a9 bf 16 ee e3 7b 49 9c 4c 81 80 69 |..5(.....{I.L..i|
-000003b0 d7 aa ed 46 ea 9a 68 c4 97 b7 11 d4 35 91 74 5e |...F..h.....5.t^|
-000003c0 54 10 34 83 cd c4 06 18 49 7d 7a 28 c9 53 06 73 |T.4.....I}z(.S.s|
-000003d0 00 7b 04 b6 d8 36 a7 4b 67 7f 81 30 94 de 40 4d |.{...6.Kg..0..@M|
-000003e0 18 f8 c4 b7 02 00 44 8e bc 72 06 24 53 15 74 72 |......D..r.$S.tr|
-000003f0 8d 16 03 02 00 04 0e 00 00 00 |..........|
+00000320 d9 16 03 02 00 cb 0c 00 00 c7 03 00 17 41 04 cc |.............A..|
+00000330 93 4b 67 67 12 37 c6 c4 77 3d 6b 3e ce 16 04 82 |.Kgg.7..w=k>....|
+00000340 09 9d b0 bc 67 a8 43 e8 06 ab 9d 8b dd fe ad 00 |....g.C.........|
+00000350 9e 32 19 f3 5f d8 2d de 18 76 1d 46 18 f1 1f ac |.2.._.-..v.F....|
+00000360 19 79 9b 6c 5b c8 92 d4 6b 91 e9 58 f7 92 b6 00 |.y.l[...k..X....|
+00000370 80 0c d6 d5 6c 2c 89 fa 8b a6 59 f8 48 cb f2 9d |....l,....Y.H...|
+00000380 02 61 b0 2d 83 5e e6 5f 41 b9 91 96 30 fb 09 85 |.a.-.^._A...0...|
+00000390 4f 9f ea 92 1a dc a2 c3 59 49 6c 46 85 91 b0 2f |O.......YIlF.../|
+000003a0 80 47 bc f2 ab 3a 0c 33 5f 46 ef fb bf 2e b7 14 |.G...:.3_F......|
+000003b0 03 ae 6d ac d6 3f 7f 0c 8e c8 18 c3 0d fd ba f3 |..m..?..........|
+000003c0 dd b1 8b a8 c9 ed 53 7c 9c d2 31 91 cc 05 2a f1 |......S|..1...*.|
+000003d0 86 f3 79 c8 d0 55 0d 9d 80 fd 0f 6f 1a 15 c4 dd |..y..U.....o....|
+000003e0 f3 37 41 2e 4f 51 10 27 80 11 82 c4 a8 4b 7f a3 |.7A.OQ.'.....K..|
+000003f0 e2 16 03 02 00 04 0e 00 00 00 |..........|
>>> Flow 3 (client to server)
00000000 16 03 02 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..|
00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.|
00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 02 00 01 |..h.A.Vk.Z......|
00000050 01 16 03 02 00 40 00 00 00 00 00 00 00 00 00 00 |.....@..........|
-00000060 00 00 00 00 00 00 8a 87 81 38 35 c0 4c bb f8 12 |.........85.L...|
-00000070 fa 75 04 cd 1e 3a 61 96 93 c8 fb 07 d1 6d b4 55 |.u...:a......m.U|
-00000080 0f b5 0f 07 35 0a 96 ce 5c 6f 24 62 d3 68 e4 b0 |....5...\o$b.h..|
-00000090 5d be 81 37 c2 9c |]..7..|
+00000060 00 00 00 00 00 00 cc 4d 33 16 3b 7e 8d 15 6f cf |.......M3.;~..o.|
+00000070 00 7b e2 5c 00 34 5e 53 30 92 2c 0b 5f 5a df bc |.{.\.4^S0.,._Z..|
+00000080 05 a1 eb e5 9b 2b 2a 94 26 60 57 cd 81 74 9f 31 |.....+*.&`W..t.1|
+00000090 55 64 b5 52 89 c8 |Ud.R..|
>>> Flow 4 (server to client)
-00000000 14 03 02 00 01 01 16 03 02 00 40 66 36 8d f8 8c |..........@f6...|
-00000010 7f db 38 e8 39 df f8 2f cb 88 9c 14 d9 89 10 b4 |..8.9../........|
-00000020 be 59 88 d7 f3 73 62 af a3 42 66 6e 74 38 64 9f |.Y...sb..Bfnt8d.|
-00000030 16 79 09 d7 14 7e 91 8a 70 73 63 28 30 58 fe cc |.y...~..psc(0X..|
-00000040 42 45 d6 37 fb 9e 8c c1 01 af 34 |BE.7......4|
+00000000 14 03 02 00 01 01 16 03 02 00 40 10 4d 3e ad a3 |..........@.M>..|
+00000010 6a c6 06 43 7f 5a b6 99 b0 70 22 fe dc 8e a9 a0 |j..C.Z...p".....|
+00000020 9e 0a 8f 0d ed d6 de 8d 16 18 df f9 cc 81 55 a5 |..............U.|
+00000030 56 6b 00 81 c1 8f eb 29 cb 46 16 e5 0f 10 9f 57 |Vk.....).F.....W|
+00000040 b9 28 6e c1 51 d7 c2 e3 46 ee 0b |.(n.Q...F..|
>>> Flow 5 (client to server)
00000000 17 03 02 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
-00000010 00 00 00 00 00 31 0b e3 9d 2a 05 83 19 7d 10 36 |.....1...*...}.6|
-00000020 23 dc da fe 00 ab d3 aa 8f ce 28 5f 08 fd b7 59 |#.........(_...Y|
-00000030 1e 00 2e 25 5a 15 03 02 00 30 00 00 00 00 00 00 |...%Z....0......|
-00000040 00 00 00 00 00 00 00 00 00 00 10 91 fd fa 59 07 |..............Y.|
-00000050 df 2c 92 25 15 7b 7c 83 44 89 0d 4f 65 43 99 2e |.,.%.{|.D..OeC..|
-00000060 41 5d 51 c9 09 89 ed 02 08 bc |A]Q.......|
+00000010 00 00 00 00 00 9e 9c cb 3c 7c b9 d9 03 1b b9 2c |........<|.....,|
+00000020 6b e8 d9 eb 9a 9d 29 5f 00 77 a2 f5 b7 cc 0e f1 |k.....)_.w......|
+00000030 78 cb 5d 3f e0 15 03 02 00 30 00 00 00 00 00 00 |x.]?.....0......|
+00000040 00 00 00 00 00 00 00 00 00 00 ca af f9 d3 73 44 |..............sD|
+00000050 f2 43 cc ad 30 5c 41 d4 c8 03 bc 77 96 76 ef 8d |.C..0\A....w.v..|
+00000060 3c 61 3c bf f3 ae 0d 41 80 96 |<a<....A..|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......|
+00000000 16 03 01 00 79 01 00 00 75 03 03 00 00 00 00 00 |....y...u.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../|
-00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............|
-00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............|
-00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................|
-00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................|
-00000070 03 02 01 02 03 ff 01 00 01 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
+00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 2e |...../.5........|
+00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
+00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0a 00 |................|
+00000070 08 04 01 04 03 02 01 02 03 ff 01 00 01 00 |..............|
>>> Flow 2 (server to client)
-00000000 16 03 02 00 51 02 00 00 4d 03 02 53 04 f1 02 d4 |....Q...M..S....|
-00000010 69 65 aa 96 3d 42 96 eb 9e 7d 8a 18 af 4c 7c 5d |ie..=B...}...L|]|
-00000020 fb 97 5f da 94 62 13 69 1f 66 06 20 aa 52 e3 08 |.._..b.i.f. .R..|
-00000030 35 0a 87 d5 ef 93 49 ab 1a 74 dd 90 bd 69 70 d1 |5.....I..t...ip.|
-00000040 e9 f1 44 17 3a dc 33 98 f5 e5 ab 93 00 05 00 00 |..D.:.3.........|
+00000000 16 03 02 00 51 02 00 00 4d 03 02 4d 2e 22 e8 40 |....Q...M..M.".@|
+00000010 e2 be 4a dd cc 74 ce 49 40 04 76 fa 30 11 04 64 |..J..t.I@.v.0..d|
+00000020 d3 d8 28 cc ef cb 1b 08 70 ca 28 20 74 90 27 2e |..(.....p.( t.'.|
+00000030 c7 bb 53 66 93 49 da 00 d9 96 06 cf ac 08 40 66 |..Sf.I........@f|
+00000040 41 eb 6e c8 32 2d 10 a6 42 7b 0d 5e 00 05 00 00 |A.n.2-..B{.^....|
00000050 05 ff 01 00 01 00 16 03 02 02 be 0b 00 02 ba 00 |................|
00000060 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......|
00000070 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..|
00000060 e6 bd 77 82 6f 23 b6 e0 bd a2 92 b7 3a ac e8 56 |..w.o#......:..V|
00000070 f1 af 54 5e 46 87 e9 3b 33 e7 b8 28 b7 d6 c8 90 |..T^F..;3..(....|
00000080 35 d4 1c 43 d1 30 6f 55 4e 0a 70 14 03 02 00 01 |5..C.0oUN.p.....|
-00000090 01 16 03 02 00 24 07 9f dc df 2d c3 a6 88 06 28 |.....$....-....(|
-000000a0 21 e0 e0 d3 31 99 fc 89 b8 82 6e 95 f4 4b 9e e2 |!...1.....n..K..|
-000000b0 d9 36 5c 14 ce d7 db e2 78 4e |.6\.....xN|
+00000090 01 16 03 02 00 24 2b 06 10 fe 60 26 58 7d 59 47 |.....$+...`&X}YG|
+000000a0 83 2d 84 43 e3 8d fe ab e6 c0 3b b8 68 78 e3 73 |.-.C......;.hx.s|
+000000b0 6c 59 d8 53 86 81 42 69 22 74 |lY.S..Bi"t|
>>> Flow 4 (server to client)
-00000000 14 03 02 00 01 01 16 03 02 00 24 81 72 75 80 d4 |..........$.ru..|
-00000010 1b 1a 32 00 89 bf 9e 79 30 b9 6b 67 e0 8e c7 eb |..2....y0.kg....|
-00000020 73 f2 e4 93 51 65 9b 5f 91 b1 b4 b1 f7 44 76 |s...Qe._.....Dv|
+00000000 14 03 02 00 01 01 16 03 02 00 24 62 dc 82 ed 69 |..........$b...i|
+00000010 cc e2 19 72 9c 1b 84 15 77 d8 a0 35 7d b7 47 55 |...r....w..5}.GU|
+00000020 95 4f 67 ad f1 8f 91 01 c0 31 2f 54 64 40 35 |.Og......1/Td@5|
>>> Flow 5 (client to server)
-00000000 17 03 02 00 1a b2 91 39 63 c0 38 3c 4d 25 fd 14 |.......9c.8<M%..|
-00000010 b9 b6 e1 23 21 b4 8d 17 9e 1f d8 33 92 69 c2 15 |...#!......3.i..|
-00000020 03 02 00 16 4b 10 25 4d 9d 09 c2 11 96 be f7 5b |....K.%M.......[|
-00000030 c2 9b 99 fd 1f 8e af 0f 2c 51 |........,Q|
+00000000 17 03 02 00 1a 63 52 52 39 6a 98 7a a8 41 cd b4 |.....cRR9j.z.A..|
+00000010 e4 de 75 32 76 9a ee 44 96 d0 e9 66 b8 0a b5 15 |..u2v..D...f....|
+00000020 03 02 00 16 9f 06 3f 07 78 12 b7 70 db 48 fc ef |......?.x..p.H..|
+00000030 ff 6e a7 4f e5 82 7f 0c f2 35 |.n.O.....5|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 8d 01 00 00 89 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../|
-00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............|
-00000040 00 2f 00 35 c0 12 00 0a 01 00 00 46 33 74 00 00 |./.5.......F3t..|
-00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
-00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0a 00 |................|
-00000070 08 04 01 04 03 02 01 02 03 ff 01 00 01 00 00 10 |................|
-00000080 00 10 00 0e 06 70 72 6f 74 6f 32 06 70 72 6f 74 |.....proto2.prot|
-00000090 6f 31 |o1|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
+00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 46 |...../.5.......F|
+00000050 33 74 00 00 00 05 00 05 01 00 00 00 00 00 0a 00 |3t..............|
+00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000070 0d 00 0a 00 08 04 01 04 03 02 01 02 03 ff 01 00 |................|
+00000080 01 00 00 10 00 10 00 0e 06 70 72 6f 74 6f 32 06 |.........proto2.|
+00000090 70 72 6f 74 6f 31 |proto1|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 66 02 00 00 62 03 03 77 a9 7d 9c 4b |....f...b..w.}.K|
-00000010 69 65 aa dc 95 cb 78 08 3d d2 1a 0a 45 69 23 73 |ie....x.=...Ei#s|
-00000020 4f 41 4f 24 12 2e 57 47 b7 53 64 20 82 9a f8 e7 |OAO$..WG.Sd ....|
-00000030 79 f8 13 2c 9d cd b5 cb cb 9a 95 56 0e e9 cb a8 |y..,.......V....|
-00000040 e4 a2 8a d6 bc dc fa 25 b3 57 cc cf c0 2f 00 00 |.......%.W.../..|
+00000000 16 03 03 00 66 02 00 00 62 03 03 7e 48 0b 4a 89 |....f...b..~H.J.|
+00000010 d3 3a a1 8a 8c 8b 11 bb ea c5 21 5c df 3c 81 2b |.:........!\.<.+|
+00000020 c5 c0 7c f9 fd d7 cb 10 1b dd d4 20 b4 8a a5 07 |..|........ ....|
+00000030 32 e7 04 9c 1c 73 87 cd e3 ae ff 8b 5c d7 56 6c |2....s......\.Vl|
+00000040 03 24 7d 35 4c ad 31 52 c3 cd 5c b0 c0 2f 00 00 |.$}5L.1R..\../..|
00000050 1a ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 10 |................|
00000060 00 09 00 07 06 70 72 6f 74 6f 31 16 03 03 02 be |.....proto1.....|
00000070 0b 00 02 ba 00 02 b7 00 02 b4 30 82 02 b0 30 82 |..........0...0.|
00000300 b6 d8 c9 75 90 96 8c 0f 52 98 b5 cd 98 1f 89 20 |...u....R...... |
00000310 5f f2 a0 1c a3 1b 96 94 dd a9 fd 57 e9 70 e8 26 |_..........W.p.&|
00000320 6d 71 99 9b 26 6e 38 50 29 6c 90 a7 bd d9 16 03 |mq..&n8P)l......|
-00000330 03 00 cd 0c 00 00 c9 03 00 17 41 04 1b 42 c3 ae |..........A..B..|
-00000340 44 19 d3 84 7c 6c 98 cb b9 22 a2 67 63 95 aa cc |D...|l...".gc...|
-00000350 bd e4 1e f8 08 e6 60 f3 bc 83 9f 81 da 9c 1c 8c |......`.........|
-00000360 ff 6f f4 3e 1e e5 3b f6 49 61 f9 70 43 7f c1 69 |.o.>..;.Ia.pC..i|
-00000370 de 73 98 4b bd 5c c3 78 24 18 a8 ec 04 01 00 80 |.s.K.\.x$.......|
-00000380 70 d2 5b e1 39 cf 4d 54 de d2 74 4e 5e a8 b3 ca |p.[.9.MT..tN^...|
-00000390 e1 f2 4e 76 3c 77 8b ef f7 d1 df b9 ad c1 70 39 |..Nv<w........p9|
-000003a0 c7 a3 1e 0f 7b 6c 78 2e c1 86 d2 67 36 d8 25 e0 |....{lx....g6.%.|
-000003b0 e8 e5 cc 35 a2 96 a1 b4 b7 06 68 1e aa c7 06 97 |...5......h.....|
-000003c0 b7 c2 83 ce c0 17 dd 4f 9e 6f 7a bd cd c7 6e 7f |.......O.oz...n.|
-000003d0 cb 80 d1 7d 06 2d f9 f1 fb 5f cc bb d8 62 5b f0 |...}.-..._...b[.|
-000003e0 27 12 57 d5 9b 55 aa 55 4b 9a 5a f6 a5 aa c1 82 |'.W..U.UK.Z.....|
-000003f0 39 11 6b dc 83 7f a8 47 28 5a 0f 3d 3f 0f c2 22 |9.k....G(Z.=?.."|
+00000330 03 00 cd 0c 00 00 c9 03 00 17 41 04 36 ae 35 52 |..........A.6.5R|
+00000340 e2 d1 7b 5f 96 91 06 73 30 0c c8 cb 42 e3 95 11 |..{_...s0...B...|
+00000350 52 02 5a 8a 8a a4 b3 f9 03 f0 6d 8b 23 3e 73 44 |R.Z.......m.#>sD|
+00000360 2d 3e fb 05 ac c2 0a f4 96 07 58 aa fc 9f f4 8b |->........X.....|
+00000370 38 af 46 6a a6 87 b7 6d 65 eb 75 17 04 01 00 80 |8.Fj...me.u.....|
+00000380 44 0d 99 2f 79 3d 66 0b 7c 76 f8 95 14 78 90 f9 |D../y=f.|v...x..|
+00000390 ee bb 74 9b 01 25 62 a3 58 d6 8d 4b 43 0a 18 16 |..t..%b.X..KC...|
+000003a0 4d 44 fa 01 13 de 32 36 16 6a 4d 9a 6d ab dd e5 |MD....26.jM.m...|
+000003b0 a8 9d 9e 4a f8 18 fd da 95 99 02 20 29 b3 79 f6 |...J....... ).y.|
+000003c0 c7 c4 eb 81 45 ef 20 5f 2b ed 5f 72 a5 5f 99 0b |....E. _+._r._..|
+000003d0 54 25 0d db 11 7f 64 ec 5a 2f 38 c7 74 29 77 f0 |T%....d.Z/8.t)w.|
+000003e0 4b 9c 92 72 02 4c f3 bf ee ba e1 51 fb b4 ac e6 |K..r.L.....Q....|
+000003f0 0c 4c 19 bc 9a b7 e9 fd 8a 86 bf 37 d5 0b 1d 2a |.L.........7...*|
00000400 16 03 03 00 04 0e 00 00 00 |.........|
>>> Flow 3 (client to server)
00000000 16 03 03 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..|
00000020 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.|
00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 03 00 01 |..h.A.Vk.Z......|
-00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 35 9d |.....(........5.|
-00000060 92 e8 bf df 7f a7 77 1b cf 03 2a bf e2 6c 62 2b |......w...*..lb+|
-00000070 26 f0 fb 93 d3 df fd 55 84 d3 ed 88 31 cb |&......U....1.|
+00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 27 e5 |.....(........'.|
+00000060 ee c8 9a 3e d6 70 d6 1a 1b ad d2 1a 88 be 77 fd |...>.p........w.|
+00000070 bc e2 33 13 22 52 df be 67 30 da 10 5c cf |..3."R..g0..\.|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 28 c8 c0 78 09 73 |..........(..x.s|
-00000010 58 41 73 66 88 cf db f3 fe c6 57 ab 45 be 2e d8 |XAsf......W.E...|
-00000020 4e e5 ff 42 57 13 74 d2 cc c2 62 07 39 8b 06 46 |N..BW.t...b.9..F|
-00000030 1d 8f 88 |...|
+00000000 14 03 03 00 01 01 16 03 03 00 28 81 ad 88 a5 2e |..........(.....|
+00000010 1f 26 3c 53 16 a7 d4 c2 13 08 52 6e ac 3b 00 9d |.&<S......Rn.;..|
+00000020 d9 ee d4 93 86 3f 8a 0e d8 06 d9 61 a6 6f bf f9 |.....?.....a.o..|
+00000030 a9 1f fe |...|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 10 c3 5f |..............._|
-00000010 3f c8 92 6c 7a a7 23 05 f3 d8 31 20 01 52 f1 99 |?..lz.#...1 .R..|
-00000020 33 c1 2a 15 03 03 00 1a 00 00 00 00 00 00 00 02 |3.*.............|
-00000030 cc ef eb 78 e4 e1 9d 90 05 6d 95 ac f2 49 ba 8e |...x.....m...I..|
-00000040 6b 8d |k.|
+00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 ab b6 ac |................|
+00000010 55 5d 72 b0 7a a1 0e 17 8d 1b 71 77 79 ef 32 6b |U]r.z.....qwy.2k|
+00000020 4e c2 df 15 03 03 00 1a 00 00 00 00 00 00 00 02 |N...............|
+00000030 34 1e 22 35 71 60 cd cf 75 2b 73 94 b6 5f 09 1d |4."5q`..u+s.._..|
+00000040 1b b5 |..|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 86 01 00 00 82 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 8a 01 00 00 86 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../|
-00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............|
-00000040 00 2f 00 35 c0 12 00 0a 01 00 00 3f 33 74 00 00 |./.5.......?3t..|
-00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
-00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0a 00 |................|
-00000070 08 04 01 04 03 02 01 02 03 ff 01 00 01 00 00 10 |................|
-00000080 00 09 00 07 06 70 72 6f 74 6f 33 |.....proto3|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
+00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 3f |...../.5.......?|
+00000050 33 74 00 00 00 05 00 05 01 00 00 00 00 00 0a 00 |3t..............|
+00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000070 0d 00 0a 00 08 04 01 04 03 02 01 02 03 ff 01 00 |................|
+00000080 01 00 00 10 00 09 00 07 06 70 72 6f 74 6f 33 |.........proto3|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 69 84 d1 d3 44 |....Y...U..i...D|
-00000010 e9 66 08 48 bc 70 d8 ae 40 0b 17 69 e7 27 f6 7a |.f.H.p..@..i.'.z|
-00000020 d5 ee 86 74 54 9e a8 bb 79 76 89 20 57 53 1b 02 |...tT...yv. WS..|
-00000030 5b 70 81 a6 f1 53 bc 9d b7 42 5e ac 92 93 b5 20 |[p...S...B^.... |
-00000040 8a bb 36 cc 8f cb 7e a0 61 a2 e8 ef c0 2f 00 00 |..6...~.a..../..|
+00000000 16 03 03 00 59 02 00 00 55 03 03 f0 ff a6 91 ca |....Y...U.......|
+00000010 e9 d7 bc 31 4c 5e 15 b0 24 41 78 17 87 a8 1c 7d |...1L^..$Ax....}|
+00000020 eb bd 28 f6 57 7f 01 ab b4 02 a7 20 38 08 43 7e |..(.W...... 8.C~|
+00000030 ca 3c 5f ba 62 bb b0 10 30 f3 f2 03 68 ef 01 43 |.<_.b...0...h..C|
+00000040 3b 70 2c 37 80 fe 1c af bc f5 db 60 c0 2f 00 00 |;p,7.......`./..|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
00000060 03 02 be 0b 00 02 ba 00 02 b7 00 02 b4 30 82 02 |.............0..|
00000070 b0 30 82 02 19 a0 03 02 01 02 02 09 00 85 b0 bb |.0..............|
000002f0 5f 33 c4 b6 d8 c9 75 90 96 8c 0f 52 98 b5 cd 98 |_3....u....R....|
00000300 1f 89 20 5f f2 a0 1c a3 1b 96 94 dd a9 fd 57 e9 |.. _..........W.|
00000310 70 e8 26 6d 71 99 9b 26 6e 38 50 29 6c 90 a7 bd |p.&mq..&n8P)l...|
-00000320 d9 16 03 03 00 cd 0c 00 00 c9 03 00 17 41 04 04 |.............A..|
-00000330 be 27 08 6f 12 83 1b 04 76 fa 5f 16 d6 e3 64 76 |.'.o....v._...dv|
-00000340 ad 0a 77 37 71 64 44 4c 3f 1a be dc 85 ce 46 c8 |..w7qdDL?.....F.|
-00000350 29 a1 e2 24 78 66 1f 35 90 05 46 c0 91 d1 fd dd |)..$xf.5..F.....|
-00000360 b5 5b 87 d7 6d 9d 77 a7 f7 b3 df 68 27 fd 6d 04 |.[..m.w....h'.m.|
-00000370 01 00 80 7b 9b fd 0d 62 57 07 ef 97 f5 ff a9 00 |...{...bW.......|
-00000380 a0 89 35 5a 8a e6 e7 ae 7b 55 c5 dc 21 64 87 6e |..5Z....{U..!d.n|
-00000390 0f ab 85 6d 82 e8 83 fd 7d 3b 49 a7 ae 92 5f 6d |...m....};I..._m|
-000003a0 a3 42 ce ff ef a6 00 6a 33 32 1f 7b eb b7 c2 5c |.B.....j32.{...\|
-000003b0 2d 38 cf 10 4b 59 69 4d 15 e0 68 49 39 ba cb 2a |-8..KYiM..hI9..*|
-000003c0 d9 b9 f3 fe 33 01 4f 7e ac 69 02 35 a5 e0 33 8d |....3.O~.i.5..3.|
-000003d0 b3 74 34 14 45 9c 89 ad 41 2d d0 27 22 90 58 c6 |.t4.E...A-.'".X.|
-000003e0 e0 2c b4 6e 19 04 e4 46 26 ec 13 35 48 a6 3f 64 |.,.n...F&..5H.?d|
-000003f0 dc 85 2b 16 03 03 00 04 0e 00 00 00 |..+.........|
+00000320 d9 16 03 03 00 cd 0c 00 00 c9 03 00 17 41 04 4e |.............A.N|
+00000330 38 ec 28 ce cb f6 6b 74 96 74 92 46 9a 41 4a 02 |8.(...kt.t.F.AJ.|
+00000340 33 cb f0 d9 24 20 fd e0 d4 8b 24 b2 1f 24 ac 38 |3...$ ....$..$.8|
+00000350 79 cc ec ff 25 c9 30 f6 85 84 51 ee cb 59 8b 0d |y...%.0...Q..Y..|
+00000360 e2 38 3d e0 24 83 84 da ef 67 f5 f7 8a 0a c0 04 |.8=.$....g......|
+00000370 01 00 80 82 72 af cb 74 fb 8c 02 d5 d4 d9 26 04 |....r..t......&.|
+00000380 06 59 64 f0 50 ce cf ed 15 b4 24 95 47 8a c6 17 |.Yd.P.....$.G...|
+00000390 b0 da a4 13 20 88 e9 b8 ef cd b2 f1 35 5a 88 81 |.... .......5Z..|
+000003a0 19 03 ee f4 74 a2 23 27 bc e9 bf f2 06 06 58 f3 |....t.#'......X.|
+000003b0 ef b6 5e de 76 58 8c ec a6 d0 d3 1e 44 ec ac 61 |..^.vX......D..a|
+000003c0 62 91 a6 9e 36 ef 64 e9 a5 2e e8 88 69 30 0f b3 |b...6.d.....i0..|
+000003d0 84 0a b4 d1 3b a5 fe 9e 96 1a ad 7b 8a 24 7e a7 |....;......{.$~.|
+000003e0 af 5b 6d 11 be 1f 2b 7a 5f 62 f7 ae be 2e 99 ec |.[m...+z_b......|
+000003f0 05 b6 7c 16 03 03 00 04 0e 00 00 00 |..|.........|
>>> Flow 3 (client to server)
00000000 16 03 03 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..|
00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.|
00000020 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.|
00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 03 00 01 |..h.A.Vk.Z......|
-00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 88 0d |.....(..........|
-00000060 04 8b 8e 93 55 58 d6 75 ca 16 26 42 a3 60 20 67 |....UX.u..&B.` g|
-00000070 84 cf d7 b3 10 fe 63 6c 2f 40 64 0c d6 78 |......cl/@d..x|
+00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 d4 91 |.....(..........|
+00000060 e7 17 05 14 7a ce cf 0c 3b c1 a6 a7 4a 57 70 9a |....z...;...JWp.|
+00000070 cf 0e ec 59 19 d3 ba 90 97 51 8b 60 8e 03 |...Y.....Q.`..|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 28 bd 6c 2f 70 b9 |..........(.l/p.|
-00000010 2f 9c 29 70 af 34 49 4c 5b 25 c3 14 b6 6d 28 81 |/.)p.4IL[%...m(.|
-00000020 ff 54 d9 71 8d 2c c7 38 dd 44 27 6b 54 1e 53 7b |.T.q.,.8.D'kT.S{|
-00000030 22 cb 65 |".e|
+00000000 14 03 03 00 01 01 16 03 03 00 28 55 64 22 e3 20 |..........(Ud". |
+00000010 eb 69 63 44 b4 68 89 29 d6 c8 83 d8 6c 30 2f af |.icD.h.)....l0/.|
+00000020 2a 86 b0 ea ce 57 b8 9c 69 9a e3 fe 86 7e 0a bf |*....W..i....~..|
+00000030 08 f1 fe |...|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 7f 0d d7 |................|
-00000010 d9 4b 87 7b 36 fb 24 92 69 22 43 50 1e 46 fb c4 |.K.{6.$.i"CP.F..|
-00000020 86 64 6f 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.do.............|
-00000030 37 d5 2d 0a be c5 a8 ae d4 bd 2b 09 34 18 a0 87 |7.-.......+.4...|
-00000040 08 a6 |..|
+00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 29 39 41 |.............)9A|
+00000010 c4 ff e3 3e 38 bf 06 09 d2 d9 05 84 66 60 58 e8 |...>8.......f`X.|
+00000020 3a 74 f5 15 03 03 00 1a 00 00 00 00 00 00 00 02 |:t..............|
+00000030 b4 1f e4 7b 84 1e 87 57 97 f6 f2 12 df 40 85 fe |...{...W.....@..|
+00000040 d0 d1 |..|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......|
+00000000 16 03 01 00 79 01 00 00 75 03 03 00 00 00 00 00 |....y...u.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../|
-00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............|
-00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............|
-00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................|
-00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................|
-00000070 03 02 01 02 03 ff 01 00 01 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
+00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 2e |...../.5........|
+00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
+00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0a 00 |................|
+00000070 08 04 01 04 03 02 01 02 03 ff 01 00 01 00 |..............|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 53 04 f1 03 6f |....Y...U..S...o|
-00000010 c6 4b 55 27 fe e8 fe 4d 7c 0e d4 20 98 b8 7c 81 |.KU'...M|.. ..|.|
-00000020 3d 31 f8 35 66 2f 0a 0b f1 2c e3 20 86 4d 12 32 |=1.5f/...,. .M.2|
-00000030 73 e3 ba be 25 50 a4 a2 a1 7b f1 9a 76 7a 75 fb |s...%P...{..vzu.|
-00000040 e2 64 a2 12 ec f3 e7 9d 9a 24 6e 94 c0 09 00 00 |.d.......$n.....|
+00000000 16 03 03 00 59 02 00 00 55 03 03 e1 64 a4 cd 65 |....Y...U...d..e|
+00000010 5a 19 5f 07 68 cb af f2 74 76 a2 99 18 e4 9e 00 |Z._.h...tv......|
+00000020 6a 72 6b 84 dd 1c ec cd 64 45 34 20 96 c3 54 88 |jrk.....dE4 ..T.|
+00000030 00 ec aa 32 95 2c ad 08 47 64 fd 2e d4 1f 8e 5e |...2.,..Gd.....^|
+00000040 ec 39 aa ba 6a 3c 8c c7 a6 63 55 8e c0 09 00 00 |.9..j<...cU.....|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
00000060 03 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..|
00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....|
00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....|
00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.|
00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....|
-00000270 2a 16 03 03 00 d7 0c 00 00 d3 03 00 17 41 04 a3 |*............A..|
-00000280 03 8c de d2 b0 68 c8 25 0e 85 ea d7 ae 13 0d 79 |.....h.%.......y|
-00000290 ec 59 0d b5 4d 51 96 d9 7f 64 36 fb 4c d5 6a 26 |.Y..MQ...d6.L.j&|
-000002a0 ae 0e 48 61 df 5c 2b d4 ff 09 41 15 c4 14 8e 1b |..Ha.\+...A.....|
-000002b0 84 a8 c8 cd ef 10 97 95 66 67 85 dd fd dc 2a 04 |........fg....*.|
-000002c0 03 00 8a 30 81 87 02 41 11 75 5d bc bd 08 28 d4 |...0...A.u]...(.|
-000002d0 5b 1b 45 7f 9c d3 8d 0b 91 fa f6 82 ba 59 bd 3e |[.E..........Y.>|
-000002e0 96 01 c6 1d 38 db fe 08 e7 56 89 fc 10 b0 37 6a |....8....V....7j|
-000002f0 3d d6 c9 50 16 53 f7 c2 a2 60 67 82 1f 74 b8 d5 |=..P.S...`g..t..|
-00000300 bc 02 ec 96 db 82 18 8c 87 02 42 01 0d df f7 b7 |..........B.....|
-00000310 05 3c 8c 56 f0 1d 33 18 cf c5 4c 80 7e 0b d9 f9 |.<.V..3...L.~...|
-00000320 f0 51 69 fe 5d b8 0b 64 c0 c7 0d f4 75 65 ae 07 |.Qi.]..d....ue..|
-00000330 9d cf f4 4b ad 52 f6 b8 10 26 18 bd d6 e2 0d a8 |...K.R...&......|
-00000340 80 10 50 34 15 cd 72 0b 7d a9 94 de 4c 16 03 03 |..P4..r.}...L...|
-00000350 00 30 0d 00 00 28 03 01 02 40 00 20 06 01 06 02 |.0...(...@. ....|
-00000360 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................|
-00000370 03 02 03 03 02 01 02 02 02 03 01 01 00 00 0e 00 |................|
-00000380 00 00 |..|
+00000270 2a 16 03 03 00 d8 0c 00 00 d4 03 00 17 41 04 bb |*............A..|
+00000280 6d 5c 62 98 a7 6c bd f1 9b 4b 09 16 31 59 6a 51 |m\b..l...K..1YjQ|
+00000290 83 c8 9f 75 9c f8 09 b0 ee 39 01 e3 7a 25 9d 66 |...u.....9..z%.f|
+000002a0 fe 14 14 15 45 1b 51 a4 47 fe 1e 58 01 28 96 13 |....E.Q.G..X.(..|
+000002b0 2a 0e 0b 40 b2 22 db 2f e6 f4 88 0a 58 92 10 04 |*..@."./....X...|
+000002c0 03 00 8b 30 81 88 02 42 01 13 f5 38 52 04 f7 3b |...0...B...8R..;|
+000002d0 55 96 ef 39 77 be 4f 85 07 18 e9 47 49 b4 bb 57 |U..9w.O....GI..W|
+000002e0 c9 c0 93 2e 9e b2 5e 3f 14 ce 43 f0 93 b5 a4 66 |......^?..C....f|
+000002f0 8c fe 3a 06 fc a7 bb 9d 87 46 b8 20 1f 0a 31 c6 |..:......F. ..1.|
+00000300 80 b0 2d fa e5 06 5f 78 b2 da 02 42 01 c0 bd 12 |..-..._x...B....|
+00000310 5b ec 79 dd bf a4 54 f1 3b a8 b8 9a 50 ac a9 7c |[.y...T.;...P..||
+00000320 d2 a6 b5 dd 84 ee dd eb 3e c7 52 1c 65 ac 1e 37 |........>.R.e..7|
+00000330 4f a8 87 fa 05 8a a4 69 c9 59 53 65 ee 8e 4c 1b |O......i.YSe..L.|
+00000340 6c d0 88 b8 65 de 85 f8 fe f9 27 96 b8 c0 16 03 |l...e.....'.....|
+00000350 03 00 2e 0d 00 00 26 03 01 02 40 00 1e 06 01 06 |......&...@.....|
+00000360 02 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 |................|
+00000370 01 03 02 03 03 02 01 02 02 02 03 00 00 0e 00 00 |................|
+00000380 00 |.|
>>> Flow 3 (client to server)
00000000 16 03 03 02 0a 0b 00 02 06 00 02 03 00 02 00 30 |...............0|
00000010 82 01 fc 30 82 01 5e 02 09 00 9a 30 84 6c 26 35 |...0..^....0.l&5|
00000220 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 |Q.5uq..T[....g..|
00000230 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 |$ >.V...(^.+-O..|
00000240 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 |..lK[.V.2B.X..I.|
-00000250 b5 68 1a 41 03 56 6b dc 5a 89 16 03 03 00 92 0f |.h.A.Vk.Z.......|
-00000260 00 00 8e 04 03 00 8a 30 81 87 02 42 00 c6 85 8e |.......0...B....|
-00000270 06 b7 04 04 e9 cd 9e 3e cb 66 23 95 b4 42 9c 64 |.......>.f#..B.d|
-00000280 81 39 05 3f b5 21 f8 28 af 60 6b 4d 3d ba a1 4b |.9.?.!.(.`kM=..K|
-00000290 5e 77 ef e7 59 28 fe 1d c1 27 a2 ff a8 de 33 48 |^w..Y(...'....3H|
-000002a0 b3 c1 85 6a 42 9b f9 7e 7e 31 c2 e5 bd 66 02 41 |...jB..~~1...f.A|
-000002b0 4b 49 c6 cd 02 e3 83 f7 03 50 18 6d b4 c9 51 02 |KI.......P.m..Q.|
-000002c0 c0 ab 87 bc e0 3e 4b 89 53 3a e2 65 89 97 02 c1 |.....>K.S:.e....|
-000002d0 88 0d 64 db 8e 4f 73 4e ea 29 0b ed a0 f5 ce 3d |..d..OsN.).....=|
-000002e0 5f cc 20 ef 0a 22 02 82 f2 14 2a b7 42 68 bd c7 |_. .."....*.Bh..|
-000002f0 4d 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 |M..........@....|
-00000300 00 00 00 00 00 00 00 00 00 00 00 00 f0 cc 4f c7 |..............O.|
-00000310 b6 0f c9 38 4d 4b 97 2c 4f be 53 08 4c d6 5b 4e |...8MK.,O.S.L.[N|
-00000320 24 70 30 81 82 3a 7f 62 95 03 4d fc 54 78 ec 13 |$p0..:.b..M.Tx..|
-00000330 b2 a1 00 85 2b 04 e4 1d 7b 6e 87 60 |....+...{n.`|
+00000250 b5 68 1a 41 03 56 6b dc 5a 89 16 03 03 00 93 0f |.h.A.Vk.Z.......|
+00000260 00 00 8f 04 03 00 8b 30 81 88 02 42 00 e9 db 80 |.......0...B....|
+00000270 e2 67 5d 00 21 88 67 99 7f df de 90 77 86 1e b7 |.g].!.g.....w...|
+00000280 28 b1 2d 08 8d 02 de 9a 29 2b ca b9 9c 48 ad bd |(.-.....)+...H..|
+00000290 58 16 68 ad a3 0f 08 4c 01 52 e7 54 97 7c 06 0a |X.h....L.R.T.|..|
+000002a0 9e c8 97 61 e6 a9 53 62 fb b1 e3 b1 d7 03 02 42 |...a..Sb.......B|
+000002b0 01 f3 99 af dc e6 69 af 1d fb d5 d0 63 bd d1 17 |......i.....c...|
+000002c0 d2 ca a5 10 97 1a 94 93 df c4 94 27 53 77 1a 9e |...........'Sw..|
+000002d0 9b a5 e6 dd 0d cf 49 46 4c 5b 83 a4 52 f2 8b d6 |......IFL[..R...|
+000002e0 b2 5f 40 e5 c3 d6 7f a2 2c 50 4d 4c 81 54 80 5b |._@.....,PML.T.[|
+000002f0 72 c7 14 03 03 00 01 01 16 03 03 00 40 00 00 00 |r...........@...|
+00000300 00 00 00 00 00 00 00 00 00 00 00 00 00 96 9f 5a |...............Z|
+00000310 9c e3 d0 6c 5f 11 c4 cf e4 34 1a 54 7e dc ec 1d |...l_....4.T~...|
+00000320 cd 08 eb 5c b4 32 1b d0 e5 12 1f 7a e7 86 16 56 |...\.2.....z...V|
+00000330 a7 10 20 e1 59 31 65 63 12 7d 45 2d 2a |.. .Y1ec.}E-*|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 40 d5 2a 76 79 1c |..........@.*vy.|
-00000010 e7 d5 b1 5c 65 6b d1 45 73 53 4c 05 3a 6c 5d 81 |...\ek.EsSL.:l].|
-00000020 dd 2f f0 74 62 e4 8e f8 ed 21 99 c7 4f d6 28 40 |./.tb....!..O.(@|
-00000030 63 d9 6d e5 b0 04 73 27 7a 1d 08 19 31 10 da ef |c.m...s'z...1...|
-00000040 79 26 33 fb 45 23 be a4 7c 03 66 |y&3.E#..|.f|
+00000000 14 03 03 00 01 01 16 03 03 00 40 54 bd b1 39 e6 |..........@T..9.|
+00000010 a7 d0 76 5e 7e 91 0d 81 d1 c6 82 05 79 90 24 fc |..v^~.......y.$.|
+00000020 26 b7 ec e6 b8 72 05 59 bd 00 99 f7 dd f4 44 1e |&....r.Y......D.|
+00000030 79 4d 6d a1 22 4a e3 2c 41 05 ec 5a f7 32 17 ff |yMm."J.,A..Z.2..|
+00000040 d3 1b ee 21 71 98 99 b7 85 34 b3 |...!q....4.|
>>> Flow 5 (client to server)
00000000 17 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
-00000010 00 00 00 00 00 e2 53 bd c0 ef 9e e6 44 94 ea 5d |......S.....D..]|
-00000020 f5 c5 a9 4b ed eb 1c 49 9f 79 44 f9 cd d7 de 02 |...K...I.yD.....|
-00000030 51 10 ae 87 7d 15 03 03 00 30 00 00 00 00 00 00 |Q...}....0......|
-00000040 00 00 00 00 00 00 00 00 00 00 d3 95 13 7f 5f 58 |.............._X|
-00000050 ab d6 17 ea 01 2c 2a ea 5d 7c 44 61 4a 27 97 52 |.....,*.]|DaJ'.R|
-00000060 cc 9b 86 f6 37 42 2b 94 01 49 |....7B+..I|
+00000010 00 00 00 00 00 b9 81 3f 48 14 95 9b 39 85 2a 9e |.......?H...9.*.|
+00000020 44 ec bb cf c2 29 a9 44 f7 8a 6b 3f 92 13 dd 0e |D....).D..k?....|
+00000030 c6 6b a1 51 79 15 03 03 00 30 00 00 00 00 00 00 |.k.Qy....0......|
+00000040 00 00 00 00 00 00 00 00 00 00 1c 93 91 23 12 11 |.............#..|
+00000050 cc 30 fb 22 9e 23 b7 60 8a 3d 4c e6 52 2b 3e 6b |.0.".#.`.=L.R+>k|
+00000060 8e 47 91 b1 68 50 07 8a d1 6f |.G..hP...o|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......|
+00000000 16 03 01 00 79 01 00 00 75 03 03 00 00 00 00 00 |....y...u.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../|
-00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............|
-00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............|
-00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................|
-00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................|
-00000070 03 02 01 02 03 ff 01 00 01 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
+00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 2e |...../.5........|
+00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
+00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0a 00 |................|
+00000070 08 04 01 04 03 02 01 02 03 ff 01 00 01 00 |..............|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 51 02 00 00 4d 03 03 53 04 f1 03 b0 |....Q...M..S....|
-00000010 43 00 97 24 a7 a8 ea b2 24 fe 96 24 a1 49 64 fd |C..$....$..$.Id.|
-00000020 1c a3 30 35 2d 85 a7 40 42 86 6b 20 af 27 7f ac |..05-..@B.k .'..|
-00000030 8b 16 89 6c 78 b7 f5 29 02 58 a6 8b 61 43 c2 b0 |...lx..).X..aC..|
-00000040 e0 a8 96 c8 fa 2b 26 ad 9a 5f 2d d6 00 05 00 00 |.....+&.._-.....|
+00000000 16 03 03 00 51 02 00 00 4d 03 03 7a 6c c2 d1 69 |....Q...M..zl..i|
+00000010 af 86 6f 03 3c e4 70 ae 03 39 fd c6 3a a9 a4 b2 |..o.<.p..9..:...|
+00000020 96 1e 50 f2 f4 16 50 e4 a2 f2 41 20 f8 83 3b 45 |..P...P...A ..;E|
+00000030 0d 5b 88 bc 87 6c 81 23 e3 1d e0 7e 22 f5 6d 95 |.[...l.#...~".m.|
+00000040 58 63 39 cf 4f 80 80 cc 41 bb b1 4c 00 05 00 00 |Xc9.O...A..L....|
00000050 05 ff 01 00 01 00 16 03 03 02 be 0b 00 02 ba 00 |................|
00000060 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......|
00000070 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..|
000002e0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.|
000002f0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....|
00000300 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&|
-00000310 6e 38 50 29 6c 90 a7 bd d9 16 03 03 00 30 0d 00 |n8P)l........0..|
-00000320 00 28 03 01 02 40 00 20 06 01 06 02 06 03 05 01 |.(...@. ........|
+00000310 6e 38 50 29 6c 90 a7 bd d9 16 03 03 00 2e 0d 00 |n8P)l...........|
+00000320 00 26 03 01 02 40 00 1e 06 01 06 02 06 03 05 01 |.&...@..........|
00000330 05 02 05 03 04 01 04 02 04 03 03 01 03 02 03 03 |................|
-00000340 02 01 02 02 02 03 01 01 00 00 0e 00 00 00 |..............|
+00000340 02 01 02 02 02 03 00 00 0e 00 00 00 |............|
>>> Flow 3 (client to server)
00000000 16 03 03 02 0a 0b 00 02 06 00 02 03 00 02 00 30 |...............0|
00000010 82 01 fc 30 82 01 5e 02 09 00 9a 30 84 6c 26 35 |...0..^....0.l&5|
00000260 ce 39 4c 9c 86 00 08 c2 4b e2 c6 ec 2f f7 ce e6 |.9L.....K.../...|
00000270 bd 77 82 6f 23 b6 e0 bd a2 92 b7 3a ac e8 56 f1 |.w.o#......:..V.|
00000280 af 54 5e 46 87 e9 3b 33 e7 b8 28 b7 d6 c8 90 35 |.T^F..;3..(....5|
-00000290 d4 1c 43 d1 30 6f 55 4e 0a 70 16 03 03 00 92 0f |..C.0oUN.p......|
-000002a0 00 00 8e 04 03 00 8a 30 81 87 02 42 00 c6 85 8e |.......0...B....|
-000002b0 06 b7 04 04 e9 cd 9e 3e cb 66 23 95 b4 42 9c 64 |.......>.f#..B.d|
-000002c0 81 39 05 3f b5 21 f8 28 af 60 6b 4d 3d ba a1 4b |.9.?.!.(.`kM=..K|
-000002d0 5e 77 ef e7 59 28 fe 1d c1 27 a2 ff a8 de 33 48 |^w..Y(...'....3H|
-000002e0 b3 c1 85 6a 42 9b f9 7e 7e 31 c2 e5 bd 66 02 41 |...jB..~~1...f.A|
-000002f0 4b 49 c6 cd 02 e3 83 f7 03 50 18 6d b4 c9 51 02 |KI.......P.m..Q.|
-00000300 c0 ab 87 bc e0 3e 4b 89 53 3a e2 65 89 97 02 c1 |.....>K.S:.e....|
-00000310 88 5a 97 82 3e 55 6b 7c d8 db b8 cc 1b 30 84 0a |.Z..>Uk|.....0..|
-00000320 7a 97 71 e4 10 bb a4 39 8c 2a cf f5 88 c7 d1 95 |z.q....9.*......|
-00000330 73 14 03 03 00 01 01 16 03 03 00 24 9f 1e f0 72 |s..........$...r|
-00000340 92 ea dc f7 56 96 37 e4 69 db db 66 1d f6 94 c4 |....V.7.i..f....|
-00000350 18 31 4f d0 5d c5 f4 53 21 aa 98 b1 dc 08 94 94 |.1O.]..S!.......|
+00000290 d4 1c 43 d1 30 6f 55 4e 0a 70 16 03 03 00 93 0f |..C.0oUN.p......|
+000002a0 00 00 8f 04 03 00 8b 30 81 88 02 42 00 87 a3 50 |.......0...B...P|
+000002b0 77 2a 46 97 68 1e ca 47 d2 46 a3 f7 37 e7 1c 3c |w*F.h..G.F..7..<|
+000002c0 e3 16 dc b9 93 b9 76 af da 46 b1 da 47 bc 8b 9c |......v..F..G...|
+000002d0 ff 61 76 45 2b cf a6 85 4a 45 d4 51 98 18 31 c5 |.avE+...JE.Q..1.|
+000002e0 61 54 3b ae 88 ca 56 ac 90 29 de f2 20 a6 02 42 |aT;...V..).. ..B|
+000002f0 01 0d 54 c6 a5 14 c2 c0 83 5d ee 32 d3 c6 05 d7 |..T......].2....|
+00000300 0c 40 42 ca 8a 69 5e cc 9b f5 c4 9b 7c 81 e9 b7 |.@B..i^.....|...|
+00000310 dd 01 c0 e5 93 de 75 d2 6b 26 dd 16 2a ec d0 0e |......u.k&..*...|
+00000320 50 76 ee 36 ac 42 a3 0b 64 dd 4d 47 18 3e 5c 18 |Pv.6.B..d.MG.>\.|
+00000330 16 3b 14 03 03 00 01 01 16 03 03 00 24 c2 c7 3a |.;..........$..:|
+00000340 a2 9b 93 ea 75 1c b6 47 60 2e 15 cf b8 63 73 8a |....u..G`....cs.|
+00000350 2c b8 86 a8 12 1d cb 30 e2 38 fe 0f 02 57 43 f0 |,......0.8...WC.|
+00000360 07 |.|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 24 ee 68 c1 87 9f |..........$.h...|
-00000010 d7 90 94 f1 3b 6d 26 0b 3d 89 7a 45 3b 52 5d 3c |....;m&.=.zE;R]<|
-00000020 dd 7c c1 4e 57 3e a9 ee 91 be cf 2b a3 98 9d |.|.NW>.....+...|
+00000000 14 03 03 00 01 01 16 03 03 00 24 ca e7 84 5c 1b |..........$...\.|
+00000010 94 4c d8 78 6f 3f 80 b2 f9 9f fd c5 a5 fd 6f 89 |.L.xo?........o.|
+00000020 d7 50 a1 81 bf d0 9d eb 75 10 69 97 35 74 06 |.P......u.i.5t.|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1a 88 33 3e 2b 22 6b 92 d0 bb 8a 1e |......3>+"k.....|
-00000010 9b f4 9e aa 91 8b 2b 95 ea 53 c8 03 0a 93 58 15 |......+..S....X.|
-00000020 03 03 00 16 c4 67 79 ba ec cf 90 b1 f9 ac ec 64 |.....gy........d|
-00000030 72 01 08 8f 3a 98 aa 66 25 00 |r...:..f%.|
+00000000 17 03 03 00 1a 4a 11 45 18 75 a7 47 d3 36 ad 24 |.....J.E.u.G.6.$|
+00000010 fc d0 68 44 f2 9a 05 54 a2 44 e3 a7 33 74 99 15 |..hD...T.D..3t..|
+00000020 03 03 00 16 d5 d5 75 a9 a9 ef f5 31 50 f7 00 08 |......u....1P...|
+00000030 78 0a 00 1f c8 42 db c7 15 6b |x....B...k|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......|
+00000000 16 03 01 00 79 01 00 00 75 03 03 00 00 00 00 00 |....y...u.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../|
-00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............|
-00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............|
-00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................|
-00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................|
-00000070 03 02 01 02 03 ff 01 00 01 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
+00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 2e |...../.5........|
+00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
+00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0a 00 |................|
+00000070 08 04 01 04 03 02 01 02 03 ff 01 00 01 00 |..............|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 53 04 f1 02 fd |....Y...U..S....|
-00000010 41 bd ef ee f3 da fc 1a 31 8c 77 f2 e9 66 54 a0 |A.......1.w..fT.|
-00000020 f4 15 b1 1c 84 0d 6d 74 87 ac 7d 20 78 17 8b 08 |......mt..} x...|
-00000030 10 20 c9 44 e4 8a 43 af 4a c7 b8 3d 99 f2 f7 af |. .D..C.J..=....|
-00000040 bb a3 21 2f 40 cc ed b6 da a8 a1 d5 c0 09 00 00 |..!/@...........|
+00000000 16 03 03 00 59 02 00 00 55 03 03 ef cd 72 a3 35 |....Y...U....r.5|
+00000010 e7 11 9f 67 a4 42 9e 34 03 b4 ab e1 0d 4f a4 09 |...g.B.4.....O..|
+00000020 4e e1 8d 52 d2 d0 0e 0e f0 7a 74 20 da 3f 9c d8 |N..R.....zt .?..|
+00000030 e3 c6 5c a1 e8 5e a0 48 50 e8 70 aa 96 a7 84 4a |..\..^.HP.p....J|
+00000040 3a b3 c3 21 24 30 6c 7a d5 b4 9b 9c c0 09 00 00 |:..!$0lz........|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
00000060 03 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..|
00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....|
00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....|
00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.|
00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....|
-00000270 2a 16 03 03 00 d8 0c 00 00 d4 03 00 17 41 04 a9 |*............A..|
-00000280 19 8b d9 9b 5c 7c 6a 7d 85 d2 70 4e 89 7e 0b 5b |....\|j}..pN.~.[|
-00000290 dd 5e a1 63 8d 15 bc 0b 0c 47 3d 4d e8 a7 56 88 |.^.c.....G=M..V.|
-000002a0 2e f6 7f e2 4d fc ed cc 03 ed a1 2d ac ae 81 a5 |....M......-....|
-000002b0 e2 6d 7f 9f a3 93 e9 10 c1 0e 48 1b f3 f4 38 04 |.m........H...8.|
-000002c0 03 00 8b 30 81 88 02 42 00 87 fe 7e 63 82 14 57 |...0...B...~c..W|
-000002d0 dc 7d e2 0f cc 97 2d ba 3c a7 56 4a 17 a8 09 6a |.}....-.<.VJ...j|
-000002e0 28 2e f2 66 1a 3f 2d 48 2b 6f 79 a1 60 cd 5e 10 |(..f.?-H+oy.`.^.|
-000002f0 0b 0a 28 f2 5f e4 3f 4f f9 c9 91 34 d9 dc bc fc |..(._.?O...4....|
-00000300 98 ea 77 0b 99 f8 a2 11 c4 bd 02 42 01 a0 b0 dc |..w........B....|
-00000310 db 5b c2 09 99 bd ee a0 b9 aa 31 b9 10 84 22 be |.[........1...".|
-00000320 5a 63 12 5a 43 00 8e c1 33 cc 91 bb c2 70 7a 63 |Zc.ZC...3....pzc|
-00000330 19 82 c0 74 48 a1 c7 3d 1f f1 6f 4a 6f 6a 8c 3f |...tH..=..oJoj.?|
-00000340 28 31 a8 0c 65 19 26 62 4b 7a 7c 4b ea 1a 16 03 |(1..e.&bKz|K....|
-00000350 03 00 30 0d 00 00 28 03 01 02 40 00 20 06 01 06 |..0...(...@. ...|
+00000270 2a 16 03 03 00 d8 0c 00 00 d4 03 00 17 41 04 7e |*............A.~|
+00000280 3b ae 99 3d b7 3b da 7a 44 b1 b3 0d 41 36 c5 47 |;..=.;.zD...A6.G|
+00000290 b2 b9 65 44 79 2a c4 a9 e3 a8 ee 6a 77 3b ee d8 |..eDy*.....jw;..|
+000002a0 ee 11 0a 20 61 9b be 03 54 29 63 b3 fb 91 6f 34 |... a...T)c...o4|
+000002b0 cb ad 6c 5e 00 5f 0a c7 fd 70 d4 d6 de 5a 00 04 |..l^._...p...Z..|
+000002c0 03 00 8b 30 81 88 02 42 00 c2 21 72 c5 61 07 2f |...0...B..!r.a./|
+000002d0 0e af fd d5 22 43 e5 2e 06 51 29 73 c2 ec 50 34 |...."C...Q)s..P4|
+000002e0 76 ab 67 fe 37 49 68 54 4b 16 d2 7a 4c 04 02 b2 |v.g.7IhTK..zL...|
+000002f0 0a 66 28 fb b5 bf 5b 00 4b dc bf e2 9e 99 a7 0c |.f(...[.K.......|
+00000300 7c 64 36 79 d6 4e 99 70 5f 97 02 42 01 bb 4b 10 ||d6y.N.p_..B..K.|
+00000310 36 f1 38 c1 42 de e9 68 41 2d 0a 4b 19 eb 3c 6b |6.8.B..hA-.K..<k|
+00000320 cd 11 3e 20 3f 95 c3 c7 ba 18 0c 4a 6a da 45 77 |..> ?......Jj.Ew|
+00000330 8c 8d f4 01 d3 15 91 3e 64 22 16 bd b5 2a 07 52 |.......>d"...*.R|
+00000340 63 e5 de 0c 22 90 2e 2f e9 b4 3f ab b8 27 16 03 |c..."../..?..'..|
+00000350 03 00 2e 0d 00 00 26 03 01 02 40 00 1e 06 01 06 |......&...@.....|
00000360 02 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 |................|
-00000370 01 03 02 03 03 02 01 02 02 02 03 01 01 00 00 0e |................|
-00000380 00 00 00 |...|
+00000370 01 03 02 03 03 02 01 02 02 02 03 00 00 0e 00 00 |................|
+00000380 00 |.|
>>> Flow 3 (client to server)
00000000 16 03 03 01 fb 0b 00 01 f7 00 01 f4 00 01 f1 30 |...............0|
00000010 82 01 ed 30 82 01 58 a0 03 02 01 02 02 01 00 30 |...0..X........0|
00000220 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.|
00000230 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
00000240 a6 b5 68 1a 41 03 56 6b dc 5a 89 16 03 03 00 88 |..h.A.Vk.Z......|
-00000250 0f 00 00 84 04 01 00 80 38 f2 16 e5 b5 86 16 62 |........8......b|
-00000260 86 e1 7d 01 f1 a8 e1 f7 e7 85 b1 a0 17 ee 84 25 |..}............%|
-00000270 cb 3c 46 61 1a 78 7b 1e ee 32 bc d9 6c fa 6b 76 |.<Fa.x{..2..l.kv|
-00000280 67 a7 9e c8 7a 4c e8 79 0d 22 27 ad e7 98 6a 98 |g...zL.y."'...j.|
-00000290 89 88 8b a9 69 5b 6f c6 00 48 9a 21 77 a9 7c 15 |....i[o..H.!w.|.|
-000002a0 ba 47 16 74 8d 6c 67 dc 6d f1 98 b6 61 e8 bc 08 |.G.t.lg.m...a...|
-000002b0 18 53 a6 93 bf fc 27 5e b7 4d d2 eb 68 e9 23 ee |.S....'^.M..h.#.|
-000002c0 d2 70 d2 55 2c c7 99 7d c0 66 b5 1c ea 38 71 5c |.p.U,..}.f...8q\|
-000002d0 a6 57 1f 52 e4 8e e8 51 14 03 03 00 01 01 16 03 |.W.R...Q........|
+00000250 0f 00 00 84 04 01 00 80 07 7e 14 14 83 b9 d9 52 |.........~.....R|
+00000260 fd db c0 a4 79 37 b7 91 0b bb d6 ab d0 d1 c8 2e |....y7..........|
+00000270 35 5b 58 3f ce 6b f6 a9 01 95 34 a9 8b da 6b 23 |5[X?.k....4...k#|
+00000280 b7 99 11 75 3e f8 db bc ab 9b d4 8f 4f 89 12 d9 |...u>.......O...|
+00000290 2d 18 0e 54 2d 61 ff 9a 0e 3d 50 66 1d c2 e0 f6 |-..T-a...=Pf....|
+000002a0 4d 65 ca e2 08 af 29 cf 6d ab 63 72 ad 7c 03 a1 |Me....).m.cr.|..|
+000002b0 1e a1 f4 75 f5 54 58 28 3b 7d f7 21 d5 67 ec 60 |...u.TX(;}.!.g.`|
+000002c0 3b 59 81 ac f5 9a c6 cb 6a af da 7e 29 c4 c2 68 |;Y......j..~)..h|
+000002d0 53 34 aa b8 0e 58 61 24 14 03 03 00 01 01 16 03 |S4...Xa$........|
000002e0 03 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............|
-000002f0 00 00 00 5e e7 6e 1c a2 02 24 34 f0 a6 b6 27 ea |...^.n...$4...'.|
-00000300 69 d5 0e 2e a8 ad 5c ad 6c 06 78 68 39 92 27 f1 |i.....\.l.xh9.'.|
-00000310 e8 35 49 67 4d fb 5d 8a 31 2e 4e 3f 19 ed ea 30 |.5IgM.].1.N?...0|
-00000320 20 60 e1 | `.|
+000002f0 00 00 00 a4 af 4b 95 ec 53 cf 49 8d b4 6c e0 3b |.....K..S.I..l.;|
+00000300 76 60 23 9b 2a f3 2c 12 61 18 cf 56 7c 1d 8c 01 |v`#.*.,.a..V|...|
+00000310 a8 bb 19 4d 1f ff ff 73 a2 90 e5 87 7b 85 d3 1b |...M...s....{...|
+00000320 74 6d 36 |tm6|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 40 ee a8 82 bc 3f |..........@....?|
-00000010 bf ab a6 e4 30 e0 3d f1 2f 19 a2 ac 7a 81 57 f1 |....0.=./...z.W.|
-00000020 ee 67 3f 55 2b 30 fa 72 b5 10 03 ec 8d 0a 8f bb |.g?U+0.r........|
-00000030 24 f5 45 f5 4e 53 4b 93 a5 0d 42 6c 46 69 98 fb |$.E.NSK...BlFi..|
-00000040 63 c5 9f 95 65 d1 b6 f0 a4 15 bd |c...e......|
+00000000 14 03 03 00 01 01 16 03 03 00 40 fb 28 05 0a 99 |..........@.(...|
+00000010 61 d1 c7 52 a7 9e 95 a5 c1 11 3c 81 ee f2 b8 68 |a..R......<....h|
+00000020 a6 35 e2 7e bb 3c e7 7b 61 72 08 29 3a a5 e9 d3 |.5.~.<.{ar.):...|
+00000030 39 9c d2 0f 38 12 9b 92 79 36 58 bc f3 23 85 76 |9...8...y6X..#.v|
+00000040 1c 7b 6c 49 0c bc 00 61 20 1b ff |.{lI...a ..|
>>> Flow 5 (client to server)
00000000 17 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
-00000010 00 00 00 00 00 cb 4e bc d1 a9 58 ef c8 39 a9 36 |......N...X..9.6|
-00000020 f4 35 05 96 8e a4 50 bc f4 15 06 f9 fd 41 6d 1e |.5....P......Am.|
-00000030 5e 7c 82 63 94 15 03 03 00 30 00 00 00 00 00 00 |^|.c.....0......|
-00000040 00 00 00 00 00 00 00 00 00 00 bd 77 87 a5 5a d4 |...........w..Z.|
-00000050 b8 59 e6 6b 0f dd ea f9 ed 18 b2 9f a9 61 b4 3a |.Y.k.........a.:|
-00000060 47 15 15 3b 83 ef e1 6d db a8 |G..;...m..|
+00000010 00 00 00 00 00 fa f6 0b 1f f6 28 c7 4c 6c c8 8d |..........(.Ll..|
+00000020 9c 97 5f 3d 22 bb 45 fc 07 ae 3a 7e 74 01 7c 71 |.._=".E...:~t.|q|
+00000030 39 45 15 d3 c7 15 03 03 00 30 00 00 00 00 00 00 |9E.......0......|
+00000040 00 00 00 00 00 00 00 00 00 00 a1 43 03 79 a4 4e |...........C.y.N|
+00000050 bd 0f 17 c4 d0 29 1a 8a dd 7b e7 48 3c e4 4b 8a |.....)...{.H<.K.|
+00000060 53 3d 1d 18 f9 05 fd 4b 73 4a |S=.....KsJ|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......|
+00000000 16 03 01 00 79 01 00 00 75 03 03 00 00 00 00 00 |....y...u.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../|
-00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............|
-00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............|
-00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................|
-00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................|
-00000070 03 02 01 02 03 ff 01 00 01 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
+00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 2e |...../.5........|
+00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
+00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0a 00 |................|
+00000070 08 04 01 04 03 02 01 02 03 ff 01 00 01 00 |..............|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 51 02 00 00 4d 03 03 53 04 f1 02 1d |....Q...M..S....|
-00000010 0e dc 86 e5 a9 07 71 46 15 34 af 47 15 3f 03 9c |......qF.4.G.?..|
-00000020 fc d6 fd 44 7c f4 f1 c7 8d 6f f8 20 28 ea 3c dc |...D|....o. (.<.|
-00000030 b2 4c b7 ba 20 88 c4 db a5 73 ea 93 ab 3a 85 a6 |.L.. ....s...:..|
-00000040 8f 59 49 d9 a9 31 14 d5 a6 2b 4f d1 00 05 00 00 |.YI..1...+O.....|
+00000000 16 03 03 00 51 02 00 00 4d 03 03 32 d8 c5 23 e3 |....Q...M..2..#.|
+00000010 c7 4c d9 e9 d9 bd 1d d4 70 60 df 01 46 dc ca c5 |.L......p`..F...|
+00000020 d3 1b 57 28 f0 c4 4b 1c b3 8d 13 20 4a b8 d7 eb |..W(..K.... J...|
+00000030 70 9e e5 6d 6f 8c d4 0d a4 25 3a ce 91 e0 25 68 |p..mo....%:...%h|
+00000040 6f 25 38 0d 91 57 af 28 39 9c 61 85 00 05 00 00 |o%8..W.(9.a.....|
00000050 05 ff 01 00 01 00 16 03 03 02 be 0b 00 02 ba 00 |................|
00000060 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......|
00000070 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..|
000002e0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.|
000002f0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....|
00000300 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&|
-00000310 6e 38 50 29 6c 90 a7 bd d9 16 03 03 00 30 0d 00 |n8P)l........0..|
-00000320 00 28 03 01 02 40 00 20 06 01 06 02 06 03 05 01 |.(...@. ........|
+00000310 6e 38 50 29 6c 90 a7 bd d9 16 03 03 00 2e 0d 00 |n8P)l...........|
+00000320 00 26 03 01 02 40 00 1e 06 01 06 02 06 03 05 01 |.&...@..........|
00000330 05 02 05 03 04 01 04 02 04 03 03 01 03 02 03 03 |................|
-00000340 02 01 02 02 02 03 01 01 00 00 0e 00 00 00 |..............|
+00000340 02 01 02 02 02 03 00 00 0e 00 00 00 |............|
>>> Flow 3 (client to server)
00000000 16 03 03 01 fb 0b 00 01 f7 00 01 f4 00 01 f1 30 |...............0|
00000010 82 01 ed 30 82 01 58 a0 03 02 01 02 02 01 00 30 |...0..X........0|
00000260 e6 bd 77 82 6f 23 b6 e0 bd a2 92 b7 3a ac e8 56 |..w.o#......:..V|
00000270 f1 af 54 5e 46 87 e9 3b 33 e7 b8 28 b7 d6 c8 90 |..T^F..;3..(....|
00000280 35 d4 1c 43 d1 30 6f 55 4e 0a 70 16 03 03 00 88 |5..C.0oUN.p.....|
-00000290 0f 00 00 84 04 01 00 80 2a 1f ae 48 9f 86 16 dc |........*..H....|
-000002a0 c2 55 1f 5f 95 81 ed 56 00 5d 35 46 e5 b6 57 d5 |.U._...V.]5F..W.|
-000002b0 a6 3e 32 38 8b e2 c6 1c b9 b1 38 b2 da 66 45 ed |.>28......8..fE.|
-000002c0 58 6a 7f 43 41 93 a5 09 da b9 04 ce 3f 13 8a 19 |Xj.CA.......?...|
-000002d0 13 e9 2c 1f c5 e7 35 b4 2d ea 7c 81 90 33 c0 66 |..,...5.-.|..3.f|
-000002e0 dc 41 8b 23 08 8f 69 d4 d6 a2 5f c1 bd 26 e6 2e |.A.#..i..._..&..|
-000002f0 7f c8 7c a8 2d d4 08 95 ce 6e 58 54 04 a2 a6 63 |..|.-....nXT...c|
-00000300 54 72 67 f2 7f 61 0a 6b 58 46 d4 88 95 38 37 f2 |Trg..a.kXF...87.|
-00000310 93 95 48 56 14 a7 b9 7c 14 03 03 00 01 01 16 03 |..HV...|........|
-00000320 03 00 24 64 bb 41 3a cb a2 2f 95 53 5c 2f f7 83 |..$d.A:../.S\/..|
-00000330 a2 35 18 f6 d0 8d 6f e2 54 ed 2f 07 10 f4 36 e2 |.5....o.T./...6.|
-00000340 3d e5 30 1d e3 63 01 |=.0..c.|
+00000290 0f 00 00 84 04 01 00 80 3a 55 0a c6 97 2d 71 bc |........:U...-q.|
+000002a0 9d e1 ec 5b cb 3d de 64 8e fd 99 c0 55 1f d5 d1 |...[.=.d....U...|
+000002b0 ae 74 79 b8 1d 25 3e 4d 19 32 62 ca 04 82 f4 3f |.ty..%>M.2b....?|
+000002c0 7c 2b 7a 82 a6 86 2b d3 ba b0 ad 48 c4 c9 33 e6 ||+z...+....H..3.|
+000002d0 c8 2c 4a 06 75 a6 e7 49 65 53 54 33 27 55 7a 30 |.,J.u..IeST3'Uz0|
+000002e0 55 64 ef a0 d9 96 29 69 3f 90 ba b3 e4 aa 4e 5f |Ud....)i?.....N_|
+000002f0 1d 00 c2 90 c2 04 f9 9b 7f f1 e5 fd f2 1e 57 fd |..............W.|
+00000300 fc 0b 70 81 71 9a 43 9b 80 ff 96 42 f5 8d ff 2f |..p.q.C....B.../|
+00000310 4f d9 48 e2 6e bf 9e f2 14 03 03 00 01 01 16 03 |O.H.n...........|
+00000320 03 00 24 32 b3 61 bd 9a e1 21 79 60 f0 4b 6c 26 |..$2.a...!y`.Kl&|
+00000330 15 91 14 6d bc 42 9b c0 21 5f 93 2d d0 f7 db 9f |...m.B..!_.-....|
+00000340 81 60 bd d6 34 fa 31 |.`..4.1|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 24 0a 22 b6 bc da |..........$."...|
-00000010 34 38 53 8e 80 e2 25 7b 31 2f 70 8e 3a db e8 a3 |48S...%{1/p.:...|
-00000020 70 0e 88 22 b4 a8 be d4 a3 e3 cc 13 94 ef 47 |p.."..........G|
+00000000 14 03 03 00 01 01 16 03 03 00 24 5c 99 fe 86 6f |..........$\...o|
+00000010 89 c3 e1 ed 24 1f a5 81 a8 fd 2a 8d 28 01 cd 86 |....$.....*.(...|
+00000020 11 48 5c 13 fe f4 29 dd ff 15 70 da 68 3b d8 |.H\...)...p.h;.|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1a b4 9c b1 57 ea 01 03 fe 01 e7 1e |........W.......|
-00000010 c4 a7 0f 25 14 99 00 4f 88 51 c1 98 6e 99 01 15 |...%...O.Q..n...|
-00000020 03 03 00 16 2e c4 11 8b 1a fc 37 81 18 33 e4 9f |..........7..3..|
-00000030 48 a3 29 e3 ad 9b 9b ec 9f 99 |H.).......|
+00000000 17 03 03 00 1a a9 5b 30 f3 9d 98 b0 a6 a6 4c 52 |......[0......LR|
+00000010 35 c9 aa 88 24 12 0f b0 53 88 21 8a 39 56 62 15 |5...$...S.!.9Vb.|
+00000020 03 03 00 16 ff 5f 0a cf 48 2a bd 2f e9 db 50 bc |....._..H*./..P.|
+00000030 11 3c c8 d2 61 69 6c 84 22 bf |.<..ail.".|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......|
+00000000 16 03 01 00 79 01 00 00 75 03 03 00 00 00 00 00 |....y...u.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../|
-00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............|
-00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............|
-00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................|
-00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................|
-00000070 03 02 01 02 03 ff 01 00 01 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
+00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 2e |...../.5........|
+00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
+00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0a 00 |................|
+00000070 08 04 01 04 03 02 01 02 03 ff 01 00 01 00 |..............|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 53 04 f1 02 a0 |....Y...U..S....|
-00000010 5f bd a4 8d 98 93 b8 da 08 86 9f b2 be 9a a4 91 |_...............|
-00000020 2b 3c 1f 18 f0 75 7c a9 a8 a0 f7 20 4a 89 9a d2 |+<...u|.... J...|
-00000030 34 3b d9 b1 c2 fd 61 bd 97 19 22 ce b9 d1 5b a7 |4;....a..."...[.|
-00000040 83 80 9c 19 d0 f5 a0 aa 4c ac 06 20 c0 09 00 00 |........L.. ....|
+00000000 16 03 03 00 59 02 00 00 55 03 03 97 dc 20 65 0f |....Y...U.... e.|
+00000010 3f 83 4a 55 06 27 32 2f 68 81 f9 4a 6d 0a 8c 3e |?.JU.'2/h..Jm..>|
+00000020 c0 aa c1 c2 e1 09 a8 a0 a5 e3 42 20 7b ed 80 22 |..........B {.."|
+00000030 22 f9 84 ab 6d f5 63 18 bc f8 dc 7d 13 31 6b 4b |"...m.c....}.1kK|
+00000040 85 c0 63 8d e5 d8 29 c8 ad 09 d7 b7 c0 09 00 00 |..c...).........|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
00000060 03 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..|
00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....|
00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....|
00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.|
00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....|
-00000270 2a 16 03 03 00 d7 0c 00 00 d3 03 00 17 41 04 3c |*............A.<|
-00000280 8f 35 1e 47 5d 7b ad 13 0c e9 5c c0 97 c7 83 06 |.5.G]{....\.....|
-00000290 49 0f 6c cf e5 4d 3b ed f7 1b c6 96 8d ba 54 35 |I.l..M;.......T5|
-000002a0 7f df 35 e3 6e 28 e9 71 f2 24 b5 ab 17 2b 4b 2b |..5.n(.q.$...+K+|
-000002b0 0c 8f 9f 48 89 73 8f 09 69 84 af 7f ec 43 7a 04 |...H.s..i....Cz.|
-000002c0 03 00 8a 30 81 87 02 41 79 84 43 0c 78 fa 7e e2 |...0...Ay.C.x.~.|
-000002d0 c5 51 c1 60 88 c4 4a 59 7d 02 fa dc 19 68 33 ed |.Q.`..JY}....h3.|
-000002e0 19 ef a1 df ef 6b 21 a6 98 aa ba a9 13 70 91 0f |.....k!......p..|
-000002f0 cc 6c 5c 1e 99 53 1b 42 51 6c 06 a7 3c c4 04 22 |.l\..S.BQl..<.."|
-00000300 5d 0d c1 30 ab e3 ec b4 54 02 42 01 15 15 1a 6e |]..0....T.B....n|
-00000310 6f f1 c6 b1 10 84 2c c8 04 de 2b 52 d5 b4 f7 c9 |o.....,...+R....|
-00000320 4f 6d 0e 0e 26 45 1d 7a 28 59 2b 8b f6 92 3a 23 |Om..&E.z(Y+...:#|
-00000330 7a 39 9c d5 4e cc 5d c5 45 92 9c d0 5f 33 12 e3 |z9..N.].E..._3..|
-00000340 2b 29 39 52 bb 16 aa e1 72 9e b5 fe 99 16 03 03 |+)9R....r.......|
-00000350 00 04 0e 00 00 00 |......|
+00000270 2a 16 03 03 00 d8 0c 00 00 d4 03 00 17 41 04 dd |*............A..|
+00000280 34 64 e4 ba 63 e0 25 f2 6b cd 24 21 58 8b e1 08 |4d..c.%.k.$!X...|
+00000290 eb 09 6f 93 e2 cd 19 13 d0 e6 5a 0c ee 57 b9 ab |..o.......Z..W..|
+000002a0 21 be 8d b5 47 1e a8 01 a4 de c4 de a7 d5 eb dd |!...G...........|
+000002b0 d9 bd 66 1a 71 0a b7 a1 3d 10 8e b6 2d 73 ba 04 |..f.q...=...-s..|
+000002c0 03 00 8b 30 81 88 02 42 01 c6 4a 64 2b 66 7f cb |...0...B..Jd+f..|
+000002d0 28 eb ad 05 d4 86 a0 d6 0f 12 52 03 fc 66 3f 76 |(.........R..f?v|
+000002e0 db 85 8f b4 f1 45 04 f5 10 27 b3 76 62 9a bc 7b |.....E...'.vb..{|
+000002f0 f9 6e f6 45 fb 15 9c eb 5c 70 ca b2 40 00 f8 18 |.n.E....\p..@...|
+00000300 b9 e4 28 fc e4 b7 d8 15 70 1a 02 42 01 d3 8f 53 |..(.....p..B...S|
+00000310 57 b5 e4 f5 84 97 a2 e9 07 5a f8 67 bd 03 02 6d |W........Z.g...m|
+00000320 ea 4e 14 da 12 2c d0 7c 89 a0 93 97 46 c9 62 ee |.N...,.|....F.b.|
+00000330 c0 d3 d6 bf 04 11 af 19 96 6b a9 86 f8 2c 2f ab |.........k...,/.|
+00000340 89 20 45 94 b6 d1 43 64 fc eb 2e ff 80 37 16 03 |. E...Cd.....7..|
+00000350 03 00 04 0e 00 00 00 |.......|
>>> Flow 3 (client to server)
00000000 16 03 03 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..|
00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.|
00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 03 00 01 |..h.A.Vk.Z......|
00000050 01 16 03 03 00 40 00 00 00 00 00 00 00 00 00 00 |.....@..........|
-00000060 00 00 00 00 00 00 20 a3 f8 5a e2 ea f3 09 19 3e |...... ..Z.....>|
-00000070 4a 54 69 70 06 5b 17 35 0f ed e7 30 3b 6f eb a1 |JTip.[.5...0;o..|
-00000080 cb 9c 35 81 10 2e 34 f7 12 a5 e4 63 20 b2 65 31 |..5...4....c .e1|
-00000090 19 da 30 43 39 59 |..0C9Y|
+00000060 00 00 00 00 00 00 21 2a 44 9c f5 f7 b5 0f 43 f4 |......!*D.....C.|
+00000070 19 03 02 64 c0 9a a0 d1 50 89 f2 f2 dd a1 dc 72 |...d....P......r|
+00000080 da 08 d1 5c 75 fa 54 ee bf c8 76 5f 57 df 62 2b |...\u.T...v_W.b+|
+00000090 36 48 40 c4 a4 ac |6H@...|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 40 8d 4d 31 07 df |..........@.M1..|
-00000010 ab 41 f5 19 9c 1a 57 fc 33 ab 5f e6 bd 45 b9 fa |.A....W.3._..E..|
-00000020 7f db c0 df 72 f2 3b ef aa d4 5e 34 e6 3d 44 7c |....r.;...^4.=D||
-00000030 12 05 c7 57 da 54 b1 e3 66 f0 0a ab cd 15 a5 bf |...W.T..f.......|
-00000040 c5 c2 07 a9 d9 a7 2e 5e 29 da da |.......^)..|
+00000000 14 03 03 00 01 01 16 03 03 00 40 72 a7 fe d8 23 |..........@r...#|
+00000010 6a 4f 4c 11 09 5d 0e d3 86 4e d6 e8 96 cb ac 71 |jOL..]...N.....q|
+00000020 68 e2 50 94 eb e4 d2 9b 61 56 e2 17 50 5e fb b2 |h.P.....aV..P^..|
+00000030 fe a0 1f 8d 74 2c c6 d0 ba 5e f7 73 b8 00 8d b5 |....t,...^.s....|
+00000040 57 e1 41 90 21 15 91 6d 69 25 83 |W.A.!..mi%.|
>>> Flow 5 (client to server)
00000000 17 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
-00000010 00 00 00 00 00 dc 03 7b 29 2c 49 64 58 2d dc f7 |.......{),IdX-..|
-00000020 26 a1 3b ec 2d e8 30 c4 6c a3 ff e2 bc b5 a4 a6 |&.;.-.0.l.......|
-00000030 93 ce 14 bd da 15 03 03 00 30 00 00 00 00 00 00 |.........0......|
-00000040 00 00 00 00 00 00 00 00 00 00 a6 77 10 30 15 eb |...........w.0..|
-00000050 ed cf 73 5b 74 5d 09 52 4a 5b e2 f0 e4 67 f8 7a |..s[t].RJ[...g.z|
-00000060 5e 5e fc ba 7f 80 0a d2 f4 fb |^^........|
+00000010 00 00 00 00 00 80 70 b8 c4 f1 ef 0c 2e 87 5c fc |......p.......\.|
+00000020 fb 54 19 4d 42 42 09 32 32 dd 54 b9 6e 35 ea 13 |.T.MBB.22.T.n5..|
+00000030 e1 2b 4c 7e e6 15 03 03 00 30 00 00 00 00 00 00 |.+L~.....0......|
+00000040 00 00 00 00 00 00 00 00 00 00 3e aa 24 38 78 63 |..........>.$8xc|
+00000050 ae 5c d4 28 2d 3b 7c 1b 66 2f 07 02 00 e1 78 dd |.\.(-;|.f/....x.|
+00000060 6e 43 e7 23 da 55 55 33 a2 d8 |nC.#.UU3..|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......|
+00000000 16 03 01 00 79 01 00 00 75 03 03 00 00 00 00 00 |....y...u.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../|
-00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............|
-00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............|
-00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................|
-00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................|
-00000070 03 02 01 02 03 ff 01 00 01 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
+00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 2e |...../.5........|
+00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
+00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0a 00 |................|
+00000070 08 04 01 04 03 02 01 02 03 ff 01 00 01 00 |..............|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 53 04 f1 02 48 |....Y...U..S...H|
-00000010 03 36 01 05 56 6f f0 54 d2 c3 d3 41 c2 e2 69 7b |.6..Vo.T...A..i{|
-00000020 50 f8 03 ef 3f 5d 7c e6 9c cb fe 20 82 a0 81 fd |P...?]|.... ....|
-00000030 72 4b b8 e6 29 76 3b 0f 1d 0a b7 82 9d 0b cf a0 |rK..)v;.........|
-00000040 65 b1 56 53 c9 d5 58 7b f0 b6 2d cf c0 2b 00 00 |e.VS..X{..-..+..|
+00000000 16 03 03 00 59 02 00 00 55 03 03 c9 39 e6 18 c8 |....Y...U...9...|
+00000010 4a 7f f3 23 75 99 22 80 48 bc e3 a7 eb 49 d5 95 |J..#u.".H....I..|
+00000020 b1 ec 1d 9e 44 09 6e d9 b7 b2 f8 20 30 fd 2b 50 |....D.n.... 0.+P|
+00000030 d2 91 de c3 d0 84 a9 d5 ba c0 45 0f 18 c4 98 73 |..........E....s|
+00000040 4b cf c6 82 dd 88 0d 35 28 8e f8 d3 c0 2b 00 00 |K......5(....+..|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
00000060 03 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..|
00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....|
00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....|
00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.|
00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....|
-00000270 2a 16 03 03 00 d7 0c 00 00 d3 03 00 17 41 04 86 |*............A..|
-00000280 36 b4 78 76 87 70 ed ae 0d 34 70 3d 16 e5 a4 db |6.xv.p...4p=....|
-00000290 ae 28 58 4c 01 5a 56 73 a7 0d 34 59 a7 04 75 69 |.(XL.ZVs..4Y..ui|
-000002a0 f2 55 24 40 b0 33 c6 93 ff ae e0 14 f5 4b ce a8 |.U$@.3.......K..|
-000002b0 e2 e6 9a 67 1d 66 fb 8f fd 56 59 e7 73 f2 2c 04 |...g.f...VY.s.,.|
-000002c0 03 00 8a 30 81 87 02 41 73 ab a8 3c 64 17 69 9f |...0...As..<d.i.|
-000002d0 4d b2 9b 55 12 60 33 94 cf f3 83 40 2b 7b 1b af |M..U.`3....@+{..|
-000002e0 5c f4 cd 02 66 fb 83 04 35 fd ab 74 98 1a 7d f6 |\...f...5..t..}.|
-000002f0 9e 50 98 c3 98 e8 56 9c f2 2a b0 30 9d 05 14 58 |.P....V..*.0...X|
-00000300 68 6a 88 04 49 07 78 bf 3a 02 42 01 be b2 05 9e |hj..I.x.:.B.....|
-00000310 67 da 1e e9 5a 36 98 52 21 9f 43 75 43 ba bb 9a |g...Z6.R!.CuC...|
-00000320 e6 e2 65 f4 e0 44 45 08 5a 1e 54 06 dd 5f 60 2e |..e..DE.Z.T.._`.|
-00000330 7d e7 55 08 d3 7b 4e 0a c7 da d4 27 34 d4 bd b0 |}.U..{N....'4...|
-00000340 12 2f 41 7a ed 71 32 ef ee 12 74 66 00 16 03 03 |./Az.q2...tf....|
-00000350 00 04 0e 00 00 00 |......|
+00000270 2a 16 03 03 00 d8 0c 00 00 d4 03 00 17 41 04 91 |*............A..|
+00000280 d0 f0 1b df 51 57 74 f3 62 ee d5 9e e8 7d bd 65 |....QWt.b....}.e|
+00000290 69 0a 5a 2b 75 c3 3c f7 24 3f 91 26 34 fe d8 8f |i.Z+u.<.$?.&4...|
+000002a0 fa d3 7e f6 f5 01 89 7b f5 69 5c c2 52 41 81 93 |..~....{.i\.RA..|
+000002b0 c4 9e 01 5d 96 fa db 41 3d 0b 78 58 ad 29 b5 04 |...]...A=.xX.)..|
+000002c0 03 00 8b 30 81 88 02 42 01 92 7c 0a 7c 79 d1 41 |...0...B..|.|y.A|
+000002d0 98 b7 57 37 10 d9 31 41 2e fe d5 a8 94 26 fa 59 |..W7..1A.....&.Y|
+000002e0 78 bf 15 c0 cf e7 a9 09 a8 6f 97 45 1b 3f e6 60 |x........o.E.?.`|
+000002f0 2d 78 dc ec 99 0f 92 43 64 20 c4 6b 59 16 df 66 |-x.....Cd .kY..f|
+00000300 83 a0 f1 d1 91 c1 8a 29 ce 4d 02 42 01 61 a2 6c |.......).M.B.a.l|
+00000310 84 58 58 0b 74 fa 9e 4c 33 6a b5 b1 a9 da ad 1c |.XX.t..L3j......|
+00000320 d9 33 25 91 59 a0 f2 21 ae b1 14 15 4a d1 65 50 |.3%.Y..!....J.eP|
+00000330 0e 1d 1e bc f6 29 da 22 09 20 de 75 30 ac 0a 1e |.....).". .u0...|
+00000340 7e 46 98 89 dd 6d e4 6a 9b 83 b5 85 f3 74 16 03 |~F...m.j.....t..|
+00000350 03 00 04 0e 00 00 00 |.......|
>>> Flow 3 (client to server)
00000000 16 03 03 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..|
00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.|
00000020 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.|
00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 03 00 01 |..h.A.Vk.Z......|
-00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 87 7a |.....(.........z|
-00000060 82 d7 46 25 1d a6 bb c2 a8 a8 4e a5 d1 f8 02 db |..F%......N.....|
-00000070 33 33 ca 78 b6 d3 bd 77 8a 33 23 a7 95 fb |33.x...w.3#...|
+00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 b0 4d |.....(.........M|
+00000060 e2 ad 33 40 f2 44 e3 c7 ad a5 c6 c7 e5 00 07 68 |..3@.D.........h|
+00000070 72 80 d5 89 f0 aa 72 2b 36 5a 51 f6 f0 6a |r.....r+6ZQ..j|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 28 ce a1 9d 01 c0 |..........(.....|
-00000010 31 e5 d5 57 16 e1 a6 b3 8b 25 58 0f fa 2a de 3e |1..W.....%X..*.>|
-00000020 0c d9 06 11 a6 b0 d7 b0 33 ad 31 73 5b 26 b4 d2 |........3.1s[&..|
-00000030 12 56 c8 |.V.|
+00000000 14 03 03 00 01 01 16 03 03 00 28 5d b6 1b 59 71 |..........(]..Yq|
+00000010 f0 7a 2c 4f d5 f0 7b a7 ab 56 48 4d b4 f7 5c bc |.z,O..{..VHM..\.|
+00000020 34 d6 cc 02 4f 1f 45 b2 e9 ff 96 0e a2 47 d6 4e |4...O.E......G.N|
+00000030 47 83 68 |G.h|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 d5 04 4c |...............L|
-00000010 7b 35 b4 d7 90 ae fe 00 d2 f2 4b 76 f1 36 5e 24 |{5........Kv.6^$|
-00000020 4a aa 94 15 03 03 00 1a 00 00 00 00 00 00 00 02 |J...............|
-00000030 d3 1c 41 37 ab f6 17 79 f0 01 a4 19 a5 75 7a 8e |..A7...y.....uz.|
-00000040 a3 b2 |..|
+00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 2f f1 95 |............./..|
+00000010 75 5e 0d fb 48 9b 40 10 6d bb 81 7e d2 ca 68 ae |u^..H.@.m..~..h.|
+00000020 84 47 d2 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.G..............|
+00000030 26 87 82 85 fa 5f a2 b2 19 b2 4e 81 f6 0f c6 c5 |&...._....N.....|
+00000040 e0 3e |.>|
--- /dev/null
+>>> Flow 1 (client to server)
+00000000 16 03 01 00 79 01 00 00 75 03 03 00 00 00 00 00 |....y...u.......|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
+00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 2e |...../.5........|
+00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
+00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0a 00 |................|
+00000070 08 04 01 04 03 02 01 02 03 ff 01 00 01 00 |..............|
+>>> Flow 2 (server to client)
+00000000 16 03 03 00 59 02 00 00 55 03 03 d2 dd 5a 60 0d |....Y...U....Z`.|
+00000010 25 72 ed e6 89 6e 4d d8 1c 75 76 e4 37 5f 06 80 |%r...nM..uv.7_..|
+00000020 26 23 48 02 cd c6 b1 e5 59 89 b2 20 99 9e e6 31 |&#H.....Y.. ...1|
+00000030 8f ca b2 aa 68 b2 6b 2e c0 f3 f8 e9 56 f4 60 90 |....h.k.....V.`.|
+00000040 bb 5d 79 fd 4f f5 71 15 5b e7 31 20 c0 2c 00 00 |.]y.O.q.[.1 .,..|
+00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
+00000060 03 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..|
+00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....|
+00000080 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 0b 30 |0...*.H.=..0E1.0|
+00000090 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...|
+000000a0 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1|
+000000b0 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern|
+000000c0 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L|
+000000d0 74 64 30 1e 17 0d 31 32 31 31 32 32 31 35 30 36 |td0...1211221506|
+000000e0 33 32 5a 17 0d 32 32 31 31 32 30 31 35 30 36 33 |32Z..22112015063|
+000000f0 32 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 |2Z0E1.0...U....A|
+00000100 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 |U1.0...U....Some|
+00000110 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 |-State1!0...U...|
+00000120 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 |.Internet Widgit|
+00000130 73 20 50 74 79 20 4c 74 64 30 81 9b 30 10 06 07 |s Pty Ltd0..0...|
+00000140 2a 86 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 |*.H.=....+...#..|
+00000150 86 00 04 00 c4 a1 ed be 98 f9 0b 48 73 36 7e c3 |...........Hs6~.|
+00000160 16 56 11 22 f2 3d 53 c3 3b 4d 21 3d cd 6b 75 e6 |.V.".=S.;M!=.ku.|
+00000170 f6 b0 dc 9a df 26 c1 bc b2 87 f0 72 32 7c b3 64 |.....&.....r2|.d|
+00000180 2f 1c 90 bc ea 68 23 10 7e fe e3 25 c0 48 3a 69 |/....h#.~..%.H:i|
+00000190 e0 28 6d d3 37 00 ef 04 62 dd 0d a0 9c 70 62 83 |.(m.7...b....pb.|
+000001a0 d8 81 d3 64 31 aa 9e 97 31 bd 96 b0 68 c0 9b 23 |...d1...1...h..#|
+000001b0 de 76 64 3f 1a 5c 7f e9 12 0e 58 58 b6 5f 70 dd |.vd?.\....XX._p.|
+000001c0 9b d8 ea d5 d7 f5 d5 cc b9 b6 9f 30 66 5b 66 9a |...........0f[f.|
+000001d0 20 e2 27 e5 bf fe 3b 30 09 06 07 2a 86 48 ce 3d | .'...;0...*.H.=|
+000001e0 04 01 03 81 8c 00 30 81 88 02 42 01 88 a2 4f eb |......0...B...O.|
+000001f0 e2 45 c5 48 7d 1b ac f5 ed 98 9d ae 47 70 c0 5e |.E.H}.......Gp.^|
+00000200 1b b6 2f bd f1 b6 4d b7 61 40 d3 11 a2 ce ee 0b |../...M.a@......|
+00000210 7e 92 7e ff 76 9d c3 3b 7e a5 3f ce fa 10 e2 59 |~.~.v..;~.?....Y|
+00000220 ec 47 2d 7c ac da 4e 97 0e 15 a0 6f d0 02 42 01 |.G-|..N....o..B.|
+00000230 4d fc be 67 13 9c 2d 05 0e bd 3f a3 8c 25 c1 33 |M..g..-...?..%.3|
+00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....|
+00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.|
+00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....|
+00000270 2a 16 03 03 00 d8 0c 00 00 d4 03 00 17 41 04 16 |*............A..|
+00000280 80 a7 71 18 d7 2e 0e 9b a0 ae 58 8b ff 56 c5 21 |..q.......X..V.!|
+00000290 44 b1 ff 7e 2a 1a c4 39 91 d8 f5 cb 67 6c eb 24 |D..~*..9....gl.$|
+000002a0 86 e3 2f 79 ca 07 a4 6a ad 92 3e 36 79 f0 00 25 |../y...j..>6y..%|
+000002b0 b5 b8 31 e5 3c 2e f1 5e 16 23 69 c4 14 a5 93 04 |..1.<..^.#i.....|
+000002c0 03 00 8b 30 81 88 02 42 01 68 cb 9b f4 22 71 10 |...0...B.h..."q.|
+000002d0 c5 5f 02 7c ab b4 db 6e af 35 89 3b ad 4d 6b 40 |._.|...n.5.;.Mk@|
+000002e0 62 64 8b e5 6c e1 9a bd 21 05 25 cb e9 b4 7a 31 |bd..l...!.%...z1|
+000002f0 2e 63 4f 77 4c 3f ab 7b 67 21 02 ae 8b 0a 7b 7e |.cOwL?.{g!....{~|
+00000300 f9 0f a8 df b1 14 0e ef 5e 66 02 42 01 c7 50 11 |........^f.B..P.|
+00000310 28 e9 aa 1d ea 52 60 af 37 35 73 13 bd f9 dd 54 |(....R`.75s....T|
+00000320 8e 34 db 9a 78 20 61 d4 6c 7f 72 06 4e 7a 58 07 |.4..x a.l.r.NzX.|
+00000330 d9 87 01 82 b8 dc 39 72 48 41 a4 ef 58 8e dd c6 |......9rHA..X...|
+00000340 8c 0d d3 c1 c6 36 79 e1 d0 78 dd 1c 89 9a 16 03 |.....6y..x......|
+00000350 03 00 04 0e 00 00 00 |.......|
+>>> Flow 3 (client to server)
+00000000 16 03 03 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..|
+00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.|
+00000020 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.|
+00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
+00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 03 00 01 |..h.A.Vk.Z......|
+00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 5f f3 |.....(........_.|
+00000060 89 d5 29 18 bb 58 6f 28 f6 15 46 a2 1b 0a 49 9a |..)..Xo(..F...I.|
+00000070 66 ab 83 31 36 f7 f6 74 35 45 2e db 80 b9 |f..16..t5E....|
+>>> Flow 4 (server to client)
+00000000 14 03 03 00 01 01 16 03 03 00 28 ef 24 92 74 6b |..........(.$.tk|
+00000010 d1 a7 26 2a 52 6e 15 70 10 65 e4 a9 89 8d 56 04 |..&*Rn.p.e....V.|
+00000020 29 d1 36 f5 aa 64 9b 34 b9 53 df fa de 47 c4 1b |).6..d.4.S...G..|
+00000030 36 59 88 |6Y.|
+>>> Flow 5 (client to server)
+00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 36 2e 40 |.............6.@|
+00000010 ed b9 f0 05 2e 08 64 28 3a da 3f 4b 80 26 6b e3 |......d(:.?K.&k.|
+00000020 97 0e 43 15 03 03 00 1a 00 00 00 00 00 00 00 02 |..C.............|
+00000030 bd 85 57 7c 08 f1 76 bf 57 16 fe 5f f7 b4 de 43 |..W|..v.W.._...C|
+00000040 64 36 |d6|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......|
+00000000 16 03 01 00 79 01 00 00 75 03 03 00 00 00 00 00 |....y...u.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../|
-00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............|
-00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............|
-00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................|
-00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................|
-00000070 03 02 01 02 03 ff 01 00 01 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
+00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 2e |...../.5........|
+00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
+00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0a 00 |................|
+00000070 08 04 01 04 03 02 01 02 03 ff 01 00 01 00 |..............|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 53 04 f1 02 41 |....Y...U..S...A|
-00000010 95 cc 56 30 65 46 24 75 d5 9e 3c a7 5b 6c 99 fe |..V0eF$u..<.[l..|
-00000020 86 35 23 42 3a 8f 4d 4c b9 98 7d 20 a7 46 43 72 |.5#B:.ML..} .FCr|
-00000030 66 bb b6 ad ff ad cf 63 37 fe 6b b4 78 94 08 49 |f......c7.k.x..I|
-00000040 54 06 ed f4 85 73 38 4a c6 fe b6 98 c0 13 00 00 |T....s8J........|
+00000000 16 03 03 00 59 02 00 00 55 03 03 81 ab f4 92 ec |....Y...U.......|
+00000010 b8 99 85 43 62 31 8e 58 63 c0 04 03 82 b4 f5 49 |...Cb1.Xc......I|
+00000020 d5 2d cd 24 de a0 24 29 39 93 90 20 ad 9c 35 ad |.-.$..$)9.. ..5.|
+00000030 20 1d 35 0a 6e 29 99 48 72 e6 fc 19 ae e6 7f 4f | .5.n).Hr......O|
+00000040 47 01 24 f4 9d 9e d7 0e 06 25 a8 93 c0 13 00 00 |G.$......%......|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
00000060 03 02 be 0b 00 02 ba 00 02 b7 00 02 b4 30 82 02 |.............0..|
00000070 b0 30 82 02 19 a0 03 02 01 02 02 09 00 85 b0 bb |.0..............|
000002f0 5f 33 c4 b6 d8 c9 75 90 96 8c 0f 52 98 b5 cd 98 |_3....u....R....|
00000300 1f 89 20 5f f2 a0 1c a3 1b 96 94 dd a9 fd 57 e9 |.. _..........W.|
00000310 70 e8 26 6d 71 99 9b 26 6e 38 50 29 6c 90 a7 bd |p.&mq..&n8P)l...|
-00000320 d9 16 03 03 00 cd 0c 00 00 c9 03 00 17 41 04 48 |.............A.H|
-00000330 68 d8 8a 10 b4 bf eb 8d d1 98 b0 a6 f4 47 5d 91 |h............G].|
-00000340 61 da 50 d9 85 7b 5d 90 02 2c 38 c9 af 81 d3 55 |a.P..{]..,8....U|
-00000350 07 62 b1 62 58 7f 39 94 d7 91 96 a8 1f 47 60 a5 |.b.bX.9......G`.|
-00000360 c0 04 f2 fb cb 15 75 a6 16 3f 94 53 7c ff dd 04 |......u..?.S|...|
-00000370 01 00 80 b9 82 fa 0b f8 8c 94 2c 6e 05 81 7d 80 |..........,n..}.|
-00000380 5d 9a 77 78 af c8 33 5d 89 7e 2e 3c e5 72 66 a8 |].wx..3].~.<.rf.|
-00000390 f1 5c 02 04 02 70 76 7b 45 ff 0d 29 a0 cb 0d db |.\...pv{E..)....|
-000003a0 7a 4c c4 13 19 cd 47 b2 f1 c9 43 4f 95 d2 f1 c6 |zL....G...CO....|
-000003b0 bc ae 31 4a 9d de 80 b2 a4 b7 b6 dd 8c 03 3e 2a |..1J..........>*|
-000003c0 46 5e d1 e7 5b c5 9e 06 58 f3 55 b2 77 09 f3 98 |F^..[...X.U.w...|
-000003d0 d5 7f 5a 74 64 7e 48 22 8f 7d a8 68 b6 1d 90 df |..Ztd~H".}.h....|
-000003e0 2c 91 d7 c5 07 3d d1 6f e9 c1 91 03 3c 23 5a 56 |,....=.o....<#ZV|
-000003f0 3b b2 c2 16 03 03 00 04 0e 00 00 00 |;...........|
+00000320 d9 16 03 03 00 cd 0c 00 00 c9 03 00 17 41 04 a3 |.............A..|
+00000330 b7 75 d0 ba b1 e1 4e aa 08 36 e2 90 52 3c e8 8c |.u....N..6..R<..|
+00000340 78 54 61 e6 ec 60 ad 95 9b 1e a0 de a4 14 95 31 |xTa..`.........1|
+00000350 fb fc 23 5b e7 22 da 68 a1 c4 68 da 7e 62 08 6e |..#[.".h..h.~b.n|
+00000360 40 0a 3d ac 28 f2 70 17 44 24 43 b6 12 f0 0e 04 |@.=.(.p.D$C.....|
+00000370 01 00 80 3c 1e 25 16 dc f0 d0 ac 3e 63 d3 c6 ee |...<.%.....>c...|
+00000380 ed 1b 1c 8b 9d ec 41 d9 10 56 f6 19 35 61 49 fc |......A..V..5aI.|
+00000390 e6 03 f5 29 89 a1 61 46 78 0b 9b 4e f9 26 18 58 |...)..aFx..N.&.X|
+000003a0 50 64 c2 a6 fb 61 d0 29 e2 f9 b1 56 07 91 69 8d |Pd...a.)...V..i.|
+000003b0 ec 69 0e ab 91 70 a9 82 52 4f b1 d8 31 28 e2 49 |.i...p..RO..1(.I|
+000003c0 fa fa 26 c7 f9 cf 30 6e 01 59 3f de 0d 56 c8 9e |..&...0n.Y?..V..|
+000003d0 ae fd 49 2a 66 a0 bb 0b b4 f8 02 7f c8 b2 53 14 |..I*f.........S.|
+000003e0 f1 7f a9 3a 02 cd 33 04 cf 73 8b 5a 61 f3 d3 5e |...:..3..s.Za..^|
+000003f0 24 78 43 16 03 03 00 04 0e 00 00 00 |$xC.........|
>>> Flow 3 (client to server)
00000000 16 03 03 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..|
00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.|
00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 03 00 01 |..h.A.Vk.Z......|
00000050 01 16 03 03 00 40 00 00 00 00 00 00 00 00 00 00 |.....@..........|
-00000060 00 00 00 00 00 00 59 e6 92 05 27 ec 09 2c b0 a5 |......Y...'..,..|
-00000070 2a fb 7e f1 03 53 16 63 68 a1 86 13 bb da 98 27 |*.~..S.ch......'|
-00000080 6d 42 08 35 6a ec 58 61 2a 4d 44 ec ae c5 b9 d2 |mB.5j.Xa*MD.....|
-00000090 76 57 1f 75 9f 8d |vW.u..|
+00000060 00 00 00 00 00 00 58 40 67 61 f4 eb d6 54 b5 f4 |......X@ga...T..|
+00000070 08 d8 27 18 ff 7f c5 58 d1 1e 43 d3 92 74 fe a8 |..'....X..C..t..|
+00000080 a6 f8 09 4e 44 0e 0e 6a 3b 72 7e 12 1f b2 bd 9c |...ND..j;r~.....|
+00000090 f8 f3 c0 f0 4e 5e |....N^|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 40 6e 03 d0 e6 98 |..........@n....|
-00000010 1f f5 39 7b 06 9f 95 f0 7a 88 35 7c 55 db c3 2f |..9{....z.5|U../|
-00000020 00 ef 5b d3 62 87 a2 94 da 2f f6 4a 89 c9 a8 3d |..[.b..../.J...=|
-00000030 3a 92 db 77 35 92 01 4b f5 c5 6b 95 09 9f cd 79 |:..w5..K..k....y|
-00000040 3c af 37 5b 27 bf 93 3e 04 55 71 |<.7['..>.Uq|
+00000000 14 03 03 00 01 01 16 03 03 00 40 ac 13 13 7a 41 |..........@...zA|
+00000010 ef 34 2e 9c 03 52 01 84 6b c3 f4 67 48 f5 32 fb |.4...R..k..gH.2.|
+00000020 07 b2 6a cf a8 57 c5 7a 16 03 02 b5 9f 90 4c 28 |..j..W.z......L(|
+00000030 65 48 0d e6 43 48 f2 06 22 88 db 90 d9 6e da 07 |eH..CH.."....n..|
+00000040 59 1f 1c 6e af 74 ab 83 68 12 15 |Y..n.t..h..|
>>> Flow 5 (client to server)
00000000 17 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
-00000010 00 00 00 00 00 bc c9 d0 8e 80 14 de 32 18 49 e8 |............2.I.|
-00000020 20 dc 5e 6c e4 6d 14 00 df 51 71 fb 86 95 16 4c | .^l.m...Qq....L|
-00000030 04 8e 71 e1 48 15 03 03 00 30 00 00 00 00 00 00 |..q.H....0......|
-00000040 00 00 00 00 00 00 00 00 00 00 b7 6d 30 72 61 53 |...........m0raS|
-00000050 d8 0a d4 1d ae e5 d4 22 46 c9 d5 4e 4a 86 f5 ac |......."F..NJ...|
-00000060 72 98 c6 db 38 29 97 2c 84 0b |r...8).,..|
+00000010 00 00 00 00 00 87 cf e1 7e 13 ec 82 ca 75 e0 4d |........~....u.M|
+00000020 ca 17 a3 de c0 2a 54 b3 3e 4d cf 73 46 c8 a3 cf |.....*T.>M.sF...|
+00000030 ad 54 1c 74 46 15 03 03 00 30 00 00 00 00 00 00 |.T.tF....0......|
+00000040 00 00 00 00 00 00 00 00 00 00 d3 9d a4 fd 16 8d |................|
+00000050 83 1b 7c c2 53 8e 10 7b e3 3c d5 23 8e c4 9c 74 |..|.S..{.<.#...t|
+00000060 86 9e 66 59 81 41 a1 14 8e 59 |..fY.A...Y|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......|
+00000000 16 03 01 00 79 01 00 00 75 03 03 00 00 00 00 00 |....y...u.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../|
-00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............|
-00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............|
-00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................|
-00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................|
-00000070 03 02 01 02 03 ff 01 00 01 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1e c0 2f |.............../|
+00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
+00000040 c0 0a 00 05 00 2f 00 35 c0 12 00 0a 01 00 00 2e |...../.5........|
+00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................|
+00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0a 00 |................|
+00000070 08 04 01 04 03 02 01 02 03 ff 01 00 01 00 |..............|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 51 02 00 00 4d 03 03 53 04 f1 02 9d |....Q...M..S....|
-00000010 2e 4e d9 17 4a 35 fa 9d 94 f6 45 0a f6 6b 5d 1c |.N..J5....E..k].|
-00000020 1e 15 19 8d 6d 94 cc 90 d9 39 94 20 8b 4b de 76 |....m....9. .K.v|
-00000030 d5 64 5d b7 19 df e7 eb 7e a0 22 c4 09 38 a0 12 |.d].....~."..8..|
-00000040 d5 59 10 c8 31 06 dc fc e4 9d d1 80 00 05 00 00 |.Y..1...........|
+00000000 16 03 03 00 51 02 00 00 4d 03 03 39 d1 22 07 3f |....Q...M..9.".?|
+00000010 57 87 49 e1 92 8f c8 45 b6 8d 49 f2 dd 91 e0 6f |W.I....E..I....o|
+00000020 86 cd 38 c4 f5 8f d1 f2 ff 13 19 20 5f 98 f8 87 |..8........ _...|
+00000030 8e 6b 63 53 67 65 88 fc e4 02 47 4d 0b 52 bc 0c |.kcSge....GM.R..|
+00000040 8a 08 23 45 74 89 ce 77 ac 15 1c 16 00 05 00 00 |..#Et..w........|
00000050 05 ff 01 00 01 00 16 03 03 02 be 0b 00 02 ba 00 |................|
00000060 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......|
00000070 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..|
00000060 e6 bd 77 82 6f 23 b6 e0 bd a2 92 b7 3a ac e8 56 |..w.o#......:..V|
00000070 f1 af 54 5e 46 87 e9 3b 33 e7 b8 28 b7 d6 c8 90 |..T^F..;3..(....|
00000080 35 d4 1c 43 d1 30 6f 55 4e 0a 70 14 03 03 00 01 |5..C.0oUN.p.....|
-00000090 01 16 03 03 00 24 37 14 b2 97 7b b5 f0 9a 38 05 |.....$7...{...8.|
-000000a0 22 35 69 9c 95 2f 86 4b 37 98 22 db 4e 9a 46 9c |"5i../.K7.".N.F.|
-000000b0 b9 81 74 72 58 18 53 0c 5c 3c |..trX.S.\<|
+00000090 01 16 03 03 00 24 d3 d5 a4 0c ae 33 1e d4 d8 ba |.....$.....3....|
+000000a0 67 e5 93 31 e2 e9 08 c8 9e 27 d8 9b 20 d5 59 4d |g..1.....'.. .YM|
+000000b0 d0 f9 d9 bd 82 f7 62 7c 95 0b |......b|..|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 24 3c b3 e7 77 5a |..........$<..wZ|
-00000010 7c 36 5a 74 74 26 8d 5b 5a 09 96 60 e8 24 45 2f ||6Ztt&.[Z..`.$E/|
-00000020 c2 39 14 5e db 58 12 49 ad a8 b6 ea ef 58 16 |.9.^.X.I.....X.|
+00000000 14 03 03 00 01 01 16 03 03 00 24 b2 af 7d da e2 |..........$..}..|
+00000010 b4 4f 9e ee 68 d4 bf eb d3 09 63 de 61 e1 c2 12 |.O..h.....c.a...|
+00000020 ba 56 d8 dc 5f 9e 31 fe 1c d4 70 2a 1a 80 3c |.V.._.1...p*..<|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1a 6d 29 d7 ba 2f 85 02 b6 f0 82 64 |.....m)../.....d|
-00000010 6c 55 ae ab f6 fd 14 ff b8 38 f0 f8 a6 ea cc 15 |lU.......8......|
-00000020 03 03 00 16 10 c5 d9 41 7b e2 89 67 dc 29 8e f8 |.......A{..g.)..|
-00000030 b5 ab 32 91 44 2c 27 84 49 f7 |..2.D,'.I.|
+00000000 17 03 03 00 1a 43 f5 b5 0e 1b 1f 20 2a 09 27 e5 |.....C..... *.'.|
+00000010 dc 11 cf e6 07 31 2b fc 60 52 86 2b 41 b0 c2 15 |.....1+.`R.+A...|
+00000020 03 03 00 16 6a b9 06 9b c6 e9 6d ad ed 2d cc 0f |....j.....m..-..|
+00000030 bc 0a f1 0c 2d 0d 74 29 17 6b |....-.t).k|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 76 01 00 00 72 03 01 53 04 f0 f9 4b |....v...r..S...K|
-00000010 30 a8 68 d0 79 13 14 69 ee 3b 5d 05 cb 71 63 43 |0.h.y..i.;]..qcC|
-00000020 4a 55 6b 05 25 53 19 ba e0 2f b1 00 00 04 c0 0a |JUk.%S.../......|
-00000030 00 ff 01 00 00 45 00 0b 00 04 03 00 01 02 00 0a |.....E..........|
-00000040 00 34 00 32 00 0e 00 0d 00 19 00 0b 00 0c 00 18 |.4.2............|
-00000050 00 09 00 0a 00 16 00 17 00 08 00 06 00 07 00 14 |................|
-00000060 00 15 00 04 00 05 00 12 00 13 00 01 00 02 00 03 |................|
-00000070 00 0f 00 10 00 11 00 0f 00 01 01 |...........|
+00000000 16 03 01 00 7d 01 00 00 79 03 01 65 14 3f 40 e4 |....}...y..e.?@.|
+00000010 2f 74 65 7e d0 c8 87 03 59 61 9d c3 84 5e c9 62 |/te~....Ya...^.b|
+00000020 e6 46 b8 0c 4a 5e 3f 33 43 a5 dd 00 00 04 c0 0a |.F..J^?3C.......|
+00000030 00 ff 02 01 00 00 4b 00 0b 00 04 03 00 01 02 00 |......K.........|
+00000040 0a 00 3a 00 38 00 0e 00 0d 00 19 00 1c 00 0b 00 |..:.8...........|
+00000050 0c 00 1b 00 18 00 09 00 0a 00 1a 00 16 00 17 00 |................|
+00000060 08 00 06 00 07 00 14 00 15 00 04 00 05 00 12 00 |................|
+00000070 13 00 01 00 02 00 03 00 0f 00 10 00 11 00 0f 00 |................|
+00000080 01 01 |..|
>>> Flow 2 (server to client)
00000000 16 03 01 00 31 02 00 00 2d 03 01 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000260 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 24 20 3e |uq..T[....g..$ >|
00000270 b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 07 9f 6c |.V...(^.+-O....l|
00000280 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 b5 68 1a |K[.V.2B.X..I..h.|
-00000290 41 03 56 6b dc 5a 89 00 8b 30 81 88 02 42 00 c6 |A.Vk.Z...0...B..|
-000002a0 85 8e 06 b7 04 04 e9 cd 9e 3e cb 66 23 95 b4 42 |.........>.f#..B|
-000002b0 9c 64 81 39 05 3f b5 21 f8 28 af 60 6b 4d 3d ba |.d.9.?.!.(.`kM=.|
-000002c0 a1 4b 5e 77 ef e7 59 28 fe 1d c1 27 a2 ff a8 de |.K^w..Y(...'....|
-000002d0 33 48 b3 c1 85 6a 42 9b f9 7e 7e 31 c2 e5 bd 66 |3H...jB..~~1...f|
-000002e0 02 42 00 ad 7d 06 35 ab ec 8d ac d4 ba 1b 49 5e |.B..}.5.......I^|
-000002f0 05 5f f0 97 93 82 b8 2b 8d 91 98 63 8e b4 14 62 |._.....+...c...b|
-00000300 db 1e c9 2b 30 f8 41 9b a6 e6 bc de 0e 68 30 21 |...+0.A......h0!|
-00000310 d8 ef 2f 05 42 da f2 e0 2c 06 33 1d 0d 9a 1a 75 |../.B...,.3....u|
-00000320 59 a7 3a bc 16 03 01 00 04 0e 00 00 00 |Y.:..........|
+00000290 41 03 56 6b dc 5a 89 00 8b 30 81 88 02 42 01 3e |A.Vk.Z...0...B.>|
+000002a0 79 81 6e 89 cd 3e 3f ec e4 b5 75 17 28 ee fb 09 |y.n..>?...u.(...|
+000002b0 21 19 6f 3c e6 ca 1e f2 18 b6 47 f8 37 05 1c 85 |!.o<......G.7...|
+000002c0 0f a4 b8 6b 40 04 50 77 e3 05 9b 24 b8 93 e8 4d |...k@.Pw...$...M|
+000002d0 ef 30 cd 51 90 58 a2 49 71 b3 3f b9 46 ab a9 72 |.0.Q.X.Iq.?.F..r|
+000002e0 02 42 01 58 ef 20 c1 0a 33 f8 fd 50 9e 65 f5 ef |.B.X. ..3..P.e..|
+000002f0 f4 91 49 2d d2 de 66 2b 97 69 7d b1 d0 ef d6 91 |..I-..f+.i}.....|
+00000300 0f fc 57 2b 73 b9 49 01 33 d2 1b 5b 9a 2c 51 35 |..W+s.I.3..[.,Q5|
+00000310 0e eb 38 53 fa 20 07 84 52 b3 43 24 09 5a 32 c0 |..8S. ..R.C$.Z2.|
+00000320 32 17 34 6c 16 03 01 00 04 0e 00 00 00 |2.4l.........|
>>> Flow 3 (client to server)
-00000000 16 03 01 00 46 10 00 00 42 41 04 08 28 cf bd 3c |....F...BA..(..<|
-00000010 3c cc 98 9e 73 3f 92 a7 cb 22 83 3b c7 61 46 0e |<...s?...".;.aF.|
-00000020 4d 7c 30 b5 06 85 2f 01 be b5 40 e2 64 1e 45 c1 |M|0.../...@.d.E.|
-00000030 9d 73 95 d5 65 92 0b 9b e7 6f c6 91 ab b6 fa be |.s..e....o......|
-00000040 61 83 a7 f2 eb f5 65 31 fe 24 7b 14 03 01 00 01 |a.....e1.${.....|
-00000050 01 16 03 01 00 30 15 d1 c4 ca 0b 01 84 13 5a ba |.....0........Z.|
-00000060 89 04 87 73 7c bb d8 89 7e 10 27 ba 6f 5d dc d3 |...s|...~.'.o]..|
-00000070 b5 ef 32 86 58 cc fb eb 5c 32 9e 95 ef 01 1c ac |..2.X...\2......|
-00000080 dc 8e df 7f fe 0a |......|
+00000000 16 03 01 00 46 10 00 00 42 41 04 31 74 f8 f6 18 |....F...BA.1t...|
+00000010 55 6a 9b 3b 78 0a 0e f0 c9 91 aa 8e 77 39 0a 88 |Uj.;x.......w9..|
+00000020 a4 d4 f6 04 9d de 89 18 b6 50 12 72 26 9c 8f e1 |.........P.r&...|
+00000030 f0 b2 e6 df ce 3b 46 be e9 2a 9a e3 7f d1 d5 92 |.....;F..*......|
+00000040 ff e3 ae 0a 2d a1 3b 07 f6 04 59 14 03 01 00 01 |....-.;...Y.....|
+00000050 01 16 03 01 00 30 02 4f df 41 30 97 6f f7 18 ca |.....0.O.A0.o...|
+00000060 05 35 17 a1 a2 a5 71 61 b1 d8 dd 9a c6 f3 54 53 |.5....qa......TS|
+00000070 84 f6 fb 93 1e 0e 9d e7 fe 35 85 9e 73 d0 2e a1 |.........5..s...|
+00000080 a7 63 d9 40 c6 ac |.c.@..|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 30 e8 48 86 81 3c |..........0.H..<|
-00000010 f5 25 5c 94 a9 06 c4 5c 71 62 b1 43 76 ec 2c 44 |.%\....\qb.Cv.,D|
-00000020 95 b5 8c 95 d2 ff 82 92 b6 fc 52 75 03 c6 a1 f0 |..........Ru....|
-00000030 99 6d b1 ed ec 68 6c d7 9f 18 50 17 03 01 00 20 |.m...hl...P.... |
-00000040 32 d9 26 8a 81 b8 9d a5 7b fd d5 4e 7a db 2e 29 |2.&.....{..Nz..)|
-00000050 58 9a 4f 6a 27 18 bc dc c2 49 b8 65 cb 8e 16 5a |X.Oj'....I.e...Z|
-00000060 17 03 01 00 30 c4 56 0a ad 9a 82 cb 3e 32 f1 7c |....0.V.....>2.||
-00000070 95 6e dd cd e9 4d f0 e5 2d c9 a3 f7 de bb d7 fd |.n...M..-.......|
-00000080 84 bb df 34 8c 64 1f 03 58 64 19 4a 5b 7a a8 81 |...4.d..Xd.J[z..|
-00000090 52 bb 51 0a 43 15 03 01 00 20 89 18 7a 40 ec 49 |R.Q.C.... ..z@.I|
-000000a0 52 d5 d3 20 ac 07 eb e9 4a 78 23 cf e7 21 32 74 |R.. ....Jx#..!2t|
-000000b0 ec 40 8d a8 f4 33 1c ae 93 cf |.@...3....|
+00000000 14 03 01 00 01 01 16 03 01 00 30 07 7e 4e 9c 19 |..........0.~N..|
+00000010 f0 35 cd 02 b7 a6 0a 1a b1 a8 11 a3 f9 b1 35 7b |.5............5{|
+00000020 96 7f e6 e1 00 c6 6d 9e e6 8a bb a2 b8 bd a3 9d |......m.........|
+00000030 05 22 1b f1 f5 28 4a 00 6e f1 71 17 03 01 00 20 |."...(J.n.q.... |
+00000040 ad c7 4c dc f4 81 1a 39 3d 86 5e 8e f5 0d a3 33 |..L....9=.^....3|
+00000050 88 32 e7 be 8b 6a 8d 44 29 7b 47 fd e5 33 01 1e |.2...j.D){G..3..|
+00000060 17 03 01 00 30 61 47 ee ae 89 25 ac 85 3b 8a 84 |....0aG...%..;..|
+00000070 47 61 ea 3e 4c 70 57 07 d6 f1 1c 21 cb 44 7e de |Ga.>LpW....!.D~.|
+00000080 b5 01 9e fb fe ad bc be 74 c0 65 a0 6b c1 0c 8c |........t.e.k...|
+00000090 2b 00 24 c6 b7 15 03 01 00 20 b7 8b 6b e5 77 ab |+.$...... ..k.w.|
+000000a0 f6 50 9e 88 4d 56 a8 25 8d 02 db cb 68 8b 3f 62 |.P..MV.%....h.?b|
+000000b0 be aa 02 24 75 b1 e5 4b 18 c9 |...$u..K..|
>>> Flow 1 (client to server)
-00000000 16 03 01 01 8a 01 00 01 86 03 03 34 54 69 f3 d7 |...........4Ti..|
-00000010 20 9d 1d 74 db 72 e9 2f 51 7c c2 82 0a 9b cb 6d | ..t.r./Q|.....m|
-00000020 90 b4 8e a2 1f 2f c7 66 74 8f 33 00 00 d6 c0 30 |...../.ft.3....0|
-00000030 c0 2c c0 28 c0 24 c0 14 c0 0a c0 22 c0 21 c0 20 |.,.(.$.....".!. |
-00000040 00 a5 00 a3 00 a1 00 9f 00 6b 00 6a 00 69 00 68 |.........k.j.i.h|
-00000050 00 39 00 38 00 37 00 36 00 88 00 87 00 86 00 85 |.9.8.7.6........|
-00000060 c0 32 c0 2e c0 2a c0 26 c0 0f c0 05 00 9d 00 3d |.2...*.&.......=|
-00000070 00 35 00 84 c0 2f c0 2b c0 27 c0 23 c0 13 c0 09 |.5.../.+.'.#....|
-00000080 c0 1f c0 1e c0 1d 00 a4 00 a2 00 a0 00 9e 00 67 |...............g|
-00000090 00 40 00 3f 00 3e 00 33 00 32 00 31 00 30 00 9a |.@.?.>.3.2.1.0..|
-000000a0 00 99 00 98 00 97 00 45 00 44 00 43 00 42 c0 31 |.......E.D.C.B.1|
-000000b0 c0 2d c0 29 c0 25 c0 0e c0 04 00 9c 00 3c 00 2f |.-.).%.......<./|
-000000c0 00 96 00 41 00 07 c0 11 c0 07 c0 0c c0 02 00 05 |...A............|
-000000d0 00 04 c0 12 c0 08 c0 1c c0 1b c0 1a 00 16 00 13 |................|
-000000e0 00 10 00 0d c0 0d c0 03 00 0a 00 15 00 12 00 0f |................|
-000000f0 00 0c 00 09 00 14 00 11 00 0e 00 0b 00 08 00 06 |................|
-00000100 00 03 00 ff 01 00 00 87 00 0b 00 04 03 00 01 02 |................|
-00000110 00 0a 00 3a 00 38 00 0e 00 0d 00 19 00 1c 00 0b |...:.8..........|
-00000120 00 0c 00 1b 00 18 00 09 00 0a 00 1a 00 16 00 17 |................|
-00000130 00 08 00 06 00 07 00 14 00 15 00 04 00 05 00 12 |................|
-00000140 00 13 00 01 00 02 00 03 00 0f 00 10 00 11 00 23 |...............#|
-00000150 00 00 00 0d 00 20 00 1e 06 01 06 02 06 03 05 01 |..... ..........|
-00000160 05 02 05 03 04 01 04 02 04 03 03 01 03 02 03 03 |................|
-00000170 02 01 02 02 02 03 00 0f 00 01 01 00 10 00 10 00 |................|
-00000180 0e 06 70 72 6f 74 6f 32 06 70 72 6f 74 6f 31 |..proto2.proto1|
+00000000 16 03 01 01 78 01 00 01 74 03 03 73 99 93 cd 3d |....x...t..s...=|
+00000010 e8 60 23 0d 6a e8 f5 e3 46 ca 38 44 85 ca 79 c8 |.`#.j...F.8D..y.|
+00000020 96 be 94 bd 43 d5 14 2b 20 da 5c 00 00 c4 c0 30 |....C..+ .\....0|
+00000030 c0 2c c0 28 c0 24 c0 14 c0 0a 00 a5 00 a3 00 a1 |.,.(.$..........|
+00000040 00 9f 00 6b 00 6a 00 69 00 68 00 39 00 38 00 37 |...k.j.i.h.9.8.7|
+00000050 00 36 00 88 00 87 00 86 00 85 c0 32 c0 2e c0 2a |.6.........2...*|
+00000060 c0 26 c0 0f c0 05 00 9d 00 3d 00 35 00 84 c0 2f |.&.......=.5.../|
+00000070 c0 2b c0 27 c0 23 c0 13 c0 09 00 a4 00 a2 00 a0 |.+.'.#..........|
+00000080 00 9e 00 67 00 40 00 3f 00 3e 00 33 00 32 00 31 |...g.@.?.>.3.2.1|
+00000090 00 30 00 9a 00 99 00 98 00 97 00 45 00 44 00 43 |.0.........E.D.C|
+000000a0 00 42 c0 31 c0 2d c0 29 c0 25 c0 0e c0 04 00 9c |.B.1.-.).%......|
+000000b0 00 3c 00 2f 00 96 00 41 00 07 c0 11 c0 07 c0 0c |.<./...A........|
+000000c0 c0 02 00 05 00 04 c0 12 c0 08 00 16 00 13 00 10 |................|
+000000d0 00 0d c0 0d c0 03 00 0a 00 15 00 12 00 0f 00 0c |................|
+000000e0 00 09 00 14 00 11 00 0e 00 0b 00 08 00 06 00 03 |................|
+000000f0 00 ff 01 00 00 87 00 0b 00 04 03 00 01 02 00 0a |................|
+00000100 00 3a 00 38 00 0e 00 0d 00 19 00 1c 00 0b 00 0c |.:.8............|
+00000110 00 1b 00 18 00 09 00 0a 00 1a 00 16 00 17 00 08 |................|
+00000120 00 06 00 07 00 14 00 15 00 04 00 05 00 12 00 13 |................|
+00000130 00 01 00 02 00 03 00 0f 00 10 00 11 00 23 00 00 |.............#..|
+00000140 00 0d 00 20 00 1e 06 01 06 02 06 03 05 01 05 02 |... ............|
+00000150 05 03 04 01 04 02 04 03 03 01 03 02 03 03 02 01 |................|
+00000160 02 02 02 03 00 0f 00 01 01 00 10 00 10 00 0e 06 |................|
+00000170 70 72 6f 74 6f 32 06 70 72 6f 74 6f 31 |proto2.proto1|
>>> Flow 2 (server to client)
00000000 16 03 03 00 42 02 00 00 3e 03 03 00 00 00 00 00 |....B...>.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 c0 14 00 00 |................|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 c0 30 00 00 |.............0..|
00000030 16 00 23 00 00 ff 01 00 01 00 00 10 00 09 00 07 |..#.............|
00000040 06 70 72 6f 74 6f 31 16 03 03 02 be 0b 00 02 ba |.proto1.........|
00000050 00 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 |......0...0.....|
00000320 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 24 20 |5uq..T[....g..$ |
00000330 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 07 9f |>.V...(^.+-O....|
00000340 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 b5 68 |lK[.V.2B.X..I..h|
-00000350 1a 41 03 56 6b dc 5a 89 04 01 00 80 2d a0 6e 47 |.A.Vk.Z.....-.nG|
-00000360 93 a2 19 17 32 f5 42 58 93 f6 4f d4 e9 4d a4 0f |....2.BX..O..M..|
-00000370 fe 4e d7 2c 62 b6 fb 83 37 a3 09 60 4b 69 e2 4c |.N.,b...7..`Ki.L|
-00000380 fc b8 4c d1 a6 9a 89 a0 c5 76 f5 62 b7 e8 eb c2 |..L......v.b....|
-00000390 fa 0f 0e 61 86 bc 70 da 13 72 8d 87 94 16 9a 8d |...a..p..r......|
-000003a0 5f 80 82 92 77 37 4f 9e 55 5d dc 35 42 a3 75 5c |_...w7O.U].5B.u\|
-000003b0 ec a4 58 78 66 97 97 da 49 67 2e b6 7e 11 de fb |..Xxf...Ig..~...|
-000003c0 e3 8f e8 bf 1d 91 1e 91 20 1b 2a df c6 58 e4 82 |........ .*..X..|
-000003d0 ce 37 dd 6f a5 ac 51 3d 65 db 3f f5 16 03 03 00 |.7.o..Q=e.?.....|
+00000350 1a 41 03 56 6b dc 5a 89 04 01 00 80 52 f3 4c 3f |.A.Vk.Z.....R.L?|
+00000360 c4 82 3c 4f 8f dc f5 33 c5 12 41 80 dc ea f2 84 |..<O...3..A.....|
+00000370 cf e4 50 f6 27 90 bb d0 09 ef 9c 9a 34 58 5c 38 |..P.'.......4X\8|
+00000380 53 27 72 e5 07 86 bb 4d 6c 17 6f 79 60 bd ca cb |S'r....Ml.oy`...|
+00000390 be 05 f1 0c 46 4b 1f 19 74 67 cd d9 64 2a fa 5f |....FK..tg..d*._|
+000003a0 b8 47 fb 98 47 a9 1f d5 20 95 19 48 70 1a 1c 57 |.G..G... ..Hp..W|
+000003b0 81 46 2a 8c 56 35 69 48 c9 23 a0 4e 7f f0 c0 fc |.F*.V5iH.#.N....|
+000003c0 eb 28 8a d3 99 45 39 cc 2b 2a 93 1f c3 0b 68 60 |.(...E9.+*....h`|
+000003d0 91 14 5e 6d be e6 40 19 38 76 d1 4c 16 03 03 00 |..^m..@.8v.L....|
000003e0 04 0e 00 00 00 |.....|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 46 10 00 00 42 41 04 f3 fc ea d8 50 |....F...BA.....P|
-00000010 e6 15 b0 e7 11 c7 6d ee 09 ad 80 d5 54 eb 4f 62 |......m.....T.Ob|
-00000020 7d bb a7 2d 28 0c 66 33 42 09 cf 2b 58 f8 58 41 |}..-(.f3B..+X.XA|
-00000030 bd 46 51 0a f0 7d 8c 0c 98 9e 26 77 20 fd 5e c1 |.FQ..}....&w .^.|
-00000040 a9 b3 e5 c3 6c 05 97 e3 81 fd db 14 03 03 00 01 |....l...........|
-00000050 01 16 03 03 00 40 02 2a 28 41 e3 9c 5d 45 d4 45 |.....@.*(A..]E.E|
-00000060 51 8c 7a c0 ba b1 8e a4 84 2c f3 83 cd c4 55 5c |Q.z......,....U\|
-00000070 d6 5c 6f 72 ab 89 7a c6 d7 9c 2a 54 f0 c4 20 ee |.\or..z...*T.. .|
-00000080 37 74 9b b6 8c f7 e4 37 2c eb d4 9f 5c 5e 55 a0 |7t.....7,...\^U.|
-00000090 e2 5a fe 1e c8 67 |.Z...g|
+00000000 16 03 03 00 46 10 00 00 42 41 04 e2 86 c1 a0 c0 |....F...BA......|
+00000010 45 9a da 1a 70 a1 3e b6 9c b7 2e ec dd 2b 0a c6 |E...p.>......+..|
+00000020 50 59 95 fe 8e 54 83 06 b6 68 42 60 56 de b2 b3 |PY...T...hB`V...|
+00000030 b9 14 f0 e0 e2 2e a3 7f ec 01 4d 10 8a 43 ab 33 |..........M..C.3|
+00000040 18 f4 b9 5d 6c ae cd 90 3e f4 64 14 03 03 00 01 |...]l...>.d.....|
+00000050 01 16 03 03 00 28 47 e5 15 81 5b f4 a0 6a 61 d6 |.....(G...[..ja.|
+00000060 df 5e 60 f1 d4 dc 55 45 84 0b ef 56 42 0b 42 1d |.^`...UE...VB.B.|
+00000070 28 b4 90 a6 2a 47 41 97 3b 91 5c 74 ab 02 |(...*GA.;.\t..|
>>> Flow 4 (server to client)
00000000 16 03 03 00 72 04 00 00 6e 00 00 00 00 00 68 00 |....r...n.....h.|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 65 |...............e|
-00000020 ea 8b c0 ef ba 59 31 75 33 96 f1 f8 c9 e1 ef 30 |.....Y1u3......0|
-00000030 00 a3 a9 1d ab c8 4b 29 94 f2 c8 c8 8d 03 57 ab |......K)......W.|
-00000040 56 df 0f 4e 0d 30 13 09 c9 e4 fa 51 4e b3 26 ad |V..N.0.....QN.&.|
-00000050 43 9f ae 62 d5 59 23 05 9b 69 8f 5b a8 ba 39 f1 |C..b.Y#..i.[..9.|
-00000060 90 84 35 bf 8f 8d d5 39 93 98 ee b9 75 03 3f 91 |..5....9....u.?.|
-00000070 e8 56 0b cb 44 a6 7a 14 03 03 00 01 01 16 03 03 |.V..D.z.........|
-00000080 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |.@..............|
-00000090 00 00 f9 a0 8e 23 34 f1 61 15 a8 4e ae c4 f3 2a |.....#4.a..N...*|
-000000a0 a6 f8 ee 1b 65 c4 c0 ff 93 14 74 ed 82 ae 48 a8 |....e.....t...H.|
-000000b0 42 fb a9 24 5d dd fd 98 b8 65 73 03 88 99 e1 ed |B..$]....es.....|
-000000c0 02 95 17 03 03 00 40 00 00 00 00 00 00 00 00 00 |......@.........|
-000000d0 00 00 00 00 00 00 00 b9 b3 f5 41 84 3b 2a a9 c3 |..........A.;*..|
-000000e0 9c e3 d4 38 90 76 c1 8c f0 4f 10 1b 04 b5 07 fe |...8.v...O......|
-000000f0 79 3d 7b 77 a4 17 0f 4e df 64 70 70 9e 34 8e b6 |y={w...N.dpp.4..|
-00000100 db b2 b6 fd 41 fe b3 15 03 03 00 30 00 00 00 00 |....A......0....|
-00000110 00 00 00 00 00 00 00 00 00 00 00 00 02 73 de fe |.............s..|
-00000120 fa 4b 69 6d 30 69 79 96 7e 4f 2f 04 67 36 96 27 |.Kim0iy.~O/.g6.'|
-00000130 67 23 2b dc 7a c4 6c 34 ea fc 79 fd |g#+.z.l4..y.|
+00000020 ea 8b e4 ef ba 19 39 3a 95 90 2b 6d 0d 59 ac 36 |......9:..+m.Y.6|
+00000030 be 71 eb b4 25 51 86 cc 80 43 ea 60 e0 53 30 ba |.q..%Q...C.`.S0.|
+00000040 3e b9 c3 29 9b 26 94 5a 43 36 d0 65 be a7 f1 06 |>..).&.ZC6.e....|
+00000050 99 e3 c5 d7 f2 59 23 11 c5 99 27 5c 7f 43 94 0e |.....Y#...'\.C..|
+00000060 b3 35 7a 66 d9 c4 49 53 2a 28 b6 3d e7 0f c5 d5 |.5zf..IS*(.=....|
+00000070 a2 d8 15 a8 3a 88 f7 14 03 03 00 01 01 16 03 03 |....:...........|
+00000080 00 28 00 00 00 00 00 00 00 00 07 2e 75 1d 9a 12 |.(..........u...|
+00000090 9f e9 7e 0b 42 dd 7b 8e ae 58 ac 49 78 8d fb 3f |..~.B.{..X.Ix..?|
+000000a0 21 e8 ef 91 3c 02 a6 23 d5 cc 17 03 03 00 25 00 |!...<..#......%.|
+000000b0 00 00 00 00 00 00 01 bb 04 db f2 86 63 96 01 60 |............c..`|
+000000c0 bb f4 68 f9 50 2a f0 15 82 f8 a1 73 bf cd 5f 4d |..h.P*.....s.._M|
+000000d0 1a 73 67 91 15 03 03 00 1a 00 00 00 00 00 00 00 |.sg.............|
+000000e0 02 02 79 34 67 e2 67 d5 52 59 91 76 90 10 c8 41 |..y4g.g.RY.v...A|
+000000f0 c5 56 c9 |.V.|
>>> Flow 1 (client to server)
-00000000 16 03 01 01 8a 01 00 01 86 03 03 0a a8 82 53 61 |..............Sa|
-00000010 68 e0 83 91 71 36 f9 c1 19 ff e8 09 fc 21 9f 03 |h...q6.......!..|
-00000020 31 f3 87 4a 04 8c 3d c2 6e 00 32 00 00 d6 c0 30 |1..J..=.n.2....0|
-00000030 c0 2c c0 28 c0 24 c0 14 c0 0a c0 22 c0 21 c0 20 |.,.(.$.....".!. |
-00000040 00 a5 00 a3 00 a1 00 9f 00 6b 00 6a 00 69 00 68 |.........k.j.i.h|
-00000050 00 39 00 38 00 37 00 36 00 88 00 87 00 86 00 85 |.9.8.7.6........|
-00000060 c0 32 c0 2e c0 2a c0 26 c0 0f c0 05 00 9d 00 3d |.2...*.&.......=|
-00000070 00 35 00 84 c0 2f c0 2b c0 27 c0 23 c0 13 c0 09 |.5.../.+.'.#....|
-00000080 c0 1f c0 1e c0 1d 00 a4 00 a2 00 a0 00 9e 00 67 |...............g|
-00000090 00 40 00 3f 00 3e 00 33 00 32 00 31 00 30 00 9a |.@.?.>.3.2.1.0..|
-000000a0 00 99 00 98 00 97 00 45 00 44 00 43 00 42 c0 31 |.......E.D.C.B.1|
-000000b0 c0 2d c0 29 c0 25 c0 0e c0 04 00 9c 00 3c 00 2f |.-.).%.......<./|
-000000c0 00 96 00 41 00 07 c0 11 c0 07 c0 0c c0 02 00 05 |...A............|
-000000d0 00 04 c0 12 c0 08 c0 1c c0 1b c0 1a 00 16 00 13 |................|
-000000e0 00 10 00 0d c0 0d c0 03 00 0a 00 15 00 12 00 0f |................|
-000000f0 00 0c 00 09 00 14 00 11 00 0e 00 0b 00 08 00 06 |................|
-00000100 00 03 00 ff 01 00 00 87 00 0b 00 04 03 00 01 02 |................|
-00000110 00 0a 00 3a 00 38 00 0e 00 0d 00 19 00 1c 00 0b |...:.8..........|
-00000120 00 0c 00 1b 00 18 00 09 00 0a 00 1a 00 16 00 17 |................|
-00000130 00 08 00 06 00 07 00 14 00 15 00 04 00 05 00 12 |................|
-00000140 00 13 00 01 00 02 00 03 00 0f 00 10 00 11 00 23 |...............#|
-00000150 00 00 00 0d 00 20 00 1e 06 01 06 02 06 03 05 01 |..... ..........|
-00000160 05 02 05 03 04 01 04 02 04 03 03 01 03 02 03 03 |................|
-00000170 02 01 02 02 02 03 00 0f 00 01 01 00 10 00 10 00 |................|
-00000180 0e 06 70 72 6f 74 6f 32 06 70 72 6f 74 6f 31 |..proto2.proto1|
+00000000 16 03 01 01 78 01 00 01 74 03 03 ba 93 c5 44 7d |....x...t.....D}|
+00000010 cf bf e3 d4 ad 9a ff 3a 48 ec 46 11 1a e5 68 87 |.......:H.F...h.|
+00000020 d1 f0 3b 7c da 86 b9 8f 5d a7 59 00 00 c4 c0 30 |..;|....].Y....0|
+00000030 c0 2c c0 28 c0 24 c0 14 c0 0a 00 a5 00 a3 00 a1 |.,.(.$..........|
+00000040 00 9f 00 6b 00 6a 00 69 00 68 00 39 00 38 00 37 |...k.j.i.h.9.8.7|
+00000050 00 36 00 88 00 87 00 86 00 85 c0 32 c0 2e c0 2a |.6.........2...*|
+00000060 c0 26 c0 0f c0 05 00 9d 00 3d 00 35 00 84 c0 2f |.&.......=.5.../|
+00000070 c0 2b c0 27 c0 23 c0 13 c0 09 00 a4 00 a2 00 a0 |.+.'.#..........|
+00000080 00 9e 00 67 00 40 00 3f 00 3e 00 33 00 32 00 31 |...g.@.?.>.3.2.1|
+00000090 00 30 00 9a 00 99 00 98 00 97 00 45 00 44 00 43 |.0.........E.D.C|
+000000a0 00 42 c0 31 c0 2d c0 29 c0 25 c0 0e c0 04 00 9c |.B.1.-.).%......|
+000000b0 00 3c 00 2f 00 96 00 41 00 07 c0 11 c0 07 c0 0c |.<./...A........|
+000000c0 c0 02 00 05 00 04 c0 12 c0 08 00 16 00 13 00 10 |................|
+000000d0 00 0d c0 0d c0 03 00 0a 00 15 00 12 00 0f 00 0c |................|
+000000e0 00 09 00 14 00 11 00 0e 00 0b 00 08 00 06 00 03 |................|
+000000f0 00 ff 01 00 00 87 00 0b 00 04 03 00 01 02 00 0a |................|
+00000100 00 3a 00 38 00 0e 00 0d 00 19 00 1c 00 0b 00 0c |.:.8............|
+00000110 00 1b 00 18 00 09 00 0a 00 1a 00 16 00 17 00 08 |................|
+00000120 00 06 00 07 00 14 00 15 00 04 00 05 00 12 00 13 |................|
+00000130 00 01 00 02 00 03 00 0f 00 10 00 11 00 23 00 00 |.............#..|
+00000140 00 0d 00 20 00 1e 06 01 06 02 06 03 05 01 05 02 |... ............|
+00000150 05 03 04 01 04 02 04 03 03 01 03 02 03 03 02 01 |................|
+00000160 02 02 02 03 00 0f 00 01 01 00 10 00 10 00 0e 06 |................|
+00000170 70 72 6f 74 6f 32 06 70 72 6f 74 6f 31 |proto2.proto1|
>>> Flow 2 (server to client)
00000000 16 03 03 00 35 02 00 00 31 03 03 00 00 00 00 00 |....5...1.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 c0 14 00 00 |................|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 c0 30 00 00 |.............0..|
00000030 09 00 23 00 00 ff 01 00 01 00 16 03 03 02 be 0b |..#.............|
00000040 00 02 ba 00 02 b7 00 02 b4 30 82 02 b0 30 82 02 |.........0...0..|
00000050 19 a0 03 02 01 02 02 09 00 85 b0 bb a4 8a 7f b8 |................|
00000310 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.|
00000320 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.|
00000330 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
-00000340 a6 b5 68 1a 41 03 56 6b dc 5a 89 04 01 00 80 b9 |..h.A.Vk.Z......|
-00000350 0f 79 8a 16 f4 da 8f 27 b4 16 fc c0 51 db ae d1 |.y.....'....Q...|
-00000360 af 79 77 d5 d5 a2 13 05 45 20 cc eb ac ed cb 30 |.yw.....E .....0|
-00000370 32 2e 2c bd fa 1c 4d b5 32 a6 37 43 c8 5c 2d f8 |2.,...M.2.7C.\-.|
-00000380 6e 85 f5 cd 54 92 29 ad 13 7d d5 9e 8c 1d b7 d0 |n...T.)..}......|
-00000390 c1 c7 3d e8 ba 4a 0f 9a a6 3e 25 5f 27 62 b1 00 |..=..J...>%_'b..|
-000003a0 91 d9 23 48 3f 10 fe c5 e3 07 9a 58 57 6d cc 10 |..#H?......XWm..|
-000003b0 3b f8 1a d5 6e 8b 1f 03 6f 82 84 98 b5 f7 71 5d |;...n...o.....q]|
-000003c0 c2 ad 60 14 c1 88 07 5a 3d 99 fd a8 c9 9a 03 16 |..`....Z=.......|
+00000340 a6 b5 68 1a 41 03 56 6b dc 5a 89 04 01 00 80 52 |..h.A.Vk.Z.....R|
+00000350 78 35 42 fa 35 a6 19 22 d1 03 f4 ed 65 31 ff fe |x5B.5.."....e1..|
+00000360 d6 83 d5 db a1 6b 7d 88 2f 53 7a e8 2a cf a7 e4 |.....k}./Sz.*...|
+00000370 83 0f e7 b6 60 60 91 65 ee ce b0 e9 5c bb 8c fd |....``.e....\...|
+00000380 10 5e c7 17 cb 1b bc db 19 59 23 5d 76 3a f8 87 |.^.......Y#]v:..|
+00000390 d8 2d a7 a2 d8 7b cc e5 f8 82 7c ed bf 08 c4 67 |.-...{....|....g|
+000003a0 c5 f6 a6 5a 2f 9f 59 cb 62 f6 b4 f3 3c d6 f5 dc |...Z/.Y.b...<...|
+000003b0 20 27 d9 14 36 5c a9 8d f6 7b c2 db 9f 84 fc 0d | '..6\...{......|
+000003c0 d3 3a d2 bf 4a 3b 3c 3e 13 eb f9 03 d2 cf 6f 16 |.:..J;<>......o.|
000003d0 03 03 00 04 0e 00 00 00 |........|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 46 10 00 00 42 41 04 76 aa 4e b9 f9 |....F...BA.v.N..|
-00000010 68 85 81 74 7c d9 f9 64 7f bd 09 83 08 5b 4f 76 |h..t|..d.....[Ov|
-00000020 6e be 79 b6 4e 97 17 63 e4 b5 1c 77 e5 85 76 8a |n.y.N..c...w..v.|
-00000030 5d 9f f1 21 88 ec f9 a7 7c 41 af f9 c5 fe 11 81 |]..!....|A......|
-00000040 11 51 8e a7 20 33 5f cf e7 90 90 14 03 03 00 01 |.Q.. 3_.........|
-00000050 01 16 03 03 00 40 44 3e 32 01 71 ac 5a b5 1f 2c |.....@D>2.q.Z..,|
-00000060 37 d9 4b 70 72 91 89 d4 d7 c2 c3 e7 ff dc 72 2a |7.Kpr.........r*|
-00000070 ba f5 30 b0 e9 dd 48 10 3d cd 98 48 a3 e3 ca de |..0...H.=..H....|
-00000080 15 0e 90 8e e5 04 14 74 42 b8 b0 12 cc 68 7b 7d |.......tB....h{}|
-00000090 6c 43 72 60 05 0d |lCr`..|
+00000000 16 03 03 00 46 10 00 00 42 41 04 f2 52 42 97 0a |....F...BA..RB..|
+00000010 df a1 e0 cb 4e 5e 3c e5 45 0e de b3 eb 3d cd c2 |....N^<.E....=..|
+00000020 78 77 ff ec 6e 74 c2 e5 9e 89 58 6f 2b bc 41 5b |xw..nt....Xo+.A[|
+00000030 d5 8f d0 ea ce c6 c9 11 74 0a c1 33 2a 52 c2 30 |........t..3*R.0|
+00000040 73 08 5f 20 f2 0a 45 95 81 a8 eb 14 03 03 00 01 |s._ ..E.........|
+00000050 01 16 03 03 00 28 52 9e 4c 11 49 07 9f b5 4b 2f |.....(R.L.I...K/|
+00000060 45 79 0c d9 cb ae 45 7d 17 1e c2 5a d3 ea bd 8b |Ey....E}...Z....|
+00000070 0d 94 b1 40 a2 56 6e a5 f8 a2 5b f8 63 73 |...@.Vn...[.cs|
>>> Flow 4 (server to client)
00000000 16 03 03 00 72 04 00 00 6e 00 00 00 00 00 68 00 |....r...n.....h.|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 65 |...............e|
-00000020 ea 8b c0 ef ba 12 45 17 61 24 cd d2 4c 22 bb 3b |......E.a$..L".;|
-00000030 e3 0e d0 ff 83 e9 7c b7 8f 10 3c 16 1c fc c2 44 |......|...<....D|
-00000040 ef 45 f8 27 30 56 db ea eb ae f5 b6 17 b2 ef f9 |.E.'0V..........|
-00000050 96 0d 2d db e4 59 23 0a fc fa e3 13 48 57 e5 b3 |..-..Y#.....HW..|
-00000060 3a d1 f5 5e ca ef d7 3f 7b b5 f4 69 85 c3 bd da |:..^...?{..i....|
-00000070 fd 9c 50 05 2f 86 ce 14 03 03 00 01 01 16 03 03 |..P./...........|
-00000080 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |.@..............|
-00000090 00 00 60 25 1c ed 6f c6 a5 bd b2 29 39 4e 09 d1 |..`%..o....)9N..|
-000000a0 64 cc 75 cd df 91 a8 90 9d 03 aa 92 07 f2 d0 8a |d.u.............|
-000000b0 60 bb 3e 85 21 22 fe f8 dc 52 3c 4e 82 77 14 14 |`.>.!"...R<N.w..|
-000000c0 0f 1f 17 03 03 00 40 00 00 00 00 00 00 00 00 00 |......@.........|
-000000d0 00 00 00 00 00 00 00 0b 87 12 62 3e e5 3e 7d 74 |..........b>.>}t|
-000000e0 0d ac c4 a9 df 67 1c 5a ad 3e 01 34 03 88 2f 39 |.....g.Z.>.4../9|
-000000f0 f7 3c 06 e4 f6 81 43 66 b1 1b ed a5 e5 b6 a8 43 |.<....Cf.......C|
-00000100 7f 36 2f b2 da 45 9a 15 03 03 00 30 00 00 00 00 |.6/..E.....0....|
-00000110 00 00 00 00 00 00 00 00 00 00 00 00 fa 63 4e c5 |.............cN.|
-00000120 77 89 71 56 e3 0a cf 98 da 2f 89 8f 74 8e 76 24 |w.qV...../..t.v$|
-00000130 e2 40 a5 9f 29 1b b2 11 ef 7a 55 7f |.@..)....zU.|
+00000020 ea 8b e4 ef ba f6 cb 68 be 7f f0 66 1a c6 3c c6 |.......h...f..<.|
+00000030 ee 5f 60 3a 62 20 c5 e8 ea 99 92 84 c1 45 a1 76 |._`:b .......E.v|
+00000040 7c a7 f2 cd 40 72 9b 38 51 77 f2 ae 54 dd 67 37 ||...@r.8Qw..T.g7|
+00000050 f8 98 43 2e 55 59 23 3b 50 26 87 ca 6b 2d 45 d6 |..C.UY#;P&..k-E.|
+00000060 3c 85 29 f4 52 58 83 98 ae ad a9 64 8b d1 cc 9c |<.).RX.....d....|
+00000070 88 3f a8 f9 d2 d3 33 14 03 03 00 01 01 16 03 03 |.?....3.........|
+00000080 00 28 00 00 00 00 00 00 00 00 84 6d 6d 57 fb dc |.(.........mmW..|
+00000090 09 54 c4 9a fc d7 dd 45 f5 c3 57 fd e9 16 76 ab |.T.....E..W...v.|
+000000a0 a8 85 eb 34 e7 21 30 85 56 ed 17 03 03 00 25 00 |...4.!0.V.....%.|
+000000b0 00 00 00 00 00 00 01 05 62 69 79 cb c0 74 ad 64 |........biy..t.d|
+000000c0 0a 0c 2a 10 2a b7 8e e2 92 6e 12 3b d7 64 df d7 |..*.*....n.;.d..|
+000000d0 4f da 52 c6 15 03 03 00 1a 00 00 00 00 00 00 00 |O.R.............|
+000000e0 02 b9 dc 49 b9 2a 12 58 3a 4b 4c e0 c8 b2 e9 d9 |...I.*.X:KL.....|
+000000f0 dc 48 17 |.H.|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 ca 01 00 00 c6 03 03 53 04 f1 3f 5f |...........S..?_|
-00000010 f4 ef 1f b3 41 0b 54 e4 4d 56 0a 31 22 b8 5c 73 |....A.T.MV.1".\s|
-00000020 a3 cb b5 b2 9d 43 f1 83 bc d3 bd 00 00 32 c0 30 |.....C.......2.0|
-00000030 c0 2c c0 28 c0 24 c0 14 c0 0a c0 22 c0 21 00 a3 |.,.(.$.....".!..|
-00000040 00 9f 00 6b 00 6a 00 39 00 38 00 88 00 87 c0 32 |...k.j.9.8.....2|
-00000050 c0 2e c0 2a c0 26 c0 0f c0 05 00 9d 00 3d 00 35 |...*.&.......=.5|
-00000060 01 00 00 6b 00 0b 00 04 03 00 01 02 00 0a 00 34 |...k...........4|
-00000070 00 32 00 0e 00 0d 00 19 00 0b 00 0c 00 18 00 09 |.2..............|
-00000080 00 0a 00 16 00 17 00 08 00 06 00 07 00 14 00 15 |................|
-00000090 00 04 00 05 00 12 00 13 00 01 00 02 00 03 00 0f |................|
-000000a0 00 10 00 11 00 0d 00 22 00 20 06 01 06 02 06 03 |.......". ......|
-000000b0 05 01 05 02 05 03 04 01 04 02 04 03 03 01 03 02 |................|
-000000c0 03 03 02 01 02 02 02 03 01 01 00 0f 00 01 01 |...............|
+00000000 16 03 01 01 61 01 00 01 5d 03 03 47 c5 84 0f 55 |....a...]..G...U|
+00000010 83 4d 4a 1c 48 51 15 e4 74 72 84 70 2f 24 e9 ab |.MJ.HQ..tr.p/$..|
+00000020 42 1e 01 e1 85 27 2f b5 c1 43 14 00 00 c4 c0 30 |B....'/..C.....0|
+00000030 c0 2c c0 28 c0 24 c0 14 c0 0a 00 a5 00 a3 00 a1 |.,.(.$..........|
+00000040 00 9f 00 6b 00 6a 00 69 00 68 00 39 00 38 00 37 |...k.j.i.h.9.8.7|
+00000050 00 36 00 88 00 87 00 86 00 85 c0 32 c0 2e c0 2a |.6.........2...*|
+00000060 c0 26 c0 0f c0 05 00 9d 00 3d 00 35 00 84 c0 2f |.&.......=.5.../|
+00000070 c0 2b c0 27 c0 23 c0 13 c0 09 00 a4 00 a2 00 a0 |.+.'.#..........|
+00000080 00 9e 00 67 00 40 00 3f 00 3e 00 33 00 32 00 31 |...g.@.?.>.3.2.1|
+00000090 00 30 00 9a 00 99 00 98 00 97 00 45 00 44 00 43 |.0.........E.D.C|
+000000a0 00 42 c0 31 c0 2d c0 29 c0 25 c0 0e c0 04 00 9c |.B.1.-.).%......|
+000000b0 00 3c 00 2f 00 96 00 41 00 07 c0 11 c0 07 c0 0c |.<./...A........|
+000000c0 c0 02 00 05 00 04 c0 12 c0 08 00 16 00 13 00 10 |................|
+000000d0 00 0d c0 0d c0 03 00 0a 00 15 00 12 00 0f 00 0c |................|
+000000e0 00 09 00 14 00 11 00 0e 00 0b 00 08 00 06 00 03 |................|
+000000f0 00 ff 02 01 00 00 6f 00 0b 00 04 03 00 01 02 00 |......o.........|
+00000100 0a 00 3a 00 38 00 0e 00 0d 00 19 00 1c 00 0b 00 |..:.8...........|
+00000110 0c 00 1b 00 18 00 09 00 0a 00 1a 00 16 00 17 00 |................|
+00000120 08 00 06 00 07 00 14 00 15 00 04 00 05 00 12 00 |................|
+00000130 13 00 01 00 02 00 03 00 0f 00 10 00 11 00 0d 00 |................|
+00000140 20 00 1e 06 01 06 02 06 03 05 01 05 02 05 03 04 | ...............|
+00000150 01 04 02 04 03 03 01 03 02 03 03 02 01 02 02 02 |................|
+00000160 03 00 0f 00 01 01 |......|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 2a 02 00 00 26 03 03 00 00 00 00 00 |....*...&.......|
+00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 c0 0a 00 16 |................|
-00000030 03 03 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 |..............0.|
-00000040 02 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb |..0..b.....-G...|
-00000050 f4 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 0b |.0...*.H.=..0E1.|
-00000060 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..|
-00000070 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State|
-00000080 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter|
-00000090 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty |
-000000a0 4c 74 64 30 1e 17 0d 31 32 31 31 32 32 31 35 30 |Ltd0...121122150|
-000000b0 36 33 32 5a 17 0d 32 32 31 31 32 30 31 35 30 36 |632Z..2211201506|
-000000c0 33 32 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |32Z0E1.0...U....|
-000000d0 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som|
-000000e0 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..|
-000000f0 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi|
-00000100 74 73 20 50 74 79 20 4c 74 64 30 81 9b 30 10 06 |ts Pty Ltd0..0..|
-00000110 07 2a 86 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 |.*.H.=....+...#.|
-00000120 81 86 00 04 00 c4 a1 ed be 98 f9 0b 48 73 36 7e |............Hs6~|
-00000130 c3 16 56 11 22 f2 3d 53 c3 3b 4d 21 3d cd 6b 75 |..V.".=S.;M!=.ku|
-00000140 e6 f6 b0 dc 9a df 26 c1 bc b2 87 f0 72 32 7c b3 |......&.....r2|.|
-00000150 64 2f 1c 90 bc ea 68 23 10 7e fe e3 25 c0 48 3a |d/....h#.~..%.H:|
-00000160 69 e0 28 6d d3 37 00 ef 04 62 dd 0d a0 9c 70 62 |i.(m.7...b....pb|
-00000170 83 d8 81 d3 64 31 aa 9e 97 31 bd 96 b0 68 c0 9b |....d1...1...h..|
-00000180 23 de 76 64 3f 1a 5c 7f e9 12 0e 58 58 b6 5f 70 |#.vd?.\....XX._p|
-00000190 dd 9b d8 ea d5 d7 f5 d5 cc b9 b6 9f 30 66 5b 66 |............0f[f|
-000001a0 9a 20 e2 27 e5 bf fe 3b 30 09 06 07 2a 86 48 ce |. .'...;0...*.H.|
-000001b0 3d 04 01 03 81 8c 00 30 81 88 02 42 01 88 a2 4f |=......0...B...O|
-000001c0 eb e2 45 c5 48 7d 1b ac f5 ed 98 9d ae 47 70 c0 |..E.H}.......Gp.|
-000001d0 5e 1b b6 2f bd f1 b6 4d b7 61 40 d3 11 a2 ce ee |^../...M.a@.....|
-000001e0 0b 7e 92 7e ff 76 9d c3 3b 7e a5 3f ce fa 10 e2 |.~.~.v..;~.?....|
-000001f0 59 ec 47 2d 7c ac da 4e 97 0e 15 a0 6f d0 02 42 |Y.G-|..N....o..B|
-00000200 01 4d fc be 67 13 9c 2d 05 0e bd 3f a3 8c 25 c1 |.M..g..-...?..%.|
-00000210 33 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e |3.......7z..z...|
-00000220 dd d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 |...i..|V..1x+..x|
-00000230 0d ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 |.....N6$1{j.9...|
-00000240 8f 2a 16 03 03 00 d8 0c 00 00 d4 03 00 17 41 04 |.*............A.|
-00000250 1e 18 37 ef 0d 19 51 88 35 75 71 b5 e5 54 5b 12 |..7...Q.5uq..T[.|
-00000260 2e 8f 09 67 fd a7 24 20 3e b2 56 1c ce 97 28 5e |...g..$ >.V...(^|
-00000270 f8 2b 2d 4f 9e f1 07 9f 6c 4b 5b 83 56 e2 32 42 |.+-O....lK[.V.2B|
-00000280 e9 58 b6 d7 49 a6 b5 68 1a 41 03 56 6b dc 5a 89 |.X..I..h.A.Vk.Z.|
-00000290 04 03 00 8b 30 81 88 02 42 00 c6 85 8e 06 b7 04 |....0...B.......|
-000002a0 04 e9 cd 9e 3e cb 66 23 95 b4 42 9c 64 81 39 05 |....>.f#..B.d.9.|
-000002b0 3f b5 21 f8 28 af 60 6b 4d 3d ba a1 4b 5e 77 ef |?.!.(.`kM=..K^w.|
-000002c0 e7 59 28 fe 1d c1 27 a2 ff a8 de 33 48 b3 c1 85 |.Y(...'....3H...|
-000002d0 6a 42 9b f9 7e 7e 31 c2 e5 bd 66 02 42 00 ad 7d |jB..~~1...f.B..}|
-000002e0 06 35 ab ec 8d ac d4 ba 1b 49 5e 05 5f f0 97 93 |.5.......I^._...|
-000002f0 82 b8 2b 8d 91 98 63 8e b4 14 62 db 1e c9 2b 64 |..+...c...b...+d|
-00000300 e9 e6 bf 15 5b 67 c2 40 90 c6 1f b7 92 db 4b f6 |....[g.@......K.|
-00000310 f4 db ae 82 f1 4f 02 75 52 40 38 10 ff 35 f0 16 |.....O.uR@8..5..|
-00000320 03 03 00 04 0e 00 00 00 |........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 c0 0a 00 00 |................|
+00000030 05 ff 01 00 01 00 16 03 03 02 0e 0b 00 02 0a 00 |................|
+00000040 02 07 00 02 04 30 82 02 00 30 82 01 62 02 09 00 |.....0...0..b...|
+00000050 b8 bf 2d 47 a0 d2 eb f4 30 09 06 07 2a 86 48 ce |..-G....0...*.H.|
+00000060 3d 04 01 30 45 31 0b 30 09 06 03 55 04 06 13 02 |=..0E1.0...U....|
+00000070 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som|
+00000080 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..|
+00000090 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi|
+000000a0 74 73 20 50 74 79 20 4c 74 64 30 1e 17 0d 31 32 |ts Pty Ltd0...12|
+000000b0 31 31 32 32 31 35 30 36 33 32 5a 17 0d 32 32 31 |1122150632Z..221|
+000000c0 31 32 30 31 35 30 36 33 32 5a 30 45 31 0b 30 09 |120150632Z0E1.0.|
+000000d0 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 55 |..U....AU1.0...U|
+000000e0 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 21 |....Some-State1!|
+000000f0 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e 65 |0...U....Interne|
+00000100 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c 74 |t Widgits Pty Lt|
+00000110 64 30 81 9b 30 10 06 07 2a 86 48 ce 3d 02 01 06 |d0..0...*.H.=...|
+00000120 05 2b 81 04 00 23 03 81 86 00 04 00 c4 a1 ed be |.+...#..........|
+00000130 98 f9 0b 48 73 36 7e c3 16 56 11 22 f2 3d 53 c3 |...Hs6~..V.".=S.|
+00000140 3b 4d 21 3d cd 6b 75 e6 f6 b0 dc 9a df 26 c1 bc |;M!=.ku......&..|
+00000150 b2 87 f0 72 32 7c b3 64 2f 1c 90 bc ea 68 23 10 |...r2|.d/....h#.|
+00000160 7e fe e3 25 c0 48 3a 69 e0 28 6d d3 37 00 ef 04 |~..%.H:i.(m.7...|
+00000170 62 dd 0d a0 9c 70 62 83 d8 81 d3 64 31 aa 9e 97 |b....pb....d1...|
+00000180 31 bd 96 b0 68 c0 9b 23 de 76 64 3f 1a 5c 7f e9 |1...h..#.vd?.\..|
+00000190 12 0e 58 58 b6 5f 70 dd 9b d8 ea d5 d7 f5 d5 cc |..XX._p.........|
+000001a0 b9 b6 9f 30 66 5b 66 9a 20 e2 27 e5 bf fe 3b 30 |...0f[f. .'...;0|
+000001b0 09 06 07 2a 86 48 ce 3d 04 01 03 81 8c 00 30 81 |...*.H.=......0.|
+000001c0 88 02 42 01 88 a2 4f eb e2 45 c5 48 7d 1b ac f5 |..B...O..E.H}...|
+000001d0 ed 98 9d ae 47 70 c0 5e 1b b6 2f bd f1 b6 4d b7 |....Gp.^../...M.|
+000001e0 61 40 d3 11 a2 ce ee 0b 7e 92 7e ff 76 9d c3 3b |a@......~.~.v..;|
+000001f0 7e a5 3f ce fa 10 e2 59 ec 47 2d 7c ac da 4e 97 |~.?....Y.G-|..N.|
+00000200 0e 15 a0 6f d0 02 42 01 4d fc be 67 13 9c 2d 05 |...o..B.M..g..-.|
+00000210 0e bd 3f a3 8c 25 c1 33 13 83 0d 94 06 bb d4 37 |..?..%.3.......7|
+00000220 7a f6 ec 7a c9 86 2e dd d7 11 69 7f 85 7c 56 de |z..z......i..|V.|
+00000230 fb 31 78 2b e4 c7 78 0d ae cb be 9e 4e 36 24 31 |.1x+..x.....N6$1|
+00000240 7b 6a 0f 39 95 12 07 8f 2a 16 03 03 00 d7 0c 00 |{j.9....*.......|
+00000250 00 d3 03 00 17 41 04 1e 18 37 ef 0d 19 51 88 35 |.....A...7...Q.5|
+00000260 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 24 20 3e |uq..T[....g..$ >|
+00000270 b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 07 9f 6c |.V...(^.+-O....l|
+00000280 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 b5 68 1a |K[.V.2B.X..I..h.|
+00000290 41 03 56 6b dc 5a 89 04 03 00 8a 30 81 87 02 42 |A.Vk.Z.....0...B|
+000002a0 00 e5 db 39 b2 73 2b 4b 19 66 d6 d6 de d2 ed ae |...9.s+K.f......|
+000002b0 0c ac 74 96 12 b2 e0 87 73 7c 63 18 8c 58 3f 56 |..t.....s|c..X?V|
+000002c0 4c fe 0f a5 2d b9 b8 1c 7d 4d 49 b9 ca f0 52 01 |L...-...}MI...R.|
+000002d0 12 e2 a9 54 9f 4d ab b7 93 71 3c 1b 96 b0 87 8b |...T.M...q<.....|
+000002e0 87 c3 02 41 79 c3 50 88 2f 9a b8 a3 f0 14 63 ee |...Ay.P./.....c.|
+000002f0 d6 76 dd d4 1d 1c ce 4c ba 53 40 ac 01 d9 62 a7 |.v.....L.S@...b.|
+00000300 bc ee 66 67 fc da f4 b3 0f fd 50 5d 31 0e 2d 41 |..fg......P]1.-A|
+00000310 64 d5 51 30 a3 0e ee 20 f9 9d 0e 11 df 68 a6 f4 |d.Q0... .....h..|
+00000320 54 d4 54 7a 05 16 03 03 00 04 0e 00 00 00 |T.Tz..........|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 46 10 00 00 42 41 04 d8 94 c4 05 26 |....F...BA.....&|
-00000010 76 29 2d 0e ec 47 b6 50 d5 a3 da 2a ba 02 11 37 |v)-..G.P...*...7|
-00000020 3d ef e6 2a db d0 47 47 a7 9a 5f 43 2d 98 78 26 |=..*..GG.._C-.x&|
-00000030 81 e2 f1 ba fe f7 66 c6 61 cb c1 b7 60 62 34 a5 |......f.a...`b4.|
-00000040 78 67 50 3d 9a 0e 4a 8c 8f d7 10 14 03 03 00 01 |xgP=..J.........|
-00000050 01 16 03 03 00 40 5e 46 b0 5d 30 f6 da 8f 9e 67 |.....@^F.]0....g|
-00000060 f5 3e bd fe c9 b8 53 b2 10 d5 7c 0e 34 e3 93 6d |.>....S...|.4..m|
-00000070 0e 8e 8a 2b df fb 9a 0f a5 23 55 e7 0a 4b e2 d3 |...+.....#U..K..|
-00000080 db 15 e8 52 74 26 78 b3 b0 56 65 63 ac ae 1e c0 |...Rt&x..Vec....|
-00000090 0b f4 92 56 a9 04 |...V..|
+00000000 16 03 03 00 46 10 00 00 42 41 04 00 a1 de 66 1d |....F...BA....f.|
+00000010 05 57 3b d2 0e 5f ba 4d e9 b7 93 0a 3e bd 25 98 |.W;.._.M....>.%.|
+00000020 76 a4 8a c9 d3 c8 04 85 f6 8d 4f 3e 32 4c 25 cb |v.........O>2L%.|
+00000030 b5 57 86 b5 04 9d f6 ba f3 17 c8 43 cb eb 8b d0 |.W.........C....|
+00000040 ed 99 23 c7 4d 63 95 e2 cd 52 ba 14 03 03 00 01 |..#.Mc...R......|
+00000050 01 16 03 03 00 40 33 b4 f5 4a 64 88 ef dc b6 e5 |.....@3..Jd.....|
+00000060 b6 1e 40 3e 64 5a 2c 11 97 69 4c b6 7a 4c 9a 8a |..@>dZ,..iL.zL..|
+00000070 71 f2 60 e9 39 db 96 2a a3 33 1b 7f 43 15 8b 99 |q.`.9..*.3..C...|
+00000080 0b 52 c2 92 86 fe 57 0d da fe 62 44 89 ce 65 4f |.R....W...bD..eO|
+00000090 a5 8d 29 8e 10 50 |..)..P|
>>> Flow 4 (server to client)
00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....|
-00000010 00 00 00 00 00 00 00 00 00 00 00 16 a9 63 0a 99 |.............c..|
-00000020 21 8a fc 5c b3 ee 05 71 4e 75 c0 d9 40 54 0d 3e |!..\...qNu..@T.>|
-00000030 4e 5d 44 b7 4b 5d a9 e7 5a 30 ed b6 d5 08 50 b1 |N]D.K]..Z0....P.|
-00000040 e8 8c 54 eb 1b 39 7a f9 3b ac 2e 17 03 03 00 40 |..T..9z.;......@|
+00000010 00 00 00 00 00 00 00 00 00 00 00 29 56 67 0c 28 |...........)Vg.(|
+00000020 ca 74 e1 ae c6 e2 30 3b f2 8b f0 fd c2 eb 11 c0 |.t....0;........|
+00000030 0e 50 eb d8 4e de e3 32 6b 69 77 d8 d7 bd 94 30 |.P..N..2kiw....0|
+00000040 1e bf 03 f0 31 98 d8 07 c0 27 4b 17 03 03 00 40 |....1....'K....@|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000060 96 03 20 2b 20 c4 c1 9a 76 7b f3 96 bd 33 ed e6 |.. + ...v{...3..|
-00000070 38 48 ea 53 d5 e0 62 b5 7e 1a 36 a8 dd 9f 2d 4b |8H.S..b.~.6...-K|
-00000080 06 0d ae f6 bc 99 14 b3 93 14 27 63 e2 a0 c8 76 |..........'c...v|
+00000060 97 7f df af a3 9e cc a1 64 5f ab 91 8a 6f fd 19 |........d_...o..|
+00000070 be 94 95 6d bb de 12 a9 54 10 b5 95 f3 68 77 73 |...m....T....hws|
+00000080 14 09 b7 3b ca b8 88 6d fd 0a 2d 24 c1 94 ce ce |...;...m..-$....|
00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
-000000a0 00 00 00 00 00 48 af e1 e4 11 e1 b7 03 19 b0 e3 |.....H..........|
-000000b0 e6 a9 66 d8 ac af aa 03 f6 0d 51 df 9a 27 78 3a |..f.......Q..'x:|
-000000c0 56 5a 03 1a 4c |VZ..L|
+000000a0 00 00 00 00 00 04 6d b7 9e 15 51 c7 f8 de ab d0 |......m...Q.....|
+000000b0 a0 45 7f 4f bc 59 73 45 e9 a8 b1 0e 9b c3 36 c7 |.E.O.YsE......6.|
+000000c0 cb db 55 19 db |..U..|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 ca 01 00 00 c6 03 03 53 04 f1 3f cc |...........S..?.|
-00000010 41 74 00 07 cb ae 3b 30 79 48 51 60 41 a3 8c ab |At....;0yHQ`A...|
-00000020 dc 76 f9 74 52 1e c5 fb a9 69 c2 00 00 32 c0 30 |.v.tR....i...2.0|
-00000030 c0 2c c0 28 c0 24 c0 14 c0 0a c0 22 c0 21 00 a3 |.,.(.$.....".!..|
-00000040 00 9f 00 6b 00 6a 00 39 00 38 00 88 00 87 c0 32 |...k.j.9.8.....2|
-00000050 c0 2e c0 2a c0 26 c0 0f c0 05 00 9d 00 3d 00 35 |...*.&.......=.5|
-00000060 01 00 00 6b 00 0b 00 04 03 00 01 02 00 0a 00 34 |...k...........4|
-00000070 00 32 00 0e 00 0d 00 19 00 0b 00 0c 00 18 00 09 |.2..............|
-00000080 00 0a 00 16 00 17 00 08 00 06 00 07 00 14 00 15 |................|
-00000090 00 04 00 05 00 12 00 13 00 01 00 02 00 03 00 0f |................|
-000000a0 00 10 00 11 00 0d 00 22 00 20 06 01 06 02 06 03 |.......". ......|
-000000b0 05 01 05 02 05 03 04 01 04 02 04 03 03 01 03 02 |................|
-000000c0 03 03 02 01 02 02 02 03 01 01 00 0f 00 01 01 |...............|
+00000000 16 03 01 01 61 01 00 01 5d 03 03 17 83 43 01 d8 |....a...]....C..|
+00000010 14 04 ed 55 41 35 99 cd f6 50 e6 47 10 60 7d d9 |...UA5...P.G.`}.|
+00000020 d1 f4 0f a1 bf 27 ab 0c 44 56 a5 00 00 c4 c0 30 |.....'..DV.....0|
+00000030 c0 2c c0 28 c0 24 c0 14 c0 0a 00 a5 00 a3 00 a1 |.,.(.$..........|
+00000040 00 9f 00 6b 00 6a 00 69 00 68 00 39 00 38 00 37 |...k.j.i.h.9.8.7|
+00000050 00 36 00 88 00 87 00 86 00 85 c0 32 c0 2e c0 2a |.6.........2...*|
+00000060 c0 26 c0 0f c0 05 00 9d 00 3d 00 35 00 84 c0 2f |.&.......=.5.../|
+00000070 c0 2b c0 27 c0 23 c0 13 c0 09 00 a4 00 a2 00 a0 |.+.'.#..........|
+00000080 00 9e 00 67 00 40 00 3f 00 3e 00 33 00 32 00 31 |...g.@.?.>.3.2.1|
+00000090 00 30 00 9a 00 99 00 98 00 97 00 45 00 44 00 43 |.0.........E.D.C|
+000000a0 00 42 c0 31 c0 2d c0 29 c0 25 c0 0e c0 04 00 9c |.B.1.-.).%......|
+000000b0 00 3c 00 2f 00 96 00 41 00 07 c0 11 c0 07 c0 0c |.<./...A........|
+000000c0 c0 02 00 05 00 04 c0 12 c0 08 00 16 00 13 00 10 |................|
+000000d0 00 0d c0 0d c0 03 00 0a 00 15 00 12 00 0f 00 0c |................|
+000000e0 00 09 00 14 00 11 00 0e 00 0b 00 08 00 06 00 03 |................|
+000000f0 00 ff 02 01 00 00 6f 00 0b 00 04 03 00 01 02 00 |......o.........|
+00000100 0a 00 3a 00 38 00 0e 00 0d 00 19 00 1c 00 0b 00 |..:.8...........|
+00000110 0c 00 1b 00 18 00 09 00 0a 00 1a 00 16 00 17 00 |................|
+00000120 08 00 06 00 07 00 14 00 15 00 04 00 05 00 12 00 |................|
+00000130 13 00 01 00 02 00 03 00 0f 00 10 00 11 00 0d 00 |................|
+00000140 20 00 1e 06 01 06 02 06 03 05 01 05 02 05 03 04 | ...............|
+00000150 01 04 02 04 03 03 01 03 02 03 03 02 01 02 02 02 |................|
+00000160 03 00 0f 00 01 01 |......|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 2a 02 00 00 26 03 03 00 00 00 00 00 |....*...&.......|
+00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000020 00 00 00 00 00 00 00 00 00 00 00 00 c0 14 00 16 |................|
-00000030 03 03 02 be 0b 00 02 ba 00 02 b7 00 02 b4 30 82 |..............0.|
-00000040 02 b0 30 82 02 19 a0 03 02 01 02 02 09 00 85 b0 |..0.............|
-00000050 bb a4 8a 7f b8 ca 30 0d 06 09 2a 86 48 86 f7 0d |......0...*.H...|
-00000060 01 01 05 05 00 30 45 31 0b 30 09 06 03 55 04 06 |.....0E1.0...U..|
-00000070 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 |..AU1.0...U....S|
-00000080 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 |ome-State1!0...U|
-00000090 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 |....Internet Wid|
-000000a0 67 69 74 73 20 50 74 79 20 4c 74 64 30 1e 17 0d |gits Pty Ltd0...|
-000000b0 31 30 30 34 32 34 30 39 30 39 33 38 5a 17 0d 31 |100424090938Z..1|
-000000c0 31 30 34 32 34 30 39 30 39 33 38 5a 30 45 31 0b |10424090938Z0E1.|
-000000d0 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..|
-000000e0 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State|
-000000f0 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter|
-00000100 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty |
-00000110 4c 74 64 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d |Ltd0..0...*.H...|
-00000120 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 |.........0......|
-00000130 bb 79 d6 f5 17 b5 e5 bf 46 10 d0 dc 69 be e6 2b |.y......F...i..+|
-00000140 07 43 5a d0 03 2d 8a 7a 43 85 b7 14 52 e7 a5 65 |.CZ..-.zC...R..e|
-00000150 4c 2c 78 b8 23 8c b5 b4 82 e5 de 1f 95 3b 7e 62 |L,x.#........;~b|
-00000160 a5 2c a5 33 d6 fe 12 5c 7a 56 fc f5 06 bf fa 58 |.,.3...\zV.....X|
-00000170 7b 26 3f b5 cd 04 d3 d0 c9 21 96 4a c7 f4 54 9f |{&?......!.J..T.|
-00000180 5a bf ef 42 71 00 fe 18 99 07 7f 7e 88 7d 7d f1 |Z..Bq......~.}}.|
-00000190 04 39 c4 a2 2e db 51 c9 7c e3 c0 4c 3b 32 66 01 |.9....Q.|..L;2f.|
-000001a0 cf af b1 1d b8 71 9a 1d db db 89 6b ae da 2d 79 |.....q.....k..-y|
-000001b0 02 03 01 00 01 a3 81 a7 30 81 a4 30 1d 06 03 55 |........0..0...U|
-000001c0 1d 0e 04 16 04 14 b1 ad e2 85 5a cf cb 28 db 69 |..........Z..(.i|
-000001d0 ce 23 69 de d3 26 8e 18 88 39 30 75 06 03 55 1d |.#i..&...90u..U.|
-000001e0 23 04 6e 30 6c 80 14 b1 ad e2 85 5a cf cb 28 db |#.n0l......Z..(.|
-000001f0 69 ce 23 69 de d3 26 8e 18 88 39 a1 49 a4 47 30 |i.#i..&...9.I.G0|
-00000200 45 31 0b 30 09 06 03 55 04 06 13 02 41 55 31 13 |E1.0...U....AU1.|
-00000210 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 |0...U....Some-St|
-00000220 61 74 65 31 21 30 1f 06 03 55 04 0a 13 18 49 6e |ate1!0...U....In|
-00000230 74 65 72 6e 65 74 20 57 69 64 67 69 74 73 20 50 |ternet Widgits P|
-00000240 74 79 20 4c 74 64 82 09 00 85 b0 bb a4 8a 7f b8 |ty Ltd..........|
-00000250 ca 30 0c 06 03 55 1d 13 04 05 30 03 01 01 ff 30 |.0...U....0....0|
-00000260 0d 06 09 2a 86 48 86 f7 0d 01 01 05 05 00 03 81 |...*.H..........|
-00000270 81 00 08 6c 45 24 c7 6b b1 59 ab 0c 52 cc f2 b0 |...lE$.k.Y..R...|
-00000280 14 d7 87 9d 7a 64 75 b5 5a 95 66 e4 c5 2b 8e ae |....zdu.Z.f..+..|
-00000290 12 66 1f eb 4f 38 b3 6e 60 d3 92 fd f7 41 08 b5 |.f..O8.n`....A..|
-000002a0 25 13 b1 18 7a 24 fb 30 1d ba ed 98 b9 17 ec e7 |%...z$.0........|
-000002b0 d7 31 59 db 95 d3 1d 78 ea 50 56 5c d5 82 5a 2d |.1Y....x.PV\..Z-|
-000002c0 5a 5f 33 c4 b6 d8 c9 75 90 96 8c 0f 52 98 b5 cd |Z_3....u....R...|
-000002d0 98 1f 89 20 5f f2 a0 1c a3 1b 96 94 dd a9 fd 57 |... _..........W|
-000002e0 e9 70 e8 26 6d 71 99 9b 26 6e 38 50 29 6c 90 a7 |.p.&mq..&n8P)l..|
-000002f0 bd d9 16 03 03 00 cd 0c 00 00 c9 03 00 17 41 04 |..............A.|
-00000300 1e 18 37 ef 0d 19 51 88 35 75 71 b5 e5 54 5b 12 |..7...Q.5uq..T[.|
-00000310 2e 8f 09 67 fd a7 24 20 3e b2 56 1c ce 97 28 5e |...g..$ >.V...(^|
-00000320 f8 2b 2d 4f 9e f1 07 9f 6c 4b 5b 83 56 e2 32 42 |.+-O....lK[.V.2B|
-00000330 e9 58 b6 d7 49 a6 b5 68 1a 41 03 56 6b dc 5a 89 |.X..I..h.A.Vk.Z.|
-00000340 04 01 00 80 9d 84 09 35 73 fb f6 ea 94 7b 49 fb |.......5s....{I.|
-00000350 c2 70 b1 11 64 5b 93 9f d9 8c f5 56 98 f6 d3 66 |.p..d[.....V...f|
-00000360 a6 1d 18 56 88 87 71 3f b0 38 9d 44 1f ad 2c 0d |...V..q?.8.D..,.|
-00000370 3a a7 e8 d4 3e 33 3c 41 20 f3 3f 5c e5 fb e3 23 |:...>3<A .?\...#|
-00000380 12 48 ff d2 c4 30 7c 8a 51 3f 9f 19 6e 34 d7 60 |.H...0|.Q?..n4.`|
-00000390 7d 12 8a aa 90 0f 50 d9 0b 9a b2 d7 66 b1 c6 84 |}.....P.....f...|
-000003a0 af 5c e2 5e 16 3e 36 61 73 84 64 89 b3 c1 6d 50 |.\.^.>6as.d...mP|
-000003b0 33 55 c7 e1 c5 a5 4c 32 5c 95 dc 07 43 60 49 11 |3U....L2\...C`I.|
-000003c0 e9 98 cc ba 16 03 03 00 04 0e 00 00 00 |.............|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 c0 14 00 00 |................|
+00000030 05 ff 01 00 01 00 16 03 03 02 be 0b 00 02 ba 00 |................|
+00000040 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......|
+00000050 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..|
+00000060 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.|
+00000070 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..|
+00000080 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State|
+00000090 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter|
+000000a0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty |
+000000b0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090|
+000000c0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909|
+000000d0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....|
+000000e0 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som|
+000000f0 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..|
+00000100 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi|
+00000110 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..|
+00000120 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............|
+00000130 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F|
+00000140 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC|
+00000150 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....|
+00000160 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z|
+00000170 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......|
+00000180 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....|
+00000190 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.||
+000001a0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...|
+000001b0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0|
+000001c0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........|
+000001d0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...|
+000001e0 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....|
+000001f0 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..|
+00000200 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.|
+00000210 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....|
+00000220 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...|
+00000230 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi|
+00000240 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...|
+00000250 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...|
+00000260 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...|
+00000270 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.|
+00000280 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z|
+00000290 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`|
+000002a0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.|
+000002b0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.|
+000002c0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.|
+000002d0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....|
+000002e0 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&|
+000002f0 6e 38 50 29 6c 90 a7 bd d9 16 03 03 00 cd 0c 00 |n8P)l...........|
+00000300 00 c9 03 00 17 41 04 1e 18 37 ef 0d 19 51 88 35 |.....A...7...Q.5|
+00000310 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 24 20 3e |uq..T[....g..$ >|
+00000320 b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 07 9f 6c |.V...(^.+-O....l|
+00000330 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 b5 68 1a |K[.V.2B.X..I..h.|
+00000340 41 03 56 6b dc 5a 89 04 01 00 80 7f 65 76 11 35 |A.Vk.Z......ev.5|
+00000350 e1 9c c6 0c 21 41 d6 b4 22 2f a3 02 57 5c 40 5c |....!A.."/..W\@\|
+00000360 2e 0c 5f 07 01 d1 78 29 a3 7b 65 37 1c c6 51 a8 |.._...x).{e7..Q.|
+00000370 e1 70 b4 73 9a cf 37 73 c8 ce 7c 8b 60 9e 0f e4 |.p.s..7s..|.`...|
+00000380 d7 2e 2a a8 fd 5a 0c 8a e7 e0 4c ca 0b 28 6d ea |..*..Z....L..(m.|
+00000390 39 da 9f ac 6c 23 f0 c6 fe 21 a8 ad fb e8 c9 6d |9...l#...!.....m|
+000003a0 96 86 75 4d 88 f0 e8 71 e0 dc 32 b9 81 f9 f3 fe |..uM...q..2.....|
+000003b0 64 e1 34 62 dc e2 0a 21 a3 7e 70 0d b0 f3 9d 13 |d.4b...!.~p.....|
+000003c0 5c 81 58 24 97 a9 fb 1d 99 60 a7 16 03 03 00 04 |\.X$.....`......|
+000003d0 0e 00 00 00 |....|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 46 10 00 00 42 41 04 28 02 84 d5 b4 |....F...BA.(....|
-00000010 58 07 47 d5 a0 d6 0b 1d 37 91 e6 34 a4 ad 0b ad |X.G.....7..4....|
-00000020 22 01 82 77 a7 32 86 78 83 3a da 75 2f e5 68 7a |"..w.2.x.:.u/.hz|
-00000030 de e4 05 e0 02 47 40 4e 38 d2 2c c3 7b da 53 73 |.....G@N8.,.{.Ss|
-00000040 19 cb 8b 73 34 72 4d 33 71 39 c8 14 03 03 00 01 |...s4rM3q9......|
-00000050 01 16 03 03 00 40 10 63 43 76 83 bd 36 e4 1e 4d |.....@.cCv..6..M|
-00000060 7e 13 b0 ac aa c8 ec 90 31 df 84 46 49 68 39 5a |~.......1..FIh9Z|
-00000070 05 8b 73 32 86 15 3a 18 57 d8 e2 2c 2d 05 89 93 |..s2..:.W..,-...|
-00000080 37 b8 dd 73 33 92 ff a7 b2 53 27 94 b7 25 56 64 |7..s3....S'..%Vd|
-00000090 a1 d3 2c f7 6b 71 |..,.kq|
+00000000 16 03 03 00 46 10 00 00 42 41 04 27 9e 27 b7 bf |....F...BA.'.'..|
+00000010 b1 a9 b0 5b 7d 1c 9a 02 51 6e 03 ba 60 5a a2 50 |...[}...Qn..`Z.P|
+00000020 17 a6 2a e4 02 cd 6f ed a2 97 49 49 0c 36 70 53 |..*...o...II.6pS|
+00000030 ce 0c 79 49 14 55 9a 7f a6 0a 10 65 4f e4 c6 10 |..yI.U.....eO...|
+00000040 c2 31 68 5c 0e 5c ab 8a a8 1c 52 14 03 03 00 01 |.1h\.\....R.....|
+00000050 01 16 03 03 00 40 25 59 40 9e 5b 9a d5 95 a1 59 |.....@%Y@.[....Y|
+00000060 d4 1d ea 0c 02 d1 66 29 c2 d5 d4 24 7a c7 9e 47 |......f)...$z..G|
+00000070 f7 79 a1 5f 72 fb c8 10 61 81 e8 e3 fb 16 7e 30 |.y._r...a.....~0|
+00000080 e2 cc 95 d2 24 2a 0f 94 96 b6 0a 27 1a 87 c9 36 |....$*.....'...6|
+00000090 c7 b4 e9 21 d1 94 |...!..|
>>> Flow 4 (server to client)
00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....|
-00000010 00 00 00 00 00 00 00 00 00 00 00 21 5c 31 b1 4b |...........!\1.K|
-00000020 96 96 30 8f 79 35 3a 3a 2d 26 67 d0 70 48 be 30 |..0.y5::-&g.pH.0|
-00000030 f8 3e e8 c1 cb 1d d5 89 f6 9c 72 bb 1c f9 4d 90 |.>........r...M.|
-00000040 9c d7 c6 fa 40 76 a5 61 46 61 24 17 03 03 00 40 |....@v.aFa$....@|
+00000010 00 00 00 00 00 00 00 00 00 00 00 fe 1d f1 25 18 |..............%.|
+00000020 dd 7a 1e 10 f0 86 7f 75 74 44 a5 89 92 c8 21 ff |.z.....utD....!.|
+00000030 b8 1b bf 79 3f 19 8e 12 04 65 58 a7 e5 96 52 3a |...y?....eX...R:|
+00000040 15 af 57 d8 9e 46 6f 3f 0d 89 67 17 03 03 00 40 |..W..Fo?..g....@|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000060 94 8a 14 04 06 b9 30 a0 67 fd b2 4c 84 f4 10 93 |......0.g..L....|
-00000070 7d d4 2b 23 f0 e9 62 93 c2 20 a2 f2 7c 07 21 4b |}.+#..b.. ..|.!K|
-00000080 94 ba 7b 7d cb 77 da 85 93 bd 53 ee ca db 9b 3e |..{}.w....S....>|
+00000060 1b fb 13 e3 c0 eb 94 bb 4f e1 9e 47 6a ce 9b 6c |........O..Gj..l|
+00000070 03 2f bf 0b 2f 08 36 48 b2 00 26 ab fb cc 3c 2f |./../.6H..&...</|
+00000080 8d 99 82 86 a1 b7 15 04 f0 59 97 d7 50 61 1c a1 |.........Y..Pa..|
00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
-000000a0 00 00 00 00 00 17 3f 53 8d b3 35 b4 84 ed bb 12 |......?S..5.....|
-000000b0 cf 73 25 25 7c c3 d3 bb 1f 5a 6b 73 9a 8a b1 a2 |.s%%|....Zks....|
-000000c0 ba 99 f8 0e 43 |....C|
+000000a0 00 00 00 00 00 95 ed 23 80 9e f5 f2 37 ac 2d 50 |.......#....7.-P|
+000000b0 3d 30 de 68 be 25 c0 72 cc c9 2d 80 41 82 f7 0e |=0.h.%.r..-.A...|
+000000c0 2e 86 0e 07 41 |....A|
>>> Flow 1 (client to server)
-00000000 16 03 01 00 9c 01 00 00 98 03 03 53 04 f0 f9 09 |...........S....|
-00000010 13 56 01 37 84 b1 32 59 4c 73 b1 8e bb 02 1a 32 |.V.7..2YLs.....2|
-00000020 db ab 8c e6 ed ad 7f 52 9a 59 39 00 00 04 c0 0a |.......R.Y9.....|
-00000030 00 ff 01 00 00 6b 00 0b 00 04 03 00 01 02 00 0a |.....k..........|
-00000040 00 34 00 32 00 0e 00 0d 00 19 00 0b 00 0c 00 18 |.4.2............|
-00000050 00 09 00 0a 00 16 00 17 00 08 00 06 00 07 00 14 |................|
-00000060 00 15 00 04 00 05 00 12 00 13 00 01 00 02 00 03 |................|
-00000070 00 0f 00 10 00 11 00 0d 00 22 00 20 06 01 06 02 |.........". ....|
-00000080 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................|
-00000090 03 02 03 03 02 01 02 02 02 03 01 01 00 0f 00 01 |................|
-000000a0 01 |.|
+00000000 16 03 01 00 a1 01 00 00 9d 03 03 eb 02 58 55 90 |.............XU.|
+00000010 a0 ba 80 52 28 a5 36 35 ee 6d eb e1 b0 d3 5d 89 |...R(.65.m....].|
+00000020 e8 2d a3 5e b1 83 e8 2f 00 f2 1e 00 00 04 c0 0a |.-.^.../........|
+00000030 00 ff 02 01 00 00 6f 00 0b 00 04 03 00 01 02 00 |......o.........|
+00000040 0a 00 3a 00 38 00 0e 00 0d 00 19 00 1c 00 0b 00 |..:.8...........|
+00000050 0c 00 1b 00 18 00 09 00 0a 00 1a 00 16 00 17 00 |................|
+00000060 08 00 06 00 07 00 14 00 15 00 04 00 05 00 12 00 |................|
+00000070 13 00 01 00 02 00 03 00 0f 00 10 00 11 00 0d 00 |................|
+00000080 20 00 1e 06 01 06 02 06 03 05 01 05 02 05 03 04 | ...............|
+00000090 01 04 02 04 03 03 01 03 02 03 03 02 01 02 02 02 |................|
+000000a0 03 00 0f 00 01 01 |......|
>>> Flow 2 (server to client)
00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000210 0e bd 3f a3 8c 25 c1 33 13 83 0d 94 06 bb d4 37 |..?..%.3.......7|
00000220 7a f6 ec 7a c9 86 2e dd d7 11 69 7f 85 7c 56 de |z..z......i..|V.|
00000230 fb 31 78 2b e4 c7 78 0d ae cb be 9e 4e 36 24 31 |.1x+..x.....N6$1|
-00000240 7b 6a 0f 39 95 12 07 8f 2a 16 03 03 00 d8 0c 00 |{j.9....*.......|
-00000250 00 d4 03 00 17 41 04 1e 18 37 ef 0d 19 51 88 35 |.....A...7...Q.5|
+00000240 7b 6a 0f 39 95 12 07 8f 2a 16 03 03 00 d7 0c 00 |{j.9....*.......|
+00000250 00 d3 03 00 17 41 04 1e 18 37 ef 0d 19 51 88 35 |.....A...7...Q.5|
00000260 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 24 20 3e |uq..T[....g..$ >|
00000270 b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 07 9f 6c |.V...(^.+-O....l|
00000280 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 b5 68 1a |K[.V.2B.X..I..h.|
-00000290 41 03 56 6b dc 5a 89 04 03 00 8b 30 81 88 02 42 |A.Vk.Z.....0...B|
-000002a0 00 c6 85 8e 06 b7 04 04 e9 cd 9e 3e cb 66 23 95 |...........>.f#.|
-000002b0 b4 42 9c 64 81 39 05 3f b5 21 f8 28 af 60 6b 4d |.B.d.9.?.!.(.`kM|
-000002c0 3d ba a1 4b 5e 77 ef e7 59 28 fe 1d c1 27 a2 ff |=..K^w..Y(...'..|
-000002d0 a8 de 33 48 b3 c1 85 6a 42 9b f9 7e 7e 31 c2 e5 |..3H...jB..~~1..|
-000002e0 bd 66 02 42 00 ad 7d 06 35 ab ec 8d ac d4 ba 1b |.f.B..}.5.......|
-000002f0 49 5e 05 5f f0 97 93 82 b8 2b 8d 91 98 63 8e b4 |I^._.....+...c..|
-00000300 14 62 db 1e c9 2c 13 ae b7 d3 17 38 23 2f f6 7f |.b...,.....8#/..|
-00000310 0c 4d d3 33 d2 79 d1 77 ee cb b1 c2 fc 34 b8 69 |.M.3.y.w.....4.i|
-00000320 f9 10 8b 61 89 85 16 03 03 00 04 0e 00 00 00 |...a...........|
+00000290 41 03 56 6b dc 5a 89 04 03 00 8a 30 81 87 02 41 |A.Vk.Z.....0...A|
+000002a0 68 cb cd c0 12 5e 1e b3 cc d9 47 e7 b5 11 5e be |h....^....G...^.|
+000002b0 74 5b 90 93 3f 4c 07 20 a1 94 50 bb 23 82 fc 5b |t[..?L. ..P.#..[|
+000002c0 78 87 a3 a1 fe 7c 6f 84 93 8f b8 f7 2e 56 65 85 |x....|o......Ve.|
+000002d0 1d 9e 8e 52 b0 89 b0 a7 66 58 98 55 30 64 94 91 |...R....fX.U0d..|
+000002e0 8e 02 42 01 3d 74 eb a4 64 9e 7c 8b 05 57 5c f7 |..B.=t..d.|..W\.|
+000002f0 fe a7 58 f4 21 7b 75 ea 51 1e 1c be 80 4e 00 d1 |..X.!{u.Q....N..|
+00000300 06 80 58 90 c2 f3 47 da 22 8b a2 6b f0 2e 34 d0 |..X...G."..k..4.|
+00000310 1a 84 54 87 62 96 b9 2c 91 9f 3f 93 24 df 6c a3 |..T.b..,..?.$.l.|
+00000320 77 1f d2 e4 30 16 03 03 00 04 0e 00 00 00 |w...0.........|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 46 10 00 00 42 41 04 dd 22 68 a1 4e |....F...BA.."h.N|
-00000010 04 1b 47 f9 c5 7d 04 1d d8 fe 84 fa be 31 2e a7 |..G..}.......1..|
-00000020 f8 e5 b8 14 92 44 99 11 0e 34 97 fc e5 b1 91 cf |.....D...4......|
-00000030 a4 d1 3f b4 71 94 c6 06 16 f0 98 c0 3e 05 f9 2f |..?.q.......>../|
-00000040 0a 97 78 3d ef dc fa a2 d7 ee 7d 14 03 03 00 01 |..x=......}.....|
-00000050 01 16 03 03 00 40 90 bf 7f e9 c9 6e d1 80 f5 12 |.....@.....n....|
-00000060 6d c5 b7 c5 15 4b 18 a5 d3 18 1e f8 8c 4d 7e 6d |m....K.......M~m|
-00000070 03 60 29 7c 45 7c b2 ca 8c 07 71 70 aa 23 fa 6e |.`)|E|....qp.#.n|
-00000080 d9 0b 0a 32 4c 9e e5 00 f9 19 9b b6 8d dc d3 67 |...2L..........g|
-00000090 3d 0f bb b8 4b 9e |=...K.|
+00000000 16 03 03 00 46 10 00 00 42 41 04 04 12 72 83 8c |....F...BA...r..|
+00000010 55 75 c4 34 48 5d d4 e3 9a 34 54 46 83 2f 69 36 |Uu.4H]...4TF./i6|
+00000020 e2 98 65 4d d2 b3 d4 6e 35 93 42 80 02 bd 26 a4 |..eM...n5.B...&.|
+00000030 ca 53 8d 50 c8 78 ec e3 0d 68 31 12 11 fe 76 52 |.S.P.x...h1...vR|
+00000040 0d 2f 63 76 43 74 5b 55 bd 9a 01 14 03 03 00 01 |./cvCt[U........|
+00000050 01 16 03 03 00 40 5f b8 b6 b9 cd 93 37 67 53 6f |.....@_.....7gSo|
+00000060 cd 2d c6 c2 92 28 d6 ab b7 31 ab 75 99 c8 83 7d |.-...(...1.u...}|
+00000070 99 69 03 2d 52 6f ae 06 ec 34 05 fc 3b dd d0 0b |.i.-Ro...4..;...|
+00000080 22 4a 84 cd 86 6c 11 10 3d 0d 9c 0f c8 c9 24 a6 |"J...l..=.....$.|
+00000090 f3 e6 e7 87 31 13 |....1.|
>>> Flow 4 (server to client)
00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....|
-00000010 00 00 00 00 00 00 00 00 00 00 00 a1 6e e5 d1 ca |............n...|
-00000020 03 f4 77 dc ec ee 5d f0 22 5e 7f 55 1a 8d ad 45 |..w...]."^.U...E|
-00000030 09 f1 3b b2 61 36 dc 3d 2a 1e 1f e5 a7 84 76 a9 |..;.a6.=*.....v.|
-00000040 41 5b 86 03 ac 22 18 20 9b a9 29 17 03 03 00 40 |A[...". ..)....@|
+00000010 00 00 00 00 00 00 00 00 00 00 00 a9 71 da 7a 3d |............q.z=|
+00000020 c1 17 da fa 05 ac ed a6 79 79 31 67 83 de 86 92 |........yy1g....|
+00000030 de 7e 6f 5c dc d7 e8 29 df 51 15 a1 6f 38 84 a5 |.~o\...).Q..o8..|
+00000040 a6 e4 f2 56 8a cc bf ad f4 b8 0c 17 03 03 00 40 |...V...........@|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000060 f5 cb 28 1e b5 bc 82 7f 82 38 54 14 e8 b9 6d 3b |..(......8T...m;|
-00000070 bc 99 d6 0e f9 00 96 99 a8 92 2e 86 9d 62 4e 90 |.............bN.|
-00000080 27 52 58 45 20 93 90 a1 f3 a8 89 2b e7 21 24 16 |'RXE ......+.!$.|
+00000060 b1 a6 a1 eb f4 26 ef e9 25 7d c8 b5 a5 4b dc c8 |.....&..%}...K..|
+00000070 32 58 d6 c3 94 e7 f7 20 10 9e a1 db 10 db e4 42 |2X..... .......B|
+00000080 3c c5 26 e7 70 f2 d7 f0 38 10 a7 63 61 22 1b 57 |<.&.p...8..ca".W|
00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
-000000a0 00 00 00 00 00 a8 2a ab 8f b0 ce 49 8b fd a5 c9 |......*....I....|
-000000b0 11 b2 04 83 18 f3 1d 6c 82 34 1d df dd 2f 45 3b |.......l.4.../E;|
-000000c0 27 8a 0f 16 69 |'...i|
+000000a0 00 00 00 00 00 29 ea 96 ea 08 88 6c 5d 67 91 f7 |.....).....l]g..|
+000000b0 31 8e b8 3a 9a d5 87 2a 81 2f 80 fb 7f b5 80 03 |1..:...*./......|
+000000c0 9c 8b 7e 39 7b |..~9{|
--- /dev/null
+>>> Flow 1 (client to server)
+00000000 16 03 01 00 9a 01 00 00 96 03 03 37 7c 30 6d df |...........7|0m.|
+00000010 4d 94 90 04 59 df ec 01 11 77 29 b6 4f 95 50 ef |M...Y....w).O.P.|
+00000020 ca d0 0f f4 a6 35 98 3b ee 16 72 00 00 04 c0 30 |.....5.;..r....0|
+00000030 00 ff 01 00 00 69 00 0b 00 04 03 00 01 02 00 0a |.....i..........|
+00000040 00 34 00 32 00 0e 00 0d 00 19 00 0b 00 0c 00 18 |.4.2............|
+00000050 00 09 00 0a 00 16 00 17 00 08 00 06 00 07 00 14 |................|
+00000060 00 15 00 04 00 05 00 12 00 13 00 01 00 02 00 03 |................|
+00000070 00 0f 00 10 00 11 00 0d 00 20 00 1e 06 01 06 02 |......... ......|
+00000080 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................|
+00000090 03 02 03 03 02 01 02 02 02 03 00 0f 00 01 01 |...............|
+>>> Flow 2 (server to client)
+00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 c0 30 00 00 |.............0..|
+00000030 05 ff 01 00 01 00 16 03 03 02 be 0b 00 02 ba 00 |................|
+00000040 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......|
+00000050 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..|
+00000060 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.|
+00000070 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..|
+00000080 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State|
+00000090 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter|
+000000a0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty |
+000000b0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090|
+000000c0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909|
+000000d0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....|
+000000e0 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som|
+000000f0 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..|
+00000100 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi|
+00000110 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..|
+00000120 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............|
+00000130 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F|
+00000140 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC|
+00000150 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....|
+00000160 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z|
+00000170 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......|
+00000180 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....|
+00000190 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.||
+000001a0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...|
+000001b0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0|
+000001c0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........|
+000001d0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...|
+000001e0 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....|
+000001f0 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..|
+00000200 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.|
+00000210 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....|
+00000220 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...|
+00000230 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi|
+00000240 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...|
+00000250 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...|
+00000260 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...|
+00000270 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.|
+00000280 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z|
+00000290 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`|
+000002a0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.|
+000002b0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.|
+000002c0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.|
+000002d0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....|
+000002e0 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&|
+000002f0 6e 38 50 29 6c 90 a7 bd d9 16 03 03 00 cd 0c 00 |n8P)l...........|
+00000300 00 c9 03 00 17 41 04 1e 18 37 ef 0d 19 51 88 35 |.....A...7...Q.5|
+00000310 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 24 20 3e |uq..T[....g..$ >|
+00000320 b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 07 9f 6c |.V...(^.+-O....l|
+00000330 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 b5 68 1a |K[.V.2B.X..I..h.|
+00000340 41 03 56 6b dc 5a 89 04 01 00 80 4f 66 0e d5 7f |A.Vk.Z.....Of...|
+00000350 a8 99 4d dc 5b a7 b0 32 67 b2 8a 2e ca 90 58 f0 |..M.[..2g.....X.|
+00000360 8d f1 fd 74 c1 3c 84 28 9d 25 7e 0a 61 f8 90 2d |...t.<.(.%~.a..-|
+00000370 99 f3 90 c9 26 ab a7 d2 38 87 e1 2b 12 6e 93 17 |....&...8..+.n..|
+00000380 3c 2f 11 8c d8 67 73 11 68 b9 d0 a7 ad 44 83 72 |</...gs.h....D.r|
+00000390 fc e4 6b ce 7f 02 7e 33 89 4b f3 dc 30 42 c0 4b |..k...~3.K..0B.K|
+000003a0 2b 29 eb e6 1c 43 bb a7 27 b9 3e f4 76 ec 69 4d |+)...C..'.>.v.iM|
+000003b0 df 49 d4 f6 b4 ac f6 0b 1d d1 68 61 30 b1 52 07 |.I........ha0.R.|
+000003c0 a5 6d 31 5e 13 24 8c 32 cd 76 57 16 03 03 00 04 |.m1^.$.2.vW.....|
+000003d0 0e 00 00 00 |....|
+>>> Flow 3 (client to server)
+00000000 16 03 03 00 46 10 00 00 42 41 04 08 73 d7 79 87 |....F...BA..s.y.|
+00000010 39 45 dd 69 33 71 a0 48 a0 8b 6e 2f 99 dc a1 4f |9E.i3q.H..n/...O|
+00000020 21 ca 70 b3 98 fe cc 5a 94 04 1b 8d 4d a4 46 24 |!.p....Z....M.F$|
+00000030 c6 61 bd e1 49 92 83 8d ea 22 fb b1 43 90 24 7e |.a..I...."..C.$~|
+00000040 d0 e5 4b cb c3 8a 41 f7 fd d1 9f 14 03 03 00 01 |..K...A.........|
+00000050 01 16 03 03 00 28 e3 99 f0 d3 65 4e 29 dd d6 eb |.....(....eN)...|
+00000060 c0 b3 f9 e2 8b bb 68 61 b2 7f 63 db de fb ae d2 |......ha..c.....|
+00000070 94 b7 45 9b 34 cb a4 26 3f 04 92 34 02 89 |..E.4..&?..4..|
+>>> Flow 4 (server to client)
+00000000 14 03 03 00 01 01 16 03 03 00 28 00 00 00 00 00 |..........(.....|
+00000010 00 00 00 5e 63 30 5d 4d 2b 87 3f 7b 9c 06 2e 44 |...^c0]M+.?{...D|
+00000020 92 c5 d0 e8 07 fa 9f db a7 2c dc ec 16 78 bd 37 |.........,...x.7|
+00000030 8a f7 24 17 03 03 00 25 00 00 00 00 00 00 00 01 |..$....%........|
+00000040 0b af 29 75 f0 67 6b 78 8c 3a 65 44 53 25 9e d5 |..)u.gkx.:eDS%..|
+00000050 8e 7e 24 5f c9 95 a1 3e 63 d2 52 09 32 15 03 03 |.~$_...>c.R.2...|
+00000060 00 1a 00 00 00 00 00 00 00 02 0b f2 f7 93 57 b3 |..............W.|
+00000070 5b 19 fd e7 a1 0f e9 41 ca f5 74 17 |[......A..t.|
}
// Name represents an X.509 distinguished name. This only includes the common
-// elements of a DN. Additional elements in the name are ignored.
+// elements of a DN. When parsing, all elements are stored in Names and
+// non-standard elements can be extracted from there. When marshaling, elements
+// in ExtraNames are appended and override other values with the same OID.
type Name struct {
Country, Organization, OrganizationalUnit []string
Locality, Province []string
StreetAddress, PostalCode []string
SerialNumber, CommonName string
- Names []AttributeTypeAndValue
+ Names []AttributeTypeAndValue
+ ExtraNames []AttributeTypeAndValue
}
func (n *Name) FillFromRDNSequence(rdns *RDNSequence) {
// and returns the new value. The relativeDistinguishedNameSET contains an
// attributeTypeAndValue for each of the given values. See RFC 5280, A.1, and
// search for AttributeTypeAndValue.
-func appendRDNs(in RDNSequence, values []string, oid asn1.ObjectIdentifier) RDNSequence {
- if len(values) == 0 {
+func (n Name) appendRDNs(in RDNSequence, values []string, oid asn1.ObjectIdentifier) RDNSequence {
+ if len(values) == 0 || oidInAttributeTypeAndValue(oid, n.ExtraNames) {
return in
}
}
func (n Name) ToRDNSequence() (ret RDNSequence) {
- ret = appendRDNs(ret, n.Country, oidCountry)
- ret = appendRDNs(ret, n.Organization, oidOrganization)
- ret = appendRDNs(ret, n.OrganizationalUnit, oidOrganizationalUnit)
- ret = appendRDNs(ret, n.Locality, oidLocality)
- ret = appendRDNs(ret, n.Province, oidProvince)
- ret = appendRDNs(ret, n.StreetAddress, oidStreetAddress)
- ret = appendRDNs(ret, n.PostalCode, oidPostalCode)
+ ret = n.appendRDNs(ret, n.Country, oidCountry)
+ ret = n.appendRDNs(ret, n.Organization, oidOrganization)
+ ret = n.appendRDNs(ret, n.OrganizationalUnit, oidOrganizationalUnit)
+ ret = n.appendRDNs(ret, n.Locality, oidLocality)
+ ret = n.appendRDNs(ret, n.Province, oidProvince)
+ ret = n.appendRDNs(ret, n.StreetAddress, oidStreetAddress)
+ ret = n.appendRDNs(ret, n.PostalCode, oidPostalCode)
if len(n.CommonName) > 0 {
- ret = appendRDNs(ret, []string{n.CommonName}, oidCommonName)
+ ret = n.appendRDNs(ret, []string{n.CommonName}, oidCommonName)
}
if len(n.SerialNumber) > 0 {
- ret = appendRDNs(ret, []string{n.SerialNumber}, oidSerialNumber)
+ ret = n.appendRDNs(ret, []string{n.SerialNumber}, oidSerialNumber)
+ }
+ for _, atv := range n.ExtraNames {
+ ret = append(ret, []AttributeTypeAndValue{atv})
}
return ret
}
+// oidInAttributeTypeAndValue returns whether a type with the given OID exists
+// in atv.
+func oidInAttributeTypeAndValue(oid asn1.ObjectIdentifier, atv []AttributeTypeAndValue) bool {
+ for _, a := range atv {
+ if a.Type.Equal(oid) {
+ return true
+ }
+ }
+ return false
+}
+
// CertificateList represents the ASN.1 structure of the same name. See RFC
// 5280, section 5.1. Use Certificate.CheckCRLSignature to verify the
// signature.
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rsa"
- "crypto/sha1"
+ _ "crypto/sha1"
_ "crypto/sha256"
_ "crypto/sha512"
"crypto/x509/pkix"
return asn1.Marshal(cert.Subject.ToRDNSequence())
}
-// signingParamsForPrivateKey returns the parameters to use for signing with
+// signingParamsForPublicKey returns the parameters to use for signing with
// priv. If requestedSigAlgo is not zero then it overrides the default
// signature algorithm.
-func signingParamsForPrivateKey(priv interface{}, requestedSigAlgo SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) {
+func signingParamsForPublicKey(pub interface{}, requestedSigAlgo SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) {
var pubType PublicKeyAlgorithm
- switch priv := priv.(type) {
- case *rsa.PrivateKey:
+ switch pub := pub.(type) {
+ case *rsa.PublicKey:
pubType = RSA
hashFunc = crypto.SHA256
sigAlgo.Algorithm = oidSignatureSHA256WithRSA
Tag: 5,
}
- case *ecdsa.PrivateKey:
+ case *ecdsa.PublicKey:
pubType = ECDSA
- switch priv.Curve {
+ switch pub.Curve {
case elliptic.P224(), elliptic.P256():
hashFunc = crypto.SHA256
sigAlgo.Algorithm = oidSignatureECDSAWithSHA256
}
default:
- err = errors.New("x509: only RSA and ECDSA private keys supported")
+ err = errors.New("x509: only RSA and ECDSA keys supported")
}
if err != nil {
//
// The returned slice is the certificate in DER encoding.
//
-// The only supported key types are RSA and ECDSA (*rsa.PublicKey or
-// *ecdsa.PublicKey for pub, *rsa.PrivateKey or *ecdsa.PrivateKey for priv).
-func CreateCertificate(rand io.Reader, template, parent *Certificate, pub interface{}, priv interface{}) (cert []byte, err error) {
- hashFunc, signatureAlgorithm, err := signingParamsForPrivateKey(priv, template.SignatureAlgorithm)
- if err != nil {
- return nil, err
+// All keys types that are implemented via crypto.Signer are supported (This
+// includes *rsa.PublicKey and *ecdsa.PublicKey.)
+func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv interface{}) (cert []byte, err error) {
+ key, ok := priv.(crypto.Signer)
+ if !ok {
+ return nil, errors.New("x509: certificate private key does not implement crypto.Signer")
}
- publicKeyBytes, publicKeyAlgorithm, err := marshalPublicKey(pub)
+ hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(key.Public(), template.SignatureAlgorithm)
if err != nil {
return nil, err
}
+ publicKeyBytes, publicKeyAlgorithm, err := marshalPublicKey(pub)
if err != nil {
- return
+ return nil, err
}
if len(parent.SubjectKeyId) > 0 {
digest := h.Sum(nil)
var signature []byte
-
- switch priv := priv.(type) {
- case *rsa.PrivateKey:
- signature, err = rsa.SignPKCS1v15(rand, priv, hashFunc, digest)
- case *ecdsa.PrivateKey:
- var r, s *big.Int
- if r, s, err = ecdsa.Sign(rand, priv, digest); err == nil {
- signature, err = asn1.Marshal(ecdsaSignature{r, s})
- }
- default:
- panic("internal error")
- }
-
+ signature, err = key.Sign(rand, digest, hashFunc)
if err != nil {
return
}
- cert, err = asn1.Marshal(certificate{
+ return asn1.Marshal(certificate{
nil,
c,
signatureAlgorithm,
asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
})
- return
}
// pemCRLPrefix is the magic string that indicates that we have a PEM encoded
// CreateCRL returns a DER encoded CRL, signed by this Certificate, that
// contains the given list of revoked certificates.
-//
-// The only supported key type is RSA (*rsa.PrivateKey for priv).
func (c *Certificate) CreateCRL(rand io.Reader, priv interface{}, revokedCerts []pkix.RevokedCertificate, now, expiry time.Time) (crlBytes []byte, err error) {
- rsaPriv, ok := priv.(*rsa.PrivateKey)
+ key, ok := priv.(crypto.Signer)
if !ok {
- return nil, errors.New("x509: non-RSA private keys not supported")
+ return nil, errors.New("x509: certificate private key does not implement crypto.Signer")
}
+
+ hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(key.Public(), 0)
+ if err != nil {
+ return nil, err
+ }
+
tbsCertList := pkix.TBSCertificateList{
- Version: 1,
- Signature: pkix.AlgorithmIdentifier{
- Algorithm: oidSignatureSHA1WithRSA,
- },
+ Version: 1,
+ Signature: signatureAlgorithm,
Issuer: c.Subject.ToRDNSequence(),
ThisUpdate: now.UTC(),
NextUpdate: expiry.UTC(),
RevokedCertificates: revokedCerts,
}
+ // Authority Key Id
+ if len(c.SubjectKeyId) > 0 {
+ var aki pkix.Extension
+ aki.Id = oidExtensionAuthorityKeyId
+ aki.Value, err = asn1.Marshal(authKeyId{Id: c.SubjectKeyId})
+ if err != nil {
+ return
+ }
+ tbsCertList.Extensions = append(tbsCertList.Extensions, aki)
+ }
+
tbsCertListContents, err := asn1.Marshal(tbsCertList)
if err != nil {
return
}
- h := sha1.New()
+ h := hashFunc.New()
h.Write(tbsCertListContents)
digest := h.Sum(nil)
- signature, err := rsa.SignPKCS1v15(rand, rsaPriv, crypto.SHA1, digest)
+ var signature []byte
+ signature, err = key.Sign(rand, digest, hashFunc)
if err != nil {
return
}
return asn1.Marshal(pkix.CertificateList{
- TBSCertList: tbsCertList,
- SignatureAlgorithm: pkix.AlgorithmIdentifier{
- Algorithm: oidSignatureSHA1WithRSA,
- },
- SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
+ TBSCertList: tbsCertList,
+ SignatureAlgorithm: signatureAlgorithm,
+ SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
})
}
//
// The returned slice is the certificate request in DER encoding.
//
-// The only supported key types are RSA (*rsa.PrivateKey) and ECDSA
-// (*ecdsa.PrivateKey).
+// All keys types that are implemented via crypto.Signer are supported (This
+// includes *rsa.PublicKey and *ecdsa.PublicKey.)
func CreateCertificateRequest(rand io.Reader, template *CertificateRequest, priv interface{}) (csr []byte, err error) {
- hashFunc, sigAlgo, err := signingParamsForPrivateKey(priv, template.SignatureAlgorithm)
+ key, ok := priv.(crypto.Signer)
+ if !ok {
+ return nil, errors.New("x509: certificate private key does not implement crypto.Signer")
+ }
+
+ var hashFunc crypto.Hash
+ var sigAlgo pkix.AlgorithmIdentifier
+ hashFunc, sigAlgo, err = signingParamsForPublicKey(key.Public(), template.SignatureAlgorithm)
if err != nil {
return nil, err
}
var publicKeyBytes []byte
var publicKeyAlgorithm pkix.AlgorithmIdentifier
-
- switch priv := priv.(type) {
- case *rsa.PrivateKey:
- publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(&priv.PublicKey)
- case *ecdsa.PrivateKey:
- publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(&priv.PublicKey)
- default:
- panic("internal error")
- }
-
+ publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(key.Public())
if err != nil {
return nil, err
}
digest := h.Sum(nil)
var signature []byte
- switch priv := priv.(type) {
- case *rsa.PrivateKey:
- signature, err = rsa.SignPKCS1v15(rand, priv, hashFunc, digest)
- case *ecdsa.PrivateKey:
- var r, s *big.Int
- if r, s, err = ecdsa.Sign(rand, priv, digest); err == nil {
- signature, err = asn1.Marshal(ecdsaSignature{r, s})
- }
- default:
- panic("internal error")
- }
-
+ signature, err = key.Sign(rand, digest, hashFunc)
if err != nil {
return
}
Subject: pkix.Name{
CommonName: commonName,
Organization: []string{"Σ Acme Co"},
+ Country: []string{"US"},
+ ExtraNames: []pkix.AttributeTypeAndValue{
+ {
+ Type: []int{2, 5, 4, 42},
+ Value: "Gopher",
+ },
+ // This should override the Country, above.
+ {
+ Type: []int{2, 5, 4, 6},
+ Value: "NL",
+ },
+ },
},
NotBefore: time.Unix(1000, 0),
NotAfter: time.Unix(100000, 0),
t.Errorf("%s: subject wasn't correctly copied from the template. Got %s, want %s", test.name, cert.Subject.CommonName, commonName)
}
+ if len(cert.Subject.Country) != 1 || cert.Subject.Country[0] != "NL" {
+ t.Errorf("%s: ExtraNames didn't override Country", test.name)
+ }
+
+ found := false
+ for _, atv := range cert.Subject.Names {
+ if atv.Type.Equal([]int{2, 5, 4, 42}) {
+ found = true
+ break
+ }
+ }
+ if !found {
+ t.Errorf("%s: Names didn't contain oid 2.5.4.42 from ExtraNames", test.name)
+ }
+
if cert.Issuer.CommonName != commonName {
t.Errorf("%s: issuer wasn't correctly copied from the template. Got %s, want %s", test.name, cert.Issuer.CommonName, commonName)
}
"runtime"
"sort"
"sync"
+ "sync/atomic"
)
var drivers = make(map[string]driver.Driver)
type DB struct {
driver driver.Driver
dsn string
+ // numClosed is an atomic counter which represents a total number of
+ // closed connections. Stmt.openStmt checks it before cleaning closed
+ // connections in Stmt.css.
+ numClosed uint64
mu sync.Mutex // protects following fields
freeConn []*driverConn
// guarded by db.mu
inUse bool
onPut []func() // code (with db.mu held) run when conn is next returned
- dbmuClosed bool // same as closed, but guarded by db.mu, for connIfFree
+ dbmuClosed bool // same as closed, but guarded by db.mu, for removeClosedStmtLocked
}
func (dc *driverConn) releaseConn(err error) {
dc.db.maybeOpenNewConnections()
dc.db.mu.Unlock()
+ atomic.AddUint64(&dc.db.numClosed, 1)
return err
}
errConnBusy = errors.New("database/sql: internal sentinel error: conn is busy")
)
-// connIfFree returns (wanted, nil) if wanted is still a valid conn and
-// isn't in use.
-//
-// The error is errConnClosed if the connection if the requested connection
-// is invalid because it's been closed.
-//
-// The error is errConnBusy if the connection is in use.
-func (db *DB) connIfFree(wanted *driverConn) (*driverConn, error) {
- db.mu.Lock()
- defer db.mu.Unlock()
- if wanted.dbmuClosed {
- return nil, errConnClosed
- }
- if wanted.inUse {
- return nil, errConnBusy
- }
- idx := -1
- for ii, v := range db.freeConn {
- if v == wanted {
- idx = ii
- break
- }
- }
- if idx >= 0 {
- db.freeConn = append(db.freeConn[:idx], db.freeConn[idx+1:]...)
- wanted.inUse = true
- return wanted, nil
- }
- // TODO(bradfitz): shouldn't get here. After Go 1.1, change this to:
- // panic("connIfFree call requested a non-closed, non-busy, non-free conn")
- // Which passes all the tests, but I'm too paranoid to include this
- // late in Go 1.1.
- // Instead, treat it like a busy connection:
- return nil, errConnBusy
-}
-
// putConnHook is a hook for testing.
var putConnHook func(*DB, *driverConn)
return nil, err
}
stmt := &Stmt{
- db: db,
- query: query,
- css: []connStmt{{dc, si}},
+ db: db,
+ query: query,
+ css: []connStmt{{dc, si}},
+ lastNumClosed: atomic.LoadUint64(&db.numClosed),
}
db.addDep(stmt, stmt)
db.putConn(dc, nil)
// used if tx == nil and one is found that has idle
// connections. If tx != nil, txsi is always used.
css []connStmt
+
+ // lastNumClosed is copied from db.numClosed when Stmt is created
+ // without tx and closed connections in css are removed.
+ lastNumClosed uint64
}
// Exec executes a prepared statement with the given arguments and
return driverResult{ds.Locker, resi}, nil
}
+// removeClosedStmtLocked removes closed conns in s.css.
+//
+// To avoid lock contention on DB.mu, we do it only when
+// s.db.numClosed - s.lastNum is large enough.
+func (s *Stmt) removeClosedStmtLocked() {
+ t := len(s.css)/2 + 1
+ if t > 10 {
+ t = 10
+ }
+ dbClosed := atomic.LoadUint64(&s.db.numClosed)
+ if dbClosed-s.lastNumClosed < uint64(t) {
+ return
+ }
+
+ s.db.mu.Lock()
+ for i := 0; i < len(s.css); i++ {
+ if s.css[i].dc.dbmuClosed {
+ s.css[i] = s.css[len(s.css)-1]
+ s.css = s.css[:len(s.css)-1]
+ i--
+ }
+ }
+ s.db.mu.Unlock()
+ s.lastNumClosed = dbClosed
+}
+
// connStmt returns a free driver connection on which to execute the
// statement, a function to call to release the connection, and a
// statement bound to that connection.
return ci, releaseConn, s.txsi.si, nil
}
- for i := 0; i < len(s.css); i++ {
- v := s.css[i]
- _, err := s.db.connIfFree(v.dc)
- if err == nil {
- s.mu.Unlock()
- return v.dc, v.dc.releaseConn, v.si, nil
- }
- if err == errConnClosed {
- // Lazily remove dead conn from our freelist.
- s.css[i] = s.css[len(s.css)-1]
- s.css = s.css[:len(s.css)-1]
- i--
- }
-
- }
+ s.removeClosedStmtLocked()
s.mu.Unlock()
- // If all connections are busy, either wait for one to become available (if
- // we've already hit the maximum number of open connections) or create a
- // new one.
- //
// TODO(bradfitz): or always wait for one? make configurable later?
dc, err := s.db.conn()
if err != nil {
return nil, nil, nil, err
}
- // Do another pass over the list to see whether this statement has
- // already been prepared on the connection assigned to us.
s.mu.Lock()
for _, v := range s.css {
if v.dc == dc {
wg.Wait()
}
-func manyConcurrentQueries(t testing.TB) {
- maxProcs, numReqs := 16, 500
- if testing.Short() {
- maxProcs, numReqs = 4, 50
- }
- defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs))
-
- db := newTestDB(t, "people")
- defer closeDB(t, db)
-
- stmt, err := db.Prepare("SELECT|people|name|")
- if err != nil {
- t.Fatal(err)
- }
- defer stmt.Close()
-
- var wg sync.WaitGroup
- wg.Add(numReqs)
-
- reqs := make(chan bool)
- defer close(reqs)
-
- for i := 0; i < maxProcs*2; i++ {
- go func() {
- for range reqs {
- rows, err := stmt.Query()
- if err != nil {
- t.Errorf("error on query: %v", err)
- wg.Done()
- continue
- }
-
- var name string
- for rows.Next() {
- rows.Scan(&name)
- }
- rows.Close()
-
- wg.Done()
- }
- }()
- }
-
- for i := 0; i < numReqs; i++ {
- reqs <- true
- }
-
- wg.Wait()
-}
-
func TestIssue6081(t *testing.T) {
db := newTestDB(t, "people")
defer closeDB(t, db)
doConcurrentTest(b, ct)
}
}
+
+func BenchmarkManyConcurrentQueries(b *testing.B) {
+ b.ReportAllocs()
+ // To see lock contention in Go 1.4, 16~ cores and 128~ goroutines are required.
+ const parallelism = 16
+
+ db := newTestDB(b, "magicquery")
+ defer closeDB(b, db)
+ db.SetMaxIdleConns(runtime.GOMAXPROCS(0) * parallelism)
+
+ stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?")
+ if err != nil {
+ b.Fatal(err)
+ }
+ defer stmt.Close()
+
+ b.SetParallelism(parallelism)
+ b.RunParallel(func(pb *testing.PB) {
+ for pb.Next() {
+ rows, err := stmt.Query("sleep", 1)
+ if err != nil {
+ b.Error(err)
+ return
+ }
+ rows.Close()
+ }
+ })
+}
// An UnmarshalTypeError describes a JSON value that was
// not appropriate for a value of a specific Go type.
type UnmarshalTypeError struct {
- Value string // description of JSON value - "bool", "array", "number -5"
- Type reflect.Type // type of Go value it could not be assigned to
+ Value string // description of JSON value - "bool", "array", "number -5"
+ Type reflect.Type // type of Go value it could not be assigned to
+ Offset int64 // error occurred after reading Offset bytes
}
func (e *UnmarshalTypeError) Error() string {
return
}
if ut != nil {
- d.saveError(&UnmarshalTypeError{"array", v.Type()})
+ d.saveError(&UnmarshalTypeError{"array", v.Type(), int64(d.off)})
d.off--
d.next()
return
// Otherwise it's invalid.
fallthrough
default:
- d.saveError(&UnmarshalTypeError{"array", v.Type()})
+ d.saveError(&UnmarshalTypeError{"array", v.Type(), int64(d.off)})
d.off--
d.next()
return
return
}
if ut != nil {
- d.saveError(&UnmarshalTypeError{"object", v.Type()})
+ d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
d.off--
d.next() // skip over { } in input
return
// map must have string kind
t := v.Type()
if t.Key().Kind() != reflect.String {
- d.saveError(&UnmarshalTypeError{"object", v.Type()})
+ d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
d.off--
d.next() // skip over { } in input
return
case reflect.Struct:
default:
- d.saveError(&UnmarshalTypeError{"object", v.Type()})
+ d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
d.off--
d.next() // skip over { } in input
return
}
f, err := strconv.ParseFloat(s, 64)
if err != nil {
- return nil, &UnmarshalTypeError{"number " + s, reflect.TypeOf(0.0)}
+ return nil, &UnmarshalTypeError{"number " + s, reflect.TypeOf(0.0), int64(d.off)}
}
return f, nil
}
if fromQuoted {
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
} else {
- d.saveError(&UnmarshalTypeError{"string", v.Type()})
+ d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
}
}
s, ok := unquoteBytes(item)
if fromQuoted {
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
} else {
- d.saveError(&UnmarshalTypeError{"bool", v.Type()})
+ d.saveError(&UnmarshalTypeError{"bool", v.Type(), int64(d.off)})
}
case reflect.Bool:
v.SetBool(value)
if v.NumMethod() == 0 {
v.Set(reflect.ValueOf(value))
} else {
- d.saveError(&UnmarshalTypeError{"bool", v.Type()})
+ d.saveError(&UnmarshalTypeError{"bool", v.Type(), int64(d.off)})
}
}
}
switch v.Kind() {
default:
- d.saveError(&UnmarshalTypeError{"string", v.Type()})
+ d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
case reflect.Slice:
if v.Type() != byteSliceType {
- d.saveError(&UnmarshalTypeError{"string", v.Type()})
+ d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
break
}
b := make([]byte, base64.StdEncoding.DecodedLen(len(s)))
if v.NumMethod() == 0 {
v.Set(reflect.ValueOf(string(s)))
} else {
- d.saveError(&UnmarshalTypeError{"string", v.Type()})
+ d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
}
}
if fromQuoted {
d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
} else {
- d.error(&UnmarshalTypeError{"number", v.Type()})
+ d.error(&UnmarshalTypeError{"number", v.Type(), int64(d.off)})
}
case reflect.Interface:
n, err := d.convertNumber(s)
break
}
if v.NumMethod() != 0 {
- d.saveError(&UnmarshalTypeError{"number", v.Type()})
+ d.saveError(&UnmarshalTypeError{"number", v.Type(), int64(d.off)})
break
}
v.Set(reflect.ValueOf(n))
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
n, err := strconv.ParseInt(s, 10, 64)
if err != nil || v.OverflowInt(n) {
- d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
+ d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)})
break
}
v.SetInt(n)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
n, err := strconv.ParseUint(s, 10, 64)
if err != nil || v.OverflowUint(n) {
- d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
+ d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)})
break
}
v.SetUint(n)
case reflect.Float32, reflect.Float64:
n, err := strconv.ParseFloat(s, v.Type().Bits())
if err != nil || v.OverflowFloat(n) {
- d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
+ d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)})
break
}
v.SetFloat(n)
{in: `"g-clef: \uD834\uDD1E"`, ptr: new(string), out: "g-clef: \U0001D11E"},
{in: `"invalid: \uD834x\uDD1E"`, ptr: new(string), out: "invalid: \uFFFDx\uFFFD"},
{in: "null", ptr: new(interface{}), out: nil},
- {in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &UnmarshalTypeError{"array", reflect.TypeOf("")}},
+ {in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &UnmarshalTypeError{"array", reflect.TypeOf(""), 7}},
{in: `{"x": 1}`, ptr: new(tx), out: tx{}},
{in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: float64(1), F2: int32(2), F3: Number("3")}},
{in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: Number("1"), F2: int32(2), F3: Number("3")}, useNumber: true},
{
in: `{"2009-11-10T23:00:00Z": "hello world"}`,
ptr: &map[time.Time]string{},
- err: &UnmarshalTypeError{"object", reflect.TypeOf(map[time.Time]string{})},
+ err: &UnmarshalTypeError{"object", reflect.TypeOf(map[time.Time]string{}), 1},
},
}
"sort"
"strconv"
"sync"
+ "sync/atomic"
)
// Var is an abstract type for all exported variables.
// Int is a 64-bit integer variable that satisfies the Var interface.
type Int struct {
- mu sync.RWMutex
- i int64
+ i int64
}
func (v *Int) String() string {
- v.mu.RLock()
- defer v.mu.RUnlock()
- return strconv.FormatInt(v.i, 10)
+ return strconv.FormatInt(atomic.LoadInt64(&v.i), 10)
}
func (v *Int) Add(delta int64) {
- v.mu.Lock()
- defer v.mu.Unlock()
- v.i += delta
+ atomic.AddInt64(&v.i, delta)
}
func (v *Int) Set(value int64) {
- v.mu.Lock()
- defer v.mu.Unlock()
- v.i = value
+ atomic.StoreInt64(&v.i, value)
}
// Float is a 64-bit float variable that satisfies the Var interface.
}
}
+func BenchmarkFprintfBytes(b *testing.B) {
+ data := []byte(string("0123456789"))
+ var buf bytes.Buffer
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ Fprintf(&buf, "%s", data)
+ }
+}
+
func BenchmarkFprintIntNoAlloc(b *testing.B) {
var x interface{} = 123456
var buf bytes.Buffer
// names from top-level declarations (including struct field and
// interface method names, but not from parameter lists) that don't
// pass through the filter f. If the declaration is empty afterwards,
-// the declaration is removed from the AST. The File.Comments list
-// is not changed.
+// the declaration is removed from the AST. Import declarations are
+// always removed. The File.Comments list is not changed.
//
// FilterFile returns true if there are any top-level declarations
// left after filtering; it returns false otherwise.
)
// filterIdentList removes unexported names from list in place
-// and returns the resulting list. If blankOk is set, blank
-// identifiers are considered exported names.
+// and returns the resulting list.
//
-func filterIdentList(list []*ast.Ident, blankOk bool) []*ast.Ident {
+func filterIdentList(list []*ast.Ident) []*ast.Ident {
j := 0
for _, x := range list {
- if ast.IsExported(x.Name) || (blankOk && x.Name == "_") {
+ if ast.IsExported(x.Name) {
list[j] = x
j++
}
return list[0:j]
}
-// hasExportedOrBlankName reports whether list contains any exported or blank names.
+// hasExportedName reports whether list contains any exported names.
//
-func hasExportedOrBlankName(list []*ast.Ident) bool {
+func hasExportedName(list []*ast.Ident) bool {
for _, x := range list {
- if x.IsExported() || x.Name == "_" {
+ if x.IsExported() {
return true
}
}
r.remember(ityp)
}
} else {
- field.Names = filterIdentList(field.Names, false)
+ field.Names = filterIdentList(field.Names)
if len(field.Names) < n {
removedFields = true
}
// always keep imports so we can collect them
return true
case *ast.ValueSpec:
- // special case: consider blank constants as exported
- // (work-around for issue 5397)
- s.Names = filterIdentList(s.Names, tok == token.CONST)
+ s.Names = filterIdentList(s.Names)
if len(s.Names) > 0 {
r.filterType(nil, s.Type)
return true
// provide current spec with an explicit type
spec.Type = copyConstType(prevType, spec.Pos())
}
- if hasExportedOrBlankName(spec.Names) {
- // both exported and blank names are preserved
- // so there's no need to propagate the type
+ if hasExportedName(spec.Names) {
+ // exported names are preserved so there's no need to propagate the type
prevType = nil
} else {
prevType = spec.Type
// Package constants.
const (
- _ int = iota
- I1
+ I1 int
I2
)
// T constants counting from a blank constant.
const (
- _ T = iota
- T1
+ T1 T
T2
)
WideOpen = 0777
)
+ // Unexported constants counting from blank iota. See issue 9615.
+ const (
+ _ = iota
+ one = iota + 1
+ )
+
VARIABLES
//
// Package constants.
const (
- _ int = iota
- I1
+ I1 int
I2
)
// T constants counting from a blank constant.
const (
- _ T = iota
- T1
+ T1 T
T2
)
I2
)
+// Unexported constants counting from blank iota.
+// See issue 9615.
+const (
+ _ = iota
+ one = iota + 1
+)
+
// Blanks not in doc output:
// S has a padding field.
defer un(trace(p, keyword.String()+"Spec"))
}
+ pos := p.pos
idents := p.parseIdentList()
typ := p.tryType()
var values []ast.Expr
}
p.expectSemi() // call before accessing p.linecomment
+ switch keyword {
+ case token.VAR:
+ if typ == nil && values == nil {
+ p.error(pos, "missing variable type or initialization")
+ }
+ case token.CONST:
+ if values == nil && (iota == 0 || typ != nil) {
+ p.error(pos, "missing constant value")
+ }
+ }
+
// Go spec: The scope of a constant or variable identifier declared inside
// a function begins at the end of the ConstSpec or VarSpec and ends at
// the end of the innermost containing block.
`package p; func _() { map[int]int{}[0]++; map[int]int{}[0] += 1 }`,
`package p; func _(x interface{f()}) { interface{f()}(x).f() }`,
`package p; func _(x chan int) { chan int(x) <- 0 }`,
+ `package p; const (x = 0; y; z)`, // issue 9639
}
func TestValid(t *testing.T) {
`package p; func f() { go f /* ERROR HERE "function must be invoked" */ }`,
`package p; func f() { defer func() {} /* ERROR HERE "function must be invoked" */ }`,
`package p; func f() { go func() { func() { f(x func /* ERROR "expected '\)'" */ (){}) } } }`,
- `package p; func f() (a b string /* ERROR "expected '\)'" */ , ok bool) // issue 8656`,
+ `package p; func f() (a b string /* ERROR "expected '\)'" */ , ok bool)`, // issue 8656
+ `package p; var x /* ERROR "missing variable type or initialization" */ , y, z;`, // issue 9639
+ `package p; const x /* ERROR "missing constant value" */ ;`, // issue 9639
+ `package p; const x /* ERROR "missing constant value" */ int;`, // issue 9639
+ `package p; const (x = 0; y; z /* ERROR "missing constant value" */ int);`, // issue 9639
}
func TestInvalid(t *testing.T) {
"bytes"
"go/ast"
"go/token"
+ "strconv"
+ "strings"
+ "unicode"
"unicode/utf8"
)
}
}
+func sanitizeImportPath(lit *ast.BasicLit) *ast.BasicLit {
+ // Note: An unmodified AST generated by go/parser will already
+ // contain a backward- or double-quoted path string that does
+ // not contain any invalid characters, and most of the work
+ // here is not needed. However, a modified or generated AST
+ // may possibly contain non-canonical paths. Do the work in
+ // all cases since it's not too hard and not speed-critical.
+
+ // if we don't have a proper string, be conservative and return whatever we have
+ if lit.Kind != token.STRING {
+ return lit
+ }
+ s, err := strconv.Unquote(lit.Value)
+ if err != nil {
+ return lit
+ }
+
+ // if the string is an invalid path, return whatever we have
+ //
+ // spec: "Implementation restriction: A compiler may restrict
+ // ImportPaths to non-empty strings using only characters belonging
+ // to Unicode's L, M, N, P, and S general categories (the Graphic
+ // characters without spaces) and may also exclude the characters
+ // !"#$%&'()*,:;<=>?[\]^`{|} and the Unicode replacement character
+ // U+FFFD."
+ if s == "" {
+ return lit
+ }
+ const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD"
+ for _, r := range s {
+ if !unicode.IsGraphic(r) || unicode.IsSpace(r) || strings.ContainsRune(illegalChars, r) {
+ return lit
+ }
+ }
+
+ // otherwise, return the double-quoted path
+ s = strconv.Quote(s)
+ if s == lit.Value {
+ return lit // nothing wrong with lit
+ }
+ return &ast.BasicLit{ValuePos: lit.ValuePos, Kind: token.STRING, Value: s}
+}
+
// The parameter n is the number of specs in the group. If doIndent is set,
// multi-line identifier lists in the spec are indented when the first
// linebreak is encountered.
p.expr(s.Name)
p.print(blank)
}
- p.expr(s.Path)
+ p.expr(sanitizeImportPath(s.Path))
p.setComment(s.Comment)
p.print(s.EndPos)
// Compute maximum common white prefix of all but the first,
// last, and blank lines, and replace blank lines with empty
// lines (the first line starts with /* and has no prefix).
- // In case of two-line comments, consider the last line for
- // the prefix computation since otherwise the prefix would
- // be empty.
+ // In cases where only the first and last lines are not blank,
+ // such as two-line comments, or comments where all inner lines
+ // are blank, consider the last line for the prefix computation
+ // since otherwise the prefix would be empty.
//
// Note that the first and last line are never empty (they
// contain the opening /* and closing */ respectively) and
// thus they can be ignored by the blank line check.
- var prefix string
+ prefix := ""
+ prefixSet := false
if len(lines) > 2 {
- first := true
for i, line := range lines[1 : len(lines)-1] {
- switch {
- case isBlank(line):
+ if isBlank(line) {
lines[1+i] = "" // range starts with lines[1]
- case first:
- prefix = commonPrefix(line, line)
- first = false
- default:
+ } else {
+ if !prefixSet {
+ prefix = line
+ prefixSet = true
+ }
prefix = commonPrefix(prefix, line)
}
+
}
- } else { // len(lines) == 2, lines cannot be blank (contain /* and */)
- line := lines[1]
+ }
+ // If we don't have a prefix yet, consider the last line.
+ if !prefixSet {
+ line := lines[len(lines)-1]
prefix = commonPrefix(line, line)
}
aligned line */
}
+// Issue 9751.
+func _() {
+ /*a string
+
+ b string*/
+
+ /*A string
+
+
+
+ Z string*/
+
+ /*a string
+
+ b string
+
+ c string*/
+
+ {
+ /*a string
+ b string*/
+
+ /*a string
+
+ b string*/
+
+ /*a string
+
+ b string
+
+ c string*/
+ }
+
+ {
+ /*a string
+ b string*/
+
+ /*a string
+
+ b string*/
+
+ /*a string
+
+ b string
+
+ c string*/
+ }
+
+ /*
+ */
+
+ /*
+
+ */
+
+ /*
+
+ * line
+
+ */
+}
+
/*
* line
* of
aligned line */
}
+// Issue 9751.
+func _() {
+ /*a string
+
+ b string*/
+
+ /*A string
+
+
+
+ Z string*/
+
+ /*a string
+
+ b string
+
+ c string*/
+
+ {
+ /*a string
+b string*/
+
+ /*a string
+
+b string*/
+
+ /*a string
+
+b string
+
+c string*/
+ }
+
+ {
+ /*a string
+ b string*/
+
+ /*a string
+
+ b string*/
+
+ /*a string
+
+ b string
+
+ c string*/
+ }
+
+ /*
+ */
+
+ /*
+
+ */
+
+ /*
+
+ * line
+
+ */
+}
+
/*
* line
* of
"package_dddd" // comment
)
+// print import paths as double-quoted strings
+// (we would like more test cases but the go/parser
+// already excludes most incorrect paths, and we don't
+// bother setting up test-ASTs manually)
+import (
+ "fmt"
+ "math"
+)
+
// at least one empty line between declarations of different kind
import _ "io"
"package_dddd" // comment
)
+// print import paths as double-quoted strings
+// (we would like more test cases but the go/parser
+// already excludes most incorrect paths, and we don't
+// bother setting up test-ASTs manually)
+import (
+ `fmt`
+ "math"
+)
+
// at least one empty line between declarations of different kind
import _ "io"
var _ int
can be invoked with
- tmpl.Execute(out, HTML(`<b>World</b>`))
+ tmpl.Execute(out, template.HTML(`<b>World</b>`))
to produce
return &Alpha{pix, 1 * w, r}
}
-// Alpha16 is an in-memory image whose At method returns color.Alpha64 values.
+// Alpha16 is an in-memory image whose At method returns color.Alpha16 values.
type Alpha16 struct {
// Pix holds the image's pixels, as alpha values in big-endian format. The pixel at
// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*2].
)
var randomTrap = map[string]uintptr{
- "386": 355,
- "amd64": 318,
- "arm": 384,
+ "386": 355,
+ "amd64": 318,
+ "arm": 384,
+ "ppc64": 359,
+ "ppc64le": 359,
}[runtime.GOARCH]
var randomUnsupported int32 // atomic
-// +build !plan9
-
/*
Inferno lib9/tokenize.c
http://code.google.com/p/inferno-os/source/browse/lib9/tokenize.c
{
/* struct Optab:
OPCODE, from, prog->reg, to, type,size,param,flag */
- { ATEXT, C_ADDR, C_NONE, C_LCON, 0, 0, 0 },
- { ATEXT, C_ADDR, C_REG, C_LCON, 0, 0, 0 },
+ { ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0 },
{ AADD, C_REG, C_REG, C_REG, 1, 4, 0 },
{ AADD, C_REG, C_NONE, C_REG, 1, 4, 0 },
static Oprang oprange[ALAST];
static uchar xcmp[C_GOK+1][C_GOK+1];
-static Prog zprg = {
- .as = AGOK,
- .scond = C_SCOND_NONE,
- .reg = NREG,
- .from = {
- .name = D_NONE,
- .type = D_NONE,
- .reg = NREG,
- },
- .to = {
- .name = D_NONE,
- .type = D_NONE,
- .reg = NREG,
- },
-};
-
static LSym *deferreturn;
static void
static void buildop(Link*);
+// Note about encoding: Prog.scond holds the condition encoding,
+// but XOR'ed with C_SCOND_XOR, so that C_SCOND_NONE == 0.
+// The code that shifts the value << 28 has the responsibility
+// for XORing with C_SCOND_XOR too.
+
// asmoutnacl assembles the instruction p. It replaces asmout for NaCl.
// It returns the total number of bytes put in out, and it can change
// p->pc if extra padding is necessary.
break;
case AB:
case ABL:
- if(p->to.type != D_OREG) {
+ if(p->to.type != TYPE_MEM) {
if(out != nil)
asmout(ctxt, p, o, out);
} else {
- if(p->to.offset != 0 || size != 4 || p->to.reg >= 16 || p->to.reg < 0)
+ if(p->to.offset != 0 || size != 4 || p->to.reg > REG_R15 || p->to.reg < REG_R0)
ctxt->diag("unsupported instruction: %P", p);
if((p->pc&15) == 12)
p->pc += 4;
if(out != nil) {
- out[0] = ((p->scond&C_SCOND)<<28) | 0x03c0013f | (p->to.reg << 12) | (p->to.reg << 16); // BIC $0xc000000f, Rx
+ out[0] = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | 0x03c0013f | ((p->to.reg&15) << 12) | ((p->to.reg&15) << 16); // BIC $0xc000000f, Rx
if(p->as == AB)
- out[1] = ((p->scond&C_SCOND)<<28) | 0x012fff10 | p->to.reg; // BX Rx
+ out[1] = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | 0x012fff10 | (p->to.reg&15)<<0; // BX Rx
else // ABL
- out[1] = ((p->scond&C_SCOND)<<28) | 0x012fff30 | p->to.reg; // BLX Rx
+ out[1] = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | 0x012fff30 | (p->to.reg&15)<<0; // BLX Rx
}
size = 8;
}
case AMOVW:
case ASTREX:
case ASTREXD:
- if(p->to.type == D_REG && p->to.reg == 15 && p->from.reg == 13) { // MOVW.W x(R13), PC
+ if(p->to.type == TYPE_REG && p->to.reg == REG_R15 && p->from.reg == REG_R13) { // MOVW.W x(R13), PC
if(out != nil)
asmout(ctxt, p, o, out);
if(size == 4) {
// Note: 5c and 5g reg.c know that DIV/MOD smashes R12
// so that this return instruction expansion is valid.
out[0] = out[0] & ~0x3000; // change PC to R12
- out[1] = ((p->scond&C_SCOND)<<28) | 0x03ccc13f; // BIC $0xc000000f, R12
- out[2] = ((p->scond&C_SCOND)<<28) | 0x012fff1c; // BX R12
+ out[1] = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | 0x03ccc13f; // BIC $0xc000000f, R12
+ out[2] = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | 0x012fff1c; // BX R12
}
size += 8;
if(((p->pc+size) & 15) == 4)
// offset to update R13, so we need to additionally mask R13.
if(out != nil) {
out[size/4-1] &= ~0x3000; // change PC to R12
- out[size/4] = ((p->scond&C_SCOND)<<28) | 0x03cdd103; // BIC $0xc0000000, R13
- out[size/4+1] = ((p->scond&C_SCOND)<<28) | 0x03ccc13f; // BIC $0xc000000f, R12
- out[size/4+2] = ((p->scond&C_SCOND)<<28) | 0x012fff1c; // BX R12
+ out[size/4] = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | 0x03cdd103; // BIC $0xc0000000, R13
+ out[size/4+1] = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | 0x03ccc13f; // BIC $0xc000000f, R12
+ out[size/4+2] = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | 0x012fff1c; // BX R12
}
// p->pc+size is only ok at 4 or 12 mod 16.
if((p->pc+size)%8 == 0)
}
}
- if(p->to.type == D_REG && p->to.reg == 15)
+ if(p->to.type == TYPE_REG && p->to.reg == REG_R15)
ctxt->diag("unsupported instruction (move to another register and use indirect jump instead): %P", p);
- if(p->to.type == D_OREG && p->to.reg == 13 && (p->scond & C_WBIT) && size > 4) {
+ if(p->to.type == TYPE_MEM && p->to.reg == REG_R13 && (p->scond & C_WBIT) && size > 4) {
// function prolog with very large frame size: MOVW.W R14,-100004(R13)
// split it into two instructions:
// ADD $-100004, R13
// MOVW R14, 0(R13)
- q = ctxt->arch->prg();
+ q = emallocz(sizeof(Prog));
p->scond &= ~C_WBIT;
*q = *p;
a = &p->to;
- if(p->to.type == D_OREG)
+ if(p->to.type == TYPE_MEM)
a2 = &q->to;
else
a2 = &q->from;
// make p into ADD $X, R13
p->as = AADD;
p->from = *a;
- p->from.reg = NREG;
- p->from.type = D_CONST;
- p->to = zprg.to;
- p->to.type = D_REG;
- p->to.reg = 13;
+ p->from.reg = 0;
+ p->from.type = TYPE_CONST;
+ p->to = zprog.to;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_R13;
// make q into p but load/store from 0(R13)
q->spadj = 0;
- *a2 = zprg.from;
- a2->type = D_OREG;
- a2->reg = 13;
+ *a2 = zprog.from;
+ a2->type = TYPE_MEM;
+ a2->reg = REG_R13;
a2->sym = nil;
a2->offset = 0;
size = oplook(ctxt, p)->size;
break;
}
- if((p->to.type == D_OREG && p->to.reg != 13 && p->to.reg != 9) || // MOVW Rx, X(Ry), y != 13 && y != 9
- (p->from.type == D_OREG && p->from.reg != 13 && p->from.reg != 9)) { // MOVW X(Rx), Ry, x != 13 && x != 9
- if(p->to.type == D_OREG)
+ if((p->to.type == TYPE_MEM && p->to.reg != REG_R13 && p->to.reg != REG_R9) || // MOVW Rx, X(Ry), y != 13 && y != 9
+ (p->from.type == TYPE_MEM && p->from.reg != REG_R13 && p->from.reg != REG_R9)) { // MOVW X(Rx), Ry, x != 13 && x != 9
+ if(p->to.type == TYPE_MEM)
a = &p->to;
else
a = &p->from;
reg = a->reg;
if(size == 4) {
- // if addr.reg == NREG, then it is probably load from x(FP) with small x, no need to modify.
- if(reg == NREG) {
+ // if addr.reg == 0, then it is probably load from x(FP) with small x, no need to modify.
+ if(reg == 0) {
if(out != nil)
asmout(ctxt, p, o, out);
} else {
if(out != nil)
- out[0] = ((p->scond&C_SCOND)<<28) | 0x03c00103 | (reg << 16) | (reg << 12); // BIC $0xc0000000, Rx
+ out[0] = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | 0x03c00103 | ((reg&15) << 16) | ((reg&15) << 12); // BIC $0xc0000000, Rx
if((p->pc&15) == 12)
p->pc += 4;
size += 4;
// This won't handle .W/.P, so we should reject such code.
if(p->scond & (C_PBIT|C_WBIT))
ctxt->diag("unsupported instruction (.P/.W): %P", p);
- q = ctxt->arch->prg();
+ q = emallocz(sizeof(Prog));
*q = *p;
- if(p->to.type == D_OREG)
+ if(p->to.type == TYPE_MEM)
a2 = &q->to;
else
a2 = &q->from;
// make p into MOVW $X(R), R11
p->as = AMOVW;
p->from = *a;
- p->from.type = D_CONST;
- p->to = zprg.to;
- p->to.type = D_REG;
- p->to.reg = 11;
+ p->from.type = TYPE_ADDR;
+ p->to = zprog.to;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_R11;
// make q into p but load/store from 0(R11)
- *a2 = zprg.from;
- a2->type = D_OREG;
- a2->reg = 11;
+ *a2 = zprog.from;
+ a2->type = TYPE_MEM;
+ a2->reg = REG_R11;
a2->sym = nil;
a2->offset = 0;
size = oplook(ctxt, p)->size;
}
// destination register specific
- if(p->to.type == D_REG) {
+ if(p->to.type == TYPE_REG) {
switch(p->to.reg) {
- case 9:
+ case REG_R9:
ctxt->diag("invalid instruction, cannot write to R9: %P", p);
break;
- case 13:
+ case REG_R13:
if(out != nil)
out[size/4] = 0xe3cdd103; // BIC $0xc0000000, R13
if(((p->pc+size) & 15) == 0)
flushpool(ctxt, p, 0, 0);
break;
}
- if(p->as==AMOVW && p->to.type==D_REG && p->to.reg==REGPC && (p->scond&C_SCOND) == C_SCOND_NONE)
+ if(p->as==AMOVW && p->to.type==TYPE_REG && p->to.reg==REGPC && (p->scond&C_SCOND) == C_SCOND_NONE)
flushpool(ctxt, p, 0, 0);
c += m;
}
if(otxt < 0)
otxt = -otxt;
if(otxt >= (1L<<17) - 10) {
- q = ctxt->arch->prg();
+ q = emallocz(sizeof(Prog));
q->link = p->link;
p->link = q;
q->as = AB;
- q->to.type = D_BRANCH;
+ q->to.type = TYPE_BRANCH;
q->pcond = p->pcond;
p->pcond = q;
- q = ctxt->arch->prg();
+ q = emallocz(sizeof(Prog));
q->link = p->link;
p->link = q;
q->as = AB;
- q->to.type = D_BRANCH;
+ q->to.type = TYPE_BRANCH;
q->pcond = q->link->link;
bflag = 1;
}
if(ctxt->blitrl) {
if(skip){
if(0 && skip==1)print("note: flush literal pool at %llux: len=%ud ref=%ux\n", p->pc+4, pool.size, pool.start);
- q = ctxt->arch->prg();
+ q = emallocz(sizeof(Prog));
q->as = AB;
- q->to.type = D_BRANCH;
+ q->to.type = TYPE_BRANCH;
q->pcond = p->link;
q->link = ctxt->blitrl;
q->lineno = p->lineno;
return 0;
if(ctxt->headtype == Hnacl && pool.size % 16 != 0) {
// if pool is not multiple of 16 bytes, add an alignment marker
- q = ctxt->arch->prg();
+ q = emallocz(sizeof(Prog));
q->as = ADATABUNDLEEND;
ctxt->elitrl->link = q;
ctxt->elitrl = q;
c = aclass(ctxt, a);
- t = zprg;
+ t = zprog;
t.as = AWORD;
switch(c) {
case C_SAUTO:
case C_LAUTO:
case C_LACON:
- t.to.type = D_CONST;
+ t.to.type = TYPE_CONST;
t.to.offset = ctxt->instoffset;
break;
}
if(ctxt->headtype == Hnacl && pool.size%16 == 0) {
// start a new data bundle
- q = ctxt->arch->prg();
- *q = zprg;
+ q = emallocz(sizeof(Prog));
+ *q = zprog;
q->as = ADATABUNDLE;
q->pc = pool.size;
pool.size += 4;
ctxt->elitrl = q;
}
- q = ctxt->arch->prg();
+ q = emallocz(sizeof(Prog));
*q = t;
q->pc = pool.size;
int t;
switch(a->type) {
- case D_NONE:
+ case TYPE_NONE:
return C_NONE;
- case D_REG:
- return C_REG;
+ case TYPE_REG:
+ if(REG_R0 <= a->reg && a->reg <= REG_R15)
+ return C_REG;
+ if(REG_F0 <= a->reg && a->reg <= REG_F15)
+ return C_FREG;
+ if(a->reg == REG_FPSR || a->reg == REG_FPCR)
+ return C_FCR;
+ if(a->reg == REG_CPSR || a->reg == REG_SPSR)
+ return C_PSR;
+ return C_GOK;
- case D_REGREG:
+ case TYPE_REGREG:
return C_REGREG;
- case D_REGREG2:
+ case TYPE_REGREG2:
return C_REGREG2;
- case D_SHIFT:
+ case TYPE_SHIFT:
return C_SHIFT;
- case D_FREG:
- return C_FREG;
-
- case D_FPCR:
- return C_FCR;
-
- case D_OREG:
+ case TYPE_MEM:
switch(a->name) {
- case D_EXTERN:
- case D_STATIC:
+ case NAME_EXTERN:
+ case NAME_STATIC:
if(a->sym == 0 || a->sym->name == 0) {
print("null sym external\n");
return C_GOK;
ctxt->instoffset = 0; // s.b. unused but just in case
return C_ADDR;
- case D_AUTO:
+ case NAME_AUTO:
ctxt->instoffset = ctxt->autosize + a->offset;
t = immaddr(ctxt->instoffset);
if(t){
}
return C_LAUTO;
- case D_PARAM:
+ case NAME_PARAM:
ctxt->instoffset = ctxt->autosize + a->offset + 4L;
t = immaddr(ctxt->instoffset);
if(t){
return C_SAUTO;
}
return C_LAUTO;
- case D_NONE:
+ case TYPE_NONE:
ctxt->instoffset = a->offset;
t = immaddr(ctxt->instoffset);
if(t) {
}
return C_GOK;
- case D_PSR:
- return C_PSR;
-
- case D_OCONST:
- switch(a->name) {
- case D_EXTERN:
- case D_STATIC:
- ctxt->instoffset = 0; // s.b. unused but just in case
- return C_ADDR;
- }
- return C_GOK;
-
- case D_FCONST:
+ case TYPE_FCONST:
if(chipzero5(ctxt, a->u.dval) >= 0)
return C_ZFCON;
if(chipfloat5(ctxt, a->u.dval) >= 0)
return C_SFCON;
return C_LFCON;
- case D_CONST:
- case D_CONST2:
+ case TYPE_TEXTSIZE:
+ return C_TEXTSIZE;
+
+ case TYPE_CONST:
+ case TYPE_ADDR:
switch(a->name) {
- case D_NONE:
+ case TYPE_NONE:
ctxt->instoffset = a->offset;
- if(a->reg != NREG)
+ if(a->reg != 0)
return aconsize(ctxt);
t = immrot(ctxt->instoffset);
return C_NCON;
return C_LCON;
- case D_EXTERN:
- case D_STATIC:
+ case NAME_EXTERN:
+ case NAME_STATIC:
s = a->sym;
if(s == nil)
break;
ctxt->instoffset = 0; // s.b. unused but just in case
return C_LCONADDR;
- case D_AUTO:
+ case NAME_AUTO:
ctxt->instoffset = ctxt->autosize + a->offset;
return aconsize(ctxt);
- case D_PARAM:
+ case NAME_PARAM:
ctxt->instoffset = ctxt->autosize + a->offset + 4L;
return aconsize(ctxt);
}
return C_GOK;
- case D_BRANCH:
+ case TYPE_BRANCH:
return C_SBRA;
}
return C_GOK;
}
a3--;
a2 = C_NONE;
- if(p->reg != NREG)
+ if(p->reg != 0)
a2 = C_REG;
r = p->as;
o = oprange[r].start;
rf = p->from.reg;
rt = p->to.reg;
r = p->reg;
- if(p->to.type == D_NONE)
+ if(p->to.type == TYPE_NONE)
rt = 0;
if(p->as == AMOVB || p->as == AMOVH || p->as == AMOVW || p->as == AMVN)
r = 0;
else
- if(r == NREG)
+ if(r == 0)
r = rt;
- o1 |= rf | (r<<16) | (rt<<12);
+ o1 |= ((rf&15)<<0) | ((r&15)<<16) | ((rt&15)<<12);
break;
case 2: /* movbu $I,[R],R */
o1 |= immrot(ctxt->instoffset);
rt = p->to.reg;
r = p->reg;
- if(p->to.type == D_NONE)
+ if(p->to.type == TYPE_NONE)
rt = 0;
if(p->as == AMOVW || p->as == AMVN)
r = 0;
- else if(r == NREG)
+ else if(r == 0)
r = rt;
- o1 |= (r<<16) | (rt<<12);
+ o1 |= ((r&15)<<16) | ((rt&15)<<12);
break;
case 3: /* add R<<[IR],[R],R */
o1 = oprrr(ctxt, AADD, p->scond);
o1 |= immrot(ctxt->instoffset);
r = p->from.reg;
- if(r == NREG)
+ if(r == 0)
r = o->param;
- o1 |= r << 16;
- o1 |= p->to.reg << 12;
+ o1 |= (r&15) << 16;
+ o1 |= (p->to.reg&15) << 12;
break;
case 5: /* bra s */
aclass(ctxt, &p->to);
o1 = oprrr(ctxt, AADD, p->scond);
o1 |= immrot(ctxt->instoffset);
- o1 |= p->to.reg << 16;
- o1 |= REGPC << 12;
+ o1 |= (p->to.reg&15) << 16;
+ o1 |= (REGPC&15) << 12;
break;
case 7: /* bl (R) -> blx R */
if(ctxt->instoffset != 0)
ctxt->diag("%P: doesn't support BL offset(REG) where offset != 0", p);
o1 = oprrr(ctxt, ABL, p->scond);
- o1 |= p->to.reg;
+ o1 |= (p->to.reg&15) << 0;
rel = addrel(ctxt->cursym);
rel->off = ctxt->pc;
rel->siz = 0;
aclass(ctxt, &p->from);
o1 = oprrr(ctxt, p->as, p->scond);
r = p->reg;
- if(r == NREG)
+ if(r == 0)
r = p->to.reg;
- o1 |= r;
+ o1 |= (r&15) << 0;
o1 |= (ctxt->instoffset&31) << 7;
- o1 |= p->to.reg << 12;
+ o1 |= (p->to.reg&15) << 12;
break;
case 9: /* sll R,[R],R -> mov (R<<R),R */
o1 = oprrr(ctxt, p->as, p->scond);
r = p->reg;
- if(r == NREG)
+ if(r == 0)
r = p->to.reg;
- o1 |= r;
- o1 |= (p->from.reg << 8) | (1<<4);
- o1 |= p->to.reg << 12;
+ o1 |= (r&15) << 0;
+ o1 |= ((p->from.reg&15) << 8) | (1<<4);
+ o1 |= (p->to.reg&15) << 12;
break;
case 10: /* swi [$con] */
o1 = oprrr(ctxt, p->as, p->scond);
- if(p->to.type != D_NONE) {
+ if(p->to.type != TYPE_NONE) {
aclass(ctxt, &p->to);
o1 |= ctxt->instoffset & 0xffffff;
}
case 12: /* movw $lcon, reg */
o1 = omvl(ctxt, p, &p->from, p->to.reg);
if(o->flag & LPCREL) {
- o2 = oprrr(ctxt, AADD, p->scond) | p->to.reg | REGPC << 16 | p->to.reg << 12;
+ o2 = oprrr(ctxt, AADD, p->scond) | (p->to.reg&15) << 0 | (REGPC&15) << 16 | (p->to.reg&15) << 12;
}
break;
if(!o1)
break;
o2 = oprrr(ctxt, p->as, p->scond);
- o2 |= REGTMP;
+ o2 |= (REGTMP&15);
r = p->reg;
if(p->as == AMOVW || p->as == AMVN)
r = 0;
- else if(r == NREG)
+ else if(r == 0)
r = p->to.reg;
- o2 |= r << 16;
- if(p->to.type != D_NONE)
- o2 |= p->to.reg << 12;
+ o2 |= (r&15) << 16;
+ if(p->to.type != TYPE_NONE)
+ o2 |= (p->to.reg&15) << 12;
break;
case 14: /* movb/movbu/movh/movhu R,R */
o2 = oprrr(ctxt, ASRA, p->scond);
r = p->to.reg;
- o1 |= (p->from.reg)|(r<<12);
- o2 |= (r)|(r<<12);
+ o1 |= ((p->from.reg&15)<<0)|((r&15)<<12);
+ o2 |= (r&15)|((r&15)<<12);
if(p->as == AMOVB || p->as == AMOVBS || p->as == AMOVBU) {
o1 |= (24<<7);
o2 |= (24<<7);
rf = p->from.reg;
rt = p->to.reg;
r = p->reg;
- if(r == NREG)
+ if(r == 0)
r = rt;
if(rt == r) {
r = rf;
rf = rt;
}
if(0)
- if(rt == r || rf == REGPC || r == REGPC || rt == REGPC) {
+ if(rt == r || rf == (REGPC&15) || r == (REGPC&15) || rt == (REGPC&15)) {
ctxt->diag("bad registers in MUL");
prasm(p);
}
- o1 |= (rf<<8) | r | (rt<<16);
+ o1 |= ((rf&15)<<8) | ((r&15)<<0) | ((rt&15)<<16);
break;
rt = p->to.reg;
rt2 = p->to.offset;
r = p->reg;
- o1 |= (rf<<8) | r | (rt<<16) | (rt2<<12);
+ o1 |= ((rf&15)<<8) | ((r&15)<<0) | ((rt&15)<<16) | ((rt2&15)<<12);
break;
case 20: /* mov/movb/movbu R,O(R) */
aclass(ctxt, &p->to);
r = p->to.reg;
- if(r == NREG)
+ if(r == 0)
r = o->param;
o1 = osr(ctxt, p->as, p->from.reg, ctxt->instoffset, r, p->scond);
break;
case 21: /* mov/movbu O(R),R -> lr */
aclass(ctxt, &p->from);
r = p->from.reg;
- if(r == NREG)
+ if(r == 0)
r = o->param;
o1 = olr(ctxt, ctxt->instoffset, r, p->to.reg, p->scond);
if(p->as != AMOVW)
if(!o1)
break;
r = p->to.reg;
- if(r == NREG)
+ if(r == 0)
r = o->param;
- o2 = osrr(ctxt, p->from.reg, REGTMP,r, p->scond);
+ o2 = osrr(ctxt, p->from.reg, REGTMP&15, r, p->scond);
if(p->as != AMOVW)
o2 |= 1<<22;
break;
if(!o1)
break;
r = p->from.reg;
- if(r == NREG)
+ if(r == 0)
r = o->param;
- o2 = olrr(ctxt, REGTMP,r, p->to.reg, p->scond);
+ o2 = olrr(ctxt, REGTMP&15, r, p->to.reg, p->scond);
if(p->as == AMOVBU || p->as == AMOVBS || p->as == AMOVB)
o2 |= 1<<22;
break;
break;
o2 = oprrr(ctxt, AADD, p->scond);
- o2 |= REGTMP;
+ o2 |= (REGTMP&15);
r = p->from.reg;
- if(r == NREG)
+ if(r == 0)
r = o->param;
- o2 |= r << 16;
- if(p->to.type != D_NONE)
- o2 |= p->to.reg << 12;
+ o2 |= (r&15) << 16;
+ if(p->to.type != TYPE_NONE)
+ o2 |= (p->to.reg&15) << 12;
break;
case 35: /* mov PSR,R */
o1 = (2<<23) | (0xf<<16) | (0<<0);
- o1 |= (p->scond & C_SCOND) << 28;
+ o1 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
o1 |= (p->from.reg & 1) << 22;
- o1 |= p->to.reg << 12;
+ o1 |= (p->to.reg&15) << 12;
break;
case 36: /* mov R,PSR */
o1 = (2<<23) | (0x29f<<12) | (0<<4);
if(p->scond & C_FBIT)
o1 ^= 0x010 << 12;
- o1 |= (p->scond & C_SCOND) << 28;
+ o1 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
o1 |= (p->to.reg & 1) << 22;
- o1 |= p->from.reg << 0;
+ o1 |= (p->from.reg&15) << 0;
break;
case 37: /* mov $con,PSR */
o1 = (2<<23) | (0x29f<<12) | (0<<4);
if(p->scond & C_FBIT)
o1 ^= 0x010 << 12;
- o1 |= (p->scond & C_SCOND) << 28;
+ o1 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
o1 |= immrot(ctxt->instoffset);
o1 |= (p->to.reg & 1) << 22;
- o1 |= p->from.reg << 0;
+ o1 |= (p->from.reg&15) << 0;
break;
case 38:
case 38: /* movm $con,oreg -> stm */
o1 = (0x4 << 25);
o1 |= p->from.offset & 0xffff;
- o1 |= p->to.reg << 16;
+ o1 |= (p->to.reg&15) << 16;
aclass(ctxt, &p->to);
break;
case 39: /* movm oreg,$con -> ldm */
o1 = (0x4 << 25) | (1 << 20);
o1 |= p->to.offset & 0xffff;
- o1 |= p->from.reg << 16;
+ o1 |= (p->from.reg&15) << 16;
aclass(ctxt, &p->from);
break;
}
if(ctxt->instoffset != 0)
ctxt->diag("offset must be zero in MOVM; %P", p);
- o1 |= (p->scond & C_SCOND) << 28;
+ o1 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
if(p->scond & C_PBIT)
o1 |= 1 << 24;
if(p->scond & C_UBIT)
o1 = (0x2<<23) | (0x9<<4);
if(p->as != ASWPW)
o1 |= 1 << 22;
- o1 |= p->from.reg << 16;
- o1 |= p->reg << 0;
- o1 |= p->to.reg << 12;
- o1 |= (p->scond & C_SCOND) << 28;
+ o1 |= (p->from.reg&15) << 16;
+ o1 |= (p->reg&15) << 0;
+ o1 |= (p->to.reg&15) << 12;
+ o1 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
break;
case 41: /* rfe -> movm.s.w.u 0(r13),[r15] */
case 50: /* floating point store */
v = regoff(ctxt, &p->to);
r = p->to.reg;
- if(r == NREG)
+ if(r == 0)
r = o->param;
o1 = ofsr(ctxt, p->as, p->from.reg, v, r, p->scond, p);
break;
case 51: /* floating point load */
v = regoff(ctxt, &p->from);
r = p->from.reg;
- if(r == NREG)
+ if(r == 0)
r = o->param;
o1 = ofsr(ctxt, p->as, p->to.reg, v, r, p->scond, p) | (1<<20);
break;
if(!o1)
break;
r = p->to.reg;
- if(r == NREG)
+ if(r == 0)
r = o->param;
- o2 = oprrr(ctxt, AADD, p->scond) | (REGTMP << 12) | (REGTMP << 16) | r;
+ o2 = oprrr(ctxt, AADD, p->scond) | ((REGTMP&15) << 12) | ((REGTMP&15) << 16) | ((r&15) << 0);
o3 = ofsr(ctxt, p->as, p->from.reg, 0, REGTMP, p->scond, p);
break;
if(!o1)
break;
r = p->from.reg;
- if(r == NREG)
+ if(r == 0)
r = o->param;
- o2 = oprrr(ctxt, AADD, p->scond) | (REGTMP << 12) | (REGTMP << 16) | r;
- o3 = ofsr(ctxt, p->as, p->to.reg, 0, REGTMP, p->scond, p) | (1<<20);
+ o2 = oprrr(ctxt, AADD, p->scond) | ((REGTMP&15) << 12) | ((REGTMP&15) << 16) | ((r&15) << 0);
+ o3 = ofsr(ctxt, p->as, p->to.reg, 0, (REGTMP&15), p->scond, p) | (1<<20);
break;
case 54: /* floating point arith */
rf = p->from.reg;
rt = p->to.reg;
r = p->reg;
- if(r == NREG) {
+ if(r == 0) {
r = rt;
if(p->as == AMOVF || p->as == AMOVD || p->as == AMOVFD || p->as == AMOVDF ||
p->as == ASQRTF || p->as == ASQRTD || p->as == AABSF || p->as == AABSD)
r = 0;
}
- o1 |= rf | (r<<16) | (rt<<12);
+ o1 |= ((rf&15)<<0) | ((r&15)<<16) | ((rt&15)<<12);
break;
case 56: /* move to FP[CS]R */
- o1 = ((p->scond & C_SCOND) << 28) | (0xe << 24) | (1<<8) | (1<<4);
- o1 |= ((p->to.reg+1)<<21) | (p->from.reg << 12);
+ o1 = (((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28) | (0xe << 24) | (1<<8) | (1<<4);
+ o1 |= (((p->to.reg&1)+1)<<21) | ((p->from.reg&15) << 12);
break;
case 57: /* move from FP[CS]R */
- o1 = ((p->scond & C_SCOND) << 28) | (0xe << 24) | (1<<8) | (1<<4);
- o1 |= ((p->from.reg+1)<<21) | (p->to.reg<<12) | (1<<20);
+ o1 = (((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28) | (0xe << 24) | (1<<8) | (1<<4);
+ o1 |= (((p->from.reg&1)+1)<<21) | ((p->to.reg&15)<<12) | (1<<20);
break;
case 58: /* movbu R,R */
o1 = oprrr(ctxt, AAND, p->scond);
o1 |= immrot(0xff);
rt = p->to.reg;
r = p->from.reg;
- if(p->to.type == D_NONE)
+ if(p->to.type == TYPE_NONE)
rt = 0;
- if(r == NREG)
+ if(r == 0)
r = rt;
- o1 |= (r<<16) | (rt<<12);
+ o1 |= ((r&15)<<16) | ((rt&15)<<12);
break;
case 59: /* movw/bu R<<I(R),R -> ldr indexed */
- if(p->from.reg == NREG) {
+ if(p->from.reg == 0) {
if(p->as != AMOVW)
ctxt->diag("byte MOV from shifter operand");
o1 = mov(ctxt, p);
break;
case 60: /* movb R(R),R -> ldrsb indexed */
- if(p->from.reg == NREG) {
+ if(p->from.reg == 0) {
ctxt->diag("byte MOV from shifter operand");
o1 = mov(ctxt, p);
break;
break;
case 61: /* movw/b/bu R,R<<[IR](R) -> str indexed */
- if(p->to.reg == NREG)
+ if(p->to.reg == 0)
ctxt->diag("MOV to shifter operand");
o1 = osrr(ctxt, p->from.reg, p->to.offset, p->to.reg, p->scond);
if(p->as == AMOVB || p->as == AMOVBS || p->as == AMOVBU)
case 62: /* case R -> movw R<<2(PC),PC */
if(o->flag & LPCREL) {
- o1 = oprrr(ctxt, AADD, p->scond) | immrot(1) | p->from.reg << 16 | REGTMP << 12;
- o2 = olrr(ctxt, REGTMP, REGPC, REGTMP, p->scond);
+ o1 = oprrr(ctxt, AADD, p->scond) | immrot(1) | (p->from.reg&15) << 16 | (REGTMP&15) << 12;
+ o2 = olrr(ctxt, REGTMP&15, REGPC, REGTMP, p->scond);
o2 |= 2<<7;
- o3 = oprrr(ctxt, AADD, p->scond) | REGTMP | REGPC << 16 | REGPC << 12;
+ o3 = oprrr(ctxt, AADD, p->scond) | (REGTMP&15) | (REGPC&15) << 16 | (REGPC&15) << 12;
} else {
- o1 = olrr(ctxt, p->from.reg, REGPC, REGPC, p->scond);
+ o1 = olrr(ctxt, p->from.reg&15, REGPC, REGPC, p->scond);
o1 |= 2<<7;
}
break;
o2 = osr(ctxt, p->as, p->from.reg, 0, REGTMP, p->scond);
if(o->flag & LPCREL) {
o3 = o2;
- o2 = oprrr(ctxt, AADD, p->scond) | REGTMP | REGPC << 16 | REGTMP << 12;
+ o2 = oprrr(ctxt, AADD, p->scond) | (REGTMP&15) | (REGPC&15) << 16 | (REGTMP&15) << 12;
}
break;
o2 |= 1<<22;
if(o->flag & LPCREL) {
o3 = o2;
- o2 = oprrr(ctxt, AADD, p->scond) | REGTMP | REGPC << 16 | REGTMP << 12;
+ o2 = oprrr(ctxt, AADD, p->scond) | (REGTMP&15) | (REGPC&15) << 16 | (REGTMP&15) << 12;
}
break;
o2 = ofsr(ctxt, p->as, p->from.reg, 0, REGTMP, p->scond, p);
if(o->flag & LPCREL) {
o3 = o2;
- o2 = oprrr(ctxt, AADD, p->scond) | REGTMP | REGPC << 16 | REGTMP << 12;
+ o2 = oprrr(ctxt, AADD, p->scond) | (REGTMP&15) | (REGPC&15) << 16 | (REGTMP&15) << 12;
}
break;
o1 = omvl(ctxt, p, &p->from, REGTMP);
if(!o1)
break;
- o2 = ofsr(ctxt, p->as, p->to.reg, 0, REGTMP, p->scond, p) | (1<<20);
+ o2 = ofsr(ctxt, p->as, p->to.reg, 0, (REGTMP&15), p->scond, p) | (1<<20);
if(o->flag & LPCREL) {
o3 = o2;
- o2 = oprrr(ctxt, AADD, p->scond) | REGTMP | REGPC << 16 | REGTMP << 12;
+ o2 = oprrr(ctxt, AADD, p->scond) | (REGTMP&15) | (REGPC&15) << 16 | (REGTMP&15) << 12;
}
break;
case 70: /* movh/movhu R,O(R) -> strh */
aclass(ctxt, &p->to);
r = p->to.reg;
- if(r == NREG)
+ if(r == 0)
r = o->param;
o1 = oshr(ctxt, p->from.reg, ctxt->instoffset, r, p->scond);
break;
case 71: /* movb/movh/movhu O(R),R -> ldrsb/ldrsh/ldrh */
aclass(ctxt, &p->from);
r = p->from.reg;
- if(r == NREG)
+ if(r == 0)
r = o->param;
o1 = olhr(ctxt, ctxt->instoffset, r, p->to.reg, p->scond);
if(p->as == AMOVB || p->as == AMOVBS)
if(!o1)
break;
r = p->to.reg;
- if(r == NREG)
+ if(r == 0)
r = o->param;
- o2 = oshrr(ctxt, p->from.reg, REGTMP,r, p->scond);
+ o2 = oshrr(ctxt, p->from.reg, REGTMP&15, r, p->scond);
break;
case 73: /* movb/movh/movhu L(R),R -> ldrsb/ldrsh/ldrh */
o1 = omvl(ctxt, p, &p->from, REGTMP);
if(!o1)
break;
r = p->from.reg;
- if(r == NREG)
+ if(r == 0)
r = o->param;
- o2 = olhrr(ctxt, REGTMP, r, p->to.reg, p->scond);
+ o2 = olhrr(ctxt, REGTMP&15, r, p->to.reg, p->scond);
if(p->as == AMOVB || p->as == AMOVBS)
o2 ^= (1<<5)|(1<<6);
else if(p->as == AMOVH || p->as == AMOVHS)
if(ctxt->instoffset != 0)
ctxt->diag("non-zero offset in ABX");
/*
- o1 = oprrr(ctxt, AADD, p->scond) | immrot(0) | (REGPC<<16) | (REGLINK<<12); // mov PC, LR
- o2 = ((p->scond&C_SCOND)<<28) | (0x12fff<<8) | (1<<4) | p->to.reg; // BX R
+ o1 = oprrr(ctxt, AADD, p->scond) | immrot(0) | ((REGPC&15)<<16) | ((REGLINK&15)<<12); // mov PC, LR
+ o2 = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | (0x12fff<<8) | (1<<4) | ((p->to.reg&15) << 0); // BX R
*/
// p->to.reg may be REGLINK
o1 = oprrr(ctxt, AADD, p->scond);
o1 |= immrot(ctxt->instoffset);
- o1 |= p->to.reg << 16;
- o1 |= REGTMP << 12;
- o2 = oprrr(ctxt, AADD, p->scond) | immrot(0) | (REGPC<<16) | (REGLINK<<12); // mov PC, LR
- o3 = ((p->scond&C_SCOND)<<28) | (0x12fff<<8) | (1<<4) | REGTMP; // BX Rtmp
+ o1 |= (p->to.reg&15) << 16;
+ o1 |= (REGTMP&15) << 12;
+ o2 = oprrr(ctxt, AADD, p->scond) | immrot(0) | ((REGPC&15)<<16) | ((REGLINK&15)<<12); // mov PC, LR
+ o3 = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | (0x12fff<<8) | (1<<4) | (REGTMP&15); // BX Rtmp
break;
case 76: /* bx O(R) when returning from fn*/
ctxt->diag("ABXRET");
if(ctxt->instoffset != 0)
ctxt->diag("offset must be zero in LDREX");
o1 = (0x19<<20) | (0xf9f);
- o1 |= p->from.reg << 16;
- o1 |= p->to.reg << 12;
- o1 |= (p->scond & C_SCOND) << 28;
+ o1 |= (p->from.reg&15) << 16;
+ o1 |= (p->to.reg&15) << 12;
+ o1 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
break;
case 78: /* strex reg,oreg,reg */
aclass(ctxt, &p->from);
if(ctxt->instoffset != 0)
ctxt->diag("offset must be zero in STREX");
o1 = (0x18<<20) | (0xf90);
- o1 |= p->from.reg << 16;
- o1 |= p->reg << 0;
- o1 |= p->to.reg << 12;
- o1 |= (p->scond & C_SCOND) << 28;
+ o1 |= (p->from.reg&15) << 16;
+ o1 |= (p->reg&15) << 0;
+ o1 |= (p->to.reg&15) << 12;
+ o1 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
break;
case 80: /* fmov zfcon,freg */
if(p->as == AMOVD) {
o2 = oprrr(ctxt, ASUBF, p->scond);
}
v = 0x70; // 1.0
- r = p->to.reg;
+ r = (p->to.reg&15) << 0;
// movf $1.0, r
- o1 |= (p->scond & C_SCOND) << 28;
- o1 |= r << 12;
+ o1 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
+ o1 |= (r&15) << 12;
o1 |= (v&0xf) << 0;
o1 |= (v&0xf0) << 12;
// subf r,r,r
- o2 |= r | (r<<16) | (r<<12);
+ o2 |= ((r&15)<<0) | ((r&15)<<16) | ((r&15)<<12);
break;
case 81: /* fmov sfcon,freg */
o1 = 0x0eb00a00; // VMOV imm 32
if(p->as == AMOVD)
o1 = 0xeeb00b00; // VMOV imm 64
- o1 |= (p->scond & C_SCOND) << 28;
- o1 |= p->to.reg << 12;
+ o1 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
+ o1 |= (p->to.reg&15) << 12;
v = chipfloat5(ctxt, p->from.u.dval);
o1 |= (v&0xf) << 0;
o1 |= (v&0xf0) << 12;
break;
case 82: /* fcmp freg,freg, */
o1 = oprrr(ctxt, p->as, p->scond);
- o1 |= (p->reg<<12) | (p->from.reg<<0);
+ o1 |= ((p->reg&15)<<12) | ((p->from.reg&15)<<0);
o2 = 0x0ef1fa10; // VMRS R15
- o2 |= (p->scond & C_SCOND) << 28;
+ o2 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
break;
case 83: /* fcmp freg,, */
o1 = oprrr(ctxt, p->as, p->scond);
- o1 |= (p->from.reg<<12) | (1<<16);
+ o1 |= ((p->from.reg&15)<<12) | (1<<16);
o2 = 0x0ef1fa10; // VMRS R15
- o2 |= (p->scond & C_SCOND) << 28;
+ o2 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
break;
case 84: /* movfw freg,freg - truncate float-to-fix */
o1 = oprrr(ctxt, p->as, p->scond);
- o1 |= (p->from.reg<<0);
- o1 |= (p->to.reg<<12);
+ o1 |= ((p->from.reg&15)<<0);
+ o1 |= ((p->to.reg&15)<<12);
break;
case 85: /* movwf freg,freg - fix-to-float */
o1 = oprrr(ctxt, p->as, p->scond);
- o1 |= (p->from.reg<<0);
- o1 |= (p->to.reg<<12);
+ o1 |= ((p->from.reg&15)<<0);
+ o1 |= ((p->to.reg&15)<<12);
break;
case 86: /* movfw freg,reg - truncate float-to-fix */
// macro for movfw freg,FTMP; movw FTMP,reg
o1 = oprrr(ctxt, p->as, p->scond);
- o1 |= (p->from.reg<<0);
- o1 |= (FREGTMP<<12);
- o2 = oprrr(ctxt, AMOVFW+AEND, p->scond);
- o2 |= (FREGTMP<<16);
- o2 |= (p->to.reg<<12);
+ o1 |= ((p->from.reg&15)<<0);
+ o1 |= ((FREGTMP&15)<<12);
+ o2 = oprrr(ctxt, AMOVFW+ALAST, p->scond);
+ o2 |= ((FREGTMP&15)<<16);
+ o2 |= ((p->to.reg&15)<<12);
break;
case 87: /* movwf reg,freg - fix-to-float */
// macro for movw reg,FTMP; movwf FTMP,freg
- o1 = oprrr(ctxt, AMOVWF+AEND, p->scond);
- o1 |= (p->from.reg<<12);
- o1 |= (FREGTMP<<16);
+ o1 = oprrr(ctxt, AMOVWF+ALAST, p->scond);
+ o1 |= ((p->from.reg&15)<<12);
+ o1 |= ((FREGTMP&15)<<16);
o2 = oprrr(ctxt, p->as, p->scond);
- o2 |= (FREGTMP<<0);
- o2 |= (p->to.reg<<12);
+ o2 |= ((FREGTMP&15)<<0);
+ o2 |= ((p->to.reg&15)<<12);
break;
case 88: /* movw reg,freg */
- o1 = oprrr(ctxt, AMOVWF+AEND, p->scond);
- o1 |= (p->from.reg<<12);
- o1 |= (p->to.reg<<16);
+ o1 = oprrr(ctxt, AMOVWF+ALAST, p->scond);
+ o1 |= ((p->from.reg&15)<<12);
+ o1 |= ((p->to.reg&15)<<16);
break;
case 89: /* movw freg,reg */
- o1 = oprrr(ctxt, AMOVFW+AEND, p->scond);
- o1 |= (p->from.reg<<16);
- o1 |= (p->to.reg<<12);
+ o1 = oprrr(ctxt, AMOVFW+ALAST, p->scond);
+ o1 |= ((p->from.reg&15)<<16);
+ o1 |= ((p->to.reg&15)<<12);
break;
case 90: /* tst reg */
- o1 = oprrr(ctxt, ACMP+AEND, p->scond);
- o1 |= p->from.reg<<16;
+ o1 = oprrr(ctxt, ACMP+ALAST, p->scond);
+ o1 |= (p->from.reg&15)<<16;
break;
case 91: /* ldrexd oreg,reg */
aclass(ctxt, &p->from);
if(ctxt->instoffset != 0)
ctxt->diag("offset must be zero in LDREX");
o1 = (0x1b<<20) | (0xf9f);
- o1 |= p->from.reg << 16;
- o1 |= p->to.reg << 12;
- o1 |= (p->scond & C_SCOND) << 28;
+ o1 |= (p->from.reg&15) << 16;
+ o1 |= (p->to.reg&15) << 12;
+ o1 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
break;
case 92: /* strexd reg,oreg,reg */
aclass(ctxt, &p->from);
if(ctxt->instoffset != 0)
ctxt->diag("offset must be zero in STREX");
o1 = (0x1a<<20) | (0xf90);
- o1 |= p->from.reg << 16;
- o1 |= p->reg << 0;
- o1 |= p->to.reg << 12;
- o1 |= (p->scond & C_SCOND) << 28;
+ o1 |= (p->from.reg&15) << 16;
+ o1 |= (p->reg&15) << 0;
+ o1 |= (p->to.reg&15) << 12;
+ o1 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
break;
case 93: /* movb/movh/movhu addr,R -> ldrsb/ldrsh/ldrh */
o1 = omvl(ctxt, p, &p->from, REGTMP);
o2 ^= (1<<6);
if(o->flag & LPCREL) {
o3 = o2;
- o2 = oprrr(ctxt, AADD, p->scond) | REGTMP | REGPC << 16 | REGTMP << 12;
+ o2 = oprrr(ctxt, AADD, p->scond) | (REGTMP&15) | (REGPC&15) << 16 | (REGTMP&15) << 12;
}
break;
case 94: /* movh/movhu R,addr -> strh */
o2 = oshr(ctxt, p->from.reg, 0, REGTMP, p->scond);
if(o->flag & LPCREL) {
o3 = o2;
- o2 = oprrr(ctxt, AADD, p->scond) | REGTMP | REGPC << 16 | REGTMP << 12;
+ o2 = oprrr(ctxt, AADD, p->scond) | (REGTMP&15) | (REGPC&15) << 16 | (REGTMP&15) << 12;
}
break;
case 95: /* PLD off(reg) */
o1 = 0xf5d0f000;
- o1 |= p->from.reg << 16;
+ o1 |= (p->from.reg&15) << 16;
if(p->from.offset < 0) {
o1 &= ~(1 << 23);
o1 |= (-p->from.offset) & 0xfff;
break;
case 97: /* CLZ Rm, Rd */
o1 = oprrr(ctxt, p->as, p->scond);
- o1 |= p->to.reg << 12;
- o1 |= p->from.reg;
+ o1 |= (p->to.reg&15) << 12;
+ o1 |= (p->from.reg&15) << 0;
break;
case 98: /* MULW{T,B} Rs, Rm, Rd */
o1 = oprrr(ctxt, p->as, p->scond);
- o1 |= p->to.reg << 16;
- o1 |= p->from.reg << 8;
- o1 |= p->reg;
+ o1 |= (p->to.reg&15) << 16;
+ o1 |= (p->from.reg&15) << 8;
+ o1 |= (p->reg&15) << 0;
break;
case 99: /* MULAW{T,B} Rs, Rm, Rn, Rd */
o1 = oprrr(ctxt, p->as, p->scond);
- o1 |= p->to.reg << 12;
- o1 |= p->from.reg << 8;
- o1 |= p->reg;
- o1 |= p->to.offset << 16;
+ o1 |= (p->to.reg&15) << 12;
+ o1 |= (p->from.reg&15) << 8;
+ o1 |= (p->reg&15) << 0;
+ o1 |= (p->to.offset&15) << 16;
break;
case 100:
// DATABUNDLE: BKPT $0x5be0, signify the start of NaCl data bundle;
o1 = oprrr(ctxt, p->as, p->scond);
o1 |= p->from.offset;
rt = p->to.reg;
- r = p->reg;
- if(p->to.type == D_NONE)
+ if(p->to.type == TYPE_NONE)
rt = 0;
+ r = p->reg;
if(p->as == AMOVW || p->as == AMVN)
r = 0;
- else if(r == NREG)
+ else if(r == 0)
r = rt;
- o1 |= (r<<16) | (rt<<12);
+ o1 |= ((r&15)<<16) | ((rt&15)<<12);
return o1;
}
{
uint32 o;
- o = (sc & C_SCOND) << 28;
+ o = ((sc & C_SCOND) ^ C_SCOND_XOR) << 28;
if(sc & C_SBIT)
o |= 1 << 20;
if(sc & (C_PBIT|C_WBIT))
return o | (0xe<<24) | (0xb<<20) | (8<<16) | (0xa<<8) | (4<<4) |
(1<<18) | (1<<8) | (1<<7); // toint, double, trunc
- case AMOVWF+AEND: // copy WtoF
+ case AMOVWF+ALAST: // copy WtoF
return o | (0xe<<24) | (0x0<<20) | (0xb<<8) | (1<<4);
- case AMOVFW+AEND: // copy FtoW
+ case AMOVFW+ALAST: // copy FtoW
return o | (0xe<<24) | (0x1<<20) | (0xb<<8) | (1<<4);
- case ACMP+AEND: // cmp imm
+ case ACMP+ALAST: // cmp imm
return o | (0x3<<24) | (0x5<<20);
case ACLZ:
if(sc & (C_SBIT|C_PBIT|C_WBIT))
ctxt->diag(".nil/.nil/.W on bra instruction");
sc &= C_SCOND;
+ sc ^= C_SCOND_XOR;
if(a == ABL || a == ADUFFZERO || a == ADUFFCOPY)
return (sc<<28)|(0x5<<25)|(0x1<<24);
if(sc != 0xe)
if(sc & C_SBIT)
ctxt->diag(".nil on LDR/STR instruction");
- o = (sc & C_SCOND) << 28;
+ o = ((sc & C_SCOND) ^ C_SCOND_XOR) << 28;
if(!(sc & C_PBIT))
o |= 1 << 24;
if(!(sc & C_UBIT))
if(v >= (1<<12) || v < 0)
ctxt->diag("literal span too large: %d (R%d)\n%P", v, b, ctxt->printp);
o |= v;
- o |= b << 16;
- o |= r << 12;
+ o |= (b&15) << 16;
+ o |= (r&15) << 12;
return o;
}
if(sc & C_SBIT)
ctxt->diag(".nil on LDRH/STRH instruction");
- o = (sc & C_SCOND) << 28;
+ o = ((sc & C_SCOND) ^ C_SCOND_XOR) << 28;
if(!(sc & C_PBIT))
o |= 1 << 24;
if(sc & C_WBIT)
if(v >= (1<<8) || v < 0)
ctxt->diag("literal span too large: %d (R%d)\n%P", v, b, ctxt->printp);
o |= (v&0xf)|((v>>4)<<8)|(1<<22);
- o |= b << 16;
- o |= r << 12;
+ o |= (b&15) << 16;
+ o |= (r&15) << 12;
return o;
}
if(sc & C_SBIT)
ctxt->diag(".nil on FLDR/FSTR instruction");
- o = (sc & C_SCOND) << 28;
+ o = ((sc & C_SCOND) ^ C_SCOND_XOR) << 28;
if(!(sc & C_PBIT))
o |= 1 << 24;
if(sc & C_WBIT)
if(v >= (1<<10) || v < 0)
ctxt->diag("literal span too large: %d\n%P", v, p);
o |= (v>>2) & 0xFF;
- o |= b << 16;
- o |= r << 12;
+ o |= (b&15) << 16;
+ o |= (r&15) << 12;
switch(a) {
default:
}
o1 = oprrr(ctxt, AMVN, p->scond&C_SCOND);
o1 |= v;
- o1 |= dr << 12;
+ o1 |= (dr&15) << 12;
} else {
v = p->pcond->pc - p->pc - 8;
o1 = olr(ctxt, v, REGPC, dr, p->scond&C_SCOND);
Ymr, Ymm,
Yxr, Yxm,
Ytls,
+ Ytextsize,
Ymax,
Zxxx = 0,
};
static uchar ycover[Ymax*Ymax];
-static int reg[D_NONE];
-static int regrex[D_NONE+1];
+static int reg[MAXREG];
+static int regrex[MAXREG+1];
static void asmins(Link *ctxt, Prog *p);
static uchar ynone[] =
};
static uchar ytext[] =
{
- Ymb, Yi64, Zpseudo,1,
+ Ymb, Ytextsize, Zpseudo,1,
0
};
static uchar ynop[] =
{ AFXRSTOR64, ysvrs, Pw, {0x0f,0xae,(01),0x0f,0xae,(01)} },
{ AFXSAVE64, ysvrs, Pw, {0x0f,0xae,(00),0x0f,0xae,(00)} },
{ AGLOBL },
- { AGOK },
- { AHISTORY },
{ AHLT, ynone, Px, {0xf4} },
{ AIDIVB, ydivb, Pb, {0xf6,(07)} },
{ AIDIVL, ydivl, Px, {0xf7,(07)} },
{ AMULSD, yxm, Pf2, {0x59} },
{ AMULSS, yxm, Pf3, {0x59} },
{ AMULW, ydivl, Pe, {0xf7,(04)} },
- { ANAME },
{ ANEGB, yscond, Pb, {0xf6,(03)} },
{ ANEGL, yscond, Px, {0xf7,(03)} },
{ ANEGQ, yscond, Pw, {0xf7,(03)} },
instinit();
for(p = ctxt->cursym->text; p != nil; p = p->link) {
- n = 0;
- if(p->to.type == D_BRANCH)
+ if(p->to.type == TYPE_BRANCH)
if(p->pcond == nil)
p->pcond = p;
- if((q = p->pcond) != nil)
- if(q->back != 2)
- n = 1;
- p->back = n;
if(p->as == AADJSP) {
- p->to.type = D_SP;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_SP;
v = -p->from.offset;
p->from.offset = v;
p->as = spadjop(ctxt, p, AADDL, AADDQ);
}
if(p->as == AADJSP) {
- p->to.type = D_SP;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_SP;
v = -p->from.offset;
p->from.offset = v;
p->as = spadjop(ctxt, p, AADDL, AADDQ);
ycover[Ym*Ymax + Yxm] = 1;
ycover[Yxr*Ymax + Yxm] = 1;
- for(i=0; i<D_NONE; i++) {
+ for(i=0; i<MAXREG; i++) {
reg[i] = -1;
- if(i >= D_AL && i <= D_R15B) {
- reg[i] = (i-D_AL) & 7;
- if(i >= D_SPB && i <= D_DIB)
+ if(i >= REG_AL && i <= REG_R15B) {
+ reg[i] = (i-REG_AL) & 7;
+ if(i >= REG_SPB && i <= REG_DIB)
regrex[i] = 0x40;
- if(i >= D_R8B && i <= D_R15B)
+ if(i >= REG_R8B && i <= REG_R15B)
regrex[i] = Rxr | Rxx | Rxb;
}
- if(i >= D_AH && i<= D_BH)
- reg[i] = 4 + ((i-D_AH) & 7);
- if(i >= D_AX && i <= D_R15) {
- reg[i] = (i-D_AX) & 7;
- if(i >= D_R8)
+ if(i >= REG_AH && i<= REG_BH)
+ reg[i] = 4 + ((i-REG_AH) & 7);
+ if(i >= REG_AX && i <= REG_R15) {
+ reg[i] = (i-REG_AX) & 7;
+ if(i >= REG_R8)
regrex[i] = Rxr | Rxx | Rxb;
}
- if(i >= D_F0 && i <= D_F0+7)
- reg[i] = (i-D_F0) & 7;
- if(i >= D_M0 && i <= D_M0+7)
- reg[i] = (i-D_M0) & 7;
- if(i >= D_X0 && i <= D_X0+15) {
- reg[i] = (i-D_X0) & 7;
- if(i >= D_X0+8)
+ if(i >= REG_F0 && i <= REG_F0+7)
+ reg[i] = (i-REG_F0) & 7;
+ if(i >= REG_M0 && i <= REG_M0+7)
+ reg[i] = (i-REG_M0) & 7;
+ if(i >= REG_X0 && i <= REG_X0+15) {
+ reg[i] = (i-REG_X0) & 7;
+ if(i >= REG_X0+8)
regrex[i] = Rxr | Rxx | Rxb;
}
- if(i >= D_CR+8 && i <= D_CR+15)
+ if(i >= REG_CR+8 && i <= REG_CR+15)
regrex[i] = Rxr;
}
}
static int
prefixof(Link *ctxt, Addr *a)
{
- switch(a->type) {
- case D_INDIR+D_CS:
- return 0x2e;
- case D_INDIR+D_DS:
- return 0x3e;
- case D_INDIR+D_ES:
- return 0x26;
- case D_INDIR+D_FS:
- return 0x64;
- case D_INDIR+D_GS:
- return 0x65;
- case D_INDIR+D_TLS:
- // NOTE: Systems listed here should be only systems that
- // support direct TLS references like 8(TLS) implemented as
- // direct references from FS or GS. Systems that require
- // the initial-exec model, where you load the TLS base into
- // a register and then index from that register, do not reach
- // this code and should not be listed.
- switch(ctxt->headtype) {
- default:
- sysfatal("unknown TLS base register for %s", headstr(ctxt->headtype));
- case Hdragonfly:
- case Hfreebsd:
- case Hlinux:
- case Hnetbsd:
- case Hopenbsd:
- case Hsolaris:
- return 0x64; // FS
- case Hdarwin:
- return 0x65; // GS
+ if(a->type == TYPE_MEM && a->name == NAME_NONE) {
+ switch(a->reg) {
+ case REG_CS:
+ return 0x2e;
+ case REG_DS:
+ return 0x3e;
+ case REG_ES:
+ return 0x26;
+ case REG_FS:
+ return 0x64;
+ case REG_GS:
+ return 0x65;
+ case REG_TLS:
+ // NOTE: Systems listed here should be only systems that
+ // support direct TLS references like 8(TLS) implemented as
+ // direct references from FS or GS. Systems that require
+ // the initial-exec model, where you load the TLS base into
+ // a register and then index from that register, do not reach
+ // this code and should not be listed.
+ switch(ctxt->headtype) {
+ default:
+ sysfatal("unknown TLS base register for %s", headstr(ctxt->headtype));
+ case Hdragonfly:
+ case Hfreebsd:
+ case Hlinux:
+ case Hnetbsd:
+ case Hopenbsd:
+ case Hsolaris:
+ return 0x64; // FS
+ case Hdarwin:
+ return 0x65; // GS
+ }
}
}
switch(a->index) {
- case D_CS:
+ case REG_CS:
return 0x2e;
- case D_DS:
+ case REG_DS:
return 0x3e;
- case D_ES:
+ case REG_ES:
return 0x26;
- case D_FS:
+ case REG_FS:
return 0x64;
- case D_GS:
+ case REG_GS:
return 0x65;
}
return 0;
{
vlong v;
int32 l;
+
+ // TODO(rsc): This special case is for SHRQ $3, AX:DX,
+ // which encodes as SHRQ $32(DX*0), AX.
+ // Similarly SHRQ CX, AX:DX is really SHRQ CX(DX*0), AX.
+ // Change encoding and remove.
+ if((a->type == TYPE_CONST || a->type == TYPE_REG) && a->index != REG_NONE && a->scale == 0)
+ return Ycol;
- if(a->type >= D_INDIR || a->index != D_NONE) {
- if(a->index != D_NONE && a->scale == 0) {
- if(a->type == D_ADDR) {
- switch(a->index) {
- case D_EXTERN:
- case D_STATIC:
- if(a->sym != nil && isextern(a->sym))
- return Yi32;
- return Yiauto; // use pc-relative addressing
- case D_AUTO:
- case D_PARAM:
- return Yiauto;
- }
- return Yxxx;
- }
- return Ycol;
- }
+ switch(a->type) {
+ case TYPE_NONE:
+ return Ynone;
+
+ case TYPE_BRANCH:
+ return Ybr;
+
+ case TYPE_MEM:
return Ym;
+
+ case TYPE_ADDR:
+ switch(a->name) {
+ case NAME_EXTERN:
+ case NAME_STATIC:
+ if(a->sym != nil && isextern(a->sym))
+ return Yi32;
+ return Yiauto; // use pc-relative addressing
+ case NAME_AUTO:
+ case NAME_PARAM:
+ return Yiauto;
+ }
+
+ // TODO(rsc): DUFFZERO/DUFFCOPY encoding forgot to set a->index
+ // and got Yi32 in an earlier version of this code.
+ // Keep doing that until we fix yduff etc.
+ if(a->sym != nil && strncmp(a->sym->name, "runtime.duff", 12) == 0)
+ return Yi32;
+
+ if(a->sym != nil || a->name != NAME_NONE)
+ ctxt->diag("unexpected addr: %D", a);
+ // fall through
+
+ case TYPE_CONST:
+ if(a->sym != nil)
+ ctxt->diag("TYPE_CONST with symbol: %D", a);
+
+ v = a->offset;
+ if(v == 0)
+ return Yi0;
+ if(v == 1)
+ return Yi1;
+ if(v >= -128 && v <= 127)
+ return Yi8;
+ l = v;
+ if((vlong)l == v)
+ return Ys32; /* can sign extend */
+ if((v>>32) == 0)
+ return Yi32; /* unsigned */
+ return Yi64;
+
+ case TYPE_TEXTSIZE:
+ return Ytextsize;
+ }
+
+ if(a->type != TYPE_REG) {
+ ctxt->diag("unexpected addr1: type=%d %D", a->type, a);
+ return Yxxx;
}
- switch(a->type)
- {
- case D_AL:
+
+ switch(a->reg) {
+ case REG_AL:
return Yal;
- case D_AX:
+ case REG_AX:
return Yax;
/*
- case D_SPB:
+ case REG_SPB:
*/
- case D_BPB:
- case D_SIB:
- case D_DIB:
- case D_R8B:
- case D_R9B:
- case D_R10B:
- case D_R11B:
- case D_R12B:
- case D_R13B:
- case D_R14B:
- case D_R15B:
+ case REG_BPB:
+ case REG_SIB:
+ case REG_DIB:
+ case REG_R8B:
+ case REG_R9B:
+ case REG_R10B:
+ case REG_R11B:
+ case REG_R12B:
+ case REG_R13B:
+ case REG_R14B:
+ case REG_R15B:
if(ctxt->asmode != 64)
return Yxxx;
- case D_DL:
- case D_BL:
- case D_AH:
- case D_CH:
- case D_DH:
- case D_BH:
+ case REG_DL:
+ case REG_BL:
+ case REG_AH:
+ case REG_CH:
+ case REG_DH:
+ case REG_BH:
return Yrb;
- case D_CL:
+ case REG_CL:
return Ycl;
- case D_CX:
+ case REG_CX:
return Ycx;
- case D_DX:
- case D_BX:
+ case REG_DX:
+ case REG_BX:
return Yrx;
- case D_R8: /* not really Yrl */
- case D_R9:
- case D_R10:
- case D_R11:
- case D_R12:
- case D_R13:
- case D_R14:
- case D_R15:
+ case REG_R8: /* not really Yrl */
+ case REG_R9:
+ case REG_R10:
+ case REG_R11:
+ case REG_R12:
+ case REG_R13:
+ case REG_R14:
+ case REG_R15:
if(ctxt->asmode != 64)
return Yxxx;
- case D_SP:
- case D_BP:
- case D_SI:
- case D_DI:
+ case REG_SP:
+ case REG_BP:
+ case REG_SI:
+ case REG_DI:
return Yrl;
- case D_F0+0:
+ case REG_F0+0:
return Yf0;
- case D_F0+1:
- case D_F0+2:
- case D_F0+3:
- case D_F0+4:
- case D_F0+5:
- case D_F0+6:
- case D_F0+7:
+ case REG_F0+1:
+ case REG_F0+2:
+ case REG_F0+3:
+ case REG_F0+4:
+ case REG_F0+5:
+ case REG_F0+6:
+ case REG_F0+7:
return Yrf;
- case D_M0+0:
- case D_M0+1:
- case D_M0+2:
- case D_M0+3:
- case D_M0+4:
- case D_M0+5:
- case D_M0+6:
- case D_M0+7:
+ case REG_M0+0:
+ case REG_M0+1:
+ case REG_M0+2:
+ case REG_M0+3:
+ case REG_M0+4:
+ case REG_M0+5:
+ case REG_M0+6:
+ case REG_M0+7:
return Ymr;
- case D_X0+0:
- case D_X0+1:
- case D_X0+2:
- case D_X0+3:
- case D_X0+4:
- case D_X0+5:
- case D_X0+6:
- case D_X0+7:
- case D_X0+8:
- case D_X0+9:
- case D_X0+10:
- case D_X0+11:
- case D_X0+12:
- case D_X0+13:
- case D_X0+14:
- case D_X0+15:
+ case REG_X0+0:
+ case REG_X0+1:
+ case REG_X0+2:
+ case REG_X0+3:
+ case REG_X0+4:
+ case REG_X0+5:
+ case REG_X0+6:
+ case REG_X0+7:
+ case REG_X0+8:
+ case REG_X0+9:
+ case REG_X0+10:
+ case REG_X0+11:
+ case REG_X0+12:
+ case REG_X0+13:
+ case REG_X0+14:
+ case REG_X0+15:
return Yxr;
- case D_NONE:
- return Ynone;
-
- case D_CS: return Ycs;
- case D_SS: return Yss;
- case D_DS: return Yds;
- case D_ES: return Yes;
- case D_FS: return Yfs;
- case D_GS: return Ygs;
- case D_TLS: return Ytls;
-
- case D_GDTR: return Ygdtr;
- case D_IDTR: return Yidtr;
- case D_LDTR: return Yldtr;
- case D_MSW: return Ymsw;
- case D_TASK: return Ytask;
-
- case D_CR+0: return Ycr0;
- case D_CR+1: return Ycr1;
- case D_CR+2: return Ycr2;
- case D_CR+3: return Ycr3;
- case D_CR+4: return Ycr4;
- case D_CR+5: return Ycr5;
- case D_CR+6: return Ycr6;
- case D_CR+7: return Ycr7;
- case D_CR+8: return Ycr8;
-
- case D_DR+0: return Ydr0;
- case D_DR+1: return Ydr1;
- case D_DR+2: return Ydr2;
- case D_DR+3: return Ydr3;
- case D_DR+4: return Ydr4;
- case D_DR+5: return Ydr5;
- case D_DR+6: return Ydr6;
- case D_DR+7: return Ydr7;
-
- case D_TR+0: return Ytr0;
- case D_TR+1: return Ytr1;
- case D_TR+2: return Ytr2;
- case D_TR+3: return Ytr3;
- case D_TR+4: return Ytr4;
- case D_TR+5: return Ytr5;
- case D_TR+6: return Ytr6;
- case D_TR+7: return Ytr7;
-
- case D_EXTERN:
- case D_STATIC:
- case D_AUTO:
- case D_PARAM:
- return Ym;
-
- case D_CONST:
- case D_ADDR:
- if(a->sym == nil) {
- v = a->offset;
- if(v == 0)
- return Yi0;
- if(v == 1)
- return Yi1;
- if(v >= -128 && v <= 127)
- return Yi8;
- l = v;
- if((vlong)l == v)
- return Ys32; /* can sign extend */
- if((v>>32) == 0)
- return Yi32; /* unsigned */
- return Yi64;
- }
- return Yi32;
+ case REG_CS: return Ycs;
+ case REG_SS: return Yss;
+ case REG_DS: return Yds;
+ case REG_ES: return Yes;
+ case REG_FS: return Yfs;
+ case REG_GS: return Ygs;
+ case REG_TLS: return Ytls;
+
+ case REG_GDTR: return Ygdtr;
+ case REG_IDTR: return Yidtr;
+ case REG_LDTR: return Yldtr;
+ case REG_MSW: return Ymsw;
+ case REG_TASK: return Ytask;
+
+ case REG_CR+0: return Ycr0;
+ case REG_CR+1: return Ycr1;
+ case REG_CR+2: return Ycr2;
+ case REG_CR+3: return Ycr3;
+ case REG_CR+4: return Ycr4;
+ case REG_CR+5: return Ycr5;
+ case REG_CR+6: return Ycr6;
+ case REG_CR+7: return Ycr7;
+ case REG_CR+8: return Ycr8;
+
+ case REG_DR+0: return Ydr0;
+ case REG_DR+1: return Ydr1;
+ case REG_DR+2: return Ydr2;
+ case REG_DR+3: return Ydr3;
+ case REG_DR+4: return Ydr4;
+ case REG_DR+5: return Ydr5;
+ case REG_DR+6: return Ydr6;
+ case REG_DR+7: return Ydr7;
+
+ case REG_TR+0: return Ytr0;
+ case REG_TR+1: return Ytr1;
+ case REG_TR+2: return Ytr2;
+ case REG_TR+3: return Ytr3;
+ case REG_TR+4: return Ytr4;
+ case REG_TR+5: return Ytr5;
+ case REG_TR+6: return Ytr6;
+ case REG_TR+7: return Ytr7;
- case D_BRANCH:
- return Ybr;
}
return Yxxx;
}
default:
goto bad;
- case D_NONE:
+ case REG_NONE:
i = 4 << 3;
goto bas;
- case D_R8:
- case D_R9:
- case D_R10:
- case D_R11:
- case D_R12:
- case D_R13:
- case D_R14:
- case D_R15:
+ case REG_R8:
+ case REG_R9:
+ case REG_R10:
+ case REG_R11:
+ case REG_R12:
+ case REG_R13:
+ case REG_R14:
+ case REG_R15:
if(ctxt->asmode != 64)
goto bad;
- case D_AX:
- case D_CX:
- case D_DX:
- case D_BX:
- case D_BP:
- case D_SI:
- case D_DI:
+ case REG_AX:
+ case REG_CX:
+ case REG_DX:
+ case REG_BX:
+ case REG_BP:
+ case REG_SI:
+ case REG_DI:
i = reg[index] << 3;
break;
}
switch(base) {
default:
goto bad;
- case D_NONE: /* must be mod=00 */
+ case REG_NONE: /* must be mod=00 */
i |= 5;
break;
- case D_R8:
- case D_R9:
- case D_R10:
- case D_R11:
- case D_R12:
- case D_R13:
- case D_R14:
- case D_R15:
+ case REG_R8:
+ case REG_R9:
+ case REG_R10:
+ case REG_R11:
+ case REG_R12:
+ case REG_R13:
+ case REG_R14:
+ case REG_R15:
if(ctxt->asmode != 64)
goto bad;
- case D_AX:
- case D_CX:
- case D_DX:
- case D_BX:
- case D_SP:
- case D_BP:
- case D_SI:
- case D_DI:
+ case REG_AX:
+ case REG_CX:
+ case REG_DX:
+ case REG_BX:
+ case REG_SP:
+ case REG_BP:
+ case REG_SI:
+ case REG_DI:
i |= reg[base];
break;
}
static vlong
vaddr(Link *ctxt, Prog *p, Addr *a, Reloc *r)
{
- int t;
- vlong v;
LSym *s;
USED(p);
if(r != nil)
memset(r, 0, sizeof *r);
- t = a->type;
- v = a->offset;
- if(t == D_ADDR)
- t = a->index;
- switch(t) {
- case D_STATIC:
- case D_EXTERN:
+ switch(a->name) {
+ case NAME_STATIC:
+ case NAME_EXTERN:
s = a->sym;
if(r == nil) {
ctxt->diag("need reloc for %D", a);
}
r->off = -1; // caller must fill in
r->sym = s;
- r->add = v;
- v = 0;
+ r->add = a->offset;
if(s->type == STLSBSS) {
r->xadd = r->add - r->siz;
r->type = R_TLS;
r->xsym = s;
}
- break;
+ return 0;
+ }
- case D_INDIR+D_TLS:
+ if((a->type == TYPE_MEM || a->type == TYPE_ADDR) && a->reg == REG_TLS) {
if(r == nil) {
ctxt->diag("need reloc for %D", a);
sysfatal("reloc");
r->type = R_TLS_LE;
r->siz = 4;
r->off = -1; // caller must fill in
- r->add = v;
- v = 0;
- break;
+ r->add = a->offset;
+ return 0;
}
- return v;
+
+ return a->offset;
}
static void
asmandsz(Link *ctxt, Prog *p, Addr *a, int r, int rex, int m64)
{
int32 v;
- int t, scale;
+ int base;
Reloc rel;
USED(m64);
rex &= (0x40 | Rxr);
v = a->offset;
- t = a->type;
rel.siz = 0;
- if(a->index != D_NONE && a->index != D_TLS) {
- if(t < D_INDIR) {
- switch(t) {
- default:
+
+ switch(a->type) {
+ case TYPE_ADDR:
+ if(a->name == NAME_NONE)
+ ctxt->diag("unexpected TYPE_ADDR with NAME_NONE");
+ if(a->index == REG_TLS)
+ ctxt->diag("unexpected TYPE_ADDR with index==REG_TLS");
+ goto bad;
+
+ case TYPE_REG:
+ if(a->reg < REG_AL || REG_X0+15 < a->reg)
+ goto bad;
+ if(v)
+ goto bad;
+ *ctxt->andptr++ = (3 << 6) | (reg[a->reg] << 0) | (r << 3);
+ ctxt->rexflag |= (regrex[a->reg] & (0x40 | Rxb)) | rex;
+ return;
+ }
+
+ if(a->type != TYPE_MEM)
+ goto bad;
+
+ if(a->index != REG_NONE && a->index != REG_TLS) {
+ base = a->reg;
+ switch(a->name) {
+ case NAME_EXTERN:
+ case NAME_STATIC:
+ if(!isextern(a->sym))
goto bad;
- case D_EXTERN:
- case D_STATIC:
- if(!isextern(a->sym))
- goto bad;
- t = D_NONE;
- v = vaddr(ctxt, p, a, &rel);
- break;
- case D_AUTO:
- case D_PARAM:
- t = D_SP;
- break;
- }
- } else
- t -= D_INDIR;
- ctxt->rexflag |= (regrex[(int)a->index] & Rxx) | (regrex[t] & Rxb) | rex;
- if(t == D_NONE) {
+ base = REG_NONE;
+ v = vaddr(ctxt, p, a, &rel);
+ break;
+ case NAME_AUTO:
+ case NAME_PARAM:
+ base = REG_SP;
+ break;
+ }
+
+ ctxt->rexflag |= (regrex[(int)a->index] & Rxx) | (regrex[base] & Rxb) | rex;
+ if(base == REG_NONE) {
*ctxt->andptr++ = (0 << 6) | (4 << 0) | (r << 3);
- asmidx(ctxt, a->scale, a->index, t);
+ asmidx(ctxt, a->scale, a->index, base);
goto putrelv;
}
- if(v == 0 && rel.siz == 0 && t != D_BP && t != D_R13) {
+ if(v == 0 && rel.siz == 0 && base != REG_BP && base != REG_R13) {
*ctxt->andptr++ = (0 << 6) | (4 << 0) | (r << 3);
- asmidx(ctxt, a->scale, a->index, t);
+ asmidx(ctxt, a->scale, a->index, base);
return;
}
if(v >= -128 && v < 128 && rel.siz == 0) {
*ctxt->andptr++ = (1 << 6) | (4 << 0) | (r << 3);
- asmidx(ctxt, a->scale, a->index, t);
+ asmidx(ctxt, a->scale, a->index, base);
*ctxt->andptr++ = v;
return;
}
*ctxt->andptr++ = (2 << 6) | (4 << 0) | (r << 3);
- asmidx(ctxt, a->scale, a->index, t);
+ asmidx(ctxt, a->scale, a->index, base);
goto putrelv;
}
- if(t >= D_AL && t <= D_X0+15) {
- if(v)
- goto bad;
- *ctxt->andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3);
- ctxt->rexflag |= (regrex[t] & (0x40 | Rxb)) | rex;
- return;
- }
-
- scale = a->scale;
- if(t < D_INDIR) {
- switch(a->type) {
- default:
- goto bad;
- case D_STATIC:
- case D_EXTERN:
- t = D_NONE;
- v = vaddr(ctxt, p, a, &rel);
- break;
- case D_AUTO:
- case D_PARAM:
- t = D_SP;
- break;
- }
- scale = 1;
- } else
- t -= D_INDIR;
- if(t == D_TLS)
+
+ base = a->reg;
+ switch(a->name) {
+ case NAME_STATIC:
+ case NAME_EXTERN:
+ if(a->sym == nil)
+ ctxt->diag("bad addr: %P", p);
+ base = REG_NONE;
v = vaddr(ctxt, p, a, &rel);
+ break;
+ case NAME_AUTO:
+ case NAME_PARAM:
+ base = REG_SP;
+ break;
+ }
- ctxt->rexflag |= (regrex[t] & Rxb) | rex;
- if(t == D_NONE || (D_CS <= t && t <= D_GS) || t == D_TLS) {
- if((a->sym == nil || !isextern(a->sym)) && t == D_NONE && (a->type == D_STATIC || a->type == D_EXTERN) || ctxt->asmode != 64) {
+ if(base == REG_TLS)
+ v = vaddr(ctxt, p, a, &rel);
+
+ ctxt->rexflag |= (regrex[base] & Rxb) | rex;
+ if(base == REG_NONE || (REG_CS <= base && base <= REG_GS) || base == REG_TLS) {
+ if((a->sym == nil || !isextern(a->sym)) && base == REG_NONE && (a->name == NAME_STATIC || a->name == NAME_EXTERN) || ctxt->asmode != 64) {
*ctxt->andptr++ = (0 << 6) | (5 << 0) | (r << 3);
goto putrelv;
}
*ctxt->andptr++ = (0 << 6) | (4 << 3) | (5 << 0); /* DS:d32 */
goto putrelv;
}
- if(t == D_SP || t == D_R12) {
+
+ if(base == REG_SP || base == REG_R12) {
if(v == 0) {
- *ctxt->andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3);
- asmidx(ctxt, scale, D_NONE, t);
+ *ctxt->andptr++ = (0 << 6) | (reg[base] << 0) | (r << 3);
+ asmidx(ctxt, a->scale, REG_NONE, base);
return;
}
if(v >= -128 && v < 128) {
- *ctxt->andptr++ = (1 << 6) | (reg[t] << 0) | (r << 3);
- asmidx(ctxt, scale, D_NONE, t);
+ *ctxt->andptr++ = (1 << 6) | (reg[base] << 0) | (r << 3);
+ asmidx(ctxt, a->scale, REG_NONE, base);
*ctxt->andptr++ = v;
return;
}
- *ctxt->andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3);
- asmidx(ctxt, scale, D_NONE, t);
+ *ctxt->andptr++ = (2 << 6) | (reg[base] << 0) | (r << 3);
+ asmidx(ctxt, a->scale, REG_NONE, base);
goto putrelv;
}
- if(t >= D_AX && t <= D_R15) {
- if(a->index == D_TLS) {
+
+ if(REG_AX <= base && base <= REG_R15) {
+ if(a->index == REG_TLS) {
memset(&rel, 0, sizeof rel);
rel.type = R_TLS_IE;
rel.siz = 4;
rel.add = v;
v = 0;
}
- if(v == 0 && rel.siz == 0 && t != D_BP && t != D_R13) {
- *ctxt->andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3);
+ if(v == 0 && rel.siz == 0 && base != REG_BP && base != REG_R13) {
+ *ctxt->andptr++ = (0 << 6) | (reg[base] << 0) | (r << 3);
return;
}
if(v >= -128 && v < 128 && rel.siz == 0) {
- ctxt->andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3);
+ ctxt->andptr[0] = (1 << 6) | (reg[base] << 0) | (r << 3);
ctxt->andptr[1] = v;
ctxt->andptr += 2;
return;
}
- *ctxt->andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3);
+ *ctxt->andptr++ = (2 << 6) | (reg[base] << 0) | (r << 3);
goto putrelv;
}
+
goto bad;
putrelv:
static void
asmand(Link *ctxt, Prog *p, Addr *a, Addr *ra)
{
- asmandsz(ctxt, p, a, reg[ra->type], regrex[ra->type], 0);
+ asmandsz(ctxt, p, a, reg[ra->reg], regrex[ra->reg], 0);
}
static void
static void
bytereg(Addr *a, uint8 *t)
{
- if(a->index == D_NONE && (a->type >= D_AX && a->type <= D_R15)) {
- a->type = D_AL + (a->type-D_AX);
+ if(a->type == TYPE_REG && a->index == REG_NONE && (REG_AX <= a->reg && a->reg <= REG_R15)) {
+ a->reg += REG_AL - REG_AX;
*t = 0;
}
}
static int
isax(Addr *a)
{
-
- switch(a->type) {
- case D_AX:
- case D_AL:
- case D_AH:
- case D_INDIR+D_AX:
+ switch(a->reg) {
+ case REG_AX:
+ case REG_AL:
+ case REG_AH:
return 1;
}
- if(a->index == D_AX)
+ if(a->index == REG_AX)
return 1;
return 0;
}
static void
subreg(Prog *p, int from, int to)
{
-
- if(0 /*debug['Q']*/)
+ if(0 /* debug['Q'] */)
print("\n%P s/%R/%R/\n", p, from, to);
- if(p->from.type == from)
- p->from.type = to;
- if(p->to.type == from)
- p->to.type = to;
+ if(p->from.reg == from) {
+ p->from.reg = to;
+ p->ft = 0;
+ }
+ if(p->to.reg == from) {
+ p->to.reg = to;
+ p->tt = 0;
+ }
- if(p->from.index == from)
+ if(p->from.index == from) {
p->from.index = to;
- if(p->to.index == from)
+ p->ft = 0;
+ }
+ if(p->to.index == from) {
p->to.index = to;
+ p->tt = 0;
+ }
- from += D_INDIR;
- if(p->from.type == from)
- p->from.type = to+D_INDIR;
- if(p->to.type == from)
- p->to.type = to+D_INDIR;
-
- if(0 /*debug['Q']*/)
+ if(0 /* debug['Q'] */)
print("%P\n", p);
}
ctxt->diag("asmins: missing op %P", p);
return;
}
-
+
pre = prefixof(ctxt, &p->from);
if(pre)
*ctxt->andptr++ = pre;
case Zaut_r:
*ctxt->andptr++ = 0x8d; /* leal */
- if(p->from.type != D_ADDR)
+ if(p->from.type != TYPE_ADDR)
ctxt->diag("asmins: Zaut sb type ADDR");
- p->from.type = p->from.index;
- p->from.index = D_NONE;
+ p->from.type = TYPE_MEM;
asmand(ctxt, p, &p->from, &p->to);
- p->from.index = p->from.type;
- p->from.type = D_ADDR;
+ p->from.type = TYPE_ADDR;
break;
case Zm_o:
break;
case Zib_rp:
- ctxt->rexflag |= regrex[p->to.type] & (Rxb|0x40);
- *ctxt->andptr++ = op + reg[p->to.type];
+ ctxt->rexflag |= regrex[p->to.reg] & (Rxb|0x40);
+ *ctxt->andptr++ = op + reg[p->to.reg];
*ctxt->andptr++ = vaddr(ctxt, p, &p->from, nil);
break;
case Zil_rp:
- ctxt->rexflag |= regrex[p->to.type] & Rxb;
- *ctxt->andptr++ = op + reg[p->to.type];
+ ctxt->rexflag |= regrex[p->to.reg] & Rxb;
+ *ctxt->andptr++ = op + reg[p->to.reg];
if(o->prefix == Pe) {
v = vaddr(ctxt, p, &p->from, nil);
*ctxt->andptr++ = v;
case Zo_iw:
*ctxt->andptr++ = op;
- if(p->from.type != D_NONE){
+ if(p->from.type != TYPE_NONE){
v = vaddr(ctxt, p, &p->from, nil);
*ctxt->andptr++ = v;
*ctxt->andptr++ = v>>8;
//p->mark |= 0100;
//print("zero: %llux %P\n", v, p);
ctxt->rexflag &= ~(0x40|Rxw);
- ctxt->rexflag |= regrex[p->to.type] & Rxb;
- *ctxt->andptr++ = 0xb8 + reg[p->to.type];
+ ctxt->rexflag |= regrex[p->to.reg] & Rxb;
+ *ctxt->andptr++ = 0xb8 + reg[p->to.reg];
if(rel.type != 0) {
r = addrel(ctxt->cursym);
*r = rel;
put4(ctxt, v);
}else{ /* need all 8 */
//print("all: %llux %P\n", v, p);
- ctxt->rexflag |= regrex[p->to.type] & Rxb;
- *ctxt->andptr++ = op + reg[p->to.type];
+ ctxt->rexflag |= regrex[p->to.reg] & Rxb;
+ *ctxt->andptr++ = op + reg[p->to.reg];
if(rel.type != 0) {
r = addrel(ctxt->cursym);
*r = rel;
break;
case Z_rp:
- ctxt->rexflag |= regrex[p->to.type] & (Rxb|0x40);
- *ctxt->andptr++ = op + reg[p->to.type];
+ ctxt->rexflag |= regrex[p->to.reg] & (Rxb|0x40);
+ *ctxt->andptr++ = op + reg[p->to.reg];
break;
case Zrp_:
- ctxt->rexflag |= regrex[p->from.type] & (Rxb|0x40);
- *ctxt->andptr++ = op + reg[p->from.type];
+ ctxt->rexflag |= regrex[p->from.reg] & (Rxb|0x40);
+ *ctxt->andptr++ = op + reg[p->from.reg];
break;
case Zclr:
* instruction with the operands renamed.
*/
pp = *p;
- z = p->from.type;
- if(z >= D_BP && z <= D_DI) {
- if(isax(&p->to) || p->to.type == D_NONE) {
+ z = p->from.reg;
+ if(p->from.type == TYPE_REG && z >= REG_BP && z <= REG_DI) {
+ if(isax(&p->to) || p->to.type == TYPE_NONE) {
// We certainly don't want to exchange
// with AX if the op is MUL or DIV.
*ctxt->andptr++ = 0x87; /* xchg lhs,bx */
- asmando(ctxt, p, &p->from, reg[D_BX]);
- subreg(&pp, z, D_BX);
+ asmando(ctxt, p, &p->from, reg[REG_BX]);
+ subreg(&pp, z, REG_BX);
doasm(ctxt, &pp);
*ctxt->andptr++ = 0x87; /* xchg lhs,bx */
- asmando(ctxt, p, &p->from, reg[D_BX]);
+ asmando(ctxt, p, &p->from, reg[REG_BX]);
} else {
*ctxt->andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */
- subreg(&pp, z, D_AX);
+ subreg(&pp, z, REG_AX);
doasm(ctxt, &pp);
*ctxt->andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */
}
return;
}
- z = p->to.type;
- if(z >= D_BP && z <= D_DI) {
+ z = p->to.reg;
+ if(p->to.type == TYPE_REG && z >= REG_BP && z <= REG_DI) {
if(isax(&p->from)) {
*ctxt->andptr++ = 0x87; /* xchg rhs,bx */
- asmando(ctxt, p, &p->to, reg[D_BX]);
- subreg(&pp, z, D_BX);
+ asmando(ctxt, p, &p->to, reg[REG_BX]);
+ subreg(&pp, z, REG_BX);
doasm(ctxt, &pp);
*ctxt->andptr++ = 0x87; /* xchg rhs,bx */
- asmando(ctxt, p, &p->to, reg[D_BX]);
+ asmando(ctxt, p, &p->to, reg[REG_BX]);
} else {
*ctxt->andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */
- subreg(&pp, z, D_AX);
+ subreg(&pp, z, REG_AX);
doasm(ctxt, &pp);
*ctxt->andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */
}
return;
}
}
- ctxt->diag("doasm: notfound from=%ux to=%ux %P", p->from.type, p->to.type, p);
+ ctxt->diag("doasm: notfound ft=%d tt=%d %P %d %d", p->ft, p->tt, p, oclass(ctxt, &p->from), oclass(ctxt, &p->to));
return;
mfound:
*ctxt->andptr++ = t[0];
*ctxt->andptr++ = t[1];
asmando(ctxt, p, &p->to, t[2]);
- ctxt->rexflag |= regrex[p->from.type] & (Rxr|0x40);
+ ctxt->rexflag |= regrex[p->from.reg] & (Rxr|0x40);
break;
case 4: /* m,r - 2op */
*ctxt->andptr++ = t[0];
*ctxt->andptr++ = t[1];
asmando(ctxt, p, &p->from, t[2]);
- ctxt->rexflag |= regrex[p->to.type] & (Rxr|0x40);
+ ctxt->rexflag |= regrex[p->to.reg] & (Rxr|0x40);
break;
case 5: /* load full pointer, trash heap */
switch(p->to.index) {
default:
goto bad;
- case D_DS:
+ case REG_DS:
*ctxt->andptr++ = 0xc5;
break;
- case D_SS:
+ case REG_SS:
*ctxt->andptr++ = 0x0f;
*ctxt->andptr++ = 0xb2;
break;
- case D_ES:
+ case REG_ES:
*ctxt->andptr++ = 0xc4;
break;
- case D_FS:
+ case REG_FS:
*ctxt->andptr++ = 0x0f;
*ctxt->andptr++ = 0xb4;
break;
- case D_GS:
+ case REG_GS:
*ctxt->andptr++ = 0x0f;
*ctxt->andptr++ = 0xb5;
break;
*ctxt->andptr++ = Pe;
t++;
}
- z = p->from.type;
- switch(z) {
+ switch(p->from.type) {
default:
goto bad;
- case D_CONST:
+ case TYPE_CONST:
*ctxt->andptr++ = 0x0f;
*ctxt->andptr++ = t[0];
asmandsz(ctxt, p, &p->to, reg[(int)p->from.index], regrex[(int)p->from.index], 0);
*ctxt->andptr++ = p->from.offset;
break;
- case D_CL:
- case D_CX:
- *ctxt->andptr++ = 0x0f;
- *ctxt->andptr++ = t[1];
- asmandsz(ctxt, p, &p->to, reg[(int)p->from.index], regrex[(int)p->from.index], 0);
- break;
+ case TYPE_REG:
+ switch(p->from.reg) {
+ default:
+ goto bad;
+ case REG_CL:
+ case REG_CX:
+ *ctxt->andptr++ = 0x0f;
+ *ctxt->andptr++ = t[1];
+ asmandsz(ctxt, p, &p->to, reg[(int)p->from.index], regrex[(int)p->from.index], 0);
+ break;
+ }
}
break;
if(ctxt->plan9privates == nil)
ctxt->plan9privates = linklookup(ctxt, "_privates", 0);
memset(&pp.from, 0, sizeof pp.from);
- pp.from.type = D_EXTERN;
+ pp.from.type = TYPE_MEM;
+ pp.from.name = NAME_EXTERN;
pp.from.sym = ctxt->plan9privates;
pp.from.offset = 0;
- pp.from.index = D_NONE;
+ pp.from.index = REG_NONE;
ctxt->rexflag |= Pw;
*ctxt->andptr++ = 0x8B;
asmand(ctxt, p, &pp.from, &p->to);
case Hsolaris: // TODO(rsc): Delete Hsolaris from list. Should not use this code. See progedit in obj6.c.
// TLS base is 0(FS).
pp.from = p->from;
- pp.from.type = D_INDIR+D_NONE;
+ pp.from.type = TYPE_MEM;
+ pp.from.name = NAME_NONE;
+ pp.from.reg = REG_NONE;
pp.from.offset = 0;
- pp.from.index = D_NONE;
+ pp.from.index = REG_NONE;
pp.from.scale = 0;
ctxt->rexflag |= Pw;
*ctxt->andptr++ = 0x64; // FS
case Hwindows:
// Windows TLS base is always 0x28(GS).
pp.from = p->from;
- pp.from.type = D_INDIR+D_GS;
+ pp.from.type = TYPE_MEM;
+ pp.from.name = NAME_NONE;
+ pp.from.reg = REG_GS;
pp.from.offset = 0x28;
- pp.from.index = D_NONE;
+ pp.from.index = REG_NONE;
pp.from.scale = 0;
ctxt->rexflag |= Pw;
*ctxt->andptr++ = 0x65; // GS
static void
nacltrunc(Link *ctxt, int reg)
{
- if(reg >= D_R8)
+ if(reg >= REG_R8)
*ctxt->andptr++ = 0x45;
- reg = (reg - D_AX) & 7;
+ reg = (reg - REG_AX) & 7;
*ctxt->andptr++ = 0x89;
*ctxt->andptr++ = (3<<6) | (reg<<3) | reg;
}
return;
}
if(p->as != ALEAQ && p->as != ALEAL) {
- if(p->from.index != D_NONE && p->from.scale > 0)
+ if(p->from.index != TYPE_NONE && p->from.scale > 0)
nacltrunc(ctxt, p->from.index);
- if(p->to.index != D_NONE && p->to.scale > 0)
+ if(p->to.index != TYPE_NONE && p->to.scale > 0)
nacltrunc(ctxt, p->to.index);
}
switch(p->as) {
return;
case ACALL:
case AJMP:
- if(D_AX <= p->to.type && p->to.type <= D_DI) {
+ if(p->to.type == TYPE_REG && REG_AX <= p->to.reg && p->to.reg <= REG_DI) {
// ANDL $~31, reg
*ctxt->andptr++ = 0x83;
- *ctxt->andptr++ = 0xe0 | (p->to.type - D_AX);
+ *ctxt->andptr++ = 0xe0 | (p->to.reg - REG_AX);
*ctxt->andptr++ = 0xe0;
// ADDQ R15, reg
*ctxt->andptr++ = 0x4c;
*ctxt->andptr++ = 0x01;
- *ctxt->andptr++ = 0xf8 | (p->to.type - D_AX);
+ *ctxt->andptr++ = 0xf8 | (p->to.reg - REG_AX);
}
- if(D_R8 <= p->to.type && p->to.type <= D_R15) {
+ if(p->to.type == TYPE_REG && REG_R8 <= p->to.reg && p->to.reg <= REG_R15) {
// ANDL $~31, reg
*ctxt->andptr++ = 0x41;
*ctxt->andptr++ = 0x83;
- *ctxt->andptr++ = 0xe0 | (p->to.type - D_R8);
+ *ctxt->andptr++ = 0xe0 | (p->to.reg - REG_R8);
*ctxt->andptr++ = 0xe0;
// ADDQ R15, reg
*ctxt->andptr++ = 0x4d;
*ctxt->andptr++ = 0x01;
- *ctxt->andptr++ = 0xf8 | (p->to.type - D_R8);
+ *ctxt->andptr++ = 0xf8 | (p->to.reg - REG_R8);
}
break;
case AINT:
r->add -= p->pc + n - (r->off + r->siz);
}
- if(ctxt->headtype == Hnacl && p->as != ACMPL && p->as != ACMPQ) {
- switch(p->to.type) {
- case D_SP:
+ if(ctxt->headtype == Hnacl && p->as != ACMPL && p->as != ACMPQ && p->to.type == TYPE_REG) {
+ switch(p->to.reg) {
+ case REG_SP:
memmove(ctxt->andptr, naclspfix, sizeof naclspfix);
ctxt->andptr += sizeof naclspfix;
break;
- case D_BP:
+ case REG_BP:
memmove(ctxt->andptr, naclbpfix, sizeof naclbpfix);
ctxt->andptr += sizeof naclbpfix;
break;
uchar op[13];
};
+static Optab* opindex[ALAST+1];
+
enum
{
Yxxx = 0,
Ym,
Ybr,
Ycol,
+ Ytextsize,
Ytls,
Ycs, Yss, Yds, Yes, Yfs, Ygs,
};
static uchar ycover[Ymax*Ymax];
-static int reg[D_NONE];
+static int reg[MAXREG];
static void asmins(Link *ctxt, Prog *p);
static uchar ynone[] =
};
static uchar ytext[] =
{
- Ymb, Yi32, Zpseudo,1,
+ Ymb, Ytextsize, Zpseudo,1,
0
};
static uchar ynop[] =
{ ADIVW, ydivl, Pe, {0xf7,(06)} },
{ AENTER }, /* botch */
{ AGLOBL },
- { AGOK },
- { AHISTORY },
{ AHLT, ynone, Px, {0xf4} },
{ AIDIVB, ydivb, Pb, {0xf6,(07)} },
{ AIDIVL, ydivl, Px, {0xf7,(07)} },
{ AMULB, ydivb, Pb, {0xf6,(04)} },
{ AMULL, ydivl, Px, {0xf7,(04)} },
{ AMULW, ydivl, Pe, {0xf7,(04)} },
- { ANAME },
{ ANEGB, yscond, Px, {0xf6,(03)} },
- { ANEGL, yscond, Px, {0xf7,(03)} },
- { ANEGW, yscond, Pe, {0xf7,(03)} },
+ { ANEGL, yscond, Px, {0xf7,(03)} }, // TODO(rsc): yscond is wrong here.
+ { ANEGW, yscond, Pe, {0xf7,(03)} }, // TODO(rsc): yscond is wrong here.
{ ANOP, ynop, Px, {0,0} },
{ ANOTB, yscond, Px, {0xf6,(02)} },
- { ANOTL, yscond, Px, {0xf7,(02)} },
- { ANOTW, yscond, Pe, {0xf7,(02)} },
+ { ANOTL, yscond, Px, {0xf7,(02)} }, // TODO(rsc): yscond is wrong here.
+ { ANOTW, yscond, Pe, {0xf7,(02)} }, // TODO(rsc): yscond is wrong here.
{ AORB, yxorb, Pb, {0x0c,0x80,(01),0x08,0x0a} },
{ AORL, yxorl, Px, {0x83,(01),0x0d,0x81,(01),0x09,0x0b} },
{ AORW, yxorl, Pe, {0x83,(01),0x0d,0x81,(01),0x09,0x0b} },
{ AFYL2X, ynone, Px, {0xd9, 0xf1} },
{ AFYL2XP1, ynone, Px, {0xd9, 0xf9} },
{ AEND },
- { ADYNT_ },
- { AINIT_ },
- { ASIGNAME },
{ ACMPXCHGB, yrb_mb, Pm, {0xb0} },
{ ACMPXCHGL, yrl_ml, Pm, {0xb1} },
{ ACMPXCHGW, yrl_ml, Pm, {0xb1} },
- { ACMPXCHG8B, yscond, Pm, {0xc7,(01)} },
+ { ACMPXCHG8B, yscond, Pm, {0xc7,(01)} }, // TODO(rsc): yscond is wrong here.
{ ACPUID, ynone, Pm, {0xa2} },
{ ARDTSC, ynone, Pm, {0x31} },
instinit();
for(p = s->text; p != nil; p = p->link) {
- n = 0;
- if(p->to.type == D_BRANCH)
+ if(p->to.type == TYPE_BRANCH)
if(p->pcond == nil)
p->pcond = p;
- if((q = p->pcond) != nil)
- if(q->back != 2)
- n = 1;
- p->back = n;
if(p->as == AADJSP) {
- p->to.type = D_SP;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_SP;
v = -p->from.offset;
p->from.offset = v;
p->as = AADDL;
p->back |= 1; // backward jump
if(p->as == AADJSP) {
- p->to.type = D_SP;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_SP;
v = -p->from.offset;
p->from.offset = v;
p->as = AADDL;
static void
instinit(void)
{
- int i;
+ int i, c;
- for(i=1; optab[i].as; i++)
- if(i != optab[i].as)
- sysfatal("phase error in optab: at %A found %A", i, optab[i].as);
+ for(i=1; optab[i].as; i++) {
+ c = optab[i].as;
+ if(opindex[c] != nil)
+ sysfatal("phase error in optab: %d (%A)", i, c);
+ opindex[c] = &optab[i];
+ }
for(i=0; i<Ymax; i++)
ycover[i*Ymax + i] = 1;
ycover[Ym*Ymax + Yxm] = 1;
ycover[Yxr*Ymax + Yxm] = 1;
- for(i=0; i<D_NONE; i++) {
+ for(i=0; i<MAXREG; i++) {
reg[i] = -1;
- if(i >= D_AL && i <= D_BH)
- reg[i] = (i-D_AL) & 7;
- if(i >= D_AX && i <= D_DI)
- reg[i] = (i-D_AX) & 7;
- if(i >= D_F0 && i <= D_F0+7)
- reg[i] = (i-D_F0) & 7;
- if(i >= D_X0 && i <= D_X0+7)
- reg[i] = (i-D_X0) & 7;
+ if(i >= REG_AL && i <= REG_BH)
+ reg[i] = (i-REG_AL) & 7;
+ if(i >= REG_AX && i <= REG_DI)
+ reg[i] = (i-REG_AX) & 7;
+ if(i >= REG_F0 && i <= REG_F0+7)
+ reg[i] = (i-REG_F0) & 7;
+ if(i >= REG_X0 && i <= REG_X0+7)
+ reg[i] = (i-REG_X0) & 7;
}
}
static int
prefixof(Link *ctxt, Addr *a)
{
- switch(a->type) {
- case D_INDIR+D_CS:
- return 0x2e;
- case D_INDIR+D_DS:
- return 0x3e;
- case D_INDIR+D_ES:
- return 0x26;
- case D_INDIR+D_FS:
- return 0x64;
- case D_INDIR+D_GS:
- return 0x65;
- case D_INDIR+D_TLS:
- // NOTE: Systems listed here should be only systems that
- // support direct TLS references like 8(TLS) implemented as
- // direct references from FS or GS. Systems that require
- // the initial-exec model, where you load the TLS base into
- // a register and then index from that register, do not reach
- // this code and should not be listed.
- switch(ctxt->headtype) {
- default:
- sysfatal("unknown TLS base register for %s", headstr(ctxt->headtype));
- case Hdarwin:
- case Hdragonfly:
- case Hfreebsd:
- case Hnetbsd:
- case Hopenbsd:
- return 0x65; // GS
+ if(a->type == TYPE_MEM && a->name == NAME_NONE) {
+ switch(a->reg) {
+ case REG_CS:
+ return 0x2e;
+ case REG_DS:
+ return 0x3e;
+ case REG_ES:
+ return 0x26;
+ case REG_FS:
+ return 0x64;
+ case REG_GS:
+ return 0x65;
+ case REG_TLS:
+ // NOTE: Systems listed here should be only systems that
+ // support direct TLS references like 8(TLS) implemented as
+ // direct references from FS or GS. Systems that require
+ // the initial-exec model, where you load the TLS base into
+ // a register and then index from that register, do not reach
+ // this code and should not be listed.
+ switch(ctxt->headtype) {
+ default:
+ sysfatal("unknown TLS base register for %s", headstr(ctxt->headtype));
+ case Hdarwin:
+ case Hdragonfly:
+ case Hfreebsd:
+ case Hnetbsd:
+ case Hopenbsd:
+ return 0x65; // GS
+ }
}
}
return 0;
}
static int
-oclass(Addr *a)
+oclass(Link *ctxt, Addr *a)
{
int32 v;
- if((a->type >= D_INDIR && a->type < 2*D_INDIR) || a->index != D_NONE) {
- if(a->index != D_NONE && a->scale == 0) {
- if(a->type == D_ADDR) {
- switch(a->index) {
- case D_EXTERN:
- case D_STATIC:
- return Yi32;
- case D_AUTO:
- case D_PARAM:
- return Yiauto;
- }
- return Yxxx;
- }
- //if(a->type == D_INDIR+D_ADDR)
- // print("*Ycol\n");
+ // TODO(rsc): This special case is for SHRQ $3, AX:DX,
+ // which encodes as SHRQ $32(DX*0), AX.
+ // Similarly SHRQ CX, AX:DX is really SHRQ CX(DX*0), AX.
+ // Change encoding and remove.
+ if((a->type == TYPE_CONST || a->type == TYPE_REG) && a->index != REG_NONE && a->scale == 0)
+ return Ycol;
+
+ switch(a->type) {
+ case TYPE_NONE:
+ return Ynone;
+
+ case TYPE_BRANCH:
+ return Ybr;
+
+ case TYPE_INDIR:
+ // TODO(rsc): Why this is also Ycol is a mystery. Should split the two meanings.
+ if(a->name != NAME_NONE && a->reg == REG_NONE && a->index == REG_NONE && a->scale == 0)
return Ycol;
- }
+ return Yxxx;
+
+ case TYPE_MEM:
return Ym;
+
+ case TYPE_ADDR:
+ switch(a->name) {
+ case NAME_EXTERN:
+ case NAME_STATIC:
+ return Yi32;
+ case NAME_AUTO:
+ case NAME_PARAM:
+ return Yiauto;
+ }
+
+ // DUFFZERO/DUFFCOPY encoding forgot to set a->index
+ // and got Yi32 in an earlier version of this code.
+ // Keep doing that until we fix yduff etc.
+ if(a->sym != nil && strncmp(a->sym->name, "runtime.duff", 12) == 0)
+ return Yi32;
+
+ if(a->sym != nil || a->name != NAME_NONE)
+ ctxt->diag("unexpected addr: %D", a);
+ // fall through
+
+ case TYPE_CONST:
+ if(a->sym != nil)
+ ctxt->diag("TYPE_CONST with symbol: %D", a);
+
+ v = a->offset;
+ if(v == 0)
+ return Yi0;
+ if(v == 1)
+ return Yi1;
+ if(v >= -128 && v <= 127)
+ return Yi8;
+ return Yi32;
+
+ case TYPE_TEXTSIZE:
+ return Ytextsize;
+ }
+
+ if(a->type != TYPE_REG) {
+ ctxt->diag("unexpected addr1: type=%d %D", a->type, a);
+ return Yxxx;
}
- switch(a->type)
- {
- case D_AL:
+
+ switch(a->reg) {
+ case REG_AL:
return Yal;
- case D_AX:
+ case REG_AX:
return Yax;
- case D_CL:
- case D_DL:
- case D_BL:
- case D_AH:
- case D_CH:
- case D_DH:
- case D_BH:
+ case REG_CL:
+ case REG_DL:
+ case REG_BL:
+ case REG_AH:
+ case REG_CH:
+ case REG_DH:
+ case REG_BH:
return Yrb;
- case D_CX:
+ case REG_CX:
return Ycx;
- case D_DX:
- case D_BX:
+ case REG_DX:
+ case REG_BX:
return Yrx;
- case D_SP:
- case D_BP:
- case D_SI:
- case D_DI:
+ case REG_SP:
+ case REG_BP:
+ case REG_SI:
+ case REG_DI:
return Yrl;
- case D_F0+0:
+ case REG_F0+0:
return Yf0;
- case D_F0+1:
- case D_F0+2:
- case D_F0+3:
- case D_F0+4:
- case D_F0+5:
- case D_F0+6:
- case D_F0+7:
+ case REG_F0+1:
+ case REG_F0+2:
+ case REG_F0+3:
+ case REG_F0+4:
+ case REG_F0+5:
+ case REG_F0+6:
+ case REG_F0+7:
return Yrf;
- case D_X0+0:
- case D_X0+1:
- case D_X0+2:
- case D_X0+3:
- case D_X0+4:
- case D_X0+5:
- case D_X0+6:
- case D_X0+7:
+ case REG_X0+0:
+ case REG_X0+1:
+ case REG_X0+2:
+ case REG_X0+3:
+ case REG_X0+4:
+ case REG_X0+5:
+ case REG_X0+6:
+ case REG_X0+7:
return Yxr;
- case D_NONE:
- return Ynone;
-
- case D_CS: return Ycs;
- case D_SS: return Yss;
- case D_DS: return Yds;
- case D_ES: return Yes;
- case D_FS: return Yfs;
- case D_GS: return Ygs;
- case D_TLS: return Ytls;
-
- case D_GDTR: return Ygdtr;
- case D_IDTR: return Yidtr;
- case D_LDTR: return Yldtr;
- case D_MSW: return Ymsw;
- case D_TASK: return Ytask;
-
- case D_CR+0: return Ycr0;
- case D_CR+1: return Ycr1;
- case D_CR+2: return Ycr2;
- case D_CR+3: return Ycr3;
- case D_CR+4: return Ycr4;
- case D_CR+5: return Ycr5;
- case D_CR+6: return Ycr6;
- case D_CR+7: return Ycr7;
-
- case D_DR+0: return Ydr0;
- case D_DR+1: return Ydr1;
- case D_DR+2: return Ydr2;
- case D_DR+3: return Ydr3;
- case D_DR+4: return Ydr4;
- case D_DR+5: return Ydr5;
- case D_DR+6: return Ydr6;
- case D_DR+7: return Ydr7;
-
- case D_TR+0: return Ytr0;
- case D_TR+1: return Ytr1;
- case D_TR+2: return Ytr2;
- case D_TR+3: return Ytr3;
- case D_TR+4: return Ytr4;
- case D_TR+5: return Ytr5;
- case D_TR+6: return Ytr6;
- case D_TR+7: return Ytr7;
-
- case D_EXTERN:
- case D_STATIC:
- case D_AUTO:
- case D_PARAM:
- return Ym;
+ case REG_CS: return Ycs;
+ case REG_SS: return Yss;
+ case REG_DS: return Yds;
+ case REG_ES: return Yes;
+ case REG_FS: return Yfs;
+ case REG_GS: return Ygs;
+ case REG_TLS: return Ytls;
+
+ case REG_GDTR: return Ygdtr;
+ case REG_IDTR: return Yidtr;
+ case REG_LDTR: return Yldtr;
+ case REG_MSW: return Ymsw;
+ case REG_TASK: return Ytask;
+
+ case REG_CR+0: return Ycr0;
+ case REG_CR+1: return Ycr1;
+ case REG_CR+2: return Ycr2;
+ case REG_CR+3: return Ycr3;
+ case REG_CR+4: return Ycr4;
+ case REG_CR+5: return Ycr5;
+ case REG_CR+6: return Ycr6;
+ case REG_CR+7: return Ycr7;
+
+ case REG_DR+0: return Ydr0;
+ case REG_DR+1: return Ydr1;
+ case REG_DR+2: return Ydr2;
+ case REG_DR+3: return Ydr3;
+ case REG_DR+4: return Ydr4;
+ case REG_DR+5: return Ydr5;
+ case REG_DR+6: return Ydr6;
+ case REG_DR+7: return Ydr7;
+
+ case REG_TR+0: return Ytr0;
+ case REG_TR+1: return Ytr1;
+ case REG_TR+2: return Ytr2;
+ case REG_TR+3: return Ytr3;
+ case REG_TR+4: return Ytr4;
+ case REG_TR+5: return Ytr5;
+ case REG_TR+6: return Ytr6;
+ case REG_TR+7: return Ytr7;
- case D_CONST:
- case D_CONST2:
- case D_ADDR:
- if(a->sym == nil) {
- v = a->offset;
- if(v == 0)
- return Yi0;
- if(v == 1)
- return Yi1;
- if(v >= -128 && v <= 127)
- return Yi8;
- }
- return Yi32;
-
- case D_BRANCH:
- return Ybr;
}
return Yxxx;
}
default:
goto bad;
- case D_NONE:
+ case TYPE_NONE:
i = 4 << 3;
goto bas;
- case D_AX:
- case D_CX:
- case D_DX:
- case D_BX:
- case D_BP:
- case D_SI:
- case D_DI:
+ case REG_AX:
+ case REG_CX:
+ case REG_DX:
+ case REG_BX:
+ case REG_BP:
+ case REG_SI:
+ case REG_DI:
i = reg[index] << 3;
break;
}
switch(base) {
default:
goto bad;
- case D_NONE: /* must be mod=00 */
+ case REG_NONE: /* must be mod=00 */
i |= 5;
break;
- case D_AX:
- case D_CX:
- case D_DX:
- case D_BX:
- case D_SP:
- case D_BP:
- case D_SI:
- case D_DI:
+ case REG_AX:
+ case REG_CX:
+ case REG_DX:
+ case REG_BX:
+ case REG_SP:
+ case REG_BP:
+ case REG_SI:
+ case REG_DI:
i |= reg[base];
break;
}
static int32
vaddr(Link *ctxt, Prog *p, Addr *a, Reloc *r)
{
- int t;
- int32 v;
LSym *s;
USED(p);
if(r != nil)
memset(r, 0, sizeof *r);
- t = a->type;
- v = a->offset;
- if(t == D_ADDR)
- t = a->index;
- switch(t) {
- case D_STATIC:
- case D_EXTERN:
+ switch(a->name) {
+ case NAME_STATIC:
+ case NAME_EXTERN:
s = a->sym;
if(s != nil) {
if(r == nil) {
r->siz = 4;
r->off = -1;
r->sym = s;
- r->add = v;
- v = 0;
+ r->add = a->offset;
+ return 0;
}
- break;
+ return a->offset;
+ }
- case D_INDIR+D_TLS:
+ if((a->type == TYPE_MEM || a->type == TYPE_ADDR) && a->reg == REG_TLS) {
if(r == nil) {
ctxt->diag("need reloc for %D", a);
sysfatal("bad code");
r->type = R_TLS_LE;
r->siz = 4;
r->off = -1; // caller must fill in
- r->add = v;
- v = 0;
- break;
+ r->add = a->offset;
+ return 0;
}
- return v;
+
+ return a->offset;
}
static void
asmand(Link *ctxt, Prog *p, Addr *a, int r)
{
int32 v;
- int t, scale;
+ int base;
Reloc rel;
USED(p);
v = a->offset;
- t = a->type;
rel.siz = 0;
- if(a->index != D_NONE && a->index != D_TLS) {
- if(t < D_INDIR || t >= 2*D_INDIR) {
- switch(t) {
- default:
- goto bad;
- case D_STATIC:
- case D_EXTERN:
- t = D_NONE;
- v = vaddr(ctxt, p, a, &rel);
- break;
- case D_AUTO:
- case D_PARAM:
- t = D_SP;
- break;
- }
- } else
- t -= D_INDIR;
- if(t == D_NONE) {
+ switch(a->type) {
+ case TYPE_ADDR:
+ if(a->name == NAME_NONE)
+ ctxt->diag("unexpected TYPE_ADDR with NAME_NONE");
+ if(a->index == REG_TLS)
+ ctxt->diag("unexpected TYPE_ADDR with index==REG_TLS");
+ goto bad;
+
+ case TYPE_REG:
+ if((a->reg < REG_AL || REG_F7 < a->reg) && (a->reg < REG_X0 || REG_X0+7 < a->reg))
+ goto bad;
+ if(v)
+ goto bad;
+ *ctxt->andptr++ = (3 << 6) | (reg[a->reg] << 0) | (r << 3);
+ return;
+ }
+
+ if(a->type != TYPE_MEM)
+ goto bad;
+
+ if(a->index != REG_NONE && a->index != REG_TLS) {
+ base = a->reg;
+ switch(a->name) {
+ case NAME_EXTERN:
+ case NAME_STATIC:
+ base = REG_NONE;
+ v = vaddr(ctxt, p, a, &rel);
+ break;
+ case NAME_AUTO:
+ case NAME_PARAM:
+ base = REG_SP;
+ break;
+ }
+
+ if(base == REG_NONE) {
*ctxt->andptr++ = (0 << 6) | (4 << 0) | (r << 3);
- asmidx(ctxt, a->scale, a->index, t);
+ asmidx(ctxt, a->scale, a->index, base);
goto putrelv;
}
- if(v == 0 && rel.siz == 0 && t != D_BP) {
+ if(v == 0 && rel.siz == 0 && base != REG_BP) {
*ctxt->andptr++ = (0 << 6) | (4 << 0) | (r << 3);
- asmidx(ctxt, a->scale, a->index, t);
+ asmidx(ctxt, a->scale, a->index, base);
return;
}
if(v >= -128 && v < 128 && rel.siz == 0) {
*ctxt->andptr++ = (1 << 6) | (4 << 0) | (r << 3);
- asmidx(ctxt, a->scale, a->index, t);
+ asmidx(ctxt, a->scale, a->index, base);
*ctxt->andptr++ = v;
return;
}
*ctxt->andptr++ = (2 << 6) | (4 << 0) | (r << 3);
- asmidx(ctxt, a->scale, a->index, t);
+ asmidx(ctxt, a->scale, a->index, base);
goto putrelv;
}
- if(t >= D_AL && t <= D_F7 || t >= D_X0 && t <= D_X7) {
- if(v)
- goto bad;
- *ctxt->andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3);
- return;
+
+ base = a->reg;
+ switch(a->name) {
+ case NAME_STATIC:
+ case NAME_EXTERN:
+ base = REG_NONE;
+ v = vaddr(ctxt, p, a, &rel);
+ break;
+ case NAME_AUTO:
+ case NAME_PARAM:
+ base = REG_SP;
+ break;
}
- scale = a->scale;
- if(t < D_INDIR || t >= 2*D_INDIR) {
- switch(a->type) {
- default:
- goto bad;
- case D_STATIC:
- case D_EXTERN:
- t = D_NONE;
- v = vaddr(ctxt, p, a, &rel);
- break;
- case D_AUTO:
- case D_PARAM:
- t = D_SP;
- break;
- }
- scale = 1;
- } else
- t -= D_INDIR;
- if(t == D_TLS)
+ if(base == REG_TLS)
v = vaddr(ctxt, p, a, &rel);
-
- if(t == D_NONE || (D_CS <= t && t <= D_GS) || t == D_TLS) {
+
+ if(base == REG_NONE || (REG_CS <= base && base <= REG_GS) || base == REG_TLS) {
*ctxt->andptr++ = (0 << 6) | (5 << 0) | (r << 3);
goto putrelv;
}
- if(t == D_SP) {
+
+ if(base == REG_SP) {
if(v == 0 && rel.siz == 0) {
*ctxt->andptr++ = (0 << 6) | (4 << 0) | (r << 3);
- asmidx(ctxt, scale, D_NONE, t);
+ asmidx(ctxt, a->scale, REG_NONE, base);
return;
}
if(v >= -128 && v < 128 && rel.siz == 0) {
*ctxt->andptr++ = (1 << 6) | (4 << 0) | (r << 3);
- asmidx(ctxt, scale, D_NONE, t);
+ asmidx(ctxt, a->scale, REG_NONE, base);
*ctxt->andptr++ = v;
return;
}
*ctxt->andptr++ = (2 << 6) | (4 << 0) | (r << 3);
- asmidx(ctxt, scale, D_NONE, t);
+ asmidx(ctxt, a->scale, REG_NONE, base);
goto putrelv;
}
- if(t >= D_AX && t <= D_DI) {
- if(a->index == D_TLS) {
+
+ if(REG_AX <= base && base <= REG_DI) {
+ if(a->index == REG_TLS) {
memset(&rel, 0, sizeof rel);
rel.type = R_TLS_IE;
rel.siz = 4;
rel.add = v;
v = 0;
}
- if(v == 0 && rel.siz == 0 && t != D_BP) {
- *ctxt->andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3);
+ if(v == 0 && rel.siz == 0 && base != REG_BP) {
+ *ctxt->andptr++ = (0 << 6) | (reg[base] << 0) | (r << 3);
return;
}
if(v >= -128 && v < 128 && rel.siz == 0) {
- ctxt->andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3);
+ ctxt->andptr[0] = (1 << 6) | (reg[base] << 0) | (r << 3);
ctxt->andptr[1] = v;
ctxt->andptr += 2;
return;
}
- *ctxt->andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3);
+ *ctxt->andptr++ = (2 << 6) | (reg[base] << 0) | (r << 3);
goto putrelv;
}
goto bad;
};
// byteswapreg returns a byte-addressable register (AX, BX, CX, DX)
-// which is not referenced in a->type.
+// which is not referenced in a.
// If a is empty, it returns BX to account for MULB-like instructions
// that might use DX and AX.
static int
cana = canb = canc = cand = 1;
- switch(a->type) {
- case D_NONE:
+ if(a->type == TYPE_NONE)
cana = cand = 0;
- break;
- case D_AX:
- case D_AL:
- case D_AH:
- case D_INDIR+D_AX:
- cana = 0;
- break;
- case D_BX:
- case D_BL:
- case D_BH:
- case D_INDIR+D_BX:
- canb = 0;
- break;
- case D_CX:
- case D_CL:
- case D_CH:
- case D_INDIR+D_CX:
- canc = 0;
- break;
- case D_DX:
- case D_DL:
- case D_DH:
- case D_INDIR+D_DX:
- cand = 0;
- break;
+
+ if(a->type == TYPE_REG || ((a->type == TYPE_MEM || a->type == TYPE_ADDR) && a->name == NAME_NONE)) {
+ switch(a->reg) {
+ case REG_NONE:
+ cana = cand = 0;
+ break;
+ case REG_AX:
+ case REG_AL:
+ case REG_AH:
+ cana = 0;
+ break;
+ case REG_BX:
+ case REG_BL:
+ case REG_BH:
+ canb = 0;
+ break;
+ case REG_CX:
+ case REG_CL:
+ case REG_CH:
+ canc = 0;
+ break;
+ case REG_DX:
+ case REG_DL:
+ case REG_DH:
+ cand = 0;
+ break;
+ }
}
- switch(a->index) {
- case D_AX:
- cana = 0;
- break;
- case D_BX:
- canb = 0;
- break;
- case D_CX:
- canc = 0;
- break;
- case D_DX:
- cand = 0;
- break;
+ if(a->type == TYPE_MEM || a->type == TYPE_ADDR) {
+ switch(a->index) {
+ case REG_AX:
+ cana = 0;
+ break;
+ case REG_BX:
+ canb = 0;
+ break;
+ case REG_CX:
+ canc = 0;
+ break;
+ case REG_DX:
+ cand = 0;
+ break;
+ }
}
if(cana)
- return D_AX;
+ return REG_AX;
if(canb)
- return D_BX;
+ return REG_BX;
if(canc)
- return D_CX;
+ return REG_CX;
if(cand)
- return D_DX;
+ return REG_DX;
ctxt->diag("impossible byte register");
sysfatal("bad code");
static void
subreg(Prog *p, int from, int to)
{
-
if(0 /* debug['Q'] */)
print("\n%P s/%R/%R/\n", p, from, to);
- if(p->from.type == from) {
- p->from.type = to;
+ if(p->from.reg == from) {
+ p->from.reg = to;
p->ft = 0;
}
- if(p->to.type == from) {
- p->to.type = to;
+ if(p->to.reg == from) {
+ p->to.reg = to;
p->tt = 0;
}
p->tt = 0;
}
- from += D_INDIR;
- if(p->from.type == from) {
- p->from.type = to+D_INDIR;
- p->ft = 0;
- }
- if(p->to.type == from) {
- p->to.type = to+D_INDIR;
- p->tt = 0;
- }
-
if(0 /* debug['Q'] */)
print("%P\n", p);
}
*ctxt->andptr++ = pre;
if(p->ft == 0)
- p->ft = oclass(&p->from);
+ p->ft = oclass(ctxt, &p->from);
if(p->tt == 0)
- p->tt = oclass(&p->to);
+ p->tt = oclass(ctxt, &p->to);
ft = p->ft * Ymax;
tt = p->tt * Ymax;
- o = &optab[p->as];
+ o = opindex[p->as];
t = o->ytab;
if(t == 0) {
ctxt->diag("asmins: noproto %P", p);
case Zlitm_r:
for(; op = o->op[z]; z++)
*ctxt->andptr++ = op;
- asmand(ctxt, p, &p->from, reg[p->to.type]);
+ asmand(ctxt, p, &p->from, reg[p->to.reg]);
break;
case Zm_r:
*ctxt->andptr++ = op;
- asmand(ctxt, p, &p->from, reg[p->to.type]);
+ asmand(ctxt, p, &p->from, reg[p->to.reg]);
break;
case Zm2_r:
*ctxt->andptr++ = op;
*ctxt->andptr++ = o->op[z+1];
- asmand(ctxt, p, &p->from, reg[p->to.type]);
+ asmand(ctxt, p, &p->from, reg[p->to.reg]);
break;
case Zm_r_xm:
mediaop(ctxt, o, op, t[3], z);
- asmand(ctxt, p, &p->from, reg[p->to.type]);
+ asmand(ctxt, p, &p->from, reg[p->to.reg]);
break;
case Zm_r_i_xm:
mediaop(ctxt, o, op, t[3], z);
- asmand(ctxt, p, &p->from, reg[p->to.type]);
+ asmand(ctxt, p, &p->from, reg[p->to.reg]);
*ctxt->andptr++ = p->to.offset;
break;
case Zibm_r:
while ((op = o->op[z++]) != 0)
*ctxt->andptr++ = op;
- asmand(ctxt, p, &p->from, reg[p->to.type]);
+ asmand(ctxt, p, &p->from, reg[p->to.reg]);
*ctxt->andptr++ = p->to.offset;
break;
case Zaut_r:
*ctxt->andptr++ = 0x8d; /* leal */
- if(p->from.type != D_ADDR)
+ if(p->from.type != TYPE_ADDR)
ctxt->diag("asmins: Zaut sb type ADDR");
- p->from.type = p->from.index;
- p->from.index = D_NONE;
+ p->from.type = TYPE_MEM;
p->ft = 0;
- asmand(ctxt, p, &p->from, reg[p->to.type]);
- p->from.index = p->from.type;
- p->from.type = D_ADDR;
+ asmand(ctxt, p, &p->from, reg[p->to.reg]);
+ p->from.type = TYPE_ADDR;
p->ft = 0;
break;
case Zr_m:
*ctxt->andptr++ = op;
- asmand(ctxt, p, &p->to, reg[p->from.type]);
+ asmand(ctxt, p, &p->to, reg[p->from.reg]);
break;
case Zr_m_xm:
mediaop(ctxt, o, op, t[3], z);
- asmand(ctxt, p, &p->to, reg[p->from.type]);
+ asmand(ctxt, p, &p->to, reg[p->from.reg]);
break;
case Zr_m_i_xm:
mediaop(ctxt, o, op, t[3], z);
- asmand(ctxt, p, &p->to, reg[p->from.type]);
+ asmand(ctxt, p, &p->to, reg[p->from.reg]);
*ctxt->andptr++ = p->from.offset;
break;
break;
case Zib_rp:
- *ctxt->andptr++ = op + reg[p->to.type];
+ *ctxt->andptr++ = op + reg[p->to.reg];
*ctxt->andptr++ = vaddr(ctxt, p, &p->from, nil);
break;
case Zil_rp:
- *ctxt->andptr++ = op + reg[p->to.type];
+ *ctxt->andptr++ = op + reg[p->to.reg];
if(o->prefix == Pe) {
v = vaddr(ctxt, p, &p->from, nil);
*ctxt->andptr++ = v;
case Zib_rr:
*ctxt->andptr++ = op;
- asmand(ctxt, p, &p->to, reg[p->to.type]);
+ asmand(ctxt, p, &p->to, reg[p->to.reg]);
*ctxt->andptr++ = vaddr(ctxt, p, &p->from, nil);
break;
case Zil_rr:
*ctxt->andptr++ = op;
- asmand(ctxt, p, &p->to, reg[p->to.type]);
+ asmand(ctxt, p, &p->to, reg[p->to.reg]);
if(o->prefix == Pe) {
v = vaddr(ctxt, p, &p->from, nil);
*ctxt->andptr++ = v;
break;
case Z_rp:
- *ctxt->andptr++ = op + reg[p->to.type];
+ *ctxt->andptr++ = op + reg[p->to.reg];
break;
case Zrp_:
- *ctxt->andptr++ = op + reg[p->from.type];
+ *ctxt->andptr++ = op + reg[p->from.reg];
break;
case Zclr:
*ctxt->andptr++ = op;
- asmand(ctxt, p, &p->to, reg[p->to.type]);
+ asmand(ctxt, p, &p->to, reg[p->to.reg]);
break;
case Zcall:
* instruction with the operands renamed.
*/
pp = *p;
- z = p->from.type;
- if(z >= D_BP && z <= D_DI) {
- if((breg = byteswapreg(ctxt, &p->to)) != D_AX) {
+ z = p->from.reg;
+ if(p->from.type == TYPE_REG && z >= REG_BP && z <= REG_DI) {
+ if((breg = byteswapreg(ctxt, &p->to)) != REG_AX) {
*ctxt->andptr++ = 0x87; /* xchg lhs,bx */
asmand(ctxt, p, &p->from, reg[breg]);
subreg(&pp, z, breg);
asmand(ctxt, p, &p->from, reg[breg]);
} else {
*ctxt->andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */
- subreg(&pp, z, D_AX);
+ subreg(&pp, z, REG_AX);
doasm(ctxt, &pp);
*ctxt->andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */
}
return;
}
- z = p->to.type;
- if(z >= D_BP && z <= D_DI) {
- if((breg = byteswapreg(ctxt, &p->from)) != D_AX) {
+ z = p->to.reg;
+ if(p->to.type == TYPE_REG && z >= REG_BP && z <= REG_DI) {
+ if((breg = byteswapreg(ctxt, &p->from)) != REG_AX) {
*ctxt->andptr++ = 0x87; /* xchg rhs,bx */
asmand(ctxt, p, &p->to, reg[breg]);
subreg(&pp, z, breg);
asmand(ctxt, p, &p->to, reg[breg]);
} else {
*ctxt->andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */
- subreg(&pp, z, D_AX);
+ subreg(&pp, z, REG_AX);
doasm(ctxt, &pp);
*ctxt->andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */
}
return;
}
- ctxt->diag("doasm: notfound t2=%ux from=%ux to=%ux %P", t[2], p->from.type, p->to.type, p);
+ ctxt->diag("doasm: notfound t2=%d from=%d to=%d %P", t[2], p->ft, p->tt, p);
return;
mfound:
switch(p->to.index) {
default:
goto bad;
- case D_DS:
+ case REG_DS:
*ctxt->andptr++ = 0xc5;
break;
- case D_SS:
+ case REG_SS:
*ctxt->andptr++ = 0x0f;
*ctxt->andptr++ = 0xb2;
break;
- case D_ES:
+ case REG_ES:
*ctxt->andptr++ = 0xc4;
break;
- case D_FS:
+ case REG_FS:
*ctxt->andptr++ = 0x0f;
*ctxt->andptr++ = 0xb4;
break;
- case D_GS:
+ case REG_GS:
*ctxt->andptr++ = 0x0f;
*ctxt->andptr++ = 0xb5;
break;
}
- asmand(ctxt, p, &p->from, reg[p->to.type]);
+ asmand(ctxt, p, &p->from, reg[p->to.reg]);
break;
case 6: /* double shift */
- z = p->from.type;
- switch(z) {
+ switch(p->from.type) {
default:
goto bad;
- case D_CONST:
+
+ case TYPE_CONST:
*ctxt->andptr++ = 0x0f;
*ctxt->andptr++ = t[4];
asmand(ctxt, p, &p->to, reg[p->from.index]);
*ctxt->andptr++ = p->from.offset;
break;
- case D_CL:
- case D_CX:
- *ctxt->andptr++ = 0x0f;
- *ctxt->andptr++ = t[5];
- asmand(ctxt, p, &p->to, reg[p->from.index]);
+
+ case TYPE_REG:
+ switch(p->from.reg) {
+ default:
+ goto bad;
+ case REG_CL:
+ case REG_CX:
+ *ctxt->andptr++ = 0x0f;
+ *ctxt->andptr++ = t[5];
+ asmand(ctxt, p, &p->to, reg[p->from.index]);
+ break;
+ }
break;
}
break;
} else
*ctxt->andptr++ = t[4];
*ctxt->andptr++ = t[5];
- asmand(ctxt, p, &p->from, reg[p->to.type]);
+ asmand(ctxt, p, &p->from, reg[p->to.reg]);
break;
case 8: /* mov tls, r */
case Hnacl:
// ELF TLS base is 0(GS).
pp.from = p->from;
- pp.from.type = D_INDIR+D_GS;
+ pp.from.type = TYPE_MEM;
+ pp.from.reg = REG_GS;
pp.from.offset = 0;
- pp.from.index = D_NONE;
+ pp.from.index = REG_NONE;
pp.from.scale = 0;
*ctxt->andptr++ = 0x65; // GS
*ctxt->andptr++ = 0x8B;
- asmand(ctxt, p, &pp.from, reg[p->to.type]);
+ asmand(ctxt, p, &pp.from, reg[p->to.reg]);
break;
case Hplan9:
if(ctxt->plan9privates == nil)
ctxt->plan9privates = linklookup(ctxt, "_privates", 0);
memset(&pp.from, 0, sizeof pp.from);
- pp.from.type = D_EXTERN;
+ pp.from.type = TYPE_MEM;
+ pp.from.name = NAME_EXTERN;
pp.from.sym = ctxt->plan9privates;
pp.from.offset = 0;
- pp.from.index = D_NONE;
+ pp.from.index = REG_NONE;
*ctxt->andptr++ = 0x8B;
- asmand(ctxt, p, &pp.from, reg[p->to.type]);
+ asmand(ctxt, p, &pp.from, reg[p->to.reg]);
break;
case Hwindows:
// Windows TLS base is always 0x14(FS).
pp.from = p->from;
- pp.from.type = D_INDIR+D_FS;
+ pp.from.type = TYPE_MEM;
+ pp.from.reg = REG_FS;
pp.from.offset = 0x14;
- pp.from.index = D_NONE;
+ pp.from.index = REG_NONE;
pp.from.scale = 0;
*ctxt->andptr++ = 0x64; // FS
*ctxt->andptr++ = 0x8B;
- asmand(ctxt, p, &pp.from, reg[p->to.type]);
+ asmand(ctxt, p, &pp.from, reg[p->to.reg]);
break;
}
break;
return;
case ACALL:
case AJMP:
- if(D_AX <= p->to.type && p->to.type <= D_DI) {
+ if(p->to.type == TYPE_REG && REG_AX <= p->to.reg && p->to.reg <= REG_DI) {
*ctxt->andptr++ = 0x83;
- *ctxt->andptr++ = 0xe0 | (p->to.type - D_AX);
+ *ctxt->andptr++ = 0xe0 | (p->to.reg - REG_AX);
*ctxt->andptr++ = 0xe0;
}
break;
};
static Optab optab[] = {
- { ATEXT, C_LEXT, C_NONE, C_NONE, C_LCON, 0, 0, 0 },
- { ATEXT, C_LEXT, C_REG, C_NONE, C_LCON, 0, 0, 0 },
- { ATEXT, C_LEXT, C_NONE, C_LCON, C_LCON, 0, 0, 0 },
- { ATEXT, C_LEXT, C_REG, C_LCON, C_LCON, 0, 0, 0 },
- { ATEXT, C_ADDR, C_NONE, C_NONE, C_LCON, 0, 0, 0 },
- { ATEXT, C_ADDR, C_REG, C_NONE, C_LCON, 0, 0, 0 },
- { ATEXT, C_ADDR, C_NONE, C_LCON, C_LCON, 0, 0, 0 },
- { ATEXT, C_ADDR, C_REG, C_LCON, C_LCON, 0, 0, 0 },
+ { ATEXT, C_LEXT, C_NONE, C_NONE, C_TEXTSIZE, 0, 0, 0 },
+ { ATEXT, C_LEXT, C_NONE, C_LCON, C_TEXTSIZE, 0, 0, 0 },
+ { ATEXT, C_ADDR, C_NONE, C_NONE, C_TEXTSIZE, 0, 0, 0 },
+ { ATEXT, C_ADDR, C_NONE, C_LCON, C_TEXTSIZE, 0, 0, 0 },
/* move register */
{ AMOVD, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0 },
if(p == nil || p->link == nil) // handle external functions and ELF section symbols
return;
ctxt->cursym = cursym;
- ctxt->autosize = (int32)(p->to.offset & 0xffffffffll) + 8;
+ ctxt->autosize = p->to.offset + 8;
if(oprange[AANDN].start == nil)
buildop(ctxt);
if((o->type == 16 || o->type == 17) && p->pcond) {
otxt = p->pcond->pc - c;
if(otxt < -(1L<<15)+10 || otxt >= (1L<<15)-10) {
- q = ctxt->arch->prg();
+ q = emallocz(sizeof(Prog));
q->link = p->link;
p->link = q;
q->as = ABR;
- q->to.type = D_BRANCH;
+ q->to.type = TYPE_BRANCH;
q->pcond = p->pcond;
p->pcond = q;
- q = ctxt->arch->prg();
+ q = emallocz(sizeof(Prog));
q->link = p->link;
p->link = q;
q->as = ABR;
- q->to.type = D_BRANCH;
+ q->to.type = TYPE_BRANCH;
q->pcond = q->link->link;
//addnop(p->link);
//addnop(p);
LSym *s;
switch(a->type) {
- case D_NONE:
+ case TYPE_NONE:
return C_NONE;
- case D_REG:
- return C_REG;
-
- case D_FREG:
- return C_FREG;
-
- case D_CREG:
- return C_CREG;
-
- case D_SPR:
- if(a->offset == D_LR)
- return C_LR;
- if(a->offset == D_XER)
- return C_XER;
- if(a->offset == D_CTR)
- return C_CTR;
- return C_SPR;
-
- case D_DCR:
- return C_SPR;
-
- case D_FPSCR:
- return C_FPSCR;
-
- case D_MSR:
- return C_MSR;
+ case TYPE_REG:
+ if(REG_R0 <= a->reg && a->reg <= REG_R31)
+ return C_REG;
+ if(REG_F0 <= a->reg && a->reg <= REG_F31)
+ return C_FREG;
+ if(REG_C0 <= a->reg && a->reg <= REG_C7 || a->reg == REG_CR)
+ return C_CREG;
+ if(REG_SPR0 <= a->reg && a->reg <= REG_SPR0+1023) {
+ switch(a->reg) {
+ case REG_LR:
+ return C_LR;
+ case REG_XER:
+ return C_XER;
+ case REG_CTR:
+ return C_CTR;
+ }
+ return C_SPR;
+ }
+ if(REG_DCR0 <= a->reg && a->reg <= REG_DCR0+1023)
+ return C_SPR;
+ if(a->reg == REG_FPSCR)
+ return C_FPSCR;
+ if(a->reg == REG_MSR)
+ return C_MSR;
+ return C_GOK;
- case D_OREG:
+ case TYPE_MEM:
switch(a->name) {
- case D_EXTERN:
- case D_STATIC:
+ case NAME_EXTERN:
+ case NAME_STATIC:
if(a->sym == nil)
break;
ctxt->instoffset = a->offset;
if(a->sym != nil) // use relocation
return C_ADDR;
return C_LEXT;
- case D_AUTO:
+ case NAME_AUTO:
ctxt->instoffset = ctxt->autosize + a->offset;
if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG)
return C_SAUTO;
return C_LAUTO;
- case D_PARAM:
+ case NAME_PARAM:
ctxt->instoffset = ctxt->autosize + a->offset + 8L;
if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG)
return C_SAUTO;
return C_LAUTO;
- case D_NONE:
+ case TYPE_NONE:
ctxt->instoffset = a->offset;
if(ctxt->instoffset == 0)
return C_ZOREG;
}
return C_GOK;
- case D_OPT:
- ctxt->instoffset = a->offset & 31L;
- if(a->name == D_NONE)
- return C_SCON;
- return C_GOK;
+ case TYPE_TEXTSIZE:
+ return C_TEXTSIZE;
- case D_CONST:
+ case TYPE_CONST:
+ case TYPE_ADDR:
switch(a->name) {
- case D_NONE:
+ case TYPE_NONE:
ctxt->instoffset = a->offset;
- if(a->reg != NREG) {
+ if(a->reg != 0) {
if(-BIG <= ctxt->instoffset && ctxt->instoffset <= BIG)
return C_SACON;
if(isint32(ctxt->instoffset))
}
goto consize;
- case D_EXTERN:
- case D_STATIC:
+ case NAME_EXTERN:
+ case NAME_STATIC:
s = a->sym;
if(s == nil)
break;
/* not sure why this barfs */
return C_LCON;
- case D_AUTO:
+ case NAME_AUTO:
ctxt->instoffset = ctxt->autosize + a->offset;
if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG)
return C_SACON;
return C_LACON;
- case D_PARAM:
+ case NAME_PARAM:
ctxt->instoffset = ctxt->autosize + a->offset + 8L;
if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG)
return C_SACON;
return C_LCON;
return C_DCON;
- case D_BRANCH:
+ case TYPE_BRANCH:
return C_SBRA;
}
return C_GOK;
}
a4--;
a2 = C_NONE;
- if(p->reg != NREG)
+ if(p->reg != 0)
a2 = C_REG;
//print("oplook %P %d %d %d %d\n", p, a1, a2, a3, a4);
r = p->as;
break;
case 1: /* mov r1,r2 ==> OR Rs,Rs,Ra */
- if(p->to.reg == REGZERO && p->from.type == D_CONST) {
+ if(p->to.reg == REGZERO && p->from.type == TYPE_CONST) {
v = regoff(ctxt, &p->from);
if(r0iszero && v != 0) {
//nerrors--;
case 2: /* int/cr/fp op Rb,[Ra],Rd */
r = p->reg;
- if(r == NREG)
+ if(r == 0)
r = p->to.reg;
o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, p->from.reg);
break;
d = vregoff(ctxt, &p->from);
v = d;
r = p->from.reg;
- if(r == NREG)
+ if(r == 0)
r = o->param;
if(r0iszero && p->to.reg == 0 && (r != 0 || v != 0))
ctxt->diag("literal operation on R0\n%P", p);
case 4: /* add/mul $scon,[r1],r2 */
v = regoff(ctxt, &p->from);
r = p->reg;
- if(r == NREG)
+ if(r == 0)
r = p->to.reg;
if(r0iszero && p->to.reg == 0)
ctxt->diag("literal operation on R0\n%P", p);
case 6: /* logical op Rb,[Rs,]Ra; no literal */
r = p->reg;
- if(r == NREG)
+ if(r == 0)
r = p->to.reg;
o1 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, p->from.reg);
break;
case 7: /* mov r, soreg ==> stw o(r) */
r = p->to.reg;
- if(r == NREG)
+ if(r == 0)
r = o->param;
v = regoff(ctxt, &p->to);
- if(p->to.type == D_OREG && p->reg != NREG) {
+ if(p->to.type == TYPE_MEM && p->reg != 0) {
if(v)
ctxt->diag("illegal indexed instruction\n%P", p);
o1 = AOP_RRR(opstorex(ctxt, p->as), p->from.reg, p->reg, r);
case 8: /* mov soreg, r ==> lbz/lhz/lwz o(r) */
r = p->from.reg;
- if(r == NREG)
+ if(r == 0)
r = o->param;
v = regoff(ctxt, &p->from);
- if(p->from.type == D_OREG && p->reg != NREG) {
+ if(p->from.type == TYPE_MEM && p->reg != 0) {
if(v)
ctxt->diag("illegal indexed instruction\n%P", p);
o1 = AOP_RRR(oploadx(ctxt, p->as), p->to.reg, p->reg, r);
case 9: /* movb soreg, r ==> lbz o(r),r2; extsb r2,r2 */
r = p->from.reg;
- if(r == NREG)
+ if(r == 0)
r = o->param;
v = regoff(ctxt, &p->from);
- if(p->from.type == D_OREG && p->reg != NREG) {
+ if(p->from.type == TYPE_MEM && p->reg != 0) {
if(v)
ctxt->diag("illegal indexed instruction\n%P", p);
o1 = AOP_RRR(oploadx(ctxt, p->as), p->to.reg, p->reg, r);
case 10: /* sub Ra,[Rb],Rd => subf Rd,Ra,Rb */
r = p->reg;
- if(r == NREG)
+ if(r == 0)
r = p->to.reg;
o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, p->from.reg, r);
break;
break;
case 12: /* movb r,r (extsb); movw r,r (extsw) */
- if(p->to.reg == REGZERO && p->from.type == D_CONST) {
+ if(p->to.reg == REGZERO && p->from.type == TYPE_CONST) {
v = regoff(ctxt, &p->from);
if(r0iszero && v != 0) {
ctxt->diag("literal operation on R0\n%P", p);
case 14: /* rldc[lr] Rb,Rs,$mask,Ra -- left, right give different masks */
r = p->reg;
- if(r == NREG)
+ if(r == 0)
r = p->to.reg;
d = vregoff(ctxt, &p->from3);
maskgen64(ctxt, p, mask, d);
case 17: /* bc bo,bi,lbra (same for now) */
case 16: /* bc bo,bi,sbra */
a = 0;
- if(p->from.type == D_CONST)
+ if(p->from.type == TYPE_CONST)
a = regoff(ctxt, &p->from);
r = p->reg;
- if(r == NREG)
+ if(r == 0)
r = 0;
v = 0;
if(p->pcond)
else
v = 20; /* unconditional */
r = p->reg;
- if(r == NREG)
+ if(r == 0)
r = 0;
- o1 = AOP_RRR(OP_MTSPR, p->to.reg, 0, 0) | ((D_LR&0x1f)<<16) | (((D_LR>>5)&0x1f)<<11);
+ o1 = AOP_RRR(OP_MTSPR, p->to.reg, 0, 0) | ((REG_LR&0x1f)<<16) | (((REG_LR>>5)&0x1f)<<11);
o2 = OPVCC(19, 16, 0, 0);
if(p->as == ABL || p->as == ABCL)
o2 |= 1;
else
v = 20; /* unconditional */
r = p->reg;
- if(r == NREG)
+ if(r == 0)
r = 0;
switch(oclass(&p->to)) {
case C_CTR:
case 20: /* add $ucon,,r */
v = regoff(ctxt, &p->from);
r = p->reg;
- if(r == NREG)
+ if(r == 0)
r = p->to.reg;
if(p->as == AADD && (!r0iszero && p->reg == 0 || r0iszero && p->to.reg == 0))
ctxt->diag("literal operation on R0\n%P", p);
- o1 = AOP_IRR(opirr(ctxt, p->as+AEND), p->to.reg, r, v>>16);
+ o1 = AOP_IRR(opirr(ctxt, p->as+ALAST), p->to.reg, r, v>>16);
break;
case 22: /* add $lcon,r1,r2 ==> cau+or+add */ /* could do add/sub more efficiently */
o1 = loadu32(REGTMP, d);
o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, (int32)d);
r = p->reg;
- if(r == NREG)
+ if(r == 0)
r = p->to.reg;
o3 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, REGTMP, r);
if(p->from.sym != nil)
o1 = loadu32(REGTMP, d);
o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, (int32)d);
r = p->reg;
- if(r == NREG)
+ if(r == 0)
r = p->to.reg;
o3 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, REGTMP, r);
if(p->from.sym != nil)
else if(v > 63)
v = 63;
r = p->reg;
- if(r == NREG)
+ if(r == 0)
r = p->to.reg;
switch(p->as){
case ASLD: case ASLDCC:
ctxt->diag("can't synthesize large constant\n%P", p);
v = regoff(ctxt, &p->from);
r = p->from.reg;
- if(r == NREG)
+ if(r == 0)
r = o->param;
o1 = AOP_IRR(OP_ADDIS, REGTMP, r, high16adjusted(v));
o2 = AOP_IRR(OP_ADDI, p->to.reg, REGTMP, v);
case 32: /* fmul frc,fra,frd */
r = p->reg;
- if(r == NREG)
+ if(r == 0)
r = p->to.reg;
o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, 0)|((p->from.reg&31L)<<6);
break;
case 35: /* mov r,lext/lauto/loreg ==> cau $(v>>16),sb,r'; store o(r') */
v = regoff(ctxt, &p->to);
r = p->to.reg;
- if(r == NREG)
+ if(r == 0)
r = o->param;
o1 = AOP_IRR(OP_ADDIS, REGTMP, r, high16adjusted(v));
o2 = AOP_IRR(opstore(ctxt, p->as), p->from.reg, REGTMP, v);
case 36: /* mov bz/h/hz lext/lauto/lreg,r ==> lbz/lha/lhz etc */
v = regoff(ctxt, &p->from);
r = p->from.reg;
- if(r == NREG)
+ if(r == 0)
r = o->param;
o1 = AOP_IRR(OP_ADDIS, REGTMP, r, high16adjusted(v));
o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v);
case 37: /* movb lext/lauto/lreg,r ==> lbz o(reg),r; extsb r */
v = regoff(ctxt, &p->from);
r = p->from.reg;
- if(r == NREG)
+ if(r == 0)
r = o->param;
o1 = AOP_IRR(OP_ADDIS, REGTMP, r, high16adjusted(v));
o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v);
case 43: /* unary indexed source: dcbf (b); dcbf (a+b) */
r = p->reg;
- if(r == NREG)
+ if(r == 0)
r = 0;
o1 = AOP_RRR(oprrr(ctxt, p->as), 0, r, p->from.reg);
break;
case 44: /* indexed store */
r = p->reg;
- if(r == NREG)
+ if(r == 0)
r = 0;
o1 = AOP_RRR(opstorex(ctxt, p->as), p->from.reg, r, p->to.reg);
break;
case 45: /* indexed load */
r = p->reg;
- if(r == NREG)
+ if(r == 0)
r = 0;
o1 = AOP_RRR(oploadx(ctxt, p->as), p->to.reg, r, p->from.reg);
break;
case 47: /* op Ra, Rd; also op [Ra,] Rd */
r = p->from.reg;
- if(r == NREG)
+ if(r == 0)
r = p->to.reg;
o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, 0);
break;
case 48: /* op Rs, Ra */
r = p->from.reg;
- if(r == NREG)
+ if(r == 0)
r = p->to.reg;
o1 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, 0);
break;
case 49: /* op Rb; op $n, Rb */
- if(p->from.type != D_REG){ /* tlbie $L, rB */
+ if(p->from.type != TYPE_REG){ /* tlbie $L, rB */
v = regoff(ctxt, &p->from) & 1;
o1 = AOP_RRR(oprrr(ctxt, p->as), 0, 0, p->to.reg) | (v<<21);
}else
case 50: /* rem[u] r1[,r2],r3 */
r = p->reg;
- if(r == NREG)
+ if(r == 0)
r = p->to.reg;
v = oprrr(ctxt, p->as);
t = v & ((1<<10)|1); /* OE|Rc */
case 51: /* remd[u] r1[,r2],r3 */
r = p->reg;
- if(r == NREG)
+ if(r == 0)
r = p->to.reg;
v = oprrr(ctxt, p->as);
t = v & ((1<<10)|1); /* OE|Rc */
case 56: /* sra $sh,[s,]a; srd $sh,[s,]a */
v = regoff(ctxt, &p->from);
r = p->reg;
- if(r == NREG)
+ if(r == 0)
r = p->to.reg;
o1 = AOP_RRR(opirr(ctxt, p->as), r, p->to.reg, v&31L);
if(p->as == ASRAD && (v&0x20))
case 57: /* slw $sh,[s,]a -> rlwinm ... */
v = regoff(ctxt, &p->from);
r = p->reg;
- if(r == NREG)
+ if(r == 0)
r = p->to.reg;
/*
* Let user (gs) shoot himself in the foot.
case 58: /* logical $andcon,[s],a */
v = regoff(ctxt, &p->from);
r = p->reg;
- if(r == NREG)
+ if(r == 0)
r = p->to.reg;
o1 = LOP_IRR(opirr(ctxt, p->as), p->to.reg, r, v);
break;
case 59: /* or/and $ucon,,r */
v = regoff(ctxt, &p->from);
r = p->reg;
- if(r == NREG)
+ if(r == 0)
r = p->to.reg;
- o1 = LOP_IRR(opirr(ctxt, p->as+AEND), p->to.reg, r, v>>16); /* oris, xoris, andis */
+ o1 = LOP_IRR(opirr(ctxt, p->as+ALAST), p->to.reg, r, v>>16); /* oris, xoris, andis */
break;
case 60: /* tw to,a,b */
break;
case 64: /* mtfsf fr[, $m] {,fpcsr} */
- if(p->from3.type != D_NONE)
+ if(p->from3.type != TYPE_NONE)
v = regoff(ctxt, &p->from3)&255L;
else
v = 255;
break;
case 65: /* MOVFL $imm,FPSCR(n) => mtfsfi crfd,imm */
- if(p->to.reg == NREG)
+ if(p->to.reg == 0)
ctxt->diag("must specify FPSCR(n)\n%P", p);
o1 = OP_MTFSFI | ((p->to.reg&15L)<<23) | ((regoff(ctxt, &p->from)&31L)<<12);
break;
case 66: /* mov spr,r1; mov r1,spr, also dcr */
- if(p->from.type == D_REG) {
+ if(REG_R0 <= p->from.reg && p->from.reg <= REG_R31) {
r = p->from.reg;
- v = p->to.offset;
- if(p->to.type == D_DCR)
+ v = p->to.reg;
+ if(REG_DCR0 <= v && v <= REG_DCR0+1023)
o1 = OPVCC(31,451,0,0); /* mtdcr */
else
o1 = OPVCC(31,467,0,0); /* mtspr */
} else {
r = p->to.reg;
- v = p->from.offset;
- if(p->from.type == D_DCR)
+ v = p->from.reg;
+ if(REG_DCR0 <= v && v <= REG_DCR0+1023)
o1 = OPVCC(31,323,0,0); /* mfdcr */
else
o1 = OPVCC(31,339,0,0); /* mfspr */
break;
case 67: /* mcrf crfD,crfS */
- if(p->from.type != D_CREG || p->from.reg == NREG ||
- p->to.type != D_CREG || p->to.reg == NREG)
+ if(p->from.type != TYPE_REG || p->from.reg < REG_C0 || REG_C7 < p->from.reg ||
+ p->to.type != TYPE_REG || p->to.reg < REG_C0 || REG_C7 < p->to.reg)
ctxt->diag("illegal CR field number\n%P", p);
o1 = AOP_RRR(OP_MCRF, ((p->to.reg&7L)<<2), ((p->from.reg&7)<<2), 0);
break;
case 68: /* mfcr rD; mfocrf CRM,rD */
- if(p->from.type == D_CREG && p->from.reg != NREG){
+ if(p->from.type == TYPE_REG && REG_C0 <= p->from.reg && p->from.reg <= REG_C7) {
v = 1<<(7-(p->to.reg&7)); /* CR(n) */
o1 = AOP_RRR(OP_MFCR, p->to.reg, 0, 0) | (1<<20) | (v<<12); /* new form, mfocrf */
}else
break;
case 69: /* mtcrf CRM,rS */
- if(p->from3.type != D_NONE) {
- if(p->to.reg != NREG)
+ if(p->from3.type != TYPE_NONE) {
+ if(p->to.reg != 0)
ctxt->diag("can't use both mask and CR(n)\n%P", p);
v = regoff(ctxt, &p->from3) & 0xff;
} else {
- if(p->to.reg == NREG)
+ if(p->to.reg == 0)
v = 0xff; /* CR */
else
v = 1<<(7-(p->to.reg&7)); /* CR(n) */
break;
case 70: /* [f]cmp r,r,cr*/
- if(p->reg == NREG)
+ if(p->reg == 0)
r = 0;
else
r = (p->reg&7)<<2;
break;
case 71: /* cmp[l] r,i,cr*/
- if(p->reg == NREG)
+ if(p->reg == 0)
r = 0;
else
r = (p->reg&7)<<2;
break;
case 73: /* mcrfs crfD,crfS */
- if(p->from.type != D_FPSCR || p->from.reg == NREG ||
- p->to.type != D_CREG || p->to.reg == NREG)
+ if(p->from.type != TYPE_REG || p->from.reg != REG_FPSCR ||
+ p->to.type != TYPE_REG || p->to.reg < REG_C0 || REG_C7 < p->to.reg)
ctxt->diag("illegal FPSCR/CR field number\n%P", p);
- o1 = AOP_RRR(OP_MCRFS, ((p->to.reg&7L)<<2), ((p->from.reg&7)<<2), 0);
+ o1 = AOP_RRR(OP_MCRFS, ((p->to.reg&7L)<<2), ((0&7)<<2), 0);
break;
case 77: /* syscall $scon, syscall Rx */
- if(p->from.type == D_CONST) {
+ if(p->from.type == TYPE_CONST) {
if(p->from.offset > BIG || p->from.offset < -BIG)
ctxt->diag("illegal syscall, sysnum too large: %P", p);
o1 = AOP_IRR(OP_ADDI, REGZERO, REGZERO, p->from.offset);
- } else if(p->from.type == D_REG) {
+ } else if(p->from.type == TYPE_REG) {
o1 = LOP_RRR(OP_OR, REGZERO, p->from.reg, p->from.reg);
} else {
ctxt->diag("illegal syscall: %P", p);
case AADD: return OPVCC(14,0,0,0);
case AADDC: return OPVCC(12,0,0,0);
case AADDCCC: return OPVCC(13,0,0,0);
- case AADD+AEND: return OPVCC(15,0,0,0); /* ADDIS/CAU */
+ case AADD+ALAST: return OPVCC(15,0,0,0); /* ADDIS/CAU */
case AANDCC: return OPVCC(28,0,0,0);
- case AANDCC+AEND: return OPVCC(29,0,0,0); /* ANDIS./ANDIU. */
+ case AANDCC+ALAST: return OPVCC(29,0,0,0); /* ANDIS./ANDIU. */
case ABR: return OPVCC(18,0,0,0);
case ABL: return OPVCC(18,0,0,0) | 1;
case AMULLW: return OPVCC(7,0,0,0);
case AOR: return OPVCC(24,0,0,0);
- case AOR+AEND: return OPVCC(25,0,0,0); /* ORIS/ORIU */
+ case AOR+ALAST: return OPVCC(25,0,0,0); /* ORIS/ORIU */
case ARLWMI: return OPVCC(20,0,0,0); /* rlwimi */
case ARLWMICC: return OPVCC(20,0,0,1);
case ATD: return OPVCC(2,0,0,0);
case AXOR: return OPVCC(26,0,0,0); /* XORIL */
- case AXOR+AEND: return OPVCC(27,0,0,0); /* XORIU */
+ case AXOR+ALAST: return OPVCC(27,0,0,0); /* XORIU */
}
ctxt->diag("bad opcode i/r %A", a);
return 0;
Reloc *r;
off = p->from.offset;
- siz = ctxt->arch->datasize(p);
+ siz = p->from3.offset;
if(off < 0 || siz < 0 || off >= 1<<30 || siz >= 100)
mangle(pn);
if(ctxt->enforce_data_order && off < s->np)
ctxt->diag("data out of order (already have %d)\n%P", p);
symgrow(ctxt, s, off+siz);
- if(p->to.type == ctxt->arch->D_FCONST) {
+ if(p->to.type == TYPE_FCONST) {
switch(siz) {
default:
case 4:
s->p[off+i] = cast[fnuxi8[i]];
break;
}
- } else if(p->to.type == ctxt->arch->D_SCONST) {
+ } else if(p->to.type == TYPE_SCONST) {
for(i=0; i<siz; i++)
s->p[off+i] = p->to.u.sval[i];
- } else if(p->to.type == ctxt->arch->D_CONST) {
+ } else if(p->to.type == TYPE_CONST) {
if(p->to.sym)
goto addr;
o = p->to.offset;
s->p[off+i] = cast[inuxi8[i]];
break;
}
- } else if(p->to.type == ctxt->arch->D_ADDR) {
+ } else if(p->to.type == TYPE_ADDR) {
addr:
r = addrel(s);
r->off = off;
#include <bio.h>
#include <link.h>
+int framepointer_enabled;
+int fieldtrack_enabled;
+Prog zprog;
+
+// Toolchain experiments.
+// These are controlled by the GOEXPERIMENT environment
+// variable recorded when the toolchain is built.
+// This list is also known to cmd/gc.
+static struct {
+ char *name;
+ int *val;
+} exper[] = {
+ {"fieldtrack", &fieldtrack_enabled},
+ {"framepointer", &framepointer_enabled},
+};
+
+static void
+addexp(char *s)
+{
+ int i;
+
+ for(i=0; i < nelem(exper); i++ ) {
+ if(strcmp(exper[i].name, s) == 0) {
+ if(exper[i].val != nil)
+ *exper[i].val = 1;
+ return;
+ }
+ }
+
+ print("unknown experiment %s\n", s);
+ exits("unknown experiment");
+}
+
+void
+linksetexp(void)
+{
+ char *f[20];
+ int i, nf;
+
+ // cmd/dist #defines GOEXPERIMENT for us.
+ nf = getfields(GOEXPERIMENT, f, nelem(f), 1, ",");
+ for(i=0; i<nf; i++)
+ addexp(f[i]);
+}
+
+char*
+expstring(void)
+{
+ int i;
+ static char buf[512];
+
+ strcpy(buf, "X");
+ for(i=0; i<nelem(exper); i++)
+ if(*exper[i].val)
+ seprint(buf+strlen(buf), buf+sizeof buf, ",%s", exper[i].name);
+ if(strlen(buf) == 1)
+ strcpy(buf, "X,none");
+ buf[1] = ':';
+ return buf;
+}
+
// replace all "". with pkg.
char*
expandpkg(char *t0, char *pkg)
{
Prog *p;
- p = ctxt->arch->prg();
+ USED(ctxt);
+ p = emallocz(sizeof(Prog));
*p = *q;
return p;
}
{
Prog *p;
- p = ctxt->arch->prg();
+ USED(ctxt);
+ p = emallocz(sizeof(Prog));
p->link = q->link;
q->link = p;
p->lineno = q->lineno;
#include <bio.h>
#include <link.h>
#include "../cmd/5l/5.out.h"
+#include "../runtime/funcdata.h"
enum
{
bigP = p;
a = p->as;
s = p->scond;
- strcpy(sc, extra[s & C_SCOND]);
+ strcpy(sc, extra[(s & C_SCOND) ^ C_SCOND_XOR]);
if(s & C_SBIT)
strcat(sc, ".S");
if(s & C_PBIT)
if(s & C_UBIT) /* ambiguous with FBIT */
strcat(sc, ".U");
if(a == AMOVM) {
- if(p->from.type == D_CONST)
+ if(p->from.type == TYPE_CONST)
sprint(str, "%.5lld (%L) %A%s %@,%D", p->pc, p->lineno, a, sc, &p->from, &p->to);
else
- if(p->to.type == D_CONST)
+ if(p->to.type == TYPE_CONST)
sprint(str, "%.5lld (%L) %A%s %D,%@", p->pc, p->lineno, a, sc, &p->from, &p->to);
else
sprint(str, "%.5lld (%L) %A%s %D,%D", p->pc, p->lineno, a, sc, &p->from, &p->to);
} else
if(a == ADATA)
- sprint(str, "%.5lld (%L) %A %D/%d,%D", p->pc, p->lineno, a, &p->from, p->reg, &p->to);
+ sprint(str, "%.5lld (%L) %A %D/%lld,%D", p->pc, p->lineno, a, &p->from, p->from3.offset, &p->to);
else
if(p->as == ATEXT)
- sprint(str, "%.5lld (%L) %A %D,%d,%D", p->pc, p->lineno, a, &p->from, p->reg, &p->to);
+ sprint(str, "%.5lld (%L) %A %D,%lld,%D", p->pc, p->lineno, a, &p->from, p->from3.offset, &p->to);
else
- if(p->reg == NREG)
+ if(p->reg == 0)
sprint(str, "%.5lld (%L) %A%s %D,%D", p->pc, p->lineno, a, sc, &p->from, &p->to);
else
- if(p->from.type != D_FREG)
- sprint(str, "%.5lld (%L) %A%s %D,R%d,%D", p->pc, p->lineno, a, sc, &p->from, p->reg, &p->to);
- else
- sprint(str, "%.5lld (%L) %A%s %D,F%d,%D", p->pc, p->lineno, a, sc, &p->from, p->reg, &p->to);
+ sprint(str, "%.5lld (%L) %A%s %D,%R,%D", p->pc, p->lineno, a, sc, &p->from, p->reg, &p->to);
bigP = nil;
return fmtstrcpy(fp, str);
}
sprint(str, "GOK-type(%d)", a->type);
break;
- case D_NONE:
+ case TYPE_NONE:
str[0] = 0;
- if(a->name != D_NONE || a->reg != NREG || a->sym != nil)
- sprint(str, "%M(R%d)(NONE)", a, a->reg);
+ if(a->name != TYPE_NONE || a->reg != 0 || a->sym != nil)
+ sprint(str, "%M(%R)(NONE)", a, a->reg);
break;
- case D_CONST:
- if(a->reg != NREG)
- sprint(str, "$%M(R%d)", a, a->reg);
+ case TYPE_CONST:
+ case TYPE_ADDR:
+ if(a->reg != 0)
+ sprint(str, "$%M(%R)", a, a->reg);
else
sprint(str, "$%M", a);
break;
- case D_CONST2:
- sprint(str, "$%lld-%d", a->offset, a->offset2);
+ case TYPE_TEXTSIZE:
+ if(a->u.argsize == ArgsSizeUnknown)
+ sprint(str, "$%lld", a->offset);
+ else
+ sprint(str, "$%lld-%lld", a->offset, a->u.argsize);
break;
- case D_SHIFT:
+ case TYPE_SHIFT:
v = a->offset;
op = &"<<>>->@>"[(((v>>5) & 3) << 1)];
if(v & (1<<4))
sprint(str, "R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15);
else
sprint(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);
+ if(a->reg != 0)
+ sprint(str+strlen(str), "(%R)", a->reg);
break;
- case D_OREG:
- if(a->reg != NREG)
- sprint(str, "%M(R%d)", a, a->reg);
+ case TYPE_MEM:
+ if(a->reg != 0)
+ sprint(str, "%M(%R)", a, a->reg);
else
sprint(str, "%M", a);
break;
- case D_REG:
- sprint(str, "R%d", a->reg);
- if(a->name != D_NONE || a->sym != nil)
- sprint(str, "%M(R%d)(REG)", a, a->reg);
- break;
-
- case D_FREG:
- sprint(str, "F%d", a->reg);
- if(a->name != D_NONE || a->sym != nil)
- sprint(str, "%M(R%d)(REG)", a, a->reg);
- break;
-
- case D_PSR:
- sprint(str, "PSR");
- if(a->name != D_NONE || a->sym != nil)
- sprint(str, "%M(PSR)(REG)", a);
+ case TYPE_REG:
+ sprint(str, "%R", a->reg);
+ if(a->name != TYPE_NONE || a->sym != nil)
+ sprint(str, "%M(%R)(REG)", a, a->reg);
break;
- case D_BRANCH:
+ case TYPE_BRANCH:
if(a->sym != nil)
sprint(str, "%s(SB)", a->sym->name);
else if(bigP != nil && bigP->pcond != nil)
sprint(str, "%lld(PC)", a->offset/*-pc*/);
break;
- case D_FCONST:
+ case TYPE_FCONST:
sprint(str, "$%.17g", a->u.dval);
break;
- case D_SCONST:
+ case TYPE_SCONST:
sprint(str, "$\"%$\"", a->u.sval);
break;
}
a = va_arg(fp->args, Addr*);
sprint(str, "GOK-reglist");
switch(a->type) {
- case D_CONST:
- case D_CONST2:
- if(a->reg != NREG)
+ case TYPE_CONST:
+ if(a->reg != 0)
break;
if(a->sym != nil)
break;
Rconv(Fmt *fp)
{
int r;
- char str[STRINGSZ];
r = va_arg(fp->args, int);
- sprint(str, "R%d", r);
- return fmtstrcpy(fp, str);
+ if(r == 0)
+ return fmtstrcpy(fp, "NONE");
+ if(REG_R0 <= r && r <= REG_R15)
+ return fmtprint(fp, "R%d", r-REG_R0);
+ if(REG_F0 <= r && r <= REG_F15)
+ return fmtprint(fp, "F%d", r-REG_F0);
+
+ switch(r) {
+ case REG_FPSR:
+ return fmtstrcpy(fp, "FPSR");
+ case REG_FPCR:
+ return fmtstrcpy(fp, "FPCR");
+ case REG_CPSR:
+ return fmtstrcpy(fp, "CPSR");
+ case REG_SPSR:
+ return fmtstrcpy(fp, "SPSR");
+ }
+
+ return fmtprint(fp, "badreg(%d)", r);
}
static int
sprint(str, "GOK-name(%d)", a->name);
break;
- case D_NONE:
+ case NAME_NONE:
sprint(str, "%lld", a->offset);
break;
- case D_EXTERN:
+ case NAME_EXTERN:
sprint(str, "%s+%d(SB)", s->name, (int)a->offset);
break;
- case D_STATIC:
+ case NAME_STATIC:
sprint(str, "%s<>+%d(SB)", s->name, (int)a->offset);
break;
- case D_AUTO:
+ case NAME_AUTO:
sprint(str, "%s-%d(SP)", s->name, (int)-a->offset);
break;
- case D_PARAM:
+ case NAME_PARAM:
sprint(str, "%s+%d(FP)", s->name, (int)a->offset);
break;
}
#include <bio.h>
#include <link.h>
#include "../cmd/6l/6.out.h"
+#include "../runtime/funcdata.h"
//
// Format conversions
// %A int Opcodes (instruction mnemonics)
//
// %D Addr* Addresses (instruction operands)
-// Flags: "%lD": seperate the high and low words of a constant by "-"
//
// %P Prog* Instructions
//
switch(p->as) {
case ADATA:
- sprint(str, "%.5lld (%L) %A %D/%d,%D",
- p->pc, p->lineno, p->as, &p->from, p->from.scale, &p->to);
+ sprint(str, "%.5lld (%L) %A %D/%lld,%D",
+ p->pc, p->lineno, p->as, &p->from, p->from3.offset, &p->to);
break;
case ATEXT:
- if(p->from.scale) {
- sprint(str, "%.5lld (%L) %A %D,%d,%lD",
- p->pc, p->lineno, p->as, &p->from, p->from.scale, &p->to);
+ if(p->from3.offset) {
+ sprint(str, "%.5lld (%L) %A %D,%lld,%D",
+ p->pc, p->lineno, p->as, &p->from, p->from3.offset, &p->to);
break;
}
- sprint(str, "%.5lld (%L) %A %D,%lD",
+ sprint(str, "%.5lld (%L) %A %D,%D",
p->pc, p->lineno, p->as, &p->from, &p->to);
break;
{
char str[STRINGSZ], s[STRINGSZ];
Addr *a;
- int i;
a = va_arg(fp->args, Addr*);
- i = a->type;
-
- if(fp->flags & FmtLong) {
- if(i == D_CONST)
- sprint(str, "$%lld-%lld", a->offset&0xffffffffLL, a->offset>>32);
- else {
- // ATEXT dst is not constant
- sprint(str, "!!%D", a);
- }
- goto brk;
- }
- if(i >= D_INDIR) {
- if(a->offset)
- sprint(str, "%lld(%R)", a->offset, i-D_INDIR);
- else
- sprint(str, "(%R)", i-D_INDIR);
- goto brk;
- }
- switch(i) {
+ switch(a->type) {
default:
- if(a->offset)
- sprint(str, "$%lld,%R", a->offset, i);
- else
- sprint(str, "%R", i);
+ sprint(str, "type=%d", a->type);
break;
- case D_NONE:
+ case TYPE_NONE:
str[0] = 0;
break;
+
+ case TYPE_REG:
+ // TODO(rsc): This special case is for instructions like
+ // PINSRQ CX,$1,X6
+ // where the $1 is included in the p->to Addr.
+ // Move into a new field.
+ if(a->offset != 0) {
+ sprint(str, "$%lld,%R", a->offset, a->reg);
+ break;
+ }
+ sprint(str, "%R", a->reg);
+ break;
- case D_BRANCH:
+ case TYPE_BRANCH:
if(a->sym != nil)
sprint(str, "%s(SB)", a->sym->name);
else if(bigP != nil && bigP->pcond != nil)
sprint(str, "%lld(PC)", a->offset);
break;
- case D_EXTERN:
- sprint(str, "%s+%lld(SB)", a->sym->name, a->offset);
- break;
-
- case D_STATIC:
- sprint(str, "%s<>+%lld(SB)", a->sym->name, a->offset);
+ case TYPE_MEM:
+ switch(a->name) {
+ default:
+ sprint(str, "name=%d", a->name);
+ break;
+ case NAME_NONE:
+ if(a->offset)
+ sprint(str, "%lld(%R)", a->offset, a->reg);
+ else
+ sprint(str, "(%R)", a->reg);
+ break;
+ case NAME_EXTERN:
+ sprint(str, "%s+%lld(SB)", a->sym->name, a->offset);
+ break;
+ case NAME_STATIC:
+ sprint(str, "%s<>+%lld(SB)", a->sym->name, a->offset);
+ break;
+ case NAME_AUTO:
+ if(a->sym)
+ sprint(str, "%s+%lld(SP)", a->sym->name, a->offset);
+ else
+ sprint(str, "%lld(SP)", a->offset);
+ break;
+ case NAME_PARAM:
+ if(a->sym)
+ sprint(str, "%s+%lld(FP)", a->sym->name, a->offset);
+ else
+ sprint(str, "%lld(FP)", a->offset);
+ break;
+ }
+ if(a->index != REG_NONE) {
+ sprint(s, "(%R*%d)", (int)a->index, (int)a->scale);
+ strcat(str, s);
+ }
break;
- case D_AUTO:
- if(a->sym)
- sprint(str, "%s+%lld(SP)", a->sym->name, a->offset);
- else
- sprint(str, "%lld(SP)", a->offset);
+ case TYPE_CONST:
+ sprint(str, "$%lld", a->offset);
+ // TODO(rsc): This special case is for SHRQ $32, AX:DX, which encodes as
+ // SHRQ $32(DX*0), AX
+ // Remove.
+ if(a->index != REG_NONE) {
+ sprint(s, "(%R*%d)", (int)a->index, (int)a->scale);
+ strcat(str, s);
+ }
break;
-
- case D_PARAM:
- if(a->sym)
- sprint(str, "%s+%lld(FP)", a->sym->name, a->offset);
+
+ case TYPE_TEXTSIZE:
+ if(a->u.argsize == ArgsSizeUnknown)
+ sprint(str, "$%lld", a->offset);
else
- sprint(str, "%lld(FP)", a->offset);
- break;
-
- case D_CONST:
- sprint(str, "$%lld", a->offset);
+ sprint(str, "$%lld-%lld", a->offset, a->u.argsize);
break;
- case D_FCONST:
+ case TYPE_FCONST:
sprint(str, "$(%.17g)", a->u.dval);
break;
- case D_SCONST:
+ case TYPE_SCONST:
sprint(str, "$\"%$\"", a->u.sval);
break;
- case D_ADDR:
- a->type = a->index;
- a->index = D_NONE;
+ case TYPE_ADDR:
+ a->type = TYPE_MEM;
sprint(str, "$%D", a);
- a->index = a->type;
- a->type = D_ADDR;
- goto conv;
- }
-brk:
- if(a->index != D_NONE) {
- sprint(s, "(%R*%d)", (int)a->index, (int)a->scale);
- strcat(str, s);
+ a->type = TYPE_ADDR;
+ break;
}
-conv:
return fmtstrcpy(fp, str);
}
"TR7",
"TLS", /* [D_TLS] */
- "NONE", /* [D_NONE] */
+ "MAXREG", /* [MAXREG] */
};
static int
int r;
r = va_arg(fp->args, int);
- if(r >= D_AL && r <= D_NONE)
- sprint(str, "%s", regstr[r-D_AL]);
+ if(r == REG_NONE)
+ return fmtstrcpy(fp, "NONE");
+
+ if(REG_AL <= r && r-REG_AL < nelem(regstr))
+ sprint(str, "%s", regstr[r-REG_AL]);
else
sprint(str, "gok(%d)", r);
#include <bio.h>
#include <link.h>
#include "../cmd/8l/8.out.h"
+#include "../runtime/funcdata.h"
static int Aconv(Fmt *fp);
static int Dconv(Fmt *fp);
bigP = p;
switch(p->as) {
case ADATA:
- sprint(str, "%.5lld (%L) %A %D/%d,%D",
- p->pc, p->lineno, p->as, &p->from, p->from.scale, &p->to);
+ sprint(str, "%.5lld (%L) %A %D/%lld,%D",
+ p->pc, p->lineno, p->as, &p->from, p->from3.offset, &p->to);
break;
case ATEXT:
- if(p->from.scale) {
- sprint(str, "%.5lld (%L) %A %D,%d,%lD",
- p->pc, p->lineno, p->as, &p->from, p->from.scale, &p->to);
+ if(p->from3.offset) {
+ sprint(str, "%.5lld (%L) %A %D,%lld,%D",
+ p->pc, p->lineno, p->as, &p->from, p->from3.offset, &p->to);
break;
}
- sprint(str, "%.5lld (%L) %A %D,%lD",
+ sprint(str, "%.5lld (%L) %A %D,%D",
p->pc, p->lineno, p->as, &p->from, &p->to);
break;
{
char str[STRINGSZ], s[STRINGSZ];
Addr *a;
- int i;
a = va_arg(fp->args, Addr*);
- i = a->type;
-
- if(fp->flags & FmtLong) {
- if(i == D_CONST2)
- sprint(str, "$%lld-%d", a->offset, a->offset2);
- else {
- // ATEXT dst is not constant
- sprint(str, "!!%D", a);
- }
- goto brk;
- }
-
- if(i >= D_INDIR) {
- if(a->offset)
- sprint(str, "%lld(%R)", a->offset, i-D_INDIR);
- else
- sprint(str, "(%R)", i-D_INDIR);
- goto brk;
- }
- switch(i) {
+
+ switch(a->type) {
default:
- if(a->offset)
- sprint(str, "$%lld,%R", a->offset, i);
- else
- sprint(str, "%R", i);
+ sprint(str, "type=%d", a->type);
break;
- case D_NONE:
+ case TYPE_NONE:
str[0] = 0;
break;
+
+ case TYPE_REG:
+ // TODO(rsc): This special case is for instructions like
+ // PINSRQ CX,$1,X6
+ // where the $1 is included in the p->to Addr.
+ // Move into a new field.
+ if(a->offset != 0) {
+ sprint(str, "$%lld,%R", a->offset, a->reg);
+ break;
+ }
+ sprint(str, "%R", a->reg);
+ // TODO(rsc): This special case is for SHRQ $32, AX:DX, which encodes as
+ // SHRQ $32(DX*0), AX
+ // Remove.
+ if(a->index != REG_NONE) {
+ sprint(s, "(%R*%d)", (int)a->index, (int)a->scale);
+ strcat(str, s);
+ }
+ break;
- case D_BRANCH:
+ case TYPE_BRANCH:
if(a->sym != nil)
sprint(str, "%s(SB)", a->sym->name);
else if(bigP != nil && bigP->pcond != nil)
sprint(str, "%lld(PC)", a->offset);
break;
- case D_EXTERN:
- sprint(str, "%s+%lld(SB)", a->sym->name, a->offset);
- break;
-
- case D_STATIC:
- sprint(str, "%s<>+%lld(SB)", a->sym->name, a->offset);
- break;
-
- case D_AUTO:
- if(a->sym)
- sprint(str, "%s+%lld(SP)", a->sym->name, a->offset);
- else
- sprint(str, "%lld(SP)", a->offset);
- break;
-
- case D_PARAM:
- if(a->sym)
- sprint(str, "%s+%lld(FP)", a->sym->name, a->offset);
- else
- sprint(str, "%lld(FP)", a->offset);
+ case TYPE_MEM:
+ switch(a->name) {
+ default:
+ sprint(str, "name=%d", a->name);
+ break;
+ case NAME_NONE:
+ if(a->offset)
+ sprint(str, "%lld(%R)", a->offset, a->reg);
+ else
+ sprint(str, "(%R)", a->reg);
+ break;
+ case NAME_EXTERN:
+ sprint(str, "%s+%lld(SB)", a->sym->name, a->offset);
+ break;
+ case NAME_STATIC:
+ sprint(str, "%s<>+%lld(SB)", a->sym->name, a->offset);
+ break;
+ case NAME_AUTO:
+ if(a->sym)
+ sprint(str, "%s+%lld(SP)", a->sym->name, a->offset);
+ else
+ sprint(str, "%lld(SP)", a->offset);
+ break;
+ case NAME_PARAM:
+ if(a->sym)
+ sprint(str, "%s+%lld(FP)", a->sym->name, a->offset);
+ else
+ sprint(str, "%lld(FP)", a->offset);
+ break;
+ }
+ if(a->index != REG_NONE) {
+ sprint(s, "(%R*%d)", (int)a->index, (int)a->scale);
+ strcat(str, s);
+ }
break;
- case D_CONST:
+ case TYPE_CONST:
sprint(str, "$%lld", a->offset);
+ // TODO(rsc): This special case is for SHRQ $32, AX:DX, which encodes as
+ // SHRQ $32(DX*0), AX
+ // Remove.
+ if(a->index != REG_NONE) {
+ sprint(s, "(%R*%d)", (int)a->index, (int)a->scale);
+ strcat(str, s);
+ }
break;
- case D_CONST2:
- if(!(fp->flags & FmtLong)) {
- // D_CONST2 outside of ATEXT should not happen
- sprint(str, "!!$%lld-%d", a->offset, a->offset2);
- }
+ case TYPE_TEXTSIZE:
+ if(a->u.argsize == ArgsSizeUnknown)
+ sprint(str, "$%lld", a->offset);
+ else
+ sprint(str, "$%lld-%lld", a->offset, a->u.argsize);
break;
- case D_FCONST:
+ case TYPE_FCONST:
sprint(str, "$(%.17g)", a->u.dval);
break;
- case D_SCONST:
+ case TYPE_SCONST:
sprint(str, "$\"%$\"", a->u.sval);
break;
- case D_ADDR:
- a->type = a->index;
- a->index = D_NONE;
+ case TYPE_ADDR:
+ a->type = TYPE_MEM;
sprint(str, "$%D", a);
- a->index = a->type;
- a->type = D_ADDR;
- goto conv;
- }
-brk:
- if(a->index != D_NONE) {
- sprint(s, "(%R*%d)", (int)a->index, (int)a->scale);
- strcat(str, s);
+ a->type = TYPE_ADDR;
+ break;
}
-conv:
+
return fmtstrcpy(fp, str);
}
static char* regstr[] =
{
- "AL", /* [D_AL] */
+ "AL", /* [REG_AL] */
"CL",
"DL",
"BL",
"DH",
"BH",
- "AX", /* [D_AX] */
+ "AX", /* [REG_AX] */
"CX",
"DX",
"BX",
"SI",
"DI",
- "F0", /* [D_F0] */
+ "F0", /* [REG_F0] */
"F1",
"F2",
"F3",
"F6",
"F7",
- "CS", /* [D_CS] */
+ "CS", /* [REG_CS] */
"SS",
"DS",
"ES",
"FS",
"GS",
- "GDTR", /* [D_GDTR] */
- "IDTR", /* [D_IDTR] */
- "LDTR", /* [D_LDTR] */
- "MSW", /* [D_MSW] */
- "TASK", /* [D_TASK] */
+ "GDTR", /* [REG_GDTR] */
+ "IDTR", /* [REG_IDTR] */
+ "LDTR", /* [REG_LDTR] */
+ "MSW", /* [REG_MSW] */
+ "TASK", /* [REG_TASK] */
- "CR0", /* [D_CR] */
+ "CR0", /* [REG_CR] */
"CR1",
"CR2",
"CR3",
"CR6",
"CR7",
- "DR0", /* [D_DR] */
+ "DR0", /* [REG_DR] */
"DR1",
"DR2",
"DR3",
"DR6",
"DR7",
- "TR0", /* [D_TR] */
+ "TR0", /* [REG_TR] */
"TR1",
"TR2",
"TR3",
"TR6",
"TR7",
- "X0", /* [D_X0] */
+ "X0", /* [REG_X0] */
"X1",
"X2",
"X3",
"X6",
"X7",
- "TLS", /* [D_TLS] */
- "NONE", /* [D_NONE] */
+ "TLS", /* [REG_TLS] */
+ "MAXREG", /* [MAXREG] */
};
static int
int r;
r = va_arg(fp->args, int);
- if(r >= D_AL && r <= D_NONE)
- sprint(str, "%s", regstr[r-D_AL]);
+ if(r == REG_NONE)
+ return fmtstrcpy(fp, "NONE");
+ if(r >= REG_AL && r-REG_AL < nelem(regstr))
+ sprint(str, "%s", regstr[r-REG_AL]);
else
sprint(str, "gok(%d)", r);
#include <bio.h>
#include <link.h>
#include "../cmd/9l/9.out.h"
+#include "../runtime/funcdata.h"
enum
{
// %A int Opcodes (instruction mnemonics)
//
// %D Addr* Addresses (instruction operands)
-// Flags: "%lD": seperate the high and low words of a constant by "-"
//
// %P Prog* Instructions
//
{
char str[STRINGSZ];
Prog *p;
- int a, ch;
+ int a;
p = va_arg(fp->args, Prog*);
bigP = p;
a = p->as;
- if(a == ADATA || a == AINIT || a == ADYNT)
- sprint(str, "%.5lld (%L) %A %D/%d,%D", p->pc, p->lineno, a, &p->from, p->reg, &p->to);
- else if(a == ATEXT) {
- if(p->reg != 0)
- sprint(str, "%.5lld (%L) %A %D,%d,%lD", p->pc, p->lineno, a, &p->from, p->reg, &p->to);
- else
- sprint(str, "%.5lld (%L) %A %D,%lD", p->pc, p->lineno, a, &p->from, &p->to);
- } else if(a == AGLOBL) {
- if(p->reg != 0)
- sprint(str, "%.5lld (%L) %A %D,%d,%D", p->pc, p->lineno, a, &p->from, p->reg, &p->to);
+ str[0] = 0;
+ if(a == ADATA)
+ sprint(str, "%.5lld (%L) %A %D/%lld,%D", p->pc, p->lineno, a, &p->from, p->from3.offset, &p->to);
+ else if(a == ATEXT || a == AGLOBL) {
+ if(p->from3.offset != 0)
+ sprint(str, "%.5lld (%L) %A %D,%lld,%D", p->pc, p->lineno, a, &p->from, p->from3.offset, &p->to);
else
- sprint(str, "%.5lld (%L) %A %D,%D", p->pc, p->lineno, a, &p->from, &p->to);
+ sprint(str, "%.5lld (%L) %A %D,%D", p->pc, p->lineno, a, &p->from, &p->to);
} else {
if(p->mark & NOSCHED)
sprint(strchr(str, 0), "*");
- if(p->reg == NREG && p->from3.type == D_NONE)
+ if(p->reg == 0 && p->from3.type == TYPE_NONE)
sprint(strchr(str, 0), "%.5lld (%L) %A %D,%D", p->pc, p->lineno, a, &p->from, &p->to);
else
- if(a != ATEXT && p->from.type == D_OREG) {
- sprint(strchr(str, 0), "%.5lld (%L) %A %lld(R%d+R%d),%D", p->pc, p->lineno, a,
+ if(a != ATEXT && p->from.type == TYPE_MEM) {
+ sprint(strchr(str, 0), "%.5lld (%L) %A %lld(%R+%R),%D", p->pc, p->lineno, a,
p->from.offset, p->from.reg, p->reg, &p->to);
} else
- if(p->to.type == D_OREG) {
- sprint(strchr(str, 0), "%.5lld (%L) %A %D,%lld(R%d+R%d)", p->pc, p->lineno, a,
+ if(p->to.type == TYPE_MEM) {
+ sprint(strchr(str, 0), "%.5lld (%L) %A %D,%lld(%R+%R)", p->pc, p->lineno, a,
&p->from, p->to.offset, p->to.reg, p->reg);
} else {
sprint(strchr(str, 0), "%.5lld (%L) %A %D", p->pc, p->lineno, a, &p->from);
- if(p->reg != NREG) {
- ch = 'R';
- if(p->from.type == D_FREG)
- ch = 'F';
- sprint(strchr(str, 0), ",%c%d", ch, p->reg);
- }
- if(p->from3.type != D_NONE)
+ if(p->reg != 0)
+ sprint(strchr(str, 0), ",%R", p->reg);
+ if(p->from3.type != TYPE_NONE)
sprint(strchr(str, 0), ",%D", &p->from3);
sprint(strchr(str, 0), ",%D", &p->to);
}
a = va_arg(fp->args, Addr*);
- if(fp->flags & FmtLong) {
- if(a->type == D_CONST)
- sprint(str, "$%d-%d", (int32)a->offset, (int32)(a->offset>>32));
- else {
- // ATEXT dst is not constant
- sprint(str, "!!%D", a);
- }
- goto ret;
- }
-
switch(a->type) {
default:
sprint(str, "GOK-type(%d)", a->type);
break;
- case D_NONE:
+ case TYPE_NONE:
str[0] = 0;
- if(a->name != D_NONE || a->reg != NREG || a->sym != nil)
- sprint(str, "%M(R%d)(NONE)", a, a->reg);
+ if(a->name != TYPE_NONE || a->reg != 0 || a->sym != nil)
+ sprint(str, "%M(%R)(NONE)", a, a->reg);
break;
- case D_CONST:
- case D_DCONST:
- if(a->reg != NREG)
- sprint(str, "$%M(R%d)", a, a->reg);
+ case TYPE_CONST:
+ case TYPE_ADDR:
+ if(a->reg != 0)
+ sprint(str, "$%M(%R)", a, a->reg);
else
sprint(str, "$%M", a);
break;
- case D_OREG:
- if(a->reg != NREG)
- sprint(str, "%M(R%d)", a, a->reg);
- else
- sprint(str, "%M", a);
- break;
-
- case D_REG:
- sprint(str, "R%d", a->reg);
- if(a->name != D_NONE || a->sym != nil)
- sprint(str, "%M(R%d)(REG)", a, a->reg);
- break;
-
- case D_FREG:
- sprint(str, "F%d", a->reg);
- if(a->name != D_NONE || a->sym != nil)
- sprint(str, "%M(F%d)(REG)", a, a->reg);
- break;
-
- case D_CREG:
- if(a->reg == NREG)
- strcpy(str, "CR");
+ case TYPE_TEXTSIZE:
+ if(a->u.argsize == ArgsSizeUnknown)
+ sprint(str, "$%lld", a->offset);
else
- sprint(str, "CR%d", a->reg);
- if(a->name != D_NONE || a->sym != nil)
- sprint(str, "%M(C%d)(REG)", a, a->reg);
+ sprint(str, "$%lld-%lld", a->offset, a->u.argsize);
break;
- case D_SPR:
- if(a->name == D_NONE && a->sym == nil) {
- switch((ulong)a->offset) {
- case D_XER: sprint(str, "XER"); break;
- case D_LR: sprint(str, "LR"); break;
- case D_CTR: sprint(str, "CTR"); break;
- default: sprint(str, "SPR(%lld)", a->offset); break;
- }
- break;
- }
- sprint(str, "SPR-GOK(%d)", a->reg);
- if(a->name != D_NONE || a->sym != nil)
- sprint(str, "%M(SPR-GOK%d)(REG)", a, a->reg);
- break;
-
- case D_DCR:
- if(a->name == D_NONE && a->sym == nil) {
- sprint(str, "DCR(%lld)", a->offset);
- break;
- }
- sprint(str, "DCR-GOK(%d)", a->reg);
- if(a->name != D_NONE || a->sym != nil)
- sprint(str, "%M(DCR-GOK%d)(REG)", a, a->reg);
- break;
-
- case D_OPT:
- sprint(str, "OPT(%d)", a->reg);
- break;
-
- case D_FPSCR:
- if(a->reg == NREG)
- strcpy(str, "FPSCR");
+ case TYPE_MEM:
+ if(a->reg != 0)
+ sprint(str, "%M(%R)", a, a->reg);
else
- sprint(str, "FPSCR(%d)", a->reg);
+ sprint(str, "%M", a);
break;
- case D_MSR:
- sprint(str, "MSR");
+ case TYPE_REG:
+ sprint(str, "%R", a->reg);
+ if(a->name != TYPE_NONE || a->sym != nil)
+ sprint(str, "%M(%R)(REG)", a, a->reg);
break;
- case D_BRANCH:
+ case TYPE_BRANCH:
if(bigP->pcond != nil) {
v = bigP->pcond->pc;
//if(v >= INITTEXT)
sprint(str, "%lld(APC)", a->offset);
break;
- case D_FCONST:
+ case TYPE_FCONST:
//sprint(str, "$%lux-%lux", a->ieee.h, a->ieee.l);
sprint(str, "$%.17g", a->u.dval);
break;
- case D_SCONST:
+ case TYPE_SCONST:
sprint(str, "$\"%$\"", a->u.sval);
break;
}
-ret:
return fmtstrcpy(fp, str);
}
sprint(str, "GOK-name(%d)", a->name);
break;
- case D_NONE:
+ case TYPE_NONE:
l = a->offset;
if((vlong)l != a->offset)
sprint(str, "0x%llux", a->offset);
sprint(str, "%lld", a->offset);
break;
- case D_EXTERN:
+ case NAME_EXTERN:
if(a->offset != 0)
sprint(str, "%s+%lld(SB)", s->name, a->offset);
else
sprint(str, "%s(SB)", s->name);
break;
- case D_STATIC:
+ case NAME_STATIC:
sprint(str, "%s<>+%lld(SB)", s->name, a->offset);
break;
- case D_AUTO:
+ case NAME_AUTO:
if(s == nil)
sprint(str, "%lld(SP)", -a->offset);
else
sprint(str, "%s-%lld(SP)", s->name, -a->offset);
break;
- case D_PARAM:
+ case NAME_PARAM:
if(s == nil)
sprint(str, "%lld(FP)", a->offset);
else
static int
Rconv(Fmt *fp)
{
- char str[STRINGSZ];
int r;
r = va_arg(fp->args, int);
- if(r < NREG)
- sprint(str, "r%d", r);
- else
- sprint(str, "f%d", r-NREG);
- return fmtstrcpy(fp, str);
+ if(r == 0)
+ return fmtstrcpy(fp, "NONE");
+ if(REG_R0 <= r && r <= REG_R31)
+ return fmtprint(fp, "R%d", r-REG_R0);
+ if(REG_F0 <= r && r <= REG_F31)
+ return fmtprint(fp, "F%d", r-REG_F0);
+ if(REG_C0 <= r && r <= REG_C7)
+ return fmtprint(fp, "C%d", r-REG_C0);
+ if(r == REG_CR)
+ return fmtstrcpy(fp, "CR");
+ if(REG_SPR0 <= r && r <= REG_SPR0+1023) {
+ switch(r) {
+ case REG_XER:
+ return fmtstrcpy(fp, "XER");
+ case REG_LR:
+ return fmtstrcpy(fp, "LR");
+ case REG_CTR:
+ return fmtstrcpy(fp, "CTR");
+ }
+ return fmtprint(fp, "SPR(%d)", r-REG_SPR0);
+ }
+ if(REG_DCR0 <= r && r <= REG_DCR0+1023)
+ return fmtprint(fp, "DCR(%d)", r-REG_DCR0);
+ if(r == REG_FPSCR)
+ return fmtstrcpy(fp, "FPSCR");
+ if(r == REG_MSR)
+ return fmtstrcpy(fp, "MSR");
+
+ return fmtprint(fp, "badreg(%d)", r);
}
static int
#include "../cmd/5l/5.out.h"
#include "../runtime/stack.h"
-static Prog zprg5 = {
- .as = AGOK,
- .scond = C_SCOND_NONE,
- .reg = NREG,
- .from = {
- .name = D_NONE,
- .type = D_NONE,
- .reg = NREG,
- },
- .to = {
- .name = D_NONE,
- .type = D_NONE,
- .reg = NREG,
- },
-};
-
-static int
-symtype(Addr *a)
-{
- return a->name;
-}
-
-static int
-isdata(Prog *p)
-{
- return p->as == ADATA || p->as == AGLOBL;
-}
-
-static int
-iscall(Prog *p)
-{
- return p->as == ABL;
-}
-
-static int
-datasize(Prog *p)
-{
- return p->reg;
-}
-
-static int
-textflag(Prog *p)
-{
- return p->reg;
-}
-
-static void
-settextflag(Prog *p, int f)
-{
- p->reg = f;
-}
-
static void
progedit(Link *ctxt, Prog *p)
{
p->from.class = 0;
p->to.class = 0;
- // Rewrite B/BL to symbol as D_BRANCH.
+ // Rewrite B/BL to symbol as TYPE_BRANCH.
switch(p->as) {
case AB:
case ABL:
case ADUFFZERO:
case ADUFFCOPY:
- if(p->to.type == D_OREG && (p->to.name == D_EXTERN || p->to.name == D_STATIC) && p->to.sym != nil)
- p->to.type = D_BRANCH;
+ if(p->to.type == TYPE_MEM && (p->to.name == NAME_EXTERN || p->to.name == NAME_STATIC) && p->to.sym != nil)
+ p->to.type = TYPE_BRANCH;
break;
}
tlsfallback = linklookup(ctxt, "runtime.read_tls_fallback", 0);
// MOVW LR, R11
p->as = AMOVW;
- p->from.type = D_REG;
+ p->from.type = TYPE_REG;
p->from.reg = REGLINK;
- p->to.type = D_REG;
+ p->to.type = TYPE_REG;
p->to.reg = REGTMP;
// BL runtime.read_tls_fallback(SB)
p = appendp(ctxt, p);
p->as = ABL;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
p->to.sym = tlsfallback;
p->to.offset = 0;
// MOVW R11, LR
p = appendp(ctxt, p);
p->as = AMOVW;
- p->from.type = D_REG;
+ p->from.type = TYPE_REG;
p->from.reg = REGTMP;
- p->to.type = D_REG;
+ p->to.type = TYPE_REG;
p->to.reg = REGLINK;
break;
}
// Rewrite float constants to values stored in memory.
switch(p->as) {
case AMOVF:
- if(p->from.type == D_FCONST && chipfloat5(ctxt, p->from.u.dval) < 0 &&
+ if(p->from.type == TYPE_FCONST && chipfloat5(ctxt, p->from.u.dval) < 0 &&
(chipzero5(ctxt, p->from.u.dval) < 0 || (p->scond & C_SCOND) != C_SCOND_NONE)) {
uint32 i32;
float32 f32;
adduint32(ctxt, s, i32);
s->reachable = 0;
}
- p->from.type = D_OREG;
+ p->from.type = TYPE_MEM;
p->from.sym = s;
- p->from.name = D_EXTERN;
+ p->from.name = NAME_EXTERN;
p->from.offset = 0;
}
break;
case AMOVD:
- if(p->from.type == D_FCONST && chipfloat5(ctxt, p->from.u.dval) < 0 &&
+ if(p->from.type == TYPE_FCONST && chipfloat5(ctxt, p->from.u.dval) < 0 &&
(chipzero5(ctxt, p->from.u.dval) < 0 || (p->scond & C_SCOND) != C_SCOND_NONE)) {
uint64 i64;
memmove(&i64, &p->from.u.dval, 8);
adduint64(ctxt, s, i64);
s->reachable = 0;
}
- p->from.type = D_OREG;
+ p->from.type = TYPE_MEM;
p->from.sym = s;
- p->from.name = D_EXTERN;
+ p->from.name = NAME_EXTERN;
p->from.offset = 0;
}
break;
if(ctxt->tlsg == nil)
ctxt->tlsg = linklookup(ctxt, "runtime.tlsg", 0);
- if(p->from.type == D_CONST && p->from.name == D_EXTERN && p->from.sym == ctxt->tlsg)
- p->from.type = D_OREG;
- if(p->to.type == D_CONST && p->to.name == D_EXTERN && p->to.sym == ctxt->tlsg)
- p->to.type = D_OREG;
+ if(p->from.type == TYPE_ADDR && p->from.name == NAME_EXTERN && p->from.sym == ctxt->tlsg)
+ p->from.type = TYPE_MEM;
+ if(p->to.type == TYPE_ADDR && p->to.name == NAME_EXTERN && p->to.sym == ctxt->tlsg)
+ p->to.type = TYPE_MEM;
}
}
-static Prog*
-prg(void)
-{
- Prog *p;
-
- p = emallocz(sizeof(*p));
- *p = zprg5;
- return p;
-}
-
static Prog* stacksplit(Link*, Prog*, int32, int);
static void initdiv(Link*);
static void softfloat(Link*, LSym*);
}
static void
-addstacksplit(Link *ctxt, LSym *cursym)
+preprocess(Link *ctxt, LSym *cursym)
{
Prog *p, *pl, *p1, *p2, *q, *q1, *q2;
int o;
if(autoffset < 0)
autoffset = 0;
cursym->locals = autoffset;
- cursym->args = p->to.offset2;
+ cursym->args = p->to.u.argsize;
if(ctxt->debugzerostack) {
- if(autoffset && !(p->reg&NOSPLIT)) {
+ if(autoffset && !(p->from3.offset&NOSPLIT)) {
// MOVW $4(R13), R1
p = appendp(ctxt, p);
p->as = AMOVW;
- p->from.type = D_CONST;
- p->from.reg = 13;
+ p->from.type = TYPE_ADDR;
+ p->from.reg = REG_R13;
p->from.offset = 4;
- p->to.type = D_REG;
- p->to.reg = 1;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_R1;
// MOVW $n(R13), R2
p = appendp(ctxt, p);
p->as = AMOVW;
- p->from.type = D_CONST;
- p->from.reg = 13;
+ p->from.type = TYPE_ADDR;
+ p->from.reg = REG_R13;
p->from.offset = 4 + autoffset;
- p->to.type = D_REG;
- p->to.reg = 2;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_R2;
// MOVW $0, R3
p = appendp(ctxt, p);
p->as = AMOVW;
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = 0;
- p->to.type = D_REG;
- p->to.reg = 3;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_R3;
// L:
// MOVW.nil R3, 0(R1) +4
// BNE L
p = pl = appendp(ctxt, p);
p->as = AMOVW;
- p->from.type = D_REG;
- p->from.reg = 3;
- p->to.type = D_OREG;
- p->to.reg = 1;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_R3;
+ p->to.type = TYPE_MEM;
+ p->to.reg = REG_R1;
p->to.offset = 4;
p->scond |= C_PBIT;
p = appendp(ctxt, p);
p->as = ACMP;
- p->from.type = D_REG;
- p->from.reg = 1;
- p->reg = 2;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_R1;
+ p->reg = REG_R2;
p = appendp(ctxt, p);
p->as = ABNE;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
p->pcond = pl;
}
}
break;
}
- if(!(p->reg & NOSPLIT))
- p = stacksplit(ctxt, p, autosize, !(cursym->text->reg&NEEDCTXT)); // emit split check
+ if(!(p->from3.offset & NOSPLIT))
+ p = stacksplit(ctxt, p, autosize, !(cursym->text->from3.offset&NEEDCTXT)); // emit split check
// MOVW.W R14,$-autosize(SP)
p = appendp(ctxt, p);
p->as = AMOVW;
p->scond |= C_WBIT;
- p->from.type = D_REG;
+ p->from.type = TYPE_REG;
p->from.reg = REGLINK;
- p->to.type = D_OREG;
+ p->to.type = TYPE_MEM;
p->to.offset = -autosize;
p->to.reg = REGSP;
p->spadj = autosize;
- if(cursym->text->reg & WRAPPER) {
+ if(cursym->text->from3.offset & WRAPPER) {
// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
//
// MOVW g_panic(g), R1
p = appendp(ctxt, p);
p->as = AMOVW;
- p->from.type = D_OREG;
+ p->from.type = TYPE_MEM;
p->from.reg = REGG;
p->from.offset = 4*ctxt->arch->ptrsize; // G.panic
- p->to.type = D_REG;
- p->to.reg = 1;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_R1;
p = appendp(ctxt, p);
p->as = ACMP;
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = 0;
- p->reg = 1;
+ p->reg = REG_R1;
p = appendp(ctxt, p);
p->as = ABEQ;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
p1 = p;
p = appendp(ctxt, p);
p->as = AMOVW;
- p->from.type = D_OREG;
- p->from.reg = 1;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_R1;
p->from.offset = 0; // Panic.argp
- p->to.type = D_REG;
- p->to.reg = 2;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_R2;
p = appendp(ctxt, p);
p->as = AADD;
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = autosize+4;
- p->reg = 13;
- p->to.type = D_REG;
- p->to.reg = 3;
+ p->reg = REG_R13;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_R3;
p = appendp(ctxt, p);
p->as = ACMP;
- p->from.type = D_REG;
- p->from.reg = 2;
- p->reg = 3;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_R2;
+ p->reg = REG_R3;
p = appendp(ctxt, p);
p->as = ABNE;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
p2 = p;
p = appendp(ctxt, p);
p->as = AADD;
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = 4;
- p->reg = 13;
- p->to.type = D_REG;
- p->to.reg = 4;
+ p->reg = REG_R13;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_R4;
p = appendp(ctxt, p);
p->as = AMOVW;
- p->from.type = D_REG;
- p->from.reg = 4;
- p->to.type = D_OREG;
- p->to.reg = 1;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_R4;
+ p->to.type = TYPE_MEM;
+ p->to.reg = REG_R1;
p->to.offset = 0; // Panic.argp
p = appendp(ctxt, p);
if(cursym->text->mark & LEAF) {
if(!autosize) {
p->as = AB;
- p->from = zprg5.from;
+ p->from = zprog.from;
if(p->to.sym) { // retjmp
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
} else {
- p->to.type = D_OREG;
+ p->to.type = TYPE_MEM;
p->to.offset = 0;
p->to.reg = REGLINK;
}
p->as = AMOVW;
p->scond |= C_PBIT;
- p->from.type = D_OREG;
+ p->from.type = TYPE_MEM;
p->from.offset = autosize;
p->from.reg = REGSP;
- p->to.type = D_REG;
+ p->to.type = TYPE_REG;
p->to.reg = REGPC;
// If there are instructions following
// this ARET, they come from a branch
p->to.reg = REGLINK;
q2 = appendp(ctxt, p);
q2->as = AB;
- q2->to.type = D_BRANCH;
+ q2->to.type = TYPE_BRANCH;
q2->to.sym = p->to.sym;
p->to.sym = nil;
p = q2;
break;
case AADD:
- if(p->from.type == D_CONST && p->from.reg == NREG && p->to.type == D_REG && p->to.reg == REGSP)
+ if(p->from.type == TYPE_CONST && p->from.reg == 0 && p->to.type == TYPE_REG && p->to.reg == REGSP)
p->spadj = -p->from.offset;
break;
case ASUB:
- if(p->from.type == D_CONST && p->from.reg == NREG && p->to.type == D_REG && p->to.reg == REGSP)
+ if(p->from.type == TYPE_CONST && p->from.reg == 0 && p->to.type == TYPE_REG && p->to.reg == REGSP)
p->spadj = p->from.offset;
break;
case AMODU:
if(ctxt->debugdivmod)
break;
- if(p->from.type != D_REG)
+ if(p->from.type != TYPE_REG)
break;
- if(p->to.type != D_REG)
+ if(p->to.type != TYPE_REG)
break;
q1 = p;
p = appendp(ctxt, p);
p->as = AMOVW;
p->lineno = q1->lineno;
- p->from.type = D_REG;
+ p->from.type = TYPE_REG;
p->from.reg = q1->from.reg;
- p->to.type = D_OREG;
+ p->to.type = TYPE_MEM;
p->to.reg = REGSP;
p->to.offset = 4;
p = appendp(ctxt, p);
p->as = AMOVW;
p->lineno = q1->lineno;
- p->from.type = D_REG;
+ p->from.type = TYPE_REG;
p->from.reg = q1->reg;
- if(q1->reg == NREG)
+ if(q1->reg == 0)
p->from.reg = q1->to.reg;
- p->to.type = D_REG;
+ p->to.type = TYPE_REG;
p->to.reg = REGTMP;
p->to.offset = 0;
p = appendp(ctxt, p);
p->as = ABL;
p->lineno = q1->lineno;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
switch(o) {
case ADIV:
p->to.sym = ctxt->sym_div;
p = appendp(ctxt, p);
p->as = AMOVW;
p->lineno = q1->lineno;
- p->from.type = D_REG;
+ p->from.type = TYPE_REG;
p->from.reg = REGTMP;
p->from.offset = 0;
- p->to.type = D_REG;
+ p->to.type = TYPE_REG;
p->to.reg = q1->to.reg;
/* ADD $8,SP */
p = appendp(ctxt, p);
p->as = AADD;
p->lineno = q1->lineno;
- p->from.type = D_CONST;
- p->from.reg = NREG;
+ p->from.type = TYPE_CONST;
+ p->from.reg = 0;
p->from.offset = 8;
- p->reg = NREG;
- p->to.type = D_REG;
+ p->reg = 0;
+ p->to.type = TYPE_REG;
p->to.reg = REGSP;
p->spadj = -8;
/* MOVW 0(SP), REGTMP; MOVW REGTMP, -8!(SP) */
/* TODO: Remove SP adjustments; see issue 6699. */
q1->as = AMOVW;
- q1->from.type = D_OREG;
+ q1->from.type = TYPE_MEM;
q1->from.reg = REGSP;
q1->from.offset = 0;
- q1->reg = NREG;
- q1->to.type = D_REG;
+ q1->reg = 0;
+ q1->to.type = TYPE_REG;
q1->to.reg = REGTMP;
/* SUB $8,SP */
q1 = appendp(ctxt, q1);
q1->as = AMOVW;
- q1->from.type = D_REG;
+ q1->from.type = TYPE_REG;
q1->from.reg = REGTMP;
- q1->reg = NREG;
- q1->to.type = D_OREG;
+ q1->reg = 0;
+ q1->to.type = TYPE_MEM;
q1->to.reg = REGSP;
q1->to.offset = -8;
q1->scond |= C_WBIT;
break;
case AMOVW:
- if((p->scond & C_WBIT) && p->to.type == D_OREG && p->to.reg == REGSP)
+ if((p->scond & C_WBIT) && p->to.type == TYPE_MEM && p->to.reg == REGSP)
p->spadj = -p->to.offset;
- if((p->scond & C_PBIT) && p->from.type == D_OREG && p->from.reg == REGSP && p->to.reg != REGPC)
+ if((p->scond & C_PBIT) && p->from.type == TYPE_MEM && p->from.reg == REGSP && p->to.reg != REGPC)
p->spadj = -p->from.offset;
- if(p->from.type == D_CONST && p->from.reg == REGSP && p->to.type == D_REG && p->to.reg == REGSP)
+ if(p->from.type == TYPE_ADDR && p->from.reg == REGSP && p->to.type == TYPE_REG && p->to.reg == REGSP)
p->spadj = -p->from.offset;
break;
}
}
}
+static int
+isfloatreg(Addr *a)
+{
+ return a->type == TYPE_REG && REG_F0 <= a->reg && a->reg <= REG_F15;
+}
+
static void
softfloat(Link *ctxt, LSym *cursym)
{
for(p = cursym->text; p != nil; p = p->link) {
switch(p->as) {
case AMOVW:
- if(p->to.type == D_FREG || p->from.type == D_FREG)
+ if(isfloatreg(&p->to) || isfloatreg(&p->from))
goto soft;
goto notsoft;
soft:
if (!wasfloat || (p->mark&LABEL)) {
- next = ctxt->arch->prg();
+ next = emallocz(sizeof(Prog));
*next = *p;
// BL _sfloat(SB)
- *p = zprg5;
+ *p = zprog;
p->link = next;
p->as = ABL;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
p->to.sym = symsfloat;
p->lineno = next->lineno;
// MOVW g_stackguard(g), R1
p = appendp(ctxt, p);
p->as = AMOVW;
- p->from.type = D_OREG;
+ p->from.type = TYPE_MEM;
p->from.reg = REGG;
p->from.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
if(ctxt->cursym->cfunc)
p->from.offset = 3*ctxt->arch->ptrsize; // G.stackguard1
- p->to.type = D_REG;
- p->to.reg = 1;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_R1;
if(framesize <= StackSmall) {
// small stack: SP < stackguard
// CMP stackguard, SP
p = appendp(ctxt, p);
p->as = ACMP;
- p->from.type = D_REG;
- p->from.reg = 1;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_R1;
p->reg = REGSP;
} else if(framesize <= StackBig) {
// large stack: SP-framesize < stackguard-StackSmall
// CMP stackguard, R2
p = appendp(ctxt, p);
p->as = AMOVW;
- p->from.type = D_CONST;
+ p->from.type = TYPE_ADDR;
p->from.reg = REGSP;
p->from.offset = -framesize;
- p->to.type = D_REG;
- p->to.reg = 2;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_R2;
p = appendp(ctxt, p);
p->as = ACMP;
- p->from.type = D_REG;
- p->from.reg = 1;
- p->reg = 2;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_R1;
+ p->reg = REG_R2;
} else {
// Such a large stack we need to protect against wraparound
// if SP is close to zero.
// CMP.NE R3, R2
p = appendp(ctxt, p);
p->as = ACMP;
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = (uint32)StackPreempt;
- p->reg = 1;
+ p->reg = REG_R1;
p = appendp(ctxt, p);
p->as = AMOVW;
- p->from.type = D_CONST;
+ p->from.type = TYPE_ADDR;
p->from.reg = REGSP;
p->from.offset = StackGuard;
- p->to.type = D_REG;
- p->to.reg = 2;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_R2;
p->scond = C_SCOND_NE;
p = appendp(ctxt, p);
p->as = ASUB;
- p->from.type = D_REG;
- p->from.reg = 1;
- p->to.type = D_REG;
- p->to.reg = 2;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_R1;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_R2;
p->scond = C_SCOND_NE;
p = appendp(ctxt, p);
p->as = AMOVW;
- p->from.type = D_CONST;
+ p->from.type = TYPE_ADDR;
p->from.offset = framesize + (StackGuard - StackSmall);
- p->to.type = D_REG;
- p->to.reg = 3;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_R3;
p->scond = C_SCOND_NE;
p = appendp(ctxt, p);
p->as = ACMP;
- p->from.type = D_REG;
- p->from.reg = 3;
- p->reg = 2;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_R3;
+ p->reg = REG_R2;
p->scond = C_SCOND_NE;
}
p = appendp(ctxt, p);
p->as = AMOVW;
p->scond = C_SCOND_LS;
- p->from.type = D_REG;
+ p->from.type = TYPE_REG;
p->from.reg = REGLINK;
- p->to.type = D_REG;
- p->to.reg = 3;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_R3;
// BL.LS runtime.morestack(SB) // modifies LR, returns with LO still asserted
p = appendp(ctxt, p);
p->as = ABL;
p->scond = C_SCOND_LS;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
if(ctxt->cursym->cfunc)
p->to.sym = linklookup(ctxt, "runtime.morestackc", 0);
else
// BLS start
p = appendp(ctxt, p);
p->as = ABLS;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
p->pcond = ctxt->cursym->text->link;
return p;
ctxt->cursym = s;
- firstp = ctxt->arch->prg();
+ firstp = emallocz(sizeof(Prog));
lastp = firstp;
xfol(ctxt, s->text, &lastp);
lastp->link = nil;
continue;
copy:
for(;;) {
- r = ctxt->arch->prg();
+ r = emallocz(sizeof(Prog));
*r = *p;
if(!(r->mark&FOLL))
print("can't happen 1\n");
}
}
a = AB;
- q = ctxt->arch->prg();
+ q = emallocz(sizeof(Prog));
q->as = a;
q->lineno = p->lineno;
- q->to.type = D_BRANCH;
+ q->to.type = TYPE_BRANCH;
q->to.offset = p->pc;
q->pcond = p;
p = q;
.thechar = '5',
.endian = LittleEndian,
- .addstacksplit = addstacksplit,
+ .preprocess = preprocess,
.assemble = span5,
- .datasize = datasize,
.follow = follow,
- .iscall = iscall,
- .isdata = isdata,
- .prg = prg,
.progedit = progedit,
- .settextflag = settextflag,
- .symtype = symtype,
- .textflag = textflag,
.minlc = 4,
.ptrsize = 4,
.regsize = 4,
-
- .D_ADDR = D_ADDR,
- .D_AUTO = D_AUTO,
- .D_BRANCH = D_BRANCH,
- .D_CONST = D_CONST,
- .D_EXTERN = D_EXTERN,
- .D_FCONST = D_FCONST,
- .D_NONE = D_NONE,
- .D_PARAM = D_PARAM,
- .D_SCONST = D_SCONST,
- .D_STATIC = D_STATIC,
- .D_OREG = D_OREG,
-
- .ACALL = ABL,
- .ADATA = ADATA,
- .AEND = AEND,
- .AFUNCDATA = AFUNCDATA,
- .AGLOBL = AGLOBL,
- .AJMP = AB,
- .ANOP = ANOP,
- .APCDATA = APCDATA,
- .ARET = ARET,
- .ATEXT = ATEXT,
- .ATYPE = ATYPE,
- .AUSEFIELD = AUSEFIELD,
};
#include "../cmd/6l/6.out.h"
#include "../runtime/stack.h"
-static Prog zprg = {
- .back = 2,
- .as = AGOK,
- .from = {
- .type = D_NONE,
- .index = D_NONE,
- },
- .to = {
- .type = D_NONE,
- .index = D_NONE,
- },
-};
-
static void
nopout(Prog *p)
{
p->as = ANOP;
- p->from.type = D_NONE;
- p->to.type = D_NONE;
-}
-
-static int
-symtype(Addr *a)
-{
- int t;
-
- t = a->type;
- if(t == D_ADDR)
- t = a->index;
- return t;
-}
-
-static int
-isdata(Prog *p)
-{
- return p->as == ADATA || p->as == AGLOBL;
-}
-
-static int
-iscall(Prog *p)
-{
- return p->as == ACALL;
-}
-
-static int
-datasize(Prog *p)
-{
- return p->from.scale;
-}
-
-static int
-textflag(Prog *p)
-{
- return p->from.scale;
-}
-
-static void
-settextflag(Prog *p, int f)
-{
- p->from.scale = f;
+ p->from.type = TYPE_NONE;
+ p->from.reg = 0;
+ p->from.name = 0;
+ p->to.type = TYPE_NONE;
+ p->to.reg = 0;
+ p->to.name = 0;
}
static void nacladdr(Link*, Prog*, Addr*);
// TODO(rsc): Remove the Hsolaris special case. It exists only to
// guarantee we are producing byte-identical binaries as before this code.
// But it should be unnecessary.
- if((p->as == AMOVQ || p->as == AMOVL) && p->from.type == D_TLS && D_AX <= p->to.type && p->to.type <= D_R15 && ctxt->headtype != Hsolaris)
+ if((p->as == AMOVQ || p->as == AMOVL) && p->from.type == TYPE_REG && p->from.reg == REG_TLS && p->to.type == TYPE_REG && REG_AX <= p->to.reg && p->to.reg <= REG_R15 && ctxt->headtype != Hsolaris)
nopout(p);
- if(p->from.index == D_TLS && D_INDIR+D_AX <= p->from.type && p->from.type <= D_INDIR+D_R15) {
- p->from.type = D_INDIR+D_TLS;
+ if(p->from.type == TYPE_MEM && p->from.index == REG_TLS && REG_AX <= p->from.reg && p->from.reg <= REG_R15) {
+ p->from.reg = REG_TLS;
p->from.scale = 0;
- p->from.index = D_NONE;
+ p->from.index = REG_NONE;
}
- if(p->to.index == D_TLS && D_INDIR+D_AX <= p->to.type && p->to.type <= D_INDIR+D_R15) {
- p->to.type = D_INDIR+D_TLS;
+ if(p->to.type == TYPE_MEM && p->to.index == REG_TLS && REG_AX <= p->to.reg && p->to.reg <= REG_R15) {
+ p->to.reg = REG_TLS;
p->to.scale = 0;
- p->to.index = D_NONE;
+ p->to.index = REG_NONE;
}
} else {
// As a courtesy to the C compilers, rewrite TLS local exec load as TLS initial exec load.
// MOVQ TLS, BX
// MOVQ off(BX)(TLS*1), BX
// This allows the C compilers to emit references to m and g using the direct off(TLS) form.
- if((p->as == AMOVQ || p->as == AMOVL) && p->from.type == D_INDIR+D_TLS && D_AX <= p->to.type && p->to.type <= D_R15) {
+ if((p->as == AMOVQ || p->as == AMOVL) && p->from.type == TYPE_MEM && p->from.reg == REG_TLS && p->to.type == TYPE_REG && REG_AX <= p->to.reg && p->to.reg <= REG_R15) {
q = appendp(ctxt, p);
q->as = p->as;
q->from = p->from;
- q->from.type = D_INDIR + p->to.type;
- q->from.index = D_TLS;
+ q->from.type = TYPE_MEM;
+ q->from.reg = p->to.reg;
+ q->from.index = REG_TLS;
q->from.scale = 2; // TODO: use 1
q->to = p->to;
- p->from.type = D_TLS;
- p->from.index = D_NONE;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_TLS;
+ p->from.index = REG_NONE;
p->from.offset = 0;
}
}
// TODO: Remove.
if(ctxt->headtype == Hwindows || ctxt->headtype == Hplan9) {
- if(p->from.scale == 1 && p->from.index == D_TLS)
+ if(p->from.scale == 1 && p->from.index == REG_TLS)
p->from.scale = 2;
- if(p->to.scale == 1 && p->to.index == D_TLS)
+ if(p->to.scale == 1 && p->to.index == REG_TLS)
p->to.scale = 2;
}
switch(p->as) {
case AMODE:
- if(p->from.type == D_CONST || p->from.type == D_INDIR+D_NONE) {
+ if(p->from.type == TYPE_CONST || (p->from.type == TYPE_MEM && p->from.reg == REG_NONE)) {
switch((int)p->from.offset) {
case 16:
case 32:
break;
}
- // Rewrite CALL/JMP/RET to symbol as D_BRANCH.
+ // Rewrite CALL/JMP/RET to symbol as TYPE_BRANCH.
switch(p->as) {
case ACALL:
case AJMP:
case ARET:
- if((p->to.type == D_EXTERN || p->to.type == D_STATIC) && p->to.sym != nil)
- p->to.type = D_BRANCH;
+ if(p->to.type == TYPE_MEM && (p->to.name == NAME_EXTERN || p->to.name == NAME_STATIC) && p->to.sym != nil)
+ p->to.type = TYPE_BRANCH;
break;
}
switch(p->as) {
case AMOVSS:
// Convert AMOVSS $(0), Xx to AXORPS Xx, Xx
- if(p->from.type == D_FCONST)
+ if(p->from.type == TYPE_FCONST)
if(p->from.u.dval == 0)
- if(p->to.type >= D_X0)
- if(p->to.type <= D_X15) {
+ if(p->to.type == TYPE_REG && REG_X0 <= p->to.reg && p->to.reg <= REG_X15) {
p->as = AXORPS;
- p->from.type = p->to.type;
- p->from.index = p->to.index;
+ p->from = p->to;
break;
}
// fallthrough
case ADIVSS:
case ACOMISS:
case AUCOMISS:
- if(p->from.type == D_FCONST) {
+ if(p->from.type == TYPE_FCONST) {
uint32 i32;
float32 f32;
f32 = p->from.u.dval;
adduint32(ctxt, s, i32);
s->reachable = 0;
}
- p->from.type = D_EXTERN;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.sym = s;
p->from.offset = 0;
}
case AMOVSD:
// Convert AMOVSD $(0), Xx to AXORPS Xx, Xx
- if(p->from.type == D_FCONST)
+ if(p->from.type == TYPE_FCONST)
if(p->from.u.dval == 0)
- if(p->to.type >= D_X0)
- if(p->to.type <= D_X15) {
+ if(p->to.type == TYPE_REG && REG_X0 <= p->to.reg && p->to.reg <= REG_X15) {
p->as = AXORPS;
- p->from.type = p->to.type;
- p->from.index = p->to.index;
+ p->from = p->to;
break;
}
// fallthrough
case ADIVSD:
case ACOMISD:
case AUCOMISD:
- if(p->from.type == D_FCONST) {
+ if(p->from.type == TYPE_FCONST) {
uint64 i64;
memmove(&i64, &p->from.u.dval, 8);
sprint(literal, "$f64.%016llux", i64);
adduint64(ctxt, s, i64);
s->reachable = 0;
}
- p->from.type = D_EXTERN;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.sym = s;
p->from.offset = 0;
}
if(p->as == ALEAL || p->as == ALEAQ)
return;
- if(a->type == D_BP || a->type == D_INDIR+D_BP) {
+ if(a->reg == REG_BP) {
ctxt->diag("invalid address: %P", p);
return;
}
- if(a->type == D_INDIR+D_TLS)
- a->type = D_INDIR+D_BP;
- else if(a->type == D_TLS)
- a->type = D_BP;
- if(D_INDIR <= a->type && a->type <= D_INDIR+D_INDIR) {
- switch(a->type) {
- case D_INDIR+D_BP:
- case D_INDIR+D_SP:
- case D_INDIR+D_R15:
+ if(a->reg == REG_TLS)
+ a->reg = REG_BP;
+ if(a->type == TYPE_MEM && a->name == NAME_NONE) {
+ switch(a->reg) {
+ case REG_BP:
+ case REG_SP:
+ case REG_R15:
// all ok
break;
default:
- if(a->index != D_NONE)
+ if(a->index != REG_NONE)
ctxt->diag("invalid address %P", p);
- a->index = a->type - D_INDIR;
- if(a->index != D_NONE)
+ a->index = a->reg;
+ if(a->index != REG_NONE)
a->scale = 1;
- a->type = D_INDIR+D_R15;
+ a->reg = REG_R15;
break;
}
}
static void indir_cx(Link*, Addr*);
static void
-parsetextconst(vlong arg, vlong *textstksiz, vlong *textarg)
-{
- *textstksiz = arg & 0xffffffffLL;
- if(*textstksiz & 0x80000000LL)
- *textstksiz = -(-*textstksiz & 0xffffffffLL);
-
- *textarg = (arg >> 32) & 0xffffffffLL;
- if(*textarg & 0x80000000LL)
- *textarg = 0;
- *textarg = (*textarg+7) & ~7LL;
-}
-
-static void
-addstacksplit(Link *ctxt, LSym *cursym)
+preprocess(Link *ctxt, LSym *cursym)
{
Prog *p, *q, *p1, *p2;
int32 autoffset, deltasp;
- int a, pcsize;
- vlong textstksiz, textarg;
+ int a, pcsize, bpsize;
+ vlong textarg;
if(ctxt->tlsg == nil)
ctxt->tlsg = linklookup(ctxt, "runtime.tlsg", 0);
return;
p = cursym->text;
- parsetextconst(p->to.offset, &textstksiz, &textarg);
- autoffset = textstksiz;
+ autoffset = p->to.offset;
if(autoffset < 0)
autoffset = 0;
- cursym->args = p->to.offset>>32;
- cursym->locals = textstksiz;
+ if(framepointer_enabled && autoffset > 0) {
+ // Make room for to save a base pointer. If autoffset == 0,
+ // this might do something special like a tail jump to
+ // another function, so in that case we omit this.
+ bpsize = ctxt->arch->ptrsize;
+ autoffset += bpsize;
+ p->to.offset += bpsize;
+ } else {
+ bpsize = 0;
+ }
+
+ textarg = p->to.u.argsize;
+ cursym->args = textarg;
+ cursym->locals = p->to.offset;
- if(autoffset < StackSmall && !(p->from.scale & NOSPLIT)) {
+ if(autoffset < StackSmall && !(p->from3.offset & NOSPLIT)) {
for(q = p; q != nil; q = q->link) {
if(q->as == ACALL)
goto noleaf;
if((q->as == ADUFFCOPY || q->as == ADUFFZERO) && autoffset >= StackSmall - 8)
goto noleaf;
}
- p->from.scale |= NOSPLIT;
+ p->from3.offset |= NOSPLIT;
noleaf:;
}
q = nil;
- if(!(p->from.scale & NOSPLIT) || (p->from.scale & WRAPPER)) {
+ if(!(p->from3.offset & NOSPLIT) || (p->from3.offset & WRAPPER)) {
p = appendp(ctxt, p);
p = load_g_cx(ctxt, p); // load g into CX
}
- if(!(cursym->text->from.scale & NOSPLIT))
- p = stacksplit(ctxt, p, autoffset, textarg, !(cursym->text->from.scale&NEEDCTXT), &q); // emit split check
+ if(!(cursym->text->from3.offset & NOSPLIT))
+ p = stacksplit(ctxt, p, autoffset, textarg, !(cursym->text->from3.offset&NEEDCTXT), &q); // emit split check
if(autoffset) {
if(autoffset%ctxt->arch->regsize != 0)
ctxt->diag("unaligned stack size %d", autoffset);
p = appendp(ctxt, p);
p->as = AADJSP;
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = autoffset;
p->spadj = autoffset;
} else {
if(q != nil)
q->pcond = p;
deltasp = autoffset;
+
+ if(bpsize > 0) {
+ // Save caller's BP
+ p = appendp(ctxt, p);
+ p->as = AMOVQ;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_BP;
+ p->to.type = TYPE_MEM;
+ p->to.reg = REG_SP;
+ p->to.scale = 1;
+ p->to.offset = autoffset - bpsize;
+
+ // Move current frame to BP
+ p = appendp(ctxt, p);
+ p->as = ALEAQ;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_SP;
+ p->from.scale = 1;
+ p->from.offset = autoffset - bpsize;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_BP;
+ }
- if(cursym->text->from.scale & WRAPPER) {
+ if(cursym->text->from3.offset & WRAPPER) {
// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
//
// MOVQ g_panic(CX), BX
p = appendp(ctxt, p);
p->as = AMOVQ;
- p->from.type = D_INDIR+D_CX;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_CX;
p->from.offset = 4*ctxt->arch->ptrsize; // G.panic
- p->to.type = D_BX;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_BX;
if(ctxt->headtype == Hnacl) {
p->as = AMOVL;
- p->from.type = D_INDIR+D_R15;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_R15;
p->from.scale = 1;
- p->from.index = D_CX;
+ p->from.index = REG_CX;
}
p = appendp(ctxt, p);
p->as = ATESTQ;
- p->from.type = D_BX;
- p->to.type = D_BX;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_BX;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_BX;
if(ctxt->headtype == Hnacl)
p->as = ATESTL;
p = appendp(ctxt, p);
p->as = AJEQ;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
p1 = p;
p = appendp(ctxt, p);
p->as = ALEAQ;
- p->from.type = D_INDIR+D_SP;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_SP;
p->from.offset = autoffset+8;
- p->to.type = D_DI;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_DI;
if(ctxt->headtype == Hnacl)
p->as = ALEAL;
p = appendp(ctxt, p);
p->as = ACMPQ;
- p->from.type = D_INDIR+D_BX;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_BX;
p->from.offset = 0; // Panic.argp
- p->to.type = D_DI;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_DI;
if(ctxt->headtype == Hnacl) {
p->as = ACMPL;
- p->from.type = D_INDIR+D_R15;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_R15;
p->from.scale = 1;
- p->from.index = D_BX;
+ p->from.index = REG_BX;
}
p = appendp(ctxt, p);
p->as = AJNE;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
p2 = p;
p = appendp(ctxt, p);
p->as = AMOVQ;
- p->from.type = D_SP;
- p->to.type = D_INDIR+D_BX;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_SP;
+ p->to.type = TYPE_MEM;
+ p->to.reg = REG_BX;
p->to.offset = 0; // Panic.argp
if(ctxt->headtype == Hnacl) {
p->as = AMOVL;
- p->to.type = D_INDIR+D_R15;
+ p->to.type = TYPE_MEM;
+ p->to.reg = REG_R15;
p->to.scale = 1;
- p->to.index = D_BX;
+ p->to.index = REG_BX;
}
p = appendp(ctxt, p);
p2->pcond = p;
}
- if(ctxt->debugzerostack && autoffset && !(cursym->text->from.scale&NOSPLIT)) {
+ if(ctxt->debugzerostack && autoffset && !(cursym->text->from3.offset&NOSPLIT)) {
// 6l -Z means zero the stack frame on entry.
// This slows down function calls but can help avoid
// false positives in garbage collection.
p = appendp(ctxt, p);
p->as = AMOVQ;
- p->from.type = D_SP;
- p->to.type = D_DI;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_SP;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_DI;
p = appendp(ctxt, p);
p->as = AMOVQ;
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = autoffset/8;
- p->to.type = D_CX;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_CX;
p = appendp(ctxt, p);
p->as = AMOVQ;
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = 0;
- p->to.type = D_AX;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_AX;
p = appendp(ctxt, p);
p->as = AREP;
for(; p != nil; p = p->link) {
pcsize = p->mode/8;
- a = p->from.type;
- if(a == D_AUTO)
- p->from.offset += deltasp;
- if(a == D_PARAM)
+ a = p->from.name;
+ if(a == NAME_AUTO)
+ p->from.offset += deltasp - bpsize;
+ if(a == NAME_PARAM)
p->from.offset += deltasp + pcsize;
- a = p->to.type;
- if(a == D_AUTO)
- p->to.offset += deltasp;
- if(a == D_PARAM)
+ a = p->to.name;
+ if(a == NAME_AUTO)
+ p->to.offset += deltasp - bpsize;
+ if(a == NAME_PARAM)
p->to.offset += deltasp + pcsize;
switch(p->as) {
ctxt->diag("unbalanced PUSH/POP");
if(autoffset) {
+ if(bpsize > 0) {
+ // Restore caller's BP
+ p->as = AMOVQ;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_SP;
+ p->from.scale = 1;
+ p->from.offset = autoffset - bpsize;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_BP;
+ p = appendp(ctxt, p);
+ }
+
p->as = AADJSP;
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = -autoffset;
p->spadj = -autoffset;
p = appendp(ctxt, p);
indir_cx(Link *ctxt, Addr *a)
{
if(ctxt->headtype == Hnacl) {
- a->type = D_INDIR + D_R15;
- a->index = D_CX;
+ a->type = TYPE_MEM;
+ a->reg = REG_R15;
+ a->index = REG_CX;
a->scale = 1;
return;
}
- a->type = D_INDIR+D_CX;
+ a->type = TYPE_MEM;
+ a->reg = REG_CX;
}
// Append code to p to load g into cx.
p->as = AMOVQ;
if(ctxt->arch->ptrsize == 4)
p->as = AMOVL;
- p->from.type = D_INDIR+D_TLS;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_TLS;
p->from.offset = 0;
- p->to.type = D_CX;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_CX;
next = p->link;
progedit(ctxt, p);
while(p->link != next)
p = p->link;
- if(p->from.index == D_TLS)
+ if(p->from.index == REG_TLS)
p->from.scale = 2;
return p;
// CMPQ SP, stackguard
p = appendp(ctxt, p);
p->as = cmp;
- p->from.type = D_SP;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_SP;
indir_cx(ctxt, &p->to);
p->to.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
if(ctxt->cursym->cfunc)
// CMPQ AX, stackguard
p = appendp(ctxt, p);
p->as = lea;
- p->from.type = D_INDIR+D_SP;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_SP;
p->from.offset = -(framesize-StackSmall);
- p->to.type = D_AX;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_AX;
p = appendp(ctxt, p);
p->as = cmp;
- p->from.type = D_AX;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_AX;
indir_cx(ctxt, &p->to);
p->to.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
if(ctxt->cursym->cfunc)
p->from.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
if(ctxt->cursym->cfunc)
p->from.offset = 3*ctxt->arch->ptrsize; // G.stackguard1
- p->to.type = D_SI;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_SI;
p = appendp(ctxt, p);
p->as = cmp;
- p->from.type = D_SI;
- p->to.type = D_CONST;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_SI;
+ p->to.type = TYPE_CONST;
p->to.offset = StackPreempt;
p = appendp(ctxt, p);
p->as = AJEQ;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
q1 = p;
p = appendp(ctxt, p);
p->as = lea;
- p->from.type = D_INDIR+D_SP;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_SP;
p->from.offset = StackGuard;
- p->to.type = D_AX;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_AX;
p = appendp(ctxt, p);
p->as = sub;
- p->from.type = D_SI;
- p->to.type = D_AX;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_SI;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_AX;
p = appendp(ctxt, p);
p->as = cmp;
- p->from.type = D_AX;
- p->to.type = D_CONST;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_AX;
+ p->to.type = TYPE_CONST;
p->to.offset = framesize+(StackGuard-StackSmall);
}
// common
p = appendp(ctxt, p);
p->as = AJHI;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
q = p;
p = appendp(ctxt, p);
p->as = ACALL;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
if(ctxt->cursym->cfunc)
p->to.sym = linklookup(ctxt, "runtime.morestackc", 0);
else
p = appendp(ctxt, p);
p->as = AJMP;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
p->pcond = ctxt->cursym->text->link;
if(q != nil)
ctxt->cursym = s;
- firstp = ctxt->arch->prg();
+ firstp = emallocz(sizeof(Prog));
lastp = firstp;
xfol(ctxt, s->text, &lastp);
lastp->link = nil;
goto loop;
}
} /* */
- q = ctxt->arch->prg();
+ q = emallocz(sizeof(Prog));
q->as = AJMP;
q->lineno = p->lineno;
- q->to.type = D_BRANCH;
+ q->to.type = TYPE_BRANCH;
q->to.offset = p->pc;
q->pcond = p;
p = q;
p->pcond = q;
if((q = brchain(ctxt, p->link)) != nil)
p->link = q;
- if(p->from.type == D_CONST) {
+ if(p->from.type == TYPE_CONST) {
if(p->from.offset == 1) {
/*
* expect conditional jump to be taken.
goto loop;
}
-static Prog*
-prg(void)
-{
- Prog *p;
-
- p = emallocz(sizeof(*p));
- *p = zprg;
- return p;
-}
-
LinkArch linkamd64 = {
.name = "amd64",
.thechar = '6',
.endian = LittleEndian,
- .addstacksplit = addstacksplit,
+ .preprocess = preprocess,
.assemble = span6,
- .datasize = datasize,
.follow = follow,
- .iscall = iscall,
- .isdata = isdata,
- .prg = prg,
.progedit = progedit,
- .settextflag = settextflag,
- .symtype = symtype,
- .textflag = textflag,
.minlc = 1,
.ptrsize = 8,
.regsize = 8,
-
- .D_ADDR = D_ADDR,
- .D_AUTO = D_AUTO,
- .D_BRANCH = D_BRANCH,
- .D_CONST = D_CONST,
- .D_EXTERN = D_EXTERN,
- .D_FCONST = D_FCONST,
- .D_NONE = D_NONE,
- .D_PARAM = D_PARAM,
- .D_SCONST = D_SCONST,
- .D_STATIC = D_STATIC,
-
- .ACALL = ACALL,
- .ADATA = ADATA,
- .AEND = AEND,
- .AFUNCDATA = AFUNCDATA,
- .AGLOBL = AGLOBL,
- .AJMP = AJMP,
- .ANOP = ANOP,
- .APCDATA = APCDATA,
- .ARET = ARET,
- .ATEXT = ATEXT,
- .ATYPE = ATYPE,
- .AUSEFIELD = AUSEFIELD,
};
LinkArch linkamd64p32 = {
.thechar = '6',
.endian = LittleEndian,
- .addstacksplit = addstacksplit,
+ .preprocess = preprocess,
.assemble = span6,
- .datasize = datasize,
.follow = follow,
- .iscall = iscall,
- .isdata = isdata,
- .prg = prg,
.progedit = progedit,
- .settextflag = settextflag,
- .symtype = symtype,
- .textflag = textflag,
.minlc = 1,
.ptrsize = 4,
.regsize = 8,
-
- .D_ADDR = D_ADDR,
- .D_AUTO = D_AUTO,
- .D_BRANCH = D_BRANCH,
- .D_CONST = D_CONST,
- .D_EXTERN = D_EXTERN,
- .D_FCONST = D_FCONST,
- .D_NONE = D_NONE,
- .D_PARAM = D_PARAM,
- .D_SCONST = D_SCONST,
- .D_STATIC = D_STATIC,
-
- .ACALL = ACALL,
- .ADATA = ADATA,
- .AEND = AEND,
- .AFUNCDATA = AFUNCDATA,
- .AGLOBL = AGLOBL,
- .AJMP = AJMP,
- .ANOP = ANOP,
- .APCDATA = APCDATA,
- .ARET = ARET,
- .ATEXT = ATEXT,
- .ATYPE = ATYPE,
- .AUSEFIELD = AUSEFIELD,
};
#include "../cmd/8l/8.out.h"
#include "../runtime/stack.h"
-static Prog zprg = {
- .back = 2,
- .as = AGOK,
- .from = {
- .type = D_NONE,
- .index = D_NONE,
- .scale = 1,
- },
- .to = {
- .type = D_NONE,
- .index = D_NONE,
- .scale = 1,
- },
-};
-
-static int
-symtype(Addr *a)
-{
- int t;
-
- t = a->type;
- if(t == D_ADDR)
- t = a->index;
- return t;
-}
-
-static int
-isdata(Prog *p)
-{
- return p->as == ADATA || p->as == AGLOBL;
-}
-
-static int
-iscall(Prog *p)
-{
- return p->as == ACALL;
-}
-
-static int
-datasize(Prog *p)
-{
- return p->from.scale;
-}
-
-static int
-textflag(Prog *p)
-{
- return p->from.scale;
-}
-
-static void
-settextflag(Prog *p, int f)
-{
- p->from.scale = f;
-}
-
static int
canuselocaltls(Link *ctxt)
{
// become
// NOP
// ... off(TLS) ...
- if(p->as == AMOVL && p->from.type == D_TLS && D_AX <= p->to.type && p->to.type <= D_DI) {
+ if(p->as == AMOVL && p->from.type == TYPE_REG && p->from.reg == REG_TLS && p->to.type == TYPE_REG && REG_AX <= p->to.reg && p->to.reg <= REG_DI) {
p->as = ANOP;
- p->from.type = D_NONE;
- p->to.type = D_NONE;
+ p->from.type = TYPE_NONE;
+ p->to.type = TYPE_NONE;
}
- if(p->from.index == D_TLS && D_INDIR+D_AX <= p->from.type && p->from.type <= D_INDIR+D_DI) {
- p->from.type = D_INDIR+D_TLS;
+ if(p->from.type == TYPE_MEM && p->from.index == REG_TLS && REG_AX <= p->from.reg && p->from.reg <= REG_DI) {
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_TLS;
p->from.scale = 0;
- p->from.index = D_NONE;
+ p->from.index = REG_NONE;
}
- if(p->to.index == D_TLS && D_INDIR+D_AX <= p->to.type && p->to.type <= D_INDIR+D_DI) {
- p->to.type = D_INDIR+D_TLS;
+ if(p->to.type == TYPE_MEM && p->to.index == REG_TLS && REG_AX <= p->to.reg && p->to.reg <= REG_DI) {
+ p->to.type = TYPE_MEM;
+ p->to.reg = REG_TLS;
p->to.scale = 0;
- p->to.index = D_NONE;
+ p->to.index = REG_NONE;
}
} else {
// As a courtesy to the C compilers, rewrite TLS local exec load as TLS initial exec load.
// MOVL TLS, BX
// MOVL off(BX)(TLS*1), BX
// This allows the C compilers to emit references to m and g using the direct off(TLS) form.
- if(p->as == AMOVL && p->from.type == D_INDIR+D_TLS && D_AX <= p->to.type && p->to.type <= D_DI) {
+ if(p->as == AMOVL && p->from.type == TYPE_MEM && p->from.reg == REG_TLS && p->to.type == TYPE_REG && REG_AX <= p->to.reg && p->to.reg <= REG_DI) {
q = appendp(ctxt, p);
q->as = p->as;
- q->from = p->from;
- q->from.type = D_INDIR + p->to.type;
- q->from.index = D_TLS;
+ q->from.type = TYPE_MEM;
+ q->from.reg = p->to.reg;
+ q->from.index = REG_TLS;
q->from.scale = 2; // TODO: use 1
q->to = p->to;
- p->from.type = D_TLS;
- p->from.index = D_NONE;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_TLS;
+ p->from.index = REG_NONE;
p->from.offset = 0;
}
}
// TODO: Remove.
if(ctxt->headtype == Hplan9) {
- if(p->from.scale == 1 && p->from.index == D_TLS)
+ if(p->from.scale == 1 && p->from.index == REG_TLS)
p->from.scale = 2;
- if(p->to.scale == 1 && p->to.index == D_TLS)
+ if(p->to.scale == 1 && p->to.index == REG_TLS)
p->to.scale = 2;
}
- // Rewrite CALL/JMP/RET to symbol as D_BRANCH.
+ // Rewrite CALL/JMP/RET to symbol as TYPE_BRANCH.
switch(p->as) {
case ACALL:
case AJMP:
case ARET:
- if((p->to.type == D_EXTERN || p->to.type == D_STATIC) && p->to.sym != nil)
- p->to.type = D_BRANCH;
+ if(p->to.type == TYPE_MEM && (p->to.name == NAME_EXTERN || p->to.name == NAME_STATIC) && p->to.sym != nil)
+ p->to.type = TYPE_BRANCH;
break;
}
switch(p->as) {
case AMOVSS:
// Convert AMOVSS $(0), Xx to AXORPS Xx, Xx
- if(p->from.type == D_FCONST)
+ if(p->from.type == TYPE_FCONST)
if(p->from.u.dval == 0)
- if(p->to.type >= D_X0)
- if(p->to.type <= D_X7) {
+ if(p->to.type == TYPE_REG && REG_X0 <= p->to.reg && p->to.reg <= REG_X7) {
p->as = AXORPS;
- p->from.type = p->to.type;
- p->from.index = p->to.index;
+ p->from = p->to;
break;
}
// fallthrough
case ADIVSS:
case ACOMISS:
case AUCOMISS:
- if(p->from.type == D_FCONST) {
+ if(p->from.type == TYPE_FCONST) {
uint32 i32;
float32 f32;
f32 = p->from.u.dval;
adduint32(ctxt, s, i32);
s->reachable = 0;
}
- p->from.type = D_EXTERN;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.sym = s;
p->from.offset = 0;
}
case AMOVSD:
// Convert AMOVSD $(0), Xx to AXORPS Xx, Xx
- if(p->from.type == D_FCONST)
+ if(p->from.type == TYPE_FCONST)
if(p->from.u.dval == 0)
- if(p->to.type >= D_X0)
- if(p->to.type <= D_X7) {
+ if(p->to.type == TYPE_REG && REG_X0 <= p->to.reg && p->to.reg <= REG_X7) {
p->as = AXORPS;
- p->from.type = p->to.type;
- p->from.index = p->to.index;
+ p->from = p->to;
break;
}
// fallthrough
case ADIVSD:
case ACOMISD:
case AUCOMISD:
- if(p->from.type == D_FCONST) {
+ if(p->from.type == TYPE_FCONST) {
uint64 i64;
memmove(&i64, &p->from.u.dval, 8);
sprint(literal, "$f64.%016llux", i64);
adduint64(ctxt, s, i64);
s->reachable = 0;
}
- p->from.type = D_EXTERN;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.sym = s;
p->from.offset = 0;
}
}
}
-static Prog*
-prg(void)
-{
- Prog *p;
-
- p = emallocz(sizeof(*p));
- *p = zprg;
- return p;
-}
-
static Prog* load_g_cx(Link*, Prog*);
static Prog* stacksplit(Link*, Prog*, int32, int, Prog**);
static void
-addstacksplit(Link *ctxt, LSym *cursym)
+preprocess(Link *ctxt, LSym *cursym)
{
Prog *p, *q, *p1, *p2;
int32 autoffset, deltasp;
autoffset = 0;
cursym->locals = autoffset;
- cursym->args = p->to.offset2;
+ cursym->args = p->to.u.argsize;
q = nil;
- if(!(p->from.scale & NOSPLIT) || (p->from.scale & WRAPPER)) {
+ if(!(p->from3.offset & NOSPLIT) || (p->from3.offset & WRAPPER)) {
p = appendp(ctxt, p);
p = load_g_cx(ctxt, p); // load g into CX
}
- if(!(cursym->text->from.scale & NOSPLIT))
- p = stacksplit(ctxt, p, autoffset, !(cursym->text->from.scale&NEEDCTXT), &q); // emit split check
+ if(!(cursym->text->from3.offset & NOSPLIT))
+ p = stacksplit(ctxt, p, autoffset, !(cursym->text->from3.offset&NEEDCTXT), &q); // emit split check
if(autoffset) {
p = appendp(ctxt, p);
p->as = AADJSP;
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = autoffset;
p->spadj = autoffset;
} else {
q->pcond = p;
deltasp = autoffset;
- if(cursym->text->from.scale & WRAPPER) {
+ if(cursym->text->from3.offset & WRAPPER) {
// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
//
// MOVL g_panic(CX), BX
p = appendp(ctxt, p);
p->as = AMOVL;
- p->from.type = D_INDIR+D_CX;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_CX;
p->from.offset = 4*ctxt->arch->ptrsize; // G.panic
- p->to.type = D_BX;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_BX;
p = appendp(ctxt, p);
p->as = ATESTL;
- p->from.type = D_BX;
- p->to.type = D_BX;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_BX;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_BX;
p = appendp(ctxt, p);
p->as = AJEQ;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
p1 = p;
p = appendp(ctxt, p);
p->as = ALEAL;
- p->from.type = D_INDIR+D_SP;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_SP;
p->from.offset = autoffset+4;
- p->to.type = D_DI;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_DI;
p = appendp(ctxt, p);
p->as = ACMPL;
- p->from.type = D_INDIR+D_BX;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_BX;
p->from.offset = 0; // Panic.argp
- p->to.type = D_DI;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_DI;
p = appendp(ctxt, p);
p->as = AJNE;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
p2 = p;
p = appendp(ctxt, p);
p->as = AMOVL;
- p->from.type = D_SP;
- p->to.type = D_INDIR+D_BX;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_SP;
+ p->to.type = TYPE_MEM;
+ p->to.reg = REG_BX;
p->to.offset = 0; // Panic.argp
p = appendp(ctxt, p);
p2->pcond = p;
}
- if(ctxt->debugzerostack && autoffset && !(cursym->text->from.scale&NOSPLIT)) {
+ if(ctxt->debugzerostack && autoffset && !(cursym->text->from3.offset&NOSPLIT)) {
// 8l -Z means zero the stack frame on entry.
// This slows down function calls but can help avoid
// false positives in garbage collection.
p = appendp(ctxt, p);
p->as = AMOVL;
- p->from.type = D_SP;
- p->to.type = D_DI;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_SP;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_DI;
p = appendp(ctxt, p);
p->as = AMOVL;
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = autoffset/4;
- p->to.type = D_CX;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_CX;
p = appendp(ctxt, p);
p->as = AMOVL;
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = 0;
- p->to.type = D_AX;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_AX;
p = appendp(ctxt, p);
p->as = AREP;
}
for(; p != nil; p = p->link) {
- a = p->from.type;
- if(a == D_AUTO)
+ a = p->from.name;
+ if(a == NAME_AUTO)
p->from.offset += deltasp;
- if(a == D_PARAM)
+ if(a == NAME_PARAM)
p->from.offset += deltasp + 4;
- a = p->to.type;
- if(a == D_AUTO)
+ a = p->to.name;
+ if(a == NAME_AUTO)
p->to.offset += deltasp;
- if(a == D_PARAM)
+ if(a == NAME_PARAM)
p->to.offset += deltasp + 4;
switch(p->as) {
if(autoffset) {
p->as = AADJSP;
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = -autoffset;
p->spadj = -autoffset;
p = appendp(ctxt, p);
Prog *next;
p->as = AMOVL;
- p->from.type = D_INDIR+D_TLS;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_TLS;
p->from.offset = 0;
- p->to.type = D_CX;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_CX;
next = p->link;
progedit(ctxt, p);
while(p->link != next)
p = p->link;
- if(p->from.index == D_TLS)
+ if(p->from.index == REG_TLS)
p->from.scale = 2;
return p;
// catches out-of-sync stack guard info.
p = appendp(ctxt, p);
p->as = ACMPL;
- p->from.type = D_INDIR+D_CX;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_CX;
p->from.offset = 4;
- p->to.type = D_SP;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_SP;
p = appendp(ctxt, p);
p->as = AJCC;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
p->to.offset = 4;
q1 = p;
p = appendp(ctxt, p);
p->as = AINT;
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = 3;
p = appendp(ctxt, p);
// CMPL SP, stackguard
p = appendp(ctxt, p);
p->as = ACMPL;
- p->from.type = D_SP;
- p->to.type = D_INDIR+D_CX;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_SP;
+ p->to.type = TYPE_MEM;
+ p->to.reg = REG_CX;
p->to.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
if(ctxt->cursym->cfunc)
p->to.offset = 3*ctxt->arch->ptrsize; // G.stackguard1
// CMPL AX, stackguard
p = appendp(ctxt, p);
p->as = ALEAL;
- p->from.type = D_INDIR+D_SP;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_SP;
p->from.offset = -(framesize-StackSmall);
- p->to.type = D_AX;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_AX;
p = appendp(ctxt, p);
p->as = ACMPL;
- p->from.type = D_AX;
- p->to.type = D_INDIR+D_CX;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_AX;
+ p->to.type = TYPE_MEM;
+ p->to.reg = REG_CX;
p->to.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
if(ctxt->cursym->cfunc)
p->to.offset = 3*ctxt->arch->ptrsize; // G.stackguard1
// CMPL AX, $(framesize+(StackGuard-StackSmall))
p = appendp(ctxt, p);
p->as = AMOVL;
- p->from.type = D_INDIR+D_CX;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_CX;
p->from.offset = 0;
p->from.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
if(ctxt->cursym->cfunc)
p->from.offset = 3*ctxt->arch->ptrsize; // G.stackguard1
- p->to.type = D_SI;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_SI;
p = appendp(ctxt, p);
p->as = ACMPL;
- p->from.type = D_SI;
- p->to.type = D_CONST;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_SI;
+ p->to.type = TYPE_CONST;
p->to.offset = (uint32)StackPreempt;
p = appendp(ctxt, p);
p->as = AJEQ;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
q1 = p;
p = appendp(ctxt, p);
p->as = ALEAL;
- p->from.type = D_INDIR+D_SP;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_SP;
p->from.offset = StackGuard;
- p->to.type = D_AX;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_AX;
p = appendp(ctxt, p);
p->as = ASUBL;
- p->from.type = D_SI;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_SI;
p->from.offset = 0;
- p->to.type = D_AX;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_AX;
p = appendp(ctxt, p);
p->as = ACMPL;
- p->from.type = D_AX;
- p->to.type = D_CONST;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_AX;
+ p->to.type = TYPE_CONST;
p->to.offset = framesize+(StackGuard-StackSmall);
}
// common
p = appendp(ctxt, p);
p->as = AJHI;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
p->to.offset = 4;
q = p;
p = appendp(ctxt, p);
p->as = ACALL;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
if(ctxt->cursym->cfunc)
p->to.sym = linklookup(ctxt, "runtime.morestackc", 0);
else
p = appendp(ctxt, p);
p->as = AJMP;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
p->pcond = ctxt->cursym->text->link;
if(q != nil)
ctxt->cursym = s;
- firstp = ctxt->arch->prg();
+ firstp = emallocz(sizeof(Prog));
lastp = firstp;
xfol(ctxt, s->text, &lastp);
lastp->link = nil;
goto loop;
}
} /* */
- q = ctxt->arch->prg();
+ q = emallocz(sizeof(Prog));
q->as = AJMP;
q->lineno = p->lineno;
- q->to.type = D_BRANCH;
+ q->to.type = TYPE_BRANCH;
q->to.offset = p->pc;
q->pcond = p;
p = q;
p->pcond = q;
if((q = brchain(ctxt, p->link)) != nil)
p->link = q;
- if(p->from.type == D_CONST) {
+ if(p->from.type == TYPE_CONST) {
if(p->from.offset == 1) {
/*
* expect conditional jump to be taken.
.thechar = '8',
.endian = LittleEndian,
- .addstacksplit = addstacksplit,
+ .preprocess = preprocess,
.assemble = span8,
- .datasize = datasize,
.follow = follow,
- .iscall = iscall,
- .isdata = isdata,
- .prg = prg,
.progedit = progedit,
- .settextflag = settextflag,
- .symtype = symtype,
- .textflag = textflag,
.minlc = 1,
.ptrsize = 4,
.regsize = 4,
-
- .D_ADDR = D_ADDR,
- .D_AUTO = D_AUTO,
- .D_BRANCH = D_BRANCH,
- .D_CONST = D_CONST,
- .D_EXTERN = D_EXTERN,
- .D_FCONST = D_FCONST,
- .D_NONE = D_NONE,
- .D_PARAM = D_PARAM,
- .D_SCONST = D_SCONST,
- .D_STATIC = D_STATIC,
-
- .ACALL = ACALL,
- .ADATA = ADATA,
- .AEND = AEND,
- .AFUNCDATA = AFUNCDATA,
- .AGLOBL = AGLOBL,
- .AJMP = AJMP,
- .ANOP = ANOP,
- .APCDATA = APCDATA,
- .ARET = ARET,
- .ATEXT = ATEXT,
- .ATYPE = ATYPE,
- .AUSEFIELD = AUSEFIELD,
};
#include "../runtime/stack.h"
#include "../runtime/funcdata.h"
-static Prog zprg = {
- .as = AGOK,
- .reg = NREG,
- .from = {
- .name = D_NONE,
- .type = D_NONE,
- .reg = NREG,
- },
- .from3 = {
- .name = D_NONE,
- .type = D_NONE,
- .reg = NREG,
- },
- .to = {
- .name = D_NONE,
- .type = D_NONE,
- .reg = NREG,
- },
-};
-
-static int
-symtype(Addr *a)
-{
- return a->name;
-}
-
-static int
-isdata(Prog *p)
-{
- return p->as == ADATA || p->as == AGLOBL;
-}
-
-static int
-iscall(Prog *p)
-{
- return p->as == ABL;
-}
-
-static int
-datasize(Prog *p)
-{
- return p->reg;
-}
-
-static int
-textflag(Prog *p)
-{
- return p->reg;
-}
-
-static void
-settextflag(Prog *p, int f)
-{
- p->reg = f;
-}
-
static void
progedit(Link *ctxt, Prog *p)
{
p->from.class = 0;
p->to.class = 0;
- // Rewrite BR/BL to symbol as D_BRANCH.
+ // Rewrite BR/BL to symbol as TYPE_BRANCH.
switch(p->as) {
case ABR:
case ABL:
case ADUFFZERO:
case ADUFFCOPY:
if(p->to.sym != nil)
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
break;
}
// Rewrite float constants to values stored in memory.
switch(p->as) {
case AFMOVS:
- if(p->from.type == D_FCONST) {
+ if(p->from.type == TYPE_FCONST) {
uint32 i32;
float32 f32;
f32 = p->from.u.dval;
sprint(literal, "$f32.%08ux", i32);
s = linklookup(ctxt, literal, 0);
s->size = 4;
- p->from.type = D_OREG;
+ p->from.type = TYPE_MEM;
p->from.sym = s;
- p->from.name = D_EXTERN;
+ p->from.name = NAME_EXTERN;
p->from.offset = 0;
}
break;
case AFMOVD:
- if(p->from.type == D_FCONST) {
+ if(p->from.type == TYPE_FCONST) {
uint64 i64;
memmove(&i64, &p->from.u.dval, 8);
sprint(literal, "$f64.%016llux", i64);
s = linklookup(ctxt, literal, 0);
s->size = 8;
- p->from.type = D_OREG;
+ p->from.type = TYPE_MEM;
p->from.sym = s;
- p->from.name = D_EXTERN;
+ p->from.name = NAME_EXTERN;
p->from.offset = 0;
}
break;
case AMOVD:
// Put >32-bit constants in memory and load them
- if(p->from.type == D_CONST && p->from.name == D_NONE && p->from.reg == NREG && (int32)p->from.offset != p->from.offset) {
+ if(p->from.type == TYPE_CONST && p->from.name == NAME_NONE && p->from.reg == 0 && (int32)p->from.offset != p->from.offset) {
sprint(literal, "$i64.%016llux", (uvlong)p->from.offset);
s = linklookup(ctxt, literal, 0);
s->size = 8;
- p->from.type = D_OREG;
+ p->from.type = TYPE_MEM;
p->from.sym = s;
- p->from.name = D_EXTERN;
+ p->from.name = NAME_EXTERN;
p->from.offset = 0;
}
}
// Rewrite SUB constants into ADD.
switch(p->as) {
case ASUBC:
- if(p->from.type == D_CONST) {
+ if(p->from.type == TYPE_CONST) {
p->from.offset = -p->from.offset;
p->as = AADDC;
}
break;
case ASUBCCC:
- if(p->from.type == D_CONST) {
+ if(p->from.type == TYPE_CONST) {
p->from.offset = -p->from.offset;
p->as = AADDCCC;
}
break;
case ASUB:
- if(p->from.type == D_CONST) {
+ if(p->from.type == TYPE_CONST) {
p->from.offset = -p->from.offset;
p->as = AADD;
}
static Prog* stacksplit(Link*, Prog*, int32, int);
static void
-parsetextconst(vlong arg, vlong *textstksiz, vlong *textarg)
-{
- *textstksiz = arg & 0xffffffffLL;
- if(*textstksiz & 0x80000000LL)
- *textstksiz = -(-*textstksiz & 0xffffffffLL);
-
- *textarg = (arg >> 32) & 0xffffffffLL;
- if(*textarg & 0x80000000LL)
- *textarg = 0;
- *textarg = (*textarg+7) & ~7LL;
-}
-
-static void
-addstacksplit(Link *ctxt, LSym *cursym)
+preprocess(Link *ctxt, LSym *cursym)
{
Prog *p, *q, *p1, *p2, *q1;
int o, mov, aoffset;
- vlong textstksiz, textarg;
+ vlong textstksiz;
int32 autosize;
if(ctxt->symmorestack[0] == nil) {
return;
p = cursym->text;
- parsetextconst(p->to.offset, &textstksiz, &textarg);
+ textstksiz = p->to.offset;
- cursym->args = p->to.offset>>32;
+ cursym->args = p->to.u.argsize;
cursym->locals = textstksiz;
/*
case ANOR:
q = p;
- if(p->to.type == D_REG)
+ if(p->to.type == TYPE_REG)
if(p->to.reg == REGZERO)
p->mark |= LABEL|SYNC;
break;
case AMOVWZ:
case AMOVD:
q = p;
- switch(p->from.type) {
- case D_MSR:
- case D_SPR:
- case D_FPSCR:
- case D_CREG:
- case D_DCR:
- p->mark |= LABEL|SYNC;
- }
- switch(p->to.type) {
- case D_MSR:
- case D_SPR:
- case D_FPSCR:
- case D_CREG:
- case D_DCR:
+ if(p->from.reg >= REG_SPECIAL || p->to.reg >= REG_SPECIAL)
p->mark |= LABEL|SYNC;
- }
continue;
case AFABS:
else
if(autosize & 4)
autosize += 4;
- p->to.offset = ((uint64)p->to.offset & (0xffffffffull<<32)) | (uint32)(autosize-8);
+ p->to.offset = autosize-8;
- if(!(p->reg & NOSPLIT))
- p = stacksplit(ctxt, p, autosize, !(cursym->text->reg&NEEDCTXT)); // emit split check
+ if(!(p->from3.offset & NOSPLIT))
+ p = stacksplit(ctxt, p, autosize, !(cursym->text->from3.offset&NEEDCTXT)); // emit split check
q = p;
if(autosize) {
q = appendp(ctxt, p);
q->as = AADD;
q->lineno = p->lineno;
- q->from.type = D_CONST;
+ q->from.type = TYPE_CONST;
q->from.offset = -autosize;
- q->to.type = D_REG;
+ q->to.type = TYPE_REG;
q->to.reg = REGSP;
q->spadj = +autosize;
}
q = appendp(ctxt, q);
q->as = AMOVD;
q->lineno = p->lineno;
- q->from.type = D_SPR;
- q->from.offset = D_LR;
- q->to.type = D_REG;
+ q->from.type = TYPE_REG;
+ q->from.reg = REG_LR;
+ q->to.type = TYPE_REG;
q->to.reg = REGTMP;
q = appendp(ctxt, q);
q->as = mov;
q->lineno = p->lineno;
- q->from.type = D_REG;
+ q->from.type = TYPE_REG;
q->from.reg = REGTMP;
- q->to.type = D_OREG;
+ q->to.type = TYPE_MEM;
q->to.offset = aoffset;
q->to.reg = REGSP;
if(q->as == AMOVDU)
q->spadj = -aoffset;
- if(cursym->text->reg & WRAPPER) {
+ if(cursym->text->from3.offset & WRAPPER) {
// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
//
// MOVD g_panic(g), R3
q = appendp(ctxt, q);
q->as = AMOVD;
- q->from.type = D_OREG;
+ q->from.type = TYPE_MEM;
q->from.reg = REGG;
q->from.offset = 4*ctxt->arch->ptrsize; // G.panic
- q->to.type = D_REG;
- q->to.reg = 3;
+ q->to.type = TYPE_REG;
+ q->to.reg = REG_R3;
q = appendp(ctxt, q);
q->as = ACMP;
- q->from.type = D_REG;
- q->from.reg = 0;
- q->to.type = D_REG;
- q->to.reg = 3;
+ q->from.type = TYPE_REG;
+ q->from.reg = REG_R0;
+ q->to.type = TYPE_REG;
+ q->to.reg = REG_R3;
q = appendp(ctxt, q);
q->as = ABEQ;
- q->to.type = D_BRANCH;
+ q->to.type = TYPE_BRANCH;
p1 = q;
q = appendp(ctxt, q);
q->as = AMOVD;
- q->from.type = D_OREG;
- q->from.reg = 3;
+ q->from.type = TYPE_MEM;
+ q->from.reg = REG_R3;
q->from.offset = 0; // Panic.argp
- q->to.type = D_REG;
- q->to.reg = 4;
+ q->to.type = TYPE_REG;
+ q->to.reg = REG_R4;
q = appendp(ctxt, q);
q->as = AADD;
- q->from.type = D_CONST;
+ q->from.type = TYPE_CONST;
q->from.offset = autosize+8;
q->reg = REGSP;
- q->to.type = D_REG;
- q->to.reg = 5;
+ q->to.type = TYPE_REG;
+ q->to.reg = REG_R5;
q = appendp(ctxt, q);
q->as = ACMP;
- q->from.type = D_REG;
- q->from.reg = 4;
- q->to.type = D_REG;
- q->to.reg = 5;
+ q->from.type = TYPE_REG;
+ q->from.reg = REG_R4;
+ q->to.type = TYPE_REG;
+ q->to.reg = REG_R5;
q = appendp(ctxt, q);
q->as = ABNE;
- q->to.type = D_BRANCH;
+ q->to.type = TYPE_BRANCH;
p2 = q;
q = appendp(ctxt, q);
q->as = AADD;
- q->from.type = D_CONST;
+ q->from.type = TYPE_CONST;
q->from.offset = 8;
q->reg = REGSP;
- q->to.type = D_REG;
- q->to.reg = 6;
+ q->to.type = TYPE_REG;
+ q->to.reg = REG_R6;
q = appendp(ctxt, q);
q->as = AMOVD;
- q->from.type = D_REG;
- q->from.reg = 6;
- q->to.type = D_OREG;
- q->to.reg = 3;
+ q->from.type = TYPE_REG;
+ q->from.reg = REG_R6;
+ q->to.type = TYPE_MEM;
+ q->to.reg = REG_R3;
q->to.offset = 0; // Panic.argp
q = appendp(ctxt, q);
break;
case ARETURN:
- if(p->from.type == D_CONST) {
+ if(p->from.type == TYPE_CONST) {
ctxt->diag("using BECOME (%P) is not supported!", p);
break;
}
if(p->to.sym) { // retjmp
p->as = ABR;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
break;
}
if(cursym->text->mark & LEAF) {
if(!autosize) {
p->as = ABR;
- p->from = zprg.from;
- p->to.type = D_SPR;
- p->to.offset = D_LR;
+ p->from = zprog.from;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_LR;
p->mark |= BRANCH;
break;
}
p->as = AADD;
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = autosize;
- p->to.type = D_REG;
+ p->to.type = TYPE_REG;
p->to.reg = REGSP;
p->spadj = -autosize;
- q = ctxt->arch->prg();
+ q = emallocz(sizeof(Prog));
q->as = ABR;
q->lineno = p->lineno;
- q->to.type = D_SPR;
- q->to.offset = D_LR;
+ q->to.type = TYPE_REG;
+ q->to.reg = REG_LR;
q->mark |= BRANCH;
q->spadj = +autosize;
}
p->as = AMOVD;
- p->from.type = D_OREG;
+ p->from.type = TYPE_MEM;
p->from.offset = 0;
p->from.reg = REGSP;
- p->to.type = D_REG;
+ p->to.type = TYPE_REG;
p->to.reg = REGTMP;
- q = ctxt->arch->prg();
+ q = emallocz(sizeof(Prog));
q->as = AMOVD;
q->lineno = p->lineno;
- q->from.type = D_REG;
+ q->from.type = TYPE_REG;
q->from.reg = REGTMP;
- q->to.type = D_SPR;
- q->to.offset = D_LR;
+ q->to.type = TYPE_REG;
+ q->to.reg = REG_LR;
q->link = p->link;
p->link = q;
if(0) {
// Debug bad returns
- q = ctxt->arch->prg();
+ q = emallocz(sizeof(Prog));
q->as = AMOVD;
q->lineno = p->lineno;
- q->from.type = D_OREG;
+ q->from.type = TYPE_MEM;
q->from.offset = 0;
q->from.reg = REGTMP;
- q->to.type = D_REG;
+ q->to.type = TYPE_REG;
q->to.reg = REGTMP;
q->link = p->link;
}
if(autosize) {
- q = ctxt->arch->prg();
+ q = emallocz(sizeof(Prog));
q->as = AADD;
q->lineno = p->lineno;
- q->from.type = D_CONST;
+ q->from.type = TYPE_CONST;
q->from.offset = autosize;
- q->to.type = D_REG;
+ q->to.type = TYPE_REG;
q->to.reg = REGSP;
q->spadj = -autosize;
p->link = q;
}
- q1 = ctxt->arch->prg();
+ q1 = emallocz(sizeof(Prog));
q1->as = ABR;
q1->lineno = p->lineno;
- q1->to.type = D_SPR;
- q1->to.offset = D_LR;
+ q1->to.type = TYPE_REG;
+ q1->to.reg = REG_LR;
q1->mark |= BRANCH;
q1->spadj = +autosize;
break;
case AADD:
- if(p->to.type == D_REG && p->to.reg == REGSP && p->from.type == D_CONST)
+ if(p->to.type == TYPE_REG && p->to.reg == REGSP && p->from.type == TYPE_CONST)
p->spadj = -p->from.offset;
break;
}
// MOVD g_stackguard(g), R3
p = appendp(ctxt, p);
p->as = AMOVD;
- p->from.type = D_OREG;
+ p->from.type = TYPE_MEM;
p->from.reg = REGG;
p->from.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
if(ctxt->cursym->cfunc)
p->from.offset = 3*ctxt->arch->ptrsize; // G.stackguard1
- p->to.type = D_REG;
- p->to.reg = 3;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_R3;
q = nil;
if(framesize <= StackSmall) {
// CMP stackguard, SP
p = appendp(ctxt, p);
p->as = ACMPU;
- p->from.type = D_REG;
- p->from.reg = 3;
- p->to.type = D_REG;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_R3;
+ p->to.type = TYPE_REG;
p->to.reg = REGSP;
} else if(framesize <= StackBig) {
// large stack: SP-framesize < stackguard-StackSmall
// CMP stackguard, R4
p = appendp(ctxt, p);
p->as = AADD;
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = -framesize;
p->reg = REGSP;
- p->to.type = D_REG;
- p->to.reg = 4;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_R4;
p = appendp(ctxt, p);
p->as = ACMPU;
- p->from.type = D_REG;
- p->from.reg = 3;
- p->to.type = D_REG;
- p->to.reg = 4;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_R3;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_R4;
} else {
// Such a large stack we need to protect against wraparound.
// If SP is close to zero:
// CMPU R31, R4
p = appendp(ctxt, p);
p->as = ACMP;
- p->from.type = D_REG;
- p->from.reg = 3;
- p->to.type = D_CONST;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_R3;
+ p->to.type = TYPE_CONST;
p->to.offset = StackPreempt;
q = p = appendp(ctxt, p);
p->as = ABEQ;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
p = appendp(ctxt, p);
p->as = AADD;
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = StackGuard;
p->reg = REGSP;
- p->to.type = D_REG;
- p->to.reg = 4;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_R4;
p = appendp(ctxt, p);
p->as = ASUB;
- p->from.type = D_REG;
- p->from.reg = 3;
- p->to.type = D_REG;
- p->to.reg = 4;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_R3;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_R4;
p = appendp(ctxt, p);
p->as = AMOVD;
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = framesize + StackGuard - StackSmall;
- p->to.type = D_REG;
+ p->to.type = TYPE_REG;
p->to.reg = REGTMP;
p = appendp(ctxt, p);
p->as = ACMPU;
- p->from.type = D_REG;
+ p->from.type = TYPE_REG;
p->from.reg = REGTMP;
- p->to.type = D_REG;
- p->to.reg = 4;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_R4;
}
// q1: BLT done
q1 = p = appendp(ctxt, p);
p->as = ABLT;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
// MOVD LR, R5
p = appendp(ctxt, p);
p->as = AMOVD;
- p->from.type = D_SPR;
- p->from.offset = D_LR;
- p->to.type = D_REG;
- p->to.reg = 5;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_LR;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_R5;
if(q)
q->pcond = p;
// BL runtime.morestack(SB)
p = appendp(ctxt, p);
p->as = ABL;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
if(ctxt->cursym->cfunc)
p->to.sym = linklookup(ctxt, "runtime.morestackc", 0);
else
// BR start
p = appendp(ctxt, p);
p->as = ABR;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
p->pcond = ctxt->cursym->text->link;
// placeholder for q1's jump target
ctxt->cursym = s;
- firstp = ctxt->arch->prg();
+ firstp = emallocz(sizeof(Prog));
lastp = firstp;
xfol(ctxt, s->text, &lastp);
lastp->link = nil;
continue;
copy:
for(;;) {
- r = ctxt->arch->prg();
+ r = emallocz(sizeof(Prog));
*r = *p;
if(!(r->mark&FOLL))
print("cant happen 1\n");
}
a = ABR;
- q = ctxt->arch->prg();
+ q = emallocz(sizeof(Prog));
q->as = a;
q->lineno = p->lineno;
- q->to.type = D_BRANCH;
+ q->to.type = TYPE_BRANCH;
q->to.offset = p->pc;
q->pcond = p;
p = q;
goto loop;
}
-static Prog*
-prg(void)
-{
- Prog *p;
-
- p = emallocz(sizeof(*p));
- *p = zprg;
- return p;
-}
-
LinkArch linkppc64 = {
.name = "ppc64",
.thechar = '9',
.endian = BigEndian,
- .addstacksplit = addstacksplit,
+ .preprocess = preprocess,
.assemble = span9,
- .datasize = datasize,
.follow = follow,
- .iscall = iscall,
- .isdata = isdata,
- .prg = prg,
.progedit = progedit,
- .settextflag = settextflag,
- .symtype = symtype,
- .textflag = textflag,
.minlc = 4,
.ptrsize = 8,
.regsize = 8,
-
- .D_ADDR = D_ADDR,
- .D_AUTO = D_AUTO,
- .D_BRANCH = D_BRANCH,
- .D_CONST = D_CONST,
- .D_EXTERN = D_EXTERN,
- .D_FCONST = D_FCONST,
- .D_NONE = D_NONE,
- .D_PARAM = D_PARAM,
- .D_SCONST = D_SCONST,
- .D_STATIC = D_STATIC,
- .D_OREG = D_OREG,
-
- .ACALL = ABL,
- .ADATA = ADATA,
- .AEND = AEND,
- .AFUNCDATA = AFUNCDATA,
- .AGLOBL = AGLOBL,
- .AJMP = ABR,
- .ANOP = ANOP,
- .APCDATA = APCDATA,
- .ARET = ARETURN,
- .ATEXT = ATEXT,
- .ATYPE = ATYPE,
- .AUSEFIELD = AUSEFIELD,
};
LinkArch linkppc64le = {
.thechar = '9',
.endian = LittleEndian,
- .addstacksplit = addstacksplit,
+ .preprocess = preprocess,
.assemble = span9,
- .datasize = datasize,
.follow = follow,
- .iscall = iscall,
- .isdata = isdata,
- .prg = prg,
.progedit = progedit,
- .settextflag = settextflag,
- .symtype = symtype,
- .textflag = textflag,
.minlc = 4,
.ptrsize = 8,
.regsize = 8,
-
- .D_ADDR = D_ADDR,
- .D_AUTO = D_AUTO,
- .D_BRANCH = D_BRANCH,
- .D_CONST = D_CONST,
- .D_EXTERN = D_EXTERN,
- .D_FCONST = D_FCONST,
- .D_NONE = D_NONE,
- .D_PARAM = D_PARAM,
- .D_SCONST = D_SCONST,
- .D_STATIC = D_STATIC,
- .D_OREG = D_OREG,
-
- .ACALL = ABL,
- .ADATA = ADATA,
- .AEND = AEND,
- .AFUNCDATA = AFUNCDATA,
- .AGLOBL = AGLOBL,
- .AJMP = ABR,
- .ANOP = ANOP,
- .APCDATA = APCDATA,
- .ARET = ARETURN,
- .ATEXT = ATEXT,
- .ATYPE = ATYPE,
- .AUSEFIELD = AUSEFIELD,
};
for(pl = ctxt->plist; pl != nil; pl = pl->link) {
for(p = pl->firstpc; p != nil; p = plink) {
if(ctxt->debugasm && ctxt->debugvlog)
- print("obj: %p %P\n", p, p);
+ print("obj: %P\n", p);
plink = p->link;
p->link = nil;
- if(p->as == ctxt->arch->AEND)
+ if(p->as == AEND)
continue;
- if(p->as == ctxt->arch->ATYPE) {
+ if(p->as == ATYPE) {
// Assume each TYPE instruction describes
// a different local variable or parameter,
// so no dedup.
a = emallocz(sizeof *a);
a->asym = p->from.sym;
a->aoffset = p->from.offset;
- a->type = ctxt->arch->symtype(&p->from);
+ a->name = p->from.name;
a->gotype = p->from.gotype;
a->link = curtext->autom;
curtext->autom = a;
continue;
}
- if(p->as == ctxt->arch->AGLOBL) {
+ if(p->as == AGLOBL) {
s = p->from.sym;
if(s->seenglobl++)
print("duplicate %P\n", p);
s->size = p->to.offset;
if(s->type == 0 || s->type == SXREF)
s->type = SBSS;
- flag = ctxt->arch->textflag(p);
+ flag = p->from3.offset;
if(flag & DUPOK)
s->dupok = 1;
if(flag & RODATA)
continue;
}
- if(p->as == ctxt->arch->ADATA) {
+ if(p->as == ADATA) {
savedata(ctxt, p->from.sym, p, "<input>");
continue;
}
- if(p->as == ctxt->arch->ATEXT) {
+ if(p->as == ATEXT) {
s = p->from.sym;
if(s == nil) {
// func _() { }
else
etext->next = s;
etext = s;
- flag = ctxt->arch->textflag(p);
+ flag = p->from3.offset;
if(flag & DUPOK)
s->dupok = 1;
if(flag & NOSPLIT)
continue;
}
- if(p->as == ctxt->arch->AFUNCDATA) {
+ if(p->as == AFUNCDATA) {
// Rewrite reference to go_args_stackmap(SB) to the Go-provided declaration information.
if(curtext == nil) // func _() {}
continue;
if(strcmp(p->to.sym->name, "go_args_stackmap") == 0) {
- if(p->from.type != ctxt->arch->D_CONST || p->from.offset != FUNCDATA_ArgsPointerMaps)
+ if(p->from.type != TYPE_CONST || p->from.offset != FUNCDATA_ArgsPointerMaps)
ctxt->diag("FUNCDATA use of go_args_stackmap(SB) without FUNCDATA_ArgsPointerMaps");
p->to.sym = linklookup(ctxt, smprint("%s.args_stackmap", curtext->name), curtext->version);
}
continue;
found = 0;
for(p = s->text; p != nil; p = p->link) {
- if(p->as == ctxt->arch->AFUNCDATA && p->from.type == ctxt->arch->D_CONST && p->from.offset == FUNCDATA_ArgsPointerMaps) {
+ if(p->as == AFUNCDATA && p->from.type == TYPE_CONST && p->from.offset == FUNCDATA_ArgsPointerMaps) {
found = 1;
break;
}
}
if(!found) {
p = appendp(ctxt, s->text);
- p->as = ctxt->arch->AFUNCDATA;
- p->from.type = ctxt->arch->D_CONST;
+ p->as = AFUNCDATA;
+ p->from.type = TYPE_CONST;
p->from.offset = FUNCDATA_ArgsPointerMaps;
- if(ctxt->arch->thechar == '6' || ctxt->arch->thechar == '8')
- p->to.type = ctxt->arch->D_EXTERN;
- else {
- p->to.type = ctxt->arch->D_OREG;
- p->to.name = ctxt->arch->D_EXTERN;
- }
+ p->to.type = TYPE_MEM;
+ p->to.name = NAME_EXTERN;
p->to.sym = linklookup(ctxt, smprint("%s.args_stackmap", s->name), s->version);
}
}
mkfwd(s);
linkpatch(ctxt, s);
ctxt->arch->follow(ctxt, s);
- ctxt->arch->addstacksplit(ctxt, s);
+ ctxt->arch->preprocess(ctxt, s);
ctxt->arch->assemble(ctxt, s);
linkpcln(ctxt, s);
}
for(a = s->autom; a != nil; a = a->link) {
wrsym(b, a->asym);
wrint(b, a->aoffset);
- if(a->type == ctxt->arch->D_AUTO)
+ if(a->name == NAME_AUTO)
wrint(b, A_AUTO);
- else if(a->type == ctxt->arch->D_PARAM)
+ else if(a->name == NAME_PARAM)
wrint(b, A_PARAM);
else
- sysfatal("%s: invalid local variable type %d", s->name, a->type);
+ sysfatal("%s: invalid local variable type %d", s->name, a->name);
wrsym(b, a->gotype);
}
a = emallocz(sizeof *a);
a->asym = rdsym(ctxt, f, pkg);
a->aoffset = rdint(f);
- a->type = rdint(f);
+ a->name = rdint(f);
a->gotype = rdsym(ctxt, f, pkg);
a->link = s->autom;
s->autom = a;
q = p;
for(p=p0; p!=q; p=p->link) {
- if(p->from.type == ctxt->arch->D_BRANCH)
+ if(p->from.type == TYPE_BRANCH)
printprog(ctxt, bw, p->from.u.branch);
- if(p->to.type == ctxt->arch->D_BRANCH)
+ if(p->to.type == TYPE_BRANCH)
printprog(ctxt, bw, p->to.u.branch);
}
}
printtype(ctxt, bw, TypeAddr);
printint(ctxt, bw, a->offset);
- if(a->type == ctxt->arch->D_FCONST) {
+ if(a->type == TYPE_FCONST) {
uint64 u;
float64 f;
f = a->u.dval;
printint(ctxt, bw, u);
} else
printint(ctxt, bw, 0);
- if(a->type == ctxt->arch->D_SCONST)
+ if(a->type == TYPE_SCONST)
Bwrite(bw, a->u.sval, 8);
else
Bwrite(bw, zero, 8);
- if(a->type == ctxt->arch->D_BRANCH)
+ if(a->type == TYPE_BRANCH)
printptr(ctxt, bw, a->u.branch);
else
printptr(ctxt, bw, nil);
printint(ctxt, bw, a->name);
printint(ctxt, bw, a->class);
printint(ctxt, bw, a->etype);
- printint(ctxt, bw, a->offset2);
+ if(a->type == TYPE_TEXTSIZE)
+ printint(ctxt, bw, a->u.argsize);
+ else
+ printint(ctxt, bw, 0);
printint(ctxt, bw, a->width);
}
{
int i;
+ USED(ctxt);
for(i=0; i<20; i++) {
- if(p == nil || p->as != ctxt->arch->AJMP || p->pcond == nil)
+ if(p == nil || p->as != AJMP || p->pcond == nil)
return p;
p = p->pcond;
}
int c;
Prog *q;
+ USED(ctxt);
c = 0;
for(q = p; q != nil; q = q->pcond) {
- if(q->as != ctxt->arch->AJMP || q->pcond == nil)
+ if(q->as != AJMP || q->pcond == nil)
break;
c++;
if(c >= 5000)
return q;
}
+static void
+checkaddr(Link *ctxt, Prog *p, Addr *a)
+{
+ // Check expected encoding, especially TYPE_CONST vs TYPE_ADDR.
+ switch(a->type) {
+ case TYPE_NONE:
+ return;
+
+ case TYPE_BRANCH:
+ if(a->reg != 0 || a->index != 0 || a->scale != 0 || a->name != 0)
+ break;
+ return;
+
+ case TYPE_TEXTSIZE:
+ if(a->reg != 0 || a->index != 0 || a->scale != 0 || a->name != 0)
+ break;
+ return;
+
+ case TYPE_MEM:
+ //if(a->u.bits != 0)
+ // break;
+ return;
+
+ case TYPE_CONST:
+ // TODO(rsc): After fixing SHRQ, check a->index != 0 too.
+ if(a->name != 0 || a->sym != 0 || a->reg != 0) {
+ ctxt->diag("argument %D is TYPE_CONST, should be TYPE_ADDR, in %P", a, p);
+ return;
+ }
+ if(a->reg != 0 || a->scale != 0 || a->name != 0 || a->sym != nil || a->u.bits != 0)
+ break;
+ return;
+
+ case TYPE_FCONST:
+ case TYPE_SCONST:
+ if(a->reg != 0 || a->index != 0 || a->scale != 0 || a->name != 0 || a->offset != 0 || a->sym != nil)
+ break;
+ return;
+
+ case TYPE_REG:
+ // TODO(rsc): After fixing PINSRQ, check a->offset != 0 too.
+ // TODO(rsc): After fixing SHRQ, check a->index != 0 too.
+ if(a->scale != 0 || a->name != 0 || a->sym != nil)
+ break;
+ return;
+
+ case TYPE_ADDR:
+ if(a->u.bits != 0)
+ break;
+ if(a->reg == 0 && a->index == 0 && a->scale == 0 && a->name == 0 && a->sym == nil)
+ ctxt->diag("argument %D is TYPE_ADDR, should be TYPE_CONST, in %P", a, p);
+ return;
+
+ case TYPE_SHIFT:
+ if(a->index != 0 || a->scale != 0 || a->name != 0 || a->sym != nil || a->u.bits != 0)
+ break;
+ return;
+
+ case TYPE_REGREG:
+ if(a->index != 0 || a->scale != 0 || a->name != 0 || a->sym != nil || a->u.bits != 0)
+ break;
+ return;
+
+ case TYPE_REGREG2:
+ return;
+
+ case TYPE_INDIR:
+ // Expect sym and name to be set, nothing else.
+ // Technically more is allowed, but this is only used for *name(SB).
+ if(a->reg != 0 || a->index != 0 || a->scale != 0 || a->name == 0 || a->offset != 0 || a->sym == nil || a->u.bits != 0)
+ break;
+ return;
+ }
+
+ ctxt->diag("invalid encoding for argument %D in %P", a, p);
+}
+
void
linkpatch(Link *ctxt, LSym *sym)
{
ctxt->cursym = sym;
for(p = sym->text; p != nil; p = p->link) {
+ checkaddr(ctxt, p, &p->from);
+ checkaddr(ctxt, p, &p->from3);
+ checkaddr(ctxt, p, &p->to);
+
if(ctxt->arch->progedit)
ctxt->arch->progedit(ctxt, p);
- if(p->to.type != ctxt->arch->D_BRANCH)
+ if(p->to.type != TYPE_BRANCH)
continue;
if(p->to.u.branch != nil) {
// TODO: Remove to.u.branch in favor of p->pcond.
if(p->to.sym)
name = p->to.sym->name;
ctxt->diag("branch out of range (%#ux)\n%P [%s]", c, p, name);
- p->to.type = ctxt->arch->D_NONE;
+ p->to.type = TYPE_NONE;
}
p->to.u.branch = q;
p->pcond = q;
if(p->pcond != nil) {
p->pcond = brloop(ctxt, p->pcond);
if(p->pcond != nil)
- if(p->to.type == ctxt->arch->D_BRANCH)
+ if(p->to.type == TYPE_BRANCH)
p->to.offset = p->pcond->pc;
}
}
USED(sym);
- if(p->as == ctxt->arch->ATEXT || p->as == ctxt->arch->ANOP || p->as == ctxt->arch->AUSEFIELD || p->lineno == 0 || phase == 1)
+ if(p->as == ATEXT || p->as == ANOP || p->as == AUSEFIELD || p->lineno == 0 || phase == 1)
return oldval;
linkgetline(ctxt, p->lineno, &f, &l);
if(f == nil) {
{
USED(sym);
- if(phase == 0 || p->as != ctxt->arch->APCDATA || p->from.offset != (uintptr)arg)
+ if(phase == 0 || p->as != APCDATA || p->from.offset != (uintptr)arg)
return oldval;
if((int32)p->to.offset != p->to.offset) {
ctxt->diag("overflow in PCDATA instruction: %P", p);
npcdata = 0;
nfuncdata = 0;
for(p = cursym->text; p != nil; p = p->link) {
- if(p->as == ctxt->arch->APCDATA && p->from.offset >= npcdata)
+ if(p->as == APCDATA && p->from.offset >= npcdata)
npcdata = p->from.offset+1;
- if(p->as == ctxt->arch->AFUNCDATA && p->from.offset >= nfuncdata)
+ if(p->as == AFUNCDATA && p->from.offset >= nfuncdata)
nfuncdata = p->from.offset+1;
}
havepc = emallocz(n);
havefunc = havepc + (npcdata+31)/32;
for(p = cursym->text; p != nil; p = p->link) {
- if(p->as == ctxt->arch->AFUNCDATA) {
+ if(p->as == AFUNCDATA) {
if((havefunc[p->from.offset/32]>>(p->from.offset%32))&1)
ctxt->diag("multiple definitions for FUNCDATA $%d", p->from.offset);
havefunc[p->from.offset/32] |= 1<<(p->from.offset%32);
}
- if(p->as == ctxt->arch->APCDATA)
+ if(p->as == APCDATA)
havepc[p->from.offset/32] |= 1<<(p->from.offset%32);
}
// pcdata.
// funcdata
if(nfuncdata > 0) {
for(p = cursym->text; p != nil; p = p->link) {
- if(p->as == ctxt->arch->AFUNCDATA) {
+ if(p->as == AFUNCDATA) {
i = p->from.offset;
pcln->funcdataoff[i] = p->to.offset;
- if(p->to.type != ctxt->arch->D_CONST) {
+ if(p->to.type != TYPE_CONST) {
// TODO: Dedup.
//funcdata_bytes += p->to.sym->size;
pcln->funcdata[i] = p->to.sym;
char *name;
int val;
} headers[] = {
- {"android", Hlinux},
{"darwin", Hdarwin},
{"dragonfly", Hdragonfly},
{"elf", Helf},
{"freebsd", Hfreebsd},
{"linux", Hlinux},
+ {"android", Hlinux}, // must be after "linux" entry or else headstr(Hlinux) == "android"
{"nacl", Hnacl},
{"netbsd", Hnetbsd},
{"openbsd", Hopenbsd},
char *p;
char buf[1024];
+ linksetexp();
nuxiinit(arch);
ctxt = emallocz(sizeof *ctxt);
return &Logger{out: out, prefix: prefix, flag: flag}
}
+// SetOutput sets the output destination for the logger.
+func (l *Logger) SetOutput(w io.Writer) {
+ l.mu.Lock()
+ defer l.mu.Unlock()
+ l.out = w
+}
+
var std = New(os.Stderr, "", LstdFlags)
// Cheap integer to fixed-width decimal ASCII. Give a negative width to avoid zero-padding.
# GO_LDFLAGS: Additional 5l/6l/8l arguments to use when
# building the commands.
#
-# GO_CCFLAGS: Additional 5c/6c/8c arguments to use when
-# building.
-#
# CGO_ENABLED: Controls cgo usage during the build. Set it to 1
# to include all cgo related files, .c and .go file with "cgo"
# build directive, in the build. Set it to 0 to ignore them.
# CC_FOR_TARGET is recorded as the default compiler for the go tool. When building for the host, however,
# use the host compiler, CC, from `cmd/dist/dist env` instead.
CC=$CC GOOS=$GOHOSTOS GOARCH=$GOHOSTARCH \
- "$GOTOOLDIR"/go_bootstrap install -ccflags "$GO_CCFLAGS" -gcflags "$GO_GCFLAGS" -ldflags "$GO_LDFLAGS" -v std
+ "$GOTOOLDIR"/go_bootstrap install -gcflags "$GO_GCFLAGS" -ldflags "$GO_LDFLAGS" -v std
echo
fi
echo "##### Building packages and commands for $GOOS/$GOARCH."
-CC=$CC_FOR_TARGET "$GOTOOLDIR"/go_bootstrap install $GO_FLAGS -ccflags "$GO_CCFLAGS" -gcflags "$GO_GCFLAGS" -ldflags "$GO_LDFLAGS" -v std
+CC=$CC_FOR_TARGET "$GOTOOLDIR"/go_bootstrap install $GO_FLAGS -gcflags "$GO_GCFLAGS" -ldflags "$GO_LDFLAGS" -v std
echo
rm -f "$GOTOOLDIR"/go_bootstrap
# GO_LDFLAGS: Additional 5l/6l/8l arguments to use when
# building the commands.
#
-# GO_CCFLAGS: Additional 5c/6c/8c arguments to use when
-# building.
-#
# CGO_ENABLED: Controls cgo usage during the build. Set it to 1
# to include all cgo related files, .c and .go file with "cgo"
# build directive, in the build. Set it to 0 to ignore them.
if(! ~ $GOHOSTARCH $GOARCH || ! ~ $GOHOSTOS $GOOS){
echo '# Building packages and commands for host,' $GOHOSTOS/$GOHOSTARCH^.
GOOS=$GOHOSTOS GOARCH=$GOHOSTARCH \
- $GOTOOLDIR/go_bootstrap install -ccflags $"GO_CCFLAGS -gcflags $"GO_GCFLAGS -ldflags $"GO_LDFLAGS -v $pflag std
+ $GOTOOLDIR/go_bootstrap install -gcflags $"GO_GCFLAGS -ldflags $"GO_LDFLAGS -v $pflag std
echo
}
echo '# Building packages and commands for' $GOOS/$GOARCH^.
-$GOTOOLDIR/go_bootstrap install -ccflags $"GO_CCFLAGS -gcflags $"GO_GCFLAGS -ldflags $"GO_LDFLAGS -v $pflag std
+$GOTOOLDIR/go_bootstrap install -gcflags $"GO_GCFLAGS -ldflags $"GO_LDFLAGS -v $pflag std
echo
rm -f $GOTOOLDIR/go_bootstrap
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements multi-precision decimal numbers.
+// The implementation is for float to decimal conversion only;
+// not general purpose use.
+// The only operations are precise conversion from binary to
+// decimal and rounding.
+//
+// The key observation and some code (shr) is borrowed from
+// strconv/decimal.go: conversion of binary fractional values can be done
+// precisely in multi-precision decimal because 2 divides 10 (required for
+// >> of mantissa); but conversion of decimal floating-point values cannot
+// be done precisely in binary representation.
+//
+// In contrast to strconv/decimal.go, only right shift is implemented in
+// decimal format - left shift can be done precisely in binary format.
+
+package big
+
+// A decimal represents a floating-point number in decimal representation.
+// The value of a decimal x is x.mant * 10 ** x.exp with 0.5 <= x.mant < 1,
+// with the most-significant mantissa digit at index 0.
+type decimal struct {
+ mant []byte // mantissa ASCII digits, big-endian
+ exp int // exponent, valid if len(mant) > 0
+}
+
+// Maximum shift amount that can be done in one pass without overflow.
+// A Word has _W bits and (1<<maxShift - 1)*10 + 9 must fit into Word.
+const maxShift = _W - 4
+
+// TODO(gri) Since we know the desired decimal precision when converting
+// a floating-point number, we may be able to limit the number of decimal
+// digits that need to be computed by init by providing an additional
+// precision argument and keeping track of when a number was truncated early
+// (equivalent of "sticky bit" in binary rounding).
+
+// Init initializes x to the decimal representation of m << shift (for
+// shift >= 0), or m >> -shift (for shift < 0).
+func (x *decimal) init(m nat, shift int) {
+ // special case 0
+ if len(m) == 0 {
+ x.mant = x.mant[:0]
+ return
+ }
+
+ // Optimization: If we need to shift right, first remove any trailing
+ // zero bits from m to reduce shift amount that needs to be done in
+ // decimal format (since that is likely slower).
+ if shift < 0 {
+ ntz := m.trailingZeroBits()
+ s := uint(-shift)
+ if s >= ntz {
+ s = ntz // shift at most ntz bits
+ }
+ m = nat(nil).shr(m, s)
+ shift += int(s)
+ }
+
+ // Do any shift left in binary representation.
+ if shift > 0 {
+ m = nat(nil).shl(m, uint(shift))
+ shift = 0
+ }
+
+ // Convert mantissa into decimal representation.
+ s := m.decimalString() // TODO(gri) avoid string conversion here
+ n := len(s)
+ x.exp = n
+ // Trim trailing zeros; instead the exponent is tracking
+ // the decimal point independent of the number of digits.
+ for n > 0 && s[n-1] == '0' {
+ n--
+ }
+ x.mant = append(x.mant[:0], s[:n]...)
+
+ // Do any (remaining) shift right in decimal representation.
+ if shift < 0 {
+ for shift < -maxShift {
+ shr(x, maxShift)
+ shift += maxShift
+ }
+ shr(x, uint(-shift))
+ }
+}
+
+// Possibly optimization: The current implementation of nat.string takes
+// a charset argument. When a right shift is needed, we could provide
+// "\x00\x01...\x09" instead of "012..9" (as in nat.decimalString) and
+// avoid the repeated +'0' and -'0' operations in decimal.shr (and do a
+// single +'0' pass at the end).
+
+// shr implements x >> s, for s <= maxShift.
+func shr(x *decimal, s uint) {
+ // Division by 1<<s using shift-and-subtract algorithm.
+
+ // pick up enough leading digits to cover first shift
+ r := 0 // read index
+ var n Word
+ for n>>s == 0 && r < len(x.mant) {
+ ch := Word(x.mant[r])
+ r++
+ n = n*10 + ch - '0'
+ }
+ if n == 0 {
+ // x == 0; shouldn't get here, but handle anyway
+ x.mant = x.mant[:0]
+ return
+ }
+ for n>>s == 0 {
+ r++
+ n *= 10
+ }
+ x.exp += 1 - r
+
+ // read a digit, write a digit
+ w := 0 // write index
+ for r < len(x.mant) {
+ ch := Word(x.mant[r])
+ r++
+ d := n >> s
+ n -= d << s
+ x.mant[w] = byte(d + '0')
+ w++
+ n = n*10 + ch - '0'
+ }
+
+ // write extra digits that still fit
+ for n > 0 && w < len(x.mant) {
+ d := n >> s
+ n -= d << s
+ x.mant[w] = byte(d + '0')
+ w++
+ n = n * 10
+ }
+ x.mant = x.mant[:w] // the number may be shorter (e.g. 1024 >> 10)
+
+ // append additional digits that didn't fit
+ for n > 0 {
+ d := n >> s
+ n -= d << s
+ x.mant = append(x.mant, byte(d+'0'))
+ n = n * 10
+ }
+
+ trim(x)
+}
+
+func (x *decimal) String() string {
+ if len(x.mant) == 0 {
+ return "0"
+ }
+
+ var buf []byte
+ switch {
+ case x.exp <= 0:
+ // 0.00ddd
+ buf = append(buf, "0."...)
+ buf = appendZeros(buf, -x.exp)
+ buf = append(buf, x.mant...)
+
+ case /* 0 < */ x.exp < len(x.mant):
+ // dd.ddd
+ buf = append(buf, x.mant[:x.exp]...)
+ buf = append(buf, '.')
+ buf = append(buf, x.mant[x.exp:]...)
+
+ default: // len(x.mant) <= x.exp
+ // ddd00
+ buf = append(buf, x.mant...)
+ buf = appendZeros(buf, x.exp-len(x.mant))
+ }
+
+ return string(buf)
+}
+
+// appendZeros appends n 0 digits to buf and returns buf.
+func appendZeros(buf []byte, n int) []byte {
+ for ; n > 0; n-- {
+ buf = append(buf, '0')
+ }
+ return buf
+}
+
+// shouldRoundUp reports if x should be rounded up
+// if shortened to n digits. n must be a valid index
+// for x.mant.
+func shouldRoundUp(x *decimal, n int) bool {
+ if x.mant[n] == '5' && n+1 == len(x.mant) {
+ // exactly halfway - round to even
+ return n > 0 && (x.mant[n-1]-'0')&1 != 0
+ }
+ // not halfway - digit tells all (x.mant has no trailing zeros)
+ return x.mant[n] >= '5'
+}
+
+// round sets x to (at most) n mantissa digits by rounding it
+// to the nearest even value with n (or fever) mantissa digits.
+// If n < 0, x remains unchanged.
+func (x *decimal) round(n int) {
+ if n < 0 || n >= len(x.mant) {
+ return // nothing to do
+ }
+
+ if shouldRoundUp(x, n) {
+ x.roundUp(n)
+ } else {
+ x.roundDown(n)
+ }
+}
+
+func (x *decimal) roundUp(n int) {
+ if n < 0 || n >= len(x.mant) {
+ return // nothing to do
+ }
+ // 0 <= n < len(x.mant)
+
+ // find first digit < '9'
+ for n > 0 && x.mant[n-1] >= '9' {
+ n--
+ }
+
+ if n == 0 {
+ // all digits are '9's => round up to '1' and update exponent
+ x.mant[0] = '1' // ok since len(x.mant) > n
+ x.mant = x.mant[:1]
+ x.exp++
+ return
+ }
+
+ // n > 0 && x.mant[n-1] < '9'
+ x.mant[n-1]++
+ x.mant = x.mant[:n]
+ // x already trimmed
+}
+
+func (x *decimal) roundDown(n int) {
+ if n < 0 || n >= len(x.mant) {
+ return // nothing to do
+ }
+ x.mant = x.mant[:n]
+ trim(x)
+}
+
+// trim cuts off any trailing zeros from x's mantissa;
+// they are meaningless for the value of x.
+func trim(x *decimal) {
+ i := len(x.mant)
+ for i > 0 && x.mant[i-1] == '0' {
+ i--
+ }
+ x.mant = x.mant[:i]
+}
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package big
+
+import "testing"
+
+func TestDecimalString(t *testing.T) {
+ for _, test := range []struct {
+ x decimal
+ want string
+ }{
+ {want: "0"},
+ {decimal{nil, 1000}, "0"}, // exponent of 0 is ignored
+ {decimal{[]byte("12345"), 0}, "0.12345"},
+ {decimal{[]byte("12345"), -3}, "0.00012345"},
+ {decimal{[]byte("12345"), +3}, "123.45"},
+ {decimal{[]byte("12345"), +10}, "1234500000"},
+ } {
+ if got := test.x.String(); got != test.want {
+ t.Errorf("%v == %s; want %s", test.x, got, test.want)
+ }
+ }
+}
+
+func TestDecimalInit(t *testing.T) {
+ for _, test := range []struct {
+ x Word
+ shift int
+ want string
+ }{
+ {0, 0, "0"},
+ {0, -100, "0"},
+ {0, 100, "0"},
+ {1, 0, "1"},
+ {1, 10, "1024"},
+ {1, 100, "1267650600228229401496703205376"},
+ {1, -100, "0.0000000000000000000000000000007888609052210118054117285652827862296732064351090230047702789306640625"},
+ {12345678, 8, "3160493568"},
+ {12345678, -8, "48225.3046875"},
+ {195312, 9, "99999744"},
+ {1953125, 9, "1000000000"},
+ } {
+ var d decimal
+ d.init(nat{test.x}.norm(), test.shift)
+ if got := d.String(); got != test.want {
+ t.Errorf("%d << %d == %s; want %s", test.x, test.shift, got, test.want)
+ }
+ }
+}
+
+func TestDecimalRounding(t *testing.T) {
+ for _, test := range []struct {
+ x uint64
+ n int
+ down, even, up string
+ }{
+ {0, 0, "0", "0", "0"},
+ {0, 1, "0", "0", "0"},
+
+ {1, 0, "0", "0", "10"},
+ {5, 0, "0", "0", "10"},
+ {9, 0, "0", "10", "10"},
+
+ {15, 1, "10", "20", "20"},
+ {45, 1, "40", "40", "50"},
+ {95, 1, "90", "100", "100"},
+
+ {12344999, 4, "12340000", "12340000", "12350000"},
+ {12345000, 4, "12340000", "12340000", "12350000"},
+ {12345001, 4, "12340000", "12350000", "12350000"},
+ {23454999, 4, "23450000", "23450000", "23460000"},
+ {23455000, 4, "23450000", "23460000", "23460000"},
+ {23455001, 4, "23450000", "23460000", "23460000"},
+
+ {99994999, 4, "99990000", "99990000", "100000000"},
+ {99995000, 4, "99990000", "100000000", "100000000"},
+ {99999999, 4, "99990000", "100000000", "100000000"},
+
+ {12994999, 4, "12990000", "12990000", "13000000"},
+ {12995000, 4, "12990000", "13000000", "13000000"},
+ {12999999, 4, "12990000", "13000000", "13000000"},
+ } {
+ x := nat(nil).setUint64(test.x)
+
+ var d decimal
+ d.init(x, 0)
+ d.roundDown(test.n)
+ if got := d.String(); got != test.down {
+ t.Errorf("roundDown(%d, %d) = %s; want %s", test.x, test.n, got, test.down)
+ }
+
+ d.init(x, 0)
+ d.round(test.n)
+ if got := d.String(); got != test.even {
+ t.Errorf("round(%d, %d) = %s; want %s", test.x, test.n, got, test.even)
+ }
+
+ d.init(x, 0)
+ d.roundUp(test.n)
+ if got := d.String(); got != test.up {
+ t.Errorf("roundUp(%d, %d) = %s; want %s", test.x, test.n, got, test.up)
+ }
+ }
+}
--- /dev/null
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements multi-precision floating-point numbers.
+// Like in the GNU MPFR library (http://www.mpfr.org/), operands
+// can be of mixed precision. Unlike MPFR, the rounding mode is
+// not specified with each operation, but with each operand. The
+// rounding mode of the result operand determines the rounding
+// mode of an operation. This is a from-scratch implementation.
+
+// CAUTION: WORK IN PROGRESS - ANY ASPECT OF THIS IMPLEMENTATION MAY CHANGE!
+
+package big
+
+import (
+ "fmt"
+ "math"
+)
+
+// TODO(gri): Determine if there's a more natural way to set the precision.
+// Should there be a special meaning for prec 0? Such as "full precision"?
+// (would be possible for all ops except quotient).
+
+const debugFloat = true // enable for debugging
+
+// Internal representation: A floating-point value x != 0 consists
+// of a sign (x.neg), mantissa (x.mant), and exponent (x.exp) such
+// that
+//
+// x = sign * 0.mantissa * 2**exponent
+//
+// and the mantissa is interpreted as a value between 0.5 and 1:
+//
+// 0.5 <= mantissa < 1.0
+//
+// The mantissa bits are stored in the shortest nat slice long enough
+// to hold x.prec mantissa bits. The mantissa is normalized such that
+// the msb of x.mant == 1. Thus, if the precision is not a multiple of
+// the Word size _W, x.mant[0] contains trailing zero bits. The number
+// 0 is represented by an empty mantissa and a zero exponent.
+
+// A Float represents a multi-precision floating point number
+// of the form
+//
+// sign * mantissa * 2**exponent
+//
+// Each value also has a precision, rounding mode, and accuracy value:
+// The precision is the number of mantissa bits used to represent a
+// value, and the result of operations is rounded to that many bits
+// according to the value's rounding mode (unless specified othewise).
+// The accuracy value indicates the rounding error with respect to the
+// exact (not rounded) value.
+//
+// The zero value for a Float represents the number 0.
+//
+// By setting the desired precision to 24 (or 53) and using ToNearestEven
+// rounding, Float arithmetic operations emulate the corresponding float32
+// or float64 IEEE-754 operations (except for denormalized numbers and NaNs).
+//
+// CAUTION: THIS IS WORK IN PROGRESS - USE AT YOUR OWN RISK.
+//
+type Float struct {
+ mode RoundingMode
+ acc Accuracy
+ neg bool
+ mant nat
+ exp int32
+ prec uint // TODO(gri) make this a 32bit field
+}
+
+// NewFloat returns a new Float with value x rounded
+// to prec bits according to the given rounding mode.
+func NewFloat(x float64, prec uint, mode RoundingMode) *Float {
+ // TODO(gri) should make this more efficient
+ z := new(Float).SetFloat64(x)
+ return z.Round(z, prec, mode)
+}
+
+// infExp is the exponent value for infinity.
+const infExp = 1<<31 - 1
+
+// NewInf returns a new Float with value positive infinity (sign >= 0),
+// or negative infinity (sign < 0).
+func NewInf(sign int) *Float {
+ return &Float{neg: sign < 0, exp: infExp}
+}
+
+func (z *Float) setExp(e int64) {
+ e32 := int32(e)
+ if int64(e32) != e {
+ panic("exponent overflow") // TODO(gri) handle this gracefully
+ }
+ z.exp = e32
+}
+
+// Accuracy describes the rounding error produced by the most recent
+// operation that generated a Float value, relative to the exact value:
+//
+// -1: below exact value
+// 0: exact value
+// +1: above exact value
+//
+type Accuracy int8
+
+// Constants describing the Accuracy of a Float.
+const (
+ Below Accuracy = -1
+ Exact Accuracy = 0
+ Above Accuracy = +1
+)
+
+func (a Accuracy) String() string {
+ switch {
+ case a < 0:
+ return "below"
+ default:
+ return "exact"
+ case a > 0:
+ return "above"
+ }
+}
+
+// RoundingMode determines how a Float value is rounded to the
+// desired precision. Rounding may change the Float value; the
+// rounding error is described by the Float's Accuracy.
+type RoundingMode uint8
+
+// The following rounding modes are supported.
+const (
+ ToNearestEven RoundingMode = iota // == IEEE 754-2008 roundTiesToEven
+ ToNearestAway // == IEEE 754-2008 roundTiesToAway
+ ToZero // == IEEE 754-2008 roundTowardZero
+ AwayFromZero // no IEEE 754-2008 equivalent
+ ToNegativeInf // == IEEE 754-2008 roundTowardNegative
+ ToPositiveInf // == IEEE 754-2008 roundTowardPositive
+)
+
+func (mode RoundingMode) String() string {
+ switch mode {
+ case ToNearestEven:
+ return "ToNearestEven"
+ case ToNearestAway:
+ return "ToNearestAway"
+ case ToZero:
+ return "ToZero"
+ case AwayFromZero:
+ return "AwayFromZero"
+ case ToNegativeInf:
+ return "ToNegativeInf"
+ case ToPositiveInf:
+ return "ToPositiveInf"
+ }
+ panic("unreachable")
+}
+
+// Precision returns the mantissa precision of x in bits.
+// The precision may be 0 if x == 0. // TODO(gri) Determine a better approach.
+func (x *Float) Precision() uint {
+ return uint(x.prec)
+}
+
+// Accuracy returns the accuracy of x produced by the most recent operation.
+func (x *Float) Accuracy() Accuracy {
+ return x.acc
+}
+
+// Mode returns the rounding mode of x.
+func (x *Float) Mode() RoundingMode {
+ return x.mode
+}
+
+// debugging support
+func (x *Float) validate() {
+ // assumes x != 0
+ const msb = 1 << (_W - 1)
+ m := len(x.mant)
+ if x.mant[m-1]&msb == 0 {
+ panic(fmt.Sprintf("msb not set in last word %#x of %s", x.mant[m-1], x.Format('p', 0)))
+ }
+ if x.prec <= 0 {
+ panic(fmt.Sprintf("invalid precision %d", x.prec))
+ }
+}
+
+// round rounds z according to z.mode to z.prec bits and sets z.acc accordingly.
+// sbit must be 0 or 1 and summarizes any "sticky bit" information one might
+// have before calling round. z's mantissa must be normalized, with the msb set.
+func (z *Float) round(sbit uint) {
+ z.acc = Exact
+
+ // handle zero
+ m := uint(len(z.mant)) // mantissa length in words for current precision
+ if m == 0 {
+ z.exp = 0
+ return
+ }
+
+ if debugFloat {
+ z.validate()
+ }
+ // z.prec > 0
+
+ bits := m * _W // available mantissa bits
+ if bits == z.prec {
+ // mantissa fits Exactly => nothing to do
+ return
+ }
+
+ n := (z.prec + (_W - 1)) / _W // mantissa length in words for desired precision
+ if bits < z.prec {
+ // mantissa too small => extend
+ if m < n {
+ // slice too short => extend slice
+ if int(n) <= cap(z.mant) {
+ // reuse existing slice
+ z.mant = z.mant[:n]
+ copy(z.mant[n-m:], z.mant[:m])
+ z.mant[:n-m].clear()
+ } else {
+ // n > cap(z.mant) => allocate new slice
+ const e = 4 // extra capacity (see nat.make)
+ new := make(nat, n, n+e)
+ copy(new[n-m:], z.mant)
+ }
+ }
+ return
+ }
+
+ // Rounding is based on two bits: the rounding bit (rbit) and the
+ // sticky bit (sbit). The rbit is the bit immediately before the
+ // mantissa bits (the "0.5"). The sbit is set if any of the bits
+ // before the rbit are set (the "0.25", "0.125", etc.):
+ //
+ // rbit sbit => "fractional part"
+ //
+ // 0 0 == 0
+ // 0 1 > 0 , < 0.5
+ // 1 0 == 0.5
+ // 1 1 > 0.5, < 1.0
+
+ // bits > z.prec: mantissa too large => round
+ r := bits - z.prec - 1 // rounding bit position; r >= 0
+ rbit := z.mant.bit(r) // rounding bit
+ if sbit == 0 {
+ sbit = z.mant.sticky(r)
+ }
+ if debugFloat && sbit&^1 != 0 {
+ panic(fmt.Sprintf("invalid sbit %#x", sbit))
+ }
+
+ // convert ToXInf rounding modes
+ mode := z.mode
+ switch mode {
+ case ToNegativeInf:
+ mode = ToZero
+ if z.neg {
+ mode = AwayFromZero
+ }
+ case ToPositiveInf:
+ mode = AwayFromZero
+ if z.neg {
+ mode = ToZero
+ }
+ }
+
+ // cut off extra words
+ if m > n {
+ copy(z.mant, z.mant[m-n:]) // move n last words to front
+ z.mant = z.mant[:n]
+ }
+
+ // determine number of trailing zero bits t
+ t := n*_W - z.prec // 0 <= t < _W
+ lsb := Word(1) << t
+
+ // make rounding decision
+ // TODO(gri) This can be simplified (see roundBits in float_test.go).
+ switch mode {
+ case ToZero:
+ // nothing to do
+ case ToNearestEven, ToNearestAway:
+ if rbit == 0 {
+ // rounding bits == 0b0x
+ mode = ToZero
+ } else if sbit == 1 {
+ // rounding bits == 0b11
+ mode = AwayFromZero
+ }
+ case AwayFromZero:
+ if rbit|sbit == 0 {
+ mode = ToZero
+ }
+ default:
+ // ToXInf modes have been converted to ToZero or AwayFromZero
+ panic("unreachable")
+ }
+
+ // round and determine accuracy
+ switch mode {
+ case ToZero:
+ if rbit|sbit != 0 {
+ z.acc = Below
+ }
+
+ case ToNearestEven, ToNearestAway:
+ if debugFloat && rbit != 1 {
+ panic("internal error in rounding")
+ }
+ if mode == ToNearestEven && sbit == 0 && z.mant[0]&lsb == 0 {
+ z.acc = Below
+ break
+ }
+ // mode == ToNearestAway || sbit == 1 || z.mant[0]&lsb != 0
+ fallthrough
+
+ case AwayFromZero:
+ // add 1 to mantissa
+ if addVW(z.mant, z.mant, lsb) != 0 {
+ // overflow => shift mantissa right by 1 and add msb
+ shrVU(z.mant, z.mant, 1)
+ z.mant[n-1] |= 1 << (_W - 1)
+ // adjust exponent
+ z.exp++
+ }
+ z.acc = Above
+ }
+
+ // zero out trailing bits in least-significant word
+ z.mant[0] &^= lsb - 1
+
+ // update accuracy
+ if z.neg {
+ z.acc = -z.acc
+ }
+
+ if debugFloat {
+ z.validate()
+ }
+
+ return
+}
+
+// Round sets z to the value of x rounded according to mode to prec bits and returns z.
+func (z *Float) Round(x *Float, prec uint, mode RoundingMode) *Float {
+ z.Set(x)
+ z.prec = prec
+ z.mode = mode
+ z.round(0)
+ return z
+}
+
+// nlz returns the number of leading zero bits in x.
+func nlz(x Word) uint {
+ return _W - uint(bitLen(x))
+}
+
+func nlz64(x uint64) uint {
+ // TODO(gri) this can be done more nicely
+ if _W == 32 {
+ if x>>32 == 0 {
+ return 32 + nlz(Word(x))
+ }
+ return nlz(Word(x >> 32))
+ }
+ if _W == 64 {
+ return nlz(Word(x))
+ }
+ panic("unreachable")
+}
+
+// SetUint64 sets z to x and returns z.
+// Precision is set to 64 bits.
+func (z *Float) SetUint64(x uint64) *Float {
+ z.neg = false
+ z.prec = 64
+ if x == 0 {
+ z.mant = z.mant[:0]
+ z.exp = 0
+ return z
+ }
+ s := nlz64(x)
+ z.mant = z.mant.setUint64(x << s)
+ z.exp = int32(64 - s)
+ return z
+}
+
+// SetInt64 sets z to x and returns z.
+// Precision is set to 64 bits.
+func (z *Float) SetInt64(x int64) *Float {
+ u := x
+ if u < 0 {
+ u = -u
+ }
+ z.SetUint64(uint64(u))
+ z.neg = x < 0
+ return z
+}
+
+// SetFloat64 sets z to x and returns z.
+// Precision is set to 53 bits.
+// TODO(gri) test denormals, +/-Inf, disallow NaN.
+func (z *Float) SetFloat64(x float64) *Float {
+ z.prec = 53
+ z.neg = math.Signbit(x) // handle -0 correctly (-0 == 0)
+ if x == 0 {
+ z.mant = z.mant[:0]
+ z.exp = 0
+ return z
+ }
+ fmant, exp := math.Frexp(x) // get normalized mantissa
+ z.mant = z.mant.setUint64(1<<63 | math.Float64bits(fmant)<<11)
+ z.exp = int32(exp)
+ return z
+}
+
+// fnorm normalizes mantissa m by shifting it to the left
+// such that the msb of the most-significant word (msw)
+// is 1. It returns the shift amount.
+// It assumes that m is not the zero nat.
+func fnorm(m nat) uint {
+ if debugFloat && (len(m) == 0 || m[len(m)-1] == 0) {
+ panic("msw of mantissa is 0")
+ }
+ s := nlz(m[len(m)-1])
+ if s > 0 {
+ c := shlVU(m, m, s)
+ if debugFloat && c != 0 {
+ panic("nlz or shlVU incorrect")
+ }
+ }
+ return s
+}
+
+// SetInt sets z to x and returns z.
+// Precision is set to the number of bits required to represent x accurately.
+// TODO(gri) what about precision for x == 0?
+func (z *Float) SetInt(x *Int) *Float {
+ if len(x.abs) == 0 {
+ z.neg = false
+ z.mant = z.mant[:0]
+ z.exp = 0
+ // z.prec = ?
+ return z
+ }
+ // x != 0
+ z.neg = x.neg
+ z.mant = z.mant.set(x.abs)
+ e := uint(len(z.mant))*_W - fnorm(z.mant)
+ z.exp = int32(e)
+ z.prec = e
+ return z
+}
+
+// SetRat sets z to x rounded to the precision of z and returns z.
+func (z *Float) SetRat(x *Rat, prec uint) *Float {
+ panic("unimplemented")
+}
+
+// Set sets z to x, with the same precision as x, and returns z.
+func (z *Float) Set(x *Float) *Float {
+ if z != x {
+ z.neg = x.neg
+ z.exp = x.exp
+ z.mant = z.mant.set(x.mant)
+ z.prec = x.prec
+ }
+ return z
+}
+
+func high64(x nat) uint64 {
+ i := len(x)
+ if i == 0 {
+ return 0
+ }
+ // i > 0
+ v := uint64(x[i-1])
+ if _W == 32 {
+ v <<= 32
+ if i > 1 {
+ v |= uint64(x[i-2])
+ }
+ }
+ return v
+}
+
+// TODO(gri) FIX THIS (rounding mode, errors, accuracy, etc.)
+func (x *Float) Uint64() uint64 {
+ m := high64(x.mant)
+ s := x.exp
+ if s >= 0 {
+ return m >> (64 - uint(s))
+ }
+ return 0 // imprecise
+}
+
+// TODO(gri) FIX THIS (rounding mode, errors, etc.)
+func (x *Float) Int64() int64 {
+ v := int64(x.Uint64())
+ if x.neg {
+ return -v
+ }
+ return v
+}
+
+// Float64 returns the closest float64 value of x
+// by rounding to nearest with 53 bits precision.
+// TODO(gri) implement/document error scenarios.
+func (x *Float) Float64() (float64, Accuracy) {
+ if len(x.mant) == 0 {
+ return 0, Exact
+ }
+ // x != 0
+ r := new(Float).Round(x, 53, ToNearestEven)
+ var s uint64
+ if r.neg {
+ s = 1 << 63
+ }
+ e := uint64(1022+r.exp) & 0x7ff // TODO(gri) check for overflow
+ m := high64(r.mant) >> 11 & (1<<52 - 1)
+ return math.Float64frombits(s | e<<52 | m), r.acc
+}
+
+func (x *Float) Int() *Int {
+ if len(x.mant) == 0 {
+ return new(Int)
+ }
+ panic("unimplemented")
+}
+
+func (x *Float) Rat() *Rat {
+ panic("unimplemented")
+}
+
+func (x *Float) IsInt() bool {
+ if len(x.mant) == 0 {
+ return true
+ }
+ if x.exp <= 0 {
+ return false
+ }
+ if uint(x.exp) >= x.prec {
+ return true
+ }
+ panic("unimplemented")
+}
+
+// Abs sets z to |x| (the absolute value of x) and returns z.
+// TODO(gri) should Abs (and Neg) below ignore z's precision and rounding mode?
+func (z *Float) Abs(x *Float) *Float {
+ z.Set(x)
+ z.neg = false
+ return z
+}
+
+// Neg sets z to x with its sign negated, and returns z.
+func (z *Float) Neg(x *Float) *Float {
+ z.Set(x)
+ z.neg = !z.neg
+ return z
+}
+
+// z = x + y, ignoring signs of x and y.
+// x and y must not be 0.
+func (z *Float) uadd(x, y *Float) {
+ // Note: This implementation requires 2 shifts most of the
+ // time. It is also inefficient if exponents or precisions
+ // differ by wide margins. The following article describes
+ // an efficient (but much more complicated) implementation
+ // compatible with the internal representation used here:
+ //
+ // Vincent Lefèvre: "The Generic Multiple-Precision Floating-
+ // Point Addition With Exact Rounding (as in the MPFR Library)"
+ // http://www.vinc17.net/research/papers/rnc6.pdf
+
+ if debugFloat && (len(x.mant) == 0 || len(y.mant) == 0) {
+ panic("uadd called with 0 argument")
+ }
+
+ // compute exponents ex, ey for mantissa with "binary point"
+ // on the right (mantissa.0) - use int64 to avoid overflow
+ ex := int64(x.exp) - int64(len(x.mant))*_W
+ ey := int64(y.exp) - int64(len(y.mant))*_W
+
+ // TODO(gri) having a combined add-and-shift primitive
+ // could make this code significantly faster
+ switch {
+ case ex < ey:
+ t := z.mant.shl(y.mant, uint(ey-ex))
+ z.mant = t.add(x.mant, t)
+ default:
+ // ex == ey, no shift needed
+ z.mant = z.mant.add(x.mant, y.mant)
+ case ex > ey:
+ t := z.mant.shl(x.mant, uint(ex-ey))
+ z.mant = t.add(t, y.mant)
+ ex = ey
+ }
+ // len(z.mant) > 0
+
+ z.setExp(ex + int64(len(z.mant))*_W - int64(fnorm(z.mant)))
+ z.round(0)
+}
+
+// z = x - y for x >= y, ignoring signs of x and y.
+// x and y must not be zero.
+func (z *Float) usub(x, y *Float) {
+ // This code is symmetric to uadd.
+ // We have not factored the common code out because
+ // eventually uadd (and usub) should be optimized
+ // by special-casing, and the code will diverge.
+
+ if debugFloat && (len(x.mant) == 0 || len(y.mant) == 0) {
+ panic("usub called with 0 argument")
+ }
+
+ ex := int64(x.exp) - int64(len(x.mant))*_W
+ ey := int64(y.exp) - int64(len(y.mant))*_W
+
+ switch {
+ case ex < ey:
+ t := z.mant.shl(y.mant, uint(ey-ex))
+ z.mant = t.sub(x.mant, t)
+ default:
+ // ex == ey, no shift needed
+ z.mant = z.mant.sub(x.mant, y.mant)
+ case ex > ey:
+ t := z.mant.shl(x.mant, uint(ex-ey))
+ z.mant = t.sub(t, y.mant)
+ ex = ey
+ }
+
+ // operands may have cancelled each other out
+ if len(z.mant) == 0 {
+ z.acc = Exact
+ z.setExp(0)
+ return
+ }
+ // len(z.mant) > 0
+
+ z.setExp(ex + int64(len(z.mant))*_W - int64(fnorm(z.mant)))
+ z.round(0)
+}
+
+// z = x * y, ignoring signs of x and y.
+// x and y must not be zero.
+func (z *Float) umul(x, y *Float) {
+ if debugFloat && (len(x.mant) == 0 || len(y.mant) == 0) {
+ panic("umul called with 0 argument")
+ }
+
+ // Note: This is doing too much work if the precision
+ // of z is less than the sum of the precisions of x
+ // and y which is often the case (e.g., if all floats
+ // have the same precision).
+ // TODO(gri) Optimize this for the common case.
+
+ e := int64(x.exp) + int64(y.exp)
+ z.mant = z.mant.mul(x.mant, y.mant)
+
+ // normalize mantissa
+ z.setExp(e - int64(fnorm(z.mant)))
+ z.round(0)
+}
+
+// z = x / y, ignoring signs of x and y.
+// x and y must not be zero.
+func (z *Float) uquo(x, y *Float) {
+ if debugFloat && (len(x.mant) == 0 || len(y.mant) == 0) {
+ panic("uquo called with 0 argument")
+ }
+
+ // mantissa length in words for desired result precision + 1
+ // (at least one extra bit so we get the rounding bit after
+ // the division)
+ n := int(z.prec/_W) + 1
+
+ // compute adjusted x.mant such that we get enough result precision
+ xadj := x.mant
+ if d := n - len(x.mant) + len(y.mant); d > 0 {
+ // d extra words needed => add d "0 digits" to x
+ xadj = make(nat, len(x.mant)+d)
+ copy(xadj[d:], x.mant)
+ }
+ // TODO(gri): If we have too many digits (d < 0), we should be able
+ // to shorten x for faster division. But we must be extra careful
+ // with rounding in that case.
+
+ // divide
+ var r nat
+ z.mant, r = z.mant.div(nil, xadj, y.mant)
+
+ // determine exponent
+ e := int64(x.exp) - int64(y.exp) - int64(len(xadj)-len(y.mant)-len(z.mant))*_W
+
+ // normalize mantissa
+ z.setExp(e - int64(fnorm(z.mant)))
+
+ // The result is long enough to include (at least) the rounding bit.
+ // If there's a non-zero remainder, the corresponding fractional part
+ // (if it were computed), would have a non-zero sticky bit (if it were
+ // zero, it couldn't have a non-zero remainder).
+ var sbit uint
+ if len(r) > 0 {
+ sbit = 1
+ }
+ z.round(sbit)
+}
+
+// ucmp returns -1, 0, or 1, depending on whether x < y, x == y, or x > y,
+// while ignoring the signs of x and y. x and y must not be zero.
+func (x *Float) ucmp(y *Float) int {
+ if debugFloat && (len(x.mant) == 0 || len(y.mant) == 0) {
+ panic("ucmp called with 0 argument")
+ }
+
+ switch {
+ case x.exp < y.exp:
+ return -1
+ case x.exp > y.exp:
+ return 1
+ }
+ // x.exp == y.exp
+
+ // compare mantissas
+ i := len(x.mant)
+ j := len(y.mant)
+ for i > 0 || j > 0 {
+ var xm, ym Word
+ if i > 0 {
+ i--
+ xm = x.mant[i]
+ }
+ if j > 0 {
+ j--
+ ym = y.mant[j]
+ }
+ switch {
+ case xm < ym:
+ return -1
+ case xm > ym:
+ return 1
+ }
+ }
+
+ return 0
+}
+
+// Handling of sign bit as defined by IEEE 754-2008,
+// section 6.3 (note that there are no NaN Floats):
+//
+// When neither the inputs nor result are NaN, the sign of a product or
+// quotient is the exclusive OR of the operands’ signs; the sign of a sum,
+// or of a difference x−y regarded as a sum x+(−y), differs from at most
+// one of the addends’ signs; and the sign of the result of conversions,
+// the quantize operation, the roundToIntegral operations, and the
+// roundToIntegralExact (see 5.3.1) is the sign of the first or only operand.
+// These rules shall apply even when operands or results are zero or infinite.
+//
+// When the sum of two operands with opposite signs (or the difference of
+// two operands with like signs) is exactly zero, the sign of that sum (or
+// difference) shall be +0 in all rounding-direction attributes except
+// roundTowardNegative; under that attribute, the sign of an exact zero
+// sum (or difference) shall be −0. However, x+x = x−(−x) retains the same
+// sign as x even when x is zero.
+
+// Add sets z to the rounded sum x+y and returns z.
+// Rounding is performed according to z's precision
+// and rounding mode; and z's accuracy reports the
+// result error relative to the exact (not rounded)
+// result.
+func (z *Float) Add(x, y *Float) *Float {
+ // TODO(gri) what about -0?
+ if len(y.mant) == 0 {
+ return z.Round(x, z.prec, z.mode)
+ }
+ if len(x.mant) == 0 {
+ return z.Round(y, z.prec, z.mode)
+ }
+
+ // x, y != 0
+ neg := x.neg
+ if x.neg == y.neg {
+ // x + y == x + y
+ // (-x) + (-y) == -(x + y)
+ z.uadd(x, y)
+ } else {
+ // x + (-y) == x - y == -(y - x)
+ // (-x) + y == y - x == -(x - y)
+ if x.ucmp(y) >= 0 {
+ z.usub(x, y)
+ } else {
+ neg = !neg
+ z.usub(y, x)
+ }
+ }
+ z.neg = neg
+ return z
+}
+
+// Sub sets z to the rounded difference x-y and returns z.
+// Rounding is performed according to z's precision
+// and rounding mode; and z's accuracy reports the
+// result error relative to the exact (not rounded)
+// result.
+func (z *Float) Sub(x, y *Float) *Float {
+ // TODO(gri) what about -0?
+ if len(y.mant) == 0 {
+ return z.Round(x, z.prec, z.mode)
+ }
+ if len(x.mant) == 0 {
+ prec := z.prec
+ mode := z.mode
+ z.Neg(y)
+ return z.Round(z, prec, mode)
+ }
+
+ // x, y != 0
+ neg := x.neg
+ if x.neg != y.neg {
+ // x - (-y) == x + y
+ // (-x) - y == -(x + y)
+ z.uadd(x, y)
+ } else {
+ // x - y == x - y == -(y - x)
+ // (-x) - (-y) == y - x == -(x - y)
+ if x.ucmp(y) >= 0 {
+ z.usub(x, y)
+ } else {
+ neg = !neg
+ z.usub(y, x)
+ }
+ }
+ z.neg = neg
+ return z
+}
+
+// Mul sets z to the rounded product x*y and returns z.
+// Rounding is performed according to z's precision
+// and rounding mode; and z's accuracy reports the
+// result error relative to the exact (not rounded)
+// result.
+func (z *Float) Mul(x, y *Float) *Float {
+ // TODO(gri) what about -0?
+ if len(x.mant) == 0 || len(y.mant) == 0 {
+ z.neg = false
+ z.mant = z.mant[:0]
+ z.exp = 0
+ z.acc = Exact
+ return z
+ }
+
+ // x, y != 0
+ z.umul(x, y)
+ z.neg = x.neg != y.neg
+ return z
+}
+
+// Quo sets z to the rounded quotient x/y and returns z.
+// If y == 0, a division-by-zero run-time panic occurs. TODO(gri) this should become Inf
+// Rounding is performed according to z's precision
+// and rounding mode; and z's accuracy reports the
+// result error relative to the exact (not rounded)
+// result.
+func (z *Float) Quo(x, y *Float) *Float {
+ // TODO(gri) what about -0?
+ if len(x.mant) == 0 {
+ z.neg = false
+ z.mant = z.mant[:0]
+ z.exp = 0
+ z.acc = Exact
+ return z
+ }
+ if len(y.mant) == 0 {
+ panic("division-by-zero") // TODO(gri) handle this better
+ }
+
+ // x, y != 0
+ z.uquo(x, y)
+ z.neg = x.neg != y.neg
+ return z
+}
+
+// Lsh sets z to the rounded x * (1<<s) and returns z.
+// Rounding is performed according to z's precision
+// and rounding mode; and z's accuracy reports the
+// result error relative to the exact (not rounded)
+// result.
+func (z *Float) Lsh(x *Float, s uint, mode RoundingMode) *Float {
+ z.Round(x, z.prec, mode)
+ z.setExp(int64(z.exp) + int64(s))
+ return z
+}
+
+// Rsh sets z to the rounded x / (1<<s) and returns z.
+// Rounding is performed according to z's precision
+// and rounding mode; and z's accuracy reports the
+// result error relative to the exact (not rounded)
+// result.
+func (z *Float) Rsh(x *Float, s uint, mode RoundingMode) *Float {
+ z.Round(x, z.prec, mode)
+ z.setExp(int64(z.exp) - int64(s))
+ return z
+}
+
+// Cmp compares x and y and returns:
+//
+// -1 if x < y
+// 0 if x == y (incl. -0 == 0)
+// +1 if x > y
+//
+func (x *Float) Cmp(y *Float) int {
+ // special cases
+ switch {
+ case len(x.mant) == 0:
+ // 0 cmp y == -sign(y)
+ return -y.Sign()
+ case len(y.mant) == 0:
+ // x cmp 0 == sign(x)
+ return x.Sign()
+ }
+ // x != 0 && y != 0
+
+ // x cmp y == x cmp y
+ // x cmp (-y) == 1
+ // (-x) cmp y == -1
+ // (-x) cmp (-y) == -(x cmp y)
+ switch {
+ case x.neg == y.neg:
+ r := x.ucmp(y)
+ if x.neg {
+ r = -r
+ }
+ return r
+ case x.neg:
+ return -1
+ default:
+ return 1
+ }
+ return 0
+}
+
+// Sign returns:
+//
+// -1 if x < 0
+// 0 if x == 0 (incl. x == -0)
+// +1 if x > 0
+//
+func (x *Float) Sign() int {
+ if len(x.mant) == 0 {
+ return 0
+ }
+ if x.neg {
+ return -1
+ }
+ return 1
+}
--- /dev/null
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package big
+
+import (
+ "fmt"
+ "sort"
+ "strconv"
+ "testing"
+)
+
+func fromBinary(s string) int64 {
+ x, err := strconv.ParseInt(s, 2, 64)
+ if err != nil {
+ panic(err)
+ }
+ return x
+}
+
+func toBinary(x int64) string {
+ return strconv.FormatInt(x, 2)
+}
+
+func testFloatRound(t *testing.T, x, r int64, prec uint, mode RoundingMode) {
+ // verify test data
+ var ok bool
+ switch mode {
+ case ToNearestEven, ToNearestAway:
+ ok = true // nothing to do for now
+ case ToZero:
+ if x < 0 {
+ ok = r >= x
+ } else {
+ ok = r <= x
+ }
+ case AwayFromZero:
+ if x < 0 {
+ ok = r <= x
+ } else {
+ ok = r >= x
+ }
+ case ToNegativeInf:
+ ok = r <= x
+ case ToPositiveInf:
+ ok = r >= x
+ default:
+ panic("unreachable")
+ }
+ if !ok {
+ t.Fatalf("incorrect test data for prec = %d, %s: x = %s, r = %s", prec, mode, toBinary(x), toBinary(r))
+ }
+
+ // compute expected accuracy
+ a := Exact
+ switch {
+ case r < x:
+ a = Below
+ case r > x:
+ a = Above
+ }
+
+ // round
+ f := new(Float).SetInt64(x)
+ f.Round(f, prec, mode)
+
+ // check result
+ r1 := f.Int64()
+ p1 := f.Precision()
+ a1 := f.Accuracy()
+ if r1 != r || p1 != prec || a1 != a {
+ t.Errorf("Round(%s, %d, %s): got %s (%d bits, %s); want %s (%d bits, %s)",
+ toBinary(x), prec, mode,
+ toBinary(r1), p1, a1,
+ toBinary(r), prec, a)
+ }
+}
+
+// TestFloatRound tests basic rounding.
+func TestFloatRound(t *testing.T) {
+ for _, test := range []struct {
+ prec uint
+ x, zero, neven, naway, away string // input, results rounded to prec bits
+ }{
+ {5, "1000", "1000", "1000", "1000", "1000"},
+ {5, "1001", "1001", "1001", "1001", "1001"},
+ {5, "1010", "1010", "1010", "1010", "1010"},
+ {5, "1011", "1011", "1011", "1011", "1011"},
+ {5, "1100", "1100", "1100", "1100", "1100"},
+ {5, "1101", "1101", "1101", "1101", "1101"},
+ {5, "1110", "1110", "1110", "1110", "1110"},
+ {5, "1111", "1111", "1111", "1111", "1111"},
+
+ {4, "1000", "1000", "1000", "1000", "1000"},
+ {4, "1001", "1001", "1001", "1001", "1001"},
+ {4, "1010", "1010", "1010", "1010", "1010"},
+ {4, "1011", "1011", "1011", "1011", "1011"},
+ {4, "1100", "1100", "1100", "1100", "1100"},
+ {4, "1101", "1101", "1101", "1101", "1101"},
+ {4, "1110", "1110", "1110", "1110", "1110"},
+ {4, "1111", "1111", "1111", "1111", "1111"},
+
+ {3, "1000", "1000", "1000", "1000", "1000"},
+ {3, "1001", "1000", "1000", "1010", "1010"},
+ {3, "1010", "1010", "1010", "1010", "1010"},
+ {3, "1011", "1010", "1100", "1100", "1100"},
+ {3, "1100", "1100", "1100", "1100", "1100"},
+ {3, "1101", "1100", "1100", "1110", "1110"},
+ {3, "1110", "1110", "1110", "1110", "1110"},
+ {3, "1111", "1110", "10000", "10000", "10000"},
+
+ {3, "1000001", "1000000", "1000000", "1000000", "1010000"},
+ {3, "1001001", "1000000", "1010000", "1010000", "1010000"},
+ {3, "1010001", "1010000", "1010000", "1010000", "1100000"},
+ {3, "1011001", "1010000", "1100000", "1100000", "1100000"},
+ {3, "1100001", "1100000", "1100000", "1100000", "1110000"},
+ {3, "1101001", "1100000", "1110000", "1110000", "1110000"},
+ {3, "1110001", "1110000", "1110000", "1110000", "10000000"},
+ {3, "1111001", "1110000", "10000000", "10000000", "10000000"},
+
+ {2, "1000", "1000", "1000", "1000", "1000"},
+ {2, "1001", "1000", "1000", "1000", "1100"},
+ {2, "1010", "1000", "1000", "1100", "1100"},
+ {2, "1011", "1000", "1100", "1100", "1100"},
+ {2, "1100", "1100", "1100", "1100", "1100"},
+ {2, "1101", "1100", "1100", "1100", "10000"},
+ {2, "1110", "1100", "10000", "10000", "10000"},
+ {2, "1111", "1100", "10000", "10000", "10000"},
+
+ {2, "1000001", "1000000", "1000000", "1000000", "1100000"},
+ {2, "1001001", "1000000", "1000000", "1000000", "1100000"},
+ {2, "1010001", "1000000", "1100000", "1100000", "1100000"},
+ {2, "1011001", "1000000", "1100000", "1100000", "1100000"},
+ {2, "1100001", "1100000", "1100000", "1100000", "10000000"},
+ {2, "1101001", "1100000", "1100000", "1100000", "10000000"},
+ {2, "1110001", "1100000", "10000000", "10000000", "10000000"},
+ {2, "1111001", "1100000", "10000000", "10000000", "10000000"},
+
+ {1, "1000", "1000", "1000", "1000", "1000"},
+ {1, "1001", "1000", "1000", "1000", "10000"},
+ {1, "1010", "1000", "1000", "1000", "10000"},
+ {1, "1011", "1000", "1000", "1000", "10000"},
+ {1, "1100", "1000", "10000", "10000", "10000"},
+ {1, "1101", "1000", "10000", "10000", "10000"},
+ {1, "1110", "1000", "10000", "10000", "10000"},
+ {1, "1111", "1000", "10000", "10000", "10000"},
+
+ {1, "1000001", "1000000", "1000000", "1000000", "10000000"},
+ {1, "1001001", "1000000", "1000000", "1000000", "10000000"},
+ {1, "1010001", "1000000", "1000000", "1000000", "10000000"},
+ {1, "1011001", "1000000", "1000000", "1000000", "10000000"},
+ {1, "1100001", "1000000", "10000000", "10000000", "10000000"},
+ {1, "1101001", "1000000", "10000000", "10000000", "10000000"},
+ {1, "1110001", "1000000", "10000000", "10000000", "10000000"},
+ {1, "1111001", "1000000", "10000000", "10000000", "10000000"},
+ } {
+ x := fromBinary(test.x)
+ z := fromBinary(test.zero)
+ e := fromBinary(test.neven)
+ n := fromBinary(test.naway)
+ a := fromBinary(test.away)
+ prec := test.prec
+
+ testFloatRound(t, x, z, prec, ToZero)
+ testFloatRound(t, x, e, prec, ToNearestEven)
+ testFloatRound(t, x, n, prec, ToNearestAway)
+ testFloatRound(t, x, a, prec, AwayFromZero)
+
+ testFloatRound(t, x, z, prec, ToNegativeInf)
+ testFloatRound(t, x, a, prec, ToPositiveInf)
+
+ testFloatRound(t, -x, -a, prec, ToNegativeInf)
+ testFloatRound(t, -x, -z, prec, ToPositiveInf)
+ }
+}
+
+// TestFloatRound24 tests that rounding a float64 to 24 bits
+// matches IEEE-754 rounding to nearest when converting a
+// float64 to a float32.
+func TestFloatRound24(t *testing.T) {
+ const x0 = 1<<26 - 0x10 // 11...110000 (26 bits)
+ for d := 0; d <= 0x10; d++ {
+ x := float64(x0 + d)
+ f := new(Float).SetFloat64(x)
+ f.Round(f, 24, ToNearestEven)
+ got, _ := f.Float64()
+ want := float64(float32(x))
+ if got != want {
+ t.Errorf("Round(%g, 24) = %g; want %g", x, got, want)
+ }
+ }
+}
+
+func TestFloatSetUint64(t *testing.T) {
+ for _, want := range []uint64{
+ 0,
+ 1,
+ 2,
+ 10,
+ 100,
+ 1<<32 - 1,
+ 1 << 32,
+ 1<<64 - 1,
+ } {
+ f := new(Float).SetUint64(want)
+ if got := f.Uint64(); got != want {
+ t.Errorf("got %d (%s); want %d", got, f.Format('p', 0), want)
+ }
+ }
+}
+
+func TestFloatSetInt64(t *testing.T) {
+ for _, want := range []int64{
+ 0,
+ 1,
+ 2,
+ 10,
+ 100,
+ 1<<32 - 1,
+ 1 << 32,
+ 1<<63 - 1,
+ } {
+ for i := range [2]int{} {
+ if i&1 != 0 {
+ want = -want
+ }
+ f := new(Float).SetInt64(want)
+ if got := f.Int64(); got != want {
+ t.Errorf("got %d (%s); want %d", got, f.Format('p', 0), want)
+ }
+ }
+ }
+}
+
+func TestFloatSetFloat64(t *testing.T) {
+ for _, want := range []float64{
+ 0,
+ 1,
+ 2,
+ 12345,
+ 1e10,
+ 1e100,
+ 3.14159265e10,
+ 2.718281828e-123,
+ 1.0 / 3,
+ } {
+ for i := range [2]int{} {
+ if i&1 != 0 {
+ want = -want
+ }
+ f := new(Float).SetFloat64(want)
+ if got, _ := f.Float64(); got != want {
+ t.Errorf("got %g (%s); want %g", got, f.Format('p', 0), want)
+ }
+ }
+ }
+}
+
+func TestFloatSetInt(t *testing.T) {
+ // TODO(gri) implement
+}
+
+// Selected precisions with which to run various tests.
+var precList = [...]uint{1, 2, 5, 8, 10, 16, 23, 24, 32, 50, 53, 64, 100, 128, 500, 511, 512, 513, 1000, 10000}
+
+// Selected bits with which to run various tests.
+// Each entry is a list of bits representing a floating-point number (see fromBits).
+var bitsList = [...][]int{
+ {}, // = 0
+ {0}, // = 1
+ {1}, // = 2
+ {-1}, // = 1/2
+ {10}, // = 2**10 == 1024
+ {-10}, // = 2**-10 == 1/1024
+ {100, 10, 1}, // = 2**100 + 2**10 + 2**1
+ {0, -1, -2, -10},
+ // TODO(gri) add more test cases
+}
+
+// TestFloatAdd tests Float.Add/Sub by comparing the result of a "manual"
+// addition/subtraction of arguments represented by bits lists with the
+// respective floating-point addition/subtraction for a variety of precisions
+// and rounding modes.
+func TestFloatAdd(t *testing.T) {
+ for _, xbits := range bitsList {
+ for _, ybits := range bitsList {
+ // exact values
+ x := fromBits(xbits...)
+ y := fromBits(ybits...)
+ zbits := append(xbits, ybits...)
+ z := fromBits(zbits...)
+
+ for i, mode := range [...]RoundingMode{ToZero, ToNearestEven, AwayFromZero} {
+ for _, prec := range precList {
+ got := NewFloat(0, prec, mode)
+ got.Add(x, y)
+ want := roundBits(zbits, prec, mode)
+ if got.Cmp(want) != 0 {
+ t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t+ %s %v\n\t= %s\n\twant %s",
+ i, prec, mode, x, xbits, y, ybits, got, want)
+ return
+ }
+
+ got.Sub(z, x)
+ want = roundBits(ybits, prec, mode)
+ if got.Cmp(want) != 0 {
+ t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t- %s %v\n\t= %s\n\twant %s",
+ i, prec, mode, z, zbits, x, xbits, got, want)
+ }
+ }
+ }
+ }
+ }
+}
+
+// TestFloatAdd32 tests that Float.Add/Sub of numbers with
+// 24bit mantissa behaves like float32 addition/subtraction.
+func TestFloatAdd32(t *testing.T) {
+ // TODO(gri) fix test for 32bit platforms
+ if _W == 32 {
+ return
+ }
+
+ // chose base such that we cross the mantissa precision limit
+ const base = 1<<26 - 0x10 // 11...110000 (26 bits)
+ for d := 0; d <= 0x10; d++ {
+ for i := range [2]int{} {
+ x0, y0 := float64(base), float64(d)
+ if i&1 != 0 {
+ x0, y0 = y0, x0
+ }
+
+ x := new(Float).SetFloat64(x0)
+ y := new(Float).SetFloat64(y0)
+ z := NewFloat(0, 24, ToNearestEven)
+
+ z.Add(x, y)
+ got, acc := z.Float64()
+ want := float64(float32(y0) + float32(x0))
+ if got != want || acc != Exact {
+ t.Errorf("d = %d: %g + %g = %g (%s); want %g exactly", d, x0, y0, got, acc, want)
+ }
+
+ z.Sub(z, y)
+ got, acc = z.Float64()
+ want = float64(float32(want) - float32(y0))
+ if got != want || acc != Exact {
+ t.Errorf("d = %d: %g - %g = %g (%s); want %g exactly", d, x0+y0, y0, got, acc, want)
+ }
+ }
+ }
+}
+
+// TestFloatAdd64 tests that Float.Add/Sub of numbers with
+// 53bit mantissa behaves like float64 addition/subtraction.
+func TestFloatAdd64(t *testing.T) {
+ // chose base such that we cross the mantissa precision limit
+ const base = 1<<55 - 0x10 // 11...110000 (55 bits)
+ for d := 0; d <= 0x10; d++ {
+ for i := range [2]int{} {
+ x0, y0 := float64(base), float64(d)
+ if i&1 != 0 {
+ x0, y0 = y0, x0
+ }
+
+ x := new(Float).SetFloat64(x0)
+ y := new(Float).SetFloat64(y0)
+ z := NewFloat(0, 53, ToNearestEven)
+
+ z.Add(x, y)
+ got, acc := z.Float64()
+ want := x0 + y0
+ if got != want || acc != Exact {
+ t.Errorf("d = %d: %g + %g = %g (%s); want %g exactly", d, x0, y0, got, acc, want)
+ }
+
+ z.Sub(z, y)
+ got, acc = z.Float64()
+ want -= y0
+ if got != want || acc != Exact {
+ t.Errorf("d = %d: %g - %g = %g (%s); want %g exactly", d, x0+y0, y0, got, acc, want)
+ }
+ }
+ }
+}
+
+func TestFloatMul(t *testing.T) {
+}
+
+// TestFloatMul64 tests that Float.Mul/Quo of numbers with
+// 53bit mantissa behaves like float64 multiplication/division.
+func TestFloatMul64(t *testing.T) {
+ for _, test := range []struct {
+ x, y float64
+ }{
+ {0, 0},
+ {0, 1},
+ {1, 1},
+ {1, 1.5},
+ {1.234, 0.5678},
+ {2.718281828, 3.14159265358979},
+ {2.718281828e10, 3.14159265358979e-32},
+ {1.0 / 3, 1e200},
+ } {
+ for i := range [8]int{} {
+ x0, y0 := test.x, test.y
+ if i&1 != 0 {
+ x0 = -x0
+ }
+ if i&2 != 0 {
+ y0 = -y0
+ }
+ if i&4 != 0 {
+ x0, y0 = y0, x0
+ }
+
+ x := new(Float).SetFloat64(x0)
+ y := new(Float).SetFloat64(y0)
+ z := NewFloat(0, 53, ToNearestEven)
+
+ z.Mul(x, y)
+ got, _ := z.Float64()
+ want := x0 * y0
+ if got != want {
+ t.Errorf("%g * %g = %g; want %g", x0, y0, got, want)
+ }
+
+ if y0 == 0 {
+ continue // avoid division-by-zero
+ }
+ z.Quo(z, y)
+ got, _ = z.Float64()
+ want /= y0
+ if got != want {
+ t.Errorf("%g / %g = %g; want %g", x0*y0, y0, got, want)
+ }
+ }
+ }
+}
+
+func TestIssue6866(t *testing.T) {
+ for _, prec := range precList {
+ two := NewFloat(2, prec, ToNearestEven)
+ one := NewFloat(1, prec, ToNearestEven)
+ three := NewFloat(3, prec, ToNearestEven)
+ msix := NewFloat(-6, prec, ToNearestEven)
+ psix := NewFloat(+6, prec, ToNearestEven)
+
+ p := NewFloat(0, prec, ToNearestEven)
+ z1 := NewFloat(0, prec, ToNearestEven)
+ z2 := NewFloat(0, prec, ToNearestEven)
+
+ // z1 = 2 + 1.0/3*-6
+ p.Quo(one, three)
+ p.Mul(p, msix)
+ z1.Add(two, p)
+
+ // z2 = 2 - 1.0/3*+6
+ p.Quo(one, three)
+ p.Mul(p, psix)
+ z2.Sub(two, p)
+
+ if z1.Cmp(z2) != 0 {
+ t.Fatalf("prec %d: got z1 = %s != z2 = %s; want z1 == z2\n", prec, z1, z2)
+ }
+ if z1.Sign() != 0 {
+ t.Errorf("prec %d: got z1 = %s; want 0", prec, z1)
+ }
+ if z2.Sign() != 0 {
+ t.Errorf("prec %d: got z2 = %s; want 0", prec, z2)
+ }
+ }
+}
+
+func TestFloatQuo(t *testing.T) {
+ // TODO(gri) make the test vary these precisions
+ preci := 200 // precision of integer part
+ precf := 20 // precision of fractional part
+
+ for i := 0; i < 8; i++ {
+ // compute accurate (not rounded) result z
+ bits := []int{preci - 1}
+ if i&3 != 0 {
+ bits = append(bits, 0)
+ }
+ if i&2 != 0 {
+ bits = append(bits, -1)
+ }
+ if i&1 != 0 {
+ bits = append(bits, -precf)
+ }
+ z := fromBits(bits...)
+
+ // compute accurate x as z*y
+ y := new(Float).SetFloat64(3.14159265358979323e123)
+
+ x := NewFloat(0, z.Precision()+y.Precision(), ToZero)
+ x.Mul(z, y)
+
+ // leave for debugging
+ // fmt.Printf("x = %s\ny = %s\nz = %s\n", x, y, z)
+
+ if got := x.Accuracy(); got != Exact {
+ t.Errorf("got acc = %s; want exact", got)
+ }
+
+ // round accurate z for a variety of precisions and
+ // modes and compare against result of x / y.
+ for _, mode := range [...]RoundingMode{ToZero, ToNearestEven, AwayFromZero} {
+ for d := -5; d < 5; d++ {
+ prec := uint(preci + d)
+ got := NewFloat(0, prec, mode).Quo(x, y)
+ want := roundBits(bits, prec, mode)
+ if got.Cmp(want) != 0 {
+ t.Errorf("i = %d, prec = %d, %s:\n\t %s\n\t/ %s\n\t= %s\n\twant %s",
+ i, prec, mode, x, y, got, want)
+ }
+ }
+ }
+ }
+}
+
+// normBits returns the normalized bits for x: It
+// removes multiple equal entries by treating them
+// as an addition (e.g., []int{5, 5} => []int{6}),
+// and it sorts the result list for reproducible
+// results.
+func normBits(x []int) []int {
+ m := make(map[int]bool)
+ for _, b := range x {
+ for m[b] {
+ m[b] = false
+ b++
+ }
+ m[b] = true
+ }
+ var z []int
+ for b, set := range m {
+ if set {
+ z = append(z, b)
+ }
+ }
+ sort.Ints(z)
+ return z
+}
+
+func TestNormBits(t *testing.T) {
+ for _, test := range []struct {
+ x, want []int
+ }{
+ {nil, nil},
+ {[]int{}, []int{}},
+ {[]int{0}, []int{0}},
+ {[]int{0, 0}, []int{1}},
+ {[]int{3, 1, 1}, []int{2, 3}},
+ {[]int{10, 9, 8, 7, 6, 6}, []int{11}},
+ } {
+ got := fmt.Sprintf("%v", normBits(test.x))
+ want := fmt.Sprintf("%v", test.want)
+ if got != want {
+ t.Errorf("normBits(%v) = %s; want %s", test.x, got, want)
+ }
+
+ }
+}
+
+// roundBits returns the Float value rounded to prec bits
+// according to mode from the bit set x.
+func roundBits(x []int, prec uint, mode RoundingMode) *Float {
+ x = normBits(x)
+
+ // determine range
+ var min, max int
+ for i, b := range x {
+ if i == 0 || b < min {
+ min = b
+ }
+ if i == 0 || b > max {
+ max = b
+ }
+ }
+ prec0 := uint(max + 1 - min)
+ if prec >= prec0 {
+ return fromBits(x...)
+ }
+ // prec < prec0
+
+ // determine bit 0, rounding, and sticky bit, and result bits z
+ var bit0, rbit, sbit uint
+ var z []int
+ r := max - int(prec)
+ for _, b := range x {
+ switch {
+ case b == r:
+ rbit = 1
+ case b < r:
+ sbit = 1
+ default:
+ // b > r
+ if b == r+1 {
+ bit0 = 1
+ }
+ z = append(z, b)
+ }
+ }
+
+ // round
+ f := fromBits(z...) // rounded to zero
+ if mode == ToNearestAway {
+ panic("not yet implemented")
+ }
+ if mode == ToNearestEven && rbit == 1 && (sbit == 1 || sbit == 0 && bit0 != 0) || mode == AwayFromZero {
+ // round away from zero
+ f.Round(f, prec, ToZero) // extend precision // TODO(gri) better approach?
+ f.Add(f, fromBits(int(r)+1))
+ }
+ return f
+}
+
+// fromBits returns the *Float z of the smallest possible precision
+// such that z = sum(2**bits[i]), with i = range bits.
+// If multiple bits[i] are equal, they are added: fromBits(0, 1, 0)
+// == 2**1 + 2**0 + 2**0 = 4.
+func fromBits(bits ...int) *Float {
+ // handle 0
+ if len(bits) == 0 {
+ return new(Float)
+ // z.prec = ?
+ }
+ // len(bits) > 0
+
+ // determine lsb exponent
+ var min int
+ for i, b := range bits {
+ if i == 0 || b < min {
+ min = b
+ }
+ }
+
+ // create bit pattern
+ x := NewInt(0)
+ for _, b := range bits {
+ badj := b - min
+ // propagate carry if necessary
+ for x.Bit(badj) != 0 {
+ x.SetBit(x, badj, 0)
+ badj++
+ }
+ x.SetBit(x, badj, 1)
+ }
+
+ // create corresponding float
+ z := new(Float).SetInt(x) // normalized
+ z.setExp(int64(z.exp) + int64(min))
+ return z
+}
+
+func TestFromBits(t *testing.T) {
+ for _, test := range []struct {
+ bits []int
+ want string
+ }{
+ // all different bit numbers
+ {nil, "0"},
+ {[]int{0}, "0x.8p1"},
+ {[]int{1}, "0x.8p2"},
+ {[]int{-1}, "0x.8p0"},
+ {[]int{63}, "0x.8p64"},
+ {[]int{33, -30}, "0x.8000000000000001p34"},
+ {[]int{255, 0}, "0x.8000000000000000000000000000000000000000000000000000000000000001p256"},
+
+ // multiple equal bit numbers
+ {[]int{0, 0}, "0x.8p2"},
+ {[]int{0, 0, 0, 0}, "0x.8p3"},
+ {[]int{0, 1, 0}, "0x.8p3"},
+ {append([]int{2, 1, 0} /* 7 */, []int{3, 1} /* 10 */ ...), "0x.88p5" /* 17 */},
+ } {
+ f := fromBits(test.bits...)
+ if got := f.Format('p', 0); got != test.want {
+ t.Errorf("setBits(%v) = %s; want %s", test.bits, got, test.want)
+ }
+ }
+}
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements float-to-string conversion functions.
+
+package big
+
+import (
+ "fmt"
+ "io"
+ "strconv"
+ "strings"
+)
+
+// SetString sets z to the value of s and returns z and a boolean indicating
+// success. s must be a floating-point number of the same format as accepted
+// by Scan, with number prefixes permitted.
+func (z *Float) SetString(s string) (*Float, bool) {
+ r := strings.NewReader(s)
+
+ f, _, err := z.Scan(r, 0)
+ if err != nil {
+ return nil, false
+ }
+
+ // there should be no unread characters left
+ if _, _, err = r.ReadRune(); err != io.EOF {
+ return nil, false
+ }
+
+ return f, true
+}
+
+// Scan scans the number corresponding to the longest possible prefix
+// of r representing a floating-point number with a mantissa in the
+// given conversion base (the exponent is always a decimal number).
+// It returns the corresponding Float f, the actual base b, and an
+// error err, if any. The number must be of the form:
+//
+// number = [ sign ] [ prefix ] mantissa [ exponent ] .
+// sign = "+" | "-" .
+// prefix = "0" ( "x" | "X" | "b" | "B" ) .
+// mantissa = digits | digits "." [ digits ] | "." digits .
+// exponent = ( "E" | "e" | "p" ) [ sign ] digits .
+// digits = digit { digit } .
+// digit = "0" ... "9" | "a" ... "z" | "A" ... "Z" .
+//
+// The base argument must be 0 or a value between 2 through MaxBase.
+//
+// For base 0, the number prefix determines the actual base: A prefix of
+// ``0x'' or ``0X'' selects base 16, and a ``0b'' or ``0B'' prefix selects
+// base 2; otherwise, the actual base is 10 and no prefix is permitted.
+// The octal prefix ``0'' is not supported.
+//
+// A "p" exponent indicates power of 2 for the exponent; for instance "1.2p3"
+// with base 0 or 10 corresponds to the value 1.2 * 2**3.
+//
+// BUG(gri) This signature conflicts with Scan(s fmt.ScanState, ch rune) error.
+func (z *Float) Scan(r io.ByteScanner, base int) (f *Float, b int, err error) {
+ // sign
+ z.neg, err = scanSign(r)
+ if err != nil {
+ return
+ }
+
+ // mantissa
+ var ecorr int // decimal exponent correction; valid if <= 0
+ z.mant, b, ecorr, err = z.mant.scan(r, base, true)
+ if err != nil {
+ return
+ }
+
+ // exponent
+ var exp int64
+ var ebase int
+ exp, ebase, err = scanExponent(r)
+ if err != nil {
+ return
+ }
+ // special-case 0
+ if len(z.mant) == 0 {
+ z.exp = 0
+ f = z
+ return
+ }
+ // len(z.mant) > 0
+
+ // determine binary (exp2) and decimal (exp) exponent
+ exp2 := int64(len(z.mant)*_W - int(fnorm(z.mant)))
+ if ebase == 2 {
+ exp2 += exp
+ exp = 0
+ }
+ if ecorr < 0 {
+ exp += int64(ecorr)
+ }
+
+ z.setExp(exp2)
+ if exp == 0 {
+ // no decimal exponent
+ z.round(0)
+ f = z
+ return
+ }
+ // exp != 0
+
+ // compute decimal exponent power
+ expabs := exp
+ if expabs < 0 {
+ expabs = -expabs
+ }
+ powTen := new(Float).SetInt(new(Int).SetBits(nat(nil).expNN(natTen, nat(nil).setWord(Word(expabs)), nil)))
+
+ // correct result
+ if exp < 0 {
+ z.uquo(z, powTen)
+ } else {
+ z.umul(z, powTen)
+ }
+
+ f = z
+ return
+}
+
+// Parse is like z.Scan(r, base), but instead of reading from an
+// io.ByteScanner, it parses the string s. An error is returned if the
+// string contains invalid or trailing characters not belonging to the
+// number.
+//
+// TODO(gri) define possible errors more precisely
+func (z *Float) Parse(s string, base int) (f *Float, b int, err error) {
+ r := strings.NewReader(s)
+
+ if f, b, err = z.Scan(r, base); err != nil {
+ return
+ }
+
+ // entire string must have been consumed
+ var ch byte
+ if ch, err = r.ReadByte(); err != io.EOF {
+ if err == nil {
+ err = fmt.Errorf("expected end of string, found %q", ch)
+ }
+ }
+
+ return
+}
+
+// ScanFloat is like f.Scan(r, base) with f set to the given precision
+// and rounding mode.
+func ScanFloat(r io.ByteScanner, base int, prec uint, mode RoundingMode) (f *Float, b int, err error) {
+ return NewFloat(0, prec, mode).Scan(r, base)
+}
+
+// ParseFloat is like f.Parse(s, base) with f set to the given precision
+// and rounding mode.
+func ParseFloat(s string, base int, prec uint, mode RoundingMode) (f *Float, b int, err error) {
+ return NewFloat(0, prec, mode).Parse(s, base)
+}
+
+// Format converts the floating-point number x to a string according
+// to the given format and precision prec. The format is one of:
+//
+// 'e' -d.dddde±dd, decimal exponent
+// 'E' -d.ddddE±dd, decimal exponent
+// 'f' -ddddd.dddd, no exponent
+// 'g' like 'e' for large exponents, like 'f' otherwise
+// 'G' like 'E' for large exponents, like 'f' otherwise
+// 'b' -ddddddp±dd, binary exponent
+// 'p' -0x.dddp±dd, binary exponent, hexadecimal mantissa
+//
+// For the binary exponent formats, the mantissa is printed in normalized form:
+//
+// 'b' decimal integer mantissa using x.Precision() bits, or -0
+// 'p' hexadecimal fraction with 0.5 <= 0.mantissa < 1.0, or -0
+//
+// The precision prec controls the number of digits (excluding the exponent)
+// printed by the 'e', 'E', 'f', 'g', and 'G' formats. For 'e', 'E', and 'f'
+// it is the number of digits after the decimal point. For 'g' and 'G' it is
+// the total number of digits. A negative precision selects the smallest
+// number of digits necessary such that ParseFloat will return f exactly.
+// The prec value is ignored for the 'b' or 'p' format.
+//
+// BUG(gri) Currently, Format only accepts the 'b' and 'p' format.
+func (x *Float) Format(format byte, prec int) string {
+ const extra = 10 // TODO(gri) determine a good/better value here
+ return string(x.Append(make([]byte, 0, prec+extra), format, prec))
+}
+
+// Append appends the string form of the floating-point number x,
+// as generated by x.Format, to buf and returns the extended buffer.
+func (x *Float) Append(buf []byte, format byte, prec int) []byte {
+ switch format {
+ case 'b':
+ return x.bstring(buf)
+ case 'p':
+ return x.pstring(buf)
+ }
+ return append(buf, fmt.Sprintf(`%%!c`, format)...)
+}
+
+// BUG(gri): Currently, String uses the 'p' (rather than 'g') format.
+func (x *Float) String() string {
+ return x.Format('p', 0)
+}
+
+// bstring appends the string of x in the format ["-"] mantissa "p" exponent
+// with a decimal mantissa and a binary exponent, or ["-"] "0" if x is zero,
+// and returns the extended buffer.
+// The mantissa is normalized such that is uses x.Precision() bits in binary
+// representation.
+func (x *Float) bstring(buf []byte) []byte {
+ // TODO(gri) handle Inf
+ if x.neg {
+ buf = append(buf, '-')
+ }
+ if len(x.mant) == 0 {
+ return append(buf, '0')
+ }
+ // x != 0
+ // normalize mantissa
+ m := x.mant
+ t := uint(len(x.mant)*_W) - x.prec // 0 <= t < _W
+ if t > 0 {
+ m = nat(nil).shr(m, t)
+ }
+ buf = append(buf, m.decimalString()...)
+ buf = append(buf, 'p')
+ e := int64(x.exp) - int64(x.prec)
+ if e >= 0 {
+ buf = append(buf, '+')
+ }
+ return strconv.AppendInt(buf, e, 10)
+}
+
+// pstring appends the string of x in the format ["-"] "0x." mantissa "p" exponent
+// with a hexadecimal mantissa and a binary exponent, or ["-"] "0" if x is zero,
+// ad returns the extended buffer.
+// The mantissa is normalized such that 0.5 <= 0.mantissa < 1.0.
+func (x *Float) pstring(buf []byte) []byte {
+ // TODO(gri) handle Inf
+ if x.neg {
+ buf = append(buf, '-')
+ }
+ if len(x.mant) == 0 {
+ return append(buf, '0')
+ }
+ // x != 0
+ // mantissa is stored in normalized form
+ buf = append(buf, "0x."...)
+ buf = append(buf, strings.TrimRight(x.mant.hexString(), "0")...)
+ buf = append(buf, 'p')
+ return strconv.AppendInt(buf, int64(x.exp), 10)
+}
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package big
+
+import (
+ "strconv"
+ "testing"
+)
+
+func TestFloatSetFloat64String(t *testing.T) {
+ for _, test := range []struct {
+ s string
+ x float64
+ }{
+ {"0", 0},
+ {"-0", -0},
+ {"+0", 0},
+ {"1", 1},
+ {"-1", -1},
+ {"+1", 1},
+ {"1.234", 1.234},
+ {"-1.234", -1.234},
+ {"+1.234", 1.234},
+ {".1", 0.1},
+ {"1.", 1},
+ {"+1.", 1},
+
+ {"0e100", 0},
+ {"-0e+100", 0},
+ {"+0e-100", 0},
+ {"0E100", 0},
+ {"-0E+100", 0},
+ {"+0E-100", 0},
+ {"0p100", 0},
+ {"-0p+100", 0},
+ {"+0p-100", 0},
+
+ {"1.e10", 1e10},
+ {"1e+10", 1e10},
+ {"+1e-10", 1e-10},
+ {"1E10", 1e10},
+ {"1.E+10", 1e10},
+ {"+1E-10", 1e-10},
+ {"1p10", 1 << 10},
+ {"1p+10", 1 << 10},
+ {"+1.p-10", 1.0 / (1 << 10)},
+
+ {"-687436.79457e-245", -687436.79457e-245},
+ {"-687436.79457E245", -687436.79457e245},
+ {"1024.p-12", 0.25},
+ {"-1.p10", -1024},
+ {"0.25p2", 1},
+
+ {".0000000000000000000000000000000000000001", 1e-40},
+ {"+10000000000000000000000000000000000000000e-0", 1e40},
+ } {
+ var x Float
+ x.prec = 53 // TODO(gri) find better solution
+ _, ok := x.SetString(test.s)
+ if !ok {
+ t.Errorf("%s: parse error", test.s)
+ continue
+ }
+ f, _ := x.Float64()
+ want := new(Float).SetFloat64(test.x)
+ if x.Cmp(want) != 0 {
+ t.Errorf("%s: got %s (%v); want %v", test.s, &x, f, test.x)
+ }
+ }
+}
+
+func TestFloatFormat(t *testing.T) {
+ for _, test := range []struct {
+ x string
+ format byte
+ prec int
+ want string
+ }{
+ {"0", 'b', 0, "0"},
+ {"-0", 'b', 0, "-0"},
+ {"1.0", 'b', 0, "4503599627370496p-52"},
+ {"-1.0", 'b', 0, "-4503599627370496p-52"},
+ {"4503599627370496", 'b', 0, "4503599627370496p+0"},
+
+ {"0", 'p', 0, "0"},
+ {"-0", 'p', 0, "-0"},
+ {"1024.0", 'p', 0, "0x.8p11"},
+ {"-1024.0", 'p', 0, "-0x.8p11"},
+ } {
+ f64, err := strconv.ParseFloat(test.x, 64)
+ if err != nil {
+ t.Error(err)
+ continue
+ }
+
+ f := new(Float).SetFloat64(f64)
+ got := f.Format(test.format, test.prec)
+ if got != test.want {
+ t.Errorf("%v: got %s; want %s", test, got, test.want)
+ }
+
+ if test.format == 'b' && f64 == 0 {
+ continue // 'b' format in strconv.Float requires knowledge of bias for 0.0
+ }
+ if test.format == 'p' {
+ continue // 'p' format not supported in strconv.Format
+ }
+
+ // verify that Float format matches strconv format
+ want := strconv.FormatFloat(f64, test.format, test.prec, 64)
+ if got != want {
+ t.Errorf("%v: got %s; want %s", test, got, want)
+ }
+ }
+}
return
}
-func (x *Int) String() string {
- switch {
- case x == nil:
- return "<nil>"
- case x.neg:
- return "-" + x.abs.decimalString()
- }
- return x.abs.decimalString()
-}
-
-func charset(ch rune) string {
- switch ch {
- case 'b':
- return lowercaseDigits[0:2]
- case 'o':
- return lowercaseDigits[0:8]
- case 'd', 's', 'v':
- return lowercaseDigits[0:10]
- case 'x':
- return lowercaseDigits[0:16]
- case 'X':
- return uppercaseDigits[0:16]
- }
- return "" // unknown format
-}
-
-// write count copies of text to s
-func writeMultiple(s fmt.State, text string, count int) {
- if len(text) > 0 {
- b := []byte(text)
- for ; count > 0; count-- {
- s.Write(b)
- }
- }
-}
-
-// Format is a support routine for fmt.Formatter. It accepts
-// the formats 'b' (binary), 'o' (octal), 'd' (decimal), 'x'
-// (lowercase hexadecimal), and 'X' (uppercase hexadecimal).
-// Also supported are the full suite of package fmt's format
-// verbs for integral types, including '+', '-', and ' '
-// for sign control, '#' for leading zero in octal and for
-// hexadecimal, a leading "0x" or "0X" for "%#x" and "%#X"
-// respectively, specification of minimum digits precision,
-// output field width, space or zero padding, and left or
-// right justification.
-//
-func (x *Int) Format(s fmt.State, ch rune) {
- cs := charset(ch)
-
- // special cases
- switch {
- case cs == "":
- // unknown format
- fmt.Fprintf(s, "%%!%c(big.Int=%s)", ch, x.String())
- return
- case x == nil:
- fmt.Fprint(s, "<nil>")
- return
- }
-
- // determine sign character
- sign := ""
- switch {
- case x.neg:
- sign = "-"
- case s.Flag('+'): // supersedes ' ' when both specified
- sign = "+"
- case s.Flag(' '):
- sign = " "
- }
-
- // determine prefix characters for indicating output base
- prefix := ""
- if s.Flag('#') {
- switch ch {
- case 'o': // octal
- prefix = "0"
- case 'x': // hexadecimal
- prefix = "0x"
- case 'X':
- prefix = "0X"
- }
- }
-
- // determine digits with base set by len(cs) and digit characters from cs
- digits := x.abs.string(cs)
-
- // number of characters for the three classes of number padding
- var left int // space characters to left of digits for right justification ("%8d")
- var zeroes int // zero characters (actually cs[0]) as left-most digits ("%.8d")
- var right int // space characters to right of digits for left justification ("%-8d")
-
- // determine number padding from precision: the least number of digits to output
- precision, precisionSet := s.Precision()
- if precisionSet {
- switch {
- case len(digits) < precision:
- zeroes = precision - len(digits) // count of zero padding
- case digits == "0" && precision == 0:
- return // print nothing if zero value (x == 0) and zero precision ("." or ".0")
- }
- }
-
- // determine field pad from width: the least number of characters to output
- length := len(sign) + len(prefix) + zeroes + len(digits)
- if width, widthSet := s.Width(); widthSet && length < width { // pad as specified
- switch d := width - length; {
- case s.Flag('-'):
- // pad on the right with spaces; supersedes '0' when both specified
- right = d
- case s.Flag('0') && !precisionSet:
- // pad with zeroes unless precision also specified
- zeroes = d
- default:
- // pad on the left with spaces
- left = d
- }
- }
-
- // print number as [left pad][sign][prefix][zero pad][digits][right pad]
- writeMultiple(s, " ", left)
- writeMultiple(s, sign, 1)
- writeMultiple(s, prefix, 1)
- writeMultiple(s, "0", zeroes)
- writeMultiple(s, digits, 1)
- writeMultiple(s, " ", right)
-}
-
-// scan sets z to the integer value corresponding to the longest possible prefix
-// read from r representing a signed integer number in a given conversion base.
-// It returns z, the actual conversion base used, and an error, if any. In the
-// error case, the value of z is undefined but the returned value is nil. The
-// syntax follows the syntax of integer literals in Go.
-//
-// The base argument must be 0 or a value from 2 through MaxBase. If the base
-// is 0, the string prefix determines the actual conversion base. A prefix of
-// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a
-// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
-//
-func (z *Int) scan(r io.RuneScanner, base int) (*Int, int, error) {
- // determine sign
- ch, _, err := r.ReadRune()
- if err != nil {
- return nil, 0, err
- }
- neg := false
- switch ch {
- case '-':
- neg = true
- case '+': // nothing to do
- default:
- r.UnreadRune()
- }
-
- // determine mantissa
- z.abs, base, err = z.abs.scan(r, base)
- if err != nil {
- return nil, base, err
- }
- z.neg = len(z.abs) > 0 && neg // 0 has no sign
-
- return z, base, nil
-}
-
-// Scan is a support routine for fmt.Scanner; it sets z to the value of
-// the scanned number. It accepts the formats 'b' (binary), 'o' (octal),
-// 'd' (decimal), 'x' (lowercase hexadecimal), and 'X' (uppercase hexadecimal).
-func (z *Int) Scan(s fmt.ScanState, ch rune) error {
- s.SkipSpace() // skip leading space characters
- base := 0
- switch ch {
- case 'b':
- base = 2
- case 'o':
- base = 8
- case 'd':
- base = 10
- case 'x', 'X':
- base = 16
- case 's', 'v':
- // let scan determine the base
- default:
- return errors.New("Int.Scan: invalid verb")
- }
- _, _, err := z.scan(s, base)
- return err
-}
-
// low32 returns the least significant 32 bits of z.
func low32(z nat) uint32 {
if len(z) == 0 {
if err != nil {
return nil, false
}
- _, _, err = r.ReadRune()
+ _, err = r.ReadByte()
if err != io.EOF {
return nil, false
}
// ProbablyPrime performs n Miller-Rabin tests to check whether x is prime.
// If it returns true, x is prime with probability 1 - 1/4^n.
-// If it returns false, x is not prime. n must be >0.
+// If it returns false, x is not prime. n must be > 0.
func (x *Int) ProbablyPrime(n int) bool {
if n <= 0 {
panic("non-positive n for ProbablyPrime")
}
}
-var stringTests = []struct {
- in string
- out string
- base int
- val int64
- ok bool
-}{
- {in: "", ok: false},
- {in: "a", ok: false},
- {in: "z", ok: false},
- {in: "+", ok: false},
- {in: "-", ok: false},
- {in: "0b", ok: false},
- {in: "0x", ok: false},
- {in: "2", base: 2, ok: false},
- {in: "0b2", base: 0, ok: false},
- {in: "08", ok: false},
- {in: "8", base: 8, ok: false},
- {in: "0xg", base: 0, ok: false},
- {in: "g", base: 16, ok: false},
- {"0", "0", 0, 0, true},
- {"0", "0", 10, 0, true},
- {"0", "0", 16, 0, true},
- {"+0", "0", 0, 0, true},
- {"-0", "0", 0, 0, true},
- {"10", "10", 0, 10, true},
- {"10", "10", 10, 10, true},
- {"10", "10", 16, 16, true},
- {"-10", "-10", 16, -16, true},
- {"+10", "10", 16, 16, true},
- {"0x10", "16", 0, 16, true},
- {in: "0x10", base: 16, ok: false},
- {"-0x10", "-16", 0, -16, true},
- {"+0x10", "16", 0, 16, true},
- {"00", "0", 0, 0, true},
- {"0", "0", 8, 0, true},
- {"07", "7", 0, 7, true},
- {"7", "7", 8, 7, true},
- {"023", "19", 0, 19, true},
- {"23", "23", 8, 19, true},
- {"cafebabe", "cafebabe", 16, 0xcafebabe, true},
- {"0b0", "0", 0, 0, true},
- {"-111", "-111", 2, -7, true},
- {"-0b111", "-7", 0, -7, true},
- {"0b1001010111", "599", 0, 0x257, true},
- {"1001010111", "1001010111", 2, 0x257, true},
-}
-
-func format(base int) string {
- switch base {
- case 2:
- return "%b"
- case 8:
- return "%o"
- case 16:
- return "%x"
- }
- return "%d"
-}
-
-func TestGetString(t *testing.T) {
- z := new(Int)
- for i, test := range stringTests {
- if !test.ok {
- continue
- }
- z.SetInt64(test.val)
-
- if test.base == 10 {
- s := z.String()
- if s != test.out {
- t.Errorf("#%da got %s; want %s", i, s, test.out)
- }
- }
-
- s := fmt.Sprintf(format(test.base), z)
- if s != test.out {
- t.Errorf("#%db got %s; want %s", i, s, test.out)
- }
- }
-}
-
-func TestSetString(t *testing.T) {
- tmp := new(Int)
- for i, test := range stringTests {
- // initialize to a non-zero value so that issues with parsing
- // 0 are detected
- tmp.SetInt64(1234567890)
- n1, ok1 := new(Int).SetString(test.in, test.base)
- n2, ok2 := tmp.SetString(test.in, test.base)
- expected := NewInt(test.val)
- if ok1 != test.ok || ok2 != test.ok {
- t.Errorf("#%d (input '%s') ok incorrect (should be %t)", i, test.in, test.ok)
- continue
- }
- if !ok1 {
- if n1 != nil {
- t.Errorf("#%d (input '%s') n1 != nil", i, test.in)
- }
- continue
- }
- if !ok2 {
- if n2 != nil {
- t.Errorf("#%d (input '%s') n2 != nil", i, test.in)
- }
- continue
- }
-
- if ok1 && !isNormalized(n1) {
- t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n1)
- }
- if ok2 && !isNormalized(n2) {
- t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n2)
- }
-
- if n1.Cmp(expected) != 0 {
- t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n1, test.val)
- }
- if n2.Cmp(expected) != 0 {
- t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n2, test.val)
- }
- }
-}
-
-var formatTests = []struct {
- input string
- format string
- output string
-}{
- {"<nil>", "%x", "<nil>"},
- {"<nil>", "%#x", "<nil>"},
- {"<nil>", "%#y", "%!y(big.Int=<nil>)"},
-
- {"10", "%b", "1010"},
- {"10", "%o", "12"},
- {"10", "%d", "10"},
- {"10", "%v", "10"},
- {"10", "%x", "a"},
- {"10", "%X", "A"},
- {"-10", "%X", "-A"},
- {"10", "%y", "%!y(big.Int=10)"},
- {"-10", "%y", "%!y(big.Int=-10)"},
-
- {"10", "%#b", "1010"},
- {"10", "%#o", "012"},
- {"10", "%#d", "10"},
- {"10", "%#v", "10"},
- {"10", "%#x", "0xa"},
- {"10", "%#X", "0XA"},
- {"-10", "%#X", "-0XA"},
- {"10", "%#y", "%!y(big.Int=10)"},
- {"-10", "%#y", "%!y(big.Int=-10)"},
-
- {"1234", "%d", "1234"},
- {"1234", "%3d", "1234"},
- {"1234", "%4d", "1234"},
- {"-1234", "%d", "-1234"},
- {"1234", "% 5d", " 1234"},
- {"1234", "%+5d", "+1234"},
- {"1234", "%-5d", "1234 "},
- {"1234", "%x", "4d2"},
- {"1234", "%X", "4D2"},
- {"-1234", "%3x", "-4d2"},
- {"-1234", "%4x", "-4d2"},
- {"-1234", "%5x", " -4d2"},
- {"-1234", "%-5x", "-4d2 "},
- {"1234", "%03d", "1234"},
- {"1234", "%04d", "1234"},
- {"1234", "%05d", "01234"},
- {"1234", "%06d", "001234"},
- {"-1234", "%06d", "-01234"},
- {"1234", "%+06d", "+01234"},
- {"1234", "% 06d", " 01234"},
- {"1234", "%-6d", "1234 "},
- {"1234", "%-06d", "1234 "},
- {"-1234", "%-06d", "-1234 "},
-
- {"1234", "%.3d", "1234"},
- {"1234", "%.4d", "1234"},
- {"1234", "%.5d", "01234"},
- {"1234", "%.6d", "001234"},
- {"-1234", "%.3d", "-1234"},
- {"-1234", "%.4d", "-1234"},
- {"-1234", "%.5d", "-01234"},
- {"-1234", "%.6d", "-001234"},
-
- {"1234", "%8.3d", " 1234"},
- {"1234", "%8.4d", " 1234"},
- {"1234", "%8.5d", " 01234"},
- {"1234", "%8.6d", " 001234"},
- {"-1234", "%8.3d", " -1234"},
- {"-1234", "%8.4d", " -1234"},
- {"-1234", "%8.5d", " -01234"},
- {"-1234", "%8.6d", " -001234"},
-
- {"1234", "%+8.3d", " +1234"},
- {"1234", "%+8.4d", " +1234"},
- {"1234", "%+8.5d", " +01234"},
- {"1234", "%+8.6d", " +001234"},
- {"-1234", "%+8.3d", " -1234"},
- {"-1234", "%+8.4d", " -1234"},
- {"-1234", "%+8.5d", " -01234"},
- {"-1234", "%+8.6d", " -001234"},
-
- {"1234", "% 8.3d", " 1234"},
- {"1234", "% 8.4d", " 1234"},
- {"1234", "% 8.5d", " 01234"},
- {"1234", "% 8.6d", " 001234"},
- {"-1234", "% 8.3d", " -1234"},
- {"-1234", "% 8.4d", " -1234"},
- {"-1234", "% 8.5d", " -01234"},
- {"-1234", "% 8.6d", " -001234"},
-
- {"1234", "%.3x", "4d2"},
- {"1234", "%.4x", "04d2"},
- {"1234", "%.5x", "004d2"},
- {"1234", "%.6x", "0004d2"},
- {"-1234", "%.3x", "-4d2"},
- {"-1234", "%.4x", "-04d2"},
- {"-1234", "%.5x", "-004d2"},
- {"-1234", "%.6x", "-0004d2"},
-
- {"1234", "%8.3x", " 4d2"},
- {"1234", "%8.4x", " 04d2"},
- {"1234", "%8.5x", " 004d2"},
- {"1234", "%8.6x", " 0004d2"},
- {"-1234", "%8.3x", " -4d2"},
- {"-1234", "%8.4x", " -04d2"},
- {"-1234", "%8.5x", " -004d2"},
- {"-1234", "%8.6x", " -0004d2"},
-
- {"1234", "%+8.3x", " +4d2"},
- {"1234", "%+8.4x", " +04d2"},
- {"1234", "%+8.5x", " +004d2"},
- {"1234", "%+8.6x", " +0004d2"},
- {"-1234", "%+8.3x", " -4d2"},
- {"-1234", "%+8.4x", " -04d2"},
- {"-1234", "%+8.5x", " -004d2"},
- {"-1234", "%+8.6x", " -0004d2"},
-
- {"1234", "% 8.3x", " 4d2"},
- {"1234", "% 8.4x", " 04d2"},
- {"1234", "% 8.5x", " 004d2"},
- {"1234", "% 8.6x", " 0004d2"},
- {"1234", "% 8.7x", " 00004d2"},
- {"1234", "% 8.8x", " 000004d2"},
- {"-1234", "% 8.3x", " -4d2"},
- {"-1234", "% 8.4x", " -04d2"},
- {"-1234", "% 8.5x", " -004d2"},
- {"-1234", "% 8.6x", " -0004d2"},
- {"-1234", "% 8.7x", "-00004d2"},
- {"-1234", "% 8.8x", "-000004d2"},
-
- {"1234", "%-8.3d", "1234 "},
- {"1234", "%-8.4d", "1234 "},
- {"1234", "%-8.5d", "01234 "},
- {"1234", "%-8.6d", "001234 "},
- {"1234", "%-8.7d", "0001234 "},
- {"1234", "%-8.8d", "00001234"},
- {"-1234", "%-8.3d", "-1234 "},
- {"-1234", "%-8.4d", "-1234 "},
- {"-1234", "%-8.5d", "-01234 "},
- {"-1234", "%-8.6d", "-001234 "},
- {"-1234", "%-8.7d", "-0001234"},
- {"-1234", "%-8.8d", "-00001234"},
-
- {"16777215", "%b", "111111111111111111111111"}, // 2**24 - 1
-
- {"0", "%.d", ""},
- {"0", "%.0d", ""},
- {"0", "%3.d", ""},
-}
-
-func TestFormat(t *testing.T) {
- for i, test := range formatTests {
- var x *Int
- if test.input != "<nil>" {
- var ok bool
- x, ok = new(Int).SetString(test.input, 0)
- if !ok {
- t.Errorf("#%d failed reading input %s", i, test.input)
- }
- }
- output := fmt.Sprintf(test.format, x)
- if output != test.output {
- t.Errorf("#%d got %q; want %q, {%q, %q, %q}", i, output, test.output, test.input, test.format, test.output)
- }
- }
-}
-
-var scanTests = []struct {
- input string
- format string
- output string
- remaining int
-}{
- {"1010", "%b", "10", 0},
- {"0b1010", "%v", "10", 0},
- {"12", "%o", "10", 0},
- {"012", "%v", "10", 0},
- {"10", "%d", "10", 0},
- {"10", "%v", "10", 0},
- {"a", "%x", "10", 0},
- {"0xa", "%v", "10", 0},
- {"A", "%X", "10", 0},
- {"-A", "%X", "-10", 0},
- {"+0b1011001", "%v", "89", 0},
- {"0xA", "%v", "10", 0},
- {"0 ", "%v", "0", 1},
- {"2+3", "%v", "2", 2},
- {"0XABC 12", "%v", "2748", 3},
-}
-
-func TestScan(t *testing.T) {
- var buf bytes.Buffer
- for i, test := range scanTests {
- x := new(Int)
- buf.Reset()
- buf.WriteString(test.input)
- if _, err := fmt.Fscanf(&buf, test.format, x); err != nil {
- t.Errorf("#%d error: %s", i, err)
- }
- if x.String() != test.output {
- t.Errorf("#%d got %s; want %s", i, x.String(), test.output)
- }
- if buf.Len() != test.remaining {
- t.Errorf("#%d got %d bytes remaining; want %d", i, buf.Len(), test.remaining)
- }
- }
-}
-
// Examples from the Go Language Spec, section "Arithmetic operators"
var divisionSignsTests = []struct {
x, y int64
}
}
+var bitsTests = []nat{
+ nil,
+ {0},
+ {1},
+ {0, 1, 2, 3, 4},
+ {4, 3, 2, 1, 0},
+ {4, 3, 2, 1, 0, 0, 0, 0},
+}
+
+func norm(x nat) nat {
+ i := len(x)
+ for i > 0 && x[i-1] == 0 {
+ i--
+ }
+ return x[:i]
+}
+
+func TestBits(t *testing.T) {
+ for _, test := range bitsTests {
+ var z Int
+ z.neg = true
+ got := z.SetBits(test)
+ want := norm(test)
+ if got.abs.cmp(want) != 0 {
+ t.Errorf("SetBits(%v) = %v; want %v", test, got.abs, want)
+ }
+
+ if got.neg {
+ t.Errorf("SetBits(%v): got negative result")
+ }
+
+ bits := nat(z.Bits())
+ if bits.cmp(want) != 0 {
+ t.Errorf("%v.Bits() = %v; want %v", z.abs, bits, want)
+ }
+ }
+}
+
func checkSetBytes(b []byte) bool {
hex1 := hex.EncodeToString(new(Int).SetBytes(b).Bytes())
hex2 := hex.EncodeToString(b)
}
var composites = []string{
+ "0",
+ "1",
"21284175091214687912771199898307297748211672914763848041968395774954376176754",
"6084766654921918907427900243509372380954290099172559290432744450051395395951",
"84594350493221918389213352992032324280367711247940675652888030554255915464401",
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements int-to-string conversion functions.
+
+package big
+
+import (
+ "errors"
+ "fmt"
+ "io"
+)
+
+func (x *Int) String() string {
+ switch {
+ case x == nil:
+ return "<nil>"
+ case x.neg:
+ return "-" + x.abs.decimalString()
+ }
+ return x.abs.decimalString()
+}
+
+func charset(ch rune) string {
+ switch ch {
+ case 'b':
+ return lowercaseDigits[0:2]
+ case 'o':
+ return lowercaseDigits[0:8]
+ case 'd', 's', 'v':
+ return lowercaseDigits[0:10]
+ case 'x':
+ return lowercaseDigits[0:16]
+ case 'X':
+ return uppercaseDigits[0:16]
+ }
+ return "" // unknown format
+}
+
+// write count copies of text to s
+func writeMultiple(s fmt.State, text string, count int) {
+ if len(text) > 0 {
+ b := []byte(text)
+ for ; count > 0; count-- {
+ s.Write(b)
+ }
+ }
+}
+
+// Format is a support routine for fmt.Formatter. It accepts
+// the formats 'b' (binary), 'o' (octal), 'd' (decimal), 'x'
+// (lowercase hexadecimal), and 'X' (uppercase hexadecimal).
+// Also supported are the full suite of package fmt's format
+// verbs for integral types, including '+', '-', and ' '
+// for sign control, '#' for leading zero in octal and for
+// hexadecimal, a leading "0x" or "0X" for "%#x" and "%#X"
+// respectively, specification of minimum digits precision,
+// output field width, space or zero padding, and left or
+// right justification.
+//
+func (x *Int) Format(s fmt.State, ch rune) {
+ cs := charset(ch)
+
+ // special cases
+ switch {
+ case cs == "":
+ // unknown format
+ fmt.Fprintf(s, "%%!%c(big.Int=%s)", ch, x.String())
+ return
+ case x == nil:
+ fmt.Fprint(s, "<nil>")
+ return
+ }
+
+ // determine sign character
+ sign := ""
+ switch {
+ case x.neg:
+ sign = "-"
+ case s.Flag('+'): // supersedes ' ' when both specified
+ sign = "+"
+ case s.Flag(' '):
+ sign = " "
+ }
+
+ // determine prefix characters for indicating output base
+ prefix := ""
+ if s.Flag('#') {
+ switch ch {
+ case 'o': // octal
+ prefix = "0"
+ case 'x': // hexadecimal
+ prefix = "0x"
+ case 'X':
+ prefix = "0X"
+ }
+ }
+
+ // determine digits with base set by len(cs) and digit characters from cs
+ digits := x.abs.string(cs)
+
+ // number of characters for the three classes of number padding
+ var left int // space characters to left of digits for right justification ("%8d")
+ var zeroes int // zero characters (actually cs[0]) as left-most digits ("%.8d")
+ var right int // space characters to right of digits for left justification ("%-8d")
+
+ // determine number padding from precision: the least number of digits to output
+ precision, precisionSet := s.Precision()
+ if precisionSet {
+ switch {
+ case len(digits) < precision:
+ zeroes = precision - len(digits) // count of zero padding
+ case digits == "0" && precision == 0:
+ return // print nothing if zero value (x == 0) and zero precision ("." or ".0")
+ }
+ }
+
+ // determine field pad from width: the least number of characters to output
+ length := len(sign) + len(prefix) + zeroes + len(digits)
+ if width, widthSet := s.Width(); widthSet && length < width { // pad as specified
+ switch d := width - length; {
+ case s.Flag('-'):
+ // pad on the right with spaces; supersedes '0' when both specified
+ right = d
+ case s.Flag('0') && !precisionSet:
+ // pad with zeroes unless precision also specified
+ zeroes = d
+ default:
+ // pad on the left with spaces
+ left = d
+ }
+ }
+
+ // print number as [left pad][sign][prefix][zero pad][digits][right pad]
+ writeMultiple(s, " ", left)
+ writeMultiple(s, sign, 1)
+ writeMultiple(s, prefix, 1)
+ writeMultiple(s, "0", zeroes)
+ writeMultiple(s, digits, 1)
+ writeMultiple(s, " ", right)
+}
+
+// scan sets z to the integer value corresponding to the longest possible prefix
+// read from r representing a signed integer number in a given conversion base.
+// It returns z, the actual conversion base used, and an error, if any. In the
+// error case, the value of z is undefined but the returned value is nil. The
+// syntax follows the syntax of integer literals in Go.
+//
+// The base argument must be 0 or a value from 2 through MaxBase. If the base
+// is 0, the string prefix determines the actual conversion base. A prefix of
+// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a
+// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
+//
+func (z *Int) scan(r io.ByteScanner, base int) (*Int, int, error) {
+ // determine sign
+ neg, err := scanSign(r)
+ if err != nil {
+ return nil, 0, err
+ }
+
+ // determine mantissa
+ z.abs, base, _, err = z.abs.scan(r, base, false)
+ if err != nil {
+ return nil, base, err
+ }
+ z.neg = len(z.abs) > 0 && neg // 0 has no sign
+
+ return z, base, nil
+}
+
+func scanSign(r io.ByteScanner) (neg bool, err error) {
+ var ch byte
+ if ch, err = r.ReadByte(); err != nil {
+ return false, err
+ }
+ switch ch {
+ case '-':
+ neg = true
+ case '+':
+ // nothing to do
+ default:
+ r.UnreadByte()
+ }
+ return
+}
+
+// byteReader is a local wrapper around fmt.ScanState;
+// it implements the ByteReader interface.
+type byteReader struct {
+ fmt.ScanState
+}
+
+func (r byteReader) ReadByte() (byte, error) {
+ ch, size, err := r.ReadRune()
+ if size != 1 && err == nil {
+ err = fmt.Errorf("invalid rune %#U", ch)
+ }
+ return byte(ch), err
+}
+
+func (r byteReader) UnreadByte() error {
+ return r.UnreadRune()
+}
+
+// Scan is a support routine for fmt.Scanner; it sets z to the value of
+// the scanned number. It accepts the formats 'b' (binary), 'o' (octal),
+// 'd' (decimal), 'x' (lowercase hexadecimal), and 'X' (uppercase hexadecimal).
+func (z *Int) Scan(s fmt.ScanState, ch rune) error {
+ s.SkipSpace() // skip leading space characters
+ base := 0
+ switch ch {
+ case 'b':
+ base = 2
+ case 'o':
+ base = 8
+ case 'd':
+ base = 10
+ case 'x', 'X':
+ base = 16
+ case 's', 'v':
+ // let scan determine the base
+ default:
+ return errors.New("Int.Scan: invalid verb")
+ }
+ _, _, err := z.scan(byteReader{s}, base)
+ return err
+}
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package big
+
+import (
+ "bytes"
+ "fmt"
+ "testing"
+)
+
+var stringTests = []struct {
+ in string
+ out string
+ base int
+ val int64
+ ok bool
+}{
+ {in: "", ok: false},
+ {in: "a", ok: false},
+ {in: "z", ok: false},
+ {in: "+", ok: false},
+ {in: "-", ok: false},
+ {in: "0b", ok: false},
+ {in: "0x", ok: false},
+ {in: "2", base: 2, ok: false},
+ {in: "0b2", base: 0, ok: false},
+ {in: "08", ok: false},
+ {in: "8", base: 8, ok: false},
+ {in: "0xg", base: 0, ok: false},
+ {in: "g", base: 16, ok: false},
+ {"0", "0", 0, 0, true},
+ {"0", "0", 10, 0, true},
+ {"0", "0", 16, 0, true},
+ {"+0", "0", 0, 0, true},
+ {"-0", "0", 0, 0, true},
+ {"10", "10", 0, 10, true},
+ {"10", "10", 10, 10, true},
+ {"10", "10", 16, 16, true},
+ {"-10", "-10", 16, -16, true},
+ {"+10", "10", 16, 16, true},
+ {"0x10", "16", 0, 16, true},
+ {in: "0x10", base: 16, ok: false},
+ {"-0x10", "-16", 0, -16, true},
+ {"+0x10", "16", 0, 16, true},
+ {"00", "0", 0, 0, true},
+ {"0", "0", 8, 0, true},
+ {"07", "7", 0, 7, true},
+ {"7", "7", 8, 7, true},
+ {"023", "19", 0, 19, true},
+ {"23", "23", 8, 19, true},
+ {"cafebabe", "cafebabe", 16, 0xcafebabe, true},
+ {"0b0", "0", 0, 0, true},
+ {"-111", "-111", 2, -7, true},
+ {"-0b111", "-7", 0, -7, true},
+ {"0b1001010111", "599", 0, 0x257, true},
+ {"1001010111", "1001010111", 2, 0x257, true},
+}
+
+func format(base int) string {
+ switch base {
+ case 2:
+ return "%b"
+ case 8:
+ return "%o"
+ case 16:
+ return "%x"
+ }
+ return "%d"
+}
+
+func TestGetString(t *testing.T) {
+ z := new(Int)
+ for i, test := range stringTests {
+ if !test.ok {
+ continue
+ }
+ z.SetInt64(test.val)
+
+ if test.base == 10 {
+ s := z.String()
+ if s != test.out {
+ t.Errorf("#%da got %s; want %s", i, s, test.out)
+ }
+ }
+
+ s := fmt.Sprintf(format(test.base), z)
+ if s != test.out {
+ t.Errorf("#%db got %s; want %s", i, s, test.out)
+ }
+ }
+}
+
+func TestSetString(t *testing.T) {
+ tmp := new(Int)
+ for i, test := range stringTests {
+ // initialize to a non-zero value so that issues with parsing
+ // 0 are detected
+ tmp.SetInt64(1234567890)
+ n1, ok1 := new(Int).SetString(test.in, test.base)
+ n2, ok2 := tmp.SetString(test.in, test.base)
+ expected := NewInt(test.val)
+ if ok1 != test.ok || ok2 != test.ok {
+ t.Errorf("#%d (input '%s') ok incorrect (should be %t)", i, test.in, test.ok)
+ continue
+ }
+ if !ok1 {
+ if n1 != nil {
+ t.Errorf("#%d (input '%s') n1 != nil", i, test.in)
+ }
+ continue
+ }
+ if !ok2 {
+ if n2 != nil {
+ t.Errorf("#%d (input '%s') n2 != nil", i, test.in)
+ }
+ continue
+ }
+
+ if ok1 && !isNormalized(n1) {
+ t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n1)
+ }
+ if ok2 && !isNormalized(n2) {
+ t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n2)
+ }
+
+ if n1.Cmp(expected) != 0 {
+ t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n1, test.val)
+ }
+ if n2.Cmp(expected) != 0 {
+ t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n2, test.val)
+ }
+ }
+}
+
+var formatTests = []struct {
+ input string
+ format string
+ output string
+}{
+ {"<nil>", "%x", "<nil>"},
+ {"<nil>", "%#x", "<nil>"},
+ {"<nil>", "%#y", "%!y(big.Int=<nil>)"},
+
+ {"10", "%b", "1010"},
+ {"10", "%o", "12"},
+ {"10", "%d", "10"},
+ {"10", "%v", "10"},
+ {"10", "%x", "a"},
+ {"10", "%X", "A"},
+ {"-10", "%X", "-A"},
+ {"10", "%y", "%!y(big.Int=10)"},
+ {"-10", "%y", "%!y(big.Int=-10)"},
+
+ {"10", "%#b", "1010"},
+ {"10", "%#o", "012"},
+ {"10", "%#d", "10"},
+ {"10", "%#v", "10"},
+ {"10", "%#x", "0xa"},
+ {"10", "%#X", "0XA"},
+ {"-10", "%#X", "-0XA"},
+ {"10", "%#y", "%!y(big.Int=10)"},
+ {"-10", "%#y", "%!y(big.Int=-10)"},
+
+ {"1234", "%d", "1234"},
+ {"1234", "%3d", "1234"},
+ {"1234", "%4d", "1234"},
+ {"-1234", "%d", "-1234"},
+ {"1234", "% 5d", " 1234"},
+ {"1234", "%+5d", "+1234"},
+ {"1234", "%-5d", "1234 "},
+ {"1234", "%x", "4d2"},
+ {"1234", "%X", "4D2"},
+ {"-1234", "%3x", "-4d2"},
+ {"-1234", "%4x", "-4d2"},
+ {"-1234", "%5x", " -4d2"},
+ {"-1234", "%-5x", "-4d2 "},
+ {"1234", "%03d", "1234"},
+ {"1234", "%04d", "1234"},
+ {"1234", "%05d", "01234"},
+ {"1234", "%06d", "001234"},
+ {"-1234", "%06d", "-01234"},
+ {"1234", "%+06d", "+01234"},
+ {"1234", "% 06d", " 01234"},
+ {"1234", "%-6d", "1234 "},
+ {"1234", "%-06d", "1234 "},
+ {"-1234", "%-06d", "-1234 "},
+
+ {"1234", "%.3d", "1234"},
+ {"1234", "%.4d", "1234"},
+ {"1234", "%.5d", "01234"},
+ {"1234", "%.6d", "001234"},
+ {"-1234", "%.3d", "-1234"},
+ {"-1234", "%.4d", "-1234"},
+ {"-1234", "%.5d", "-01234"},
+ {"-1234", "%.6d", "-001234"},
+
+ {"1234", "%8.3d", " 1234"},
+ {"1234", "%8.4d", " 1234"},
+ {"1234", "%8.5d", " 01234"},
+ {"1234", "%8.6d", " 001234"},
+ {"-1234", "%8.3d", " -1234"},
+ {"-1234", "%8.4d", " -1234"},
+ {"-1234", "%8.5d", " -01234"},
+ {"-1234", "%8.6d", " -001234"},
+
+ {"1234", "%+8.3d", " +1234"},
+ {"1234", "%+8.4d", " +1234"},
+ {"1234", "%+8.5d", " +01234"},
+ {"1234", "%+8.6d", " +001234"},
+ {"-1234", "%+8.3d", " -1234"},
+ {"-1234", "%+8.4d", " -1234"},
+ {"-1234", "%+8.5d", " -01234"},
+ {"-1234", "%+8.6d", " -001234"},
+
+ {"1234", "% 8.3d", " 1234"},
+ {"1234", "% 8.4d", " 1234"},
+ {"1234", "% 8.5d", " 01234"},
+ {"1234", "% 8.6d", " 001234"},
+ {"-1234", "% 8.3d", " -1234"},
+ {"-1234", "% 8.4d", " -1234"},
+ {"-1234", "% 8.5d", " -01234"},
+ {"-1234", "% 8.6d", " -001234"},
+
+ {"1234", "%.3x", "4d2"},
+ {"1234", "%.4x", "04d2"},
+ {"1234", "%.5x", "004d2"},
+ {"1234", "%.6x", "0004d2"},
+ {"-1234", "%.3x", "-4d2"},
+ {"-1234", "%.4x", "-04d2"},
+ {"-1234", "%.5x", "-004d2"},
+ {"-1234", "%.6x", "-0004d2"},
+
+ {"1234", "%8.3x", " 4d2"},
+ {"1234", "%8.4x", " 04d2"},
+ {"1234", "%8.5x", " 004d2"},
+ {"1234", "%8.6x", " 0004d2"},
+ {"-1234", "%8.3x", " -4d2"},
+ {"-1234", "%8.4x", " -04d2"},
+ {"-1234", "%8.5x", " -004d2"},
+ {"-1234", "%8.6x", " -0004d2"},
+
+ {"1234", "%+8.3x", " +4d2"},
+ {"1234", "%+8.4x", " +04d2"},
+ {"1234", "%+8.5x", " +004d2"},
+ {"1234", "%+8.6x", " +0004d2"},
+ {"-1234", "%+8.3x", " -4d2"},
+ {"-1234", "%+8.4x", " -04d2"},
+ {"-1234", "%+8.5x", " -004d2"},
+ {"-1234", "%+8.6x", " -0004d2"},
+
+ {"1234", "% 8.3x", " 4d2"},
+ {"1234", "% 8.4x", " 04d2"},
+ {"1234", "% 8.5x", " 004d2"},
+ {"1234", "% 8.6x", " 0004d2"},
+ {"1234", "% 8.7x", " 00004d2"},
+ {"1234", "% 8.8x", " 000004d2"},
+ {"-1234", "% 8.3x", " -4d2"},
+ {"-1234", "% 8.4x", " -04d2"},
+ {"-1234", "% 8.5x", " -004d2"},
+ {"-1234", "% 8.6x", " -0004d2"},
+ {"-1234", "% 8.7x", "-00004d2"},
+ {"-1234", "% 8.8x", "-000004d2"},
+
+ {"1234", "%-8.3d", "1234 "},
+ {"1234", "%-8.4d", "1234 "},
+ {"1234", "%-8.5d", "01234 "},
+ {"1234", "%-8.6d", "001234 "},
+ {"1234", "%-8.7d", "0001234 "},
+ {"1234", "%-8.8d", "00001234"},
+ {"-1234", "%-8.3d", "-1234 "},
+ {"-1234", "%-8.4d", "-1234 "},
+ {"-1234", "%-8.5d", "-01234 "},
+ {"-1234", "%-8.6d", "-001234 "},
+ {"-1234", "%-8.7d", "-0001234"},
+ {"-1234", "%-8.8d", "-00001234"},
+
+ {"16777215", "%b", "111111111111111111111111"}, // 2**24 - 1
+
+ {"0", "%.d", ""},
+ {"0", "%.0d", ""},
+ {"0", "%3.d", ""},
+}
+
+func TestFormat(t *testing.T) {
+ for i, test := range formatTests {
+ var x *Int
+ if test.input != "<nil>" {
+ var ok bool
+ x, ok = new(Int).SetString(test.input, 0)
+ if !ok {
+ t.Errorf("#%d failed reading input %s", i, test.input)
+ }
+ }
+ output := fmt.Sprintf(test.format, x)
+ if output != test.output {
+ t.Errorf("#%d got %q; want %q, {%q, %q, %q}", i, output, test.output, test.input, test.format, test.output)
+ }
+ }
+}
+
+var scanTests = []struct {
+ input string
+ format string
+ output string
+ remaining int
+}{
+ {"1010", "%b", "10", 0},
+ {"0b1010", "%v", "10", 0},
+ {"12", "%o", "10", 0},
+ {"012", "%v", "10", 0},
+ {"10", "%d", "10", 0},
+ {"10", "%v", "10", 0},
+ {"a", "%x", "10", 0},
+ {"0xa", "%v", "10", 0},
+ {"A", "%X", "10", 0},
+ {"-A", "%X", "-10", 0},
+ {"+0b1011001", "%v", "89", 0},
+ {"0xA", "%v", "10", 0},
+ {"0 ", "%v", "0", 1},
+ {"2+3", "%v", "2", 2},
+ {"0XABC 12", "%v", "2748", 3},
+}
+
+func TestScan(t *testing.T) {
+ var buf bytes.Buffer
+ for i, test := range scanTests {
+ x := new(Int)
+ buf.Reset()
+ buf.WriteString(test.input)
+ if _, err := fmt.Fscanf(&buf, test.format, x); err != nil {
+ t.Errorf("#%d error: %s", i, err)
+ }
+ if x.String() != test.output {
+ t.Errorf("#%d got %s; want %s", i, x.String(), test.output)
+ }
+ if buf.Len() != test.remaining {
+ t.Errorf("#%d got %d bytes remaining; want %d", i, buf.Len(), test.remaining)
+ }
+ }
+}
// Package big implements multi-precision arithmetic (big numbers).
// The following numeric types are supported:
//
-// - Int signed integers
-// - Rat rational numbers
+// Int signed integers
+// Rat rational numbers
+// Float floating-point numbers
//
// Methods are typically of the form:
//
-// func (z *Int) Op(x, y *Int) *Int (similar for *Rat)
+// func (z *T) Unary(x *T) *T // z = op x
+// func (z *T) Binary(x, y *T) *T // z = x op y
+// func (x *T) M() T1 // v = x.M()
//
-// and implement operations z = x Op y with the result as receiver; if it
-// is one of the operands it may be overwritten (and its memory reused).
+// with T one of Int, Rat, or Float. For unary and binary operations, the
+// result is the receiver (usually named z in that case); if it is one of
+// the operands x or y it may be overwritten (and its memory reused).
// To enable chaining of operations, the result is also returned. Methods
-// returning a result other than *Int or *Rat take one of the operands as
-// the receiver.
+// returning a result other than *Int, *Rat, or *Float take an operand as
+// the receiver (usually named x in that case).
//
package big
// These are the building blocks for the operations on signed integers
// and rationals.
-import (
- "errors"
- "io"
- "math"
- "math/rand"
- "sync"
-)
+import "math/rand"
// An unsigned integer x of the form
//
func (z nat) make(n int) nat {
if n <= cap(z) {
- return z[0:n] // reuse z
+ return z[:n] // reuse z
}
// Choosing a good value for e has significant performance impact
// because it increases the chance that a value can be reused.
func (z nat) setWord(x Word) nat {
if x == 0 {
- return z.make(0)
+ return z[:0]
}
z = z.make(1)
z[0] = x
return z.add(y, x)
case m == 0:
// n == 0 because m >= n; result is 0
- return z.make(0)
+ return z[:0]
case n == 0:
// result is x
return z.set(x)
panic("underflow")
case m == 0:
// n == 0 because m >= n; result is 0
- return z.make(0)
+ return z[:0]
case n == 0:
// result is x
return z.set(x)
case m < n:
return z.mul(y, x)
case m == 0 || n == 0:
- return z.make(0)
+ return z[:0]
case n == 1:
return z.mulAddWW(x, y[0], 0)
}
q = z.set(x) // result is x
return
case m == 0:
- q = z.make(0) // result is 0
+ q = z[:0] // result is 0
return
}
// m > 0
}
if u.cmp(v) < 0 {
- q = z.make(0)
+ q = z[:0]
r = z2.set(u)
return
}
u = nil // u is an alias for uIn or v - cannot reuse
}
u = u.make(len(uIn) + 1)
- u.clear()
+ u.clear() // TODO(gri) no need to clear if we allocated a new u
// D1.
shift := leadingZeros(v[n-1])
return 0
}
-// MaxBase is the largest number base accepted for string conversions.
-const MaxBase = 'z' - 'a' + 10 + 1 // = hexValue('z') + 1
-
-func hexValue(ch rune) Word {
- d := int(MaxBase + 1) // illegal base
- switch {
- case '0' <= ch && ch <= '9':
- d = int(ch - '0')
- case 'a' <= ch && ch <= 'z':
- d = int(ch - 'a' + 10)
- case 'A' <= ch && ch <= 'Z':
- d = int(ch - 'A' + 10)
- }
- return Word(d)
-}
-
-// scan sets z to the natural number corresponding to the longest possible prefix
-// read from r representing an unsigned integer in a given conversion base.
-// It returns z, the actual conversion base used, and an error, if any. In the
-// error case, the value of z is undefined. The syntax follows the syntax of
-// unsigned integer literals in Go.
-//
-// The base argument must be 0 or a value from 2 through MaxBase. If the base
-// is 0, the string prefix determines the actual conversion base. A prefix of
-// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a
-// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
-//
-func (z nat) scan(r io.RuneScanner, base int) (nat, int, error) {
- // reject illegal bases
- if base < 0 || base == 1 || MaxBase < base {
- return z, 0, errors.New("illegal number base")
- }
-
- // one char look-ahead
- ch, _, err := r.ReadRune()
- if err != nil {
- return z, 0, err
- }
-
- // determine base if necessary
- b := Word(base)
- if base == 0 {
- b = 10
- if ch == '0' {
- switch ch, _, err = r.ReadRune(); err {
- case nil:
- b = 8
- switch ch {
- case 'x', 'X':
- b = 16
- case 'b', 'B':
- b = 2
- }
- if b == 2 || b == 16 {
- if ch, _, err = r.ReadRune(); err != nil {
- return z, 0, err
- }
- }
- case io.EOF:
- return z.make(0), 10, nil
- default:
- return z, 10, err
- }
- }
- }
-
- // convert string
- // - group as many digits d as possible together into a "super-digit" dd with "super-base" bb
- // - only when bb does not fit into a word anymore, do a full number mulAddWW using bb and dd
- z = z.make(0)
- bb := Word(1)
- dd := Word(0)
- for max := _M / b; ; {
- d := hexValue(ch)
- if d >= b {
- r.UnreadRune() // ch does not belong to number anymore
- break
- }
-
- if bb <= max {
- bb *= b
- dd = dd*b + d
- } else {
- // bb * b would overflow
- z = z.mulAddWW(z, bb, dd)
- bb = b
- dd = d
- }
-
- if ch, _, err = r.ReadRune(); err != nil {
- if err != io.EOF {
- return z, int(b), err
- }
- break
- }
- }
-
- switch {
- case bb > 1:
- // there was at least one mantissa digit
- z = z.mulAddWW(z, bb, dd)
- case base == 0 && b == 8:
- // there was only the octal prefix 0 (possibly followed by digits > 7);
- // return base 10, not 8
- return z, 10, nil
- case base != 0 || b != 8:
- // there was neither a mantissa digit nor the octal prefix 0
- return z, int(b), errors.New("syntax error scanning number")
- }
-
- return z.norm(), int(b), nil
-}
-
-// Character sets for string conversion.
-const (
- lowercaseDigits = "0123456789abcdefghijklmnopqrstuvwxyz"
- uppercaseDigits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-)
-
-// decimalString returns a decimal representation of x.
-// It calls x.string with the charset "0123456789".
-func (x nat) decimalString() string {
- return x.string(lowercaseDigits[0:10])
-}
-
-// string converts x to a string using digits from a charset; a digit with
-// value d is represented by charset[d]. The conversion base is determined
-// by len(charset), which must be >= 2 and <= 256.
-func (x nat) string(charset string) string {
- b := Word(len(charset))
-
- // special cases
- switch {
- case b < 2 || MaxBase > 256:
- panic("illegal base")
- case len(x) == 0:
- return string(charset[0])
- }
-
- // allocate buffer for conversion
- i := int(float64(x.bitLen())/math.Log2(float64(b))) + 1 // off by one at most
- s := make([]byte, i)
-
- // convert power of two and non power of two bases separately
- if b == b&-b {
- // shift is base-b digit size in bits
- shift := trailingZeroBits(b) // shift > 0 because b >= 2
- mask := Word(1)<<shift - 1
- w := x[0]
- nbits := uint(_W) // number of unprocessed bits in w
-
- // convert less-significant words
- for k := 1; k < len(x); k++ {
- // convert full digits
- for nbits >= shift {
- i--
- s[i] = charset[w&mask]
- w >>= shift
- nbits -= shift
- }
-
- // convert any partial leading digit and advance to next word
- if nbits == 0 {
- // no partial digit remaining, just advance
- w = x[k]
- nbits = _W
- } else {
- // partial digit in current (k-1) and next (k) word
- w |= x[k] << nbits
- i--
- s[i] = charset[w&mask]
-
- // advance
- w = x[k] >> (shift - nbits)
- nbits = _W - (shift - nbits)
- }
- }
-
- // convert digits of most-significant word (omit leading zeros)
- for nbits >= 0 && w != 0 {
- i--
- s[i] = charset[w&mask]
- w >>= shift
- nbits -= shift
- }
-
- } else {
- // determine "big base"; i.e., the largest possible value bb
- // that is a power of base b and still fits into a Word
- // (as in 10^19 for 19 decimal digits in a 64bit Word)
- bb := b // big base is b**ndigits
- ndigits := 1 // number of base b digits
- for max := Word(_M / b); bb <= max; bb *= b {
- ndigits++ // maximize ndigits where bb = b**ndigits, bb <= _M
- }
-
- // construct table of successive squares of bb*leafSize to use in subdivisions
- // result (table != nil) <=> (len(x) > leafSize > 0)
- table := divisors(len(x), b, ndigits, bb)
-
- // preserve x, create local copy for use by convertWords
- q := nat(nil).set(x)
-
- // convert q to string s in base b
- q.convertWords(s, charset, b, ndigits, bb, table)
-
- // strip leading zeros
- // (x != 0; thus s must contain at least one non-zero digit
- // and the loop will terminate)
- i = 0
- for zero := charset[0]; s[i] == zero; {
- i++
- }
- }
-
- return string(s[i:])
-}
-
-// Convert words of q to base b digits in s. If q is large, it is recursively "split in half"
-// by nat/nat division using tabulated divisors. Otherwise, it is converted iteratively using
-// repeated nat/Word division.
-//
-// The iterative method processes n Words by n divW() calls, each of which visits every Word in the
-// incrementally shortened q for a total of n + (n-1) + (n-2) ... + 2 + 1, or n(n+1)/2 divW()'s.
-// Recursive conversion divides q by its approximate square root, yielding two parts, each half
-// the size of q. Using the iterative method on both halves means 2 * (n/2)(n/2 + 1)/2 divW()'s
-// plus the expensive long div(). Asymptotically, the ratio is favorable at 1/2 the divW()'s, and
-// is made better by splitting the subblocks recursively. Best is to split blocks until one more
-// split would take longer (because of the nat/nat div()) than the twice as many divW()'s of the
-// iterative approach. This threshold is represented by leafSize. Benchmarking of leafSize in the
-// range 2..64 shows that values of 8 and 16 work well, with a 4x speedup at medium lengths and
-// ~30x for 20000 digits. Use nat_test.go's BenchmarkLeafSize tests to optimize leafSize for
-// specific hardware.
-//
-func (q nat) convertWords(s []byte, charset string, b Word, ndigits int, bb Word, table []divisor) {
- // split larger blocks recursively
- if table != nil {
- // len(q) > leafSize > 0
- var r nat
- index := len(table) - 1
- for len(q) > leafSize {
- // find divisor close to sqrt(q) if possible, but in any case < q
- maxLength := q.bitLen() // ~= log2 q, or at of least largest possible q of this bit length
- minLength := maxLength >> 1 // ~= log2 sqrt(q)
- for index > 0 && table[index-1].nbits > minLength {
- index-- // desired
- }
- if table[index].nbits >= maxLength && table[index].bbb.cmp(q) >= 0 {
- index--
- if index < 0 {
- panic("internal inconsistency")
- }
- }
-
- // split q into the two digit number (q'*bbb + r) to form independent subblocks
- q, r = q.div(r, q, table[index].bbb)
-
- // convert subblocks and collect results in s[:h] and s[h:]
- h := len(s) - table[index].ndigits
- r.convertWords(s[h:], charset, b, ndigits, bb, table[0:index])
- s = s[:h] // == q.convertWords(s, charset, b, ndigits, bb, table[0:index+1])
- }
- }
-
- // having split any large blocks now process the remaining (small) block iteratively
- i := len(s)
- var r Word
- if b == 10 {
- // hard-coding for 10 here speeds this up by 1.25x (allows for / and % by constants)
- for len(q) > 0 {
- // extract least significant, base bb "digit"
- q, r = q.divW(q, bb)
- for j := 0; j < ndigits && i > 0; j++ {
- i--
- // avoid % computation since r%10 == r - int(r/10)*10;
- // this appears to be faster for BenchmarkString10000Base10
- // and smaller strings (but a bit slower for larger ones)
- t := r / 10
- s[i] = charset[r-t<<3-t-t] // TODO(gri) replace w/ t*10 once compiler produces better code
- r = t
- }
- }
- } else {
- for len(q) > 0 {
- // extract least significant, base bb "digit"
- q, r = q.divW(q, bb)
- for j := 0; j < ndigits && i > 0; j++ {
- i--
- s[i] = charset[r%b]
- r /= b
- }
- }
- }
-
- // prepend high-order zeroes
- zero := charset[0]
- for i > 0 { // while need more leading zeroes
- i--
- s[i] = zero
- }
-}
-
-// Split blocks greater than leafSize Words (or set to 0 to disable recursive conversion)
-// Benchmark and configure leafSize using: go test -bench="Leaf"
-// 8 and 16 effective on 3.0 GHz Xeon "Clovertown" CPU (128 byte cache lines)
-// 8 and 16 effective on 2.66 GHz Core 2 Duo "Penryn" CPU
-var leafSize int = 8 // number of Word-size binary values treat as a monolithic block
-
-type divisor struct {
- bbb nat // divisor
- nbits int // bit length of divisor (discounting leading zeroes) ~= log2(bbb)
- ndigits int // digit length of divisor in terms of output base digits
-}
-
-var cacheBase10 struct {
- sync.Mutex
- table [64]divisor // cached divisors for base 10
-}
-
-// expWW computes x**y
-func (z nat) expWW(x, y Word) nat {
- return z.expNN(nat(nil).setWord(x), nat(nil).setWord(y), nil)
-}
-
-// construct table of powers of bb*leafSize to use in subdivisions
-func divisors(m int, b Word, ndigits int, bb Word) []divisor {
- // only compute table when recursive conversion is enabled and x is large
- if leafSize == 0 || m <= leafSize {
- return nil
- }
-
- // determine k where (bb**leafSize)**(2**k) >= sqrt(x)
- k := 1
- for words := leafSize; words < m>>1 && k < len(cacheBase10.table); words <<= 1 {
- k++
- }
-
- // reuse and extend existing table of divisors or create new table as appropriate
- var table []divisor // for b == 10, table overlaps with cacheBase10.table
- if b == 10 {
- cacheBase10.Lock()
- table = cacheBase10.table[0:k] // reuse old table for this conversion
- } else {
- table = make([]divisor, k) // create new table for this conversion
- }
-
- // extend table
- if table[k-1].ndigits == 0 {
- // add new entries as needed
- var larger nat
- for i := 0; i < k; i++ {
- if table[i].ndigits == 0 {
- if i == 0 {
- table[0].bbb = nat(nil).expWW(bb, Word(leafSize))
- table[0].ndigits = ndigits * leafSize
- } else {
- table[i].bbb = nat(nil).mul(table[i-1].bbb, table[i-1].bbb)
- table[i].ndigits = 2 * table[i-1].ndigits
- }
-
- // optimization: exploit aggregated extra bits in macro blocks
- larger = nat(nil).set(table[i].bbb)
- for mulAddVWW(larger, larger, b, 0) == 0 {
- table[i].bbb = table[i].bbb.set(larger)
- table[i].ndigits++
- }
-
- table[i].nbits = table[i].bbb.bitLen()
- }
- }
- }
-
- if b == 10 {
- cacheBase10.Unlock()
- }
-
- return table
-}
-
const deBruijn32 = 0x077CB531
var deBruijn32Lookup = []byte{
func (z nat) shl(x nat, s uint) nat {
m := len(x)
if m == 0 {
- return z.make(0)
+ return z[:0]
}
// m > 0
m := len(x)
n := m - int(s/_W)
if n <= 0 {
- return z.make(0)
+ return z[:0]
}
// n > 0
panic("set bit is not 0 or 1")
}
-func (z nat) bit(i uint) uint {
- j := int(i / _W)
- if j >= len(z) {
+// bit returns the value of the i'th bit, with lsb == bit 0.
+func (x nat) bit(i uint) uint {
+ j := i / _W
+ if j >= uint(len(x)) {
return 0
}
- return uint(z[j] >> (i % _W) & 1)
+ // 0 <= j < len(x)
+ return uint(x[j] >> (i % _W) & 1)
+}
+
+// sticky returns 1 if there's a 1 bit within the
+// i least significant bits, otherwise it returns 0.
+func (x nat) sticky(i uint) uint {
+ j := i / _W
+ if j >= uint(len(x)) {
+ if len(x) == 0 {
+ return 0
+ }
+ return 1
+ }
+ // 0 <= j < len(x)
+ for _, x := range x[:j] {
+ if x != 0 {
+ return 1
+ }
+ }
+ if x[j]<<(_W-i%_W) != 0 {
+ return 1
+ }
+ return 0
}
func (z nat) and(x, y nat) nat {
package big
import (
- "io"
"runtime"
"strings"
"testing"
}
func natFromString(s string) nat {
- x, _, err := nat(nil).scan(strings.NewReader(s), 0)
+ x, _, _, err := nat(nil).scan(strings.NewReader(s), 0, false)
if err != nil {
panic(err)
}
}
}
-func toString(x nat, charset string) string {
- base := len(charset)
-
- // special cases
- switch {
- case base < 2:
- panic("illegal base")
- case len(x) == 0:
- return string(charset[0])
- }
-
- // allocate buffer for conversion
- i := x.bitLen()/log2(Word(base)) + 1 // +1: round up
- s := make([]byte, i)
-
- // don't destroy x
- q := nat(nil).set(x)
-
- // convert
- for len(q) > 0 {
- i--
- var r Word
- q, r = q.divW(q, Word(base))
- s[i] = charset[r]
- }
-
- return string(s[i:])
-}
-
-var strTests = []struct {
- x nat // nat value to be converted
- c string // conversion charset
- s string // expected result
-}{
- {nil, "01", "0"},
- {nat{1}, "01", "1"},
- {nat{0xc5}, "01", "11000101"},
- {nat{03271}, lowercaseDigits[0:8], "3271"},
- {nat{10}, lowercaseDigits[0:10], "10"},
- {nat{1234567890}, uppercaseDigits[0:10], "1234567890"},
- {nat{0xdeadbeef}, lowercaseDigits[0:16], "deadbeef"},
- {nat{0xdeadbeef}, uppercaseDigits[0:16], "DEADBEEF"},
- {nat{0x229be7}, lowercaseDigits[0:17], "1a2b3c"},
- {nat{0x309663e6}, uppercaseDigits[0:32], "O9COV6"},
-}
-
-func TestString(t *testing.T) {
- for _, a := range strTests {
- s := a.x.string(a.c)
- if s != a.s {
- t.Errorf("string%+v\n\tgot s = %s; want %s", a, s, a.s)
- }
-
- x, b, err := nat(nil).scan(strings.NewReader(a.s), len(a.c))
- if x.cmp(a.x) != 0 {
- t.Errorf("scan%+v\n\tgot z = %v; want %v", a, x, a.x)
- }
- if b != len(a.c) {
- t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, len(a.c))
- }
- if err != nil {
- t.Errorf("scan%+v\n\tgot error = %s", a, err)
- }
- }
-}
-
-var natScanTests = []struct {
- s string // string to be scanned
- base int // input base
- x nat // expected nat
- b int // expected base
- ok bool // expected success
- next rune // next character (or 0, if at EOF)
-}{
- // error: illegal base
- {base: -1},
- {base: 1},
- {base: 37},
-
- // error: no mantissa
- {},
- {s: "?"},
- {base: 10},
- {base: 36},
- {s: "?", base: 10},
- {s: "0x"},
- {s: "345", base: 2},
-
- // no errors
- {"0", 0, nil, 10, true, 0},
- {"0", 10, nil, 10, true, 0},
- {"0", 36, nil, 36, true, 0},
- {"1", 0, nat{1}, 10, true, 0},
- {"1", 10, nat{1}, 10, true, 0},
- {"0 ", 0, nil, 10, true, ' '},
- {"08", 0, nil, 10, true, '8'},
- {"018", 0, nat{1}, 8, true, '8'},
- {"0b1", 0, nat{1}, 2, true, 0},
- {"0b11000101", 0, nat{0xc5}, 2, true, 0},
- {"03271", 0, nat{03271}, 8, true, 0},
- {"10ab", 0, nat{10}, 10, true, 'a'},
- {"1234567890", 0, nat{1234567890}, 10, true, 0},
- {"xyz", 36, nat{(33*36+34)*36 + 35}, 36, true, 0},
- {"xyz?", 36, nat{(33*36+34)*36 + 35}, 36, true, '?'},
- {"0x", 16, nil, 16, true, 'x'},
- {"0xdeadbeef", 0, nat{0xdeadbeef}, 16, true, 0},
- {"0XDEADBEEF", 0, nat{0xdeadbeef}, 16, true, 0},
-}
-
-func TestScanBase(t *testing.T) {
- for _, a := range natScanTests {
- r := strings.NewReader(a.s)
- x, b, err := nat(nil).scan(r, a.base)
- if err == nil && !a.ok {
- t.Errorf("scan%+v\n\texpected error", a)
- }
- if err != nil {
- if a.ok {
- t.Errorf("scan%+v\n\tgot error = %s", a, err)
- }
- continue
- }
- if x.cmp(a.x) != 0 {
- t.Errorf("scan%+v\n\tgot z = %v; want %v", a, x, a.x)
- }
- if b != a.b {
- t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, a.base)
- }
- next, _, err := r.ReadRune()
- if err == io.EOF {
- next = 0
- err = nil
- }
- if err == nil && next != a.next {
- t.Errorf("scan%+v\n\tgot next = %q; want %q", a, next, a.next)
- }
- }
-}
-
-var pi = "3" +
- "14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651" +
- "32823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461" +
- "28475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920" +
- "96282925409171536436789259036001133053054882046652138414695194151160943305727036575959195309218611738193261179" +
- "31051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798" +
- "60943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901" +
- "22495343014654958537105079227968925892354201995611212902196086403441815981362977477130996051870721134999999837" +
- "29780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083" +
- "81420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909" +
- "21642019893809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913151" +
- "55748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035" +
- "63707660104710181942955596198946767837449448255379774726847104047534646208046684259069491293313677028989152104" +
- "75216205696602405803815019351125338243003558764024749647326391419927260426992279678235478163600934172164121992" +
- "45863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818" +
- "34797753566369807426542527862551818417574672890977772793800081647060016145249192173217214772350141441973568548" +
- "16136115735255213347574184946843852332390739414333454776241686251898356948556209921922218427255025425688767179" +
- "04946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886" +
- "26945604241965285022210661186306744278622039194945047123713786960956364371917287467764657573962413890865832645" +
- "99581339047802759009946576407895126946839835259570982582262052248940772671947826848260147699090264013639443745" +
- "53050682034962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382" +
- "68683868942774155991855925245953959431049972524680845987273644695848653836736222626099124608051243884390451244" +
- "13654976278079771569143599770012961608944169486855584840635342207222582848864815845602850601684273945226746767" +
- "88952521385225499546667278239864565961163548862305774564980355936345681743241125150760694794510965960940252288" +
- "79710893145669136867228748940560101503308617928680920874760917824938589009714909675985261365549781893129784821" +
- "68299894872265880485756401427047755513237964145152374623436454285844479526586782105114135473573952311342716610" +
- "21359695362314429524849371871101457654035902799344037420073105785390621983874478084784896833214457138687519435" +
- "06430218453191048481005370614680674919278191197939952061419663428754440643745123718192179998391015919561814675" +
- "14269123974894090718649423196156794520809514655022523160388193014209376213785595663893778708303906979207734672" +
- "21825625996615014215030680384477345492026054146659252014974428507325186660021324340881907104863317346496514539" +
- "05796268561005508106658796998163574736384052571459102897064140110971206280439039759515677157700420337869936007" +
- "23055876317635942187312514712053292819182618612586732157919841484882916447060957527069572209175671167229109816" +
- "90915280173506712748583222871835209353965725121083579151369882091444210067510334671103141267111369908658516398" +
- "31501970165151168517143765761835155650884909989859982387345528331635507647918535893226185489632132933089857064" +
- "20467525907091548141654985946163718027098199430992448895757128289059232332609729971208443357326548938239119325" +
- "97463667305836041428138830320382490375898524374417029132765618093773444030707469211201913020330380197621101100" +
- "44929321516084244485963766983895228684783123552658213144957685726243344189303968642624341077322697802807318915" +
- "44110104468232527162010526522721116603966655730925471105578537634668206531098965269186205647693125705863566201" +
- "85581007293606598764861179104533488503461136576867532494416680396265797877185560845529654126654085306143444318" +
- "58676975145661406800700237877659134401712749470420562230538994561314071127000407854733269939081454664645880797" +
- "27082668306343285878569830523580893306575740679545716377525420211495576158140025012622859413021647155097925923" +
- "09907965473761255176567513575178296664547791745011299614890304639947132962107340437518957359614589019389713111" +
- "79042978285647503203198691514028708085990480109412147221317947647772622414254854540332157185306142288137585043" +
- "06332175182979866223717215916077166925474873898665494945011465406284336639379003976926567214638530673609657120" +
- "91807638327166416274888800786925602902284721040317211860820419000422966171196377921337575114959501566049631862" +
- "94726547364252308177036751590673502350728354056704038674351362222477158915049530984448933309634087807693259939" +
- "78054193414473774418426312986080998886874132604721569516239658645730216315981931951673538129741677294786724229" +
- "24654366800980676928238280689964004824354037014163149658979409243237896907069779422362508221688957383798623001" +
- "59377647165122893578601588161755782973523344604281512627203734314653197777416031990665541876397929334419521541" +
- "34189948544473456738316249934191318148092777710386387734317720754565453220777092120190516609628049092636019759" +
- "88281613323166636528619326686336062735676303544776280350450777235547105859548702790814356240145171806246436267" +
- "94561275318134078330336254232783944975382437205835311477119926063813346776879695970309833913077109870408591337"
-
-// Test case for BenchmarkScanPi.
-func TestScanPi(t *testing.T) {
- var x nat
- z, _, err := x.scan(strings.NewReader(pi), 10)
- if err != nil {
- t.Errorf("scanning pi: %s", err)
- }
- if s := z.decimalString(); s != pi {
- t.Errorf("scanning pi: got %s", s)
- }
-}
-
-func TestScanPiParallel(t *testing.T) {
- const n = 2
- c := make(chan int)
- for i := 0; i < n; i++ {
- go func() {
- TestScanPi(t)
- c <- 0
- }()
- }
- for i := 0; i < n; i++ {
- <-c
- }
-}
-
-func BenchmarkScanPi(b *testing.B) {
- for i := 0; i < b.N; i++ {
- var x nat
- x.scan(strings.NewReader(pi), 10)
- }
-}
-
-func BenchmarkStringPiParallel(b *testing.B) {
- var x nat
- x, _, _ = x.scan(strings.NewReader(pi), 0)
- if x.decimalString() != pi {
- panic("benchmark incorrect: conversion failed")
- }
- b.RunParallel(func(pb *testing.PB) {
- for pb.Next() {
- x.decimalString()
- }
- })
-}
-
-func BenchmarkScan10Base2(b *testing.B) { ScanHelper(b, 2, 10, 10) }
-func BenchmarkScan100Base2(b *testing.B) { ScanHelper(b, 2, 10, 100) }
-func BenchmarkScan1000Base2(b *testing.B) { ScanHelper(b, 2, 10, 1000) }
-func BenchmarkScan10000Base2(b *testing.B) { ScanHelper(b, 2, 10, 10000) }
-func BenchmarkScan100000Base2(b *testing.B) { ScanHelper(b, 2, 10, 100000) }
-
-func BenchmarkScan10Base8(b *testing.B) { ScanHelper(b, 8, 10, 10) }
-func BenchmarkScan100Base8(b *testing.B) { ScanHelper(b, 8, 10, 100) }
-func BenchmarkScan1000Base8(b *testing.B) { ScanHelper(b, 8, 10, 1000) }
-func BenchmarkScan10000Base8(b *testing.B) { ScanHelper(b, 8, 10, 10000) }
-func BenchmarkScan100000Base8(b *testing.B) { ScanHelper(b, 8, 10, 100000) }
-
-func BenchmarkScan10Base10(b *testing.B) { ScanHelper(b, 10, 10, 10) }
-func BenchmarkScan100Base10(b *testing.B) { ScanHelper(b, 10, 10, 100) }
-func BenchmarkScan1000Base10(b *testing.B) { ScanHelper(b, 10, 10, 1000) }
-func BenchmarkScan10000Base10(b *testing.B) { ScanHelper(b, 10, 10, 10000) }
-func BenchmarkScan100000Base10(b *testing.B) { ScanHelper(b, 10, 10, 100000) }
-
-func BenchmarkScan10Base16(b *testing.B) { ScanHelper(b, 16, 10, 10) }
-func BenchmarkScan100Base16(b *testing.B) { ScanHelper(b, 16, 10, 100) }
-func BenchmarkScan1000Base16(b *testing.B) { ScanHelper(b, 16, 10, 1000) }
-func BenchmarkScan10000Base16(b *testing.B) { ScanHelper(b, 16, 10, 10000) }
-func BenchmarkScan100000Base16(b *testing.B) { ScanHelper(b, 16, 10, 100000) }
-
-func ScanHelper(b *testing.B, base int, x, y Word) {
- b.StopTimer()
- var z nat
- z = z.expWW(x, y)
-
- var s string
- s = z.string(lowercaseDigits[0:base])
- if t := toString(z, lowercaseDigits[0:base]); t != s {
- b.Fatalf("scanning: got %s; want %s", s, t)
- }
- b.StartTimer()
-
- for i := 0; i < b.N; i++ {
- z.scan(strings.NewReader(s), base)
- }
-}
-
-func BenchmarkString10Base2(b *testing.B) { StringHelper(b, 2, 10, 10) }
-func BenchmarkString100Base2(b *testing.B) { StringHelper(b, 2, 10, 100) }
-func BenchmarkString1000Base2(b *testing.B) { StringHelper(b, 2, 10, 1000) }
-func BenchmarkString10000Base2(b *testing.B) { StringHelper(b, 2, 10, 10000) }
-func BenchmarkString100000Base2(b *testing.B) { StringHelper(b, 2, 10, 100000) }
-
-func BenchmarkString10Base8(b *testing.B) { StringHelper(b, 8, 10, 10) }
-func BenchmarkString100Base8(b *testing.B) { StringHelper(b, 8, 10, 100) }
-func BenchmarkString1000Base8(b *testing.B) { StringHelper(b, 8, 10, 1000) }
-func BenchmarkString10000Base8(b *testing.B) { StringHelper(b, 8, 10, 10000) }
-func BenchmarkString100000Base8(b *testing.B) { StringHelper(b, 8, 10, 100000) }
-
-func BenchmarkString10Base10(b *testing.B) { StringHelper(b, 10, 10, 10) }
-func BenchmarkString100Base10(b *testing.B) { StringHelper(b, 10, 10, 100) }
-func BenchmarkString1000Base10(b *testing.B) { StringHelper(b, 10, 10, 1000) }
-func BenchmarkString10000Base10(b *testing.B) { StringHelper(b, 10, 10, 10000) }
-func BenchmarkString100000Base10(b *testing.B) { StringHelper(b, 10, 10, 100000) }
-
-func BenchmarkString10Base16(b *testing.B) { StringHelper(b, 16, 10, 10) }
-func BenchmarkString100Base16(b *testing.B) { StringHelper(b, 16, 10, 100) }
-func BenchmarkString1000Base16(b *testing.B) { StringHelper(b, 16, 10, 1000) }
-func BenchmarkString10000Base16(b *testing.B) { StringHelper(b, 16, 10, 10000) }
-func BenchmarkString100000Base16(b *testing.B) { StringHelper(b, 16, 10, 100000) }
-
-func StringHelper(b *testing.B, base int, x, y Word) {
- b.StopTimer()
- var z nat
- z = z.expWW(x, y)
- z.string(lowercaseDigits[0:base]) // warm divisor cache
- b.StartTimer()
-
- for i := 0; i < b.N; i++ {
- _ = z.string(lowercaseDigits[0:base])
- }
-}
-
-func BenchmarkLeafSize0(b *testing.B) { LeafSizeHelper(b, 10, 0) } // test without splitting
-func BenchmarkLeafSize1(b *testing.B) { LeafSizeHelper(b, 10, 1) }
-func BenchmarkLeafSize2(b *testing.B) { LeafSizeHelper(b, 10, 2) }
-func BenchmarkLeafSize3(b *testing.B) { LeafSizeHelper(b, 10, 3) }
-func BenchmarkLeafSize4(b *testing.B) { LeafSizeHelper(b, 10, 4) }
-func BenchmarkLeafSize5(b *testing.B) { LeafSizeHelper(b, 10, 5) }
-func BenchmarkLeafSize6(b *testing.B) { LeafSizeHelper(b, 10, 6) }
-func BenchmarkLeafSize7(b *testing.B) { LeafSizeHelper(b, 10, 7) }
-func BenchmarkLeafSize8(b *testing.B) { LeafSizeHelper(b, 10, 8) }
-func BenchmarkLeafSize9(b *testing.B) { LeafSizeHelper(b, 10, 9) }
-func BenchmarkLeafSize10(b *testing.B) { LeafSizeHelper(b, 10, 10) }
-func BenchmarkLeafSize11(b *testing.B) { LeafSizeHelper(b, 10, 11) }
-func BenchmarkLeafSize12(b *testing.B) { LeafSizeHelper(b, 10, 12) }
-func BenchmarkLeafSize13(b *testing.B) { LeafSizeHelper(b, 10, 13) }
-func BenchmarkLeafSize14(b *testing.B) { LeafSizeHelper(b, 10, 14) }
-func BenchmarkLeafSize15(b *testing.B) { LeafSizeHelper(b, 10, 15) }
-func BenchmarkLeafSize16(b *testing.B) { LeafSizeHelper(b, 10, 16) }
-func BenchmarkLeafSize32(b *testing.B) { LeafSizeHelper(b, 10, 32) } // try some large lengths
-func BenchmarkLeafSize64(b *testing.B) { LeafSizeHelper(b, 10, 64) }
-
-func LeafSizeHelper(b *testing.B, base Word, size int) {
- b.StopTimer()
- originalLeafSize := leafSize
- resetTable(cacheBase10.table[:])
- leafSize = size
- b.StartTimer()
-
- for d := 1; d <= 10000; d *= 10 {
- b.StopTimer()
- var z nat
- z = z.expWW(base, Word(d)) // build target number
- _ = z.string(lowercaseDigits[0:base]) // warm divisor cache
- b.StartTimer()
-
- for i := 0; i < b.N; i++ {
- _ = z.string(lowercaseDigits[0:base])
- }
- }
-
- b.StopTimer()
- resetTable(cacheBase10.table[:])
- leafSize = originalLeafSize
- b.StartTimer()
-}
-
-func resetTable(table []divisor) {
- if table != nil && table[0].bbb != nil {
- for i := 0; i < len(table); i++ {
- table[i].bbb = nil
- table[i].nbits = 0
- table[i].ndigits = 0
- }
- }
-}
-
-func TestStringPowers(t *testing.T) {
- var b, p Word
- for b = 2; b <= 16; b++ {
- for p = 0; p <= 512; p++ {
- x := nat(nil).expWW(b, p)
- xs := x.string(lowercaseDigits[0:b])
- xs2 := toString(x, lowercaseDigits[0:b])
- if xs != xs2 {
- t.Errorf("failed at %d ** %d in base %d: %s != %s", b, p, b, xs, xs2)
- }
- }
- if b >= 3 && testing.Short() {
- break
- }
- }
-}
-
func TestLeadingZeros(t *testing.T) {
var x Word = _B >> 1
for i := 0; i <= _W; i++ {
}
func TestTrailingZeroBits(t *testing.T) {
+ // test 0 case explicitly
+ if n := trailingZeroBits(0); n != 0 {
+ t.Errorf("got trailingZeroBits(0) = %d; want 0", n)
+ }
+
x := Word(1)
- for i := uint(0); i <= _W; i++ {
+ for i := uint(0); i < _W; i++ {
n := trailingZeroBits(x)
- if n != i%_W {
+ if n != i {
t.Errorf("got trailingZeroBits(%#x) = %d; want %d", x, n, i%_W)
}
x <<= 1
}
+ // test 0 case explicitly
+ if n := nat(nil).trailingZeroBits(); n != 0 {
+ t.Errorf("got nat(nil).trailingZeroBits() = %d; want 0", n)
+ }
+
y := nat(nil).set(natOne)
for i := uint(0); i <= 3*_W; i++ {
n := y.trailingZeroBits()
if n != i {
- t.Errorf("got 0x%s.trailingZeroBits() = %d; want %d", y.string(lowercaseDigits[0:16]), n, i)
+ t.Errorf("got 0x%s.trailingZeroBits() = %d; want %d", y.hexString(), n, i)
}
y = y.shl(y, 1)
}
func TestExpNN(t *testing.T) {
for i, test := range expNNTests {
- x, _, _ := nat(nil).scan(strings.NewReader(test.x), 0)
- y, _, _ := nat(nil).scan(strings.NewReader(test.y), 0)
- out, _, _ := nat(nil).scan(strings.NewReader(test.out), 0)
+ x := natFromString(test.x)
+ y := natFromString(test.y)
+ out := natFromString(test.out)
var m nat
-
if len(test.m) > 0 {
- m, _, _ = nat(nil).scan(strings.NewReader(test.m), 0)
+ m = natFromString(test.m)
}
z := nat(nil).expNN(x, y, m)
fibo(1e5)
}
}
+
+var bitTests = []struct {
+ x string
+ i uint
+ want uint
+}{
+ {"0", 0, 0},
+ {"0", 1, 0},
+ {"0", 1000, 0},
+
+ {"0x1", 0, 1},
+ {"0x10", 0, 0},
+ {"0x10", 3, 0},
+ {"0x10", 4, 1},
+ {"0x10", 5, 0},
+
+ {"0x8000000000000000", 62, 0},
+ {"0x8000000000000000", 63, 1},
+ {"0x8000000000000000", 64, 0},
+
+ {"0x3" + strings.Repeat("0", 32), 127, 0},
+ {"0x3" + strings.Repeat("0", 32), 128, 1},
+ {"0x3" + strings.Repeat("0", 32), 129, 1},
+ {"0x3" + strings.Repeat("0", 32), 130, 0},
+}
+
+func TestBit(t *testing.T) {
+ for i, test := range bitTests {
+ x := natFromString(test.x)
+ if got := x.bit(test.i); got != test.want {
+ t.Errorf("#%d: %s.bit(%d) = %v; want %v", i, test.x, test.i, got, test.want)
+ }
+ }
+}
+
+var stickyTests = []struct {
+ x string
+ i uint
+ want uint
+}{
+ {"0", 0, 0},
+ {"0", 1, 0},
+ {"0", 1000, 0},
+
+ {"0x1", 0, 0},
+ {"0x1", 1, 1},
+
+ {"0x1350", 0, 0},
+ {"0x1350", 4, 0},
+ {"0x1350", 5, 1},
+
+ {"0x8000000000000000", 63, 0},
+ {"0x8000000000000000", 64, 1},
+
+ {"0x1" + strings.Repeat("0", 100), 400, 0},
+ {"0x1" + strings.Repeat("0", 100), 401, 1},
+}
+
+func TestSticky(t *testing.T) {
+ for i, test := range stickyTests {
+ x := natFromString(test.x)
+ if got := x.sticky(test.i); got != test.want {
+ t.Errorf("#%d: %s.sticky(%d) = %v; want %v", i, test.x, test.i, got, test.want)
+ }
+ if test.want == 1 {
+ // all subsequent i's should also return 1
+ for d := uint(1); d <= 3; d++ {
+ if got := x.sticky(test.i + d); got != 1 {
+ t.Errorf("#%d: %s.sticky(%d) = %v; want %v", i, test.x, test.i+d, got, 1)
+ }
+ }
+ }
+ }
+}
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements nat-to-string conversion functions.
+
+package big
+
+import (
+ "errors"
+ "io"
+ "math"
+ "sync"
+)
+
+// MaxBase is the largest number base accepted for string conversions.
+const MaxBase = 'z' - 'a' + 10 + 1
+
+// maxPow returns (b**n, n) such that b**n is the largest power b**n <= _M.
+// For instance maxPow(10) == (1e19, 19) for 19 decimal digits in a 64bit Word.
+// In other words, at most n digits in base b fit into a Word.
+// TODO(gri) replace this with a table, generated at build time.
+func maxPow(b Word) (p Word, n int) {
+ p, n = b, 1 // assuming b <= _M
+ for max := _M / b; p <= max; {
+ // p == b**n && p <= max
+ p *= b
+ n++
+ }
+ // p == b**n && p <= _M
+ return
+}
+
+// pow returns x**n for n > 0, and 1 otherwise.
+func pow(x Word, n int) (p Word) {
+ // n == sum of bi * 2**i, for 0 <= i < imax, and bi is 0 or 1
+ // thus x**n == product of x**(2**i) for all i where bi == 1
+ // (Russian Peasant Method for exponentiation)
+ p = 1
+ for n > 0 {
+ if n&1 != 0 {
+ p *= x
+ }
+ x *= x
+ n >>= 1
+ }
+ return
+}
+
+// scan scans the number corresponding to the longest possible prefix
+// from r representing an unsigned number in a given conversion base.
+// It returns the corresponding natural number res, the actual base b,
+// a digit count, and an error err, if any.
+//
+// number = [ prefix ] mantissa .
+// prefix = "0" [ "x" | "X" | "b" | "B" ] .
+// mantissa = digits | digits "." [ digits ] | "." digits .
+// digits = digit { digit } .
+// digit = "0" ... "9" | "a" ... "z" | "A" ... "Z" .
+//
+// The base argument must be 0 or a value between 0 through MaxBase.
+//
+// For base 0, the number prefix determines the actual base: A prefix of
+// ``0x'' or ``0X'' selects base 16; if fracOk is not set, the ``0'' prefix
+// selects base 8, and a ``0b'' or ``0B'' prefix selects base 2. Otherwise
+// the selected base is 10 and no prefix is permitted.
+//
+// If fracOk is set, an octal prefix is ignored (a leading ``0'' simply
+// stands for a zero digit), and a period followed by a fractional part
+// is permitted. The result value is computed as if there were no period
+// present; and the count value is used to determine the fractional part.
+//
+// A result digit count > 0 corresponds to the number of (non-prefix) digits
+// parsed. A digit count <= 0 indicates the presence of a period (if fracOk
+// is set, only), and -count is the number of fractional digits found.
+// In this case, the value of the scanned number is res * 10**count.
+//
+func (z nat) scan(r io.ByteScanner, base int, fracOk bool) (res nat, b, count int, err error) {
+ // reject illegal bases
+ if base != 0 && base < 2 || base > MaxBase {
+ err = errors.New("illegal number base")
+ return
+ }
+
+ // one char look-ahead
+ ch, err := r.ReadByte()
+ if err != nil {
+ return
+ }
+
+ // determine actual base
+ b = base
+ if base == 0 {
+ // actual base is 10 unless there's a base prefix
+ b = 10
+ if ch == '0' {
+ count = 1
+ switch ch, err = r.ReadByte(); err {
+ case nil:
+ // possibly one of 0x, 0X, 0b, 0B
+ if !fracOk {
+ b = 8
+ }
+ switch ch {
+ case 'x', 'X':
+ b = 16
+ case 'b', 'B':
+ b = 2
+ }
+ switch b {
+ case 16, 2:
+ count = 0 // prefix is not counted
+ if ch, err = r.ReadByte(); err != nil {
+ // io.EOF is also an error in this case
+ return
+ }
+ case 8:
+ count = 0 // prefix is not counted
+ }
+ case io.EOF:
+ // input is "0"
+ res = z[:0]
+ err = nil
+ return
+ default:
+ // read error
+ return
+ }
+ }
+ }
+
+ // convert string
+ // Algorithm: Collect digits in groups of at most n digits in di
+ // and then use mulAddWW for every such group to add them to the
+ // result.
+ z = z[:0]
+ b1 := Word(b)
+ bn, n := maxPow(b1) // at most n digits in base b1 fit into Word
+ di := Word(0) // 0 <= di < b1**i < bn
+ i := 0 // 0 <= i < n
+ dp := -1 // position of decimal point
+ for {
+ if fracOk && ch == '.' {
+ fracOk = false
+ dp = count
+ // advance
+ if ch, err = r.ReadByte(); err != nil {
+ if err == io.EOF {
+ err = nil
+ break
+ }
+ return
+ }
+ }
+
+ // convert rune into digit value d1
+ var d1 Word
+ switch {
+ case '0' <= ch && ch <= '9':
+ d1 = Word(ch - '0')
+ case 'a' <= ch && ch <= 'z':
+ d1 = Word(ch - 'a' + 10)
+ case 'A' <= ch && ch <= 'Z':
+ d1 = Word(ch - 'A' + 10)
+ default:
+ d1 = MaxBase + 1
+ }
+ if d1 >= b1 {
+ r.UnreadByte() // ch does not belong to number anymore
+ break
+ }
+ count++
+
+ // collect d1 in di
+ di = di*b1 + d1
+ i++
+
+ // if di is "full", add it to the result
+ if i == n {
+ z = z.mulAddWW(z, bn, di)
+ di = 0
+ i = 0
+ }
+
+ // advance
+ if ch, err = r.ReadByte(); err != nil {
+ if err == io.EOF {
+ err = nil
+ break
+ }
+ return
+ }
+ }
+
+ if count == 0 {
+ // no digits found
+ switch {
+ case base == 0 && b == 8:
+ // there was only the octal prefix 0 (possibly followed by digits > 7);
+ // count as one digit and return base 10, not 8
+ count = 1
+ b = 10
+ case base != 0 || b != 8:
+ // there was neither a mantissa digit nor the octal prefix 0
+ err = errors.New("syntax error scanning number")
+ }
+ return
+ }
+ // count > 0
+
+ // add remaining digits to result
+ if i > 0 {
+ z = z.mulAddWW(z, pow(b1, i), di)
+ }
+ res = z.norm()
+
+ // adjust for fraction, if any
+ if dp >= 0 {
+ // 0 <= dp <= count > 0
+ count = dp - count
+ }
+
+ return
+}
+
+// Character sets for string conversion.
+const (
+ lowercaseDigits = "0123456789abcdefghijklmnopqrstuvwxyz"
+ uppercaseDigits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+)
+
+// decimalString returns a decimal representation of x.
+// It calls x.string with the charset "0123456789".
+func (x nat) decimalString() string {
+ return x.string(lowercaseDigits[:10])
+}
+
+// hexString returns a hexadecimal representation of x.
+// It calls x.string with the charset "0123456789abcdef".
+func (x nat) hexString() string {
+ return x.string(lowercaseDigits[:16])
+}
+
+// string converts x to a string using digits from a charset; a digit with
+// value d is represented by charset[d]. The conversion base is determined
+// by len(charset), which must be >= 2 and <= 256.
+func (x nat) string(charset string) string {
+ b := Word(len(charset))
+
+ // special cases
+ switch {
+ case b < 2 || b > 256:
+ panic("invalid character set length")
+ case len(x) == 0:
+ return string(charset[0])
+ }
+
+ // allocate buffer for conversion
+ i := int(float64(x.bitLen())/math.Log2(float64(b))) + 1 // off by one at most
+ s := make([]byte, i)
+
+ // convert power of two and non power of two bases separately
+ if b == b&-b {
+ // shift is base-b digit size in bits
+ shift := trailingZeroBits(b) // shift > 0 because b >= 2
+ mask := Word(1)<<shift - 1
+ w := x[0]
+ nbits := uint(_W) // number of unprocessed bits in w
+
+ // convert less-significant words
+ for k := 1; k < len(x); k++ {
+ // convert full digits
+ for nbits >= shift {
+ i--
+ s[i] = charset[w&mask]
+ w >>= shift
+ nbits -= shift
+ }
+
+ // convert any partial leading digit and advance to next word
+ if nbits == 0 {
+ // no partial digit remaining, just advance
+ w = x[k]
+ nbits = _W
+ } else {
+ // partial digit in current (k-1) and next (k) word
+ w |= x[k] << nbits
+ i--
+ s[i] = charset[w&mask]
+
+ // advance
+ w = x[k] >> (shift - nbits)
+ nbits = _W - (shift - nbits)
+ }
+ }
+
+ // convert digits of most-significant word (omit leading zeros)
+ for nbits >= 0 && w != 0 {
+ i--
+ s[i] = charset[w&mask]
+ w >>= shift
+ nbits -= shift
+ }
+
+ } else {
+ bb, ndigits := maxPow(Word(b))
+
+ // construct table of successive squares of bb*leafSize to use in subdivisions
+ // result (table != nil) <=> (len(x) > leafSize > 0)
+ table := divisors(len(x), b, ndigits, bb)
+
+ // preserve x, create local copy for use by convertWords
+ q := nat(nil).set(x)
+
+ // convert q to string s in base b
+ q.convertWords(s, charset, b, ndigits, bb, table)
+
+ // strip leading zeros
+ // (x != 0; thus s must contain at least one non-zero digit
+ // and the loop will terminate)
+ i = 0
+ for zero := charset[0]; s[i] == zero; {
+ i++
+ }
+ }
+
+ return string(s[i:])
+}
+
+// Convert words of q to base b digits in s. If q is large, it is recursively "split in half"
+// by nat/nat division using tabulated divisors. Otherwise, it is converted iteratively using
+// repeated nat/Word division.
+//
+// The iterative method processes n Words by n divW() calls, each of which visits every Word in the
+// incrementally shortened q for a total of n + (n-1) + (n-2) ... + 2 + 1, or n(n+1)/2 divW()'s.
+// Recursive conversion divides q by its approximate square root, yielding two parts, each half
+// the size of q. Using the iterative method on both halves means 2 * (n/2)(n/2 + 1)/2 divW()'s
+// plus the expensive long div(). Asymptotically, the ratio is favorable at 1/2 the divW()'s, and
+// is made better by splitting the subblocks recursively. Best is to split blocks until one more
+// split would take longer (because of the nat/nat div()) than the twice as many divW()'s of the
+// iterative approach. This threshold is represented by leafSize. Benchmarking of leafSize in the
+// range 2..64 shows that values of 8 and 16 work well, with a 4x speedup at medium lengths and
+// ~30x for 20000 digits. Use nat_test.go's BenchmarkLeafSize tests to optimize leafSize for
+// specific hardware.
+//
+func (q nat) convertWords(s []byte, charset string, b Word, ndigits int, bb Word, table []divisor) {
+ // split larger blocks recursively
+ if table != nil {
+ // len(q) > leafSize > 0
+ var r nat
+ index := len(table) - 1
+ for len(q) > leafSize {
+ // find divisor close to sqrt(q) if possible, but in any case < q
+ maxLength := q.bitLen() // ~= log2 q, or at of least largest possible q of this bit length
+ minLength := maxLength >> 1 // ~= log2 sqrt(q)
+ for index > 0 && table[index-1].nbits > minLength {
+ index-- // desired
+ }
+ if table[index].nbits >= maxLength && table[index].bbb.cmp(q) >= 0 {
+ index--
+ if index < 0 {
+ panic("internal inconsistency")
+ }
+ }
+
+ // split q into the two digit number (q'*bbb + r) to form independent subblocks
+ q, r = q.div(r, q, table[index].bbb)
+
+ // convert subblocks and collect results in s[:h] and s[h:]
+ h := len(s) - table[index].ndigits
+ r.convertWords(s[h:], charset, b, ndigits, bb, table[0:index])
+ s = s[:h] // == q.convertWords(s, charset, b, ndigits, bb, table[0:index+1])
+ }
+ }
+
+ // having split any large blocks now process the remaining (small) block iteratively
+ i := len(s)
+ var r Word
+ if b == 10 {
+ // hard-coding for 10 here speeds this up by 1.25x (allows for / and % by constants)
+ for len(q) > 0 {
+ // extract least significant, base bb "digit"
+ q, r = q.divW(q, bb)
+ for j := 0; j < ndigits && i > 0; j++ {
+ i--
+ // avoid % computation since r%10 == r - int(r/10)*10;
+ // this appears to be faster for BenchmarkString10000Base10
+ // and smaller strings (but a bit slower for larger ones)
+ t := r / 10
+ s[i] = charset[r-t<<3-t-t] // TODO(gri) replace w/ t*10 once compiler produces better code
+ r = t
+ }
+ }
+ } else {
+ for len(q) > 0 {
+ // extract least significant, base bb "digit"
+ q, r = q.divW(q, bb)
+ for j := 0; j < ndigits && i > 0; j++ {
+ i--
+ s[i] = charset[r%b]
+ r /= b
+ }
+ }
+ }
+
+ // prepend high-order zeroes
+ zero := charset[0]
+ for i > 0 { // while need more leading zeroes
+ i--
+ s[i] = zero
+ }
+}
+
+// Split blocks greater than leafSize Words (or set to 0 to disable recursive conversion)
+// Benchmark and configure leafSize using: go test -bench="Leaf"
+// 8 and 16 effective on 3.0 GHz Xeon "Clovertown" CPU (128 byte cache lines)
+// 8 and 16 effective on 2.66 GHz Core 2 Duo "Penryn" CPU
+var leafSize int = 8 // number of Word-size binary values treat as a monolithic block
+
+type divisor struct {
+ bbb nat // divisor
+ nbits int // bit length of divisor (discounting leading zeroes) ~= log2(bbb)
+ ndigits int // digit length of divisor in terms of output base digits
+}
+
+var cacheBase10 struct {
+ sync.Mutex
+ table [64]divisor // cached divisors for base 10
+}
+
+// expWW computes x**y
+func (z nat) expWW(x, y Word) nat {
+ return z.expNN(nat(nil).setWord(x), nat(nil).setWord(y), nil)
+}
+
+// construct table of powers of bb*leafSize to use in subdivisions
+func divisors(m int, b Word, ndigits int, bb Word) []divisor {
+ // only compute table when recursive conversion is enabled and x is large
+ if leafSize == 0 || m <= leafSize {
+ return nil
+ }
+
+ // determine k where (bb**leafSize)**(2**k) >= sqrt(x)
+ k := 1
+ for words := leafSize; words < m>>1 && k < len(cacheBase10.table); words <<= 1 {
+ k++
+ }
+
+ // reuse and extend existing table of divisors or create new table as appropriate
+ var table []divisor // for b == 10, table overlaps with cacheBase10.table
+ if b == 10 {
+ cacheBase10.Lock()
+ table = cacheBase10.table[0:k] // reuse old table for this conversion
+ } else {
+ table = make([]divisor, k) // create new table for this conversion
+ }
+
+ // extend table
+ if table[k-1].ndigits == 0 {
+ // add new entries as needed
+ var larger nat
+ for i := 0; i < k; i++ {
+ if table[i].ndigits == 0 {
+ if i == 0 {
+ table[0].bbb = nat(nil).expWW(bb, Word(leafSize))
+ table[0].ndigits = ndigits * leafSize
+ } else {
+ table[i].bbb = nat(nil).mul(table[i-1].bbb, table[i-1].bbb)
+ table[i].ndigits = 2 * table[i-1].ndigits
+ }
+
+ // optimization: exploit aggregated extra bits in macro blocks
+ larger = nat(nil).set(table[i].bbb)
+ for mulAddVWW(larger, larger, b, 0) == 0 {
+ table[i].bbb = table[i].bbb.set(larger)
+ table[i].ndigits++
+ }
+
+ table[i].nbits = table[i].bbb.bitLen()
+ }
+ }
+ }
+
+ if b == 10 {
+ cacheBase10.Unlock()
+ }
+
+ return table
+}
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package big
+
+import (
+ "io"
+ "strings"
+ "testing"
+)
+
+func toString(x nat, charset string) string {
+ base := len(charset)
+
+ // special cases
+ switch {
+ case base < 2:
+ panic("illegal base")
+ case len(x) == 0:
+ return string(charset[0])
+ }
+
+ // allocate buffer for conversion
+ i := x.bitLen()/log2(Word(base)) + 1 // +1: round up
+ s := make([]byte, i)
+
+ // don't destroy x
+ q := nat(nil).set(x)
+
+ // convert
+ for len(q) > 0 {
+ i--
+ var r Word
+ q, r = q.divW(q, Word(base))
+ s[i] = charset[r]
+ }
+
+ return string(s[i:])
+}
+
+var strTests = []struct {
+ x nat // nat value to be converted
+ c string // conversion charset
+ s string // expected result
+}{
+ {nil, "01", "0"},
+ {nat{1}, "01", "1"},
+ {nat{0xc5}, "01", "11000101"},
+ {nat{03271}, lowercaseDigits[:8], "3271"},
+ {nat{10}, lowercaseDigits[:10], "10"},
+ {nat{1234567890}, uppercaseDigits[:10], "1234567890"},
+ {nat{0xdeadbeef}, lowercaseDigits[:16], "deadbeef"},
+ {nat{0xdeadbeef}, uppercaseDigits[:16], "DEADBEEF"},
+ {nat{0x229be7}, lowercaseDigits[:17], "1a2b3c"},
+ {nat{0x309663e6}, uppercaseDigits[:32], "O9COV6"},
+}
+
+func TestString(t *testing.T) {
+ // test invalid character set explicitly
+ var panicStr string
+ func() {
+ defer func() {
+ panicStr = recover().(string)
+ }()
+ natOne.string("0")
+ }()
+ if panicStr != "invalid character set length" {
+ t.Errorf("expected panic for invalid character set")
+ }
+
+ for _, a := range strTests {
+ s := a.x.string(a.c)
+ if s != a.s {
+ t.Errorf("string%+v\n\tgot s = %s; want %s", a, s, a.s)
+ }
+
+ x, b, _, err := nat(nil).scan(strings.NewReader(a.s), len(a.c), false)
+ if x.cmp(a.x) != 0 {
+ t.Errorf("scan%+v\n\tgot z = %v; want %v", a, x, a.x)
+ }
+ if b != len(a.c) {
+ t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, len(a.c))
+ }
+ if err != nil {
+ t.Errorf("scan%+v\n\tgot error = %s", a, err)
+ }
+ }
+}
+
+var natScanTests = []struct {
+ s string // string to be scanned
+ base int // input base
+ frac bool // fraction ok
+ x nat // expected nat
+ b int // expected base
+ count int // expected digit count
+ ok bool // expected success
+ next rune // next character (or 0, if at EOF)
+}{
+ // error: illegal base
+ {base: -1},
+ {base: 37},
+
+ // error: no mantissa
+ {},
+ {s: "?"},
+ {base: 10},
+ {base: 36},
+ {s: "?", base: 10},
+ {s: "0x"},
+ {s: "345", base: 2},
+
+ // error: incorrect use of decimal point
+ {s: ".0"},
+ {s: ".0", base: 10},
+ {s: ".", base: 1},
+ {s: "0x.0"},
+
+ // no errors
+ {"0", 0, false, nil, 10, 1, true, 0},
+ {"0", 10, false, nil, 10, 1, true, 0},
+ {"0", 36, false, nil, 36, 1, true, 0},
+ {"1", 0, false, nat{1}, 10, 1, true, 0},
+ {"1", 10, false, nat{1}, 10, 1, true, 0},
+ {"0 ", 0, false, nil, 10, 1, true, ' '},
+ {"08", 0, false, nil, 10, 1, true, '8'},
+ {"08", 10, false, nat{8}, 10, 2, true, 0},
+ {"018", 0, false, nat{1}, 8, 1, true, '8'},
+ {"0b1", 0, false, nat{1}, 2, 1, true, 0},
+ {"0b11000101", 0, false, nat{0xc5}, 2, 8, true, 0},
+ {"03271", 0, false, nat{03271}, 8, 4, true, 0},
+ {"10ab", 0, false, nat{10}, 10, 2, true, 'a'},
+ {"1234567890", 0, false, nat{1234567890}, 10, 10, true, 0},
+ {"xyz", 36, false, nat{(33*36+34)*36 + 35}, 36, 3, true, 0},
+ {"xyz?", 36, false, nat{(33*36+34)*36 + 35}, 36, 3, true, '?'},
+ {"0x", 16, false, nil, 16, 1, true, 'x'},
+ {"0xdeadbeef", 0, false, nat{0xdeadbeef}, 16, 8, true, 0},
+ {"0XDEADBEEF", 0, false, nat{0xdeadbeef}, 16, 8, true, 0},
+
+ // no errors, decimal point
+ {"0.", 0, false, nil, 10, 1, true, '.'},
+ {"0.", 10, true, nil, 10, 0, true, 0},
+ {"0.1.2", 10, true, nat{1}, 10, -1, true, '.'},
+ {".000", 10, true, nil, 10, -3, true, 0},
+ {"12.3", 10, true, nat{123}, 10, -1, true, 0},
+ {"012.345", 10, true, nat{12345}, 10, -3, true, 0},
+}
+
+func TestScanBase(t *testing.T) {
+ for _, a := range natScanTests {
+ r := strings.NewReader(a.s)
+ x, b, count, err := nat(nil).scan(r, a.base, a.frac)
+ if err == nil && !a.ok {
+ t.Errorf("scan%+v\n\texpected error", a)
+ }
+ if err != nil {
+ if a.ok {
+ t.Errorf("scan%+v\n\tgot error = %s", a, err)
+ }
+ continue
+ }
+ if x.cmp(a.x) != 0 {
+ t.Errorf("scan%+v\n\tgot z = %v; want %v", a, x, a.x)
+ }
+ if b != a.b {
+ t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, a.base)
+ }
+ if count != a.count {
+ t.Errorf("scan%+v\n\tgot count = %d; want %d", a, count, a.count)
+ }
+ next, _, err := r.ReadRune()
+ if err == io.EOF {
+ next = 0
+ err = nil
+ }
+ if err == nil && next != a.next {
+ t.Errorf("scan%+v\n\tgot next = %q; want %q", a, next, a.next)
+ }
+ }
+}
+
+var pi = "3" +
+ "14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651" +
+ "32823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461" +
+ "28475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920" +
+ "96282925409171536436789259036001133053054882046652138414695194151160943305727036575959195309218611738193261179" +
+ "31051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798" +
+ "60943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901" +
+ "22495343014654958537105079227968925892354201995611212902196086403441815981362977477130996051870721134999999837" +
+ "29780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083" +
+ "81420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909" +
+ "21642019893809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913151" +
+ "55748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035" +
+ "63707660104710181942955596198946767837449448255379774726847104047534646208046684259069491293313677028989152104" +
+ "75216205696602405803815019351125338243003558764024749647326391419927260426992279678235478163600934172164121992" +
+ "45863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818" +
+ "34797753566369807426542527862551818417574672890977772793800081647060016145249192173217214772350141441973568548" +
+ "16136115735255213347574184946843852332390739414333454776241686251898356948556209921922218427255025425688767179" +
+ "04946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886" +
+ "26945604241965285022210661186306744278622039194945047123713786960956364371917287467764657573962413890865832645" +
+ "99581339047802759009946576407895126946839835259570982582262052248940772671947826848260147699090264013639443745" +
+ "53050682034962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382" +
+ "68683868942774155991855925245953959431049972524680845987273644695848653836736222626099124608051243884390451244" +
+ "13654976278079771569143599770012961608944169486855584840635342207222582848864815845602850601684273945226746767" +
+ "88952521385225499546667278239864565961163548862305774564980355936345681743241125150760694794510965960940252288" +
+ "79710893145669136867228748940560101503308617928680920874760917824938589009714909675985261365549781893129784821" +
+ "68299894872265880485756401427047755513237964145152374623436454285844479526586782105114135473573952311342716610" +
+ "21359695362314429524849371871101457654035902799344037420073105785390621983874478084784896833214457138687519435" +
+ "06430218453191048481005370614680674919278191197939952061419663428754440643745123718192179998391015919561814675" +
+ "14269123974894090718649423196156794520809514655022523160388193014209376213785595663893778708303906979207734672" +
+ "21825625996615014215030680384477345492026054146659252014974428507325186660021324340881907104863317346496514539" +
+ "05796268561005508106658796998163574736384052571459102897064140110971206280439039759515677157700420337869936007" +
+ "23055876317635942187312514712053292819182618612586732157919841484882916447060957527069572209175671167229109816" +
+ "90915280173506712748583222871835209353965725121083579151369882091444210067510334671103141267111369908658516398" +
+ "31501970165151168517143765761835155650884909989859982387345528331635507647918535893226185489632132933089857064" +
+ "20467525907091548141654985946163718027098199430992448895757128289059232332609729971208443357326548938239119325" +
+ "97463667305836041428138830320382490375898524374417029132765618093773444030707469211201913020330380197621101100" +
+ "44929321516084244485963766983895228684783123552658213144957685726243344189303968642624341077322697802807318915" +
+ "44110104468232527162010526522721116603966655730925471105578537634668206531098965269186205647693125705863566201" +
+ "85581007293606598764861179104533488503461136576867532494416680396265797877185560845529654126654085306143444318" +
+ "58676975145661406800700237877659134401712749470420562230538994561314071127000407854733269939081454664645880797" +
+ "27082668306343285878569830523580893306575740679545716377525420211495576158140025012622859413021647155097925923" +
+ "09907965473761255176567513575178296664547791745011299614890304639947132962107340437518957359614589019389713111" +
+ "79042978285647503203198691514028708085990480109412147221317947647772622414254854540332157185306142288137585043" +
+ "06332175182979866223717215916077166925474873898665494945011465406284336639379003976926567214638530673609657120" +
+ "91807638327166416274888800786925602902284721040317211860820419000422966171196377921337575114959501566049631862" +
+ "94726547364252308177036751590673502350728354056704038674351362222477158915049530984448933309634087807693259939" +
+ "78054193414473774418426312986080998886874132604721569516239658645730216315981931951673538129741677294786724229" +
+ "24654366800980676928238280689964004824354037014163149658979409243237896907069779422362508221688957383798623001" +
+ "59377647165122893578601588161755782973523344604281512627203734314653197777416031990665541876397929334419521541" +
+ "34189948544473456738316249934191318148092777710386387734317720754565453220777092120190516609628049092636019759" +
+ "88281613323166636528619326686336062735676303544776280350450777235547105859548702790814356240145171806246436267" +
+ "94561275318134078330336254232783944975382437205835311477119926063813346776879695970309833913077109870408591337"
+
+// Test case for BenchmarkScanPi.
+func TestScanPi(t *testing.T) {
+ var x nat
+ z, _, _, err := x.scan(strings.NewReader(pi), 10, false)
+ if err != nil {
+ t.Errorf("scanning pi: %s", err)
+ }
+ if s := z.decimalString(); s != pi {
+ t.Errorf("scanning pi: got %s", s)
+ }
+}
+
+func TestScanPiParallel(t *testing.T) {
+ const n = 2
+ c := make(chan int)
+ for i := 0; i < n; i++ {
+ go func() {
+ TestScanPi(t)
+ c <- 0
+ }()
+ }
+ for i := 0; i < n; i++ {
+ <-c
+ }
+}
+
+func BenchmarkScanPi(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ var x nat
+ x.scan(strings.NewReader(pi), 10, false)
+ }
+}
+
+func BenchmarkStringPiParallel(b *testing.B) {
+ var x nat
+ x, _, _, _ = x.scan(strings.NewReader(pi), 0, false)
+ if x.decimalString() != pi {
+ panic("benchmark incorrect: conversion failed")
+ }
+ b.RunParallel(func(pb *testing.PB) {
+ for pb.Next() {
+ x.decimalString()
+ }
+ })
+}
+
+func BenchmarkScan10Base2(b *testing.B) { ScanHelper(b, 2, 10, 10) }
+func BenchmarkScan100Base2(b *testing.B) { ScanHelper(b, 2, 10, 100) }
+func BenchmarkScan1000Base2(b *testing.B) { ScanHelper(b, 2, 10, 1000) }
+func BenchmarkScan10000Base2(b *testing.B) { ScanHelper(b, 2, 10, 10000) }
+func BenchmarkScan100000Base2(b *testing.B) { ScanHelper(b, 2, 10, 100000) }
+
+func BenchmarkScan10Base8(b *testing.B) { ScanHelper(b, 8, 10, 10) }
+func BenchmarkScan100Base8(b *testing.B) { ScanHelper(b, 8, 10, 100) }
+func BenchmarkScan1000Base8(b *testing.B) { ScanHelper(b, 8, 10, 1000) }
+func BenchmarkScan10000Base8(b *testing.B) { ScanHelper(b, 8, 10, 10000) }
+func BenchmarkScan100000Base8(b *testing.B) { ScanHelper(b, 8, 10, 100000) }
+
+func BenchmarkScan10Base10(b *testing.B) { ScanHelper(b, 10, 10, 10) }
+func BenchmarkScan100Base10(b *testing.B) { ScanHelper(b, 10, 10, 100) }
+func BenchmarkScan1000Base10(b *testing.B) { ScanHelper(b, 10, 10, 1000) }
+func BenchmarkScan10000Base10(b *testing.B) { ScanHelper(b, 10, 10, 10000) }
+func BenchmarkScan100000Base10(b *testing.B) { ScanHelper(b, 10, 10, 100000) }
+
+func BenchmarkScan10Base16(b *testing.B) { ScanHelper(b, 16, 10, 10) }
+func BenchmarkScan100Base16(b *testing.B) { ScanHelper(b, 16, 10, 100) }
+func BenchmarkScan1000Base16(b *testing.B) { ScanHelper(b, 16, 10, 1000) }
+func BenchmarkScan10000Base16(b *testing.B) { ScanHelper(b, 16, 10, 10000) }
+func BenchmarkScan100000Base16(b *testing.B) { ScanHelper(b, 16, 10, 100000) }
+
+func ScanHelper(b *testing.B, base int, x, y Word) {
+ b.StopTimer()
+ var z nat
+ z = z.expWW(x, y)
+
+ var s string
+ s = z.string(lowercaseDigits[:base])
+ if t := toString(z, lowercaseDigits[:base]); t != s {
+ b.Fatalf("scanning: got %s; want %s", s, t)
+ }
+ b.StartTimer()
+
+ for i := 0; i < b.N; i++ {
+ z.scan(strings.NewReader(s), base, false)
+ }
+}
+
+func BenchmarkString10Base2(b *testing.B) { StringHelper(b, 2, 10, 10) }
+func BenchmarkString100Base2(b *testing.B) { StringHelper(b, 2, 10, 100) }
+func BenchmarkString1000Base2(b *testing.B) { StringHelper(b, 2, 10, 1000) }
+func BenchmarkString10000Base2(b *testing.B) { StringHelper(b, 2, 10, 10000) }
+func BenchmarkString100000Base2(b *testing.B) { StringHelper(b, 2, 10, 100000) }
+
+func BenchmarkString10Base8(b *testing.B) { StringHelper(b, 8, 10, 10) }
+func BenchmarkString100Base8(b *testing.B) { StringHelper(b, 8, 10, 100) }
+func BenchmarkString1000Base8(b *testing.B) { StringHelper(b, 8, 10, 1000) }
+func BenchmarkString10000Base8(b *testing.B) { StringHelper(b, 8, 10, 10000) }
+func BenchmarkString100000Base8(b *testing.B) { StringHelper(b, 8, 10, 100000) }
+
+func BenchmarkString10Base10(b *testing.B) { StringHelper(b, 10, 10, 10) }
+func BenchmarkString100Base10(b *testing.B) { StringHelper(b, 10, 10, 100) }
+func BenchmarkString1000Base10(b *testing.B) { StringHelper(b, 10, 10, 1000) }
+func BenchmarkString10000Base10(b *testing.B) { StringHelper(b, 10, 10, 10000) }
+func BenchmarkString100000Base10(b *testing.B) { StringHelper(b, 10, 10, 100000) }
+
+func BenchmarkString10Base16(b *testing.B) { StringHelper(b, 16, 10, 10) }
+func BenchmarkString100Base16(b *testing.B) { StringHelper(b, 16, 10, 100) }
+func BenchmarkString1000Base16(b *testing.B) { StringHelper(b, 16, 10, 1000) }
+func BenchmarkString10000Base16(b *testing.B) { StringHelper(b, 16, 10, 10000) }
+func BenchmarkString100000Base16(b *testing.B) { StringHelper(b, 16, 10, 100000) }
+
+func StringHelper(b *testing.B, base int, x, y Word) {
+ b.StopTimer()
+ var z nat
+ z = z.expWW(x, y)
+ z.string(lowercaseDigits[:base]) // warm divisor cache
+ b.StartTimer()
+
+ for i := 0; i < b.N; i++ {
+ _ = z.string(lowercaseDigits[:base])
+ }
+}
+
+func BenchmarkLeafSize0(b *testing.B) { LeafSizeHelper(b, 10, 0) } // test without splitting
+func BenchmarkLeafSize1(b *testing.B) { LeafSizeHelper(b, 10, 1) }
+func BenchmarkLeafSize2(b *testing.B) { LeafSizeHelper(b, 10, 2) }
+func BenchmarkLeafSize3(b *testing.B) { LeafSizeHelper(b, 10, 3) }
+func BenchmarkLeafSize4(b *testing.B) { LeafSizeHelper(b, 10, 4) }
+func BenchmarkLeafSize5(b *testing.B) { LeafSizeHelper(b, 10, 5) }
+func BenchmarkLeafSize6(b *testing.B) { LeafSizeHelper(b, 10, 6) }
+func BenchmarkLeafSize7(b *testing.B) { LeafSizeHelper(b, 10, 7) }
+func BenchmarkLeafSize8(b *testing.B) { LeafSizeHelper(b, 10, 8) }
+func BenchmarkLeafSize9(b *testing.B) { LeafSizeHelper(b, 10, 9) }
+func BenchmarkLeafSize10(b *testing.B) { LeafSizeHelper(b, 10, 10) }
+func BenchmarkLeafSize11(b *testing.B) { LeafSizeHelper(b, 10, 11) }
+func BenchmarkLeafSize12(b *testing.B) { LeafSizeHelper(b, 10, 12) }
+func BenchmarkLeafSize13(b *testing.B) { LeafSizeHelper(b, 10, 13) }
+func BenchmarkLeafSize14(b *testing.B) { LeafSizeHelper(b, 10, 14) }
+func BenchmarkLeafSize15(b *testing.B) { LeafSizeHelper(b, 10, 15) }
+func BenchmarkLeafSize16(b *testing.B) { LeafSizeHelper(b, 10, 16) }
+func BenchmarkLeafSize32(b *testing.B) { LeafSizeHelper(b, 10, 32) } // try some large lengths
+func BenchmarkLeafSize64(b *testing.B) { LeafSizeHelper(b, 10, 64) }
+
+func LeafSizeHelper(b *testing.B, base Word, size int) {
+ b.StopTimer()
+ originalLeafSize := leafSize
+ resetTable(cacheBase10.table[:])
+ leafSize = size
+ b.StartTimer()
+
+ for d := 1; d <= 10000; d *= 10 {
+ b.StopTimer()
+ var z nat
+ z = z.expWW(base, Word(d)) // build target number
+ _ = z.string(lowercaseDigits[:base]) // warm divisor cache
+ b.StartTimer()
+
+ for i := 0; i < b.N; i++ {
+ _ = z.string(lowercaseDigits[:base])
+ }
+ }
+
+ b.StopTimer()
+ resetTable(cacheBase10.table[:])
+ leafSize = originalLeafSize
+ b.StartTimer()
+}
+
+func resetTable(table []divisor) {
+ if table != nil && table[0].bbb != nil {
+ for i := 0; i < len(table); i++ {
+ table[i].bbb = nil
+ table[i].nbits = 0
+ table[i].ndigits = 0
+ }
+ }
+}
+
+func TestStringPowers(t *testing.T) {
+ var b, p Word
+ for b = 2; b <= 16; b++ {
+ for p = 0; p <= 512; p++ {
+ x := nat(nil).expWW(b, p)
+ xs := x.string(lowercaseDigits[:b])
+ xs2 := toString(x, lowercaseDigits[:b])
+ if xs != xs2 {
+ t.Errorf("failed at %d ** %d in base %d: %s != %s", b, p, b, xs, xs2)
+ }
+ }
+ if b >= 3 && testing.Short() {
+ break
+ }
+ }
+}
"errors"
"fmt"
"math"
- "strings"
)
// A Rat represents a quotient a/b of arbitrary precision.
// SetInt sets z to x (by making a copy of x) and returns z.
func (z *Rat) SetInt(x *Int) *Rat {
z.a.Set(x)
- z.b.abs = z.b.abs.make(0)
+ z.b.abs = z.b.abs[:0]
return z
}
// SetInt64 sets z to x and returns z.
func (z *Rat) SetInt64(x int64) *Rat {
z.a.SetInt64(x)
- z.b.abs = z.b.abs.make(0)
+ z.b.abs = z.b.abs[:0]
return z
}
}
b := z.a.abs
if b.cmp(natOne) == 0 {
- b = b.make(0) // normalize denominator
+ b = b[:0] // normalize denominator
}
z.a.abs, z.b.abs = a, b // sign doesn't change
return z
case len(z.a.abs) == 0:
// z == 0 - normalize sign and denominator
z.a.neg = false
- z.b.abs = z.b.abs.make(0)
+ z.b.abs = z.b.abs[:0]
case len(z.b.abs) == 0:
// z is normalized int - nothing to do
case z.b.abs.cmp(natOne) == 0:
// z is int - normalize denominator
- z.b.abs = z.b.abs.make(0)
+ z.b.abs = z.b.abs[:0]
default:
neg := z.a.neg
z.a.neg = false
z.b.abs, _ = z.b.abs.div(nil, z.b.abs, f.abs)
if z.b.abs.cmp(natOne) == 0 {
// z is int - normalize denominator
- z.b.abs = z.b.abs.make(0)
+ z.b.abs = z.b.abs[:0]
}
}
z.a.neg = neg
return z.norm()
}
-func ratTok(ch rune) bool {
- return strings.IndexRune("+-/0123456789.eE", ch) >= 0
-}
-
-// Scan is a support routine for fmt.Scanner. It accepts the formats
-// 'e', 'E', 'f', 'F', 'g', 'G', and 'v'. All formats are equivalent.
-func (z *Rat) Scan(s fmt.ScanState, ch rune) error {
- tok, err := s.Token(true, ratTok)
- if err != nil {
- return err
- }
- if strings.IndexRune("efgEFGv", ch) < 0 {
- return errors.New("Rat.Scan: invalid verb")
- }
- if _, ok := z.SetString(string(tok)); !ok {
- return errors.New("Rat.Scan: invalid syntax")
- }
- return nil
-}
-
-// SetString sets z to the value of s and returns z and a boolean indicating
-// success. s can be given as a fraction "a/b" or as a floating-point number
-// optionally followed by an exponent. If the operation failed, the value of
-// z is undefined but the returned value is nil.
-func (z *Rat) SetString(s string) (*Rat, bool) {
- if len(s) == 0 {
- return nil, false
- }
-
- // check for a quotient
- sep := strings.Index(s, "/")
- if sep >= 0 {
- if _, ok := z.a.SetString(s[0:sep], 10); !ok {
- return nil, false
- }
- s = s[sep+1:]
- var err error
- if z.b.abs, _, err = z.b.abs.scan(strings.NewReader(s), 10); err != nil {
- return nil, false
- }
- if len(z.b.abs) == 0 {
- return nil, false
- }
- return z.norm(), true
- }
-
- // check for a decimal point
- sep = strings.Index(s, ".")
- // check for an exponent
- e := strings.IndexAny(s, "eE")
- var exp Int
- if e >= 0 {
- if e < sep {
- // The E must come after the decimal point.
- return nil, false
- }
- if _, ok := exp.SetString(s[e+1:], 10); !ok {
- return nil, false
- }
- s = s[0:e]
- }
- if sep >= 0 {
- s = s[0:sep] + s[sep+1:]
- exp.Sub(&exp, NewInt(int64(len(s)-sep)))
- }
-
- if _, ok := z.a.SetString(s, 10); !ok {
- return nil, false
- }
- powTen := nat(nil).expNN(natTen, exp.abs, nil)
- if exp.neg {
- z.b.abs = powTen
- z.norm()
- } else {
- z.a.abs = z.a.abs.mul(z.a.abs, powTen)
- z.b.abs = z.b.abs.make(0)
- }
-
- return z, true
-}
-
-// String returns a string representation of x in the form "a/b" (even if b == 1).
-func (x *Rat) String() string {
- s := "/1"
- if len(x.b.abs) != 0 {
- s = "/" + x.b.abs.decimalString()
- }
- return x.a.String() + s
-}
-
-// RatString returns a string representation of x in the form "a/b" if b != 1,
-// and in the form "a" if b == 1.
-func (x *Rat) RatString() string {
- if x.IsInt() {
- return x.a.String()
- }
- return x.String()
-}
-
-// FloatString returns a string representation of x in decimal form with prec
-// digits of precision after the decimal point and the last digit rounded.
-func (x *Rat) FloatString(prec int) string {
- if x.IsInt() {
- s := x.a.String()
- if prec > 0 {
- s += "." + strings.Repeat("0", prec)
- }
- return s
- }
- // x.b.abs != 0
-
- q, r := nat(nil).div(nat(nil), x.a.abs, x.b.abs)
-
- p := natOne
- if prec > 0 {
- p = nat(nil).expNN(natTen, nat(nil).setUint64(uint64(prec)), nil)
- }
-
- r = r.mul(r, p)
- r, r2 := r.div(nat(nil), r, x.b.abs)
-
- // see if we need to round up
- r2 = r2.add(r2, r2)
- if x.b.abs.cmp(r2) <= 0 {
- r = r.add(r, natOne)
- if r.cmp(p) >= 0 {
- q = nat(nil).add(q, natOne)
- r = nat(nil).sub(r, p)
- }
- }
-
- s := q.decimalString()
- if x.a.neg {
- s = "-" + s
- }
-
- if prec > 0 {
- rs := r.decimalString()
- leadingZeros := prec - len(rs)
- s += "." + strings.Repeat("0", leadingZeros) + rs
- }
-
- return s
-}
-
// Gob codec version. Permits backward-compatible changes to the encoding.
const ratGobVersion byte = 1
}
buf := make([]byte, 1+4+(len(x.a.abs)+len(x.b.abs))*_S) // extra bytes for version and sign bit (1), and numerator length (4)
i := x.b.abs.bytes(buf)
- j := x.a.abs.bytes(buf[0:i])
+ j := x.a.abs.bytes(buf[:i])
n := i - j
if int(uint32(n)) != n {
// this should never happen
"encoding/gob"
"encoding/json"
"encoding/xml"
- "fmt"
"math"
- "strconv"
- "strings"
"testing"
)
z.Quo(&x, &y)
}
-var setStringTests = []struct {
- in, out string
- ok bool
-}{
- {"0", "0", true},
- {"-0", "0", true},
- {"1", "1", true},
- {"-1", "-1", true},
- {"1.", "1", true},
- {"1e0", "1", true},
- {"1.e1", "10", true},
- {in: "1e", ok: false},
- {in: "1.e", ok: false},
- {in: "1e+14e-5", ok: false},
- {in: "1e4.5", ok: false},
- {in: "r", ok: false},
- {in: "a/b", ok: false},
- {in: "a.b", ok: false},
- {"-0.1", "-1/10", true},
- {"-.1", "-1/10", true},
- {"2/4", "1/2", true},
- {".25", "1/4", true},
- {"-1/5", "-1/5", true},
- {"8129567.7690E14", "812956776900000000000", true},
- {"78189e+4", "781890000", true},
- {"553019.8935e+8", "55301989350000", true},
- {"98765432109876543210987654321e-10", "98765432109876543210987654321/10000000000", true},
- {"9877861857500000E-7", "3951144743/4", true},
- {"2169378.417e-3", "2169378417/1000000", true},
- {"884243222337379604041632732738665534", "884243222337379604041632732738665534", true},
- {"53/70893980658822810696", "53/70893980658822810696", true},
- {"106/141787961317645621392", "53/70893980658822810696", true},
- {"204211327800791583.81095", "4084226556015831676219/20000", true},
- {in: "1/0", ok: false},
-}
-
-func TestRatSetString(t *testing.T) {
- for i, test := range setStringTests {
- x, ok := new(Rat).SetString(test.in)
-
- if ok {
- if !test.ok {
- t.Errorf("#%d SetString(%q) expected failure", i, test.in)
- } else if x.RatString() != test.out {
- t.Errorf("#%d SetString(%q) got %s want %s", i, test.in, x.RatString(), test.out)
- }
- } else if x != nil {
- t.Errorf("#%d SetString(%q) got %p want nil", i, test.in, x)
- }
- }
-}
-
-func TestRatScan(t *testing.T) {
- var buf bytes.Buffer
- for i, test := range setStringTests {
- x := new(Rat)
- buf.Reset()
- buf.WriteString(test.in)
-
- _, err := fmt.Fscanf(&buf, "%v", x)
- if err == nil != test.ok {
- if test.ok {
- t.Errorf("#%d error: %s", i, err)
- } else {
- t.Errorf("#%d expected error", i)
- }
- continue
- }
- if err == nil && x.RatString() != test.out {
- t.Errorf("#%d got %s want %s", i, x.RatString(), test.out)
- }
- }
-}
-
-var floatStringTests = []struct {
- in string
- prec int
- out string
-}{
- {"0", 0, "0"},
- {"0", 4, "0.0000"},
- {"1", 0, "1"},
- {"1", 2, "1.00"},
- {"-1", 0, "-1"},
- {".25", 2, "0.25"},
- {".25", 1, "0.3"},
- {".25", 3, "0.250"},
- {"-1/3", 3, "-0.333"},
- {"-2/3", 4, "-0.6667"},
- {"0.96", 1, "1.0"},
- {"0.999", 2, "1.00"},
- {"0.9", 0, "1"},
- {".25", -1, "0"},
- {".55", -1, "1"},
-}
-
-func TestFloatString(t *testing.T) {
- for i, test := range floatStringTests {
- x, _ := new(Rat).SetString(test.in)
-
- if x.FloatString(test.prec) != test.out {
- t.Errorf("#%d got %s want %s", i, x.FloatString(test.prec), test.out)
- }
- }
-}
-
func TestRatSign(t *testing.T) {
zero := NewRat(0, 1)
for _, a := range setStringTests {
}
}
-// Test inputs to Rat.SetString. The prefix "long:" causes the test
-// to be skipped in --test.short mode. (The threshold is about 500us.)
-var float64inputs = []string{
- // Constants plundered from strconv/testfp.txt.
-
- // Table 1: Stress Inputs for Conversion to 53-bit Binary, < 1/2 ULP
- "5e+125",
- "69e+267",
- "999e-026",
- "7861e-034",
- "75569e-254",
- "928609e-261",
- "9210917e+080",
- "84863171e+114",
- "653777767e+273",
- "5232604057e-298",
- "27235667517e-109",
- "653532977297e-123",
- "3142213164987e-294",
- "46202199371337e-072",
- "231010996856685e-073",
- "9324754620109615e+212",
- "78459735791271921e+049",
- "272104041512242479e+200",
- "6802601037806061975e+198",
- "20505426358836677347e-221",
- "836168422905420598437e-234",
- "4891559871276714924261e+222",
-
- // Table 2: Stress Inputs for Conversion to 53-bit Binary, > 1/2 ULP
- "9e-265",
- "85e-037",
- "623e+100",
- "3571e+263",
- "81661e+153",
- "920657e-023",
- "4603285e-024",
- "87575437e-309",
- "245540327e+122",
- "6138508175e+120",
- "83356057653e+193",
- "619534293513e+124",
- "2335141086879e+218",
- "36167929443327e-159",
- "609610927149051e-255",
- "3743626360493413e-165",
- "94080055902682397e-242",
- "899810892172646163e+283",
- "7120190517612959703e+120",
- "25188282901709339043e-252",
- "308984926168550152811e-052",
- "6372891218502368041059e+064",
-
- // Table 14: Stress Inputs for Conversion to 24-bit Binary, <1/2 ULP
- "5e-20",
- "67e+14",
- "985e+15",
- "7693e-42",
- "55895e-16",
- "996622e-44",
- "7038531e-32",
- "60419369e-46",
- "702990899e-20",
- "6930161142e-48",
- "25933168707e+13",
- "596428896559e+20",
-
- // Table 15: Stress Inputs for Conversion to 24-bit Binary, >1/2 ULP
- "3e-23",
- "57e+18",
- "789e-35",
- "2539e-18",
- "76173e+28",
- "887745e-11",
- "5382571e-37",
- "82381273e-35",
- "750486563e-38",
- "3752432815e-39",
- "75224575729e-45",
- "459926601011e+15",
-
- // Constants plundered from strconv/atof_test.go.
-
- "0",
- "1",
- "+1",
- "1e23",
- "1E23",
- "100000000000000000000000",
- "1e-100",
- "123456700",
- "99999999999999974834176",
- "100000000000000000000001",
- "100000000000000008388608",
- "100000000000000016777215",
- "100000000000000016777216",
- "-1",
- "-0.1",
- "-0", // NB: exception made for this input
- "1e-20",
- "625e-3",
-
- // largest float64
- "1.7976931348623157e308",
- "-1.7976931348623157e308",
- // next float64 - too large
- "1.7976931348623159e308",
- "-1.7976931348623159e308",
- // the border is ...158079
- // borderline - okay
- "1.7976931348623158e308",
- "-1.7976931348623158e308",
- // borderline - too large
- "1.797693134862315808e308",
- "-1.797693134862315808e308",
-
- // a little too large
- "1e308",
- "2e308",
- "1e309",
-
- // way too large
- "1e310",
- "-1e310",
- "1e400",
- "-1e400",
- "long:1e400000",
- "long:-1e400000",
-
- // denormalized
- "1e-305",
- "1e-306",
- "1e-307",
- "1e-308",
- "1e-309",
- "1e-310",
- "1e-322",
- // smallest denormal
- "5e-324",
- "4e-324",
- "3e-324",
- // too small
- "2e-324",
- // way too small
- "1e-350",
- "long:1e-400000",
- // way too small, negative
- "-1e-350",
- "long:-1e-400000",
-
- // try to overflow exponent
- // [Disabled: too slow and memory-hungry with rationals.]
- // "1e-4294967296",
- // "1e+4294967296",
- // "1e-18446744073709551616",
- // "1e+18446744073709551616",
-
- // http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
- "2.2250738585072012e-308",
- // http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
- "2.2250738585072011e-308",
-
- // A very large number (initially wrongly parsed by the fast algorithm).
- "4.630813248087435e+307",
-
- // A different kind of very large number.
- "22.222222222222222",
- "long:2." + strings.Repeat("2", 4000) + "e+1",
-
- // Exactly halfway between 1 and math.Nextafter(1, 2).
- // Round to even (down).
- "1.00000000000000011102230246251565404236316680908203125",
- // Slightly lower; still round down.
- "1.00000000000000011102230246251565404236316680908203124",
- // Slightly higher; round up.
- "1.00000000000000011102230246251565404236316680908203126",
- // Slightly higher, but you have to read all the way to the end.
- "long:1.00000000000000011102230246251565404236316680908203125" + strings.Repeat("0", 10000) + "1",
-
- // Smallest denormal, 2^(-1022-52)
- "4.940656458412465441765687928682213723651e-324",
- // Half of smallest denormal, 2^(-1022-53)
- "2.470328229206232720882843964341106861825e-324",
- // A little more than the exact half of smallest denormal
- // 2^-1075 + 2^-1100. (Rounds to 1p-1074.)
- "2.470328302827751011111470718709768633275e-324",
- // The exact halfway between smallest normal and largest denormal:
- // 2^-1022 - 2^-1075. (Rounds to 2^-1022.)
- "2.225073858507201136057409796709131975935e-308",
-
- "1152921504606846975", // 1<<60 - 1
- "-1152921504606846975", // -(1<<60 - 1)
- "1152921504606846977", // 1<<60 + 1
- "-1152921504606846977", // -(1<<60 + 1)
-
- "1/3",
-}
-
-// isFinite reports whether f represents a finite rational value.
-// It is equivalent to !math.IsNan(f) && !math.IsInf(f, 0).
-func isFinite(f float64) bool {
- return math.Abs(f) <= math.MaxFloat64
-}
-
-func TestFloat32SpecialCases(t *testing.T) {
- for _, input := range float64inputs {
- if strings.HasPrefix(input, "long:") {
- if testing.Short() {
- continue
- }
- input = input[len("long:"):]
- }
-
- r, ok := new(Rat).SetString(input)
- if !ok {
- t.Errorf("Rat.SetString(%q) failed", input)
- continue
- }
- f, exact := r.Float32()
-
- // 1. Check string -> Rat -> float32 conversions are
- // consistent with strconv.ParseFloat.
- // Skip this check if the input uses "a/b" rational syntax.
- if !strings.Contains(input, "/") {
- e64, _ := strconv.ParseFloat(input, 32)
- e := float32(e64)
-
- // Careful: negative Rats too small for
- // float64 become -0, but Rat obviously cannot
- // preserve the sign from SetString("-0").
- switch {
- case math.Float32bits(e) == math.Float32bits(f):
- // Ok: bitwise equal.
- case f == 0 && r.Num().BitLen() == 0:
- // Ok: Rat(0) is equivalent to both +/- float64(0).
- default:
- t.Errorf("strconv.ParseFloat(%q) = %g (%b), want %g (%b); delta = %g", input, e, e, f, f, f-e)
- }
- }
-
- if !isFinite(float64(f)) {
- continue
- }
-
- // 2. Check f is best approximation to r.
- if !checkIsBestApprox32(t, f, r) {
- // Append context information.
- t.Errorf("(input was %q)", input)
- }
-
- // 3. Check f->R->f roundtrip is non-lossy.
- checkNonLossyRoundtrip32(t, f)
-
- // 4. Check exactness using slow algorithm.
- if wasExact := new(Rat).SetFloat64(float64(f)).Cmp(r) == 0; wasExact != exact {
- t.Errorf("Rat.SetString(%q).Float32().exact = %t, want %t", input, exact, wasExact)
- }
- }
-}
-
-func TestFloat64SpecialCases(t *testing.T) {
- for _, input := range float64inputs {
- if strings.HasPrefix(input, "long:") {
- if testing.Short() {
- continue
- }
- input = input[len("long:"):]
- }
-
- r, ok := new(Rat).SetString(input)
- if !ok {
- t.Errorf("Rat.SetString(%q) failed", input)
- continue
- }
- f, exact := r.Float64()
-
- // 1. Check string -> Rat -> float64 conversions are
- // consistent with strconv.ParseFloat.
- // Skip this check if the input uses "a/b" rational syntax.
- if !strings.Contains(input, "/") {
- e, _ := strconv.ParseFloat(input, 64)
-
- // Careful: negative Rats too small for
- // float64 become -0, but Rat obviously cannot
- // preserve the sign from SetString("-0").
- switch {
- case math.Float64bits(e) == math.Float64bits(f):
- // Ok: bitwise equal.
- case f == 0 && r.Num().BitLen() == 0:
- // Ok: Rat(0) is equivalent to both +/- float64(0).
- default:
- t.Errorf("strconv.ParseFloat(%q) = %g (%b), want %g (%b); delta = %g", input, e, e, f, f, f-e)
- }
- }
-
- if !isFinite(f) {
- continue
- }
-
- // 2. Check f is best approximation to r.
- if !checkIsBestApprox64(t, f, r) {
- // Append context information.
- t.Errorf("(input was %q)", input)
- }
-
- // 3. Check f->R->f roundtrip is non-lossy.
- checkNonLossyRoundtrip64(t, f)
-
- // 4. Check exactness using slow algorithm.
- if wasExact := new(Rat).SetFloat64(f).Cmp(r) == 0; wasExact != exact {
- t.Errorf("Rat.SetString(%q).Float64().exact = %t, want %t", input, exact, wasExact)
- }
- }
-}
-
func TestFloat32Distribution(t *testing.T) {
// Generate a distribution of (sign, mantissa, exp) values
// broader than the float32 range, and check Rat.Float32()
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements rat-to-string conversion functions.
+
+package big
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "strconv"
+ "strings"
+)
+
+func ratTok(ch rune) bool {
+ return strings.IndexRune("+-/0123456789.eE", ch) >= 0
+}
+
+// Scan is a support routine for fmt.Scanner. It accepts the formats
+// 'e', 'E', 'f', 'F', 'g', 'G', and 'v'. All formats are equivalent.
+func (z *Rat) Scan(s fmt.ScanState, ch rune) error {
+ tok, err := s.Token(true, ratTok)
+ if err != nil {
+ return err
+ }
+ if strings.IndexRune("efgEFGv", ch) < 0 {
+ return errors.New("Rat.Scan: invalid verb")
+ }
+ if _, ok := z.SetString(string(tok)); !ok {
+ return errors.New("Rat.Scan: invalid syntax")
+ }
+ return nil
+}
+
+// SetString sets z to the value of s and returns z and a boolean indicating
+// success. s can be given as a fraction "a/b" or as a floating-point number
+// optionally followed by an exponent. If the operation failed, the value of
+// z is undefined but the returned value is nil.
+func (z *Rat) SetString(s string) (*Rat, bool) {
+ if len(s) == 0 {
+ return nil, false
+ }
+ // len(s) > 0
+
+ // parse fraction a/b, if any
+ if sep := strings.Index(s, "/"); sep >= 0 {
+ if _, ok := z.a.SetString(s[:sep], 0); !ok {
+ return nil, false
+ }
+ s = s[sep+1:]
+ var err error
+ if z.b.abs, _, _, err = z.b.abs.scan(strings.NewReader(s), 0, false); err != nil {
+ return nil, false
+ }
+ if len(z.b.abs) == 0 {
+ return nil, false
+ }
+ return z.norm(), true
+ }
+
+ // parse floating-point number
+ r := strings.NewReader(s)
+
+ // sign
+ neg, err := scanSign(r)
+ if err != nil {
+ return nil, false
+ }
+
+ // mantissa
+ var ecorr int
+ z.a.abs, _, ecorr, err = z.a.abs.scan(r, 10, true)
+ if err != nil {
+ return nil, false
+ }
+
+ // exponent
+ var exp int64
+ var ebase int
+ exp, ebase, err = scanExponent(r)
+ if ebase == 2 || err != nil {
+ return nil, false
+ }
+
+ // there should be no unread characters left
+ if _, err = r.ReadByte(); err != io.EOF {
+ return nil, false
+ }
+
+ // correct exponent
+ if ecorr < 0 {
+ exp += int64(ecorr)
+ }
+
+ // compute exponent power
+ expabs := exp
+ if expabs < 0 {
+ expabs = -expabs
+ }
+ powTen := nat(nil).expNN(natTen, nat(nil).setWord(Word(expabs)), nil)
+
+ // complete fraction
+ if exp < 0 {
+ z.b.abs = powTen
+ z.norm()
+ } else {
+ z.a.abs = z.a.abs.mul(z.a.abs, powTen)
+ z.b.abs = z.b.abs[:0]
+ }
+
+ z.a.neg = neg && len(z.a.abs) > 0 // 0 has no sign
+
+ return z, true
+}
+
+func scanExponent(r io.ByteScanner) (exp int64, base int, err error) {
+ base = 10
+
+ var ch byte
+ if ch, err = r.ReadByte(); err != nil {
+ if err == io.EOF {
+ err = nil // no exponent; same as e0
+ }
+ return
+ }
+
+ switch ch {
+ case 'e', 'E':
+ // ok
+ case 'p':
+ base = 2
+ default:
+ r.UnreadByte()
+ return // no exponent; same as e0
+ }
+
+ var neg bool
+ if neg, err = scanSign(r); err != nil {
+ return
+ }
+
+ var digits []byte
+ if neg {
+ digits = append(digits, '-')
+ }
+
+ // no need to use nat.scan for exponent digits
+ // since we only care about int64 values - the
+ // from-scratch scan is easy enough and faster
+ for i := 0; ; i++ {
+ if ch, err = r.ReadByte(); err != nil {
+ if err != io.EOF || i == 0 {
+ return
+ }
+ err = nil
+ break // i > 0
+ }
+ if ch < '0' || '9' < ch {
+ if i == 0 {
+ r.UnreadByte()
+ err = fmt.Errorf("invalid exponent (missing digits)")
+ return
+ }
+ break // i > 0
+ }
+ digits = append(digits, byte(ch))
+ }
+ // i > 0 => we have at least one digit
+
+ exp, err = strconv.ParseInt(string(digits), 10, 64)
+ return
+}
+
+// String returns a string representation of x in the form "a/b" (even if b == 1).
+func (x *Rat) String() string {
+ s := "/1"
+ if len(x.b.abs) != 0 {
+ s = "/" + x.b.abs.decimalString()
+ }
+ return x.a.String() + s
+}
+
+// RatString returns a string representation of x in the form "a/b" if b != 1,
+// and in the form "a" if b == 1.
+func (x *Rat) RatString() string {
+ if x.IsInt() {
+ return x.a.String()
+ }
+ return x.String()
+}
+
+// FloatString returns a string representation of x in decimal form with prec
+// digits of precision after the decimal point and the last digit rounded.
+func (x *Rat) FloatString(prec int) string {
+ if x.IsInt() {
+ s := x.a.String()
+ if prec > 0 {
+ s += "." + strings.Repeat("0", prec)
+ }
+ return s
+ }
+ // x.b.abs != 0
+
+ q, r := nat(nil).div(nat(nil), x.a.abs, x.b.abs)
+
+ p := natOne
+ if prec > 0 {
+ p = nat(nil).expNN(natTen, nat(nil).setUint64(uint64(prec)), nil)
+ }
+
+ r = r.mul(r, p)
+ r, r2 := r.div(nat(nil), r, x.b.abs)
+
+ // see if we need to round up
+ r2 = r2.add(r2, r2)
+ if x.b.abs.cmp(r2) <= 0 {
+ r = r.add(r, natOne)
+ if r.cmp(p) >= 0 {
+ q = nat(nil).add(q, natOne)
+ r = nat(nil).sub(r, p)
+ }
+ }
+
+ s := q.decimalString()
+ if x.a.neg {
+ s = "-" + s
+ }
+
+ if prec > 0 {
+ rs := r.decimalString()
+ leadingZeros := prec - len(rs)
+ s += "." + strings.Repeat("0", leadingZeros) + rs
+ }
+
+ return s
+}
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package big
+
+import (
+ "bytes"
+ "fmt"
+ "math"
+ "strconv"
+ "strings"
+ "testing"
+)
+
+type StringTest struct {
+ in, out string
+ ok bool
+}
+
+var setStringTests = []StringTest{
+ {"0", "0", true},
+ {"-0", "0", true},
+ {"1", "1", true},
+ {"-1", "-1", true},
+ {"1.", "1", true},
+ {"1e0", "1", true},
+ {"1.e1", "10", true},
+ {in: "1e"},
+ {in: "1.e"},
+ {in: "1e+14e-5"},
+ {in: "1e4.5"},
+ {in: "r"},
+ {in: "a/b"},
+ {in: "a.b"},
+ {"-0.1", "-1/10", true},
+ {"-.1", "-1/10", true},
+ {"2/4", "1/2", true},
+ {".25", "1/4", true},
+ {"-1/5", "-1/5", true},
+ {"8129567.7690E14", "812956776900000000000", true},
+ {"78189e+4", "781890000", true},
+ {"553019.8935e+8", "55301989350000", true},
+ {"98765432109876543210987654321e-10", "98765432109876543210987654321/10000000000", true},
+ {"9877861857500000E-7", "3951144743/4", true},
+ {"2169378.417e-3", "2169378417/1000000", true},
+ {"884243222337379604041632732738665534", "884243222337379604041632732738665534", true},
+ {"53/70893980658822810696", "53/70893980658822810696", true},
+ {"106/141787961317645621392", "53/70893980658822810696", true},
+ {"204211327800791583.81095", "4084226556015831676219/20000", true},
+ {in: "1/0"},
+}
+
+// These are not supported by fmt.Fscanf.
+var setStringTests2 = []StringTest{
+ {"0x10", "16", true},
+ {"-010/1", "-8", true}, // TODO(gri) should we even permit octal here?
+ {"-010.", "-10", true},
+ {"0x10/0x20", "1/2", true},
+ {"0b1000/3", "8/3", true},
+ // TODO(gri) add more tests
+}
+
+func TestRatSetString(t *testing.T) {
+ var tests []StringTest
+ tests = append(tests, setStringTests...)
+ tests = append(tests, setStringTests2...)
+
+ for i, test := range tests {
+ x, ok := new(Rat).SetString(test.in)
+
+ if ok {
+ if !test.ok {
+ t.Errorf("#%d SetString(%q) expected failure", i, test.in)
+ } else if x.RatString() != test.out {
+ t.Errorf("#%d SetString(%q) got %s want %s", i, test.in, x.RatString(), test.out)
+ }
+ } else if x != nil {
+ t.Errorf("#%d SetString(%q) got %p want nil", i, test.in, x)
+ }
+ }
+}
+
+func TestRatScan(t *testing.T) {
+ var buf bytes.Buffer
+ for i, test := range setStringTests {
+ x := new(Rat)
+ buf.Reset()
+ buf.WriteString(test.in)
+
+ _, err := fmt.Fscanf(&buf, "%v", x)
+ if err == nil != test.ok {
+ if test.ok {
+ t.Errorf("#%d (%s) error: %s", i, test.in, err)
+ } else {
+ t.Errorf("#%d (%s) expected error", i, test.in)
+ }
+ continue
+ }
+ if err == nil && x.RatString() != test.out {
+ t.Errorf("#%d got %s want %s", i, x.RatString(), test.out)
+ }
+ }
+}
+
+var floatStringTests = []struct {
+ in string
+ prec int
+ out string
+}{
+ {"0", 0, "0"},
+ {"0", 4, "0.0000"},
+ {"1", 0, "1"},
+ {"1", 2, "1.00"},
+ {"-1", 0, "-1"},
+ {".25", 2, "0.25"},
+ {".25", 1, "0.3"},
+ {".25", 3, "0.250"},
+ {"-1/3", 3, "-0.333"},
+ {"-2/3", 4, "-0.6667"},
+ {"0.96", 1, "1.0"},
+ {"0.999", 2, "1.00"},
+ {"0.9", 0, "1"},
+ {".25", -1, "0"},
+ {".55", -1, "1"},
+}
+
+func TestFloatString(t *testing.T) {
+ for i, test := range floatStringTests {
+ x, _ := new(Rat).SetString(test.in)
+
+ if x.FloatString(test.prec) != test.out {
+ t.Errorf("#%d got %s want %s", i, x.FloatString(test.prec), test.out)
+ }
+ }
+}
+
+// Test inputs to Rat.SetString. The prefix "long:" causes the test
+// to be skipped in --test.short mode. (The threshold is about 500us.)
+var float64inputs = []string{
+ // Constants plundered from strconv/testfp.txt.
+
+ // Table 1: Stress Inputs for Conversion to 53-bit Binary, < 1/2 ULP
+ "5e+125",
+ "69e+267",
+ "999e-026",
+ "7861e-034",
+ "75569e-254",
+ "928609e-261",
+ "9210917e+080",
+ "84863171e+114",
+ "653777767e+273",
+ "5232604057e-298",
+ "27235667517e-109",
+ "653532977297e-123",
+ "3142213164987e-294",
+ "46202199371337e-072",
+ "231010996856685e-073",
+ "9324754620109615e+212",
+ "78459735791271921e+049",
+ "272104041512242479e+200",
+ "6802601037806061975e+198",
+ "20505426358836677347e-221",
+ "836168422905420598437e-234",
+ "4891559871276714924261e+222",
+
+ // Table 2: Stress Inputs for Conversion to 53-bit Binary, > 1/2 ULP
+ "9e-265",
+ "85e-037",
+ "623e+100",
+ "3571e+263",
+ "81661e+153",
+ "920657e-023",
+ "4603285e-024",
+ "87575437e-309",
+ "245540327e+122",
+ "6138508175e+120",
+ "83356057653e+193",
+ "619534293513e+124",
+ "2335141086879e+218",
+ "36167929443327e-159",
+ "609610927149051e-255",
+ "3743626360493413e-165",
+ "94080055902682397e-242",
+ "899810892172646163e+283",
+ "7120190517612959703e+120",
+ "25188282901709339043e-252",
+ "308984926168550152811e-052",
+ "6372891218502368041059e+064",
+
+ // Table 14: Stress Inputs for Conversion to 24-bit Binary, <1/2 ULP
+ "5e-20",
+ "67e+14",
+ "985e+15",
+ "7693e-42",
+ "55895e-16",
+ "996622e-44",
+ "7038531e-32",
+ "60419369e-46",
+ "702990899e-20",
+ "6930161142e-48",
+ "25933168707e+13",
+ "596428896559e+20",
+
+ // Table 15: Stress Inputs for Conversion to 24-bit Binary, >1/2 ULP
+ "3e-23",
+ "57e+18",
+ "789e-35",
+ "2539e-18",
+ "76173e+28",
+ "887745e-11",
+ "5382571e-37",
+ "82381273e-35",
+ "750486563e-38",
+ "3752432815e-39",
+ "75224575729e-45",
+ "459926601011e+15",
+
+ // Constants plundered from strconv/atof_test.go.
+
+ "0",
+ "1",
+ "+1",
+ "1e23",
+ "1E23",
+ "100000000000000000000000",
+ "1e-100",
+ "123456700",
+ "99999999999999974834176",
+ "100000000000000000000001",
+ "100000000000000008388608",
+ "100000000000000016777215",
+ "100000000000000016777216",
+ "-1",
+ "-0.1",
+ "-0", // NB: exception made for this input
+ "1e-20",
+ "625e-3",
+
+ // largest float64
+ "1.7976931348623157e308",
+ "-1.7976931348623157e308",
+ // next float64 - too large
+ "1.7976931348623159e308",
+ "-1.7976931348623159e308",
+ // the border is ...158079
+ // borderline - okay
+ "1.7976931348623158e308",
+ "-1.7976931348623158e308",
+ // borderline - too large
+ "1.797693134862315808e308",
+ "-1.797693134862315808e308",
+
+ // a little too large
+ "1e308",
+ "2e308",
+ "1e309",
+
+ // way too large
+ "1e310",
+ "-1e310",
+ "1e400",
+ "-1e400",
+ "long:1e400000",
+ "long:-1e400000",
+
+ // denormalized
+ "1e-305",
+ "1e-306",
+ "1e-307",
+ "1e-308",
+ "1e-309",
+ "1e-310",
+ "1e-322",
+ // smallest denormal
+ "5e-324",
+ "4e-324",
+ "3e-324",
+ // too small
+ "2e-324",
+ // way too small
+ "1e-350",
+ "long:1e-400000",
+ // way too small, negative
+ "-1e-350",
+ "long:-1e-400000",
+
+ // try to overflow exponent
+ // [Disabled: too slow and memory-hungry with rationals.]
+ // "1e-4294967296",
+ // "1e+4294967296",
+ // "1e-18446744073709551616",
+ // "1e+18446744073709551616",
+
+ // http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
+ "2.2250738585072012e-308",
+ // http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
+ "2.2250738585072011e-308",
+
+ // A very large number (initially wrongly parsed by the fast algorithm).
+ "4.630813248087435e+307",
+
+ // A different kind of very large number.
+ "22.222222222222222",
+ "long:2." + strings.Repeat("2", 4000) + "e+1",
+
+ // Exactly halfway between 1 and math.Nextafter(1, 2).
+ // Round to even (down).
+ "1.00000000000000011102230246251565404236316680908203125",
+ // Slightly lower; still round down.
+ "1.00000000000000011102230246251565404236316680908203124",
+ // Slightly higher; round up.
+ "1.00000000000000011102230246251565404236316680908203126",
+ // Slightly higher, but you have to read all the way to the end.
+ "long:1.00000000000000011102230246251565404236316680908203125" + strings.Repeat("0", 10000) + "1",
+
+ // Smallest denormal, 2^(-1022-52)
+ "4.940656458412465441765687928682213723651e-324",
+ // Half of smallest denormal, 2^(-1022-53)
+ "2.470328229206232720882843964341106861825e-324",
+ // A little more than the exact half of smallest denormal
+ // 2^-1075 + 2^-1100. (Rounds to 1p-1074.)
+ "2.470328302827751011111470718709768633275e-324",
+ // The exact halfway between smallest normal and largest denormal:
+ // 2^-1022 - 2^-1075. (Rounds to 2^-1022.)
+ "2.225073858507201136057409796709131975935e-308",
+
+ "1152921504606846975", // 1<<60 - 1
+ "-1152921504606846975", // -(1<<60 - 1)
+ "1152921504606846977", // 1<<60 + 1
+ "-1152921504606846977", // -(1<<60 + 1)
+
+ "1/3",
+}
+
+// isFinite reports whether f represents a finite rational value.
+// It is equivalent to !math.IsNan(f) && !math.IsInf(f, 0).
+func isFinite(f float64) bool {
+ return math.Abs(f) <= math.MaxFloat64
+}
+
+func TestFloat32SpecialCases(t *testing.T) {
+ for _, input := range float64inputs {
+ if strings.HasPrefix(input, "long:") {
+ if testing.Short() {
+ continue
+ }
+ input = input[len("long:"):]
+ }
+
+ r, ok := new(Rat).SetString(input)
+ if !ok {
+ t.Errorf("Rat.SetString(%q) failed", input)
+ continue
+ }
+ f, exact := r.Float32()
+
+ // 1. Check string -> Rat -> float32 conversions are
+ // consistent with strconv.ParseFloat.
+ // Skip this check if the input uses "a/b" rational syntax.
+ if !strings.Contains(input, "/") {
+ e64, _ := strconv.ParseFloat(input, 32)
+ e := float32(e64)
+
+ // Careful: negative Rats too small for
+ // float64 become -0, but Rat obviously cannot
+ // preserve the sign from SetString("-0").
+ switch {
+ case math.Float32bits(e) == math.Float32bits(f):
+ // Ok: bitwise equal.
+ case f == 0 && r.Num().BitLen() == 0:
+ // Ok: Rat(0) is equivalent to both +/- float64(0).
+ default:
+ t.Errorf("strconv.ParseFloat(%q) = %g (%b), want %g (%b); delta = %g", input, e, e, f, f, f-e)
+ }
+ }
+
+ if !isFinite(float64(f)) {
+ continue
+ }
+
+ // 2. Check f is best approximation to r.
+ if !checkIsBestApprox32(t, f, r) {
+ // Append context information.
+ t.Errorf("(input was %q)", input)
+ }
+
+ // 3. Check f->R->f roundtrip is non-lossy.
+ checkNonLossyRoundtrip32(t, f)
+
+ // 4. Check exactness using slow algorithm.
+ if wasExact := new(Rat).SetFloat64(float64(f)).Cmp(r) == 0; wasExact != exact {
+ t.Errorf("Rat.SetString(%q).Float32().exact = %t, want %t", input, exact, wasExact)
+ }
+ }
+}
+
+func TestFloat64SpecialCases(t *testing.T) {
+ for _, input := range float64inputs {
+ if strings.HasPrefix(input, "long:") {
+ if testing.Short() {
+ continue
+ }
+ input = input[len("long:"):]
+ }
+
+ r, ok := new(Rat).SetString(input)
+ if !ok {
+ t.Errorf("Rat.SetString(%q) failed", input)
+ continue
+ }
+ f, exact := r.Float64()
+
+ // 1. Check string -> Rat -> float64 conversions are
+ // consistent with strconv.ParseFloat.
+ // Skip this check if the input uses "a/b" rational syntax.
+ if !strings.Contains(input, "/") {
+ e, _ := strconv.ParseFloat(input, 64)
+
+ // Careful: negative Rats too small for
+ // float64 become -0, but Rat obviously cannot
+ // preserve the sign from SetString("-0").
+ switch {
+ case math.Float64bits(e) == math.Float64bits(f):
+ // Ok: bitwise equal.
+ case f == 0 && r.Num().BitLen() == 0:
+ // Ok: Rat(0) is equivalent to both +/- float64(0).
+ default:
+ t.Errorf("strconv.ParseFloat(%q) = %g (%b), want %g (%b); delta = %g", input, e, e, f, f, f-e)
+ }
+ }
+
+ if !isFinite(f) {
+ continue
+ }
+
+ // 2. Check f is best approximation to r.
+ if !checkIsBestApprox64(t, f, r) {
+ // Append context information.
+ t.Errorf("(input was %q)", input)
+ }
+
+ // 3. Check f->R->f roundtrip is non-lossy.
+ checkNonLossyRoundtrip64(t, f)
+
+ // 4. Check exactness using slow algorithm.
+ if wasExact := new(Rat).SetFloat64(f).Cmp(r) == 0; wasExact != exact {
+ t.Errorf("Rat.SetString(%q).Float64().exact = %t, want %t", input, exact, wasExact)
+ }
+ }
+}
// license that can be found in the LICENSE file.
// +build !netgo
-// +build darwin dragonfly freebsd solaris
+// +build darwin dragonfly freebsd
package net
return "", &DNSError{Err: "unrecognized address", Name: addr}
}
if ip.To4() != nil {
- return itoa(int(ip[15])) + "." + itoa(int(ip[14])) + "." + itoa(int(ip[13])) + "." +
- itoa(int(ip[12])) + ".in-addr.arpa.", nil
+ return uitoa(uint(ip[15])) + "." + uitoa(uint(ip[14])) + "." + uitoa(uint(ip[13])) + "." +
+ uitoa(uint(ip[12])) + ".in-addr.arpa.", nil
}
// Must be IPv6
buf := make([]byte, 0, len(ip)*4+len("ip6.arpa."))
continue
}
h := rr.Header()
- if h.Class == dnsClassINET && h.Name == name {
+ if h.Class == dnsClassINET && equalASCIILabel(h.Name, name) {
switch h.Rrtype {
case qtype:
addrs = append(addrs, rr)
return "", nil, &DNSError{Err: "too many redirects", Name: name, Server: server}
}
+func equalASCIILabel(x, y string) bool {
+ if len(x) != len(y) {
+ return false
+ }
+ for i := 0; i < len(x); i++ {
+ a := x[i]
+ b := y[i]
+ if 'A' <= a && a <= 'Z' {
+ a += 0x20
+ }
+ if 'A' <= b && b <= 'Z' {
+ b += 0x20
+ }
+ if a != b {
+ return false
+ }
+ }
+ return true
+}
+
func isDomainName(s string) bool {
// See RFC 1035, RFC 3696.
if len(s) == 0 {
msg := new(dnsMsg)
ok := msg.Unpack(data)
if !ok {
- t.Fatalf("unpacking packet failed")
+ t.Fatal("unpacking packet failed")
}
msg.String() // exercise this code path
if g, e := len(msg.answer), 5; g != e {
t.Errorf("answer[%d] = %T; want *dnsRR_SRV", idx, rr)
}
}
- _, addrs, err := answer("_xmpp-server._tcp.google.com.", "foo:53", msg, uint16(dnsTypeSRV))
- if err != nil {
- t.Fatalf("answer: %v", err)
- }
- if g, e := len(addrs), 5; g != e {
- t.Errorf("len(addrs) = %d; want %d", g, e)
- t.Logf("addrs = %#v", addrs)
+ for _, name := range [...]string{
+ "_xmpp-server._tcp.google.com.",
+ "_XMPP-Server._TCP.Google.COM.",
+ "_XMPP-SERVER._TCP.GOOGLE.COM.",
+ } {
+ _, addrs, err := answer(name, "foo:53", msg, uint16(dnsTypeSRV))
+ if err != nil {
+ t.Error(err)
+ }
+ if g, e := len(addrs), 5; g != e {
+ t.Errorf("len(addrs) = %d; want %d", g, e)
+ t.Logf("addrs = %#v", addrs)
+ }
}
// repack and unpack.
data2, ok := msg.Pack()
msg2.Unpack(data2)
switch {
case !ok:
- t.Errorf("failed to repack message")
+ t.Error("failed to repack message")
case !reflect.DeepEqual(msg, msg2):
- t.Errorf("repacked message differs from original")
+ t.Error("repacked message differs from original")
}
}
func setWriteBuffer(fd *netFD, bytes int) error {
return syscall.EPLAN9
}
-
-func skipRawSocketTests() (skip bool, skipmsg string, err error) {
- return true, "skipping test on plan9", nil
-}
func (pd *pollDesc) Close() {}
-func (pd *pollDesc) Lock() {}
-
-func (pd *pollDesc) Unlock() {}
-
-func (pd *pollDesc) Wakeup() {}
-
-func (pd *pollDesc) Evict() bool {
+func (pd *pollDesc) Evict() {
pd.closing = true
if pd.fd != nil {
syscall.StopIO(pd.fd.sysfd)
}
- return false
}
func (pd *pollDesc) Prepare(mode int) error {
pd.runtimeCtx = 0
}
-func (pd *pollDesc) Lock() {
-}
-
-func (pd *pollDesc) Unlock() {
-}
-
-func (pd *pollDesc) Wakeup() {
-}
-
// Evict evicts fd from the pending list, unblocking any I/O running on fd.
-// Return value is whether the pollServer should be woken up.
-func (pd *pollDesc) Evict() bool {
+func (pd *pollDesc) Evict() {
if pd.runtimeCtx == 0 {
- return false
+ return
}
runtime_pollUnblock(pd.runtimeCtx)
- return false
}
func (pd *pollDesc) Prepare(mode int) error {
}
func (fd *netFD) Close() error {
- fd.pd.Lock() // needed for both fd.incref(true) and pollDesc.Evict
if !fd.fdmu.IncrefAndClose() {
- fd.pd.Unlock()
return errClosing
}
// Unblock any I/O. Once it all unblocks and returns,
// the final decref will close fd.sysfd. This should happen
// fairly quickly, since all the I/O is non-blocking, and any
// attempts to block in the pollDesc will return errClosing.
- doWakeup := fd.pd.Evict()
- fd.pd.Unlock()
+ fd.pd.Evict()
fd.decref()
- if doWakeup {
- fd.pd.Wakeup()
- }
return nil
}
func closesocket(s int) error {
return syscall.Close(s)
}
-
-func skipRawSocketTests() (skip bool, skipmsg string, err error) {
- if os.Getuid() != 0 {
- return true, "skipping test; must be root", nil
- }
- return false, "", nil
-}
return netfd, nil
}
-func skipRawSocketTests() (skip bool, skipmsg string, err error) {
- // From http://msdn.microsoft.com/en-us/library/windows/desktop/ms740548.aspx:
- // Note: To use a socket of type SOCK_RAW requires administrative privileges.
- // Users running Winsock applications that use raw sockets must be a member of
- // the Administrators group on the local computer, otherwise raw socket calls
- // will fail with an error code of WSAEACCES. On Windows Vista and later, access
- // for raw sockets is enforced at socket creation. In earlier versions of Windows,
- // access for raw sockets is enforced during other socket operations.
- s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, 0)
- if err == syscall.WSAEACCES {
- return true, "skipping test; no access to raw socket allowed", nil
- }
- if err != nil {
- return true, "", err
- }
- defer syscall.Closesocket(s)
- return false, "", nil
-}
-
// Unimplemented functions.
func (fd *netFD) dup() (*os.File, error) {
return true
}
-func afterTest(t *testing.T) {
+func afterTest(t testing.TB) {
http.DefaultTransport.(*http.Transport).CloseIdleConnections()
if testing.Short() {
return
//
// go tool pprof http://localhost:6060/debug/pprof/block
//
+// Or to collect a 5-second execution trace:
+//
+// wget http://localhost:6060/debug/pprof/trace?seconds=5
+//
// To view all available profiles, open http://localhost:6060/debug/pprof/
// in your browser.
//
http.Handle("/debug/pprof/cmdline", http.HandlerFunc(Cmdline))
http.Handle("/debug/pprof/profile", http.HandlerFunc(Profile))
http.Handle("/debug/pprof/symbol", http.HandlerFunc(Symbol))
+ http.Handle("/debug/pprof/trace", http.HandlerFunc(Trace))
}
// Cmdline responds with the running program's
pprof.StopCPUProfile()
}
+// Trace responds with the execution trace in binary form.
+// Tracing lasts for duration specified in seconds GET parameter, or for 1 second if not specified.
+// The package initialization registers it as /debug/pprof/trace.
+func Trace(w http.ResponseWriter, r *http.Request) {
+ sec, _ := strconv.ParseInt(r.FormValue("seconds"), 10, 64)
+ if sec == 0 {
+ sec = 1
+ }
+
+ // Set Content Type assuming StartTrace will work,
+ // because if it does it starts writing.
+ w.Header().Set("Content-Type", "application/octet-stream")
+ if err := pprof.StartTrace(w); err != nil {
+ // StartTrace failed, so no writes yet.
+ // Can change header back to text content and send error code.
+ w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+ w.WriteHeader(http.StatusInternalServerError)
+ fmt.Fprintf(w, "Could not enable tracing: %s\n", err)
+ return
+ }
+ time.Sleep(time.Duration(sec) * time.Second)
+ pprof.StopTrace()
+}
+
// Symbol looks up the program counters listed in the request,
// responding with a table mapping program counters to function names.
// The package initialization registers it as /debug/pprof/symbol.
// parseBasicAuth parses an HTTP Basic Authentication string.
// "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" returns ("Aladdin", "open sesame", true).
func parseBasicAuth(auth string) (username, password string, ok bool) {
- if !strings.HasPrefix(auth, "Basic ") {
+ const prefix = "Basic "
+ if !strings.HasPrefix(auth, prefix) {
return
}
- c, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(auth, "Basic "))
+ c, err := base64.StdEncoding.DecodeString(auth[len(prefix):])
if err != nil {
return
}
defer ts.Close()
b.StartTimer()
- cmd := exec.Command(os.Args[0], "-test.run=XXXX", "-test.bench=BenchmarkServer")
+ cmd := exec.Command(os.Args[0], "-test.run=XXXX", "-test.bench=BenchmarkServer$")
cmd.Env = append([]string{
fmt.Sprintf("TEST_BENCH_CLIENT_N=%d", b.N),
fmt.Sprintf("TEST_BENCH_SERVER_URL=%s", ts.URL),
}
}
+// getNoBody wraps Get but closes any Response.Body before returning the response.
+func getNoBody(urlStr string) (*Response, error) {
+ res, err := Get(urlStr)
+ if err != nil {
+ return nil, err
+ }
+ res.Body.Close()
+ return res, nil
+}
+
+// A benchmark for profiling the client without the HTTP server code.
+// The server code runs in a subprocess.
+func BenchmarkClient(b *testing.B) {
+ b.ReportAllocs()
+ b.StopTimer()
+ defer afterTest(b)
+
+ port := os.Getenv("TEST_BENCH_SERVER_PORT") // can be set by user
+ if port == "" {
+ port = "39207"
+ }
+ var data = []byte("Hello world.\n")
+ if server := os.Getenv("TEST_BENCH_SERVER"); server != "" {
+ // Server process mode.
+ HandleFunc("/", func(w ResponseWriter, r *Request) {
+ r.ParseForm()
+ if r.Form.Get("stop") != "" {
+ os.Exit(0)
+ }
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ w.Write(data)
+ })
+ log.Fatal(ListenAndServe("localhost:"+port, nil))
+ }
+
+ // Start server process.
+ cmd := exec.Command(os.Args[0], "-test.run=XXXX", "-test.bench=BenchmarkClient$")
+ cmd.Env = append(os.Environ(), "TEST_BENCH_SERVER=yes")
+ if err := cmd.Start(); err != nil {
+ b.Fatalf("subprocess failed to start: %v", err)
+ }
+ defer cmd.Process.Kill()
+ done := make(chan error)
+ go func() {
+ done <- cmd.Wait()
+ }()
+
+ // Wait for the server process to respond.
+ url := "http://localhost:" + port + "/"
+ for i := 0; i < 100; i++ {
+ time.Sleep(50 * time.Millisecond)
+ if _, err := getNoBody(url); err == nil {
+ break
+ }
+ if i == 99 {
+ b.Fatalf("subprocess does not respond")
+ }
+ }
+
+ // Do b.N requests to the server.
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ res, err := Get(url)
+ if err != nil {
+ b.Fatalf("Get: %v", err)
+ }
+ body, err := ioutil.ReadAll(res.Body)
+ res.Body.Close()
+ if err != nil {
+ b.Fatalf("ReadAll: %v", err)
+ }
+ if bytes.Compare(body, data) != 0 {
+ b.Fatalf("Got body: %q", body)
+ }
+ }
+ b.StopTimer()
+
+ // Instruct server process to stop.
+ getNoBody(url + "?stop=yes")
+ select {
+ case err := <-done:
+ if err != nil {
+ b.Fatalf("subprocess failed: %v", err)
+ }
+ case <-time.After(5 * time.Second):
+ b.Fatalf("subprocess did not stop")
+ }
+}
+
func BenchmarkServerFakeConnNoKeepAlive(b *testing.B) {
b.ReportAllocs()
req := reqBytes(`GET / HTTP/1.0
c.clientGone = true
}
-// A switchReader can have its Reader changed at runtime.
-// It's not safe for concurrent Reads and switches.
-type switchReader struct {
- io.Reader
-}
-
// A switchWriter can have its Writer changed at runtime.
// It's not safe for concurrent Writes and switches.
type switchWriter struct {
io.Writer
}
-// A liveSwitchReader is a switchReader that's safe for concurrent
-// reads and switches, if its mutex is held.
+// A liveSwitchReader can have its Reader changed at runtime. It's
+// safe for concurrent reads and switches, if its mutex is held.
type liveSwitchReader struct {
sync.Mutex
r io.Reader
import (
"reflect"
+ "runtime"
"testing"
)
}
for _, ifa := range ifat {
switch ifa := ifa.(type) {
- case *IPAddr:
- if ifa.IP.To4() == nil && ifa.IP.IsLinkLocalUnicast() {
- return ifa.IP.String()
- }
case *IPNet:
if ifa.IP.To4() == nil && ifa.IP.IsLinkLocalUnicast() {
return ifa.IP.String()
}
func TestInterfaces(t *testing.T) {
+ if runtime.GOOS == "windows" {
+ t.Skip("temporarily disabled until golang.org/issue/5395 is fixed")
+ }
+
ift, err := Interfaces()
if err != nil {
- t.Fatalf("Interfaces failed: %v", err)
+ t.Fatal(err)
}
- t.Logf("table: len/cap = %v/%v", len(ift), cap(ift))
-
+ var nifs, naf4, naf6, nmaf4, nmaf6 int
for _, ifi := range ift {
ifxi, err := InterfaceByIndex(ifi.Index)
if err != nil {
- t.Fatalf("InterfaceByIndex(%v) failed: %v", ifi.Index, err)
+ t.Fatal(err)
}
if !reflect.DeepEqual(ifxi, &ifi) {
- t.Fatalf("InterfaceByIndex(%v) = %v, want %v", ifi.Index, ifxi, ifi)
+ t.Errorf("got %v; want %v", ifxi, ifi)
}
ifxn, err := InterfaceByName(ifi.Name)
if err != nil {
- t.Fatalf("InterfaceByName(%q) failed: %v", ifi.Name, err)
+ t.Fatal(err)
}
if !reflect.DeepEqual(ifxn, &ifi) {
- t.Fatalf("InterfaceByName(%q) = %v, want %v", ifi.Name, ifxn, ifi)
+ t.Errorf("got %v; want %v", ifxn, ifi)
}
t.Logf("%q: flags %q, ifindex %v, mtu %v", ifi.Name, ifi.Flags.String(), ifi.Index, ifi.MTU)
- t.Logf("\thardware address %q", ifi.HardwareAddr.String())
- testInterfaceAddrs(t, &ifi)
- testInterfaceMulticastAddrs(t, &ifi)
+ t.Logf("hardware address %q", ifi.HardwareAddr.String())
+ if ifi.Flags&FlagUp != 0 && ifi.Flags&FlagLoopback == 0 {
+ nifs++ // active interfaces except loopback interfaces
+ }
+ n4, n6 := testInterfaceAddrs(t, &ifi)
+ naf4 += n4
+ naf6 += n6
+ n4, n6 = testInterfaceMulticastAddrs(t, &ifi)
+ nmaf4 += n4
+ nmaf6 += n6
+ }
+ switch runtime.GOOS {
+ case "nacl", "plan9", "solaris":
+ default:
+ if supportsIPv4 && nifs > 0 && naf4 == 0 {
+ t.Errorf("got %v; want more than or equal to one", naf4)
+ }
+ if supportsIPv6 && nifs > 0 && naf6 == 0 {
+ t.Errorf("got %v; want more than or equal to one", naf6)
+ }
+ }
+ switch runtime.GOOS {
+ case "dragonfly", "nacl", "netbsd", "openbsd", "plan9", "solaris":
+ default:
+ // Unlike IPv6, IPv4 multicast capability is not a
+ // mandatory feature.
+ //if supportsIPv4 && nactvifs > 0 && nmaf4 == 0 {
+ // t.Errorf("got %v; want more than or equal to one", nmaf4)
+ //}
+ if supportsIPv6 && nifs > 0 && nmaf6 == 0 {
+ t.Errorf("got %v; want more than or equal to one", nmaf6)
+ }
}
}
func TestInterfaceAddrs(t *testing.T) {
+ if runtime.GOOS == "windows" {
+ t.Skip("temporarily disabled until golang.org/issue/5395 is fixed")
+ }
+
+ ift, err := Interfaces()
+ if err != nil {
+ t.Fatal(err)
+ }
+ var nifs int
+ for _, ifi := range ift {
+ if ifi.Flags&FlagUp != 0 && ifi.Flags&FlagLoopback == 0 {
+ nifs++ // active interfaces except loopback interfaces
+ }
+ }
ifat, err := InterfaceAddrs()
if err != nil {
- t.Fatalf("InterfaceAddrs failed: %v", err)
+ t.Fatal(err)
+ }
+ naf4, naf6 := testAddrs(t, ifat)
+ if supportsIPv4 && nifs > 0 && naf4 == 0 {
+ t.Errorf("got %v; want more than or equal to one", naf4)
+ }
+ if supportsIPv6 && nifs > 0 && naf6 == 0 {
+ t.Errorf("got %v; want more than or equal to one", naf6)
}
- t.Logf("table: len/cap = %v/%v", len(ifat), cap(ifat))
- testAddrs(t, ifat)
}
-func testInterfaceAddrs(t *testing.T, ifi *Interface) {
+func testInterfaceAddrs(t *testing.T, ifi *Interface) (naf4, naf6 int) {
ifat, err := ifi.Addrs()
if err != nil {
- t.Fatalf("Interface.Addrs failed: %v", err)
+ t.Fatal(err)
}
- testAddrs(t, ifat)
+ return testAddrs(t, ifat)
}
-func testInterfaceMulticastAddrs(t *testing.T, ifi *Interface) {
+func testInterfaceMulticastAddrs(t *testing.T, ifi *Interface) (nmaf4, nmaf6 int) {
ifmat, err := ifi.MulticastAddrs()
if err != nil {
- t.Fatalf("Interface.MulticastAddrs failed: %v", err)
+ t.Fatal(err)
}
- testMulticastAddrs(t, ifmat)
+ return testMulticastAddrs(t, ifmat)
}
-func testAddrs(t *testing.T, ifat []Addr) {
+func testAddrs(t *testing.T, ifat []Addr) (naf4, naf6 int) {
for _, ifa := range ifat {
switch ifa := ifa.(type) {
- case *IPAddr:
- if ifa == nil || ifa.IP == nil {
- t.Errorf("\tunexpected value: %v, %v", ifa, ifa.IP)
- } else {
- t.Logf("\tinterface address %q", ifa.String())
- }
case *IPNet:
- if ifa == nil || ifa.IP == nil || ifa.Mask == nil {
- t.Errorf("\tunexpected value: %v, %v, %v", ifa, ifa.IP, ifa.Mask)
- } else {
- _, prefixLen := ifa.Mask.Size()
- if ifa.IP.To4() != nil && prefixLen != 8*IPv4len || ifa.IP.To16() != nil && ifa.IP.To4() == nil && prefixLen != 8*IPv6len {
- t.Errorf("\tunexpected value: %v, %v, %v, %v", ifa, ifa.IP, ifa.Mask, prefixLen)
- } else {
- t.Logf("\tinterface address %q", ifa.String())
+ if ifa == nil || ifa.IP == nil || ifa.IP.IsUnspecified() || ifa.IP.IsMulticast() || ifa.Mask == nil {
+ t.Errorf("unexpected value: %#v", ifa)
+ continue
+ }
+ prefixLen, maxPrefixLen := ifa.Mask.Size()
+ if ifa.IP.To4() != nil {
+ if 0 >= prefixLen || prefixLen > 8*IPv4len || maxPrefixLen != 8*IPv4len {
+ t.Errorf("unexpected prefix length: %v/%v", prefixLen, maxPrefixLen)
+ continue
+ }
+ naf4++
+ } else if ifa.IP.To16() != nil {
+ if 0 >= prefixLen || prefixLen > 8*IPv6len || maxPrefixLen != 8*IPv6len {
+ t.Errorf("unexpected prefix length: %v/%v", prefixLen, maxPrefixLen)
+ continue
}
+ naf6++
}
+ t.Logf("interface address %q", ifa.String())
default:
- t.Errorf("\tunexpected type: %T", ifa)
+ t.Errorf("unexpected type: %T", ifa)
}
}
+ return
}
-func testMulticastAddrs(t *testing.T, ifmat []Addr) {
+func testMulticastAddrs(t *testing.T, ifmat []Addr) (nmaf4, nmaf6 int) {
for _, ifma := range ifmat {
switch ifma := ifma.(type) {
case *IPAddr:
- if ifma == nil {
- t.Errorf("\tunexpected value: %v", ifma)
- } else {
- t.Logf("\tjoined group address %q", ifma.String())
+ if ifma == nil || ifma.IP == nil || ifma.IP.IsUnspecified() || !ifma.IP.IsMulticast() {
+ t.Errorf("unexpected value: %#v", ifma)
+ continue
+ }
+ if ifma.IP.To4() != nil {
+ nmaf4++
+ } else if ifma.IP.To16() != nil {
+ nmaf6++
}
+ t.Logf("joined group address %q", ifma.String())
default:
- t.Errorf("\tunexpected type: %T", ifma)
+ t.Errorf("unexpected type: %T", ifma)
}
}
+ return
}
func BenchmarkInterfaces(b *testing.B) {
for i := 0; i < b.N; i++ {
if _, err := Interfaces(); err != nil {
- b.Fatalf("Interfaces failed: %v", err)
+ b.Fatal(err)
}
}
}
}
for i := 0; i < b.N; i++ {
if _, err := InterfaceByIndex(ifi.Index); err != nil {
- b.Fatalf("InterfaceByIndex failed: %v", err)
+ b.Fatal(err)
}
}
}
}
for i := 0; i < b.N; i++ {
if _, err := InterfaceByName(ifi.Name); err != nil {
- b.Fatalf("InterfaceByName failed: %v", err)
+ b.Fatal(err)
}
}
}
func BenchmarkInterfaceAddrs(b *testing.B) {
for i := 0; i < b.N; i++ {
if _, err := InterfaceAddrs(); err != nil {
- b.Fatalf("InterfaceAddrs failed: %v", err)
+ b.Fatal(err)
}
}
}
}
for i := 0; i < b.N; i++ {
if _, err := ifi.Addrs(); err != nil {
- b.Fatalf("Interface.Addrs failed: %v", err)
+ b.Fatal(err)
}
}
}
}
for i := 0; i < b.N; i++ {
if _, err := ifi.MulticastAddrs(); err != nil {
- b.Fatalf("Interface.MulticastAddrs failed: %v", err)
+ b.Fatal(err)
}
}
}
// If IPv4, use dotted notation.
if p4 := p.To4(); len(p4) == IPv4len {
- return itod(uint(p4[0])) + "." +
- itod(uint(p4[1])) + "." +
- itod(uint(p4[2])) + "." +
- itod(uint(p4[3]))
+ return uitoa(uint(p4[0])) + "." +
+ uitoa(uint(p4[1])) + "." +
+ uitoa(uint(p4[2])) + "." +
+ uitoa(uint(p4[3]))
}
if len(p) != IPv6len {
return "?"
if l == -1 {
return nn.String() + "/" + m.String()
}
- return nn.String() + "/" + itod(uint(l))
+ return nn.String() + "/" + uitoa(uint(l))
}
// Parse IPv4 address (d.d.d.d).
package net
import (
- "bytes"
"fmt"
"os"
"reflect"
"runtime"
"testing"
- "time"
)
+// The full stack test cases for IPConn have been moved to the
+// following:
+// golang.org/x/net/ipv4
+// golang.org/x/net/ipv6
+// golang.org/x/net/icmp
+
type resolveIPAddrTest struct {
net string
litAddrOrName string
}
}
-func skipRawSocketTest(t *testing.T) (skip bool, skipmsg string) {
- skip, skipmsg, err := skipRawSocketTests()
- if err != nil {
- t.Fatal(err)
- }
- return skip, skipmsg
-}
-
func TestResolveIPAddr(t *testing.T) {
switch runtime.GOOS {
case "nacl":
}
}
-var icmpEchoTests = []struct {
- net string
- laddr string
- raddr string
-}{
- {"ip4:icmp", "0.0.0.0", "127.0.0.1"},
- {"ip6:ipv6-icmp", "::", "::1"},
-}
-
-func TestConnICMPEcho(t *testing.T) {
- if skip, skipmsg := skipRawSocketTest(t); skip {
- t.Skip(skipmsg)
- }
-
- for i, tt := range icmpEchoTests {
- net, _, err := parseNetwork(tt.net)
- if err != nil {
- t.Fatalf("parseNetwork failed: %v", err)
- }
- if net == "ip6" && !supportsIPv6 {
- continue
- }
-
- c, err := Dial(tt.net, tt.raddr)
- if err != nil {
- t.Fatalf("Dial failed: %v", err)
- }
- c.SetDeadline(time.Now().Add(100 * time.Millisecond))
- defer c.Close()
-
- typ := icmpv4EchoRequest
- if net == "ip6" {
- typ = icmpv6EchoRequest
- }
- xid, xseq := os.Getpid()&0xffff, i+1
- wb, err := (&icmpMessage{
- Type: typ, Code: 0,
- Body: &icmpEcho{
- ID: xid, Seq: xseq,
- Data: bytes.Repeat([]byte("Go Go Gadget Ping!!!"), 3),
- },
- }).Marshal()
- if err != nil {
- t.Fatalf("icmpMessage.Marshal failed: %v", err)
- }
- if _, err := c.Write(wb); err != nil {
- t.Fatalf("Conn.Write failed: %v", err)
- }
- var m *icmpMessage
- rb := make([]byte, 20+len(wb))
- for {
- if _, err := c.Read(rb); err != nil {
- t.Fatalf("Conn.Read failed: %v", err)
- }
- if net == "ip4" {
- rb = ipv4Payload(rb)
- }
- if m, err = parseICMPMessage(rb); err != nil {
- t.Fatalf("parseICMPMessage failed: %v", err)
- }
- switch m.Type {
- case icmpv4EchoRequest, icmpv6EchoRequest:
- continue
- }
- break
- }
- switch p := m.Body.(type) {
- case *icmpEcho:
- if p.ID != xid || p.Seq != xseq {
- t.Fatalf("got id=%v, seqnum=%v; expected id=%v, seqnum=%v", p.ID, p.Seq, xid, xseq)
- }
- default:
- t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, typ, 0)
- }
- }
-}
-
-func TestPacketConnICMPEcho(t *testing.T) {
- if skip, skipmsg := skipRawSocketTest(t); skip {
- t.Skip(skipmsg)
- }
-
- for i, tt := range icmpEchoTests {
- net, _, err := parseNetwork(tt.net)
- if err != nil {
- t.Fatalf("parseNetwork failed: %v", err)
- }
- if net == "ip6" && !supportsIPv6 {
- continue
- }
-
- c, err := ListenPacket(tt.net, tt.laddr)
- if err != nil {
- t.Fatalf("ListenPacket failed: %v", err)
- }
- c.SetDeadline(time.Now().Add(100 * time.Millisecond))
- defer c.Close()
-
- ra, err := ResolveIPAddr(tt.net, tt.raddr)
- if err != nil {
- t.Fatalf("ResolveIPAddr failed: %v", err)
- }
- typ := icmpv4EchoRequest
- if net == "ip6" {
- typ = icmpv6EchoRequest
- }
- xid, xseq := os.Getpid()&0xffff, i+1
- wb, err := (&icmpMessage{
- Type: typ, Code: 0,
- Body: &icmpEcho{
- ID: xid, Seq: xseq,
- Data: bytes.Repeat([]byte("Go Go Gadget Ping!!!"), 3),
- },
- }).Marshal()
- if err != nil {
- t.Fatalf("icmpMessage.Marshal failed: %v", err)
- }
- if _, err := c.WriteTo(wb, ra); err != nil {
- t.Fatalf("PacketConn.WriteTo failed: %v", err)
- }
- var m *icmpMessage
- rb := make([]byte, 20+len(wb))
- for {
- if _, _, err := c.ReadFrom(rb); err != nil {
- t.Fatalf("PacketConn.ReadFrom failed: %v", err)
- }
- // See BUG section.
- //if net == "ip4" {
- // rb = ipv4Payload(rb)
- //}
- if m, err = parseICMPMessage(rb); err != nil {
- t.Fatalf("parseICMPMessage failed: %v", err)
- }
- switch m.Type {
- case icmpv4EchoRequest, icmpv6EchoRequest:
- continue
- }
- break
- }
- switch p := m.Body.(type) {
- case *icmpEcho:
- if p.ID != xid || p.Seq != xseq {
- t.Fatalf("got id=%v, seqnum=%v; expected id=%v, seqnum=%v", p.ID, p.Seq, xid, xseq)
- }
- default:
- t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, typ, 0)
- }
- }
-}
-
-func ipv4Payload(b []byte) []byte {
- if len(b) < 20 {
- return b
- }
- hdrlen := int(b[0]&0x0f) << 2
- return b[hdrlen:]
-}
-
var ipConnLocalNameTests = []struct {
net string
laddr *IPAddr
if ifi, err := InterfaceByIndex(zone); err == nil {
return ifi.Name
}
- return itod(uint(zone))
+ return uitoa(uint(zone))
}
func zoneToInt(zone string) int {
+++ /dev/null
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package net
-
-import "errors"
-
-const (
- icmpv4EchoRequest = 8
- icmpv4EchoReply = 0
- icmpv6EchoRequest = 128
- icmpv6EchoReply = 129
-)
-
-// icmpMessage represents an ICMP message.
-type icmpMessage struct {
- Type int // type
- Code int // code
- Checksum int // checksum
- Body icmpMessageBody // body
-}
-
-// icmpMessageBody represents an ICMP message body.
-type icmpMessageBody interface {
- Len() int
- Marshal() ([]byte, error)
-}
-
-// Marshal returns the binary enconding of the ICMP echo request or
-// reply message m.
-func (m *icmpMessage) Marshal() ([]byte, error) {
- b := []byte{byte(m.Type), byte(m.Code), 0, 0}
- if m.Body != nil && m.Body.Len() != 0 {
- mb, err := m.Body.Marshal()
- if err != nil {
- return nil, err
- }
- b = append(b, mb...)
- }
- switch m.Type {
- case icmpv6EchoRequest, icmpv6EchoReply:
- return b, nil
- }
- csumcv := len(b) - 1 // checksum coverage
- s := uint32(0)
- for i := 0; i < csumcv; i += 2 {
- s += uint32(b[i+1])<<8 | uint32(b[i])
- }
- if csumcv&1 == 0 {
- s += uint32(b[csumcv])
- }
- s = s>>16 + s&0xffff
- s = s + s>>16
- // Place checksum back in header; using ^= avoids the
- // assumption the checksum bytes are zero.
- b[2] ^= byte(^s)
- b[3] ^= byte(^s >> 8)
- return b, nil
-}
-
-// parseICMPMessage parses b as an ICMP message.
-func parseICMPMessage(b []byte) (*icmpMessage, error) {
- msglen := len(b)
- if msglen < 4 {
- return nil, errors.New("message too short")
- }
- m := &icmpMessage{Type: int(b[0]), Code: int(b[1]), Checksum: int(b[2])<<8 | int(b[3])}
- if msglen > 4 {
- var err error
- switch m.Type {
- case icmpv4EchoRequest, icmpv4EchoReply, icmpv6EchoRequest, icmpv6EchoReply:
- m.Body, err = parseICMPEcho(b[4:])
- if err != nil {
- return nil, err
- }
- }
- }
- return m, nil
-}
-
-// imcpEcho represenets an ICMP echo request or reply message body.
-type icmpEcho struct {
- ID int // identifier
- Seq int // sequence number
- Data []byte // data
-}
-
-func (p *icmpEcho) Len() int {
- if p == nil {
- return 0
- }
- return 4 + len(p.Data)
-}
-
-// Marshal returns the binary enconding of the ICMP echo request or
-// reply message body p.
-func (p *icmpEcho) Marshal() ([]byte, error) {
- b := make([]byte, 4+len(p.Data))
- b[0], b[1] = byte(p.ID>>8), byte(p.ID)
- b[2], b[3] = byte(p.Seq>>8), byte(p.Seq)
- copy(b[4:], p.Data)
- return b, nil
-}
-
-// parseICMPEcho parses b as an ICMP echo request or reply message
-// body.
-func parseICMPEcho(b []byte) (*icmpEcho, error) {
- bodylen := len(b)
- p := &icmpEcho{ID: int(b[0])<<8 | int(b[1]), Seq: int(b[2])<<8 | int(b[3])}
- if bodylen > 4 {
- p.Data = make([]byte, bodylen-4)
- copy(p.Data, b[4:])
- }
- return p, nil
-}
*/
package net
-// TODO(rsc):
-// support for raw ethernet sockets
-
import (
"errors"
"io"
"time"
)
+// The full stack test cases for IPConn have been moved to the
+// following:
+// golang.org/x/net/ipv4
+// golang.org/x/net/ipv6
+// golang.org/x/net/icmp
+
func packetConnTestData(t *testing.T, net string, i int) ([]byte, func()) {
switch net {
case "udp":
return []byte("UDP PACKETCONN TEST"), nil
- case "ip":
- if skip, skipmsg := skipRawSocketTest(t); skip {
- return nil, func() {
- t.Logf(skipmsg)
- }
- }
- b, err := (&icmpMessage{
- Type: icmpv4EchoRequest, Code: 0,
- Body: &icmpEcho{
- ID: os.Getpid() & 0xffff, Seq: i + 1,
- Data: []byte("IP PACKETCONN TEST"),
- },
- }).Marshal()
- if err != nil {
- return nil, func() {
- t.Fatalf("icmpMessage.Marshal failed: %v", err)
- }
- }
- return b, nil
case "unixgram":
switch runtime.GOOS {
case "nacl", "plan9", "windows":
addr2 string
}{
{"udp", "127.0.0.1:0", "127.0.0.1:0"},
- {"ip:icmp", "127.0.0.1", "127.0.0.1"},
{"unixgram", testUnixAddr(), testUnixAddr()},
}
return byte(n), ok && ei == 2
}
-// Integer to decimal.
-func itoa(i int) string {
- var buf [30]byte
- n := len(buf)
- neg := false
- if i < 0 {
- i = -i
- neg = true
- }
- ui := uint(i)
- for ui > 0 || n == len(buf) {
- n--
- buf[n] = byte('0' + ui%10)
- ui /= 10
- }
- if neg {
- n--
- buf[n] = '-'
- }
- return string(buf[n:])
+// Convert integer to decimal string.
+func itoa(val int) string {
+ if val < 0 {
+ return "-" + uitoa(uint(-val))
+ }
+ return uitoa(uint(val))
}
-// Convert i to decimal string.
-func itod(i uint) string {
- if i == 0 {
+// Convert unsigned integer to decimal string.
+func uitoa(val uint) string {
+ if val == 0 { // avoid string allocation
return "0"
}
-
- // Assemble decimal in reverse order.
- var b [32]byte
- bp := len(b)
- for ; i > 0; i /= 10 {
- bp--
- b[bp] = byte(i%10) + '0'
- }
-
- return string(b[bp:])
+ var buf [20]byte // big enough for 64bit value base 10
+ i := len(buf) - 1
+ for val >= 10 {
+ q := val / 10
+ buf[i] = byte('0' + val - q*10)
+ i--
+ val = q
+ }
+ // val < 10
+ buf[i] = byte('0' + val)
+ return string(buf[i:])
}
// Convert i to a hexadecimal string. Leading zeros are not printed.
"time"
)
+// The full stack test cases for IPConn have been moved to the
+// following:
+// golang.org/x/net/ipv4
+// golang.org/x/net/ipv6
+// golang.org/x/net/icmp
+
// testUnixAddr uses ioutil.TempFile to get a name that is unique. It
// also uses /tmp directory in case it is prohibited to create UNIX
// sockets in TMPDIR.
}
func TestIPConnSpecificMethods(t *testing.T) {
- if skip, skipmsg := skipRawSocketTest(t); skip {
- t.Skip(skipmsg)
+ if os.Getuid() != 0 {
+ t.Skip("must be root")
}
la, err := ResolveIPAddr("ip4", "127.0.0.1")
c.SetReadBuffer(2048)
c.SetWriteBuffer(2048)
- wb, err := (&icmpMessage{
- Type: icmpv4EchoRequest, Code: 0,
- Body: &icmpEcho{
- ID: os.Getpid() & 0xffff, Seq: 1,
- Data: []byte("IPCONN TEST "),
- },
- }).Marshal()
- if err != nil {
- t.Fatalf("icmpMessage.Marshal failed: %v", err)
- }
- rb := make([]byte, 20+len(wb))
- if _, err := c.WriteToIP(wb, c.LocalAddr().(*IPAddr)); err != nil {
- t.Fatalf("IPConn.WriteToIP failed: %v", err)
- }
- if _, _, err := c.ReadFromIP(rb); err != nil {
- t.Fatalf("IPConn.ReadFromIP failed: %v", err)
- }
- if _, _, err := c.WriteMsgIP(wb, nil, c.LocalAddr().(*IPAddr)); err != nil {
- condFatalf(t, "IPConn.WriteMsgIP failed: %v", err)
- }
- if _, _, _, _, err := c.ReadMsgIP(rb, nil); err != nil {
- condFatalf(t, "IPConn.ReadMsgIP failed: %v", err)
- }
-
if f, err := c.File(); err != nil {
condFatalf(t, "IPConn.File failed: %v", err)
} else {
}
}()
+ wb := []byte("IPCONN TEST")
c.WriteToIP(wb, nil)
c.WriteMsgIP(wb, nil, nil)
}
}
c, err := ListenPacket(net, laddr)
if err != nil {
- t.Fatalf("ListenPacket(%q, %q) faild: %v", net, laddr, err)
+ t.Fatalf("ListenPacket(%q, %q) failed: %v", net, laddr, err)
}
defer c.Close()
c.SetReadDeadline(time.Now().Add(1 * time.Second))
"testing"
)
+func init() {
+ isReadonlyError = func(err error) bool { return err == syscall.EROFS }
+}
+
func checkUidGid(t *testing.T, path string, uid, gid int) {
dir, err := Stat(path)
if err != nil {
"testing"
)
+var isReadonlyError = func(error) bool { return false }
+
func TestMkdirAll(t *testing.T) {
tmpDir := TempDir()
path := tmpDir + "/_TestMkdirAll_/dir/./dir2"
t.Skipf("skipping on %s", runtime.GOOS)
}
RemoveAll("/_go_os_test")
- err := MkdirAll("/_go_os_test/dir", 0777)
+ const dir = "/go_os_test/dir"
+ err := MkdirAll(dir, 0777)
if err != nil {
pathErr, ok := err.(*PathError)
// common for users not to be able to write to /
- if ok && pathErr.Err == syscall.EACCES {
- return
+ if ok && (pathErr.Err == syscall.EACCES || isReadonlyError(pathErr.Err)) {
+ t.Skipf("could not create %v: %v", dir, err)
}
t.Fatalf(`MkdirAll "/_go_os_test/dir": %v`, err)
}
"time"
)
+const _BIT16SZ = 2
+
func sameFile(fs1, fs2 *fileStat) bool {
a := fs1.sys.(*syscall.Dir)
b := fs2.sys.(*syscall.Dir)
// arg is an open *File or a path string.
func dirstat(arg interface{}) (*syscall.Dir, error) {
var name string
+ var err error
- // This is big enough for most stat messages
- // and rounded to a multiple of 128 bytes.
- size := (syscall.STATFIXLEN + 16*4 + 128) &^ 128
+ size := syscall.STATFIXLEN + 16*4
for i := 0; i < 2; i++ {
- buf := make([]byte, size)
+ buf := make([]byte, _BIT16SZ+size)
var n int
- var err error
switch a := arg.(type) {
case *File:
name = a.name
default:
panic("phase error in dirstat")
}
- if err != nil {
- return nil, &PathError{"stat", name, err}
- }
- if n < syscall.STATFIXLEN {
+
+ if n < _BIT16SZ {
return nil, &PathError{"stat", name, syscall.ErrShortStat}
}
// If the stat message is larger than our buffer we will
// go around the loop and allocate one that is big enough.
- if size > n {
- continue
+ if size <= n {
+ d, err := syscall.UnmarshalDir(buf[:n])
+ if err != nil {
+ return nil, &PathError{"stat", name, err}
+ }
+ return d, nil
}
- d, err := syscall.UnmarshalDir(buf[:n])
- if err != nil {
- return nil, &PathError{"stat", name, err}
- }
- return d, nil
}
- return nil, &PathError{"stat", name, syscall.ErrBadStat}
+
+ if err == nil {
+ err = syscall.ErrBadStat
+ }
+
+ return nil, &PathError{"stat", name, err}
}
// Stat returns a FileInfo describing the named file.
// Join joins any number of path elements into a single path, adding
// a Separator if necessary. The result is Cleaned, in particular
// all empty strings are ignored.
+// On Windows, the result is a UNC path if and only if the first path
+// element is a UNC path.
func Join(elem ...string) string {
- for i, e := range elem {
- if e != "" {
- return Clean(strings.Join(elem[i:], string(Separator)))
- }
- }
- return ""
+ return join(elem)
}
// Ext returns the file name extension used by path.
func abs(path string) (string, error) {
return unixAbs(path)
}
+
+func join(elem []string) string {
+ // If there's a bug here, fix the logic in ./path_unix.go too.
+ for i, e := range elem {
+ if e != "" {
+ return Clean(strings.Join(elem[i:], string(Separator)))
+ }
+ }
+ return ""
+}
// one parameter
{[]string{""}, ""},
+ {[]string{"/"}, "/"},
{[]string{"a"}, "a"},
// two parameters
{[]string{"a", ""}, "a"},
{[]string{"", "b"}, "b"},
{[]string{"/", "a"}, "/a"},
+ {[]string{"/", "a/b"}, "/a/b"},
{[]string{"/", ""}, "/"},
+ {[]string{"//", "a"}, "/a"},
+ {[]string{"/a", "b"}, "/a/b"},
{[]string{"a/", "b"}, "a/b"},
{[]string{"a/", ""}, "a"},
{[]string{"", ""}, ""},
+
+ // three parameters
+ {[]string{"/", "a", "b"}, "/a/b"},
}
var winjointests = []JoinTest{
{[]string{`C:\`, `Windows`}, `C:\Windows`},
{[]string{`C:`, `Windows`}, `C:\Windows`},
{[]string{`\\host\share`, `foo`}, `\\host\share\foo`},
+ {[]string{`\\host\share\foo`}, `\\host\share\foo`},
{[]string{`//host/share`, `foo/bar`}, `\\host\share\foo\bar`},
-}
-
-// join takes a []string and passes it to Join.
-func join(elem []string, args ...string) string {
- args = elem
- return filepath.Join(args...)
+ {[]string{`\`}, `\`},
+ {[]string{`\`, ``}, `\`},
+ {[]string{`\`, `a`}, `\a`},
+ {[]string{`\\`, `a`}, `\a`},
+ {[]string{`\`, `a`, `b`}, `\a\b`},
+ {[]string{`\\`, `a`, `b`}, `\a\b`},
+ {[]string{`\`, `\\a\b`, `c`}, `\a\b\c`},
+ {[]string{`\\a`, `b`, `c`}, `\a\b\c`},
+ {[]string{`\\a\`, `b`, `c`}, `\a\b\c`},
}
func TestJoin(t *testing.T) {
jointests = append(jointests, winjointests...)
}
for _, test := range jointests {
- if p := join(test.elem); p != filepath.FromSlash(test.path) {
- t.Errorf("join(%q) = %q, want %q", test.elem, p, test.path)
+ expected := filepath.FromSlash(test.path)
+ if p := filepath.Join(test.elem...); p != expected {
+ t.Errorf("join(%q) = %q, want %q", test.elem, p, expected)
}
}
}
func abs(path string) (string, error) {
return unixAbs(path)
}
+
+func join(elem []string) string {
+ // If there's a bug here, fix the logic in ./path_plan9.go too.
+ for i, e := range elem {
+ if e != "" {
+ return Clean(strings.Join(elem[i:], string(Separator)))
+ }
+ }
+ return ""
+}
func abs(path string) (string, error) {
return syscall.FullPath(path)
}
+
+func join(elem []string) string {
+ for i, e := range elem {
+ if e != "" {
+ return joinNonEmpty(elem[i:])
+ }
+ }
+ return ""
+}
+
+// joinNonEmpty is like join, but it assumes that the first element is non-empty.
+func joinNonEmpty(elem []string) string {
+ // The following logic prevents Join from inadvertently creating a
+ // UNC path on Windows. Unless the first element is a UNC path, Join
+ // shouldn't create a UNC path. See golang.org/issue/9167.
+ p := Clean(strings.Join(elem, string(Separator)))
+ if !isUNC(p) {
+ return p
+ }
+ // p == UNC only allowed when the first element is a UNC path.
+ head := Clean(elem[0])
+ if isUNC(head) {
+ return p
+ }
+ // head + tail == UNC, but joining two non-UNC paths should not result
+ // in a UNC path. Undo creation of UNC path.
+ tail := Clean(strings.Join(elem[1:], string(Separator)))
+ if head[len(head)-1] == Separator {
+ return head + tail
+ }
+ return head + string(Separator) + tail
+}
+
+// isUNC returns true if path is a UNC path.
+func isUNC(path string) bool {
+ return volumeNameLen(path) > 2
+}
}
}
+func BenchmarkCall(b *testing.B) {
+ fv := ValueOf(func(a, b string) {})
+ b.ReportAllocs()
+ b.RunParallel(func(pb *testing.PB) {
+ args := []Value{ValueOf("a"), ValueOf("b")}
+ for pb.Next() {
+ fv.Call(args)
+ }
+ })
+}
+
func TestMakeFunc(t *testing.T) {
f := dummy
fv := MakeFunc(TypeOf(f), func(in []Value) []Value { return in })
var ft *rtype
var s *bitVector
if rcvr != nil {
- ft, argSize, retOffset, s = funcLayout(t.(*rtype), rcvr.(*rtype))
+ ft, argSize, retOffset, s, _ = funcLayout(t.(*rtype), rcvr.(*rtype))
} else {
- ft, argSize, retOffset, s = funcLayout(t.(*rtype), nil)
+ ft, argSize, retOffset, s, _ = funcLayout(t.(*rtype), nil)
}
frametype = ft
for i := uint32(0); i < s.n; i += 2 {
code := **(**uintptr)(unsafe.Pointer(&dummy))
// makeFuncImpl contains a stack map for use by the runtime
- _, _, _, stack := funcLayout(t, nil)
+ _, _, _, stack, _ := funcLayout(t, nil)
impl := &makeFuncImpl{code: code, stack: stack, typ: ftyp, fn: fn}
code := **(**uintptr)(unsafe.Pointer(&dummy))
// methodValue contains a stack map for use by the runtime
- _, _, _, stack := funcLayout(funcType, nil)
+ _, _, _, stack, _ := funcLayout(funcType, nil)
fv := &methodValue{
fn: code,
// Make a map type.
var imap interface{} = (map[unsafe.Pointer]unsafe.Pointer)(nil)
- prototype := *(**mapType)(unsafe.Pointer(&imap))
mt := new(mapType)
- *mt = *prototype
+ *mt = **(**mapType)(unsafe.Pointer(&imap))
mt.string = &s
mt.hash = fnv1(etyp.hash, 'm', byte(ktyp.hash>>24), byte(ktyp.hash>>16), byte(ktyp.hash>>8), byte(ktyp.hash))
mt.key = ktyp
for i := 0; i < c; i++ {
gc.appendProg(t.Field(i).Type.common())
}
- if gc.size > oldsize + t.size {
+ if gc.size > oldsize+t.size {
panic("reflect: struct components are larger than the struct itself")
}
gc.size = oldsize + t.size
)
func bucketOf(ktyp, etyp *rtype) *rtype {
+ // See comment on hmap.overflow in ../runtime/hashmap.go.
+ var kind uint8
+ if ktyp.kind&kindNoPointers != 0 && etyp.kind&kindNoPointers != 0 {
+ kind = kindNoPointers
+ }
+
if ktyp.size > maxKeySize {
ktyp = PtrTo(ktyp).(*rtype)
}
b := new(rtype)
b.size = gc.size
+ b.kind = kind
b.gc[0], _ = gc.finalize()
s := "bucket(" + *ktyp.string + "," + *etyp.string + ")"
b.string = &s
argSize uintptr // size of arguments
retOffset uintptr // offset of return values.
stack *bitVector
+ framePool *sync.Pool
}
var layoutCache struct {
// The returned type exists only for GC, so we only fill out GC relevant info.
// Currently, that's just size and the GC program. We also fill in
// the name for possible debugging use.
-func funcLayout(t *rtype, rcvr *rtype) (frametype *rtype, argSize, retOffset uintptr, stack *bitVector) {
+func funcLayout(t *rtype, rcvr *rtype) (frametype *rtype, argSize, retOffset uintptr, stack *bitVector, framePool *sync.Pool) {
if t.Kind() != Func {
panic("reflect: funcLayout of non-func type")
}
layoutCache.RLock()
if x := layoutCache.m[k]; x.t != nil {
layoutCache.RUnlock()
- return x.t, x.argSize, x.retOffset, x.stack
+ return x.t, x.argSize, x.retOffset, x.stack, x.framePool
}
layoutCache.RUnlock()
layoutCache.Lock()
if x := layoutCache.m[k]; x.t != nil {
layoutCache.Unlock()
- return x.t, x.argSize, x.retOffset, x.stack
+ return x.t, x.argSize, x.retOffset, x.stack, x.framePool
}
tt := (*funcType)(unsafe.Pointer(t))
if layoutCache.m == nil {
layoutCache.m = make(map[layoutKey]layoutType)
}
+ framePool = &sync.Pool{New: func() interface{} {
+ return unsafe_New(x)
+ }}
layoutCache.m[k] = layoutType{
t: x,
argSize: argSize,
retOffset: retOffset,
stack: stack,
+ framePool: framePool,
}
layoutCache.Unlock()
- return x, argSize, retOffset, stack
+ return x, argSize, retOffset, stack, framePool
}
// ifaceIndir reports whether t is stored indirectly in an interface value.
}
nout := t.NumOut()
- // Compute frame type, allocate a chunk of memory for frame
- frametype, _, retOffset, _ := funcLayout(t, rcvrtype)
- args := unsafe_New(frametype)
+ // Compute frame type.
+ frametype, _, retOffset, _, framePool := funcLayout(t, rcvrtype)
+
+ // Allocate a chunk of memory for frame.
+ var args unsafe.Pointer
+ if nout == 0 {
+ args = framePool.Get().(unsafe.Pointer)
+ } else {
+ // Can't use pool if the function has return values.
+ // We will leak pointer to args in ret, so its lifetime is not scoped.
+ args = unsafe_New(frametype)
+ }
off := uintptr(0)
// Copy inputs into args.
runtime.GC()
}
- // Copy return values out of args.
- ret := make([]Value, nout)
- off = retOffset
- for i := 0; i < nout; i++ {
- tv := t.Out(i)
- a := uintptr(tv.Align())
- off = (off + a - 1) &^ (a - 1)
- fl := flagIndir | flag(tv.Kind())
- ret[i] = Value{tv.common(), unsafe.Pointer(uintptr(args) + off), fl}
- off += tv.Size()
+ var ret []Value
+ if nout == 0 {
+ memclr(args, frametype.size)
+ framePool.Put(args)
+ } else {
+ // Zero the now unused input area of args,
+ // because the Values returned by this function contain pointers to the args object,
+ // and will thus keep the args object alive indefinitely.
+ memclr(args, retOffset)
+ // Copy return values out of args.
+ ret = make([]Value, nout)
+ off = retOffset
+ for i := 0; i < nout; i++ {
+ tv := t.Out(i)
+ a := uintptr(tv.Align())
+ off = (off + a - 1) &^ (a - 1)
+ fl := flagIndir | flag(tv.Kind())
+ ret[i] = Value{tv.common(), unsafe.Pointer(uintptr(args) + off), fl}
+ off += tv.Size()
+ }
}
return ret
func callMethod(ctxt *methodValue, frame unsafe.Pointer) {
rcvr := ctxt.rcvr
rcvrtype, t, fn := methodReceiver("call", rcvr, ctxt.method)
- frametype, argSize, retOffset, _ := funcLayout(t, rcvrtype)
+ frametype, argSize, retOffset, _, framePool := funcLayout(t, rcvrtype)
// Make a new frame that is one word bigger so we can store the receiver.
- args := unsafe_New(frametype)
+ args := framePool.Get().(unsafe.Pointer)
// Copy in receiver and rest of args.
storeRcvr(rcvr, args)
unsafe.Pointer(uintptr(args)+retOffset),
retOffset,
frametype.size-retOffset)
+
+ memclr(args, frametype.size)
+ framePool.Put(args)
}
// funcName returns the name of f, for use in error messages.
//go:noescape
func typedslicecopy(elemType *rtype, dst, src sliceHeader) int
+//go:noescape
+func memclr(ptr unsafe.Pointer, n uintptr)
+
// Dummy annotation marking that the value x escapes,
// for use in cases where the reflect code is so clever that
// the compiler cannot follow.
// TestFowler runs this package's regexp API against the
// POSIX regular expression tests collected by Glenn Fowler
-// at http://www2.research.att.com/~gsf/testregex/.
+// at http://www2.research.att.com/~astopen/testregex/testregex.html.
func TestFowler(t *testing.T) {
files, err := filepath.Glob("testdata/*.dat")
if err != nil {
break Reading
}
- // http://www2.research.att.com/~gsf/man/man1/testregex.html
+ // http://www2.research.att.com/~astopen/man/man1/testregex.html
//
// INPUT FORMAT
// Input lines may be blank, a comment beginning with #, or a test
thechar = '6'
_BigEndian = 0
_CacheLineSize = 64
- _RuntimeGogoBytes = 64 + (goos_plan9|goos_solaris|goos_windows)*16
+ _RuntimeGogoBytes = 80 + (goos_solaris)*16
_PhysPageSize = 4096
_PCQuantum = 1
_Int64Align = 8
// uint64 atomicload64(uint64 volatile* addr);
TEXT runtime·atomicload64(SB), NOSPLIT, $0-12
MOVL ptr+0(FP), AX
+ TESTL $7, AX
+ JZ 2(PC)
+ MOVL 0, AX // crash with nil ptr deref
LEAL ret_lo+4(FP), BX
// MOVQ (%EAX), %MM0
BYTE $0x0f; BYTE $0x6f; BYTE $0x00
// void runtime·atomicstore64(uint64 volatile* addr, uint64 v);
TEXT runtime·atomicstore64(SB), NOSPLIT, $0-12
MOVL ptr+0(FP), AX
+ TESTL $7, AX
+ JZ 2(PC)
+ MOVL 0, AX // crash with nil ptr deref
// MOVQ and EMMS were introduced on the Pentium MMX.
// MOVQ 0x8(%ESP), %MM0
BYTE $0x0f; BYTE $0x6f; BYTE $0x44; BYTE $0x24; BYTE $0x08
CALL runtime·schedinit(SB)
// create a new goroutine to start program
- MOVQ $runtime·main·f(SB), BP // entry
- PUSHQ BP
+ MOVQ $runtime·main·f(SB), AX // entry
+ PUSHQ AX
PUSHQ $0 // arg size
CALL runtime·newproc(SB)
POPQ AX
MOVQ BX, gobuf_pc(AX)
MOVQ $0, gobuf_ret(AX)
MOVQ $0, gobuf_ctxt(AX)
+ MOVQ BP, gobuf_bp(AX)
get_tls(CX)
MOVQ g(CX), BX
MOVQ BX, gobuf_g(AX)
MOVQ gobuf_sp(BX), SP // restore SP
MOVQ gobuf_ret(BX), AX
MOVQ gobuf_ctxt(BX), DX
+ MOVQ gobuf_bp(BX), BP
MOVQ $0, gobuf_sp(BX) // clear to help garbage collector
MOVQ $0, gobuf_ret(BX)
MOVQ $0, gobuf_ctxt(BX)
+ MOVQ $0, gobuf_bp(BX)
MOVQ gobuf_pc(BX), BX
JMP BX
LEAQ fn+0(FP), BX // caller's SP
MOVQ BX, (g_sched+gobuf_sp)(AX)
MOVQ AX, (g_sched+gobuf_g)(AX)
+ MOVQ BP, (g_sched+gobuf_bp)(AX)
// switch to m->g0 & its stack, call fn
MOVQ g(CX), BX
CMPQ AX, DX
JEQ noswitch
- MOVQ m_curg(BX), BP
- CMPQ AX, BP
+ MOVQ m_curg(BX), R8
+ CMPQ AX, R8
JEQ switch
// Bad: g is not gsignal, not g0, not curg. What is it?
switch:
// save our state in g->sched. Pretend to
// be systemstack_switch if the G stack is scanned.
- MOVQ $runtime·systemstack_switch(SB), BP
- MOVQ BP, (g_sched+gobuf_pc)(AX)
+ MOVQ $runtime·systemstack_switch(SB), SI
+ MOVQ SI, (g_sched+gobuf_pc)(AX)
MOVQ SP, (g_sched+gobuf_sp)(AX)
MOVQ AX, (g_sched+gobuf_g)(AX)
+ MOVQ BP, (g_sched+gobuf_bp)(AX)
// switch to g0
MOVQ DX, g(CX)
LEAQ 8(SP), AX // f's SP
MOVQ AX, (g_sched+gobuf_sp)(SI)
MOVQ DX, (g_sched+gobuf_ctxt)(SI)
+ MOVQ BP, (g_sched+gobuf_bp)(SI)
// Call newstack on m->g0's stack.
- MOVQ m_g0(BX), BP
- MOVQ BP, g(CX)
- MOVQ (g_sched+gobuf_sp)(BP), SP
+ MOVQ m_g0(BX), BX
+ MOVQ BX, g(CX)
+ MOVQ (g_sched+gobuf_sp)(BX), SP
CALL runtime·newstack(SB)
MOVQ $0, 0x1003 // crash if newstack returns
RET
MOVQ R9, (g_sched+gobuf_sp)(R8)
MOVQ $0, (g_sched+gobuf_ret)(R8)
MOVQ $0, (g_sched+gobuf_ctxt)(R8)
+ MOVQ BP, (g_sched+gobuf_bp)(R8)
RET
// asmcgocall(void(*fn)(void*), void *arg)
// We get called to create new OS threads too, and those
// come in on the m->g0 stack already.
get_tls(CX)
- MOVQ g(CX), BP
- MOVQ g_m(BP), BP
- MOVQ m_g0(BP), SI
+ MOVQ g(CX), R8
+ MOVQ g_m(R8), R8
+ MOVQ m_g0(R8), SI
MOVQ g(CX), DI
CMPQ SI, DI
JEQ nosave
- MOVQ m_gsignal(BP), SI
+ MOVQ m_gsignal(R8), SI
CMPQ SI, DI
JEQ nosave
- MOVQ m_g0(BP), SI
+ MOVQ m_g0(R8), SI
CALL gosave<>(SB)
MOVQ SI, g(CX)
MOVQ (g_sched+gobuf_sp)(SI), SP
// the linker analysis by using an indirect call through AX.
get_tls(CX)
#ifdef GOOS_windows
- MOVL $0, BP
+ MOVL $0, BX
CMPQ CX, $0
JEQ 2(PC)
#endif
- MOVQ g(CX), BP
- CMPQ BP, $0
+ MOVQ g(CX), BX
+ CMPQ BX, $0
JEQ needm
- MOVQ g_m(BP), BP
- MOVQ BP, R8 // holds oldm until end of function
+ MOVQ g_m(BX), BX
+ MOVQ BX, R8 // holds oldm until end of function
JMP havem
needm:
MOVQ $0, 0(SP)
CALL AX
MOVQ 0(SP), R8
get_tls(CX)
- MOVQ g(CX), BP
- MOVQ g_m(BP), BP
+ MOVQ g(CX), BX
+ MOVQ g_m(BX), BX
// Set m->sched.sp = SP, so that if a panic happens
// during the function we are about to execute, it will
// and then systemstack will try to use it. If we don't set it here,
// that restored SP will be uninitialized (typically 0) and
// will not be usable.
- MOVQ m_g0(BP), SI
+ MOVQ m_g0(BX), SI
MOVQ SP, (g_sched+gobuf_sp)(SI)
havem:
// Save current sp in m->g0->sched.sp in preparation for
// switch back to m->curg stack.
// NOTE: unwindm knows that the saved g->sched.sp is at 0(SP).
- MOVQ m_g0(BP), SI
+ MOVQ m_g0(BX), SI
MOVQ (g_sched+gobuf_sp)(SI), AX
MOVQ AX, 0(SP)
MOVQ SP, (g_sched+gobuf_sp)(SI)
// the earlier calls.
//
// In the new goroutine, 0(SP) holds the saved R8.
- MOVQ m_curg(BP), SI
+ MOVQ m_curg(BX), SI
MOVQ SI, g(CX)
MOVQ (g_sched+gobuf_sp)(SI), DI // prepare stack as DI
- MOVQ (g_sched+gobuf_pc)(SI), BP
- MOVQ BP, -8(DI)
- LEAQ -(8+8)(DI), SP
+ MOVQ (g_sched+gobuf_pc)(SI), BX
+ MOVQ BX, -8(DI)
+ // Compute the size of the frame, including return PC and, if
+ // GOEXPERIMENT=framepointer, the saved based pointer
+ LEAQ x+0(FP), AX
+ SUBQ SP, AX
+ SUBQ AX, DI
+ MOVQ DI, SP
+
MOVQ R8, 0(SP)
CALL runtime·cgocallbackg(SB)
MOVQ 0(SP), R8
+ // Compute the size of the frame again. FP and SP have
+ // completely different values here than they did above,
+ // but only their difference matters.
+ LEAQ x+0(FP), AX
+ SUBQ SP, AX
+
// Restore g->sched (== m->curg->sched) from saved values.
get_tls(CX)
MOVQ g(CX), SI
- MOVQ 8(SP), BP
- MOVQ BP, (g_sched+gobuf_pc)(SI)
- LEAQ (8+8)(SP), DI
+ MOVQ SP, DI
+ ADDQ AX, DI
+ MOVQ -8(DI), BX
+ MOVQ BX, (g_sched+gobuf_pc)(SI)
MOVQ DI, (g_sched+gobuf_sp)(SI)
// Switch back to m->g0's stack and restore m->g0->sched.sp.
// (Unlike m->curg, the g0 goroutine never uses sched.pc,
// so we do not have to restore it.)
- MOVQ g(CX), BP
- MOVQ g_m(BP), BP
- MOVQ m_g0(BP), SI
+ MOVQ g(CX), BX
+ MOVQ g_m(BX), BX
+ MOVQ m_g0(BX), SI
MOVQ SI, g(CX)
MOVQ (g_sched+gobuf_sp)(SI), SP
MOVQ 0(SP), AX
// a page boundary, so we can load it directly.
MOVOU -16(AX), X0
ADDQ CX, CX
- MOVQ $masks<>(SB), BP
- PAND (BP)(CX*8), X0
+ MOVQ $masks<>(SB), AX
+ PAND (AX)(CX*8), X0
// scramble 3 times
AESENC X6, X0
// Then shift bytes down using pshufb.
MOVOU -32(AX)(CX*1), X0
ADDQ CX, CX
- MOVQ $shifts<>(SB), BP
- PSHUFB (BP)(CX*8), X0
+ MOVQ $shifts<>(SB), AX
+ PSHUFB (AX)(CX*8), X0
AESENC X6, X0
AESENC X7, X0
AESENC X7, X0
CMPQ SI, DI
JEQ allsame
CMPQ BX, DX
- MOVQ DX, BP
- CMOVQLT BX, BP // BP = min(alen, blen) = # of bytes to compare
- CMPQ BP, $8
+ MOVQ DX, R8
+ CMOVQLT BX, R8 // R8 = min(alen, blen) = # of bytes to compare
+ CMPQ R8, $8
JB small
loop:
- CMPQ BP, $16
+ CMPQ R8, $16
JBE _0through16
MOVOU (SI), X0
MOVOU (DI), X1
JNE diff16 // branch if at least one byte is not equal
ADDQ $16, SI
ADDQ $16, DI
- SUBQ $16, BP
+ SUBQ $16, R8
JMP loop
// AX = bit mask of differences
// 0 through 16 bytes left, alen>=8, blen>=8
_0through16:
- CMPQ BP, $8
+ CMPQ R8, $8
JBE _0through8
MOVQ (SI), AX
MOVQ (DI), CX
CMPQ AX, CX
JNE diff8
_0through8:
- MOVQ -8(SI)(BP*1), AX
- MOVQ -8(DI)(BP*1), CX
+ MOVQ -8(SI)(R8*1), AX
+ MOVQ -8(DI)(R8*1), CX
CMPQ AX, CX
JEQ allsame
// 0-7 bytes in common
small:
- LEAQ (BP*8), CX // bytes left -> bits left
+ LEAQ (R8*8), CX // bytes left -> bits left
NEGQ CX // - bits lift (== 64 - bits left mod 64)
JEQ allsame
MOVQ (SI), SI
JMP si_finish
si_high:
- MOVQ -8(SI)(BP*1), SI
+ MOVQ -8(SI)(R8*1), SI
SHRQ CX, SI
si_finish:
SHLQ CX, SI
MOVQ (DI), DI
JMP di_finish
di_high:
- MOVQ -8(DI)(BP*1), DI
+ MOVQ -8(DI)(R8*1), DI
SHRQ CX, DI
di_finish:
SHLQ CX, DI
cb = (*args)(unsafe.Pointer(sp + 4*ptrSize))
case "amd64":
// On amd64, stack frame is one word, plus caller PC.
+ if framepointer_enabled {
+ // In this case, there's also saved BP.
+ cb = (*args)(unsafe.Pointer(sp + 3*ptrSize))
+ break
+ }
cb = (*args)(unsafe.Pointer(sp + 2*ptrSize))
case "386":
// On 386, stack frame is three words, plus caller PC.
if !block {
return false
}
- gopark(nil, nil, "chan send (nil chan)")
+ gopark(nil, nil, "chan send (nil chan)", traceEvGoStop)
throw("unreachable")
}
mysg.selectdone = nil
gp.param = nil
c.sendq.enqueue(mysg)
- goparkunlock(&c.lock, "chan send")
+ goparkunlock(&c.lock, "chan send", traceEvGoBlockSend)
// someone woke us up.
if mysg != gp.waiting {
mysg.elem = nil
mysg.selectdone = nil
c.sendq.enqueue(mysg)
- goparkunlock(&c.lock, "chan send")
+ goparkunlock(&c.lock, "chan send", traceEvGoBlockSend)
// someone woke us up - try again
if mysg.releasetime > 0 {
if !block {
return
}
- gopark(nil, nil, "chan receive (nil chan)")
+ gopark(nil, nil, "chan receive (nil chan)", traceEvGoStop)
throw("unreachable")
}
mysg.selectdone = nil
gp.param = nil
c.recvq.enqueue(mysg)
- goparkunlock(&c.lock, "chan receive")
+ goparkunlock(&c.lock, "chan receive", traceEvGoBlockRecv)
// someone woke us up
if mysg != gp.waiting {
mysg.selectdone = nil
c.recvq.enqueue(mysg)
- goparkunlock(&c.lock, "chan receive")
+ goparkunlock(&c.lock, "chan receive", traceEvGoBlockRecv)
// someone woke us up - try again
if mysg.releasetime > 0 {
semacquire(&worldsema, false)
gp := getg()
- gp.m.gcing = 1
+ gp.m.preemptoff = "GOMAXPROCS"
systemstack(stoptheworld)
// newprocs will be processed by starttheworld
newprocs = int32(n)
- gp.m.gcing = 0
+ gp.m.preemptoff = ""
semrelease(&worldsema)
systemstack(starttheworld)
return ret
_ITIMER_PROF = 0x2
_ITIMER_VIRTUAL = 0x1
_O_RDONLY = 0
- _O_CLOEXEC = 02000000
+ _O_CLOEXEC = 0x80000
_EPOLLIN = 0x1
_EPOLLOUT = 0x4
_EPOLL_CTL_ADD = 0x1
_EPOLL_CTL_DEL = 0x2
_EPOLL_CTL_MOD = 0x3
+
+ _AF_UNIX = 0x1
+ _F_SETFL = 0x4
+ _SOCK_DGRAM = 0x2
)
type timespec struct {
_pad uint32
data [8]byte // to match amd64
}
+
+type sockaddr_un struct {
+ family uint16
+ path [108]byte
+}
}
type ParFor struct {
- body *byte
- done uint32
- Nthr uint32
- nthrmax uint32
- thrseq uint32
- Cnt uint32
- Ctx *byte
- wait bool
+ body func(*ParFor, uint32)
+ done uint32
+ Nthr uint32
+ thrseq uint32
+ Cnt uint32
+ wait bool
}
func NewParFor(nthrmax uint32) *ParFor {
return desc
}
-func ParForSetup(desc *ParFor, nthr, n uint32, ctx *byte, wait bool, body func(*ParFor, uint32)) {
+func ParForSetup(desc *ParFor, nthr, n uint32, wait bool, body func(*ParFor, uint32)) {
systemstack(func() {
- parforsetup((*parfor)(unsafe.Pointer(desc)), nthr, n, unsafe.Pointer(ctx), wait,
+ parforsetup((*parfor)(unsafe.Pointer(desc)), nthr, n, wait,
*(*func(*parfor, uint32))(unsafe.Pointer(&body)))
})
}
func ParForIters(desc *ParFor, tid uint32) (uint32, uint32) {
desc1 := (*parfor)(unsafe.Pointer(desc))
- pos := desc_thr_index(desc1, tid).pos
+ pos := desc1.thr[tid].pos
return uint32(pos), uint32(pos >> 32)
}
This should only be used as a temporary workaround to diagnose buggy code.
The real fix is to not store integers in pointer-typed locations.
+ memprofilerate: setting memprofilerate=X will update the value of runtime.MemProfileRate.
+ When set to 0 memory profiling is disabled. Refer to the description of
+ MemProfileRate for the default value.
+
scheddetail: setting schedtrace=X and scheddetail=1 causes the scheduler to emit
detailed multiline info every X milliseconds, describing state of the scheduler,
processors, threads and goroutines.
// Note: the format of the Hmap is encoded in ../../cmd/gc/reflect.c and
// ../reflect/type.go. Don't change this structure without also changing that code!
count int // # live cells == size of map. Must be first (used by len() builtin)
- flags uint32
- hash0 uint32 // hash seed
+ flags uint8
B uint8 // log_2 of # of buckets (can hold up to loadFactor * 2^B items)
+ hash0 uint32 // hash seed
buckets unsafe.Pointer // array of 2^B Buckets. may be nil if count==0.
oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing
nevacuate uintptr // progress counter for evacuation (buckets less than this have been evacuated)
+
+ // If both key and value do not contain pointers, then we mark bucket
+ // type as containing no pointers. This avoids scanning such maps.
+ // However, bmap.overflow is a pointer. In order to keep overflow buckets
+ // alive, we store pointers to all overflow buckets in hmap.overflow.
+ // Overflow is used only if key and value do not contain pointers.
+ // overflow[0] contains overflow buckets for hmap.buckets.
+ // overflow[1] contains overflow buckets for hmap.oldbuckets.
+ // The first indirection allows us to reduce static size of hmap.
+ // The second indirection allows to store a pointer to the slice in hiter.
+ overflow *[2]*[]*bmap
}
// A bucket for a Go map.
h *hmap
buckets unsafe.Pointer // bucket ptr at hash_iter initialization time
bptr *bmap // current bucket
+ overflow [2]*[]*bmap // keeps overflow buckets alive
startBucket uintptr // bucket iteration started at
offset uint8 // intra-bucket offset to start from during iteration (should be big enough to hold bucketCnt-1)
wrapped bool // already wrapped around from end of bucket array to beginning
func (b *bmap) overflow(t *maptype) *bmap {
return *(**bmap)(add(unsafe.Pointer(b), uintptr(t.bucketsize)-regSize))
}
-func (b *bmap) setoverflow(t *maptype, ovf *bmap) {
+
+func (h *hmap) setoverflow(t *maptype, b, ovf *bmap) {
+ if t.bucket.kind&kindNoPointers != 0 {
+ h.createOverflow()
+ *h.overflow[0] = append(*h.overflow[0], ovf)
+ }
*(**bmap)(add(unsafe.Pointer(b), uintptr(t.bucketsize)-regSize)) = ovf
}
+func (h *hmap) createOverflow() {
+ if h.overflow == nil {
+ h.overflow = new([2]*[]*bmap)
+ }
+ if h.overflow[0] == nil {
+ h.overflow[0] = new([]*bmap)
+ }
+}
+
func makemap(t *maptype, hint int64) *hmap {
if sz := unsafe.Sizeof(hmap{}); sz > 48 || sz != uintptr(t.hmap.size) {
throw("bad hmap size")
memstats.next_gc = memstats.heap_alloc
}
newb := (*bmap)(newobject(t.bucket))
- b.setoverflow(t, newb)
+ h.setoverflow(t, b, newb)
inserti = &newb.tophash[0]
insertk = add(unsafe.Pointer(newb), dataOffset)
insertv = add(insertk, bucketCnt*uintptr(t.keysize))
it.h = nil
it.buckets = nil
it.bptr = nil
+ it.overflow[0] = nil
+ it.overflow[1] = nil
if raceenabled && h != nil {
callerpc := getcallerpc(unsafe.Pointer(&t))
return
}
- if unsafe.Sizeof(hiter{})/ptrSize != 10 {
+ if unsafe.Sizeof(hiter{})/ptrSize != 12 {
throw("hash_iter size incorrect") // see ../../cmd/gc/reflect.c
}
it.t = t
// grab snapshot of bucket state
it.B = h.B
it.buckets = h.buckets
+ if t.bucket.kind&kindNoPointers != 0 {
+ // Allocate the current slice and remember pointers to both current and old.
+ // This preserves all relevant overflow buckets alive even if
+ // the table grows and/or overflow buckets are added to the table
+ // while we are iterating.
+ h.createOverflow()
+ it.overflow = *h.overflow
+ }
// decide where to start
r := uintptr(fastrand1())
// Remember we have an iterator.
// Can run concurrently with another hash_iter_init().
- for {
- old := h.flags
- if old == old|iterator|oldIterator {
- break
- }
- if cas(&h.flags, old, old|iterator|oldIterator) {
- break
- }
+ if old := h.flags; old&(iterator|oldIterator) != iterator|oldIterator {
+ atomicor8(&h.flags, iterator|oldIterator)
}
mapiternext(it)
h.buckets = newbuckets
h.nevacuate = 0
+ if h.overflow != nil {
+ // Promote current overflow buckets to the old generation.
+ if h.overflow[1] != nil {
+ throw("overflow is not nil")
+ }
+ h.overflow[1] = h.overflow[0]
+ h.overflow[0] = nil
+ }
+
// the actual copying of the hash table data is done incrementally
// by growWork() and evacuate().
}
memstats.next_gc = memstats.heap_alloc
}
newx := (*bmap)(newobject(t.bucket))
- x.setoverflow(t, newx)
+ h.setoverflow(t, x, newx)
x = newx
xi = 0
xk = add(unsafe.Pointer(x), dataOffset)
memstats.next_gc = memstats.heap_alloc
}
newy := (*bmap)(newobject(t.bucket))
- y.setoverflow(t, newy)
+ h.setoverflow(t, y, newy)
y = newy
yi = 0
yk = add(unsafe.Pointer(y), dataOffset)
if oldbucket+1 == newbit { // newbit == # of oldbuckets
// Growing is all done. Free old main bucket array.
h.oldbuckets = nil
+ // Can discard old overflow buckets as well.
+ // If they are still referenced by an iterator,
+ // then the iterator holds a pointers to the slice.
+ if h.overflow != nil {
+ h.overflow[1] = nil
+ }
}
}
}
func notetsleep(n *note, ns int64) bool {
gp := getg()
- if gp != gp.m.g0 && gp.m.gcing == 0 {
+ if gp != gp.m.g0 && gp.m.preemptoff != "" {
throw("notetsleep not on g0")
}
func notetsleep(n *note, ns int64) bool {
gp := getg()
- if gp != gp.m.g0 && gp.m.gcing == 0 {
+ if gp != gp.m.g0 && gp.m.preemptoff != "" {
throw("notetsleep not on g0")
}
if gp.m.waitsema == 0 {
// base address for all 0-byte allocations
var zerobase uintptr
+// Trigger the concurrent GC when 1/triggerratio memory is available to allocate.
+// Adjust this ratio as part of a scheme to ensure that mutators have enough
+// memory to allocate in durring a concurrent GC cycle.
+var triggerratio = int64(8)
+
// Determine whether to initiate a GC.
-// Currently the primitive heuristic we use will start a new
-// concurrent GC when approximately half the available space
-// made available by the last GC cycle has been used.
// If the GC is already working no need to trigger another one.
// This should establish a feedback loop where if the GC does not
// have sufficient time to complete then more memory will be
// A false negative simple does not start a GC, a false positive
// will start a GC needlessly. Neither have correctness issues.
func shouldtriggergc() bool {
- return memstats.heap_alloc+memstats.heap_alloc*3/4 >= memstats.next_gc && atomicloaduint(&bggc.working) == 0
+ return triggerratio*(int64(memstats.next_gc)-int64(memstats.heap_alloc)) <= int64(memstats.next_gc) && atomicloaduint(&bggc.working) == 0
}
// Allocate an object of size bytes.
// Ok, we're doing it! Stop everybody else
mp := acquirem()
- mp.gcing = 1
+ mp.preemptoff = "gcing"
releasem(mp)
gctimer.count++
if force == 0 {
gctimer.cycle.sweepterm = nanotime()
}
+
+ if trace.enabled {
+ traceGoSched()
+ traceGCStart()
+ }
+
// Pick up the remaining unswept/not being swept spans before we STW
for gosweepone() != ^uintptr(0) {
sweep.nbgsweep++
gctimer.cycle.markterm = nanotime()
systemstack(stoptheworld)
systemstack(gcinstalloffwb_m)
+ } else {
+ // For non-concurrent GC (force != 0) g stack have not been scanned so
+ // set gcscanvalid such that mark termination scans all stacks.
+ // No races here since we are in a STW phase.
+ for _, gp := range allgs {
+ gp.gcworkdone = false // set to true in gcphasework
+ gp.gcscanvalid = false // stack has not been scanned
+ }
}
startTime := nanotime()
gccheckmark_m(startTime, eagersweep)
})
+ if trace.enabled {
+ traceGCDone()
+ traceGoStart()
+ }
+
// all done
- mp.gcing = 0
+ mp.preemptoff = ""
if force == 0 {
gctimer.cycle.sweep = nanotime()
h := &mheap_
memstats.heap_alloc += uint64(c.local_cachealloc)
c.local_cachealloc = 0
+ if trace.enabled {
+ traceHeapAlloc()
+ }
memstats.tinyallocs += uint64(c.local_tinyallocs)
c.local_tinyallocs = 0
memstats.nlookup += uint64(c.local_nlookup)
nbit int32 // number of bits in each bitmap
bytedata [1]byte // bitmaps, each starting on a 32-bit boundary
}
-
-// Returns pointer map data for the given stackmap index
-// (the index is encoded in PCDATA_StackMapIndex).
-
-// defined in mgc0.go
}
}
+func TestStringConcatenationAllocs(t *testing.T) {
+ n := testing.AllocsPerRun(1e3, func() {
+ b := make([]byte, 10)
+ for i := 0; i < 10; i++ {
+ b[i] = byte(i) + '0'
+ }
+ s := "foo" + string(b)
+ if want := "foo0123456789"; s != want {
+ t.Fatalf("want %v, got %v", want, s)
+ }
+ })
+ // Only string concatenation allocates.
+ if n != 1 {
+ t.Fatalf("want 1 allocation, got %v", n)
+ }
+}
+
var mallocSink uintptr
func BenchmarkMalloc8(b *testing.B) {
return
}
- if src != 0 && (src < _PageSize || src == poisonStack) {
+ if src != 0 && (src < _PhysPageSize || src == poisonStack) {
systemstack(func() { throw("bad pointer in write barrier") })
}
if mheap_.shadow_enabled {
- systemstack(func() {
- addr := uintptr(unsafe.Pointer(dst))
- shadow := shadowptr(addr)
- if shadow == nil {
- return
- }
- // There is a race here but only if the program is using
- // racy writes instead of sync/atomic. In that case we
- // don't mind crashing.
- if *shadow != *dst && *shadow != noShadow && istrackedptr(*dst) {
- mheap_.shadow_enabled = false
- print("runtime: write barrier dst=", dst, " old=", hex(*dst), " shadow=", shadow, " old=", hex(*shadow), " new=", hex(src), "\n")
- throw("missed write barrier")
- }
- *shadow = src
- })
+ writebarrierptr_shadow(dst, src)
}
*dst = src
writebarrierptr_nostore1(dst, src)
}
+//go:nosplit
+func writebarrierptr_shadow(dst *uintptr, src uintptr) {
+ systemstack(func() {
+ addr := uintptr(unsafe.Pointer(dst))
+ shadow := shadowptr(addr)
+ if shadow == nil {
+ return
+ }
+ // There is a race here but only if the program is using
+ // racy writes instead of sync/atomic. In that case we
+ // don't mind crashing.
+ if *shadow != *dst && *shadow != noShadow && istrackedptr(*dst) {
+ mheap_.shadow_enabled = false
+ print("runtime: write barrier dst=", dst, " old=", hex(*dst), " shadow=", shadow, " old=", hex(*shadow), " new=", hex(src), "\n")
+ throw("missed write barrier")
+ }
+ *shadow = src
+ })
+}
+
// Like writebarrierptr, but the store has already been applied.
// Do not reapply.
//go:nosplit
return
}
- if src != 0 && (src < _PageSize || src == poisonStack) {
+ if src != 0 && (src < _PhysPageSize || src == poisonStack) {
systemstack(func() { throw("bad pointer in write barrier") })
}
if end < uintptr(unsafe.Pointer(&ebss)) {
end = uintptr(unsafe.Pointer(&ebss))
}
- start &^= _PageSize - 1
- end = round(end, _PageSize)
+ start &^= _PhysPageSize - 1
+ end = round(end, _PhysPageSize)
mheap_.data_start = start
mheap_.data_end = end
reserved = false
// a pending garbage collection already calling it.
semacquire(&worldsema, false)
gp := getg()
- gp.m.gcing = 1
+ gp.m.preemptoff = "read mem stats"
systemstack(stoptheworld)
systemstack(func() {
readmemstats_m(m)
})
- gp.m.gcing = 0
+ gp.m.preemptoff = ""
gp.m.locks++
semrelease(&worldsema)
systemstack(starttheworld)
func runtime_debug_WriteHeapDump(fd uintptr) {
semacquire(&worldsema, false)
gp := getg()
- gp.m.gcing = 1
+ gp.m.preemptoff = "write heap dump"
systemstack(stoptheworld)
systemstack(func() {
writeheapdump_m(fd)
})
- gp.m.gcing = 0
+ gp.m.preemptoff = ""
gp.m.locks++
semrelease(&worldsema)
systemstack(starttheworld)
var bloc uintptr
var memlock mutex
-const memRound = _PAGESIZE - 1
+func memRound(p uintptr) uintptr {
+ return (p + _PAGESIZE - 1) &^ (_PAGESIZE - 1)
+}
func initBloc() {
- bloc = uintptr(unsafe.Pointer(&end))
+ bloc = memRound(uintptr(unsafe.Pointer(&end)))
}
func sbrk(n uintptr) unsafe.Pointer {
lock(&memlock)
// Plan 9 sbrk from /sys/src/libc/9sys/sbrk.c
- bl := (bloc + memRound) &^ memRound
+ bl := bloc
+ n = memRound(n)
if brk_(unsafe.Pointer(bl+n)) < 0 {
unlock(&memlock)
return nil
}
- bloc = bl + n
+ bloc += n
unlock(&memlock)
return unsafe.Pointer(bl)
}
// from tiny/mem.c
// Push pointer back if this is a free
// of the most recent sysAlloc.
- n += (n + memRound) &^ memRound
+ n = memRound(n)
if bloc == uintptr(v)+n {
bloc -= n
}
fing = gp
fingwait = true
gp.issystem = true
- goparkunlock(&finlock, "finalizer wait")
+ goparkunlock(&finlock, "finalizer wait", traceEvGoBlock)
gp.issystem = false
continue
}
racefingo()
}
for fb != nil {
- for i := int32(0); i < fb.cnt; i++ {
- f := (*finalizer)(add(unsafe.Pointer(&fb.fin), uintptr(i)*unsafe.Sizeof(finalizer{})))
+ for i := fb.cnt; i > 0; i-- {
+ f := (*finalizer)(add(unsafe.Pointer(&fb.fin), uintptr(i-1)*unsafe.Sizeof(finalizer{})))
framesz := unsafe.Sizeof((interface{})(nil)) + uintptr(f.nret)
if framecap < framesz {
f.fn = nil
f.arg = nil
f.ot = nil
+ fb.cnt = i - 1
}
- fb.cnt = 0
next := fb.next
lock(&finlock)
fb.next = finc
// The procedure is:
//
// semacquire(&worldsema);
-// m.gcing = 1;
+// m.preemptoff = "reason";
// stoptheworld();
//
// ... do stuff ...
//
-// m.gcing = 0;
+// m.preemptoff = "";
// semrelease(&worldsema);
// starttheworld();
//
print("runtime:greyobject: checkmarks finds unexpected unmarked object obj=", hex(obj), "\n")
print("runtime: found obj at *(", hex(base), "+", hex(off), ")\n")
+ // Dump the source (base) object
+
+ kb := base >> _PageShift
+ xb := kb
+ xb -= mheap_.arena_start >> _PageShift
+ sb := h_spans[xb]
+ printlock()
+ print("runtime:greyobject Span: base=", hex(base), " kb=", hex(kb))
+ if sb == nil {
+ print(" sb=nil\n")
+ } else {
+ print(" sb.start*_PageSize=", hex(sb.start*_PageSize), " sb.limit=", hex(sb.limit), " sb.sizeclass=", sb.sizeclass, " sb.elemsize=", sb.elemsize, "\n")
+ // base is (a pointer to) the source object holding the reference to object. Create a pointer to each of the fields
+ // fields in base and print them out as hex values.
+ for i := 0; i < int(sb.elemsize/ptrSize); i++ {
+ print(" *(base+", i*ptrSize, ") = ", hex(*(*uintptr)(unsafe.Pointer(base + uintptr(i)*ptrSize))), "\n")
+ }
+ }
+
+ // Dump the object
+
k := obj >> _PageShift
x := k
x -= mheap_.arena_start >> _PageShift
s := h_spans[x]
- printlock()
print("runtime:greyobject Span: obj=", hex(obj), " k=", hex(k))
if s == nil {
print(" s=nil\n")
}
}
-// Scan at most count objects in the wbuf.
+// Scan count objects starting with those in wbuf.
//go:nowritebarrier
func drainobjects(wbuf *workbuf, count uintptr) {
for i := uintptr(0); i < count; i++ {
if wbuf.nobj == 0 {
putempty(wbuf)
- return
+ wbuf = trygetfull()
+ if wbuf == nil {
+ return
+ }
}
// This might be a good place to add prefetch code...
}
// Shrink a stack if not much of it is being used but not in the scan phase.
- if gcphase != _GCscan { // Do not shrink during GCscan phase.
+ if gcphase == _GCmarktermination {
+ // Shrink during STW GCmarktermination phase thus avoiding
+ // complications introduced by shrinking during
+ // non-STW phases.
shrinkstack(gp)
}
if readgstatus(gp) == _Gdead {
//go:nowritebarrier
func scanstack(gp *g) {
+ if gp.gcscanvalid {
+ return
+ }
if readgstatus(gp)&_Gscan == 0 {
print("runtime:scanstack: gp=", gp, ", goid=", gp.goid, ", gp->atomicstatus=", hex(readgstatus(gp)), "\n")
gentraceback(^uintptr(0), ^uintptr(0), 0, gp, 0, nil, 0x7fffffff, scanframe, nil, 0)
tracebackdefers(gp, scanframe, nil)
+ gp.gcscanvalid = true
}
// Shade the object if it isn't already.
case _GCscan:
// scan the stack, mark the objects, put pointers in work buffers
// hanging off the P where this is being run.
+ // Indicate that the scan is valid until the goroutine runs again
scanstack(gp)
case _GCmark:
// No work.
print("MSpan_Sweep: state=", s.state, " sweepgen=", s.sweepgen, " mheap.sweepgen=", sweepgen, "\n")
throw("MSpan_Sweep: bad span state")
}
+
+ if trace.enabled {
+ traceGCSweepStart()
+ }
+
cl := s.sizeclass
size := s.elemsize
res := false
}
c.local_nlargefree++
c.local_largefree += size
- xadd64(&memstats.next_gc, -int64(size)*int64(gcpercent+100)/100)
+ reduction := int64(size) * int64(gcpercent+100) / 100
+ if int64(memstats.next_gc)-reduction > int64(heapminimum) {
+ xadd64(&memstats.next_gc, -reduction)
+ } else {
+ atomicstore64(&memstats.next_gc, heapminimum)
+ }
res = true
} else {
// Free small object.
if nfree > 0 {
c.local_nsmallfree[cl] += uintptr(nfree)
c.local_cachealloc -= intptr(uintptr(nfree) * size)
- xadd64(&memstats.next_gc, -int64(nfree)*int64(size)*int64(gcpercent+100)/100)
+ reduction := int64(nfree) * int64(size) * int64(gcpercent+100) / 100
+ if int64(memstats.next_gc)-reduction > int64(heapminimum) {
+ xadd64(&memstats.next_gc, -reduction)
+ } else {
+ atomicstore64(&memstats.next_gc, heapminimum)
+ }
res = mCentral_FreeSpan(&mheap_.central[cl].mcentral, s, int32(nfree), head, end, preserve)
// MCentral_FreeSpan updates sweepgen
}
+ if trace.enabled {
+ traceGCSweepDone()
+ traceNextGC()
+ }
return res
}
_g_.m.traceback = 2
gchelperstart()
+ if trace.enabled {
+ traceGCScanStart()
+ }
+
// parallel mark for over GC roots
parfordo(work.markfor)
if gcphase != _GCscan {
scanblock(0, 0, nil) // blocks in getfull
}
+ if trace.enabled {
+ traceGCScanDone()
+ }
+
nproc := work.nproc // work.nproc can change right after we increment work.ndone
if xadd(&work.ndone, +1) == nproc-1 {
notewakeup(&work.alldone)
memstats.heap_objects = memstats.nmalloc - memstats.nfree
}
+// heapminimum is the minimum number of bytes in the heap.
+// This cleans up the corner case of where we have a very small live set but a lot
+// of allocations and collecting every GOGC * live set is expensive.
+var heapminimum = uint64(4 << 20)
+
func gcinit() {
if unsafe.Sizeof(workbuf{}) != _WorkbufSize {
throw("runtime: size of Workbuf is suboptimal")
gcpercent = readgogc()
gcdatamask = unrollglobgcprog((*byte)(unsafe.Pointer(&gcdata)), uintptr(unsafe.Pointer(&edata))-uintptr(unsafe.Pointer(&data)))
gcbssmask = unrollglobgcprog((*byte)(unsafe.Pointer(&gcbss)), uintptr(unsafe.Pointer(&ebss))-uintptr(unsafe.Pointer(&bss)))
+ memstats.next_gc = heapminimum
}
-// Called from malloc.go using onM, stopping and starting the world handled in caller.
+// Called from malloc.go using systemstack, stopping and starting the world handled in caller.
//go:nowritebarrier
func gc_m(start_time int64, eagersweep bool) {
_g_ := getg()
}
}
-// Called from malloc.go using onM.
+// Called from malloc.go using systemstack.
// The world is stopped. Rerun the scan and mark phases
// using the bitMarkedCheck bit instead of the
// bitMarked bit. If the marking encounters an
local_allglen := allglen
for i := uintptr(0); i < local_allglen; i++ {
gp := allgs[i]
- gp.gcworkdone = false // set to true in gcphasework
+ gp.gcworkdone = false // set to true in gcphasework
+ gp.gcscanvalid = false // stack has not been scanned
}
unlock(&allglock)
work.ndone = 0
work.nproc = 1 // For now do not do this in parallel.
// ackgcphase is not needed since we are not scanning running goroutines.
- parforsetup(work.markfor, work.nproc, uint32(_RootCount+local_allglen), nil, false, markroot)
+ parforsetup(work.markfor, work.nproc, uint32(_RootCount+local_allglen), false, markroot)
parfordo(work.markfor)
lock(&allglock)
gp.gcworkdone = false // set to true in gcphasework
}
- parforsetup(work.markfor, work.nproc, uint32(_RootCount+allglen), nil, false, markroot)
+ if trace.enabled {
+ traceGCScanStart()
+ }
+
+ parforsetup(work.markfor, work.nproc, uint32(_RootCount+allglen), false, markroot)
if work.nproc > 1 {
noteclear(&work.alldone)
helpgc(int32(work.nproc))
notesleep(&work.alldone)
}
+ if trace.enabled {
+ traceGCScanDone()
+ }
+
shrinkfinish()
cachestats()
// conservatively set next_gc to high value assuming that everything is live
// concurrent/lazy sweep will reduce this number while discovering new garbage
memstats.next_gc = memstats.heap_alloc + memstats.heap_alloc*uint64(gcpercent)/100
+ if memstats.next_gc < heapminimum {
+ memstats.next_gc = heapminimum
+ }
+
+ if trace.enabled {
+ traceNextGC()
+ }
t4 := nanotime()
atomicstore64(&memstats.last_gc, uint64(unixnanotime())) // must be Unix time to make sense to user
gcwork(0)
lock(&bggc.lock)
bggc.working = 0
- goparkunlock(&bggc.lock, "Concurrent GC wait")
+ goparkunlock(&bggc.lock, "Concurrent GC wait", traceEvGoBlock)
}
}
continue
}
sweep.parked = true
- goparkunlock(&gclock, "GC sweep wait")
+ goparkunlock(&gclock, "GC sweep wait", traceEvGoBlock)
}
}
}
}
}
+ if trace.enabled {
+ traceHeapAlloc()
+ }
unlock(&h.lock)
return s
}
memstats.heap_objects--
}
mHeap_FreeSpanLocked(h, s, true, true)
+ if trace.enabled {
+ traceHeapAlloc()
+ }
unlock(&h.lock)
})
}
if n <= len(p) {
gp := getg()
semacquire(&worldsema, false)
- gp.m.gcing = 1
+ gp.m.preemptoff = "profile"
systemstack(stoptheworld)
n = NumGoroutine()
}
}
- gp.m.gcing = 0
+ gp.m.preemptoff = ""
semrelease(&worldsema)
systemstack(starttheworld)
}
if all {
semacquire(&worldsema, false)
gp := getg()
- gp.m.gcing = 1
+ gp.m.preemptoff = "stack trace"
systemstack(stoptheworld)
}
if all {
gp := getg()
- gp.m.gcing = 0
+ gp.m.preemptoff = ""
semrelease(&worldsema)
systemstack(starttheworld)
}
var (
netpollInited uint32
- pollcache pollCache
+ pollcache pollCache
)
//go:linkname net_runtime_pollServerInit net.runtime_pollServerInit
// this is necessary because runtime_pollUnblock/runtime_pollSetDeadline/deadlineimpl
// do the opposite: store to closing/rd/wd, membarrier, load of rg/wg
if waitio || netpollcheckerr(pd, mode) == 0 {
- gopark(netpollblockcommit, unsafe.Pointer(gpp), "IO wait")
+ gopark(netpollblockcommit, unsafe.Pointer(gpp), "IO wait", traceEvGoBlockNet)
}
// be careful to not lose concurrent READY notification
old := xchguintptr(gpp, 0)
print("\n")
throw("panic during malloc")
}
- if gp.m.gcing != 0 {
+ if gp.m.preemptoff != "" {
print("panic: ")
printany(e)
print("\n")
- throw("panic during gc")
+ print("preempt off reason: ")
+ print(gp.m.preemptoff)
+ print("\n")
+ throw("panic during preemptoff")
}
if gp.m.locks != 0 {
print("panic: ")
if gp == nil || gp != _m_.curg {
return false
}
- if _m_.locks-_m_.softfloat != 0 || _m_.mallocing != 0 || _m_.throwing != 0 || _m_.gcing != 0 || _m_.dying != 0 {
+ if _m_.locks-_m_.softfloat != 0 || _m_.mallocing != 0 || _m_.throwing != 0 || _m_.preemptoff != "" || _m_.dying != 0 {
return false
}
status := readgstatus(gp)
package runtime
-import "unsafe"
+// A parfor holds state for the parallel for operation.
+type parfor struct {
+ body func(*parfor, uint32) // executed for each element
+ done uint32 // number of idle threads
+ nthr uint32 // total number of threads
+ thrseq uint32 // thread id sequencer
+ cnt uint32 // iteration space [0, cnt)
+ wait bool // if true, wait while all threads finish processing,
+ // otherwise parfor may return while other threads are still working
+
+ thr []parforthread // thread descriptors
+ // stats
+ nsteal uint64
+ nstealcnt uint64
+ nprocyield uint64
+ nosyield uint64
+ nsleep uint64
+}
+
+// A parforthread holds state for a single thread in the parallel for.
type parforthread struct {
// the thread's iteration space [32lsb, 32msb)
pos uint64
pad [_CacheLineSize]byte
}
-func desc_thr_index(desc *parfor, i uint32) *parforthread {
- return (*parforthread)(add(unsafe.Pointer(desc.thr), uintptr(i)*unsafe.Sizeof(*desc.thr)))
+func parforalloc(nthrmax uint32) *parfor {
+ return &parfor{
+ thr: make([]parforthread, nthrmax),
+ }
}
-func parforsetup(desc *parfor, nthr, n uint32, ctx unsafe.Pointer, wait bool, body func(*parfor, uint32)) {
- if desc == nil || nthr == 0 || nthr > desc.nthrmax || body == nil {
+// Parforsetup initializes desc for a parallel for operation with nthr
+// threads executing n jobs.
+//
+// On return the nthr threads are each expected to call parfordo(desc)
+// to run the operation. During those calls, for each i in [0, n), one
+// thread will be used invoke body(desc, i).
+// If wait is true, no parfordo will return until all work has been completed.
+// If wait is false, parfordo may return when there is a small amount
+// of work left, under the assumption that another thread has that
+// work well in hand.
+func parforsetup(desc *parfor, nthr, n uint32, wait bool, body func(*parfor, uint32)) {
+ if desc == nil || nthr == 0 || nthr > uint32(len(desc.thr)) || body == nil {
print("desc=", desc, " nthr=", nthr, " count=", n, " body=", body, "\n")
throw("parfor: invalid args")
}
- desc.body = *(*unsafe.Pointer)(unsafe.Pointer(&body))
+ desc.body = body
desc.done = 0
desc.nthr = nthr
desc.thrseq = 0
desc.cnt = n
- desc.ctx = ctx
desc.wait = wait
desc.nsteal = 0
desc.nstealcnt = 0
desc.nosyield = 0
desc.nsleep = 0
- for i := uint32(0); i < nthr; i++ {
+ for i := range desc.thr {
begin := uint32(uint64(n) * uint64(i) / uint64(nthr))
end := uint32(uint64(n) * uint64(i+1) / uint64(nthr))
- pos := &desc_thr_index(desc, i).pos
- if uintptr(unsafe.Pointer(pos))&7 != 0 {
- throw("parforsetup: pos is not aligned")
- }
- *pos = uint64(begin) | uint64(end)<<32
+ desc.thr[i].pos = uint64(begin) | uint64(end)<<32
}
}
}
// If single-threaded, just execute the for serially.
- body := *(*func(*parfor, uint32))(unsafe.Pointer(&desc.body))
+ body := desc.body
if desc.nthr == 1 {
for i := uint32(0); i < desc.cnt; i++ {
body(desc, i)
return
}
- me := desc_thr_index(desc, tid)
+ me := &desc.thr[tid]
mypos := &me.pos
for {
for {
if victim >= tid {
victim++
}
- victimpos := &desc_thr_index(desc, victim).pos
+ victimpos := &desc.thr[victim].pos
for {
// See if it has any work.
pos := atomicload64(victimpos)
import (
. "runtime"
"testing"
- "unsafe"
)
-var gdata []uint64
-
// Simple serial sanity test for parallelfor.
func TestParFor(t *testing.T) {
const P = 1
data[i] = i
}
desc := NewParFor(P)
- // Avoid making func a closure: parfor cannot invoke them.
- // Since it doesn't happen in the C code, it's not worth doing
- // just for the test.
- gdata = data
- ParForSetup(desc, P, N, nil, true, func(desc *ParFor, i uint32) {
- data := gdata
+ ParForSetup(desc, P, N, true, func(desc *ParFor, i uint32) {
data[i] = data[i]*data[i] + 1
})
ParForDo(desc)
data[i] = i
}
desc := NewParFor(P)
- ParForSetup(desc, P, N, (*byte)(unsafe.Pointer(&data)), false, func(desc *ParFor, i uint32) {
- d := *(*[]uint64)(unsafe.Pointer(desc.Ctx))
- d[i] = d[i]*d[i] + 1
+ ParForSetup(desc, P, N, false, func(desc *ParFor, i uint32) {
+ data[i] = data[i]*data[i] + 1
})
for p := 0; p < P; p++ {
ParForDo(desc)
desc := NewParFor(P)
for n := uint32(0); n < N; n++ {
for p := uint32(1); p <= P; p++ {
- ParForSetup(desc, p, n, nil, true, func(desc *ParFor, i uint32) {})
+ ParForSetup(desc, p, n, true, func(desc *ParFor, i uint32) {})
sum := uint32(0)
size0 := uint32(0)
end0 := uint32(0)
P := GOMAXPROCS(-1)
c := make(chan bool, P)
desc := NewParFor(uint32(P))
- gdata = data
- ParForSetup(desc, uint32(P), uint32(N), nil, false, func(desc *ParFor, i uint32) {
- data := gdata
+ ParForSetup(desc, uint32(P), uint32(N), false, func(desc *ParFor, i uint32) {
data[i] = data[i]*data[i] + 1
})
for p := 1; p < P; p++ {
<-cpu.done
}
+// TODO(rsc): Decide if StartTrace belongs in this package.
+// See golang.org/issue/9710.
+// StartTrace enables tracing for the current process.
+// While tracing, the trace will be buffered and written to w.
+// StartTrace returns an error if profiling is tracing enabled.
+func StartTrace(w io.Writer) error {
+ if err := runtime.StartTrace(); err != nil {
+ return err
+ }
+ go func() {
+ for {
+ data := runtime.ReadTrace()
+ if data == nil {
+ break
+ }
+ w.Write(data)
+ }
+ }()
+ return nil
+}
+
+// StopTrace stops the current tracing, if any.
+// StopTrace only returns after all the writes for the trace have completed.
+func StopTrace() {
+ runtime.StopTrace()
+}
+
type byCycles []runtime.BlockProfileRecord
func (x byCycles) Len() int { return len(x) }
"bytes"
"fmt"
"math/big"
+ "os"
"os/exec"
"regexp"
"runtime"
t.Skipf("ignoring failure on %s; see golang.org/issue/6047", runtime.GOOS)
return
}
+ // Ignore the failure if the tests are running in a QEMU-based emulator,
+ // QEMU is not perfect at emulating everything.
+ // IN_QEMU environmental variable is set by some of the Go builders.
+ // IN_QEMU=1 indicates that the tests are running in QEMU. See issue 9605.
+ if os.Getenv("IN_QEMU") == "1" {
+ t.Skip("ignore the failure in QEMU; see golang.org/issue/9605")
+ return
+ }
t.FailNow()
}
}
--- /dev/null
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pprof_test
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "os/exec"
+ "sort"
+ "strconv"
+ "strings"
+)
+
+// Event describes one event in the trace.
+type Event struct {
+ off int // offset in input file (for debugging and error reporting)
+ typ byte // one of traceEv*
+ ts int64 // timestamp in nanoseconds
+ p int // P on which the event happened (can be one of timerP, netpollP, syscallP)
+ g uint64 // G on which the event happened
+ stkID uint64 // unique stack ID
+ stk []*Frame // stack trace (can be empty)
+ args [2]uint64 // event-type-specific arguments
+ // linked event (can be nil), depends on event type:
+ // for GCStart: the GCStop
+ // for GCScanStart: the GCScanDone
+ // for GCSweepStart: the GCSweepDone
+ // for GoCreate: first GoStart of the created goroutine
+ // for GoStart: the associated GoEnd, GoBlock or other blocking event
+ // for GoSched/GoPreempt: the next GoStart
+ // for GoBlock and other blocking events: the unblock event
+ // for GoUnblock: the associated GoStart
+ // for blocking GoSysCall: the associated GoSysExit
+ // for GoSysExit: the next GoStart
+ link *Event
+}
+
+// Frame is a frame in stack traces.
+type Frame struct {
+ pc uint64
+ fn string
+ file string
+ line int
+}
+
+const (
+ // Special P identifiers:
+ timerP = 1000000 + iota // depicts timer unblocks
+ netpollP // depicts network unblocks
+ syscallP // depicts returns from syscalls
+)
+
+// parseTrace parses, post-processes and verifies the trace.
+func parseTrace(r io.Reader) ([]*Event, error) {
+ rawEvents, err := readTrace(r)
+ if err != nil {
+ return nil, err
+ }
+ events, err := parseEvents(rawEvents)
+ if err != nil {
+ return nil, err
+ }
+ err = postProcessTrace(events)
+ if err != nil {
+ return nil, err
+ }
+ return events, nil
+}
+
+// RawEvent is a helper type used during parsing.
+type RawEvent struct {
+ off int
+ typ byte
+ args []uint64
+}
+
+// readTrace does wire-format parsing and verification.
+// It does not care about specific event types and argument meaning.
+func readTrace(r io.Reader) ([]RawEvent, error) {
+ // Read and validate trace header.
+ var buf [8]byte
+ off, err := r.Read(buf[:])
+ if off != 8 || err != nil {
+ return nil, fmt.Errorf("failed to read header: read %v, err %v", off, err)
+ }
+ if bytes.Compare(buf[:], []byte("gotrace\x00")) != 0 {
+ return nil, fmt.Errorf("not a trace file")
+ }
+
+ // Read events.
+ var events []RawEvent
+ for {
+ // Read event type and number of arguments (1 byte).
+ off0 := off
+ n, err := r.Read(buf[:1])
+ if err == io.EOF {
+ break
+ }
+ if err != nil || n != 1 {
+ return nil, fmt.Errorf("failed to read trace at offset 0x%x: n=%v err=%v", off0, n, err)
+ }
+ off += n
+ typ := buf[0] << 2 >> 2
+ narg := buf[0]>>6 + 1
+ ev := RawEvent{typ: typ, off: off0}
+ if narg <= 3 {
+ for i := 0; i < int(narg); i++ {
+ var v uint64
+ v, off, err = readVal(r, off)
+ if err != nil {
+ return nil, err
+ }
+ ev.args = append(ev.args, v)
+ }
+ } else {
+ // If narg == 4, the first value is length of the event in bytes.
+ var v uint64
+ v, off, err = readVal(r, off)
+ if err != nil {
+ return nil, err
+ }
+ evLen := v
+ off1 := off
+ for evLen > uint64(off-off1) {
+ v, off, err = readVal(r, off)
+ if err != nil {
+ return nil, err
+ }
+ ev.args = append(ev.args, v)
+ }
+ if evLen != uint64(off-off1) {
+ return nil, fmt.Errorf("event has wrong length at offset 0x%x: want %v, got %v", off0, evLen, off-off1)
+ }
+ }
+ events = append(events, ev)
+ }
+ return events, nil
+}
+
+// Parse events transforms raw events into events.
+// It does analyze and verify per-event-type arguments.
+func parseEvents(rawEvents []RawEvent) (events []*Event, err error) {
+ var ticksPerSec, lastTs int64
+ var lastG, timerGoid uint64
+ var lastP int
+ lastGs := make(map[int]uint64) // last goroutine running on P
+ stacks := make(map[uint64][]*Frame)
+ for _, raw := range rawEvents {
+ if raw.typ == traceEvNone || raw.typ >= traceEvCount {
+ err = fmt.Errorf("unknown event type %v at offset 0x%x", raw.typ, raw.off)
+ return
+ }
+ desc := evDescriptions[raw.typ]
+ if desc.name == "" {
+ err = fmt.Errorf("missing description for event type %v", raw.typ)
+ return
+ }
+ if raw.typ != traceEvStack {
+ narg := len(desc.args)
+ if desc.stack {
+ narg++
+ }
+ if raw.typ != traceEvBatch && raw.typ != traceEvFrequency && raw.typ != traceEvTimerGoroutine {
+ narg++ // timestamp
+ }
+ if len(raw.args) != narg {
+ err = fmt.Errorf("%v has wrong number of arguments at offset 0x%x: want %v, got %v",
+ desc.name, raw.off, narg, len(raw.args))
+ return
+ }
+ }
+ switch raw.typ {
+ case traceEvBatch:
+ lastGs[lastP] = lastG
+ lastP = int(raw.args[0])
+ lastG = lastGs[lastP]
+ lastTs = int64(raw.args[1])
+ case traceEvFrequency:
+ ticksPerSec = int64(raw.args[0])
+ if ticksPerSec <= 0 {
+ err = fmt.Errorf("traceEvFrequency contains invalid frequency %v at offset 0x%x",
+ ticksPerSec, raw.off)
+ return
+ }
+ case traceEvTimerGoroutine:
+ timerGoid = raw.args[0]
+ case traceEvStack:
+ if len(raw.args) < 2 {
+ err = fmt.Errorf("traceEvStack has wrong number of arguments at offset 0x%x: want at least 2, got %v",
+ raw.off, len(raw.args))
+ return
+ }
+ size := raw.args[1]
+ if size > 1000 {
+ err = fmt.Errorf("traceEvStack has bad number of frames at offset 0x%x: %v",
+ raw.off, size)
+ return
+ }
+ id := raw.args[0]
+ if id != 0 && size > 0 {
+ stk := make([]*Frame, size)
+ for i := 0; i < int(size); i++ {
+ stk[i] = &Frame{pc: raw.args[i+2]}
+ }
+ stacks[id] = stk
+ }
+ default:
+ e := &Event{off: raw.off, typ: raw.typ, p: lastP, g: lastG}
+ e.ts = lastTs + int64(raw.args[0])
+ lastTs = e.ts
+ for i := range desc.args {
+ e.args[i] = raw.args[i+1]
+ }
+ if desc.stack {
+ e.stkID = raw.args[len(desc.args)+1]
+ }
+ switch raw.typ {
+ case traceEvGoStart:
+ lastG = e.args[0]
+ e.g = lastG
+ case traceEvGCStart, traceEvGCDone, traceEvGCScanStart, traceEvGCScanDone:
+ e.g = 0
+ case traceEvGoEnd, traceEvGoStop, traceEvGoSched, traceEvGoPreempt,
+ traceEvGoSleep, traceEvGoBlock, traceEvGoBlockSend, traceEvGoBlockRecv,
+ traceEvGoBlockSelect, traceEvGoBlockSync, traceEvGoBlockCond, traceEvGoBlockNet,
+ traceEvGoSysBlock:
+ lastG = 0
+ }
+ events = append(events, e)
+ }
+ }
+
+ // Attach stack traces.
+ for _, ev := range events {
+ if ev.stkID != 0 {
+ ev.stk = stacks[ev.stkID]
+ }
+ }
+
+ // Sort by time and translate cpu ticks to real time.
+ sort.Sort(EventList(events))
+ if ticksPerSec == 0 {
+ err = fmt.Errorf("no traceEvFrequency event")
+ return
+ }
+ minTs := events[0].ts
+ for _, ev := range events {
+ ev.ts = (ev.ts - minTs) * 1e9 / ticksPerSec
+ // Move timers and syscalls to separate fake Ps.
+ if timerGoid != 0 && ev.g == timerGoid && ev.typ == traceEvGoUnblock {
+ ev.p = timerP
+ }
+ if ev.typ == traceEvGoSysExit {
+ ev.p = syscallP
+ ev.g = ev.args[0]
+ }
+ }
+
+ return
+}
+
+// postProcessTrace does inter-event verification and information restoration.
+// The resulting trace is guaranteed to be consistent
+// (for example, a P does not run two Gs at the same time, or a G is indeed
+// blocked before an unblock event).
+func postProcessTrace(events []*Event) error {
+ const (
+ gDead = iota
+ gRunnable
+ gRunning
+ gWaiting
+ )
+ type gdesc struct {
+ state int
+ ev *Event
+ evStart *Event
+ }
+ type pdesc struct {
+ running bool
+ g uint64
+ evGC *Event
+ evScan *Event
+ evSweep *Event
+ }
+
+ gs := make(map[uint64]gdesc)
+ ps := make(map[int]pdesc)
+ gs[0] = gdesc{state: gRunning}
+
+ checkRunning := func(p pdesc, g gdesc, ev *Event) error {
+ name := evDescriptions[ev.typ].name
+ if g.state != gRunning {
+ return fmt.Errorf("g %v is not running while %v (offset %v, time %v)", ev.g, name, ev.off, ev.ts)
+ }
+ if p.g != ev.g {
+ return fmt.Errorf("p %v is not running g %v while %v (offset %v, time %v)", ev.p, ev.g, name, ev.off, ev.ts)
+ }
+ return nil
+ }
+
+ for _, ev := range events {
+ g := gs[ev.g]
+ p := ps[ev.p]
+
+ switch ev.typ {
+ case traceEvProcStart:
+ if p.running {
+ return fmt.Errorf("p %v is running before start (offset %v, time %v)", ev.p, ev.off, ev.ts)
+ }
+ p.running = true
+ case traceEvProcStop:
+ if !p.running {
+ return fmt.Errorf("p %v is not running before stop (offset %v, time %v)", ev.p, ev.off, ev.ts)
+ }
+ if p.g != 0 {
+ return fmt.Errorf("p %v is running a goroutine %v during stop (offset %v, time %v)", ev.p, p.g, ev.off, ev.ts)
+ }
+ p.running = false
+ case traceEvGCStart:
+ if p.evGC != nil {
+ return fmt.Errorf("previous GC is not ended before a new one (offset %v, time %v)", ev.off, ev.ts)
+ }
+ p.evGC = ev
+ case traceEvGCDone:
+ if p.evGC == nil {
+ return fmt.Errorf("bogus GC end (offset %v, time %v)", ev.off, ev.ts)
+ }
+ p.evGC.link = ev
+ p.evGC = nil
+ case traceEvGCScanStart:
+ if p.evScan != nil {
+ return fmt.Errorf("previous scanning is not ended before a new one (offset %v, time %v)", ev.off, ev.ts)
+ }
+ p.evScan = ev
+ case traceEvGCScanDone:
+ if p.evScan == nil {
+ return fmt.Errorf("bogus scanning end (offset %v, time %v)", ev.off, ev.ts)
+ }
+ p.evScan.link = ev
+ p.evScan = nil
+ case traceEvGCSweepStart:
+ if p.evSweep != nil {
+ return fmt.Errorf("previous sweeping is not ended before a new one (offset %v, time %v)", ev.off, ev.ts)
+ }
+ p.evSweep = ev
+ case traceEvGCSweepDone:
+ if p.evSweep == nil {
+ return fmt.Errorf("bogus sweeping end (offset %v, time %v)", ev.off, ev.ts)
+ }
+ p.evSweep.link = ev
+ p.evSweep = nil
+ case traceEvGoWaiting:
+ g1 := gs[ev.args[0]]
+ if g1.state != gRunnable {
+ return fmt.Errorf("g %v is not runnable before traceEvGoWaiting (offset %v, time %v)", ev.args[0], ev.off, ev.ts)
+ }
+ g1.state = gWaiting
+ gs[ev.args[0]] = g1
+ case traceEvGoInSyscall:
+ // this case is intentionally left blank
+ case traceEvGoCreate:
+ if err := checkRunning(p, g, ev); err != nil {
+ return err
+ }
+ if _, ok := gs[ev.args[0]]; ok {
+ return fmt.Errorf("g %v already exists (offset %v, time %v)", ev.args[0], ev.off, ev.ts)
+ }
+ gs[ev.args[0]] = gdesc{state: gRunnable, ev: ev}
+ case traceEvGoStart:
+ if g.state != gRunnable {
+ return fmt.Errorf("g %v is not runnable before start (offset %v, time %v)", ev.g, ev.off, ev.ts)
+ }
+ if p.g != 0 {
+ return fmt.Errorf("p %v is already running g %v while start g %v (offset %v, time %v)", ev.p, p.g, ev.g, ev.off, ev.ts)
+ }
+ g.state = gRunning
+ g.evStart = ev
+ p.g = ev.g
+ if g.ev != nil {
+ if g.ev.typ == traceEvGoCreate {
+ // +1 because symblizer expects return pc.
+ ev.stk = []*Frame{&Frame{pc: g.ev.args[1] + 1}}
+ }
+ g.ev.link = ev
+ g.ev = nil
+ }
+ case traceEvGoEnd, traceEvGoStop:
+ if err := checkRunning(p, g, ev); err != nil {
+ return err
+ }
+ g.evStart.link = ev
+ g.evStart = nil
+ g.state = gDead
+ p.g = 0
+ case traceEvGoSched, traceEvGoPreempt:
+ if err := checkRunning(p, g, ev); err != nil {
+ return err
+ }
+ g.state = gRunnable
+ g.evStart.link = ev
+ g.evStart = nil
+ p.g = 0
+ g.ev = ev
+ case traceEvGoUnblock:
+ if g.state != gRunning {
+ return fmt.Errorf("g %v is not running while unpark (offset %v, time %v)", ev.g, ev.off, ev.ts)
+ }
+ if ev.p != timerP && p.g != ev.g {
+ return fmt.Errorf("p %v is not running g %v while unpark (offset %v, time %v)", ev.p, ev.g, ev.off, ev.ts)
+ }
+ g1 := gs[ev.args[0]]
+ if g1.state != gWaiting {
+ return fmt.Errorf("g %v is not waiting before unpark (offset %v, time %v)", ev.args[0], ev.off, ev.ts)
+ }
+ if g1.ev != nil && g1.ev.typ == traceEvGoBlockNet && ev.p != timerP {
+ ev.p = netpollP
+ }
+ if g1.ev != nil {
+ g1.ev.link = ev
+ }
+ g1.state = gRunnable
+ g1.ev = ev
+ gs[ev.args[0]] = g1
+ case traceEvGoSysCall:
+ if err := checkRunning(p, g, ev); err != nil {
+ return err
+ }
+ g.ev = ev
+ case traceEvGoSysBlock:
+ if err := checkRunning(p, g, ev); err != nil {
+ return err
+ }
+ g.state = gRunnable
+ g.evStart.link = ev
+ g.evStart = nil
+ p.g = 0
+ case traceEvGoSysExit:
+ if g.state != gRunnable {
+ return fmt.Errorf("g %v is not runnable during syscall exit (offset %v, time %v)", ev.g, ev.off, ev.ts)
+ }
+ if g.ev != nil && g.ev.typ == traceEvGoSysCall {
+ g.ev.link = ev
+ }
+ g.ev = ev
+ case traceEvGoSleep, traceEvGoBlock, traceEvGoBlockSend, traceEvGoBlockRecv,
+ traceEvGoBlockSelect, traceEvGoBlockSync, traceEvGoBlockCond, traceEvGoBlockNet:
+ if err := checkRunning(p, g, ev); err != nil {
+ return err
+ }
+ g.state = gWaiting
+ g.ev = ev
+ g.evStart.link = ev
+ g.evStart = nil
+ p.g = 0
+ }
+
+ gs[ev.g] = g
+ ps[ev.p] = p
+ }
+
+ return nil
+}
+
+// symbolizeTrace attaches func/file/line info to stack traces.
+func symbolizeTrace(events []*Event, bin string) error {
+ // First, collect and dedup all pcs.
+ pcs := make(map[uint64]*Frame)
+ for _, ev := range events {
+ for _, f := range ev.stk {
+ pcs[f.pc] = nil
+ }
+ }
+
+ // Start addr2line.
+ cmd := exec.Command("go", "tool", "addr2line", bin)
+ in, err := cmd.StdinPipe()
+ if err != nil {
+ return fmt.Errorf("failed to pipe addr2line stdin: %v", err)
+ }
+ out, err := cmd.StdoutPipe()
+ if err != nil {
+ return fmt.Errorf("failed to pipe addr2line stdout: %v", err)
+ }
+ err = cmd.Start()
+ if err != nil {
+ return fmt.Errorf("failed to start addr2line: %v", err)
+ }
+ outb := bufio.NewReader(out)
+
+ // Write all pcs to addr2line.
+ // Need to copy pcs to an array, because map iteration order is non-deterministic.
+ var pcArray []uint64
+ for pc := range pcs {
+ pcArray = append(pcArray, pc)
+ _, err := fmt.Fprintf(in, "0x%x\n", pc-1)
+ if err != nil {
+ return fmt.Errorf("failed to write to addr2line: %v", err)
+ }
+ }
+ in.Close()
+
+ // Read in answers.
+ for _, pc := range pcArray {
+ fn, err := outb.ReadString('\n')
+ if err != nil {
+ return fmt.Errorf("failed to read from addr2line: %v", err)
+ }
+ file, err := outb.ReadString('\n')
+ if err != nil {
+ return fmt.Errorf("failed to read from addr2line: %v", err)
+ }
+ f := &Frame{pc: pc}
+ f.fn = fn[:len(fn)-1]
+ f.file = file[:len(file)-1]
+ if colon := strings.LastIndex(f.file, ":"); colon != -1 {
+ ln, err := strconv.Atoi(f.file[colon+1:])
+ if err == nil {
+ f.file = f.file[:colon]
+ f.line = ln
+ }
+ }
+ pcs[pc] = f
+ }
+ cmd.Wait()
+
+ // Replace frames in events array.
+ for _, ev := range events {
+ for i, f := range ev.stk {
+ ev.stk[i] = pcs[f.pc]
+ }
+ }
+
+ return nil
+}
+
+// readVal reads unsigned base-128 value from r.
+func readVal(r io.Reader, off0 int) (v uint64, off int, err error) {
+ off = off0
+ for i := 0; i < 10; i++ {
+ var buf [1]byte
+ var n int
+ n, err = r.Read(buf[:])
+ if err != nil || n != 1 {
+ return 0, 0, fmt.Errorf("failed to read trace at offset: read %v, error %v", off0, n, err)
+ }
+ off++
+ v |= uint64(buf[0]&0x7f) << (uint(i) * 7)
+ if buf[0]&0x80 == 0 {
+ return
+ }
+ }
+ return 0, 0, fmt.Errorf("bad value at offset 0x%x", off0)
+}
+
+type EventList []*Event
+
+func (l EventList) Len() int {
+ return len(l)
+}
+
+func (l EventList) Less(i, j int) bool {
+ return l[i].ts < l[j].ts
+}
+
+func (l EventList) Swap(i, j int) {
+ l[i], l[j] = l[j], l[i]
+}
+
+// Event types in the trace.
+// Verbatim copy from src/runtime/trace.go.
+const (
+ traceEvNone = 0 // unused
+ traceEvBatch = 1 // start of per-P batch of events [pid, timestamp]
+ traceEvFrequency = 2 // contains tracer timer frequency [frequency (ticks per second)]
+ traceEvStack = 3 // stack [stack id, number of PCs, array of PCs]
+ traceEvGomaxprocs = 4 // current value of GOMAXPROCS [timestamp, GOMAXPROCS, stack id]
+ traceEvProcStart = 5 // start of P [timestamp]
+ traceEvProcStop = 6 // stop of P [timestamp]
+ traceEvGCStart = 7 // GC start [timestamp, stack id]
+ traceEvGCDone = 8 // GC done [timestamp]
+ traceEvGCScanStart = 9 // GC scan start [timestamp]
+ traceEvGCScanDone = 10 // GC scan done [timestamp]
+ traceEvGCSweepStart = 11 // GC sweep start [timestamp, stack id]
+ traceEvGCSweepDone = 12 // GC sweep done [timestamp]
+ traceEvGoCreate = 13 // goroutine creation [timestamp, new goroutine id, start PC, stack id]
+ traceEvGoStart = 14 // goroutine starts running [timestamp, goroutine id]
+ traceEvGoEnd = 15 // goroutine ends [timestamp]
+ traceEvGoStop = 16 // goroutine stops (like in select{}) [timestamp, stack]
+ traceEvGoSched = 17 // goroutine calls Gosched [timestamp, stack]
+ traceEvGoPreempt = 18 // goroutine is preempted [timestamp, stack]
+ traceEvGoSleep = 19 // goroutine calls Sleep [timestamp, stack]
+ traceEvGoBlock = 20 // goroutine blocks [timestamp, stack]
+ traceEvGoUnblock = 21 // goroutine is unblocked [timestamp, goroutine id, stack]
+ traceEvGoBlockSend = 22 // goroutine blocks on chan send [timestamp, stack]
+ traceEvGoBlockRecv = 23 // goroutine blocks on chan recv [timestamp, stack]
+ traceEvGoBlockSelect = 24 // goroutine blocks on select [timestamp, stack]
+ traceEvGoBlockSync = 25 // goroutine blocks on Mutex/RWMutex [timestamp, stack]
+ traceEvGoBlockCond = 26 // goroutine blocks on Cond [timestamp, stack]
+ traceEvGoBlockNet = 27 // goroutine blocks on network [timestamp, stack]
+ traceEvGoSysCall = 28 // syscall enter [timestamp, stack]
+ traceEvGoSysExit = 29 // syscall exit [timestamp, goroutine id]
+ traceEvGoSysBlock = 30 // syscall blocks [timestamp, stack]
+ traceEvGoWaiting = 31 // denotes that goroutine is blocked when tracing starts [goroutine id]
+ traceEvGoInSyscall = 32 // denotes that goroutine is in syscall when tracing starts [goroutine id]
+ traceEvHeapAlloc = 33 // memstats.heap_alloc change [timestamp, heap_alloc]
+ traceEvNextGC = 34 // memstats.next_gc change [timestamp, next_gc]
+ traceEvTimerGoroutine = 35 // denotes timer goroutine [timer goroutine id]
+ traceEvCount = 36
+)
+
+var evDescriptions = [traceEvCount]struct {
+ name string
+ stack bool
+ args []string
+}{
+ traceEvNone: {"None", false, []string{}},
+ traceEvBatch: {"Batch", false, []string{"p", "ticks"}},
+ traceEvFrequency: {"Frequency", false, []string{"freq"}},
+ traceEvStack: {"Stack", false, []string{"id", "siz"}},
+ traceEvGomaxprocs: {"Gomaxprocs", true, []string{"procs"}},
+ traceEvProcStart: {"ProcStart", false, []string{}},
+ traceEvProcStop: {"ProcStop", false, []string{}},
+ traceEvGCStart: {"GCStart", true, []string{}},
+ traceEvGCDone: {"GCDone", false, []string{}},
+ traceEvGCScanStart: {"GCScanStart", false, []string{}},
+ traceEvGCScanDone: {"GCScanDone", false, []string{}},
+ traceEvGCSweepStart: {"GCSweepStart", true, []string{}},
+ traceEvGCSweepDone: {"GCSweepDone", false, []string{}},
+ traceEvGoCreate: {"GoCreate", true, []string{"g", "pc"}},
+ traceEvGoStart: {"GoStart", false, []string{"g"}},
+ traceEvGoEnd: {"GoEnd", false, []string{}},
+ traceEvGoStop: {"GoStop", true, []string{}},
+ traceEvGoSched: {"GoSched", true, []string{}},
+ traceEvGoPreempt: {"GoPreempt", true, []string{}},
+ traceEvGoSleep: {"GoSleep", true, []string{}},
+ traceEvGoBlock: {"GoBlock", true, []string{}},
+ traceEvGoUnblock: {"GoUnblock", true, []string{"g"}},
+ traceEvGoBlockSend: {"GoBlockSend", true, []string{}},
+ traceEvGoBlockRecv: {"GoBlockRecv", true, []string{}},
+ traceEvGoBlockSelect: {"GoBlockSelect", true, []string{}},
+ traceEvGoBlockSync: {"GoBlockSync", true, []string{}},
+ traceEvGoBlockCond: {"GoBlockCond", true, []string{}},
+ traceEvGoBlockNet: {"GoBlockNet", true, []string{}},
+ traceEvGoSysCall: {"GoSysCall", true, []string{}},
+ traceEvGoSysExit: {"GoSysExit", false, []string{"g"}},
+ traceEvGoSysBlock: {"GoSysBlock", true, []string{}},
+ traceEvGoWaiting: {"GoWaiting", false, []string{"g"}},
+ traceEvGoInSyscall: {"GoInSyscall", false, []string{"g"}},
+ traceEvHeapAlloc: {"HeapAlloc", false, []string{"mem"}},
+ traceEvNextGC: {"NextGC", false, []string{"mem"}},
+ traceEvTimerGoroutine: {"TimerGoroutine", false, []string{"g"}},
+}
--- /dev/null
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pprof_test
+
+import (
+ "bytes"
+ "net"
+ "os"
+ "runtime"
+ . "runtime/pprof"
+ "strings"
+ "sync"
+ "testing"
+ "time"
+)
+
+func skipTraceTestsIfNeeded(t *testing.T) {
+ switch runtime.GOOS {
+ case "solaris":
+ t.Skip("skipping: solaris timer can go backwards (http://golang.org/issue/8976)")
+ }
+
+ switch runtime.GOARCH {
+ case "arm":
+ t.Skip("skipping: arm tests fail with 'failed to parse trace' (http://golang.org/issue/9725)")
+ }
+}
+
+func TestTraceStartStop(t *testing.T) {
+ skipTraceTestsIfNeeded(t)
+ buf := new(bytes.Buffer)
+ if err := StartTrace(buf); err != nil {
+ t.Fatalf("failed to start tracing: %v", err)
+ }
+ StopTrace()
+ size := buf.Len()
+ if size == 0 {
+ t.Fatalf("trace is empty")
+ }
+ time.Sleep(100 * time.Millisecond)
+ if size != buf.Len() {
+ t.Fatalf("trace writes after stop: %v -> %v", size, buf.Len())
+ }
+}
+
+func TestTraceDoubleStart(t *testing.T) {
+ skipTraceTestsIfNeeded(t)
+ StopTrace()
+ buf := new(bytes.Buffer)
+ if err := StartTrace(buf); err != nil {
+ t.Fatalf("failed to start tracing: %v", err)
+ }
+ if err := StartTrace(buf); err == nil {
+ t.Fatalf("succeed to start tracing second time")
+ }
+ StopTrace()
+ StopTrace()
+}
+
+func TestTrace(t *testing.T) {
+ skipTraceTestsIfNeeded(t)
+ buf := new(bytes.Buffer)
+ if err := StartTrace(buf); err != nil {
+ t.Fatalf("failed to start tracing: %v", err)
+ }
+ StopTrace()
+ _, err := parseTrace(buf)
+ if err != nil {
+ t.Fatalf("failed to parse trace: %v", err)
+ }
+}
+
+func TestTraceStress(t *testing.T) {
+ skipTraceTestsIfNeeded(t)
+
+ var wg sync.WaitGroup
+ done := make(chan bool)
+
+ // Create a goroutine blocked before tracing.
+ wg.Add(1)
+ go func() {
+ <-done
+ wg.Done()
+ }()
+
+ // Create a goroutine blocked in syscall before tracing.
+ rp, wp, err := os.Pipe()
+ if err != nil {
+ t.Fatalf("failed to create pipe: %v", err)
+ }
+ defer func() {
+ rp.Close()
+ wp.Close()
+ }()
+ wg.Add(1)
+ go func() {
+ var tmp [1]byte
+ rp.Read(tmp[:])
+ <-done
+ wg.Done()
+ }()
+ time.Sleep(time.Millisecond)
+
+ buf := new(bytes.Buffer)
+ if err := StartTrace(buf); err != nil {
+ t.Fatalf("failed to start tracing: %v", err)
+ }
+
+ procs := runtime.GOMAXPROCS(10)
+
+ go func() {
+ runtime.LockOSThread()
+ for {
+ select {
+ case <-done:
+ return
+ default:
+ runtime.Gosched()
+ }
+ }
+ }()
+
+ runtime.GC()
+ // Trigger GC from malloc.
+ for i := 0; i < 1e3; i++ {
+ _ = make([]byte, 1<<20)
+ }
+
+ // Create a bunch of busy goroutines to load all Ps.
+ for p := 0; p < 10; p++ {
+ wg.Add(1)
+ go func() {
+ // Do something useful.
+ tmp := make([]byte, 1<<16)
+ for i := range tmp {
+ tmp[i]++
+ }
+ _ = tmp
+ <-done
+ wg.Done()
+ }()
+ }
+
+ // Block in syscall.
+ wg.Add(1)
+ go func() {
+ var tmp [1]byte
+ rp.Read(tmp[:])
+ <-done
+ wg.Done()
+ }()
+
+ // Test timers.
+ timerDone := make(chan bool)
+ go func() {
+ time.Sleep(time.Millisecond)
+ timerDone <- true
+ }()
+ <-timerDone
+
+ // A bit of network.
+ ln, err := net.Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatalf("listen failed: %v", err)
+ }
+ defer ln.Close()
+ go func() {
+ c, err := ln.Accept()
+ if err != nil {
+ return
+ }
+ time.Sleep(time.Millisecond)
+ var buf [1]byte
+ c.Write(buf[:])
+ c.Close()
+ }()
+ c, err := net.Dial("tcp", ln.Addr().String())
+ if err != nil {
+ t.Fatalf("dial failed: %v", err)
+ }
+ var tmp [1]byte
+ c.Read(tmp[:])
+ c.Close()
+
+ go func() {
+ runtime.Gosched()
+ select {}
+ }()
+
+ // Unblock helper goroutines and wait them to finish.
+ wp.Write(tmp[:])
+ wp.Write(tmp[:])
+ close(done)
+ wg.Wait()
+
+ runtime.GOMAXPROCS(procs)
+
+ StopTrace()
+ _, err = parseTrace(buf)
+ if err != nil {
+ t.Fatalf("failed to parse trace: %v", err)
+ }
+}
+
+func TestTraceSymbolize(t *testing.T) {
+ skipTraceTestsIfNeeded(t)
+ if runtime.GOOS == "nacl" {
+ t.Skip("skipping: nacl tests fail with 'failed to symbolize trace: failed to start addr2line'")
+ }
+ buf := new(bytes.Buffer)
+ if err := StartTrace(buf); err != nil {
+ t.Fatalf("failed to start tracing: %v", err)
+ }
+ runtime.GC()
+ StopTrace()
+ events, err := parseTrace(buf)
+ if err != nil {
+ t.Fatalf("failed to parse trace: %v", err)
+ }
+ err = symbolizeTrace(events, os.Args[0])
+ if err != nil {
+ t.Fatalf("failed to symbolize trace: %v", err)
+ }
+ found := false
+eventLoop:
+ for _, ev := range events {
+ if ev.typ != traceEvGCStart {
+ continue
+ }
+ for _, f := range ev.stk {
+ if strings.HasSuffix(f.file, "trace_test.go") &&
+ strings.HasSuffix(f.fn, "pprof_test.TestTraceSymbolize") &&
+ f.line == 216 {
+ found = true
+ break eventLoop
+ }
+ }
+ }
+ if !found {
+ t.Fatalf("the trace does not contain GC event")
+ }
+}
var (
writeHeader = []byte{6 /* ANDROID_LOG_ERROR */, 'G', 'o', 0}
writePath = []byte("/dev/log/main\x00")
- writeFD uintptr
- writeBuf [1024]byte
- writePos int
+ writeLogd = []byte("/dev/socket/logdw\x00")
+
+ // guarded by printlock/printunlock.
+ writeFD uintptr
+ writeBuf [1024]byte
+ writePos int
+)
+
+// Prior to Android-L, logging was done through writes to /dev/log files implemented
+// in kernel ring buffers. In Android-L, those /dev/log files are no longer
+// accessible and logging is done through a centralized user-mode logger, logd.
+//
+// https://android.googlesource.com/platform/system/core/+/master/liblog/logd_write.c
+type loggerType int32
+
+const (
+ unknown loggerType = iota
+ legacy
+ logd
+ // TODO(hakim): logging for emulator?
)
+var logger loggerType
+
func writeErr(b []byte) {
- // Log format: "<priority 1 byte><tag n bytes>\x00<message m bytes>\x00"
+ if logger == unknown {
+ // Use logd if /dev/socket/logdw is available.
+ if v := uintptr(access(&writeLogd[0], 0x02 /* W_OK */)); v == 0 {
+ logger = logd
+ initLogd()
+ } else {
+ logger = legacy
+ initLegacy()
+ }
+ }
+
+ // Log format: "<header>\x00<message m bytes>\x00"
+ //
+ // <header>
+ // In legacy mode: "<priority 1 byte><tag n bytes>".
+ // In logd mode: "<android_log_header_t 11 bytes><priority 1 byte><tag n bytes>"
+ //
// The entire log needs to be delivered in a single syscall (the NDK
// does this with writev). Each log is its own line, so we need to
// buffer writes until we see a newline.
- if writeFD == 0 {
- writeFD = uintptr(open(&writePath[0], 0x1 /* O_WRONLY */, 0))
- if writeFD == 0 {
- // It is hard to do anything here. Write to stderr just
- // in case user has root on device and has run
- // adb shell setprop log.redirect-stdio true
- msg := []byte("runtime: cannot open /dev/log/main\x00")
- write(2, unsafe.Pointer(&msg[0]), int32(len(msg)))
- exit(2)
- }
- copy(writeBuf[:], writeHeader)
+ var hlen int
+ switch logger {
+ case logd:
+ hlen = writeLogdHeader()
+ case legacy:
+ hlen = len(writeHeader)
}
- dst := writeBuf[len(writeHeader):]
+
+ dst := writeBuf[hlen:]
for _, v := range b {
if v == 0 { // android logging won't print a zero byte
v = '0'
writePos++
if v == '\n' || writePos == len(dst)-1 {
dst[writePos] = 0
- write(writeFD, unsafe.Pointer(&writeBuf[0]), int32(len(writeHeader)+writePos))
+ write(writeFD, unsafe.Pointer(&writeBuf[0]), int32(hlen+writePos))
memclrBytes(dst)
writePos = 0
}
}
}
+
+func initLegacy() {
+ // In legacy mode, logs are written to /dev/log/main
+ writeFD = uintptr(open(&writePath[0], 0x1 /* O_WRONLY */, 0))
+ if writeFD == 0 {
+ // It is hard to do anything here. Write to stderr just
+ // in case user has root on device and has run
+ // adb shell setprop log.redirect-stdio true
+ msg := []byte("runtime: cannot open /dev/log/main\x00")
+ write(2, unsafe.Pointer(&msg[0]), int32(len(msg)))
+ exit(2)
+ }
+
+ // Prepopulate the invariant header part.
+ copy(writeBuf[:len(writeHeader)], writeHeader)
+}
+
+// used in initLogdWrite but defined here to avoid heap allocation.
+var logdAddr sockaddr_un
+
+func initLogd() {
+ // In logd mode, logs are sent to the logd via a unix domain socket.
+ logdAddr.family = _AF_UNIX
+ copy(logdAddr.path[:], writeLogd)
+
+ // We are not using non-blocking I/O because writes taking this path
+ // are most likely triggered by panic, we cannot think of the advantage of
+ // non-blocking I/O for panic but see disadvantage (dropping panic message),
+ // and blocking I/O simplifies the code a lot.
+ fd := socket(_AF_UNIX, _SOCK_DGRAM|_O_CLOEXEC, 0)
+ if fd < 0 {
+ msg := []byte("runtime: cannot create a socket for logging\x00")
+ write(2, unsafe.Pointer(&msg[0]), int32(len(msg)))
+ exit(2)
+ }
+
+ errno := connect(uintptr(fd), unsafe.Pointer(&logdAddr), int32(unsafe.Sizeof(logdAddr)))
+ if errno < 0 {
+ msg := []byte("runtime: cannot connect to /dev/socket/logdw\x00")
+ write(2, unsafe.Pointer(&msg[0]), int32(len(msg)))
+ // TODO(hakim): or should we just close fd and hope for better luck next time?
+ exit(2)
+ }
+ writeFD = uintptr(fd)
+
+ // Prepopulate invariant part of the header.
+ // The first 11 bytes will be populated later in writeLogdHeader.
+ copy(writeBuf[11:11+len(writeHeader)], writeHeader)
+}
+
+// writeLogdHeader populates the header and returns the length of the payload.
+func writeLogdHeader() int {
+ hdr := writeBuf[:11]
+
+ // The first 11 bytes of the header corresponds to android_log_header_t
+ // as defined in system/core/include/private/android_logger.h
+ // hdr[0] log type id (unsigned char), defined in <log/log.h>
+ // hdr[1:2] tid (uint16_t)
+ // hdr[3:11] log_time defined in <log/log_read.h>
+ // hdr[3:7] sec unsigned uint32, little endian.
+ // hdr[7:11] nsec unsigned uint32, little endian.
+ hdr[0] = 0 // LOG_ID_MAIN
+ sec, nsec := time_now()
+ packUint32(hdr[3:7], uint32(sec))
+ packUint32(hdr[7:11], uint32(nsec))
+
+ // TODO(hakim): hdr[1:2] = gettid?
+
+ return 11 + len(writeHeader)
+}
+
+func packUint32(b []byte, v uint32) {
+ // little-endian.
+ b[0] = byte(v)
+ b[1] = byte(v >> 8)
+ b[2] = byte(v >> 16)
+ b[3] = byte(v >> 24)
+}
// let the other goroutine finish printing the panic trace.
// Once it does, it will exit. See issue 3934.
if panicking != 0 {
- gopark(nil, nil, "panicwait")
+ gopark(nil, nil, "panicwait", traceEvGoStop)
}
exit(0)
throw("forcegc: phase error")
}
atomicstore(&forcegc.idle, 1)
- goparkunlock(&forcegc.lock, "force gc (idle)")
+ goparkunlock(&forcegc.lock, "force gc (idle)", traceEvGoBlock)
// this goroutine is explicitly resumed by sysmon
if debug.gctrace > 0 {
println("GC forced")
// Puts the current goroutine into a waiting state and calls unlockf.
// If unlockf returns false, the goroutine is resumed.
-func gopark(unlockf func(*g, unsafe.Pointer) bool, lock unsafe.Pointer, reason string) {
+func gopark(unlockf func(*g, unsafe.Pointer) bool, lock unsafe.Pointer, reason string, traceEv byte) {
mp := acquirem()
gp := mp.curg
status := readgstatus(gp)
mp.waitlock = lock
mp.waitunlockf = *(*unsafe.Pointer)(unsafe.Pointer(&unlockf))
gp.waitreason = reason
+ mp.waittraceev = traceEv
releasem(mp)
// can't do anything that might move the G between Ms here.
mcall(park_m)
// Puts the current goroutine into a waiting state and unlocks the lock.
// The goroutine can be made runnable again by calling goready(gp).
-func goparkunlock(lock *mutex, reason string) {
- gopark(parkunlock_c, unsafe.Pointer(lock), reason)
+func goparkunlock(lock *mutex, reason string, traceEv byte) {
+ gopark(parkunlock_c, unsafe.Pointer(lock), reason, traceEv)
}
func goready(gp *g) {
return gp.lockedm != nil && gp.m.lockedg != nil
}
-func newP() *p {
- return new(p)
-}
-
-func newM() *m {
- return new(m)
-}
-
-func newG() *g {
- return new(g)
-}
-
var (
allgs []*g
allglock mutex
_GoidCacheBatch = 16
)
-/*
-SchedT sched;
-int32 gomaxprocs;
-uint32 needextram;
-bool iscgo;
-M m0;
-G g0; // idle goroutine for m0
-G* lastg;
-M* allm;
-M* extram;
-P* allp[MaxGomaxprocs+1];
-int8* goos;
-int32 ncpu;
-int32 newprocs;
-
-Mutex allglock; // the following vars are protected by this lock or by stoptheworld
-G** allg;
-Slice allgs;
-uintptr allglen;
-ForceGCState forcegc;
-
-void mstart(void);
-static void runqput(P*, G*);
-static G* runqget(P*);
-static bool runqputslow(P*, G*, uint32, uint32);
-static G* runqsteal(P*, P*);
-static void mput(M*);
-static M* mget(void);
-static void mcommoninit(M*);
-static void schedule(void);
-static void procresize(int32);
-static void acquirep(P*);
-static P* releasep(void);
-static void newm(void(*)(void), P*);
-static void stopm(void);
-static void startm(P*, bool);
-static void handoffp(P*);
-static void wakep(void);
-static void stoplockedm(void);
-static void startlockedm(G*);
-static void sysmon(void);
-static uint32 retake(int64);
-static void incidlelocked(int32);
-static void checkdead(void);
-static void exitsyscall0(G*);
-void park_m(G*);
-static void goexit0(G*);
-static void gfput(P*, G*);
-static G* gfget(P*);
-static void gfpurge(P*);
-static void globrunqput(G*);
-static void globrunqputbatch(G*, G*, int32);
-static G* globrunqget(P*, int32);
-static P* pidleget(void);
-static void pidleput(P*);
-static void injectglist(G*);
-static bool preemptall(void);
-static bool preemptone(P*);
-static bool exitsyscallfast(void);
-static bool haveexperiment(int8*);
-void allgadd(G*);
-static void dropg(void);
-
-extern String buildVersion;
-*/
-
// The bootstrap sequence is:
//
// call osinit
sched.maxmcount = 10000
+ // Cache the framepointer experiment. This affects stack unwinding.
+ framepointer_enabled = haveexperiment("framepointer")
+
tracebackinit()
symtabinit()
stackinit()
// Mark gp ready to run.
func ready(gp *g) {
+ if trace.enabled {
+ traceGoUnpark(gp)
+ }
+
status := readgstatus(gp)
// Mark runnable.
throw("gcprocs inconsistency")
}
mp.helpgc = n
+ mp.p = allp[pos]
mp.mcache = allp[pos].mcache
pos++
notewakeup(&mp.park)
dumpgstatus(gp)
throw("casfrom_Gscanstatus: gp->status is not in scan state")
}
+ if newval == _Grunning {
+ gp.gcscanvalid = false
+ }
}
// This will return false if the gp is not in the expected status and the cas fails.
return cas(&gp.atomicstatus, oldval, newval)
}
case _Grunning:
+ if gp.gcscanvalid {
+ print("runtime: castogscanstatus _Grunning and gp.gcscanvalid is true, newval=", hex(newval), "\n")
+ throw("castogscanstatus")
+ }
if newval == _Gscanrunning || newval == _Gscanenqueue {
return cas(&gp.atomicstatus, oldval, newval)
}
func casgstatus(gp *g, oldval, newval uint32) {
if (oldval&_Gscan != 0) || (newval&_Gscan != 0) || oldval == newval {
systemstack(func() {
- print("casgstatus: oldval=", hex(oldval), " newval=", hex(newval), "\n")
+ print("runtime: casgstatus: oldval=", hex(oldval), " newval=", hex(newval), "\n")
throw("casgstatus: bad incoming values")
})
}
// })
// }
}
+ if newval == _Grunning {
+ gp.gcscanvalid = false
+ }
}
// casgstatus(gp, oldstatus, Gcopystack), assuming oldstatus is Gwaiting or Grunnable.
p := allp[i]
s := p.status
if s == _Psyscall && cas(&p.status, s, _Pgcstop) {
+ if trace.enabled {
+ traceGoSysBlock(p)
+ traceProcStop(p)
+ }
+ p.syscalltick++
sched.stopwait--
}
}
if _g_.m.p == nil {
acquirep(_p_) // temporarily borrow p for mallocs in this function
}
- mp := newM()
+ mp := new(m)
mcommoninit(mp)
// In case of cgo or Solaris, pthread_create will make us a stack.
return mp
}
-func allocg() *g {
- return newG()
-}
-
// needm is called when a cgo callback happens on a
// thread without an m (a thread not created by Go).
// In this case, needm is expected to find an m to use
gchelper()
_g_.m.helpgc = 0
_g_.m.mcache = nil
+ _g_.m.p = nil
goto retry
}
acquirep(_g_.m.nextp)
resetcpuprofiler(hz)
}
+ if trace.enabled {
+ traceGoStart()
+ }
+
gogo(&gp.sched)
}
if gp := netpoll(false); gp != nil { // non-blocking
injectglist(gp.schedlink)
casgstatus(gp, _Gwaiting, _Grunnable)
+ if trace.enabled {
+ traceGoUnpark(gp)
+ }
return gp
}
acquirep(_p_)
injectglist(gp.schedlink)
casgstatus(gp, _Gwaiting, _Grunnable)
+ if trace.enabled {
+ traceGoUnpark(gp)
+ }
return gp
}
injectglist(gp)
if glist == nil {
return
}
+ if trace.enabled {
+ for gp := glist; gp != nil; gp = gp.schedlink {
+ traceGoUnpark(gp)
+ }
+ }
lock(&sched.lock)
var n int
for n = 0; glist != nil; n++ {
}
var gp *g
- // Check the global runnable queue once in a while to ensure fairness.
- // Otherwise two goroutines can completely occupy the local runqueue
- // by constantly respawning each other.
- tick := _g_.m.p.schedtick
- // This is a fancy way to say tick%61==0,
- // it uses 2 MUL instructions instead of a single DIV and so is faster on modern processors.
- if uint64(tick)-((uint64(tick)*0x4325c53f)>>36)*61 == 0 && sched.runqsize > 0 {
- lock(&sched.lock)
- gp = globrunqget(_g_.m.p, 1)
- unlock(&sched.lock)
+ if trace.enabled || trace.shutdown {
+ gp = traceReader()
if gp != nil {
+ casgstatus(gp, _Gwaiting, _Grunnable)
+ traceGoUnpark(gp)
resetspinning()
}
}
+ if gp == nil {
+ // Check the global runnable queue once in a while to ensure fairness.
+ // Otherwise two goroutines can completely occupy the local runqueue
+ // by constantly respawning each other.
+ if _g_.m.p.schedtick%61 == 0 && sched.runqsize > 0 {
+ lock(&sched.lock)
+ gp = globrunqget(_g_.m.p, 1)
+ unlock(&sched.lock)
+ if gp != nil {
+ resetspinning()
+ }
+ }
+ }
if gp == nil {
gp = runqget(_g_.m.p)
if gp != nil && _g_.m.spinning {
// Puts the current goroutine into a waiting state and calls unlockf.
// If unlockf returns false, the goroutine is resumed.
-func park(unlockf func(*g, unsafe.Pointer) bool, lock unsafe.Pointer, reason string) {
+func park(unlockf func(*g, unsafe.Pointer) bool, lock unsafe.Pointer, reason string, traceev byte) {
_g_ := getg()
_g_.m.waitlock = lock
_g_.m.waitunlockf = *(*unsafe.Pointer)(unsafe.Pointer(&unlockf))
+ _g_.m.waittraceev = traceev
_g_.waitreason = reason
mcall(park_m)
}
// Puts the current goroutine into a waiting state and unlocks the lock.
// The goroutine can be made runnable again by calling ready(gp).
-func parkunlock(lock *mutex, reason string) {
- park(parkunlock_c, unsafe.Pointer(lock), reason)
+func parkunlock(lock *mutex, reason string, traceev byte) {
+ park(parkunlock_c, unsafe.Pointer(lock), reason, traceev)
}
// park continuation on g0.
func park_m(gp *g) {
_g_ := getg()
+ if trace.enabled {
+ traceGoPark(_g_.m.waittraceev, gp)
+ }
+
casgstatus(gp, _Grunning, _Gwaiting)
dropg()
_g_.m.waitunlockf = nil
_g_.m.waitlock = nil
if !ok {
+ if trace.enabled {
+ traceGoUnpark(gp)
+ }
casgstatus(gp, _Gwaiting, _Grunnable)
execute(gp) // Schedule it back, never returns.
}
schedule()
}
-// Gosched continuation on g0.
-func gosched_m(gp *g) {
+func goschedImpl(gp *g) {
status := readgstatus(gp)
if status&^_Gscan != _Grunning {
dumpgstatus(gp)
schedule()
}
+// Gosched continuation on g0.
+func gosched_m(gp *g) {
+ if trace.enabled {
+ traceGoSched()
+ }
+ goschedImpl(gp)
+}
+
+func gopreempt_m(gp *g) {
+ if trace.enabled {
+ traceGoPreempt()
+ }
+ goschedImpl(gp)
+}
+
// Finishes execution of the current goroutine.
// Must be NOSPLIT because it is called from Go. (TODO - probably not anymore)
//go:nosplit
if raceenabled {
racegoend()
}
+ if trace.enabled {
+ traceGoEnd()
+ }
mcall(goexit0)
}
// from a function further up in the call stack than the parent, as g->syscallsp
// must always point to a valid stack frame. entersyscall below is the normal
// entry point for syscalls, which obtains the SP and PC from the caller.
+//
+// Syscall tracing:
+// At the start of a syscall we emit traceGoSysCall to capture the stack trace.
+// If the syscall does not block, that is it, we do not emit any other events.
+// If the syscall blocks (that is, P is retaken), retaker emits traceGoSysBlock;
+// when syscall returns we emit traceGoSysExit and when the goroutine starts running
+// (potentially instantly, if exitsyscallfast returns true) we emit traceGoStart.
+// To ensure that traceGoSysExit is emitted strictly after traceGoSysBlock,
+// we remember current value of syscalltick in m (_g_.m.syscalltick = _g_.m.p.syscalltick),
+// whoever emits traceGoSysBlock increments p.syscalltick afterwards;
+// and we wait for the increment before emitting traceGoSysExit.
+// Note that the increment is done even if tracing is not enabled,
+// because tracing can be enabled in the middle of syscall. We don't want the wait to hang.
+//
//go:nosplit
func reentersyscall(pc, sp uintptr) {
_g_ := getg()
// but can have inconsistent g->sched, do not let GC observe it.
_g_.m.locks++
+ if trace.enabled {
+ systemstack(traceGoSysCall)
+ }
+
// Entersyscall must not call any function that might split/grow the stack.
// (See details in comment above.)
// Catch calls that might, by replacing the stack guard with something that
save(pc, sp)
}
+ _g_.m.syscalltick = _g_.m.p.syscalltick
_g_.m.mcache = nil
_g_.m.p.m = nil
atomicstore(&_g_.m.p.status, _Psyscall)
func entersyscall_gcwait() {
_g_ := getg()
+ _p_ := _g_.m.p
lock(&sched.lock)
- if sched.stopwait > 0 && cas(&_g_.m.p.status, _Psyscall, _Pgcstop) {
+ if sched.stopwait > 0 && cas(&_p_.status, _Psyscall, _Pgcstop) {
+ if trace.enabled {
+ traceGoSysBlock(_p_)
+ traceProcStop(_p_)
+ }
+ _p_.syscalltick++
if sched.stopwait--; sched.stopwait == 0 {
notewakeup(&sched.stopnote)
}
_g_.m.locks++ // see comment in entersyscall
_g_.throwsplit = true
_g_.stackguard0 = stackPreempt // see comment in entersyscall
+ _g_.m.syscalltick = _g_.m.p.syscalltick
+ _g_.m.p.syscalltick++
// Leave SP around for GC and traceback.
pc := getcallerpc(unsafe.Pointer(&dummy))
}
func entersyscallblock_handoff() {
+ if trace.enabled {
+ traceGoSysCall()
+ traceGoSysBlock(getg().m.p)
+ }
handoffp(releasep())
}
}
_g_.waitsince = 0
+ oldp := _g_.m.p
if exitsyscallfast() {
if _g_.m.mcache == nil {
throw("lost mcache")
}
+ if trace.enabled {
+ if oldp != _g_.m.p || _g_.m.syscalltick != _g_.m.p.syscalltick {
+ systemstack(traceGoStart)
+ }
+ }
// There's a cpu for us, so we can run.
_g_.m.p.syscalltick++
// We need to cas the status and scan before resuming...
return
}
+ if trace.enabled {
+ // Wait till traceGoSysBlock event is emited.
+ // This ensures consistency of the trace (the goroutine is started after it is blocked).
+ for oldp != nil && oldp.syscalltick == _g_.m.syscalltick {
+ osyield()
+ }
+ systemstack(traceGoSysExit)
+ }
+
_g_.m.locks--
// Call the scheduler.
// There's a cpu for us, so we can run.
_g_.m.mcache = _g_.m.p.mcache
_g_.m.p.m = _g_.m
+ if _g_.m.syscalltick != _g_.m.p.syscalltick {
+ if trace.enabled {
+ // The p was retaken and then enter into syscall again (since _g_.m.syscalltick has changed).
+ // traceGoSysBlock for this syscall was already emitted,
+ // but here we effectively retake the p from the new syscall running on the same p.
+ systemstack(func() {
+ // Denote blocking of the new syscall.
+ traceGoSysBlock(_g_.m.p)
+ // Denote completion of the current syscall.
+ traceGoSysExit()
+ })
+ }
+ _g_.m.p.syscalltick++
+ }
return true
}
// Try to get any other idle P.
+ oldp := _g_.m.p
_g_.m.mcache = nil
_g_.m.p = nil
if sched.pidle != nil {
var ok bool
systemstack(func() {
ok = exitsyscallfast_pidle()
+ if ok && trace.enabled {
+ if oldp != nil {
+ // Wait till traceGoSysBlock event is emited.
+ // This ensures consistency of the trace (the goroutine is started after it is blocked).
+ for oldp.syscalltick == _g_.m.syscalltick {
+ osyield()
+ }
+ }
+ traceGoSysExit()
+ }
})
if ok {
return true
// Allocate a new g, with a stack big enough for stacksize bytes.
func malg(stacksize int32) *g {
- newg := allocg()
+ newg := new(g)
if stacksize >= 0 {
stacksize = round2(_StackSystem + stacksize)
systemstack(func() {
newg.sched.g = guintptr(unsafe.Pointer(newg))
gostartcallfn(&newg.sched, fn)
newg.gopc = callerpc
+ newg.startpc = fn.fn
casgstatus(newg, _Gdead, _Grunnable)
if _p_.goidcache == _p_.goidcacheend {
if raceenabled {
newg.racectx = racegostart(callerpc)
}
+ if trace.enabled {
+ traceGoCreate(newg, newg.startpc)
+ }
runqput(_p_, newg)
if atomicload(&sched.npidle) != 0 && atomicload(&sched.nmspinning) == 0 && unsafe.Pointer(fn.fn) != unsafe.Pointer(funcPC(main)) { // TODO: fast atomic
pc = (*uint8)(unsafe.Pointer(uintptr(funcPC(_ExternalCode) + _PCQuantum)))
}
stk[0] = uintptr(unsafe.Pointer(pc))
- if mp.gcing != 0 || mp.helpgc != 0 {
+ if mp.preemptoff != "" || mp.helpgc != 0 {
stk[1] = funcPC(_GC) + _PCQuantum
} else {
stk[1] = funcPC(_System) + _PCQuantum
// gcworkbufs are not being modified by either the GC or
// the write barrier code.
// Returns list of Ps with local work, they need to be scheduled by the caller.
-func procresize(new int32) *p {
+func procresize(nprocs int32) *p {
old := gomaxprocs
- if old < 0 || old > _MaxGomaxprocs || new <= 0 || new > _MaxGomaxprocs {
+ if old < 0 || old > _MaxGomaxprocs || nprocs <= 0 || nprocs > _MaxGomaxprocs {
throw("procresize: invalid arg")
}
+ if trace.enabled {
+ traceGomaxprocs(nprocs)
+ }
// initialize new P's
- for i := int32(0); i < new; i++ {
- p := allp[i]
- if p == nil {
- p = newP()
- p.id = i
- p.status = _Pgcstop
- atomicstorep(unsafe.Pointer(&allp[i]), unsafe.Pointer(p))
- }
- if p.mcache == nil {
+ for i := int32(0); i < nprocs; i++ {
+ pp := allp[i]
+ if pp == nil {
+ pp = new(p)
+ pp.id = i
+ pp.status = _Pgcstop
+ atomicstorep(unsafe.Pointer(&allp[i]), unsafe.Pointer(pp))
+ }
+ if pp.mcache == nil {
if old == 0 && i == 0 {
if getg().m.mcache == nil {
throw("missing mcache?")
}
- p.mcache = getg().m.mcache // bootstrap
+ pp.mcache = getg().m.mcache // bootstrap
} else {
- p.mcache = allocmcache()
+ pp.mcache = allocmcache()
}
}
}
// free unused P's
- for i := new; i < old; i++ {
+ for i := nprocs; i < old; i++ {
p := allp[i]
+ if trace.enabled {
+ if p == getg().m.p {
+ // moving to p[0], pretend that we were descheduled
+ // and then scheduled again to keep the trace sane.
+ traceGoSched()
+ traceProcStop(p)
+ }
+ }
// move all runable goroutines to the global queue
for p.runqhead != p.runqtail {
// pop from tail of local queue
freemcache(p.mcache)
p.mcache = nil
gfpurge(p)
+ traceProcFree(p)
p.status = _Pdead
// can't free P itself because it can be referenced by an M in syscall
}
_g_ := getg()
- if _g_.m.p != nil && _g_.m.p.id < new {
+ if _g_.m.p != nil && _g_.m.p.id < nprocs {
// continue to use the current P
_g_.m.p.status = _Prunning
} else {
p.m = nil
p.status = _Pidle
acquirep(p)
+ if trace.enabled {
+ traceGoStart()
+ }
}
var runnablePs *p
- for i := new - 1; i >= 0; i-- {
+ for i := nprocs - 1; i >= 0; i-- {
p := allp[i]
if _g_.m.p == p {
continue
}
}
var int32p *int32 = &gomaxprocs // make compiler check that gomaxprocs is an int32
- atomicstore((*uint32)(unsafe.Pointer(int32p)), uint32(new))
+ atomicstore((*uint32)(unsafe.Pointer(int32p)), uint32(nprocs))
return runnablePs
}
_g_.m.p = _p_
_p_.m = _g_.m
_p_.status = _Prunning
+
+ if trace.enabled {
+ traceProcStart()
+ }
}
// Disassociate p and the current m.
print("releasep: m=", _g_.m, " m->p=", _g_.m.p, " p->m=", _p_.m, " m->mcache=", _g_.m.mcache, " p->mcache=", _p_.mcache, " p->status=", _p_.status, "\n")
throw("releasep: invalid p state")
}
+ if trace.enabled {
+ traceProcStop(_g_.m.p)
+ }
_g_.m.p = nil
_g_.m.mcache = nil
_p_.m = nil
// increment nmidle and report deadlock.
incidlelocked(-1)
if cas(&_p_.status, s, _Pidle) {
+ if trace.enabled {
+ traceGoSysBlock(_p_)
+ traceProcStop(_p_)
+ }
n++
+ _p_.syscalltick++
handoffp(_p_)
}
incidlelocked(1)
if lockedg != nil {
id3 = lockedg.goid
}
- print(" M", mp.id, ": p=", id1, " curg=", id2, " mallocing=", mp.mallocing, " throwing=", mp.throwing, " gcing=", mp.gcing, ""+" locks=", mp.locks, " dying=", mp.dying, " helpgc=", mp.helpgc, " spinning=", mp.spinning, " blocked=", getg().m.blocked, " lockedg=", id3, "\n")
+ print(" M", mp.id, ": p=", id1, " curg=", id2, " mallocing=", mp.mallocing, " throwing=", mp.throwing, " preemptoff=", mp.preemptoff, ""+" locks=", mp.locks, " dying=", mp.dying, " helpgc=", mp.helpgc, " spinning=", mp.spinning, " blocked=", getg().m.blocked, " lockedg=", id3, "\n")
}
lock(&allglock)
return
}
-var goexperiment string = "GOEXPERIMENT" // TODO: defined in zaexperiment.h
-
func haveexperiment(name string) bool {
x := goexperiment
for x != "" {
import (
"math"
"runtime"
+ "sync"
"sync/atomic"
"syscall"
"testing"
}
}
+func BenchmarkCreateGoroutinesCapture(b *testing.B) {
+ b.ReportAllocs()
+ for i := 0; i < b.N; i++ {
+ const N = 4
+ var wg sync.WaitGroup
+ wg.Add(N)
+ for i := 0; i < N; i++ {
+ i := i
+ go func() {
+ if i >= N {
+ b.Logf("bad") // just to capture b
+ }
+ wg.Done()
+ }()
+ }
+ wg.Wait()
+ }
+}
+
type Matrix [][]float64
func BenchmarkMatmult(b *testing.B) {
var ticks struct {
lock mutex
+ pad uint32 // ensure 8-byte alignment of val on 386
val uint64
}
return make([]string, n)
}
-// TODO: Move to parfor.go when parfor.c becomes parfor.go.
-func parforalloc(nthrmax uint32) *parfor {
- return &parfor{
- thr: &make([]parforthread, nthrmax)[0],
- nthrmax: nthrmax,
- }
-}
-
var envs []string
var argslice []string
return envs
}
+// TODO: These should be locals in testAtomic64, but we don't 8-byte
+// align stack variables on 386.
+var test_z64, test_x64 uint64
+
func testAtomic64() {
- var z64, x64 uint64
-
- z64 = 42
- x64 = 0
- prefetcht0(uintptr(unsafe.Pointer(&z64)))
- prefetcht1(uintptr(unsafe.Pointer(&z64)))
- prefetcht2(uintptr(unsafe.Pointer(&z64)))
- prefetchnta(uintptr(unsafe.Pointer(&z64)))
- if cas64(&z64, x64, 1) {
+ test_z64 = 42
+ test_x64 = 0
+ prefetcht0(uintptr(unsafe.Pointer(&test_z64)))
+ prefetcht1(uintptr(unsafe.Pointer(&test_z64)))
+ prefetcht2(uintptr(unsafe.Pointer(&test_z64)))
+ prefetchnta(uintptr(unsafe.Pointer(&test_z64)))
+ if cas64(&test_z64, test_x64, 1) {
throw("cas64 failed")
}
- if x64 != 0 {
+ if test_x64 != 0 {
throw("cas64 failed")
}
- x64 = 42
- if !cas64(&z64, x64, 1) {
+ test_x64 = 42
+ if !cas64(&test_z64, test_x64, 1) {
throw("cas64 failed")
}
- if x64 != 42 || z64 != 1 {
+ if test_x64 != 42 || test_z64 != 1 {
throw("cas64 failed")
}
- if atomicload64(&z64) != 1 {
+ if atomicload64(&test_z64) != 1 {
throw("load64 failed")
}
- atomicstore64(&z64, (1<<40)+1)
- if atomicload64(&z64) != (1<<40)+1 {
+ atomicstore64(&test_z64, (1<<40)+1)
+ if atomicload64(&test_z64) != (1<<40)+1 {
throw("store64 failed")
}
- if xadd64(&z64, (1<<40)+1) != (2<<40)+2 {
+ if xadd64(&test_z64, (1<<40)+1) != (2<<40)+2 {
throw("xadd64 failed")
}
- if atomicload64(&z64) != (2<<40)+2 {
+ if atomicload64(&test_z64) != (2<<40)+2 {
throw("xadd64 failed")
}
- if xchg64(&z64, (3<<40)+3) != (2<<40)+2 {
+ if xchg64(&test_z64, (3<<40)+3) != (2<<40)+2 {
throw("xchg64 failed")
}
- if atomicload64(&z64) != (3<<40)+3 {
+ if atomicload64(&test_z64) != (3<<40)+3 {
throw("xchg64 failed")
}
}
// TODO(rsc): Make GC respect debug.invalidptr.
-// Holds variables parsed from GODEBUG env var.
+// Holds variables parsed from GODEBUG env var,
+// except for "memprofilerate" since there is an
+// existing int var for that value, which may
+// already have an initial value.
var debug struct {
allocfreetrace int32
efence int32
continue
}
key, value := field[:i], field[i+1:]
- for _, v := range dbgvars {
- if v.name == key {
- *v.value = int32(atoi(value))
+
+ // Update MemProfileRate directly here since it
+ // is int, not int32, and should only be updated
+ // if specified in GODEBUG.
+ if key == "memprofilerate" {
+ MemProfileRate = atoi(value)
+ } else {
+ for _, v := range dbgvars {
+ if v.name == key {
+ *v.value = int32(atoi(value))
+ }
}
}
}
ctxt unsafe.Pointer // this has to be a pointer so that gc scans it
ret uintreg
lr uintptr
+ bp uintptr // for GOEXPERIMENT=framepointer
}
// Known to compiler.
paniconfault bool // panic (instead of crash) on unexpected fault address
preemptscan bool // preempted g does scan for gc
gcworkdone bool // debug: cleared at begining of gc work phase cycle, set by gcphasework, tested at end of cycle
+ gcscanvalid bool // false at start of gc cycle, true if G has not run since last scan
throwsplit bool // must not split stack
raceignore int8 // ignore race detection events
m *m // for debuggers, but offset not hard-coded
sigcode1 uintptr
sigpc uintptr
gopc uintptr // pc of go statement that created this goroutine
+ startpc uintptr // pc of goroutine function
racectx uintptr
waiting *sudog // sudog structures this g is waiting on (that have a valid elem ptr)
}
id int32
mallocing int32
throwing int32
- gcing int32
+ preemptoff string // if != "", keep curg running on this m
locks int32
softfloat int32
dying int32
traceback uint8
waitunlockf unsafe.Pointer // todo go func(*g, unsafe.pointer) bool
waitlock unsafe.Pointer
+ waittraceev byte
+ syscalltick uint32
//#ifdef GOOS_windows
thread uintptr // thread handle
// these are here because they are too large to be on the stack
gfree *g
gfreecnt int32
+ tracebuf *traceBuf
+
pad [64]byte
}
pushcnt uintptr
}
-// Parallel for descriptor.
-type parfor struct {
- body unsafe.Pointer // go func(*parfor, uint32), executed for each element
- done uint32 // number of idle threads
- nthr uint32 // total number of threads
- nthrmax uint32 // maximum number of threads
- thrseq uint32 // thread id sequencer
- cnt uint32 // iteration space [0, cnt)
- ctx unsafe.Pointer // arbitrary user context
- wait bool // if true, wait while all threads finish processing,
- // otherwise parfor may return while other threads are still working
- thr *parforthread // array of thread descriptors
- pad uint32 // to align parforthread.pos for 64-bit atomic operations
- // stats
- nsteal uint64
- nstealcnt uint64
- nprocyield uint64
- nosyield uint64
- nsleep uint64
-}
-
// Track memory allocated by code not written in Go during a cgo call,
// so that the garbage collector can see them.
type cgomal struct {
* so they can be garbage collected if there are no other pointers to nodes.
*/
-/*
- * Parallel for over [0, n).
- * body() is executed for each iteration.
- * nthr - total number of worker threads.
- * ctx - arbitrary user context.
- * if wait=true, threads return from parfor() when all work is done;
- * otherwise, threads can return while other threads are still finishing processing.
- */
-
// for mmap, we only pass the lower 32 bits of file offset to the
// assembly routine; the higher bits (if required), should be provided
// by the assembly routine as 0.
}
func block() {
- gopark(nil, nil, "select (no cases)") // forever
+ gopark(nil, nil, "select (no cases)", traceEvGoStop) // forever
}
// overwrites return pc on stack to signal which case of the select
// wait for someone to wake us up
gp.param = nil
- gopark(selparkcommit, unsafe.Pointer(sel), "select")
+ gopark(selparkcommit, unsafe.Pointer(sel), "select", traceEvGoBlockSelect)
// someone woke us up
sellock(sel)
// Any semrelease after the cansemacquire knows we're waiting
// (we set nwait above), so go to sleep.
root.queue(addr, s)
- goparkunlock(&root.lock, "semacquire")
+ goparkunlock(&root.lock, "semacquire", traceEvGoBlockSync)
if cansemacquire(addr) {
break
}
s.tail.next = w
}
s.tail = w
- goparkunlock(&s.lock, "semacquire")
+ goparkunlock(&s.lock, "semacquire", traceEvGoBlockCond)
if t0 != 0 {
blockevent(int64(w.releasetime)-t0, 2)
}
s.tail.next = w
}
s.tail = w
- goparkunlock(&s.lock, "semarelease")
+ goparkunlock(&s.lock, "semarelease", traceEvGoBlockCond)
releaseSudog(w)
} else {
unlock(&s.lock)
var stackfreequeue stack
+// Cached value of haveexperiment("framepointer")
+var framepointer_enabled bool
+
func stackinit() {
if _StackCacheSize&_PageMask != 0 {
throw("cache size must be a multiple of page size")
}
var x gclinkptr
c := thisg.m.mcache
- if c == nil || thisg.m.gcing != 0 || thisg.m.helpgc != 0 {
+ if c == nil || thisg.m.preemptoff != "" || thisg.m.helpgc != 0 {
// c == nil can happen in the guts of exitsyscall or
// procresize. Just get a stack from the global pool.
// Also don't touch stackcache during gc
}
x := gclinkptr(v)
c := gp.m.mcache
- if c == nil || gp.m.gcing != 0 || gp.m.helpgc != 0 {
+ if c == nil || gp.m.preemptoff != "" || gp.m.helpgc != 0 {
lock(&stackpoolmu)
stackpoolfree(x, order)
unlock(&stackpoolmu)
// | args from caller |
// +------------------+ <- frame->argp
// | return address |
+// +------------------+
+// | caller's BP (*) | (*) if framepointer_enabled && varp < sp
// +------------------+ <- frame->varp
// | locals |
// +------------------+
adjustpointers(unsafe.Pointer(frame.varp-size), &bv, adjinfo, f)
}
+ // Adjust saved base pointer if there is one.
+ if thechar == '6' && frame.argp-frame.varp == 2*regSize {
+ if !framepointer_enabled {
+ print("runtime: found space for saved base pointer, but no framepointer experiment\n")
+ print("argp=", hex(frame.argp), " varp=", hex(frame.varp), "\n")
+ throw("bad frame layout")
+ }
+ if stackDebug >= 3 {
+ print(" saved bp\n")
+ }
+ adjustpointer(adjinfo, unsafe.Pointer(frame.varp))
+ }
+
// Adjust arguments.
if frame.arglen > 0 {
var bv bitvector
// Be conservative about where we preempt.
// We are interested in preempting user Go code, not runtime code.
- // If we're holding locks, mallocing, or GCing, don't preempt.
+ // If we're holding locks, mallocing, or preemption is disabled, don't
+ // preempt.
// This check is very early in newstack so that even the status change
// from Grunning to Gwaiting and back doesn't happen in this case.
// That status change by itself can be viewed as a small preemption,
// it needs a lock held by the goroutine), that small preemption turns
// into a real deadlock.
if preempt {
- if thisg.m.locks != 0 || thisg.m.mallocing != 0 || thisg.m.gcing != 0 || thisg.m.p.status != _Prunning {
+ if thisg.m.locks != 0 || thisg.m.mallocing != 0 || thisg.m.preemptoff != "" || thisg.m.p.status != _Prunning {
// Let the goroutine keep running for now.
// gp->preempt is set, so it will be preempted next time.
gp.stackguard0 = gp.stack.lo + _StackGuard
// Act like goroutine called runtime.Gosched.
casgstatus(gp, _Gwaiting, _Grunning)
- gosched_m(gp) // never return
+ gopreempt_m(gp) // never return
}
// Allocate a bigger segment and move the stack.
"unsafe"
)
-func concatstrings(a []string) string {
+// The constant is known to the compiler.
+// There is no fundamental theory behind this number.
+const tmpStringBufSize = 32
+
+type tmpBuf [tmpStringBufSize]byte
+
+// concatstrings implements a Go string concatenation x+y+z+...
+// The operands are passed in the slice a.
+// If buf != nil, the compiler has determined that the result does not
+// escape the calling function, so the string data can be stored in buf
+// if small enough.
+func concatstrings(buf *tmpBuf, a []string) string {
idx := 0
l := 0
count := 0
if count == 0 {
return ""
}
- if count == 1 {
+
+ // If there is just one string and either it is not on the stack
+ // or our result does not escape the calling frame (buf != nil),
+ // then we can return that string directly.
+ if count == 1 && (buf != nil || !stringDataOnStack(a[idx])) {
return a[idx]
}
- s, b := rawstring(l)
+ s, b := rawstringtmp(buf, l)
l = 0
for _, x := range a {
copy(b[l:], x)
return s
}
-func concatstring2(a [2]string) string {
- return concatstrings(a[:])
+func concatstring2(buf *tmpBuf, a [2]string) string {
+ return concatstrings(buf, a[:])
}
-func concatstring3(a [3]string) string {
- return concatstrings(a[:])
+func concatstring3(buf *tmpBuf, a [3]string) string {
+ return concatstrings(buf, a[:])
}
-func concatstring4(a [4]string) string {
- return concatstrings(a[:])
+func concatstring4(buf *tmpBuf, a [4]string) string {
+ return concatstrings(buf, a[:])
}
-func concatstring5(a [5]string) string {
- return concatstrings(a[:])
+func concatstring5(buf *tmpBuf, a [5]string) string {
+ return concatstrings(buf, a[:])
}
-func slicebytetostring(b []byte) string {
- if raceenabled && len(b) > 0 {
+// Buf is a fixed-size buffer for the result,
+// it is not nil if the result does not escape.
+func slicebytetostring(buf *tmpBuf, b []byte) string {
+ l := len(b)
+ if l == 0 {
+ // Turns out to be a relatively common case.
+ // Consider that you want to parse out data between parens in "foo()bar",
+ // you find the indices and convert the subslice to string.
+ return ""
+ }
+ if raceenabled && l > 0 {
racereadrangepc(unsafe.Pointer(&b[0]),
- uintptr(len(b)),
+ uintptr(l),
getcallerpc(unsafe.Pointer(&b)),
funcPC(slicebytetostring))
}
- s, c := rawstring(len(b))
+ s, c := rawstringtmp(buf, l)
copy(c, b)
return s
}
+// stringDataOnStack reports whether the string's data is
+// stored on the current goroutine's stack.
+func stringDataOnStack(s string) bool {
+ ptr := uintptr((*stringStruct)(unsafe.Pointer(&s)).str)
+ stk := getg().stack
+ return stk.lo <= ptr && ptr < stk.hi
+}
+
+func rawstringtmp(buf *tmpBuf, l int) (s string, b []byte) {
+ if buf != nil && l <= len(buf) {
+ b = buf[:l]
+ s = slicebytetostringtmp(b)
+ } else {
+ s, b = rawstring(l)
+ }
+ return
+}
+
func slicebytetostringtmp(b []byte) string {
// Return a "string" referring to the actual []byte bytes.
// This is only for use by internal compiler optimizations
// that know that the string form will be discarded before
// the calling goroutine could possibly modify the original
// slice or synchronize with another goroutine.
- // Today, the only such case is a m[string(k)] lookup where
+ // First such case is a m[string(k)] lookup where
// m is a string-keyed map and k is a []byte.
+ // Second such case is "<"+string(b)+">" concatenation where b is []byte.
+ // Third such case is string(b)=="foo" comparison where b is []byte.
if raceenabled && len(b) > 0 {
racereadrangepc(unsafe.Pointer(&b[0]),
return b
}
+func stringtoslicebytetmp(s string) []byte {
+ // Return a slice referring to the actual string bytes.
+ // This is only for use by internal compiler optimizations
+ // that know that the slice won't be mutated.
+ // The only such case today is:
+ // for i, c := range []byte(str)
+
+ str := (*stringStruct)(unsafe.Pointer(&s))
+ ret := slice{array: (*byte)(str.str), len: uint(str.len), cap: uint(str.len)}
+ return *(*[]byte)(unsafe.Pointer(&ret))
+}
+
func stringtoslicerune(s string) []rune {
// two passes.
// unlike slicerunetostring, no race because strings are immutable.
len int
}
-func intstring(v int64) string {
- s, b := rawstring(4)
+func intstring(buf *[4]byte, v int64) string {
+ var s string
+ var b []byte
+ if buf != nil {
+ b = buf[:]
+ s = slicebytetostringtmp(b)
+ } else {
+ s, b = rawstring(4)
+ }
n := runetochar(b, rune(v))
return s[:n]
}
t.Errorf("want %d, got %d", max+9, newmax)
}
}
+
+func TestCompareTempString(t *testing.T) {
+ s := "foo"
+ b := []byte(s)
+ n := testing.AllocsPerRun(1000, func() {
+ if string(b) != s {
+ t.Fatalf("strings are not equal: '%v' and '%v'", string(b), s)
+ }
+ if string(b) == s {
+ } else {
+ t.Fatalf("strings are not equal: '%v' and '%v'", string(b), s)
+ }
+ })
+ if n != 0 {
+ t.Fatalf("want 0 allocs, got %v", n)
+ }
+}
+
+func TestStringOnStack(t *testing.T) {
+ s := ""
+ for i := 0; i < 3; i++ {
+ s = "a" + s + "b" + s + "c"
+ }
+
+ if want := "aaabcbabccbaabcbabccc"; s != want {
+ t.Fatalf("want: '%v', got '%v'", want, s)
+ }
+}
+
+func TestIntString(t *testing.T) {
+ // Non-escaping result of intstring.
+ s := ""
+ for i := 0; i < 4; i++ {
+ s += string(i+'0') + string(i+'0'+1)
+ }
+ if want := "01122334"; s != want {
+ t.Fatalf("want '%v', got '%v'", want, s)
+ }
+
+ // Escaping result of intstring.
+ var a [4]string
+ for i := 0; i < 4; i++ {
+ a[i] = string(i + '0')
+ }
+ s = a[0] + a[1] + a[2] + a[3]
+ if want := "0123"; s != want {
+ t.Fatalf("want '%v', got '%v'", want, s)
+ }
+}
+
+func TestIntStringAllocs(t *testing.T) {
+ unknown := '0'
+ n := testing.AllocsPerRun(1000, func() {
+ s1 := string(unknown)
+ s2 := string(unknown + 1)
+ if s1 == s2 {
+ t.Fatalf("bad")
+ }
+ })
+ if n != 0 {
+ t.Fatalf("want 0 allocs, got %v", n)
+ }
+}
+
+func TestRangeStringCast(t *testing.T) {
+ s := "abc"
+ n := testing.AllocsPerRun(1000, func() {
+ for i, c := range []byte(s) {
+ if c != s[i] {
+ t.Fatalf("want '%c' at pos %v, got '%c'", s[i], i, c)
+ }
+ }
+ })
+ if n != 0 {
+ t.Fatalf("want 0 allocs, got %v", n)
+ }
+}
//go:noescape
func memclr(ptr unsafe.Pointer, n uintptr)
+//go:linkname reflect_memclr reflect.memclr
+func reflect_memclr(ptr unsafe.Pointer, n uintptr) {
+ memclr(ptr, n)
+}
+
// memmove copies n bytes from "from" to "to".
// in memmove_*.s
//go:noescape
--- /dev/null
+package runtime
+
+import "unsafe"
+
+//go:noescape
+func access(name *byte, mode int32) int32
+
+func connect(fd uintptr, addr unsafe.Pointer, len int32) int32
+
+func socket(domain int32, typ int32, prot int32) int32
MOVQ R10, 40(SP)
// g = m->signal
- MOVQ g_m(R10), BP
- MOVQ m_gsignal(BP), BP
- MOVQ BP, g(BX)
+ MOVQ g_m(R10), AX
+ MOVQ m_gsignal(AX), AX
+ MOVQ AX, g(BX)
MOVQ DI, 0(SP)
MOVQ SI, 8(SP)
MOVQ R10, 40(SP)
// g = m->signal
- MOVQ g_m(R10), BP
- MOVQ m_gsignal(BP), BP
- MOVQ BP, g(BX)
+ MOVQ g_m(R10), AX
+ MOVQ m_gsignal(AX), AX
+ MOVQ AX, g(BX)
MOVQ DI, 0(SP)
MOVQ SI, 8(SP)
MOVQ R10, 40(SP)
// g = m->gsignal
- MOVQ g_m(R10), BP
- MOVQ m_gsignal(BP), BP
- MOVQ BP, g(BX)
+ MOVQ g_m(R10), AX
+ MOVQ m_gsignal(AX), AX
+ MOVQ AX, g(BX)
MOVQ DI, 0(SP)
MOVQ SI, 8(SP)
#define SYS_epoll_wait (SYS_BASE + 252)
#define SYS_epoll_create1 (SYS_BASE + 357)
#define SYS_fcntl (SYS_BASE + 55)
+#define SYS_access (SYS_BASE + 33)
+#define SYS_connect (SYS_BASE + 283)
+#define SYS_socket (SYS_BASE + 281)
#define ARM_BASE (SYS_BASE + 0x0f0000)
TEXT runtime·read_tls_fallback(SB),NOSPLIT,$-4
MOVW $0xffff0fe0, R0
B (R0)
+
+TEXT runtime·access(SB),NOSPLIT,$0
+ MOVW 0(FP), R0
+ MOVW 4(FP), R1
+ MOVW $SYS_access, R7
+ SWI $0
+ MOVW R0, ret+8(FP)
+ RET
+
+TEXT runtime·connect(SB),NOSPLIT,$0
+ MOVW 0(FP), R0
+ MOVW 4(FP), R1
+ MOVW 8(FP), R2
+ MOVW $SYS_connect, R7
+ SWI $0
+ MOVW R0, ret+12(FP)
+ RET
+
+TEXT runtime·socket(SB),NOSPLIT,$0
+ MOVW 0(FP), R0
+ MOVW 4(FP), R1
+ MOVW 8(FP), R2
+ MOVW $SYS_socket, R7
+ SWI $0
+ MOVW R0, ret+12(FP)
+ RET
MOVQ R10, 40(SP)
// g = m->signal
- MOVQ g_m(R10), BP
- MOVQ m_gsignal(BP), BP
- MOVQ BP, g(BX)
+ MOVQ g_m(R10), AX
+ MOVQ m_gsignal(AX), AX
+ MOVQ AX, g(BX)
MOVQ DI, 0(SP)
MOVQ SI, 8(SP)
MOVQ R10, 40(SP)
// g = m->signal
- MOVQ g_m(R10), BP
- MOVQ m_gsignal(BP), BP
- MOVQ BP, g(BX)
+ MOVQ g_m(R10), AX
+ MOVQ m_gsignal(AX), AX
+ MOVQ AX, g(BX)
MOVQ DI, 0(SP)
MOVQ SI, 8(SP)
t.arg = getg()
lock(&timers.lock)
addtimerLocked(t)
- goparkunlock(&timers.lock, "sleep")
+ goparkunlock(&timers.lock, "sleep", traceEvGoSleep)
}
// startTimer adds t to the timer heap.
if delta < 0 || faketime > 0 {
// No timers left - put goroutine to sleep.
timers.rescheduling = true
- goparkunlock(&timers.lock, "timer goroutine (idle)")
+ goparkunlock(&timers.lock, "timer goroutine (idle)", traceEvGoBlock)
continue
}
// At least one timer pending. Sleep until then.
--- /dev/null
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Go execution tracer.
+// The tracer captures a wide range of execution events like goroutine
+// creation/blocking/unblocking, syscall enter/exit/block, GC-related events,
+// changes of heap size, processor start/stop, etc and writes them to a buffer
+// in a compact form. A precise nanosecond-precision timestamp and a stack
+// trace is captured for most events.
+// See http://golang.org/s/go15trace for more info.
+
+package runtime
+
+import "unsafe"
+
+// Event types in the trace, args are given in square brackets.
+const (
+ traceEvNone = 0 // unused
+ traceEvBatch = 1 // start of per-P batch of events [pid, timestamp]
+ traceEvFrequency = 2 // contains tracer timer frequency [frequency (ticks per second)]
+ traceEvStack = 3 // stack [stack id, number of PCs, array of PCs]
+ traceEvGomaxprocs = 4 // current value of GOMAXPROCS [timestamp, GOMAXPROCS, stack id]
+ traceEvProcStart = 5 // start of P [timestamp]
+ traceEvProcStop = 6 // stop of P [timestamp]
+ traceEvGCStart = 7 // GC start [timestamp, stack id]
+ traceEvGCDone = 8 // GC done [timestamp]
+ traceEvGCScanStart = 9 // GC scan start [timestamp]
+ traceEvGCScanDone = 10 // GC scan done [timestamp]
+ traceEvGCSweepStart = 11 // GC sweep start [timestamp, stack id]
+ traceEvGCSweepDone = 12 // GC sweep done [timestamp]
+ traceEvGoCreate = 13 // goroutine creation [timestamp, new goroutine id, start PC, stack id]
+ traceEvGoStart = 14 // goroutine starts running [timestamp, goroutine id]
+ traceEvGoEnd = 15 // goroutine ends [timestamp]
+ traceEvGoStop = 16 // goroutine stops (like in select{}) [timestamp, stack]
+ traceEvGoSched = 17 // goroutine calls Gosched [timestamp, stack]
+ traceEvGoPreempt = 18 // goroutine is preempted [timestamp, stack]
+ traceEvGoSleep = 19 // goroutine calls Sleep [timestamp, stack]
+ traceEvGoBlock = 20 // goroutine blocks [timestamp, stack]
+ traceEvGoUnblock = 21 // goroutine is unblocked [timestamp, goroutine id, stack]
+ traceEvGoBlockSend = 22 // goroutine blocks on chan send [timestamp, stack]
+ traceEvGoBlockRecv = 23 // goroutine blocks on chan recv [timestamp, stack]
+ traceEvGoBlockSelect = 24 // goroutine blocks on select [timestamp, stack]
+ traceEvGoBlockSync = 25 // goroutine blocks on Mutex/RWMutex [timestamp, stack]
+ traceEvGoBlockCond = 26 // goroutine blocks on Cond [timestamp, stack]
+ traceEvGoBlockNet = 27 // goroutine blocks on network [timestamp, stack]
+ traceEvGoSysCall = 28 // syscall enter [timestamp, stack]
+ traceEvGoSysExit = 29 // syscall exit [timestamp, goroutine id]
+ traceEvGoSysBlock = 30 // syscall blocks [timestamp, stack]
+ traceEvGoWaiting = 31 // denotes that goroutine is blocked when tracing starts [goroutine id]
+ traceEvGoInSyscall = 32 // denotes that goroutine is in syscall when tracing starts [goroutine id]
+ traceEvHeapAlloc = 33 // memstats.heap_alloc change [timestamp, heap_alloc]
+ traceEvNextGC = 34 // memstats.next_gc change [timestamp, next_gc]
+ traceEvTimerGoroutine = 35 // denotes timer goroutine [timer goroutine id]
+ traceEvCount = 36
+)
+
+const (
+ // Timestamps in trace are cputicks/traceTickDiv.
+ // This makes absolute values of timestamp diffs smaller,
+ // and so they are encoded in less number of bytes.
+ // 64 is somewhat arbitrary (one tick is ~20ns on a 3GHz machine).
+ traceTickDiv = 64
+ // Maximum number of PCs in a single stack trace.
+ // Since events contain only stack id rather than whole stack trace,
+ // we can allow quite large values here.
+ traceStackSize = 128
+ // Identifier of a fake P that is used when we trace without a real P.
+ traceGlobProc = -1
+ // Maximum number of bytes to encode uint64 in base-128.
+ traceBytesPerNumber = 10
+ // Shift of the number of arguments in the first event byte.
+ traceArgCountShift = 6
+)
+
+// trace is global tracing context.
+var trace struct {
+ lock mutex // protects the following members
+ lockOwner *g // to avoid deadlocks during recursive lock locks
+ enabled bool // when set runtime traces events
+ shutdown bool // set when we are waiting for trace reader to finish after setting enabled to false
+ headerWritten bool // whether ReadTrace has emitted trace header
+ footerWritten bool // whether ReadTrace has emitted trace footer
+ shutdownSema uint32 // used to wait for ReadTrace completion
+ ticksStart int64 // cputicks when tracing was started
+ ticksEnd int64 // cputicks when tracing was stopped
+ timeStart int64 // nanotime when tracing was started
+ timeEnd int64 // nanotime when tracing was stopped
+ reading *traceBuf // buffer currently handed off to user
+ empty *traceBuf // stack of empty buffers
+ fullHead *traceBuf // queue of full buffers
+ fullTail *traceBuf
+ reader *g // goroutine that called ReadTrace, or nil
+ stackTab traceStackTable // maps stack traces to unique ids
+
+ bufLock mutex // protects buf
+ buf *traceBuf // global trace buffer, used when running without a p
+}
+
+// traceBufHeader is per-P tracing buffer.
+type traceBufHeader struct {
+ link *traceBuf // in trace.empty/full
+ lastTicks uint64 // when we wrote the last event
+ buf []byte // trace data, always points to traceBuf.arr
+ stk [traceStackSize]uintptr // scratch buffer for traceback
+}
+
+// traceBuf is per-P tracing buffer.
+type traceBuf struct {
+ traceBufHeader
+ arr [64<<10 - unsafe.Sizeof(traceBufHeader{})]byte // underlying buffer for traceBufHeader.buf
+}
+
+// StartTrace enables tracing for the current process.
+// While tracing, the data will be buffered and available via ReadTrace.
+// StartTrace returns an error if tracing is already enabled.
+// Most clients should use the runtime/pprof package or the testing package's
+// -test.trace flag instead of calling StartTrace directly.
+func StartTrace() error {
+ // Stop the world, so that we can take a consistent snapshot
+ // of all goroutines at the beginning of the trace.
+ semacquire(&worldsema, false)
+ _g_ := getg()
+ _g_.m.preemptoff = "start tracing"
+ systemstack(stoptheworld)
+
+ // We are in stop-the-world, but syscalls can finish and write to trace concurrently.
+ // Exitsyscall could check trace.enabled long before and then suddenly wake up
+ // and decide to write to trace at a random point in time.
+ // However, such syscall will use the global trace.buf buffer, because we've
+ // acquired all p's by doing stop-the-world. So this protects us from such races.
+ lock(&trace.bufLock)
+
+ if trace.enabled || trace.shutdown {
+ unlock(&trace.bufLock)
+ _g_.m.preemptoff = ""
+ semrelease(&worldsema)
+ systemstack(starttheworld)
+ return errorString("tracing is already enabled")
+ }
+
+ trace.ticksStart = cputicks()
+ trace.timeStart = nanotime()
+ trace.enabled = true
+ trace.headerWritten = false
+ trace.footerWritten = false
+
+ for _, gp := range allgs {
+ status := readgstatus(gp)
+ if status != _Gdead {
+ traceGoCreate(gp, gp.startpc)
+ }
+ if status == _Gwaiting {
+ traceEvent(traceEvGoWaiting, false, uint64(gp.goid))
+ }
+ if status == _Gsyscall {
+ traceEvent(traceEvGoInSyscall, false, uint64(gp.goid))
+ }
+ }
+ traceProcStart()
+ traceGoStart()
+
+ unlock(&trace.bufLock)
+
+ _g_.m.preemptoff = ""
+ semrelease(&worldsema)
+ systemstack(starttheworld)
+ return nil
+}
+
+// StopTrace stops tracing, if it was previously enabled.
+// StopTrace only returns after all the reads for the trace have completed.
+func StopTrace() {
+ // Stop the world so that we can collect the trace buffers from all p's below,
+ // and also to avoid races with traceEvent.
+ semacquire(&worldsema, false)
+ _g_ := getg()
+ _g_.m.preemptoff = "stop tracing"
+ systemstack(stoptheworld)
+
+ // See the comment in StartTrace.
+ lock(&trace.bufLock)
+
+ if !trace.enabled {
+ unlock(&trace.bufLock)
+ _g_.m.preemptoff = ""
+ semrelease(&worldsema)
+ systemstack(starttheworld)
+ return
+ }
+
+ traceGoSched()
+ traceGoStart()
+
+ for _, p := range &allp {
+ if p == nil {
+ break
+ }
+ buf := p.tracebuf
+ if buf != nil {
+ traceFullQueue(buf)
+ p.tracebuf = nil
+ }
+ }
+ if trace.buf != nil && len(trace.buf.buf) != 0 {
+ buf := trace.buf
+ trace.buf = nil
+ traceFullQueue(buf)
+ }
+
+ for {
+ trace.ticksEnd = cputicks()
+ trace.timeEnd = nanotime()
+ // Windows time can tick only every 15ms, wait for at least one tick.
+ if trace.timeEnd != trace.timeStart {
+ break
+ }
+ osyield()
+ }
+
+ trace.enabled = false
+ trace.shutdown = true
+ trace.stackTab.dump()
+
+ unlock(&trace.bufLock)
+
+ _g_.m.preemptoff = ""
+ semrelease(&worldsema)
+ systemstack(starttheworld)
+
+ // The world is started but we've set trace.shutdown, so new tracing can't start.
+ // Wait for the trace reader to flush pending buffers and stop.
+ semacquire(&trace.shutdownSema, false)
+ if raceenabled {
+ raceacquire(unsafe.Pointer(&trace.shutdownSema))
+ }
+
+ // The lock protects us from races with StartTrace/StopTrace because they do stop-the-world.
+ lock(&trace.lock)
+ for _, p := range &allp {
+ if p == nil {
+ break
+ }
+ if p.tracebuf != nil {
+ throw("trace: non-empty trace buffer in proc")
+ }
+ }
+ if trace.buf != nil {
+ throw("trace: non-empty global trace buffer")
+ }
+ if trace.fullHead != nil || trace.fullTail != nil {
+ throw("trace: non-empty full trace buffer")
+ }
+ if trace.reading != nil || trace.reader != nil {
+ throw("trace: reading after shutdown")
+ }
+ for trace.empty != nil {
+ buf := trace.empty
+ trace.empty = buf.link
+ sysFree(unsafe.Pointer(buf), unsafe.Sizeof(*buf), &memstats.other_sys)
+ }
+ trace.shutdown = false
+ unlock(&trace.lock)
+}
+
+// ReadTrace returns the next chunk of binary tracing data, blocking until data
+// is available. If tracing is turned off and all the data accumulated while it
+// was on has been returned, ReadTrace returns nil. The caller must copy the
+// returned data before calling ReadTrace again.
+// ReadTrace must be called from one goroutine at a time.
+func ReadTrace() []byte {
+ // This function may need to lock trace.lock recursively
+ // (goparkunlock -> traceGoPark -> traceEvent -> traceFlush).
+ // To allow this we use trace.lockOwner.
+ // Also this function must not allocate while holding trace.lock:
+ // allocation can call heap allocate, which will try to emit a trace
+ // event while holding heap lock.
+ lock(&trace.lock)
+ trace.lockOwner = getg()
+
+ if trace.reader != nil {
+ // More than one goroutine reads trace. This is bad.
+ // But we rather do not crash the program because of tracing,
+ // because tracing can be enabled at runtime on prod servers.
+ trace.lockOwner = nil
+ unlock(&trace.lock)
+ println("runtime: ReadTrace called from multiple goroutines simultaneously")
+ return nil
+ }
+ // Recycle the old buffer.
+ if buf := trace.reading; buf != nil {
+ buf.link = trace.empty
+ trace.empty = buf
+ trace.reading = nil
+ }
+ // Write trace header.
+ if !trace.headerWritten {
+ trace.headerWritten = true
+ trace.lockOwner = nil
+ unlock(&trace.lock)
+ return []byte("gotrace\x00")
+ }
+ // Wait for new data.
+ if trace.fullHead == nil && !trace.shutdown {
+ trace.reader = getg()
+ goparkunlock(&trace.lock, "trace reader (blocked)", traceEvGoBlock)
+ lock(&trace.lock)
+ }
+ // Write a buffer.
+ if trace.fullHead != nil {
+ buf := traceFullDequeue()
+ trace.reading = buf
+ trace.lockOwner = nil
+ unlock(&trace.lock)
+ return buf.buf
+ }
+ // Write footer with timer frequency.
+ if !trace.footerWritten {
+ trace.footerWritten = true
+ // Use float64 because (trace.ticksEnd - trace.ticksStart) * 1e9 can overflow int64.
+ freq := float64(trace.ticksEnd-trace.ticksStart) * 1e9 / float64(trace.timeEnd-trace.timeStart) / traceTickDiv
+ trace.lockOwner = nil
+ unlock(&trace.lock)
+ var data []byte
+ data = append(data, traceEvFrequency|0<<traceArgCountShift)
+ data = traceAppend(data, uint64(freq))
+ if timers.gp != nil {
+ data = append(data, traceEvTimerGoroutine|0<<traceArgCountShift)
+ data = traceAppend(data, uint64(timers.gp.goid))
+ }
+ return data
+ }
+ // Done.
+ if trace.shutdown {
+ trace.lockOwner = nil
+ unlock(&trace.lock)
+ if raceenabled {
+ // Model synchronization on trace.shutdownSema, which race
+ // detector does not see. This is required to avoid false
+ // race reports on writer passed to pprof.StartTrace.
+ racerelease(unsafe.Pointer(&trace.shutdownSema))
+ }
+ // trace.enabled is already reset, so can call traceable functions.
+ semrelease(&trace.shutdownSema)
+ return nil
+ }
+ // Also bad, but see the comment above.
+ trace.lockOwner = nil
+ unlock(&trace.lock)
+ println("runtime: spurious wakeup of trace reader")
+ return nil
+}
+
+// traceReader returns the trace reader that should be woken up, if any.
+func traceReader() *g {
+ if trace.reader == nil || (trace.fullHead == nil && !trace.shutdown) {
+ return nil
+ }
+ lock(&trace.lock)
+ if trace.reader == nil || (trace.fullHead == nil && !trace.shutdown) {
+ unlock(&trace.lock)
+ return nil
+ }
+ gp := trace.reader
+ trace.reader = nil
+ unlock(&trace.lock)
+ return gp
+}
+
+// traceProcFree frees trace buffer associated with pp.
+func traceProcFree(pp *p) {
+ buf := pp.tracebuf
+ pp.tracebuf = nil
+ if buf == nil {
+ return
+ }
+ lock(&trace.lock)
+ traceFullQueue(buf)
+ unlock(&trace.lock)
+}
+
+// traceFullQueue queues buf into queue of full buffers.
+func traceFullQueue(buf *traceBuf) {
+ buf.link = nil
+ if trace.fullHead == nil {
+ trace.fullHead = buf
+ } else {
+ trace.fullTail.link = buf
+ }
+ trace.fullTail = buf
+}
+
+// traceFullDequeue dequeues from queue of full buffers.
+func traceFullDequeue() *traceBuf {
+ buf := trace.fullHead
+ if buf == nil {
+ return nil
+ }
+ trace.fullHead = buf.link
+ if trace.fullHead == nil {
+ trace.fullTail = nil
+ }
+ buf.link = nil
+ return buf
+}
+
+// traceEvent writes a single event to trace buffer, flushing the buffer if necessary.
+// ev is event type.
+// If stack, write current stack id as the last argument.
+func traceEvent(ev byte, stack bool, args ...uint64) {
+ mp, pid, bufp := traceAcquireBuffer()
+ // Double-check trace.enabled now that we've done m.locks++ and acquired bufLock.
+ // This protects from races between traceEvent and StartTrace/StopTrace.
+
+ // The caller checked that trace.enabled == true, but trace.enabled might have been
+ // turned off between the check and now. Check again. traceLockBuffer did mp.locks++,
+ // StopTrace does stoptheworld, and stoptheworld waits for mp.locks to go back to zero,
+ // so if we see trace.enabled == true now, we know it's true for the rest of the function.
+ // Exitsyscall can run even during stoptheworld. The race with StartTrace/StopTrace
+ // during tracing in exitsyscall is resolved by locking trace.bufLock in traceLockBuffer.
+ if !trace.enabled {
+ traceReleaseBuffer(pid)
+ return
+ }
+ buf := *bufp
+ const maxSize = 2 + 4*traceBytesPerNumber // event type, length, timestamp, stack id and two add params
+ if buf == nil || cap(buf.buf)-len(buf.buf) < maxSize {
+ buf = traceFlush(buf)
+ *bufp = buf
+ }
+
+ ticks := uint64(cputicks()) / traceTickDiv
+ tickDiff := ticks - buf.lastTicks
+ if len(buf.buf) == 0 {
+ data := buf.buf
+ data = append(data, traceEvBatch|1<<traceArgCountShift)
+ data = traceAppend(data, uint64(pid))
+ data = traceAppend(data, ticks)
+ buf.buf = data
+ tickDiff = 0
+ }
+ buf.lastTicks = ticks
+ narg := byte(len(args))
+ if stack {
+ narg++
+ }
+ // We have only 2 bits for number of arguments.
+ // If number is >= 3, then the event type is followed by event length in bytes.
+ if narg > 3 {
+ narg = 3
+ }
+ data := buf.buf
+ data = append(data, ev|narg<<traceArgCountShift)
+ var lenp *byte
+ if narg == 3 {
+ // Reserve the byte for length assuming that length < 128.
+ data = append(data, 0)
+ lenp = &data[len(data)-1]
+ }
+ data = traceAppend(data, tickDiff)
+ for _, a := range args {
+ data = traceAppend(data, a)
+ }
+ if stack {
+ _g_ := getg()
+ gp := mp.curg
+ if gp == nil && ev == traceEvGoSysBlock {
+ gp = _g_
+ }
+ var nstk int
+ if gp == _g_ {
+ nstk = callers(1, &buf.stk[0], len(buf.stk))
+ } else if gp != nil {
+ nstk = gcallers(mp.curg, 1, &buf.stk[0], len(buf.stk))
+ }
+ id := trace.stackTab.put(buf.stk[:nstk])
+ data = traceAppend(data, uint64(id))
+ }
+ evSize := len(data) - len(buf.buf)
+ if evSize > maxSize {
+ throw("invalid length of trace event")
+ }
+ if lenp != nil {
+ // Fill in actual length.
+ *lenp = byte(evSize - 2)
+ }
+ buf.buf = data
+ traceReleaseBuffer(pid)
+}
+
+// traceAcquireBuffer returns trace buffer to use and, if necessary, locks it.
+func traceAcquireBuffer() (mp *m, pid int32, bufp **traceBuf) {
+ mp = acquirem()
+ if p := mp.p; p != nil {
+ return mp, p.id, &p.tracebuf
+ }
+ lock(&trace.bufLock)
+ return mp, traceGlobProc, &trace.buf
+}
+
+// traceReleaseBuffer releases a buffer previously acquired with traceAcquireBuffer.
+func traceReleaseBuffer(pid int32) {
+ if pid == traceGlobProc {
+ unlock(&trace.bufLock)
+ }
+ releasem(getg().m)
+}
+
+// traceFlush puts buf onto stack of full buffers and returns an empty buffer.
+func traceFlush(buf *traceBuf) *traceBuf {
+ owner := trace.lockOwner
+ dolock := owner == nil || owner != getg().m.curg
+ if dolock {
+ lock(&trace.lock)
+ }
+ if buf != nil {
+ if &buf.buf[0] != &buf.arr[0] {
+ throw("trace buffer overflow")
+ }
+ traceFullQueue(buf)
+ }
+ if trace.empty != nil {
+ buf = trace.empty
+ trace.empty = buf.link
+ } else {
+ buf = (*traceBuf)(sysAlloc(unsafe.Sizeof(traceBuf{}), &memstats.other_sys))
+ if buf == nil {
+ throw("trace: out of memory")
+ }
+ }
+ buf.link = nil
+ buf.buf = buf.arr[:0]
+ buf.lastTicks = 0
+ if dolock {
+ unlock(&trace.lock)
+ }
+ return buf
+}
+
+// traceAppend appends v to buf in little-endian-base-128 encoding.
+func traceAppend(buf []byte, v uint64) []byte {
+ for ; v >= 0x80; v >>= 7 {
+ buf = append(buf, 0x80|byte(v))
+ }
+ buf = append(buf, byte(v))
+ return buf
+}
+
+// traceStackTable maps stack traces (arrays of PC's) to unique uint32 ids.
+// It is lock-free for reading.
+type traceStackTable struct {
+ lock mutex
+ seq uint32
+ mem traceAlloc
+ tab [1 << 13]*traceStack
+}
+
+// traceStack is a single stack in traceStackTable.
+type traceStack struct {
+ link *traceStack
+ hash uintptr
+ id uint32
+ n int
+ stk [0]uintptr // real type [n]uintptr
+}
+
+// stack returns slice of PCs.
+func (ts *traceStack) stack() []uintptr {
+ return (*[traceStackSize]uintptr)(unsafe.Pointer(&ts.stk))[:ts.n]
+}
+
+// put returns a unique id for the stack trace pcs and caches it in the table,
+// if it sees the trace for the first time.
+func (tab *traceStackTable) put(pcs []uintptr) uint32 {
+ if len(pcs) == 0 {
+ return 0
+ }
+ hash := memhash(unsafe.Pointer(&pcs[0]), uintptr(len(pcs))*unsafe.Sizeof(pcs[0]), 0)
+ // First, search the hashtable w/o the mutex.
+ if id := tab.find(pcs, hash); id != 0 {
+ return id
+ }
+ // Now, double check under the mutex.
+ lock(&tab.lock)
+ if id := tab.find(pcs, hash); id != 0 {
+ unlock(&tab.lock)
+ return id
+ }
+ // Create new record.
+ tab.seq++
+ stk := tab.newStack(len(pcs))
+ stk.hash = hash
+ stk.id = tab.seq
+ stk.n = len(pcs)
+ stkpc := stk.stack()
+ for i, pc := range pcs {
+ stkpc[i] = pc
+ }
+ part := int(hash % uintptr(len(tab.tab)))
+ stk.link = tab.tab[part]
+ atomicstorep(unsafe.Pointer(&tab.tab[part]), unsafe.Pointer(stk))
+ unlock(&tab.lock)
+ return stk.id
+}
+
+// find checks if the stack trace pcs is already present in the table.
+func (tab *traceStackTable) find(pcs []uintptr, hash uintptr) uint32 {
+ part := int(hash % uintptr(len(tab.tab)))
+Search:
+ for stk := tab.tab[part]; stk != nil; stk = stk.link {
+ if stk.hash == hash && stk.n == len(pcs) {
+ for i, stkpc := range stk.stack() {
+ if stkpc != pcs[i] {
+ continue Search
+ }
+ }
+ return stk.id
+ }
+ }
+ return 0
+}
+
+// newStack allocates a new stack of size n.
+func (tab *traceStackTable) newStack(n int) *traceStack {
+ return (*traceStack)(tab.mem.alloc(unsafe.Sizeof(traceStack{}) + uintptr(n)*ptrSize))
+}
+
+// dump writes all previously cached stacks to trace buffers,
+// releases all memory and resets state.
+func (tab *traceStackTable) dump() {
+ var tmp [(2 + traceStackSize) * traceBytesPerNumber]byte
+ buf := traceFlush(nil)
+ for _, stk := range tab.tab {
+ for ; stk != nil; stk = stk.link {
+ maxSize := 1 + (3+stk.n)*traceBytesPerNumber
+ if cap(buf.buf)-len(buf.buf) < maxSize {
+ buf = traceFlush(buf)
+ }
+ // Form the event in the temp buffer, we need to know the actual length.
+ tmpbuf := tmp[:0]
+ tmpbuf = traceAppend(tmpbuf, uint64(stk.id))
+ tmpbuf = traceAppend(tmpbuf, uint64(stk.n))
+ for _, pc := range stk.stack() {
+ tmpbuf = traceAppend(tmpbuf, uint64(pc))
+ }
+ // Now copy to the buffer.
+ data := buf.buf
+ data = append(data, traceEvStack|3<<traceArgCountShift)
+ data = traceAppend(data, uint64(len(tmpbuf)))
+ data = append(data, tmpbuf...)
+ buf.buf = data
+ }
+ }
+
+ lock(&trace.lock)
+ traceFullQueue(buf)
+ unlock(&trace.lock)
+
+ tab.mem.drop()
+ *tab = traceStackTable{}
+}
+
+// traceAlloc is a non-thread-safe region allocator.
+// It holds a linked list of traceAllocBlock.
+type traceAlloc struct {
+ head *traceAllocBlock
+ off uintptr
+}
+
+// traceAllocBlock is a block in traceAlloc.
+type traceAllocBlock struct {
+ next *traceAllocBlock
+ data [64<<10 - ptrSize]byte
+}
+
+// alloc allocates n-byte block.
+func (a *traceAlloc) alloc(n uintptr) unsafe.Pointer {
+ n = round(n, ptrSize)
+ if a.head == nil || a.off+n > uintptr(len(a.head.data)) {
+ if n > uintptr(len(a.head.data)) {
+ throw("trace: alloc too large")
+ }
+ block := (*traceAllocBlock)(sysAlloc(unsafe.Sizeof(traceAllocBlock{}), &memstats.other_sys))
+ if block == nil {
+ throw("trace: out of memory")
+ }
+ block.next = a.head
+ a.head = block
+ a.off = 0
+ }
+ p := &a.head.data[a.off]
+ a.off += n
+ return unsafe.Pointer(p)
+}
+
+// drop frees all previously allocated memory and resets the allocator.
+func (a *traceAlloc) drop() {
+ for a.head != nil {
+ block := a.head
+ a.head = block.next
+ sysFree(unsafe.Pointer(block), unsafe.Sizeof(traceAllocBlock{}), &memstats.other_sys)
+ }
+}
+
+// The following functions write specific events to trace.
+
+func traceGomaxprocs(procs int32) {
+ traceEvent(traceEvGomaxprocs, true, uint64(procs))
+}
+
+func traceProcStart() {
+ traceEvent(traceEvProcStart, false)
+}
+
+func traceProcStop(pp *p) {
+ // Sysmon and stoptheworld can stop Ps blocked in syscalls,
+ // to handle this we temporary employ the P.
+ mp := acquirem()
+ oldp := mp.p
+ mp.p = pp
+ traceEvent(traceEvProcStop, false)
+ mp.p = oldp
+ releasem(mp)
+}
+
+func traceGCStart() {
+ traceEvent(traceEvGCStart, true)
+}
+
+func traceGCDone() {
+ traceEvent(traceEvGCDone, false)
+}
+
+func traceGCScanStart() {
+ traceEvent(traceEvGCScanStart, false)
+}
+
+func traceGCScanDone() {
+ traceEvent(traceEvGCScanDone, false)
+}
+
+func traceGCSweepStart() {
+ traceEvent(traceEvGCSweepStart, true)
+}
+
+func traceGCSweepDone() {
+ traceEvent(traceEvGCSweepDone, false)
+}
+
+func traceGoCreate(newg *g, pc uintptr) {
+ traceEvent(traceEvGoCreate, true, uint64(newg.goid), uint64(pc))
+}
+
+func traceGoStart() {
+ traceEvent(traceEvGoStart, false, uint64(getg().m.curg.goid))
+}
+
+func traceGoEnd() {
+ traceEvent(traceEvGoEnd, false)
+}
+
+func traceGoSched() {
+ traceEvent(traceEvGoSched, true)
+}
+
+func traceGoPreempt() {
+ traceEvent(traceEvGoPreempt, true)
+}
+
+func traceGoStop() {
+ traceEvent(traceEvGoStop, true)
+}
+
+func traceGoPark(traceEv byte, gp *g) {
+ traceEvent(traceEv, true)
+}
+
+func traceGoUnpark(gp *g) {
+ traceEvent(traceEvGoUnblock, true, uint64(gp.goid))
+}
+
+func traceGoSysCall() {
+ traceEvent(traceEvGoSysCall, true)
+}
+
+func traceGoSysExit() {
+ traceEvent(traceEvGoSysExit, false, uint64(getg().m.curg.goid))
+}
+
+func traceGoSysBlock(pp *p) {
+ // Sysmon and stoptheworld can declare syscalls running on remote Ps as blocked,
+ // to handle this we temporary employ the P.
+ mp := acquirem()
+ oldp := mp.p
+ mp.p = pp
+ traceEvent(traceEvGoSysBlock, true)
+ mp.p = oldp
+ releasem(mp)
+}
+
+func traceHeapAlloc() {
+ traceEvent(traceEvHeapAlloc, false, memstats.heap_alloc)
+}
+
+func traceNextGC() {
+ traceEvent(traceEvNextGC, false, memstats.next_gc)
+}
frame.varp -= regSize
}
+ // If framepointer_enabled and there's a frame, then
+ // there's a saved bp here.
+ if framepointer_enabled && GOARCH == "amd64" && frame.varp > frame.sp {
+ frame.varp -= regSize
+ }
+
// Derive size of arguments.
// Most functions have a fixed-size argument block,
// so we can use metadata about the function f.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Runtime _type representation.
+// Runtime type representation.
package runtime
fieldalign uint8
kind uint8
alg *typeAlg
- // gc stores _type info required for garbage collector.
+ // gc stores type info required for garbage collector.
// If (kind&KindGCProg)==0, then gc[0] points at sparse GC bitmap
// (no indirection), 4 bits per word.
// If (kind&KindGCProg)!=0, then gc[1] points to a compiler-generated
// read-only GC program; and gc[0] points to BSS space for sparse GC bitmap.
- // For huge _types (>maxGCMask), runtime unrolls the program directly into
- // GC bitmap and gc[0] is not used. For moderately-sized _types, runtime
+ // For huge types (>maxGCMask), runtime unrolls the program directly into
+ // GC bitmap and gc[0] is not used. For moderately-sized types, runtime
// unrolls the program into gc[0] space on first use. The first byte of gc[0]
// (gc[0][0]) contains 'unroll' flag saying whether the program is already
// unrolled into gc[0] or not.
_string *string
x *uncommontype
ptrto *_type
- zero *byte // ptr to the zero value for this _type
+ zero *byte // ptr to the zero value for this type
}
type method struct {
typ _type
key *_type
elem *_type
- bucket *_type // internal _type representing a hash bucket
- hmap *_type // internal _type representing a hmap
+ bucket *_type // internal type representing a hash bucket
+ hmap *_type // internal type representing a hmap
keysize uint8 // size of key slot
indirectkey bool // store ptr to key instead of key itself
valuesize uint8 // size of value slot
}
// Count counts the number of non-overlapping instances of sep in s.
+// If sep is an empty string, Count returns 1 + the number of Unicode code points in s.
func Count(s, sep string) int {
n := 0
// special cases
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// TODO(rsc): Rewrite all nn(SP) references into name+(nn-8)(FP)
-// so that go vet can check that they are correct.
-
#include "textflag.h"
#include "funcdata.h"
TEXT ·Syscall(SB),NOSPLIT,$0-28
CALL runtime·entersyscall(SB)
- MOVL 4(SP), AX // syscall entry
- MOVL 8(SP), BX
- MOVL 12(SP), CX
- MOVL 16(SP), DX
+ MOVL trap+0(FP), AX // syscall entry
+ MOVL a1+4(FP), BX
+ MOVL a2+8(FP), CX
+ MOVL a3+12(FP), DX
MOVL $0, SI
MOVL $0, DI
CALL *runtime·_vdso(SB)
CMPL AX, $0xfffff001
JLS ok
- MOVL $-1, 20(SP) // r1
- MOVL $0, 24(SP) // r2
+ MOVL $-1, r1+16(FP)
+ MOVL $0, r2+20(FP)
NEGL AX
- MOVL AX, 28(SP) // errno
+ MOVL AX, err+24(FP)
CALL runtime·exitsyscall(SB)
RET
ok:
- MOVL AX, 20(SP) // r1
- MOVL DX, 24(SP) // r2
- MOVL $0, 28(SP) // errno
+ MOVL AX, r1+16(FP)
+ MOVL DX, r2+20(FP)
+ MOVL $0, err+24(FP)
CALL runtime·exitsyscall(SB)
RET
// func Syscall6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr);
TEXT ·Syscall6(SB),NOSPLIT,$0-40
CALL runtime·entersyscall(SB)
- MOVL 4(SP), AX // syscall entry
- MOVL 8(SP), BX
- MOVL 12(SP), CX
- MOVL 16(SP), DX
- MOVL 20(SP), SI
- MOVL 24(SP), DI
- MOVL 28(SP), BP
+ MOVL trap+0(FP), AX // syscall entry
+ MOVL a1+4(FP), BX
+ MOVL a2+8(FP), CX
+ MOVL a3+12(FP), DX
+ MOVL a4+16(FP), SI
+ MOVL a5+20(FP), DI
+ MOVL a6+24(FP), BP
CALL *runtime·_vdso(SB)
CMPL AX, $0xfffff001
JLS ok6
- MOVL $-1, 32(SP) // r1
- MOVL $0, 36(SP) // r2
+ MOVL $-1, r1+28(FP)
+ MOVL $0, r2+32(FP)
NEGL AX
- MOVL AX, 40(SP) // errno
+ MOVL AX, err+36(FP)
CALL runtime·exitsyscall(SB)
RET
ok6:
- MOVL AX, 32(SP) // r1
- MOVL DX, 36(SP) // r2
- MOVL $0, 40(SP) // errno
+ MOVL AX, r1+28(FP)
+ MOVL DX, r2+32(FP)
+ MOVL $0, err+36(FP)
CALL runtime·exitsyscall(SB)
RET
// func RawSyscall(trap uintptr, a1, a2, a3 uintptr) (r1, r2, err uintptr);
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
- MOVL 4(SP), AX // syscall entry
- MOVL 8(SP), BX
- MOVL 12(SP), CX
- MOVL 16(SP), DX
+ MOVL trap+0(FP), AX // syscall entry
+ MOVL a1+4(FP), BX
+ MOVL a2+8(FP), CX
+ MOVL a3+12(FP), DX
MOVL $0, SI
MOVL $0, DI
CALL *runtime·_vdso(SB)
CMPL AX, $0xfffff001
JLS ok1
- MOVL $-1, 20(SP) // r1
- MOVL $0, 24(SP) // r2
+ MOVL $-1, r1+16(FP)
+ MOVL $0, r2+20(FP)
NEGL AX
- MOVL AX, 28(SP) // errno
+ MOVL AX, err+24(FP)
RET
ok1:
- MOVL AX, 20(SP) // r1
- MOVL DX, 24(SP) // r2
- MOVL $0, 28(SP) // errno
+ MOVL AX, r1+16(FP)
+ MOVL DX, r2+20(FP)
+ MOVL $0, err+24(FP)
RET
// func RawSyscall6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr);
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
- MOVL 4(SP), AX // syscall entry
- MOVL 8(SP), BX
- MOVL 12(SP), CX
- MOVL 16(SP), DX
- MOVL 20(SP), SI
- MOVL 24(SP), DI
- MOVL 28(SP), BP
+ MOVL trap+0(FP), AX // syscall entry
+ MOVL a1+4(FP), BX
+ MOVL a2+8(FP), CX
+ MOVL a3+12(FP), DX
+ MOVL a4+16(FP), SI
+ MOVL a5+20(FP), DI
+ MOVL a6+24(FP), BP
CALL *runtime·_vdso(SB)
CMPL AX, $0xfffff001
JLS ok2
- MOVL $-1, 32(SP) // r1
- MOVL $0, 36(SP) // r2
+ MOVL $-1, r1+28(FP)
+ MOVL $0, r2+32(FP)
NEGL AX
- MOVL AX, 40(SP) // errno
+ MOVL AX, err+36(FP)
RET
ok2:
- MOVL AX, 32(SP) // r1
- MOVL DX, 36(SP) // r2
- MOVL $0, 40(SP) // errno
+ MOVL AX, r1+28(FP)
+ MOVL DX, r2+32(FP)
+ MOVL $0, err+36(FP)
RET
#define SYS_SOCKETCALL 102 /* from zsysnum_linux_386.go */
-// func socketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, errno int)
+// func socketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, err int)
// Kernel interface gets call sub-number and pointer to a0.
TEXT ·socketcall(SB),NOSPLIT,$0-36
CALL runtime·entersyscall(SB)
MOVL $SYS_SOCKETCALL, AX // syscall entry
- MOVL 4(SP), BX // socket call number
- LEAL 8(SP), CX // pointer to call arguments
+ MOVL call+0(FP), BX // socket call number
+ LEAL a0+4(FP), CX // pointer to call arguments
MOVL $0, DX
MOVL $0, SI
MOVL $0, DI
CALL *runtime·_vdso(SB)
CMPL AX, $0xfffff001
JLS oksock
- MOVL $-1, 32(SP) // n
+ MOVL $-1, n+28(FP)
NEGL AX
- MOVL AX, 36(SP) // errno
+ MOVL AX, err+32(FP)
CALL runtime·exitsyscall(SB)
RET
oksock:
- MOVL AX, 32(SP) // n
- MOVL $0, 36(SP) // errno
+ MOVL AX, n+28(FP)
+ MOVL $0, err+32(FP)
CALL runtime·exitsyscall(SB)
RET
-// func rawsocketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, errno int)
+// func rawsocketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, err int)
// Kernel interface gets call sub-number and pointer to a0.
TEXT ·rawsocketcall(SB),NOSPLIT,$0-36
MOVL $SYS_SOCKETCALL, AX // syscall entry
- MOVL 4(SP), BX // socket call number
- LEAL 8(SP), CX // pointer to call arguments
+ MOVL call+0(FP), BX // socket call number
+ LEAL a0+4(FP), CX // pointer to call arguments
MOVL $0, DX
MOVL $0, SI
MOVL $0, DI
CALL *runtime·_vdso(SB)
CMPL AX, $0xfffff001
JLS oksock1
- MOVL $-1, 32(SP) // n
+ MOVL $-1, n+28(FP)
NEGL AX
- MOVL AX, 36(SP) // errno
+ MOVL AX, err+32(FP)
RET
oksock1:
- MOVL AX, 32(SP) // n
- MOVL $0, 36(SP) // errno
+ MOVL AX, n+28(FP)
+ MOVL $0, err+32(FP)
RET
#define SYS__LLSEEK 140 /* from zsysnum_linux_386.go */
-// func Seek(fd int, offset int64, whence int) (newoffset int64, errno int)
+// func Seek(fd int, offset int64, whence int) (newoffset int64, err int)
// Implemented in assembly to avoid allocation when
// taking the address of the return value newoffset.
// Underlying system call is
TEXT ·seek(SB),NOSPLIT,$0-28
CALL runtime·entersyscall(SB)
MOVL $SYS__LLSEEK, AX // syscall entry
- MOVL 4(SP), BX // fd
- MOVL 12(SP), CX // offset-high
- MOVL 8(SP), DX // offset-low
- LEAL 20(SP), SI // result pointer
- MOVL 16(SP), DI // whence
+ MOVL fd+0(FP), BX
+ MOVL offset_hi+8(FP), CX
+ MOVL offset_lo+4(FP), DX
+ LEAL newoffset_lo+16(FP), SI // result pointer
+ MOVL whence+12(FP), DI
CALL *runtime·_vdso(SB)
CMPL AX, $0xfffff001
JLS okseek
- MOVL $-1, 20(SP) // newoffset low
- MOVL $-1, 24(SP) // newoffset high
+ MOVL $-1, newoffset_lo+16(FP)
+ MOVL $-1, newoffset_hi+20(FP)
NEGL AX
- MOVL AX, 28(SP) // errno
+ MOVL AX, err+24(FP)
CALL runtime·exitsyscall(SB)
RET
okseek:
// system call filled in newoffset already
- MOVL $0, 28(SP) // errno
+ MOVL $0, err+24(FP)
CALL runtime·exitsyscall(SB)
RET
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// TODO(rsc): Rewrite all nn(SP) references into name+(nn-8)(FP)
-// so that go vet can check that they are correct.
-
#include "textflag.h"
#include "funcdata.h"
TEXT ·Syscall(SB),NOSPLIT,$0-56
CALL runtime·entersyscall(SB)
- MOVQ 16(SP), DI
- MOVQ 24(SP), SI
- MOVQ 32(SP), DX
+ MOVQ a1+8(FP), DI
+ MOVQ a2+16(FP), SI
+ MOVQ a3+24(FP), DX
MOVQ $0, R10
MOVQ $0, R8
MOVQ $0, R9
- MOVQ 8(SP), AX // syscall entry
+ MOVQ trap+0(FP), AX // syscall entry
SYSCALL
CMPQ AX, $0xfffffffffffff001
JLS ok
- MOVQ $-1, 40(SP) // r1
- MOVQ $0, 48(SP) // r2
+ MOVQ $-1, r1+32(FP)
+ MOVQ $0, r2+40(FP)
NEGQ AX
- MOVQ AX, 56(SP) // errno
+ MOVQ AX, err+48(FP)
CALL runtime·exitsyscall(SB)
RET
ok:
- MOVQ AX, 40(SP) // r1
- MOVQ DX, 48(SP) // r2
- MOVQ $0, 56(SP) // errno
+ MOVQ AX, r1+32(FP)
+ MOVQ DX, r2+40(FP)
+ MOVQ $0, err+48(FP)
CALL runtime·exitsyscall(SB)
RET
+// func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
TEXT ·Syscall6(SB),NOSPLIT,$0-80
CALL runtime·entersyscall(SB)
- MOVQ 16(SP), DI
- MOVQ 24(SP), SI
- MOVQ 32(SP), DX
- MOVQ 40(SP), R10
- MOVQ 48(SP), R8
- MOVQ 56(SP), R9
- MOVQ 8(SP), AX // syscall entry
+ MOVQ a1+8(FP), DI
+ MOVQ a2+16(FP), SI
+ MOVQ a3+24(FP), DX
+ MOVQ a4+32(FP), R10
+ MOVQ a5+40(FP), R8
+ MOVQ a6+48(FP), R9
+ MOVQ trap+0(FP), AX // syscall entry
SYSCALL
CMPQ AX, $0xfffffffffffff001
JLS ok6
- MOVQ $-1, 64(SP) // r1
- MOVQ $0, 72(SP) // r2
+ MOVQ $-1, r1+56(FP)
+ MOVQ $0, r2+64(FP)
NEGQ AX
- MOVQ AX, 80(SP) // errno
+ MOVQ AX, err+72(FP)
CALL runtime·exitsyscall(SB)
RET
ok6:
- MOVQ AX, 64(SP) // r1
- MOVQ DX, 72(SP) // r2
- MOVQ $0, 80(SP) // errno
+ MOVQ AX, r1+56(FP)
+ MOVQ DX, r2+64(FP)
+ MOVQ $0, err+72(FP)
CALL runtime·exitsyscall(SB)
RET
+// func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
- MOVQ 16(SP), DI
- MOVQ 24(SP), SI
- MOVQ 32(SP), DX
+ MOVQ a1+8(FP), DI
+ MOVQ a2+16(FP), SI
+ MOVQ a3+24(FP), DX
MOVQ $0, R10
MOVQ $0, R8
MOVQ $0, R9
- MOVQ 8(SP), AX // syscall entry
+ MOVQ trap+0(FP), AX // syscall entry
SYSCALL
CMPQ AX, $0xfffffffffffff001
JLS ok1
- MOVQ $-1, 40(SP) // r1
- MOVQ $0, 48(SP) // r2
+ MOVQ $-1, r1+32(FP)
+ MOVQ $0, r2+40(FP)
NEGQ AX
- MOVQ AX, 56(SP) // errno
+ MOVQ AX, err+48(FP)
RET
ok1:
- MOVQ AX, 40(SP) // r1
- MOVQ DX, 48(SP) // r2
- MOVQ $0, 56(SP) // errno
+ MOVQ AX, r1+32(FP)
+ MOVQ DX, r2+40(FP)
+ MOVQ $0, err+48(FP)
RET
+// func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
- MOVQ 16(SP), DI
- MOVQ 24(SP), SI
- MOVQ 32(SP), DX
- MOVQ 40(SP), R10
- MOVQ 48(SP), R8
- MOVQ 56(SP), R9
- MOVQ 8(SP), AX // syscall entry
+ MOVQ a1+8(FP), DI
+ MOVQ a2+16(FP), SI
+ MOVQ a3+24(FP), DX
+ MOVQ a4+32(FP), R10
+ MOVQ a5+40(FP), R8
+ MOVQ a6+48(FP), R9
+ MOVQ trap+0(FP), AX // syscall entry
SYSCALL
CMPQ AX, $0xfffffffffffff001
JLS ok2
- MOVQ $-1, 64(SP) // r1
- MOVQ $0, 72(SP) // r2
+ MOVQ $-1, r1+56(FP)
+ MOVQ $0, r2+64(FP)
NEGQ AX
- MOVQ AX, 80(SP) // errno
+ MOVQ AX, err+72(FP)
RET
ok2:
- MOVQ AX, 64(SP) // r1
- MOVQ DX, 72(SP) // r2
- MOVQ $0, 80(SP) // errno
+ MOVQ AX, r1+56(FP)
+ MOVQ DX, r2+64(FP)
+ MOVQ $0, err+72(FP)
RET
+// func gettimeofday(tv *Timeval) (err uintptr)
TEXT ·gettimeofday(SB),NOSPLIT,$0-16
- MOVQ 8(SP), DI
+ MOVQ tv+0(FP), DI
MOVQ $0, SI
MOVQ runtime·__vdso_gettimeofday_sym(SB), AX
CALL AX
CMPQ AX, $0xfffffffffffff001
JLS ok7
NEGQ AX
- MOVQ AX, 16(SP) // errno
+ MOVQ AX, err+8(FP)
RET
ok7:
- MOVQ $0, 16(SP) // errno
+ MOVQ $0, err+8(FP)
RET
}
v.Index(i).Set(elem)
}
+ case reflect.Array:
+ for i := 0; i < v.Len(); i++ {
+ elem, ok := Value(concrete.Elem(), rand)
+ if !ok {
+ return reflect.Value{}, false
+ }
+ v.Index(i).Set(elem)
+ }
case reflect.String:
numChars := rand.Intn(complexSize)
codePoints := make([]rune, numChars)
func fIntptrAlias(a TestIntptrAlias) TestIntptrAlias { return a }
+func fArray(a [4]byte) [4]byte { return a }
+
+type TestArrayAlias [4]byte
+
+func fArrayAlias(a TestArrayAlias) TestArrayAlias { return a }
+
func reportError(property string, err error, t *testing.T) {
if err != nil {
t.Errorf("%s: %s", property, err)
reportError("fUintptrAlias", CheckEqual(fUintptrAlias, fUintptrAlias, nil), t)
reportError("fIntptr", CheckEqual(fIntptr, fIntptr, nil), t)
reportError("fIntptrAlias", CheckEqual(fIntptrAlias, fIntptrAlias, nil), t)
+ reportError("fArray", CheckEqual(fArray, fArray, nil), t)
+ reportError("fArrayAlais", CheckEqual(fArrayAlias, fArrayAlias, nil), t)
}
// This tests that ArbitraryValue is working by checking that all the arbitrary
cpuProfile = flag.String("test.cpuprofile", "", "write a cpu profile to the named file during execution")
blockProfile = flag.String("test.blockprofile", "", "write a goroutine blocking profile to the named file after execution")
blockProfileRate = flag.Int("test.blockprofilerate", 1, "if >= 0, calls runtime.SetBlockProfileRate()")
+ trace = flag.String("test.trace", "", "write an execution trace to the named file after execution")
timeout = flag.Duration("test.timeout", 0, "if positive, sets an aggregate time limit for all tests")
cpuListStr = flag.String("test.cpu", "", "comma-separated list of number of CPUs to use for each test")
parallel = flag.Int("test.parallel", runtime.GOMAXPROCS(0), "maximum test parallelism")
}
// Could save f so after can call f.Close; not worth the effort.
}
+ if *trace != "" {
+ f, err := os.Create(toOutputDir(*trace))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "testing: %s", err)
+ return
+ }
+ if err := pprof.StartTrace(f); err != nil {
+ fmt.Fprintf(os.Stderr, "testing: can't start tracing: %s", err)
+ f.Close()
+ return
+ }
+ // Could save f so after can call f.Close; not worth the effort.
+ }
if *blockProfile != "" && *blockProfileRate >= 0 {
runtime.SetBlockProfileRate(*blockProfileRate)
}
if *cpuProfile != "" {
pprof.StopCPUProfile() // flushes profile to disk
}
+ if *trace != "" {
+ pprof.StopTrace() // flushes trace to disk
+ }
if *memProfile != "" {
f, err := os.Create(toOutputDir(*memProfile))
if err != nil {
// arbitrary memory. It should be used with extreme care.
type Pointer *ArbitraryType
-// Sizeof returns the size in bytes occupied by the value v. The size is that of the
-// "top level" of the value only. For instance, if v is a slice, it returns the size of
-// the slice descriptor, not the size of the memory referenced by the slice.
-func Sizeof(v ArbitraryType) uintptr
+// Sizeof takes an expression x of any type and returns the size in bytes
+// of a hypothetical variable v as if v was declared via var v = x.
+// The size does not include any memory possibly referenced by x.
+// For instance, if x is a slice, Sizeof returns the size of the slice
+// descriptor, not the size of the memory referenced by the slice.
+func Sizeof(x ArbitraryType) uintptr
-// Offsetof returns the offset within the struct of the field represented by v,
+// Offsetof returns the offset within the struct of the field represented by x,
// which must be of the form structValue.field. In other words, it returns the
// number of bytes between the start of the struct and the start of the field.
-func Offsetof(v ArbitraryType) uintptr
+func Offsetof(x ArbitraryType) uintptr
-// Alignof returns the alignment of the value v. It is the maximum value m such
-// that the address of a variable with the type of v will always be zero mod m.
-// If v is of the form structValue.field, it returns the alignment of field f within struct object obj.
-func Alignof(v ArbitraryType) uintptr
+// Alignof takes an expression x of any type and returns the alignment
+// of a hypothetical variable v as if v was declared via var v = x.
+// It is the largest value m such that the address of v is zero mod m.
+func Alignof(x ArbitraryType) uintptr
--- /dev/null
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ x := 0
+ func() {
+ x = 1
+ }()
+ func() {
+ if x != 1 {
+ panic("x != 1")
+ }
+ }()
+}
\ No newline at end of file
--- /dev/null
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check that these do not use "by value" capturing,
+// because changes are made to the value during the closure.
+
+package main
+
+func main() {
+ {
+ type X struct {
+ v int
+ }
+ var x X
+ func() {
+ x.v++
+ }()
+ if x.v != 1 {
+ panic("x.v != 1")
+ }
+
+ type Y struct {
+ X
+ }
+ var y Y
+ func() {
+ y.v = 1
+ }()
+ if y.v != 1 {
+ panic("y.v != 1")
+ }
+ }
+
+ {
+ type Z struct {
+ a [3]byte
+ }
+ var z Z
+ func() {
+ i := 0
+ for z.a[1] = 1; i < 10; i++ {
+ }
+ }()
+ if z.a[1] != 1 {
+ panic("z.a[1] != 1")
+ }
+ }
+
+ {
+ w := 0
+ tmp := 0
+ f := func() {
+ if w != 1 {
+ panic("w != 1")
+ }
+ }
+ func() {
+ tmp = w // force capture of w, but do not write to it yet
+ _ = tmp
+ func() {
+ func() {
+ w++ // write in a nested closure
+ }()
+ }()
+ }()
+ f()
+ }
+
+ {
+ var g func() int
+ for i := range [2]int{} {
+ if i == 0 {
+ g = func() int {
+ return i // test that we capture by ref here, i is mutated on every interation
+ }
+ }
+ }
+ if g() != 1 {
+ panic("g() != 1")
+ }
+ }
+
+ {
+ var g func() int
+ q := 0
+ for range [2]int{} {
+ q++
+ g = func() int {
+ return q // test that we capture by ref here
+ // q++ must on a different decldepth than q declaration
+ }
+ }
+ if g() != 2 {
+ panic("g() != 2")
+ }
+ }
+
+ {
+ var g func() int
+ var a [2]int
+ q := 0
+ for a[func() int {
+ q++
+ return 0
+ }()] = range [2]int{} {
+ g = func() int {
+ return q // test that we capture by ref here
+ // q++ must on a different decldepth than q declaration
+ }
+ }
+ if g() != 2 {
+ panic("g() != 2")
+ }
+ }
+}
}
func foo21() func() int {
+ x := 42
+ return func() int { // ERROR "func literal escapes to heap"
+ return x
+ }
+}
+
+func foo21a() func() int {
x := 42 // ERROR "moved to heap: x"
return func() int { // ERROR "func literal escapes to heap"
- return x // ERROR "&x escapes to heap"
+ x++ // ERROR "&x escapes to heap"
+ return x
}
}
}()
}
-func foo23(x int) func() int { // ERROR "moved to heap: x"
+func foo23(x int) func() int {
return func() int { // ERROR "func literal escapes to heap"
- return x // ERROR "&x escapes to heap"
+ return x
}
}
-func foo23a(x int) func() int { // ERROR "moved to heap: x"
+func foo23a(x int) func() int {
f := func() int { // ERROR "func literal escapes to heap"
- return x // ERROR "&x escapes to heap"
+ return x
}
return f
}
-func foo23b(x int) *(func() int) { // ERROR "moved to heap: x"
- f := func() int { return x } // ERROR "moved to heap: f" "func literal escapes to heap" "&x escapes to heap"
+func foo23b(x int) *(func() int) {
+ f := func() int { return x } // ERROR "moved to heap: f" "func literal escapes to heap"
return &f // ERROR "&f escapes to heap"
}
+func foo23c(x int) func() int { // ERROR "moved to heap: x"
+ return func() int { // ERROR "func literal escapes to heap"
+ x++ // ERROR "&x escapes to heap"
+ return x
+ }
+}
+
func foo24(x int) int {
return func() int { // ERROR "func literal does not escape"
return x
// issue 2145
func foo73() {
+ s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape"
+ for _, v := range s {
+ vv := v
+ // actually just escapes its scope
+ defer func() { // ERROR "func literal escapes to heap"
+ println(vv)
+ }()
+ }
+}
+
+func foo731() {
s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape"
for _, v := range s {
vv := v // ERROR "moved to heap: vv"
// actually just escapes its scope
defer func() { // ERROR "func literal escapes to heap"
- println(vv) // ERROR "&vv escapes to heap"
+ vv = 42 // ERROR "&vv escapes to heap"
+ println(vv)
}()
}
}
func foo74() {
+ s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape"
+ for _, v := range s {
+ vv := v
+ // actually just escapes its scope
+ fn := func() { // ERROR "func literal escapes to heap"
+ println(vv)
+ }
+ defer fn()
+ }
+}
+
+func foo74a() {
s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape"
for _, v := range s {
vv := v // ERROR "moved to heap: vv"
// actually just escapes its scope
fn := func() { // ERROR "func literal escapes to heap"
- println(vv) // ERROR "&vv escapes to heap"
+ vv += 1 // ERROR "&vv escapes to heap"
+ println(vv)
}
defer fn()
}
// issue 3975
func foo74b() {
+ var array [3]func()
+ s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape"
+ for i, v := range s {
+ vv := v
+ // actually just escapes its scope
+ array[i] = func() { // ERROR "func literal escapes to heap"
+ println(vv)
+ }
+ }
+}
+
+func foo74c() {
var array [3]func()
s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape"
for i, v := range s {
vv := v // ERROR "moved to heap: vv"
// actually just escapes its scope
array[i] = func() { // ERROR "func literal escapes to heap"
- println(vv) // ERROR "&vv escapes to heap"
+ println(&vv) // ERROR "&vv escapes to heap" "&vv does not escape"
}
}
}
func foo135() {
var i int // ERROR "moved to heap: i"
- p := &i // ERROR "&i escapes to heap" "moved to heap: p"
+ p := &i // ERROR "&i escapes to heap"
go func() { // ERROR "func literal escapes to heap"
- q := p // ERROR "&p escapes to heap"
+ q := p
func() { // ERROR "func literal does not escape"
r := q
_ = r
func foo136() {
var i int // ERROR "moved to heap: i"
- p := &i // ERROR "&i escapes to heap" "moved to heap: p"
+ p := &i // ERROR "&i escapes to heap"
go func() { // ERROR "func literal escapes to heap"
- q := p // ERROR "&p escapes to heap" "leaking closure reference p"
+ q := p // ERROR "leaking closure reference p"
func() { // ERROR "func literal does not escape"
r := q // ERROR "leaking closure reference q"
px = r
var i int // ERROR "moved to heap: i"
p := &i // ERROR "&i escapes to heap"
func() { // ERROR "func literal does not escape"
- q := p // ERROR "leaking closure reference p" "moved to heap: q"
+ q := p // ERROR "leaking closure reference p"
go func() { // ERROR "func literal escapes to heap"
- r := q // ERROR "&q escapes to heap"
+ r := q
_ = r
}()
}()
x = &x // ERROR "&x escapes to heap"
return
}
+
+var sink interface{}
+
+type Lit struct {
+ p *int
+}
+
+func ptrlitNoescape() {
+ // Both literal and element do not escape.
+ i := 0
+ x := &Lit{&i} // ERROR "&Lit literal does not escape" "&i does not escape"
+ _ = x
+}
+
+func ptrlitNoEscape2() {
+ // Literal does not escape, but element does.
+ i := 0 // ERROR "moved to heap: i"
+ x := &Lit{&i} // ERROR "&Lit literal does not escape" "&i escapes to heap"
+ sink = *x
+}
+
+func ptrlitEscape() {
+ // Both literal and element escape.
+ i := 0 // ERROR "moved to heap: i"
+ x := &Lit{&i} // ERROR "&Lit literal escapes to heap" "&i escapes to heap"
+ sink = x
+}
+
+// self-assignments
+
+type Buffer struct {
+ arr [64]byte
+ buf1 []byte
+ buf2 []byte
+ str1 string
+ str2 string
+}
+
+func (b *Buffer) foo() { // ERROR "b does not escape"
+ b.buf1 = b.buf1[1:2] // ERROR "ignoring self-assignment to b.buf1"
+ b.buf1 = b.buf1[1:2:3] // ERROR "ignoring self-assignment to b.buf1"
+ b.buf1 = b.buf2[1:2] // ERROR "ignoring self-assignment to b.buf1"
+ b.buf1 = b.buf2[1:2:3] // ERROR "ignoring self-assignment to b.buf1"
+}
+
+func (b *Buffer) bar() { // ERROR "leaking param: b"
+ b.buf1 = b.arr[1:2] // ERROR "b.arr escapes to heap"
+}
+
+func (b *Buffer) baz() { // ERROR "b does not escape"
+ b.str1 = b.str1[1:2] // ERROR "ignoring self-assignment to b.str1"
+ b.str1 = b.str2[1:2] // ERROR "ignoring self-assignment to b.str1"
+}
+
+func (b *Buffer) bat() { // ERROR "leaking param: b"
+ o := new(Buffer) // ERROR "new\(Buffer\) escapes to heap"
+ o.buf1 = b.buf1[1:2]
+ sink = o
+}
+
+func quux(sp *string, bp *[]byte) { // ERROR "sp does not escape" "bp does not escape"
+ *sp = (*sp)[1:2] // ERROR "quux ignoring self-assignment to \*sp"
+ *bp = (*bp)[1:2] // ERROR "quux ignoring self-assignment to \*bp"
+}
+
+type StructWithString struct {
+ p *int
+ s string
+}
+
+// This is escape analysis false negative.
+// We assign the pointer to x.p but leak x.s. Escape analysis coarsens flows
+// to just x, and thus &i looks escaping.
+func fieldFlowTracking() {
+ var x StructWithString
+ i := 0 // ERROR "moved to heap: i"
+ x.p = &i // ERROR "&i escapes to heap"
+ sink = x.s
+}
+
+// String operations.
+
+func slicebytetostring0() {
+ b := make([]byte, 20) // ERROR "does not escape"
+ s := string(b) // ERROR "string\(b\) does not escape"
+ _ = s
+}
+
+func slicebytetostring1() {
+ b := make([]byte, 20) // ERROR "does not escape"
+ s := string(b) // ERROR "string\(b\) does not escape"
+ s1 := s[0:1]
+ _ = s1
+}
+
+func slicebytetostring2() {
+ b := make([]byte, 20) // ERROR "does not escape"
+ s := string(b) // ERROR "string\(b\) escapes to heap"
+ s1 := s[0:1] // ERROR "moved to heap: s1"
+ sink = &s1 // ERROR "&s1 escapes to heap"
+}
+
+func slicebytetostring3() {
+ b := make([]byte, 20) // ERROR "does not escape"
+ s := string(b) // ERROR "string\(b\) escapes to heap"
+ s1 := s[0:1]
+ sink = s1
+}
+
+func addstr0() {
+ s0 := "a"
+ s1 := "b"
+ s := s0 + s1 // ERROR "s0 \+ s1 does not escape"
+ _ = s
+}
+
+func addstr1() {
+ s0 := "a"
+ s1 := "b"
+ s := "c"
+ s += s0 + s1 // ERROR "s0 \+ s1 does not escape"
+ _ = s
+}
+
+func addstr2() {
+ b := make([]byte, 20) // ERROR "does not escape"
+ s0 := "a"
+ s := string(b) + s0 // ERROR "string\(b\) does not escape" "string\(b\) \+ s0 does not escape"
+ _ = s
+}
+
+func addstr3() {
+ s0 := "a"
+ s1 := "b"
+ s := s0 + s1 // ERROR "s0 \+ s1 escapes to heap"
+ s2 := s[0:1]
+ sink = s2
+}
+
+func intstring0() bool {
+ // string does not escape
+ x := '0'
+ s := string(x) // ERROR "string\(x\) does not escape"
+ return s == "0"
+}
+
+func intstring1() string {
+ // string does not escape, but the buffer does
+ x := '0'
+ s := string(x) // ERROR "string\(x\) escapes to heap"
+ return s
+}
+
+func intstring2() {
+ // string escapes to heap
+ x := '0'
+ s := string(x) // ERROR "string\(x\) escapes to heap" "moved to heap: s"
+ sink = &s // ERROR "&s escapes to heap"
+}
}
func foo21() func() int {
+ x := 42
+ return func() int { // ERROR "func literal escapes to heap"
+ return x
+ }
+}
+
+func foo21a() func() int {
x := 42 // ERROR "moved to heap: x"
return func() int { // ERROR "func literal escapes to heap"
- return x // ERROR "&x escapes to heap"
+ x++ // ERROR "&x escapes to heap"
+ return x
}
}
}()
}
-func foo23(x int) func() int { // ERROR "moved to heap: x"
+func foo23(x int) func() int {
return func() int { // ERROR "func literal escapes to heap"
- return x // ERROR "&x escapes to heap"
+ return x
}
}
-func foo23a(x int) func() int { // ERROR "moved to heap: x"
+func foo23a(x int) func() int {
f := func() int { // ERROR "func literal escapes to heap"
- return x // ERROR "&x escapes to heap"
+ return x
}
return f
}
-func foo23b(x int) *(func() int) { // ERROR "moved to heap: x"
- f := func() int { return x } // ERROR "moved to heap: f" "func literal escapes to heap" "&x escapes to heap"
+func foo23b(x int) *(func() int) {
+ f := func() int { return x } // ERROR "moved to heap: f" "func literal escapes to heap"
return &f // ERROR "&f escapes to heap"
}
+func foo23c(x int) func() int { // ERROR "moved to heap: x"
+ return func() int { // ERROR "func literal escapes to heap"
+ x++ // ERROR "&x escapes to heap"
+ return x
+ }
+}
+
func foo24(x int) int {
return func() int { // ERROR "func literal does not escape"
return x
// issue 2145
func foo73() {
+ s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape"
+ for _, v := range s {
+ vv := v
+ // actually just escapes its scope
+ defer func() { // ERROR "func literal escapes to heap"
+ println(vv)
+ }()
+ }
+}
+
+func foo731() {
s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape"
for _, v := range s {
vv := v // ERROR "moved to heap: vv"
// actually just escapes its scope
defer func() { // ERROR "func literal escapes to heap"
- println(vv) // ERROR "&vv escapes to heap"
+ vv = 42 // ERROR "&vv escapes to heap"
+ println(vv)
}()
}
}
func foo74() {
+ s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape"
+ for _, v := range s {
+ vv := v
+ // actually just escapes its scope
+ fn := func() { // ERROR "func literal escapes to heap"
+ println(vv)
+ }
+ defer fn()
+ }
+}
+
+func foo74a() {
s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape"
for _, v := range s {
vv := v // ERROR "moved to heap: vv"
// actually just escapes its scope
fn := func() { // ERROR "func literal escapes to heap"
- println(vv) // ERROR "&vv escapes to heap"
+ vv += 1 // ERROR "&vv escapes to heap"
+ println(vv)
}
defer fn()
}
// issue 3975
func foo74b() {
+ var array [3]func()
+ s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape"
+ for i, v := range s {
+ vv := v
+ // actually just escapes its scope
+ array[i] = func() { // ERROR "func literal escapes to heap"
+ println(vv)
+ }
+ }
+}
+
+func foo74c() {
var array [3]func()
s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape"
for i, v := range s {
vv := v // ERROR "moved to heap: vv"
// actually just escapes its scope
array[i] = func() { // ERROR "func literal escapes to heap"
- println(vv) // ERROR "&vv escapes to heap"
+ println(&vv) // ERROR "&vv escapes to heap" "&vv does not escape"
}
}
}
func foo135() {
var i int // ERROR "moved to heap: i"
- p := &i // ERROR "&i escapes to heap" "moved to heap: p"
+ p := &i // ERROR "&i escapes to heap"
go func() { // ERROR "func literal escapes to heap"
- q := p // ERROR "&p escapes to heap"
+ q := p
func() { // ERROR "func literal does not escape"
r := q
_ = r
func foo136() {
var i int // ERROR "moved to heap: i"
- p := &i // ERROR "&i escapes to heap" "moved to heap: p"
+ p := &i // ERROR "&i escapes to heap"
go func() { // ERROR "func literal escapes to heap"
- q := p // ERROR "&p escapes to heap" "leaking closure reference p"
+ q := p // ERROR "leaking closure reference p"
func() { // ERROR "func literal does not escape"
r := q // ERROR "leaking closure reference q"
px = r
var i int // ERROR "moved to heap: i"
p := &i // ERROR "&i escapes to heap"
func() { // ERROR "func literal does not escape"
- q := p // ERROR "leaking closure reference p" "moved to heap: q"
+ q := p // ERROR "leaking closure reference p"
go func() { // ERROR "func literal escapes to heap"
- r := q // ERROR "&q escapes to heap"
+ r := q
_ = r
}()
}()
x = &x // ERROR "&x escapes to heap"
return
}
+
+var sink interface{}
+
+type Lit struct {
+ p *int
+}
+
+func ptrlitNoescape() {
+ // Both literal and element do not escape.
+ i := 0
+ x := &Lit{&i} // ERROR "&Lit literal does not escape" "&i does not escape"
+ _ = x
+}
+
+func ptrlitNoEscape2() {
+ // Literal does not escape, but element does.
+ i := 0 // ERROR "moved to heap: i"
+ x := &Lit{&i} // ERROR "&Lit literal does not escape" "&i escapes to heap"
+ sink = *x
+}
+
+func ptrlitEscape() {
+ // Both literal and element escape.
+ i := 0 // ERROR "moved to heap: i"
+ x := &Lit{&i} // ERROR "&Lit literal escapes to heap" "&i escapes to heap"
+ sink = x
+}
+
+// self-assignments
+
+type Buffer struct {
+ arr [64]byte
+ buf1 []byte
+ buf2 []byte
+ str1 string
+ str2 string
+}
+
+func (b *Buffer) foo() { // ERROR "b does not escape"
+ b.buf1 = b.buf1[1:2] // ERROR "ignoring self-assignment to b.buf1"
+ b.buf1 = b.buf1[1:2:3] // ERROR "ignoring self-assignment to b.buf1"
+ b.buf1 = b.buf2[1:2] // ERROR "ignoring self-assignment to b.buf1"
+ b.buf1 = b.buf2[1:2:3] // ERROR "ignoring self-assignment to b.buf1"
+}
+
+func (b *Buffer) bar() { // ERROR "leaking param: b"
+ b.buf1 = b.arr[1:2] // ERROR "b.arr escapes to heap"
+}
+
+func (b *Buffer) baz() { // ERROR "b does not escape"
+ b.str1 = b.str1[1:2] // ERROR "ignoring self-assignment to b.str1"
+ b.str1 = b.str2[1:2] // ERROR "ignoring self-assignment to b.str1"
+}
+
+func (b *Buffer) bat() { // ERROR "leaking param: b"
+ o := new(Buffer) // ERROR "new\(Buffer\) escapes to heap"
+ o.buf1 = b.buf1[1:2]
+ sink = o
+}
+
+func quux(sp *string, bp *[]byte) { // ERROR "sp does not escape" "bp does not escape"
+ *sp = (*sp)[1:2] // ERROR "quux ignoring self-assignment to \*sp"
+ *bp = (*bp)[1:2] // ERROR "quux ignoring self-assignment to \*bp"
+}
+
+type StructWithString struct {
+ p *int
+ s string
+}
+
+// This is escape analysis false negative.
+// We assign the pointer to x.p but leak x.s. Escape analysis coarsens flows
+// to just x, and thus &i looks escaping.
+func fieldFlowTracking() {
+ var x StructWithString
+ i := 0 // ERROR "moved to heap: i"
+ x.p = &i // ERROR "&i escapes to heap"
+ sink = x.s
+}
+
+// String operations.
+
+func slicebytetostring0() {
+ b := make([]byte, 20) // ERROR "does not escape"
+ s := string(b) // ERROR "string\(b\) does not escape"
+ _ = s
+}
+
+func slicebytetostring1() {
+ b := make([]byte, 20) // ERROR "does not escape"
+ s := string(b) // ERROR "string\(b\) does not escape"
+ s1 := s[0:1]
+ _ = s1
+}
+
+func slicebytetostring2() {
+ b := make([]byte, 20) // ERROR "does not escape"
+ s := string(b) // ERROR "string\(b\) escapes to heap"
+ s1 := s[0:1] // ERROR "moved to heap: s1"
+ sink = &s1 // ERROR "&s1 escapes to heap"
+}
+
+func slicebytetostring3() {
+ b := make([]byte, 20) // ERROR "does not escape"
+ s := string(b) // ERROR "string\(b\) escapes to heap"
+ s1 := s[0:1]
+ sink = s1
+}
+
+func addstr0() {
+ s0 := "a"
+ s1 := "b"
+ s := s0 + s1 // ERROR "s0 \+ s1 does not escape"
+ _ = s
+}
+
+func addstr1() {
+ s0 := "a"
+ s1 := "b"
+ s := "c"
+ s += s0 + s1 // ERROR "s0 \+ s1 does not escape"
+ _ = s
+}
+
+func addstr2() {
+ b := make([]byte, 20) // ERROR "does not escape"
+ s0 := "a"
+ s := string(b) + s0 // ERROR "string\(b\) does not escape" "string\(b\) \+ s0 does not escape"
+ _ = s
+}
+
+func addstr3() {
+ s0 := "a"
+ s1 := "b"
+ s := s0 + s1 // ERROR "s0 \+ s1 escapes to heap"
+ s2 := s[0:1]
+ sink = s2
+}
+
+func intstring0() bool {
+ // string does not escape
+ x := '0'
+ s := string(x) // ERROR "string\(x\) does not escape"
+ return s == "0"
+}
+
+func intstring1() string {
+ // string does not escape, but the buffer does
+ x := '0'
+ s := string(x) // ERROR "string\(x\) escapes to heap"
+ return s
+}
+
+func intstring2() {
+ // string escapes to heap
+ x := '0'
+ s := string(x) // ERROR "string\(x\) escapes to heap" "moved to heap: s"
+ sink = &s // ERROR "&s escapes to heap"
+}
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type X struct {
+ T [32]byte
+}
+
+func (x *X) Get() []byte {
+ t := x.T
+ return t[:]
+}
+
+func (x *X) RetPtr(i int) *int {
+ i++
+ return &i
+}
+
+func (x *X) RetRPtr(i int) (r1 int, r2 *int) {
+ r1 = i + 1
+ r2 = &r1
+ return
+}
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "bytes"
+
+ "./a"
+)
+
+type X struct {
+ *a.X
+}
+
+type Intf interface {
+ Get() []byte
+ RetPtr(int) *int
+ RetRPtr(int) (int, *int)
+}
+
+func main() {
+ x := &a.X{T: [32]byte{1, 2, 3, 4}}
+ var ix Intf = X{x}
+ t1 := ix.Get()
+ t2 := x.Get()
+ if !bytes.Equal(t1, t2) {
+ panic(t1)
+ }
+
+ p1 := ix.RetPtr(5)
+ p2 := x.RetPtr(7)
+ if *p1 != 6 || *p2 != 8 {
+ panic(*p1)
+ }
+
+ r1, r2 := ix.RetRPtr(10)
+ r3, r4 := x.RetRPtr(13)
+ if r1 != 11 || *r2 != 11 || r3 != 14 || *r4 != 14 {
+ panic("bad RetRPtr")
+ }
+}
--- /dev/null
+// rundir
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 9537: Compiler does not run escape analysis on an inlined
+// generated method wrapper.
+
+package ignored
--- /dev/null
+// errorcheck
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 9634: Structs are incorrectly unpacked when passed as an argument
+// to append.
+
+package main
+
+func main() {
+ s := struct{
+ t []int
+ u int
+ }{}
+ _ = append(s, 0) // ERROR "must be a slice|must be slice"
+}
--- /dev/null
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ s := "foo"
+ b := []byte(s)
+ m := make(map[string]int)
+ // Test that map index can be used in range
+ // and that slicebytetostringtmp is not used in this context.
+ for m[string(b)] = range s {
+ }
+ b[0] = 'b'
+ if m["foo"] != 2 {
+ panic("bad")
+ }
+}
--- /dev/null
+// compile
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f(x interface{}) {
+ switch x := x.(type) {
+ case int:
+ func() {
+ _ = x
+ }()
+ case map[int]int:
+ func() {
+ for range x {
+ }
+ }()
+ }
+}
--- /dev/null
+// run
+
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func F() (x int) {
+ defer func() {
+ if x != 42 {
+ println("BUG: x =", x)
+ }
+ }()
+ return 42
+}
+
+func main() {
+ F()
+}
goarch = runtime.GOARCH
}
+ thechar := ""
+ if gochar, err := exec.Command("go", "env", "GOCHAR").Output(); err != nil {
+ bug()
+ fmt.Printf("running go env GOCHAR: %v\n", err)
+ return
+ } else {
+ thechar = strings.TrimSpace(string(gochar))
+ }
+
+ version, err := exec.Command("go", "tool", thechar+"g", "-V").Output()
+ if err != nil {
+ bug()
+ fmt.Printf("running go tool %sg -V: %v\n", thechar, err)
+ return
+ }
+ if strings.Contains(string(version), "framepointer") {
+ // Skip this test if GOEXPERIMENT=framepointer
+ return
+ }
+
dir, err := ioutil.TempDir("", "go-test-nosplit")
if err != nil {
bug()