[dev.cc] cmd/6a, cmd/6g etc: replace C implementations with Go implementations

Change-Id: I58e00a39cf63df07813d21453f91e68eef6a413c
Reviewed-on: https://go-review.googlesource.com/5635
Reviewed-by: Rob Pike <r@golang.org>
This commit is contained in:
Russ Cox 2015-02-23 14:20:01 -05:00
parent d10ede5ede
commit 3af0d791be
175 changed files with 854 additions and 97601 deletions

View file

@ -1,10 +0,0 @@
# Copyright 2012 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.
include ../../Make.dist
install: y.tab.h
y.tab.h: a.y
LANG=C LANGUAGE=en_US.UTF8 bison -d -v -y a.y

View file

@ -1,173 +0,0 @@
// Inferno utils/5a/a.h
// http://code.google.com/p/inferno-os/source/browse/utils/5a/a.h
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <bio.h>
#include <link.h>
#include "../5l/5.out.h"
#ifndef EXTERN
#define EXTERN extern
#endif
#undef getc
#undef ungetc
#undef BUFSIZ
#define getc ccgetc
#define ungetc ccungetc
typedef struct Sym Sym;
typedef struct Io Io;
#define MAXALIGN 7
#define FPCHIP 1
#define NSYMB 8192
#define BUFSIZ 8192
#define HISTSZ 20
#ifndef EOF
#define EOF (-1)
#endif
#define IGN (-2)
#define GETC() ((--fi.c < 0)? filbuf(): *fi.p++ & 0xff)
#define NHASH 503
#define STRINGSZ 200
#define NMACRO 10
struct Sym
{
Sym* link;
char* macro;
int32 value;
ushort type;
char *name;
char* labelname;
char sym;
};
#define S ((Sym*)0)
EXTERN struct
{
char* p;
int c;
} fi;
struct Io
{
Io* link;
char b[BUFSIZ];
char* p;
short c;
short f;
};
#define I ((Io*)0)
enum
{
CLAST,
CMACARG,
CMACRO,
CPREPROC,
Always = C_SCOND_NONE,
};
EXTERN int debug[256];
EXTERN Sym* hash[NHASH];
EXTERN char** Dlist;
EXTERN int nDlist;
EXTERN int newflag;
EXTERN char* hunk;
EXTERN char** include;
EXTERN Io* iofree;
EXTERN Io* ionext;
EXTERN Io* iostack;
EXTERN int32 lineno;
EXTERN int nerrors;
EXTERN int32 nhunk;
EXTERN int ninclude;
EXTERN int32 nsymb;
EXTERN Addr nullgen;
EXTERN char* outfile;
EXTERN int pass;
EXTERN int32 pc;
EXTERN int peekc;
EXTERN int32 stmtline;
EXTERN int sym;
EXTERN char* symb;
EXTERN int thechar;
EXTERN char* thestring;
EXTERN int32 thunk;
EXTERN Biobuf obuf;
EXTERN Link* ctxt;
EXTERN Biobuf bstdout;
EXTERN Prog* lastpc;
void* alloc(int32);
void* allocn(void*, int32, int32);
void ensuresymb(int32);
void errorexit(void);
void pushio(void);
void newio(void);
void newfile(char*, int);
Sym* slookup(char*);
Sym* lookup(void);
Sym* labellookup(Sym*);
void settext(LSym*);
void syminit(Sym*);
int32 yylex(void);
int getc(void);
int getnsc(void);
void unget(int);
int escchar(int);
void cinit(void);
void pinit(char*);
void cclean(void);
int isreg(Addr*);
void outcode(int, int, Addr*, int, Addr*);
int filbuf(void);
Sym* getsym(void);
void domacro(void);
void macund(void);
void macdef(void);
void macexpand(Sym*, char*);
void macinc(void);
void maclin(void);
void macprag(void);
void macif(int);
void macend(void);
void dodefine(char*);
void prfile(int32);
void linehist(char*, int);
void gethunk(void);
void yyerror(char*, ...);
int yyparse(void);
void setinclude(char*);
int assemble(char*);
void listinit(void);

View file

