| // 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}, |
| |
| [ADUFFZERO]= {Call}, |
| [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.type == D_CONST) && p->from.reg != NREG) { |
| info->regindex |= RtoB(p->from.reg); |
| if(info->flags & PostInc) { |
| info->regset |= RtoB(p->from.reg); |
| } |
| } |
| if((p->to.type == D_OREG || p->to.type == D_CONST) && p->to.reg != NREG) { |
| info->regindex |= RtoB(p->to.reg); |
| if(info->flags & PostInc) { |
| info->regset |= RtoB(p->to.reg); |
| } |
| } |
| |
| if(p->from.type == D_CONST && p->from.sym != nil && (info->flags & LeftRead)) { |
| info->flags &= ~LeftRead; |
| info->flags |= LeftAddr; |
| } |
| |
| if(p->as == ADUFFZERO) { |
| info->reguse |= RtoB(0) | RtoB(2); |
| info->regset |= RtoB(2); |
| } |
| if(p->as == ADUFFCOPY) { |
| info->reguse |= RtoB(0) | RtoB(2) | RtoB(3); |
| info->regset |= RtoB(2) | RtoB(3); |
| } |
| } |