diff options
Diffstat (limited to 'src/cmd/9g/prog.c')
-rw-r--r-- | src/cmd/9g/prog.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/src/cmd/9g/prog.c b/src/cmd/9g/prog.c new file mode 100644 index 000000000..0a51a533a --- /dev/null +++ b/src/cmd/9g/prog.c @@ -0,0 +1,138 @@ +// 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. + +#include <u.h> +#include <libc.h> +#include "gg.h" +#include "opt.h" + +enum { + LeftRdwr = LeftRead | LeftWrite, + 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 Power opcode. + [ANOP]= {LeftRead | RightWrite}, + + // Integer + [AADD]= {SizeQ | LeftRead | RegRead | RightWrite}, + [ASUB]= {SizeQ | LeftRead | RegRead | RightWrite}, + [ANEG]= {SizeQ | LeftRead | RegRead | RightWrite}, + [AAND]= {SizeQ | LeftRead | RegRead | RightWrite}, + [AOR]= {SizeQ | LeftRead | RegRead | RightWrite}, + [AXOR]= {SizeQ | LeftRead | RegRead | RightWrite}, + [AMULLD]= {SizeQ | LeftRead | RegRead | RightWrite}, + [AMULLW]= {SizeL | LeftRead | RegRead | RightWrite}, + [AMULHD]= {SizeL | LeftRead | RegRead | RightWrite}, + [AMULHDU]= {SizeL | LeftRead | RegRead | RightWrite}, + [ADIVD]= {SizeQ | LeftRead | RegRead | RightWrite}, + [ADIVDU]= {SizeQ | LeftRead | RegRead | RightWrite}, + [ASLD]= {SizeQ | LeftRead | RegRead | RightWrite}, + [ASRD]= {SizeQ | LeftRead | RegRead | RightWrite}, + [ASRAD]= {SizeQ | LeftRead | RegRead | RightWrite}, + [ACMP]= {SizeQ | LeftRead | RightRead}, + [ACMPU]= {SizeQ | LeftRead | RightRead}, + [ATD]= {SizeQ | RightRead}, + + // Floating point. + [AFADD]= {SizeD | LeftRead | RegRead | RightWrite}, + [AFADDS]= {SizeF | LeftRead | RegRead | RightWrite}, + [AFSUB]= {SizeD | LeftRead | RegRead | RightWrite}, + [AFSUBS]= {SizeF | LeftRead | RegRead | RightWrite}, + [AFMUL]= {SizeD | LeftRead | RegRead | RightWrite}, + [AFMULS]= {SizeF | LeftRead | RegRead | RightWrite}, + [AFDIV]= {SizeD | LeftRead | RegRead | RightWrite}, + [AFDIVS]= {SizeF | LeftRead | RegRead | RightWrite}, + [AFCTIDZ]= {SizeF | LeftRead | RegRead | RightWrite}, + [AFCFID]= {SizeF | LeftRead | RegRead | RightWrite}, + [AFCMPU]= {SizeD | LeftRead | RightRead}, + [AFRSP]= {SizeD | LeftRead | RightWrite | Conv}, + + // Moves + [AMOVB]= {SizeB | LeftRead | RightWrite | Move | Conv}, + [AMOVBU]= {SizeB | LeftRead | RightWrite | Move | Conv | PostInc}, + [AMOVBZ]= {SizeB | LeftRead | RightWrite | Move | Conv}, + [AMOVH]= {SizeW | LeftRead | RightWrite | Move | Conv}, + [AMOVHU]= {SizeW | LeftRead | RightWrite | Move | Conv | PostInc}, + [AMOVHZ]= {SizeW | LeftRead | RightWrite | Move | Conv}, + [AMOVW]= {SizeL | LeftRead | RightWrite | Move | Conv}, + // there is no AMOVWU. + [AMOVWZU]= {SizeL | LeftRead | RightWrite | Move | Conv | PostInc}, + [AMOVWZ]= {SizeL | LeftRead | RightWrite | Move | Conv}, + [AMOVD]= {SizeQ | LeftRead | RightWrite | Move}, + [AMOVDU]= {SizeQ | LeftRead | RightWrite | Move | PostInc}, + [AFMOVS]= {SizeF | LeftRead | RightWrite | Move | Conv}, + [AFMOVD]= {SizeD | LeftRead | RightWrite | Move}, + + // Jumps + [ABR]= {Jump | Break}, + [ABL]= {Call}, + [ABEQ]= {Cjmp}, + [ABNE]= {Cjmp}, + [ABGE]= {Cjmp}, + [ABLT]= {Cjmp}, + [ABGT]= {Cjmp}, + [ABLE]= {Cjmp}, + [ARETURN]= {Break}, + // In addtion, duffzero reads R0,R2 and writes R2. This fact must be + // encoded in peep.c (TODO) + [ADUFFZERO]= {Call}, + // In addtion, duffcopy reads R0,R2,R3 and writes R2,R3. This fact must be + // encoded in peep.c (TODO) + [ADUFFCOPY]= {Call}, +}; + +void +proginfo(ProgInfo *info, Prog *p) +{ + *info = progtable[p->as]; + if(info->flags == 0) { + *info = progtable[AADD]; + fatal("proginfo: unknown instruction %P", p); + } + + if((info->flags & RegRead) && p->reg == NREG) { + info->flags &= ~RegRead; + info->flags |= /*CanRegRead |*/ RightRead; + } + + if(p->from.type == D_OREG && p->from.reg != NREG) { + info->reguse |= RtoB(p->from.reg); + if(info->flags & PostInc) { + info->regset |= RtoB(p->from.reg); + } + } + if(p->to.type == D_OREG && p->to.reg != NREG) { + info->reguse |= RtoB(p->to.reg); + if(info->flags & PostInc) { + info->regset |= RtoB(p->to.reg); + } + } + + if(p->from.type == D_CONST && p->from.sym != nil && (info->flags & LeftRead)) { + info->flags &= ~LeftRead; + info->flags |= LeftAddr; + } +} |