@ -29,20 +29,23 @@
// THE SOFTWARE.
%{
#include <u.h>
#include <stdio.h> /* if we don't, bison will, and a.h re-#defines getc */
#include <libc.h>
#include "a.h"
#include "../../runtime/funcdata.h"
package main
import (
"cmd/internal/asm"
"cmd/internal/obj"
. "cmd/internal/obj/arm"
)
%}
%union
{
Sym *sym;
int32 lval;
double dval;
char sval[8];
Addr addr;
%union {
sym *asm.Sym
lval int32
dval float64
sval string
addr obj.Addr
}
%left '|'
%left '^'
%left '&'
@ -51,12 +54,12 @@
%left '*' '/' '%'
%token <lval> LTYPE1 LTYPE2 LTYPE3 LTYPE4 LTYPE5
%token <lval> LTYPE6 LTYPE7 LTYPE8 LTYPE9 LTYPEA
%token <lval> LTYPEB LGLOBL LTYPEC LTYPED LTYPEE
%token <lval> LTYPEB 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 <lval> LTYPEX LTYPEPC LTYPEF LR LREG LF LFREG LC LCREG LPSR LFCR
%token <lval> LCOND LS LAT
%token <lval> LCOND LS LAT LGLOBL
%token <dval> LFCONST
%token <sval> LSCONST
%token <sym> LNAME LLAB LVAR
@ -68,30 +71,32 @@
prog:
| prog
{
stmtline = lineno;
stmtline = asm.Lineno;
}
line
line:
LNAME ':'
{
$1 = labellookup($1);
if($1->type == LLAB && $1->value != pc)
yyerror("redeclaration of %s", $1->labelname);
$1->type = LLAB;
$1->value = pc;
$1 = asm.LabelLookup($1);
if $1.Type == LLAB && $1.Value != int64(asm.PC) {
yyerror("redeclaration of %s", $1.Labelname)
}
$1.Type = LLAB;
$1.Value = int64(asm.PC)
}
line
| LNAME '=' expr ';'
{
$1->type = LVAR;
$1->value = $3;
$1.Type = LVAR;
$1.Value = int64($3);
}
| LVAR '=' expr ';'
{
if($1->value != $3)
yyerror("redeclaration of %s", $1->name);
$1->value = $3;
if $1.Value != int64($3) {
yyerror("redeclaration of %s", $1.Name)
}
$1.Value = int64($3);
}
| ';'
| inst ';'
@ -171,20 +176,20 @@ inst:
*/
| LTYPE8 cond ioreg ',' '[' reglist ']'
{
Addr g;
var g obj.Addr
g = nullgen;
g.type = TYPE_CONST;
g.offset = $6;
g.Type = obj.TYPE_CONST;
g.Offset = int64($6);
outcode($1, $2, &$3, 0, &g);
}
| LTYPE8 cond '[' reglist ']' ',' ioreg
{
Addr g;
var g obj.Addr
g = nullgen;
g.type = TYPE_CONST;
g.offset = $4;
g.Type = obj.TYPE_CONST;
g.Offset = int64($4);
outcode($1, $2, &g, 0, &$7);
}
/*
@ -192,15 +197,15 @@ inst:
*/
| LTYPE9 cond reg ',' ireg ',' reg
{
outcode($1, $2, &$5, $3.reg, &$7);
outcode($1, $2, &$5, int32($3.Reg), &$7);
}
| LTYPE9 cond reg ',' ireg comma
{
outcode($1, $2, &$5, $3.reg, &$3);
outcode($1, $2, &$5, int32($3.Reg), &$3);
}
| LTYPE9 cond comma ireg ',' reg
{
outcode($1, $2, &$4, $6.reg, &$6);
outcode($1, $2, &$4, int32($6.Reg), &$6);
}
/*
* RET
@ -214,16 +219,16 @@ inst:
*/
| LTYPEB name ',' '$' textsize
{
settext($2.sym);
asm.Settext($2.Sym);
outcode($1, Always, &$2, 0, &$5);
}
| LTYPEB name ',' con ',' '$' textsize
{
settext($2.sym);
asm.Settext($2.Sym);
outcode($1, Always, &$2, 0, &$7);
if(pass > 1) {
lastpc->from3.type = TYPE_CONST;
lastpc->from3.offset = $4;
if asm.Pass > 1 {
lastpc.From3.Type = obj.TYPE_CONST;
lastpc.From3.Offset = int64($4)
}
}
/*
@ -231,27 +236,28 @@ inst:
*/
| LGLOBL name ',' imm
{
settext($2.sym);
outcode($1, Always, &$2, 0, &$4);
asm.Settext($2.Sym)
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;
asm.Settext($2.Sym)
outcode($1, Always, &$2, 0, &$6)
if asm.Pass > 1 {
lastpc.From3.Type = obj.TYPE_CONST
lastpc.From3.Offset = int64($4)
}
}
/*
* DATA
*/
| LTYPEC name '/' con ',' ximm
{
outcode($1, Always, &$2, 0, &$6);
if(pass > 1) {
lastpc->from3.type = TYPE_CONST;
lastpc->from3.offset = $4;
outcode($1, Always, &$2, 0, &$6)
if asm.Pass > 1 {
lastpc.From3.Type = obj.TYPE_CONST
lastpc.From3.Offset = int64($4)
}
}
/*
@ -285,18 +291,18 @@ inst:
}
| LTYPEL cond freg ',' freg comma
{
outcode($1, $2, &$3, $5.reg, &nullgen);
outcode($1, $2, &$3, int32($5.Reg), &nullgen);
}
/*
* MCR MRC
*/
| LTYPEJ cond con ',' expr ',' spreg ',' creg ',' creg oexpr
{
Addr g;
var g obj.Addr
g = nullgen;
g.type = TYPE_CONST;
g.offset =
g.Type = obj.TYPE_CONST;
g.Offset = int64(
(0xe << 24) | /* opcode */
($1 << 20) | /* MCR/MRC */
(($2^C_SCOND_XOR) << 28) | /* scond */
@ -306,7 +312,7 @@ inst:
(($9 & 15) << 16) | /* Crn */
(($11 & 15) << 0) | /* Crm */
(($12 & 7) << 5) | /* coprocessor information */
(1<<4); /* must be set */
(1<<4)); /* must be set */
outcode(AMRC, Always, &nullgen, 0, &g);
}
/*
@ -314,17 +320,17 @@ inst:
*/
| LTYPEM cond reg ',' reg ',' regreg
{
outcode($1, $2, &$3, $5.reg, &$7);
outcode($1, $2, &$3, int32($5.Reg), &$7);
}
/*
* MULA r1,r2,r3,r4: (r1*r2+r3) & 0xffffffff -> r4
* MULA r1,r2,r3,r4: (r1*r2+r3) & 0xffffffff . r4
* MULAW{T,B} r1,r2,r3,r4
*/
| LTYPEN cond reg ',' reg ',' reg ',' spreg
{
$7.type = TYPE_REGREG2;
$7.offset = $9;
outcode($1, $2, &$3, $5.reg, &$7);
$7.Type = obj.TYPE_REGREG2;
$7.Offset = int64($9);
outcode($1, $2, &$3, int32($5.Reg), &$7);
}
/*
* PLD
@ -338,8 +344,9 @@ inst:
*/
| LTYPEPC gen ',' gen
{
if($2.type != TYPE_CONST || $4.type != TYPE_CONST)
yyerror("arguments to PCDATA must be integer constants");
if $2.Type != obj.TYPE_CONST || $4.Type != obj.TYPE_CONST {
yyerror("arguments to PCDATA must be integer constants")
}
outcode($1, Always, &$2, 0, &$4);
}
/*
@ -347,10 +354,12 @@ inst:
*/
| LTYPEF gen ',' gen
{
if($2.type != TYPE_CONST)
yyerror("index for FUNCDATA must be integer constant");
if($4.type != NAME_EXTERN && $4.type != NAME_STATIC && $4.type != TYPE_MEM)
yyerror("value for FUNCDATA must be symbol reference");
if $2.Type != obj.TYPE_CONST {
yyerror("index for FUNCDATA must be integer constant")
}
if $4.Type != obj.NAME_EXTERN && $4.Type != obj.NAME_STATIC && $4.Type != obj.TYPE_MEM {
yyerror("value for FUNCDATA must be symbol reference")
}
outcode($1, Always, &$2, 0, &$4);
}
/*
@ -361,13 +370,43 @@ inst:
outcode($1, Always, &nullgen, 0, &nullgen);
}
textsize:
LCONST
{
$$ = nullgen;
$$.Type = obj.TYPE_TEXTSIZE;
$$.Offset = int64($1)
$$.U.Argsize = obj.ArgsSizeUnknown;
}
| '-' LCONST
{
$$ = nullgen;
$$.Type = obj.TYPE_TEXTSIZE;
$$.Offset = -int64($2)
$$.U.Argsize = obj.ArgsSizeUnknown;
}
| LCONST '-' LCONST
{
$$ = nullgen;
$$.Type = obj.TYPE_TEXTSIZE;
$$.Offset = int64($1)
$$.U.Argsize = int32($3);
}
| '-' LCONST '-' LCONST
{
$$ = nullgen;
$$.Type = obj.TYPE_TEXTSIZE;
$$.Offset = -int64($2)
$$.U.Argsize = int32($4);
}
cond:
{
$$ = Always;
}
| cond LCOND
{
$$ = ($1 & ~C_SCOND) | $2;
$$ = ($1 & ^ C_SCOND) | $2;
}
| cond LS
{
@ -381,65 +420,36 @@ rel:
con '(' LPC ')'
{
$$ = nullgen;
$$.type = TYPE_BRANCH;
$$.offset = $1 + pc;
$$.Type = obj.TYPE_BRANCH;
$$.Offset = int64($1) + int64(asm.PC);
}
| LNAME offset
{
$1 = labellookup($1);
$1 = asm.LabelLookup($1);
$$ = nullgen;
if(pass == 2 && $1->type != LLAB)
yyerror("undefined label: %s", $1->labelname);
$$.type = TYPE_BRANCH;
$$.offset = $1->value + $2;
if asm.Pass == 2 && $1.Type != LLAB {
yyerror("undefined label: %s", $1.Labelname)
}
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;
$$.Type = obj.TYPE_BRANCH;
$$.Offset = $1.Value + int64($2);
}
ximm: '$' con
{
$$ = nullgen;
$$.type = TYPE_CONST;
$$.offset = $2;
$$.Type = obj.TYPE_CONST;
$$.Offset = int64($2);
}
| '$' oreg
{
$$ = $2;
$$.type = TYPE_ADDR;
$$.Type = obj.TYPE_ADDR;
}
| '$' LSCONST
{
$$ = nullgen;
$$.type = TYPE_SCONST;
memcpy($$.u.sval, $2, sizeof($$.u.sval));
$$.Type = obj.TYPE_SCONST;
$$.U.Sval = $2
}
| fcon
@ -447,45 +457,34 @@ fcon:
'$' LFCONST
{
$$ = nullgen;
$$.type = TYPE_FCONST;
$$.u.dval = $2;
$$.Type = obj.TYPE_FCONST;
$$.U.Dval = $2;
}
| '$' '-' LFCONST
{
$$ = nullgen;
$$.type = TYPE_FCONST;
$$.u.dval = -$3;
$$.Type = obj.TYPE_FCONST;
$$.U.Dval = -$3;
}
reglist:
spreg
{
if($1 < REG_R0 || $1 > REG_R15)
yyerror("invalid register in reglist");
$$ = 1 << ($1&15);
$$ = 1 << uint($1&15);
}
| spreg '-' spreg
{
int i;
if($1 < REG_R0 || $1 > REG_R15)
yyerror("invalid register in reglist");
if($3 < REG_R0 || $3 > REG_R15)
yyerror("invalid register in reglist");
$$=0;
for(i=$1; i<=$3; i++)
$$ |= 1<<(i&15);
for(i=$3; i<=$1; i++)
$$ |= 1<<(i&15);
for i:=$1; i<=$3; i++ {
$$ |= 1<<uint(i&15)
}
for i:=$3; i<=$1; i++ {
$$ |= 1<<uint(i&15)
}
}
| spreg comma reglist
{
if($1 < REG_R0 || $1 > REG_R15)
yyerror("invalid register in reglist");
$$ = (1<<($1&15)) | $3;
$$ = (1<<uint($1&15)) | $3;
}
gen:
@ -495,25 +494,25 @@ gen:
| shift '(' spreg ')'
{
$$ = $1;
$$.reg = $3;
$$.Reg = int16($3);
}
| LPSR
{
$$ = nullgen;
$$.type = TYPE_REG;
$$.reg = $1;
$$.Type = obj.TYPE_REG
$$.Reg = int16($1);
}
| LFCR
{
$$ = nullgen;
$$.type = TYPE_REG;
$$.reg = $1;
$$.Type = obj.TYPE_REG
$$.Reg = int16($1);
}
| con
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.offset = $1;
$$.Type = obj.TYPE_MEM;
$$.Offset = int64($1);
}
| oreg
| freg
@ -523,7 +522,7 @@ nireg:
| name
{
$$ = $1;
if($1.name != NAME_EXTERN && $1.name != NAME_STATIC) {
if($1.Name != obj.NAME_EXTERN && $1.Name != obj.NAME_STATIC) {
}
}
@ -531,9 +530,9 @@ ireg:
'(' spreg ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.reg = $2;
$$.offset = 0;
$$.Type = obj.TYPE_MEM;
$$.Reg = int16($2);
$$.Offset = 0;
}
ioreg:
@ -541,9 +540,9 @@ ioreg:
| con '(' sreg ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.reg = $3;
$$.offset = $1;
$$.Type = obj.TYPE_MEM;
$$.Reg = int16($3);
$$.Offset = int64($1);
}
oreg:
@ -551,8 +550,8 @@ oreg:
| name '(' sreg ')'
{
$$ = $1;
$$.type = TYPE_MEM;
$$.reg = $3;
$$.Type = obj.TYPE_MEM;
$$.Reg = int16($3);
}
| ioreg
@ -564,64 +563,66 @@ imsr:
imm: '$' con
{
$$ = nullgen;
$$.type = TYPE_CONST;
$$.offset = $2;
$$.Type = obj.TYPE_CONST;
$$.Offset = int64($2);
}
reg:
spreg
{
$$ = nullgen;
$$.type = TYPE_REG;
$$.reg = $1;
$$.Type = obj.TYPE_REG;
$$.Reg = int16($1);
}
regreg:
'(' spreg ',' spreg ')'
{
$$ = nullgen;
$$.type = TYPE_REGREG;
$$.reg = $2;
$$.offset = $4;
$$.Type = obj.TYPE_REGREG;
$$.Reg = int16($2);
$$.Offset = int64($4);
}
shift:
spreg '<' '<' rcon
{
$$ = nullgen;
$$.type = TYPE_SHIFT;
$$.offset = $1&15 | $4 | (0 << 5);
$$.Type = obj.TYPE_SHIFT;
$$.Offset = int64($1&15) | int64($4) | (0 << 5);
}
| spreg '>' '>' rcon
{
$$ = nullgen;
$$.type = TYPE_SHIFT;
$$.offset = $1&15 | $4 | (1 << 5);
$$.Type = obj.TYPE_SHIFT;
$$.Offset = int64($1&15) | int64($4) | (1 << 5);
}
| spreg '-' '>' rcon
{
$$ = nullgen;
$$.type = TYPE_SHIFT;
$$.offset = $1&15 | $4 | (2 << 5);
$$.Type = obj.TYPE_SHIFT;
$$.Offset = int64($1&15) | int64($4) | (2 << 5);
}
| spreg LAT '>' rcon
{
$$ = nullgen;
$$.type = TYPE_SHIFT;
$$.offset = $1&15 | $4 | (3 << 5);
$$.Type = obj.TYPE_SHIFT;
$$.Offset = int64($1&15) | int64($4) | (3 << 5);
}
rcon:
spreg
{
if($$ < REG_R0 || $$ > REG_R15)
print("register value out of range in shift\n");
if $$ < REG_R0 || $$ > REG_R15 {
print("register value out of range\n")
}
$$ = (($1&15) << 8) | (1 << 4);
}
| con
{
if($$ < 0 || $$ >= 32)
print("shift value out of range\n");
if $$ < 0 || $$ >= 32 {
print("shift value out of range\n")
}
$$ = ($1&31) << 7;
}
@ -633,8 +634,9 @@ sreg:
}
| LR '(' expr ')'
{
if($3 < 0 || $3 >= NREG)
print("register value out of range in R(...)\n");
if $3 < 0 || $3 >= NREG {
print("register value out of range\n")
}
$$ = REG_R0 + $3;
}
@ -649,8 +651,9 @@ creg:
LCREG
| LC '(' expr ')'
{
if($3 < 0 || $3 >= NREG)
print("register value out of range in C(...)\n");
if $3 < 0 || $3 >= NREG {
print("register value out of range\n")
}
$$ = $3; // TODO(rsc): REG_C0+$3
}
@ -662,40 +665,40 @@ freg:
LFREG
{
$$ = nullgen;
$$.type = TYPE_REG;
$$.reg = $1;
$$.Type = obj.TYPE_REG;
$$.Reg = int16($1);
}
| LF '(' con ')'
{
$$ = nullgen;
$$.type = TYPE_REG;
$$.reg = REG_F0 + $3;
$$.Type = obj.TYPE_REG;
$$.Reg = int16(REG_F0 + $3);
}
name:
con '(' pointer ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.name = $3;
$$.sym = nil;
$$.offset = $1;
$$.Type = obj.TYPE_MEM;
$$.Name = int8($3);
$$.Sym = nil;
$$.Offset = int64($1);
}
| LNAME offset '(' pointer ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.name = $4;
$$.sym = linklookup(ctxt, $1->name, 0);
$$.offset = $2;
$$.Type = obj.TYPE_MEM;
$$.Name = int8($4);
$$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
$$.Offset = int64($2);
}
| LNAME '<' '>' offset '(' LSB ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.name = NAME_STATIC;
$$.sym = linklookup(ctxt, $1->name, 1);
$$.offset = $4;
$$.Type = obj.TYPE_MEM;
$$.Name = obj.NAME_STATIC;
$$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 1);
$$.Offset = int64($4);
}
offset:
@ -720,7 +723,7 @@ con:
LCONST
| LVAR
{
$$ = $1->value;
$$ = int32($1.Value);
}
| '-' con
{
@ -732,7 +735,7 @@ con:
}
| '~' con
{
$$ = ~$2;
$$ = ^$2;
}
| '(' expr ')'
{
@ -772,11 +775,11 @@ expr:
}
| expr '<' '<' expr
{
$$ = $1 << $4;
$$ = $1 << uint($4);
}
| expr '>' '>' expr
{
$$ = $1 >> $4;
$$ = $1 >> uint($4);
}
| expr '&' expr
{

View file

@ -1,20 +0,0 @@
// 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.
// +build ignore
/*
5a is a version of the Plan 9 assembler. The original is documented at
http://plan9.bell-labs.com/magic/man2html/1/8a
Go-specific considerations are documented at
http://golang.org/doc/asm
Its target architecture is the ARM, referred to by these tools as arm.
*/
package main

View file

@ -1,538 +0,0 @@
// Inferno utils/5a/lex.c
// http://code.google.com/p/inferno-os/source/browse/utils/5a/lex.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#define EXTERN
#include <u.h>
#include <libc.h>
#include "a.h"
#include "y.tab.h"
enum
{
Plan9 = 1<<0,
Unix = 1<<1,
Windows = 1<<2,
};
int
systemtype(int sys)
{
#ifdef _WIN32
return sys&Windows;
#else
return sys&Plan9;
#endif
}
int
Lconv(Fmt *fp)
{
return linklinefmt(ctxt, fp);
}
void
dodef(char *p)
{
if(nDlist%8 == 0)
Dlist = allocn(Dlist, nDlist*sizeof(char *),
8*sizeof(char *));
Dlist[nDlist++] = p;
}
void
usage(void)
{
print("usage: %ca [options] file.c...\n", thechar);
flagprint(1);
errorexit();
}
void
main(int argc, char *argv[])
{
char *p;
thechar = '5';
thestring = "arm";
ctxt = linknew(&linkarm);
ctxt->diag = yyerror;
ctxt->bso = &bstdout;
ctxt->enforce_data_order = 1;
Binit(&bstdout, 1, OWRITE);
listinit5();
fmtinstall('L', Lconv);
// Allow GOARCH=thestring or GOARCH=thestringsuffix,
// but not other values.
p = getgoarch();
if(strncmp(p, thestring, strlen(thestring)) != 0)
sysfatal("cannot use %cc with GOARCH=%s", thechar, p);
ensuresymb(NSYMB);
memset(debug, 0, sizeof(debug));
cinit();
outfile = 0;
setinclude(".");
flagfn1("D", "name[=value]: add #define", dodef);
flagfn1("I", "dir: add dir to include path", setinclude);
flagcount("S", "print assembly and machine code", &debug['S']);
flagcount("m", "debug preprocessor macros", &debug['m']);
flagstr("o", "file: set output file", &outfile);
flagstr("trimpath", "prefix: remove prefix from recorded source file paths", &ctxt->trimpath);
flagparse(&argc, &argv, usage);
ctxt->debugasm = debug['S'];
if(argc < 1)
usage();
if(argc > 1){
print("can't assemble multiple files\n");
errorexit();
}
if(assemble(argv[0]))
errorexit();
Bflush(&bstdout);
if(nerrors > 0)
errorexit();
exits(0);
}
int
assemble(char *file)
{
char *ofile, *p;
int i, of;
ofile = alloc(strlen(file)+3); // +3 for .x\0 (x=thechar)
strcpy(ofile, file);
p = utfrrune(ofile, '/');
if(p) {
include[0] = ofile;
*p++ = 0;
} else
p = ofile;
if(outfile == 0) {
outfile = p;
if(outfile){
p = utfrrune(outfile, '.');
if(p)
if(p[1] == 's' && p[2] == 0)
p[0] = 0;
p = utfrune(outfile, 0);
p[0] = '.';
p[1] = thechar;
p[2] = 0;
} else
outfile = "/dev/null";
}
of = create(outfile, OWRITE, 0664);
if(of < 0) {
yyerror("%ca: cannot create %s", thechar, outfile);
errorexit();
}
Binit(&obuf, of, OWRITE);
Bprint(&obuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
Bprint(&obuf, "!\n");
for(pass = 1; pass <= 2; pass++) {
pinit(file);
for(i=0; i<nDlist; i++)
dodefine(Dlist[i]);
yyparse();
cclean();
if(nerrors)
return nerrors;
}
writeobj(ctxt, &obuf);
Bflush(&obuf);
return 0;
}
struct
{
char *name;
ushort type;
ushort value;
} itab[] =
{
"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,
"C0", LCREG, 0,
"C1", LCREG, 1,
"C2", LCREG, 2,
"C3", LCREG, 3,
"C4", LCREG, 4,
"C5", LCREG, 5,
"C6", LCREG, 6,
"C7", LCREG, 7,
"C8", LCREG, 8,
"C9", LCREG, 9,
"C10", LCREG, 10,
"C11", LCREG, 11,
"C12", LCREG, 12,
"C13", LCREG, 13,
"C14", LCREG, 14,
"C15", LCREG, 15,
"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,
".W", LS, C_WBIT,
".P", LS, C_PBIT,
".PW", LS, C_WBIT|C_PBIT,
".WP", LS, C_WBIT|C_PBIT,
".F", LS, C_FBIT,
".IBW", LS, C_WBIT|C_PBIT|C_UBIT,
".IAW", LS, C_WBIT|C_UBIT,
".DBW", LS, C_WBIT|C_PBIT,
".DAW", LS, C_WBIT,
".IB", LS, C_PBIT|C_UBIT,
".IA", LS, C_UBIT,
".DB", LS, C_PBIT,
".DA", LS, 0,
"@", LAT, 0,
"AND", LTYPE1, AAND,
"EOR", LTYPE1, AEOR,
"SUB", LTYPE1, ASUB,
"RSB", LTYPE1, ARSB,
"ADD", LTYPE1, AADD,
"ADC", LTYPE1, AADC,
"SBC", LTYPE1, ASBC,
"RSC", LTYPE1, ARSC,
"ORR", LTYPE1, AORR,
"BIC", LTYPE1, ABIC,
"SLL", LTYPE1, ASLL,
"SRL", LTYPE1, ASRL,
"SRA", LTYPE1, ASRA,
"MUL", LTYPE1, AMUL,
"MULA", LTYPEN, AMULA,
"DIV", LTYPE1, ADIV,
"MOD", LTYPE1, AMOD,
"MULL", LTYPEM, AMULL,
"MULAL", LTYPEM, AMULAL,
"MULLU", LTYPEM, AMULLU,
"MULALU", LTYPEM, AMULALU,
"MVN", LTYPE2, AMVN, /* op2 ignored */
"MOVB", LTYPE3, AMOVB,
"MOVBU", LTYPE3, AMOVBU,
"MOVH", LTYPE3, AMOVH,
"MOVHU", LTYPE3, AMOVHU,
"MOVW", LTYPE3, AMOVW,
"MOVD", LTYPE3, AMOVD,
"MOVDF", LTYPE3, AMOVDF,
"MOVDW", LTYPE3, AMOVDW,
"MOVF", LTYPE3, AMOVF,
"MOVFD", LTYPE3, AMOVFD,
"MOVFW", LTYPE3, AMOVFW,
"MOVWD", LTYPE3, AMOVWD,
"MOVWF", LTYPE3, AMOVWF,
"LDREX", LTYPE3, ALDREX,
"LDREXD", LTYPE3, ALDREXD,
"STREX", LTYPE9, ASTREX,
"STREXD", LTYPE9, ASTREXD,
/*
"NEGF", LTYPEI, ANEGF,
"NEGD", LTYPEI, ANEGD,
"SQTF", LTYPEI, ASQTF,
"SQTD", LTYPEI, ASQTD,
"RNDF", LTYPEI, ARNDF,
"RNDD", LTYPEI, ARNDD,
"URDF", LTYPEI, AURDF,
"URDD", LTYPEI, AURDD,
"NRMF", LTYPEI, ANRMF,
"NRMD", LTYPEI, ANRMD,
*/
"ABSF", LTYPEI, AABSF,
"ABSD", LTYPEI, AABSD,
"SQRTF", LTYPEI, ASQRTF,
"SQRTD", LTYPEI, ASQRTD,
"CMPF", LTYPEL, ACMPF,
"CMPD", LTYPEL, ACMPD,
"ADDF", LTYPEK, AADDF,
"ADDD", LTYPEK, AADDD,
"SUBF", LTYPEK, ASUBF,
"SUBD", LTYPEK, ASUBD,
"MULF", LTYPEK, AMULF,
"MULD", LTYPEK, AMULD,
"DIVF", LTYPEK, ADIVF,
"DIVD", LTYPEK, ADIVD,
"B", LTYPE4, AB,
"BL", LTYPE4, ABL,
"BX", LTYPEBX, ABX,
"BEQ", LTYPE5, ABEQ,
"BNE", LTYPE5, ABNE,
"BCS", LTYPE5, ABCS,
"BHS", LTYPE5, ABHS,
"BCC", LTYPE5, ABCC,
"BLO", LTYPE5, ABLO,
"BMI", LTYPE5, ABMI,
"BPL", LTYPE5, ABPL,
"BVS", LTYPE5, ABVS,
"BVC", LTYPE5, ABVC,
"BHI", LTYPE5, ABHI,
"BLS", LTYPE5, ABLS,
"BGE", LTYPE5, ABGE,
"BLT", LTYPE5, ABLT,
"BGT", LTYPE5, ABGT,
"BLE", LTYPE5, ABLE,
"BCASE", LTYPE5, ABCASE,
"SWI", LTYPE6, ASWI,
"CMP", LTYPE7, ACMP,
"TST", LTYPE7, ATST,
"TEQ", LTYPE7, ATEQ,
"CMN", LTYPE7, ACMN,
"MOVM", LTYPE8, AMOVM,
"SWPBU", LTYPE9, ASWPBU,
"SWPW", LTYPE9, ASWPW,
"RET", LTYPEA, ARET,
"RFE", LTYPEA, ARFE,
"TEXT", LTYPEB, ATEXT,
"GLOBL", LGLOBL, AGLOBL,
"DATA", LTYPEC, ADATA,
"CASE", LTYPED, ACASE,
"END", LTYPEE, AEND,
"WORD", LTYPEH, AWORD,
"NOP", LTYPEI, ANOP,
"MCR", LTYPEJ, 0,
"MRC", LTYPEJ, 1,
"PLD", LTYPEPLD, APLD,
"UNDEF", LTYPEE, AUNDEF,
"CLZ", LTYPE2, ACLZ,
"MULWT", LTYPE1, AMULWT,
"MULWB", LTYPE1, AMULWB,
"MULAWT", LTYPEN, AMULAWT,
"MULAWB", LTYPEN, AMULAWB,
"USEFIELD", LTYPEN, AUSEFIELD,
"PCDATA", LTYPEPC, APCDATA,
"FUNCDATA", LTYPEF, AFUNCDATA,
0
};
void
cinit(void)
{
Sym *s;
int i;
nullgen.type = TYPE_NONE;
nullgen.name = NAME_NONE;
nerrors = 0;
iostack = I;
iofree = I;
peekc = IGN;
nhunk = 0;
for(i=0; i<NHASH; i++)
hash[i] = S;
for(i=0; itab[i].name; i++) {
s = slookup(itab[i].name);
s->type = itab[i].type;
s->value = itab[i].value;
}
}
void
syminit(Sym *s)
{
s->type = LNAME;
s->value = 0;
}
int
isreg(Addr *g)
{
USED(g);
return 1;
}
void
cclean(void)
{
outcode(AEND, Always, &nullgen, 0, &nullgen);
}
static int bcode[] =
{
ABEQ,
ABNE,
ABCS,
ABCC,
ABMI,
ABPL,
ABVS,
ABVC,
ABHI,
ABLS,
ABGE,
ABLT,
ABGT,
ABLE,
AB,
ANOP,
};
void
outcode(int a, int scond, Addr *g1, int reg, Addr *g2)
{
Prog *p;
Plist *pl;
/* hack to make B.NE etc. work: turn it into the corresponding conditional */
if(a == AB){
a = bcode[(scond^C_SCOND_XOR)&0xf];
scond = (scond & ~0xf) | C_SCOND_NONE;
}
if(pass == 1)
goto out;
p = malloc(sizeof *p);
memset(p, 0, sizeof *p);
p->as = a;
p->lineno = stmtline;
p->scond = scond;
p->from = *g1;
p->reg = reg;
p->to = *g2;
p->pc = pc;
if(lastpc == nil) {
pl = linknewplist(ctxt);
pl->firstpc = p;
} else
lastpc->link = p;
lastpc = p;
out:
if(a != AGLOBL && a != ADATA)
pc++;
}
#include "../cc/lexbody"
#include "../cc/macbody"

File diff suppressed because it is too large Load diff

View file

@ -1,166 +0,0 @@
/* A Bison parser, made by GNU Bison 2.3. */
/* Skeleton interface for Bison's Yacc-like parsers in C
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
under terms of your choice, so long as that work isn't itself a
parser generator using the skeleton or a modified version thereof
as a parser skeleton. Alternatively, if you modify or redistribute
the parser skeleton itself, you may (at your option) remove this
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
LTYPE1 = 258,
LTYPE2 = 259,
LTYPE3 = 260,
LTYPE4 = 261,
LTYPE5 = 262,
LTYPE6 = 263,
LTYPE7 = 264,
LTYPE8 = 265,
LTYPE9 = 266,
LTYPEA = 267,
LTYPEB = 268,
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 LTYPE1 258
#define LTYPE2 259
#define LTYPE3 260
#define LTYPE4 261
#define LTYPE5 262
#define LTYPE6 263
#define LTYPE7 264
#define LTYPE8 265
#define LTYPE9 266
#define LTYPEA 267
#define LTYPEB 268
#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
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
#line 39 "a.y"
{
Sym *sym;
int32 lval;
double dval;
char sval[8];
Addr addr;
}
/* Line 1529 of yacc.c. */
#line 159 "y.tab.h"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
#endif
extern YYSTYPE yylval;

View file

@ -1,5 +0,0 @@
# Copyright 2012 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.
include ../../Make.dist

File diff suppressed because it is too large Load diff

View file

@ -1,760 +0,0 @@
// 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.
#include <u.h>
#include <libc.h>
#include "gg.h"
/*
* attempt to generate 64-bit
* res = n
* return 1 on success, 0 if op not handled.
*/
void
cgen64(Node *n, Node *res)
{
Node t1, t2, *l, *r;
Node lo1, lo2, hi1, hi2;
Node al, ah, bl, bh, cl, ch, s, n1, creg;
Prog *p1, *p2, *p3, *p4, *p5, *p6;
uint64 v;
if(res->op != OINDREG && res->op != ONAME) {
dump("n", n);
dump("res", res);
fatal("cgen64 %O of %O", n->op, res->op);
}
l = n->left;
if(!l->addable) {
tempname(&t1, l->type);
cgen(l, &t1);
l = &t1;
}
split64(l, &lo1, &hi1);
switch(n->op) {
default:
fatal("cgen64 %O", n->op);
case OMINUS:
split64(res, &lo2, &hi2);
regalloc(&t1, lo1.type, N);
regalloc(&al, lo1.type, N);
regalloc(&ah, hi1.type, N);
gins(AMOVW, &lo1, &al);
gins(AMOVW, &hi1, &ah);
gmove(ncon(0), &t1);
p1 = gins(ASUB, &al, &t1);
p1->scond |= C_SBIT;
gins(AMOVW, &t1, &lo2);
gmove(ncon(0), &t1);
gins(ASBC, &ah, &t1);
gins(AMOVW, &t1, &hi2);
regfree(&t1);
regfree(&al);
regfree(&ah);
splitclean();
splitclean();
return;
case OCOM:
regalloc(&t1, lo1.type, N);
gmove(ncon(-1), &t1);
split64(res, &lo2, &hi2);
regalloc(&n1, lo1.type, N);
gins(AMOVW, &lo1, &n1);
gins(AEOR, &t1, &n1);
gins(AMOVW, &n1, &lo2);
gins(AMOVW, &hi1, &n1);
gins(AEOR, &t1, &n1);
gins(AMOVW, &n1, &hi2);
regfree(&t1);
regfree(&n1);
splitclean();
splitclean();
return;
case OADD:
case OSUB:
case OMUL:
case OLSH:
case ORSH:
case OAND:
case OOR:
case OXOR:
case OLROT:
// binary operators.
// common setup below.
break;
}
// setup for binary operators
r = n->right;
if(r != N && !r->addable) {
tempname(&t2, r->type);
cgen(r, &t2);
r = &t2;
}
if(is64(r->type))
split64(r, &lo2, &hi2);
regalloc(&al, lo1.type, N);
regalloc(&ah, hi1.type, N);
// Do op. Leave result in ah:al.
switch(n->op) {
default:
fatal("cgen64: not implemented: %N\n", n);
case OADD:
// TODO: Constants
regalloc(&bl, types[TPTR32], N);
regalloc(&bh, types[TPTR32], N);
gins(AMOVW, &hi1, &ah);
gins(AMOVW, &lo1, &al);
gins(AMOVW, &hi2, &bh);
gins(AMOVW, &lo2, &bl);
p1 = gins(AADD, &bl, &al);
p1->scond |= C_SBIT;
gins(AADC, &bh, &ah);
regfree(&bl);
regfree(&bh);
break;
case OSUB:
// TODO: Constants.
regalloc(&bl, types[TPTR32], N);
regalloc(&bh, types[TPTR32], N);
gins(AMOVW, &lo1, &al);
gins(AMOVW, &hi1, &ah);
gins(AMOVW, &lo2, &bl);
gins(AMOVW, &hi2, &bh);
p1 = gins(ASUB, &bl, &al);
p1->scond |= C_SBIT;
gins(ASBC, &bh, &ah);
regfree(&bl);
regfree(&bh);
break;
case OMUL:
// TODO(kaib): this can be done with 4 regs and does not need 6
regalloc(&bl, types[TPTR32], N);
regalloc(&bh, types[TPTR32], N);
regalloc(&cl, types[TPTR32], N);
regalloc(&ch, types[TPTR32], N);
// load args into bh:bl and bh:bl.
gins(AMOVW, &hi1, &bh);
gins(AMOVW, &lo1, &bl);
gins(AMOVW, &hi2, &ch);
gins(AMOVW, &lo2, &cl);
// bl * cl -> ah al
p1 = gins(AMULLU, N, N);
p1->from.type = TYPE_REG;
p1->from.reg = bl.val.u.reg;
p1->reg = cl.val.u.reg;
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 = TYPE_REG;
p1->from.reg = bl.val.u.reg;
p1->reg = ch.val.u.reg;
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 = TYPE_REG;
p1->from.reg = bh.val.u.reg;
p1->reg = cl.val.u.reg;
p1->to.type = TYPE_REGREG2;
p1->to.reg = ah.val.u.reg;
p1->to.offset = ah.val.u.reg;
//print("%P\n", p1);
regfree(&bh);
regfree(&bl);
regfree(&ch);
regfree(&cl);
break;
case OLROT:
// We only rotate by a constant c in [0,64).
// if c >= 32:
// lo, hi = hi, lo
// c -= 32
// if c == 0:
// no-op
// else:
// t = hi
// shld hi:lo, c
// shld lo:t, c
v = mpgetfix(r->val.u.xval);
regalloc(&bl, lo1.type, N);
regalloc(&bh, hi1.type, N);
if(v >= 32) {
// reverse during load to do the first 32 bits of rotate
v -= 32;
gins(AMOVW, &hi1, &bl);
gins(AMOVW, &lo1, &bh);
} else {
gins(AMOVW, &hi1, &bh);
gins(AMOVW, &lo1, &bl);
}
if(v == 0) {
gins(AMOVW, &bh, &ah);
gins(AMOVW, &bl, &al);
} else {
// rotate by 1 <= v <= 31
// MOVW bl<<v, al
// MOVW bh<<v, ah
// OR bl>>(32-v), ah
// OR bh>>(32-v), al
gshift(AMOVW, &bl, SHIFT_LL, v, &al);
gshift(AMOVW, &bh, SHIFT_LL, v, &ah);
gshift(AORR, &bl, SHIFT_LR, 32-v, &ah);
gshift(AORR, &bh, SHIFT_LR, 32-v, &al);
}
regfree(&bl);
regfree(&bh);
break;
case OLSH:
regalloc(&bl, lo1.type, N);
regalloc(&bh, hi1.type, N);
gins(AMOVW, &hi1, &bh);
gins(AMOVW, &lo1, &bl);
if(r->op == OLITERAL) {
v = mpgetfix(r->val.u.xval);
if(v >= 64) {
// TODO(kaib): replace with gins(AMOVW, nodintconst(0), &al)
// here and below (verify it optimizes to EOR)
gins(AEOR, &al, &al);
gins(AEOR, &ah, &ah);
} else
if(v > 32) {
gins(AEOR, &al, &al);
// MOVW bl<<(v-32), ah
gshift(AMOVW, &bl, SHIFT_LL, (v-32), &ah);
} else
if(v == 32) {
gins(AEOR, &al, &al);
gins(AMOVW, &bl, &ah);
} else
if(v > 0) {
// MOVW bl<<v, al
gshift(AMOVW, &bl, SHIFT_LL, v, &al);
// MOVW bh<<v, ah
gshift(AMOVW, &bh, SHIFT_LL, v, &ah);
// OR bl>>(32-v), ah
gshift(AORR, &bl, SHIFT_LR, 32-v, &ah);
} else {
gins(AMOVW, &bl, &al);
gins(AMOVW, &bh, &ah);
}
goto olsh_break;
}
regalloc(&s, types[TUINT32], N);
regalloc(&creg, types[TUINT32], N);
if (is64(r->type)) {
// shift is >= 1<<32
split64(r, &cl, &ch);
gmove(&ch, &s);
gins(ATST, &s, N);
p6 = gbranch(ABNE, T, 0);
gmove(&cl, &s);
splitclean();
} else {
gmove(r, &s);
p6 = P;
}
gins(ATST, &s, N);
// shift == 0
p1 = gins(AMOVW, &bl, &al);
p1->scond = C_SCOND_EQ;
p1 = gins(AMOVW, &bh, &ah);
p1->scond = C_SCOND_EQ;
p2 = gbranch(ABEQ, T, 0);
// shift is < 32
nodconst(&n1, types[TUINT32], 32);
gmove(&n1, &creg);
gcmp(ACMP, &s, &creg);
// MOVW.LO bl<<s, al
p1 = gregshift(AMOVW, &bl, SHIFT_LL, &s, &al);
p1->scond = C_SCOND_LO;
// MOVW.LO bh<<s, ah
p1 = gregshift(AMOVW, &bh, SHIFT_LL, &s, &ah);
p1->scond = C_SCOND_LO;
// SUB.LO s, creg
p1 = gins(ASUB, &s, &creg);
p1->scond = C_SCOND_LO;
// OR.LO bl>>creg, ah
p1 = gregshift(AORR, &bl, SHIFT_LR, &creg, &ah);
p1->scond = C_SCOND_LO;
// BLO end
p3 = gbranch(ABLO, T, 0);
// shift == 32
p1 = gins(AEOR, &al, &al);
p1->scond = C_SCOND_EQ;
p1 = gins(AMOVW, &bl, &ah);
p1->scond = C_SCOND_EQ;
p4 = gbranch(ABEQ, T, 0);
// shift is < 64
nodconst(&n1, types[TUINT32], 64);
gmove(&n1, &creg);
gcmp(ACMP, &s, &creg);
// EOR.LO al, al
p1 = gins(AEOR, &al, &al);
p1->scond = C_SCOND_LO;
// MOVW.LO creg>>1, creg
p1 = gshift(AMOVW, &creg, SHIFT_LR, 1, &creg);
p1->scond = C_SCOND_LO;
// SUB.LO creg, s
p1 = gins(ASUB, &creg, &s);
p1->scond = C_SCOND_LO;
// MOVW bl<<s, ah
p1 = gregshift(AMOVW, &bl, SHIFT_LL, &s, &ah);
p1->scond = C_SCOND_LO;
p5 = gbranch(ABLO, T, 0);
// shift >= 64
if (p6 != P) patch(p6, pc);
gins(AEOR, &al, &al);
gins(AEOR, &ah, &ah);
patch(p2, pc);
patch(p3, pc);
patch(p4, pc);
patch(p5, pc);
regfree(&s);
regfree(&creg);
olsh_break:
regfree(&bl);
regfree(&bh);
break;
case ORSH:
regalloc(&bl, lo1.type, N);
regalloc(&bh, hi1.type, N);
gins(AMOVW, &hi1, &bh);
gins(AMOVW, &lo1, &bl);
if(r->op == OLITERAL) {
v = mpgetfix(r->val.u.xval);
if(v >= 64) {
if(bh.type->etype == TINT32) {
// MOVW bh->31, al
gshift(AMOVW, &bh, SHIFT_AR, 31, &al);
// MOVW bh->31, ah
gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
} else {
gins(AEOR, &al, &al);
gins(AEOR, &ah, &ah);
}
} else
if(v > 32) {
if(bh.type->etype == TINT32) {
// MOVW bh->(v-32), al
gshift(AMOVW, &bh, SHIFT_AR, v-32, &al);
// MOVW bh->31, ah
gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
} else {
// MOVW bh>>(v-32), al
gshift(AMOVW, &bh, SHIFT_LR, v-32, &al);
gins(AEOR, &ah, &ah);
}
} else
if(v == 32) {
gins(AMOVW, &bh, &al);
if(bh.type->etype == TINT32) {
// MOVW bh->31, ah
gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
} else {
gins(AEOR, &ah, &ah);
}
} else
if( v > 0) {
// MOVW bl>>v, al
gshift(AMOVW, &bl, SHIFT_LR, v, &al);
// OR bh<<(32-v), al
gshift(AORR, &bh, SHIFT_LL, 32-v, &al);
if(bh.type->etype == TINT32) {
// MOVW bh->v, ah
gshift(AMOVW, &bh, SHIFT_AR, v, &ah);
} else {
// MOVW bh>>v, ah
gshift(AMOVW, &bh, SHIFT_LR, v, &ah);
}
} else {
gins(AMOVW, &bl, &al);
gins(AMOVW, &bh, &ah);
}
goto orsh_break;
}
regalloc(&s, types[TUINT32], N);
regalloc(&creg, types[TUINT32], N);
if(is64(r->type)) {
// shift is >= 1<<32
split64(r, &cl, &ch);
gmove(&ch, &s);
gins(ATST, &s, N);
if(bh.type->etype == TINT32)
p1 = gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
else
p1 = gins(AEOR, &ah, &ah);
p1->scond = C_SCOND_NE;
p6 = gbranch(ABNE, T, 0);
gmove(&cl, &s);
splitclean();
} else {
gmove(r, &s);
p6 = P;
}
gins(ATST, &s, N);
// shift == 0
p1 = gins(AMOVW, &bl, &al);
p1->scond = C_SCOND_EQ;
p1 = gins(AMOVW, &bh, &ah);
p1->scond = C_SCOND_EQ;
p2 = gbranch(ABEQ, T, 0);
// check if shift is < 32
nodconst(&n1, types[TUINT32], 32);
gmove(&n1, &creg);
gcmp(ACMP, &s, &creg);
// MOVW.LO bl>>s, al
p1 = gregshift(AMOVW, &bl, SHIFT_LR, &s, &al);
p1->scond = C_SCOND_LO;
// SUB.LO s,creg
p1 = gins(ASUB, &s, &creg);
p1->scond = C_SCOND_LO;
// OR.LO bh<<(32-s), al
p1 = gregshift(AORR, &bh, SHIFT_LL, &creg, &al);
p1->scond = C_SCOND_LO;
if(bh.type->etype == TINT32) {
// MOVW bh->s, ah
p1 = gregshift(AMOVW, &bh, SHIFT_AR, &s, &ah);
} else {
// MOVW bh>>s, ah
p1 = gregshift(AMOVW, &bh, SHIFT_LR, &s, &ah);
}
p1->scond = C_SCOND_LO;
// BLO end
p3 = gbranch(ABLO, T, 0);
// shift == 32
p1 = gins(AMOVW, &bh, &al);
p1->scond = C_SCOND_EQ;
if(bh.type->etype == TINT32)
gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
else
gins(AEOR, &ah, &ah);
p4 = gbranch(ABEQ, T, 0);
// check if shift is < 64
nodconst(&n1, types[TUINT32], 64);
gmove(&n1, &creg);
gcmp(ACMP, &s, &creg);
// MOVW.LO creg>>1, creg
p1 = gshift(AMOVW, &creg, SHIFT_LR, 1, &creg);
p1->scond = C_SCOND_LO;
// SUB.LO creg, s
p1 = gins(ASUB, &creg, &s);
p1->scond = C_SCOND_LO;
if(bh.type->etype == TINT32) {
// MOVW bh->(s-32), al
p1 = gregshift(AMOVW, &bh, SHIFT_AR, &s, &al);
p1->scond = C_SCOND_LO;
} else {
// MOVW bh>>(v-32), al
p1 = gregshift(AMOVW, &bh, SHIFT_LR, &s, &al);
p1->scond = C_SCOND_LO;
}
// BLO end
p5 = gbranch(ABLO, T, 0);
// s >= 64
if(p6 != P)
patch(p6, pc);
if(bh.type->etype == TINT32) {
// MOVW bh->31, al
gshift(AMOVW, &bh, SHIFT_AR, 31, &al);
} else {
gins(AEOR, &al, &al);
}
patch(p2, pc);
patch(p3, pc);
patch(p4, pc);
patch(p5, pc);
regfree(&s);
regfree(&creg);
orsh_break:
regfree(&bl);
regfree(&bh);
break;
case OXOR:
case OAND:
case OOR:
// TODO(kaib): literal optimizations
// make constant the right side (it usually is anyway).
// if(lo1.op == OLITERAL) {
// nswap(&lo1, &lo2);
// nswap(&hi1, &hi2);
// }
// if(lo2.op == OLITERAL) {
// // special cases for constants.
// lv = mpgetfix(lo2.val.u.xval);
// hv = mpgetfix(hi2.val.u.xval);
// splitclean(); // right side
// split64(res, &lo2, &hi2);
// switch(n->op) {
// case OXOR:
// gmove(&lo1, &lo2);
// gmove(&hi1, &hi2);
// switch(lv) {
// case 0:
// break;
// case 0xffffffffu:
// gins(ANOTL, N, &lo2);
// break;
// default:
// gins(AXORL, ncon(lv), &lo2);
// break;
// }
// switch(hv) {
// case 0:
// break;
// case 0xffffffffu:
// gins(ANOTL, N, &hi2);
// break;
// default:
// gins(AXORL, ncon(hv), &hi2);
// break;
// }
// break;
// case OAND:
// switch(lv) {
// case 0:
// gins(AMOVL, ncon(0), &lo2);
// break;
// default:
// gmove(&lo1, &lo2);
// if(lv != 0xffffffffu)
// gins(AANDL, ncon(lv), &lo2);
// break;
// }
// switch(hv) {
// case 0:
// gins(AMOVL, ncon(0), &hi2);
// break;
// default:
// gmove(&hi1, &hi2);
// if(hv != 0xffffffffu)
// gins(AANDL, ncon(hv), &hi2);
// break;
// }
// break;
// case OOR:
// switch(lv) {
// case 0:
// gmove(&lo1, &lo2);
// break;
// case 0xffffffffu:
// gins(AMOVL, ncon(0xffffffffu), &lo2);
// break;
// default:
// gmove(&lo1, &lo2);
// gins(AORL, ncon(lv), &lo2);
// break;
// }
// switch(hv) {
// case 0:
// gmove(&hi1, &hi2);
// break;
// case 0xffffffffu:
// gins(AMOVL, ncon(0xffffffffu), &hi2);
// break;
// default:
// gmove(&hi1, &hi2);
// gins(AORL, ncon(hv), &hi2);
// break;
// }
// break;
// }
// splitclean();
// splitclean();
// goto out;
// }
regalloc(&n1, lo1.type, N);
gins(AMOVW, &lo1, &al);
gins(AMOVW, &hi1, &ah);
gins(AMOVW, &lo2, &n1);
gins(optoas(n->op, lo1.type), &n1, &al);
gins(AMOVW, &hi2, &n1);
gins(optoas(n->op, lo1.type), &n1, &ah);
regfree(&n1);
break;
}
if(is64(r->type))
splitclean();
splitclean();
split64(res, &lo1, &hi1);
gins(AMOVW, &al, &lo1);
gins(AMOVW, &ah, &hi1);
splitclean();
//out:
regfree(&al);
regfree(&ah);
}
/*
* generate comparison of nl, nr, both 64-bit.
* nl is memory; nr is constant or memory.
*/
void
cmp64(Node *nl, Node *nr, int op, int likely, Prog *to)
{
Node lo1, hi1, lo2, hi2, r1, r2;
Prog *br;
Type *t;
split64(nl, &lo1, &hi1);
split64(nr, &lo2, &hi2);
// compare most significant word;
// if they differ, we're done.
t = hi1.type;
regalloc(&r1, types[TINT32], N);
regalloc(&r2, types[TINT32], N);
gins(AMOVW, &hi1, &r1);
gins(AMOVW, &hi2, &r2);
gcmp(ACMP, &r1, &r2);
regfree(&r1);
regfree(&r2);
br = P;
switch(op) {
default:
fatal("cmp64 %O %T", op, t);
case OEQ:
// cmp hi
// bne L
// cmp lo
// beq to
// L:
br = gbranch(ABNE, T, -likely);
break;
case ONE:
// cmp hi
// bne to
// cmp lo
// bne to
patch(gbranch(ABNE, T, likely), to);
break;
case OGE:
case OGT:
// cmp hi
// bgt to
// blt L
// cmp lo
// bge to (or bgt to)
// L:
patch(gbranch(optoas(OGT, t), T, likely), to);
br = gbranch(optoas(OLT, t), T, -likely);
break;
case OLE:
case OLT:
// cmp hi
// blt to
// bgt L
// cmp lo
// ble to (or jlt to)
// L:
patch(gbranch(optoas(OLT, t), T, likely), to);
br = gbranch(optoas(OGT, t), T, -likely);
break;
}
// compare least significant word
t = lo1.type;
regalloc(&r1, types[TINT32], N);
regalloc(&r2, types[TINT32], N);
gins(AMOVW, &lo1, &r1);
gins(AMOVW, &lo2, &r2);
gcmp(ACMP, &r1, &r2);
regfree(&r1);
regfree(&r2);
// jump again
patch(gbranch(optoas(op, t), T, likely), to);
// point first branch down here if appropriate
if(br != P)
patch(br, pc);
splitclean();
splitclean();
}

View file

@ -1,15 +0,0 @@
// 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.
// +build ignore
/*
5g is the version of the gc compiler for the ARM.
The $GOARCH for these tools is arm.
It reads .go files and outputs .5 files. The flags are documented in ../gc/doc.go.
*/
package main

View file

@ -1,87 +0,0 @@
// 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.
#include <u.h>
#include <libc.h>
#include "gg.h"
int thechar = '5';
char* thestring = "arm";
LinkArch* thelinkarch = &linkarm;
void
linkarchinit(void)
{
}
vlong MAXWIDTH = (1LL<<32) - 1;
/*
* go declares several platform-specific type aliases:
* int, uint, float, and uintptr
*/
Typedef typedefs[] =
{
{"int", TINT, TINT32},
{"uint", TUINT, TUINT32},
{"uintptr", TUINTPTR, TUINT32},
{0}
};
void
betypeinit(void)
{
widthptr = 4;
widthint = 4;
widthreg = 4;
listinit5();
}
void
main(int argc, char **argv)
{
thearch.thechar = thechar;
thearch.thestring = thestring;
thearch.thelinkarch = thelinkarch;
thearch.typedefs = typedefs;
thearch.REGSP = REGSP;
thearch.REGCTXT = REGCTXT;
thearch.MAXWIDTH = MAXWIDTH;
thearch.anyregalloc = anyregalloc;
thearch.betypeinit = betypeinit;
thearch.bgen = bgen;
thearch.cgen = cgen;
thearch.cgen_call = cgen_call;
thearch.cgen_callinter = cgen_callinter;
thearch.cgen_ret = cgen_ret;
thearch.clearfat = clearfat;
thearch.defframe = defframe;
thearch.excise = excise;
thearch.expandchecks = expandchecks;
thearch.gclean = gclean;
thearch.ginit = ginit;
thearch.gins = gins;
thearch.ginscall = ginscall;
thearch.igen = igen;
thearch.linkarchinit = linkarchinit;
thearch.peep = peep;
thearch.proginfo = proginfo;
thearch.regalloc = regalloc;
thearch.regfree = regfree;
thearch.regtyp = regtyp;
thearch.sameaddr = sameaddr;
thearch.smallindir = smallindir;
thearch.stackaddr = stackaddr;
thearch.excludedregs = excludedregs;
thearch.RtoB = RtoB;
thearch.FtoB = RtoB;
thearch.BtoR = BtoR;
thearch.BtoF = BtoF;
thearch.optoas = optoas;
thearch.doregbits = doregbits;
thearch.regnames = regnames;
gcmain(argc, argv);
}

View file

@ -1,177 +0,0 @@
// 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.
#ifndef EXTERN
#define EXTERN extern
#endif
#include "../gc/go.h"
#include "../5l/5.out.h"
enum
{
REGALLOC_R0 = REG_R0,
REGALLOC_RMAX = REGEXT,
REGALLOC_F0 = REG_F0,
REGALLOC_FMAX = FREGEXT,
};
EXTERN uchar reg[REGALLOC_FMAX+1];
extern long unmappedzero;
/*
* gen.c
*/
void compile(Node*);
void gen(Node*);
Node* lookdot(Node*, Node*, int);
void cgen_as(Node*, Node*);
void cgen_callmeth(Node*, int);
void cgen_callinter(Node*, Node*, int);
void cgen_proc(Node*, int);
void cgen_callret(Node*, Node*);
void cgen_dcl(Node*);
int needconvert(Type*, Type*);
void genconv(Type*, Type*);
void allocparams(void);
void checklabels(void);
void ginscall(Node*, int);
/*
* cgen
*/
void agen(Node*, Node*);
Prog* cgenindex(Node *, Node *, int);
void igen(Node*, Node*, Node*);
void agenr(Node *n, Node *a, Node *res);
vlong fieldoffset(Type*, Node*);
void sgen(Node*, Node*, int64);
void gmove(Node*, Node*);
Prog* gins(int, Node*, Node*);
int samaddr(Node*, Node*);
void raddr(Node *n, Prog *p);
Prog* gcmp(int, Node*, Node*);
Prog* gshift(int as, Node *lhs, int32 stype, int32 sval, Node *rhs);
Prog * gregshift(int as, Node *lhs, int32 stype, Node *reg, Node *rhs);
void naddr(Node*, Addr*, int);
void cgen_aret(Node*, Node*);
void cgen_hmul(Node*, Node*, Node*);
void cgen_shift(int, int, Node*, Node*, Node*);
int componentgen(Node*, Node*);
/*
* cgen64.c
*/
void cmp64(Node*, Node*, int, int, Prog*);
void cgen64(Node*, Node*);
/*
* gsubr.c
*/
void clearp(Prog*);
Prog* gbranch(int, Type*, int);
Prog* prog(int);
void gconv(int, int);
int conv2pt(Type*);
vlong convvtox(vlong, int);
void fnparam(Type*, int, int);
Prog* gop(int, Node*, Node*, Node*);
int optoas(int, Type*);
void ginit(void);
void gclean(void);
void regalloc(Node*, Type*, Node*);
void regfree(Node*);
Node* nodarg(Type*, int);
void nodreg(Node*, Type*, int);
void nodindreg(Node*, Type*, int);
void buildtxt(void);
Plist* newplist(void);
int isfat(Type*);
int dotaddable(Node*, Node*);
void sudoclean(void);
int sudoaddable(int, Node*, Addr*, int*);
void afunclit(Addr*, Node*);
void datagostring(Strlit*, Addr*);
void split64(Node*, Node*, Node*);
void splitclean(void);
Node* ncon(uint32 i);
void gtrack(Sym*);
/*
* obj.c
*/
void datastring(char*, int, Addr*);
/*
* list.c
*/
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_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*);
/*
* reg.c
*/
uint64 excludedregs(void);
uint64 RtoB(int);
uint64 FtoB(int);
int BtoR(uint64);
int BtoF(uint64);
uint64 doregbits(int);
char** regnames(int*);
/*
* peep.c
*/
void peep(Prog*);

View file

@ -1,751 +0,0 @@
// 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.
#undef EXTERN
#define EXTERN
#include <u.h>
#include <libc.h>
#include "gg.h"
#include "../gc/popt.h"
static Prog* appendpp(Prog*, int, int, int, int32, int, int, int32);
static Prog *zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *r0);
void
defframe(Prog *ptxt)
{
uint32 frame, r0;
Prog *p;
vlong hi, lo;
NodeList *l;
Node *n;
// 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
// so that garbage collector only sees initialized values
// when it looks for pointers.
p = ptxt;
lo = hi = 0;
r0 = 0;
for(l=curfn->dcl; l != nil; l = l->next) {
n = l->n;
if(!n->needzero)
continue;
if(n->class != PAUTO)
fatal("needzero class %d", n->class);
if(n->type->width % widthptr != 0 || n->xoffset % widthptr != 0 || n->type->width == 0)
fatal("var %lN has size %d offset %d", n, (int)n->type->width, (int)n->xoffset);
if(lo != hi && n->xoffset + n->type->width >= lo - 2*widthptr) {
// merge with range we already have
lo = rnd(n->xoffset, widthptr);
continue;
}
// zero old range
p = zerorange(p, frame, lo, hi, &r0);
// set new range
hi = n->xoffset + n->type->width;
lo = n->xoffset;
}
// zero final range
zerorange(p, frame, lo, hi, &r0);
}
static Prog*
zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *r0)
{
vlong cnt, i;
Prog *p1;
Node *f;
cnt = hi - lo;
if(cnt == 0)
return p;
if(*r0 == 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, TYPE_REG, REG_R0, 0, TYPE_MEM, REGSP, 4+frame+lo+i);
} else if(!nacl && (cnt <= 128*widthptr)) {
p = appendpp(p, AADD, TYPE_CONST, 0, 4+frame+lo, TYPE_REG, REG_R1, 0);
p->reg = REGSP;
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, TYPE_CONST, 0, 4+frame+lo, TYPE_REG, REG_R1, 0);
p->reg = REGSP;
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, 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;
}
static Prog*
appendpp(Prog *p, int as, int ftype, int freg, int32 foffset, int ttype, int treg, int32 toffset)
{
Prog *q;
q = mal(sizeof(*q));
clearp(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;
return q;
}
/*
* generate:
* call f
* proc=-1 normal call but no return
* proc=0 normal call
* proc=1 goroutine run in new proc
* proc=2 defer call save away stack
* proc=3 normal call to C pointer (not Go func value)
*/
void
ginscall(Node *f, int proc)
{
Prog *p;
Node r, r1, con;
int32 extra;
if(f->type != T) {
extra = 0;
if(proc == 1 || proc == 2)
extra = 2 * widthptr;
setmaxarg(f->type, extra);
}
switch(proc) {
default:
fatal("ginscall: bad proc %d", proc);
break;
case 0: // normal call
case -1: // normal call but no return
if(f->op == ONAME && f->class == PFUNC) {
if(f == deferreturn) {
// Deferred calls will appear to be returning to
// the BL deferreturn(SB) that we are about to emit.
// However, the stack trace code will show the line
// of the instruction before that return PC.
// To avoid that instruction being an unrelated instruction,
// insert a NOP so that we will have the right line number.
// 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], REG_R0);
p = gins(AAND, &r, &r);
p->scond = C_SCOND_EQ;
}
p = gins(ABL, N, f);
afunclit(&p->to, f);
if(proc == -1 || noreturn(p))
gins(AUNDEF, N, N);
break;
}
nodreg(&r, types[tptr], REG_R7);
nodreg(&r1, types[tptr], REG_R1);
gmove(f, &r);
r.op = OINDREG;
gmove(&r, &r1);
r.op = OREGISTER;
r1.op = OINDREG;
gins(ABL, &r, &r1);
break;
case 3: // normal call of c function pointer
gins(ABL, N, f);
break;
case 1: // call in new proc (go)
case 2: // deferred call (defer)
regalloc(&r, types[tptr], N);
nodconst(&con, types[TINT32], argsize(f->type));
gins(AMOVW, &con, &r);
p = gins(AMOVW, &r, N);
p->to.type = TYPE_MEM;
p->to.reg = REGSP;
p->to.offset = 4;
gins(AMOVW, f, &r);
p = gins(AMOVW, &r, N);
p->to.type = TYPE_MEM;
p->to.reg = REGSP;
p->to.offset = 8;
regfree(&r);
if(proc == 1)
ginscall(newproc, 0);
else
ginscall(deferproc, 0);
if(proc == 2) {
nodconst(&con, types[TINT32], 0);
p = gins(ACMP, &con, N);
p->reg = REG_R0;
p = gbranch(ABEQ, T, +1);
cgen_ret(N);
patch(p, pc);
}
break;
}
}
/*
* n is call to interface method.
* generate res = n.
*/
void
cgen_callinter(Node *n, Node *res, int proc)
{
int r;
Node *i, *f;
Node tmpi, nodo, nodr, nodsp;
Prog *p;
i = n->left;
if(i->op != ODOTINTER)
fatal("cgen_callinter: not ODOTINTER %O", i->op);
f = i->right; // field
if(f->op != ONAME)
fatal("cgen_callinter: not ONAME %O", f->op);
i = i->left; // interface
// Release res register during genlist and cgen,
// which might have their own function calls.
r = -1;
if(res != N && (res->op == OREGISTER || res->op == OINDREG)) {
r = res->val.u.reg;
reg[r]--;
}
if(!i->addable) {
tempname(&tmpi, i->type);
cgen(i, &tmpi);
i = &tmpi;
}
genlist(n->list); // args
if(r >= 0)
reg[r]++;
regalloc(&nodr, types[tptr], res);
regalloc(&nodo, types[tptr], &nodr);
nodo.op = OINDREG;
agen(i, &nodr); // REG = &inter
nodindreg(&nodsp, types[tptr], REGSP);
nodsp.xoffset = widthptr;
if(proc != 0)
nodsp.xoffset += 2 * widthptr; // leave room for size & fn
nodo.xoffset += widthptr;
cgen(&nodo, &nodsp); // {4 or 12}(SP) = 4(REG) -- i.data
nodo.xoffset -= widthptr;
cgen(&nodo, &nodr); // REG = 0(REG) -- i.tab
cgen_checknil(&nodr); // in case offset is huge
nodo.xoffset = n->left->xoffset + 3*widthptr + 8;
if(proc == 0) {
// plain call: use direct c function pointer - more efficient
cgen(&nodo, &nodr); // REG = 20+offset(REG) -- i.tab->fun[f]
nodr.op = OINDREG;
proc = 3;
} else {
// go/defer. generate go func value.
p = gins(AMOVW, &nodo, &nodr);
p->from.type = TYPE_ADDR; // REG = &(20+offset(REG)) -- i.tab->fun[f]
}
nodr.type = n->left->type;
ginscall(&nodr, proc);
regfree(&nodr);
regfree(&nodo);
}
/*
* generate function call;
* proc=0 normal call
* proc=1 goroutine run in new proc
* proc=2 defer call save away stack
*/
void
cgen_call(Node *n, int proc)
{
Type *t;
Node nod, afun;
if(n == N)
return;
if(n->left->ullman >= UINF) {
// if name involves a fn call
// precompute the address of the fn
tempname(&afun, types[tptr]);
cgen(n->left, &afun);
}
genlist(n->list); // assign the args
t = n->left->type;
// call tempname pointer
if(n->left->ullman >= UINF) {
regalloc(&nod, types[tptr], N);
cgen_as(&nod, &afun);
nod.type = t;
ginscall(&nod, proc);
regfree(&nod);
goto ret;
}
// call pointer
if(n->left->op != ONAME || n->left->class != PFUNC) {
regalloc(&nod, types[tptr], N);
cgen_as(&nod, n->left);
nod.type = t;
ginscall(&nod, proc);
regfree(&nod);
goto ret;
}
// call direct
n->left->method = 1;
ginscall(n->left, proc);
ret:
;
}
/*
* call to n has already been generated.
* generate:
* res = return value from call.
*/
void
cgen_callret(Node *n, Node *res)
{
Node nod;
Type *fp, *t;
Iter flist;
t = n->left->type;
if(t->etype == TPTR32 || t->etype == TPTR64)
t = t->type;
fp = structfirst(&flist, getoutarg(t));
if(fp == T)
fatal("cgen_callret: nil");
memset(&nod, 0, sizeof(nod));
nod.op = OINDREG;
nod.val.u.reg = REGSP;
nod.addable = 1;
nod.xoffset = fp->width + 4; // +4: saved lr at 0(SP)
nod.type = fp->type;
cgen_as(res, &nod);
}
/*
* call to n has already been generated.
* generate:
* res = &return value from call.
*/
void
cgen_aret(Node *n, Node *res)
{
Node nod1, nod2;
Type *fp, *t;
Iter flist;
t = n->left->type;
if(isptr[t->etype])
t = t->type;
fp = structfirst(&flist, getoutarg(t));
if(fp == T)
fatal("cgen_aret: nil");
memset(&nod1, 0, sizeof(nod1));
nod1.op = OINDREG;
nod1.val.u.reg = REGSP;
nod1.addable = 1;
nod1.xoffset = fp->width + 4; // +4: saved lr at 0(SP)
nod1.type = fp->type;
if(res->op != OREGISTER) {
regalloc(&nod2, types[tptr], res);
agen(&nod1, &nod2);
gins(AMOVW, &nod2, res);
regfree(&nod2);
} else
agen(&nod1, res);
}
/*
* generate return.
* n->left is assignments to return values.
*/
void
cgen_ret(Node *n)
{
Prog *p;
if(n != N)
genlist(n->list); // copy out args
if(hasdefer)
ginscall(deferreturn, 0);
genlist(curfn->exit);
p = gins(ARET, N, N);
if(n != N && n->op == ORETJMP) {
p->to.name = NAME_EXTERN;
p->to.type = TYPE_ADDR;
p->to.sym = linksym(n->left->sym);
}
}
/*
* generate high multiply
* res = (nl * nr) >> wordsize
*/
void
cgen_hmul(Node *nl, Node *nr, Node *res)
{
int w;
Node n1, n2, *tmp;
Type *t;
Prog *p;
if(nl->ullman < nr->ullman) {
tmp = nl;
nl = nr;
nr = tmp;
}
t = nl->type;
w = t->width * 8;
regalloc(&n1, t, res);
cgen(nl, &n1);
regalloc(&n2, t, N);
cgen(nr, &n2);
switch(simtype[t->etype]) {
case TINT8:
case TINT16:
gins(optoas(OMUL, t), &n2, &n1);
gshift(AMOVW, &n1, SHIFT_AR, w, &n1);
break;
case TUINT8:
case TUINT16:
gins(optoas(OMUL, t), &n2, &n1);
gshift(AMOVW, &n1, SHIFT_LR, w, &n1);
break;
case TINT32:
case TUINT32:
// perform a long multiplication.
if(issigned[t->etype])
p = gins(AMULL, &n2, N);
else
p = gins(AMULLU, &n2, N);
// n2 * n1 -> (n1 n2)
p->reg = n1.val.u.reg;
p->to.type = TYPE_REGREG;
p->to.reg = n1.val.u.reg;
p->to.offset = n2.val.u.reg;
break;
default:
fatal("cgen_hmul %T", t);
break;
}
cgen(&n1, res);
regfree(&n1);
regfree(&n2);
}
/*
* generate shift according to op, one of:
* res = nl << nr
* res = nl >> nr
*/
void
cgen_shift(int op, int bounded, Node *nl, Node *nr, Node *res)
{
Node n1, n2, n3, nt, t, lo, hi;
int w, v;
Prog *p1, *p2, *p3;
Type *tr;
uvlong sc;
USED(bounded);
if(nl->type->width > 4)
fatal("cgen_shift %T", nl->type);
w = nl->type->width * 8;
if(op == OLROT) {
v = mpgetfix(nr->val.u.xval);
regalloc(&n1, nl->type, res);
if(w == 32) {
cgen(nl, &n1);
gshift(AMOVW, &n1, SHIFT_RR, w-v, &n1);
} else {
regalloc(&n2, nl->type, N);
cgen(nl, &n2);
gshift(AMOVW, &n2, SHIFT_LL, v, &n1);
gshift(AORR, &n2, SHIFT_LR, w-v, &n1);
regfree(&n2);
// Ensure sign/zero-extended result.
gins(optoas(OAS, nl->type), &n1, &n1);
}
gmove(&n1, res);
regfree(&n1);
return;
}
if(nr->op == OLITERAL) {
regalloc(&n1, nl->type, res);
cgen(nl, &n1);
sc = mpgetfix(nr->val.u.xval);
if(sc == 0) {
// nothing to do
} else if(sc >= nl->type->width*8) {
if(op == ORSH && issigned[nl->type->etype])
gshift(AMOVW, &n1, SHIFT_AR, w, &n1);
else
gins(AEOR, &n1, &n1);
} else {
if(op == ORSH && issigned[nl->type->etype])
gshift(AMOVW, &n1, SHIFT_AR, sc, &n1);
else if(op == ORSH)
gshift(AMOVW, &n1, SHIFT_LR, sc, &n1);
else // OLSH
gshift(AMOVW, &n1, SHIFT_LL, sc, &n1);
}
if(w < 32 && op == OLSH)
gins(optoas(OAS, nl->type), &n1, &n1);
gmove(&n1, res);
regfree(&n1);
return;
}
tr = nr->type;
if(tr->width > 4) {
tempname(&nt, nr->type);
if(nl->ullman >= nr->ullman) {
regalloc(&n2, nl->type, res);
cgen(nl, &n2);
cgen(nr, &nt);
n1 = nt;
} else {
cgen(nr, &nt);
regalloc(&n2, nl->type, res);
cgen(nl, &n2);
}
split64(&nt, &lo, &hi);
regalloc(&n1, types[TUINT32], N);
regalloc(&n3, types[TUINT32], N);
gmove(&lo, &n1);
gmove(&hi, &n3);
splitclean();
gins(ATST, &n3, N);
nodconst(&t, types[TUINT32], w);
p1 = gins(AMOVW, &t, &n1);
p1->scond = C_SCOND_NE;
tr = types[TUINT32];
regfree(&n3);
} else {
if(nl->ullman >= nr->ullman) {
regalloc(&n2, nl->type, res);
cgen(nl, &n2);
regalloc(&n1, nr->type, N);
cgen(nr, &n1);
} else {
regalloc(&n1, nr->type, N);
cgen(nr, &n1);
regalloc(&n2, nl->type, res);
cgen(nl, &n2);
}
}
// test for shift being 0
gins(ATST, &n1, N);
p3 = gbranch(ABEQ, T, -1);
// test and fix up large shifts
// TODO: if(!bounded), don't emit some of this.
regalloc(&n3, tr, N);
nodconst(&t, types[TUINT32], w);
gmove(&t, &n3);
gcmp(ACMP, &n1, &n3);
if(op == ORSH) {
if(issigned[nl->type->etype]) {
p1 = gshift(AMOVW, &n2, SHIFT_AR, w-1, &n2);
p2 = gregshift(AMOVW, &n2, SHIFT_AR, &n1, &n2);
} else {
p1 = gins(AEOR, &n2, &n2);
p2 = gregshift(AMOVW, &n2, SHIFT_LR, &n1, &n2);
}
p1->scond = C_SCOND_HS;
p2->scond = C_SCOND_LO;
} else {
p1 = gins(AEOR, &n2, &n2);
p2 = gregshift(AMOVW, &n2, SHIFT_LL, &n1, &n2);
p1->scond = C_SCOND_HS;
p2->scond = C_SCOND_LO;
}
regfree(&n3);
patch(p3, pc);
// Left-shift of smaller word must be sign/zero-extended.
if(w < 32 && op == OLSH)
gins(optoas(OAS, nl->type), &n2, &n2);
gmove(&n2, res);
regfree(&n1);
regfree(&n2);
}
void
clearfat(Node *nl)
{
uint32 w, c, q;
Node dst, nc, nz, end, r0, r1, *f;
Prog *p, *pl;
/* clear a fat object */
if(debug['g'])
dump("\nclearfat", nl);
w = nl->type->width;
// Avoid taking the address for simple enough types.
if(componentgen(N, nl))
return;
c = w % 4; // bytes
q = w / 4; // quads
r0.op = OREGISTER;
r0.val.u.reg = REGALLOC_R0;
r1.op = OREGISTER;
r1.val.u.reg = REGALLOC_R0 + 1;
regalloc(&dst, types[tptr], &r1);
agen(nl, &dst);
nodconst(&nc, types[TUINT32], 0);
regalloc(&nz, types[TUINT32], &r0);
cgen(&nc, &nz);
if(q > 128) {
regalloc(&end, types[tptr], N);
p = gins(AMOVW, &dst, &end);
p->from.type = TYPE_ADDR;
p->from.offset = q*4;
p = gins(AMOVW, &nz, &dst);
p->to.type = TYPE_MEM;
p->to.offset = 4;
p->scond |= C_PBIT;
pl = p;
p = gins(ACMP, &dst, N);
raddr(&end, p);
patch(gbranch(ABNE, T, 0), pl);
regfree(&end);
} else if(q >= 4 && !nacl) {
f = sysfunc("duffzero");
p = gins(ADUFFZERO, N, f);
afunclit(&p->to, f);
// 4 and 128 = magic constants: see ../../runtime/asm_arm.s
p->to.offset = 4*(128-q);
} else
while(q > 0) {
p = gins(AMOVW, &nz, &dst);
p->to.type = TYPE_MEM;
p->to.offset = 4;
p->scond |= C_PBIT;
//print("1. %P\n", p);
q--;
}
while(c > 0) {
p = gins(AMOVB, &nz, &dst);
p->to.type = TYPE_MEM;
p->to.offset = 1;
p->scond |= C_PBIT;
//print("2. %P\n", p);
c--;
}
regfree(&dst);
regfree(&nz);
}
// Called after regopt and peep have run.
// Expand CHECKNIL pseudo-op into actual nil pointer check.
void
expandchecks(Prog *firstp)
{
int reg;
Prog *p, *p1;
for(p = firstp; p != P; p = p->link) {
if(p->as != ACHECKNIL)
continue;
if(debug_checknil && p->lineno > 1) // p->lineno==1 in generated wrappers
warnl(p->lineno, "generated nil check");
if(p->from.type != TYPE_REG)
fatal("invalid nil check %P", p);
reg = p->from.reg;
// check is
// CMP arg, $0
// MOV.EQ arg, 0(arg)
p1 = mal(sizeof *p1);
clearp(p1);
p1->link = p->link;
p->link = p1;
p1->lineno = p->lineno;
p1->pc = 9999;
p1->as = AMOVW;
p1->from.type = TYPE_REG;
p1->from.reg = reg;
p1->to.type = TYPE_MEM;
p1->to.reg = reg;
p1->to.offset = 0;
p1->scond = C_SCOND_EQ;
p->as = ACMP;
p->from.type = TYPE_CONST;
p->from.reg = 0;
p->from.offset = 0;
p->reg = reg;
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,160 +0,0 @@
// 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.
#include <u.h>
#include <libc.h>
#include "gg.h"
#include "../gc/popt.h"
enum
{
RightRdwr = RightRead | RightWrite,
};
// This table gives the basic information about instruction
// generated by the compiler and processed in the optimizer.
// See opt.h for bit definitions.
//
// Instructions not generated need not be listed.
// As an exception to that rule, we typically write down all the
// size variants of an operation even if we just use a subset.
//
// The table is formatted for 8-space tabs.
static ProgInfo progtable[ALAST] = {
[ATYPE]= {Pseudo | Skip},
[ATEXT]= {Pseudo},
[AFUNCDATA]= {Pseudo},
[APCDATA]= {Pseudo},
[AUNDEF]= {Break},
[AUSEFIELD]= {OK},
[ACHECKNIL]= {LeftRead},
[AVARDEF]= {Pseudo | RightWrite},
[AVARKILL]= {Pseudo | RightWrite},
// NOP is an internal no-op that also stands
// for USED and SET annotations, not the Intel opcode.
[ANOP]= {LeftRead | RightWrite},
// Integer.
[AADC]= {SizeL | LeftRead | RegRead | RightWrite},
[AADD]= {SizeL | LeftRead | RegRead | RightWrite},
[AAND]= {SizeL | LeftRead | RegRead | RightWrite},
[ABIC]= {SizeL | LeftRead | RegRead | RightWrite},
[ACMN]= {SizeL | LeftRead | RightRead},
[ACMP]= {SizeL | LeftRead | RightRead},
[ADIVU]= {SizeL | LeftRead | RegRead | RightWrite},
[ADIV]= {SizeL | LeftRead | RegRead | RightWrite},
[AEOR]= {SizeL | LeftRead | RegRead | RightWrite},
[AMODU]= {SizeL | LeftRead | RegRead | RightWrite},
[AMOD]= {SizeL | LeftRead | RegRead | RightWrite},
[AMULALU]= {SizeL | LeftRead | RegRead | RightRdwr},
[AMULAL]= {SizeL | LeftRead | RegRead | RightRdwr},
[AMULA]= {SizeL | LeftRead | RegRead | RightRdwr},
[AMULU]= {SizeL | LeftRead | RegRead | RightWrite},
[AMUL]= {SizeL | LeftRead | RegRead | RightWrite},
[AMULL]= {SizeL | LeftRead | RegRead | RightWrite},
[AMULLU]= {SizeL | LeftRead | RegRead | RightWrite},
[AMVN]= {SizeL | LeftRead | RightWrite},
[AORR]= {SizeL | LeftRead | RegRead | RightWrite},
[ARSB]= {SizeL | LeftRead | RegRead | RightWrite},
[ARSC]= {SizeL | LeftRead | RegRead | RightWrite},
[ASBC]= {SizeL | LeftRead | RegRead | RightWrite},
[ASLL]= {SizeL | LeftRead | RegRead | RightWrite},
[ASRA]= {SizeL | LeftRead | RegRead | RightWrite},
[ASRL]= {SizeL | LeftRead | RegRead | RightWrite},
[ASUB]= {SizeL | LeftRead | RegRead | RightWrite},
[ATEQ]= {SizeL | LeftRead | RightRead},
[ATST]= {SizeL | LeftRead | RightRead},
// Floating point.
[AADDD]= {SizeD | LeftRead | RightRdwr},
[AADDF]= {SizeF | LeftRead | RightRdwr},
[ACMPD]= {SizeD | LeftRead | RightRead},
[ACMPF]= {SizeF | LeftRead | RightRead},
[ADIVD]= {SizeD | LeftRead | RightRdwr},
[ADIVF]= {SizeF | LeftRead | RightRdwr},
[AMULD]= {SizeD | LeftRead | RightRdwr},
[AMULF]= {SizeF | LeftRead | RightRdwr},
[ASUBD]= {SizeD | LeftRead | RightRdwr},
[ASUBF]= {SizeF | LeftRead | RightRdwr},
// Conversions.
[AMOVWD]= {SizeD | LeftRead | RightWrite | Conv},
[AMOVWF]= {SizeF | LeftRead | RightWrite | Conv},
[AMOVDF]= {SizeF | LeftRead | RightWrite | Conv},
[AMOVDW]= {SizeL | LeftRead | RightWrite | Conv},
[AMOVFD]= {SizeD | LeftRead | RightWrite | Conv},
[AMOVFW]= {SizeL | LeftRead | RightWrite | Conv},
// Moves.
[AMOVB]= {SizeB | LeftRead | RightWrite | Move},
[AMOVD]= {SizeD | LeftRead | RightWrite | Move},
[AMOVF]= {SizeF | LeftRead | RightWrite | Move},
[AMOVH]= {SizeW | LeftRead | RightWrite | Move},
[AMOVW]= {SizeL | LeftRead | RightWrite | Move},
// In addtion, duffzero reads R0,R1 and writes R1. This fact is
// encoded in peep.c
[ADUFFZERO]= {Call},
// In addtion, duffcopy reads R1,R2 and writes R0,R1,R2. This fact is
// encoded in peep.c
[ADUFFCOPY]= {Call},
// These should be split into the two different conversions instead
// of overloading the one.
[AMOVBS]= {SizeB | LeftRead | RightWrite | Conv},
[AMOVBU]= {SizeB | LeftRead | RightWrite | Conv},
[AMOVHS]= {SizeW | LeftRead | RightWrite | Conv},
[AMOVHU]= {SizeW | LeftRead | RightWrite | Conv},
// Jumps.
[AB]= {Jump | Break},
[ABL]= {Call},
[ABEQ]= {Cjmp},
[ABNE]= {Cjmp},
[ABCS]= {Cjmp},
[ABHS]= {Cjmp},
[ABCC]= {Cjmp},
[ABLO]= {Cjmp},
[ABMI]= {Cjmp},
[ABPL]= {Cjmp},
[ABVS]= {Cjmp},
[ABVC]= {Cjmp},
[ABHI]= {Cjmp},
[ABLS]= {Cjmp},
[ABGE]= {Cjmp},
[ABLT]= {Cjmp},
[ABGT]= {Cjmp},
[ABLE]= {Cjmp},
[ARET]= {Break},
};
void
proginfo(ProgInfo *info, Prog *p)
{
*info = progtable[p->as];
if(info->flags == 0)
fatal("unknown instruction %P", p);
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 == 0) {
info->flags &= ~RegRead;
info->flags |= CanRegRead | RightRead;
}
if(((p->scond & C_SCOND) != C_SCOND_NONE) && (info->flags & RightWrite))
info->flags |= RightRead;
switch(p->as) {
case ADIV:
case ADIVU:
case AMOD:
case AMODU:
info->regset |= RtoB(REG_R12);
break;
}
}

View file

@ -1,146 +0,0 @@
// Inferno utils/5c/reg.c
// http://code.google.com/p/inferno-os/source/browse/utils/5c/reg.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <u.h>
#include <libc.h>
#include "gg.h"
#include "../gc/popt.h"
enum {
NREGVAR = 32,
};
static char* regname[] = {
".R0",
".R1",
".R2",
".R3",
".R4",
".R5",
".R6",
".R7",
".R8",
".R9",
".R10",
".R11",
".R12",
".R13",
".R14",
".R15",
".F0",
".F1",
".F2",
".F3",
".F4",
".F5",
".F6",
".F7",
".F8",
".F9",
".F10",
".F11",
".F12",
".F13",
".F14",
".F15",
};
char**
regnames(int *n)
{
*n = NREGVAR;
return regname;
}
uint64
excludedregs(void)
{
return RtoB(REGSP)|RtoB(REGLINK)|RtoB(REGPC);
}
uint64
doregbits(int r)
{
USED(r);
return 0;
}
/*
* bit reg
* 0 R0
* 1 R1
* ... ...
* 10 R10
* 12 R12
*
* bit reg
* 18 F2
* 19 F3
* ... ...
* 31 F15
*/
uint64
RtoB(int 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 1ULL << (r - REG_R0);
}
if(REG_F0 <= r && r <= REG_F15) {
if(r < REG_F2 || r > REG_F0+NFREG-1)
return 0;
return 1ULL << ((r - REG_F0) + 16);
}
return 0;
}
int
BtoR(uint64 b)
{
// TODO Allow R0 and R1, but be careful with a 0 return
// TODO Allow R9. Only R10 is reserved now (just g, not m).
b &= 0x11fcL; // excluded R9 and R10 for m and g, but not R12
if(b == 0)
return 0;
return bitno(b) + REG_R0;
}
int
BtoF(uint64 b)
{
b &= 0xfffc0000L;
if(b == 0)
return 0;
return bitno(b) - 16 + REG_F0;
}

View file

@ -1,10 +0,0 @@
# Copyright 2012 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.
include ../../Make.dist
install: y.tab.h
y.tab.h: a.y
LANG=C LANGUAGE=en_US.UTF8 bison -d -v -y a.y

View file

@ -1,188 +0,0 @@
// Inferno utils/6a/a.h
// http://code.google.com/p/inferno-os/source/browse/utils/6a/a.h
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <bio.h>
#include <link.h>
#include "../6l/6.out.h"
#ifndef EXTERN
#define EXTERN extern
#endif
#undef getc
#undef ungetc
#undef BUFSIZ
#define getc ccgetc
#define ungetc ccungetc
typedef struct Sym Sym;
typedef struct Ref Ref;
typedef struct Io Io;
typedef struct Addr2 Addr2;
#define MAXALIGN 7
#define FPCHIP 1
#define NSYMB 500
#define BUFSIZ 8192
#define HISTSZ 20
#ifndef EOF
#define EOF (-1)
#endif
#define IGN (-2)
#define GETC() ((--fi.c < 0)? filbuf(): *fi.p++ & 0xff)
#define NHASH 503
#define STRINGSZ 200
#define NMACRO 10
struct Sym
{
Sym* link;
Ref* ref;
char* macro;
vlong value;
ushort type;
char *name;
char* labelname;
char sym;
};
#define S ((Sym*)0)
struct Ref
{
int class;
};
EXTERN struct
{
char* p;
int c;
} fi;
struct Io
{
Io* link;
char b[BUFSIZ];
char* p;
short c;
short f;
};
#define I ((Io*)0)
struct Addr2
{
Addr from;
Addr to;
};
enum
{
CLAST,
CMACARG,
CMACRO,
CPREPROC,
};
EXTERN int debug[256];
EXTERN Sym* hash[NHASH];
EXTERN char** Dlist;
EXTERN int nDlist;
EXTERN int newflag;
EXTERN char* hunk;
EXTERN char** include;
EXTERN Io* iofree;
EXTERN Io* ionext;
EXTERN Io* iostack;
EXTERN int32 lineno;
EXTERN int nerrors;
EXTERN int32 nhunk;
EXTERN int ninclude;
EXTERN int32 nsymb;
EXTERN Addr nullgen;
EXTERN char* outfile;
EXTERN int pass;
EXTERN int32 pc;
EXTERN int peekc;
EXTERN int32 stmtline;
EXTERN int sym;
EXTERN char* symb;
EXTERN int thechar;
EXTERN char* thestring;
EXTERN int32 thunk;
EXTERN Biobuf obuf;
EXTERN Link* ctxt;
EXTERN Biobuf bstdout;
EXTERN Prog* lastpc;
void* alloc(int32);
void* allocn(void*, int32, int32);
void ensuresymb(int32);
void errorexit(void);
void pushio(void);
void newio(void);
void newfile(char*, int);
Sym* slookup(char*);
Sym* lookup(void);
Sym* labellookup(Sym*);
void settext(LSym*);
void syminit(Sym*);
int32 yylex(void);
int getc(void);
int getnsc(void);
void unget(int);
int escchar(int);
void cinit(void);
void checkscale(int);
void pinit(char*);
void cclean(void);
int isreg(Addr*);
void outcode(int, Addr2*);
void outhist(void);
void zaddr(Addr*, int);
void zname(char*, int, int);
int filbuf(void);
Sym* getsym(void);
void domacro(void);
void macund(void);
void macdef(void);
void macexpand(Sym*, char*);
void macinc(void);
void macprag(void);
void maclin(void);
void macif(int);
void macend(void);
void dodefine(char*);
void prfile(int32);
void linehist(char*, int);
void gethunk(void);
void yyerror(char*, ...);
int yyparse(void);
void setinclude(char*);
int assemble(char*);

View file

@ -29,20 +29,24 @@
// THE SOFTWARE.
%{
#include <u.h>
#include <stdio.h> /* if we don't, bison will, and a.h re-#defines getc */
#include <libc.h>
#include "a.h"
#include "../../runtime/funcdata.h"
package main
import (
"cmd/internal/asm"
"cmd/internal/obj"
"cmd/internal/obj/x86"
)
%}
%union {
Sym *sym;
vlong lval;
double dval;
char sval[8];
Addr addr;
Addr2 addr2;
sym *asm.Sym
lval int64
dval float64
sval string
addr obj.Addr
addr2 Addr2
}
%left '|'
%left '^'
%left '&'
@ -58,7 +62,7 @@
%token <sval> LSCONST LSP
%token <sym> LNAME LLAB LVAR
%type <lval> con expr pointer offset
%type <addr> mem imm reg nam rel rem rim rom omem nmem textsize
%type <addr> mem imm textsize reg nam rel rem rim rom omem nmem
%type <addr2> nonnon nonrel nonrem rimnon rimrem remrim
%type <addr2> spec3 spec4 spec5 spec6 spec7 spec8 spec9
%type <addr2> spec10 spec12 spec13
@ -66,18 +70,19 @@
prog:
| prog
{
stmtline = lineno;
stmtline = asm.Lineno;
}
line
line:
LNAME ':'
{
$1 = labellookup($1);
if($1->type == LLAB && $1->value != pc)
yyerror("redeclaration of %s (%s)", $1->labelname, $1->name);
$1->type = LLAB;
$1->value = pc;
$1 = asm.LabelLookup($1);
if $1.Type == LLAB && $1.Value != int64(asm.PC) {
yyerror("redeclaration of %s (%s)", $1.Labelname, $1.Name);
}
$1.Type = LLAB;
$1.Value = int64(asm.PC)
}
line
| ';'
@ -87,34 +92,35 @@ line:
inst:
LNAME '=' expr
{
$1->type = LVAR;
$1->value = $3;
$1.Type = LVAR;
$1.Value = $3;
}
| LVAR '=' expr
{
if($1->value != $3)
yyerror("redeclaration of %s", $1->name);
$1->value = $3;
if $1.Value != $3 {
yyerror("redeclaration of %s", $1.Name);
}
| LTYPE0 nonnon { outcode($1, &$2); }
| LTYPE1 nonrem { outcode($1, &$2); }
| LTYPE2 rimnon { outcode($1, &$2); }
| LTYPE3 rimrem { outcode($1, &$2); }
| LTYPE4 remrim { outcode($1, &$2); }
| LTYPER nonrel { outcode($1, &$2); }
$1.Value = $3;
}
| LTYPE0 nonnon { outcode(int($1), &$2); }
| LTYPE1 nonrem { outcode(int($1), &$2); }
| LTYPE2 rimnon { outcode(int($1), &$2); }
| LTYPE3 rimrem { outcode(int($1), &$2); }
| LTYPE4 remrim { outcode(int($1), &$2); }
| LTYPER nonrel { outcode(int($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); }
| LTYPEXC spec8 { outcode($1, &$2); }
| LTYPEX spec9 { outcode($1, &$2); }
| LTYPERT spec10 { outcode($1, &$2); }
| LTYPEC spec3 { outcode(int($1), &$2); }
| LTYPEN spec4 { outcode(int($1), &$2); }
| LTYPES spec5 { outcode(int($1), &$2); }
| LTYPEM spec6 { outcode(int($1), &$2); }
| LTYPEI spec7 { outcode(int($1), &$2); }
| LTYPEXC spec8 { outcode(int($1), &$2); }
| LTYPEX spec9 { outcode(int($1), &$2); }
| LTYPERT spec10 { outcode(int($1), &$2); }
| spec11
| LTYPEPC spec12 { outcode($1, &$2); }
| LTYPEF spec13 { outcode($1, &$2); }
| LTYPEPC spec12 { outcode(int($1), &$2); }
| LTYPEF spec13 { outcode(int($1), &$2); }
nonnon:
{
@ -185,57 +191,45 @@ nonrel:
spec1: /* DATA */
LTYPED nam '/' con ',' imm
{
Addr2 a;
a.from = $2;
a.to = $6;
outcode(ADATA, &a);
if(pass > 1) {
lastpc->from3.type = TYPE_CONST;
lastpc->from3.offset = $4;
var a Addr2
a.from = $2
a.to = $6
outcode(obj.ADATA, &a)
if asm.Pass > 1 {
lastpc.From3.Type = obj.TYPE_CONST
lastpc.From3.Offset = $4
}
}
spec2: /* TEXT */
LTYPET mem ',' '$' textsize
{
Addr2 a;
settext($2.sym);
a.from = $2;
a.to = $5;
outcode(ATEXT, &a);
asm.Settext($2.Sym);
outcode(obj.ATEXT, &Addr2{$2, $5})
}
| LTYPET mem ',' con ',' '$' textsize
{
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;
asm.Settext($2.Sym);
outcode(obj.ATEXT, &Addr2{$2, $7})
if asm.Pass > 1 {
lastpc.From3.Type = obj.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);
asm.Settext($2.Sym)
outcode(obj.AGLOBL, &Addr2{$2, $4})
}
| 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;
asm.Settext($2.Sym)
outcode(obj.AGLOBL, &Addr2{$2, $6})
if asm.Pass > 1 {
lastpc.From3.Type = obj.TYPE_CONST
lastpc.From3.Offset = $4
}
}
@ -265,9 +259,10 @@ spec5: /* SHL/SHR */
{
$$.from = $1;
$$.to = $3;
if($$.from.index != TYPE_NONE)
if $$.from.Index != obj.TYPE_NONE {
yyerror("dp shift with lhs index");
$$.from.index = $5;
}
$$.from.Index = int16($5);
}
spec6: /* MOVW/MOVL */
@ -280,9 +275,10 @@ spec6: /* MOVW/MOVL */
{
$$.from = $1;
$$.to = $3;
if($$.to.index != TYPE_NONE)
if $$.to.Index != obj.TYPE_NONE {
yyerror("dp move with lhs index");
$$.to.index = $5;
}
$$.to.Index = int16($5);
}
spec7:
@ -307,7 +303,7 @@ spec8: /* CMPPS/CMPPD */
{
$$.from = $1;
$$.to = $3;
$$.to.offset = $5;
$$.to.Offset = $5;
}
spec9: /* shufl */
@ -315,9 +311,10 @@ spec9: /* shufl */
{
$$.from = $3;
$$.to = $5;
if($1.type != TYPE_CONST)
if $1.Type != obj.TYPE_CONST {
yyerror("illegal constant");
$$.to.offset = $1.offset;
}
$$.to.Offset = $1.Offset;
}
spec10: /* RET/RETF */
@ -331,11 +328,12 @@ spec10: /* RET/RETF */
$$.to = nullgen;
}
spec12: /* PCDATA */
spec12: /* asm.PCDATA */
rim ',' rim
{
if($1.type != TYPE_CONST || $3.type != TYPE_CONST)
yyerror("arguments to PCDATA must be integer constants");
if $1.Type != obj.TYPE_CONST || $3.Type != obj.TYPE_CONST {
yyerror("arguments to asm.PCDATA must be integer constants");
}
$$.from = $1;
$$.to = $3;
}
@ -343,10 +341,12 @@ spec12: /* PCDATA */
spec13: /* FUNCDATA */
rim ',' rim
{
if($1.type != TYPE_CONST)
if $1.Type != obj.TYPE_CONST {
yyerror("index for FUNCDATA must be integer constant");
if($3.type != TYPE_MEM || ($3.name != NAME_EXTERN && $3.name != NAME_STATIC))
}
if $3.Type != obj.TYPE_MEM || ($3.Name != obj.NAME_EXTERN && $3.Name != obj.NAME_STATIC) {
yyerror("value for FUNCDATA must be symbol reference");
}
$$.from = $1;
$$.to = $3;
}
@ -377,109 +377,110 @@ rel:
con '(' LPC ')'
{
$$ = nullgen;
$$.type = TYPE_BRANCH;
$$.offset = $1 + pc;
$$.Type = obj.TYPE_BRANCH;
$$.Offset = $1 + int64(asm.PC);
}
| LNAME offset
{
$1 = labellookup($1);
$1 = asm.LabelLookup($1);
$$ = nullgen;
if(pass == 2 && $1->type != LLAB)
yyerror("undefined label: %s", $1->labelname);
$$.type = TYPE_BRANCH;
$$.offset = $1->value + $2;
if asm.Pass == 2 && $1.Type != LLAB {
yyerror("undefined label: %s", $1.Labelname);
}
$$.Type = obj.TYPE_BRANCH;
$$.Offset = $1.Value + $2;
}
reg:
LBREG
{
$$ = nullgen;
$$.type = TYPE_REG;
$$.reg = $1;
$$.Type = obj.TYPE_REG
$$.Reg = int16($1);
}
| LFREG
{
$$ = nullgen;
$$.type = TYPE_REG;
$$.reg = $1;
$$.Type = obj.TYPE_REG
$$.Reg = int16($1);
}
| LLREG
{
$$ = nullgen;
$$.type = TYPE_REG;
$$.reg = $1;
$$.Type = obj.TYPE_REG
$$.Reg = int16($1);
}
| LMREG
{
$$ = nullgen;
$$.type = TYPE_REG;
$$.reg = $1;
$$.Type = obj.TYPE_REG
$$.Reg = int16($1);
}
| LSP
{
$$ = nullgen;
$$.type = TYPE_REG;
$$.reg = REG_SP;
$$.Type = obj.TYPE_REG
$$.Reg = x86.REG_SP;
}
| LSREG
{
$$ = nullgen;
$$.type = TYPE_REG;
$$.reg = $1;
$$.Type = obj.TYPE_REG
$$.Reg = int16($1);
}
| LXREG
{
$$ = nullgen;
$$.type = TYPE_REG;
$$.reg = $1;
$$.Type = obj.TYPE_REG
$$.Reg = int16($1);
}
imm:
'$' con
{
$$ = nullgen;
$$.type = TYPE_CONST;
$$.offset = $2;
$$.Type = obj.TYPE_CONST;
$$.Offset = $2;
}
| '$' nam
{
$$ = $2;
$$.type = TYPE_ADDR;
$$.Type = obj.TYPE_ADDR;
/*
if($2.type == D_AUTO || $2.type == D_PARAM)
if($2.Type == x86.D_AUTO || $2.Type == x86.D_PARAM)
yyerror("constant cannot be automatic: %s",
$2.sym->name);
$2.sym.Name);
*/
}
| '$' LSCONST
{
$$ = nullgen;
$$.type = TYPE_SCONST;
memcpy($$.u.sval, $2, sizeof($$.u.sval));
$$.Type = obj.TYPE_SCONST;
$$.U.Sval = ($2+"\x00\x00\x00\x00\x00\x00\x00\x00")[:8]
}
| '$' LFCONST
{
$$ = nullgen;
$$.type = TYPE_FCONST;
$$.u.dval = $2;
$$.Type = obj.TYPE_FCONST;
$$.U.Dval = $2;
}
| '$' '(' LFCONST ')'
{
$$ = nullgen;
$$.type = TYPE_FCONST;
$$.u.dval = $3;
$$.Type = obj.TYPE_FCONST;
$$.U.Dval = $3;
}
| '$' '(' '-' LFCONST ')'
{
$$ = nullgen;
$$.type = TYPE_FCONST;
$$.u.dval = -$4;
$$.Type = obj.TYPE_FCONST;
$$.U.Dval = -$4;
}
| '$' '-' LFCONST
{
$$ = nullgen;
$$.type = TYPE_FCONST;
$$.u.dval = -$3;
$$.Type = obj.TYPE_FCONST;
$$.U.Dval = -$3;
}
mem:
@ -490,87 +491,87 @@ omem:
con
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.offset = $1;
$$.Type = obj.TYPE_MEM
$$.Offset = $1;
}
| con '(' LLREG ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.reg = $3;
$$.offset = $1;
$$.Type = obj.TYPE_MEM
$$.Reg = int16($3)
$$.Offset = $1;
}
| con '(' LSP ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.reg = REG_SP;
$$.offset = $1;
$$.Type = obj.TYPE_MEM
$$.Reg = x86.REG_SP
$$.Offset = $1;
}
| con '(' LSREG ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.reg = $3;
$$.offset = $1;
$$.Type = obj.TYPE_MEM
$$.Reg = int16($3)
$$.Offset = $1;
}
| con '(' LLREG '*' con ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.offset = $1;
$$.index = $3;
$$.scale = $5;
checkscale($$.scale);
$$.Type = obj.TYPE_MEM
$$.Offset = $1;
$$.Index = int16($3);
$$.Scale = int8($5);
checkscale($$.Scale);
}
| con '(' LLREG ')' '(' LLREG '*' con ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.reg = $3;
$$.offset = $1;
$$.index = $6;
$$.scale = $8;
checkscale($$.scale);
$$.Type = obj.TYPE_MEM
$$.Reg = int16($3)
$$.Offset = $1;
$$.Index = int16($6);
$$.Scale = int8($8);
checkscale($$.Scale);
}
| con '(' LLREG ')' '(' LSREG '*' con ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.reg = $3;
$$.offset = $1;
$$.index = $6;
$$.scale = $8;
checkscale($$.scale);
$$.Type = obj.TYPE_MEM
$$.Reg = int16($3)
$$.Offset = $1;
$$.Index = int16($6);
$$.Scale = int8($8);
checkscale($$.Scale);
}
| '(' LLREG ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.reg = $2;
$$.Type = obj.TYPE_MEM
$$.Reg = int16($2)
}
| '(' LSP ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.reg = REG_SP;
$$.Type = obj.TYPE_MEM
$$.Reg = x86.REG_SP
}
| '(' LLREG '*' con ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.index = $2;
$$.scale = $4;
checkscale($$.scale);
$$.Type = obj.TYPE_MEM
$$.Index = int16($2);
$$.Scale = int8($4);
checkscale($$.Scale);
}
| '(' LLREG ')' '(' LLREG '*' con ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.reg = $2;
$$.index = $5;
$$.scale = $7;
checkscale($$.scale);
$$.Type = obj.TYPE_MEM
$$.Reg = int16($2)
$$.Index = int16($5);
$$.Scale = int8($7);
checkscale($$.Scale);
}
nmem:
@ -581,27 +582,27 @@ nmem:
| nam '(' LLREG '*' con ')'
{
$$ = $1;
$$.index = $3;
$$.scale = $5;
checkscale($$.scale);
$$.Index = int16($3);
$$.Scale = int8($5);
checkscale($$.Scale);
}
nam:
LNAME offset '(' pointer ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.name = $4;
$$.sym = linklookup(ctxt, $1->name, 0);
$$.offset = $2;
$$.Type = obj.TYPE_MEM
$$.Name = int8($4)
$$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
$$.Offset = $2;
}
| LNAME '<' '>' offset '(' LSB ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.name = NAME_STATIC;
$$.sym = linklookup(ctxt, $1->name, 1);
$$.offset = $4;
$$.Type = obj.TYPE_MEM
$$.Name = obj.NAME_STATIC
$$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 1);
$$.Offset = $4;
}
offset:
@ -621,7 +622,7 @@ pointer:
LSB
| LSP
{
$$ = NAME_AUTO;
$$ = obj.NAME_AUTO;
}
| LFP
@ -629,7 +630,7 @@ con:
LCONST
| LVAR
{
$$ = $1->value;
$$ = $1.Value;
}
| '-' con
{
@ -641,7 +642,7 @@ con:
}
| '~' con
{
$$ = ~$2;
$$ = ^$2;
}
| '(' expr ')'
{
@ -652,30 +653,30 @@ textsize:
LCONST
{
$$ = nullgen;
$$.type = TYPE_TEXTSIZE;
$$.offset = $1;
$$.u.argsize = ArgsSizeUnknown;
$$.Type = obj.TYPE_TEXTSIZE;
$$.Offset = $1;
$$.U.Argsize = obj.ArgsSizeUnknown;
}
| '-' LCONST
{
$$ = nullgen;
$$.type = TYPE_TEXTSIZE;
$$.offset = -$2;
$$.u.argsize = ArgsSizeUnknown;
$$.Type = obj.TYPE_TEXTSIZE;
$$.Offset = -$2;
$$.U.Argsize = obj.ArgsSizeUnknown;
}
| LCONST '-' LCONST
{
$$ = nullgen;
$$.type = TYPE_TEXTSIZE;
$$.offset = $1;
$$.u.argsize = $3;
$$.Type = obj.TYPE_TEXTSIZE;
$$.Offset = $1;
$$.U.Argsize = int32($3);
}
| '-' LCONST '-' LCONST
{
$$ = nullgen;
$$.type = TYPE_TEXTSIZE;
$$.offset = -$2;
$$.u.argsize = $4;
$$.Type = obj.TYPE_TEXTSIZE;
$$.Offset = -$2;
$$.U.Argsize = int32($4);
}
expr:
@ -702,11 +703,11 @@ expr:
}
| expr '<' '<' expr
{
$$ = $1 << $4;
$$ = $1 << uint($4);
}
| expr '>' '>' expr
{
$$ = $1 >> $4;
$$ = $1 >> uint($4);
}
| expr '&' expr
{

View file

@ -1,20 +0,0 @@
// 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.
// +build ignore
/*
6a is a version of the Plan 9 assembler. The original is documented at
http://plan9.bell-labs.com/magic/man2html/1/8a
Go-specific considerations are documented at
http://golang.org/doc/asm
Its target architecture is the x86-64, referred to by these tools as amd64.
*/
package main

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,139 +0,0 @@
/* A Bison parser, made by GNU Bison 2.3. */
/* Skeleton interface for Bison's Yacc-like parsers in C
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
under terms of your choice, so long as that work isn't itself a
parser generator using the skeleton or a modified version thereof
as a parser skeleton. Alternatively, if you modify or redistribute
the parser skeleton itself, you may (at your option) remove this
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
LTYPE0 = 258,
LTYPE1 = 259,
LTYPE2 = 260,
LTYPE3 = 261,
LTYPE4 = 262,
LTYPEC = 263,
LTYPED = 264,
LTYPEN = 265,
LTYPER = 266,
LTYPET = 267,
LTYPEG = 268,
LTYPEPC = 269,
LTYPES = 270,
LTYPEM = 271,
LTYPEI = 272,
LTYPEXC = 273,
LTYPEX = 274,
LTYPERT = 275,
LTYPEF = 276,
LCONST = 277,
LFP = 278,
LPC = 279,
LSB = 280,
LBREG = 281,
LLREG = 282,
LSREG = 283,
LFREG = 284,
LMREG = 285,
LXREG = 286,
LFCONST = 287,
LSCONST = 288,
LSP = 289,
LNAME = 290,
LLAB = 291,
LVAR = 292
};
#endif
/* Tokens. */
#define LTYPE0 258
#define LTYPE1 259
#define LTYPE2 260
#define LTYPE3 261
#define LTYPE4 262
#define LTYPEC 263
#define LTYPED 264
#define LTYPEN 265
#define LTYPER 266
#define LTYPET 267
#define LTYPEG 268
#define LTYPEPC 269
#define LTYPES 270
#define LTYPEM 271
#define LTYPEI 272
#define LTYPEXC 273
#define LTYPEX 274
#define LTYPERT 275
#define LTYPEF 276
#define LCONST 277
#define LFP 278
#define LPC 279
#define LSB 280
#define LBREG 281
#define LLREG 282
#define LSREG 283
#define LFREG 284
#define LMREG 285
#define LXREG 286
#define LFCONST 287
#define LSCONST 288
#define LSP 289
#define LNAME 290
#define LLAB 291
#define LVAR 292
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
#line 38 "a.y"
{
Sym *sym;
vlong lval;
double dval;
char sval[8];
Addr addr;
Addr2 addr2;
}
/* Line 1529 of yacc.c. */
#line 132 "y.tab.h"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
#endif
extern YYSTYPE yylval;

View file

@ -1,5 +0,0 @@
# Copyright 2012 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.
include ../../Make.dist

File diff suppressed because it is too large Load diff

View file

@ -1,15 +0,0 @@
// 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.
// +build ignore
/*
6g is the version of the gc compiler for the x86-64.
The $GOARCH for these tools is amd64.
It reads .go files and outputs .6 files. The flags are documented in ../gc/doc.go.
*/
package main

View file

@ -1,110 +0,0 @@
// 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.
#include <u.h>
#include <libc.h>
#include "gg.h"
int thechar = '6';
char* thestring = "amd64";
LinkArch* thelinkarch = &linkamd64;
void
linkarchinit(void)
{
if(strcmp(getgoarch(), "amd64p32") == 0) {
thelinkarch = &linkamd64p32;
thearch.thelinkarch = thelinkarch;
thestring = "amd64p32";
thearch.thestring = "amd64p32";
}
}
vlong MAXWIDTH = 1LL<<50;
int addptr = AADDQ;
int movptr = AMOVQ;
int leaptr = ALEAQ;
int cmpptr = ACMPQ;
/*
* go declares several platform-specific type aliases:
* int, uint, float, and uintptr
*/
Typedef typedefs[] =
{
{"int", TINT, TINT64},
{"uint", TUINT, TUINT64},
{"uintptr", TUINTPTR, TUINT64},
{0}
};
void
betypeinit(void)
{
widthptr = 8;
widthint = 8;
widthreg = 8;
if(strcmp(getgoarch(), "amd64p32") == 0) {
widthptr = 4;
widthint = 4;
addptr = AADDL;
movptr = AMOVL;
leaptr = ALEAL;
cmpptr = ACMPL;
typedefs[0].sameas = TINT32;
typedefs[1].sameas = TUINT32;
typedefs[2].sameas = TUINT32;
}
listinit6();
}
void
main(int argc, char **argv)
{
thearch.thechar = thechar;
thearch.thestring = thestring;
thearch.thelinkarch = thelinkarch;
thearch.typedefs = typedefs;
thearch.REGSP = REGSP;
thearch.REGCTXT = REGCTXT;
thearch.MAXWIDTH = MAXWIDTH;
thearch.anyregalloc = anyregalloc;
thearch.betypeinit = betypeinit;
thearch.bgen = bgen;
thearch.cgen = cgen;
thearch.cgen_call = cgen_call;
thearch.cgen_callinter = cgen_callinter;
thearch.cgen_ret = cgen_ret;
thearch.clearfat = clearfat;
thearch.defframe = defframe;
thearch.excise = excise;
thearch.expandchecks = expandchecks;
thearch.gclean = gclean;
thearch.ginit = ginit;
thearch.gins = gins;
thearch.ginscall = ginscall;
thearch.igen = igen;
thearch.linkarchinit = linkarchinit;
thearch.peep = peep;
thearch.proginfo = proginfo;
thearch.regalloc = regalloc;
thearch.regfree = regfree;
thearch.regtyp = regtyp;
thearch.sameaddr = sameaddr;
thearch.smallindir = smallindir;
thearch.stackaddr = stackaddr;
thearch.excludedregs = excludedregs;
thearch.RtoB = RtoB;
thearch.FtoB = FtoB;
thearch.BtoR = BtoR;
thearch.BtoF = BtoF;
thearch.optoas = optoas;
thearch.doregbits = doregbits;
thearch.regnames = regnames;
gcmain(argc, argv);
}

View file

@ -1,176 +0,0 @@
// 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.
#ifndef EXTERN
#define EXTERN extern
#endif
#include "../gc/go.h"
#include "../6l/6.out.h"
EXTERN uchar reg[MAXREG];
EXTERN Node* panicdiv;
extern vlong unmappedzero;
extern int addptr;
extern int cmpptr;
extern int movptr;
extern int leaptr;
/*
* ggen.c
*/
void compile(Node*);
void gen(Node*);
Node* lookdot(Node*, Node*, int);
void cgen_as(Node*, Node*);
void cgen_callmeth(Node*, int);
void cgen_callinter(Node*, Node*, int);
void cgen_proc(Node*, int);
void cgen_callret(Node*, Node*);
void cgen_div(int, Node*, Node*, Node*);
void cgen_bmul(int, Node*, Node*, Node*);
void cgen_hmul(Node*, Node*, Node*);
void cgen_shift(int, int, Node*, Node*, Node*);
void cgen_dcl(Node*);
int needconvert(Type*, Type*);
void genconv(Type*, Type*);
void allocparams(void);
void checklabels(void);
void ginscall(Node*, int);
int gen_as_init(Node*);
/*
* cgen.c
*/
void agen(Node*, Node*);
void agenr(Node*, Node*, Node*);
void cgenr(Node*, Node*, Node*);
void igen(Node*, Node*, Node*);
vlong fieldoffset(Type*, Node*);
void sgen(Node*, Node*, int64);
void gmove(Node*, Node*);
Prog* gins(int, Node*, Node*);
int samaddr(Node*, Node*);
void naddr(Node*, Addr*, int);
void cgen_aret(Node*, Node*);
void restx(Node*, Node*);
void savex(int, Node*, Node*, Node*, Type*);
int componentgen(Node*, Node*);
/*
* gsubr.c
*/
void clearp(Prog*);
Prog* gbranch(int, Type*, int);
Prog* prog(int);
void gconv(int, int);
int conv2pt(Type*);
vlong convvtox(vlong, int);
void fnparam(Type*, int, int);
Prog* gop(int, Node*, Node*, Node*);
int optoas(int, Type*);
void ginit(void);
void gclean(void);
void regalloc(Node*, Type*, Node*);
void regfree(Node*);
Node* nodarg(Type*, int);
void nodreg(Node*, Type*, int);
void nodindreg(Node*, Type*, int);
void gconreg(int, vlong, int);
void ginscon(int, vlong, Node*);
void buildtxt(void);
Plist* newplist(void);
int isfat(Type*);
void sudoclean(void);
int sudoaddable(int, Node*, Addr*);
void afunclit(Addr*, Node*);
void nodfconst(Node*, Type*, Mpflt*);
void gtrack(Sym*);
void fixlargeoffset(Node *n);
/*
* cplx.c
*/
int complexop(Node*, Node*);
void complexmove(Node*, Node*);
void complexgen(Node*, Node*);
/*
* gobj.c
*/
void datastring(char*, int, Addr*);
void datagostring(Strlit*, Addr*);
/*
* list.c
*/
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_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*);
/*
* reg.c
*/
uint64 excludedregs(void);
uint64 RtoB(int);
uint64 FtoB(int);
int BtoR(uint64);
int BtoF(uint64);
uint64 doregbits(int);
char** regnames(int*);
/*
* peep.c
*/
void peep(Prog*);

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,988 +0,0 @@
// Derived from Inferno utils/6c/peep.c
// http://code.google.com/p/inferno-os/source/browse/utils/6c/peep.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <u.h>
#include <libc.h>
#include "gg.h"
#include "../gc/popt.h"
static void conprop(Flow *r);
static void elimshortmov(Graph *g);
static int prevl(Flow *r, int reg);
static void pushback(Flow *r);
static int regconsttyp(Adr*);
static int subprop(Flow*);
static int copyprop(Graph*, Flow*);
static int copy1(Adr*, Adr*, Flow*, int);
static int copyas(Adr*, Adr*);
static int copyau(Adr*, Adr*);
static int copysub(Adr*, Adr*, Adr*, int);
static int copyu(Prog*, Adr*, Adr*);
static uint32 gactive;
enum
{
exregoffset = REG_R15,
};
// do we need the carry bit
static int
needc(Prog *p)
{
ProgInfo info;
while(p != P) {
proginfo(&info, p);
if(info.flags & UseCarry)
return 1;
if(info.flags & (SetCarry|KillCarry))
return 0;
p = p->link;
}
return 0;
}
static Flow*
rnops(Flow *r)
{
Prog *p;
Flow *r1;
if(r != nil)
for(;;) {
p = r->prog;
if(p->as != ANOP || p->from.type != TYPE_NONE || p->to.type != TYPE_NONE)
break;
r1 = uniqs(r);
if(r1 == nil)
break;
r = r1;
}
return r;
}
void
peep(Prog *firstp)
{
Flow *r, *r1;
Graph *g;
Prog *p, *p1;
int t;
g = flowstart(firstp, 0);
if(g == nil)
return;
gactive = 0;
// byte, word arithmetic elimination.
elimshortmov(g);
// constant propagation
// find MOV $con,R followed by
// another MOV $con,R without
// setting R in the interim
for(r=g->start; r!=nil; r=r->link) {
p = r->prog;
switch(p->as) {
case ALEAL:
case ALEAQ:
if(regtyp(&p->to))
if(p->from.sym != nil)
if(p->from.index == REG_NONE)
conprop(r);
break;
case AMOVB:
case AMOVW:
case AMOVL:
case AMOVQ:
case AMOVSS:
case AMOVSD:
if(regtyp(&p->to))
if(p->from.type == TYPE_CONST || p->from.type == TYPE_FCONST)
conprop(r);
break;
}
}
loop1:
if(debug['P'] && debug['v'])
dumpit("loop1", g->start, 0);
t = 0;
for(r=g->start; r!=nil; r=r->link) {
p = r->prog;
switch(p->as) {
case AMOVL:
case AMOVQ:
case AMOVSS:
case AMOVSD:
if(regtyp(&p->to))
if(regtyp(&p->from)) {
if(copyprop(g, r)) {
excise(r);
t++;
} else
if(subprop(r) && copyprop(g, r)) {
excise(r);
t++;
}
}
break;
case AMOVBLZX:
case AMOVWLZX:
case AMOVBLSX:
case AMOVWLSX:
if(regtyp(&p->to)) {
r1 = rnops(uniqs(r));
if(r1 != nil) {
p1 = r1->prog;
if(p->as == p1->as && p->to.type == p1->from.type && p->to.reg == p1->from.reg){
p1->as = AMOVL;
t++;
}
}
}
break;
case AMOVBQSX:
case AMOVBQZX:
case AMOVWQSX:
case AMOVWQZX:
case AMOVLQSX:
case AMOVLQZX:
case AMOVQL:
if(regtyp(&p->to)) {
r1 = rnops(uniqs(r));
if(r1 != nil) {
p1 = r1->prog;
if(p->as == p1->as && p->to.type == p1->from.type && p->to.reg == p1->from.reg){
p1->as = AMOVQ;
t++;
}
}
}
break;
case AADDL:
case AADDQ:
case AADDW:
if(p->from.type != TYPE_CONST || needc(p->link))
break;
if(p->from.offset == -1){
if(p->as == AADDQ)
p->as = ADECQ;
else
if(p->as == AADDL)
p->as = ADECL;
else
p->as = ADECW;
p->from = zprog.from;
break;
}
if(p->from.offset == 1){
if(p->as == AADDQ)
p->as = AINCQ;
else if(p->as == AADDL)
p->as = AINCL;
else
p->as = AINCW;
p->from = zprog.from;
break;
}
break;
case ASUBL:
case ASUBQ:
case ASUBW:
if(p->from.type != TYPE_CONST || needc(p->link))
break;
if(p->from.offset == -1) {
if(p->as == ASUBQ)
p->as = AINCQ;
else
if(p->as == ASUBL)
p->as = AINCL;
else
p->as = AINCW;
p->from = zprog.from;
break;
}
if(p->from.offset == 1){
if(p->as == ASUBQ)
p->as = ADECQ;
else
if(p->as == ASUBL)
p->as = ADECL;
else
p->as = ADECW;
p->from = zprog.from;
break;
}
break;
}
}
if(t)
goto loop1;
// MOVLQZX removal.
// The MOVLQZX exists to avoid being confused for a
// MOVL that is just copying 32-bit data around during
// copyprop. Now that copyprop is done, remov MOVLQZX R1, R2
// if it is dominated by an earlier ADDL/MOVL/etc into R1 that
// will have already cleared the high bits.
//
// MOVSD removal.
// We never use packed registers, so a MOVSD between registers
// can be replaced by MOVAPD, which moves the pair of float64s
// instead of just the lower one. We only use the lower one, but
// the processor can do better if we do moves using both.
for(r=g->start; r!=nil; r=r->link) {
p = r->prog;
if(p->as == AMOVLQZX)
if(regtyp(&p->from))
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(regtyp(&p->from))
if(regtyp(&p->to))
p->as = AMOVAPD;
}
// load pipelining
// push any load from memory as early as possible
// to give it time to complete before use.
for(r=g->start; r!=nil; r=r->link) {
p = r->prog;
switch(p->as) {
case AMOVB:
case AMOVW:
case AMOVL:
case AMOVQ:
case AMOVLQZX:
if(regtyp(&p->to) && !regconsttyp(&p->from))
pushback(r);
}
}
flowend(g);
}
static void
pushback(Flow *r0)
{
Flow *r, *b;
Prog *p0, *p, t;
b = nil;
p0 = r0->prog;
for(r=uniqp(r0); r!=nil && uniqs(r)!=nil; r=uniqp(r)) {
p = r->prog;
if(p->as != ANOP) {
if(!regconsttyp(&p->from) || !regtyp(&p->to))
break;
if(copyu(p, &p0->to, nil) || copyu(p0, &p->to, nil))
break;
}
if(p->as == ACALL)
break;
b = r;
}
if(b == nil) {
if(debug['v']) {
print("no pushback: %P\n", r0->prog);
if(r)
print("\t%P [%d]\n", r->prog, uniqs(r)!=nil);
}
return;
}
if(debug['v']) {
print("pushback\n");
for(r=b;; r=r->link) {
print("\t%P\n", r->prog);
if(r == r0)
break;
}
}
t = *r0->prog;
for(r=uniqp(r0);; r=uniqp(r)) {
p0 = r->link->prog;
p = r->prog;
p0->as = p->as;
p0->lineno = p->lineno;
p0->from = p->from;
p0->to = p->to;
if(r == b)
break;
}
p0 = r->prog;
p0->as = t.as;
p0->lineno = t.lineno;
p0->from = t.from;
p0->to = t.to;
if(debug['v']) {
print("\tafter\n");
for(r=b;; r=r->link) {
print("\t%P\n", r->prog);
if(r == r0)
break;
}
}
}
void
excise(Flow *r)
{
Prog *p;
p = r->prog;
if(debug['P'] && debug['v'])
print("%P ===delete===\n", p);
nopout(p);
ostats.ndelmov++;
}
int
regtyp(Adr *a)
{
return a->type == TYPE_REG && (REG_AX <= a->reg && a->reg <= REG_R15 || REG_X0 <= a->reg && a->reg <= REG_X15);
}
// movb elimination.
// movb is simulated by the linker
// when a register other than ax, bx, cx, dx
// is used, so rewrite to other instructions
// when possible. a movb into a register
// can smash the entire 32-bit register without
// causing any trouble.
//
// TODO: Using the Q forms here instead of the L forms
// seems unnecessary, and it makes the instructions longer.
static void
elimshortmov(Graph *g)
{
Prog *p;
Flow *r;
for(r=g->start; r!=nil; r=r->link) {
p = r->prog;
if(regtyp(&p->to)) {
switch(p->as) {
case AINCB:
case AINCW:
p->as = AINCQ;
break;
case ADECB:
case ADECW:
p->as = ADECQ;
break;
case ANEGB:
case ANEGW:
p->as = ANEGQ;
break;
case ANOTB:
case ANOTW:
p->as = ANOTQ;
break;
}
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
// change how the carry bit is set (and the carry bit is needed).
switch(p->as) {
case AMOVB:
case AMOVW:
p->as = AMOVQ;
break;
case AADDB:
case AADDW:
if(!needc(p->link))
p->as = AADDQ;
break;
case ASUBB:
case ASUBW:
if(!needc(p->link))
p->as = ASUBQ;
break;
case AMULB:
case AMULW:
p->as = AMULQ;
break;
case AIMULB:
case AIMULW:
p->as = AIMULQ;
break;
case AANDB:
case AANDW:
p->as = AANDQ;
break;
case AORB:
case AORW:
p->as = AORQ;
break;
case AXORB:
case AXORW:
p->as = AXORQ;
break;
case ASHLB:
case ASHLW:
p->as = ASHLQ;
break;
}
} 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).
switch(p->as) {
case AMOVB:
p->as = AMOVBQZX;
break;
case AMOVW:
p->as = AMOVWQZX;
break;
}
}
}
}
}
// is 'a' a register or constant?
static int
regconsttyp(Adr *a)
{
if(regtyp(a))
return 1;
switch(a->type) {
case TYPE_CONST:
case TYPE_FCONST:
case TYPE_SCONST:
case TYPE_ADDR: // TODO(rsc): Not all TYPE_ADDRs are constants.
return 1;
}
return 0;
}
// is reg guaranteed to be truncated by a previous L instruction?
static int
prevl(Flow *r0, int reg)
{
Prog *p;
Flow *r;
ProgInfo info;
for(r=uniqp(r0); r!=nil; r=uniqp(r)) {
p = r->prog;
if(p->to.type == TYPE_REG && p->to.reg == reg) {
proginfo(&info, p);
if(info.flags & RightWrite) {
if(info.flags & SizeL)
return 1;
return 0;
}
}
}
return 0;
}
/*
* the idea is to substitute
* one register for another
* from one MOV to another
* MOV a, R0
* ADD b, R0 / no use of R1
* MOV R0, R1
* would be converted to
* MOV a, R1
* ADD b, R1
* MOV R1, R0
* hopefully, then the former or latter MOV
* will be eliminated by copy propagation.
*/
static int
subprop(Flow *r0)
{
Prog *p;
ProgInfo info;
Adr *v1, *v2;
Flow *r;
int t;
if(debug['P'] && debug['v'])
print("subprop %P\n", r0->prog);
p = r0->prog;
v1 = &p->from;
if(!regtyp(v1)) {
if(debug['P'] && debug['v'])
print("\tnot regtype %D; return 0\n", v1);
return 0;
}
v2 = &p->to;
if(!regtyp(v2)) {
if(debug['P'] && debug['v'])
print("\tnot regtype %D; return 0\n", v2);
return 0;
}
for(r=uniqp(r0); r!=nil; r=uniqp(r)) {
if(debug['P'] && debug['v'])
print("\t? %P\n", r->prog);
if(uniqs(r) == nil) {
if(debug['P'] && debug['v'])
print("\tno unique successor\n");
break;
}
p = r->prog;
if(p->as == AVARDEF || p->as == AVARKILL)
continue;
proginfo(&info, p);
if(info.flags & Call) {
if(debug['P'] && debug['v'])
print("\tfound %P; return 0\n", p);
return 0;
}
if(info.reguse | info.regset) {
if(debug['P'] && debug['v'])
print("\tfound %P; return 0\n", p);
return 0;
}
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)) {
if(debug['P'] && debug['v'])
print("\tcopyau %D failed\n", v2);
break;
}
if(copysub(&p->from, v1, v2, 0) ||
copysub(&p->to, v1, v2, 0)) {
if(debug['P'] && debug['v'])
print("\tcopysub failed\n");
break;
}
}
if(debug['P'] && debug['v'])
print("\tran off end; return 0\n");
return 0;
gotit:
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 && p->from.reg == v2->reg)
print(" excise");
print("\n");
}
for(r=uniqs(r); r!=r0; r=uniqs(r)) {
p = r->prog;
copysub(&p->from, v1, v2, 1);
copysub(&p->to, v1, v2, 1);
if(debug['P'])
print("%P\n", r->prog);
}
t = v1->reg;
v1->reg = v2->reg;
v2->reg = t;
if(debug['P'])
print("%P last\n", r->prog);
return 1;
}
/*
* The idea is to remove redundant copies.
* v1->v2 F=0
* (use v2 s/v2/v1/)*
* set v1 F=1
* use v2 return fail
* -----------------
* v1->v2 F=0
* (use v2 s/v2/v1/)*
* set v1 F=1
* set v2 return success
*/
static int
copyprop(Graph *g, Flow *r0)
{
Prog *p;
Adr *v1, *v2;
USED(g);
if(debug['P'] && debug['v'])
print("copyprop %P\n", r0->prog);
p = r0->prog;
v1 = &p->from;
v2 = &p->to;
if(copyas(v1, v2))
return 1;
gactive++;
return copy1(v1, v2, r0->s1, 0);
}
static int
copy1(Adr *v1, Adr *v2, Flow *r, int f)
{
int t;
Prog *p;
if(r->active == gactive) {
if(debug['P'])
print("act set; return 1\n");
return 1;
}
r->active = gactive;
if(debug['P'])
print("copy %D->%D f=%d\n", v1, v2, f);
for(; r != nil; r = r->s1) {
p = r->prog;
if(debug['P'])
print("%P", p);
if(!f && uniqp(r) == nil) {
f = 1;
if(debug['P'])
print("; merge; f=%d", f);
}
t = copyu(p, v2, nil);
switch(t) {
case 2: /* rar, can't split */
if(debug['P'])
print("; %D rar; return 0\n", v2);
return 0;
case 3: /* set */
if(debug['P'])
print("; %D set; return 1\n", v2);
return 1;
case 1: /* used, substitute */
case 4: /* use and set */
if(f) {
if(!debug['P'])
return 0;
if(t == 4)
print("; %D used+set and f=%d; return 0\n", v2, f);
else
print("; %D used and f=%d; return 0\n", v2, f);
return 0;
}
if(copyu(p, v2, v1)) {
if(debug['P'])
print("; sub fail; return 0\n");
return 0;
}
if(debug['P'])
print("; sub %D/%D", v2, v1);
if(t == 4) {
if(debug['P'])
print("; %D used+set; return 1\n", v2);
return 1;
}
break;
}
if(!f) {
t = copyu(p, v1, nil);
if(!f && (t == 2 || t == 3 || t == 4)) {
f = 1;
if(debug['P'])
print("; %D set and !f; f=%d", v1, f);
}
}
if(debug['P'])
print("\n");
if(r->s2)
if(!copy1(v1, v2, r->s2, f))
return 0;
}
return 1;
}
/*
* return
* 1 if v only used (and substitute),
* 2 if read-alter-rewrite
* 3 if set
* 4 if set and used
* 0 otherwise (not touched)
*/
static int
copyu(Prog *p, Adr *v, Adr *s)
{
ProgInfo info;
switch(p->as) {
case AJMP:
if(s != nil) {
if(copysub(&p->to, v, s, 1))
return 1;
return 0;
}
if(copyau(&p->to, v))
return 1;
return 0;
case ARET:
if(s != nil)
return 1;
return 3;
case ACALL:
if(REGEXT && v->type == TYPE_REG && v->reg <= REGEXT && v->reg > exregoffset)
return 2;
if(REGARG >= 0 && v->type == TYPE_REG && v->reg == REGARG)
return 2;
if(v->type == p->from.type && v->reg == p->from.reg)
return 2;
if(s != nil) {
if(copysub(&p->to, v, s, 1))
return 1;
return 0;
}
if(copyau(&p->to, v))
return 4;
return 3;
case ATEXT:
if(REGARG >= 0 && v->type == TYPE_REG && v->reg == REGARG)
return 3;
return 0;
}
if(p->as == AVARDEF || p->as == AVARKILL)
return 0;
proginfo(&info, p);
if((info.reguse|info.regset) & RtoB(v->reg))
return 2;
if(info.flags & LeftAddr)
if(copyas(&p->from, v))
return 2;
if((info.flags & (RightRead|RightWrite)) == (RightRead|RightWrite))
if(copyas(&p->to, v))
return 2;
if(info.flags & RightWrite) {
if(copyas(&p->to, v)) {
if(s != nil)
return copysub(&p->from, v, s, 1);
if(copyau(&p->from, v))
return 4;
return 3;
}
}
if(info.flags & (LeftAddr|LeftRead|LeftWrite|RightAddr|RightRead|RightWrite)) {
if(s != nil) {
if(copysub(&p->from, v, s, 1))
return 1;
return copysub(&p->to, v, s, 1);
}
if(copyau(&p->from, v))
return 1;
if(copyau(&p->to, v))
return 1;
}
return 0;
}
/*
* direct reference,
* could be set/use depending on
* semantics
*/
static int
copyas(Adr *a, Adr *v)
{
if(REG_AL <= a->reg && a->reg <= REG_R15B)
fatal("use of byte register");
if(REG_AL <= v->reg && v->reg <= REG_R15B)
fatal("use of byte register");
if(a->type != v->type || a->name != v->name || a->reg != v->reg)
return 0;
if(regtyp(v))
return 1;
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 || a->name != v->name || a->reg != v->reg)
return 0;
if(regtyp(v))
return 1;
if(v->type == TYPE_MEM && (v->name == NAME_AUTO || v->name == NAME_PARAM))
if(v->offset == a->offset)
return 1;
return 0;
}
/*
* either direct or indirect
*/
static int
copyau(Adr *a, Adr *v)
{
if(copyas(a, v)) {
if(debug['P'] && debug['v'])
print("\tcopyau: copyas returned 1\n");
return 1;
}
if(regtyp(v)) {
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->reg) {
if(debug['P'] && debug['v'])
print("\tcopyau: found index use - return 1\n");
return 1;
}
}
return 0;
}
/*
* substitute s for v in a
* return failure to substitute
*/
static int
copysub(Adr *a, Adr *v, Adr *s, int f)
{
int reg;
if(copyas(a, v)) {
reg = s->reg;
if(reg >= REG_AX && reg <= REG_R15 || reg >= REG_X0 && reg <= REG_X0+15) {
if(f)
a->reg = reg;
}
return 0;
}
if(regtyp(v)) {
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->reg = s->reg;
// return 0;
}
if(a->index == reg) {
if(f)
a->index = s->reg;
return 0;
}
return 0;
}
return 0;
}
static void
conprop(Flow *r0)
{
Flow *r;
Prog *p, *p0;
int t;
Adr *v0;
p0 = r0->prog;
v0 = &p0->to;
r = r0;
loop:
r = uniqs(r);
if(r == nil || r == r0)
return;
if(uniqp(r) == nil)
return;
p = r->prog;
t = copyu(p, v0, nil);
switch(t) {
case 0: // miss
case 1: // use
goto loop;
case 2: // rar
case 4: // use and set
break;
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 == TYPE_FCONST && p->from.u.dval == p0->from.u.dval)
if(p->from.index == p0->from.index) {
excise(r);
goto loop;
}
break;
}
}
int
smallindir(Addr *a, Addr *reg)
{
return regtyp(reg) &&
a->type == TYPE_MEM && a->reg == reg->reg &&
a->index == REG_NONE &&
0 <= a->offset && a->offset < 4096;
}
int
stackaddr(Addr *a)
{
return a->type == TYPE_REG && a->reg == REG_SP;
}

