summaryrefslogtreecommitdiff
path: root/src/cmd/8g/prog.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/8g/prog.c')
-rw-r--r--src/cmd/8g/prog.c340
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);
+}