]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/x86: add oclass function tests
authorIskander Sharipov <quasilyte@gmail.com>
Sun, 5 May 2019 09:55:47 +0000 (12:55 +0300)
committerIskander Sharipov <quasilyte@gmail.com>
Sun, 12 May 2019 07:14:09 +0000 (07:14 +0000)
To make refactoring/optimizations easier in future.

Change-Id: I158f52af7c72849df1d6bd9334b3ce9dd199318f
Reviewed-on: https://go-review.googlesource.com/c/go/+/175357
Run-TryBot: Iskander Sharipov <quasilyte@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/cmd/internal/obj/x86/asm_test.go

index d9caa2ecd31a474d834a582235628d5761fdd3e2..d1499dea7e3c9323648e0706db5a03ef4a53acf8 100644 (file)
@@ -9,11 +9,214 @@ import (
        "testing"
 )
 
+type oclassTest struct {
+       arg  *obj.Addr
+       want int // Expected oclass return value for a given arg
+}
+
+// Filled inside init, because it's easier to do with helper functions.
+var (
+       oclassTestsAMD64 []*oclassTest
+       oclassTests386   []*oclassTest
+)
+
 func init() {
        // Required for tests that access any of
        // opindex/ycover/reg/regrex global tables.
        var ctxt obj.Link
        instinit(&ctxt)
+
+       regAddr := func(reg int16) *obj.Addr {
+               return &obj.Addr{Type: obj.TYPE_REG, Reg: reg}
+       }
+       immAddr := func(v int64) *obj.Addr {
+               return &obj.Addr{Type: obj.TYPE_CONST, Offset: v}
+       }
+       regListAddr := func(regFrom, regTo int16) *obj.Addr {
+               return &obj.Addr{Type: obj.TYPE_REGLIST, Offset: EncodeRegisterRange(regFrom, regTo)}
+       }
+       memAddr := func(base, index int16) *obj.Addr {
+               return &obj.Addr{Type: obj.TYPE_MEM, Reg: base, Index: index}
+       }
+
+       // TODO(quasilyte): oclass doesn't return Yxxx for X/Y regs with
+       // ID higher than 7. We don't encode such instructions, but this
+       // behavior seems inconsistent. It should probably either
+       // never check for arch or do it in all cases.
+
+       oclassTestsCommon := []*oclassTest{
+               {&obj.Addr{Type: obj.TYPE_NONE}, Ynone},
+               {&obj.Addr{Type: obj.TYPE_BRANCH}, Ybr},
+               {&obj.Addr{Type: obj.TYPE_TEXTSIZE}, Ytextsize},
+
+               {&obj.Addr{Type: obj.TYPE_INDIR, Name: obj.NAME_EXTERN}, Yindir},
+               {&obj.Addr{Type: obj.TYPE_INDIR, Name: obj.NAME_GOTREF}, Yindir},
+
+               {&obj.Addr{Type: obj.TYPE_ADDR, Name: obj.NAME_AUTO}, Yiauto},
+               {&obj.Addr{Type: obj.TYPE_ADDR, Name: obj.NAME_PARAM}, Yiauto},
+               {&obj.Addr{Type: obj.TYPE_ADDR, Name: obj.NAME_EXTERN}, Yiauto},
+               {&obj.Addr{Type: obj.TYPE_ADDR, Sym: &obj.LSym{Name: "runtime.duff"}}, Yi32},
+               {&obj.Addr{Type: obj.TYPE_ADDR, Offset: 4}, Yu7},
+               {&obj.Addr{Type: obj.TYPE_ADDR, Offset: 255}, Yu8},
+
+               {immAddr(0), Yi0},
+               {immAddr(1), Yi1},
+               {immAddr(2), Yu2},
+               {immAddr(3), Yu2},
+               {immAddr(4), Yu7},
+               {immAddr(86), Yu7},
+               {immAddr(127), Yu7},
+               {immAddr(128), Yu8},
+               {immAddr(200), Yu8},
+               {immAddr(255), Yu8},
+               {immAddr(-1), Yi8},
+               {immAddr(-100), Yi8},
+               {immAddr(-128), Yi8},
+
+               {regAddr(REG_AL), Yal},
+               {regAddr(REG_AX), Yax},
+               {regAddr(REG_DL), Yrb},
+               {regAddr(REG_DH), Yrb},
+               {regAddr(REG_BH), Yrb},
+               {regAddr(REG_CL), Ycl},
+               {regAddr(REG_CX), Ycx},
+               {regAddr(REG_DX), Yrx},
+               {regAddr(REG_BX), Yrx},
+               {regAddr(REG_F0), Yf0},
+               {regAddr(REG_F3), Yrf},
+               {regAddr(REG_F7), Yrf},
+               {regAddr(REG_M0), Ymr},
+               {regAddr(REG_M3), Ymr},
+               {regAddr(REG_M7), Ymr},
+               {regAddr(REG_X0), Yxr0},
+               {regAddr(REG_X6), Yxr},
+               {regAddr(REG_X13), Yxr},
+               {regAddr(REG_X20), YxrEvex},
+               {regAddr(REG_X31), YxrEvex},
+               {regAddr(REG_Y0), Yyr},
+               {regAddr(REG_Y6), Yyr},
+               {regAddr(REG_Y13), Yyr},
+               {regAddr(REG_Y20), YyrEvex},
+               {regAddr(REG_Y31), YyrEvex},
+               {regAddr(REG_Z0), Yzr},
+               {regAddr(REG_Z6), Yzr},
+               {regAddr(REG_K0), Yk0},
+               {regAddr(REG_K5), Yknot0},
+               {regAddr(REG_K7), Yknot0},
+               {regAddr(REG_CS), Ycs},
+               {regAddr(REG_SS), Yss},
+               {regAddr(REG_DS), Yds},
+               {regAddr(REG_ES), Yes},
+               {regAddr(REG_FS), Yfs},
+               {regAddr(REG_GS), Ygs},
+               {regAddr(REG_TLS), Ytls},
+               {regAddr(REG_GDTR), Ygdtr},
+               {regAddr(REG_IDTR), Yidtr},
+               {regAddr(REG_LDTR), Yldtr},
+               {regAddr(REG_MSW), Ymsw},
+               {regAddr(REG_TASK), Ytask},
+               {regAddr(REG_CR0), Ycr0},
+               {regAddr(REG_CR5), Ycr5},
+               {regAddr(REG_CR8), Ycr8},
+               {regAddr(REG_DR0), Ydr0},
+               {regAddr(REG_DR5), Ydr5},
+               {regAddr(REG_DR7), Ydr7},
+               {regAddr(REG_TR0), Ytr0},
+               {regAddr(REG_TR5), Ytr5},
+               {regAddr(REG_TR7), Ytr7},
+
+               {regListAddr(REG_X0, REG_X3), YxrEvexMulti4},
+               {regListAddr(REG_X4, REG_X7), YxrEvexMulti4},
+               {regListAddr(REG_Y0, REG_Y3), YyrEvexMulti4},
+               {regListAddr(REG_Y4, REG_Y7), YyrEvexMulti4},
+               {regListAddr(REG_Z0, REG_Z3), YzrMulti4},
+               {regListAddr(REG_Z4, REG_Z7), YzrMulti4},
+
+               {memAddr(REG_AL, REG_NONE), Ym},
+               {memAddr(REG_AL, REG_SI), Ym},
+               {memAddr(REG_SI, REG_CX), Ym},
+               {memAddr(REG_DI, REG_X0), Yxvm},
+               {memAddr(REG_DI, REG_X7), Yxvm},
+               {memAddr(REG_DI, REG_Y0), Yyvm},
+               {memAddr(REG_DI, REG_Y7), Yyvm},
+               {memAddr(REG_DI, REG_Z0), Yzvm},
+               {memAddr(REG_DI, REG_Z7), Yzvm},
+       }
+
+       oclassTestsAMD64 = []*oclassTest{
+               {immAddr(-200), Ys32},
+               {immAddr(500), Ys32},
+               {immAddr(0x7FFFFFFF), Ys32},
+               {immAddr(0x7FFFFFFF + 1), Yi32},
+               {immAddr(0xFFFFFFFF), Yi32},
+               {immAddr(0xFFFFFFFF + 1), Yi64},
+
+               {regAddr(REG_BPB), Yrb},
+               {regAddr(REG_SIB), Yrb},
+               {regAddr(REG_DIB), Yrb},
+               {regAddr(REG_R8B), Yrb},
+               {regAddr(REG_R12B), Yrb},
+               {regAddr(REG_R8), Yrl},
+               {regAddr(REG_R13), Yrl},
+               {regAddr(REG_R15), Yrl},
+               {regAddr(REG_SP), Yrl},
+               {regAddr(REG_SI), Yrl},
+               {regAddr(REG_DI), Yrl},
+               {regAddr(REG_Z13), Yzr},
+               {regAddr(REG_Z20), Yzr},
+               {regAddr(REG_Z31), Yzr},
+
+               {regListAddr(REG_X10, REG_X13), YxrEvexMulti4},
+               {regListAddr(REG_X24, REG_X27), YxrEvexMulti4},
+               {regListAddr(REG_Y10, REG_Y13), YyrEvexMulti4},
+               {regListAddr(REG_Y24, REG_Y27), YyrEvexMulti4},
+               {regListAddr(REG_Z10, REG_Z13), YzrMulti4},
+               {regListAddr(REG_Z24, REG_Z27), YzrMulti4},
+
+               {memAddr(REG_DI, REG_X20), YxvmEvex},
+               {memAddr(REG_DI, REG_X27), YxvmEvex},
+               {memAddr(REG_DI, REG_Y20), YyvmEvex},
+               {memAddr(REG_DI, REG_Y27), YyvmEvex},
+               {memAddr(REG_DI, REG_Z20), Yzvm},
+               {memAddr(REG_DI, REG_Z27), Yzvm},
+       }
+
+       oclassTests386 = []*oclassTest{
+               {&obj.Addr{Type: obj.TYPE_ADDR, Name: obj.NAME_EXTERN, Sym: &obj.LSym{}}, Yi32},
+
+               {immAddr(-200), Yi32},
+
+               {regAddr(REG_SP), Yrl32},
+               {regAddr(REG_SI), Yrl32},
+               {regAddr(REG_DI), Yrl32},
+       }
+
+       // Add tests that are arch-independent for all sets.
+       oclassTestsAMD64 = append(oclassTestsAMD64, oclassTestsCommon...)
+       oclassTests386 = append(oclassTests386, oclassTestsCommon...)
+}
+
+func TestOclass(t *testing.T) {
+       runTest := func(t *testing.T, ctxt *obj.Link, tests []*oclassTest) {
+               var p obj.Prog
+               for _, test := range tests {
+                       have := oclass(ctxt, &p, test.arg)
+                       if have != test.want {
+                               t.Errorf("oclass(%q):\nhave: %d\nwant: %d",
+                                       obj.Dconv(&p, test.arg), have, test.want)
+                       }
+               }
+       }
+
+       t.Run("AMD64", func(t *testing.T) {
+               ctxtAMD64 := obj.Linknew(&Linkamd64)
+               runTest(t, ctxtAMD64, oclassTestsAMD64)
+       })
+
+       t.Run("386", func(t *testing.T) {
+               ctxt386 := obj.Linknew(&Link386)
+               runTest(t, ctxt386, oclassTests386)
+       })
 }
 
 func TestRegisterListEncDec(t *testing.T) {