diff options
Diffstat (limited to 'src/cmd/5g/prog.c')
-rw-r--r-- | src/cmd/5g/prog.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/src/cmd/5g/prog.c b/src/cmd/5g/prog.c new file mode 100644 index 000000000..5aa6163d8 --- /dev/null +++ b/src/cmd/5g/prog.c @@ -0,0 +1,143 @@ +// 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 "opt.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]= {OK}, + [AUSEFIELD]= {OK}, + [ACHECKNIL]= {LeftRead}, + + // 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}, + + // 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 == D_CONST && p->from.sym != nil && (info->flags & LeftRead)) { + info->flags &= ~LeftRead; + info->flags |= LeftAddr; + } + + if((info->flags & RegRead) && p->reg == NREG) { + info->flags &= ~RegRead; + info->flags |= CanRegRead | RightRead; + } + + if(((p->scond & C_SCOND) != C_SCOND_NONE) && (info->flags & RightWrite)) + info->flags |= RightRead; +} |