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 //
     25 // The table is formatted for 8-space tabs.
     26 var progtable = [arm.ALAST]obj.ProgInfo{
     27 	obj.ATYPE:     {gc.Pseudo | gc.Skip, 0, 0, 0},
     28 	obj.ATEXT:     {gc.Pseudo, 0, 0, 0},
     29 	obj.AFUNCDATA: {gc.Pseudo, 0, 0, 0},
     30 	obj.APCDATA:   {gc.Pseudo, 0, 0, 0},
     31 	obj.AUNDEF:    {gc.Break, 0, 0, 0},
     32 	obj.AUSEFIELD: {gc.OK, 0, 0, 0},
     33 	obj.ACHECKNIL: {gc.LeftRead, 0, 0, 0},
     34 	obj.AVARDEF:   {gc.Pseudo | gc.RightWrite, 0, 0, 0},
     35 	obj.AVARKILL:  {gc.Pseudo | gc.RightWrite, 0, 0, 0},
     36 
     37 	// NOP is an internal no-op that also stands
     38 	// for USED and SET annotations, not the Intel opcode.
     39 	obj.ANOP: {gc.LeftRead | gc.RightWrite, 0, 0, 0},
     40 
     41 	// Integer.
     42 	arm.AADC:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
     43 	arm.AADD:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
     44 	arm.AAND:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
     45 	arm.ABIC:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
     46 	arm.ACMN:    {gc.SizeL | gc.LeftRead | gc.RightRead, 0, 0, 0},
     47 	arm.ACMP:    {gc.SizeL | gc.LeftRead | gc.RightRead, 0, 0, 0},
     48 	arm.ADIVU:   {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
     49 	arm.ADIV:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
     50 	arm.AEOR:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
     51 	arm.AMODU:   {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
     52 	arm.AMOD:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
     53 	arm.AMULALU: {gc.SizeL | gc.LeftRead | gc.RegRead | RightRdwr, 0, 0, 0},
     54 	arm.AMULAL:  {gc.SizeL | gc.LeftRead | gc.RegRead | RightRdwr, 0, 0, 0},
     55 	arm.AMULA:   {gc.SizeL | gc.LeftRead | gc.RegRead | RightRdwr, 0, 0, 0},
     56 	arm.AMULU:   {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
     57 	arm.AMUL:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
     58 	arm.AMULL:   {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
     59 	arm.AMULLU:  {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
     60 	arm.AMVN:    {gc.SizeL | gc.LeftRead | gc.RightWrite, 0, 0, 0},
     61 	arm.AORR:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
     62 	arm.ARSB:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
     63 	arm.ARSC:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
     64 	arm.ASBC:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
     65 	arm.ASLL:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
     66 	arm.ASRA:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
     67 	arm.ASRL:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
     68 	arm.ASUB:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
     69 	arm.ATEQ:    {gc.SizeL | gc.LeftRead | gc.RightRead, 0, 0, 0},
     70 	arm.ATST:    {gc.SizeL | gc.LeftRead | gc.RightRead, 0, 0, 0},
     71 
     72 	// Floating point.
     73 	arm.AADDD:  {gc.SizeD | gc.LeftRead | RightRdwr, 0, 0, 0},
     74 	arm.AADDF:  {gc.SizeF | gc.LeftRead | RightRdwr, 0, 0, 0},
     75 	arm.ACMPD:  {gc.SizeD | gc.LeftRead | gc.RightRead, 0, 0, 0},
     76 	arm.ACMPF:  {gc.SizeF | gc.LeftRead | gc.RightRead, 0, 0, 0},
     77 	arm.ADIVD:  {gc.SizeD | gc.LeftRead | RightRdwr, 0, 0, 0},
     78 	arm.ADIVF:  {gc.SizeF | gc.LeftRead | RightRdwr, 0, 0, 0},
     79 	arm.AMULD:  {gc.SizeD | gc.LeftRead | RightRdwr, 0, 0, 0},
     80 	arm.AMULF:  {gc.SizeF | gc.LeftRead | RightRdwr, 0, 0, 0},
     81 	arm.ASUBD:  {gc.SizeD | gc.LeftRead | RightRdwr, 0, 0, 0},
     82 	arm.ASUBF:  {gc.SizeF | gc.LeftRead | RightRdwr, 0, 0, 0},
     83 	arm.ASQRTD: {gc.SizeD | gc.LeftRead | RightRdwr, 0, 0, 0},
     84 
     85 	// Conversions.
     86 	arm.AMOVWD: {gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
     87 	arm.AMOVWF: {gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
     88 	arm.AMOVDF: {gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
     89 	arm.AMOVDW: {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
     90 	arm.AMOVFD: {gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
     91 	arm.AMOVFW: {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
     92 
     93 	// Moves.
     94 	arm.AMOVB: {gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
     95 	arm.AMOVD: {gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
     96 	arm.AMOVF: {gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
     97 	arm.AMOVH: {gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
     98 	arm.AMOVW: {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
     99 
    100 	// In addtion, duffzero reads R0,R1 and writes R1.  This fact is
    101 	// encoded in peep.c
    102 	obj.ADUFFZERO: {gc.Call, 0, 0, 0},
    103 
    104 	// In addtion, duffcopy reads R1,R2 and writes R0,R1,R2.  This fact is
    105 	// encoded in peep.c
    106 	obj.ADUFFCOPY: {gc.Call, 0, 0, 0},
    107 
    108 	// These should be split into the two different conversions instead
    109 	// of overloading the one.
    110 	arm.AMOVBS: {gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
    111 	arm.AMOVBU: {gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
    112 	arm.AMOVHS: {gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
    113 	arm.AMOVHU: {gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
    114 
    115 	// Jumps.
    116 	arm.AB:   {gc.Jump | gc.Break, 0, 0, 0},
    117 	arm.ABL:  {gc.Call, 0, 0, 0},
    118 	arm.ABEQ: {gc.Cjmp, 0, 0, 0},
    119 	arm.ABNE: {gc.Cjmp, 0, 0, 0},
    120 	arm.ABCS: {gc.Cjmp, 0, 0, 0},
    121 	arm.ABHS: {gc.Cjmp, 0, 0, 0},
    122 	arm.ABCC: {gc.Cjmp, 0, 0, 0},
    123 	arm.ABLO: {gc.Cjmp, 0, 0, 0},
    124 	arm.ABMI: {gc.Cjmp, 0, 0, 0},
    125 	arm.ABPL: {gc.Cjmp, 0, 0, 0},
    126 	arm.ABVS: {gc.Cjmp, 0, 0, 0},
    127 	arm.ABVC: {gc.Cjmp, 0, 0, 0},
    128 	arm.ABHI: {gc.Cjmp, 0, 0, 0},
    129 	arm.ABLS: {gc.Cjmp, 0, 0, 0},
    130 	arm.ABGE: {gc.Cjmp, 0, 0, 0},
    131 	arm.ABLT: {gc.Cjmp, 0, 0, 0},
    132 	arm.ABGT: {gc.Cjmp, 0, 0, 0},
    133 	arm.ABLE: {gc.Cjmp, 0, 0, 0},
    134 	obj.ARET: {gc.Break, 0, 0, 0},
    135 }
    136 
    137 func proginfo(p *obj.Prog) {
    138 	info := &p.Info
    139 	*info = progtable[p.As]
    140 	if info.Flags == 0 {
    141 		gc.Fatal("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 	switch p.As {
    159 	case arm.ADIV,
    160 		arm.ADIVU,
    161 		arm.AMOD,
    162 		arm.AMODU:
    163 		info.Regset |= RtoB(arm.REG_R12)
    164 	}
    165 }
    166