]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/compile/internal/amd64/prog.go
[dev.ssa] Merge remote-tracking branch 'origin/master' into mergebranch
[gostls13.git] / src / cmd / compile / internal / amd64 / prog.go
1 // Copyright 2013 The Go Authors.  All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package amd64
6
7 import (
8         "cmd/compile/internal/gc"
9         "cmd/internal/obj"
10         "cmd/internal/obj/x86"
11 )
12
13 const (
14         LeftRdwr  uint32 = gc.LeftRead | gc.LeftWrite
15         RightRdwr uint32 = gc.RightRead | gc.RightWrite
16 )
17
18 // This table gives the basic information about instruction
19 // generated by the compiler and processed in the optimizer.
20 // See opt.h for bit definitions.
21 //
22 // Instructions not generated need not be listed.
23 // As an exception to that rule, we typically write down all the
24 // size variants of an operation even if we just use a subset.
25 //
26 // The table is formatted for 8-space tabs.
27 var progtable = [x86.ALAST]obj.ProgInfo{
28         obj.ATYPE:     {Flags: gc.Pseudo | gc.Skip},
29         obj.ATEXT:     {Flags: gc.Pseudo},
30         obj.AFUNCDATA: {Flags: gc.Pseudo},
31         obj.APCDATA:   {Flags: gc.Pseudo},
32         obj.AUNDEF:    {Flags: gc.Break},
33         obj.AUSEFIELD: {Flags: gc.OK},
34         obj.ACHECKNIL: {Flags: gc.LeftRead},
35         obj.AVARDEF:   {Flags: gc.Pseudo | gc.RightWrite},
36         obj.AVARKILL:  {Flags: gc.Pseudo | gc.RightWrite},
37
38         // NOP is an internal no-op that also stands
39         // for USED and SET annotations, not the Intel opcode.
40         obj.ANOP:       {Flags: gc.LeftRead | gc.RightWrite},
41         x86.AADCL:      {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry},
42         x86.AADCQ:      {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry},
43         x86.AADCW:      {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry},
44         x86.AADDB:      {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry},
45         x86.AADDL:      {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry},
46         x86.AADDW:      {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry},
47         x86.AADDQ:      {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.SetCarry},
48         x86.AADDSD:     {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
49         x86.AADDSS:     {Flags: gc.SizeF | gc.LeftRead | RightRdwr},
50         x86.AANDB:      {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry},
51         x86.AANDL:      {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry},
52         x86.AANDQ:      {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.SetCarry},
53         x86.AANDW:      {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry},
54         obj.ACALL:      {Flags: gc.RightAddr | gc.Call | gc.KillCarry},
55         x86.ACDQ:       {Flags: gc.OK, Reguse: AX, Regset: AX | DX},
56         x86.ACQO:       {Flags: gc.OK, Reguse: AX, Regset: AX | DX},
57         x86.ACWD:       {Flags: gc.OK, Reguse: AX, Regset: AX | DX},
58         x86.ACLD:       {Flags: gc.OK},
59         x86.ASTD:       {Flags: gc.OK},
60         x86.ACMPB:      {Flags: gc.SizeB | gc.LeftRead | gc.RightRead | gc.SetCarry},
61         x86.ACMPL:      {Flags: gc.SizeL | gc.LeftRead | gc.RightRead | gc.SetCarry},
62         x86.ACMPQ:      {Flags: gc.SizeQ | gc.LeftRead | gc.RightRead | gc.SetCarry},
63         x86.ACMPW:      {Flags: gc.SizeW | gc.LeftRead | gc.RightRead | gc.SetCarry},
64         x86.ACOMISD:    {Flags: gc.SizeD | gc.LeftRead | gc.RightRead | gc.SetCarry},
65         x86.ACOMISS:    {Flags: gc.SizeF | gc.LeftRead | gc.RightRead | gc.SetCarry},
66         x86.ACVTSD2SL:  {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
67         x86.ACVTSD2SQ:  {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
68         x86.ACVTSD2SS:  {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
69         x86.ACVTSL2SD:  {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
70         x86.ACVTSL2SS:  {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
71         x86.ACVTSQ2SD:  {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
72         x86.ACVTSQ2SS:  {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
73         x86.ACVTSS2SD:  {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
74         x86.ACVTSS2SL:  {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
75         x86.ACVTSS2SQ:  {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
76         x86.ACVTTSD2SL: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
77         x86.ACVTTSD2SQ: {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
78         x86.ACVTTSS2SL: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
79         x86.ACVTTSS2SQ: {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
80         x86.ADECB:      {Flags: gc.SizeB | RightRdwr},
81         x86.ADECL:      {Flags: gc.SizeL | RightRdwr},
82         x86.ADECQ:      {Flags: gc.SizeQ | RightRdwr},
83         x86.ADECW:      {Flags: gc.SizeW | RightRdwr},
84         x86.ADIVB:      {Flags: gc.SizeB | gc.LeftRead | gc.SetCarry, Reguse: AX, Regset: AX},
85         x86.ADIVL:      {Flags: gc.SizeL | gc.LeftRead | gc.SetCarry, Reguse: AX | DX, Regset: AX | DX},
86         x86.ADIVQ:      {Flags: gc.SizeQ | gc.LeftRead | gc.SetCarry, Reguse: AX | DX, Regset: AX | DX},
87         x86.ADIVW:      {Flags: gc.SizeW | gc.LeftRead | gc.SetCarry, Reguse: AX | DX, Regset: AX | DX},
88         x86.ADIVSD:     {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
89         x86.ADIVSS:     {Flags: gc.SizeF | gc.LeftRead | RightRdwr},
90         x86.AIDIVB:     {Flags: gc.SizeB | gc.LeftRead | gc.SetCarry, Reguse: AX, Regset: AX},
91         x86.AIDIVL:     {Flags: gc.SizeL | gc.LeftRead | gc.SetCarry, Reguse: AX | DX, Regset: AX | DX},
92         x86.AIDIVQ:     {Flags: gc.SizeQ | gc.LeftRead | gc.SetCarry, Reguse: AX | DX, Regset: AX | DX},
93         x86.AIDIVW:     {Flags: gc.SizeW | gc.LeftRead | gc.SetCarry, Reguse: AX | DX, Regset: AX | DX},
94         x86.AIMULB:     {Flags: gc.SizeB | gc.LeftRead | gc.SetCarry, Reguse: AX, Regset: AX},
95         x86.AIMULL:     {Flags: gc.SizeL | gc.LeftRead | gc.ImulAXDX | gc.SetCarry},
96         x86.AIMULQ:     {Flags: gc.SizeQ | gc.LeftRead | gc.ImulAXDX | gc.SetCarry},
97         x86.AIMULW:     {Flags: gc.SizeW | gc.LeftRead | gc.ImulAXDX | gc.SetCarry},
98         x86.AINCB:      {Flags: gc.SizeB | RightRdwr},
99         x86.AINCL:      {Flags: gc.SizeL | RightRdwr},
100         x86.AINCQ:      {Flags: gc.SizeQ | RightRdwr},
101         x86.AINCW:      {Flags: gc.SizeW | RightRdwr},
102         x86.AJCC:       {Flags: gc.Cjmp | gc.UseCarry},
103         x86.AJCS:       {Flags: gc.Cjmp | gc.UseCarry},
104         x86.AJEQ:       {Flags: gc.Cjmp | gc.UseCarry},
105         x86.AJGE:       {Flags: gc.Cjmp | gc.UseCarry},
106         x86.AJGT:       {Flags: gc.Cjmp | gc.UseCarry},
107         x86.AJHI:       {Flags: gc.Cjmp | gc.UseCarry},
108         x86.AJLE:       {Flags: gc.Cjmp | gc.UseCarry},
109         x86.AJLS:       {Flags: gc.Cjmp | gc.UseCarry},
110         x86.AJLT:       {Flags: gc.Cjmp | gc.UseCarry},
111         x86.AJMI:       {Flags: gc.Cjmp | gc.UseCarry},
112         x86.AJNE:       {Flags: gc.Cjmp | gc.UseCarry},
113         x86.AJOC:       {Flags: gc.Cjmp | gc.UseCarry},
114         x86.AJOS:       {Flags: gc.Cjmp | gc.UseCarry},
115         x86.AJPC:       {Flags: gc.Cjmp | gc.UseCarry},
116         x86.AJPL:       {Flags: gc.Cjmp | gc.UseCarry},
117         x86.AJPS:       {Flags: gc.Cjmp | gc.UseCarry},
118         obj.AJMP:       {Flags: gc.Jump | gc.Break | gc.KillCarry},
119         x86.ALEAW:      {Flags: gc.LeftAddr | gc.RightWrite},
120         x86.ALEAL:      {Flags: gc.LeftAddr | gc.RightWrite},
121         x86.ALEAQ:      {Flags: gc.LeftAddr | gc.RightWrite},
122         x86.AMOVBLSX:   {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
123         x86.AMOVBLZX:   {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
124         x86.AMOVBQSX:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
125         x86.AMOVBQZX:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
126         x86.AMOVBWSX:   {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Conv},
127         x86.AMOVBWZX:   {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Conv},
128         x86.AMOVLQSX:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
129         x86.AMOVLQZX:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
130         x86.AMOVWLSX:   {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
131         x86.AMOVWLZX:   {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
132         x86.AMOVWQSX:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
133         x86.AMOVWQZX:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
134         x86.AMOVQL:     {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
135         x86.AMOVB:      {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move},
136         x86.AMOVL:      {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move},
137         x86.AMOVQ:      {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move},
138         x86.AMOVW:      {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move},
139         x86.AMOVUPS:    {Flags: gc.LeftRead | gc.RightWrite | gc.Move},
140         x86.AMOVSB:     {Flags: gc.OK, Reguse: DI | SI, Regset: DI | SI},
141         x86.AMOVSL:     {Flags: gc.OK, Reguse: DI | SI, Regset: DI | SI},
142         x86.AMOVSQ:     {Flags: gc.OK, Reguse: DI | SI, Regset: DI | SI},
143         x86.AMOVSW:     {Flags: gc.OK, Reguse: DI | SI, Regset: DI | SI},
144         obj.ADUFFCOPY:  {Flags: gc.OK, Reguse: DI | SI, Regset: DI | SI | X0},
145         x86.AMOVSD:     {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move},
146         x86.AMOVSS:     {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move},
147
148         // We use MOVAPD as a faster synonym for MOVSD.
149         x86.AMOVAPD:   {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move},
150         x86.AMULB:     {Flags: gc.SizeB | gc.LeftRead | gc.SetCarry, Reguse: AX, Regset: AX},
151         x86.AMULL:     {Flags: gc.SizeL | gc.LeftRead | gc.SetCarry, Reguse: AX, Regset: AX | DX},
152         x86.AMULQ:     {Flags: gc.SizeQ | gc.LeftRead | gc.SetCarry, Reguse: AX, Regset: AX | DX},
153         x86.AMULW:     {Flags: gc.SizeW | gc.LeftRead | gc.SetCarry, Reguse: AX, Regset: AX | DX},
154         x86.AMULSD:    {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
155         x86.AMULSS:    {Flags: gc.SizeF | gc.LeftRead | RightRdwr},
156         x86.ANEGB:     {Flags: gc.SizeB | RightRdwr | gc.SetCarry},
157         x86.ANEGL:     {Flags: gc.SizeL | RightRdwr | gc.SetCarry},
158         x86.ANEGQ:     {Flags: gc.SizeQ | RightRdwr | gc.SetCarry},
159         x86.ANEGW:     {Flags: gc.SizeW | RightRdwr | gc.SetCarry},
160         x86.ANOTB:     {Flags: gc.SizeB | RightRdwr},
161         x86.ANOTL:     {Flags: gc.SizeL | RightRdwr},
162         x86.ANOTQ:     {Flags: gc.SizeQ | RightRdwr},
163         x86.ANOTW:     {Flags: gc.SizeW | RightRdwr},
164         x86.AORB:      {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry},
165         x86.AORL:      {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry},
166         x86.AORQ:      {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.SetCarry},
167         x86.AORW:      {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry},
168         x86.APOPQ:     {Flags: gc.SizeQ | gc.RightWrite},
169         x86.APUSHQ:    {Flags: gc.SizeQ | gc.LeftRead},
170         x86.APXOR:     {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
171         x86.ARCLB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry},
172         x86.ARCLL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry},
173         x86.ARCLQ:     {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry},
174         x86.ARCLW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry},
175         x86.ARCRB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry},
176         x86.ARCRL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry},
177         x86.ARCRQ:     {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry},
178         x86.ARCRW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry},
179         x86.AREP:      {Flags: gc.OK, Reguse: CX, Regset: CX},
180         x86.AREPN:     {Flags: gc.OK, Reguse: CX, Regset: CX},
181         obj.ARET:      {Flags: gc.Break | gc.KillCarry},
182         x86.AROLB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
183         x86.AROLL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
184         x86.AROLQ:     {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
185         x86.AROLW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
186         x86.ARORB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
187         x86.ARORL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
188         x86.ARORQ:     {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
189         x86.ARORW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
190         x86.ASALB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
191         x86.ASALL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
192         x86.ASALQ:     {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
193         x86.ASALW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
194         x86.ASARB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
195         x86.ASARL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
196         x86.ASARQ:     {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
197         x86.ASARW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
198         x86.ASBBB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry},
199         x86.ASBBL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry},
200         x86.ASBBQ:     {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry},
201         x86.ASBBW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry},
202         x86.ASETCC:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
203         x86.ASETCS:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
204         x86.ASETEQ:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
205         x86.ASETGE:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
206         x86.ASETGT:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
207         x86.ASETHI:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
208         x86.ASETLE:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
209         x86.ASETLS:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
210         x86.ASETLT:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
211         x86.ASETMI:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
212         x86.ASETNE:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
213         x86.ASETOC:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
214         x86.ASETOS:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
215         x86.ASETPC:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
216         x86.ASETPL:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
217         x86.ASETPS:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
218         x86.ASHLB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
219         x86.ASHLL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
220         x86.ASHLQ:     {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
221         x86.ASHLW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
222         x86.ASHRB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
223         x86.ASHRL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
224         x86.ASHRQ:     {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
225         x86.ASHRW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
226         x86.ASQRTSD:   {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
227         x86.ASTOSB:    {Flags: gc.OK, Reguse: AX | DI, Regset: DI},
228         x86.ASTOSL:    {Flags: gc.OK, Reguse: AX | DI, Regset: DI},
229         x86.ASTOSQ:    {Flags: gc.OK, Reguse: AX | DI, Regset: DI},
230         x86.ASTOSW:    {Flags: gc.OK, Reguse: AX | DI, Regset: DI},
231         obj.ADUFFZERO: {Flags: gc.OK, Reguse: X0 | DI, Regset: DI},
232         x86.ASUBB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry},
233         x86.ASUBL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry},
234         x86.ASUBQ:     {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.SetCarry},
235         x86.ASUBW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry},
236         x86.ASUBSD:    {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
237         x86.ASUBSS:    {Flags: gc.SizeF | gc.LeftRead | RightRdwr},
238         x86.ATESTB:    {Flags: gc.SizeB | gc.LeftRead | gc.RightRead | gc.SetCarry},
239         x86.ATESTL:    {Flags: gc.SizeL | gc.LeftRead | gc.RightRead | gc.SetCarry},
240         x86.ATESTQ:    {Flags: gc.SizeQ | gc.LeftRead | gc.RightRead | gc.SetCarry},
241         x86.ATESTW:    {Flags: gc.SizeW | gc.LeftRead | gc.RightRead | gc.SetCarry},
242         x86.AUCOMISD:  {Flags: gc.SizeD | gc.LeftRead | gc.RightRead},
243         x86.AUCOMISS:  {Flags: gc.SizeF | gc.LeftRead | gc.RightRead},
244         x86.AXCHGB:    {Flags: gc.SizeB | LeftRdwr | RightRdwr},
245         x86.AXCHGL:    {Flags: gc.SizeL | LeftRdwr | RightRdwr},
246         x86.AXCHGQ:    {Flags: gc.SizeQ | LeftRdwr | RightRdwr},
247         x86.AXCHGW:    {Flags: gc.SizeW | LeftRdwr | RightRdwr},
248         x86.AXORB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry},
249         x86.AXORL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry},
250         x86.AXORQ:     {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.SetCarry},
251         x86.AXORW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry},
252         x86.AXORPS:    {Flags: gc.LeftRead | RightRdwr},
253 }
254
255 func progflags(p *obj.Prog) uint32 {
256         flags := progtable[p.As].Flags
257         if flags&gc.ImulAXDX != 0 && p.To.Type != obj.TYPE_NONE {
258                 flags |= RightRdwr
259         }
260         return flags
261 }
262
263 func progcarryflags(p *obj.Prog) uint32 {
264         return progtable[p.As].Flags
265 }
266
267 func proginfo(p *obj.Prog) {
268         info := &p.Info
269         *info = progtable[p.As]
270         if info.Flags == 0 {
271                 gc.Fatalf("unknown instruction %v", p)
272         }
273
274         if (info.Flags&gc.ShiftCX != 0) && p.From.Type != obj.TYPE_CONST {
275                 info.Reguse |= CX
276         }
277
278         if info.Flags&gc.ImulAXDX != 0 {
279                 if p.To.Type == obj.TYPE_NONE {
280                         info.Reguse |= AX
281                         info.Regset |= AX | DX
282                 } else {
283                         info.Flags |= RightRdwr
284                 }
285         }
286
287         // Addressing makes some registers used.
288         if p.From.Type == obj.TYPE_MEM && p.From.Name == obj.NAME_NONE {
289                 info.Regindex |= RtoB(int(p.From.Reg))
290         }
291         if p.From.Index != x86.REG_NONE {
292                 info.Regindex |= RtoB(int(p.From.Index))
293         }
294         if p.To.Type == obj.TYPE_MEM && p.To.Name == obj.NAME_NONE {
295                 info.Regindex |= RtoB(int(p.To.Reg))
296         }
297         if p.To.Index != x86.REG_NONE {
298                 info.Regindex |= RtoB(int(p.To.Index))
299         }
300         if gc.Ctxt.Flag_dynlink {
301                 // When -dynlink is passed, many operations on external names (and
302                 // also calling duffzero/duffcopy) use R15 as a scratch register.
303                 if p.As == x86.ALEAQ || info.Flags == gc.Pseudo || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP {
304                         return
305                 }
306                 if p.As == obj.ADUFFZERO || p.As == obj.ADUFFCOPY || (p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local) || (p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local) {
307                         info.Reguse |= R15
308                         info.Regset |= R15
309                         return
310                 }
311         }
312 }