mirror of
https://github.com/golang/go.git
synced 2025-11-06 11:40:59 +00:00
[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:
parent
d10ede5ede
commit
3af0d791be
175 changed files with 854 additions and 97601 deletions
|
|
@ -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
|
|
||||||
173
src/cmd/5a/a.h
173
src/cmd/5a/a.h
|
|
@ -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);
|
|
||||||
385
src/cmd/5a/a.y
385
src/cmd/5a/a.y
|
|
@ -29,20 +29,23 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
%{
|
%{
|
||||||
#include <u.h>
|
package main
|
||||||
#include <stdio.h> /* if we don't, bison will, and a.h re-#defines getc */
|
|
||||||
#include <libc.h>
|
import (
|
||||||
#include "a.h"
|
"cmd/internal/asm"
|
||||||
#include "../../runtime/funcdata.h"
|
"cmd/internal/obj"
|
||||||
|
. "cmd/internal/obj/arm"
|
||||||
|
)
|
||||||
%}
|
%}
|
||||||
%union
|
|
||||||
{
|
%union {
|
||||||
Sym *sym;
|
sym *asm.Sym
|
||||||
int32 lval;
|
lval int32
|
||||||
double dval;
|
dval float64
|
||||||
char sval[8];
|
sval string
|
||||||
Addr addr;
|
addr obj.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
%left '|'
|
%left '|'
|
||||||
%left '^'
|
%left '^'
|
||||||
%left '&'
|
%left '&'
|
||||||
|
|
@ -51,12 +54,12 @@
|
||||||
%left '*' '/' '%'
|
%left '*' '/' '%'
|
||||||
%token <lval> LTYPE1 LTYPE2 LTYPE3 LTYPE4 LTYPE5
|
%token <lval> LTYPE1 LTYPE2 LTYPE3 LTYPE4 LTYPE5
|
||||||
%token <lval> LTYPE6 LTYPE7 LTYPE8 LTYPE9 LTYPEA
|
%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> LTYPEG LTYPEH LTYPEI LTYPEJ LTYPEK
|
||||||
%token <lval> LTYPEL LTYPEM LTYPEN LTYPEBX LTYPEPLD
|
%token <lval> LTYPEL LTYPEM LTYPEN LTYPEBX LTYPEPLD
|
||||||
%token <lval> LCONST LSP LSB LFP LPC
|
%token <lval> LCONST LSP LSB LFP LPC
|
||||||
%token <lval> LTYPEX LTYPEPC LTYPEF LR LREG LF LFREG LC LCREG LPSR LFCR
|
%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 <dval> LFCONST
|
||||||
%token <sval> LSCONST
|
%token <sval> LSCONST
|
||||||
%token <sym> LNAME LLAB LVAR
|
%token <sym> LNAME LLAB LVAR
|
||||||
|
|
@ -68,30 +71,32 @@
|
||||||
prog:
|
prog:
|
||||||
| prog
|
| prog
|
||||||
{
|
{
|
||||||
stmtline = lineno;
|
stmtline = asm.Lineno;
|
||||||
}
|
}
|
||||||
line
|
line
|
||||||
|
|
||||||
line:
|
line:
|
||||||
LNAME ':'
|
LNAME ':'
|
||||||
{
|
{
|
||||||
$1 = labellookup($1);
|
$1 = asm.LabelLookup($1);
|
||||||
if($1->type == LLAB && $1->value != pc)
|
if $1.Type == LLAB && $1.Value != int64(asm.PC) {
|
||||||
yyerror("redeclaration of %s", $1->labelname);
|
yyerror("redeclaration of %s", $1.Labelname)
|
||||||
$1->type = LLAB;
|
}
|
||||||
$1->value = pc;
|
$1.Type = LLAB;
|
||||||
|
$1.Value = int64(asm.PC)
|
||||||
}
|
}
|
||||||
line
|
line
|
||||||
| LNAME '=' expr ';'
|
| LNAME '=' expr ';'
|
||||||
{
|
{
|
||||||
$1->type = LVAR;
|
$1.Type = LVAR;
|
||||||
$1->value = $3;
|
$1.Value = int64($3);
|
||||||
}
|
}
|
||||||
| LVAR '=' expr ';'
|
| LVAR '=' expr ';'
|
||||||
{
|
{
|
||||||
if($1->value != $3)
|
if $1.Value != int64($3) {
|
||||||
yyerror("redeclaration of %s", $1->name);
|
yyerror("redeclaration of %s", $1.Name)
|
||||||
$1->value = $3;
|
}
|
||||||
|
$1.Value = int64($3);
|
||||||
}
|
}
|
||||||
| ';'
|
| ';'
|
||||||
| inst ';'
|
| inst ';'
|
||||||
|
|
@ -171,20 +176,20 @@ inst:
|
||||||
*/
|
*/
|
||||||
| LTYPE8 cond ioreg ',' '[' reglist ']'
|
| LTYPE8 cond ioreg ',' '[' reglist ']'
|
||||||
{
|
{
|
||||||
Addr g;
|
var g obj.Addr
|
||||||
|
|
||||||
g = nullgen;
|
g = nullgen;
|
||||||
g.type = TYPE_CONST;
|
g.Type = obj.TYPE_CONST;
|
||||||
g.offset = $6;
|
g.Offset = int64($6);
|
||||||
outcode($1, $2, &$3, 0, &g);
|
outcode($1, $2, &$3, 0, &g);
|
||||||
}
|
}
|
||||||
| LTYPE8 cond '[' reglist ']' ',' ioreg
|
| LTYPE8 cond '[' reglist ']' ',' ioreg
|
||||||
{
|
{
|
||||||
Addr g;
|
var g obj.Addr
|
||||||
|
|
||||||
g = nullgen;
|
g = nullgen;
|
||||||
g.type = TYPE_CONST;
|
g.Type = obj.TYPE_CONST;
|
||||||
g.offset = $4;
|
g.Offset = int64($4);
|
||||||
outcode($1, $2, &g, 0, &$7);
|
outcode($1, $2, &g, 0, &$7);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
@ -192,15 +197,15 @@ inst:
|
||||||
*/
|
*/
|
||||||
| LTYPE9 cond reg ',' ireg ',' reg
|
| 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
|
| 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
|
| LTYPE9 cond comma ireg ',' reg
|
||||||
{
|
{
|
||||||
outcode($1, $2, &$4, $6.reg, &$6);
|
outcode($1, $2, &$4, int32($6.Reg), &$6);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* RET
|
* RET
|
||||||
|
|
@ -214,16 +219,16 @@ inst:
|
||||||
*/
|
*/
|
||||||
| LTYPEB name ',' '$' textsize
|
| LTYPEB name ',' '$' textsize
|
||||||
{
|
{
|
||||||
settext($2.sym);
|
asm.Settext($2.Sym);
|
||||||
outcode($1, Always, &$2, 0, &$5);
|
outcode($1, Always, &$2, 0, &$5);
|
||||||
}
|
}
|
||||||
| LTYPEB name ',' con ',' '$' textsize
|
| LTYPEB name ',' con ',' '$' textsize
|
||||||
{
|
{
|
||||||
settext($2.sym);
|
asm.Settext($2.Sym);
|
||||||
outcode($1, Always, &$2, 0, &$7);
|
outcode($1, Always, &$2, 0, &$7);
|
||||||
if(pass > 1) {
|
if asm.Pass > 1 {
|
||||||
lastpc->from3.type = TYPE_CONST;
|
lastpc.From3.Type = obj.TYPE_CONST;
|
||||||
lastpc->from3.offset = $4;
|
lastpc.From3.Offset = int64($4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
@ -231,27 +236,28 @@ inst:
|
||||||
*/
|
*/
|
||||||
| LGLOBL name ',' imm
|
| LGLOBL name ',' imm
|
||||||
{
|
{
|
||||||
settext($2.sym);
|
asm.Settext($2.Sym)
|
||||||
outcode($1, Always, &$2, 0, &$4);
|
outcode($1, Always, &$2, 0, &$4)
|
||||||
}
|
}
|
||||||
| LGLOBL name ',' con ',' imm
|
| LGLOBL name ',' con ',' imm
|
||||||
{
|
{
|
||||||
settext($2.sym);
|
asm.Settext($2.Sym)
|
||||||
outcode($1, Always, &$2, 0, &$6);
|
outcode($1, Always, &$2, 0, &$6)
|
||||||
if(pass > 1) {
|
if asm.Pass > 1 {
|
||||||
lastpc->from3.type = TYPE_CONST;
|
lastpc.From3.Type = obj.TYPE_CONST
|
||||||
lastpc->from3.offset = $4;
|
lastpc.From3.Offset = int64($4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DATA
|
* DATA
|
||||||
*/
|
*/
|
||||||
| LTYPEC name '/' con ',' ximm
|
| LTYPEC name '/' con ',' ximm
|
||||||
{
|
{
|
||||||
outcode($1, Always, &$2, 0, &$6);
|
outcode($1, Always, &$2, 0, &$6)
|
||||||
if(pass > 1) {
|
if asm.Pass > 1 {
|
||||||
lastpc->from3.type = TYPE_CONST;
|
lastpc.From3.Type = obj.TYPE_CONST
|
||||||
lastpc->from3.offset = $4;
|
lastpc.From3.Offset = int64($4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
@ -285,18 +291,18 @@ inst:
|
||||||
}
|
}
|
||||||
| LTYPEL cond freg ',' freg comma
|
| LTYPEL cond freg ',' freg comma
|
||||||
{
|
{
|
||||||
outcode($1, $2, &$3, $5.reg, &nullgen);
|
outcode($1, $2, &$3, int32($5.Reg), &nullgen);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* MCR MRC
|
* MCR MRC
|
||||||
*/
|
*/
|
||||||
| LTYPEJ cond con ',' expr ',' spreg ',' creg ',' creg oexpr
|
| LTYPEJ cond con ',' expr ',' spreg ',' creg ',' creg oexpr
|
||||||
{
|
{
|
||||||
Addr g;
|
var g obj.Addr
|
||||||
|
|
||||||
g = nullgen;
|
g = nullgen;
|
||||||
g.type = TYPE_CONST;
|
g.Type = obj.TYPE_CONST;
|
||||||
g.offset =
|
g.Offset = int64(
|
||||||
(0xe << 24) | /* opcode */
|
(0xe << 24) | /* opcode */
|
||||||
($1 << 20) | /* MCR/MRC */
|
($1 << 20) | /* MCR/MRC */
|
||||||
(($2^C_SCOND_XOR) << 28) | /* scond */
|
(($2^C_SCOND_XOR) << 28) | /* scond */
|
||||||
|
|
@ -306,7 +312,7 @@ inst:
|
||||||
(($9 & 15) << 16) | /* Crn */
|
(($9 & 15) << 16) | /* Crn */
|
||||||
(($11 & 15) << 0) | /* Crm */
|
(($11 & 15) << 0) | /* Crm */
|
||||||
(($12 & 7) << 5) | /* coprocessor information */
|
(($12 & 7) << 5) | /* coprocessor information */
|
||||||
(1<<4); /* must be set */
|
(1<<4)); /* must be set */
|
||||||
outcode(AMRC, Always, &nullgen, 0, &g);
|
outcode(AMRC, Always, &nullgen, 0, &g);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
@ -314,17 +320,17 @@ inst:
|
||||||
*/
|
*/
|
||||||
| LTYPEM cond reg ',' reg ',' regreg
|
| 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
|
* MULAW{T,B} r1,r2,r3,r4
|
||||||
*/
|
*/
|
||||||
| LTYPEN cond reg ',' reg ',' reg ',' spreg
|
| LTYPEN cond reg ',' reg ',' reg ',' spreg
|
||||||
{
|
{
|
||||||
$7.type = TYPE_REGREG2;
|
$7.Type = obj.TYPE_REGREG2;
|
||||||
$7.offset = $9;
|
$7.Offset = int64($9);
|
||||||
outcode($1, $2, &$3, $5.reg, &$7);
|
outcode($1, $2, &$3, int32($5.Reg), &$7);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* PLD
|
* PLD
|
||||||
|
|
@ -338,8 +344,9 @@ inst:
|
||||||
*/
|
*/
|
||||||
| LTYPEPC gen ',' gen
|
| LTYPEPC gen ',' gen
|
||||||
{
|
{
|
||||||
if($2.type != TYPE_CONST || $4.type != TYPE_CONST)
|
if $2.Type != obj.TYPE_CONST || $4.Type != obj.TYPE_CONST {
|
||||||
yyerror("arguments to PCDATA must be integer constants");
|
yyerror("arguments to PCDATA must be integer constants")
|
||||||
|
}
|
||||||
outcode($1, Always, &$2, 0, &$4);
|
outcode($1, Always, &$2, 0, &$4);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
@ -347,10 +354,12 @@ inst:
|
||||||
*/
|
*/
|
||||||
| LTYPEF gen ',' gen
|
| LTYPEF gen ',' gen
|
||||||
{
|
{
|
||||||
if($2.type != TYPE_CONST)
|
if $2.Type != obj.TYPE_CONST {
|
||||||
yyerror("index for FUNCDATA must be integer constant");
|
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 $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);
|
outcode($1, Always, &$2, 0, &$4);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
@ -361,13 +370,43 @@ inst:
|
||||||
outcode($1, Always, &nullgen, 0, &nullgen);
|
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:
|
cond:
|
||||||
{
|
{
|
||||||
$$ = Always;
|
$$ = Always;
|
||||||
}
|
}
|
||||||
| cond LCOND
|
| cond LCOND
|
||||||
{
|
{
|
||||||
$$ = ($1 & ~C_SCOND) | $2;
|
$$ = ($1 & ^ C_SCOND) | $2;
|
||||||
}
|
}
|
||||||
| cond LS
|
| cond LS
|
||||||
{
|
{
|
||||||
|
|
@ -381,65 +420,36 @@ rel:
|
||||||
con '(' LPC ')'
|
con '(' LPC ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_BRANCH;
|
$$.Type = obj.TYPE_BRANCH;
|
||||||
$$.offset = $1 + pc;
|
$$.Offset = int64($1) + int64(asm.PC);
|
||||||
}
|
}
|
||||||
| LNAME offset
|
| LNAME offset
|
||||||
{
|
{
|
||||||
$1 = labellookup($1);
|
$1 = asm.LabelLookup($1);
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
if(pass == 2 && $1->type != LLAB)
|
if asm.Pass == 2 && $1.Type != LLAB {
|
||||||
yyerror("undefined label: %s", $1->labelname);
|
yyerror("undefined label: %s", $1.Labelname)
|
||||||
$$.type = TYPE_BRANCH;
|
}
|
||||||
$$.offset = $1->value + $2;
|
$$.Type = obj.TYPE_BRANCH;
|
||||||
}
|
$$.Offset = $1.Value + int64($2);
|
||||||
|
|
||||||
textsize:
|
|
||||||
LCONST
|
|
||||||
{
|
|
||||||
$$ = nullgen;
|
|
||||||
$$.type = TYPE_TEXTSIZE;
|
|
||||||
$$.offset = $1;
|
|
||||||
$$.u.argsize = ArgsSizeUnknown;
|
|
||||||
}
|
|
||||||
| '-' LCONST
|
|
||||||
{
|
|
||||||
$$ = nullgen;
|
|
||||||
$$.type = TYPE_TEXTSIZE;
|
|
||||||
$$.offset = -$2;
|
|
||||||
$$.u.argsize = ArgsSizeUnknown;
|
|
||||||
}
|
|
||||||
| LCONST '-' LCONST
|
|
||||||
{
|
|
||||||
$$ = nullgen;
|
|
||||||
$$.type = TYPE_TEXTSIZE;
|
|
||||||
$$.offset = $1;
|
|
||||||
$$.u.argsize = $3;
|
|
||||||
}
|
|
||||||
| '-' LCONST '-' LCONST
|
|
||||||
{
|
|
||||||
$$ = nullgen;
|
|
||||||
$$.type = TYPE_TEXTSIZE;
|
|
||||||
$$.offset = -$2;
|
|
||||||
$$.u.argsize = $4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ximm: '$' con
|
ximm: '$' con
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_CONST;
|
$$.Type = obj.TYPE_CONST;
|
||||||
$$.offset = $2;
|
$$.Offset = int64($2);
|
||||||
}
|
}
|
||||||
| '$' oreg
|
| '$' oreg
|
||||||
{
|
{
|
||||||
$$ = $2;
|
$$ = $2;
|
||||||
$$.type = TYPE_ADDR;
|
$$.Type = obj.TYPE_ADDR;
|
||||||
}
|
}
|
||||||
| '$' LSCONST
|
| '$' LSCONST
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_SCONST;
|
$$.Type = obj.TYPE_SCONST;
|
||||||
memcpy($$.u.sval, $2, sizeof($$.u.sval));
|
$$.U.Sval = $2
|
||||||
}
|
}
|
||||||
| fcon
|
| fcon
|
||||||
|
|
||||||
|
|
@ -447,45 +457,34 @@ fcon:
|
||||||
'$' LFCONST
|
'$' LFCONST
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_FCONST;
|
$$.Type = obj.TYPE_FCONST;
|
||||||
$$.u.dval = $2;
|
$$.U.Dval = $2;
|
||||||
}
|
}
|
||||||
| '$' '-' LFCONST
|
| '$' '-' LFCONST
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_FCONST;
|
$$.Type = obj.TYPE_FCONST;
|
||||||
$$.u.dval = -$3;
|
$$.U.Dval = -$3;
|
||||||
}
|
}
|
||||||
|
|
||||||
reglist:
|
reglist:
|
||||||
spreg
|
spreg
|
||||||
{
|
{
|
||||||
if($1 < REG_R0 || $1 > REG_R15)
|
$$ = 1 << uint($1&15);
|
||||||
yyerror("invalid register in reglist");
|
|
||||||
|
|
||||||
$$ = 1 << ($1&15);
|
|
||||||
}
|
}
|
||||||
| spreg '-' spreg
|
| 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;
|
$$=0;
|
||||||
for(i=$1; i<=$3; i++)
|
for i:=$1; i<=$3; i++ {
|
||||||
$$ |= 1<<(i&15);
|
$$ |= 1<<uint(i&15)
|
||||||
for(i=$3; i<=$1; i++)
|
}
|
||||||
$$ |= 1<<(i&15);
|
for i:=$3; i<=$1; i++ {
|
||||||
|
$$ |= 1<<uint(i&15)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
| spreg comma reglist
|
| spreg comma reglist
|
||||||
{
|
{
|
||||||
if($1 < REG_R0 || $1 > REG_R15)
|
$$ = (1<<uint($1&15)) | $3;
|
||||||
yyerror("invalid register in reglist");
|
|
||||||
|
|
||||||
$$ = (1<<($1&15)) | $3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gen:
|
gen:
|
||||||
|
|
@ -495,25 +494,25 @@ gen:
|
||||||
| shift '(' spreg ')'
|
| shift '(' spreg ')'
|
||||||
{
|
{
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
$$.reg = $3;
|
$$.Reg = int16($3);
|
||||||
}
|
}
|
||||||
| LPSR
|
| LPSR
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_REG;
|
$$.Type = obj.TYPE_REG
|
||||||
$$.reg = $1;
|
$$.Reg = int16($1);
|
||||||
}
|
}
|
||||||
| LFCR
|
| LFCR
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_REG;
|
$$.Type = obj.TYPE_REG
|
||||||
$$.reg = $1;
|
$$.Reg = int16($1);
|
||||||
}
|
}
|
||||||
| con
|
| con
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM;
|
||||||
$$.offset = $1;
|
$$.Offset = int64($1);
|
||||||
}
|
}
|
||||||
| oreg
|
| oreg
|
||||||
| freg
|
| freg
|
||||||
|
|
@ -523,7 +522,7 @@ nireg:
|
||||||
| name
|
| name
|
||||||
{
|
{
|
||||||
$$ = $1;
|
$$ = $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 ')'
|
'(' spreg ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM;
|
||||||
$$.reg = $2;
|
$$.Reg = int16($2);
|
||||||
$$.offset = 0;
|
$$.Offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ioreg:
|
ioreg:
|
||||||
|
|
@ -541,9 +540,9 @@ ioreg:
|
||||||
| con '(' sreg ')'
|
| con '(' sreg ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM;
|
||||||
$$.reg = $3;
|
$$.Reg = int16($3);
|
||||||
$$.offset = $1;
|
$$.Offset = int64($1);
|
||||||
}
|
}
|
||||||
|
|
||||||
oreg:
|
oreg:
|
||||||
|
|
@ -551,8 +550,8 @@ oreg:
|
||||||
| name '(' sreg ')'
|
| name '(' sreg ')'
|
||||||
{
|
{
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM;
|
||||||
$$.reg = $3;
|
$$.Reg = int16($3);
|
||||||
}
|
}
|
||||||
| ioreg
|
| ioreg
|
||||||
|
|
||||||
|
|
@ -564,64 +563,66 @@ imsr:
|
||||||
imm: '$' con
|
imm: '$' con
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_CONST;
|
$$.Type = obj.TYPE_CONST;
|
||||||
$$.offset = $2;
|
$$.Offset = int64($2);
|
||||||
}
|
}
|
||||||
|
|
||||||
reg:
|
reg:
|
||||||
spreg
|
spreg
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_REG;
|
$$.Type = obj.TYPE_REG;
|
||||||
$$.reg = $1;
|
$$.Reg = int16($1);
|
||||||
}
|
}
|
||||||
|
|
||||||
regreg:
|
regreg:
|
||||||
'(' spreg ',' spreg ')'
|
'(' spreg ',' spreg ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_REGREG;
|
$$.Type = obj.TYPE_REGREG;
|
||||||
$$.reg = $2;
|
$$.Reg = int16($2);
|
||||||
$$.offset = $4;
|
$$.Offset = int64($4);
|
||||||
}
|
}
|
||||||
|
|
||||||
shift:
|
shift:
|
||||||
spreg '<' '<' rcon
|
spreg '<' '<' rcon
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_SHIFT;
|
$$.Type = obj.TYPE_SHIFT;
|
||||||
$$.offset = $1&15 | $4 | (0 << 5);
|
$$.Offset = int64($1&15) | int64($4) | (0 << 5);
|
||||||
}
|
}
|
||||||
| spreg '>' '>' rcon
|
| spreg '>' '>' rcon
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_SHIFT;
|
$$.Type = obj.TYPE_SHIFT;
|
||||||
$$.offset = $1&15 | $4 | (1 << 5);
|
$$.Offset = int64($1&15) | int64($4) | (1 << 5);
|
||||||
}
|
}
|
||||||
| spreg '-' '>' rcon
|
| spreg '-' '>' rcon
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_SHIFT;
|
$$.Type = obj.TYPE_SHIFT;
|
||||||
$$.offset = $1&15 | $4 | (2 << 5);
|
$$.Offset = int64($1&15) | int64($4) | (2 << 5);
|
||||||
}
|
}
|
||||||
| spreg LAT '>' rcon
|
| spreg LAT '>' rcon
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_SHIFT;
|
$$.Type = obj.TYPE_SHIFT;
|
||||||
$$.offset = $1&15 | $4 | (3 << 5);
|
$$.Offset = int64($1&15) | int64($4) | (3 << 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
rcon:
|
rcon:
|
||||||
spreg
|
spreg
|
||||||
{
|
{
|
||||||
if($$ < REG_R0 || $$ > REG_R15)
|
if $$ < REG_R0 || $$ > REG_R15 {
|
||||||
print("register value out of range in shift\n");
|
print("register value out of range\n")
|
||||||
|
}
|
||||||
$$ = (($1&15) << 8) | (1 << 4);
|
$$ = (($1&15) << 8) | (1 << 4);
|
||||||
}
|
}
|
||||||
| con
|
| con
|
||||||
{
|
{
|
||||||
if($$ < 0 || $$ >= 32)
|
if $$ < 0 || $$ >= 32 {
|
||||||
print("shift value out of range\n");
|
print("shift value out of range\n")
|
||||||
|
}
|
||||||
$$ = ($1&31) << 7;
|
$$ = ($1&31) << 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -633,8 +634,9 @@ sreg:
|
||||||
}
|
}
|
||||||
| LR '(' expr ')'
|
| LR '(' expr ')'
|
||||||
{
|
{
|
||||||
if($3 < 0 || $3 >= NREG)
|
if $3 < 0 || $3 >= NREG {
|
||||||
print("register value out of range in R(...)\n");
|
print("register value out of range\n")
|
||||||
|
}
|
||||||
$$ = REG_R0 + $3;
|
$$ = REG_R0 + $3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -649,8 +651,9 @@ creg:
|
||||||
LCREG
|
LCREG
|
||||||
| LC '(' expr ')'
|
| LC '(' expr ')'
|
||||||
{
|
{
|
||||||
if($3 < 0 || $3 >= NREG)
|
if $3 < 0 || $3 >= NREG {
|
||||||
print("register value out of range in C(...)\n");
|
print("register value out of range\n")
|
||||||
|
}
|
||||||
$$ = $3; // TODO(rsc): REG_C0+$3
|
$$ = $3; // TODO(rsc): REG_C0+$3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -662,40 +665,40 @@ freg:
|
||||||
LFREG
|
LFREG
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_REG;
|
$$.Type = obj.TYPE_REG;
|
||||||
$$.reg = $1;
|
$$.Reg = int16($1);
|
||||||
}
|
}
|
||||||
| LF '(' con ')'
|
| LF '(' con ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_REG;
|
$$.Type = obj.TYPE_REG;
|
||||||
$$.reg = REG_F0 + $3;
|
$$.Reg = int16(REG_F0 + $3);
|
||||||
}
|
}
|
||||||
|
|
||||||
name:
|
name:
|
||||||
con '(' pointer ')'
|
con '(' pointer ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM;
|
||||||
$$.name = $3;
|
$$.Name = int8($3);
|
||||||
$$.sym = nil;
|
$$.Sym = nil;
|
||||||
$$.offset = $1;
|
$$.Offset = int64($1);
|
||||||
}
|
}
|
||||||
| LNAME offset '(' pointer ')'
|
| LNAME offset '(' pointer ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM;
|
||||||
$$.name = $4;
|
$$.Name = int8($4);
|
||||||
$$.sym = linklookup(ctxt, $1->name, 0);
|
$$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
|
||||||
$$.offset = $2;
|
$$.Offset = int64($2);
|
||||||
}
|
}
|
||||||
| LNAME '<' '>' offset '(' LSB ')'
|
| LNAME '<' '>' offset '(' LSB ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM;
|
||||||
$$.name = NAME_STATIC;
|
$$.Name = obj.NAME_STATIC;
|
||||||
$$.sym = linklookup(ctxt, $1->name, 1);
|
$$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 1);
|
||||||
$$.offset = $4;
|
$$.Offset = int64($4);
|
||||||
}
|
}
|
||||||
|
|
||||||
offset:
|
offset:
|
||||||
|
|
@ -720,7 +723,7 @@ con:
|
||||||
LCONST
|
LCONST
|
||||||
| LVAR
|
| LVAR
|
||||||
{
|
{
|
||||||
$$ = $1->value;
|
$$ = int32($1.Value);
|
||||||
}
|
}
|
||||||
| '-' con
|
| '-' con
|
||||||
{
|
{
|
||||||
|
|
@ -732,7 +735,7 @@ con:
|
||||||
}
|
}
|
||||||
| '~' con
|
| '~' con
|
||||||
{
|
{
|
||||||
$$ = ~$2;
|
$$ = ^$2;
|
||||||
}
|
}
|
||||||
| '(' expr ')'
|
| '(' expr ')'
|
||||||
{
|
{
|
||||||
|
|
@ -772,11 +775,11 @@ expr:
|
||||||
}
|
}
|
||||||
| expr '<' '<' expr
|
| expr '<' '<' expr
|
||||||
{
|
{
|
||||||
$$ = $1 << $4;
|
$$ = $1 << uint($4);
|
||||||
}
|
}
|
||||||
| expr '>' '>' expr
|
| expr '>' '>' expr
|
||||||
{
|
{
|
||||||
$$ = $1 >> $4;
|
$$ = $1 >> uint($4);
|
||||||
}
|
}
|
||||||
| expr '&' expr
|
| expr '&' expr
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
538
src/cmd/5a/lex.c
538
src/cmd/5a/lex.c
|
|
@ -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"
|
|
||||||
2855
src/cmd/5a/y.tab.c
2855
src/cmd/5a/y.tab.c
File diff suppressed because it is too large
Load diff
|
|
@ -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;
|
|
||||||
|
|
||||||
|
|
@ -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
|
|
||||||
1840
src/cmd/5g/cgen.c
1840
src/cmd/5g/cgen.c
File diff suppressed because it is too large
Load diff
|
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
177
src/cmd/5g/gg.h
177
src/cmd/5g/gg.h
|
|
@ -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*);
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1527
src/cmd/5g/gsubr.c
1527
src/cmd/5g/gsubr.c
File diff suppressed because it is too large
Load diff
1619
src/cmd/5g/peep.c
1619
src/cmd/5g/peep.c
File diff suppressed because it is too large
Load diff
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
146
src/cmd/5g/reg.c
146
src/cmd/5g/reg.c
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
||||||
188
src/cmd/6a/a.h
188
src/cmd/6a/a.h
|
|
@ -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*);
|
|
||||||
381
src/cmd/6a/a.y
381
src/cmd/6a/a.y
|
|
@ -29,20 +29,24 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
%{
|
%{
|
||||||
#include <u.h>
|
package main
|
||||||
#include <stdio.h> /* if we don't, bison will, and a.h re-#defines getc */
|
|
||||||
#include <libc.h>
|
import (
|
||||||
#include "a.h"
|
"cmd/internal/asm"
|
||||||
#include "../../runtime/funcdata.h"
|
"cmd/internal/obj"
|
||||||
|
"cmd/internal/obj/x86"
|
||||||
|
)
|
||||||
%}
|
%}
|
||||||
%union {
|
|
||||||
Sym *sym;
|
%union {
|
||||||
vlong lval;
|
sym *asm.Sym
|
||||||
double dval;
|
lval int64
|
||||||
char sval[8];
|
dval float64
|
||||||
Addr addr;
|
sval string
|
||||||
Addr2 addr2;
|
addr obj.Addr
|
||||||
|
addr2 Addr2
|
||||||
}
|
}
|
||||||
|
|
||||||
%left '|'
|
%left '|'
|
||||||
%left '^'
|
%left '^'
|
||||||
%left '&'
|
%left '&'
|
||||||
|
|
@ -58,7 +62,7 @@
|
||||||
%token <sval> LSCONST LSP
|
%token <sval> LSCONST LSP
|
||||||
%token <sym> LNAME LLAB LVAR
|
%token <sym> LNAME LLAB LVAR
|
||||||
%type <lval> con expr pointer offset
|
%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> nonnon nonrel nonrem rimnon rimrem remrim
|
||||||
%type <addr2> spec3 spec4 spec5 spec6 spec7 spec8 spec9
|
%type <addr2> spec3 spec4 spec5 spec6 spec7 spec8 spec9
|
||||||
%type <addr2> spec10 spec12 spec13
|
%type <addr2> spec10 spec12 spec13
|
||||||
|
|
@ -66,18 +70,19 @@
|
||||||
prog:
|
prog:
|
||||||
| prog
|
| prog
|
||||||
{
|
{
|
||||||
stmtline = lineno;
|
stmtline = asm.Lineno;
|
||||||
}
|
}
|
||||||
line
|
line
|
||||||
|
|
||||||
line:
|
line:
|
||||||
LNAME ':'
|
LNAME ':'
|
||||||
{
|
{
|
||||||
$1 = labellookup($1);
|
$1 = asm.LabelLookup($1);
|
||||||
if($1->type == LLAB && $1->value != pc)
|
if $1.Type == LLAB && $1.Value != int64(asm.PC) {
|
||||||
yyerror("redeclaration of %s (%s)", $1->labelname, $1->name);
|
yyerror("redeclaration of %s (%s)", $1.Labelname, $1.Name);
|
||||||
$1->type = LLAB;
|
}
|
||||||
$1->value = pc;
|
$1.Type = LLAB;
|
||||||
|
$1.Value = int64(asm.PC)
|
||||||
}
|
}
|
||||||
line
|
line
|
||||||
| ';'
|
| ';'
|
||||||
|
|
@ -87,34 +92,35 @@ line:
|
||||||
inst:
|
inst:
|
||||||
LNAME '=' expr
|
LNAME '=' expr
|
||||||
{
|
{
|
||||||
$1->type = LVAR;
|
$1.Type = LVAR;
|
||||||
$1->value = $3;
|
$1.Value = $3;
|
||||||
}
|
}
|
||||||
| LVAR '=' expr
|
| LVAR '=' expr
|
||||||
{
|
{
|
||||||
if($1->value != $3)
|
if $1.Value != $3 {
|
||||||
yyerror("redeclaration of %s", $1->name);
|
yyerror("redeclaration of %s", $1.Name);
|
||||||
$1->value = $3;
|
}
|
||||||
|
$1.Value = $3;
|
||||||
}
|
}
|
||||||
| LTYPE0 nonnon { outcode($1, &$2); }
|
| LTYPE0 nonnon { outcode(int($1), &$2); }
|
||||||
| LTYPE1 nonrem { outcode($1, &$2); }
|
| LTYPE1 nonrem { outcode(int($1), &$2); }
|
||||||
| LTYPE2 rimnon { outcode($1, &$2); }
|
| LTYPE2 rimnon { outcode(int($1), &$2); }
|
||||||
| LTYPE3 rimrem { outcode($1, &$2); }
|
| LTYPE3 rimrem { outcode(int($1), &$2); }
|
||||||
| LTYPE4 remrim { outcode($1, &$2); }
|
| LTYPE4 remrim { outcode(int($1), &$2); }
|
||||||
| LTYPER nonrel { outcode($1, &$2); }
|
| LTYPER nonrel { outcode(int($1), &$2); }
|
||||||
| spec1
|
| spec1
|
||||||
| spec2
|
| spec2
|
||||||
| LTYPEC spec3 { outcode($1, &$2); }
|
| LTYPEC spec3 { outcode(int($1), &$2); }
|
||||||
| LTYPEN spec4 { outcode($1, &$2); }
|
| LTYPEN spec4 { outcode(int($1), &$2); }
|
||||||
| LTYPES spec5 { outcode($1, &$2); }
|
| LTYPES spec5 { outcode(int($1), &$2); }
|
||||||
| LTYPEM spec6 { outcode($1, &$2); }
|
| LTYPEM spec6 { outcode(int($1), &$2); }
|
||||||
| LTYPEI spec7 { outcode($1, &$2); }
|
| LTYPEI spec7 { outcode(int($1), &$2); }
|
||||||
| LTYPEXC spec8 { outcode($1, &$2); }
|
| LTYPEXC spec8 { outcode(int($1), &$2); }
|
||||||
| LTYPEX spec9 { outcode($1, &$2); }
|
| LTYPEX spec9 { outcode(int($1), &$2); }
|
||||||
| LTYPERT spec10 { outcode($1, &$2); }
|
| LTYPERT spec10 { outcode(int($1), &$2); }
|
||||||
| spec11
|
| spec11
|
||||||
| LTYPEPC spec12 { outcode($1, &$2); }
|
| LTYPEPC spec12 { outcode(int($1), &$2); }
|
||||||
| LTYPEF spec13 { outcode($1, &$2); }
|
| LTYPEF spec13 { outcode(int($1), &$2); }
|
||||||
|
|
||||||
nonnon:
|
nonnon:
|
||||||
{
|
{
|
||||||
|
|
@ -185,57 +191,45 @@ nonrel:
|
||||||
spec1: /* DATA */
|
spec1: /* DATA */
|
||||||
LTYPED nam '/' con ',' imm
|
LTYPED nam '/' con ',' imm
|
||||||
{
|
{
|
||||||
Addr2 a;
|
var a Addr2
|
||||||
a.from = $2;
|
a.from = $2
|
||||||
a.to = $6;
|
a.to = $6
|
||||||
outcode(ADATA, &a);
|
outcode(obj.ADATA, &a)
|
||||||
if(pass > 1) {
|
if asm.Pass > 1 {
|
||||||
lastpc->from3.type = TYPE_CONST;
|
lastpc.From3.Type = obj.TYPE_CONST
|
||||||
lastpc->from3.offset = $4;
|
lastpc.From3.Offset = $4
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spec2: /* TEXT */
|
spec2: /* TEXT */
|
||||||
LTYPET mem ',' '$' textsize
|
LTYPET mem ',' '$' textsize
|
||||||
{
|
{
|
||||||
Addr2 a;
|
asm.Settext($2.Sym);
|
||||||
settext($2.sym);
|
outcode(obj.ATEXT, &Addr2{$2, $5})
|
||||||
a.from = $2;
|
|
||||||
a.to = $5;
|
|
||||||
outcode(ATEXT, &a);
|
|
||||||
}
|
}
|
||||||
| LTYPET mem ',' con ',' '$' textsize
|
| LTYPET mem ',' con ',' '$' textsize
|
||||||
{
|
{
|
||||||
Addr2 a;
|
asm.Settext($2.Sym);
|
||||||
settext($2.sym);
|
outcode(obj.ATEXT, &Addr2{$2, $7})
|
||||||
a.from = $2;
|
if asm.Pass > 1 {
|
||||||
a.to = $7;
|
lastpc.From3.Type = obj.TYPE_CONST
|
||||||
outcode(ATEXT, &a);
|
lastpc.From3.Offset = $4
|
||||||
if(pass > 1) {
|
|
||||||
lastpc->from3.type = TYPE_CONST;
|
|
||||||
lastpc->from3.offset = $4;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spec11: /* GLOBL */
|
spec11: /* GLOBL */
|
||||||
LTYPEG mem ',' imm
|
LTYPEG mem ',' imm
|
||||||
{
|
{
|
||||||
Addr2 a;
|
asm.Settext($2.Sym)
|
||||||
settext($2.sym);
|
outcode(obj.AGLOBL, &Addr2{$2, $4})
|
||||||
a.from = $2;
|
|
||||||
a.to = $4;
|
|
||||||
outcode(AGLOBL, &a);
|
|
||||||
}
|
}
|
||||||
| LTYPEG mem ',' con ',' imm
|
| LTYPEG mem ',' con ',' imm
|
||||||
{
|
{
|
||||||
Addr2 a;
|
asm.Settext($2.Sym)
|
||||||
settext($2.sym);
|
outcode(obj.AGLOBL, &Addr2{$2, $6})
|
||||||
a.from = $2;
|
if asm.Pass > 1 {
|
||||||
a.to = $6;
|
lastpc.From3.Type = obj.TYPE_CONST
|
||||||
outcode(AGLOBL, &a);
|
lastpc.From3.Offset = $4
|
||||||
if(pass > 1) {
|
|
||||||
lastpc->from3.type = TYPE_CONST;
|
|
||||||
lastpc->from3.offset = $4;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -265,9 +259,10 @@ spec5: /* SHL/SHR */
|
||||||
{
|
{
|
||||||
$$.from = $1;
|
$$.from = $1;
|
||||||
$$.to = $3;
|
$$.to = $3;
|
||||||
if($$.from.index != TYPE_NONE)
|
if $$.from.Index != obj.TYPE_NONE {
|
||||||
yyerror("dp shift with lhs index");
|
yyerror("dp shift with lhs index");
|
||||||
$$.from.index = $5;
|
}
|
||||||
|
$$.from.Index = int16($5);
|
||||||
}
|
}
|
||||||
|
|
||||||
spec6: /* MOVW/MOVL */
|
spec6: /* MOVW/MOVL */
|
||||||
|
|
@ -280,9 +275,10 @@ spec6: /* MOVW/MOVL */
|
||||||
{
|
{
|
||||||
$$.from = $1;
|
$$.from = $1;
|
||||||
$$.to = $3;
|
$$.to = $3;
|
||||||
if($$.to.index != TYPE_NONE)
|
if $$.to.Index != obj.TYPE_NONE {
|
||||||
yyerror("dp move with lhs index");
|
yyerror("dp move with lhs index");
|
||||||
$$.to.index = $5;
|
}
|
||||||
|
$$.to.Index = int16($5);
|
||||||
}
|
}
|
||||||
|
|
||||||
spec7:
|
spec7:
|
||||||
|
|
@ -307,7 +303,7 @@ spec8: /* CMPPS/CMPPD */
|
||||||
{
|
{
|
||||||
$$.from = $1;
|
$$.from = $1;
|
||||||
$$.to = $3;
|
$$.to = $3;
|
||||||
$$.to.offset = $5;
|
$$.to.Offset = $5;
|
||||||
}
|
}
|
||||||
|
|
||||||
spec9: /* shufl */
|
spec9: /* shufl */
|
||||||
|
|
@ -315,9 +311,10 @@ spec9: /* shufl */
|
||||||
{
|
{
|
||||||
$$.from = $3;
|
$$.from = $3;
|
||||||
$$.to = $5;
|
$$.to = $5;
|
||||||
if($1.type != TYPE_CONST)
|
if $1.Type != obj.TYPE_CONST {
|
||||||
yyerror("illegal constant");
|
yyerror("illegal constant");
|
||||||
$$.to.offset = $1.offset;
|
}
|
||||||
|
$$.to.Offset = $1.Offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
spec10: /* RET/RETF */
|
spec10: /* RET/RETF */
|
||||||
|
|
@ -331,11 +328,12 @@ spec10: /* RET/RETF */
|
||||||
$$.to = nullgen;
|
$$.to = nullgen;
|
||||||
}
|
}
|
||||||
|
|
||||||
spec12: /* PCDATA */
|
spec12: /* asm.PCDATA */
|
||||||
rim ',' rim
|
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");
|
yyerror("arguments to asm.PCDATA must be integer constants");
|
||||||
|
}
|
||||||
$$.from = $1;
|
$$.from = $1;
|
||||||
$$.to = $3;
|
$$.to = $3;
|
||||||
}
|
}
|
||||||
|
|
@ -343,10 +341,12 @@ spec12: /* PCDATA */
|
||||||
spec13: /* FUNCDATA */
|
spec13: /* FUNCDATA */
|
||||||
rim ',' rim
|
rim ',' rim
|
||||||
{
|
{
|
||||||
if($1.type != TYPE_CONST)
|
if $1.Type != obj.TYPE_CONST {
|
||||||
yyerror("index for FUNCDATA must be integer constant");
|
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");
|
yyerror("value for FUNCDATA must be symbol reference");
|
||||||
|
}
|
||||||
$$.from = $1;
|
$$.from = $1;
|
||||||
$$.to = $3;
|
$$.to = $3;
|
||||||
}
|
}
|
||||||
|
|
@ -377,109 +377,110 @@ rel:
|
||||||
con '(' LPC ')'
|
con '(' LPC ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_BRANCH;
|
$$.Type = obj.TYPE_BRANCH;
|
||||||
$$.offset = $1 + pc;
|
$$.Offset = $1 + int64(asm.PC);
|
||||||
}
|
}
|
||||||
| LNAME offset
|
| LNAME offset
|
||||||
{
|
{
|
||||||
$1 = labellookup($1);
|
$1 = asm.LabelLookup($1);
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
if(pass == 2 && $1->type != LLAB)
|
if asm.Pass == 2 && $1.Type != LLAB {
|
||||||
yyerror("undefined label: %s", $1->labelname);
|
yyerror("undefined label: %s", $1.Labelname);
|
||||||
$$.type = TYPE_BRANCH;
|
}
|
||||||
$$.offset = $1->value + $2;
|
$$.Type = obj.TYPE_BRANCH;
|
||||||
|
$$.Offset = $1.Value + $2;
|
||||||
}
|
}
|
||||||
|
|
||||||
reg:
|
reg:
|
||||||
LBREG
|
LBREG
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_REG;
|
$$.Type = obj.TYPE_REG
|
||||||
$$.reg = $1;
|
$$.Reg = int16($1);
|
||||||
}
|
}
|
||||||
| LFREG
|
| LFREG
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_REG;
|
$$.Type = obj.TYPE_REG
|
||||||
$$.reg = $1;
|
$$.Reg = int16($1);
|
||||||
}
|
}
|
||||||
| LLREG
|
| LLREG
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_REG;
|
$$.Type = obj.TYPE_REG
|
||||||
$$.reg = $1;
|
$$.Reg = int16($1);
|
||||||
}
|
}
|
||||||
| LMREG
|
| LMREG
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_REG;
|
$$.Type = obj.TYPE_REG
|
||||||
$$.reg = $1;
|
$$.Reg = int16($1);
|
||||||
}
|
}
|
||||||
| LSP
|
| LSP
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_REG;
|
$$.Type = obj.TYPE_REG
|
||||||
$$.reg = REG_SP;
|
$$.Reg = x86.REG_SP;
|
||||||
}
|
}
|
||||||
| LSREG
|
| LSREG
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_REG;
|
$$.Type = obj.TYPE_REG
|
||||||
$$.reg = $1;
|
$$.Reg = int16($1);
|
||||||
}
|
}
|
||||||
| LXREG
|
| LXREG
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_REG;
|
$$.Type = obj.TYPE_REG
|
||||||
$$.reg = $1;
|
$$.Reg = int16($1);
|
||||||
}
|
}
|
||||||
|
|
||||||
imm:
|
imm:
|
||||||
'$' con
|
'$' con
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_CONST;
|
$$.Type = obj.TYPE_CONST;
|
||||||
$$.offset = $2;
|
$$.Offset = $2;
|
||||||
}
|
}
|
||||||
| '$' nam
|
| '$' nam
|
||||||
{
|
{
|
||||||
$$ = $2;
|
$$ = $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",
|
yyerror("constant cannot be automatic: %s",
|
||||||
$2.sym->name);
|
$2.sym.Name);
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
| '$' LSCONST
|
| '$' LSCONST
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_SCONST;
|
$$.Type = obj.TYPE_SCONST;
|
||||||
memcpy($$.u.sval, $2, sizeof($$.u.sval));
|
$$.U.Sval = ($2+"\x00\x00\x00\x00\x00\x00\x00\x00")[:8]
|
||||||
}
|
}
|
||||||
| '$' LFCONST
|
| '$' LFCONST
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_FCONST;
|
$$.Type = obj.TYPE_FCONST;
|
||||||
$$.u.dval = $2;
|
$$.U.Dval = $2;
|
||||||
}
|
}
|
||||||
| '$' '(' LFCONST ')'
|
| '$' '(' LFCONST ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_FCONST;
|
$$.Type = obj.TYPE_FCONST;
|
||||||
$$.u.dval = $3;
|
$$.U.Dval = $3;
|
||||||
}
|
}
|
||||||
| '$' '(' '-' LFCONST ')'
|
| '$' '(' '-' LFCONST ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_FCONST;
|
$$.Type = obj.TYPE_FCONST;
|
||||||
$$.u.dval = -$4;
|
$$.U.Dval = -$4;
|
||||||
}
|
}
|
||||||
| '$' '-' LFCONST
|
| '$' '-' LFCONST
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_FCONST;
|
$$.Type = obj.TYPE_FCONST;
|
||||||
$$.u.dval = -$3;
|
$$.U.Dval = -$3;
|
||||||
}
|
}
|
||||||
|
|
||||||
mem:
|
mem:
|
||||||
|
|
@ -490,87 +491,87 @@ omem:
|
||||||
con
|
con
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.offset = $1;
|
$$.Offset = $1;
|
||||||
}
|
}
|
||||||
| con '(' LLREG ')'
|
| con '(' LLREG ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.reg = $3;
|
$$.Reg = int16($3)
|
||||||
$$.offset = $1;
|
$$.Offset = $1;
|
||||||
}
|
}
|
||||||
| con '(' LSP ')'
|
| con '(' LSP ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.reg = REG_SP;
|
$$.Reg = x86.REG_SP
|
||||||
$$.offset = $1;
|
$$.Offset = $1;
|
||||||
}
|
}
|
||||||
| con '(' LSREG ')'
|
| con '(' LSREG ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.reg = $3;
|
$$.Reg = int16($3)
|
||||||
$$.offset = $1;
|
$$.Offset = $1;
|
||||||
}
|
}
|
||||||
| con '(' LLREG '*' con ')'
|
| con '(' LLREG '*' con ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.offset = $1;
|
$$.Offset = $1;
|
||||||
$$.index = $3;
|
$$.Index = int16($3);
|
||||||
$$.scale = $5;
|
$$.Scale = int8($5);
|
||||||
checkscale($$.scale);
|
checkscale($$.Scale);
|
||||||
}
|
}
|
||||||
| con '(' LLREG ')' '(' LLREG '*' con ')'
|
| con '(' LLREG ')' '(' LLREG '*' con ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.reg = $3;
|
$$.Reg = int16($3)
|
||||||
$$.offset = $1;
|
$$.Offset = $1;
|
||||||
$$.index = $6;
|
$$.Index = int16($6);
|
||||||
$$.scale = $8;
|
$$.Scale = int8($8);
|
||||||
checkscale($$.scale);
|
checkscale($$.Scale);
|
||||||
}
|
}
|
||||||
| con '(' LLREG ')' '(' LSREG '*' con ')'
|
| con '(' LLREG ')' '(' LSREG '*' con ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.reg = $3;
|
$$.Reg = int16($3)
|
||||||
$$.offset = $1;
|
$$.Offset = $1;
|
||||||
$$.index = $6;
|
$$.Index = int16($6);
|
||||||
$$.scale = $8;
|
$$.Scale = int8($8);
|
||||||
checkscale($$.scale);
|
checkscale($$.Scale);
|
||||||
}
|
}
|
||||||
| '(' LLREG ')'
|
| '(' LLREG ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.reg = $2;
|
$$.Reg = int16($2)
|
||||||
}
|
}
|
||||||
| '(' LSP ')'
|
| '(' LSP ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.reg = REG_SP;
|
$$.Reg = x86.REG_SP
|
||||||
}
|
}
|
||||||
| '(' LLREG '*' con ')'
|
| '(' LLREG '*' con ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.index = $2;
|
$$.Index = int16($2);
|
||||||
$$.scale = $4;
|
$$.Scale = int8($4);
|
||||||
checkscale($$.scale);
|
checkscale($$.Scale);
|
||||||
}
|
}
|
||||||
| '(' LLREG ')' '(' LLREG '*' con ')'
|
| '(' LLREG ')' '(' LLREG '*' con ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.reg = $2;
|
$$.Reg = int16($2)
|
||||||
$$.index = $5;
|
$$.Index = int16($5);
|
||||||
$$.scale = $7;
|
$$.Scale = int8($7);
|
||||||
checkscale($$.scale);
|
checkscale($$.Scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
nmem:
|
nmem:
|
||||||
|
|
@ -581,27 +582,27 @@ nmem:
|
||||||
| nam '(' LLREG '*' con ')'
|
| nam '(' LLREG '*' con ')'
|
||||||
{
|
{
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
$$.index = $3;
|
$$.Index = int16($3);
|
||||||
$$.scale = $5;
|
$$.Scale = int8($5);
|
||||||
checkscale($$.scale);
|
checkscale($$.Scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
nam:
|
nam:
|
||||||
LNAME offset '(' pointer ')'
|
LNAME offset '(' pointer ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.name = $4;
|
$$.Name = int8($4)
|
||||||
$$.sym = linklookup(ctxt, $1->name, 0);
|
$$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
|
||||||
$$.offset = $2;
|
$$.Offset = $2;
|
||||||
}
|
}
|
||||||
| LNAME '<' '>' offset '(' LSB ')'
|
| LNAME '<' '>' offset '(' LSB ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.name = NAME_STATIC;
|
$$.Name = obj.NAME_STATIC
|
||||||
$$.sym = linklookup(ctxt, $1->name, 1);
|
$$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 1);
|
||||||
$$.offset = $4;
|
$$.Offset = $4;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset:
|
offset:
|
||||||
|
|
@ -621,7 +622,7 @@ pointer:
|
||||||
LSB
|
LSB
|
||||||
| LSP
|
| LSP
|
||||||
{
|
{
|
||||||
$$ = NAME_AUTO;
|
$$ = obj.NAME_AUTO;
|
||||||
}
|
}
|
||||||
| LFP
|
| LFP
|
||||||
|
|
||||||
|
|
@ -629,7 +630,7 @@ con:
|
||||||
LCONST
|
LCONST
|
||||||
| LVAR
|
| LVAR
|
||||||
{
|
{
|
||||||
$$ = $1->value;
|
$$ = $1.Value;
|
||||||
}
|
}
|
||||||
| '-' con
|
| '-' con
|
||||||
{
|
{
|
||||||
|
|
@ -641,7 +642,7 @@ con:
|
||||||
}
|
}
|
||||||
| '~' con
|
| '~' con
|
||||||
{
|
{
|
||||||
$$ = ~$2;
|
$$ = ^$2;
|
||||||
}
|
}
|
||||||
| '(' expr ')'
|
| '(' expr ')'
|
||||||
{
|
{
|
||||||
|
|
@ -652,30 +653,30 @@ textsize:
|
||||||
LCONST
|
LCONST
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_TEXTSIZE;
|
$$.Type = obj.TYPE_TEXTSIZE;
|
||||||
$$.offset = $1;
|
$$.Offset = $1;
|
||||||
$$.u.argsize = ArgsSizeUnknown;
|
$$.U.Argsize = obj.ArgsSizeUnknown;
|
||||||
}
|
}
|
||||||
| '-' LCONST
|
| '-' LCONST
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_TEXTSIZE;
|
$$.Type = obj.TYPE_TEXTSIZE;
|
||||||
$$.offset = -$2;
|
$$.Offset = -$2;
|
||||||
$$.u.argsize = ArgsSizeUnknown;
|
$$.U.Argsize = obj.ArgsSizeUnknown;
|
||||||
}
|
}
|
||||||
| LCONST '-' LCONST
|
| LCONST '-' LCONST
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_TEXTSIZE;
|
$$.Type = obj.TYPE_TEXTSIZE;
|
||||||
$$.offset = $1;
|
$$.Offset = $1;
|
||||||
$$.u.argsize = $3;
|
$$.U.Argsize = int32($3);
|
||||||
}
|
}
|
||||||
| '-' LCONST '-' LCONST
|
| '-' LCONST '-' LCONST
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_TEXTSIZE;
|
$$.Type = obj.TYPE_TEXTSIZE;
|
||||||
$$.offset = -$2;
|
$$.Offset = -$2;
|
||||||
$$.u.argsize = $4;
|
$$.U.Argsize = int32($4);
|
||||||
}
|
}
|
||||||
|
|
||||||
expr:
|
expr:
|
||||||
|
|
@ -702,11 +703,11 @@ expr:
|
||||||
}
|
}
|
||||||
| expr '<' '<' expr
|
| expr '<' '<' expr
|
||||||
{
|
{
|
||||||
$$ = $1 << $4;
|
$$ = $1 << uint($4);
|
||||||
}
|
}
|
||||||
| expr '>' '>' expr
|
| expr '>' '>' expr
|
||||||
{
|
{
|
||||||
$$ = $1 >> $4;
|
$$ = $1 >> uint($4);
|
||||||
}
|
}
|
||||||
| expr '&' expr
|
| expr '&' expr
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
1137
src/cmd/6a/lex.c
1137
src/cmd/6a/lex.c
File diff suppressed because it is too large
Load diff
2800
src/cmd/6a/y.tab.c
2800
src/cmd/6a/y.tab.c
File diff suppressed because it is too large
Load diff
|
|
@ -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;
|
|
||||||
|
|
||||||
|
|
@ -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
|
|
||||||
1745
src/cmd/6g/cgen.c
1745
src/cmd/6g/cgen.c
File diff suppressed because it is too large
Load diff
|
|
@ -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
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
176
src/cmd/6g/gg.h
176
src/cmd/6g/gg.h
|
|
@ -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*);
|
|
||||||
1046
src/cmd/6g/ggen.c
1046
src/cmd/6g/ggen.c
File diff suppressed because it is too large
Load diff
1737
src/cmd/6g/gsubr.c
1737
src/cmd/6g/gsubr.c
File diff suppressed because it is too large
Load diff
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
153
src/cmd/6g/reg.c
153
src/cmd/6g/reg.c
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
||||||
186
src/cmd/8a/a.h
186
src/cmd/8a/a.h
|
|
@ -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*);
|
|
||||||
379
src/cmd/8a/a.y
379
src/cmd/8a/a.y
|
|
@ -29,20 +29,28 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
%{
|
%{
|
||||||
#include <u.h>
|
package main
|
||||||
#include <stdio.h> /* if we don't, bison will, and a.h re-#defines getc */
|
|
||||||
#include <libc.h>
|
import (
|
||||||
#include "a.h"
|
"cmd/internal/asm"
|
||||||
#include "../../runtime/funcdata.h"
|
"cmd/internal/obj"
|
||||||
|
. "cmd/internal/obj/i386"
|
||||||
|
)
|
||||||
%}
|
%}
|
||||||
%union {
|
|
||||||
Sym *sym;
|
%union {
|
||||||
int32 lval;
|
sym *asm.Sym
|
||||||
double dval;
|
lval int64
|
||||||
char sval[8];
|
con2 struct {
|
||||||
Addr addr;
|
v1 int32
|
||||||
Addr2 addr2;
|
v2 int32
|
||||||
|
}
|
||||||
|
dval float64
|
||||||
|
sval string
|
||||||
|
addr obj.Addr
|
||||||
|
addr2 Addr2
|
||||||
}
|
}
|
||||||
|
|
||||||
%left '|'
|
%left '|'
|
||||||
%left '^'
|
%left '^'
|
||||||
%left '&'
|
%left '&'
|
||||||
|
|
@ -64,18 +72,19 @@
|
||||||
prog:
|
prog:
|
||||||
| prog
|
| prog
|
||||||
{
|
{
|
||||||
stmtline = lineno;
|
stmtline = asm.Lineno;
|
||||||
}
|
}
|
||||||
line
|
line
|
||||||
|
|
||||||
line:
|
line:
|
||||||
LNAME ':'
|
LNAME ':'
|
||||||
{
|
{
|
||||||
$1 = labellookup($1);
|
$1 = asm.LabelLookup($1);
|
||||||
if($1->type == LLAB && $1->value != pc)
|
if $1.Type == LLAB && $1.Value != int64(asm.PC) {
|
||||||
yyerror("redeclaration of %s", $1->labelname);
|
yyerror("redeclaration of %s", $1.Labelname)
|
||||||
$1->type = LLAB;
|
}
|
||||||
$1->value = pc;
|
$1.Type = LLAB;
|
||||||
|
$1.Value = int64(asm.PC)
|
||||||
}
|
}
|
||||||
line
|
line
|
||||||
| ';'
|
| ';'
|
||||||
|
|
@ -85,33 +94,34 @@ line:
|
||||||
inst:
|
inst:
|
||||||
LNAME '=' expr
|
LNAME '=' expr
|
||||||
{
|
{
|
||||||
$1->type = LVAR;
|
$1.Type = LVAR;
|
||||||
$1->value = $3;
|
$1.Value = $3;
|
||||||
}
|
}
|
||||||
| LVAR '=' expr
|
| LVAR '=' expr
|
||||||
{
|
{
|
||||||
if($1->value != $3)
|
if $1.Value != int64($3) {
|
||||||
yyerror("redeclaration of %s", $1->name);
|
yyerror("redeclaration of %s", $1.Name);
|
||||||
$1->value = $3;
|
}
|
||||||
|
$1.Value = $3;
|
||||||
}
|
}
|
||||||
| LTYPE0 nonnon { outcode($1, &$2); }
|
| LTYPE0 nonnon { outcode(int($1), &$2); }
|
||||||
| LTYPE1 nonrem { outcode($1, &$2); }
|
| LTYPE1 nonrem { outcode(int($1), &$2); }
|
||||||
| LTYPE2 rimnon { outcode($1, &$2); }
|
| LTYPE2 rimnon { outcode(int($1), &$2); }
|
||||||
| LTYPE3 rimrem { outcode($1, &$2); }
|
| LTYPE3 rimrem { outcode(int($1), &$2); }
|
||||||
| LTYPE4 remrim { outcode($1, &$2); }
|
| LTYPE4 remrim { outcode(int($1), &$2); }
|
||||||
| LTYPER nonrel { outcode($1, &$2); }
|
| LTYPER nonrel { outcode(int($1), &$2); }
|
||||||
| spec1
|
| spec1
|
||||||
| spec2
|
| spec2
|
||||||
| LTYPEC spec3 { outcode($1, &$2); }
|
| LTYPEC spec3 { outcode(int($1), &$2); }
|
||||||
| LTYPEN spec4 { outcode($1, &$2); }
|
| LTYPEN spec4 { outcode(int($1), &$2); }
|
||||||
| LTYPES spec5 { outcode($1, &$2); }
|
| LTYPES spec5 { outcode(int($1), &$2); }
|
||||||
| LTYPEM spec6 { outcode($1, &$2); }
|
| LTYPEM spec6 { outcode(int($1), &$2); }
|
||||||
| LTYPEI spec7 { outcode($1, &$2); }
|
| LTYPEI spec7 { outcode(int($1), &$2); }
|
||||||
| spec8
|
| spec8
|
||||||
| LTYPEXC spec9 { outcode($1, &$2); }
|
| LTYPEXC spec9 { outcode(int($1), &$2); }
|
||||||
| LTYPEX spec10 { outcode($1, &$2); }
|
| LTYPEX spec10 { outcode(int($1), &$2); }
|
||||||
| LTYPEPC spec11 { outcode($1, &$2); }
|
| LTYPEPC spec11 { outcode(int($1), &$2); }
|
||||||
| LTYPEF spec12 { outcode($1, &$2); }
|
| LTYPEF spec12 { outcode(int($1), &$2); }
|
||||||
|
|
||||||
nonnon:
|
nonnon:
|
||||||
{
|
{
|
||||||
|
|
@ -182,60 +192,46 @@ nonrel:
|
||||||
spec1: /* DATA */
|
spec1: /* DATA */
|
||||||
LTYPED nam '/' con ',' imm
|
LTYPED nam '/' con ',' imm
|
||||||
{
|
{
|
||||||
Addr2 a;
|
outcode(obj.ADATA, &Addr2{$2, $6})
|
||||||
a.from = $2;
|
if asm.Pass > 1 {
|
||||||
a.to = $6;
|
lastpc.From3.Type = obj.TYPE_CONST
|
||||||
outcode(ADATA, &a);
|
lastpc.From3.Offset = $4
|
||||||
if(pass > 1) {
|
|
||||||
lastpc->from3.type = TYPE_CONST;
|
|
||||||
lastpc->from3.offset = $4;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spec2: /* TEXT */
|
spec2: /* TEXT */
|
||||||
LTYPET mem ',' '$' textsize
|
LTYPET mem ',' '$' textsize
|
||||||
{
|
{
|
||||||
Addr2 a;
|
asm.Settext($2.Sym);
|
||||||
settext($2.sym);
|
outcode(obj.ATEXT, &Addr2{$2, $5})
|
||||||
a.from = $2;
|
|
||||||
a.to = $5;
|
|
||||||
outcode(ATEXT, &a);
|
|
||||||
}
|
}
|
||||||
| LTYPET mem ',' con ',' '$' textsize
|
| LTYPET mem ',' con ',' '$' textsize
|
||||||
{
|
{
|
||||||
Addr2 a;
|
asm.Settext($2.Sym);
|
||||||
settext($2.sym);
|
outcode(obj.ATEXT, &Addr2{$2, $7})
|
||||||
a.from = $2;
|
if asm.Pass > 1 {
|
||||||
a.to = $7;
|
lastpc.From3.Type = obj.TYPE_CONST
|
||||||
outcode(ATEXT, &a);
|
lastpc.From3.Offset = $4
|
||||||
if(pass > 1) {
|
|
||||||
lastpc->from3.type = TYPE_CONST;
|
|
||||||
lastpc->from3.offset = $4;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spec8: /* GLOBL */
|
spec8: /* GLOBL */
|
||||||
LTYPEG mem ',' imm
|
LTYPEG mem ',' imm
|
||||||
{
|
{
|
||||||
Addr2 a;
|
asm.Settext($2.Sym);
|
||||||
settext($2.sym);
|
outcode(obj.AGLOBL, &Addr2{$2, $4})
|
||||||
a.from = $2;
|
|
||||||
a.to = $4;
|
|
||||||
outcode(AGLOBL, &a);
|
|
||||||
}
|
}
|
||||||
| LTYPEG mem ',' con ',' imm
|
| LTYPEG mem ',' con ',' imm
|
||||||
{
|
{
|
||||||
Addr2 a;
|
asm.Settext($2.Sym);
|
||||||
settext($2.sym);
|
outcode(obj.AGLOBL, &Addr2{$2, $6})
|
||||||
a.from = $2;
|
if asm.Pass > 1 {
|
||||||
a.to = $6;
|
lastpc.From3.Type = obj.TYPE_CONST
|
||||||
outcode(AGLOBL, &a);
|
lastpc.From3.Offset = $4
|
||||||
if(pass > 1) {
|
|
||||||
lastpc->from3.type = TYPE_CONST;
|
|
||||||
lastpc->from3.offset = $4;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
spec3: /* JMP/CALL */
|
spec3: /* JMP/CALL */
|
||||||
',' rom
|
',' rom
|
||||||
{
|
{
|
||||||
|
|
@ -251,7 +247,7 @@ spec3: /* JMP/CALL */
|
||||||
{
|
{
|
||||||
$$.from = nullgen;
|
$$.from = nullgen;
|
||||||
$$.to = $2;
|
$$.to = $2;
|
||||||
$$.to.type = TYPE_INDIR;
|
$$.to.Type = obj.TYPE_INDIR
|
||||||
}
|
}
|
||||||
|
|
||||||
spec4: /* NOP */
|
spec4: /* NOP */
|
||||||
|
|
@ -268,9 +264,10 @@ spec5: /* SHL/SHR */
|
||||||
{
|
{
|
||||||
$$.from = $1;
|
$$.from = $1;
|
||||||
$$.to = $3;
|
$$.to = $3;
|
||||||
if($$.from.index != TYPE_NONE)
|
if $$.from.Index != obj.TYPE_NONE {
|
||||||
yyerror("dp shift with lhs index");
|
yyerror("dp shift with lhs index");
|
||||||
$$.from.index = $5;
|
}
|
||||||
|
$$.from.Index = int16($5);
|
||||||
}
|
}
|
||||||
|
|
||||||
spec6: /* MOVW/MOVL */
|
spec6: /* MOVW/MOVL */
|
||||||
|
|
@ -283,9 +280,10 @@ spec6: /* MOVW/MOVL */
|
||||||
{
|
{
|
||||||
$$.from = $1;
|
$$.from = $1;
|
||||||
$$.to = $3;
|
$$.to = $3;
|
||||||
if($$.to.index != TYPE_NONE)
|
if $$.to.Index != obj.TYPE_NONE {
|
||||||
yyerror("dp move with lhs index");
|
yyerror("dp move with lhs index");
|
||||||
$$.to.index = $5;
|
}
|
||||||
|
$$.to.Index = int16($5);
|
||||||
}
|
}
|
||||||
|
|
||||||
spec7:
|
spec7:
|
||||||
|
|
@ -310,7 +308,7 @@ spec9: /* CMPPS/CMPPD */
|
||||||
{
|
{
|
||||||
$$.from = $1;
|
$$.from = $1;
|
||||||
$$.to = $3;
|
$$.to = $3;
|
||||||
$$.to.offset = $5;
|
$$.to.Offset = $5;
|
||||||
}
|
}
|
||||||
|
|
||||||
spec10: /* PINSRD */
|
spec10: /* PINSRD */
|
||||||
|
|
@ -318,16 +316,18 @@ spec10: /* PINSRD */
|
||||||
{
|
{
|
||||||
$$.from = $3;
|
$$.from = $3;
|
||||||
$$.to = $5;
|
$$.to = $5;
|
||||||
if($1.type != TYPE_CONST)
|
if $1.Type != obj.TYPE_CONST {
|
||||||
yyerror("illegal constant");
|
yyerror("illegal constant")
|
||||||
$$.to.offset = $1.offset;
|
}
|
||||||
|
$$.to.Offset = $1.Offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
spec11: /* PCDATA */
|
spec11: /* PCDATA */
|
||||||
rim ',' rim
|
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");
|
yyerror("arguments to PCDATA must be integer constants");
|
||||||
|
}
|
||||||
$$.from = $1;
|
$$.from = $1;
|
||||||
$$.to = $3;
|
$$.to = $3;
|
||||||
}
|
}
|
||||||
|
|
@ -335,10 +335,12 @@ spec11: /* PCDATA */
|
||||||
spec12: /* FUNCDATA */
|
spec12: /* FUNCDATA */
|
||||||
rim ',' rim
|
rim ',' rim
|
||||||
{
|
{
|
||||||
if($1.type != TYPE_CONST)
|
if $1.Type != obj.TYPE_CONST {
|
||||||
yyerror("index for FUNCDATA must be integer constant");
|
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");
|
yyerror("value for FUNCDATA must be symbol reference");
|
||||||
|
}
|
||||||
$$.from = $1;
|
$$.from = $1;
|
||||||
$$.to = $3;
|
$$.to = $3;
|
||||||
}
|
}
|
||||||
|
|
@ -370,135 +372,137 @@ rel:
|
||||||
con '(' LPC ')'
|
con '(' LPC ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_BRANCH;
|
$$.Type = obj.TYPE_BRANCH;
|
||||||
$$.offset = $1 + pc;
|
$$.Offset = $1 + int64(asm.PC);
|
||||||
}
|
}
|
||||||
| LNAME offset
|
| LNAME offset
|
||||||
{
|
{
|
||||||
$1 = labellookup($1);
|
$1 = asm.LabelLookup($1);
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
if(pass == 2 && $1->type != LLAB)
|
if asm.Pass == 2 && $1.Type != LLAB {
|
||||||
yyerror("undefined label: %s", $1->labelname);
|
yyerror("undefined label: %s", $1.Labelname);
|
||||||
$$.type = TYPE_BRANCH;
|
}
|
||||||
$$.offset = $1->value + $2;
|
$$.Type = obj.TYPE_BRANCH;
|
||||||
|
$$.Offset = $1.Value + $2;
|
||||||
}
|
}
|
||||||
|
|
||||||
reg:
|
reg:
|
||||||
LBREG
|
LBREG
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_REG;
|
$$.Type = obj.TYPE_REG
|
||||||
$$.reg = $1;
|
$$.Reg = int16($1);
|
||||||
}
|
}
|
||||||
| LFREG
|
| LFREG
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_REG;
|
$$.Type = obj.TYPE_REG
|
||||||
$$.reg = $1;
|
$$.Reg = int16($1);
|
||||||
}
|
}
|
||||||
| LLREG
|
| LLREG
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_REG;
|
$$.Type = obj.TYPE_REG
|
||||||
$$.reg = $1;
|
$$.Reg = int16($1);
|
||||||
}
|
}
|
||||||
| LXREG
|
| LXREG
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_REG;
|
$$.Type = obj.TYPE_REG
|
||||||
$$.reg = $1;
|
$$.Reg = int16($1);
|
||||||
}
|
}
|
||||||
| LSP
|
| LSP
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_REG;
|
$$.Type = obj.TYPE_REG
|
||||||
$$.reg = REG_SP;
|
$$.Reg = REG_SP;
|
||||||
}
|
}
|
||||||
| LSREG
|
| LSREG
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_REG;
|
$$.Type = obj.TYPE_REG
|
||||||
$$.reg = $1;
|
$$.Reg = int16($1);
|
||||||
}
|
}
|
||||||
|
|
||||||
imm:
|
imm:
|
||||||
'$' con
|
'$' con
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_CONST;
|
$$.Type = obj.TYPE_CONST;
|
||||||
$$.offset = $2;
|
$$.Offset = $2;
|
||||||
}
|
}
|
||||||
| '$' nam
|
| '$' nam
|
||||||
{
|
{
|
||||||
$$ = $2;
|
$$ = $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",
|
yyerror("constant cannot be automatic: %s",
|
||||||
$2.sym->name);
|
$2.Sym.name);
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
| '$' LSCONST
|
| '$' LSCONST
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_SCONST;
|
$$.Type = obj.TYPE_SCONST;
|
||||||
memcpy($$.u.sval, $2, sizeof($$.u.sval));
|
$$.U.Sval = $2
|
||||||
}
|
}
|
||||||
| '$' LFCONST
|
| '$' LFCONST
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_FCONST;
|
$$.Type = obj.TYPE_FCONST;
|
||||||
$$.u.dval = $2;
|
$$.U.Dval = $2;
|
||||||
}
|
}
|
||||||
| '$' '(' LFCONST ')'
|
| '$' '(' LFCONST ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_FCONST;
|
$$.Type = obj.TYPE_FCONST;
|
||||||
$$.u.dval = $3;
|
$$.U.Dval = $3;
|
||||||
}
|
}
|
||||||
| '$' '(' '-' LFCONST ')'
|
| '$' '(' '-' LFCONST ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_FCONST;
|
$$.Type = obj.TYPE_FCONST;
|
||||||
$$.u.dval = -$4;
|
$$.U.Dval = -$4;
|
||||||
}
|
}
|
||||||
| '$' '-' LFCONST
|
| '$' '-' LFCONST
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_FCONST;
|
$$.Type = obj.TYPE_FCONST;
|
||||||
$$.u.dval = -$3;
|
$$.U.Dval = -$3;
|
||||||
}
|
}
|
||||||
|
|
||||||
textsize:
|
textsize:
|
||||||
LCONST
|
LCONST
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_TEXTSIZE;
|
$$.Type = obj.TYPE_TEXTSIZE;
|
||||||
$$.offset = $1;
|
$$.Offset = $1;
|
||||||
$$.u.argsize = ArgsSizeUnknown;
|
$$.U.Argsize = obj.ArgsSizeUnknown;
|
||||||
}
|
}
|
||||||
| '-' LCONST
|
| '-' LCONST
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_TEXTSIZE;
|
$$.Type = obj.TYPE_TEXTSIZE;
|
||||||
$$.offset = -$2;
|
$$.Offset = -$2;
|
||||||
$$.u.argsize = ArgsSizeUnknown;
|
$$.U.Argsize = obj.ArgsSizeUnknown;
|
||||||
}
|
}
|
||||||
| LCONST '-' LCONST
|
| LCONST '-' LCONST
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_TEXTSIZE;
|
$$.Type = obj.TYPE_TEXTSIZE;
|
||||||
$$.offset = $1;
|
$$.Offset = $1;
|
||||||
$$.u.argsize = $3;
|
$$.U.Argsize = int32($3);
|
||||||
}
|
}
|
||||||
| '-' LCONST '-' LCONST
|
| '-' LCONST '-' LCONST
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_TEXTSIZE;
|
$$.Type = obj.TYPE_TEXTSIZE;
|
||||||
$$.offset = -$2;
|
$$.Offset = -$2;
|
||||||
$$.u.argsize = $4;
|
$$.U.Argsize = int32($4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mem:
|
mem:
|
||||||
omem
|
omem
|
||||||
| nmem
|
| nmem
|
||||||
|
|
@ -507,90 +511,87 @@ omem:
|
||||||
con
|
con
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.reg = REG_NONE;
|
$$.Offset = $1;
|
||||||
$$.offset = $1;
|
|
||||||
}
|
}
|
||||||
| con '(' LLREG ')'
|
| con '(' LLREG ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.reg = $3;
|
$$.Reg = int16($3)
|
||||||
$$.offset = $1;
|
$$.Offset = $1;
|
||||||
}
|
}
|
||||||
| con '(' LSP ')'
|
| con '(' LSP ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.reg = REG_SP;
|
$$.Reg = REG_SP
|
||||||
$$.offset = $1;
|
$$.Offset = $1;
|
||||||
}
|
}
|
||||||
| con '(' LLREG '*' con ')'
|
| con '(' LLREG '*' con ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.reg = REG_NONE;
|
$$.Offset = $1;
|
||||||
$$.offset = $1;
|
$$.Index = int16($3);
|
||||||
$$.index = $3;
|
$$.Scale = int8($5);
|
||||||
$$.scale = $5;
|
checkscale($$.Scale);
|
||||||
checkscale($$.scale);
|
|
||||||
}
|
}
|
||||||
| con '(' LLREG ')' '(' LLREG '*' con ')'
|
| con '(' LLREG ')' '(' LLREG '*' con ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.reg = $3;
|
$$.Reg = int16($3)
|
||||||
$$.offset = $1;
|
$$.Offset = $1;
|
||||||
$$.index = $6;
|
$$.Index = int16($6);
|
||||||
$$.scale = $8;
|
$$.Scale = int8($8);
|
||||||
checkscale($$.scale);
|
checkscale($$.Scale);
|
||||||
}
|
}
|
||||||
| con '(' LLREG ')' '(' LSREG '*' con ')'
|
| con '(' LLREG ')' '(' LSREG '*' con ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.reg = $3;
|
$$.Reg = int16($3)
|
||||||
$$.offset = $1;
|
$$.Offset = $1;
|
||||||
$$.index = $6;
|
$$.Index = int16($6);
|
||||||
$$.scale = $8;
|
$$.Scale = int8($8);
|
||||||
checkscale($$.scale);
|
checkscale($$.Scale);
|
||||||
}
|
}
|
||||||
| '(' LLREG ')'
|
| '(' LLREG ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.reg = $2;
|
$$.Reg = int16($2);
|
||||||
}
|
}
|
||||||
| '(' LSP ')'
|
| '(' LSP ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.reg = REG_SP;
|
$$.Reg = REG_SP
|
||||||
}
|
}
|
||||||
| con '(' LSREG ')'
|
| con '(' LSREG ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.reg = $3;
|
$$.Reg = int16($3)
|
||||||
$$.offset = $1;
|
$$.Offset = $1;
|
||||||
}
|
}
|
||||||
| '(' LLREG '*' con ')'
|
| '(' LLREG '*' con ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.reg = REG_NONE;
|
$$.Index = int16($2);
|
||||||
$$.index = $2;
|
$$.Scale = int8($4);
|
||||||
$$.scale = $4;
|
checkscale($$.Scale);
|
||||||
checkscale($$.scale);
|
|
||||||
}
|
}
|
||||||
| '(' LLREG ')' '(' LLREG '*' con ')'
|
| '(' LLREG ')' '(' LLREG '*' con ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.reg = $2;
|
$$.Reg = int16($2)
|
||||||
$$.index = $5;
|
$$.Index = int16($5);
|
||||||
$$.scale = $7;
|
$$.Scale = int8($7);
|
||||||
checkscale($$.scale);
|
checkscale($$.Scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
nmem:
|
nmem:
|
||||||
|
|
@ -601,27 +602,27 @@ nmem:
|
||||||
| nam '(' LLREG '*' con ')'
|
| nam '(' LLREG '*' con ')'
|
||||||
{
|
{
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
$$.index = $3;
|
$$.Index = int16($3);
|
||||||
$$.scale = $5;
|
$$.Scale = int8($5);
|
||||||
checkscale($$.scale);
|
checkscale($$.Scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
nam:
|
nam:
|
||||||
LNAME offset '(' pointer ')'
|
LNAME offset '(' pointer ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.name = $4;
|
$$.Name = int8($4);
|
||||||
$$.sym = linklookup(ctxt, $1->name, 0);
|
$$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
|
||||||
$$.offset = $2;
|
$$.Offset = $2;
|
||||||
}
|
}
|
||||||
| LNAME '<' '>' offset '(' LSB ')'
|
| LNAME '<' '>' offset '(' LSB ')'
|
||||||
{
|
{
|
||||||
$$ = nullgen;
|
$$ = nullgen;
|
||||||
$$.type = TYPE_MEM;
|
$$.Type = obj.TYPE_MEM
|
||||||
$$.name = NAME_STATIC;
|
$$.Name = obj.NAME_STATIC
|
||||||
$$.sym = linklookup(ctxt, $1->name, 1);
|
$$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 1);
|
||||||
$$.offset = $4;
|
$$.Offset = $4;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset:
|
offset:
|
||||||
|
|
@ -641,7 +642,7 @@ pointer:
|
||||||
LSB
|
LSB
|
||||||
| LSP
|
| LSP
|
||||||
{
|
{
|
||||||
$$ = NAME_AUTO;
|
$$ = obj.NAME_AUTO;
|
||||||
}
|
}
|
||||||
| LFP
|
| LFP
|
||||||
|
|
||||||
|
|
@ -649,7 +650,7 @@ con:
|
||||||
LCONST
|
LCONST
|
||||||
| LVAR
|
| LVAR
|
||||||
{
|
{
|
||||||
$$ = $1->value;
|
$$ = $1.Value;
|
||||||
}
|
}
|
||||||
| '-' con
|
| '-' con
|
||||||
{
|
{
|
||||||
|
|
@ -661,7 +662,7 @@ con:
|
||||||
}
|
}
|
||||||
| '~' con
|
| '~' con
|
||||||
{
|
{
|
||||||
$$ = ~$2;
|
$$ = ^$2;
|
||||||
}
|
}
|
||||||
| '(' expr ')'
|
| '(' expr ')'
|
||||||
{
|
{
|
||||||
|
|
@ -692,11 +693,11 @@ expr:
|
||||||
}
|
}
|
||||||
| expr '<' '<' expr
|
| expr '<' '<' expr
|
||||||
{
|
{
|
||||||
$$ = $1 << $4;
|
$$ = $1 << uint($4);
|
||||||
}
|
}
|
||||||
| expr '>' '>' expr
|
| expr '>' '>' expr
|
||||||
{
|
{
|
||||||
$$ = $1 >> $4;
|
$$ = $1 >> uint($4);
|
||||||
}
|
}
|
||||||
| expr '&' expr
|
| expr '&' expr
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
914
src/cmd/8a/lex.c
914
src/cmd/8a/lex.c
|
|
@ -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"
|
|
||||||
2778
src/cmd/8a/y.tab.c
2778
src/cmd/8a/y.tab.c
File diff suppressed because it is too large
Load diff
|
|
@ -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;
|
|
||||||
|
|
||||||
|
|
@ -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
|
|
||||||
1590
src/cmd/8g/cgen.c
1590
src/cmd/8g/cgen.c
File diff suppressed because it is too large
Load diff
|
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
189
src/cmd/8g/gg.h
189
src/cmd/8g/gg.h
|
|
@ -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*);
|
|
||||||
1165
src/cmd/8g/ggen.c
1165
src/cmd/8g/ggen.c
File diff suppressed because it is too large
Load diff
1874
src/cmd/8g/gsubr.c
1874
src/cmd/8g/gsubr.c
File diff suppressed because it is too large
Load diff
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
112
src/cmd/8g/reg.c
112
src/cmd/8g/reg.c
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
||||||
172
src/cmd/9a/a.h
172
src/cmd/9a/a.h
|
|
@ -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*);
|
|
||||||
544
src/cmd/9a/a.y
544
src/cmd/9a/a.y
File diff suppressed because it is too large
Load diff
|
|
@ -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
|
|
||||||
726
src/cmd/9a/lex.c
726
src/cmd/9a/lex.c
|
|
@ -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"
|
|
||||||
3466
src/cmd/9a/y.tab.c
3466
src/cmd/9a/y.tab.c
File diff suppressed because it is too large
Load diff
|
|
@ -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;
|
|
||||||
|
|
||||||
1758
src/cmd/9g/cgen.c
1758
src/cmd/9g/cgen.c
File diff suppressed because it is too large
Load diff
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue