github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/internal/obj/x86/asm_test.go (about) 1 // Copyright 2018 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 x86 6 7 import ( 8 "github.com/gagliardetto/golang-go/cmd/internal/obj" 9 "github.com/gagliardetto/golang-go/cmd/internal/objabi" 10 "testing" 11 ) 12 13 type oclassTest struct { 14 arg *obj.Addr 15 want int // Expected oclass return value for a given arg 16 } 17 18 // Filled inside init, because it's easier to do with helper functions. 19 var ( 20 oclassTestsAMD64 []*oclassTest 21 oclassTests386 []*oclassTest 22 ) 23 24 func init() { 25 // Required for tests that access any of 26 // opindex/ycover/reg/regrex global tables. 27 var ctxt obj.Link 28 instinit(&ctxt) 29 30 regAddr := func(reg int16) *obj.Addr { 31 return &obj.Addr{Type: obj.TYPE_REG, Reg: reg} 32 } 33 immAddr := func(v int64) *obj.Addr { 34 return &obj.Addr{Type: obj.TYPE_CONST, Offset: v} 35 } 36 regListAddr := func(regFrom, regTo int16) *obj.Addr { 37 return &obj.Addr{Type: obj.TYPE_REGLIST, Offset: EncodeRegisterRange(regFrom, regTo)} 38 } 39 memAddr := func(base, index int16) *obj.Addr { 40 return &obj.Addr{Type: obj.TYPE_MEM, Reg: base, Index: index} 41 } 42 43 // TODO(quasilyte): oclass doesn't return Yxxx for X/Y regs with 44 // ID higher than 7. We don't encode such instructions, but this 45 // behavior seems inconsistent. It should probably either 46 // never check for arch or do it in all cases. 47 48 oclassTestsCommon := []*oclassTest{ 49 {&obj.Addr{Type: obj.TYPE_NONE}, Ynone}, 50 {&obj.Addr{Type: obj.TYPE_BRANCH}, Ybr}, 51 {&obj.Addr{Type: obj.TYPE_TEXTSIZE}, Ytextsize}, 52 53 {&obj.Addr{Type: obj.TYPE_INDIR, Name: obj.NAME_EXTERN}, Yindir}, 54 {&obj.Addr{Type: obj.TYPE_INDIR, Name: obj.NAME_GOTREF}, Yindir}, 55 56 {&obj.Addr{Type: obj.TYPE_ADDR, Name: obj.NAME_AUTO}, Yiauto}, 57 {&obj.Addr{Type: obj.TYPE_ADDR, Name: obj.NAME_PARAM}, Yiauto}, 58 {&obj.Addr{Type: obj.TYPE_ADDR, Name: obj.NAME_EXTERN}, Yiauto}, 59 {&obj.Addr{Type: obj.TYPE_ADDR, Sym: &obj.LSym{Name: "runtime.duff"}}, Yi32}, 60 {&obj.Addr{Type: obj.TYPE_ADDR, Offset: 4}, Yu7}, 61 {&obj.Addr{Type: obj.TYPE_ADDR, Offset: 255}, Yu8}, 62 63 {immAddr(0), Yi0}, 64 {immAddr(1), Yi1}, 65 {immAddr(2), Yu2}, 66 {immAddr(3), Yu2}, 67 {immAddr(4), Yu7}, 68 {immAddr(86), Yu7}, 69 {immAddr(127), Yu7}, 70 {immAddr(128), Yu8}, 71 {immAddr(200), Yu8}, 72 {immAddr(255), Yu8}, 73 {immAddr(-1), Yi8}, 74 {immAddr(-100), Yi8}, 75 {immAddr(-128), Yi8}, 76 77 {regAddr(REG_AL), Yal}, 78 {regAddr(REG_AX), Yax}, 79 {regAddr(REG_DL), Yrb}, 80 {regAddr(REG_DH), Yrb}, 81 {regAddr(REG_BH), Yrb}, 82 {regAddr(REG_CL), Ycl}, 83 {regAddr(REG_CX), Ycx}, 84 {regAddr(REG_DX), Yrx}, 85 {regAddr(REG_BX), Yrx}, 86 {regAddr(REG_F0), Yf0}, 87 {regAddr(REG_F3), Yrf}, 88 {regAddr(REG_F7), Yrf}, 89 {regAddr(REG_M0), Ymr}, 90 {regAddr(REG_M3), Ymr}, 91 {regAddr(REG_M7), Ymr}, 92 {regAddr(REG_X0), Yxr0}, 93 {regAddr(REG_X6), Yxr}, 94 {regAddr(REG_X13), Yxr}, 95 {regAddr(REG_X20), YxrEvex}, 96 {regAddr(REG_X31), YxrEvex}, 97 {regAddr(REG_Y0), Yyr}, 98 {regAddr(REG_Y6), Yyr}, 99 {regAddr(REG_Y13), Yyr}, 100 {regAddr(REG_Y20), YyrEvex}, 101 {regAddr(REG_Y31), YyrEvex}, 102 {regAddr(REG_Z0), Yzr}, 103 {regAddr(REG_Z6), Yzr}, 104 {regAddr(REG_K0), Yk0}, 105 {regAddr(REG_K5), Yknot0}, 106 {regAddr(REG_K7), Yknot0}, 107 {regAddr(REG_CS), Ycs}, 108 {regAddr(REG_SS), Yss}, 109 {regAddr(REG_DS), Yds}, 110 {regAddr(REG_ES), Yes}, 111 {regAddr(REG_FS), Yfs}, 112 {regAddr(REG_GS), Ygs}, 113 {regAddr(REG_TLS), Ytls}, 114 {regAddr(REG_GDTR), Ygdtr}, 115 {regAddr(REG_IDTR), Yidtr}, 116 {regAddr(REG_LDTR), Yldtr}, 117 {regAddr(REG_MSW), Ymsw}, 118 {regAddr(REG_TASK), Ytask}, 119 {regAddr(REG_CR0), Ycr0}, 120 {regAddr(REG_CR5), Ycr5}, 121 {regAddr(REG_CR8), Ycr8}, 122 {regAddr(REG_DR0), Ydr0}, 123 {regAddr(REG_DR5), Ydr5}, 124 {regAddr(REG_DR7), Ydr7}, 125 {regAddr(REG_TR0), Ytr0}, 126 {regAddr(REG_TR5), Ytr5}, 127 {regAddr(REG_TR7), Ytr7}, 128 129 {regListAddr(REG_X0, REG_X3), YxrEvexMulti4}, 130 {regListAddr(REG_X4, REG_X7), YxrEvexMulti4}, 131 {regListAddr(REG_Y0, REG_Y3), YyrEvexMulti4}, 132 {regListAddr(REG_Y4, REG_Y7), YyrEvexMulti4}, 133 {regListAddr(REG_Z0, REG_Z3), YzrMulti4}, 134 {regListAddr(REG_Z4, REG_Z7), YzrMulti4}, 135 136 {memAddr(REG_AL, REG_NONE), Ym}, 137 {memAddr(REG_AL, REG_SI), Ym}, 138 {memAddr(REG_SI, REG_CX), Ym}, 139 {memAddr(REG_DI, REG_X0), Yxvm}, 140 {memAddr(REG_DI, REG_X7), Yxvm}, 141 {memAddr(REG_DI, REG_Y0), Yyvm}, 142 {memAddr(REG_DI, REG_Y7), Yyvm}, 143 {memAddr(REG_DI, REG_Z0), Yzvm}, 144 {memAddr(REG_DI, REG_Z7), Yzvm}, 145 } 146 147 oclassTestsAMD64 = []*oclassTest{ 148 {immAddr(-200), Ys32}, 149 {immAddr(500), Ys32}, 150 {immAddr(0x7FFFFFFF), Ys32}, 151 {immAddr(0x7FFFFFFF + 1), Yi32}, 152 {immAddr(0xFFFFFFFF), Yi32}, 153 {immAddr(0xFFFFFFFF + 1), Yi64}, 154 155 {regAddr(REG_BPB), Yrb}, 156 {regAddr(REG_SIB), Yrb}, 157 {regAddr(REG_DIB), Yrb}, 158 {regAddr(REG_R8B), Yrb}, 159 {regAddr(REG_R12B), Yrb}, 160 {regAddr(REG_R8), Yrl}, 161 {regAddr(REG_R13), Yrl}, 162 {regAddr(REG_R15), Yrl}, 163 {regAddr(REG_SP), Yrl}, 164 {regAddr(REG_SI), Yrl}, 165 {regAddr(REG_DI), Yrl}, 166 {regAddr(REG_Z13), Yzr}, 167 {regAddr(REG_Z20), Yzr}, 168 {regAddr(REG_Z31), Yzr}, 169 170 {regListAddr(REG_X10, REG_X13), YxrEvexMulti4}, 171 {regListAddr(REG_X24, REG_X27), YxrEvexMulti4}, 172 {regListAddr(REG_Y10, REG_Y13), YyrEvexMulti4}, 173 {regListAddr(REG_Y24, REG_Y27), YyrEvexMulti4}, 174 {regListAddr(REG_Z10, REG_Z13), YzrMulti4}, 175 {regListAddr(REG_Z24, REG_Z27), YzrMulti4}, 176 177 {memAddr(REG_DI, REG_X20), YxvmEvex}, 178 {memAddr(REG_DI, REG_X27), YxvmEvex}, 179 {memAddr(REG_DI, REG_Y20), YyvmEvex}, 180 {memAddr(REG_DI, REG_Y27), YyvmEvex}, 181 {memAddr(REG_DI, REG_Z20), Yzvm}, 182 {memAddr(REG_DI, REG_Z27), Yzvm}, 183 } 184 185 oclassTests386 = []*oclassTest{ 186 {&obj.Addr{Type: obj.TYPE_ADDR, Name: obj.NAME_EXTERN, Sym: &obj.LSym{}}, Yi32}, 187 188 {immAddr(-200), Yi32}, 189 190 {regAddr(REG_SP), Yrl32}, 191 {regAddr(REG_SI), Yrl32}, 192 {regAddr(REG_DI), Yrl32}, 193 } 194 195 // Add tests that are arch-independent for all sets. 196 oclassTestsAMD64 = append(oclassTestsAMD64, oclassTestsCommon...) 197 oclassTests386 = append(oclassTests386, oclassTestsCommon...) 198 } 199 200 func TestOclass(t *testing.T) { 201 runTest := func(t *testing.T, ctxt *obj.Link, tests []*oclassTest) { 202 var p obj.Prog 203 for _, test := range tests { 204 have := oclass(ctxt, &p, test.arg) 205 if have != test.want { 206 t.Errorf("oclass(%q):\nhave: %d\nwant: %d", 207 obj.Dconv(&p, test.arg), have, test.want) 208 } 209 } 210 } 211 212 // TODO(quasilyte): test edge cases for Hsolaris, etc? 213 214 t.Run("linux/AMD64", func(t *testing.T) { 215 ctxtAMD64 := obj.Linknew(&Linkamd64) 216 ctxtAMD64.Headtype = objabi.Hlinux // See #32028 217 runTest(t, ctxtAMD64, oclassTestsAMD64) 218 }) 219 220 t.Run("linux/386", func(t *testing.T) { 221 ctxt386 := obj.Linknew(&Link386) 222 ctxt386.Headtype = objabi.Hlinux // See #32028 223 runTest(t, ctxt386, oclassTests386) 224 }) 225 } 226 227 func TestRegisterListEncDec(t *testing.T) { 228 tests := []struct { 229 printed string 230 reg0 int16 231 reg1 int16 232 }{ 233 {"[R10-R13]", REG_R10, REG_R13}, 234 {"[X0-AX]", REG_X0, REG_AX}, 235 236 {"[X0-X3]", REG_X0, REG_X3}, 237 {"[X21-X24]", REG_X21, REG_X24}, 238 239 {"[Y0-Y3]", REG_Y0, REG_Y3}, 240 {"[Y21-Y24]", REG_Y21, REG_Y24}, 241 242 {"[Z0-Z3]", REG_Z0, REG_Z3}, 243 {"[Z21-Z24]", REG_Z21, REG_Z24}, 244 } 245 246 for _, test := range tests { 247 enc := EncodeRegisterRange(test.reg0, test.reg1) 248 reg0, reg1 := decodeRegisterRange(enc) 249 250 if int16(reg0) != test.reg0 { 251 t.Errorf("%s reg0 mismatch: have %d, want %d", 252 test.printed, reg0, test.reg0) 253 } 254 if int16(reg1) != test.reg1 { 255 t.Errorf("%s reg1 mismatch: have %d, want %d", 256 test.printed, reg1, test.reg1) 257 } 258 wantPrinted := test.printed 259 if rlconv(enc) != wantPrinted { 260 t.Errorf("%s string mismatch: have %s, want %s", 261 test.printed, rlconv(enc), wantPrinted) 262 } 263 } 264 } 265 266 func TestRegIndex(t *testing.T) { 267 tests := []struct { 268 regFrom int 269 regTo int 270 }{ 271 {REG_AL, REG_R15B}, 272 {REG_AX, REG_R15}, 273 {REG_M0, REG_M7}, 274 {REG_K0, REG_K7}, 275 {REG_X0, REG_X31}, 276 {REG_Y0, REG_Y31}, 277 {REG_Z0, REG_Z31}, 278 } 279 280 for _, test := range tests { 281 for index, reg := 0, test.regFrom; reg <= test.regTo; index, reg = index+1, reg+1 { 282 have := regIndex(int16(reg)) 283 want := index 284 if have != want { 285 regName := rconv(int(reg)) 286 t.Errorf("regIndex(%s):\nhave: %d\nwant: %d", 287 regName, have, want) 288 } 289 } 290 } 291 }