Home | History | Annotate | Download | only in arm
      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 arm
      6 
      7 import (
      8 	"cmd/compile/internal/gc"
      9 	"cmd/internal/obj"
     10 	"cmd/internal/obj/arm"
     11 )
     12 
     13 const (
     14 	RightRdwr = gc.RightRead | gc.RightWrite
     15 )
     16 
     17 // This table gives the basic information about instruction
     18 // generated by the compiler and processed in the optimizer.
     19 // See opt.h for bit definitions.
     20 //
     21 // Instructions not generated need not be listed.
     22 // As an exception to that rule, we typically write down all the
     23 // size variants of an operation even if we just use a subset.
     24 var progtable = [arm.ALAST & obj.AMask]gc.ProgInfo{
     25 	obj.ATYPE:     {Flags: gc.Pseudo | gc.Skip},
     26 	obj.ATEXT:     {Flags: gc.Pseudo},
     27 	obj.AFUNCDATA: {Flags: gc.Pseudo},
     28 	obj.APCDATA:   {Flags: gc.Pseudo},
     29 	obj.AUNDEF:    {Flags: gc.Break},
     30 	obj.AUSEFIELD: {Flags: gc.OK},
     31 	obj.AVARDEF:   {Flags: gc.Pseudo | gc.RightWrite},
     32 	obj.AVARKILL:  {Flags: gc.Pseudo | gc.RightWrite},
     33 	obj.AVARLIVE:  {Flags: gc.Pseudo | gc.LeftRead},
     34 
     35 	// NOP is an internal no-op that also stands
     36 	// for USED and SET annotations, not the Intel opcode.
     37 	obj.ANOP: {Flags: gc.LeftRead | gc.RightWrite},
     38 
     39 	// Integer.
     40 	arm.AADC & obj.AMask:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     41 	arm.AADD & obj.AMask:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     42 	arm.AAND & obj.AMask:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     43 	arm.ABIC & obj.AMask:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     44 	arm.ACMN & obj.AMask:    {Flags: gc.SizeL | gc.LeftRead | gc.RightRead},
     45 	arm.ACMP & obj.AMask:    {Flags: gc.SizeL | gc.LeftRead | gc.RightRead},
     46 	arm.ADIVU & obj.AMask:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     47 	arm.ADIV & obj.AMask:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     48 	arm.AEOR & obj.AMask:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     49 	arm.AMODU & obj.AMask:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     50 	arm.AMOD & obj.AMask:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     51 	arm.AMULALU & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | RightRdwr},
     52 	arm.AMULAL & obj.AMask:  {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | RightRdwr},
     53 	arm.AMULA & obj.AMask:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | RightRdwr},
     54 	arm.AMULU & obj.AMask:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     55 	arm.AMUL & obj.AMask:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     56 	arm.AMULL & obj.AMask:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     57 	arm.AMULLU & obj.AMask:  {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     58 	arm.AMVN & obj.AMask:    {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite},
     59 	arm.AORR & obj.AMask:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     60 	arm.ARSB & obj.AMask:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     61 	arm.ARSC & obj.AMask:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     62 	arm.ASBC & obj.AMask:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     63 	arm.ASLL & obj.AMask:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     64 	arm.ASRA & obj.AMask:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     65 	arm.ASRL & obj.AMask:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     66 	arm.ASUB & obj.AMask:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
     67 	arm.ACLZ & obj.AMask:    {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite},
     68 	arm.ATEQ & obj.AMask:    {Flags: gc.SizeL | gc.LeftRead | gc.RightRead},
     69 	arm.ATST & obj.AMask:    {Flags: gc.SizeL | gc.LeftRead | gc.RightRead},
     70 
     71 	// Floating point.
     72 	arm.AADDD & obj.AMask:  {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
     73 	arm.AADDF & obj.AMask:  {Flags: gc.SizeF | gc.LeftRead | RightRdwr},
     74 	arm.ACMPD & obj.AMask:  {Flags: gc.SizeD | gc.LeftRead | gc.RightRead},
     75 	arm.ACMPF & obj.AMask:  {Flags: gc.SizeF | gc.LeftRead | gc.RightRead},
     76 	arm.ADIVD & obj.AMask:  {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
     77 	arm.ADIVF & obj.AMask:  {Flags: gc.SizeF | gc.LeftRead | RightRdwr},
     78 	arm.AMULD & obj.AMask:  {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
     79 	arm.AMULF & obj.AMask:  {Flags: gc.SizeF | gc.LeftRead | RightRdwr},
     80 	arm.ASUBD & obj.AMask:  {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
     81 	arm.ASUBF & obj.AMask:  {Flags: gc.SizeF | gc.LeftRead | RightRdwr},
     82 	arm.ANEGD & obj.AMask:  {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
     83 	arm.ANEGF & obj.AMask:  {Flags: gc.SizeF | gc.LeftRead | RightRdwr},
     84 	arm.ASQRTD & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
     85 
     86 	// Conversions.
     87 	arm.AMOVWD & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
     88 	arm.AMOVWF & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
     89 	arm.AMOVDF & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
     90 	arm.AMOVDW & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
     91 	arm.AMOVFD & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
     92 	arm.AMOVFW & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
     93 
     94 	// Moves.
     95 	arm.AMOVB & obj.AMask: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move},
     96 	arm.AMOVD & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move},
     97 	arm.AMOVF & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move},
     98 	arm.AMOVH & obj.AMask: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move},
     99 	arm.AMOVW & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move},
    100 
    101 	// In addition, duffzero reads R0,R1 and writes R1.  This fact is
    102 	// encoded in peep.c
    103 	obj.ADUFFZERO: {Flags: gc.Call},
    104 
    105 	// In addition, duffcopy reads R1,R2 and writes R0,R1,R2.  This fact is
    106 	// encoded in peep.c
    107 	obj.ADUFFCOPY: {Flags: gc.Call},
    108 
    109 	// These should be split into the two different conversions instead
    110 	// of overloading the one.
    111 	arm.AMOVBS & obj.AMask: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Conv},
    112 	arm.AMOVBU & obj.AMask: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Conv},
    113 	arm.AMOVHS & obj.AMask: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Conv},
    114 	arm.AMOVHU & obj.AMask: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Conv},
    115 
    116 	// Jumps.
    117 	arm.AB & obj.AMask:   {Flags: gc.Jump | gc.Break},
    118 	arm.ABL & obj.AMask:  {Flags: gc.Call},
    119 	arm.ABEQ & obj.AMask: {Flags: gc.Cjmp},
    120 	arm.ABNE & obj.AMask: {Flags: gc.Cjmp},
    121 	arm.ABCS & obj.AMask: {Flags: gc.Cjmp},
    122 	arm.ABHS & obj.AMask: {Flags: gc.Cjmp},
    123 	arm.ABCC & obj.AMask: {Flags: gc.Cjmp},
    124 	arm.ABLO & obj.AMask: {Flags: gc.Cjmp},
    125 	arm.ABMI & obj.AMask: {Flags: gc.Cjmp},
    126 	arm.ABPL & obj.AMask: {Flags: gc.Cjmp},
    127 	arm.ABVS & obj.AMask: {Flags: gc.Cjmp},
    128 	arm.ABVC & obj.AMask: {Flags: gc.Cjmp},
    129 	arm.ABHI & obj.AMask: {Flags: gc.Cjmp},
    130 	arm.ABLS & obj.AMask: {Flags: gc.Cjmp},
    131 	arm.ABGE & obj.AMask: {Flags: gc.Cjmp},
    132 	arm.ABLT & obj.AMask: {Flags: gc.Cjmp},
    133 	arm.ABGT & obj.AMask: {Flags: gc.Cjmp},
    134 	arm.ABLE & obj.AMask: {Flags: gc.Cjmp},
    135 	obj.ARET:             {Flags: gc.Break},
    136 }
    137 
    138 func proginfo(p *obj.Prog) gc.ProgInfo {
    139 	info := progtable[p.As&obj.AMask]
    140 	if info.Flags == 0 {
    141 		gc.Fatalf("unknown instruction %v", p)
    142 	}
    143 
    144 	if p.From.Type == obj.TYPE_ADDR && p.From.Sym != nil && (info.Flags&gc.LeftRead != 0) {
    145 		info.Flags &^= gc.LeftRead
    146 		info.Flags |= gc.LeftAddr
    147 	}
    148 
    149 	if (info.Flags&gc.RegRead != 0) && p.Reg == 0 {
    150 		info.Flags &^= gc.RegRead
    151 		info.Flags |= gc.CanRegRead | gc.RightRead
    152 	}
    153 
    154 	if (p.Scond&arm.C_SCOND != arm.C_SCOND_NONE) && (info.Flags&gc.RightWrite != 0) {
    155 		info.Flags |= gc.RightRead
    156 	}
    157 
    158 	return info
    159 }
    160