From 2e4edf46977994c9d26df9327f0e41c1b60f3435 Mon Sep 17 00:00:00 2001 From: Iskander Sharipov Date: Sun, 5 May 2019 12:55:47 +0300 Subject: [PATCH] cmd/internal/obj/x86: add oclass function tests To make refactoring/optimizations easier in future. Change-Id: I158f52af7c72849df1d6bd9334b3ce9dd199318f Reviewed-on: https://go-review.googlesource.com/c/go/+/175357 Run-TryBot: Iskander Sharipov TryBot-Result: Gobot Gobot Reviewed-by: Cherry Zhang --- src/cmd/internal/obj/x86/asm_test.go | 203 +++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) diff --git a/src/cmd/internal/obj/x86/asm_test.go b/src/cmd/internal/obj/x86/asm_test.go index d9caa2ecd3..d1499dea7e 100644 --- a/src/cmd/internal/obj/x86/asm_test.go +++ b/src/cmd/internal/obj/x86/asm_test.go @@ -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) { -- 2.50.0