diff options
Diffstat (limited to 'src/cmd/8g/prog.c')
-rw-r--r-- | src/cmd/8g/prog.c | 340 |
1 files changed, 340 insertions, 0 deletions
diff --git a/src/cmd/8g/prog.c b/src/cmd/8g/prog.c new file mode 100644 index 000000000..14f197b6a --- /dev/null +++ b/src/cmd/8g/prog.c @@ -0,0 +1,340 @@ +// 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" + +// Matches real RtoB but can be used in global initializer. +#define RtoB(r) (1<<((r)-D_AX)) + +enum { + AX = RtoB(D_AX), + BX = RtoB(D_BX), + CX = RtoB(D_CX), + DX = RtoB(D_DX), + DI = RtoB(D_DI), + SI = RtoB(D_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]= {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}, + + [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}, + + [AFMOVDP]= {SizeD | LeftRead | RightAddr}, + [AFMOVFP]= {SizeF | LeftRead | RightAddr}, + [AFMOVLP]= {SizeL | LeftRead | RightAddr}, + [AFMOVWP]= {SizeW | LeftRead | RightAddr}, + [AFMOVVP]= {SizeQ | LeftRead | 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}, + + [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}, + + [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 != D_CONST) + info->reguse |= CX; + + if(info->flags & ImulAXDX) { + if(p->to.type == D_NONE) { + info->reguse |= AX; + info->regset |= AX | DX; + } else { + info->flags |= RightRdwr; + } + } + + // Addressing makes some registers used. + if(p->from.type >= D_INDIR) + info->regindex |= RtoB(p->from.type-D_INDIR); + if(p->from.index != D_NONE) + info->regindex |= RtoB(p->from.index); + if(p->to.type >= D_INDIR) + info->regindex |= RtoB(p->to.type-D_INDIR); + if(p->to.index != D_NONE) + info->regindex |= RtoB(p->to.index); +} |