blob: ee68399d5adf13ef34e866c9ffa1553abc453bb8 [file] [log] [blame]
// 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]= {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},
[AADCL]= {SizeL | LeftRead | RightRdwr | SetCarry | UseCarry},
[AADCQ]= {SizeQ | 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},
[AADDQ]= {SizeQ | LeftRead | RightRdwr | SetCarry},
[AADDSD]= {SizeD | LeftRead | RightRdwr},
[AADDSS]= {SizeF | LeftRead | RightRdwr},
[AANDB]= {SizeB | LeftRead | RightRdwr | SetCarry},
[AANDL]= {SizeL | LeftRead | RightRdwr | SetCarry},
[AANDQ]= {SizeQ | LeftRead | RightRdwr | SetCarry},
[AANDW]= {SizeW | LeftRead | RightRdwr | SetCarry},
[ACALL]= {RightAddr | Call | KillCarry},
[ACDQ]= {OK, AX, AX | DX},
[ACQO]= {OK, AX, AX | DX},
[ACWD]= {OK, AX, AX | DX},
[ACLD]= {OK},
[ASTD]= {OK},
[ACMPB]= {SizeB | LeftRead | RightRead | SetCarry},
[ACMPL]= {SizeL | LeftRead | RightRead | SetCarry},
[ACMPQ]= {SizeQ | LeftRead | RightRead | SetCarry},
[ACMPW]= {SizeW | LeftRead | RightRead | SetCarry},
[ACOMISD]= {SizeD | LeftRead | RightRead | SetCarry},
[ACOMISS]= {SizeF | LeftRead | RightRead | SetCarry},
[ACVTSD2SL]= {SizeL | LeftRead | RightWrite | Conv},
[ACVTSD2SQ]= {SizeQ | LeftRead | RightWrite | Conv},
[ACVTSD2SS]= {SizeF | LeftRead | RightWrite | Conv},
[ACVTSL2SD]= {SizeD | LeftRead | RightWrite | Conv},
[ACVTSL2SS]= {SizeF | LeftRead | RightWrite | Conv},
[ACVTSQ2SD]= {SizeD | LeftRead | RightWrite | Conv},
[ACVTSQ2SS]= {SizeF | LeftRead | RightWrite | Conv},
[ACVTSS2SD]= {SizeD | LeftRead | RightWrite | Conv},
[ACVTSS2SL]= {SizeL | LeftRead | RightWrite | Conv},
[ACVTSS2SQ]= {SizeQ | LeftRead | RightWrite | Conv},
[ACVTTSD2SL]= {SizeL | LeftRead | RightWrite | Conv},
[ACVTTSD2SQ]= {SizeQ | LeftRead | RightWrite | Conv},
[ACVTTSS2SL]= {SizeL | LeftRead | RightWrite | Conv},
[ACVTTSS2SQ]= {SizeQ | LeftRead | RightWrite | Conv},
[ADECB]= {SizeB | RightRdwr},
[ADECL]= {SizeL | RightRdwr},
[ADECQ]= {SizeQ | RightRdwr},
[ADECW]= {SizeW | RightRdwr},
[ADIVB]= {SizeB | LeftRead | SetCarry, AX, AX},
[ADIVL]= {SizeL | LeftRead | SetCarry, AX|DX, AX|DX},
[ADIVQ]= {SizeQ | LeftRead | SetCarry, AX|DX, AX|DX},
[ADIVW]= {SizeW | LeftRead | SetCarry, AX|DX, AX|DX},
[ADIVSD]= {SizeD | LeftRead | RightRdwr},
[ADIVSS]= {SizeF | LeftRead | RightRdwr},
[AIDIVB]= {SizeB | LeftRead | SetCarry, AX, AX},
[AIDIVL]= {SizeL | LeftRead | SetCarry, AX|DX, AX|DX},
[AIDIVQ]= {SizeQ | 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},
[AIMULQ]= {SizeQ | LeftRead | ImulAXDX | SetCarry},
[AIMULW]= {SizeW | LeftRead | ImulAXDX | SetCarry},
[AINCB]= {SizeB | RightRdwr},
[AINCL]= {SizeL | RightRdwr},
[AINCQ]= {SizeQ | 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},
[ALEAQ]= {LeftAddr | RightWrite},
[AMOVBLSX]= {SizeL | LeftRead | RightWrite | Conv},
[AMOVBLZX]= {SizeL | LeftRead | RightWrite | Conv},
[AMOVBQSX]= {SizeQ | LeftRead | RightWrite | Conv},
[AMOVBQZX]= {SizeQ | LeftRead | RightWrite | Conv},
[AMOVBWSX]= {SizeW | LeftRead | RightWrite | Conv},
[AMOVBWZX]= {SizeW | LeftRead | RightWrite | Conv},
[AMOVLQSX]= {SizeQ | LeftRead | RightWrite | Conv},
[AMOVLQZX]= {SizeQ | LeftRead | RightWrite | Conv},
[AMOVWLSX]= {SizeL | LeftRead | RightWrite | Conv},
[AMOVWLZX]= {SizeL | LeftRead | RightWrite | Conv},
[AMOVWQSX]= {SizeQ | LeftRead | RightWrite | Conv},
[AMOVWQZX]= {SizeQ | LeftRead | RightWrite | Conv},
[AMOVQL]= {SizeL | LeftRead | RightWrite | Conv},
[AMOVB]= {SizeB | LeftRead | RightWrite | Move},
[AMOVL]= {SizeL | LeftRead | RightWrite | Move},
[AMOVQ]= {SizeQ | LeftRead | RightWrite | Move},
[AMOVW]= {SizeW | LeftRead | RightWrite | Move},
[AMOVSB]= {OK, DI|SI, DI|SI},
[AMOVSL]= {OK, DI|SI, DI|SI},
[AMOVSQ]= {OK, DI|SI, DI|SI},
[AMOVSW]= {OK, DI|SI, DI|SI},
[ADUFFCOPY]= {OK, DI|SI, DI|SI|CX},
[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},
[AMULQ]= {SizeQ | 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},
[ANEGQ]= {SizeQ | RightRdwr | SetCarry},
[ANEGW]= {SizeW | RightRdwr | SetCarry},
[ANOTB]= {SizeB | RightRdwr},
[ANOTL]= {SizeL | RightRdwr},
[ANOTQ]= {SizeQ | RightRdwr},
[ANOTW]= {SizeW | RightRdwr},
[AORB]= {SizeB | LeftRead | RightRdwr | SetCarry},
[AORL]= {SizeL | LeftRead | RightRdwr | SetCarry},
[AORQ]= {SizeQ | LeftRead | RightRdwr | SetCarry},
[AORW]= {SizeW | LeftRead | RightRdwr | SetCarry},
[APOPQ]= {SizeQ | RightWrite},
[APUSHQ]= {SizeQ | LeftRead},
[ARCLB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
[ARCLL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
[ARCLQ]= {SizeQ | 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},
[ARCRQ]= {SizeQ | 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},
[AROLQ]= {SizeQ | LeftRead | RightRdwr | ShiftCX | SetCarry},
[AROLW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ARORB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ARORL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ARORQ]= {SizeQ | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ARORW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASALB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASALL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASALQ]= {SizeQ | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASALW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASARB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASARL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASARQ]= {SizeQ | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASARW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASBBB]= {SizeB | LeftRead | RightRdwr | SetCarry | UseCarry},
[ASBBL]= {SizeL | LeftRead | RightRdwr | SetCarry | UseCarry},
[ASBBQ]= {SizeQ | LeftRead | RightRdwr | SetCarry | UseCarry},
[ASBBW]= {SizeW | LeftRead | RightRdwr | SetCarry | UseCarry},
[ASHLB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASHLL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASHLQ]= {SizeQ | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASHLW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASHRB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASHRL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASHRQ]= {SizeQ | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASHRW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
[ASTOSB]= {OK, AX|DI, DI},
[ASTOSL]= {OK, AX|DI, DI},
[ASTOSQ]= {OK, AX|DI, DI},
[ASTOSW]= {OK, AX|DI, DI},
[ADUFFZERO]= {OK, AX|DI, DI},
[ASUBB]= {SizeB | LeftRead | RightRdwr | SetCarry},
[ASUBL]= {SizeL | LeftRead | RightRdwr | SetCarry},
[ASUBQ]= {SizeQ | 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},
[ATESTQ]= {SizeQ | LeftRead | RightRead | SetCarry},
[ATESTW]= {SizeW | LeftRead | RightRead | SetCarry},
[AUCOMISD]= {SizeD | LeftRead | RightRead},
[AUCOMISS]= {SizeF | LeftRead | RightRead},
[AXCHGB]= {SizeB | LeftRdwr | RightRdwr},
[AXCHGL]= {SizeL | LeftRdwr | RightRdwr},
[AXCHGQ]= {SizeQ | LeftRdwr | RightRdwr},
[AXCHGW]= {SizeW | LeftRdwr | RightRdwr},
[AXORB]= {SizeB | LeftRead | RightRdwr | SetCarry},
[AXORL]= {SizeL | LeftRead | RightRdwr | SetCarry},
[AXORQ]= {SizeQ | 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);
}