View file

@ -1,318 +0,0 @@
// 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.
#include <u.h>
#include <libc.h>
#include "gg.h"
#include "../gc/popt.h"
// Matches real RtoB but can be used in global initializer.
#define RtoB(r) (1<<((r)-REG_AX))
enum {
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,
};
#undef RtoB
// This table gives the basic information about instruction
// generated by the compiler and processed in the optimizer.
// See opt.h for bit definitions.
//
// Instructions not generated need not be listed.
// As an exception to that rule, we typically write down all the
// size variants of an operation even if we just use a subset.
//
// The table is formatted for 8-space tabs.
static ProgInfo progtable[ALAST] = {
[ATYPE]= {Pseudo | Skip},
[ATEXT]= {Pseudo},
[AFUNCDATA]= {Pseudo},
[APCDATA]= {Pseudo},
[AUNDEF]= {Break},
[AUSEFIELD]= {OK},
[ACHECKNIL]= {LeftRead},
[AVARDEF]= {Pseudo | RightWrite},
[AVARKILL]= {Pseudo | RightWrite},
// NOP is an internal no-op that also stands
// for USED and SET annotations, not the Intel opcode.
[ANOP]= {LeftRead | RightWrite},
[AADCL]= {SizeL | LeftRead | RightRdwr | SetCarry | UseCarry},
[AADCQ]= {SizeQ | LeftRead | RightRdwr | SetCarry | UseCarry},
[AADCW]= {SizeW | LeftRead | RightRdwr | SetCarry | UseCarry},
[AADDB]= {SizeB | LeftRead | RightRdwr | SetCarry},
[AADDL]= {SizeL | LeftRead | RightRdwr | SetCarry},
[AADDW]= {SizeW | LeftRead | RightRdwr | SetCarry},
[AADDQ]= {SizeQ | LeftRead | RightRdwr | SetCarry},
[AADDSD]= {SizeD | LeftRead | RightRdwr},
[AADDSS]= {SizeF | LeftRead | RightRdwr},
[AANDB]= {SizeB | LeftRead | RightRdwr | SetCarry},
[AANDL]= {SizeL | LeftRead | RightRdwr | SetCarry},
[AANDQ]= {SizeQ | LeftRead | RightRdwr | SetCarry},
[AANDW]= {SizeW | LeftRead | RightRdwr | SetCarry},
[ACALL]= {RightAddr | Call | KillCarry},
[ACDQ]= {OK, AX, AX | DX},
[ACQO]= {OK, AX, AX | DX},
[ACWD]= {OK, AX, AX | DX},
[ACLD]= {OK},
[ASTD]= {OK},
[ACMPB]= {SizeB | LeftRead | RightRead | SetCarry},
[ACMPL]= {SizeL | LeftRead | RightRead | SetCarry},
[ACMPQ]= {SizeQ | LeftRead | RightRead | SetCarry},
[ACMPW]= {SizeW | LeftRead | RightRead | SetCarry},
[ACOMISD]= {SizeD | LeftRead | RightRead | SetCarry},
[ACOMISS]= {SizeF | LeftRead | RightRead | SetCarry},
[ACVTSD2SL]= {SizeL | LeftRead | RightWrite | Conv},
[ACVTSD2SQ]= {SizeQ | LeftRead | RightWrite | Conv},
[ACVTSD2SS]= {SizeF | LeftRead | RightWrite | Conv},
[ACVTSL2SD]= {SizeD | LeftRead | RightWrite | Conv},
[ACVTSL2SS]= {SizeF | LeftRead | RightWrite | Conv},
[ACVTSQ2SD]= {SizeD | LeftRead | RightWrite | Conv},
[ACVTSQ2SS]= {SizeF | LeftRead | RightWrite | Conv},
[ACVTSS2SD]= {SizeD | LeftRead | RightWrite | Conv},
[ACVTSS2SL]= {SizeL | LeftRead | RightWrite | Conv},
[ACVTSS2SQ]= {SizeQ | LeftRead | RightWrite | Conv},
[ACVTTSD2SL]= {SizeL | LeftRead | RightWrite | Conv},
[ACVTTSD2SQ]= {SizeQ | LeftRead | RightWrite | Conv},
[ACVTTSS2SL]= {SizeL | LeftRead | RightWrite | Conv},
[ACVTTSS2SQ]= {SizeQ | LeftRead | RightWrite | Conv},
[ADECB]= {SizeB | RightRdwr},
[ADECL]= {SizeL | RightRdwr},
[ADECQ]= {SizeQ | RightRdwr},
[ADECW]= {SizeW | RightRdwr},
[ADIVB]= {SizeB | LeftRead | SetCarry, AX, AX},
[ADIVL]= {SizeL | LeftRead | SetCarry, AX|DX, AX|DX},
[ADIVQ]= {SizeQ | LeftRead | SetCarry, AX|DX, AX|DX},
[ADIVW]= {SizeW | LeftRead | SetCarry, AX|DX, AX|DX},
[ADIVSD]= {SizeD | LeftRead | RightRdwr},
[ADIVSS]= {SizeF | LeftRead | RightRdwr},
[AIDIVB]= {SizeB | LeftRead | SetCarry, AX, AX},
[AIDIVL]= {SizeL | LeftRead | SetCarry, AX|DX, AX|DX},
[AIDIVQ]= {SizeQ | LeftRead | SetCarry, AX|DX, AX|DX},
[AIDIVW]= {SizeW | LeftRead | SetCarry, AX|DX, AX|DX},
[AIMULB]= {SizeB | LeftRead | SetCarry, AX, AX},
[AIMULL]= {SizeL | LeftRead | ImulAXDX | SetCarry},
[AIMULQ]= {SizeQ | LeftRead | ImulAXDX | SetCarry},
[AIMULW]= {SizeW | LeftRead | ImulAXDX | SetCarry},
[AINCB]= {SizeB | RightRdwr},
[AINCL]= {SizeL | RightRdwr},
[AINCQ]= {SizeQ | RightRdwr},
[AINCW]= {SizeW | RightRdwr},
[AJCC]= {Cjmp | UseCarry},
[AJCS]= {Cjmp | UseCarry},
[AJEQ]= {Cjmp | UseCarry},
[AJGE]= {Cjmp | UseCarry},
[AJGT]= {Cjmp | UseCarry},
[AJHI]= {Cjmp | UseCarry},
[AJLE]= {Cjmp | UseCarry},
[AJLS]= {Cjmp | UseCarry},
[AJLT]= {Cjmp | UseCarry},
[AJMI]= {Cjmp | UseCarry},
[AJNE]= {Cjmp | UseCarry},
[AJOC]= {Cjmp | UseCarry},
[AJOS]= {Cjmp | UseCarry},
[AJPC]= {Cjmp | UseCarry},
[AJPL]= {Cjmp | UseCarry},
[AJPS]= {Cjmp | UseCarry},
[AJMP]= {Jump | Break | KillCarry},
[ALEAL]= {LeftAddr | RightWrite},
[ALEAQ]= {LeftAddr | RightWrite},
[AMOVBLSX]= {SizeL | LeftRead | RightWrite | Conv},
[AMOVBLZX]= {SizeL | LeftRead | RightWrite | Conv},
[AMOVBQSX]= {SizeQ | LeftRead | RightWrite | Conv},
[AMOVBQZX]= {SizeQ | LeftRead | RightWrite | Conv},
[AMOVBWSX]= {SizeW | LeftRead | RightWrite | Conv},
[AMOVBWZX]= {SizeW | LeftRead | RightWrite | Conv},
[AMOVLQSX]= {SizeQ | LeftRead | RightWrite | Conv},
[AMOVLQZX]= {SizeQ | LeftRead | RightWrite | Conv},
[AMOVWLSX]= {SizeL | LeftRead | RightWrite | Conv},
[AMOVWLZX]= {SizeL | LeftRead | RightWrite | Conv},
[AMOVWQSX]= {SizeQ | LeftRead | RightWrite | Conv},
[AMOVWQZX]= {SizeQ | LeftRead | RightWrite | Conv},
[AMOVQL]= {SizeL | LeftRead | RightWrite | Conv},
[AMOVB]= {SizeB | LeftRead | RightWrite | Move},
[AMOVL]= {SizeL | LeftRead | RightWrite | Move},
[AMOVQ]= {SizeQ | LeftRead | RightWrite | Move},
[AMOVW]= {SizeW | LeftRead | RightWrite | Move},
[AMOVSB]= {OK, DI|SI, DI|SI},
[AMOVSL]= {OK, DI|SI, DI|SI},
[AMOVSQ]= {OK, DI|SI, DI|SI},
[AMOVSW]= {OK, DI|SI, DI|SI},
[ADUFFCOPY]= {OK, DI|SI, DI|SI|CX},
[AMOVSD]= {SizeD | LeftRead | RightWrite | Move},
[AMOVSS]= {SizeF | LeftRead | RightWrite | Move},
// We use MOVAPD as a faster synonym for MOVSD.
[AMOVAPD]= {SizeD | LeftRead | RightWrite | Move},
[AMULB]= {SizeB | LeftRead | SetCarry, AX, AX},
[AMULL]= {SizeL | LeftRead | SetCarry, AX, AX|DX},
[AMULQ]= {SizeQ | LeftRead | SetCarry, AX, AX|DX},
[AMULW]= {SizeW | LeftRead | SetCarry, AX, AX|DX},
[AMULSD]= {SizeD | LeftRead | RightRdwr},
[AMULSS]= {SizeF | LeftRead | RightRdwr},
[ANEGB]= {SizeB | RightRdwr | SetCarry},
[ANEGL]= {SizeL | RightRdwr | SetCarry},
[ANEGQ]= {SizeQ | RightRdwr | SetCarry},
[ANEGW]= {SizeW | RightRdwr | SetCarry},
[ANOTB]= {SizeB | RightRdwr},
[ANOTL]= {SizeL | RightRdwr},
[ANOTQ]= {SizeQ | RightRdwr},
[ANOTW]= {SizeW | RightRdwr},
[AORB]= {SizeB | LeftRead | RightRdwr | SetCarry},
[AORL]= {SizeL | LeftRead | RightRdwr | SetCarry},
[AORQ]= {SizeQ | LeftRead | RightRdwr | SetCarry},
[AORW]= {SizeW | LeftRead | RightRdwr | SetCarry},
[APOPQ]= {SizeQ | RightWrite},
[APUSHQ]= {SizeQ | LeftRead},
[ARCLB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
[ARCLL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
[ARCLQ]= {SizeQ | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
[ARCLW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
[ARCRB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
[ARCRL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
[ARCRQ]= {SizeQ | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
[ARCRW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
[AREP]= {OK, CX, CX},
[AREPN]= {OK, CX, CX},
[ARET]= {Break | KillCarry},
[AROLB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
[AROLL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
[AROLQ]= {SizeQ | LeftRead | RightRdwr | ShiftCX | SetCarry},
[AROLW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ARORB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ARORL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ARORQ]= {SizeQ | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ARORW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASALB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASALL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASALQ]= {SizeQ | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASALW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASARB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASARL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASARQ]= {SizeQ | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASARW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASBBB]= {SizeB | LeftRead | RightRdwr | SetCarry | UseCarry},
[ASBBL]= {SizeL | LeftRead | RightRdwr | SetCarry | UseCarry},
[ASBBQ]= {SizeQ | LeftRead | RightRdwr | SetCarry | UseCarry},
[ASBBW]= {SizeW | LeftRead | RightRdwr | SetCarry | UseCarry},
[ASHLB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASHLL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASHLQ]= {SizeQ | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASHLW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASHRB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASHRL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASHRQ]= {SizeQ | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASHRW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASTOSB]= {OK, AX|DI, DI},
[ASTOSL]= {OK, AX|DI, DI},
[ASTOSQ]= {OK, AX|DI, DI},
[ASTOSW]= {OK, AX|DI, DI},
[ADUFFZERO]= {OK, AX|DI, DI},
[ASUBB]= {SizeB | LeftRead | RightRdwr | SetCarry},
[ASUBL]= {SizeL | LeftRead | RightRdwr | SetCarry},
[ASUBQ]= {SizeQ | LeftRead | RightRdwr | SetCarry},
[ASUBW]= {SizeW | LeftRead | RightRdwr | SetCarry},
[ASUBSD]= {SizeD | LeftRead | RightRdwr},
[ASUBSS]= {SizeF | LeftRead | RightRdwr},
[ATESTB]= {SizeB | LeftRead | RightRead | SetCarry},
[ATESTL]= {SizeL | LeftRead | RightRead | SetCarry},
[ATESTQ]= {SizeQ | LeftRead | RightRead | SetCarry},
[ATESTW]= {SizeW | LeftRead | RightRead | SetCarry},
[AUCOMISD]= {SizeD | LeftRead | RightRead},
[AUCOMISS]= {SizeF | LeftRead | RightRead},
[AXCHGB]= {SizeB | LeftRdwr | RightRdwr},
[AXCHGL]= {SizeL | LeftRdwr | RightRdwr},
[AXCHGQ]= {SizeQ | LeftRdwr | RightRdwr},
[AXCHGW]= {SizeW | LeftRdwr | RightRdwr},
[AXORB]= {SizeB | LeftRead | RightRdwr | SetCarry},
[AXORL]= {SizeL | LeftRead | RightRdwr | SetCarry},
[AXORQ]= {SizeQ | LeftRead | RightRdwr | SetCarry},
[AXORW]= {SizeW | LeftRead | RightRdwr | SetCarry},
};
void
proginfo(ProgInfo *info, Prog *p)
{
*info = progtable[p->as];
if(info->flags == 0)
fatal("unknown instruction %P", p);
if((info->flags & ShiftCX) && p->from.type != TYPE_CONST)
info->reguse |= CX;
if(info->flags & ImulAXDX) {
if(p->to.type == TYPE_NONE) {
info->reguse |= AX;
info->regset |= AX | DX;
} else {
info->flags |= RightRdwr;
}
}
// Addressing makes some registers used.
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 == 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);
}

View file

@ -1,153 +0,0 @@
// Derived from Inferno utils/6c/reg.c
// http://code.google.com/p/inferno-os/source/browse/utils/6c/reg.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <u.h>
#include <libc.h>
#include "gg.h"
#include "../gc/popt.h"
enum {
NREGVAR = 32,
};
static char* regname[] = {
".AX",
".CX",
".DX",
".BX",
".SP",
".BP",
".SI",
".DI",
".R8",
".R9",
".R10",
".R11",
".R12",
".R13",
".R14",
".R15",
".X0",
".X1",
".X2",
".X3",
".X4",
".X5",
".X6",
".X7",
".X8",
".X9",
".X10",
".X11",
".X12",
".X13",
".X14",
".X15",
};
char**
regnames(int *n)
{
*n = NREGVAR;
return regname;
}
uint64
excludedregs(void)
{
return RtoB(REG_SP);
}
uint64
doregbits(int r)
{
uint64 b;
b = 0;
if(r >= REG_AX && r <= REG_R15)
b |= RtoB(r);
else
if(r >= REG_AL && r <= REG_R15B)
b |= RtoB(r-REG_AL+REG_AX);
else
if(r >= REG_AH && r <= REG_BH)
b |= RtoB(r-REG_AH+REG_AX);
else
if(r >= REG_X0 && r <= REG_X0+15)
b |= FtoB(r);
return b;
}
uint64
RtoB(int r)
{
if(r < REG_AX || r > REG_R15)
return 0;
return 1ULL << (r-REG_AX);
}
int
BtoR(uint64 b)
{
b &= 0xffffULL;
if(nacl)
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) + REG_AX;
}
/*
* bit reg
* 16 X0
* ...
* 31 X15
*/
uint64
FtoB(int f)
{
if(f < REG_X0 || f > REG_X15)
return 0;
return 1ULL << (f - REG_X0 + 16);
}
int
BtoF(uint64 b)
{
b &= 0xFFFF0000L;
if(b == 0)
return 0;
return bitno(b) - 16 + REG_X0;
}

View file

@ -1,10 +0,0 @@
# Copyright 2012 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.
include ../../Make.dist
install: y.tab.h
y.tab.h: a.y
LANG=C LANGUAGE=en_US.UTF8 bison -d -v -y a.y

View file

@ -1,186 +0,0 @@
// Inferno utils/8a/a.h
// http://code.google.com/p/inferno-os/source/browse/utils/8a/a.h
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <bio.h>
#include <link.h>
#include "../8l/8.out.h"
#ifndef EXTERN
#define EXTERN extern
#endif
#undef getc
#undef ungetc
#undef BUFSIZ
#define getc ccgetc
#define ungetc ccungetc
typedef struct Sym Sym;
typedef struct Ref Ref;
typedef struct Io Io;
typedef struct Addr2 Addr2;
#define MAXALIGN 7
#define FPCHIP 1
#define NSYMB 500
#define BUFSIZ 8192
#define HISTSZ 20
#ifndef EOF
#define EOF (-1)
#endif
#define IGN (-2)
#define GETC() ((--fi.c < 0)? filbuf(): *fi.p++ & 0xff)
#define NHASH 503
#define STRINGSZ 200
#define NMACRO 10
struct Sym
{
Sym* link;
Ref* ref;
char* macro;
int32 value;
ushort type;
char *name;
char* labelname;
char sym;
};
#define S ((Sym*)0)
struct Ref
{
int class;
};
EXTERN struct
{
char* p;
int c;
} fi;
struct Io
{
Io* link;
char b[BUFSIZ];
char* p;
short c;
short f;
};
#define I ((Io*)0)
struct Addr2
{
Addr from;
Addr to;
};
enum
{
CLAST,
CMACARG,
CMACRO,
CPREPROC,
};
EXTERN int debug[256];
EXTERN Sym* hash[NHASH];
EXTERN char** Dlist;
EXTERN int nDlist;
EXTERN int newflag;
EXTERN char* hunk;
EXTERN char** include;
EXTERN Io* iofree;
EXTERN Io* ionext;
EXTERN Io* iostack;
EXTERN int32 lineno;
EXTERN int nerrors;
EXTERN int32 nhunk;
EXTERN int ninclude;
EXTERN int32 nsymb;
EXTERN Addr nullgen;
EXTERN char* outfile;
EXTERN int pass;
EXTERN int32 pc;
EXTERN int peekc;
EXTERN int32 stmtline;
EXTERN int sym;
EXTERN char* symb;
EXTERN int thechar;
EXTERN char* thestring;
EXTERN int32 thunk;
EXTERN Biobuf obuf;
EXTERN Link* ctxt;
EXTERN Biobuf bstdout;
EXTERN Prog* lastpc;
void* alloc(int32);
void* allocn(void*, int32, int32);
void ensuresymb(int32);
void errorexit(void);
void pushio(void);
void newio(void);
void newfile(char*, int);
Sym* slookup(char*);
Sym* lookup(void);
Sym* labellookup(Sym*);
void settext(LSym*);
void syminit(Sym*);
int32 yylex(void);
int getc(void);
int getnsc(void);
void unget(int);
int escchar(int);
void cinit(void);
void checkscale(int);
void pinit(char*);
void cclean(void);
int isreg(Addr*);
void outcode(int, Addr2*);
void outhist(void);
int filbuf(void);
Sym* getsym(void);
void domacro(void);
void macund(void);
void macdef(void);
void macexpand(Sym*, char*);
void macinc(void);
void macprag(void);
void maclin(void);
void macif(int);
void macend(void);
void dodefine(char*);
void prfile(int32);
void linehist(char*, int);
void gethunk(void);
void yyerror(char*, ...);
int yyparse(void);
void setinclude(char*);
int assemble(char*);

View file

@ -29,20 +29,28 @@
// THE SOFTWARE.
%{
#include <u.h>
#include <stdio.h> /* if we don't, bison will, and a.h re-#defines getc */
#include <libc.h>
#include "a.h"
#include "../../runtime/funcdata.h"
package main
import (
"cmd/internal/asm"
"cmd/internal/obj"
. "cmd/internal/obj/i386"
)
%}
%union {
Sym *sym;
int32 lval;
double dval;
char sval[8];
Addr addr;
Addr2 addr2;
sym *asm.Sym
lval int64
con2 struct {
v1 int32
v2 int32
}
dval float64
sval string
addr obj.Addr
addr2 Addr2
}
%left '|'
%left '^'
%left '&'
@ -64,18 +72,19 @@
prog:
| prog
{
stmtline = lineno;
stmtline = asm.Lineno;
}
line
line:
LNAME ':'
{
$1 = labellookup($1);
if($1->type == LLAB && $1->value != pc)
yyerror("redeclaration of %s", $1->labelname);
$1->type = LLAB;
$1->value = pc;
$1 = asm.LabelLookup($1);
if $1.Type == LLAB && $1.Value != int64(asm.PC) {
yyerror("redeclaration of %s", $1.Labelname)
}
$1.Type = LLAB;
$1.Value = int64(asm.PC)
}
line
| ';'
@ -85,33 +94,34 @@ line:
inst:
LNAME '=' expr
{
$1->type = LVAR;
$1->value = $3;
$1.Type = LVAR;
$1.Value = $3;
}
| LVAR '=' expr
{
if($1->value != $3)
yyerror("redeclaration of %s", $1->name);
$1->value = $3;
if $1.Value != int64($3) {
yyerror("redeclaration of %s", $1.Name);
}
| LTYPE0 nonnon { outcode($1, &$2); }
| LTYPE1 nonrem { outcode($1, &$2); }
| LTYPE2 rimnon { outcode($1, &$2); }
| LTYPE3 rimrem { outcode($1, &$2); }
| LTYPE4 remrim { outcode($1, &$2); }
| LTYPER nonrel { outcode($1, &$2); }
$1.Value = $3;
}
| LTYPE0 nonnon { outcode(int($1), &$2); }
| LTYPE1 nonrem { outcode(int($1), &$2); }
| LTYPE2 rimnon { outcode(int($1), &$2); }
| LTYPE3 rimrem { outcode(int($1), &$2); }
| LTYPE4 remrim { outcode(int($1), &$2); }
| LTYPER nonrel { outcode(int($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); }
| LTYPEC spec3 { outcode(int($1), &$2); }
| LTYPEN spec4 { outcode(int($1), &$2); }
| LTYPES spec5 { outcode(int($1), &$2); }
| LTYPEM spec6 { outcode(int($1), &$2); }
| LTYPEI spec7 { outcode(int($1), &$2); }
| spec8
| LTYPEXC spec9 { outcode($1, &$2); }
| LTYPEX spec10 { outcode($1, &$2); }
| LTYPEPC spec11 { outcode($1, &$2); }
| LTYPEF spec12 { outcode($1, &$2); }
| LTYPEXC spec9 { outcode(int($1), &$2); }
| LTYPEX spec10 { outcode(int($1), &$2); }
| LTYPEPC spec11 { outcode(int($1), &$2); }
| LTYPEF spec12 { outcode(int($1), &$2); }
nonnon:
{
@ -182,60 +192,46 @@ nonrel:
spec1: /* DATA */
LTYPED nam '/' con ',' imm
{
Addr2 a;
a.from = $2;
a.to = $6;
outcode(ADATA, &a);
if(pass > 1) {
lastpc->from3.type = TYPE_CONST;
lastpc->from3.offset = $4;
outcode(obj.ADATA, &Addr2{$2, $6})
if asm.Pass > 1 {
lastpc.From3.Type = obj.TYPE_CONST
lastpc.From3.Offset = $4
}
}
spec2: /* TEXT */
LTYPET mem ',' '$' textsize
{
Addr2 a;
settext($2.sym);
a.from = $2;
a.to = $5;
outcode(ATEXT, &a);
asm.Settext($2.Sym);
outcode(obj.ATEXT, &Addr2{$2, $5})
}
| LTYPET mem ',' con ',' '$' textsize
{
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;
asm.Settext($2.Sym);
outcode(obj.ATEXT, &Addr2{$2, $7})
if asm.Pass > 1 {
lastpc.From3.Type = obj.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);
asm.Settext($2.Sym);
outcode(obj.AGLOBL, &Addr2{$2, $4})
}
| 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;
asm.Settext($2.Sym);
outcode(obj.AGLOBL, &Addr2{$2, $6})
if asm.Pass > 1 {
lastpc.From3.Type = obj.TYPE_CONST
lastpc.From3.Offset = $4
}
}
spec3: /* JMP/CALL */
',' rom
{
@ -251,7 +247,7 @@ spec3: /* JMP/CALL */
{
$$.from = nullgen;
$$.to = $2;
$$.to.type = TYPE_INDIR;
$$.to.Type = obj.TYPE_INDIR
}
spec4: /* NOP */
@ -268,9 +264,10 @@ spec5: /* SHL/SHR */
{
$$.from = $1;
$$.to = $3;
if($$.from.index != TYPE_NONE)
if $$.from.Index != obj.TYPE_NONE {
yyerror("dp shift with lhs index");
$$.from.index = $5;
}
$$.from.Index = int16($5);
}
spec6: /* MOVW/MOVL */
@ -283,9 +280,10 @@ spec6: /* MOVW/MOVL */
{
$$.from = $1;
$$.to = $3;
if($$.to.index != TYPE_NONE)
if $$.to.Index != obj.TYPE_NONE {
yyerror("dp move with lhs index");
$$.to.index = $5;
}
$$.to.Index = int16($5);
}
spec7:
@ -310,7 +308,7 @@ spec9: /* CMPPS/CMPPD */
{
$$.from = $1;
$$.to = $3;
$$.to.offset = $5;
$$.to.Offset = $5;
}
spec10: /* PINSRD */
@ -318,16 +316,18 @@ spec10: /* PINSRD */
{
$$.from = $3;
$$.to = $5;
if($1.type != TYPE_CONST)
yyerror("illegal constant");
$$.to.offset = $1.offset;
if $1.Type != obj.TYPE_CONST {
yyerror("illegal constant")
}
$$.to.Offset = $1.Offset;
}
spec11: /* PCDATA */
rim ',' rim
{
if($1.type != TYPE_CONST || $3.type != TYPE_CONST)
if $1.Type != obj.TYPE_CONST || $3.Type != obj.TYPE_CONST {
yyerror("arguments to PCDATA must be integer constants");
}
$$.from = $1;
$$.to = $3;
}
@ -335,10 +335,12 @@ spec11: /* PCDATA */
spec12: /* FUNCDATA */
rim ',' rim
{
if($1.type != TYPE_CONST)
if $1.Type != obj.TYPE_CONST {
yyerror("index for FUNCDATA must be integer constant");
if($3.type != TYPE_MEM || ($3.name != NAME_EXTERN && $3.name != NAME_STATIC))
}
if $3.Type != obj.TYPE_MEM || ($3.Name != obj.NAME_EXTERN && $3.Name != obj.NAME_STATIC) {
yyerror("value for FUNCDATA must be symbol reference");
}
$$.from = $1;
$$.to = $3;
}
@ -370,135 +372,137 @@ rel:
con '(' LPC ')'
{
$$ = nullgen;
$$.type = TYPE_BRANCH;
$$.offset = $1 + pc;
$$.Type = obj.TYPE_BRANCH;
$$.Offset = $1 + int64(asm.PC);
}
| LNAME offset
{
$1 = labellookup($1);
$1 = asm.LabelLookup($1);
$$ = nullgen;
if(pass == 2 && $1->type != LLAB)
yyerror("undefined label: %s", $1->labelname);
$$.type = TYPE_BRANCH;
$$.offset = $1->value + $2;
if asm.Pass == 2 && $1.Type != LLAB {
yyerror("undefined label: %s", $1.Labelname);
}
$$.Type = obj.TYPE_BRANCH;
$$.Offset = $1.Value + $2;
}
reg:
LBREG
{
$$ = nullgen;
$$.type = TYPE_REG;
$$.reg = $1;
$$.Type = obj.TYPE_REG
$$.Reg = int16($1);
}
| LFREG
{
$$ = nullgen;
$$.type = TYPE_REG;
$$.reg = $1;
$$.Type = obj.TYPE_REG
$$.Reg = int16($1);
}
| LLREG
{
$$ = nullgen;
$$.type = TYPE_REG;
$$.reg = $1;
$$.Type = obj.TYPE_REG
$$.Reg = int16($1);
}
| LXREG
{
$$ = nullgen;
$$.type = TYPE_REG;
$$.reg = $1;
$$.Type = obj.TYPE_REG
$$.Reg = int16($1);
}
| LSP
{
$$ = nullgen;
$$.type = TYPE_REG;
$$.reg = REG_SP;
$$.Type = obj.TYPE_REG
$$.Reg = REG_SP;
}
| LSREG
{
$$ = nullgen;
$$.type = TYPE_REG;
$$.reg = $1;
$$.Type = obj.TYPE_REG
$$.Reg = int16($1);
}
imm:
'$' con
{
$$ = nullgen;
$$.type = TYPE_CONST;
$$.offset = $2;
$$.Type = obj.TYPE_CONST;
$$.Offset = $2;
}
| '$' nam
{
$$ = $2;
$$.type = TYPE_ADDR;
$$.Type = obj.TYPE_ADDR
/*
if($2.name == NAME_AUTO || $2.name == NAME_PARAM)
if($2.Type == D_AUTO || $2.Type == D_PARAM)
yyerror("constant cannot be automatic: %s",
$2.sym->name);
$2.Sym.name);
*/
}
| '$' LSCONST
{
$$ = nullgen;
$$.type = TYPE_SCONST;
memcpy($$.u.sval, $2, sizeof($$.u.sval));
$$.Type = obj.TYPE_SCONST;
$$.U.Sval = $2
}
| '$' LFCONST
{
$$ = nullgen;
$$.type = TYPE_FCONST;
$$.u.dval = $2;
$$.Type = obj.TYPE_FCONST;
$$.U.Dval = $2;
}
| '$' '(' LFCONST ')'
{
$$ = nullgen;
$$.type = TYPE_FCONST;
$$.u.dval = $3;
$$.Type = obj.TYPE_FCONST;
$$.U.Dval = $3;
}
| '$' '(' '-' LFCONST ')'
{
$$ = nullgen;
$$.type = TYPE_FCONST;
$$.u.dval = -$4;
$$.Type = obj.TYPE_FCONST;
$$.U.Dval = -$4;
}
| '$' '-' LFCONST
{
$$ = nullgen;
$$.type = TYPE_FCONST;
$$.u.dval = -$3;
$$.Type = obj.TYPE_FCONST;
$$.U.Dval = -$3;
}
textsize:
LCONST
{
$$ = nullgen;
$$.type = TYPE_TEXTSIZE;
$$.offset = $1;
$$.u.argsize = ArgsSizeUnknown;
$$.Type = obj.TYPE_TEXTSIZE;
$$.Offset = $1;
$$.U.Argsize = obj.ArgsSizeUnknown;
}
| '-' LCONST
{
$$ = nullgen;
$$.type = TYPE_TEXTSIZE;
$$.offset = -$2;
$$.u.argsize = ArgsSizeUnknown;
$$.Type = obj.TYPE_TEXTSIZE;
$$.Offset = -$2;
$$.U.Argsize = obj.ArgsSizeUnknown;
}
| LCONST '-' LCONST
{
$$ = nullgen;
$$.type = TYPE_TEXTSIZE;
$$.offset = $1;
$$.u.argsize = $3;
$$.Type = obj.TYPE_TEXTSIZE;
$$.Offset = $1;
$$.U.Argsize = int32($3);
}
| '-' LCONST '-' LCONST
{
$$ = nullgen;
$$.type = TYPE_TEXTSIZE;
$$.offset = -$2;
$$.u.argsize = $4;
$$.Type = obj.TYPE_TEXTSIZE;
$$.Offset = -$2;
$$.U.Argsize = int32($4);
}
mem:
omem
| nmem
@ -507,90 +511,87 @@ omem:
con
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.reg = REG_NONE;
$$.offset = $1;
$$.Type = obj.TYPE_MEM
$$.Offset = $1;
}
| con '(' LLREG ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.reg = $3;
$$.offset = $1;
$$.Type = obj.TYPE_MEM
$$.Reg = int16($3)
$$.Offset = $1;
}
| con '(' LSP ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.reg = REG_SP;
$$.offset = $1;
$$.Type = obj.TYPE_MEM
$$.Reg = REG_SP
$$.Offset = $1;
}
| con '(' LLREG '*' con ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.reg = REG_NONE;
$$.offset = $1;
$$.index = $3;
$$.scale = $5;
checkscale($$.scale);
$$.Type = obj.TYPE_MEM
$$.Offset = $1;
$$.Index = int16($3);
$$.Scale = int8($5);
checkscale($$.Scale);
}
| con '(' LLREG ')' '(' LLREG '*' con ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.reg = $3;
$$.offset = $1;
$$.index = $6;
$$.scale = $8;
checkscale($$.scale);
$$.Type = obj.TYPE_MEM
$$.Reg = int16($3)
$$.Offset = $1;
$$.Index = int16($6);
$$.Scale = int8($8);
checkscale($$.Scale);
}
| con '(' LLREG ')' '(' LSREG '*' con ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.reg = $3;
$$.offset = $1;
$$.index = $6;
$$.scale = $8;
checkscale($$.scale);
$$.Type = obj.TYPE_MEM
$$.Reg = int16($3)
$$.Offset = $1;
$$.Index = int16($6);
$$.Scale = int8($8);
checkscale($$.Scale);
}
| '(' LLREG ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.reg = $2;
$$.Type = obj.TYPE_MEM
$$.Reg = int16($2);
}
| '(' LSP ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.reg = REG_SP;
$$.Type = obj.TYPE_MEM
$$.Reg = REG_SP
}
| con '(' LSREG ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.reg = $3;
$$.offset = $1;
$$.Type = obj.TYPE_MEM
$$.Reg = int16($3)
$$.Offset = $1;
}
| '(' LLREG '*' con ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.reg = REG_NONE;
$$.index = $2;
$$.scale = $4;
checkscale($$.scale);
$$.Type = obj.TYPE_MEM
$$.Index = int16($2);
$$.Scale = int8($4);
checkscale($$.Scale);
}
| '(' LLREG ')' '(' LLREG '*' con ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.reg = $2;
$$.index = $5;
$$.scale = $7;
checkscale($$.scale);
$$.Type = obj.TYPE_MEM
$$.Reg = int16($2)
$$.Index = int16($5);
$$.Scale = int8($7);
checkscale($$.Scale);
}
nmem:
@ -601,27 +602,27 @@ nmem:
| nam '(' LLREG '*' con ')'
{
$$ = $1;
$$.index = $3;
$$.scale = $5;
checkscale($$.scale);
$$.Index = int16($3);
$$.Scale = int8($5);
checkscale($$.Scale);
}
nam:
LNAME offset '(' pointer ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.name = $4;
$$.sym = linklookup(ctxt, $1->name, 0);
$$.offset = $2;
$$.Type = obj.TYPE_MEM
$$.Name = int8($4);
$$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
$$.Offset = $2;
}
| LNAME '<' '>' offset '(' LSB ')'
{
$$ = nullgen;
$$.type = TYPE_MEM;
$$.name = NAME_STATIC;
$$.sym = linklookup(ctxt, $1->name, 1);
$$.offset = $4;
$$.Type = obj.TYPE_MEM
$$.Name = obj.NAME_STATIC
$$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 1);
$$.Offset = $4;
}
offset:
@ -641,7 +642,7 @@ pointer:
LSB
| LSP
{
$$ = NAME_AUTO;
$$ = obj.NAME_AUTO;
}
| LFP
@ -649,7 +650,7 @@ con:
LCONST
| LVAR
{
$$ = $1->value;
$$ = $1.Value;
}
| '-' con
{
@ -661,7 +662,7 @@ con:
}
| '~' con
{
$$ = ~$2;
$$ = ^$2;
}
| '(' expr ')'
{
@ -692,11 +693,11 @@ expr:
}
| expr '<' '<' expr
{
$$ = $1 << $4;
$$ = $1 << uint($4);
}
| expr '>' '>' expr
{
$$ = $1 >> $4;
$$ = $1 >> uint($4);
}
| expr '&' expr
{

View file

@ -1,21 +0,0 @@
// 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.
// +build ignore
/*
8a is a version of the Plan 9 assembler. The original is documented at
http://plan9.bell-labs.com/magic/man2html/1/8a
Go-specific considerations are documented at
http://golang.org/doc/asm
I
Its target architecture is the x86, referred to by these tools for historical reasons as 386.
*/
package main

View file

@ -1,914 +0,0 @@
// Inferno utils/8a/lex.c
// http://code.google.com/p/inferno-os/source/browse/utils/8a/lex.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#define EXTERN
#include <u.h>
#include <libc.h>
#include "a.h"
#include "y.tab.h"
enum
{
Plan9 = 1<<0,
Unix = 1<<1,
Windows = 1<<2,
};
int
systemtype(int sys)
{
#ifdef _WIN32
return sys&Windows;
#else
return sys&Plan9;
#endif
}
int
pathchar(void)
{
return '/';
}
int
Lconv(Fmt *fp)
{
return linklinefmt(ctxt, fp);
}
void
dodef(char *p)
{
if(nDlist%8 == 0)
Dlist = allocn(Dlist, nDlist*sizeof(char *),
8*sizeof(char *));
Dlist[nDlist++] = p;
}
void
usage(void)
{
print("usage: %ca [options] file.c...\n", thechar);
flagprint(1);
errorexit();
}
void
main(int argc, char *argv[])
{
char *p;
thechar = '8';
thestring = "386";
ctxt = linknew(&link386);
ctxt->diag = yyerror;
ctxt->bso = &bstdout;
ctxt->enforce_data_order = 1;
Binit(&bstdout, 1, OWRITE);
listinit8();
fmtinstall('L', Lconv);
// Allow GOARCH=thestring or GOARCH=thestringsuffix,
// but not other values.
p = getgoarch();
if(strncmp(p, thestring, strlen(thestring)) != 0)
sysfatal("cannot use %cc with GOARCH=%s", thechar, p);
ensuresymb(NSYMB);
memset(debug, 0, sizeof(debug));
cinit();
outfile = 0;
setinclude(".");
flagfn1("D", "name[=value]: add #define", dodef);
flagfn1("I", "dir: add dir to include path", setinclude);
flagcount("S", "print assembly and machine code", &debug['S']);
flagcount("m", "debug preprocessor macros", &debug['m']);
flagstr("o", "file: set output file", &outfile);
flagstr("trimpath", "prefix: remove prefix from recorded source file paths", &ctxt->trimpath);
flagparse(&argc, &argv, usage);
ctxt->debugasm = debug['S'];
if(argc < 1)
usage();
if(argc > 1){
print("can't assemble multiple files\n");
errorexit();
}
if(assemble(argv[0]))
errorexit();
Bflush(&bstdout);
if(nerrors > 0)
errorexit();
exits(0);
}
int
assemble(char *file)
{
char *ofile, *p;
int i, of;
ofile = alloc(strlen(file)+3); // +3 for .x\0 (x=thechar)
strcpy(ofile, file);
p = utfrrune(ofile, pathchar());
if(p) {
include[0] = ofile;
*p++ = 0;
} else
p = ofile;
if(outfile == 0) {
outfile = p;
if(outfile){
p = utfrrune(outfile, '.');
if(p)
if(p[1] == 's' && p[2] == 0)
p[0] = 0;
p = utfrune(outfile, 0);
p[0] = '.';
p[1] = thechar;
p[2] = 0;
} else
outfile = "/dev/null";
}
of = create(outfile, OWRITE, 0664);
if(of < 0) {
yyerror("%ca: cannot create %s", thechar, outfile);
errorexit();
}
Binit(&obuf, of, OWRITE);
Bprint(&obuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
Bprint(&obuf, "!\n");
for(pass = 1; pass <= 2; pass++) {
pinit(file);
for(i=0; i<nDlist; i++)
dodefine(Dlist[i]);
yyparse();
cclean();
if(nerrors)
return nerrors;
}
writeobj(ctxt, &obuf);
Bflush(&obuf);
return 0;
}
struct
{
char *name;
ushort type;
ushort value;
} itab[] =
{
"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,
"AAM", LTYPE0, AAAM,
"AAS", LTYPE0, AAAS,
"ADCB", LTYPE3, AADCB,
"ADCL", LTYPE3, AADCL,
"ADCW", LTYPE3, AADCW,
"ADDB", LTYPE3, AADDB,
"ADDL", LTYPE3, AADDL,
"ADDW", LTYPE3, AADDW,
"ADJSP", LTYPE2, AADJSP,
"ANDB", LTYPE3, AANDB,
"ANDL", LTYPE3, AANDL,
"ANDW", LTYPE3, AANDW,
"ARPL", LTYPE3, AARPL,
"BOUNDL", LTYPE3, ABOUNDL,
"BOUNDW", LTYPE3, ABOUNDW,
"BSFL", LTYPE3, ABSFL,
"BSFW", LTYPE3, ABSFW,
"BSRL", LTYPE3, ABSRL,
"BSRW", LTYPE3, ABSRW,
"BSWAPL", LTYPE1, ABSWAPL,
"BTCL", LTYPE3, ABTCL,
"BTCW", LTYPE3, ABTCW,
"BTL", LTYPE3, ABTL,
"BTRL", LTYPE3, ABTRL,
"BTRW", LTYPE3, ABTRW,
"BTSL", LTYPE3, ABTSL,
"BTSW", LTYPE3, ABTSW,
"BTW", LTYPE3, ABTW,
"BYTE", LTYPE2, ABYTE,
"CALL", LTYPEC, ACALL,
"CLC", LTYPE0, ACLC,
"CLD", LTYPE0, ACLD,
"CLI", LTYPE0, ACLI,
"CLTS", LTYPE0, ACLTS,
"CMC", LTYPE0, ACMC,
"CMPB", LTYPE4, ACMPB,
"CMPL", LTYPE4, ACMPL,
"CMPW", LTYPE4, ACMPW,
"CMPSB", LTYPE0, ACMPSB,
"CMPSL", LTYPE0, ACMPSL,
"CMPSW", LTYPE0, ACMPSW,
"CMPXCHG8B", LTYPE1, ACMPXCHG8B,
"CMPXCHGB", LTYPE3, ACMPXCHGB,
"CMPXCHGL", LTYPE3, ACMPXCHGL,
"CMPXCHGW", LTYPE3, ACMPXCHGW,
"CPUID", LTYPE0, ACPUID,
"DAA", LTYPE0, ADAA,
"DAS", LTYPE0, ADAS,
"DATA", LTYPED, ADATA,
"DECB", LTYPE1, ADECB,
"DECL", LTYPE1, ADECL,
"DECW", LTYPE1, ADECW,
"DIVB", LTYPE2, ADIVB,
"DIVL", LTYPE2, ADIVL,
"DIVW", LTYPE2, ADIVW,
"END", LTYPE0, AEND,
"ENTER", LTYPE2, AENTER,
"GLOBL", LTYPEG, AGLOBL,
"HLT", LTYPE0, AHLT,
"IDIVB", LTYPE2, AIDIVB,
"IDIVL", LTYPE2, AIDIVL,
"IDIVW", LTYPE2, AIDIVW,
"IMULB", LTYPE2, AIMULB,
"IMULL", LTYPEI, AIMULL,
"IMULW", LTYPEI, AIMULW,
"INB", LTYPE0, AINB,
"INL", LTYPE0, AINL,
"INW", LTYPE0, AINW,
"INCB", LTYPE1, AINCB,
"INCL", LTYPE1, AINCL,
"INCW", LTYPE1, AINCW,
"INSB", LTYPE0, AINSB,
"INSL", LTYPE0, AINSL,
"INSW", LTYPE0, AINSW,
"INT", LTYPE2, AINT,
"INTO", LTYPE0, AINTO,
"IRETL", LTYPE0, AIRETL,
"IRETW", LTYPE0, AIRETW,
"JOS", LTYPER, AJOS, /* overflow set (OF = 1) */
"JO", LTYPER, AJOS, /* alternate */
"JOC", LTYPER, AJOC, /* overflow clear (OF = 0) */
"JNO", LTYPER, AJOC, /* alternate */
"JCS", LTYPER, AJCS, /* carry set (CF = 1) */
"JB", LTYPER, AJCS, /* alternate */
"JC", LTYPER, AJCS, /* alternate */
"JNAE", LTYPER, AJCS, /* alternate */
"JLO", LTYPER, AJCS, /* alternate */
"JCC", LTYPER, AJCC, /* carry clear (CF = 0) */
"JAE", LTYPER, AJCC, /* alternate */
"JNB", LTYPER, AJCC, /* alternate */
"JNC", LTYPER, AJCC, /* alternate */
"JHS", LTYPER, AJCC, /* alternate */
"JEQ", LTYPER, AJEQ, /* equal (ZF = 1) */
"JE", LTYPER, AJEQ, /* alternate */
"JZ", LTYPER, AJEQ, /* alternate */
"JNE", LTYPER, AJNE, /* not equal (ZF = 0) */
"JNZ", LTYPER, AJNE, /* alternate */
"JLS", LTYPER, AJLS, /* lower or same (unsigned) (CF = 1 || ZF = 1) */
"JBE", LTYPER, AJLS, /* alternate */
"JNA", LTYPER, AJLS, /* alternate */
"JHI", LTYPER, AJHI, /* higher (unsigned) (CF = 0 && ZF = 0) */
"JA", LTYPER, AJHI, /* alternate */
"JNBE", LTYPER, AJHI, /* alternate */
"JMI", LTYPER, AJMI, /* negative (minus) (SF = 1) */
"JS", LTYPER, AJMI, /* alternate */
"JPL", LTYPER, AJPL, /* non-negative (plus) (SF = 0) */
"JNS", LTYPER, AJPL, /* alternate */
"JPS", LTYPER, AJPS, /* parity set (PF = 1) */
"JP", LTYPER, AJPS, /* alternate */
"JPE", LTYPER, AJPS, /* alternate */
"JPC", LTYPER, AJPC, /* parity clear (PF = 0) */
"JNP", LTYPER, AJPC, /* alternate */
"JPO", LTYPER, AJPC, /* alternate */
"JLT", LTYPER, AJLT, /* less than (signed) (SF != OF) */
"JL", LTYPER, AJLT, /* alternate */
"JNGE", LTYPER, AJLT, /* alternate */
"JGE", LTYPER, AJGE, /* greater than or equal (signed) (SF = OF) */
"JNL", LTYPER, AJGE, /* alternate */
"JLE", LTYPER, AJLE, /* less than or equal (signed) (ZF = 1 || SF != OF) */
"JNG", LTYPER, AJLE, /* alternate */
"JGT", LTYPER, AJGT, /* greater than (signed) (ZF = 0 && SF = OF) */
"JG", LTYPER, AJGT, /* alternate */
"JNLE", LTYPER, AJGT, /* alternate */
"JCXZL", LTYPER, AJCXZL,
"JCXZW", LTYPER, AJCXZW,
"JMP", LTYPEC, AJMP,
"LAHF", LTYPE0, ALAHF,
"LARL", LTYPE3, ALARL,
"LARW", LTYPE3, ALARW,
"LEAL", LTYPE3, ALEAL,
"LEAW", LTYPE3, ALEAW,
"LEAVEL", LTYPE0, ALEAVEL,
"LEAVEW", LTYPE0, ALEAVEW,
"LOCK", LTYPE0, ALOCK,
"LODSB", LTYPE0, ALODSB,
"LODSL", LTYPE0, ALODSL,
"LODSW", LTYPE0, ALODSW,
"LONG", LTYPE2, ALONG,
"LOOP", LTYPER, ALOOP,
"LOOPEQ", LTYPER, ALOOPEQ,
"LOOPNE", LTYPER, ALOOPNE,
"LSLL", LTYPE3, ALSLL,
"LSLW", LTYPE3, ALSLW,
"MOVB", LTYPE3, AMOVB,
"MOVL", LTYPEM, AMOVL,
"MOVW", LTYPEM, AMOVW,
"MOVQ", LTYPEM, AMOVQ,
"MOVBLSX", LTYPE3, AMOVBLSX,
"MOVBLZX", LTYPE3, AMOVBLZX,
"MOVBWSX", LTYPE3, AMOVBWSX,
"MOVBWZX", LTYPE3, AMOVBWZX,
"MOVWLSX", LTYPE3, AMOVWLSX,
"MOVWLZX", LTYPE3, AMOVWLZX,
"MOVSB", LTYPE0, AMOVSB,
"MOVSL", LTYPE0, AMOVSL,
"MOVSW", LTYPE0, AMOVSW,
"MULB", LTYPE2, AMULB,
"MULL", LTYPE2, AMULL,
"MULW", LTYPE2, AMULW,
"NEGB", LTYPE1, ANEGB,
"NEGL", LTYPE1, ANEGL,
"NEGW", LTYPE1, ANEGW,
"NOP", LTYPEN, ANOP,
"NOTB", LTYPE1, ANOTB,
"NOTL", LTYPE1, ANOTL,
"NOTW", LTYPE1, ANOTW,
"ORB", LTYPE3, AORB,
"ORL", LTYPE3, AORL,
"ORW", LTYPE3, AORW,
"OUTB", LTYPE0, AOUTB,
"OUTL", LTYPE0, AOUTL,
"OUTW", LTYPE0, AOUTW,
"OUTSB", LTYPE0, AOUTSB,
"OUTSL", LTYPE0, AOUTSL,
"OUTSW", LTYPE0, AOUTSW,
"PAUSE", LTYPEN, APAUSE,
"PINSRD", LTYPEX, APINSRD,
"POPAL", LTYPE0, APOPAL,
"POPAW", LTYPE0, APOPAW,
"POPFL", LTYPE0, APOPFL,
"POPFW", LTYPE0, APOPFW,
"POPL", LTYPE1, APOPL,
"POPW", LTYPE1, APOPW,
"PUSHAL", LTYPE0, APUSHAL,
"PUSHAW", LTYPE0, APUSHAW,
"PUSHFL", LTYPE0, APUSHFL,
"PUSHFW", LTYPE0, APUSHFW,
"PUSHL", LTYPE2, APUSHL,
"PUSHW", LTYPE2, APUSHW,
"RCLB", LTYPE3, ARCLB,
"RCLL", LTYPE3, ARCLL,
"RCLW", LTYPE3, ARCLW,
"RCRB", LTYPE3, ARCRB,
"RCRL", LTYPE3, ARCRL,
"RCRW", LTYPE3, ARCRW,
"RDTSC", LTYPE0, ARDTSC,
"REP", LTYPE0, AREP,
"REPN", LTYPE0, AREPN,
"RET", LTYPE0, ARET,
"ROLB", LTYPE3, AROLB,
"ROLL", LTYPE3, AROLL,
"ROLW", LTYPE3, AROLW,
"RORB", LTYPE3, ARORB,
"RORL", LTYPE3, ARORL,
"RORW", LTYPE3, ARORW,
"SAHF", LTYPE0, ASAHF,
"SALB", LTYPE3, ASALB,
"SALL", LTYPE3, ASALL,
"SALW", LTYPE3, ASALW,
"SARB", LTYPE3, ASARB,
"SARL", LTYPE3, ASARL,
"SARW", LTYPE3, ASARW,
"SBBB", LTYPE3, ASBBB,
"SBBL", LTYPE3, ASBBL,
"SBBW", LTYPE3, ASBBW,
"SCASB", LTYPE0, ASCASB,
"SCASL", LTYPE0, ASCASL,
"SCASW", LTYPE0, ASCASW,
"SETCC", LTYPE1, ASETCC, /* see JCC etc above for condition codes */
"SETCS", LTYPE1, ASETCS,
"SETEQ", LTYPE1, ASETEQ,
"SETGE", LTYPE1, ASETGE,
"SETGT", LTYPE1, ASETGT,
"SETHI", LTYPE1, ASETHI,
"SETLE", LTYPE1, ASETLE,
"SETLS", LTYPE1, ASETLS,
"SETLT", LTYPE1, ASETLT,
"SETMI", LTYPE1, ASETMI,
"SETNE", LTYPE1, ASETNE,
"SETOC", LTYPE1, ASETOC,
"SETOS", LTYPE1, ASETOS,
"SETPC", LTYPE1, ASETPC,
"SETPL", LTYPE1, ASETPL,
"SETPS", LTYPE1, ASETPS,
"CDQ", LTYPE0, ACDQ,
"CWD", LTYPE0, ACWD,
"SHLB", LTYPE3, ASHLB,
"SHLL", LTYPES, ASHLL,
"SHLW", LTYPES, ASHLW,
"SHRB", LTYPE3, ASHRB,
"SHRL", LTYPES, ASHRL,
"SHRW", LTYPES, ASHRW,
"STC", LTYPE0, ASTC,
"STD", LTYPE0, ASTD,
"STI", LTYPE0, ASTI,
"STOSB", LTYPE0, ASTOSB,
"STOSL", LTYPE0, ASTOSL,
"STOSW", LTYPE0, ASTOSW,
"SUBB", LTYPE3, ASUBB,
"SUBL", LTYPE3, ASUBL,
"SUBW", LTYPE3, ASUBW,
"SYSCALL", LTYPE0, ASYSCALL,
"TESTB", LTYPE3, ATESTB,
"TESTL", LTYPE3, ATESTL,
"TESTW", LTYPE3, ATESTW,
"TEXT", LTYPET, ATEXT,
"VERR", LTYPE2, AVERR,
"VERW", LTYPE2, AVERW,
"WAIT", LTYPE0, AWAIT,
"WORD", LTYPE2, AWORD,
"XADDB", LTYPE3, AXADDB,
"XADDL", LTYPE3, AXADDL,
"XADDW", LTYPE3, AXADDW,
"XCHGB", LTYPE3, AXCHGB,
"XCHGL", LTYPE3, AXCHGL,
"XCHGW", LTYPE3, AXCHGW,
"XLAT", LTYPE2, AXLAT,
"XORB", LTYPE3, AXORB,
"XORL", LTYPE3, AXORL,
"XORW", LTYPE3, AXORW,
"CMOVLCC", LTYPE3, ACMOVLCC,
"CMOVLCS", LTYPE3, ACMOVLCS,
"CMOVLEQ", LTYPE3, ACMOVLEQ,
"CMOVLGE", LTYPE3, ACMOVLGE,
"CMOVLGT", LTYPE3, ACMOVLGT,
"CMOVLHI", LTYPE3, ACMOVLHI,
"CMOVLLE", LTYPE3, ACMOVLLE,
"CMOVLLS", LTYPE3, ACMOVLLS,
"CMOVLLT", LTYPE3, ACMOVLLT,
"CMOVLMI", LTYPE3, ACMOVLMI,
"CMOVLNE", LTYPE3, ACMOVLNE,
"CMOVLOC", LTYPE3, ACMOVLOC,
"CMOVLOS", LTYPE3, ACMOVLOS,
"CMOVLPC", LTYPE3, ACMOVLPC,
"CMOVLPL", LTYPE3, ACMOVLPL,
"CMOVLPS", LTYPE3, ACMOVLPS,
"CMOVWCC", LTYPE3, ACMOVWCC,
"CMOVWCS", LTYPE3, ACMOVWCS,
"CMOVWEQ", LTYPE3, ACMOVWEQ,
"CMOVWGE", LTYPE3, ACMOVWGE,
"CMOVWGT", LTYPE3, ACMOVWGT,
"CMOVWHI", LTYPE3, ACMOVWHI,
"CMOVWLE", LTYPE3, ACMOVWLE,
"CMOVWLS", LTYPE3, ACMOVWLS,
"CMOVWLT", LTYPE3, ACMOVWLT,
"CMOVWMI", LTYPE3, ACMOVWMI,
"CMOVWNE", LTYPE3, ACMOVWNE,
"CMOVWOC", LTYPE3, ACMOVWOC,
"CMOVWOS", LTYPE3, ACMOVWOS,
"CMOVWPC", LTYPE3, ACMOVWPC,
"CMOVWPL", LTYPE3, ACMOVWPL,
"CMOVWPS", LTYPE3, ACMOVWPS,
"FMOVB", LTYPE3, AFMOVB,
"FMOVBP", LTYPE3, AFMOVBP,
"FMOVD", LTYPE3, AFMOVD,
"FMOVDP", LTYPE3, AFMOVDP,
"FMOVF", LTYPE3, AFMOVF,
"FMOVFP", LTYPE3, AFMOVFP,
"FMOVL", LTYPE3, AFMOVL,
"FMOVLP", LTYPE3, AFMOVLP,
"FMOVV", LTYPE3, AFMOVV,
"FMOVVP", LTYPE3, AFMOVVP,
"FMOVW", LTYPE3, AFMOVW,
"FMOVWP", LTYPE3, AFMOVWP,
"FMOVX", LTYPE3, AFMOVX,
"FMOVXP", LTYPE3, AFMOVXP,
"FCMOVCC", LTYPE3, AFCMOVCC,
"FCMOVCS", LTYPE3, AFCMOVCS,
"FCMOVEQ", LTYPE3, AFCMOVEQ,
"FCMOVHI", LTYPE3, AFCMOVHI,
"FCMOVLS", LTYPE3, AFCMOVLS,
"FCMOVNE", LTYPE3, AFCMOVNE,
"FCMOVNU", LTYPE3, AFCMOVNU,
"FCMOVUN", LTYPE3, AFCMOVUN,
"FCOMB", LTYPE3, AFCOMB,
"FCOMBP", LTYPE3, AFCOMBP,
"FCOMD", LTYPE3, AFCOMD,
"FCOMDP", LTYPE3, AFCOMDP,
"FCOMDPP", LTYPE3, AFCOMDPP,
"FCOMF", LTYPE3, AFCOMF,
"FCOMFP", LTYPE3, AFCOMFP,
"FCOMI", LTYPE3, AFCOMI,
"FCOMIP", LTYPE3, AFCOMIP,
"FCOML", LTYPE3, AFCOML,
"FCOMLP", LTYPE3, AFCOMLP,
"FCOMW", LTYPE3, AFCOMW,
"FCOMWP", LTYPE3, AFCOMWP,
"FUCOM", LTYPE3, AFUCOM,
"FUCOMI", LTYPE3, AFUCOMI,
"FUCOMIP", LTYPE3, AFUCOMIP,
"FUCOMP", LTYPE3, AFUCOMP,
"FUCOMPP", LTYPE3, AFUCOMPP,
"FADDW", LTYPE3, AFADDW,
"FADDL", LTYPE3, AFADDL,
"FADDF", LTYPE3, AFADDF,
"FADDD", LTYPE3, AFADDD,
"FADDDP", LTYPE3, AFADDDP,
"FSUBDP", LTYPE3, AFSUBDP,
"FSUBW", LTYPE3, AFSUBW,
"FSUBL", LTYPE3, AFSUBL,
"FSUBF", LTYPE3, AFSUBF,
"FSUBD", LTYPE3, AFSUBD,
"FSUBRDP", LTYPE3, AFSUBRDP,
"FSUBRW", LTYPE3, AFSUBRW,
"FSUBRL", LTYPE3, AFSUBRL,
"FSUBRF", LTYPE3, AFSUBRF,
"FSUBRD", LTYPE3, AFSUBRD,
"FMULDP", LTYPE3, AFMULDP,
"FMULW", LTYPE3, AFMULW,
"FMULL", LTYPE3, AFMULL,
"FMULF", LTYPE3, AFMULF,
"FMULD", LTYPE3, AFMULD,
"FDIVDP", LTYPE3, AFDIVDP,
"FDIVW", LTYPE3, AFDIVW,
"FDIVL", LTYPE3, AFDIVL,
"FDIVF", LTYPE3, AFDIVF,
"FDIVD", LTYPE3, AFDIVD,
"FDIVRDP", LTYPE3, AFDIVRDP,
"FDIVRW", LTYPE3, AFDIVRW,
"FDIVRL", LTYPE3, AFDIVRL,
"FDIVRF", LTYPE3, AFDIVRF,
"FDIVRD", LTYPE3, AFDIVRD,
"FXCHD", LTYPE3, AFXCHD,
"FFREE", LTYPE1, AFFREE,
"FLDCW", LTYPE2, AFLDCW,
"FLDENV", LTYPE1, AFLDENV,
"FRSTOR", LTYPE2, AFRSTOR,
"FSAVE", LTYPE1, AFSAVE,
"FSTCW", LTYPE1, AFSTCW,
"FSTENV", LTYPE1, AFSTENV,
"FSTSW", LTYPE1, AFSTSW,
"F2XM1", LTYPE0, AF2XM1,
"FABS", LTYPE0, AFABS,
"FCHS", LTYPE0, AFCHS,
"FCLEX", LTYPE0, AFCLEX,
"FCOS", LTYPE0, AFCOS,
"FDECSTP", LTYPE0, AFDECSTP,
"FINCSTP", LTYPE0, AFINCSTP,
"FINIT", LTYPE0, AFINIT,
"FLD1", LTYPE0, AFLD1,
"FLDL2E", LTYPE0, AFLDL2E,
"FLDL2T", LTYPE0, AFLDL2T,
"FLDLG2", LTYPE0, AFLDLG2,
"FLDLN2", LTYPE0, AFLDLN2,
"FLDPI", LTYPE0, AFLDPI,
"FLDZ", LTYPE0, AFLDZ,
"FNOP", LTYPE0, AFNOP,
"FPATAN", LTYPE0, AFPATAN,
"FPREM", LTYPE0, AFPREM,
"FPREM1", LTYPE0, AFPREM1,
"FPTAN", LTYPE0, AFPTAN,
"FRNDINT", LTYPE0, AFRNDINT,
"FSCALE", LTYPE0, AFSCALE,
"FSIN", LTYPE0, AFSIN,
"FSINCOS", LTYPE0, AFSINCOS,
"FSQRT", LTYPE0, AFSQRT,
"FTST", LTYPE0, AFTST,
"FXAM", LTYPE0, AFXAM,
"FXTRACT", LTYPE0, AFXTRACT,
"FYL2X", LTYPE0, AFYL2X,
"FYL2XP1", LTYPE0, AFYL2XP1,
"LFENCE", LTYPE0, ALFENCE,
"MFENCE", LTYPE0, AMFENCE,
"SFENCE", LTYPE0, ASFENCE,
"EMMS", LTYPE0, AEMMS,
"PREFETCHT0", LTYPE2, APREFETCHT0,
"PREFETCHT1", LTYPE2, APREFETCHT1,
"PREFETCHT2", LTYPE2, APREFETCHT2,
"PREFETCHNTA", LTYPE2, APREFETCHNTA,
"UNDEF", LTYPE0, AUNDEF,
"ADDPD", LTYPE3, AADDPD,
"ADDPS", LTYPE3, AADDPS,
"ADDSD", LTYPE3, AADDSD,
"ADDSS", LTYPE3, AADDSS,
"AESENC", LTYPE3, AAESENC,
"ANDNPD", LTYPE3, AANDNPD,
"ANDNPS", LTYPE3, AANDNPS,
"ANDPD", LTYPE3, AANDPD,
"ANDPS", LTYPE3, AANDPS,
"CMPPD", LTYPEXC,ACMPPD,
"CMPPS", LTYPEXC,ACMPPS,
"CMPSD", LTYPEXC,ACMPSD,
"CMPSS", LTYPEXC,ACMPSS,
"COMISD", LTYPE3, ACOMISD,
"COMISS", LTYPE3, ACOMISS,
"CVTPL2PD", LTYPE3, ACVTPL2PD,
"CVTPL2PS", LTYPE3, ACVTPL2PS,
"CVTPD2PL", LTYPE3, ACVTPD2PL,
"CVTPD2PS", LTYPE3, ACVTPD2PS,
"CVTPS2PL", LTYPE3, ACVTPS2PL,
"CVTPS2PD", LTYPE3, ACVTPS2PD,
"CVTSD2SL", LTYPE3, ACVTSD2SL,
"CVTSD2SS", LTYPE3, ACVTSD2SS,
"CVTSL2SD", LTYPE3, ACVTSL2SD,
"CVTSL2SS", LTYPE3, ACVTSL2SS,
"CVTSS2SD", LTYPE3, ACVTSS2SD,
"CVTSS2SL", LTYPE3, ACVTSS2SL,
"CVTTPD2PL", LTYPE3, ACVTTPD2PL,
"CVTTPS2PL", LTYPE3, ACVTTPS2PL,
"CVTTSD2SL", LTYPE3, ACVTTSD2SL,
"CVTTSS2SL", LTYPE3, ACVTTSS2SL,
"DIVPD", LTYPE3, ADIVPD,
"DIVPS", LTYPE3, ADIVPS,
"DIVSD", LTYPE3, ADIVSD,
"DIVSS", LTYPE3, ADIVSS,
"MASKMOVOU", LTYPE3, AMASKMOVOU,
"MASKMOVDQU", LTYPE3, AMASKMOVOU, /* syn */
"MAXPD", LTYPE3, AMAXPD,
"MAXPS", LTYPE3, AMAXPS,
"MAXSD", LTYPE3, AMAXSD,
"MAXSS", LTYPE3, AMAXSS,
"MINPD", LTYPE3, AMINPD,
"MINPS", LTYPE3, AMINPS,
"MINSD", LTYPE3, AMINSD,
"MINSS", LTYPE3, AMINSS,
"MOVAPD", LTYPE3, AMOVAPD,
"MOVAPS", LTYPE3, AMOVAPS,
"MOVO", LTYPE3, AMOVO,
"MOVOA", LTYPE3, AMOVO, /* syn */
"MOVOU", LTYPE3, AMOVOU,
"MOVHLPS", LTYPE3, AMOVHLPS,
"MOVHPD", LTYPE3, AMOVHPD,
"MOVHPS", LTYPE3, AMOVHPS,
"MOVLHPS", LTYPE3, AMOVLHPS,
"MOVLPD", LTYPE3, AMOVLPD,
"MOVLPS", LTYPE3, AMOVLPS,
"MOVMSKPD", LTYPE3, AMOVMSKPD,
"MOVMSKPS", LTYPE3, AMOVMSKPS,
"MOVNTO", LTYPE3, AMOVNTO,
"MOVNTDQ", LTYPE3, AMOVNTO, /* syn */
"MOVNTPD", LTYPE3, AMOVNTPD,
"MOVNTPS", LTYPE3, AMOVNTPS,
"MOVSD", LTYPE3, AMOVSD,
"MOVSS", LTYPE3, AMOVSS,
"MOVUPD", LTYPE3, AMOVUPD,
"MOVUPS", LTYPE3, AMOVUPS,
"MULPD", LTYPE3, AMULPD,
"MULPS", LTYPE3, AMULPS,
"MULSD", LTYPE3, AMULSD,
"MULSS", LTYPE3, AMULSS,
"ORPD", LTYPE3, AORPD,
"ORPS", LTYPE3, AORPS,
"PADDQ", LTYPE3, APADDQ,
"PAND", LTYPE3, APAND,
"PCMPEQB", LTYPE3, APCMPEQB,
"PMAXSW", LTYPE3, APMAXSW,
"PMAXUB", LTYPE3, APMAXUB,
"PMINSW", LTYPE3, APMINSW,
"PMINUB", LTYPE3, APMINUB,
"PMOVMSKB", LTYPE3, APMOVMSKB,
"PSADBW", LTYPE3, APSADBW,
"PSHUFB", LTYPE3, APSHUFB,
"PSHUFHW", LTYPEX, APSHUFHW,
"PSHUFL", LTYPEX, APSHUFL,
"PSHUFLW", LTYPEX, APSHUFLW,
"PSUBB", LTYPE3, APSUBB,
"PSUBL", LTYPE3, APSUBL,
"PSUBQ", LTYPE3, APSUBQ,
"PSUBSB", LTYPE3, APSUBSB,
"PSUBSW", LTYPE3, APSUBSW,
"PSUBUSB", LTYPE3, APSUBUSB,
"PSUBUSW", LTYPE3, APSUBUSW,
"PSUBW", LTYPE3, APSUBW,
"PUNPCKHQDQ", LTYPE3, APUNPCKHQDQ,
"PUNPCKLQDQ", LTYPE3, APUNPCKLQDQ,
"PXOR", LTYPE3, APXOR,
"RCPPS", LTYPE3, ARCPPS,
"RCPSS", LTYPE3, ARCPSS,
"RSQRTPS", LTYPE3, ARSQRTPS,
"RSQRTSS", LTYPE3, ARSQRTSS,
"SQRTPD", LTYPE3, ASQRTPD,
"SQRTPS", LTYPE3, ASQRTPS,
"SQRTSD", LTYPE3, ASQRTSD,
"SQRTSS", LTYPE3, ASQRTSS,
"SUBPD", LTYPE3, ASUBPD,
"SUBPS", LTYPE3, ASUBPS,
"SUBSD", LTYPE3, ASUBSD,
"SUBSS", LTYPE3, ASUBSS,
"UCOMISD", LTYPE3, AUCOMISD,
"UCOMISS", LTYPE3, AUCOMISS,
"UNPCKHPD", LTYPE3, AUNPCKHPD,
"UNPCKHPS", LTYPE3, AUNPCKHPS,
"UNPCKLPD", LTYPE3, AUNPCKLPD,
"UNPCKLPS", LTYPE3, AUNPCKLPS,
"XORPD", LTYPE3, AXORPD,
"XORPS", LTYPE3, AXORPS,
"USEFIELD", LTYPEN, AUSEFIELD,
"PCDATA", LTYPEPC, APCDATA,
"FUNCDATA", LTYPEF, AFUNCDATA,
0
};
void
cinit(void)
{
Sym *s;
int i;
nullgen.type = TYPE_NONE;
nullgen.index = TYPE_NONE;
nerrors = 0;
iostack = I;
iofree = I;
peekc = IGN;
nhunk = 0;
for(i=0; i<NHASH; i++)
hash[i] = S;
for(i=0; itab[i].name; i++) {
s = slookup(itab[i].name);
if(s->type != LNAME)
yyerror("double initialization %s", itab[i].name);
s->type = itab[i].type;
s->value = itab[i].value;
}
}
void
checkscale(int scale)
{
switch(scale) {
case 1:
case 2:
case 4:
case 8:
return;
}
yyerror("scale must be 1248: %d", scale);
}
void
syminit(Sym *s)
{
s->type = LNAME;
s->value = 0;
}
void
cclean(void)
{
Addr2 g2;
g2.from = nullgen;
g2.to = nullgen;
outcode(AEND, &g2);
}
void
outcode(int a, Addr2 *g2)
{
Prog *p;
Plist *pl;
if(pass == 1)
goto out;
p = malloc(sizeof *p);
memset(p, 0, sizeof *p);
p->as = a;
p->lineno = stmtline;
p->from = g2->from;
p->to = g2->to;
p->pc = pc;
if(lastpc == nil) {
pl = linknewplist(ctxt);
pl->firstpc = p;
} else
lastpc->link = p;
lastpc = p;
out:
if(a != AGLOBL && a != ADATA)
pc++;
}
#include "../cc/lexbody"
#include "../cc/macbody"

File diff suppressed because it is too large Load diff

View file

@ -1,135 +0,0 @@
/* A Bison parser, made by GNU Bison 2.3. */
/* Skeleton interface for Bison's Yacc-like parsers in C
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
under terms of your choice, so long as that work isn't itself a
parser generator using the skeleton or a modified version thereof
as a parser skeleton. Alternatively, if you modify or redistribute
the parser skeleton itself, you may (at your option) remove this
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
LTYPE0 = 258,
LTYPE1 = 259,
LTYPE2 = 260,
LTYPE3 = 261,
LTYPE4 = 262,
LTYPEC = 263,
LTYPED = 264,
LTYPEN = 265,
LTYPER = 266,
LTYPET = 267,
LTYPES = 268,
LTYPEM = 269,
LTYPEI = 270,
LTYPEG = 271,
LTYPEXC = 272,
LTYPEX = 273,
LTYPEPC = 274,
LTYPEF = 275,
LCONST = 276,
LFP = 277,
LPC = 278,
LSB = 279,
LBREG = 280,
LLREG = 281,
LSREG = 282,
LFREG = 283,
LXREG = 284,
LFCONST = 285,
LSCONST = 286,
LSP = 287,
LNAME = 288,
LLAB = 289,
LVAR = 290
};
#endif
/* Tokens. */
#define LTYPE0 258
#define LTYPE1 259
#define LTYPE2 260
#define LTYPE3 261
#define LTYPE4 262
#define LTYPEC 263
#define LTYPED 264
#define LTYPEN 265
#define LTYPER 266
#define LTYPET 267
#define LTYPES 268
#define LTYPEM 269
#define LTYPEI 270
#define LTYPEG 271
#define LTYPEXC 272
#define LTYPEX 273
#define LTYPEPC 274
#define LTYPEF 275
#define LCONST 276
#define LFP 277
#define LPC 278
#define LSB 279
#define LBREG 280
#define LLREG 281
#define LSREG 282
#define LFREG 283
#define LXREG 284
#define LFCONST 285
#define LSCONST 286
#define LSP 287
#define LNAME 288
#define LLAB 289
#define LVAR 290
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
#line 38 "a.y"
{
Sym *sym;
int32 lval;
double dval;
char sval[8];
Addr addr;
Addr2 addr2;
}
/* Line 1529 of yacc.c. */
#line 128 "y.tab.h"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
#endif
extern YYSTYPE yylval;

View file

@ -1,5 +0,0 @@
# Copyright 2012 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.
include ../../Make.dist

File diff suppressed because it is too large Load diff

View file

@ -1,549 +0,0 @@
// 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.
#include <u.h>
#include <libc.h>
#include "gg.h"
/*
* attempt to generate 64-bit
* res = n
* return 1 on success, 0 if op not handled.
*/
void
cgen64(Node *n, Node *res)
{
Node t1, t2, ax, dx, cx, ex, fx, *l, *r;
Node lo1, lo2, hi1, hi2;
Prog *p1, *p2;
uint64 v;
uint32 lv, hv;
if(res->op != OINDREG && res->op != ONAME) {
dump("n", n);
dump("res", res);
fatal("cgen64 %O of %O", n->op, res->op);
}
switch(n->op) {
default:
fatal("cgen64 %O", n->op);
case OMINUS:
cgen(n->left, res);
split64(res, &lo1, &hi1);
gins(ANEGL, N, &lo1);
gins(AADCL, ncon(0), &hi1);
gins(ANEGL, N, &hi1);
splitclean();
return;
case OCOM:
cgen(n->left, res);
split64(res, &lo1, &hi1);
gins(ANOTL, N, &lo1);
gins(ANOTL, N, &hi1);
splitclean();
return;
case OADD:
case OSUB:
case OMUL:
case OLROT:
case OLSH:
case ORSH:
case OAND:
case OOR:
case OXOR:
// binary operators.
// common setup below.
break;
}
l = n->left;
r = n->right;
if(!l->addable) {
tempname(&t1, l->type);
cgen(l, &t1);
l = &t1;
}
if(r != N && !r->addable) {
tempname(&t2, r->type);
cgen(r, &t2);
r = &t2;
}
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);
if(is64(r->type))
split64(r, &lo2, &hi2);
// Do op. Leave result in DX:AX.
switch(n->op) {
case OADD:
// TODO: Constants
gins(AMOVL, &lo1, &ax);
gins(AMOVL, &hi1, &dx);
gins(AADDL, &lo2, &ax);
gins(AADCL, &hi2, &dx);
break;
case OSUB:
// TODO: Constants.
gins(AMOVL, &lo1, &ax);
gins(AMOVL, &hi1, &dx);
gins(ASUBL, &lo2, &ax);
gins(ASBBL, &hi2, &dx);
break;
case OMUL:
// let's call the next two EX and FX.
regalloc(&ex, types[TPTR32], N);
regalloc(&fx, types[TPTR32], N);
// load args into DX:AX and EX:CX.
gins(AMOVL, &lo1, &ax);
gins(AMOVL, &hi1, &dx);
gins(AMOVL, &lo2, &cx);
gins(AMOVL, &hi2, &ex);
// if DX and EX are zero, use 32 x 32 -> 64 unsigned multiply.
gins(AMOVL, &dx, &fx);
gins(AORL, &ex, &fx);
p1 = gbranch(AJNE, T, 0);
gins(AMULL, &cx, N); // implicit &ax
p2 = gbranch(AJMP, T, 0);
patch(p1, pc);
// full 64x64 -> 64, from 32x32 -> 64.
gins(AIMULL, &cx, &dx);
gins(AMOVL, &ax, &fx);
gins(AIMULL, &ex, &fx);
gins(AADDL, &dx, &fx);
gins(AMOVL, &cx, &dx);
gins(AMULL, &dx, N); // implicit &ax
gins(AADDL, &fx, &dx);
patch(p2, pc);
regfree(&ex);
regfree(&fx);
break;
case OLROT:
// We only rotate by a constant c in [0,64).
// if c >= 32:
// lo, hi = hi, lo
// c -= 32
// if c == 0:
// no-op
// else:
// t = hi
// shld hi:lo, c
// shld lo:t, c
v = mpgetfix(r->val.u.xval);
if(v >= 32) {
// reverse during load to do the first 32 bits of rotate
v -= 32;
gins(AMOVL, &lo1, &dx);
gins(AMOVL, &hi1, &ax);
} else {
gins(AMOVL, &lo1, &ax);
gins(AMOVL, &hi1, &dx);
}
if(v == 0) {
// done
} else {
gins(AMOVL, &dx, &cx);
p1 = gins(ASHLL, ncon(v), &dx);
p1->from.index = REG_AX; // double-width shift
p1->from.scale = 0;
p1 = gins(ASHLL, ncon(v), &ax);
p1->from.index = REG_CX; // double-width shift
p1->from.scale = 0;
}
break;
case OLSH:
if(r->op == OLITERAL) {
v = mpgetfix(r->val.u.xval);
if(v >= 64) {
if(is64(r->type))
splitclean();
splitclean();
split64(res, &lo2, &hi2);
gins(AMOVL, ncon(0), &lo2);
gins(AMOVL, ncon(0), &hi2);
splitclean();
goto out;
}
if(v >= 32) {
if(is64(r->type))
splitclean();
split64(res, &lo2, &hi2);
gmove(&lo1, &hi2);
if(v > 32) {
gins(ASHLL, ncon(v - 32), &hi2);
}
gins(AMOVL, ncon(0), &lo2);
splitclean();
splitclean();
goto out;
}
// general shift
gins(AMOVL, &lo1, &ax);
gins(AMOVL, &hi1, &dx);
p1 = gins(ASHLL, ncon(v), &dx);
p1->from.index = REG_AX; // double-width shift
p1->from.scale = 0;
gins(ASHLL, ncon(v), &ax);
break;
}
// load value into DX:AX.
gins(AMOVL, &lo1, &ax);
gins(AMOVL, &hi1, &dx);
// load shift value into register.
// if high bits are set, zero value.
p1 = P;
if(is64(r->type)) {
gins(ACMPL, &hi2, ncon(0));
p1 = gbranch(AJNE, T, +1);
gins(AMOVL, &lo2, &cx);
} else {
cx.type = types[TUINT32];
gmove(r, &cx);
}
// if shift count is >=64, zero value
gins(ACMPL, &cx, ncon(64));
p2 = gbranch(optoas(OLT, types[TUINT32]), T, +1);
if(p1 != P)
patch(p1, pc);
gins(AXORL, &dx, &dx);
gins(AXORL, &ax, &ax);
patch(p2, pc);
// if shift count is >= 32, zero low.
gins(ACMPL, &cx, ncon(32));
p1 = gbranch(optoas(OLT, types[TUINT32]), T, +1);
gins(AMOVL, &ax, &dx);
gins(ASHLL, &cx, &dx); // SHLL only uses bottom 5 bits of count
gins(AXORL, &ax, &ax);
p2 = gbranch(AJMP, T, 0);
patch(p1, pc);
// general shift
p1 = gins(ASHLL, &cx, &dx);
p1->from.index = REG_AX; // double-width shift
p1->from.scale = 0;
gins(ASHLL, &cx, &ax);
patch(p2, pc);
break;
case ORSH:
if(r->op == OLITERAL) {
v = mpgetfix(r->val.u.xval);
if(v >= 64) {
if(is64(r->type))
splitclean();
splitclean();
split64(res, &lo2, &hi2);
if(hi1.type->etype == TINT32) {
gmove(&hi1, &lo2);
gins(ASARL, ncon(31), &lo2);
gmove(&hi1, &hi2);
gins(ASARL, ncon(31), &hi2);
} else {
gins(AMOVL, ncon(0), &lo2);
gins(AMOVL, ncon(0), &hi2);
}
splitclean();
goto out;
}
if(v >= 32) {
if(is64(r->type))
splitclean();
split64(res, &lo2, &hi2);
gmove(&hi1, &lo2);
if(v > 32)
gins(optoas(ORSH, hi1.type), ncon(v-32), &lo2);
if(hi1.type->etype == TINT32) {
gmove(&hi1, &hi2);
gins(ASARL, ncon(31), &hi2);
} else
gins(AMOVL, ncon(0), &hi2);
splitclean();
splitclean();
goto out;
}
// general shift
gins(AMOVL, &lo1, &ax);
gins(AMOVL, &hi1, &dx);
p1 = gins(ASHRL, ncon(v), &ax);
p1->from.index = REG_DX; // double-width shift
p1->from.scale = 0;
gins(optoas(ORSH, hi1.type), ncon(v), &dx);
break;
}
// load value into DX:AX.
gins(AMOVL, &lo1, &ax);
gins(AMOVL, &hi1, &dx);
// load shift value into register.
// if high bits are set, zero value.
p1 = P;
if(is64(r->type)) {
gins(ACMPL, &hi2, ncon(0));
p1 = gbranch(AJNE, T, +1);
gins(AMOVL, &lo2, &cx);
} else {
cx.type = types[TUINT32];
gmove(r, &cx);
}
// if shift count is >=64, zero or sign-extend value
gins(ACMPL, &cx, ncon(64));
p2 = gbranch(optoas(OLT, types[TUINT32]), T, +1);
if(p1 != P)
patch(p1, pc);
if(hi1.type->etype == TINT32) {
gins(ASARL, ncon(31), &dx);
gins(AMOVL, &dx, &ax);
} else {
gins(AXORL, &dx, &dx);
gins(AXORL, &ax, &ax);
}
patch(p2, pc);
// if shift count is >= 32, sign-extend hi.
gins(ACMPL, &cx, ncon(32));
p1 = gbranch(optoas(OLT, types[TUINT32]), T, +1);
gins(AMOVL, &dx, &ax);
if(hi1.type->etype == TINT32) {
gins(ASARL, &cx, &ax); // SARL only uses bottom 5 bits of count
gins(ASARL, ncon(31), &dx);
} else {
gins(ASHRL, &cx, &ax);
gins(AXORL, &dx, &dx);
}
p2 = gbranch(AJMP, T, 0);
patch(p1, pc);
// general shift
p1 = gins(ASHRL, &cx, &ax);
p1->from.index = REG_DX; // double-width shift
p1->from.scale = 0;
gins(optoas(ORSH, hi1.type), &cx, &dx);
patch(p2, pc);
break;
case OXOR:
case OAND:
case OOR:
// make constant the right side (it usually is anyway).
if(lo1.op == OLITERAL) {
nswap(&lo1, &lo2);
nswap(&hi1, &hi2);
}
if(lo2.op == OLITERAL) {
// special cases for constants.
lv = mpgetfix(lo2.val.u.xval);
hv = mpgetfix(hi2.val.u.xval);
splitclean(); // right side
split64(res, &lo2, &hi2);
switch(n->op) {
case OXOR:
gmove(&lo1, &lo2);
gmove(&hi1, &hi2);
switch(lv) {
case 0:
break;
case 0xffffffffu:
gins(ANOTL, N, &lo2);
break;
default:
gins(AXORL, ncon(lv), &lo2);
break;
}
switch(hv) {
case 0:
break;
case 0xffffffffu:
gins(ANOTL, N, &hi2);
break;
default:
gins(AXORL, ncon(hv), &hi2);
break;
}
break;
case OAND:
switch(lv) {
case 0:
gins(AMOVL, ncon(0), &lo2);
break;
default:
gmove(&lo1, &lo2);
if(lv != 0xffffffffu)
gins(AANDL, ncon(lv), &lo2);
break;
}
switch(hv) {
case 0:
gins(AMOVL, ncon(0), &hi2);
break;
default:
gmove(&hi1, &hi2);
if(hv != 0xffffffffu)
gins(AANDL, ncon(hv), &hi2);
break;
}
break;
case OOR:
switch(lv) {
case 0:
gmove(&lo1, &lo2);
break;
case 0xffffffffu:
gins(AMOVL, ncon(0xffffffffu), &lo2);
break;
default:
gmove(&lo1, &lo2);
gins(AORL, ncon(lv), &lo2);
break;
}
switch(hv) {
case 0:
gmove(&hi1, &hi2);
break;
case 0xffffffffu:
gins(AMOVL, ncon(0xffffffffu), &hi2);
break;
default:
gmove(&hi1, &hi2);
gins(AORL, ncon(hv), &hi2);
break;
}
break;
}
splitclean();
splitclean();
goto out;
}
gins(AMOVL, &lo1, &ax);
gins(AMOVL, &hi1, &dx);
gins(optoas(n->op, lo1.type), &lo2, &ax);
gins(optoas(n->op, lo1.type), &hi2, &dx);
break;
}
if(is64(r->type))
splitclean();
splitclean();
split64(res, &lo1, &hi1);
gins(AMOVL, &ax, &lo1);
gins(AMOVL, &dx, &hi1);
splitclean();
out:;
}
/*
* generate comparison of nl, nr, both 64-bit.
* nl is memory; nr is constant or memory.
*/
void
cmp64(Node *nl, Node *nr, int op, int likely, Prog *to)
{
Node lo1, hi1, lo2, hi2, rr;
Prog *br;
Type *t;
split64(nl, &lo1, &hi1);
split64(nr, &lo2, &hi2);
// compare most significant word;
// if they differ, we're done.
t = hi1.type;
if(nl->op == OLITERAL || nr->op == OLITERAL)
gins(ACMPL, &hi1, &hi2);
else {
regalloc(&rr, types[TINT32], N);
gins(AMOVL, &hi1, &rr);
gins(ACMPL, &rr, &hi2);
regfree(&rr);
}
br = P;
switch(op) {
default:
fatal("cmp64 %O %T", op, t);
case OEQ:
// cmp hi
// jne L
// cmp lo
// jeq to
// L:
br = gbranch(AJNE, T, -likely);
break;
case ONE:
// cmp hi
// jne to
// cmp lo
// jne to
patch(gbranch(AJNE, T, likely), to);
break;
case OGE:
case OGT:
// cmp hi
// jgt to
// jlt L
// cmp lo
// jge to (or jgt to)
// L:
patch(gbranch(optoas(OGT, t), T, likely), to);
br = gbranch(optoas(OLT, t), T, -likely);
break;
case OLE:
case OLT:
// cmp hi
// jlt to
// jgt L
// cmp lo
// jle to (or jlt to)
// L:
patch(gbranch(optoas(OLT, t), T, likely), to);
br = gbranch(optoas(OGT, t), T, -likely);
break;
}
// compare least significant word
t = lo1.type;
if(nl->op == OLITERAL || nr->op == OLITERAL)
gins(ACMPL, &lo1, &lo2);
else {
regalloc(&rr, types[TINT32], N);
gins(AMOVL, &lo1, &rr);
gins(ACMPL, &rr, &lo2);
regfree(&rr);
}
// jump again
patch(gbranch(optoas(op, t), T, likely), to);
// point first branch down here if appropriate
if(br != P)
patch(br, pc);
splitclean();
splitclean();
}

View file

@ -1,15 +0,0 @@
// 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.
// +build ignore
/*
8g is the version of the gc compiler for the x86.
The $GOARCH for these tools is 386.
It reads .go files and outputs .8 files. The flags are documented in ../gc/doc.go.
*/
package main

View file

@ -1,87 +0,0 @@
// 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.
#include <u.h>
#include <libc.h>
#include "gg.h"
int thechar = '8';
char* thestring = "386";
LinkArch* thelinkarch = &link386;
void
linkarchinit(void)
{
}
vlong MAXWIDTH = (1LL<<32) - 1;
/*
* go declares several platform-specific type aliases:
* int, uint, float, and uintptr
*/
Typedef typedefs[] =
{
{"int", TINT, TINT32},
{"uint", TUINT, TUINT32},
{"uintptr", TUINTPTR, TUINT32},
{0}
};
void
betypeinit(void)
{
widthptr = 4;
widthint = 4;
widthreg = 4;
listinit8();
}
void
main(int argc, char **argv)
{
thearch.thechar = thechar;
thearch.thestring = thestring;
thearch.thelinkarch = thelinkarch;
thearch.typedefs = typedefs;
thearch.REGSP = REGSP;
thearch.REGCTXT = REGCTXT;
thearch.MAXWIDTH = MAXWIDTH;
thearch.anyregalloc = anyregalloc;
thearch.betypeinit = betypeinit;
thearch.bgen = bgen;
thearch.cgen = cgen;
thearch.cgen_call = cgen_call;
thearch.cgen_callinter = cgen_callinter;
thearch.cgen_ret = cgen_ret;
thearch.clearfat = clearfat;
thearch.defframe = defframe;
thearch.excise = excise;
thearch.expandchecks = expandchecks;
thearch.gclean = gclean;
thearch.ginit = ginit;
thearch.gins = gins;
thearch.ginscall = ginscall;
thearch.igen = igen;
thearch.linkarchinit = linkarchinit;
thearch.peep = peep;
thearch.proginfo = proginfo;
thearch.regalloc = regalloc;
thearch.regfree = regfree;
thearch.regtyp = regtyp;
thearch.sameaddr = sameaddr;
thearch.smallindir = smallindir;
thearch.stackaddr = stackaddr;
thearch.excludedregs = excludedregs;
thearch.RtoB = RtoB;
thearch.FtoB = FtoB;
thearch.BtoR = BtoR;
thearch.BtoF = BtoF;
thearch.optoas = optoas;
thearch.doregbits = doregbits;
thearch.regnames = regnames;
gcmain(argc, argv);
}

View file

@ -1,189 +0,0 @@
// 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.
#ifndef EXTERN
#define EXTERN extern
#endif
#include "../gc/go.h"
#include "../8l/8.out.h"
// foptoas flags
enum
{
Frev = 1<<0,
Fpop = 1<<1,
Fpop2 = 1<<2,
};
EXTERN uchar reg[MAXREG];
EXTERN Node* panicdiv;
extern uint32 unmappedzero;
/*
* ggen.c
*/
void compile(Node*);
void gen(Node*);
Node* lookdot(Node*, Node*, int);
void cgen_as(Node*, Node*);
void cgen_callmeth(Node*, int);
void cgen_callinter(Node*, Node*, int);
void cgen_proc(Node*, int);
void cgen_callret(Node*, Node*);
void cgen_div(int, Node*, Node*, Node*);
void cgen_bmul(int, Node*, Node*, Node*);
void cgen_hmul(Node*, Node*, Node*);
void cgen_shift(int, int, Node*, Node*, Node*);
void cgen_float(Node*, Node*);
void bgen_float(Node *n, int true, int likely, Prog *to);
void cgen_dcl(Node*);
int needconvert(Type*, Type*);
void genconv(Type*, Type*);
void allocparams(void);
void checklabels(void);
void ginscall(Node*, int);
/*
* cgen.c
*/
void agen(Node*, Node*);
void igen(Node*, Node*, Node*);
vlong fieldoffset(Type*, Node*);
void sgen(Node*, Node*, int64);
void gmove(Node*, Node*);
Prog* gins(int, Node*, Node*);
int samaddr(Node*, Node*);
void naddr(Node*, Addr*, int);
void cgen_aret(Node*, Node*);
Node* ncon(uint32);
void mgen(Node*, Node*, Node*);
void mfree(Node*);
int componentgen(Node*, Node*);
/*
* cgen64.c
*/
void cmp64(Node*, Node*, int, int, Prog*);
void cgen64(Node*, Node*);
/*
* gsubr.c
*/
void clearp(Prog*);
Prog* gbranch(int, Type*, int);
Prog* prog(int);
void gconv(int, int);
int conv2pt(Type*);
vlong convvtox(vlong, int);
void fnparam(Type*, int, int);
Prog* gop(int, Node*, Node*, Node*);
int optoas(int, Type*);
int foptoas(int, Type*, int);
void ginit(void);
void gclean(void);
void regalloc(Node*, Type*, Node*);
void regfree(Node*);
Node* nodarg(Type*, int);
void nodreg(Node*, Type*, int);
void nodindreg(Node*, Type*, int);
void nodconst(Node*, Type*, int64);
void gconreg(int, vlong, int);
void buildtxt(void);
Plist* newplist(void);
int isfat(Type*);
void sudoclean(void);
int sudoaddable(int, Node*, Addr*);
int dotaddable(Node*, Node*);
void afunclit(Addr*, Node*);
void split64(Node*, Node*, Node*);
void splitclean(void);
void nswap(Node*, Node*);
void gtrack(Sym*);
/*
* cplx.c
*/
int complexop(Node*, Node*);
void complexmove(Node*, Node*);
void complexgen(Node*, Node*);
/*
* gobj.c
*/
void datastring(char*, int, Addr*);
void datagostring(Strlit*, Addr*);
/*
* list.c
*/
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_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*);
/*
* reg.c
*/
uint64 excludedregs(void);
uint64 RtoB(int);
uint64 FtoB(int);
int BtoR(uint64);
int BtoF(uint64);
uint64 doregbits(int);
char** regnames(int*);
/*
* peep.c
*/
void peep(Prog*);

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,773 +0,0 @@
// Derived from Inferno utils/6c/peep.c
// http://code.google.com/p/inferno-os/source/browse/utils/6c/peep.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <u.h>
#include <libc.h>
#include "gg.h"
#include "../gc/popt.h"
enum {
REGEXT = 0,
exregoffset = REG_DI,
};
static void conprop(Flow *r);
static void elimshortmov(Graph*);
static int subprop(Flow*);
static int copyprop(Graph*, Flow*);
static int copy1(Adr*, Adr*, Flow*, int);
static int copyas(Adr*, Adr*);
static int copyau(Adr*, Adr*);
static int copysub(Adr*, Adr*, Adr*, int);
static int copyu(Prog*, Adr*, Adr*);
static uint32 gactive;
// do we need the carry bit
static int
needc(Prog *p)
{
ProgInfo info;
while(p != P) {
proginfo(&info, p);
if(info.flags & UseCarry)
return 1;
if(info.flags & (SetCarry|KillCarry))
return 0;
p = p->link;
}
return 0;
}
static Flow*
rnops(Flow *r)
{
Prog *p;
Flow *r1;
if(r != nil)
for(;;) {
p = r->prog;
if(p->as != ANOP || p->from.type != TYPE_NONE || p->to.type != TYPE_NONE)
break;
r1 = uniqs(r);
if(r1 == nil)
break;
r = r1;
}
return r;
}
void
peep(Prog *firstp)
{
Flow *r, *r1;
Graph *g;
Prog *p, *p1;
int t;
g = flowstart(firstp, 0);
if(g == nil)
return;
gactive = 0;
// byte, word arithmetic elimination.
elimshortmov(g);
// constant propagation
// find MOV $con,R followed by
// another MOV $con,R without
// setting R in the interim
for(r=g->start; r!=nil; r=r->link) {
p = r->prog;
switch(p->as) {
case ALEAL:
if(regtyp(&p->to))
if(p->from.sym != nil)
if(p->from.index == REG_NONE)
conprop(r);
break;
case AMOVB:
case AMOVW:
case AMOVL:
case AMOVSS:
case AMOVSD:
if(regtyp(&p->to))
if(p->from.type == TYPE_CONST || p->from.type == TYPE_FCONST)
conprop(r);
break;
}
}
loop1:
if(debug['P'] && debug['v'])
dumpit("loop1", g->start, 0);
t = 0;
for(r=g->start; r!=nil; r=r->link) {
p = r->prog;
switch(p->as) {
case AMOVL:
case AMOVSS:
case AMOVSD:
if(regtyp(&p->to))
if(regtyp(&p->from)) {
if(copyprop(g, r)) {
excise(r);
t++;
} else
if(subprop(r) && copyprop(g, r)) {
excise(r);
t++;
}
}
break;
case AMOVBLZX:
case AMOVWLZX:
case AMOVBLSX:
case AMOVWLSX:
if(regtyp(&p->to)) {
r1 = rnops(uniqs(r));
if(r1 != nil) {
p1 = r1->prog;
if(p->as == p1->as && p->to.type == p1->from.type && p->to.reg == p1->from.reg){
p1->as = AMOVL;
t++;
}
}
}
break;
case AADDL:
case AADDW:
if(p->from.type != TYPE_CONST || needc(p->link))
break;
if(p->from.offset == -1){
if(p->as == AADDL)
p->as = ADECL;
else
p->as = ADECW;
p->from = zprog.from;
break;
}
if(p->from.offset == 1){
if(p->as == AADDL)
p->as = AINCL;
else
p->as = AINCW;
p->from = zprog.from;
break;
}
break;
case ASUBL:
case ASUBW:
if(p->from.type != TYPE_CONST || needc(p->link))
break;
if(p->from.offset == -1) {
if(p->as == ASUBL)
p->as = AINCL;
else
p->as = AINCW;
p->from = zprog.from;
break;
}
if(p->from.offset == 1){
if(p->as == ASUBL)
p->as = ADECL;
else
p->as = ADECW;
p->from = zprog.from;
break;
}
break;
}
}
if(t)
goto loop1;
// MOVSD removal.
// We never use packed registers, so a MOVSD between registers
// can be replaced by MOVAPD, which moves the pair of float64s
// instead of just the lower one. We only use the lower one, but
// the processor can do better if we do moves using both.
for(r=g->start; r!=nil; r=r->link) {
p = r->prog;
if(p->as == AMOVSD)
if(regtyp(&p->from))
if(regtyp(&p->to))
p->as = AMOVAPD;
}
flowend(g);
}
void
excise(Flow *r)
{
Prog *p;
p = r->prog;
if(debug['P'] && debug['v'])
print("%P ===delete===\n", p);
nopout(p);
ostats.ndelmov++;
}
int
regtyp(Adr *a)
{
return a->type == TYPE_REG && (REG_AX <= a->reg && a->reg <= REG_DI || REG_X0 <= a->reg && a->reg <= REG_X7);
}
// movb elimination.
// movb is simulated by the linker
// when a register other than ax, bx, cx, dx
// is used, so rewrite to other instructions
// when possible. a movb into a register
// can smash the entire 64-bit register without
// causing any trouble.
static void
elimshortmov(Graph *g)
{
Prog *p;
Flow *r;
for(r=g->start; r!=nil; r=r->link) {
p = r->prog;
if(regtyp(&p->to)) {
switch(p->as) {
case AINCB:
case AINCW:
p->as = AINCL;
break;
case ADECB:
case ADECW:
p->as = ADECL;
break;
case ANEGB:
case ANEGW:
p->as = ANEGL;
break;
case ANOTB:
case ANOTW:
p->as = ANOTL;
break;
}
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
// change how the carry bit is set (and the carry bit is needed).
switch(p->as) {
case AMOVB:
case AMOVW:
p->as = AMOVL;
break;
case AADDB:
case AADDW:
if(!needc(p->link))
p->as = AADDL;
break;
case ASUBB:
case ASUBW:
if(!needc(p->link))
p->as = ASUBL;
break;
case AMULB:
case AMULW:
p->as = AMULL;
break;
case AIMULB:
case AIMULW:
p->as = AIMULL;
break;
case AANDB:
case AANDW:
p->as = AANDL;
break;
case AORB:
case AORW:
p->as = AORL;
break;
case AXORB:
case AXORW:
p->as = AXORL;
break;
case ASHLB:
case ASHLW:
p->as = ASHLL;
break;
}
} else {
// explicit zero extension
switch(p->as) {
case AMOVB:
p->as = AMOVBLZX;
break;
case AMOVW:
p->as = AMOVWLZX;
break;
}
}
}
}
}
/*
* the idea is to substitute
* one register for another
* from one MOV to another
* MOV a, R0
* ADD b, R0 / no use of R1
* MOV R0, R1
* would be converted to
* MOV a, R1
* ADD b, R1
* MOV R1, R0
* hopefully, then the former or latter MOV
* will be eliminated by copy propagation.
*/
static int
subprop(Flow *r0)
{
Prog *p;
Adr *v1, *v2;
Flow *r;
int t;
ProgInfo info;
p = r0->prog;
v1 = &p->from;
if(!regtyp(v1))
return 0;
v2 = &p->to;
if(!regtyp(v2))
return 0;
for(r=uniqp(r0); r!=nil; r=uniqp(r)) {
if(debug['P'] && debug['v'])
print("\t? %P\n", r->prog);
if(uniqs(r) == nil)
break;
p = r->prog;
if(p->as == AVARDEF || p->as == AVARKILL)
continue;
proginfo(&info, p);
if(info.flags & Call)
return 0;
if(info.reguse | info.regset)
return 0;
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))
break;
if(copysub(&p->from, v1, v2, 0) || copysub(&p->to, v1, v2, 0))
break;
}
return 0;
gotit:
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 && p->from.reg == v2->reg)
print(" excise");
print("\n");
}
for(r=uniqs(r); r!=r0; r=uniqs(r)) {
p = r->prog;
copysub(&p->from, v1, v2, 1);
copysub(&p->to, v1, v2, 1);
if(debug['P'])
print("%P\n", r->prog);
}
t = v1->reg;
v1->reg = v2->reg;
v2->reg = t;
if(debug['P'])
print("%P last\n", r->prog);
return 1;
}
/*
* The idea is to remove redundant copies.
* v1->v2 F=0
* (use v2 s/v2/v1/)*
* set v1 F=1
* use v2 return fail
* -----------------
* v1->v2 F=0
* (use v2 s/v2/v1/)*
* set v1 F=1
* set v2 return success
*/
static int
copyprop(Graph *g, Flow *r0)
{
Prog *p;
Adr *v1, *v2;
USED(g);
p = r0->prog;
v1 = &p->from;
v2 = &p->to;
if(copyas(v1, v2))
return 1;
gactive++;
return copy1(v1, v2, r0->s1, 0);
}
static int
copy1(Adr *v1, Adr *v2, Flow *r, int f)
{
int t;
Prog *p;
if(r->active == gactive) {
if(debug['P'])
print("act set; return 1\n");
return 1;
}
r->active = gactive;
if(debug['P'])
print("copy %D->%D f=%d\n", v1, v2, f);
for(; r != nil; r = r->s1) {
p = r->prog;
if(debug['P'])
print("%P", p);
if(!f && uniqp(r) == nil) {
f = 1;
if(debug['P'])
print("; merge; f=%d", f);
}
t = copyu(p, v2, nil);
switch(t) {
case 2: /* rar, can't split */
if(debug['P'])
print("; %D rar; return 0\n", v2);
return 0;
case 3: /* set */
if(debug['P'])
print("; %D set; return 1\n", v2);
return 1;
case 1: /* used, substitute */
case 4: /* use and set */
if(f) {
if(!debug['P'])
return 0;
if(t == 4)
print("; %D used+set and f=%d; return 0\n", v2, f);
else
print("; %D used and f=%d; return 0\n", v2, f);
return 0;
}
if(copyu(p, v2, v1)) {
if(debug['P'])
print("; sub fail; return 0\n");
return 0;
}
if(debug['P'])
print("; sub %D/%D", v2, v1);
if(t == 4) {
if(debug['P'])
print("; %D used+set; return 1\n", v2);
return 1;
}
break;
}
if(!f) {
t = copyu(p, v1, nil);
if(!f && (t == 2 || t == 3 || t == 4)) {
f = 1;
if(debug['P'])
print("; %D set and !f; f=%d", v1, f);
}
}
if(debug['P'])
print("\n");
if(r->s2)
if(!copy1(v1, v2, r->s2, f))
return 0;
}
return 1;
}
/*
* return
* 1 if v only used (and substitute),
* 2 if read-alter-rewrite
* 3 if set
* 4 if set and used
* 0 otherwise (not touched)
*/
static int
copyu(Prog *p, Adr *v, Adr *s)
{
ProgInfo info;
switch(p->as) {
case AJMP:
if(s != nil) {
if(copysub(&p->to, v, s, 1))
return 1;
return 0;
}
if(copyau(&p->to, v))
return 1;
return 0;
case ARET:
if(s != nil)
return 1;
return 3;
case ACALL:
if(REGEXT && v->type == TYPE_REG && v->reg <= REGEXT && v->reg > exregoffset)
return 2;
if(REGARG >= 0 && v->type == TYPE_REG && v->reg == REGARG)
return 2;
if(v->type == p->from.type && v->reg == p->from.reg)
return 2;
if(s != nil) {
if(copysub(&p->to, v, s, 1))
return 1;
return 0;
}
if(copyau(&p->to, v))
return 4;
return 3;
case ATEXT:
if(REGARG >= 0 && v->type == TYPE_REG && v->reg == REGARG)
return 3;
return 0;
}
if(p->as == AVARDEF || p->as == AVARKILL)
return 0;
proginfo(&info, p);
if((info.reguse|info.regset) & RtoB(v->reg))
return 2;
if(info.flags & LeftAddr)
if(copyas(&p->from, v))
return 2;
if((info.flags & (RightRead|RightWrite)) == (RightRead|RightWrite))
if(copyas(&p->to, v))
return 2;
if(info.flags & RightWrite) {
if(copyas(&p->to, v)) {
if(s != nil)
return copysub(&p->from, v, s, 1);
if(copyau(&p->from, v))
return 4;
return 3;
}
}
if(info.flags & (LeftAddr|LeftRead|LeftWrite|RightAddr|RightRead|RightWrite)) {
if(s != nil) {
if(copysub(&p->from, v, s, 1))
return 1;
return copysub(&p->to, v, s, 1);
}
if(copyau(&p->from, v))
return 1;
if(copyau(&p->to, v))
return 1;
}
return 0;
}
/*
* direct reference,
* could be set/use depending on
* semantics
*/
static int
copyas(Adr *a, Adr *v)
{
if(REG_AL <= a->reg && a->reg <= REG_BL)
fatal("use of byte register");
if(REG_AL <= v->reg && v->reg <= REG_BL)
fatal("use of byte register");
if(a->type != v->type || a->name != v->name || a->reg != v->reg)
return 0;
if(regtyp(v))
return 1;
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 || a->name != v->name || a->reg != v->reg)
return 0;
if(regtyp(v))
return 1;
if(v->type == TYPE_MEM && (v->name == NAME_AUTO || v->name == NAME_PARAM))
if(v->offset == a->offset)
return 1;
return 0;
}
/*
* either direct or indirect
*/
static int
copyau(Adr *a, Adr *v)
{
if(copyas(a, v))
return 1;
if(regtyp(v)) {
if(a->type == TYPE_MEM && a->reg == v->reg)
return 1;
if(a->index == v->reg)
return 1;
}
return 0;
}
/*
* substitute s for v in a
* return failure to substitute
*/
static int
copysub(Adr *a, Adr *v, Adr *s, int f)
{
int reg;
if(copyas(a, v)) {
reg = s->reg;
if(reg >= REG_AX && reg <= REG_DI || reg >= REG_X0 && reg <= REG_X7) {
if(f)
a->reg = reg;
}
return 0;
}
if(regtyp(v)) {
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->reg = s->reg;
// return 0;
}
if(a->index == reg) {
if(f)
a->index = s->reg;
return 0;
}
return 0;
}
return 0;
}
static void
conprop(Flow *r0)
{
Flow *r;
Prog *p, *p0;
int t;
Adr *v0;
p0 = r0->prog;
v0 = &p0->to;
r = r0;
loop:
r = uniqs(r);
if(r == nil || r == r0)
return;
if(uniqp(r) == nil)
return;
p = r->prog;
t = copyu(p, v0, nil);
switch(t) {
case 0: // miss
case 1: // use
goto loop;
case 2: // rar
case 4: // use and set
break;
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 == TYPE_FCONST && p->from.u.dval == p0->from.u.dval)
if(p->from.index == p0->from.index) {
excise(r);
goto loop;
}
break;
}
}
int
smallindir(Addr *a, Addr *reg)
{
return regtyp(reg) &&
a->type == TYPE_MEM && a->reg == reg->reg &&
a->index == REG_NONE &&
0 <= a->offset && a->offset < 4096;
}
int
stackaddr(Addr *a)
{
return a->type == TYPE_REG && a->reg == REG_SP;
}

