Home | History | Annotate | Download | only in ppc64
      1 // Copyright 2014 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 ppc64
      6 
      7 import (
      8 	"cmd/compile/internal/gc"
      9 	"cmd/internal/obj"
     10 	"cmd/internal/obj/ppc64"
     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 = [ppc64.ALAST & obj.AMask]gc.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.AVARDEF:   {Flags: gc.Pseudo | gc.RightWrite},
     35 	obj.AVARKILL:  {Flags: gc.Pseudo | gc.RightWrite},
     36 	obj.AVARLIVE:  {Flags: gc.Pseudo | gc.LeftRead},
     37 
     38 	// NOP is an internal no-op that also stands
     39 	// for USED and SET annotations, not the Power opcode.
     40 	obj.ANOP: {Flags: gc.LeftRead | gc.RightWrite},
     41 
     42 	// Integer
     43 	ppc64.AADD & obj.AMask:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
     44 	ppc64.AADDC & obj.AMask:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
     45 	ppc64.ASUB & obj.AMask:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
     46 	ppc64.AADDME & obj.AMask:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
     47 	ppc64.ANEG & obj.AMask:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
     48 	ppc64.AAND & obj.AMask:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
     49 	ppc64.AANDN & obj.AMask:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
     50 	ppc64.AOR & obj.AMask:     {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
     51 	ppc64.AORN & obj.AMask:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
     52 	ppc64.AXOR & obj.AMask:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
     53 	ppc64.AEQV & obj.AMask:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
     54 	ppc64.AMULLD & obj.AMask:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
     55 	ppc64.AMULLW & obj.AMask:  {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     56 	ppc64.AMULHD & obj.AMask:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
     57 	ppc64.AMULHDU & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
     58 	ppc64.AMULHW & obj.AMask:  {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     59 	ppc64.AMULHWU & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     60 	ppc64.ADIVD & obj.AMask:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
     61 	ppc64.ADIVDU & obj.AMask:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
     62 	ppc64.ADIVW & obj.AMask:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     63 	ppc64.ADIVWU & obj.AMask:  {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     64 	ppc64.ASLD & obj.AMask:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
     65 	ppc64.ASRD & obj.AMask:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
     66 	ppc64.ASRAD & obj.AMask:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
     67 	ppc64.ASLW & obj.AMask:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     68 	ppc64.ASRW & obj.AMask:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     69 	ppc64.ASRAW & obj.AMask:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     70 	ppc64.ACMP & obj.AMask:    {Flags: gc.SizeQ | gc.LeftRead | gc.RightRead},
     71 	ppc64.ACMPU & obj.AMask:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightRead},
     72 	ppc64.ACMPW & obj.AMask:   {Flags: gc.SizeL | gc.LeftRead | gc.RightRead},
     73 	ppc64.ACMPWU & obj.AMask:  {Flags: gc.SizeL | gc.LeftRead | gc.RightRead},
     74 	ppc64.ATD & obj.AMask:     {Flags: gc.SizeQ | gc.RightRead},
     75 
     76 	// Floating point.
     77 	ppc64.AFADD & obj.AMask:   {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
     78 	ppc64.AFADDS & obj.AMask:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
     79 	ppc64.AFSUB & obj.AMask:   {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
     80 	ppc64.AFSUBS & obj.AMask:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
     81 	ppc64.AFMUL & obj.AMask:   {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
     82 	ppc64.AFMULS & obj.AMask:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
     83 	ppc64.AFDIV & obj.AMask:   {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
     84 	ppc64.AFDIVS & obj.AMask:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
     85 	ppc64.AFCTIDZ & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
     86 	ppc64.AFCTIWZ & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
     87 	ppc64.AFCFID & obj.AMask:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
     88 	ppc64.AFCFIDU & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
     89 	ppc64.AFCMPU & obj.AMask:  {Flags: gc.SizeD | gc.LeftRead | gc.RightRead},
     90 	ppc64.AFRSP & obj.AMask:   {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
     91 	ppc64.AFSQRT & obj.AMask:  {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite},
     92 	ppc64.AFNEG & obj.AMask:   {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite},
     93 
     94 	// Moves
     95 	ppc64.AMOVB & obj.AMask:  {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
     96 	ppc64.AMOVBU & obj.AMask: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv | gc.PostInc},
     97 	ppc64.AMOVBZ & obj.AMask: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
     98 	ppc64.AMOVH & obj.AMask:  {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
     99 	ppc64.AMOVHU & obj.AMask: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv | gc.PostInc},
    100 	ppc64.AMOVHZ & obj.AMask: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
    101 	ppc64.AMOVW & obj.AMask:  {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
    102 
    103 	ppc64.AISEL & obj.AMask: {Flags: gc.SizeQ | gc.RegRead | gc.From3Read | gc.RightWrite},
    104 
    105 	// there is no AMOVWU.
    106 	ppc64.AMOVWZU & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv | gc.PostInc},
    107 	ppc64.AMOVWZ & obj.AMask:  {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
    108 	ppc64.AMOVD & obj.AMask:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move},
    109 	ppc64.AMOVDU & obj.AMask:  {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move | gc.PostInc},
    110 	ppc64.AFMOVS & obj.AMask:  {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
    111 	ppc64.AFMOVSX & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
    112 	ppc64.AFMOVSZ & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
    113 	ppc64.AFMOVD & obj.AMask:  {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move},
    114 
    115 	// Jumps
    116 	ppc64.ABR & obj.AMask:  {Flags: gc.Jump | gc.Break},
    117 	ppc64.ABL & obj.AMask:  {Flags: gc.Call},
    118 	ppc64.ABVS & obj.AMask: {Flags: gc.Cjmp},
    119 	ppc64.ABVC & obj.AMask: {Flags: gc.Cjmp},
    120 	ppc64.ABEQ & obj.AMask: {Flags: gc.Cjmp},
    121 	ppc64.ABNE & obj.AMask: {Flags: gc.Cjmp},
    122 	ppc64.ABGE & obj.AMask: {Flags: gc.Cjmp},
    123 	ppc64.ABLT & obj.AMask: {Flags: gc.Cjmp},
    124 	ppc64.ABGT & obj.AMask: {Flags: gc.Cjmp},
    125 	ppc64.ABLE & obj.AMask: {Flags: gc.Cjmp},
    126 	obj.ARET:               {Flags: gc.Break},
    127 	obj.ADUFFZERO:          {Flags: gc.Call},
    128 	obj.ADUFFCOPY:          {Flags: gc.Call},
    129 }
    130 
    131 func initproginfo() {
    132 	var addvariant = []int{V_CC, V_V, V_CC | V_V}
    133 
    134 	// Perform one-time expansion of instructions in progtable to
    135 	// their CC, V, and VCC variants
    136 	for i := range progtable {
    137 		as := obj.As(i)
    138 		if progtable[as].Flags == 0 {
    139 			continue
    140 		}
    141 		variant := as2variant(as)
    142 		for i := range addvariant {
    143 			as2 := variant2as(as, variant|addvariant[i])
    144 			if as2 != 0 && progtable[as2&obj.AMask].Flags == 0 {
    145 				progtable[as2&obj.AMask] = progtable[as]
    146 			}
    147 		}
    148 	}
    149 }
    150 
    151 func proginfo(p *obj.Prog) gc.ProgInfo {
    152 	info := progtable[p.As&obj.AMask]
    153 	if info.Flags == 0 {
    154 		gc.Fatalf("proginfo: unknown instruction %v", p)
    155 	}
    156 
    157 	if (info.Flags&gc.RegRead != 0) && p.Reg == 0 {
    158 		info.Flags &^= gc.RegRead
    159 		info.Flags |= gc.RightRead /*CanRegRead |*/
    160 	}
    161 
    162 	if p.From.Type == obj.TYPE_ADDR && p.From.Sym != nil && (info.Flags&gc.LeftRead != 0) {
    163 		info.Flags &^= gc.LeftRead
    164 		info.Flags |= gc.LeftAddr
    165 	}
    166 
    167 	return info
    168 }
    169 
    170 // Instruction variants table, populated by initvariants via Main.
    171 // The index is the base form of the instruction, masked by obj.AMask.
    172 // The 4 values are the unmasked base form, then the unmasked CC, V,
    173 // and VCC variants, respectively.
    174 var varianttable = [ppc64.ALAST & obj.AMask][4]obj.As{}
    175 
    176 func initvariant(as obj.As, variants ...obj.As) {
    177 	vv := &varianttable[as&obj.AMask]
    178 	vv[0] = as
    179 	for i, v := range variants {
    180 		vv[i+1] = v
    181 	}
    182 }
    183 
    184 func initvariants() {
    185 	initvariant(ppc64.AADD, ppc64.AADDCC, ppc64.AADDV, ppc64.AADDVCC)
    186 	initvariant(ppc64.AADDC, ppc64.AADDCCC, ppc64.AADDCV, ppc64.AADDCVCC)
    187 	initvariant(ppc64.AADDE, ppc64.AADDECC, ppc64.AADDEV, ppc64.AADDEVCC)
    188 	initvariant(ppc64.AADDME, ppc64.AADDMECC, ppc64.AADDMEV, ppc64.AADDMEVCC)
    189 	initvariant(ppc64.AADDZE, ppc64.AADDZECC, ppc64.AADDZEV, ppc64.AADDZEVCC)
    190 	initvariant(ppc64.AAND, ppc64.AANDCC)
    191 	initvariant(ppc64.AANDN, ppc64.AANDNCC)
    192 	initvariant(ppc64.ACNTLZD, ppc64.ACNTLZDCC)
    193 	initvariant(ppc64.ACNTLZW, ppc64.ACNTLZWCC)
    194 	initvariant(ppc64.ADIVD, ppc64.ADIVDCC, ppc64.ADIVDV, ppc64.ADIVDVCC)
    195 	initvariant(ppc64.ADIVDU, ppc64.ADIVDUCC, ppc64.ADIVDUV, ppc64.ADIVDUVCC)
    196 	initvariant(ppc64.ADIVW, ppc64.ADIVWCC, ppc64.ADIVWV, ppc64.ADIVWVCC)
    197 	initvariant(ppc64.ADIVWU, ppc64.ADIVWUCC, ppc64.ADIVWUV, ppc64.ADIVWUVCC)
    198 	initvariant(ppc64.AEQV, ppc64.AEQVCC)
    199 	initvariant(ppc64.AEXTSB, ppc64.AEXTSBCC)
    200 	initvariant(ppc64.AEXTSH, ppc64.AEXTSHCC)
    201 	initvariant(ppc64.AEXTSW, ppc64.AEXTSWCC)
    202 	initvariant(ppc64.AFABS, ppc64.AFABSCC)
    203 	initvariant(ppc64.AFADD, ppc64.AFADDCC)
    204 	initvariant(ppc64.AFADDS, ppc64.AFADDSCC)
    205 	initvariant(ppc64.AFCFID, ppc64.AFCFIDCC)
    206 	initvariant(ppc64.AFCFIDU, ppc64.AFCFIDUCC)
    207 	initvariant(ppc64.AFCTID, ppc64.AFCTIDCC)
    208 	initvariant(ppc64.AFCTIDZ, ppc64.AFCTIDZCC)
    209 	initvariant(ppc64.AFCTIW, ppc64.AFCTIWCC)
    210 	initvariant(ppc64.AFCTIWZ, ppc64.AFCTIWZCC)
    211 	initvariant(ppc64.AFDIV, ppc64.AFDIVCC)
    212 	initvariant(ppc64.AFDIVS, ppc64.AFDIVSCC)
    213 	initvariant(ppc64.AFMADD, ppc64.AFMADDCC)
    214 	initvariant(ppc64.AFMADDS, ppc64.AFMADDSCC)
    215 	initvariant(ppc64.AFMOVD, ppc64.AFMOVDCC)
    216 	initvariant(ppc64.AFMSUB, ppc64.AFMSUBCC)
    217 	initvariant(ppc64.AFMSUBS, ppc64.AFMSUBSCC)
    218 	initvariant(ppc64.AFMUL, ppc64.AFMULCC)
    219 	initvariant(ppc64.AFMULS, ppc64.AFMULSCC)
    220 	initvariant(ppc64.AFNABS, ppc64.AFNABSCC)
    221 	initvariant(ppc64.AFNEG, ppc64.AFNEGCC)
    222 	initvariant(ppc64.AFNMADD, ppc64.AFNMADDCC)
    223 	initvariant(ppc64.AFNMADDS, ppc64.AFNMADDSCC)
    224 	initvariant(ppc64.AFNMSUB, ppc64.AFNMSUBCC)
    225 	initvariant(ppc64.AFNMSUBS, ppc64.AFNMSUBSCC)
    226 	initvariant(ppc64.AFRES, ppc64.AFRESCC)
    227 	initvariant(ppc64.AFRSP, ppc64.AFRSPCC)
    228 	initvariant(ppc64.AFRSQRTE, ppc64.AFRSQRTECC)
    229 	initvariant(ppc64.AFSEL, ppc64.AFSELCC)
    230 	initvariant(ppc64.AFSQRT, ppc64.AFSQRTCC)
    231 	initvariant(ppc64.AFSQRTS, ppc64.AFSQRTSCC)
    232 	initvariant(ppc64.AFSUB, ppc64.AFSUBCC)
    233 	initvariant(ppc64.AFSUBS, ppc64.AFSUBSCC)
    234 	initvariant(ppc64.AMTFSB0, ppc64.AMTFSB0CC)
    235 	initvariant(ppc64.AMTFSB1, ppc64.AMTFSB1CC)
    236 	initvariant(ppc64.AMULHD, ppc64.AMULHDCC)
    237 	initvariant(ppc64.AMULHDU, ppc64.AMULHDUCC)
    238 	initvariant(ppc64.AMULHW, ppc64.AMULHWCC)
    239 	initvariant(ppc64.AMULHWU, ppc64.AMULHWUCC)
    240 	initvariant(ppc64.AMULLD, ppc64.AMULLDCC, ppc64.AMULLDV, ppc64.AMULLDVCC)
    241 	initvariant(ppc64.AMULLW, ppc64.AMULLWCC, ppc64.AMULLWV, ppc64.AMULLWVCC)
    242 	initvariant(ppc64.ANAND, ppc64.ANANDCC)
    243 	initvariant(ppc64.ANEG, ppc64.ANEGCC, ppc64.ANEGV, ppc64.ANEGVCC)
    244 	initvariant(ppc64.ANOR, ppc64.ANORCC)
    245 	initvariant(ppc64.AOR, ppc64.AORCC)
    246 	initvariant(ppc64.AORN, ppc64.AORNCC)
    247 	initvariant(ppc64.AREM, ppc64.AREMCC, ppc64.AREMV, ppc64.AREMVCC)
    248 	initvariant(ppc64.AREMD, ppc64.AREMDCC, ppc64.AREMDV, ppc64.AREMDVCC)
    249 	initvariant(ppc64.AREMDU, ppc64.AREMDUCC, ppc64.AREMDUV, ppc64.AREMDUVCC)
    250 	initvariant(ppc64.AREMU, ppc64.AREMUCC, ppc64.AREMUV, ppc64.AREMUVCC)
    251 	initvariant(ppc64.ARLDC, ppc64.ARLDCCC)
    252 	initvariant(ppc64.ARLDCL, ppc64.ARLDCLCC)
    253 	initvariant(ppc64.ARLDCR, ppc64.ARLDCRCC)
    254 	initvariant(ppc64.ARLDMI, ppc64.ARLDMICC)
    255 	initvariant(ppc64.ARLWMI, ppc64.ARLWMICC)
    256 	initvariant(ppc64.ARLWNM, ppc64.ARLWNMCC)
    257 	initvariant(ppc64.ASLD, ppc64.ASLDCC)
    258 	initvariant(ppc64.ASLW, ppc64.ASLWCC)
    259 	initvariant(ppc64.ASRAD, ppc64.ASRADCC)
    260 	initvariant(ppc64.ASRAW, ppc64.ASRAWCC)
    261 	initvariant(ppc64.ASRD, ppc64.ASRDCC)
    262 	initvariant(ppc64.ASRW, ppc64.ASRWCC)
    263 	initvariant(ppc64.ASUB, ppc64.ASUBCC, ppc64.ASUBV, ppc64.ASUBVCC)
    264 	initvariant(ppc64.ASUBC, ppc64.ASUBCCC, ppc64.ASUBCV, ppc64.ASUBCVCC)
    265 	initvariant(ppc64.ASUBE, ppc64.ASUBECC, ppc64.ASUBEV, ppc64.ASUBEVCC)
    266 	initvariant(ppc64.ASUBME, ppc64.ASUBMECC, ppc64.ASUBMEV, ppc64.ASUBMEVCC)
    267 	initvariant(ppc64.ASUBZE, ppc64.ASUBZECC, ppc64.ASUBZEV, ppc64.ASUBZEVCC)
    268 	initvariant(ppc64.AXOR, ppc64.AXORCC)
    269 
    270 	for i := range varianttable {
    271 		vv := &varianttable[i]
    272 		if vv[0] == 0 {
    273 			// Instruction has no variants
    274 			varianttable[i][0] = obj.As(i)
    275 			continue
    276 		}
    277 
    278 		// Copy base form to other variants
    279 		if vv[0]&obj.AMask == obj.As(i) {
    280 			for _, v := range vv {
    281 				if v != 0 {
    282 					varianttable[v&obj.AMask] = varianttable[i]
    283 				}
    284 			}
    285 		}
    286 	}
    287 }
    288 
    289 // as2variant returns the variant (V_*) flags of instruction as.
    290 func as2variant(as obj.As) int {
    291 	for i, v := range varianttable[as&obj.AMask] {
    292 		if v&obj.AMask == as&obj.AMask {
    293 			return i
    294 		}
    295 	}
    296 	gc.Fatalf("as2variant: instruction %v is not a variant of itself", as&obj.AMask)
    297 	return 0
    298 }
    299 
    300 // variant2as returns the instruction as with the given variant (V_*) flags.
    301 // If no such variant exists, this returns 0.
    302 func variant2as(as obj.As, flags int) obj.As {
    303 	return varianttable[as&obj.AMask][flags]
    304 }
    305