blob: 7524cfcc10201e6a779d6d4031045fbd818d8698 [file] [log] [blame]
// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package asm
import (
"bytes"
"testing"
"android.googlesource.com/platform/tools/gpu/binary/endian"
"android.googlesource.com/platform/tools/gpu/binary/flat"
"android.googlesource.com/platform/tools/gpu/check"
"android.googlesource.com/platform/tools/gpu/replay/opcode"
"android.googlesource.com/platform/tools/gpu/replay/protocol"
"android.googlesource.com/platform/tools/gpu/replay/value"
)
type testPtrResolver struct{}
func (testPtrResolver) TranslateTemporaryPointer(ptr uint64) uint64 { return ptr }
func (testPtrResolver) TranslateRemappedPointer(ptr uint64) (protocol.Type, uint64) {
return protocol.TypeVolatilePointer, ptr
}
func test(t *testing.T, Instructions []Instruction, expected ...interface{}) {
buf := &bytes.Buffer{}
b := flat.Encoder(endian.Writer(buf, endian.Little))
for _, instruction := range Instructions {
err := instruction.Encode(testPtrResolver{}, b)
if err != nil {
t.Errorf("Unexpected error encoding instruction %T %+v: %v",
instruction, instruction, err)
}
}
got, err := opcode.Disassemble(buf, endian.Little)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
check.SlicesEqual(t, got, expected)
}
func TestCall(t *testing.T) {
test(t,
[]Instruction{
Call{false, 0x1234},
Call{true, 0x5678},
},
opcode.Call{PushReturn: false, FunctionID: 0x1234},
opcode.Call{PushReturn: true, FunctionID: 0x5678},
)
}
func TestPush_UnsignedNoExpand(t *testing.T) {
test(t,
[]Instruction{
Push{value.U32(0xaaaaa)}, // Repeating pattern of 1010
Push{value.U32(0x55555)}, // Repeating pattern of 0101
},
opcode.PushI{DataType: protocol.TypeUint32, Value: 0xaaaaa},
opcode.PushI{DataType: protocol.TypeUint32, Value: 0x55555},
)
}
func TestPush_UnsignedOneExpand(t *testing.T) {
test(t,
[]Instruction{
Push{value.U32(0x100000)}, // One bit beyond what can fit in a PushI
Push{value.U32(0x4000000)}, // One bit beyond what can fit in a Extend payload
Push{value.U32(0xaaaaaaaa)}, // 1010101010...
Push{value.U32(0x55555555)}, // 0101010101...
},
opcode.PushI{DataType: protocol.TypeUint32, Value: 0},
opcode.Extend{Value: 0x100000},
opcode.PushI{DataType: protocol.TypeUint32, Value: 1},
opcode.Extend{Value: 0},
opcode.PushI{DataType: protocol.TypeUint32, Value: 0x2a},
opcode.Extend{Value: 0x2aaaaaa},
opcode.PushI{DataType: protocol.TypeUint32, Value: 0x15},
opcode.Extend{Value: 0x1555555},
)
}
func TestPush_SignedPositiveNoExpand(t *testing.T) {
test(t,
[]Instruction{
Push{value.S32(0x2aaaa)}, // 0010101010...
Push{value.S32(0x55555)}, // 1010101010...
},
opcode.PushI{DataType: protocol.TypeInt32, Value: 0x2aaaa},
opcode.PushI{DataType: protocol.TypeInt32, Value: 0x55555},
)
}
func TestPush_SignedPositiveOneExpand(t *testing.T) {
test(t,
[]Instruction{
Push{value.S32(0x80000)}, // One bit beyond what can fit in a PushI
Push{value.S32(0x4000000)}, // One bit beyond what can fit in a Extend payload
Push{value.S32(0x2aaaaaaa)}, // 0010101010...
Push{value.S32(0x55555555)}, // 0101010101...
},
opcode.PushI{DataType: protocol.TypeInt32, Value: 0},
opcode.Extend{Value: 0x80000},
opcode.PushI{DataType: protocol.TypeInt32, Value: 1},
opcode.Extend{Value: 0},
opcode.PushI{DataType: protocol.TypeInt32, Value: 0x0a},
opcode.Extend{Value: 0x2aaaaaa},
opcode.PushI{DataType: protocol.TypeInt32, Value: 0x15},
opcode.Extend{Value: 0x1555555},
)
}
func TestPush_SignedNegativeNoExpand(t *testing.T) {
test(t,
[]Instruction{
Push{value.S32(-1)},
Push{value.S32(-0x55556)}, // Repeating pattern of 1010
Push{value.S32(-0x2aaab)}, // Repeating pattern of 0101
},
opcode.PushI{DataType: protocol.TypeInt32, Value: 0xfffff},
opcode.PushI{DataType: protocol.TypeInt32, Value: 0xaaaaa},
opcode.PushI{DataType: protocol.TypeInt32, Value: 0xd5555},
)
}
func TestPush_SignedNegativeOneExpand(t *testing.T) {
test(t,
[]Instruction{
Push{value.S32(-0x100001)}, // One bit beyond what can fit in a PushI
Push{value.S32(-0x4000001)}, // One bit beyond what can fit in a Extend payload
Push{value.S32(-0x2aaaaaab)}, // 110101010...
Push{value.S32(-0x55555556)}, // 101010101...
},
opcode.PushI{DataType: protocol.TypeInt32, Value: 0xfffff},
opcode.Extend{Value: 0x03efffff},
opcode.PushI{DataType: protocol.TypeInt32, Value: 0xffffe},
opcode.Extend{Value: 0x03ffffff},
opcode.PushI{DataType: protocol.TypeInt32, Value: 0xffff5},
opcode.Extend{Value: 0x1555555},
opcode.PushI{DataType: protocol.TypeInt32, Value: 0xfffea},
opcode.Extend{Value: 0x2aaaaaa},
)
}
func TestPush_FloatNoExpand(t *testing.T) {
test(t,
[]Instruction{
Push{value.F32(-2.0)},
Push{value.F32(-1.0)},
Push{value.F32(-0.5)},
Push{value.F32(0)},
Push{value.F32(0.5)},
Push{value.F32(1.0)},
Push{value.F32(2.0)},
},
opcode.PushI{DataType: protocol.TypeFloat, Value: 0x180},
opcode.PushI{DataType: protocol.TypeFloat, Value: 0x17f},
opcode.PushI{DataType: protocol.TypeFloat, Value: 0x17e},
opcode.PushI{DataType: protocol.TypeFloat, Value: 0x000},
opcode.PushI{DataType: protocol.TypeFloat, Value: 0x07e},
opcode.PushI{DataType: protocol.TypeFloat, Value: 0x07f},
opcode.PushI{DataType: protocol.TypeFloat, Value: 0x080},
)
}
func TestPush_FloatOneExpand(t *testing.T) {
test(t,
[]Instruction{
Push{value.F32(-3)},
Push{value.F32(-1.75)},
Push{value.F32(1.75)},
Push{value.F32(3)},
},
opcode.PushI{DataType: protocol.TypeFloat, Value: 0x180},
opcode.Extend{Value: 0x400000},
opcode.PushI{DataType: protocol.TypeFloat, Value: 0x17F},
opcode.Extend{Value: 0x600000},
opcode.PushI{DataType: protocol.TypeFloat, Value: 0x07F},
opcode.Extend{Value: 0x600000},
opcode.PushI{DataType: protocol.TypeFloat, Value: 0x080},
opcode.Extend{Value: 0x400000},
)
}
func TestPush_DoubleNoExpand(t *testing.T) {
test(t,
[]Instruction{
Push{value.F64(-2.0)},
Push{value.F64(-1.0)},
Push{value.F64(-0.5)},
Push{value.F64(0)},
Push{value.F64(0.5)},
Push{value.F64(1.0)},
Push{value.F64(2.0)},
},
opcode.PushI{DataType: protocol.TypeDouble, Value: 0xc00},
opcode.PushI{DataType: protocol.TypeDouble, Value: 0xbff},
opcode.PushI{DataType: protocol.TypeDouble, Value: 0xbfe},
opcode.PushI{DataType: protocol.TypeDouble, Value: 0x000},
opcode.PushI{DataType: protocol.TypeDouble, Value: 0x3fe},
opcode.PushI{DataType: protocol.TypeDouble, Value: 0x3ff},
opcode.PushI{DataType: protocol.TypeDouble, Value: 0x400},
)
}
func TestPush_DoubleExpand(t *testing.T) {
test(t,
[]Instruction{
Push{value.F64(-3)},
Push{value.F64(-1.75)},
Push{value.F64(1) / 3},
Push{value.F64(1.75)},
Push{value.F64(3)},
},
opcode.PushI{DataType: protocol.TypeDouble, Value: 0xc00},
opcode.Extend{Value: 0x2000000},
opcode.Extend{Value: 0x0},
opcode.PushI{DataType: protocol.TypeDouble, Value: 0xbff},
opcode.Extend{Value: 0x3000000},
opcode.Extend{Value: 0x0},
opcode.PushI{DataType: protocol.TypeDouble, Value: 0x3fd},
opcode.Extend{Value: 0x1555555},
opcode.Extend{Value: 0x1555555},
opcode.PushI{DataType: protocol.TypeDouble, Value: 0x3ff},
opcode.Extend{Value: 0x3000000},
opcode.Extend{Value: 0x0},
opcode.PushI{DataType: protocol.TypeDouble, Value: 0x400},
opcode.Extend{Value: 0x2000000},
opcode.Extend{Value: 0x0},
)
}
func TestPop(t *testing.T) {
test(t,
[]Instruction{
Pop{10},
},
opcode.Pop{Count: 10},
)
}
func TestCopy(t *testing.T) {
test(t,
[]Instruction{
Copy{100},
},
opcode.Copy{Count: 100},
)
}
func TestClone(t *testing.T) {
test(t,
[]Instruction{
Clone{100},
},
opcode.Clone{Index: 100},
)
}
func TestLoad(t *testing.T) {
test(t,
[]Instruction{
Load{protocol.TypeUint16, value.ConstantPointer(0x10)},
Load{protocol.TypeUint16, value.ConstantPointer(0x123456)},
Load{protocol.TypeUint16, value.VolatilePointer(0x10)},
Load{protocol.TypeUint16, value.VolatilePointer(0x123456)},
},
opcode.LoadC{DataType: protocol.TypeUint16, Address: 0x10},
opcode.PushI{DataType: protocol.TypeConstantPointer, Value: 0},
opcode.Extend{Value: 0x123456},
opcode.Load{DataType: protocol.TypeUint16},
opcode.LoadV{DataType: protocol.TypeUint16, Address: 0x10},
opcode.PushI{DataType: protocol.TypeVolatilePointer, Value: 0},
opcode.Extend{Value: 0x123456},
opcode.Load{DataType: protocol.TypeUint16},
)
}
func TestStore(t *testing.T) {
test(t,
[]Instruction{
Store{value.VolatilePointer(0x10)},
Store{value.VolatilePointer(0x4000000)},
},
opcode.StoreV{Address: 0x10},
opcode.PushI{DataType: protocol.TypeVolatilePointer, Value: 1},
opcode.Extend{Value: 0},
opcode.Store{},
)
}
func TestStrcpy(t *testing.T) {
test(t,
[]Instruction{
Strcpy{0x3000},
},
opcode.Strcpy{MaxSize: 0x3000},
)
}
func TestResource(t *testing.T) {
test(t,
[]Instruction{
Resource{10, 0x10},
Resource{20, 0x4050607},
},
opcode.PushI{DataType: protocol.TypeVolatilePointer, Value: 0x10},
opcode.Resource{10},
opcode.PushI{DataType: protocol.TypeVolatilePointer, Value: 1},
opcode.Extend{Value: 0x50607},
opcode.Resource{20},
)
}
func TestPost(t *testing.T) {
test(t,
[]Instruction{
Post{value.AbsolutePointer(0x10), 0x50},
Post{value.VolatilePointer(0x4050607), 0x8090a0b},
},
opcode.PushI{DataType: protocol.TypeAbsolutePointer, Value: 0x10},
opcode.PushI{DataType: protocol.TypeUint32, Value: 0x50},
opcode.Post{},
opcode.PushI{DataType: protocol.TypeVolatilePointer, Value: 1},
opcode.Extend{Value: 0x50607},
opcode.PushI{DataType: protocol.TypeUint32, Value: 2},
opcode.Extend{Value: 0x90a0b},
opcode.Post{},
)
}