View file

@ -1,349 +0,0 @@
// 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.
#include <u.h>
#include <libc.h>
#include "gg.h"
#include "../gc/popt.h"
// Matches real RtoB but can be used in global initializer.
#define RtoB(r) (1<<((r)-REG_AX))
enum {
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,
};
#undef RtoB
// This table gives the basic information about instruction
// generated by the compiler and processed in the optimizer.
// See opt.h for bit definitions.
//
// Instructions not generated need not be listed.
// As an exception to that rule, we typically write down all the
// size variants of an operation even if we just use a subset.
//
// The table is formatted for 8-space tabs.
static ProgInfo progtable[ALAST] = {
[ATYPE]= {Pseudo | Skip},
[ATEXT]= {Pseudo},
[AFUNCDATA]= {Pseudo},
[APCDATA]= {Pseudo},
[AUNDEF]= {Break},
[AUSEFIELD]= {OK},
[ACHECKNIL]= {LeftRead},
[AVARDEF]= {Pseudo | RightWrite},
[AVARKILL]= {Pseudo | RightWrite},
// NOP is an internal no-op that also stands
// for USED and SET annotations, not the Intel opcode.
[ANOP]= {LeftRead | RightWrite},
[AADCL]= {SizeL | LeftRead | RightRdwr | SetCarry | UseCarry},
[AADCW]= {SizeW | LeftRead | RightRdwr | SetCarry | UseCarry},
[AADDB]= {SizeB | LeftRead | RightRdwr | SetCarry},
[AADDL]= {SizeL | LeftRead | RightRdwr | SetCarry},
[AADDW]= {SizeW | LeftRead | RightRdwr | SetCarry},
[AADDSD]= {SizeD | LeftRead | RightRdwr},
[AADDSS]= {SizeF | LeftRead | RightRdwr},
[AANDB]= {SizeB | LeftRead | RightRdwr | SetCarry},
[AANDL]= {SizeL | LeftRead | RightRdwr | SetCarry},
[AANDW]= {SizeW | LeftRead | RightRdwr | SetCarry},
[ACALL]= {RightAddr | Call | KillCarry},
[ACDQ]= {OK, AX, AX | DX},
[ACWD]= {OK, AX, AX | DX},
[ACLD]= {OK},
[ASTD]= {OK},
[ACMPB]= {SizeB | LeftRead | RightRead | SetCarry},
[ACMPL]= {SizeL | LeftRead | RightRead | SetCarry},
[ACMPW]= {SizeW | LeftRead | RightRead | SetCarry},
[ACOMISD]= {SizeD | LeftRead | RightRead | SetCarry},
[ACOMISS]= {SizeF | LeftRead | RightRead | SetCarry},
[ACVTSD2SL]= {SizeL | LeftRead | RightWrite | Conv},
[ACVTSD2SS]= {SizeF | LeftRead | RightWrite | Conv},
[ACVTSL2SD]= {SizeD | LeftRead | RightWrite | Conv},
[ACVTSL2SS]= {SizeF | LeftRead | RightWrite | Conv},
[ACVTSS2SD]= {SizeD | LeftRead | RightWrite | Conv},
[ACVTSS2SL]= {SizeL | LeftRead | RightWrite | Conv},
[ACVTTSD2SL]= {SizeL | LeftRead | RightWrite | Conv},
[ACVTTSS2SL]= {SizeL | LeftRead | RightWrite | Conv},
[ADECB]= {SizeB | RightRdwr},
[ADECL]= {SizeL | RightRdwr},
[ADECW]= {SizeW | RightRdwr},
[ADIVB]= {SizeB | LeftRead | SetCarry, AX, AX},
[ADIVL]= {SizeL | LeftRead | SetCarry, AX|DX, AX|DX},
[ADIVW]= {SizeW | LeftRead | SetCarry, AX|DX, AX|DX},
[ADIVSD]= {SizeD | LeftRead | RightRdwr},
[ADIVSS]= {SizeF | LeftRead | RightRdwr},
[AFLDCW]= {SizeW | LeftAddr},
[AFSTCW]= {SizeW | RightAddr},
[AFSTSW]= {SizeW | RightAddr | RightWrite},
[AFADDD]= {SizeD | LeftAddr | RightRdwr},
[AFADDDP]= {SizeD | LeftAddr | RightRdwr},
[AFADDF]= {SizeF | LeftAddr | RightRdwr},
[AFCOMD]= {SizeD | LeftAddr | RightRead},
[AFCOMDP]= {SizeD | LeftAddr | RightRead},
[AFCOMDPP]= {SizeD | LeftAddr | RightRead},
[AFCOMF]= {SizeF | LeftAddr | RightRead},
[AFCOMFP]= {SizeF | LeftAddr | RightRead},
[AFUCOMIP]= {SizeF | LeftAddr | RightRead},
[AFCHS]= {SizeD | RightRdwr}, // also SizeF
[AFDIVDP]= {SizeD | LeftAddr | RightRdwr},
[AFDIVF]= {SizeF | LeftAddr | RightRdwr},
[AFDIVD]= {SizeD | LeftAddr | RightRdwr},
[AFDIVRDP]= {SizeD | LeftAddr | RightRdwr},
[AFDIVRF]= {SizeF | LeftAddr | RightRdwr},
[AFDIVRD]= {SizeD | LeftAddr | RightRdwr},
[AFXCHD]= {SizeD | LeftRdwr | RightRdwr},
[AFSUBD]= {SizeD | LeftAddr | RightRdwr},
[AFSUBDP]= {SizeD | LeftAddr | RightRdwr},
[AFSUBF]= {SizeF | LeftAddr | RightRdwr},
[AFSUBRD]= {SizeD | LeftAddr | RightRdwr},
[AFSUBRDP]= {SizeD | LeftAddr | RightRdwr},
[AFSUBRF]= {SizeF | LeftAddr | RightRdwr},
[AFMOVD]= {SizeD | LeftAddr | RightWrite},
[AFMOVF]= {SizeF | LeftAddr | RightWrite},
[AFMOVL]= {SizeL | LeftAddr | RightWrite},
[AFMOVW]= {SizeW | LeftAddr | RightWrite},
[AFMOVV]= {SizeQ | LeftAddr | RightWrite},
// These instructions are marked as RightAddr
// so that the register optimizer does not try to replace the
// memory references with integer register references.
// But they do not use the previous value at the address, so
// we also mark them RightWrite.
[AFMOVDP]= {SizeD | LeftRead | RightWrite | RightAddr},
[AFMOVFP]= {SizeF | LeftRead | RightWrite | RightAddr},
[AFMOVLP]= {SizeL | LeftRead | RightWrite | RightAddr},
[AFMOVWP]= {SizeW | LeftRead | RightWrite | RightAddr},
[AFMOVVP]= {SizeQ | LeftRead | RightWrite | RightAddr},
[AFMULD]= {SizeD | LeftAddr | RightRdwr},
[AFMULDP]= {SizeD | LeftAddr | RightRdwr},
[AFMULF]= {SizeF | LeftAddr | RightRdwr},
[AIDIVB]= {SizeB | LeftRead | SetCarry, AX, AX},
[AIDIVL]= {SizeL | LeftRead | SetCarry, AX|DX, AX|DX},
[AIDIVW]= {SizeW | LeftRead | SetCarry, AX|DX, AX|DX},
[AIMULB]= {SizeB | LeftRead | SetCarry, AX, AX},
[AIMULL]= {SizeL | LeftRead | ImulAXDX | SetCarry},
[AIMULW]= {SizeW | LeftRead | ImulAXDX | SetCarry},
[AINCB]= {SizeB | RightRdwr},
[AINCL]= {SizeL | RightRdwr},
[AINCW]= {SizeW | RightRdwr},
[AJCC]= {Cjmp | UseCarry},
[AJCS]= {Cjmp | UseCarry},
[AJEQ]= {Cjmp | UseCarry},
[AJGE]= {Cjmp | UseCarry},
[AJGT]= {Cjmp | UseCarry},
[AJHI]= {Cjmp | UseCarry},
[AJLE]= {Cjmp | UseCarry},
[AJLS]= {Cjmp | UseCarry},
[AJLT]= {Cjmp | UseCarry},
[AJMI]= {Cjmp | UseCarry},
[AJNE]= {Cjmp | UseCarry},
[AJOC]= {Cjmp | UseCarry},
[AJOS]= {Cjmp | UseCarry},
[AJPC]= {Cjmp | UseCarry},
[AJPL]= {Cjmp | UseCarry},
[AJPS]= {Cjmp | UseCarry},
[AJMP]= {Jump | Break | KillCarry},
[ALEAL]= {LeftAddr | RightWrite},
[AMOVBLSX]= {SizeL | LeftRead | RightWrite | Conv},
[AMOVBLZX]= {SizeL | LeftRead | RightWrite | Conv},
[AMOVBWSX]= {SizeW | LeftRead | RightWrite | Conv},
[AMOVBWZX]= {SizeW | LeftRead | RightWrite | Conv},
[AMOVWLSX]= {SizeL | LeftRead | RightWrite | Conv},
[AMOVWLZX]= {SizeL | LeftRead | RightWrite | Conv},
[AMOVB]= {SizeB | LeftRead | RightWrite | Move},
[AMOVL]= {SizeL | LeftRead | RightWrite | Move},
[AMOVW]= {SizeW | LeftRead | RightWrite | Move},
[AMOVSB]= {OK, DI|SI, DI|SI},
[AMOVSL]= {OK, DI|SI, DI|SI},
[AMOVSW]= {OK, DI|SI, DI|SI},
[ADUFFCOPY]= {OK, DI|SI, DI|SI|CX},
[AMOVSD]= {SizeD | LeftRead | RightWrite | Move},
[AMOVSS]= {SizeF | LeftRead | RightWrite | Move},
// We use MOVAPD as a faster synonym for MOVSD.
[AMOVAPD]= {SizeD | LeftRead | RightWrite | Move},
[AMULB]= {SizeB | LeftRead | SetCarry, AX, AX},
[AMULL]= {SizeL | LeftRead | SetCarry, AX, AX|DX},
[AMULW]= {SizeW | LeftRead | SetCarry, AX, AX|DX},
[AMULSD]= {SizeD | LeftRead | RightRdwr},
[AMULSS]= {SizeF | LeftRead | RightRdwr},
[ANEGB]= {SizeB | RightRdwr | SetCarry},
[ANEGL]= {SizeL | RightRdwr | SetCarry},
[ANEGW]= {SizeW | RightRdwr | SetCarry},
[ANOTB]= {SizeB | RightRdwr},
[ANOTL]= {SizeL | RightRdwr},
[ANOTW]= {SizeW | RightRdwr},
[AORB]= {SizeB | LeftRead | RightRdwr | SetCarry},
[AORL]= {SizeL | LeftRead | RightRdwr | SetCarry},
[AORW]= {SizeW | LeftRead | RightRdwr | SetCarry},
[APOPL]= {SizeL | RightWrite},
[APUSHL]= {SizeL | LeftRead},
[ARCLB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
[ARCLL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
[ARCLW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
[ARCRB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
[ARCRL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
[ARCRW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
[AREP]= {OK, CX, CX},
[AREPN]= {OK, CX, CX},
[ARET]= {Break | KillCarry},
[AROLB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
[AROLL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
[AROLW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ARORB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ARORL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ARORW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASAHF]= {OK, AX, AX},
[ASALB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASALL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASALW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASARB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASARL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASARW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASBBB]= {SizeB | LeftRead | RightRdwr | SetCarry | UseCarry},
[ASBBL]= {SizeL | LeftRead | RightRdwr | SetCarry | UseCarry},
[ASBBW]= {SizeW | LeftRead | RightRdwr | SetCarry | UseCarry},
[ASETCC]= {SizeB | RightRdwr | UseCarry},
[ASETCS]= {SizeB | RightRdwr | UseCarry},
[ASETEQ]= {SizeB | RightRdwr | UseCarry},
[ASETGE]= {SizeB | RightRdwr | UseCarry},
[ASETGT]= {SizeB | RightRdwr | UseCarry},
[ASETHI]= {SizeB | RightRdwr | UseCarry},
[ASETLE]= {SizeB | RightRdwr | UseCarry},
[ASETLS]= {SizeB | RightRdwr | UseCarry},
[ASETLT]= {SizeB | RightRdwr | UseCarry},
[ASETMI]= {SizeB | RightRdwr | UseCarry},
[ASETNE]= {SizeB | RightRdwr | UseCarry},
[ASETOC]= {SizeB | RightRdwr | UseCarry},
[ASETOS]= {SizeB | RightRdwr | UseCarry},
[ASETPC]= {SizeB | RightRdwr | UseCarry},
[ASETPL]= {SizeB | RightRdwr | UseCarry},
[ASETPS]= {SizeB | RightRdwr | UseCarry},
[ASHLB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASHLL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASHLW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASHRB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASHRL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASHRW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASTOSB]= {OK, AX|DI, DI},
[ASTOSL]= {OK, AX|DI, DI},
[ASTOSW]= {OK, AX|DI, DI},
[ADUFFZERO]= {OK, AX|DI, DI},
[ASUBB]= {SizeB | LeftRead | RightRdwr | SetCarry},
[ASUBL]= {SizeL | LeftRead | RightRdwr | SetCarry},
[ASUBW]= {SizeW | LeftRead | RightRdwr | SetCarry},
[ASUBSD]= {SizeD | LeftRead | RightRdwr},
[ASUBSS]= {SizeF | LeftRead | RightRdwr},
[ATESTB]= {SizeB | LeftRead | RightRead | SetCarry},
[ATESTL]= {SizeL | LeftRead | RightRead | SetCarry},
[ATESTW]= {SizeW | LeftRead | RightRead | SetCarry},
[AUCOMISD]= {SizeD | LeftRead | RightRead},
[AUCOMISS]= {SizeF | LeftRead | RightRead},
[AXCHGB]= {SizeB | LeftRdwr | RightRdwr},
[AXCHGL]= {SizeL | LeftRdwr | RightRdwr},
[AXCHGW]= {SizeW | LeftRdwr | RightRdwr},
[AXORB]= {SizeB | LeftRead | RightRdwr | SetCarry},
[AXORL]= {SizeL | LeftRead | RightRdwr | SetCarry},
[AXORW]= {SizeW | LeftRead | RightRdwr | SetCarry},
};
void
proginfo(ProgInfo *info, Prog *p)
{
*info = progtable[p->as];
if(info->flags == 0)
fatal("unknown instruction %P", p);
if((info->flags & ShiftCX) && p->from.type != TYPE_CONST)
info->reguse |= CX;
if(info->flags & ImulAXDX) {
if(p->to.type == TYPE_NONE) {
info->reguse |= AX;
info->regset |= AX | DX;
} else {
info->flags |= RightRdwr;
}
}
// Addressing makes some registers used.
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 == 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);
}

View file

@ -1,112 +0,0 @@
// Derived from Inferno utils/6c/reg.c
// http://code.google.com/p/inferno-os/source/browse/utils/6c/reg.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <u.h>
#include <libc.h>
#include "gg.h"
#include "../gc/popt.h"
enum {
NREGVAR = 16, /* 8 integer + 8 floating */
};
static char* regname[] = {
".ax", ".cx", ".dx", ".bx", ".sp", ".bp", ".si", ".di",
".x0", ".x1", ".x2", ".x3", ".x4", ".x5", ".x6", ".x7",
};
char**
regnames(int *n)
{
*n = NREGVAR;
return regname;
}
uint64
excludedregs(void)
{
return RtoB(REG_SP);
}
uint64
doregbits(int r)
{
uint64 b;
b = 0;
if(r >= REG_AX && r <= REG_DI)
b |= RtoB(r);
else
if(r >= REG_AL && r <= REG_BL)
b |= RtoB(r-REG_AL+REG_AX);
else
if(r >= REG_AH && r <= REG_BH)
b |= RtoB(r-REG_AH+REG_AX);
else
if(r >= REG_X0 && r <= REG_X0+7)
b |= FtoB(r);
return b;
}
uint64
RtoB(int r)
{
if(r < REG_AX || r > REG_DI)
return 0;
return 1ULL << (r-REG_AX);
}
int
BtoR(uint64 b)
{
b &= 0xffL;
if(b == 0)
return 0;
return bitno(b) + REG_AX;
}
uint64
FtoB(int f)
{
if(f < REG_X0 || f > REG_X7)
return 0;
return 1ULL << (f - REG_X0 + 8);
}
int
BtoF(uint64 b)
{
b &= 0xFF00L;
if(b == 0)
return 0;
return bitno(b) - 8 + REG_X0;
}

View file

@ -1,10 +0,0 @@
# Copyright 2012 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.
include ../../Make.dist
install: y.tab.h
y.tab.h: a.y
LANG=C LANGUAGE=en_US.UTF8 bison -d -v -y a.y

View file

@ -1,172 +0,0 @@
// cmd/9a/a.h from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <bio.h>
#include <link.h>
#include "../9l/9.out.h"
#ifndef EXTERN
#define EXTERN extern
#endif
#undef getc
#undef ungetc
#undef BUFSIZ
#define getc ccgetc
#define ungetc ccungetc
typedef struct Sym Sym;
typedef struct Io Io;
#define MAXALIGN 7
#define FPCHIP 1
#define NSYMB 8192
#define BUFSIZ 8192
#define HISTSZ 20
#define NINCLUDE 10
#define NHUNK 10000
#ifndef EOF
#define EOF (-1)
#endif
#define IGN (-2)
#define GETC() ((--fi.c < 0)? filbuf(): *fi.p++ & 0xff)
#define NHASH 503
#define STRINGSZ 200
#define NMACRO 10
struct Sym
{
Sym* link;
char* macro;
vlong value;
ushort type;
char *name;
char* labelname;
char sym;
};
#define S ((Sym*)0)
EXTERN struct
{
char* p;
int c;
} fi;
struct Io
{
Io* link;
char b[BUFSIZ];
char* p;
short c;
short f;
};
#define I ((Io*)0)
enum
{
CLAST,
CMACARG,
CMACRO,
CPREPROC,
};
EXTERN int debug[256];
EXTERN Sym* hash[NHASH];
EXTERN char** Dlist;
EXTERN int nDlist;
EXTERN int newflag;
EXTERN char* hunk;
EXTERN char** include;
EXTERN Io* iofree;
EXTERN Io* ionext;
EXTERN Io* iostack;
EXTERN int32 lineno;
EXTERN int nerrors;
EXTERN int32 nhunk;
EXTERN int nosched;
EXTERN int ninclude;
EXTERN int32 nsymb;
EXTERN Addr nullgen;
EXTERN char* outfile;
EXTERN int pass;
EXTERN int32 pc;
EXTERN int peekc;
EXTERN int32 stmtline;
EXTERN int sym;
EXTERN char* symb;
EXTERN int thechar;
EXTERN char* thestring;
EXTERN int32 thunk;
EXTERN Biobuf obuf;
EXTERN Link* ctxt;
EXTERN Biobuf bstdout;
EXTERN Prog* lastpc;
void* alloc(int32);
void* allocn(void*, int32, int32);
void ensuresymb(int32);
void errorexit(void);
void pushio(void);
void newio(void);
void newfile(char*, int);
Sym* slookup(char*);
Sym* lookup(void);
Sym* labellookup(Sym*);
void settext(LSym*);
void syminit(Sym*);
int32 yylex(void);
int getc(void);
int getnsc(void);
void unget(int);
int escchar(int);
void cinit(void);
void pinit(char*);
void cclean(void);
void outcode(int, Addr*, int, Addr*);
void outgcode(int, Addr*, int, Addr*, Addr*);
int filbuf(void);
Sym* getsym(void);
void domacro(void);
void macund(void);
void macdef(void);
void macexpand(Sym*, char*);
void macinc(void);
void macprag(void);
void maclin(void);
void macif(int);
void macend(void);
void dodefine(char*);
void prfile(int32);
void linehist(char*, int);
void gethunk(void);
void yyerror(char*, ...);
int yyparse(void);
void setinclude(char*);
int assemble(char*);

File diff suppressed because it is too large Load diff

View file

@ -1,21 +0,0 @@
// 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.
// +build ignore
/*
9a is a version of the Plan 9 assembler. The original is documented at
http://plan9.bell-labs.com/magic/man2html/1/8a
Go-specific considerations are documented at
http://golang.org/doc/asm
Its target architecture is 64-bit PowerPC and Power Architecture processors,
referred to by these tools as ppc64 (big endian) or ppc64le (little endian).
*/
package main

View file

@ -1,726 +0,0 @@
// cmd/9a/lex.c from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#define EXTERN
#include <u.h>
#include <libc.h>
#include "a.h"
#include "y.tab.h"
enum
{
Plan9 = 1<<0,
Unix = 1<<1,
Windows = 1<<2,
};
int
systemtype(int sys)
{
#ifdef _WIN32
return sys&Windows;
#else
return sys&Plan9;
#endif
}
int
pathchar(void)
{
return '/';
}
int
Lconv(Fmt *fp)
{
return linklinefmt(ctxt, fp);
}
void
dodef(char *p)
{
if(nDlist%8 == 0)
Dlist = allocn(Dlist, nDlist*sizeof(char *),
8*sizeof(char *));
Dlist[nDlist++] = p;
}
LinkArch* thelinkarch = &linkppc64;
void
usage(void)
{
print("usage: %ca [options] file.c...\n", thechar);
flagprint(1);
errorexit();
}
void
main(int argc, char *argv[])
{
char *p;
thechar = '9';
thestring = "ppc64";
// Allow GOARCH=thestring or GOARCH=thestringsuffix,
// but not other values.
p = getgoarch();
if(strncmp(p, thestring, strlen(thestring)) != 0)
sysfatal("cannot use %cc with GOARCH=%s", thechar, p);
if(strcmp(p, "ppc64le") == 0)
thelinkarch = &linkppc64le;
ctxt = linknew(thelinkarch);
ctxt->diag = yyerror;
ctxt->bso = &bstdout;
ctxt->enforce_data_order = 1;
Binit(&bstdout, 1, OWRITE);
listinit9();
fmtinstall('L', Lconv);
ensuresymb(NSYMB);
memset(debug, 0, sizeof(debug));
cinit();
outfile = 0;
setinclude(".");
flagfn1("D", "name[=value]: add #define", dodef);
flagfn1("I", "dir: add dir to include path", setinclude);
flagcount("S", "print assembly and machine code", &debug['S']);
flagcount("m", "debug preprocessor macros", &debug['m']);
flagstr("o", "file: set output file", &outfile);
flagstr("trimpath", "prefix: remove prefix from recorded source file paths", &ctxt->trimpath);
flagparse(&argc, &argv, usage);
ctxt->debugasm = debug['S'];
if(argc < 1)
usage();
if(argc > 1){
print("can't assemble multiple files\n");
errorexit();
}
if(assemble(argv[0]))
errorexit();
Bflush(&bstdout);
if(nerrors > 0)
errorexit();
exits(0);
}
int
assemble(char *file)
{
char *ofile, *p;
int i, of;
ofile = alloc(strlen(file)+3); // +3 for .x\0 (x=thechar)
strcpy(ofile, file);
p = utfrrune(ofile, pathchar());
if(p) {
include[0] = ofile;
*p++ = 0;
} else
p = ofile;
if(outfile == 0) {
outfile = p;
if(outfile){
p = utfrrune(outfile, '.');
if(p)
if(p[1] == 's' && p[2] == 0)
p[0] = 0;
p = utfrune(outfile, 0);
p[0] = '.';
p[1] = thechar;
p[2] = 0;
} else
outfile = "/dev/null";
}
of = create(outfile, OWRITE, 0664);
if(of < 0) {
yyerror("%ca: cannot create %s", thechar, outfile);
errorexit();
}
Binit(&obuf, of, OWRITE);
Bprint(&obuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
Bprint(&obuf, "!\n");
for(pass = 1; pass <= 2; pass++) {
nosched = 0;
pinit(file);
for(i=0; i<nDlist; i++)
dodefine(Dlist[i]);
yyparse();
cclean();
if(nerrors)
return nerrors;
}
writeobj(ctxt, &obuf);
Bflush(&obuf);
return 0;
}
struct
{
char *name;
ushort type;
ushort value;
} itab[] =
{
"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, 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, 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,
"CRAND", LCROP, ACRAND,
"CROR", LCROP, ACROR,
"CRANDN", LCROP, ACRANDN,
"CRORN", LCROP, ACRORN,
"CRNAND", LCROP, ACRNAND,
"CRNOR", LCROP, ACRNOR,
"ADD", LADDW, AADD,
"ADDV", LADDW, AADDV,
"ADDCC", LADDW, AADDCC,
"ADDVCC", LADDW, AADDVCC,
"ADDC", LADDW, AADDC,
"ADDCV", LADDW, AADDCV,
"ADDCCC", LADDW, AADDCCC,
"ADDCVCC", LADDW, AADDCVCC,
"ADDE", LLOGW, AADDE,
"ADDEV", LLOGW, AADDEV,
"ADDECC", LLOGW, AADDECC,
"ADDEVCC", LLOGW, AADDEVCC,
"ADDME", LABS, AADDME,
"ADDMEV", LABS, AADDMEV,
"ADDMECC", LABS, AADDMECC,
"ADDMEVCC", LABS, AADDMEVCC,
"ADDZE", LABS, AADDZE,
"ADDZEV", LABS, AADDZEV,
"ADDZECC", LABS, AADDZECC,
"ADDZEVCC", LABS, AADDZEVCC,
"SUB", LADDW, ASUB,
"SUBV", LADDW, ASUBV,
"SUBCC", LADDW, ASUBCC,
"SUBVCC", LADDW, ASUBVCC,
"SUBE", LLOGW, ASUBE,
"SUBECC", LLOGW, ASUBECC,
"SUBEV", LLOGW, ASUBEV,
"SUBEVCC", LLOGW, ASUBEVCC,
"SUBC", LADDW, ASUBC,
"SUBCCC", LADDW, ASUBCCC,
"SUBCV", LADDW, ASUBCV,
"SUBCVCC", LADDW, ASUBCVCC,
"SUBME", LABS, ASUBME,
"SUBMEV", LABS, ASUBMEV,
"SUBMECC", LABS, ASUBMECC,
"SUBMEVCC", LABS, ASUBMEVCC,
"SUBZE", LABS, ASUBZE,
"SUBZEV", LABS, ASUBZEV,
"SUBZECC", LABS, ASUBZECC,
"SUBZEVCC", LABS, ASUBZEVCC,
"AND", LADDW, AAND,
"ANDCC", LADDW, AANDCC, /* includes andil & andiu */
"ANDN", LLOGW, AANDN,
"ANDNCC", LLOGW, AANDNCC,
"EQV", LLOGW, AEQV,
"EQVCC", LLOGW, AEQVCC,
"NAND", LLOGW, ANAND,
"NANDCC", LLOGW, ANANDCC,
"NOR", LLOGW, ANOR,
"NORCC", LLOGW, ANORCC,
"OR", LADDW, AOR, /* includes oril & oriu */
"ORCC", LADDW, AORCC,
"ORN", LLOGW, AORN,
"ORNCC", LLOGW, AORNCC,
"XOR", LADDW, AXOR, /* includes xoril & xoriu */
"XORCC", LLOGW, AXORCC,
"EXTSB", LABS, AEXTSB,
"EXTSBCC", LABS, AEXTSBCC,
"EXTSH", LABS, AEXTSH,
"EXTSHCC", LABS, AEXTSHCC,
"CNTLZW", LABS, ACNTLZW,
"CNTLZWCC", LABS, ACNTLZWCC,
"RLWMI", LRLWM, ARLWMI,
"RLWMICC", LRLWM, ARLWMICC,
"RLWNM", LRLWM, ARLWNM,
"RLWNMCC", LRLWM, ARLWNMCC,
"SLW", LSHW, ASLW,
"SLWCC", LSHW, ASLWCC,
"SRW", LSHW, ASRW,
"SRWCC", LSHW, ASRWCC,
"SRAW", LSHW, ASRAW,
"SRAWCC", LSHW, ASRAWCC,
"BR", LBRA, ABR,
"BC", LBRA, ABC,
"BCL", LBRA, ABC,
"BL", LBRA, ABL,
"BEQ", LBRA, ABEQ,
"BNE", LBRA, ABNE,
"BGT", LBRA, ABGT,
"BGE", LBRA, ABGE,
"BLT", LBRA, ABLT,
"BLE", LBRA, ABLE,
"BVC", LBRA, ABVC,
"BVS", LBRA, ABVS,
"CMP", LCMP, ACMP,
"CMPU", LCMP, ACMPU,
"CMPW", LCMP, ACMPW,
"CMPWU", LCMP, ACMPWU,
"DIVW", LLOGW, ADIVW,
"DIVWV", LLOGW, ADIVWV,
"DIVWCC", LLOGW, ADIVWCC,
"DIVWVCC", LLOGW, ADIVWVCC,
"DIVWU", LLOGW, ADIVWU,
"DIVWUV", LLOGW, ADIVWUV,
"DIVWUCC", LLOGW, ADIVWUCC,
"DIVWUVCC", LLOGW, ADIVWUVCC,
"FABS", LFCONV, AFABS,
"FABSCC", LFCONV, AFABSCC,
"FNEG", LFCONV, AFNEG,
"FNEGCC", LFCONV, AFNEGCC,
"FNABS", LFCONV, AFNABS,
"FNABSCC", LFCONV, AFNABSCC,
"FADD", LFADD, AFADD,
"FADDCC", LFADD, AFADDCC,
"FSUB", LFADD, AFSUB,
"FSUBCC", LFADD, AFSUBCC,
"FMUL", LFADD, AFMUL,
"FMULCC", LFADD, AFMULCC,
"FDIV", LFADD, AFDIV,
"FDIVCC", LFADD, AFDIVCC,
"FRSP", LFCONV, AFRSP,
"FRSPCC", LFCONV, AFRSPCC,
"FCTIW", LFCONV, AFCTIW,
"FCTIWCC", LFCONV, AFCTIWCC,
"FCTIWZ", LFCONV, AFCTIWZ,
"FCTIWZCC", LFCONV, AFCTIWZCC,
"FMADD", LFMA, AFMADD,
"FMADDCC", LFMA, AFMADDCC,
"FMSUB", LFMA, AFMSUB,
"FMSUBCC", LFMA, AFMSUBCC,
"FNMADD", LFMA, AFNMADD,
"FNMADDCC", LFMA, AFNMADDCC,
"FNMSUB", LFMA, AFNMSUB,
"FNMSUBCC", LFMA, AFNMSUBCC,
"FMADDS", LFMA, AFMADDS,
"FMADDSCC", LFMA, AFMADDSCC,
"FMSUBS", LFMA, AFMSUBS,
"FMSUBSCC", LFMA, AFMSUBSCC,
"FNMADDS", LFMA, AFNMADDS,
"FNMADDSCC", LFMA, AFNMADDSCC,
"FNMSUBS", LFMA, AFNMSUBS,
"FNMSUBSCC", LFMA, AFNMSUBSCC,
"FCMPU", LFCMP, AFCMPU,
"FCMPO", LFCMP, AFCMPO,
"MTFSB0", LMTFSB, AMTFSB0,
"MTFSB1", LMTFSB, AMTFSB1,
"FMOVD", LFMOV, AFMOVD,
"FMOVS", LFMOV, AFMOVS,
"FMOVDCC", LFCONV, AFMOVDCC, /* fmr. */
"GLOBL", LGLOBL, AGLOBL,
"MOVB", LMOVB, AMOVB,
"MOVBZ", LMOVB, AMOVBZ,
"MOVBU", LMOVB, AMOVBU,
"MOVBZU", LMOVB, AMOVBZU,
"MOVH", LMOVB, AMOVH,
"MOVHZ", LMOVB, AMOVHZ,
"MOVHU", LMOVB, AMOVHU,
"MOVHZU", LMOVB, AMOVHZU,
"MOVHBR", LXMV, AMOVHBR,
"MOVWBR", LXMV, AMOVWBR,
"MOVW", LMOVW, AMOVW,
"MOVWU", LMOVW, AMOVWU,
"MOVMW", LMOVMW, AMOVMW,
"MOVFL", LMOVW, AMOVFL,
"MULLW", LADDW, AMULLW, /* includes multiply immediate 10-139 */
"MULLWV", LLOGW, AMULLWV,
"MULLWCC", LLOGW, AMULLWCC,
"MULLWVCC", LLOGW, AMULLWVCC,
"MULHW", LLOGW, AMULHW,
"MULHWCC", LLOGW, AMULHWCC,
"MULHWU", LLOGW, AMULHWU,
"MULHWUCC", LLOGW, AMULHWUCC,
"NEG", LABS, ANEG,
"NEGV", LABS, ANEGV,
"NEGCC", LABS, ANEGCC,
"NEGVCC", LABS, ANEGVCC,
"NOP", LNOP, ANOP, /* ori 0,0,0 */
"SYSCALL", LNOP, ASYSCALL,
"UNDEF", LNOP, AUNDEF,
"RET", LRETRN, ARETURN,
"RETURN", LRETRN, ARETURN,
"RFI", LRETRN, ARFI,
"RFCI", LRETRN, ARFCI,
"DATA", LDATA, ADATA,
"END", LEND, AEND,
"TEXT", LTEXT, ATEXT,
/* 64-bit instructions */
"CNTLZD", LABS, ACNTLZD,
"CNTLZDCC", LABS, ACNTLZDCC,
"DIVD", LLOGW, ADIVD,
"DIVDCC", LLOGW, ADIVDCC,
"DIVDVCC", LLOGW, ADIVDVCC,
"DIVDV", LLOGW, ADIVDV,
"DIVDU", LLOGW, ADIVDU,
"DIVDUCC", LLOGW, ADIVDUCC,
"DIVDUVCC", LLOGW, ADIVDUVCC,
"DIVDUV", LLOGW, ADIVDUV,
"EXTSW", LABS, AEXTSW,
"EXTSWCC", LABS, AEXTSWCC,
"FCTID", LFCONV, AFCTID,
"FCTIDCC", LFCONV, AFCTIDCC,
"FCTIDZ", LFCONV, AFCTIDZ,
"FCTIDZCC", LFCONV, AFCTIDZCC,
"FCFID", LFCONV, AFCFID,
"FCFIDCC", LFCONV, AFCFIDCC,
"LDAR", LXLD, ALDAR,
"MOVD", LMOVW, AMOVD,
"MOVDU", LMOVW, AMOVDU,
"MOVWZ", LMOVW, AMOVWZ,
"MOVWZU", LMOVW, AMOVWZU,
"MULHD", LLOGW, AMULHD,
"MULHDCC", LLOGW, AMULHDCC,
"MULHDU", LLOGW, AMULHDU,
"MULHDUCC", LLOGW, AMULHDUCC,
"MULLD", LADDW, AMULLD, /* includes multiply immediate? */
"MULLDCC", LLOGW, AMULLDCC,
"MULLDVCC", LLOGW, AMULLDVCC,
"MULLDV", LLOGW, AMULLDV,
"RFID", LRETRN, ARFID,
"HRFID", LRETRN, AHRFID,
"RLDMI", LRLWM, ARLDMI,
"RLDMICC", LRLWM, ARLDMICC,
"RLDC", LRLWM, ARLDC,
"RLDCCC", LRLWM, ARLDCCC,
"RLDCR", LRLWM, ARLDCR,
"RLDCRCC", LRLWM, ARLDCRCC,
"RLDCL", LRLWM, ARLDCL,
"RLDCLCC", LRLWM, ARLDCLCC,
"SLBIA", LNOP, ASLBIA,
"SLBIE", LNOP, ASLBIE,
"SLBMFEE", LABS, ASLBMFEE,
"SLBMFEV", LABS, ASLBMFEV,
"SLBMTE", LABS, ASLBMTE,
"SLD", LSHW, ASLD,
"SLDCC", LSHW, ASLDCC,
"SRD", LSHW, ASRD,
"SRAD", LSHW, ASRAD,
"SRADCC", LSHW, ASRADCC,
"SRDCC", LSHW, ASRDCC,
"STDCCC", LXST, ASTDCCC,
"TD", LADDW, ATD,
/* pseudo instructions */
"REM", LLOGW, AREM,
"REMCC", LLOGW, AREMCC,
"REMV", LLOGW, AREMV,
"REMVCC", LLOGW, AREMVCC,
"REMU", LLOGW, AREMU,
"REMUCC", LLOGW, AREMUCC,
"REMUV", LLOGW, AREMUV,
"REMUVCC", LLOGW, AREMUVCC,
"REMD", LLOGW, AREMD,
"REMDCC", LLOGW, AREMDCC,
"REMDV", LLOGW, AREMDV,
"REMDVCC", LLOGW, AREMDVCC,
"REMDU", LLOGW, AREMDU,
"REMDUCC", LLOGW, AREMDUCC,
"REMDUV", LLOGW, AREMDUV,
"REMDUVCC", LLOGW, AREMDUVCC,
/* special instructions */
"DCBF", LXOP, ADCBF,
"DCBI", LXOP, ADCBI,
"DCBST", LXOP, ADCBST,
"DCBT", LXOP, ADCBT,
"DCBTST", LXOP, ADCBTST,
"DCBZ", LXOP, ADCBZ,
"ICBI", LXOP, AICBI,
"ECIWX", LXLD, AECIWX,
"ECOWX", LXST, AECOWX,
"LWAR", LXLD, ALWAR,
"LWAR", LXLD, ALWAR,
"STWCCC", LXST, ASTWCCC,
"EIEIO", LRETRN, AEIEIO,
"TLBIE", LNOP, ATLBIE,
"TLBIEL", LNOP, ATLBIEL,
"LSW", LXLD, ALSW,
"STSW", LXST, ASTSW,
"ISYNC", LRETRN, AISYNC,
"SYNC", LRETRN, ASYNC,
"TLBSYNC", LRETRN, ATLBSYNC,
"PTESYNC", LRETRN, APTESYNC,
/* "TW", LADDW, ATW,*/
"WORD", LWORD, AWORD,
"DWORD", LWORD, ADWORD,
"SCHED", LSCHED, 0,
"NOSCHED", LSCHED, 0x80,
"PCDATA", LPCDAT, APCDATA,
"FUNCDATA", LFUNCDAT, AFUNCDATA,
0
};
void
cinit(void)
{
Sym *s;
int i;
nullgen.type = TYPE_NONE;
nullgen.name = NAME_NONE;
nullgen.reg = 0;
nullgen.scale = 0; // replaced Gen.xreg with Prog.scale
nerrors = 0;
iostack = I;
iofree = I;
peekc = IGN;
nhunk = 0;
for(i=0; i<NHASH; i++)
hash[i] = S;
for(i=0; itab[i].name; i++) {
s = slookup(itab[i].name);
s->type = itab[i].type;
s->value = itab[i].value;
}
}
void
syminit(Sym *s)
{
s->type = LNAME;
s->value = 0;
}
void
cclean(void)
{
outcode(AEND, &nullgen, 0, &nullgen);
}
void
outcode(int a, Addr *g1, int reg, Addr *g2)
{
Prog *p;
Plist *pl;
if(pass == 1)
goto out;
if(g1->scale != 0) {
if(reg != 0 || g2->scale != 0)
yyerror("bad addressing modes");
reg = g1->scale;
} else
if(g2->scale != 0) {
if(reg != 0)
yyerror("bad addressing modes");
reg = g2->scale;
}
p = emallocz(sizeof(Prog));
p->as = a;
p->lineno = stmtline;
if(nosched)
p->mark |= NOSCHED;
p->from = *g1;
p->reg = reg;
p->to = *g2;
p->pc = pc;
if(lastpc == nil) {
pl = linknewplist(ctxt);
pl->firstpc = p;
} else
lastpc->link = p;
lastpc = p;
out:
if(a != AGLOBL && a != ADATA)
pc++;
}
void
outgcode(int a, Addr *g1, int reg, Addr *g2, Addr *g3)
{
Prog *p;
Plist *pl;
if(pass == 1)
goto out;
p = emallocz(sizeof(Prog));
p->as = a;
p->lineno = stmtline;
if(nosched)
p->mark |= NOSCHED;
p->from = *g1;
p->reg = reg;
p->from3 = *g2;
p->to = *g3;
p->pc = pc;
if(lastpc == nil) {
pl = linknewplist(ctxt);
pl->firstpc = p;
} else
lastpc->link = p;
lastpc = p;
out:
if(a != AGLOBL && a != ADATA)
pc++;
}
#include "../cc/lexbody"
#include "../cc/macbody"

File diff suppressed because it is too large Load diff

View file

@ -1,190 +0,0 @@
/* A Bison parser, made by GNU Bison 2.3. */
/* Skeleton interface for Bison's Yacc-like parsers in C
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
under terms of your choice, so long as that work isn't itself a
parser generator using the skeleton or a modified version thereof
as a parser skeleton. Alternatively, if you modify or redistribute
the parser skeleton itself, you may (at your option) remove this
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
LMOVW = 258,
LMOVB = 259,
LABS = 260,
LLOGW = 261,
LSHW = 262,
LADDW = 263,
LCMP = 264,
LCROP = 265,
LBRA = 266,
LFMOV = 267,
LFCONV = 268,
LFCMP = 269,
LFADD = 270,
LFMA = 271,
LTRAP = 272,
LXORW = 273,
LNOP = 274,
LEND = 275,
LRETT = 276,
LWORD = 277,
LTEXT = 278,
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 LMOVW 258
#define LMOVB 259
#define LABS 260
#define LLOGW 261
#define LSHW 262
#define LADDW 263
#define LCMP 264
#define LCROP 265
#define LBRA 266
#define LFMOV 267
#define LFCONV 268
#define LFCMP 269
#define LFADD 270
#define LFMA 271
#define LTRAP 272
#define LXORW 273
#define LNOP 274
#define LEND 275
#define LRETT 276
#define LWORD 277
#define LTEXT 278
#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
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
#line 38 "a.y"
{
Sym *sym;
vlong lval;
double dval;
char sval[8];
Addr addr;
}
/* Line 1529 of yacc.c. */
#line 183 "y.tab.h"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
#endif
extern YYSTYPE yylval;

File diff suppressed because it is too large Load diff

View file

@ -1,16 +0,0 @@
// 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.
// +build ignore
/*
9g is the version of the gc compiler for 64-bit PowerPC or Power Architecture processors.
The $GOARCH for these tools is ppc64 (big endian) or
ppc64le (little endian).
It reads .go files and outputs .9 files. The flags are documented in ../gc/doc.go.
*/
package main

Some files were not shown because too many files have changed in this diff Show more