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