root/src/cmd/5g/prog.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. proginfo

// 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]=       {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 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},
        // In addtion, duffzero reads R0,R1 and writes R1.  This fact is
        // encoded in peep.c
        [ADUFFZERO]=            {Call},
        // In addtion, duffcopy reads R1,R2 and writes R0,R1,R2.  This fact is
        // encoded in peep.c
        [ADUFFCOPY]=            {Call},

        // 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;
}

/* [<][>][^][v][top][bottom][index][help] */